@maximai/maxim-js
Version:
Maxim AI JS SDK. Visit https://getmaxim.ai for more info.
478 lines (477 loc) • 16.8 kB
TypeScript
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>;
}