Commit Graph

69 Commits

Author SHA1 Message Date
can1357 5053a6a4d3 fix(coding-agent): corrected coding-agent incomplete stop recovery logic
- Handled "incomplete" stop reasons in session recovery and auto-compaction workflows.
- Dropped the prior assistant turn before attempting recovery on incomplete-length stops.
- Expanded auto-compaction reason types and triggers to include "incomplete".
- Updated internal URLs parsing internals, export order, tests, and Obsidian URI prompt docs.
2026-05-28 10:10:34 +02:00
can1357 7dd00c015b feat: hashline improvements for spark
- Redesigned hashline patch syntax from anchor-based (`A-B:`) to hunk-header format (`@@ A..B @@`) with unified-diff compatibility.
- Removed `autoDropPureInsertDuplicates` option and simplified apply behavior to preserve duplicated boundary and context lines.
- Changed repeat operator from `^A-B` to `&A..B` and range separator from `-` to `..` for consistency with hunk-header syntax.
- Added image resizing and dimension notes to eval tool output; improved write tool hashline header sanitation for legacy formats.
- Removed 521 lines of boundary-duplicate absorption code and simplified parser to auto-convert bare body rows and unified-diff contamination.
2026-05-28 03:06:52 +02:00
can1357 7c64576524 feat(hashline): replaced file-hash anchors with opaque snapshot-store tags
- Replaced 4-hex content-derived file hashes with 3-hex opaque tags minted by InMemorySnapshotStore, making tags session-bound pointers rather than content fingerprints.
- Removed lru-cache dependency; replaced LRU-bounded per-path rings with a flat 4096-slot global ring using a scrambled permutation to prevent LLM tag extrapolation.
- Made SnapshotStore required in Patcher (was optional); tag resolution now drives stale-anchor detection instead of recomputing hashes at apply time.
- Changed literal payload sigil from `|` to `+` and accepted `^A` shorthand for `^A-A`; added lenient recovery for bare bodies, lone `-` rows, and overlapping bare/concrete block pairs.
2026-05-28 01:00:23 +02:00
Leo Kim b373c54cd7 fix(coding-agent): guard sendCompletionNotification on aborted/error stopReason
Bug: Ctrl+C on the ask tool selector threw ToolAbortError, the turn
ended with stopReason === "aborted", and handleBackgroundEvent fired
sendCompletionNotification() unconditionally — producing a misleading
"Task complete" desktop toast for a turn that never actually completed.

Fix mirrors the stopReason filter already used by
#currentContextTokens, #handleMessageEnd, and the retry / TTSR /
compaction skip paths across agent-session.ts: check the most recent
assistant message via session.getLastAssistantMessage() and return
early when stopReason is "aborted" or "error".

Test coverage (event-controller-abort-guard.test.ts, 6 cases):
- aborted   -> 0 sendNotification calls
- error     -> 0 calls
- stop      -> 1 call (normal completion)
- no last assistant message -> proceeds (defensive)
- isBackgrounded=false (foreground) -> still 0
- completion.notify=off -> still 0

Matching guard applied to the standalone desktop-notify extension
(~/.omp/agent/extensions/desktop-notify/index.ts) which is currently
the live producer of completion toasts after Phase 1 of
seed_0ca7e1143ac1.
2026-05-25 12:08:36 +02:00
can1357 f29e733b67 refactor(coding-agent/modes): reorganized working-message hints in modes
- Added a shared `interruptHint()` utility in the modes shared module to generate the interrupt suffix with themed bracket glyphs.
- Replaced hardcoded working-message interrupt text in interactive and event controllers with calls to `interruptHint()`.
- Updated working-message rendering to recognize and strip the new themed hint when applying shimmer styling.
2026-05-22 17:44:20 +09:00
can1357 8b1364d4c2 feat(coding-agent): implemented one-shot generateHandoff in coding-agent
- Replaced event-driven handoff with one-shot `generateHandoff(...)` via `completeSimple`.
- Added cancellable `/handoff` command handling with a loader and Escape-to-abort flow.
- Removed legacy `compaction/handoff.ts` exports and added `generateHandoff(messages, model, apiKey, options)`.
- Fixed pre-cancelled handoff behavior to return `Handoff cancelled` and propagate abort signals.
- Updated handoff tests/mocks to assert `generateHandoff` invocation details and `AgentSession.handoff()` options.
2026-05-15 18:49:53 +02:00
can1357 e1aaf78874 refactor(compaction): moved compaction APIs to @oh-my-pi/pi-agent-core
- Relocated compaction, branch-summarization, pruning, and utils from coding-agent to packages/agent/src/compaction.
- Moved OpenAI remote compaction helpers from packages/ai to the new compaction module.
- Added handoff.ts with extractHandoffDocument, createHandoffContext, and renderHandoffPrompt helpers.
- Exposed new entries.ts with standalone SessionEntry types so coding-agent no longer owns them.
2026-05-15 18:31:12 +02:00
can1357 933058a241 feat(goals): added per-session goal mode with token budget tracking
- Added GoalRuntime with wall-clock and token accounting, budget steering, and lifecycle operations (create, pause, resume, drop, complete).
- Exposed goal tool as a hidden agent tool, activated only when goal mode is enabled.
- Integrated goal continuation loop in InteractiveMode with auto-submit between turns.
- Added status line segment and theme icons for goal mode state.
2026-05-14 06:40:41 +02:00
can1357 ef5cbef51f feat(coding-agent): added resolve-based plan approval flow in coding-agent
- Removed ExitPlanModeTool and deleted exit-plan-mode docs/tests, dropping the old approval contract outputs.
- Replaced plan-mode approval flow from exit_plan_mode to resolve across session, SDK, controllers, and discovery.
- Added standing resolve handler accessors and updated resolve routing for queued or standing approval handlers.
- Added PlanApprovalDetails and enforced normalized, validated approval titles with readable plan-file requirements.
- Extended resolve schema and invocation signatures with optional extra metadata and reason trimming behavior updates.
- Updated plan and resolve prompts and changelog guidance to require resolve action, reason, and extra.title for apply/discard.
2026-05-14 05:33:30 +02:00
Can Bölük 8f1d98fa38 Merge branch 'main' into fix/skill-chip-and-silent-abort 2026-05-14 04:51:41 +02:00
David Marshall c7722838b7 fix(coding-agent/acp): pushed config_option_update on every thinking-level change
ACP clients (Zed, etc.) only received `config_option_update` notifications
when they themselves drove the change via `session/set_session_config_option`.
Internal thinking-level updates (slash commands, automatic model-driven
adjustments, extension UI) bypassed the notification path, so client config
panels went stale until the next user-initiated change.

AgentSession now emits a `thinking_level_changed` event from
`setThinkingLevel`, and AcpAgent installs a session-lifetime subscription on
each managed session that pushes a fresh `config_option_update` whenever the
event fires — independent of prompt-turn lifecycle. The
`session/set_session_config_option` handler no longer pushes its own
notification for the `thinking` config (lifetime subscription covers it);
the response still returns fresh `configOptions` so callers see the new
state synchronously. Subscriptions are released in `#disposeSessionRecord`.

Also consolidated four duplicate `config_option_update` send sites into a
new `#pushConfigOptionUpdate(record)` helper.

Tests: added two cases to `test/acp-agent.test.ts` — one verifying internal
`setThinkingLevel` calls produce a `config_option_update` and a no-op
re-set produces none, and one verifying client-driven
`setSessionConfigOption(thinking, …)` produces exactly one notification.

Co-Authored-By: omp <noreply@oh-my-pi.dev>
2026-05-13 16:14:18 -05:00
cognitive f02ab20acb fix(coding-agent/tui): refreshed pending bar on tagged-custom dequeue
Op: correct
Restores: ref:44e5e0bb8 — queued /skill: chip lifecycle parity with plain-text steer

EventController.#handleMessageStart now mirrors the user-role refresh in
the custom branch, gated on readPendingDisplayTag(details). Without this,
AgentSession's tag-keyed dequeue mutated #steeringMessages /
#followUpMessages correctly but pendingMessagesContainer kept painting
the stale chip until an unrelated trigger (next user submit, dequeue key,
compaction flush) fired a refresh.

Non-queued custom variants (ttsr-injection, irc:*, async-result,
hookMessage) skip the refresh — they never registered a pending chip, so
rebuilding pendingMessagesContainer for them would be pure waste.

Pairs with the existing E4 (array splice) regression — the new E10 covers
the UI-refresh side of the same dequeue event with both positive and
negative gate assertions.

Co-Authored-By: chatgpt-codex-connector[bot] (P2 review on PR #1043)
2026-05-13 15:28:31 +00:00
cognitive 8aba137941 fix(coding-agent/tui): silenced spurious "Operation aborted" on plan-mode compaction approval 2026-05-13 08:18:07 +00:00
can1357 e7b4b4c20d fix(coding-agent): fixed read tool streaming routing and result expansion behavior
- Updated event-controller read-tool streaming handling to wait for a parseable target before routing tool calls, avoiding early component binding for unresolved arguments.
- Allowed internal-URL read calls to bypass the regular read grouping path and fall through to direct tool execution.
- Adjusted read tool rendering to honor the computed `expanded` flag for completed output instead of forcing expanded output.
2026-05-13 04:42:43 +02:00
can1357 64b4aa1ae0 feat(coding-agent): implemented PR diff URL parsing for pr://<N>/diff
- Replaced `op: pr_diff` with `pr://<N>/diff` URL variants and routed PR diffs through URL parsing.
- Added `readArgsHaveTarget` checks to gate read-call tracking on `path`/`file_path` targets.
- Added auth-key-aware GitHub caching with scoped rows, default auth resolution, and hard-TTL invalidation.
- Added markdown output rendering for read with markdown-cell layout, ANSI-aware truncation, and expand-width cache reuse.
- Updated PR diff and cache tests, replacing deprecated `pr_diff` cases with `/diff` and auth/TLL coverage.
2026-05-13 04:32:16 +02:00
can1357 d483531b6b fix(coding-agent): decoupled internal URL read calls from read tool grouping
- Added readArgsTargetInternalUrl in the read tool group component to detect targets handled by InternalUrlRouter from path or file_path arguments.
- Updated event-controller and UI helper read rendering paths to skip grouping read tool calls when those arguments target internal URLs.
- Passed session cwd and settings into internal URL resolution in read.ts and added tests for internal versus non-internal target detection.
2026-05-13 04:05:23 +02:00
can1357 6d513c606f feat(coding-agent/modes): added timed expiry and cleanup for IRC chat messages
- Updated addMessageToChat in UI helpers and InteractiveModeContext to return rendered components instead of void.
- EventController now tracks IRC message components and removes them after a 10-second TTL, avoiding duplicate expiry scheduling per message signature.
- EventController dispose now clears all pending IRC expiry timers and tests were added for immediate render, TTL removal, duplicate suppression, and timer cleanup.
2026-05-12 03:11:49 +02:00
can1357 af8504d081 feat(coding-agent/modes): converted non-PNG tool images to PNG for Kitty terminal rendering
- Added asynchronous Kitty conversion for assistant tool images using `convertToPng`, keyed per tool-call entry with cached and in-flight tracking.
- Updated assistant image rendering to prefer converted PNGs for Kitty terminals while preserving existing behavior for other protocols.
- Added a unit test that verifies WebP tool images are converted and rendered as Kitty image output instead of the raw image/webp fallback.
2026-05-09 22:01:56 +02:00
can1357 1cce2ee96b feat(coding-agent/edit): added opt-in setting for pure-insert hashline duplicate dropping
- Added a new `edit.hashlineAutoDropPureInsertDuplicates` boolean setting with default `false` for hashline edits.
- Threaded the setting through tool execution contexts so hashline previews and execution honor the configured option.
- Changed pure-insert duplicate boundary absorption to run only when enabled and added tests for default-disabled and enabled behavior.
2026-05-04 05:58:43 +02:00
can1357 51dc178be8 feat(hindsight): implemented per-session hindsight retain queue auto-flush
- Added per-session retain queues with size/time auto-flush, recursive drain, and lifecycle flushes on end/clear/enqueue.
- Changed `hindsight-retain` to validate session state, enqueue writes, and return `Memory queued.` immediately.
- Added `notice` event support and handlers that route error/warning/status messages with source-aware formatting.
- Updated client and tests with shared request mapping, `RequestOptions`, `buildMemoryItem`, and expanded batch/list/doc APIs.
2026-05-03 08:51:53 +02:00
can1357 cb0d51b0f1 fix(coding-agent): guard non-string _i in event-controller intent update
Streamed tool-call JSON can deliver `_i` as an object, number, or boolean
before schema validation lands. The optional-chain in
#updateWorkingMessageFromIntent only guarded null/undefined, so any
non-string value crashed the UI with 'intent?.trim is not a function'.

Accept `unknown` and bail unless typeof intent === 'string', mirroring
the typed guard in agent-loop's extractIntent. Drop the misleading
`as string | undefined` cast at the streaming call site.

Fixes #900
2026-05-02 07:47:21 +02:00
can1357 7467add484 refactor(coding-agent): unified session title and accent handling around session names
- Removed title-source aware branching from session terminal-title and accent helpers, and updated callers to use session name plus cwd only.
- Dropped UUID-based recent-session naming by preferring explicit header titles or first user prompts and generating an "Untitled · <time>" fallback.
- Adjusted welcome session-row rendering for width-aware name truncation and disabled reasoning in title generation requests to keep terminal titles concise.
2026-05-02 01:42:06 +02:00
can1357 65507f343e fix(coding-agent/modes): preserved editor drafts for local message_start deliveries
- Tracked locally submitted user signatures for both optimistic and streamed-queue submissions in interactive-mode context state.
- Updated user message_start handling to avoid re-clearing the editor and re-adding chat for locally originated messages.
- Cleared consumed local signatures on queued-message restore and added tests for queued, external, and optimistic message_start editor behavior.
2026-04-29 19:39:26 +02:00
can1357 2b53492c2f feat(coding-agent): added IRC message event handling and chat rendering
- Added an `irc_message` session event carrying custom IRC messages and emitted it when IRC records are created.
- Registered an IRC message handler in EventController that skips duplicate messages by role, custom type, and timestamp.
- The handler now appends IRC messages to chat, resets read grouping, and triggers a UI render.
2026-04-27 02:44:58 +02:00
can1357 37a8203f94 refactor(coding-agent): standardized tool intent handling via unified intent option
- Replaced `AgentTool` `nointent` and `deriveIntent` with a unified `intent` option that supports `omit`, `optional`, `require`, or a callback function.
- Updated agent tool schema injection and execution paths to inject `_i` as required/optional/omitted and to derive intent through the new `intent` callback.
- Aligned atom-edit tests with the updated default sed behavior (`g` now off by default and explicit `g: true` for global replacement).
2026-04-26 14:54:53 +02:00
can1357 18085ac704 feat(coding-agent): added optional tool intent derivation and opt-out support
- Added `nointent` and `deriveIntent` to `AgentTool`, and made intent-schema injection honor `PI_NO_INTENT` plus per-tool opt-outs.
- Updated tool execution and streaming UI handling to derive a fallback intent when `_i` is absent, without aborting on derivation failures.
- Marked several coding tools as `nointent` and added `deriveIntent` callbacks where needed, then relaxed prompt language to indicate intent is present on most tools.
2026-04-26 14:22:26 +02:00
can1357 2e3e032645 fix(coding-agent): preserve editor draft on optimistic user message_start
Fixes #783
2026-04-26 13:00:00 +02:00
can1357 d82377cda8 revert: "read-to-open"
This reverts commit c48d2e6080.
2026-04-24 22:36:44 +02:00
can1357 c48d2e6080 feat(coding-agent): implemented read-to-open tool aliasing in runtime
- Canonicalized file and CLI defaults from `read` to `open` across tool registration and prompts.
- Added `resolveToolAlias()` and applied alias-normalized tool selection so legacy `read` maps to `open`.
- Updated runtime, UI, and export layers to treat `open` as first-class while preserving `read` compatibility.
- Renamed read prompt docs to `open.md`/`open-chunk.md` and refreshed system guidance to recommend `open`.
- Updated tool-related tests and expectations from `read` to `open` (including test fixtures and aliases).
2026-04-24 19:13:11 +02:00
can1357 7453c10801 feat(coding-agent): added optional inline read preview toggle
- Added a new read.toolResultPreview boolean setting defaulting to false to control inline read result rendering.
- Updated read tool group rendering to show inline previews only when enabled and to hide duplicate summary rows for previewed entries.
- Passed the setting through event and UI helper constructors and added tests for default-off behavior and the duplicate-preview summary case.
2026-04-18 23:37:47 +02:00
can1357 8bd7310cb4 feat(coding-agent): implemented vim tool-call preview mapping per command
- Added vim tool-call IDs across EventController, UiHelpers, and ToolExecution for per-call preview mapping.
- Extended Vim type and command parsing with update/write, edit, global, yank, and put handling.
- Added Vim engine support for new commands and motions, including gJ, g*, g#, g_, |, and gu/gU/g~.
- Reworked Vim tool flow to cache per-file engine clones, reuse tool details, and stream inserts in chunks.
- Updated vim.md and changelog to document new vim keys, ex aliases, and fixed :global preview behavior.
- Added parser and renderer tests plus a tmp/vim_test.txt fixture for chunked, cursor, and partial-insert cases.
2026-04-13 21:57:33 +02:00
can1357 655a3bffea feat(coding-agent): added multi-file edits in coding-agent with per-entry payloads
- Added multi-file edit payload support by requiring per-entry `edits` arrays across patch, hashline, replace, and chunk modes.
- Changed edit schemas and validators to move `path` (and `sel`->`path`) and op data into each edit entry.
- Changed edit execution flow to parse `file:selector` paths, run single-entry executors per file, and return grouped per-file results.
- Updated chunk diff rendering and test expectations to emit consistent anchor gutters with spaced pipes and `^` head-line markers.
2026-04-13 06:59:01 +02:00
can1357 11b7ba7846 fix(coding-agent): respected session title source when formatting terminal titles
- Propagated session title source through terminal-title update calls so auto and user names are handled consistently across controllers.
- Suppressed auto-generated names in status-line segments and completion messages by falling back to cwd-based titles.
- Updated title formatter tests to verify auto-generated and user-specified session titles produce different terminal labels.
2026-04-13 06:22:37 +02:00
can1357 f4b6b32262 refactor(modes): restructured event controller into dedicated handler methods for type safety
- Extracted large switch statement into 16 dedicated event handler methods for improved maintainability and type safety.
- Introduced AgentSessionEventHandlers type and handler dispatch map to enable compile-time verification of event coverage.
2026-04-10 14:49:06 +02:00
can1357 3d29a48e7a fix(coding-agent): fixed memory leak by cancelling idle compaction
- Fixed memory leak by cancelling idle compaction timer on event controller disposal.
- Fixed session resumption to preserve last non-empty session when starting fresh.
- Fixed stash detection to use git ref resolution instead of output parsing for reliability.
- Fixed secret obfuscation to deobfuscate restored session messages locally while keeping LLM messages obfuscated.
- Fixed stash pop operation to preserve staged changes with --index flag after task branch merges.
- Changed idle compaction settings from enum to numeric type for flexible configuration.
2026-04-05 03:50:52 +02:00
can1357 b278e56343 fix: recheck usage on idle timer fire and honor strategy=off for idle compaction 2026-04-05 01:17:35 +02:00
DeprecatedLuke 5dfa44f2a3 feat(coding-agent): add idle compaction flow 2026-04-04 11:52:43 +01:00
enieuwy 323a3bc29c feat(core): add first-class retry fallback chains for model/provider failover (#541)
* feat(rules): implemented alwaysApply auto-injection into system prompt

rules with alwaysApply: true were parsed by all providers and used to
exclude the rule from rulebookRules, but the inclusion half was never
built — rule content was silently dropped. now:

- full content is injected directly into the system prompt (before the
  rulebook rules section) in both default and custom prompt templates
- rules remain addressable via rule:// for re-reading
- ttsr rules still take priority (condition + alwaysApply goes to ttsr only)

updated rulebook-matching-pipeline.md to reflect the three-bucket split
(ttsr > always-apply > rulebook) and corrected the rule:// resolution
docs.

* feat(browser): implement screenshot path saving

- Add `browser.screenshotDir` setting (tools tab) for a persistent
  default screenshot directory, configurable via /settings
- Honour the existing `path` parameter in the screenshot action,
  which was declared in the schema but never consumed by the implementation
- Resolution order: params.path (abs) > join(screenshotDir, params.path)
  > join(screenshotDir, screenshot-<timestamp>.png) > /tmp only
- Writes full-resolution buffer to disk (not the API-compressed copy)
- Creates destination directory recursively if it doesn't exist
- details.screenshotPath reflects the actual saved location

Fixes: path param silently ignored since removal in v11.5.0

* feat(browser): expand ~ in screenshotDir and path params

Users can now configure browser.screenshotDir as ~/Downloads or
~/Pictures and use params.path as ~/screenshots/foo.png without
needing to supply fully-qualified paths.

* fix(browser): write screenshot to exactly one location

Previously wrote to /tmp unconditionally then copied to user path,
resulting in two files. Now resolves a single destination upfront:
  1. params.path (absolute, or relative to screenshotDir/cwd)
  2. screenshotDir + auto-timestamp filename
  3. /tmp fallback (original behaviour, unchanged)

Also: user-defined destinations receive the full-res buffer;
/tmp fallback retains the API-compressed copy as before.

* feat(settings): add text input support for plain string settings

Settings with type: "string" and no submenu now render as an editable
text field in the /settings TUI panel instead of being silently skipped.

- settings-defs.ts: add TextInputSettingDef interface; pathToSettingDef
  falls through to { type: "text" } for any plain string schema entry
- settings-selector.ts: add TextInputSubmenu class (mirrors
  ConfigInputSubmenu from plugin-settings.ts); add "text" case to
  #defToItem; add #createTextInput method

This makes browser.screenshotDir visible and editable in the Tools tab.
Empty field on submit clears the setting (falls back to /tmp behavior).

* fix(settings): text input — cursor at end, block tab navigation

- Cursor: call handleInput(ctrl+e) after setValue to jump to end of
  pre-filled string instead of leaving it at position 0
- Tab/arrow guard: add #textInputActive flag; suppress tab-switch and
  left/right routing to tab bar while a TextInputSubmenu is open, so
  arrow keys reach the Input component's cursor movement handlers
  instead of switching settings tabs

* fix(browser): expand ~\ (Windows backslash) in screenshot paths

expandHome now handles both Unix ~/... and Windows ~\... separators,
matching user expectation on all platforms. Addresses Codex review.

* fix(coding-agent): use expandPath for screenshots

* docs: add changelog for screenshot path option

Bug fixes:
- Add browser.screenshotDir to settings-schema.ts (lost during rebase conflict)
- Fix stale expandHome comment to expandPath in settings-selector.ts
- Final screenshotDir description: Directory to save screenshots with ~ support

* fix: biome format corrections for screenshot-path-option branch

* fix: add missing #textInputActive field and screenshotDir default

* fix(browser): align screenshot metadata with saved file contents

When screenshotDir or params.path is set, the full-resolution PNG buffer
is written to disk. Previously mimeType/bytes in details still reflected
the resized payload sent to the model, making metadata inconsistent with
the actual saved file.

Now savedBuffer/savedMimeType track what is written, and details reflects
that. Display output distinguishes 'Saved' vs 'Model' when full-res is
used, and collapses to a single Format/Dimensions line for temp-only.

* fix(browser): resolve params.path relative to cwd regardless of screenshotDir

screenshotDir is a default save location, not an anchor for explicit
paths. A relative params.path should always resolve against cwd so its
semantics are stable and predictable regardless of user settings.

* fix(tui): enforce strict line budget for collapsed tool output

The grep, ast_grep, and ast_edit renderers used group-count-based
collapse that always included the first group unconditionally,
allowing collapsed output to remain visually large when a single
group contained many lines.

Add maxCollapsedLines to renderTreeList that enforces a strict
total-line cap in collapsed mode. Items that exceed the remaining
budget are skipped entirely (no broken fragments). The isLast tree
branch is computed after the budget check to avoid double-last
branches when a summary line follows.

Remove the per-tool getCollapsedMatchLimit / getCollapsedChangeLimit
helpers that are now redundant.

Fixes #455

Made-with: Cursor

* WIP

* WIP

* cleanup

* docs(coding-agent): update changelog for custom model tags and cycle order

* Fix custom model precedence across load and refresh

* feat(ask): add multiline editor support for custom input

* feat(extension-ui): add dialog options and abort signal support to editor

* docs(ask): add multiline editor and timeout behavior guidance

* docs(ask): simplify multiline input documentation

* fix(tui): preserve terminal scrollback during full redraws

Replace destructive \x1b[3J\x1b[2J\x1b[H full-redraw sequence with
scrollback-preserving repaint helpers:

- seedTranscript: first paint with no prior frame, writes full transcript
  without clearing scrollback
- repaintViewport: trusted-frame repaints that scroll viewport-shift
  delta into scrollback before overwriting visible rows in-place
- Height-increase handler that pushes revealed scrollback back before
  reclaiming the display

Replace requestRender(true) state destruction with a one-shot
without resetting #previousLines or cursor bookkeeping.

Track #previousHeight to detect terminal height increases that pull
scrollback lines into the visible area.

fixes #507

* fix(tui): fix exit gaps, content shrink drift, and overlay cursor recovery

- Rewrite stop() to use viewport-relative cursor positioning instead of
  content-length, preventing blank gaps when content is shorter than viewport
- Replace trailing \r\n\x1b[2K clear loops in repaintViewport() and
  height-increase path with \r\n\x1b[J to avoid cursor drift past content
- Add 12 TUI regression tests for exit gaps, content shrink, and overlay
  dismiss cursor recovery
- Add 6 coding-agent controller tests for /new and /tree commands

* fix(tui): redraw sparse height increases atomically

* fix(coding-agent,tui): address review regressions

* fix(tui): reseed after terminal resume

* test(ai): avoid leaking kagi module mocks

* fix(ask): keep multiline custom input in prompt gutter

* fix(ask): preserve multiselect choices on editor dismiss

* fix(ask): honor app interrupt in prompt editor

* fix(coding-agent): preserve new-session approval state

* feat(core): add session-scoped model/provider retry fallback policy

* feat(core): validate retry fallback chains on session startup

* fix(ask): preserve prior answer when custom editor dismissed in single-select

* fix(core): harden retry fallback policy semantics

* fix(core): correct retry fallback edge cases

* test(coding-agent): removed macOS fallback test case from theme detection

- Removed test case for macOS fallback behavior inside Zellij.

* refactor: simplified null checks using optional chaining across TypeScript and Rust modules

- Simplified null/empty checks across TypeScript codebase using optional chaining operator (?.) for improved readability.
- Replaced explicit null checks in validation logic with optional chaining in oauth-discovery, gemini-cli, claude, zai, and lsp modules.
- Updated error handling in Rust command invocation to use double question mark operator (??) for cmd_result.
- Consolidated null validation patterns across tools (bash-skill-urls, browser, gemini-image, resolve) and keybindings using optional chaining.

* chore: bump version to 13.15.1

* fix(core): address PR review on fallback retry behavior

* test(ai): refactored auth storage test to use spyOn for cleaner mocks

- Refactored auth storage test to use vi.spyOn() instead of vi.mock() for cleaner mock management.
- Simplified mock type definitions by leveraging bun:test's Mock type import.

* chore: bump version to 13.15.2

* Fix stale OpenAI Responses replay across session boundaries (#534)

* Fix stale OpenAI Responses replay across session boundaries

Fixes #505

* Fix CI tests for session replay change

* Harden session reload and switch rollback

* Guard session switch snapshots

* fix(coding-agent): preserve responses replay snapshots

* Normalize pasted image formats before attach (#543)

Co-authored-by: iter <itertoolz@gmail.com>

* Allow overriding the Codex web search model (#516)

* Allow codex web search model override

* Handle blank codex web search model

* feat(ai): add gemini-3.1-pro-preview models to google-vertex provider (#521)

Add gemini-3.1-pro-preview and gemini-3.1-pro-preview-customtools to
the google-vertex provider in models.json, matching the existing
google-generative-ai entries.

Fixes #520

Co-authored-by: Muness Castle <munesscastle@artium.ai>

* Make temporary model selector keybinding configurable (#539)

Fixes #533

* chore: bump models.json

* refactor(coding-agent): migrated test mocks to vitest spyOn with Symbol.dispose cleanup

- Migrated test mocking from bun:test mock API to vitest spyOn pattern across 9 test files.
- Extracted mock setup logic into reusable helper functions with Symbol.dispose cleanup pattern.
- Replaced manual beforeEach/afterEach and try-finally blocks with TypeScript 5.2 using declarations.
- Removed 178 lines of boilerplate mock initialization and restoration code from test suite.

* chore: bump version to 13.15.3

* fix(ask): restore prompt-style enter handling

* fix(tui): avoid blank scrollback regressions

* fix(models): keep same-id replacements authoritative

* fix(tui): enforce collapsed line budgets

* fix(models): unify selector role sources

* fix(rules): dedupe always-apply prompt injection

* fix(browser): show saved screenshot path

* style: format merged PR fixes

* refactor(coding-agent): restructured screenshot and prompt utilities into focused helpers

- Extracted screenshot formatting logic into dedicated `formatScreenshot()` function with options support.
- Consolidated prompt source deduplication into `dedupePromptSource()` helper to prevent rule duplication.
- Refactored editor text sanitization to use `replaceTabs()` utility for consistent tab width handling.
- Added test coverage verifying editor respects configured tab width when loading text programmatically.

* refactor(coding-agent): restructured validation and rendering for consistency

- Refactored theme color validation to use single source of truth with THEME_COLOR_RECORD object.
- Simplified model registry to defer per-model overrides to dedicated method and use constant for role IDs.
- Refactored tree list rendering to pre-render items once for consistent line counts across phases.
- Refactored question result formatting to use early returns and consistently include question ID in output.
- Updated hook editor hint text to include ctrl+g external editor option when prompt style is enabled.
- Removed unused isLogicalLineStart property from LayoutLine interface in editor component.

* revert: 535 due to TUI regressions

* test(coding-agent): corrected hook-editor assertion for keybinding render

- Corrected assertion in hook-editor test to verify external editor keybinding is rendered.

* feat(tools): added root path alias to resolve bare / to working directory

- Added root path alias feature to resolve bare `/` to session working directory in path resolution.
- Updated browser tool to use `resolveToCwd()` for consistent workspace-relative path handling.
- Added comprehensive test suite validating root path alias resolution across grep, read, find, ast_grep, and ast_edit tools.

* feat(prompts/tools): clarified hashline block boundary handling with examples

- Improved hashline tool documentation with clearer guidance on block boundary handling and closing delimiter duplication prevention.
- Added concrete example demonstrating correct anchor placement when replacing entire blocks including closing braces.
- Reorganized boundary duplication warnings into actionable self-check guidance with visual comparison steps.

* chore: bump version to 13.16.0

* fix(coding-agent): fixed python kernel startup hangs (#548)

* fix(coding-agent): fixed python kernel startup hangs

* fix(coding-agent): fixed startup timeout regressions

* fix(coding-agent): preserved startup cancellation typing

* perf(pi-natives): optimized memory allocation with MiMalloc integration

- Integrated MiMalloc as global allocator to improve memory allocation performance.

* feat: fff

- Added SearchDb class for stateful shared search database instances enabling persistent file indexing and frecency tracking across grep, glob, and fuzzyFind operations.
- Added optional db parameter to grep(), glob(), and fuzzyFind() functions for database-backed searching with improved performance via cached file indices.
- Replaced grep-searcher with fff-grep and added fff-search dependency for enhanced file discovery and search capabilities with memory-mapped file support.
- Migrated fuzzy file discovery from fd module to fff module with SearchDb integration for stateful caching and improved search performance.
- Exported SearchDb type from @oh-my-pi/pi-natives public API for type-safe usage in grep, glob, and fuzzyFind workflows.

* feat(pi-natives): added unified picker coordination for file search operations

- Added `wait_for_picker_scan()` function to search_db module with cancellation token support for polling picker scan completion.
- Integrated picker-based file search into glob matching logic with `collect_files_from_picker()` helper to reuse shared SearchDb picker results.
- Refactored fff and grep modules to use centralized `wait_for_picker_scan()` wrapper instead of direct FilePicker calls, improving cancellation handling.
- Propagated SearchDb instance through agent session initialization and input controller to enable unified file picker coordination across search operations.

* chore: bump version to 13.16.1

* fix: install zig in CI

* feat(tui): make inline image max-width configurable via tui.maxInlineImageColumns (#551)

* feat(tui): make inline image max-width configurable via tui.maxInlineImageColumns

* fix(tui): handle 0 as unlimited in maxInlineImageColumns; drop || undefined coercion

* feat(browser): auto-detect NixOS and use system Chromium (#550)

Puppeteer's bundled Chromium is a dynamically-linked FHS binary that
cannot run on NixOS. On startup, resolveSystemChromium() checks for
/etc/NIXOS and searches for a usable binary in order:

  1. chromium on PATH
  2. chromium-browser on PATH
  3. ~/.nix-profile/bin/chromium
  4. /run/current-system/sw/bin/chromium

The resolved path is passed as executablePath to puppeteer.launch().
Result is cached per process. On non-NixOS systems the function returns
undefined immediately, leaving Puppeteer's default resolution intact.

* feat(pi-natives): added automatic parenthesis escaping in regex patterns

- Added automatic escaping of unescaped parentheses in regex patterns when group syntax errors occur, enabling literal function call patterns like `fetchAnthropicProvider(` to work as search queries.
- Extracted regex matcher builder into separate function for reusability and error recovery logic.
- Added 2 test cases validating parenthesis escaping behavior for both escaped and literal parentheses.
- Fixed documentation formatting in sanitize_braces comment.

* style: reformat

* chore: bump version to 13.16.2

* fix: only show update banner when npm version is strictly newer (#552)

* fix(ai): corrected OAuth credential updates to replace in-place instead of accumulating soft-deleted rows

- Fixed OAuth credential updates to replace matching credentials in-place rather than creating disabled rows, preventing unbounded accumulation of soft-deleted credentials.
- Modified OAuth credential saving to preserve unrelated identities instead of replacing all credentials for a provider.
- Updated credential identity resolution to use provider context for more accurate email deduplication.
- Implemented upsertAuthCredentialForProvider method to handle credential matching and in-place updates.
- Added 5 test cases covering credential preservation across reauth, multi-account scenarios, and stale cache handling.

* chore: bump version to 13.16.3

* feat: introduced unified range API for hashline edits and model catalog updates

- Simplified hashline edit location API by replacing separate `line` and `block` properties with unified `range` property accepting `{ pos, end }` anchors.
- Renamed hashline helper functions from `hlineref`/`hlinefull` to `href`/`hline` for improved brevity and consistency.
- Added detection for `kysely-codegen` generated files in auto-generated file guard with corresponding test coverage.
- Added 13 new AI model configurations and updated token limits and pricing for existing models across multiple providers.
- Enhanced file type validation in grep native to reject symlinks, FIFOs, sockets, and non-regular files with improved error handling.

* chore: bump version to 13.16.4

* fix: pin rustc-hash to 2.1.1 to avoid SIGILL on CI

rustc-hash 2.1.2 (released today) refactored hash_bytes to use
split_first_chunk, which produces illegal instructions when compiled
with nightly + -C target-cpu=x86-64-v3 on CI runners.

* fix(ci): pin nightly to 2026-03-27 to avoid codegen SIGILL regression

Today's nightly produces illegal instructions when compiled with
-C target-cpu=x86-64-v3. Reverts the unnecessary rustc-hash pin from
the previous commit since the real cause is the nightly compiler.

Also lets Cargo.lock return to rustc-hash 2.1.2 (not the culprit).

* fix(ci): add rustup target fallback for pinned nightly cross-compile

* fix(coding-agent): do not prompt to use grep and find tools if they are disabled (#566)

Co-authored-by: le-cameleon <200889489+le-cameleon@users.noreply.github.com>

* fix(natives): skipped grep special files (#565)

avoided opening fifos and other special filesystem nodes during grep and added fifo regressions in native and coding-agent tests.

* fix: skill baseDir regex fails on Windows backslash paths (#554)

The regex that strips SKILL.md from the path to compute baseDir only
matches forward slashes. On Windows where paths use backslashes, the
replace is a no-op and baseDir equals the full SKILL.md file path.

This breaks sub-path resolution for skills: the subpath gets appended
to the SKILL.md file path instead of the skill directory.

Fix: use character class matching both path separators.

---------

Co-authored-by: deadcode-walker <268043493+deadcode-walker@users.noreply.github.com>
Co-authored-by: Rens Tillmann <rens@super-forms.com>
Co-authored-by: haiyang.zhou <haiyang.zhou@seamoney.com>
Co-authored-by: Leo P <junk@slact.net>
Co-authored-by: Zakhar Kogan <36503576+zaharkogan@users.noreply.github.com>
Co-authored-by: Vu Anh Nguyen <vuanhng00@gmail.com>
Co-authored-by: can1357 <me@can.ac>
Co-authored-by: daandden <64765666+daandden@users.noreply.github.com>
Co-authored-by: iter <72358817+itertea@users.noreply.github.com>
Co-authored-by: iter <itertoolz@gmail.com>
Co-authored-by: Cheol Kang <dev@cheol.me>
Co-authored-by: Muness Castle <931+muness@users.noreply.github.com>
Co-authored-by: Muness Castle <munesscastle@artium.ai>
Co-authored-by: zamo <falby97@proton.me>
Co-authored-by: elikoga <elikowa@gmail.com>
Co-authored-by: BayLee4 <63376748+BayLee4@users.noreply.github.com>
Co-authored-by: le-cameleon <200889489+le-cameleon@users.noreply.github.com>
Co-authored-by: Wiedzmin <56316383+art-wiedzmin@users.noreply.github.com>
2026-03-29 17:50:36 +02:00
luke c0f14aa248 feat(coding-agent): auto-clear completed todo tasks (#435)
- Schedule auto-removal of completed/abandoned tasks after ~1 minute delay
- Strip already-done tasks when restoring session from branch history
- Add todo_auto_clear event to trigger UI refresh on removal
- Add blank line before Todos header for visual spacing
2026-03-15 19:02:02 +01:00
luke 2f496efba9 Spill over artifact output and add token usage information display. (#391)
* feat: spill large tool results to artifacts, show tail

- Add centralized spillLargeResultToArtifact() in wrappedExecute pipeline
- Tool results exceeding 50KB saved as session artifacts via saveArtifact()
- Content truncated to tail (20KB / 500 lines) instead of head
- Truncation notice includes artifact:// reference for full output retrieval
- Skip spill when tool already saved its own artifact (bash/python/ssh)
- Update formatFullOutputReference to use action-oriented wording

* feat: per-turn token usage display on assistant messages

* fix: TS errors in output-meta truncation fields
2026-03-14 11:27:18 +01:00
Bryce Thorpe 490782c0b6 fix(coding-agent): suppress false maintenance-failed warning on benign compaction skips (#394)
Three early-return paths in #runAutoCompaction emitted auto_compaction_end
with result=undefined, aborted=false, and no errorMessage when compaction
was legitimately not needed (no model selected, no candidate models
available, or nothing to compact yet). The event-controller had no way to
distinguish these benign skips from a genuine failure, and fell through to
show the warning:

  'Auto context-full maintenance failed; continuing without maintenance'

This was visible after a successful compaction: the next threshold check
would find nothing new to compact (prepareCompaction returns null), emit a
soft-skip event, and trigger the false warning.

Add skipped?: boolean to the auto_compaction_end event type and set it on
the three soft-skip paths. Update the event-controller to treat skipped
events as silent no-ops. Propagate the field through the extension and
hook AutoCompactionEndEvent interfaces so extensions can observe the
distinction.
2026-03-14 10:48:37 +01:00
can1357 e019a3e352 refactor(coding-agent): restructured loading animation lifecycle into ensureLoadingAnimation
- Extracted loading animation lifecycle management into centralized ensureLoadingAnimation() method.
- Consolidated duplicate loading animation setup across event-controller and interactive-mode into single reusable method.
- Updated showError() to properly clean up loading animation state when errors occur.
- Added comprehensive test coverage for InputController escape key behavior with optimistic submission.
2026-03-10 05:51:09 +01:00
Miroslav Drbal [ApoC] ef33f7b4c8 fix(coding-agent): show compaction summary after manual /compact (#318)
The manual /compact command path in executeCompaction() called
rebuildChatFromMessages() but never added the compactionSummary
message to the chat. The auto-compaction path in event-controller
explicitly adds it, but the manual path was missing this step.

Capture the CompactionResult returned by session.compact() and
render the summary via addMessageToChat(), matching the behavior
of the auto-compaction flow.

Co-authored-by: Miroslav Drbal <miroslav.drbal@gendigital.com>
2026-03-10 02:48:52 +01:00
ravshansbox c4715a918a Fix delayed display of submitted user messages (#312) 2026-03-10 02:42:46 +01:00
can1357 57c89cf503 refactor(auth-storage): restructured credential matching to use accountId
- Extracted OAuth identifier logic into public functions extractOAuthCredentialIdentifiers and extractOAuthTokenIdentifiers.
- Replaced single credentialIdentity string with multi-identifier resolveCredentialIdentifiers returning string[] for flexible matching.
- Changed credential deduplication from email-based to accountId-based matching in replaceAuthCredentialsForProvider.
- Updated auth-storage tests to verify accountId-prioritized deduplication behavior across soft-disable and hard-delete scenarios.
- Added documentation comments in coding-agent modules explaining partial JSON preservation for streaming tool previews.
- Documented streaming tool preview requirements and render paths in AGENTS.md.
2026-03-08 15:58:52 +01:00
can1357 19feec9592 feat(bash): added env parameter to bash tool for safe variable passing
- Added `env` parameter to bash tool for safe environment variable passing without shell re-parsing.
- Added support for rendering partial environment variable assignments in command preview during streaming.
- Updated bash tool prompt to recommend `env` parameter for multiline, quote-heavy, and untrusted values.
- Refactored tool execution component to conditionally merge partial JSON arguments during streaming.
- Added helper functions for environment variable normalization, escaping, and formatting.
2026-03-08 15:53:33 +01:00
HvC b93c6c0e12 Offer handoff as a compaction strategy (#305)
* idiomatic rust fixes

* idiomatic rust fixes

* display an image if we are fetching an image

* MIME type strictness

* codex nagging me

* codex nagging

* handoff instead of compaction as context filled strategy and surfacing

* handoff instead of compaction as context filled strategy and surfacing p2

* handoff instead of compaction as context filled strategy and surfacing p3

* handoff instead of compaction as context filled strategy and surfacing p4

* handoff instead of compaction as context filled strategy and surfacing p5

* handoff instead of compaction as context filled strategy and surfacing, fixes

* failing fetch test from the fetch tool updates

* handoff focus prompt skeleton

* handoff focus prompt skeleton p2

* fetch bugs

* further codex improvements

* further codex improvements

---------

Co-authored-by: Brit <lol@no.com>
2026-03-06 03:12:31 +01:00
can1357 c7eeb76949 fix(images): preserve async state, text blocks, and reject unknown protocol overrides
- event-controller: check async state for inlined image read results
  instead of hardcoding isBackgroundRunning=false
- ui-helpers: fall through to render text blocks when read results
  contain both images and text
- terminal-capabilities: return null for unknown PI_FORCE_IMAGE_PROTOCOL
  values instead of silently falling through to fallback detection
2026-02-28 12:36:51 +01:00
Matej da7eba9c25 fix(images): restore read rendering and protocol fallbacks (#195)
* fix(images): restore read rendering and protocol fallbacks

* fix(tui): narrow kitty fallback heuristic

* fix(coding-agent): keep read placeholder on abort

---------

Co-authored-by: Can Bölük <can1357@users.noreply.github.com>
2026-02-28 12:27:34 +01:00
can1357 2574d4c977 feat(todo): add phased todo ops and task statuses 2026-02-22 18:35:06 +01:00