@astack-tech/integrations 0.2.0-beta.7 → 0.2.0-beta.8
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/CHANGELOG.md +11 -0
- package/README.md +22 -1
- package/dist/index.cjs +27 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +27 -9
- package/dist/index.js.map +1 -1
- package/dist/model-provider/index.cjs +29 -10
- package/dist/model-provider/index.cjs.map +1 -1
- package/dist/model-provider/index.d.cts +85 -14
- package/dist/model-provider/index.d.ts +85 -14
- package/dist/model-provider/index.js +27 -9
- package/dist/model-provider/index.js.map +1 -1
- package/package.json +6 -4
- package/src/index.ts +7 -1
- package/src/model-provider/deepseek/index.ts +27 -433
- package/src/model-provider/index.ts +14 -0
- package/src/model-provider/openai-compatible/index.ts +499 -0
|
@@ -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 AssistantMessage as DeepseekAssistantMessage,\n type ChatCompletionOptions as DeepseekChatCompletionOptions,\n type DeepseekConfig,\n type Message as DeepseekMessage,\n type MessageRole as DeepseekMessageRole,\n type RawTool as DeepseekRawTool,\n type ResponseToolCall as DeepseekResponseToolCall,\n type StreamChunk as DeepseekStreamChunk,\n type StreamToolCall as DeepseekStreamToolCall,\n type TokenUsage as DeepseekTokenUsage,\n type ToolCall as DeepseekToolCall,\n} from './deepseek';\n","import { Component } from '@astack-tech/core';\nimport type { Port } from '@astack-tech/core';\nimport OpenAI from 'openai';\n\n/**\n * Options for the DeepSeek model provider.\n */\nexport interface DeepseekConfig {\n /** DeepSeek API key. */\n apiKey: string;\n /** Model name. Defaults to `deepseek-chat`. */\n model?: string | undefined;\n /** API base URL. Defaults to `https://api.deepseek.com/v1`. */\n baseURL?: string | undefined;\n /** Sampling temperature. Defaults to `0.7`. */\n temperature?: number | undefined;\n /** Maximum number of generated tokens. */\n maxTokens?: number | undefined;\n /** Nucleus sampling probability. */\n topP?: number | undefined;\n /** System prompt added before every request. */\n systemPrompt?: string | undefined;\n /**\n * Tools given as `{ name, description, parameters }` objects.\n * When this list is not empty, it takes precedence over `tools`.\n */\n rawTools?: RawTool[] | undefined;\n /** Tools in the OpenAI-compatible `{ type: 'function', function }` format. */\n tools?: unknown[] | undefined;\n /** Allows the OpenAI client to run in a browser. Defaults to `false`. */\n dangerouslyAllowBrowser?: boolean | undefined;\n /** Logs API errors to the console. Defaults to `false`. */\n verbose?: boolean | undefined;\n}\n\n/**\n * Tool description accepted by `rawTools` and `temporaryTools`.\n */\nexport interface RawTool {\n name: string;\n description: string;\n parameters?: Record<string, unknown> | undefined;\n}\n\n/**\n * Role of a chat message.\n */\nexport type MessageRole = 'system' | 'user' | 'assistant' | 'tool';\n\n/**\n * Tool call in the internal format.\n */\nexport interface ToolCall {\n /** Identifier assigned by the API. */\n id?: string | undefined;\n /** Name of the tool. */\n tool_name: string;\n /** Parsed arguments. */\n arguments: Record<string, unknown>;\n}\n\n/**\n * Tool call returned by `chatCompletion`. It carries both the OpenAI shape\n * (`type`, `function`) and the internal shape (`tool_name`, `arguments`).\n */\nexport interface ResponseToolCall {\n id: string;\n type: 'function';\n function: { name: string; arguments: string };\n tool_name: string;\n arguments: Record<string, unknown>;\n}\n\n/**\n * Partial tool call emitted while streaming. `arguments` holds the raw JSON fragment.\n */\nexport interface StreamToolCall {\n id: string;\n type: 'function';\n function: { name: string; arguments: string };\n tool_name: string;\n arguments: string;\n}\n\n/**\n * Token usage reported by the API.\n */\nexport interface TokenUsage {\n completion_tokens: number;\n prompt_tokens: number;\n prompt_cache_hit_tokens?: number | undefined;\n prompt_cache_miss_tokens?: number | undefined;\n total_tokens: number;\n}\n\n/**\n * Chat message accepted as input. It matches the agent message contract in\n * `@astack-tech/components`, so agent histories can be passed directly.\n */\nexport interface Message {\n /** One of `system`, `user`, `assistant` or `tool` (see `MessageRole`). */\n role: string;\n content?: string | undefined;\n /** Accepted for compatibility. Assistant tool calls are not forwarded to the API. */\n tool_calls?: readonly unknown[] | undefined;\n /** Identifier of the call that a `tool` message answers. */\n tool_call_id?: string | undefined;\n usage?: TokenUsage | undefined;\n}\n\n/**\n * Assistant message returned by `chatCompletion`.\n */\nexport interface AssistantMessage {\n role: 'assistant';\n content: string;\n tool_calls?: ResponseToolCall[] | undefined;\n usage?: TokenUsage | undefined;\n}\n\n/**\n * Chunk yielded by `streamChatCompletion`.\n */\nexport interface StreamChunk {\n role: 'assistant';\n content: string;\n tool_calls?: StreamToolCall[] | undefined;\n usage?: TokenUsage | undefined;\n}\n\n/**\n * Per-call options.\n */\nexport interface ChatCompletionOptions {\n /** Tools for this call only. They replace the configured tools. */\n temporaryTools?: unknown[] | undefined;\n}\n\ntype ChatMessageParam = OpenAI.Chat.ChatCompletionMessageParam;\ntype ChatTool = OpenAI.Chat.ChatCompletionTool;\n\ninterface DeepseekUsage {\n completion_tokens?: number;\n prompt_tokens?: number;\n total_tokens?: number;\n prompt_cache_hit_tokens?: number;\n prompt_cache_miss_tokens?: number;\n}\n\nconst DEFAULT_BASE_URL = 'https://api.deepseek.com/v1';\nconst DEFAULT_MODEL = 'deepseek-chat';\nconst DEFAULT_TEMPERATURE = 0.7;\nconst FALLBACK_TEXT = 'API call failed';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Converts a `{ name, description, parameters }` object to the OpenAI tool format.\n * Objects already in the OpenAI format are returned unchanged.\n */\nfunction toApiTool(tool: unknown): ChatTool {\n if (isRecord(tool) && tool['type'] === 'function') {\n return tool as unknown as ChatTool;\n }\n const raw = isRecord(tool) ? tool : {};\n const { name, description, parameters } = raw;\n return {\n type: 'function',\n function: {\n name: typeof name === 'string' ? name : '',\n description: typeof description === 'string' ? description : '',\n parameters: isRecord(parameters) ? parameters : {},\n },\n };\n}\n\n/**\n * Parses tool-call arguments. Anything that is not a JSON object becomes `{}`.\n */\nfunction parseArguments(raw: string): Record<string, unknown> {\n if (raw.trim().length === 0) {\n return {};\n }\n try {\n const parsed: unknown = JSON.parse(raw);\n return isRecord(parsed) ? parsed : {};\n } catch {\n return {};\n }\n}\n\nfunction mapUsage(usage: DeepseekUsage): TokenUsage {\n return {\n completion_tokens: usage.completion_tokens ?? 0,\n prompt_tokens: usage.prompt_tokens ?? 0,\n total_tokens: usage.total_tokens ?? 0,\n ...(usage.prompt_cache_hit_tokens === undefined\n ? {}\n : { prompt_cache_hit_tokens: usage.prompt_cache_hit_tokens }),\n ...(usage.prompt_cache_miss_tokens === undefined\n ? {}\n : { prompt_cache_miss_tokens: usage.prompt_cache_miss_tokens }),\n };\n}\n\n/**\n * DeepSeek model provider. It calls the DeepSeek API through the OpenAI-compatible client.\n *\n * Ports:\n * - `prompt` (in): a text prompt. The answer is sent on `completion`.\n * - `messages` (in): a list of chat messages. The reply is sent on `message`.\n */\nclass Deepseek extends Component {\n private readonly client: OpenAI;\n private readonly model: string;\n private readonly temperature: number;\n private readonly maxTokens: number | undefined;\n private readonly topP: number | undefined;\n private readonly systemPrompt: string | undefined;\n private readonly tools: unknown[] | undefined;\n private readonly verbose: boolean;\n\n constructor(config: DeepseekConfig) {\n super({});\n\n this.client = new OpenAI({\n apiKey: config.apiKey,\n baseURL: config.baseURL ?? DEFAULT_BASE_URL,\n dangerouslyAllowBrowser: config.dangerouslyAllowBrowser ?? false,\n });\n\n this.model = config.model ?? DEFAULT_MODEL;\n this.temperature = config.temperature ?? DEFAULT_TEMPERATURE;\n this.maxTokens = config.maxTokens;\n this.topP = config.topP;\n this.systemPrompt = config.systemPrompt;\n this.verbose = config.verbose ?? false;\n this.tools =\n config.rawTools !== undefined && config.rawTools.length > 0\n ? config.rawTools.map(toApiTool)\n : config.tools;\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 * Generates a completion for a single prompt.\n *\n * @returns The text answer, or the JSON-encoded assistant message when it contains tool calls.\n */\n async generateCompletion(prompt: string): Promise<string> {\n const response = await this.client.chat.completions.create({\n ...this.baseRequest(),\n messages: [...this.systemMessages(), { role: 'user', content: prompt }],\n ...this.toolsParam(this.tools),\n });\n\n const message = this.firstMessage(response);\n if (message.tool_calls !== undefined && message.tool_calls.length > 0) {\n return JSON.stringify(message);\n }\n return message.content ?? '';\n }\n\n /**\n * Sends a conversation and returns the assistant reply.\n */\n async chatCompletion(\n messages: Message[],\n options?: ChatCompletionOptions\n ): Promise<AssistantMessage> {\n const response = await this.client.chat.completions.create({\n ...this.baseRequest(),\n messages: this.formatMessages(messages),\n ...this.toolsParam(options?.temporaryTools ?? this.tools),\n });\n\n const message = this.firstMessage(response);\n const result: AssistantMessage = { role: 'assistant', content: message.content ?? '' };\n\n if (response.usage !== undefined) {\n result.usage = mapUsage(response.usage);\n }\n\n if (message.tool_calls !== undefined && message.tool_calls.length > 0) {\n result.tool_calls = message.tool_calls.map(toolCall => {\n if (toolCall.type !== 'function') {\n throw new Error(`Unsupported tool call type: ${toolCall.type}`);\n }\n const rawArguments = toolCall.function.arguments;\n return {\n id: toolCall.id,\n type: 'function',\n function: {\n name: toolCall.function.name,\n arguments: rawArguments.length > 0 ? rawArguments : '{}',\n },\n tool_name: toolCall.function.name,\n arguments: parseArguments(rawArguments),\n };\n });\n }\n\n return result;\n }\n\n /**\n * Streams the assistant reply. Each chunk holds a text delta, tool-call deltas, or usage.\n */\n async *streamChatCompletion(\n messages: Message[],\n options?: ChatCompletionOptions\n ): AsyncGenerator<StreamChunk> {\n const stream = await this.client.chat.completions.create({\n ...this.baseRequest(),\n messages: this.formatMessages(messages),\n ...this.toolsParam(options?.temporaryTools ?? this.tools),\n stream: true,\n });\n\n for await (const chunk of stream) {\n const delta = chunk.choices[0]?.delta;\n\n if (delta?.content) {\n yield { role: 'assistant', content: delta.content };\n }\n\n if (delta?.tool_calls) {\n yield {\n role: 'assistant',\n content: '',\n tool_calls: delta.tool_calls.map(toolCall => {\n const name = toolCall.function?.name ?? '';\n const args = toolCall.function?.arguments ?? '';\n return {\n id: toolCall.id ?? '',\n type: 'function',\n function: { name, arguments: args },\n tool_name: name,\n arguments: args,\n };\n }),\n };\n }\n\n if (chunk.usage) {\n yield { role: 'assistant', content: '', usage: mapUsage(chunk.usage) };\n }\n }\n }\n\n /**\n * Runs the model outside a pipeline.\n *\n * @param input A prompt string or a list of messages.\n */\n override run(input: string | Message[]): Promise<string | AssistantMessage> {\n return typeof input === 'string' ? this.generateCompletion(input) : this.chatCompletion(input);\n }\n\n /**\n * Connects the `prompt` and `messages` input ports to the model.\n * API errors produce a fallback value so the pipeline keeps flowing.\n */\n override _transform($i: Port, $o: Port): void {\n $i('prompt').receive((prompt: string) => {\n this.generateCompletion(prompt).then(\n completion => {\n $o('completion').send(completion);\n },\n (error: unknown) => {\n this.logError(error);\n $o('completion').send(FALLBACK_TEXT);\n }\n );\n });\n\n $i('messages').receive((messages: Message[]) => {\n this.chatCompletion(messages).then(\n message => {\n $o('message').send(message);\n },\n (error: unknown) => {\n this.logError(error);\n $o('message').send({ role: 'assistant', content: FALLBACK_TEXT });\n }\n );\n });\n }\n\n private baseRequest(): {\n model: string;\n temperature: number;\n max_tokens?: number;\n top_p?: number;\n } {\n return {\n model: this.model,\n temperature: this.temperature,\n ...(this.maxTokens === undefined ? {} : { max_tokens: this.maxTokens }),\n ...(this.topP === undefined ? {} : { top_p: this.topP }),\n };\n }\n\n private toolsParam(tools: unknown[] | undefined): { tools?: ChatTool[] } {\n return tools !== undefined && tools.length > 0 ? { tools: tools.map(toApiTool) } : {};\n }\n\n private systemMessages(): ChatMessageParam[] {\n return this.systemPrompt ? [{ role: 'system', content: this.systemPrompt }] : [];\n }\n\n /**\n * Converts input messages to API messages. Assistant `tool_calls` are not forwarded:\n * agents send tool results back as user messages, and the API rejects assistant tool\n * calls that are not followed by tool messages.\n */\n private formatMessages(messages: Message[]): ChatMessageParam[] {\n return [\n ...this.systemMessages(),\n ...messages.map(\n (message): ChatMessageParam =>\n ({\n role: message.role,\n content: message.content,\n ...(message.role === 'tool' && message.tool_call_id\n ? { tool_call_id: message.tool_call_id }\n : {}),\n }) as ChatMessageParam\n ),\n ];\n }\n\n private firstMessage(response: OpenAI.Chat.ChatCompletion): OpenAI.Chat.ChatCompletionMessage {\n const choice = response.choices[0];\n if (choice === undefined) {\n throw new Error('DeepSeek returned no choices.');\n }\n return choice.message;\n }\n\n private logError(error: unknown): void {\n if (this.verbose) {\n // eslint-disable-next-line no-console -- opt-in diagnostics controlled by `verbose`.\n console.error('[Deepseek] API call failed:', error);\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/openai-compatible/index.ts","../../src/model-provider/deepseek/index.ts"],"sourcesContent":["export {\n default as Deepseek,\n type AssistantMessage as DeepseekAssistantMessage,\n type ChatCompletionOptions as DeepseekChatCompletionOptions,\n type DeepseekConfig,\n type Message as DeepseekMessage,\n type MessageRole as DeepseekMessageRole,\n type RawTool as DeepseekRawTool,\n type ResponseToolCall as DeepseekResponseToolCall,\n type StreamChunk as DeepseekStreamChunk,\n type StreamToolCall as DeepseekStreamToolCall,\n type TokenUsage as DeepseekTokenUsage,\n type ToolCall as DeepseekToolCall,\n} from './deepseek';\nexport {\n default as OpenAICompatible,\n type AssistantMessage,\n type ChatCompletionOptions,\n type Message,\n type MessageRole,\n type OpenAICompatibleConfig,\n type RawTool,\n type ResponseToolCall,\n type StreamChunk,\n type StreamToolCall,\n type TokenUsage,\n type ToolCall,\n} from './openai-compatible';\n","import { Component } from '@astack-tech/core';\nimport type { Port } from '@astack-tech/core';\nimport OpenAI from 'openai';\n\n/**\n * Options for a provider that speaks the OpenAI chat completions API.\n */\nexport interface OpenAICompatibleConfig {\n /** API key of the provider. */\n apiKey: string;\n /** Model name, for example `gpt-4o-mini`, `qwen-plus` or `llama3.1`. */\n model: string;\n /** API base URL. Defaults to `https://api.openai.com/v1`. */\n baseURL?: string | undefined;\n /** Provider name used in errors and logs. Defaults to `The model API`. */\n name?: string | undefined;\n /** Sampling temperature. Defaults to `0.7`. */\n temperature?: number | undefined;\n /** Maximum number of generated tokens. */\n maxTokens?: number | undefined;\n /** Nucleus sampling probability. */\n topP?: number | undefined;\n /** System prompt added before every request. */\n systemPrompt?: string | undefined;\n /**\n * Tools given as `{ name, description, parameters }` objects.\n * When this list is not empty, it takes precedence over `tools`.\n */\n rawTools?: RawTool[] | undefined;\n /** Tools in the OpenAI-compatible `{ type: 'function', function }` format. */\n tools?: unknown[] | undefined;\n /** Allows the OpenAI client to run in a browser. Defaults to `false`. */\n dangerouslyAllowBrowser?: boolean | undefined;\n /** Logs API errors to the console. Defaults to `false`. */\n verbose?: boolean | undefined;\n}\n\n/**\n * Tool description accepted by `rawTools` and `temporaryTools`.\n */\nexport interface RawTool {\n /** Unique tool name. */\n name: string;\n /** Description that tells the model when to use the tool. */\n description: string;\n /** JSON Schema of the arguments. Defaults to `{}`. */\n parameters?: Record<string, unknown> | undefined;\n}\n\n/**\n * Role of a chat message.\n */\nexport type MessageRole = 'system' | 'user' | 'assistant' | 'tool';\n\n/**\n * Tool call in the internal format.\n */\nexport interface ToolCall {\n /** Identifier assigned by the API. */\n id?: string | undefined;\n /** Name of the tool. */\n tool_name: string;\n /** Parsed arguments. */\n arguments: Record<string, unknown>;\n}\n\n/**\n * Tool call returned by `chatCompletion`. It carries both the OpenAI shape\n * (`type`, `function`) and the internal shape (`tool_name`, `arguments`).\n */\nexport interface ResponseToolCall {\n /** Identifier assigned by the API. A `tool` message answers the call with it. */\n id: string;\n /** Always `function`. */\n type: 'function';\n /** The call in the OpenAI shape: function name and raw JSON arguments. An empty argument string is sent as `{}`. */\n function: {\n /** Name of the tool to call. */\n name: string;\n /** Arguments as JSON text. */\n arguments: string;\n };\n /** Name of the tool, same as `function.name`. */\n tool_name: string;\n /** Parsed arguments. JSON that is not an object becomes `{}`. */\n arguments: Record<string, unknown>;\n}\n\n/**\n * Partial tool call emitted while streaming. `arguments` holds the raw JSON fragment.\n */\nexport interface StreamToolCall {\n /** Identifier assigned by the API. Only the first delta of a call carries it; later deltas have `''`. */\n id: string;\n /** Always `function`. */\n type: 'function';\n /** The delta in the OpenAI shape. `arguments` holds only this delta's JSON fragment. */\n function: {\n /** Name of the tool to call. */\n name: string;\n /** Arguments as JSON text. */\n arguments: string;\n };\n /** Name of the tool when this delta carries it, otherwise `''`. */\n tool_name: string;\n /** Raw JSON fragment of this delta. Concatenate the fragments of a call to get its arguments. */\n arguments: string;\n}\n\n/**\n * Token usage reported by the API.\n */\nexport interface TokenUsage {\n /** Tokens in the generated reply. */\n completion_tokens: number;\n /** Tokens in the request. */\n prompt_tokens: number;\n /** Prompt tokens served from the provider's context cache (reported by DeepSeek). */\n prompt_cache_hit_tokens?: number | undefined;\n /** Prompt tokens not served from the cache. */\n prompt_cache_miss_tokens?: number | undefined;\n /** Sum of prompt and completion tokens. */\n total_tokens: number;\n}\n\n/**\n * Chat message accepted as input. It matches the agent message contract in\n * `@astack-tech/components`, so agent histories can be passed directly.\n */\nexport interface Message {\n /** One of `system`, `user`, `assistant` or `tool` (see `MessageRole`). */\n role: string;\n /** Text content. Omitted content is sent as no content. */\n content?: string | undefined;\n /** Accepted for compatibility. Assistant tool calls are not forwarded to the API. */\n tool_calls?: readonly unknown[] | undefined;\n /** Identifier of the call that a `tool` message answers. */\n tool_call_id?: string | undefined;\n /** Ignored on input. Present so agent histories can be passed unchanged. */\n usage?: TokenUsage | undefined;\n}\n\n/**\n * Assistant message returned by `chatCompletion`.\n */\nexport interface AssistantMessage {\n /** Always `assistant`. */\n role: 'assistant';\n /** Reply text. Empty when the model only calls tools. */\n content: string;\n /** Tool calls requested by the model, if any. */\n tool_calls?: ResponseToolCall[] | undefined;\n /** Token usage of this request, when the API reports it. */\n usage?: TokenUsage | undefined;\n}\n\n/**\n * Chunk yielded by `streamChatCompletion`.\n */\nexport interface StreamChunk {\n /** Always `assistant`. */\n role: 'assistant';\n /** Text delta. Empty in chunks that carry tool calls or usage. */\n content: string;\n /** Tool-call deltas in this chunk. */\n tool_calls?: StreamToolCall[] | undefined;\n /** Token usage. Sent once, in the final chunk, when the API reports it. */\n usage?: TokenUsage | undefined;\n}\n\n/**\n * Per-call options.\n */\nexport interface ChatCompletionOptions {\n /** Tools for this call only. They replace the configured tools. */\n temporaryTools?: unknown[] | undefined;\n}\n\ntype ChatMessageParam = OpenAI.Chat.ChatCompletionMessageParam;\ntype ChatTool = OpenAI.Chat.ChatCompletionTool;\n\ninterface ApiUsage {\n completion_tokens?: number;\n prompt_tokens?: number;\n total_tokens?: number;\n prompt_cache_hit_tokens?: number;\n prompt_cache_miss_tokens?: number;\n}\n\nconst DEFAULT_BASE_URL = 'https://api.openai.com/v1';\nconst DEFAULT_NAME = 'The model API';\nconst DEFAULT_TEMPERATURE = 0.7;\nconst FALLBACK_TEXT = 'API call failed';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Converts a `{ name, description, parameters }` object to the OpenAI tool format.\n * Objects already in the OpenAI format are returned unchanged.\n */\nfunction toApiTool(tool: unknown): ChatTool {\n if (isRecord(tool) && tool['type'] === 'function') {\n return tool as unknown as ChatTool;\n }\n const raw = isRecord(tool) ? tool : {};\n const { name, description, parameters } = raw;\n return {\n type: 'function',\n function: {\n name: typeof name === 'string' ? name : '',\n description: typeof description === 'string' ? description : '',\n parameters: isRecord(parameters) ? parameters : {},\n },\n };\n}\n\n/**\n * Parses tool-call arguments. Anything that is not a JSON object becomes `{}`.\n */\nfunction parseArguments(raw: string): Record<string, unknown> {\n if (raw.trim().length === 0) {\n return {};\n }\n try {\n const parsed: unknown = JSON.parse(raw);\n return isRecord(parsed) ? parsed : {};\n } catch {\n return {};\n }\n}\n\nfunction mapUsage(usage: ApiUsage): TokenUsage {\n return {\n completion_tokens: usage.completion_tokens ?? 0,\n prompt_tokens: usage.prompt_tokens ?? 0,\n total_tokens: usage.total_tokens ?? 0,\n ...(usage.prompt_cache_hit_tokens === undefined\n ? {}\n : { prompt_cache_hit_tokens: usage.prompt_cache_hit_tokens }),\n ...(usage.prompt_cache_miss_tokens === undefined\n ? {}\n : { prompt_cache_miss_tokens: usage.prompt_cache_miss_tokens }),\n };\n}\n\n/**\n * Model provider for any API that speaks the OpenAI chat completions protocol:\n * OpenAI itself, and the compatible endpoints of DeepSeek, Qwen, Moonshot, Ollama,\n * vLLM and others. Set `baseURL` and `model` for the provider you use.\n *\n * Ports:\n * - `prompt` (in): a text prompt. The answer is sent on `completion`.\n * - `messages` (in): a list of chat messages. The reply is sent on `message`.\n */\nclass OpenAICompatible extends Component {\n private readonly client: OpenAI;\n private readonly model: string;\n private readonly temperature: number;\n private readonly maxTokens: number | undefined;\n private readonly topP: number | undefined;\n private readonly systemPrompt: string | undefined;\n private readonly tools: unknown[] | undefined;\n private readonly verbose: boolean;\n private readonly name: string;\n\n constructor(config: OpenAICompatibleConfig) {\n super({});\n\n this.client = new OpenAI({\n apiKey: config.apiKey,\n baseURL: config.baseURL ?? DEFAULT_BASE_URL,\n dangerouslyAllowBrowser: config.dangerouslyAllowBrowser ?? false,\n });\n\n this.model = config.model;\n this.name = config.name ?? DEFAULT_NAME;\n this.temperature = config.temperature ?? DEFAULT_TEMPERATURE;\n this.maxTokens = config.maxTokens;\n this.topP = config.topP;\n this.systemPrompt = config.systemPrompt;\n this.verbose = config.verbose ?? false;\n this.tools =\n config.rawTools !== undefined && config.rawTools.length > 0\n ? config.rawTools.map(toApiTool)\n : config.tools;\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 * Generates a completion for a single prompt.\n *\n * @returns The text answer, or the JSON-encoded assistant message when it contains tool calls.\n */\n async generateCompletion(prompt: string): Promise<string> {\n const response = await this.client.chat.completions.create({\n ...this.baseRequest(),\n messages: [...this.systemMessages(), { role: 'user', content: prompt }],\n ...this.toolsParam(this.tools),\n });\n\n const message = this.firstMessage(response);\n if (message.tool_calls !== undefined && message.tool_calls.length > 0) {\n return JSON.stringify(message);\n }\n return message.content ?? '';\n }\n\n /**\n * Sends a conversation and returns the assistant reply.\n */\n async chatCompletion(\n messages: Message[],\n options?: ChatCompletionOptions\n ): Promise<AssistantMessage> {\n const response = await this.client.chat.completions.create({\n ...this.baseRequest(),\n messages: this.formatMessages(messages),\n ...this.toolsParam(options?.temporaryTools ?? this.tools),\n });\n\n const message = this.firstMessage(response);\n const result: AssistantMessage = { role: 'assistant', content: message.content ?? '' };\n\n if (response.usage !== undefined) {\n result.usage = mapUsage(response.usage);\n }\n\n if (message.tool_calls !== undefined && message.tool_calls.length > 0) {\n result.tool_calls = message.tool_calls.map(toolCall => {\n if (toolCall.type !== 'function') {\n throw new Error(`Unsupported tool call type: ${toolCall.type}`);\n }\n const rawArguments = toolCall.function.arguments;\n return {\n id: toolCall.id,\n type: 'function',\n function: {\n name: toolCall.function.name,\n arguments: rawArguments.length > 0 ? rawArguments : '{}',\n },\n tool_name: toolCall.function.name,\n arguments: parseArguments(rawArguments),\n };\n });\n }\n\n return result;\n }\n\n /**\n * Streams the assistant reply. Each chunk holds a text delta, tool-call deltas, or usage.\n */\n async *streamChatCompletion(\n messages: Message[],\n options?: ChatCompletionOptions\n ): AsyncGenerator<StreamChunk> {\n const stream = await this.client.chat.completions.create({\n ...this.baseRequest(),\n messages: this.formatMessages(messages),\n ...this.toolsParam(options?.temporaryTools ?? this.tools),\n stream: true,\n });\n\n for await (const chunk of stream) {\n const delta = chunk.choices[0]?.delta;\n\n if (delta?.content) {\n yield { role: 'assistant', content: delta.content };\n }\n\n if (delta?.tool_calls) {\n yield {\n role: 'assistant',\n content: '',\n tool_calls: delta.tool_calls.map(toolCall => {\n const name = toolCall.function?.name ?? '';\n const args = toolCall.function?.arguments ?? '';\n return {\n id: toolCall.id ?? '',\n type: 'function',\n function: { name, arguments: args },\n tool_name: name,\n arguments: args,\n };\n }),\n };\n }\n\n if (chunk.usage) {\n yield { role: 'assistant', content: '', usage: mapUsage(chunk.usage) };\n }\n }\n }\n\n /**\n * Runs the model outside a pipeline.\n *\n * @param input - A prompt string or a list of messages.\n */\n override run(input: string | Message[]): Promise<string | AssistantMessage> {\n return typeof input === 'string' ? this.generateCompletion(input) : this.chatCompletion(input);\n }\n\n /**\n * Connects the `prompt` and `messages` input ports to the model.\n * API errors produce a fallback value so the pipeline keeps flowing.\n */\n override _transform($i: Port, $o: Port): void {\n $i('prompt').receive((prompt: string) => {\n this.generateCompletion(prompt).then(\n completion => {\n $o('completion').send(completion);\n },\n (error: unknown) => {\n this.logError(error);\n $o('completion').send(FALLBACK_TEXT);\n }\n );\n });\n\n $i('messages').receive((messages: Message[]) => {\n this.chatCompletion(messages).then(\n message => {\n $o('message').send(message);\n },\n (error: unknown) => {\n this.logError(error);\n $o('message').send({ role: 'assistant', content: FALLBACK_TEXT });\n }\n );\n });\n }\n\n private baseRequest(): {\n model: string;\n temperature: number;\n max_tokens?: number;\n top_p?: number;\n } {\n return {\n model: this.model,\n temperature: this.temperature,\n ...(this.maxTokens === undefined ? {} : { max_tokens: this.maxTokens }),\n ...(this.topP === undefined ? {} : { top_p: this.topP }),\n };\n }\n\n private toolsParam(tools: unknown[] | undefined): { tools?: ChatTool[] } {\n return tools !== undefined && tools.length > 0 ? { tools: tools.map(toApiTool) } : {};\n }\n\n private systemMessages(): ChatMessageParam[] {\n return this.systemPrompt ? [{ role: 'system', content: this.systemPrompt }] : [];\n }\n\n /**\n * Converts input messages to API messages. Assistant `tool_calls` are not forwarded:\n * agents send tool results back as user messages, and the API rejects assistant tool\n * calls that are not followed by tool messages.\n */\n private formatMessages(messages: Message[]): ChatMessageParam[] {\n return [\n ...this.systemMessages(),\n ...messages.map(\n (message): ChatMessageParam =>\n ({\n role: message.role,\n content: message.content,\n ...(message.role === 'tool' && message.tool_call_id\n ? { tool_call_id: message.tool_call_id }\n : {}),\n }) as ChatMessageParam\n ),\n ];\n }\n\n private firstMessage(response: OpenAI.Chat.ChatCompletion): OpenAI.Chat.ChatCompletionMessage {\n const choice = response.choices[0];\n if (choice === undefined) {\n throw new Error(`${this.name} returned no choices.`);\n }\n return choice.message;\n }\n\n private logError(error: unknown): void {\n if (this.verbose) {\n // eslint-disable-next-line no-console -- opt-in diagnostics controlled by `verbose`.\n console.error(`[${this.name}] API call failed:`, error);\n }\n }\n}\n\nexport default OpenAICompatible;\n","import OpenAICompatible from '../openai-compatible';\nimport type { OpenAICompatibleConfig } from '../openai-compatible';\n\nexport type {\n AssistantMessage,\n ChatCompletionOptions,\n Message,\n MessageRole,\n RawTool,\n ResponseToolCall,\n StreamChunk,\n StreamToolCall,\n TokenUsage,\n ToolCall,\n} from '../openai-compatible';\n\nconst DEFAULT_BASE_URL = 'https://api.deepseek.com/v1';\nconst DEFAULT_MODEL = 'deepseek-chat';\n\n/**\n * Options for the DeepSeek model provider. They are the options of\n * `OpenAICompatible`, with DeepSeek's endpoint and model as defaults.\n */\nexport interface DeepseekConfig extends Omit<OpenAICompatibleConfig, 'model' | 'name'> {\n /** Model name. Defaults to `deepseek-chat`. */\n model?: string | undefined;\n /** API base URL. Defaults to `https://api.deepseek.com/v1`. */\n baseURL?: string | undefined;\n}\n\n/**\n * DeepSeek model provider: `OpenAICompatible` set up for the DeepSeek API.\n *\n * Ports:\n * - `prompt` (in): a text prompt. The answer is sent on `completion`.\n * - `messages` (in): a list of chat messages. The reply is sent on `message`.\n */\nclass Deepseek extends OpenAICompatible {\n constructor(config: DeepseekConfig) {\n super({\n ...config,\n model: config.model ?? DEFAULT_MODEL,\n baseURL: config.baseURL ?? DEFAULT_BASE_URL,\n name: 'DeepSeek',\n });\n }\n}\n\nexport default Deepseek;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,kBAA0B;AAE1B,oBAAmB;AA2LnB,IAAM,mBAAmB;AACzB,IAAM,eAAe;AACrB,IAAM,sBAAsB;AAC5B,IAAM,gBAAgB;AAEtB,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAMA,SAAS,UAAU,MAAyB;AAC1C,MAAI,SAAS,IAAI,KAAK,KAAK,MAAM,MAAM,YAAY;AACjD,WAAO;AAAA,EACT;AACA,QAAM,MAAM,SAAS,IAAI,IAAI,OAAO,CAAC;AACrC,QAAM,EAAE,MAAM,aAAa,WAAW,IAAI;AAC1C,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU;AAAA,MACR,MAAM,OAAO,SAAS,WAAW,OAAO;AAAA,MACxC,aAAa,OAAO,gBAAgB,WAAW,cAAc;AAAA,MAC7D,YAAY,SAAS,UAAU,IAAI,aAAa,CAAC;AAAA,IACnD;AAAA,EACF;AACF;AAKA,SAAS,eAAe,KAAsC;AAC5D,MAAI,IAAI,KAAK,EAAE,WAAW,GAAG;AAC3B,WAAO,CAAC;AAAA,EACV;AACA,MAAI;AACF,UAAM,SAAkB,KAAK,MAAM,GAAG;AACtC,WAAO,SAAS,MAAM,IAAI,SAAS,CAAC;AAAA,EACtC,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,SAAS,SAAS,OAA6B;AAC7C,SAAO;AAAA,IACL,mBAAmB,MAAM,qBAAqB;AAAA,IAC9C,eAAe,MAAM,iBAAiB;AAAA,IACtC,cAAc,MAAM,gBAAgB;AAAA,IACpC,GAAI,MAAM,4BAA4B,SAClC,CAAC,IACD,EAAE,yBAAyB,MAAM,wBAAwB;AAAA,IAC7D,GAAI,MAAM,6BAA6B,SACnC,CAAC,IACD,EAAE,0BAA0B,MAAM,yBAAyB;AAAA,EACjE;AACF;AAWA,IAAM,mBAAN,cAA+B,sBAAU;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,QAAgC;AAC1C,UAAM,CAAC,CAAC;AAER,SAAK,SAAS,IAAI,cAAAA,QAAO;AAAA,MACvB,QAAQ,OAAO;AAAA,MACf,SAAS,OAAO,WAAW;AAAA,MAC3B,yBAAyB,OAAO,2BAA2B;AAAA,IAC7D,CAAC;AAED,SAAK,QAAQ,OAAO;AACpB,SAAK,OAAO,OAAO,QAAQ;AAC3B,SAAK,cAAc,OAAO,eAAe;AACzC,SAAK,YAAY,OAAO;AACxB,SAAK,OAAO,OAAO;AACnB,SAAK,eAAe,OAAO;AAC3B,SAAK,UAAU,OAAO,WAAW;AACjC,SAAK,QACH,OAAO,aAAa,UAAa,OAAO,SAAS,SAAS,IACtD,OAAO,SAAS,IAAI,SAAS,IAC7B,OAAO;AAEb,0BAAU,KAAK,EAAE,QAAQ,EAAE,OAAO,IAAI;AACtC,0BAAU,KAAK,EAAE,UAAU,EAAE,OAAO,IAAI;AACxC,0BAAU,KAAK,EAAE,YAAY,EAAE,OAAO,IAAI;AAC1C,0BAAU,KAAK,EAAE,SAAS,EAAE,OAAO,IAAI;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,mBAAmB,QAAiC;AACxD,UAAM,WAAW,MAAM,KAAK,OAAO,KAAK,YAAY,OAAO;AAAA,MACzD,GAAG,KAAK,YAAY;AAAA,MACpB,UAAU,CAAC,GAAG,KAAK,eAAe,GAAG,EAAE,MAAM,QAAQ,SAAS,OAAO,CAAC;AAAA,MACtE,GAAG,KAAK,WAAW,KAAK,KAAK;AAAA,IAC/B,CAAC;AAED,UAAM,UAAU,KAAK,aAAa,QAAQ;AAC1C,QAAI,QAAQ,eAAe,UAAa,QAAQ,WAAW,SAAS,GAAG;AACrE,aAAO,KAAK,UAAU,OAAO;AAAA,IAC/B;AACA,WAAO,QAAQ,WAAW;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eACJ,UACA,SAC2B;AAC3B,UAAM,WAAW,MAAM,KAAK,OAAO,KAAK,YAAY,OAAO;AAAA,MACzD,GAAG,KAAK,YAAY;AAAA,MACpB,UAAU,KAAK,eAAe,QAAQ;AAAA,MACtC,GAAG,KAAK,WAAW,SAAS,kBAAkB,KAAK,KAAK;AAAA,IAC1D,CAAC;AAED,UAAM,UAAU,KAAK,aAAa,QAAQ;AAC1C,UAAM,SAA2B,EAAE,MAAM,aAAa,SAAS,QAAQ,WAAW,GAAG;AAErF,QAAI,SAAS,UAAU,QAAW;AAChC,aAAO,QAAQ,SAAS,SAAS,KAAK;AAAA,IACxC;AAEA,QAAI,QAAQ,eAAe,UAAa,QAAQ,WAAW,SAAS,GAAG;AACrE,aAAO,aAAa,QAAQ,WAAW,IAAI,cAAY;AACrD,YAAI,SAAS,SAAS,YAAY;AAChC,gBAAM,IAAI,MAAM,+BAA+B,SAAS,IAAI,EAAE;AAAA,QAChE;AACA,cAAM,eAAe,SAAS,SAAS;AACvC,eAAO;AAAA,UACL,IAAI,SAAS;AAAA,UACb,MAAM;AAAA,UACN,UAAU;AAAA,YACR,MAAM,SAAS,SAAS;AAAA,YACxB,WAAW,aAAa,SAAS,IAAI,eAAe;AAAA,UACtD;AAAA,UACA,WAAW,SAAS,SAAS;AAAA,UAC7B,WAAW,eAAe,YAAY;AAAA,QACxC;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,qBACL,UACA,SAC6B;AAC7B,UAAM,SAAS,MAAM,KAAK,OAAO,KAAK,YAAY,OAAO;AAAA,MACvD,GAAG,KAAK,YAAY;AAAA,MACpB,UAAU,KAAK,eAAe,QAAQ;AAAA,MACtC,GAAG,KAAK,WAAW,SAAS,kBAAkB,KAAK,KAAK;AAAA,MACxD,QAAQ;AAAA,IACV,CAAC;AAED,qBAAiB,SAAS,QAAQ;AAChC,YAAM,QAAQ,MAAM,QAAQ,CAAC,GAAG;AAEhC,UAAI,OAAO,SAAS;AAClB,cAAM,EAAE,MAAM,aAAa,SAAS,MAAM,QAAQ;AAAA,MACpD;AAEA,UAAI,OAAO,YAAY;AACrB,cAAM;AAAA,UACJ,MAAM;AAAA,UACN,SAAS;AAAA,UACT,YAAY,MAAM,WAAW,IAAI,cAAY;AAC3C,kBAAM,OAAO,SAAS,UAAU,QAAQ;AACxC,kBAAM,OAAO,SAAS,UAAU,aAAa;AAC7C,mBAAO;AAAA,cACL,IAAI,SAAS,MAAM;AAAA,cACnB,MAAM;AAAA,cACN,UAAU,EAAE,MAAM,WAAW,KAAK;AAAA,cAClC,WAAW;AAAA,cACX,WAAW;AAAA,YACb;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAEA,UAAI,MAAM,OAAO;AACf,cAAM,EAAE,MAAM,aAAa,SAAS,IAAI,OAAO,SAAS,MAAM,KAAK,EAAE;AAAA,MACvE;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOS,IAAI,OAA+D;AAC1E,WAAO,OAAO,UAAU,WAAW,KAAK,mBAAmB,KAAK,IAAI,KAAK,eAAe,KAAK;AAAA,EAC/F;AAAA;AAAA;AAAA;AAAA;AAAA,EAMS,WAAW,IAAU,IAAgB;AAC5C,OAAG,QAAQ,EAAE,QAAQ,CAAC,WAAmB;AACvC,WAAK,mBAAmB,MAAM,EAAE;AAAA,QAC9B,gBAAc;AACZ,aAAG,YAAY,EAAE,KAAK,UAAU;AAAA,QAClC;AAAA,QACA,CAAC,UAAmB;AAClB,eAAK,SAAS,KAAK;AACnB,aAAG,YAAY,EAAE,KAAK,aAAa;AAAA,QACrC;AAAA,MACF;AAAA,IACF,CAAC;AAED,OAAG,UAAU,EAAE,QAAQ,CAAC,aAAwB;AAC9C,WAAK,eAAe,QAAQ,EAAE;AAAA,QAC5B,aAAW;AACT,aAAG,SAAS,EAAE,KAAK,OAAO;AAAA,QAC5B;AAAA,QACA,CAAC,UAAmB;AAClB,eAAK,SAAS,KAAK;AACnB,aAAG,SAAS,EAAE,KAAK,EAAE,MAAM,aAAa,SAAS,cAAc,CAAC;AAAA,QAClE;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,cAKN;AACA,WAAO;AAAA,MACL,OAAO,KAAK;AAAA,MACZ,aAAa,KAAK;AAAA,MAClB,GAAI,KAAK,cAAc,SAAY,CAAC,IAAI,EAAE,YAAY,KAAK,UAAU;AAAA,MACrE,GAAI,KAAK,SAAS,SAAY,CAAC,IAAI,EAAE,OAAO,KAAK,KAAK;AAAA,IACxD;AAAA,EACF;AAAA,EAEQ,WAAW,OAAsD;AACvE,WAAO,UAAU,UAAa,MAAM,SAAS,IAAI,EAAE,OAAO,MAAM,IAAI,SAAS,EAAE,IAAI,CAAC;AAAA,EACtF;AAAA,EAEQ,iBAAqC;AAC3C,WAAO,KAAK,eAAe,CAAC,EAAE,MAAM,UAAU,SAAS,KAAK,aAAa,CAAC,IAAI,CAAC;AAAA,EACjF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,eAAe,UAAyC;AAC9D,WAAO;AAAA,MACL,GAAG,KAAK,eAAe;AAAA,MACvB,GAAG,SAAS;AAAA,QACV,CAAC,aACE;AAAA,UACC,MAAM,QAAQ;AAAA,UACd,SAAS,QAAQ;AAAA,UACjB,GAAI,QAAQ,SAAS,UAAU,QAAQ,eACnC,EAAE,cAAc,QAAQ,aAAa,IACrC,CAAC;AAAA,QACP;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,aAAa,UAAyE;AAC5F,UAAM,SAAS,SAAS,QAAQ,CAAC;AACjC,QAAI,WAAW,QAAW;AACxB,YAAM,IAAI,MAAM,GAAG,KAAK,IAAI,uBAAuB;AAAA,IACrD;AACA,WAAO,OAAO;AAAA,EAChB;AAAA,EAEQ,SAAS,OAAsB;AACrC,QAAI,KAAK,SAAS;AAEhB,cAAQ,MAAM,IAAI,KAAK,IAAI,sBAAsB,KAAK;AAAA,IACxD;AAAA,EACF;AACF;AAEA,IAAO,4BAAQ;;;AClef,IAAMC,oBAAmB;AACzB,IAAM,gBAAgB;AAoBtB,IAAM,WAAN,cAAuB,0BAAiB;AAAA,EACtC,YAAY,QAAwB;AAClC,UAAM;AAAA,MACJ,GAAG;AAAA,MACH,OAAO,OAAO,SAAS;AAAA,MACvB,SAAS,OAAO,WAAWA;AAAA,MAC3B,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AACF;AAEA,IAAO,mBAAQ;","names":["OpenAI","DEFAULT_BASE_URL"]}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { Component, Port } from '@astack-tech/core';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Options for the
|
|
4
|
+
* Options for a provider that speaks the OpenAI chat completions API.
|
|
5
5
|
*/
|
|
6
|
-
interface
|
|
7
|
-
/**
|
|
6
|
+
interface OpenAICompatibleConfig {
|
|
7
|
+
/** API key of the provider. */
|
|
8
8
|
apiKey: string;
|
|
9
|
-
/** Model name
|
|
10
|
-
model
|
|
11
|
-
/** API base URL. Defaults to `https://api.
|
|
9
|
+
/** Model name, for example `gpt-4o-mini`, `qwen-plus` or `llama3.1`. */
|
|
10
|
+
model: string;
|
|
11
|
+
/** API base URL. Defaults to `https://api.openai.com/v1`. */
|
|
12
12
|
baseURL?: string | undefined;
|
|
13
|
+
/** Provider name used in errors and logs. Defaults to `The model API`. */
|
|
14
|
+
name?: string | undefined;
|
|
13
15
|
/** Sampling temperature. Defaults to `0.7`. */
|
|
14
16
|
temperature?: number | undefined;
|
|
15
17
|
/** Maximum number of generated tokens. */
|
|
@@ -34,8 +36,11 @@ interface DeepseekConfig {
|
|
|
34
36
|
* Tool description accepted by `rawTools` and `temporaryTools`.
|
|
35
37
|
*/
|
|
36
38
|
interface RawTool {
|
|
39
|
+
/** Unique tool name. */
|
|
37
40
|
name: string;
|
|
41
|
+
/** Description that tells the model when to use the tool. */
|
|
38
42
|
description: string;
|
|
43
|
+
/** JSON Schema of the arguments. Defaults to `{}`. */
|
|
39
44
|
parameters?: Record<string, unknown> | undefined;
|
|
40
45
|
}
|
|
41
46
|
/**
|
|
@@ -58,36 +63,55 @@ interface ToolCall {
|
|
|
58
63
|
* (`type`, `function`) and the internal shape (`tool_name`, `arguments`).
|
|
59
64
|
*/
|
|
60
65
|
interface ResponseToolCall {
|
|
66
|
+
/** Identifier assigned by the API. A `tool` message answers the call with it. */
|
|
61
67
|
id: string;
|
|
68
|
+
/** Always `function`. */
|
|
62
69
|
type: 'function';
|
|
70
|
+
/** The call in the OpenAI shape: function name and raw JSON arguments. An empty argument string is sent as `{}`. */
|
|
63
71
|
function: {
|
|
72
|
+
/** Name of the tool to call. */
|
|
64
73
|
name: string;
|
|
74
|
+
/** Arguments as JSON text. */
|
|
65
75
|
arguments: string;
|
|
66
76
|
};
|
|
77
|
+
/** Name of the tool, same as `function.name`. */
|
|
67
78
|
tool_name: string;
|
|
79
|
+
/** Parsed arguments. JSON that is not an object becomes `{}`. */
|
|
68
80
|
arguments: Record<string, unknown>;
|
|
69
81
|
}
|
|
70
82
|
/**
|
|
71
83
|
* Partial tool call emitted while streaming. `arguments` holds the raw JSON fragment.
|
|
72
84
|
*/
|
|
73
85
|
interface StreamToolCall {
|
|
86
|
+
/** Identifier assigned by the API. Only the first delta of a call carries it; later deltas have `''`. */
|
|
74
87
|
id: string;
|
|
88
|
+
/** Always `function`. */
|
|
75
89
|
type: 'function';
|
|
90
|
+
/** The delta in the OpenAI shape. `arguments` holds only this delta's JSON fragment. */
|
|
76
91
|
function: {
|
|
92
|
+
/** Name of the tool to call. */
|
|
77
93
|
name: string;
|
|
94
|
+
/** Arguments as JSON text. */
|
|
78
95
|
arguments: string;
|
|
79
96
|
};
|
|
97
|
+
/** Name of the tool when this delta carries it, otherwise `''`. */
|
|
80
98
|
tool_name: string;
|
|
99
|
+
/** Raw JSON fragment of this delta. Concatenate the fragments of a call to get its arguments. */
|
|
81
100
|
arguments: string;
|
|
82
101
|
}
|
|
83
102
|
/**
|
|
84
103
|
* Token usage reported by the API.
|
|
85
104
|
*/
|
|
86
105
|
interface TokenUsage {
|
|
106
|
+
/** Tokens in the generated reply. */
|
|
87
107
|
completion_tokens: number;
|
|
108
|
+
/** Tokens in the request. */
|
|
88
109
|
prompt_tokens: number;
|
|
110
|
+
/** Prompt tokens served from the provider's context cache (reported by DeepSeek). */
|
|
89
111
|
prompt_cache_hit_tokens?: number | undefined;
|
|
112
|
+
/** Prompt tokens not served from the cache. */
|
|
90
113
|
prompt_cache_miss_tokens?: number | undefined;
|
|
114
|
+
/** Sum of prompt and completion tokens. */
|
|
91
115
|
total_tokens: number;
|
|
92
116
|
}
|
|
93
117
|
/**
|
|
@@ -97,29 +121,39 @@ interface TokenUsage {
|
|
|
97
121
|
interface Message {
|
|
98
122
|
/** One of `system`, `user`, `assistant` or `tool` (see `MessageRole`). */
|
|
99
123
|
role: string;
|
|
124
|
+
/** Text content. Omitted content is sent as no content. */
|
|
100
125
|
content?: string | undefined;
|
|
101
126
|
/** Accepted for compatibility. Assistant tool calls are not forwarded to the API. */
|
|
102
127
|
tool_calls?: readonly unknown[] | undefined;
|
|
103
128
|
/** Identifier of the call that a `tool` message answers. */
|
|
104
129
|
tool_call_id?: string | undefined;
|
|
130
|
+
/** Ignored on input. Present so agent histories can be passed unchanged. */
|
|
105
131
|
usage?: TokenUsage | undefined;
|
|
106
132
|
}
|
|
107
133
|
/**
|
|
108
134
|
* Assistant message returned by `chatCompletion`.
|
|
109
135
|
*/
|
|
110
136
|
interface AssistantMessage {
|
|
137
|
+
/** Always `assistant`. */
|
|
111
138
|
role: 'assistant';
|
|
139
|
+
/** Reply text. Empty when the model only calls tools. */
|
|
112
140
|
content: string;
|
|
141
|
+
/** Tool calls requested by the model, if any. */
|
|
113
142
|
tool_calls?: ResponseToolCall[] | undefined;
|
|
143
|
+
/** Token usage of this request, when the API reports it. */
|
|
114
144
|
usage?: TokenUsage | undefined;
|
|
115
145
|
}
|
|
116
146
|
/**
|
|
117
147
|
* Chunk yielded by `streamChatCompletion`.
|
|
118
148
|
*/
|
|
119
149
|
interface StreamChunk {
|
|
150
|
+
/** Always `assistant`. */
|
|
120
151
|
role: 'assistant';
|
|
152
|
+
/** Text delta. Empty in chunks that carry tool calls or usage. */
|
|
121
153
|
content: string;
|
|
154
|
+
/** Tool-call deltas in this chunk. */
|
|
122
155
|
tool_calls?: StreamToolCall[] | undefined;
|
|
156
|
+
/** Token usage. Sent once, in the final chunk, when the API reports it. */
|
|
123
157
|
usage?: TokenUsage | undefined;
|
|
124
158
|
}
|
|
125
159
|
/**
|
|
@@ -130,13 +164,15 @@ interface ChatCompletionOptions {
|
|
|
130
164
|
temporaryTools?: unknown[] | undefined;
|
|
131
165
|
}
|
|
132
166
|
/**
|
|
133
|
-
*
|
|
167
|
+
* Model provider for any API that speaks the OpenAI chat completions protocol:
|
|
168
|
+
* OpenAI itself, and the compatible endpoints of DeepSeek, Qwen, Moonshot, Ollama,
|
|
169
|
+
* vLLM and others. Set `baseURL` and `model` for the provider you use.
|
|
134
170
|
*
|
|
135
171
|
* Ports:
|
|
136
172
|
* - `prompt` (in): a text prompt. The answer is sent on `completion`.
|
|
137
173
|
* - `messages` (in): a list of chat messages. The reply is sent on `message`.
|
|
138
174
|
*/
|
|
139
|
-
declare class
|
|
175
|
+
declare class OpenAICompatible extends Component {
|
|
140
176
|
private readonly client;
|
|
141
177
|
private readonly model;
|
|
142
178
|
private readonly temperature;
|
|
@@ -145,7 +181,8 @@ declare class Deepseek extends Component {
|
|
|
145
181
|
private readonly systemPrompt;
|
|
146
182
|
private readonly tools;
|
|
147
183
|
private readonly verbose;
|
|
148
|
-
|
|
184
|
+
private readonly name;
|
|
185
|
+
constructor(config: OpenAICompatibleConfig);
|
|
149
186
|
/**
|
|
150
187
|
* Generates a completion for a single prompt.
|
|
151
188
|
*
|
|
@@ -163,7 +200,7 @@ declare class Deepseek extends Component {
|
|
|
163
200
|
/**
|
|
164
201
|
* Runs the model outside a pipeline.
|
|
165
202
|
*
|
|
166
|
-
* @param input A prompt string or a list of messages.
|
|
203
|
+
* @param input - A prompt string or a list of messages.
|
|
167
204
|
*/
|
|
168
205
|
run(input: string | Message[]): Promise<string | AssistantMessage>;
|
|
169
206
|
/**
|
|
@@ -184,13 +221,47 @@ declare class Deepseek extends Component {
|
|
|
184
221
|
private logError;
|
|
185
222
|
}
|
|
186
223
|
|
|
224
|
+
/**
|
|
225
|
+
* Options for the DeepSeek model provider. They are the options of
|
|
226
|
+
* `OpenAICompatible`, with DeepSeek's endpoint and model as defaults.
|
|
227
|
+
*/
|
|
228
|
+
interface DeepseekConfig extends Omit<OpenAICompatibleConfig, 'model' | 'name'> {
|
|
229
|
+
/** Model name. Defaults to `deepseek-chat`. */
|
|
230
|
+
model?: string | undefined;
|
|
231
|
+
/** API base URL. Defaults to `https://api.deepseek.com/v1`. */
|
|
232
|
+
baseURL?: string | undefined;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* DeepSeek model provider: `OpenAICompatible` set up for the DeepSeek API.
|
|
236
|
+
*
|
|
237
|
+
* Ports:
|
|
238
|
+
* - `prompt` (in): a text prompt. The answer is sent on `completion`.
|
|
239
|
+
* - `messages` (in): a list of chat messages. The reply is sent on `message`.
|
|
240
|
+
*/
|
|
241
|
+
declare class Deepseek extends OpenAICompatible {
|
|
242
|
+
constructor(config: DeepseekConfig);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
type index_AssistantMessage = AssistantMessage;
|
|
246
|
+
type index_ChatCompletionOptions = ChatCompletionOptions;
|
|
187
247
|
type index_Deepseek = Deepseek;
|
|
188
248
|
declare const index_Deepseek: typeof Deepseek;
|
|
189
249
|
type index_DeepseekConfig = DeepseekConfig;
|
|
250
|
+
type index_Message = Message;
|
|
251
|
+
type index_MessageRole = MessageRole;
|
|
252
|
+
type index_OpenAICompatible = OpenAICompatible;
|
|
253
|
+
declare const index_OpenAICompatible: typeof OpenAICompatible;
|
|
254
|
+
type index_OpenAICompatibleConfig = OpenAICompatibleConfig;
|
|
255
|
+
type index_RawTool = RawTool;
|
|
256
|
+
type index_ResponseToolCall = ResponseToolCall;
|
|
257
|
+
type index_StreamChunk = StreamChunk;
|
|
258
|
+
type index_StreamToolCall = StreamToolCall;
|
|
259
|
+
type index_TokenUsage = TokenUsage;
|
|
260
|
+
type index_ToolCall = ToolCall;
|
|
190
261
|
declare namespace index {
|
|
191
|
-
export { index_Deepseek as Deepseek };
|
|
192
|
-
export type { AssistantMessage as DeepseekAssistantMessage, ChatCompletionOptions as DeepseekChatCompletionOptions, index_DeepseekConfig as DeepseekConfig, Message as DeepseekMessage, MessageRole as DeepseekMessageRole, RawTool as DeepseekRawTool, ResponseToolCall as DeepseekResponseToolCall, StreamChunk as DeepseekStreamChunk, StreamToolCall as DeepseekStreamToolCall, TokenUsage as DeepseekTokenUsage, ToolCall as DeepseekToolCall };
|
|
262
|
+
export { index_Deepseek as Deepseek, index_OpenAICompatible as OpenAICompatible };
|
|
263
|
+
export type { index_AssistantMessage as AssistantMessage, index_ChatCompletionOptions as ChatCompletionOptions, AssistantMessage as DeepseekAssistantMessage, ChatCompletionOptions as DeepseekChatCompletionOptions, index_DeepseekConfig as DeepseekConfig, Message as DeepseekMessage, MessageRole as DeepseekMessageRole, RawTool as DeepseekRawTool, ResponseToolCall as DeepseekResponseToolCall, StreamChunk as DeepseekStreamChunk, StreamToolCall as DeepseekStreamToolCall, TokenUsage as DeepseekTokenUsage, ToolCall as DeepseekToolCall, index_Message as Message, index_MessageRole as MessageRole, index_OpenAICompatibleConfig as OpenAICompatibleConfig, index_RawTool as RawTool, index_ResponseToolCall as ResponseToolCall, index_StreamChunk as StreamChunk, index_StreamToolCall as StreamToolCall, index_TokenUsage as TokenUsage, index_ToolCall as ToolCall };
|
|
193
264
|
}
|
|
194
265
|
|
|
195
|
-
export { Deepseek, index as i };
|
|
196
|
-
export type { AssistantMessage as DeepseekAssistantMessage, ChatCompletionOptions as DeepseekChatCompletionOptions, DeepseekConfig, Message as DeepseekMessage, MessageRole as DeepseekMessageRole, RawTool as DeepseekRawTool, ResponseToolCall as DeepseekResponseToolCall, StreamChunk as DeepseekStreamChunk, StreamToolCall as DeepseekStreamToolCall, TokenUsage as DeepseekTokenUsage, ToolCall as DeepseekToolCall };
|
|
266
|
+
export { Deepseek, OpenAICompatible, index as i };
|
|
267
|
+
export type { AssistantMessage, ChatCompletionOptions, AssistantMessage as DeepseekAssistantMessage, ChatCompletionOptions as DeepseekChatCompletionOptions, DeepseekConfig, Message as DeepseekMessage, MessageRole as DeepseekMessageRole, RawTool as DeepseekRawTool, ResponseToolCall as DeepseekResponseToolCall, StreamChunk as DeepseekStreamChunk, StreamToolCall as DeepseekStreamToolCall, TokenUsage as DeepseekTokenUsage, ToolCall as DeepseekToolCall, Message, MessageRole, OpenAICompatibleConfig, RawTool, ResponseToolCall, StreamChunk, StreamToolCall, TokenUsage, ToolCall };
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
import { Component, Port } from '@astack-tech/core';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Options for the
|
|
4
|
+
* Options for a provider that speaks the OpenAI chat completions API.
|
|
5
5
|
*/
|
|
6
|
-
interface
|
|
7
|
-
/**
|
|
6
|
+
interface OpenAICompatibleConfig {
|
|
7
|
+
/** API key of the provider. */
|
|
8
8
|
apiKey: string;
|
|
9
|
-
/** Model name
|
|
10
|
-
model
|
|
11
|
-
/** API base URL. Defaults to `https://api.
|
|
9
|
+
/** Model name, for example `gpt-4o-mini`, `qwen-plus` or `llama3.1`. */
|
|
10
|
+
model: string;
|
|
11
|
+
/** API base URL. Defaults to `https://api.openai.com/v1`. */
|
|
12
12
|
baseURL?: string | undefined;
|
|
13
|
+
/** Provider name used in errors and logs. Defaults to `The model API`. */
|
|
14
|
+
name?: string | undefined;
|
|
13
15
|
/** Sampling temperature. Defaults to `0.7`. */
|
|
14
16
|
temperature?: number | undefined;
|
|
15
17
|
/** Maximum number of generated tokens. */
|
|
@@ -34,8 +36,11 @@ interface DeepseekConfig {
|
|
|
34
36
|
* Tool description accepted by `rawTools` and `temporaryTools`.
|
|
35
37
|
*/
|
|
36
38
|
interface RawTool {
|
|
39
|
+
/** Unique tool name. */
|
|
37
40
|
name: string;
|
|
41
|
+
/** Description that tells the model when to use the tool. */
|
|
38
42
|
description: string;
|
|
43
|
+
/** JSON Schema of the arguments. Defaults to `{}`. */
|
|
39
44
|
parameters?: Record<string, unknown> | undefined;
|
|
40
45
|
}
|
|
41
46
|
/**
|
|
@@ -58,36 +63,55 @@ interface ToolCall {
|
|
|
58
63
|
* (`type`, `function`) and the internal shape (`tool_name`, `arguments`).
|
|
59
64
|
*/
|
|
60
65
|
interface ResponseToolCall {
|
|
66
|
+
/** Identifier assigned by the API. A `tool` message answers the call with it. */
|
|
61
67
|
id: string;
|
|
68
|
+
/** Always `function`. */
|
|
62
69
|
type: 'function';
|
|
70
|
+
/** The call in the OpenAI shape: function name and raw JSON arguments. An empty argument string is sent as `{}`. */
|
|
63
71
|
function: {
|
|
72
|
+
/** Name of the tool to call. */
|
|
64
73
|
name: string;
|
|
74
|
+
/** Arguments as JSON text. */
|
|
65
75
|
arguments: string;
|
|
66
76
|
};
|
|
77
|
+
/** Name of the tool, same as `function.name`. */
|
|
67
78
|
tool_name: string;
|
|
79
|
+
/** Parsed arguments. JSON that is not an object becomes `{}`. */
|
|
68
80
|
arguments: Record<string, unknown>;
|
|
69
81
|
}
|
|
70
82
|
/**
|
|
71
83
|
* Partial tool call emitted while streaming. `arguments` holds the raw JSON fragment.
|
|
72
84
|
*/
|
|
73
85
|
interface StreamToolCall {
|
|
86
|
+
/** Identifier assigned by the API. Only the first delta of a call carries it; later deltas have `''`. */
|
|
74
87
|
id: string;
|
|
88
|
+
/** Always `function`. */
|
|
75
89
|
type: 'function';
|
|
90
|
+
/** The delta in the OpenAI shape. `arguments` holds only this delta's JSON fragment. */
|
|
76
91
|
function: {
|
|
92
|
+
/** Name of the tool to call. */
|
|
77
93
|
name: string;
|
|
94
|
+
/** Arguments as JSON text. */
|
|
78
95
|
arguments: string;
|
|
79
96
|
};
|
|
97
|
+
/** Name of the tool when this delta carries it, otherwise `''`. */
|
|
80
98
|
tool_name: string;
|
|
99
|
+
/** Raw JSON fragment of this delta. Concatenate the fragments of a call to get its arguments. */
|
|
81
100
|
arguments: string;
|
|
82
101
|
}
|
|
83
102
|
/**
|
|
84
103
|
* Token usage reported by the API.
|
|
85
104
|
*/
|
|
86
105
|
interface TokenUsage {
|
|
106
|
+
/** Tokens in the generated reply. */
|
|
87
107
|
completion_tokens: number;
|
|
108
|
+
/** Tokens in the request. */
|
|
88
109
|
prompt_tokens: number;
|
|
110
|
+
/** Prompt tokens served from the provider's context cache (reported by DeepSeek). */
|
|
89
111
|
prompt_cache_hit_tokens?: number | undefined;
|
|
112
|
+
/** Prompt tokens not served from the cache. */
|
|
90
113
|
prompt_cache_miss_tokens?: number | undefined;
|
|
114
|
+
/** Sum of prompt and completion tokens. */
|
|
91
115
|
total_tokens: number;
|
|
92
116
|
}
|
|
93
117
|
/**
|
|
@@ -97,29 +121,39 @@ interface TokenUsage {
|
|
|
97
121
|
interface Message {
|
|
98
122
|
/** One of `system`, `user`, `assistant` or `tool` (see `MessageRole`). */
|
|
99
123
|
role: string;
|
|
124
|
+
/** Text content. Omitted content is sent as no content. */
|
|
100
125
|
content?: string | undefined;
|
|
101
126
|
/** Accepted for compatibility. Assistant tool calls are not forwarded to the API. */
|
|
102
127
|
tool_calls?: readonly unknown[] | undefined;
|
|
103
128
|
/** Identifier of the call that a `tool` message answers. */
|
|
104
129
|
tool_call_id?: string | undefined;
|
|
130
|
+
/** Ignored on input. Present so agent histories can be passed unchanged. */
|
|
105
131
|
usage?: TokenUsage | undefined;
|
|
106
132
|
}
|
|
107
133
|
/**
|
|
108
134
|
* Assistant message returned by `chatCompletion`.
|
|
109
135
|
*/
|
|
110
136
|
interface AssistantMessage {
|
|
137
|
+
/** Always `assistant`. */
|
|
111
138
|
role: 'assistant';
|
|
139
|
+
/** Reply text. Empty when the model only calls tools. */
|
|
112
140
|
content: string;
|
|
141
|
+
/** Tool calls requested by the model, if any. */
|
|
113
142
|
tool_calls?: ResponseToolCall[] | undefined;
|
|
143
|
+
/** Token usage of this request, when the API reports it. */
|
|
114
144
|
usage?: TokenUsage | undefined;
|
|
115
145
|
}
|
|
116
146
|
/**
|
|
117
147
|
* Chunk yielded by `streamChatCompletion`.
|
|
118
148
|
*/
|
|
119
149
|
interface StreamChunk {
|
|
150
|
+
/** Always `assistant`. */
|
|
120
151
|
role: 'assistant';
|
|
152
|
+
/** Text delta. Empty in chunks that carry tool calls or usage. */
|
|
121
153
|
content: string;
|
|
154
|
+
/** Tool-call deltas in this chunk. */
|
|
122
155
|
tool_calls?: StreamToolCall[] | undefined;
|
|
156
|
+
/** Token usage. Sent once, in the final chunk, when the API reports it. */
|
|
123
157
|
usage?: TokenUsage | undefined;
|
|
124
158
|
}
|
|
125
159
|
/**
|
|
@@ -130,13 +164,15 @@ interface ChatCompletionOptions {
|
|
|
130
164
|
temporaryTools?: unknown[] | undefined;
|
|
131
165
|
}
|
|
132
166
|
/**
|
|
133
|
-
*
|
|
167
|
+
* Model provider for any API that speaks the OpenAI chat completions protocol:
|
|
168
|
+
* OpenAI itself, and the compatible endpoints of DeepSeek, Qwen, Moonshot, Ollama,
|
|
169
|
+
* vLLM and others. Set `baseURL` and `model` for the provider you use.
|
|
134
170
|
*
|
|
135
171
|
* Ports:
|
|
136
172
|
* - `prompt` (in): a text prompt. The answer is sent on `completion`.
|
|
137
173
|
* - `messages` (in): a list of chat messages. The reply is sent on `message`.
|
|
138
174
|
*/
|
|
139
|
-
declare class
|
|
175
|
+
declare class OpenAICompatible extends Component {
|
|
140
176
|
private readonly client;
|
|
141
177
|
private readonly model;
|
|
142
178
|
private readonly temperature;
|
|
@@ -145,7 +181,8 @@ declare class Deepseek extends Component {
|
|
|
145
181
|
private readonly systemPrompt;
|
|
146
182
|
private readonly tools;
|
|
147
183
|
private readonly verbose;
|
|
148
|
-
|
|
184
|
+
private readonly name;
|
|
185
|
+
constructor(config: OpenAICompatibleConfig);
|
|
149
186
|
/**
|
|
150
187
|
* Generates a completion for a single prompt.
|
|
151
188
|
*
|
|
@@ -163,7 +200,7 @@ declare class Deepseek extends Component {
|
|
|
163
200
|
/**
|
|
164
201
|
* Runs the model outside a pipeline.
|
|
165
202
|
*
|
|
166
|
-
* @param input A prompt string or a list of messages.
|
|
203
|
+
* @param input - A prompt string or a list of messages.
|
|
167
204
|
*/
|
|
168
205
|
run(input: string | Message[]): Promise<string | AssistantMessage>;
|
|
169
206
|
/**
|
|
@@ -184,13 +221,47 @@ declare class Deepseek extends Component {
|
|
|
184
221
|
private logError;
|
|
185
222
|
}
|
|
186
223
|
|
|
224
|
+
/**
|
|
225
|
+
* Options for the DeepSeek model provider. They are the options of
|
|
226
|
+
* `OpenAICompatible`, with DeepSeek's endpoint and model as defaults.
|
|
227
|
+
*/
|
|
228
|
+
interface DeepseekConfig extends Omit<OpenAICompatibleConfig, 'model' | 'name'> {
|
|
229
|
+
/** Model name. Defaults to `deepseek-chat`. */
|
|
230
|
+
model?: string | undefined;
|
|
231
|
+
/** API base URL. Defaults to `https://api.deepseek.com/v1`. */
|
|
232
|
+
baseURL?: string | undefined;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* DeepSeek model provider: `OpenAICompatible` set up for the DeepSeek API.
|
|
236
|
+
*
|
|
237
|
+
* Ports:
|
|
238
|
+
* - `prompt` (in): a text prompt. The answer is sent on `completion`.
|
|
239
|
+
* - `messages` (in): a list of chat messages. The reply is sent on `message`.
|
|
240
|
+
*/
|
|
241
|
+
declare class Deepseek extends OpenAICompatible {
|
|
242
|
+
constructor(config: DeepseekConfig);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
type index_AssistantMessage = AssistantMessage;
|
|
246
|
+
type index_ChatCompletionOptions = ChatCompletionOptions;
|
|
187
247
|
type index_Deepseek = Deepseek;
|
|
188
248
|
declare const index_Deepseek: typeof Deepseek;
|
|
189
249
|
type index_DeepseekConfig = DeepseekConfig;
|
|
250
|
+
type index_Message = Message;
|
|
251
|
+
type index_MessageRole = MessageRole;
|
|
252
|
+
type index_OpenAICompatible = OpenAICompatible;
|
|
253
|
+
declare const index_OpenAICompatible: typeof OpenAICompatible;
|
|
254
|
+
type index_OpenAICompatibleConfig = OpenAICompatibleConfig;
|
|
255
|
+
type index_RawTool = RawTool;
|
|
256
|
+
type index_ResponseToolCall = ResponseToolCall;
|
|
257
|
+
type index_StreamChunk = StreamChunk;
|
|
258
|
+
type index_StreamToolCall = StreamToolCall;
|
|
259
|
+
type index_TokenUsage = TokenUsage;
|
|
260
|
+
type index_ToolCall = ToolCall;
|
|
190
261
|
declare namespace index {
|
|
191
|
-
export { index_Deepseek as Deepseek };
|
|
192
|
-
export type { AssistantMessage as DeepseekAssistantMessage, ChatCompletionOptions as DeepseekChatCompletionOptions, index_DeepseekConfig as DeepseekConfig, Message as DeepseekMessage, MessageRole as DeepseekMessageRole, RawTool as DeepseekRawTool, ResponseToolCall as DeepseekResponseToolCall, StreamChunk as DeepseekStreamChunk, StreamToolCall as DeepseekStreamToolCall, TokenUsage as DeepseekTokenUsage, ToolCall as DeepseekToolCall };
|
|
262
|
+
export { index_Deepseek as Deepseek, index_OpenAICompatible as OpenAICompatible };
|
|
263
|
+
export type { index_AssistantMessage as AssistantMessage, index_ChatCompletionOptions as ChatCompletionOptions, AssistantMessage as DeepseekAssistantMessage, ChatCompletionOptions as DeepseekChatCompletionOptions, index_DeepseekConfig as DeepseekConfig, Message as DeepseekMessage, MessageRole as DeepseekMessageRole, RawTool as DeepseekRawTool, ResponseToolCall as DeepseekResponseToolCall, StreamChunk as DeepseekStreamChunk, StreamToolCall as DeepseekStreamToolCall, TokenUsage as DeepseekTokenUsage, ToolCall as DeepseekToolCall, index_Message as Message, index_MessageRole as MessageRole, index_OpenAICompatibleConfig as OpenAICompatibleConfig, index_RawTool as RawTool, index_ResponseToolCall as ResponseToolCall, index_StreamChunk as StreamChunk, index_StreamToolCall as StreamToolCall, index_TokenUsage as TokenUsage, index_ToolCall as ToolCall };
|
|
193
264
|
}
|
|
194
265
|
|
|
195
|
-
export { Deepseek, index as i };
|
|
196
|
-
export type { AssistantMessage as DeepseekAssistantMessage, ChatCompletionOptions as DeepseekChatCompletionOptions, DeepseekConfig, Message as DeepseekMessage, MessageRole as DeepseekMessageRole, RawTool as DeepseekRawTool, ResponseToolCall as DeepseekResponseToolCall, StreamChunk as DeepseekStreamChunk, StreamToolCall as DeepseekStreamToolCall, TokenUsage as DeepseekTokenUsage, ToolCall as DeepseekToolCall };
|
|
266
|
+
export { Deepseek, OpenAICompatible, index as i };
|
|
267
|
+
export type { AssistantMessage, ChatCompletionOptions, AssistantMessage as DeepseekAssistantMessage, ChatCompletionOptions as DeepseekChatCompletionOptions, DeepseekConfig, Message as DeepseekMessage, MessageRole as DeepseekMessageRole, RawTool as DeepseekRawTool, ResponseToolCall as DeepseekResponseToolCall, StreamChunk as DeepseekStreamChunk, StreamToolCall as DeepseekStreamToolCall, TokenUsage as DeepseekTokenUsage, ToolCall as DeepseekToolCall, Message, MessageRole, OpenAICompatibleConfig, RawTool, ResponseToolCall, StreamChunk, StreamToolCall, TokenUsage, ToolCall };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
// src/model-provider/
|
|
1
|
+
// src/model-provider/openai-compatible/index.ts
|
|
2
2
|
import { Component } from "@astack-tech/core";
|
|
3
3
|
import OpenAI from "openai";
|
|
4
|
-
var DEFAULT_BASE_URL = "https://api.
|
|
5
|
-
var
|
|
4
|
+
var DEFAULT_BASE_URL = "https://api.openai.com/v1";
|
|
5
|
+
var DEFAULT_NAME = "The model API";
|
|
6
6
|
var DEFAULT_TEMPERATURE = 0.7;
|
|
7
7
|
var FALLBACK_TEXT = "API call failed";
|
|
8
8
|
function isRecord(value) {
|
|
@@ -43,7 +43,7 @@ function mapUsage(usage) {
|
|
|
43
43
|
...usage.prompt_cache_miss_tokens === void 0 ? {} : { prompt_cache_miss_tokens: usage.prompt_cache_miss_tokens }
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
|
-
var
|
|
46
|
+
var OpenAICompatible = class extends Component {
|
|
47
47
|
client;
|
|
48
48
|
model;
|
|
49
49
|
temperature;
|
|
@@ -52,6 +52,7 @@ var Deepseek = class extends Component {
|
|
|
52
52
|
systemPrompt;
|
|
53
53
|
tools;
|
|
54
54
|
verbose;
|
|
55
|
+
name;
|
|
55
56
|
constructor(config) {
|
|
56
57
|
super({});
|
|
57
58
|
this.client = new OpenAI({
|
|
@@ -59,7 +60,8 @@ var Deepseek = class extends Component {
|
|
|
59
60
|
baseURL: config.baseURL ?? DEFAULT_BASE_URL,
|
|
60
61
|
dangerouslyAllowBrowser: config.dangerouslyAllowBrowser ?? false
|
|
61
62
|
});
|
|
62
|
-
this.model = config.model
|
|
63
|
+
this.model = config.model;
|
|
64
|
+
this.name = config.name ?? DEFAULT_NAME;
|
|
63
65
|
this.temperature = config.temperature ?? DEFAULT_TEMPERATURE;
|
|
64
66
|
this.maxTokens = config.maxTokens;
|
|
65
67
|
this.topP = config.topP;
|
|
@@ -162,7 +164,7 @@ var Deepseek = class extends Component {
|
|
|
162
164
|
/**
|
|
163
165
|
* Runs the model outside a pipeline.
|
|
164
166
|
*
|
|
165
|
-
* @param input A prompt string or a list of messages.
|
|
167
|
+
* @param input - A prompt string or a list of messages.
|
|
166
168
|
*/
|
|
167
169
|
run(input) {
|
|
168
170
|
return typeof input === "string" ? this.generateCompletion(input) : this.chatCompletion(input);
|
|
@@ -229,18 +231,34 @@ var Deepseek = class extends Component {
|
|
|
229
231
|
firstMessage(response) {
|
|
230
232
|
const choice = response.choices[0];
|
|
231
233
|
if (choice === void 0) {
|
|
232
|
-
throw new Error(
|
|
234
|
+
throw new Error(`${this.name} returned no choices.`);
|
|
233
235
|
}
|
|
234
236
|
return choice.message;
|
|
235
237
|
}
|
|
236
238
|
logError(error) {
|
|
237
239
|
if (this.verbose) {
|
|
238
|
-
console.error(
|
|
240
|
+
console.error(`[${this.name}] API call failed:`, error);
|
|
239
241
|
}
|
|
240
242
|
}
|
|
241
243
|
};
|
|
244
|
+
var openai_compatible_default = OpenAICompatible;
|
|
245
|
+
|
|
246
|
+
// src/model-provider/deepseek/index.ts
|
|
247
|
+
var DEFAULT_BASE_URL2 = "https://api.deepseek.com/v1";
|
|
248
|
+
var DEFAULT_MODEL = "deepseek-chat";
|
|
249
|
+
var Deepseek = class extends openai_compatible_default {
|
|
250
|
+
constructor(config) {
|
|
251
|
+
super({
|
|
252
|
+
...config,
|
|
253
|
+
model: config.model ?? DEFAULT_MODEL,
|
|
254
|
+
baseURL: config.baseURL ?? DEFAULT_BASE_URL2,
|
|
255
|
+
name: "DeepSeek"
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
};
|
|
242
259
|
var deepseek_default = Deepseek;
|
|
243
260
|
export {
|
|
244
|
-
deepseek_default as Deepseek
|
|
261
|
+
deepseek_default as Deepseek,
|
|
262
|
+
openai_compatible_default as OpenAICompatible
|
|
245
263
|
};
|
|
246
264
|
//# sourceMappingURL=index.js.map
|