@mastra/factory 0.19.2-alpha.7 → 0.20.0-alpha.10
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/dist/factory.js +7 -7
- package/dist/factory.js.map +1 -1
- package/dist/integrations/base.d.ts +5 -5
- package/dist/integrations/base.d.ts.map +1 -1
- package/dist/integrations/github/default-rules.d.ts +4 -4
- package/dist/integrations/github/default-rules.d.ts.map +1 -1
- package/dist/integrations/github/default-rules.js +13 -2
- package/dist/integrations/github/default-rules.js.map +1 -1
- package/dist/integrations/github/integration.js +1 -1
- package/dist/integrations/github/provenance.d.ts.map +1 -1
- package/dist/integrations/github/provenance.js +2 -1
- package/dist/integrations/github/provenance.js.map +1 -1
- package/dist/integrations/github/routes.d.ts.map +1 -1
- package/dist/integrations/github/routes.js +3 -1
- package/dist/integrations/github/routes.js.map +1 -1
- package/dist/integrations/github/rules.d.ts +8 -0
- package/dist/integrations/github/rules.d.ts.map +1 -1
- package/dist/integrations/github/rules.js +2 -2
- package/dist/integrations/github/rules.js.map +1 -1
- package/dist/integrations/github/session-subscriptions.js +1 -1
- package/dist/integrations/platform/github/integration.js +1 -1
- package/dist/integrations/slack/integration.js +1 -1
- package/dist/integrations/slack/integration.js.map +1 -1
- package/dist/integrations/slack/slack.d.ts +10 -11
- package/dist/integrations/slack/slack.d.ts.map +1 -1
- package/dist/integrations/slack/slack.js +36 -37
- package/dist/integrations/slack/slack.js.map +1 -1
- package/dist/routes/config.d.ts +15 -61
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +40 -217
- package/dist/routes/config.js.map +1 -1
- package/dist/routes/projects.d.ts.map +1 -1
- package/dist/routes/projects.js +2 -17
- package/dist/routes/projects.js.map +1 -1
- package/dist/routes/surface.d.ts +4 -4
- package/dist/routes/surface.d.ts.map +1 -1
- package/dist/routes/surface.js +3 -3
- package/dist/routes/surface.js.map +1 -1
- package/dist/session/default-model-hydration.d.ts +40 -0
- package/dist/session/default-model-hydration.d.ts.map +1 -0
- package/dist/session/default-model-hydration.js +45 -0
- package/dist/session/default-model-hydration.js.map +1 -0
- package/dist/session/factory-session.js +1 -1
- package/dist/session/factory-session.js.map +1 -1
- package/dist/storage/domains/model-defaults/base.d.ts +29 -0
- package/dist/storage/domains/model-defaults/base.d.ts.map +1 -0
- package/dist/storage/domains/model-defaults/base.js +79 -0
- package/dist/storage/domains/model-defaults/base.js.map +1 -0
- package/package.json +8 -8
- package/dist/session/model-pack-hydration.d.ts +0 -55
- package/dist/session/model-pack-hydration.d.ts.map +0 -1
- package/dist/session/model-pack-hydration.js +0 -56
- package/dist/session/model-pack-hydration.js.map +0 -1
- package/dist/storage/domains/model-packs/base.d.ts +0 -75
- package/dist/storage/domains/model-packs/base.d.ts.map +0 -1
- package/dist/storage/domains/model-packs/base.js +0 -185
- package/dist/storage/domains/model-packs/base.js.map +0 -1
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
//#region src/session/default-model-hydration.ts
|
|
2
|
+
async function applyDefaultModel(session, modelId) {
|
|
3
|
+
await session.model.switch(modelId);
|
|
4
|
+
for (const agentType of [
|
|
5
|
+
"explore",
|
|
6
|
+
"plan",
|
|
7
|
+
"execute"
|
|
8
|
+
]) await session.subagents.model.set({
|
|
9
|
+
modelId,
|
|
10
|
+
agentType
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
/** Seed the user's default model unless the interactive thread already selected its own model. */
|
|
14
|
+
async function hydrateSessionDefaultModel(session, { sourceControl, workItems, modelDefaults }) {
|
|
15
|
+
const resourceId = session.identity.getResourceId();
|
|
16
|
+
if (session.state.get()?.factoryProjectId || typeof session.thread.getSetting !== "function") return;
|
|
17
|
+
try {
|
|
18
|
+
const sourceSession = await sourceControl.sessions.getBySessionId(resourceId);
|
|
19
|
+
if (!sourceSession) return;
|
|
20
|
+
const threadId = session.thread.getId();
|
|
21
|
+
if (threadId && await workItems.findActiveRunBindingByThread({
|
|
22
|
+
orgId: sourceSession.orgId,
|
|
23
|
+
threadId,
|
|
24
|
+
resourceId,
|
|
25
|
+
sessionId: resourceId
|
|
26
|
+
})) return;
|
|
27
|
+
if ((await Promise.all([
|
|
28
|
+
session.thread.getSetting({ key: "currentModelId" }),
|
|
29
|
+
session.thread.getSetting({ key: "modeModelId_build" }),
|
|
30
|
+
session.thread.getSetting({ key: "modeModelId_plan" }),
|
|
31
|
+
session.thread.getSetting({ key: "modeModelId_fast" })
|
|
32
|
+
])).some((setting) => typeof setting === "string")) return;
|
|
33
|
+
const modelDefault = await modelDefaults.get({
|
|
34
|
+
orgId: sourceSession.orgId,
|
|
35
|
+
userId: sourceSession.userId
|
|
36
|
+
});
|
|
37
|
+
if (modelDefault) await applyDefaultModel(session, modelDefault.modelId);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.warn("[Factory default-model hydration] Unable to apply the user default model.", error);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { hydrateSessionDefaultModel };
|
|
44
|
+
|
|
45
|
+
//# sourceMappingURL=default-model-hydration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-model-hydration.js","names":[],"sources":["../../src/session/default-model-hydration.ts"],"sourcesContent":["import type { ModelDefaultsStorage } from '../storage/domains/model-defaults/base.js';\nimport type { SourceControlStorageHandle } from '../storage/domains/source-control/base.js';\nimport type { WorkItemsStorage } from '../storage/domains/work-items/base.js';\n\nexport interface DefaultModelApplicableSession {\n model: { switch(modelId: string): Promise<unknown> };\n subagents: { model: { set(args: { modelId: string; agentType: string }): Promise<unknown> } };\n}\n\nexport interface DefaultModelHydrationSession extends DefaultModelApplicableSession {\n readonly identity: { getResourceId(): string };\n state: { get(): Record<string, unknown> | undefined };\n thread: {\n getId(): string | null | undefined;\n getSetting(args: { key: string }): Promise<unknown>;\n };\n}\n\nasync function applyDefaultModel(session: DefaultModelApplicableSession, modelId: string): Promise<void> {\n await session.model.switch(modelId);\n\n for (const agentType of ['explore', 'plan', 'execute']) {\n await session.subagents.model.set({ modelId, agentType });\n }\n}\n\nexport interface DefaultModelHydrationDependencies {\n sourceControl: {\n sessions: Pick<SourceControlStorageHandle['sessions'], 'getBySessionId'>;\n };\n workItems: Pick<WorkItemsStorage, 'findActiveRunBindingByThread'>;\n modelDefaults: Pick<ModelDefaultsStorage, 'get'>;\n}\n\n/** Seed the user's default model unless the interactive thread already selected its own model. */\nexport async function hydrateSessionDefaultModel(\n session: DefaultModelHydrationSession,\n { sourceControl, workItems, modelDefaults }: DefaultModelHydrationDependencies,\n): Promise<void> {\n const resourceId = session.identity.getResourceId();\n if (session.state.get()?.factoryProjectId || typeof session.thread.getSetting !== 'function') return;\n try {\n const sourceSession = await sourceControl.sessions.getBySessionId(resourceId);\n if (!sourceSession) return;\n const threadId = session.thread.getId();\n if (\n threadId &&\n (await workItems.findActiveRunBindingByThread({\n orgId: sourceSession.orgId,\n threadId,\n resourceId,\n sessionId: resourceId,\n }))\n ) {\n return;\n }\n const existingThreadSettings = await Promise.all([\n session.thread.getSetting({ key: 'currentModelId' }),\n session.thread.getSetting({ key: 'modeModelId_build' }),\n session.thread.getSetting({ key: 'modeModelId_plan' }),\n session.thread.getSetting({ key: 'modeModelId_fast' }),\n ]);\n if (existingThreadSettings.some(setting => typeof setting === 'string')) return;\n\n const modelDefault = await modelDefaults.get({ orgId: sourceSession.orgId, userId: sourceSession.userId });\n if (modelDefault) await applyDefaultModel(session, modelDefault.modelId);\n } catch (error) {\n console.warn('[Factory default-model hydration] Unable to apply the user default model.', error);\n }\n}\n"],"mappings":";AAkBA,eAAe,kBAAkB,SAAwC,SAAgC;CACvG,MAAM,QAAQ,MAAM,OAAO,OAAO;CAElC,KAAK,MAAM,aAAa;EAAC;EAAW;EAAQ;CAAS,GACnD,MAAM,QAAQ,UAAU,MAAM,IAAI;EAAE;EAAS;CAAU,CAAC;AAE5D;;AAWA,eAAsB,2BACpB,SACA,EAAE,eAAe,WAAW,iBACb;CACf,MAAM,aAAa,QAAQ,SAAS,cAAc;CAClD,IAAI,QAAQ,MAAM,IAAI,CAAC,EAAE,oBAAoB,OAAO,QAAQ,OAAO,eAAe,YAAY;CAC9F,IAAI;EACF,MAAM,gBAAgB,MAAM,cAAc,SAAS,eAAe,UAAU;EAC5E,IAAI,CAAC,eAAe;EACpB,MAAM,WAAW,QAAQ,OAAO,MAAM;EACtC,IACE,YACC,MAAM,UAAU,6BAA6B;GAC5C,OAAO,cAAc;GACrB;GACA;GACA,WAAW;EACb,CAAC,GAED;EAQF,KAAI,MANiC,QAAQ,IAAI;GAC/C,QAAQ,OAAO,WAAW,EAAE,KAAK,iBAAiB,CAAC;GACnD,QAAQ,OAAO,WAAW,EAAE,KAAK,oBAAoB,CAAC;GACtD,QAAQ,OAAO,WAAW,EAAE,KAAK,mBAAmB,CAAC;GACrD,QAAQ,OAAO,WAAW,EAAE,KAAK,mBAAmB,CAAC;EACvD,CAAC,EAAA,CAC0B,MAAK,YAAW,OAAO,YAAY,QAAQ,GAAG;EAEzE,MAAM,eAAe,MAAM,cAAc,IAAI;GAAE,OAAO,cAAc;GAAO,QAAQ,cAAc;EAAO,CAAC;EACzG,IAAI,cAAc,MAAM,kBAAkB,SAAS,aAAa,OAAO;CACzE,SAAS,OAAO;EACd,QAAQ,KAAK,6EAA6E,KAAK;CACjG;AACF"}
|
|
@@ -227,7 +227,7 @@ async function hydrateFactorySession(session, args) {
|
|
|
227
227
|
}
|
|
228
228
|
if (args.defaultModelId) {
|
|
229
229
|
try {
|
|
230
|
-
await session.model.switch(
|
|
230
|
+
await session.model.switch(args.defaultModelId);
|
|
231
231
|
} catch (error) {
|
|
232
232
|
console.warn("[Factory Start] Failed to apply factory default model", {
|
|
233
233
|
modelId: args.defaultModelId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory-session.js","names":[],"sources":["../../src/session/factory-session.ts"],"sourcesContent":["import { resolveProviderOMDefault } from '@mastra/code-sdk/onboarding/packs';\nimport type { MastraCodeState } from '@mastra/code-sdk/schema';\nimport type { AgentController } from '@mastra/core/agent-controller';\n\nimport { factoryMemorySettingsUserId } from '../storage/domains/memory-settings/base.js';\nimport type { MemorySettingsStorage } from '../storage/domains/memory-settings/base.js';\nimport type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';\nimport {\n SourceControlConnectionNotFoundError,\n type SourceControlSession,\n type SourceControlStorageHandle,\n} from '../storage/domains/source-control/base.js';\nimport { applyStoredMemorySettings, type OMConfigurableSession } from './memory-settings-hydration.js';\nimport { seedSessionOrg } from './org-seed.js';\n\ntype FactorySession = Awaited<ReturnType<AgentController<MastraCodeState>['createSession']>>;\n\nexport class FactorySourceControlConflictError extends Error {}\n\n/**\n * Read the factory project's default model. Best-effort: a missing project or an\n * uninitialized storage domain means \"no default\", never a failed run.\n */\nexport async function resolveFactoryDefaultModelId(\n projects: FactoryProjectsStorage | undefined,\n factoryProjectId: string | undefined,\n): Promise<string | undefined> {\n if (!projects || !factoryProjectId) return undefined;\n try {\n const project = await projects.getById({ id: factoryProjectId });\n return project?.defaultModelId ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nexport interface SourceControlSessionLookup {\n getBySessionId(sessionId: string): Promise<SourceControlSession | null>;\n getSourceControlBySessionId(sessionId: string): Promise<SourceControlStorageHandle | null>;\n rename(args: { sessionId: string; title: string }): Promise<void>;\n markFirstMessage(args: { sessionId: string }): Promise<void>;\n markFirstMeaningfulExec(args: { sessionId: string }): Promise<void>;\n}\n\n/**\n * Read or update a session across every registered source-control partition.\n * Session ids are globally generated, so more than one match is invalid and\n * fails closed instead of mutating an arbitrary provider.\n */\nexport function createSourceControlSessionLookup(\n sourceControls: readonly SourceControlStorageHandle[],\n): SourceControlSessionLookup {\n const resolve = async (\n sessionId: string,\n ): Promise<{ sourceControl: SourceControlStorageHandle; session: SourceControlSession } | null> => {\n const matches = (\n await Promise.all(\n sourceControls.map(async sourceControl => ({\n sourceControl,\n session: await sourceControl.sessions.getBySessionId(sessionId),\n })),\n )\n ).filter(\n (match): match is { sourceControl: SourceControlStorageHandle; session: SourceControlSession } =>\n match.session !== null,\n );\n if (matches.length > 1) throw new Error('Factory session exists in multiple source-control providers.');\n return matches[0] ?? null;\n };\n\n return {\n getBySessionId: async sessionId => (await resolve(sessionId))?.session ?? null,\n getSourceControlBySessionId: async sessionId => (await resolve(sessionId))?.sourceControl ?? null,\n rename: async args => (await resolve(args.sessionId))?.sourceControl.sessions.rename(args),\n markFirstMessage: async args => (await resolve(args.sessionId))?.sourceControl.sessions.markFirstMessage(args),\n markFirstMeaningfulExec: async args =>\n (await resolve(args.sessionId))?.sourceControl.sessions.markFirstMeaningfulExec(args),\n };\n}\n\n/**\n * Resolve the source-control provider from durable Factory repository links,\n * never from the issue tracker that happened to create the work item.\n */\nexport async function resolveFactorySourceControl(args: {\n sourceControls: readonly SourceControlStorageHandle[];\n orgId: string;\n factoryProjectId: string;\n sessionId?: string;\n}): Promise<SourceControlStorageHandle | undefined> {\n if (args.sessionId) {\n const sessionMatches = (\n await Promise.all(\n args.sourceControls.map(async sourceControl => ({\n sourceControl,\n session: await sourceControl.sessions.getBySessionId(args.sessionId!),\n })),\n )\n ).filter(match => match.session !== null);\n if (sessionMatches.length > 1) throw new Error('Factory session exists in multiple source-control providers.');\n if (sessionMatches[0]) return sessionMatches[0].sourceControl;\n }\n\n const linked = [];\n for (const sourceControl of args.sourceControls) {\n const connections = await sourceControl.connections.list({\n orgId: args.orgId,\n factoryProjectId: args.factoryProjectId,\n });\n let hasLinkedRepository = false;\n for (const connection of connections) {\n try {\n if (\n (await sourceControl.projectRepositories.list({ orgId: args.orgId, connectionId: connection.id })).length > 0\n ) {\n hasLinkedRepository = true;\n break;\n }\n } catch (error) {\n if (!(error instanceof SourceControlConnectionNotFoundError)) throw error;\n }\n }\n if (hasLinkedRepository) linked.push(sourceControl);\n }\n if (linked.length > 1)\n throw new FactorySourceControlConflictError(\n 'Factory project has repositories linked through multiple source-control providers.',\n );\n return linked[0];\n}\n\nexport interface EnsureFactorySourceSessionArgs {\n /**\n * Storage handle of the integration that owns source control. Nothing here is\n * provider-specific: the connection is matched by the handle's own\n * `integrationId`, so GitHub, Slack-on-behalf-of-GitHub, or any future owner\n * all resolve through the same traversal.\n */\n sourceControl: SourceControlStorageHandle;\n orgId: string;\n factoryProjectId: string;\n branch: string;\n /** Pick the linked repository that the work item targets. */\n repositorySlug: string;\n /**\n * Attribute the run to this user instead of the repo connector. Set when the\n * run has an interactive user — e.g. the person who approved a proposed run.\n */\n attributeToUserId?: string;\n}\n\nexport interface EnsuredFactorySourceSession {\n sessionId: string;\n userId: string;\n projectRepositoryId: string;\n branch: string;\n baseBranch: string;\n}\n\nexport class FactorySourceSessionResolutionError extends Error {\n constructor(readonly reason: 'connection' | 'repository') {\n super(\n reason === 'connection'\n ? 'Factory source-control connection not found.'\n : 'Factory source-control repository not found.',\n );\n this.name = 'FactorySourceSessionResolutionError';\n }\n}\n\nexport interface ResolvedFactorySourceRepository {\n projectRepositoryId: string;\n /** The repository's pinned branch, else its default branch. */\n baseBranch: string;\n /** Who connected the repository. The attribution for runs with no interactive user. */\n connectedByUserId: string;\n}\n\n/**\n * Outcome of {@link resolveFactorySourceRepository}. A miss carries which step\n * failed: callers differ on whether that is an error (an autonomous run cannot\n * proceed) or a routine fallback (a chat integration drops to a chat-only\n * session), and the two steps fail for different reasons worth reporting apart.\n */\nexport type FactorySourceRepositoryResult =\n | ({ found: true } & ResolvedFactorySourceRepository)\n | { found: false; reason: 'connection' | 'repository' };\n\n/**\n * Resolve which repository a factory project's source-control runs act on: the\n * owner's connection on the project, then one of its linked repositories.\n *\n * The owner is whichever integration owns source control, matched by the\n * handle's own `integrationId` — nothing here is provider-specific.\n */\nexport async function resolveFactorySourceRepository(\n args:\n | {\n sourceControl: SourceControlStorageHandle;\n orgId: string;\n factoryProjectId: string;\n repositorySlug: string;\n }\n | {\n sourceControl: SourceControlStorageHandle;\n orgId: string;\n factoryProjectId: string;\n firstLinkedRepository: true;\n },\n): Promise<FactorySourceRepositoryResult> {\n const { sourceControl, orgId, factoryProjectId } = args;\n const repositorySlug = 'repositorySlug' in args ? args.repositorySlug : undefined;\n const firstLinkedRepository = 'firstLinkedRepository' in args;\n\n const connections = await sourceControl.connections.list({ orgId, factoryProjectId });\n const candidates = connections.filter(candidate => candidate.integrationId === sourceControl.integrationId);\n if (candidates.length === 0) return { found: false, reason: 'connection' };\n\n // A project can carry stale connections: a provider-app reinstall leaves the\n // old connection pointing at an installation that no longer exists, and that\n // row can sit ahead of the healthy one. Try every candidate and skip the ones\n // that no longer resolve rather than failing on the first.\n for (const connection of candidates) {\n let resolved;\n try {\n const projectRepositories = await sourceControl.projectRepositories.list({ orgId, connectionId: connection.id });\n const resolvedRepositories = await Promise.all(\n projectRepositories.map(async projectRepository => ({\n projectRepository,\n repository: await sourceControl.repositories.get({ orgId, id: projectRepository.repositoryId }),\n })),\n );\n resolved = resolvedRepositories.find(\n candidate => candidate.repository && (firstLinkedRepository || candidate.repository.slug === repositorySlug),\n );\n } catch (error) {\n // A deleted installation invalidates a stale connection; storage failures must propagate.\n if (!(error instanceof SourceControlConnectionNotFoundError)) throw error;\n continue;\n }\n if (!resolved?.repository) continue;\n\n return {\n found: true,\n projectRepositoryId: resolved.projectRepository.id,\n baseBranch: resolved.projectRepository.branch ?? resolved.repository.defaultBranch,\n connectedByUserId: connection.createdByUserId,\n };\n }\n\n return { found: false, reason: 'repository' };\n}\n\n/**\n * Walk a Factory user-session id back to the project it belongs to.\n *\n * Repo-backed channel threads are keyed by their Factory session id, which is\n * the only handle a session-start hook gets. This turns that id back into the\n * project whose configuration the session should adopt. Durable by\n * construction — it reads the same rows the session was created from, so it\n * survives restarts without any in-memory mapping.\n */\nexport async function resolveFactoryProjectForSession(args: {\n sourceControl: SourceControlStorageHandle;\n sessionId: string;\n}): Promise<{ factoryProjectId: string; orgId: string; userId: string } | null> {\n const { sourceControl, sessionId } = args;\n\n const session = await sourceControl.sessions.getBySessionId(sessionId);\n if (!session) return null;\n const projectRepository = await sourceControl.projectRepositories.get({\n orgId: session.orgId,\n id: session.projectRepositoryId,\n });\n if (!projectRepository) return null;\n const connection = await sourceControl.connections.get({ orgId: session.orgId, id: projectRepository.connectionId });\n if (!connection) return null;\n\n return { factoryProjectId: connection.factoryProjectId, orgId: session.orgId, userId: session.userId };\n}\n\n/**\n * Create the source-control session a repo-backed factory run needs.\n *\n * `FactoryStartCoordinator.prepare` requires this record to already exist —\n * `resolveSourceSession` throws `Factory session not found` otherwise — so every\n * autonomous entry point has to produce one before it can start a run. This is\n * that step, in one place: the owner's connection on the factory project, one of\n * its linked repositories, and a session on the requested branch with the\n * repository's pinned or default branch as the base.\n *\n * The run is attributed to `attributeToUserId` when the caller has an\n * interactive user (e.g. the approver of a proposed run), and otherwise falls\n * back to whoever connected the repository (`connection.createdByUserId`),\n * because a genuinely autonomous run has no interactive user of its own.\n */\nexport async function ensureFactorySourceSession(\n args: EnsureFactorySourceSessionArgs,\n): Promise<EnsuredFactorySourceSession> {\n const { sourceControl, orgId, factoryProjectId, branch, repositorySlug } = args;\n\n const resolved = await resolveFactorySourceRepository({ sourceControl, orgId, factoryProjectId, repositorySlug });\n if (!resolved.found) throw new FactorySourceSessionResolutionError(resolved.reason);\n\n const userId = args.attributeToUserId ?? resolved.connectedByUserId;\n const session = await sourceControl.sessions.create({\n sessionId: globalThis.crypto.randomUUID(),\n projectRepositoryId: resolved.projectRepositoryId,\n orgId,\n userId,\n branch,\n baseBranch: resolved.baseBranch,\n visibility: 'org',\n });\n return {\n sessionId: session.sessionId,\n userId,\n projectRepositoryId: resolved.projectRepositoryId,\n branch: session.branch,\n baseBranch: resolved.baseBranch,\n };\n}\n\nexport interface HydrateFactorySessionArgs {\n orgId: string;\n /**\n * The factory project whose shared memory settings apply. Factory sessions\n * never read an individual user's personal memory settings — the project's\n * own row (or the built-in defaults) is what they run with.\n */\n factoryProjectId?: string;\n /** The factory project's default model. Without it the session keeps the SDK's built-in mode default. */\n defaultModelId?: string;\n /**\n * Model whose provider supplies the observational-memory fallback. Defaults\n * to the factory model, but channel sessions can use the sender's model so OM\n * resolves against that sender's credentials.\n */\n observationalMemoryModelId?: string;\n /**\n * When provided, the factory project's stored memory-settings row is\n * applied. When omitted (or no row exists) the session is reset to the\n * built-in memory defaults.\n */\n memorySettings?: MemorySettingsStorage;\n}\n\n/**\n * Apply a factory project's configuration to a freshly created session:\n * observational-memory settings, then the project's default model.\n *\n * Both steps are best-effort. A retired model id or an unreachable settings row\n * must not sink a run that is otherwise ready — the session simply keeps the\n * default it was created with, and the reason is logged.\n */\nexport async function hydrateFactorySession(session: FactorySession, args: HydrateFactorySessionArgs): Promise<void> {\n // The org rung knowledge curation scopes on. Seeded first so it lands even if\n // a later best-effort step fails; an empty org marks the session unresolved.\n await seedSessionOrg(session, args.orgId);\n try {\n const record =\n args.memorySettings && args.factoryProjectId\n ? await args.memorySettings.get({\n orgId: args.orgId,\n userId: factoryMemorySettingsUserId(args.factoryProjectId),\n })\n : null;\n // Without a stored row, fall back to the low-cost OM model of the factory\n // default model's provider — a factory connected only to Anthropic should\n // not observe with the (uncredentialed) built-in Google default.\n const observationalMemoryModelId = args.observationalMemoryModelId ?? args.defaultModelId;\n const provider = observationalMemoryModelId?.split('/')[0];\n const fallbackOmModelId = provider\n ? resolveProviderOMDefault(provider, observationalMemoryModelId).modelId\n : undefined;\n await applyStoredMemorySettings(session, record, fallbackOmModelId);\n } catch (error) {\n console.warn('[Factory Start] Failed to apply observational-memory settings', {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n if (args.defaultModelId) {\n try {\n await session.model.switch({ modelId: args.defaultModelId });\n } catch (error) {\n console.warn('[Factory Start] Failed to apply factory default model', {\n modelId: args.defaultModelId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n // Subagents otherwise keep the server-wide settings (or the SDK's built-in\n // default), which may name a provider this factory has no credentials for.\n // Each role is independent, so one failure doesn't strand the others.\n for (const agentType of ['explore', 'plan', 'execute']) {\n try {\n await session.subagents.model.set({ modelId: args.defaultModelId, agentType });\n } catch (error) {\n console.warn('[Factory Start] Failed to apply factory default subagent model', {\n agentType,\n modelId: args.defaultModelId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n }\n}\n\nexport interface RefreshFactorySessionMemorySettingsArgs {\n orgId: string;\n factoryProjectId: string;\n projects: Pick<FactoryProjectsStorage, 'get'>;\n memorySettings: Pick<MemorySettingsStorage, 'get'>;\n}\n\n/**\n * Re-apply a factory project's stored observational-memory settings to an\n * already-running session that automation is about to reuse. Session creation\n * hydrates these settings once (`hydrateFactorySession`), but a reused binding\n * keeps whatever observer/reflector models it was created with — so a project\n * whose OM models changed since would keep observing with the stale (and\n * possibly since-rejected) models. This reads the project's current row with the\n * same provider-aware fallback as initial hydration and applies it, mirroring\n * the `GET /web/config/om` refresh. Best-effort: a settings lookup failure must\n * never sink an otherwise-ready run, so it is logged and swallowed.\n */\nexport async function refreshFactorySessionMemorySettings(\n session: OMConfigurableSession,\n args: RefreshFactorySessionMemorySettingsArgs,\n): Promise<void> {\n try {\n const record = await args.memorySettings.get({\n orgId: args.orgId,\n userId: factoryMemorySettingsUserId(args.factoryProjectId),\n });\n const project = await args.projects.get({ orgId: args.orgId, id: args.factoryProjectId });\n const provider = project?.defaultModelId?.split('/')[0];\n const fallbackOmModelId = provider\n ? resolveProviderOMDefault(provider, project?.defaultModelId ?? undefined).modelId\n : undefined;\n await applyStoredMemorySettings(session, record, fallbackOmModelId);\n } catch (error) {\n console.warn('[Factory dispatch] Failed to reapply observational-memory settings on session reuse', {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"factory-session.js","names":[],"sources":["../../src/session/factory-session.ts"],"sourcesContent":["import { resolveProviderOMDefault } from '@mastra/code-sdk/onboarding/packs';\nimport type { MastraCodeState } from '@mastra/code-sdk/schema';\nimport type { AgentController } from '@mastra/core/agent-controller';\n\nimport { factoryMemorySettingsUserId } from '../storage/domains/memory-settings/base.js';\nimport type { MemorySettingsStorage } from '../storage/domains/memory-settings/base.js';\nimport type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';\nimport {\n SourceControlConnectionNotFoundError,\n type SourceControlSession,\n type SourceControlStorageHandle,\n} from '../storage/domains/source-control/base.js';\nimport { applyStoredMemorySettings, type OMConfigurableSession } from './memory-settings-hydration.js';\nimport { seedSessionOrg } from './org-seed.js';\n\ntype FactorySession = Awaited<ReturnType<AgentController<MastraCodeState>['createSession']>>;\n\nexport class FactorySourceControlConflictError extends Error {}\n\n/**\n * Read the factory project's default model. Best-effort: a missing project or an\n * uninitialized storage domain means \"no default\", never a failed run.\n */\nexport async function resolveFactoryDefaultModelId(\n projects: FactoryProjectsStorage | undefined,\n factoryProjectId: string | undefined,\n): Promise<string | undefined> {\n if (!projects || !factoryProjectId) return undefined;\n try {\n const project = await projects.getById({ id: factoryProjectId });\n return project?.defaultModelId ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nexport interface SourceControlSessionLookup {\n getBySessionId(sessionId: string): Promise<SourceControlSession | null>;\n getSourceControlBySessionId(sessionId: string): Promise<SourceControlStorageHandle | null>;\n rename(args: { sessionId: string; title: string }): Promise<void>;\n markFirstMessage(args: { sessionId: string }): Promise<void>;\n markFirstMeaningfulExec(args: { sessionId: string }): Promise<void>;\n}\n\n/**\n * Read or update a session across every registered source-control partition.\n * Session ids are globally generated, so more than one match is invalid and\n * fails closed instead of mutating an arbitrary provider.\n */\nexport function createSourceControlSessionLookup(\n sourceControls: readonly SourceControlStorageHandle[],\n): SourceControlSessionLookup {\n const resolve = async (\n sessionId: string,\n ): Promise<{ sourceControl: SourceControlStorageHandle; session: SourceControlSession } | null> => {\n const matches = (\n await Promise.all(\n sourceControls.map(async sourceControl => ({\n sourceControl,\n session: await sourceControl.sessions.getBySessionId(sessionId),\n })),\n )\n ).filter(\n (match): match is { sourceControl: SourceControlStorageHandle; session: SourceControlSession } =>\n match.session !== null,\n );\n if (matches.length > 1) throw new Error('Factory session exists in multiple source-control providers.');\n return matches[0] ?? null;\n };\n\n return {\n getBySessionId: async sessionId => (await resolve(sessionId))?.session ?? null,\n getSourceControlBySessionId: async sessionId => (await resolve(sessionId))?.sourceControl ?? null,\n rename: async args => (await resolve(args.sessionId))?.sourceControl.sessions.rename(args),\n markFirstMessage: async args => (await resolve(args.sessionId))?.sourceControl.sessions.markFirstMessage(args),\n markFirstMeaningfulExec: async args =>\n (await resolve(args.sessionId))?.sourceControl.sessions.markFirstMeaningfulExec(args),\n };\n}\n\n/**\n * Resolve the source-control provider from durable Factory repository links,\n * never from the issue tracker that happened to create the work item.\n */\nexport async function resolveFactorySourceControl(args: {\n sourceControls: readonly SourceControlStorageHandle[];\n orgId: string;\n factoryProjectId: string;\n sessionId?: string;\n}): Promise<SourceControlStorageHandle | undefined> {\n if (args.sessionId) {\n const sessionMatches = (\n await Promise.all(\n args.sourceControls.map(async sourceControl => ({\n sourceControl,\n session: await sourceControl.sessions.getBySessionId(args.sessionId!),\n })),\n )\n ).filter(match => match.session !== null);\n if (sessionMatches.length > 1) throw new Error('Factory session exists in multiple source-control providers.');\n if (sessionMatches[0]) return sessionMatches[0].sourceControl;\n }\n\n const linked = [];\n for (const sourceControl of args.sourceControls) {\n const connections = await sourceControl.connections.list({\n orgId: args.orgId,\n factoryProjectId: args.factoryProjectId,\n });\n let hasLinkedRepository = false;\n for (const connection of connections) {\n try {\n if (\n (await sourceControl.projectRepositories.list({ orgId: args.orgId, connectionId: connection.id })).length > 0\n ) {\n hasLinkedRepository = true;\n break;\n }\n } catch (error) {\n if (!(error instanceof SourceControlConnectionNotFoundError)) throw error;\n }\n }\n if (hasLinkedRepository) linked.push(sourceControl);\n }\n if (linked.length > 1)\n throw new FactorySourceControlConflictError(\n 'Factory project has repositories linked through multiple source-control providers.',\n );\n return linked[0];\n}\n\nexport interface EnsureFactorySourceSessionArgs {\n /**\n * Storage handle of the integration that owns source control. Nothing here is\n * provider-specific: the connection is matched by the handle's own\n * `integrationId`, so GitHub, Slack-on-behalf-of-GitHub, or any future owner\n * all resolve through the same traversal.\n */\n sourceControl: SourceControlStorageHandle;\n orgId: string;\n factoryProjectId: string;\n branch: string;\n /** Pick the linked repository that the work item targets. */\n repositorySlug: string;\n /**\n * Attribute the run to this user instead of the repo connector. Set when the\n * run has an interactive user — e.g. the person who approved a proposed run.\n */\n attributeToUserId?: string;\n}\n\nexport interface EnsuredFactorySourceSession {\n sessionId: string;\n userId: string;\n projectRepositoryId: string;\n branch: string;\n baseBranch: string;\n}\n\nexport class FactorySourceSessionResolutionError extends Error {\n constructor(readonly reason: 'connection' | 'repository') {\n super(\n reason === 'connection'\n ? 'Factory source-control connection not found.'\n : 'Factory source-control repository not found.',\n );\n this.name = 'FactorySourceSessionResolutionError';\n }\n}\n\nexport interface ResolvedFactorySourceRepository {\n projectRepositoryId: string;\n /** The repository's pinned branch, else its default branch. */\n baseBranch: string;\n /** Who connected the repository. The attribution for runs with no interactive user. */\n connectedByUserId: string;\n}\n\n/**\n * Outcome of {@link resolveFactorySourceRepository}. A miss carries which step\n * failed: callers differ on whether that is an error (an autonomous run cannot\n * proceed) or a routine fallback (a chat integration drops to a chat-only\n * session), and the two steps fail for different reasons worth reporting apart.\n */\nexport type FactorySourceRepositoryResult =\n | ({ found: true } & ResolvedFactorySourceRepository)\n | { found: false; reason: 'connection' | 'repository' };\n\n/**\n * Resolve which repository a factory project's source-control runs act on: the\n * owner's connection on the project, then one of its linked repositories.\n *\n * The owner is whichever integration owns source control, matched by the\n * handle's own `integrationId` — nothing here is provider-specific.\n */\nexport async function resolveFactorySourceRepository(\n args:\n | {\n sourceControl: SourceControlStorageHandle;\n orgId: string;\n factoryProjectId: string;\n repositorySlug: string;\n }\n | {\n sourceControl: SourceControlStorageHandle;\n orgId: string;\n factoryProjectId: string;\n firstLinkedRepository: true;\n },\n): Promise<FactorySourceRepositoryResult> {\n const { sourceControl, orgId, factoryProjectId } = args;\n const repositorySlug = 'repositorySlug' in args ? args.repositorySlug : undefined;\n const firstLinkedRepository = 'firstLinkedRepository' in args;\n\n const connections = await sourceControl.connections.list({ orgId, factoryProjectId });\n const candidates = connections.filter(candidate => candidate.integrationId === sourceControl.integrationId);\n if (candidates.length === 0) return { found: false, reason: 'connection' };\n\n // A project can carry stale connections: a provider-app reinstall leaves the\n // old connection pointing at an installation that no longer exists, and that\n // row can sit ahead of the healthy one. Try every candidate and skip the ones\n // that no longer resolve rather than failing on the first.\n for (const connection of candidates) {\n let resolved;\n try {\n const projectRepositories = await sourceControl.projectRepositories.list({ orgId, connectionId: connection.id });\n const resolvedRepositories = await Promise.all(\n projectRepositories.map(async projectRepository => ({\n projectRepository,\n repository: await sourceControl.repositories.get({ orgId, id: projectRepository.repositoryId }),\n })),\n );\n resolved = resolvedRepositories.find(\n candidate => candidate.repository && (firstLinkedRepository || candidate.repository.slug === repositorySlug),\n );\n } catch (error) {\n // A deleted installation invalidates a stale connection; storage failures must propagate.\n if (!(error instanceof SourceControlConnectionNotFoundError)) throw error;\n continue;\n }\n if (!resolved?.repository) continue;\n\n return {\n found: true,\n projectRepositoryId: resolved.projectRepository.id,\n baseBranch: resolved.projectRepository.branch ?? resolved.repository.defaultBranch,\n connectedByUserId: connection.createdByUserId,\n };\n }\n\n return { found: false, reason: 'repository' };\n}\n\n/**\n * Walk a Factory user-session id back to the project it belongs to.\n *\n * Repo-backed channel threads are keyed by their Factory session id, which is\n * the only handle a session-start hook gets. This turns that id back into the\n * project whose configuration the session should adopt. Durable by\n * construction — it reads the same rows the session was created from, so it\n * survives restarts without any in-memory mapping.\n */\nexport async function resolveFactoryProjectForSession(args: {\n sourceControl: SourceControlStorageHandle;\n sessionId: string;\n}): Promise<{ factoryProjectId: string; orgId: string; userId: string } | null> {\n const { sourceControl, sessionId } = args;\n\n const session = await sourceControl.sessions.getBySessionId(sessionId);\n if (!session) return null;\n const projectRepository = await sourceControl.projectRepositories.get({\n orgId: session.orgId,\n id: session.projectRepositoryId,\n });\n if (!projectRepository) return null;\n const connection = await sourceControl.connections.get({ orgId: session.orgId, id: projectRepository.connectionId });\n if (!connection) return null;\n\n return { factoryProjectId: connection.factoryProjectId, orgId: session.orgId, userId: session.userId };\n}\n\n/**\n * Create the source-control session a repo-backed factory run needs.\n *\n * `FactoryStartCoordinator.prepare` requires this record to already exist —\n * `resolveSourceSession` throws `Factory session not found` otherwise — so every\n * autonomous entry point has to produce one before it can start a run. This is\n * that step, in one place: the owner's connection on the factory project, one of\n * its linked repositories, and a session on the requested branch with the\n * repository's pinned or default branch as the base.\n *\n * The run is attributed to `attributeToUserId` when the caller has an\n * interactive user (e.g. the approver of a proposed run), and otherwise falls\n * back to whoever connected the repository (`connection.createdByUserId`),\n * because a genuinely autonomous run has no interactive user of its own.\n */\nexport async function ensureFactorySourceSession(\n args: EnsureFactorySourceSessionArgs,\n): Promise<EnsuredFactorySourceSession> {\n const { sourceControl, orgId, factoryProjectId, branch, repositorySlug } = args;\n\n const resolved = await resolveFactorySourceRepository({ sourceControl, orgId, factoryProjectId, repositorySlug });\n if (!resolved.found) throw new FactorySourceSessionResolutionError(resolved.reason);\n\n const userId = args.attributeToUserId ?? resolved.connectedByUserId;\n const session = await sourceControl.sessions.create({\n sessionId: globalThis.crypto.randomUUID(),\n projectRepositoryId: resolved.projectRepositoryId,\n orgId,\n userId,\n branch,\n baseBranch: resolved.baseBranch,\n visibility: 'org',\n });\n return {\n sessionId: session.sessionId,\n userId,\n projectRepositoryId: resolved.projectRepositoryId,\n branch: session.branch,\n baseBranch: resolved.baseBranch,\n };\n}\n\nexport interface HydrateFactorySessionArgs {\n orgId: string;\n /**\n * The factory project whose shared memory settings apply. Factory sessions\n * never read an individual user's personal memory settings — the project's\n * own row (or the built-in defaults) is what they run with.\n */\n factoryProjectId?: string;\n /** The factory project's default model. Without it the session keeps the SDK's built-in mode default. */\n defaultModelId?: string;\n /**\n * Model whose provider supplies the observational-memory fallback. Defaults\n * to the factory model, but channel sessions can use the sender's model so OM\n * resolves against that sender's credentials.\n */\n observationalMemoryModelId?: string;\n /**\n * When provided, the factory project's stored memory-settings row is\n * applied. When omitted (or no row exists) the session is reset to the\n * built-in memory defaults.\n */\n memorySettings?: MemorySettingsStorage;\n}\n\n/**\n * Apply a factory project's configuration to a freshly created session:\n * observational-memory settings, then the project's default model.\n *\n * Both steps are best-effort. A retired model id or an unreachable settings row\n * must not sink a run that is otherwise ready — the session simply keeps the\n * default it was created with, and the reason is logged.\n */\nexport async function hydrateFactorySession(session: FactorySession, args: HydrateFactorySessionArgs): Promise<void> {\n // The org rung knowledge curation scopes on. Seeded first so it lands even if\n // a later best-effort step fails; an empty org marks the session unresolved.\n await seedSessionOrg(session, args.orgId);\n try {\n const record =\n args.memorySettings && args.factoryProjectId\n ? await args.memorySettings.get({\n orgId: args.orgId,\n userId: factoryMemorySettingsUserId(args.factoryProjectId),\n })\n : null;\n // Without a stored row, fall back to the low-cost OM model of the factory\n // default model's provider — a factory connected only to Anthropic should\n // not observe with the (uncredentialed) built-in Google default.\n const observationalMemoryModelId = args.observationalMemoryModelId ?? args.defaultModelId;\n const provider = observationalMemoryModelId?.split('/')[0];\n const fallbackOmModelId = provider\n ? resolveProviderOMDefault(provider, observationalMemoryModelId).modelId\n : undefined;\n await applyStoredMemorySettings(session, record, fallbackOmModelId);\n } catch (error) {\n console.warn('[Factory Start] Failed to apply observational-memory settings', {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n if (args.defaultModelId) {\n try {\n await session.model.switch(args.defaultModelId);\n } catch (error) {\n console.warn('[Factory Start] Failed to apply factory default model', {\n modelId: args.defaultModelId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n // Subagents otherwise keep the server-wide settings (or the SDK's built-in\n // default), which may name a provider this factory has no credentials for.\n // Each role is independent, so one failure doesn't strand the others.\n for (const agentType of ['explore', 'plan', 'execute']) {\n try {\n await session.subagents.model.set({ modelId: args.defaultModelId, agentType });\n } catch (error) {\n console.warn('[Factory Start] Failed to apply factory default subagent model', {\n agentType,\n modelId: args.defaultModelId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n }\n}\n\nexport interface RefreshFactorySessionMemorySettingsArgs {\n orgId: string;\n factoryProjectId: string;\n projects: Pick<FactoryProjectsStorage, 'get'>;\n memorySettings: Pick<MemorySettingsStorage, 'get'>;\n}\n\n/**\n * Re-apply a factory project's stored observational-memory settings to an\n * already-running session that automation is about to reuse. Session creation\n * hydrates these settings once (`hydrateFactorySession`), but a reused binding\n * keeps whatever observer/reflector models it was created with — so a project\n * whose OM models changed since would keep observing with the stale (and\n * possibly since-rejected) models. This reads the project's current row with the\n * same provider-aware fallback as initial hydration and applies it, mirroring\n * the `GET /web/config/om` refresh. Best-effort: a settings lookup failure must\n * never sink an otherwise-ready run, so it is logged and swallowed.\n */\nexport async function refreshFactorySessionMemorySettings(\n session: OMConfigurableSession,\n args: RefreshFactorySessionMemorySettingsArgs,\n): Promise<void> {\n try {\n const record = await args.memorySettings.get({\n orgId: args.orgId,\n userId: factoryMemorySettingsUserId(args.factoryProjectId),\n });\n const project = await args.projects.get({ orgId: args.orgId, id: args.factoryProjectId });\n const provider = project?.defaultModelId?.split('/')[0];\n const fallbackOmModelId = provider\n ? resolveProviderOMDefault(provider, project?.defaultModelId ?? undefined).modelId\n : undefined;\n await applyStoredMemorySettings(session, record, fallbackOmModelId);\n } catch (error) {\n console.warn('[Factory dispatch] Failed to reapply observational-memory settings on session reuse', {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { FactoryStorageDomain } from '@mastra/core/storage';
|
|
2
|
+
import type { CollectionSchema } from '@mastra/core/storage';
|
|
3
|
+
export interface ModelDefaultRecord {
|
|
4
|
+
orgId: string;
|
|
5
|
+
userId: string;
|
|
6
|
+
modelId: string;
|
|
7
|
+
updatedAt: Date;
|
|
8
|
+
}
|
|
9
|
+
export declare const USER_DEFAULT_MODELS_SCHEMA: CollectionSchema;
|
|
10
|
+
export declare class ModelDefaultsStorage extends FactoryStorageDomain {
|
|
11
|
+
#private;
|
|
12
|
+
constructor();
|
|
13
|
+
init(): Promise<void>;
|
|
14
|
+
dangerouslyClearAll(): Promise<void>;
|
|
15
|
+
get({ orgId, userId }: {
|
|
16
|
+
orgId: string;
|
|
17
|
+
userId: string;
|
|
18
|
+
}): Promise<ModelDefaultRecord | null>;
|
|
19
|
+
set({ orgId, userId, modelId, }: {
|
|
20
|
+
orgId: string;
|
|
21
|
+
userId: string;
|
|
22
|
+
modelId: string;
|
|
23
|
+
}): Promise<ModelDefaultRecord>;
|
|
24
|
+
clear({ orgId, userId }: {
|
|
25
|
+
orgId: string;
|
|
26
|
+
userId: string;
|
|
27
|
+
}): Promise<boolean>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/storage/domains/model-defaults/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAwB,MAAM,sBAAsB,CAAC;AAClF,OAAO,KAAK,EAAE,gBAAgB,EAAqB,MAAM,sBAAsB,CAAC;AAEhF,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,eAAO,MAAM,0BAA0B,EAAE,gBAUxC,CAAC;AAmBF,qBAAa,oBAAqB,SAAQ,oBAAoB;;;IAKtD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAQpC,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAQ7F,GAAG,CAAC,EACR,KAAK,EACL,MAAM,EACN,OAAO,GACR,EAAE;QACD,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;KACjB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAyBzB,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC;CAGpF"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { FactoryStorageDomain, UniqueViolationError } from "@mastra/core/storage";
|
|
2
|
+
//#region src/storage/domains/model-defaults/base.ts
|
|
3
|
+
const USER_DEFAULT_MODELS_SCHEMA = {
|
|
4
|
+
name: "user_default_models",
|
|
5
|
+
columns: {
|
|
6
|
+
id: { type: "uuid-pk" },
|
|
7
|
+
org_id: { type: "text" },
|
|
8
|
+
user_id: { type: "text" },
|
|
9
|
+
model_id: { type: "text" },
|
|
10
|
+
updated_at: { type: "timestamp" }
|
|
11
|
+
},
|
|
12
|
+
uniqueIndexes: [{
|
|
13
|
+
name: "user_default_models_org_user_key",
|
|
14
|
+
columns: ["org_id", "user_id"]
|
|
15
|
+
}]
|
|
16
|
+
};
|
|
17
|
+
function toRecord(row) {
|
|
18
|
+
return {
|
|
19
|
+
orgId: row.org_id,
|
|
20
|
+
userId: row.user_id,
|
|
21
|
+
modelId: row.model_id,
|
|
22
|
+
updatedAt: row.updated_at
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
var ModelDefaultsStorage = class extends FactoryStorageDomain {
|
|
26
|
+
constructor() {
|
|
27
|
+
super("model-defaults");
|
|
28
|
+
}
|
|
29
|
+
async init() {
|
|
30
|
+
await this.ensureCollections([USER_DEFAULT_MODELS_SCHEMA]);
|
|
31
|
+
}
|
|
32
|
+
async dangerouslyClearAll() {
|
|
33
|
+
await this.ops.deleteMany("user_default_models", {});
|
|
34
|
+
}
|
|
35
|
+
get #db() {
|
|
36
|
+
return this.ops;
|
|
37
|
+
}
|
|
38
|
+
async get({ orgId, userId }) {
|
|
39
|
+
const row = await this.#db.findOne("user_default_models", {
|
|
40
|
+
org_id: orgId,
|
|
41
|
+
user_id: userId
|
|
42
|
+
});
|
|
43
|
+
return row ? toRecord(row) : null;
|
|
44
|
+
}
|
|
45
|
+
async set({ orgId, userId, modelId }) {
|
|
46
|
+
const values = {
|
|
47
|
+
model_id: modelId,
|
|
48
|
+
updated_at: /* @__PURE__ */ new Date()
|
|
49
|
+
};
|
|
50
|
+
const updateExisting = () => this.#db.updateAtomic("user_default_models", {
|
|
51
|
+
org_id: orgId,
|
|
52
|
+
user_id: userId
|
|
53
|
+
}, () => values);
|
|
54
|
+
const updated = await updateExisting();
|
|
55
|
+
if (updated) return toRecord(updated);
|
|
56
|
+
try {
|
|
57
|
+
return toRecord(await this.#db.insertOne("user_default_models", {
|
|
58
|
+
org_id: orgId,
|
|
59
|
+
user_id: userId,
|
|
60
|
+
...values
|
|
61
|
+
}));
|
|
62
|
+
} catch (error) {
|
|
63
|
+
if (!(error instanceof UniqueViolationError)) throw error;
|
|
64
|
+
const row = await updateExisting();
|
|
65
|
+
if (!row) throw error;
|
|
66
|
+
return toRecord(row);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async clear({ orgId, userId }) {
|
|
70
|
+
return await this.#db.deleteMany("user_default_models", {
|
|
71
|
+
org_id: orgId,
|
|
72
|
+
user_id: userId
|
|
73
|
+
}) > 0;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
//#endregion
|
|
77
|
+
export { ModelDefaultsStorage, USER_DEFAULT_MODELS_SCHEMA };
|
|
78
|
+
|
|
79
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","names":["#db"],"sources":["../../../../src/storage/domains/model-defaults/base.ts"],"sourcesContent":["import { FactoryStorageDomain, UniqueViolationError } from '@mastra/core/storage';\nimport type { CollectionSchema, FactoryStorageOps } from '@mastra/core/storage';\n\nexport interface ModelDefaultRecord {\n orgId: string;\n userId: string;\n modelId: string;\n updatedAt: Date;\n}\n\nexport const USER_DEFAULT_MODELS_SCHEMA: CollectionSchema = {\n name: 'user_default_models',\n columns: {\n id: { type: 'uuid-pk' },\n org_id: { type: 'text' },\n user_id: { type: 'text' },\n model_id: { type: 'text' },\n updated_at: { type: 'timestamp' },\n },\n uniqueIndexes: [{ name: 'user_default_models_org_user_key', columns: ['org_id', 'user_id'] }],\n};\n\ninterface ModelDefaultDbRow extends Record<string, unknown> {\n id: string;\n org_id: string;\n user_id: string;\n model_id: string;\n updated_at: Date;\n}\n\nfunction toRecord(row: ModelDefaultDbRow): ModelDefaultRecord {\n return {\n orgId: row.org_id,\n userId: row.user_id,\n modelId: row.model_id,\n updatedAt: row.updated_at,\n };\n}\n\nexport class ModelDefaultsStorage extends FactoryStorageDomain {\n constructor() {\n super('model-defaults');\n }\n\n async init(): Promise<void> {\n await this.ensureCollections([USER_DEFAULT_MODELS_SCHEMA]);\n }\n\n async dangerouslyClearAll(): Promise<void> {\n await this.ops.deleteMany('user_default_models', {});\n }\n\n get #db(): FactoryStorageOps {\n return this.ops;\n }\n\n async get({ orgId, userId }: { orgId: string; userId: string }): Promise<ModelDefaultRecord | null> {\n const row = await this.#db.findOne<ModelDefaultDbRow>('user_default_models', {\n org_id: orgId,\n user_id: userId,\n });\n return row ? toRecord(row) : null;\n }\n\n async set({\n orgId,\n userId,\n modelId,\n }: {\n orgId: string;\n userId: string;\n modelId: string;\n }): Promise<ModelDefaultRecord> {\n const now = new Date();\n const values = { model_id: modelId, updated_at: now };\n const updateExisting = () =>\n this.#db.updateAtomic<ModelDefaultDbRow>('user_default_models', { org_id: orgId, user_id: userId }, () => values);\n\n const updated = await updateExisting();\n if (updated) return toRecord(updated);\n\n try {\n return toRecord(\n await this.#db.insertOne<ModelDefaultDbRow>('user_default_models', {\n org_id: orgId,\n user_id: userId,\n ...values,\n }),\n );\n } catch (error) {\n if (!(error instanceof UniqueViolationError)) throw error;\n const row = await updateExisting();\n if (!row) throw error;\n return toRecord(row);\n }\n }\n\n async clear({ orgId, userId }: { orgId: string; userId: string }): Promise<boolean> {\n return (await this.#db.deleteMany('user_default_models', { org_id: orgId, user_id: userId })) > 0;\n }\n}\n"],"mappings":";;AAUA,MAAa,6BAA+C;CAC1D,MAAM;CACN,SAAS;EACP,IAAI,EAAE,MAAM,UAAU;EACtB,QAAQ,EAAE,MAAM,OAAO;EACvB,SAAS,EAAE,MAAM,OAAO;EACxB,UAAU,EAAE,MAAM,OAAO;EACzB,YAAY,EAAE,MAAM,YAAY;CAClC;CACA,eAAe,CAAC;EAAE,MAAM;EAAoC,SAAS,CAAC,UAAU,SAAS;CAAE,CAAC;AAC9F;AAUA,SAAS,SAAS,KAA4C;CAC5D,OAAO;EACL,OAAO,IAAI;EACX,QAAQ,IAAI;EACZ,SAAS,IAAI;EACb,WAAW,IAAI;CACjB;AACF;AAEA,IAAa,uBAAb,cAA0C,qBAAqB;CAC7D,cAAc;EACZ,MAAM,gBAAgB;CACxB;CAEA,MAAM,OAAsB;EAC1B,MAAM,KAAK,kBAAkB,CAAC,0BAA0B,CAAC;CAC3D;CAEA,MAAM,sBAAqC;EACzC,MAAM,KAAK,IAAI,WAAW,uBAAuB,CAAC,CAAC;CACrD;CAEA,IAAIA,MAAyB;EAC3B,OAAO,KAAK;CACd;CAEA,MAAM,IAAI,EAAE,OAAO,UAAiF;EAClG,MAAM,MAAM,MAAM,KAAKA,IAAI,QAA2B,uBAAuB;GAC3E,QAAQ;GACR,SAAS;EACX,CAAC;EACD,OAAO,MAAM,SAAS,GAAG,IAAI;CAC/B;CAEA,MAAM,IAAI,EACR,OACA,QACA,WAK8B;EAE9B,MAAM,SAAS;GAAE,UAAU;GAAS,4BAAY,IADhC,KACkC;EAAE;EACpD,MAAM,uBACJ,KAAKA,IAAI,aAAgC,uBAAuB;GAAE,QAAQ;GAAO,SAAS;EAAO,SAAS,MAAM;EAElH,MAAM,UAAU,MAAM,eAAe;EACrC,IAAI,SAAS,OAAO,SAAS,OAAO;EAEpC,IAAI;GACF,OAAO,SACL,MAAM,KAAKA,IAAI,UAA6B,uBAAuB;IACjE,QAAQ;IACR,SAAS;IACT,GAAG;GACL,CAAC,CACH;EACF,SAAS,OAAO;GACd,IAAI,EAAE,iBAAiB,uBAAuB,MAAM;GACpD,MAAM,MAAM,MAAM,eAAe;GACjC,IAAI,CAAC,KAAK,MAAM;GAChB,OAAO,SAAS,GAAG;EACrB;CACF;CAEA,MAAM,MAAM,EAAE,OAAO,UAA+D;EAClF,OAAQ,MAAM,KAAKA,IAAI,WAAW,uBAAuB;GAAE,QAAQ;GAAO,SAAS;EAAO,CAAC,IAAK;CAClG;AACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/factory",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0-alpha.10",
|
|
4
4
|
"description": "Mastra Software Factory module: the server core behind the Mastra Software Factory — storage domains, integrations, and surfaces for agent-powered software delivery",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -58,10 +58,10 @@
|
|
|
58
58
|
"posthog-node": "^5.46.1",
|
|
59
59
|
"zod": "^4.6.4",
|
|
60
60
|
"@mastra/auth-studio": "1.3.8",
|
|
61
|
-
"@mastra/
|
|
62
|
-
"@mastra/
|
|
63
|
-
"@mastra/slack": "1.7.2-alpha.
|
|
64
|
-
"@mastra/
|
|
61
|
+
"@mastra/auth-workos": "1.6.6",
|
|
62
|
+
"@mastra/code-sdk": "1.11.0-alpha.10",
|
|
63
|
+
"@mastra/slack": "1.7.2-alpha.1",
|
|
64
|
+
"@mastra/core": "1.75.0-alpha.8"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@types/node": "22.20.1",
|
|
@@ -71,10 +71,10 @@
|
|
|
71
71
|
"typescript-eslint": "^8.57.0",
|
|
72
72
|
"vitest": "4.1.11",
|
|
73
73
|
"@internal/lint": "0.0.140",
|
|
74
|
-
"@mastra/pg": "1.30.0-alpha.3",
|
|
75
|
-
"@internal/types-builder": "0.0.115",
|
|
76
74
|
"@mastra/libsql": "1.25.1-alpha.0",
|
|
77
|
-
"@internal/workspace": "0.0.12"
|
|
75
|
+
"@internal/workspace": "0.0.12",
|
|
76
|
+
"@mastra/pg": "1.30.0-alpha.6",
|
|
77
|
+
"@internal/types-builder": "0.0.115"
|
|
78
78
|
},
|
|
79
79
|
"engines": {
|
|
80
80
|
"node": ">=22.19.0"
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import type { ActiveModelPackRecord, ModelPacksStorage } from '../storage/domains/model-packs/base.js';
|
|
2
|
-
import type { SourceControlStorageHandle } from '../storage/domains/source-control/base.js';
|
|
3
|
-
import type { WorkItemsStorage } from '../storage/domains/work-items/base.js';
|
|
4
|
-
export interface ModelPackApplicableSession {
|
|
5
|
-
mode: {
|
|
6
|
-
get(): string;
|
|
7
|
-
};
|
|
8
|
-
model: {
|
|
9
|
-
switch(args: {
|
|
10
|
-
modelId: string;
|
|
11
|
-
}): Promise<unknown>;
|
|
12
|
-
};
|
|
13
|
-
subagents: {
|
|
14
|
-
model: {
|
|
15
|
-
set(args: {
|
|
16
|
-
modelId: string;
|
|
17
|
-
agentType: string;
|
|
18
|
-
}): Promise<unknown>;
|
|
19
|
-
};
|
|
20
|
-
};
|
|
21
|
-
thread: {
|
|
22
|
-
getSetting?(args: {
|
|
23
|
-
key: string;
|
|
24
|
-
}): Promise<unknown>;
|
|
25
|
-
setSetting(args: {
|
|
26
|
-
key: string;
|
|
27
|
-
value: unknown;
|
|
28
|
-
}): Promise<unknown>;
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
export interface ModelPackHydrationSession extends ModelPackApplicableSession {
|
|
32
|
-
readonly identity: {
|
|
33
|
-
getResourceId(): string;
|
|
34
|
-
};
|
|
35
|
-
state: {
|
|
36
|
-
get(): Record<string, unknown> | undefined;
|
|
37
|
-
};
|
|
38
|
-
thread: ModelPackApplicableSession['thread'] & {
|
|
39
|
-
getId(): string | null | undefined;
|
|
40
|
-
getSetting(args: {
|
|
41
|
-
key: string;
|
|
42
|
-
}): Promise<unknown>;
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
export declare function applyActiveModelPack(session: ModelPackApplicableSession, activePack: Pick<ActiveModelPackRecord, 'packId' | 'models'>): Promise<void>;
|
|
46
|
-
export interface ModelPackHydrationDependencies {
|
|
47
|
-
sourceControl: {
|
|
48
|
-
sessions: Pick<SourceControlStorageHandle['sessions'], 'getBySessionId'>;
|
|
49
|
-
};
|
|
50
|
-
workItems: Pick<WorkItemsStorage, 'findActiveRunBindingByThread'>;
|
|
51
|
-
modelPacks: Pick<ModelPacksStorage, 'getActive'>;
|
|
52
|
-
}
|
|
53
|
-
/** Seed the user's default pack unless the interactive thread already selected its own pack. */
|
|
54
|
-
export declare function hydrateSessionModelPack(session: ModelPackHydrationSession, { sourceControl, workItems, modelPacks }: ModelPackHydrationDependencies): Promise<void>;
|
|
55
|
-
//# sourceMappingURL=model-pack-hydration.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"model-pack-hydration.d.ts","sourceRoot":"","sources":["../../src/session/model-pack-hydration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAC;AACvG,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AAC5F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAE9E,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE;QAAE,GAAG,IAAI,MAAM,CAAA;KAAE,CAAC;IACxB,KAAK,EAAE;QAAE,MAAM,CAAC,IAAI,EAAE;YAAE,OAAO,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;KAAE,CAAC;IAC/D,SAAS,EAAE;QAAE,KAAK,EAAE;YAAE,GAAG,CAAC,IAAI,EAAE;gBAAE,OAAO,EAAE,MAAM,CAAC;gBAAC,SAAS,EAAE,MAAM,CAAA;aAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;SAAE,CAAA;KAAE,CAAC;IAC9F,MAAM,EAAE;QACN,UAAU,CAAC,CAAC,IAAI,EAAE;YAAE,GAAG,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACrD,UAAU,CAAC,IAAI,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,OAAO,CAAA;SAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;KACrE,CAAC;CACH;AAED,MAAM,WAAW,yBAA0B,SAAQ,0BAA0B;IAC3E,QAAQ,CAAC,QAAQ,EAAE;QAAE,aAAa,IAAI,MAAM,CAAA;KAAE,CAAC;IAC/C,KAAK,EAAE;QAAE,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAA;KAAE,CAAC;IACtD,MAAM,EAAE,0BAA0B,CAAC,QAAQ,CAAC,GAAG;QAC7C,KAAK,IAAI,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;QACnC,UAAU,CAAC,IAAI,EAAE;YAAE,GAAG,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;KACrD,CAAC;CACH;AAED,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,0BAA0B,EACnC,UAAU,EAAE,IAAI,CAAC,qBAAqB,EAAE,QAAQ,GAAG,QAAQ,CAAC,GAC3D,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED,MAAM,WAAW,8BAA8B;IAC7C,aAAa,EAAE;QACb,QAAQ,EAAE,IAAI,CAAC,0BAA0B,CAAC,UAAU,CAAC,EAAE,gBAAgB,CAAC,CAAC;KAC1E,CAAC;IACF,SAAS,EAAE,IAAI,CAAC,gBAAgB,EAAE,8BAA8B,CAAC,CAAC;IAClE,UAAU,EAAE,IAAI,CAAC,iBAAiB,EAAE,WAAW,CAAC,CAAC;CAClD;AAED,gGAAgG;AAChG,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,yBAAyB,EAClC,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,8BAA8B,GACvE,OAAO,CAAC,IAAI,CAAC,CA+Bf"}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
//#region src/session/model-pack-hydration.ts
|
|
2
|
-
async function applyActiveModelPack(session, activePack) {
|
|
3
|
-
for (const [modeId, modelId] of Object.entries(activePack.models)) await session.thread.setSetting({
|
|
4
|
-
key: `modeModelId_${modeId}`,
|
|
5
|
-
value: modelId
|
|
6
|
-
});
|
|
7
|
-
const currentMode = session.mode.get();
|
|
8
|
-
const currentModeModel = currentMode === "build" || currentMode === "plan" || currentMode === "fast" ? activePack.models[currentMode] : void 0;
|
|
9
|
-
if (currentModeModel) await session.model.switch({ modelId: currentModeModel });
|
|
10
|
-
const subagentModels = [
|
|
11
|
-
["explore", activePack.models.fast],
|
|
12
|
-
["plan", activePack.models.plan],
|
|
13
|
-
["execute", activePack.models.build]
|
|
14
|
-
];
|
|
15
|
-
for (const [agentType, modelId] of subagentModels) await session.subagents.model.set({
|
|
16
|
-
modelId,
|
|
17
|
-
agentType
|
|
18
|
-
});
|
|
19
|
-
await session.thread.setSetting({
|
|
20
|
-
key: "activeModelPackId",
|
|
21
|
-
value: activePack.packId
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
/** Seed the user's default pack unless the interactive thread already selected its own pack. */
|
|
25
|
-
async function hydrateSessionModelPack(session, { sourceControl, workItems, modelPacks }) {
|
|
26
|
-
const resourceId = session.identity.getResourceId();
|
|
27
|
-
if (session.state.get()?.factoryProjectId || typeof session.thread.getSetting !== "function") return;
|
|
28
|
-
try {
|
|
29
|
-
const sourceSession = await sourceControl.sessions.getBySessionId(resourceId);
|
|
30
|
-
if (!sourceSession) return;
|
|
31
|
-
const threadId = session.thread.getId();
|
|
32
|
-
if (threadId && await workItems.findActiveRunBindingByThread({
|
|
33
|
-
orgId: sourceSession.orgId,
|
|
34
|
-
threadId,
|
|
35
|
-
resourceId,
|
|
36
|
-
sessionId: resourceId
|
|
37
|
-
})) return;
|
|
38
|
-
if ((await Promise.all([
|
|
39
|
-
session.thread.getSetting({ key: "activeModelPackId" }),
|
|
40
|
-
session.thread.getSetting({ key: "modeModelId_build" }),
|
|
41
|
-
session.thread.getSetting({ key: "modeModelId_plan" }),
|
|
42
|
-
session.thread.getSetting({ key: "modeModelId_fast" })
|
|
43
|
-
])).some((setting) => typeof setting === "string")) return;
|
|
44
|
-
const activePack = await modelPacks.getActive({
|
|
45
|
-
orgId: sourceSession.orgId,
|
|
46
|
-
userId: sourceSession.userId
|
|
47
|
-
});
|
|
48
|
-
if (activePack) await applyActiveModelPack(session, activePack);
|
|
49
|
-
} catch (error) {
|
|
50
|
-
console.warn("[Factory model-pack hydration] Unable to apply the active model pack.", error);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
//#endregion
|
|
54
|
-
export { applyActiveModelPack, hydrateSessionModelPack };
|
|
55
|
-
|
|
56
|
-
//# sourceMappingURL=model-pack-hydration.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"model-pack-hydration.js","names":[],"sources":["../../src/session/model-pack-hydration.ts"],"sourcesContent":["import type { ActiveModelPackRecord, ModelPacksStorage } from '../storage/domains/model-packs/base.js';\nimport type { SourceControlStorageHandle } from '../storage/domains/source-control/base.js';\nimport type { WorkItemsStorage } from '../storage/domains/work-items/base.js';\n\nexport interface ModelPackApplicableSession {\n mode: { get(): string };\n model: { switch(args: { modelId: string }): Promise<unknown> };\n subagents: { model: { set(args: { modelId: string; agentType: string }): Promise<unknown> } };\n thread: {\n getSetting?(args: { key: string }): Promise<unknown>;\n setSetting(args: { key: string; value: unknown }): Promise<unknown>;\n };\n}\n\nexport interface ModelPackHydrationSession extends ModelPackApplicableSession {\n readonly identity: { getResourceId(): string };\n state: { get(): Record<string, unknown> | undefined };\n thread: ModelPackApplicableSession['thread'] & {\n getId(): string | null | undefined;\n getSetting(args: { key: string }): Promise<unknown>;\n };\n}\n\nexport async function applyActiveModelPack(\n session: ModelPackApplicableSession,\n activePack: Pick<ActiveModelPackRecord, 'packId' | 'models'>,\n): Promise<void> {\n for (const [modeId, modelId] of Object.entries(activePack.models)) {\n await session.thread.setSetting({ key: `modeModelId_${modeId}`, value: modelId });\n }\n\n const currentMode = session.mode.get();\n const currentModeModel =\n currentMode === 'build' || currentMode === 'plan' || currentMode === 'fast'\n ? activePack.models[currentMode]\n : undefined;\n if (currentModeModel) {\n await session.model.switch({ modelId: currentModeModel });\n }\n\n const subagentModels = [\n ['explore', activePack.models.fast],\n ['plan', activePack.models.plan],\n ['execute', activePack.models.build],\n ] as const;\n for (const [agentType, modelId] of subagentModels) {\n await session.subagents.model.set({ modelId, agentType });\n }\n\n await session.thread.setSetting({ key: 'activeModelPackId', value: activePack.packId });\n}\n\nexport interface ModelPackHydrationDependencies {\n sourceControl: {\n sessions: Pick<SourceControlStorageHandle['sessions'], 'getBySessionId'>;\n };\n workItems: Pick<WorkItemsStorage, 'findActiveRunBindingByThread'>;\n modelPacks: Pick<ModelPacksStorage, 'getActive'>;\n}\n\n/** Seed the user's default pack unless the interactive thread already selected its own pack. */\nexport async function hydrateSessionModelPack(\n session: ModelPackHydrationSession,\n { sourceControl, workItems, modelPacks }: ModelPackHydrationDependencies,\n): Promise<void> {\n const resourceId = session.identity.getResourceId();\n if (session.state.get()?.factoryProjectId || typeof session.thread.getSetting !== 'function') return;\n try {\n const sourceSession = await sourceControl.sessions.getBySessionId(resourceId);\n if (!sourceSession) return;\n const threadId = session.thread.getId();\n if (\n threadId &&\n (await workItems.findActiveRunBindingByThread({\n orgId: sourceSession.orgId,\n threadId,\n resourceId,\n sessionId: resourceId,\n }))\n ) {\n return;\n }\n const existingThreadSettings = await Promise.all([\n session.thread.getSetting({ key: 'activeModelPackId' }),\n session.thread.getSetting({ key: 'modeModelId_build' }),\n session.thread.getSetting({ key: 'modeModelId_plan' }),\n session.thread.getSetting({ key: 'modeModelId_fast' }),\n ]);\n if (existingThreadSettings.some(setting => typeof setting === 'string')) return;\n\n const activePack = await modelPacks.getActive({ orgId: sourceSession.orgId, userId: sourceSession.userId });\n if (activePack) await applyActiveModelPack(session, activePack);\n } catch (error) {\n console.warn('[Factory model-pack hydration] Unable to apply the active model pack.', error);\n }\n}\n"],"mappings":";AAuBA,eAAsB,qBACpB,SACA,YACe;CACf,KAAK,MAAM,CAAC,QAAQ,YAAY,OAAO,QAAQ,WAAW,MAAM,GAC9D,MAAM,QAAQ,OAAO,WAAW;EAAE,KAAK,eAAe;EAAU,OAAO;CAAQ,CAAC;CAGlF,MAAM,cAAc,QAAQ,KAAK,IAAI;CACrC,MAAM,mBACJ,gBAAgB,WAAW,gBAAgB,UAAU,gBAAgB,SACjE,WAAW,OAAO,eAClB,KAAA;CACN,IAAI,kBACF,MAAM,QAAQ,MAAM,OAAO,EAAE,SAAS,iBAAiB,CAAC;CAG1D,MAAM,iBAAiB;EACrB,CAAC,WAAW,WAAW,OAAO,IAAI;EAClC,CAAC,QAAQ,WAAW,OAAO,IAAI;EAC/B,CAAC,WAAW,WAAW,OAAO,KAAK;CACrC;CACA,KAAK,MAAM,CAAC,WAAW,YAAY,gBACjC,MAAM,QAAQ,UAAU,MAAM,IAAI;EAAE;EAAS;CAAU,CAAC;CAG1D,MAAM,QAAQ,OAAO,WAAW;EAAE,KAAK;EAAqB,OAAO,WAAW;CAAO,CAAC;AACxF;;AAWA,eAAsB,wBACpB,SACA,EAAE,eAAe,WAAW,cACb;CACf,MAAM,aAAa,QAAQ,SAAS,cAAc;CAClD,IAAI,QAAQ,MAAM,IAAI,CAAC,EAAE,oBAAoB,OAAO,QAAQ,OAAO,eAAe,YAAY;CAC9F,IAAI;EACF,MAAM,gBAAgB,MAAM,cAAc,SAAS,eAAe,UAAU;EAC5E,IAAI,CAAC,eAAe;EACpB,MAAM,WAAW,QAAQ,OAAO,MAAM;EACtC,IACE,YACC,MAAM,UAAU,6BAA6B;GAC5C,OAAO,cAAc;GACrB;GACA;GACA,WAAW;EACb,CAAC,GAED;EAQF,KAAI,MANiC,QAAQ,IAAI;GAC/C,QAAQ,OAAO,WAAW,EAAE,KAAK,oBAAoB,CAAC;GACtD,QAAQ,OAAO,WAAW,EAAE,KAAK,oBAAoB,CAAC;GACtD,QAAQ,OAAO,WAAW,EAAE,KAAK,mBAAmB,CAAC;GACrD,QAAQ,OAAO,WAAW,EAAE,KAAK,mBAAmB,CAAC;EACvD,CAAC,EAAA,CAC0B,MAAK,YAAW,OAAO,YAAY,QAAQ,GAAG;EAEzE,MAAM,aAAa,MAAM,WAAW,UAAU;GAAE,OAAO,cAAc;GAAO,QAAQ,cAAc;EAAO,CAAC;EAC1G,IAAI,YAAY,MAAM,qBAAqB,SAAS,UAAU;CAChE,SAAS,OAAO;EACd,QAAQ,KAAK,yEAAyE,KAAK;CAC7F;AACF"}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { FactoryStorageDomain } from '@mastra/core/storage';
|
|
2
|
-
import type { CollectionSchema } from '@mastra/core/storage';
|
|
3
|
-
/** A saved custom model pack: one model per mode (build / plan / fast). */
|
|
4
|
-
export interface ModelPackRecord {
|
|
5
|
-
id: string;
|
|
6
|
-
orgId: string;
|
|
7
|
-
createdBy: string;
|
|
8
|
-
name: string;
|
|
9
|
-
models: {
|
|
10
|
-
build: string;
|
|
11
|
-
plan: string;
|
|
12
|
-
fast: string;
|
|
13
|
-
};
|
|
14
|
-
createdAt: Date;
|
|
15
|
-
updatedAt: Date;
|
|
16
|
-
}
|
|
17
|
-
export interface UpsertModelPackInput {
|
|
18
|
-
name: string;
|
|
19
|
-
models: {
|
|
20
|
-
build: string;
|
|
21
|
-
plan: string;
|
|
22
|
-
fast: string;
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
export interface ActiveModelPackRecord {
|
|
26
|
-
orgId: string;
|
|
27
|
-
userId: string;
|
|
28
|
-
packId: string;
|
|
29
|
-
models: {
|
|
30
|
-
build: string;
|
|
31
|
-
plan: string;
|
|
32
|
-
fast: string;
|
|
33
|
-
};
|
|
34
|
-
updatedAt: Date;
|
|
35
|
-
}
|
|
36
|
-
export declare const MODEL_PACKS_SCHEMA: CollectionSchema;
|
|
37
|
-
export declare const ACTIVE_MODEL_PACKS_SCHEMA: CollectionSchema;
|
|
38
|
-
export declare class ModelPacksStorage extends FactoryStorageDomain {
|
|
39
|
-
#private;
|
|
40
|
-
constructor();
|
|
41
|
-
init(): Promise<void>;
|
|
42
|
-
dangerouslyClearAll(): Promise<void>;
|
|
43
|
-
/** Create or replace a pack by `(orgId, name)` — mirrors the settings.json upsert semantics. */
|
|
44
|
-
upsert({ orgId, userId, input, }: {
|
|
45
|
-
orgId: string;
|
|
46
|
-
userId: string;
|
|
47
|
-
input: UpsertModelPackInput;
|
|
48
|
-
}): Promise<ModelPackRecord>;
|
|
49
|
-
list({ orgId }: {
|
|
50
|
-
orgId: string;
|
|
51
|
-
}): Promise<ModelPackRecord[]>;
|
|
52
|
-
get({ orgId, id }: {
|
|
53
|
-
orgId: string;
|
|
54
|
-
id: string;
|
|
55
|
-
}): Promise<ModelPackRecord | null>;
|
|
56
|
-
setActive({ orgId, userId, packId, models, }: {
|
|
57
|
-
orgId: string;
|
|
58
|
-
userId: string;
|
|
59
|
-
packId: string;
|
|
60
|
-
models: ActiveModelPackRecord['models'];
|
|
61
|
-
}): Promise<ActiveModelPackRecord>;
|
|
62
|
-
getActive({ orgId, userId }: {
|
|
63
|
-
orgId: string;
|
|
64
|
-
userId: string;
|
|
65
|
-
}): Promise<ActiveModelPackRecord | null>;
|
|
66
|
-
clearActive({ orgId, userId }: {
|
|
67
|
-
orgId: string;
|
|
68
|
-
userId: string;
|
|
69
|
-
}): Promise<boolean>;
|
|
70
|
-
delete({ orgId, id }: {
|
|
71
|
-
orgId: string;
|
|
72
|
-
id: string;
|
|
73
|
-
}): Promise<boolean>;
|
|
74
|
-
}
|
|
75
|
-
//# sourceMappingURL=base.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/storage/domains/model-packs/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAwB,MAAM,sBAAsB,CAAC;AAClF,OAAO,KAAK,EAAE,gBAAgB,EAAqB,MAAM,sBAAsB,CAAC;AAEhF,2EAA2E;AAC3E,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACvD;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,eAAO,MAAM,kBAAkB,EAAE,gBAchC,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,gBAavC,CAAC;AA+CF,qBAAa,iBAAkB,SAAQ,oBAAoB;;;IAKnD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAS1C,gGAAgG;IAC1F,MAAM,CAAC,EACX,KAAK,EACL,MAAM,EACN,KAAK,GACN,EAAE;QACD,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,oBAAoB,CAAC;KAC7B,GAAG,OAAO,CAAC,eAAe,CAAC;IAuCtB,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAS9D,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAKlF,SAAS,CAAC,EACd,KAAK,EACL,MAAM,EACN,MAAM,EACN,MAAM,GACP,EAAE;QACD,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,qBAAqB,CAAC,QAAQ,CAAC,CAAC;KACzC,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAmC5B,SAAS,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;IAQtG,WAAW,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAInF,MAAM,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC;CAO7E"}
|