mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-08 07:17:39 +00:00
feat(codex): import and resume sessions from runners (#1088)
* fix codex import resume flow * fix hub restart session active state * fix codex transcript workspace scoping * Address Codex import review findings * Fix Codex import machine selection * Update Codex sessions error test * Address Codex import review findings * Preserve forked Codex session id on sync * Make Codex duplicate cleanup source-aware * Handle Codex archive failures * Limit existing session flag to Codex * Preserve Codex import machine binding * fix: rebase runner Codex import onto current main * fix: preserve runner-scoped Codex import behavior --------- Co-authored-by: syy <815728149@qq.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { isPermissionModeAllowedForFlavor } from '@hapi/protocol'
|
||||
import type { ApiClient } from '@/api/client'
|
||||
import type { CodexCollaborationMode, PermissionMode } from '@/types/api'
|
||||
import type { CodexCollaborationMode, PermissionMode, SessionResponse, SessionsResponse } from '@/types/api'
|
||||
import type { ReopenSessionResponse } from '@hapi/protocol/apiTypes'
|
||||
import { queryKeys } from '@/lib/query-keys'
|
||||
import { clearMessageWindow } from '@/lib/message-window-store'
|
||||
@@ -29,6 +29,36 @@ export function useSessionActions(
|
||||
} {
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
const markSessionActiveInCache = (targetSessionId: string) => {
|
||||
// 中文注释:恢复/重开接口成功后,session-alive SSE 可能已经先到或稍后才到。
|
||||
// 这里先乐观更新详情和侧边栏摘要,避免 UI 在下一次 SSE/REST 前仍显示离线。
|
||||
queryClient.setQueryData<SessionResponse | undefined>(queryKeys.session(targetSessionId), (previous) => {
|
||||
if (!previous?.session) return previous
|
||||
return {
|
||||
...previous,
|
||||
session: {
|
||||
...previous.session,
|
||||
active: true,
|
||||
activeAt: Math.max(previous.session.activeAt ?? 0, Date.now())
|
||||
}
|
||||
}
|
||||
})
|
||||
queryClient.setQueryData<SessionsResponse | undefined>(queryKeys.sessions, (previous) => {
|
||||
if (!previous) return previous
|
||||
let changed = false
|
||||
const sessions = previous.sessions.map((summary) => {
|
||||
if (summary.id !== targetSessionId) return summary
|
||||
changed = true
|
||||
return {
|
||||
...summary,
|
||||
active: true,
|
||||
activeAt: Math.max(summary.activeAt ?? 0, Date.now())
|
||||
}
|
||||
})
|
||||
return changed ? { ...previous, sessions } : previous
|
||||
})
|
||||
}
|
||||
|
||||
const invalidateSession = async () => {
|
||||
if (!sessionId) return
|
||||
await queryClient.invalidateQueries({ queryKey: queryKeys.session(sessionId) })
|
||||
@@ -68,7 +98,12 @@ export function useSessionActions(
|
||||
}
|
||||
return await api.reopenSession(sessionId)
|
||||
},
|
||||
onSuccess: () => void invalidateSession(),
|
||||
onSuccess: (result) => {
|
||||
void (async () => {
|
||||
await invalidateSession()
|
||||
markSessionActiveInCache(result.sessionId)
|
||||
})()
|
||||
},
|
||||
})
|
||||
|
||||
const switchMutation = useMutation({
|
||||
|
||||
@@ -346,6 +346,9 @@ export function useSSE(options: {
|
||||
? patch.backgroundTaskCount ?? 0
|
||||
: current.backgroundTaskCount,
|
||||
model: Object.prototype.hasOwnProperty.call(patch, 'model') ? patch.model ?? null : current.model,
|
||||
modelReasoningEffort: Object.prototype.hasOwnProperty.call(patch, 'modelReasoningEffort')
|
||||
? patch.modelReasoningEffort ?? null
|
||||
: current.modelReasoningEffort,
|
||||
effort: Object.prototype.hasOwnProperty.call(patch, 'effort') ? patch.effort ?? null : current.effort
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user