Commit 244702c4 authored by edy's avatar edy

会话管理bug修复

parent d88fa0ca
...@@ -61,6 +61,31 @@ export function useChatSessionsController(deps: UseChatSessionsControllerDeps) { ...@@ -61,6 +61,31 @@ export function useChatSessionsController(deps: UseChatSessionsControllerDeps) {
setActiveProjectSession(preferredSessionId) setActiveProjectSession(preferredSessionId)
}, [activeSessionId, preferredSessionId, setActiveProjectSession]) }, [activeSessionId, preferredSessionId, setActiveProjectSession])
useEffect(() => {
if (!workspace || !sessionScopeProjectId || workspace.currentProjectId !== sessionScopeProjectId) {
return
}
const scopedWorkspaceSessions = workspace.sessions.filter((session) => session.projectId === sessionScopeProjectId)
if (!scopedWorkspaceSessions.length) {
return
}
setSessions(scopedWorkspaceSessions)
if (sendPhase !== "idle" || scopedWorkspaceSessions.some((session) => session.id === activeSessionId)) {
return
}
setActiveProjectSession(scopedWorkspaceSessions[0].id)
}, [
activeSessionId,
sendPhase,
sessionScopeProjectId,
setActiveProjectSession,
setSessions,
workspace
])
useEffect(() => { useEffect(() => {
let cancelled = false let cancelled = false
const preserveVisibleConversation = sendPhase !== "idle" const preserveVisibleConversation = sendPhase !== "idle"
...@@ -151,19 +176,53 @@ export function useChatSessionsController(deps: UseChatSessionsControllerDeps) { ...@@ -151,19 +176,53 @@ export function useChatSessionsController(deps: UseChatSessionsControllerDeps) {
return return
} }
const preserveVisibleConversation = sendPhase !== "idle"
setProjectActionPending(true) setProjectActionPending(true)
setErrorText("") setErrorText("")
try { try {
const nextWorkspace = await desktopApi.projects.setActive(projectId) const nextWorkspace = await desktopApi.projects.setActive(projectId)
setWorkspace(nextWorkspace) setWorkspace(nextWorkspace)
if (nextWorkspace.currentProjectId === projectId) {
const nextSessions = nextWorkspace.sessions.filter((session) => session.projectId === projectId)
if (nextSessions.length) {
setSessions(nextSessions)
const nextSessionId = resolvePreferredSessionId(nextSessions, activeSessionId)
if (nextSessionId) {
setActiveProjectSession(nextSessionId)
}
} else if (!preserveVisibleConversation) {
clearSessions()
clearAllSessionMessages()
setActiveProjectSession(EMPTY_SESSION_ID)
}
} else if (!preserveVisibleConversation) {
clearSessions() clearSessions()
clearAllSessionMessages() clearAllSessionMessages()
setActiveProjectSession(EMPTY_SESSION_ID)
}
} catch (error) { } catch (error) {
if (!preserveVisibleConversation) {
clearSessions()
clearAllSessionMessages()
setActiveProjectSession(EMPTY_SESSION_ID)
}
setErrorText(error instanceof Error ? error.message : String(error)) setErrorText(error instanceof Error ? error.message : String(error))
} finally { } finally {
setProjectActionPending(false) setProjectActionPending(false)
} }
}, [clearAllSessionMessages, clearSessions, desktopApi.projects, projectActionPending, setErrorText, setWorkspace]) }, [
activeSessionId,
clearAllSessionMessages,
clearSessions,
desktopApi.projects,
projectActionPending,
sendPhase,
setActiveProjectSession,
setErrorText,
setSessions,
setWorkspace
])
const switchProjectPreservingMessages = useCallback(async (projectId: string) => { const switchProjectPreservingMessages = useCallback(async (projectId: string) => {
if (projectActionPending) { if (projectActionPending) {
......
...@@ -115,6 +115,7 @@ const finalState = result.finalState || {}; ...@@ -115,6 +115,7 @@ const finalState = result.finalState || {};
const finalWorkspace = finalState.workspaceSummary || {}; const finalWorkspace = finalState.workspaceSummary || {};
const expertEntry = sendResult.expertEntry || {}; const expertEntry = sendResult.expertEntry || {};
const experts = finalState.experts || {}; const experts = finalState.experts || {};
const finalSessions = Array.isArray(finalState.sessions) ? finalState.sessions : [];
const standaloneIds = Array.isArray(experts.standaloneIds) ? experts.standaloneIds.map((value) => String(value || '')).sort() : []; const standaloneIds = Array.isArray(experts.standaloneIds) ? experts.standaloneIds.map((value) => String(value || '')).sort() : [];
const homeShortcutIds = Array.isArray(experts.homeShortcutIds) ? experts.homeShortcutIds.map((value) => String(value || '')).sort() : []; const homeShortcutIds = Array.isArray(experts.homeShortcutIds) ? experts.homeShortcutIds.map((value) => String(value || '')).sort() : [];
const standalonePromptAvailableIds = Array.isArray(experts.standalonePromptAvailableIds) ? experts.standalonePromptAvailableIds.map((value) => String(value || '')).sort() : []; const standalonePromptAvailableIds = Array.isArray(experts.standalonePromptAvailableIds) ? experts.standalonePromptAvailableIds.map((value) => String(value || '')).sort() : [];
...@@ -157,6 +158,16 @@ if (expectedStandaloneIds.includes(expectedExpertEntryId)) { ...@@ -157,6 +158,16 @@ if (expectedStandaloneIds.includes(expectedExpertEntryId)) {
if (String(finalWorkspace.currentProjectId || '') !== String(expertEntry.currentProjectId || '')) { if (String(finalWorkspace.currentProjectId || '') !== String(expertEntry.currentProjectId || '')) {
throw new Error('Standalone expert final project mismatch: ' + String(finalWorkspace.currentProjectId || '')); throw new Error('Standalone expert final project mismatch: ' + String(finalWorkspace.currentProjectId || ''));
} }
if (String(finalState.ui && finalState.ui.sessionScopeProjectId || '') !== String(finalWorkspace.currentProjectId || '')) {
throw new Error('Standalone expert session scope mismatch: ' + String(finalState.ui && finalState.ui.sessionScopeProjectId || ''));
}
if (finalSessions.length < 1) {
throw new Error('Standalone expert did not expose any sessions for project: ' + String(finalWorkspace.currentProjectId || ''));
}
const foreignSession = finalSessions.find((session) => String(session && session.projectId || '') !== String(finalWorkspace.currentProjectId || ''));
if (foreignSession) {
throw new Error('Standalone expert exposed a session from another project: ' + JSON.stringify(foreignSession));
}
} else if (expectedHomeShortcutIds.includes(expectedExpertEntryId)) { } else if (expectedHomeShortcutIds.includes(expectedExpertEntryId)) {
if (String(finalState.viewMode || '') !== 'chat') { if (String(finalState.viewMode || '') !== 'chat') {
throw new Error('Home shortcut did not land on chat view.'); throw new Error('Home shortcut did not land on chat view.');
...@@ -190,6 +201,8 @@ console.log(JSON.stringify({ ...@@ -190,6 +201,8 @@ console.log(JSON.stringify({
entryMode: expertEntry.entryMode || null, entryMode: expertEntry.entryMode || null,
finalViewMode: finalState.viewMode || null, finalViewMode: finalState.viewMode || null,
currentProjectId: finalWorkspace.currentProjectId || null, currentProjectId: finalWorkspace.currentProjectId || null,
sessionScopeProjectId: finalState.ui && finalState.ui.sessionScopeProjectId || null,
sessionCount: finalSessions.length,
standaloneIds, standaloneIds,
homeShortcutIds, homeShortcutIds,
standalonePromptAvailableIds standalonePromptAvailableIds
......
...@@ -461,6 +461,7 @@ if (smokeViewMode === 'skills') { ...@@ -461,6 +461,7 @@ if (smokeViewMode === 'skills') {
const finalWorkspace = finalState.workspaceSummary || {}; const finalWorkspace = finalState.workspaceSummary || {};
const experts = finalState.experts || {}; const experts = finalState.experts || {};
const expertEntry = sendResult.expertEntry || {}; const expertEntry = sendResult.expertEntry || {};
const finalSessions = Array.isArray(finalState.sessions) ? finalState.sessions : [];
const standaloneIds = Array.isArray(experts.standaloneIds) const standaloneIds = Array.isArray(experts.standaloneIds)
? experts.standaloneIds.map((value) => String(value || '')).sort() ? experts.standaloneIds.map((value) => String(value || '')).sort()
: []; : [];
...@@ -502,6 +503,16 @@ if (smokeViewMode === 'skills') { ...@@ -502,6 +503,16 @@ if (smokeViewMode === 'skills') {
if (!standalonePromptAvailableIds.includes(smokeExpertEntryId)) { if (!standalonePromptAvailableIds.includes(smokeExpertEntryId)) {
throw new Error('Standalone expert id did not report prompt availability: ' + smokeExpertEntryId); throw new Error('Standalone expert id did not report prompt availability: ' + smokeExpertEntryId);
} }
if (String(finalState.ui && finalState.ui.sessionScopeProjectId || '') !== String(finalWorkspace.currentProjectId || '')) {
throw new Error('Standalone expert final session scope mismatch: ' + String(finalState.ui && finalState.ui.sessionScopeProjectId || ''));
}
if (finalSessions.length < 1) {
throw new Error('Standalone expert final state did not expose project sessions for: ' + String(finalWorkspace.currentProjectId || ''));
}
const foreignSession = finalSessions.find((session) => String(session && session.projectId || '') !== String(finalWorkspace.currentProjectId || ''));
if (foreignSession) {
throw new Error('Standalone expert final state exposed a session from another project: ' + JSON.stringify(foreignSession));
}
const streamSessionId = String(streamSmoke.sessionId || sendResult.sessionId || ''); const streamSessionId = String(streamSmoke.sessionId || sendResult.sessionId || '');
if (streamSessionId && !streamSessionId.startsWith('project:' + String(expertEntry.currentProjectId || '') + ':')) { if (streamSessionId && !streamSessionId.startsWith('project:' + String(expertEntry.currentProjectId || '') + ':')) {
throw new Error('Standalone expert entry did not send through the expected project session. session=' + streamSessionId + ' expected=' + String(expertEntry.currentProjectId || '')); throw new Error('Standalone expert entry did not send through the expected project session. session=' + streamSessionId + ' expected=' + String(expertEntry.currentProjectId || ''));
...@@ -821,4 +832,3 @@ finally { ...@@ -821,4 +832,3 @@ finally {
Remove-Item Env:QJCLAW_SMOKE_STARTUP_ONLY -ErrorAction SilentlyContinue Remove-Item Env:QJCLAW_SMOKE_STARTUP_ONLY -ErrorAction SilentlyContinue
Remove-Item Env:QJCLAW_SECRET_BACKEND -ErrorAction SilentlyContinue Remove-Item Env:QJCLAW_SECRET_BACKEND -ErrorAction SilentlyContinue
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment