UNPKG

@pompeii-labs/pompeii

Version:

The Pompeii Platform SDK from Pompeii Labs

574 lines (567 loc) 19.5 kB
import dotenv from 'dotenv'; import fs from 'fs'; import path from 'path'; var __create = Object.create; var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropNames = Object.getOwnPropertyNames; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); var __objRest = (source, exclude) => { var target = {}; for (var prop in source) if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0) target[prop] = source[prop]; if (source != null && __getOwnPropSymbols) for (var prop of __getOwnPropSymbols(source)) { if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop)) target[prop] = source[prop]; } return target; }; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __async = (__this, __arguments, generator) => { return new Promise((resolve, reject) => { var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }; var rejected = (value) => { try { step(generator.throw(value)); } catch (e) { reject(e); } }; var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected); step((generator = generator.apply(__this, __arguments)).next()); }); }; // node_modules/@pompeii-labs/magma/dist/types/index.js var require_types = __commonJS({ "node_modules/@pompeii-labs/magma/dist/types/index.js"(exports) { var __defProp2 = Object.defineProperty; var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __name = (target, value) => __defProp2(target, "name", { value, configurable: true }); var __publicField = (obj, key, value) => __defNormalProp2(obj, typeof key !== "symbol" ? key + "" : key, value); var _MagmaMessage = class _MagmaMessage { constructor({ role, content, blocks, id }) { __publicField(this, "id"); __publicField(this, "role"); __publicField(this, "blocks", []); this.id = id; this.role = role; if (blocks) { this.blocks = blocks; } else if (content !== void 0 && content !== null) { this.blocks = [ { type: "text", text: content } ]; } } getText() { return this.blocks.filter((block) => block.type === "text").map((block) => block.text).join("\n"); } getToolCalls() { return this.blocks.filter((block) => block.type === "tool_call").map((block) => block.tool_call); } getToolResults() { return this.blocks.filter((block) => block.type === "tool_result").map((block) => block.tool_result); } getReasoning() { return this.blocks.filter((block) => block.type === "reasoning").filter((block) => !block.redacted).map((block) => block.reasoning).join("\n"); } getImages() { return this.blocks.filter((block) => block.type === "image").map((block) => block.image); } get content() { return this.getText(); } }; __name(_MagmaMessage, "MagmaMessage"); var MagmaMessage3 = _MagmaMessage; var _MagmaUserMessage = class _MagmaUserMessage extends MagmaMessage3 { constructor(magmaUserMessage) { super(magmaUserMessage); __publicField(this, "role", "user"); } }; __name(_MagmaUserMessage, "MagmaUserMessage"); var MagmaUserMessage = _MagmaUserMessage; var _MagmaAssistantMessage = class _MagmaAssistantMessage extends MagmaMessage3 { constructor(magmaAssistantMessage) { super(magmaAssistantMessage); __publicField(this, "role", "assistant"); } }; __name(_MagmaAssistantMessage, "MagmaAssistantMessage"); var MagmaAssistantMessage = _MagmaAssistantMessage; var _MagmaSystemMessage = class _MagmaSystemMessage extends MagmaMessage3 { constructor(magmaSystemMessage) { super(magmaSystemMessage); __publicField(this, "role", "system"); this.blocks.forEach((block) => { var _a; block.cache = (_a = block.cache) != null ? _a : magmaSystemMessage.cache; }); } }; __name(_MagmaSystemMessage, "MagmaSystemMessage"); var MagmaSystemMessage = _MagmaSystemMessage; var MagmaProviders = [ "openai", "anthropic", "groq", "google" ]; var MagmaMiddlewareTriggers = [ "onCompletion", "preCompletion", "onToolExecution", "preToolExecution", "onMainFinish" ]; exports.MagmaAssistantMessage = MagmaAssistantMessage; exports.MagmaMessage = MagmaMessage3; exports.MagmaMiddlewareTriggers = MagmaMiddlewareTriggers; exports.MagmaProviders = MagmaProviders; exports.MagmaSystemMessage = MagmaSystemMessage; exports.MagmaUserMessage = MagmaUserMessage; } }); // src/acp.ts var import_types = __toESM(require_types()); var ACPAgent = class { constructor(acpAgent) { this.id = acpAgent.id; this.name = acpAgent.name; this.status = acpAgent.status; this.endpoint = acpAgent.endpoint; this.templateId = acpAgent.templateId; this.summary = acpAgent.summary; this.apiKey = acpAgent.apiKey; } /** * Send a chat request to the ACP agent * * @param request The chat request to send to the ACP agent * @param onChunk Optional callback function for streaming SSE data * @returns The response message from the ACP agent */ chat(request) { return __async(this, null, function* () { const _a = request, { cb } = _a, rest = __objRest(_a, ["cb"]); const endpoint3 = this.endpoint || "https://api.magmadeploy.com/v1"; let response; try { response = yield fetch(`${endpoint3}/chat`, { method: "POST", headers: { "Content-Type": "application/json", "x-api-key": this.apiKey }, body: JSON.stringify(rest) }); } catch (error) { throw new Error( "Failed to chat with ACP agent. Please check your API key and try again." ); } if (!response.ok) throw yield response.json(); const contentType = response.headers.get("content-type") || ""; let messageType; if (contentType.includes("text/event-stream")) { messageType = yield this.handleSSEResponse(response, cb); } else { messageType = yield response.json(); } return new import_types.MagmaMessage(messageType); }); } /** * Handle Server-Sent Events response stream * * @param response The fetch response object * @param onChunk Optional callback for each data chunk * @returns The final message result */ handleSSEResponse(response, cb) { return __async(this, null, function* () { var _a; const reader = (_a = response.body) == null ? void 0 : _a.getReader(); if (!reader) { throw new Error("Unable to read SSE response stream"); } const decoder = new TextDecoder(); let buffer = ""; let finalResult = null; try { while (true) { const { done, value } = yield reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split("\n"); buffer = lines.pop() || ""; for (const line of lines) { if (line.startsWith("data: ")) { try { const cleaned = line.slice(6).trim(); const jsonData = JSON.parse(cleaned); cb == null ? void 0 : cb(jsonData); if (["magma.message", "magma.trace"].includes(jsonData.type) && jsonData.data !== void 0 && jsonData.data !== null) { finalResult = jsonData.data; } } catch (parseError) { continue; } } else if (line.trim() === "") { continue; } } } } finally { reader.releaseLock(); } if (!finalResult) { throw new Error("No message received from agent"); } return finalResult; }); } request(path2, options, cb) { return __async(this, null, function* () { if (!this.endpoint) { throw new Error(`ACPAgent.request() can only be used from a deployed agent`); } let response; try { response = yield fetch(`${this.endpoint}/${path2}`, options); } catch (error) { throw new Error( "Failed to make request to ACP agent. Please check your API key and try again." ); } if (!response.ok) throw yield response.json(); const contentType = response.headers.get("content-type") || ""; if (contentType.includes("text/event-stream")) { return yield this.handleSSEResponse(response, cb); } return yield response.json(); }); } }; // src/inference.ts var import_types2 = __toESM(require_types()); var endpoint = "https://api.magmadeploy.com/v1"; var Inference = class { constructor(apiKey) { if (!apiKey) { throw new Error("POMPEII_API_KEY is not set"); } this.apiKey = apiKey; } /** * List all inference agents * * @returns list of inference agents */ list() { return __async(this, null, function* () { let response; try { response = yield fetch(endpoint + "/inference", { method: "GET", headers: { "x-api-key": this.apiKey } }); } catch (error) { throw new Error("Failed to list agents. Please check your API key and try again."); } if (!response.ok) { throw yield response.json(); } return yield response.json(); }); } run(request) { return __async(this, null, function* () { const _a = request, { cb } = _a, rest = __objRest(_a, ["cb"]); let response; try { response = yield fetch(`${endpoint}/inference`, { method: "POST", headers: { "Content-Type": "application/json", "x-api-key": this.apiKey }, body: JSON.stringify(rest) }); } catch (error) { throw new Error("Failed to run inference. Please check your API key and try again."); } if (!response.ok) throw yield response.json(); const contentType = response.headers.get("content-type") || ""; let messageType; if (contentType.includes("text/event-stream")) { messageType = yield this.handleSSEResponse(response, cb); } else { messageType = yield response.json(); } return new import_types2.MagmaMessage(messageType); }); } /** * Handle Server-Sent Events response stream * * @param response The fetch response object * @param onChunk Optional callback for each data chunk * @returns The final message result */ handleSSEResponse(response, cb) { return __async(this, null, function* () { var _a; const reader = (_a = response.body) == null ? void 0 : _a.getReader(); if (!reader) { throw new Error("Unable to read SSE response stream"); } const decoder = new TextDecoder(); let buffer = ""; let finalResult = null; try { while (true) { const { done, value } = yield reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); const lines = buffer.split("\n"); buffer = lines.pop() || ""; for (const line of lines) { if (line.startsWith("data: ")) { try { const cleaned = line.slice(6).trim(); const jsonData = JSON.parse(cleaned); cb == null ? void 0 : cb(jsonData); if (["magma.message", "magma.trace"].includes(jsonData.type) && jsonData.data !== void 0 && jsonData.data !== null) { finalResult = jsonData.data; } } catch (parseError) { continue; } } else if (line.trim() === "") { continue; } } } } finally { reader.releaseLock(); } if (!finalResult) { throw new Error("No message received from agent"); } return finalResult; }); } }; // src/client.ts dotenv.config(); var endpoint2 = "https://api.magmadeploy.com/v1"; var Pompeii = class { constructor(apiKey = ((_a) => (_a = process.env.POMPEII_API_KEY) != null ? _a : "")()) { if (!apiKey) { throw new Error("POMPEII_API_KEY is not set"); } this.apiKey = apiKey; this.inference = new Inference(apiKey); } /** * Make a request to the Pompeii Platform API * * @param route The route to make the request to * @param args The arguments to pass to the request * @returns The response from the request */ request(_0) { return __async(this, arguments, function* (route, args = {}) { const requestArgs = __spreadProps(__spreadValues({}, args), { headers: __spreadValues({ "x-api-key": this.apiKey, "Content-Type": "application/json" }, (args == null ? void 0 : args.headers) || {}) }); if (this.apiKey.startsWith("magma_test")) { console.log(requestArgs.method, `${endpoint2}${route}`); console.log("Headers:", JSON.stringify(requestArgs.headers, null, 2)); if (requestArgs.body) { console.log( "Body:", JSON.stringify(JSON.parse(requestArgs.body), null, 2) ); } return new Response("OK"); } return yield fetch(`${endpoint2}${route}`, requestArgs); }); } /** * List all available ACP agents * * @returns A list of ACP agents * @throws Error if the request fails */ acp() { return __async(this, null, function* () { try { const response = yield this.request("/acp", { method: "GET" }); if (!response.ok) throw yield response.json(); const acpAgents = yield response.json(); return acpAgents.map((acpAgent) => new ACPAgent(__spreadProps(__spreadValues({}, acpAgent), { apiKey: this.apiKey }))); } catch (error) { return []; } }); } /** * Post a notification to the Pompeii Platform. This will be displayed to applicable users on their home page. * * @param notification The notification to post * @returns void * @throws Error if the request fails */ notify(notification) { return __async(this, null, function* () { try { const response = yield this.request("/notifications", { method: "POST", body: JSON.stringify(notification) }); if (!response.ok) throw yield response.json(); } catch (error) { console.error( "Failed to post notification:", error instanceof Error ? error.message : error ); } }); } /** * Post an event to the Pompeii Platform. This will be displayed in the Agent's Observability tab. * * @param event The event to post * @returns void * @throws Error if the request fails */ event(event) { return __async(this, null, function* () { try { const response = yield this.request("/events", { method: "POST", body: JSON.stringify(event) }); if (!response.ok) throw yield response.json(); } catch (error) { console.error("Failed to post event:", error instanceof Error ? error.message : error); } }); } downloadFiles(_0) { return __async(this, arguments, function* (targetDir, paths = []) { try { const searchParams = new URLSearchParams(); for (const path2 of paths) { searchParams.append("paths", path2); } const response = yield this.request(`/storage?${searchParams.toString()}`, { method: "GET", headers: { Accept: "application/json" } }); if (!response.ok) throw yield response.json(); const files = yield response.json(); const filePaths = []; for (const file of files) { if (file.error) { console.warn(`Error fetching file ${file.name}: ${file.error}`); continue; } const filePath = yield this.downloadFile(file.url, file.name, targetDir); if (filePath) { filePaths.push(filePath); } } return filePaths; } catch (error) { console.error("Failed to list files:", error instanceof Error ? error.message : error); return []; } }); } downloadFile(url, filename, downloadDir) { return __async(this, null, function* () { try { if (!fs.existsSync(downloadDir)) { fs.mkdirSync(downloadDir, { recursive: true }); } const response = yield fetch(url); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const arrayBuffer = yield response.arrayBuffer(); const buffer = Buffer.from(arrayBuffer); const filepath = path.join(downloadDir, filename); fs.writeFileSync(filepath, buffer); return filepath; } catch (error) { console.error( `Error downloading ${filename}:`, error instanceof Error ? error.message : error ); return null; } }); } }; export { ACPAgent, Pompeii };