Commit Graph

749 Commits

Author SHA1 Message Date
can1357 e7955ddf3c feat(coding-agent): introduced sequential message queueing and commands
- Implemented `/queue` command and `->`/`=>` shorthands to support deferred, sequential message processing.
- Added a robust parsing utility to handle various list-based queue inputs and automate yield management.
- Integrated visual decorations and state tracking to provide real-time feedback on queueing status.
- Enabled non-cursor line text decoration in the TUI to support dynamic queue header rendering and list numbering.
2026-07-11 22:07:51 +02:00
can1357 54bafa1cce feat(coding-agent): implemented interactive fallback chain configuration
- Implemented model-specific keys and provider wildcards for `retry.fallbackChains` with updated resolution logic.
- Added interactive fallback chain management in the model roles UI, including support for reordering and editing.
- Improved fallback chain specificity rules and added comprehensive validation with startup warnings.
- Fixed mouse interaction alignment and hover state coordinate mapping in the roles view.
2026-07-11 22:03:35 +02:00
can1357 7957d0b88c Merge remote-tracking branch 'origin/farm/3b0815b6/fix-btw-gpt-luna-esc' 2026-07-11 20:38:37 +02:00
can1357 6c292b97c3 refactor(coding-agent): preserved completed and abandoned tasks in session
- Updated task synchronization to include all todo phases regardless of completion status.
- Removed logic that filtered out completed or abandoned tasks during session synchronization.
2026-07-11 20:35:43 +02:00
roboomp 2c161d2a8f fix(coding-agent): preserved btw codex websocket routing
- Preserved the session websocket preference for ephemeral /btw side-channel turns so Codex websocket-only models do not fall back to SSE.
- Prioritized active /btw and /omfg panels in Esc handling before loop, maintenance, and main-turn interrupts.
- Added regression coverage for side-channel websocket options and /btw Escape priority.

Fixes #5213
2026-07-11 17:31:37 +00:00
can1357 408a92d91a feat(coding-agent): enabled asynchronous background task execution
- Enabled granular task execution by allowing batches to interleave blocking items with non-blocking async background spawns.
- Updated task orchestration to support simultaneous inline result collection and persistent background job tracking.
- Improved agent visibility in the job tool by reporting running subagents even when not explicitly linked to a backing job ID.
- Enhanced terminal state handling to prevent premature tool block closures while async background operations remain active.
2026-07-11 16:17:03 +02:00
can1357 ab7b776f9a feat(coding-agent): implemented custom role management in model hub
- Implemented custom role creation within the Model Hub, including a virtual row for direct initiation and name stripping.
- Added quick-switch cycle editing functionality with persistent ordering and live preview of role membership.
- Optimized sidebar scope navigation to mute empty entries and improve keyboard focus stability during search.
- Updated the Model Hub sidebar UI to prioritize Roles and included comprehensive tests for new navigation and management flows.
2026-07-11 15:39:06 +02:00
can1357 59d08172c1 feat(coding-agent): introduced model hub for unified management and search
- Replaced the legacy model selector with a full-screen Model Hub, introducing mouse support and a fuzzy-searchable browser.
- Integrated comprehensive model management, including role assignment, thinking-level visualization, and manual provider discovery.
- Implemented a cancellable OAuth login flow and integrated it directly into the Model Hub for provider authentication.
- Centralized model logic and migrated existing tests to support the new component architecture.
2026-07-11 15:10:53 +02:00
can1357 bcee73e587 feat(coding-agent-modes): streamlined ask dialog workflow and layout
- Refined dialog layout with stable height clamping and improved preview visibility logic.
- Simplified interaction flow by replacing the "Next" row with "Submit" tab confirmation.
- Enabled accessible option toggling using Enter and Space keys.
- Removed legacy chat integration and streamlined internal dialog state management.
2026-07-11 14:47:20 +02:00
can1357 6f65a58d1b merge PR #4375: feat(ask): add rich interactive dialog
Closes #4375
2026-07-11 14:15:55 +02:00
roboomp f534112957 fix(coding-agent): bound startup changelog rendering
- Treated missing or invalid changelog markers as first install and persisted the current version without replaying historical notes.
- Shared bounded changelog rendering between startup and recent changelog views, with a 64 KiB startup cap and full-history hint on truncation.
- Added marker, truncation, recent/full rendering, and PTY startup regression coverage.

Fixes #5135
2026-07-11 02:28:27 +00:00
can1357 f4283e035a Merge PR #4994: fix(auth): decouple login success from model refresh 2026-07-10 12:37:36 +02:00
can1357 5d6e9a92d7 Merge PR #4999: fix(coding-agent): restore ask tool timeout fallback 2026-07-10 12:37:36 +02:00
roboomp bc9f4c4be6 fix(coding-agent): armed ask timeout for legacy ui
Added an explicit timeout presentation capability so interactive queued dialogs defer the fallback while older UI implementations still get an immediate tool-owned timeout.

Refs #4995
2026-07-10 04:13:18 +00:00
roboomp fcf389ae72 fix(coding-agent): deferred ask timeout until display
Started the ask tool fallback timeout from the selector presentation callback so queued dialogs do not consume the user's response window.

Refs #4995
2026-07-10 02:49:33 +00:00
roboomp facfb3c35a fix(coding-agent): synced ask fallback timeout resets
Reset the ask tool fallback timeout whenever the interactive selector resets its UI countdown, preventing late keypresses from falling back to the original recommended option.

Refs #4995
2026-07-09 23:37:50 +00:00
roboomp 497d385ce0 fix(auth): decoupled login success from model refresh
Switched interactive OAuth login to start model discovery in the background after credentials are saved.

Added a regression test that keeps model refresh pending and asserts the success transcript appears immediately.

Fixes #4989
2026-07-09 22:12:17 +00:00
roboomp bf64806474 fix(mcp): kept macos stdio servers attached
Left Darwin stdio MCP server launches in the inherited session so macOS TCC can prompt for Apple Events permissions used by xcrun mcpbridge.

Added resolver coverage for Darwin while preserving Linux detach and Windows console behavior.

Fixes #4987
2026-07-09 21:39:42 +00:00
roboomp 894cf489ff fix(tui): canceled streaming prompts on first escape
Esc during an active streaming turn required a second press within 2s
(two-step arm from #3493). In the no-input-waiter submit path the turn
starts with isStreaming=true but no working loader, so Esc fell into
the two-step branch and the agent_start subscription then wiped the
arm — repeated presses kept re-arming and never aborted. The loader-up
path already aborted on a single press, so the confirmation guarded no
coherent state. First Esc now aborts the streaming turn directly.

Adopted from PR #4938 (test + input-controller + changelog hunks only;
unrelated workflow-notice.md churn dropped).

Fixes #4921
2026-07-09 18:30:48 +02:00
can1357 c944870566 fix(coding-agent): implemented pi's ui.addAutocompleteProvider API
Extensions calling ctx.ui.addAutocompleteProvider (e.g. @ff-labs/pi-fff)
crashed at load with 'TypeError: ... is not a function' because omp's
ExtensionAPI.ui omitted pi's autocomplete-provider API; the throw also
aborted the rest of a try/catch-guarded session_start init.

ExtensionUIContext now declares addAutocompleteProvider(factory).
Interactive mode stacks each factory on the built-in editor provider in
registration order, re-applies the stack on every slash-command refresh,
and skips throwing/malformed factories; RPC, ACP, and headless contexts
accept the factory as a no-op, matching upstream pi's RPC behavior.

Fixes #4919
2026-07-09 18:27:23 +02:00
can1357 ba7a8fc420 merge PR #4693: fix(tui): dispose stale session UI renderers 2026-07-08 15:19:40 +02:00
can1357 92b2923f7b fix(coding-agent): normalize fallback chain picker writes 2026-07-08 15:19:39 +02:00
can1357 8d484435c2 merge PR #4535: fix(coding-agent): restore fallback model selection 2026-07-08 15:19:38 +02:00
can1357 41f2074ec4 fix(coding-agent): align python prompt mode detection 2026-07-08 15:19:36 +02:00
can1357 b1bfaa7b55 merge PR #4681: fix(coding-agent): guard pasted shell prompts from python 2026-07-08 15:19:36 +02:00
roboomp 568226abb9 fix(tui): disposed stale session ui renderers
Stopped new-session and session-switch UI paths from detaching active loader/render components without running their disposal hooks.

Added container and loader coverage for disposing children before destructive transcript/status replacement.

Fixes #4686
2026-07-06 08:49:02 +00:00
roboomp 2d180b885f fix(coding-agent): guarded pasted shell prompts from python
- Detected copied shell-prompt transcripts before the Python shortcut router.
- Forwarded OMP terminal chrome pastes through normal prompt submission.
- Added regression coverage for the #4678 transcript shape.

Fixes #4678
2026-07-06 06:14:21 +00:00
Dylan Bohlender 54f0a00dd2 fix(oauth): copy-safe URL chunks and loopback-only launch URLs
Resolves the two Codex P2s raised on #4420 that merged unaddressed:

- wrapUrlRows indented every continuation chunk. A multi-row terminal
  selection includes the newline plus that indent; address bars strip
  newlines but preserve or percent-encode embedded spaces, so the
  reassembled URL was corrupted at every chunk boundary - silently,
  when the damage landed inside a query value. Chunk rows now carry
  zero leading bytes (label rows keep their indent), and the test
  reassembly helper concatenates chunks raw instead of stripping the
  indent that previously masked exactly this defect.

- #launchUrlIfSafe advertised a localhost /launch copy target for
  flows whose redirectUri never returns to the loopback server. Its
  catch-comment assumed custom-scheme URIs are non-parseable, but
  new URL('vscode://gitlab.gitlab-workflow/authentication') parses
  fine and sailed through the pathname check. The guard now requires
  an http(s) loopback redirectUri (localhost / 127.0.0.1 / [::1]);
  custom schemes, non-loopback hosts, and unparseable URIs all
  suppress the launch URL. Regression tests cover the GitLab Duo
  vscode:// shape and a fixed non-loopback HTTPS redirect.

Refs #4418
2026-07-05 16:01:30 -06:00
can1357 f3e372e7bf fix(tui): preserve agent hub persisted gating 2026-07-05 13:39:10 +02:00
can1357 734aed4c03 Merge PR #4382: fix(compaction): keep plan-mode guidance off the session_before_compact hook (@roboomp) 2026-07-05 13:25:28 +02:00
can1357 a8528540cf Merge PR #4383: perf(coding-agent/tui): scoped renders + shimmer band fast-path (@roboomp) 2026-07-05 13:25:27 +02:00
can1357 7be558eda9 Merge PR #4342: fix(extension): refresh editor after extension paste (@roboomp) 2026-07-05 13:25:24 +02:00
can1357 8ec34a7662 Merge PR #4349: fix(session): handle malformed custom messages (@roboomp) 2026-07-05 13:25:24 +02:00
can1357 5681eeede2 Merge PR #4523: fix(tts): stop queued TTS playback on Esc after stream end (@roboomp) 2026-07-05 13:03:07 +02:00
roboomp 177977856a fix(tui): kept token badges for billed empty turns
Replace the visible-anchor suppression with a billed-usage predicate so live and resume paths agree on rendering the badge whenever the turn actually consumed tokens. Only genuinely free turns (no input, output, cache, or premium requests) drop the row, so hidden automated turns keep cost transparency.

Fixes #4532
2026-07-04 16:58:50 +00:00
roboomp 1ac9802508 fix(coding-agent): restored fallback model selection
- Exposed retry fallback chains in the model settings panel.
- Added a /model action that assigns the selected model as the default retry fallback.
- Cleared retry cooldown suppression when users manually switch models.

Fixes #4533
2026-07-04 16:42:38 +00:00
roboomp c5c95ecd12 fix(tui): suppressed empty assistant token badges
Suppress token-usage rows for assistant turns that have no visible text, tool call, or terminal error anchor. Share the same decision across live rendering and transcript rebuilds so resume matches live output.

Fixes #4532
2026-07-04 16:40:09 +00:00
roboomp 8cce6f637c fix(tts): stopped queued TTS playback on Esc after stream end
Once the assistant reply stops streaming, `vocalizer.clear()` was only invoked from the aborted-stream cascade in EventController. Escaping after the model finished fell through InputController to the empty-editor double-Esc gesture while StreamingAudioPlayer kept draining buffered Kokoro PCM.

Add `Vocalizer.isSpeaking()` (true while any live player, stream handle, or in-flight abort is around) and consult it in the Esc handler before the double-Esc branch: if speech is still audible, a single Esc calls `vocalizer.clear()` and resets `lastEscapeTime` so tree/branch stays reachable via the next press.

Fixes #4521
2026-07-04 14:42:24 +00:00
can1357 78126d925c test(ci): kept messagePersistenceKey call strict in event-controller
Reverted the defensive typeof guard; the assistant component contract guarantees the method, and test doubles now mock it. Keeping the production call strict avoids masking broken mocks or silently skipping persistence-key recovery.
2026-07-04 14:41:22 +02:00
can1357 53e8a8b807 test(ci): fixed event-controller and auth-storage test failures
- Mocked messagePersistenceKey in event-controller-error-banner.test.ts and safe-guarded it in event-controller.ts to prevent TypeError.
- Updated thinking loop retry test expectations to handle new dynamic recoveredErrors structure.
- Updated schema version assertions in auth-storage-email-dedupe.test.ts to v5, preserving v6 for future schema test.
- Simulated scrollback commitment in event-controller-message-start.test.ts by rendering container and committing rows before advancing timers.
2026-07-04 14:21:01 +02:00
can1357 10043a5990 feat(coding-agent): gated block lifecycle and state transitions
- Enforced strict history protection by gating ephemeral block removal on uncommitted state across controllers and UI components.
- Optimized settled-row calculations using explicit mermaid fence detection and improved scrollback integrity.
- Refactored transience management to target only actively streaming blocks, preventing redundant label rendering.
- Implemented persistent compaction for auto-retry errors and enabled consistent terminal title updates during session renaming.
2026-07-04 12:13:34 +02:00
can1357 0cdd0a09b8 refactor(coding-agent): consolidated session title update logic
- Moved terminal title update logic to a single listener onSessionNameChanged.
- Removed redundant setSessionTerminalTitle calls from ExtensionUiController, InputController, and InteractiveMode.
- Ensured consistent side-effect execution for terminal titles and editor accents across all session name change triggers.
2026-07-04 12:13:34 +02:00
can1357 6e2bba871e feat(agent): implemented automated retry recovery and transcript compaction
- Introduced an automated retry recovery system to track, manage, and persist recovered error states within agent sessions.
- Enabled compact transcript rendering for recovered auto-retry errors by removing heuristic commit machinery.
- Improved raw read tracking and provenance in the ReadTool to support refined file snapshot recording and hashline editing.
- Excluded recovered assistant messages from default model context and updated event controllers to handle retry recovery life cycles.
2026-07-04 11:22:04 +02:00
can1357 a96f2f9292 Merge remote-tracking branch 'origin/farm/ab9741c2/fix-mcp-oauth-windows-opener-and-url-truncation' 2026-07-04 05:14:28 +02:00
roboomp 7049966def fix(mcp): hydrate JSON-body OAuth scopes from resource metadata
When the error body already advertises OAuth endpoints, `/mcp add` and `/mcp reauth` use `authResult.oauth` directly and skip `discoverOAuthEndpoints`, so scopes advertised only in the RFC 9728 protected-resource metadata document never reach the grant.

Add exported `fetchResourceMetadataScopes(url, opts?)` that fetches the metadata doc and returns `scopes_supported` / `scopes` / `scope`. Hoist the shared `readMetadataScopes` reader out of `discoverOAuthEndpoints`. At all three call sites (wizard, `/mcp add`, `/mcp reauth`), when `oauth` is populated from the JSON body but `oauth.scopes` is empty and `authResult.resourceMetadataUrl` was advertised, fetch the metadata and merge scopes onto `oauth`.

Regression tests cover the resource-metadata fetch and its failure/empty-doc paths.

Refs #4467
2026-07-03 23:27:18 +00:00
roboomp 1d4e9a5384 fix(mcp): width-wrap the full authorize URL so narrow viewports cannot truncate
@DylanBohlender's follow-up caught that MCPAuthorizationLinkPrompt.render
still ignored `width` and emitted `Copy URL: <full URL>` as one composed
row. On any viewport narrower than the row (~272 columns for a
Linear-shaped authorize URL), TUI#prepareLine's
`truncateToWidth(..., Ellipsis.Omit)` silently clipped the trailing
`code_challenge_method=S256` — the exact #4418 fingerprint reappearing
inside the remote-safety fix. A remote user on a narrow terminal
copying the rendered line would lose the S256 method again; the local
shortcut below cannot help them (localhost isn't reachable), and the
OSC 52 clipboard staged full URL isn't visible in their local browser.

Component-level fix: honor `width` in render.

- New `wrapUrlRows(label, url, width)` helper.
  - When `label + " " + url` fits in `width`, emit one inline row.
  - Otherwise emit the label on its own row and slice the URL into
    chunks of `width - indent`, each on its own row.
  - Floors the effective width at 16 columns so degenerately narrow
    terminals still emit every character; browsers strip whitespace
    when a multi-row selection is pasted into the address bar, so the
    reassembled URL is byte-identical.
- `render(width)` now uses the helper for both the primary `Copy URL:`
  row and the additive `Local shortcut (this machine only):` row.

Regression tests in
`packages/coding-agent/test/modes/controllers/mcp-authorization-link.test.ts`:

- Wide viewport (1000 cols): inline `Copy URL: <url>` layout preserved.
- Narrow viewport (80 cols) + Linear-shaped URL: every row's visible
  width ≤ 80, and the chunks reassemble byte-for-byte to the URL —
  explicitly asserting the trailing `code_challenge_method=S256`
  survives.
- Launch shortcut also wrapped at 80 cols; every row fits.
- Degenerate viewport (4 cols): URL still reconstructs exactly; the
  16-col floor governs chunk width.
- Full URL remains the primary target even when a launch URL is
  present, and the shortcut row is omitted when launchUrl is absent
  or identical to the full URL.
2026-07-03 17:45:08 +00:00
roboomp 89fc4df9f4 fix(extension): refreshed editor after extension paste
Scheduled a TUI repaint after extension-driven prompt mutations so pasteToEditor and setEditorText do not leave the editor visually stale until the next input event.

Fixes #4341
2026-07-03 16:40:48 +00:00
roboomp debce0757b fix(mcp): carry OAuth scopes from challenge and resource metadata
MCP servers such as JIT gateways advertise required scopes via the RFC 6750 `WWW-Authenticate` challenge (`scope="..."`) and via RFC 9728 protected-resource metadata (`scopes_supported` / `scopes` / `scope`), then reject follow-up requests with `insufficient_scope` when a bearer token was issued without them. OMP's discovery only picked up `scopes_supported` from the auth-server metadata document, so `/mcp reauth`, `/mcp add`, and the MCP add wizard silently minted scope-less tokens.

- Extract `scope`/`scopes` from the WWW-Authenticate challenge into a new `AuthDetectionResult.scopes` field via `extractOAuthChallengeScopes`.

- Thread a `protectedScopes` option through `discoverOAuthEndpoints` and its recursion; capture `scopes_supported`/`scopes`/`scope` off resource-metadata documents; use those scopes when the auth-server metadata omits them.

- Pass `authResult.scopes` from `analyzeAuthError` into every discovery call site (`/mcp reauth`, `/mcp add`, MCP add wizard).

- Add regression tests for insufficient_scope + resource_metadata, resource-metadata `scopes_supported` passthrough, and challenge-scope threading.

Fixes #4467
2026-07-03 16:10:21 +00:00
roboomp 721f6d4a08 fix(mcp): make full URL the primary OAuth copy target so SSH sessions work
Codex review flagged that advertising `launchUrl`
(http://localhost:<omp-port>/launch) as the visible `Copy URL:` breaks
SSH/WSL/headless users: their local browser resolves the URL against
the local machine (no OMP listening) and fails before ever hitting the
provider. On terminals without OSC 8 support, they lose the manual
`/login <redirect>` path entirely.

Every OAuth-facing surface now shows the full authorization URL as the
primary copy target and offers `launchUrl` as an additional "Local
shortcut (this machine only)" line for wide-terminal local users who
want the truncation-safe convenience:

- MCPAuthorizationLinkPrompt renders `Copy URL:` with the full URL and
  appends the local-shortcut row only when `launchUrl` differs. OSC 52
  clipboard staging in the MCP onAuth handler switches to the full URL
  (OSC 52 is a wire-level protocol — the terminal writes to the
  caller's LOCAL clipboard even when OMP is on a remote SSH box).
- LoginDialogComponent.showAuth, selector-controller onAuth,
  setup-wizard sign-in, and the auth-broker CLI mirror the pattern:
  full URL first, launchUrl as an optional local shortcut.
- Setup wizard uses `wrapTextWithAnsi`, not truncation, so the RFC
  7636 §4.3 downgrade bug that motivated launchUrl is unreachable
  through it; still surfaces launchUrl for wide-terminal convenience.

Regression tests in
`packages/coding-agent/test/modes/controllers/mcp-authorization-link.test.ts`
now assert:
- Full URL is the primary `Copy URL:` line so SSH sessions can complete.
- launchUrl still appears beneath as `Local shortcut (this machine only): …`
  when it differs from the full URL.
- No shortcut row when launchUrl is absent OR equals the full URL.
2026-07-03 08:57:55 +00:00
roboomp 97c1d08cce fix(mcp): surface a short launch URL and log Windows opener failures for OAuth
Two independent defects broke /mcp reauth against S256-only providers on
Windows boxes whose PATH no longer references System32:

1. openPath spawned bare rundll32 and swallowed the
   `Executable not found in $PATH` throw with a bare `catch {}`, so the MCP
   controller's outer try/catch was dead and the transcript unconditionally
   claimed "Opening browser automatically...".
2. TUI#prepareLine silently truncates any composed row wider than the
   viewport. MCPAuthorizationLinkPrompt rendered `Copy URL: <full URL>` as a
   single ~271-column line whose trailing parameter is
   code_challenge_method=S256. On the reporter's 270-col terminal the cut
   landed inside that parameter, dropping the method while keeping
   code_challenge — which RFC 7636 §4.3 treats as plain PKCE, which Linear
   correctly rejects with "The plain PKCE method is not allowed. Use S256
   instead."

OAuthCallbackFlow now hosts a `GET /launch` route on the same loopback
callback server it already runs; the route 302-redirects to the pending
authorization URL and is advertised as `OAuthAuthInfo.launchUrl` — a
~30-char copy target no viewport can meaningfully truncate. The MCP OAuth
fallback, /login, setup wizard, auth-broker CLI, and login-dialog all
prefer the launch URL for the visible copy target, keep the full URL in
the OSC 8 hyperlink for click-through, and the MCP flow additionally
stages the copy target on the clipboard via OSC 52 (same pattern the
setup wizard uses).

openPath now resolves rundll32.exe through %SystemRoot%\System32 (with a
C:\Windows fallback when SystemRoot is unset) and logs both synchronous
spawn throws and non-zero exits via the shared logger, so silent
misconfigurations show up in ~/.omp/logs/omp.*.log. The dead try/catch
around openPath in the MCP controller is removed.

Fixes #4418
2026-07-03 08:19:14 +00:00