Skip to content

Conversation

@TylerBarnes
Copy link

Summary

This PR adds proper session persistence and history replay to the ACP implementation.

Changes

  • ACPSessionManager persistence: Sessions are now persisted to Storage, allowing them to survive process restarts
  • loadSession improvements: Properly loads existing sessions from disk instead of always creating new ones
  • Model restoration: When loading a session, the user's previous model choice is restored
  • History replay: When a session is loaded, the conversation history is replayed to the client via session/update notifications (as per ACP spec)

Testing

Added tests for session persistence:

  • Persisting session on create
  • Loading session from Storage
  • Returning null for non-existent sessions
  • Updating persisted session when model changes

All 258 tests pass.

- ACPSessionManager now persists sessions to Storage
- loadSession properly loads existing sessions from disk
- Restores user's model choice when loading a session
- replaySessionHistory sends session/update notifications for conversation history
- Added tests for session persistence
@rekram1-node
Copy link
Collaborator

/review

modelID: string
}
modeId?: string
internalSessionId?: string
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: The internalSessionId field was added but appears unused in this PR. Consider removing it if not needed, or adding a comment explaining its intended future use.

Suggested change
internalSessionId?: string
modeId?: string

const model = existingSession.model ?? (await defaultModel(this.config, directory))

this.setupEventSubscriptions(existingSession)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential Bug: Adding setupEventSubscriptions here means it will be called twice when creating new sessions, since newSession also calls setupEventSubscriptions(state) after calling loadSession. This could result in duplicate event handlers being registered.

You should either:

  1. Remove the setupEventSubscriptions call from newSession (since loadSession now handles it), OR
  2. Only call setupEventSubscriptions here when this is NOT a newly created session (though this may be tricky to detect)


// Verify session is stored in Storage
const stored = await Storage.read<any>(["acp_session", session.id]).catch(() => null)
expect(stored).not.toBeNull()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Consider adding cleanup for consistency with other tests in this file that do clean up after themselves.

Suggested change
expect(stored).not.toBeNull()
expect(stored?.id).toBe(session.id)
expect(stored?.cwd).toBe("/test/cwd")
// Clean up
await Storage.remove(["acp_session", session.id])
},

const sdk = createMockSDK()
const manager = new ACPSessionManager(sdk)

const session = await manager.create("/test/cwd", [])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential Race Condition: setModel persists asynchronously with .catch() (fire-and-forget), so this Storage.read immediately after might read stale data if the persist hasnt completed yet. Consider either:

  1. Making setModel return the persist promise, or
  2. Adding a small delay or polling in the test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants