Apply saved agent config when resuming chats - #2776
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cda9594dd1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| }); | ||
| if (descriptor.applyInitialSessionConfig) { | ||
| try { | ||
| await descriptor.applyInitialSessionConfig(session, getSettings()); |
There was a problem hiding this comment.
Prevent stale resume completions from stealing focus
When a user opens another history row while the first resumed Claude chat is awaiting this configuration hook, both rows can remain actionable because the first session is not added to this.sessions until the await finishes. If the second load completes first, the older load subsequently continues and unconditionally makes itself active, returning the user to the chat they selected first; opening the same row twice can additionally create duplicate AgentSession objects whose backend handlers overwrite each other. Deduplicate in-flight loads by (backendId, sessionId) and/or guard activation with a latest-load token before introducing this new suspension point.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 56acb7a. Resume work is now single-flighted by the native (backendId, sessionId) identity, and history opens use a latest-request guard before activating the pooled session. The new regressions cover both out-of-order completion keeping focus on the newer row and opening the same row twice producing one AgentSession.
| }); | ||
| if (descriptor.applyInitialSessionConfig) { | ||
| try { | ||
| await descriptor.applyInitialSessionConfig(session, getSettings()); |
There was a problem hiding this comment.
Replay the persisted mode on resumed sessions
When a user has a sticky defaultMode such as auto or plan, a resumed Claude session still opens in default: ClaudeSdkBackendProcess.resumeSession() initializes no permissionMode, and this new block invokes only applyInitialSessionConfig, which replays effort. Fresh sessions subsequently call replayPersistedMode(session, this.getDefaultMode(...)), but the resume path never does, so the same saved configuration remains inconsistent between new and reopened chats. Replay the persisted mode before returning the resumed session as well.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 56acb7a. The resume path now awaits replayPersistedMode after backend-specific config and before the session is returned or activated. The regression starts a resumed Claude session in default mode with auto persisted, asserts the bypassPermissions mode write, and verifies the returned state is auto.
| }); | ||
| if (descriptor.applyInitialSessionConfig) { | ||
| try { | ||
| await descriptor.applyInitialSessionConfig(session, getSettings()); |
There was a problem hiding this comment.
Update the hook contract to include resumed sessions
This call broadens BackendDescriptor.applyInitialSessionConfig to restored sessions even though the exported interface contract still says it runs only on a freshly created session after createSession, and Claude's implementation documents the same restriction. A backend author can therefore legitimately add fresh-only or non-idempotent setup based on that contract and have it unexpectedly executed against an existing transcript here. Update the descriptor and implementation documentation to define resume semantics, or introduce a separate resume hook.
AGENTS.md reference: AGENTS.md:L27-L27
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 56acb7a. The exported BackendDescriptor contract now explicitly defines the hook for both fresh and resumed sessions, including that seededSelection is absent on resume. The Claude descriptor documentation now matches that lifecycle and clarifies that mode replay remains manager-owned.
cda9594 to
5a07c7a
Compare
Relates to logancyang/obsidian-copilot-preview#130
Why
When Agent Home reopens a saved Claude chat, the resumed backend reports its fallback effort (
low) and the history path makes that session active without replaying the user's saved default effort. Fresh chats already replay the same initial configuration, so a user who selectedhighsees different behavior depending on whether a chat is new or resumed.What
If initial configuration fails, the chat still opens with the backend-reported state, matching fresh-chat fallback behavior.
Non goal
Screenshot
Not applicable — this changes resumed-session initialization; Agent Home layout and copy are unchanged.
Risk
High
lowtohightransition and send gatingReview: inspect
AgentSessionManager.tryResumeSessionFromHistoryinsrc/agentMode/session/AgentSessionManager.tsand theloadNativeSessionFromHistory()tests insrc/agentMode/session/AgentSessionManager.test.tsline by line, then run Verification steps 2–4.Verification
high, create a chat, then return it to Recent Chats.highbefore the composer becomes sendable.