/** * 自有 RAG Chat API 模块 * * 保持前端 dify-chat 调用面不变,内部转发到新的 /api/v3/rag/* 接口。 * * @module api/dify-chat/chat */ import { difyFetch } from './client.server'; function unwrapResult(payload: any): T { if (payload && typeof payload === 'object' && 'data' in payload) { return payload.data as T; } return payload as T; } function toIntAppId(appId?: string): string | undefined { if (!appId) return undefined; const parsed = Number(appId); return Number.isFinite(parsed) ? String(parsed) : undefined; } function normalizeConversationName(name: string): string { const compact = (name || '').replace(/\s+/g, ' ').trim(); if (!compact) return '新对话'; return compact.length > 20 ? `${compact.slice(0, 20)}...` : compact; } export const difyClient = { async getApplicationParameters(jwt?: string, appId?: string): Promise { const response = await difyFetch('chat/parameters', { method: 'GET', appId: toIntAppId(appId), }, jwt); const payload = unwrapResult(await response.json()); return { opening_statement: payload?.openingStatement || '', suggested_questions: payload?.suggestedQuestions || [], user_input_form: payload?.userInputForm || [], file_upload: payload?.fileUpload || { enabled: false }, }; }, async getConversations(jwt?: string, appId?: string): Promise { const params = new URLSearchParams({ page: '1', pageSize: '100', }); const normalizedAppId = toIntAppId(appId); if (normalizedAppId) { params.set('appId', normalizedAppId); } const response = await difyFetch(`chat/conversations?${params.toString()}`, { method: 'GET', }, jwt); const payload = unwrapResult(await response.json()); return { data: (payload?.data || []).map((item: any) => ({ id: item.id, name: item.name, introduction: item.introduction || '', created_at: item.createdAt || 0, updated_at: item.updatedAt || 0, })), has_more: Boolean(payload?.hasMore), limit: payload?.limit || 100, }; }, async getConversationMessages(conversationId: string, jwt?: string): Promise { const params = new URLSearchParams({ page: '1', pageSize: '100', }); const response = await difyFetch(`chat/conversations/${conversationId}/messages?${params.toString()}`, { method: 'GET', }, jwt); const payload = unwrapResult(await response.json()); return { data: (payload?.data || []).map((item: any) => ({ id: item.id, query: item.query, answer: item.answer, feedback: item.feedback || undefined, retriever_resources: item.retrieverResources || [], created_at: item.createdAt || 0, })), has_more: Boolean(payload?.hasMore), limit: payload?.limit || 100, }; }, async createChatMessage( inputs: Record, query: string, responseMode: string = 'streaming', conversationId?: string, files?: any[], jwt?: string, appId?: string ): Promise { const body = { inputs, query, response_mode: responseMode, conversation_id: conversationId, files: files || [], appId: toIntAppId(appId) ? Number(appId) : null, conversationId: conversationId || null, }; const response = await difyFetch('chat/messages', { method: 'POST', body: JSON.stringify(body), }, jwt); if (responseMode === 'streaming') { return response; } return response.json(); }, async renameConversation( conversationId: string, name: string, autoGenerate: boolean = false, jwt?: string ): Promise { let nextName = name?.trim() || ''; if (autoGenerate || !nextName) { const messages = await this.getConversationMessages(conversationId, jwt); const firstQuestion = messages?.data?.find((item: any) => item?.query)?.query || ''; nextName = normalizeConversationName(firstQuestion); } const response = await difyFetch(`chat/conversations/${conversationId}`, { method: 'PATCH', body: JSON.stringify({ name: nextName }), }, jwt); return unwrapResult(await response.json()); }, async deleteConversation(conversationId: string, jwt?: string): Promise { const response = await difyFetch(`chat/conversations/${conversationId}`, { method: 'DELETE', }, jwt); return unwrapResult(await response.json()); }, async updateMessageFeedback( messageId: string, rating: 'like' | 'dislike' | null, jwt?: string ): Promise { const response = await difyFetch(`chat/messages/${messageId}/feedback`, { method: 'POST', body: JSON.stringify({ rating }), }, jwt); return unwrapResult(await response.json()); }, };