- Removed export leakage by demoting many helper and const symbols to module-local scope.
- Renamed underscore-prefixed internals and cache fields, then updated related references and `satisfies never` checks.
- Deleted obsolete logic branches and helpers, including harmony-stream interruption flow and unused benchmark runtime helpers.
- Updated Biome config and manifests by broadening lint coverage and removing an unused `@napi-rs/cli` dev dependency.
- Adjusted tests and utilities to use renamed test helpers and remove redundant private test-only helpers/locals.
Adds a new `rpc-ui` mode that extends the existing headless RPC mode with
interactive tool support (ask tool, extension UI dialogs, etc.).
In plain `rpc` mode the session has `hasUI=false` and no UI context is
wired, so interactive tools are disabled. `rpc-ui` mode sets `hasUI=true`
and wires a single shared `RpcExtensionUIContext` instance into both the
tool context store and the extension runner. Both consumers share the same
`pendingExtensionRequests` map and output closure, so `extension_ui_response`
messages received on stdin are routed to the correct waiting promise
regardless of which code path (tool or extension) created the request.
Changes:
- `args.ts`: add `rpc-ui` to the `Mode` union and the parse guard
- `launch.ts`: expose `rpc-ui` in the OCLIF flag definition and help text
- `main.ts`: propagate `rpc-ui` through all RPC-mode guard conditions and
pass `setToolUIContext` to `runRpcMode` when the mode is `rpc-ui`
- `rpc-mode.ts`: accept optional `setToolUIContext` callback; create one
shared `RpcExtensionUIContext` instance and pass it to both the tool
context store and the extension runner
- Replaced Python execution with a local `python -u runner.py` subprocess and NDJSON stdin/stdout framing.
- Removed shared-gateway architecture, including coordinator lifecycle APIs, `useSharedGateway` wiring, and `jupyter` CLI/actions.
- Simplified setup checks to a plain Python 3 availability probe and removed automatic dependency-install fallbacks.
- Updated kernel cancellation and display processing to use status frames, SIGINT/SIGTERM escalation, and normalized output coercion.
- Added `python-runner` integration and display tests while deleting legacy websocket and kernel lifecycle test suites.
- Added new frustration and revised behavior metrics across stats types, parser mappings, and UI charts.
- Reworked session sync to fan out parsing across a capped worker pool with SyncOptions progress callbacks.
- Added worker-based parse messaging and throttled TTY progress rendering in the stats sync command.
- Updated behavior scoring to strip structured content, ignore noisy prompts, and fix profanity boundary regressions.
- Expanded user message schema and migrations, then repaired assistant model/provider links during sync backfill.
- Updated worker-import guidance in AGENTS.md and recorded sync-progress/metrics updates in package changelogs.
- Removed the read CLI argument and tool schema field so read requests no longer accept custom timeouts.
- Updated URL read handling to stop forwarding timeout values and execute URL reads without a timeout parameter.
- Standardized URL read fetching to a fixed 30-second timeout and dropped timeout metadata from URL call rendering.
- Added configurable `ScanDetail` modes across native fd/glob/ast flows and exposed `size` on `GlobMatch`/types.
- Added parallel grep processing with optional workers, buffered entry visits, and direct small-file reads.
- Changed `filesWithMatches` to stop at first match per file and report `totalMatches` as matching-file count.
- Fixed grep count/offset limits, timeout checks, and cancel handling by enforcing offsets in aggregate results.
- Updated PI_GREP_WORKERS and auto-absorb/read-summarize behavior/docs, including `read.summarize.prose` and pure-insert defaults.
- Added tests for filesWithMatches counts, cancel cases, and count-mode behavior, plus updated grep benchmark imports.
- Registered a new `read` command in the CLI command registry so `omp read` can be invoked.
- Implemented `runReadCommand` to execute the read tool, wrap it with meta notices, and print text or image-result blocks.
- Added a `read` command class with required path input, optional timeout flag, and usage examples.
- Added a `list`/`clean` positional action and examples to the grievances command, along with new `--id`, `--tool`, and `--all` flags for cleaning.
- Implemented `cleanGrievances` to delete grievances by id, tool, or all entries, enforce mutually exclusive selectors, and emit JSON counts when requested.
- Updated grievance DB access to use writable handles for clean operations and reset autoincrement sequence when removing all rows.
The --list-models handler in runRootCommand short-circuited to
listModels() right after Settings.init and modelRegistry.refresh,
exiting before extension loading ran in createAgentSession. As a
result, providers contributed via pi.registerProvider() (from -e
paths or settings.extensions) never appeared in the listing.
Extract a runListModelsCommand entry point in cli/list-models.ts
that loads extensions (CLI -e paths and settings.extensions) into
the supplied ModelRegistry, mirroring sdk.ts's handoff of pending
provider registrations, and then delegates to listModels. The load
is intentionally narrow: no agent loop, no MCP servers, no custom
tools.
Fixes#905
- Added a unified eval framework with parser grammar, backend interfaces, and JS/Python execution result types.
- Added eval tool docs and updated prompts for fenced cells, `eval.py`/`eval.js`, and fallback behavior.
- Replaced the built-in `python` tool with `eval` across registry, rendering, interactive modes, and tool settings.
- Migrated Python execution runtime from `src/ipy` to `src/eval/py`, renamed state fields, and removed legacy introspection.
- Refactored browser tooling from in-process VM helpers to worker-managed tab supervisors and protocol transport.
- Added eval parser fallback and JS tool-bridge tests, updated imports, and removed obsolete python-mode suites.
isPathInDirectory only normalized strings via path.resolve, so on Windows
when Bun is installed via Scoop (~/.bun is a junction to scoop\persist\
Oven-sh.Bun\.bun) the omp path from $which and the bunBinDir from
'bun pm bin -g' compared as different directories, causing 'omp update'
to take the binary-swap path instead of 'bun install -g' and fail with
EPERM unlinking omp.exe.bak (Bun has the running exe open). Layer
fs.realpathSync.native on top of the existing lexical guard, resolving
the file's parent dir so non-existent target paths still fall through.
Fixes#845
- Removed `pi-natives` chunk language classifier modules and all core chunk subsystems (kind, state, render, edit, resolve).
- Removed chunk-mode CLI/read/edit entrypoints, including `read` command and chunk mode registration/prompt tooling.
- Removed chunk selectors from `read` and `grep` tools, switching behavior to raw/L-range handling.
- Fixed poll wait parsing to keep defaulting to `30s` when the provided value is empty.
- Canonicalized file and CLI defaults from `read` to `open` across tool registration and prompts.
- Added `resolveToolAlias()` and applied alias-normalized tool selection so legacy `read` maps to `open`.
- Updated runtime, UI, and export layers to treat `open` as first-class while preserving `read` compatibility.
- Renamed read prompt docs to `open.md`/`open-chunk.md` and refreshed system guidance to recommend `open`.
- Updated tool-related tests and expectations from `read` to `open` (including test fixtures and aliases).
- Added configurable minimizer settings to native and coding-agent APIs, including shellMinimizer options.
- Added minimizer execution plumbing through shell config, session-key generation, and buffered output capture.
- Added command identity detection and dispatching by program/subcommand with safe fallback to passthrough output.
- Added filter suites for git, docker, go, bun, cloud, and system commands to strip ANSI and compact noisy output.
- Added unit tests for detection and minimizer behavior across command support, failures, and passthrough paths.
- Standardized missing-file read errors and now return `File not found: <path>` for absent edit targets.
- Centralized AI provider, usage, and OAuth helpers into shared modules to remove duplicated logic.
- Migrated OAuth/API-key login flows to shared factory helpers and removed inline prompt/token-exchange code.
- Reused shared tools and formatter utilities for discovery, stream tails, LSP batching, and source formatting.
- Consolidated repeated test helpers and fixtures into shared modules, replacing inline helper duplicates.
- Added canonical model equivalence types, cache helpers, and registry APIs for provider variant lookup.
- Changed model resolution to apply canonical ID overrides/excludes with provider order before fallback matching.
- Added canonical and provider model views in list-models and selector UI with canonical sorting/persistence.
- Updated role/model persistence to store selectors while runtime now resolves concrete canonical-backed provider models.
- Added support for embedded URL selectors with `:raw` and `:L#-L#` line range syntax in read command.
- Implemented `parseReadUrlTarget()` function to parse and validate URL read targets with line range support.
- Updated read CLI to delegate URL inputs through read tool pipeline instead of treating as local file paths.
- Added comprehensive test coverage for URL selector parsing and CLI URL delegation.
- Refactored URL handling in read tool to use structured `ParsedReadUrlTarget` object.
- Extracted image metadata detection and MIME type utilities to @oh-my-pi/pi-utils package for shared use across projects.
- Consolidated image-input.ts and mime.ts modules into image-loading.ts with simplified API removing redundant metadata parameters.
- Updated all import paths across coding-agent to use readImageMetadata from @oh-my-pi/pi-utils instead of local utilities.
- Added peek-file utility module to @oh-my-pi/pi-utils with buffer pooling for efficient file header reading.
- Added Auto QA tool (`report_tool_issue`) for automated tracking of unexpected tool behavior with environment variable and setting support.
- Added Python tool environment warmup on first execution to ensure prelude helpers are available before use.
- Fixed Python prelude introspection to respect execution timeout and signal options, preventing hangs.
- Refactored prelude documentation caching and loading logic into reusable helper functions with test environment awareness.
- Enhanced kernel introspection with optional timeout and signal parameters for better execution control.
- Added system prompt guidance to encourage agents to report tool issues via Auto QA when available.
- Replaced all Bun.which() calls with $which() utility from @oh-my-pi/pi-utils across 22 files.
- Removed findBashOnPath() wrapper function from procmgr.ts, consolidating binary path resolution.
- Updated AGENTS.md documentation to reflect new $which() API usage pattern.
- Centralized binary detection logic through shared utility, reducing code duplication.
- Reorganized edit tool from `patch/` to `edit/` directory with dedicated mode subdirectories (chunk, patch, hashline, replace).
- Replaced line-scoped edit operations with substring-based `find` parameter and added `replace_body` operation for preserving signatures.
- Added chunk focus modes (Expanded, Collapsed, Container) and focused rendering to display only touched chunks and adjacent siblings.
- Implemented notebook (ipynb) language support with virtual source conversion and cell-based chunk parsing.
- Enhanced chunk edit error messages with consistent checksum mismatch reporting and improved chunk selector auto-resolution.
- Extracted edit mode implementations into separate modules with improved helper functions and LSP integration for diagnostics.
- 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.
- Consolidated fetch tool into read tool with URL reading capability and caching support.
- Removed standalone fetch tool from all agent prompts and CLI documentation.
- Extended read tool schema with timeout and raw parameters for URL fetch control.
- Added URL caching mechanism to prevent redundant network requests during read operations.
- Refactored fetch module from class-based tool to standalone executeReadUrl function.
- Updated read tool documentation to describe multi-purpose capabilities including web pages, GitHub, Stack Overflow, Wikipedia, Reddit, NPM, arXiv, blogs, and feeds.
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
- classifyInstallTarget skips known npm dist-tags (latest, next, beta,
etc.) and semver-like strings before checking marketplace names
- updateMarketplace throws if fetched catalog name differs from the
registered name, preventing stale data on upstream renames
- parseMarketplaceCatalog validates variant-specific required fields
(github.repo, url.url, git-subdir.url+path, npm.package) at parse
time instead of deferring to install-time crashes
Check installed_plugins.json directly instead of relying on the
marketplace being registered. Handles the case where a marketplace
entry is removed but its plugins are still installed.
- handleUninstall now classifies targets and routes marketplace
specs to MarketplaceManager.uninstallPlugin()
- handleList shows both npm and marketplace plugins grouped by type
Route marketplace install targets (name@marketplace) to
MarketplaceManager.installPlugin() instead of npm install.
classifyInstallTarget() was implemented but never called from
the install handler.
- Added retry mechanism for benchmark tasks with separate system and retry prompt templates to improve edit success rates.
- Introduced autocorrect tracking metrics including autocorrect-free success rate and edit autocorrect counts in task and benchmark summaries.
- Refactored prompt building into modular functions (buildBenchmarkSystemPrompt, buildInitialBenchmarkPrompt, buildRetryBenchmarkPrompt) with BenchmarkPromptDelivery type for distinguishing initial and follow-up messages.
- Added session management with cache-keyed provider session IDs using xxHash64 and centralized RPC argument building via prepareBenchmarkSessionSetup.
- Added ACP (Agent Client Protocol) mode for headless agent operation via --mode acp flag.
- Integrated Agent Client Protocol SDK with session management, streaming communication, and event mapping.
- Added ensureOnDisk() method to SessionManager for immediate session persistence without requiring assistant messages.
- Changed session persistence to use atomic file rewrite for unflushed sessions.
- Implemented AcpAgent class with session management, prompt handling, MCP server configuration, and event streaming.
- 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.
* feat(utils): full XDG Base Directory support for all path helpers
Implement XDG-first resolution across all omp path helpers, extend the
migration command to cover every data/state/cache location, and fix
five data-safety issues found in review.
dirs.ts:
- Add getXdgCachePath() helper ($XDG_CACHE_HOME/omp/<subpath>)
- Add isDefaultAgentDir() helper: XDG lookup is only valid when the
resolved agentDir equals the process default (~/.omp/agent); custom
profiles set via PI_CODING_AGENT_DIR or setAgentDir() are never
silently redirected to the global XDG database
- Update 15 functions to XDG-first resolution:
data: getPluginsDir, getRemoteDir, getRemoteHostDir, getPythonEnvDir,
getWorktreeBaseDir
state: getReportsDir, getSshControlDir, getCrashLogPath, getDebugLogPath
cache: getPuppeteerDir, getGpuCachePath, getNativesDir
- Guard XDG lookup with isDefaultAgentDir(agentDir ?? getAgentDir()) in
all 9 agent-subdir helpers so that callers passing the global default
agentDir still resolve to the migrated XDG location, while callers
passing a non-default agentDir or running under a custom profile via
setAgentDir() bypass XDG entirely
- Plugin-derived helpers delegate to getPluginsDir() and follow XDG
resolution automatically
migrate-xdg.ts:
- Add getXdgCacheHome() helper
- Extend MigrationItem.category to include 'cache'
- Add 12 new migration entries: reports, plugins, remote, ssh-control,
remote-host, python-env, puppeteer, wt, gpu_cache.json, natives,
omp-crash.log, omp-debug.log
- Refuse to run when PI_CODING_AGENT_DIR points to a non-default
profile: migration only makes sense for the default ~/.omp/agent tree
- copyDirectory returns skipped source paths (target existed, non-force)
- verifyIntegrity: remove size-mismatch early-return that masked stale
targets as successful copies
- executeMigration: delete only entries that were actually copied;
use rmdir on source dir so it is removed only when empty, preserving
any skipped files for a subsequent --force run
- executeMigration: rename partial target to <target>.bak on integrity
failure instead of deleting; preserves pre-existing user data while
preventing getXdgDataPath from treating the partial tree as
authoritative; source remains intact for re-copy on next run
test isolation:
- Set XDG_DATA_HOME/XDG_STATE_HOME to non-existent paths in
memories-runtime.test.ts beforeEach/afterEach to prevent
getXdgDataPath/getXdgStatePath from resolving to real user data
* fix(utils,coding-agent): fix XDG support issues
dirs.ts:
- Refactor path resolution into DirResolver class. XDG base dirs are
resolved once at construction from env vars (Linux only, no
existsSync). setAgentDir creates a fresh instance, naturally
invalidating all cached paths and recomputing isDefaultProfile.
- getRootSubdir/agentSubdir accept optional XdgCategory parameter;
when set, the XDG base replaces the config root. Every accessor
is a one-liner delegate.
- Non-Linux platforms: XDG fields are null, zero overhead. No
filesystem probing, no string comparisons on the hot path.
- Config-only subdirs (themes, tools, commands, prompts, modules)
have no XDG category — they stay under the config root.
- Remove `import { env } from 'bun'`, use process.env consistently.
- Restore JSDoc comments to document actual defaults (~/.omp/...).
migrate-xdg.ts:
- Gate migrateToXdg on Linux — exits with clear error on other
platforms.
- Fix data loss bug: verifyIntegrity now accepts a Set of skipped
paths and skips verification for files that were intentionally not
copied (pre-existing at target in non-force mode).
- Fix nested directory source deletion: recursive removeSourceEntries
walks the tree and only deletes files not in the skipped set.
- Remove dead _sourcePath variable and unused force parameter from
verifyIntegrity.
- Remove `import { env } from 'bun'`, use process.env consistently.
logger.ts:
- Revert JSDoc to document ~/.omp/logs/ as default.
oauth.ts:
- Replace direct getAgentSubdir call with getTestAuthPath().
CHANGELOG.md:
- Merge duplicate section headers under [Unreleased].
- Add missing blank line before [13.11.1].
---------
Co-authored-by: can1357 <me@can.ac>
- Changed abort() method signature to return Promise<void> instead of void, making it async-compatible.
- Added bash executor fallback to one-shot shell execution when persistent sessions fail to respond to cancellation.
- Fixed bash execution timeout handling to prevent subsequent commands from hanging after hard timeouts.
- Extracted abort token management into ShellAbortState for thread-safe cancellation handling across shell sessions.
- Added SessionManager.close() method for proper cleanup of persistent writers and session resources.
- Removed provider parameter from web search tool schema; provider selection now handled internally.
- Removed deprecated no_fallback option from search parameters; fallback behavior is now automatic.
- Renamed SearchParams type to SearchToolParams and introduced SearchQueryParams for CLI queries.
- Updated executeSearch() to accept SearchQueryParams with optional provider selection.
- Added Tavily web search provider with API key authentication and credential discovery from environment or database.
- Integrated Tavily as highest-priority search provider in fallback chain with structured response mapping and error handling.
- Added Tavily OAuth login flow in CLI and auth-storage with manual API key input and validation.
- Added comprehensive test suite for Tavily provider covering registration, response mapping, error handling, and credential validation.
Fixes#313
- 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.