mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-08 07:17:39 +00:00
178 lines
6.6 KiB
TypeScript
178 lines
6.6 KiB
TypeScript
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 { queryKeys } from '@/lib/query-keys'
|
|
import { clearMessageWindow } from '@/lib/message-window-store'
|
|
import { isKnownFlavor } from '@/lib/agentFlavorUtils'
|
|
|
|
export function useSessionActions(
|
|
api: ApiClient | null,
|
|
sessionId: string | null,
|
|
agentFlavor?: string | null,
|
|
codexCollaborationModeSupported?: boolean
|
|
): {
|
|
abortSession: () => Promise<void>
|
|
archiveSession: () => Promise<void>
|
|
switchSession: () => Promise<void>
|
|
setPermissionMode: (mode: PermissionMode) => Promise<void>
|
|
setCollaborationMode: (mode: CodexCollaborationMode) => Promise<void>
|
|
setModel: (model: string | null) => Promise<void>
|
|
setModelReasoningEffort: (modelReasoningEffort: string | null) => Promise<void>
|
|
setEffort: (effort: string | null) => Promise<void>
|
|
renameSession: (name: string) => Promise<void>
|
|
deleteSession: () => Promise<void>
|
|
isPending: boolean
|
|
} {
|
|
const queryClient = useQueryClient()
|
|
|
|
const invalidateSession = async () => {
|
|
if (!sessionId) return
|
|
await queryClient.invalidateQueries({ queryKey: queryKeys.session(sessionId) })
|
|
await queryClient.invalidateQueries({ queryKey: queryKeys.sessions })
|
|
}
|
|
|
|
const abortMutation = useMutation({
|
|
mutationFn: async () => {
|
|
if (!api || !sessionId) {
|
|
throw new Error('Session unavailable')
|
|
}
|
|
await api.abortSession(sessionId)
|
|
},
|
|
onSuccess: () => void invalidateSession(),
|
|
})
|
|
|
|
const archiveMutation = useMutation({
|
|
mutationFn: async () => {
|
|
if (!api || !sessionId) {
|
|
throw new Error('Session unavailable')
|
|
}
|
|
await api.archiveSession(sessionId)
|
|
},
|
|
onSuccess: () => void invalidateSession(),
|
|
})
|
|
|
|
const switchMutation = useMutation({
|
|
mutationFn: async () => {
|
|
if (!api || !sessionId) {
|
|
throw new Error('Session unavailable')
|
|
}
|
|
await api.switchSession(sessionId)
|
|
},
|
|
onSuccess: () => void invalidateSession(),
|
|
})
|
|
|
|
const permissionMutation = useMutation({
|
|
mutationFn: async (mode: PermissionMode) => {
|
|
if (!api || !sessionId) {
|
|
throw new Error('Session unavailable')
|
|
}
|
|
if (isKnownFlavor(agentFlavor) && !isPermissionModeAllowedForFlavor(mode, agentFlavor)) {
|
|
throw new Error('Invalid permission mode for session flavor')
|
|
}
|
|
await api.setPermissionMode(sessionId, mode)
|
|
},
|
|
onSuccess: () => void invalidateSession(),
|
|
})
|
|
|
|
const collaborationMutation = useMutation({
|
|
mutationFn: async (mode: CodexCollaborationMode) => {
|
|
if (!api || !sessionId) {
|
|
throw new Error('Session unavailable')
|
|
}
|
|
if (agentFlavor !== 'codex') {
|
|
throw new Error('Collaboration mode is only supported for Codex sessions')
|
|
}
|
|
if (!codexCollaborationModeSupported) {
|
|
throw new Error('Collaboration mode is only supported for remote Codex sessions')
|
|
}
|
|
await api.setCollaborationMode(sessionId, mode)
|
|
},
|
|
onSuccess: () => void invalidateSession(),
|
|
})
|
|
|
|
const modelMutation = useMutation({
|
|
mutationFn: async (model: string | null) => {
|
|
if (!api || !sessionId) {
|
|
throw new Error('Session unavailable')
|
|
}
|
|
await api.setModel(sessionId, model)
|
|
},
|
|
onSuccess: () => void invalidateSession(),
|
|
})
|
|
|
|
const modelReasoningEffortMutation = useMutation({
|
|
mutationFn: async (modelReasoningEffort: string | null) => {
|
|
if (!api || !sessionId) {
|
|
throw new Error('Session unavailable')
|
|
}
|
|
if (agentFlavor !== 'codex') {
|
|
throw new Error('Model reasoning effort is only supported for Codex sessions')
|
|
}
|
|
if (!codexCollaborationModeSupported) {
|
|
throw new Error('Model reasoning effort is only supported for remote Codex sessions')
|
|
}
|
|
await api.setModelReasoningEffort(sessionId, modelReasoningEffort)
|
|
},
|
|
onSuccess: () => void invalidateSession(),
|
|
})
|
|
|
|
const effortMutation = useMutation({
|
|
mutationFn: async (effort: string | null) => {
|
|
if (!api || !sessionId) {
|
|
throw new Error('Session unavailable')
|
|
}
|
|
await api.setEffort(sessionId, effort)
|
|
},
|
|
onSuccess: () => void invalidateSession(),
|
|
})
|
|
|
|
const renameMutation = useMutation({
|
|
mutationFn: async (name: string) => {
|
|
if (!api || !sessionId) {
|
|
throw new Error('Session unavailable')
|
|
}
|
|
await api.renameSession(sessionId, name)
|
|
},
|
|
onSuccess: () => void invalidateSession(),
|
|
})
|
|
|
|
const deleteMutation = useMutation({
|
|
mutationFn: async () => {
|
|
if (!api || !sessionId) {
|
|
throw new Error('Session unavailable')
|
|
}
|
|
await api.deleteSession(sessionId)
|
|
},
|
|
onSuccess: async () => {
|
|
if (!sessionId) return
|
|
queryClient.removeQueries({ queryKey: queryKeys.session(sessionId) })
|
|
clearMessageWindow(sessionId)
|
|
await queryClient.invalidateQueries({ queryKey: queryKeys.sessions })
|
|
},
|
|
})
|
|
|
|
return {
|
|
abortSession: abortMutation.mutateAsync,
|
|
archiveSession: archiveMutation.mutateAsync,
|
|
switchSession: switchMutation.mutateAsync,
|
|
setPermissionMode: permissionMutation.mutateAsync,
|
|
setCollaborationMode: collaborationMutation.mutateAsync,
|
|
setModel: modelMutation.mutateAsync,
|
|
setModelReasoningEffort: modelReasoningEffortMutation.mutateAsync,
|
|
setEffort: effortMutation.mutateAsync,
|
|
renameSession: renameMutation.mutateAsync,
|
|
deleteSession: deleteMutation.mutateAsync,
|
|
isPending: abortMutation.isPending
|
|
|| archiveMutation.isPending
|
|
|| switchMutation.isPending
|
|
|| permissionMutation.isPending
|
|
|| collaborationMutation.isPending
|
|
|| modelMutation.isPending
|
|
|| modelReasoningEffortMutation.isPending
|
|
|| effortMutation.isPending
|
|
|| renameMutation.isPending
|
|
|| deleteMutation.isPending,
|
|
}
|
|
}
|