Commit Graph

190 Commits

Author SHA1 Message Date
can1357 9b78a6fa85 refactor(natives): migrated native bindings to NAPI-RS with auto-generated types
- Migrated native bindings from TypeScript wrappers to NAPI-RS generated modules with auto-generated type definitions and runtime enums.
- Replaced chunk tree API with stateful ChunkState class supporting render, edit, and resolve operations with improved error handling.
- Converted callback signatures to error-first pattern (error, result) for shell, PTY, glob, and grep operations.
- Introduced type-safe enums for MacOSAppearance, GrepOutputMode, KeyEventType, ImageFormat, and AstMatchStrictness replacing string literals.
- Refactored chunk tree implementation with dedicated modules for edit, indent, resolve, and state management with comprehensive validation.
- Moved clipboard utilities from native bindings to coding-agent package with improved OSC 52 and Termux compatibility.
2026-04-07 02:00:59 +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
Can Bölük 63625184d8 Merge branch 'main' into feat/idle-compaction 2026-04-05 01:18:59 +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
Patrik Sundberg 94d3636bc5 fix(coding-agent): address session observer PR review feedback
- Move lifecycle end event after finalizeSubprocessOutput() so
  submit_result({status:'aborted'}) is correctly reflected in the
  observer instead of showing completed/failed (P1)
- Reset observer registry on session resume and /new command so
  stale subagent sessions from prior conversations are cleared (P2)
- Cache parsed JSONL transcript incrementally: track byte offset,
  only read and parse new bytes on each refresh instead of reparsing
  the entire file, avoiding render loop blocking on large sessions (P2)
2026-04-04 15:53:31 +02:00
Patrik Sundberg 4d641a52b4 feat(coding-agent): add session observer (Ctrl+S) to view subagent sessions
Wire EventBus through task runtime so subagent lifecycle and progress
events propagate to the TUI. Add SessionObserverRegistry to track
active sessions, and a session observer overlay accessible via Ctrl+S
that shows a picker of running subagents and a read-only transcript
viewer that reads the subagent's session JSONL file to display
thinking, text, tool calls, and results.

- Add TASK_SUBAGENT_LIFECYCLE_CHANNEL for start/end events
- Add SubagentProgressPayload.sessionFile for session file tracking
- Pass eventBus through sdk.ts -> main.ts -> InteractiveMode
- SessionObserverRegistry with multi-listener onChange pattern
- Overlay picker preserves selection position across live refreshes
- Viewer renders full transcript from session JSONL (thinking, text,
  tool calls with smart arg summaries, inline tool results)
2026-04-04 15:53:31 +02:00
DeprecatedLuke 5dfa44f2a3 feat(coding-agent): add idle compaction flow 2026-04-04 11:52:43 +01:00
can1357 6bb10ca40e feat(modes): enabled external editor integration for plan review and editing workflows
- Added external editor callback support to extension UI dialogs and hook selector for opening plans in external editor.
- Added `matchesAppExternalEditor()` keybinding matcher to detect external editor shortcuts (ctrl+g) across components.
- Added `trimTrailingNewline` option to `openInEditor()` function to preserve trailing newlines when editing externally.
- Modified plan review flow to re-read plan content from disk before approval to reflect external editor changes.
- Refactored plan preview rendering to cache and reuse UI container instead of recreating children on each render.
- Refactored Promise creation in external editor utility to use `Promise.withResolvers()` for cleaner async handling.
2026-04-02 07:43:01 +02:00
can1357 e59436ba31 feat(coding-agent): added /tools command to display available agent tools
- Added `/tools` slash command to display agent-visible tools in interactive sessions.
- Added `handleToolsCommand()` method to InteractiveMode to delegate tools display to command controller.
- Added `buildToolsMarkdown()` utility function to generate formatted markdown table of available tools.
- Refactored `showMarkdownPanel()` helper to reduce duplication in markdown display logic across commands.
2026-04-01 20:32:59 +02:00
Miroslav Drbal c7f4f597bd fix(coding-agent): pass scope through plugin selector uninstall flow
When a plugin is installed in both user and project scope, the selector
now shows separate scoped entries (e.g. 'plugin-name@1.0 [project]' and
'plugin-name@1.0 [user]') and forwards the selected scope to
uninstallPlugin(), preventing the disambiguation error introduced when
dual-scope support was added.
2026-03-31 21:29:24 +02:00
Miroslav Drbal 05966c8910 feat(coding-agent): marketplace plugin project scope
Plugins can now be installed at user scope (global) or project scope
(per-project, higher capability priority). Scope is encoded in registry
file location, not a metadata field:

  user:    ~/.omp/plugins/installed_plugins.json
  project: <nearest-project>/.omp/plugins/installed_plugins.json
  cache:   ~/.omp/plugins/cache/plugins/  (shared, path-referenced)

Project root discovery: resolveActiveProjectRegistryPath(cwd) walks up
from cwd looking for the nearest .omp/ directory, falling back to the
nearest .git root. This is the single resolver used by install, uninstall,
list, upgrade, discovery, and doctor.

Discovery: listClaudePluginRoots(home, cwd?) reads both registries when
cwd is provided. Project entries shadow user entries for the same plugin
ID. Cache key is canonical ("${home}:${resolvedProjectPath}") so nested
cwds within the same project share a cache entry.

Manager changes:
- installPlugin({ scope? }): routes registry reads/writes by scope;
  checks collectReferencedPaths() across both registries before deleting
  any cached plugin dir to prevent cross-scope data loss
- uninstallPlugin(id, scope?), setPluginEnabled(id, enabled, scope?),
  upgradePlugin(id, scope?): throw a disambiguation error when the plugin
  exists in both scopes and no scope is specified
- upgradePluginAcrossScopes(id): new; upgrades all scopes the plugin is
  installed in; returns InstalledPluginEntry[]
- upgradeAllPlugins(): uses upgradePluginAcrossScopes; result includes scope
- listInstalledPlugins(): returns InstalledPluginSummary[] merged from both
  registries; user entries marked shadowedBy: "project" when overridden

CLI: omp plugin install|uninstall|upgrade|enable|disable --scope user|project
Slash: /marketplace install [--scope user|project] name@marketplace
MarketplaceManager constructed with projectInstalledRegistryPath in all
CLI handlers and builtin-registry.ts via resolveActiveProjectRegistryPath.

.gitignore: .omp/plugins/ added (local runtime state, not committed).
preloadPluginRoots/clearClaudePluginRootsCache carry cwd through for LSP.
main.ts passes getProjectDir() at startup.

Tests: 226 pass across 13 files. New: project-scope.test.ts (resolver
walk-up, .git fallback, null return, canonical path, shadow precedence);
manager scope tests (registry isolation, disambiguation errors, cross-scope
cache-ref protection, upgradePluginAcrossScopes, shadowedBy marking).

fixes #581
2026-03-31 17:43:09 +02:00
can1357 d18504d632 fix(coding-agent): corrected marketplace plugin selector error handling and cleanup
- Added error handling for marketplace plugin selector failures with user-facing error messages.
- Fixed marketplace clone promotion timing by extracting logic into separate function and applying consistently across addMarketplace and refreshMarketplace methods.
- Added cleanup of temporary clone directories on source verification failures to prevent orphaned files.
- Improved plugin selector UI rendering by expanding onCancel callback to trigger requestRender after completion.
- Fixed LSP config path handling by replacing hardcoded filename array with variable reference.
- Enhanced error handling for unknown plugin source variants in marketplace validation.
2026-03-30 13:54:31 +02:00
Miroslav Drbal 4e199f93f7 feat: add marketplace plugin system
Add Claude Code-compatible marketplace plugin infrastructure:

- Registry: types, ID helpers, atomic read/write for marketplaces.json
  and installed_plugins.json (Claude Code format with version: 2)
- Fetcher: classifySource (6 ordered rules), parseMarketplaceCatalog,
  fetchMarketplace (local sources; git/http stubs for Phase 2)
- Resolver + Cache: resolvePluginSource with pathIsWithin containment,
  cachePlugin, removeCachedPlugin, cleanOrphanedCache
- MarketplaceManager: orchestrates add/remove/update marketplaces,
  install/uninstall/enable plugins, clearPluginRootsCache on mutation
- CLI: omp plugin marketplace add|remove|update|list,
  omp plugin discover, classifyInstallTarget for name@marketplace
- Discovery: listClaudePluginRoots reads OMP registry alongside
  Claude's, OMP authoritative for duplicate plugin IDs
- Args: --plugin-dir repeatable flag (parsing only, runtime wiring TBD)
- Slash command: /reload-plugins clears fs + roots cache
- Test fixtures and 130 tests across 8 test files
2026-03-30 13:44:53 +02:00
can1357 bc2b99f9b0 feat(coding-agent): removed grep.app provider, consolidated code search to Exa
- Removed grep.app code search provider support; code search now uses Exa exclusively.
- Removed `providers.codeSearch` configuration setting and related UI options from settings schema.
- Removed `setPreferredCodeSearchProvider` and `isCodeSearchProviderId` exports from public API.
- Simplified code search implementation by eliminating provider selection logic and grep-specific parsing.
2026-03-30 13:44:52 +02:00
Miroslav Drbal [ApoC] 62676f4de8 fix(mcp): activate new server tools immediately after /mcp add (#557)
refreshMCPTools preserves the prior MCP tool selection by only keeping
tools that were already active. Brand-new servers added via /mcp add
had their tools registered in the registry but never activated on the
agent, making them invisible until restart.

After the connection is confirmed in #handleWizardComplete, explicitly
add the new server's tools to the active set via setActiveToolsByName.
Covers both the normal connection path and the fallback

Co-authored-by: Miroslav Drbal <miroslav.drbal@gendigital.com>
2026-03-30 13:28:42 +02: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
can1357 49cb500175 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.
2026-03-27 11:40:50 +01:00
can1357 8e5cc87f00 revert: 535 due to TUI regressions 2026-03-26 19:56:49 +01:00
can1357 1d565bc3f7 Merge review/pr-477-fix 2026-03-26 19:14:52 +01:00
can1357 306ea795dc Merge review/pr-535-fix 2026-03-26 19:14:23 +01:00
can1357 5390239999 Merge review/pr-538-fix 2026-03-26 19:13:08 +01:00
daandden 6ea9504b03 Make temporary model selector keybinding configurable (#539)
Fixes #533
2026-03-26 15:33:26 +01:00
iter 978f56121a Normalize pasted image formats before attach (#543)
Co-authored-by: iter <itertoolz@gmail.com>
2026-03-26 15:28:04 +01:00
can1357 e31f2ef6f0 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.
2026-03-26 14:09:14 +01:00
Vu Anh Nguyen 0d979cc187 fix(coding-agent): preserve new-session approval state 2026-03-26 16:52:30 +07:00
Vu Anh Nguyen 99ce9a0fee Merge origin/main into omp-506 2026-03-26 16:22:21 +07:00
Vu Anh Nguyen 99dabb7c18 fix(ask): keep multiline custom input in prompt gutter 2026-03-26 16:14:52 +07:00
Vu Anh Nguyen 60b6e51b25 fix(coding-agent,tui): address review regressions 2026-03-26 15:01:28 +07:00
Vu Anh Nguyen 7c6df0fdad feat(extension-ui): add dialog options and abort signal support to editor 2026-03-26 01:27:55 +07:00
Leo P afdfe24ea3 cleanup 2026-03-23 08:54:54 -04:00
Leo P e265c20d58 WIP 2026-03-23 08:54:54 -04:00
can1357 7fb18faf4c fix(coding-agent): backported pi-mono changes (1feccfed..b21b42d0)
packages/ai:
- feat: expose provider responseId on AssistantMessage
- feat: lazy-load provider modules for faster startup
- fix: hash foreign Responses API tool call IDs exceeding 64-char limit
- fix: ignore null chunks in openai-completions streams
- fix: keep image tool results inline for Gemini 3+ and Antigravity
- fix: correct Bedrock Claude 4.6 context window to 200k
- fix: support prompt caching for Bedrock application inference profiles
- fix: add OpenRouter reasoning payload format
- fix: ignore placeholder Vertex API keys
- fix: skip AJV validation in restricted runtimes
- fix: Anthropic OAuth client injection and responseId extraction
- fix: Codex incomplete/failed response status handling

packages/agent:
- fix: defer steering until after tool execution completes

packages/tui:
- feat: namespaced keybinding IDs with KeybindingsManager conflict detection
- feat: configurable select list column sizing (#2154 by @markusylisiurunen)
- fix: stream truncateToWidth for large strings
- fix: skip Termux height redraws
- fix: stop evicting unrelated default keybindings
- fix: resolve raw backspace ambiguity on Windows Terminal
- fix: clear stale scrollback on session switch (#2155 by @Perlence)
- fix: remove trailing markdown block spacing (#2152 by @markusylisiurunen)

packages/coding-agent:
- feat: add resizable share sidebar (#2435 by @dmmulroy)
- feat: emit OSC 133 command-executed marker
- feat: reload custom themes from disk watcher
- feat: add --fork session flag
- feat: file mutation queue for serialized writes
- feat: initial message consolidation utility
- fix: keybindings migrated to namespaced IDs
- fix: resolve waitForRetry() race when auto-retry produces tool calls
- fix: handle slash-delimited /model refs
- fix: refresh active model after provider updates
- fix: extended transient error patterns for retry
2026-03-22 18:28:40 +01:00
can1357 2771c2399d feat(autoresearch): introduced autonomous experiment loop with metric-driven optimization
- Added autoresearch extension with autonomous experiment loop supporting init, run, and log experiment tools for metric-driven optimization.
- Added widget placement system enabling extensions to position UI components above or below the editor via ExtensionWidgetOptions.
- Added dashboard controller with interactive overlay for viewing experiment results, metrics, and progress with keyboard navigation.
- Removed auto-correction logic for off-by-one range edits in hashline editor to preserve user intent in patch operations.
- Added state reconstruction utilities to parse autoresearch.jsonl logs and rebuild experiment state across sessions.
- Added comprehensive type definitions and helper utilities for metric parsing, ASI validation, and process management.
2026-03-22 16:50:13 +01:00
can1357 1bf48ca208 fix(modes): corrected setHookWidget to preserve undefined/null values
- Corrected setHookWidget to preserve undefined/null values instead of converting them to string literals.

Fixes #496
2026-03-22 01:39:05 +01:00
luke 47dc03b835 fix: prevent TUI freeze on massive bash output and fix spinner rendering (#500)
- Sync OutputSink.push(): eliminate promise chain per chunk, buffer
  management and onChunk run inline, file writes deferred via queue
- 64KB native read buffer (was 4KB): reduces chunk count ~16x
- chunkThrottleMs in OutputSink: gate onChunk to every 50ms
- BashExecutionComponent streaming throttle: gate + 100-line cap
- Remove requestRender from chunk callbacks: spinner drives renders
- Remove double sanitization in appendOutput (already done by OutputSink)
- Inline SEGMENT_RESET in TUI doRender buffer writes: eliminates O(N)
  string allocations per frame from #applyLineResets
- Cache header Text in BashExecutionComponent (created once, reused)
- Gate sixel mask computation behind protocol + passthrough check
- Fix spinner: #spinnerFrame made optional, interval calls #updateDisplay
- Remove pendingChunks promise chains from bash-executor and bash-interactive
2026-03-21 16:05:42 +01:00
Miroslav Drbal [ApoC] 8b028224e3 feat: auto-reconnect MCP servers on connection loss (#482)
* feat: auto-reconnect MCP servers on connection loss

When an HTTP SSE stream drops (server restart, network interruption),
the transport fires onClose, and the manager proactively reconnects
with retry backoff (500ms, 1s, 2s, 4s). Tools are kept in the registry
during reconnection so they remain selected and available to the agent.

If proactive reconnection fails, stale tools stay registered. When the
agent calls one, the tool bridge detects the retriable connection error
(ECONNREFUSED, ECONNRESET, stale session 404/502/503, etc.), triggers
reconnectServer on the manager, and retries the call once on the fresh
connection. Concurrent reconnect attempts for the same server are deduped.

connectToServer now always installs a default onRequest handler for ping
and roots/list (using getProjectDir()), so all connections -- including
short-lived test/probe ones -- properly respond to server-initiated
requests during initialization.

Post-connection setup (resources, prompts, subscriptions) is extracted
into a shared #loadServerResourcesAndPrompts method used by both initial
connection and reconnection paths.

Add /mcp reconnect <name> command for manual recovery after extended
outages where both proactive and reactive reconnection have failed.

* docs: add changelog entry for MCP auto-reconnect

* fix: address P1 review findings in MCP reconnection

- Save server configs before connection attempt so deferred tools can
  reconnect even when the initial connection timed out (P1-1)
- Make waitForConnection() and getConnectionStatus() aware of in-flight
  reconnections so callers wait instead of failing immediately (P1-2)
- Add epoch counter incremented on disconnectAll() and checked in
  connectAndWireServer() to invalidate stale reconnect attempts that
  outlive a manager reset/reload (P1-3)
- Skip servers with pending reconnections in connectServers() to prevent
  parallel connection attempts for the same server

* fix: deferred tool reconnect and non-blocking transport teardown

- DeferredMCPTool.execute now reconnects when getConnection() fails
  ("MCP server not connected"), not only on network errors from
  callTool. Servers that missed the startup window can now be woken
  by the first tool call against their cached tools. (P1-4)
- #doReconnect fire-and-forgets the old transport close instead of
  awaiting it. HttpTransport.close() sends a DELETE with 30s timeout;
  blocking here delayed the first reconnect attempt by that amount
  on every server restart. (P1-5)

* fix: abort-aware reconnect waits and preserve tool selection on reconnect

- Wrap all reconnect() awaits with withAbort(signal) so user
  cancellation (Esc) interrupts the reconnect backoff loop instead
  of blocking for up to 7.5s. Applies to MCPTool (1 site) and
  DeferredMCPTool (2 sites). (P2-1)
- Remove activateDiscoveredMCPTools call from /mcp reconnect handler.
  refreshMCPTools already preserves the user's prior MCP tool
  selection; the extra activation was silently opting into all
  server tools including ones the user had not enabled. (P2-2)

* fix: rebind MCPTool connection after reconnect, add stdio retriable error

- MCPTool.connection is now mutable; after a successful reconnect retry,
  this.connection is rebound to the fresh connection so subsequent calls
  on the same instance (e.g. batched tool calls) use it instead of
  triggering another reconnect cycle. (P2-3)
- Add "Transport closed" to RETRIABLE_PATTERNS. StdioTransport rejects
  pending requests with this message when the subprocess dies, which
  should trigger the reconnect path just like HTTP transport errors. (P2-4)

---------

Co-authored-by: Miroslav Drbal <miroslav.drbal@gendigital.com>
Co-authored-by: Can Bölük <can1357@users.noreply.github.com>
2026-03-20 23:27:30 +01:00
can1357 22a876bb8f feat(coding-agent): added automatic deduplication of context files by content
- Added automatic deduplication of identical context files by content, keeping the closest (lowest depth) copy when duplicates are discovered.
- Implemented dedupeExactContextFiles() function to filter duplicate context entries in both explicit and discovered file lists.
- Added 3 test cases covering deduplication of explicit context entries, discovered context entries, and preservation of distinct entries.
2026-03-18 23:00:17 +01:00
can1357 20cdf31b9f feat: display session title in terminal tab
fixes #461
2026-03-18 22:46:22 +01:00
can1357 fb76484aa4 fix: route all app-level shortcuts through KeybindingsManager
fixes #468
2026-03-18 22:46:22 +01:00
can1357 afc2276a12 refactor(ai): extracted OpenAI compat logic into dedicated module
- Extracted OpenAI compatibility detection and resolution logic into dedicated `openai-completions-compat` module.
- Refactored `detectCompat()` and `getCompat()` to delegate to new compat module functions with simplified conditional logic.
- Fixed OAuth redirect URI validation to preserve exact configured values without trailing slash normalization.
- Improved session deletion to return boolean status and display error messages in UI instead of silently failing.
- Added `/session delete` command with Delete key support and confirmation dialogs for session management.
2026-03-17 16:07:26 +01:00
can1357 e8eed16c1e chore: reformat 2026-03-17 14:52:06 +01:00
slact 2825c894f5 feat: session deletion (#448)
* feat: session deletion

* better session deletion cleanup error handling

* fix: complete deletion including artifacts
fix: native confirmation for session deletion

* even better native configmation for session picker

* fix(coding-agent): detach active session before deletion

* fix(coding-agent): keep failed session deletes visible

* fix(coding-agent): await session delete command

* fix(coding-agent): surface session artifact cleanup failures

---------

Co-authored-by: can1357 <me@can.ac>
Co-authored-by: Can Bölük <can1357@users.noreply.github.com>
2026-03-17 14:51:21 +01:00
maximhar 571510bdf3 fix: MCP OAuth exact redirect URIs for Slack-style providers (#454)
* Add exact MCP OAuth redirect URI support

* Allow proxied HTTPS loopback MCP redirects

* Fix MCP OAuth busy-port test determinism

* Make MCP OAuth redirect test deterministic

* fix(coding-agent): honor exact loopback redirect ports

* fix(coding-agent): expand env vars in standalone MCP oauth config

---------

Co-authored-by: can1357 <me@can.ac>
2026-03-17 14:49:23 +01:00
daandden b7978c9e0d feat: add undo action and fix hotkeys rendering (#438)
* Fix prompt action undo and hotkeys rendering

* Fix prompt action test typechecks

* Simplify undo and hotkeys PR

* Fix editor formatting
2026-03-16 14:05:21 +01: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
Variable Fate 1957c702a4 fix(move): resolve quoted Windows paths and fresh-session ENOENT (#416) (#418)
Two /move bugs on Windows:
1. Quoted absolute paths (e.g. /move "C:\...") were treated as relative
   because surrounding quotes weren't stripped before path.isAbsolute().
2. /move before any model response threw ENOENT because the session
   .jsonl file hadn't been created on disk yet (lazy-persist).

Changes:
- Extract stripOuterDoubleQuotes() helper in path-utils.ts, use in
  handleMoveCommand() with empty-after-strip guard
- Guard session file rename with existsSync in moveTo(), leaving
  artifact dir rename independently guarded
- Guard #rewriteFile() with hadSessionFile || hasAssistant to preserve
  lazy-persist while still updating header cwd for existing files
- Add comprehensive test suite (13 tests) covering all moveTo() edge
  cases including header-only sessions, deferred persistence, and
  artifact migration
2026-03-15 16:39:30 +01:00
can1357 b5faa7d4be feat(coding-agent): added cursor navigation to message boundaries
- Added `moveCursorToMessageStart()` and `moveCursorToMessageEnd()` prompt actions for cursor navigation to message boundaries.
- Exposed editor methods for cursor movement to message start and end positions in InputController keybindings.
- Implemented message boundary navigation in Editor class with private helper methods for cursor positioning.
- Removed remote compaction settings test suite to align with feature deprecation.
2026-03-14 13:38:29 +01:00
AK 226133712b fix(coding-agent) Restrict automatic session title generation to the resolved smol model only. (#409)
* fix(coding-agent)

* edit: prefer smol title model with current-model fallback
2026-03-14 13:16:28 +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