UNPKG

@artinet/sdk

Version:

A TypeScript SDK for building collaborative AI agents.

108 lines (107 loc) 3.26 kB
/** * 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;