{"repo": "bzcasper/dev-projects", "files": {"prompt-optimizer/packages/core/tests/integration/llm/openai.test.js": {"0b4c8ef1f163270c9981bfb72e2fea72a7b74e59": {"t": 1785746673.0333135, "n": 14973, "h": "6f0969ebb344fcec", "c": "import { createLLMService, ModelManager, LocalStorageProvider } from '../../../src/index.js';\nimport { expect, describe, it, beforeEach, beforeAll } from 'vitest';\nimport dotenv from 'dotenv';\nimport path from 'path';\n\n// 加载环境变量\nbeforeAll(() => {\n dotenv.config({ path: path.resolve(process.cwd(), '.env.local') });\n});\n\ndescribe('OpenAI API 真实连接测试', () => {\n // 检查OpenAI兼容的环境变量(任何一个存在就可以运行测试)\n const openaiCompatibleKeys = [\n 'OPENAI_API_KEY', 'VITE_OPENAI_API_KEY',\n 'DEEPSEEK_API_KEY', 'VITE_DEEPSEEK_API_KEY', \n 'SILICONFLOW_API_KEY', 'VITE_SILICONFLOW_API_KEY',\n 'ZHIPU_API_KEY', 'VITE_ZHIPU_API_KEY',\n 'CUSTOM_API_KEY', 'VITE_CUSTOM_API_KEY'\n ];\n\n const availableKeys = openaiCompatibleKeys.filter(key => \n process.env[key] && process.env[key].trim()\n );\n\n if (availableKeys.length === 0) {\n console.log('跳过 OpenAI 真实API测试:未设置任何 OpenAI 兼容的 API 密钥');\n it.skip('应该能正确调用 OpenAI 兼容的 API', () => {});\n it.skip('应该能正确处理多轮对话', () => {});\n it.skip('应该能正确使用高级参数', () => {});\n return;\n }\n\n // 选择第一个可用的密钥和对应的配置\n const getModelConfig = () => {\n if (process.env.SILICONFLOW_API_KEY || process.env.VITE_SILICONFLOW_API_KEY) {\n return {\n key: 'siliconflow',\n apiKey: process.env.SILICONFLOW_API_KEY || process.env.VITE_SILICONFLOW_API_KEY,\n baseURL: 'https://api.siliconflow.cn/v1',\n defaultModel: 'Qwen/Qwen3-8B'\n };\n }\n if (process.env.OPENAI_API_KEY || process.env.VITE_OPENAI_API_KEY) {\n return {\n key: 'openai',\n apiKey: process.env.OPENAI_API_KEY || process.env.VITE_OPENAI_API_KEY,\n baseURL: 'https://api.openai.com/v1',\n defaultModel: 'gpt-3.5-turbo'\n };\n }\n if (process.env.DEEPSEEK_API_KEY || process.env.VITE_DEEPSEEK_API_KEY) {\n return {\n key: 'deepseek',\n apiKey: process.env.DEEPSEEK_API_KEY || process.env.VITE_DEEPSEEK_API_KEY,\n baseURL: 'https://api.deepseek.com/v1',\n defaultModel: 'deepseek-chat'\n };\n }\n if (process.env.ZHIPU_API_KEY || process.env.VITE_ZHIPU_API_KEY) {\n return {\n key: 'zhipu',\n apiKey: process.env.ZHIPU_API_KEY || process.env.VITE_ZHIPU_API_KEY,\n baseURL: 'https://open.bigmodel.cn/api/paas/v4',\n defaultModel: 'glm-4-flash'\n };\n }\n if (process.env.CUSTOM_API_KEY || process.env.VITE_CUSTOM_API_KEY) {\n const baseURL = process.env.CUSTOM_API_BASE_URL || process.env.VITE_CUSTOM_API_BASE_URL;\n const model = process.env.CUSTOM_API_MODEL || process.env.VITE_CUSTOM_API_MODEL;\n \n // 只有当baseURL和model都有值时才返回custom配置\n if (baseURL && model) {\n return {\n key: 'custom',\n apiKey: process.env.CUSTOM_API_KEY || process.env.VITE_CUSTOM_API_KEY,\n baseURL: baseURL,\n defaultModel: model\n };\n }\n }\n return null;\n };\n\n const modelConfig = getModelConfig();\n \n if (!modelConfig) {\n console.log('跳过 OpenAI 真实API测试:无有效的模型配置');\n it.skip('应该能正确调用 OpenAI 兼容的 API', () => {});\n it.skip('应该能正确处理多轮对话', () => {});\n it.skip('应该能正确使用高级参数', () => {});\n return;\n }\n\n console.log(`使用 ${modelConfig.key} 进行 OpenAI 兼容 API 测试,模型: ${modelConfig.defaultModel}`);\n\n it('应该能正确调用 OpenAI 兼容的 API', async () => {\n const storage = new LocalStorageProvider();\n const modelManager = new ModelManager(storage);\n const llmService = createLLMService(modelManager);\n\n try {\n // 更新模型配置\n await modelManager.updateModel(modelConfig.key, {\n apiKey: modelConfig.apiKey,\n baseURL: modelConfig.baseURL,\n defaultModel: modelConfig.defaultModel,\n enabled: true,\n provider: 'openai' // 所有兼容提供商都使用openai提供商类型\n });\n\n const messages = [\n { role: 'user', content: '你好,请用一句话介绍你自己' }\n ];\n\n const response = await llmService.sendMessage(messages, modelConfig.key);\n expect(response).toBeDefined();\n expect(typeof response).toBe('string');\n expect(response.length).toBeGreaterThan(0);\n } catch (error) {\n console.error(`API调用失败 (${modelConfig.key}):`, error.message);\n // 如果是400错误,可能是配置问题,跳过测试\n if (error.message.includes('400')) {\n console.log(`跳过测试:${modelConfig.key} API配置可能有问题`);\n return;\n }\n throw error;\n }\n }, 300000);\n\n it('应该能正确处理多轮对话', async () => {\n const storage = new LocalStorageProvider();\n const modelManager = new ModelManager(storage);\n const llmService = createLLMService(modelManager);\n\n try {\n // 更新模型配置\n await modelManager.updateModel(modelConfig.key, {\n apiKey: modelConfig.apiKey,\n baseURL: modelConfig.baseURL,\n defaultModel: modelConfig.defaultModel,\n enabled: true,\n provider: 'openai'\n });\n\n const messages = [\n { role: 'user', content: '你好,我们来玩个游戏' },\n { role: 'assistant', content: '好啊,你想玩什么游戏?' },\n { role: 'user', content: '我们来玩猜数字游戏,1到100之间' }\n ];\n\n const response = await llmService.sendMessage(messages, modelConfig.key);\n expect(response).toBeDefined();\n expect(typeof response).toBe('string');\n expect(response.length).toBeGreaterThan(0);\n } catch (error) {\n console.error(`多轮对话测试失败 (${modelConfig.key}):`, error.message);\n if (error.message.includes('400')) {\n console.log(`跳过测试:${modelConfig.key} API配置可能有问题`);\n return;\n }\n throw error;\n }\n }, 300000);\n\n it('应该能正确使用高级参数', async () => {\n const storage = new LocalStorageProvider();\n const modelManager = new ModelManager(storage);\n const llmService = createLLMService(modelManager);\n\n try {\n // 更新模型配置,包含高级参数\n await modelManager.updateModel(modelConfig.key, {\n apiKey: modelConfig.apiKey,\n baseURL: modelConfig.baseURL,\n defaultModel: modelConfig.defaultModel,\n enabled: true,\n provider: 'openai',\n llmParams: {\n temperature: 0.3,\n max_tokens: 100\n }\n });\n\n const messages = [\n { role: 'user', content: '请用一句话回答:什么是人工智能?' }\n ];\n\n const response = await llmService.sendMessage(messages, modelConfig.key);\n expect(response).toBeDefined();\n expect(typeof response).toBe('string');\n expect(response.length).toBeGreaterThan(0);\n // 由于设置了max_tokens=100,响应应该相对较短\n expect(response.length).toBeLessThan(200);\n } catch (error) {\n console.error(`高级参数测试失败 (${modelConfig.key}):`, error.message);\n if (error.message.includes('400')) {\n console.log(`跳过测试:${modelConfig.key} API配置可能有问题`);\n return;\n }\n throw error;\n }\n }, 300000);\n\n it('应该能兼容处理所有模型的响应格式(reasoning_content + think标签 + 普通文本)', async () => {\n const storage = new LocalStorageProvider();\n const modelManager = new ModelManager(storage);\n const llmService = createLLMService(modelManager);\n\n try {\n // 测试通用兼容性处理\n await modelManager.updateModel(modelConfig.key, {\n apiKey: modelConfig.apiKey,\n baseURL: modelConfig.baseURL,\n defaultModel: modelConfig.defaultModel,\n enabled: true,\n provider: 'openai',\n llmParams: {\n temperature: 0.1,\n max_tokens: 100\n }\n });\n\n const testMessages = [\n {\n role: 'user',\n content: '请简单回答:什么是AI?'\n }\n ];\n\n // 测试非流式处理\n const result = await llmService.sendMessage(testMessages, modelConfig.key);\n \n expect(result).toBeTruthy();\n expect(typeof result).toBe('string');\n expect(result.length).toBeGreaterThan(0);\n \n console.log('兼容性测试结果:', {\n hasThinkTags: result.includes(''),\n hasContent: result.length > 0,\n result: result\n });\n\n // 测试流式处理\n let streamResult = '';\n let tokenCount = 0;\n let isCompleted = false;\n let hasError = false;\n\n await llmService.sendMessageStream(testMessages, modelConfig.key, {\n onToken: (token) => {\n streamResult += token;\n tokenCount++;\n },\n onComplete: (response) => {\n isCompleted = true;\n },\n onError: (error) => {\n hasError = true;\n console.error('流式测试错误:', error);\n }\n });\n\n expect(hasError).toBe(false);\n expect(isCompleted).toBe(true);\n expect(streamResult.length).toBeGreaterThan(0);\n expect(tokenCount).toBeGreaterThan(0);\n\n console.log('流式兼容性测试结果:', {\n tokenCount,\n hasThinkTags: streamResult.includes(''),\n streamLength: streamResult.length,\n isCompleted\n });\n\n } catch (error) {\n console.error('兼容性测试失败:', error);\n throw error;\n }\n },300000);\n\n it('应该能正确处理reasoning_content的流式输出', async () => {\n const storage = new LocalStorageProvider();\n const modelManager = new ModelManager(storage);\n const llmService = createLLMService(modelManager);\n\n try {\n // 配置模型\n await modelManager.updateModel(modelConfig.key, {\n apiKey: modelConfig.apiKey,\n baseURL: modelConfig.baseURL,\n defaultModel: modelConfig.defaultModel,\n enabled: true,\n provider: 'openai',\n llmParams: {\n temperature: 0.1,\n max_tokens: 2000\n }\n });\n\n const testMessages = [\n {\n role: 'user',\n content: '你是谁'\n }\n ];\n\n // 模拟包含reasoning_content的流式响应\n let fullResult = '';\n let tokenCount = 0;\n let hasThinkTags = false;\n let thinkTagsClosed = false;\n let isCompleted = false;\n let hasError = false;\n\n await llmService.sendMessageStream(testMessages, modelConfig.key, {\n onToken: (token) => {\n fullResult += token;\n tokenCount++;\n \n // 检查think标签的完整性\n if (token.includes('')) {\n hasThinkTags = true;\n }\n if (token.includes('')) {\n thinkTagsClosed = true;\n }\n },\n onComplete: (response) => {\n isCompleted = true;\n },\n onError: (error) => {\n hasError = true;\n console.error('流式测试错误:', error);\n }\n });\n\n // 等待流式完成\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n console.log('reasoning_content流式测试结果:', {\n tokenCount,\n hasThinkTags,\n thinkTagsClosed,\n isCompleted,\n hasError,\n resultLength: fullResult.length,\n fullResult: fullResult\n });\n\n expect(isCompleted).toBe(true);\n expect(hasError).toBe(false);\n expect(tokenCount).toBeGreaterThan(0);\n expect(fullResult.length).toBeGreaterThan(0);\n \n // 如果有think标签,检查它们是否正确闭合\n const thinkOpenCount = (fullResult.match(//g) || []).length;\n const thinkCloseCount = (fullResult.match(/<\\/think>/g) || []).length;\n \n if (thinkOpenCount > 0) {\n expect(thinkOpenCount).toBe(thinkCloseCount);\n console.log(`✅ Think标签匹配: ${thinkOpenCount} 个开始标签, ${thinkCloseCount} 个结束标签`);\n }\n\n } catch (error) {\n console.error('reasoning_content流式测试失败:', error);\n throw error;\n }\n },300000);\n\n it('应该能使用结构化API发送消息', async () => {\n const storage = new LocalStorageProvider();\n const modelManager = new ModelManager(storage);\n const llmService = createLLMService(modelManager);\n\n try {\n // 配置模型\n await modelManager.updateModel(modelConfig.key, {\n apiKey: modelConfig.apiKey,\n baseURL: modelConfig.baseURL,\n defaultModel: modelConfig.defaultModel,\n enabled: true,\n provider: 'openai',\n llmParams: {\n temperature: 0.3,\n max_tokens: 100\n }\n });\n\n const testMessages = [\n {\n role: 'user',\n content: '请简单回答:什么是AI?'\n }\n ];\n\n // 测试结构化API\n const response = await llmService.sendMessageStructured(testMessages, modelConfig.key);\n \n expect(response).toBeDefined();\n expect(typeof response).toBe('object');\n expect(response.content).toBeDefined();\n expect(typeof response.content).toBe('string');\n expect(response.content.length).toBeGreaterThan(0);\n \n // 检查元数据\n expect(response.metadata).toBeDefined();\n expect(response.metadata.model).toBe(modelConfig.defaultModel);\n \n console.log('结构化API测试结果:', {\n hasContent: response.content.length > 0,\n hasReasoning: !!response.reasoning,\n content: response.content,\n reasoning: response.reasoning,\n model: response.metadata?.model\n });\n\n } catch (error) {\n console.error('结构化API测试失败:', error);\n throw error;\n }\n }, 300000);\n\n it('应该能使用结构化回调进行流式处理', async () => {\n const storage = new LocalStorageProvider();\n const modelManager = new ModelManager(storage);\n const llmService = createLLMService(modelManager);\n\n try {\n // 配置模型\n await modelManager.updateModel(modelConfig.key, {\n apiKey: modelConfig.apiKey,\n baseURL: modelConfig.baseURL,\n defaultModel: modelConfig.defaultModel,\n enabled: true,\n provider: 'openai',\n llmParams: {\n temperature: 0.1,\n max_tokens: 1500\n }\n });\n\n const testMessages = [\n {\n role: 'user',\n content: '请简单回答:什么是AI?'\n }\n ];\n\n let contentTokens = '';\n let reasoningTokens = '';\n let finalResponse = null;\n let contentTokenCount = 0;\n let reasoningTokenCount = 0;\n let isCompleted = false;\n let hasError = false;\n\n await llmService.sendMessageStream(testMessages, modelConfig.key, {\n onToken: (token) => {\n contentTokens += token;\n contentTokenCount++;\n },\n onReasoningToken: (token) => {\n reasoningTokens += token;\n reasoningTokenCount++;\n },\n onComplete: (response) => {\n finalResponse = response;\n isCompleted = true;\n },\n onError: (error) => {\n hasError = true;\n console.error('结构化流式测试错误:', error);\n }\n });\n\n // 等待流式完成\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n console.log('结构化流式测试结果:', {\n contentTokenCount,\n reasoningTokenCount,\n isCompleted,\n hasError,\n content: contentTokens,\n reasoning: reasoningTokens,\n finalResponse: finalResponse\n });\n\n expect(isCompleted).toBe(true);\n expect(hasError).toBe(false);\n expect(finalResponse).toBeDefined();\n expect(finalResponse.content).toBeDefined();\n expect(contentTokenCount).toBeGreaterThan(0);\n expect(contentTokens.length).toBeGreaterThan(0);\n \n // 验证内容一致性\n expect(contentTokens).toBe(finalResponse.content);\n \n // 如果有推理内容,验证一致性\n if (reasoningTokenCount > 0) {\n expect(reasoningTokens).toBe(finalResponse.reasoning || '');\n }\n\n } catch (error) {\n console.error('结构化流式测试失败:', error);\n throw error;\n }\n }, 300000);\n}); "}, "efe8e75ac7c39bb3679157d41d7949388eefe5ee": {"t": 1785766739.266065, "n": 14973, "h": "6f0969ebb344fcec", "c": "import { createLLMService, ModelManager, LocalStorageProvider } from '../../../src/index.js';\nimport { expect, describe, it, beforeEach, beforeAll } from 'vitest';\nimport dotenv from 'dotenv';\nimport path from 'path';\n\n// 加载环境变量\nbeforeAll(() => {\n dotenv.config({ path: path.resolve(process.cwd(), '.env.local') });\n});\n\ndescribe('OpenAI API 真实连接测试', () => {\n // 检查OpenAI兼容的环境变量(任何一个存在就可以运行测试)\n const openaiCompatibleKeys = [\n 'OPENAI_API_KEY', 'VITE_OPENAI_API_KEY',\n 'DEEPSEEK_API_KEY', 'VITE_DEEPSEEK_API_KEY', \n 'SILICONFLOW_API_KEY', 'VITE_SILICONFLOW_API_KEY',\n 'ZHIPU_API_KEY', 'VITE_ZHIPU_API_KEY',\n 'CUSTOM_API_KEY', 'VITE_CUSTOM_API_KEY'\n ];\n\n const availableKeys = openaiCompatibleKeys.filter(key => \n process.env[key] && process.env[key].trim()\n );\n\n if (availableKeys.length === 0) {\n console.log('跳过 OpenAI 真实API测试:未设置任何 OpenAI 兼容的 API 密钥');\n it.skip('应该能正确调用 OpenAI 兼容的 API', () => {});\n it.skip('应该能正确处理多轮对话', () => {});\n it.skip('应该能正确使用高级参数', () => {});\n return;\n }\n\n // 选择第一个可用的密钥和对应的配置\n const getModelConfig = () => {\n if (process.env.SILICONFLOW_API_KEY || process.env.VITE_SILICONFLOW_API_KEY) {\n return {\n key: 'siliconflow',\n apiKey: process.env.SILICONFLOW_API_KEY || process.env.VITE_SILICONFLOW_API_KEY,\n baseURL: 'https://api.siliconflow.cn/v1',\n defaultModel: 'Qwen/Qwen3-8B'\n };\n }\n if (process.env.OPENAI_API_KEY || process.env.VITE_OPENAI_API_KEY) {\n return {\n key: 'openai',\n apiKey: process.env.OPENAI_API_KEY || process.env.VITE_OPENAI_API_KEY,\n baseURL: 'https://api.openai.com/v1',\n defaultModel: 'gpt-3.5-turbo'\n };\n }\n if (process.env.DEEPSEEK_API_KEY || process.env.VITE_DEEPSEEK_API_KEY) {\n return {\n key: 'deepseek',\n apiKey: process.env.DEEPSEEK_API_KEY || process.env.VITE_DEEPSEEK_API_KEY,\n baseURL: 'https://api.deepseek.com/v1',\n defaultModel: 'deepseek-chat'\n };\n }\n if (process.env.ZHIPU_API_KEY || process.env.VITE_ZHIPU_API_KEY) {\n return {\n key: 'zhipu',\n apiKey: process.env.ZHIPU_API_KEY || process.env.VITE_ZHIPU_API_KEY,\n baseURL: 'https://open.bigmodel.cn/api/paas/v4',\n defaultModel: 'glm-4-flash'\n };\n }\n if (process.env.CUSTOM_API_KEY || process.env.VITE_CUSTOM_API_KEY) {\n const baseURL = process.env.CUSTOM_API_BASE_URL || process.env.VITE_CUSTOM_API_BASE_URL;\n const model = process.env.CUSTOM_API_MODEL || process.env.VITE_CUSTOM_API_MODEL;\n \n // 只有当baseURL和model都有值时才返回custom配置\n if (baseURL && model) {\n return {\n key: 'custom',\n apiKey: process.env.CUSTOM_API_KEY || process.env.VITE_CUSTOM_API_KEY,\n baseURL: baseURL,\n defaultModel: model\n };\n }\n }\n return null;\n };\n\n const modelConfig = getModelConfig();\n \n if (!modelConfig) {\n console.log('跳过 OpenAI 真实API测试:无有效的模型配置');\n it.skip('应该能正确调用 OpenAI 兼容的 API', () => {});\n it.skip('应该能正确处理多轮对话', () => {});\n it.skip('应该能正确使用高级参数', () => {});\n return;\n }\n\n console.log(`使用 ${modelConfig.key} 进行 OpenAI 兼容 API 测试,模型: ${modelConfig.defaultModel}`);\n\n it('应该能正确调用 OpenAI 兼容的 API', async () => {\n const storage = new LocalStorageProvider();\n const modelManager = new ModelManager(storage);\n const llmService = createLLMService(modelManager);\n\n try {\n // 更新模型配置\n await modelManager.updateModel(modelConfig.key, {\n apiKey: modelConfig.apiKey,\n baseURL: modelConfig.baseURL,\n defaultModel: modelConfig.defaultModel,\n enabled: true,\n provider: 'openai' // 所有兼容提供商都使用openai提供商类型\n });\n\n const messages = [\n { role: 'user', content: '你好,请用一句话介绍你自己' }\n ];\n\n const response = await llmService.sendMessage(messages, modelConfig.key);\n expect(response).toBeDefined();\n expect(typeof response).toBe('string');\n expect(response.length).toBeGreaterThan(0);\n } catch (error) {\n console.error(`API调用失败 (${modelConfig.key}):`, error.message);\n // 如果是400错误,可能是配置问题,跳过测试\n if (error.message.includes('400')) {\n console.log(`跳过测试:${modelConfig.key} API配置可能有问题`);\n return;\n }\n throw error;\n }\n }, 300000);\n\n it('应该能正确处理多轮对话', async () => {\n const storage = new LocalStorageProvider();\n const modelManager = new ModelManager(storage);\n const llmService = createLLMService(modelManager);\n\n try {\n // 更新模型配置\n await modelManager.updateModel(modelConfig.key, {\n apiKey: modelConfig.apiKey,\n baseURL: modelConfig.baseURL,\n defaultModel: modelConfig.defaultModel,\n enabled: true,\n provider: 'openai'\n });\n\n const messages = [\n { role: 'user', content: '你好,我们来玩个游戏' },\n { role: 'assistant', content: '好啊,你想玩什么游戏?' },\n { role: 'user', content: '我们来玩猜数字游戏,1到100之间' }\n ];\n\n const response = await llmService.sendMessage(messages, modelConfig.key);\n expect(response).toBeDefined();\n expect(typeof response).toBe('string');\n expect(response.length).toBeGreaterThan(0);\n } catch (error) {\n console.error(`多轮对话测试失败 (${modelConfig.key}):`, error.message);\n if (error.message.includes('400')) {\n console.log(`跳过测试:${modelConfig.key} API配置可能有问题`);\n return;\n }\n throw error;\n }\n }, 300000);\n\n it('应该能正确使用高级参数', async () => {\n const storage = new LocalStorageProvider();\n const modelManager = new ModelManager(storage);\n const llmService = createLLMService(modelManager);\n\n try {\n // 更新模型配置,包含高级参数\n await modelManager.updateModel(modelConfig.key, {\n apiKey: modelConfig.apiKey,\n baseURL: modelConfig.baseURL,\n defaultModel: modelConfig.defaultModel,\n enabled: true,\n provider: 'openai',\n llmParams: {\n temperature: 0.3,\n max_tokens: 100\n }\n });\n\n const messages = [\n { role: 'user', content: '请用一句话回答:什么是人工智能?' }\n ];\n\n const response = await llmService.sendMessage(messages, modelConfig.key);\n expect(response).toBeDefined();\n expect(typeof response).toBe('string');\n expect(response.length).toBeGreaterThan(0);\n // 由于设置了max_tokens=100,响应应该相对较短\n expect(response.length).toBeLessThan(200);\n } catch (error) {\n console.error(`高级参数测试失败 (${modelConfig.key}):`, error.message);\n if (error.message.includes('400')) {\n console.log(`跳过测试:${modelConfig.key} API配置可能有问题`);\n return;\n }\n throw error;\n }\n }, 300000);\n\n it('应该能兼容处理所有模型的响应格式(reasoning_content + think标签 + 普通文本)', async () => {\n const storage = new LocalStorageProvider();\n const modelManager = new ModelManager(storage);\n const llmService = createLLMService(modelManager);\n\n try {\n // 测试通用兼容性处理\n await modelManager.updateModel(modelConfig.key, {\n apiKey: modelConfig.apiKey,\n baseURL: modelConfig.baseURL,\n defaultModel: modelConfig.defaultModel,\n enabled: true,\n provider: 'openai',\n llmParams: {\n temperature: 0.1,\n max_tokens: 100\n }\n });\n\n const testMessages = [\n {\n role: 'user',\n content: '请简单回答:什么是AI?'\n }\n ];\n\n // 测试非流式处理\n const result = await llmService.sendMessage(testMessages, modelConfig.key);\n \n expect(result).toBeTruthy();\n expect(typeof result).toBe('string');\n expect(result.length).toBeGreaterThan(0);\n \n console.log('兼容性测试结果:', {\n hasThinkTags: result.includes(''),\n hasContent: result.length > 0,\n result: result\n });\n\n // 测试流式处理\n let streamResult = '';\n let tokenCount = 0;\n let isCompleted = false;\n let hasError = false;\n\n await llmService.sendMessageStream(testMessages, modelConfig.key, {\n onToken: (token) => {\n streamResult += token;\n tokenCount++;\n },\n onComplete: (response) => {\n isCompleted = true;\n },\n onError: (error) => {\n hasError = true;\n console.error('流式测试错误:', error);\n }\n });\n\n expect(hasError).toBe(false);\n expect(isCompleted).toBe(true);\n expect(streamResult.length).toBeGreaterThan(0);\n expect(tokenCount).toBeGreaterThan(0);\n\n console.log('流式兼容性测试结果:', {\n tokenCount,\n hasThinkTags: streamResult.includes(''),\n streamLength: streamResult.length,\n isCompleted\n });\n\n } catch (error) {\n console.error('兼容性测试失败:', error);\n throw error;\n }\n },300000);\n\n it('应该能正确处理reasoning_content的流式输出', async () => {\n const storage = new LocalStorageProvider();\n const modelManager = new ModelManager(storage);\n const llmService = createLLMService(modelManager);\n\n try {\n // 配置模型\n await modelManager.updateModel(modelConfig.key, {\n apiKey: modelConfig.apiKey,\n baseURL: modelConfig.baseURL,\n defaultModel: modelConfig.defaultModel,\n enabled: true,\n provider: 'openai',\n llmParams: {\n temperature: 0.1,\n max_tokens: 2000\n }\n });\n\n const testMessages = [\n {\n role: 'user',\n content: '你是谁'\n }\n ];\n\n // 模拟包含reasoning_content的流式响应\n let fullResult = '';\n let tokenCount = 0;\n let hasThinkTags = false;\n let thinkTagsClosed = false;\n let isCompleted = false;\n let hasError = false;\n\n await llmService.sendMessageStream(testMessages, modelConfig.key, {\n onToken: (token) => {\n fullResult += token;\n tokenCount++;\n \n // 检查think标签的完整性\n if (token.includes('')) {\n hasThinkTags = true;\n }\n if (token.includes('')) {\n thinkTagsClosed = true;\n }\n },\n onComplete: (response) => {\n isCompleted = true;\n },\n onError: (error) => {\n hasError = true;\n console.error('流式测试错误:', error);\n }\n });\n\n // 等待流式完成\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n console.log('reasoning_content流式测试结果:', {\n tokenCount,\n hasThinkTags,\n thinkTagsClosed,\n isCompleted,\n hasError,\n resultLength: fullResult.length,\n fullResult: fullResult\n });\n\n expect(isCompleted).toBe(true);\n expect(hasError).toBe(false);\n expect(tokenCount).toBeGreaterThan(0);\n expect(fullResult.length).toBeGreaterThan(0);\n \n // 如果有think标签,检查它们是否正确闭合\n const thinkOpenCount = (fullResult.match(//g) || []).length;\n const thinkCloseCount = (fullResult.match(/<\\/think>/g) || []).length;\n \n if (thinkOpenCount > 0) {\n expect(thinkOpenCount).toBe(thinkCloseCount);\n console.log(`✅ Think标签匹配: ${thinkOpenCount} 个开始标签, ${thinkCloseCount} 个结束标签`);\n }\n\n } catch (error) {\n console.error('reasoning_content流式测试失败:', error);\n throw error;\n }\n },300000);\n\n it('应该能使用结构化API发送消息', async () => {\n const storage = new LocalStorageProvider();\n const modelManager = new ModelManager(storage);\n const llmService = createLLMService(modelManager);\n\n try {\n // 配置模型\n await modelManager.updateModel(modelConfig.key, {\n apiKey: modelConfig.apiKey,\n baseURL: modelConfig.baseURL,\n defaultModel: modelConfig.defaultModel,\n enabled: true,\n provider: 'openai',\n llmParams: {\n temperature: 0.3,\n max_tokens: 100\n }\n });\n\n const testMessages = [\n {\n role: 'user',\n content: '请简单回答:什么是AI?'\n }\n ];\n\n // 测试结构化API\n const response = await llmService.sendMessageStructured(testMessages, modelConfig.key);\n \n expect(response).toBeDefined();\n expect(typeof response).toBe('object');\n expect(response.content).toBeDefined();\n expect(typeof response.content).toBe('string');\n expect(response.content.length).toBeGreaterThan(0);\n \n // 检查元数据\n expect(response.metadata).toBeDefined();\n expect(response.metadata.model).toBe(modelConfig.defaultModel);\n \n console.log('结构化API测试结果:', {\n hasContent: response.content.length > 0,\n hasReasoning: !!response.reasoning,\n content: response.content,\n reasoning: response.reasoning,\n model: response.metadata?.model\n });\n\n } catch (error) {\n console.error('结构化API测试失败:', error);\n throw error;\n }\n }, 300000);\n\n it('应该能使用结构化回调进行流式处理', async () => {\n const storage = new LocalStorageProvider();\n const modelManager = new ModelManager(storage);\n const llmService = createLLMService(modelManager);\n\n try {\n // 配置模型\n await modelManager.updateModel(modelConfig.key, {\n apiKey: modelConfig.apiKey,\n baseURL: modelConfig.baseURL,\n defaultModel: modelConfig.defaultModel,\n enabled: true,\n provider: 'openai',\n llmParams: {\n temperature: 0.1,\n max_tokens: 1500\n }\n });\n\n const testMessages = [\n {\n role: 'user',\n content: '请简单回答:什么是AI?'\n }\n ];\n\n let contentTokens = '';\n let reasoningTokens = '';\n let finalResponse = null;\n let contentTokenCount = 0;\n let reasoningTokenCount = 0;\n let isCompleted = false;\n let hasError = false;\n\n await llmService.sendMessageStream(testMessages, modelConfig.key, {\n onToken: (token) => {\n contentTokens += token;\n contentTokenCount++;\n },\n onReasoningToken: (token) => {\n reasoningTokens += token;\n reasoningTokenCount++;\n },\n onComplete: (response) => {\n finalResponse = response;\n isCompleted = true;\n },\n onError: (error) => {\n hasError = true;\n console.error('结构化流式测试错误:', error);\n }\n });\n\n // 等待流式完成\n await new Promise(resolve => setTimeout(resolve, 1000));\n\n console.log('结构化流式测试结果:', {\n contentTokenCount,\n reasoningTokenCount,\n isCompleted,\n hasError,\n content: contentTokens,\n reasoning: reasoningTokens,\n finalResponse: finalResponse\n });\n\n expect(isCompleted).toBe(true);\n expect(hasError).toBe(false);\n expect(finalResponse).toBeDefined();\n expect(finalResponse.content).toBeDefined();\n expect(contentTokenCount).toBeGreaterThan(0);\n expect(contentTokens.length).toBeGreaterThan(0);\n \n // 验证内容一致性\n expect(contentTokens).toBe(finalResponse.content);\n \n // 如果有推理内容,验证一致性\n if (reasoningTokenCount > 0) {\n expect(reasoningTokens).toBe(finalResponse.reasoning || '');\n }\n\n } catch (error) {\n console.error('结构化流式测试失败:', error);\n throw error;\n }\n }, 300000);\n}); "}}, "prompt-optimizer/docker/generate-config.sh": {"0b4c8ef1f163270c9981bfb72e2fea72a7b74e59": {"t": 1786068350.498124, "n": 1782, "h": "592e0728a5f543aa", "c": "#!/bin/sh\n\n# 配置文件路径\nCONFIG_FILE=\"/usr/share/nginx/html/config.js\"\n\necho \"开始生成运行时配置文件...\"\n\n# 扫描动态自定义模型环境变量\necho \"扫描动态自定义模型环境变量...\"\nDYNAMIC_CONFIG=\"\"\nDYNAMIC_COUNT=0\n\n# 扫描所有VITE_CUSTOM_API_*_suffix模式的环境变量\nfor var in $(env | grep '^VITE_CUSTOM_API_.*_[^=]*=' | cut -d= -f1); do\n # 验证环境变量名格式\n if echo \"$var\" | grep -qE '^VITE_CUSTOM_API_(KEY|BASE_URL|MODEL)_[a-zA-Z0-9_-]+$'; then\n # 提取配置类型和后缀\n config_type=$(echo \"$var\" | sed 's/^VITE_CUSTOM_API_\\([^_]*\\)_.*$/\\1/')\n suffix=$(echo \"$var\" | sed 's/^VITE_CUSTOM_API_[^_]*_\\(.*\\)$/\\1/')\n\n # 获取环境变量值(安全方式)\n value=$(printenv \"$var\" 2>/dev/null)\n\n if [ -n \"$value\" ]; then\n # 移除VITE_前缀生成运行时配置键名\n runtime_key=$(echo \"$var\" | sed 's/^VITE_//')\n\n # 简单有效的转义:只转义必要的字符\n # - 反斜杠、双引号\n escaped_value=$(printf '%s' \"$value\" | sed 's/\\\\/\\\\\\\\/g; s/\"/\\\\\"/g')\n\n # 添加到动态配置中\n if [ -n \"$DYNAMIC_CONFIG\" ]; then\n DYNAMIC_CONFIG=\"$DYNAMIC_CONFIG,\"\n fi\n DYNAMIC_CONFIG=\"$DYNAMIC_CONFIG\n $runtime_key: \\\"$escaped_value\\\"\"\n\n DYNAMIC_COUNT=$((DYNAMIC_COUNT + 1))\n echo \"Found: $runtime_key\"\n fi\n fi\ndone\n\necho \"Found $DYNAMIC_COUNT dynamic custom model configurations\"\n\n# 生成配置文件\ncat > $CONFIG_FILE << EOF\nwindow.runtime_config = {\n OPENAI_API_KEY: \"${VITE_OPENAI_API_KEY:-}\",\n GEMINI_API_KEY: \"${VITE_GEMINI_API_KEY:-}\",\n DEEPSEEK_API_KEY: \"${VITE_DEEPSEEK_API_KEY:-}\",\n ZHIPU_API_KEY: \"${VITE_ZHIPU_API_KEY:-}\",\n SILICONFLOW_API_KEY: \"${VITE_SILICONFLOW_API_KEY:-}\",\n CUSTOM_API_KEY: \"${VITE_CUSTOM_API_KEY:-}\",\n CUSTOM_API_BASE_URL: \"${VITE_CUSTOM_API_BASE_URL:-}\",\n CUSTOM_API_MODEL: \"${VITE_CUSTOM_API_MODEL:-}\"${DYNAMIC_CONFIG:+,$DYNAMIC_CONFIG}\n};\nconsole.log(\"运行时配置已加载,包含 $DYNAMIC_COUNT 个动态自定义模型\");\nEOF\n\necho \"配置文件已生成: $CONFIG_FILE\"\necho \"动态配置: $DYNAMIC_COUNT 项\""}}}}