@mastra/factory 0.5.1-alpha.0 → 0.6.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +151 -0
- package/dist/auth.d.ts +2 -0
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +2 -0
- package/dist/auth.js.map +1 -1
- package/dist/capabilities/intake.d.ts +1 -0
- package/dist/capabilities/intake.d.ts.map +1 -1
- package/dist/capabilities/version-control.d.ts +3 -0
- package/dist/capabilities/version-control.d.ts.map +1 -1
- package/dist/factory.d.ts +10 -0
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +15 -2
- package/dist/factory.js.map +1 -1
- package/dist/integrations/base.d.ts +6 -0
- package/dist/integrations/base.d.ts.map +1 -1
- package/dist/integrations/github/integration.d.ts +14 -1
- package/dist/integrations/github/integration.d.ts.map +1 -1
- package/dist/integrations/github/integration.js +61 -3
- package/dist/integrations/github/integration.js.map +1 -1
- package/dist/integrations/github/issue-reconciler.d.ts +24 -0
- package/dist/integrations/github/issue-reconciler.d.ts.map +1 -0
- package/dist/integrations/github/issue-reconciler.js +104 -0
- package/dist/integrations/github/issue-reconciler.js.map +1 -0
- package/dist/integrations/github/reconcile-worker.d.ts +8 -0
- package/dist/integrations/github/reconcile-worker.d.ts.map +1 -1
- package/dist/integrations/github/reconcile-worker.js +38 -1
- package/dist/integrations/github/reconcile-worker.js.map +1 -1
- package/dist/integrations/github/routes.d.ts.map +1 -1
- package/dist/integrations/github/routes.js +65 -52
- package/dist/integrations/github/routes.js.map +1 -1
- package/dist/integrations/github/rules.d.ts +37 -2
- package/dist/integrations/github/rules.d.ts.map +1 -1
- package/dist/integrations/github/rules.js +150 -14
- package/dist/integrations/github/rules.js.map +1 -1
- package/dist/integrations/github/sandbox-release.d.ts +16 -1
- package/dist/integrations/github/sandbox-release.d.ts.map +1 -1
- package/dist/integrations/github/sandbox-release.js +42 -1
- package/dist/integrations/github/sandbox-release.js.map +1 -1
- package/dist/integrations/github/sandbox.d.ts.map +1 -1
- package/dist/integrations/github/sandbox.js +74 -8
- package/dist/integrations/github/sandbox.js.map +1 -1
- package/dist/integrations/issue-reconcile-worker.d.ts +19 -0
- package/dist/integrations/issue-reconcile-worker.d.ts.map +1 -0
- package/dist/integrations/issue-reconcile-worker.js +98 -0
- package/dist/integrations/issue-reconcile-worker.js.map +1 -0
- package/dist/integrations/issue-reconciler.d.ts +47 -0
- package/dist/integrations/issue-reconciler.d.ts.map +1 -0
- package/dist/integrations/issue-reconciler.js +104 -0
- package/dist/integrations/issue-reconciler.js.map +1 -0
- package/dist/integrations/linear/integration.d.ts +4 -0
- package/dist/integrations/linear/integration.d.ts.map +1 -1
- package/dist/integrations/linear/integration.js +19 -2
- package/dist/integrations/linear/integration.js.map +1 -1
- package/dist/integrations/linear/issue-reconciler.d.ts +6 -0
- package/dist/integrations/linear/issue-reconciler.d.ts.map +1 -0
- package/dist/integrations/linear/issue-reconciler.js +64 -0
- package/dist/integrations/linear/issue-reconciler.js.map +1 -0
- package/dist/integrations/linear/routes.d.ts.map +1 -1
- package/dist/integrations/linear/routes.js +1 -0
- package/dist/integrations/linear/routes.js.map +1 -1
- package/dist/integrations/linear/rules.d.ts +2 -0
- package/dist/integrations/linear/rules.d.ts.map +1 -1
- package/dist/integrations/linear/rules.js +5 -2
- package/dist/integrations/linear/rules.js.map +1 -1
- package/dist/integrations/platform/github/event-worker.d.ts +7 -0
- package/dist/integrations/platform/github/event-worker.d.ts.map +1 -1
- package/dist/integrations/platform/github/event-worker.js +24 -0
- package/dist/integrations/platform/github/event-worker.js.map +1 -1
- package/dist/integrations/platform/github/integration.d.ts +13 -3
- package/dist/integrations/platform/github/integration.d.ts.map +1 -1
- package/dist/integrations/platform/github/integration.js +42 -1
- package/dist/integrations/platform/github/integration.js.map +1 -1
- package/dist/integrations/platform/linear/event-worker.d.ts +105 -0
- package/dist/integrations/platform/linear/event-worker.d.ts.map +1 -0
- package/dist/integrations/platform/linear/event-worker.js +380 -0
- package/dist/integrations/platform/linear/event-worker.js.map +1 -0
- package/dist/integrations/platform/linear/integration.d.ts +9 -0
- package/dist/integrations/platform/linear/integration.d.ts.map +1 -1
- package/dist/integrations/platform/linear/integration.js +37 -1
- package/dist/integrations/platform/linear/integration.js.map +1 -1
- package/dist/integrations/slack/integration.d.ts.map +1 -1
- package/dist/integrations/slack/integration.js +3 -2
- package/dist/integrations/slack/integration.js.map +1 -1
- package/dist/integrations/slack/slack.d.ts +37 -110
- package/dist/integrations/slack/slack.d.ts.map +1 -1
- package/dist/integrations/slack/slack.js +49 -44
- package/dist/integrations/slack/slack.js.map +1 -1
- package/dist/routes/config.d.ts +25 -0
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +63 -1
- package/dist/routes/config.js.map +1 -1
- package/dist/routes/fs.d.ts +16 -2
- package/dist/routes/fs.d.ts.map +1 -1
- package/dist/routes/fs.js +47 -5
- package/dist/routes/fs.js.map +1 -1
- package/dist/routes/surface.d.ts +13 -1
- package/dist/routes/surface.d.ts.map +1 -1
- package/dist/routes/surface.js +20 -9
- package/dist/routes/surface.js.map +1 -1
- package/dist/rules/binding-context.d.ts +28 -1
- package/dist/rules/binding-context.d.ts.map +1 -1
- package/dist/rules/binding-context.js +66 -1
- package/dist/rules/binding-context.js.map +1 -1
- package/dist/rules/defaults.d.ts.map +1 -1
- package/dist/rules/defaults.js +71 -5
- package/dist/rules/defaults.js.map +1 -1
- package/dist/rules/start-coordinator.d.ts.map +1 -1
- package/dist/rules/start-coordinator.js +7 -26
- package/dist/rules/start-coordinator.js.map +1 -1
- package/dist/rules/tools.d.ts +2 -0
- package/dist/rules/tools.d.ts.map +1 -1
- package/dist/rules/tools.js +15 -6
- package/dist/rules/tools.js.map +1 -1
- package/dist/rules/types.d.ts +17 -2
- package/dist/rules/types.d.ts.map +1 -1
- package/dist/rules/types.js +2 -1
- package/dist/rules/types.js.map +1 -1
- package/dist/session/factory-session.d.ts +116 -0
- package/dist/session/factory-session.d.ts.map +1 -0
- package/dist/session/factory-session.js +162 -0
- package/dist/session/factory-session.js.map +1 -0
- package/dist/session/filesystem-capture.d.ts +26 -0
- package/dist/session/filesystem-capture.d.ts.map +1 -0
- package/dist/session/filesystem-capture.js +75 -0
- package/dist/session/filesystem-capture.js.map +1 -0
- package/dist/storage/domains/audit/domain.d.ts +9 -2
- package/dist/storage/domains/audit/domain.d.ts.map +1 -1
- package/dist/storage/domains/audit/domain.js +106 -4
- package/dist/storage/domains/audit/domain.js.map +1 -1
- package/dist/storage/domains/filesystem/base.d.ts +26 -0
- package/dist/storage/domains/filesystem/base.d.ts.map +1 -0
- package/dist/storage/domains/filesystem/base.js +74 -0
- package/dist/storage/domains/filesystem/base.js.map +1 -0
- package/dist/storage/domains/projects/base.d.ts +1 -0
- package/dist/storage/domains/projects/base.d.ts.map +1 -1
- package/dist/storage/domains/projects/base.js +3 -0
- package/dist/storage/domains/projects/base.js.map +1 -1
- package/dist/storage/domains/source-control/base.d.ts +2 -0
- package/dist/storage/domains/source-control/base.d.ts.map +1 -1
- package/dist/storage/domains/source-control/base.js +6 -0
- package/dist/storage/domains/source-control/base.js.map +1 -1
- package/dist/storage/domains/source-control/inmemory.d.ts.map +1 -1
- package/dist/storage/domains/source-control/inmemory.js +3 -0
- package/dist/storage/domains/source-control/inmemory.js.map +1 -1
- package/dist/storage/domains/work-items/base.d.ts +11 -0
- package/dist/storage/domains/work-items/base.d.ts.map +1 -1
- package/dist/storage/domains/work-items/base.js +28 -0
- package/dist/storage/domains/work-items/base.js.map +1 -1
- package/factory-skills/factory-triage/SKILL.md +45 -12
- package/package.json +5 -5
- package/dist/integrations/github/factory-session.d.ts +0 -12
- package/dist/integrations/github/factory-session.d.ts.map +0 -1
- package/dist/integrations/github/factory-session.js +0 -37
- package/dist/integrations/github/factory-session.js.map +0 -1
package/dist/factory.js
CHANGED
|
@@ -20,6 +20,7 @@ import { FactoryPhaseStateProcessor } from "./rules/processor.js";
|
|
|
20
20
|
import { createFactoryTransitionTools } from "./rules/tools.js";
|
|
21
21
|
import { registerSandboxReattach } from "./sandbox/reattach.js";
|
|
22
22
|
import { handleServerError } from "./server-error.js";
|
|
23
|
+
import { observeSessionFilesystem } from "./session/filesystem-capture.js";
|
|
23
24
|
import { createSpaStaticMiddleware, resolveUiDistDir } from "./spa-static.js";
|
|
24
25
|
import { createStateSigner } from "./state-signing.js";
|
|
25
26
|
import { observeAgentGitAction } from "./storage/domains/audit/agent-audit.js";
|
|
@@ -27,6 +28,7 @@ import { AuditStorage } from "./storage/domains/audit/base.js";
|
|
|
27
28
|
import { AuditDomain } from "./storage/domains/audit/domain.js";
|
|
28
29
|
import { ChannelIdentityStorage } from "./storage/domains/channel-identity/base.js";
|
|
29
30
|
import { CustomProvidersStorage } from "./storage/domains/custom-providers/base.js";
|
|
31
|
+
import { FilesystemStorage } from "./storage/domains/filesystem/base.js";
|
|
30
32
|
import { IntakeStorage } from "./storage/domains/intake/base.js";
|
|
31
33
|
import { IntegrationStorage } from "./storage/domains/integrations/base.js";
|
|
32
34
|
import { MemorySettingsStorage } from "./storage/domains/memory-settings/base.js";
|
|
@@ -34,7 +36,7 @@ import { ModelPacksStorage } from "./storage/domains/model-packs/base.js";
|
|
|
34
36
|
import { FactoryProjectsStorage } from "./storage/domains/projects/base.js";
|
|
35
37
|
import { SourceControlStorage } from "./storage/domains/source-control/base.js";
|
|
36
38
|
import { createWorkspaceFactory } from "./workspace.js";
|
|
37
|
-
import { hasAuthInit } from "@mastra/core/server";
|
|
39
|
+
import { hasAuthInit, isUserProvider } from "@mastra/core/server";
|
|
38
40
|
import { MastraAuthStudio } from "@mastra/auth-studio";
|
|
39
41
|
import { prepareAgentControllerMount } from "@mastra/code-sdk";
|
|
40
42
|
import { AgentControllerChannels } from "@mastra/core/channels";
|
|
@@ -178,6 +180,7 @@ var MastraFactory = class {
|
|
|
178
180
|
const queueHealthStorage = storage.registerDomain(new QueueHealthStorage());
|
|
179
181
|
const integrationStorage = storage.registerDomain(new IntegrationStorage());
|
|
180
182
|
const factoryProjectsStorage = storage.registerDomain(new FactoryProjectsStorage());
|
|
183
|
+
const filesystemStorage = storage.registerDomain(new FilesystemStorage());
|
|
181
184
|
const sourceControlStorage = storage.registerDomain(new SourceControlStorage());
|
|
182
185
|
const domains = {
|
|
183
186
|
intake: intakeStorage,
|
|
@@ -185,6 +188,7 @@ var MastraFactory = class {
|
|
|
185
188
|
modelPacks: modelPacksStorage,
|
|
186
189
|
memorySettings: memorySettingsStorage,
|
|
187
190
|
customProviders: customProvidersStorage,
|
|
191
|
+
filesystem: filesystemStorage,
|
|
188
192
|
projects: factoryProjectsStorage,
|
|
189
193
|
queueHealth: queueHealthStorage,
|
|
190
194
|
workItems: workItemsStorage,
|
|
@@ -200,6 +204,7 @@ var MastraFactory = class {
|
|
|
200
204
|
auth: routeAuth,
|
|
201
205
|
audit: auditStorage,
|
|
202
206
|
projects: factoryProjectsStorage,
|
|
207
|
+
users: auth && isUserProvider(auth) ? auth : void 0,
|
|
203
208
|
sinks: integrations,
|
|
204
209
|
agentTenant: (requestContext) => {
|
|
205
210
|
const user = requestContext.get("user");
|
|
@@ -318,7 +323,8 @@ var MastraFactory = class {
|
|
|
318
323
|
if (workItemsStorage && transitionService) mergeTools("factory", await createFactoryTransitionTools({
|
|
319
324
|
requestContext,
|
|
320
325
|
storage: workItemsStorage,
|
|
321
|
-
transitionService
|
|
326
|
+
transitionService,
|
|
327
|
+
...storage.isDomainReady("source-control") ? { sessions: sourceControlStorage.forIntegration("github").sessions } : {}
|
|
322
328
|
}));
|
|
323
329
|
for (const { integration, ready, ensureReady } of toolIntegrations) {
|
|
324
330
|
if (!ready && ensureReady) try {
|
|
@@ -381,6 +387,7 @@ var MastraFactory = class {
|
|
|
381
387
|
controller,
|
|
382
388
|
transitionService: runtimeTransitionService,
|
|
383
389
|
storage: storage.getDomain("work-items"),
|
|
390
|
+
maxInFlight: this.#config.dispatcher?.maxInFlight,
|
|
384
391
|
reconcileToolResults: () => factoryProcessor?.reconcileAllBoundThreads() ?? Promise.resolve(),
|
|
385
392
|
prepareBinding,
|
|
386
393
|
primeCredentials: (tenant) => primeTenantCredentials({
|
|
@@ -430,6 +437,12 @@ var MastraFactory = class {
|
|
|
430
437
|
};
|
|
431
438
|
}
|
|
432
439
|
}));
|
|
440
|
+
prepared.base.controller.onSessionCreated((session) => {
|
|
441
|
+
observeSessionFilesystem(session, {
|
|
442
|
+
filesystem: filesystemStorage,
|
|
443
|
+
sourceControl: sourceControlStorage.forIntegration("github")
|
|
444
|
+
});
|
|
445
|
+
});
|
|
433
446
|
this.#prepared = prepared;
|
|
434
447
|
this.#factoryProcessor = factoryProcessor;
|
|
435
448
|
const channelRegistrations = integrationRegistrations.filter(({ integration, ready }) => ready && integration.channels);
|
package/dist/factory.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.js","names":["#config","#preparing","#dispatcher","#prepared","#factoryProcessor"],"sources":["../src/factory.ts"],"sourcesContent":["/**\n * `MastraFactory` — the single entry point to the whole Mastra Software Factory.\n *\n * The consumer's deploy entry constructs deployment-specific config instances\n * (auth adapter, pubsub) and passes them here explicitly. The only provider\n * defaults constructed here are Platform GitHub and Linear integrations when\n * Platform credentials exist and the caller did not provide those integrations.\n *\n * `prepare()` resolves feature readiness, threads every dependency explicitly,\n * assembles the web routes/middleware, and returns the constructor args for\n * `new Mastra(...)`. The literal `export const mastra = new Mastra(...)` must\n * stay in the entry file — the deployer's `checkConfigExport` Babel plugin\n * only marks the config valid when it finds that literal in the entry AST —\n * so the factory produces args instead of the instance. `finalize()` runs the\n * post-construct boot (controller init + workers).\n *\n * Integration readiness is derived from each instance's declared capabilities\n * and the storage domains those capabilities require.\n */\n\nimport { MastraAuthStudio } from '@mastra/auth-studio';\nimport { prepareAgentControllerMount } from '@mastra/code-sdk';\nimport { AgentControllerChannels } from '@mastra/core/channels';\nimport type { PubSub } from '@mastra/core/events';\nimport type { Mastra } from '@mastra/core/mastra';\nimport type { RequestContext } from '@mastra/core/request-context';\nimport { hasAuthInit } from '@mastra/core/server';\nimport type { IMastraAuthProvider } from '@mastra/core/server';\nimport type { FactoryStorage } from '@mastra/core/storage';\nimport type { MastraVector } from '@mastra/core/vector';\nimport { LocalSandbox } from '@mastra/core/workspace';\nimport type { WorkspaceSandbox } from '@mastra/core/workspace';\nimport type { FactoryAuthUser } from './auth.js';\nimport {\n buildAuthRoutes,\n createFactoryAuthGate,\n createFactoryRouteAuth,\n getFactoryAuthOrgId,\n getFactoryAuthUserId,\n} from './auth.js';\nimport type { FactoryIntegration, IntegrationPostToolContext, IntegrationTools } from './integrations/base.js';\nimport type { GithubIntegration } from './integrations/github/integration.js';\nimport type { GithubIssueTriageInput, GithubIssueTriageResult } from './integrations/github/issue-triage.js';\nimport { recordFactoryPullRequestProvenance } from './integrations/github/provenance.js';\nimport { releaseWorkItemSandboxes } from './integrations/github/sandbox-release.js';\nimport { PlatformGithubIntegration } from './integrations/platform/github/integration.js';\nimport { PlatformLinearIntegration } from './integrations/platform/linear/integration.js';\nimport { createCustomProvidersPrimer, registerCustomProvidersSource } from './routes/custom-provider-source.js';\nimport { ProjectRoutes } from './routes/projects.js';\nimport { assembleFactoryApiRoutes, buildIntegrationContext } from './routes/surface.js';\nimport type { FactoryApiRoutesDeps } from './routes/surface.js';\nimport {\n createTenantCredentialPrimer,\n primeTenantCredentials,\n registerTenantCredentialResolver,\n} from './routes/tenant-credentials.js';\nimport { builtInFactoryRules } from './rules/defaults.js';\nimport { FactoryDecisionDispatcher } from './rules/dispatcher.js';\nimport { FactoryPhaseStateProcessor } from './rules/processor.js';\nimport { createFactoryTransitionTools } from './rules/tools.js';\nimport { FactoryTransitionService } from './rules/transition-service.js';\nimport type { FactoryRules } from './rules/types.js';\nimport { assertFactoryRules } from './rules/validation.js';\nimport { SandboxFleet } from './sandbox/fleet.js';\nimport { registerSandboxReattach } from './sandbox/reattach.js';\nimport { handleServerError } from './server-error.js';\nimport { createSpaStaticMiddleware, resolveUiDistDir } from './spa-static.js';\nimport { createStateSigner } from './state-signing.js';\nimport { observeAgentGitAction } from './storage/domains/audit/agent-audit.js';\nimport { AuditStorage } from './storage/domains/audit/base.js';\nimport { AuditDomain } from './storage/domains/audit/domain.js';\nimport { ChannelIdentityStorage } from './storage/domains/channel-identity/base.js';\nimport { ModelCredentialsStorage } from './storage/domains/credentials/base.js';\nimport { CustomProvidersStorage } from './storage/domains/custom-providers/base.js';\nimport { IntakeStorage } from './storage/domains/intake/base.js';\nimport { IntegrationStorage } from './storage/domains/integrations/base.js';\nimport { MemorySettingsStorage } from './storage/domains/memory-settings/base.js';\nimport { ModelPacksStorage } from './storage/domains/model-packs/base.js';\nimport { FactoryProjectsStorage } from './storage/domains/projects/base.js';\nimport { QueueHealthStorage } from './storage/domains/queue-health/base.js';\nimport { SourceControlStorage } from './storage/domains/source-control/base.js';\nimport { WorkItemsStorage } from './storage/domains/work-items/base.js';\nimport { timedPhase } from './timing.js';\nimport { createWorkspaceFactory } from './workspace.js';\n\ntype BuildApiRoutesDeps = Pick<FactoryApiRoutesDeps, 'controller' | 'authStorage'>;\n\n/** Constructor args for the `new Mastra(...)` literal in the deploy entry. */\nexport type MastraArgs = NonNullable<ConstructorParameters<typeof Mastra>[0]>;\n\nexport interface MastraFactoryConfig {\n /**\n * Auth provider instance — `MastraAuthStudio` (`@mastra/auth-studio`),\n * `MastraAuthWorkos` (`@mastra/auth-workos`), `MastraAuthBetterAuth`\n * (`@mastra/auth-better-auth`), or any custom `MastraAuthProvider`. Whatever\n * instance is passed is the active provider; a passed instance is always\n * honored as-is.\n *\n * Omitted → the factory defaults to `MastraAuthStudio`, proxying auth\n * through the shared Mastra platform API. `MastraAuthStudio` resolves its\n * own env (`MASTRA_SHARED_API_URL`, `MASTRA_ORGANIZATION_ID`,\n * `MASTRA_COOKIE_DOMAIN`).\n *\n * Pass `null` to disable auth entirely (open server, local-dev behavior)\n * without falling back to the default.\n */\n auth?: IMastraAuthProvider | null;\n /**\n * REQUIRED. Factory storage backend powering BOTH agent storage (threads,\n * messages, memory, OM — via `getMastraStorage()`) and the app tables\n * (projects/source-control/audit/intake — via the generic ops surface). Pass a\n * `PgFactoryStorage` (`@mastra/pg`) for deployments or a\n * `LibSQLFactoryStorage` (`@mastra/libsql`) for local dev — one backend,\n * one connection, every feature on.\n */\n storage: FactoryStorage;\n /**\n * Vector store instance for recall search — `PgVector` (`@mastra/pg`) on\n * the same database as `storage`. Omitted → the SDK mount's default vector\n * store resolution applies.\n */\n vector?: MastraVector;\n /**\n * Distributed event bus instance (e.g. `new RedisStreamsPubSub({ url })`).\n * When set, streams/workflows/signals ride it across processes and the\n * controller drops file-based thread locks in favor of pubsub-coordinated\n * leases. Omitted → in-process default.\n */\n pubsub?: PubSub;\n /**\n * Browser-facing origin used to build integration OAuth/install callback\n * URLs and to derive the auth redirect URI. On the platform the SPA is\n * hosted separately, so this MUST be the public API origin.\n * Default: `http://localhost:4111` (the local Factory server, which also\n * serves the UI).\n */\n publicUrl?: string;\n /**\n * Allowed cross-origin SPA origins. The SPA may be served from a separate\n * static host, so credentialed requests must be explicitly allowed.\n */\n allowedOrigins?: string[];\n /** Sandbox configuration. Omitted → repository sandboxes are disabled. */\n sandbox?: MastraFactorySandboxConfig;\n /**\n * Deployment-stable secret for signing integration OAuth `state` values.\n * Omitted → a per-process random secret, which is fine for single-process\n * local development but rejected for integrations that declare\n * `requiresStableStateSigner`.\n */\n stateSecret?: string;\n /**\n * Registered capability providers. The factory registers the pieces each\n * `FactoryIntegration` instance provides — HTTP routes, storage domains,\n * agent/session tools, intake, source control, and diagnostics — into the\n * system. When Platform credentials are configured, missing `github` and\n * `linear` integrations default to their Platform-backed implementations.\n */\n integrations?: FactoryIntegration[];\n /**\n * Authoritative Factory board, tool-result, and GitHub-event rules. Construct\n * with `defaultFactoryRules({ version, overrides })` so deployment policy has\n * an explicit version and exact handler leaves replace rather than compose.\n * Omitted → conservative built-in rules for the current deployment.\n */\n rules?: FactoryRules;\n\n /**\n * Platform-specific overrides. When the Platform-backed GitHub integration\n * is active, it derives a `runIssueTriage` runner from the mounted\n * controller automatically. An explicit `runIssueTriage` here takes\n * precedence over the controller-derived default. `githubAppSlug` identifies\n * Factory's own GitHub App writes so their webhook deliveries do not retrigger\n * triage.\n */\n platform?: {\n runIssueTriage?: (input: GithubIssueTriageInput) => Promise<GithubIssueTriageResult>;\n githubAppSlug?: string;\n };\n}\n\nexport interface MastraFactorySandboxConfig {\n /**\n * Template machine — `RailwaySandbox` (`@mastra/railway`), core\n * `LocalSandbox` (`@mastra/core/workspace`), or any `WorkspaceSandbox` that\n * implements `clone()`. Each project-repository execution environment gets\n * its own sandbox cloned from this machine; the machine itself is never\n * started. `prepare()` fails fast when the instance lacks `clone()`.\n */\n machine: WorkspaceSandbox;\n /**\n * In-sandbox base directory repos check out under (nested `owner/name` per\n * repo). Default: the machine's own `workingDirectory` when it exposes one\n * (core `LocalSandbox` does), else `/workspace`.\n */\n workdir?: string;\n /**\n * Per-replica cap on concurrently provisioned sandboxes. `0`/omitted means\n * unlimited. A lightweight per-process budget, not a cross-replica scheduler.\n */\n maxSandboxes?: number;\n}\n\nconst CONTROLLER_ID = 'code';\n\nfunction hasPlatformSecretKey(): boolean {\n return Boolean(process.env.MASTRA_PLATFORM_SECRET_KEY?.trim());\n}\n\n/**\n * The template sandbox's own working directory, when it exposes one as a\n * string (core `LocalSandbox` does; remote providers generally don't).\n * Used as the default checkout base so a local template rooted at a host\n * directory checks repos out under that same root.\n */\nfunction templateWorkingDirectory(sandbox: WorkspaceSandbox): string | undefined {\n const wd = (sandbox as { workingDirectory?: unknown }).workingDirectory;\n return typeof wd === 'string' && wd.length > 0 ? wd : undefined;\n}\n\nfunction resolveSandboxWorkdirBase(machine: WorkspaceSandbox, configuredWorkdir?: string): string {\n const machineWorkdir = templateWorkingDirectory(machine);\n const workdir =\n configuredWorkdir === '/workspace' && machineWorkdir ? machineWorkdir : (configuredWorkdir ?? machineWorkdir);\n return (workdir ?? '/workspace').replace(/\\/+$/, '');\n}\n\n/**\n * Default auth provider — `MastraAuthStudio`, which proxies identity to the\n * shared Mastra platform API. `MastraAuthStudio` resolves `MASTRA_SHARED_API_URL`,\n * `MASTRA_ORGANIZATION_ID`, and `MASTRA_COOKIE_DOMAIN` from env on its own —\n * this helper only derives a cookie-domain fallback from the factory's\n * `publicUrl`.\n *\n * Cookie-domain resolution (Studio picks the first that wins):\n * 1. explicit `MASTRA_COOKIE_DOMAIN` env, if set;\n * 2. `.mastra.ai` when `sharedApiUrl` is on `.mastra.ai`;\n * 3. this parent-domain fallback derived from `publicUrl` — so a deploy on\n * `https://foo.mastra.cloud` mints cookies with `Domain=.mastra.cloud`\n * without the caller wiring the env var by hand.\n * 4. otherwise host-only (no `Domain=`), which is correct for `localhost`.\n */\nfunction buildDefaultStudioAuth(publicUrl: string): IMastraAuthProvider {\n return new MastraAuthStudio({\n cookieDomain: parentDomainFromPublicUrl(publicUrl),\n });\n}\n\n/**\n * Derive a parent cookie domain from `publicUrl` by stripping the leftmost\n * label — the same shape platform-API's env injection uses (see\n * `platform/servers/api/src/lib/studio-env-vars.ts`: `.${routingDomain.replace(/^[^.]+\\./, '')}`).\n *\n * Rather than a generic `strip-left-label` heuristic — which either emits\n * cookies scoped to a public suffix (`sub.example.co.uk` → `.example.co.uk`\n * requires PSL data to be safe) or misclassifies numeric hostnames like\n * `3scale.example.com` as IPv4 — we only derive a parent domain when the\n * host sits under one of the platform's known registrable domains. Anything\n * else (custom domains, arbitrary tenant hostnames, IPs, `localhost`)\n * falls through to host-only cookies. Callers that need a different scope\n * pass `MASTRA_COOKIE_DOMAIN` explicitly (Studio honors that first).\n */\nconst KNOWN_PLATFORM_COOKIE_PARENTS = ['mastra.cloud', 'mastra.ai'] as const;\n\nfunction isIpLiteral(hostname: string): boolean {\n // IPv6 addresses in URLs are bracketed; `URL.hostname` strips the brackets\n // but the address itself still contains `:`. IPv4 is four dot-separated\n // numeric octets — trust the parser to have already validated shape.\n if (hostname.includes(':')) return true;\n return /^\\d+(?:\\.\\d+){3}$/.test(hostname);\n}\n\nfunction parentDomainFromPublicUrl(publicUrl: string): string | undefined {\n let hostname: string;\n try {\n hostname = new URL(publicUrl).hostname.toLowerCase();\n } catch {\n return undefined;\n }\n if (hostname === 'localhost' || isIpLiteral(hostname)) return undefined;\n for (const parent of KNOWN_PLATFORM_COOKIE_PARENTS) {\n // Exact match → we're already on the parent, host-only is correct.\n // Subdomain match → mint the parent-scoped cookie.\n if (hostname === parent) return undefined;\n if (hostname.endsWith(`.${parent}`)) return `.${parent}`;\n }\n return undefined;\n}\n\nexport class MastraFactory {\n readonly #config: MastraFactoryConfig;\n #prepared: Awaited<ReturnType<typeof prepareAgentControllerMount>> | undefined;\n #dispatcher: FactoryDecisionDispatcher | undefined;\n #factoryProcessor: FactoryPhaseStateProcessor | undefined;\n #preparing = false;\n\n constructor(config: MastraFactoryConfig) {\n if (!config?.storage) {\n throw new Error(\n \"MastraFactory: 'storage' is required. Pass a FactoryStorage backend — e.g. \" +\n \"new PgFactoryStorage({ connectionString }) from '@mastra/pg' for deployments, or \" +\n \"new LibSQLFactoryStorage({ url }) from '@mastra/libsql' for local dev.\",\n );\n }\n this.#config = config;\n }\n\n /**\n * Resolve feature readiness, wire every dependency explicitly, and assemble\n * everything needed to construct the server-owned Mastra. Returns the args\n * for the `new Mastra(...)` literal that must live in the entry file.\n */\n async prepare(): Promise<MastraArgs> {\n // Guard set synchronously (before the first await) so overlapping calls —\n // not just strictly sequential ones — can't double-seed the runtime\n // registry or double-run one-time adapter init.\n if (this.#preparing) throw new Error('MastraFactory.prepare() called twice');\n this.#preparing = true;\n\n const publicOrigin = (this.#config.publicUrl ?? 'http://localhost:4111').replace(/\\/+$/, '');\n const allowedOrigins = (this.#config.allowedOrigins ?? []).map(o => o.replace(/\\/+$/, '')).filter(Boolean);\n const storage = this.#config.storage;\n const vector = this.#config.vector;\n const pubsub = this.#config.pubsub;\n // Default auth: honor an explicitly-passed provider (including `null` to\n // disable auth) as-is; otherwise fall back to `MastraAuthStudio`\n // (platform-proxied identity). The default derives its cookie domain\n // from `publicUrl` — deploys on `<sub>.mastra.cloud` mint parent-domain\n // cookies without the caller wiring `MASTRA_COOKIE_DOMAIN` explicitly.\n const configuredAuth = this.#config.auth;\n const auth: IMastraAuthProvider | undefined =\n configuredAuth === null ? undefined : (configuredAuth ?? buildDefaultStudioAuth(publicOrigin));\n // One RouteAuth seam per boot, closed over the resolved provider. Every\n // factory route module receives this handle — no service locator.\n const routeAuth = createFactoryRouteAuth(auth);\n\n // Explicit integrations win. Platform credentials fill only missing GitHub\n // and Linear slots so callers can override either provider independently.\n const integrations = [...(this.#config.integrations ?? [])];\n if (hasPlatformSecretKey()) {\n if (!integrations.some(integration => integration.id === 'github')) {\n integrations.push(\n new PlatformGithubIntegration({\n runIssueTriage: this.#config.platform?.runIssueTriage,\n slug: this.#config.platform?.githubAppSlug,\n }),\n );\n }\n if (!integrations.some(integration => integration.id === 'linear')) {\n integrations.push(new PlatformLinearIntegration());\n }\n }\n\n // Validate ids up front so a copy-paste duplicate fails loud instead of one\n // instance silently shadowing the other.\n const integrationIds = new Set<string>();\n for (const integration of integrations) {\n if (integrationIds.has(integration.id)) {\n throw new Error(`MastraFactory: duplicate integration id '${integration.id}' in 'integrations'.`);\n }\n integrationIds.add(integration.id);\n }\n const rules = this.#config.rules ?? builtInFactoryRules();\n assertFactoryRules(rules);\n\n // FactoryStorage owns every app-table domain and initializes them through\n // the same lifecycle as the backend connection.\n const intakeStorage = storage.registerDomain(new IntakeStorage());\n const auditStorage = storage.registerDomain(new AuditStorage());\n const workItemsStorage = storage.registerDomain(new WorkItemsStorage());\n const modelCredentialsStorage = storage.registerDomain(new ModelCredentialsStorage());\n const modelPacksStorage = storage.registerDomain(new ModelPacksStorage());\n const memorySettingsStorage = storage.registerDomain(new MemorySettingsStorage());\n const customProvidersStorage = storage.registerDomain(new CustomProvidersStorage());\n const queueHealthStorage = storage.registerDomain(new QueueHealthStorage());\n // Generic integration storage (connections/subscriptions/settings) — the\n // default persistence surface for integrations without a bespoke domain.\n const integrationStorage = storage.registerDomain(new IntegrationStorage());\n const factoryProjectsStorage = storage.registerDomain(new FactoryProjectsStorage());\n const sourceControlStorage = storage.registerDomain(new SourceControlStorage());\n // Reverse index from a platform sender (Slack/Discord/...) to a Mastra\n // tenant, so inbound channel events can resolve the sender's model creds.\n const channelIdentityStorage = storage.registerDomain(new ChannelIdentityStorage());\n // Every app-table domain handle the route builders and integrations need,\n // threaded explicitly (no service locator).\n const domains = {\n intake: intakeStorage,\n modelCredentials: modelCredentialsStorage,\n modelPacks: modelPacksStorage,\n memorySettings: memorySettingsStorage,\n customProviders: customProvidersStorage,\n projects: factoryProjectsStorage,\n queueHealth: queueHealthStorage,\n workItems: workItemsStorage,\n channelIdentity: channelIdentityStorage,\n };\n const projectRoutes = new ProjectRoutes({\n auth: routeAuth,\n projects: factoryProjectsStorage,\n sourceControl: sourceControlStorage,\n versionControlIntegrationIds: integrations\n .filter(integration => integration.versionControl)\n .map(integration => integration.id),\n });\n const auditDomain = new AuditDomain({\n auth: routeAuth,\n audit: auditStorage,\n projects: factoryProjectsStorage,\n sinks: integrations,\n agentTenant: requestContext => {\n const user = requestContext.get('user') as FactoryAuthUser | undefined;\n return { orgId: getFactoryAuthOrgId(user), userId: getFactoryAuthUserId(user) };\n },\n });\n\n // Repository execution needs one sandbox per project-repository link,\n // cloned from the configured machine. A machine without `clone()` would\n // only fail on first use, so fail fast at boot instead.\n const sandboxConfig = this.#config.sandbox;\n const machine = sandboxConfig?.machine;\n if (machine && typeof machine.clone !== 'function') {\n throw new Error(\n `MastraFactory: the configured sandbox machine (provider '${machine.provider}') does not implement clone(). ` +\n `Project repositories each get their own sandbox cloned from the configured machine. ` +\n `Pass a machine that implements clone() — e.g. RailwaySandbox (@mastra/railway) or ` +\n `LocalSandbox (@mastra/core/workspace) — or omit 'sandbox' to disable sandboxes.`,\n );\n }\n\n // One sandbox fleet per boot: constructed with the machine config when\n // sandboxes are configured, disabled otherwise. Handed to integrations\n // through the IntegrationContext — no global registry.\n const fleet = new SandboxFleet(\n machine\n ? {\n machine,\n workdirBase: resolveSandboxWorkdirBase(machine, sandboxConfig?.workdir),\n maxSandboxes: sandboxConfig?.maxSandboxes,\n }\n : undefined,\n );\n // Core's `getDynamicWorkspace` reattaches project sandboxes through the\n // SDK seam; only this factory owns the fleet, so register it here.\n registerSandboxReattach(fleet);\n\n // One shared OAuth state signer per boot. The deploy entry supplies a\n // replica-stable secret when needed; otherwise local development gets a\n // per-process random signer (`stable: false`).\n const stateSigner = createStateSigner(this.#config.stateSecret);\n\n // One-time provider initialization with factory-level context (e.g.\n // better-auth builds its default instance on the backend's auth\n // database, WorkOS derives its redirect URI from the public URL).\n // Failures surface here, at prepare() — a misconfigured provider must\n // not boot.\n if (auth && hasAuthInit(auth)) {\n await timedPhase('prepare.auth.init', () =>\n auth.init({ database: storage.authDatabase?.(), publicUrl: publicOrigin, allowedOrigins }),\n );\n }\n\n // Single init path: backend connection failure is a hard boot error;\n // registered app domains initialize fail-soft inside FactoryStorage.\n await timedPhase('prepare.storage.init', () => storage.init());\n\n // Per-tenant model credentials: once the credentials domain is up, model\n // resolution goes through the caller's own store and the SDK stops\n // mirroring stored API keys into process.env.\n //\n // Only register when a real auth adapter gates callers. In local /\n // auth-disabled mode there is no authenticated tenant, so registering would\n // force every model call through an empty tenant store (fail-closed, no env\n // fallback) and break chat with \"Not logged in\". Leaving it unregistered\n // lets the SDK fall back to the file-backed AuthStorage (auth.json) — the\n // same store the local /login and Settings pages read and write.\n if (auth) {\n registerTenantCredentialResolver(modelCredentialsStorage);\n }\n\n // Custom providers: DB-backed in both modes (org rows in tenant mode, the\n // sentinel `local` org in no-auth mode). Once registered, model resolution\n // and the gateway catalog never read settings.json custom providers.\n registerCustomProvidersSource({ storage: customProvidersStorage, authEnabled: Boolean(auth) });\n\n for (const integration of integrations) {\n integration.initialize?.({\n storage: integrationStorage.forIntegration(integration.id),\n projects: factoryProjectsStorage,\n auth: routeAuth,\n });\n if (integration.versionControl) {\n integration.versionControl.initialize({\n storage: sourceControlStorage.forIntegration(integration.id),\n });\n }\n }\n\n // Every integration uses generic integration storage. Version-control\n // providers additionally require the source-control storage domain. Readiness\n // is derived solely from capability presence, never from provider ids.\n const integrationRegistrations = integrations.map(integration => {\n const requiredDomains = [\n 'integrations',\n ...(integration.versionControl ? ['source-control'] : []),\n // Channels resolve an inbound sender to a tenant through the reverse\n // index; without it every message would dispatch tenant-less.\n ...(integration.channels ? ['channel-identity'] : []),\n ];\n return {\n integration,\n ready: requiredDomains.every(domain => storage.isDomainReady(domain)),\n ensureReady: async () => {\n for (const domain of requiredDomains) await storage.ensureDomainReady(domain);\n },\n };\n });\n const intakeReady =\n integrations.some(integration => integration.intake !== undefined) && storage.isDomainReady('intake');\n const factoryReady = storage.isDomainReady('projects') && storage.isDomainReady('work-items');\n const githubIntegration = integrations.find(integration => integration.id === 'github') as\n | GithubIntegration\n | undefined;\n const workItemsReady = storage.isDomainReady('work-items');\n // Terminal work items release their session sandboxes back to the reuse\n // pool so the next session for the same repository/user claims a warm VM\n // instead of provisioning fresh. Remote providers only: local \"sandboxes\"\n // are the host machine with per-session workdirs — nothing to pool.\n const releaseTerminalSandboxes =\n machine && !(machine instanceof LocalSandbox) && workItemsReady && storage.isDomainReady('source-control')\n ? async ({ orgId, workItemId }: { orgId: string; workItemId: string }) =>\n releaseWorkItemSandboxes({\n workItems: workItemsStorage,\n sourceControl: sourceControlStorage.forIntegration('github'),\n fleet,\n orgId,\n workItemId,\n })\n : undefined;\n const transitionService = workItemsReady\n ? new FactoryTransitionService({\n rules,\n storage: workItemsStorage,\n ...(releaseTerminalSandboxes ? { onTerminalStage: releaseTerminalSandboxes } : {}),\n })\n : undefined;\n const factoryProcessor = workItemsReady\n ? new FactoryPhaseStateProcessor({\n rules,\n storage: workItemsStorage,\n ...(transitionService ? { transitionService } : {}),\n ...(githubIntegration\n ? {\n recordPullRequestProvenance: (input: Parameters<typeof recordFactoryPullRequestProvenance>[3]) =>\n recordFactoryPullRequestProvenance(\n githubIntegration,\n sourceControlStorage.forIntegration('github'),\n integrationStorage.forIntegration('github'),\n input,\n ),\n }\n : {}),\n messageReader: {\n listMessages: async input => {\n const memory = await storage.getMastraStorage().getStore('memory');\n return memory ? memory.listMessages(input) : { messages: [], hasMore: false };\n },\n },\n })\n : undefined;\n\n // Boot assertion: an active integration that signs OAuth `state` needs a\n // replica-stable signer — a per-process random secret silently breaks the\n // OAuth callback on any replica that didn't sign the state. Fail loud now\n // instead. (The built-ins also assert this inside their readiness gates.)\n for (const { integration } of integrationRegistrations) {\n if (integration.requiresStableStateSigner && !stateSigner.stable) {\n throw new Error(\n `MastraFactory: integration '${integration.id}' signs OAuth state and requires a ` +\n `replica-stable state secret, but none is configured. Set 'stateSecret' on the factory config.`,\n );\n }\n }\n\n // The SDK needs to know which backend the injected Mastra store uses\n // (its own `instanceof` detection breaks when the dependency graph holds\n // duplicate package copies). Resolve it by walking the FactoryStorage\n // prototype chain by class name — the factory can't import the concrete\n // classes since '@mastra/pg' / '@mastra/libsql' are the user's choice.\n const mastraStorageBackend = (() => {\n for (let proto = Object.getPrototypeOf(storage); proto; proto = Object.getPrototypeOf(proto)) {\n if (proto.constructor?.name === 'PgFactoryStorage') return 'pg' as const;\n if (proto.constructor?.name === 'LibSQLFactoryStorage') return 'libsql' as const;\n }\n return undefined;\n })();\n\n // Integrations contributing tools to agent sessions: org-scoped\n // `agentTools` (resolved per request) + session-scoped `sessionTools`.\n const toolIntegrations = integrationRegistrations.filter(\n ({ integration }) => integration.agentTools || integration.sessionTools,\n );\n\n // Build the real production controller (agents, modes, tools, memory, OM,\n // MCP, providers) — identical to the terminal app. Agent state lives in\n // the storage backend's Mastra store alongside the Factory app tables —\n // one shared database for all users, separated by `resourceId` scoping.\n const prepared = await timedPhase('prepare.controllerMount', () =>\n prepareAgentControllerMount({\n controllerId: CONTROLLER_ID,\n workspace: createWorkspaceFactory({\n ...(this.#config.sandbox ? { sandbox: this.#config.sandbox } : {}),\n ...(githubIntegration ? { github: githubIntegration } : {}),\n ...(workItemsStorage ? { workItems: workItemsStorage } : {}),\n fleet,\n }),\n disableGithubSignals: true,\n // Memory settings live in the factory's `memory-settings` app table (per\n // org/user), so the host machine's TUI settings.json must not seed them.\n disableSettingsOmSeed: true,\n // A factory reads the repository it works on and its skill, never the\n // ~/.claude instructions of whoever hosts the process. On the controller\n // rather than per session, so webhook-recreated sessions keep it too.\n initialState: { skipGlobalInstructions: true },\n storage: storage.getMastraStorage(),\n ...(mastraStorageBackend ? { storageBackend: mastraStorageBackend } : {}),\n ...(factoryProcessor ? { inputProcessors: [factoryProcessor] } : {}),\n ...(vector ? { vector } : {}),\n ...(toolIntegrations.length > 0 || (workItemsStorage && transitionService)\n ? {\n extraTools: async ({ requestContext }: { requestContext: RequestContext }) => {\n const tools: IntegrationTools = {};\n const toolOwners = new Map<string, string>();\n const mergeTools = (ownerId: string, contributed: IntegrationTools) => {\n for (const [name, tool] of Object.entries(contributed)) {\n const owner = toolOwners.get(name);\n if (owner) {\n throw new Error(\n `MastraFactory: integration tool '${name}' from '${ownerId}' conflicts with '${owner}'.`,\n );\n }\n toolOwners.set(name, ownerId);\n tools[name] = tool;\n }\n };\n if (workItemsStorage && transitionService) {\n mergeTools(\n 'factory',\n await createFactoryTransitionTools({\n requestContext,\n storage: workItemsStorage,\n transitionService,\n }),\n );\n }\n for (const { integration, ready, ensureReady } of toolIntegrations) {\n if (!ready && ensureReady) {\n try {\n await ensureReady();\n } catch {\n continue;\n }\n }\n if (integration.agentTools) {\n mergeTools(integration.id, await integration.agentTools({ requestContext }));\n }\n if (integration.sessionTools) {\n mergeTools(integration.id, integration.sessionTools({ requestContext }));\n }\n }\n return tools;\n },\n }\n : {}),\n postToolObserver: async (toolContext: IntegrationPostToolContext) => {\n const requestContext = (toolContext.context as { requestContext?: RequestContext } | undefined)\n ?.requestContext;\n if (requestContext) {\n await observeAgentGitAction({\n audit: auditDomain,\n toolContext: { ...toolContext, context: requestContext },\n });\n }\n await Promise.all(\n integrations.map(async integration => {\n if (!integration.postToolObserver) return;\n try {\n await integration.postToolObserver({ toolContext, requestContext });\n } catch (error) {\n console.warn(`[factory] Integration '${integration.id}' post-tool observer failed:`, error);\n }\n }),\n );\n },\n ...(pubsub ? { pubsub, crossProcessPubSub: true } : {}),\n buildApiRoutes: ({ controller, authStorage }: BuildApiRoutesDeps) => [\n // Public `/auth/*` routes (login/callback/logout/me). Folded in as\n // `apiRoutes` (not plain Hono routes) because the entry can't touch the\n // Hono app the deployer generates. `requiresAuth: false`; the gate\n // skips `/auth/*`.\n ...(auth ? buildAuthRoutes(auth, { publicUrl: publicOrigin }) : []),\n // Custom `/web/*` routes (fs / config / integrations / factory / audit).\n ...assembleFactoryApiRoutes({\n controllerId: CONTROLLER_ID,\n controller,\n auth: routeAuth,\n authStorage,\n audit: auditDomain,\n publicOrigin,\n stateSigner,\n fleet,\n factoryStorage: storage,\n integrationStorage,\n sourceControlStorage,\n domains,\n integrations: integrationRegistrations,\n intakeReady,\n factoryReady,\n rules,\n factoryTransitionService: transitionService,\n onFactoryRuntime: ({ transitionService: runtimeTransitionService, prepareBinding }) => {\n this.#dispatcher ??= new FactoryDecisionDispatcher({\n controller,\n transitionService: runtimeTransitionService,\n storage: storage.getDomain<WorkItemsStorage>('work-items'),\n reconcileToolResults: () => factoryProcessor?.reconcileAllBoundThreads() ?? Promise.resolve(),\n prepareBinding,\n primeCredentials: tenant => primeTenantCredentials({ tenant, credentials: modelCredentialsStorage }),\n });\n },\n }),\n ...projectRoutes.routes(),\n ...auditDomain.routes(),\n ],\n buildServerConfig: () => {\n const cors = allowedOrigins.length ? { cors: { origin: allowedOrigins, credentials: true } } : {};\n // Log route errors with method/path/stack and answer with structured\n // JSON instead of an opaque `Internal Server Error`. Applied by the\n // deployer to both the top-level app and the custom-route sub-app.\n const onError = { onError: handleServerError };\n // Same-origin SPA: when a vite build is present (see resolveUiDistDir),\n // serve it at `/` from this server. Mounted last so the auth gate (when\n // enabled) covers it; it always passes `/api`, `/web`, `/auth` through.\n const uiDist = resolveUiDistDir();\n const spa = uiDist ? [createSpaStaticMiddleware(uiDist)] : [];\n if (!auth) {\n // Auth disabled: no gate. Still prime the sentinel-local custom\n // provider snapshot so model calls see DB rows, then SPA + CORS.\n return {\n middleware: [\n createCustomProvidersPrimer({ auth: routeAuth, storage: customProvidersStorage, authEnabled: false }),\n ...spa,\n ],\n ...cors,\n ...onError,\n };\n }\n\n // Ordered middleware. The deployer applies these AFTER its context\n // middleware sets `c.set('mastra', mastra)` and BEFORE routes, so:\n // 1. gate — validates the auth session, stashes the user, and 401s /\n // redirects unauthenticated requests. Skips public `/auth/*`.\n // 2. primers — hydrate the caller's model-credential and custom\n // provider snapshots so the request's first model call\n // resolves tenant credentials and custom providers.\n // 3. spa — serves the built UI for everything the server doesn't own.\n // `auth` also lands on `server.auth` so the core auth middleware (and\n // Studio's dual-auth routing — see `studio.auth` on the returned args)\n // authenticates core `/api/*` routes with the same provider.\n return {\n auth,\n middleware: [\n createFactoryAuthGate(auth),\n createTenantCredentialPrimer({ auth: routeAuth, credentials: modelCredentialsStorage }),\n createCustomProvidersPrimer({\n auth: routeAuth,\n storage: customProvidersStorage,\n authEnabled: Boolean(auth),\n }),\n ...spa,\n ],\n ...cors,\n ...onError,\n };\n },\n }),\n );\n\n this.#prepared = prepared;\n this.#factoryProcessor = factoryProcessor;\n\n // Chat-platform channels (Slack, Discord, …) contributed by integrations,\n // attached to the mounted controller so inbound platform messages reach\n // the same agents the web UI drives. READY integrations only — readiness\n // means the `channel-identity` domain's `init()` succeeded, so its link\n // table is queryable. Without it a sender can't be resolved to a tenant,\n // and attaching anyway would dispatch runs on default credentials.\n const channelRegistrations = integrationRegistrations.filter(\n ({ integration, ready }) => ready && integration.channels,\n );\n // `setChannels` replaces rather than merges, so a second provider would\n // silently never receive a message. Fail loud instead.\n if (channelRegistrations.length > 1) {\n throw new Error(\n `MastraFactory: integrations [${channelRegistrations\n .map(({ integration }) => integration.id)\n .join(', ')}] all provide channels, but only one may. Remove all but one.`,\n );\n }\n for (const { integration } of channelRegistrations) {\n // Integrations return a channels CONFIG; the factory owns construction.\n prepared.base.controller.setChannels(\n new AgentControllerChannels(\n integration.channels!(\n buildIntegrationContext(\n {\n controller: prepared.base.controller,\n publicOrigin,\n auth: routeAuth,\n stateSigner,\n fleet,\n factoryStorage: storage,\n integrationStorage,\n sourceControlStorage,\n rules,\n factoryReady,\n domains,\n ...(githubIntegration ? { sourceControlOwnerId: 'github' } : {}),\n },\n integration.id,\n ),\n ),\n ),\n );\n }\n\n // Integration lifecycle workers (e.g. polling an upstream without\n // webhooks): collected from READY integrations only, folded into the\n // constructor args so `new Mastra(...)` merges them with the default\n // workers and `finalize()`'s `startWorkers()` starts them alongside the\n // built-ins. Never passed for the disabled/not-ready case — a worker for\n // an unavailable integration must not run.\n const integrationWorkers = integrationRegistrations\n .filter(({ integration, ready }) => ready && integration.workers)\n .flatMap(({ integration }) =>\n integration.workers!(\n buildIntegrationContext(\n {\n controller: prepared.base.controller,\n publicOrigin,\n auth: routeAuth,\n stateSigner,\n fleet,\n factoryStorage: storage,\n integrationStorage,\n sourceControlStorage,\n rules,\n factoryReady,\n domains,\n ...(githubIntegration ? { sourceControlOwnerId: 'github' } : {}),\n },\n integration.id,\n ),\n ),\n );\n\n return {\n ...prepared.mastraArgs,\n // Same provider on `studio.auth` as on `server.auth` (buildServerConfig):\n // deployed factories must authenticate BOTH plain API callers and Studio\n // requests (`x-mastra-client-type: studio` routes to `studio.auth`).\n ...(auth ? { studio: { auth } } : {}),\n ...(integrationWorkers.length > 0 ? { workers: integrationWorkers } : {}),\n };\n }\n\n /**\n * Post-construct boot: initialize the controller (which inherits the\n * constructed Mastra's storage) and start its workers. Call AFTER the entry\n * has run `new Mastra(prepare()'s args)`.\n */\n async finalize(): Promise<void> {\n if (!this.#prepared) {\n throw new Error('MastraFactory.finalize() called before prepare()');\n }\n await timedPhase('finalize.controller', () => this.#prepared!.finalize());\n await timedPhase(\n 'finalize.reconcileBoundThreads',\n () => this.#factoryProcessor?.reconcileAllBoundThreads() ?? Promise.resolve(),\n );\n this.#dispatcher?.start();\n }\n\n /** Stop Factory-owned background dispatch before the host process shuts down. */\n async shutdown(): Promise<void> {\n await this.#dispatcher?.stop();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"factory.js","names":["#config","#preparing","#dispatcher","#prepared","#factoryProcessor"],"sources":["../src/factory.ts"],"sourcesContent":["/**\n * `MastraFactory` — the single entry point to the whole Mastra Software Factory.\n *\n * The consumer's deploy entry constructs deployment-specific config instances\n * (auth adapter, pubsub) and passes them here explicitly. The only provider\n * defaults constructed here are Platform GitHub and Linear integrations when\n * Platform credentials exist and the caller did not provide those integrations.\n *\n * `prepare()` resolves feature readiness, threads every dependency explicitly,\n * assembles the web routes/middleware, and returns the constructor args for\n * `new Mastra(...)`. The literal `export const mastra = new Mastra(...)` must\n * stay in the entry file — the deployer's `checkConfigExport` Babel plugin\n * only marks the config valid when it finds that literal in the entry AST —\n * so the factory produces args instead of the instance. `finalize()` runs the\n * post-construct boot (controller init + workers).\n *\n * Integration readiness is derived from each instance's declared capabilities\n * and the storage domains those capabilities require.\n */\n\nimport { MastraAuthStudio } from '@mastra/auth-studio';\nimport { prepareAgentControllerMount } from '@mastra/code-sdk';\nimport { AgentControllerChannels } from '@mastra/core/channels';\nimport type { PubSub } from '@mastra/core/events';\nimport type { Mastra } from '@mastra/core/mastra';\nimport type { RequestContext } from '@mastra/core/request-context';\nimport { hasAuthInit, isUserProvider } from '@mastra/core/server';\nimport type { IMastraAuthProvider } from '@mastra/core/server';\nimport type { FactoryStorage } from '@mastra/core/storage';\nimport type { MastraVector } from '@mastra/core/vector';\nimport { LocalSandbox } from '@mastra/core/workspace';\nimport type { WorkspaceSandbox } from '@mastra/core/workspace';\nimport type { FactoryAuthUser } from './auth.js';\nimport {\n buildAuthRoutes,\n createFactoryAuthGate,\n createFactoryRouteAuth,\n getFactoryAuthOrgId,\n getFactoryAuthUserId,\n} from './auth.js';\nimport type { FactoryIntegration, IntegrationPostToolContext, IntegrationTools } from './integrations/base.js';\nimport type { GithubIntegration } from './integrations/github/integration.js';\nimport type { GithubIssueTriageInput, GithubIssueTriageResult } from './integrations/github/issue-triage.js';\nimport { recordFactoryPullRequestProvenance } from './integrations/github/provenance.js';\nimport { releaseWorkItemSandboxes } from './integrations/github/sandbox-release.js';\nimport { PlatformGithubIntegration } from './integrations/platform/github/integration.js';\nimport { PlatformLinearIntegration } from './integrations/platform/linear/integration.js';\nimport { createCustomProvidersPrimer, registerCustomProvidersSource } from './routes/custom-provider-source.js';\nimport { ProjectRoutes } from './routes/projects.js';\nimport { assembleFactoryApiRoutes, buildIntegrationContext } from './routes/surface.js';\nimport type { FactoryApiRoutesDeps } from './routes/surface.js';\nimport {\n createTenantCredentialPrimer,\n primeTenantCredentials,\n registerTenantCredentialResolver,\n} from './routes/tenant-credentials.js';\nimport { builtInFactoryRules } from './rules/defaults.js';\nimport { FactoryDecisionDispatcher } from './rules/dispatcher.js';\nimport { FactoryPhaseStateProcessor } from './rules/processor.js';\nimport { createFactoryTransitionTools } from './rules/tools.js';\nimport { FactoryTransitionService } from './rules/transition-service.js';\nimport type { FactoryRules } from './rules/types.js';\nimport { assertFactoryRules } from './rules/validation.js';\nimport { SandboxFleet } from './sandbox/fleet.js';\nimport { registerSandboxReattach } from './sandbox/reattach.js';\nimport { handleServerError } from './server-error.js';\nimport { observeSessionFilesystem } from './session/filesystem-capture.js';\nimport { createSpaStaticMiddleware, resolveUiDistDir } from './spa-static.js';\nimport { createStateSigner } from './state-signing.js';\nimport { observeAgentGitAction } from './storage/domains/audit/agent-audit.js';\nimport { AuditStorage } from './storage/domains/audit/base.js';\nimport { AuditDomain } from './storage/domains/audit/domain.js';\nimport { ChannelIdentityStorage } from './storage/domains/channel-identity/base.js';\nimport { ModelCredentialsStorage } from './storage/domains/credentials/base.js';\nimport { CustomProvidersStorage } from './storage/domains/custom-providers/base.js';\nimport { FilesystemStorage } from './storage/domains/filesystem/base.js';\nimport { IntakeStorage } from './storage/domains/intake/base.js';\nimport { IntegrationStorage } from './storage/domains/integrations/base.js';\nimport { MemorySettingsStorage } from './storage/domains/memory-settings/base.js';\nimport { ModelPacksStorage } from './storage/domains/model-packs/base.js';\nimport { FactoryProjectsStorage } from './storage/domains/projects/base.js';\nimport { QueueHealthStorage } from './storage/domains/queue-health/base.js';\nimport { SourceControlStorage } from './storage/domains/source-control/base.js';\nimport { WorkItemsStorage } from './storage/domains/work-items/base.js';\nimport { timedPhase } from './timing.js';\nimport { createWorkspaceFactory } from './workspace.js';\n\ntype BuildApiRoutesDeps = Pick<FactoryApiRoutesDeps, 'controller' | 'authStorage'>;\n\n/** Constructor args for the `new Mastra(...)` literal in the deploy entry. */\nexport type MastraArgs = NonNullable<ConstructorParameters<typeof Mastra>[0]>;\n\nexport interface MastraFactoryConfig {\n /**\n * Auth provider instance — `MastraAuthStudio` (`@mastra/auth-studio`),\n * `MastraAuthWorkos` (`@mastra/auth-workos`), `MastraAuthBetterAuth`\n * (`@mastra/auth-better-auth`), or any custom `MastraAuthProvider`. Whatever\n * instance is passed is the active provider; a passed instance is always\n * honored as-is.\n *\n * Omitted → the factory defaults to `MastraAuthStudio`, proxying auth\n * through the shared Mastra platform API. `MastraAuthStudio` resolves its\n * own env (`MASTRA_SHARED_API_URL`, `MASTRA_ORGANIZATION_ID`,\n * `MASTRA_COOKIE_DOMAIN`).\n *\n * Pass `null` to disable auth entirely (open server, local-dev behavior)\n * without falling back to the default.\n */\n auth?: IMastraAuthProvider | null;\n /**\n * REQUIRED. Factory storage backend powering BOTH agent storage (threads,\n * messages, memory, OM — via `getMastraStorage()`) and the app tables\n * (projects/source-control/audit/intake — via the generic ops surface). Pass a\n * `PgFactoryStorage` (`@mastra/pg`) for deployments or a\n * `LibSQLFactoryStorage` (`@mastra/libsql`) for local dev — one backend,\n * one connection, every feature on.\n */\n storage: FactoryStorage;\n /**\n * Vector store instance for recall search — `PgVector` (`@mastra/pg`) on\n * the same database as `storage`. Omitted → the SDK mount's default vector\n * store resolution applies.\n */\n vector?: MastraVector;\n /**\n * Distributed event bus instance (e.g. `new RedisStreamsPubSub({ url })`).\n * When set, streams/workflows/signals ride it across processes and the\n * controller drops file-based thread locks in favor of pubsub-coordinated\n * leases. Omitted → in-process default.\n */\n pubsub?: PubSub;\n /**\n * Browser-facing origin used to build integration OAuth/install callback\n * URLs and to derive the auth redirect URI. On the platform the SPA is\n * hosted separately, so this MUST be the public API origin.\n * Default: `http://localhost:4111` (the local Factory server, which also\n * serves the UI).\n */\n publicUrl?: string;\n /**\n * Allowed cross-origin SPA origins. The SPA may be served from a separate\n * static host, so credentialed requests must be explicitly allowed.\n */\n allowedOrigins?: string[];\n /** Sandbox configuration. Omitted → repository sandboxes are disabled. */\n sandbox?: MastraFactorySandboxConfig;\n /** Background Factory dispatcher configuration. */\n dispatcher?: MastraFactoryDispatcherConfig;\n /**\n * Deployment-stable secret for signing integration OAuth `state` values.\n * Omitted → a per-process random secret, which is fine for single-process\n * local development but rejected for integrations that declare\n * `requiresStableStateSigner`.\n */\n stateSecret?: string;\n /**\n * Registered capability providers. The factory registers the pieces each\n * `FactoryIntegration` instance provides — HTTP routes, storage domains,\n * agent/session tools, intake, source control, and diagnostics — into the\n * system. When Platform credentials are configured, missing `github` and\n * `linear` integrations default to their Platform-backed implementations.\n */\n integrations?: FactoryIntegration[];\n /**\n * Authoritative Factory board, tool-result, and GitHub-event rules. Construct\n * with `defaultFactoryRules({ version, overrides })` so deployment policy has\n * an explicit version and exact handler leaves replace rather than compose.\n * Omitted → conservative built-in rules for the current deployment.\n */\n rules?: FactoryRules;\n\n /**\n * Platform-specific overrides. When the Platform-backed GitHub integration\n * is active, it derives a `runIssueTriage` runner from the mounted\n * controller automatically. An explicit `runIssueTriage` here takes\n * precedence over the controller-derived default. `githubAppSlug` identifies\n * Factory's own GitHub App writes so their webhook deliveries do not retrigger\n * triage.\n */\n platform?: {\n runIssueTriage?: (input: GithubIssueTriageInput) => Promise<GithubIssueTriageResult>;\n githubAppSlug?: string;\n };\n}\n\nexport interface MastraFactorySandboxConfig {\n /**\n * Template machine — `RailwaySandbox` (`@mastra/railway`), core\n * `LocalSandbox` (`@mastra/core/workspace`), or any `WorkspaceSandbox` that\n * implements `clone()`. Each project-repository execution environment gets\n * its own sandbox cloned from this machine; the machine itself is never\n * started. `prepare()` fails fast when the instance lacks `clone()`.\n */\n machine: WorkspaceSandbox;\n /**\n * In-sandbox base directory repos check out under (nested `owner/name` per\n * repo). Default: the machine's own `workingDirectory` when it exposes one\n * (core `LocalSandbox` does), else `/workspace`.\n */\n workdir?: string;\n /**\n * Per-replica cap on concurrently provisioned sandboxes. `0`/omitted means\n * unlimited. A lightweight per-process budget, not a cross-replica scheduler.\n */\n maxSandboxes?: number;\n}\n\n/**\n * Per-process cap on concurrent background Factory dispatches. Omitted means\n * the dispatcher default; this is a local replica budget, not a global queue\n * limit shared across deployments.\n */\nexport interface MastraFactoryDispatcherConfig {\n maxInFlight?: number;\n}\n\nconst CONTROLLER_ID = 'code';\n\nfunction hasPlatformSecretKey(): boolean {\n return Boolean(process.env.MASTRA_PLATFORM_SECRET_KEY?.trim());\n}\n\n/**\n * The template sandbox's own working directory, when it exposes one as a\n * string (core `LocalSandbox` does; remote providers generally don't).\n * Used as the default checkout base so a local template rooted at a host\n * directory checks repos out under that same root.\n */\nfunction templateWorkingDirectory(sandbox: WorkspaceSandbox): string | undefined {\n const wd = (sandbox as { workingDirectory?: unknown }).workingDirectory;\n return typeof wd === 'string' && wd.length > 0 ? wd : undefined;\n}\n\nfunction resolveSandboxWorkdirBase(machine: WorkspaceSandbox, configuredWorkdir?: string): string {\n const machineWorkdir = templateWorkingDirectory(machine);\n const workdir =\n configuredWorkdir === '/workspace' && machineWorkdir ? machineWorkdir : (configuredWorkdir ?? machineWorkdir);\n return (workdir ?? '/workspace').replace(/\\/+$/, '');\n}\n\n/**\n * Default auth provider — `MastraAuthStudio`, which proxies identity to the\n * shared Mastra platform API. `MastraAuthStudio` resolves `MASTRA_SHARED_API_URL`,\n * `MASTRA_ORGANIZATION_ID`, and `MASTRA_COOKIE_DOMAIN` from env on its own —\n * this helper only derives a cookie-domain fallback from the factory's\n * `publicUrl`.\n *\n * Cookie-domain resolution (Studio picks the first that wins):\n * 1. explicit `MASTRA_COOKIE_DOMAIN` env, if set;\n * 2. `.mastra.ai` when `sharedApiUrl` is on `.mastra.ai`;\n * 3. this parent-domain fallback derived from `publicUrl` — so a deploy on\n * `https://foo.mastra.cloud` mints cookies with `Domain=.mastra.cloud`\n * without the caller wiring the env var by hand.\n * 4. otherwise host-only (no `Domain=`), which is correct for `localhost`.\n */\nfunction buildDefaultStudioAuth(publicUrl: string): IMastraAuthProvider {\n return new MastraAuthStudio({\n cookieDomain: parentDomainFromPublicUrl(publicUrl),\n });\n}\n\n/**\n * Derive a parent cookie domain from `publicUrl` by stripping the leftmost\n * label — the same shape platform-API's env injection uses (see\n * `platform/servers/api/src/lib/studio-env-vars.ts`: `.${routingDomain.replace(/^[^.]+\\./, '')}`).\n *\n * Rather than a generic `strip-left-label` heuristic — which either emits\n * cookies scoped to a public suffix (`sub.example.co.uk` → `.example.co.uk`\n * requires PSL data to be safe) or misclassifies numeric hostnames like\n * `3scale.example.com` as IPv4 — we only derive a parent domain when the\n * host sits under one of the platform's known registrable domains. Anything\n * else (custom domains, arbitrary tenant hostnames, IPs, `localhost`)\n * falls through to host-only cookies. Callers that need a different scope\n * pass `MASTRA_COOKIE_DOMAIN` explicitly (Studio honors that first).\n */\nconst KNOWN_PLATFORM_COOKIE_PARENTS = ['mastra.cloud', 'mastra.ai'] as const;\n\nfunction isIpLiteral(hostname: string): boolean {\n // IPv6 addresses in URLs are bracketed; `URL.hostname` strips the brackets\n // but the address itself still contains `:`. IPv4 is four dot-separated\n // numeric octets — trust the parser to have already validated shape.\n if (hostname.includes(':')) return true;\n return /^\\d+(?:\\.\\d+){3}$/.test(hostname);\n}\n\nfunction parentDomainFromPublicUrl(publicUrl: string): string | undefined {\n let hostname: string;\n try {\n hostname = new URL(publicUrl).hostname.toLowerCase();\n } catch {\n return undefined;\n }\n if (hostname === 'localhost' || isIpLiteral(hostname)) return undefined;\n for (const parent of KNOWN_PLATFORM_COOKIE_PARENTS) {\n // Exact match → we're already on the parent, host-only is correct.\n // Subdomain match → mint the parent-scoped cookie.\n if (hostname === parent) return undefined;\n if (hostname.endsWith(`.${parent}`)) return `.${parent}`;\n }\n return undefined;\n}\n\nexport class MastraFactory {\n readonly #config: MastraFactoryConfig;\n #prepared: Awaited<ReturnType<typeof prepareAgentControllerMount>> | undefined;\n #dispatcher: FactoryDecisionDispatcher | undefined;\n #factoryProcessor: FactoryPhaseStateProcessor | undefined;\n #preparing = false;\n\n constructor(config: MastraFactoryConfig) {\n if (!config?.storage) {\n throw new Error(\n \"MastraFactory: 'storage' is required. Pass a FactoryStorage backend — e.g. \" +\n \"new PgFactoryStorage({ connectionString }) from '@mastra/pg' for deployments, or \" +\n \"new LibSQLFactoryStorage({ url }) from '@mastra/libsql' for local dev.\",\n );\n }\n this.#config = config;\n }\n\n /**\n * Resolve feature readiness, wire every dependency explicitly, and assemble\n * everything needed to construct the server-owned Mastra. Returns the args\n * for the `new Mastra(...)` literal that must live in the entry file.\n */\n async prepare(): Promise<MastraArgs> {\n // Guard set synchronously (before the first await) so overlapping calls —\n // not just strictly sequential ones — can't double-seed the runtime\n // registry or double-run one-time adapter init.\n if (this.#preparing) throw new Error('MastraFactory.prepare() called twice');\n this.#preparing = true;\n\n const publicOrigin = (this.#config.publicUrl ?? 'http://localhost:4111').replace(/\\/+$/, '');\n const allowedOrigins = (this.#config.allowedOrigins ?? []).map(o => o.replace(/\\/+$/, '')).filter(Boolean);\n const storage = this.#config.storage;\n const vector = this.#config.vector;\n const pubsub = this.#config.pubsub;\n // Default auth: honor an explicitly-passed provider (including `null` to\n // disable auth) as-is; otherwise fall back to `MastraAuthStudio`\n // (platform-proxied identity). The default derives its cookie domain\n // from `publicUrl` — deploys on `<sub>.mastra.cloud` mint parent-domain\n // cookies without the caller wiring `MASTRA_COOKIE_DOMAIN` explicitly.\n const configuredAuth = this.#config.auth;\n const auth: IMastraAuthProvider | undefined =\n configuredAuth === null ? undefined : (configuredAuth ?? buildDefaultStudioAuth(publicOrigin));\n // One RouteAuth seam per boot, closed over the resolved provider. Every\n // factory route module receives this handle — no service locator.\n const routeAuth = createFactoryRouteAuth(auth);\n\n // Explicit integrations win. Platform credentials fill only missing GitHub\n // and Linear slots so callers can override either provider independently.\n const integrations = [...(this.#config.integrations ?? [])];\n if (hasPlatformSecretKey()) {\n if (!integrations.some(integration => integration.id === 'github')) {\n integrations.push(\n new PlatformGithubIntegration({\n runIssueTriage: this.#config.platform?.runIssueTriage,\n slug: this.#config.platform?.githubAppSlug,\n }),\n );\n }\n if (!integrations.some(integration => integration.id === 'linear')) {\n integrations.push(new PlatformLinearIntegration());\n }\n }\n\n // Validate ids up front so a copy-paste duplicate fails loud instead of one\n // instance silently shadowing the other.\n const integrationIds = new Set<string>();\n for (const integration of integrations) {\n if (integrationIds.has(integration.id)) {\n throw new Error(`MastraFactory: duplicate integration id '${integration.id}' in 'integrations'.`);\n }\n integrationIds.add(integration.id);\n }\n const rules = this.#config.rules ?? builtInFactoryRules();\n assertFactoryRules(rules);\n\n // FactoryStorage owns every app-table domain and initializes them through\n // the same lifecycle as the backend connection.\n const intakeStorage = storage.registerDomain(new IntakeStorage());\n const auditStorage = storage.registerDomain(new AuditStorage());\n const workItemsStorage = storage.registerDomain(new WorkItemsStorage());\n const modelCredentialsStorage = storage.registerDomain(new ModelCredentialsStorage());\n const modelPacksStorage = storage.registerDomain(new ModelPacksStorage());\n const memorySettingsStorage = storage.registerDomain(new MemorySettingsStorage());\n const customProvidersStorage = storage.registerDomain(new CustomProvidersStorage());\n const queueHealthStorage = storage.registerDomain(new QueueHealthStorage());\n // Generic integration storage (connections/subscriptions/settings) — the\n // default persistence surface for integrations without a bespoke domain.\n const integrationStorage = storage.registerDomain(new IntegrationStorage());\n const factoryProjectsStorage = storage.registerDomain(new FactoryProjectsStorage());\n const filesystemStorage = storage.registerDomain(new FilesystemStorage());\n const sourceControlStorage = storage.registerDomain(new SourceControlStorage());\n // Reverse index from a platform sender (Slack/Discord/...) to a Mastra\n // tenant, so inbound channel events can resolve the sender's model creds.\n const channelIdentityStorage = storage.registerDomain(new ChannelIdentityStorage());\n // Every app-table domain handle the route builders and integrations need,\n // threaded explicitly (no service locator).\n const domains = {\n intake: intakeStorage,\n modelCredentials: modelCredentialsStorage,\n modelPacks: modelPacksStorage,\n memorySettings: memorySettingsStorage,\n customProviders: customProvidersStorage,\n filesystem: filesystemStorage,\n projects: factoryProjectsStorage,\n queueHealth: queueHealthStorage,\n workItems: workItemsStorage,\n channelIdentity: channelIdentityStorage,\n };\n const projectRoutes = new ProjectRoutes({\n auth: routeAuth,\n projects: factoryProjectsStorage,\n sourceControl: sourceControlStorage,\n versionControlIntegrationIds: integrations\n .filter(integration => integration.versionControl)\n .map(integration => integration.id),\n });\n const auditDomain = new AuditDomain({\n auth: routeAuth,\n audit: auditStorage,\n projects: factoryProjectsStorage,\n users: auth && isUserProvider(auth) ? auth : undefined,\n sinks: integrations,\n agentTenant: requestContext => {\n const user = requestContext.get('user') as FactoryAuthUser | undefined;\n return { orgId: getFactoryAuthOrgId(user), userId: getFactoryAuthUserId(user) };\n },\n });\n\n // Repository execution needs one sandbox per project-repository link,\n // cloned from the configured machine. A machine without `clone()` would\n // only fail on first use, so fail fast at boot instead.\n const sandboxConfig = this.#config.sandbox;\n const machine = sandboxConfig?.machine;\n if (machine && typeof machine.clone !== 'function') {\n throw new Error(\n `MastraFactory: the configured sandbox machine (provider '${machine.provider}') does not implement clone(). ` +\n `Project repositories each get their own sandbox cloned from the configured machine. ` +\n `Pass a machine that implements clone() — e.g. RailwaySandbox (@mastra/railway) or ` +\n `LocalSandbox (@mastra/core/workspace) — or omit 'sandbox' to disable sandboxes.`,\n );\n }\n\n // One sandbox fleet per boot: constructed with the machine config when\n // sandboxes are configured, disabled otherwise. Handed to integrations\n // through the IntegrationContext — no global registry.\n const fleet = new SandboxFleet(\n machine\n ? {\n machine,\n workdirBase: resolveSandboxWorkdirBase(machine, sandboxConfig?.workdir),\n maxSandboxes: sandboxConfig?.maxSandboxes,\n }\n : undefined,\n );\n // Core's `getDynamicWorkspace` reattaches project sandboxes through the\n // SDK seam; only this factory owns the fleet, so register it here.\n registerSandboxReattach(fleet);\n\n // One shared OAuth state signer per boot. The deploy entry supplies a\n // replica-stable secret when needed; otherwise local development gets a\n // per-process random signer (`stable: false`).\n const stateSigner = createStateSigner(this.#config.stateSecret);\n\n // One-time provider initialization with factory-level context (e.g.\n // better-auth builds its default instance on the backend's auth\n // database, WorkOS derives its redirect URI from the public URL).\n // Failures surface here, at prepare() — a misconfigured provider must\n // not boot.\n if (auth && hasAuthInit(auth)) {\n await timedPhase('prepare.auth.init', () =>\n auth.init({ database: storage.authDatabase?.(), publicUrl: publicOrigin, allowedOrigins }),\n );\n }\n\n // Single init path: backend connection failure is a hard boot error;\n // registered app domains initialize fail-soft inside FactoryStorage.\n await timedPhase('prepare.storage.init', () => storage.init());\n\n // Per-tenant model credentials: once the credentials domain is up, model\n // resolution goes through the caller's own store and the SDK stops\n // mirroring stored API keys into process.env.\n //\n // Only register when a real auth adapter gates callers. In local /\n // auth-disabled mode there is no authenticated tenant, so registering would\n // force every model call through an empty tenant store (fail-closed, no env\n // fallback) and break chat with \"Not logged in\". Leaving it unregistered\n // lets the SDK fall back to the file-backed AuthStorage (auth.json) — the\n // same store the local /login and Settings pages read and write.\n if (auth) {\n registerTenantCredentialResolver(modelCredentialsStorage);\n }\n\n // Custom providers: DB-backed in both modes (org rows in tenant mode, the\n // sentinel `local` org in no-auth mode). Once registered, model resolution\n // and the gateway catalog never read settings.json custom providers.\n registerCustomProvidersSource({ storage: customProvidersStorage, authEnabled: Boolean(auth) });\n\n for (const integration of integrations) {\n integration.initialize?.({\n storage: integrationStorage.forIntegration(integration.id),\n projects: factoryProjectsStorage,\n auth: routeAuth,\n });\n if (integration.versionControl) {\n integration.versionControl.initialize({\n storage: sourceControlStorage.forIntegration(integration.id),\n });\n }\n }\n\n // Every integration uses generic integration storage. Version-control\n // providers additionally require the source-control storage domain. Readiness\n // is derived solely from capability presence, never from provider ids.\n const integrationRegistrations = integrations.map(integration => {\n const requiredDomains = [\n 'integrations',\n ...(integration.versionControl ? ['source-control'] : []),\n // Channels resolve an inbound sender to a tenant through the reverse\n // index; without it every message would dispatch tenant-less.\n ...(integration.channels ? ['channel-identity'] : []),\n ];\n return {\n integration,\n ready: requiredDomains.every(domain => storage.isDomainReady(domain)),\n ensureReady: async () => {\n for (const domain of requiredDomains) await storage.ensureDomainReady(domain);\n },\n };\n });\n const intakeReady =\n integrations.some(integration => integration.intake !== undefined) && storage.isDomainReady('intake');\n const factoryReady = storage.isDomainReady('projects') && storage.isDomainReady('work-items');\n const githubIntegration = integrations.find(integration => integration.id === 'github') as\n | GithubIntegration\n | undefined;\n const workItemsReady = storage.isDomainReady('work-items');\n // Terminal work items release their session sandboxes back to the reuse\n // pool so the next session for the same repository/user claims a warm VM\n // instead of provisioning fresh. Remote providers only: local \"sandboxes\"\n // are the host machine with per-session workdirs — nothing to pool.\n const releaseTerminalSandboxes =\n machine && !(machine instanceof LocalSandbox) && workItemsReady && storage.isDomainReady('source-control')\n ? async ({ orgId, workItemId }: { orgId: string; workItemId: string }) =>\n releaseWorkItemSandboxes({\n workItems: workItemsStorage,\n sourceControl: sourceControlStorage.forIntegration('github'),\n fleet,\n orgId,\n workItemId,\n })\n : undefined;\n const transitionService = workItemsReady\n ? new FactoryTransitionService({\n rules,\n storage: workItemsStorage,\n ...(releaseTerminalSandboxes ? { onTerminalStage: releaseTerminalSandboxes } : {}),\n })\n : undefined;\n const factoryProcessor = workItemsReady\n ? new FactoryPhaseStateProcessor({\n rules,\n storage: workItemsStorage,\n ...(transitionService ? { transitionService } : {}),\n ...(githubIntegration\n ? {\n recordPullRequestProvenance: (input: Parameters<typeof recordFactoryPullRequestProvenance>[3]) =>\n recordFactoryPullRequestProvenance(\n githubIntegration,\n sourceControlStorage.forIntegration('github'),\n integrationStorage.forIntegration('github'),\n input,\n ),\n }\n : {}),\n messageReader: {\n listMessages: async input => {\n const memory = await storage.getMastraStorage().getStore('memory');\n return memory ? memory.listMessages(input) : { messages: [], hasMore: false };\n },\n },\n })\n : undefined;\n\n // Boot assertion: an active integration that signs OAuth `state` needs a\n // replica-stable signer — a per-process random secret silently breaks the\n // OAuth callback on any replica that didn't sign the state. Fail loud now\n // instead. (The built-ins also assert this inside their readiness gates.)\n for (const { integration } of integrationRegistrations) {\n if (integration.requiresStableStateSigner && !stateSigner.stable) {\n throw new Error(\n `MastraFactory: integration '${integration.id}' signs OAuth state and requires a ` +\n `replica-stable state secret, but none is configured. Set 'stateSecret' on the factory config.`,\n );\n }\n }\n\n // The SDK needs to know which backend the injected Mastra store uses\n // (its own `instanceof` detection breaks when the dependency graph holds\n // duplicate package copies). Resolve it by walking the FactoryStorage\n // prototype chain by class name — the factory can't import the concrete\n // classes since '@mastra/pg' / '@mastra/libsql' are the user's choice.\n const mastraStorageBackend = (() => {\n for (let proto = Object.getPrototypeOf(storage); proto; proto = Object.getPrototypeOf(proto)) {\n if (proto.constructor?.name === 'PgFactoryStorage') return 'pg' as const;\n if (proto.constructor?.name === 'LibSQLFactoryStorage') return 'libsql' as const;\n }\n return undefined;\n })();\n\n // Integrations contributing tools to agent sessions: org-scoped\n // `agentTools` (resolved per request) + session-scoped `sessionTools`.\n const toolIntegrations = integrationRegistrations.filter(\n ({ integration }) => integration.agentTools || integration.sessionTools,\n );\n\n // Build the real production controller (agents, modes, tools, memory, OM,\n // MCP, providers) — identical to the terminal app. Agent state lives in\n // the storage backend's Mastra store alongside the Factory app tables —\n // one shared database for all users, separated by `resourceId` scoping.\n const prepared = await timedPhase('prepare.controllerMount', () =>\n prepareAgentControllerMount({\n controllerId: CONTROLLER_ID,\n workspace: createWorkspaceFactory({\n ...(this.#config.sandbox ? { sandbox: this.#config.sandbox } : {}),\n ...(githubIntegration ? { github: githubIntegration } : {}),\n ...(workItemsStorage ? { workItems: workItemsStorage } : {}),\n fleet,\n }),\n disableGithubSignals: true,\n // Memory settings live in the factory's `memory-settings` app table (per\n // org/user), so the host machine's TUI settings.json must not seed them.\n disableSettingsOmSeed: true,\n // A factory reads the repository it works on and its skill, never the\n // ~/.claude instructions of whoever hosts the process. On the controller\n // rather than per session, so webhook-recreated sessions keep it too.\n initialState: { skipGlobalInstructions: true },\n storage: storage.getMastraStorage(),\n ...(mastraStorageBackend ? { storageBackend: mastraStorageBackend } : {}),\n ...(factoryProcessor ? { inputProcessors: [factoryProcessor] } : {}),\n ...(vector ? { vector } : {}),\n ...(toolIntegrations.length > 0 || (workItemsStorage && transitionService)\n ? {\n extraTools: async ({ requestContext }: { requestContext: RequestContext }) => {\n const tools: IntegrationTools = {};\n const toolOwners = new Map<string, string>();\n const mergeTools = (ownerId: string, contributed: IntegrationTools) => {\n for (const [name, tool] of Object.entries(contributed)) {\n const owner = toolOwners.get(name);\n if (owner) {\n throw new Error(\n `MastraFactory: integration tool '${name}' from '${ownerId}' conflicts with '${owner}'.`,\n );\n }\n toolOwners.set(name, ownerId);\n tools[name] = tool;\n }\n };\n if (workItemsStorage && transitionService) {\n mergeTools(\n 'factory',\n await createFactoryTransitionTools({\n requestContext,\n storage: workItemsStorage,\n transitionService,\n // Heals crash-resumed sessions: recovered addresses re-seed\n // projectRepositoryId/baseRef from the source session record.\n // Only offered while the source-control domain is ready — a\n // throwing lookup would abort recovery's catch block and also\n // skip the metadata baseRef fallback.\n ...(storage.isDomainReady('source-control')\n ? { sessions: sourceControlStorage.forIntegration('github').sessions }\n : {}),\n }),\n );\n }\n for (const { integration, ready, ensureReady } of toolIntegrations) {\n if (!ready && ensureReady) {\n try {\n await ensureReady();\n } catch {\n continue;\n }\n }\n if (integration.agentTools) {\n mergeTools(integration.id, await integration.agentTools({ requestContext }));\n }\n if (integration.sessionTools) {\n mergeTools(integration.id, integration.sessionTools({ requestContext }));\n }\n }\n return tools;\n },\n }\n : {}),\n postToolObserver: async (toolContext: IntegrationPostToolContext) => {\n const requestContext = (toolContext.context as { requestContext?: RequestContext } | undefined)\n ?.requestContext;\n if (requestContext) {\n await observeAgentGitAction({\n audit: auditDomain,\n toolContext: { ...toolContext, context: requestContext },\n });\n }\n await Promise.all(\n integrations.map(async integration => {\n if (!integration.postToolObserver) return;\n try {\n await integration.postToolObserver({ toolContext, requestContext });\n } catch (error) {\n console.warn(`[factory] Integration '${integration.id}' post-tool observer failed:`, error);\n }\n }),\n );\n },\n ...(pubsub ? { pubsub, crossProcessPubSub: true } : {}),\n buildApiRoutes: ({ controller, authStorage }: BuildApiRoutesDeps) => [\n // Public `/auth/*` routes (login/callback/logout/me). Folded in as\n // `apiRoutes` (not plain Hono routes) because the entry can't touch the\n // Hono app the deployer generates. `requiresAuth: false`; the gate\n // skips `/auth/*`.\n ...(auth ? buildAuthRoutes(auth, { publicUrl: publicOrigin }) : []),\n // Custom `/web/*` routes (fs / config / integrations / factory / audit).\n ...assembleFactoryApiRoutes({\n controllerId: CONTROLLER_ID,\n controller,\n auth: routeAuth,\n authStorage,\n audit: auditDomain,\n publicOrigin,\n stateSigner,\n fleet,\n factoryStorage: storage,\n integrationStorage,\n sourceControlStorage,\n domains,\n integrations: integrationRegistrations,\n intakeReady,\n factoryReady,\n rules,\n factoryTransitionService: transitionService,\n onFactoryRuntime: ({ transitionService: runtimeTransitionService, prepareBinding }) => {\n this.#dispatcher ??= new FactoryDecisionDispatcher({\n controller,\n transitionService: runtimeTransitionService,\n storage: storage.getDomain<WorkItemsStorage>('work-items'),\n maxInFlight: this.#config.dispatcher?.maxInFlight,\n reconcileToolResults: () => factoryProcessor?.reconcileAllBoundThreads() ?? Promise.resolve(),\n prepareBinding,\n primeCredentials: tenant => primeTenantCredentials({ tenant, credentials: modelCredentialsStorage }),\n });\n },\n }),\n ...projectRoutes.routes(),\n ...auditDomain.routes(),\n ],\n buildServerConfig: () => {\n const cors = allowedOrigins.length ? { cors: { origin: allowedOrigins, credentials: true } } : {};\n // Log route errors with method/path/stack and answer with structured\n // JSON instead of an opaque `Internal Server Error`. Applied by the\n // deployer to both the top-level app and the custom-route sub-app.\n const onError = { onError: handleServerError };\n // Same-origin SPA: when a vite build is present (see resolveUiDistDir),\n // serve it at `/` from this server. Mounted last so the auth gate (when\n // enabled) covers it; it always passes `/api`, `/web`, `/auth` through.\n const uiDist = resolveUiDistDir();\n const spa = uiDist ? [createSpaStaticMiddleware(uiDist)] : [];\n if (!auth) {\n // Auth disabled: no gate. Still prime the sentinel-local custom\n // provider snapshot so model calls see DB rows, then SPA + CORS.\n return {\n middleware: [\n createCustomProvidersPrimer({ auth: routeAuth, storage: customProvidersStorage, authEnabled: false }),\n ...spa,\n ],\n ...cors,\n ...onError,\n };\n }\n\n // Ordered middleware. The deployer applies these AFTER its context\n // middleware sets `c.set('mastra', mastra)` and BEFORE routes, so:\n // 1. gate — validates the auth session, stashes the user, and 401s /\n // redirects unauthenticated requests. Skips public `/auth/*`.\n // 2. primers — hydrate the caller's model-credential and custom\n // provider snapshots so the request's first model call\n // resolves tenant credentials and custom providers.\n // 3. spa — serves the built UI for everything the server doesn't own.\n // `auth` also lands on `server.auth` so the core auth middleware (and\n // Studio's dual-auth routing — see `studio.auth` on the returned args)\n // authenticates core `/api/*` routes with the same provider.\n return {\n auth,\n middleware: [\n createFactoryAuthGate(auth),\n createTenantCredentialPrimer({ auth: routeAuth, credentials: modelCredentialsStorage }),\n createCustomProvidersPrimer({\n auth: routeAuth,\n storage: customProvidersStorage,\n authEnabled: Boolean(auth),\n }),\n ...spa,\n ],\n ...cors,\n ...onError,\n };\n },\n }),\n );\n\n prepared.base.controller.onSessionCreated(session => {\n observeSessionFilesystem(session, {\n filesystem: filesystemStorage,\n sourceControl: sourceControlStorage.forIntegration('github'),\n });\n });\n\n this.#prepared = prepared;\n this.#factoryProcessor = factoryProcessor;\n\n // Chat-platform channels (Slack, Discord, …) contributed by integrations,\n // attached to the mounted controller so inbound platform messages reach\n // the same agents the web UI drives. READY integrations only — readiness\n // means the `channel-identity` domain's `init()` succeeded, so its link\n // table is queryable. Without it a sender can't be resolved to a tenant,\n // and attaching anyway would dispatch runs on default credentials.\n const channelRegistrations = integrationRegistrations.filter(\n ({ integration, ready }) => ready && integration.channels,\n );\n // `setChannels` replaces rather than merges, so a second provider would\n // silently never receive a message. Fail loud instead.\n if (channelRegistrations.length > 1) {\n throw new Error(\n `MastraFactory: integrations [${channelRegistrations\n .map(({ integration }) => integration.id)\n .join(', ')}] all provide channels, but only one may. Remove all but one.`,\n );\n }\n for (const { integration } of channelRegistrations) {\n // Integrations return a channels CONFIG; the factory owns construction.\n prepared.base.controller.setChannels(\n new AgentControllerChannels(\n integration.channels!(\n buildIntegrationContext(\n {\n controller: prepared.base.controller,\n publicOrigin,\n auth: routeAuth,\n stateSigner,\n fleet,\n factoryStorage: storage,\n integrationStorage,\n sourceControlStorage,\n rules,\n factoryReady,\n domains,\n ...(githubIntegration ? { sourceControlOwnerId: 'github' } : {}),\n },\n integration.id,\n ),\n ),\n ),\n );\n }\n\n // Integration lifecycle workers (e.g. polling an upstream without\n // webhooks): collected from READY integrations only, folded into the\n // constructor args so `new Mastra(...)` merges them with the default\n // workers and `finalize()`'s `startWorkers()` starts them alongside the\n // built-ins. Never passed for the disabled/not-ready case — a worker for\n // an unavailable integration must not run.\n const integrationWorkers = integrationRegistrations\n .filter(({ integration, ready }) => ready && integration.workers)\n .flatMap(({ integration }) =>\n integration.workers!(\n buildIntegrationContext(\n {\n controller: prepared.base.controller,\n publicOrigin,\n auth: routeAuth,\n stateSigner,\n fleet,\n factoryStorage: storage,\n integrationStorage,\n sourceControlStorage,\n rules,\n factoryReady,\n domains,\n ...(githubIntegration ? { sourceControlOwnerId: 'github' } : {}),\n },\n integration.id,\n ),\n ),\n );\n\n return {\n ...prepared.mastraArgs,\n // Same provider on `studio.auth` as on `server.auth` (buildServerConfig):\n // deployed factories must authenticate BOTH plain API callers and Studio\n // requests (`x-mastra-client-type: studio` routes to `studio.auth`).\n ...(auth ? { studio: { auth } } : {}),\n ...(integrationWorkers.length > 0 ? { workers: integrationWorkers } : {}),\n };\n }\n\n /**\n * Post-construct boot: initialize the controller (which inherits the\n * constructed Mastra's storage) and start its workers. Call AFTER the entry\n * has run `new Mastra(prepare()'s args)`.\n */\n async finalize(): Promise<void> {\n if (!this.#prepared) {\n throw new Error('MastraFactory.finalize() called before prepare()');\n }\n await timedPhase('finalize.controller', () => this.#prepared!.finalize());\n await timedPhase(\n 'finalize.reconcileBoundThreads',\n () => this.#factoryProcessor?.reconcileAllBoundThreads() ?? Promise.resolve(),\n );\n this.#dispatcher?.start();\n }\n\n /** Stop Factory-owned background dispatch before the host process shuts down. */\n async shutdown(): Promise<void> {\n await this.#dispatcher?.stop();\n }\n}\n"],"mappings":"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"}
|
|
@@ -33,6 +33,7 @@ import type { AuditEmitter } from '../storage/domains/audit/domain.js';
|
|
|
33
33
|
import type { ChannelIdentityStorage } from '../storage/domains/channel-identity/base.js';
|
|
34
34
|
import type { IntakeStorage } from '../storage/domains/intake/base.js';
|
|
35
35
|
import type { IntegrationStorageHandle } from '../storage/domains/integrations/base.js';
|
|
36
|
+
import type { MemorySettingsStorage } from '../storage/domains/memory-settings/base.js';
|
|
36
37
|
import type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';
|
|
37
38
|
import type { SourceControlStorageHandle } from '../storage/domains/source-control/base.js';
|
|
38
39
|
import type { WorkItemsStorage } from '../storage/domains/work-items/base.js';
|
|
@@ -94,6 +95,11 @@ export interface IntegrationContext {
|
|
|
94
95
|
sourceControlOwner?: SourceControlStorageHandle;
|
|
95
96
|
/** Factory projects domain — e.g. resolving a project's default model. */
|
|
96
97
|
projects: FactoryProjectsStorage;
|
|
98
|
+
/**
|
|
99
|
+
* Observational-memory settings domain, so a session an integration starts
|
|
100
|
+
* adopts the same memory configuration the web kickoff applies.
|
|
101
|
+
*/
|
|
102
|
+
memorySettings: MemorySettingsStorage;
|
|
97
103
|
/** Cross-integration intake selection (which sources are synced). */
|
|
98
104
|
intake: IntakeStorage;
|
|
99
105
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/integrations/base.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/integrations/base.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,7 +29,7 @@ import { Octokit } from '@octokit/rest';
|
|
|
29
29
|
import type { Intake } from '../../capabilities/intake.js';
|
|
30
30
|
import type { VersionControl } from '../../capabilities/version-control.js';
|
|
31
31
|
import type { FactoryIntegration, IntegrationContext, IntegrationTools } from '../base.js';
|
|
32
|
-
import type { ReconcilePullRequestState } from './rules.js';
|
|
32
|
+
import type { ReconcileIssueState, ReconcilePullRequestState } from './rules.js';
|
|
33
33
|
import type { GithubSubscriptionStorage } from './subscriptions.js';
|
|
34
34
|
/**
|
|
35
35
|
* Normalize a PEM private key supplied via env. Env tooling tends to mangle
|
|
@@ -60,6 +60,7 @@ export interface IssueSummary {
|
|
|
60
60
|
title: string;
|
|
61
61
|
url: string;
|
|
62
62
|
author: string | null;
|
|
63
|
+
assignees: string[];
|
|
63
64
|
labels: string[];
|
|
64
65
|
comments: number;
|
|
65
66
|
createdAt: string;
|
|
@@ -153,6 +154,8 @@ export declare class GithubIntegration implements FactoryIntegration {
|
|
|
153
154
|
getInstallationRepo(installationId: number, repoFullName: string): Promise<RepoSummary | null>;
|
|
154
155
|
/** Add labels to an issue (deduplicated; no-op on empty/malformed input). */
|
|
155
156
|
addIssueLabels(installationId: number, repoFullName: string, issueNumber: number, labels: string[]): Promise<void>;
|
|
157
|
+
/** Remove one label from an issue. */
|
|
158
|
+
removeIssueLabel(installationId: number, repoFullName: string, issueNumber: number, label: string): Promise<void>;
|
|
156
159
|
/**
|
|
157
160
|
* List one page of a repo's open issues through an installation token. The
|
|
158
161
|
* issues API also returns pull requests, so those are filtered out (the
|
|
@@ -195,6 +198,16 @@ export declare class GithubIntegration implements FactoryIntegration {
|
|
|
195
198
|
repository: string;
|
|
196
199
|
number: number;
|
|
197
200
|
}): Promise<ReconcilePullRequestState | undefined>;
|
|
201
|
+
/**
|
|
202
|
+
* Reads live issue state for the reconciler. Returns undefined when the
|
|
203
|
+
* issue cannot be resolved (missing, is actually a PR, API error) so a
|
|
204
|
+
* sweep never fabricates a close.
|
|
205
|
+
*/
|
|
206
|
+
fetchIssueState(input: {
|
|
207
|
+
installationId: number;
|
|
208
|
+
repository: string;
|
|
209
|
+
number: number;
|
|
210
|
+
}): Promise<ReconcileIssueState | undefined>;
|
|
198
211
|
/**
|
|
199
212
|
* Session-scoped agent tools for token refresh and PR subscriptions in
|
|
200
213
|
* sessions bound to a GitHub-backed project. Empty elsewhere.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../../src/integrations/github/integration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAGxC,OAAO,KAAK,EAGV,MAAM,EAKP,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAKV,cAAc,EACf,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../../src/integrations/github/integration.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { createGithubSubscriptionTools, parseCreatedPullRequest, subscribeCurrentSessionToPullRequest } from "./session-subscriptions.js";
|
|
2
|
+
import { attachGithubReconciler, attachGithubRules } from "./rules.js";
|
|
3
|
+
import { attachGithubIssueReconciler } from "./issue-reconciler.js";
|
|
2
4
|
import { runGithubIssueTriage } from "./issue-triage.js";
|
|
3
5
|
import { buildGithubRoutes } from "./routes.js";
|
|
4
|
-
import { attachGithubReconciler, attachGithubRules } from "./rules.js";
|
|
5
6
|
import { GithubReconcileWorker } from "./reconcile-worker.js";
|
|
6
7
|
import { createAppAuth } from "@octokit/auth-app";
|
|
7
8
|
import { Octokit } from "@octokit/rest";
|
|
@@ -399,7 +400,8 @@ var GithubIntegration = class {
|
|
|
399
400
|
state: "open",
|
|
400
401
|
stateType: "open",
|
|
401
402
|
priority: null,
|
|
402
|
-
assignee: null,
|
|
403
|
+
assignee: issue.assignees[0] ?? null,
|
|
404
|
+
assignees: issue.assignees,
|
|
403
405
|
source: repoFullName,
|
|
404
406
|
labels: issue.labels,
|
|
405
407
|
commentCount: issue.comments,
|
|
@@ -438,6 +440,7 @@ var GithubIntegration = class {
|
|
|
438
440
|
stateType: issue.state,
|
|
439
441
|
priority: null,
|
|
440
442
|
assignee: issue.assignee?.login ?? null,
|
|
443
|
+
assignees: (issue.assignees ?? []).map((user) => user.login).filter((login) => Boolean(login)),
|
|
441
444
|
source: repoFullName,
|
|
442
445
|
labels: issue.labels.map((label) => typeof label === "string" ? label : label.name ?? "").filter(Boolean),
|
|
443
446
|
commentCount: issue.comments,
|
|
@@ -495,6 +498,7 @@ var GithubIntegration = class {
|
|
|
495
498
|
stateType: issue.state,
|
|
496
499
|
priority: null,
|
|
497
500
|
assignee: issue.assignee?.login ?? null,
|
|
501
|
+
assignees: (issue.assignees ?? []).map((user) => user.login).filter((login) => Boolean(login)),
|
|
498
502
|
source: repoFullName,
|
|
499
503
|
labels: issue.labels.map((label) => typeof label === "string" ? label : label.name ?? "").filter(Boolean),
|
|
500
504
|
commentCount: issue.comments,
|
|
@@ -825,6 +829,18 @@ var GithubIntegration = class {
|
|
|
825
829
|
labels: uniqueLabels
|
|
826
830
|
});
|
|
827
831
|
}
|
|
832
|
+
/** Remove one label from an issue. */
|
|
833
|
+
async removeIssueLabel(installationId, repoFullName, issueNumber, label) {
|
|
834
|
+
const parts = splitRepoFullName(repoFullName);
|
|
835
|
+
const labelName = label.trim();
|
|
836
|
+
if (!parts || !labelName) return;
|
|
837
|
+
await this.getInstallationOctokit(installationId).issues.removeLabel({
|
|
838
|
+
owner: parts.owner,
|
|
839
|
+
repo: parts.repo,
|
|
840
|
+
issue_number: issueNumber,
|
|
841
|
+
name: labelName
|
|
842
|
+
});
|
|
843
|
+
}
|
|
828
844
|
/**
|
|
829
845
|
* List one page of a repo's open issues through an installation token. The
|
|
830
846
|
* issues API also returns pull requests, so those are filtered out (the
|
|
@@ -851,6 +867,7 @@ var GithubIntegration = class {
|
|
|
851
867
|
title: issue.title,
|
|
852
868
|
url: issue.html_url,
|
|
853
869
|
author: issue.user?.login ?? null,
|
|
870
|
+
assignees: issue.assignees?.flatMap((assignee) => assignee.login ? [assignee.login] : []) ?? [],
|
|
854
871
|
labels: issue.labels.map((label) => typeof label === "string" ? label : label.name ?? "").filter(Boolean),
|
|
855
872
|
comments: issue.comments,
|
|
856
873
|
createdAt: issue.created_at,
|
|
@@ -936,11 +953,14 @@ var GithubIntegration = class {
|
|
|
936
953
|
if (process.env.MASTRACODE_GITHUB_RECONCILE_ENABLED?.trim().toLowerCase() === "false") return [];
|
|
937
954
|
const reconcile = attachGithubReconciler(this, ctx, (input) => this.fetchPullRequestState(input));
|
|
938
955
|
if (!reconcile) return [];
|
|
956
|
+
const issues = attachGithubIssueReconciler(this, ctx, (input) => this.fetchIssueState(input));
|
|
939
957
|
const intervalMs = Number(process.env.MASTRACODE_GITHUB_RECONCILE_INTERVAL_MS);
|
|
958
|
+
const interval = Number.isSafeInteger(intervalMs) && intervalMs > 0 ? { intervalMs } : {};
|
|
940
959
|
return [new GithubReconcileWorker({
|
|
941
960
|
reconcile,
|
|
961
|
+
...issues ? { reconcileIssues: issues } : {},
|
|
942
962
|
sourceControl: ctx.storage.sourceControl,
|
|
943
|
-
...
|
|
963
|
+
...interval
|
|
944
964
|
})];
|
|
945
965
|
}
|
|
946
966
|
/**
|
|
@@ -962,9 +982,14 @@ var GithubIntegration = class {
|
|
|
962
982
|
title: pullRequest.title,
|
|
963
983
|
url: pullRequest.url,
|
|
964
984
|
state: pullRequest.state === "closed" ? "closed" : "open",
|
|
985
|
+
draft: pullRequest.draft,
|
|
965
986
|
merged: pullRequest.merged,
|
|
987
|
+
assignees: pullRequest.assignees ?? [],
|
|
988
|
+
requestedReviewers: pullRequest.requestedReviewers ?? [],
|
|
989
|
+
labels: pullRequest.labels ?? [],
|
|
966
990
|
headBranch: pullRequest.headBranch,
|
|
967
991
|
baseBranch: pullRequest.baseBranch,
|
|
992
|
+
...pullRequest.author ? { author: pullRequest.author } : {},
|
|
968
993
|
...pullRequest.createdAt ? { createdAt: pullRequest.createdAt } : {}
|
|
969
994
|
};
|
|
970
995
|
} catch {
|
|
@@ -972,6 +997,36 @@ var GithubIntegration = class {
|
|
|
972
997
|
}
|
|
973
998
|
}
|
|
974
999
|
/**
|
|
1000
|
+
* Reads live issue state for the reconciler. Returns undefined when the
|
|
1001
|
+
* issue cannot be resolved (missing, is actually a PR, API error) so a
|
|
1002
|
+
* sweep never fabricates a close.
|
|
1003
|
+
*/
|
|
1004
|
+
async fetchIssueState(input) {
|
|
1005
|
+
const parts = splitRepoFullName(input.repository);
|
|
1006
|
+
if (!parts) return void 0;
|
|
1007
|
+
try {
|
|
1008
|
+
const { data: issue } = await this.getInstallationOctokit(input.installationId).issues.get({
|
|
1009
|
+
owner: parts.owner,
|
|
1010
|
+
repo: parts.repo,
|
|
1011
|
+
issue_number: input.number
|
|
1012
|
+
});
|
|
1013
|
+
if (issue.pull_request) return void 0;
|
|
1014
|
+
return {
|
|
1015
|
+
title: issue.title,
|
|
1016
|
+
url: issue.html_url,
|
|
1017
|
+
state: issue.state === "closed" ? "closed" : "open",
|
|
1018
|
+
...issue.state_reason ? { stateReason: issue.state_reason } : {},
|
|
1019
|
+
assignees: (issue.assignees ?? []).map((user) => user.login).filter((login) => Boolean(login)),
|
|
1020
|
+
labels: (issue.labels ?? []).map((label) => typeof label === "string" ? label : label.name).filter((name) => Boolean(name)),
|
|
1021
|
+
...issue.user?.login ? { author: issue.user.login } : {},
|
|
1022
|
+
createdAt: issue.created_at,
|
|
1023
|
+
updatedAt: issue.updated_at
|
|
1024
|
+
};
|
|
1025
|
+
} catch {
|
|
1026
|
+
return;
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
/**
|
|
975
1030
|
* Session-scoped agent tools for token refresh and PR subscriptions in
|
|
976
1031
|
* sessions bound to a GitHub-backed project. Empty elsewhere.
|
|
977
1032
|
*/
|
|
@@ -997,6 +1052,9 @@ function parsePullRequest(pr) {
|
|
|
997
1052
|
title: pr.title,
|
|
998
1053
|
url: pr.html_url,
|
|
999
1054
|
author: pr.user?.login ?? null,
|
|
1055
|
+
assignees: (pr.assignees ?? []).flatMap((assignee) => assignee.login ? [assignee.login] : []),
|
|
1056
|
+
requestedReviewers: (pr.requested_reviewers ?? []).flatMap((reviewer) => reviewer.login ? [reviewer.login] : []),
|
|
1057
|
+
labels: (pr.labels ?? []).flatMap((label) => typeof label === "string" ? [label] : label.name ? [label.name] : []),
|
|
1000
1058
|
body: pr.body?.trim() ? pr.body : null,
|
|
1001
1059
|
state: pr.state === "closed" ? "closed" : "open",
|
|
1002
1060
|
draft: pr.draft ?? false,
|