fix: improve syncing when switching conversations

This commit is contained in:
Danny Avila 2025-12-12 01:10:08 -05:00
parent 8018762f11
commit 1b2d3f30ef
No known key found for this signature in database
GPG key ID: BF31EEB2C5CA0956
14 changed files with 314 additions and 176 deletions

View file

@ -14,6 +14,7 @@ const {
getBalanceConfig,
getProviderConfig,
memoryInstructions,
GenerationJobManager,
getTransactionsConfig,
createMemoryProcessor,
filterMalformedContentParts,
@ -953,6 +954,12 @@ class AgentClient extends BaseClient {
}
this.run = run;
const streamId = this.options.req?._resumableStreamId;
if (streamId && run.Graph) {
GenerationJobManager.setGraph(streamId, run.Graph);
}
if (userMCPAuthMap != null) {
config.configurable.userMCPAuthMap = userMCPAuthMap;
}

View file

@ -144,6 +144,11 @@ const ResumableAgentController = async (req, res, next, initializeClient, addTit
GenerationJobManager.updateMetadata(streamId, { sender: client.sender });
}
// Store reference to client's contentParts - graph will be set when run is created
if (client?.contentParts) {
GenerationJobManager.setContentParts(streamId, client.contentParts);
}
res.json({ streamId, status: 'started' });
let conversationId = reqConversationId;

View file

@ -56,17 +56,20 @@ router.get('/chat/stream/:streamId', (req, res) => {
logger.debug(`[AgentStream] Client subscribed to ${streamId}, resume: ${isResume}`);
// Send sync event with resume state for reconnecting clients
if (isResume && !GenerationJobManager.wasSyncSent(streamId)) {
// Send sync event with resume state for ALL reconnecting clients
// This supports multi-tab scenarios where each tab needs run step data
if (isResume) {
const resumeState = GenerationJobManager.getResumeState(streamId);
if (resumeState && !res.writableEnded) {
// Send sync event with run steps AND aggregatedContent
// Client will use aggregatedContent to initialize message state
res.write(`event: message\ndata: ${JSON.stringify({ sync: true, resumeState })}\n\n`);
if (typeof res.flush === 'function') {
res.flush();
}
GenerationJobManager.markSyncSent(streamId);
const textPart = resumeState.aggregatedContent?.find((p) => p.type === 'text');
logger.debug(
`[AgentStream] Sent sync event for ${streamId} with ${resumeState.runSteps.length} run steps`,
`[AgentStream] Sent sync event for ${streamId} with ${resumeState.runSteps.length} run steps, content length: ${textPart?.text?.length ?? 0}`,
);
}
}