Commit Graph
834 Commits
Author SHA1 Message Date
can1357 ae89b3ff08 fix(tui): merged scrollback offer boundary repair
Merged PR #4330 and fixed the remaining offered-boundary regression by stopping offer promotion at intervening live blocks.

Verified with targeted transcript/native scrollback regressions: 40 pass.
2026-07-02 23:41:53 +02:00
roboomp 49b4ef50f8 fix(tui): fixed audited scrollback tail rows
Separated audited offerable transcript rows from durable snapshot rows so lower finalized content below a live block can be repaired instead of duplicated when the live block grows.

Added transcript and virtual-terminal regressions for the lower finalized tail case.

Fixes #4326
2026-07-02 16:24:11 +00:00
can1357 3830ad353e merge PR #3843 (surviving delta): perf: streaming-reveal/render throughput + core hot-path optimizations (@oldschoola)
# Conflicts:
#	packages/coding-agent/src/config/model-resolver.ts
2026-07-02 10:31:45 +02:00
can1357 ebf41281e7 fix(tui): stop spinner ticks for frozen pending previews
The github renderer materializes plain Text per display rebuild, so its
animatedPendingPreview opt-in requested 30fps repaints with a frozen
glyph for the whole run_watch wait; drop the flag. Custom tools with
only one of renderCall/renderResult never route to the animated generic
fallback, so gate the unregistered-renderer spinner on both being
absent. Regression tests for both no-tick contracts.
2026-07-02 10:30:06 +02:00
can1357 6429de3e83 merge PR #4172: fix(tui): animate live tool spinners (@roboomp) 2026-07-02 10:30:06 +02:00
can1357 278056025b merge PR #4200: fix(tui): stop /move overlay from statting every entry per keystroke (@roboomp) 2026-07-02 10:30:06 +02:00
can1357 95b91c7f73 feat(coding-agent/tools)!: replaced paths arrays with path strings
- Replaced `grep`, `glob`, and `ast_grep` `paths` inputs with optional single `path` strings while preserving default workspace-root behavior.
- Added shared `toPathList` normalization for legacy arrays and JSON-encoded arrays across tool execution and TUI renderers.
- Updated prompts, fixtures, shims, transcript summaries, and tests to send and display the new `path` argument.
- Updated collab-web search tool cards to read `path` while falling back to legacy `paths` for historical transcripts.
- Recorded the contiguous coding-agent changelog run for the tool-path breaking change and adjacent TTS entries.
2026-07-02 08:30:33 +02:00
roboomp cf9533ac95 fix(tui): stat-fallback /move overlay Dirents with unknown type
Some filesystems (NFS, FUSE, older SMB) return UV_DIRENT_UNKNOWN, making every Dirent.isX() return false. The prior early-return dropped real directories on those mounts. Now only reject when a known non-directory type (file/device/fifo/socket) is reported; symlink and unknown-type entries fall back to fs.statSync.
2026-07-02 04:46:36 +00:00
roboomp e04316dc52 fix(tui): stop /move overlay from statting every entry per keystroke
The overlay's directory cache stored names only, so listChildDirectories/searchDirectories called fs.statSync on every cached entry per keystroke to filter directories — a stat storm scaling with the target directory size and particularly costly on Windows.

Cache fs.Dirent[] via readdirSync({ withFileTypes: true }) instead of names, classify with entry.isDirectory(), and fall back to fs.statSync only for entry.isSymbolicLink() so a symlinked directory still counts as one. Adds a regression test that spies on fs.statSync and asserts an O(1) stat budget per keystroke.

Fixes #4199
2026-07-02 04:41:46 +00:00
Can Bölükandcan1357 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 2b8f6bd568 fix(coding-agent): prevented terminal layout breakage from long error strings
- Introduces `sanitizeErrorLine` to collapse newlines, replace tabs, and shorten absolute paths.
- Truncates remote error and notice text to the available terminal width to prevent layout breaking.
- Corrects a potential runtime exception in status-line by safely accessing JSON stringified length.
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
luk 308eabc6b3 feat(status-line): add throughput icon and simplify cache segments 2026-07-02 00:24:55 +01:00
roboomp 5d07fe5041 style: bun run fix 2026-07-01 22:10:59 +00:00
roboomp f6adba2931 fix(tui): bound macos command-v image paste
Fixes #4178
2026-07-01 22:10:38 +00:00
can1357 e4c3cba143 Merge PR #3875 (selective): skip double-format of revealed thinking blocks (@oldschoola)
Ports only the thinking double-format fix: resolveThinkingDisplay reuses block.thinking when rawThinking is set (buildDisplayMessage already formatted it), plus a single-entry memo in formatThinkingForDisplay and a rawThinking regression test. The PR's incremental reveal slicing is superseded by the already-merged #3848 (memoized grapheme slicing).
2026-07-01 22:37:36 +02:00
can1357 d9beb9731d Merge PR #4158: fix(coding-agent): paint selectedBg band on focused HookSelector row (@roboomp) 2026-07-01 21:53:19 +02:00
can1357 debe71ae0e Merge PR #4129: fix(coding-agent): preserved explicit :auto suffix in modelRoles (@roboomp) 2026-07-01 21:53:17 +02:00
can1357 3364c3c6fd fix(collab): surface remote transcript errors after rows 2026-07-01 21:50:54 +02:00
can1357 6019be42c5 Merge PR #3938: fix(collab): reject oversized remote transcript entries (@roboomp) 2026-07-01 21:50:54 +02:00
can1357 c078f92582 Merge PR #3884: fix(coding-agent): handle BigInt tool-call fingerprints (@wolfiesch) 2026-07-01 21:50:53 +02:00
can1357 f3744bce8e Merge PR #3776: Fix hidden thinking glyph-only status rows (@jeffscottward) 2026-07-01 21:42:26 +02:00
roboomp fb2804247a fix(tui): gated live tool spinner ticks
Added renderer metadata for pending and partial result paths that visibly consume spinner frames.

Stopped headerless bash pending previews from scheduling repaint ticks while preserving eval and shell header animation.
2026-07-01 18:34:12 +00:00
roboomp 469ff4a0ad fix(tui): stopped async tool spinner ticks
Excluded running async result snapshots from live partial spinner intervals so finalized background tool rows do not repaint scrollback.

Added regression coverage for async bash snapshots staying static.
2026-07-01 18:26:34 +00:00
roboomp 9e7814a638 fix(tui): animated live tool spinners
Started live partial tool spinner intervals for non-static tool blocks and forwarded spinner frames through eval and shell-style renderers.

Added regression coverage for live eval and shell preview spinner frames.

Fixes #4170
2026-07-01 18:19:31 +00:00
roboomp ffb4d93389 style: bun run fix 2026-07-01 15:15:53 +00:00
roboomp 8a5fb33464 fix(coding-agent): paint selectedBg band on focused HookSelector row
The multi-select (checkbox) ask picker signaled focus only by shifting the
label fg to `accent` and flipping the checkbox glyph between `accent`
and `dim`. On themes where `accent` is close to `text` (built-in
`light`, others) the focused row was effectively invisible: `↑/↓` would
change the toggle target with no perceptible cue. Radio pickers dodged this
because the glyph shape changes (`◉` vs `○`); checkboxes always render
`☑`/`☐` regardless of focus.

Root cause: HookSelectorComponent's option rendering picked focus via
`textColor = isSelected ? 'accent' : 'text'` and the fallback
`marker ?? cursorChevron` — so with any marker in play the chevron
disappeared, and the only remaining signal was fg color contrast.

Fix: route rendered lines through a `SelectorRow = { text, highlight }`
carrier. `OutlinedList` paints highlighted rows with
`theme.bg('selectedBg', wrappedLine + padding)` inside the border rails,
and the non-outlined plain list feeds the same painter as `Text`'s
`customBgFn` (which `applyBackgroundToLine` already extends across
wrap continuations). The band spans label plus wrapped description rows
so the focus reads as one continuous bar, independent of accent/text
contrast. Precedent: the Ctrl+R history overlay and plan-review overlay
use the same selectedBg-band pattern.

Regression tests cover both outlined and non-outlined lists, focus
movement, control rows past markableCount, and multi-line description
highlighting.

Fixes #4157
2026-07-01 15:15:40 +00:00
roboomp a4ae4c130c fix(coding-agent): preserved explicit :auto suffix in modelRoles
The model selector's persistence path dropped the `:auto` selector when parsing role values, producing a warning ('Invalid thinking level "auto"') and rendering the badge as `inherit` instead of `auto`. Reload of the default role also lost the auto state whenever the role value carried an explicit `:auto` suffix instead of relying on `defaultThinkingLevel`.

Widen the resolver chain (`parseThinkingSuffix`, `splitThinkingSuffix`, `parseModelString`, `parseModelPattern*`, `ResolvedModelRoleValue`, `ResolvedRoleModel`, `ResolveCliModelResult`) to carry the `AUTO_THINKING` sentinel end to end, and coerce it back to `undefined` at concrete-only boundaries (glob scope patterns, retry fallback, advisor, commit pipeline, guided-goal, bench).

Regression tests cover:

- `resolveModelRoleValue("provider/model:auto")` returns explicit auto without a warning.

- `ModelSelector` renders `DEFAULT (auto)` and `SMOL (auto)` when the role value has `:auto`.

- `cycleRoleModels` activates auto thinking on entering a `:auto` role.

- Startup resume activates auto thinking when `modelRoles.default` carries `:auto`.

Fixes #4128
2026-07-01 08:18:42 +00:00
can1357 ef7636805b feat(coding-agent): removed canonical model variant selection and tracking
- Removed the canonical model variant indexing, selection, and tracking logic from the model registry and resolver.
- Eliminated the `canonical` sub-command, tab view, search tokens, and equivalence configuration structures from the CLI and model selector components.
- Refined model identification, lookup, and provider fallback resolution to bind exclusively to standard, raw model IDs.
- Relocated the equivalence utility script within the catalog package to support script-only policy generation.
2026-07-01 05:22:42 +02:00
roboomp 21adbcf40b fix(collab): rejected oversized transcript entries
Return an explicit remote transcript error when the host cannot fit a complete JSONL entry inside the fetch cap, and stop the guest viewer poll loop after surfacing that error.

Fixes #3931
2026-06-30 23:39:37 +00:00
can1357 112317bc8e fix(coding-agent): resolved duplicate todo reminders in terminal scrollback
- Anchors the incomplete-todo reminder block inside the scrollback transcript instead of a floating live container.
- Eliminates duplicate reminder copies piling up in terminal scrollback during terminal reflows.
- Removes the dedicated `todoReminderContainer` and simplifies state synchronization on todo reload.
- Updates tests to verify sequential reminders commit as separate blocks and are left intact when tools succeed.
2026-06-30 23:32:58 +02:00
can1357 3c012a6c54 Merge remote-tracking branch 'origin/farm/a3e74c54/preserve-auto-model-thinking' 2026-06-30 17:54:52 +02:00
roboomp 51da3add83 fix(coding-agent): preserved auto thinking across plan approval
Captured the configured thinking selector when entering plan mode so approving a plan restores auto instead of the provisional concrete effort. Reloaded DEFAULT(auto) badges from defaultThinkingLevel and covered the plan-approval handoff plus /model display.

Fixes #3901
2026-06-30 14:28:07 +00:00
roboomp a6b2bac882 fix(mcp): made Esc cancel /mcp reauth and /mcp add OAuth flow
#handleOAuthFlow now installs an editor.onEscape hook that aborts its
AbortController, and accepts an external abortSignal so the add-wizard
can thread its own controller through (the wizard owns focus and absorbs
Esc itself). Cancellation surfaces as MCPOAuthCancelledError, which the
reauth and add catches translate into a neutral status line instead of
the generic OAuth failure banner. Disambiguated from the existing 5-min
timeout via a userCancelled flag so timeouts still read as errors.

The wizard intercepts Esc/Ctrl+C while #oauthAbort is set so its own
"Press Esc to cancel" advertisement now matches the behaviour, and
renames its error heading + tip when the failure is a user cancel. Also
fixed the misleading "(Press Ctrl+C to cancel)" message in the chat
transcript onAuth block to say "Press Esc" — Ctrl+C is bound to the
editor clear action, not interrupt.

Fixes #3888
2026-06-30 10:07:05 +00:00
Wolfgang Schoenberger 6d15894c0a fix(coding-agent): handle BigInt tool-call fingerprints 2026-06-30 01:38:36 -07:00
oldschoola 5abde300a1 Merge remote-tracking branch 'origin/main' into perf/streaming-reveal-throughput 2026-06-29 22:08:03 -07:00
oldschoola 8288ebb525 perf(tui): reduce streaming reveal + render cost ~2.3x
Three changes to the streaming text-reveal path (the 30fps typewriter animation during model streaming), cutting real per-tick render CPU ~2.3x (measured ~73ms -> ~31ms to animate a 12k-char response; ~1.35ms -> ~0.57ms per tick).

- streaming-reveal: incremental grapheme slicing. BlockUnitCounter.slice resumes segmentation from the cached boundary cluster each tick instead of re-segmenting the whole revealed prefix (O(delta) vs O(revealed)). Handles fixed-text catch-up and append-only live streaming via startsWith + boundary-cluster re-segment.

- assistant-message: fix the transient flag dropped on the fast path. #tryFastPathUpdate(message) was called without opts, so streaming updates always set Markdown.transientRenderCache=false, running code syntax highlighting + L2 cache-key work every tick. Now passes opts through; highlighting applies once at message finalization.

- markdown: render-prefix cache for transient renders. Caches content lines (render+wrap+margin) for the stable streaming-lex prefix tokens [0..frozenCount-2] and re-renders only the changed tail each tick. Byte-identical to the full pipeline (OSC66 margin state resets per token; nextTokenType boundary handled; content-identity guard).

Correctness: byte-identity verified (transient split == full render across 57 reveal steps); BlockUnitCounter.slice verified against a pure Intl.Segmenter reference across fixed/append/cluster-extend/ZWJ-merge/shrink/replace/fuzz cases. Regression tests added in both packages.
2026-06-29 16:59:10 -07:00
roboomp e34f2a81e9 fix(tui): force-enabled MCP from tool-owned sources via enabledServers
Codex review on #3829: when an MCP server lives in a non-writable
source config such as opencode.json with enabled:false, the dashboard
re-enable had nowhere to write to — the writable mcp.json fallback
did not own the server, so setMcpServerEnabled fell through to the
denylist and the source's enabled:false kept the row disabled.

Added a parallel allowlist to the user-level mcp.json that overrides
a non-writable source's enabled:false flag without ever mutating the
foreign config:

- types + schema: new enabledServers array (mirrors disabledServers).
- config-writer: readEnabledServers + setServerForceEnabled helpers,
  and setMcpServerEnabled now writes to enabledServers on enable
  when no writable mcp.json owns the server, clears it whenever a
  writable source becomes the source of truth, and always clears the
  override on disable so a force-enabled server can be turned off.
- mcp/config (runtime loader) and state-manager (dashboard read):
  honor enabledServers as an override on enabled:false, while still
  letting disabledServers win.
- Added a regression test that walks the full lifecycle for an
  opencode.json server: enabled:false is surfaced as disabled, the
  dashboard re-enable force-enables via enabledServers without
  touching opencode.json, then disable clears the override and
  populates disabledServers.

Fixes #3827
2026-06-29 20:39:50 +00:00
roboomp 16ef3c54f4 fix(tui): re-enabled MCP alternate config sources
Codex review on #3829: the dashboard re-enable path still missed MCP
servers loaded from supported non-primary native config files such as
.omp/.mcp.json or user .mcp.json. Those rows carry enabled:false from
their source file, so falling back to the user disabledServers denylist
could not make the row active again.

- setMcpServerEnabled now accepts the loaded row's sourcePath and checks
  it before the primary project/user mcp.json paths.
- extension-dashboard passes the source path for writable MCP providers
  (native and mcp-json), avoiding accidental edits to third-party tool
  configs while still updating .omp/.mcp.json and standalone MCP JSON
  sources.
- Added a regression test for a server loaded from .omp/.mcp.json with
  enabled:false; re-enable flips that file to enabled:true and does not
  write the denylist.

Fixes #3827
2026-06-29 20:26:16 +00:00
roboomp 812b246e7e fix(tui): dashboard re-enable flips enabled:false in mcp.json
Codex review on #3829: when an MCP server's mcp.json entry carries
enabled:false, the dashboard toggle previously only removed the name
from the user-level disabledServers denylist. state-manager's new
`server.enabled === false` check (state-manager.ts:156) then still
marked the row disabled, leaving such servers impossible to re-enable
from /extensions.

Extracted setMcpServerEnabled() into mcp/config-writer.ts mirroring
/mcp enable | /mcp disable semantics:

- Server defined in project mcp.json -> update enabled on that entry.
- Else server defined in user mcp.json -> update enabled on that entry.
- Else (discovered third-party server) -> use the user-level disabledServers denylist.
- On re-enable, always clear any stale denylist entry.

extension-dashboard.ts routes mcp:* toggles through this helper. Added
four new regression tests covering: enabled:false re-enable, mixed
flag+denylist re-enable, disable on a config-resident server writing
enabled:false (not denylist), and discovered-server denylist round-trip.

Fixes #3827
2026-06-29 20:13:15 +00:00
roboomp 6256f97eaf fix(tui): aligned /extensions MCP status with /mcp list
Two read paths previously diverged on whether an MCP server was active or
disabled. /mcp list (slash-commands/helpers/mcp.ts:388) treats a server
as disabled when config.enabled === false OR the name is in the
user-level disabledServers denylist; the runtime MCP loader does the
same in mcp/config.ts:115. The /extensions dashboard only consulted
the dashboard-private settings.disabledExtensions array, so a server
disabled via /mcp disable or enabled:false kept showing as active.

Toggling MCP servers from the dashboard had the mirror problem: it only
wrote to settings.disabledExtensions, so /mcp list never noticed.

- state-manager: read user-level disabledServers from mcp.json once and
  consider enabled:false / denylist membership when deriving each MCP
  extension's state, matching /mcp list semantics.
- extension-dashboard: route mcp:* toggles through setServerDisabled
  against the canonical mcp.json denylist, and clean any legacy
  settings.disabledExtensions entry on re-enable so it doesn't keep the
  server marked disabled.
- Added a regression test exercising both read signals and the
  setServerDisabled round-trip the dashboard's MCP toggle now uses.

Fixes #3827
2026-06-29 20:05:04 +00:00
Jeff Scott Ward 3854b0ec16 fix: describe hidden thinking pulse 2026-06-29 11:57:59 -04:00
can1357 4db3d68bdb feat(coding-agent): implemented git worktree detection and rendering
- Added `git.repo.linkedWorktreeSync` to identify and resolve git worktree metadata without spawning subprocesses.
- Updated `StatusLineComponent` to detect linked worktrees and resolve project/worktree context names.
- Modified path segment rendering to collapse nested git worktree paths and display the worktree name when it diverges from the active branch.
- Introduced `icon.worktree` symbol across themes to visually distinguish git worktree paths.
2026-06-28 22:50:30 +02:00
can1357 6dab2b3196 Merge PR #3604: fix stale todo HUD rows (@jeffscottward) 2026-06-28 18:55:26 +02:00
can1357 8185fdbfa9 feat(coding-agent): queued tool argument updates to prevent edit loss
- Implemented a queueing mechanism in `ToolExecutionComponent` to prevent starvation of edit previews during high-frequency argument updates.
- Replaced eager cancellation of in-flight diff computations with a drain loop that ensures every update is processed once the current compute settles.
- Added `partialJsonOf` helper to safely narrow streamed JSON buffers from tool arguments.
- Added regression test to verify that slow diff computations are not aborted by incoming stream chunks and instead queue a subsequent re-run.
2026-06-28 17:11:43 +02:00
Jeff Scott Ward 54f83e794e fix: preserve subagent hint API 2026-06-28 11:09:17 -04:00
can1357 fbad280b57 feat: implemented multi-advisor concurrent runtime with tui management
- Introduced comprehensive support for multiple concurrent, independently-configured advisors via `WATCHDOG.yml` files.
- Implemented a full-screen TUI overlay for managing advisor rosters, models, tools, and instructions.
- Added session-wide advisor initialization, telemetry aggregation, and named transcript isolation.
- Enhanced advisor security and observability with secret redaction in tool results and secure XML attribute encoding.
2026-06-28 12:55:09 +02:00
can1357 51a2a0342f test(coding-agent): implemented guest reconciliation and expanded testing for collaboration
- Introduced guest snapshot reconciliation to maintain host state consistency during session switching.
- Improved yield tool reliability by implementing incremental schema validation and strict parameter enforcement.
- Fixed a calculation edge case in the status line to prevent negative time values during activity tracking.
- Expanded the test suite with new validation for session interruption, collab state synchronization, and process error handling.
2026-06-28 09:52:44 +02:00
roboomp 3765d80cbc fix(coding-agent): fixed alt-m default over context
Decoupled default-role persistence from live model switching when the selected model is below the current session context window.

Updated the model selector regression coverage so the Alt+M Default action remains selectable and advances to thinking selection.

Fixes #3708
2026-06-28 07:04:31 +00:00
can1357 1852329c8c feat(coding-agent): added compact status line thinking level setting
- Added `statusLine.compactThinkingLevel` setting to render the thinking level as a leading icon.
- Replaced the verbose ` · <level>` suffix with a single glyph when compact mode is enabled.
- Updated the status line controller and component to resolve and propagate the new configuration.
2026-06-28 08:04:55 +02:00