SCAL-336112: share one conversation fetch across replayed MCP frames - #693
Open
mouryabalabhadra wants to merge 2 commits into
Open
mouryabalabhadra wants to merge 2 commits into
mouryabalabhadra wants to merge 2 commits into
Conversation
### Summary
Replaying a stored conversation mounts every answer frame at once, and each `AutoFrameRenderer` resolved on its own. A conversation with N answers made N identical `GET /conversation/v2/{id}/public` calls, plus the N `POST .../load/public` calls it needs anyway.
### Change
- The list step moves out of `resolveAnswerSessionParams` into `fetchAnswerIds()`, which never rejects and returns `null` on failure.
- `getAnswerIds()` keeps a module-level `Map<conversationUrl, Promise<string[] | null>>` of **in-flight** list requests only:
- Frames from the same conversation that resolve together share one `GET`.
- The entry is removed as soon as its request settles, whether it succeeded or failed. A failed response is never reused, and a frame mounted later always reads a fresh list. Nothing is cached long-term, so a stored list can't go stale.
- The `load` POST is never shared: it returns live session state with its own expiry, and each answer needs its own.
- **Index miss.** The answer list only grows as messages are appended, so a list too short for the requested index may predate the answer. The frame reads the list once more before failing. Frames that miss together share that second read.
- Key is the full conversation-service URL, so different conversations (and hosts) never share.
### Compatibility
No API or behaviour change for host apps, apart from the extra list read on an index miss. `developer-examples/mcp/python-react-agent-simple-ui` works unchanged on `^1.52.1` and picks this up on the next release.
### Testing
New cases in `auto-frame-renderer.spec.ts`:
- Two concurrent frames from one conversation → one list call, two load calls, both resolved.
- Frames from different conversations → separate list calls.
- A failed list is not reused by a later frame.
- A frame mounted after the batch settles reads a fresh list.
- A list too short for the index is read exactly once more. Two concurrent missing frames share that re-read and both resolve.
Contributor
There was a problem hiding this comment.
Code Review
This pull request optimizes the replay of stored chats by sharing in-flight answer-id list requests across concurrent frames of the same conversation, preventing redundant API calls. It also adds comprehensive unit tests to verify this behavior under various scenarios. The review feedback correctly identifies JSDoc formatting issues in the newly added helper functions, specifically pointing out missing parameter and return tags and their canonical ordering according to the style guide.
commit: |
Rifdhan
approved these changes
Oct 1, 2026
This branch has not been deployed
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
Replaying a stored conversation mounts every answer frame at once, and each
AutoFrameRendererresolved on its own. A conversation with N answers made N identicalGET /conversation/v2/{id}/publiccalls, plus the NPOST .../load/publiccalls it needs anyway.Change
resolveAnswerSessionParamsintofetchAnswerIds(), which never rejects and returnsnullon failure.getAnswerIds()keeps a module-levelMap<conversationUrl, Promise<string[] | null>>of in-flight list requests only:GET.loadPOST is never shared: it returns live session state with its own expiry, and each answer needs its own.Compatibility
No API or behaviour change for host apps, apart from the extra list read on an index miss.
developer-examples/mcp/python-react-agent-simple-uiworks unchanged on^1.52.1and picks this up on the next release.Testing
New cases in
auto-frame-renderer.spec.ts: