fix(cli): restaure la conversation au retour de layout via cache conversationId+sessionId — #217
This commit is contained in:
@ -67,15 +67,18 @@ interface CachedChatView {
|
||||
turns: ChatTurn[];
|
||||
progressIndex: Map<string, ProgressIndexEntry>;
|
||||
chunkCount: number;
|
||||
sessionId?: string;
|
||||
}
|
||||
|
||||
const chatSessionViewCache = new Map<string, CachedChatView>();
|
||||
const chatConversationViewCache = new Map<string, CachedChatView>();
|
||||
const EMPTY_MODEL_RESPONSE_MESSAGE = "Le modèle n'a renvoyé aucune réponse.";
|
||||
const COMPOSER_RESIZE_STEP = 12;
|
||||
const FALLBACK_COMPOSER_HEIGHT = 64;
|
||||
|
||||
export function __clearCustomAgentChatViewCacheForTests() {
|
||||
chatSessionViewCache.clear();
|
||||
chatConversationViewCache.clear();
|
||||
}
|
||||
|
||||
interface AttachmentDraft {
|
||||
@ -310,6 +313,14 @@ function emptyChatViewState(): ChatViewState {
|
||||
return { turns: [], progressIndex: new Map() };
|
||||
}
|
||||
|
||||
function conversationCacheKey(
|
||||
projectId: string,
|
||||
agentId: string,
|
||||
conversationId: string | null,
|
||||
): string | null {
|
||||
return conversationId ? `${projectId}::${agentId}::${conversationId}` : null;
|
||||
}
|
||||
|
||||
function appendProgress(state: ChatViewState, progress: ReplyProgress): ChatViewState {
|
||||
const key = progressUpsertKey(progress);
|
||||
const existingIndex = state.turns.findIndex(
|
||||
@ -711,10 +722,27 @@ export function CustomAgentChatView({
|
||||
}: CustomAgentChatViewProps) {
|
||||
const { agent, profile: profileGateway, system } = useGateways();
|
||||
const pluginRuntime = usePluginRuntime();
|
||||
const [turns, setTurns] = useState<ChatTurn[]>(
|
||||
() => (sessionId ? (chatSessionViewCache.get(sessionId)?.turns ?? []) : []),
|
||||
const initialConversationCacheKey = conversationCacheKey(
|
||||
projectId,
|
||||
agentId,
|
||||
conversationId,
|
||||
);
|
||||
const [turns, setTurns] = useState<ChatTurn[]>(
|
||||
() =>
|
||||
sessionId
|
||||
? (chatSessionViewCache.get(sessionId)?.turns ?? [])
|
||||
: initialConversationCacheKey
|
||||
? (chatConversationViewCache.get(initialConversationCacheKey)?.turns ?? [])
|
||||
: [],
|
||||
);
|
||||
const [progressIndex, setProgressIndex] = useState<Map<string, ProgressIndexEntry>>(
|
||||
() =>
|
||||
sessionId
|
||||
? (chatSessionViewCache.get(sessionId)?.progressIndex ?? new Map())
|
||||
: initialConversationCacheKey
|
||||
? (chatConversationViewCache.get(initialConversationCacheKey)?.progressIndex ?? new Map())
|
||||
: new Map(),
|
||||
);
|
||||
const [progressIndex, setProgressIndex] = useState<Map<string, ProgressIndexEntry>>(new Map());
|
||||
const [currentSession, setCurrentSession] = useState(sessionId);
|
||||
const [externalSessionId, setExternalSessionId] = useState(sessionId);
|
||||
const [draft, setDraft] = useState("");
|
||||
@ -724,7 +752,7 @@ export function CustomAgentChatView({
|
||||
const [slashActiveIndex, setSlashActiveIndex] = useState(0);
|
||||
const [profileDialog, setProfileDialog] =
|
||||
useState<ProfileCommandDialogState | null>(null);
|
||||
const [opening, setOpening] = useState(Boolean(sessionId));
|
||||
const [opening, setOpening] = useState(Boolean(sessionId || conversationId));
|
||||
const [busy, setBusy] = useState(false);
|
||||
const [stopping, setStopping] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
@ -849,6 +877,10 @@ export function CustomAgentChatView({
|
||||
() => (layoutId ? { projectId, layoutId, nodeId } : null),
|
||||
[layoutId, nodeId, projectId],
|
||||
);
|
||||
const currentConversationCacheKey = useMemo(
|
||||
() => conversationCacheKey(projectId, agentId, conversationId),
|
||||
[agentId, conversationId, projectId],
|
||||
);
|
||||
const displayTurns = turns;
|
||||
|
||||
const clearPersistedDraft = useCallback(async () => {
|
||||
@ -918,13 +950,27 @@ export function CustomAgentChatView({
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!currentSession) return;
|
||||
chatSessionViewCache.set(currentSession, {
|
||||
turns,
|
||||
progressIndex,
|
||||
chunkCount: scrollbackChunkCountRef.current,
|
||||
});
|
||||
}, [currentSession, progressIndex, turns]);
|
||||
if (currentSession) {
|
||||
chatSessionViewCache.set(currentSession, {
|
||||
turns,
|
||||
progressIndex,
|
||||
chunkCount: scrollbackChunkCountRef.current,
|
||||
sessionId: currentSession,
|
||||
});
|
||||
}
|
||||
if (currentConversationCacheKey) {
|
||||
const previous = chatConversationViewCache.get(currentConversationCacheKey);
|
||||
const cachedSessionId = currentSession ?? previous?.sessionId;
|
||||
if (cachedSessionId || turns.length > 0 || progressIndex.size > 0) {
|
||||
chatConversationViewCache.set(currentConversationCacheKey, {
|
||||
turns,
|
||||
progressIndex,
|
||||
chunkCount: scrollbackChunkCountRef.current,
|
||||
...(cachedSessionId ? { sessionId: cachedSessionId } : {}),
|
||||
});
|
||||
}
|
||||
}
|
||||
}, [currentConversationCacheKey, currentSession, progressIndex, turns]);
|
||||
|
||||
useEffect(() => {
|
||||
draftSaveSeqRef.current += 1;
|
||||
@ -1216,6 +1262,15 @@ export function CustomAgentChatView({
|
||||
setOpening(true);
|
||||
setError(null);
|
||||
try {
|
||||
const localSession = sessionRef.current;
|
||||
if (!externalSessionId && localSession) {
|
||||
console.debug("[ticket149] openOrAttach:local-session-present:skip", {
|
||||
timestamp: new Date().toISOString(),
|
||||
execution,
|
||||
currentSession: localSession,
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (externalSessionId) {
|
||||
const cached = chatSessionViewCache.get(externalSessionId);
|
||||
if (cached) {
|
||||
@ -1250,9 +1305,32 @@ export function CustomAgentChatView({
|
||||
error: instrumentationError(e),
|
||||
});
|
||||
}
|
||||
} else if (currentConversationCacheKey) {
|
||||
const cached = chatConversationViewCache.get(currentConversationCacheKey);
|
||||
if (cached) {
|
||||
scrollbackChunkCountRef.current = cached.chunkCount;
|
||||
applyChatViewState({
|
||||
turns: cached.turns,
|
||||
progressIndex: cached.progressIndex ?? new Map(),
|
||||
});
|
||||
if (cached.sessionId) {
|
||||
const reattachedSessionId = await reattachStructuredSession(cached.sessionId, {
|
||||
applyScrollback: true,
|
||||
});
|
||||
if (cancelled) return;
|
||||
publishSessionId(reattachedSessionId);
|
||||
console.debug("[ticket149] openOrAttach:reattach-conversation-cache:success", {
|
||||
timestamp: new Date().toISOString(),
|
||||
execution,
|
||||
sessionId: reattachedSessionId,
|
||||
});
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
await recoverStructuredSession({
|
||||
applyScrollback: false,
|
||||
applyScrollback: Boolean(conversationId),
|
||||
retryAttachNotFound: true,
|
||||
});
|
||||
if (cancelled) return;
|
||||
@ -1285,6 +1363,8 @@ export function CustomAgentChatView({
|
||||
recoverStructuredSession,
|
||||
publishSessionId,
|
||||
applyChatViewState,
|
||||
currentConversationCacheKey,
|
||||
conversationId,
|
||||
]);
|
||||
|
||||
const canSend = useMemo(
|
||||
|
||||
Reference in New Issue
Block a user