@mastra/factory 0.2.2-alpha.1 → 0.2.2-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/dist/auth.js +401 -334
- package/dist/auth.js.map +1 -1
- package/dist/capabilities/connection.js +1 -1
- package/dist/capabilities/intake.js +1 -1
- package/dist/capabilities/version-control.js +1 -1
- package/dist/factory.js +441 -39622
- package/dist/factory.js.map +1 -1
- package/dist/index.js +2 -39633
- package/dist/integrations/base.js +1 -1
- package/dist/integrations/github/config.js +36 -22
- package/dist/integrations/github/config.js.map +1 -1
- package/dist/integrations/github/factory-session.js +33 -37
- package/dist/integrations/github/factory-session.js.map +1 -1
- package/dist/integrations/github/integration.js +1037 -3672
- package/dist/integrations/github/integration.js.map +1 -1
- package/dist/integrations/github/issue-triage.js +71 -71
- package/dist/integrations/github/issue-triage.js.map +1 -1
- package/dist/integrations/github/pat.js +47 -36
- package/dist/integrations/github/pat.js.map +1 -1
- package/dist/integrations/github/provenance.js +72 -101
- package/dist/integrations/github/provenance.js.map +1 -1
- package/dist/integrations/github/routes.js +1272 -1881
- package/dist/integrations/github/routes.js.map +1 -1
- package/dist/integrations/github/rules.js +203 -471
- package/dist/integrations/github/rules.js.map +1 -1
- package/dist/integrations/github/sandbox.js +400 -345
- package/dist/integrations/github/sandbox.js.map +1 -1
- package/dist/integrations/github/session-subscriptions.js +165 -223
- package/dist/integrations/github/session-subscriptions.js.map +1 -1
- package/dist/integrations/github/subscriptions.js +43 -51
- package/dist/integrations/github/subscriptions.js.map +1 -1
- package/dist/integrations/github/token-refresh.js +15 -18
- package/dist/integrations/github/token-refresh.js.map +1 -1
- package/dist/integrations/github/webhook.js +359 -343
- package/dist/integrations/github/webhook.js.map +1 -1
- package/dist/integrations/linear/agent-tools.js +77 -100
- package/dist/integrations/linear/agent-tools.js.map +1 -1
- package/dist/integrations/linear/integration.js +611 -1309
- package/dist/integrations/linear/integration.js.map +1 -1
- package/dist/integrations/linear/routes.js +227 -230
- package/dist/integrations/linear/routes.js.map +1 -1
- package/dist/integrations/linear/rules.js +126 -346
- package/dist/integrations/linear/rules.js.map +1 -1
- package/dist/integrations/linear/storage.js +1 -1
- package/dist/integrations/platform/api-client.js +131 -135
- package/dist/integrations/platform/api-client.js.map +1 -1
- package/dist/integrations/platform/github/event-worker.js +275 -573
- package/dist/integrations/platform/github/event-worker.js.map +1 -1
- package/dist/integrations/platform/github/integration.js +845 -4022
- package/dist/integrations/platform/github/integration.js.map +1 -1
- package/dist/integrations/platform/linear/integration.js +457 -1309
- package/dist/integrations/platform/linear/integration.js.map +1 -1
- package/dist/integrations/workos/integration.js +80 -85
- package/dist/integrations/workos/integration.js.map +1 -1
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +933 -912
- package/dist/routes/config.js.map +1 -1
- package/dist/routes/custom-provider-source.js +110 -93
- package/dist/routes/custom-provider-source.js.map +1 -1
- package/dist/routes/fs.js +401 -349
- package/dist/routes/fs.js.map +1 -1
- package/dist/routes/intake.js +165 -165
- package/dist/routes/intake.js.map +1 -1
- package/dist/routes/oauth.js +447 -25166
- package/dist/routes/oauth.js.map +1 -1
- package/dist/routes/projects.js +437 -376
- package/dist/routes/projects.js.map +1 -1
- package/dist/routes/provider-credentials.js +76 -58
- package/dist/routes/provider-credentials.js.map +1 -1
- package/dist/routes/route.js +12 -8
- package/dist/routes/route.js.map +1 -1
- package/dist/routes/skills.js +160 -173
- package/dist/routes/skills.js.map +1 -1
- package/dist/routes/surface.js +250 -28615
- package/dist/routes/surface.js.map +1 -1
- package/dist/routes/tenant-credentials.js +141 -166
- package/dist/routes/tenant-credentials.js.map +1 -1
- package/dist/routes/work-items.js +654 -862
- package/dist/routes/work-items.js.map +1 -1
- package/dist/rules/binding-context.js +23 -35
- package/dist/rules/binding-context.js.map +1 -1
- package/dist/rules/defaults.js +200 -309
- package/dist/rules/defaults.js.map +1 -1
- package/dist/rules/dispatcher.js +438 -683
- package/dist/rules/dispatcher.js.map +1 -1
- package/dist/rules/index.js +5 -599
- package/dist/rules/processor.js +344 -596
- package/dist/rules/processor.js.map +1 -1
- package/dist/rules/resolve.js +21 -18
- package/dist/rules/resolve.js.map +1 -1
- package/dist/rules/start-coordinator.js +168 -157
- package/dist/rules/start-coordinator.js.map +1 -1
- package/dist/rules/tools.js +50 -85
- package/dist/rules/tools.js.map +1 -1
- package/dist/rules/transition-service.js +183 -454
- package/dist/rules/transition-service.js.map +1 -1
- package/dist/rules/types.js +33 -29
- package/dist/rules/types.js.map +1 -1
- package/dist/rules/validation.js +266 -281
- package/dist/rules/validation.js.map +1 -1
- package/dist/sandbox/fleet.js +272 -250
- package/dist/sandbox/fleet.js.map +1 -1
- package/dist/sandbox/reattach.js +13 -6
- package/dist/sandbox/reattach.js.map +1 -1
- package/dist/server-error.js +12 -16
- package/dist/server-error.js.map +1 -1
- package/dist/skills/service.js +30 -35
- package/dist/skills/service.js.map +1 -1
- package/dist/spa-static.js +91 -65
- package/dist/spa-static.js.map +1 -1
- package/dist/state-signing.js +73 -44
- package/dist/state-signing.js.map +1 -1
- package/dist/storage/domains/audit/agent-audit.js +60 -59
- package/dist/storage/domains/audit/agent-audit.js.map +1 -1
- package/dist/storage/domains/audit/base.js +169 -112
- package/dist/storage/domains/audit/base.js.map +1 -1
- package/dist/storage/domains/audit/domain.js +155 -153
- package/dist/storage/domains/audit/domain.js.map +1 -1
- package/dist/storage/domains/credentials/base.js +259 -243
- package/dist/storage/domains/credentials/base.js.map +1 -1
- package/dist/storage/domains/custom-providers/base.js +138 -143
- package/dist/storage/domains/custom-providers/base.js.map +1 -1
- package/dist/storage/domains/intake/base.js +75 -57
- package/dist/storage/domains/intake/base.js.map +1 -1
- package/dist/storage/domains/integrations/base.js +310 -245
- package/dist/storage/domains/integrations/base.js.map +1 -1
- package/dist/storage/domains/memory-settings/base.js +117 -102
- package/dist/storage/domains/memory-settings/base.js.map +1 -1
- package/dist/storage/domains/model-packs/base.js +89 -88
- package/dist/storage/domains/model-packs/base.js.map +1 -1
- package/dist/storage/domains/projects/base.js +97 -92
- package/dist/storage/domains/projects/base.js.map +1 -1
- package/dist/storage/domains/queue-health/base.js +111 -76
- package/dist/storage/domains/queue-health/base.js.map +1 -1
- package/dist/storage/domains/source-control/base.js +777 -706
- package/dist/storage/domains/source-control/base.js.map +1 -1
- package/dist/storage/domains/source-control/inmemory.js +322 -348
- package/dist/storage/domains/source-control/inmemory.js.map +1 -1
- package/dist/storage/domains/work-items/base.js +1266 -1148
- package/dist/storage/domains/work-items/base.js.map +1 -1
- package/dist/storage/domains/work-items/metrics.js +202 -184
- package/dist/storage/domains/work-items/metrics.js.map +1 -1
- package/dist/timing.js +29 -22
- package/dist/timing.js.map +1 -1
- package/dist/workspace.js +236 -477
- package/dist/workspace.js.map +1 -1
- package/package.json +8 -8
- package/dist/capabilities/connection.js.map +0 -1
- package/dist/capabilities/intake.js.map +0 -1
- package/dist/capabilities/version-control.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/integrations/base.js.map +0 -1
- package/dist/integrations/linear/storage.js.map +0 -1
- package/dist/rules/index.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/storage/domains/integrations/base.ts"],"sourcesContent":["/**\n * Generic integration storage — the default persistence surface for\n * `FactoryIntegration`s.\n *\n * Most integrations persist the same three shapes: an org-owned OAuth\n * **connection**, **subscriptions** binding external objects to\n * sessions/threads, and per-`(org, user)` **settings**. This built-in domain\n * stores all three in shared collections keyed by `integration_id`, so an\n * integration author writes zero schema, zero DDL, and zero queries — and\n * org scoping is enforced by construction through the pre-scoped handle\n * returned by {@link IntegrationStorage.forIntegration}.\n *\n * Source-control integrations additionally use the shared, provider-scoped\n * source-control domain for installations, projects, worktrees, and sandboxes.\n *\n * Payloads (`data` / `config`) are JSON documents typed per-integration via\n * the handle's generics. JSON round-trips exactly what JSON can represent:\n * store timestamps inside payloads as epoch millis or ISO strings, not\n * `Date`s.\n */\n\nimport { FactoryStorageDomain, UniqueViolationError } from '@mastra/core/storage';\nimport type { CollectionSchema, FactoryStorageOps } from '@mastra/core/storage';\n\nexport const INTEGRATION_CONNECTIONS_SCHEMA: CollectionSchema = {\n name: 'integration_connections',\n columns: {\n id: { type: 'uuid-pk' },\n integration_id: { type: 'text' },\n org_id: { type: 'text' },\n /** Who connected it (audit only — never scopes reads). */\n user_id: { type: 'text', nullable: true },\n data: { type: 'json' },\n metadata: { type: 'json' },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n uniqueIndexes: [{ name: 'integration_connections_integration_org_unique', columns: ['integration_id', 'org_id'] }],\n};\n\nexport const INTEGRATION_SUBSCRIPTIONS_SCHEMA: CollectionSchema = {\n name: 'integration_subscriptions',\n columns: {\n id: { type: 'uuid-pk' },\n integration_id: { type: 'text' },\n org_id: { type: 'text' },\n /** Canonical external-object key the integration derives (e.g. `pr:{installation}:{repo}:{number}`). */\n target_key: { type: 'text' },\n session_id: { type: 'text', nullable: true },\n resource_id: { type: 'text', nullable: true },\n thread_id: { type: 'text', nullable: true },\n session_scope: { type: 'text', nullable: true },\n status: { type: 'text' },\n data: { type: 'json' },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n indexes: [\n { name: 'integration_subscriptions_target_idx', columns: ['integration_id', 'target_key'] },\n { name: 'integration_subscriptions_org_idx', columns: ['integration_id', 'org_id'] },\n ],\n};\n\nexport const INTEGRATION_SETTINGS_SCHEMA: CollectionSchema = {\n name: 'integration_settings',\n columns: {\n id: { type: 'uuid-pk' },\n integration_id: { type: 'text' },\n org_id: { type: 'text' },\n user_id: { type: 'text' },\n config: { type: 'json' },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n uniqueIndexes: [\n { name: 'integration_settings_integration_org_user_unique', columns: ['integration_id', 'org_id', 'user_id'] },\n ],\n};\n\n/** An integration's org-owned connection (typically the OAuth grant). */\nexport interface IntegrationConnection<TData> {\n id: string;\n orgId: string;\n /** Who connected it (audit only). */\n userId: string | null;\n data: TData;\n metadata: Record<string, unknown>;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/** A subscription binding an external object to a session/thread. */\nexport interface IntegrationSubscription<TData> {\n id: string;\n orgId: string;\n targetKey: string;\n sessionId: string | null;\n resourceId: string | null;\n threadId: string | null;\n sessionScope: string | null;\n status: string;\n data: TData;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport type CreateIntegrationSubscriptionInput<TData> = {\n orgId: string;\n targetKey: string;\n sessionId?: string | null;\n resourceId?: string | null;\n threadId?: string | null;\n sessionScope?: string | null;\n /** Defaults to `'active'`. */\n status?: string;\n} & ({} extends TData ? { data?: TData } : { data: TData });\n\n/**\n * Typed query surface pre-scoped to one `integration_id`. Every read and\n * write is automatically filtered/stamped with the integration id, so an\n * integration cannot reach another integration's rows.\n */\nexport interface IntegrationStorageHandle<\n TConnection = Record<string, unknown>,\n TSettings = Record<string, unknown>,\n TSubscription = Record<string, unknown>,\n> {\n readonly integrationId: string;\n connections: {\n /** The org's connection, or `null` when not connected. */\n get(orgId: string): Promise<IntegrationConnection<TConnection> | null>;\n /** Insert or replace the org's connection (one per org; `created_at` preserved on update). */\n upsert(\n orgId: string,\n input: { userId?: string | null; data: TConnection; metadata?: Record<string, unknown> },\n ): Promise<void>;\n /**\n * Atomic read-modify-write of the connection's `data` payload (token\n * rotation etc.). Returns the updated connection, or `null` when the org\n * has no connection.\n */\n update(orgId: string, fn: (data: TConnection) => TConnection): Promise<IntegrationConnection<TConnection> | null>;\n /** Remove the org's connection. Returns whether a row was deleted. */\n delete(orgId: string): Promise<boolean>;\n };\n subscriptions: {\n create(input: CreateIntegrationSubscriptionInput<TSubscription>): Promise<IntegrationSubscription<TSubscription>>;\n /** All subscriptions for an external object (webhook fan-out), optionally filtered by status. */\n listByTarget(targetKey: string, opts?: { status?: string }): Promise<IntegrationSubscription<TSubscription>[]>;\n listBySession(sessionId: string): Promise<IntegrationSubscription<TSubscription>[]>;\n listByThread(resourceId: string, threadId: string): Promise<IntegrationSubscription<TSubscription>[]>;\n updateStatus(id: string, status: string): Promise<void>;\n delete(id: string): Promise<boolean>;\n /** Targeted cleanup, always org-scoped. Returns the number of rows deleted. */\n deleteWhere(where: { orgId: string; targetKey?: string; sessionId?: string }): Promise<number>;\n };\n settings: {\n /** The `(org, user)` config, or `null` when never saved. */\n get(orgId: string, userId: string): Promise<TSettings | null>;\n /** Upsert the `(org, user)` config (`created_at` preserved on update). */\n save(orgId: string, userId: string, config: TSettings): Promise<void>;\n };\n}\n\ninterface ConnectionRow extends Record<string, unknown> {\n id: string;\n integration_id: string;\n org_id: string;\n user_id: string | null;\n data: unknown;\n metadata: Record<string, unknown>;\n created_at: Date;\n updated_at: Date;\n}\n\ninterface SubscriptionRow extends Record<string, unknown> {\n id: string;\n integration_id: string;\n org_id: string;\n target_key: string;\n session_id: string | null;\n resource_id: string | null;\n thread_id: string | null;\n session_scope: string | null;\n status: string;\n data: unknown;\n created_at: Date;\n updated_at: Date;\n}\n\n/**\n * The built-in generic integration domain, written once against the\n * `FactoryStorageOps` surface — works on any `FactoryStorage` backend.\n */\nexport class IntegrationStorage extends FactoryStorageDomain {\n constructor() {\n super('integrations');\n }\n\n async init(): Promise<void> {\n await this.ensureCollections([\n INTEGRATION_CONNECTIONS_SCHEMA,\n INTEGRATION_SUBSCRIPTIONS_SCHEMA,\n INTEGRATION_SETTINGS_SCHEMA,\n ]);\n }\n\n async dangerouslyClearAll(): Promise<void> {\n await this.ops.deleteMany('integration_subscriptions', {});\n await this.ops.deleteMany('integration_settings', {});\n await this.ops.deleteMany('integration_connections', {});\n }\n\n get #db(): FactoryStorageOps {\n return this.ops;\n }\n\n /** A typed handle pre-scoped to `integrationId`. */\n forIntegration<\n TConnection = Record<string, unknown>,\n TSettings = Record<string, unknown>,\n TSubscription = Record<string, unknown>,\n >(integrationId: string): IntegrationStorageHandle<TConnection, TSettings, TSubscription> {\n if (!integrationId) throw new Error('[IntegrationStorage] integrationId is required.');\n const db = () => this.#db;\n const scoped = { integration_id: integrationId };\n\n const mapConnection = (row: ConnectionRow): IntegrationConnection<TConnection> => ({\n id: row.id,\n orgId: row.org_id,\n userId: row.user_id,\n data: row.data as TConnection,\n metadata: row.metadata ?? {},\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n });\n\n const mapSubscription = (row: SubscriptionRow): IntegrationSubscription<TSubscription> => ({\n id: row.id,\n orgId: row.org_id,\n targetKey: row.target_key,\n sessionId: row.session_id,\n resourceId: row.resource_id,\n threadId: row.thread_id,\n sessionScope: row.session_scope,\n status: row.status,\n data: row.data as TSubscription,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n });\n\n return {\n integrationId,\n connections: {\n get: async orgId => {\n const row = await db().findOne<ConnectionRow>('integration_connections', { ...scoped, org_id: orgId });\n return row ? mapConnection(row) : null;\n },\n upsert: async (orgId, input) => {\n const where = { ...scoped, org_id: orgId };\n const update = async () =>\n db().updateMany('integration_connections', where, {\n user_id: input.userId ?? null,\n data: input.data,\n metadata: input.metadata ?? {},\n updated_at: new Date(),\n });\n\n let lastError: unknown;\n for (let attempt = 0; attempt < 2; attempt++) {\n if ((await update()) > 0) return;\n\n const now = new Date();\n try {\n await db().insertOne<ConnectionRow>('integration_connections', {\n ...where,\n user_id: input.userId ?? null,\n data: input.data,\n metadata: input.metadata ?? {},\n created_at: now,\n updated_at: now,\n });\n return;\n } catch (error) {\n if (!(error instanceof UniqueViolationError)) throw error;\n lastError = error;\n }\n }\n throw lastError;\n },\n update: async (orgId, fn) => {\n const row = await db().updateAtomic<ConnectionRow>(\n 'integration_connections',\n { ...scoped, org_id: orgId },\n current => ({ data: fn(current.data as TConnection), updated_at: new Date() }),\n );\n return row ? mapConnection(row) : null;\n },\n delete: async orgId => {\n const deleted = await db().deleteMany('integration_connections', { ...scoped, org_id: orgId });\n return deleted > 0;\n },\n },\n subscriptions: {\n create: async input => {\n const now = new Date();\n const row = await db().insertOne<SubscriptionRow>('integration_subscriptions', {\n ...scoped,\n org_id: input.orgId,\n target_key: input.targetKey,\n session_id: input.sessionId ?? null,\n resource_id: input.resourceId ?? null,\n thread_id: input.threadId ?? null,\n session_scope: input.sessionScope ?? null,\n status: input.status ?? 'active',\n data: input.data ?? {},\n created_at: now,\n updated_at: now,\n });\n return mapSubscription(row);\n },\n listByTarget: async (targetKey, opts) => {\n const rows = await db().findMany<SubscriptionRow>(\n 'integration_subscriptions',\n { ...scoped, target_key: targetKey, ...(opts?.status !== undefined ? { status: opts.status } : {}) },\n { orderBy: [['created_at', 'asc']] },\n );\n return rows.map(mapSubscription);\n },\n listBySession: async sessionId => {\n const rows = await db().findMany<SubscriptionRow>(\n 'integration_subscriptions',\n { ...scoped, session_id: sessionId },\n { orderBy: [['created_at', 'asc']] },\n );\n return rows.map(mapSubscription);\n },\n listByThread: async (resourceId, threadId) => {\n const rows = await db().findMany<SubscriptionRow>(\n 'integration_subscriptions',\n { ...scoped, resource_id: resourceId, thread_id: threadId },\n { orderBy: [['created_at', 'asc']] },\n );\n return rows.map(mapSubscription);\n },\n updateStatus: async (id, status) => {\n await db().updateMany('integration_subscriptions', { ...scoped, id }, { status, updated_at: new Date() });\n },\n delete: async id => {\n const deleted = await db().deleteMany('integration_subscriptions', { ...scoped, id });\n return deleted > 0;\n },\n deleteWhere: async where => {\n return db().deleteMany('integration_subscriptions', {\n ...scoped,\n org_id: where.orgId,\n ...(where.targetKey !== undefined ? { target_key: where.targetKey } : {}),\n ...(where.sessionId !== undefined ? { session_id: where.sessionId } : {}),\n });\n },\n },\n settings: {\n get: async (orgId, userId) => {\n const row = await db().findOne<{ config: TSettings }>('integration_settings', {\n ...scoped,\n org_id: orgId,\n user_id: userId,\n });\n return row ? structuredClone(row.config) : null;\n },\n save: async (orgId, userId, config) => {\n const where = { ...scoped, org_id: orgId, user_id: userId };\n const update = async () =>\n db().updateMany('integration_settings', where, {\n config,\n updated_at: new Date(),\n });\n\n let lastError: unknown;\n for (let attempt = 0; attempt < 2; attempt++) {\n if ((await update()) > 0) return;\n\n const now = new Date();\n try {\n await db().insertOne('integration_settings', {\n ...where,\n config,\n created_at: now,\n updated_at: now,\n });\n return;\n } catch (error) {\n if (!(error instanceof UniqueViolationError)) throw error;\n lastError = error;\n }\n }\n throw lastError;\n },\n },\n };\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"file":"base.js","names":["#db"],"sources":["../../../../src/storage/domains/integrations/base.ts"],"sourcesContent":["/**\n * Generic integration storage — the default persistence surface for\n * `FactoryIntegration`s.\n *\n * Most integrations persist the same three shapes: an org-owned OAuth\n * **connection**, **subscriptions** binding external objects to\n * sessions/threads, and per-`(org, user)` **settings**. This built-in domain\n * stores all three in shared collections keyed by `integration_id`, so an\n * integration author writes zero schema, zero DDL, and zero queries — and\n * org scoping is enforced by construction through the pre-scoped handle\n * returned by {@link IntegrationStorage.forIntegration}.\n *\n * Source-control integrations additionally use the shared, provider-scoped\n * source-control domain for installations, projects, worktrees, and sandboxes.\n *\n * Payloads (`data` / `config`) are JSON documents typed per-integration via\n * the handle's generics. JSON round-trips exactly what JSON can represent:\n * store timestamps inside payloads as epoch millis or ISO strings, not\n * `Date`s.\n */\n\nimport { FactoryStorageDomain, UniqueViolationError } from '@mastra/core/storage';\nimport type { CollectionSchema, FactoryStorageOps } from '@mastra/core/storage';\n\nexport const INTEGRATION_CONNECTIONS_SCHEMA: CollectionSchema = {\n name: 'integration_connections',\n columns: {\n id: { type: 'uuid-pk' },\n integration_id: { type: 'text' },\n org_id: { type: 'text' },\n /** Who connected it (audit only — never scopes reads). */\n user_id: { type: 'text', nullable: true },\n data: { type: 'json' },\n metadata: { type: 'json' },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n uniqueIndexes: [{ name: 'integration_connections_integration_org_unique', columns: ['integration_id', 'org_id'] }],\n};\n\nexport const INTEGRATION_SUBSCRIPTIONS_SCHEMA: CollectionSchema = {\n name: 'integration_subscriptions',\n columns: {\n id: { type: 'uuid-pk' },\n integration_id: { type: 'text' },\n org_id: { type: 'text' },\n /** Canonical external-object key the integration derives (e.g. `pr:{installation}:{repo}:{number}`). */\n target_key: { type: 'text' },\n session_id: { type: 'text', nullable: true },\n resource_id: { type: 'text', nullable: true },\n thread_id: { type: 'text', nullable: true },\n session_scope: { type: 'text', nullable: true },\n status: { type: 'text' },\n data: { type: 'json' },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n indexes: [\n { name: 'integration_subscriptions_target_idx', columns: ['integration_id', 'target_key'] },\n { name: 'integration_subscriptions_org_idx', columns: ['integration_id', 'org_id'] },\n ],\n};\n\nexport const INTEGRATION_SETTINGS_SCHEMA: CollectionSchema = {\n name: 'integration_settings',\n columns: {\n id: { type: 'uuid-pk' },\n integration_id: { type: 'text' },\n org_id: { type: 'text' },\n user_id: { type: 'text' },\n config: { type: 'json' },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n uniqueIndexes: [\n { name: 'integration_settings_integration_org_user_unique', columns: ['integration_id', 'org_id', 'user_id'] },\n ],\n};\n\n/** An integration's org-owned connection (typically the OAuth grant). */\nexport interface IntegrationConnection<TData> {\n id: string;\n orgId: string;\n /** Who connected it (audit only). */\n userId: string | null;\n data: TData;\n metadata: Record<string, unknown>;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/** A subscription binding an external object to a session/thread. */\nexport interface IntegrationSubscription<TData> {\n id: string;\n orgId: string;\n targetKey: string;\n sessionId: string | null;\n resourceId: string | null;\n threadId: string | null;\n sessionScope: string | null;\n status: string;\n data: TData;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport type CreateIntegrationSubscriptionInput<TData> = {\n orgId: string;\n targetKey: string;\n sessionId?: string | null;\n resourceId?: string | null;\n threadId?: string | null;\n sessionScope?: string | null;\n /** Defaults to `'active'`. */\n status?: string;\n} & ({} extends TData ? { data?: TData } : { data: TData });\n\n/**\n * Typed query surface pre-scoped to one `integration_id`. Every read and\n * write is automatically filtered/stamped with the integration id, so an\n * integration cannot reach another integration's rows.\n */\nexport interface IntegrationStorageHandle<\n TConnection = Record<string, unknown>,\n TSettings = Record<string, unknown>,\n TSubscription = Record<string, unknown>,\n> {\n readonly integrationId: string;\n connections: {\n /** The org's connection, or `null` when not connected. */\n get(orgId: string): Promise<IntegrationConnection<TConnection> | null>;\n /** Insert or replace the org's connection (one per org; `created_at` preserved on update). */\n upsert(\n orgId: string,\n input: { userId?: string | null; data: TConnection; metadata?: Record<string, unknown> },\n ): Promise<void>;\n /**\n * Atomic read-modify-write of the connection's `data` payload (token\n * rotation etc.). Returns the updated connection, or `null` when the org\n * has no connection.\n */\n update(orgId: string, fn: (data: TConnection) => TConnection): Promise<IntegrationConnection<TConnection> | null>;\n /** Remove the org's connection. Returns whether a row was deleted. */\n delete(orgId: string): Promise<boolean>;\n };\n subscriptions: {\n create(input: CreateIntegrationSubscriptionInput<TSubscription>): Promise<IntegrationSubscription<TSubscription>>;\n /** All subscriptions for an external object (webhook fan-out), optionally filtered by status. */\n listByTarget(targetKey: string, opts?: { status?: string }): Promise<IntegrationSubscription<TSubscription>[]>;\n listBySession(sessionId: string): Promise<IntegrationSubscription<TSubscription>[]>;\n listByThread(resourceId: string, threadId: string): Promise<IntegrationSubscription<TSubscription>[]>;\n updateStatus(id: string, status: string): Promise<void>;\n delete(id: string): Promise<boolean>;\n /** Targeted cleanup, always org-scoped. Returns the number of rows deleted. */\n deleteWhere(where: { orgId: string; targetKey?: string; sessionId?: string }): Promise<number>;\n };\n settings: {\n /** The `(org, user)` config, or `null` when never saved. */\n get(orgId: string, userId: string): Promise<TSettings | null>;\n /** Upsert the `(org, user)` config (`created_at` preserved on update). */\n save(orgId: string, userId: string, config: TSettings): Promise<void>;\n };\n}\n\ninterface ConnectionRow extends Record<string, unknown> {\n id: string;\n integration_id: string;\n org_id: string;\n user_id: string | null;\n data: unknown;\n metadata: Record<string, unknown>;\n created_at: Date;\n updated_at: Date;\n}\n\ninterface SubscriptionRow extends Record<string, unknown> {\n id: string;\n integration_id: string;\n org_id: string;\n target_key: string;\n session_id: string | null;\n resource_id: string | null;\n thread_id: string | null;\n session_scope: string | null;\n status: string;\n data: unknown;\n created_at: Date;\n updated_at: Date;\n}\n\n/**\n * The built-in generic integration domain, written once against the\n * `FactoryStorageOps` surface — works on any `FactoryStorage` backend.\n */\nexport class IntegrationStorage extends FactoryStorageDomain {\n constructor() {\n super('integrations');\n }\n\n async init(): Promise<void> {\n await this.ensureCollections([\n INTEGRATION_CONNECTIONS_SCHEMA,\n INTEGRATION_SUBSCRIPTIONS_SCHEMA,\n INTEGRATION_SETTINGS_SCHEMA,\n ]);\n }\n\n async dangerouslyClearAll(): Promise<void> {\n await this.ops.deleteMany('integration_subscriptions', {});\n await this.ops.deleteMany('integration_settings', {});\n await this.ops.deleteMany('integration_connections', {});\n }\n\n get #db(): FactoryStorageOps {\n return this.ops;\n }\n\n /** A typed handle pre-scoped to `integrationId`. */\n forIntegration<\n TConnection = Record<string, unknown>,\n TSettings = Record<string, unknown>,\n TSubscription = Record<string, unknown>,\n >(integrationId: string): IntegrationStorageHandle<TConnection, TSettings, TSubscription> {\n if (!integrationId) throw new Error('[IntegrationStorage] integrationId is required.');\n const db = () => this.#db;\n const scoped = { integration_id: integrationId };\n\n const mapConnection = (row: ConnectionRow): IntegrationConnection<TConnection> => ({\n id: row.id,\n orgId: row.org_id,\n userId: row.user_id,\n data: row.data as TConnection,\n metadata: row.metadata ?? {},\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n });\n\n const mapSubscription = (row: SubscriptionRow): IntegrationSubscription<TSubscription> => ({\n id: row.id,\n orgId: row.org_id,\n targetKey: row.target_key,\n sessionId: row.session_id,\n resourceId: row.resource_id,\n threadId: row.thread_id,\n sessionScope: row.session_scope,\n status: row.status,\n data: row.data as TSubscription,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n });\n\n return {\n integrationId,\n connections: {\n get: async orgId => {\n const row = await db().findOne<ConnectionRow>('integration_connections', { ...scoped, org_id: orgId });\n return row ? mapConnection(row) : null;\n },\n upsert: async (orgId, input) => {\n const where = { ...scoped, org_id: orgId };\n const update = async () =>\n db().updateMany('integration_connections', where, {\n user_id: input.userId ?? null,\n data: input.data,\n metadata: input.metadata ?? {},\n updated_at: new Date(),\n });\n\n let lastError: unknown;\n for (let attempt = 0; attempt < 2; attempt++) {\n if ((await update()) > 0) return;\n\n const now = new Date();\n try {\n await db().insertOne<ConnectionRow>('integration_connections', {\n ...where,\n user_id: input.userId ?? null,\n data: input.data,\n metadata: input.metadata ?? {},\n created_at: now,\n updated_at: now,\n });\n return;\n } catch (error) {\n if (!(error instanceof UniqueViolationError)) throw error;\n lastError = error;\n }\n }\n throw lastError;\n },\n update: async (orgId, fn) => {\n const row = await db().updateAtomic<ConnectionRow>(\n 'integration_connections',\n { ...scoped, org_id: orgId },\n current => ({ data: fn(current.data as TConnection), updated_at: new Date() }),\n );\n return row ? mapConnection(row) : null;\n },\n delete: async orgId => {\n const deleted = await db().deleteMany('integration_connections', { ...scoped, org_id: orgId });\n return deleted > 0;\n },\n },\n subscriptions: {\n create: async input => {\n const now = new Date();\n const row = await db().insertOne<SubscriptionRow>('integration_subscriptions', {\n ...scoped,\n org_id: input.orgId,\n target_key: input.targetKey,\n session_id: input.sessionId ?? null,\n resource_id: input.resourceId ?? null,\n thread_id: input.threadId ?? null,\n session_scope: input.sessionScope ?? null,\n status: input.status ?? 'active',\n data: input.data ?? {},\n created_at: now,\n updated_at: now,\n });\n return mapSubscription(row);\n },\n listByTarget: async (targetKey, opts) => {\n const rows = await db().findMany<SubscriptionRow>(\n 'integration_subscriptions',\n { ...scoped, target_key: targetKey, ...(opts?.status !== undefined ? { status: opts.status } : {}) },\n { orderBy: [['created_at', 'asc']] },\n );\n return rows.map(mapSubscription);\n },\n listBySession: async sessionId => {\n const rows = await db().findMany<SubscriptionRow>(\n 'integration_subscriptions',\n { ...scoped, session_id: sessionId },\n { orderBy: [['created_at', 'asc']] },\n );\n return rows.map(mapSubscription);\n },\n listByThread: async (resourceId, threadId) => {\n const rows = await db().findMany<SubscriptionRow>(\n 'integration_subscriptions',\n { ...scoped, resource_id: resourceId, thread_id: threadId },\n { orderBy: [['created_at', 'asc']] },\n );\n return rows.map(mapSubscription);\n },\n updateStatus: async (id, status) => {\n await db().updateMany('integration_subscriptions', { ...scoped, id }, { status, updated_at: new Date() });\n },\n delete: async id => {\n const deleted = await db().deleteMany('integration_subscriptions', { ...scoped, id });\n return deleted > 0;\n },\n deleteWhere: async where => {\n return db().deleteMany('integration_subscriptions', {\n ...scoped,\n org_id: where.orgId,\n ...(where.targetKey !== undefined ? { target_key: where.targetKey } : {}),\n ...(where.sessionId !== undefined ? { session_id: where.sessionId } : {}),\n });\n },\n },\n settings: {\n get: async (orgId, userId) => {\n const row = await db().findOne<{ config: TSettings }>('integration_settings', {\n ...scoped,\n org_id: orgId,\n user_id: userId,\n });\n return row ? structuredClone(row.config) : null;\n },\n save: async (orgId, userId, config) => {\n const where = { ...scoped, org_id: orgId, user_id: userId };\n const update = async () =>\n db().updateMany('integration_settings', where, {\n config,\n updated_at: new Date(),\n });\n\n let lastError: unknown;\n for (let attempt = 0; attempt < 2; attempt++) {\n if ((await update()) > 0) return;\n\n const now = new Date();\n try {\n await db().insertOne('integration_settings', {\n ...where,\n config,\n created_at: now,\n updated_at: now,\n });\n return;\n } catch (error) {\n if (!(error instanceof UniqueViolationError)) throw error;\n lastError = error;\n }\n }\n throw lastError;\n },\n },\n };\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,iCAAmD;CAC9D,MAAM;CACN,SAAS;EACP,IAAI,EAAE,MAAM,UAAU;EACtB,gBAAgB,EAAE,MAAM,OAAO;EAC/B,QAAQ,EAAE,MAAM,OAAO;;EAEvB,SAAS;GAAE,MAAM;GAAQ,UAAU;EAAK;EACxC,MAAM,EAAE,MAAM,OAAO;EACrB,UAAU,EAAE,MAAM,OAAO;EACzB,YAAY,EAAE,MAAM,YAAY;EAChC,YAAY,EAAE,MAAM,YAAY;CAClC;CACA,eAAe,CAAC;EAAE,MAAM;EAAkD,SAAS,CAAC,kBAAkB,QAAQ;CAAE,CAAC;AACnH;AAEA,MAAa,mCAAqD;CAChE,MAAM;CACN,SAAS;EACP,IAAI,EAAE,MAAM,UAAU;EACtB,gBAAgB,EAAE,MAAM,OAAO;EAC/B,QAAQ,EAAE,MAAM,OAAO;;EAEvB,YAAY,EAAE,MAAM,OAAO;EAC3B,YAAY;GAAE,MAAM;GAAQ,UAAU;EAAK;EAC3C,aAAa;GAAE,MAAM;GAAQ,UAAU;EAAK;EAC5C,WAAW;GAAE,MAAM;GAAQ,UAAU;EAAK;EAC1C,eAAe;GAAE,MAAM;GAAQ,UAAU;EAAK;EAC9C,QAAQ,EAAE,MAAM,OAAO;EACvB,MAAM,EAAE,MAAM,OAAO;EACrB,YAAY,EAAE,MAAM,YAAY;EAChC,YAAY,EAAE,MAAM,YAAY;CAClC;CACA,SAAS,CACP;EAAE,MAAM;EAAwC,SAAS,CAAC,kBAAkB,YAAY;CAAE,GAC1F;EAAE,MAAM;EAAqC,SAAS,CAAC,kBAAkB,QAAQ;CAAE,CACrF;AACF;AAEA,MAAa,8BAAgD;CAC3D,MAAM;CACN,SAAS;EACP,IAAI,EAAE,MAAM,UAAU;EACtB,gBAAgB,EAAE,MAAM,OAAO;EAC/B,QAAQ,EAAE,MAAM,OAAO;EACvB,SAAS,EAAE,MAAM,OAAO;EACxB,QAAQ,EAAE,MAAM,OAAO;EACvB,YAAY,EAAE,MAAM,YAAY;EAChC,YAAY,EAAE,MAAM,YAAY;CAClC;CACA,eAAe,CACb;EAAE,MAAM;EAAoD,SAAS;GAAC;GAAkB;GAAU;EAAS;CAAE,CAC/G;AACF;;;;;AAqHA,IAAa,qBAAb,cAAwC,qBAAqB;CAC3D,cAAc;EACZ,MAAM,cAAc;CACtB;CAEA,MAAM,OAAsB;EAC1B,MAAM,KAAK,kBAAkB;GAC3B;GACA;GACA;EACF,CAAC;CACH;CAEA,MAAM,sBAAqC;EACzC,MAAM,KAAK,IAAI,WAAW,6BAA6B,CAAC,CAAC;EACzD,MAAM,KAAK,IAAI,WAAW,wBAAwB,CAAC,CAAC;EACpD,MAAM,KAAK,IAAI,WAAW,2BAA2B,CAAC,CAAC;CACzD;CAEA,IAAIA,MAAyB;EAC3B,OAAO,KAAK;CACd;;CAGA,eAIE,eAAwF;EACxF,IAAI,CAAC,eAAe,MAAM,IAAI,MAAM,iDAAiD;EACrF,MAAM,WAAW,KAAKA;EACtB,MAAM,SAAS,EAAE,gBAAgB,cAAc;EAE/C,MAAM,iBAAiB,SAA4D;GACjF,IAAI,IAAI;GACR,OAAO,IAAI;GACX,QAAQ,IAAI;GACZ,MAAM,IAAI;GACV,UAAU,IAAI,YAAY,CAAC;GAC3B,WAAW,IAAI;GACf,WAAW,IAAI;EACjB;EAEA,MAAM,mBAAmB,SAAkE;GACzF,IAAI,IAAI;GACR,OAAO,IAAI;GACX,WAAW,IAAI;GACf,WAAW,IAAI;GACf,YAAY,IAAI;GAChB,UAAU,IAAI;GACd,cAAc,IAAI;GAClB,QAAQ,IAAI;GACZ,MAAM,IAAI;GACV,WAAW,IAAI;GACf,WAAW,IAAI;EACjB;EAEA,OAAO;GACL;GACA,aAAa;IACX,KAAK,OAAM,UAAS;KAClB,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,QAAuB,2BAA2B;MAAE,GAAG;MAAQ,QAAQ;KAAM,CAAC;KACrG,OAAO,MAAM,cAAc,GAAG,IAAI;IACpC;IACA,QAAQ,OAAO,OAAO,UAAU;KAC9B,MAAM,QAAQ;MAAE,GAAG;MAAQ,QAAQ;KAAM;KACzC,MAAM,SAAS,YACb,GAAG,CAAC,CAAC,WAAW,2BAA2B,OAAO;MAChD,SAAS,MAAM,UAAU;MACzB,MAAM,MAAM;MACZ,UAAU,MAAM,YAAY,CAAC;MAC7B,4BAAY,IAAI,KAAK;KACvB,CAAC;KAEH,IAAI;KACJ,KAAK,IAAI,UAAU,GAAG,UAAU,GAAG,WAAW;MAC5C,IAAK,MAAM,OAAO,IAAK,GAAG;MAE1B,MAAM,sBAAM,IAAI,KAAK;MACrB,IAAI;OACF,MAAM,GAAG,CAAC,CAAC,UAAyB,2BAA2B;QAC7D,GAAG;QACH,SAAS,MAAM,UAAU;QACzB,MAAM,MAAM;QACZ,UAAU,MAAM,YAAY,CAAC;QAC7B,YAAY;QACZ,YAAY;OACd,CAAC;OACD;MACF,SAAS,OAAO;OACd,IAAI,EAAE,iBAAiB,uBAAuB,MAAM;OACpD,YAAY;MACd;KACF;KACA,MAAM;IACR;IACA,QAAQ,OAAO,OAAO,OAAO;KAC3B,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,aACrB,2BACA;MAAE,GAAG;MAAQ,QAAQ;KAAM,IAC3B,aAAY;MAAE,MAAM,GAAG,QAAQ,IAAmB;MAAG,4BAAY,IAAI,KAAK;KAAE,EAC9E;KACA,OAAO,MAAM,cAAc,GAAG,IAAI;IACpC;IACA,QAAQ,OAAM,UAAS;KAErB,OAAO,MADe,GAAG,CAAC,CAAC,WAAW,2BAA2B;MAAE,GAAG;MAAQ,QAAQ;KAAM,CAAC,IAC5E;IACnB;GACF;GACA,eAAe;IACb,QAAQ,OAAM,UAAS;KACrB,MAAM,sBAAM,IAAI,KAAK;KACrB,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,UAA2B,6BAA6B;MAC7E,GAAG;MACH,QAAQ,MAAM;MACd,YAAY,MAAM;MAClB,YAAY,MAAM,aAAa;MAC/B,aAAa,MAAM,cAAc;MACjC,WAAW,MAAM,YAAY;MAC7B,eAAe,MAAM,gBAAgB;MACrC,QAAQ,MAAM,UAAU;MACxB,MAAM,MAAM,QAAQ,CAAC;MACrB,YAAY;MACZ,YAAY;KACd,CAAC;KACD,OAAO,gBAAgB,GAAG;IAC5B;IACA,cAAc,OAAO,WAAW,SAAS;KAMvC,QAAO,MALY,GAAG,CAAC,CAAC,SACtB,6BACA;MAAE,GAAG;MAAQ,YAAY;MAAW,GAAI,MAAM,WAAW,KAAA,IAAY,EAAE,QAAQ,KAAK,OAAO,IAAI,CAAC;KAAG,GACnG,EAAE,SAAS,CAAC,CAAC,cAAc,KAAK,CAAC,EAAE,CACrC,EAAA,CACY,IAAI,eAAe;IACjC;IACA,eAAe,OAAM,cAAa;KAMhC,QAAO,MALY,GAAG,CAAC,CAAC,SACtB,6BACA;MAAE,GAAG;MAAQ,YAAY;KAAU,GACnC,EAAE,SAAS,CAAC,CAAC,cAAc,KAAK,CAAC,EAAE,CACrC,EAAA,CACY,IAAI,eAAe;IACjC;IACA,cAAc,OAAO,YAAY,aAAa;KAM5C,QAAO,MALY,GAAG,CAAC,CAAC,SACtB,6BACA;MAAE,GAAG;MAAQ,aAAa;MAAY,WAAW;KAAS,GAC1D,EAAE,SAAS,CAAC,CAAC,cAAc,KAAK,CAAC,EAAE,CACrC,EAAA,CACY,IAAI,eAAe;IACjC;IACA,cAAc,OAAO,IAAI,WAAW;KAClC,MAAM,GAAG,CAAC,CAAC,WAAW,6BAA6B;MAAE,GAAG;MAAQ;KAAG,GAAG;MAAE;MAAQ,4BAAY,IAAI,KAAK;KAAE,CAAC;IAC1G;IACA,QAAQ,OAAM,OAAM;KAElB,OAAO,MADe,GAAG,CAAC,CAAC,WAAW,6BAA6B;MAAE,GAAG;MAAQ;KAAG,CAAC,IACnE;IACnB;IACA,aAAa,OAAM,UAAS;KAC1B,OAAO,GAAG,CAAC,CAAC,WAAW,6BAA6B;MAClD,GAAG;MACH,QAAQ,MAAM;MACd,GAAI,MAAM,cAAc,KAAA,IAAY,EAAE,YAAY,MAAM,UAAU,IAAI,CAAC;MACvE,GAAI,MAAM,cAAc,KAAA,IAAY,EAAE,YAAY,MAAM,UAAU,IAAI,CAAC;KACzE,CAAC;IACH;GACF;GACA,UAAU;IACR,KAAK,OAAO,OAAO,WAAW;KAC5B,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,QAA+B,wBAAwB;MAC5E,GAAG;MACH,QAAQ;MACR,SAAS;KACX,CAAC;KACD,OAAO,MAAM,gBAAgB,IAAI,MAAM,IAAI;IAC7C;IACA,MAAM,OAAO,OAAO,QAAQ,WAAW;KACrC,MAAM,QAAQ;MAAE,GAAG;MAAQ,QAAQ;MAAO,SAAS;KAAO;KAC1D,MAAM,SAAS,YACb,GAAG,CAAC,CAAC,WAAW,wBAAwB,OAAO;MAC7C;MACA,4BAAY,IAAI,KAAK;KACvB,CAAC;KAEH,IAAI;KACJ,KAAK,IAAI,UAAU,GAAG,UAAU,GAAG,WAAW;MAC5C,IAAK,MAAM,OAAO,IAAK,GAAG;MAE1B,MAAM,sBAAM,IAAI,KAAK;MACrB,IAAI;OACF,MAAM,GAAG,CAAC,CAAC,UAAU,wBAAwB;QAC3C,GAAG;QACH;QACA,YAAY;QACZ,YAAY;OACd,CAAC;OACD;MACF,SAAS,OAAO;OACd,IAAI,EAAE,iBAAiB,uBAAuB,MAAM;OACpD,YAAY;MACd;KACF;KACA,MAAM;IACR;GACF;EACF;CACF;AACF"}
|
|
@@ -1,111 +1,126 @@
|
|
|
1
|
-
// src/storage/domains/memory-settings/base.ts
|
|
2
1
|
import { FactoryStorageDomain, UniqueViolationError } from "@mastra/core/storage";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
2
|
+
//#region src/storage/domains/memory-settings/base.ts
|
|
3
|
+
const MEMORY_SETTINGS_SCHEMA = {
|
|
4
|
+
name: "memory_settings",
|
|
5
|
+
columns: {
|
|
6
|
+
id: { type: "uuid-pk" },
|
|
7
|
+
org_id: { type: "text" },
|
|
8
|
+
user_id: { type: "text" },
|
|
9
|
+
observer_model_id: {
|
|
10
|
+
type: "text",
|
|
11
|
+
nullable: true
|
|
12
|
+
},
|
|
13
|
+
reflector_model_id: {
|
|
14
|
+
type: "text",
|
|
15
|
+
nullable: true
|
|
16
|
+
},
|
|
17
|
+
observation_threshold: {
|
|
18
|
+
type: "integer",
|
|
19
|
+
nullable: true
|
|
20
|
+
},
|
|
21
|
+
reflection_threshold: {
|
|
22
|
+
type: "integer",
|
|
23
|
+
nullable: true
|
|
24
|
+
},
|
|
25
|
+
observe_attachments: {
|
|
26
|
+
type: "json",
|
|
27
|
+
nullable: true
|
|
28
|
+
},
|
|
29
|
+
created_at: { type: "timestamp" },
|
|
30
|
+
updated_at: { type: "timestamp" }
|
|
31
|
+
},
|
|
32
|
+
uniqueIndexes: [{
|
|
33
|
+
name: "memory_settings_org_user_key",
|
|
34
|
+
columns: ["org_id", "user_id"]
|
|
35
|
+
}]
|
|
19
36
|
};
|
|
20
37
|
function toRecord(row) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
38
|
+
return {
|
|
39
|
+
orgId: row.org_id,
|
|
40
|
+
userId: row.user_id,
|
|
41
|
+
observerModelId: row.observer_model_id,
|
|
42
|
+
reflectorModelId: row.reflector_model_id,
|
|
43
|
+
observationThreshold: row.observation_threshold,
|
|
44
|
+
reflectionThreshold: row.reflection_threshold,
|
|
45
|
+
observeAttachments: row.observe_attachments,
|
|
46
|
+
createdAt: row.created_at,
|
|
47
|
+
updatedAt: row.updated_at
|
|
48
|
+
};
|
|
32
49
|
}
|
|
33
50
|
function patchToColumns(patch) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
51
|
+
const columns = {};
|
|
52
|
+
if (patch.observerModelId !== void 0) columns.observer_model_id = patch.observerModelId;
|
|
53
|
+
if (patch.reflectorModelId !== void 0) columns.reflector_model_id = patch.reflectorModelId;
|
|
54
|
+
if (patch.observationThreshold !== void 0) columns.observation_threshold = patch.observationThreshold;
|
|
55
|
+
if (patch.reflectionThreshold !== void 0) columns.reflection_threshold = patch.reflectionThreshold;
|
|
56
|
+
if (patch.observeAttachments !== void 0) columns.observe_attachments = patch.observeAttachments;
|
|
57
|
+
return columns;
|
|
41
58
|
}
|
|
42
59
|
var MemorySettingsStorage = class extends FactoryStorageDomain {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
export {
|
|
108
|
-
MEMORY_SETTINGS_SCHEMA,
|
|
109
|
-
MemorySettingsStorage
|
|
60
|
+
constructor() {
|
|
61
|
+
super("memory-settings");
|
|
62
|
+
}
|
|
63
|
+
async init() {
|
|
64
|
+
await this.ensureCollections([MEMORY_SETTINGS_SCHEMA]);
|
|
65
|
+
}
|
|
66
|
+
async dangerouslyClearAll() {
|
|
67
|
+
await this.ops.deleteMany("memory_settings", {});
|
|
68
|
+
}
|
|
69
|
+
get #db() {
|
|
70
|
+
return this.ops;
|
|
71
|
+
}
|
|
72
|
+
async get({ orgId, userId }) {
|
|
73
|
+
const row = await this.#db.findOne("memory_settings", {
|
|
74
|
+
org_id: orgId,
|
|
75
|
+
user_id: userId
|
|
76
|
+
});
|
|
77
|
+
return row ? toRecord(row) : null;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Upsert the user's row, writing only the knobs present in `patch`.
|
|
81
|
+
* `fillIfUnset` knobs are written only where the stored value is still
|
|
82
|
+
* `NULL`, decided inside the atomic update so concurrent explicit writes
|
|
83
|
+
* win over fills. Concurrent first writes are resolved via the shared
|
|
84
|
+
* insert-then-catch-unique-violation pattern (see `queue_health`).
|
|
85
|
+
*/
|
|
86
|
+
async patch({ orgId, userId, patch, fillIfUnset }) {
|
|
87
|
+
const now = /* @__PURE__ */ new Date();
|
|
88
|
+
const updateExisting = () => this.#db.updateAtomic("memory_settings", {
|
|
89
|
+
org_id: orgId,
|
|
90
|
+
user_id: userId
|
|
91
|
+
}, (row) => {
|
|
92
|
+
const columns = {
|
|
93
|
+
...patchToColumns(patch),
|
|
94
|
+
updated_at: now
|
|
95
|
+
};
|
|
96
|
+
if (fillIfUnset?.observerModelId !== void 0 && row.observer_model_id == null) columns.observer_model_id = patch.observerModelId ?? fillIfUnset.observerModelId;
|
|
97
|
+
if (fillIfUnset?.reflectorModelId !== void 0 && row.reflector_model_id == null) columns.reflector_model_id = patch.reflectorModelId ?? fillIfUnset.reflectorModelId;
|
|
98
|
+
return columns;
|
|
99
|
+
});
|
|
100
|
+
const updated = await updateExisting();
|
|
101
|
+
if (updated) return toRecord(updated);
|
|
102
|
+
try {
|
|
103
|
+
return toRecord(await this.#db.insertOne("memory_settings", {
|
|
104
|
+
org_id: orgId,
|
|
105
|
+
user_id: userId,
|
|
106
|
+
observer_model_id: fillIfUnset?.observerModelId ?? null,
|
|
107
|
+
reflector_model_id: fillIfUnset?.reflectorModelId ?? null,
|
|
108
|
+
observation_threshold: null,
|
|
109
|
+
reflection_threshold: null,
|
|
110
|
+
observe_attachments: null,
|
|
111
|
+
...patchToColumns(patch),
|
|
112
|
+
created_at: now,
|
|
113
|
+
updated_at: now
|
|
114
|
+
}));
|
|
115
|
+
} catch (error) {
|
|
116
|
+
if (!(error instanceof UniqueViolationError)) throw error;
|
|
117
|
+
const row = await updateExisting();
|
|
118
|
+
if (!row) throw error;
|
|
119
|
+
return toRecord(row);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
110
122
|
};
|
|
123
|
+
//#endregion
|
|
124
|
+
export { MEMORY_SETTINGS_SCHEMA, MemorySettingsStorage };
|
|
125
|
+
|
|
111
126
|
//# sourceMappingURL=base.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/storage/domains/memory-settings/base.ts"],"sourcesContent":["import { FactoryStorageDomain, UniqueViolationError } from '@mastra/core/storage';\nimport type { CollectionSchema, FactoryStorageOps } from '@mastra/core/storage';\n\n/**\n * A user's persisted memory (observational-memory) configuration. The\n * DB-backed tenant counterpart of the local `settings.json` OM fields\n * (`observerModelOverride`, `reflectorModelOverride`, `omObservationThreshold`,\n * `omReflectionThreshold`, `omObserveAttachments`): one row per `(org, user)`,\n * every knob nullable so only explicitly-changed values are stored.\n */\nexport interface MemorySettingsRecord {\n orgId: string;\n userId: string;\n observerModelId: string | null;\n reflectorModelId: string | null;\n observationThreshold: number | null;\n reflectionThreshold: number | null;\n observeAttachments: 'auto' | boolean | null;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/** Partial update — only the provided knobs are written. */\nexport interface MemorySettingsPatch {\n observerModelId?: string;\n reflectorModelId?: string;\n observationThreshold?: number;\n reflectionThreshold?: number;\n observeAttachments?: 'auto' | boolean;\n}\n\n/**\n * Knobs written only when the stored value is still unset (`NULL`). The check\n * happens inside the backend's atomic-update primitive, so a concurrent\n * explicit write to the same knob is never clobbered by a fill.\n */\nexport interface MemorySettingsFillIfUnset {\n observerModelId?: string;\n reflectorModelId?: string;\n}\n\nexport const MEMORY_SETTINGS_SCHEMA: CollectionSchema = {\n name: 'memory_settings',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n user_id: { type: 'text' },\n observer_model_id: { type: 'text', nullable: true },\n reflector_model_id: { type: 'text', nullable: true },\n observation_threshold: { type: 'integer', nullable: true },\n reflection_threshold: { type: 'integer', nullable: true },\n // 'auto' | true | false — json keeps the tri-state without string encoding.\n observe_attachments: { type: 'json', nullable: true },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n uniqueIndexes: [{ name: 'memory_settings_org_user_key', columns: ['org_id', 'user_id'] }],\n};\n\ninterface MemorySettingsDbRow extends Record<string, unknown> {\n id: string;\n org_id: string;\n user_id: string;\n observer_model_id: string | null;\n reflector_model_id: string | null;\n observation_threshold: number | null;\n reflection_threshold: number | null;\n observe_attachments: 'auto' | boolean | null;\n created_at: Date;\n updated_at: Date;\n}\n\nfunction toRecord(row: MemorySettingsDbRow): MemorySettingsRecord {\n return {\n orgId: row.org_id,\n userId: row.user_id,\n observerModelId: row.observer_model_id,\n reflectorModelId: row.reflector_model_id,\n observationThreshold: row.observation_threshold,\n reflectionThreshold: row.reflection_threshold,\n observeAttachments: row.observe_attachments,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nfunction patchToColumns(patch: MemorySettingsPatch): Partial<MemorySettingsDbRow> {\n const columns: Partial<MemorySettingsDbRow> = {};\n if (patch.observerModelId !== undefined) columns.observer_model_id = patch.observerModelId;\n if (patch.reflectorModelId !== undefined) columns.reflector_model_id = patch.reflectorModelId;\n if (patch.observationThreshold !== undefined) columns.observation_threshold = patch.observationThreshold;\n if (patch.reflectionThreshold !== undefined) columns.reflection_threshold = patch.reflectionThreshold;\n if (patch.observeAttachments !== undefined) columns.observe_attachments = patch.observeAttachments;\n return columns;\n}\n\nexport class MemorySettingsStorage extends FactoryStorageDomain {\n constructor() {\n super('memory-settings');\n }\n\n async init(): Promise<void> {\n await this.ensureCollections([MEMORY_SETTINGS_SCHEMA]);\n }\n\n async dangerouslyClearAll(): Promise<void> {\n await this.ops.deleteMany('memory_settings', {});\n }\n\n get #db(): FactoryStorageOps {\n return this.ops;\n }\n\n async get({ orgId, userId }: { orgId: string; userId: string }): Promise<MemorySettingsRecord | null> {\n const row = await this.#db.findOne<MemorySettingsDbRow>('memory_settings', { org_id: orgId, user_id: userId });\n return row ? toRecord(row) : null;\n }\n\n /**\n * Upsert the user's row, writing only the knobs present in `patch`.\n * `fillIfUnset` knobs are written only where the stored value is still\n * `NULL`, decided inside the atomic update so concurrent explicit writes\n * win over fills. Concurrent first writes are resolved via the shared\n * insert-then-catch-unique-violation pattern (see `queue_health`).\n */\n async patch({\n orgId,\n userId,\n patch,\n fillIfUnset,\n }: {\n orgId: string;\n userId: string;\n patch: MemorySettingsPatch;\n fillIfUnset?: MemorySettingsFillIfUnset;\n }): Promise<MemorySettingsRecord> {\n const now = new Date();\n const updateExisting = () =>\n this.#db.updateAtomic<MemorySettingsDbRow>('memory_settings', { org_id: orgId, user_id: userId }, row => {\n const columns: Partial<MemorySettingsDbRow> = { ...patchToColumns(patch), updated_at: now };\n if (fillIfUnset?.observerModelId !== undefined && row.observer_model_id == null) {\n columns.observer_model_id = patch.observerModelId ?? fillIfUnset.observerModelId;\n }\n if (fillIfUnset?.reflectorModelId !== undefined && row.reflector_model_id == null) {\n columns.reflector_model_id = patch.reflectorModelId ?? fillIfUnset.reflectorModelId;\n }\n return columns;\n });\n\n const updated = await updateExisting();\n if (updated) return toRecord(updated);\n\n try {\n const row = await this.#db.insertOne<MemorySettingsDbRow>('memory_settings', {\n org_id: orgId,\n user_id: userId,\n observer_model_id: fillIfUnset?.observerModelId ?? null,\n reflector_model_id: fillIfUnset?.reflectorModelId ?? null,\n observation_threshold: null,\n reflection_threshold: null,\n observe_attachments: null,\n ...patchToColumns(patch),\n created_at: now,\n updated_at: now,\n });\n return toRecord(row);\n } catch (error) {\n if (!(error instanceof UniqueViolationError)) throw error;\n // Lost the first-write race — apply the patch to the winning row.\n const row = await updateExisting();\n if (!row) throw error;\n return toRecord(row);\n }\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"base.js","names":["#db"],"sources":["../../../../src/storage/domains/memory-settings/base.ts"],"sourcesContent":["import { FactoryStorageDomain, UniqueViolationError } from '@mastra/core/storage';\nimport type { CollectionSchema, FactoryStorageOps } from '@mastra/core/storage';\n\n/**\n * A user's persisted memory (observational-memory) configuration. The\n * DB-backed tenant counterpart of the local `settings.json` OM fields\n * (`observerModelOverride`, `reflectorModelOverride`, `omObservationThreshold`,\n * `omReflectionThreshold`, `omObserveAttachments`): one row per `(org, user)`,\n * every knob nullable so only explicitly-changed values are stored.\n */\nexport interface MemorySettingsRecord {\n orgId: string;\n userId: string;\n observerModelId: string | null;\n reflectorModelId: string | null;\n observationThreshold: number | null;\n reflectionThreshold: number | null;\n observeAttachments: 'auto' | boolean | null;\n createdAt: Date;\n updatedAt: Date;\n}\n\n/** Partial update — only the provided knobs are written. */\nexport interface MemorySettingsPatch {\n observerModelId?: string;\n reflectorModelId?: string;\n observationThreshold?: number;\n reflectionThreshold?: number;\n observeAttachments?: 'auto' | boolean;\n}\n\n/**\n * Knobs written only when the stored value is still unset (`NULL`). The check\n * happens inside the backend's atomic-update primitive, so a concurrent\n * explicit write to the same knob is never clobbered by a fill.\n */\nexport interface MemorySettingsFillIfUnset {\n observerModelId?: string;\n reflectorModelId?: string;\n}\n\nexport const MEMORY_SETTINGS_SCHEMA: CollectionSchema = {\n name: 'memory_settings',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n user_id: { type: 'text' },\n observer_model_id: { type: 'text', nullable: true },\n reflector_model_id: { type: 'text', nullable: true },\n observation_threshold: { type: 'integer', nullable: true },\n reflection_threshold: { type: 'integer', nullable: true },\n // 'auto' | true | false — json keeps the tri-state without string encoding.\n observe_attachments: { type: 'json', nullable: true },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n uniqueIndexes: [{ name: 'memory_settings_org_user_key', columns: ['org_id', 'user_id'] }],\n};\n\ninterface MemorySettingsDbRow extends Record<string, unknown> {\n id: string;\n org_id: string;\n user_id: string;\n observer_model_id: string | null;\n reflector_model_id: string | null;\n observation_threshold: number | null;\n reflection_threshold: number | null;\n observe_attachments: 'auto' | boolean | null;\n created_at: Date;\n updated_at: Date;\n}\n\nfunction toRecord(row: MemorySettingsDbRow): MemorySettingsRecord {\n return {\n orgId: row.org_id,\n userId: row.user_id,\n observerModelId: row.observer_model_id,\n reflectorModelId: row.reflector_model_id,\n observationThreshold: row.observation_threshold,\n reflectionThreshold: row.reflection_threshold,\n observeAttachments: row.observe_attachments,\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nfunction patchToColumns(patch: MemorySettingsPatch): Partial<MemorySettingsDbRow> {\n const columns: Partial<MemorySettingsDbRow> = {};\n if (patch.observerModelId !== undefined) columns.observer_model_id = patch.observerModelId;\n if (patch.reflectorModelId !== undefined) columns.reflector_model_id = patch.reflectorModelId;\n if (patch.observationThreshold !== undefined) columns.observation_threshold = patch.observationThreshold;\n if (patch.reflectionThreshold !== undefined) columns.reflection_threshold = patch.reflectionThreshold;\n if (patch.observeAttachments !== undefined) columns.observe_attachments = patch.observeAttachments;\n return columns;\n}\n\nexport class MemorySettingsStorage extends FactoryStorageDomain {\n constructor() {\n super('memory-settings');\n }\n\n async init(): Promise<void> {\n await this.ensureCollections([MEMORY_SETTINGS_SCHEMA]);\n }\n\n async dangerouslyClearAll(): Promise<void> {\n await this.ops.deleteMany('memory_settings', {});\n }\n\n get #db(): FactoryStorageOps {\n return this.ops;\n }\n\n async get({ orgId, userId }: { orgId: string; userId: string }): Promise<MemorySettingsRecord | null> {\n const row = await this.#db.findOne<MemorySettingsDbRow>('memory_settings', { org_id: orgId, user_id: userId });\n return row ? toRecord(row) : null;\n }\n\n /**\n * Upsert the user's row, writing only the knobs present in `patch`.\n * `fillIfUnset` knobs are written only where the stored value is still\n * `NULL`, decided inside the atomic update so concurrent explicit writes\n * win over fills. Concurrent first writes are resolved via the shared\n * insert-then-catch-unique-violation pattern (see `queue_health`).\n */\n async patch({\n orgId,\n userId,\n patch,\n fillIfUnset,\n }: {\n orgId: string;\n userId: string;\n patch: MemorySettingsPatch;\n fillIfUnset?: MemorySettingsFillIfUnset;\n }): Promise<MemorySettingsRecord> {\n const now = new Date();\n const updateExisting = () =>\n this.#db.updateAtomic<MemorySettingsDbRow>('memory_settings', { org_id: orgId, user_id: userId }, row => {\n const columns: Partial<MemorySettingsDbRow> = { ...patchToColumns(patch), updated_at: now };\n if (fillIfUnset?.observerModelId !== undefined && row.observer_model_id == null) {\n columns.observer_model_id = patch.observerModelId ?? fillIfUnset.observerModelId;\n }\n if (fillIfUnset?.reflectorModelId !== undefined && row.reflector_model_id == null) {\n columns.reflector_model_id = patch.reflectorModelId ?? fillIfUnset.reflectorModelId;\n }\n return columns;\n });\n\n const updated = await updateExisting();\n if (updated) return toRecord(updated);\n\n try {\n const row = await this.#db.insertOne<MemorySettingsDbRow>('memory_settings', {\n org_id: orgId,\n user_id: userId,\n observer_model_id: fillIfUnset?.observerModelId ?? null,\n reflector_model_id: fillIfUnset?.reflectorModelId ?? null,\n observation_threshold: null,\n reflection_threshold: null,\n observe_attachments: null,\n ...patchToColumns(patch),\n created_at: now,\n updated_at: now,\n });\n return toRecord(row);\n } catch (error) {\n if (!(error instanceof UniqueViolationError)) throw error;\n // Lost the first-write race — apply the patch to the winning row.\n const row = await updateExisting();\n if (!row) throw error;\n return toRecord(row);\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,95 +1,96 @@
|
|
|
1
|
-
// src/storage/domains/model-packs/base.ts
|
|
2
1
|
import { FactoryStorageDomain } from "@mastra/core/storage";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
2
|
+
//#region src/storage/domains/model-packs/base.ts
|
|
3
|
+
const MODEL_PACKS_SCHEMA = {
|
|
4
|
+
name: "model_packs",
|
|
5
|
+
columns: {
|
|
6
|
+
id: { type: "uuid-pk" },
|
|
7
|
+
org_id: { type: "text" },
|
|
8
|
+
created_by: { type: "text" },
|
|
9
|
+
name: { type: "text" },
|
|
10
|
+
build_model_id: { type: "text" },
|
|
11
|
+
plan_model_id: { type: "text" },
|
|
12
|
+
fast_model_id: { type: "text" },
|
|
13
|
+
created_at: { type: "timestamp" },
|
|
14
|
+
updated_at: { type: "timestamp" }
|
|
15
|
+
},
|
|
16
|
+
indexes: [{
|
|
17
|
+
name: "model_packs_org_name_idx",
|
|
18
|
+
columns: ["org_id", "name"]
|
|
19
|
+
}]
|
|
17
20
|
};
|
|
18
21
|
function toModelPack(row) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
return {
|
|
23
|
+
id: row.id,
|
|
24
|
+
orgId: row.org_id,
|
|
25
|
+
createdBy: row.created_by,
|
|
26
|
+
name: row.name,
|
|
27
|
+
models: {
|
|
28
|
+
build: row.build_model_id,
|
|
29
|
+
plan: row.plan_model_id,
|
|
30
|
+
fast: row.fast_model_id
|
|
31
|
+
},
|
|
32
|
+
createdAt: row.created_at,
|
|
33
|
+
updatedAt: row.updated_at
|
|
34
|
+
};
|
|
28
35
|
}
|
|
29
36
|
var ModelPacksStorage = class extends FactoryStorageDomain {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return row ? toModelPack(row) : null;
|
|
86
|
-
}
|
|
87
|
-
async delete({ orgId, id }) {
|
|
88
|
-
return await this.#db.deleteMany("model_packs", { org_id: orgId, id }) > 0;
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
export {
|
|
92
|
-
MODEL_PACKS_SCHEMA,
|
|
93
|
-
ModelPacksStorage
|
|
37
|
+
constructor() {
|
|
38
|
+
super("model-packs");
|
|
39
|
+
}
|
|
40
|
+
async init() {
|
|
41
|
+
await this.ensureCollections([MODEL_PACKS_SCHEMA]);
|
|
42
|
+
}
|
|
43
|
+
async dangerouslyClearAll() {
|
|
44
|
+
await this.ops.deleteMany("model_packs", {});
|
|
45
|
+
}
|
|
46
|
+
get #db() {
|
|
47
|
+
return this.ops;
|
|
48
|
+
}
|
|
49
|
+
/** Create or replace a pack by `(orgId, name)` — mirrors the settings.json upsert semantics. */
|
|
50
|
+
async upsert({ orgId, userId, input }) {
|
|
51
|
+
const now = /* @__PURE__ */ new Date();
|
|
52
|
+
const existing = await this.#db.findOne("model_packs", {
|
|
53
|
+
org_id: orgId,
|
|
54
|
+
name: input.name
|
|
55
|
+
});
|
|
56
|
+
if (existing) return toModelPack(await this.#db.updateAtomic("model_packs", {
|
|
57
|
+
org_id: orgId,
|
|
58
|
+
id: existing.id
|
|
59
|
+
}, () => ({
|
|
60
|
+
build_model_id: input.models.build,
|
|
61
|
+
plan_model_id: input.models.plan,
|
|
62
|
+
fast_model_id: input.models.fast,
|
|
63
|
+
updated_at: now
|
|
64
|
+
})) ?? existing);
|
|
65
|
+
return toModelPack(await this.#db.insertOne("model_packs", {
|
|
66
|
+
org_id: orgId,
|
|
67
|
+
created_by: userId,
|
|
68
|
+
name: input.name,
|
|
69
|
+
build_model_id: input.models.build,
|
|
70
|
+
plan_model_id: input.models.plan,
|
|
71
|
+
fast_model_id: input.models.fast,
|
|
72
|
+
created_at: now,
|
|
73
|
+
updated_at: now
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
async list({ orgId }) {
|
|
77
|
+
return (await this.#db.findMany("model_packs", { org_id: orgId }, { orderBy: [["name", "asc"]] })).map(toModelPack);
|
|
78
|
+
}
|
|
79
|
+
async get({ orgId, id }) {
|
|
80
|
+
const row = await this.#db.findOne("model_packs", {
|
|
81
|
+
org_id: orgId,
|
|
82
|
+
id
|
|
83
|
+
});
|
|
84
|
+
return row ? toModelPack(row) : null;
|
|
85
|
+
}
|
|
86
|
+
async delete({ orgId, id }) {
|
|
87
|
+
return await this.#db.deleteMany("model_packs", {
|
|
88
|
+
org_id: orgId,
|
|
89
|
+
id
|
|
90
|
+
}) > 0;
|
|
91
|
+
}
|
|
94
92
|
};
|
|
93
|
+
//#endregion
|
|
94
|
+
export { MODEL_PACKS_SCHEMA, ModelPacksStorage };
|
|
95
|
+
|
|
95
96
|
//# sourceMappingURL=base.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/storage/domains/model-packs/base.ts"],"sourcesContent":["import { FactoryStorageDomain } from '@mastra/core/storage';\nimport type { CollectionSchema, FactoryStorageOps } from '@mastra/core/storage';\n\n/** A saved custom model pack: one model per mode (build / plan / fast). */\nexport interface ModelPackRecord {\n id: string;\n orgId: string;\n createdBy: string;\n name: string;\n models: { build: string; plan: string; fast: string };\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface UpsertModelPackInput {\n name: string;\n models: { build: string; plan: string; fast: string };\n}\n\nexport const MODEL_PACKS_SCHEMA: CollectionSchema = {\n name: 'model_packs',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n created_by: { type: 'text' },\n name: { type: 'text' },\n build_model_id: { type: 'text' },\n plan_model_id: { type: 'text' },\n fast_model_id: { type: 'text' },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n indexes: [{ name: 'model_packs_org_name_idx', columns: ['org_id', 'name'] }],\n};\n\ninterface ModelPackDbRow extends Record<string, unknown> {\n id: string;\n org_id: string;\n created_by: string;\n name: string;\n build_model_id: string;\n plan_model_id: string;\n fast_model_id: string;\n created_at: Date;\n updated_at: Date;\n}\n\nfunction toModelPack(row: ModelPackDbRow): ModelPackRecord {\n return {\n id: row.id,\n orgId: row.org_id,\n createdBy: row.created_by,\n name: row.name,\n models: { build: row.build_model_id, plan: row.plan_model_id, fast: row.fast_model_id },\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nexport class ModelPacksStorage extends FactoryStorageDomain {\n constructor() {\n super('model-packs');\n }\n\n async init(): Promise<void> {\n await this.ensureCollections([MODEL_PACKS_SCHEMA]);\n }\n\n async dangerouslyClearAll(): Promise<void> {\n await this.ops.deleteMany('model_packs', {});\n }\n\n get #db(): FactoryStorageOps {\n return this.ops;\n }\n\n /** Create or replace a pack by `(orgId, name)` — mirrors the settings.json upsert semantics. */\n async upsert({\n orgId,\n userId,\n input,\n }: {\n orgId: string;\n userId: string;\n input: UpsertModelPackInput;\n }): Promise<ModelPackRecord> {\n const now = new Date();\n const existing = await this.#db.findOne<ModelPackDbRow>('model_packs', { org_id: orgId, name: input.name });\n if (existing) {\n const row = await this.#db.updateAtomic<ModelPackDbRow>(\n 'model_packs',\n { org_id: orgId, id: existing.id },\n () => ({\n build_model_id: input.models.build,\n plan_model_id: input.models.plan,\n fast_model_id: input.models.fast,\n updated_at: now,\n }),\n );\n return toModelPack(row ?? existing);\n }\n const row = await this.#db.insertOne<ModelPackDbRow>('model_packs', {\n org_id: orgId,\n created_by: userId,\n name: input.name,\n build_model_id: input.models.build,\n plan_model_id: input.models.plan,\n fast_model_id: input.models.fast,\n created_at: now,\n updated_at: now,\n });\n return toModelPack(row);\n }\n\n async list({ orgId }: { orgId: string }): Promise<ModelPackRecord[]> {\n const rows = await this.#db.findMany<ModelPackDbRow>(\n 'model_packs',\n { org_id: orgId },\n { orderBy: [['name', 'asc']] },\n );\n return rows.map(toModelPack);\n }\n\n async get({ orgId, id }: { orgId: string; id: string }): Promise<ModelPackRecord | null> {\n const row = await this.#db.findOne<ModelPackDbRow>('model_packs', { org_id: orgId, id });\n return row ? toModelPack(row) : null;\n }\n\n async delete({ orgId, id }: { orgId: string; id: string }): Promise<boolean> {\n return (await this.#db.deleteMany('model_packs', { org_id: orgId, id })) > 0;\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"base.js","names":["#db"],"sources":["../../../../src/storage/domains/model-packs/base.ts"],"sourcesContent":["import { FactoryStorageDomain } from '@mastra/core/storage';\nimport type { CollectionSchema, FactoryStorageOps } from '@mastra/core/storage';\n\n/** A saved custom model pack: one model per mode (build / plan / fast). */\nexport interface ModelPackRecord {\n id: string;\n orgId: string;\n createdBy: string;\n name: string;\n models: { build: string; plan: string; fast: string };\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport interface UpsertModelPackInput {\n name: string;\n models: { build: string; plan: string; fast: string };\n}\n\nexport const MODEL_PACKS_SCHEMA: CollectionSchema = {\n name: 'model_packs',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n created_by: { type: 'text' },\n name: { type: 'text' },\n build_model_id: { type: 'text' },\n plan_model_id: { type: 'text' },\n fast_model_id: { type: 'text' },\n created_at: { type: 'timestamp' },\n updated_at: { type: 'timestamp' },\n },\n indexes: [{ name: 'model_packs_org_name_idx', columns: ['org_id', 'name'] }],\n};\n\ninterface ModelPackDbRow extends Record<string, unknown> {\n id: string;\n org_id: string;\n created_by: string;\n name: string;\n build_model_id: string;\n plan_model_id: string;\n fast_model_id: string;\n created_at: Date;\n updated_at: Date;\n}\n\nfunction toModelPack(row: ModelPackDbRow): ModelPackRecord {\n return {\n id: row.id,\n orgId: row.org_id,\n createdBy: row.created_by,\n name: row.name,\n models: { build: row.build_model_id, plan: row.plan_model_id, fast: row.fast_model_id },\n createdAt: row.created_at,\n updatedAt: row.updated_at,\n };\n}\n\nexport class ModelPacksStorage extends FactoryStorageDomain {\n constructor() {\n super('model-packs');\n }\n\n async init(): Promise<void> {\n await this.ensureCollections([MODEL_PACKS_SCHEMA]);\n }\n\n async dangerouslyClearAll(): Promise<void> {\n await this.ops.deleteMany('model_packs', {});\n }\n\n get #db(): FactoryStorageOps {\n return this.ops;\n }\n\n /** Create or replace a pack by `(orgId, name)` — mirrors the settings.json upsert semantics. */\n async upsert({\n orgId,\n userId,\n input,\n }: {\n orgId: string;\n userId: string;\n input: UpsertModelPackInput;\n }): Promise<ModelPackRecord> {\n const now = new Date();\n const existing = await this.#db.findOne<ModelPackDbRow>('model_packs', { org_id: orgId, name: input.name });\n if (existing) {\n const row = await this.#db.updateAtomic<ModelPackDbRow>(\n 'model_packs',\n { org_id: orgId, id: existing.id },\n () => ({\n build_model_id: input.models.build,\n plan_model_id: input.models.plan,\n fast_model_id: input.models.fast,\n updated_at: now,\n }),\n );\n return toModelPack(row ?? existing);\n }\n const row = await this.#db.insertOne<ModelPackDbRow>('model_packs', {\n org_id: orgId,\n created_by: userId,\n name: input.name,\n build_model_id: input.models.build,\n plan_model_id: input.models.plan,\n fast_model_id: input.models.fast,\n created_at: now,\n updated_at: now,\n });\n return toModelPack(row);\n }\n\n async list({ orgId }: { orgId: string }): Promise<ModelPackRecord[]> {\n const rows = await this.#db.findMany<ModelPackDbRow>(\n 'model_packs',\n { org_id: orgId },\n { orderBy: [['name', 'asc']] },\n );\n return rows.map(toModelPack);\n }\n\n async get({ orgId, id }: { orgId: string; id: string }): Promise<ModelPackRecord | null> {\n const row = await this.#db.findOne<ModelPackDbRow>('model_packs', { org_id: orgId, id });\n return row ? toModelPack(row) : null;\n }\n\n async delete({ orgId, id }: { orgId: string; id: string }): Promise<boolean> {\n return (await this.#db.deleteMany('model_packs', { org_id: orgId, id })) > 0;\n }\n}\n"],"mappings":";;AAmBA,MAAa,qBAAuC;CAClD,MAAM;CACN,SAAS;EACP,IAAI,EAAE,MAAM,UAAU;EACtB,QAAQ,EAAE,MAAM,OAAO;EACvB,YAAY,EAAE,MAAM,OAAO;EAC3B,MAAM,EAAE,MAAM,OAAO;EACrB,gBAAgB,EAAE,MAAM,OAAO;EAC/B,eAAe,EAAE,MAAM,OAAO;EAC9B,eAAe,EAAE,MAAM,OAAO;EAC9B,YAAY,EAAE,MAAM,YAAY;EAChC,YAAY,EAAE,MAAM,YAAY;CAClC;CACA,SAAS,CAAC;EAAE,MAAM;EAA4B,SAAS,CAAC,UAAU,MAAM;CAAE,CAAC;AAC7E;AAcA,SAAS,YAAY,KAAsC;CACzD,OAAO;EACL,IAAI,IAAI;EACR,OAAO,IAAI;EACX,WAAW,IAAI;EACf,MAAM,IAAI;EACV,QAAQ;GAAE,OAAO,IAAI;GAAgB,MAAM,IAAI;GAAe,MAAM,IAAI;EAAc;EACtF,WAAW,IAAI;EACf,WAAW,IAAI;CACjB;AACF;AAEA,IAAa,oBAAb,cAAuC,qBAAqB;CAC1D,cAAc;EACZ,MAAM,aAAa;CACrB;CAEA,MAAM,OAAsB;EAC1B,MAAM,KAAK,kBAAkB,CAAC,kBAAkB,CAAC;CACnD;CAEA,MAAM,sBAAqC;EACzC,MAAM,KAAK,IAAI,WAAW,eAAe,CAAC,CAAC;CAC7C;CAEA,IAAIA,MAAyB;EAC3B,OAAO,KAAK;CACd;;CAGA,MAAM,OAAO,EACX,OACA,QACA,SAK2B;EAC3B,MAAM,sBAAM,IAAI,KAAK;EACrB,MAAM,WAAW,MAAM,KAAKA,IAAI,QAAwB,eAAe;GAAE,QAAQ;GAAO,MAAM,MAAM;EAAK,CAAC;EAC1G,IAAI,UAWF,OAAO,YAAY,MAVD,KAAKA,IAAI,aACzB,eACA;GAAE,QAAQ;GAAO,IAAI,SAAS;EAAG,UAC1B;GACL,gBAAgB,MAAM,OAAO;GAC7B,eAAe,MAAM,OAAO;GAC5B,eAAe,MAAM,OAAO;GAC5B,YAAY;EACd,EACF,KAC0B,QAAQ;EAYpC,OAAO,YAAY,MAVD,KAAKA,IAAI,UAA0B,eAAe;GAClE,QAAQ;GACR,YAAY;GACZ,MAAM,MAAM;GACZ,gBAAgB,MAAM,OAAO;GAC7B,eAAe,MAAM,OAAO;GAC5B,eAAe,MAAM,OAAO;GAC5B,YAAY;GACZ,YAAY;EACd,CAAC,CACqB;CACxB;CAEA,MAAM,KAAK,EAAE,SAAwD;EAMnE,QAAO,MALY,KAAKA,IAAI,SAC1B,eACA,EAAE,QAAQ,MAAM,GAChB,EAAE,SAAS,CAAC,CAAC,QAAQ,KAAK,CAAC,EAAE,CAC/B,EAAA,CACY,IAAI,WAAW;CAC7B;CAEA,MAAM,IAAI,EAAE,OAAO,MAAsE;EACvF,MAAM,MAAM,MAAM,KAAKA,IAAI,QAAwB,eAAe;GAAE,QAAQ;GAAO;EAAG,CAAC;EACvF,OAAO,MAAM,YAAY,GAAG,IAAI;CAClC;CAEA,MAAM,OAAO,EAAE,OAAO,MAAuD;EAC3E,OAAQ,MAAM,KAAKA,IAAI,WAAW,eAAe;GAAE,QAAQ;GAAO;EAAG,CAAC,IAAK;CAC7E;AACF"}
|