Commit Graph

1418 Commits

Author SHA1 Message Date
can1357 b3612324a6 chore: normalized changelog sections after merging community fixes 2026-07-27 05:00:04 +02:00
can1357 9d76e168ba Merge PR #6706: fix(ai): preserve custom Anthropic web-search history (@roboomp) 2026-07-27 04:58:24 +02:00
can1357 6d2a8de1bb chore: bump version to 17.1.4 2026-07-26 17:01:19 +02:00
can1357 741b32b773 refactor(agent): drop unused beforeSteeringPoll hook left over from gate split
setBeforeSteeringPoll/#beforeSteeringPoll had no callers anywhere at the PR
head (the pre-model-call gate moved to #6543, which does not reference it).
Restores hasSteeringMessages to its synchronous baseline form.
2026-07-26 15:55:40 +02:00
can1357 0d3fd6197c Merge PR #6544: feat(agent): wake steering on an event instead of polling for it (@paralin) 2026-07-26 15:55:40 +02:00
roboomp f26de4fad3 fix(agent): preserved legacy proxy terminal streams
Made finalized terminal content optional and retained the delta-reconstructed assistant content when older proxy servers omit it.

Covered both legacy done and error events so terminal cleanup remains safe and the stream resolves.

Fixes #6703
2026-07-26 13:50:34 +00:00
roboomp e26c3034f0 fix(agent): carried terminal content through proxy streams
Made proxy done and error events carry finalized assistant content so provider-only blocks survive event reconstruction.

Covered Anthropic native web-search history restored after live events omitted the opaque blocks.

Fixes #6703
2026-07-26 13:44:14 +00:00
can1357 26f89bd897 Merge PR #6556: fix(omp): fit native compaction after large tool output (@oleksoleksoleks) 2026-07-26 15:41:27 +02:00
Diogo Soares Rodrigues 9088fe821b fix(cursor): await error-drain transforms and sanitize mirrored todo labels
Two boundary defects on the mirrored-todo path.

1. The Agent error drain snapshotted #cursorToolResultBuffer without
   awaiting entry.pending, unlike #emitCursorSplitAssistantMessage. An
   async cursorOnToolResult still running when the provider errored
   patched an entry the catch path had already detached, so the
   pre-transform payload was persisted. A provider error is exactly when
   a transform is most likely to be in flight.

2. The todo renderer interpolated mirrored provider text straight into
   terminal output. A Cursor snapshot carries model-authored task
   content, phase names and summary text verbatim, so a label holding
   ANSI/C0 sequences rewrote the terminal on every render and replay.
   sanitizeText alone is not enough - it preserves tabs, which punch
   holes in bordered output - so every display path now funnels through
   one forDisplay() helper: task labels, blocker notes, phase headers,
   the zero-task fallback, and the streaming renderCall preview. Raw
   values are untouched; content and phase name are the identity keys
   the local list is looked up by and what gets persisted.
2026-07-26 09:29:13 -03:00
Diogo Soares Rodrigues eaf7a3d605 fix(cursor): pair a result for every server-resolved call
Three orphan paths, same failure mode: the assistant block is marked
kCursorExecResolved before the work runs, so agent-loop.ts emits no
placeholder for it, and any path that produces no toolResult leaves the
call unpaired — buildSessionContext then strips the whole interaction
from every rebuilt transcript.

1. resolveExecHandler returned no toolResult on three exits (no handler
   installed, handler produced nothing, handler threw). Each now pairs a
   result carrying the same text the server sees in execResult, routed
   through onToolResult like a real one. `pairing` is a required
   parameter so a new callsite cannot silently recreate the orphan.

2. Agent only installed its result-buffer sink when cursorExecHandlers
   or cursorOnToolResult was set. Both are optional, so a bare SDK host
   dropped the provider result on the floor. Installed unconditionally;
   a non-Cursor provider never calls it.

3. A todo completion frame with no tool_call (the field is optional)
   skipped settlement entirely. It now settles as "nothing to mirror".

Also fixes an empty update_todos with a nonzero total_count being
mirrored as an authoritative clear: the length guard added earlier
skipped the mismatch check for empty responses, so a partial or
size-limited merge response deleted every local task at once.
2026-07-26 09:29:13 -03:00
Diogo Soares Rodrigues a9f1e3a257 fix(agent): await pending cursor result transformers before draining
An async cursorOnToolResult that resolved after the message_end drain
had its rewrite silently discarded: the reservation kept the call from
dangling, but the late patch mutated a buffer entry the drain had
already detached, so the persisted message kept the pre-transform
payload.

Each entry now records the in-flight transformer promise, and
#emitCursorSplitAssistantMessage awaits any that are still pending
before appending and emitting. This matches the exec-channel paths,
which already await onToolResult (cursor.ts:1461).

A rejecting transformer is swallowed per-entry, so a failing hook can
neither take the turn down nor cost the reserved result.

The previous test asserted the old limitation (late rewrite NOT
persisted) and its premise is now unreachable, so it is replaced by the
rejection contract. Stale limitation notes in agent.ts and types.ts are
updated.
2026-07-26 09:29:13 -03:00
Diogo Soares Rodrigues cc210094ef fix(cursor): refuse todo dependency graphs and sanitize failure text
Two review findings on the native todo sync.

- TodoItem.dependencies is a graph the local model cannot store: rows
  are keyed by content, carry no id, and hold no edges. An imported
  dependent row files as plain pending and nextActionableTask then
  offers work the server considers blocked. Refuse snapshots with an
  edge pointing at an unfinished row; edges whose blockers already
  finished constrain nothing and still mirror.

- The todo failure warning interpolated the provider error verbatim.
  Collapse and truncate it at the render boundary.

Also documents two known, unfixed defects: an async cursorOnToolResult
transformer resolving after the buffer drain, and the todo card
lifecycle race. Emitting a synthetic tool_execution_start for the
latter was measured and rejected -- the completion deletes the entry it
creates, so the late streamed block adds a second card.
2026-07-26 09:29:13 -03:00
Diogo Soares Rodrigues ea023c380a fix(cursor): persist the phase-bearing todo result and close a buffer race
The previous commit paired every server-resolved todo block with a
result, but built that result in the provider from the flat snapshot.
`todoToolRenderer.renderResult` reconstructs the list exclusively from
`details.phases`, so the block survived the dangling-strip only to replay
as `Todo 0 tasks`.

Only the host computes that grouping -- the provider sees a flat list --
so `todoSync` now returns the result it already assembled and the
provider persists it verbatim. A refused snapshot never reaches the host,
so the provider's summary-only fallback still covers that path, and
exactly one result is emitted either way.

Separately, `Agent`'s Cursor buffering wrapper pushed its entry only
after awaiting the optional `cursorOnToolResult` transformer. The
provider dispatches decoded messages with `void handleServerMessage(...)`,
so a `message_end` from the same chunk could drain the buffer while a
transformer was still pending, dropping the result. The entry is now
reserved synchronously and patched in place when the transformer
resolves, keeping buffer order and still applying the customization.
Production is unaffected -- `sdk.ts` sets no transformer -- but the
option is supported and its contract returns a Promise.

Tests: a delayed-transformer case that loses the result without the
buffering change, and a replay case driving the persisted result through
`buildSessionContext` and asserting `details.phases` rebuilds a non-empty
list -- the id-pair assertion alone did not catch the empty render.
2026-07-26 09:29:13 -03:00
Christian Stewart d363ca0968 feat(agent): wake steering on an event instead of polling for it
While a turn is running, the loop watched for out-of-band steering by
re-checking the queue on a fixed interval. The interval sets a floor on how long
a message waits and burns a wakeup on every tick that finds nothing, and the
delay is worst exactly when it matters: a cancellation or a correction issued
during a long tool loop sits until the next tick.

Wait on the queue instead. `Agent` keeps a set of steering waiters and notifies
them whenever a message is enqueued, and the loop awaits
`waitForSteeringMessages`, re-checking only when woken. The timer path remains
for the IRC interrupt queue, which is session-owned and has no wake callback, so
nothing regresses where no event source exists.

Every wait races against local abort. The callback contract does not require an
implementation to observe the signal, and one that resolves only on the next
queue event would otherwise never settle once a batch finished, so awaiting it
during teardown would hang a batch that simply had no steer.

Which controllers a steer raises is unchanged: this is a timing change, not a
change to what an interrupt does.

Signed-off-by: Christian Stewart <christian@aperture.us>
2026-07-25 03:54:46 -07:00
Alexander Kirilin 11672ae847 fix(omp): load compaction truncation prompt from markdown 2026-07-24 22:00:38 -04:00
Alexander Kirilin 46067950d6 fix(omp): reserve maximum image compaction budget 2026-07-24 21:29:43 -04:00
Alexander Kirilin 1a0a7c3e74 fix(omp): harden native compaction fit checks 2026-07-24 21:20:47 -04:00
Alexander Kirilin 51195b2300 fix(omp): preserve compaction input when trimming fails 2026-07-24 21:07:09 -04:00
Alexander Kirilin cc336acec4 fix(omp): fit native compaction after large tool output 2026-07-24 20:16:48 -04:00
can1357 0491f2961a chore: bump version to 17.1.3 2026-07-25 01:10:32 +02:00
can1357 7ebf141743 chore: bump version to 17.1.2
- fixed rustfmt drift and clippy errors in pi-shell moreutils builtins (combine, errno, ifne, isutf8, sponge, ts) that blocked the release check gate
2026-07-24 16:53:52 +02:00
can1357 b0f1b5c0c5 Merge PR #6496: fix(ai): preserve Anthropic server-tool history (@roboomp) 2026-07-24 16:26:52 +02:00
can1357 9f8aa87dbf feat(task): removed per-call model override from task tool
- Removes `model` field from task item/schema, TaskParams, and TaskItem types.
- Removes model selector validation, formatting, and approval display logic.
- Updates task tool priority docs to reflect that model is no longer per-call overridable.
- Updates eval agent() helper docs and prompt templates to remove model parameter.
- Updates tests to reflect removal of model override capability.
2026-07-24 14:51:48 +02:00
roboomp b461b8e766 fix(agent): counted Anthropic server-tool blocks in token estimate
estimateTokens now charges for serialized anthropicServerTool blocks so context maintenance sees the server-tool payload replayed on the wire; excluded from the compaction floor like other encrypted reasoning.
2026-07-24 10:43:58 +00:00
can1357 c780662881 feat(agent): added resolveFallbackTool option for routing unadvertised tool calls
- Add `resolveFallbackTool` callback to `AgentOptions` and `AgentLoopConfig` that resolves tool calls not found in the advertised set.
- Use the callback as a third lookup step after `name` and `customWireName` match, enabling side transports like `xd://` device mounts.
- Add test coverage verifying the fallback resolves known devices and preserves "not found" errors for unknown names.
- Wire the coding agent's device registry as `resolveFallbackTool` in both `createAgentSession` and `streamAgentSession` paths.
2026-07-24 12:18:17 +02:00
roboomp 07fcec1e68 fix(ai): preserved Anthropic server-tool history
Persisted native server-tool calls and web-search results in assistant content, replayed them only to the issuing Anthropic provider, and retained Umans gateway filtering.

Fixes #6495
2026-07-24 08:49:43 +00:00
can1357 c36826cbac chore: bump version to 17.1.1 2026-07-24 09:18:41 +02:00
can1357 17735c7786 feat: added x-oai-attestation header for ChatGPT-OAuth Codex requests
- Add `CodexAttestationProvider` hook and `getCodexAttestationHeader` resolver that gates on ChatGPT-OAuth credentials.
- Integrate attestation into WebSocket transport, SSE event stream, and OpenAI compaction requests.
- Wire `setCodexAttestationProvider(generateCodexAttestation)` in model-registry init for OAuth sessions.
2026-07-24 09:17:00 +02:00
usr-bin-roygbiv 914a0d0645 chore(changelog): restore computer entries to Unreleased 2026-07-24 01:40:46 +00:00
usr-bin-roygbiv b9504f65e7 feat: add native Codex computer use 2026-07-24 01:40:04 +00:00
can1357 5e63cc5696 chore: bump version to 17.1.0 2026-07-24 02:49:18 +02:00
can1357 6cf5b25399 chore: update changelogs 2026-07-24 02:38:32 +02:00
can1357 2fce6c1d8e docs: normalized changelog headings after merges 2026-07-24 02:25:52 +02:00
can1357 81254e45a1 fixed changelog markdown spacing before Added heading 2026-07-24 02:24:30 +02:00
can1357 2d5f8d52d0 Merge PR #6411: feat(agent): classify Cloudflare response cache status (@riverpilot) 2026-07-24 02:24:30 +02:00
can1357 46d2b7d864 Merge PR #6439: fix(compaction): stop feeding reasoning back to Claude summarizer (@roboomp) 2026-07-23 23:05:47 +02:00
roboomp 5a70eda7d7 fix(compaction): stop feeding reasoning back to Claude summarizer
Both compaction serializers reproduced prior assistant reasoning as text
bound for a Claude target, tripping Anthropic's reasoning_extraction
refusal and wedging Fable 5 sessions:

- context-full: serializeConversation rendered thinking verbatim inside
  <thinking> tags via the anthropic dialect renderer. Now drops thinking
  blocks when the summary target dialect is anthropic; other dialects
  (e.g. Harmony) keep native reasoning.
- snapcompact: emitted ¶think sections baked into replayed archive
  frames. Added an includeThinking serialize option (default true) and
  wired the agent session to disable it for Anthropic-dialect models.

Fixes #6093
2026-07-23 20:38:27 +00:00
can1357 9c35eb225a chore(changelog): normalized unreleased sections after merges 2026-07-23 22:17:17 +02:00
can1357 29c2bd2595 Merge PR #6415: fix(compaction): judge remote-preserve reuse against the active model (@roboomp)
# Conflicts:
#	packages/coding-agent/src/session/agent-session.ts
2026-07-23 22:16:11 +02:00
Alexander Kirilin b225b27e92 feat(agent): classify Cloudflare response cache status 2026-07-23 15:18:37 -04:00
roboomp 116b8f4597 fix(compaction): judged remote-preserve reuse against the active model
After an OpenAI remote compaction, prepareCompaction decided whether to
keep the provider-native replay boundary or re-expand its originals by
asking whether *any* compaction candidate (every role model plus the
largest-context available model) shared the payload's provider. In a
multi-role setup where a role such as modelRoles.smol stays on OpenAI,
the check passed forever, so a session switched to a non-OpenAI active
model kept a placeholder-only summary and never recovered the compacted
span for the rest of the session.

Judge reusability against the active model — the one that assembles the
request context every turn — instead of the candidate set. When the
active model cannot replay the payload, re-expand the originals into a
portable local summary, matching the self-healing already present for
single-provider migrations.

Fixes #6343
2026-07-23 19:12:50 +00:00
roboomp 0640b7e3c7 fix(agent): deliver queued steer on empty transcript instead of looping
A steer queued on a session with an empty transcript was undeliverable:
Agent.continue() threw "No messages to continue from" before dequeuing any
steering message, so the RPC idle-drain re-armed continue() on every microtask
(gated only on hasQueuedMessages(), which never cleared) — an unbounded
allocation loop that OOM-killed the process.

continue() now consumes a queued steer/follow-up as the opening turn when the
transcript is empty, mirroring the assistant-tail branch. The queue drains, the
re-arm's hasQueuedMessages() gate goes false, and the loop terminates.

Fixes #6344
2026-07-23 19:02:47 +00:00
can1357 2cccaedbec chore: promoted merged changelog entries to unreleased 2026-07-23 17:57:43 +02:00
can1357 c522eceff2 Merge PR #6119: feat: lift subagent async/auto-background limits via owner-routed delivery and quiescence (@korri123)
# Conflicts:
#	packages/coding-agent/src/task/executor.ts
2026-07-23 17:52:52 +02:00
can1357 794515fd1a Merge PR #6363: feat(coding-agent): support per-command bash approval rules (@WahidinAji) 2026-07-23 17:30:32 +02:00
can1357 639bac596d chore: bump version to 17.0.9 2026-07-23 14:40:52 +02:00
Cakrawala 6d7457663f feat(coding-agent): support per-command bash approval rules 2026-07-23 17:11:41 +07:00
can1357 9b54d9e9ac chore: bump version to 17.0.8 2026-07-23 00:41:54 +02:00
can1357 7d404686c2 chore: updated changelogs + remove summarization marker 2026-07-22 23:59:32 +02:00
can1357 0002905ec5 chore: untrack node_modules symlinks and harden ignore pattern
- An eval-worktree cherry-pick swept 16 packages/*/node_modules symlinks into the index; 'node_modules/' with a trailing slash only matches directories, so symlinked installs bypassed the ignore. Dropped the slash and removed the tracked links.
2026-07-22 21:43:22 +02:00