Commit Graph
4215 Commits
Author SHA1 Message Date
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 bea614ef64 Merge PR #4143: fix(coding-agent): fall back for Kernel field when os.version returns 'unknown' (@roboomp) 2026-07-01 21:53:18 +02:00
can1357 87a53cbe0d Merge PR #4137: fix(agent): handle already-applied patch-mode merges (@roboomp) 2026-07-01 21:53:18 +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 c704c5248f fix(rpc): wait for background bash before stdin shutdown 2026-07-01 21:53:16 +02:00
can1357 82232cefb6 Merge PR #4117: fix(rpc): dispatch bash concurrently and reset abort controller on restart (@roboomp) 2026-07-01 21:53:16 +02:00
can1357 9e64acfc93 fix(coding-agent): wait for timed-out git subprocesses 2026-07-01 21:53:16 +02:00
can1357 9e02f47748 Merge PR #4116: fix(coding-agent): bound git subprocess execution (@roboomp) 2026-07-01 21:53:16 +02:00
can1357 4cbb7afbbe Merge PR #4111: fix(edit): guard apply_patch against clobber and swallowed multi-file failures (@roboomp) 2026-07-01 21:53:15 +02:00
can1357 9ae2b48b10 Merge PR #4077: fix(agent): add retry path diagnostics (@roboomp) 2026-07-01 21:53:14 +02:00
can1357 edef5c052d Merge PR #4056: fix(tui): smooth write streaming previews (@roboomp) 2026-07-01 21:53:14 +02:00
can1357 09dc1f0139 fix(collab): handle pending guest ui requests 2026-07-01 21:53:00 +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 c982cb34e9 Merge PR #3987: fix(eval): keep agent progress commit-unstable while partial (@metaphorics) 2026-07-01 21:50:55 +02:00
can1357 826517dc69 Merge PR #3969: fix: preserve bash cwd without hidden pwd probe (@jeffscottward) 2026-07-01 21:50:54 +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 aee8b091ee fix(agent): honor closed schema label edge cases 2026-07-01 21:50:54 +02:00
can1357 88e3e77f3e Merge PR #3927: fix(agent): reject stale yield labels for override schemas (@roboomp) 2026-07-01 21:50:54 +02:00
can1357 2289765840 Merge PR #3894: fix(cli): restore /copy code and /copy cmd shortcuts (@roboomp) 2026-07-01 21:50:54 +02:00
can1357 87a9b9e98e Merge PR #3891: fix(coding-agent): replay scrollback on theme changes (@lederniermagicien) 2026-07-01 21:50:53 +02:00
can1357 52003878b5 Merge PR #3865: fix(web-search): clarify DuckDuckGo bot detection failures (@roboomp) 2026-07-01 21:47:55 +02:00
can1357 2f88b1dddc test(coding-agent): cover maintenance abort diagnostics 2026-07-01 21:47:55 +02:00
can1357 38a6821729 test(coding-agent): avoid unchecked session loader casts 2026-07-01 21:47:54 +02:00
can1357 ac8ad5972b Merge PR #3849: perf(coding-agent): speed up large-session resume with Bun.JSONL (@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 00563b01dd Merge PR #3809: fix(plugins): restore legacy tool factory shim (@roboomp) 2026-07-01 21:42:26 +02:00
can1357 f3744bce8e Merge PR #3776: Fix hidden thinking glyph-only status rows (@jeffscottward) 2026-07-01 21:42:26 +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
can1357 3b80dc01de fix(tui): cap sparse ask other gaps 2026-07-01 21:42:24 +02:00
can1357 278b715ab8 Merge PR #3662: fix(tui): keep ask Other context visible (@roboomp) 2026-07-01 21:42:24 +02:00
can1357 97b72df087 fix(coding-agent): reset mid-run todo counter after stop reminder 2026-07-01 21:42:24 +02:00
can1357 2d734f65c4 Merge PR #3652: fix(coding-agent): nudge todo reconciliation mid-run instead of only at stop (@roboomp) 2026-07-01 21:42:23 +02:00
can1357 8350e4a139 fix URL search scope edge cases 2026-07-01 21:42:23 +02:00
can1357 6066814d3e Merge PR #3650: fix(tools): materialize URL paths for search scopes (@roboomp) 2026-07-01 21:42:23 +02:00
can1357 12120a1cd4 Merge PR #3647: fix(tool): require browser run code in schema (@roboomp) 2026-07-01 21:42:23 +02:00
roboomp 809a8a348d fix(tui): coalesce editor top-border rebuild to render tempo
EventController.handleEvent rebuilt the editor's status-line top border
synchronously on every session event via updateEditorTopBorder(). During
a long-running eval that fires 5-10 events/s, each rebuild ran
StatusLine.getTopBorder → #buildSegmentContext → getCachedContextBreakdown
→ session.getContextUsage → estimateTokens (with JSON.stringify per
toolCall block) — the render pipeline is throttled to ~30 fps, so most
rebuilds were dropped before painting. Combined with a scheduler that
collapsed cadenceDelay to zero whenever a frame overran the 33ms budget,
the TUI busy-looped at ~40-50% CPU.

Fix:
- Editor gains setTopBorderProvider(): a lazy builder invoked once per
  editor render. InteractiveMode installs it in the constructor and on
  setEditorComponent, so the rebuild coalesces to the render tempo
  regardless of event rate.
- Delete updateEditorTopBorder wrapper (now equivalent to
  ui.requestRender) and inline every call site.
- Add adaptive render backpressure: a frame that exceeds
  MIN_RENDER_INTERVAL_MS inflates the next scheduling delay to
  2 * last_frame_cost, capped at 200 ms, targeting a 50% render duty
  cycle instead of pinning the CPU at t=0.

New regression tests:
- editor-top-border-provider.test.ts: provider fires exactly once per
  render, wins over eager setTopBorder, falls back when cleared, gets
  the correct availableWidth.
- adaptive-render-backpressure.test.ts: cheap frames keep the 33 ms
  cadence, a slow frame idles proportionally, pathological frames are
  capped at 200 ms.

Verified with bun test packages/tui/test (all 246 relevant tests pass)
and bun test packages/coding-agent/test/modes (455 tests pass). Three
pre-existing agent-session-handoff snapcompact failures on main are
unrelated (snapcompactSupportedChars binding).

Fixes #4145
2026-07-01 13:51:43 +00:00
roboomp 80d80b6bee fix(coding-agent): fell back for kernel field when os.version returns unknown
Bun on macOS 15+ (Darwin 24/25) returns the literal string "unknown" from
os.version() when uv_os_uname() cannot populate the version field. That
value was piped straight into the <workstation> block as `Kernel:
unknown`, and the model then guessed the OS glyph from the ambiguous
signal — displaying a Windows logo on Macs.

Fall back to `${os.type()} ${os.release()}` (uname -s + uname -r, e.g.
`Darwin 25.5.0`) whenever os.version() is empty or the literal
"unknown". Linux keeps its build string when Bun returns one.

Fixes #4141
2026-07-01 13:13:27 +00:00
roboomp f2c436eb00 style: bun run fix 2026-07-01 12:17:49 +00:00
roboomp cd692bcb02 fix(agent): required forward-check failure for patch-mode no-op
Reverse-check alone can theoretically succeed via git-apply fuzz when the file carries the postimage at another location, so treating it as sufficient risked silently dropping a task patch whose intended hunk still needed to run.

Required both `--reverse --check` to succeed AND forward `--check` to fail before declaring a no-op. When both check directions succeed (ambiguous), the merge falls through to a forward apply instead of skipping — mirroring the pre-idempotence behavior. Both checks are read-only, so no worktree writes on ambiguity.

Added a spy-based regression that forces the ambiguous case and asserts the merge applies forward instead of silently dropping the change.
2026-07-01 12:17:42 +00:00
roboomp f474fa0e11 fix(agent): detected patch-mode idempotence via reverse-check
git apply --3way --check exits 0 even when the real apply would write conflict markers and unmerged index stages, so the previous fix left the worktree dirty on conflicting patches while only flipping changesApplied to false.

Dropped --3way for patch-mode merge and used a --reverse --check probe instead: it succeeds only when the target state is already present (true no-op) and reads without touching the worktree. Conflicts fall through to the normal --check + apply path, which rejects them before writing anything.

Added regression coverage for the conflict scenario asserting the worktree stays clean, and for the fresh apply path.
2026-07-01 12:06:06 +00:00
roboomp 4c9f18972c style: bun run fix 2026-07-01 11:59:11 +00:00
roboomp 66052863bb fix(agent): handled already-applied patch merges
Use git apply --3way for patch-mode isolated merge checks and applies so diff-tree patches that are already present are accepted as no-ops.

Added regression coverage for a clean already-applied binary/full-index patch.

Fixes #4135
2026-07-01 11:58:52 +00:00
roboomp 9f3e648e5a fix(coding-agent): gated :auto suffix behind allowAutoAlias
Follow-up on the review: the widened parseThinkingSuffix recognized :auto unconditionally, so parseModelString and extractExplicitThinkingSelector would silently strip a literal provider/model:auto id before the isLiteralModelId guard the :max path already uses.

- Add allowAutoAlias option and require callers to opt in, mirroring allowMaxAlias.

- MAX_THINKING_SUFFIX_OPTIONS enables both aliases; parseModelPatternWithContext still tries exact match first, so a real :auto id wins there too.

- sdk.ts (session restore x2), agent-session.ts (retry fallback selector, context-promotion/compaction targets), and model-registry.ts (normalizeSuppressedSelector) now pass allowAutoAlias: true alongside allowMaxAlias.

- Regressions: literal example/runtime:auto wins over the sentinel in parseModelPattern, parseModelString (with and without isLiteralModelId), resolveModelFromString, and extractExplicitThinkingSelector; auto is still extracted when the id isn't literal.
2026-07-01 08:30:58 +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
roboomp eb4d2a9e93 fix(rpc): dispatch bash concurrently and reset abort controller on restart
The RPC transport did not treat cancellation as an independent, resettable
control plane, so two lifecycle contract violations shared a root cause:

A. Server-side: the stdin loop in `rpc-mode.ts` awaited each commands
   `handleCommand` before pulling the next frame, so `abort_bash` queued
   behind the `bash` it must cancel. Extracted `dispatchRpcInputFrame` and
   dispatch `bash` in the background: the input loop keeps reading, so
   `abort_bash` (or any other command) can preempt an in-flight shell.
   Response correlation still rides `command.id`; ordering across
   concurrent commands is documented as not guaranteed.

B. Client-side: `RpcClient.stop()` aborted the shared `#abortController`
   but never replaced it, so a subsequent `start()` handed a pre-aborted
   signal to `readJsonl` and the stdout reader exited immediately with a
   spurious "Agent process exited before ready" while the spawned child
   leaked in `#process`. Mint a fresh `AbortController` inside `start()`
   and clean up the child on any post-spawn failure.

Adds:
- `dispatchRpcInputFrame` unit tests covering the concurrent bash + abort
  ordering, serial dispatch of other commands, and background error
  reporting.
- `RpcClient` lifecycle tests covering start->stop->start on the same
  instance (via a mock fixture agent) and retry after a failed start.
- Documents the bash concurrency contract in `docs/rpc.md`.

Fixes #4079
2026-07-01 07:15:09 +00:00
roboomp ae34cc1b1c fix(coding-agent): bounded git subprocesses
Forced non-interactive credential env for git and gh subprocesses, added a default timeout, and capped captured stdout/stderr with a truncation marker. Added regression coverage for prompt env, output capping, and timeout cleanup.

Fixes #4072
2026-07-01 07:13:23 +00:00
roboomp 15dfda45a4 fix(edit): guarded apply_patch against clobber and swallowed multi-file failures
The apply_patch language documents `*** Add File` and `*** Move to` as
strictly non-overwriting (create / rename), but the fs-level create and
rename paths in applyNormalizedPatch wrote through to the resolved target
without checking whether it already existed. Existing destinations were
silently replaced, and in the rename case the source was also deleted.

The multi-file executeApplyPatchPerFile aggregator caught each per-file
exception, appended an error entry, and kept iterating. Later files
still ran against an inconsistent post-state, and the aggregate result
had no top-level isError — so a mixed partial application looked like a
successful edit to the agent loop.

Changes:
- Add fs.exists guards before the create write and before the rename
  write/delete in packages/coding-agent/src/edit/modes/patch.ts. Both
  reject with ApplyPatchError before any side effect.
- Make executeApplyPatchPerFile in packages/coding-agent/src/edit/index.ts
  stop at the first per-file failure, list applied vs. skipped files in
  the aggregate text, and propagate isError, matching executeSinglePathEntries.
- Rename the two apply-patch scenario fixtures (010_move_..., 011_add_...)
  that pinned the buggy overwrite behavior to _rejects_ variants, and
  flip their expected/ trees so source and pre-existing destination
  remain byte-identical after the rejected apply.
- Cover both failure modes with new regressions in
  packages/coding-agent/test/core/apply-patch.test.ts and a new
  packages/coding-agent/test/core/apply-patch-multi-file.test.ts.

Fixes #4074
2026-07-01 07:05:25 +00:00
roboomp 9009d5b8f7 fix(agent): added retry path diagnostics
Logged assistant-tail removal outcomes and scheduled continuation state for transient retry failures.

Fixes #4070
2026-07-01 06:55:03 +00:00
roboomp 19f3058c55 fix(tui): extended smooth streaming previews to edit and eval
Registered `edit.input` and `eval.code` alongside `write.content` so the reveal controller decodes those top-level string arguments incrementally between throttled full-JSON parses.
Added a regression test covering multi-key extraction so the wire-up survives future additions.

Refs #4043
2026-07-01 05:32:15 +00:00