import { DataAPIClient } from '@datastax/astra-db-ts';
export interface ToolParameter {
param: string;
description?: string;
attribute?: string;
type?: string;
required?: boolean | number;
operator?: string;
expr?: string;
enum?: string[];
embedding_model?: string;
info?: string;
value?: any;
}
export interface Tool {
_id?: string;
tags?: string[];
type: string;
name: string;
description?: string;
limit?: number;
method?: string;
collection_name?: string;
table_name?: string;
db_name?: string;
enabled?: boolean | true;
projection?: Record<string, number>;
parameters?: ToolParameter[];
}
class AstraClient {
private client: DataAPIClient | null = null;
private db: any = null;
private collection: any = null;
private token: string | null = null;
private endpoint: string | null = null;
private dbName: string | null = null;
private collectionName: string = 'tool_catalog';
async connect(): Promise<void> {
// Access Vite environment variables
this.token = import.meta.env.VITE_ASTRA_DB_APPLICATION_TOKEN || '';
this.endpoint = import.meta.env.VITE_ASTRA_DB_API_ENDPOINT || '';
this.dbName = import.meta.env.VITE_ASTRA_DB_DB_NAME || '';
this.collectionName = import.meta.env.VITE_ASTRA_DB_CATALOG_COLLECTION || 'tool_catalog';
if (!this.token || !this.endpoint || !this.dbName) {
throw new Error('Missing required environment variables: ASTRA_DB_APPLICATION_TOKEN, ASTRA_DB_API_ENDPOINT, and ASTRA_DB_DB_NAME are required');
}
try {
// Initialize the DataAPIClient with the token
this.client = new DataAPIClient(this.token);
// Get the database using the endpoint and token
// The endpoint format: https://<database-id>-<region>.apps.astra.datastax.com
this.db = this.client.db(this.endpoint, { token: this.token });
// Get the collection
this.collection = this.db.collection(this.collectionName);
} catch (error) {
throw new Error(`Failed to connect to Astra DB: ${error instanceof Error ? error.message : String(error)}`);
}
}
async getTools(): Promise<Tool[]> {
if (!this.collection) {
await this.connect();
}
try {
// Use find() with filter, which returns a cursor
const cursor = this.collection.find({ type: 'tool' });
// Convert cursor to array
const tools: Tool[] = [];
for await (const doc of cursor) {
tools.push(doc as Tool);
}
return tools;
} catch (error) {
throw new Error(`Failed to fetch tools: ${error instanceof Error ? error.message : String(error)}`);
}
}
async updateTool(tool: Tool): Promise<void> {
if (!this.collection) {
await this.connect();
}
try {
if (tool._id) {
// Update existing document
await this.collection.updateOne(
{ _id: tool._id },
{ $set: tool }
);
} else {
// Insert new document
await this.collection.insertOne({ document: tool });
}
} catch (error) {
throw new Error(`Failed to update tool: ${error instanceof Error ? error.message : String(error)}`);
}
}
}
export const astraClient = new AstraClient();