Commit Graph

1673 Commits

Author SHA1 Message Date
usr-bin-roygbiv a8349d4dea fix: retain native compaction auth fallback
(cherry picked from commit 164d77ee90ed109b62ed7f1b6afcf644d26abe12)
2026-07-30 01:42:06 +02:00
Roy 5ce80fdedc fix: preserve provider-native compaction semantics
(cherry picked from commit 426ac1e147c08092c7d0b6c4a7af5f2e09eaf941)
2026-07-30 01:42:06 +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 0249fa4715 Merge PR #7036: feat(rpc): expose live fast-mode control and token throughput (@fredluz) 2026-07-30 01:26:49 +02:00
can1357 07ed00ae22 Merge PR #7028: fix(ai): bound Anthropic retry-after waits (@metaphorics) 2026-07-30 01:26:49 +02:00
can1357 65f3743622 feat(coding-agent/session): supported importing session compactions in Codex session store
- Support parsing compacted records with replacement history and conversion to compaction entries.
- Add test coverage for foreign session import of Codex session compactions.
2026-07-30 01:13:37 +02:00
can1357 f11641d5a8 feat(coding-agent): enabled importing foreign sessions from claude and codex
- Implemented session stores and metadata converters to import Claude and Codex sessions into OMP.
- Added `--from-claude` and `--from-codex` CLI flags and `/resume` command arguments for foreign session resolution.
- Updated session selector components and controllers to support listing and picking external agent sessions.
- Added comprehensive unit tests and documentation covering foreign session import functionality.
2026-07-30 00:28:40 +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 93819dbec4 fix(coding-agent): gate refusal retries on replay safety
(cherry picked from commit 531b25beffa2096c76adff6692f3697e649f0e95)
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
metaphorics c806a9b482 fix(coding-agent): guard Fireworks fallback after visible output
- reuse the centralized replay-unsafe predicate in Fast fallback
- exercise visible-text and replay-safe Fireworks branches

(cherry picked from commit f596392b891bb8ec82171a25c6651ed3cc8e0d61)
2026-07-29 23:08:50 +02:00
metaphorics b5602ddfc1 fix(coding-agent): treat streamed visible text as replay-unsafe in turn recovery
(cherry picked from commit 3aeac1a4afa756e9c7d579246d8f334cd0731cda)
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 359dfb5b8f fix(session): keep pending xd mount delta on transcript reset
The previous reset dropped #pendingXdevMountDelta alongside the announced
baseline. Unlike /new and different-session switchSession, branch() does
not rebuild the base system prompt afterward, and because the device is
already in mountedNames no later refresh re-queues an add delta. Dropping
the undelivered delta therefore left the branched transcript unaware of a
still-mounted discoverable device.

Only the announced baseline is reset now; pending adds (still-live mounts
awaiting delivery) survive and announce on the next prompt in the new
transcript. Redundant on /new (the rebuilt prompt lists them too) but
harmless, and correct for branch.

Fixes #6921

(cherry picked from commit 5866440f27c15a320657e25fbfa0d2d65aad1fa2)
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
roboomp 82dc0d43ae fix(session): migrated legacy xd mount notices on resume
Replayed the stable added and removed inventory sections from legacy
xdev-mount-notice content when structured details are absent. This keeps
the first post-upgrade resume from re-announcing devices that persisted
history already introduced.

Covered both structured and legacy resume histories, including removed
devices and inline docs that must not be interpreted as inventory.

Fixes #6921

(cherry picked from commit 634a4c2de75f99e219f408c56bed83c04fe1290a)
2026-07-29 23:08:32 +02:00
roboomp ac67548bc1 fix(session): gated xd:// mount notices against announced history
Mount-notice injection diff-gated only against the in-memory mountedNames
set, which is reseeded on every process resume / host reconnect. Dynamic
devices (MCP / RPC host) already announced in persisted history therefore
re-announced, splicing a redundant developer message that busts the
provider prompt-cache prefix and re-bills the whole suffix at full price
on metered providers.

Notices now persist a structured { added, removed } payload. On the first
consumption after resume the announced-device baseline is reconstructed
from history, and only a net change relative to what the model already
knows is announced, so a resume re-establishing the same inventory emits
nothing.

Fixes #6921

(cherry picked from commit 03c2ed5189510f41431bd164fa80187a69ed8de9)
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
Márton Danóczy bce1ff55a7 feat(session): emit model_changed event on every internal model switch
AgentSession#setModelWithProviderSessionReset is the single choke point
every model mutation runs through (explicit /model, prewalk hand-offs,
retry-fallback, model cycling). It previously changed agent.state.model
silently — no session event told subscribers (ACP, RPC, TUI) that the
active model moved.

Emit a new model_changed AgentSessionEvent from that choke point
whenever the model actually changes, and wire it into every consumer
that must exhaustively handle AgentSessionEvent: the TUI event
controller (invalidates the status line, same as thinking_level_changed)
and the RPC client's forwarded-event allowlist.

(cherry picked from commit f76325de2c7821dd7046ddb67546577c3575a263)
2026-07-29 23:08:25 +02:00
Frederico Luz 1e96750437 fix(rpc): report Anthropic fast fallback honestly
Anthropic's provider-scoped fastModeDisabled state was omitted from the session active predicate, and the unchanged-tier guard prevented explicit retries.
2026-07-29 20:58:01 +01:00
metaphorics 6cd48aca74 fix(ai): address Anthropic retry cap review 2026-07-30 01:38:23 +09:00
Paolo Mazzitti 3c7233af44 fix(coding-agent): scope advisor cost to active session 2026-07-29 07:18:48 +00:00
usr-bin-roygbiv 085f870faa feat(extensions): expose session async job snapshots 2026-07-28 23:12:28 +00:00
can1357 ac6cd57bd4 Merge PR #6820: fix(coding-agent): preserve parent todos in vibe mode (@Iron-Ham) 2026-07-28 10:59:37 +02:00
can1357 be0e593428 Merge PR #6880: fix(session): preserve auto-thinking level on classifier failure (@roboomp) 2026-07-28 10:59:37 +02:00
can1357 2b759b89e3 Merge PR #6838: fix(session): attribute user bang executions in advisor transcripts (@roboomp) 2026-07-28 10:59:36 +02:00
can1357 f464c9b168 Merge PR #6829: fix(cli): purge completed async jobs on /new (@roboomp) 2026-07-28 10:59:36 +02:00
roboomp 5d9cbf19e6 fix(session): preserved auto-thinking level on classifier failure
- Kept the last successfully classified effort when a later classification fails.
- Added regression coverage for the success-then-failure transition.

Fixes #6877
2026-07-28 08:06:17 +00:00
can1357 641d20fa5c refactor(coding-agent/advisor): removed stale-review-window warning from advisor notes
- Remove `annotateForStaleness` and `hasFreshBacklog` from the advisor runtime.
- Stop appending staleness warnings to delivered advisor notes when newer primary turns queue.
2026-07-28 04:25:41 +02:00
can1357 21b3764b08 refactor(coding-agent): replaced xdevregistry with state interface and helpers
- Replaced the `XdevRegistry` class with the `XdevState` interface and pure helper functions across core and session tools.
- Updated session configurations, tool execution, and renderers to utilize canonical tool map initialization and sharing.
- Adapted unit tests and mocks to use `XdevState` and associated helper functions for permission and dispatch verification.
2026-07-28 03:34:36 +02:00
can1357 bbe0236a0f fix(coding-agent): prevented duplicate artifact saves and mismatched ids in bash output 2026-07-28 02:05:55 +02:00
roboomp 550894de9a fix(session): attribute user bang executions in advisor transcripts
User-initiated `!`/`$` (and RPC bash) executions persist as
`bashExecution`/`pythonExecution` roles, which are always user-run —
the model's bash goes through `toolCall`. The history serializer emitted
them as a bare `→ bash! …` line and cleared the watched-mode role label,
so in advisor deltas the command trailed the `**agent**:` block with no
user attribution. The advisor then misread user-run commands as agent
actions (e.g. a false blocker over a user-run worktree cleanup).

Render these lines under a `**user**:` label in watched mode and prefix
them `→ user-bash!` / `→ user-python!` so provenance is explicit in every
render path.

Fixes #6837
2026-07-27 23:39:31 +00:00
can1357 cfd335d2b1 fix(tui): restored image attachments on /tree and esc-esc branch
- branch() and navigateTree() now return the selected user message's image
  parts (selectedImages/editorImages) alongside the text, extracted in marker
  order by #extractUserMessageImages.
- CustomEditor.setDraft() replaces the composer draft with text plus its
  pending images, so restored [Image #N] markers resolve on resubmit instead
  of degrading to literal text.
- Wired all six restore call sites (selector-controller, extension-ui-controller)
  through setDraft; updated rpc-subagents mocks for the new branch shape.
- Added offline regression tests for branch/navigateTree image restitution,
  multi-image marker order, and text-only prompts.
2026-07-28 00:57:34 +02:00
can1357 392aac4e49 fix(coding-agent): resolved third review pass on inspect_image vision mode
- read now treats an xd://-mounted inspect_image as available (top-level
  predicate OR mounted device gated by the effective mode), so default
  xdev sessions with a text-only model keep metadata-guidance reads
  instead of inlining images the provider boundary would scrub
- advisor tool session stops inheriting the primary's isToolActive and
  xdevRegistry: advisors cannot execute xd:// devices, so their reads
  inline images again
- setModelWithProviderSessionReset is now async and awaited at every
  callsite, so retry-fallback model switches cannot race the
  inspect_image tool-slate reconcile
- regression tests for both xd:// availability directions
2026-07-27 23:07:26 +02:00
can1357 1bba24f191 Merge PR #6830: feat(coding-agent): capability-aware inspect_image with tri-state mode and /vision toggle (@epsilver) 2026-07-27 23:07:26 +02:00
can1357 da6d11de0e feat(agent): introduced prepareToolCall phase supporting argument replacement
- Added a prepareToolCall phase to the agent loop running before tool scheduling for validation and hooks.
- Updated BeforeToolCallContext and result types to support argument replacement instead of in-place mutation.
- Updated coding-agent extension handling and runner to track emitted tool calls and re-evaluate approvals on input revisions.
- Added comprehensive test coverage for argument replacement, concurrency resolution, and schema validation.
2026-07-27 22:55:20 +02:00
alexis@epsilver.xyz b58a943a8e fix(coding-agent): address second codex pass on vision mode
- read now derives its image behavior from actual tool availability
  (session.isToolActive) with the mode computation as fallback, so
  restricted sessions whose explicit slate omits inspect_image (e.g.
  subagents) never get metadata-only reads pointing at an absent tool
- reconcile passes the post-change availability into the read
  description sync, keeping the advertised prompt correct across flips
  in both directions and when tool construction fails
- flat quoted-dotted inspect_image.mode is normalized into the nested
  target during migration instead of being silently dropped when a
  legacy flat enabled key is present
- regression tests for all three: availability-driven read behavior,
  flat+flat migration, description advertising
2026-07-27 16:24:02 -04:00
alexis@epsilver.xyz 3854c1c3b1 fix(coding-agent): address codex review on vision mode
- Reconcile inspect_image centrally from setModelWithProviderSessionReset
  so retry-fallback model changes (turn-recovery.ts) that bypass
  syncAfterModelChange cannot leave a stale tool set
- Apply persisted inspect_image.mode changes immediately from the
  settings selector via a new handleSettingChange branch
- Refresh the read tool's advertised description during reconciliation,
  before applyActiveToolsByName rebuilds the prompt, instead of only
  lazily on the next image read
- Fix the flat (quoted-dotted) enabled->mode migration to write the
  nested target form the resolver actually reads
- Add committed regression tests: tri-state x capability matrix,
  override precedence, and enabled->mode migration (nested, flat, and
  explicit-mode-wins)
2026-07-27 16:24:02 -04:00
alexis@epsilver.xyz c33b98e260 feat(coding-agent): capability-aware inspect_image with tri-state mode and /vision toggle
Replace the inspect_image.enabled boolean with inspect_image.mode
(auto|on|off, default auto). In auto the tool is registered only when
the active model lacks native image input, so vision-capable models
(e.g. kimi-code/k3) read images inline with their own capabilities
instead of delegating to a separate vision model. on/off force
registration regardless of model capability.

- New utils/inspect-image-mode.ts resolves the effective state from the
  /vision session override, the persisted setting, and model capability
- read tool re-evaluates the effective state per image read and
  re-renders its description, so it returns decoded image blocks again
  whenever inspect_image is hidden
- /vision [on|off|auto|status] slash command (modeled on /computer)
  overrides the mode for the current session only
- Tool set is reconciled on model switch with a status notice when
  inspect_image appears/disappears
- Legacy inspect_image.enabled true/false migrates to mode on/off
2026-07-27 16:24:02 -04:00
roboomp e4a586ac08 fix(cli): invalidated async deliveries by generation
- Stamped a per-owner delivery generation on each async-result follow-up.
- Bumped the generation on session transitions and dropped stale-generation
  deliveries at format-time and flush-time, closing the job-id-reuse race.
- Reverted the fragile persistent-suppression eviction to full row removal.
- Covered the reused-id late-delivery contract at the transcript level.

Fixes #6828
2026-07-27 20:09:26 +00:00
roboomp 3488b92508 fix(cli): dropped pending async deliveries on new session
- Evicted jobs now drop queued/in-flight deliveries and stay suppressed.
- /new clears already-queued async-result yield follow-ups.
- Added a transcript-level test asserting no prior-session result leaks.

Fixes #6828
2026-07-27 19:53:58 +00:00
roboomp 6bc98eb3b9 fix(cli): evicted failed jobs on new sessions
- Included failed terminal jobs in owner-scoped session cleanup.
- Extended the /new regression test to cover failed prior-session jobs.

Fixes #6828
2026-07-27 19:44:28 +00:00
roboomp fd24dcc551 fix(cli): purged prior session async jobs
- Added owner-scoped eviction for retained completed jobs.
- Cleared completed async rows during fresh-session cleanup.
- Covered /new isolation while preserving other owners' jobs.

Fixes #6828
2026-07-27 19:38:29 +00:00
can1357 6b42097d12 perf(agent): implemented caching for session file scans and actions
- Add an LRU cache to `scanSessionFile` in `session-listing.ts` keyed by file path, stat identity, and scan mode.
- Add a match key union probe in `CustomEditor` in `custom-editor.ts` to bypass per-action lookups on plain text input.
- Add tests covering cache hits, size and mtime invalidations, and negative result caching.
2026-07-27 20:33:38 +02:00
Hesham Salman 7f7e742db6 fix(coding-agent): preserve parent todos in vibe mode 2026-07-27 13:52:25 -04:00
can1357 d16a251777 chore: reorg tests 2026-07-27 16:43:53 +02:00