@weisiren000/oiiai 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +359 -27
- package/dist/index.d.mts +1762 -17
- package/dist/index.d.ts +1762 -17
- package/dist/index.js +3154 -797
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3135 -789
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -3
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/providers/openrouter.ts","../src/providers/__base__.ts","../src/providers/__types__.ts","../src/providers/gemini.ts","../src/providers/groq.ts","../src/providers/huggingface.ts","../src/providers/modelscope.ts","../src/providers/deepseek.ts","../src/providers/__factory__.ts"],"sourcesContent":["/**\n * OpenRouter Provider 实现\n */\n\nimport { OpenRouter } from '@openrouter/sdk';\nimport { BaseProvider } from './__base__';\nimport type {\n ChatOptions,\n ChatResult,\n StreamChunk,\n ModelInfo,\n ReasoningConfig,\n} from './__types__';\nimport { EFFORT_TOKEN_MAP } from './__types__';\n\n/**\n * OpenRouter 扩展的模型信息\n */\nexport interface OpenRouterModelInfo extends ModelInfo {\n /** 规范化的 slug */\n canonicalSlug: string;\n /** 创建时间戳 */\n created: number;\n /** 架构信息 */\n architecture: {\n modality: string;\n inputModalities: string[];\n outputModalities: string[];\n tokenizer: string;\n instructType: string;\n };\n}\n\n/**\n * 从 SDK 返回的 content 中提取文本\n */\nfunction extractTextContent(content: unknown): string {\n if (typeof content === 'string') {\n return content;\n }\n if (Array.isArray(content)) {\n return content\n .filter(\n (item): item is { type: 'text'; text: string } =>\n typeof item === 'object' &&\n item !== null &&\n item.type === 'text' &&\n typeof item.text === 'string'\n )\n .map(item => item.text)\n .join('');\n }\n return '';\n}\n\n/**\n * 构建 reasoning 参数(统一配置转换为 OpenRouter API 格式)\n */\nfunction buildReasoningParam(\n config?: ReasoningConfig\n): Record<string, unknown> | undefined {\n if (!config) return undefined;\n if (config.effort === 'off') return undefined;\n\n const param: Record<string, unknown> = {};\n\n // 设置 effort\n if (config.effort) {\n param.effort = config.effort;\n }\n\n // budgetTokens 优先,否则使用 effort 对应的默认值\n if (config.budgetTokens !== undefined) {\n param.max_tokens = config.budgetTokens;\n } else if (config.effort && EFFORT_TOKEN_MAP[config.effort]) {\n param.max_tokens = EFFORT_TOKEN_MAP[config.effort];\n }\n\n if (config.exclude !== undefined) {\n param.exclude = config.exclude;\n }\n\n return Object.keys(param).length > 0 ? param : undefined;\n}\n\n/**\n * OpenRouter Provider\n */\nexport class OpenRouterProvider extends BaseProvider {\n readonly name = 'openrouter';\n private client: OpenRouter;\n\n constructor(apiKey: string) {\n super();\n this.client = new OpenRouter({ apiKey });\n }\n\n /**\n * 发送聊天请求(非流式)\n */\n async chat(options: ChatOptions): Promise<ChatResult> {\n const {\n model,\n messages,\n temperature = 0.7,\n maxTokens,\n reasoning,\n } = options;\n\n const reasoningParam = buildReasoningParam(reasoning);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model,\n messages,\n temperature,\n maxTokens,\n stream: false,\n };\n\n if (reasoningParam) {\n requestParams.reasoning = reasoningParam;\n }\n\n const result = await this.client.chat.send(requestParams);\n\n const choice = result.choices[0];\n if (!choice) {\n throw new Error('No response from model');\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const msg = choice.message as any;\n const reasoningContent = msg.reasoning_content ?? msg.reasoning ?? null;\n\n return {\n content: extractTextContent(msg.content),\n reasoning: reasoningContent ? extractTextContent(reasoningContent) : null,\n model: result.model,\n usage: {\n promptTokens: result.usage?.promptTokens ?? 0,\n completionTokens: result.usage?.completionTokens ?? 0,\n totalTokens: result.usage?.totalTokens ?? 0,\n },\n finishReason: choice.finishReason,\n };\n }\n\n /**\n * 发送流式聊天请求\n */\n async *chatStream(\n options: ChatOptions\n ): AsyncGenerator<StreamChunk, void, unknown> {\n const {\n model,\n messages,\n temperature = 0.7,\n maxTokens,\n reasoning,\n } = options;\n\n const reasoningParam = buildReasoningParam(reasoning);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model,\n messages,\n temperature,\n maxTokens,\n stream: true,\n };\n\n if (reasoningParam) {\n requestParams.reasoning = reasoningParam;\n }\n\n const stream = (await this.client.chat.send(\n requestParams\n )) as unknown as AsyncIterable<{\n choices?: Array<{ delta?: unknown }>;\n }>;\n\n for await (const chunk of stream) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const delta = chunk.choices?.[0]?.delta as any;\n if (!delta) continue;\n\n const reasoningContent = delta.reasoning_content ?? delta.reasoning;\n if (reasoningContent) {\n yield { type: 'reasoning', text: extractTextContent(reasoningContent) };\n }\n\n if (delta.content) {\n yield { type: 'content', text: extractTextContent(delta.content) };\n }\n }\n }\n\n /**\n * 获取可用模型列表\n */\n async listModels(): Promise<OpenRouterModelInfo[]> {\n const result = await this.client.models.list();\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (result.data ?? []).map((m: any) => ({\n id: m.id,\n canonicalSlug: m.canonical_slug ?? m.id,\n name: m.name,\n description: m.description ?? '',\n created: m.created ?? 0,\n pricing: {\n prompt: m.pricing?.prompt ?? '0',\n completion: m.pricing?.completion ?? '0',\n request: m.pricing?.request ?? '0',\n image: m.pricing?.image ?? '0',\n },\n contextLength: m.context_length ?? 0,\n architecture: {\n modality: m.architecture?.modality ?? '',\n inputModalities: m.architecture?.input_modalities ?? [],\n outputModalities: m.architecture?.output_modalities ?? [],\n tokenizer: m.architecture?.tokenizer ?? '',\n instructType: m.architecture?.instruct_type ?? '',\n },\n supportedParameters: m.supported_parameters ?? [],\n }));\n }\n}\n","/**\n * AI Provider 接口和基类\n */\n\nimport type {\n ChatOptions,\n ChatResult,\n StreamChunk,\n ModelInfo,\n} from './__types__';\n\n/**\n * AI Provider 基础接口\n * 所有 provider 实现都需要实现这个接口\n */\nexport interface AIProvider {\n /** Provider 名称 */\n readonly name: string;\n\n /**\n * 发送聊天请求(非流式)\n */\n chat(options: ChatOptions): Promise<ChatResult>;\n\n /**\n * 发送流式聊天请求\n */\n chatStream(options: ChatOptions): AsyncGenerator<StreamChunk, void, unknown>;\n\n /**\n * 简单对话:单轮问答\n */\n ask(\n model: string,\n question: string,\n options?: Omit<ChatOptions, 'model' | 'messages'>\n ): Promise<string>;\n\n /**\n * 带系统提示的对话\n */\n askWithSystem(\n model: string,\n systemPrompt: string,\n userMessage: string,\n options?: Omit<ChatOptions, 'model' | 'messages'>\n ): Promise<string>;\n\n /**\n * 获取可用模型列表(可选实现)\n */\n listModels?(): Promise<ModelInfo[]>;\n}\n\n/**\n * AI Provider 基础抽象类\n * 提供一些通用实现,子类只需实现核心方法\n */\nexport abstract class BaseProvider implements AIProvider {\n abstract readonly name: string;\n\n abstract chat(options: ChatOptions): Promise<ChatResult>;\n\n abstract chatStream(\n options: ChatOptions\n ): AsyncGenerator<StreamChunk, void, unknown>;\n\n /**\n * 简单对话:单轮问答(默认实现)\n * 对于思考模型,如果 content 为空则返回 reasoning\n */\n async ask(\n model: string,\n question: string,\n options?: Omit<ChatOptions, 'model' | 'messages'>\n ): Promise<string> {\n const result = await this.chat({\n model,\n messages: [{ role: 'user', content: question }],\n ...options,\n });\n return result.content || result.reasoning || '';\n }\n\n /**\n * 带系统提示的对话(默认实现)\n * 对于思考模型,如果 content 为空则返回 reasoning\n */\n async askWithSystem(\n model: string,\n systemPrompt: string,\n userMessage: string,\n options?: Omit<ChatOptions, 'model' | 'messages'>\n ): Promise<string> {\n const result = await this.chat({\n model,\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userMessage },\n ],\n ...options,\n });\n return result.content || result.reasoning || '';\n }\n}\n","/**\n * AI Provider 统一类型定义\n */\n\n// ============ 消息类型 ============\n\nexport interface ChatMessage {\n role: 'system' | 'user' | 'assistant';\n content: string;\n}\n\n// ============ 思考/推理配置 ============\n\n/**\n * 统一的思考努力程度\n * - off: 关闭思考\n * - low: 快速思考,适合简单问题\n * - medium: 平衡模式(默认)\n * - high: 深度思考,适合复杂问题\n */\nexport type ReasoningEffort = 'off' | 'low' | 'medium' | 'high';\n\n/**\n * 统一的思考/推理配置\n *\n * 只需设置 effort,库会自动转换为各 Provider 需要的格式:\n * - OpenRouter: effort 参数\n * - Gemini: reasoning_effort 参数\n * - Groq: reasoning_effort 参数\n * - ModelScope: enable_thinking 参数\n *\n * @example\n * ```ts\n * // 简单用法 - 只设置 effort\n * { effort: 'high' }\n *\n * // 高级用法 - 精细控制\n * { effort: 'high', budgetTokens: 8000 }\n * ```\n */\nexport interface ReasoningConfig {\n /**\n * 思考努力程度(推荐使用)\n * - 'off': 关闭思考\n * - 'low': 快速思考\n * - 'medium': 平衡模式\n * - 'high': 深度思考\n */\n effort?: ReasoningEffort;\n\n /**\n * 思考 token 预算(可选,精细控制)\n * 设置后会覆盖 effort 对应的默认值\n * 仅部分 Provider 支持(OpenRouter)\n */\n budgetTokens?: number;\n\n /**\n * 是否在响应中排除思考内容\n * 仅部分 Provider 支持(OpenRouter)\n */\n exclude?: boolean;\n}\n\n/**\n * effort 到 token 预算的默认映射\n */\nexport const EFFORT_TOKEN_MAP: Record<ReasoningEffort, number> = {\n off: 0,\n low: 1024,\n medium: 4096,\n high: 16384,\n};\n\n// ============ 请求/响应类型 ============\n\nexport interface ChatOptions {\n /** 模型 ID */\n model: string;\n /** 对话消息列表 */\n messages: ChatMessage[];\n /** 温度参数 0-2 */\n temperature?: number;\n /** 最大输出 token 数 */\n maxTokens?: number;\n /** 思考/推理配置 */\n reasoning?: ReasoningConfig;\n}\n\nexport interface ChatResult {\n /** 最终回答内容 */\n content: string;\n /** 思考过程(仅 reasoning 模型有) */\n reasoning: string | null;\n /** 使用的模型 */\n model: string;\n /** Token 使用情况 */\n usage: TokenUsage;\n /** 完成原因 */\n finishReason: string | null;\n}\n\nexport interface TokenUsage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n}\n\n// ============ 流式输出类型 ============\n\nexport interface StreamChunk {\n type: 'reasoning' | 'content';\n text: string;\n}\n\n// ============ 模型信息类型 ============\n\nexport interface ModelPricing {\n /** 输入 token 单价 ($/token) */\n prompt: string;\n /** 输出 token 单价 ($/token) */\n completion: string;\n /** 请求单价 */\n request: string;\n /** 图片单价 */\n image: string;\n}\n\nexport interface ModelInfo {\n /** 模型 ID */\n id: string;\n /** 模型名称 */\n name: string;\n /** 模型描述 */\n description: string;\n /** 定价信息 */\n pricing: ModelPricing;\n /** 上下文长度 */\n contextLength: number;\n /** 支持的参数 */\n supportedParameters: string[];\n}\n","/**\n * Gemini Provider 实现\n * 使用 Google Gemini API (OpenAI 兼容格式)\n * https://ai.google.dev/gemini-api/docs/openai\n */\n\nimport { BaseProvider } from './__base__';\nimport type { ChatOptions, ChatResult, StreamChunk } from './__types__';\n\nconst BASE_URL = 'https://generativelanguage.googleapis.com/v1beta/openai';\n\n/**\n * Gemini Provider 配置\n */\nexport interface GeminiConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\n/**\n * 从 content 中提取文本\n */\nfunction extractTextContent(content: unknown): string {\n if (typeof content === 'string') {\n return content;\n }\n if (Array.isArray(content)) {\n return content\n .filter(\n (item): item is { type: 'text'; text: string } =>\n typeof item === 'object' &&\n item !== null &&\n item.type === 'text' &&\n typeof item.text === 'string'\n )\n .map(item => item.text)\n .join('');\n }\n return '';\n}\n\n/**\n * Gemini Provider\n * 使用 Google Gemini API,兼容 OpenAI 格式\n */\nexport class GeminiProvider extends BaseProvider {\n readonly name = 'gemini';\n private apiKey: string;\n private baseUrl: string;\n\n constructor(config: GeminiConfig | string) {\n super();\n if (typeof config === 'string') {\n this.apiKey = config;\n this.baseUrl = BASE_URL;\n } else {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl ?? BASE_URL;\n }\n }\n\n /**\n * 发送聊天请求(非流式)\n */\n async chat(options: ChatOptions): Promise<ChatResult> {\n const {\n model,\n messages,\n temperature = 0.7,\n maxTokens,\n reasoning,\n } = options;\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream: false,\n };\n\n if (maxTokens) {\n body.max_tokens = maxTokens;\n }\n\n // Gemini 2.5+ 模型使用 reasoning_effort 控制思考\n // 参考: https://ai.google.dev/gemini-api/docs/text-generation\n // 支持的值: 'low', 'medium', 'high'\n if (reasoning?.effort && reasoning.effort !== 'off') {\n body.reasoning_effort = reasoning.effort;\n }\n\n const response = await fetch(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Gemini API error: ${response.status} ${error}`);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result: any = await response.json();\n const choice = result.choices?.[0];\n\n if (!choice) {\n throw new Error('No response from model');\n }\n\n const msg = choice.message;\n const reasoningContent = msg?.reasoning_content ?? null;\n\n return {\n content: extractTextContent(msg?.content),\n reasoning: reasoningContent ? extractTextContent(reasoningContent) : null,\n model: result.model ?? model,\n usage: {\n promptTokens: result.usage?.prompt_tokens ?? 0,\n completionTokens: result.usage?.completion_tokens ?? 0,\n totalTokens: result.usage?.total_tokens ?? 0,\n },\n finishReason: choice.finish_reason ?? null,\n };\n }\n\n /**\n * 发送流式聊天请求\n */\n async *chatStream(\n options: ChatOptions\n ): AsyncGenerator<StreamChunk, void, unknown> {\n const {\n model,\n messages,\n temperature = 0.7,\n maxTokens,\n reasoning,\n } = options;\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream: true,\n };\n\n if (maxTokens) {\n body.max_tokens = maxTokens;\n }\n\n // Gemini 2.5+ 模型使用 reasoning_effort 控制思考\n if (reasoning?.effort && reasoning.effort !== 'off') {\n body.reasoning_effort = reasoning.effort;\n }\n\n const response = await fetch(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Gemini API error: ${response.status} ${error}`);\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error('No response body');\n }\n\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed === 'data: [DONE]') continue;\n if (!trimmed.startsWith('data: ')) continue;\n\n try {\n const data = JSON.parse(trimmed.slice(6));\n const delta = data.choices?.[0]?.delta;\n if (!delta) continue;\n\n // 思考内容 (Gemini 可能用 reasoning_content 或 thoughts)\n const thought = delta.reasoning_content ?? delta.thoughts;\n if (thought) {\n yield {\n type: 'reasoning',\n text: extractTextContent(thought),\n };\n }\n\n // 回答内容\n if (delta.content) {\n yield {\n type: 'content',\n text: extractTextContent(delta.content),\n };\n }\n } catch {\n // 忽略解析错误\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n}\n","/**\n * Groq Provider 实现\n * 使用 Groq API (OpenAI 兼容)\n */\n\nimport { BaseProvider } from './__base__';\nimport type { ChatOptions, ChatResult, StreamChunk } from './__types__';\n\nconst BASE_URL = 'https://api.groq.com/openai/v1';\n\n/**\n * Groq Provider 配置\n */\nexport interface GroqConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\n/**\n * 从 content 中提取文本\n */\nfunction extractTextContent(content: unknown): string {\n if (typeof content === 'string') {\n return content;\n }\n if (Array.isArray(content)) {\n return content\n .filter(\n (item): item is { type: 'text'; text: string } =>\n typeof item === 'object' &&\n item !== null &&\n item.type === 'text' &&\n typeof item.text === 'string'\n )\n .map(item => item.text)\n .join('');\n }\n return '';\n}\n\n/**\n * Groq Provider\n * 兼容 OpenAI API 格式,支持 reasoning_effort 参数\n */\nexport class GroqProvider extends BaseProvider {\n readonly name = 'groq';\n private apiKey: string;\n private baseUrl: string;\n\n constructor(config: GroqConfig | string) {\n super();\n if (typeof config === 'string') {\n this.apiKey = config;\n this.baseUrl = BASE_URL;\n } else {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl ?? BASE_URL;\n }\n }\n\n /**\n * 发送聊天请求(非流式)\n */\n async chat(options: ChatOptions): Promise<ChatResult> {\n const { model, messages, temperature = 1, maxTokens, reasoning } = options;\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream: false,\n top_p: 1,\n };\n\n if (maxTokens) {\n body.max_completion_tokens = maxTokens;\n }\n\n // Groq 使用 reasoning_format 参数控制推理输出\n // 参考: https://console.groq.com/docs/reasoning\n // reasoning_format: \"raw\" | \"parsed\" - 控制推理输出格式\n // 注意: 不能同时使用 include_reasoning 和 reasoning_format\n if (reasoning?.effort && reasoning.effort !== 'off') {\n body.reasoning_format = 'parsed';\n } else if (reasoning?.effort === 'off') {\n body.include_reasoning = false;\n }\n\n const response = await fetch(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Groq API error: ${response.status} ${error}`);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result: any = await response.json();\n const choice = result.choices?.[0];\n\n if (!choice) {\n throw new Error('No response from model');\n }\n\n const msg = choice.message;\n const reasoningContent = msg?.reasoning_content ?? msg?.reasoning ?? null;\n\n return {\n content: extractTextContent(msg?.content),\n reasoning: reasoningContent ? extractTextContent(reasoningContent) : null,\n model: result.model ?? model,\n usage: {\n promptTokens: result.usage?.prompt_tokens ?? 0,\n completionTokens: result.usage?.completion_tokens ?? 0,\n totalTokens: result.usage?.total_tokens ?? 0,\n },\n finishReason: choice.finish_reason ?? null,\n };\n }\n\n /**\n * 发送流式聊天请求\n */\n async *chatStream(\n options: ChatOptions\n ): AsyncGenerator<StreamChunk, void, unknown> {\n const { model, messages, temperature = 1, maxTokens, reasoning } = options;\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream: true,\n top_p: 1,\n };\n\n if (maxTokens) {\n body.max_completion_tokens = maxTokens;\n }\n\n // Groq 使用 reasoning_format 参数控制推理输出\n // 注意: 不能同时使用 include_reasoning 和 reasoning_format\n if (reasoning?.effort && reasoning.effort !== 'off') {\n body.reasoning_format = 'parsed';\n } else if (reasoning?.effort === 'off') {\n body.include_reasoning = false;\n }\n\n const response = await fetch(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Groq API error: ${response.status} ${error}`);\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error('No response body');\n }\n\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed === 'data: [DONE]') continue;\n if (!trimmed.startsWith('data: ')) continue;\n\n try {\n const data = JSON.parse(trimmed.slice(6));\n const delta = data.choices?.[0]?.delta;\n if (!delta) continue;\n\n // 思考内容\n const reasoningContent = delta.reasoning_content ?? delta.reasoning;\n if (reasoningContent) {\n yield {\n type: 'reasoning',\n text: extractTextContent(reasoningContent),\n };\n }\n\n // 回答内容\n if (delta.content) {\n yield {\n type: 'content',\n text: extractTextContent(delta.content),\n };\n }\n } catch {\n // 忽略解析错误\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n}\n","/**\n * HuggingFace Provider 实现\n * 使用 HuggingFace Router API (OpenAI 兼容)\n */\n\nimport { BaseProvider } from './__base__';\nimport type { ChatOptions, ChatResult, StreamChunk } from './__types__';\n\nconst BASE_URL = 'https://router.huggingface.co/v1';\n\n/**\n * HuggingFace Provider 配置\n */\nexport interface HuggingFaceConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\n/**\n * 从 content 中提取文本\n */\nfunction extractTextContent(content: unknown): string {\n if (typeof content === 'string') {\n return content;\n }\n if (Array.isArray(content)) {\n return content\n .filter(\n (item): item is { type: 'text'; text: string } =>\n typeof item === 'object' &&\n item !== null &&\n item.type === 'text' &&\n typeof item.text === 'string'\n )\n .map(item => item.text)\n .join('');\n }\n return '';\n}\n\n/**\n * HuggingFace Provider\n * 使用 HuggingFace Router,兼容 OpenAI API 格式\n */\nexport class HuggingFaceProvider extends BaseProvider {\n readonly name = 'huggingface';\n private apiKey: string;\n private baseUrl: string;\n\n constructor(config: HuggingFaceConfig | string) {\n super();\n if (typeof config === 'string') {\n this.apiKey = config;\n this.baseUrl = BASE_URL;\n } else {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl ?? BASE_URL;\n }\n }\n\n /**\n * 发送聊天请求(非流式)\n */\n async chat(options: ChatOptions): Promise<ChatResult> {\n const { model, messages, temperature = 0.7, maxTokens } = options;\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream: false,\n };\n\n if (maxTokens) {\n body.max_tokens = maxTokens;\n }\n\n const response = await fetch(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`HuggingFace API error: ${response.status} ${error}`);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result: any = await response.json();\n const choice = result.choices?.[0];\n\n if (!choice) {\n throw new Error('No response from model');\n }\n\n const msg = choice.message;\n const reasoningContent = msg?.reasoning_content ?? null;\n\n return {\n content: extractTextContent(msg?.content),\n reasoning: reasoningContent ? extractTextContent(reasoningContent) : null,\n model: result.model ?? model,\n usage: {\n promptTokens: result.usage?.prompt_tokens ?? 0,\n completionTokens: result.usage?.completion_tokens ?? 0,\n totalTokens: result.usage?.total_tokens ?? 0,\n },\n finishReason: choice.finish_reason ?? null,\n };\n }\n\n /**\n * 发送流式聊天请求\n */\n async *chatStream(\n options: ChatOptions\n ): AsyncGenerator<StreamChunk, void, unknown> {\n const { model, messages, temperature = 0.7, maxTokens } = options;\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream: true,\n };\n\n if (maxTokens) {\n body.max_tokens = maxTokens;\n }\n\n const response = await fetch(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`HuggingFace API error: ${response.status} ${error}`);\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error('No response body');\n }\n\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed === 'data: [DONE]') continue;\n if (!trimmed.startsWith('data: ')) continue;\n\n try {\n const data = JSON.parse(trimmed.slice(6));\n const delta = data.choices?.[0]?.delta;\n if (!delta) continue;\n\n // 思考内容\n if (delta.reasoning_content) {\n yield {\n type: 'reasoning',\n text: extractTextContent(delta.reasoning_content),\n };\n }\n\n // 回答内容\n if (delta.content) {\n yield {\n type: 'content',\n text: extractTextContent(delta.content),\n };\n }\n } catch {\n // 忽略解析错误\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n}\n","/**\n * ModelScope Provider 实现\n * 使用 OpenAI 兼容 API\n */\n\nimport { BaseProvider } from './__base__';\nimport type { ChatOptions, ChatResult, StreamChunk } from './__types__';\n\nconst BASE_URL = 'https://api-inference.modelscope.cn/v1';\n\n/**\n * ModelScope Provider 配置\n */\nexport interface ModelScopeConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\n/**\n * 从 content 中提取文本\n */\nfunction extractTextContent(content: unknown): string {\n if (typeof content === 'string') {\n return content;\n }\n if (Array.isArray(content)) {\n return content\n .filter(\n (item): item is { type: 'text'; text: string } =>\n typeof item === 'object' &&\n item !== null &&\n item.type === 'text' &&\n typeof item.text === 'string'\n )\n .map(item => item.text)\n .join('');\n }\n return '';\n}\n\n/**\n * ModelScope Provider\n * 兼容 OpenAI API 格式,支持 DeepSeek 等模型\n */\nexport class ModelScopeProvider extends BaseProvider {\n readonly name = 'modelscope';\n private apiKey: string;\n private baseUrl: string;\n\n constructor(config: ModelScopeConfig | string) {\n super();\n if (typeof config === 'string') {\n this.apiKey = config;\n this.baseUrl = BASE_URL;\n } else {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl ?? BASE_URL;\n }\n }\n\n /**\n * 发送聊天请求(非流式)\n */\n async chat(options: ChatOptions): Promise<ChatResult> {\n const {\n model,\n messages,\n temperature = 0.7,\n maxTokens,\n reasoning,\n } = options;\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream: false,\n };\n\n if (maxTokens) {\n body.max_tokens = maxTokens;\n }\n\n // ModelScope 使用 enable_thinking 控制思考\n // 参考: https://www.alibabacloud.com/help/en/model-studio/deepseek-api\n // 只在用户明确设置时才添加该参数\n if (reasoning?.effort) {\n if (reasoning.effort === 'off') {\n body.enable_thinking = false;\n } else {\n body.enable_thinking = true;\n }\n }\n\n const response = await fetch(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`ModelScope API error: ${response.status} ${error}`);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result: any = await response.json();\n const choice = result.choices?.[0];\n\n if (!choice) {\n throw new Error('No response from model');\n }\n\n const msg = choice.message;\n const reasoningContent = msg?.reasoning_content ?? null;\n\n return {\n content: extractTextContent(msg?.content),\n reasoning: reasoningContent ? extractTextContent(reasoningContent) : null,\n model: result.model ?? model,\n usage: {\n promptTokens: result.usage?.prompt_tokens ?? 0,\n completionTokens: result.usage?.completion_tokens ?? 0,\n totalTokens: result.usage?.total_tokens ?? 0,\n },\n finishReason: choice.finish_reason ?? null,\n };\n }\n\n /**\n * 发送流式聊天请求\n */\n async *chatStream(\n options: ChatOptions\n ): AsyncGenerator<StreamChunk, void, unknown> {\n const {\n model,\n messages,\n temperature = 0.7,\n maxTokens,\n reasoning,\n } = options;\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream: true,\n };\n\n if (maxTokens) {\n body.max_tokens = maxTokens;\n }\n\n // ModelScope 使用 enable_thinking 控制思考\n // 只在用户明确设置时才添加该参数\n if (reasoning?.effort) {\n if (reasoning.effort === 'off') {\n body.enable_thinking = false;\n } else {\n body.enable_thinking = true;\n }\n }\n\n const response = await fetch(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`ModelScope API error: ${response.status} ${error}`);\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error('No response body');\n }\n\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed === 'data: [DONE]') continue;\n if (!trimmed.startsWith('data: ')) continue;\n\n try {\n const data = JSON.parse(trimmed.slice(6));\n const delta = data.choices?.[0]?.delta;\n if (!delta) continue;\n\n // 思考内容\n if (delta.reasoning_content) {\n yield {\n type: 'reasoning',\n text: extractTextContent(delta.reasoning_content),\n };\n }\n\n // 回答内容\n if (delta.content) {\n yield {\n type: 'content',\n text: extractTextContent(delta.content),\n };\n }\n } catch {\n // 忽略解析错误\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n}\n","/**\n * DeepSeek Provider 实现\n * 使用 DeepSeek API (OpenAI 兼容格式)\n * https://api-docs.deepseek.com/\n *\n * 支持模型:\n * - deepseek-chat: DeepSeek-V3 通用对话模型(可通过 thinking 参数启用思考)\n * - deepseek-reasoner: DeepSeek-R1 推理模型(自动启用思考)\n *\n * 思考模式:\n * - 使用 reasoning.effort 不为 'off' 时,会启用 thinking 模式\n * - effort 映射为 max_tokens 控制思考量:low=1024, medium=4096, high=16384\n */\n\nimport { BaseProvider } from './__base__';\nimport type {\n ChatOptions,\n ChatResult,\n StreamChunk,\n ReasoningConfig,\n} from './__types__';\nimport { EFFORT_TOKEN_MAP } from './__types__';\n\nconst BASE_URL = 'https://api.deepseek.com';\n\n/**\n * DeepSeek Provider 配置\n */\nexport interface DeepSeekConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\n/**\n * 根据 reasoning 配置计算 max_tokens\n * budgetTokens 优先,否则使用 effort 映射\n */\nfunction getReasoningMaxTokens(\n reasoning?: ReasoningConfig,\n userMaxTokens?: number\n): number | undefined {\n if (!reasoning || reasoning.effort === 'off') {\n return userMaxTokens;\n }\n\n // budgetTokens 优先\n if (reasoning.budgetTokens !== undefined) {\n return reasoning.budgetTokens;\n }\n\n // 使用 effort 映射\n if (reasoning.effort) {\n return EFFORT_TOKEN_MAP[reasoning.effort];\n }\n\n return userMaxTokens;\n}\n\n/**\n * 从 content 中提取文本\n */\nfunction extractTextContent(content: unknown): string {\n if (typeof content === 'string') {\n return content;\n }\n if (Array.isArray(content)) {\n return content\n .filter(\n (item): item is { type: 'text'; text: string } =>\n typeof item === 'object' &&\n item !== null &&\n item.type === 'text' &&\n typeof item.text === 'string'\n )\n .map(item => item.text)\n .join('');\n }\n return '';\n}\n\n/**\n * DeepSeek Provider\n * 使用 DeepSeek API,兼容 OpenAI 格式\n */\nexport class DeepSeekProvider extends BaseProvider {\n readonly name = 'deepseek';\n private apiKey: string;\n private baseUrl: string;\n\n constructor(config: DeepSeekConfig | string) {\n super();\n if (typeof config === 'string') {\n this.apiKey = config;\n this.baseUrl = BASE_URL;\n } else {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl ?? BASE_URL;\n }\n }\n\n /**\n * 发送聊天请求(非流式)\n */\n async chat(options: ChatOptions): Promise<ChatResult> {\n const {\n model,\n messages,\n temperature = 0.7,\n maxTokens,\n reasoning,\n } = options;\n\n // 计算 max_tokens(包含思考 token)\n const effectiveMaxTokens = getReasoningMaxTokens(reasoning, maxTokens);\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream: false,\n };\n\n if (effectiveMaxTokens) {\n body.max_tokens = effectiveMaxTokens;\n }\n\n // 如果 effort 不为 'off',启用 thinking 模式\n if (reasoning?.effort && reasoning.effort !== 'off') {\n body.thinking = { type: 'enabled' };\n }\n\n const response = await fetch(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`DeepSeek API error: ${response.status} ${error}`);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result: any = await response.json();\n const choice = result.choices?.[0];\n\n if (!choice) {\n throw new Error('No response from model');\n }\n\n const msg = choice.message;\n // DeepSeek R1 使用 reasoning_content 返回思考过程\n const reasoningContent = msg?.reasoning_content ?? null;\n\n return {\n content: extractTextContent(msg?.content),\n reasoning: reasoningContent ? extractTextContent(reasoningContent) : null,\n model: result.model ?? model,\n usage: {\n promptTokens: result.usage?.prompt_tokens ?? 0,\n completionTokens: result.usage?.completion_tokens ?? 0,\n totalTokens: result.usage?.total_tokens ?? 0,\n },\n finishReason: choice.finish_reason ?? null,\n };\n }\n\n /**\n * 发送流式聊天请求\n */\n async *chatStream(\n options: ChatOptions\n ): AsyncGenerator<StreamChunk, void, unknown> {\n const {\n model,\n messages,\n temperature = 0.7,\n maxTokens,\n reasoning,\n } = options;\n\n // 计算 max_tokens(包含思考 token)\n const effectiveMaxTokens = getReasoningMaxTokens(reasoning, maxTokens);\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream: true,\n };\n\n if (effectiveMaxTokens) {\n body.max_tokens = effectiveMaxTokens;\n }\n\n // 如果 effort 不为 'off',启用 thinking 模式\n if (reasoning?.effort && reasoning.effort !== 'off') {\n body.thinking = { type: 'enabled' };\n }\n\n const response = await fetch(`${this.baseUrl}/chat/completions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`DeepSeek API error: ${response.status} ${error}`);\n }\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error('No response body');\n }\n\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed === 'data: [DONE]') continue;\n if (!trimmed.startsWith('data: ')) continue;\n\n try {\n const data = JSON.parse(trimmed.slice(6));\n const delta = data.choices?.[0]?.delta;\n if (!delta) continue;\n\n // DeepSeek R1 推理模型的思考内容\n if (delta.reasoning_content) {\n yield {\n type: 'reasoning',\n text: extractTextContent(delta.reasoning_content),\n };\n }\n\n // 回答内容\n if (delta.content) {\n yield {\n type: 'content',\n text: extractTextContent(delta.content),\n };\n }\n } catch {\n // 忽略解析错误\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n}\n","/**\n * 统一的 Provider 工厂\n * 让所有 Provider 使用方式一致\n */\n\nimport type { AIProvider } from './__base__';\nimport { OpenRouterProvider } from './openrouter';\nimport { GeminiProvider } from './gemini';\nimport { GroqProvider } from './groq';\nimport { HuggingFaceProvider } from './huggingface';\nimport { ModelScopeProvider } from './modelscope';\nimport { DeepSeekProvider } from './deepseek';\n\n/**\n * 支持的 Provider 类型\n */\nexport type ProviderType =\n | 'openrouter'\n | 'gemini'\n | 'groq'\n | 'huggingface'\n | 'modelscope'\n | 'deepseek';\n\n/**\n * 统一的 Provider 配置\n */\nexport interface ProviderConfig {\n /** Provider 类型 */\n provider: ProviderType;\n /** API Key */\n apiKey: string;\n /** 自定义 API 地址(可选) */\n baseUrl?: string;\n}\n\n/**\n * 创建 AI Provider 实例\n *\n * @example\n * ```ts\n * // 所有 Provider 使用相同方式创建\n * const openrouter = createProvider({ provider: 'openrouter', apiKey: 'xxx' });\n * const gemini = createProvider({ provider: 'gemini', apiKey: 'xxx' });\n * const groq = createProvider({ provider: 'groq', apiKey: 'xxx' });\n *\n * // 之后使用方式完全一致\n * const answer = await openrouter.ask('gpt-4o', '你好');\n * const answer = await gemini.ask('gemini-2.5-flash', '你好');\n * ```\n */\nexport function createProvider(config: ProviderConfig): AIProvider {\n const { provider, apiKey, baseUrl } = config;\n\n switch (provider) {\n case 'openrouter':\n return new OpenRouterProvider(apiKey);\n\n case 'gemini':\n return new GeminiProvider(baseUrl ? { apiKey, baseUrl } : apiKey);\n\n case 'groq':\n return new GroqProvider(baseUrl ? { apiKey, baseUrl } : apiKey);\n\n case 'huggingface':\n return new HuggingFaceProvider(baseUrl ? { apiKey, baseUrl } : apiKey);\n\n case 'modelscope':\n return new ModelScopeProvider(baseUrl ? { apiKey, baseUrl } : apiKey);\n\n case 'deepseek':\n return new DeepSeekProvider(baseUrl ? { apiKey, baseUrl } : apiKey);\n\n default:\n throw new Error(`Unknown provider: ${provider}`);\n }\n}\n\n/**\n * 快捷创建函数\n */\nexport const ai = {\n openrouter: (apiKey: string, baseUrl?: string) =>\n createProvider({ provider: 'openrouter', apiKey, baseUrl }),\n\n gemini: (apiKey: string, baseUrl?: string) =>\n createProvider({ provider: 'gemini', apiKey, baseUrl }),\n\n groq: (apiKey: string, baseUrl?: string) =>\n createProvider({ provider: 'groq', apiKey, baseUrl }),\n\n huggingface: (apiKey: string, baseUrl?: string) =>\n createProvider({ provider: 'huggingface', apiKey, baseUrl }),\n\n modelscope: (apiKey: string, baseUrl?: string) =>\n createProvider({ provider: 'modelscope', apiKey, baseUrl }),\n\n deepseek: (apiKey: string, baseUrl?: string) =>\n createProvider({ provider: 'deepseek', apiKey, baseUrl }),\n};\n"],"mappings":"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","names":["extractTextContent","BASE_URL","extractTextContent","BASE_URL","extractTextContent","BASE_URL","extractTextContent","BASE_URL","extractTextContent"]}
|
|
1
|
+
{"version":3,"sources":["../src/providers/__types__.ts","../src/utils/request-builder.ts","../src/client/types.ts","../src/client/http-provider-client.ts","../src/utils/stream-processor.ts","../src/fluent/chat-session.ts","../src/adapters/types.ts","../src/adapters/openrouter-adapter.ts","../src/adapters/gemini-adapter.ts","../src/adapters/groq-adapter.ts","../src/adapters/huggingface-adapter.ts","../src/adapters/modelscope-adapter.ts","../src/adapters/deepseek-adapter.ts","../src/adapters/poe-adapter.ts","../src/adapters/nova-adapter.ts","../src/adapters/index.ts","../src/registry/provider-registry.ts","../src/config/types.ts","../src/utils/config-validator.ts","../src/config/config-manager.ts","../src/providers/__factory__.ts","../src/providers/__model-detection__.ts","../src/providers/__base__.ts","../src/providers/__index__.ts","../src/providers/openrouter.ts","../src/providers/modelscope.ts","../src/providers/huggingface.ts","../src/providers/groq.ts","../src/providers/gemini.ts","../src/providers/deepseek.ts","../src/providers/poe.ts","../src/providers/nova.ts","../src/utils/index.ts","../src/client/index.ts","../src/fluent/errors.ts","../src/fluent/builder.ts","../src/fluent/preset-provider.ts","../src/fluent/index.ts","../src/fluent/preset-instances.ts"],"sourcesContent":["/**\n * AI Provider 统一类型定义\n */\n\n// ============ 消息类型 ============\n\nexport interface ChatMessage {\n role: 'system' | 'user' | 'assistant';\n content: string;\n}\n\n// ============ 思考/推理配置 ============\n\n/**\n * 统一的思考努力程度\n * - off: 关闭思考\n * - low: 快速思考,适合简单问题\n * - medium: 平衡模式(默认)\n * - high: 深度思考,适合复杂问题\n */\nexport type ReasoningEffort = 'off' | 'low' | 'medium' | 'high';\n\n/**\n * 统一的思考/推理配置\n *\n * 只需设置 effort,库会自动转换为各 Provider 需要的格式:\n * - OpenRouter: effort 参数\n * - Gemini: reasoning_effort 参数\n * - Groq: reasoning_effort 参数\n * - ModelScope: enable_thinking 参数\n *\n * @example\n * ```ts\n * // 简单用法 - 只设置 effort\n * { effort: 'high' }\n *\n * // 高级用法 - 精细控制\n * { effort: 'high', budgetTokens: 8000 }\n * ```\n */\nexport interface ReasoningConfig {\n /**\n * 思考努力程度(推荐使用)\n * - 'off': 关闭思考\n * - 'low': 快速思考\n * - 'medium': 平衡模式\n * - 'high': 深度思考\n */\n effort?: ReasoningEffort;\n\n /**\n * 思考 token 预算(可选,精细控制)\n * 设置后会覆盖 effort 对应的默认值\n * 仅部分 Provider 支持(OpenRouter)\n */\n budgetTokens?: number;\n\n /**\n * 是否在响应中排除思考内容\n * 仅部分 Provider 支持(OpenRouter)\n */\n exclude?: boolean;\n}\n\n/**\n * effort 到 token 预算的默认映射\n */\nexport const EFFORT_TOKEN_MAP: Record<ReasoningEffort, number> = {\n off: 0,\n low: 1024,\n medium: 4096,\n high: 16384,\n};\n\n// ============ 请求/响应类型 ============\n\nexport interface ChatOptions {\n /** 模型 ID */\n model: string;\n /** 对话消息列表 */\n messages: ChatMessage[];\n /** 温度参数 0-2 */\n temperature?: number;\n /** 最大输出 token 数 */\n maxTokens?: number;\n /** 思考/推理配置 */\n reasoning?: ReasoningConfig;\n}\n\nexport interface ChatResult {\n /** 最终回答内容 */\n content: string;\n /** 思考过程(仅 reasoning 模型有) */\n reasoning: string | null;\n /** 使用的模型 */\n model: string;\n /** Token 使用情况 */\n usage: TokenUsage;\n /** 完成原因 */\n finishReason: string | null;\n}\n\nexport interface TokenUsage {\n promptTokens: number;\n completionTokens: number;\n totalTokens: number;\n}\n\n// ============ 流式输出类型 ============\n\nexport interface StreamChunk {\n type: 'reasoning' | 'content';\n text: string;\n}\n\n// ============ 模型信息类型 ============\n\nexport interface ModelPricing {\n /** 输入 token 单价 ($/token) */\n prompt: string;\n /** 输出 token 单价 ($/token) */\n completion: string;\n /** 请求单价 */\n request: string;\n /** 图片单价 */\n image: string;\n}\n\nexport interface ModelInfo {\n /** 模型 ID */\n id: string;\n /** 模型名称 */\n name: string;\n /** 模型描述 */\n description: string;\n /** 定价信息 */\n pricing: ModelPricing;\n /** 上下文长度 */\n contextLength: number;\n /** 支持的参数 */\n supportedParameters: string[];\n}\n","/**\n * 请求构建器 - 构建标准化的 API 请求\n * 统一各 Provider 的请求参数构建逻辑\n */\n\nimport type { ChatOptions, ReasoningConfig } from '../providers/__types__';\nimport { EFFORT_TOKEN_MAP } from '../providers/__types__';\n\n/**\n * 请求构建器类\n * 提供统一的 API 请求参数构建功能\n */\nexport class RequestBuilder {\n /**\n * 构建聊天请求的基础参数\n * 生成标准化的 OpenAI 兼容格式请求体\n *\n * @param options - 聊天选项\n * @param stream - 是否为流式请求\n * @returns 请求体对象\n *\n * @example\n * ```ts\n * const body = RequestBuilder.buildChatBody({\n * model: 'gpt-4',\n * messages: [{ role: 'user', content: 'Hello' }],\n * temperature: 0.7\n * });\n * ```\n */\n static buildChatBody(\n options: ChatOptions,\n stream: boolean = false\n ): Record<string, unknown> {\n const { model, messages, temperature = 0.7, maxTokens } = options;\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream,\n };\n\n if (maxTokens !== undefined) {\n body.max_tokens = maxTokens;\n }\n\n return body;\n }\n\n /**\n * 构建 OpenRouter 格式的 reasoning 参数\n *\n * @param config - 推理配置\n * @returns OpenRouter 格式的 reasoning 参数,或 undefined\n *\n * @example\n * ```ts\n * const reasoning = RequestBuilder.buildOpenRouterReasoning({ effort: 'high' });\n * // => { effort: 'high', max_tokens: 16384 }\n * ```\n */\n static buildOpenRouterReasoning(\n config?: ReasoningConfig\n ): Record<string, unknown> | undefined {\n if (!config) return undefined;\n if (config.effort === 'off') return undefined;\n\n const param: Record<string, unknown> = {};\n\n // 设置 effort\n if (config.effort) {\n param.effort = config.effort;\n }\n\n // budgetTokens 优先,否则使用 effort 对应的默认值\n if (config.budgetTokens !== undefined) {\n param.max_tokens = config.budgetTokens;\n } else if (config.effort && EFFORT_TOKEN_MAP[config.effort]) {\n param.max_tokens = EFFORT_TOKEN_MAP[config.effort];\n }\n\n if (config.exclude !== undefined) {\n param.exclude = config.exclude;\n }\n\n return Object.keys(param).length > 0 ? param : undefined;\n }\n\n /**\n * 构建 Gemini 格式的 reasoning 参数\n * Gemini 2.5+ 模型使用 reasoning_effort 控制思考\n *\n * @param config - 推理配置\n * @returns Gemini 格式的参数对象\n *\n * @example\n * ```ts\n * const params = RequestBuilder.buildGeminiReasoning({ effort: 'high' });\n * // => { reasoning_effort: 'high' }\n * ```\n */\n static buildGeminiReasoning(\n config?: ReasoningConfig\n ): Record<string, unknown> {\n if (!config || !config.effort || config.effort === 'off') {\n return {};\n }\n\n return {\n reasoning_effort: config.effort,\n };\n }\n\n /**\n * 构建 Groq 格式的 reasoning 参数\n * Groq 使用 reasoning_format 参数控制推理输出\n *\n * @param config - 推理配置\n * @returns Groq 格式的参数对象\n *\n * @example\n * ```ts\n * const params = RequestBuilder.buildGroqReasoning({ effort: 'high' });\n * // => { reasoning_format: 'parsed' }\n * ```\n */\n static buildGroqReasoning(config?: ReasoningConfig): Record<string, unknown> {\n if (!config) {\n return {};\n }\n\n if (config.effort === 'off') {\n return { include_reasoning: false };\n }\n\n if (config.effort) {\n return { reasoning_format: 'parsed' };\n }\n\n return {};\n }\n\n /**\n * 构建 DeepSeek 格式的 reasoning 参数\n * DeepSeek 使用 thinking 参数启用思考模式\n *\n * @param config - 推理配置\n * @returns DeepSeek 格式的参数对象\n */\n static buildDeepSeekReasoning(\n config?: ReasoningConfig\n ): Record<string, unknown> {\n if (!config || !config.effort || config.effort === 'off') {\n return {};\n }\n\n return {\n thinking: { type: 'enabled' },\n };\n }\n\n /**\n * 构建 Nova 格式的 reasoning 参数\n * Nova 使用 reasoningConfig 控制 extended thinking\n *\n * @param config - 推理配置\n * @returns Nova 格式的参数对象\n */\n static buildNovaReasoning(config?: ReasoningConfig): Record<string, unknown> {\n if (!config || !config.effort || config.effort === 'off') {\n return {};\n }\n\n return {\n reasoningConfig: {\n type: 'enabled',\n maxReasoningEffort: config.effort,\n },\n };\n }\n\n /**\n * 构建 HTTP 请求头\n *\n * @param apiKey - API 密钥\n * @param additionalHeaders - 额外的请求头\n * @returns 请求头对象\n *\n * @example\n * ```ts\n * const headers = RequestBuilder.buildHeaders('sk-xxx', {\n * 'X-Custom-Header': 'value'\n * });\n * ```\n */\n static buildHeaders(\n apiKey: string,\n additionalHeaders?: Record<string, string>\n ): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey}`,\n ...additionalHeaders,\n };\n }\n}\n","/**\n * Provider 客户端层类型定义\n * 定义执行 HTTP 请求的客户端接口\n */\n\n/**\n * Provider 客户端配置\n */\nexport interface ProviderClientConfig {\n /** API 密钥 */\n apiKey: string;\n /** 基础 URL */\n baseUrl: string;\n /** 请求超时时间(毫秒) */\n timeout?: number;\n /** 额外的请求头 */\n headers?: Record<string, string>;\n}\n\n/**\n * Provider 客户端接口\n * 定义执行 HTTP 请求的统一接口\n */\nexport interface ProviderClient {\n /**\n * 发送聊天请求(非流式)\n *\n * @param endpoint - API 端点路径\n * @param body - 请求体\n * @returns 响应数据\n * @throws ProviderError 当请求失败时\n */\n chat(\n endpoint: string,\n body: Record<string, unknown>\n ): Promise<Record<string, unknown>>;\n\n /**\n * 发送流式聊天请求\n *\n * @param endpoint - API 端点路径\n * @param body - 请求体\n * @returns fetch Response 对象,用于流式处理\n * @throws ProviderError 当请求失败时\n */\n chatStream(\n endpoint: string,\n body: Record<string, unknown>\n ): Promise<Response>;\n}\n\n/**\n * Provider 错误基类\n */\nexport class ProviderError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n public readonly provider: string,\n public readonly cause?: Error\n ) {\n super(message);\n this.name = 'ProviderError';\n }\n}\n\n/**\n * API 错误\n * 用于 HTTP 请求失败的情况\n */\nexport class APIError extends ProviderError {\n constructor(\n message: string,\n provider: string,\n public readonly statusCode: number,\n public readonly responseBody?: string\n ) {\n super(message, 'API_ERROR', provider);\n this.name = 'APIError';\n }\n}\n\n/**\n * 网络错误\n * 用于网络连接失败的情况\n */\nexport class NetworkError extends ProviderError {\n constructor(message: string, provider: string, cause?: Error) {\n super(message, 'NETWORK_ERROR', provider, cause);\n this.name = 'NetworkError';\n }\n}\n\n/**\n * 超时错误\n * 用于请求超时的情况\n */\nexport class TimeoutError extends ProviderError {\n constructor(\n message: string,\n provider: string,\n public readonly timeoutMs: number\n ) {\n super(message, 'TIMEOUT_ERROR', provider);\n this.name = 'TimeoutError';\n }\n}\n","/**\n * HTTP Provider 客户端实现\n * 提供基于 fetch 的 HTTP 请求功能\n */\n\nimport { RequestBuilder } from '../utils/request-builder';\nimport type { ProviderClient, ProviderClientConfig } from './types';\nimport { APIError, NetworkError, TimeoutError } from './types';\n\n/**\n * 默认配置\n */\nconst DEFAULT_TIMEOUT = 30000; // 30 秒\n\n/**\n * HTTP Provider 客户端\n * 实现 ProviderClient 接口,提供统一的 HTTP 请求功能\n */\nexport class HttpProviderClient implements ProviderClient {\n private readonly config: Required<\n Pick<ProviderClientConfig, 'apiKey' | 'baseUrl'>\n > &\n ProviderClientConfig;\n\n /**\n * 创建 HTTP Provider 客户端实例\n *\n * @param config - 客户端配置\n *\n * @example\n * ```ts\n * const client = new HttpProviderClient({\n * apiKey: 'sk-xxx',\n * baseUrl: 'https://api.openai.com/v1',\n * timeout: 60000\n * });\n * ```\n */\n constructor(config: ProviderClientConfig) {\n this.config = {\n ...config,\n timeout: config.timeout ?? DEFAULT_TIMEOUT,\n };\n }\n\n /**\n * 获取 Provider 名称(从 baseUrl 推断)\n */\n private getProviderName(): string {\n try {\n const url = new URL(this.config.baseUrl);\n return url.hostname;\n } catch {\n return 'unknown';\n }\n }\n\n /**\n * 构建完整的请求 URL\n */\n private buildUrl(endpoint: string): string {\n const baseUrl = this.config.baseUrl.replace(/\\/$/, '');\n const path = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;\n return `${baseUrl}${path}`;\n }\n\n /**\n * 构建请求头\n */\n private buildHeaders(): Record<string, string> {\n return RequestBuilder.buildHeaders(this.config.apiKey, this.config.headers);\n }\n\n /**\n * 创建带超时的 AbortController\n */\n private createAbortController(): {\n controller: AbortController;\n timeoutId: ReturnType<typeof setTimeout>;\n } {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => {\n controller.abort();\n }, this.config.timeout ?? DEFAULT_TIMEOUT);\n\n return { controller, timeoutId };\n }\n\n /**\n * 处理 HTTP 错误响应\n */\n private async handleErrorResponse(response: Response): Promise<never> {\n const provider = this.getProviderName();\n let responseBody: string | undefined;\n\n try {\n responseBody = await response.text();\n } catch {\n // 忽略读取响应体失败的情况\n }\n\n // 根据状态码生成友好的错误消息\n let message: string;\n switch (response.status) {\n case 400:\n message = '请求参数错误';\n break;\n case 401:\n message = 'API 密钥无效或已过期';\n break;\n case 403:\n message = '没有权限访问此资源';\n break;\n case 404:\n message = '请求的资源不存在';\n break;\n case 429:\n message = '请求过于频繁,请稍后重试';\n break;\n case 500:\n message = '服务器内部错误';\n break;\n case 502:\n message = '网关错误';\n break;\n case 503:\n message = '服务暂时不可用';\n break;\n default:\n message = `HTTP 错误: ${response.status} ${response.statusText}`;\n }\n\n throw new APIError(message, provider, response.status, responseBody);\n }\n\n /**\n * 发送聊天请求(非流式)\n *\n * @param endpoint - API 端点路径\n * @param body - 请求体\n * @returns 响应数据\n */\n async chat(\n endpoint: string,\n body: Record<string, unknown>\n ): Promise<Record<string, unknown>> {\n const url = this.buildUrl(endpoint);\n const headers = this.buildHeaders();\n const { controller, timeoutId } = this.createAbortController();\n const provider = this.getProviderName();\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n await this.handleErrorResponse(response);\n }\n\n const data = await response.json();\n return data as Record<string, unknown>;\n } catch (error) {\n clearTimeout(timeoutId);\n\n // 已经是我们的错误类型,直接抛出\n if (error instanceof APIError) {\n throw error;\n }\n\n // 处理超时错误\n if (error instanceof Error && error.name === 'AbortError') {\n throw new TimeoutError(\n `请求超时(${this.config.timeout}ms)`,\n provider,\n this.config.timeout ?? DEFAULT_TIMEOUT\n );\n }\n\n // 处理网络错误\n if (error instanceof TypeError) {\n throw new NetworkError('网络连接失败,请检查网络设置', provider, error);\n }\n\n // 其他未知错误\n throw new NetworkError(\n error instanceof Error ? error.message : '未知错误',\n provider,\n error instanceof Error ? error : undefined\n );\n }\n }\n\n /**\n * 发送流式聊天请求\n *\n * @param endpoint - API 端点路径\n * @param body - 请求体\n * @returns fetch Response 对象\n */\n async chatStream(\n endpoint: string,\n body: Record<string, unknown>\n ): Promise<Response> {\n const url = this.buildUrl(endpoint);\n const headers = this.buildHeaders();\n const { controller, timeoutId } = this.createAbortController();\n const provider = this.getProviderName();\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n // 注意:流式请求不清除超时,让调用者处理\n // 但我们需要在响应完成后清除\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n await this.handleErrorResponse(response);\n }\n\n return response;\n } catch (error) {\n clearTimeout(timeoutId);\n\n // 已经是我们的错误类型,直接抛出\n if (error instanceof APIError) {\n throw error;\n }\n\n // 处理超时错误\n if (error instanceof Error && error.name === 'AbortError') {\n throw new TimeoutError(\n `请求超时(${this.config.timeout}ms)`,\n provider,\n this.config.timeout ?? DEFAULT_TIMEOUT\n );\n }\n\n // 处理网络错误\n if (error instanceof TypeError) {\n throw new NetworkError('网络连接失败,请检查网络设置', provider, error);\n }\n\n // 其他未知错误\n throw new NetworkError(\n error instanceof Error ? error.message : '未知错误',\n provider,\n error instanceof Error ? error : undefined\n );\n }\n }\n}\n","/**\n * 流处理器 - 处理 SSE 流式响应\n * 从各 Provider 中提取并统一的流处理逻辑\n */\n\nimport type { StreamChunk } from '../providers/__types__';\n\n/**\n * Delta 提取器函数类型\n * 从流式响应的 delta 中提取 StreamChunk\n */\nexport type DeltaExtractor = (\n delta: Record<string, unknown>\n) => StreamChunk | null;\n\n/**\n * 流处理器类\n * 提供统一的 SSE 流式响应处理功能\n */\nexport class StreamProcessor {\n /**\n * 从响应内容中提取文本\n * 支持字符串和数组格式的 content\n *\n * @param content - 响应内容,可以是字符串、数组或其他类型\n * @returns 提取的文本内容\n *\n * @example\n * ```ts\n * // 字符串格式\n * StreamProcessor.extractTextContent('Hello') // => 'Hello'\n *\n * // 数组格式\n * StreamProcessor.extractTextContent([\n * { type: 'text', text: 'Hello' },\n * { type: 'text', text: ' World' }\n * ]) // => 'Hello World'\n * ```\n */\n static extractTextContent(content: unknown): string {\n if (typeof content === 'string') {\n return content;\n }\n if (Array.isArray(content)) {\n return content\n .filter(\n (item): item is { type: 'text'; text: string } =>\n typeof item === 'object' &&\n item !== null &&\n item.type === 'text' &&\n typeof item.text === 'string'\n )\n .map(item => item.text)\n .join('');\n }\n return '';\n }\n\n /**\n * 解析 SSE 数据行\n *\n * @param line - SSE 数据行(如 \"data: {...}\")\n * @returns 解析后的 JSON 对象,或 null(如果是 [DONE] 或无效数据)\n *\n * @example\n * ```ts\n * StreamProcessor.parseSSELine('data: {\"content\": \"Hello\"}')\n * // => { content: 'Hello' }\n *\n * StreamProcessor.parseSSELine('data: [DONE]')\n * // => null\n * ```\n */\n static parseSSELine(line: string): Record<string, unknown> | null {\n const trimmed = line.trim();\n\n // 空行或 [DONE] 标记\n if (!trimmed || trimmed === 'data: [DONE]') {\n return null;\n }\n\n // 必须以 \"data: \" 开头\n if (!trimmed.startsWith('data: ')) {\n return null;\n }\n\n try {\n const jsonStr = trimmed.slice(6); // 移除 \"data: \" 前缀\n return JSON.parse(jsonStr) as Record<string, unknown>;\n } catch {\n // 解析失败返回 null\n return null;\n }\n }\n\n /**\n * 创建流式响应处理器\n * 处理 SSE 格式的流式响应,提取并生成 StreamChunk\n *\n * @param response - fetch Response 对象\n * @param deltaExtractor - 从 delta 中提取 StreamChunk 的函数\n * @returns AsyncGenerator<StreamChunk>\n *\n * @example\n * ```ts\n * const response = await fetch(url, { ... });\n * const extractor = (delta) => {\n * if (delta.content) {\n * return { type: 'content', text: delta.content };\n * }\n * return null;\n * };\n *\n * for await (const chunk of StreamProcessor.processStream(response, extractor)) {\n * console.log(chunk.type, chunk.text);\n * }\n * ```\n */\n static async *processStream(\n response: Response,\n deltaExtractor: DeltaExtractor\n ): AsyncGenerator<StreamChunk, void, unknown> {\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error('No response body');\n }\n\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n const data = StreamProcessor.parseSSELine(line);\n if (!data) continue;\n\n // 从响应数据中提取 delta\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const choices = data.choices as any[] | undefined;\n const delta = choices?.[0]?.delta as Record<string, unknown>;\n if (!delta) continue;\n\n // 使用提取器函数获取 StreamChunk\n const chunk = deltaExtractor(delta);\n if (chunk) {\n yield chunk;\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n /**\n * 创建默认的 delta 提取器\n * 支持 reasoning_content、reasoning、thoughts 和 content 字段\n *\n * @returns DeltaExtractor 函数\n */\n static createDefaultExtractor(): DeltaExtractor {\n return (delta: Record<string, unknown>): StreamChunk | null => {\n // 思考内容(支持多种字段名)\n const reasoningContent =\n delta.reasoning_content ?? delta.reasoning ?? delta.thoughts;\n if (reasoningContent) {\n return {\n type: 'reasoning',\n text: StreamProcessor.extractTextContent(reasoningContent),\n };\n }\n\n // 回答内容\n if (delta.content) {\n return {\n type: 'content',\n text: StreamProcessor.extractTextContent(delta.content),\n };\n }\n\n return null;\n };\n }\n}\n","/**\n * 多轮对话会话实现\n * 自动维护对话历史,支持流式和非流式响应\n */\n\nimport type {\n ChatSession,\n ChatSessionOptions,\n StreamChunk,\n ChatMessage,\n PresetProvider,\n} from './types';\n\n/**\n * 多轮对话会话实现类\n * 自动维护对话历史\n */\nexport class ChatSessionImpl implements ChatSession {\n /** 预设实例引用 */\n private readonly preset: PresetProvider;\n\n /** 模型 ID */\n private readonly model: string;\n\n /** 会话配置 */\n private readonly options: ChatSessionOptions;\n\n /** 对话历史 */\n private history: ChatMessage[] = [];\n\n /**\n * 创建对话会话\n * @param preset - 预设实例\n * @param model - 模型 ID\n * @param options - 会话配置\n */\n constructor(\n preset: PresetProvider,\n model: string,\n options?: ChatSessionOptions\n ) {\n this.preset = preset;\n this.model = model;\n this.options = options ?? {};\n\n // 如果有系统提示词,添加到历史开头\n if (this.options.system) {\n this.history.push({\n role: 'system',\n content: this.options.system,\n });\n }\n }\n\n /**\n * 发送消息并获取响应(非流式)\n * @param message - 用户消息\n * @returns 助手响应内容\n */\n async send(message: string): Promise<string> {\n // 添加用户消息到历史\n this.history.push({\n role: 'user',\n content: message,\n });\n\n try {\n // 调用预设实例的 ask 方法\n const response = await this.preset.ask(this.model, message, {\n system: this.buildSystemContext(),\n temperature: this.options.temperature,\n maxTokens: this.options.maxTokens,\n reasoning: this.options.reasoning,\n });\n\n // 添加助手响应到历史\n this.history.push({\n role: 'assistant',\n content: response,\n });\n\n return response;\n } catch (error) {\n // 发生错误时,移除刚添加的用户消息\n this.history.pop();\n throw error;\n }\n }\n\n /**\n * 发送消息并获取流式响应\n * @param message - 用户消息\n * @returns 流式数据块生成器\n */\n async *sendStream(message: string): AsyncGenerator<StreamChunk> {\n // 添加用户消息到历史\n this.history.push({\n role: 'user',\n content: message,\n });\n\n // 累积响应内容\n let responseContent = '';\n\n try {\n // 调用预设实例的 stream 方法\n const stream = this.preset.stream(this.model, message, {\n system: this.buildSystemContext(),\n temperature: this.options.temperature,\n maxTokens: this.options.maxTokens,\n reasoning: this.options.reasoning,\n });\n\n for await (const chunk of stream) {\n // 只累积 content 类型的文本\n if (chunk.type === 'content') {\n responseContent += chunk.text;\n }\n yield chunk;\n }\n\n // 流结束后,添加助手响应到历史\n this.history.push({\n role: 'assistant',\n content: responseContent,\n });\n } catch (error) {\n // 发生错误时,移除刚添加的用户消息\n this.history.pop();\n throw error;\n }\n }\n\n /**\n * 获取对话历史\n * @returns 按发送顺序排列的消息列表\n */\n getHistory(): ChatMessage[] {\n return [...this.history];\n }\n\n /**\n * 清空对话历史\n */\n clearHistory(): void {\n this.history = [];\n\n // 如果有系统提示词,重新添加\n if (this.options.system) {\n this.history.push({\n role: 'system',\n content: this.options.system,\n });\n }\n }\n\n /**\n * 构建系统上下文\n * 将对话历史转换为系统提示词的一部分\n * @returns 系统上下文字符串\n */\n private buildSystemContext(): string | undefined {\n // 获取非系统消息的历史(不包括最后一条用户消息,因为它会作为 question 传递)\n const conversationHistory = this.history.filter(\n (msg, index) => msg.role !== 'system' && index < this.history.length - 1\n );\n\n if (conversationHistory.length === 0) {\n return this.options.system;\n }\n\n // 构建对话历史上下文\n const historyContext = conversationHistory\n .map(msg => `${msg.role === 'user' ? '用户' : '助手'}: ${msg.content}`)\n .join('\\n');\n\n const baseSystem = this.options.system ?? '';\n return `${baseSystem}\\n\\n以下是之前的对话历史:\\n${historyContext}`.trim();\n }\n}\n","/**\n * Provider 适配器层类型定义\n * 定义所有 Provider 适配器必须实现的接口\n */\n\nimport type {\n ChatOptions,\n ChatResult,\n StreamChunk,\n ReasoningConfig,\n} from '../providers/__types__';\nimport type { ProviderClient, ProviderClientConfig } from '../client/types';\n\n/**\n * Provider 类型枚举\n * 支持的所有 Provider 类型\n */\nexport type ProviderType =\n | 'openrouter'\n | 'gemini'\n | 'groq'\n | 'huggingface'\n | 'modelscope'\n | 'deepseek'\n | 'poe'\n | 'nova';\n\n/**\n * 适配器配置\n * 用于创建适配器实例时的配置\n */\nexport interface AdapterConfig {\n /** API 密钥 */\n apiKey: string;\n /** 基础 URL(可选,使用默认值) */\n baseUrl?: string;\n /** 额外的请求头 */\n headers?: Record<string, string>;\n /** 请求超时时间(毫秒) */\n timeout?: number;\n}\n\n/**\n * Provider 适配器接口\n * 每个 Provider 实现一个适配器,负责将 Provider 特定的 API 适配为统一接口\n *\n * 适配器的职责:\n * 1. 构建 Provider 特定的请求格式\n * 2. 解析 Provider 特定的响应格式\n * 3. 处理 Provider 特定的 reasoning 参数\n * 4. 提供 API 端点 URL\n */\nexport interface ProviderAdapter {\n /**\n * 适配器名称(与 ProviderType 对应)\n */\n readonly name: ProviderType;\n\n /**\n * Provider 的默认基础 URL\n */\n readonly defaultBaseUrl: string;\n\n /**\n * 创建 Provider 客户端\n *\n * @param config - 客户端配置\n * @returns ProviderClient 实例\n */\n createClient(config: ProviderClientConfig): ProviderClient;\n\n /**\n * 构建聊天请求体\n * 将统一的 ChatOptions 转换为 Provider 特定的请求格式\n *\n * @param options - 聊天选项\n * @param stream - 是否为流式请求\n * @returns Provider 特定格式的请求体\n */\n buildChatRequest(\n options: ChatOptions,\n stream?: boolean\n ): Record<string, unknown>;\n\n /**\n * 构建 Provider 特定的 reasoning 参数\n *\n * @param config - 推理配置\n * @returns Provider 特定格式的 reasoning 参数\n */\n buildReasoningParams(config?: ReasoningConfig): Record<string, unknown>;\n\n /**\n * 解析聊天响应\n * 将 Provider 特定的响应格式转换为统一的 ChatResult\n *\n * @param response - Provider 返回的原始响应\n * @param model - 请求使用的模型\n * @returns 统一格式的 ChatResult\n */\n parseChatResponse(\n response: Record<string, unknown>,\n model: string\n ): ChatResult;\n\n /**\n * 从流式响应的 delta 中提取 StreamChunk\n *\n * @param delta - 流式响应中的 delta 对象\n * @returns StreamChunk 或 null(如果无法提取)\n */\n extractStreamChunk(delta: Record<string, unknown>): StreamChunk | null;\n\n /**\n * 获取 API 端点 URL\n *\n * @param baseUrl - 基础 URL\n * @returns 完整的 API 端点 URL\n */\n getEndpointUrl(baseUrl: string): string;\n}\n\n/**\n * 基础适配器抽象类\n * 提供通用的默认实现,子类可以覆盖特定方法\n */\nexport abstract class BaseAdapter implements ProviderAdapter {\n abstract readonly name: ProviderType;\n abstract readonly defaultBaseUrl: string;\n\n /**\n * 创建 Provider 客户端\n * 默认实现:需要在运行时导入 HttpProviderClient 以避免循环依赖\n */\n createClient(config: ProviderClientConfig): ProviderClient {\n // 延迟导入以避免循环依赖\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { HttpProviderClient } = require('../client/http-provider-client');\n return new HttpProviderClient(config);\n }\n\n /**\n * 构建聊天请求体\n * 默认实现:构建 OpenAI 兼容格式的请求体\n */\n buildChatRequest(\n options: ChatOptions,\n stream: boolean = false\n ): Record<string, unknown> {\n const {\n model,\n messages,\n temperature = 0.7,\n maxTokens,\n reasoning,\n } = options;\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream,\n };\n\n if (maxTokens !== undefined) {\n body.max_tokens = maxTokens;\n }\n\n // 合并 Provider 特定的 reasoning 参数\n const reasoningParams = this.buildReasoningParams(reasoning);\n Object.assign(body, reasoningParams);\n\n return body;\n }\n\n /**\n * 构建 reasoning 参数\n * 默认实现:返回空对象,子类应覆盖此方法\n */\n buildReasoningParams(_config?: ReasoningConfig): Record<string, unknown> {\n return {};\n }\n\n /**\n * 解析聊天响应\n * 默认实现:解析 OpenAI 兼容格式的响应\n */\n parseChatResponse(\n response: Record<string, unknown>,\n model: string\n ): ChatResult {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const choices = response.choices as any[] | undefined;\n const choice = choices?.[0];\n\n if (!choice) {\n throw new Error('No response from model');\n }\n\n const msg = choice.message;\n const reasoningContent = msg?.reasoning_content ?? msg?.reasoning ?? null;\n\n // 延迟导入以避免循环依赖\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { StreamProcessor } = require('../utils/stream-processor');\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const usage = response.usage as any;\n\n return {\n content: StreamProcessor.extractTextContent(msg?.content),\n reasoning: reasoningContent\n ? StreamProcessor.extractTextContent(reasoningContent)\n : null,\n model: (response.model as string) ?? model,\n usage: {\n promptTokens: usage?.prompt_tokens ?? usage?.promptTokens ?? 0,\n completionTokens:\n usage?.completion_tokens ?? usage?.completionTokens ?? 0,\n totalTokens: usage?.total_tokens ?? usage?.totalTokens ?? 0,\n },\n finishReason: choice.finish_reason ?? choice.finishReason ?? null,\n };\n }\n\n /**\n * 从 delta 中提取 StreamChunk\n * 默认实现:支持 reasoning_content、reasoning、thoughts 和 content 字段\n */\n extractStreamChunk(delta: Record<string, unknown>): StreamChunk | null {\n // 延迟导入以避免循环依赖\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { StreamProcessor } = require('../utils/stream-processor');\n\n // 思考内容(支持多种字段名)\n const reasoningContent =\n delta.reasoning_content ?? delta.reasoning ?? delta.thoughts;\n if (reasoningContent) {\n return {\n type: 'reasoning',\n text: StreamProcessor.extractTextContent(reasoningContent),\n };\n }\n\n // 回答内容\n if (delta.content) {\n return {\n type: 'content',\n text: StreamProcessor.extractTextContent(delta.content),\n };\n }\n\n return null;\n }\n\n /**\n * 获取 API 端点 URL\n * 默认实现:返回 /chat/completions 端点\n */\n getEndpointUrl(baseUrl: string): string {\n return `${baseUrl}/chat/completions`;\n }\n}\n","/**\n * OpenRouter 适配器实现\n * 将 OpenRouter API 适配为统一接口\n *\n * OpenRouter 特点:\n * - 支持多种模型(Claude、GPT、Gemini 等)\n * - 使用 reasoning 参数控制思考模式\n * - 支持 effort 和 max_tokens 参数\n */\n\nimport { BaseAdapter, type ProviderType } from './types';\nimport type { ReasoningConfig, ChatOptions } from '../providers/__types__';\nimport { EFFORT_TOKEN_MAP } from '../providers/__types__';\nimport { RequestBuilder } from '../utils/request-builder';\n\n/**\n * OpenRouter 默认基础 URL\n */\nconst DEFAULT_BASE_URL = 'https://openrouter.ai/api/v1';\n\n/**\n * OpenRouter 适配器\n * 实现 ProviderAdapter 接口,处理 OpenRouter 特定的 API 格式\n */\nexport class OpenRouterAdapter extends BaseAdapter {\n readonly name: ProviderType = 'openrouter';\n readonly defaultBaseUrl = DEFAULT_BASE_URL;\n\n /**\n * 构建聊天请求体\n * OpenRouter 使用 OpenAI 兼容格式,但有特殊的 reasoning 参数\n */\n buildChatRequest(\n options: ChatOptions,\n stream: boolean = false\n ): Record<string, unknown> {\n const {\n model,\n messages,\n temperature = 0.7,\n maxTokens,\n reasoning,\n } = options;\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream,\n };\n\n if (maxTokens !== undefined) {\n body.max_tokens = maxTokens;\n }\n\n // OpenRouter 使用 reasoning 参数(不是合并到 body 中)\n const reasoningParam = this.buildReasoningParams(reasoning);\n if (reasoningParam && Object.keys(reasoningParam).length > 0) {\n body.reasoning = reasoningParam;\n }\n\n return body;\n }\n\n /**\n * 构建 OpenRouter 格式的 reasoning 参数\n *\n * OpenRouter reasoning 参数格式:\n * {\n * effort: 'low' | 'medium' | 'high',\n * max_tokens: number,\n * exclude: boolean\n * }\n */\n buildReasoningParams(config?: ReasoningConfig): Record<string, unknown> {\n return RequestBuilder.buildOpenRouterReasoning(config) ?? {};\n }\n\n /**\n * 获取 API 端点 URL\n * OpenRouter 使用标准的 /chat/completions 端点\n */\n getEndpointUrl(baseUrl: string): string {\n return `${baseUrl}/chat/completions`;\n }\n}\n","/**\n * Gemini 适配器实现\n * 将 Google Gemini API 适配为统一接口\n *\n * Gemini 特点:\n * - 使用 OpenAI 兼容格式\n * - Gemini 2.5+ 模型支持 reasoning_effort 参数\n * - 思考内容通过 reasoning_content 或 thoughts 字段返回\n */\n\nimport { BaseAdapter, type ProviderType } from './types';\nimport type {\n ReasoningConfig,\n ChatOptions,\n StreamChunk,\n} from '../providers/__types__';\nimport { RequestBuilder } from '../utils/request-builder';\n\n/**\n * Gemini 默认基础 URL\n */\nconst DEFAULT_BASE_URL =\n 'https://generativelanguage.googleapis.com/v1beta/openai';\n\n/**\n * Gemini 适配器\n * 实现 ProviderAdapter 接口,处理 Gemini 特定的 API 格式\n */\nexport class GeminiAdapter extends BaseAdapter {\n readonly name: ProviderType = 'gemini';\n readonly defaultBaseUrl = DEFAULT_BASE_URL;\n\n /**\n * 构建聊天请求体\n * Gemini 使用 OpenAI 兼容格式,reasoning_effort 直接放在请求体中\n */\n buildChatRequest(\n options: ChatOptions,\n stream: boolean = false\n ): Record<string, unknown> {\n const {\n model,\n messages,\n temperature = 0.7,\n maxTokens,\n reasoning,\n } = options;\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream,\n };\n\n if (maxTokens !== undefined) {\n body.max_tokens = maxTokens;\n }\n\n // Gemini 的 reasoning_effort 直接放在请求体中\n const reasoningParams = this.buildReasoningParams(reasoning);\n Object.assign(body, reasoningParams);\n\n return body;\n }\n\n /**\n * 构建 Gemini 格式的 reasoning 参数\n *\n * Gemini 2.5+ 模型使用 reasoning_effort 参数:\n * - 'low': 快速思考\n * - 'medium': 平衡模式\n * - 'high': 深度思考\n */\n buildReasoningParams(config?: ReasoningConfig): Record<string, unknown> {\n return RequestBuilder.buildGeminiReasoning(config);\n }\n\n /**\n * 从 delta 中提取 StreamChunk\n * Gemini 可能使用 reasoning_content 或 thoughts 字段\n */\n extractStreamChunk(delta: Record<string, unknown>): StreamChunk | null {\n // 延迟导入以避免循环依赖\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { StreamProcessor } = require('../utils/stream-processor');\n\n // 思考内容(Gemini 可能用 reasoning_content 或 thoughts)\n const reasoningContent = delta.reasoning_content ?? delta.thoughts;\n if (reasoningContent) {\n return {\n type: 'reasoning',\n text: StreamProcessor.extractTextContent(reasoningContent),\n };\n }\n\n // 回答内容\n if (delta.content) {\n return {\n type: 'content',\n text: StreamProcessor.extractTextContent(delta.content),\n };\n }\n\n return null;\n }\n\n /**\n * 获取 API 端点 URL\n */\n getEndpointUrl(baseUrl: string): string {\n return `${baseUrl}/chat/completions`;\n }\n}\n","/**\n * Groq 适配器实现\n * 将 Groq API 适配为统一接口\n *\n * Groq 特点:\n * - 使用 OpenAI 兼容格式\n * - 使用 reasoning_format 参数控制推理输出\n * - 不能同时使用 include_reasoning 和 reasoning_format\n * - 使用 max_completion_tokens 而不是 max_tokens\n */\n\nimport { BaseAdapter, type ProviderType } from './types';\nimport type {\n ReasoningConfig,\n ChatOptions,\n StreamChunk,\n} from '../providers/__types__';\nimport { RequestBuilder } from '../utils/request-builder';\n\n/**\n * Groq 默认基础 URL\n */\nconst DEFAULT_BASE_URL = 'https://api.groq.com/openai/v1';\n\n/**\n * Groq 适配器\n * 实现 ProviderAdapter 接口,处理 Groq 特定的 API 格式\n */\nexport class GroqAdapter extends BaseAdapter {\n readonly name: ProviderType = 'groq';\n readonly defaultBaseUrl = DEFAULT_BASE_URL;\n\n /**\n * 构建聊天请求体\n * Groq 使用 OpenAI 兼容格式,但有一些特殊参数\n */\n buildChatRequest(\n options: ChatOptions,\n stream: boolean = false\n ): Record<string, unknown> {\n const { model, messages, temperature = 1, maxTokens, reasoning } = options;\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream,\n top_p: 1,\n };\n\n // Groq 使用 max_completion_tokens 而不是 max_tokens\n if (maxTokens !== undefined) {\n body.max_completion_tokens = maxTokens;\n }\n\n // 合并 reasoning 参数\n const reasoningParams = this.buildReasoningParams(reasoning);\n Object.assign(body, reasoningParams);\n\n return body;\n }\n\n /**\n * 构建 Groq 格式的 reasoning 参数\n *\n * Groq 使用 reasoning_format 参数:\n * - 'raw': 原始格式\n * - 'parsed': 解析格式(推荐)\n *\n * 注意:不能同时使用 include_reasoning 和 reasoning_format\n */\n buildReasoningParams(config?: ReasoningConfig): Record<string, unknown> {\n return RequestBuilder.buildGroqReasoning(config);\n }\n\n /**\n * 从 delta 中提取 StreamChunk\n * Groq 使用 reasoning_content 或 reasoning 字段\n */\n extractStreamChunk(delta: Record<string, unknown>): StreamChunk | null {\n // 延迟导入以避免循环依赖\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { StreamProcessor } = require('../utils/stream-processor');\n\n // 思考内容\n const reasoningContent = delta.reasoning_content ?? delta.reasoning;\n if (reasoningContent) {\n return {\n type: 'reasoning',\n text: StreamProcessor.extractTextContent(reasoningContent),\n };\n }\n\n // 回答内容\n if (delta.content) {\n return {\n type: 'content',\n text: StreamProcessor.extractTextContent(delta.content),\n };\n }\n\n return null;\n }\n\n /**\n * 获取 API 端点 URL\n */\n getEndpointUrl(baseUrl: string): string {\n return `${baseUrl}/chat/completions`;\n }\n}\n","/**\n * HuggingFace 适配器实现\n * 将 HuggingFace Router API 适配为统一接口\n *\n * HuggingFace 特点:\n * - 使用 OpenAI 兼容格式\n * - 是模型聚合平台,thinking 支持取决于具体模型\n * - 使用 reasoning_effort 参数(如果模型支持)\n */\n\nimport { BaseAdapter, type ProviderType } from './types';\nimport type {\n ReasoningConfig,\n ChatOptions,\n StreamChunk,\n} from '../providers/__types__';\n\n/**\n * HuggingFace 默认基础 URL\n */\nconst DEFAULT_BASE_URL = 'https://router.huggingface.co/v1';\n\n/**\n * HuggingFace 适配器\n * 实现 ProviderAdapter 接口,处理 HuggingFace 特定的 API 格式\n */\nexport class HuggingFaceAdapter extends BaseAdapter {\n readonly name: ProviderType = 'huggingface';\n readonly defaultBaseUrl = DEFAULT_BASE_URL;\n\n /**\n * 构建聊天请求体\n * HuggingFace 使用标准 OpenAI 兼容格式\n */\n buildChatRequest(\n options: ChatOptions,\n stream: boolean = false\n ): Record<string, unknown> {\n const {\n model,\n messages,\n temperature = 0.7,\n maxTokens,\n reasoning,\n } = options;\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream,\n };\n\n if (maxTokens !== undefined) {\n body.max_tokens = maxTokens;\n }\n\n // 合并 reasoning 参数\n const reasoningParams = this.buildReasoningParams(reasoning);\n Object.assign(body, reasoningParams);\n\n return body;\n }\n\n /**\n * 构建 HuggingFace 格式的 reasoning 参数\n * HuggingFace 使用 reasoning_effort 参数(取决于具体模型是否支持)\n */\n buildReasoningParams(config?: ReasoningConfig): Record<string, unknown> {\n if (!config || !config.effort || config.effort === 'off') {\n return {};\n }\n\n return {\n reasoning_effort: config.effort,\n };\n }\n\n /**\n * 从 delta 中提取 StreamChunk\n */\n extractStreamChunk(delta: Record<string, unknown>): StreamChunk | null {\n // 延迟导入以避免循环依赖\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { StreamProcessor } = require('../utils/stream-processor');\n\n // 思考内容\n if (delta.reasoning_content) {\n return {\n type: 'reasoning',\n text: StreamProcessor.extractTextContent(delta.reasoning_content),\n };\n }\n\n // 回答内容\n if (delta.content) {\n return {\n type: 'content',\n text: StreamProcessor.extractTextContent(delta.content),\n };\n }\n\n return null;\n }\n\n /**\n * 获取 API 端点 URL\n */\n getEndpointUrl(baseUrl: string): string {\n return `${baseUrl}/chat/completions`;\n }\n}\n","/**\n * ModelScope 适配器实现\n * 将 ModelScope API 适配为统一接口\n *\n * ModelScope 特点:\n * - 使用 OpenAI 兼容格式\n * - 使用 enable_thinking 参数控制思考模式\n * - 支持 DeepSeek 等模型\n */\n\nimport { BaseAdapter, type ProviderType } from './types';\nimport type {\n ReasoningConfig,\n ChatOptions,\n StreamChunk,\n} from '../providers/__types__';\n\n/**\n * ModelScope 默认基础 URL\n */\nconst DEFAULT_BASE_URL = 'https://api-inference.modelscope.cn/v1';\n\n/**\n * ModelScope 适配器\n * 实现 ProviderAdapter 接口,处理 ModelScope 特定的 API 格式\n */\nexport class ModelScopeAdapter extends BaseAdapter {\n readonly name: ProviderType = 'modelscope';\n readonly defaultBaseUrl = DEFAULT_BASE_URL;\n\n /**\n * 构建聊天请求体\n * ModelScope 使用 OpenAI 兼容格式\n */\n buildChatRequest(\n options: ChatOptions,\n stream: boolean = false\n ): Record<string, unknown> {\n const {\n model,\n messages,\n temperature = 0.7,\n maxTokens,\n reasoning,\n } = options;\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream,\n };\n\n if (maxTokens !== undefined) {\n body.max_tokens = maxTokens;\n }\n\n // 合并 reasoning 参数\n const reasoningParams = this.buildReasoningParams(reasoning);\n Object.assign(body, reasoningParams);\n\n return body;\n }\n\n /**\n * 构建 ModelScope 格式的 reasoning 参数\n * ModelScope 使用 enable_thinking 参数控制思考模式\n */\n buildReasoningParams(config?: ReasoningConfig): Record<string, unknown> {\n // 只在用户明确设置时才添加该参数\n if (!config || !config.effort) {\n return {};\n }\n\n if (config.effort === 'off') {\n return { enable_thinking: false };\n }\n\n return { enable_thinking: true };\n }\n\n /**\n * 从 delta 中提取 StreamChunk\n */\n extractStreamChunk(delta: Record<string, unknown>): StreamChunk | null {\n // 延迟导入以避免循环依赖\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { StreamProcessor } = require('../utils/stream-processor');\n\n // 思考内容\n if (delta.reasoning_content) {\n return {\n type: 'reasoning',\n text: StreamProcessor.extractTextContent(delta.reasoning_content),\n };\n }\n\n // 回答内容\n if (delta.content) {\n return {\n type: 'content',\n text: StreamProcessor.extractTextContent(delta.content),\n };\n }\n\n return null;\n }\n\n /**\n * 获取 API 端点 URL\n */\n getEndpointUrl(baseUrl: string): string {\n return `${baseUrl}/chat/completions`;\n }\n}\n","/**\n * DeepSeek 适配器实现\n * 将 DeepSeek API 适配为统一接口\n *\n * DeepSeek 特点:\n * - 使用 OpenAI 兼容格式\n * - 使用 thinking 参数启用思考模式\n * - deepseek-chat: 通用对话模型(可通过 thinking 参数启用思考)\n * - deepseek-reasoner: 推理模型(自动启用思考)\n */\n\nimport { BaseAdapter, type ProviderType } from './types';\nimport type {\n ReasoningConfig,\n ChatOptions,\n StreamChunk,\n} from '../providers/__types__';\nimport { RequestBuilder } from '../utils/request-builder';\n\n/**\n * DeepSeek 默认基础 URL\n */\nconst DEFAULT_BASE_URL = 'https://api.deepseek.com';\n\n/**\n * DeepSeek 适配器\n * 实现 ProviderAdapter 接口,处理 DeepSeek 特定的 API 格式\n */\nexport class DeepSeekAdapter extends BaseAdapter {\n readonly name: ProviderType = 'deepseek';\n readonly defaultBaseUrl = DEFAULT_BASE_URL;\n\n /**\n * 构建聊天请求体\n * DeepSeek 使用 OpenAI 兼容格式\n */\n buildChatRequest(\n options: ChatOptions,\n stream: boolean = false\n ): Record<string, unknown> {\n const {\n model,\n messages,\n temperature = 0.7,\n maxTokens,\n reasoning,\n } = options;\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream,\n };\n\n if (maxTokens !== undefined) {\n body.max_tokens = maxTokens;\n }\n\n // 合并 reasoning 参数\n const reasoningParams = this.buildReasoningParams(reasoning);\n Object.assign(body, reasoningParams);\n\n return body;\n }\n\n /**\n * 构建 DeepSeek 格式的 reasoning 参数\n * DeepSeek 使用 thinking 参数启用思考模式\n */\n buildReasoningParams(config?: ReasoningConfig): Record<string, unknown> {\n return RequestBuilder.buildDeepSeekReasoning(config);\n }\n\n /**\n * 从 delta 中提取 StreamChunk\n * DeepSeek R1 使用 reasoning_content 返回思考过程\n */\n extractStreamChunk(delta: Record<string, unknown>): StreamChunk | null {\n // 延迟导入以避免循环依赖\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { StreamProcessor } = require('../utils/stream-processor');\n\n // DeepSeek R1 推理模型的思考内容\n if (delta.reasoning_content) {\n return {\n type: 'reasoning',\n text: StreamProcessor.extractTextContent(delta.reasoning_content),\n };\n }\n\n // 回答内容\n if (delta.content) {\n return {\n type: 'content',\n text: StreamProcessor.extractTextContent(delta.content),\n };\n }\n\n return null;\n }\n\n /**\n * 获取 API 端点 URL\n */\n getEndpointUrl(baseUrl: string): string {\n return `${baseUrl}/chat/completions`;\n }\n}\n","/**\n * Poe 适配器实现\n * 将 Poe API 适配为统一接口\n *\n * Poe 特点:\n * - 使用 OpenAI 兼容格式\n * - 单一 API Key 访问数百个模型\n * - 通过 extra_body 传递 reasoning_effort, thinking_budget 等参数\n * - 支持 <think>...</think> 标签和 *Thinking...*\\n> ... 格式的思考内容\n */\n\nimport { BaseAdapter, type ProviderType } from './types';\nimport type {\n ReasoningConfig,\n ChatOptions,\n ChatResult,\n StreamChunk,\n} from '../providers/__types__';\nimport { EFFORT_TOKEN_MAP } from '../providers/__types__';\n\n/**\n * Poe 默认基础 URL\n */\nconst DEFAULT_BASE_URL = 'https://api.poe.com/v1';\n\n/**\n * 从内容中提取思考内容\n * 支持多种格式:\n * 1. <think>...</think> 标签\n * 2. *Thinking...*\\n> ... 格式(DeepSeek 在 Poe 上的格式)\n */\nfunction extractThinkingFromContent(content: string): {\n thinking: string;\n content: string;\n} {\n // 格式1: <think>...</think> 标签\n const thinkMatch = content.match(/<think>([\\s\\S]*?)<\\/think>/);\n if (thinkMatch) {\n const thinking = thinkMatch[1].trim();\n const cleanContent = content.replace(/<think>[\\s\\S]*?<\\/think>/, '').trim();\n return { thinking, content: cleanContent };\n }\n\n // 格式2: *Thinking...*\\n> ... 格式\n const thinkingMatch = content.match(\n /^\\*Thinking\\.{0,3}\\*\\s*\\n((?:>.*(?:\\n|$))+)/\n );\n if (thinkingMatch) {\n const thinking = thinkingMatch[1]\n .split('\\n')\n .map(line => line.replace(/^>\\s?/, ''))\n .join('\\n')\n .trim();\n const cleanContent = content.replace(thinkingMatch[0], '').trim();\n return { thinking, content: cleanContent };\n }\n\n return { thinking: '', content };\n}\n\n/**\n * Poe 适配器\n * 实现 ProviderAdapter 接口,处理 Poe 特定的 API 格式\n */\nexport class PoeAdapter extends BaseAdapter {\n readonly name: ProviderType = 'poe';\n readonly defaultBaseUrl = DEFAULT_BASE_URL;\n\n /**\n * 构建聊天请求体\n * Poe 使用 OpenAI 兼容格式,通过 extra_body 传递自定义参数\n */\n buildChatRequest(\n options: ChatOptions,\n stream: boolean = false\n ): Record<string, unknown> {\n const {\n model,\n messages,\n temperature = 0.7,\n maxTokens,\n reasoning,\n } = options;\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream,\n };\n\n if (maxTokens !== undefined) {\n body.max_tokens = maxTokens;\n }\n\n // Poe 通过 extra_body 传递自定义参数\n const reasoningParams = this.buildReasoningParams(reasoning);\n Object.assign(body, reasoningParams);\n\n return body;\n }\n\n /**\n * 构建 Poe 格式的 reasoning 参数\n * Poe 通过 extra_body 传递 reasoning_effort 和 thinking_budget\n */\n buildReasoningParams(config?: ReasoningConfig): Record<string, unknown> {\n if (!config || config.effort === 'off') {\n return {};\n }\n\n const params: Record<string, unknown> = {};\n\n // Poe 通过 extra_body 传递 reasoning_effort\n if (config.effort) {\n params.reasoning_effort = config.effort;\n }\n\n // 设置 thinking_budget(budgetTokens 优先,否则使用 effort 映射)\n if (config.budgetTokens !== undefined) {\n params.thinking_budget = config.budgetTokens;\n } else if (config.effort && EFFORT_TOKEN_MAP[config.effort]) {\n params.thinking_budget = EFFORT_TOKEN_MAP[config.effort];\n }\n\n return params;\n }\n\n /**\n * 解析聊天响应\n * Poe 可能返回 reasoning_content,或者需要从 <think> 标签提取\n */\n parseChatResponse(\n response: Record<string, unknown>,\n model: string\n ): ChatResult {\n // 延迟导入以避免循环依赖\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { StreamProcessor } = require('../utils/stream-processor');\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const choices = response.choices as any[] | undefined;\n const choice = choices?.[0];\n\n if (!choice) {\n throw new Error('No response from model');\n }\n\n const msg = choice.message;\n let reasoningContent = msg?.reasoning_content ?? null;\n let contentText = StreamProcessor.extractTextContent(msg?.content);\n\n // 如果没有 reasoning_content,尝试从 <think> 标签提取\n if (!reasoningContent && contentText) {\n const extracted = extractThinkingFromContent(contentText);\n if (extracted.thinking) {\n reasoningContent = extracted.thinking;\n contentText = extracted.content;\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const usage = response.usage as any;\n\n return {\n content: contentText,\n reasoning: reasoningContent\n ? StreamProcessor.extractTextContent(reasoningContent)\n : null,\n model: (response.model as string) ?? model,\n usage: {\n promptTokens: usage?.prompt_tokens ?? usage?.promptTokens ?? 0,\n completionTokens:\n usage?.completion_tokens ?? usage?.completionTokens ?? 0,\n totalTokens: usage?.total_tokens ?? usage?.totalTokens ?? 0,\n },\n finishReason: choice.finish_reason ?? choice.finishReason ?? null,\n };\n }\n\n /**\n * 从 delta 中提取 StreamChunk\n * Poe 的流式响应处理比较复杂,需要处理多种思考格式\n */\n extractStreamChunk(delta: Record<string, unknown>): StreamChunk | null {\n // 延迟导入以避免循环依赖\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { StreamProcessor } = require('../utils/stream-processor');\n\n // 思考内容(如果底层模型支持 reasoning_content)\n if (delta.reasoning_content) {\n return {\n type: 'reasoning',\n text: StreamProcessor.extractTextContent(delta.reasoning_content),\n };\n }\n\n // 回答内容\n if (delta.content) {\n return {\n type: 'content',\n text: StreamProcessor.extractTextContent(delta.content),\n };\n }\n\n return null;\n }\n\n /**\n * 获取 API 端点 URL\n */\n getEndpointUrl(baseUrl: string): string {\n return `${baseUrl}/chat/completions`;\n }\n}\n","/**\n * AWS Nova 适配器实现\n * 将 Amazon Nova API 适配为统一接口\n *\n * Nova 特点:\n * - 使用 OpenAI 兼容格式\n * - Nova 2 Lite 支持 extended thinking (reasoningConfig)\n * - effort 映射为 maxReasoningEffort: low/medium/high\n * - temperature 范围是 0-1(不是 0-2)\n */\n\nimport { BaseAdapter, type ProviderType } from './types';\nimport type {\n ReasoningConfig,\n ChatOptions,\n StreamChunk,\n} from '../providers/__types__';\nimport { RequestBuilder } from '../utils/request-builder';\n\n/**\n * Nova 默认基础 URL\n */\nconst DEFAULT_BASE_URL = 'https://api.nova.amazon.com/v1';\n\n/**\n * Nova 适配器\n * 实现 ProviderAdapter 接口,处理 Nova 特定的 API 格式\n */\nexport class NovaAdapter extends BaseAdapter {\n readonly name: ProviderType = 'nova';\n readonly defaultBaseUrl = DEFAULT_BASE_URL;\n\n /**\n * 构建聊天请求体\n * Nova 使用 OpenAI 兼容格式\n */\n buildChatRequest(\n options: ChatOptions,\n stream: boolean = false\n ): Record<string, unknown> {\n const {\n model,\n messages,\n temperature = 0.7,\n maxTokens,\n reasoning,\n } = options;\n\n const body: Record<string, unknown> = {\n model,\n messages,\n temperature,\n stream,\n };\n\n if (maxTokens !== undefined) {\n body.max_tokens = maxTokens;\n }\n\n // 合并 reasoning 参数\n const reasoningParams = this.buildReasoningParams(reasoning);\n Object.assign(body, reasoningParams);\n\n return body;\n }\n\n /**\n * 构建 Nova 格式的 reasoning 参数\n * Nova 使用 reasoningConfig 控制 extended thinking\n */\n buildReasoningParams(config?: ReasoningConfig): Record<string, unknown> {\n return RequestBuilder.buildNovaReasoning(config);\n }\n\n /**\n * 从 delta 中提取 StreamChunk\n * Nova 返回 reasoning_content 作为思考过程\n */\n extractStreamChunk(delta: Record<string, unknown>): StreamChunk | null {\n // 延迟导入以避免循环依赖\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { StreamProcessor } = require('../utils/stream-processor');\n\n // 思考内容\n if (delta.reasoning_content) {\n return {\n type: 'reasoning',\n text: StreamProcessor.extractTextContent(delta.reasoning_content),\n };\n }\n\n // 回答内容\n if (delta.content) {\n return {\n type: 'content',\n text: StreamProcessor.extractTextContent(delta.content),\n };\n }\n\n return null;\n }\n\n /**\n * 获取 API 端点 URL\n */\n getEndpointUrl(baseUrl: string): string {\n return `${baseUrl}/chat/completions`;\n }\n}\n","/**\n * 适配器层导出文件\n * 导出所有 Provider 适配器和相关类型\n */\n\n// 类型导出\nexport type { ProviderType, AdapterConfig, ProviderAdapter } from './types';\n\n// 基础类导出\nexport { BaseAdapter } from './types';\n\n// 适配器导出\nexport { OpenRouterAdapter } from './openrouter-adapter';\nexport { GeminiAdapter } from './gemini-adapter';\nexport { GroqAdapter } from './groq-adapter';\nexport { HuggingFaceAdapter } from './huggingface-adapter';\nexport { ModelScopeAdapter } from './modelscope-adapter';\nexport { DeepSeekAdapter } from './deepseek-adapter';\nexport { PoeAdapter } from './poe-adapter';\nexport { NovaAdapter } from './nova-adapter';\n\n// 适配器映射表(便于注册表使用)\nimport { OpenRouterAdapter } from './openrouter-adapter';\nimport { GeminiAdapter } from './gemini-adapter';\nimport { GroqAdapter } from './groq-adapter';\nimport { HuggingFaceAdapter } from './huggingface-adapter';\nimport { ModelScopeAdapter } from './modelscope-adapter';\nimport { DeepSeekAdapter } from './deepseek-adapter';\nimport { PoeAdapter } from './poe-adapter';\nimport { NovaAdapter } from './nova-adapter';\nimport type { ProviderType, ProviderAdapter } from './types';\n\n/**\n * 创建所有内置适配器实例\n * 用于 ProviderRegistry 初始化\n */\nexport function createBuiltInAdapters(): Map<ProviderType, ProviderAdapter> {\n const adapters = new Map<ProviderType, ProviderAdapter>();\n\n adapters.set('openrouter', new OpenRouterAdapter());\n adapters.set('gemini', new GeminiAdapter());\n adapters.set('groq', new GroqAdapter());\n adapters.set('huggingface', new HuggingFaceAdapter());\n adapters.set('modelscope', new ModelScopeAdapter());\n adapters.set('deepseek', new DeepSeekAdapter());\n adapters.set('poe', new PoeAdapter());\n adapters.set('nova', new NovaAdapter());\n\n return adapters;\n}\n","/**\n * Provider 注册表\n * 管理所有已注册的 Provider 适配器\n *\n * 职责:\n * 1. 注册和管理 Provider 适配器\n * 2. 提供适配器的获取和查询功能\n * 3. 支持从配置文件加载 Provider\n * 4. 自动初始化内置 Provider\n */\n\nimport type { ProviderAdapter, ProviderType } from '../adapters/types';\nimport type { RegistryConfig } from '../config/types';\nimport { createBuiltInAdapters } from '../adapters';\n\n/**\n * 注册表错误\n * 当 Provider 未注册或注册失败时抛出\n */\nexport class RegistryError extends Error {\n constructor(\n message: string,\n public readonly provider?: ProviderType | string,\n public readonly code: string = 'REGISTRY_ERROR'\n ) {\n super(message);\n this.name = 'RegistryError';\n }\n}\n\n/**\n * Provider 注册表\n * 管理所有已注册的 Provider 适配器\n *\n * @example\n * ```typescript\n * // 获取适配器\n * const adapter = ProviderRegistry.getAdapter('openrouter');\n *\n * // 检查是否支持\n * if (ProviderRegistry.hasAdapter('gemini')) {\n * // ...\n * }\n *\n * // 列出所有支持的 Provider\n * const supported = ProviderRegistry.listSupported();\n *\n * // 注册自定义适配器\n * ProviderRegistry.register(myCustomAdapter);\n * ```\n */\nexport class ProviderRegistry {\n /** 适配器映射表 */\n private static adapters: Map<ProviderType | string, ProviderAdapter> =\n new Map();\n\n /** 是否已初始化内置适配器 */\n private static initialized: boolean = false;\n\n /**\n * 注册 Provider 适配器\n *\n * @param adapter - 要注册的适配器实例\n * @throws RegistryError 如果适配器无效\n *\n * @example\n * ```typescript\n * const myAdapter = new MyCustomAdapter();\n * ProviderRegistry.register(myAdapter);\n * ```\n */\n static register(adapter: ProviderAdapter): void {\n if (!adapter) {\n throw new RegistryError('适配器不能为空', undefined, 'INVALID_ADAPTER');\n }\n\n if (!adapter.name) {\n throw new RegistryError(\n '适配器必须有 name 属性',\n undefined,\n 'INVALID_ADAPTER'\n );\n }\n\n this.adapters.set(adapter.name, adapter);\n }\n\n /**\n * 获取 Provider 适配器\n *\n * @param type - Provider 类型\n * @returns 对应的适配器实例\n * @throws RegistryError 如果 Provider 未注册\n *\n * @example\n * ```typescript\n * const adapter = ProviderRegistry.getAdapter('openrouter');\n * const client = adapter.createClient(config);\n * ```\n */\n static getAdapter(type: ProviderType | string): ProviderAdapter {\n // 确保内置适配器已初始化\n this.initializeBuiltIn();\n\n const adapter = this.adapters.get(type);\n\n if (!adapter) {\n const supported = this.listSupported();\n throw new RegistryError(\n `Provider \"${type}\" 未注册。可用的 Provider: ${supported.join(', ')}`,\n type,\n 'PROVIDER_NOT_FOUND'\n );\n }\n\n return adapter;\n }\n\n /**\n * 检查 Provider 是否已注册\n *\n * @param type - Provider 类型\n * @returns 是否已注册\n *\n * @example\n * ```typescript\n * if (ProviderRegistry.hasAdapter('gemini')) {\n * console.log('Gemini 已注册');\n * }\n * ```\n */\n static hasAdapter(type: ProviderType | string): boolean {\n // 确保内置适配器已初始化\n this.initializeBuiltIn();\n\n return this.adapters.has(type);\n }\n\n /**\n * 获取所有已注册的 Provider 类型\n *\n * @returns Provider 类型数组\n *\n * @example\n * ```typescript\n * const providers = ProviderRegistry.listSupported();\n * console.log('支持的 Provider:', providers);\n * ```\n */\n static listSupported(): (ProviderType | string)[] {\n // 确保内置适配器已初始化\n this.initializeBuiltIn();\n\n return Array.from(this.adapters.keys());\n }\n\n /**\n * 从配置文件加载并注册 Provider\n *\n * @param config - 注册表配置\n * @throws RegistryError 如果配置无效或加载失败\n *\n * @example\n * ```typescript\n * const config: RegistryConfig = {\n * providers: {\n * 'custom-provider': {\n * adapter: './my-adapter',\n * config: {\n * apiKey: 'xxx',\n * baseUrl: 'https://api.example.com'\n * }\n * }\n * }\n * };\n * ProviderRegistry.loadFromConfig(config);\n * ```\n */\n static loadFromConfig(config: RegistryConfig): void {\n if (!config || !config.providers) {\n throw new RegistryError(\n '配置无效:缺少 providers 字段',\n undefined,\n 'INVALID_CONFIG'\n );\n }\n\n // 确保内置适配器已初始化\n this.initializeBuiltIn();\n\n for (const [providerName, providerConfig] of Object.entries(\n config.providers\n )) {\n // 如果指定了自定义适配器路径,尝试加载\n if (providerConfig.adapter) {\n try {\n // 动态加载自定义适配器\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const CustomAdapter = require(providerConfig.adapter);\n const AdapterClass = CustomAdapter.default || CustomAdapter;\n const adapter = new AdapterClass();\n\n // 验证适配器实现了必要的接口\n if (\n typeof adapter.name !== 'string' ||\n typeof adapter.createClient !== 'function'\n ) {\n throw new RegistryError(\n `自定义适配器 \"${providerConfig.adapter}\" 未正确实现 ProviderAdapter 接口`,\n providerName,\n 'INVALID_ADAPTER'\n );\n }\n\n this.adapters.set(providerName, adapter);\n } catch (error) {\n if (error instanceof RegistryError) {\n throw error;\n }\n throw new RegistryError(\n `加载自定义适配器失败: ${providerConfig.adapter}`,\n providerName,\n 'ADAPTER_LOAD_ERROR'\n );\n }\n }\n // 如果没有指定自定义适配器,检查是否是内置 Provider\n else if (!this.adapters.has(providerName)) {\n throw new RegistryError(\n `Provider \"${providerName}\" 未注册且未指定自定义适配器`,\n providerName,\n 'PROVIDER_NOT_FOUND'\n );\n }\n }\n }\n\n /**\n * 初始化内置 Provider\n * 在首次使用时自动调用\n *\n * @example\n * ```typescript\n * // 通常不需要手动调用,会在首次使用时自动初始化\n * ProviderRegistry.initializeBuiltIn();\n * ```\n */\n static initializeBuiltIn(): void {\n if (this.initialized) {\n return;\n }\n\n // 加载所有内置适配器\n const builtInAdapters = createBuiltInAdapters();\n\n for (const [type, adapter] of builtInAdapters) {\n // 只有在未注册时才添加,允许用户覆盖内置适配器\n if (!this.adapters.has(type)) {\n this.adapters.set(type, adapter);\n }\n }\n\n this.initialized = true;\n }\n\n /**\n * 重置注册表(主要用于测试)\n * 清除所有已注册的适配器并重置初始化状态\n */\n static reset(): void {\n this.adapters.clear();\n this.initialized = false;\n }\n\n /**\n * 获取适配器数量(主要用于测试)\n *\n * @returns 已注册的适配器数量\n */\n static get size(): number {\n this.initializeBuiltIn();\n return this.adapters.size;\n }\n}\n","/**\n * 配置管理类型定义\n * 定义统一的 Provider 配置格式和注册表配置\n */\n\n/**\n * Provider 类型\n */\nexport type ProviderType =\n | 'openrouter'\n | 'gemini'\n | 'groq'\n | 'huggingface'\n | 'modelscope'\n | 'deepseek'\n | 'poe'\n | 'nova';\n\n/**\n * 统一的 Provider 配置格式\n * 用于配置各种 AI Provider 的连接和行为\n */\nexport interface UnifiedProviderConfig {\n /** Provider 类型 */\n provider: ProviderType;\n /** 自定义适配器路径(可选) */\n adapter?: string;\n /** 凭证信息 */\n credentials: {\n /** API 密钥 */\n apiKey: string;\n /** 基础 URL(可选) */\n baseUrl?: string;\n };\n /** 选项配置(可选) */\n options?: {\n /** 超时时间(毫秒) */\n timeout?: number;\n /** 重试次数 */\n retries?: number;\n /** 额外请求头 */\n headers?: Record<string, string>;\n };\n /** 功能开关(可选) */\n features?: {\n /** 是否支持流式输出 */\n streaming?: boolean;\n /** 是否支持推理 */\n reasoning?: boolean;\n };\n}\n\n/**\n * 注册表配置(用于配置文件)\n * 支持从 JSON 配置文件加载多个 Provider\n */\nexport interface RegistryConfig {\n /** Provider 配置映射 */\n providers: {\n [key: string]: {\n /** 自定义适配器路径(可选) */\n adapter?: string;\n /** Provider 配置 */\n config: {\n /** API 密钥 */\n apiKey: string;\n /** 基础 URL(可选) */\n baseUrl?: string;\n };\n };\n };\n}\n\n/**\n * Provider 能力描述\n * 描述 Provider 支持的功能特性\n */\nexport interface ProviderCapabilities {\n /** 是否支持流式输出 */\n streaming: boolean;\n /** 是否支持推理/思考 */\n reasoning: boolean;\n /** 是否支持函数调用 */\n functionCalling: boolean;\n /** 是否支持视觉/图像 */\n vision: boolean;\n}\n\n/**\n * 旧格式的 Provider 配置\n * 用于向后兼容\n */\nexport interface LegacyProviderConfig {\n /** Provider 类型 */\n provider: ProviderType;\n /** API 密钥 */\n apiKey: string;\n /** 基础 URL(可选) */\n baseUrl?: string;\n}\n\n/**\n * 配置默认值\n */\nexport const CONFIG_DEFAULTS = {\n /** 默认超时时间(毫秒) */\n timeout: 30000,\n /** 默认重试次数 */\n retries: 3,\n /** 默认功能开关 */\n features: {\n streaming: true,\n reasoning: false,\n },\n} as const;\n\n/**\n * 有效的 Provider 类型列表\n */\nexport const VALID_PROVIDERS: ProviderType[] = [\n 'openrouter',\n 'gemini',\n 'groq',\n 'huggingface',\n 'modelscope',\n 'deepseek',\n 'poe',\n 'nova',\n];\n","/**\n * 配置验证器 - 验证 Provider 配置的有效性\n */\n\n/**\n * 验证错误\n */\nexport interface ValidationError {\n /** 错误字段路径 */\n field: string;\n /** 错误消息 */\n message: string;\n /** 错误代码 */\n code: string;\n}\n\n/**\n * 验证结果\n */\nexport interface ValidationResult {\n /** 是否验证通过 */\n valid: boolean;\n /** 错误列表 */\n errors: ValidationError[];\n}\n\n/**\n * Provider 类型\n */\nexport type ProviderType =\n | 'openrouter'\n | 'gemini'\n | 'groq'\n | 'huggingface'\n | 'modelscope'\n | 'deepseek'\n | 'poe'\n | 'nova';\n\n/**\n * 统一的 Provider 配置格式\n */\nexport interface UnifiedProviderConfig {\n /** Provider 类型 */\n provider: ProviderType;\n /** 自定义适配器路径(可选) */\n adapter?: string;\n /** 凭证信息 */\n credentials: {\n /** API 密钥 */\n apiKey: string;\n /** 基础 URL(可选) */\n baseUrl?: string;\n };\n /** 选项配置(可选) */\n options?: {\n /** 超时时间(毫秒) */\n timeout?: number;\n /** 重试次数 */\n retries?: number;\n /** 额外请求头 */\n headers?: Record<string, string>;\n };\n /** 功能开关(可选) */\n features?: {\n /** 是否支持流式输出 */\n streaming?: boolean;\n /** 是否支持推理 */\n reasoning?: boolean;\n };\n}\n\n/**\n * 有效的 Provider 类型列表\n */\nconst VALID_PROVIDERS: ProviderType[] = [\n 'openrouter',\n 'gemini',\n 'groq',\n 'huggingface',\n 'modelscope',\n 'deepseek',\n 'poe',\n 'nova',\n];\n\n/**\n * 配置验证器类\n * 提供 Provider 配置验证功能\n */\nexport class ConfigValidator {\n /**\n * 验证 Provider 配置\n *\n * @param config - 要验证的配置对象\n * @returns 验证结果\n *\n * @example\n * ```ts\n * const result = ConfigValidator.validate({\n * provider: 'openrouter',\n * credentials: { apiKey: 'sk-xxx' }\n * });\n *\n * if (!result.valid) {\n * console.error(result.errors);\n * }\n * ```\n */\n static validate(config: unknown): ValidationResult {\n const errors: ValidationError[] = [];\n\n // 检查配置是否为对象\n if (!config || typeof config !== 'object') {\n return {\n valid: false,\n errors: [\n {\n field: '',\n message: '配置必须是一个对象',\n code: 'INVALID_CONFIG_TYPE',\n },\n ],\n };\n }\n\n const cfg = config as Record<string, unknown>;\n\n // 检查 provider 字段\n if (!cfg.provider) {\n errors.push({\n field: 'provider',\n message: 'provider 字段是必填的',\n code: 'MISSING_PROVIDER',\n });\n } else if (typeof cfg.provider !== 'string') {\n errors.push({\n field: 'provider',\n message: 'provider 必须是字符串',\n code: 'INVALID_PROVIDER_TYPE',\n });\n } else if (!VALID_PROVIDERS.includes(cfg.provider as ProviderType)) {\n errors.push({\n field: 'provider',\n message: `无效的 provider: ${cfg.provider},有效值为: ${VALID_PROVIDERS.join(', ')}`,\n code: 'INVALID_PROVIDER',\n });\n }\n\n // 检查 credentials 字段\n if (!cfg.credentials) {\n errors.push({\n field: 'credentials',\n message: 'credentials 字段是必填的',\n code: 'MISSING_CREDENTIALS',\n });\n } else if (typeof cfg.credentials !== 'object') {\n errors.push({\n field: 'credentials',\n message: 'credentials 必须是一个对象',\n code: 'INVALID_CREDENTIALS_TYPE',\n });\n } else {\n const creds = cfg.credentials as Record<string, unknown>;\n\n // 检查 apiKey\n if (!creds.apiKey) {\n errors.push({\n field: 'credentials.apiKey',\n message: 'apiKey 字段是必填的',\n code: 'MISSING_API_KEY',\n });\n } else if (typeof creds.apiKey !== 'string') {\n errors.push({\n field: 'credentials.apiKey',\n message: 'apiKey 必须是字符串',\n code: 'INVALID_API_KEY_TYPE',\n });\n } else if (creds.apiKey.trim() === '') {\n errors.push({\n field: 'credentials.apiKey',\n message: 'apiKey 不能为空',\n code: 'EMPTY_API_KEY',\n });\n }\n\n // 检查 baseUrl(如果提供)\n if (creds.baseUrl !== undefined) {\n const urlResult = ConfigValidator.validateUrl(creds.baseUrl as string);\n if (!urlResult.valid) {\n errors.push(\n ...urlResult.errors.map(e => ({\n ...e,\n field: 'credentials.baseUrl',\n }))\n );\n }\n }\n }\n\n // 检查 options(如果提供)\n if (cfg.options !== undefined) {\n if (typeof cfg.options !== 'object') {\n errors.push({\n field: 'options',\n message: 'options 必须是一个对象',\n code: 'INVALID_OPTIONS_TYPE',\n });\n } else {\n const opts = cfg.options as Record<string, unknown>;\n\n // 检查 timeout\n if (opts.timeout !== undefined) {\n if (typeof opts.timeout !== 'number' || opts.timeout <= 0) {\n errors.push({\n field: 'options.timeout',\n message: 'timeout 必须是正数',\n code: 'INVALID_TIMEOUT',\n });\n }\n }\n\n // 检查 retries\n if (opts.retries !== undefined) {\n if (\n typeof opts.retries !== 'number' ||\n opts.retries < 0 ||\n !Number.isInteger(opts.retries)\n ) {\n errors.push({\n field: 'options.retries',\n message: 'retries 必须是非负整数',\n code: 'INVALID_RETRIES',\n });\n }\n }\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n }\n\n /**\n * 验证 API Key 格式\n * 不同 Provider 可能有不同的 API Key 格式要求\n *\n * @param apiKey - API 密钥\n * @param provider - Provider 类型\n * @returns 验证结果\n */\n static validateApiKey(\n apiKey: string,\n provider: ProviderType\n ): ValidationResult {\n const errors: ValidationError[] = [];\n\n if (!apiKey || typeof apiKey !== 'string') {\n errors.push({\n field: 'apiKey',\n message: 'apiKey 必须是非空字符串',\n code: 'INVALID_API_KEY',\n });\n return { valid: false, errors };\n }\n\n const trimmed = apiKey.trim();\n if (trimmed === '') {\n errors.push({\n field: 'apiKey',\n message: 'apiKey 不能为空',\n code: 'EMPTY_API_KEY',\n });\n return { valid: false, errors };\n }\n\n // 根据 Provider 类型进行特定格式验证\n switch (provider) {\n case 'openrouter':\n // OpenRouter API Key 通常以 sk- 开头\n if (!trimmed.startsWith('sk-')) {\n errors.push({\n field: 'apiKey',\n message: 'OpenRouter API Key 应以 sk- 开头',\n code: 'INVALID_API_KEY_FORMAT',\n });\n }\n break;\n case 'gemini':\n // Gemini API Key 通常以 AI 开头\n if (!trimmed.startsWith('AI')) {\n errors.push({\n field: 'apiKey',\n message: 'Gemini API Key 格式可能不正确',\n code: 'INVALID_API_KEY_FORMAT',\n });\n }\n break;\n // 其他 Provider 暂不做特定格式验证\n default:\n break;\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n }\n\n /**\n * 验证 URL 格式\n *\n * @param url - 要验证的 URL\n * @returns 验证结果\n */\n static validateUrl(url: unknown): ValidationResult {\n const errors: ValidationError[] = [];\n\n if (typeof url !== 'string') {\n errors.push({\n field: 'url',\n message: 'URL 必须是字符串',\n code: 'INVALID_URL_TYPE',\n });\n return { valid: false, errors };\n }\n\n const trimmed = url.trim();\n if (trimmed === '') {\n errors.push({\n field: 'url',\n message: 'URL 不能为空',\n code: 'EMPTY_URL',\n });\n return { valid: false, errors };\n }\n\n // 验证 URL 格式\n try {\n const parsed = new URL(trimmed);\n // 只允许 http 和 https 协议\n if (!['http:', 'https:'].includes(parsed.protocol)) {\n errors.push({\n field: 'url',\n message: 'URL 必须使用 http 或 https 协议',\n code: 'INVALID_URL_PROTOCOL',\n });\n }\n } catch {\n errors.push({\n field: 'url',\n message: 'URL 格式无效',\n code: 'INVALID_URL_FORMAT',\n });\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n }\n}\n","/**\n * 配置管理器\n * 提供配置验证、默认值应用、环境变量替换等功能\n */\n\nimport {\n type UnifiedProviderConfig,\n type LegacyProviderConfig,\n type ProviderType,\n CONFIG_DEFAULTS,\n VALID_PROVIDERS,\n} from './types';\nimport {\n type ValidationResult,\n type ValidationError,\n ConfigValidator,\n} from '../utils/config-validator';\n\n/**\n * 配置管理器类\n * 统一管理 Provider 配置的验证、转换和处理\n */\nexport class ConfigManager {\n /**\n * 验证配置\n * 检查配置是否符合 UnifiedProviderConfig 格式要求\n *\n * @param config - 要验证的配置对象\n * @returns 验证结果\n *\n * @example\n * ```ts\n * const result = ConfigManager.validate({\n * provider: 'openrouter',\n * credentials: { apiKey: 'sk-xxx' }\n * });\n *\n * if (!result.valid) {\n * console.error(result.errors);\n * }\n * ```\n */\n static validate(config: unknown): ValidationResult {\n // 使用 ConfigValidator 进行基础验证\n return ConfigValidator.validate(config);\n }\n\n /**\n * 应用默认值\n * 为缺失的可选字段填充默认值\n *\n * @param config - 部分配置对象\n * @returns 填充默认值后的完整配置\n *\n * @example\n * ```ts\n * const fullConfig = ConfigManager.applyDefaults({\n * provider: 'openrouter',\n * credentials: { apiKey: 'sk-xxx' }\n * });\n * // fullConfig.options.timeout === 30000\n * // fullConfig.options.retries === 3\n * ```\n */\n static applyDefaults(\n config: Partial<UnifiedProviderConfig>\n ): UnifiedProviderConfig {\n // 确保必填字段存在\n if (!config.provider || !config.credentials?.apiKey) {\n throw new Error('配置缺少必填字段: provider 和 credentials.apiKey');\n }\n\n return {\n provider: config.provider,\n adapter: config.adapter,\n credentials: {\n apiKey: config.credentials.apiKey,\n baseUrl: config.credentials.baseUrl,\n },\n options: {\n timeout: config.options?.timeout ?? CONFIG_DEFAULTS.timeout,\n retries: config.options?.retries ?? CONFIG_DEFAULTS.retries,\n headers: config.options?.headers ?? {},\n },\n features: {\n streaming:\n config.features?.streaming ?? CONFIG_DEFAULTS.features.streaming,\n reasoning:\n config.features?.reasoning ?? CONFIG_DEFAULTS.features.reasoning,\n },\n };\n }\n\n /**\n * 合并环境变量\n * 将 ${ENV_VAR} 格式的占位符替换为实际环境变量值\n *\n * @param config - 包含环境变量占位符的配置\n * @returns 替换后的配置\n *\n * @example\n * ```ts\n * // 假设 process.env.OPENROUTER_API_KEY = 'sk-xxx'\n * const config = ConfigManager.mergeWithEnv({\n * provider: 'openrouter',\n * credentials: { apiKey: '${OPENROUTER_API_KEY}' }\n * });\n * // config.credentials.apiKey === 'sk-xxx'\n * ```\n */\n static mergeWithEnv(config: UnifiedProviderConfig): UnifiedProviderConfig {\n // 深拷贝配置以避免修改原对象\n const result = JSON.parse(JSON.stringify(config)) as UnifiedProviderConfig;\n\n // 递归替换字符串中的环境变量占位符\n const replaceEnvVars = (obj: Record<string, unknown>): void => {\n for (const key of Object.keys(obj)) {\n const value = obj[key];\n if (typeof value === 'string') {\n obj[key] = ConfigManager.replaceEnvPlaceholders(value);\n } else if (\n value &&\n typeof value === 'object' &&\n !Array.isArray(value)\n ) {\n replaceEnvVars(value as Record<string, unknown>);\n }\n }\n };\n\n replaceEnvVars(result as unknown as Record<string, unknown>);\n return result;\n }\n\n /**\n * 替换字符串中的环境变量占位符\n * 支持 ${ENV_VAR} 格式\n *\n * @param str - 包含占位符的字符串\n * @returns 替换后的字符串\n */\n private static replaceEnvPlaceholders(str: string): string {\n // 匹配 ${ENV_VAR} 格式的占位符\n const envVarPattern = /\\$\\{([^}]+)\\}/g;\n\n return str.replace(envVarPattern, (match, envVarName: string) => {\n const envValue = process.env[envVarName];\n // 如果环境变量存在,返回其值;否则保留原占位符\n return envValue !== undefined ? envValue : match;\n });\n }\n\n /**\n * 从旧格式配置转换为新格式\n * 保持向后兼容性\n *\n * @param config - 旧格式的 Provider 配置\n * @returns 新格式的统一配置\n *\n * @example\n * ```ts\n * const newConfig = ConfigManager.fromLegacyConfig({\n * provider: 'openrouter',\n * apiKey: 'sk-xxx',\n * baseUrl: 'https://api.example.com'\n * });\n * // newConfig.credentials.apiKey === 'sk-xxx'\n * // newConfig.credentials.baseUrl === 'https://api.example.com'\n * ```\n */\n static fromLegacyConfig(config: LegacyProviderConfig): UnifiedProviderConfig {\n // 验证旧格式配置的必填字段\n if (!config.provider) {\n throw new Error('旧格式配置缺少 provider 字段');\n }\n if (!config.apiKey) {\n throw new Error('旧格式配置缺少 apiKey 字段');\n }\n\n // 验证 provider 类型\n if (!VALID_PROVIDERS.includes(config.provider)) {\n throw new Error(\n `无效的 provider: ${config.provider},有效值为: ${VALID_PROVIDERS.join(', ')}`\n );\n }\n\n // 转换为新格式并应用默认值\n return ConfigManager.applyDefaults({\n provider: config.provider,\n credentials: {\n apiKey: config.apiKey,\n baseUrl: config.baseUrl,\n },\n });\n }\n\n /**\n * 检查配置是否为旧格式\n *\n * @param config - 要检查的配置对象\n * @returns 是否为旧格式\n */\n static isLegacyConfig(config: unknown): config is LegacyProviderConfig {\n if (!config || typeof config !== 'object') {\n return false;\n }\n\n const cfg = config as Record<string, unknown>;\n\n // 旧格式特征:有 apiKey 字段但没有 credentials 字段\n return (\n typeof cfg.provider === 'string' &&\n typeof cfg.apiKey === 'string' &&\n cfg.credentials === undefined\n );\n }\n\n /**\n * 智能转换配置\n * 自动检测配置格式并转换为统一格式\n *\n * @param config - 任意格式的配置\n * @returns 统一格式的配置\n */\n static normalize(\n config: LegacyProviderConfig | Partial<UnifiedProviderConfig>\n ): UnifiedProviderConfig {\n if (ConfigManager.isLegacyConfig(config)) {\n return ConfigManager.fromLegacyConfig(config);\n }\n\n return ConfigManager.applyDefaults(\n config as Partial<UnifiedProviderConfig>\n );\n }\n\n /**\n * 获取指定 Provider 的默认基础 URL\n *\n * @param provider - Provider 类型\n * @returns 默认基础 URL\n */\n static getDefaultBaseUrl(provider: ProviderType): string {\n const defaultUrls: Record<ProviderType, string> = {\n openrouter: 'https://openrouter.ai/api/v1',\n gemini: 'https://generativelanguage.googleapis.com/v1beta',\n groq: 'https://api.groq.com/openai/v1',\n huggingface: 'https://api-inference.huggingface.co',\n modelscope: 'https://dashscope.aliyuncs.com/compatible-mode/v1',\n deepseek: 'https://api.deepseek.com/v1',\n poe: 'https://api.poe.com/bot',\n nova: 'https://bedrock-runtime.us-east-1.amazonaws.com',\n };\n\n return defaultUrls[provider];\n }\n}\n","/**\n * 统一的 Provider 工厂\n * 让所有 Provider 使用方式一致\n *\n * 重构后使用 ProviderRegistry 和 ConfigManager 实现:\n * - 通过注册表获取适配器\n * - 通过配置管理器处理配置\n * - 保持与现有 API 的完全向后兼容性\n */\n\nimport type { AIProvider } from './__base__';\nimport { ProviderRegistry } from '../registry/provider-registry';\nimport { ConfigManager } from '../config/config-manager';\nimport type { ProviderType } from '../config/types';\n\n// 重新导出 ProviderType 以保持向后兼容\nexport type { ProviderType } from '../config/types';\n\n/**\n * 统一的 Provider 配置(旧格式,保持向后兼容)\n */\nexport interface ProviderConfig {\n /** Provider 类型 */\n provider: ProviderType;\n /** API Key */\n apiKey: string;\n /** 自定义 API 地址(可选) */\n baseUrl?: string;\n}\n\n/**\n * 基于适配器的 Provider 包装类\n * 将适配器和客户端组合成符合 AIProvider 接口的实例\n */\nclass AdapterBasedProvider implements AIProvider {\n readonly name: string;\n\n constructor(\n private readonly adapter: ReturnType<typeof ProviderRegistry.getAdapter>,\n private readonly apiKey: string,\n private readonly baseUrl?: string\n ) {\n this.name = adapter.name;\n }\n\n /**\n * 获取客户端实例\n */\n private getClient() {\n return this.adapter.createClient({\n apiKey: this.apiKey,\n baseUrl: this.baseUrl ?? this.adapter.defaultBaseUrl,\n });\n }\n\n /**\n * 发送聊天请求(非流式)\n */\n async chat(\n options: Parameters<AIProvider['chat']>[0]\n ): Promise<\n ReturnType<AIProvider['chat']> extends Promise<infer R> ? R : never\n > {\n const client = this.getClient();\n const baseUrl = this.baseUrl ?? this.adapter.defaultBaseUrl;\n const endpoint = this.adapter.getEndpointUrl(baseUrl);\n const endpointPath = endpoint.replace(baseUrl, '');\n const body = this.adapter.buildChatRequest(options, false);\n\n const response = await client.chat(endpointPath, body);\n return this.adapter.parseChatResponse(response, options.model);\n }\n\n /**\n * 发送流式聊天请求\n */\n async *chatStream(\n options: Parameters<AIProvider['chatStream']>[0]\n ): AsyncGenerator<\n ReturnType<AIProvider['chatStream']> extends AsyncGenerator<\n infer T,\n unknown,\n unknown\n >\n ? T\n : never,\n void,\n unknown\n > {\n const client = this.getClient();\n const baseUrl = this.baseUrl ?? this.adapter.defaultBaseUrl;\n const endpoint = this.adapter.getEndpointUrl(baseUrl);\n const endpointPath = endpoint.replace(baseUrl, '');\n const body = this.adapter.buildChatRequest(options, true);\n\n const response = await client.chatStream(endpointPath, body);\n\n // 使用 StreamProcessor 处理流式响应\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { StreamProcessor } = require('../utils/stream-processor');\n\n yield* StreamProcessor.processStream(\n response,\n (delta: Record<string, unknown>) => this.adapter.extractStreamChunk(delta)\n );\n }\n\n /**\n * 简单对话:单轮问答\n */\n async ask(\n model: string,\n question: string,\n options?: Omit<Parameters<AIProvider['chat']>[0], 'model' | 'messages'>\n ): Promise<string> {\n const result = await this.chat({\n model,\n messages: [{ role: 'user', content: question }],\n ...options,\n });\n return result.content;\n }\n\n /**\n * 带系统提示的对话\n */\n async askWithSystem(\n model: string,\n systemPrompt: string,\n userMessage: string,\n options?: Omit<Parameters<AIProvider['chat']>[0], 'model' | 'messages'>\n ): Promise<string> {\n const result = await this.chat({\n model,\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userMessage },\n ],\n ...options,\n });\n return result.content;\n }\n}\n\n/**\n * 创建 AI Provider 实例\n *\n * 重构后的实现:\n * - 使用 ConfigManager 处理配置(支持旧格式自动转换)\n * - 使用 ProviderRegistry 获取适配器\n * - 返回基于适配器的 Provider 包装类\n *\n * @example\n * ```ts\n * // 所有 Provider 使用相同方式创建\n * const openrouter = createProvider({ provider: 'openrouter', apiKey: 'xxx' });\n * const gemini = createProvider({ provider: 'gemini', apiKey: 'xxx' });\n * const groq = createProvider({ provider: 'groq', apiKey: 'xxx' });\n *\n * // 之后使用方式完全一致\n * const answer = await openrouter.ask('gpt-4o', '你好');\n * const answer = await gemini.ask('gemini-2.5-flash', '你好');\n * ```\n */\nexport function createProvider(config: ProviderConfig): AIProvider {\n // 使用 ConfigManager 转换旧格式配置为统一格式\n const unifiedConfig = ConfigManager.fromLegacyConfig(config);\n\n // 从注册表获取适配器\n const adapter = ProviderRegistry.getAdapter(unifiedConfig.provider);\n\n // 创建基于适配器的 Provider 实例\n return new AdapterBasedProvider(\n adapter,\n unifiedConfig.credentials.apiKey,\n unifiedConfig.credentials.baseUrl\n );\n}\n\n/**\n * 快捷创建函数\n * 提供更简洁的 API 来创建各种 Provider\n */\nexport const ai = {\n openrouter: (apiKey: string, baseUrl?: string) =>\n createProvider({ provider: 'openrouter', apiKey, baseUrl }),\n\n gemini: (apiKey: string, baseUrl?: string) =>\n createProvider({ provider: 'gemini', apiKey, baseUrl }),\n\n groq: (apiKey: string, baseUrl?: string) =>\n createProvider({ provider: 'groq', apiKey, baseUrl }),\n\n huggingface: (apiKey: string, baseUrl?: string) =>\n createProvider({ provider: 'huggingface', apiKey, baseUrl }),\n\n modelscope: (apiKey: string, baseUrl?: string) =>\n createProvider({ provider: 'modelscope', apiKey, baseUrl }),\n\n deepseek: (apiKey: string, baseUrl?: string) =>\n createProvider({ provider: 'deepseek', apiKey, baseUrl }),\n\n poe: (apiKey: string, baseUrl?: string) =>\n createProvider({ provider: 'poe', apiKey, baseUrl }),\n\n nova: (apiKey: string, baseUrl?: string) =>\n createProvider({ provider: 'nova', apiKey, baseUrl }),\n};\n","/**\n * 模型特性自动检测与智能降级策略\n *\n * 解决问题:\n * 1. 思考模型(thinking models)在低 token 限制下 content 为空\n * 2. 模型聚合平台无法预知哪些是思考模型\n * 3. 避免硬编码模型列表\n *\n * 策略:\n * 1. 基于模型名称模式匹配(启发式检测)\n * 2. 基于响应特征动态检测(运行时检测)\n * 3. 智能降级:自动调整参数或提取有效内容\n */\n\nimport type { ChatResult, ChatOptions, ReasoningConfig } from './__types__';\n\n// ============ 模型特性类型 ============\n\n/**\n * 模型行为类型\n */\nexport type ModelBehavior =\n | 'thinking-first' // 思考优先:先输出 reasoning,content 可能延迟或为空\n | 'direct-answer' // 直接回答:主要输出 content\n | 'hybrid' // 混合模式:同时输出 reasoning 和 content\n | 'unknown'; // 未知\n\n/**\n * 模型特性信息\n */\nexport interface ModelCharacteristics {\n /** 模型行为类型 */\n behavior: ModelBehavior;\n /** 是否支持 reasoning 参数 */\n supportsReasoningConfig: boolean;\n /** 推荐的最小 maxTokens(针对思考模型) */\n recommendedMinTokens: number;\n /** 检测置信度 0-1 */\n confidence: number;\n /** 检测来源 */\n detectedBy: 'pattern' | 'runtime' | 'cache';\n}\n\n/**\n * 降级策略结果\n */\nexport interface FallbackResult {\n /** 最终返回的内容 */\n content: string;\n /** 是否触发了降级 */\n didFallback: boolean;\n /** 降级原因 */\n fallbackReason?: string;\n /** 原始 reasoning(如果有) */\n originalReasoning?: string | null;\n}\n\n// ============ 模型名称模式检测 ============\n\n/**\n * 思考模型的名称模式(启发式检测)\n * 这些模式用于初步判断,不是硬编码的模型列表\n *\n * 注意:模式按优先级排序,更具体的模式在前\n */\nconst THINKING_MODEL_PATTERNS: RegExp[] = [\n // 明确的思考/推理标识\n /[-_]think(?:ing)?(?:[-_:]|$)/i, // *-think, *-thinking\n /[-_]reason(?:ing)?(?:[-_:]|$)/i, // *-reason, *-reasoning\n /[-_]cot(?:[-_:]|$)/i, // chain-of-thought\n /[-_]reflect(?:ion)?(?:[-_:]|$)/i, // reflection models\n\n // 知名推理模型系列\n /\\bo1[-_]?/i, // OpenAI o1 系列\n /\\bo3[-_]?/i, // OpenAI o3 系列\n /\\br1[-_]?/i, // DeepSeek R1 等\n /\\bqwq\\b/i, // Qwen QwQ\n /\\bn1[-_]?/i, // nex-n1 等\n\n // 通用思考关键词(较低优先级)\n /think/i, // 包含 think\n];\n\n/**\n * 明确的直接回答模型模式\n * 注意:这些模式优先级低于思考模型模式\n */\nconst DIRECT_ANSWER_PATTERNS: RegExp[] = [\n /[-_]chat$/i, // *-chat (结尾)\n /[-_]instruct/i, // *-instruct\n /[-_]turbo/i, // *-turbo\n /[-_]flash/i, // gemini-flash 等快速模型\n /[-_]lite[-_v]/i, // lite 版本(但不匹配 lite 结尾,避免误判)\n /[-_]fast/i, // fast 模型\n];\n\n/**\n * 需要特殊处理的模型模式(可能返回空响应)\n */\nconst PROBLEMATIC_MODEL_PATTERNS: RegExp[] = [\n /nova[-_]?\\d*[-_]lite/i, // Amazon Nova Lite 系列\n];\n\n/**\n * 检查是否是已知的问题模型\n */\nexport function isProblematicModel(modelId: string): boolean {\n return PROBLEMATIC_MODEL_PATTERNS.some(pattern => pattern.test(modelId));\n}\n\n/**\n * 基于模型名称模式检测模型特性\n */\nexport function detectByModelName(modelId: string): ModelCharacteristics {\n const normalizedId = modelId.toLowerCase();\n\n // 检查是否匹配思考模型模式\n const isThinkingPattern = THINKING_MODEL_PATTERNS.some(pattern =>\n pattern.test(normalizedId)\n );\n\n // 检查是否匹配直接回答模式\n const isDirectPattern = DIRECT_ANSWER_PATTERNS.some(pattern =>\n pattern.test(normalizedId)\n );\n\n // 检查是否是问题模型\n const isProblematic = isProblematicModel(normalizedId);\n\n // 如果同时匹配两种模式,优先认为是思考模型(更保守的策略)\n if (isThinkingPattern) {\n return {\n behavior: 'thinking-first',\n supportsReasoningConfig: true,\n recommendedMinTokens: 500,\n confidence: 0.7,\n detectedBy: 'pattern',\n };\n }\n\n if (isDirectPattern) {\n return {\n behavior: 'direct-answer',\n supportsReasoningConfig: false,\n // 问题模型需要更多 token\n recommendedMinTokens: isProblematic ? 300 : 100,\n confidence: 0.6,\n detectedBy: 'pattern',\n };\n }\n\n // 未知模型,使用保守默认值\n return {\n behavior: 'unknown',\n supportsReasoningConfig: false,\n recommendedMinTokens: isProblematic ? 300 : 200,\n confidence: 0.3,\n detectedBy: 'pattern',\n };\n}\n\n// ============ 运行时特性检测 ============\n\n/**\n * 模型特性缓存(运行时学习)\n */\nconst modelCharacteristicsCache = new Map<string, ModelCharacteristics>();\n\n/**\n * 基于响应结果检测模型特性\n */\nexport function detectByResponse(\n modelId: string,\n result: ChatResult\n): ModelCharacteristics {\n const hasReasoning = !!result.reasoning && result.reasoning.length > 0;\n const hasContent = !!result.content && result.content.trim().length > 0;\n const reasoningLength = result.reasoning?.length ?? 0;\n const contentLength = result.content?.length ?? 0;\n\n let behavior: ModelBehavior;\n let supportsReasoningConfig = false;\n let recommendedMinTokens = 200;\n\n if (hasReasoning && !hasContent) {\n // 只有 reasoning,没有 content -> 典型的思考优先模型\n behavior = 'thinking-first';\n supportsReasoningConfig = true;\n recommendedMinTokens = Math.max(500, reasoningLength + 200);\n } else if (hasReasoning && hasContent) {\n // 两者都有\n if (reasoningLength > contentLength * 2) {\n // reasoning 明显更长 -> 思考优先\n behavior = 'thinking-first';\n supportsReasoningConfig = true;\n recommendedMinTokens = 500;\n } else {\n // 混合模式\n behavior = 'hybrid';\n supportsReasoningConfig = true;\n recommendedMinTokens = 300;\n }\n } else if (hasContent && !hasReasoning) {\n // 只有 content -> 直接回答模型\n behavior = 'direct-answer';\n supportsReasoningConfig = false;\n recommendedMinTokens = 100;\n } else {\n // 都没有 -> 可能是 token 限制太低\n behavior = 'unknown';\n recommendedMinTokens = 500;\n }\n\n const characteristics: ModelCharacteristics = {\n behavior,\n supportsReasoningConfig,\n recommendedMinTokens,\n confidence: 0.9,\n detectedBy: 'runtime',\n };\n\n // 缓存结果\n modelCharacteristicsCache.set(modelId, characteristics);\n\n return characteristics;\n}\n\n/**\n * 获取模型特性(优先使用缓存)\n */\nexport function getModelCharacteristics(modelId: string): ModelCharacteristics {\n // 优先使用运行时缓存\n const cached = modelCharacteristicsCache.get(modelId);\n if (cached) {\n return { ...cached, detectedBy: 'cache' };\n }\n\n // 否则使用模式匹配\n return detectByModelName(modelId);\n}\n\n// ============ 智能降级策略 ============\n\n/**\n * 降级策略配置\n */\nexport interface FallbackConfig {\n /** 是否启用自动降级 */\n enabled: boolean;\n /** 当 content 为空时,是否返回 reasoning */\n returnReasoningAsContent: boolean;\n /** 是否从 reasoning 中提取结论 */\n extractConclusionFromReasoning: boolean;\n /** 是否自动增加 maxTokens 重试 */\n autoRetryWithMoreTokens: boolean;\n /** 重试时的 token 增量 */\n retryTokenIncrement: number;\n /** 最大重试次数 */\n maxRetries: number;\n}\n\n/**\n * 默认降级配置\n */\nexport const DEFAULT_FALLBACK_CONFIG: FallbackConfig = {\n enabled: true,\n returnReasoningAsContent: true,\n extractConclusionFromReasoning: true,\n autoRetryWithMoreTokens: false, // 默认关闭自动重试,避免额外消耗\n retryTokenIncrement: 300,\n maxRetries: 2,\n};\n\n/**\n * 从 reasoning 中提取结论\n * 尝试找到最终答案或结论部分\n */\nexport function extractConclusionFromReasoning(\n reasoning: string\n): string | null {\n if (!reasoning) return null;\n\n // 常见的结论标记模式\n const conclusionPatterns = [\n /(?:therefore|thus|so|hence|finally|in conclusion|the answer is|result is)[:\\s]*(.+?)(?:\\n|$)/i,\n /(?:答案是|结论是|因此|所以|最终)[::\\s]*(.+?)(?:\\n|$)/,\n /(?:\\*\\*answer\\*\\*|\\*\\*result\\*\\*)[:\\s]*(.+?)(?:\\n|$)/i,\n /=\\s*(.+?)(?:\\n|$)/, // 数学等式结果\n ];\n\n for (const pattern of conclusionPatterns) {\n const match = reasoning.match(pattern);\n if (match && match[1]) {\n return match[1].trim();\n }\n }\n\n // 如果没找到明确结论,返回最后一段非空内容\n const paragraphs = reasoning.split(/\\n\\n+/).filter(p => p.trim());\n if (paragraphs.length > 0) {\n const lastParagraph = paragraphs[paragraphs.length - 1].trim();\n // 只返回较短的最后段落(可能是结论)\n if (lastParagraph.length < 500) {\n return lastParagraph;\n }\n }\n\n return null;\n}\n\n/**\n * 应用降级策略处理响应结果\n */\nexport function applyFallbackStrategy(\n result: ChatResult,\n config: Partial<FallbackConfig> = {}\n): FallbackResult {\n const finalConfig = { ...DEFAULT_FALLBACK_CONFIG, ...config };\n\n // 如果已有有效 content,直接返回\n if (result.content && result.content.trim().length > 0) {\n return {\n content: result.content,\n didFallback: false,\n originalReasoning: result.reasoning,\n };\n }\n\n // content 为空,需要降级处理\n if (!finalConfig.enabled) {\n return {\n content: '',\n didFallback: false,\n originalReasoning: result.reasoning,\n };\n }\n\n // 尝试从 reasoning 提取结论\n if (finalConfig.extractConclusionFromReasoning && result.reasoning) {\n const conclusion = extractConclusionFromReasoning(result.reasoning);\n if (conclusion) {\n return {\n content: conclusion,\n didFallback: true,\n fallbackReason: 'extracted_conclusion_from_reasoning',\n originalReasoning: result.reasoning,\n };\n }\n }\n\n // 直接返回 reasoning 作为 content\n if (finalConfig.returnReasoningAsContent && result.reasoning) {\n return {\n content: result.reasoning,\n didFallback: true,\n fallbackReason: 'returned_reasoning_as_content',\n originalReasoning: result.reasoning,\n };\n }\n\n // 无法降级\n return {\n content: '',\n didFallback: false,\n fallbackReason: 'no_fallback_available',\n originalReasoning: result.reasoning,\n };\n}\n\n// ============ 智能参数调整 ============\n\n/**\n * 根据模型特性智能调整请求参数\n */\nexport function adjustOptionsForModel(\n modelId: string,\n options: ChatOptions\n): ChatOptions {\n const characteristics = getModelCharacteristics(modelId);\n\n // 如果是思考模型且 maxTokens 过低,自动调整\n if (\n characteristics.behavior === 'thinking-first' &&\n (!options.maxTokens ||\n options.maxTokens < characteristics.recommendedMinTokens)\n ) {\n return {\n ...options,\n maxTokens: Math.max(\n options.maxTokens ?? 0,\n characteristics.recommendedMinTokens\n ),\n };\n }\n\n return options;\n}\n\n/**\n * 为思考模型生成推荐配置\n */\nexport function getRecommendedConfig(\n modelId: string,\n scenario: 'simple' | 'math' | 'reasoning' | 'fast' = 'simple'\n): Partial<ChatOptions> {\n const characteristics = getModelCharacteristics(modelId);\n\n if (characteristics.behavior !== 'thinking-first') {\n // 非思考模型,返回基础配置\n return {};\n }\n\n // 思考模型的场景化配置\n const configs: Record<string, Partial<ChatOptions>> = {\n simple: {\n maxTokens: 300,\n reasoning: { effort: 'low' },\n },\n math: {\n maxTokens: 600,\n reasoning: { effort: 'high' },\n },\n reasoning: {\n maxTokens: 800,\n reasoning: { effort: 'medium' },\n },\n fast: {\n maxTokens: 200,\n reasoning: { effort: 'off' },\n },\n };\n\n return configs[scenario] ?? configs.simple;\n}\n\n// ============ 导出工具函数 ============\n\nexport const ModelDetection = {\n detectByModelName,\n detectByResponse,\n getModelCharacteristics,\n applyFallbackStrategy,\n adjustOptionsForModel,\n getRecommendedConfig,\n extractConclusionFromReasoning,\n isProblematicModel,\n clearCache: () => modelCharacteristicsCache.clear(),\n};\n","/**\n * AI Provider 接口和基类\n */\n\nimport type {\n ChatOptions,\n ChatResult,\n StreamChunk,\n ModelInfo,\n} from './__types__';\nimport {\n ModelDetection,\n type FallbackConfig,\n type ModelCharacteristics,\n DEFAULT_FALLBACK_CONFIG,\n} from './__model-detection__';\n\n/**\n * AI Provider 基础接口\n * 所有 provider 实现都需要实现这个接口\n */\nexport interface AIProvider {\n /** Provider 名称 */\n readonly name: string;\n\n /**\n * 发送聊天请求(非流式)\n */\n chat(options: ChatOptions): Promise<ChatResult>;\n\n /**\n * 发送流式聊天请求\n */\n chatStream(options: ChatOptions): AsyncGenerator<StreamChunk, void, unknown>;\n\n /**\n * 简单对话:单轮问答\n */\n ask(\n model: string,\n question: string,\n options?: Omit<ChatOptions, 'model' | 'messages'>\n ): Promise<string>;\n\n /**\n * 带系统提示的对话\n */\n askWithSystem(\n model: string,\n systemPrompt: string,\n userMessage: string,\n options?: Omit<ChatOptions, 'model' | 'messages'>\n ): Promise<string>;\n\n /**\n * 获取可用模型列表(可选实现)\n */\n listModels?(): Promise<ModelInfo[]>;\n\n /**\n * 获取模型特性信息(可选实现)\n */\n getModelCharacteristics?(modelId: string): ModelCharacteristics;\n}\n\n/**\n * 扩展的 ask 选项,支持降级配置\n */\nexport interface AskOptions extends Omit<ChatOptions, 'model' | 'messages'> {\n /** 降级策略配置 */\n fallback?: Partial<FallbackConfig>;\n /** 是否自动调整参数以适应模型特性 */\n autoAdjust?: boolean;\n}\n\n/**\n * AI Provider 基础抽象类\n * 提供一些通用实现,子类只需实现核心方法\n *\n * 特性:\n * - 自动检测模型类型(思考模型 vs 直接回答模型)\n * - 智能降级策略(content 为空时自动处理)\n * - 参数自动调整(为思考模型增加 maxTokens)\n */\nexport abstract class BaseProvider implements AIProvider {\n abstract readonly name: string;\n\n /** 降级策略配置 */\n protected fallbackConfig: FallbackConfig = DEFAULT_FALLBACK_CONFIG;\n\n /** 是否启用自动参数调整 */\n protected autoAdjustEnabled: boolean = true;\n\n abstract chat(options: ChatOptions): Promise<ChatResult>;\n\n abstract chatStream(\n options: ChatOptions\n ): AsyncGenerator<StreamChunk, void, unknown>;\n\n /**\n * 配置降级策略\n */\n configureFallback(config: Partial<FallbackConfig>): this {\n this.fallbackConfig = { ...this.fallbackConfig, ...config };\n return this;\n }\n\n /**\n * 启用/禁用自动参数调整\n */\n setAutoAdjust(enabled: boolean): this {\n this.autoAdjustEnabled = enabled;\n return this;\n }\n\n /**\n * 获取模型特性信息\n */\n getModelCharacteristics(modelId: string): ModelCharacteristics {\n return ModelDetection.getModelCharacteristics(modelId);\n }\n\n /**\n * 智能聊天:自动检测模型特性并应用降级策略\n */\n async chatSmart(options: ChatOptions): Promise<ChatResult> {\n // 自动调整参数\n const adjustedOptions = this.autoAdjustEnabled\n ? ModelDetection.adjustOptionsForModel(options.model, options)\n : options;\n\n const result = await this.chat(adjustedOptions);\n\n // 运行时检测并缓存模型特性\n ModelDetection.detectByResponse(options.model, result);\n\n return result;\n }\n\n /**\n * 简单对话:单轮问答(默认实现)\n *\n * 智能处理思考模型:\n * 1. 自动检测模型类型\n * 2. 为思考模型自动调整 maxTokens\n * 3. 如果 content 为空,智能降级(提取结论或返回 reasoning)\n */\n async ask(\n model: string,\n question: string,\n options?: AskOptions\n ): Promise<string> {\n const {\n fallback,\n autoAdjust = this.autoAdjustEnabled,\n ...chatOptions\n } = options ?? {};\n\n // 构建请求选项\n let finalOptions: ChatOptions = {\n model,\n messages: [{ role: 'user', content: question }],\n ...chatOptions,\n };\n\n // 自动调整参数\n if (autoAdjust) {\n finalOptions = ModelDetection.adjustOptionsForModel(model, finalOptions);\n }\n\n const result = await this.chat(finalOptions);\n\n // 运行时检测模型特性\n ModelDetection.detectByResponse(model, result);\n\n // 应用降级策略\n const fallbackResult = ModelDetection.applyFallbackStrategy(result, {\n ...this.fallbackConfig,\n ...fallback,\n });\n\n return fallbackResult.content;\n }\n\n /**\n * 带系统提示的对话(默认实现)\n *\n * 智能处理思考模型:\n * 1. 自动检测模型类型\n * 2. 为思考模型自动调整 maxTokens\n * 3. 如果 content 为空,智能降级(提取结论或返回 reasoning)\n */\n async askWithSystem(\n model: string,\n systemPrompt: string,\n userMessage: string,\n options?: AskOptions\n ): Promise<string> {\n const {\n fallback,\n autoAdjust = this.autoAdjustEnabled,\n ...chatOptions\n } = options ?? {};\n\n // 构建请求选项\n let finalOptions: ChatOptions = {\n model,\n messages: [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: userMessage },\n ],\n ...chatOptions,\n };\n\n // 自动调整参数\n if (autoAdjust) {\n finalOptions = ModelDetection.adjustOptionsForModel(model, finalOptions);\n }\n\n const result = await this.chat(finalOptions);\n\n // 运行时检测模型特性\n ModelDetection.detectByResponse(model, result);\n\n // 应用降级策略\n const fallbackResult = ModelDetection.applyFallbackStrategy(result, {\n ...this.fallbackConfig,\n ...fallback,\n });\n\n return fallbackResult.content;\n }\n\n /**\n * 场景化问答:根据场景自动配置参数\n *\n * @param model 模型 ID\n * @param question 问题\n * @param scenario 场景类型\n * - 'simple': 简单问答(默认)\n * - 'math': 数学计算\n * - 'reasoning': 逻辑推理\n * - 'fast': 快速回答(关闭思考)\n */\n async askWithScenario(\n model: string,\n question: string,\n scenario: 'simple' | 'math' | 'reasoning' | 'fast' = 'simple',\n options?: AskOptions\n ): Promise<string> {\n const recommendedConfig = ModelDetection.getRecommendedConfig(\n model,\n scenario\n );\n return this.ask(model, question, {\n ...recommendedConfig,\n ...options,\n });\n }\n}\n","// 统一工厂(推荐使用)\nexport { createProvider, ai } from './__factory__';\nexport type { ProviderType, ProviderConfig } from './__factory__';\n\n// 基类和接口\nexport type { AIProvider, AskOptions } from './__base__';\nexport { BaseProvider } from './__base__';\n\n// 模型检测与降级策略\nexport {\n ModelDetection,\n DEFAULT_FALLBACK_CONFIG,\n detectByModelName,\n detectByResponse,\n getModelCharacteristics,\n applyFallbackStrategy,\n adjustOptionsForModel,\n getRecommendedConfig,\n extractConclusionFromReasoning,\n isProblematicModel,\n} from './__model-detection__';\nexport type {\n ModelBehavior,\n ModelCharacteristics,\n FallbackConfig,\n FallbackResult,\n} from './__model-detection__';\n\n// 类型\nexport type {\n ChatMessage,\n ChatOptions,\n ChatResult,\n ReasoningConfig,\n ReasoningEffort,\n StreamChunk,\n TokenUsage,\n ModelInfo,\n ModelPricing,\n} from './__types__';\n\nexport { EFFORT_TOKEN_MAP } from './__types__';\n\n// Provider 实现(直接使用)\nexport { OpenRouterProvider } from './openrouter';\nexport type { OpenRouterModelInfo } from './openrouter';\n\nexport { ModelScopeProvider } from './modelscope';\nexport type { ModelScopeConfig } from './modelscope';\n\nexport { HuggingFaceProvider } from './huggingface';\nexport type { HuggingFaceConfig } from './huggingface';\n\nexport { GroqProvider } from './groq';\nexport type { GroqConfig } from './groq';\n\nexport { GeminiProvider } from './gemini';\nexport type { GeminiConfig } from './gemini';\n\nexport { DeepSeekProvider } from './deepseek';\nexport type { DeepSeekConfig } from './deepseek';\n\nexport { PoeProvider } from './poe';\nexport type { PoeConfig } from './poe';\n\nexport { NovaProvider } from './nova';\nexport type { NovaConfig } from './nova';\n\n// ============================================\n// 新架构组件重导出(便于从 providers 模块访问)\n// ============================================\n\n// 工具层\nexport { StreamProcessor, RequestBuilder, ConfigValidator } from '../utils';\nexport type {\n DeltaExtractor,\n ValidationResult,\n ValidationError,\n} from '../utils';\n\n// 配置管理\nexport { ConfigManager } from '../config';\nexport type {\n UnifiedProviderConfig,\n RegistryConfig,\n ProviderCapabilities,\n LegacyProviderConfig,\n} from '../config';\nexport { CONFIG_DEFAULTS, VALID_PROVIDERS } from '../config';\n\n// 客户端层\nexport { HttpProviderClient } from '../client';\nexport type { ProviderClient, ProviderClientConfig } from '../client';\nexport { ProviderError, APIError, NetworkError, TimeoutError } from '../client';\n\n// 注册层\nexport { ProviderRegistry, RegistryError } from '../registry';\n\n// 适配器层\nexport {\n BaseAdapter,\n OpenRouterAdapter,\n GeminiAdapter,\n GroqAdapter,\n HuggingFaceAdapter,\n ModelScopeAdapter,\n DeepSeekAdapter,\n PoeAdapter,\n NovaAdapter,\n createBuiltInAdapters,\n} from '../adapters';\nexport type { ProviderAdapter, AdapterConfig } from '../adapters';\n","/**\n * OpenRouter Provider 实现\n * 使用 OpenRouterAdapter 和 HttpProviderClient 进行重构\n */\n\nimport { BaseProvider } from './__base__';\nimport type {\n ChatOptions,\n ChatResult,\n StreamChunk,\n ModelInfo,\n} from './__types__';\nimport { OpenRouterAdapter } from '../adapters/openrouter-adapter';\nimport { HttpProviderClient } from '../client/http-provider-client';\nimport { StreamProcessor } from '../utils/stream-processor';\nimport type { ProviderClient } from '../client/types';\n\n/**\n * OpenRouter 扩展的模型信息\n */\nexport interface OpenRouterModelInfo extends ModelInfo {\n /** 规范化的 slug */\n canonicalSlug: string;\n /** 创建时间戳 */\n created: number;\n /** 架构信息 */\n architecture: {\n modality: string;\n inputModalities: string[];\n outputModalities: string[];\n tokenizer: string;\n instructType: string;\n };\n}\n\n/**\n * OpenRouter Provider\n * 使用适配器模式重构,复用统一的工具层\n */\nexport class OpenRouterProvider extends BaseProvider {\n readonly name = 'openrouter';\n private adapter: OpenRouterAdapter;\n private client: ProviderClient;\n private baseUrl: string;\n private apiKey: string;\n\n constructor(apiKey: string, baseUrl?: string) {\n super();\n this.apiKey = apiKey;\n this.adapter = new OpenRouterAdapter();\n this.baseUrl = baseUrl ?? this.adapter.defaultBaseUrl;\n this.client = new HttpProviderClient({\n apiKey,\n baseUrl: this.baseUrl,\n });\n }\n\n /**\n * 发送聊天请求(非流式)\n */\n async chat(options: ChatOptions): Promise<ChatResult> {\n // 使用适配器构建请求体\n const body = this.adapter.buildChatRequest(options, false);\n\n // 获取端点 URL\n const endpoint = this.adapter.getEndpointUrl(this.baseUrl);\n // 从完整 URL 中提取路径部分\n const endpointPath = endpoint.replace(this.baseUrl, '');\n\n // 使用客户端发送请求\n const response = await this.client.chat(endpointPath, body);\n\n // 使用适配器解析响应\n return this.adapter.parseChatResponse(response, options.model);\n }\n\n /**\n * 发送流式聊天请求\n */\n async *chatStream(\n options: ChatOptions\n ): AsyncGenerator<StreamChunk, void, unknown> {\n // 使用适配器构建请求体\n const body = this.adapter.buildChatRequest(options, true);\n\n // 获取端点 URL\n const endpoint = this.adapter.getEndpointUrl(this.baseUrl);\n // 从完整 URL 中提取路径部分\n const endpointPath = endpoint.replace(this.baseUrl, '');\n\n // 使用客户端发送流式请求\n const response = await this.client.chatStream(endpointPath, body);\n\n // 使用 StreamProcessor 处理流式响应\n // 使用适配器的 extractStreamChunk 方法作为 delta 提取器\n yield* StreamProcessor.processStream(response, delta =>\n this.adapter.extractStreamChunk(delta)\n );\n }\n\n /**\n * 获取可用模型列表\n * 注意:此方法直接调用 OpenRouter API,不使用适配器\n */\n async listModels(): Promise<OpenRouterModelInfo[]> {\n // 使用 fetch 直接调用模型列表 API\n const response = await fetch(`${this.baseUrl}/models`, {\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch models: ${response.status} ${response.statusText}`\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result: any = await response.json();\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (result.data ?? []).map((m: any) => ({\n id: m.id,\n canonicalSlug: m.canonical_slug ?? m.id,\n name: m.name,\n description: m.description ?? '',\n created: m.created ?? 0,\n pricing: {\n prompt: m.pricing?.prompt ?? '0',\n completion: m.pricing?.completion ?? '0',\n request: m.pricing?.request ?? '0',\n image: m.pricing?.image ?? '0',\n },\n contextLength: m.context_length ?? 0,\n architecture: {\n modality: m.architecture?.modality ?? '',\n inputModalities: m.architecture?.input_modalities ?? [],\n outputModalities: m.architecture?.output_modalities ?? [],\n tokenizer: m.architecture?.tokenizer ?? '',\n instructType: m.architecture?.instruct_type ?? '',\n },\n supportedParameters: m.supported_parameters ?? [],\n }));\n }\n}\n","/**\n * ModelScope Provider 实现\n * 使用 OpenAI 兼容 API\n * 使用 ModelScopeAdapter 和 HttpProviderClient 进行重构\n */\n\nimport { BaseProvider } from './__base__';\nimport type { ChatOptions, ChatResult, StreamChunk } from './__types__';\nimport { ModelScopeAdapter } from '../adapters/modelscope-adapter';\nimport { HttpProviderClient } from '../client/http-provider-client';\nimport { StreamProcessor } from '../utils/stream-processor';\nimport type { ProviderClient } from '../client/types';\n\n/**\n * ModelScope Provider 配置\n */\nexport interface ModelScopeConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\n/**\n * ModelScope Provider\n * 兼容 OpenAI API 格式,支持 DeepSeek 等模型\n * 使用适配器模式重构,复用统一的工具层\n */\nexport class ModelScopeProvider extends BaseProvider {\n readonly name = 'modelscope';\n private adapter: ModelScopeAdapter;\n private client: ProviderClient;\n private baseUrl: string;\n\n constructor(config: ModelScopeConfig | string) {\n super();\n this.adapter = new ModelScopeAdapter();\n\n if (typeof config === 'string') {\n this.baseUrl = this.adapter.defaultBaseUrl;\n this.client = new HttpProviderClient({\n apiKey: config,\n baseUrl: this.baseUrl,\n });\n } else {\n this.baseUrl = config.baseUrl ?? this.adapter.defaultBaseUrl;\n this.client = new HttpProviderClient({\n apiKey: config.apiKey,\n baseUrl: this.baseUrl,\n });\n }\n }\n\n /**\n * 发送聊天请求(非流式)\n */\n async chat(options: ChatOptions): Promise<ChatResult> {\n // 使用适配器构建请求体\n const body = this.adapter.buildChatRequest(options, false);\n\n // 获取端点 URL\n const endpoint = this.adapter.getEndpointUrl(this.baseUrl);\n // 从完整 URL 中提取路径部分\n const endpointPath = endpoint.replace(this.baseUrl, '');\n\n // 使用客户端发送请求\n const response = await this.client.chat(endpointPath, body);\n\n // 使用适配器解析响应\n return this.adapter.parseChatResponse(response, options.model);\n }\n\n /**\n * 发送流式聊天请求\n */\n async *chatStream(\n options: ChatOptions\n ): AsyncGenerator<StreamChunk, void, unknown> {\n // 使用适配器构建请求体\n const body = this.adapter.buildChatRequest(options, true);\n\n // 获取端点 URL\n const endpoint = this.adapter.getEndpointUrl(this.baseUrl);\n // 从完整 URL 中提取路径部分\n const endpointPath = endpoint.replace(this.baseUrl, '');\n\n // 使用客户端发送流式请求\n const response = await this.client.chatStream(endpointPath, body);\n\n // 使用 StreamProcessor 处理流式响应\n // 使用适配器的 extractStreamChunk 方法作为 delta 提取器\n yield* StreamProcessor.processStream(response, delta =>\n this.adapter.extractStreamChunk(delta)\n );\n }\n}\n","/**\n * HuggingFace Provider 实现\n * 使用 HuggingFace Router API (OpenAI 兼容)\n * 使用 HuggingFaceAdapter 和 HttpProviderClient 进行重构\n */\n\nimport { BaseProvider } from './__base__';\nimport type { ChatOptions, ChatResult, StreamChunk } from './__types__';\nimport { HuggingFaceAdapter } from '../adapters/huggingface-adapter';\nimport { HttpProviderClient } from '../client/http-provider-client';\nimport { StreamProcessor } from '../utils/stream-processor';\nimport type { ProviderClient } from '../client/types';\n\n/**\n * HuggingFace Provider 配置\n */\nexport interface HuggingFaceConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\n/**\n * HuggingFace Provider\n * 使用 HuggingFace Router,兼容 OpenAI API 格式\n * 使用适配器模式重构,复用统一的工具层\n */\nexport class HuggingFaceProvider extends BaseProvider {\n readonly name = 'huggingface';\n private adapter: HuggingFaceAdapter;\n private client: ProviderClient;\n private baseUrl: string;\n\n constructor(config: HuggingFaceConfig | string) {\n super();\n this.adapter = new HuggingFaceAdapter();\n\n if (typeof config === 'string') {\n this.baseUrl = this.adapter.defaultBaseUrl;\n this.client = new HttpProviderClient({\n apiKey: config,\n baseUrl: this.baseUrl,\n });\n } else {\n this.baseUrl = config.baseUrl ?? this.adapter.defaultBaseUrl;\n this.client = new HttpProviderClient({\n apiKey: config.apiKey,\n baseUrl: this.baseUrl,\n });\n }\n }\n\n /**\n * 发送聊天请求(非流式)\n *\n * reasoning 参数说明:\n * - HuggingFace 是模型聚合平台,thinking 支持取决于具体模型\n * - 如果模型支持,会返回 reasoning_content\n */\n async chat(options: ChatOptions): Promise<ChatResult> {\n // 使用适配器构建请求体\n const body = this.adapter.buildChatRequest(options, false);\n\n // 获取端点 URL\n const endpoint = this.adapter.getEndpointUrl(this.baseUrl);\n // 从完整 URL 中提取路径部分\n const endpointPath = endpoint.replace(this.baseUrl, '');\n\n // 使用客户端发送请求\n const response = await this.client.chat(endpointPath, body);\n\n // 使用适配器解析响应\n return this.adapter.parseChatResponse(response, options.model);\n }\n\n /**\n * 发送流式聊天请求\n */\n async *chatStream(\n options: ChatOptions\n ): AsyncGenerator<StreamChunk, void, unknown> {\n // 使用适配器构建请求体\n const body = this.adapter.buildChatRequest(options, true);\n\n // 获取端点 URL\n const endpoint = this.adapter.getEndpointUrl(this.baseUrl);\n // 从完整 URL 中提取路径部分\n const endpointPath = endpoint.replace(this.baseUrl, '');\n\n // 使用客户端发送流式请求\n const response = await this.client.chatStream(endpointPath, body);\n\n // 使用 StreamProcessor 处理流式响应\n // 使用适配器的 extractStreamChunk 方法作为 delta 提取器\n yield* StreamProcessor.processStream(response, delta =>\n this.adapter.extractStreamChunk(delta)\n );\n }\n}\n","/**\n * Groq Provider 实现\n * 使用 Groq API (OpenAI 兼容)\n * 使用 GroqAdapter 和 HttpProviderClient 进行重构\n */\n\nimport { BaseProvider } from './__base__';\nimport type { ChatOptions, ChatResult, StreamChunk } from './__types__';\nimport { GroqAdapter } from '../adapters/groq-adapter';\nimport { HttpProviderClient } from '../client/http-provider-client';\nimport { StreamProcessor } from '../utils/stream-processor';\nimport type { ProviderClient } from '../client/types';\n\n/**\n * Groq Provider 配置\n */\nexport interface GroqConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\n/**\n * Groq Provider\n * 兼容 OpenAI API 格式,支持 reasoning_format 参数\n * 使用适配器模式重构,复用统一的工具层\n */\nexport class GroqProvider extends BaseProvider {\n readonly name = 'groq';\n private adapter: GroqAdapter;\n private client: ProviderClient;\n private baseUrl: string;\n\n constructor(config: GroqConfig | string) {\n super();\n this.adapter = new GroqAdapter();\n\n if (typeof config === 'string') {\n this.baseUrl = this.adapter.defaultBaseUrl;\n this.client = new HttpProviderClient({\n apiKey: config,\n baseUrl: this.baseUrl,\n });\n } else {\n this.baseUrl = config.baseUrl ?? this.adapter.defaultBaseUrl;\n this.client = new HttpProviderClient({\n apiKey: config.apiKey,\n baseUrl: this.baseUrl,\n });\n }\n }\n\n /**\n * 发送聊天请求(非流式)\n */\n async chat(options: ChatOptions): Promise<ChatResult> {\n // 使用适配器构建请求体\n const body = this.adapter.buildChatRequest(options, false);\n\n // 获取端点 URL\n const endpoint = this.adapter.getEndpointUrl(this.baseUrl);\n // 从完整 URL 中提取路径部分\n const endpointPath = endpoint.replace(this.baseUrl, '');\n\n // 使用客户端发送请求\n const response = await this.client.chat(endpointPath, body);\n\n // 使用适配器解析响应\n return this.adapter.parseChatResponse(response, options.model);\n }\n\n /**\n * 发送流式聊天请求\n */\n async *chatStream(\n options: ChatOptions\n ): AsyncGenerator<StreamChunk, void, unknown> {\n // 使用适配器构建请求体\n const body = this.adapter.buildChatRequest(options, true);\n\n // 获取端点 URL\n const endpoint = this.adapter.getEndpointUrl(this.baseUrl);\n // 从完整 URL 中提取路径部分\n const endpointPath = endpoint.replace(this.baseUrl, '');\n\n // 使用客户端发送流式请求\n const response = await this.client.chatStream(endpointPath, body);\n\n // 使用 StreamProcessor 处理流式响应\n // 使用适配器的 extractStreamChunk 方法作为 delta 提取器\n yield* StreamProcessor.processStream(response, delta =>\n this.adapter.extractStreamChunk(delta)\n );\n }\n}\n","/**\n * Gemini Provider 实现\n * 使用 Google Gemini API (OpenAI 兼容格式)\n * 使用 GeminiAdapter 和 HttpProviderClient 进行重构\n * https://ai.google.dev/gemini-api/docs/openai\n */\n\nimport { BaseProvider } from './__base__';\nimport type { ChatOptions, ChatResult, StreamChunk } from './__types__';\nimport { GeminiAdapter } from '../adapters/gemini-adapter';\nimport { HttpProviderClient } from '../client/http-provider-client';\nimport { StreamProcessor } from '../utils/stream-processor';\nimport type { ProviderClient } from '../client/types';\n\n/**\n * Gemini Provider 配置\n */\nexport interface GeminiConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\n/**\n * Gemini Provider\n * 使用 Google Gemini API,兼容 OpenAI 格式\n * 使用适配器模式重构,复用统一的工具层\n */\nexport class GeminiProvider extends BaseProvider {\n readonly name = 'gemini';\n private adapter: GeminiAdapter;\n private client: ProviderClient;\n private baseUrl: string;\n\n constructor(config: GeminiConfig | string) {\n super();\n this.adapter = new GeminiAdapter();\n\n if (typeof config === 'string') {\n this.baseUrl = this.adapter.defaultBaseUrl;\n this.client = new HttpProviderClient({\n apiKey: config,\n baseUrl: this.baseUrl,\n });\n } else {\n this.baseUrl = config.baseUrl ?? this.adapter.defaultBaseUrl;\n this.client = new HttpProviderClient({\n apiKey: config.apiKey,\n baseUrl: this.baseUrl,\n });\n }\n }\n\n /**\n * 发送聊天请求(非流式)\n */\n async chat(options: ChatOptions): Promise<ChatResult> {\n // 使用适配器构建请求体\n const body = this.adapter.buildChatRequest(options, false);\n\n // 获取端点 URL\n const endpoint = this.adapter.getEndpointUrl(this.baseUrl);\n // 从完整 URL 中提取路径部分\n const endpointPath = endpoint.replace(this.baseUrl, '');\n\n // 使用客户端发送请求\n const response = await this.client.chat(endpointPath, body);\n\n // 使用适配器解析响应\n return this.adapter.parseChatResponse(response, options.model);\n }\n\n /**\n * 发送流式聊天请求\n */\n async *chatStream(\n options: ChatOptions\n ): AsyncGenerator<StreamChunk, void, unknown> {\n // 使用适配器构建请求体\n const body = this.adapter.buildChatRequest(options, true);\n\n // 获取端点 URL\n const endpoint = this.adapter.getEndpointUrl(this.baseUrl);\n // 从完整 URL 中提取路径部分\n const endpointPath = endpoint.replace(this.baseUrl, '');\n\n // 使用客户端发送流式请求\n const response = await this.client.chatStream(endpointPath, body);\n\n // 使用 StreamProcessor 处理流式响应\n // 使用适配器的 extractStreamChunk 方法作为 delta 提取器\n yield* StreamProcessor.processStream(response, delta =>\n this.adapter.extractStreamChunk(delta)\n );\n }\n}\n","/**\n * DeepSeek Provider 实现\n * 使用 DeepSeek API (OpenAI 兼容格式)\n * 使用 DeepSeekAdapter 和 HttpProviderClient 进行重构\n * https://api-docs.deepseek.com/\n *\n * 支持模型:\n * - deepseek-chat: DeepSeek-V3 通用对话模型(可通过 thinking 参数启用思考)\n * - deepseek-reasoner: DeepSeek-R1 推理模型(自动启用思考)\n *\n * 思考模式:\n * - reasoning.effort 不为 'off' 时启用 thinking 模式\n * - maxTokens 独立控制输出长度,不受 effort 影响\n */\n\nimport { BaseProvider } from './__base__';\nimport type { ChatOptions, ChatResult, StreamChunk } from './__types__';\nimport { DeepSeekAdapter } from '../adapters/deepseek-adapter';\nimport { HttpProviderClient } from '../client/http-provider-client';\nimport { StreamProcessor } from '../utils/stream-processor';\nimport type { ProviderClient } from '../client/types';\n\n/**\n * DeepSeek Provider 配置\n */\nexport interface DeepSeekConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\n/**\n * DeepSeek Provider\n * 使用 DeepSeek API,兼容 OpenAI 格式\n * 使用适配器模式重构,复用统一的工具层\n */\nexport class DeepSeekProvider extends BaseProvider {\n readonly name = 'deepseek';\n private adapter: DeepSeekAdapter;\n private client: ProviderClient;\n private baseUrl: string;\n\n constructor(config: DeepSeekConfig | string) {\n super();\n this.adapter = new DeepSeekAdapter();\n\n if (typeof config === 'string') {\n this.baseUrl = this.adapter.defaultBaseUrl;\n this.client = new HttpProviderClient({\n apiKey: config,\n baseUrl: this.baseUrl,\n });\n } else {\n this.baseUrl = config.baseUrl ?? this.adapter.defaultBaseUrl;\n this.client = new HttpProviderClient({\n apiKey: config.apiKey,\n baseUrl: this.baseUrl,\n });\n }\n }\n\n /**\n * 发送聊天请求(非流式)\n *\n * reasoning 参数说明:\n * - effort 不为 'off' 时启用 thinking 模式\n * - maxTokens 独立控制输出长度,不受 effort 影响\n */\n async chat(options: ChatOptions): Promise<ChatResult> {\n // 使用适配器构建请求体\n const body = this.adapter.buildChatRequest(options, false);\n\n // 获取端点 URL\n const endpoint = this.adapter.getEndpointUrl(this.baseUrl);\n // 从完整 URL 中提取路径部分\n const endpointPath = endpoint.replace(this.baseUrl, '');\n\n // 使用客户端发送请求\n const response = await this.client.chat(endpointPath, body);\n\n // 使用适配器解析响应\n return this.adapter.parseChatResponse(response, options.model);\n }\n\n /**\n * 发送流式聊天请求\n */\n async *chatStream(\n options: ChatOptions\n ): AsyncGenerator<StreamChunk, void, unknown> {\n // 使用适配器构建请求体\n const body = this.adapter.buildChatRequest(options, true);\n\n // 获取端点 URL\n const endpoint = this.adapter.getEndpointUrl(this.baseUrl);\n // 从完整 URL 中提取路径部分\n const endpointPath = endpoint.replace(this.baseUrl, '');\n\n // 使用客户端发送流式请求\n const response = await this.client.chatStream(endpointPath, body);\n\n // 使用 StreamProcessor 处理流式响应\n // 使用适配器的 extractStreamChunk 方法作为 delta 提取器\n yield* StreamProcessor.processStream(response, delta =>\n this.adapter.extractStreamChunk(delta)\n );\n }\n}\n","/**\n * Poe Provider 实现\n * 使用 Poe API (OpenAI 兼容格式)\n * 使用 PoeAdapter 和 HttpProviderClient 进行重构\n * https://creator.poe.com/docs/external-applications/openai-compatible-api\n *\n * 支持模型:\n * - 所有 Poe 上的公开 bot,如 Claude-Opus-4.1, GPT-4o, Gemini-2.5-Pro 等\n * - 支持通过 extra_body 传递 reasoning_effort, thinking_budget 等参数\n *\n * 特点:\n * - 单一 API Key 访问数百个模型\n * - 使用 Poe 订阅点数,无需额外费用\n */\n\nimport { BaseProvider } from './__base__';\nimport type { ChatOptions, ChatResult, StreamChunk } from './__types__';\nimport { PoeAdapter } from '../adapters/poe-adapter';\nimport { HttpProviderClient } from '../client/http-provider-client';\nimport { StreamProcessor } from '../utils/stream-processor';\nimport type { ProviderClient } from '../client/types';\n\n/**\n * Poe Provider 配置\n */\nexport interface PoeConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\n/**\n * Poe Provider\n * 使用 Poe API,兼容 OpenAI 格式\n * 使用适配器模式重构,复用统一的工具层\n *\n * 注意:Poe 的流式响应需要特殊处理,支持多种思考格式:\n * 1. <think>...</think> 标签\n * 2. *Thinking...*\\n> ... 格式(DeepSeek 在 Poe 上的格式)\n */\nexport class PoeProvider extends BaseProvider {\n readonly name = 'poe';\n private adapter: PoeAdapter;\n private client: ProviderClient;\n private baseUrl: string;\n\n constructor(config: PoeConfig | string) {\n super();\n this.adapter = new PoeAdapter();\n\n if (typeof config === 'string') {\n this.baseUrl = this.adapter.defaultBaseUrl;\n this.client = new HttpProviderClient({\n apiKey: config,\n baseUrl: this.baseUrl,\n });\n } else {\n this.baseUrl = config.baseUrl ?? this.adapter.defaultBaseUrl;\n this.client = new HttpProviderClient({\n apiKey: config.apiKey,\n baseUrl: this.baseUrl,\n });\n }\n }\n\n /**\n * 发送聊天请求(非流式)\n */\n async chat(options: ChatOptions): Promise<ChatResult> {\n // 使用适配器构建请求体\n const body = this.adapter.buildChatRequest(options, false);\n\n // 获取端点 URL\n const endpoint = this.adapter.getEndpointUrl(this.baseUrl);\n // 从完整 URL 中提取路径部分\n const endpointPath = endpoint.replace(this.baseUrl, '');\n\n // 使用客户端发送请求\n const response = await this.client.chat(endpointPath, body);\n\n // 使用适配器解析响应(PoeAdapter 会处理 <think> 标签提取)\n return this.adapter.parseChatResponse(response, options.model);\n }\n\n /**\n * 发送流式聊天请求\n *\n * Poe 的流式响应需要特殊处理,支持多种思考格式:\n * 1. reasoning_content 字段(如果底层模型支持)\n * 2. <think>...</think> 标签\n * 3. *Thinking...*\\n> ... 格式\n */\n async *chatStream(\n options: ChatOptions\n ): AsyncGenerator<StreamChunk, void, unknown> {\n // 使用适配器构建请求体\n const body = this.adapter.buildChatRequest(options, true);\n\n // 获取端点 URL\n const endpoint = this.adapter.getEndpointUrl(this.baseUrl);\n // 从完整 URL 中提取路径部分\n const endpointPath = endpoint.replace(this.baseUrl, '');\n\n // 使用客户端发送流式请求\n const response = await this.client.chatStream(endpointPath, body);\n\n // Poe 需要特殊的流式处理逻辑来处理 <think> 标签和 *Thinking...* 格式\n // 因此使用自定义的流处理逻辑\n yield* this.processStreamWithThinkingExtraction(response);\n }\n\n /**\n * 处理流式响应,支持从内容中提取思考内容\n * 支持多种格式:\n * 1. reasoning_content 字段\n * 2. <think>...</think> 标签\n * 3. *Thinking...*\\n> ... 格式\n */\n private async *processStreamWithThinkingExtraction(\n response: Response\n ): AsyncGenerator<StreamChunk, void, unknown> {\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error('No response body');\n }\n\n const decoder = new TextDecoder();\n let buffer = '';\n // 用于追踪思考模式状态\n // 'none' | 'think_tag' | 'markdown_thinking' | 'markdown_quote'\n let thinkingMode:\n | 'none'\n | 'think_tag'\n | 'markdown_thinking'\n | 'markdown_quote' = 'none';\n let contentBuffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n\n for (const line of lines) {\n const data = StreamProcessor.parseSSELine(line);\n if (!data) continue;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const choices = data.choices as any[] | undefined;\n const delta = choices?.[0]?.delta as Record<string, unknown>;\n if (!delta) continue;\n\n // 思考内容(如果底层模型支持 reasoning_content)\n if (delta.reasoning_content) {\n yield {\n type: 'reasoning',\n text: StreamProcessor.extractTextContent(delta.reasoning_content),\n };\n continue;\n }\n\n // 处理 content\n if (delta.content) {\n const text = StreamProcessor.extractTextContent(delta.content);\n contentBuffer += text;\n\n // 检测并处理不同的思考格式\n // eslint-disable-next-line no-constant-condition\n while (true) {\n if (thinkingMode === 'none') {\n // 检测 <think> 标签\n const thinkStart = contentBuffer.indexOf('<think>');\n if (thinkStart !== -1) {\n if (thinkStart > 0) {\n yield {\n type: 'content',\n text: contentBuffer.slice(0, thinkStart),\n };\n }\n contentBuffer = contentBuffer.slice(thinkStart + 7);\n thinkingMode = 'think_tag';\n continue;\n }\n\n // 检测 *Thinking...* 格式\n const thinkingMatch = contentBuffer.match(\n /^\\*Thinking\\.{0,3}\\*\\s*\\n/\n );\n if (thinkingMatch) {\n contentBuffer = contentBuffer.slice(thinkingMatch[0].length);\n thinkingMode = 'markdown_thinking';\n continue;\n }\n\n // 没有思考标记,输出内容\n if (contentBuffer.length > 0) {\n // 保留可能不完整的标记\n const keepLen = Math.min(15, contentBuffer.length);\n const output = contentBuffer.slice(0, -keepLen) || '';\n if (output) {\n yield { type: 'content', text: output };\n contentBuffer = contentBuffer.slice(-keepLen);\n }\n }\n break;\n } else if (thinkingMode === 'think_tag') {\n // 在 <think> 标签内\n const endIdx = contentBuffer.indexOf('</think>');\n if (endIdx !== -1) {\n yield {\n type: 'reasoning',\n text: contentBuffer.slice(0, endIdx),\n };\n contentBuffer = contentBuffer.slice(endIdx + 8);\n thinkingMode = 'none';\n continue;\n }\n // 输出思考内容\n if (contentBuffer.length > 8) {\n yield { type: 'reasoning', text: contentBuffer.slice(0, -8) };\n contentBuffer = contentBuffer.slice(-8);\n }\n break;\n } else if (thinkingMode === 'markdown_thinking') {\n // 等待 > 引用块开始\n if (contentBuffer.startsWith('>')) {\n thinkingMode = 'markdown_quote';\n continue;\n }\n // 如果不是 > 开头,说明思考结束\n if (\n contentBuffer.length > 0 &&\n !contentBuffer.startsWith('>')\n ) {\n thinkingMode = 'none';\n continue;\n }\n break;\n } else if (thinkingMode === 'markdown_quote') {\n // 在 > 引用块内\n const newlineIdx = contentBuffer.indexOf('\\n');\n if (newlineIdx !== -1) {\n const quoteLine = contentBuffer.slice(0, newlineIdx);\n contentBuffer = contentBuffer.slice(newlineIdx + 1);\n\n // 如果是 > 开头,输出为思考内容\n if (quoteLine.startsWith('>')) {\n const thinkText = quoteLine.replace(/^>\\s?/, '');\n yield { type: 'reasoning', text: thinkText + '\\n' };\n continue;\n }\n\n // 如果是空行,继续等待(可能还有更多引用块)\n if (quoteLine.trim() === '') {\n yield { type: 'reasoning', text: '\\n' };\n continue;\n }\n\n // 非空非引用行,思考结束,这行是正文内容\n thinkingMode = 'none';\n yield { type: 'content', text: quoteLine + '\\n' };\n continue;\n }\n break;\n }\n }\n }\n }\n }\n\n // 输出剩余内容\n if (contentBuffer.length > 0) {\n if (thinkingMode === 'think_tag' || thinkingMode === 'markdown_quote') {\n yield { type: 'reasoning', text: contentBuffer };\n } else {\n yield { type: 'content', text: contentBuffer };\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n}\n","/**\n * AWS Nova Provider 实现\n * 使用 Amazon Nova API (OpenAI 兼容格式)\n * 使用 NovaAdapter 和 HttpProviderClient 进行重构\n * https://docs.aws.amazon.com/nova/\n *\n * 支持模型:\n * - nova-2-lite-v1: Nova 2 Lite 推理模型,支持 extended thinking\n * - nova-2-v1: Nova 2 标准模型\n * - nova-premier-v1: Nova Premier 高级模型\n *\n * 思考模式:\n * - Nova 2 Lite 支持 extended thinking (reasoningConfig)\n * - effort 映射为 maxReasoningEffort: low/medium/high\n */\n\nimport { BaseProvider } from './__base__';\nimport type { ChatOptions, ChatResult, StreamChunk } from './__types__';\nimport { NovaAdapter } from '../adapters/nova-adapter';\nimport { HttpProviderClient } from '../client/http-provider-client';\nimport { StreamProcessor } from '../utils/stream-processor';\nimport type { ProviderClient } from '../client/types';\n\n/**\n * AWS Nova Provider 配置\n */\nexport interface NovaConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\n/**\n * AWS Nova Provider\n * 使用 Amazon Nova API,兼容 OpenAI 格式\n * 使用适配器模式重构,复用统一的工具层\n */\nexport class NovaProvider extends BaseProvider {\n readonly name = 'nova';\n private adapter: NovaAdapter;\n private client: ProviderClient;\n private baseUrl: string;\n\n constructor(config: NovaConfig | string) {\n super();\n this.adapter = new NovaAdapter();\n\n if (typeof config === 'string') {\n this.baseUrl = this.adapter.defaultBaseUrl;\n this.client = new HttpProviderClient({\n apiKey: config,\n baseUrl: this.baseUrl,\n });\n } else {\n this.baseUrl = config.baseUrl ?? this.adapter.defaultBaseUrl;\n this.client = new HttpProviderClient({\n apiKey: config.apiKey,\n baseUrl: this.baseUrl,\n });\n }\n }\n\n /**\n * 发送聊天请求(非流式)\n *\n * 注意:\n * - Nova API 的 temperature 范围是 0-1(不是 0-2)\n * - Nova 2 Lite 支持 extended thinking (reasoningConfig)\n * - effort 映射为 maxReasoningEffort\n */\n async chat(options: ChatOptions): Promise<ChatResult> {\n // 使用适配器构建请求体\n const body = this.adapter.buildChatRequest(options, false);\n\n // 获取端点 URL\n const endpoint = this.adapter.getEndpointUrl(this.baseUrl);\n // 从完整 URL 中提取路径部分\n const endpointPath = endpoint.replace(this.baseUrl, '');\n\n // 使用客户端发送请求\n const response = await this.client.chat(endpointPath, body);\n\n // 使用适配器解析响应\n return this.adapter.parseChatResponse(response, options.model);\n }\n\n /**\n * 发送流式聊天请求\n */\n async *chatStream(\n options: ChatOptions\n ): AsyncGenerator<StreamChunk, void, unknown> {\n // 使用适配器构建请求体\n const body = this.adapter.buildChatRequest(options, true);\n\n // 获取端点 URL\n const endpoint = this.adapter.getEndpointUrl(this.baseUrl);\n // 从完整 URL 中提取路径部分\n const endpointPath = endpoint.replace(this.baseUrl, '');\n\n // 使用客户端发送流式请求\n const response = await this.client.chatStream(endpointPath, body);\n\n // 使用 StreamProcessor 处理流式响应\n // 使用适配器的 extractStreamChunk 方法作为 delta 提取器\n yield* StreamProcessor.processStream(response, delta =>\n this.adapter.extractStreamChunk(delta)\n );\n }\n}\n","/**\n * 工具层导出文件\n * 导出所有工具类和类型\n */\n\n// StreamProcessor - 流处理器\nexport { StreamProcessor } from './stream-processor';\nexport type { DeltaExtractor } from './stream-processor';\n\n// RequestBuilder - 请求构建器\nexport { RequestBuilder } from './request-builder';\n\n// ConfigValidator - 配置验证器\nexport { ConfigValidator } from './config-validator';\nexport type {\n ValidationResult,\n ValidationError,\n UnifiedProviderConfig,\n ProviderType,\n} from './config-validator';\n","/**\n * 客户端层导出\n * 导出所有客户端相关类型和类\n */\n\n// 类型导出\nexport type { ProviderClient, ProviderClientConfig } from './types';\n\n// 错误类导出\nexport { ProviderError, APIError, NetworkError, TimeoutError } from './types';\n\n// 客户端实现导出\nexport { HttpProviderClient } from './http-provider-client';\n","/**\n * Fluent API 错误类定义\n * 提供配置错误和验证错误的统一处理\n */\n\n/**\n * 配置错误\n * 在调用 ask() 时验证配置是否完整\n *\n * @example\n * ```typescript\n * // 未配置 API Key\n * throw new ConfigurationError('请先配置 API Key:调用 configure({ apiKey: \\'xxx\\' }) 或 fromEnv()');\n *\n * // 未调用 use()\n * throw new ConfigurationError('请先调用 use(provider) 选择服务提供商');\n * ```\n */\nexport class ConfigurationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ConfigurationError';\n // 保持正确的原型链\n Object.setPrototypeOf(this, ConfigurationError.prototype);\n }\n}\n\n/**\n * 验证错误\n * 在设置参数时验证参数是否有效\n *\n * @example\n * ```typescript\n * // temperature 超出范围\n * throw new ValidationError('temperature 必须在 0-2 之间');\n *\n * // 无效的 Provider\n * throw new ValidationError('不支持的 Provider: xxx,支持的 Provider: deepseek, openrouter, ...');\n * ```\n */\nexport class ValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ValidationError';\n // 保持正确的原型链\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n}\n","/**\n * Fluent API 链式构建器实现\n * 支持流畅的方法链配置请求参数\n */\n\nimport type {\n OiiaiBuilder,\n StreamBuilder,\n BuilderConfig,\n ReasoningConfig,\n StreamChunk,\n ProviderType,\n} from './types';\nimport { ProviderRegistry } from '../registry/provider-registry';\nimport { ConfigurationError, ValidationError } from './errors';\n\n/**\n * 构建器实现类\n * 实现 OiiaiBuilder 和 StreamBuilder 接口\n */\nexport class OiiaiBuilderImpl implements OiiaiBuilder {\n /** 内部配置状态 */\n protected config: BuilderConfig = {};\n\n /**\n * 创建构建器实例\n * @param initialConfig - 可选的初始配置\n */\n constructor(initialConfig?: Partial<BuilderConfig>) {\n if (initialConfig) {\n this.config = { ...initialConfig };\n }\n }\n\n /**\n * 选择服务提供商\n * @param provider - Provider 类型\n * @returns this 支持链式调用\n */\n use(provider: ProviderType): this {\n // 验证 provider 类型是否有效\n if (!ProviderRegistry.hasAdapter(provider)) {\n const supported = ProviderRegistry.listSupported();\n throw new ValidationError(\n `不支持的 Provider: ${provider},支持的 Provider: ${supported.join(', ')}`\n );\n }\n this.config.provider = provider;\n return this;\n }\n\n /**\n * 指定模型\n * @param modelId - 模型 ID\n * @returns this 支持链式调用\n */\n model(modelId: string): this {\n this.config.model = modelId;\n return this;\n }\n\n /**\n * 设置系统提示词\n * @param prompt - 系统提示词\n * @returns this 支持链式调用\n */\n system(prompt: string): this {\n this.config.system = prompt;\n return this;\n }\n\n /**\n * 设置温度参数\n * @param value - 温度值 (0-2)\n * @returns this 支持链式调用\n */\n temperature(value: number): this {\n if (value < 0 || value > 2) {\n throw new ValidationError('temperature 必须在 0-2 之间');\n }\n this.config.temperature = value;\n return this;\n }\n\n /**\n * 设置最大输出 token 数\n * @param value - token 数量\n * @returns this 支持链式调用\n */\n maxTokens(value: number): this {\n this.config.maxTokens = value;\n return this;\n }\n\n /**\n * 配置思考/推理模式\n * @param config - 推理配置\n * @returns this 支持链式调用\n */\n reasoning(config: ReasoningConfig): this {\n this.config.reasoning = config;\n return this;\n }\n\n /**\n * 设置 API Key\n * @param apiKey - API Key\n * @returns this 支持链式调用\n */\n key(apiKey: string): this {\n this.config.apiKey = apiKey;\n return this;\n }\n\n /**\n * 设置基础 URL\n * @param url - 基础 URL\n * @returns this 支持链式调用\n */\n baseUrl(url: string): this {\n this.config.baseUrl = url;\n return this;\n }\n\n /**\n * 标记为流式请求\n * 调用后 ask() 将返回 AsyncGenerator\n * @returns StreamBuilder 类型\n */\n stream(): StreamBuilder {\n this.config.isStream = true;\n // 返回 this,但类型转换为 StreamBuilder\n return this as unknown as StreamBuilder;\n }\n\n /**\n * 执行请求\n * 非流式模式返回 Promise<string>\n * 流式模式(调用 stream() 后)返回 AsyncGenerator<StreamChunk>\n * @param question - 问题\n * @returns 响应内容或流式数据块生成器\n */\n ask(question: string): Promise<string>;\n ask(question: string): AsyncGenerator<StreamChunk>;\n ask(question: string): Promise<string> | AsyncGenerator<StreamChunk> {\n // 验证必需参数\n this.validateConfig();\n\n // 创建 Provider 实例\n const adapter = ProviderRegistry.getAdapter(this.config.provider!);\n const client = adapter.createClient({\n apiKey: this.config.apiKey!,\n baseUrl: this.config.baseUrl ?? adapter.defaultBaseUrl,\n });\n\n // 构建消息列表\n const messages: Array<{\n role: 'system' | 'user' | 'assistant';\n content: string;\n }> = [];\n if (this.config.system) {\n messages.push({ role: 'system', content: this.config.system });\n }\n messages.push({ role: 'user', content: question });\n\n // 构建请求选项\n const chatOptions = {\n model: this.config.model!,\n messages,\n temperature: this.config.temperature,\n maxTokens: this.config.maxTokens,\n reasoning: this.config.reasoning,\n };\n\n // 根据是否流式决定执行方式\n if (this.config.isStream) {\n // 流式请求返回 AsyncGenerator\n return this.executeStreamRequest(adapter, client, chatOptions);\n }\n\n // 非流式请求\n return this.executeNonStreamRequest(adapter, client, chatOptions);\n }\n\n /**\n * 执行非流式请求\n * @param adapter - Provider 适配器\n * @param client - Provider 客户端\n * @param chatOptions - 聊天选项\n * @returns 响应内容\n */\n protected async executeNonStreamRequest(\n adapter: ReturnType<typeof ProviderRegistry.getAdapter>,\n client: ReturnType<\n ReturnType<typeof ProviderRegistry.getAdapter>['createClient']\n >,\n chatOptions: {\n model: string;\n messages: Array<{\n role: 'system' | 'user' | 'assistant';\n content: string;\n }>;\n temperature?: number;\n maxTokens?: number;\n reasoning?: ReasoningConfig;\n }\n ): Promise<string> {\n const baseUrl = this.config.baseUrl ?? adapter.defaultBaseUrl;\n const endpoint = adapter.getEndpointUrl(baseUrl);\n const endpointPath = endpoint.replace(baseUrl, '');\n const body = adapter.buildChatRequest(chatOptions, false);\n\n const response = await client.chat(endpointPath, body);\n const result = adapter.parseChatResponse(response, this.config.model!);\n\n return result.content;\n }\n\n /**\n * 执行流式请求\n * @param adapter - Provider 适配器\n * @param client - Provider 客户端\n * @param chatOptions - 聊天选项\n * @returns 流式数据块生成器\n */\n protected async *executeStreamRequest(\n adapter: ReturnType<typeof ProviderRegistry.getAdapter>,\n client: ReturnType<\n ReturnType<typeof ProviderRegistry.getAdapter>['createClient']\n >,\n chatOptions: {\n model: string;\n messages: Array<{\n role: 'system' | 'user' | 'assistant';\n content: string;\n }>;\n temperature?: number;\n maxTokens?: number;\n reasoning?: ReasoningConfig;\n }\n ): AsyncGenerator<StreamChunk> {\n const baseUrl = this.config.baseUrl ?? adapter.defaultBaseUrl;\n const endpoint = adapter.getEndpointUrl(baseUrl);\n const endpointPath = endpoint.replace(baseUrl, '');\n const body = adapter.buildChatRequest(chatOptions, true);\n\n const response = await client.chatStream(endpointPath, body);\n\n // 使用 StreamProcessor 处理流式响应\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { StreamProcessor } = require('../utils/stream-processor');\n\n yield* StreamProcessor.processStream(\n response,\n (delta: Record<string, unknown>) => adapter.extractStreamChunk(delta)\n );\n }\n\n /**\n * 验证配置是否完整\n * @throws ConfigurationError 如果缺少必需参数\n */\n protected validateConfig(): void {\n if (!this.config.provider) {\n throw new ConfigurationError('请先调用 use(provider) 选择服务提供商');\n }\n if (!this.config.model) {\n throw new ConfigurationError('请先调用 model(modelId) 指定模型');\n }\n if (!this.config.apiKey) {\n throw new ConfigurationError(\n '请先配置 API Key:调用 key(apiKey) 或通过预设实例配置'\n );\n }\n }\n\n /**\n * 获取当前配置(用于测试)\n * @returns 当前配置的副本\n */\n getConfig(): BuilderConfig {\n return { ...this.config };\n }\n\n /**\n * 克隆构建器(用于创建新实例)\n * @returns 新的构建器实例\n */\n clone(): OiiaiBuilderImpl {\n return new OiiaiBuilderImpl({ ...this.config });\n }\n}\n\n/**\n * 创建新的构建器实例\n * @param initialConfig - 可选的初始配置\n * @returns 构建器实例\n */\nexport function createBuilder(\n initialConfig?: Partial<BuilderConfig>\n): OiiaiBuilder {\n return new OiiaiBuilderImpl(initialConfig);\n}\n\n/**\n * 全局构建器入口\n * 每次访问返回新实例,避免状态污染\n */\nexport const oiiai: OiiaiBuilder = new Proxy({} as OiiaiBuilder, {\n get(_target, prop: string) {\n // 每次访问属性时创建新实例\n const builder = new OiiaiBuilderImpl();\n const value = (builder as unknown as Record<string, unknown>)[prop];\n // 如果是方法,绑定到 builder 实例\n if (typeof value === 'function') {\n return value.bind(builder);\n }\n return value;\n },\n});\n","/**\n * 预设实例实现\n * 提供快捷的 AI 调用方法,预配置了 Provider 类型\n */\n\nimport type {\n PresetProvider,\n PresetConfigOptions,\n AskOptions,\n StreamCallbacks,\n ChatSessionOptions,\n ChatSession,\n OiiaiBuilder,\n StreamChunk,\n ProviderType,\n} from './types';\nimport { OiiaiBuilderImpl } from './builder';\nimport { ProviderRegistry } from '../registry/provider-registry';\nimport { ConfigurationError, ValidationError } from './errors';\n\n/**\n * 预设实例配置状态\n */\ninterface PresetConfig {\n /** API Key */\n apiKey?: string;\n /** 基础 URL */\n baseUrl?: string;\n}\n\n/**\n * 预设实例实现类\n * 提供快捷的 AI 调用方法\n */\nexport class PresetProviderImpl implements PresetProvider {\n /** Provider 名称 */\n readonly name: ProviderType;\n\n /** 内部配置状态 */\n private config: PresetConfig = {};\n\n /** 环境变量名称映射 */\n private static readonly ENV_KEY_MAP: Record<ProviderType, string> = {\n deepseek: 'DEEPSEEK_API_KEY',\n openrouter: 'OPENROUTER_API_KEY',\n gemini: 'GEMINI_API_KEY',\n groq: 'GROQ_API_KEY',\n huggingface: 'HUGGINGFACE_API_KEY',\n modelscope: 'MODELSCOPE_API_KEY',\n poe: 'POE_API_KEY',\n nova: 'NOVA_API_KEY',\n };\n\n /**\n * 创建预设实例\n * @param providerType - Provider 类型\n */\n constructor(providerType: ProviderType) {\n // 验证 provider 类型是否有效\n if (!ProviderRegistry.hasAdapter(providerType)) {\n const supported = ProviderRegistry.listSupported();\n throw new ValidationError(\n `不支持的 Provider: ${providerType},支持的 Provider: ${supported.join(', ')}`\n );\n }\n this.name = providerType;\n }\n\n /**\n * 配置 API Key 和其他选项\n * @param options - 配置选项\n * @returns this 支持链式调用\n */\n configure(options: PresetConfigOptions): this {\n this.config.apiKey = options.apiKey;\n if (options.baseUrl) {\n this.config.baseUrl = options.baseUrl;\n }\n return this;\n }\n\n /**\n * 从环境变量读取配置\n * 环境变量名格式: {PROVIDER}_API_KEY (如 DEEPSEEK_API_KEY)\n * @returns this 支持链式调用\n */\n fromEnv(): this {\n const envKey = PresetProviderImpl.ENV_KEY_MAP[this.name];\n const apiKey = process.env[envKey];\n\n if (!apiKey) {\n throw new ConfigurationError(`环境变量 ${envKey} 未设置`);\n }\n\n this.config.apiKey = apiKey;\n return this;\n }\n\n /**\n * 简单问答(非流式)\n * @param model - 模型 ID\n * @param question - 问题\n * @param options - 可选配置\n * @returns 响应内容\n */\n async ask(\n model: string,\n question: string,\n options?: AskOptions\n ): Promise<string> {\n // 验证 API Key\n this.validateApiKey();\n\n // 创建构建器并执行非流式请求\n const builder = this.createConfiguredBuilder(model, options);\n // 直接调用内部方法,确保返回 Promise<string>\n const result = builder.ask(question);\n // 类型断言:非流式模式下返回 Promise<string>\n return result as Promise<string>;\n }\n\n /**\n * 流式问答\n * @param model - 模型 ID\n * @param question - 问题\n * @param options - 可选配置\n * @returns 流式数据块生成器\n */\n async *stream(\n model: string,\n question: string,\n options?: AskOptions\n ): AsyncGenerator<StreamChunk> {\n // 验证 API Key\n this.validateApiKey();\n\n // 创建构建器并执行流式请求\n const builder = this.createConfiguredBuilder(model, options);\n const streamBuilder = builder.stream();\n yield* streamBuilder.ask(question);\n }\n\n /**\n * 带回调的流式问答\n * @param model - 模型 ID\n * @param question - 问题\n * @param callbacks - 回调函数\n * @returns Promise,完成时 resolve\n */\n async streamWithCallbacks(\n model: string,\n question: string,\n callbacks: StreamCallbacks\n ): Promise<void> {\n // 验证 API Key\n this.validateApiKey();\n\n // 累积内容\n let reasoningContent = '';\n let contentText = '';\n\n // 创建构建器并执行流式请求\n const builder = this.createConfiguredBuilder(model);\n const streamBuilder = builder.stream();\n\n for await (const chunk of streamBuilder.ask(question)) {\n if (chunk.type === 'reasoning') {\n reasoningContent += chunk.text;\n callbacks.onReasoning?.(chunk.text);\n } else if (chunk.type === 'content') {\n contentText += chunk.text;\n callbacks.onContent?.(chunk.text);\n }\n }\n\n // 调用完成回调\n callbacks.onDone?.({\n reasoning: reasoningContent,\n content: contentText,\n });\n }\n\n /**\n * 获取构建器(预配置 provider 和 model)\n * @param model - 模型 ID\n * @returns 预配置的构建器\n */\n builder(model: string): OiiaiBuilder {\n // 验证 API Key\n this.validateApiKey();\n\n // 创建预配置的构建器\n const adapter = ProviderRegistry.getAdapter(this.name);\n const builder = new OiiaiBuilderImpl({\n provider: this.name,\n model,\n apiKey: this.config.apiKey,\n baseUrl: this.config.baseUrl ?? adapter.defaultBaseUrl,\n });\n\n // 类型断言:OiiaiBuilderImpl 实现了 OiiaiBuilder 接口\n // ask() 在非流式模式下返回 Promise<string>\n return builder as unknown as OiiaiBuilder;\n }\n\n /**\n * 创建多轮对话会话\n * @param model - 模型 ID\n * @param options - 会话配置\n * @returns 对话会话实例\n */\n chat(model: string, options?: ChatSessionOptions): ChatSession {\n // 验证 API Key\n this.validateApiKey();\n\n // 延迟导入以避免循环依赖\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { ChatSessionImpl } = require('./chat-session');\n return new ChatSessionImpl(this, model, options);\n }\n\n /**\n * 验证 API Key 是否已配置\n * @throws ConfigurationError 如果未配置 API Key\n */\n private validateApiKey(): void {\n if (!this.config.apiKey) {\n throw new ConfigurationError(\n `请先配置 API Key:调用 configure({ apiKey: 'xxx' }) 或 fromEnv()`\n );\n }\n }\n\n /**\n * 创建已配置的构建器\n * @param model - 模型 ID\n * @param options - 可选配置\n * @returns 配置好的构建器\n */\n private createConfiguredBuilder(\n model: string,\n options?: AskOptions\n ): OiiaiBuilderImpl {\n const adapter = ProviderRegistry.getAdapter(this.name);\n const builder = new OiiaiBuilderImpl({\n provider: this.name,\n model,\n apiKey: this.config.apiKey,\n baseUrl: this.config.baseUrl ?? adapter.defaultBaseUrl,\n });\n\n // 应用可选配置\n if (options?.system) {\n builder.system(options.system);\n }\n if (options?.temperature !== undefined) {\n builder.temperature(options.temperature);\n }\n if (options?.maxTokens !== undefined) {\n builder.maxTokens(options.maxTokens);\n }\n if (options?.reasoning) {\n builder.reasoning(options.reasoning);\n }\n\n return builder;\n }\n\n /**\n * 获取当前配置(用于测试)\n * @returns 当前配置的副本\n */\n getConfig(): PresetConfig {\n return { ...this.config };\n }\n}\n\n/**\n * 创建预设实例\n * @param providerType - Provider 类型\n * @returns 预设实例\n */\nexport function createPresetProvider(\n providerType: ProviderType\n): PresetProvider {\n return new PresetProviderImpl(providerType);\n}\n","/**\n * Fluent API 模块入口\n * 导出所有类型和实现\n */\n\n// 导出类型定义\nexport type {\n // 选项类型\n AskOptions,\n StreamCallbacks,\n ChatSessionOptions,\n PresetConfigOptions,\n BuilderConfig,\n // 接口类型\n OiiaiBuilder,\n StreamBuilder,\n ChatSession,\n PresetProvider,\n // 重新导出的类型\n ProviderType,\n ChatMessage,\n ReasoningConfig,\n StreamChunk,\n ChatResult,\n} from './types';\n\n// 导出构建器实现\nexport { OiiaiBuilderImpl, createBuilder, oiiai } from './builder';\n\n// 导出预设实例实现\nexport { PresetProviderImpl, createPresetProvider } from './preset-provider';\n\n// 导出对话会话实现\nexport { ChatSessionImpl } from './chat-session';\n\n// 导出错误类\nexport { ConfigurationError, ValidationError } from './errors';\n\n// 导出所有预设实例\nexport {\n deepseek,\n openrouter,\n gemini,\n groq,\n huggingface,\n modelscope,\n poe,\n nova,\n} from './preset-instances';\n","/**\n * 预设实例导出\n * 提供所有 Provider 的预配置实例\n *\n * @example\n * ```typescript\n * import { deepseek, openrouter, gemini } from 'oiiai';\n *\n * // 配置并使用\n * deepseek.configure({ apiKey: 'your-key' });\n * const answer = await deepseek.ask('deepseek-chat', '你好');\n *\n * // 或从环境变量读取\n * openrouter.fromEnv();\n * const stream = openrouter.stream('gpt-4o', '写首诗');\n * ```\n */\n\nimport { PresetProviderImpl } from './preset-provider';\nimport type { PresetProvider } from './types';\n\n/**\n * DeepSeek 预设实例\n * 环境变量: DEEPSEEK_API_KEY\n */\nexport const deepseek: PresetProvider = new PresetProviderImpl('deepseek');\n\n/**\n * OpenRouter 预设实例\n * 环境变量: OPENROUTER_API_KEY\n */\nexport const openrouter: PresetProvider = new PresetProviderImpl('openrouter');\n\n/**\n * Gemini 预设实例\n * 环境变量: GEMINI_API_KEY\n */\nexport const gemini: PresetProvider = new PresetProviderImpl('gemini');\n\n/**\n * Groq 预设实例\n * 环境变量: GROQ_API_KEY\n */\nexport const groq: PresetProvider = new PresetProviderImpl('groq');\n\n/**\n * HuggingFace 预设实例\n * 环境变量: HUGGINGFACE_API_KEY\n */\nexport const huggingface: PresetProvider = new PresetProviderImpl(\n 'huggingface'\n);\n\n/**\n * ModelScope 预设实例\n * 环境变量: MODELSCOPE_API_KEY\n */\nexport const modelscope: PresetProvider = new PresetProviderImpl('modelscope');\n\n/**\n * Poe 预设实例\n * 环境变量: POE_API_KEY\n */\nexport const poe: PresetProvider = new PresetProviderImpl('poe');\n\n/**\n * Nova 预设实例\n * 环境变量: NOVA_API_KEY\n */\nexport const nova: PresetProvider = new PresetProviderImpl('nova');\n"],"mappings":"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","names":["init_types","init_types","HttpProviderClient","StreamProcessor","DEFAULT_BASE_URL","StreamProcessor","DEFAULT_BASE_URL","StreamProcessor","DEFAULT_BASE_URL","StreamProcessor","DEFAULT_BASE_URL","StreamProcessor","DEFAULT_BASE_URL","StreamProcessor","DEFAULT_BASE_URL","StreamProcessor","DEFAULT_BASE_URL","StreamProcessor","VALID_PROVIDERS","StreamProcessor","init_types","StreamProcessor","ChatSessionImpl"]}
|