Commit Graph

115 Commits

Author SHA1 Message Date
Vu Anh Nguyen 81fd90ecc0 Fix Mermaid markdown rendering on non-image terminals 2026-04-24 06:47:56 +02:00
can1357 23c66791bc fix: stabilize merged review follow-ups 2026-04-18 23:24:00 +02:00
djdembeck f353873b75 refactor: extract local:// URL normalization to shared utility
Extract duplicate normalizeLocalScheme regex pattern into a shared function in path-utils.ts. Updated interactive-mode.ts, approved-plan.ts, agent-session.ts, bash-skill-urls.ts, and plan-mode-guard.ts to use the shared utility. Also fixed error message formatting (removed extra backslashes).
2026-04-18 22:40:07 +02:00
djdembeck 5da806671e fix: prevent local:// URI from creating local: directory on Linux
On Linux, Node's path.normalize() collapses the double slash in
local://PLAN.md to local:/PLAN.md, creating a directory called local:
in the project root instead of routing through the local:// protocol handler.

Defense-in-depth fixes across 5 layers:

1. resolveToCwd() now throws if a path starts with any internal URL
   scheme prefix (local:, agent:, skill:, etc.), preventing all 59
   call sites from treating URIs as relative filesystem paths.

2. resolvePlanPath() now matches on local: prefix (not just local://)
   and normalizes local:/ to local:// before resolution, catching
   all slash variants.

3. Bash URL expansion regex and early-exit checks now also match
   local:/ (single slash), and normalize before resolution.

4. Edit preview/diff functions now gracefully skip internal URL paths
   instead of crashing via the resolveToCwd guard.

5. All startsWith('local://') checks updated to startsWith('local:')
   with normalization in agent-session, interactive-mode, and
   approved-plan modules.

Also adds local: to .gitignore to prevent accidental commits of the
leaked directory.
2026-04-18 22:40:07 +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 d2caf2770c feat: added /rename command to set session titles for status/header/tab display
- Added `/rename <title>` slash command to set explicit session names and update header/tab titles.
- Added `session_name` status segment with hash-derived accent color for session titles.
- Fixed shell execution failure sanitization to preserve all `execResult` fields after redacting stderr.
- Fixed tool execution completion output to pass original `toolResult` text instead of sanitized `content`.
2026-04-13 01:09:38 +02:00
can1357 d2202d0b0b fix(coding-agent): ignore auto titles for session accent 2026-04-13 00:42:24 +02:00
Christoph Gross 09810120ba feat(coding-agent): add /rename command with session accent coloring
- Add /rename <title> slash command to set an explicit session name,
  updating the session header, terminal tab title, and status line
- Add session_name status segment: displays the session name on the
  right side of the status bar with a stable djb2-hash-derived accent
  color unique to each name; shown in all presets when a name is set
- Add setSessionName source tracking ('user' vs 'auto'): auto-generated
  titles are silently ignored once the user has explicitly set a name,
  preventing the async title generation from overwriting a /rename
- Sanitize session names at storage time: strip C0/C1 control characters
  (including ANSI ESC) via static #sanitizeName before storing, blocking
  escape sequence injection into the TUI, terminal title, and session file
- Extend sanitizeStatusText to cover the full C0/C1 range as
  defense-in-depth (superset of the previous \r\n\t-only strip)
- Use stored (sanitized) name for showStatus message and terminal title
  in handleRenameCommand, not the raw user input
- Guard terminal title update in auto-title path via titleSource === 'auto'
  so a user rename is never overwritten by a late-resolving LLM call
- Reset #titleSource in #newSessionSync so each new session starts fresh
- Thread source parameter through AgentSession.setSessionName wrapper;
  extension API and RPC set_session_name treated as 'user' intent

Closes #658
2026-04-11 13:49:01 +02:00
can1357 16ad914da0 feat(coding-agent): added LSP status updates to welcome banner on warmup completion
- Added real-time LSP server status updates in welcome banner when background warmup completes.
- Changed welcome banner status icon from warning to muted pending symbol for improved visual clarity.
- Extracted LSP server conversion logic into dedicated helper methods for better maintainability.
- Added comprehensive test coverage for interactive mode LSP startup welcome banner updates.
2026-04-08 08:58:39 +02:00
can1357 7f88a0c24c refactor: restructured logger.time() API to accept function references with wall-clock markers
- Refactored logger.time() API to accept function references and arguments separately instead of wrapped callbacks.
- Replaced RingBuffer-based timing with wall-clock markers and async span tracking for improved timing accuracy.
- Updated 20+ call sites across executor, kernel, main, and tools modules to use new logger.time() signature.
- Removed parsePath() helper function and inlined path.split() calls in settings module.
- Added test case verifying model selection without auth validation during startup.
2026-04-08 08:47:32 +02:00
can1357 593add00fb feat(lsp): implemented async LSP server discovery with real-time startup events
- Added asynchronous LSP server discovery and warmup at startup via `discoverStartupLspServers()` function.
- Added LSP startup event channel (`lsp:startup`) for real-time server status notifications during warmup.
- Added `LspStartupServerInfo` type to track LSP server status (connecting, ready, error) throughout lifecycle.
- Changed LSP server warmup from blocking synchronous operation to non-blocking background task.
- Refactored interactive mode to subscribe to LSP startup events and display real-time server status updates.
2026-04-08 07:15:11 +02:00
can1357 a21a542afd refactor(prompt-templates): migrated prompt utilities to pi-utils package
- Extracted prompt rendering and formatting utilities from coding-agent to centralized pi-utils package with new API surface (prompt.render, prompt.format, prompt.registerHelper).
- Migrated parseFrontmatter utility from coding-agent to pi-utils package; updated 8 files to import from @oh-my-pi/pi-utils.
- Removed 170-line prompt-format.ts module and consolidated 192 lines of Handlebars helper registrations into pi-utils prompt module.
- Updated 60+ files across coding-agent and typescript-edit-benchmark to use new prompt.render() and prompt.format() API from pi-utils.
- Simplified prompt-templates.ts by delegating core functionality to pi-utils while retaining custom helper registrations (jtdToTypeScript, jsonStringify, etc.).
2026-04-08 05:47:35 +02:00
can1357 e6d36e2d8a fix(coding-agent): corrected plan review previews to re-append at chat tail on refresh
- Fixed plan review previews to re-append at the chat tail on refresh, keeping them adjacent to the active selector instead of updating off-screen.
- Added comprehensive test coverage for plan review rendering behavior across multiple refresh cycles.
2026-04-07 22:38:49 +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 9b92461fa2 Merge pull request #610 from loftiskg/loftiskg/fix-plan-mode-thinking-level
fix(plan-mode): propagate thinking level when entering/exiting plan mode
2026-04-05 01:19:45 +02:00
can1357 5f93ef47b8 fix: skip provider session reset when plan-mode model matches current model 2026-04-05 01:16:08 +02:00
Can Bölük 70a3707915 Merge pull request #612 from kamafozilov/fix/plan-refine-double-enter
fix(coding-agent): submit plan refinement directly instead of requiring double enter
2026-04-05 01:10:56 +02:00
Patrik Sundberg 9ac969f0a0 fix(coding-agent): invalidate transcript cache when session file shrinks
Compaction and tool-output pruning can rewrite the session JSONL in
place, shrinking the file. When stat.size < bytesRead, the cache is
now invalidated and the file is re-read from scratch, preventing the
observer from getting stuck on a stale transcript.
2026-04-04 15:57:23 +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
kamafozilov 17bfadcb5f fix(coding-agent): submit plan refinement directly instead of requiring double enter
When selecting 'Refine plan' during plan review, the refinement text was
placed into the editor via setText() but not submitted. The user had to
press Enter a second time to actually send the message.

After session.abort() at the start of handleExitPlanModeTool, the main
loop cycles back to getUserInput() which sets onInputCallback before the
hook selector and input can resolve. By the time the user finishes typing
the refinement, onInputCallback is available. Submit the refinement
directly through onInputCallback + startPendingSubmission, matching the
pattern already used by handlePlanModeCommand for initial prompts.

Falls back to editor.setText() if onInputCallback is unexpectedly absent.

Fixes #597
2026-04-04 03:42:31 +05:00
Kevin Loftis 06b8e17ddc fix(plan-mode): propagate thinking level when entering/exiting plan mode
When entering plan mode, the thinking level configured on the plan role
(e.g., 'anthropic/claude-sonnet-4-5:xhigh') was discarded because
#resolveRoleModel() called resolveModelRoleValue() but only returned
.model, dropping the thinking level.

This is the same class of bug that was fixed in cycleRoleModels (which
correctly preserves and applies thinking level from role configs).
#applyPlanModeModel was the remaining unfixed call site.

Changes:
- Refactor #resolveRoleModel to #resolveRoleModelFull returning the
  full ResolvedModelRoleValue instead of just Model
- Add resolveRoleModelWithThinking() public method exposing the full
  resolution result
- Add optional thinkingLevel param to setModelTemporary() for atomic
  model+thinking switches (eliminates two-step set-then-apply pattern)
- Bundle model+thinking into paired state objects in InteractiveMode
  (#planModePreviousModelState, #pendingModelSwitch) — eliminates
  4 parallel fields that could desync
- Simplify #applyPlanModeModel, flushPendingModelSwitch, #exitPlanMode
  to single setModelTemporary calls
- Collapse cycleRoleModels two-step into single setModelTemporary call
- Add 6 tests for resolveRoleModelWithThinking
2026-04-03 10:46:46 -07: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 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
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 8e5cc87f00 revert: 535 due to TUI regressions 2026-03-26 19:56:49 +01:00
can1357 306ea795dc Merge review/pr-535-fix 2026-03-26 19:14:23 +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
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 138e7e1d91 fix(interactive-mode): corrected mic cursor width measurement to prevent TUI overflow
- Fixed STT Alt+H mic cursor rendering to measure the actual microphone glyph width, preventing one-column TUI overflow crashes when the active symbol preset uses a wide icon (#484).
- Extracted mic cursor styling into dedicated method to consolidate color and width calculation logic.

Fixes #484
2026-03-20 23:40:48 +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
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
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
maximhar 952db9fd93 feat: add ephemeral /btw side-question panel (#399)
* feat: add ephemeral /btw side-question panel

* fix: preserve /btw live context and payload hooks

* fix: send /btw question through session pipeline
2026-03-14 10:42:26 +01:00
can1357 ffa208adcf feat(modes): added /copy subcommands for flexible code and command extraction
- Added `/copy` command subcommands (code, all, cmd, last) for flexible code block and command copying.
- Added support for copying last executed bash or python command via `/copy cmd` subcommand.
- Refactored handleCopyCommand() to route subcommands with dedicated private methods for each copy operation.
- Added regex-based code block extraction from markdown with fallback warnings for missing blocks.
2026-03-11 03:08:51 +01:00
lederniermagicien 486fd4c753 refactor(theme): replace CoreFoundation FFI with OSC 11 for machine-agnostic dark/light detection (#347)
* refactor(theme): replace CoreFoundation FFI + Mode 2031 with OSC 11 for dark/light detection

Replace the 415-line Rust CoreFoundation FFI module and Mode 2031-only
detection with OSC 11 background color queries — the machine-agnostic
method used by Neovim, fish, bat, and terminal-colorsaurus.

Detection stack:
- OSC 11 query + DA1 sentinel at startup (works over SSH, mobile clients)
- Mode 2031 subscribe: re-queries OSC 11 with 100ms debounce (Neovim
  convention) instead of trusting binary dark/light value directly
- 2s OSC 11 poll for terminals without Mode 2031 (Warp, Alacritty,
  WezTerm, iTerm2); self-disables once Mode 2031 fires
- COLORFGBG env var fallback (free, no I/O)
- macOS defaults read fallback (Zellij edge case)

Deleted:
- crates/pi-natives/src/appearance.rs (414 lines of unsafe FFI)
- packages/natives/src/appearance/ (66 lines of TS bindings)
- macOS appearance observer and SIGWINCH coupling in theme.ts

Net: -424 lines. Rust crate lighter, detection works over SSH.

* fix(theme): ignore bogus zellij osc11 dark reading

* fix(theme): scope macOS fallback to broken terminal paths

* fix(tui): swallow DA1 sentinels for OSC 11 probes

---------

Co-authored-by: can1357 <me@can.ac>
2026-03-11 00:58:17 +01:00
can1357 1a5bbc3e51 feat(coding-agent): added details field to TodoItem for storing implementation specifics
- Added optional `details` field to TodoItem type for storing implementation specifics, file paths, and edge cases.
- Enhanced todo item display to show multi-line details with automatic indentation in interactive and reminder modes.
- Updated eager-todo system prompt to enforce separation of short task content (5-10 words) from detailed implementation information.
- Extended TodoWriteTool to support creating and updating tasks with details field via add_task and update operations.
- Added comprehensive test coverage for details field handling across todo operations (replace, add_task, update).
2026-03-11 00:56:54 +01:00
can1357 f256376e90 feat(coding-agent): added cancellation support for pending user submissions
- Introduced SubmittedUserInput type to track submission state including cancelled and started flags. Added startPendingSubmission, cancelPendingSubmission, markPendingSubmissionStarted, and finishPendingSubmission methods to manage the lifecycle of user input submissions. Enhanced escape key handling to prioritize canceling pending optimistic submissions before aborting active sessions.
2026-03-10 06:25:38 +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
ravshansbox c4715a918a Fix delayed display of submitted user messages (#312) 2026-03-10 02:42:46 +01:00
can1357 aa18e3f26d feat: add hash prompt actions
Fixes #283
2026-03-09 15:38:39 +01:00
can1357 8e3e0ebf9e feat: introduced Effort enum and ThinkingConfig for model-aware reasoning
- Introduced Effort enum and ThinkingConfig metadata for per-model reasoning capabilities with min/max effort levels.
- Migrated thinking level API from string-based ThinkingLevel to structured Effort enum across agent and AI packages.
- Added model-thinking module with effort mapping, policy application, and semantic versioning utilities for provider-specific thinking modes.
- Removed supportsXhigh() function and replaced effort clamping with model-aware validation using ThinkingConfig metadata.
- Expanded models.json with thinking configuration objects for 50+ models including Claude, Gemini, and OpenAI variants.
- Added Python analysis scripts for edit tool usage patterns and tool invocation stream processing.
2026-03-06 12:35:01 +01:00
can1357 fd5c1e9115 fix(coding-agent): removed unnecessary awaits from non-promise function calls
- Removed await from stream() calls that return async iterables directly.
- Removed await from synchronous utility functions like findApiKey(), resolvePythonRuntime(), and getToolPath().
- Removed await from prerenderMermaid() and findExaKey() calls that don't require awaiting.
2026-03-04 02:09:12 +01:00