UNPKG

@maximai/maxim-js

Version:

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

1,116 lines 60.8 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Maxim = void 0; const dataset_1 = require("./apis/dataset"); const folder_1 = require("./apis/folder"); const logs_1 = require("./apis/logs"); const prompt_1 = require("./apis/prompt"); const promptChain_1 = require("./apis/promptChain"); const inMemory_1 = require("./cache/inMemory"); const filterObjects_1 = require("./filterObjects"); const logger_1 = require("./logger/logger"); const utils_1 = require("./logger/utils"); const platform_1 = require("./platform"); const testRun_1 = require("./testRun/testRun"); const expiringKeyValueStore_1 = __importDefault(require("./utils/expiringKeyValueStore")); var EntityType; (function (EntityType) { EntityType[EntityType["PROMPT"] = 0] = "PROMPT"; EntityType[EntityType["PROMPT_CHAIN"] = 1] = "PROMPT_CHAIN"; EntityType[EntityType["FOLDER"] = 2] = "FOLDER"; })(EntityType || (EntityType = {})); /** * 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(); */ class Maxim { /** * 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) { this.isPromptManagementEnabled = false; this.loggers = new Map(); this.promptVersionByNumberCache = new expiringKeyValueStore_1.default(); if (!config.apiKey) { throw new Error("[Maxim-SDK] API key is required"); } // Check if an instance with the same API key already exists if (globalThis.__maxim__sdk__instances__ && globalThis.__maxim__sdk__instances__.get(config.apiKey)) { console.warn("[Maxim-SDK] You have initialized multiple instances of Maxim with the same API key."); } this.baseUrl = config.baseUrl || "https://app.getmaxim.ai"; this.apiKey = config.apiKey; this._raiseExceptions = config.raiseExceptions || false; this.isDebug = config.debug || false; this.APIService = { prompt: new prompt_1.MaximPromptAPI(this.baseUrl, this.apiKey, this.isDebug), promptChain: new promptChain_1.MaximPromptChainAPI(this.baseUrl, this.apiKey, this.isDebug), folder: new folder_1.MaximFolderAPI(this.baseUrl, this.apiKey, this.isDebug), dataset: new dataset_1.MaximDatasetAPI(this.baseUrl, this.apiKey, this.isDebug), logs: new logs_1.MaximLogsAPI(this.baseUrl, this.apiKey, this.isDebug), }; this.cache = config.cache || new inMemory_1.MaximInMemoryCache(); if (config.promptManagement) { this.isPromptManagementEnabled = true; this.sync = this.syncEntities(); this.intervalHandle = platform_1.platform.timers.setInterval(() => { this.syncEntities(); }, 1000 * 60); // Call unref() to tell Node.js that this interval should not keep the process alive platform_1.platform.timers.maybeUnref(this.intervalHandle); } // Initialize or update the global instances array if (!globalThis.__maxim__sdk__instances__) { globalThis.__maxim__sdk__instances__ = new Map(); } globalThis.__maxim__sdk__instances__.set(this.apiKey, this); } // We will always bootstrap using REST call // Updates will be sent using realtime server async syncEntities() { try { return new Promise((resolve, reject) => { Promise.all([this.syncPrompts(), this.syncFolders(), this.syncPromptChains()]) .then(() => { resolve(); }) .catch((err) => { console.error(`[Maxim-SDK] ${err}`); resolve(); }); }); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while syncing entities: ${err instanceof Error ? err.message : err}`); } } } async syncPrompts() { try { await this.APIService.prompt.getPrompts().then(async (prompts) => { if (this.isDebug) { console.log(`[Maxim-SDK] Syncing ${prompts.length} prompts`); } await Promise.all(prompts.map(async (prompt) => { try { await this.cache.set(this.getCacheKey(EntityType.PROMPT, prompt.promptId), JSON.stringify(prompt)); } catch (err) { console.error(err); } })); }); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while syncing prompts: ${err instanceof Error ? err.message : err}`); } } } async syncPromptChains() { try { await this.APIService.promptChain.getPromptChains().then(async (promptChains) => { if (this.isDebug) { console.log(`[Maxim-SDK] Syncing ${promptChains.length} prompt chains`); } await Promise.all(promptChains.map(async (promptChain) => { try { await this.cache.set(this.getCacheKey(EntityType.PROMPT_CHAIN, promptChain.promptChainId), JSON.stringify(promptChain)); } catch (err) { console.error(err); } })); }); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while syncing prompt chains: ${err instanceof Error ? err.message : err}`); } } } async syncFolders() { try { await this.APIService.folder.getFolders().then(async (folders) => { if (this.isDebug) { console.log(`[Maxim-SDK] Syncing ${folders.length} folders`); } await Promise.all(folders.map(async (folder) => { try { await this.cache.set(this.getCacheKey(EntityType.FOLDER, folder.id), JSON.stringify(folder)); } catch (err) { console.error(err); } })); }); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while syncing folders: ${err instanceof Error ? err.message : err}`); } } } async getPromptFromCache(key) { try { let data = await this.cache.get(key); if (!data) { return null; } return JSON.parse(data); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching prompt from cache: ${err instanceof Error ? err.message : err}`); return null; } } } async getAllPromptsFromCache() { try { let keys = await this.cache.getAllKeys(); if (!keys) { return null; } // Fetching all prompts let data = await Promise.all(keys.filter((key) => key.startsWith("prompt:")).map((key) => this.cache.get(key))); return data.filter((d) => d !== null).map((d) => JSON.parse(d)); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching all prompts from cache: ${err instanceof Error ? err.message : err}`); return null; } } } async getPromptChainFromCache(key) { try { let data = await this.cache.get(key); if (!data) { return null; } return JSON.parse(data); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching prompt chain from cache: ${err instanceof Error ? err.message : err}`); return null; } } } async getAllPromptChainsFromCache() { try { let keys = await this.cache.getAllKeys(); if (!keys) { return null; } // Fetching all prompts let data = await Promise.all(keys.filter((key) => key.startsWith("promptChain:")).map((key) => this.cache.get(key))); return data.filter((d) => d !== null).map((d) => JSON.parse(d)); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching all prompt chains from cache: ${err instanceof Error ? err.message : err}`); return null; } } } async getFolderFromCache(key) { try { let data = await this.cache.get(key); if (!data) { return null; } return JSON.parse(data); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching folder from cache: ${err instanceof Error ? err.message : err}`); return null; } } } async getAllFoldersFromCache() { try { let keys = await this.cache.getAllKeys(); if (!keys) { return null; } // Fetching all prompts let data = await Promise.all(keys.filter((key) => key.startsWith("folder:")).map((key) => this.cache.get(key))); return data.filter((d) => d !== null).map((d) => JSON.parse(d)); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching all folders from cache: ${err instanceof Error ? err.message : err}`); return null; } } } getCacheKey(entity, id) { switch (entity) { case EntityType.PROMPT: return `prompt:${id}`; case EntityType.PROMPT_CHAIN: return `promptChain:${id}`; case EntityType.FOLDER: return `folder:${id}`; } } getPromptVersionForRule(promptVersionAndRules, rule) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t; const sdk = this; try { if (rule) { let incomingQuery = { query: rule.query, operator: rule.operator, exactMatch: rule.exactMatch, }; const objects = []; Object.keys(promptVersionAndRules.rules).forEach((versionId) => { const versionRules = promptVersionAndRules.rules[versionId]; versionRules.forEach((versionRule) => { var _a; if (!versionRule.rules.query) { return; } // Checking for scope and type of scope and filtering candidates if (rule.scopes) { Object.keys(rule.scopes).forEach((key) => { switch (key) { case "folder": break; default: throw new Error("Invalid scope added"); } }); } const version = promptVersionAndRules === null || promptVersionAndRules === void 0 ? void 0 : promptVersionAndRules.versions.find((v) => v.id === versionId); const query = versionRule.rules.query; if (!version) return; // Here we will attach tags to that query if ((_a = version.config) === null || _a === void 0 ? void 0 : _a.tags) { const parsedIncomingQuery = (0, filterObjects_1.parseIncomingQuery)(incomingQuery.query); const tags = version.config.tags; // Generating QueryType from key value pair in tags Object.keys(tags) .filter((key) => tags[key] !== undefined) .filter((key) => parsedIncomingQuery.map((incomingQueryRule) => incomingQueryRule.field).includes(key)) .forEach((key) => { query.rules.push({ field: key, operator: "=", value: tags[key] }); }); } objects.push({ query, id: versionId, }); }); }); const deployedVersionObject = (0, filterObjects_1.findBestMatch)(objects, incomingQuery); if (deployedVersionObject) { const deployedVersion = promptVersionAndRules === null || promptVersionAndRules === void 0 ? void 0 : promptVersionAndRules.versions.find((v) => v.id === deployedVersionObject.id); let prompt; prompt = { promptId: deployedVersion.promptId, versionId: deployedVersion.id, version: deployedVersion.version, messages: (_a = deployedVersion.config) === null || _a === void 0 ? void 0 : _a.messages, modelParameters: ((_b = deployedVersion.config) === null || _b === void 0 ? void 0 : _b.modelParameters) || {}, model: ((_c = deployedVersion.config) === null || _c === void 0 ? void 0 : _c.model) || "", deploymentId: (_d = deployedVersion.config) === null || _d === void 0 ? void 0 : _d.deploymentId, provider: ((_e = deployedVersion.config) === null || _e === void 0 ? void 0 : _e.provider) || "", tags: ((_f = deployedVersion.config) === null || _f === void 0 ? void 0 : _f.tags) || {}, run: async function (input, options) { if (!deployedVersion) { throw new Error("[Maxim-SDK] Deployed version missing while attempting to run prompt"); } return executePromptWithLogging(this.parent, this.generationConfig, deployedVersion, options, () => sdk.APIService.prompt.runPromptVersion(deployedVersion.id, input, options)); }, withLogger: function (parent, generationConfig) { const newPrompt = { ...this, parent, generationConfig, }; return newPrompt; }, }; return prompt; } } else { // Checking version rules with rule being undefined for (const versionId in promptVersionAndRules.rules) { const versionRules = promptVersionAndRules.rules[versionId]; let isMatch = false; for (const rule of versionRules) { if (rule.rules.query === undefined || ((_g = rule.rules.query) === null || _g === void 0 ? void 0 : _g.rules.length) === 0) { isMatch = true; break; } } if (isMatch) { const deployedVersion = promptVersionAndRules.versions.find((v) => v.id === versionId); let prompt; prompt = { promptId: deployedVersion.promptId, versionId: deployedVersion.id, version: deployedVersion.version, messages: (_h = deployedVersion.config) === null || _h === void 0 ? void 0 : _h.messages, modelParameters: ((_j = deployedVersion.config) === null || _j === void 0 ? void 0 : _j.modelParameters) || {}, model: ((_k = deployedVersion.config) === null || _k === void 0 ? void 0 : _k.model) || "", deploymentId: (_l = deployedVersion.config) === null || _l === void 0 ? void 0 : _l.deploymentId, provider: ((_m = deployedVersion.config) === null || _m === void 0 ? void 0 : _m.provider) || "", tags: ((_o = deployedVersion.config) === null || _o === void 0 ? void 0 : _o.tags) || {}, run: async function (input, options) { if (!deployedVersion) { throw new Error("[Maxim-SDK] Deployed version missing while attempting to run prompt"); } return executePromptWithLogging(this.parent, this.generationConfig, deployedVersion, options, () => sdk.APIService.prompt.runPromptVersion(deployedVersion.id, input, options)); }, withLogger: function (parent, generationConfig) { const newPrompt = { ...this, parent, generationConfig, }; return newPrompt; }, }; return prompt; } } } if (promptVersionAndRules.fallbackVersion) { let prompt; prompt = { promptId: promptVersionAndRules.fallbackVersion.promptId, versionId: promptVersionAndRules.fallbackVersion.id, version: promptVersionAndRules.fallbackVersion.version, ...promptVersionAndRules.fallbackVersion.config, messages: ((_p = promptVersionAndRules.fallbackVersion.config) === null || _p === void 0 ? void 0 : _p.messages) || [], modelParameters: ((_q = promptVersionAndRules.fallbackVersion.config) === null || _q === void 0 ? void 0 : _q.modelParameters) || {}, model: ((_r = promptVersionAndRules.fallbackVersion.config) === null || _r === void 0 ? void 0 : _r.model) || "", provider: ((_s = promptVersionAndRules.fallbackVersion.config) === null || _s === void 0 ? void 0 : _s.provider) || "", tags: ((_t = promptVersionAndRules.fallbackVersion.config) === null || _t === void 0 ? void 0 : _t.tags) || {}, run: async function (input, options) { var _a; if (!((_a = promptVersionAndRules.fallbackVersion) === null || _a === void 0 ? void 0 : _a.id)) { throw new Error("[Maxim-SDK] Deployed fallback version missing while attempting to run prompt"); } return executePromptWithLogging(this.parent, this.generationConfig, promptVersionAndRules.fallbackVersion, options, () => sdk.APIService.prompt.runPromptVersion(promptVersionAndRules.fallbackVersion.id, input, options)); }, withLogger: function (parent, generationConfig) { const newPrompt = { ...this, parent, generationConfig, }; return newPrompt; }, }; return prompt; } return undefined; } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching prompt version for rule: ${err instanceof Error ? err.message : err}`); return undefined; } } } getPromptChainVersionForRule(promptChainVersionAndRules, rule) { var _a, _b, _c; try { if (rule) { let incomingQuery = { query: rule.query, operator: rule.operator, exactMatch: rule.exactMatch, }; const objects = []; Object.keys(promptChainVersionAndRules.rules).forEach((versionId) => { const versionRules = promptChainVersionAndRules.rules[versionId]; versionRules.forEach((versionRule) => { if (!versionRule.rules.query) { return; } // Checking for scope and type of scope and filtering candidates if (rule.scopes) { Object.keys(rule.scopes).forEach((key) => { switch (key) { case "folder": break; default: throw new Error("Invalid scope added"); } }); } const version = promptChainVersionAndRules === null || promptChainVersionAndRules === void 0 ? void 0 : promptChainVersionAndRules.versions.find((v) => v.id === versionId); const query = versionRule.rules.query; if (!version) return; // Here we will attach tags to that query objects.push({ query, id: versionId, }); }); }); const deployedVersionObject = (0, filterObjects_1.findBestMatch)(objects, incomingQuery); if (deployedVersionObject) { const deployedVersion = promptChainVersionAndRules === null || promptChainVersionAndRules === void 0 ? void 0 : promptChainVersionAndRules.versions.find((v) => v.id === deployedVersionObject.id); return { promptChainId: deployedVersion.promptChainId, versionId: deployedVersion.id, version: deployedVersion.version, nodes: (_a = deployedVersion.config) === null || _a === void 0 ? void 0 : _a.nodes.filter((n) => "prompt" in n), run: (input, options) => { if (!(deployedVersion === null || deployedVersion === void 0 ? void 0 : deployedVersion.id)) { throw new Error("[Maxim-SDK] Deployed version missing while attempting to run prompt chain"); } return this.APIService.promptChain.runPromptChainVersion(deployedVersion.id, input, options); }, }; } } else { // Checking version rules with rule being undefined for (const versionId in promptChainVersionAndRules.rules) { const versionRules = promptChainVersionAndRules.rules[versionId]; let isMatch = false; for (const rule of versionRules) { if (rule.rules.query === undefined || ((_b = rule.rules.query) === null || _b === void 0 ? void 0 : _b.rules.length) === 0) { isMatch = true; break; } } if (isMatch) { const deployedVersion = promptChainVersionAndRules.versions.find((v) => v.id === versionId); return { promptChainId: deployedVersion.promptChainId, versionId: deployedVersion.id, version: deployedVersion.version, nodes: (_c = deployedVersion.config) === null || _c === void 0 ? void 0 : _c.nodes.filter((n) => "prompt" in n), run: (input, options) => { if (!(deployedVersion === null || deployedVersion === void 0 ? void 0 : deployedVersion.id)) { throw new Error("[Maxim-SDK] Deployed version missing while attempting to run prompt chain"); } return this.APIService.promptChain.runPromptChainVersion(deployedVersion.id, input, options); }, }; } } } if (promptChainVersionAndRules.fallbackVersion) { return { promptChainId: promptChainVersionAndRules.fallbackVersion.promptChainId, versionId: promptChainVersionAndRules.fallbackVersion.id, version: promptChainVersionAndRules.fallbackVersion.version, nodes: promptChainVersionAndRules.fallbackVersion.config ? promptChainVersionAndRules.fallbackVersion.config.nodes.filter((n) => "prompt" in n) : [], run: (input, options) => { var _a; if (!((_a = promptChainVersionAndRules.fallbackVersion) === null || _a === void 0 ? void 0 : _a.id)) { throw new Error("[Maxim-SDK] Deployed fallback version missing while attempting to run prompt chain"); } return this.APIService.promptChain.runPromptChainVersion(promptChainVersionAndRules.fallbackVersion.id, input, options); }, }; } return undefined; } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching prompt chain version for rule: ${err instanceof Error ? err.message : err}`); return undefined; } } } getFoldersForRule(folders, rule) { try { let incomingQuery = { query: rule.query, operator: rule.operator, exactMatch: rule.exactMatch, }; const objects = []; folders.forEach((folder) => { const query = { combinator: "AND", not: false, rules: [], }; if (!folder.tags) { return; } const parsedIncomingQuery = (0, filterObjects_1.parseIncomingQuery)(incomingQuery.query); const tags = folder.tags; Object.keys(tags) .filter((key) => tags[key] !== undefined) .filter((key) => parsedIncomingQuery.map((rule) => rule.field).includes(key)) .forEach((key) => { query.rules.push({ field: key, operator: "=", value: tags[key] }); }); if (query.rules.length === 0) { return; } objects.push({ query, id: folder.id, }); }); const folderObjects = (0, filterObjects_1.findAllMatches)(objects, incomingQuery); const ids = folderObjects.map((fo) => fo.id); return folders.filter((f) => ids.includes(f.id)); } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching folders for rule: ${err instanceof Error ? err.message : err}`); return undefined; } } } /** * 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); */ async getPrompt(promptId, rule) { var _a, _b, _c, _d, _e, _f; const sdk = this; try { if (!this.isPromptManagementEnabled) { throw new Error("Prompt Management feature is not enabled. Please enable it in the configuration."); } await this.sync; // Short-circuit: if only condition is promptVersionNumber, fetch exact version with 60s TTL const parsed = (0, filterObjects_1.parseIncomingQuery)(rule.query); if (parsed.length === 1 && parsed[0].field === "promptVersionNumber" && parsed[0].operator === "=") { const num = Number(parsed[0].value); if (isNaN(num)) { throw new Error("Invalid promptVersionNumber value"); } const cacheKey = `pvnum:${promptId}:${num}`; const cached = this.promptVersionByNumberCache.get(cacheKey); if (cached) { return cached; } const versionAndRules = await this.APIService.prompt.getPrompt(promptId, num); if (!versionAndRules || versionAndRules.versions.length === 0) { throw new Error(`No active deployments found for Prompt ${promptId}`); } const deployedVersion = versionAndRules.versions.find((v) => v.version === num); if (!deployedVersion) { throw new Error(`No version ${num} found for Prompt ${promptId}`); } let prompt; prompt = { promptId: deployedVersion.promptId, versionId: deployedVersion.id, version: deployedVersion.version, messages: ((_a = deployedVersion.config) === null || _a === void 0 ? void 0 : _a.messages) || [], modelParameters: ((_b = deployedVersion.config) === null || _b === void 0 ? void 0 : _b.modelParameters) || {}, model: ((_c = deployedVersion.config) === null || _c === void 0 ? void 0 : _c.model) || "", deploymentId: (_d = deployedVersion.config) === null || _d === void 0 ? void 0 : _d.deploymentId, provider: ((_e = deployedVersion.config) === null || _e === void 0 ? void 0 : _e.provider) || "", tags: ((_f = deployedVersion.config) === null || _f === void 0 ? void 0 : _f.tags) || {}, run: async function (input, options) { return executePromptWithLogging(this.parent, this.generationConfig, deployedVersion, options, () => sdk.APIService.prompt.runPromptVersion(deployedVersion.id, input, options)); }, withLogger: function (parent, generationConfig) { const newPrompt = { ...this, parent, generationConfig, }; return newPrompt; }, }; this.promptVersionByNumberCache.set(cacheKey, prompt, 60); return prompt; } const key = this.getCacheKey(EntityType.PROMPT, promptId); // check if prompt is present in cache let versionAndRules = await this.getPromptFromCache(key); // If not present in cache, we make an API call and set in cache if (versionAndRules === null) { versionAndRules = await this.APIService.prompt.getPrompt(promptId); if (versionAndRules.versions.length === 0) { throw new Error(`No active deployments found for Prompt ${promptId}`); } await this.cache.set(promptId, JSON.stringify(versionAndRules)); } // Neither present in cache nor received via API call if (!versionAndRules) { throw new Error(`No active deployments found for Prompt ${promptId}`); } const prompt = this.getPromptVersionForRule(versionAndRules, rule); if (!prompt) { throw new Error(`No active deployments found for Prompt ${promptId}`); } return prompt; } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching prompt: ${err instanceof Error ? err.message : err}`); return 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); */ async getPrompts(rule) { try { if (!this.isPromptManagementEnabled) { throw new Error("Prompt Management feature is not enabled. Please enable it in the configuration."); } await this.sync; let versionAndRules = await this.getAllPromptsFromCache(); if (versionAndRules === null || versionAndRules.length === 0) { // We will try to get all prompts from server (if something has gone wrong with initialization) await this.syncEntities(); versionAndRules = await this.getAllPromptsFromCache(); } if (!versionAndRules) { throw new Error(`No active deployments found for any prompt`); } let prompts = versionAndRules .filter((v) => { if (Object.keys(rule.scopes).length === 0) { return true; } if (rule.scopes["folder"]) { return v.folderId === rule.scopes["folder"]; } return true; }) .map((v) => this.getPromptVersionForRule(v, rule)) .filter((p) => p !== undefined); if (prompts.length === 0) { throw new Error(`No active deployments found for any prompt`); } return prompts; } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching prompts: ${err instanceof Error ? err.message : err}`); return 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); */ async getPromptChain(promptChainId, rule) { try { if (!this.isPromptManagementEnabled) { throw new Error("Prompt Management feature is not enabled. Please enable it in the configuration."); } await this.sync; const key = this.getCacheKey(EntityType.PROMPT_CHAIN, promptChainId); let versionAndRules = await this.getPromptChainFromCache(key); if (versionAndRules === null) { versionAndRules = await this.APIService.promptChain.getPromptChain(promptChainId); if (versionAndRules.versions.length === 0) { throw new Error(`No active deployments found for Prompt Chain ${promptChainId}`); } await this.cache.set(promptChainId, JSON.stringify(versionAndRules)); } if (!versionAndRules) { throw new Error(`No active deployments found for Prompt Chain ${promptChainId}`); } const promptChain = this.getPromptChainVersionForRule(versionAndRules, rule); if (!promptChain) { throw new Error(`No active deployments found for Prompt Chain ${promptChainId}`); } return promptChain; } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching prompt chain: ${err instanceof Error ? err.message : err}`); return 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); */ async getPromptChains(rule) { try { if (!this.isPromptManagementEnabled) { throw new Error("Prompt Management feature is not enabled. Please enable it in the configuration."); } await this.sync; let versionAndRules = await this.getAllPromptChainsFromCache(); if (versionAndRules === null || versionAndRules.length === 0) { // We will try to get all prompts from server (if something has gone wrong with initialization) await this.syncEntities(); versionAndRules = await this.getAllPromptChainsFromCache(); } if (!versionAndRules) { throw new Error(`No active deployments found for any prompt chain`); } let promptChains = versionAndRules .filter((v) => { if (Object.keys(rule.scopes).length === 0) { return true; } if (rule.scopes["folder"]) { return v.folderId === rule.scopes["folder"]; } return true; }) .map((v) => this.getPromptChainVersionForRule(v, rule)) .filter((p) => p !== undefined); if (promptChains.length === 0) { throw new Error(`No active deployments found for any prompt chain`); } return promptChains; } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching prompt chains: ${err instanceof Error ? err.message : err}`); return 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"); */ async getFolderById(folderId) { try { if (!this.isPromptManagementEnabled) { throw new Error("Prompt Management feature is not enabled. Please enable it in the configuration."); } await this.sync; const key = this.getCacheKey(EntityType.FOLDER, folderId); let folder = await this.getFolderFromCache(key); if (folder === null) { folder = await this.APIService.folder.getFolder(folderId); if (!folder) { throw new Error(`No folder found with id ${folderId}`); } await this.cache.set(key, JSON.stringify(folder)); } return folder; } catch (err) { if (this._raiseExceptions) { throw err; } else { console.error(`[Maxim-SDK] Error while fetching folder by id: ${err instanceof Error ? err.message : err}`); return undefined; } } } /** * This method is used to get all folders that match the query rule * @async