Commit Graph

1321 Commits

Author SHA1 Message Date
can1357 1a8caad23e chore: update docs + rename reset to clear 2026-08-03 18:37:23 +02:00
can1357 fc04aa6fa7 refactor(coding-agent): deferred startup parsing and schema compilation
- Wrapped security contract schemas in a lazy initializer with jitless scopes to eliminate startup JIT compilation tax.
- Enabled jitless scope configuration in auth-broker wire schemas to skip definition-time codegen.
- Deferred startup changelog parsing to overlap with interactive session creation.
2026-08-03 16:31:27 +02:00
can1357 a418920ec1 feat: made /reset semantically different
Closes #4447
2026-08-03 15:46:46 +02:00
can1357 267856deb8 Merge PR #7475: fix(session): prevent stale /btw branch promotion (@roboomp) 2026-08-03 15:12:03 +02:00
can1357 6a44844c57 Merge PR #7377: fix(hub): wake owners when supervised processes exit (@paralin) 2026-08-03 15:12:03 +02:00
can1357 b1d75bb55b fix(session): preserve title on first-turn branches 2026-08-03 14:46:24 +02:00
roboomp 98f484bd2f fix(session): validated session identity for /btw branch
Branched session files preserve entry ids, so leaf-id equality alone let a stale /btw answer promote into a different loaded session. Capture the originating session id at /btw start and require it to match at both the controller gate and every branchFromBtw checkpoint.

Fixes #7474
2026-08-03 09:22:32 +00:00
roboomp 7a1183da91 fix(session): prevented stale /btw branch promotion
- Passed the authorized leaf through the branch executor and revalidated it before rewriting history.
- Refused promotion during active turns and bounded post-prompt drains.
- Consumed unavailable branch keys while showing pending and refusal state in the panel.

Fixes #7474
2026-08-03 09:07:12 +00:00
Christian Stewart 302148523f fix(hub): wake owners when supervised processes exit
Publish terminal daemon completions to the session that started the
process so idle agents can resume without polling hub status.

Persist every unacknowledged generation with a stable completion ID and
immutable snapshot. Replay the collection after reconnect or broker
recovery, and clear each event only after the owning client acknowledges
it.

Signed-off-by: Christian Stewart <christian@aperture.us>
2026-08-03 01:31:39 -07:00
can1357 965d1239cf Merge PR #7310: fix(omp): refresh context budget after shake (@oleksoleksoleks) 2026-08-02 20:53:46 +02:00
can1357 160bdd05c3 fix(agent): keep session scout notices live 2026-08-02 20:52:57 +02:00
Alexander Kirilin e50138f2a6 fix(omp): refresh context budget after shake 2026-08-02 12:12:07 -04:00
Slava Zavadsky 9885ee34fc fix(agent): stop leaking scout into prompts when it is disabled
Hard-coded 'scout' references reached the model even when the scout
agent was disabled via task.disabledAgents or absent from the session
spawn list. Gate every such reference on scout actually being spawnable:
the task tool description, the delegation gates, the plan-mode and
workflowz notices, the glob/grep/ast-grep guidance, and the task
specialization advisory. Prompt shape is otherwise unchanged; only
erroneous references to the unavailable subagent are dropped.

Closes #7313
2026-08-01 23:50:33 -04:00
can1357 992963f949 feat(coding-agent): allowed switching to models smaller than session context with compaction
- Make over-context models selectable in the model picker by graying them instead of disabling them.
- Trigger automatic session compaction with the current model prior to switching when an over-context model is chosen.
2026-08-01 20:59:24 +02:00
can1357 93a9f0d991 Merge PR #7262: fix(coding-agent): refresh context files on plugin reload (@roboomp) 2026-08-01 20:13:38 +02:00
can1357 401ff44f08 Merge PR #7202: fix(agent): route codex v2 compaction through websockets (@roboomp)
# Conflicts:
#	packages/ai/src/providers/openai-codex-responses.ts
2026-08-01 20:13:28 +02:00
roboomp 55115f4bfd fix(coding-agent): refresh advisor context prompt on reload
Rebuilt advisor runtimes with the rediscovered context files so advisor turns stop evaluating against stale AGENTS.md instructions after /reload-plugins.

Fixes #7258
2026-08-01 11:46:55 +00:00
roboomp 838d120249 fix(coding-agent): reused effective prompt cache key
- Reused the agent's explicit or inherited cache identity for ephemeral side turns.
- Forwarded the same effective key through manual and automatic native compaction.
- Added regression coverage for all three secondary request paths.

Fixes #7218
2026-08-01 03:44:59 +00:00
roboomp 5283c4c99b fix(agent): routed codex v2 compaction through websockets
- Reused the live Codex provider session for WebSocket-first V2 compaction.
- Fell back to SSE V2 on WebSocket transport failure before the existing V1 fallback.
- Propagated the configured WebSocket preference through manual, automatic, and advisor compaction paths.
- Added transport reuse and fallback regression coverage.

Fixes #7198
2026-07-31 21:00:15 +00:00
can1357 06649b7407 feat(coding-agent): rewrote codex saved-reset trigger algorithm
- Replaced the reactive weekly-only auto-redeem predicate with a pool-wide
  planner: an expiry-salvage sweep piggybacks on the 5-minute usage
  heartbeat and spends any account's reset that would otherwise expire
  within codexResets.salvageHorizonHours, and the blocked-turn path scans
  all stored accounts with eligibility built from the exact exhausted
  5h/weekly windows (openai/codex#28525), unblocking at the latest reset
  among them.
- Made the live 429's parsed unblock timestamp authoritative for the
  active account (pre-block snapshots survive cache invalidation via
  in-flight adoption and last-good fallback), synthesizing the candidate
  when no usable report exists, and overlaying live credit counts from
  the dedicated credits route since a stale /wham/usage zero is never
  corrected upstream.
- Treated nothing_to_reset, credit_list_failed, and thrown consumes as
  non-terminal: the episode key is released and deferred 30 minutes
  instead of burying a banked credit; redeemResetCredit now spends the
  soonest-expiring credit.
- Added planner unit fixtures plus integration regressions driving the
  real triggers end to end, with an injectable per-session coordinator
  seam and a sweep settlement handle.
2026-07-31 20:39:12 +02:00
can1357 bd96752b83 fix(rpc): serialize IRC wake finalization 2026-07-31 19:28:43 +02:00
can1357 e02510f8c9 Merge PR #7108: fix(rpc): restore frames for IRC-revived subagents (@roboomp) 2026-07-31 19:28:42 +02:00
can1357 03c923d376 Merge PR #7140: fix(agent): suppress redundant xd:// mount notice after catalog rebuild (@roboomp) 2026-07-31 19:16:57 +02:00
can1357 3a68ce7eb0 Merge PR #7167: fix(cli): generate titles for positional initial messages (@roboomp) 2026-07-31 19:07:17 +02:00
roboomp 19818fd8fb fix(cli): skipped titles for positional extension commands
Applied the extension-command eligibility check inside the shared AgentSession title gate so editor and CLI bootstrap submissions cannot diverge.

Added direct regression coverage for programmatic startup submissions.

Fixes #7166
2026-07-31 10:34:46 +00:00
roboomp 223122d6b0 fix(cli): generated titles for positional initial messages
Moved automatic title eligibility and persistence into AgentSession so editor and CLI bootstrap submissions share one path.

Added a PTY regression probe covering the positional-message launch flow.

Fixes #7166
2026-07-31 10:28:48 +00:00
roboomp 4119bc461e fix(agent): resolve xd:// notice after final prompt override
A before_agent_start extension can replace the base system prompt after the
mount notice was consumed. Catalog-backed additions were then marked
announced and suppressed even though the provider request no longer contained
the catalog.

Reserve the notice's pre-user message position, wait until the extension has
selected the final prompt, and suppress catalog-backed additions only when no
per-turn replacement dropped the base catalog. Explicit replacements retain
the mount notice as the device-discovery channel.

Fixes #7139
2026-07-31 02:45:21 +00:00
can1357 652647770e feat(coding-agent): added app.live.toggle keybinding and map display reset to alt+l
- Add the `app.live.toggle` keybinding defaulted to `Ctrl+L` to start or stop live voice mode.
- Remap the default display-reset action (`app.display.reset`) from `Ctrl+L` to `Alt+L`.
- Update the live visualizer to listen for stop keys so the toggle chord terminates active sessions.
2026-07-31 00:20:04 +02:00
roboomp 8d0a193f19 fix(rpc): guarded IRC wake recovery by prompt generation
- Captured the prompt generation before an IRC wake and passed it to the post-prompt recovery wait.
- Stops the wait from following a successor turn once an abort supersedes the wake, so the wake monitor finalizes promptly instead of misattributing successor progress.

Fixes #7105
2026-07-30 20:16:20 +00:00
roboomp 4670a34590 fix(rpc): waited for IRC wake session settlement
- Kept IRC run monitors attached through post-prompt retry and continuation recovery.
- Flushed the final deferred agent_end before terminal lifecycle emission.
- Covered empty-stop retry ordering for RPC event subscribers.

Fixes #7105
2026-07-30 19:53:39 +00:00
roboomp b2d18b6920 fix(rpc): restored frames for IRC-revived subagents
- Monitored autonomous IRC wake turns with the task executor lifecycle and progress channels.
- Preserved monitoring after idle-TTL parking and session revival.
- Covered RPC subscriptions for both idle and parked keep-alive agents.

Fixes #7105
2026-07-30 19:42:58 +00:00
can1357 e05f229f43 refactor: standardized editing syntax by removing copy and delete operations
- Removed copy and delete operations across tokenizer, parser, grammar, and clipboard logic.
- Standardized line-editing operations and block resolvers to use cut exclusively.
- Updated documentation, prompts, and test suites to reflect the removal of copy and delete syntax.
2026-07-30 07:42:48 +02:00
can1357 9aada058ee feat(hashline): implemented clipboard operations in hashline engine
- Implemented clipboard register management, parsing, and execution rules for CUT, COPY, and PASTE operations in the hashline engine.
- Added session-persistent clipboard state and integration across agent session execution, diff previews, and streaming tools.
- Added comprehensive validation, error messages, recovery handling, and test coverage for clipboard and block operations.
2026-07-30 07:21:43 +02:00
can1357 6b4efa896f feat(coding-agent): implemented oauth credential pin persistence and seeding
- Added hashing utilities and session entry definitions for OAuth credential pins.
- Added session manager methods to append and retrieve credential pins with backdated timestamp support.
- Added credential pin recording after assistant turns and seeding during session restoration.
- Added comprehensive unit tests covering credential pin recording, persistence, and seeding.
2026-07-30 07:21:08 +02:00
can1357 1b25ff01a2 style: apply biome formatting to merged changes 2026-07-30 02:01:03 +02:00
can1357 7ccbe51b2d fix(session): preserved Codex commentary on empty stops
(cherry picked from commit 0b4887a4098e6296ac72ea2837db22be18dc9894)
2026-07-30 02:01:02 +02:00
Diogo Soares Rodrigues 5ab98cded8 fix(cursor): persist resource listings, wire advisor MCP resources, reject unavailable pi edit/write
Three remaining review findings:

- `list_mcp_resources` frames a handler answered now synthesize a
  `list_mcp_resources` block and pair a result derived from the same
  answer sent on the wire; the streamed `ListMcpResourcesToolCall` /
  `ReadMcpResourceToolCall` announcements join the exec-owned set so
  they cannot double-render. No-handler frames still synthesize
  nothing, since nothing ran.

- Advisors receive the same `MCPManager`-backed resource adapter as the
  primary bridge, so their `list_mcp_resources` no longer reports every
  server as empty and `read_mcp_resource` no longer answers `not_found`
  against live connections the advisor shares.

- An unavailable `pi_edit`/`pi_write` answers with the protocol's
  `rejected` variant instead of `error`: refusal and failure are
  separate oneof cases, and a denial reported as an execution error
  invites a retry of an operation that was never permitted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SSWZTe6YA2PX1cqtukZvYi
(cherry picked from commit 47ce936c8df05d6970504af19e5ef7d2e8c38d7b)
2026-07-30 01:43:07 +02:00
Diogo Soares Rodrigues a363f95009 fix(cursor): pair interrupted calls and gate advisor bridge approval
Two independent bugs found in review.

A stream that dies mid-turn takes the terminal-error path: `settleH2`
rejects when the transport closes without `turnEnded`, so the flush on
the success path never runs. `connect_scm` and native todo blocks are
stamped `kCursorExecResolved` at start, so `agent-loop.ts` synthesizes
no placeholder and only their completion frame pairs a result - the call
was left unpaired and its card animating, and `buildSessionContext`
strips a dangling call from every rebuilt transcript. The catch path now
closes open blocks and pairs those server-owned calls with an
interrupted result. Exec-settled MCP blocks are excluded: the dispatch
that ran them owns their result and `drainInFlightDispatches` awaits it,
so pairing here would duplicate against the same id.

Separately, the advisor bridge supplied no `getToolContext`.
`ExtensionToolWrapper` reads the approval mode, per-tool policies and
`autoApprove` only from that execute-time context, so every wrapped
advisor bridge tool resolved as `yolo` with empty policies - a
configured `ask` or `deny` on `edit`/`grep` did not apply to native
frames. Advisors now get the same `ToolContextStore` as the primary
bridge.

Both are covered against the real paths: the interrupted call through
the HTTP/2 fixture server (a helper-level test passes even with the
catch-path flush removed), and approval through real deny policies.

(cherry picked from commit 5ace682578af96708caf88db2d44b9077a1c0e74)
2026-07-30 01:42:28 +02:00
Diogo Soares Rodrigues 5779c762de fix(cursor): give advisors the replace-mode edit pi_edit needs
The primary bridge builds a `replace`-mode `EditTool` because
`PiEditExecArgs` carries `old_text`/`new_text` pairs that no other mode
accepts. The advisor roster passed its own instances straight through,
and those follow the session's configured `edit.mode` - `hashline` by
default, whose schema is a single `input` string - so every native
advisor edit failed validation instead of touching the file.

Both bridge-only tools now come from `cursor-bridge-tools.ts`:
`createBridgeEditTool` builds the wrapped `replace` instance, and
`bridgeToolMap` substitutes it into a granted map. The substitution is
gated on `edit` actually having been granted, since the tool is
constructed rather than looked up - handing one to a read-only roster is
the #5680 escalation. The advisor's own loop keeps its instance; only
the exec map is swapped.

(cherry picked from commit e6cf9f8046c595cab9793b4b2a5795d8488d8d22)
2026-07-30 01:42:28 +02:00
Diogo Soares Rodrigues 6eaf090ccc fix(cursor): repair pi_edit and close the scoped-grep approval bypass
Three defects the exec bridge shipped with, all found by review.

`pi_edit` never worked. The session removes `edit` from the tool
registry for Cursor so the model is steered to full-file `write`
(8ba0498eb), but that same registry is the bridge's tool source, so the
native frame — which the server sends regardless of the advertised
catalog — resolved nothing and answered `Tool "edit" not available`.
Retaining the instance is not enough either: `PiEditExecArgs` carries
`old_text`/`new_text` pairs, which only `replace` accepts, while the
default mode is `hashline` (`{ input: string }`). `EditTool` now takes
an optional mode, and the bridge resolves a pinned `replace` instance
through its fallback resolver.

A `pi_grep` frame carrying `context` or `limit` escaped the approval
gate. Honoring those needs a per-call tool, and the per-call instance
was built raw while every registry tool is wrapped — so exactly those
calls skipped `tools.approval.grep` and the exec-tier SSH check. Both
callsites now go through one `createBridgeGrepFactory`.

Advisors ignored the same two fields: only the primary session supplied
the factory. They now get it too, gated on the advisor actually holding
`grep` so the factory cannot grant a denied tool.

Also moves the pure Pi arg translation to `providers/cursor-pi-args`.
The legacy shim shares it and is compiled into the bundled virtual
registry, where `./providers/*` cannot match a nested specifier — it
fell through to `Bun.resolveSync`, unsatisfiable under bunfs (#3442) —
and the exec module would have dragged the protobuf graph along.

Verified against real files and the real module graph: `pi_edit` mutates
a temp file, the bundled probe executes the shim's shared module in a
subprocess, and the grep test drives the shared factory. Mutation-
checked: returning a raw tool from the factory, ignoring the pinned edit
mode, dropping the `getTool` fallback, or moving the helpers back to a
nested path each fails a test.

(cherry picked from commit e46ba22b634e449005f7c22b6d0efd19a45ce1f8)
2026-07-30 01:42:23 +02:00
can1357 5486c8fd1d Merge PR #6939: feat(extensions): expose session async job snapshots (@usr-bin-roygbiv) 2026-07-30 01:26:50 +02:00
can1357 832d4f1506 Merge PR #6987: fix(coding-agent): treat streamed visible text as replay-unsafe in turn recovery (@metaphorics) 2026-07-29 23:08:51 +02:00
metaphorics 9733d13827 fix(coding-agent): make replay safety authoritative
(cherry picked from commit 118ecabb22f406afbd56864ff0fbafc8f4f1fa4c)
2026-07-29 23:08:50 +02:00
can1357 d5457eba24 fix(session): reset announced mounts after changed reload
(cherry picked from commit f7ec56c1c8b73476322904666d560492a6027ef7)
2026-07-29 23:08:34 +02:00
can1357 a73cd40c8f Merge PR #6922: fix(session): gate xd:// mount notices against announced history (@roboomp) 2026-07-29 23:08:33 +02:00
roboomp 13b1077d3e fix(session): reset announced xd mounts on transcript replace
The announced-mount baseline persisted across /new, switchSession, and
branch, which replace agent.state.messages but only clear session-scoped
tool state. A device announced in the old transcript stayed in the cache,
so reconnecting it into the fresh history was filtered as already known
and never announced, leaving the new conversation unaware of the device.

Reset the announced baseline (and any undelivered pending delta) from
#clearSessionScopedToolState, so the next notice re-seeds from the new
transcript and a reconnecting device announces again.

Fixes #6921

(cherry picked from commit d06dde02b9de4aacacd7aea5ee51edc7e524e3fb)
2026-07-29 23:08:32 +02:00
can1357 0e7ae1d6ac Merge PR #6908: fix(acp): sync model status when the agent switches models internally (@marton78) 2026-07-29 23:08:27 +02:00
Márton Danóczy 9aaa455708 fix(session): defer rollback's model_changed emit until after thinking is restored
#emit's listeners (ACP's #handleLifetimeEvent -> #pushConfigOptionUpdate
-> #buildConfigOptions) run synchronously up to their first await, and
#buildConfigOptions is evaluated as a synchronous argument expression
before that await. Emitting model_changed immediately after
agent.setModel(previousModel) but before #models.restoreThinkingSnapshot
ran meant ACP could push a { previousModel, target-session-thinking }
config that was never an actual session state -- neither the failed
target nor the restored previous session.

Move the emit after restoreThinkingSnapshot/restoreServiceTiers so it
observes fully-restored state, same as every other rollback consumer
in this catch block already does implicitly by running after both.

Found by Codex on PR #6908 (pullrequestreview-4801303428), against
a33aa07df from this same branch.

bun test test/acp-agent.test.ts (57) + agent-session-switch-prev-context,
agent-session-model-persistence, agent-session-model-switch-auth,
agent-session-openai-completions-model-switch, nonvision-model-switch
-- 90 pass, 0 fail. Workspace typecheck clean.

(cherry picked from commit 0ac190a39a1687ebf85849dde5e1af9c2f9147fc)
2026-07-29 23:08:26 +02:00
Márton Danóczy 3c0aa19820 fix(session): emit model_changed when switchSession rollback restores the model
switchSession's success path may already have called
#setModelWithProviderSessionReset for the target session's model,
which emits model_changed for it. If a later step in the try block
then throws, the catch restores previousModel via a direct
agent.setModel(...) that bypasses that method entirely and emitted
nothing — ACP/RPC/TUI kept advertising the target model that was
never actually committed.

Emit model_changed from the rollback path too, but only when the
restore actually changes the model back (guards the common case where
switchSession never touched the model or restores the same one).

Flagged independently by @roboomp and @chatgpt-codex-connector on
PR #6908.

bun test test/acp-agent.test.ts (57), agent-session-switch-prev-context.test.ts
(3), agent-session-model-persistence.test.ts (10 files) -- 80 pass, 0 fail.

(cherry picked from commit a33aa07df6fd61508956d73cc5b5284051bbfa86)
2026-07-29 23:08:26 +02:00
Márton Danóczy 986b1a1e70 refactor(session): emit model_changed via sync #emit, not #emitSessionEvent
model_changed has no extension-facing hook (#emitExtensionEvent never
maps it), unlike message_start/tool_execution_end/etc. Routing it
through #emitSessionEvent added an await on extension delivery plus
the FIFO subscriber gate inside every model switch, including
retry-fallback on the hot error-recovery path, for zero benefit.

Match the sibling thinking_level_changed event, which already goes
through the plain synchronous #emit. ACP/RPC/TUI still receive it
identically since they subscribe via #eventListeners either way.

No observable behavior change: bun test test/acp-agent.test.ts stays
at 57 pass, dedup logic for client-initiated model changes unaffected
(push still lands during the awaited #setModelById call).

(cherry picked from commit 3edc9f8495b1b06fd990a64756d92e60354451fc)
2026-07-29 23:08:26 +02:00