feat: injectable session storage — ChatSessionRepository port (SDK P2, slice 2)#225
Merged
Merged
Conversation
Second pluggable-storage slice (SDK posture rung 5), following the artifact-repository pattern: hosts can back chat session persistence with their own storage instead of the file catalog under the state root. - Document ChatSessionRepository as the session persistence port (catalog entries plus full session bodies) and drop deriveStoragePaths() from the port: it is file-layout detail only the File implementation needs, so hosted implementers no longer have to invent fake paths. - createConversationEngine accepts sessionRepository and resolves the default FileChatSessionRepository once at the engine boundary. The instance flows to the session service and the whole turn path: turn context building, preflight lease/compaction persistence, completed-turn persistence, background memory-maintenance writes, and lease clearing. The quickstart runner passes it through. - Inner turn services (context builder, preflight, persistence, memory maintenance) now receive the repository instance in their args instead of re-deriving storage from sessionStoragePath at nine call sites. EngineConversationTurnService.clearLeaseFromStorage takes the repository directly. - Export ChatSessionRepository, FileChatSessionRepository, catalog types, and ChatSession from the curated rung-5 surface so implementers have the full contract. Proof: a unit test drives session create/read/rename through an in-memory repository and asserts the on-disk session catalog is never created. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CjFdZgZhov8wdwFinVTfjz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Second slice of SDK maturation P2 (pluggable storage, posture rung 5), following the merged artifact-repository pattern (#224): chat session persistence is now injectable, so a hosted service can back the session catalog and session bodies with its own storage instead of the file catalog under the state root.
Design
Port already existed — this slice makes it real.
ChatSessionRepository(list/readCatalog/read/save) was an internal interface with one implementer; the engine and the whole turn path constructedFileChatSessionRepositoryfrom asessionStoragePathstring at nine call sites. Now:deriveStoragePaths()from the port — it's file-layout detail only the File implementation needs internally. Hosted implementers no longer have to invent fake paths. Port doc added.createConversationEngine({ sessionRepository })resolvesconfig.sessionRepository ?? new FileChatSessionRepository({ sessionStoragePath })in config normalization. The instance flows to:ConversationTurnContextBuilder)clearLeaseFromStoragenow takes the repository)runQuickstartConversationCli({ sessionRepository }))EngineConversationTurnService.run(args)callers get the same resolve-once at therun()boundary (args.sessionRepository ?? File default), and every inner service receives the instance in its args instead of re-deriving storage from paths — deleting all nine scattered constructions.Curated surface (rung 5): exports
ChatSessionRepository,FileChatSessionRepository,ChatSessionCatalog(Entry), andChatSessionso implementers have the full contract.Proof
chat-sessions.catalog.jsonis never created.Verification
yarn build— passyarn test:unit— 601 passed ·yarn test:integration— 285 passedyarn lint— cleanDocs: "Bring your own session storage" guide section, ladder README rung 5 updated, curated index rung-5 note updated. Traces and memory remain path-oriented — next slices, same pattern.
🤖 Generated with Claude Code
https://claude.ai/code/session_01CjFdZgZhov8wdwFinVTfjz