Commit Graph

5626 Commits

Author SHA1 Message Date
can1357 9fae4fb64d Merge pull request #2160: fix(mcp): accept manual OAuth redirect input 2026-06-10 08:26:58 +02:00
can1357 e19f2f689c Merge pull request #2147: fix(coding-agent): hide secrets in provider requests 2026-06-10 08:26:58 +02:00
can1357 4c71da5ebc Merge pull request #2094: fix(coding-agent): cache status line context usage 2026-06-10 08:26:57 +02:00
can1357 c03075c9ae Merge pull request #2083: fix(coding-agent): broke runaway edit loops and capped bash artifact spew 2026-06-10 08:26:57 +02:00
can1357 b3ed88d398 Merge pull request #2076: fix(coding-agent): prefer daemonizing CLI clipboards over arboard on Linux 2026-06-10 08:26:57 +02:00
can1357 26c6326f52 Merge pull request #2052: fix(acp): emit extension-registered commands in available_commands_update 2026-06-10 08:26:57 +02:00
can1357 af01abef32 Merge pull request #2019: feat(coding-agent): add provider setup command 2026-06-10 08:26:57 +02:00
can1357 5187dc1a7b fix(acp): skip colon-namespaced extension commands shadowed by builtins
parseSlashCommand treats ':' as a name/args separator, so an extension
command like 'model:foo' was advertised in available_commands_update but
dispatched to the '/model' builtin. Filter such names via
isAcpBuiltinShadowedName, and fix the FakeAgentSession prompt stubs in
acp-agent.test.ts to return true now that AgentSession.prompt() reports
whether the agent was invoked (6 tests were failing against the new
early-finish path).

Addresses review feedback on #2052.
2026-06-10 08:26:08 +02:00
Theo Mathieu 416c9947bd fix(acp): finish prompt turn when extension/custom command is handled locally
Extension commands (e.g. /sonnet) and TypeScript custom commands that
consume the input without calling the LLM return early from
session.prompt() with no agent turn. In ACP mode this left the pending
prompt promise unresolved, hanging the client forever.

Change session.prompt() to return Promise<boolean>: true when the LLM
was invoked, false when the command was fully handled locally.
#runPromptOrCommand calls #finishPrompt immediately on a false return so
the ACP turn completes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 08:26:07 +02:00
Theo Mathieu b0063a08f0 fix(acp): include builtin aliases in reserved-command filter for extensions
ACP_BUILTIN_SLASH_COMMANDS only carries primary names; the reserved set
passed to getRegisteredCommands was therefore missing aliases like
"models" (/model) and "force:" (/force). An extension registering one
of these aliases would appear in the palette but the builtin would win
at dispatch time (lookupBuiltinSlashCommand searches aliases too).

Export ACP_BUILTIN_RESERVED_NAMES from acp-builtins — the union of all
primary names and aliases for ACP-surfaced builtins — and use it as the
reserved set. Widen getRegisteredCommands parameter to ReadonlySet since
it only calls .has().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 08:26:07 +02:00
Theo Mathieu d8db20cb0d fix(acp): advertise extension commands before custom TS commands
Dispatch in AgentSession runs #tryExecuteExtensionCommand before
#tryExecuteCustomCommand, so the palette must reflect the same order.
Moving the extension-runner block before session.customCommands ensures
that on a name collision the advertised command matches what will
actually execute.

Update the test to assert the extension description wins over the
colliding custom TS description.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 08:26:07 +02:00
Theo Mathieu 0d67407773 fix(acp): address review comments on extension-commands PR
- Update ordering comment in #buildAvailableCommands to document the
  extension tier and explain why skills/custom TS commands intentionally
  shadow extension commands (unlike interactive mode)
- Add CHANGELOG entry under [Unreleased]
- Add regression test: verifies extension commands surface in
  available_commands_update and that a builtin-colliding extension
  command is excluded via the reserved-set, with no duplicates

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 08:26:07 +02:00
Theo Mathieu f6ff54bb75 fix(acp): emit extension-registered commands in available_commands_update
`#buildAvailableCommands` was omitting commands registered by extensions
via `extensionRunner.getRegisteredCommands()`. ACP clients (e.g. Zed)
never saw these in the `available_commands_update` notification, so they
couldn't forward the corresponding slash commands to the agent.

Mirrors the interactive-mode pattern: pass ACP builtin names as the
reserved set so extensions cannot shadow core commands.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 08:26:07 +02:00
can1357 ccf495441a style(coding-agent): drop stray blank line from rebase conflict resolution
Addresses rebase cleanup on #2076.
2026-06-10 08:26:06 +02:00
roboomp d4ce2a00cb fix(coding-agent): prefer daemonizing CLI tools over arboard for Linux clipboard
The native arboard backend cannot retain X11 / Wayland selection ownership
after the calling process exits, and for short-lived napi calls it can drop
ownership before any consumer sees the selection — leaving the clipboard
empty even though set_text returned success. tmux + QTerminal made this
visible because OSC 52 is also dropped by libqtermwidget, so both backends
fail and the UI's 'Copied to clipboard' status reads as a lie.

utils/clipboard.ts now:
- Tries wl-copy / xclip / xsel before arboard on Linux. These CLIs fork
  after reading stdin and serve the selection until another app claims it,
  so the payload survives our process exit.
- Honors OMP_CLIPBOARD_COMMAND as a shell-string escape hatch (e.g.
  `xclip -selection clipboard -in -silent`).
- Logs a single warning when every backend fails, so the silent-success
  regression from #2075 cannot recur unnoticed.

Tests assert dispatch order: Linux+X11 prefers xclip, Wayland prefers
wl-copy, xclip→xsel fallback works, all-fail falls back to native,
macOS still goes straight to native, and OMP_CLIPBOARD_COMMAND wins
over the CLI chain.

Fixes #2075
2026-06-10 08:26:05 +02:00
can1357 ec81b927fa fix(coding-agent): redact ephemeral side-channel context and preserved remote compaction history
runEphemeralTurn (IRC//btw) called streamSimple directly with the raw
system prompt, bypassing the SDK-level obfuscateProviderContext wrapper;
and #obfuscatePreparationForProvider skipped previousPreserveData, so a
pre-fix openaiRemoteCompaction.replacementHistory could resend raw
secrets on the next remote compaction.

Addresses review feedback on #2147.
2026-06-10 08:26:02 +02:00
roboomp d39e4b0d38 fix(coding-agent): hid previous compaction summary
Obfuscated preparation.previousSummary, hook prompt/context, before forwarding to compact() so prior pi- or extension-supplied summaries do not leak verbatim secrets on subsequent compactions.

Fixes #2146
2026-06-10 08:26:02 +02:00
roboomp 5517115f1a fix(coding-agent): hid handoff instructions
Obfuscated custom instructions before handoff and related side-request provider calls, then deobfuscated generated handoff output before persistence.

Fixes #2146
2026-06-10 08:26:02 +02:00
roboomp aa4cd0ab2d fix(coding-agent): preserved tool schemas while redacting
Converted provider-facing tool parameters to wire JSON Schema before redaction so live Zod instances are not deep-cloned into plain objects.

Fixes #2146
2026-06-10 08:26:02 +02:00
danzaio 7db4d143e1 fix(mcp): wire manual OAuth abort signal 2026-06-10 08:26:01 +02:00
Matt Anger 5f084acbdc feat(coding-agent): watch reftable directory instead of tables.list to survive atomic renames 2026-06-10 08:26:01 +02:00
roboomp 2a90108893 fix(coding-agent): hid secrets in provider requests
Redacted configured secrets across provider-facing system prompts, tool definitions, developer reminders, and assistant tool-call payloads before LLM requests.

Fixes #2146
2026-06-10 08:26:01 +02:00
Matt Anger 91ff632d6a feat(coding-agent): verify HEAD before resolving reftable HEAD commit 2026-06-10 08:26:01 +02:00
Matt Anger b5b6424e7a feat(coding-agent): strip comments before matching section headers in git config 2026-06-10 08:26:01 +02:00
Matt Anger 4943d8d639 feat(coding-agent): use git rev-parse --verify when resolving reftable refs 2026-06-10 08:26:01 +02:00
Matt Anger c99751ac43 feat(coding-agent): strip adjacent git config comments 2026-06-10 08:26:01 +02:00
Matt Anger d26bb4e331 feat(coding-agent): watch linked worktree reftable stack for HEAD switches 2026-06-10 08:26:01 +02:00
can1357 f54aa7bf60 fix(coding-agent): move changelog entry to Unreleased section
Addresses review feedback on #2094: rebase onto current main landed the
entry inside the released 15.9.67 section.
2026-06-10 08:26:00 +02:00
can1357 9988c1ca7e fix(coding-agent): align bash renderer cache slot with readonly render output
main's CachedOutputBlock.render now returns readonly string[]; the
cache slot added by this PR was still mutable, failing check:types.

Addresses review feedback on #2083.
2026-06-10 08:26:00 +02:00
danzaio 314cea633a fix(mcp): preserve existing manual login waits 2026-06-10 08:26:00 +02:00
Matt Anger 2e31abcc16 feat(coding-agent): address PR comments and improve reftable support 2026-06-10 08:26:00 +02:00
ben af98154b9e fix(coding-agent): cache status line context usage 2026-06-10 08:26:00 +02:00
can1357 dbf1be2096 fix(coding-agent): count head-retained bytes against the artifact cap
After rebasing onto a13e9827f, #createFileSink's head-retention flush
wrote directly to the sink, bypassing #emitToSink's budget accounting —
the on-disk artifact could grow past artifactMaxBytes by up to the head
window. Route the flush through #emitToSink and pin it with a
regression test (fails 24B vs 16B cap without the fix).

Addresses review feedback on #2083.
2026-06-10 08:26:00 +02:00
handlecusion 8b6c1f97af fix: address setup command review 2026-06-10 08:26:00 +02:00
danzaio 8e6f6c13e5 fix(mcp): cancel manual OAuth waits on timeout 2026-06-10 08:26:00 +02:00
Matt Anger 65c56db2f5 test(coding-agent): pin the initial branch to main in the reftable test 2026-06-10 08:26:00 +02:00
roboomp e18a8649f0 fix(coding-agent): suppressed artifact truncation notice when nothing was elided
Codex review on PR #2083 caught a corruption case in `OutputSink`:
when a stream exceeds `artifactHeadBytes` but still fits below
`artifactMaxBytes`, post-head bytes flow into the tail ring without any
eviction (`droppedBytes === 0`) — yet `#flushArtifactTailIfCapped`
unconditionally injected `[ARTIFACT TRUNCATED: kept first … + last … of
…; 0 B elided from the middle]` between head and tail. The resulting
artifact-on-disk is then no longer verbatim and falsely advertises
truncation for outputs that actually fit. With the default 4 MiB / 3 MiB
split, every ~3–4 MiB bash capture in this band tripped the bug.

The notice is now gated on `droppedBytes > 0`. The tail ring is still
flushed unconditionally so head + tail still equal the verbatim stream
in this band. Regression pinned by a new test in
`test/streaming-output.test.ts` that pushes 24 bytes into a 16-head /
16-tail cap and asserts the file equals the payload byte-for-byte with
no `[ARTIFACT TRUNCATED:` marker.

Refs #2081
2026-06-10 08:26:00 +02:00
handlecusion f61cd7aad0 feat(coding-agent): add provider setup command 2026-06-10 08:26:00 +02:00
danzaio 3b47ee93e9 fix(mcp): accept manual OAuth redirect input 2026-06-10 08:26:00 +02:00
Matt Anger 08982932b2 feat(coding-agent): add support for git reftables 2026-06-10 08:26:00 +02:00
roboomp f17733570e perf(coding-agent): cached bash result renderer to stop per-keystroke restyle
Follow-up to the loop guard + artifact cap that addressed the root cause
of issue #2081's runaway captures. The reporter then noted Ctrl+X/Ctrl+C
remaining unresponsive — confirming the secondary symptom: per-keystroke
TUI repaints walked every visible bash row and re-ran `split` /
`replaceTabs` / `truncateToVisualLines` over the stored output. With a
1,000+ message transcript and a 50KB-tail per row, that string work was
what pinned the main thread, not the loop itself.

The eval renderer already caches its computed lines keyed by `(width,
previewLines)` — see `eval-render.ts:709-752`. Mirrored that pattern in
the bash result renderer with a slightly wider key (`width`,
`previewLines`, `expanded`, `rawOutput`, `isPartial`) so the cache is
busted whenever any input that affects the produced lines actually
changes. `invalidate()` continues to clear `CachedOutputBlock` and now
also clears the lines cache, so callers that already drive invalidation
keep working unchanged.

A render() with cache-equivalent inputs is now an array-reference
return; the `CachedOutputBlock` round trip is skipped entirely. New
test in `test/tools/bash-sixel-render.test.ts` pins the contract:
identical inputs → same array reference; width change → cache miss;
invalidate() → fresh array.

Refs #2081
2026-06-10 08:26:00 +02:00
roboomp 77a68b1070 fix(coding-agent): broke runaway edit loops and capped bash artifact spew
Two pathologies surfaced in the same captured failure (#2081): a subagent
spent 16 minutes hammering 205 `edit` calls (182 byte-identical no-ops)
against a file that already matched its payload, while a sibling bash
invocation persisted 7.6MB of PowerShell rich-object metadata to
`~/.omp/agent/artifacts/<id>.bash.log` from what was intended as a small
tail. Both are addressed independently here:

- Hashline executor now consults a per-ToolSession `noopLoopGuard` that
  hashes the raw patch input and tracks consecutive no-ops per canonical
  path. After NOOP_HARD_LIMIT (3) repeats of the same payload the soft
  "byte-identical" hint escalates to a thrown ToolError, which the agent
  loop surfaces as a tool failure rather than success-with-text — far
  more effective at breaking the loop than the soft hint alone. A
  non-noop commit (or any variant payload) resets the counter; state is
  isolated per ToolSession so subagents cannot inherit each other's
  history.
- OutputSink artifact-on-disk writes are now bounded by
  `artifactMaxBytes` (default 4 MiB = 3 MiB head + 1 MiB rolling tail).
  Once the head budget is exhausted, subsequent chunks divert into a
  fixed-size tail ring; `dump()` replays the ring behind a single
  `[ARTIFACT TRUNCATED: kept first … + last … of …; … elided from the
  middle]` notice before closing the sink. Setting `artifactMaxBytes: 0`
  restores the historical unbounded behavior. Sized comfortably above
  anything a model would reasonably scroll through via the artifact URL
  scheme while preventing the captured 7.6MB spray from sitting on disk.

The terminal-typing lag the reporter observed has multiple compounding
causes (transcript-render freezing is disabled on win32; the bash result
renderer lacks the per-render cache that the eval renderer already has).
Those land in a follow-up — the loop guard + artifact cap address the
root pathologies that turned the session into a multi-MB transcript in
the first place.

Fixes #2081
2026-06-10 08:26:00 +02:00
can1357 4824c58132 fix(coding-agent/edit): hid the preview label on expanded streaming diffs
The streaming-spinner relocation in 61a57c1d2 re-added the trailing
"(preview)" label to expanded approval previews whenever a spinner frame
was active, breaking the #1992 contract. Expanded previews now drop the
label but keep the animated glyph so the volatile tail stays live.
2026-06-10 08:04:48 +02:00
can1357 d616fbf991 chore: bump version to 15.10.11 2026-06-10 07:50:54 +02:00
can1357 661587e110 feat(coding-agent): raised retry limits to ten with capped exponential backoff
- Raised Anthropic provider retries to 10 attempts and used a shared jittered exponential backoff for each retry.
- Updated coding-agent retry defaults and session delay calculation to a 500ms base with an 8,000ms jittered cap.
- Added tests that verify capped ten-step backoff sequences and recovery after repeated 502 errors.
2026-06-10 07:49:12 +02:00
can1357 15fc5af5e1 chore: update changelogs 2026-06-10 07:28:05 +02:00
can1357 529706c368 Merge remote-tracking branch 'origin/farm/d501d509/modelroles-comma-fallback' 2026-06-10 07:26:15 +02:00
can1357 61a57c1d21 fix(coding-agent): stabilized streaming TUI rendering with readonly rows and memoized reuse
- Changed render methods to return component-owned `readonly string[]` rows.
- Added `RenderStablePrefix` row reuse to avoid repainting unchanged streaming content.
- Stabilized streaming gutters and spinner placement to reduce preview jitter and flicker.
- Finalized commit-safe transcript behavior for tool-call previews and added streaming edge-case tests.
2026-06-10 07:26:02 +02:00
can1357 53b8950072 fix(coding-agent/edit): stopped stacking adjacent diff gap markers
- Separated non-contiguous diff regions with a single blank gap row, normalized after block-context insertion.
- Rendered gap rows as one dim ellipsis in the TUI and HTML export.
- Applied the same blank-separator dedupe and edge-trimming to hashline's compact diff preview.
2026-06-10 07:23:29 +02:00
can1357 b0fec42218 feat(coding-agent): surfaced lazy LSP servers as available in welcome screen
- Added "available" status so recognized servers show under lazy mode without warmup.
- Rendered full welcome box as pre-TUI splash with fixed slot heights to avoid layout shift.
- Reported lazy servers as available in /status instead of omitting the section.
2026-06-10 07:22:22 +02:00