├── LICENSE ├── src ├── index.ts ├── types.ts ├── agent.ts └── client.ts ├── CHANGELOG.md ├── tsconfig.json ├── .gitignore ├── package.json └── README.md /LICENSE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/truffle-ai/truffle-ai-sdk/HEAD/LICENSE -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * TruffleAI SDK 3 | * @module truffle-ai 4 | */ 5 | 6 | export { TruffleAI } from './client'; 7 | export { Agent } from './agent'; 8 | export { 9 | // Core types 10 | AgentConfig, 11 | ChatMessage, 12 | ChatResponse, 13 | RunResponse, 14 | DeployedAgent, 15 | TruffleAIOptions, 16 | 17 | // Error types 18 | TruffleError, 19 | ValidationError, 20 | AuthenticationError 21 | } from './types'; -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [2.1.0] - 2025-02-19 11 | ### Added 12 | - Added support for json_mode in run API 13 | 14 | ## [2.0.0] - 2025-02-13 15 | ### Added 16 | - Updated all functions to use the new Truffle AI APIs 17 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "ESNext", 5 | "lib": ["ES2020"], 6 | "declaration": true, 7 | "declarationMap": true, 8 | "sourceMap": true, 9 | "outDir": "./dist", 10 | "rootDir": "./src", 11 | "strict": true, 12 | "moduleResolution": "node", 13 | "esModuleInterop": true, 14 | "skipLibCheck": true, 15 | "forceConsistentCasingInFileNames": true 16 | }, 17 | "include": ["src/**/*"], 18 | "exclude": ["node_modules", "dist"] 19 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules/ 3 | .pnp/ 4 | .pnp.js 5 | 6 | # Build outputs 7 | dist/ 8 | build/ 9 | *.tsbuildinfo 10 | 11 | # IDE and editor files 12 | .idea/ 13 | .vscode/ 14 | *.swp 15 | *.swo 16 | .DS_Store 17 | *.sublime-workspace 18 | *.sublime-project 19 | 20 | # Debug logs 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | debug.log 25 | 26 | # Environment variables 27 | .env 28 | .env.local 29 | .env.*.local 30 | 31 | # Test coverage 32 | coverage/ 33 | 34 | # Temporary files 35 | *.log 36 | .tmp/ 37 | .temp/ 38 | 39 | # Cache directories 40 | .npm/ 41 | .eslintcache 42 | .cache/ -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "truffle-ai", 3 | "version": "2.0.2", 4 | "description": "An SDK to interact with serverless AI agents using Truffle AI", 5 | "main": "./dist/index.js", 6 | "module": "./dist/index.mjs", 7 | "types": "./dist/index.d.ts", 8 | "files": [ 9 | "dist", 10 | "README.md", 11 | "LICENSE" 12 | ], 13 | "scripts": { 14 | "build": "tsup src/index.ts --format cjs,esm --dts", 15 | "clean": "rimraf dist", 16 | "typecheck": "tsc --noEmit", 17 | "lint": "eslint src --ext .ts", 18 | "prepublishOnly": "npm run build" 19 | }, 20 | "author": "Truffle AI", 21 | "license": "MIT", 22 | "repository": { 23 | "type": "git", 24 | "url": "git+https://github.com/truffle-ai/truffle-ai-sdk.git" 25 | }, 26 | "keywords": [ 27 | "ai", 28 | "agents", 29 | "llm", 30 | "typescript" 31 | ], 32 | "bugs": { 33 | "url": "https://github.com/truffle-ai/truffle-ai-sdk/issues" 34 | }, 35 | "homepage": "https://github.com/truffle-ai/truffle-ai-sdk#readme", 36 | "exports": { 37 | ".": { 38 | "types": "./dist/index.d.ts", 39 | "import": "./dist/index.mjs", 40 | "require": "./dist/index.js", 41 | "default": "./dist/index.js" 42 | } 43 | }, 44 | "devDependencies": { 45 | "@types/node": "^20.0.0", 46 | "typescript": "^5.0.0", 47 | "tsup": "^8.0.0", 48 | "rimraf": "^5.0.0", 49 | "eslint": "^8.0.0", 50 | "@typescript-eslint/eslint-plugin": "^6.0.0", 51 | "@typescript-eslint/parser": "^6.0.0" 52 | }, 53 | "engines": { 54 | "node": ">=14.0.0" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TruffleAI SDK 2 | 3 | A TypeScript SDK for interacting with the TruffleAI API. Build and deploy AI agents with ease. 4 | 5 | 📚 [View Full Documentation](https://docs.trytruffle.ai/introduction) 6 | 7 | ## Installation 8 | 9 | ```bash 10 | npm install truffle-ai 11 | ``` 12 | 13 | ## Quick Start 14 | 15 | ```typescript 16 | import { TruffleAI } from 'truffle-ai'; 17 | 18 | // Initialize the client 19 | const client = new TruffleAI('your-api-key'); 20 | 21 | // Create and deploy a new agent 22 | const agent = await client.deployAgent({ 23 | name: 'My Assistant', 24 | instruction: 'Help users with their questions', 25 | model: 'gpt-4o-mini', 26 | tool: 'None' 27 | }); 28 | 29 | // Run a task with the agent 30 | const result = await agent.run('What is the capital of France?'); 31 | console.log(result.data); // Paris 32 | 33 | // Load an existing agent 34 | // AgentId can be found in the dashboard 35 | const existingAgent = await client.loadAgent('agent-id'); 36 | ``` 37 | 38 | ## Core Features 39 | 40 | - 🚀 Create and deploy AI agents with minimal setup 41 | - 🤖 Run one-off tasks with deployed agents 42 | - 🔒 Type-safe with comprehensive error handling 43 | 44 | ## Creating Agents 45 | 46 | Agents are created with a configuration that defines their behavior: 47 | 48 | ```typescript 49 | const agentConfig = { 50 | name: 'My Assistant', // Name of your agent 51 | instruction: 'You are...', // Instructions defining behavior 52 | model: 'gpt-4o-mini', // AI model to use 53 | tool: 'None' // Tool configuration 54 | }; 55 | 56 | const agent = await client.deployAgent(agentConfig); 57 | ``` 58 | 59 | ### Using Tools 60 | 61 | Agents can be equipped with powerful tools to enhance their capabilities. Here's an example using the pre-built Tavily Research tool for web search. For a complete list of available tools and capabilities, check out our [documentation](https://docs.trytruffle.ai/introduction). 62 | 63 | ```typescript 64 | // Create an agent with Tavily Research tool 65 | const researchAgent = await client.deployAgent({ 66 | name: 'Research Assistant', 67 | instruction: 'You are a research assistant that helps users find accurate information from the web.', 68 | model: 'gpt-4o-mini', 69 | tool: 'Tavily Research' // Enable web search capabilities 70 | }); 71 | 72 | // Run a research task 73 | const result = await researchAgent.run('What are the latest developments in quantum computing?'); 74 | console.log(result.data); // Contains AI-processed research findings from the web 75 | ``` 76 | 77 | ## Running Tasks 78 | 79 | Once deployed, you can run tasks with your agent: 80 | 81 | ```typescript 82 | // Run a single task 83 | const result = await agent.run('Analyze this text...'); 84 | console.log(result.data); 85 | 86 | // Load and use an existing agent 87 | const existingAgent = await client.loadAgent('agent-id'); 88 | const result = await existingAgent.run('Another task...'); 89 | ``` 90 | 91 | ## Error Handling 92 | 93 | The SDK provides structured error handling: 94 | 95 | ```typescript 96 | try { 97 | const agent = await client.deployAgent({ 98 | name: 'My Assistant', 99 | instruction: 'Help users with questions', 100 | model: 'gpt-4o-mini' 101 | }); 102 | } catch (error) { 103 | if (error instanceof ValidationError) { 104 | // Handle validation errors (e.g., missing required fields) 105 | console.error('Invalid configuration:', error.message); 106 | } else if (error instanceof AuthenticationError) { 107 | // Handle authentication errors (e.g., invalid API key) 108 | console.error('Authentication failed:', error.message); 109 | } else if (error instanceof TruffleError) { 110 | // Handle other API errors 111 | console.error('API error:', error.message); 112 | } 113 | } 114 | ``` 115 | 116 | ## Support 117 | 118 | For support, email founders@trytruffle.ai or open an issue on GitHub. -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Configuration options for creating or updating an agent 3 | */ 4 | export interface AgentConfig { 5 | /** Unique identifier of the agent */ 6 | agent_id?: string; 7 | /** Name of the agent */ 8 | name: string; 9 | /** Instructions that define the agent's behavior */ 10 | instruction: string; 11 | /** Model to be used by the agent (e.g. 'gpt-4') */ 12 | model: string; 13 | /** Optional tool configuration */ 14 | tool?: string; 15 | /** Optional document ID for RAG */ 16 | documentId?: string; 17 | } 18 | 19 | /** 20 | * Represents a file-like object for Node.js environments 21 | */ 22 | export interface NodeFile { 23 | /** File data as Buffer or ArrayBuffer */ 24 | data: Buffer | ArrayBuffer; 25 | /** Filename */ 26 | name: string; 27 | /** MIME type */ 28 | type: string; 29 | /** File size in bytes */ 30 | size?: number; 31 | } 32 | 33 | /** 34 | * Response from deploying a new agent 35 | */ 36 | export interface DeployResponse { 37 | agent_id: string; 38 | created_at: string; 39 | } 40 | 41 | /** 42 | * Response from loading an existing agent 43 | */ 44 | export interface LoadAgentResponse { 45 | config: { 46 | agent_id: string; 47 | name: string; 48 | instruction: string; 49 | selectedModel: string; 50 | selectedTool?: string; 51 | }; 52 | created_at: string; 53 | updated_at: string; 54 | } 55 | 56 | /** 57 | * Message format for chat interactions 58 | */ 59 | export interface ChatMessage { 60 | /** Role of the message sender */ 61 | role: 'system' | 'user' | 'assistant'; 62 | /** Content of the message */ 63 | content: string; 64 | } 65 | 66 | /** 67 | * Response format for chat interactions 68 | */ 69 | export interface ChatResponse { 70 | /** The message content from the agent */ 71 | message: string; 72 | /** Optional session ID if provided */ 73 | session_id?: string; 74 | } 75 | 76 | /** 77 | * Response format for one-off run operations 78 | */ 79 | export interface RunResponse { 80 | /** Whether the operation was successful */ 81 | success: boolean; 82 | /** Response data - either a string or structured data */ 83 | data: string | Record; 84 | /** Optional error message if the operation failed */ 85 | error?: string; 86 | } 87 | 88 | /** 89 | * Information about a deployed agent 90 | */ 91 | export interface DeployedAgent { 92 | /** Unique identifier of the agent */ 93 | agent_id: string; 94 | /** Configuration of the agent */ 95 | config: AgentConfig; 96 | /** ISO timestamp of when the agent was created */ 97 | created_at: string; 98 | /** ISO timestamp of when the agent was last updated */ 99 | updated_at: string; 100 | } 101 | 102 | /** 103 | * Configuration options for the TruffleAI client 104 | */ 105 | export interface TruffleAIOptions { 106 | /** Base URL for the API (defaults to https://www.trytruffle.ai) */ 107 | baseUrl?: string; 108 | } 109 | 110 | /** 111 | * Base error class for TruffleAI SDK 112 | */ 113 | export class TruffleError extends Error { 114 | constructor( 115 | message: string, 116 | public readonly statusCode: number, 117 | public readonly details?: Record 118 | ) { 119 | super(message); 120 | this.name = 'TruffleError'; 121 | } 122 | } 123 | 124 | /** 125 | * Validation error class for invalid inputs 126 | */ 127 | export class ValidationError extends TruffleError { 128 | constructor(message: string, details?: Record) { 129 | super(message, 400, details); 130 | this.name = 'ValidationError'; 131 | } 132 | } 133 | 134 | /** 135 | * Authentication error class 136 | */ 137 | export class AuthenticationError extends TruffleError { 138 | constructor(message: string = 'Invalid API key') { 139 | super(message, 401); 140 | this.name = 'AuthenticationError'; 141 | } 142 | } 143 | 144 | /** 145 | * Rate limit error class 146 | */ 147 | export class RateLimitError extends TruffleError { 148 | constructor(message: string = 'Rate limit exceeded') { 149 | super(message, 429); 150 | this.name = 'RateLimitError'; 151 | } 152 | } 153 | 154 | /** 155 | * Network error class 156 | */ 157 | export class NetworkError extends TruffleError { 158 | constructor(message: string) { 159 | super(message, 0); 160 | this.name = 'NetworkError'; 161 | } 162 | } -------------------------------------------------------------------------------- /src/agent.ts: -------------------------------------------------------------------------------- 1 | import type { TruffleAI } from './client'; 2 | import { 3 | AgentConfig, 4 | ChatMessage, 5 | ChatResponse, 6 | RunResponse, 7 | ValidationError, 8 | TruffleError 9 | } from './types'; 10 | 11 | /** 12 | * Represents a deployed TruffleAI agent that can be used for chat and task execution 13 | * @example 14 | * const agent = await client.deployAgent({ 15 | * name: 'My Assistant', 16 | * instruction: 'Help users with their questions', 17 | * model: 'gpt-4' 18 | * }); 19 | * 20 | * // Run a one-off task 21 | * const result = await agent.run('What is the capital of France?'); 22 | * 23 | * // Start a chat session 24 | * const chat = agent.chat(); 25 | * const response = await chat.send('Hello!'); 26 | */ 27 | export class Agent { 28 | /** 29 | * Creates a new Agent instance 30 | * @param id The unique identifier of the agent 31 | * @param config The agent's configuration 32 | * @param client The TruffleAI client instance 33 | */ 34 | constructor( 35 | public readonly id: string, 36 | private readonly config: AgentConfig, 37 | private readonly client: TruffleAI 38 | ) { 39 | if (!id) { 40 | throw new ValidationError('Agent ID is required'); 41 | } 42 | if (!config) { 43 | throw new ValidationError('Agent configuration is required'); 44 | } 45 | } 46 | 47 | /** 48 | * Runs a one-off task with the agent 49 | * @param input The input text for the task 50 | * @param json_mode Whether to return the response in JSON format 51 | * @param json_format Optional JSON schema to validate the response against 52 | * @returns The agent's response 53 | * @throws {ValidationError} If the input is empty 54 | * @throws {TruffleError} If the request fails 55 | */ 56 | async run( 57 | input: string, 58 | json_mode?: boolean, 59 | json_format?: string 60 | ): Promise { 61 | if (!input?.trim()) { 62 | throw new ValidationError('Input is required'); 63 | } 64 | 65 | // Construct payload with optional fields only included when defined 66 | // Using spread operator with logical AND to conditionally add properties 67 | const payload = { 68 | input_data: input, 69 | ...(json_mode !== undefined && { json_mode }), 70 | ...(json_format !== undefined && { json_format }) 71 | }; 72 | 73 | const response = await this.client.makeRequest( 74 | `agents/${this.id}/run`, 75 | 'POST', 76 | payload 77 | ); 78 | 79 | return response; 80 | } 81 | 82 | /** 83 | * Creates a new chat session with the agent 84 | * @returns A new AgentChat instance 85 | */ 86 | chat(): AgentChat { 87 | return new AgentChat(this.id, this.client); 88 | } 89 | 90 | /** 91 | * Gets the agent's unique identifier 92 | * @returns The agent ID 93 | * @deprecated Use the id property directly instead 94 | */ 95 | getId(): string { 96 | return this.id; 97 | } 98 | 99 | /** 100 | * Gets the agent's configuration 101 | * @returns A copy of the agent's configuration 102 | */ 103 | getConfig(): AgentConfig { 104 | return { ...this.config }; 105 | } 106 | 107 | /** 108 | * Updates the agent's configuration 109 | * @param updates Partial configuration updates 110 | * @throws {ValidationError} If the updates are invalid 111 | * @throws {TruffleError} If the update request fails 112 | */ 113 | async update(updates: Partial): Promise { 114 | const response = await this.client.makeRequest<{ success: boolean; data: { config: AgentConfig } }>( 115 | `agents/${this.id}`, 116 | 'PUT', 117 | updates 118 | ); 119 | 120 | if (!response.success) { 121 | throw new TruffleError('Failed to update agent', 500); 122 | } 123 | 124 | Object.assign(this.config, response.data.config); 125 | } 126 | 127 | /** 128 | * Deletes the agent 129 | * @throws {TruffleError} If the delete request fails 130 | */ 131 | async delete(): Promise { 132 | await this.client.makeRequest( 133 | `agents/${this.id}`, 134 | 'DELETE' 135 | ); 136 | } 137 | } 138 | 139 | /** 140 | * Manages a chat session with an agent 141 | */ 142 | class AgentChat { 143 | private messages: ChatMessage[] = []; 144 | 145 | constructor( 146 | private readonly agentId: string, 147 | private readonly client: TruffleAI 148 | ) { 149 | if (!agentId) { 150 | throw new ValidationError('Agent ID is required'); 151 | } 152 | } 153 | 154 | /** 155 | * Sends a message to the agent 156 | * @param message The message to send 157 | * @returns The agent's response 158 | * @throws {ValidationError} If the message is empty 159 | * @throws {TruffleError} If the request fails 160 | */ 161 | async send(message: string): Promise { 162 | if (!message?.trim()) { 163 | throw new ValidationError('Message is required'); 164 | } 165 | 166 | const userMessage: ChatMessage = { 167 | role: 'user', 168 | content: message 169 | }; 170 | 171 | this.messages.push(userMessage); 172 | 173 | const response = await this.client.makeRequest( 174 | `agents/${this.agentId}/chat`, 175 | 'POST', 176 | { messages: this.messages } 177 | ); 178 | 179 | const assistantMessage = response.message; 180 | this.messages.push({ role: 'assistant', content: assistantMessage }); 181 | 182 | return assistantMessage; 183 | } 184 | 185 | /** 186 | * Gets the chat history 187 | * @returns A copy of the chat messages 188 | */ 189 | getHistory(): ChatMessage[] { 190 | return [...this.messages]; 191 | } 192 | 193 | /** 194 | * Clears the chat history 195 | */ 196 | clearHistory(): void { 197 | this.messages = []; 198 | } 199 | } -------------------------------------------------------------------------------- /src/client.ts: -------------------------------------------------------------------------------- 1 | import { Agent } from './agent'; 2 | import { 3 | AgentConfig, 4 | ChatMessage, 5 | ChatResponse, 6 | TruffleAIOptions, 7 | TruffleError, 8 | ValidationError, 9 | AuthenticationError, 10 | DeployResponse, 11 | LoadAgentResponse, 12 | NodeFile 13 | } from './types'; 14 | 15 | /** 16 | * Main client for interacting with the TruffleAI API 17 | * @example 18 | * const client = new TruffleAI('your-api-key'); 19 | * 20 | * const agent = await client.deployAgent({ 21 | * name: 'My Assistant', 22 | * instruction: 'Help users with their questions', 23 | * model: 'gpt-4' 24 | * }); 25 | */ 26 | export class TruffleAI { 27 | private readonly apiKey: string; 28 | private readonly baseUrl: string; 29 | 30 | /** 31 | * Creates a new TruffleAI client instance 32 | * @param apiKey Your TruffleAI API key 33 | * @param options Configuration options 34 | */ 35 | constructor(apiKey: string, options: TruffleAIOptions = {}) { 36 | if (!apiKey) { 37 | throw new ValidationError('API key is required'); 38 | } 39 | 40 | this.apiKey = apiKey; 41 | this.baseUrl = options.baseUrl || 'https://www.trytruffle.ai'; 42 | } 43 | 44 | /** 45 | * Deploys a new agent with the specified configuration 46 | * @param config The agent configuration 47 | * @param ragFile Optional file to use for RAG (Browser File or Node.js file-like object) 48 | * @returns A promise that resolves to the created agent 49 | */ 50 | async deployAgent(config: AgentConfig, ragFile?: File | NodeFile): Promise { 51 | // First upload RAG file if provided 52 | let documentId: string | undefined; 53 | 54 | if (ragFile) { 55 | // Upload the file 56 | const uploadResult = await this.uploadRAGFile(ragFile); 57 | documentId = uploadResult.documentId; 58 | } 59 | 60 | // Include documentId in the agent configuration if available 61 | const agentConfig: AgentConfig = { 62 | ...config, 63 | ...(documentId && { documentId }) 64 | }; 65 | 66 | // Create the agent with the existing logic 67 | const response = await this.makeRequest<{ success: boolean; data: { agent_id: string } }>( 68 | 'agents', 69 | 'POST', 70 | agentConfig 71 | ); 72 | 73 | if (!response.success) { 74 | throw new TruffleError('Failed to create agent', 500); 75 | } 76 | 77 | return new Agent(response.data.agent_id, agentConfig, this); 78 | } 79 | 80 | /** 81 | * Loads an existing agent by ID 82 | * @param agentId ID of the agent to load 83 | * @returns An Agent instance 84 | * @throws {ValidationError} If the agent ID is invalid 85 | * @throws {TruffleError} If the agent is not found 86 | */ 87 | async loadAgent(agentId: string): Promise { 88 | if (!agentId) { 89 | throw new ValidationError('Agent ID is required'); 90 | } 91 | 92 | const response = await this.makeRequest<{ success: boolean; data: LoadAgentResponse }>( 93 | `agents/${agentId}`, 94 | 'GET' 95 | ); 96 | 97 | console.log(response); 98 | 99 | if (!response.success) { 100 | throw new TruffleError('Failed to load agent', 500, response); 101 | } 102 | 103 | // Transform the config to match AgentConfig interface 104 | const config: AgentConfig = { 105 | ...response.data.config, 106 | model: response.data.config.selectedModel, 107 | tool: response.data.config.selectedTool 108 | }; 109 | 110 | return new Agent(agentId, config, this); 111 | } 112 | 113 | /** 114 | * Makes an authenticated request to the TruffleAI API 115 | * @template T The expected response type 116 | * @param endpoint API endpoint to call 117 | * @param method HTTP method 118 | * @param body Optional request body 119 | * @returns The response data 120 | * @throws {TruffleError} If the request fails 121 | */ 122 | async makeRequest( 123 | endpoint: string, 124 | method: 'GET' | 'POST' | 'PUT' | 'DELETE', 125 | body?: unknown 126 | ): Promise { 127 | try { 128 | const response = await fetch(`${this.baseUrl}/api/v1/${endpoint}`, { 129 | method, 130 | headers: { 131 | 'Content-Type': 'application/json', 132 | 'x-api-key': this.apiKey 133 | }, 134 | body: body ? JSON.stringify(body) : undefined 135 | }); 136 | 137 | if (!response.ok) { 138 | const error = await response.json() as { error: string }; 139 | 140 | if (response.status === 401) { 141 | throw new AuthenticationError(error.error); 142 | } 143 | throw new TruffleError(error.error || 'Request failed', response.status); 144 | } 145 | 146 | return await response.json() as T; 147 | } catch (error) { 148 | if (error instanceof TruffleError) { 149 | throw error; 150 | } 151 | throw new TruffleError('Network error', 0); 152 | } 153 | } 154 | 155 | /** 156 | * Initiates a chat session with an agent 157 | * @param agentId ID of the agent to chat with 158 | * @param messages Array of chat messages 159 | * @returns The agent's response 160 | */ 161 | async chat(agentId: string, messages: ChatMessage[]): Promise { 162 | return this.makeRequest( 163 | `agents/${agentId}/chat`, 164 | 'POST', 165 | { messages } 166 | ); 167 | } 168 | 169 | /** 170 | * Validates agent configuration 171 | * @param config Agent configuration to validate 172 | * @throws {ValidationError} If the configuration is invalid 173 | */ 174 | private validateAgentConfig(config: AgentConfig): void { 175 | const requiredFields: (keyof AgentConfig)[] = ['name', 'instruction', 'model']; 176 | const missingFields = requiredFields.filter(field => !config[field]); 177 | 178 | if (missingFields.length > 0) { 179 | throw new ValidationError( 180 | `Missing required fields: ${missingFields.join(', ')}`, 181 | { fields: missingFields } 182 | ); 183 | } 184 | } 185 | /** 186 | * Uploads a file for RAG processing 187 | * @param file The file to upload (Browser File or Node.js file-like object) 188 | * @returns A promise that resolves to the document ID 189 | */ 190 | async uploadRAGFile(file: File | NodeFile): Promise<{ documentId: string }> { 191 | const formData = new FormData(); 192 | 193 | // Handle both browser File objects and Node.js file-like objects 194 | if ('data' in file) { 195 | // Node.js environment - create a blob from the data 196 | const blob = new Blob([file.data as ArrayBuffer], { type: file.type }); 197 | formData.append('file', blob, file.name); 198 | } else { 199 | // Browser environment - use File object directly 200 | formData.append('file', file); 201 | } 202 | 203 | const response = await this.makeFormDataRequest<{ documentId: string }>( 204 | 'rag/upload', 205 | 'POST', 206 | formData 207 | ); 208 | 209 | return { documentId: response.documentId }; 210 | } 211 | 212 | /** 213 | * Makes a request with FormData payload 214 | */ 215 | private async makeFormDataRequest( 216 | endpoint: string, 217 | method: string, 218 | formData: FormData 219 | ): Promise { 220 | const url = `${this.baseUrl}/api/v1/${endpoint}`; 221 | 222 | const headers = { 223 | 'x-api-key': this.apiKey 224 | }; 225 | 226 | const response = await fetch(url, { 227 | method, 228 | headers, 229 | body: formData 230 | }); 231 | 232 | if (!response.ok) { 233 | // Get the response text for better error debugging 234 | const responseText = await response.text(); 235 | try { 236 | // Try to parse as JSON 237 | const errorData = JSON.parse(responseText) as { error: string }; 238 | throw new TruffleError(errorData.error || 'Request failed', response.status); 239 | } catch (e) { 240 | // If parsing fails, return the raw text 241 | throw new TruffleError(`Request failed: ${responseText}`, response.status); 242 | } 243 | } 244 | 245 | // Parse the response as JSON 246 | const responseText = await response.text(); 247 | if (!responseText) { 248 | return {} as T; 249 | } 250 | return JSON.parse(responseText) as T; 251 | } 252 | } --------------------------------------------------------------------------------