UNPKG

@agentdb/sdk

Version:

JavaScript SDK for AgentDB database service

667 lines (498 loc) 19.1 kB
# AgentDB JavaScript SDK A lightweight JavaScript SDK for the AgentDB database service. This SDK provides a simple interface for listing databases and executing SQL statements against SQLite and DuckDB databases. ## Features - **Fetch-only**: Uses only the native fetch API, no external dependencies - **Async/Await**: Modern promise-based API - **Error Handling**: Comprehensive error handling with custom exception types - **TypeScript Ready**: Written with TypeScript compatibility in mind - **Multi-Database**: Supports both SQLite and DuckDB databases - **Vector Support**: Built-in utilities for vector operations and embeddings - **Template Management**: Create, manage, and apply database templates - **Natural Language to SQL**: Convert natural language queries to SQL - **MCP Integration**: Create and manage MCP server URL slugs - **Debug Mode**: Built-in debug logging with server-side debug information ## Installation ```bash npm install @agentdb/sdk ``` ## Quick Start ```javascript import { DatabaseService } from '@agentdb/sdk'; // Create a service instance const service = new DatabaseService('https://api.agentdb.dev', 'your-api-key'); // List databases for a token const databases = await service.listDatabases('your-uuid-token'); console.log('Available databases:', databases); // Create a connection const connection = service.connect('your-uuid-token', 'my-database', 'sqlite'); // Execute SQL statements const result = await connection.execute([ { sql: 'CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)', params: [] }, { sql: 'INSERT INTO users (name) VALUES (?)', params: ['John Doe'] } ]); console.log('Execution result:', result); ``` ## API Reference ### DatabaseService The main service class for listing databases and creating connections. #### Constructor ```javascript new DatabaseService(baseUrl, apiKey, debug = false) ``` - `baseUrl` (string): The base URL of the AgentDB service - `apiKey` (string): Your API key for authentication - `debug` (boolean, optional): Enable debug logging (default: false) #### Methods ##### `listDatabases(token)` Lists all databases for a given token. - `token` (string): The UUID token for database access - Returns: `Promise<Array>` - Array of database objects ```javascript const databases = await service.listDatabases('uuid-token'); // Returns: [{ name: 'db1', type: 'sqlite', fileName: 'db1.sqlite', size: 8192, modified: '2024-01-01T00:00:00.000Z' }] ``` ##### `connect(token, dbName, dbType)` Creates a new database connection. - `token` (string): The UUID token for database access - `dbName` (string): The name of the database - `dbType` (string): The type of database ('sqlite' or 'duckdb', defaults to 'sqlite') - Returns: `DatabaseConnection` - A new connection instance ```javascript const connection = service.connect('uuid-token', 'my-database', 'sqlite'); ``` ##### `deleteDatabase(token, dbName, dbType)` Deletes a database permanently. - `token` (string): The UUID token for database access - `dbName` (string): The name of the database to delete - `dbType` (string): The type of database ('sqlite' or 'duckdb', defaults to 'sqlite') - Returns: `Promise<Object>` - Deletion result with success message ```javascript await service.deleteDatabase('uuid-token', 'old-database', 'sqlite'); ``` ##### `renameDatabase(token, oldDbName, newDbName, dbType)` Renames a database. - `token` (string): The UUID token for database access - `oldDbName` (string): The current name of the database - `newDbName` (string): The new name for the database - `dbType` (string): The type of database ('sqlite' or 'duckdb', defaults to 'sqlite') - Returns: `Promise<Object>` - Rename result with success message ```javascript await service.renameDatabase('uuid-token', 'old-name', 'new-name', 'sqlite'); ``` ##### `copyDatabase(sourceToken, sourceDbName, sourceDbType, destToken, destDbName)` Copies a database from one location to another. - `sourceToken` (string): The UUID token for the source database - `sourceDbName` (string): The name of the source database - `sourceDbType` (string): The type of the source database ('sqlite' or 'duckdb') - `destToken` (string): The UUID token for the destination - `destDbName` (string): The name for the destination database - Returns: `Promise<Object>` - Copy result with success message ```javascript await service.copyDatabase('source-token', 'source-db', 'sqlite', 'dest-token', 'dest-db'); ``` ##### `getUploadUrl(token, dbName, dbType)` Gets a presigned URL for uploading a database file. - `token` (string): The UUID token for database access - `dbName` (string): The name for the database - `dbType` (string): The type of database ('sqlite' or 'duckdb', defaults to 'sqlite') - Returns: `Promise<Object>` - Upload URL information with uploadUrl, fileName, and expiresIn ```javascript const { uploadUrl, fileName } = await service.getUploadUrl('uuid-token', 'my-db', 'sqlite'); ``` ##### `getDownloadUrl(token, dbName, dbType)` Gets a presigned URL for downloading a database file. - `token` (string): The UUID token for database access - `dbName` (string): The name of the database - `dbType` (string): The type of database ('sqlite' or 'duckdb', defaults to 'sqlite') - Returns: `Promise<Object>` - Download URL information with downloadUrl, fileName, and expiresIn ```javascript const { downloadUrl, fileName } = await service.getDownloadUrl('uuid-token', 'my-db', 'sqlite'); ``` ##### `createTemplate(templateName, initializationSql, description)` Creates a new database template. - `templateName` (string): The name for the template - `initializationSql` (Array<string>): Array of SQL statements to initialize the template - `description` (string): Description of the template - Returns: `Promise<Object>` - Created template information ```javascript const template = await service.createTemplate( 'my-template', ['CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)'], 'A simple user table template' ); ``` ##### `listTemplates()` Lists all available templates. - Returns: `Promise<Array>` - Array of template objects ```javascript const templates = await service.listTemplates(); ``` ##### `getTemplate(templateName)` Gets a specific template by name. - `templateName` (string): The name of the template to retrieve - Returns: `Promise<Object>` - Template information ```javascript const template = await service.getTemplate('my-template'); ``` ##### `updateTemplate(templateName, initializationSql, description)` Updates an existing template. - `templateName` (string): The name of the template to update - `initializationSql` (Array<string>): Array of SQL statements to initialize the template - `description` (string): Description of the template - Returns: `Promise<Object>` - Update result with success message and old template info ```javascript const result = await service.updateTemplate( 'my-template', ['CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)'], 'Updated user table template with email' ); ``` ##### `deleteTemplate(templateName)` Deletes a template. - `templateName` (string): The name of the template to delete - Returns: `Promise<Object>` - Deletion result with success message ```javascript await service.deleteTemplate('my-template'); ``` ##### `getTemplateInfo(templateName, token, dbName, dbType)` Gets template information for a specific database. - `templateName` (string): The name of the template - `token` (string): The UUID token for database access - `dbName` (string): The name of the database - `dbType` (string): The type of database ('sqlite' or 'duckdb', defaults to 'sqlite') - Returns: `Promise<Object>` - Template info including schema and application status ```javascript const info = await service.getTemplateInfo('my-template', 'uuid-token', 'my-db', 'sqlite'); ``` ##### `getAppliedTemplates(token, dbName, dbType)` Gets applied templates for a database. - `token` (string): The UUID token for database access - `dbName` (string): The name of the database - `dbType` (string): The type of database ('sqlite' or 'duckdb', defaults to 'sqlite') - Returns: `Promise<Object>` - Applied templates information ```javascript const applied = await service.getAppliedTemplates('uuid-token', 'my-db', 'sqlite'); ``` ##### `createMcpSlug(queryParams)` Creates a permanent URL slug for MCP server endpoints. - `queryParams` (Object): Query parameters for the MCP endpoint - Returns: `Promise<Object>` - Created slug information with slug and full URL ```javascript const slug = await service.createMcpSlug({ key: 'your-api-key', token: 'uuid-token', dbName: 'my-db' }); ``` ##### `getMcpSlug(slug)` Gets MCP slug information. - `slug` (string): The slug identifier - Returns: `Promise<Object>` - Slug information and query parameters ```javascript const slugInfo = await service.getMcpSlug('abc123'); ``` ### DatabaseConnection A connection to a specific database for executing SQL statements. #### Constructor ```javascript new DatabaseConnection(baseUrl, apiKey, token, dbName, dbType) ``` Typically created via `DatabaseService.connect()` rather than directly. #### Methods ##### `execute(statements)` Executes one or more SQL statements. - `statements` (Array|Object): Array of statement objects or single statement object - Returns: `Promise<Object>` - Execution results Each statement object should have: - `sql` (string): The SQL statement to execute - `params` (Array, optional): Parameters for the SQL statement ```javascript // Single statement const result = await connection.execute({ sql: 'SELECT * FROM users WHERE id = ?', params: [1] }); // Multiple statements const result = await connection.execute([ { sql: 'INSERT INTO users (name) VALUES (?)', params: ['Alice'] }, { sql: 'INSERT INTO users (name) VALUES (?)', params: ['Bob'] } ]); ``` ##### `naturalLanguageToSql(query, conversationHistory, templateName)` Converts natural language to SQL and optionally executes it. - `query` (string): The natural language query - `conversationHistory` (Array, optional): Optional conversation history for context - `templateName` (string, optional): Optional template name for schema context - Returns: `Promise<Object>` - Natural language conversion results with generated SQL and optional execution results ```javascript // Simple natural language query const result = await connection.naturalLanguageToSql('show me all users'); console.log('Generated SQL:', result.sql); console.log('Results:', result.results); // With conversation history for context const conversationHistory = [ { query: 'show me all users', sql: 'SELECT * FROM users', results: [{ rows: [{ id: 1, name: 'John' }] }] } ]; const result2 = await connection.naturalLanguageToSql( 'how many are there?', conversationHistory ); // With template for schema context const result3 = await connection.naturalLanguageToSql( 'show me customer orders', null, 'crm-template' ); ``` ## Error Handling The SDK provides specific error types for different scenarios: ```javascript import { AgentDBError, AuthenticationError, ValidationError, DatabaseError, createVectorBuffer } from '@agentdb/sdk'; try { const result = await connection.execute({ sql: 'SELECT * FROM users', params: [] }); } catch (error) { if (error instanceof AuthenticationError) { console.error('Authentication failed:', error.message); } else if (error instanceof ValidationError) { console.error('Invalid request:', error.message); } else if (error instanceof DatabaseError) { console.error('Database error:', error.message); } else if (error instanceof AgentDBError) { console.error('AgentDB error:', error.message); } else { console.error('Unexpected error:', error.message); } } ``` ## Examples ### Basic CRUD Operations ```javascript import { DatabaseService } from '@agentdb/sdk'; const service = new DatabaseService('https://api.agentdb.dev', 'your-api-key'); const connection = service.connect('your-token', 'users-db', 'sqlite'); // Create table await connection.execute({ sql: `CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT UNIQUE, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )`, params: [] }); // Insert data await connection.execute({ sql: 'INSERT INTO users (name, email) VALUES (?, ?)', params: ['John Doe', 'john@example.com'] }); // Query data const result = await connection.execute({ sql: 'SELECT * FROM users WHERE email = ?', params: ['john@example.com'] }); console.log('User data:', result.results[0].data); ``` ### Batch Operations ```javascript // Insert multiple records in a single request const users = [ ['Alice Smith', 'alice@example.com'], ['Bob Johnson', 'bob@example.com'], ['Carol Williams', 'carol@example.com'] ]; const statements = users.map(([name, email]) => ({ sql: 'INSERT INTO users (name, email) VALUES (?, ?)', params: [name, email] })); await connection.execute(statements); ``` ### Using DuckDB for Analytics ```javascript const analyticsConnection = service.connect('your-token', 'analytics', 'duckdb'); // Create analytics table await analyticsConnection.execute({ sql: `CREATE TABLE IF NOT EXISTS events ( id UUID DEFAULT gen_random_uuid(), timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, event_type VARCHAR(50), user_id VARCHAR(50), properties JSON )`, params: [] }); // Aggregate query const result = await analyticsConnection.execute({ sql: `SELECT event_type, COUNT(*) as total_events, COUNT(DISTINCT user_id) as unique_users FROM events WHERE timestamp >= CURRENT_DATE - INTERVAL '7 days' GROUP BY event_type ORDER BY total_events DESC`, params: [] }); console.log('Weekly analytics:', result.results[0].data); ``` ### Database Management Operations ```javascript import { DatabaseService } from '@agentdb/sdk'; const service = new DatabaseService('https://api.agentdb.dev', 'your-api-key'); const token = 'your-uuid-token'; // Delete a database await service.deleteDatabase(token, 'old-database', 'sqlite'); // Rename a database await service.renameDatabase(token, 'current-name', 'new-name', 'sqlite'); // Copy a database between tokens await service.copyDatabase( 'source-token', 'source-db', 'sqlite', 'dest-token', 'backup-db' ); ``` ### Vector Operations The SDK provides utilities for working with vector embeddings and similarity search: ```javascript import { DatabaseService, createVectorBuffer } from '@agentdb/sdk'; const service = new DatabaseService('https://api.agentdb.dev', 'your-api-key'); const connection = service.connect('your-token', 'documents-db', 'sqlite'); // Create a table with vector embeddings await connection.execute({ sql: `CREATE TABLE IF NOT EXISTS documents ( id INTEGER PRIMARY KEY, content TEXT, embedding BLOB )`, params: [] }); // Insert documents with vector embeddings const documents = [ { content: 'Machine learning basics', embedding: [0.1, 0.2, 0.3, 0.4] }, { content: 'Database fundamentals', embedding: [0.5, 0.6, 0.7, 0.8] }, { content: 'Vector search techniques', embedding: [0.2, 0.3, 0.4, 0.5] } ]; for (const doc of documents) { await connection.execute({ sql: 'INSERT INTO documents (content, embedding) VALUES (?, ?)', params: [doc.content, createVectorBuffer(doc.embedding)] }); } // Perform vector similarity search const queryEmbedding = createVectorBuffer([0.1, 0.2, 0.3, 0.4]); const searchResult = await connection.execute({ sql: `SELECT id, content, vec_distance_cosine(embedding, ?) as similarity FROM documents ORDER BY similarity LIMIT 5`, params: [queryEmbedding] }); console.log('Similar documents:', searchResult.results[0].rows); // You can also use arrays directly (they will be automatically converted) const directArrayResult = await connection.execute({ sql: `SELECT id, content, vec_distance_cosine(embedding, ?) as similarity FROM documents ORDER BY similarity LIMIT 5`, params: [[0.1, 0.2, 0.3, 0.4]] // Array will be processed server-side }); ``` For a complete vector operations example, see [`examples/vector-operations.js`](./examples/vector-operations.js). ### File Upload/Download ```javascript // Get upload URL and upload a file const { uploadUrl } = await service.getUploadUrl(token, 'imported-db', 'sqlite'); // Upload file using the presigned URL const file = new File([fileData], 'database.sqlite'); await fetch(uploadUrl, { method: 'PUT', body: file, headers: { 'Content-Type': 'application/octet-stream' } }); // Get download URL and download a file const { downloadUrl, fileName } = await service.getDownloadUrl(token, 'my-db', 'sqlite'); // Download the file const response = await fetch(downloadUrl); const blob = await response.blob(); // Create download link const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = fileName; a.click(); URL.revokeObjectURL(url); ``` ## Debug Mode The SDK supports debug mode for troubleshooting and development. When enabled, it provides detailed logging of requests, responses, and server-side debug information. ```javascript // Enable debug mode const service = new DatabaseService('https://api.agentdb.dev', 'your-api-key', true); // Debug logs will be shown in console const databases = await service.listDatabases('your-token'); // Connections inherit debug mode from service const connection = service.connect('your-token', 'my-db', 'sqlite'); // Execute with debug information const result = await connection.execute({ sql: 'SELECT * FROM users', params: [] }); // Access server-side debug logs from response if (result.debugLogs) { console.log('Server debug logs:', result.debugLogs); } ``` For detailed debug mode documentation, see [DEBUG_USAGE.md](./DEBUG_USAGE.md). ## API Reference ### createVectorBuffer(values) Creates a Float32 buffer from an array of numbers for use as vector parameters in SQL queries. **Parameters:** - `values` (number[]): Array of numeric values to convert to a vector buffer **Returns:** - `Buffer|Uint8Array`: Buffer containing the vector data as Float32 values **Throws:** - `ValidationError`: If values is not an array, is empty, or contains non-numeric values **Example:** ```javascript import { createVectorBuffer } from '@agentdb/sdk'; // Create a vector buffer const embedding = createVectorBuffer([0.1, 0.2, 0.3, 0.4]); // Use in a query const result = await connection.execute({ sql: 'SELECT * FROM documents WHERE vec_distance_cosine(embedding, ?) < 0.5', params: [embedding] }); ``` **Notes:** - Each number is stored as a 32-bit float (4 bytes) - The resulting buffer length will be `values.length × 4` bytes - Works in both Node.js and browser environments - For simple use cases, you can pass arrays directly to `params` and they will be processed server-side ## Requirements - Node.js 18.0.0 or higher - Modern browser with fetch API support ## License MIT