Files
leaudit-platform-frontend/app/services/dify-client.server.ts
T
TanWenyan 5949d057fb 添加详细日志:显示服务端实际调用的FastAPI地址
添加日志输出:
1. 启动时显示完整的Dify API URL配置
   - apiBaseUrl: 当前环境的FastAPI地址
   - fullDifyUrl: 完整的Dify代理路径

2. 每次请求时显示:
   - endpoint: 请求的具体端点
   - fullUrl: 完整的请求URL (baseUrl/dify/endpoint)
   - baseUrl: FastAPI基础地址
   - hasJWT: 是否携带JWT

示例输出(端口51703):
🔧 Dify Client Config: {
  apiUrl: 'http://172.16.0.55:8073/dify',
  apiBaseUrl: 'http://172.16.0.55:8073',
  fullDifyUrl: 'http://172.16.0.55:8073/dify'
}

🌐 [DifyClient] 请求FastAPI代理: {
  endpoint: 'chat-messages',
  fullUrl: 'http://172.16.0.55:8073/dify/chat-messages',
  baseUrl: 'http://172.16.0.55:8073',
  hasJWT: true
}

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 14:33:10 +08:00

230 lines
7.5 KiB
TypeScript

import { API_BASE_URL } from '~/config/api-config';
// 获取环境变量的服务端函数
const getServerEnvVar = (name: string, defaultValue: string = '') => {
const value = process.env[name] || defaultValue;
// console.log(`🌐 [DifyClient] 读取环境变量 ${name}:`, {
// hasValue: !!process.env[name],
// value: process.env[name] ? `${process.env[name].substring(0, 20)}...` : 'undefined',
// usingDefault: !process.env[name]
// });
return value;
};
// Dify API 客户端配置
// 注意:现在通过 FastAPI 后端的 /dify 路由代理访问 Dify,使用 JWT 认证
const DIFY_CONFIG = {
// API_URL 指向 FastAPI 后端的 /dify 路由
// API_BASE_URL 来自 api-config.ts,根据环境/端口自动配置
API_URL: `${API_BASE_URL}/dify`,
// API_KEY 保留用于配置验证(实际不再使用,改用JWT)
API_KEY: getServerEnvVar('NEXT_PUBLIC_APP_KEY', ''),
APP_ID: (() => {
const rawAppId = getServerEnvVar('NEXT_PUBLIC_APP_ID', '');
// 从完整URL中提取APP ID
const match = rawAppId.match(/\/app\/([a-f0-9-]{36})/);
return match ? match[1] : rawAppId;
})(),
};
console.log('🔧 Dify Client Config:', {
apiUrl: DIFY_CONFIG.API_URL,
apiBaseUrl: API_BASE_URL,
fullDifyUrl: `${API_BASE_URL}/dify`,
appId: DIFY_CONFIG.APP_ID,
hasApiKey: !!DIFY_CONFIG.API_KEY,
configComplete: !!(DIFY_CONFIG.API_URL && DIFY_CONFIG.APP_ID)
});
// 基础请求函数 - 使用 JWT 认证通过 FastAPI 代理访问 Dify
const difyFetch = async (endpoint: string, options: RequestInit = {}, jwt?: string) => {
const url = `${DIFY_CONFIG.API_URL}/${endpoint.replace(/^\//, '')}`;
console.log('🌐 [DifyClient] 请求FastAPI代理:', {
endpoint,
fullUrl: url,
baseUrl: API_BASE_URL,
hasJWT: !!jwt
});
// 使用 JWT 认证而非 API_KEY
const headers: HeadersInit = {
'Content-Type': 'application/json',
...options.headers,
};
// 如果提供了 JWT,添加到请求头
if (jwt) {
(headers as Record<string, string>)['Authorization'] = `Bearer ${jwt}`;
} else {
console.warn('⚠️ [DifyClient] 没有提供 JWT,请求可能失败');
}
console.log('🌐 [DifyClient] Dify API Request:', {
url,
method: options.method || 'GET',
hasJWT: !!jwt,
jwtPreview: jwt ? `${jwt.substring(0, 20)}...` : 'none'
});
const response = await fetch(url, {
...options,
headers,
});
if (!response.ok) {
const errorText = await response.text();
console.error('❌ [DifyClient] Dify API Error:', {
status: response.status,
statusText: response.statusText,
error: errorText
});
// 如果是401错误,说明JWT过期或无效
if (response.status === 401) {
throw new Error('JWT认证失败,请重新登录');
}
throw new Error(`Dify API Error: ${response.status} ${response.statusText}`);
}
return response;
};
// Dify API 客户端 - 所有方法都需要传入 JWT
// 注意:user 参数已移除,由后端自动从 JWT 中提取 username
export const difyClient = {
// 获取应用参数
async getApplicationParameters(jwt?: string) {
const response = await difyFetch('parameters', {
method: 'GET',
}, jwt);
return response.json();
},
// 获取会话列表
async getConversations(jwt?: string) {
const params = new URLSearchParams({
limit: '100',
first_id: '',
});
const response = await difyFetch(`conversations?${params}`, {
method: 'GET',
}, jwt);
return response.json();
},
// 获取会话消息
async getConversationMessages(conversationId: string, jwt?: string) {
const params = new URLSearchParams({
conversation_id: conversationId,
limit: '20',
last_id: '',
});
const response = await difyFetch(`messages?${params}`, {
method: 'GET',
}, jwt);
return response.json();
},
// 发送聊天消息
async createChatMessage(
inputs: Record<string, any>,
query: string,
responseMode: string = 'streaming',
conversationId?: string,
files?: any[],
jwt?: string
) {
const body = {
inputs,
query,
// user 字段已移除,后端会自动从 JWT 中提取 username
response_mode: responseMode,
conversation_id: conversationId,
files: files || [],
};
console.log('🌐 [DifyClient] 发送聊天消息:', {
queryLength: query.length,
queryPreview: query.substring(0, 100) + (query.length > 100 ? '...' : ''),
responseMode,
conversationId,
hasInputs: !!inputs && Object.keys(inputs).length > 0,
inputsKeys: inputs ? Object.keys(inputs) : [],
hasFiles: !!files && files.length > 0,
filesCount: files?.length || 0,
hasJWT: !!jwt
});
const response = await difyFetch('chat-messages', {
method: 'POST',
body: JSON.stringify(body),
}, jwt);
console.log('📡 [DifyClient] Dify API响应:', {
status: response.status,
statusText: response.statusText,
hasBody: !!response.body,
contentType: response.headers.get('Content-Type'),
responseMode
});
// 对于流式响应,直接返回Response对象
if (responseMode === 'streaming') {
console.log('🌊 [DifyClient] 返回流式响应对象');
return response;
}
console.log('📄 [DifyClient] 解析JSON响应');
return response.json();
},
// 重命名会话
async renameConversation(conversationId: string, name: string, autoGenerate: boolean = false, jwt?: string) {
const body = {
name,
auto_generate: autoGenerate,
// user 字段已移除,后端会自动从 JWT 中提取 username
};
const response = await difyFetch(`conversations/${conversationId}/name`, {
method: 'POST',
body: JSON.stringify(body),
}, jwt);
return response.json();
},
// 删除会话
async deleteConversation(conversationId: string, jwt?: string) {
// user 字段已移除,后端会自动从 JWT 中提取 username
const body = {};
const response = await difyFetch(`conversations/${conversationId}`, {
method: 'DELETE',
body: JSON.stringify(body),
}, jwt);
return response.json();
},
// 更新消息反馈
async updateMessageFeedback(messageId: string, rating: 'like' | 'dislike' | null, jwt?: string) {
const body = {
rating,
// user 字段已移除,后端会自动从 JWT 中提取 username
};
const response = await difyFetch(`messages/${messageId}/feedbacks`, {
method: 'POST',
body: JSON.stringify(body),
}, jwt);
return response.json();
},
};
// 工具函数
export const difyUtils = {
getConfig: () => DIFY_CONFIG,
};