Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@bluexlab/maos-ts

Package Overview
Dependencies
Maintainers
0
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@bluexlab/maos-ts - npm Package Compare versions

Comparing version 0.0.3 to 0.0.4

43

dist/index.d.ts

@@ -0,3 +1,3 @@

import { Level, Logger } from 'pino';
import { ResultAsync } from 'neverthrow';
import { Level } from 'pino';

@@ -11,2 +11,6 @@ interface MaosConfig {

}
interface MaosClientConfig {
apiKey: string;
coreUrl: string;
}
interface MaosResponse {

@@ -23,3 +27,10 @@ [key: string]: object;

}
type HandlerInputType = Record<string, unknown>;
interface HandlerContext {
logger: Logger;
meta: InvocationMetaType;
}
interface HandlerInputType {
context: HandlerContext;
payload: Record<string, unknown>;
}
type HandlerResultType = ResultAsync<Record<string, unknown>, Error>;

@@ -39,17 +50,33 @@ type HandlerType = (input: HandlerInputType) => HandlerResultType;

private abortController;
private abortSignal;
constructor(config?: MaosConfig);
getConfig(): ResultAsync<MaosResponse, Error>;
getLogger(): Logger;
on(methodName: string, handler: HandlerType): Maos;
shutdown(): void;
run(): Promise<void>;
private fetchWithAuth;
private postWithAuth;
getConfig(): ResultAsync<MaosResponse, Error>;
private getNextInvocation;
private respondToInvocation;
on(methodName: string, handler: HandlerType): Maos;
private getHandler;
private handleInvocation;
private worker;
shutdown(): void;
run(): Promise<void>;
}
export { type HandlerInputType, type HandlerResultType, type HandlerType, type Invocation, type InvocationMetaType, Maos, type MaosConfig, type MaosResponse };
declare class MaosClient {
private apiKey;
private coreUrl;
constructor(config: MaosClientConfig);
execute(agent: string, kind: string, input: Record<string, unknown>, wait?: number): ResultAsync<MaosResponse, Error>;
executeAsync(agent: string, kind: string, input: Record<string, unknown>): ResultAsync<MaosAsyncResponder, Error>;
private fetchWithAuth;
private getInvocationResult;
}
declare class MaosAsyncResponder {
private readonly fetcher;
private readonly id;
constructor(fetcher: (endpoint: string) => ResultAsync<MaosResponse, unknown>, id: string);
getResult(wait?: number): ResultAsync<MaosResponse, Error>;
}
export { type HandlerContext, type HandlerInputType, type HandlerResultType, type HandlerType, type Invocation, type InvocationMetaType, Maos, MaosClient, type MaosClientConfig, type MaosConfig, type MaosResponse };

210

dist/index.js

@@ -38,10 +38,7 @@ // src/maos.ts

}
}), (err2) => err2);
}), (err3) => err3);
}
function joinUrl(base, ...parts) {
function joinUrl(base, part) {
const url = new URL(base);
parts.forEach((part) => {
url.pathname = new URL(part, url).pathname;
});
return url.toString();
return new URL(part, url).toString();
}

@@ -59,2 +56,8 @@ function jsonValueConverter(key, value) {

};
var AbortedError = class extends Error {
constructor() {
super("Aborted");
this.name = "Aborted";
}
};
var Maos = class {

@@ -73,4 +76,3 @@ // configs

logger;
abortController;
abortSignal;
abortController = null;
constructor(config = {}) {

@@ -89,6 +91,27 @@ this.apiKey = config.apiKey || process.env.APIKEY || "";

this.handlers = /* @__PURE__ */ new Map();
this.logger = pino({ level: this.logLevel });
this.abortController = new AbortController();
this.abortSignal = this.abortController.signal;
this.logger = createLogger(this.logLevel);
}
getConfig() {
return this.fetchWithAuth("/v1/config").mapErr((err3) => err3 instanceof Error ? err3 : new Error(String(err3)));
}
getLogger() {
return this.logger;
}
// Register a handler for a method name
on(methodName, handler) {
if (this.handlers.has(methodName)) {
throw new Error(`Handler already registered with method name: ${methodName}`);
}
this.handlers.set(methodName, handler);
return this;
}
shutdown() {
this.abortController?.abort();
this.shouldRun = false;
}
async run() {
process.on("SIGTERM", () => this.shutdown());
process.on("SIGINT", () => this.shutdown());
await Promise.all(Array.from({ length: this.concurrentInvocationNum }, () => this.worker()));
}
fetchWithAuth(endpoint, options = {}, allowAbort = false) {

@@ -101,6 +124,7 @@ const url = joinUrl(this.coreUrl, endpoint);

});
const fetchPromise = fetch(url, { ...options, headers, signal: allowAbort ? this.abortSignal : void 0 });
const abortSignal = this.abortController?.signal;
const fetchPromise = fetch(url, { ...options, headers, signal: allowAbort ? abortSignal : void 0 });
if (!fetchPromise)
return errAsync(new NotFoundError());
return ResultAsync2.fromPromise(fetchPromise, (err2) => err2).andThen((res) => {
return ResultAsync2.fromPromise(fetchPromise, (err3) => err3).andThen((res) => {
if (!res)

@@ -114,4 +138,4 @@ return err(new Error("No response"));

return ok(res);
}).andThen((res) => ResultAsync2.fromPromise(res.text(), (err2) => err2).map((body) => ({ res, body }))).andThen(({ res, body }) => {
this.logger.info(`Response status: ${res.status}, ${res.statusText} body: ${body}`);
}).andThen((res) => ResultAsync2.fromPromise(res.text(), (err3) => err3).map((body) => ({ res, body }))).andThen(({ res, body }) => {
this.logger.debug(`Response status: ${res.status}, ${res.statusText} body: ${body}`);
if (!body)

@@ -128,28 +152,20 @@ return ok({});

}
getConfig() {
return this.fetchWithAuth("/v1/config").mapErr((err2) => err2 instanceof Error ? err2 : new Error(String(err2)));
}
getNextInvocation() {
return this.fetchWithAuth("/v1/invocations/next", void 0, true).mapErr((err2) => {
if (err2 instanceof NotFoundError)
return err2;
return new Error(`Failed to get next invocation: ${formatMaosError(err2)}`);
return this.fetchWithAuth("/v1/invocations/next", void 0, true).mapErr((err3) => {
if (err3 instanceof NotFoundError)
return err3;
if (err3 instanceof Error && err3.name === "AbortError") {
return new AbortedError();
}
return new Error(`Failed to get next invocation: ${formatMaosError(err3)}`);
});
}
respondToInvocation(invokeId, result) {
return result.andThen((res) => this.postWithAuth(`/v1/invocations/${invokeId}/response`, { result: res })).orElse((err2) => this.postWithAuth(`/v1/invocations/${invokeId}/error`, {
errors: { message: formatMaosError(err2) }
})).mapErr((err2) => {
this.logger.error(`Failed to respond to invocation with id ${invokeId}: ${formatMaosError(err2)}`);
return err2;
return result.andThen((res) => this.postWithAuth(`/v1/invocations/${invokeId}/response`, { result: res })).orElse((err3) => this.postWithAuth(`/v1/invocations/${invokeId}/error`, {
errors: { message: formatMaosError(err3) }
})).mapErr((err3) => {
this.logger.error(`Failed to respond to invocation with id ${invokeId}: ${formatMaosError(err3)}`);
return err3;
});
}
// Register a handler for a method name
on(methodName, handler) {
if (this.handlers.has(methodName)) {
throw new Error(`Handler already registered with method name: ${methodName}`);
}
this.handlers.set(methodName, handler);
return this;
}
getHandler(methodName) {

@@ -172,12 +188,14 @@ const handler = this.handlers.get(methodName);

const kind = meta.kind;
return this.getHandler(kind).map((handler) => ({ payload, handler }));
return this.getHandler(kind).map((handler) => ({ meta, payload, handler }));
}).andThen(
// trigger the handler within a throwable context
// even though the handler is expected not to throw, we can still catch any errors thrown
Result.fromThrowable(({ payload, handler }) => handler(payload))
Result.fromThrowable(
({ meta, payload, handler }) => handler({ context: { logger: this.logger, meta }, payload })
)
).asyncAndThen(
(result) => result.andThen((res) => this.respondToInvocation(String(id), okAsync(res)))
).mapErr(async (err2) => {
this.respondToInvocation(String(id), errAsync(err2 instanceof Error ? err2 : new Error(String(err2))));
return err2;
).mapErr(async (err3) => {
this.respondToInvocation(String(id), errAsync(err3 instanceof Error ? err3 : new Error(String(err3))));
return err3;
});

@@ -189,16 +207,21 @@ });

while (this.shouldRun) {
await this.handleInvocation().mapErr((err2) => {
if (!(err2 instanceof NotFoundError)) {
this.logger.error(`Error during worker run: ${formatMaosError(err2)}`);
this.abortController = new AbortController();
await this.handleInvocation().mapErr((err3) => {
if (err3 instanceof AbortedError) {
this.logger.info("Worker run aborted");
this.shouldRun = false;
} else if (!(err3 instanceof NotFoundError)) {
this.logger.error(`Error during worker run: ${formatMaosError(err3)}`);
}
});
if (!this.shouldRun)
break;
const timeSinceLastRun = Date.now() - lastRun;
if (timeSinceLastRun < this.minInvocationInterval) {
await sleep(this.invocationPollInterval, this.abortSignal).mapErr((err2) => {
if (err2 instanceof Error && err2.message === "Aborted") {
await sleep(this.invocationPollInterval, this.abortController.signal).mapErr((err3) => {
if (err3 instanceof Error && err3.message === "Aborted") {
this.logger.info("Worker sleep aborted");
this.shouldRun = false;
} else {
this.logger.error(`Error during worker sleep: ${formatMaosError(err2)}`);
this.logger.error(`Error during worker sleep: ${formatMaosError(err3)}`);
}

@@ -208,16 +231,95 @@ });

lastRun = Date.now();
this.abortController = null;
}
}
shutdown() {
this.abortController.abort();
this.shouldRun = false;
};
function createLogger(logLevel) {
return pino({
level: logLevel,
timestamp: () => `,"ts":${Date.now()}`,
// Use Unix timestamp in milliseconds
formatters: {
level: (label) => {
return { level: label.toUpperCase() };
}
},
// Customize the output
base: void 0,
// Remove the default 'pid' and 'hostname' fields
messageKey: "msg"
// Set the key for the 'message' field in the output
});
}
// src/maos-client.ts
import { ResultAsync as ResultAsync3, err as err2, ok as ok2 } from "neverthrow";
var MaosClient = class {
apiKey;
coreUrl;
constructor(config) {
this.apiKey = config.apiKey;
this.coreUrl = config.coreUrl;
}
async run() {
process.on("SIGTERM", () => this.shutdown());
process.on("SIGINT", () => this.shutdown());
await Promise.all(Array.from({ length: this.concurrentInvocationNum }, () => this.worker()));
execute(agent, kind, input, wait) {
const path = `/v1/invocations/sync${wait ? `?wait=${wait}` : ""}`;
return this.fetchWithAuth(
path,
{ method: "POST", body: JSON.stringify({ agent, meta: { kind }, payload: input }) }
).mapErr((err3) => err3 instanceof Error ? err3 : new Error(String(err3)));
}
executeAsync(agent, kind, input) {
return this.fetchWithAuth("/v1/invocations/async", {
method: "POST",
body: JSON.stringify({ agent, meta: { kind }, payload: input })
}).andThen((res) => {
if (!res || !res.id || typeof res.id !== "string") {
return err2(new Error("Missing invocation id from MAOS"));
}
return ok2(res.id);
}).map((id) => new MaosAsyncResponder((url) => this.fetchWithAuth(url), id)).mapErr((err3) => err3 instanceof Error ? err3 : new Error(String(err3)));
}
fetchWithAuth(endpoint, options = {}) {
const url = joinUrl(this.coreUrl, endpoint);
const headers = new Headers({
"Authorization": `Bearer ${this.apiKey}`,
"Content-Type": "application/json",
...options.headers
});
return ResultAsync3.fromPromise(fetch(url, { ...options, headers }), (err3) => err3).andThen((res) => {
if (!res.ok) {
return err2(new Error(`HTTP error! status: ${res.status}, statusText: ${res.statusText}`));
}
return ok2(res);
}).andThen((res) => ResultAsync3.fromPromise(res.text(), (err3) => err3)).andThen((body) => {
if (!body)
return ok2({});
return ok2(JSON.parse(body));
});
}
getInvocationResult(id) {
return this.fetchWithAuth(`/v1/invocations/${id}`).andThen((res) => {
if (!res || !res.status || typeof res.status !== "string") {
return err2(new Error("Missing status from MAOS"));
}
if (res.status === "completed" || res.status === "discarded") {
return ok2(String(res.result));
}
return this.getInvocationResult(id);
});
}
};
var MaosAsyncResponder = class {
fetcher;
id;
constructor(fetcher, id) {
this.fetcher = fetcher;
this.id = id;
}
getResult(wait) {
return this.fetcher(`/v1/invocations/${this.id}${wait ? `?wait=${wait}` : ""}`).mapErr((err3) => err3 instanceof Error ? err3 : new Error(String(err3)));
}
};
export {
Maos
Maos,
MaosClient
};
{
"name": "@bluexlab/maos-ts",
"type": "module",
"version": "0.0.3",
"version": "0.0.4",
"packageManager": "pnpm@9.5.0",

@@ -6,0 +6,0 @@ "description": "TypeScript binding of MAOS",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc