- Added tracking of the last successful non-error yield tool call when a yield execution ends.
- Cleared the tracked yield ID and skipped post-turn maintenance when appropriate, including when the last assistant message was a successful yield.
- Standardized unchanged-result error messages in atom and replace edit modes.
- 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).
- Parallelized `collectSessionsFromFiles` via strided workers sized by file count and CPU parallelism, reducing large-list latency.
- Read only a fixed 1024-byte prefix per session file in `collectSessionFromFile`, avoiding full-file scans.
- Added partial-prefix fallbacks to extract session title and first user message when JSONL parsing is incomplete.
- Updated SessionManager.listAll to retrieve session files with Bun.Glob.scan instead of scanSync.
- Awaited the async glob scan results via Array.fromAsync before collecting session metadata.
- Added minimizer API fields (`MinimizerResult.text`, `settingsHash`) and shell options for minimized output behavior.
- Changed bash execution to print minimized text output and append artifact footers only after minimized output is saved.
- Added UTF-8-safe shell streaming with `on_chunk` callback routing and `replace()` output sink updates.
- Added core filter enhancements for git, cargo, go, and listing/python outputs to produce compact summaries.
- Added RTK command filters and fixtures to strip noise, truncate output, and normalize success fallbacks.
- Added command-marker metadata and lifecycle in process execution, including completion markers and exit-code writes.
- Refactored minimization to support `MarkedCommands` mode, token-based detection, and marker-aware stripping.
- Added `onMinimizedSave` and `saveBashOriginalArtifact` to persist full bash-original output artifacts.
- Expanded public exports and marker hooks so external command launch metadata can be controlled by consumers.
- 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.
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).
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.
When persist writes race with test-level tempDir cleanup (e.g. in agent-session-auto-compaction-queue.test.ts), fs.rename can fail with ENOENT during the atomic swap inside #writeEntriesAtomically. The error is already routed through #persistChain so #persistError surfaces it to future persist calls, but the awaited rejection returned by #queuePersistTask was bubbling out of the fire-and-forget callers (#rewriteFile path and the incremental writer path) and Bun's test runner reported it as an 'Unhandled error between tests' even though the test itself passed. Attach a silent .catch on both void paths so the rejection is considered handled at the callsite while the persistChain retains the error state.
- Replaced Snowflake session IDs with UUIDv7 for created, forked, branched, and resumed sessions.
- Derived cache session IDs from OpenAI request options and passed them into Responses client creation.
- Used derived session IDs for OpenAI `session_id`/`x-client-request-id` headers and `prompt_cache_key`; omitted headers when retention was none.
- Added tests for UUIDv7 session creation/branching and OpenAI cache-affinity default, override, and disabled-header modes.
- Documented UUIDv7 session handling and OpenAI cache-routing fixes in package Unreleased changelogs.
The #emitSessionEvent refactoring changed the order: #emit was called before
#emitExtensionEvent, but for non-message_update events this introduced
microtask timing issues that broke auto-compaction and handoff tests.
Fix: keep the original order (extension first, then emit) for non-message_update
events. Only message_update events use fire-and-forget extension queueing with
emit-first ordering.
The #emitSessionEvent refactoring introduced a microtask gap between session
event emission and the compaction check in #handleAgentEvent. This allowed
#waitForPostPromptRecovery to run before #postPromptTasksPromise was created,
causing deferred handoff tasks to be missed.
Fix: track the handler's agent_end work as a post-prompt task synchronously
before the await, ensuring #waitForPostPromptRecovery always blocks until the
compaction check completes.
- Removed the standalone vim tool and normalized built-in/requested tooling to edit.
- Updated session and SDK tool activation to dedupe lowercase names and track edit state via the edit key.
- Added vim-mode argument detection and delegated edit rendering/execution into Vim handlers under edit.
- Updated Vim step handling to auto-reorder numeric-positioned commands, including cc/C/S/s/i/I/A cases.
- Renamed prompt/changelog text and test expectations to reflect edit-only tool naming and usage.
- Removed `SearchDb` APIs and `searchDb` fields, dropping db-backed state from native and agent sessions.
- Replaced crate export `fff` with `fd`, moving fuzzy-find bindings into `fd.rs`.
- Removed `SearchDb`/picker fast-path logic from `glob` and `grep`, simplifying scan flow and dropping db args.
- Removed `SearchDb`/`getSearchDb` wiring from extension, tool, and task context constructors across coding-agent.
- Added over-indentation validation warnings in chunk-edit normalization for suspicious `~` body line formatting.
- Removed `bytes`, `fff-grep`, `fff-search`, and `blake3` deps, adding `grep-searcher = "0.1"`.
- Updated `AgentSession` and `createAgentSession` to resolve active edit tool names via `resolveEditToolName`.
- Filtered inactive edit variants with `filterInactiveEditToolName` so tool listings expose the active edit mode.
- Normalized requested edit-capable tool names with `normalizeToolNamesForEditMode` during activation and startup.
- Synced edit-tool mode after model changes so the active tool swaps between `edit` and `vim` automatically.
- Enabled per-file partial updates by threading `onUpdate` through `EditTool` and `executePerFile`.
- Updated `ToolExecutionComponent` to render multi-file edit `perFileResult` entries as separate boxes with pending state.
fixed retained-kernel restart and owner cleanup edge cases during recovery and disposal
tracked async user_python hooks during disposal-sensitive execution paths and hardened startup warmup tracking
strengthened cleanup and kernel lifecycle regressions to remove deadlocks, false positives, and timing flakes
scoped retained-kernel ownership to agent sessions and cleaned it up on session disposal
cleaned up warmed python owners on session startup failure and rejected new direct and tool-based python starts during disposal, including async hook, preflight, and warmup races
- Added a guard in AgentSession to detect prior user messages and skip eager todo injection after the initial user turn.
- Updated session tests to assert that only the first user message triggers eager todo enforcement while follow-up prompts do not.
- Documented the behavior change in the package changelog under Unreleased.
- 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
- 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.
- Document session name getter/setter methods in extensions.md
- Add stub methods to ExtensionProxy that throw if called before init
- Add delegating implementations to ExtensionProxyInit
- Wire up getSessionName and setSessionName in extension runtime
- Add method signatures to ExtensionContext interface and type
- Add getSessionName to session manager API
- Add getSessionName and setSessionName to all mode contexts:
- ACP agent
- Extension UI controller (also updates terminal title)
- Print mode
- RPC mode
- Detect 401/403 from Copilot and rewrite to actionable re-login message,
invalidating stale credentials in the session layer (Fix 1)
- Add 9 unit tests for loginGitHubCopilot device-code flow (Fix 2)
- Centralize duplicated "opencode/1.3.15" User-Agent into a single
exported COPILOT_USER_AGENT / OPENCODE_HEADERS constant (Fix 3)
- Batch model enablement to 5-at-a-time to avoid rate limits (Fix 4)
- Migrated hash API calls from Bun.hash.xxHash64() to Bun.hash() across TypeScript packages for simplified hash generation.
- Consolidated mermaid cache failure tracking by replacing separate failed Set with null values in cache Map.
- Refactored schema-based child extraction in Rust by introducing promotion_fields tracking and schema_wrapper_child() helper function.
- Updated TypeScript configuration files with reformatted arrays and added compiler options for consistency.
- Added `/force` slash command and `ToolChoiceQueue` system for managing tool-choice directives with lifecycle callbacks and requeue semantics.
- Added `setForcedToolChoice()`, `peekQueueInvoker()`, `buildToolChoice()`, `steer()`, and `getToolChoiceQueue()` methods to AgentSession and ToolSession APIs.
- Refactored tool-choice override mechanism from simple override to queue-based system with generator directives, lifecycle callbacks, and requeue preservation.
- Removed `PendingActionStore` class and replaced with `ToolChoiceQueue`; updated `ResolveTool` and custom tool loader to use queue invokers.
- Fixed tool-choice queue cleanup on agent loop abort and requeue semantics to preserve callbacks across abort cycles.
- Added `onAssistantMessageEvent` callback to Agent API for inspecting and aborting assistant streaming events.
- Added `setAssistantMessageEventInterceptor()` method to dynamically update assistant message event handlers.
- Converted `checkAutoGeneratedFileContent()` from async to synchronous for improved streaming edit abort detection performance.
- Implemented LRU caching in auto-generated file detection with early path-based checks to prevent unnecessary edits.
- Refactored streaming edit pre-caching to use assistant message event interception for real-time abort capability.
- Extracted `peekFile()` utility for efficient file prefix reading with pooled buffer reuse strategy.
- Renamed ChunkRegion::Inner variant to Body across Rust and TypeScript for clearer semantics.
- Renamed chunk edit tool parameter from target to sel and made op required instead of optional.
- Removed region aliases (prologue, epilogue, inner) and simplified region validation to accept only head, body, tail.
- Replaced db.exec() calls with db.run() for SQL execution in auth-storage, agent-storage, and history-storage.
- Enhanced chunk edit documentation with comprehensive examples, indentation rules, and CRC refresh guidance.
- Improved chunk statement merging logic to consolidate leaf statements into parent function bodies by default.
- 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.
- 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.).
- 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.
- Eager todo enforcement now skips prompts ending with question marks or exclamation marks, treating them as queries or commands rather than statements requiring task planning.
- Added 2 test cases validating that eager todo enforcement is skipped for prompts ending with question and exclamation marks.
- Removed native binding validation function that checked required exports at load time.
- Enhanced native module loader to check XDG_DATA_HOME environment variable before ~/.omp/natives fallback.
- Removed dependency on @oh-my-pi/pi-utils from native module loader by inlining helper functions.
- Migrated child process termination from waitForChildProcess utility to killTree native binding.
- Added MacOSPowerAssertion native module to prevent idle-sleep on macOS during active sessions.
- Integrated power assertion lifecycle management into coding-agent session with automatic start/stop.
- Implemented N-API bindings for macOS IOKit power assertions with RAII cleanup and cross-platform no-op fallback.
- Reformatted indentation from spaces to tabs across Rust chunk module for consistency.
- Migrated react-edit-benchmark package to typescript-edit-benchmark with pi-mono source repository.
- Added InProcessClient implementation to eliminate subprocess spawning overhead in benchmark runs.
- Extended benchmark configuration with chunk edit variant, retry limits, and conversation dump support.
- Refactored runner.ts to support both RPC and in-process client modes with improved error telemetry.
- Cleaned up 129 benchmark report files from react-edit-benchmark/runs directory.