- Replaced inline chat view with a dedicated fullscreen `AgentTranscriptViewer` overlay.
- Introduced `ChatTranscriptBuilder` to enable non-incremental, full-history transcript rendering.
- Implemented robust state management for thinking blocks, message history, and transcript disposal.
- Added support for auto-reloading local session files and sync for remote transcript data.
- Replace individual component invalidation with a full display reset when toggling thinking block visibility.
- Ensure stale snapshots of thinking blocks in terminal scrollback are retired correctly.
- Implemented `AdvisorTranscriptRecorder` to persist advisor sessions to append-only `__advisor.jsonl` files.
- Integrated transcript recording into agent sessions with managed flushing, atomic file switching, and synthetic turn attribution.
- Restricted advisor-kind agents by excluding them from rosters, history protocols, messaging, and interactive agent commands.
- Reserved the `__advisor` filename stem across the output manager and task registry to prevent task ID collisions.
- Included advisor syncBacklog and immuneTurns in the default-resetting configuration for protocol hosts.
- Updated the lazy startup tests to verify that these settings are reset to defaults rather than inheriting user-defined values when a protocol host initiates.
Added the ACP mobile speech.models.list method so voice settings can fetch static local STT, TTS, and voice catalog options without invoking setup/download paths.
Fixes#3011
- Added a `mode` property to `CompactOptions` to allow fine-grained control over compaction strategies.
- Implemented `soft`, `remote`, and `snapcompact` submode overrides for the `/compact` command.
- Integrated `parseCompactArgs` to enable robust subcommand routing and validation, including focus instruction rejection for specific modes.
- Established a `CompactMode` registry to manage compaction strategies and verify remote availability.
- Validated every stage of a pipeline against `simple_command_is_safe` instead of only the first stage to prevent improper segmentation of compound shell constructs.
- Guarded segment re-execution by verifying that each `Display`-reconstructed command parses back to the expected pipeline shape.
- Configured segmented-chain execution to fall back to an unsegmented, whole-command path whenever a reconstructed segment diverges from the original AST.
- Resolved a syntax error during command execution by preventing `Display` from stripping terminators from compound commands like `while` and `for` loops.
- Removed qrcode and qrcode-view subcommands from the collab command.
- Updated showCollabLink to always trigger QR code display.
- Refactored internal verb logic to simplify session sharing flow.
Drop the runtime qrcode + @types/qrcode packages in favor of a zero-dependency
byte-mode QR encoder (versions 1-40, EC L/M/Q/H, auto version + mask selection)
with a half-block ANSI renderer. Cross-validated byte-for-byte against the qrcode
reference library and decoded end-to-end with jsQR. Adds encoder regression tests.
- Added collab.webUrl and rendered browser links as web UI wrappers whose fragments carry relay links.
- Added one-shot /collab qrcode and /collab qrcode-view commands with terminal QR rendering.
- Updated coding-agent and collab-web parsers to prefer parseable wrapper fragments while preserving legacy links.
- Added regression tests and changelog entries for split-host collab links and QR commands.
- Migrated the `pi` AI dialect from legacy XML-style elements to a compact, token-frugal sigil-delimited format using `§` for calls, `""` for body fences, and `¤` for thinking.
- Implemented robust parsing for the new format, including support for incremental streaming of tool arguments and automatic escalation of body fences to prevent content collisions.
- Updated documentation, settings configurations, and test suites across the `ai` and `coding-agent` packages to ensure consistency with the new dialect rules.
- Standardized moderation category terminology in `stats` to improve clarity in reporting metrics.
getOpenRouterRouteSuffix() used strict parseThinkingLevel(), which never
recognizes the max->xhigh alias, so openrouter/<id>:max was consumed as an
OpenRouter route suffix and cloned into a literal <id>:max model id with the
reasoning level dropped. This hit every exact-selector funnel
(parseModelPattern -> resolveCliModel/--model, resolveModelRoleValue/modelRoles
+ model picker, SDK default role) for the dominant aggregator provider.
Exclude max via parseThinkingSuffix(.., MAX_THINKING_SUFFIX_OPTIONS) so the
pattern falls through to the existing max-aware selector split. Literal :max
ids stay safe (none exist under openrouter; nanogpt literals win via exact
lookup before this path). Adds an openrouter/<id>:max regression test.
The dispose() disconnect added by this PR awaited mcpManager.disconnectAll()
unbounded. An owned manager holding an HTTP/SSE server whose session-
termination DELETE hangs would block dispose for the full MCP request timeout
(30s default, unbounded when OMP_MCP_TIMEOUT_MS=0), stalling /exit and
print-mode shutdown on a broken remote endpoint.
Wrap the disconnect in withTimeout(..., 3_000) — mirroring the bounded
async-job teardown two lines above and the startup bound from issue #2100.
stdio close (the subprocess reap this PR targets) completes well within the
bound; a slow transport close is left to finish detached.
Adds a regression test driving the real MCPManager.disconnectAll() with a
stalled transport close.
The quoted-path fix entry was appended under the already-released [16.0.6] section (creating a duplicate ### Fixed heading); released sections are immutable per repo convention. Move it to [Unreleased] and normalize the bullet.
Resolved Amazon Bedrock application inference profile ARNs through the provider-specific model resolver and routed Bedrock requests to the ARN region.
Fixes#3004
Threading printThoughts only into runPrintMode is too late when
hideThinkingBlock is set (settings or --hide-thinking): the session is
built with hideThinkingSummary=true, so the provider omits reasoning
summaries and --print-thoughts prints nothing. Override hideThinkingBlock
to false for single-shot print mode before session creation, gated on
print mode; an explicit --hide-thinking still wins.
After plan approval the executor delivers the plan-mode-reference exactly
once and sets `#planReferenceSent = true`. Both compaction paths — `compact()`
and `#runAutoCompaction()` — replace the conversation history that carried
that reference but never cleared the flag, so `#buildPlanReferenceMessage()`
short-circuited to null on every subsequent turn and the executor permanently
lost the plan it was working on (exactly the long-session failure reported).
Clear `#planReferenceSent` right after `replaceMessages()` in both paths so the
next turn re-reads the plan from disk and re-injects it. The reset is a no-op
for ordinary sessions: the default plan path (PLAN.md in session-local scratch)
has no file on disk, so `#buildPlanReferenceMessage()` still returns null there.
Adds a deterministic regression test (short-circuited compaction, mock stream)
that fails before this change and passes after, plus a guard proving normal
sessions get no spurious plan injection.
Fixes#1246
- Refined the advisor's scope to prioritize concrete technical risks and user advocacy while discouraging process-related critiques.
- Explicitly barred the advisor from intervening on user intent, process questions, or issues already handled by developer tooling.
- Updated `advise` tool documentation to clarify its purpose in preventing wasteful or incorrect work.
A login entry can store credentials under a different provider id via
storeCredentialsAs (e.g. openai-codex-device => openai-codex). Filtering
only on provider.id left such alias logins visible after disabling the
underlying model provider. Surface storeCredentialsAs on OAuthProviderInfo
and hide a login entry when either its own id or its storeCredentialsAs
target is in disabledProviders.
Addresses Codex review on #2906.
The vendored markit engine kept `mupdf` external, but a single-file
`bun --compile` binary has no node_modules to resolve it from, so the
standalone binary aborted at startup with `Cannot find package 'mupdf'`
— the otherwise-lazy import is resolved eagerly at boot. Bundle mupdf and
embed its WASM blob (scripts/embed-mupdf-wasm.ts, reset after the build);
npm and source installs still load mupdf from node_modules.
Import mupdf lazily inside the PDF converter so the bundled markit chunk's
init stays synchronous: mupdf's top-level await otherwise made the chunk
init async and bun's compiled bundler failed to await it through the
barrel, exposing the converters before their module-level const tables
initialized (undefined EXTENSIONS). Also keeps the ~10MB wasm off non-PDF
document conversions.
- Replaced insufficient file size checks with comprehensive validation for ZIP header and length limits.
- Added explicit rejection for archives that would exceed ZIP32 entry counts, name lengths, or total offsets.
- Added validation for central directory size to prevent overflow before generating the EOCD record.
- Implemented structured markdown role headings and tool result merging to improve conversation readability.
- Added explicit `<out>` tags for tool result wrapping and enhanced rendering for thinking blocks.
- Refactored authentication snapshot validation to use manual structural checks instead of schema dependencies.
- Fixed instability in settings overlay scrolling and addressed assistant message splitting issues.