初始化模版工程
This commit is contained in:
159
components/nova-sdk/hooks/useNovaService.ts
Normal file
159
components/nova-sdk/hooks/useNovaService.ts
Normal file
@@ -0,0 +1,159 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user