diff --git a/blocks/blocks/agent.ts b/blocks/blocks/agent.ts index ef6cc42ed3..570e1c458d 100644 --- a/blocks/blocks/agent.ts +++ b/blocks/blocks/agent.ts @@ -4,10 +4,11 @@ import { BlockConfig } from '../types' // Map of models to their tools const MODEL_TOOLS = { 'gpt-4o': 'openai.chat', - 'o1-mini': 'openai.chat', 'claude-3-5-sonnet-20241022': 'anthropic.chat', 'gemini-pro': 'google.chat', - 'grok-2-latest': 'xai.chat' + 'grok-2-latest': 'xai.chat', + 'deepseek-v3': 'deepseek.chat', + 'deepseek-r1': 'deepseek.reasoner' } as const; export const AgentBlock: BlockConfig = { @@ -20,7 +21,7 @@ export const AgentBlock: BlockConfig = { category: 'basic', }, tools: { - access: ['openai.chat', 'anthropic.chat', 'google.chat', 'xai.chat'], + access: ['openai.chat', 'anthropic.chat', 'google.chat', 'xai.chat', 'deepseek.chat', 'deepseek.reasoner'], config: { tool: (params: Record) => { const model = params.model || 'gpt-4o'; diff --git a/tools/deepseek/chat.ts b/tools/deepseek/chat.ts new file mode 100644 index 0000000000..91a94f473c --- /dev/null +++ b/tools/deepseek/chat.ts @@ -0,0 +1,119 @@ +import { ToolConfig, ToolResponse } from '../types' + +interface Message { + role: 'system' | 'user' | 'assistant' + content: string +} + +interface ChatParams { + apiKey: string + systemPrompt?: string + context?: string + model?: string + temperature?: number + responseFormat?: string +} + +interface ChatResponse extends ToolResponse { + tokens?: number + model: string +} + +export const chatTool: ToolConfig = { + id: 'deepseek.chat', + name: 'DeepSeek Chat', + description: 'Chat with DeepSeek-v3 model', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + description: 'DeepSeek API key' + }, + systemPrompt: { + type: 'string', + required: false, + description: 'System prompt to guide the model' + }, + context: { + type: 'string', + required: false, + description: 'User input context' + }, + model: { + type: 'string', + default: 'deepseek-chat', + description: 'Model to use' + }, + temperature: { + type: 'number', + required: false, + default: 0.7, + description: 'Sampling temperature' + }, + responseFormat: { + type: 'string', + required: false, + description: 'Response format specification' + } + }, + + request: { + url: 'https://api.deepseek.com/v1/chat/completions', + method: 'POST', + headers: (params) => ({ + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${params.apiKey}` + }), + body: (params) => { + const messages: Message[] = [] + + if (params.systemPrompt) { + messages.push({ + role: 'system', + content: params.systemPrompt + }) + } + + if (params.context) { + messages.push({ + role: 'user', + content: params.context + }) + } + + const body: any = { + model: 'deepseek-chat', + messages, + temperature: params.temperature + } + + if (params.responseFormat === 'json') { + body.response_format = { type: 'json_object' } + } + + return body + } + }, + + async transformResponse(response: Response): Promise { + if (!response.ok) { + const error = await response.json() + throw new Error(`DeepSeek API error: ${error.message || response.statusText}`) + } + + const data = await response.json() + return { + output: data.choices[0].message.content, + tokens: data.usage?.total_tokens, + model: data.model + } + }, + + transformError(error: any): string { + const message = error.error?.message || error.message + const code = error.error?.type || error.code + return `${message} (${code})` + } +} diff --git a/tools/deepseek/reasoner.ts b/tools/deepseek/reasoner.ts new file mode 100644 index 0000000000..9270ae79a9 --- /dev/null +++ b/tools/deepseek/reasoner.ts @@ -0,0 +1,114 @@ +import { ToolConfig, ToolResponse } from '../types' + +interface Message { + role: 'system' | 'user' | 'assistant' + content: string +} + +interface ChatParams { + apiKey: string + systemPrompt?: string + context?: string + model?: string + temperature?: number +} + +interface ChatResponse extends ToolResponse { + tokens?: number + model: string + reasoning_content?: string +} + +export const reasonerTool: ToolConfig = { + id: 'deepseek.reasoner', + name: 'DeepSeek Reasoner', + description: 'Chat with DeepSeek-R1 reasoning model', + version: '1.0.0', + + params: { + apiKey: { + type: 'string', + required: true, + description: 'DeepSeek API key' + }, + systemPrompt: { + type: 'string', + required: false, + description: 'System prompt to guide the model' + }, + context: { + type: 'string', + required: false, + description: 'User input context' + }, + model: { + type: 'string', + default: 'deepseek-reasoner', + description: 'Model to use' + }, + temperature: { + type: 'number', + required: false, + description: 'Temperature (has no effect on reasoner)' + } + }, + + request: { + url: 'https://api.deepseek.com/v1/chat/completions', + method: 'POST', + headers: (params) => ({ + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${params.apiKey}` + }), + body: (params) => { + const messages: Message[] = [] + + if (params.systemPrompt) { + messages.push({ + role: 'system', + content: params.systemPrompt + }) + } + + // Always ensure the last message is a user message + if (params.context) { + messages.push({ + role: 'user', + content: params.context + }) + } else if (params.systemPrompt) { + // If we have a system prompt but no context, add an empty user message + messages.push({ + role: 'user', + content: 'Please respond.' + }) + } + + return { + model: 'deepseek-reasoner', + messages + } + } + }, + + async transformResponse(response: Response): Promise { + if (!response.ok) { + const error = await response.json() + throw new Error(`DeepSeek API error: ${error.message || response.statusText}`) + } + + const data = await response.json() + return { + output: data.choices[0].message.content, + tokens: data.usage?.total_tokens, + model: data.model, + reasoning_content: data.choices[0].message.reasoning_content + } + }, + + transformError(error: any): string { + const message = error.error?.message || error.message + const code = error.error?.type || error.code + return `${message} (${code})` + } +} \ No newline at end of file diff --git a/tools/index.ts b/tools/index.ts index b9dba82a41..7456420ea4 100644 --- a/tools/index.ts +++ b/tools/index.ts @@ -3,6 +3,8 @@ import { chatTool as openaiChat } from './openai/chat'; import { chatTool as anthropicChat } from './anthropic/chat'; import { chatTool as googleChat } from './google/chat'; import { chatTool as xaiChat } from './xai/chat'; +import { chatTool as deepseekChat } from './deepseek/chat'; +import { reasonerTool as deepseekReasoner } from './deepseek/reasoner'; import { requestTool as httpRequest } from './http/request'; import { contactsTool as hubspotContacts } from './hubspot/contacts'; import { opportunitiesTool as salesforceOpportunities } from './salesforce/opportunities'; @@ -15,13 +17,15 @@ export const tools: Record = { 'anthropic.chat': anthropicChat, 'google.chat': googleChat, 'xai.chat': xaiChat, + 'deepseek.chat': deepseekChat, + 'deepseek.reasoner': deepseekReasoner, // HTTP 'http.request': httpRequest, // CRM Tools 'hubspot.contacts': hubspotContacts, 'salesforce.opportunities': salesforceOpportunities, // Function Tools - 'function.execute': functionExecute, + 'function.execute': functionExecute }; // Get a tool by its ID