- Added `getForceFileSuggestions` and `shouldTriggerFileCompletion` to `AutocompleteProvider` interface.
- Updated `Editor` to invoke file completion logic dynamically when providers support it.
- Corrected log viewer scroll offset calculation to account for viewport height.
- Added comprehensive unit test for log row selection and expansion.
Migrate 203 test files (356 call sites) from fs.rm/fs.rmSync to
removeWithRetries/removeSyncWithRetries to reduce EBUSY test failures
on Windows. removeWithRetries is now exported from @oh-my-pi/pi-utils.
The migration uses a regex-based approach that:
- Replaces fs.rm(path, { recursive, force }) → removeWithRetries(path)
- Replaces fs.rmSync(path, { recursive, force }) → removeSyncWithRetries(path)
- Replaces fs.rm(path) → removeWithRetries(path) (no options)
- Skips fs.rm/fs.rmSync inside template literals (bun --eval scripts)
- Adds imports to existing @oh-my-pi/pi-utils import or creates new one
- Removes unused fs imports where fs.rm was the only fs usage (4 files)
- Replaced O(n) `Array.shift()` calls with O(1) head-index tracking in `RawSseDebugBuffer`.
- Implemented lazy compaction to reclaim the dead-prefix memory only when the leading window grows sufficiently large.
- Added comprehensive tests to verify ordering, dropped count accuracy, and buffer limits under heavy load.
- Adjusted image budget IDs to use a shared 24-bit seed and wrap safely so new budgets no longer collide.
- Added transmit-state reset and changed image output ordering so full paints can replay image data after terminal clears.
- Updated image and protocol tests to match the new wrapped-id behavior and cursor-save/restore-wrapped transmit sequences.
- Centralized catalog and registry handling on `ModelSpec` and `buildModel`, resolving compatibility at model build time.
- Removed runtime compatibility detectors and switched provider request flows to direct `model.compat` reads.
- Added compat fields (`supportsReasoningParams`, `alwaysSendMaxTokens`, `strictResponsesPairing`, `whenThinking`).
- Persisted explicit compatibility overrides through `compatConfig` in discovery and cache merge paths.
- Removed terminal risk mode toggles from config, terminal state collection, and render controllers.
- Dropped snapshot freezing, thaw tracking, and finalized-block replay in transcript rendering.
- Removed clear-on-shrink settings and initialization hooks from selector and interactive mode flows.
- Simplified render scheduling by using requestRender() without mutation flags or stream checkpoints.
- Added reconstructed SSE event emission for OpenAI, Azure, and Anthropic streams.
- Added raw SSE text to debug report bundles, including raw-sse.txt output.
- Included dropped-record metadata in raw SSE text when events were trimmed.
- Updated raw SSE and sse-debug tests for observer-based capture and safety checks.
The repo bans inline imports. Replace per-test `await import("../../src/dap")`
calls with a single top-level `import * as dapModule from "../../src/dap"`
and reuse the namespace for every spy in this file.
Fixes#2020
Prefer directory-capable adapters when selecting a launch adapter for a
resolved directory program. This keeps Go package directories on dlv in
mixed projects that also expose native-debugger root markers such as a
Makefile, instead of selecting gdb/lldb-dap first and rejecting the
directory during validation.
Added a regression test covering a Go module with both go.mod and
Makefile plus local dlv/gdb adapter shims.
Fixes#2020
The debug tool ran validateLaunchProgram before adapter selection and
rejected any directory program with `launch program resolves to a
directory`, while dlv's default `mode=debug` requires a Go package
path (a directory or .go source file). Every Go-module launch failed:
passing the module dir was rejected outright, and passing the compiled
binary failed at dlv with `not a valid go module`.
- Add `acceptsDirectoryProgram` to DapAdapterConfig/DapResolvedAdapter
and flag dlv in dap/defaults.json.
- In DebugTool.execute(launch), resolve the adapter first, then call
validateLaunchProgram with the resolved adapter — the directory
rejection only fires when the adapter does not advertise the flag.
- Add resolveLaunchOverrides in dap/config.ts: for dlv, derive `mode`
from the program shape (directory or .go file → debug; other file
→ exec). Plumbed through DapLaunchSessionOptions.extraLaunchArguments
and spread between adapter.launchDefaults and the hard-coded launch
fields in session.ts.
- Refresh tests: cover the no-dir-support adapter rejection, dlv on a
package directory keeping mode=debug, and dlv on a binary switching
to mode=exec.
Fixes#2020
Used fs.stat to confirm delayed dlv Unix socket creation before connecting so Linux socket-mode adapters do not race Bun.connect. Added a delayed socket adapter regression test covering the launch path.\n\nFixes #2013
- Added `textSizing` terminal capability and `tui.textSizing` setting for Kitty OSC66 scaling.
- Updated OSC66 range and visible-width handling to preserve grapheme slice behavior.
- Updated markdown rendering to apply heading text sizing only when enabled.
- Fixed DECCARA trailing-background fill tracking and DECRPM status 3/4 recognition.
- Added debug menu options for terminal state and protocol checks with new handlers.
- Added terminal diagnostics models and collectors to report geometry, protocol flags, and multiplexer data.
- Added protocol-probe utilities to encode RGB PNGs, generate sample content, and render test panels.
- Added support components for verbatim line rendering and OSC66-scaled text rows.
- Added tests validating image encoding, OSC66 output, and terminal state formatting.
- Added helpers to synthesize RawSseEvent records for inbound, outbound, and malformed Codex WebSocket traffic.
- Passed onSseEvent through websocket transport and stream setup so frames are forwarded to the raw-SSE debug pipeline during streaming.
- Added a stream test that verifies outbound and inbound websocket frames are emitted with SSE-style raw lines for the debug viewer.
Refactor:
- session.ts: extract mapDebugpyMissingModule helper; replace the duplicated
inline check in launch/attach catch blocks. Add jsdoc on DapStartRequestFailure.settled
documenting per-call ownership and how throwPreferredDapStartError consumes it.
- path-utils.ts: replace the no-op keepOpaqueResourceUri branch with an
OPAQUE_RESOURCE_SCHEMES Set so the structure carries the intent. Functionally
equivalent; new opaque schemes become a one-line Set change.
Tests:
- dap-launch-failures: cover the debugpy stderr -> 'pip install debugpy'
rewrite for launch and attach, plus a negative case (non-debugpy adapter
with the substring in stderr is left untouched).
- dap-launch-failures: model the delayed-launch-failure case the new
settled-race in throwPreferredDapStartError defends against. FakeDapClient
gains optional launchErrorDelayMs/attachErrorDelayMs.
- dap-launch-failures (DebugTool): assert adapter:'debugpy' early-throw
surfaces 'python not found in PATH' on both launch and attach when
selectLaunchAdapter/selectAttachAdapter return null, and the unspecified-adapter
path still falls back to the generic 'No debugger adapter' error.
- find.ts: export validateFindPathInputs and pin the new backslash-escape
semantics (\, no longer trips the comma-joined heuristic) plus the
existing brace-expansion and rejection paths.
- patch.ts: cover the post-write verification error message. The user-facing
ToolError must contain the caller-supplied relative path and not the
absolute resolvedPath (which still lives in the structured context for
log correlation).
- split-internal-url-sel: reword two mcp:// test comments that described a
'peeler refuses' guard that doesn't exist; rename the tests to reflect the
actual opaque-scheme rule.
- browser tool's existing-tab re-nav defaults to waitUntil: 'load' (matching
new-tab path); identical acquireTab() calls no longer hang on dev servers
- patch tool error path uses caller-supplied relative path; absolute
resolvedPath stays in structured context only ($HOME no longer leaks to TUI)
- splitInternalUrlSel keeps mcp:// resource URIs opaque even when they end in
':raw' or '/:1-50' (McpProtocolHandler matches by verbatim URI)
- find tool: timeout signal honored by onMatch; partial results sorted by
mtime desc; backslash-escaped commas skipped in path-list validation
- DAP throwPreferredDapStartError waits up to 50ms for the underlying
launch/attach error instead of one microtask
- debug tool surfaces 'python missing' and 'pip install debugpy' diagnostics
separately when adapter: 'debugpy' is requested
- Preserved launch and attach request failures when configurationDone also fails.
- Handled initial stop-outcome watcher rejections for failed launch and attach attempts.
- Rejected directory-valued debug launch programs before adapter selection and documented the debugpy launch shape.
Fixes#1187
Adds an opt-in onSseEvent callback across HTTP-streaming providers (Anthropic, OpenAI Responses/Completions, Azure OpenAI Responses, OpenAI Codex SSE, Google Gemini CLI, GitLab Duo, Kimi, Synthetic) so callers can inspect raw SSE frames without altering parsed output. Provider fetch wrapping only tees response bodies when an observer is wired; standalone packages/ai consumers without onSseEvent are not penalized.
Adds streamIdleTimeoutMs (env: PI_STREAM_IDLE_TIMEOUT_MS, with PI_OPENAI_STREAM_IDLE_TIMEOUT_MS as a backward-compatible alias). Anthropic now enforces a steady-state idle watchdog (default 120s) in addition to the first-event watchdog. OpenAI Responses, Azure Responses, and Codex (SSE + WebSocket) gain a semantic-progress predicate so response.in_progress-style keepalives no longer keep stalled tool calls alive forever.
Adds a coding-agent debug-panel raw SSE viewer backed by a per-session bounded buffer (1000 records / 512KB) that AgentSession populates unconditionally so users can post-hoc inspect a stuck stream from the TUI.
- Added a DebugLogSource that reads dated log files and feeds the viewer from the debug selector.
- Made load-older handling asynchronous to fetch external chunks while preserving cursor and scroll state.
- Updated log viewer tests for the new options, external log sources, and async loading paths.
- Added pid filter toggle and load-older pagination controls to the debug log viewer.
- Introduced ctrl+o and enter shortcuts plus load-older row to page earlier logs while keeping the newest 50 visible.
- Adjusted cursor and selection to ignore non-log rows, allow select-all, and keep expansion anchored when rebuilding.
- Parsed pids from JSON log lines, read full log files for viewing, and covered pid filtering and pagination in tests.
- Added case-insensitive substring filtering with inline query entry and visible count line in the debug log viewer.
- Preserved cursor and selection when filters change and show a no matches placeholder with adjusted scroll bounds.
- Updated filter sanitization and frame layout, removing Kitty-specific help text and aligning status counters.
- Expanded tests to cover filtering, selection anchoring, copy payloads, and session boundary warnings.
- Replaced the log preview with an interactive viewer supporting navigation, selection, expansion, and clipboard copy.
- Added log formatting helpers to wrap multi-line entries and parse timestamps for session boundary detection.
- Covered viewer selection, copy payload sanitization, expanded formatting, and timestamp parsing with new tests.
- Sanitized debug log lines by stripping ANSI/control codes, replacing tabs, and truncating to terminal width.
- Added formatting helper and unit tests covering sanitization, tab handling, and truncation.