@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projects.js","names":["#versionControlIntegrationIds","#projects","#sourceControl","#handles","#project","#findConnection","#findProjectRepository","#repositoryPayload","#retireProjectRepositorySessions","#resolveTenant"],"sources":["../../src/routes/projects.ts"],"sourcesContent":["import type { ApiRoute } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\nimport type { Context } from 'hono';\n\nimport type { SessionRetirementCoordinator } from '../sandbox/session-retirement.js';\nimport type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';\nimport type {\n ProjectRepository,\n SourceControlRepository,\n SourceControlStorage,\n SourceControlStorageHandle,\n UpdateProjectRepositoryInput,\n} from '../storage/domains/source-control/base.js';\nimport { ACTIVE_RUN_BINDING_STAGES } from '../storage/domains/work-items/base.js';\nimport type { WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport { FACTORY_ROUTE_CONTRACTS } from './contracts.js';\nimport type { RouteDependencies } from './route.js';\nimport { Route } from './route.js';\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst MAX_NAME_LENGTH = 200;\nconst MAX_REPOSITORY_COMMAND_LENGTH = 2_000;\nconst MAX_BRANCH_LENGTH = 255;\nconst MAX_SANDBOX_PROVIDER_LENGTH = 100;\nconst MAX_SANDBOX_WORKDIR_LENGTH = 1_000;\nconst CONTROL_CHAR_RE = /[\\0-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]/;\n\nfunction loose(context: unknown): Context {\n return context as Context;\n}\n\nasync function readJson(context: Context): Promise<unknown | undefined> {\n try {\n return await context.req.json();\n } catch {\n return undefined;\n }\n}\n\nfunction parseConnectionInput(value: unknown): { integrationId: string; installationId: string } | null {\n if (!value || typeof value !== 'object') return null;\n const input = value as Record<string, unknown>;\n if (typeof input.integrationId !== 'string' || !input.integrationId.trim()) return null;\n if (typeof input.installationId !== 'string' || !UUID_RE.test(input.installationId)) return null;\n return { integrationId: input.integrationId.trim(), installationId: input.installationId };\n}\n\nfunction parseOptionalString(\n value: unknown,\n { maxLength, nullable = false }: { maxLength: number; nullable?: boolean },\n): string | null | undefined | false {\n if (value === undefined) return undefined;\n if (value === null) return nullable ? null : false;\n if (typeof value !== 'string') return false;\n const normalized = value.trim();\n if (!normalized) return nullable ? null : false;\n if (normalized.length > maxLength || CONTROL_CHAR_RE.test(normalized)) return false;\n return normalized;\n}\n\nfunction parseRepositoryLinkInput(value: unknown): {\n repositoryId?: string;\n repository?: { externalId: string; slug: string };\n branch: string | null;\n sandboxProvider: string;\n sandboxWorkdir: string;\n setupCommand: string | null;\n teardownCommand: string | null;\n} | null {\n if (!value || typeof value !== 'object') return null;\n const input = value as Record<string, unknown>;\n const repositoryId =\n typeof input.repositoryId === 'string' && UUID_RE.test(input.repositoryId) ? input.repositoryId : undefined;\n const repositoryInput = input.repository;\n let repository: { externalId: string; slug: string } | undefined;\n if (repositoryInput && typeof repositoryInput === 'object') {\n const candidate = repositoryInput as Record<string, unknown>;\n const externalId = parseOptionalString(candidate.externalId, { maxLength: MAX_NAME_LENGTH });\n const slug = parseOptionalString(candidate.slug, { maxLength: MAX_NAME_LENGTH });\n if (typeof externalId !== 'string' || typeof slug !== 'string') return null;\n repository = { externalId, slug };\n }\n if (!repositoryId && !repository) return null;\n const branch = parseOptionalString(input.branch, { maxLength: MAX_BRANCH_LENGTH, nullable: true });\n const sandboxProvider = parseOptionalString(input.sandboxProvider, { maxLength: MAX_SANDBOX_PROVIDER_LENGTH });\n const sandboxWorkdir = parseOptionalString(input.sandboxWorkdir, { maxLength: MAX_SANDBOX_WORKDIR_LENGTH });\n const setupCommand = parseOptionalString(input.setupCommand, {\n maxLength: MAX_REPOSITORY_COMMAND_LENGTH,\n nullable: true,\n });\n const teardownCommand = parseOptionalString(input.teardownCommand, {\n maxLength: MAX_REPOSITORY_COMMAND_LENGTH,\n nullable: true,\n });\n if (\n branch === false ||\n typeof sandboxProvider !== 'string' ||\n typeof sandboxWorkdir !== 'string' ||\n setupCommand === false ||\n teardownCommand === false\n )\n return null;\n return {\n ...(repositoryId ? { repositoryId } : {}),\n ...(repository ? { repository } : {}),\n branch: branch ?? null,\n sandboxProvider,\n sandboxWorkdir,\n setupCommand: setupCommand ?? null,\n teardownCommand: teardownCommand ?? null,\n };\n}\n\nfunction parseRepositoryUpdateInput(value: unknown): UpdateProjectRepositoryInput | null {\n if (!value || typeof value !== 'object') return null;\n const input = value as Record<string, unknown>;\n const patch: UpdateProjectRepositoryInput = {};\n const branch = parseOptionalString(input.branch, { maxLength: MAX_BRANCH_LENGTH, nullable: true });\n const sandboxProvider = parseOptionalString(input.sandboxProvider, { maxLength: MAX_SANDBOX_PROVIDER_LENGTH });\n const sandboxWorkdir = parseOptionalString(input.sandboxWorkdir, { maxLength: MAX_SANDBOX_WORKDIR_LENGTH });\n const setupCommand = parseOptionalString(input.setupCommand, {\n maxLength: MAX_REPOSITORY_COMMAND_LENGTH,\n nullable: true,\n });\n const teardownCommand = parseOptionalString(input.teardownCommand, {\n maxLength: MAX_REPOSITORY_COMMAND_LENGTH,\n nullable: true,\n });\n if (\n branch === false ||\n sandboxProvider === false ||\n sandboxProvider === null ||\n sandboxWorkdir === false ||\n sandboxWorkdir === null ||\n setupCommand === false ||\n teardownCommand === false\n )\n return null;\n if (branch !== undefined) patch.branch = branch;\n if (sandboxProvider !== undefined) patch.sandboxProvider = sandboxProvider;\n if (sandboxWorkdir !== undefined) patch.sandboxWorkdir = sandboxWorkdir;\n if (setupCommand !== undefined) patch.setupCommand = setupCommand;\n if (teardownCommand !== undefined) patch.teardownCommand = teardownCommand;\n return Object.keys(patch).length > 0 ? patch : null;\n}\n\ninterface ModelApplySession {\n thread: {\n getById: (args: { threadId: string }) => Promise<{ metadata?: Record<string, unknown> | null } | null>;\n setSettingOn: (args: { threadId: string; key: string; value: unknown }) => Promise<unknown> | unknown;\n };\n}\n\ninterface ModelApplyController {\n getSessionByResource: (resourceId: string) => Promise<ModelApplySession | undefined>;\n}\n\nfunction persistedThreadMode(metadata: Record<string, unknown> | null | undefined): string | undefined {\n if (typeof metadata?.currentModeId === 'string' && metadata.currentModeId) return metadata.currentModeId;\n const modeKeys = Object.keys(metadata ?? {}).filter(key => key.startsWith('modeModelId_'));\n if (modeKeys.length !== 1) return undefined;\n return modeKeys[0]?.slice('modeModelId_'.length) || undefined;\n}\n\nexport interface ProjectRoutesDeps extends RouteDependencies {\n /** Factory projects domain backing the CRUD surface. */\n projects: FactoryProjectsStorage;\n /** Source-control domain the connection/repository routes fan out over. */\n sourceControl: SourceControlStorage;\n /** Integration ids allowed as source-control connection targets. */\n versionControlIntegrationIds?: string[];\n /** Validate and persist a repository selected from a provider-backed listing. */\n resolveRepository?: (input: {\n integrationId: string;\n orgId: string;\n userId: string;\n installationId: string;\n externalId: string;\n slug: string;\n }) => Promise<SourceControlRepository | null>;\n /**\n * Fire-and-forget hook invoked after a repository is linked to a project —\n * kicks the initial base-checkpoint build. Must never throw.\n */\n onProjectRepositoryLinked?: (args: { orgId: string; projectRepository: ProjectRepository }) => void;\n /** Shared lifecycle for retiring sessions before their owning records are deleted. */\n sessionRetirement?: SessionRetirementCoordinator;\n /** Work-items domain used by session retirement and running-thread model updates. */\n workItems?: Pick<WorkItemsStorage, 'clearSessionReferences' | 'listRunBindings' | 'get'>;\n /** Controller used to reach the thread store behind each active binding. */\n controller?: ModelApplyController;\n}\n\nexport class ProjectRoutes extends Route<ProjectRoutesDeps> {\n readonly #versionControlIntegrationIds: Set<string>;\n\n constructor(deps: ProjectRoutesDeps) {\n super(deps);\n this.#versionControlIntegrationIds = new Set(deps.versionControlIntegrationIds ?? []);\n }\n\n async #projects(): Promise<FactoryProjectsStorage> {\n await this.deps.projects.ensureReady();\n return this.deps.projects;\n }\n\n async #sourceControl(): Promise<SourceControlStorage> {\n await this.deps.sourceControl.ensureReady();\n return this.deps.sourceControl;\n }\n\n async #handles(): Promise<SourceControlStorageHandle[]> {\n const storage = await this.#sourceControl();\n return [...this.#versionControlIntegrationIds].map(integrationId => storage.forIntegration(integrationId));\n }\n\n async #project(orgId: string, id: string) {\n return (await this.#projects()).get({ orgId, id });\n }\n\n async #findConnection({ orgId, projectId, id }: { orgId: string; projectId: string; id: string }) {\n for (const handle of await this.#handles()) {\n const connection = await handle.connections.get({ orgId, id });\n if (connection?.factoryProjectId === projectId) return { handle, connection };\n }\n return null;\n }\n\n async #findProjectRepository({ orgId, projectId, id }: { orgId: string; projectId: string; id: string }) {\n for (const handle of await this.#handles()) {\n const projectRepository = await handle.projectRepositories.get({ orgId, id });\n if (!projectRepository) continue;\n const connection = await handle.connections.get({ orgId, id: projectRepository.connectionId });\n if (connection?.factoryProjectId === projectId) return { handle, connection, projectRepository };\n }\n return null;\n }\n\n async #repositoryPayload(handle: SourceControlStorageHandle, orgId: string, projectRepository: ProjectRepository) {\n const repository = await handle.repositories.get({ orgId, id: projectRepository.repositoryId });\n return { ...projectRepository, repository };\n }\n\n async #retireProjectRepositorySessions(\n handle: SourceControlStorageHandle,\n orgId: string,\n projectRepositoryId: string,\n ): Promise<boolean> {\n const sessions = await handle.sessions.listByProjectRepository({ projectRepositoryId });\n if (sessions.length === 0) return true;\n if (!this.deps.sessionRetirement) return false;\n await this.deps.sessionRetirement.retireProjectRepositorySessions({\n sourceControl: handle,\n ...(this.deps.workItems ? { workItems: this.deps.workItems } : {}),\n orgId,\n projectRepositoryId,\n });\n return true;\n }\n\n async #resolveTenant(context: Context): Promise<{ orgId: string; userId: string } | { response: Response }> {\n await this.deps.auth.ensureUser(context);\n const tenant = this.deps.auth.tenant(context);\n if (!tenant) return { response: context.json({ error: 'unauthorized' }, 401) };\n if (!tenant.orgId) {\n return {\n response: context.json(\n { error: 'organization_required', message: 'Factory projects require an organization.' },\n 403,\n ),\n };\n }\n return { orgId: tenant.orgId, userId: tenant.userId };\n }\n\n routes(): ApiRoute[] {\n return [\n registerApiRoute(FACTORY_ROUTE_CONTRACTS.projectList.path, {\n method: FACTORY_ROUTE_CONTRACTS.projectList.method,\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n return context.json({ projects: await (await this.#projects()).list({ orgId: tenant.orgId }) });\n },\n }),\n registerApiRoute(FACTORY_ROUTE_CONTRACTS.projectCreate.path, {\n method: FACTORY_ROUTE_CONTRACTS.projectCreate.method,\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const parsed = FACTORY_ROUTE_CONTRACTS.projectCreate.bodySchema.safeParse(await readJson(context));\n if (!parsed.success) return context.json({ error: 'invalid_project' }, 400);\n const project = await (\n await this.#projects()\n ).create({ orgId: tenant.orgId, userId: tenant.userId, input: parsed.data });\n return context.json({ project }, 201);\n },\n }),\n registerApiRoute(FACTORY_ROUTE_CONTRACTS.projectGet.path, {\n method: FACTORY_ROUTE_CONTRACTS.projectGet.method,\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const parsedPath = FACTORY_ROUTE_CONTRACTS.projectGet.pathSchema.safeParse({ id: context.req.param('id') });\n if (!parsedPath.success) return context.json({ error: 'Project not found' }, 404);\n const { id } = parsedPath.data;\n const project = await this.#project(tenant.orgId, id);\n return project ? context.json({ project }) : context.json({ error: 'Project not found' }, 404);\n },\n }),\n registerApiRoute(FACTORY_ROUTE_CONTRACTS.projectUpdate.path, {\n method: FACTORY_ROUTE_CONTRACTS.projectUpdate.method,\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const parsedPath = FACTORY_ROUTE_CONTRACTS.projectUpdate.pathSchema.safeParse({\n id: context.req.param('id'),\n });\n if (!parsedPath.success) return context.json({ error: 'Project not found' }, 404);\n const parsedBody = FACTORY_ROUTE_CONTRACTS.projectUpdate.bodySchema.safeParse(await readJson(context));\n if (!parsedBody.success) return context.json({ error: 'invalid_project' }, 400);\n const project = await (\n await this.#projects()\n ).update({ orgId: tenant.orgId, id: parsedPath.data.id, input: parsedBody.data });\n return project ? context.json({ project }) : context.json({ error: 'Project not found' }, 404);\n },\n }),\n registerApiRoute(FACTORY_ROUTE_CONTRACTS.projectApplyDefaultModel.path, {\n method: FACTORY_ROUTE_CONTRACTS.projectApplyDefaultModel.method,\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n if (!(await this.deps.auth.isOrganizationAdmin(context, tenant.orgId))) {\n return context.json(\n {\n error: 'forbidden',\n message: 'Organization administrator access is required to update running sessions.',\n },\n 403,\n );\n }\n const parsedPath = FACTORY_ROUTE_CONTRACTS.projectApplyDefaultModel.pathSchema.safeParse({\n id: context.req.param('id'),\n });\n if (!parsedPath.success) return context.json({ error: 'Project not found' }, 404);\n const project = await this.#project(tenant.orgId, parsedPath.data.id);\n if (!project) return context.json({ error: 'Project not found' }, 404);\n const modelId = project.defaultModelId;\n if (!modelId) {\n return context.json(\n { error: 'default_model_not_set', message: 'Set a default model on the project first.' },\n 400,\n );\n }\n const { workItems, controller } = this.deps;\n if (!workItems || !controller) return context.json({ error: 'model_apply_unavailable' }, 503);\n\n const bindings = (await workItems.listRunBindings(tenant.orgId, project.id)).filter(\n binding => binding.status === 'active',\n );\n const seen = new Set<string>();\n const applied: string[] = [];\n const skipped: Array<{\n threadId: string;\n reason:\n | 'not-running'\n | 'work-item-missing'\n | 'stage-inactive'\n | 'thread-missing'\n | 'mode-unknown'\n | 'apply-failed';\n }> = [];\n\n for (const binding of bindings) {\n const key = `${binding.sessionId}:${binding.threadId}`;\n if (seen.has(key)) continue;\n seen.add(key);\n\n const item = await workItems.get({ orgId: tenant.orgId, id: binding.workItemId });\n if (!item || item.factoryProjectId !== project.id) {\n skipped.push({ threadId: binding.threadId, reason: 'work-item-missing' });\n continue;\n }\n if (!ACTIVE_RUN_BINDING_STAGES.has(item.stages[0] ?? '')) {\n skipped.push({ threadId: binding.threadId, reason: 'stage-inactive' });\n continue;\n }\n const session = await controller.getSessionByResource(binding.resourceId);\n if (!session) {\n skipped.push({ threadId: binding.threadId, reason: 'not-running' });\n continue;\n }\n const thread = await session.thread.getById({ threadId: binding.threadId });\n if (!thread) {\n skipped.push({ threadId: binding.threadId, reason: 'thread-missing' });\n continue;\n }\n const modeId = persistedThreadMode(thread.metadata);\n if (!modeId) {\n skipped.push({ threadId: binding.threadId, reason: 'mode-unknown' });\n continue;\n }\n try {\n await session.thread.setSettingOn({\n threadId: binding.threadId,\n key: `modeModelId_${modeId}`,\n value: modelId,\n });\n applied.push(binding.threadId);\n } catch (error) {\n console.warn('[factory] apply-default-model failed for thread', binding.threadId, error);\n skipped.push({ threadId: binding.threadId, reason: 'apply-failed' });\n }\n }\n\n return context.json({ modelId, applied, skipped });\n },\n }),\n registerApiRoute(FACTORY_ROUTE_CONTRACTS.projectDelete.path, {\n method: FACTORY_ROUTE_CONTRACTS.projectDelete.method,\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const parsedPath = FACTORY_ROUTE_CONTRACTS.projectDelete.pathSchema.safeParse({\n id: context.req.param('id'),\n });\n if (!parsedPath.success) return context.json({ error: 'Project not found' }, 404);\n const { id } = parsedPath.data;\n if (!(await this.#project(tenant.orgId, id))) return context.json({ error: 'Project not found' }, 404);\n for (const handle of await this.#handles()) {\n for (const connection of await handle.connections.list({ orgId: tenant.orgId, factoryProjectId: id })) {\n for (const projectRepository of await handle.projectRepositories.list({\n orgId: tenant.orgId,\n connectionId: connection.id,\n })) {\n if (!(await this.#retireProjectRepositorySessions(handle, tenant.orgId, projectRepository.id))) {\n return context.json({ error: 'session_retirement_unavailable' }, 409);\n }\n }\n await handle.connections.delete({ orgId: tenant.orgId, id: connection.id });\n }\n }\n await (await this.#projects()).delete({ orgId: tenant.orgId, id });\n return context.body(null, 204);\n },\n }),\n registerApiRoute('/web/factory/projects/:id/source-control-connections', {\n method: 'GET',\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const projectId = context.req.param('id');\n if (!projectId || !UUID_RE.test(projectId) || !(await this.#project(tenant.orgId, projectId)))\n return context.json({ error: 'Project not found' }, 404);\n const connections = [];\n for (const handle of await this.#handles()) {\n for (const connection of await handle.connections.list({\n orgId: tenant.orgId,\n factoryProjectId: projectId,\n })) {\n const installation = await handle.installations.get({\n orgId: tenant.orgId,\n id: connection.installationId,\n });\n // Skip orphaned connections whose installation was pruned (e.g.\n // the user uninstalled the GitHub App). Otherwise\n // `projectRepositories.list` throws `requireConnection` and the\n // whole endpoint 500s, which hangs the web UI on the page\n // loader for every project. New code cascade-deletes these on\n // installation removal, but this defensive skip lets already-\n // orphaned rows in existing databases self-heal on read.\n if (!installation) continue;\n const links = await handle.projectRepositories.list({ orgId: tenant.orgId, connectionId: connection.id });\n connections.push({\n ...connection,\n installation,\n repositories: await Promise.all(links.map(link => this.#repositoryPayload(handle, tenant.orgId, link))),\n });\n }\n }\n return context.json({ connections });\n },\n }),\n registerApiRoute('/web/factory/projects/:id/source-control-connections', {\n method: 'POST',\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const projectId = context.req.param('id');\n if (!projectId || !UUID_RE.test(projectId) || !(await this.#project(tenant.orgId, projectId)))\n return context.json({ error: 'Project not found' }, 404);\n const input = parseConnectionInput(await readJson(context));\n if (!input) return context.json({ error: 'invalid_source_control_connection' }, 400);\n if (!this.#versionControlIntegrationIds.has(input.integrationId))\n return context.json({ error: 'Source-control integration not found' }, 404);\n const handle = (await this.#sourceControl()).forIntegration(input.integrationId);\n if (!(await handle.installations.get({ orgId: tenant.orgId, id: input.installationId })))\n return context.json({ error: 'Source-control installation not found' }, 404);\n const connection = await handle.connections.create({\n orgId: tenant.orgId,\n factoryProjectId: projectId,\n installationId: input.installationId,\n createdByUserId: tenant.userId,\n });\n return context.json({ connection }, 201);\n },\n }),\n registerApiRoute('/web/factory/projects/:id/source-control-connections/:connectionId', {\n method: 'DELETE',\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const projectId = context.req.param('id');\n const connectionId = context.req.param('connectionId');\n if (!projectId || !UUID_RE.test(projectId) || !connectionId || !UUID_RE.test(connectionId))\n return context.json({ error: 'Source-control connection not found' }, 404);\n const found = await this.#findConnection({ orgId: tenant.orgId, projectId, id: connectionId });\n if (!found) return context.json({ error: 'Source-control connection not found' }, 404);\n for (const projectRepository of await found.handle.projectRepositories.list({\n orgId: tenant.orgId,\n connectionId,\n })) {\n if (!(await this.#retireProjectRepositorySessions(found.handle, tenant.orgId, projectRepository.id))) {\n return context.json({ error: 'session_retirement_unavailable' }, 409);\n }\n }\n await found.handle.connections.delete({ orgId: tenant.orgId, id: connectionId });\n return context.body(null, 204);\n },\n }),\n registerApiRoute('/web/factory/projects/:id/source-control-connections/:connectionId/repositories', {\n method: 'POST',\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const projectId = context.req.param('id');\n const connectionId = context.req.param('connectionId');\n if (!projectId || !UUID_RE.test(projectId) || !connectionId || !UUID_RE.test(connectionId))\n return context.json({ error: 'Source-control connection not found' }, 404);\n const found = await this.#findConnection({ orgId: tenant.orgId, projectId, id: connectionId });\n if (!found) return context.json({ error: 'Source-control connection not found' }, 404);\n const input = parseRepositoryLinkInput(await readJson(context));\n if (!input) return context.json({ error: 'invalid_project_repository' }, 400);\n const repository = input.repositoryId\n ? await found.handle.repositories.get({ orgId: tenant.orgId, id: input.repositoryId })\n : input.repository && this.deps.resolveRepository\n ? await this.deps.resolveRepository({\n integrationId: found.connection.integrationId,\n orgId: tenant.orgId,\n userId: tenant.userId,\n installationId: found.connection.installationId,\n ...input.repository,\n })\n : null;\n if (!repository || repository.installationId !== found.connection.installationId)\n return context.json({ error: 'Source-control repository not found' }, 404);\n const { repositoryId: _repositoryId, repository: _repository, ...linkInput } = input;\n const projectRepository = await found.handle.projectRepositories.link({\n orgId: tenant.orgId,\n connectionId,\n createdByUserId: tenant.userId,\n repositoryId: repository.id,\n ...linkInput,\n });\n try {\n this.deps.onProjectRepositoryLinked?.({ orgId: tenant.orgId, projectRepository });\n } catch (error) {\n console.warn('[factory] onProjectRepositoryLinked failed after a successful repository link:', error);\n }\n return context.json(\n { projectRepository: await this.#repositoryPayload(found.handle, tenant.orgId, projectRepository) },\n 201,\n );\n },\n }),\n registerApiRoute('/web/factory/projects/:id/repositories/:projectRepositoryId', {\n method: 'PATCH',\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const projectId = context.req.param('id');\n const projectRepositoryId = context.req.param('projectRepositoryId');\n if (!projectId || !UUID_RE.test(projectId) || !projectRepositoryId || !UUID_RE.test(projectRepositoryId))\n return context.json({ error: 'Project repository not found' }, 404);\n const found = await this.#findProjectRepository({ orgId: tenant.orgId, projectId, id: projectRepositoryId });\n if (!found) return context.json({ error: 'Project repository not found' }, 404);\n const input = parseRepositoryUpdateInput(await readJson(context));\n if (!input) return context.json({ error: 'invalid_project_repository' }, 400);\n const projectRepository = await found.handle.projectRepositories.update({\n orgId: tenant.orgId,\n id: projectRepositoryId,\n input,\n });\n return context.json({\n projectRepository: await this.#repositoryPayload(found.handle, tenant.orgId, projectRepository!),\n });\n },\n }),\n registerApiRoute('/web/factory/projects/:id/repositories/:projectRepositoryId', {\n method: 'DELETE',\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const projectId = context.req.param('id');\n const projectRepositoryId = context.req.param('projectRepositoryId');\n if (!projectId || !UUID_RE.test(projectId) || !projectRepositoryId || !UUID_RE.test(projectRepositoryId))\n return context.json({ error: 'Project repository not found' }, 404);\n const found = await this.#findProjectRepository({ orgId: tenant.orgId, projectId, id: projectRepositoryId });\n if (!found) return context.json({ error: 'Project repository not found' }, 404);\n if (!(await this.#retireProjectRepositorySessions(found.handle, tenant.orgId, projectRepositoryId))) {\n return context.json({ error: 'session_retirement_unavailable' }, 409);\n }\n await found.handle.projectRepositories.unlink({ orgId: tenant.orgId, id: projectRepositoryId });\n return context.body(null, 204);\n },\n }),\n ];\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"projects.js","names":["#versionControlIntegrationIds","#projects","#sourceControl","#handles","#project","#findConnection","#findProjectRepository","#repositoryPayload","#retireProjectRepositorySessions","#resolveTenant"],"sources":["../../src/routes/projects.ts"],"sourcesContent":["import type { ApiRoute } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\nimport type { Context } from 'hono';\n\nimport type { SessionRetirementCoordinator } from '../sandbox/session-retirement.js';\nimport type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';\nimport type {\n ProjectRepository,\n SourceControlRepository,\n SourceControlStorage,\n SourceControlStorageHandle,\n UpdateProjectRepositoryInput,\n} from '../storage/domains/source-control/base.js';\nimport { ACTIVE_RUN_BINDING_STAGES } from '../storage/domains/work-items/base.js';\nimport type { WorkItemsStorage } from '../storage/domains/work-items/base.js';\nimport { FACTORY_ROUTE_CONTRACTS } from './contracts.js';\nimport type { RouteDependencies } from './route.js';\nimport { Route } from './route.js';\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst MAX_NAME_LENGTH = 200;\nconst MAX_REPOSITORY_COMMAND_LENGTH = 2_000;\nconst MAX_BRANCH_LENGTH = 255;\nconst MAX_SANDBOX_PROVIDER_LENGTH = 100;\nconst MAX_SANDBOX_WORKDIR_LENGTH = 1_000;\nconst CONTROL_CHAR_RE = /[\\0-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]/;\n\nfunction loose(context: unknown): Context {\n return context as Context;\n}\n\nasync function readJson(context: Context): Promise<unknown | undefined> {\n try {\n return await context.req.json();\n } catch {\n return undefined;\n }\n}\n\nfunction parseConnectionInput(value: unknown): { integrationId: string; installationId: string } | null {\n if (!value || typeof value !== 'object') return null;\n const input = value as Record<string, unknown>;\n if (typeof input.integrationId !== 'string' || !input.integrationId.trim()) return null;\n if (typeof input.installationId !== 'string' || !UUID_RE.test(input.installationId)) return null;\n return { integrationId: input.integrationId.trim(), installationId: input.installationId };\n}\n\nfunction parseOptionalString(\n value: unknown,\n { maxLength, nullable = false }: { maxLength: number; nullable?: boolean },\n): string | null | undefined | false {\n if (value === undefined) return undefined;\n if (value === null) return nullable ? null : false;\n if (typeof value !== 'string') return false;\n const normalized = value.trim();\n if (!normalized) return nullable ? null : false;\n if (normalized.length > maxLength || CONTROL_CHAR_RE.test(normalized)) return false;\n return normalized;\n}\n\nfunction parseRepositoryLinkInput(value: unknown): {\n repositoryId?: string;\n repository?: { externalId: string; slug: string };\n branch: string | null;\n sandboxProvider: string;\n sandboxWorkdir: string;\n setupCommand: string | null;\n teardownCommand: string | null;\n} | null {\n if (!value || typeof value !== 'object') return null;\n const input = value as Record<string, unknown>;\n const repositoryId =\n typeof input.repositoryId === 'string' && UUID_RE.test(input.repositoryId) ? input.repositoryId : undefined;\n const repositoryInput = input.repository;\n let repository: { externalId: string; slug: string } | undefined;\n if (repositoryInput && typeof repositoryInput === 'object') {\n const candidate = repositoryInput as Record<string, unknown>;\n const externalId = parseOptionalString(candidate.externalId, { maxLength: MAX_NAME_LENGTH });\n const slug = parseOptionalString(candidate.slug, { maxLength: MAX_NAME_LENGTH });\n if (typeof externalId !== 'string' || typeof slug !== 'string') return null;\n repository = { externalId, slug };\n }\n if (!repositoryId && !repository) return null;\n const branch = parseOptionalString(input.branch, { maxLength: MAX_BRANCH_LENGTH, nullable: true });\n const sandboxProvider = parseOptionalString(input.sandboxProvider, { maxLength: MAX_SANDBOX_PROVIDER_LENGTH });\n const sandboxWorkdir = parseOptionalString(input.sandboxWorkdir, { maxLength: MAX_SANDBOX_WORKDIR_LENGTH });\n const setupCommand = parseOptionalString(input.setupCommand, {\n maxLength: MAX_REPOSITORY_COMMAND_LENGTH,\n nullable: true,\n });\n const teardownCommand = parseOptionalString(input.teardownCommand, {\n maxLength: MAX_REPOSITORY_COMMAND_LENGTH,\n nullable: true,\n });\n if (\n branch === false ||\n typeof sandboxProvider !== 'string' ||\n typeof sandboxWorkdir !== 'string' ||\n setupCommand === false ||\n teardownCommand === false\n )\n return null;\n return {\n ...(repositoryId ? { repositoryId } : {}),\n ...(repository ? { repository } : {}),\n branch: branch ?? null,\n sandboxProvider,\n sandboxWorkdir,\n setupCommand: setupCommand ?? null,\n teardownCommand: teardownCommand ?? null,\n };\n}\n\nfunction parseRepositoryUpdateInput(value: unknown): UpdateProjectRepositoryInput | null {\n if (!value || typeof value !== 'object') return null;\n const input = value as Record<string, unknown>;\n const patch: UpdateProjectRepositoryInput = {};\n const branch = parseOptionalString(input.branch, { maxLength: MAX_BRANCH_LENGTH, nullable: true });\n const sandboxProvider = parseOptionalString(input.sandboxProvider, { maxLength: MAX_SANDBOX_PROVIDER_LENGTH });\n const sandboxWorkdir = parseOptionalString(input.sandboxWorkdir, { maxLength: MAX_SANDBOX_WORKDIR_LENGTH });\n const setupCommand = parseOptionalString(input.setupCommand, {\n maxLength: MAX_REPOSITORY_COMMAND_LENGTH,\n nullable: true,\n });\n const teardownCommand = parseOptionalString(input.teardownCommand, {\n maxLength: MAX_REPOSITORY_COMMAND_LENGTH,\n nullable: true,\n });\n if (\n branch === false ||\n sandboxProvider === false ||\n sandboxProvider === null ||\n sandboxWorkdir === false ||\n sandboxWorkdir === null ||\n setupCommand === false ||\n teardownCommand === false\n )\n return null;\n if (branch !== undefined) patch.branch = branch;\n if (sandboxProvider !== undefined) patch.sandboxProvider = sandboxProvider;\n if (sandboxWorkdir !== undefined) patch.sandboxWorkdir = sandboxWorkdir;\n if (setupCommand !== undefined) patch.setupCommand = setupCommand;\n if (teardownCommand !== undefined) patch.teardownCommand = teardownCommand;\n return Object.keys(patch).length > 0 ? patch : null;\n}\n\ninterface ModelApplySession {\n thread: {\n getById: (args: { threadId: string }) => Promise<{ metadata?: Record<string, unknown> | null } | null>;\n setSettingOn: (args: { threadId: string; key: string; value: unknown }) => Promise<unknown> | unknown;\n };\n}\n\ninterface ModelApplyController {\n getSessionByResource: (resourceId: string) => Promise<ModelApplySession | undefined>;\n}\n\nexport interface ProjectRoutesDeps extends RouteDependencies {\n /** Factory projects domain backing the CRUD surface. */\n projects: FactoryProjectsStorage;\n /** Source-control domain the connection/repository routes fan out over. */\n sourceControl: SourceControlStorage;\n /** Integration ids allowed as source-control connection targets. */\n versionControlIntegrationIds?: string[];\n /** Validate and persist a repository selected from a provider-backed listing. */\n resolveRepository?: (input: {\n integrationId: string;\n orgId: string;\n userId: string;\n installationId: string;\n externalId: string;\n slug: string;\n }) => Promise<SourceControlRepository | null>;\n /**\n * Fire-and-forget hook invoked after a repository is linked to a project —\n * kicks the initial base-checkpoint build. Must never throw.\n */\n onProjectRepositoryLinked?: (args: { orgId: string; projectRepository: ProjectRepository }) => void;\n /** Shared lifecycle for retiring sessions before their owning records are deleted. */\n sessionRetirement?: SessionRetirementCoordinator;\n /** Work-items domain used by session retirement and running-thread model updates. */\n workItems?: Pick<WorkItemsStorage, 'clearSessionReferences' | 'listRunBindings' | 'get'>;\n /** Controller used to reach the thread store behind each active binding. */\n controller?: ModelApplyController;\n}\n\nexport class ProjectRoutes extends Route<ProjectRoutesDeps> {\n readonly #versionControlIntegrationIds: Set<string>;\n\n constructor(deps: ProjectRoutesDeps) {\n super(deps);\n this.#versionControlIntegrationIds = new Set(deps.versionControlIntegrationIds ?? []);\n }\n\n async #projects(): Promise<FactoryProjectsStorage> {\n await this.deps.projects.ensureReady();\n return this.deps.projects;\n }\n\n async #sourceControl(): Promise<SourceControlStorage> {\n await this.deps.sourceControl.ensureReady();\n return this.deps.sourceControl;\n }\n\n async #handles(): Promise<SourceControlStorageHandle[]> {\n const storage = await this.#sourceControl();\n return [...this.#versionControlIntegrationIds].map(integrationId => storage.forIntegration(integrationId));\n }\n\n async #project(orgId: string, id: string) {\n return (await this.#projects()).get({ orgId, id });\n }\n\n async #findConnection({ orgId, projectId, id }: { orgId: string; projectId: string; id: string }) {\n for (const handle of await this.#handles()) {\n const connection = await handle.connections.get({ orgId, id });\n if (connection?.factoryProjectId === projectId) return { handle, connection };\n }\n return null;\n }\n\n async #findProjectRepository({ orgId, projectId, id }: { orgId: string; projectId: string; id: string }) {\n for (const handle of await this.#handles()) {\n const projectRepository = await handle.projectRepositories.get({ orgId, id });\n if (!projectRepository) continue;\n const connection = await handle.connections.get({ orgId, id: projectRepository.connectionId });\n if (connection?.factoryProjectId === projectId) return { handle, connection, projectRepository };\n }\n return null;\n }\n\n async #repositoryPayload(handle: SourceControlStorageHandle, orgId: string, projectRepository: ProjectRepository) {\n const repository = await handle.repositories.get({ orgId, id: projectRepository.repositoryId });\n return { ...projectRepository, repository };\n }\n\n async #retireProjectRepositorySessions(\n handle: SourceControlStorageHandle,\n orgId: string,\n projectRepositoryId: string,\n ): Promise<boolean> {\n const sessions = await handle.sessions.listByProjectRepository({ projectRepositoryId });\n if (sessions.length === 0) return true;\n if (!this.deps.sessionRetirement) return false;\n await this.deps.sessionRetirement.retireProjectRepositorySessions({\n sourceControl: handle,\n ...(this.deps.workItems ? { workItems: this.deps.workItems } : {}),\n orgId,\n projectRepositoryId,\n });\n return true;\n }\n\n async #resolveTenant(context: Context): Promise<{ orgId: string; userId: string } | { response: Response }> {\n await this.deps.auth.ensureUser(context);\n const tenant = this.deps.auth.tenant(context);\n if (!tenant) return { response: context.json({ error: 'unauthorized' }, 401) };\n if (!tenant.orgId) {\n return {\n response: context.json(\n { error: 'organization_required', message: 'Factory projects require an organization.' },\n 403,\n ),\n };\n }\n return { orgId: tenant.orgId, userId: tenant.userId };\n }\n\n routes(): ApiRoute[] {\n return [\n registerApiRoute(FACTORY_ROUTE_CONTRACTS.projectList.path, {\n method: FACTORY_ROUTE_CONTRACTS.projectList.method,\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n return context.json({ projects: await (await this.#projects()).list({ orgId: tenant.orgId }) });\n },\n }),\n registerApiRoute(FACTORY_ROUTE_CONTRACTS.projectCreate.path, {\n method: FACTORY_ROUTE_CONTRACTS.projectCreate.method,\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const parsed = FACTORY_ROUTE_CONTRACTS.projectCreate.bodySchema.safeParse(await readJson(context));\n if (!parsed.success) return context.json({ error: 'invalid_project' }, 400);\n const project = await (\n await this.#projects()\n ).create({ orgId: tenant.orgId, userId: tenant.userId, input: parsed.data });\n return context.json({ project }, 201);\n },\n }),\n registerApiRoute(FACTORY_ROUTE_CONTRACTS.projectGet.path, {\n method: FACTORY_ROUTE_CONTRACTS.projectGet.method,\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const parsedPath = FACTORY_ROUTE_CONTRACTS.projectGet.pathSchema.safeParse({ id: context.req.param('id') });\n if (!parsedPath.success) return context.json({ error: 'Project not found' }, 404);\n const { id } = parsedPath.data;\n const project = await this.#project(tenant.orgId, id);\n return project ? context.json({ project }) : context.json({ error: 'Project not found' }, 404);\n },\n }),\n registerApiRoute(FACTORY_ROUTE_CONTRACTS.projectUpdate.path, {\n method: FACTORY_ROUTE_CONTRACTS.projectUpdate.method,\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const parsedPath = FACTORY_ROUTE_CONTRACTS.projectUpdate.pathSchema.safeParse({\n id: context.req.param('id'),\n });\n if (!parsedPath.success) return context.json({ error: 'Project not found' }, 404);\n const parsedBody = FACTORY_ROUTE_CONTRACTS.projectUpdate.bodySchema.safeParse(await readJson(context));\n if (!parsedBody.success) return context.json({ error: 'invalid_project' }, 400);\n const project = await (\n await this.#projects()\n ).update({ orgId: tenant.orgId, id: parsedPath.data.id, input: parsedBody.data });\n return project ? context.json({ project }) : context.json({ error: 'Project not found' }, 404);\n },\n }),\n registerApiRoute(FACTORY_ROUTE_CONTRACTS.projectApplyDefaultModel.path, {\n method: FACTORY_ROUTE_CONTRACTS.projectApplyDefaultModel.method,\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n if (!(await this.deps.auth.isOrganizationAdmin(context, tenant.orgId))) {\n return context.json(\n {\n error: 'forbidden',\n message: 'Organization administrator access is required to update running sessions.',\n },\n 403,\n );\n }\n const parsedPath = FACTORY_ROUTE_CONTRACTS.projectApplyDefaultModel.pathSchema.safeParse({\n id: context.req.param('id'),\n });\n if (!parsedPath.success) return context.json({ error: 'Project not found' }, 404);\n const project = await this.#project(tenant.orgId, parsedPath.data.id);\n if (!project) return context.json({ error: 'Project not found' }, 404);\n const modelId = project.defaultModelId;\n if (!modelId) {\n return context.json(\n { error: 'default_model_not_set', message: 'Set a default model on the project first.' },\n 400,\n );\n }\n const { workItems, controller } = this.deps;\n if (!workItems || !controller) return context.json({ error: 'model_apply_unavailable' }, 503);\n\n const bindings = (await workItems.listRunBindings(tenant.orgId, project.id)).filter(\n binding => binding.status === 'active',\n );\n const seen = new Set<string>();\n const applied: string[] = [];\n const skipped: Array<{\n threadId: string;\n reason:\n | 'not-running'\n | 'work-item-missing'\n | 'stage-inactive'\n | 'thread-missing'\n | 'mode-unknown'\n | 'apply-failed';\n }> = [];\n\n for (const binding of bindings) {\n const key = `${binding.sessionId}:${binding.threadId}`;\n if (seen.has(key)) continue;\n seen.add(key);\n\n const item = await workItems.get({ orgId: tenant.orgId, id: binding.workItemId });\n if (!item || item.factoryProjectId !== project.id) {\n skipped.push({ threadId: binding.threadId, reason: 'work-item-missing' });\n continue;\n }\n if (!ACTIVE_RUN_BINDING_STAGES.has(item.stages[0] ?? '')) {\n skipped.push({ threadId: binding.threadId, reason: 'stage-inactive' });\n continue;\n }\n const session = await controller.getSessionByResource(binding.resourceId);\n if (!session) {\n skipped.push({ threadId: binding.threadId, reason: 'not-running' });\n continue;\n }\n const thread = await session.thread.getById({ threadId: binding.threadId });\n if (!thread) {\n skipped.push({ threadId: binding.threadId, reason: 'thread-missing' });\n continue;\n }\n try {\n // This route targets inactive bound threads, so persist the controller-owned key through the session gateway.\n await session.thread.setSettingOn({\n threadId: binding.threadId,\n key: 'currentModelId',\n value: modelId,\n });\n applied.push(binding.threadId);\n } catch (error) {\n console.warn('[factory] apply-default-model failed for thread', binding.threadId, error);\n skipped.push({ threadId: binding.threadId, reason: 'apply-failed' });\n }\n }\n\n return context.json({ modelId, applied, skipped });\n },\n }),\n registerApiRoute(FACTORY_ROUTE_CONTRACTS.projectDelete.path, {\n method: FACTORY_ROUTE_CONTRACTS.projectDelete.method,\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const parsedPath = FACTORY_ROUTE_CONTRACTS.projectDelete.pathSchema.safeParse({\n id: context.req.param('id'),\n });\n if (!parsedPath.success) return context.json({ error: 'Project not found' }, 404);\n const { id } = parsedPath.data;\n if (!(await this.#project(tenant.orgId, id))) return context.json({ error: 'Project not found' }, 404);\n for (const handle of await this.#handles()) {\n for (const connection of await handle.connections.list({ orgId: tenant.orgId, factoryProjectId: id })) {\n for (const projectRepository of await handle.projectRepositories.list({\n orgId: tenant.orgId,\n connectionId: connection.id,\n })) {\n if (!(await this.#retireProjectRepositorySessions(handle, tenant.orgId, projectRepository.id))) {\n return context.json({ error: 'session_retirement_unavailable' }, 409);\n }\n }\n await handle.connections.delete({ orgId: tenant.orgId, id: connection.id });\n }\n }\n await (await this.#projects()).delete({ orgId: tenant.orgId, id });\n return context.body(null, 204);\n },\n }),\n registerApiRoute('/web/factory/projects/:id/source-control-connections', {\n method: 'GET',\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const projectId = context.req.param('id');\n if (!projectId || !UUID_RE.test(projectId) || !(await this.#project(tenant.orgId, projectId)))\n return context.json({ error: 'Project not found' }, 404);\n const connections = [];\n for (const handle of await this.#handles()) {\n for (const connection of await handle.connections.list({\n orgId: tenant.orgId,\n factoryProjectId: projectId,\n })) {\n const installation = await handle.installations.get({\n orgId: tenant.orgId,\n id: connection.installationId,\n });\n // Skip orphaned connections whose installation was pruned (e.g.\n // the user uninstalled the GitHub App). Otherwise\n // `projectRepositories.list` throws `requireConnection` and the\n // whole endpoint 500s, which hangs the web UI on the page\n // loader for every project. New code cascade-deletes these on\n // installation removal, but this defensive skip lets already-\n // orphaned rows in existing databases self-heal on read.\n if (!installation) continue;\n const links = await handle.projectRepositories.list({ orgId: tenant.orgId, connectionId: connection.id });\n connections.push({\n ...connection,\n installation,\n repositories: await Promise.all(links.map(link => this.#repositoryPayload(handle, tenant.orgId, link))),\n });\n }\n }\n return context.json({ connections });\n },\n }),\n registerApiRoute('/web/factory/projects/:id/source-control-connections', {\n method: 'POST',\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const projectId = context.req.param('id');\n if (!projectId || !UUID_RE.test(projectId) || !(await this.#project(tenant.orgId, projectId)))\n return context.json({ error: 'Project not found' }, 404);\n const input = parseConnectionInput(await readJson(context));\n if (!input) return context.json({ error: 'invalid_source_control_connection' }, 400);\n if (!this.#versionControlIntegrationIds.has(input.integrationId))\n return context.json({ error: 'Source-control integration not found' }, 404);\n const handle = (await this.#sourceControl()).forIntegration(input.integrationId);\n if (!(await handle.installations.get({ orgId: tenant.orgId, id: input.installationId })))\n return context.json({ error: 'Source-control installation not found' }, 404);\n const connection = await handle.connections.create({\n orgId: tenant.orgId,\n factoryProjectId: projectId,\n installationId: input.installationId,\n createdByUserId: tenant.userId,\n });\n return context.json({ connection }, 201);\n },\n }),\n registerApiRoute('/web/factory/projects/:id/source-control-connections/:connectionId', {\n method: 'DELETE',\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const projectId = context.req.param('id');\n const connectionId = context.req.param('connectionId');\n if (!projectId || !UUID_RE.test(projectId) || !connectionId || !UUID_RE.test(connectionId))\n return context.json({ error: 'Source-control connection not found' }, 404);\n const found = await this.#findConnection({ orgId: tenant.orgId, projectId, id: connectionId });\n if (!found) return context.json({ error: 'Source-control connection not found' }, 404);\n for (const projectRepository of await found.handle.projectRepositories.list({\n orgId: tenant.orgId,\n connectionId,\n })) {\n if (!(await this.#retireProjectRepositorySessions(found.handle, tenant.orgId, projectRepository.id))) {\n return context.json({ error: 'session_retirement_unavailable' }, 409);\n }\n }\n await found.handle.connections.delete({ orgId: tenant.orgId, id: connectionId });\n return context.body(null, 204);\n },\n }),\n registerApiRoute('/web/factory/projects/:id/source-control-connections/:connectionId/repositories', {\n method: 'POST',\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const projectId = context.req.param('id');\n const connectionId = context.req.param('connectionId');\n if (!projectId || !UUID_RE.test(projectId) || !connectionId || !UUID_RE.test(connectionId))\n return context.json({ error: 'Source-control connection not found' }, 404);\n const found = await this.#findConnection({ orgId: tenant.orgId, projectId, id: connectionId });\n if (!found) return context.json({ error: 'Source-control connection not found' }, 404);\n const input = parseRepositoryLinkInput(await readJson(context));\n if (!input) return context.json({ error: 'invalid_project_repository' }, 400);\n const repository = input.repositoryId\n ? await found.handle.repositories.get({ orgId: tenant.orgId, id: input.repositoryId })\n : input.repository && this.deps.resolveRepository\n ? await this.deps.resolveRepository({\n integrationId: found.connection.integrationId,\n orgId: tenant.orgId,\n userId: tenant.userId,\n installationId: found.connection.installationId,\n ...input.repository,\n })\n : null;\n if (!repository || repository.installationId !== found.connection.installationId)\n return context.json({ error: 'Source-control repository not found' }, 404);\n const { repositoryId: _repositoryId, repository: _repository, ...linkInput } = input;\n const projectRepository = await found.handle.projectRepositories.link({\n orgId: tenant.orgId,\n connectionId,\n createdByUserId: tenant.userId,\n repositoryId: repository.id,\n ...linkInput,\n });\n try {\n this.deps.onProjectRepositoryLinked?.({ orgId: tenant.orgId, projectRepository });\n } catch (error) {\n console.warn('[factory] onProjectRepositoryLinked failed after a successful repository link:', error);\n }\n return context.json(\n { projectRepository: await this.#repositoryPayload(found.handle, tenant.orgId, projectRepository) },\n 201,\n );\n },\n }),\n registerApiRoute('/web/factory/projects/:id/repositories/:projectRepositoryId', {\n method: 'PATCH',\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const projectId = context.req.param('id');\n const projectRepositoryId = context.req.param('projectRepositoryId');\n if (!projectId || !UUID_RE.test(projectId) || !projectRepositoryId || !UUID_RE.test(projectRepositoryId))\n return context.json({ error: 'Project repository not found' }, 404);\n const found = await this.#findProjectRepository({ orgId: tenant.orgId, projectId, id: projectRepositoryId });\n if (!found) return context.json({ error: 'Project repository not found' }, 404);\n const input = parseRepositoryUpdateInput(await readJson(context));\n if (!input) return context.json({ error: 'invalid_project_repository' }, 400);\n const projectRepository = await found.handle.projectRepositories.update({\n orgId: tenant.orgId,\n id: projectRepositoryId,\n input,\n });\n return context.json({\n projectRepository: await this.#repositoryPayload(found.handle, tenant.orgId, projectRepository!),\n });\n },\n }),\n registerApiRoute('/web/factory/projects/:id/repositories/:projectRepositoryId', {\n method: 'DELETE',\n requiresAuth: false,\n handler: async routeContext => {\n const context = loose(routeContext);\n const tenant = await this.#resolveTenant(context);\n if ('response' in tenant) return tenant.response;\n const projectId = context.req.param('id');\n const projectRepositoryId = context.req.param('projectRepositoryId');\n if (!projectId || !UUID_RE.test(projectId) || !projectRepositoryId || !UUID_RE.test(projectRepositoryId))\n return context.json({ error: 'Project repository not found' }, 404);\n const found = await this.#findProjectRepository({ orgId: tenant.orgId, projectId, id: projectRepositoryId });\n if (!found) return context.json({ error: 'Project repository not found' }, 404);\n if (!(await this.#retireProjectRepositorySessions(found.handle, tenant.orgId, projectRepositoryId))) {\n return context.json({ error: 'session_retirement_unavailable' }, 409);\n }\n await found.handle.projectRepositories.unlink({ orgId: tenant.orgId, id: projectRepositoryId });\n return context.body(null, 204);\n },\n }),\n ];\n }\n}\n"],"mappings":"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"}
|
package/dist/routes/surface.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ import type { FilesystemStorage } from '../storage/domains/filesystem/base.js';
|
|
|
22
22
|
import type { IntakeStorage } from '../storage/domains/intake/base.js';
|
|
23
23
|
import type { IntegrationStorage } from '../storage/domains/integrations/base.js';
|
|
24
24
|
import type { MemorySettingsStorage } from '../storage/domains/memory-settings/base.js';
|
|
25
|
-
import type {
|
|
25
|
+
import type { ModelDefaultsStorage } from '../storage/domains/model-defaults/base.js';
|
|
26
26
|
import type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';
|
|
27
27
|
import type { QueueHealthStorage } from '../storage/domains/queue-health/base.js';
|
|
28
28
|
import { type SourceControlStorage, type SourceControlStorageHandle } from '../storage/domains/source-control/base.js';
|
|
@@ -60,7 +60,7 @@ export interface FactoryApiRoutesDeps {
|
|
|
60
60
|
memorySettings: MemorySettingsStorage;
|
|
61
61
|
customProviders: CustomProvidersStorage;
|
|
62
62
|
filesystem: FilesystemStorage;
|
|
63
|
-
|
|
63
|
+
modelDefaults: ModelDefaultsStorage;
|
|
64
64
|
projects: FactoryProjectsStorage;
|
|
65
65
|
queueHealth: QueueHealthStorage;
|
|
66
66
|
workItems: WorkItemsStorage;
|
|
@@ -106,7 +106,7 @@ export declare function buildIntegrationContext(deps: Pick<FactoryApiRoutesDeps,
|
|
|
106
106
|
factoryReady: boolean;
|
|
107
107
|
/** Work-item feed service, so a channel integration can ingest platform messages. */
|
|
108
108
|
feed: CommentsDomain;
|
|
109
|
-
domains: Pick<FactoryApiRoutesDeps['domains'], 'projects' | 'intake' | 'workItems' | 'channelIdentity' | 'memorySettings' | '
|
|
109
|
+
domains: Pick<FactoryApiRoutesDeps['domains'], 'projects' | 'intake' | 'workItems' | 'channelIdentity' | 'memorySettings' | 'modelDefaults'>;
|
|
110
110
|
/**
|
|
111
111
|
* Stable id of the registered source-control-owning integration (today:
|
|
112
112
|
* `'github'` when registered). Every call site must derive and pass it so
|
|
@@ -117,7 +117,7 @@ export declare function buildIntegrationContext(deps: Pick<FactoryApiRoutesDeps,
|
|
|
117
117
|
/**
|
|
118
118
|
* Assemble the custom `/web/*` API routes as Mastra `server.apiRoutes`:
|
|
119
119
|
* - fs browser routes (project picker), confined to `fsRoot`
|
|
120
|
-
* - config routes (provider/API-key/model
|
|
120
|
+
* - config routes (provider/API-key/default-model/OM management)
|
|
121
121
|
* - every registered integration's `routes()` surface (full set when ready,
|
|
122
122
|
* disabled-status stub otherwise), plus stubs for absent known ids
|
|
123
123
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"surface.d.ts","sourceRoot":"","sources":["../../src/routes/surface.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAEtF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAG/E,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAWhF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AAC1F,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qCAAqC,CAAC;AACnF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wCAAwC,CAAC;AACtF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AAC1F,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAClF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AACxF,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"surface.d.ts","sourceRoot":"","sources":["../../src/routes/surface.ts"],"names":[],"mappings":"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"}
|
package/dist/routes/surface.js
CHANGED
|
@@ -255,7 +255,7 @@ function buildIntegrationContext(deps, integrationId) {
|
|
|
255
255
|
intake: deps.domains.intake,
|
|
256
256
|
channelIdentity: deps.domains.channelIdentity,
|
|
257
257
|
memorySettings: deps.domains.memorySettings,
|
|
258
|
-
|
|
258
|
+
modelDefaults: deps.domains.modelDefaults
|
|
259
259
|
},
|
|
260
260
|
...deps.factoryReady ? {
|
|
261
261
|
workItems: deps.domains.workItems,
|
|
@@ -352,7 +352,7 @@ function absentSlackChannelAccountsRoutes() {
|
|
|
352
352
|
/**
|
|
353
353
|
* Assemble the custom `/web/*` API routes as Mastra `server.apiRoutes`:
|
|
354
354
|
* - fs browser routes (project picker), confined to `fsRoot`
|
|
355
|
-
* - config routes (provider/API-key/model
|
|
355
|
+
* - config routes (provider/API-key/default-model/OM management)
|
|
356
356
|
* - every registered integration's `routes()` surface (full set when ready,
|
|
357
357
|
* disabled-status stub otherwise), plus stubs for absent known ids
|
|
358
358
|
*/
|
|
@@ -440,7 +440,7 @@ function assembleFactoryApiRoutes(deps) {
|
|
|
440
440
|
controller: deps.controller,
|
|
441
441
|
authStorage: deps.authStorage,
|
|
442
442
|
modelCredentials: deps.domains.modelCredentials,
|
|
443
|
-
|
|
443
|
+
modelDefaults: deps.domains.modelDefaults,
|
|
444
444
|
sourceControlSessions,
|
|
445
445
|
memorySettings: deps.domains.memorySettings,
|
|
446
446
|
factoryProjects: deps.domains.projects,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"surface.js","names":[],"sources":["../../src/routes/surface.ts"],"sourcesContent":["import type { AuthStorage } from '@mastra/code-sdk/auth/storage';\nimport type { MastraCodeState } from '@mastra/code-sdk/schema';\nimport type { AgentController } from '@mastra/core/agent-controller';\nimport type { ApiRoute, IUserProvider } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\nimport type { FactoryStorage } from '@mastra/core/storage';\n\nimport { boardForWorkItem } from '../boards/index.js';\nimport type { BoardRegistry } from '../boards/index.js';\nimport type { FactoryIntegration, IntegrationContext } from '../integrations/base.js';\nimport { getGithubFeatureDiagnostics } from '../integrations/github/config.js';\nimport type { GithubIntegration } from '../integrations/github/integration.js';\nimport { MaterializeError } from '../integrations/github/sandbox.js';\nimport { FactoryDispatchError } from '../rules/dispatch-errors.js';\nimport type { FactoryBindingPreparationInput } from '../rules/dispatcher.js';\nimport { FactoryStartCoordinator } from '../rules/start-coordinator.js';\nimport { FactoryTransitionService } from '../rules/transition-service.js';\nimport type { MastraFactorySandboxConfig } from '../sandbox/session-sandbox.js';\nimport {\n createSourceControlSessionLookup,\n ensureFactorySourceSession,\n FactorySourceSessionResolutionError,\n resolveFactoryDefaultModelId,\n resolveFactoryProjectForSession,\n resolveFactorySourceControl,\n resolveFactorySourceRepository,\n} from '../session/factory-session.js';\nimport type { EnsuredFactorySourceSession } from '../session/factory-session.js';\nimport type { LiveSessions } from '../session/live-sessions.js';\nimport { resolveWorkItemRepository } from '../session/work-item-repository.js';\nimport type { StateSigner } from '../state-signing.js';\nimport type { AuditEmitter, AuditRecorder } from '../storage/domains/audit/domain.js';\nimport type { ChannelIdentityStorage } from '../storage/domains/channel-identity/base.js';\nimport type { WorkItemCommentsStorage } from '../storage/domains/comments/base.js';\nimport type { CommentsDomain } from '../storage/domains/comments/domain.js';\nimport type { ModelCredentialsStorage } from '../storage/domains/credentials/base.js';\nimport type { CustomProvidersStorage } from '../storage/domains/custom-providers/base.js';\nimport type { FilesystemStorage } from '../storage/domains/filesystem/base.js';\nimport type { IntakeStorage } from '../storage/domains/intake/base.js';\nimport type { IntegrationStorage } from '../storage/domains/integrations/base.js';\nimport type { MemorySettingsStorage } from '../storage/domains/memory-settings/base.js';\nimport type { ModelPacksStorage } from '../storage/domains/model-packs/base.js';\nimport type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';\nimport type { QueueHealthStorage } from '../storage/domains/queue-health/base.js';\nimport {\n SourceControlConnectionNotFoundError,\n type SourceControlStorage,\n type SourceControlStorageHandle,\n} from '../storage/domains/source-control/base.js';\nimport {\n isAgentActor,\n type FactoryDispatchFailureCode,\n type WorkItemsStorage,\n} from '../storage/domains/work-items/base.js';\nimport { workItemBranch, workItemBranchSource, workItemThreadTitle } from '../work-item-branch.js';\nimport { buildAutomationRunRoutes } from './automation-runs.js';\nimport { ConfigRoutes } from './config.js';\nimport { invalidateCustomProvidersSnapshots } from './custom-provider-source.js';\nimport { buildFsRoutes } from './fs.js';\nimport { IntakeRoutes } from './intake.js';\nimport { KnowledgeRoutes } from './knowledge.js';\nimport { OAuthRoutes } from './oauth.js';\nimport type { RouteAuth } from './route.js';\nimport { SkillRoutes } from './skills.js';\nimport { buildSourceControlSessionRoutes } from './source-control-sessions.js';\nimport { buildSourceControlSettingsRoutes } from './source-control-settings.js';\nimport { invalidateTenantCredentialSnapshots } from './tenant-credentials.js';\nimport { WorkItemRoutes } from './work-items.js';\n\nconst MATERIALIZE_FAILURE_CODE = {\n 'git-missing': 'repository_git_missing',\n 'egress-blocked': 'repository_egress_blocked',\n 'clone-failed': 'repository_clone_failed',\n 'pull-failed': 'repository_pull_failed',\n 'push-failed': 'repository_push_failed',\n 'commit-failed': 'repository_commit_failed',\n 'gh-missing': 'repository_cli_missing',\n 'pr-failed': 'repository_pr_failed',\n} satisfies Record<MaterializeError['code'], FactoryDispatchFailureCode>;\nexport interface IntegrationRegistration {\n integration: FactoryIntegration;\n ready: boolean;\n ensureReady: () => Promise<void>;\n}\n\nexport interface FactoryApiRoutesDeps {\n controllerId: string;\n controller: AgentController<MastraCodeState>;\n /** Registry of the sessions this process holds, owned by the host so it can watch them too. */\n liveSessions: LiveSessions;\n /** Request-auth seam threaded from the host (no service locator). */\n auth: RouteAuth;\n /** Optional user directory for resolving persisted owners to display profiles. */\n users?: Pick<IUserProvider, 'getUser' | 'getUsers'>;\n authStorage: AuthStorage;\n audit: AuditEmitter & AuditRecorder;\n fsRoot?: string;\n publicOrigin: string;\n stateSigner?: StateSigner;\n /** Sandbox surface (enablement, provider label, create callback). */\n sandbox?: MastraFactorySandboxConfig;\n /** Root factory storage backend (distributed locks, app-db diagnostics). */\n factoryStorage?: FactoryStorage;\n integrationStorage: IntegrationStorage;\n sourceControlStorage: SourceControlStorage;\n /** App-table domain handles, registered and owned by `MastraFactory.prepare()`. */\n domains: {\n intake: IntakeStorage;\n modelCredentials: ModelCredentialsStorage;\n memorySettings: MemorySettingsStorage;\n customProviders: CustomProvidersStorage;\n filesystem: FilesystemStorage;\n modelPacks: ModelPacksStorage;\n projects: FactoryProjectsStorage;\n queueHealth: QueueHealthStorage;\n workItems: WorkItemsStorage;\n channelIdentity: ChannelIdentityStorage;\n comments: WorkItemCommentsStorage;\n };\n integrations?: IntegrationRegistration[];\n intakeReady: boolean;\n factoryReady: boolean;\n knowledgeEnabled: boolean;\n /** Resolved Factory rule set, threaded from the host (no service locator). */\n configVersion: string;\n /** Boards installed for this Factory instance. */\n boardRegistry: BoardRegistry;\n /** Work-item feed service, handed to integrations that ingest platform messages. */\n feed: CommentsDomain;\n factoryTransitionService?: FactoryTransitionService;\n sessionRetirement?: import('../sandbox/session-retirement.js').SessionRetirementCoordinator;\n onFactoryRuntime?: (runtime: {\n transitionService: FactoryTransitionService;\n prepareBinding?: (input: FactoryBindingPreparationInput) => Promise<void>;\n }) => void;\n}\n\nfunction guardIntegrationRoutes({\n integration,\n ready,\n ensureReady,\n routes,\n}: IntegrationRegistration & { routes: ApiRoute[] }): ApiRoute[] {\n if (ready) return routes;\n return routes.map(route => {\n if ('handler' in route) {\n const handler = route.handler;\n return {\n ...route,\n handler: async (context: Parameters<typeof handler>[0]) => {\n try {\n await ensureReady();\n } catch {\n return context.json(\n { error: 'integration_unavailable', message: `${integration.id} integration is unavailable.` },\n 503,\n );\n }\n return handler(context, async () => {});\n },\n };\n }\n\n const createHandler = route.createHandler;\n return {\n ...route,\n createHandler: async (args: Parameters<typeof createHandler>[0]) => {\n const handler = await createHandler(args);\n return async (context: Parameters<typeof handler>[0]) => {\n try {\n await ensureReady();\n } catch {\n return context.json(\n { error: 'integration_unavailable', message: `${integration.id} integration is unavailable.` },\n 503,\n );\n }\n return handler(context);\n };\n },\n };\n });\n}\n\n/**\n * Resolve the source-control session the work item already holds for this role,\n * when it still resolves to the item's org and factory project. Returns\n * `undefined` when there is no ref or the ref no longer resolves, so the caller\n * falls back to minting one.\n */\nasync function reuseBoundSession(\n sourceControl: SourceControlStorageHandle,\n input: FactoryBindingPreparationInput,\n role: string = input.role,\n): Promise<EnsuredFactorySourceSession | undefined> {\n const ref = input.item.sessions[role];\n if (!ref) return undefined;\n // At least as strict as the coordinator's resolveSourceSession: a ref it\n // would reject must fall through to minting, not hard-fail the run.\n const resolved = await resolveFactoryProjectForSession({ sourceControl, sessionId: ref.sessionId });\n if (\n !resolved ||\n resolved.orgId !== input.record.orgId ||\n resolved.factoryProjectId !== input.record.factoryProjectId\n ) {\n return undefined;\n }\n const session = await sourceControl.sessions.getBySessionId(ref.sessionId);\n if (!session) return undefined;\n return {\n sessionId: session.sessionId,\n userId: session.userId,\n projectRepositoryId: session.projectRepositoryId,\n branch: session.branch,\n baseBranch: session.baseBranch,\n };\n}\n\n/** Roles whose sessions a later role may continue in, newest stage first. */\nconst INHERITABLE_ROLE_FALLBACK = ['plan', 'triage'];\n\n/**\n * A role running for the first time continues in the card's latest earlier\n * session on the same branch, so a build approved by someone other than the\n * plan's owner keeps the plan's context instead of starting empty. Review is\n * independent by design and never inherits.\n */\nasync function inheritEarlierSession(\n sourceControl: SourceControlStorageHandle,\n input: FactoryBindingPreparationInput,\n board: { roleForPhase(phase: string): string | undefined } | undefined,\n branch: string,\n repositorySlug: string,\n): Promise<EnsuredFactorySourceSession | undefined> {\n if (input.role === 'review') return undefined;\n // The card's linked repository can change after an earlier role ran; only\n // continue in a session on the repository a fresh session would use.\n const repository = await resolveFactorySourceRepository({\n sourceControl,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n repositorySlug,\n });\n if (!repository.found) return undefined;\n const candidates: string[] = [];\n for (const entry of [...(input.item.stageHistory ?? [])].reverse()) {\n const role = board?.roleForPhase(entry.stage);\n if (role && role !== input.role && role !== 'review' && !candidates.includes(role)) candidates.push(role);\n }\n for (const role of INHERITABLE_ROLE_FALLBACK) {\n if (role !== input.role && !candidates.includes(role)) candidates.push(role);\n }\n for (const role of candidates) {\n const session = await reuseBoundSession(sourceControl, input, role);\n if (session && session.branch === branch && session.projectRepositoryId === repository.projectRepositoryId) {\n return session;\n }\n }\n return undefined;\n}\n\n/**\n * Start a factory run for a rule binding: ensure the source-control session the\n * coordinator requires, then hand it to `prepare` along with the factory's\n * default model. Exported for tests — this is the autonomous entry point with no\n * browser and no interactive user, so nothing else would catch a regression in\n * what it forwards.\n */\nexport async function prepareFactoryRuleBinding(\n sourceControlProvider: SourceControlStorageHandle | Pick<GithubIntegration, 'sourceControlStorage'>,\n coordinator: Pick<FactoryStartCoordinator, 'prepare'>,\n projects: FactoryProjectsStorage,\n boards: BoardRegistry,\n input: FactoryBindingPreparationInput,\n intake?: Pick<IntakeStorage, 'getConfig'>,\n): Promise<void> {\n try {\n const sourceControl =\n 'sourceControlStorage' in sourceControlProvider\n ? sourceControlProvider.sourceControlStorage\n : sourceControlProvider;\n const source = workItemBranchSource(input.item.externalSource);\n const branch = workItemBranch({ id: input.item.id, source, metadata: input.item.metadata });\n // Only leaving a resting phase derives a lane from the role: roles don't own lanes,\n // and the Done close-out running in the triage seat must not drag the card back.\n // Both the current phase and the role's lane come from the installed board; an\n // unknown board or phase yields no destination rather than a guessed one.\n const board = boards.get(boardForWorkItem(input.item));\n const currentStage = input.item.stages.length === 1 ? input.item.stages[0] : undefined;\n const currentKind = currentStage === undefined ? undefined : board?.phaseKind(currentStage);\n const destinationStage =\n currentKind === undefined\n ? undefined\n : currentKind === 'resting'\n ? board?.phaseForRole(input.role)\n : currentStage;\n if (!destinationStage) {\n throw new FactoryDispatchError(\n 'unsupported_provider_item',\n `Factory skill invocation has no destination lane (role \"${input.role}\", stages [${input.item.stages.join(', ')}]).`,\n );\n }\n const connections = await sourceControl.connections.list({\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n });\n if (!connections.some(connection => connection.integrationId === sourceControl.integrationId)) {\n throw new FactoryDispatchError('source_control_missing', 'Factory source-control connection not found.');\n }\n // A retry may already own a role session. Check it before treating a\n // repository-less card as ambiguous, but never override an explicit signal.\n const boundSession = await reuseBoundSession(sourceControl, input);\n const intakeConfig = await intake?.getConfig({ orgId: input.record.orgId, integrationIds: ['linear'] });\n let repository = await resolveWorkItemRepository({\n sourceControl,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n item: input.item,\n linearRepositoryMap: intakeConfig?.linear?.repositoryByLinearProject,\n });\n if (repository.status === 'ambiguous' && boundSession) {\n const link = await sourceControl.projectRepositories.get({\n orgId: input.record.orgId,\n id: boundSession.projectRepositoryId,\n });\n const linked =\n link && (await sourceControl.repositories.get({ orgId: input.record.orgId, id: link.repositoryId }));\n if (linked && repository.candidates.includes(linked.slug)) {\n const match = await resolveFactorySourceRepository({\n sourceControl,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n repositorySlug: linked.slug,\n });\n if (match.found && match.projectRepositoryId === boundSession.projectRepositoryId) {\n repository = { status: 'resolved', slug: linked.slug, projectRepositoryId: match.projectRepositoryId };\n }\n }\n }\n if (repository.status !== 'resolved') {\n const detail =\n repository.status === 'ambiguous'\n ? `Choose one of the linked repositories: ${repository.candidates.join(', ')}.`\n : repository.hint;\n throw new FactoryDispatchError('source_repository_ambiguous', detail);\n }\n // Re-preparing a binding (server restart, retired controller session) must\n // land in the role's existing session: minting a replacement would repoint\n // the work item, flip the session's owner to the approver, and orphan the\n // previous sandbox.\n const approver = input.record.approvedBy ?? undefined;\n if (boundSession && boundSession.projectRepositoryId !== repository.projectRepositoryId) {\n throw new FactoryDispatchError(\n 'source_repository_ambiguous',\n `The existing session is bound to a different repository than ${repository.slug}. Choose the correct repository and retry.`,\n );\n }\n const preparedSession =\n boundSession ??\n (await inheritEarlierSession(sourceControl, input, board, branch, repository.slug)) ??\n (await ensureFactorySourceSession({\n sourceControl,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n repositorySlug: repository.slug,\n branch,\n // A person who approved the run is its interactive user: attribute it to\n // them, not the repo connector. An agent's pre-approval names no person.\n attributeToUserId: isAgentActor(approver) ? undefined : approver,\n }));\n\n await coordinator.prepare({\n orgId: input.record.orgId,\n userId: preparedSession.userId,\n factoryProjectId: input.record.factoryProjectId,\n sessionId: preparedSession.sessionId,\n defaultModelId: await resolveFactoryDefaultModelId(projects, input.record.factoryProjectId),\n threadTitle: workItemThreadTitle({ source, title: input.item.title, metadata: input.item.metadata }),\n kickoffKey: input.record.id,\n destinationStage,\n workItem: {\n id: input.item.id,\n role: input.role,\n input: {\n externalSource: input.item.externalSource,\n parentWorkItemId: input.item.parentWorkItemId,\n title: input.item.title,\n stages: ['intake'],\n sessions: input.item.sessions,\n metadata: input.item.metadata,\n },\n },\n });\n } catch (error) {\n if (error instanceof FactoryDispatchError) throw error;\n if (error instanceof FactorySourceSessionResolutionError) {\n const code = error.reason === 'connection' ? 'source_control_missing' : 'source_repository_missing';\n throw new FactoryDispatchError(code, error.message, { cause: error });\n }\n if (error instanceof SourceControlConnectionNotFoundError) {\n throw new FactoryDispatchError('source_control_missing', error.message, { cause: error });\n }\n if (error instanceof MaterializeError) {\n throw new FactoryDispatchError(MATERIALIZE_FAILURE_CODE[error.code], error.message, { cause: error });\n }\n throw error;\n }\n}\n\n/**\n * Build the {@link IntegrationContext} handed to an integration when the\n * factory collects its capabilities (routes, workers). One shape everywhere:\n * `assembleFactoryApiRoutes` uses it per registration, and `MastraFactory` uses it\n * when collecting integration workers at finalize.\n */\nexport function buildIntegrationContext(\n deps: Pick<\n FactoryApiRoutesDeps,\n | 'controller'\n | 'publicOrigin'\n | 'auth'\n | 'sandbox'\n | 'users'\n | 'factoryStorage'\n | 'integrationStorage'\n | 'sourceControlStorage'\n | 'integrations'\n > & {\n stateSigner: StateSigner;\n emitAudit?: AuditEmitter['emit'];\n configVersion: string;\n boardRegistry: BoardRegistry;\n factoryReady: boolean;\n /** Work-item feed service, so a channel integration can ingest platform messages. */\n feed: CommentsDomain;\n domains: Pick<\n FactoryApiRoutesDeps['domains'],\n 'projects' | 'intake' | 'workItems' | 'channelIdentity' | 'memorySettings' | 'modelPacks'\n >;\n /**\n * Stable id of the registered source-control-owning integration (today:\n * `'github'` when registered). Every call site must derive and pass it so\n * `routes()`, `channels()`, and `workers()` all see the same context shape.\n */\n sourceControlOwnerId?: string;\n },\n integrationId: string,\n): IntegrationContext {\n return {\n auth: deps.auth,\n sandbox: deps.sandbox,\n ...(deps.users ? { users: deps.users } : {}),\n factoryStorage: deps.factoryStorage,\n baseUrl: deps.publicOrigin,\n controller: deps.controller,\n stateSigner: deps.stateSigner,\n storage: {\n generic: deps.integrationStorage.forIntegration(integrationId),\n sourceControl: deps.sourceControlStorage.forIntegration(integrationId),\n ...(deps.sourceControlOwnerId\n ? { sourceControlOwner: deps.sourceControlStorage.forIntegration(deps.sourceControlOwnerId) }\n : {}),\n sourceControls: (deps.integrations ?? [])\n .filter(({ integration }) => integration.versionControl)\n .map(({ integration }) => deps.sourceControlStorage.forIntegration(integration.id)),\n projects: deps.domains.projects,\n intake: deps.domains.intake,\n channelIdentity: deps.domains.channelIdentity,\n memorySettings: deps.domains.memorySettings,\n modelPacks: deps.domains.modelPacks,\n },\n ...(deps.factoryReady ? { workItems: deps.domains.workItems, feed: deps.feed } : {}),\n ...(deps.factoryReady\n ? {\n runtime: { configVersion: deps.configVersion, workItems: deps.domains.workItems, boards: deps.boardRegistry },\n }\n : {}),\n ...(deps.emitAudit ? { hooks: { emitAudit: deps.emitAudit } } : {}),\n };\n}\n\n/**\n * Disabled-status stub for the well-known integration ids. The SPA polls\n * `/web/github/status`, `/web/linear/status`, and `/web/jira/status`\n * unconditionally, so when an integration is absent (or not ready) the status\n * contract must still hold. Unknown custom ids get no stub — the SPA doesn't\n * poll them.\n */\nfunction disabledIntegrationStatusRoutes(deps: FactoryApiRoutesDeps, id: string, configured = false): ApiRoute[] {\n if (id === 'github') {\n return [\n registerApiRoute('/web/github/status', {\n method: 'GET',\n requiresAuth: false,\n handler: c =>\n c.json({\n enabled: false,\n connected: false,\n installations: [],\n reason: 'missing_config',\n diagnostics: getGithubFeatureDiagnostics({\n github: undefined,\n auth: deps.auth,\n appDbConfigured: deps.factoryStorage !== undefined,\n stateSigner: deps.stateSigner,\n sandbox: deps.sandbox,\n }),\n }),\n }),\n ];\n }\n if (id === 'linear') {\n return [\n registerApiRoute('/web/linear/status', {\n method: 'GET',\n requiresAuth: false,\n handler: c =>\n c.json({\n enabled: false,\n connected: false,\n workspace: null,\n reason: 'missing_config',\n diagnostics: {\n linearAppConfigured: configured,\n factoryAuthEnabled: deps.auth.enabled(),\n appDbConfigured: true,\n },\n }),\n }),\n ];\n }\n if (id === 'jira') {\n return [\n registerApiRoute('/web/jira/status', {\n method: 'GET',\n requiresAuth: false,\n handler: c =>\n c.json({\n enabled: false,\n configured,\n site: null,\n reason: 'missing_config',\n diagnostics: {\n jiraConfigured: configured,\n factoryAuthEnabled: deps.auth.enabled(),\n appDbConfigured: deps.factoryStorage !== undefined,\n },\n }),\n }),\n ];\n }\n return [];\n}\n\n/**\n * Stub for `GET /web/channel-accounts` when NO Slack integration is\n * registered. The SPA's Connections section polls the path unconditionally;\n * without a stub the SPA fallback serves HTML, which the UI can only read as\n * \"old server / unknown\". The machine-readable reason lets it say the truth:\n * the integration isn't registered.\n *\n * Mounted only for ABSENT slack — a registered integration owns the path via\n * its connect routes (or, when the state signer is unstable, gets no routes\n * at all and the UI falls back to the generic copy). Static payload, leaks\n * nothing → no auth needed, same posture as the github/linear stubs.\n */\nfunction absentSlackChannelAccountsRoutes(): ApiRoute[] {\n return [\n registerApiRoute('/web/channel-accounts', {\n method: 'GET',\n requiresAuth: false,\n handler: c => c.json({ accounts: [], canConnect: false, reason: 'not_registered' }),\n }),\n ];\n}\n\n/**\n * Assemble the custom `/web/*` API routes as Mastra `server.apiRoutes`:\n * - fs browser routes (project picker), confined to `fsRoot`\n * - config routes (provider/API-key/model-pack/OM management)\n * - every registered integration's `routes()` surface (full set when ready,\n * disabled-status stub otherwise), plus stubs for absent known ids\n */\nexport function assembleFactoryApiRoutes(deps: FactoryApiRoutesDeps): ApiRoute[] {\n const emitAudit: AuditEmitter['emit'] = args => deps.audit.emit(args);\n const registrations = deps.integrations ?? [];\n const githubRegistration = registrations.find(({ integration }) => integration.id === 'github');\n const githubStorage = githubRegistration ? deps.sourceControlStorage.forIntegration('github') : undefined;\n const githubIntegration = githubRegistration?.integration as GithubIntegration | undefined;\n const sourceControlRegistrations = registrations.filter(({ integration }) => integration.versionControl);\n const sourceControlIntegrationIds = [\n ...new Set(['github', ...sourceControlRegistrations.map(({ integration }) => integration.id)]),\n ];\n const sourceControls = sourceControlIntegrationIds.map(id => deps.sourceControlStorage.forIntegration(id));\n const sourceControlSessions = createSourceControlSessionLookup(sourceControls);\n\n const integrationRoutes = registrations.flatMap(registration => {\n const { integration } = registration;\n if (!deps.stateSigner) return disabledIntegrationStatusRoutes(deps, integration.id, true);\n const context = buildIntegrationContext(\n {\n ...deps,\n stateSigner: deps.stateSigner,\n emitAudit,\n ...(githubRegistration ? { sourceControlOwnerId: 'github' } : {}),\n },\n integration.id,\n );\n return guardIntegrationRoutes({ ...registration, routes: integration.routes(context) });\n });\n // Session persistence belongs to the linked source-control provider, not to\n // GitHub. Replace legacy GitHub-owned handlers with one resolver spanning\n // the legacy GitHub partition and every registered source-control partition.\n const sharedSessionRouteKeys = new Set([\n 'GET /web/github/projects/:id/sessions',\n 'POST /web/github/projects/:id/sessions',\n 'GET /web/user-sessions/:sessionId',\n 'DELETE /web/user-sessions/:sessionId',\n 'POST /web/user-sessions/:sessionId/title',\n ]);\n const providerRoutes = integrationRoutes.filter(\n route => !sharedSessionRouteKeys.has(route.method + ' ' + route.path),\n );\n const sourceControlSessionRoutes =\n sourceControls.length === 0\n ? []\n : buildSourceControlSessionRoutes({\n auth: deps.auth,\n sourceControls,\n ...(deps.users ? { users: deps.users } : {}),\n controller: deps.controller,\n memorySettings: deps.domains.memorySettings,\n sessionRetirement: deps.sessionRetirement,\n ...(deps.factoryReady ? { workItems: deps.domains.workItems } : {}),\n });\n // Absent known integrations still get their disabled-status stub.\n const absentStubs = ['github', 'linear', 'jira']\n .filter(id => !registrations.some(({ integration }) => integration.id === id))\n .flatMap(id => disabledIntegrationStatusRoutes(deps, id));\n // Absent slack gets the channel-accounts not-registered stub (registered\n // slack owns the path via its own connect routes).\n const slackAbsentStubs = registrations.some(({ integration }) => integration.id === 'slack')\n ? []\n : absentSlackChannelAccountsRoutes();\n\n const transitionService = deps.factoryReady\n ? (deps.factoryTransitionService ??\n new FactoryTransitionService({\n configVersion: deps.configVersion,\n boards: deps.boardRegistry,\n storage: deps.domains.workItems,\n audit: deps.audit,\n }))\n : undefined;\n const startCoordinator = transitionService\n ? new FactoryStartCoordinator(\n deps.controller,\n deps.domains.workItems,\n transitionService,\n request =>\n resolveFactorySourceControl({\n sourceControls,\n orgId: request.orgId,\n factoryProjectId: request.factoryProjectId,\n sessionId: request.sessionId,\n }),\n deps.domains.memorySettings,\n deps.domains.intake,\n )\n : undefined;\n if (transitionService && startCoordinator) {\n deps.onFactoryRuntime?.({\n transitionService,\n ...(sourceControlRegistrations.length > 0\n ? {\n prepareBinding: async (input: FactoryBindingPreparationInput) => {\n const sourceControl = await resolveFactorySourceControl({\n sourceControls,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n });\n if (!sourceControl) {\n throw new FactoryDispatchError(\n 'source_control_missing',\n 'Factory project has no linked source-control repository.',\n );\n }\n return prepareFactoryRuleBinding(\n sourceControl,\n startCoordinator,\n deps.domains.projects,\n deps.boardRegistry,\n input,\n deps.domains.intake,\n );\n },\n }\n : {}),\n });\n }\n\n return [\n ...buildFsRoutes({\n root: deps.fsRoot,\n sessionFs: {\n auth: deps.auth,\n sessions: sourceControlSessions,\n filesystem: deps.domains.filesystem,\n },\n }),\n ...new ConfigRoutes({\n auth: deps.auth,\n controller: deps.controller,\n authStorage: deps.authStorage,\n modelCredentials: deps.domains.modelCredentials,\n modelPacks: deps.domains.modelPacks,\n sourceControlSessions,\n memorySettings: deps.domains.memorySettings,\n factoryProjects: deps.domains.projects,\n customProviders: deps.domains.customProviders,\n features: { knowledge: deps.knowledgeEnabled },\n onCredentialsChanged: invalidateTenantCredentialSnapshots,\n onCustomProvidersChanged: invalidateCustomProvidersSnapshots,\n }).routes(),\n ...new OAuthRoutes({\n auth: deps.auth,\n authStorage: deps.authStorage,\n modelCredentials: deps.domains.modelCredentials,\n memorySettings: deps.domains.memorySettings,\n onCredentialsChanged: invalidateTenantCredentialSnapshots,\n }).routes(),\n ...new SkillRoutes({\n auth: deps.auth,\n controllerId: deps.controllerId,\n controller: deps.controller,\n sourceControlStorage: githubStorage,\n ensureSourceControlReady: githubRegistration?.ensureReady,\n }).routes(),\n ...sourceControlSessionRoutes,\n ...(sourceControls.length === 0 ? [] : buildSourceControlSettingsRoutes({ auth: deps.auth, sourceControls })),\n ...providerRoutes,\n ...absentStubs,\n ...slackAbsentStubs,\n ...(deps.intakeReady\n ? new IntakeRoutes({\n auth: deps.auth,\n audit: deps.audit,\n intake: deps.domains.intake,\n projects: deps.domains.projects,\n boardRegistry: deps.boardRegistry,\n // Relocation reads and writes work items, which init fail-soft separately from intake.\n ...(deps.factoryReady ? { workItems: deps.domains.workItems } : {}),\n integrations: (deps.integrations ?? []).flatMap(({ integration }) =>\n integration.intake ? [{ id: integration.id, intake: integration.intake }] : [],\n ),\n }).routes()\n : []),\n ...(deps.factoryReady && deps.knowledgeEnabled\n ? new KnowledgeRoutes({\n auth: deps.auth,\n projects: deps.domains.projects,\n knowledge: async () => deps.factoryStorage?.getMastraStorage().getStore('knowledge'),\n }).routes()\n : []),\n ...(deps.factoryReady\n ? new WorkItemRoutes({\n auth: deps.auth,\n audit: deps.audit,\n projects: deps.domains.projects,\n workItems: deps.domains.workItems,\n boardRegistry: deps.boardRegistry,\n comments: deps.domains.comments,\n queueHealth: deps.domains.queueHealth,\n transitionService,\n startCoordinator,\n liveSessions: deps.liveSessions,\n }).routes()\n : []),\n ...(deps.factoryReady\n ? buildAutomationRunRoutes({\n auth: deps.auth,\n audit: deps.audit,\n projects: deps.domains.projects,\n workItems: deps.domains.workItems,\n configVersion: deps.configVersion,\n })\n : []),\n ];\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAqEA,MAAM,2BAA2B;CAC/B,eAAe;CACf,kBAAkB;CAClB,gBAAgB;CAChB,eAAe;CACf,eAAe;CACf,iBAAiB;CACjB,cAAc;CACd,aAAa;AACf;AA2DA,SAAS,uBAAuB,EAC9B,aACA,OACA,aACA,UAC+D;CAC/D,IAAI,OAAO,OAAO;CAClB,OAAO,OAAO,KAAI,UAAS;EACzB,IAAI,aAAa,OAAO;GACtB,MAAM,UAAU,MAAM;GACtB,OAAO;IACL,GAAG;IACH,SAAS,OAAO,YAA2C;KACzD,IAAI;MACF,MAAM,YAAY;KACpB,QAAQ;MACN,OAAO,QAAQ,KACb;OAAE,OAAO;OAA2B,SAAS,GAAG,YAAY,GAAG;MAA8B,GAC7F,GACF;KACF;KACA,OAAO,QAAQ,SAAS,YAAY,CAAC,CAAC;IACxC;GACF;EACF;EAEA,MAAM,gBAAgB,MAAM;EAC5B,OAAO;GACL,GAAG;GACH,eAAe,OAAO,SAA8C;IAClE,MAAM,UAAU,MAAM,cAAc,IAAI;IACxC,OAAO,OAAO,YAA2C;KACvD,IAAI;MACF,MAAM,YAAY;KACpB,QAAQ;MACN,OAAO,QAAQ,KACb;OAAE,OAAO;OAA2B,SAAS,GAAG,YAAY,GAAG;MAA8B,GAC7F,GACF;KACF;KACA,OAAO,QAAQ,OAAO;IACxB;GACF;EACF;CACF,CAAC;AACH;;;;;;;AAQA,eAAe,kBACb,eACA,OACA,OAAe,MAAM,MAC6B;CAClD,MAAM,MAAM,MAAM,KAAK,SAAS;CAChC,IAAI,CAAC,KAAK,OAAO,KAAA;CAGjB,MAAM,WAAW,MAAM,gCAAgC;EAAE;EAAe,WAAW,IAAI;CAAU,CAAC;CAClG,IACE,CAAC,YACD,SAAS,UAAU,MAAM,OAAO,SAChC,SAAS,qBAAqB,MAAM,OAAO,kBAE3C;CAEF,MAAM,UAAU,MAAM,cAAc,SAAS,eAAe,IAAI,SAAS;CACzE,IAAI,CAAC,SAAS,OAAO,KAAA;CACrB,OAAO;EACL,WAAW,QAAQ;EACnB,QAAQ,QAAQ;EAChB,qBAAqB,QAAQ;EAC7B,QAAQ,QAAQ;EAChB,YAAY,QAAQ;CACtB;AACF;;AAGA,MAAM,4BAA4B,CAAC,QAAQ,QAAQ;;;;;;;AAQnD,eAAe,sBACb,eACA,OACA,OACA,QACA,gBACkD;CAClD,IAAI,MAAM,SAAS,UAAU,OAAO,KAAA;CAGpC,MAAM,aAAa,MAAM,+BAA+B;EACtD;EACA,OAAO,MAAM,OAAO;EACpB,kBAAkB,MAAM,OAAO;EAC/B;CACF,CAAC;CACD,IAAI,CAAC,WAAW,OAAO,OAAO,KAAA;CAC9B,MAAM,aAAuB,CAAC;CAC9B,KAAK,MAAM,SAAS,CAAC,GAAI,MAAM,KAAK,gBAAgB,CAAC,CAAE,CAAC,CAAC,QAAQ,GAAG;EAClE,MAAM,OAAO,OAAO,aAAa,MAAM,KAAK;EAC5C,IAAI,QAAQ,SAAS,MAAM,QAAQ,SAAS,YAAY,CAAC,WAAW,SAAS,IAAI,GAAG,WAAW,KAAK,IAAI;CAC1G;CACA,KAAK,MAAM,QAAQ,2BACjB,IAAI,SAAS,MAAM,QAAQ,CAAC,WAAW,SAAS,IAAI,GAAG,WAAW,KAAK,IAAI;CAE7E,KAAK,MAAM,QAAQ,YAAY;EAC7B,MAAM,UAAU,MAAM,kBAAkB,eAAe,OAAO,IAAI;EAClE,IAAI,WAAW,QAAQ,WAAW,UAAU,QAAQ,wBAAwB,WAAW,qBACrF,OAAO;CAEX;AAEF;;;;;;;;AASA,eAAsB,0BACpB,uBACA,aACA,UACA,QACA,OACA,QACe;CACf,IAAI;EACF,MAAM,gBACJ,0BAA0B,wBACtB,sBAAsB,uBACtB;EACN,MAAM,SAAS,qBAAqB,MAAM,KAAK,cAAc;EAC7D,MAAM,SAAS,eAAe;GAAE,IAAI,MAAM,KAAK;GAAI;GAAQ,UAAU,MAAM,KAAK;EAAS,CAAC;EAK1F,MAAM,QAAQ,OAAO,IAAI,iBAAiB,MAAM,IAAI,CAAC;EACrD,MAAM,eAAe,MAAM,KAAK,OAAO,WAAW,IAAI,MAAM,KAAK,OAAO,KAAK,KAAA;EAC7E,MAAM,cAAc,iBAAiB,KAAA,IAAY,KAAA,IAAY,OAAO,UAAU,YAAY;EAC1F,MAAM,mBACJ,gBAAgB,KAAA,IACZ,KAAA,IACA,gBAAgB,YACd,OAAO,aAAa,MAAM,IAAI,IAC9B;EACR,IAAI,CAAC,kBACH,MAAM,IAAI,qBACR,6BACA,2DAA2D,MAAM,KAAK,aAAa,MAAM,KAAK,OAAO,KAAK,IAAI,EAAE,IAClH;EAMF,IAAI,EAAC,MAJqB,cAAc,YAAY,KAAK;GACvD,OAAO,MAAM,OAAO;GACpB,kBAAkB,MAAM,OAAO;EACjC,CAAC,EAAA,CACgB,MAAK,eAAc,WAAW,kBAAkB,cAAc,aAAa,GAC1F,MAAM,IAAI,qBAAqB,0BAA0B,8CAA8C;EAIzG,MAAM,eAAe,MAAM,kBAAkB,eAAe,KAAK;EACjE,MAAM,eAAe,MAAM,QAAQ,UAAU;GAAE,OAAO,MAAM,OAAO;GAAO,gBAAgB,CAAC,QAAQ;EAAE,CAAC;EACtG,IAAI,aAAa,MAAM,0BAA0B;GAC/C;GACA,OAAO,MAAM,OAAO;GACpB,kBAAkB,MAAM,OAAO;GAC/B,MAAM,MAAM;GACZ,qBAAqB,cAAc,QAAQ;EAC7C,CAAC;EACD,IAAI,WAAW,WAAW,eAAe,cAAc;GACrD,MAAM,OAAO,MAAM,cAAc,oBAAoB,IAAI;IACvD,OAAO,MAAM,OAAO;IACpB,IAAI,aAAa;GACnB,CAAC;GACD,MAAM,SACJ,QAAS,MAAM,cAAc,aAAa,IAAI;IAAE,OAAO,MAAM,OAAO;IAAO,IAAI,KAAK;GAAa,CAAC;GACpG,IAAI,UAAU,WAAW,WAAW,SAAS,OAAO,IAAI,GAAG;IACzD,MAAM,QAAQ,MAAM,+BAA+B;KACjD;KACA,OAAO,MAAM,OAAO;KACpB,kBAAkB,MAAM,OAAO;KAC/B,gBAAgB,OAAO;IACzB,CAAC;IACD,IAAI,MAAM,SAAS,MAAM,wBAAwB,aAAa,qBAC5D,aAAa;KAAE,QAAQ;KAAY,MAAM,OAAO;KAAM,qBAAqB,MAAM;IAAoB;GAEzG;EACF;EACA,IAAI,WAAW,WAAW,YAKxB,MAAM,IAAI,qBAAqB,+BAH7B,WAAW,WAAW,cAClB,0CAA0C,WAAW,WAAW,KAAK,IAAI,EAAE,KAC3E,WAAW,IACmD;EAMtE,MAAM,WAAW,MAAM,OAAO,cAAc,KAAA;EAC5C,IAAI,gBAAgB,aAAa,wBAAwB,WAAW,qBAClE,MAAM,IAAI,qBACR,+BACA,gEAAgE,WAAW,KAAK,2CAClF;EAEF,MAAM,kBACJ,gBACC,MAAM,sBAAsB,eAAe,OAAO,OAAO,QAAQ,WAAW,IAAI,KAChF,MAAM,2BAA2B;GAChC;GACA,OAAO,MAAM,OAAO;GACpB,kBAAkB,MAAM,OAAO;GAC/B,gBAAgB,WAAW;GAC3B;GAGA,mBAAmB,aAAa,QAAQ,IAAI,KAAA,IAAY;EAC1D,CAAC;EAEH,MAAM,YAAY,QAAQ;GACxB,OAAO,MAAM,OAAO;GACpB,QAAQ,gBAAgB;GACxB,kBAAkB,MAAM,OAAO;GAC/B,WAAW,gBAAgB;GAC3B,gBAAgB,MAAM,6BAA6B,UAAU,MAAM,OAAO,gBAAgB;GAC1F,aAAa,oBAAoB;IAAE;IAAQ,OAAO,MAAM,KAAK;IAAO,UAAU,MAAM,KAAK;GAAS,CAAC;GACnG,YAAY,MAAM,OAAO;GACzB;GACA,UAAU;IACR,IAAI,MAAM,KAAK;IACf,MAAM,MAAM;IACZ,OAAO;KACL,gBAAgB,MAAM,KAAK;KAC3B,kBAAkB,MAAM,KAAK;KAC7B,OAAO,MAAM,KAAK;KAClB,QAAQ,CAAC,QAAQ;KACjB,UAAU,MAAM,KAAK;KACrB,UAAU,MAAM,KAAK;IACvB;GACF;EACF,CAAC;CACH,SAAS,OAAO;EACd,IAAI,iBAAiB,sBAAsB,MAAM;EACjD,IAAI,iBAAiB,qCAEnB,MAAM,IAAI,qBADG,MAAM,WAAW,eAAe,2BAA2B,6BACnC,MAAM,SAAS,EAAE,OAAO,MAAM,CAAC;EAEtE,IAAI,iBAAiB,sCACnB,MAAM,IAAI,qBAAqB,0BAA0B,MAAM,SAAS,EAAE,OAAO,MAAM,CAAC;EAE1F,IAAI,iBAAiB,kBACnB,MAAM,IAAI,qBAAqB,yBAAyB,MAAM,OAAO,MAAM,SAAS,EAAE,OAAO,MAAM,CAAC;EAEtG,MAAM;CACR;AACF;;;;;;;AAQA,SAAgB,wBACd,MA8BA,eACoB;CACpB,OAAO;EACL,MAAM,KAAK;EACX,SAAS,KAAK;EACd,GAAI,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;EAC1C,gBAAgB,KAAK;EACrB,SAAS,KAAK;EACd,YAAY,KAAK;EACjB,aAAa,KAAK;EAClB,SAAS;GACP,SAAS,KAAK,mBAAmB,eAAe,aAAa;GAC7D,eAAe,KAAK,qBAAqB,eAAe,aAAa;GACrE,GAAI,KAAK,uBACL,EAAE,oBAAoB,KAAK,qBAAqB,eAAe,KAAK,oBAAoB,EAAE,IAC1F,CAAC;GACL,iBAAiB,KAAK,gBAAgB,CAAC,EAAA,CACpC,QAAQ,EAAE,kBAAkB,YAAY,cAAc,CAAC,CACvD,KAAK,EAAE,kBAAkB,KAAK,qBAAqB,eAAe,YAAY,EAAE,CAAC;GACpF,UAAU,KAAK,QAAQ;GACvB,QAAQ,KAAK,QAAQ;GACrB,iBAAiB,KAAK,QAAQ;GAC9B,gBAAgB,KAAK,QAAQ;GAC7B,YAAY,KAAK,QAAQ;EAC3B;EACA,GAAI,KAAK,eAAe;GAAE,WAAW,KAAK,QAAQ;GAAW,MAAM,KAAK;EAAK,IAAI,CAAC;EAClF,GAAI,KAAK,eACL,EACE,SAAS;GAAE,eAAe,KAAK;GAAe,WAAW,KAAK,QAAQ;GAAW,QAAQ,KAAK;EAAc,EAC9G,IACA,CAAC;EACL,GAAI,KAAK,YAAY,EAAE,OAAO,EAAE,WAAW,KAAK,UAAU,EAAE,IAAI,CAAC;CACnE;AACF;;;;;;;;AASA,SAAS,gCAAgC,MAA4B,IAAY,aAAa,OAAmB;CAC/G,IAAI,OAAO,UACT,OAAO,CACL,iBAAiB,sBAAsB;EACrC,QAAQ;EACR,cAAc;EACd,UAAS,MACP,EAAE,KAAK;GACL,SAAS;GACT,WAAW;GACX,eAAe,CAAC;GAChB,QAAQ;GACR,aAAa,4BAA4B;IACvC,QAAQ,KAAA;IACR,MAAM,KAAK;IACX,iBAAiB,KAAK,mBAAmB,KAAA;IACzC,aAAa,KAAK;IAClB,SAAS,KAAK;GAChB,CAAC;EACH,CAAC;CACL,CAAC,CACH;CAEF,IAAI,OAAO,UACT,OAAO,CACL,iBAAiB,sBAAsB;EACrC,QAAQ;EACR,cAAc;EACd,UAAS,MACP,EAAE,KAAK;GACL,SAAS;GACT,WAAW;GACX,WAAW;GACX,QAAQ;GACR,aAAa;IACX,qBAAqB;IACrB,oBAAoB,KAAK,KAAK,QAAQ;IACtC,iBAAiB;GACnB;EACF,CAAC;CACL,CAAC,CACH;CAEF,IAAI,OAAO,QACT,OAAO,CACL,iBAAiB,oBAAoB;EACnC,QAAQ;EACR,cAAc;EACd,UAAS,MACP,EAAE,KAAK;GACL,SAAS;GACT;GACA,MAAM;GACN,QAAQ;GACR,aAAa;IACX,gBAAgB;IAChB,oBAAoB,KAAK,KAAK,QAAQ;IACtC,iBAAiB,KAAK,mBAAmB,KAAA;GAC3C;EACF,CAAC;CACL,CAAC,CACH;CAEF,OAAO,CAAC;AACV;;;;;;;;;;;;;AAcA,SAAS,mCAA+C;CACtD,OAAO,CACL,iBAAiB,yBAAyB;EACxC,QAAQ;EACR,cAAc;EACd,UAAS,MAAK,EAAE,KAAK;GAAE,UAAU,CAAC;GAAG,YAAY;GAAO,QAAQ;EAAiB,CAAC;CACpF,CAAC,CACH;AACF;;;;;;;;AASA,SAAgB,yBAAyB,MAAwC;CAC/E,MAAM,aAAkC,SAAQ,KAAK,MAAM,KAAK,IAAI;CACpE,MAAM,gBAAgB,KAAK,gBAAgB,CAAC;CAC5C,MAAM,qBAAqB,cAAc,MAAM,EAAE,kBAAkB,YAAY,OAAO,QAAQ;CAC9F,MAAM,gBAAgB,qBAAqB,KAAK,qBAAqB,eAAe,QAAQ,IAAI,KAAA;CACtE,oBAAoB;CAC9C,MAAM,6BAA6B,cAAc,QAAQ,EAAE,kBAAkB,YAAY,cAAc;CAIvG,MAAM,iBAAiB,CAFrB,mBAAG,IAAI,IAAI,CAAC,UAAU,GAAG,2BAA2B,KAAK,EAAE,kBAAkB,YAAY,EAAE,CAAC,CAAC,CAE9C,CAAC,CAAC,KAAI,OAAM,KAAK,qBAAqB,eAAe,EAAE,CAAC;CACzG,MAAM,wBAAwB,iCAAiC,cAAc;CAE7E,MAAM,oBAAoB,cAAc,SAAQ,iBAAgB;EAC9D,MAAM,EAAE,gBAAgB;EACxB,IAAI,CAAC,KAAK,aAAa,OAAO,gCAAgC,MAAM,YAAY,IAAI,IAAI;EACxF,MAAM,UAAU,wBACd;GACE,GAAG;GACH,aAAa,KAAK;GAClB;GACA,GAAI,qBAAqB,EAAE,sBAAsB,SAAS,IAAI,CAAC;EACjE,GACA,YAAY,EACd;EACA,OAAO,uBAAuB;GAAE,GAAG;GAAc,QAAQ,YAAY,OAAO,OAAO;EAAE,CAAC;CACxF,CAAC;CAID,MAAM,yCAAyB,IAAI,IAAI;EACrC;EACA;EACA;EACA;EACA;CACF,CAAC;CACD,MAAM,iBAAiB,kBAAkB,QACvC,UAAS,CAAC,uBAAuB,IAAI,MAAM,SAAS,MAAM,MAAM,IAAI,CACtE;CACA,MAAM,6BACJ,eAAe,WAAW,IACtB,CAAC,IACD,gCAAgC;EAC9B,MAAM,KAAK;EACX;EACA,GAAI,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;EAC1C,YAAY,KAAK;EACjB,gBAAgB,KAAK,QAAQ;EAC7B,mBAAmB,KAAK;EACxB,GAAI,KAAK,eAAe,EAAE,WAAW,KAAK,QAAQ,UAAU,IAAI,CAAC;CACnE,CAAC;CAEP,MAAM,cAAc;EAAC;EAAU;EAAU;CAAM,CAAC,CAC7C,QAAO,OAAM,CAAC,cAAc,MAAM,EAAE,kBAAkB,YAAY,OAAO,EAAE,CAAC,CAAC,CAC7E,SAAQ,OAAM,gCAAgC,MAAM,EAAE,CAAC;CAG1D,MAAM,mBAAmB,cAAc,MAAM,EAAE,kBAAkB,YAAY,OAAO,OAAO,IACvF,CAAC,IACD,iCAAiC;CAErC,MAAM,oBAAoB,KAAK,eAC1B,KAAK,4BACN,IAAI,yBAAyB;EAC3B,eAAe,KAAK;EACpB,QAAQ,KAAK;EACb,SAAS,KAAK,QAAQ;EACtB,OAAO,KAAK;CACd,CAAC,IACD,KAAA;CACJ,MAAM,mBAAmB,oBACrB,IAAI,wBACF,KAAK,YACL,KAAK,QAAQ,WACb,oBACA,YACE,4BAA4B;EAC1B;EACA,OAAO,QAAQ;EACf,kBAAkB,QAAQ;EAC1B,WAAW,QAAQ;CACrB,CAAC,GACH,KAAK,QAAQ,gBACb,KAAK,QAAQ,MACf,IACA,KAAA;CACJ,IAAI,qBAAqB,kBACvB,KAAK,mBAAmB;EACtB;EACA,GAAI,2BAA2B,SAAS,IACpC,EACE,gBAAgB,OAAO,UAA0C;GAC/D,MAAM,gBAAgB,MAAM,4BAA4B;IACtD;IACA,OAAO,MAAM,OAAO;IACpB,kBAAkB,MAAM,OAAO;GACjC,CAAC;GACD,IAAI,CAAC,eACH,MAAM,IAAI,qBACR,0BACA,0DACF;GAEF,OAAO,0BACL,eACA,kBACA,KAAK,QAAQ,UACb,KAAK,eACL,OACA,KAAK,QAAQ,MACf;EACF,EACF,IACA,CAAC;CACP,CAAC;CAGH,OAAO;EACL,GAAG,cAAc;GACf,MAAM,KAAK;GACX,WAAW;IACT,MAAM,KAAK;IACX,UAAU;IACV,YAAY,KAAK,QAAQ;GAC3B;EACF,CAAC;EACD,GAAG,IAAI,aAAa;GAClB,MAAM,KAAK;GACX,YAAY,KAAK;GACjB,aAAa,KAAK;GAClB,kBAAkB,KAAK,QAAQ;GAC/B,YAAY,KAAK,QAAQ;GACzB;GACA,gBAAgB,KAAK,QAAQ;GAC7B,iBAAiB,KAAK,QAAQ;GAC9B,iBAAiB,KAAK,QAAQ;GAC9B,UAAU,EAAE,WAAW,KAAK,iBAAiB;GAC7C,sBAAsB;GACtB,0BAA0B;EAC5B,CAAC,CAAC,CAAC,OAAO;EACV,GAAG,IAAI,YAAY;GACjB,MAAM,KAAK;GACX,aAAa,KAAK;GAClB,kBAAkB,KAAK,QAAQ;GAC/B,gBAAgB,KAAK,QAAQ;GAC7B,sBAAsB;EACxB,CAAC,CAAC,CAAC,OAAO;EACV,GAAG,IAAI,YAAY;GACjB,MAAM,KAAK;GACX,cAAc,KAAK;GACnB,YAAY,KAAK;GACjB,sBAAsB;GACtB,0BAA0B,oBAAoB;EAChD,CAAC,CAAC,CAAC,OAAO;EACV,GAAG;EACH,GAAI,eAAe,WAAW,IAAI,CAAC,IAAI,iCAAiC;GAAE,MAAM,KAAK;GAAM;EAAe,CAAC;EAC3G,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAI,KAAK,cACL,IAAI,aAAa;GACf,MAAM,KAAK;GACX,OAAO,KAAK;GACZ,QAAQ,KAAK,QAAQ;GACrB,UAAU,KAAK,QAAQ;GACvB,eAAe,KAAK;GAEpB,GAAI,KAAK,eAAe,EAAE,WAAW,KAAK,QAAQ,UAAU,IAAI,CAAC;GACjE,eAAe,KAAK,gBAAgB,CAAC,EAAA,CAAG,SAAS,EAAE,kBACjD,YAAY,SAAS,CAAC;IAAE,IAAI,YAAY;IAAI,QAAQ,YAAY;GAAO,CAAC,IAAI,CAAC,CAC/E;EACF,CAAC,CAAC,CAAC,OAAO,IACV,CAAC;EACL,GAAI,KAAK,gBAAgB,KAAK,mBAC1B,IAAI,gBAAgB;GAClB,MAAM,KAAK;GACX,UAAU,KAAK,QAAQ;GACvB,WAAW,YAAY,KAAK,gBAAgB,iBAAiB,CAAC,CAAC,SAAS,WAAW;EACrF,CAAC,CAAC,CAAC,OAAO,IACV,CAAC;EACL,GAAI,KAAK,eACL,IAAI,eAAe;GACjB,MAAM,KAAK;GACX,OAAO,KAAK;GACZ,UAAU,KAAK,QAAQ;GACvB,WAAW,KAAK,QAAQ;GACxB,eAAe,KAAK;GACpB,UAAU,KAAK,QAAQ;GACvB,aAAa,KAAK,QAAQ;GAC1B;GACA;GACA,cAAc,KAAK;EACrB,CAAC,CAAC,CAAC,OAAO,IACV,CAAC;EACL,GAAI,KAAK,eACL,yBAAyB;GACvB,MAAM,KAAK;GACX,OAAO,KAAK;GACZ,UAAU,KAAK,QAAQ;GACvB,WAAW,KAAK,QAAQ;GACxB,eAAe,KAAK;EACtB,CAAC,IACD,CAAC;CACP;AACF"}
|
|
1
|
+
{"version":3,"file":"surface.js","names":[],"sources":["../../src/routes/surface.ts"],"sourcesContent":["import type { AuthStorage } from '@mastra/code-sdk/auth/storage';\nimport type { MastraCodeState } from '@mastra/code-sdk/schema';\nimport type { AgentController } from '@mastra/core/agent-controller';\nimport type { ApiRoute, IUserProvider } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\nimport type { FactoryStorage } from '@mastra/core/storage';\n\nimport { boardForWorkItem } from '../boards/index.js';\nimport type { BoardRegistry } from '../boards/index.js';\nimport type { FactoryIntegration, IntegrationContext } from '../integrations/base.js';\nimport { getGithubFeatureDiagnostics } from '../integrations/github/config.js';\nimport type { GithubIntegration } from '../integrations/github/integration.js';\nimport { MaterializeError } from '../integrations/github/sandbox.js';\nimport { FactoryDispatchError } from '../rules/dispatch-errors.js';\nimport type { FactoryBindingPreparationInput } from '../rules/dispatcher.js';\nimport { FactoryStartCoordinator } from '../rules/start-coordinator.js';\nimport { FactoryTransitionService } from '../rules/transition-service.js';\nimport type { MastraFactorySandboxConfig } from '../sandbox/session-sandbox.js';\nimport {\n createSourceControlSessionLookup,\n ensureFactorySourceSession,\n FactorySourceSessionResolutionError,\n resolveFactoryDefaultModelId,\n resolveFactoryProjectForSession,\n resolveFactorySourceControl,\n resolveFactorySourceRepository,\n} from '../session/factory-session.js';\nimport type { EnsuredFactorySourceSession } from '../session/factory-session.js';\nimport type { LiveSessions } from '../session/live-sessions.js';\nimport { resolveWorkItemRepository } from '../session/work-item-repository.js';\nimport type { StateSigner } from '../state-signing.js';\nimport type { AuditEmitter, AuditRecorder } from '../storage/domains/audit/domain.js';\nimport type { ChannelIdentityStorage } from '../storage/domains/channel-identity/base.js';\nimport type { WorkItemCommentsStorage } from '../storage/domains/comments/base.js';\nimport type { CommentsDomain } from '../storage/domains/comments/domain.js';\nimport type { ModelCredentialsStorage } from '../storage/domains/credentials/base.js';\nimport type { CustomProvidersStorage } from '../storage/domains/custom-providers/base.js';\nimport type { FilesystemStorage } from '../storage/domains/filesystem/base.js';\nimport type { IntakeStorage } from '../storage/domains/intake/base.js';\nimport type { IntegrationStorage } from '../storage/domains/integrations/base.js';\nimport type { MemorySettingsStorage } from '../storage/domains/memory-settings/base.js';\nimport type { ModelDefaultsStorage } from '../storage/domains/model-defaults/base.js';\nimport type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';\nimport type { QueueHealthStorage } from '../storage/domains/queue-health/base.js';\nimport {\n SourceControlConnectionNotFoundError,\n type SourceControlStorage,\n type SourceControlStorageHandle,\n} from '../storage/domains/source-control/base.js';\nimport {\n isAgentActor,\n type FactoryDispatchFailureCode,\n type WorkItemsStorage,\n} from '../storage/domains/work-items/base.js';\nimport { workItemBranch, workItemBranchSource, workItemThreadTitle } from '../work-item-branch.js';\nimport { buildAutomationRunRoutes } from './automation-runs.js';\nimport { ConfigRoutes } from './config.js';\nimport { invalidateCustomProvidersSnapshots } from './custom-provider-source.js';\nimport { buildFsRoutes } from './fs.js';\nimport { IntakeRoutes } from './intake.js';\nimport { KnowledgeRoutes } from './knowledge.js';\nimport { OAuthRoutes } from './oauth.js';\nimport type { RouteAuth } from './route.js';\nimport { SkillRoutes } from './skills.js';\nimport { buildSourceControlSessionRoutes } from './source-control-sessions.js';\nimport { buildSourceControlSettingsRoutes } from './source-control-settings.js';\nimport { invalidateTenantCredentialSnapshots } from './tenant-credentials.js';\nimport { WorkItemRoutes } from './work-items.js';\n\nconst MATERIALIZE_FAILURE_CODE = {\n 'git-missing': 'repository_git_missing',\n 'egress-blocked': 'repository_egress_blocked',\n 'clone-failed': 'repository_clone_failed',\n 'pull-failed': 'repository_pull_failed',\n 'push-failed': 'repository_push_failed',\n 'commit-failed': 'repository_commit_failed',\n 'gh-missing': 'repository_cli_missing',\n 'pr-failed': 'repository_pr_failed',\n} satisfies Record<MaterializeError['code'], FactoryDispatchFailureCode>;\nexport interface IntegrationRegistration {\n integration: FactoryIntegration;\n ready: boolean;\n ensureReady: () => Promise<void>;\n}\n\nexport interface FactoryApiRoutesDeps {\n controllerId: string;\n controller: AgentController<MastraCodeState>;\n /** Registry of the sessions this process holds, owned by the host so it can watch them too. */\n liveSessions: LiveSessions;\n /** Request-auth seam threaded from the host (no service locator). */\n auth: RouteAuth;\n /** Optional user directory for resolving persisted owners to display profiles. */\n users?: Pick<IUserProvider, 'getUser' | 'getUsers'>;\n authStorage: AuthStorage;\n audit: AuditEmitter & AuditRecorder;\n fsRoot?: string;\n publicOrigin: string;\n stateSigner?: StateSigner;\n /** Sandbox surface (enablement, provider label, create callback). */\n sandbox?: MastraFactorySandboxConfig;\n /** Root factory storage backend (distributed locks, app-db diagnostics). */\n factoryStorage?: FactoryStorage;\n integrationStorage: IntegrationStorage;\n sourceControlStorage: SourceControlStorage;\n /** App-table domain handles, registered and owned by `MastraFactory.prepare()`. */\n domains: {\n intake: IntakeStorage;\n modelCredentials: ModelCredentialsStorage;\n memorySettings: MemorySettingsStorage;\n customProviders: CustomProvidersStorage;\n filesystem: FilesystemStorage;\n modelDefaults: ModelDefaultsStorage;\n projects: FactoryProjectsStorage;\n queueHealth: QueueHealthStorage;\n workItems: WorkItemsStorage;\n channelIdentity: ChannelIdentityStorage;\n comments: WorkItemCommentsStorage;\n };\n integrations?: IntegrationRegistration[];\n intakeReady: boolean;\n factoryReady: boolean;\n knowledgeEnabled: boolean;\n /** Resolved Factory rule set, threaded from the host (no service locator). */\n configVersion: string;\n /** Boards installed for this Factory instance. */\n boardRegistry: BoardRegistry;\n /** Work-item feed service, handed to integrations that ingest platform messages. */\n feed: CommentsDomain;\n factoryTransitionService?: FactoryTransitionService;\n sessionRetirement?: import('../sandbox/session-retirement.js').SessionRetirementCoordinator;\n onFactoryRuntime?: (runtime: {\n transitionService: FactoryTransitionService;\n prepareBinding?: (input: FactoryBindingPreparationInput) => Promise<void>;\n }) => void;\n}\n\nfunction guardIntegrationRoutes({\n integration,\n ready,\n ensureReady,\n routes,\n}: IntegrationRegistration & { routes: ApiRoute[] }): ApiRoute[] {\n if (ready) return routes;\n return routes.map(route => {\n if ('handler' in route) {\n const handler = route.handler;\n return {\n ...route,\n handler: async (context: Parameters<typeof handler>[0]) => {\n try {\n await ensureReady();\n } catch {\n return context.json(\n { error: 'integration_unavailable', message: `${integration.id} integration is unavailable.` },\n 503,\n );\n }\n return handler(context, async () => {});\n },\n };\n }\n\n const createHandler = route.createHandler;\n return {\n ...route,\n createHandler: async (args: Parameters<typeof createHandler>[0]) => {\n const handler = await createHandler(args);\n return async (context: Parameters<typeof handler>[0]) => {\n try {\n await ensureReady();\n } catch {\n return context.json(\n { error: 'integration_unavailable', message: `${integration.id} integration is unavailable.` },\n 503,\n );\n }\n return handler(context);\n };\n },\n };\n });\n}\n\n/**\n * Resolve the source-control session the work item already holds for this role,\n * when it still resolves to the item's org and factory project. Returns\n * `undefined` when there is no ref or the ref no longer resolves, so the caller\n * falls back to minting one.\n */\nasync function reuseBoundSession(\n sourceControl: SourceControlStorageHandle,\n input: FactoryBindingPreparationInput,\n role: string = input.role,\n): Promise<EnsuredFactorySourceSession | undefined> {\n const ref = input.item.sessions[role];\n if (!ref) return undefined;\n // At least as strict as the coordinator's resolveSourceSession: a ref it\n // would reject must fall through to minting, not hard-fail the run.\n const resolved = await resolveFactoryProjectForSession({ sourceControl, sessionId: ref.sessionId });\n if (\n !resolved ||\n resolved.orgId !== input.record.orgId ||\n resolved.factoryProjectId !== input.record.factoryProjectId\n ) {\n return undefined;\n }\n const session = await sourceControl.sessions.getBySessionId(ref.sessionId);\n if (!session) return undefined;\n return {\n sessionId: session.sessionId,\n userId: session.userId,\n projectRepositoryId: session.projectRepositoryId,\n branch: session.branch,\n baseBranch: session.baseBranch,\n };\n}\n\n/** Roles whose sessions a later role may continue in, newest stage first. */\nconst INHERITABLE_ROLE_FALLBACK = ['plan', 'triage'];\n\n/**\n * A role running for the first time continues in the card's latest earlier\n * session on the same branch, so a build approved by someone other than the\n * plan's owner keeps the plan's context instead of starting empty. Review is\n * independent by design and never inherits.\n */\nasync function inheritEarlierSession(\n sourceControl: SourceControlStorageHandle,\n input: FactoryBindingPreparationInput,\n board: { roleForPhase(phase: string): string | undefined } | undefined,\n branch: string,\n repositorySlug: string,\n): Promise<EnsuredFactorySourceSession | undefined> {\n if (input.role === 'review') return undefined;\n // The card's linked repository can change after an earlier role ran; only\n // continue in a session on the repository a fresh session would use.\n const repository = await resolveFactorySourceRepository({\n sourceControl,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n repositorySlug,\n });\n if (!repository.found) return undefined;\n const candidates: string[] = [];\n for (const entry of [...(input.item.stageHistory ?? [])].reverse()) {\n const role = board?.roleForPhase(entry.stage);\n if (role && role !== input.role && role !== 'review' && !candidates.includes(role)) candidates.push(role);\n }\n for (const role of INHERITABLE_ROLE_FALLBACK) {\n if (role !== input.role && !candidates.includes(role)) candidates.push(role);\n }\n for (const role of candidates) {\n const session = await reuseBoundSession(sourceControl, input, role);\n if (session && session.branch === branch && session.projectRepositoryId === repository.projectRepositoryId) {\n return session;\n }\n }\n return undefined;\n}\n\n/**\n * Start a factory run for a rule binding: ensure the source-control session the\n * coordinator requires, then hand it to `prepare` along with the factory's\n * default model. Exported for tests — this is the autonomous entry point with no\n * browser and no interactive user, so nothing else would catch a regression in\n * what it forwards.\n */\nexport async function prepareFactoryRuleBinding(\n sourceControlProvider: SourceControlStorageHandle | Pick<GithubIntegration, 'sourceControlStorage'>,\n coordinator: Pick<FactoryStartCoordinator, 'prepare'>,\n projects: FactoryProjectsStorage,\n boards: BoardRegistry,\n input: FactoryBindingPreparationInput,\n intake?: Pick<IntakeStorage, 'getConfig'>,\n): Promise<void> {\n try {\n const sourceControl =\n 'sourceControlStorage' in sourceControlProvider\n ? sourceControlProvider.sourceControlStorage\n : sourceControlProvider;\n const source = workItemBranchSource(input.item.externalSource);\n const branch = workItemBranch({ id: input.item.id, source, metadata: input.item.metadata });\n // Only leaving a resting phase derives a lane from the role: roles don't own lanes,\n // and the Done close-out running in the triage seat must not drag the card back.\n // Both the current phase and the role's lane come from the installed board; an\n // unknown board or phase yields no destination rather than a guessed one.\n const board = boards.get(boardForWorkItem(input.item));\n const currentStage = input.item.stages.length === 1 ? input.item.stages[0] : undefined;\n const currentKind = currentStage === undefined ? undefined : board?.phaseKind(currentStage);\n const destinationStage =\n currentKind === undefined\n ? undefined\n : currentKind === 'resting'\n ? board?.phaseForRole(input.role)\n : currentStage;\n if (!destinationStage) {\n throw new FactoryDispatchError(\n 'unsupported_provider_item',\n `Factory skill invocation has no destination lane (role \"${input.role}\", stages [${input.item.stages.join(', ')}]).`,\n );\n }\n const connections = await sourceControl.connections.list({\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n });\n if (!connections.some(connection => connection.integrationId === sourceControl.integrationId)) {\n throw new FactoryDispatchError('source_control_missing', 'Factory source-control connection not found.');\n }\n // A retry may already own a role session. Check it before treating a\n // repository-less card as ambiguous, but never override an explicit signal.\n const boundSession = await reuseBoundSession(sourceControl, input);\n const intakeConfig = await intake?.getConfig({ orgId: input.record.orgId, integrationIds: ['linear'] });\n let repository = await resolveWorkItemRepository({\n sourceControl,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n item: input.item,\n linearRepositoryMap: intakeConfig?.linear?.repositoryByLinearProject,\n });\n if (repository.status === 'ambiguous' && boundSession) {\n const link = await sourceControl.projectRepositories.get({\n orgId: input.record.orgId,\n id: boundSession.projectRepositoryId,\n });\n const linked =\n link && (await sourceControl.repositories.get({ orgId: input.record.orgId, id: link.repositoryId }));\n if (linked && repository.candidates.includes(linked.slug)) {\n const match = await resolveFactorySourceRepository({\n sourceControl,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n repositorySlug: linked.slug,\n });\n if (match.found && match.projectRepositoryId === boundSession.projectRepositoryId) {\n repository = { status: 'resolved', slug: linked.slug, projectRepositoryId: match.projectRepositoryId };\n }\n }\n }\n if (repository.status !== 'resolved') {\n const detail =\n repository.status === 'ambiguous'\n ? `Choose one of the linked repositories: ${repository.candidates.join(', ')}.`\n : repository.hint;\n throw new FactoryDispatchError('source_repository_ambiguous', detail);\n }\n // Re-preparing a binding (server restart, retired controller session) must\n // land in the role's existing session: minting a replacement would repoint\n // the work item, flip the session's owner to the approver, and orphan the\n // previous sandbox.\n const approver = input.record.approvedBy ?? undefined;\n if (boundSession && boundSession.projectRepositoryId !== repository.projectRepositoryId) {\n throw new FactoryDispatchError(\n 'source_repository_ambiguous',\n `The existing session is bound to a different repository than ${repository.slug}. Choose the correct repository and retry.`,\n );\n }\n const preparedSession =\n boundSession ??\n (await inheritEarlierSession(sourceControl, input, board, branch, repository.slug)) ??\n (await ensureFactorySourceSession({\n sourceControl,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n repositorySlug: repository.slug,\n branch,\n // A person who approved the run is its interactive user: attribute it to\n // them, not the repo connector. An agent's pre-approval names no person.\n attributeToUserId: isAgentActor(approver) ? undefined : approver,\n }));\n\n await coordinator.prepare({\n orgId: input.record.orgId,\n userId: preparedSession.userId,\n factoryProjectId: input.record.factoryProjectId,\n sessionId: preparedSession.sessionId,\n defaultModelId: await resolveFactoryDefaultModelId(projects, input.record.factoryProjectId),\n threadTitle: workItemThreadTitle({ source, title: input.item.title, metadata: input.item.metadata }),\n kickoffKey: input.record.id,\n destinationStage,\n workItem: {\n id: input.item.id,\n role: input.role,\n input: {\n externalSource: input.item.externalSource,\n parentWorkItemId: input.item.parentWorkItemId,\n title: input.item.title,\n stages: ['intake'],\n sessions: input.item.sessions,\n metadata: input.item.metadata,\n },\n },\n });\n } catch (error) {\n if (error instanceof FactoryDispatchError) throw error;\n if (error instanceof FactorySourceSessionResolutionError) {\n const code = error.reason === 'connection' ? 'source_control_missing' : 'source_repository_missing';\n throw new FactoryDispatchError(code, error.message, { cause: error });\n }\n if (error instanceof SourceControlConnectionNotFoundError) {\n throw new FactoryDispatchError('source_control_missing', error.message, { cause: error });\n }\n if (error instanceof MaterializeError) {\n throw new FactoryDispatchError(MATERIALIZE_FAILURE_CODE[error.code], error.message, { cause: error });\n }\n throw error;\n }\n}\n\n/**\n * Build the {@link IntegrationContext} handed to an integration when the\n * factory collects its capabilities (routes, workers). One shape everywhere:\n * `assembleFactoryApiRoutes` uses it per registration, and `MastraFactory` uses it\n * when collecting integration workers at finalize.\n */\nexport function buildIntegrationContext(\n deps: Pick<\n FactoryApiRoutesDeps,\n | 'controller'\n | 'publicOrigin'\n | 'auth'\n | 'sandbox'\n | 'users'\n | 'factoryStorage'\n | 'integrationStorage'\n | 'sourceControlStorage'\n | 'integrations'\n > & {\n stateSigner: StateSigner;\n emitAudit?: AuditEmitter['emit'];\n configVersion: string;\n boardRegistry: BoardRegistry;\n factoryReady: boolean;\n /** Work-item feed service, so a channel integration can ingest platform messages. */\n feed: CommentsDomain;\n domains: Pick<\n FactoryApiRoutesDeps['domains'],\n 'projects' | 'intake' | 'workItems' | 'channelIdentity' | 'memorySettings' | 'modelDefaults'\n >;\n /**\n * Stable id of the registered source-control-owning integration (today:\n * `'github'` when registered). Every call site must derive and pass it so\n * `routes()`, `channels()`, and `workers()` all see the same context shape.\n */\n sourceControlOwnerId?: string;\n },\n integrationId: string,\n): IntegrationContext {\n return {\n auth: deps.auth,\n sandbox: deps.sandbox,\n ...(deps.users ? { users: deps.users } : {}),\n factoryStorage: deps.factoryStorage,\n baseUrl: deps.publicOrigin,\n controller: deps.controller,\n stateSigner: deps.stateSigner,\n storage: {\n generic: deps.integrationStorage.forIntegration(integrationId),\n sourceControl: deps.sourceControlStorage.forIntegration(integrationId),\n ...(deps.sourceControlOwnerId\n ? { sourceControlOwner: deps.sourceControlStorage.forIntegration(deps.sourceControlOwnerId) }\n : {}),\n sourceControls: (deps.integrations ?? [])\n .filter(({ integration }) => integration.versionControl)\n .map(({ integration }) => deps.sourceControlStorage.forIntegration(integration.id)),\n projects: deps.domains.projects,\n intake: deps.domains.intake,\n channelIdentity: deps.domains.channelIdentity,\n memorySettings: deps.domains.memorySettings,\n modelDefaults: deps.domains.modelDefaults,\n },\n ...(deps.factoryReady ? { workItems: deps.domains.workItems, feed: deps.feed } : {}),\n ...(deps.factoryReady\n ? {\n runtime: { configVersion: deps.configVersion, workItems: deps.domains.workItems, boards: deps.boardRegistry },\n }\n : {}),\n ...(deps.emitAudit ? { hooks: { emitAudit: deps.emitAudit } } : {}),\n };\n}\n\n/**\n * Disabled-status stub for the well-known integration ids. The SPA polls\n * `/web/github/status`, `/web/linear/status`, and `/web/jira/status`\n * unconditionally, so when an integration is absent (or not ready) the status\n * contract must still hold. Unknown custom ids get no stub — the SPA doesn't\n * poll them.\n */\nfunction disabledIntegrationStatusRoutes(deps: FactoryApiRoutesDeps, id: string, configured = false): ApiRoute[] {\n if (id === 'github') {\n return [\n registerApiRoute('/web/github/status', {\n method: 'GET',\n requiresAuth: false,\n handler: c =>\n c.json({\n enabled: false,\n connected: false,\n installations: [],\n reason: 'missing_config',\n diagnostics: getGithubFeatureDiagnostics({\n github: undefined,\n auth: deps.auth,\n appDbConfigured: deps.factoryStorage !== undefined,\n stateSigner: deps.stateSigner,\n sandbox: deps.sandbox,\n }),\n }),\n }),\n ];\n }\n if (id === 'linear') {\n return [\n registerApiRoute('/web/linear/status', {\n method: 'GET',\n requiresAuth: false,\n handler: c =>\n c.json({\n enabled: false,\n connected: false,\n workspace: null,\n reason: 'missing_config',\n diagnostics: {\n linearAppConfigured: configured,\n factoryAuthEnabled: deps.auth.enabled(),\n appDbConfigured: true,\n },\n }),\n }),\n ];\n }\n if (id === 'jira') {\n return [\n registerApiRoute('/web/jira/status', {\n method: 'GET',\n requiresAuth: false,\n handler: c =>\n c.json({\n enabled: false,\n configured,\n site: null,\n reason: 'missing_config',\n diagnostics: {\n jiraConfigured: configured,\n factoryAuthEnabled: deps.auth.enabled(),\n appDbConfigured: deps.factoryStorage !== undefined,\n },\n }),\n }),\n ];\n }\n return [];\n}\n\n/**\n * Stub for `GET /web/channel-accounts` when NO Slack integration is\n * registered. The SPA's Connections section polls the path unconditionally;\n * without a stub the SPA fallback serves HTML, which the UI can only read as\n * \"old server / unknown\". The machine-readable reason lets it say the truth:\n * the integration isn't registered.\n *\n * Mounted only for ABSENT slack — a registered integration owns the path via\n * its connect routes (or, when the state signer is unstable, gets no routes\n * at all and the UI falls back to the generic copy). Static payload, leaks\n * nothing → no auth needed, same posture as the github/linear stubs.\n */\nfunction absentSlackChannelAccountsRoutes(): ApiRoute[] {\n return [\n registerApiRoute('/web/channel-accounts', {\n method: 'GET',\n requiresAuth: false,\n handler: c => c.json({ accounts: [], canConnect: false, reason: 'not_registered' }),\n }),\n ];\n}\n\n/**\n * Assemble the custom `/web/*` API routes as Mastra `server.apiRoutes`:\n * - fs browser routes (project picker), confined to `fsRoot`\n * - config routes (provider/API-key/default-model/OM management)\n * - every registered integration's `routes()` surface (full set when ready,\n * disabled-status stub otherwise), plus stubs for absent known ids\n */\nexport function assembleFactoryApiRoutes(deps: FactoryApiRoutesDeps): ApiRoute[] {\n const emitAudit: AuditEmitter['emit'] = args => deps.audit.emit(args);\n const registrations = deps.integrations ?? [];\n const githubRegistration = registrations.find(({ integration }) => integration.id === 'github');\n const githubStorage = githubRegistration ? deps.sourceControlStorage.forIntegration('github') : undefined;\n const githubIntegration = githubRegistration?.integration as GithubIntegration | undefined;\n const sourceControlRegistrations = registrations.filter(({ integration }) => integration.versionControl);\n const sourceControlIntegrationIds = [\n ...new Set(['github', ...sourceControlRegistrations.map(({ integration }) => integration.id)]),\n ];\n const sourceControls = sourceControlIntegrationIds.map(id => deps.sourceControlStorage.forIntegration(id));\n const sourceControlSessions = createSourceControlSessionLookup(sourceControls);\n\n const integrationRoutes = registrations.flatMap(registration => {\n const { integration } = registration;\n if (!deps.stateSigner) return disabledIntegrationStatusRoutes(deps, integration.id, true);\n const context = buildIntegrationContext(\n {\n ...deps,\n stateSigner: deps.stateSigner,\n emitAudit,\n ...(githubRegistration ? { sourceControlOwnerId: 'github' } : {}),\n },\n integration.id,\n );\n return guardIntegrationRoutes({ ...registration, routes: integration.routes(context) });\n });\n // Session persistence belongs to the linked source-control provider, not to\n // GitHub. Replace legacy GitHub-owned handlers with one resolver spanning\n // the legacy GitHub partition and every registered source-control partition.\n const sharedSessionRouteKeys = new Set([\n 'GET /web/github/projects/:id/sessions',\n 'POST /web/github/projects/:id/sessions',\n 'GET /web/user-sessions/:sessionId',\n 'DELETE /web/user-sessions/:sessionId',\n 'POST /web/user-sessions/:sessionId/title',\n ]);\n const providerRoutes = integrationRoutes.filter(\n route => !sharedSessionRouteKeys.has(route.method + ' ' + route.path),\n );\n const sourceControlSessionRoutes =\n sourceControls.length === 0\n ? []\n : buildSourceControlSessionRoutes({\n auth: deps.auth,\n sourceControls,\n ...(deps.users ? { users: deps.users } : {}),\n controller: deps.controller,\n memorySettings: deps.domains.memorySettings,\n sessionRetirement: deps.sessionRetirement,\n ...(deps.factoryReady ? { workItems: deps.domains.workItems } : {}),\n });\n // Absent known integrations still get their disabled-status stub.\n const absentStubs = ['github', 'linear', 'jira']\n .filter(id => !registrations.some(({ integration }) => integration.id === id))\n .flatMap(id => disabledIntegrationStatusRoutes(deps, id));\n // Absent slack gets the channel-accounts not-registered stub (registered\n // slack owns the path via its own connect routes).\n const slackAbsentStubs = registrations.some(({ integration }) => integration.id === 'slack')\n ? []\n : absentSlackChannelAccountsRoutes();\n\n const transitionService = deps.factoryReady\n ? (deps.factoryTransitionService ??\n new FactoryTransitionService({\n configVersion: deps.configVersion,\n boards: deps.boardRegistry,\n storage: deps.domains.workItems,\n audit: deps.audit,\n }))\n : undefined;\n const startCoordinator = transitionService\n ? new FactoryStartCoordinator(\n deps.controller,\n deps.domains.workItems,\n transitionService,\n request =>\n resolveFactorySourceControl({\n sourceControls,\n orgId: request.orgId,\n factoryProjectId: request.factoryProjectId,\n sessionId: request.sessionId,\n }),\n deps.domains.memorySettings,\n deps.domains.intake,\n )\n : undefined;\n if (transitionService && startCoordinator) {\n deps.onFactoryRuntime?.({\n transitionService,\n ...(sourceControlRegistrations.length > 0\n ? {\n prepareBinding: async (input: FactoryBindingPreparationInput) => {\n const sourceControl = await resolveFactorySourceControl({\n sourceControls,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n });\n if (!sourceControl) {\n throw new FactoryDispatchError(\n 'source_control_missing',\n 'Factory project has no linked source-control repository.',\n );\n }\n return prepareFactoryRuleBinding(\n sourceControl,\n startCoordinator,\n deps.domains.projects,\n deps.boardRegistry,\n input,\n deps.domains.intake,\n );\n },\n }\n : {}),\n });\n }\n\n return [\n ...buildFsRoutes({\n root: deps.fsRoot,\n sessionFs: {\n auth: deps.auth,\n sessions: sourceControlSessions,\n filesystem: deps.domains.filesystem,\n },\n }),\n ...new ConfigRoutes({\n auth: deps.auth,\n controller: deps.controller,\n authStorage: deps.authStorage,\n modelCredentials: deps.domains.modelCredentials,\n modelDefaults: deps.domains.modelDefaults,\n sourceControlSessions,\n memorySettings: deps.domains.memorySettings,\n factoryProjects: deps.domains.projects,\n customProviders: deps.domains.customProviders,\n features: { knowledge: deps.knowledgeEnabled },\n onCredentialsChanged: invalidateTenantCredentialSnapshots,\n onCustomProvidersChanged: invalidateCustomProvidersSnapshots,\n }).routes(),\n ...new OAuthRoutes({\n auth: deps.auth,\n authStorage: deps.authStorage,\n modelCredentials: deps.domains.modelCredentials,\n memorySettings: deps.domains.memorySettings,\n onCredentialsChanged: invalidateTenantCredentialSnapshots,\n }).routes(),\n ...new SkillRoutes({\n auth: deps.auth,\n controllerId: deps.controllerId,\n controller: deps.controller,\n sourceControlStorage: githubStorage,\n ensureSourceControlReady: githubRegistration?.ensureReady,\n }).routes(),\n ...sourceControlSessionRoutes,\n ...(sourceControls.length === 0 ? [] : buildSourceControlSettingsRoutes({ auth: deps.auth, sourceControls })),\n ...providerRoutes,\n ...absentStubs,\n ...slackAbsentStubs,\n ...(deps.intakeReady\n ? new IntakeRoutes({\n auth: deps.auth,\n audit: deps.audit,\n intake: deps.domains.intake,\n projects: deps.domains.projects,\n boardRegistry: deps.boardRegistry,\n // Relocation reads and writes work items, which init fail-soft separately from intake.\n ...(deps.factoryReady ? { workItems: deps.domains.workItems } : {}),\n integrations: (deps.integrations ?? []).flatMap(({ integration }) =>\n integration.intake ? [{ id: integration.id, intake: integration.intake }] : [],\n ),\n }).routes()\n : []),\n ...(deps.factoryReady && deps.knowledgeEnabled\n ? new KnowledgeRoutes({\n auth: deps.auth,\n projects: deps.domains.projects,\n knowledge: async () => deps.factoryStorage?.getMastraStorage().getStore('knowledge'),\n }).routes()\n : []),\n ...(deps.factoryReady\n ? new WorkItemRoutes({\n auth: deps.auth,\n audit: deps.audit,\n projects: deps.domains.projects,\n workItems: deps.domains.workItems,\n boardRegistry: deps.boardRegistry,\n comments: deps.domains.comments,\n queueHealth: deps.domains.queueHealth,\n transitionService,\n startCoordinator,\n liveSessions: deps.liveSessions,\n }).routes()\n : []),\n ...(deps.factoryReady\n ? buildAutomationRunRoutes({\n auth: deps.auth,\n audit: deps.audit,\n projects: deps.domains.projects,\n workItems: deps.domains.workItems,\n configVersion: deps.configVersion,\n })\n : []),\n ];\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ModelDefaultsStorage } from '../storage/domains/model-defaults/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 DefaultModelApplicableSession {
|
|
5
|
+
model: {
|
|
6
|
+
switch(modelId: string): Promise<unknown>;
|
|
7
|
+
};
|
|
8
|
+
subagents: {
|
|
9
|
+
model: {
|
|
10
|
+
set(args: {
|
|
11
|
+
modelId: string;
|
|
12
|
+
agentType: string;
|
|
13
|
+
}): Promise<unknown>;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export interface DefaultModelHydrationSession extends DefaultModelApplicableSession {
|
|
18
|
+
readonly identity: {
|
|
19
|
+
getResourceId(): string;
|
|
20
|
+
};
|
|
21
|
+
state: {
|
|
22
|
+
get(): Record<string, unknown> | undefined;
|
|
23
|
+
};
|
|
24
|
+
thread: {
|
|
25
|
+
getId(): string | null | undefined;
|
|
26
|
+
getSetting(args: {
|
|
27
|
+
key: string;
|
|
28
|
+
}): Promise<unknown>;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export interface DefaultModelHydrationDependencies {
|
|
32
|
+
sourceControl: {
|
|
33
|
+
sessions: Pick<SourceControlStorageHandle['sessions'], 'getBySessionId'>;
|
|
34
|
+
};
|
|
35
|
+
workItems: Pick<WorkItemsStorage, 'findActiveRunBindingByThread'>;
|
|
36
|
+
modelDefaults: Pick<ModelDefaultsStorage, 'get'>;
|
|
37
|
+
}
|
|
38
|
+
/** Seed the user's default model unless the interactive thread already selected its own model. */
|
|
39
|
+
export declare function hydrateSessionDefaultModel(session: DefaultModelHydrationSession, { sourceControl, workItems, modelDefaults }: DefaultModelHydrationDependencies): Promise<void>;
|
|
40
|
+
//# sourceMappingURL=default-model-hydration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-model-hydration.d.ts","sourceRoot":"","sources":["../../src/session/default-model-hydration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACtF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,2CAA2C,CAAC;AAC5F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAC;AAE9E,MAAM,WAAW,6BAA6B;IAC5C,KAAK,EAAE;QAAE,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;KAAE,CAAC;IACrD,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;CAC/F;AAED,MAAM,WAAW,4BAA6B,SAAQ,6BAA6B;IACjF,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;QACN,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;AAUD,MAAM,WAAW,iCAAiC;IAChD,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,aAAa,EAAE,IAAI,CAAC,oBAAoB,EAAE,KAAK,CAAC,CAAC;CAClD;AAED,kGAAkG;AAClG,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,4BAA4B,EACrC,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,EAAE,iCAAiC,GAC7E,OAAO,CAAC,IAAI,CAAC,CA+Bf"}
|