@pompeii-labs/pompeii
Version:
The Pompeii Platform SDK from Pompeii Labs
574 lines (567 loc) • 19.5 kB
JavaScript
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 };