Commit Graph

724 Commits

Author SHA1 Message Date
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
roboomp 31ac7e27eb perf(coding-agent/tui): scoped renders + shimmer band fast-path
Timer-driven reveal and spinner ticks (streaming reveal, tool-args reveal,
tool-execution spinner, todo strike animation) now hand the changed
component to `TUI.requestComponentRender(component)` instead of forcing a
full-tree render at 30fps. Every other root subtree reuses its previous
frame rows, cutting the Box/Container tree walk out of the compose
pipeline while the transcript grows.

Shimmer:
- Intern the working-message palette per accent (WeakMap-keyed) so the
  Symbol-slot compiled-ANSI cache in `shimmerSegments.compile` actually
  hits between frames — the fresh palette literal in `renderWorkingMessage`
  guaranteed a per-tick miss.
- Add an `activeBand` fast-path: outside the sweep window the intensity
  is guaranteed zero, so those code points coalesce into a single low-tier
  run without running `intensityFn` or `tierFor`. On the typical ~60-char
  working message the classic band is 12 cells wide, so ~80% of the per-char
  loop disappears.

Widen `ToolExecutionHandle` to extend `Component` (matches every
concrete impl — `ToolExecutionComponent`, `ReadToolGroupComponent` —
which already extend `Container`) so the reveal controller callback
sites are type-checked.

Fixes #4377
2026-07-03 00:50:03 +00:00
roboomp 72df91c3c8 fix(compaction): route plan-mode guidance via internalGuidance channel
Plan-approval's 'Approve and compact context' used to pass the rendered
plan-mode-compact-instructions prompt as the first positional argument
to handleCompactCommand -> session.compact(), which landed on the
session_before_compact extension hook as customInstructions. Extensions
treating that field as user focus (e.g. to bias a query-focused summary)
would then see plan-mode boilerplate instead of operator intent and
produce query-biased compactions.

Add CompactOptions.internalGuidance: a private summarizer-only channel.
session.compact() reads it into the fallback-model summarizer while the
session_before_compact hook payload still only carries the public
customInstructions arg (undefined for the plan-compact path). The
snapcompact-disable predicate and the /compact rejectsFocus guard cover
both fields so a directed summary is never silently downgraded.

Extend the interactive-mode handleCompactCommand facade + command
controller with a fourth internalGuidance parameter, and switch the
plan-approval callsite in interactive-mode.ts to route the plan prompt
through it.

Fixes #4359
2026-07-03 00:36:38 +00:00
roboomp 30527aee0c fix(tui): cut TUI CPU overhead during interactive sessions
Four tightly-scoped hot-path fixes covering the highest-impact items in the
reporter's CPU profile (13.1 s profiled / 30 s window):

1. `event-controller.ts:handleEvent` no longer fires a blanket
   `statusLine.invalidate() + ui.requestRender()` before every session event.
   The pre-render was a leftover from #4145 when `updateEditorTopBorder()`
   still eagerly rebuilt the border; the lazy provider added in #4145 made
   it redundant. It fired on every `message_update`/`tool_execution_update`
   during streaming — the pre-render's frame ran while the handler was
   awaiting, then the handler's own `requestRender` scheduled a second
   identical frame. Every handler that mutates visible state already calls
   `requestRender()`.

2. `shimmer.ts:shimmerSegments` iterates the segment string in place instead
   of building a code-point array with `Array.from(seg.text)` every animation
   frame. Runs of same-tier chars are emitted via a single `slice` per run
   rather than accumulating into `runBuf`. Surrogate pairs stay atomic — the
   code-point index still advances by 1 per emoji. Microbench over 30k
   frames: 45 ms → 18 ms (2.53x), allocation rate down from ~N-per-frame to
   a handful per frame. New tests cover mixed BMP+surrogate and all-emoji
   inputs. `Array.from` was the #1 self-time hotspot in the reporter's
   profile at 10.2%.

3. `Markdown.setText` gains an equality guard mirroring `Text.setText`
   (returns `false` when `text === #text`). Providers re-emit identical text
   on ticks with no delta (throttled frames, reconciled tool-execution
   updates); each of those now short-circuits instead of dropping
   `#cachedLines` and forcing a full lex + wrap on the accumulated paragraph
   (the reporter's #3 hotspot at 8.4%). New test asserts render-reference
   stability + return-value semantics.

4. `SPINNER_RENDER_INTERVAL_MS` aligned with `SPINNER_GLYPH_ADVANCE_MS`
   (both 80 ms). The previous 33 ms cadence emitted ~2.4 paints per glyph
   step; the differential-output dedup only skips the write, not the
   compose walk. Visually identical (glyph advance was already 12.5fps),
   halves paints during tool execution.

Skipped (out of scope for a bug fix, deserve dedicated PRs):
- Freezing streaming prefix on single `\n` boundaries — correctness-bound
  to `\n\n` block separators (CommonMark loose-list continuation).
- Compose-phase idle gate + adaptive-backpressure moving-average — need a
  component-level dirty flag; the 200 ms cap in `#scheduleRender` was set
  for a reason (#4145 tail-latency guard).

Tests updated: two IRC-expiry tests in event-controller-message-start.test.ts
that were asserting the pre-render's second `requestRender` call now expect
one.

Fixes #4353
2026-07-02 22:11:26 +00:00
can1357 2c8daf0578 feat: implemented dynamic coercion for legacy tool argument aliases
- Added `normalizeSingleStringField` to dynamically map misplaced string inputs to required schema fields for single-argument tools.
- Integrated argument normalization into `validateToolArguments` to handle model-specific variations in JSON payloads during validation passes.
- Updated `coding-agent` streaming and rendering components to recognize `_input` as a legacy alias for `input` across various UI paths and logic flows.
- Refactored `hashlineEditParamsSchema` to strictly enforce the `input` field while maintaining support for legacy aliases via runtime coercion rather than schema definition.
- Corrected unit tests to reflect that `_input` is rejected by the strict schema but handled gracefully by the validation layer.
2026-07-02 23:32:35 +02:00
roboomp 8da17ba3b5 fix(session): handled malformed custom messages
Normalized extension custom-message payloads before session state or persistence, including bare string sendMessage shorthands. Skipped legacy bare custom_message entries during context rebuilds and dropped malformed custom/hook messages before LLM conversion. Added regression coverage for the poisoned-session resume crash.\n\nFixes #4345
2026-07-02 20:34:15 +00:00
can1357 94645752ff feat(coding-agent/tts): introduced natural speech synthesis pipeline
- Added an enhanced speech pipeline that utilizes small models to rewrite text for natural language synthesis.
- Implemented `SpeechEnhancer` and `BlockAccumulator` to manage fence-aware text streaming and paragraph splitting.
- Configured a new `speech.enhanced` setting to toggle between mechanical and enhanced vocalization modes.
- Resolved `EPIPE` rejections during speech playback by ensuring stream flushes and suppressing stop-related errors.
2026-07-02 08:59:13 +02:00
Can Bölük 8e68b26315 Merge pull request #4185 from DeprecatedLuke/feat/make-token-info-nice
feat/make token info nicer
2026-07-02 02:59:04 +02:00
can1357 ad4f82eb8f test(coding-agent): unified collab test infrastructure and refined guest ui dialog fallback
- Introduced the `CollabGuestUiResult` type to distinguish between answers and unavailable states during guest UI requests.
- Updated the remote dialog race logic to ignore unavailable guest results and fallback to the local host dialog.
- Centralized the `FakeWebSocket` and `InMemoryRelay` test infrastructure into a shared test helpers file.
- Cleaned up duplicate mock implementations and updated existing test suites to utilize the shared in-memory relay helpers.
2026-07-02 02:40:08 +02:00
can1357 51684b4b1d refactor(coding-agent): streamlined codebase by deduplicating helper logic and shims
- Consolidated duplicated inline thinking level comparisons into a unified `concreteThinkingLevel` helper.
- Enhanced legacy tool shims to respect isolated session settings and support legacy options.
- Cleaned up redundant UI render requests and extra status-line updates.
- Refactored `grep` tool shim to configure context dynamically via isolated settings.
- Disabled platform-incompatible shell shim tests on Windows environments.
2026-07-02 02:40:08 +02:00
can1357 1ded0d3759 fix(coding-agent): restricted key extraction to top-level json depth
- Introduced JSON depth tracking to ensure string keys are only extracted at the top level.
- Prevented nested keys matching designated streaming keys from being prematurely or incorrectly captured.
- Added comprehensive unit tests validating nested key exclusion and correct top-level extraction order.
2026-07-02 02:40:07 +02:00
luk 62efd9ded6 feat(usage-row): use database icon for cache, add ttft + throughput display 2026-07-02 00:25:54 +01:00
can1357 cc78244217 fix(coding-agent): shared streamed-arg decode across render paths
- Extracted decodeStreamedToolArgs into tool-args-reveal.ts and used it from both the live event path and transcript rebuilds, so mid-write theme/settings/focus replays no longer show stale streamed write/edit/eval content.
- Fixed the smoothing-off live path returning stale provider-parsed args.
- Documented the mandatory shared decode in the AGENTS.md streaming-preview hazard note; added changelog entries for this batch.
2026-07-02 01:03:48 +02:00
roboomp 9aa729c586 fix(tui): preserved prompt drafts on esc
Stopped Esc from clearing typed TUI prompt text while preserving double-Esc disarming behavior.\n\nFixes #3869
2026-07-01 22:17:37 +02:00
can1357 63b812320d Merge PR #3903: fix(coding-agent): identify user-invoked skills and expose skill directory (@metaphorics)
# Conflicts:
#	packages/coding-agent/src/extensibility/skills.ts
#	packages/coding-agent/src/modes/acp/acp-agent.ts
#	packages/coding-agent/src/modes/rpc/rpc-mode.ts
#	packages/coding-agent/src/modes/skill-command.ts
2026-07-01 22:16:53 +02:00
can1357 ab7f623ac4 Merge PR #4149: fix(tui): coalesce editor top-border rebuild to render tempo (#4145) (@roboomp) 2026-07-01 21:53:18 +02:00
can1357 edef5c052d Merge PR #4056: fix(tui): smooth write streaming previews (@roboomp) 2026-07-01 21:53:14 +02:00
can1357 cdd6e558e9 Merge PR #4049: fix(collab): enable mobile ask responses (@roboomp)
# Conflicts:
#	packages/coding-agent/src/collab/protocol.ts
2026-07-01 21:53:00 +02:00
can1357 637c1105de Merge PR #3851: fix(coding-agent): log Esc/Ctrl+C abort failures instead of swallowing them (@oldschoola) 2026-07-01 21:47:54 +02:00
can1357 dae0ab3580 Merge PR #3848: perf(coding-agent): memoize incremental grapheme slicing in streaming reveal (@oldschoola) 2026-07-01 21:47:54 +02:00
can1357 b3b4a762ac Merge PR #3736: fix(coding-agent): replan title refresh honors TITLE_SYSTEM.md override (@roboomp) 2026-07-01 21:42:25 +02:00