@toothfairyai/sdk
v0.7.2
Published
JavaScript/TypeScript SDK for ToothFairyAI API integration
Maintainers
Readme
ToothFairyAI SDK for JavaScript/TypeScript
Official TypeScript SDK for the ToothFairyAI API - A comprehensive toolkit for building AI-powered applications with chat, document processing, agent management, and more.
Status: Production Ready | Version: 0.7.0
Test Results
The SDK includes comprehensive verification tests ensuring all managers and methods are properly implemented:
Test Suites: 1 passed, 1 total
Tests: 62 passed, 62 total
✓ SDK Structure (3 tests)
- Client initialization with proper parameters
- All 24 managers accessible
- Expected methods on each manager
✓ Method Signatures (17 tests)
- Agent, Chat, Document, Entity, Streaming, Billing managers
✓ Error Handling (5 tests)
- Missing API key/workspace ID validation
- ToothFairyError properties and inheritance
✓ SDK Completeness (27 tests)
- Core files present
- All 24 manager directories with manager files
- Proper export structure
✓ Type Definitions (4 tests)
- AgentMode, EntityType, DocumentType, StreamEventType
✓ Client Methods (6 tests)
- testConnection, getHealth, getStreamingUrl, getWorkspaceId, getConfig, request, aiRequestInstallation
npm install @toothfairyai/sdkQuick Start
import { ToothFairyClient } from '@toothfairyai/sdk';
const client = new ToothFairyClient({
apiKey: 'your-api-key',
workspaceId: 'your-workspace-id'
});
// Send a message to an agent
const response = await client.chat.sendToAgent('Hello, how can you help me?', 'agent-id');
console.log(response.agentResponse);Table of Contents
- SDK Overview
- Client Configuration
- Core Features
- Complete API Reference
- Streaming Responses
- Error Handling
- Best Practices
SDK Overview
The ToothFairyAI SDK provides a TypeScript-first interface to all 95 API endpoints, organized into 18 specialized managers:
| Manager | Purpose | Endpoints |
|---------|---------|-----------|
| client.chat | Chat conversations & messages | 7 |
| client.agents | AI agent management | 5 |
| client.documents | Document upload & management | 6 |
| client.entities | Topics, intents, NER entities | 5 |
| client.folders | Content organization | 5 |
| client.prompts | Prompt templates | 5 |
| client.agentFunctions | Agent function calls | 5 |
| client.authorisations | Auth configurations | 5 |
| client.channels | Communication channels | 5 |
| client.connections | Database/API connections | 3 |
| client.members | Workspace members | 4 |
| client.sites | Website crawling | 4 |
| client.benchmarks | Performance testing | 5 |
| client.hooks | Custom code execution | 5 |
| client.scheduledJobs | Cron jobs & scheduling | 5 |
| client.secrets | Secret management | 2 |
| client.dictionary | Translation dictionary | 2 |
| client.embeddings | Document embeddings | 1 |
| client.chartingSettings | Charting configuration | 2 |
| client.embeddingsSettings | Embeddings configuration | 2 |
| client.billing | Usage & costs | 1 |
| client.streams | Output streams | 2 |
| client.requestLogs | Request logging | 2 |
| client.streaming | Real-time streaming | - |
Client Configuration
Region-Specific Endpoints
ToothFairyAI operates in multiple regions. Configure your client to use the appropriate endpoints:
// US Region
const clientUS = new ToothFairyClient({
apiKey: 'your-api-key',
workspaceId: 'your-workspace-id',
baseUrl: 'https://api.us.toothfairyai.com',
aiUrl: 'https://ai.us.toothfairyai.com',
aiStreamUrl: 'https://ai-stream.us.toothfairyai.com'
});
// EU Region
const clientEU = new ToothFairyClient({
apiKey: 'your-api-key',
workspaceId: 'your-workspace-id',
baseUrl: 'https://api.eu.toothfairyai.com',
aiUrl: 'https://ai.eu.toothfairyai.com',
aiStreamUrl: 'https://ai-stream.eu.toothfairyai.com'
});
// Australia Region (default)
const clientAU = new ToothFairyClient({
apiKey: 'your-api-key',
workspaceId: 'your-workspace-id',
baseUrl: 'https://api.toothfairyai.com',
aiUrl: 'https://ai.toothfairyai.com',
aiStreamUrl: 'https://ais.toothfairyai.com'
});Configuration Options
const client = new ToothFairyClient({
apiKey: 'your-api-key', // Required: Your API key
workspaceId: 'your-workspace-id', // Required: Your workspace ID
baseUrl: 'https://api.toothfairyai.com', // Optional: API base URL (region-specific)
aiUrl: 'https://ai.toothfairyai.com', // Optional: AI service URL (region-specific)
aiStreamUrl: 'https://ais.toothfairyai.com', // Optional: Streaming URL (region-specific)
timeout: 120000 // Optional: Request timeout in ms (default: 120000)
});Getting Your Credentials
- API Key: Log in to ToothFairyAI Admin → API Integration → Generate API Key
- Workspace ID: Found in your workspace settings or API dashboard
Core Features
1. Chat & Messaging
Create conversations, send messages, and manage chat history with AI agents.
2. Agent Management
Create, configure, and manage AI agents with different modes (retriever, chatter, planner, etc.).
3. Document Processing
Upload, search, and manage documents for knowledge base integration.
4. Entity Management
Organize content with topics, intents, and named entity recognition.
5. Streaming
Real-time streaming responses with EventEmitter-based pattern.
Complete API Reference
Chat & Messaging
Create a Chat Session
const chat = await client.chat.create({
name: 'Customer Support',
primaryRole: 'agent-id',
customerId: 'customer-123',
customerInfo: { name: 'John Doe', email: '[email protected]' },
externalParticipantId: '[email protected]',
channelSettings: {
sms: { isEnabled: true, recipient: '+1234567890', providerID: 'twilio' },
email: { isEnabled: true, recipient: '[email protected]' }
}
});
console.log(`Chat ID: ${chat.id}`);Update a Chat
const chat = await client.chat.update({
id: 'chat-id',
name: 'Updated Chat Name',
customerId: 'new-customer-id'
});Get Chat Details
const chat = await client.chat.get('chat-id');
console.log(`Chat: ${chat.name}`);
console.log(`Primary Role: ${chat.primaryRole}`);List Chats
const chats = await client.chat.list(10, 0);
for (const chat of chats.items) {
console.log(`${chat.name} (ID: ${chat.id})`);
}Delete a Chat
await client.chat.delete('chat-id');Create a Message
const message = await client.chat.createMessage({
chatID: 'chat-id',
text: 'Hello, I need help with my account',
role: 'user',
userID: 'user-123',
images: ['https://example.com/image.jpg'],
files: ['https://example.com/document.pdf']
});Update a Message
const message = await client.chat.updateMessage('message-id', {
text: 'Updated message text',
role: 'user'
});Get a Message
const message = await client.chat.getMessage('message-id');
console.log(`Message: ${message.text}`);List Messages in a Chat
const messages = await client.chat.listMessages('chat-id', 20, 0);
for (const msg of messages.items) {
console.log(`${msg.role}: ${msg.text}`);
}Send Message to Agent (Non-Streaming)
const response = await client.chat.sendToAgent(
'Hello, how can you help me?',
'agent-id',
{
chatId: 'existing-chat-id', // Optional - creates new chat if not provided
phoneNumber: '+1234567890', // Optional
customerId: 'customer-123', // Optional
providerId: 'provider-id', // Optional
customerInfo: { name: 'John' }, // Optional
attachments: {
images: ['https://example.com/image.jpg'],
files: ['https://example.com/document.pdf'],
audios: ['https://example.com/audio.mp3'],
videos: ['https://example.com/video.mp4']
}
}
);
console.log(`Response: ${response.agentResponse}`);
console.log(`Chat ID: ${response.chatId}`);
console.log(`Message ID: ${response.messageId}`);Agents
Create an Agent
const agent = await client.agents.create({
label: 'Customer Support Agent',
mode: 'retriever', // retriever, coder, chatter, planner, computer, voice
interpolationString: 'You are a helpful customer support assistant...',
goals: 'Help customers resolve issues and answer questions',
temperature: 0.7,
maxTokens: 2000,
maxHistory: 10,
topK: 10,
docTopK: 5,
description: 'Specialized agent for customer support',
hasMemory: true,
showCitations: true,
allowedTopics: ['topic-1', 'topic-2'],
staticDocs: ['doc-1', 'doc-2']
});
console.log(`Agent ID: ${agent.id}`);Update an Agent
const agent = await client.agents.update('agent-id', {
label: 'Updated Agent Name',
temperature: 0.8,
maxTokens: 3000
});Get Agent Details
const agent = await client.agents.get('agent-id');
console.log(`Agent: ${agent.label}`);
console.log(`Mode: ${agent.mode}`);
console.log(`Goals: ${agent.goals}`);List Agents
const agents = await client.agents.list(10, 0);
for (const agent of agents.items) {
console.log(`${agent.label} (${agent.mode})`);
}Delete an Agent
await client.agents.delete('agent-id');Documents
Upload a Document
const result = await client.documents.upload('/path/to/document.pdf', 'folder-id', {
onProgress: (percent, loaded, total) => {
console.log(`Progress: ${percent}%`);
}
});
console.log(`Uploaded: ${result.filename}`);
console.log(`Size: ${result.sizeInMB} MB`);Upload from Base64
const base64Data = 'base64-encoded-file-data';
const result = await client.documents.uploadFromBase64(
base64Data,
'document.pdf',
'application/pdf',
'folder-id'
);Create Document from URL
const doc = await client.documents.createFromPath(
'https://example.com/document.pdf',
'user-123',
{
title: 'My Document',
folderId: 'folder-id',
topics: ['topic-1', 'topic-2'],
status: 'published'
}
);Create Document Record
const doc = await client.documents.create({
userid: 'user-123',
title: 'My Document',
type: 'readComprehensionFile', // readComprehensionUrl, readComprehensionPdf
topics: ['topic-1'],
folderid: 'folder-id',
external_path: 'https://example.com/doc.pdf',
source: 'external',
status: 'published',
scope: 'training'
});Get Document
const doc = await client.documents.get('doc-id');
console.log(`Title: ${doc.title}`);
console.log(`Type: ${doc.type}`);
console.log(`Status: ${doc.status}`);Update Document
const doc = await client.documents.update('doc-id', {
userid: 'user-123',
title: 'Updated Title',
topics: ['new-topic'],
folderid: 'new-folder-id',
status: 'published'
});List Documents
const docs = await client.documents.list(20, 0, 'folder-id', 'published');
for (const doc of docs.items) {
console.log(`${doc.title} (ID: ${doc.id})`);
}Delete Document
await client.documents.delete('doc-id');Search Documents
const results = await client.documents.search('product documentation', {
topK: 10,
metadata: { category: 'procedures' }
});
for (const result of results) {
console.log(`Score: ${result.score}`);
console.log(`Content: ${result.content}`);
}Download Document
const result = await client.documents.download(
'document.pdf',
'/downloads/document.pdf',
'documents',
{
onProgress: (percent, loaded, total) => {
console.log(`Download: ${percent}%`);
}
}
);
console.log(`Downloaded: ${result.filename}`);Entities
Create an Entity
const entity = await client.entities.create('user-123', 'Product Launch', 'topic', {
description: 'New product launch announcements and updates',
emoji: '🚀',
parentEntity: 'parent-topic-id',
backgroundColor: '#FF5733'
});Get Entity
const entity = await client.entities.get('entity-id');
console.log(`Label: ${entity.label}`);
console.log(`Type: ${entity.type}`);Update Entity
const entity = await client.entities.update('entity-id', {
label: 'Updated Label',
description: 'New description',
emoji: '🔧'
});Delete Entity
await client.entities.delete('entity-id');List Entities
const entities = await client.entities.list(20, 'topic');
for (const entity of entities.items) {
console.log(`${entity.label} (${entity.type})`);
}Get Entities by Type
const topics = await client.entities.getByType('topic');
const intents = await client.entities.getByType('intent');
const nerEntities = await client.entities.getByType('ner');Search Entities
const results = await client.entities.search('product', 'topic');
for (const entity of results) {
console.log(`${entity.label}`);
}Folders
Create a Folder
const folder = await client.folders.create('user-123', 'Procedures', {
description: 'Medical procedures documentation',
emoji: '📁',
status: 'active',
parent: 'parent-folder-id' // Optional - for subfolders
});Get Folder
const folder = await client.folders.get('folder-id');
console.log(`Name: ${folder.name}`);
console.log(`Parent: ${folder.parent}`);Update Folder
const folder = await client.folders.update('folder-id', {
name: 'Updated Name',
description: 'New description',
status: 'active'
});Delete Folder
await client.folders.delete('folder-id');List Folders
const folders = await client.folders.list('active', 20, 0);
for (const folder of folders.items) {
console.log(`${folder.name}`);
}Get Root Folders
const rootFolders = await client.folders.getRootFolders();
for (const folder of rootFolders) {
console.log(`Root: ${folder.name}`);
}Get Subfolders
const subfolders = await client.folders.getSubfolders('folder-id');
for (const folder of subfolders) {
console.log(`Subfolder: ${folder.name}`);
}Get Folder Tree
const tree = await client.folders.getTree();
function printTree(nodes: any[], level = 0) {
for (const node of nodes) {
console.log(' '.repeat(level) + `📁 ${node.name}`);
printTree(node.children, level + 1);
}
}
printTree(tree);Search Folders
const results = await client.folders.search('procedures');
for (const folder of results) {
console.log(`${folder.name}`);
}Prompts
Create a Prompt
const prompt = await client.prompts.create('user-123', {
type: 'greeting',
label: 'Greeting',
promptLength: 50,
interpolationString: 'Hello {{name}}, how can I help you today?',
scope: 'global',
style: 'friendly',
domain: 'customer-support',
promptPlaceholder: 'Enter greeting message',
availableToAgents: ['agent-1', 'agent-2']
});Get Prompt
const prompt = await client.prompts.get('prompt-id');
console.log(`Label: ${prompt.label}`);
console.log(`Template: ${prompt.interpolationString}`);Update Prompt
const prompt = await client.prompts.update('prompt-id', {
label: 'Updated Label',
interpolationString: 'New template string',
availableToAgents: ['agent-3']
});Delete Prompt
await client.prompts.delete('prompt-id');List Prompts
const prompts = await client.prompts.list({
type: 'greeting',
limit: 20,
offset: 0
});
for (const prompt of prompts.items) {
console.log(`${prompt.label}`);
}Get Prompts by Type
const greetings = await client.prompts.getByType('greeting');Get Prompts by Agent
const agentPrompts = await client.prompts.getByAgent('agent-id');Get Prompts by Scope
const globalPrompts = await client.prompts.getByScope('global');Search Prompts
const results = await client.prompts.search('greeting', 'greeting');Clone Prompt
const cloned = await client.prompts.clone('prompt-id', 'user-123', {
label: 'Cloned Greeting',
interpolationString: 'Modified template'
});Agent Functions
Create an Agent Function
// Create a GET function
const getFunc = await client.agentFunctions.create('Weather API', {
description: 'Get current weather data for a location',
url: 'https://api.weather.com/current',
requestType: 'GET',
authorisationType: 'bearer',
authorisationKey: 'your-token',
parameters: [
{ name: 'location', type: 'string', required: true }
]
});
// Create a POST function with headers
const postFunc = await client.agentFunctions.create('Create Order', {
description: 'Create a new order in the system',
url: 'https://api.example.com/orders',
requestType: 'POST',
authorisationType: 'apikey',
headers: [{ key: 'Content-Type', value: 'application/json' }],
staticArgs: [{ key: 'source', value: 'chatbot' }]
});Update Agent Function
const func = await client.agentFunctions.update('function-id', {
name: 'Updated Function Name',
url: 'https://new-url.com'
});Delete Agent Function
await client.agentFunctions.delete('function-id');Get Agent Function
const func = await client.agentFunctions.get('function-id');
console.log(`Name: ${func.name}`);
console.log(`URL: ${func.url}`);List Agent Functions
const functions = await client.agentFunctions.list(20, 0);
for (const func of functions.items) {
console.log(`${func.name}`);
}Search Agent Functions
const results = await client.agentFunctions.search('weather');
for (const func of results) {
console.log(`${func.name}`);
}Authorisations
Create an Authorisation
// API Key authorisation
const apiKeyAuth = await client.authorisations.create('External API Key', 'apikey', {
description: 'API key for external service',
tokenSecret: 'your-api-key-value'
});
// Bearer token authorisation
const bearerAuth = await client.authorisations.create('Service Token', 'bearer', {
tokenSecret: 'your-bearer-token'
});
// OAuth authorisation
const oauthAuth = await client.authorisations.create('GitHub OAuth', 'oauth', {
description: 'GitHub OAuth for API access',
scope: 'repo,user',
grantType: 'authorization_code',
clientId: 'github-client-id',
clientSecret: 'encrypted-secret',
authorizationBaseUrl: 'https://github.com/login/oauth/authorize',
tokenBaseUrl: 'https://github.com/login/oauth/access_token'
});Update Authorisation
const auth = await client.authorisations.update('auth-id', {
name: 'Updated Auth Name',
description: 'New description'
});Delete Authorisation
await client.authorisations.delete('auth-id');Get Authorisation
const auth = await client.authorisations.get('auth-id');
console.log(`Name: ${auth.name}`);
console.log(`Type: ${auth.type}`);List Authorisations
const auths = await client.authorisations.list(20, 0);
for (const auth of auths.items) {
console.log(`${auth.name} (${auth.type})`);
}Get Authorisations by Type
const apiKeys = await client.authorisations.getByType('apikey');
const oauthAuths = await client.authorisations.getByType('oauth');Search Authorisations
const results = await client.authorisations.search('github');
for (const auth of results) {
console.log(`${auth.name}`);
}Channels
Create a Channel
const channel = await client.channels.create('SMS Channel', 'sms', 'twilio', {
senderId: '+1234567890',
description: 'SMS notifications via Twilio',
isActive: true
});Update Channel
const channel = await client.channels.update('channel-id', {
name: 'Updated Channel',
isActive: false
});Delete Channel
await client.channels.delete('channel-id');Get Channel
const channel = await client.channels.get('channel-id');
console.log(`Name: ${channel.name}`);
console.log(`Provider: ${channel.provider}`);List Channels
const channels = await client.channels.list(20, 0);
for (const channel of channels.items) {
console.log(`${channel.name} (${channel.provider})`);
}Connections
Get Connection
const connection = await client.connections.get('connection-id');
console.log(`Name: ${connection.name}`);
console.log(`Type: ${connection.type}`);
console.log(`Host: ${connection.host}`);List Connections
const connections = await client.connections.list(20, 0);
for (const conn of connections.items) {
console.log(`${conn.name} (${conn.type})`);
}Get Connections by Type
const postgresConns = await client.connections.getByType('postgres');
const mysqlConns = await client.connections.getByType('mysql');Search Connections
const results = await client.connections.search('database');
for (const conn of results) {
console.log(`${conn.name}`);
}Delete Connection
await client.connections.delete('connection-id');Members
Get Member
const member = await client.members.get('member-id');
console.log(`User ID: ${member.userID}`);
console.log(`Role: ${member.role}`);
console.log(`Status: ${member.status}`);List Members
const members = await client.members.list(20);
for (const member of members.items) {
console.log(`${member.userID} (${member.role})`);
}Update Member
const member = await client.members.update({
id: 'member-id',
role: 'admin',
status: 'active'
});Delete Member
await client.members.delete('member-id');Sites
Get Site
const site = await client.sites.get('site-id');
console.log(`Name: ${site.name}`);
console.log(`URL: ${site.url}`);
console.log(`Status: ${site.status}`);List Sites
const sites = await client.sites.list(20, 0);
for (const site of sites.items) {
console.log(`${site.name} - ${site.url}`);
}Update Site
const site = await client.sites.update('site-id', {
name: 'Updated Site',
status: 'active',
allowedPaths: ['/docs', '/blog']
});Delete Site
await client.sites.delete('site-id');Benchmarks
Create a Benchmark
const benchmark = await client.benchmarks.create('Customer Support Test', {
description: 'Test agent performance on customer support queries',
questions: [
{
question: 'How do I reset my password?',
answer: 'Go to Settings > Security > Reset Password',
reasoning: 'Standard password reset flow',
context: 'Account management'
}
],
files: ['doc-1', 'doc-2']
});Update Benchmark
const benchmark = await client.benchmarks.update('benchmark-id', {
name: 'Updated Benchmark',
description: 'New description'
});Delete Benchmark
await client.benchmarks.delete('benchmark-id');Get Benchmark
const benchmark = await client.benchmarks.get('benchmark-id');
console.log(`Name: ${benchmark.name}`);
console.log(`Questions: ${benchmark.questions?.length}`);List Benchmarks
const benchmarks = await client.benchmarks.list(20, 0);
for (const benchmark of benchmarks.items) {
console.log(`${benchmark.name}`);
}Hooks
Create a Hook
const hook = await client.hooks.create('Data Processing Hook', 'process_data', {
customExecutionCode: 'def process_data(data): return data.upper()',
customExecutionInstructions: 'Process incoming data',
availableLibraries: 'pandas,numpy',
allowExternalApi: true,
hardcodedScript: false
});Update Hook
const hook = await client.hooks.update('hook-id', {
name: 'Updated Hook',
customExecutionCode: 'def process_data(data): return data.lower()'
});Delete Hook
await client.hooks.delete('hook-id');Get Hook
const hook = await client.hooks.get('hook-id');
console.log(`Name: ${hook.name}`);
console.log(`Function: ${hook.functionName}`);List Hooks
const hooks = await client.hooks.list(20, 0);
for (const hook of hooks.items) {
console.log(`${hook.name}`);
}Scheduled Jobs
Create a Scheduled Job
const job = await client.scheduledJobs.create('Daily Report', {
description: 'Generate daily report at 9 AM',
agentId: 'agent-id',
customPromptId: 'prompt-id',
forcedPrompt: 'Generate a daily summary report',
schedule: {
frequency: 'DAILY',
hour: 9,
minute: 0
},
timezone: 'UTC',
isActive: true,
status: 'ACTIVE'
});Update Scheduled Job
const job = await client.scheduledJobs.update('job-id', {
name: 'Updated Job',
isActive: false,
schedule: {
frequency: 'WEEKLY',
dayOfWeek: 1,
hour: 9
}
});Delete Scheduled Job
await client.scheduledJobs.delete('job-id');Get Scheduled Job
const job = await client.scheduledJobs.get('job-id');
console.log(`Name: ${job.name}`);
console.log(`Status: ${job.status}`);
console.log(`Schedule: ${JSON.stringify(job.schedule)}`);List Scheduled Jobs
const jobs = await client.scheduledJobs.list(20, 0);
for (const job of jobs.items) {
console.log(`${job.name} (${job.status})`);
}Secrets
Secrets are linked to authorisations. You must first create an authorisation, then create a secret for it.
Create a Secret
// First, create an authorisation
const auth = await client.authorisations.create('External Service Auth', 'apikey', {
description: 'Authorisation for external service'
});
// Then create a secret linked to that authorisation
const secret = await client.secrets.create(auth.id, 'your-secret-api-key-12345');
console.log(`Secret created: ${secret.name}`);Get a Secret
const secret = await client.secrets.get('secret-id');
console.log(`Secret: ${secret.name}`);List Secrets
const secrets = await client.secrets.list(20, 0);
for (const secret of secrets.items) {
console.log(`${secret.name}`);
}Delete Secret
await client.secrets.delete('secret-id');Dictionary
Get Dictionary Entry
const entry = await client.dictionary.get('entry-id');
console.log(`Source: ${entry.sourceText}`);
console.log(`Target: ${entry.targetText}`);
console.log(`Languages: ${entry.sourceLanguage} -> ${entry.targetLanguage}`);List Dictionary Entries
const entries = await client.dictionary.list(20);
for (const entry of entries.items) {
console.log(`${entry.sourceLanguage} -> ${entry.targetLanguage}`);
}Embeddings
Get Document Embeddings
const embeddings = await client.embeddings.get();
for (const emb of embeddings) {
console.log(`Document: ${emb.title}`);
console.log(`Chunk: ${emb.chunk_id}`);
console.log(`Type: ${emb.type}`);
}Settings
Charting Settings
// Get charting settings
const settings = await client.chartingSettings.get();
console.log(`Primary Color: ${settings.primaryColor}`);
console.log(`Secondary Color: ${settings.secondaryColor}`);
// Update charting settings
const updated = await client.chartingSettings.update({
primaryColor: '#FF5733',
secondaryColor: '#33FF57',
lineColor: '#3357FF'
});Embeddings Settings
// Get embeddings settings
const settings = await client.embeddingsSettings.get();
console.log(`Max Chunk Words: ${settings.maxChunkWords}`);
console.log(`Chunking Strategy: ${settings.chunkingStrategy}`);
// Update embeddings settings
const updated = await client.embeddingsSettings.update({
maxChunkWords: 1000,
chunkingStrategy: 'summary',
imageExtractionStrategy: 'safe'
});Billing
Get Monthly Costs
// Using get() method (like Python SDK)
const costs = await client.billing.get();
console.log(`API Usage: ${JSON.stringify(costs.apiUsage)}`);
console.log(`Training Usage: ${JSON.stringify(costs.trainingUsage)}`);
console.log(`Total Cost: $${costs.apiUsage?.totalCostUSD || 0}`);
// Or using getMonthCosts() alias
const costs2 = await client.billing.getMonthCosts();Streams
Get Output Stream
const stream = await client.streams.get('stream-id');
console.log(`Content: ${stream.content}`);
console.log(`Type: ${stream.type}`);
console.log(`Status: ${stream.status}`);List Output Streams
const streams = await client.streams.list(20);
for (const stream of streams.items) {
console.log(`${stream.type} - ${stream.status}`);
}Request Logs
Get Request Log
const log = await client.requestLogs.get('log-id');
console.log(`Type: ${log.type}`);
console.log(`Status: ${log.status}`);
console.log(`Tokens: ${log.tokens}`);
console.log(`Words: ${log.words}`);List Request Logs
const logs = await client.requestLogs.list(20);
for (const log of logs.items) {
console.log(`${log.type} - ${log.status} (${log.tokens} tokens)`);
}Streaming Responses
Simple Streaming
const session = await client.streaming.sendToAgent('Tell me about your AI capabilities', 'agent-id');
session.on('data', (data) => {
console.log(data.text, end='', flush=true);
});
session.on('complete', () => {
console.log('\nDone!');
console.log(`Chat ID: ${session.chatId}`);
console.log(`Message ID: ${session.messageId}`);
});Streaming with Event Types
const session = await client.streaming.sendToAgent('Hello', 'agent-id');
session.on('status', (data) => {
console.log('Status:', data.status);
});
session.on('progress', (data) => {
console.log('Progress:', data.processing_status);
});
session.on('data', (data) => {
console.log('Response:', data.text);
});
session.on('complete', (data) => {
console.log('Complete:', data);
});
session.on('error', (error) => {
console.error('Error:', error);
});Streaming with Progress Tracking
// Enable ALL SSE events tracking
const session = await client.streaming.sendToAgent('Explain AI', 'agent-id', {
showProgress: true
});
// Standard events
session.on('data', (data) => {
console.log('Agent text:', data.text);
});
// NEW: Raw SSE events (when showProgress=true)
session.on('sse_event', (data) => {
console.log('Raw SSE event:', data);
// This gives you access to ALL events from the streaming endpoint
});Continue a Conversation
// First message creates a new chat
const session1 = await client.streaming.sendToAgent('Hello', 'agent-id');
session1.on('data', (data) => {
console.log(data.text, end='');
});
session1.on('complete', () => {
// Continue in the same chat
const session2 = await client.streaming.sendToAgent(
'Tell me more',
'agent-id',
{ chatId: session1.chatId } // Use the chat ID from first session
);
session2.on('data', (data) => {
console.log(data.text, end='');
});
});Streaming with Attachments
const session = await client.streaming.sendToAgent(
'What\'s in this image?',
'agent-id',
{
attachments: {
images: ['https://example.com/image.jpg']
}
}
);
session.on('data', (data) => {
console.log(data.text, end='');
});Error Handling
import { ToothFairyError } from '@toothfairyai/sdk';
const client = new ToothFairyClient({
apiKey: '...',
workspaceId: '...'
});
try {
const response = await client.chat.sendToAgent('Hello', 'agent-id');
} catch (error) {
if (error instanceof ToothFairyError) {
console.error('Error:', error.message);
console.error('Code:', error.code);
console.error('Status:', error.statusCode);
console.error('Response:', error.response);
} else {
console.error('Unknown error:', error);
}
}Specific Error Types
import {
ToothFairyError
} from '@toothfairyai/sdk';
try {
const client = new ToothFairyClient({
apiKey: '',
workspaceId: ''
});
} catch (error) {
if (error instanceof ToothFairyError) {
console.error('Error:', error.message);
console.error('Code:', error.code);
}
}
try {
const result = await client.documents.upload('large_file.pdf');
} catch (error) {
if (error instanceof ToothFairyError) {
console.error('Error:', error.message);
console.error('Status:', error.statusCode);
}
}Connection Testing
// Test connection
const isConnected = await client.testConnection();
console.log(`Connected: ${isConnected}`);
// Get health status
const health = await client.getHealth();
console.log(`Status: ${health.status}`);Best Practices
1. Use Environment Variables for Credentials
import { ToothFairyClient } from '@toothfairyai/sdk';
const client = new ToothFairyClient({
apiKey: process.env.TOOTHPAIRY_API_KEY!,
workspaceId: process.env.TOOTHPAIRY_WORKSPACE_ID!
});2. Handle Pagination
async function getAllChats() {
const allChats: any[] = [];
let offset = 0;
const limit = 100;
while (true) {
const response = await client.chat.list(limit, offset);
allChats.push(...response.items);
if (response.items.length < limit) {
break;
}
offset += limit;
}
return allChats;
}3. Use Streaming for Long Responses
// For long responses, use streaming to show progress
const session = await client.streaming.sendToAgent(
'Generate a comprehensive report',
'agent-id'
);
session.on('data', (data) => {
console.log(data.text, end='', flush=true);
});4. Implement Retry Logic
async function sendWithRetry(
message: string,
agentId: string,
maxRetries = 3
): Promise<any> {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await client.chat.sendToAgent(message, agentId);
} catch (error) {
if (attempt < maxRetries - 1) {
const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
}5. Use Chat IDs for Conversations
// Create a chat once
const chat = await client.chat.create({
name: 'Support Session',
primaryRole: 'agent-id'
});
// Use the same chat ID for all messages in the conversation
const response1 = await client.chat.sendToAgent('Hello', 'agent-id', {
chatId: chat.id
});
const response2 = await client.chat.sendToAgent('Tell me more', 'agent-id', {
chatId: chat.id
});6. Organize Documents with Folders
// Create folder structure
const procedures = await client.folders.create('user-123', 'Procedures', {
description: 'Medical procedures documentation'
});
const policies = await client.folders.create('user-123', 'Policies', {
description: 'Company policies'
});
// Upload documents to appropriate folders
await client.documents.upload('procedure1.pdf', procedures.id);
await client.documents.upload('policy1.pdf', policies.id);7. Use Topics for Content Organization
// Create topics
const productTopic = await client.entities.create(
'user-123',
'Product Updates',
'topic',
{
description: 'Latest product updates and announcements',
emoji: '🚀'
}
);
// Associate documents with topics
const doc = await client.documents.createFromPath(
'product_guide.pdf',
'user-123',
{
title: 'Product Guide',
topics: [productTopic.id]
}
);8. Monitor Usage with Billing
// Check monthly usage
const costs = await client.billing.getMonthCosts();
const apiCost = costs.apiUsage?.totalCostUSD || 0;
const trainingCost = costs.trainingUsage?.totalCharge || 0;
console.log(`API Cost: $${apiCost.toFixed(2)}`);
console.log(`Training Cost: $${trainingCost.toFixed(2)}`);
console.log(`Total: $${(apiCost + trainingCost).toFixed(2)}`);9. Use Scheduled Jobs for Automation
// Create a daily report job
const job = await client.scheduledJobs.create({
id: 'daily-report',
name: 'Daily Summary Report',
agentID: 'report-agent-id',
schedule: {
frequency: 'DAILY',
hour: 9,
minute: 0
},
timezone: 'UTC',
isActive: true,
status: 'ACTIVE'
});10. Secure Secrets Management
// Store sensitive data as secrets
await client.secrets.create({
id: 'external-api-key',
name: 'External Service API Key',
description: 'API key for external service integration'
});
// Reference secrets in agent functions
await client.agentFunctions.create({
id: 'api-function',
name: 'External API Call',
url: 'https://api.example.com/data',
authorisationType: 'apikey',
// Use secret reference instead of hardcoding
});Integration Examples
Express.js Server
import express from 'express';
import { ToothFairyClient } from '@toothfairyai/sdk';
const app = express();
const client = new ToothFairyClient({
apiKey: process.env.TOOTHPAIRY_API_KEY!,
workspaceId: process.env.TOOTHPAIRY_WORKSPACE_ID!
});
app.post('/chat', async (req, res) => {
const { message, agentId } = req.body;
try {
const response = await client.chat.sendToAgent(message, agentId);
res.json(response);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000);Next.js API Route
// pages/api/chat.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { ToothFairyClient } from '@toothfairyai/sdk';
const client = new ToothFairyClient({
apiKey: process.env.TOOTHPAIRY_API_KEY!,
workspaceId: process.env.TOOTHPAIRY_WORKSPACE_ID!
});
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const { message, agentId } = req.body;
try {
const response = await client.chat.sendToAgent(message, agentId);
res.status(200).json(response);
} catch (error) {
res.status(500).json({ error: error.message });
}
}React Component with Streaming
import React, { useState, useEffect } from 'react';
import { ToothFairyClient } from '@toothfairyai/sdk';
const client = new ToothFairyClient({
apiKey: process.env.REACT_APP_TOOTHFAIRY_API_KEY!,
workspaceId: process.env.REACT_APP_TOOTHFAIRY_WORKSPACE_ID!
});
function ChatComponent() {
const [messages, setMessages] = useState<string[]>([]);
const [currentResponse, setCurrentResponse] = useState('');
const sendMessage = async (message: string) => {
const session = await client.streaming.sendToAgent(message, 'agent-id');
session.on('data', (data) => {
setCurrentResponse(prev => prev + data.text);
});
session.on('complete', () => {
setMessages(prev => [...prev, currentResponse]);
setCurrentResponse('');
});
};
return (
<div>
{messages.map((msg, i) => <div key={i}>{msg}</div>)}
{currentResponse && <div>{currentResponse}</div>}
</div>
);
}Development
Building
npm run buildTesting
# Run unit tests
npm test
# Run integration tests (requires API credentials)
TF_API_KEY=your-api-key \
TF_WORKSPACE_ID=your-workspace-id \
TF_AGENT_ID=your-agent-id \
npx ts-node tests/integration/test-streaming.tsLinting
npm run lint
npm run lint:fixRequirements
- Node.js >= 14.0.0
- TypeScript >= 4.9.5 (for development)
License
MIT
Support
For issues and questions:
- GitHub Issues: Report an issue
- Documentation: Full API documentation
- Email: [email protected]
