@astack-tech/integrations 0.1.1-beta.4 → 0.1.1-beta.5

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/dist/index.cjs CHANGED
@@ -185,6 +185,19 @@ var Deepseek = class extends import_core.Component {
185
185
  }))
186
186
  };
187
187
  }
188
+ if (chunk.usage) {
189
+ yield {
190
+ role: "assistant",
191
+ content: "",
192
+ usage: {
193
+ completion_tokens: chunk.usage.completion_tokens || 0,
194
+ prompt_tokens: chunk.usage.prompt_tokens || 0,
195
+ prompt_cache_hit_tokens: chunk.usage.prompt_cache_hit_tokens,
196
+ prompt_cache_miss_tokens: chunk.usage.prompt_cache_miss_tokens,
197
+ total_tokens: chunk.usage.total_tokens || 0
198
+ }
199
+ };
200
+ }
188
201
  }
189
202
  }
190
203
  /**
@@ -244,6 +257,16 @@ var Deepseek = class extends import_core.Component {
244
257
  role: "assistant",
245
258
  content: responseMessage.content || ""
246
259
  };
260
+ if (response.usage) {
261
+ const usage = response.usage;
262
+ result.usage = {
263
+ completion_tokens: usage.completion_tokens || 0,
264
+ prompt_tokens: usage.prompt_tokens || 0,
265
+ prompt_cache_hit_tokens: usage.prompt_cache_hit_tokens,
266
+ prompt_cache_miss_tokens: usage.prompt_cache_miss_tokens,
267
+ total_tokens: usage.total_tokens || 0
268
+ };
269
+ }
247
270
  if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {
248
271
  result.tool_calls = responseMessage.tool_calls.map((toolCall) => {
249
272
  let args;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/model-provider/index.ts","../src/model-provider/deepseek/index.ts"],"sourcesContent":["/**\n * Astack 集成包\n *\n * 提供与各种外部服务和平台的集成组件\n */\n\n// 导出模型提供者组件\nexport * as ModelProvider from './model-provider';\n","export {\n default as Deepseek,\n type Message as DeepseekMessage,\n type ToolCall as DeepseekToolCall,\n type DeepseekConfig,\n type MessageRole as DeepseekMessageRole,\n} from './deepseek';\n","import { Component } from '@astack-tech/core';\nimport OpenAI from 'openai';\n\n/**\n * Deepseek 模型提供者配置\n */\nexport interface DeepseekConfig {\n /**\n * API 密钥\n */\n apiKey: string;\n\n /**\n * 使用的模型名称\n * 默认为 'deepseek-chat'\n */\n model?: string;\n\n /**\n * 自定义 API 基础 URL\n * 默认为 Deepseek 官方 API 地址\n */\n baseURL?: string;\n\n /**\n * 温度参数,控制输出的随机性\n */\n temperature?: number;\n\n /**\n * 最大生成的 token 数\n */\n maxTokens?: number;\n\n /**\n * 采样概率\n */\n topP?: number;\n\n /**\n * 系统提示消息\n */\n systemPrompt?: string;\n\n /**\n * 工具实例数组,直接传递工具实例\n * 每个工具应具有 name、description 和 parameters 属性\n */\n rawTools?: Array<{\n name: string;\n description: string;\n parameters?: Record<string, unknown>;\n }>;\n\n /**\n * API 格式的工具定义数组,与 rawTools 二选一\n * 使用 OpenAI 兼容的工具定义格式\n */\n tools?: unknown[];\n\n /**\n * dangerouslyAllowBrowser\n * 是否允许在浏览器等非安全环境内运行\n */\n dangerouslyAllowBrowser?: boolean;\n}\n\n/**\n * 消息角色类型\n */\nexport type MessageRole = 'system' | 'user' | 'assistant' | 'tool';\n\n/**\n * 工具调用\n */\nexport interface ToolCall {\n /**\n * 工具调用 ID\n */\n id?: string;\n\n /**\n * 工具名称\n */\n tool_name: string;\n\n /**\n * 工具调用参数\n */\n arguments: Record<string, unknown>;\n}\n\n/**\n * 对话消息类型\n */\nexport interface Message {\n /**\n * 消息角色\n */\n role: MessageRole;\n\n /**\n * 消息内容\n */\n content?: string;\n\n /**\n * 工具调用\n */\n tool_calls?: ToolCall[];\n\n /**\n * 工具调用 ID,用于工具响应消息\n */\n tool_call_id?: string;\n}\n\n/**\n * Deepseek 组件\n *\n * 使用 OpenAI 兼容接口调用 Deepseek 模型\n *\n * 输入:\n * - prompt: 文本提示\n * - messages: 对话消息数组\n *\n * 输出:\n * - completion: 生成的文本完成\n * - message: 生成的响应消息\n */\nclass Deepseek extends Component {\n // OpenAI 客户端实例\n private client: OpenAI;\n\n // 配置选项\n private model: string;\n private temperature: number;\n private maxTokens?: number;\n private topP?: number;\n private systemPrompt?: string;\n private tools?: unknown[];\n\n constructor(config: DeepseekConfig) {\n super({});\n\n // 配置客户端\n this.client = new OpenAI({\n apiKey: config.apiKey,\n baseURL: config.baseURL || 'https://api.deepseek.com/v1',\n dangerouslyAllowBrowser: config.dangerouslyAllowBrowser ?? false,\n });\n\n // 保存基本配置\n this.model = config.model || 'deepseek-chat';\n this.temperature = config.temperature ?? 0.7;\n this.maxTokens = config.maxTokens;\n this.topP = config.topP;\n this.systemPrompt = config.systemPrompt;\n\n // 处理工具配置,优先使用 rawTools\n if (config.rawTools && config.rawTools.length > 0) {\n // 将工具实例转换为 API 格式\n this.tools = config.rawTools.map(tool => ({\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters || {},\n },\n }));\n } else {\n // 使用直接提供的 API 格式工具\n this.tools = config.tools;\n }\n\n // 重命名端口\n Component.Port.I('prompt').attach(this);\n Component.Port.I('messages').attach(this);\n Component.Port.O('completion').attach(this);\n Component.Port.O('message').attach(this);\n }\n\n /**\n * 生成文本完成\n * @param prompt 提示文本\n * @returns 生成的文本\n */\n async generateCompletion(prompt: string): Promise<string> {\n const messages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n messages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提示\n messages.push({\n role: 'user',\n content: prompt,\n });\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 如果有工具定义,添加到请求中\n if (this.tools && this.tools.length > 0) {\n requestParams.tools = this.tools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 处理工具调用结果\n if (\n response.choices[0].message.tool_calls &&\n response.choices[0].message.tool_calls.length > 0\n ) {\n return JSON.stringify(response.choices[0].message);\n }\n\n return response.choices[0].message.content || '';\n }\n\n /**\n * 流式处理对话消息\n * @param messages 对话消息数组\n * @param options 可选的调用选项,包含临时工具列表\n * @returns 生成的流式响应消息异步生成器\n */\n async *streamChatCompletion(\n messages: Message[],\n options?: { temporaryTools?: unknown[] }\n ): AsyncGenerator<Partial<Message>> {\n // 转换消息格式 (复用现有逻辑)\n const formattedMessages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n formattedMessages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提供的消息\n formattedMessages.push(\n ...messages.map(msg => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const formattedMsg: any = {\n role: msg.role,\n content: msg.content,\n };\n\n if (msg.role === 'tool' && msg.tool_call_id) {\n formattedMsg.tool_call_id = msg.tool_call_id;\n }\n\n return formattedMsg;\n })\n );\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages: formattedMessages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n stream: true, // 开启流式模式\n };\n\n // 决定使用哪些工具\n const toolsToUse = options?.temporaryTools || this.tools;\n\n // 如果有工具定义,添加到请求中\n if (toolsToUse && toolsToUse.length > 0) {\n const formattedTools = toolsToUse.map(tool => {\n type ToolType = {\n type?: string;\n name?: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n\n const typedTool = tool as ToolType;\n\n if (typedTool.type === 'function') {\n return tool;\n }\n\n return {\n type: 'function',\n function: {\n name: typedTool.name,\n description: typedTool.description,\n parameters: typedTool.parameters || {},\n },\n };\n });\n\n requestParams.tools = formattedTools;\n }\n\n // 调用流式 API\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const stream = (await this.client.chat.completions.create(requestParams)) as any;\n\n // 处理流式响应\n for await (const chunk of stream) {\n const delta = chunk.choices[0]?.delta;\n\n if (delta?.content) {\n // 流式文本内容\n yield {\n role: 'assistant',\n content: delta.content,\n };\n }\n\n if (delta?.tool_calls) {\n // 流式工具调用(如果需要)\n yield {\n role: 'assistant',\n content: '',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n tool_calls: delta.tool_calls.map((toolCall: any) => ({\n id: toolCall.id || '',\n function: {\n name: toolCall.function?.name || '',\n arguments: toolCall.function?.arguments || '',\n },\n type: 'function',\n tool_name: toolCall.function?.name || '',\n arguments: toolCall.function?.arguments || '',\n })),\n };\n }\n }\n }\n\n /**\n * 处理对话消息\n * @param messages 对话消息数组\n * @param options 可选的调用选项,包含临时工具列表\n * @returns 生成的响应消息\n */\n async chatCompletion(\n messages: Message[],\n options?: { temporaryTools?: unknown[] }\n ): Promise<Message> {\n // 转换消息格式\n const formattedMessages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n formattedMessages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提供的消息\n formattedMessages.push(\n ...messages.map(msg => {\n // 基本消息结构\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const formattedMsg: any = {\n role: msg.role,\n content: msg.content,\n };\n\n // 如果有工具调用 ID,添加到消息中\n if (msg.role === 'tool' && msg.tool_call_id) {\n formattedMsg.tool_call_id = msg.tool_call_id;\n }\n\n return formattedMsg;\n })\n );\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages: formattedMessages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 决定使用哪些工具\n // 如果提供了临时工具,优先使用临时工具\n const toolsToUse = options?.temporaryTools || this.tools;\n\n // 如果有工具定义,添加到请求中\n if (toolsToUse && toolsToUse.length > 0) {\n // 检查工具格式并转换,确保符合 Deepseek API 要求\n const formattedTools = toolsToUse.map(tool => {\n // 使用类型断言来处理 unknown 类型\n type ToolType = {\n type?: string;\n name?: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n\n const typedTool = tool as ToolType;\n\n // 如果工具已经是 API 格式,直接返回\n if (typedTool.type === 'function') {\n return tool;\n }\n\n // 如果是简单工具实例,转换为 API 格式\n return {\n type: 'function',\n function: {\n name: typedTool.name,\n description: typedTool.description,\n parameters: typedTool.parameters || {},\n },\n };\n });\n\n requestParams.tools = formattedTools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 解析响应\n const responseMessage = response.choices[0].message;\n\n // 转换为内部消息格式\n const result: Message = {\n role: 'assistant',\n content: responseMessage.content || '',\n };\n\n // 如果有工具调用,添加到结果中\n if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {\n // 为了兼容 Agent 组件期望的格式,保留 function 和 type 字段\n // 同时为了满足内部 ToolCall 接口,也添加 tool_name 和 arguments 字段\n result.tool_calls = responseMessage.tool_calls.map(toolCall => {\n // 解析参数,确保是对象形式\n let args: Record<string, unknown>;\n\n const rawArgs = toolCall.function.arguments;\n\n if (typeof rawArgs === 'string') {\n const raw = rawArgs;\n try {\n args = raw && raw.trim().length > 0 ? (JSON.parse(raw) as Record<string, unknown>) : {};\n } catch {\n args = {};\n }\n } else if (rawArgs && typeof rawArgs === 'object') {\n args = rawArgs as Record<string, unknown>;\n } else {\n args = {};\n }\n\n return {\n id: toolCall.id,\n // 满足 Agent 组件期望的格式\n function: {\n name: toolCall.function.name,\n arguments: toolCall.function.arguments || '{}',\n },\n type: 'function',\n // 满足内部 ToolCall 接口\n tool_name: toolCall.function.name,\n arguments: args,\n };\n });\n }\n\n return result;\n }\n\n /**\n * 在独立模式下运行组件\n * @param input 输入参数,可以是提示文本或对话消息数组\n * @returns 生成的文本或响应消息\n */\n async run(input: string | Message[]): Promise<string | Message> {\n if (typeof input === 'string') {\n return this.generateCompletion(input);\n } else {\n return this.chatCompletion(input);\n }\n }\n\n /**\n * 在流水线中运行组件\n * @param $i 输入端口\n * @param $o 输出端口\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n _transform($i: any, $o: any) {\n // 处理文本提示输入\n $i('prompt').receive(async (prompt: string) => {\n try {\n const completion = await this.generateCompletion(prompt);\n $o('completion').send(completion);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('completion').send('API 调用错误');\n }\n });\n\n // 处理对话消息输入\n $i('messages').receive(async (messages: Message[]) => {\n try {\n const responseMessage = await this.chatCompletion(messages);\n $o('message').send(responseMessage);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('message').send({\n role: 'assistant',\n content: 'API 调用错误',\n });\n }\n });\n }\n}\n\n// 默认导出组件\nexport default Deepseek;\n"],"mappings":"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","names":["OpenAI"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/model-provider/index.ts","../src/model-provider/deepseek/index.ts"],"sourcesContent":["/**\n * Astack 集成包\n *\n * 提供与各种外部服务和平台的集成组件\n */\n\n// 导出模型提供者组件\nexport * as ModelProvider from './model-provider';\n","export {\n default as Deepseek,\n type Message as DeepseekMessage,\n type ToolCall as DeepseekToolCall,\n type DeepseekConfig,\n type MessageRole as DeepseekMessageRole,\n} from './deepseek';\n","import { Component } from '@astack-tech/core';\nimport OpenAI from 'openai';\n\n/**\n * Deepseek 模型提供者配置\n */\nexport interface DeepseekConfig {\n /**\n * API 密钥\n */\n apiKey: string;\n\n /**\n * 使用的模型名称\n * 默认为 'deepseek-chat'\n */\n model?: string;\n\n /**\n * 自定义 API 基础 URL\n * 默认为 Deepseek 官方 API 地址\n */\n baseURL?: string;\n\n /**\n * 温度参数,控制输出的随机性\n */\n temperature?: number;\n\n /**\n * 最大生成的 token 数\n */\n maxTokens?: number;\n\n /**\n * 采样概率\n */\n topP?: number;\n\n /**\n * 系统提示消息\n */\n systemPrompt?: string;\n\n /**\n * 工具实例数组,直接传递工具实例\n * 每个工具应具有 name、description 和 parameters 属性\n */\n rawTools?: Array<{\n name: string;\n description: string;\n parameters?: Record<string, unknown>;\n }>;\n\n /**\n * API 格式的工具定义数组,与 rawTools 二选一\n * 使用 OpenAI 兼容的工具定义格式\n */\n tools?: unknown[];\n\n /**\n * dangerouslyAllowBrowser\n * 是否允许在浏览器等非安全环境内运行\n */\n dangerouslyAllowBrowser?: boolean;\n}\n\n/**\n * 消息角色类型\n */\nexport type MessageRole = 'system' | 'user' | 'assistant' | 'tool';\n\n/**\n * 工具调用\n */\nexport interface ToolCall {\n /**\n * 工具调用 ID\n */\n id?: string;\n\n /**\n * 工具名称\n */\n tool_name: string;\n\n /**\n * 工具调用参数\n */\n arguments: Record<string, unknown>;\n}\n\n/**\n * Token 使用统计\n */\nexport interface TokenUsage {\n /**\n * 完成部分的 token 数量\n */\n completion_tokens: number;\n\n /**\n * 提示部分的 token 数量\n */\n prompt_tokens: number;\n\n /**\n * 提示缓存命中的 token 数量(可选)\n */\n prompt_cache_hit_tokens?: number;\n\n /**\n * 提示缓存未命中的 token 数量(可选)\n */\n prompt_cache_miss_tokens?: number;\n\n /**\n * 总 token 数量\n */\n total_tokens: number;\n}\n\n/**\n * 对话消息类型\n */\nexport interface Message {\n /**\n * 消息角色\n */\n role: MessageRole;\n\n /**\n * 消息内容\n */\n content?: string;\n\n /**\n * 工具调用\n */\n tool_calls?: ToolCall[];\n\n /**\n * 工具调用 ID,用于工具响应消息\n */\n tool_call_id?: string;\n\n /**\n * Token 使用统计(可选)\n */\n usage?: TokenUsage;\n}\n\n/**\n * Deepseek 组件\n *\n * 使用 OpenAI 兼容接口调用 Deepseek 模型\n *\n * 输入:\n * - prompt: 文本提示\n * - messages: 对话消息数组\n *\n * 输出:\n * - completion: 生成的文本完成\n * - message: 生成的响应消息\n */\nclass Deepseek extends Component {\n // OpenAI 客户端实例\n private client: OpenAI;\n\n // 配置选项\n private model: string;\n private temperature: number;\n private maxTokens?: number;\n private topP?: number;\n private systemPrompt?: string;\n private tools?: unknown[];\n\n constructor(config: DeepseekConfig) {\n super({});\n\n // 配置客户端\n this.client = new OpenAI({\n apiKey: config.apiKey,\n baseURL: config.baseURL || 'https://api.deepseek.com/v1',\n dangerouslyAllowBrowser: config.dangerouslyAllowBrowser ?? false,\n });\n\n // 保存基本配置\n this.model = config.model || 'deepseek-chat';\n this.temperature = config.temperature ?? 0.7;\n this.maxTokens = config.maxTokens;\n this.topP = config.topP;\n this.systemPrompt = config.systemPrompt;\n\n // 处理工具配置,优先使用 rawTools\n if (config.rawTools && config.rawTools.length > 0) {\n // 将工具实例转换为 API 格式\n this.tools = config.rawTools.map(tool => ({\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters || {},\n },\n }));\n } else {\n // 使用直接提供的 API 格式工具\n this.tools = config.tools;\n }\n\n // 重命名端口\n Component.Port.I('prompt').attach(this);\n Component.Port.I('messages').attach(this);\n Component.Port.O('completion').attach(this);\n Component.Port.O('message').attach(this);\n }\n\n /**\n * 生成文本完成\n * @param prompt 提示文本\n * @returns 生成的文本\n */\n async generateCompletion(prompt: string): Promise<string> {\n const messages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n messages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提示\n messages.push({\n role: 'user',\n content: prompt,\n });\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 如果有工具定义,添加到请求中\n if (this.tools && this.tools.length > 0) {\n requestParams.tools = this.tools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 处理工具调用结果\n if (\n response.choices[0].message.tool_calls &&\n response.choices[0].message.tool_calls.length > 0\n ) {\n return JSON.stringify(response.choices[0].message);\n }\n\n return response.choices[0].message.content || '';\n }\n\n /**\n * 流式处理对话消息\n * @param messages 对话消息数组\n * @param options 可选的调用选项,包含临时工具列表\n * @returns 生成的流式响应消息异步生成器\n */\n async *streamChatCompletion(\n messages: Message[],\n options?: { temporaryTools?: unknown[] }\n ): AsyncGenerator<Partial<Message>> {\n // 转换消息格式 (复用现有逻辑)\n const formattedMessages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n formattedMessages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提供的消息\n formattedMessages.push(\n ...messages.map(msg => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const formattedMsg: any = {\n role: msg.role,\n content: msg.content,\n };\n\n if (msg.role === 'tool' && msg.tool_call_id) {\n formattedMsg.tool_call_id = msg.tool_call_id;\n }\n\n return formattedMsg;\n })\n );\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages: formattedMessages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n stream: true, // 开启流式模式\n };\n\n // 决定使用哪些工具\n const toolsToUse = options?.temporaryTools || this.tools;\n\n // 如果有工具定义,添加到请求中\n if (toolsToUse && toolsToUse.length > 0) {\n const formattedTools = toolsToUse.map(tool => {\n type ToolType = {\n type?: string;\n name?: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n\n const typedTool = tool as ToolType;\n\n if (typedTool.type === 'function') {\n return tool;\n }\n\n return {\n type: 'function',\n function: {\n name: typedTool.name,\n description: typedTool.description,\n parameters: typedTool.parameters || {},\n },\n };\n });\n\n requestParams.tools = formattedTools;\n }\n\n // 调用流式 API\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const stream = (await this.client.chat.completions.create(requestParams)) as any;\n\n // 处理流式响应\n for await (const chunk of stream) {\n const delta = chunk.choices[0]?.delta;\n\n if (delta?.content) {\n // 流式文本内容\n yield {\n role: 'assistant',\n content: delta.content,\n };\n }\n\n if (delta?.tool_calls) {\n // 流式工具调用(如果需要)\n yield {\n role: 'assistant',\n content: '',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n tool_calls: delta.tool_calls.map((toolCall: any) => ({\n id: toolCall.id || '',\n function: {\n name: toolCall.function?.name || '',\n arguments: toolCall.function?.arguments || '',\n },\n type: 'function',\n tool_name: toolCall.function?.name || '',\n arguments: toolCall.function?.arguments || '',\n })),\n };\n }\n\n // 提取并返回 token 使用统计信息\n if (chunk.usage) {\n yield {\n role: 'assistant',\n content: '',\n usage: {\n completion_tokens: chunk.usage.completion_tokens || 0,\n prompt_tokens: chunk.usage.prompt_tokens || 0,\n prompt_cache_hit_tokens: chunk.usage.prompt_cache_hit_tokens,\n prompt_cache_miss_tokens: chunk.usage.prompt_cache_miss_tokens,\n total_tokens: chunk.usage.total_tokens || 0,\n },\n };\n }\n }\n }\n\n /**\n * 处理对话消息\n * @param messages 对话消息数组\n * @param options 可选的调用选项,包含临时工具列表\n * @returns 生成的响应消息\n */\n async chatCompletion(\n messages: Message[],\n options?: { temporaryTools?: unknown[] }\n ): Promise<Message> {\n // 转换消息格式\n const formattedMessages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n formattedMessages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提供的消息\n formattedMessages.push(\n ...messages.map(msg => {\n // 基本消息结构\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const formattedMsg: any = {\n role: msg.role,\n content: msg.content,\n };\n\n // 如果有工具调用 ID,添加到消息中\n if (msg.role === 'tool' && msg.tool_call_id) {\n formattedMsg.tool_call_id = msg.tool_call_id;\n }\n\n return formattedMsg;\n })\n );\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages: formattedMessages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 决定使用哪些工具\n // 如果提供了临时工具,优先使用临时工具\n const toolsToUse = options?.temporaryTools || this.tools;\n\n // 如果有工具定义,添加到请求中\n if (toolsToUse && toolsToUse.length > 0) {\n // 检查工具格式并转换,确保符合 Deepseek API 要求\n const formattedTools = toolsToUse.map(tool => {\n // 使用类型断言来处理 unknown 类型\n type ToolType = {\n type?: string;\n name?: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n\n const typedTool = tool as ToolType;\n\n // 如果工具已经是 API 格式,直接返回\n if (typedTool.type === 'function') {\n return tool;\n }\n\n // 如果是简单工具实例,转换为 API 格式\n return {\n type: 'function',\n function: {\n name: typedTool.name,\n description: typedTool.description,\n parameters: typedTool.parameters || {},\n },\n };\n });\n\n requestParams.tools = formattedTools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 解析响应\n const responseMessage = response.choices[0].message;\n\n // 转换为内部消息格式\n const result: Message = {\n role: 'assistant',\n content: responseMessage.content || '',\n };\n\n // 提取并添加 token 使用统计信息\n if (response.usage) {\n const usage = response.usage as typeof response.usage & {\n prompt_cache_hit_tokens?: number;\n prompt_cache_miss_tokens?: number;\n };\n result.usage = {\n completion_tokens: usage.completion_tokens || 0,\n prompt_tokens: usage.prompt_tokens || 0,\n prompt_cache_hit_tokens: usage.prompt_cache_hit_tokens,\n prompt_cache_miss_tokens: usage.prompt_cache_miss_tokens,\n total_tokens: usage.total_tokens || 0,\n };\n }\n\n // 如果有工具调用,添加到结果中\n if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {\n // 为了兼容 Agent 组件期望的格式,保留 function 和 type 字段\n // 同时为了满足内部 ToolCall 接口,也添加 tool_name 和 arguments 字段\n result.tool_calls = responseMessage.tool_calls.map(toolCall => {\n // 解析参数,确保是对象形式\n let args: Record<string, unknown>;\n\n const rawArgs = toolCall.function.arguments;\n\n if (typeof rawArgs === 'string') {\n const raw = rawArgs;\n try {\n args = raw && raw.trim().length > 0 ? (JSON.parse(raw) as Record<string, unknown>) : {};\n } catch {\n args = {};\n }\n } else if (rawArgs && typeof rawArgs === 'object') {\n args = rawArgs as Record<string, unknown>;\n } else {\n args = {};\n }\n\n return {\n id: toolCall.id,\n // 满足 Agent 组件期望的格式\n function: {\n name: toolCall.function.name,\n arguments: toolCall.function.arguments || '{}',\n },\n type: 'function',\n // 满足内部 ToolCall 接口\n tool_name: toolCall.function.name,\n arguments: args,\n };\n });\n }\n\n return result;\n }\n\n /**\n * 在独立模式下运行组件\n * @param input 输入参数,可以是提示文本或对话消息数组\n * @returns 生成的文本或响应消息\n */\n async run(input: string | Message[]): Promise<string | Message> {\n if (typeof input === 'string') {\n return this.generateCompletion(input);\n } else {\n return this.chatCompletion(input);\n }\n }\n\n /**\n * 在流水线中运行组件\n * @param $i 输入端口\n * @param $o 输出端口\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n _transform($i: any, $o: any) {\n // 处理文本提示输入\n $i('prompt').receive(async (prompt: string) => {\n try {\n const completion = await this.generateCompletion(prompt);\n $o('completion').send(completion);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('completion').send('API 调用错误');\n }\n });\n\n // 处理对话消息输入\n $i('messages').receive(async (messages: Message[]) => {\n try {\n const responseMessage = await this.chatCompletion(messages);\n $o('message').send(responseMessage);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('message').send({\n role: 'assistant',\n content: 'API 调用错误',\n });\n }\n });\n }\n}\n\n// 默认导出组件\nexport default Deepseek;\n"],"mappings":"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","names":["OpenAI"]}
package/dist/index.js CHANGED
@@ -155,6 +155,19 @@ var Deepseek = class extends Component {
155
155
  }))
156
156
  };
157
157
  }
158
+ if (chunk.usage) {
159
+ yield {
160
+ role: "assistant",
161
+ content: "",
162
+ usage: {
163
+ completion_tokens: chunk.usage.completion_tokens || 0,
164
+ prompt_tokens: chunk.usage.prompt_tokens || 0,
165
+ prompt_cache_hit_tokens: chunk.usage.prompt_cache_hit_tokens,
166
+ prompt_cache_miss_tokens: chunk.usage.prompt_cache_miss_tokens,
167
+ total_tokens: chunk.usage.total_tokens || 0
168
+ }
169
+ };
170
+ }
158
171
  }
159
172
  }
160
173
  /**
@@ -214,6 +227,16 @@ var Deepseek = class extends Component {
214
227
  role: "assistant",
215
228
  content: responseMessage.content || ""
216
229
  };
230
+ if (response.usage) {
231
+ const usage = response.usage;
232
+ result.usage = {
233
+ completion_tokens: usage.completion_tokens || 0,
234
+ prompt_tokens: usage.prompt_tokens || 0,
235
+ prompt_cache_hit_tokens: usage.prompt_cache_hit_tokens,
236
+ prompt_cache_miss_tokens: usage.prompt_cache_miss_tokens,
237
+ total_tokens: usage.total_tokens || 0
238
+ };
239
+ }
217
240
  if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {
218
241
  result.tool_calls = responseMessage.tool_calls.map((toolCall) => {
219
242
  let args;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/model-provider/index.ts","../src/model-provider/deepseek/index.ts"],"sourcesContent":["export {\n default as Deepseek,\n type Message as DeepseekMessage,\n type ToolCall as DeepseekToolCall,\n type DeepseekConfig,\n type MessageRole as DeepseekMessageRole,\n} from './deepseek';\n","import { Component } from '@astack-tech/core';\nimport OpenAI from 'openai';\n\n/**\n * Deepseek 模型提供者配置\n */\nexport interface DeepseekConfig {\n /**\n * API 密钥\n */\n apiKey: string;\n\n /**\n * 使用的模型名称\n * 默认为 'deepseek-chat'\n */\n model?: string;\n\n /**\n * 自定义 API 基础 URL\n * 默认为 Deepseek 官方 API 地址\n */\n baseURL?: string;\n\n /**\n * 温度参数,控制输出的随机性\n */\n temperature?: number;\n\n /**\n * 最大生成的 token 数\n */\n maxTokens?: number;\n\n /**\n * 采样概率\n */\n topP?: number;\n\n /**\n * 系统提示消息\n */\n systemPrompt?: string;\n\n /**\n * 工具实例数组,直接传递工具实例\n * 每个工具应具有 name、description 和 parameters 属性\n */\n rawTools?: Array<{\n name: string;\n description: string;\n parameters?: Record<string, unknown>;\n }>;\n\n /**\n * API 格式的工具定义数组,与 rawTools 二选一\n * 使用 OpenAI 兼容的工具定义格式\n */\n tools?: unknown[];\n\n /**\n * dangerouslyAllowBrowser\n * 是否允许在浏览器等非安全环境内运行\n */\n dangerouslyAllowBrowser?: boolean;\n}\n\n/**\n * 消息角色类型\n */\nexport type MessageRole = 'system' | 'user' | 'assistant' | 'tool';\n\n/**\n * 工具调用\n */\nexport interface ToolCall {\n /**\n * 工具调用 ID\n */\n id?: string;\n\n /**\n * 工具名称\n */\n tool_name: string;\n\n /**\n * 工具调用参数\n */\n arguments: Record<string, unknown>;\n}\n\n/**\n * 对话消息类型\n */\nexport interface Message {\n /**\n * 消息角色\n */\n role: MessageRole;\n\n /**\n * 消息内容\n */\n content?: string;\n\n /**\n * 工具调用\n */\n tool_calls?: ToolCall[];\n\n /**\n * 工具调用 ID,用于工具响应消息\n */\n tool_call_id?: string;\n}\n\n/**\n * Deepseek 组件\n *\n * 使用 OpenAI 兼容接口调用 Deepseek 模型\n *\n * 输入:\n * - prompt: 文本提示\n * - messages: 对话消息数组\n *\n * 输出:\n * - completion: 生成的文本完成\n * - message: 生成的响应消息\n */\nclass Deepseek extends Component {\n // OpenAI 客户端实例\n private client: OpenAI;\n\n // 配置选项\n private model: string;\n private temperature: number;\n private maxTokens?: number;\n private topP?: number;\n private systemPrompt?: string;\n private tools?: unknown[];\n\n constructor(config: DeepseekConfig) {\n super({});\n\n // 配置客户端\n this.client = new OpenAI({\n apiKey: config.apiKey,\n baseURL: config.baseURL || 'https://api.deepseek.com/v1',\n dangerouslyAllowBrowser: config.dangerouslyAllowBrowser ?? false,\n });\n\n // 保存基本配置\n this.model = config.model || 'deepseek-chat';\n this.temperature = config.temperature ?? 0.7;\n this.maxTokens = config.maxTokens;\n this.topP = config.topP;\n this.systemPrompt = config.systemPrompt;\n\n // 处理工具配置,优先使用 rawTools\n if (config.rawTools && config.rawTools.length > 0) {\n // 将工具实例转换为 API 格式\n this.tools = config.rawTools.map(tool => ({\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters || {},\n },\n }));\n } else {\n // 使用直接提供的 API 格式工具\n this.tools = config.tools;\n }\n\n // 重命名端口\n Component.Port.I('prompt').attach(this);\n Component.Port.I('messages').attach(this);\n Component.Port.O('completion').attach(this);\n Component.Port.O('message').attach(this);\n }\n\n /**\n * 生成文本完成\n * @param prompt 提示文本\n * @returns 生成的文本\n */\n async generateCompletion(prompt: string): Promise<string> {\n const messages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n messages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提示\n messages.push({\n role: 'user',\n content: prompt,\n });\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 如果有工具定义,添加到请求中\n if (this.tools && this.tools.length > 0) {\n requestParams.tools = this.tools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 处理工具调用结果\n if (\n response.choices[0].message.tool_calls &&\n response.choices[0].message.tool_calls.length > 0\n ) {\n return JSON.stringify(response.choices[0].message);\n }\n\n return response.choices[0].message.content || '';\n }\n\n /**\n * 流式处理对话消息\n * @param messages 对话消息数组\n * @param options 可选的调用选项,包含临时工具列表\n * @returns 生成的流式响应消息异步生成器\n */\n async *streamChatCompletion(\n messages: Message[],\n options?: { temporaryTools?: unknown[] }\n ): AsyncGenerator<Partial<Message>> {\n // 转换消息格式 (复用现有逻辑)\n const formattedMessages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n formattedMessages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提供的消息\n formattedMessages.push(\n ...messages.map(msg => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const formattedMsg: any = {\n role: msg.role,\n content: msg.content,\n };\n\n if (msg.role === 'tool' && msg.tool_call_id) {\n formattedMsg.tool_call_id = msg.tool_call_id;\n }\n\n return formattedMsg;\n })\n );\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages: formattedMessages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n stream: true, // 开启流式模式\n };\n\n // 决定使用哪些工具\n const toolsToUse = options?.temporaryTools || this.tools;\n\n // 如果有工具定义,添加到请求中\n if (toolsToUse && toolsToUse.length > 0) {\n const formattedTools = toolsToUse.map(tool => {\n type ToolType = {\n type?: string;\n name?: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n\n const typedTool = tool as ToolType;\n\n if (typedTool.type === 'function') {\n return tool;\n }\n\n return {\n type: 'function',\n function: {\n name: typedTool.name,\n description: typedTool.description,\n parameters: typedTool.parameters || {},\n },\n };\n });\n\n requestParams.tools = formattedTools;\n }\n\n // 调用流式 API\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const stream = (await this.client.chat.completions.create(requestParams)) as any;\n\n // 处理流式响应\n for await (const chunk of stream) {\n const delta = chunk.choices[0]?.delta;\n\n if (delta?.content) {\n // 流式文本内容\n yield {\n role: 'assistant',\n content: delta.content,\n };\n }\n\n if (delta?.tool_calls) {\n // 流式工具调用(如果需要)\n yield {\n role: 'assistant',\n content: '',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n tool_calls: delta.tool_calls.map((toolCall: any) => ({\n id: toolCall.id || '',\n function: {\n name: toolCall.function?.name || '',\n arguments: toolCall.function?.arguments || '',\n },\n type: 'function',\n tool_name: toolCall.function?.name || '',\n arguments: toolCall.function?.arguments || '',\n })),\n };\n }\n }\n }\n\n /**\n * 处理对话消息\n * @param messages 对话消息数组\n * @param options 可选的调用选项,包含临时工具列表\n * @returns 生成的响应消息\n */\n async chatCompletion(\n messages: Message[],\n options?: { temporaryTools?: unknown[] }\n ): Promise<Message> {\n // 转换消息格式\n const formattedMessages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n formattedMessages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提供的消息\n formattedMessages.push(\n ...messages.map(msg => {\n // 基本消息结构\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const formattedMsg: any = {\n role: msg.role,\n content: msg.content,\n };\n\n // 如果有工具调用 ID,添加到消息中\n if (msg.role === 'tool' && msg.tool_call_id) {\n formattedMsg.tool_call_id = msg.tool_call_id;\n }\n\n return formattedMsg;\n })\n );\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages: formattedMessages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 决定使用哪些工具\n // 如果提供了临时工具,优先使用临时工具\n const toolsToUse = options?.temporaryTools || this.tools;\n\n // 如果有工具定义,添加到请求中\n if (toolsToUse && toolsToUse.length > 0) {\n // 检查工具格式并转换,确保符合 Deepseek API 要求\n const formattedTools = toolsToUse.map(tool => {\n // 使用类型断言来处理 unknown 类型\n type ToolType = {\n type?: string;\n name?: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n\n const typedTool = tool as ToolType;\n\n // 如果工具已经是 API 格式,直接返回\n if (typedTool.type === 'function') {\n return tool;\n }\n\n // 如果是简单工具实例,转换为 API 格式\n return {\n type: 'function',\n function: {\n name: typedTool.name,\n description: typedTool.description,\n parameters: typedTool.parameters || {},\n },\n };\n });\n\n requestParams.tools = formattedTools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 解析响应\n const responseMessage = response.choices[0].message;\n\n // 转换为内部消息格式\n const result: Message = {\n role: 'assistant',\n content: responseMessage.content || '',\n };\n\n // 如果有工具调用,添加到结果中\n if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {\n // 为了兼容 Agent 组件期望的格式,保留 function 和 type 字段\n // 同时为了满足内部 ToolCall 接口,也添加 tool_name 和 arguments 字段\n result.tool_calls = responseMessage.tool_calls.map(toolCall => {\n // 解析参数,确保是对象形式\n let args: Record<string, unknown>;\n\n const rawArgs = toolCall.function.arguments;\n\n if (typeof rawArgs === 'string') {\n const raw = rawArgs;\n try {\n args = raw && raw.trim().length > 0 ? (JSON.parse(raw) as Record<string, unknown>) : {};\n } catch {\n args = {};\n }\n } else if (rawArgs && typeof rawArgs === 'object') {\n args = rawArgs as Record<string, unknown>;\n } else {\n args = {};\n }\n\n return {\n id: toolCall.id,\n // 满足 Agent 组件期望的格式\n function: {\n name: toolCall.function.name,\n arguments: toolCall.function.arguments || '{}',\n },\n type: 'function',\n // 满足内部 ToolCall 接口\n tool_name: toolCall.function.name,\n arguments: args,\n };\n });\n }\n\n return result;\n }\n\n /**\n * 在独立模式下运行组件\n * @param input 输入参数,可以是提示文本或对话消息数组\n * @returns 生成的文本或响应消息\n */\n async run(input: string | Message[]): Promise<string | Message> {\n if (typeof input === 'string') {\n return this.generateCompletion(input);\n } else {\n return this.chatCompletion(input);\n }\n }\n\n /**\n * 在流水线中运行组件\n * @param $i 输入端口\n * @param $o 输出端口\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n _transform($i: any, $o: any) {\n // 处理文本提示输入\n $i('prompt').receive(async (prompt: string) => {\n try {\n const completion = await this.generateCompletion(prompt);\n $o('completion').send(completion);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('completion').send('API 调用错误');\n }\n });\n\n // 处理对话消息输入\n $i('messages').receive(async (messages: Message[]) => {\n try {\n const responseMessage = await this.chatCompletion(messages);\n $o('message').send(responseMessage);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('message').send({\n role: 'assistant',\n content: 'API 调用错误',\n });\n }\n });\n }\n}\n\n// 默认导出组件\nexport default Deepseek;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/model-provider/index.ts","../src/model-provider/deepseek/index.ts"],"sourcesContent":["export {\n default as Deepseek,\n type Message as DeepseekMessage,\n type ToolCall as DeepseekToolCall,\n type DeepseekConfig,\n type MessageRole as DeepseekMessageRole,\n} from './deepseek';\n","import { Component } from '@astack-tech/core';\nimport OpenAI from 'openai';\n\n/**\n * Deepseek 模型提供者配置\n */\nexport interface DeepseekConfig {\n /**\n * API 密钥\n */\n apiKey: string;\n\n /**\n * 使用的模型名称\n * 默认为 'deepseek-chat'\n */\n model?: string;\n\n /**\n * 自定义 API 基础 URL\n * 默认为 Deepseek 官方 API 地址\n */\n baseURL?: string;\n\n /**\n * 温度参数,控制输出的随机性\n */\n temperature?: number;\n\n /**\n * 最大生成的 token 数\n */\n maxTokens?: number;\n\n /**\n * 采样概率\n */\n topP?: number;\n\n /**\n * 系统提示消息\n */\n systemPrompt?: string;\n\n /**\n * 工具实例数组,直接传递工具实例\n * 每个工具应具有 name、description 和 parameters 属性\n */\n rawTools?: Array<{\n name: string;\n description: string;\n parameters?: Record<string, unknown>;\n }>;\n\n /**\n * API 格式的工具定义数组,与 rawTools 二选一\n * 使用 OpenAI 兼容的工具定义格式\n */\n tools?: unknown[];\n\n /**\n * dangerouslyAllowBrowser\n * 是否允许在浏览器等非安全环境内运行\n */\n dangerouslyAllowBrowser?: boolean;\n}\n\n/**\n * 消息角色类型\n */\nexport type MessageRole = 'system' | 'user' | 'assistant' | 'tool';\n\n/**\n * 工具调用\n */\nexport interface ToolCall {\n /**\n * 工具调用 ID\n */\n id?: string;\n\n /**\n * 工具名称\n */\n tool_name: string;\n\n /**\n * 工具调用参数\n */\n arguments: Record<string, unknown>;\n}\n\n/**\n * Token 使用统计\n */\nexport interface TokenUsage {\n /**\n * 完成部分的 token 数量\n */\n completion_tokens: number;\n\n /**\n * 提示部分的 token 数量\n */\n prompt_tokens: number;\n\n /**\n * 提示缓存命中的 token 数量(可选)\n */\n prompt_cache_hit_tokens?: number;\n\n /**\n * 提示缓存未命中的 token 数量(可选)\n */\n prompt_cache_miss_tokens?: number;\n\n /**\n * 总 token 数量\n */\n total_tokens: number;\n}\n\n/**\n * 对话消息类型\n */\nexport interface Message {\n /**\n * 消息角色\n */\n role: MessageRole;\n\n /**\n * 消息内容\n */\n content?: string;\n\n /**\n * 工具调用\n */\n tool_calls?: ToolCall[];\n\n /**\n * 工具调用 ID,用于工具响应消息\n */\n tool_call_id?: string;\n\n /**\n * Token 使用统计(可选)\n */\n usage?: TokenUsage;\n}\n\n/**\n * Deepseek 组件\n *\n * 使用 OpenAI 兼容接口调用 Deepseek 模型\n *\n * 输入:\n * - prompt: 文本提示\n * - messages: 对话消息数组\n *\n * 输出:\n * - completion: 生成的文本完成\n * - message: 生成的响应消息\n */\nclass Deepseek extends Component {\n // OpenAI 客户端实例\n private client: OpenAI;\n\n // 配置选项\n private model: string;\n private temperature: number;\n private maxTokens?: number;\n private topP?: number;\n private systemPrompt?: string;\n private tools?: unknown[];\n\n constructor(config: DeepseekConfig) {\n super({});\n\n // 配置客户端\n this.client = new OpenAI({\n apiKey: config.apiKey,\n baseURL: config.baseURL || 'https://api.deepseek.com/v1',\n dangerouslyAllowBrowser: config.dangerouslyAllowBrowser ?? false,\n });\n\n // 保存基本配置\n this.model = config.model || 'deepseek-chat';\n this.temperature = config.temperature ?? 0.7;\n this.maxTokens = config.maxTokens;\n this.topP = config.topP;\n this.systemPrompt = config.systemPrompt;\n\n // 处理工具配置,优先使用 rawTools\n if (config.rawTools && config.rawTools.length > 0) {\n // 将工具实例转换为 API 格式\n this.tools = config.rawTools.map(tool => ({\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters || {},\n },\n }));\n } else {\n // 使用直接提供的 API 格式工具\n this.tools = config.tools;\n }\n\n // 重命名端口\n Component.Port.I('prompt').attach(this);\n Component.Port.I('messages').attach(this);\n Component.Port.O('completion').attach(this);\n Component.Port.O('message').attach(this);\n }\n\n /**\n * 生成文本完成\n * @param prompt 提示文本\n * @returns 生成的文本\n */\n async generateCompletion(prompt: string): Promise<string> {\n const messages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n messages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提示\n messages.push({\n role: 'user',\n content: prompt,\n });\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 如果有工具定义,添加到请求中\n if (this.tools && this.tools.length > 0) {\n requestParams.tools = this.tools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 处理工具调用结果\n if (\n response.choices[0].message.tool_calls &&\n response.choices[0].message.tool_calls.length > 0\n ) {\n return JSON.stringify(response.choices[0].message);\n }\n\n return response.choices[0].message.content || '';\n }\n\n /**\n * 流式处理对话消息\n * @param messages 对话消息数组\n * @param options 可选的调用选项,包含临时工具列表\n * @returns 生成的流式响应消息异步生成器\n */\n async *streamChatCompletion(\n messages: Message[],\n options?: { temporaryTools?: unknown[] }\n ): AsyncGenerator<Partial<Message>> {\n // 转换消息格式 (复用现有逻辑)\n const formattedMessages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n formattedMessages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提供的消息\n formattedMessages.push(\n ...messages.map(msg => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const formattedMsg: any = {\n role: msg.role,\n content: msg.content,\n };\n\n if (msg.role === 'tool' && msg.tool_call_id) {\n formattedMsg.tool_call_id = msg.tool_call_id;\n }\n\n return formattedMsg;\n })\n );\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages: formattedMessages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n stream: true, // 开启流式模式\n };\n\n // 决定使用哪些工具\n const toolsToUse = options?.temporaryTools || this.tools;\n\n // 如果有工具定义,添加到请求中\n if (toolsToUse && toolsToUse.length > 0) {\n const formattedTools = toolsToUse.map(tool => {\n type ToolType = {\n type?: string;\n name?: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n\n const typedTool = tool as ToolType;\n\n if (typedTool.type === 'function') {\n return tool;\n }\n\n return {\n type: 'function',\n function: {\n name: typedTool.name,\n description: typedTool.description,\n parameters: typedTool.parameters || {},\n },\n };\n });\n\n requestParams.tools = formattedTools;\n }\n\n // 调用流式 API\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const stream = (await this.client.chat.completions.create(requestParams)) as any;\n\n // 处理流式响应\n for await (const chunk of stream) {\n const delta = chunk.choices[0]?.delta;\n\n if (delta?.content) {\n // 流式文本内容\n yield {\n role: 'assistant',\n content: delta.content,\n };\n }\n\n if (delta?.tool_calls) {\n // 流式工具调用(如果需要)\n yield {\n role: 'assistant',\n content: '',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n tool_calls: delta.tool_calls.map((toolCall: any) => ({\n id: toolCall.id || '',\n function: {\n name: toolCall.function?.name || '',\n arguments: toolCall.function?.arguments || '',\n },\n type: 'function',\n tool_name: toolCall.function?.name || '',\n arguments: toolCall.function?.arguments || '',\n })),\n };\n }\n\n // 提取并返回 token 使用统计信息\n if (chunk.usage) {\n yield {\n role: 'assistant',\n content: '',\n usage: {\n completion_tokens: chunk.usage.completion_tokens || 0,\n prompt_tokens: chunk.usage.prompt_tokens || 0,\n prompt_cache_hit_tokens: chunk.usage.prompt_cache_hit_tokens,\n prompt_cache_miss_tokens: chunk.usage.prompt_cache_miss_tokens,\n total_tokens: chunk.usage.total_tokens || 0,\n },\n };\n }\n }\n }\n\n /**\n * 处理对话消息\n * @param messages 对话消息数组\n * @param options 可选的调用选项,包含临时工具列表\n * @returns 生成的响应消息\n */\n async chatCompletion(\n messages: Message[],\n options?: { temporaryTools?: unknown[] }\n ): Promise<Message> {\n // 转换消息格式\n const formattedMessages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n formattedMessages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提供的消息\n formattedMessages.push(\n ...messages.map(msg => {\n // 基本消息结构\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const formattedMsg: any = {\n role: msg.role,\n content: msg.content,\n };\n\n // 如果有工具调用 ID,添加到消息中\n if (msg.role === 'tool' && msg.tool_call_id) {\n formattedMsg.tool_call_id = msg.tool_call_id;\n }\n\n return formattedMsg;\n })\n );\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages: formattedMessages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 决定使用哪些工具\n // 如果提供了临时工具,优先使用临时工具\n const toolsToUse = options?.temporaryTools || this.tools;\n\n // 如果有工具定义,添加到请求中\n if (toolsToUse && toolsToUse.length > 0) {\n // 检查工具格式并转换,确保符合 Deepseek API 要求\n const formattedTools = toolsToUse.map(tool => {\n // 使用类型断言来处理 unknown 类型\n type ToolType = {\n type?: string;\n name?: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n\n const typedTool = tool as ToolType;\n\n // 如果工具已经是 API 格式,直接返回\n if (typedTool.type === 'function') {\n return tool;\n }\n\n // 如果是简单工具实例,转换为 API 格式\n return {\n type: 'function',\n function: {\n name: typedTool.name,\n description: typedTool.description,\n parameters: typedTool.parameters || {},\n },\n };\n });\n\n requestParams.tools = formattedTools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 解析响应\n const responseMessage = response.choices[0].message;\n\n // 转换为内部消息格式\n const result: Message = {\n role: 'assistant',\n content: responseMessage.content || '',\n };\n\n // 提取并添加 token 使用统计信息\n if (response.usage) {\n const usage = response.usage as typeof response.usage & {\n prompt_cache_hit_tokens?: number;\n prompt_cache_miss_tokens?: number;\n };\n result.usage = {\n completion_tokens: usage.completion_tokens || 0,\n prompt_tokens: usage.prompt_tokens || 0,\n prompt_cache_hit_tokens: usage.prompt_cache_hit_tokens,\n prompt_cache_miss_tokens: usage.prompt_cache_miss_tokens,\n total_tokens: usage.total_tokens || 0,\n };\n }\n\n // 如果有工具调用,添加到结果中\n if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {\n // 为了兼容 Agent 组件期望的格式,保留 function 和 type 字段\n // 同时为了满足内部 ToolCall 接口,也添加 tool_name 和 arguments 字段\n result.tool_calls = responseMessage.tool_calls.map(toolCall => {\n // 解析参数,确保是对象形式\n let args: Record<string, unknown>;\n\n const rawArgs = toolCall.function.arguments;\n\n if (typeof rawArgs === 'string') {\n const raw = rawArgs;\n try {\n args = raw && raw.trim().length > 0 ? (JSON.parse(raw) as Record<string, unknown>) : {};\n } catch {\n args = {};\n }\n } else if (rawArgs && typeof rawArgs === 'object') {\n args = rawArgs as Record<string, unknown>;\n } else {\n args = {};\n }\n\n return {\n id: toolCall.id,\n // 满足 Agent 组件期望的格式\n function: {\n name: toolCall.function.name,\n arguments: toolCall.function.arguments || '{}',\n },\n type: 'function',\n // 满足内部 ToolCall 接口\n tool_name: toolCall.function.name,\n arguments: args,\n };\n });\n }\n\n return result;\n }\n\n /**\n * 在独立模式下运行组件\n * @param input 输入参数,可以是提示文本或对话消息数组\n * @returns 生成的文本或响应消息\n */\n async run(input: string | Message[]): Promise<string | Message> {\n if (typeof input === 'string') {\n return this.generateCompletion(input);\n } else {\n return this.chatCompletion(input);\n }\n }\n\n /**\n * 在流水线中运行组件\n * @param $i 输入端口\n * @param $o 输出端口\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n _transform($i: any, $o: any) {\n // 处理文本提示输入\n $i('prompt').receive(async (prompt: string) => {\n try {\n const completion = await this.generateCompletion(prompt);\n $o('completion').send(completion);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('completion').send('API 调用错误');\n }\n });\n\n // 处理对话消息输入\n $i('messages').receive(async (messages: Message[]) => {\n try {\n const responseMessage = await this.chatCompletion(messages);\n $o('message').send(responseMessage);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('message').send({\n role: 'assistant',\n content: 'API 调用错误',\n });\n }\n });\n }\n}\n\n// 默认导出组件\nexport default Deepseek;\n"],"mappings":"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","names":[]}
@@ -179,6 +179,19 @@ var Deepseek = class extends import_core.Component {
179
179
  }))
180
180
  };
181
181
  }
182
+ if (chunk.usage) {
183
+ yield {
184
+ role: "assistant",
185
+ content: "",
186
+ usage: {
187
+ completion_tokens: chunk.usage.completion_tokens || 0,
188
+ prompt_tokens: chunk.usage.prompt_tokens || 0,
189
+ prompt_cache_hit_tokens: chunk.usage.prompt_cache_hit_tokens,
190
+ prompt_cache_miss_tokens: chunk.usage.prompt_cache_miss_tokens,
191
+ total_tokens: chunk.usage.total_tokens || 0
192
+ }
193
+ };
194
+ }
182
195
  }
183
196
  }
184
197
  /**
@@ -238,6 +251,16 @@ var Deepseek = class extends import_core.Component {
238
251
  role: "assistant",
239
252
  content: responseMessage.content || ""
240
253
  };
254
+ if (response.usage) {
255
+ const usage = response.usage;
256
+ result.usage = {
257
+ completion_tokens: usage.completion_tokens || 0,
258
+ prompt_tokens: usage.prompt_tokens || 0,
259
+ prompt_cache_hit_tokens: usage.prompt_cache_hit_tokens,
260
+ prompt_cache_miss_tokens: usage.prompt_cache_miss_tokens,
261
+ total_tokens: usage.total_tokens || 0
262
+ };
263
+ }
241
264
  if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {
242
265
  result.tool_calls = responseMessage.tool_calls.map((toolCall) => {
243
266
  let args;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/model-provider/index.ts","../../src/model-provider/deepseek/index.ts"],"sourcesContent":["export {\n default as Deepseek,\n type Message as DeepseekMessage,\n type ToolCall as DeepseekToolCall,\n type DeepseekConfig,\n type MessageRole as DeepseekMessageRole,\n} from './deepseek';\n","import { Component } from '@astack-tech/core';\nimport OpenAI from 'openai';\n\n/**\n * Deepseek 模型提供者配置\n */\nexport interface DeepseekConfig {\n /**\n * API 密钥\n */\n apiKey: string;\n\n /**\n * 使用的模型名称\n * 默认为 'deepseek-chat'\n */\n model?: string;\n\n /**\n * 自定义 API 基础 URL\n * 默认为 Deepseek 官方 API 地址\n */\n baseURL?: string;\n\n /**\n * 温度参数,控制输出的随机性\n */\n temperature?: number;\n\n /**\n * 最大生成的 token 数\n */\n maxTokens?: number;\n\n /**\n * 采样概率\n */\n topP?: number;\n\n /**\n * 系统提示消息\n */\n systemPrompt?: string;\n\n /**\n * 工具实例数组,直接传递工具实例\n * 每个工具应具有 name、description 和 parameters 属性\n */\n rawTools?: Array<{\n name: string;\n description: string;\n parameters?: Record<string, unknown>;\n }>;\n\n /**\n * API 格式的工具定义数组,与 rawTools 二选一\n * 使用 OpenAI 兼容的工具定义格式\n */\n tools?: unknown[];\n\n /**\n * dangerouslyAllowBrowser\n * 是否允许在浏览器等非安全环境内运行\n */\n dangerouslyAllowBrowser?: boolean;\n}\n\n/**\n * 消息角色类型\n */\nexport type MessageRole = 'system' | 'user' | 'assistant' | 'tool';\n\n/**\n * 工具调用\n */\nexport interface ToolCall {\n /**\n * 工具调用 ID\n */\n id?: string;\n\n /**\n * 工具名称\n */\n tool_name: string;\n\n /**\n * 工具调用参数\n */\n arguments: Record<string, unknown>;\n}\n\n/**\n * 对话消息类型\n */\nexport interface Message {\n /**\n * 消息角色\n */\n role: MessageRole;\n\n /**\n * 消息内容\n */\n content?: string;\n\n /**\n * 工具调用\n */\n tool_calls?: ToolCall[];\n\n /**\n * 工具调用 ID,用于工具响应消息\n */\n tool_call_id?: string;\n}\n\n/**\n * Deepseek 组件\n *\n * 使用 OpenAI 兼容接口调用 Deepseek 模型\n *\n * 输入:\n * - prompt: 文本提示\n * - messages: 对话消息数组\n *\n * 输出:\n * - completion: 生成的文本完成\n * - message: 生成的响应消息\n */\nclass Deepseek extends Component {\n // OpenAI 客户端实例\n private client: OpenAI;\n\n // 配置选项\n private model: string;\n private temperature: number;\n private maxTokens?: number;\n private topP?: number;\n private systemPrompt?: string;\n private tools?: unknown[];\n\n constructor(config: DeepseekConfig) {\n super({});\n\n // 配置客户端\n this.client = new OpenAI({\n apiKey: config.apiKey,\n baseURL: config.baseURL || 'https://api.deepseek.com/v1',\n dangerouslyAllowBrowser: config.dangerouslyAllowBrowser ?? false,\n });\n\n // 保存基本配置\n this.model = config.model || 'deepseek-chat';\n this.temperature = config.temperature ?? 0.7;\n this.maxTokens = config.maxTokens;\n this.topP = config.topP;\n this.systemPrompt = config.systemPrompt;\n\n // 处理工具配置,优先使用 rawTools\n if (config.rawTools && config.rawTools.length > 0) {\n // 将工具实例转换为 API 格式\n this.tools = config.rawTools.map(tool => ({\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters || {},\n },\n }));\n } else {\n // 使用直接提供的 API 格式工具\n this.tools = config.tools;\n }\n\n // 重命名端口\n Component.Port.I('prompt').attach(this);\n Component.Port.I('messages').attach(this);\n Component.Port.O('completion').attach(this);\n Component.Port.O('message').attach(this);\n }\n\n /**\n * 生成文本完成\n * @param prompt 提示文本\n * @returns 生成的文本\n */\n async generateCompletion(prompt: string): Promise<string> {\n const messages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n messages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提示\n messages.push({\n role: 'user',\n content: prompt,\n });\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 如果有工具定义,添加到请求中\n if (this.tools && this.tools.length > 0) {\n requestParams.tools = this.tools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 处理工具调用结果\n if (\n response.choices[0].message.tool_calls &&\n response.choices[0].message.tool_calls.length > 0\n ) {\n return JSON.stringify(response.choices[0].message);\n }\n\n return response.choices[0].message.content || '';\n }\n\n /**\n * 流式处理对话消息\n * @param messages 对话消息数组\n * @param options 可选的调用选项,包含临时工具列表\n * @returns 生成的流式响应消息异步生成器\n */\n async *streamChatCompletion(\n messages: Message[],\n options?: { temporaryTools?: unknown[] }\n ): AsyncGenerator<Partial<Message>> {\n // 转换消息格式 (复用现有逻辑)\n const formattedMessages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n formattedMessages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提供的消息\n formattedMessages.push(\n ...messages.map(msg => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const formattedMsg: any = {\n role: msg.role,\n content: msg.content,\n };\n\n if (msg.role === 'tool' && msg.tool_call_id) {\n formattedMsg.tool_call_id = msg.tool_call_id;\n }\n\n return formattedMsg;\n })\n );\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages: formattedMessages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n stream: true, // 开启流式模式\n };\n\n // 决定使用哪些工具\n const toolsToUse = options?.temporaryTools || this.tools;\n\n // 如果有工具定义,添加到请求中\n if (toolsToUse && toolsToUse.length > 0) {\n const formattedTools = toolsToUse.map(tool => {\n type ToolType = {\n type?: string;\n name?: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n\n const typedTool = tool as ToolType;\n\n if (typedTool.type === 'function') {\n return tool;\n }\n\n return {\n type: 'function',\n function: {\n name: typedTool.name,\n description: typedTool.description,\n parameters: typedTool.parameters || {},\n },\n };\n });\n\n requestParams.tools = formattedTools;\n }\n\n // 调用流式 API\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const stream = (await this.client.chat.completions.create(requestParams)) as any;\n\n // 处理流式响应\n for await (const chunk of stream) {\n const delta = chunk.choices[0]?.delta;\n\n if (delta?.content) {\n // 流式文本内容\n yield {\n role: 'assistant',\n content: delta.content,\n };\n }\n\n if (delta?.tool_calls) {\n // 流式工具调用(如果需要)\n yield {\n role: 'assistant',\n content: '',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n tool_calls: delta.tool_calls.map((toolCall: any) => ({\n id: toolCall.id || '',\n function: {\n name: toolCall.function?.name || '',\n arguments: toolCall.function?.arguments || '',\n },\n type: 'function',\n tool_name: toolCall.function?.name || '',\n arguments: toolCall.function?.arguments || '',\n })),\n };\n }\n }\n }\n\n /**\n * 处理对话消息\n * @param messages 对话消息数组\n * @param options 可选的调用选项,包含临时工具列表\n * @returns 生成的响应消息\n */\n async chatCompletion(\n messages: Message[],\n options?: { temporaryTools?: unknown[] }\n ): Promise<Message> {\n // 转换消息格式\n const formattedMessages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n formattedMessages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提供的消息\n formattedMessages.push(\n ...messages.map(msg => {\n // 基本消息结构\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const formattedMsg: any = {\n role: msg.role,\n content: msg.content,\n };\n\n // 如果有工具调用 ID,添加到消息中\n if (msg.role === 'tool' && msg.tool_call_id) {\n formattedMsg.tool_call_id = msg.tool_call_id;\n }\n\n return formattedMsg;\n })\n );\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages: formattedMessages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 决定使用哪些工具\n // 如果提供了临时工具,优先使用临时工具\n const toolsToUse = options?.temporaryTools || this.tools;\n\n // 如果有工具定义,添加到请求中\n if (toolsToUse && toolsToUse.length > 0) {\n // 检查工具格式并转换,确保符合 Deepseek API 要求\n const formattedTools = toolsToUse.map(tool => {\n // 使用类型断言来处理 unknown 类型\n type ToolType = {\n type?: string;\n name?: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n\n const typedTool = tool as ToolType;\n\n // 如果工具已经是 API 格式,直接返回\n if (typedTool.type === 'function') {\n return tool;\n }\n\n // 如果是简单工具实例,转换为 API 格式\n return {\n type: 'function',\n function: {\n name: typedTool.name,\n description: typedTool.description,\n parameters: typedTool.parameters || {},\n },\n };\n });\n\n requestParams.tools = formattedTools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 解析响应\n const responseMessage = response.choices[0].message;\n\n // 转换为内部消息格式\n const result: Message = {\n role: 'assistant',\n content: responseMessage.content || '',\n };\n\n // 如果有工具调用,添加到结果中\n if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {\n // 为了兼容 Agent 组件期望的格式,保留 function 和 type 字段\n // 同时为了满足内部 ToolCall 接口,也添加 tool_name 和 arguments 字段\n result.tool_calls = responseMessage.tool_calls.map(toolCall => {\n // 解析参数,确保是对象形式\n let args: Record<string, unknown>;\n\n const rawArgs = toolCall.function.arguments;\n\n if (typeof rawArgs === 'string') {\n const raw = rawArgs;\n try {\n args = raw && raw.trim().length > 0 ? (JSON.parse(raw) as Record<string, unknown>) : {};\n } catch {\n args = {};\n }\n } else if (rawArgs && typeof rawArgs === 'object') {\n args = rawArgs as Record<string, unknown>;\n } else {\n args = {};\n }\n\n return {\n id: toolCall.id,\n // 满足 Agent 组件期望的格式\n function: {\n name: toolCall.function.name,\n arguments: toolCall.function.arguments || '{}',\n },\n type: 'function',\n // 满足内部 ToolCall 接口\n tool_name: toolCall.function.name,\n arguments: args,\n };\n });\n }\n\n return result;\n }\n\n /**\n * 在独立模式下运行组件\n * @param input 输入参数,可以是提示文本或对话消息数组\n * @returns 生成的文本或响应消息\n */\n async run(input: string | Message[]): Promise<string | Message> {\n if (typeof input === 'string') {\n return this.generateCompletion(input);\n } else {\n return this.chatCompletion(input);\n }\n }\n\n /**\n * 在流水线中运行组件\n * @param $i 输入端口\n * @param $o 输出端口\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n _transform($i: any, $o: any) {\n // 处理文本提示输入\n $i('prompt').receive(async (prompt: string) => {\n try {\n const completion = await this.generateCompletion(prompt);\n $o('completion').send(completion);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('completion').send('API 调用错误');\n }\n });\n\n // 处理对话消息输入\n $i('messages').receive(async (messages: Message[]) => {\n try {\n const responseMessage = await this.chatCompletion(messages);\n $o('message').send(responseMessage);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('message').send({\n role: 'assistant',\n content: 'API 调用错误',\n });\n }\n });\n }\n}\n\n// 默认导出组件\nexport default Deepseek;\n"],"mappings":"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","names":["OpenAI"]}
1
+ {"version":3,"sources":["../../src/model-provider/index.ts","../../src/model-provider/deepseek/index.ts"],"sourcesContent":["export {\n default as Deepseek,\n type Message as DeepseekMessage,\n type ToolCall as DeepseekToolCall,\n type DeepseekConfig,\n type MessageRole as DeepseekMessageRole,\n} from './deepseek';\n","import { Component } from '@astack-tech/core';\nimport OpenAI from 'openai';\n\n/**\n * Deepseek 模型提供者配置\n */\nexport interface DeepseekConfig {\n /**\n * API 密钥\n */\n apiKey: string;\n\n /**\n * 使用的模型名称\n * 默认为 'deepseek-chat'\n */\n model?: string;\n\n /**\n * 自定义 API 基础 URL\n * 默认为 Deepseek 官方 API 地址\n */\n baseURL?: string;\n\n /**\n * 温度参数,控制输出的随机性\n */\n temperature?: number;\n\n /**\n * 最大生成的 token 数\n */\n maxTokens?: number;\n\n /**\n * 采样概率\n */\n topP?: number;\n\n /**\n * 系统提示消息\n */\n systemPrompt?: string;\n\n /**\n * 工具实例数组,直接传递工具实例\n * 每个工具应具有 name、description 和 parameters 属性\n */\n rawTools?: Array<{\n name: string;\n description: string;\n parameters?: Record<string, unknown>;\n }>;\n\n /**\n * API 格式的工具定义数组,与 rawTools 二选一\n * 使用 OpenAI 兼容的工具定义格式\n */\n tools?: unknown[];\n\n /**\n * dangerouslyAllowBrowser\n * 是否允许在浏览器等非安全环境内运行\n */\n dangerouslyAllowBrowser?: boolean;\n}\n\n/**\n * 消息角色类型\n */\nexport type MessageRole = 'system' | 'user' | 'assistant' | 'tool';\n\n/**\n * 工具调用\n */\nexport interface ToolCall {\n /**\n * 工具调用 ID\n */\n id?: string;\n\n /**\n * 工具名称\n */\n tool_name: string;\n\n /**\n * 工具调用参数\n */\n arguments: Record<string, unknown>;\n}\n\n/**\n * Token 使用统计\n */\nexport interface TokenUsage {\n /**\n * 完成部分的 token 数量\n */\n completion_tokens: number;\n\n /**\n * 提示部分的 token 数量\n */\n prompt_tokens: number;\n\n /**\n * 提示缓存命中的 token 数量(可选)\n */\n prompt_cache_hit_tokens?: number;\n\n /**\n * 提示缓存未命中的 token 数量(可选)\n */\n prompt_cache_miss_tokens?: number;\n\n /**\n * 总 token 数量\n */\n total_tokens: number;\n}\n\n/**\n * 对话消息类型\n */\nexport interface Message {\n /**\n * 消息角色\n */\n role: MessageRole;\n\n /**\n * 消息内容\n */\n content?: string;\n\n /**\n * 工具调用\n */\n tool_calls?: ToolCall[];\n\n /**\n * 工具调用 ID,用于工具响应消息\n */\n tool_call_id?: string;\n\n /**\n * Token 使用统计(可选)\n */\n usage?: TokenUsage;\n}\n\n/**\n * Deepseek 组件\n *\n * 使用 OpenAI 兼容接口调用 Deepseek 模型\n *\n * 输入:\n * - prompt: 文本提示\n * - messages: 对话消息数组\n *\n * 输出:\n * - completion: 生成的文本完成\n * - message: 生成的响应消息\n */\nclass Deepseek extends Component {\n // OpenAI 客户端实例\n private client: OpenAI;\n\n // 配置选项\n private model: string;\n private temperature: number;\n private maxTokens?: number;\n private topP?: number;\n private systemPrompt?: string;\n private tools?: unknown[];\n\n constructor(config: DeepseekConfig) {\n super({});\n\n // 配置客户端\n this.client = new OpenAI({\n apiKey: config.apiKey,\n baseURL: config.baseURL || 'https://api.deepseek.com/v1',\n dangerouslyAllowBrowser: config.dangerouslyAllowBrowser ?? false,\n });\n\n // 保存基本配置\n this.model = config.model || 'deepseek-chat';\n this.temperature = config.temperature ?? 0.7;\n this.maxTokens = config.maxTokens;\n this.topP = config.topP;\n this.systemPrompt = config.systemPrompt;\n\n // 处理工具配置,优先使用 rawTools\n if (config.rawTools && config.rawTools.length > 0) {\n // 将工具实例转换为 API 格式\n this.tools = config.rawTools.map(tool => ({\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters || {},\n },\n }));\n } else {\n // 使用直接提供的 API 格式工具\n this.tools = config.tools;\n }\n\n // 重命名端口\n Component.Port.I('prompt').attach(this);\n Component.Port.I('messages').attach(this);\n Component.Port.O('completion').attach(this);\n Component.Port.O('message').attach(this);\n }\n\n /**\n * 生成文本完成\n * @param prompt 提示文本\n * @returns 生成的文本\n */\n async generateCompletion(prompt: string): Promise<string> {\n const messages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n messages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提示\n messages.push({\n role: 'user',\n content: prompt,\n });\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 如果有工具定义,添加到请求中\n if (this.tools && this.tools.length > 0) {\n requestParams.tools = this.tools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 处理工具调用结果\n if (\n response.choices[0].message.tool_calls &&\n response.choices[0].message.tool_calls.length > 0\n ) {\n return JSON.stringify(response.choices[0].message);\n }\n\n return response.choices[0].message.content || '';\n }\n\n /**\n * 流式处理对话消息\n * @param messages 对话消息数组\n * @param options 可选的调用选项,包含临时工具列表\n * @returns 生成的流式响应消息异步生成器\n */\n async *streamChatCompletion(\n messages: Message[],\n options?: { temporaryTools?: unknown[] }\n ): AsyncGenerator<Partial<Message>> {\n // 转换消息格式 (复用现有逻辑)\n const formattedMessages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n formattedMessages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提供的消息\n formattedMessages.push(\n ...messages.map(msg => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const formattedMsg: any = {\n role: msg.role,\n content: msg.content,\n };\n\n if (msg.role === 'tool' && msg.tool_call_id) {\n formattedMsg.tool_call_id = msg.tool_call_id;\n }\n\n return formattedMsg;\n })\n );\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages: formattedMessages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n stream: true, // 开启流式模式\n };\n\n // 决定使用哪些工具\n const toolsToUse = options?.temporaryTools || this.tools;\n\n // 如果有工具定义,添加到请求中\n if (toolsToUse && toolsToUse.length > 0) {\n const formattedTools = toolsToUse.map(tool => {\n type ToolType = {\n type?: string;\n name?: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n\n const typedTool = tool as ToolType;\n\n if (typedTool.type === 'function') {\n return tool;\n }\n\n return {\n type: 'function',\n function: {\n name: typedTool.name,\n description: typedTool.description,\n parameters: typedTool.parameters || {},\n },\n };\n });\n\n requestParams.tools = formattedTools;\n }\n\n // 调用流式 API\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const stream = (await this.client.chat.completions.create(requestParams)) as any;\n\n // 处理流式响应\n for await (const chunk of stream) {\n const delta = chunk.choices[0]?.delta;\n\n if (delta?.content) {\n // 流式文本内容\n yield {\n role: 'assistant',\n content: delta.content,\n };\n }\n\n if (delta?.tool_calls) {\n // 流式工具调用(如果需要)\n yield {\n role: 'assistant',\n content: '',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n tool_calls: delta.tool_calls.map((toolCall: any) => ({\n id: toolCall.id || '',\n function: {\n name: toolCall.function?.name || '',\n arguments: toolCall.function?.arguments || '',\n },\n type: 'function',\n tool_name: toolCall.function?.name || '',\n arguments: toolCall.function?.arguments || '',\n })),\n };\n }\n\n // 提取并返回 token 使用统计信息\n if (chunk.usage) {\n yield {\n role: 'assistant',\n content: '',\n usage: {\n completion_tokens: chunk.usage.completion_tokens || 0,\n prompt_tokens: chunk.usage.prompt_tokens || 0,\n prompt_cache_hit_tokens: chunk.usage.prompt_cache_hit_tokens,\n prompt_cache_miss_tokens: chunk.usage.prompt_cache_miss_tokens,\n total_tokens: chunk.usage.total_tokens || 0,\n },\n };\n }\n }\n }\n\n /**\n * 处理对话消息\n * @param messages 对话消息数组\n * @param options 可选的调用选项,包含临时工具列表\n * @returns 生成的响应消息\n */\n async chatCompletion(\n messages: Message[],\n options?: { temporaryTools?: unknown[] }\n ): Promise<Message> {\n // 转换消息格式\n const formattedMessages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n formattedMessages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提供的消息\n formattedMessages.push(\n ...messages.map(msg => {\n // 基本消息结构\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const formattedMsg: any = {\n role: msg.role,\n content: msg.content,\n };\n\n // 如果有工具调用 ID,添加到消息中\n if (msg.role === 'tool' && msg.tool_call_id) {\n formattedMsg.tool_call_id = msg.tool_call_id;\n }\n\n return formattedMsg;\n })\n );\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages: formattedMessages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 决定使用哪些工具\n // 如果提供了临时工具,优先使用临时工具\n const toolsToUse = options?.temporaryTools || this.tools;\n\n // 如果有工具定义,添加到请求中\n if (toolsToUse && toolsToUse.length > 0) {\n // 检查工具格式并转换,确保符合 Deepseek API 要求\n const formattedTools = toolsToUse.map(tool => {\n // 使用类型断言来处理 unknown 类型\n type ToolType = {\n type?: string;\n name?: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n\n const typedTool = tool as ToolType;\n\n // 如果工具已经是 API 格式,直接返回\n if (typedTool.type === 'function') {\n return tool;\n }\n\n // 如果是简单工具实例,转换为 API 格式\n return {\n type: 'function',\n function: {\n name: typedTool.name,\n description: typedTool.description,\n parameters: typedTool.parameters || {},\n },\n };\n });\n\n requestParams.tools = formattedTools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 解析响应\n const responseMessage = response.choices[0].message;\n\n // 转换为内部消息格式\n const result: Message = {\n role: 'assistant',\n content: responseMessage.content || '',\n };\n\n // 提取并添加 token 使用统计信息\n if (response.usage) {\n const usage = response.usage as typeof response.usage & {\n prompt_cache_hit_tokens?: number;\n prompt_cache_miss_tokens?: number;\n };\n result.usage = {\n completion_tokens: usage.completion_tokens || 0,\n prompt_tokens: usage.prompt_tokens || 0,\n prompt_cache_hit_tokens: usage.prompt_cache_hit_tokens,\n prompt_cache_miss_tokens: usage.prompt_cache_miss_tokens,\n total_tokens: usage.total_tokens || 0,\n };\n }\n\n // 如果有工具调用,添加到结果中\n if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {\n // 为了兼容 Agent 组件期望的格式,保留 function 和 type 字段\n // 同时为了满足内部 ToolCall 接口,也添加 tool_name 和 arguments 字段\n result.tool_calls = responseMessage.tool_calls.map(toolCall => {\n // 解析参数,确保是对象形式\n let args: Record<string, unknown>;\n\n const rawArgs = toolCall.function.arguments;\n\n if (typeof rawArgs === 'string') {\n const raw = rawArgs;\n try {\n args = raw && raw.trim().length > 0 ? (JSON.parse(raw) as Record<string, unknown>) : {};\n } catch {\n args = {};\n }\n } else if (rawArgs && typeof rawArgs === 'object') {\n args = rawArgs as Record<string, unknown>;\n } else {\n args = {};\n }\n\n return {\n id: toolCall.id,\n // 满足 Agent 组件期望的格式\n function: {\n name: toolCall.function.name,\n arguments: toolCall.function.arguments || '{}',\n },\n type: 'function',\n // 满足内部 ToolCall 接口\n tool_name: toolCall.function.name,\n arguments: args,\n };\n });\n }\n\n return result;\n }\n\n /**\n * 在独立模式下运行组件\n * @param input 输入参数,可以是提示文本或对话消息数组\n * @returns 生成的文本或响应消息\n */\n async run(input: string | Message[]): Promise<string | Message> {\n if (typeof input === 'string') {\n return this.generateCompletion(input);\n } else {\n return this.chatCompletion(input);\n }\n }\n\n /**\n * 在流水线中运行组件\n * @param $i 输入端口\n * @param $o 输出端口\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n _transform($i: any, $o: any) {\n // 处理文本提示输入\n $i('prompt').receive(async (prompt: string) => {\n try {\n const completion = await this.generateCompletion(prompt);\n $o('completion').send(completion);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('completion').send('API 调用错误');\n }\n });\n\n // 处理对话消息输入\n $i('messages').receive(async (messages: Message[]) => {\n try {\n const responseMessage = await this.chatCompletion(messages);\n $o('message').send(responseMessage);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('message').send({\n role: 'assistant',\n content: 'API 调用错误',\n });\n }\n });\n }\n}\n\n// 默认导出组件\nexport default Deepseek;\n"],"mappings":"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","names":["OpenAI"]}
@@ -75,6 +75,31 @@ interface ToolCall {
75
75
  */
76
76
  arguments: Record<string, unknown>;
77
77
  }
78
+ /**
79
+ * Token 使用统计
80
+ */
81
+ interface TokenUsage {
82
+ /**
83
+ * 完成部分的 token 数量
84
+ */
85
+ completion_tokens: number;
86
+ /**
87
+ * 提示部分的 token 数量
88
+ */
89
+ prompt_tokens: number;
90
+ /**
91
+ * 提示缓存命中的 token 数量(可选)
92
+ */
93
+ prompt_cache_hit_tokens?: number;
94
+ /**
95
+ * 提示缓存未命中的 token 数量(可选)
96
+ */
97
+ prompt_cache_miss_tokens?: number;
98
+ /**
99
+ * 总 token 数量
100
+ */
101
+ total_tokens: number;
102
+ }
78
103
  /**
79
104
  * 对话消息类型
80
105
  */
@@ -95,6 +120,10 @@ interface Message {
95
120
  * 工具调用 ID,用于工具响应消息
96
121
  */
97
122
  tool_call_id?: string;
123
+ /**
124
+ * Token 使用统计(可选)
125
+ */
126
+ usage?: TokenUsage;
98
127
  }
99
128
  /**
100
129
  * Deepseek 组件
@@ -75,6 +75,31 @@ interface ToolCall {
75
75
  */
76
76
  arguments: Record<string, unknown>;
77
77
  }
78
+ /**
79
+ * Token 使用统计
80
+ */
81
+ interface TokenUsage {
82
+ /**
83
+ * 完成部分的 token 数量
84
+ */
85
+ completion_tokens: number;
86
+ /**
87
+ * 提示部分的 token 数量
88
+ */
89
+ prompt_tokens: number;
90
+ /**
91
+ * 提示缓存命中的 token 数量(可选)
92
+ */
93
+ prompt_cache_hit_tokens?: number;
94
+ /**
95
+ * 提示缓存未命中的 token 数量(可选)
96
+ */
97
+ prompt_cache_miss_tokens?: number;
98
+ /**
99
+ * 总 token 数量
100
+ */
101
+ total_tokens: number;
102
+ }
78
103
  /**
79
104
  * 对话消息类型
80
105
  */
@@ -95,6 +120,10 @@ interface Message {
95
120
  * 工具调用 ID,用于工具响应消息
96
121
  */
97
122
  tool_call_id?: string;
123
+ /**
124
+ * Token 使用统计(可选)
125
+ */
126
+ usage?: TokenUsage;
98
127
  }
99
128
  /**
100
129
  * Deepseek 组件
@@ -143,6 +143,19 @@ var Deepseek = class extends Component {
143
143
  }))
144
144
  };
145
145
  }
146
+ if (chunk.usage) {
147
+ yield {
148
+ role: "assistant",
149
+ content: "",
150
+ usage: {
151
+ completion_tokens: chunk.usage.completion_tokens || 0,
152
+ prompt_tokens: chunk.usage.prompt_tokens || 0,
153
+ prompt_cache_hit_tokens: chunk.usage.prompt_cache_hit_tokens,
154
+ prompt_cache_miss_tokens: chunk.usage.prompt_cache_miss_tokens,
155
+ total_tokens: chunk.usage.total_tokens || 0
156
+ }
157
+ };
158
+ }
146
159
  }
147
160
  }
148
161
  /**
@@ -202,6 +215,16 @@ var Deepseek = class extends Component {
202
215
  role: "assistant",
203
216
  content: responseMessage.content || ""
204
217
  };
218
+ if (response.usage) {
219
+ const usage = response.usage;
220
+ result.usage = {
221
+ completion_tokens: usage.completion_tokens || 0,
222
+ prompt_tokens: usage.prompt_tokens || 0,
223
+ prompt_cache_hit_tokens: usage.prompt_cache_hit_tokens,
224
+ prompt_cache_miss_tokens: usage.prompt_cache_miss_tokens,
225
+ total_tokens: usage.total_tokens || 0
226
+ };
227
+ }
205
228
  if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {
206
229
  result.tool_calls = responseMessage.tool_calls.map((toolCall) => {
207
230
  let args;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/model-provider/deepseek/index.ts"],"sourcesContent":["import { Component } from '@astack-tech/core';\nimport OpenAI from 'openai';\n\n/**\n * Deepseek 模型提供者配置\n */\nexport interface DeepseekConfig {\n /**\n * API 密钥\n */\n apiKey: string;\n\n /**\n * 使用的模型名称\n * 默认为 'deepseek-chat'\n */\n model?: string;\n\n /**\n * 自定义 API 基础 URL\n * 默认为 Deepseek 官方 API 地址\n */\n baseURL?: string;\n\n /**\n * 温度参数,控制输出的随机性\n */\n temperature?: number;\n\n /**\n * 最大生成的 token 数\n */\n maxTokens?: number;\n\n /**\n * 采样概率\n */\n topP?: number;\n\n /**\n * 系统提示消息\n */\n systemPrompt?: string;\n\n /**\n * 工具实例数组,直接传递工具实例\n * 每个工具应具有 name、description 和 parameters 属性\n */\n rawTools?: Array<{\n name: string;\n description: string;\n parameters?: Record<string, unknown>;\n }>;\n\n /**\n * API 格式的工具定义数组,与 rawTools 二选一\n * 使用 OpenAI 兼容的工具定义格式\n */\n tools?: unknown[];\n\n /**\n * dangerouslyAllowBrowser\n * 是否允许在浏览器等非安全环境内运行\n */\n dangerouslyAllowBrowser?: boolean;\n}\n\n/**\n * 消息角色类型\n */\nexport type MessageRole = 'system' | 'user' | 'assistant' | 'tool';\n\n/**\n * 工具调用\n */\nexport interface ToolCall {\n /**\n * 工具调用 ID\n */\n id?: string;\n\n /**\n * 工具名称\n */\n tool_name: string;\n\n /**\n * 工具调用参数\n */\n arguments: Record<string, unknown>;\n}\n\n/**\n * 对话消息类型\n */\nexport interface Message {\n /**\n * 消息角色\n */\n role: MessageRole;\n\n /**\n * 消息内容\n */\n content?: string;\n\n /**\n * 工具调用\n */\n tool_calls?: ToolCall[];\n\n /**\n * 工具调用 ID,用于工具响应消息\n */\n tool_call_id?: string;\n}\n\n/**\n * Deepseek 组件\n *\n * 使用 OpenAI 兼容接口调用 Deepseek 模型\n *\n * 输入:\n * - prompt: 文本提示\n * - messages: 对话消息数组\n *\n * 输出:\n * - completion: 生成的文本完成\n * - message: 生成的响应消息\n */\nclass Deepseek extends Component {\n // OpenAI 客户端实例\n private client: OpenAI;\n\n // 配置选项\n private model: string;\n private temperature: number;\n private maxTokens?: number;\n private topP?: number;\n private systemPrompt?: string;\n private tools?: unknown[];\n\n constructor(config: DeepseekConfig) {\n super({});\n\n // 配置客户端\n this.client = new OpenAI({\n apiKey: config.apiKey,\n baseURL: config.baseURL || 'https://api.deepseek.com/v1',\n dangerouslyAllowBrowser: config.dangerouslyAllowBrowser ?? false,\n });\n\n // 保存基本配置\n this.model = config.model || 'deepseek-chat';\n this.temperature = config.temperature ?? 0.7;\n this.maxTokens = config.maxTokens;\n this.topP = config.topP;\n this.systemPrompt = config.systemPrompt;\n\n // 处理工具配置,优先使用 rawTools\n if (config.rawTools && config.rawTools.length > 0) {\n // 将工具实例转换为 API 格式\n this.tools = config.rawTools.map(tool => ({\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters || {},\n },\n }));\n } else {\n // 使用直接提供的 API 格式工具\n this.tools = config.tools;\n }\n\n // 重命名端口\n Component.Port.I('prompt').attach(this);\n Component.Port.I('messages').attach(this);\n Component.Port.O('completion').attach(this);\n Component.Port.O('message').attach(this);\n }\n\n /**\n * 生成文本完成\n * @param prompt 提示文本\n * @returns 生成的文本\n */\n async generateCompletion(prompt: string): Promise<string> {\n const messages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n messages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提示\n messages.push({\n role: 'user',\n content: prompt,\n });\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 如果有工具定义,添加到请求中\n if (this.tools && this.tools.length > 0) {\n requestParams.tools = this.tools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 处理工具调用结果\n if (\n response.choices[0].message.tool_calls &&\n response.choices[0].message.tool_calls.length > 0\n ) {\n return JSON.stringify(response.choices[0].message);\n }\n\n return response.choices[0].message.content || '';\n }\n\n /**\n * 流式处理对话消息\n * @param messages 对话消息数组\n * @param options 可选的调用选项,包含临时工具列表\n * @returns 生成的流式响应消息异步生成器\n */\n async *streamChatCompletion(\n messages: Message[],\n options?: { temporaryTools?: unknown[] }\n ): AsyncGenerator<Partial<Message>> {\n // 转换消息格式 (复用现有逻辑)\n const formattedMessages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n formattedMessages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提供的消息\n formattedMessages.push(\n ...messages.map(msg => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const formattedMsg: any = {\n role: msg.role,\n content: msg.content,\n };\n\n if (msg.role === 'tool' && msg.tool_call_id) {\n formattedMsg.tool_call_id = msg.tool_call_id;\n }\n\n return formattedMsg;\n })\n );\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages: formattedMessages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n stream: true, // 开启流式模式\n };\n\n // 决定使用哪些工具\n const toolsToUse = options?.temporaryTools || this.tools;\n\n // 如果有工具定义,添加到请求中\n if (toolsToUse && toolsToUse.length > 0) {\n const formattedTools = toolsToUse.map(tool => {\n type ToolType = {\n type?: string;\n name?: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n\n const typedTool = tool as ToolType;\n\n if (typedTool.type === 'function') {\n return tool;\n }\n\n return {\n type: 'function',\n function: {\n name: typedTool.name,\n description: typedTool.description,\n parameters: typedTool.parameters || {},\n },\n };\n });\n\n requestParams.tools = formattedTools;\n }\n\n // 调用流式 API\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const stream = (await this.client.chat.completions.create(requestParams)) as any;\n\n // 处理流式响应\n for await (const chunk of stream) {\n const delta = chunk.choices[0]?.delta;\n\n if (delta?.content) {\n // 流式文本内容\n yield {\n role: 'assistant',\n content: delta.content,\n };\n }\n\n if (delta?.tool_calls) {\n // 流式工具调用(如果需要)\n yield {\n role: 'assistant',\n content: '',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n tool_calls: delta.tool_calls.map((toolCall: any) => ({\n id: toolCall.id || '',\n function: {\n name: toolCall.function?.name || '',\n arguments: toolCall.function?.arguments || '',\n },\n type: 'function',\n tool_name: toolCall.function?.name || '',\n arguments: toolCall.function?.arguments || '',\n })),\n };\n }\n }\n }\n\n /**\n * 处理对话消息\n * @param messages 对话消息数组\n * @param options 可选的调用选项,包含临时工具列表\n * @returns 生成的响应消息\n */\n async chatCompletion(\n messages: Message[],\n options?: { temporaryTools?: unknown[] }\n ): Promise<Message> {\n // 转换消息格式\n const formattedMessages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n formattedMessages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提供的消息\n formattedMessages.push(\n ...messages.map(msg => {\n // 基本消息结构\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const formattedMsg: any = {\n role: msg.role,\n content: msg.content,\n };\n\n // 如果有工具调用 ID,添加到消息中\n if (msg.role === 'tool' && msg.tool_call_id) {\n formattedMsg.tool_call_id = msg.tool_call_id;\n }\n\n return formattedMsg;\n })\n );\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages: formattedMessages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 决定使用哪些工具\n // 如果提供了临时工具,优先使用临时工具\n const toolsToUse = options?.temporaryTools || this.tools;\n\n // 如果有工具定义,添加到请求中\n if (toolsToUse && toolsToUse.length > 0) {\n // 检查工具格式并转换,确保符合 Deepseek API 要求\n const formattedTools = toolsToUse.map(tool => {\n // 使用类型断言来处理 unknown 类型\n type ToolType = {\n type?: string;\n name?: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n\n const typedTool = tool as ToolType;\n\n // 如果工具已经是 API 格式,直接返回\n if (typedTool.type === 'function') {\n return tool;\n }\n\n // 如果是简单工具实例,转换为 API 格式\n return {\n type: 'function',\n function: {\n name: typedTool.name,\n description: typedTool.description,\n parameters: typedTool.parameters || {},\n },\n };\n });\n\n requestParams.tools = formattedTools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 解析响应\n const responseMessage = response.choices[0].message;\n\n // 转换为内部消息格式\n const result: Message = {\n role: 'assistant',\n content: responseMessage.content || '',\n };\n\n // 如果有工具调用,添加到结果中\n if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {\n // 为了兼容 Agent 组件期望的格式,保留 function 和 type 字段\n // 同时为了满足内部 ToolCall 接口,也添加 tool_name 和 arguments 字段\n result.tool_calls = responseMessage.tool_calls.map(toolCall => {\n // 解析参数,确保是对象形式\n let args: Record<string, unknown>;\n\n const rawArgs = toolCall.function.arguments;\n\n if (typeof rawArgs === 'string') {\n const raw = rawArgs;\n try {\n args = raw && raw.trim().length > 0 ? (JSON.parse(raw) as Record<string, unknown>) : {};\n } catch {\n args = {};\n }\n } else if (rawArgs && typeof rawArgs === 'object') {\n args = rawArgs as Record<string, unknown>;\n } else {\n args = {};\n }\n\n return {\n id: toolCall.id,\n // 满足 Agent 组件期望的格式\n function: {\n name: toolCall.function.name,\n arguments: toolCall.function.arguments || '{}',\n },\n type: 'function',\n // 满足内部 ToolCall 接口\n tool_name: toolCall.function.name,\n arguments: args,\n };\n });\n }\n\n return result;\n }\n\n /**\n * 在独立模式下运行组件\n * @param input 输入参数,可以是提示文本或对话消息数组\n * @returns 生成的文本或响应消息\n */\n async run(input: string | Message[]): Promise<string | Message> {\n if (typeof input === 'string') {\n return this.generateCompletion(input);\n } else {\n return this.chatCompletion(input);\n }\n }\n\n /**\n * 在流水线中运行组件\n * @param $i 输入端口\n * @param $o 输出端口\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n _transform($i: any, $o: any) {\n // 处理文本提示输入\n $i('prompt').receive(async (prompt: string) => {\n try {\n const completion = await this.generateCompletion(prompt);\n $o('completion').send(completion);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('completion').send('API 调用错误');\n }\n });\n\n // 处理对话消息输入\n $i('messages').receive(async (messages: Message[]) => {\n try {\n const responseMessage = await this.chatCompletion(messages);\n $o('message').send(responseMessage);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('message').send({\n role: 'assistant',\n content: 'API 调用错误',\n });\n }\n });\n }\n}\n\n// 默认导出组件\nexport default Deepseek;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/model-provider/deepseek/index.ts"],"sourcesContent":["import { Component } from '@astack-tech/core';\nimport OpenAI from 'openai';\n\n/**\n * Deepseek 模型提供者配置\n */\nexport interface DeepseekConfig {\n /**\n * API 密钥\n */\n apiKey: string;\n\n /**\n * 使用的模型名称\n * 默认为 'deepseek-chat'\n */\n model?: string;\n\n /**\n * 自定义 API 基础 URL\n * 默认为 Deepseek 官方 API 地址\n */\n baseURL?: string;\n\n /**\n * 温度参数,控制输出的随机性\n */\n temperature?: number;\n\n /**\n * 最大生成的 token 数\n */\n maxTokens?: number;\n\n /**\n * 采样概率\n */\n topP?: number;\n\n /**\n * 系统提示消息\n */\n systemPrompt?: string;\n\n /**\n * 工具实例数组,直接传递工具实例\n * 每个工具应具有 name、description 和 parameters 属性\n */\n rawTools?: Array<{\n name: string;\n description: string;\n parameters?: Record<string, unknown>;\n }>;\n\n /**\n * API 格式的工具定义数组,与 rawTools 二选一\n * 使用 OpenAI 兼容的工具定义格式\n */\n tools?: unknown[];\n\n /**\n * dangerouslyAllowBrowser\n * 是否允许在浏览器等非安全环境内运行\n */\n dangerouslyAllowBrowser?: boolean;\n}\n\n/**\n * 消息角色类型\n */\nexport type MessageRole = 'system' | 'user' | 'assistant' | 'tool';\n\n/**\n * 工具调用\n */\nexport interface ToolCall {\n /**\n * 工具调用 ID\n */\n id?: string;\n\n /**\n * 工具名称\n */\n tool_name: string;\n\n /**\n * 工具调用参数\n */\n arguments: Record<string, unknown>;\n}\n\n/**\n * Token 使用统计\n */\nexport interface TokenUsage {\n /**\n * 完成部分的 token 数量\n */\n completion_tokens: number;\n\n /**\n * 提示部分的 token 数量\n */\n prompt_tokens: number;\n\n /**\n * 提示缓存命中的 token 数量(可选)\n */\n prompt_cache_hit_tokens?: number;\n\n /**\n * 提示缓存未命中的 token 数量(可选)\n */\n prompt_cache_miss_tokens?: number;\n\n /**\n * 总 token 数量\n */\n total_tokens: number;\n}\n\n/**\n * 对话消息类型\n */\nexport interface Message {\n /**\n * 消息角色\n */\n role: MessageRole;\n\n /**\n * 消息内容\n */\n content?: string;\n\n /**\n * 工具调用\n */\n tool_calls?: ToolCall[];\n\n /**\n * 工具调用 ID,用于工具响应消息\n */\n tool_call_id?: string;\n\n /**\n * Token 使用统计(可选)\n */\n usage?: TokenUsage;\n}\n\n/**\n * Deepseek 组件\n *\n * 使用 OpenAI 兼容接口调用 Deepseek 模型\n *\n * 输入:\n * - prompt: 文本提示\n * - messages: 对话消息数组\n *\n * 输出:\n * - completion: 生成的文本完成\n * - message: 生成的响应消息\n */\nclass Deepseek extends Component {\n // OpenAI 客户端实例\n private client: OpenAI;\n\n // 配置选项\n private model: string;\n private temperature: number;\n private maxTokens?: number;\n private topP?: number;\n private systemPrompt?: string;\n private tools?: unknown[];\n\n constructor(config: DeepseekConfig) {\n super({});\n\n // 配置客户端\n this.client = new OpenAI({\n apiKey: config.apiKey,\n baseURL: config.baseURL || 'https://api.deepseek.com/v1',\n dangerouslyAllowBrowser: config.dangerouslyAllowBrowser ?? false,\n });\n\n // 保存基本配置\n this.model = config.model || 'deepseek-chat';\n this.temperature = config.temperature ?? 0.7;\n this.maxTokens = config.maxTokens;\n this.topP = config.topP;\n this.systemPrompt = config.systemPrompt;\n\n // 处理工具配置,优先使用 rawTools\n if (config.rawTools && config.rawTools.length > 0) {\n // 将工具实例转换为 API 格式\n this.tools = config.rawTools.map(tool => ({\n type: 'function',\n function: {\n name: tool.name,\n description: tool.description,\n parameters: tool.parameters || {},\n },\n }));\n } else {\n // 使用直接提供的 API 格式工具\n this.tools = config.tools;\n }\n\n // 重命名端口\n Component.Port.I('prompt').attach(this);\n Component.Port.I('messages').attach(this);\n Component.Port.O('completion').attach(this);\n Component.Port.O('message').attach(this);\n }\n\n /**\n * 生成文本完成\n * @param prompt 提示文本\n * @returns 生成的文本\n */\n async generateCompletion(prompt: string): Promise<string> {\n const messages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n messages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提示\n messages.push({\n role: 'user',\n content: prompt,\n });\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 如果有工具定义,添加到请求中\n if (this.tools && this.tools.length > 0) {\n requestParams.tools = this.tools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 处理工具调用结果\n if (\n response.choices[0].message.tool_calls &&\n response.choices[0].message.tool_calls.length > 0\n ) {\n return JSON.stringify(response.choices[0].message);\n }\n\n return response.choices[0].message.content || '';\n }\n\n /**\n * 流式处理对话消息\n * @param messages 对话消息数组\n * @param options 可选的调用选项,包含临时工具列表\n * @returns 生成的流式响应消息异步生成器\n */\n async *streamChatCompletion(\n messages: Message[],\n options?: { temporaryTools?: unknown[] }\n ): AsyncGenerator<Partial<Message>> {\n // 转换消息格式 (复用现有逻辑)\n const formattedMessages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n formattedMessages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提供的消息\n formattedMessages.push(\n ...messages.map(msg => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const formattedMsg: any = {\n role: msg.role,\n content: msg.content,\n };\n\n if (msg.role === 'tool' && msg.tool_call_id) {\n formattedMsg.tool_call_id = msg.tool_call_id;\n }\n\n return formattedMsg;\n })\n );\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages: formattedMessages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n stream: true, // 开启流式模式\n };\n\n // 决定使用哪些工具\n const toolsToUse = options?.temporaryTools || this.tools;\n\n // 如果有工具定义,添加到请求中\n if (toolsToUse && toolsToUse.length > 0) {\n const formattedTools = toolsToUse.map(tool => {\n type ToolType = {\n type?: string;\n name?: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n\n const typedTool = tool as ToolType;\n\n if (typedTool.type === 'function') {\n return tool;\n }\n\n return {\n type: 'function',\n function: {\n name: typedTool.name,\n description: typedTool.description,\n parameters: typedTool.parameters || {},\n },\n };\n });\n\n requestParams.tools = formattedTools;\n }\n\n // 调用流式 API\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const stream = (await this.client.chat.completions.create(requestParams)) as any;\n\n // 处理流式响应\n for await (const chunk of stream) {\n const delta = chunk.choices[0]?.delta;\n\n if (delta?.content) {\n // 流式文本内容\n yield {\n role: 'assistant',\n content: delta.content,\n };\n }\n\n if (delta?.tool_calls) {\n // 流式工具调用(如果需要)\n yield {\n role: 'assistant',\n content: '',\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n tool_calls: delta.tool_calls.map((toolCall: any) => ({\n id: toolCall.id || '',\n function: {\n name: toolCall.function?.name || '',\n arguments: toolCall.function?.arguments || '',\n },\n type: 'function',\n tool_name: toolCall.function?.name || '',\n arguments: toolCall.function?.arguments || '',\n })),\n };\n }\n\n // 提取并返回 token 使用统计信息\n if (chunk.usage) {\n yield {\n role: 'assistant',\n content: '',\n usage: {\n completion_tokens: chunk.usage.completion_tokens || 0,\n prompt_tokens: chunk.usage.prompt_tokens || 0,\n prompt_cache_hit_tokens: chunk.usage.prompt_cache_hit_tokens,\n prompt_cache_miss_tokens: chunk.usage.prompt_cache_miss_tokens,\n total_tokens: chunk.usage.total_tokens || 0,\n },\n };\n }\n }\n }\n\n /**\n * 处理对话消息\n * @param messages 对话消息数组\n * @param options 可选的调用选项,包含临时工具列表\n * @returns 生成的响应消息\n */\n async chatCompletion(\n messages: Message[],\n options?: { temporaryTools?: unknown[] }\n ): Promise<Message> {\n // 转换消息格式\n const formattedMessages: Array<OpenAI.Chat.ChatCompletionMessageParam> = [];\n\n // 添加系统提示\n if (this.systemPrompt) {\n formattedMessages.push({\n role: 'system',\n content: this.systemPrompt,\n });\n }\n\n // 添加用户提供的消息\n formattedMessages.push(\n ...messages.map(msg => {\n // 基本消息结构\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const formattedMsg: any = {\n role: msg.role,\n content: msg.content,\n };\n\n // 如果有工具调用 ID,添加到消息中\n if (msg.role === 'tool' && msg.tool_call_id) {\n formattedMsg.tool_call_id = msg.tool_call_id;\n }\n\n return formattedMsg;\n })\n );\n\n // 创建请求参数\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const requestParams: any = {\n model: this.model,\n messages: formattedMessages,\n temperature: this.temperature,\n max_tokens: this.maxTokens,\n top_p: this.topP,\n };\n\n // 决定使用哪些工具\n // 如果提供了临时工具,优先使用临时工具\n const toolsToUse = options?.temporaryTools || this.tools;\n\n // 如果有工具定义,添加到请求中\n if (toolsToUse && toolsToUse.length > 0) {\n // 检查工具格式并转换,确保符合 Deepseek API 要求\n const formattedTools = toolsToUse.map(tool => {\n // 使用类型断言来处理 unknown 类型\n type ToolType = {\n type?: string;\n name?: string;\n description?: string;\n parameters?: Record<string, unknown>;\n };\n\n const typedTool = tool as ToolType;\n\n // 如果工具已经是 API 格式,直接返回\n if (typedTool.type === 'function') {\n return tool;\n }\n\n // 如果是简单工具实例,转换为 API 格式\n return {\n type: 'function',\n function: {\n name: typedTool.name,\n description: typedTool.description,\n parameters: typedTool.parameters || {},\n },\n };\n });\n\n requestParams.tools = formattedTools;\n }\n\n // 调用 API\n const response = await this.client.chat.completions.create(requestParams);\n\n // 解析响应\n const responseMessage = response.choices[0].message;\n\n // 转换为内部消息格式\n const result: Message = {\n role: 'assistant',\n content: responseMessage.content || '',\n };\n\n // 提取并添加 token 使用统计信息\n if (response.usage) {\n const usage = response.usage as typeof response.usage & {\n prompt_cache_hit_tokens?: number;\n prompt_cache_miss_tokens?: number;\n };\n result.usage = {\n completion_tokens: usage.completion_tokens || 0,\n prompt_tokens: usage.prompt_tokens || 0,\n prompt_cache_hit_tokens: usage.prompt_cache_hit_tokens,\n prompt_cache_miss_tokens: usage.prompt_cache_miss_tokens,\n total_tokens: usage.total_tokens || 0,\n };\n }\n\n // 如果有工具调用,添加到结果中\n if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {\n // 为了兼容 Agent 组件期望的格式,保留 function 和 type 字段\n // 同时为了满足内部 ToolCall 接口,也添加 tool_name 和 arguments 字段\n result.tool_calls = responseMessage.tool_calls.map(toolCall => {\n // 解析参数,确保是对象形式\n let args: Record<string, unknown>;\n\n const rawArgs = toolCall.function.arguments;\n\n if (typeof rawArgs === 'string') {\n const raw = rawArgs;\n try {\n args = raw && raw.trim().length > 0 ? (JSON.parse(raw) as Record<string, unknown>) : {};\n } catch {\n args = {};\n }\n } else if (rawArgs && typeof rawArgs === 'object') {\n args = rawArgs as Record<string, unknown>;\n } else {\n args = {};\n }\n\n return {\n id: toolCall.id,\n // 满足 Agent 组件期望的格式\n function: {\n name: toolCall.function.name,\n arguments: toolCall.function.arguments || '{}',\n },\n type: 'function',\n // 满足内部 ToolCall 接口\n tool_name: toolCall.function.name,\n arguments: args,\n };\n });\n }\n\n return result;\n }\n\n /**\n * 在独立模式下运行组件\n * @param input 输入参数,可以是提示文本或对话消息数组\n * @returns 生成的文本或响应消息\n */\n async run(input: string | Message[]): Promise<string | Message> {\n if (typeof input === 'string') {\n return this.generateCompletion(input);\n } else {\n return this.chatCompletion(input);\n }\n }\n\n /**\n * 在流水线中运行组件\n * @param $i 输入端口\n * @param $o 输出端口\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n _transform($i: any, $o: any) {\n // 处理文本提示输入\n $i('prompt').receive(async (prompt: string) => {\n try {\n const completion = await this.generateCompletion(prompt);\n $o('completion').send(completion);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('completion').send('API 调用错误');\n }\n });\n\n // 处理对话消息输入\n $i('messages').receive(async (messages: Message[]) => {\n try {\n const responseMessage = await this.chatCompletion(messages);\n $o('message').send(responseMessage);\n } catch (error) {\n console.error('Deepseek API 调用错误:', error);\n $o('message').send({\n role: 'assistant',\n content: 'API 调用错误',\n });\n }\n });\n }\n}\n\n// 默认导出组件\nexport default Deepseek;\n"],"mappings":";AAAA,SAAS,iBAAiB;AAC1B,OAAO,YAAY;AAoKnB,IAAM,WAAN,cAAuB,UAAU;AAAA,EAY/B,YAAY,QAAwB;AAClC,UAAM,CAAC,CAAC;AAGR,SAAK,SAAS,IAAI,OAAO;AAAA,MACvB,QAAQ,OAAO;AAAA,MACf,SAAS,OAAO,WAAW;AAAA,MAC3B,yBAAyB,OAAO,2BAA2B;AAAA,IAC7D,CAAC;AAGD,SAAK,QAAQ,OAAO,SAAS;AAC7B,SAAK,cAAc,OAAO,eAAe;AACzC,SAAK,YAAY,OAAO;AACxB,SAAK,OAAO,OAAO;AACnB,SAAK,eAAe,OAAO;AAG3B,QAAI,OAAO,YAAY,OAAO,SAAS,SAAS,GAAG;AAEjD,WAAK,QAAQ,OAAO,SAAS,IAAI,WAAS;AAAA,QACxC,MAAM;AAAA,QACN,UAAU;AAAA,UACR,MAAM,KAAK;AAAA,UACX,aAAa,KAAK;AAAA,UAClB,YAAY,KAAK,cAAc,CAAC;AAAA,QAClC;AAAA,MACF,EAAE;AAAA,IACJ,OAAO;AAEL,WAAK,QAAQ,OAAO;AAAA,IACtB;AAGA,cAAU,KAAK,EAAE,QAAQ,EAAE,OAAO,IAAI;AACtC,cAAU,KAAK,EAAE,UAAU,EAAE,OAAO,IAAI;AACxC,cAAU,KAAK,EAAE,YAAY,EAAE,OAAO,IAAI;AAC1C,cAAU,KAAK,EAAE,SAAS,EAAE,OAAO,IAAI;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,mBAAmB,QAAiC;AACxD,UAAM,WAA0D,CAAC;AAGjE,QAAI,KAAK,cAAc;AACrB,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS,KAAK;AAAA,MAChB,CAAC;AAAA,IACH;AAGA,aAAS,KAAK;AAAA,MACZ,MAAM;AAAA,MACN,SAAS;AAAA,IACX,CAAC;AAID,UAAM,gBAAqB;AAAA,MACzB,OAAO,KAAK;AAAA,MACZ;AAAA,MACA,aAAa,KAAK;AAAA,MAClB,YAAY,KAAK;AAAA,MACjB,OAAO,KAAK;AAAA,IACd;AAGA,QAAI,KAAK,SAAS,KAAK,MAAM,SAAS,GAAG;AACvC,oBAAc,QAAQ,KAAK;AAAA,IAC7B;AAGA,UAAM,WAAW,MAAM,KAAK,OAAO,KAAK,YAAY,OAAO,aAAa;AAGxE,QACE,SAAS,QAAQ,CAAC,EAAE,QAAQ,cAC5B,SAAS,QAAQ,CAAC,EAAE,QAAQ,WAAW,SAAS,GAChD;AACA,aAAO,KAAK,UAAU,SAAS,QAAQ,CAAC,EAAE,OAAO;AAAA,IACnD;AAEA,WAAO,SAAS,QAAQ,CAAC,EAAE,QAAQ,WAAW;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,qBACL,UACA,SACkC;AAElC,UAAM,oBAAmE,CAAC;AAG1E,QAAI,KAAK,cAAc;AACrB,wBAAkB,KAAK;AAAA,QACrB,MAAM;AAAA,QACN,SAAS,KAAK;AAAA,MAChB,CAAC;AAAA,IACH;AAGA,sBAAkB;AAAA,MAChB,GAAG,SAAS,IAAI,SAAO;AAErB,cAAM,eAAoB;AAAA,UACxB,MAAM,IAAI;AAAA,UACV,SAAS,IAAI;AAAA,QACf;AAEA,YAAI,IAAI,SAAS,UAAU,IAAI,cAAc;AAC3C,uBAAa,eAAe,IAAI;AAAA,QAClC;AAEA,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAIA,UAAM,gBAAqB;AAAA,MACzB,OAAO,KAAK;AAAA,MACZ,UAAU;AAAA,MACV,aAAa,KAAK;AAAA,MAClB,YAAY,KAAK;AAAA,MACjB,OAAO,KAAK;AAAA,MACZ,QAAQ;AAAA;AAAA,IACV;AAGA,UAAM,aAAa,SAAS,kBAAkB,KAAK;AAGnD,QAAI,cAAc,WAAW,SAAS,GAAG;AACvC,YAAM,iBAAiB,WAAW,IAAI,UAAQ;AAQ5C,cAAM,YAAY;AAElB,YAAI,UAAU,SAAS,YAAY;AACjC,iBAAO;AAAA,QACT;AAEA,eAAO;AAAA,UACL,MAAM;AAAA,UACN,UAAU;AAAA,YACR,MAAM,UAAU;AAAA,YAChB,aAAa,UAAU;AAAA,YACvB,YAAY,UAAU,cAAc,CAAC;AAAA,UACvC;AAAA,QACF;AAAA,MACF,CAAC;AAED,oBAAc,QAAQ;AAAA,IACxB;AAIA,UAAM,SAAU,MAAM,KAAK,OAAO,KAAK,YAAY,OAAO,aAAa;AAGvE,qBAAiB,SAAS,QAAQ;AAChC,YAAM,QAAQ,MAAM,QAAQ,CAAC,GAAG;AAEhC,UAAI,OAAO,SAAS;AAElB,cAAM;AAAA,UACJ,MAAM;AAAA,UACN,SAAS,MAAM;AAAA,QACjB;AAAA,MACF;AAEA,UAAI,OAAO,YAAY;AAErB,cAAM;AAAA,UACJ,MAAM;AAAA,UACN,SAAS;AAAA;AAAA,UAET,YAAY,MAAM,WAAW,IAAI,CAAC,cAAmB;AAAA,YACnD,IAAI,SAAS,MAAM;AAAA,YACnB,UAAU;AAAA,cACR,MAAM,SAAS,UAAU,QAAQ;AAAA,cACjC,WAAW,SAAS,UAAU,aAAa;AAAA,YAC7C;AAAA,YACA,MAAM;AAAA,YACN,WAAW,SAAS,UAAU,QAAQ;AAAA,YACtC,WAAW,SAAS,UAAU,aAAa;AAAA,UAC7C,EAAE;AAAA,QACJ;AAAA,MACF;AAGA,UAAI,MAAM,OAAO;AACf,cAAM;AAAA,UACJ,MAAM;AAAA,UACN,SAAS;AAAA,UACT,OAAO;AAAA,YACL,mBAAmB,MAAM,MAAM,qBAAqB;AAAA,YACpD,eAAe,MAAM,MAAM,iBAAiB;AAAA,YAC5C,yBAAyB,MAAM,MAAM;AAAA,YACrC,0BAA0B,MAAM,MAAM;AAAA,YACtC,cAAc,MAAM,MAAM,gBAAgB;AAAA,UAC5C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,eACJ,UACA,SACkB;AAElB,UAAM,oBAAmE,CAAC;AAG1E,QAAI,KAAK,cAAc;AACrB,wBAAkB,KAAK;AAAA,QACrB,MAAM;AAAA,QACN,SAAS,KAAK;AAAA,MAChB,CAAC;AAAA,IACH;AAGA,sBAAkB;AAAA,MAChB,GAAG,SAAS,IAAI,SAAO;AAGrB,cAAM,eAAoB;AAAA,UACxB,MAAM,IAAI;AAAA,UACV,SAAS,IAAI;AAAA,QACf;AAGA,YAAI,IAAI,SAAS,UAAU,IAAI,cAAc;AAC3C,uBAAa,eAAe,IAAI;AAAA,QAClC;AAEA,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAIA,UAAM,gBAAqB;AAAA,MACzB,OAAO,KAAK;AAAA,MACZ,UAAU;AAAA,MACV,aAAa,KAAK;AAAA,MAClB,YAAY,KAAK;AAAA,MACjB,OAAO,KAAK;AAAA,IACd;AAIA,UAAM,aAAa,SAAS,kBAAkB,KAAK;AAGnD,QAAI,cAAc,WAAW,SAAS,GAAG;AAEvC,YAAM,iBAAiB,WAAW,IAAI,UAAQ;AAS5C,cAAM,YAAY;AAGlB,YAAI,UAAU,SAAS,YAAY;AACjC,iBAAO;AAAA,QACT;AAGA,eAAO;AAAA,UACL,MAAM;AAAA,UACN,UAAU;AAAA,YACR,MAAM,UAAU;AAAA,YAChB,aAAa,UAAU;AAAA,YACvB,YAAY,UAAU,cAAc,CAAC;AAAA,UACvC;AAAA,QACF;AAAA,MACF,CAAC;AAED,oBAAc,QAAQ;AAAA,IACxB;AAGA,UAAM,WAAW,MAAM,KAAK,OAAO,KAAK,YAAY,OAAO,aAAa;AAGxE,UAAM,kBAAkB,SAAS,QAAQ,CAAC,EAAE;AAG5C,UAAM,SAAkB;AAAA,MACtB,MAAM;AAAA,MACN,SAAS,gBAAgB,WAAW;AAAA,IACtC;AAGA,QAAI,SAAS,OAAO;AAClB,YAAM,QAAQ,SAAS;AAIvB,aAAO,QAAQ;AAAA,QACb,mBAAmB,MAAM,qBAAqB;AAAA,QAC9C,eAAe,MAAM,iBAAiB;AAAA,QACtC,yBAAyB,MAAM;AAAA,QAC/B,0BAA0B,MAAM;AAAA,QAChC,cAAc,MAAM,gBAAgB;AAAA,MACtC;AAAA,IACF;AAGA,QAAI,gBAAgB,cAAc,gBAAgB,WAAW,SAAS,GAAG;AAGvE,aAAO,aAAa,gBAAgB,WAAW,IAAI,cAAY;AAE7D,YAAI;AAEJ,cAAM,UAAU,SAAS,SAAS;AAElC,YAAI,OAAO,YAAY,UAAU;AAC/B,gBAAM,MAAM;AACZ,cAAI;AACF,mBAAO,OAAO,IAAI,KAAK,EAAE,SAAS,IAAK,KAAK,MAAM,GAAG,IAAgC,CAAC;AAAA,UACxF,QAAQ;AACN,mBAAO,CAAC;AAAA,UACV;AAAA,QACF,WAAW,WAAW,OAAO,YAAY,UAAU;AACjD,iBAAO;AAAA,QACT,OAAO;AACL,iBAAO,CAAC;AAAA,QACV;AAEA,eAAO;AAAA,UACL,IAAI,SAAS;AAAA;AAAA,UAEb,UAAU;AAAA,YACR,MAAM,SAAS,SAAS;AAAA,YACxB,WAAW,SAAS,SAAS,aAAa;AAAA,UAC5C;AAAA,UACA,MAAM;AAAA;AAAA,UAEN,WAAW,SAAS,SAAS;AAAA,UAC7B,WAAW;AAAA,QACb;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,IAAI,OAAsD;AAC9D,QAAI,OAAO,UAAU,UAAU;AAC7B,aAAO,KAAK,mBAAmB,KAAK;AAAA,IACtC,OAAO;AACL,aAAO,KAAK,eAAe,KAAK;AAAA,IAClC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAAW,IAAS,IAAS;AAE3B,OAAG,QAAQ,EAAE,QAAQ,OAAO,WAAmB;AAC7C,UAAI;AACF,cAAM,aAAa,MAAM,KAAK,mBAAmB,MAAM;AACvD,WAAG,YAAY,EAAE,KAAK,UAAU;AAAA,MAClC,SAAS,OAAO;AACd,gBAAQ,MAAM,0CAAsB,KAAK;AACzC,WAAG,YAAY,EAAE,KAAK,8BAAU;AAAA,MAClC;AAAA,IACF,CAAC;AAGD,OAAG,UAAU,EAAE,QAAQ,OAAO,aAAwB;AACpD,UAAI;AACF,cAAM,kBAAkB,MAAM,KAAK,eAAe,QAAQ;AAC1D,WAAG,SAAS,EAAE,KAAK,eAAe;AAAA,MACpC,SAAS,OAAO;AACd,gBAAQ,MAAM,0CAAsB,KAAK;AACzC,WAAG,SAAS,EAAE,KAAK;AAAA,UACjB,MAAM;AAAA,UACN,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAGA,IAAO,mBAAQ;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astack-tech/integrations",
3
- "version": "0.1.1-beta.4",
3
+ "version": "0.1.1-beta.5",
4
4
  "description": "Integrations for the Astack AI Framework.",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -90,6 +90,36 @@ export interface ToolCall {
90
90
  arguments: Record<string, unknown>;
91
91
  }
92
92
 
93
+ /**
94
+ * Token 使用统计
95
+ */
96
+ export interface TokenUsage {
97
+ /**
98
+ * 完成部分的 token 数量
99
+ */
100
+ completion_tokens: number;
101
+
102
+ /**
103
+ * 提示部分的 token 数量
104
+ */
105
+ prompt_tokens: number;
106
+
107
+ /**
108
+ * 提示缓存命中的 token 数量(可选)
109
+ */
110
+ prompt_cache_hit_tokens?: number;
111
+
112
+ /**
113
+ * 提示缓存未命中的 token 数量(可选)
114
+ */
115
+ prompt_cache_miss_tokens?: number;
116
+
117
+ /**
118
+ * 总 token 数量
119
+ */
120
+ total_tokens: number;
121
+ }
122
+
93
123
  /**
94
124
  * 对话消息类型
95
125
  */
@@ -113,6 +143,11 @@ export interface Message {
113
143
  * 工具调用 ID,用于工具响应消息
114
144
  */
115
145
  tool_call_id?: string;
146
+
147
+ /**
148
+ * Token 使用统计(可选)
149
+ */
150
+ usage?: TokenUsage;
116
151
  }
117
152
 
118
153
  /**
@@ -346,6 +381,21 @@ class Deepseek extends Component {
346
381
  })),
347
382
  };
348
383
  }
384
+
385
+ // 提取并返回 token 使用统计信息
386
+ if (chunk.usage) {
387
+ yield {
388
+ role: 'assistant',
389
+ content: '',
390
+ usage: {
391
+ completion_tokens: chunk.usage.completion_tokens || 0,
392
+ prompt_tokens: chunk.usage.prompt_tokens || 0,
393
+ prompt_cache_hit_tokens: chunk.usage.prompt_cache_hit_tokens,
394
+ prompt_cache_miss_tokens: chunk.usage.prompt_cache_miss_tokens,
395
+ total_tokens: chunk.usage.total_tokens || 0,
396
+ },
397
+ };
398
+ }
349
399
  }
350
400
  }
351
401
 
@@ -448,6 +498,21 @@ class Deepseek extends Component {
448
498
  content: responseMessage.content || '',
449
499
  };
450
500
 
501
+ // 提取并添加 token 使用统计信息
502
+ if (response.usage) {
503
+ const usage = response.usage as typeof response.usage & {
504
+ prompt_cache_hit_tokens?: number;
505
+ prompt_cache_miss_tokens?: number;
506
+ };
507
+ result.usage = {
508
+ completion_tokens: usage.completion_tokens || 0,
509
+ prompt_tokens: usage.prompt_tokens || 0,
510
+ prompt_cache_hit_tokens: usage.prompt_cache_hit_tokens,
511
+ prompt_cache_miss_tokens: usage.prompt_cache_miss_tokens,
512
+ total_tokens: usage.total_tokens || 0,
513
+ };
514
+ }
515
+
451
516
  // 如果有工具调用,添加到结果中
452
517
  if (responseMessage.tool_calls && responseMessage.tool_calls.length > 0) {
453
518
  // 为了兼容 Agent 组件期望的格式,保留 function 和 type 字段