MCPManager.disconnectAll clears connections without notifying the session's
prompt-command consumer, so removed or disabled prompt servers left stale
/server:prompt commands after /reload-plugins and /mcp reload.
Clear the session MCP prompt-command registry immediately after disconnect and
before asynchronous rediscovery. Newly loaded prompts repopulate it through
the existing manager callback. Extend the reload regression coverage.
Fixes#7189
reloadServers() rediscovered MCP with no options, so loadAllMCPConfigs
defaulted enableProjectConfig to true — /reload-plugins (and /mcp reload)
could start project .mcp.json servers a user opted out of.
Derive discovery filters (enableProjectConfig, filterExa, filterBrowser)
from ctx.settings before reconnecting, matching startup discovery. Added a
regression test asserting the opt-out is forwarded.
Fixes#7189
/reload-plugins documents MCP in its reload scope but the TUI handler only
reset skill/command/capability caches and never reconnected MCP servers or
refreshed the session MCP tool registry, so .mcp.json edits stayed inactive
until process restart.
Route the TUI reload pipeline through a shared reloadTuiPluginState() helper
that also runs the disconnect/rediscover/refreshMCPTools path used by
/mcp reload, exposed as MCPCommandController.reloadServers().
Fixes#7189
Moved automatic title eligibility and persistence into AgentSession so editor and CLI bootstrap submissions share one path.
Added a PTY regression probe covering the positional-message launch flow.
Fixes#7166
- Add the `app.live.toggle` keybinding defaulted to `Ctrl+L` to start or stop live voice mode.
- Remap the default display-reset action (`app.display.reset`) from `Ctrl+L` to `Alt+L`.
- Update the live visualizer to listen for stop keys so the toggle chord terminates active sessions.
- Implemented clipboard register management, parsing, and execution rules for CUT, COPY, and PASTE operations in the hashline engine.
- Added session-persistent clipboard state and integration across agent session execution, diff previews, and streaming tools.
- Added comprehensive validation, error messages, recovery handling, and test coverage for clipboard and block operations.
- Implemented session stores and metadata converters to import Claude and Codex sessions into OMP.
- Added `--from-claude` and `--from-codex` CLI flags and `/resume` command arguments for foreign session resolution.
- Updated session selector components and controllers to support listing and picking external agent sessions.
- Added comprehensive unit tests and documentation covering foreign session import functionality.
Snapshot this.ctx.sessionManager.getSessionId() for the tan clone's local://
mapping instead of session.sessionId. The two diverge after /fresh or a
provider session override, and the Windows short-root fallback keys
%TEMP%/omp-local/<id> off the session-manager id used by the parent's
large-paste writes and '/data/workspaces/can1357__oh-my-pi__6971/.omp-session/2026-07-29T06-08-45-283Z_019fac7d-5ee3-7000-a7aa-16fe9394fdc9/local' reads, so the mismatched id left attachments
unreachable.
Diverge the mocked session id from the manager id in the regression test so
it pins the session-manager id.
Fixes#6971
(cherry picked from commit 1efcd22326d76fdb8b50c0977a836c892e80ab76)
Capture the parent artifacts directory and session ID when /tan dispatches
instead of resolving them through the mutable interactive SessionManager.
This keeps background tan '/data/workspaces/can1357__oh-my-pi__6971/.omp-session/2026-07-29T06-08-45-283Z_019fac7d-5ee3-7000-a7aa-16fe9394fdc9/local' reads pinned to the dispatching transcript
after the user switches or resumes another session.
Extend the regression test to switch the mocked interactive session before
the background job starts and assert the original local mapping is retained.
Fixes#6971
(cherry picked from commit e05db428eabd5087e4b2b4a462f47927c0628e72)
TanCommandController.start nests the tan clone at
<parent-artifacts>/Tan-<id>.jsonl, so the clone's session manager derived
its own artifacts dir and hence local root <parent-artifacts>/Tan-<id>/local.
Its sdk.createAgentSession call omitted localProtocolOptions, unlike the
task-subagent path which inherits the parent's mapping, so parent-session
'/data/workspaces/can1357__oh-my-pi__6971/.omp-session/2026-07-29T06-08-45-283Z_019fac7d-5ee3-7000-a7aa-16fe9394fdc9/local' attachments (pasted files, generated references) were unreadable.
Thread the parent session manager's localProtocolOptions into the tan clone
so local:// resolves against <parent-artifacts>/local.
Fixes#6971
(cherry picked from commit 1ded46e182fc24f9f57d8e9a907aaad58f790783)
handleEvent has no blanket pre-render (removed for issue #4353), so
each handler must explicitly schedule one when it changes something
visible -- every other statusLine.invalidate() call site in this file
pairs it with ui.requestRender(). The new model_changed handler only
invalidated the cache, so an internal model switch (prewalk hand-off,
retry-fallback) while the TUI was otherwise idle left the status line
showing the stale model until an unrelated event happened to render.
Flagged by @chatgpt-codex-connector on PR #6908.
(cherry picked from commit f565e3a4956bda467b6679a3c3f1e48379395a78)
AgentSession#setModelWithProviderSessionReset is the single choke point
every model mutation runs through (explicit /model, prewalk hand-offs,
retry-fallback, model cycling). It previously changed agent.state.model
silently — no session event told subscribers (ACP, RPC, TUI) that the
active model moved.
Emit a new model_changed AgentSessionEvent from that choke point
whenever the model actually changes, and wire it into every consumer
that must exhaustively handle AgentSessionEvent: the TUI event
controller (invalidates the status line, same as thinking_level_changed)
and the RPC client's forwarded-event allowlist.
(cherry picked from commit f76325de2c7821dd7046ddb67546577c3575a263)
- branch() and navigateTree() now return the selected user message's image
parts (selectedImages/editorImages) alongside the text, extracted in marker
order by #extractUserMessageImages.
- CustomEditor.setDraft() replaces the composer draft with text plus its
pending images, so restored [Image #N] markers resolve on resubmit instead
of degrading to literal text.
- Wired all six restore call sites (selector-controller, extension-ui-controller)
through setDraft; updated rpc-subagents mocks for the new branch shape.
- Added offline regression tests for branch/navigateTree image restitution,
multi-image marker order, and text-only prompts.
- Reconcile inspect_image centrally from setModelWithProviderSessionReset
so retry-fallback model changes (turn-recovery.ts) that bypass
syncAfterModelChange cannot leave a stale tool set
- Apply persisted inspect_image.mode changes immediately from the
settings selector via a new handleSettingChange branch
- Refresh the read tool's advertised description during reconciliation,
before applyActiveToolsByName rebuilds the prompt, instead of only
lazily on the next image read
- Fix the flat (quoted-dotted) enabled->mode migration to write the
nested target form the resolver actually reads
- Add committed regression tests: tri-state x capability matrix,
override precedence, and enabled->mode migration (nested, flat, and
explicit-mode-wins)
Forwarded confirmation dialog options in the interactive TUI and scoped extension UI dialogs to each handler watchdog signal.
Added regressions for direct confirmation cancellation and fail-closed tool-call timeout cleanup.
Fixes#6805
/usage, /session, /advisor status, /jobs, /changelog, /context, and
/memory view mounted their finalized panel immediately via ctx.present()
instead of ctx.presentCommandOutput(), the streaming-deferral path added in
#5427 for /tools and /mcp. When invoked mid-turn, the panel landed above a
still-growing live block and the append-only scrollback contract recommitted
it lower down, so it appeared twice in native scrollback.
Route all six large command panels through presentCommandOutput() so they
defer until agent_end, matching /tools and /mcp.
Fixes#6767
A failed async submission can restore the draft while a nested ask prompt
(note/custom answer) is open, re-blocking the input guard; restoreAskDialog
mounted only the ask component, routing guarded input to an unmounted
editor. Restore now mirrors the initial presentation and remounts the
draft editor whenever the guard exists.
handleDraftEdit routed everything through the base editor, which reserves Ctrl+C for the parent and returns without touching the buffer, so the configured app.clear never ran and the guard's 'finish or clear the prompt' hint had no working clear key when Ctrl+C reached the guard.
handleDraftEdit now dispatches the app.clear action explicitly (onClear, falling back to clearing its own text), which empties the draft and lifts the guard without swapping the editor slot.
Fixes#6737
The draft editor renders an insertion cursor only when its focused flag is set, but ask holds TUI focus, so the preserved draft had no visible caret while it required finishing or clearing.
The input guard now mirrors its blocked state onto the draft editor each ask render (editor is the next sibling in the same container), showing the cursor while it owns input and dropping it once the draft clears.
Fixes#6737
Forwarding raw keys through CustomEditor.handleInput enabled its app-slot shortcuts (Agent Hub, model selector, ...) while an ask dialog was open over a draft; those clear editorContainer and orphan the pending ask promise.
handleDraftEdit bypasses the shortcut interception so only text editing, cursor movement, and submission reach the buffer.
Fixes#6737
- Kept a populated editor visible beneath an asynchronously opened Ask form.
- Routed input to the draft until it is submitted or cleared, then activated Ask controls.
- Added regression coverage for the focus handoff.
Fixes#6737
Added the supported realtime voice catalog to settings and passed the selected value into each new live session.
Covered the voice list, default, UI options, and persisted override.
Fixes#6566
When Cursor packs toolCallStarted and toolCallCompleted into one HTTP/2
chunk, the bridge tool_execution_end (synchronous callback, fired
mid-parse) reaches the interactive controller before the streamed
toolcall_start (queued on AssistantMessageEventStream, delivered a
microtask later). The controller found no pendingTools entry, dropped
the completion, and the card created afterwards animated forever.
Two halves, each necessary:
- Hold an early todo completion in #orphanedToolCompletions and replay
it when the streamed block creates its component.
- Guard card creation from cumulative message_update frames with the
turn-scoped #toolTimelineComponents map. Without this, the update
after the replay re-lists the same toolCall block, finds pendingTools
empty again, and spawns a second, permanently pending card. This is
also why emitting a synthetic tool_execution_start from the bridge
(previous attempt, reverted) could not work.
Both maps are cleared together at the existing transcript-anchor reset
sites. The normal ordering (start first) is covered by a control test.
Two review findings on the native todo sync.
- TodoItem.dependencies is a graph the local model cannot store: rows
are keyed by content, carry no id, and hold no edges. An imported
dependent row files as plain pending and nextActionableTask then
offers work the server considers blocked. Refuse snapshots with an
edge pointing at an unfinished row; edges whose blockers already
finished constrain nothing and still mirror.
- The todo failure warning interpolated the provider error verbatim.
Collapse and truncate it at the render boundary.
Also documents two known, unfixed defects: an async cursorOnToolResult
transformer resolving after the buffer drain, and the todo card
lifecycle race. Emitting a synthetic tool_execution_start for the
latter was measured and rejected -- the completion deletes the entry it
creates, so the late streamed block adds a second card.
Disabling the Advisor from /settings persisted the setting but left the
live Advisor runtime running until the session restarted.
SelectorController.handleSettingChange had no case for "advisor.enabled",
unlike other session-managed toggles (autoCompact, steeringMode, ...), so
the change never reached session.setAdvisorEnabled — the same call /advisor
off already uses to stop the runtime immediately.
- Large-paste menu now saves pastes as local://paste-N.md instead of
local://attachment-N, giving the artifact a markdown extension and a
clearer name.
- Add `CodexAttestationProvider` hook and `getCodexAttestationHeader` resolver that gates on ChatGPT-OAuth credentials.
- Integrate attestation into WebSocket transport, SSE event stream, and OpenAI compaction requests.
- Wire `setCodexAttestationProvider(generateCodexAttestation)` in model-registry init for OAuth sessions.
- Added `LIVE_DELEGATION_MESSAGE_TYPE` constant and delegation message handling for voice sessions.
- Implemented turn-based transcript coalescing with user and assistant turn counters.
- Added transcript display row with normalized rendering in the live visualizer.
- Refactored controller to send delegation messages via `sendCustomMessage` with configurable frame styling.
- Removed microphone permission error reporting from silence detection logic.
- Switched from `miniaudio` to `maudio` Rust crate and added `AudioCapture` and `AudioPlayback` native classes.
- Removed browser-side audio infrastructure including Web Audio API, audio worklet processor, and WebRTC runtime.
- Migrated STT recorder and transcriber modules to use native `AudioCapture` with callback-based streaming.
- Replaced streaming audio player with native `AudioPlayback` that writes PCM directly without TypeScript intermediaries.
- Removed ffmpeg, wav, and platform-specific playback commands from the audio toolchain.
- Add `pinSessionOAuthAccount` storage method and active account flag to the auth storage API.
- Introduce session account selector component, controller logic, and interactive mode delegation.
- Implement the `/session pin` builtin slash command with text listing and account pinning capabilities.
- Add unit tests covering session account selection, component navigation, and command handling.