Files
test1/components/nova-sdk/hooks/useNovaService.ts
2026-03-20 07:33:46 +00:00

160 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useMemo, useCallback } from 'react'
import { request } from '@/http/request'
import type { TaskArtifact } from '../types'
import type { PlatformConfig } from './useNovaEvents'
export interface ConversationInfo {
conversation_id: string
title?: string
task_status?: string
is_read?: boolean
is_favourite?: boolean
}
interface UseNovaServiceProps {
platformConfig?: PlatformConfig
getToken?: () => string | undefined
getTenantId?: () => string | undefined
conversationId?: string
}
interface DirFileItem {
desc?: string
file_name?: string
file_type?: string
last_modified?: number
path?: string
}
const toAbsoluteHttpUrl = (value: unknown): string | null => {
if (typeof value !== 'string' || !value) return null
if (value.startsWith('http://') || value.startsWith('https://')) return value
return null
}
const extractDirFileList = (payload: unknown): DirFileItem[] => {
if (Array.isArray(payload)) return payload
if (!payload || typeof payload !== 'object') return []
const obj = payload as Record<string, unknown>
if (Array.isArray(obj.data)) return obj.data as DirFileItem[]
return []
}
const normalizeFileName = (name: string): string => {
const raw = name.trim()
if (!raw) return ''
const withoutPrefix = raw.startsWith('/upload/') ? raw.slice('/upload/'.length) : raw
return withoutPrefix
}
const resolvePathByName = (files: DirFileItem[], fileName?: string): string | null => {
if (!fileName) return null
const normalizedName = normalizeFileName(fileName)
if (!normalizedName) return null
const expectedSegment = `upload/${normalizedName}`
const matched = files.find(item => {
if (typeof item.file_name !== 'string' || !item.file_name) return false
return item.file_name.includes(expectedSegment)
})
return matched?.path || null
}
export function useNovaService({
platformConfig,
conversationId,
}: UseNovaServiceProps) {
// API Client Singleton
const apiClient = useMemo(() => {
if (!platformConfig?.apiBaseUrl) {
return null
}
return request
}, [platformConfig])
// Get Artifact URL Method
const getArtifactUrl = useCallback(
async (
artifact: TaskArtifact,
params?: Record<string, string>
): Promise<{ data: string }> => {
try {
if (!apiClient) {
throw new Error('API client is not initialized')
}
const taskId = artifact.task_id || conversationId
let resolvedPath = artifact.path
if (taskId) {
const dirFilesResponse = await apiClient.post<unknown>(
'/v1/super_agent/chat/get_dir_file',
{ task_id: taskId }
)
const dirFiles = extractDirFileList(dirFilesResponse)
const matchedPath = resolvePathByName(dirFiles, artifact.file_name)
if (matchedPath) {
resolvedPath = matchedPath
}
}
// Call OSS URL interface
const response = await apiClient.post<string>('/chat/oss_url', {
file_path: resolvedPath,
task_id: taskId,
params
})
const signedUrl = toAbsoluteHttpUrl(response) || ''
const fallback = toAbsoluteHttpUrl(artifact.path) || ''
return { data: signedUrl || fallback }
} catch (error) {
console.error('Failed to fetch artifact URL:', error)
return { data: toAbsoluteHttpUrl(artifact.path) || '' }
}
},
[conversationId, apiClient]
)
const stopChat = useCallback(async () => {
try {
if (!apiClient) {
throw new Error('API client is not initialized')
}
if (!conversationId) {
throw new Error('Conversation ID is required')
}
await apiClient.get('/chat/stop', { conversation_id: conversationId })
} catch (error) {
console.error('Failed to stop chat:', error)
throw error
}
}, [conversationId, apiClient])
/** 获取会话信息列表(用于轮询 task_status使用 novaRequest */
const getConversationInfoList = useCallback(
async (conversationIds: string[]) => {
if (conversationIds.length === 0) {
return { data: [] as ConversationInfo[] }
}
const res = await request.post<{ data?: ConversationInfo[] } | ConversationInfo[]>(
'/conversation/info',
{ conversation_ids: conversationIds }
)
const list = Array.isArray(res) ? res : (res?.data ?? [])
return { data: list }
},
[]
)
return {
apiClient,
getArtifactUrl,
stopChat,
getConversationInfoList,
}
}