fix: persist direct chat transcript before Goosed escalation

Prevent portal direct-chat history from being lost when snapshot cache
is invalidated on Goosed submit by writing non-empty messages to DB first,
and stop caching empty Goose placeholder messages in snapshots.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-07-05 11:16:55 +08:00
parent 614837e199
commit bdeab23b83
6 changed files with 311 additions and 5 deletions
+39
View File
@@ -2,6 +2,11 @@ import crypto from 'node:crypto';
import fs from 'node:fs/promises';
import path from 'node:path';
import { isDirectChatSessionId } from './direct-chat-service.mjs';
import {
loadSnapshotMessages,
persistSessionTranscriptFromSnapshot,
persistSessionTranscriptMessages,
} from './conversation-transcript-persist.mjs';
const DEFAULT_RUN_RETRY_DELAYS_MS = [1500, 5000, 15000];
const TERMINAL_STATUSES = new Set(['succeeded', 'failed']);
@@ -225,6 +230,7 @@ export function createAgentRunGateway({
directChatService = null,
chatIntentRouter = null,
sessionSnapshotService = null,
conversationMemoryService = null,
retryDelaysMs = DEFAULT_RUN_RETRY_DELAYS_MS,
autoDispatch = envFlag(process.env.MEMIND_AGENT_RUN_AUTODISPATCH, true),
maxConcurrentRuns = positiveInteger(
@@ -546,7 +552,9 @@ export function createAgentRunGateway({
}
let sessionId = row.agent_session_id ?? null;
let escalatedDirectSessionId = null;
if (isDirectChatSessionId(sessionId)) {
escalatedDirectSessionId = sessionId;
await appendEvent(runId, 'direct_session_escalated_to_deep_reasoning', {
previousSessionId: sessionId,
});
@@ -568,8 +576,39 @@ export function createAgentRunGateway({
toolMode: runOptions.toolMode,
taskType: runOptions.taskType,
});
if (escalatedDirectSessionId) {
const priorMessages = await loadSnapshotMessages(
sessionSnapshotService,
escalatedDirectSessionId,
);
const persisted = await persistSessionTranscriptMessages({
conversationMemoryService,
sessionId,
userId: row.user_id,
messages: priorMessages,
});
if (persisted.saved > 0) {
await appendEvent(runId, 'direct_session_transcript_persisted', {
previousSessionId: escalatedDirectSessionId,
sessionId,
saved: persisted.saved,
});
}
}
}
const transcriptPersisted = await persistSessionTranscriptFromSnapshot({
sessionSnapshotService,
conversationMemoryService,
sessionId,
userId: row.user_id,
});
if (transcriptPersisted.saved > 0) {
await appendEvent(runId, 'portal_direct_transcript_persisted', {
sessionId,
saved: transcriptPersisted.saved,
});
}
await invalidatePortalDirectChatSnapshot(sessionId);
await tkmindProxy.submitSessionReplyForUser(
row.user_id,