Mirror the existing `commands.enableClaudeUser`/`commands.enableClaudeProject`
schema entries so the OpenCode discovery provider exposes the same
user/project toggle surface as Claude. Default remains true to preserve
current behavior.
Fixes#661
The structured SQLite helper interpolates `where=` directly into SQL.
A crafted clause like `where=1=1 LIMIT 1000000 --` could comment out
the helper's bound `LIMIT ? OFFSET ?`, returning the full table in
violation of the documented pagination contract.
Validate where= at the selector boundary and reject SQL comments,
statement terminators, and pagination/attach/pragma keywords. Raw SQL
remains available via ?q=SELECT... for callers that need it.
Fixes#735
resolveMultiSearchPath now reports `exactFilePaths` when every token
resolves to a plain file (no globs, no suffix glob) and accepts a
single resolvable token so partially-missing lists still search the
resolvable subset. grep iterates those exact files individually
instead of collapsing them into a brace-union glob, which preserves
the user's explicit file set even when siblings share a basename.
Also adds a small `[grep] match lines use ':'; context lines use '-'`
banner when context lines are rendered, and splits the per-file
rendering helpers so files with no remaining matches no longer emit
empty headers.
Apply now recomputes per-file replacement counts from the actual apply
pass and compares them against the preview. If totals or per-file
counts drift (file changed between preview and apply, or apply matched
nothing), the tool returns an isError result explaining that the
preview is stale instead of silently claiming success with mismatched
numbers.
- Queued outbound JSON-RPC messages behind a per-client promise queue to serialize writes.
- Added a project-load gate for project-aware LSP operations before diagnostics and reference lookups.
- Retried declaration-only references with a short delay until project metadata is available, then proceeded with normal results.
- Relaxed chunk-mode parameter validation to accept `{path}`-only edits as valid delete operations.
- Updated the invalid-parameters help text to document accepted chunk delete payloads.
- Added a test that verifies a bare `{path}` edit removes the targeted chunk when null values are stripped.
- Added a streaming parser path for apply_patch envelopes that tolerates incomplete patch bodies.
- Updated apply patch preview expansion to return best-effort hunks when the renderer is in partial mode.
- Added a renderer test confirming streaming apply_patch input shows file paths without end-marker parse errors.
Slots a new "apply_patch" variant alongside the existing edit modes
(replace, patch, hashline, chunk, vim). The mode accepts a single input
string containing a Codex *** Begin Patch / *** End Patch envelope,
parses it with a new lenient parser (heredoc-tolerant), and fans each
file-op out to the existing executePatchSingle so LSP writethrough,
plan-mode guards, fs-cache invalidation and diagnostics are shared
with the patch mode.
Exposes both tool shapes from the spec: the JSON function-tool variant
(§1.2, {input: string}) and the OpenAI custom-tool / Lark-grammar
"freeform" variant (§1.1, raw patch string). The edit tool advertises
a Lark grammar via customFormat and a wire name via customWireName;
openai-responses emits it as a grammar-constrained custom tool when a
model opts in with applyPatchToolType: "freeform" in models.json.
custom_tool_call / custom_tool_call_output are plumbed end-to-end
through the shared responses code (emission, streaming, history
replay), and the agent-loop dispatcher matches tool calls by either
name or customWireName so returned calls route correctly.
Also threads preview/diff rendering for apply_patch through the TUI
(tool-execution + edit renderer) so streaming patches show per-file
diffs like the other edit modes.
Default edit mode is unchanged (hashline); opt in via edit.mode or
PI_EDIT_VARIANT=apply_patch.
- Refactor path normalization to combine expandPath and normalizeLocalScheme
- Add validation in utils.ts to reject local:// paths as filesystem paths
- Fix bash-skill-urls regex to handle hyphen-prefixed local:/ patterns
- Add tests for hyphen-prefixed and @local: patterns
- Add negative lookbehind to regex in bash-skill-urls to prevent matching local:/
inside paths like /repo/local:/PLAN.md
- Normalize local scheme before expanding paths in path-utils
- Add test cases for both changes
Expands the regex pattern to match local:/ (single-slash) URLs in addition to local:// (triple-slash), preventing potential Linux path leaks.
- Add regex patterns for single-quoted, double-quoted, and unquoted local:/ URLs
- Add test coverage for all three quote styles
Removed unconditional topic:news coupling in buildRequestBody that scoped
Tavily index to news publications whenever recency was set. Technical queries
with --recency now search the general index filtered by time only.
Tightened SearchParams.recency contract in base.ts: providers MUST interpret
recency as a pure time filter and MUST NOT change topic scope as a side effect.
- Updated todo start handling to set the requested task to in_progress while demoting all other in_progress tasks to pending.
- Added task note rendering in summary output by prefixing each note line with "Note:".
- Set GIT_OPTIONAL_LOCKS to 0 in git execution options and added tests for out-of-order start jumps and note summaries.
- Replaced todo_write's `ops` payload with top-level mutation fields (`phases`, `complete`, `start`, `add_notes`, etc.).
- Removed in-place task content and note updates; moved note writes to append-only `add_notes` calls.
- Matched `add_tasks.phase` by phase ID or name and appended new note text to existing notes.
- Changed execution to drop strict in-progress update sequencing, support `start`, and auto-promote next pending task.
- Updated tests and prompt docs to use direct payloads (`phases`, `complete`, `add_tasks`) instead of `ops`.
- Reworked `idle-iterator` to replace the first-event watchdog wrapper with a shared timeout handle passed through stream iteration.
- Updated Anthropic and OpenAI/Azure response-completion streams to pass the watchdog into `iterateWithIdleTimeout` and rely on unified first-event timeout logic.
- Raised the default first-stream-event timeout from 60 seconds to 100 seconds.
- Added task.simple to settings and schema with default, schema-free, and independent modes.
- Added mode-aware task schema and validation to enforce context/schema rules per simple mode.
- Updated prompts and template rendering to tailor headers and guidance for each simple mode.
- Added simple-mode capabilities and updated TaskTool execution for mode-aware context behavior.
- Added tests for independent rendering and mode-specific rejection of invalid context or schema inputs.
The tests were using the old { sel, op, content } format which is no longer
recognized after the edit tool consolidation. Updated to use the new
{ path: 'file:selector', write/insert } format.
- 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.
- Implemented parsing of `:j`/`:join` and `:j!`/`:join!` ex commands and mapped them to a new `join` command shape with a whitespace-trim flag.
- Added VimEngine handling for `join` to concatenate addressed lines (or the current plus next line by default), optionally normalizing whitespace and reporting line count in the status message.
- Updated vim prompt guidance, changelog notes, and tests to document and verify both normal and `:join!` join behavior.
- Removed live Vim preview state fields and priming/cleanup flow from tool execution and rendering.
- Changed vim insert-mode exit logic to close insert mode unless the final step is paused.
- Updated changelog entries and Vim edit-file prompts to clarify insertion behavior and examples.
- Updated vim tool argument handling to clone args directly and ignore __toolCallId/__cwd metadata.
- Added vim tool-call IDs across EventController, UiHelpers, and ToolExecution for per-call preview mapping.
- Extended Vim type and command parsing with update/write, edit, global, yank, and put handling.
- Added Vim engine support for new commands and motions, including gJ, g*, g#, g_, |, and gu/gU/g~.
- Reworked Vim tool flow to cache per-file engine clones, reuse tool details, and stream inserts in chunks.
- Updated vim.md and changelog to document new vim keys, ex aliases, and fixed :global preview behavior.
- Added parser and renderer tests plus a tmp/vim_test.txt fixture for chunked, cursor, and partial-insert cases.
- Changed chunk edit normalization to prefer write operations, then replace, insert, then delete, with empty write values now treated as clear-content writes.
- Allowed space motions in vim input as `<Space>`, handled them as movement and rendered in error output via token display.
- Adjusted benchmark retry flow to reset files on each retry, reduced per-run call limits, and lowered the default per-turn timeout.
- Added rollback handling for pending INSERT-mode changes whenever a non-final kbd sequence leaves insert mode, and updated the resulting VimInputError with guidance for using `insert` and escaping insert transitions.
- Hardened VimTool execution by resetting stale insert state before processing commands and by only applying empty inserts when Vim remains in INSERT mode.
- Adjusted Vim search handling to mimic Vim magic escaping and taught `o`/`O` numeric prefixes to act like `Go`/`GO` line inserts, then updated the expected error message test.
- Clarified the Vim tool prompt to require `file` and clearly separate key commands from insert text.
- Added updated usage examples and best-practice guidance for whole-file replacement, line edits, search/replace, and undo.
- Documented key/mode constraints, including insert-entry requirements and required `<Esc>` handling between non-final commands.
- Fixed `G`/`gg` motions to distinguish "no count" (go to last/first line) from explicit count.
- Added parsing for literal `\x1b`/`\r` bytes and backslash escape sequences (`\r`, `\e`, `\n`, `\t`).
- Updated `#readCount` to return `hasCount` flag propagated through operator and motion resolution.
- Synced vim buffer fingerprint from disk on reuse to handle LSP writethrough reformats.
- Added `toolStrictMode` support with `all_strict`/`none`/`mixed` options to OpenAI compatibility.
- Fixed OpenAI-completion strict-mode flows by capturing failed HTTP responses and retrying once as non-strict.
- Fixed completion error reporting by surfacing captured status, headers, and JSON `type`/`param`/`code` details.
- Improved strict-schema enforcement with WeakMap memoization and circular-schema detection in sanitization.
- Fixed OpenRouter provider lookup by resolving fallback model IDs for suffix and date variants in registry resolution.
- Refactored benchmark tooling and added async RPC error-window tracking for scheduled run execution.
- Replaced deprecated `await` tool wiring with `poll` in tool exports and built-in tool registry.
- Updated bash and task prompts plus start-result messaging to direct users to the `poll` tool.
- Added effective timeout metadata to Bash tool results and rendered output to show that effective timeout.
- Implemented bounded auto-background wait logic that backgrounds jobs when the timeout window is exhausted.
- Added `VimTool` in `src/tools/vim.ts` with `open`, `kbd`, `insert`, and `pause` actions.
- Implemented `src/vim/{buffer,engine,parser,commands,render,types}.ts` for interactive Vim modes and operators.
- Updated `src/tools/index.ts` to normalize `edit`/`vim` tool selection and skip the inactive edit variant.
- Added `vim` registration in `BUILTIN_TOOLS` and `toolRenderers` for discoverability and output formatting.
- Added streaming renderer snapshots with viewport, caret focus, and diff output for `vim` calls.
- Added `test/tools/vim.test.ts` and `scripts/vim-edit-benchmark.py` coverage for the new editor stack.
- 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.
- Added `vim` as a supported edit mode and resolved mode-specific active tool names.
- Migrated chunk-edit requests from legacy `op`/`content` to `path` plus `write`, `replace`, and `insert`.
- Replaced chunk-edit internals with `put`/`replace`/`delete` operations and ID-based selection.
- Updated chunk prompts/output docs to document ID-based selectors and `write: null` deletions.
- Switched chunk and grep render output to `@`/dash-style anchors and updated file-count behavior for multi-file edits.
- Updated multi-file result rendering with distinct file counting and pending-file progress indicator.
- Refreshed chunk-mode and chunk-tree tests for the new contract and anchor style.
- Tracked `$/progress` begin/end notifications to keep active work-done progress tokens.
- Added `projectLoaded` signaling with timeout fallback while awaiting initial project load completion.
- Blocked cross-file LSP actions until project load finished to avoid premature file-index lookups.
- Handled `window/workDoneProgress/create` requests by acknowledging them for progress-capable servers.
- Extended `LspClient` with `activeProgressTokens`, `projectLoaded`, and `resolveProjectLoaded` for startup sync.
- Updated LSP regression and diagnostics tests to initialize new `LspClient` state fields.
- Added multi-file edit payload support by requiring per-entry `edits` arrays across patch, hashline, replace, and chunk modes.
- Changed edit schemas and validators to move `path` (and `sel`->`path`) and op data into each edit entry.
- Changed edit execution flow to parse `file:selector` paths, run single-entry executors per file, and return grouped per-file results.
- Updated chunk diff rendering and test expectations to emit consistent anchor gutters with spaced pipes and `^` head-line markers.
- Added hierarchical chunk grep output grouped by directory, file, and chunk with aligned chunk anchors.
- Updated chunk rendering to show clipped head/tail context with explicit truncation and expand markers.
- Changed chunk edit and streaming validation to use chunkToolEditSchema-based checks for safe edit detection.
- Enhanced grep rendering to use structured ChunkedGrepMatch data with displayPath and chunk checksum metadata.
- Updated selector-controller session-delete test mocks to include updateEditorBorderColor.
- Extended session deletion expectations to verify updateEditorBorderColor is called.
- Refined a long chunk-mode test string assertion to multiline formatting for readability.
- Updated chunk-mode and core chunk tests to use abbreviated chunk selectors introduced by path truncation.
- Adjusted expected chunk-path and error-path strings for markdown, Rust, and TLA+ fixtures to match the new naming scheme.
- Updated SIXEL sanitization assertions to check for the new "visible columns omitted" truncation message.
- Updated the chunk-mode test assertion regex to accept single-line parse-error locations.
- Removed the required L\d+-L\d+ range from the expected error pattern.
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 language-aware chunking for Svelte, Vue, Astro, and HTML script/style tags using `lang` aliases.
- Added markdown/html markup handling for fenced code and HTML blocks with detected injected languages.
- Added injected-subtree chunk infrastructure and build-time merge logic in `pi-natives/chunk`.
- Added tests for markdown and script-chunking embedded-language behavior in chunk-tree and chunk-mode suites.
- Added SQLite path parsing and candidate validation for `.sqlite`, `.db`, `.db3`, and `.sqlite3` targets in read/write flows.
- Added SQLite read operations for table lists, schema views, row lookups, paginated queries, and raw SELECT mode.
- Added SQLite write operations for insert, update-by-key, and delete-by-key using JSON5 row payloads.
- Updated selector routing to validate SQLite headers and fall back to normal file reads/writes when not databases.
- Secured read mode by enforcing query validation to block destructive SQL execution on SQLite inputs.
- Updated the gemini-image test harness to use CustomToolContext, ModelRegistry, and ReadonlySessionManager types.
- Expanded getHeaderValue in gemini-image tests to handle string-array header values.
- Adjusted the resolve.rs stale-selector test to use a let-else Err(err) binding.
- Clarified the fence_marker doc comment to describe CommonMark triple-marker detection semantics.