@olakai/sdk
Version:
This document demonstrates how to use the Olakai SDK with all its features.
262 lines • 11.3 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.addMiddleware = addMiddleware;
exports.removeMiddleware = removeMiddleware;
exports.monitor = monitor;
const client_1 = require("./client");
const utils_1 = require("./utils");
const exceptions_1 = require("./exceptions");
const middleware_1 = require("./middleware");
// Global middleware registry
const middlewares = [];
/**
* Add a middleware to the global middleware registry
* @param middleware - The middleware to add. See exports from ./middleware/index.ts for available middlewares
*/
function addMiddleware(middleware) {
middlewares.push(middleware);
}
/**
* Remove a middleware from the global middleware registry
* @param name - The name of the middleware to remove
*/
function removeMiddleware(name) {
const index = middlewares.findIndex((m) => m.name === name);
if (index > -1) {
middlewares.splice(index, 1);
}
}
async function shouldAllowCall(options, args) {
try {
const { chatId, email } = resolveIdentifiers(options, args);
// Create control payload
const payload = {
prompt: (0, utils_1.toJsonValue)(args.length === 1 ? args[0] : args),
chatId: chatId,
task: options.task,
subTask: options.subTask,
tokens: 0,
email: email,
overrideControlCriteria: options.askOverride,
};
// Send control request
const response = await (0, client_1.sendToAPI)(payload, "control");
(0, utils_1.olakaiLogger)(`Control response: ${JSON.stringify(response)}`, "info");
// If not allowed, handle the blocking
if (!response.allowed) {
return response;
}
return response;
}
catch (error) {
(0, utils_1.olakaiLogger)(`Control call failed, disallowing execution ${error}`, "error");
return {
allowed: false,
details: {
detectedSensitivity: [],
isAllowedPersona: false,
},
};
}
}
/**
* Resolve dynamic chatId and userId from options
* @param options - Monitor options
* @param args - Function arguments
* @returns Object with resolved chatId and userId
*/
function resolveIdentifiers(options, args) {
let chatId = "123";
let email = "anonymous@olakai.ai";
if (typeof options.chatId === "function") {
try {
chatId = options.chatId(args);
(0, utils_1.olakaiLogger)("ChatId resolved...", "info");
}
catch (error) {
(0, utils_1.olakaiLogger)(`Error during chatId resolution: ${error}. \n Continuing execution...`, "error");
}
}
else {
chatId = options.chatId || "123";
}
if (typeof options.email === "function") {
try {
email = options.email(args);
(0, utils_1.olakaiLogger)("Email resolved...", "info");
}
catch (error) {
(0, utils_1.olakaiLogger)(`Error during userId resolution: ${error}. \n Continuing execution...`, "error");
}
}
else {
email = options.email || "anonymous@olakai.ai";
}
return { chatId, email };
}
// Implementation
function monitor(arg1, arg2) {
if (typeof arg1 === "function" && arg2) {
// Direct form: monitor(fn, options)
const fn = arg1;
const options = arg2;
return monitor(options)(fn);
}
// Curried form: monitor(options)(fn)
const options = arg1;
return (fn) => {
return async (...args) => {
(0, utils_1.olakaiLogger)(`Monitoring function: ${fn.name}`, "info");
(0, utils_1.olakaiLogger)(`Monitoring options: ${JSON.stringify(options)}`, "info");
(0, utils_1.olakaiLogger)(`Monitoring arguments: ${JSON.stringify(args)}`, "info");
let config;
let start;
let processedArgs = args;
// Safely initialize monitoring data
try {
config = (0, client_1.getConfig)();
start = Date.now();
}
catch (error) {
(0, utils_1.olakaiLogger)(`Monitoring initialization failed: \n${error}`, "error");
// If monitoring setup fails, still execute the function
const result = await Promise.resolve(fn(...args));
return result;
}
(0, utils_1.olakaiLogger)("Monitoring initialization completed...", "info");
(0, utils_1.olakaiLogger)("Checking if we should control this call...", "info");
const shouldAllow = await shouldAllowCall(options, args);
(0, utils_1.olakaiLogger)("Should control check completed...", "info");
//If we should control (block execution), throw an error
if (!shouldAllow.allowed) {
(0, utils_1.olakaiLogger)("Function execution blocked by Olakai's Control API", "error");
const { chatId, email } = resolveIdentifiers(options, args);
const payload = {
prompt: (0, utils_1.toJsonValue)(args.length === 1 ? args[0] : args, false),
response: "",
chatId: chatId,
email: email,
task: options.task,
subTask: options.subTask,
blocked: true,
tokens: 0,
sensitivity: shouldAllow.details.detectedSensitivity,
};
(0, client_1.sendToAPI)(payload, "monitoring", {
retries: config.retries,
timeout: config.timeout,
priority: "high", // Errors always get high priority
});
throw new exceptions_1.OlakaiBlockedError("Function execution blocked by Olakai's Control API", shouldAllow.details);
}
(0, utils_1.olakaiLogger)("Applying beforeCall middleware...", "info");
try {
processedArgs = await (0, middleware_1.applyMiddleware)(middlewares, processedArgs, "beforeCall");
}
catch (error) {
(0, utils_1.olakaiLogger)(`BeforeCall middleware failed: ${error}. \n Continuing execution...`, "error");
}
(0, utils_1.olakaiLogger)("BeforeCall middleware completed...", "info");
let result;
(0, utils_1.olakaiLogger)("Executing the original function...", "info");
try {
// Handle both sync and async functions uniformly
const functionResult = fn(...processedArgs);
result = await Promise.resolve(functionResult);
(0, utils_1.olakaiLogger)("Original function executed successfully...", "info");
}
catch (error) {
(0, utils_1.olakaiLogger)(`Original function failed: ${error}. \n Continuing execution...`, "error");
// Handle error case monitoring
reportError(error, processedArgs, options, config, shouldAllow.details.detectedSensitivity);
throw error; // Re-throw the original error to be handled by the caller
}
// Handle success case asynchronously
makeMonitoringCall(result, processedArgs, args, options, shouldAllow.details.detectedSensitivity, config, start);
return result; // We know result is defined if we get here (no function error)
};
};
}
/**
* Make the monitoring call
* @param result - The result of the monitored function
* @param processedArgs - The processed arguments
* @param args - The original arguments
* @param options - The options for the monitored function
* @param config - The configuration for the monitored function
* @param start - The start time of the monitored function
*/
async function makeMonitoringCall(result, processedArgs, args, options, detectedSensitivity, config, start) {
let processedResult = result;
try {
(0, utils_1.olakaiLogger)("Applying afterCall middleware...", "info");
processedResult = await (0, middleware_1.applyMiddleware)(middlewares, processedArgs, "afterCall", result);
}
catch (error) {
(0, utils_1.olakaiLogger)(`Error during afterCall middleware: ${error}. \n Continuing execution...`, "error");
}
(0, utils_1.olakaiLogger)("AfterCall middleware completed...", "info");
(0, utils_1.olakaiLogger)("Resolving identifiers...", "info");
const { chatId, email } = resolveIdentifiers(options, args);
(0, utils_1.olakaiLogger)("Creating payload...", "info");
const payload = {
prompt: (0, utils_1.toJsonValue)(processedArgs, options.sanitize),
response: (0, utils_1.toJsonValue)(processedResult, options.sanitize),
chatId: chatId,
email: email,
tokens: 0,
requestTime: Number(Date.now() - start),
...((options.task !== undefined && options.task !== "") ? { task: options.task } : {}),
...((options.subTask !== undefined && options.subTask !== "") ? { subTask: options.subTask } : {}),
blocked: false,
sensitivity: detectedSensitivity,
};
(0, utils_1.olakaiLogger)(`Successfully defined payload: ${JSON.stringify(payload)}`, "info");
// Send to API (with batching and retry logic handled in client)
try {
await (0, client_1.sendToAPI)(payload, "monitoring", {
retries: config.retries,
timeout: config.timeout,
priority: options.priority || "normal",
});
}
catch (error) {
(0, utils_1.olakaiLogger)(`Error during api call: ${error}.`, "error");
}
(0, utils_1.olakaiLogger)("API call completed...", "info");
//End of monitoring operations
(0, utils_1.olakaiLogger)("Monitoring operations completed...", "info");
}
/**
* Report an error to the API
* @param functionError - The error from the monitored function
* @param args - The original arguments
* @param options - The options for the monitored function
* @param config - The configuration for the monitored function
*/
async function reportError(functionError, args, options, config, detectedSensitivity) {
if (options.onMonitoredFunctionError ?? true) {
try {
const errorInfo = (0, utils_1.createErrorInfo)(functionError);
const { chatId, email } = resolveIdentifiers(options, args);
const payload = {
prompt: "",
response: "",
errorMessage: errorInfo.errorMessage + (errorInfo.stackTrace ? `\n${errorInfo.stackTrace}` : ""),
chatId: chatId,
email: email,
sensitivity: detectedSensitivity,
};
await (0, client_1.sendToAPI)(payload, "monitoring", {
retries: config.retries,
timeout: config.timeout,
priority: "high", // Errors always get high priority
});
}
catch (error) {
(0, utils_1.olakaiLogger)(`Error during error monitoring: ${error}.`, "error");
}
(0, utils_1.olakaiLogger)("Error monitoring completed...", "info");
}
}
//# sourceMappingURL=monitor.js.map