UNPKG

@maximai/maxim-js

Version:

Maxim AI JS SDK. Visit https://getmaxim.ai for more info.

478 lines (477 loc) 16.8 kB
import { MaximCache } from "./cache/cache"; import { LoggerConfig, MaximLogger } from "./logger/logger"; import type { DatasetEntry } from "./models/dataset"; import { Folder } from "./models/folder"; import { Prompt } from "./models/prompt"; import { PromptChain } from "./models/promptChain"; import { QueryRule } from "./models/queryBuilder"; import { type TestRunBuilder } from "./models/testRun"; declare global { var __maxim__sdk__instances__: Map<string, Maxim>; } /** * Configuration object for initializing the Maxim SDK. */ export type Config = { /** * Base URL for the Maxim API. * @default "https://app.getmaxim.ai" */ baseUrl?: string; /** * API key for authenticating requests to the Maxim API. * Required for all API calls. * @see https://app.getmaxim.ai/workspace?redirect=/settings/api-keys to generate your API key */ apiKey: string; /** * Enable prompt management features. * When enabled, allows synchronization of prompts, prompt chains, and folders from Maxim. * @default false */ promptManagement?: boolean; /** * Custom cache implementation for storing and retrieving data. * @default InMemoryCache - Uses a simple in-memory caching mechanism */ cache?: MaximCache; /** * Enable debug mode for additional logging and troubleshooting information. * Useful during development and integration. * @default false */ debug?: boolean; /** * Raise exceptions instead of logging them. * @default false */ raiseExceptions?: boolean; }; /** * Main class for the Maxim SDK that provides access to all platform features. * * The Maxim class is the primary entry point for interacting with the Maxim * observability platform. It provides methods for prompt management, logging, * dataset operations, and test run execution. The class handles authentication, * caching, and API communication. * * @class Maxim * @example * import { Maxim } from '@maximai/maxim-js'; * * // Basic initialization * const maxim = new Maxim({ * apiKey: 'your-api-key' * }); * * @example * // Full configuration * const maxim = new Maxim({ * apiKey: 'your-api-key', * baseUrl: 'https://app.getmaxim.ai', * promptManagement: true, * debug: true, * cache: new CustomCacheImplementation() * }); * * @example * // Using prompt management * const maxim = new Maxim({ * apiKey: 'your-api-key', * promptManagement: true * }); * * // Get a prompt with deployment rules * const rule = new QueryBuilder() * .deploymentVar('environment', 'production') * .tag('version', 'v2.0') * .build(); * * const prompt = await maxim.getPrompt('prompt-id', rule); * if (prompt) { * const response = await prompt.run('Hello world'); * console.log(response.choices[0].message.content); * } * * @example * // Creating and running test runs * const testResult = await maxim * .createTestRun('sample-test-run', 'workspace-id') * .withDataStructure({ * input: 'INPUT', * expectedOutput: 'EXPECTED_OUTPUT' * }) * .withData('dataset-id') * .withEvaluators('bias', 'toxicity') * .yieldsOutput(async (data) => { * const response = await callYourModel(data.input); * return { data: response }; * }) * .run(); * * @example * // Logging with Maxim * const logger = await maxim.logger({ id: 'my-app' }); * const session = logger.session({ id: 'session-1', name: 'User session' }); * const trace = session.trace({ id: 'trace-1', name: 'Query Processing', sessionId: 'session-1' }); * * // ... Log other operations * * trace.end(); * * // finally, before app shutdown * await maxim.cleanup(); */ export declare class Maxim { private readonly apiKey; private readonly baseUrl; private readonly isDebug; private intervalHandle?; private cache; private isPromptManagementEnabled; private sync?; private loggers; private promptVersionByNumberCache; private APIService; private _raiseExceptions; /** * Creates a new Maxim SDK instance. * * @param config - Configuration object for the SDK * @throws {Error} When the API key is not provided * @important **CRITICAL**: Always call `cleanup()` before your application * exits. Failure to do so may result in memory leaks, unflushed data, or * hanging processes. This is especially important in production environments * and long-running applications. * @example * const maxim = new Maxim({ * apiKey: process.env.MAXIM_API_KEY, * promptManagement: true, * debug: process.env.NODE_ENV === 'development' * }); * * @example * // With custom cache * import { RedisCacheImplementation } from './custom-cache'; * * const maxim = new Maxim({ * apiKey: 'your-api-key', * cache: new RedisCacheImplementation({ * host: 'localhost', * port: 6379 * }) * }); * * // Always remember to cleanup before exit * process.on('SIGINT', async () => { * await maxim.cleanup(); * process.exit(0); * }); */ constructor(config: Config); private syncEntities; private syncPrompts; private syncPromptChains; private syncFolders; private getPromptFromCache; private getAllPromptsFromCache; private getPromptChainFromCache; private getAllPromptChainsFromCache; private getFolderFromCache; private getAllFoldersFromCache; private getCacheKey; private getPromptVersionForRule; private getPromptChainVersionForRule; private getFoldersForRule; /** * Retrieves a specific prompt by ID that matches the given query rule. * * This method fetches a prompt from the Maxim platform based on deployment rules * and query criteria. It supports versioning and rule-based prompt selection. * * @async * @param promptId - The unique identifier of the prompt to fetch * @param rule - Query rule defining deployment variables, tags, and matching criteria * @returns The matching prompt with run capabilities, or undefined if not found * @throws {Error} When prompt management is not enabled * @throws {Error} When no active deployments found for the prompt matching the query rule * @example * import { QueryBuilder } from '@maximai/maxim-js'; * * const rule = new QueryBuilder() * .deploymentVar('environment', 'production') * .tag('version', 'v2.0') * .build(); * * const prompt = await maxim.getPrompt('user-greeting-prompt-id', rule); * if (prompt) { * const response = await prompt.run('Hello!', { * variables: { userName: 'John' }, * imageUrls: [] * }); * console.log(response.choices[0].message.content); * } * * @example * // Using folder-scoped queries * const rule = new QueryBuilder() * .folder('customer-service-folder') * .deploymentVar('language', 'en') * .build(); * * const prompt = await maxim.getPrompt('support-template', rule); */ getPrompt(promptId: string, rule: QueryRule): Promise<Prompt | undefined>; /** * Retrieves all prompts that match the given query rule. * * This method fetches multiple prompts from the Maxim platform based on * deployment rules and query criteria. Useful for getting all prompts * within a specific folder or matching certain deployment variables. * * @async * @param rule - Query rule defining deployment variables, tags, and matching criteria * @returns Array of matching prompts with run capabilities, or undefined if none found * @throws {Error} When prompt management is not enabled * @throws {Error} When no active deployments found for any prompt matching the query rule * @example * import { QueryBuilder } from '@maximai/maxim-js'; * * // Get all production prompts in a specific folder * const rule = new QueryBuilder() * .folder('customer-support') * .deploymentVar('environment', 'production') * .build(); * * const prompts = await maxim.getPrompts(rule); * if (prompts) { * for (const prompt of prompts) { * console.log(`Prompt: ${prompt.promptId}, Version: ${prompt.version}`); * } * } * * @example * // Get all prompts with specific tags * const rule = new QueryBuilder() * .tag('category', 'greeting') * .tag('language', 'english') * .and() * .build(); * * const greetingPrompts = await maxim.getPrompts(rule); */ getPrompts(rule: QueryRule): Promise<Prompt[] | undefined>; /** * Retrieves a specific prompt chain by ID that matches the given query rule. * * This method fetches a prompt chain from the Maxim platform based on deployment rules * and query criteria. It supports versioning and rule-based prompt chain selection. * Prompt chains allow you to orchestrate multiple prompts in sequence with conditional logic. * * @async * @param promptChainId - The unique identifier of the prompt chain to fetch * @param rule - Query rule defining deployment variables, tags, and matching criteria * @returns The matching prompt chain with run capabilities, or undefined if not found * @throws {Error} When prompt management is not enabled * @throws {Error} When no active deployments found for the prompt chain matching the query rule * @example * import { QueryBuilder } from '@maximai/maxim-js'; * * const rule = new QueryBuilder() * .deploymentVar('environment', 'production') * .tag('version', 'v2.0') * .build(); * * const promptChain = await maxim.getPromptChain('user-onboarding-chain-id', rule); * if (promptChain) { * const response = await promptChain.run('New user registration', { * variables: { userName: 'John', userType: 'premium' } * }); * console.log(response.finalOutput); * } * * @example * // Using folder-scoped queries * const rule = new QueryBuilder() * .folder('customer-onboarding-folder') * .deploymentVar('language', 'en') * .build(); * * const promptChain = await maxim.getPromptChain('welcome-sequence', rule); */ getPromptChain(promptChainId: string, rule: QueryRule): Promise<PromptChain | undefined>; /** * Retrieves all prompt chains that match the given query rule. * * This method fetches multiple prompt chains from the Maxim platform based on * deployment rules and query criteria. Useful for getting all prompt chains * within a specific folder or matching certain deployment variables. * * @async * @param rule - Query rule defining deployment variables, tags, and matching criteria * @returns Array of matching prompt chains with run capabilities, or undefined if none found * @throws {Error} When prompt management is not enabled * @throws {Error} When no active deployments found for any prompt chain matching the query rule * @example * import { QueryBuilder } from '@maximai/maxim-js'; * * // Get all production prompt chains in a specific folder * const rule = new QueryBuilder() * .folder('customer-support') * .deploymentVar('environment', 'production') * .build(); * * const promptChains = await maxim.getPromptChains(rule); * if (promptChains) { * for (const promptChain of promptChains) { * console.log(`Prompt Chain: ${promptChain.promptChainId}, Version: ${promptChain.version}`); * } * } * * @example * // Get all prompt chains with specific tags * const rule = new QueryBuilder() * .tag('category', 'workflow') * .tag('complexity', 'advanced') * .and() * .build(); * * const workflowChains = await maxim.getPromptChains(rule); */ getPromptChains(rule: QueryRule): Promise<PromptChain[] | undefined>; /** * This method is used to get a folder by id * @async * @param folderId - Folder id to fetch * @returns a single folder * @throws {Error} If no folder found with id * @example * const folder = await maxim.getFolderById("folderId"); */ getFolderById(folderId: string): Promise<Folder | undefined>; /** * This method is used to get all folders that match the query rule * @async * @param rule - Query rule to match * @returns Array of folders * @throws {Error} If no folders found matching the query rule * @example * const folders = await maxim.getFolders( * new QueryBuilder() * .and() * .deploymentVar("Environment", "Production") * .build() * ); */ getFolders(rule: QueryRule): Promise<Folder[] | undefined>; /** * This method is used to add entries to a dataset * @async * @param datasetId Dataset id to add entries to * @param entries Entries to add to the dataset * @returns void * @example * await maxim.addDatasetEntries("datasetId", [ * { * columnName: "input", * cellValue: { * type: VariableType.TEXT, * payload: "cell value", * }, * }, * ]); */ addDatasetEntries(datasetId: string, entries: DatasetEntry[]): Promise<void>; /** * Creates a logger instance for capturing observability data. * * The logger provides methods for tracking sessions, traces, generations, and * other observability events. It handles buffering, batching, and sending data * to the Maxim platform. * * @async * @param config - Configuration for the logger instance * @returns Logger instance for capturing observability data, or undefined if creation fails * @throws {Error} When the specified log repository is not found * @example * // Basic logger creation * const logger = await maxim.logger({ * id: 'my-repository-id', * }); * * if (logger) { * // Create a session for user interactions * const session = logger.session({ * id: 'user-session-123', * name: 'Customer Support Chat' * }); * * // Create a trace for a specific operation * const trace = session.trace({ * id: 'query-trace-456', * name: 'Customer Query Processing' * }); * * // ... Log other operations * * trace.end(); * * // finally, before app shutdown * await maxim.cleanup(); * } */ logger(config: LoggerConfig): Promise<MaximLogger | undefined>; private checkIfRepoExists; /** * This method is used to create a test run * @param name - Name of the test run * @param inWorkspaceId - Workspace Id to create the test run in * @returns Test run instance * @example * // You can keep chaining methods to * // the created test run to configure it * const testRun = maxim * .createTestRun( * "testRunName", * "workspaceId" * ); // .with___(...) */ createTestRun(name: string, inWorkspaceId: string): TestRunBuilder<undefined>; /** * Cleans up all SDK resources and prepares for application shutdown. * * This method performs essential cleanup operations including stopping sync intervals, * flushing logger data, clearing caches, and destroying HTTP agents. It ensures proper * resource deallocation and prevents memory leaks. * * @async * @important **CRITICAL**: Always call this method before your application * exits. Failure to do so may result in memory leaks, unflushed data, or * hanging processes. This is especially important in production environments * and long-running applications. * @example * // Basic cleanup on application shutdown * process.on('SIGINT', async () => { * console.log('Shutting down gracefully...'); * await maxim.cleanup(); * process.exit(0); * }); * * @example * // Cleanup in Express.js application * process.on('SIGTERM', async () => { * console.log('SIGTERM received, shutting down...'); * await maxim.cleanup(); * server.close(() => { * process.exit(0); * }); * }); * * @example * // Cleanup in test suites * afterAll(async () => { * await maxim.cleanup(); * }); */ cleanup(): Promise<void>; }