Commit Graph
967 Commits
Author SHA1 Message Date
can1357 9aada058ee feat(hashline): implemented clipboard operations in hashline engine
- 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.
2026-07-30 07:21:43 +02:00
can1357 4a05d02f01 test(extensions): cover session async job wiring
(cherry picked from commit e79cc9e79a68b53332eb6ca04f2e555e25d1b7e0)
2026-07-30 01:26:50 +02:00
can1357 5486c8fd1d Merge PR #6939: feat(extensions): expose session async job snapshots (@usr-bin-roygbiv) 2026-07-30 01:26:50 +02:00
can1357 f11641d5a8 feat(coding-agent): enabled importing foreign sessions from claude and codex
- 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.
2026-07-30 00:28:40 +02:00
can1357 4bad9b481d Merge PR #6973: fix(coding-agent): share parent local:// root with /tan clone (@roboomp) 2026-07-29 23:08:44 +02:00
roboompandcan1357 bbf3d78c7e fix(coding-agent): keyed tan local root on session-manager id
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)
2026-07-29 23:08:44 +02:00
roboompandcan1357 fb4393ae16 fix(coding-agent): snapshotted tan parent local root
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)
2026-07-29 23:08:43 +02:00
roboompandcan1357 d933cfbe05 fix(coding-agent): shared parent local root with tan clone
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)
2026-07-29 23:08:43 +02:00
can1357 756e872f64 Merge PR #6946: fix(tui): nest usage metrics in grouped reads (@joshrzemien) 2026-07-29 23:08:42 +02:00
joshrzemienandcan1357 daf1557b3d fix(tui): seal mixed read groups before usage
(cherry picked from commit 576b950b80583d8fd028edd08967b537f4eb18f0)
2026-07-29 23:08:42 +02:00
joshrzemienandcan1357 a3e90b3d95 fix(tui): nest usage metrics in read groups
(cherry picked from commit 101268adc632e80bb3f8304b95497ac7bd884131)
2026-07-29 23:08:41 +02:00
can1357 0e7ae1d6ac Merge PR #6908: fix(acp): sync model status when the agent switches models internally (@marton78) 2026-07-29 23:08:27 +02:00
Márton Danóczyandcan1357 80c32cf16a fix(tui): request a render on model_changed, not just cache invalidation
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)
2026-07-29 23:08:26 +02:00
Márton Danóczyandcan1357 bce1ff55a7 feat(session): emit model_changed event on every internal model switch
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)
2026-07-29 23:08:25 +02:00
can1357 2be93e7c84 fix(coding-agent): filter disabled MCP completions
(cherry picked from commit 33886ad9691cf4d330cf1a645e19cae7681c8e94)
2026-07-29 23:07:53 +02:00
can1357 0617ff6e80 Merge PR #6454: feat(coding-agent): autocomplete MCP server names in /mcp subcommands (@Mathews-Tom) 2026-07-29 23:07:52 +02:00
usr-bin-roygbiv 085f870faa feat(extensions): expose session async job snapshots 2026-07-28 23:12:28 +00:00
can1357 cfd335d2b1 fix(tui): restored image attachments on /tree and esc-esc branch
- 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.
2026-07-28 00:57:34 +02:00
alexis@epsilver.xyz 3854c1c3b1 fix(coding-agent): address codex review on vision mode
- 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)
2026-07-27 16:24:02 -04:00
can1357 d16a251777 chore: reorg tests 2026-07-27 16:43:53 +02:00
can1357 d220cfee9b Merge PR #6806: fix(extensions): cancel timed-out handler dialogs (@roboomp) 2026-07-27 15:57:46 +02:00
roboomp 5e6f12b278 fix(extensions): cancelled timed-out handler dialogs
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
2026-07-27 13:28:24 +00:00
roboomp 4bc71bdafc fix(tui): defer large command panels during streaming to stop scrollback dupes
/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
2026-07-27 05:49:42 +00:00
can1357 905fb283df Merge PR #6724: feat(live): add selectable voice setting (@roboomp) 2026-07-27 05:26:35 +02:00
can1357 c2e07a2028 fix(tui): remounted guarded draft editor when ask surface is restored
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.
2026-07-27 04:58:27 +02:00
roboomp 3657219bbe fix(tui): honor clear action in guarded ask draft editing
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
2026-07-26 23:46:46 +00:00
roboomp 2803bf721b fix(tui): show draft cursor while ask proxies its input
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
2026-07-26 23:41:13 +00:00
roboomp 5a1ded4b9e fix(tui): route ask draft input through text pipeline only
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
2026-07-26 23:35:37 +00:00
roboomp 283d9a5d0c fix(tui): preserved prompt input while ask opens
- 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
2026-07-26 23:27:08 +00:00
roboomp bb8c0f12d3 test(live): covered selected voice session boundary
Replaced schema self-comparisons with a controller contract test that selects vale and captures the options used to construct the live session.
2026-07-26 18:52:17 +00:00
roboomp ea60fc1df3 feat(live): added selectable voice setting
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
2026-07-26 18:41:48 +00:00
can1357 60b0968e1f Merge PR #6484: fix(coding-agent): resume agent after /tree ask re-answer (@roboomp) 2026-07-26 15:41:31 +02:00
can1357 0e3f695a56 Merge PR #6701: fix(coding-agent): stop the live advisor runtime when /settings disables it (@paolomazzitti) 2026-07-26 15:41:28 +02:00
Diogo Soares Rodrigues c7c375f5e1 fix(cursor): settle todo cards whose completion outruns the streamed block
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.
2026-07-26 09:29:13 -03:00
Diogo Soares Rodrigues cc210094ef fix(cursor): refuse todo dependency graphs and sanitize failure text
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.
2026-07-26 09:29:13 -03:00
Paolo Mazzitti 81bc0d4368 fix(coding-agent): stop the live advisor runtime when /settings disables it
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.
2026-07-26 12:25:19 +00:00
can1357 de00e7f136 feat(tui): renamed large-paste local refs to paste-N.md
- 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.
2026-07-24 12:25:40 +02:00
can1357 17735c7786 feat: added x-oai-attestation header for ChatGPT-OAuth Codex requests
- 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.
2026-07-24 09:17:00 +02:00
can1357 c1d4e38aa6 feat(coding-agent): added live session delegation with turn-based transcript display
- 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.
2026-07-24 09:16:50 +02:00
can1357 c9c0882724 feat(audio): replaced Chromium browser audio with native audio stack
- 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.
2026-07-24 08:54:16 +02:00
can1357 af9e8546a9 feat: implemented session account selection and pinning via slash command
- 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.
2026-07-24 07:57:55 +02:00
roboomp 7dee729ef7 fix(coding-agent): defer /tree ask re-answer resume until after ui rebuild
Scheduling agent.continue() inside navigateTree started a post-prompt
task before the interactive /tree handler rebuilt its transcript, so a
fast provider's agent_start/turn_start could render against the stale
pre-rebuild UI and then be clobbered by renderInitialMessages.

navigateTree now reports the commit via askReanswerCommitted instead of
resuming, and SelectorController.showTreeSelector calls the new
AgentSession.resumeAfterAskReanswer() only after renderInitialMessages +
reloadTodos, so the resumed turn always renders against the rebuilt
transcript.

Addresses chatgpt-codex-connector review on #6484.
Fixes #6483
2026-07-24 05:27:00 +00:00
roboomp 3cdb93cd01 fix(tui): prewarm tiny-title worker off the first-submit hot path
The first interactive submit fired session.generateTitle() before
startPendingSubmission() painted the optimistic user row, and
tinyTitleClient.generate() spawned the local tiny-title subprocess
synchronously in #ensureWorker() before its first await. With a local
providers.tinyModel configured, subprocess-spawn latency therefore landed
ahead of the first frame, stalling the first prompt.

Paint the pending row before starting titling, and prewarm an idle,
unref'd worker at TUI startup via a no-op ping (no model load) so the
first submit reuses a live subprocess.

Fixes #6462
2026-07-24 03:48:43 +00:00
Mathews-Tom 416a3cf65e fix(coding-agent): scope disabled-only autocomplete to enable/disable; fix changelog section
- collectMcpServerNames takes an includeDisabled flag (default true); the
  /mcp completer now passes false for test/reconnect/reauth/unauth, whose
  handlers (#resolveServerForAuth, reconnectServer) can never resolve a
  disabled-only discovered name (dropped from mcpManager, absent from
  mcpServers). enable/disable keep offering it since #handleSetEnabled
  handles that case for both directions.
- Moved the /mcp autocomplete CHANGELOG entry from the now-released
  ## [17.1.0] section (where an earlier upstream merge relocated it) back
  under ## [Unreleased].
2026-07-24 07:42:30 +05:30
Mathews-Tom d1c828b356 fix(coding-agent): include disabled-discovered servers in /mcp autocomplete, harden config-read failures
- collectMcpServerNames now unions userConfig.disabledServers so a
  third-party-discovered server that was /mcp disable'd (and thus dropped
  from mcpManager.getAllServerNames()) still tab-completes as an /mcp
  enable target.
- collectMcpServerNames accepts an optional preloaded { userConfig,
  projectConfig }; #handleList() passes what it already read instead of
  re-reading both config files a second time.
- /mcp's argument completer catches collectMcpServerNames failures (e.g.
  malformed config JSON) and returns null instead of letting the
  rejection escape un-awaited callers.
2026-07-24 06:24:17 +05:30
Mathews-Tom 21721834b2 chore: merge upstream/main into feat/mcp-name-autocomplete 2026-07-24 06:18:47 +05:30
Mathews-Tom 5bb4282878 feat(coding-agent): autocomplete MCP server names in /mcp subcommands
Adds an exported collectMcpServerNames() helper (used by both /mcp list
and the new completer) and a runtime-bound getArgumentCompletions for
/mcp that resolves server names after enable/disable/test/remove/
reconnect/reauth/unauth, filtered by the typed prefix. Subcommands with
a different argument shape (add, smithery-search, ...) keep returning
null, and subcommand-name completion is unaffected.

Closes #5654.
2026-07-24 06:01:08 +05:30
can1357 366bd6203e Merge PR #6392: feat(coding-agent): add usage-aware model fallback (@eggpeat) 2026-07-24 02:25:35 +02:00
can1357 77669aed54 Merge PR #6395: feat: configure xdev prompt docs (@joeshull) 2026-07-24 02:25:35 +02:00
can1357 0689092866 Merge PR #6445: feat(extensions): expose session service tiers (@atyrode) 2026-07-24 02:24:29 +02:00