@artinet/sdk
Version:
A TypeScript SDK for building collaborative AI agents.
108 lines (107 loc) • 3.26 kB
JavaScript
/**
* Copyright 2025 The Artinet Project
* SPDX-License-Identifier: Apache-2.0
*/
import { logger } from "../../config/index.js";
//TODO: Turn Manager into an LRU cache.
//TODO: Consider warning when size exceeds a certain threshold.
export class Manager {
_cache;
throwOnSet;
storage;
constructor(_cache = new Map(), throwOnSet = true, storage) {
this._cache = _cache;
this.throwOnSet = throwOnSet;
this.storage = storage;
//TODO: consider async initialization of storage/lazy loading of cold data (to an upper-bound)
}
get cache() {
return this._cache;
}
/**
* @deprecated use cache instead
* @note removing in v0.7
*/
get data() {
return this.cache;
}
async set(id, data) {
logger.debug(`${this.constructor.name}[set]:`, { id });
if (!data && this.throwOnSet) {
throw new Error('Data is required');
}
else if (!data) {
return;
}
this.cache.set(id, data);
if (this.storage) {
await this.storage.set(id, data);
}
}
async get(id) {
let data = this.cache.get(id);
if (!data && this.storage) {
data = await this.storage.get(id);
if (data) {
this.cache.set(id, data);
}
}
return data;
}
async delete(id) {
logger.debug(`${this.constructor.name}[delete]:`, { id });
if (this.storage) {
/** Probably best to delete from storage first to avoid race conditions. */
await this.storage.delete(id);
}
this.cache.delete(id);
}
async has(id) {
if (this.cache.has(id)) {
return true;
}
if (this.storage) {
const data = await this.storage.get(id);
if (data) {
this.cache.set(id, data);
return true;
}
}
return false;
}
async list() {
const listed = Array.from(this.cache.values());
if (this.storage) {
const storedList = (await this.storage.list?.())?.filter((item) => item !== undefined && !listed.includes(item));
/** Could be an expensive operation */
listed.push(...(storedList ?? []));
}
return listed;
}
async search(query, filter) {
if (!filter && !this.storage) {
const data = this.cache.get(query);
if (data) {
return [data];
}
return [];
}
const results = [];
if (filter) {
for (const item of this.cache.values()) {
if (await filter(item)) {
results.push(item);
}
}
}
if (this.storage) {
const storageFilter = async (item) => {
return ((await filter?.(item)) ?? true) && !results.includes(item);
};
/**Spreads are fine for now, but a for of loop and push is safer at scale. */
results.push(...((await this.storage.search?.(query, storageFilter)) ?? []));
}
return results;
}
}
export const ResourceManager = Manager;