UNPKG

@mastra/core

Version:

Mastra is a framework for building AI-powered applications and agents with a modern TypeScript stack.

454 lines (449 loc) • 14.6 kB
'use strict'; var chunk3VBF5IP7_cjs = require('./chunk-3VBF5IP7.cjs'); var chunk7JE7FOGJ_cjs = require('./chunk-7JE7FOGJ.cjs'); // src/storage/domains/agents/base.ts var AgentsStorage = class extends chunk3VBF5IP7_cjs.VersionedStorageDomain { listKey = "agents"; versionMetadataFields = [ "id", "agentId", "versionNumber", "changedFields", "changeMessage", "createdAt" ]; constructor() { super({ component: "STORAGE", name: "AGENTS" }); } }; // src/storage/domains/agents/inmemory.ts var InMemoryAgentsStorage = class extends AgentsStorage { db; constructor({ db }) { super(); this.db = db; } async dangerouslyClearAll() { this.db.agents.clear(); this.db.agentVersions.clear(); } // ========================================================================== // Agent CRUD Methods // ========================================================================== async getById(id) { const agent = this.db.agents.get(id); return agent ? this.deepCopyAgent(agent) : null; } async create(input) { const { agent } = input; if (this.db.agents.has(agent.id)) { throw new Error(`Agent with id ${agent.id} already exists`); } const now = /* @__PURE__ */ new Date(); const visibility = agent.visibility ?? (agent.authorId ? "private" : void 0); const newAgent = { id: agent.id, status: "draft", activeVersionId: void 0, authorId: agent.authorId, visibility, metadata: agent.metadata, favoriteCount: 0, createdAt: now, updatedAt: now }; this.db.agents.set(agent.id, newAgent); const { id: _id, authorId: _authorId, visibility: _visibility, metadata: _metadata, ...snapshotConfig } = agent; const versionId = crypto.randomUUID(); await this.createVersion({ id: versionId, agentId: agent.id, versionNumber: 1, ...snapshotConfig, changedFields: Object.keys(snapshotConfig), changeMessage: "Initial version" }); return this.deepCopyAgent(newAgent); } async update(input) { const { id, ...updates } = input; const existingAgent = this.db.agents.get(id); if (!existingAgent) { throw new Error(`Agent with id ${id} not found`); } const { authorId, visibility, activeVersionId, metadata, status } = updates; const updatedAgent = { ...existingAgent, ...authorId !== void 0 && { authorId }, ...visibility !== void 0 && { visibility }, ...activeVersionId !== void 0 && { activeVersionId }, ...metadata !== void 0 && { metadata: { ...existingAgent.metadata, ...metadata } }, ...status !== void 0 && { status }, updatedAt: /* @__PURE__ */ new Date() }; this.db.agents.set(id, updatedAgent); return this.deepCopyAgent(updatedAgent); } async delete(id) { this.db.agents.delete(id); await this.deleteVersionsByParentId(id); } async list(args) { const { page = 0, perPage: perPageInput, orderBy, authorId, visibility, metadata, status, entityIds, pinFavoritedFor, favoritedOnly } = args || {}; const { field, direction } = this.parseOrderBy(orderBy); const perPage = chunk3VBF5IP7_cjs.normalizePerPage(perPageInput, 100); if (page < 0) { throw new Error("page must be >= 0"); } const maxOffset = Number.MAX_SAFE_INTEGER / 2; if (page * perPage > maxOffset) { throw new Error("page value too large"); } let agents = Array.from(this.db.agents.values()); if (entityIds !== void 0) { if (entityIds.length === 0) { return { agents: [], total: 0, page, perPage: perPageInput === false ? false : perPage, hasMore: false }; } const idSet = new Set(entityIds); agents = agents.filter((agent) => idSet.has(agent.id)); } if (status) { agents = agents.filter((agent) => agent.status === status); } if (authorId !== void 0) { agents = agents.filter((agent) => agent.authorId === authorId); } if (visibility !== void 0) { agents = agents.filter((agent) => agent.visibility === visibility); } if (metadata && Object.keys(metadata).length > 0) { agents = agents.filter((agent) => { if (!agent.metadata) return false; return Object.entries(metadata).every(([key, value]) => chunk7JE7FOGJ_cjs.deepEqual(agent.metadata[key], value)); }); } const favoritedIds = pinFavoritedFor ? this.collectFavoritedIdsFor(pinFavoritedFor) : void 0; if (favoritedOnly) { if (favoritedIds) { agents = agents.filter((agent) => favoritedIds.has(agent.id)); } else { agents = []; } } const sortedAgents = this.sortAgents(agents, field, direction, favoritedIds); const clonedAgents = sortedAgents.map((agent) => this.deepCopyAgent(agent)); const { offset, perPage: perPageForResponse } = chunk3VBF5IP7_cjs.calculatePagination(page, perPageInput, perPage); return { agents: clonedAgents.slice(offset, offset + perPage), total: clonedAgents.length, page, perPage: perPageForResponse, hasMore: offset + perPage < clonedAgents.length }; } // ========================================================================== // Agent Version Methods // ========================================================================== async createVersion(input) { if (this.db.agentVersions.has(input.id)) { throw new Error(`Version with id ${input.id} already exists`); } for (const version2 of this.db.agentVersions.values()) { if (version2.agentId === input.agentId && version2.versionNumber === input.versionNumber) { throw new Error(`Version number ${input.versionNumber} already exists for agent ${input.agentId}`); } } const version = { ...input, createdAt: /* @__PURE__ */ new Date() }; this.db.agentVersions.set(input.id, this.deepCopyVersion(version)); return this.deepCopyVersion(version); } async getVersion(id) { const version = this.db.agentVersions.get(id); return version ? this.deepCopyVersion(version) : null; } async getVersionByNumber(agentId, versionNumber) { for (const version of this.db.agentVersions.values()) { if (version.agentId === agentId && version.versionNumber === versionNumber) { return this.deepCopyVersion(version); } } return null; } async getLatestVersion(agentId) { let latest = null; for (const version of this.db.agentVersions.values()) { if (version.agentId === agentId) { if (!latest || version.versionNumber > latest.versionNumber) { latest = version; } } } return latest ? this.deepCopyVersion(latest) : null; } async listVersions(input) { const { agentId, page = 0, perPage: perPageInput, orderBy } = input; const { field, direction } = this.parseVersionOrderBy(orderBy); const perPage = chunk3VBF5IP7_cjs.normalizePerPage(perPageInput, 20); if (page < 0) { throw new Error("page must be >= 0"); } const maxOffset = Number.MAX_SAFE_INTEGER / 2; if (page * perPage > maxOffset) { throw new Error("page value too large"); } let versions = Array.from(this.db.agentVersions.values()).filter((v) => v.agentId === agentId); versions = this.sortVersions(versions, field, direction); const clonedVersions = versions.map((v) => this.deepCopyVersion(v)); const total = clonedVersions.length; const { offset, perPage: perPageForResponse } = chunk3VBF5IP7_cjs.calculatePagination(page, perPageInput, perPage); const paginatedVersions = clonedVersions.slice(offset, offset + perPage); return { versions: paginatedVersions, total, page, perPage: perPageForResponse, hasMore: offset + perPage < total }; } async deleteVersion(id) { this.db.agentVersions.delete(id); } async deleteVersionsByParentId(entityId) { const idsToDelete = []; for (const [id, version] of this.db.agentVersions.entries()) { if (version.agentId === entityId) { idsToDelete.push(id); } } for (const id of idsToDelete) { this.db.agentVersions.delete(id); } } async countVersions(agentId) { let count = 0; for (const version of this.db.agentVersions.values()) { if (version.agentId === agentId) { count++; } } return count; } // ========================================================================== // Private Helper Methods // ========================================================================== /** * Deep copy a thin agent record to prevent external mutation of stored data */ deepCopyAgent(agent) { return { ...agent, metadata: agent.metadata ? { ...agent.metadata } : agent.metadata }; } /** * Deep copy a version to prevent external mutation of stored data */ deepCopyVersion(version) { return structuredClone(version); } sortAgents(agents, field, direction, favoritedIds) { return agents.sort((a, b) => { if (favoritedIds) { const aFav = favoritedIds.has(a.id) ? 1 : 0; const bFav = favoritedIds.has(b.id) ? 1 : 0; if (aFav !== bFav) return bFav - aFav; } const aValue = new Date(a[field]).getTime(); const bValue = new Date(b[field]).getTime(); if (aValue !== bValue) { return direction === "ASC" ? aValue - bValue : bValue - aValue; } return a.id < b.id ? -1 : a.id > b.id ? 1 : 0; }); } /** * Collect the set of agent IDs favorited by the given user. Returns an empty * Set when the favorites domain is not wired or the user has no favorites. */ collectFavoritedIdsFor(userId) { const favorited = /* @__PURE__ */ new Set(); for (const row of this.db.favorites.values()) { if (row.userId === userId && row.entityType === "agent") { favorited.add(row.entityId); } } return favorited; } sortVersions(versions, field, direction) { return versions.sort((a, b) => { let aVal; let bVal; if (field === "createdAt") { aVal = a.createdAt.getTime(); bVal = b.createdAt.getTime(); } else { aVal = a.versionNumber; bVal = b.versionNumber; } return direction === "ASC" ? aVal - bVal : bVal - aVal; }); } }; // src/storage/domains/agents/filesystem.ts var PERSISTED_SNAPSHOT_FIELDS = /* @__PURE__ */ new Set([ "name", "instructions", "model", "tools", "integrationTools", "mcpClients", "requestContextSchema" ]); function stripUnusedFields(obj) { const result = {}; for (const [key, value] of Object.entries(obj)) { if (PERSISTED_SNAPSHOT_FIELDS.has(key)) { result[key] = value; } } return result; } var FilesystemAgentsStorage = class extends AgentsStorage { helpers; constructor({ db }) { super(); this.helpers = new chunk3VBF5IP7_cjs.FilesystemVersionedHelpers({ db, entitiesFile: "agents.json", parentIdField: "agentId", name: "FilesystemAgentsStorage", versionMetadataFields: ["id", "agentId", "versionNumber", "changedFields", "changeMessage", "createdAt"] }); } async init() { await this.helpers.db.init(); } async dangerouslyClearAll() { await this.helpers.dangerouslyClearAll(); } async getById(id) { return this.helpers.getById(id); } async create(input) { const { agent } = input; const now = /* @__PURE__ */ new Date(); const visibility = agent.visibility ?? (agent.authorId ? "private" : void 0); const entity = { id: agent.id, status: "draft", activeVersionId: void 0, authorId: agent.authorId, visibility, metadata: agent.metadata, createdAt: now, updatedAt: now }; await this.helpers.createEntity(agent.id, entity); const { id: _id, authorId: _authorId, visibility: _visibility, metadata: _metadata, ...snapshotConfig } = agent; const filtered = stripUnusedFields(snapshotConfig); const versionId = crypto.randomUUID(); await this.createVersion({ id: versionId, agentId: agent.id, versionNumber: 1, ...filtered, changedFields: Object.keys(filtered), changeMessage: "Initial version" }); return structuredClone(entity); } async update(input) { const { id, ...updates } = input; const entityUpdates = {}; const entityFields = /* @__PURE__ */ new Set(["authorId", "visibility", "metadata", "activeVersionId", "status"]); for (const [key, value] of Object.entries(updates)) { if (entityFields.has(key)) { entityUpdates[key] = value; } } return this.helpers.updateEntity(id, entityUpdates); } async delete(id) { await this.helpers.deleteEntity(id); } async list(args) { const { page, perPage, orderBy, authorId, visibility, metadata, status } = args || {}; const result = await this.helpers.listEntities({ page, perPage, orderBy, listKey: "agents", filters: { authorId, visibility, metadata, status } }); return result; } async createVersion(input) { const { id, agentId, versionNumber, changedFields, changeMessage, ...snapshotFields } = input; const filtered = stripUnusedFields(snapshotFields); return this.helpers.createVersion({ id, agentId, versionNumber, changedFields, changeMessage, ...filtered }); } async getVersion(id) { return this.helpers.getVersion(id); } async getVersionByNumber(agentId, versionNumber) { return this.helpers.getVersionByNumber(agentId, versionNumber); } async getLatestVersion(agentId) { return this.helpers.getLatestVersion(agentId); } async listVersions(input) { const result = await this.helpers.listVersions(input, "agentId"); return result; } async deleteVersion(id) { await this.helpers.deleteVersion(id); } async deleteVersionsByParentId(entityId) { await this.helpers.deleteVersionsByParentId(entityId); } async countVersions(agentId) { return this.helpers.countVersions(agentId); } }; exports.AgentsStorage = AgentsStorage; exports.FilesystemAgentsStorage = FilesystemAgentsStorage; exports.InMemoryAgentsStorage = InMemoryAgentsStorage; //# sourceMappingURL=chunk-FYN37C2K.cjs.map //# sourceMappingURL=chunk-FYN37C2K.cjs.map