Commit Graph
3727 Commits
Author SHA1 Message Date
roboomp f2db96c819 fix(coding-agent): assemble bracketed pastes across stdin chunks before routing
Address PR #3602 review feedback from chatgpt-codex-connector:
when the terminal fragments a bracketed paste across stdin chunks
(\x1b[200~ in one read, \x1b[201~ in the next — Windows Terminal
under load, certain SSH muxes, tmux extended-keys passthrough),
the previous single-chunk `isEmptyBracketedPaste` /
`extractBracketedImagePastePaths` guards never saw both markers
in the same `handleInput` call. The inherited
`BracketedPasteHandler` then buffered the run as a zero-length
text paste and Cmd+V still disappeared.

CustomEditor now owns its own BracketedPasteHandler that runs
ahead of `super.handleInput`, so split bracketed pastes resolve
to a single assembled payload before any routing decision:

- empty payload -> onPasteImage (Cmd+V macOS image-only screenshot)
- image-file paths -> onPasteImagePath (#3506 also gains split-chunk
  coverage as a bonus)
- everything else -> base editor's public `pasteText` so the
  `[Paste #N]` markers, autocomplete, and undo state stay intact

Removed the now-redundant single-chunk `isEmptyBracketedPaste`
helper. New repro tests cover the split-chunk empty paste, the
split-chunk image-file path, and a split-chunk text paste
forwarding exactly once to the base editor.
2026-06-26 23:50:59 +00:00
roboomp 4e5d3eb799 fix(coding-agent): restrict empty-paste fallback to strict zero-length payloads
Address PR #3602 review feedback from chatgpt-codex-connector:
a whitespace-only bracketed paste carries real user content
(indentation, blank-line padding) and must reach the editor as
literal whitespace. The prior 'trim().length === 0' guard treated
whitespace pastes the same as empty pastes and routed them to the
clipboard-image reader, which in SSH/headless sessions silently
replaced the whitespace with a 'Clipboard is empty' diagnostic.

isEmptyBracketedPaste now matches only strict zero-length payloads
('\x1b[200~\x1b[201~'). Whitespace pastes flow through to the
normal text-paste path; empty pastes still route to onPasteImage so
Cmd+V on an image-only macOS clipboard keeps working.

The whitespace-only test case is flipped to assert the preservation
contract instead of the hijack path.
2026-06-26 23:39:45 +00:00
roboomp d1baf6ab20 style: bun run fix 2026-06-26 23:39:45 +00:00
roboomp 7d655fcfdc fix(coding-agent): attach clipboard image on empty bracketed paste
macOS terminals (iTerm2, Terminal.app, Warp, Ghostty without OSC 5522,
…) intercept Cmd+V and read NSPasteboardTypeString first. For an
image-only clipboard (Cmd+Shift+5 screenshot saved to clipboard, Chrome
image copy, …) that read returns empty, so the terminal forwards a
complete-but-empty bracketed paste — '\x1b[200~\x1b[201~' — to the app.
CustomEditor.handleInput inserted that empty payload and the keystroke
disappeared, forcing users back to Ctrl+V (which is never intercepted
and already routes through handleImagePaste).

Add isEmptyBracketedPaste and route a complete, empty-or-whitespace-only
bracketed paste through the same onPasteImage smart reader the
app.clipboard.pasteImage keybind uses, so Cmd+V attaches the clipboard
image (or falls back to the #1628 smart text paste / 'clipboard is
empty' diagnostic) instead of silent nothing. Bracketed pastes carrying
any text (including the explicit image-file path branch from #3506)
keep their existing routing.

Fixes #3601
2026-06-26 23:39:45 +00:00
can1357 71e044cfe1 feat(coding-agent): added Gemini reasoning runaway detection and interruption
- Implemented a monitoring system to identify Gemini model runaway behavior during thinking steps using consecutive header detection.
- Introduced a configurable tool-call reminder prompt to inject corrective context when reasoning stalls.
- Added session-level logic to automatically interrupt and prune stalled assistant turns from the conversation history.
- Provided comprehensive test coverage for the detection logic and stream interruption scenarios.
2026-06-27 01:01:02 +02:00
can1357 ae1650d689 refactor: renamed search and find tools to grep and glob
- Renamed the `find` and `search` tools to `glob` and `grep` respectively across the codebase to improve command clarity.
- Implemented full-stack support for the renamed tools, including CLI arguments, system prompts, SDK exports, and tool registration.
- Added automated migration logic in `settings` to transform legacy `find` and `search` configuration keys to their new equivalents.
- Updated the `collab-web` renderer registry to ensure backwards compatibility with legacy tool outputs.
2026-06-27 00:57:55 +02:00
can1357 53af82d539 fix(coding-agent/tools): removed the enforced minimum length for the
- Removed the enforced minimum length for the `items` array in the tool schema to prevent unnecessary validation errors on operations that ignore the field.
- Added tests to verify schema acceptance of empty `items` arrays and confirmed that runtime errors are still correctly thrown for empty inputs during specific operations like `append`.
2026-06-27 00:44:45 +02:00
can1357 eb4a02433c refactor: consolidated json parsing and stream utilities
- Centralized JSON parsing and stream processing logic by moving utilities from `packages/ai` to the shared `@oh-my-pi/pi-utils` package.
- Standardized import paths for JSON parsing and streaming across the agent, ai, and coding-agent packages.
- Refactored SSE stream handling to use consolidated `parseStreamingJson` logic and introduced robust error recovery for malformed container-shaped tail events.
- Cleaned up legacy bundled registry references and updated related module exports and tests to reflect the new utility structure.
2026-06-27 00:11:42 +02:00
can1357 2c20a2d368 Fix subagent yield abort cleanup
(cherry picked from commit e22673537f7cc95920cd4ec75d2a4b36d81d7626)
2026-06-26 23:43:03 +02:00
Wolfgang Schoenbergerandcan1357 261b7b6d00 fix(coding-agent): treat disabled compaction continue as dead-end
(cherry picked from commit c55b9885e012baec1ca02da8ab292699daf5e77a)
2026-06-26 23:42:51 +02:00
Wolfgang Schoenbergerandcan1357 e7be60929f fix(coding-agent): block follow-up continuations after compaction dead-end
(cherry picked from commit aefb744d04a6401f999bab9f7f5b11ca9bd05ad8)
2026-06-26 23:42:51 +02:00
Wolfgang Schoenbergerandcan1357 8558eb0359 style(coding-agent): format compaction progress guard test
(cherry picked from commit 74e62c0822a7507fe6ea8c3461da65b6468177d3)
2026-06-26 23:42:51 +02:00
Wolfgang Schoenbergerandcan1357 6958b86822 fix(coding-agent): treat at-band residual as compaction headroom
The post-maintenance headroom guard returned residualTokens < triggerContextTokens
as a secondary check after the recovery-band test. When stale/tool-output pruning
already drove the trigger (postMaintenanceContextTokens) below the band before this
pass, that strict-less comparison made a residual which merely held the line at/under
the band report a false no-progress, suppressing a valid auto-continue and emitting a
spurious warning even though the next turn could no longer re-trip threshold compaction.

The recovery band sits strictly under the compaction threshold, so reaching it already
guarantees the next turn cannot re-trip. Make the band authoritative (residual <= band)
and drop the trigger argument. Adds a regression covering the sub-band trigger case.

(cherry picked from commit 31cf2dc7a30c4134f7a351d61065eca76543f154)
2026-06-26 23:42:51 +02:00
Wolfgang Schoenbergerandcan1357 ed418324c3 fix(coding-agent): drain queued messages after stalled compaction
(cherry picked from commit c2197e41d333e9018bbb9f1993e552cd582df411)
2026-06-26 23:42:50 +02:00
Wolfgang Schoenbergerandcan1357 699e07fea7 fix(coding-agent): separate overflow-retry fit check from auto-continue band
Addresses PR #3412 review (roboomp blocking + codex P2 + Copilot nits):

- The overflow/incomplete retry no longer reuses the COMPACTION_RECOVERY_BAND
  hysteresis. Reusing it required residual context below 0.8×threshold, which
  turned a recoverable overflow (e.g. 150k on a 200k window, under the ~170k
  threshold) into a manual dead-end. Add #compactionCreatedRetryFit, which
  measures the rebuilt prompt against the usable fit budget
  (contextWindow - effectiveReserveTokens) and is evaluated AFTER the failed
  assistant is dropped, so the just-failed turn is excluded.
- The threshold auto-continue keeps the stricter recovery-band check
  (#compactionCreatedHeadroom) — that path is the snapcompact thrash guard.
- Split the no-progress warning so each path warns on its own signal.
- Alias errorIsFromBeforeCompaction as assistantPredatesCompaction in the
  threshold-usage path for clarity; de-duplicate the rationale comment.

Adds two regression tests (recoverable overflow retries; non-fitting overflow
pauses + warns), mutation-verified against the band-vs-fit split.

(cherry picked from commit f8cf45b2740f04d8776a84521ba563b779d65b25)
2026-06-26 23:42:50 +02:00
Wolfgang Schoenbergerandcan1357 6a55205b68 fix(coding-agent): stop auto-compaction thrash when a single turn exceeds the threshold
prepareCompaction keeps the most-recent turn verbatim (findCutPoint never
cuts at tool results), so when that single turn already exceeds the
compaction threshold the rewritten context stays above threshold. The
context-full / snapcompact auto-compaction success tail scheduled the
agent-authored auto-continue (and the overflow/incomplete retry)
unconditionally, so the next agent_end re-entered #checkCompaction over
the same oversized tail and re-fired forever.

This is the residual loop left after #3247 capped snapcompact's own frame
projection: once #computeSnapcompactMaxFrames drops the frame cap below
one frame, snapcompact is skipped and the context-full summarizer path
still creates no headroom, so the loop persists on that path.

- #runAutoCompaction now gates the continuation and the overflow/
  incomplete retry on a post-maintenance headroom check
  (#compactionCreatedHeadroom), reusing the shake recovery-band
  hysteresis from #2275 (consolidated as the shared
  COMPACTION_RECOVERY_BAND). When a pass frees too little it pauses
  automatic maintenance and emits a single warning instead of looping.
- The post-turn threshold check ignores an assistant's stale
  pre-compaction usage so the scheduled auto-continue can't re-trip on
  the kept assistant's old high token count.

Adds a regression test covering the no-headroom (pause + warn, no
continuation) and headroom (auto-continue, no warn) paths; both
assertions are mutation-verified against the guard.

(cherry picked from commit 6fcbbe2b3075827ee621acaee8efa2c586eedd3e)
2026-06-26 23:42:50 +02:00
can1357 c50af68125 Merge PR #3594: fix(session): prune classifier refusals from context (@roboomp) 2026-06-26 23:42:15 +02:00
can1357 363d5ca6c5 test: cover empty usage metadata scope fallback 2026-06-26 23:27:57 +02:00
can1357 38e189d88c test(coding-agent): cover TUI usage remainingFraction bars 2026-06-26 23:27:57 +02:00
can1357 ab7c1829e7 fix: respect focused session thinking toggle 2026-06-26 23:27:50 +02:00
can1357 665b5dd16c add-jpeg-resize-fallback-regression-test 2026-06-26 23:27:50 +02:00
can1357 1ed343d9a4 Merge PR #3595: fix(agent): stop replaying provider refusals (@roboomp) 2026-06-26 23:27:40 +02:00
can1357 6a83a27e91 Merge PR #3314: fix(tui): auto-hide provider thinking blocks when thinking is off (@oldschoola) 2026-06-26 23:27:40 +02:00
can1357 2e3479a045 Merge PR #3334: fix(coding-agent): detect CMakeLists.txt language by basename (@oldschoola) 2026-06-26 23:27:39 +02:00
can1357 a355c05261 Merge PR #3178: fix(tui): keep partial SSH results in pending chrome (@roboomp) 2026-06-26 23:27:39 +02:00
can1357 772a1d454f Merge PR #3585: fix(coding-agent): report screenshot fallback dimensions (@roboomp) 2026-06-26 23:27:39 +02:00
can1357 7771553265 Merge PR #3584: fix(mcp): strip harness intent field at MCP tools/call boundary (@roboomp) 2026-06-26 23:27:39 +02:00
can1357 aa2d55737b Merge remote-tracking branch 'origin/farm/3d30aa66/snapcompact-local-fallback' 2026-06-26 22:49:15 +02:00
roboomp 061c0ffb43 fix(compaction): kept snapcompact local on preflight failure
Stopped snapcompact preflight failures from falling through to the provider-backed LLM summarizer and covered manual plus auto compaction paths.

Fixes #3599
2026-06-26 20:37:50 +00:00
can1357 c1a0c968b0 feat(coding-agent): changed inlineToolDescriptors to a three-way enum
- Changed `inlineToolDescriptors` from a boolean to a three-way enum (`auto` | `on` | `off`) to allow per-model defaults.
- Implemented `auto` logic which defaults to inlining descriptors specifically for Gemini models.
- Added a migration to automatically map existing boolean values to `on` or `off` to maintain backward compatibility.
2026-06-26 22:29:28 +02:00
can1357 132f28dd11 fix(coding-agent): prevented duplicate IRC broadcast messages in transcript
- Suppressed main-UI relay for sibling broadcast legs when the main agent is a direct target.
- Added `suppressRelay` option to `IrcBus.send` to allow selective disabling of relay rendering.
- Ensured broadcast fan-outs avoid rendering the same message twice in the main transcript.
2026-06-26 22:25:38 +02:00
can1357 52b8fb1565 feat(coding-agent): improved session title casing logic
- Updated `normalizeGeneratedTitle` to reconcile model-generated titles against the user's input instead of forcing title-case.
- Added logic to restore distinctive proper-noun casing (e.g., `TinyVMM`) and flatten model-generated camelCase artifacts (e.g., `dAemon`) that do not appear in the user's message.
- Ensured model-cased proper nouns that are not in the source message (e.g., `GitHub`) are preserved.
2026-06-26 20:27:40 +02:00
roboomp 11c96c9ae3 fix(session): preserved refusal stop payloads
Passed the settled assistant message into session_stop emission so refusal-as-error turns can be pruned from replay context without hiding their stop details from extension hooks.

Expanded the refusal regression test to assert the session_stop payload still exposes the refusal as last_assistant_message.

Fixes #3591
2026-06-26 18:06:09 +00:00
roboomp 22f43b26ae fix(agent): preserved refusals in summaries
Scoped provider-refusal filtering to live replay so compaction and snapcompact summaries retain the refused turn while outbound provider context still drops the refusal.

Fixes #3592
2026-06-26 18:04:34 +00:00
roboomp db61ca0274 fix(session): kept session_stop hooks on classifier refusals
Removed the early return after refusal pruning so the agent_end tail still reaches `#emitSessionStopEvent`, restoring `session_stop` extension hooks (block/continue/telemetry) for refusal-as-error stops.

Regression test wires an extensionRunner with a session_stop handler and asserts it fires for both the refusal turn and the following clean turn.

Fixes #3591
2026-06-26 17:59:26 +00:00
roboomp d68980fe58 fix(agent): stopped replaying provider refusals
API-level refusals now stay visible as terminal errors without being sent back as assistant dialogue on the next provider request. Added core and coding-agent conversion coverage for Anthropic refusal metadata.

Fixes #3592
2026-06-26 17:56:07 +00:00
roboomp fbcc157b75 fix(session): pruned classifier refusals from context
Stopped API-level classifier refusal messages from being persisted or replayed as assistant dialogue after the failed turn settles.

Fixes #3591
2026-06-26 17:53:48 +00:00
can1357 51779aeefd chore: bump version to 16.1.23
Fixed a non-deterministic gc-cli archive test: archive-me and keep-recent
shared ageDays:90, so their mtimes tied within a millisecond on fast CI and
the retainNewestGlobal:1 'keep newest' pick fell back to readdir order,
archiving the wrong session. Give keep-recent ageDays:60 (still cold-eligible,
unambiguously newer).
2026-06-26 18:43:32 +02:00
roboomp 830e99400d fix(coding-agent): reported fallback image dimensions
Read PNG/JPEG headers when Bun.Image rejects a screenshot so browser results keep real dimensions and surface the unresized fallback.

Fixes #3577
2026-06-26 16:23:22 +00:00
roboomp bd51aee5fc fix(mcp): strip harness intent field at MCP tools/call boundary
OMP injects `INTENT_FIELD` (`i`) into every tool's wire schema. The direct

model tool-call path strips it via `extractIntent` in agent-loop, but the

eval `tool.*` bridge forwards args verbatim, so strict-schema MCP servers

(Linear, anything with `additionalProperties:false` / Zod `.strict()`)

rejected every call with `-32602 unrecognized_keys: ["i"]`. The eval

bridge surfaced the rejection as `hasError: true` instead of throwing, so

batch callers reading the value as success silently mutated nothing.

Move the strip to the MCP boundary so it owns the contract regardless of

caller: `MCPTool.execute` / `DeferredMCPTool.execute` route params through

a new `prepareOutboundArgs` that runs `stripHarnessIntent` before

`omitUnusedOptionalArgs`. `stripHarnessIntent` leaves `i` in place when

the server's own `inputSchema.properties` declares it, so a server that

legitimately uses `i` as a parameter is unaffected.

Fixes #3575
2026-06-26 16:17:58 +00:00
can1357 5d4203d52b fix(coding-agent): preserved resume scoping after PR merges 2026-06-26 17:17:43 +02:00
can1357 d07d03d2af Merge PR #3565: compact long tool loops mid-turn (@riverpilot) 2026-06-26 17:12:09 +02:00
can1357 b6b0379a3b Merge PR #3540: manual coding-agent GC command (@Kenmege)
# Conflicts:
#	packages/coding-agent/test/issue-3461-repro.test.ts
2026-06-26 17:09:24 +02:00
can1357 80c6528c93 fix(coding-agent): resolved PR 3562 merge fallout 2026-06-26 17:08:53 +02:00
can1357 40e56a6318 Merge PR #3562: resume by ID, Nix/Mermaid highlighting (@arg3t)
# Conflicts:
#	packages/coding-agent/test/issue-3461-repro.test.ts
2026-06-26 17:07:48 +02:00
Alexander Kirilin e9530895a1 Merge remote-tracking branch 'origin/main' into fix/mid-turn-auto-compaction-3525 2026-06-26 11:02:40 -04:00
Alexander Kirilin d2b6bde571 fix(agent): preserve mid-turn tool persistence order 2026-06-26 10:57:36 -04:00
can1357 55b02a568d feat(coding-agent): improved local artifact sandbox handling and path recovery
- Enabled tag-based path recovery for artifacts within the session `local://` sandbox.
- Restructured `hashline` path recovery logic to ensure preflight validation runs on resolved paths.
- Prevented ACP editor buffer routing for session `local://` sandbox artifacts.
- Added comprehensive tests covering sandbox target identification and recovery for bare file names.
2026-06-26 16:39:48 +02:00
can1357 bf110f9a18 feat(coding-agent): updated plan-mode guidance for block-level edits
- Added instructions for writing sections as cohesive multi-line blocks when performing edit operations.
- Clarified that block operations require multi-line sections to avoid falling back to standard editing behavior.
2026-06-26 16:20:05 +02:00
can1357 cf7894ffa1 Merge remote-tracking branch 'origin/farm/2a4ef5fb/use-default-role-for-fresh-startup' 2026-06-26 16:14:50 +02:00