@mastra/factory 0.21.0-alpha.2 → 0.21.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth.d.ts +7 -12
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +20 -1
- package/dist/auth.js.map +1 -1
- package/dist/factory.d.ts +9 -0
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +56 -23
- package/dist/factory.js.map +1 -1
- package/dist/integrations/github/routes.js +1 -0
- package/dist/integrations/github/routes.js.map +1 -1
- package/dist/integrations/linear/issue-reconciler.d.ts +3 -1
- package/dist/integrations/linear/issue-reconciler.d.ts.map +1 -1
- package/dist/integrations/linear/issue-reconciler.js +1 -1
- package/dist/integrations/linear/issue-reconciler.js.map +1 -1
- package/dist/integrations/platform/linear/integration.d.ts.map +1 -1
- package/dist/integrations/platform/linear/integration.js +10 -9
- 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 +0 -1
- package/dist/integrations/slack/integration.js.map +1 -1
- package/dist/integrations/slack/slack.d.ts +0 -17
- package/dist/integrations/slack/slack.d.ts.map +1 -1
- package/dist/integrations/slack/slack.js +8 -40
- package/dist/integrations/slack/slack.js.map +1 -1
- package/dist/packages/_internals/workspace/dist/index.js +3 -0
- package/dist/packages/_internals/workspace/dist/index.js.map +1 -1
- package/dist/routes/config.d.ts +15 -36
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +72 -123
- package/dist/routes/config.js.map +1 -1
- package/dist/routes/knowledge.d.ts +115 -21
- package/dist/routes/knowledge.d.ts.map +1 -1
- package/dist/routes/knowledge.js +715 -30
- package/dist/routes/knowledge.js.map +1 -1
- package/dist/routes/oauth.d.ts +0 -3
- package/dist/routes/oauth.d.ts.map +1 -1
- package/dist/routes/oauth.js +2 -10
- package/dist/routes/oauth.js.map +1 -1
- package/dist/routes/provider-credentials.d.ts.map +1 -1
- package/dist/routes/provider-credentials.js +2 -1
- package/dist/routes/provider-credentials.js.map +1 -1
- package/dist/routes/surface.d.ts +1 -0
- package/dist/routes/surface.d.ts.map +1 -1
- package/dist/routes/surface.js +6 -3
- package/dist/routes/surface.js.map +1 -1
- package/dist/rules/binding-context.d.ts +19 -0
- package/dist/rules/binding-context.d.ts.map +1 -1
- package/dist/rules/binding-context.js +39 -1
- package/dist/rules/binding-context.js.map +1 -1
- package/dist/rules/dispatcher.d.ts +2 -13
- package/dist/rules/dispatcher.d.ts.map +1 -1
- package/dist/rules/dispatcher.js +0 -6
- package/dist/rules/dispatcher.js.map +1 -1
- package/dist/rules/processor.d.ts +35 -1
- package/dist/rules/processor.d.ts.map +1 -1
- package/dist/rules/processor.js +80 -4
- package/dist/rules/processor.js.map +1 -1
- package/dist/rules/start-coordinator.d.ts +1 -2
- package/dist/rules/start-coordinator.d.ts.map +1 -1
- package/dist/rules/start-coordinator.js +2 -6
- package/dist/rules/start-coordinator.js.map +1 -1
- package/dist/session/factory-session.d.ts +5 -43
- package/dist/session/factory-session.d.ts.map +1 -1
- package/dist/session/factory-session.js +6 -47
- package/dist/session/factory-session.js.map +1 -1
- package/dist/session/memory-settings-hydration.d.ts +17 -89
- package/dist/session/memory-settings-hydration.d.ts.map +1 -1
- package/dist/session/memory-settings-hydration.js +25 -111
- package/dist/session/memory-settings-hydration.js.map +1 -1
- package/dist/storage/domains/memory-settings/base.d.ts +5 -17
- package/dist/storage/domains/memory-settings/base.d.ts.map +1 -1
- package/dist/storage/domains/memory-settings/base.js +8 -15
- package/dist/storage/domains/memory-settings/base.js.map +1 -1
- package/dist/supervisor/session.d.ts +2 -4
- package/dist/supervisor/session.d.ts.map +1 -1
- package/dist/supervisor/session.js +3 -5
- package/dist/supervisor/session.js.map +1 -1
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +2 -2
- package/dist/workspace.js.map +1 -1
- package/package.json +8 -8
- package/dist/routes/om-seed.d.ts +0 -22
- package/dist/routes/om-seed.d.ts.map +0 -1
- package/dist/routes/om-seed.js +0 -40
- package/dist/routes/om-seed.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-credentials.js","names":[],"sources":["../../src/routes/provider-credentials.ts"],"sourcesContent":["/**\n * Per-request model-provider credential context.\n *\n * The provider config/OAuth routes serve two deployment shapes:\n *\n * - **Local** (no web auth adapter): credentials live in the server-global\n * file-backed `AuthStorage` (`auth.json`) — unchanged TUI behavior.\n * - **Tenant** (auth adapter active): credentials live in the\n * `model-credentials` factory storage domain, scoped per `(orgId, userId)`\n * with optional org-wide rows (`userId` absent).\n *\n * `resolveCredentialContext` decides which shape a request is in: an\n * authenticated user always gets the tenant path; an unauthenticated request\n * is rejected when auth is enabled and falls back to local otherwise.\n */\n\nimport type { Context } from 'hono';\n\nimport type {\n CredentialRecord,\n LoginSessionKind,\n ModelCredentialsStorage,\n} from '../storage/domains/credentials/base.js';\nimport type { RouteAuth } from './route.js';\n\n/**\n * OAuth credentials are stored under the auth provider id, which differs from\n * the catalog provider id for OpenAI (stored as `openai-codex`). Tenant rows\n * use the same keying so one lookup serves both OAuth tokens and API keys.\n */\nexport function getAuthProviderId(provider: string): string {\n return provider === 'openai' ? 'openai-codex' : provider;\n}\n\n/**\n * Providers that support a browser-driven OAuth sign-in flow, keyed by\n * *catalog* provider id (what the routes and settings UI use). All flows need\n * no inbound connection to the server: Anthropic uses paste-code PKCE, the\n * rest use RFC 8628-style device codes.\n */\nexport const WEB_OAUTH_FLOW_KINDS: Readonly<Record<string, LoginSessionKind>> = {\n anthropic: 'paste-code',\n openai: 'device-code',\n 'github-copilot': 'device-code',\n xai: 'device-code',\n};\n\nexport type CredentialContext =\n | { mode: 'local' }\n | { mode: 'tenant'; storage: ModelCredentialsStorage; orgId: string; userId: string };\n\n/**\n * The tenant credentials domain, when registered and ready. `undefined` means\n * the factory never ran (no handle threaded in) or the domain's init failed\n * (fail-soft — callers report the feature unavailable instead of crashing).\n */\nexport async function getTenantCredentialsStorage(\n credentials: ModelCredentialsStorage | undefined,\n): Promise<ModelCredentialsStorage | undefined> {\n if (!credentials) return undefined;\n try {\n await credentials.ensureReady();\n } catch {\n return undefined;\n }\n return credentials;\n}\n\n/**\n * Org key for tenant rows. Personal accounts get an org bootstrapped by the\n * auth adapter (`ensureOrg`); if one still isn't present, scope rows under a\n * per-user synthetic org so credentials never become server-global.\n */\nexport function tenantOrgId(tenant: { orgId?: string; userId: string }): string {\n return tenant.orgId ?? `user:${tenant.userId}`;\n}\n\n/**\n * Resolve the credential context for a request, or a ready-to-return error\n * response. Mutating credential routes call this and hard-fail (401/503)\n * when the tenant path is required but unavailable.\n */\nexport async function resolveCredentialContext({\n c,\n auth,\n credentials,\n}: {\n c: Context;\n auth: RouteAuth;\n /** Tenant credential domain handle; absent in local (no-DB) mode. */\n credentials?: ModelCredentialsStorage;\n}): Promise<CredentialContext | { response: Response }> {\n await auth.ensureUser(c);\n const tenant = auth.tenant(c);\n if (!tenant) {\n // When an auth provider is active, credential operations always require a\n // signed-in caller — otherwise one anonymous request could write keys for\n // everyone. Without a provider this is a single-user local server.\n if (auth.enabled()) return { response: c.json({ error: 'unauthorized' }, 401) };\n return { mode: 'local' };\n }\n const storage = await getTenantCredentialsStorage(credentials);\n if (!storage) {\n return {\n response: c.json(\n {\n error: 'credentials_unavailable',\n message: 'Tenant credential storage is unavailable — the app database is not configured or failed to start.',\n },\n 503,\n ),\n };\n }\n return { mode: 'tenant', storage, orgId: tenantOrgId(tenant), userId: tenant.userId };\n}\n\n/**\n * List the caller's tenant credential records for provider listing, or\n * `undefined` in local mode (caller should fall back to `AuthStorage`).\n * Read-only and degradation-friendly: an authenticated caller with the domain\n * unavailable gets an empty list (sources show `env`/`none`) instead of a 503\n * so the settings page still renders.\n */\nexport async function listTenantCredentialsForRequest({\n c,\n auth,\n credentials,\n}: {\n c: Context;\n auth: RouteAuth;\n /** Tenant credential domain handle; absent in local (no-DB) mode. */\n credentials?: ModelCredentialsStorage;\n}): Promise<CredentialRecord[] | undefined> {\n await auth.ensureUser(c);\n const tenant = auth.tenant(c);\n if (!tenant) return auth.enabled() ? [] : undefined;\n const storage = await getTenantCredentialsStorage(credentials);\n if (!storage) return [];\n return storage.listCredentials(tenantOrgId(tenant), tenant.userId);\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"provider-credentials.js","names":[],"sources":["../../src/routes/provider-credentials.ts"],"sourcesContent":["/**\n * Per-request model-provider credential context.\n *\n * The provider config/OAuth routes serve two deployment shapes:\n *\n * - **Local** (no web auth adapter): credentials live in the server-global\n * file-backed `AuthStorage` (`auth.json`) — unchanged TUI behavior.\n * - **Tenant** (auth adapter active): credentials live in the\n * `model-credentials` factory storage domain, scoped per `(orgId, userId)`\n * with optional org-wide rows (`userId` absent).\n *\n * `resolveCredentialContext` decides which shape a request is in: an\n * authenticated user always gets the tenant path; an unauthenticated request\n * is rejected when auth is enabled and falls back to local otherwise.\n */\n\nimport type { Context } from 'hono';\n\nimport { factoryUserOrgId } from '../auth.js';\nimport type {\n CredentialRecord,\n LoginSessionKind,\n ModelCredentialsStorage,\n} from '../storage/domains/credentials/base.js';\nimport type { RouteAuth } from './route.js';\n\n/**\n * OAuth credentials are stored under the auth provider id, which differs from\n * the catalog provider id for OpenAI (stored as `openai-codex`). Tenant rows\n * use the same keying so one lookup serves both OAuth tokens and API keys.\n */\nexport function getAuthProviderId(provider: string): string {\n return provider === 'openai' ? 'openai-codex' : provider;\n}\n\n/**\n * Providers that support a browser-driven OAuth sign-in flow, keyed by\n * *catalog* provider id (what the routes and settings UI use). All flows need\n * no inbound connection to the server: Anthropic uses paste-code PKCE, the\n * rest use RFC 8628-style device codes.\n */\nexport const WEB_OAUTH_FLOW_KINDS: Readonly<Record<string, LoginSessionKind>> = {\n anthropic: 'paste-code',\n openai: 'device-code',\n 'github-copilot': 'device-code',\n xai: 'device-code',\n};\n\nexport type CredentialContext =\n | { mode: 'local' }\n | { mode: 'tenant'; storage: ModelCredentialsStorage; orgId: string; userId: string };\n\n/**\n * The tenant credentials domain, when registered and ready. `undefined` means\n * the factory never ran (no handle threaded in) or the domain's init failed\n * (fail-soft — callers report the feature unavailable instead of crashing).\n */\nexport async function getTenantCredentialsStorage(\n credentials: ModelCredentialsStorage | undefined,\n): Promise<ModelCredentialsStorage | undefined> {\n if (!credentials) return undefined;\n try {\n await credentials.ensureReady();\n } catch {\n return undefined;\n }\n return credentials;\n}\n\n/**\n * Org key for tenant rows. Personal accounts get an org bootstrapped by the\n * auth adapter (`ensureOrg`); if one still isn't present, scope rows under a\n * per-user synthetic org so credentials never become server-global.\n */\nexport function tenantOrgId(tenant: { orgId?: string; userId: string }): string {\n return tenant.orgId ?? factoryUserOrgId({ id: tenant.userId }) ?? `user:${tenant.userId}`;\n}\n\n/**\n * Resolve the credential context for a request, or a ready-to-return error\n * response. Mutating credential routes call this and hard-fail (401/503)\n * when the tenant path is required but unavailable.\n */\nexport async function resolveCredentialContext({\n c,\n auth,\n credentials,\n}: {\n c: Context;\n auth: RouteAuth;\n /** Tenant credential domain handle; absent in local (no-DB) mode. */\n credentials?: ModelCredentialsStorage;\n}): Promise<CredentialContext | { response: Response }> {\n await auth.ensureUser(c);\n const tenant = auth.tenant(c);\n if (!tenant) {\n // When an auth provider is active, credential operations always require a\n // signed-in caller — otherwise one anonymous request could write keys for\n // everyone. Without a provider this is a single-user local server.\n if (auth.enabled()) return { response: c.json({ error: 'unauthorized' }, 401) };\n return { mode: 'local' };\n }\n const storage = await getTenantCredentialsStorage(credentials);\n if (!storage) {\n return {\n response: c.json(\n {\n error: 'credentials_unavailable',\n message: 'Tenant credential storage is unavailable — the app database is not configured or failed to start.',\n },\n 503,\n ),\n };\n }\n return { mode: 'tenant', storage, orgId: tenantOrgId(tenant), userId: tenant.userId };\n}\n\n/**\n * List the caller's tenant credential records for provider listing, or\n * `undefined` in local mode (caller should fall back to `AuthStorage`).\n * Read-only and degradation-friendly: an authenticated caller with the domain\n * unavailable gets an empty list (sources show `env`/`none`) instead of a 503\n * so the settings page still renders.\n */\nexport async function listTenantCredentialsForRequest({\n c,\n auth,\n credentials,\n}: {\n c: Context;\n auth: RouteAuth;\n /** Tenant credential domain handle; absent in local (no-DB) mode. */\n credentials?: ModelCredentialsStorage;\n}): Promise<CredentialRecord[] | undefined> {\n await auth.ensureUser(c);\n const tenant = auth.tenant(c);\n if (!tenant) return auth.enabled() ? [] : undefined;\n const storage = await getTenantCredentialsStorage(credentials);\n if (!storage) return [];\n return storage.listCredentials(tenantOrgId(tenant), tenant.userId);\n}\n"],"mappings":";;;;;;;AA+BA,SAAgB,kBAAkB,UAA0B;CAC1D,OAAO,aAAa,WAAW,iBAAiB;AAClD;;;;;;;AAQA,MAAa,uBAAmE;CAC9E,WAAW;CACX,QAAQ;CACR,kBAAkB;CAClB,KAAK;AACP;;;;;;AAWA,eAAsB,4BACpB,aAC8C;CAC9C,IAAI,CAAC,aAAa,OAAO,KAAA;CACzB,IAAI;EACF,MAAM,YAAY,YAAY;CAChC,QAAQ;EACN;CACF;CACA,OAAO;AACT;;;;;;AAOA,SAAgB,YAAY,QAAoD;CAC9E,OAAO,OAAO,SAAS,iBAAiB,EAAE,IAAI,OAAO,OAAO,CAAC,KAAK,QAAQ,OAAO;AACnF;;;;;;AAOA,eAAsB,yBAAyB,EAC7C,GACA,MACA,eAMsD;CACtD,MAAM,KAAK,WAAW,CAAC;CACvB,MAAM,SAAS,KAAK,OAAO,CAAC;CAC5B,IAAI,CAAC,QAAQ;EAIX,IAAI,KAAK,QAAQ,GAAG,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,eAAe,GAAG,GAAG,EAAE;EAC9E,OAAO,EAAE,MAAM,QAAQ;CACzB;CACA,MAAM,UAAU,MAAM,4BAA4B,WAAW;CAC7D,IAAI,CAAC,SACH,OAAO,EACL,UAAU,EAAE,KACV;EACE,OAAO;EACP,SAAS;CACX,GACA,GACF,EACF;CAEF,OAAO;EAAE,MAAM;EAAU;EAAS,OAAO,YAAY,MAAM;EAAG,QAAQ,OAAO;CAAO;AACtF;;;;;;;;AASA,eAAsB,gCAAgC,EACpD,GACA,MACA,eAM0C;CAC1C,MAAM,KAAK,WAAW,CAAC;CACvB,MAAM,SAAS,KAAK,OAAO,CAAC;CAC5B,IAAI,CAAC,QAAQ,OAAO,KAAK,QAAQ,IAAI,CAAC,IAAI,KAAA;CAC1C,MAAM,UAAU,MAAM,4BAA4B,WAAW;CAC7D,IAAI,CAAC,SAAS,OAAO,CAAC;CACtB,OAAO,QAAQ,gBAAgB,YAAY,MAAM,GAAG,OAAO,MAAM;AACnE"}
|
package/dist/routes/surface.d.ts
CHANGED
|
@@ -73,6 +73,7 @@ export interface FactoryApiRoutesDeps {
|
|
|
73
73
|
knowledgeEnabled: boolean;
|
|
74
74
|
/** Providers the operator opted in to run on the server process's own credentials. */
|
|
75
75
|
deploymentModelProviders?: ReadonlySet<string>;
|
|
76
|
+
knowledgeKey?: string;
|
|
76
77
|
/** Resolved Factory rule set, threaded from the host (no service locator). */
|
|
77
78
|
configVersion: string;
|
|
78
79
|
/** Boards installed for this Factory instance. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"surface.d.ts","sourceRoot":"","sources":["../../src/routes/surface.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"surface.d.ts","sourceRoot":"","sources":["../../src/routes/surface.ts"],"names":[],"mappings":"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"}
|
package/dist/routes/surface.js
CHANGED
|
@@ -413,7 +413,7 @@ function assembleFactoryApiRoutes(deps) {
|
|
|
413
413
|
orgId: request.orgId,
|
|
414
414
|
factoryProjectId: request.factoryProjectId,
|
|
415
415
|
sessionId: request.sessionId
|
|
416
|
-
}), deps.domains.
|
|
416
|
+
}), deps.domains.intake) : void 0;
|
|
417
417
|
if (transitionService && startCoordinator) deps.onFactoryRuntime?.({
|
|
418
418
|
transitionService,
|
|
419
419
|
...sourceControlRegistrations.length > 0 ? { prepareBinding: async (input) => {
|
|
@@ -454,7 +454,6 @@ function assembleFactoryApiRoutes(deps) {
|
|
|
454
454
|
auth: deps.auth,
|
|
455
455
|
authStorage: deps.authStorage,
|
|
456
456
|
modelCredentials: deps.domains.modelCredentials,
|
|
457
|
-
memorySettings: deps.domains.memorySettings,
|
|
458
457
|
onCredentialsChanged: invalidateTenantCredentialSnapshots
|
|
459
458
|
}).routes(),
|
|
460
459
|
...new SkillRoutes({
|
|
@@ -487,7 +486,11 @@ function assembleFactoryApiRoutes(deps) {
|
|
|
487
486
|
...deps.factoryReady && deps.knowledgeEnabled ? new KnowledgeRoutes({
|
|
488
487
|
auth: deps.auth,
|
|
489
488
|
projects: deps.domains.projects,
|
|
490
|
-
knowledge: async () => deps.
|
|
489
|
+
knowledge: async (key) => deps.controller.getMastra()?.getKnowledge(key),
|
|
490
|
+
defaultKnowledgeKey: deps.knowledgeKey,
|
|
491
|
+
threadTitle: async (threadId) => {
|
|
492
|
+
return (await (await deps.controller.getMastra()?.getStorage()?.getStore("memory"))?.getThreadById({ threadId }))?.title;
|
|
493
|
+
}
|
|
491
494
|
}).routes() : [],
|
|
492
495
|
...deps.factoryReady ? new WorkItemRoutes({
|
|
493
496
|
auth: deps.auth,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"surface.js","names":[],"sources":["../../src/routes/surface.ts"],"sourcesContent":["import type { AuthStorage } from '@mastra/code-sdk/auth/storage';\nimport type { MastraCodeState } from '@mastra/code-sdk/schema';\nimport type { AgentController } from '@mastra/core/agent-controller';\nimport type { ApiRoute, IUserProvider } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\nimport type { FactoryStorage } from '@mastra/core/storage';\n\nimport { boardForWorkItem } from '../boards/index.js';\nimport type { BoardRegistry } from '../boards/index.js';\nimport type { FactoryIntegration, IntegrationContext } from '../integrations/base.js';\nimport { getGithubFeatureDiagnostics } from '../integrations/github/config.js';\nimport type { GithubIntegration } from '../integrations/github/integration.js';\nimport { MaterializeError } from '../integrations/github/sandbox.js';\nimport { FactoryDispatchError } from '../rules/dispatch-errors.js';\nimport type { FactoryBindingPreparationInput } from '../rules/dispatcher.js';\nimport { FactoryStartCoordinator } from '../rules/start-coordinator.js';\nimport { FactoryTransitionService } from '../rules/transition-service.js';\nimport type { MastraFactorySandboxConfig } from '../sandbox/session-sandbox.js';\nimport {\n createSourceControlSessionLookup,\n ensureFactorySourceSession,\n FactorySourceSessionResolutionError,\n resolveFactoryDefaultModelId,\n resolveFactoryProjectForSession,\n resolveFactorySourceControl,\n resolveFactorySourceRepository,\n} from '../session/factory-session.js';\nimport type { EnsuredFactorySourceSession } from '../session/factory-session.js';\nimport type { LiveSessions } from '../session/live-sessions.js';\nimport { resolveWorkItemRepository } from '../session/work-item-repository.js';\nimport type { StateSigner } from '../state-signing.js';\nimport type { AuditEmitter, AuditRecorder } from '../storage/domains/audit/domain.js';\nimport type { ChannelIdentityStorage } from '../storage/domains/channel-identity/base.js';\nimport type { WorkItemCommentsStorage } from '../storage/domains/comments/base.js';\nimport type { CommentsDomain } from '../storage/domains/comments/domain.js';\nimport type { ModelCredentialsStorage } from '../storage/domains/credentials/base.js';\nimport type { CustomProvidersStorage } from '../storage/domains/custom-providers/base.js';\nimport type { FilesystemStorage } from '../storage/domains/filesystem/base.js';\nimport type { IntakeStorage } from '../storage/domains/intake/base.js';\nimport type { IntegrationStorage } from '../storage/domains/integrations/base.js';\nimport type { MemorySettingsStorage } from '../storage/domains/memory-settings/base.js';\nimport type { ModelDefaultsStorage } from '../storage/domains/model-defaults/base.js';\nimport type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';\nimport type { QueueHealthStorage } from '../storage/domains/queue-health/base.js';\nimport {\n SourceControlConnectionNotFoundError,\n type SourceControlStorage,\n type SourceControlStorageHandle,\n} from '../storage/domains/source-control/base.js';\nimport {\n isAgentActor,\n type FactoryDispatchFailureCode,\n type WorkItemsStorage,\n} from '../storage/domains/work-items/base.js';\nimport { workItemBranch, workItemBranchSource, workItemThreadTitle } from '../work-item-branch.js';\nimport { buildAutomationRunRoutes } from './automation-runs.js';\nimport { ConfigRoutes } from './config.js';\nimport { invalidateCustomProvidersSnapshots } from './custom-provider-source.js';\nimport { buildFsRoutes } from './fs.js';\nimport { IntakeRoutes } from './intake.js';\nimport { KnowledgeRoutes } from './knowledge.js';\nimport { OAuthRoutes } from './oauth.js';\nimport type { RouteAuth } from './route.js';\nimport { SkillRoutes } from './skills.js';\nimport { buildSourceControlSessionRoutes } from './source-control-sessions.js';\nimport { buildSourceControlSettingsRoutes } from './source-control-settings.js';\nimport { invalidateTenantCredentialSnapshots } from './tenant-credentials.js';\nimport { WorkItemRoutes } from './work-items.js';\n\nconst MATERIALIZE_FAILURE_CODE = {\n 'git-missing': 'repository_git_missing',\n 'egress-blocked': 'repository_egress_blocked',\n 'clone-failed': 'repository_clone_failed',\n 'pull-failed': 'repository_pull_failed',\n 'push-failed': 'repository_push_failed',\n 'commit-failed': 'repository_commit_failed',\n 'gh-missing': 'repository_cli_missing',\n 'pr-failed': 'repository_pr_failed',\n} satisfies Record<MaterializeError['code'], FactoryDispatchFailureCode>;\nexport interface IntegrationRegistration {\n integration: FactoryIntegration;\n ready: boolean;\n ensureReady: () => Promise<void>;\n}\n\nexport interface FactoryApiRoutesDeps {\n controllerId: string;\n controller: AgentController<MastraCodeState>;\n /** Registry of the sessions this process holds, owned by the host so it can watch them too. */\n liveSessions: LiveSessions;\n /** Request-auth seam threaded from the host (no service locator). */\n auth: RouteAuth;\n /** Optional user directory for resolving persisted owners to display profiles. */\n users?: Pick<IUserProvider, 'getUser' | 'getUsers'>;\n authStorage: AuthStorage;\n audit: AuditEmitter & AuditRecorder;\n fsRoot?: string;\n publicOrigin: string;\n stateSigner?: StateSigner;\n /** Sandbox surface (enablement, provider label, create callback). */\n sandbox?: MastraFactorySandboxConfig;\n /** Root factory storage backend (distributed locks, app-db diagnostics). */\n factoryStorage?: FactoryStorage;\n integrationStorage: IntegrationStorage;\n sourceControlStorage: SourceControlStorage;\n /** App-table domain handles, registered and owned by `MastraFactory.prepare()`. */\n domains: {\n intake: IntakeStorage;\n modelCredentials: ModelCredentialsStorage;\n memorySettings: MemorySettingsStorage;\n customProviders: CustomProvidersStorage;\n filesystem: FilesystemStorage;\n modelDefaults: ModelDefaultsStorage;\n projects: FactoryProjectsStorage;\n queueHealth: QueueHealthStorage;\n workItems: WorkItemsStorage;\n channelIdentity: ChannelIdentityStorage;\n comments: WorkItemCommentsStorage;\n };\n integrations?: IntegrationRegistration[];\n intakeReady: boolean;\n factoryReady: boolean;\n knowledgeEnabled: boolean;\n /** Providers the operator opted in to run on the server process's own credentials. */\n deploymentModelProviders?: ReadonlySet<string>;\n /** Resolved Factory rule set, threaded from the host (no service locator). */\n configVersion: string;\n /** Boards installed for this Factory instance. */\n boardRegistry: BoardRegistry;\n /** Work-item feed service, handed to integrations that ingest platform messages. */\n feed: CommentsDomain;\n factoryTransitionService?: FactoryTransitionService;\n sessionRetirement?: import('../sandbox/session-retirement.js').SessionRetirementCoordinator;\n onFactoryRuntime?: (runtime: {\n transitionService: FactoryTransitionService;\n prepareBinding?: (input: FactoryBindingPreparationInput) => Promise<void>;\n }) => void;\n}\n\nfunction guardIntegrationRoutes({\n integration,\n ready,\n ensureReady,\n routes,\n}: IntegrationRegistration & { routes: ApiRoute[] }): ApiRoute[] {\n if (ready) return routes;\n return routes.map(route => {\n if ('handler' in route) {\n const handler = route.handler;\n return {\n ...route,\n handler: async (context: Parameters<typeof handler>[0]) => {\n try {\n await ensureReady();\n } catch {\n return context.json(\n { error: 'integration_unavailable', message: `${integration.id} integration is unavailable.` },\n 503,\n );\n }\n return handler(context, async () => {});\n },\n };\n }\n\n const createHandler = route.createHandler;\n return {\n ...route,\n createHandler: async (args: Parameters<typeof createHandler>[0]) => {\n const handler = await createHandler(args);\n return async (context: Parameters<typeof handler>[0]) => {\n try {\n await ensureReady();\n } catch {\n return context.json(\n { error: 'integration_unavailable', message: `${integration.id} integration is unavailable.` },\n 503,\n );\n }\n return handler(context);\n };\n },\n };\n });\n}\n\n/**\n * Resolve the source-control session the work item already holds for this role,\n * when it still resolves to the item's org and factory project. Returns\n * `undefined` when there is no ref or the ref no longer resolves, so the caller\n * falls back to minting one.\n */\nasync function reuseBoundSession(\n sourceControl: SourceControlStorageHandle,\n input: FactoryBindingPreparationInput,\n role: string = input.role,\n): Promise<EnsuredFactorySourceSession | undefined> {\n const ref = input.item.sessions[role];\n if (!ref) return undefined;\n // At least as strict as the coordinator's resolveSourceSession: a ref it\n // would reject must fall through to minting, not hard-fail the run.\n const resolved = await resolveFactoryProjectForSession({ sourceControl, sessionId: ref.sessionId });\n if (\n !resolved ||\n resolved.orgId !== input.record.orgId ||\n resolved.factoryProjectId !== input.record.factoryProjectId\n ) {\n return undefined;\n }\n const session = await sourceControl.sessions.getBySessionId(ref.sessionId);\n if (!session) return undefined;\n return {\n sessionId: session.sessionId,\n userId: session.userId,\n projectRepositoryId: session.projectRepositoryId,\n branch: session.branch,\n baseBranch: session.baseBranch,\n };\n}\n\n/** Roles whose sessions a later role may continue in, newest stage first. */\nconst INHERITABLE_ROLE_FALLBACK = ['plan', 'triage'];\n\n/**\n * A role running for the first time continues in the card's latest earlier\n * session on the same branch, so a build approved by someone other than the\n * plan's owner keeps the plan's context instead of starting empty. Review is\n * independent by design and never inherits.\n */\nasync function inheritEarlierSession(\n sourceControl: SourceControlStorageHandle,\n input: FactoryBindingPreparationInput,\n board: { roleForPhase(phase: string): string | undefined } | undefined,\n branch: string,\n repositorySlug: string,\n): Promise<EnsuredFactorySourceSession | undefined> {\n if (input.role === 'review') return undefined;\n // The card's linked repository can change after an earlier role ran; only\n // continue in a session on the repository a fresh session would use.\n const repository = await resolveFactorySourceRepository({\n sourceControl,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n repositorySlug,\n });\n if (!repository.found) return undefined;\n const candidates: string[] = [];\n for (const entry of [...(input.item.stageHistory ?? [])].reverse()) {\n const role = board?.roleForPhase(entry.stage);\n if (role && role !== input.role && role !== 'review' && !candidates.includes(role)) candidates.push(role);\n }\n for (const role of INHERITABLE_ROLE_FALLBACK) {\n if (role !== input.role && !candidates.includes(role)) candidates.push(role);\n }\n for (const role of candidates) {\n const session = await reuseBoundSession(sourceControl, input, role);\n if (session && session.branch === branch && session.projectRepositoryId === repository.projectRepositoryId) {\n return session;\n }\n }\n return undefined;\n}\n\n/**\n * Start a factory run for a rule binding: ensure the source-control session the\n * coordinator requires, then hand it to `prepare` along with the factory's\n * default model. Exported for tests — this is the autonomous entry point with no\n * browser and no interactive user, so nothing else would catch a regression in\n * what it forwards.\n */\nexport async function prepareFactoryRuleBinding(\n sourceControlProvider: SourceControlStorageHandle | Pick<GithubIntegration, 'sourceControlStorage'>,\n coordinator: Pick<FactoryStartCoordinator, 'prepare'>,\n projects: FactoryProjectsStorage,\n boards: BoardRegistry,\n input: FactoryBindingPreparationInput,\n intake?: Pick<IntakeStorage, 'getConfig'>,\n): Promise<void> {\n try {\n const sourceControl =\n 'sourceControlStorage' in sourceControlProvider\n ? sourceControlProvider.sourceControlStorage\n : sourceControlProvider;\n const source = workItemBranchSource(input.item.externalSource);\n const branch = workItemBranch({ id: input.item.id, source, metadata: input.item.metadata });\n // Only leaving a resting phase derives a lane from the role: roles don't own lanes,\n // and the Done close-out running in the triage seat must not drag the card back.\n // Both the current phase and the role's lane come from the installed board; an\n // unknown board or phase yields no destination rather than a guessed one.\n const board = boards.get(boardForWorkItem(input.item));\n const currentStage = input.item.stages.length === 1 ? input.item.stages[0] : undefined;\n const currentKind = currentStage === undefined ? undefined : board?.phaseKind(currentStage);\n const destinationStage =\n currentKind === undefined\n ? undefined\n : currentKind === 'resting'\n ? board?.phaseForRole(input.role)\n : currentStage;\n if (!destinationStage) {\n throw new FactoryDispatchError(\n 'unsupported_provider_item',\n `Factory skill invocation has no destination lane (role \"${input.role}\", stages [${input.item.stages.join(', ')}]).`,\n );\n }\n const connections = await sourceControl.connections.list({\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n });\n if (!connections.some(connection => connection.integrationId === sourceControl.integrationId)) {\n throw new FactoryDispatchError('source_control_missing', 'Factory source-control connection not found.');\n }\n // A retry may already own a role session. Check it before treating a\n // repository-less card as ambiguous, but never override an explicit signal.\n const boundSession = await reuseBoundSession(sourceControl, input);\n const intakeConfig = await intake?.getConfig({ orgId: input.record.orgId, integrationIds: ['linear'] });\n let repository = await resolveWorkItemRepository({\n sourceControl,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n item: input.item,\n linearRepositoryMap: intakeConfig?.linear?.repositoryByLinearProject,\n });\n if (repository.status === 'ambiguous' && boundSession) {\n const link = await sourceControl.projectRepositories.get({\n orgId: input.record.orgId,\n id: boundSession.projectRepositoryId,\n });\n const linked =\n link && (await sourceControl.repositories.get({ orgId: input.record.orgId, id: link.repositoryId }));\n if (linked && repository.candidates.includes(linked.slug)) {\n const match = await resolveFactorySourceRepository({\n sourceControl,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n repositorySlug: linked.slug,\n });\n if (match.found && match.projectRepositoryId === boundSession.projectRepositoryId) {\n repository = { status: 'resolved', slug: linked.slug, projectRepositoryId: match.projectRepositoryId };\n }\n }\n }\n if (repository.status !== 'resolved') {\n const detail =\n repository.status === 'ambiguous'\n ? `Choose one of the linked repositories: ${repository.candidates.join(', ')}.`\n : repository.hint;\n throw new FactoryDispatchError('source_repository_ambiguous', detail);\n }\n // Re-preparing a binding (server restart, retired controller session) must\n // land in the role's existing session: minting a replacement would repoint\n // the work item, flip the session's owner to the approver, and orphan the\n // previous sandbox.\n const approver = input.record.approvedBy ?? undefined;\n if (boundSession && boundSession.projectRepositoryId !== repository.projectRepositoryId) {\n throw new FactoryDispatchError(\n 'source_repository_ambiguous',\n `The existing session is bound to a different repository than ${repository.slug}. Choose the correct repository and retry.`,\n );\n }\n const preparedSession =\n boundSession ??\n (await inheritEarlierSession(sourceControl, input, board, branch, repository.slug)) ??\n (await ensureFactorySourceSession({\n sourceControl,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n repositorySlug: repository.slug,\n branch,\n // A person who approved the run is its interactive user: attribute it to\n // them, not the repo connector. An agent's pre-approval names no person.\n attributeToUserId: isAgentActor(approver) ? undefined : approver,\n }));\n\n await coordinator.prepare({\n orgId: input.record.orgId,\n userId: preparedSession.userId,\n factoryProjectId: input.record.factoryProjectId,\n sessionId: preparedSession.sessionId,\n defaultModelId: await resolveFactoryDefaultModelId(projects, input.record.factoryProjectId),\n threadTitle: workItemThreadTitle({ source, title: input.item.title, metadata: input.item.metadata }),\n kickoffKey: input.record.id,\n destinationStage,\n workItem: {\n id: input.item.id,\n role: input.role,\n input: {\n externalSource: input.item.externalSource,\n parentWorkItemId: input.item.parentWorkItemId,\n title: input.item.title,\n stages: ['intake'],\n sessions: input.item.sessions,\n metadata: input.item.metadata,\n },\n },\n });\n } catch (error) {\n if (error instanceof FactoryDispatchError) throw error;\n if (error instanceof FactorySourceSessionResolutionError) {\n const code = error.reason === 'connection' ? 'source_control_missing' : 'source_repository_missing';\n throw new FactoryDispatchError(code, error.message, { cause: error });\n }\n if (error instanceof SourceControlConnectionNotFoundError) {\n throw new FactoryDispatchError('source_control_missing', error.message, { cause: error });\n }\n if (error instanceof MaterializeError) {\n throw new FactoryDispatchError(MATERIALIZE_FAILURE_CODE[error.code], error.message, { cause: error });\n }\n throw error;\n }\n}\n\n/**\n * Build the {@link IntegrationContext} handed to an integration when the\n * factory collects its capabilities (routes, workers). One shape everywhere:\n * `assembleFactoryApiRoutes` uses it per registration, and `MastraFactory` uses it\n * when collecting integration workers at finalize.\n */\nexport function buildIntegrationContext(\n deps: Pick<\n FactoryApiRoutesDeps,\n | 'controller'\n | 'publicOrigin'\n | 'auth'\n | 'sandbox'\n | 'users'\n | 'factoryStorage'\n | 'integrationStorage'\n | 'sourceControlStorage'\n | 'integrations'\n > & {\n stateSigner: StateSigner;\n emitAudit?: AuditEmitter['emit'];\n configVersion: string;\n boardRegistry: BoardRegistry;\n factoryReady: boolean;\n /** Work-item feed service, so a channel integration can ingest platform messages. */\n feed: CommentsDomain;\n domains: Pick<\n FactoryApiRoutesDeps['domains'],\n 'projects' | 'intake' | 'workItems' | 'channelIdentity' | 'memorySettings' | 'modelDefaults'\n >;\n /**\n * Stable id of the registered source-control-owning integration (today:\n * `'github'` when registered). Every call site must derive and pass it so\n * `routes()`, `channels()`, and `workers()` all see the same context shape.\n */\n sourceControlOwnerId?: string;\n },\n integrationId: string,\n): IntegrationContext {\n return {\n auth: deps.auth,\n sandbox: deps.sandbox,\n ...(deps.users ? { users: deps.users } : {}),\n factoryStorage: deps.factoryStorage,\n baseUrl: deps.publicOrigin,\n controller: deps.controller,\n stateSigner: deps.stateSigner,\n storage: {\n generic: deps.integrationStorage.forIntegration(integrationId),\n sourceControl: deps.sourceControlStorage.forIntegration(integrationId),\n ...(deps.sourceControlOwnerId\n ? { sourceControlOwner: deps.sourceControlStorage.forIntegration(deps.sourceControlOwnerId) }\n : {}),\n sourceControls: (deps.integrations ?? [])\n .filter(({ integration }) => integration.versionControl)\n .map(({ integration }) => deps.sourceControlStorage.forIntegration(integration.id)),\n projects: deps.domains.projects,\n intake: deps.domains.intake,\n channelIdentity: deps.domains.channelIdentity,\n memorySettings: deps.domains.memorySettings,\n modelDefaults: deps.domains.modelDefaults,\n },\n ...(deps.factoryReady ? { workItems: deps.domains.workItems, feed: deps.feed } : {}),\n ...(deps.factoryReady\n ? {\n runtime: { configVersion: deps.configVersion, workItems: deps.domains.workItems, boards: deps.boardRegistry },\n }\n : {}),\n ...(deps.emitAudit ? { hooks: { emitAudit: deps.emitAudit } } : {}),\n };\n}\n\n/**\n * Disabled-status stub for the well-known integration ids. The SPA polls\n * `/web/github/status`, `/web/linear/status`, and `/web/jira/status`\n * unconditionally, so when an integration is absent (or not ready) the status\n * contract must still hold. Unknown custom ids get no stub — the SPA doesn't\n * poll them.\n */\nfunction disabledIntegrationStatusRoutes(deps: FactoryApiRoutesDeps, id: string, configured = false): ApiRoute[] {\n if (id === 'github') {\n return [\n registerApiRoute('/web/github/status', {\n method: 'GET',\n requiresAuth: false,\n handler: c =>\n c.json({\n enabled: false,\n connected: false,\n installations: [],\n reason: 'missing_config',\n diagnostics: getGithubFeatureDiagnostics({\n github: undefined,\n auth: deps.auth,\n appDbConfigured: deps.factoryStorage !== undefined,\n stateSigner: deps.stateSigner,\n sandbox: deps.sandbox,\n }),\n }),\n }),\n ];\n }\n if (id === 'linear') {\n return [\n registerApiRoute('/web/linear/status', {\n method: 'GET',\n requiresAuth: false,\n handler: c =>\n c.json({\n enabled: false,\n connected: false,\n workspace: null,\n reason: 'missing_config',\n diagnostics: {\n linearAppConfigured: configured,\n factoryAuthEnabled: deps.auth.enabled(),\n appDbConfigured: true,\n },\n }),\n }),\n ];\n }\n if (id === 'jira') {\n return [\n registerApiRoute('/web/jira/status', {\n method: 'GET',\n requiresAuth: false,\n handler: c =>\n c.json({\n enabled: false,\n configured,\n site: null,\n reason: 'missing_config',\n diagnostics: {\n jiraConfigured: configured,\n factoryAuthEnabled: deps.auth.enabled(),\n appDbConfigured: deps.factoryStorage !== undefined,\n },\n }),\n }),\n ];\n }\n return [];\n}\n\n/**\n * Stub for `GET /web/channel-accounts` when NO Slack integration is\n * registered. The SPA's Connections section polls the path unconditionally;\n * without a stub the SPA fallback serves HTML, which the UI can only read as\n * \"old server / unknown\". The machine-readable reason lets it say the truth:\n * the integration isn't registered.\n *\n * Mounted only for ABSENT slack — a registered integration owns the path via\n * its connect routes (or, when the state signer is unstable, gets no routes\n * at all and the UI falls back to the generic copy). Static payload, leaks\n * nothing → no auth needed, same posture as the github/linear stubs.\n */\nfunction absentSlackChannelAccountsRoutes(): ApiRoute[] {\n return [\n registerApiRoute('/web/channel-accounts', {\n method: 'GET',\n requiresAuth: false,\n handler: c => c.json({ accounts: [], canConnect: false, reason: 'not_registered' }),\n }),\n ];\n}\n\n/**\n * Assemble the custom `/web/*` API routes as Mastra `server.apiRoutes`:\n * - fs browser routes (project picker), confined to `fsRoot`\n * - config routes (provider/API-key/default-model/OM management)\n * - every registered integration's `routes()` surface (full set when ready,\n * disabled-status stub otherwise), plus stubs for absent known ids\n */\nexport function assembleFactoryApiRoutes(deps: FactoryApiRoutesDeps): ApiRoute[] {\n const emitAudit: AuditEmitter['emit'] = args => deps.audit.emit(args);\n const registrations = deps.integrations ?? [];\n const githubRegistration = registrations.find(({ integration }) => integration.id === 'github');\n const githubStorage = githubRegistration ? deps.sourceControlStorage.forIntegration('github') : undefined;\n const githubIntegration = githubRegistration?.integration as GithubIntegration | undefined;\n const sourceControlRegistrations = registrations.filter(({ integration }) => integration.versionControl);\n const sourceControlIntegrationIds = [\n ...new Set(['github', ...sourceControlRegistrations.map(({ integration }) => integration.id)]),\n ];\n const sourceControls = sourceControlIntegrationIds.map(id => deps.sourceControlStorage.forIntegration(id));\n const sourceControlSessions = createSourceControlSessionLookup(sourceControls);\n\n const integrationRoutes = registrations.flatMap(registration => {\n const { integration } = registration;\n if (!deps.stateSigner) return disabledIntegrationStatusRoutes(deps, integration.id, true);\n const context = buildIntegrationContext(\n {\n ...deps,\n stateSigner: deps.stateSigner,\n emitAudit,\n ...(githubRegistration ? { sourceControlOwnerId: 'github' } : {}),\n },\n integration.id,\n );\n return guardIntegrationRoutes({ ...registration, routes: integration.routes(context) });\n });\n // Session persistence belongs to the linked source-control provider, not to\n // GitHub. Replace legacy GitHub-owned handlers with one resolver spanning\n // the legacy GitHub partition and every registered source-control partition.\n const sharedSessionRouteKeys = new Set([\n 'GET /web/github/projects/:id/sessions',\n 'POST /web/github/projects/:id/sessions',\n 'GET /web/user-sessions/:sessionId',\n 'DELETE /web/user-sessions/:sessionId',\n 'POST /web/user-sessions/:sessionId/title',\n ]);\n const providerRoutes = integrationRoutes.filter(\n route => !sharedSessionRouteKeys.has(route.method + ' ' + route.path),\n );\n const sourceControlSessionRoutes =\n sourceControls.length === 0\n ? []\n : buildSourceControlSessionRoutes({\n auth: deps.auth,\n sourceControls,\n ...(deps.users ? { users: deps.users } : {}),\n controller: deps.controller,\n memorySettings: deps.domains.memorySettings,\n sessionRetirement: deps.sessionRetirement,\n ...(deps.factoryReady ? { workItems: deps.domains.workItems } : {}),\n });\n // Absent known integrations still get their disabled-status stub.\n const absentStubs = ['github', 'linear', 'jira']\n .filter(id => !registrations.some(({ integration }) => integration.id === id))\n .flatMap(id => disabledIntegrationStatusRoutes(deps, id));\n // Absent slack gets the channel-accounts not-registered stub (registered\n // slack owns the path via its own connect routes).\n const slackAbsentStubs = registrations.some(({ integration }) => integration.id === 'slack')\n ? []\n : absentSlackChannelAccountsRoutes();\n\n const transitionService = deps.factoryReady\n ? (deps.factoryTransitionService ??\n new FactoryTransitionService({\n configVersion: deps.configVersion,\n boards: deps.boardRegistry,\n storage: deps.domains.workItems,\n audit: deps.audit,\n }))\n : undefined;\n const startCoordinator = transitionService\n ? new FactoryStartCoordinator(\n deps.controller,\n deps.domains.workItems,\n transitionService,\n request =>\n resolveFactorySourceControl({\n sourceControls,\n orgId: request.orgId,\n factoryProjectId: request.factoryProjectId,\n sessionId: request.sessionId,\n }),\n deps.domains.memorySettings,\n deps.domains.intake,\n )\n : undefined;\n if (transitionService && startCoordinator) {\n deps.onFactoryRuntime?.({\n transitionService,\n ...(sourceControlRegistrations.length > 0\n ? {\n prepareBinding: async (input: FactoryBindingPreparationInput) => {\n const sourceControl = await resolveFactorySourceControl({\n sourceControls,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n });\n if (!sourceControl) {\n throw new FactoryDispatchError(\n 'source_control_missing',\n 'Factory project has no linked source-control repository.',\n );\n }\n return prepareFactoryRuleBinding(\n sourceControl,\n startCoordinator,\n deps.domains.projects,\n deps.boardRegistry,\n input,\n deps.domains.intake,\n );\n },\n }\n : {}),\n });\n }\n\n return [\n ...buildFsRoutes({\n root: deps.fsRoot,\n sessionFs: {\n auth: deps.auth,\n sessions: sourceControlSessions,\n filesystem: deps.domains.filesystem,\n },\n }),\n ...new ConfigRoutes({\n auth: deps.auth,\n controller: deps.controller,\n authStorage: deps.authStorage,\n modelCredentials: deps.domains.modelCredentials,\n modelDefaults: deps.domains.modelDefaults,\n sourceControlSessions,\n memorySettings: deps.domains.memorySettings,\n factoryProjects: deps.domains.projects,\n customProviders: deps.domains.customProviders,\n features: { knowledge: deps.knowledgeEnabled },\n deploymentProviders: deps.deploymentModelProviders,\n onCredentialsChanged: invalidateTenantCredentialSnapshots,\n onCustomProvidersChanged: invalidateCustomProvidersSnapshots,\n }).routes(),\n ...new OAuthRoutes({\n auth: deps.auth,\n authStorage: deps.authStorage,\n modelCredentials: deps.domains.modelCredentials,\n memorySettings: deps.domains.memorySettings,\n onCredentialsChanged: invalidateTenantCredentialSnapshots,\n }).routes(),\n ...new SkillRoutes({\n auth: deps.auth,\n controllerId: deps.controllerId,\n controller: deps.controller,\n sourceControlStorage: githubStorage,\n ensureSourceControlReady: githubRegistration?.ensureReady,\n }).routes(),\n ...sourceControlSessionRoutes,\n ...(sourceControls.length === 0 ? [] : buildSourceControlSettingsRoutes({ auth: deps.auth, sourceControls })),\n ...providerRoutes,\n ...absentStubs,\n ...slackAbsentStubs,\n ...(deps.intakeReady\n ? new IntakeRoutes({\n auth: deps.auth,\n audit: deps.audit,\n intake: deps.domains.intake,\n projects: deps.domains.projects,\n boardRegistry: deps.boardRegistry,\n // Relocation reads and writes work items, which init fail-soft separately from intake.\n ...(deps.factoryReady ? { workItems: deps.domains.workItems } : {}),\n integrations: (deps.integrations ?? []).flatMap(({ integration }) =>\n integration.intake ? [{ id: integration.id, intake: integration.intake }] : [],\n ),\n }).routes()\n : []),\n ...(deps.factoryReady && deps.knowledgeEnabled\n ? new KnowledgeRoutes({\n auth: deps.auth,\n projects: deps.domains.projects,\n knowledge: async () => deps.factoryStorage?.getMastraStorage().getStore('knowledge'),\n }).routes()\n : []),\n ...(deps.factoryReady\n ? new WorkItemRoutes({\n auth: deps.auth,\n audit: deps.audit,\n projects: deps.domains.projects,\n workItems: deps.domains.workItems,\n boardRegistry: deps.boardRegistry,\n comments: deps.domains.comments,\n queueHealth: deps.domains.queueHealth,\n transitionService,\n startCoordinator,\n liveSessions: deps.liveSessions,\n }).routes()\n : []),\n ...(deps.factoryReady\n ? buildAutomationRunRoutes({\n auth: deps.auth,\n audit: deps.audit,\n projects: deps.domains.projects,\n workItems: deps.domains.workItems,\n configVersion: deps.configVersion,\n })\n : []),\n ];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"surface.js","names":[],"sources":["../../src/routes/surface.ts"],"sourcesContent":["import type { AuthStorage } from '@mastra/code-sdk/auth/storage';\nimport type { MastraCodeState } from '@mastra/code-sdk/schema';\nimport type { AgentController } from '@mastra/core/agent-controller';\nimport type { ApiRoute, IUserProvider } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\nimport type { FactoryStorage } from '@mastra/core/storage';\n\nimport { boardForWorkItem } from '../boards/index.js';\nimport type { BoardRegistry } from '../boards/index.js';\nimport type { FactoryIntegration, IntegrationContext } from '../integrations/base.js';\nimport { getGithubFeatureDiagnostics } from '../integrations/github/config.js';\nimport type { GithubIntegration } from '../integrations/github/integration.js';\nimport { MaterializeError } from '../integrations/github/sandbox.js';\nimport { FactoryDispatchError } from '../rules/dispatch-errors.js';\nimport type { FactoryBindingPreparationInput } from '../rules/dispatcher.js';\nimport { FactoryStartCoordinator } from '../rules/start-coordinator.js';\nimport { FactoryTransitionService } from '../rules/transition-service.js';\nimport type { MastraFactorySandboxConfig } from '../sandbox/session-sandbox.js';\nimport {\n createSourceControlSessionLookup,\n ensureFactorySourceSession,\n FactorySourceSessionResolutionError,\n resolveFactoryDefaultModelId,\n resolveFactoryProjectForSession,\n resolveFactorySourceControl,\n resolveFactorySourceRepository,\n} from '../session/factory-session.js';\nimport type { EnsuredFactorySourceSession } from '../session/factory-session.js';\nimport type { LiveSessions } from '../session/live-sessions.js';\nimport { resolveWorkItemRepository } from '../session/work-item-repository.js';\nimport type { StateSigner } from '../state-signing.js';\nimport type { AuditEmitter, AuditRecorder } from '../storage/domains/audit/domain.js';\nimport type { ChannelIdentityStorage } from '../storage/domains/channel-identity/base.js';\nimport type { WorkItemCommentsStorage } from '../storage/domains/comments/base.js';\nimport type { CommentsDomain } from '../storage/domains/comments/domain.js';\nimport type { ModelCredentialsStorage } from '../storage/domains/credentials/base.js';\nimport type { CustomProvidersStorage } from '../storage/domains/custom-providers/base.js';\nimport type { FilesystemStorage } from '../storage/domains/filesystem/base.js';\nimport type { IntakeStorage } from '../storage/domains/intake/base.js';\nimport type { IntegrationStorage } from '../storage/domains/integrations/base.js';\nimport type { MemorySettingsStorage } from '../storage/domains/memory-settings/base.js';\nimport type { ModelDefaultsStorage } from '../storage/domains/model-defaults/base.js';\nimport type { FactoryProjectsStorage } from '../storage/domains/projects/base.js';\nimport type { QueueHealthStorage } from '../storage/domains/queue-health/base.js';\nimport {\n SourceControlConnectionNotFoundError,\n type SourceControlStorage,\n type SourceControlStorageHandle,\n} from '../storage/domains/source-control/base.js';\nimport {\n isAgentActor,\n type FactoryDispatchFailureCode,\n type WorkItemsStorage,\n} from '../storage/domains/work-items/base.js';\nimport { workItemBranch, workItemBranchSource, workItemThreadTitle } from '../work-item-branch.js';\nimport { buildAutomationRunRoutes } from './automation-runs.js';\nimport { ConfigRoutes } from './config.js';\nimport { invalidateCustomProvidersSnapshots } from './custom-provider-source.js';\nimport { buildFsRoutes } from './fs.js';\nimport { IntakeRoutes } from './intake.js';\nimport { KnowledgeRoutes } from './knowledge.js';\nimport { OAuthRoutes } from './oauth.js';\nimport type { RouteAuth } from './route.js';\nimport { SkillRoutes } from './skills.js';\nimport { buildSourceControlSessionRoutes } from './source-control-sessions.js';\nimport { buildSourceControlSettingsRoutes } from './source-control-settings.js';\nimport { invalidateTenantCredentialSnapshots } from './tenant-credentials.js';\nimport { WorkItemRoutes } from './work-items.js';\n\nconst MATERIALIZE_FAILURE_CODE = {\n 'git-missing': 'repository_git_missing',\n 'egress-blocked': 'repository_egress_blocked',\n 'clone-failed': 'repository_clone_failed',\n 'pull-failed': 'repository_pull_failed',\n 'push-failed': 'repository_push_failed',\n 'commit-failed': 'repository_commit_failed',\n 'gh-missing': 'repository_cli_missing',\n 'pr-failed': 'repository_pr_failed',\n} satisfies Record<MaterializeError['code'], FactoryDispatchFailureCode>;\nexport interface IntegrationRegistration {\n integration: FactoryIntegration;\n ready: boolean;\n ensureReady: () => Promise<void>;\n}\n\nexport interface FactoryApiRoutesDeps {\n controllerId: string;\n controller: AgentController<MastraCodeState>;\n /** Registry of the sessions this process holds, owned by the host so it can watch them too. */\n liveSessions: LiveSessions;\n /** Request-auth seam threaded from the host (no service locator). */\n auth: RouteAuth;\n /** Optional user directory for resolving persisted owners to display profiles. */\n users?: Pick<IUserProvider, 'getUser' | 'getUsers'>;\n authStorage: AuthStorage;\n audit: AuditEmitter & AuditRecorder;\n fsRoot?: string;\n publicOrigin: string;\n stateSigner?: StateSigner;\n /** Sandbox surface (enablement, provider label, create callback). */\n sandbox?: MastraFactorySandboxConfig;\n /** Root factory storage backend (distributed locks, app-db diagnostics). */\n factoryStorage?: FactoryStorage;\n integrationStorage: IntegrationStorage;\n sourceControlStorage: SourceControlStorage;\n /** App-table domain handles, registered and owned by `MastraFactory.prepare()`. */\n domains: {\n intake: IntakeStorage;\n modelCredentials: ModelCredentialsStorage;\n memorySettings: MemorySettingsStorage;\n customProviders: CustomProvidersStorage;\n filesystem: FilesystemStorage;\n modelDefaults: ModelDefaultsStorage;\n projects: FactoryProjectsStorage;\n queueHealth: QueueHealthStorage;\n workItems: WorkItemsStorage;\n channelIdentity: ChannelIdentityStorage;\n comments: WorkItemCommentsStorage;\n };\n integrations?: IntegrationRegistration[];\n intakeReady: boolean;\n factoryReady: boolean;\n knowledgeEnabled: boolean;\n /** Providers the operator opted in to run on the server process's own credentials. */\n deploymentModelProviders?: ReadonlySet<string>;\n knowledgeKey?: string;\n /** Resolved Factory rule set, threaded from the host (no service locator). */\n configVersion: string;\n /** Boards installed for this Factory instance. */\n boardRegistry: BoardRegistry;\n /** Work-item feed service, handed to integrations that ingest platform messages. */\n feed: CommentsDomain;\n factoryTransitionService?: FactoryTransitionService;\n sessionRetirement?: import('../sandbox/session-retirement.js').SessionRetirementCoordinator;\n onFactoryRuntime?: (runtime: {\n transitionService: FactoryTransitionService;\n prepareBinding?: (input: FactoryBindingPreparationInput) => Promise<void>;\n }) => void;\n}\n\nfunction guardIntegrationRoutes({\n integration,\n ready,\n ensureReady,\n routes,\n}: IntegrationRegistration & { routes: ApiRoute[] }): ApiRoute[] {\n if (ready) return routes;\n return routes.map(route => {\n if ('handler' in route) {\n const handler = route.handler;\n return {\n ...route,\n handler: async (context: Parameters<typeof handler>[0]) => {\n try {\n await ensureReady();\n } catch {\n return context.json(\n { error: 'integration_unavailable', message: `${integration.id} integration is unavailable.` },\n 503,\n );\n }\n return handler(context, async () => {});\n },\n };\n }\n\n const createHandler = route.createHandler;\n return {\n ...route,\n createHandler: async (args: Parameters<typeof createHandler>[0]) => {\n const handler = await createHandler(args);\n return async (context: Parameters<typeof handler>[0]) => {\n try {\n await ensureReady();\n } catch {\n return context.json(\n { error: 'integration_unavailable', message: `${integration.id} integration is unavailable.` },\n 503,\n );\n }\n return handler(context);\n };\n },\n };\n });\n}\n\n/**\n * Resolve the source-control session the work item already holds for this role,\n * when it still resolves to the item's org and factory project. Returns\n * `undefined` when there is no ref or the ref no longer resolves, so the caller\n * falls back to minting one.\n */\nasync function reuseBoundSession(\n sourceControl: SourceControlStorageHandle,\n input: FactoryBindingPreparationInput,\n role: string = input.role,\n): Promise<EnsuredFactorySourceSession | undefined> {\n const ref = input.item.sessions[role];\n if (!ref) return undefined;\n // At least as strict as the coordinator's resolveSourceSession: a ref it\n // would reject must fall through to minting, not hard-fail the run.\n const resolved = await resolveFactoryProjectForSession({ sourceControl, sessionId: ref.sessionId });\n if (\n !resolved ||\n resolved.orgId !== input.record.orgId ||\n resolved.factoryProjectId !== input.record.factoryProjectId\n ) {\n return undefined;\n }\n const session = await sourceControl.sessions.getBySessionId(ref.sessionId);\n if (!session) return undefined;\n return {\n sessionId: session.sessionId,\n userId: session.userId,\n projectRepositoryId: session.projectRepositoryId,\n branch: session.branch,\n baseBranch: session.baseBranch,\n };\n}\n\n/** Roles whose sessions a later role may continue in, newest stage first. */\nconst INHERITABLE_ROLE_FALLBACK = ['plan', 'triage'];\n\n/**\n * A role running for the first time continues in the card's latest earlier\n * session on the same branch, so a build approved by someone other than the\n * plan's owner keeps the plan's context instead of starting empty. Review is\n * independent by design and never inherits.\n */\nasync function inheritEarlierSession(\n sourceControl: SourceControlStorageHandle,\n input: FactoryBindingPreparationInput,\n board: { roleForPhase(phase: string): string | undefined } | undefined,\n branch: string,\n repositorySlug: string,\n): Promise<EnsuredFactorySourceSession | undefined> {\n if (input.role === 'review') return undefined;\n // The card's linked repository can change after an earlier role ran; only\n // continue in a session on the repository a fresh session would use.\n const repository = await resolveFactorySourceRepository({\n sourceControl,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n repositorySlug,\n });\n if (!repository.found) return undefined;\n const candidates: string[] = [];\n for (const entry of [...(input.item.stageHistory ?? [])].reverse()) {\n const role = board?.roleForPhase(entry.stage);\n if (role && role !== input.role && role !== 'review' && !candidates.includes(role)) candidates.push(role);\n }\n for (const role of INHERITABLE_ROLE_FALLBACK) {\n if (role !== input.role && !candidates.includes(role)) candidates.push(role);\n }\n for (const role of candidates) {\n const session = await reuseBoundSession(sourceControl, input, role);\n if (session && session.branch === branch && session.projectRepositoryId === repository.projectRepositoryId) {\n return session;\n }\n }\n return undefined;\n}\n\n/**\n * Start a factory run for a rule binding: ensure the source-control session the\n * coordinator requires, then hand it to `prepare` along with the factory's\n * default model. Exported for tests — this is the autonomous entry point with no\n * browser and no interactive user, so nothing else would catch a regression in\n * what it forwards.\n */\nexport async function prepareFactoryRuleBinding(\n sourceControlProvider: SourceControlStorageHandle | Pick<GithubIntegration, 'sourceControlStorage'>,\n coordinator: Pick<FactoryStartCoordinator, 'prepare'>,\n projects: FactoryProjectsStorage,\n boards: BoardRegistry,\n input: FactoryBindingPreparationInput,\n intake?: Pick<IntakeStorage, 'getConfig'>,\n): Promise<void> {\n try {\n const sourceControl =\n 'sourceControlStorage' in sourceControlProvider\n ? sourceControlProvider.sourceControlStorage\n : sourceControlProvider;\n const source = workItemBranchSource(input.item.externalSource);\n const branch = workItemBranch({ id: input.item.id, source, metadata: input.item.metadata });\n // Only leaving a resting phase derives a lane from the role: roles don't own lanes,\n // and the Done close-out running in the triage seat must not drag the card back.\n // Both the current phase and the role's lane come from the installed board; an\n // unknown board or phase yields no destination rather than a guessed one.\n const board = boards.get(boardForWorkItem(input.item));\n const currentStage = input.item.stages.length === 1 ? input.item.stages[0] : undefined;\n const currentKind = currentStage === undefined ? undefined : board?.phaseKind(currentStage);\n const destinationStage =\n currentKind === undefined\n ? undefined\n : currentKind === 'resting'\n ? board?.phaseForRole(input.role)\n : currentStage;\n if (!destinationStage) {\n throw new FactoryDispatchError(\n 'unsupported_provider_item',\n `Factory skill invocation has no destination lane (role \"${input.role}\", stages [${input.item.stages.join(', ')}]).`,\n );\n }\n const connections = await sourceControl.connections.list({\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n });\n if (!connections.some(connection => connection.integrationId === sourceControl.integrationId)) {\n throw new FactoryDispatchError('source_control_missing', 'Factory source-control connection not found.');\n }\n // A retry may already own a role session. Check it before treating a\n // repository-less card as ambiguous, but never override an explicit signal.\n const boundSession = await reuseBoundSession(sourceControl, input);\n const intakeConfig = await intake?.getConfig({ orgId: input.record.orgId, integrationIds: ['linear'] });\n let repository = await resolveWorkItemRepository({\n sourceControl,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n item: input.item,\n linearRepositoryMap: intakeConfig?.linear?.repositoryByLinearProject,\n });\n if (repository.status === 'ambiguous' && boundSession) {\n const link = await sourceControl.projectRepositories.get({\n orgId: input.record.orgId,\n id: boundSession.projectRepositoryId,\n });\n const linked =\n link && (await sourceControl.repositories.get({ orgId: input.record.orgId, id: link.repositoryId }));\n if (linked && repository.candidates.includes(linked.slug)) {\n const match = await resolveFactorySourceRepository({\n sourceControl,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n repositorySlug: linked.slug,\n });\n if (match.found && match.projectRepositoryId === boundSession.projectRepositoryId) {\n repository = { status: 'resolved', slug: linked.slug, projectRepositoryId: match.projectRepositoryId };\n }\n }\n }\n if (repository.status !== 'resolved') {\n const detail =\n repository.status === 'ambiguous'\n ? `Choose one of the linked repositories: ${repository.candidates.join(', ')}.`\n : repository.hint;\n throw new FactoryDispatchError('source_repository_ambiguous', detail);\n }\n // Re-preparing a binding (server restart, retired controller session) must\n // land in the role's existing session: minting a replacement would repoint\n // the work item, flip the session's owner to the approver, and orphan the\n // previous sandbox.\n const approver = input.record.approvedBy ?? undefined;\n if (boundSession && boundSession.projectRepositoryId !== repository.projectRepositoryId) {\n throw new FactoryDispatchError(\n 'source_repository_ambiguous',\n `The existing session is bound to a different repository than ${repository.slug}. Choose the correct repository and retry.`,\n );\n }\n const preparedSession =\n boundSession ??\n (await inheritEarlierSession(sourceControl, input, board, branch, repository.slug)) ??\n (await ensureFactorySourceSession({\n sourceControl,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n repositorySlug: repository.slug,\n branch,\n // A person who approved the run is its interactive user: attribute it to\n // them, not the repo connector. An agent's pre-approval names no person.\n attributeToUserId: isAgentActor(approver) ? undefined : approver,\n }));\n\n await coordinator.prepare({\n orgId: input.record.orgId,\n userId: preparedSession.userId,\n factoryProjectId: input.record.factoryProjectId,\n sessionId: preparedSession.sessionId,\n defaultModelId: await resolveFactoryDefaultModelId(projects, input.record.factoryProjectId),\n threadTitle: workItemThreadTitle({ source, title: input.item.title, metadata: input.item.metadata }),\n kickoffKey: input.record.id,\n destinationStage,\n workItem: {\n id: input.item.id,\n role: input.role,\n input: {\n externalSource: input.item.externalSource,\n parentWorkItemId: input.item.parentWorkItemId,\n title: input.item.title,\n stages: ['intake'],\n sessions: input.item.sessions,\n metadata: input.item.metadata,\n },\n },\n });\n } catch (error) {\n if (error instanceof FactoryDispatchError) throw error;\n if (error instanceof FactorySourceSessionResolutionError) {\n const code = error.reason === 'connection' ? 'source_control_missing' : 'source_repository_missing';\n throw new FactoryDispatchError(code, error.message, { cause: error });\n }\n if (error instanceof SourceControlConnectionNotFoundError) {\n throw new FactoryDispatchError('source_control_missing', error.message, { cause: error });\n }\n if (error instanceof MaterializeError) {\n throw new FactoryDispatchError(MATERIALIZE_FAILURE_CODE[error.code], error.message, { cause: error });\n }\n throw error;\n }\n}\n\n/**\n * Build the {@link IntegrationContext} handed to an integration when the\n * factory collects its capabilities (routes, workers). One shape everywhere:\n * `assembleFactoryApiRoutes` uses it per registration, and `MastraFactory` uses it\n * when collecting integration workers at finalize.\n */\nexport function buildIntegrationContext(\n deps: Pick<\n FactoryApiRoutesDeps,\n | 'controller'\n | 'publicOrigin'\n | 'auth'\n | 'sandbox'\n | 'users'\n | 'factoryStorage'\n | 'integrationStorage'\n | 'sourceControlStorage'\n | 'integrations'\n > & {\n stateSigner: StateSigner;\n emitAudit?: AuditEmitter['emit'];\n configVersion: string;\n boardRegistry: BoardRegistry;\n factoryReady: boolean;\n /** Work-item feed service, so a channel integration can ingest platform messages. */\n feed: CommentsDomain;\n domains: Pick<\n FactoryApiRoutesDeps['domains'],\n 'projects' | 'intake' | 'workItems' | 'channelIdentity' | 'memorySettings' | 'modelDefaults'\n >;\n /**\n * Stable id of the registered source-control-owning integration (today:\n * `'github'` when registered). Every call site must derive and pass it so\n * `routes()`, `channels()`, and `workers()` all see the same context shape.\n */\n sourceControlOwnerId?: string;\n },\n integrationId: string,\n): IntegrationContext {\n return {\n auth: deps.auth,\n sandbox: deps.sandbox,\n ...(deps.users ? { users: deps.users } : {}),\n factoryStorage: deps.factoryStorage,\n baseUrl: deps.publicOrigin,\n controller: deps.controller,\n stateSigner: deps.stateSigner,\n storage: {\n generic: deps.integrationStorage.forIntegration(integrationId),\n sourceControl: deps.sourceControlStorage.forIntegration(integrationId),\n ...(deps.sourceControlOwnerId\n ? { sourceControlOwner: deps.sourceControlStorage.forIntegration(deps.sourceControlOwnerId) }\n : {}),\n sourceControls: (deps.integrations ?? [])\n .filter(({ integration }) => integration.versionControl)\n .map(({ integration }) => deps.sourceControlStorage.forIntegration(integration.id)),\n projects: deps.domains.projects,\n intake: deps.domains.intake,\n channelIdentity: deps.domains.channelIdentity,\n memorySettings: deps.domains.memorySettings,\n modelDefaults: deps.domains.modelDefaults,\n },\n ...(deps.factoryReady ? { workItems: deps.domains.workItems, feed: deps.feed } : {}),\n ...(deps.factoryReady\n ? {\n runtime: { configVersion: deps.configVersion, workItems: deps.domains.workItems, boards: deps.boardRegistry },\n }\n : {}),\n ...(deps.emitAudit ? { hooks: { emitAudit: deps.emitAudit } } : {}),\n };\n}\n\n/**\n * Disabled-status stub for the well-known integration ids. The SPA polls\n * `/web/github/status`, `/web/linear/status`, and `/web/jira/status`\n * unconditionally, so when an integration is absent (or not ready) the status\n * contract must still hold. Unknown custom ids get no stub — the SPA doesn't\n * poll them.\n */\nfunction disabledIntegrationStatusRoutes(deps: FactoryApiRoutesDeps, id: string, configured = false): ApiRoute[] {\n if (id === 'github') {\n return [\n registerApiRoute('/web/github/status', {\n method: 'GET',\n requiresAuth: false,\n handler: c =>\n c.json({\n enabled: false,\n connected: false,\n installations: [],\n reason: 'missing_config',\n diagnostics: getGithubFeatureDiagnostics({\n github: undefined,\n auth: deps.auth,\n appDbConfigured: deps.factoryStorage !== undefined,\n stateSigner: deps.stateSigner,\n sandbox: deps.sandbox,\n }),\n }),\n }),\n ];\n }\n if (id === 'linear') {\n return [\n registerApiRoute('/web/linear/status', {\n method: 'GET',\n requiresAuth: false,\n handler: c =>\n c.json({\n enabled: false,\n connected: false,\n workspace: null,\n reason: 'missing_config',\n diagnostics: {\n linearAppConfigured: configured,\n factoryAuthEnabled: deps.auth.enabled(),\n appDbConfigured: true,\n },\n }),\n }),\n ];\n }\n if (id === 'jira') {\n return [\n registerApiRoute('/web/jira/status', {\n method: 'GET',\n requiresAuth: false,\n handler: c =>\n c.json({\n enabled: false,\n configured,\n site: null,\n reason: 'missing_config',\n diagnostics: {\n jiraConfigured: configured,\n factoryAuthEnabled: deps.auth.enabled(),\n appDbConfigured: deps.factoryStorage !== undefined,\n },\n }),\n }),\n ];\n }\n return [];\n}\n\n/**\n * Stub for `GET /web/channel-accounts` when NO Slack integration is\n * registered. The SPA's Connections section polls the path unconditionally;\n * without a stub the SPA fallback serves HTML, which the UI can only read as\n * \"old server / unknown\". The machine-readable reason lets it say the truth:\n * the integration isn't registered.\n *\n * Mounted only for ABSENT slack — a registered integration owns the path via\n * its connect routes (or, when the state signer is unstable, gets no routes\n * at all and the UI falls back to the generic copy). Static payload, leaks\n * nothing → no auth needed, same posture as the github/linear stubs.\n */\nfunction absentSlackChannelAccountsRoutes(): ApiRoute[] {\n return [\n registerApiRoute('/web/channel-accounts', {\n method: 'GET',\n requiresAuth: false,\n handler: c => c.json({ accounts: [], canConnect: false, reason: 'not_registered' }),\n }),\n ];\n}\n\n/**\n * Assemble the custom `/web/*` API routes as Mastra `server.apiRoutes`:\n * - fs browser routes (project picker), confined to `fsRoot`\n * - config routes (provider/API-key/default-model/OM management)\n * - every registered integration's `routes()` surface (full set when ready,\n * disabled-status stub otherwise), plus stubs for absent known ids\n */\nexport function assembleFactoryApiRoutes(deps: FactoryApiRoutesDeps): ApiRoute[] {\n const emitAudit: AuditEmitter['emit'] = args => deps.audit.emit(args);\n const registrations = deps.integrations ?? [];\n const githubRegistration = registrations.find(({ integration }) => integration.id === 'github');\n const githubStorage = githubRegistration ? deps.sourceControlStorage.forIntegration('github') : undefined;\n const githubIntegration = githubRegistration?.integration as GithubIntegration | undefined;\n const sourceControlRegistrations = registrations.filter(({ integration }) => integration.versionControl);\n const sourceControlIntegrationIds = [\n ...new Set(['github', ...sourceControlRegistrations.map(({ integration }) => integration.id)]),\n ];\n const sourceControls = sourceControlIntegrationIds.map(id => deps.sourceControlStorage.forIntegration(id));\n const sourceControlSessions = createSourceControlSessionLookup(sourceControls);\n\n const integrationRoutes = registrations.flatMap(registration => {\n const { integration } = registration;\n if (!deps.stateSigner) return disabledIntegrationStatusRoutes(deps, integration.id, true);\n const context = buildIntegrationContext(\n {\n ...deps,\n stateSigner: deps.stateSigner,\n emitAudit,\n ...(githubRegistration ? { sourceControlOwnerId: 'github' } : {}),\n },\n integration.id,\n );\n return guardIntegrationRoutes({ ...registration, routes: integration.routes(context) });\n });\n // Session persistence belongs to the linked source-control provider, not to\n // GitHub. Replace legacy GitHub-owned handlers with one resolver spanning\n // the legacy GitHub partition and every registered source-control partition.\n const sharedSessionRouteKeys = new Set([\n 'GET /web/github/projects/:id/sessions',\n 'POST /web/github/projects/:id/sessions',\n 'GET /web/user-sessions/:sessionId',\n 'DELETE /web/user-sessions/:sessionId',\n 'POST /web/user-sessions/:sessionId/title',\n ]);\n const providerRoutes = integrationRoutes.filter(\n route => !sharedSessionRouteKeys.has(route.method + ' ' + route.path),\n );\n const sourceControlSessionRoutes =\n sourceControls.length === 0\n ? []\n : buildSourceControlSessionRoutes({\n auth: deps.auth,\n sourceControls,\n ...(deps.users ? { users: deps.users } : {}),\n controller: deps.controller,\n memorySettings: deps.domains.memorySettings,\n sessionRetirement: deps.sessionRetirement,\n ...(deps.factoryReady ? { workItems: deps.domains.workItems } : {}),\n });\n // Absent known integrations still get their disabled-status stub.\n const absentStubs = ['github', 'linear', 'jira']\n .filter(id => !registrations.some(({ integration }) => integration.id === id))\n .flatMap(id => disabledIntegrationStatusRoutes(deps, id));\n // Absent slack gets the channel-accounts not-registered stub (registered\n // slack owns the path via its own connect routes).\n const slackAbsentStubs = registrations.some(({ integration }) => integration.id === 'slack')\n ? []\n : absentSlackChannelAccountsRoutes();\n\n const transitionService = deps.factoryReady\n ? (deps.factoryTransitionService ??\n new FactoryTransitionService({\n configVersion: deps.configVersion,\n boards: deps.boardRegistry,\n storage: deps.domains.workItems,\n audit: deps.audit,\n }))\n : undefined;\n const startCoordinator = transitionService\n ? new FactoryStartCoordinator(\n deps.controller,\n deps.domains.workItems,\n transitionService,\n request =>\n resolveFactorySourceControl({\n sourceControls,\n orgId: request.orgId,\n factoryProjectId: request.factoryProjectId,\n sessionId: request.sessionId,\n }),\n deps.domains.intake,\n )\n : undefined;\n if (transitionService && startCoordinator) {\n deps.onFactoryRuntime?.({\n transitionService,\n ...(sourceControlRegistrations.length > 0\n ? {\n prepareBinding: async (input: FactoryBindingPreparationInput) => {\n const sourceControl = await resolveFactorySourceControl({\n sourceControls,\n orgId: input.record.orgId,\n factoryProjectId: input.record.factoryProjectId,\n });\n if (!sourceControl) {\n throw new FactoryDispatchError(\n 'source_control_missing',\n 'Factory project has no linked source-control repository.',\n );\n }\n return prepareFactoryRuleBinding(\n sourceControl,\n startCoordinator,\n deps.domains.projects,\n deps.boardRegistry,\n input,\n deps.domains.intake,\n );\n },\n }\n : {}),\n });\n }\n\n return [\n ...buildFsRoutes({\n root: deps.fsRoot,\n sessionFs: {\n auth: deps.auth,\n sessions: sourceControlSessions,\n filesystem: deps.domains.filesystem,\n },\n }),\n ...new ConfigRoutes({\n auth: deps.auth,\n controller: deps.controller,\n authStorage: deps.authStorage,\n modelCredentials: deps.domains.modelCredentials,\n modelDefaults: deps.domains.modelDefaults,\n sourceControlSessions,\n memorySettings: deps.domains.memorySettings,\n factoryProjects: deps.domains.projects,\n customProviders: deps.domains.customProviders,\n features: { knowledge: deps.knowledgeEnabled },\n deploymentProviders: deps.deploymentModelProviders,\n onCredentialsChanged: invalidateTenantCredentialSnapshots,\n onCustomProvidersChanged: invalidateCustomProvidersSnapshots,\n }).routes(),\n ...new OAuthRoutes({\n auth: deps.auth,\n authStorage: deps.authStorage,\n modelCredentials: deps.domains.modelCredentials,\n onCredentialsChanged: invalidateTenantCredentialSnapshots,\n }).routes(),\n ...new SkillRoutes({\n auth: deps.auth,\n controllerId: deps.controllerId,\n controller: deps.controller,\n sourceControlStorage: githubStorage,\n ensureSourceControlReady: githubRegistration?.ensureReady,\n }).routes(),\n ...sourceControlSessionRoutes,\n ...(sourceControls.length === 0 ? [] : buildSourceControlSettingsRoutes({ auth: deps.auth, sourceControls })),\n ...providerRoutes,\n ...absentStubs,\n ...slackAbsentStubs,\n ...(deps.intakeReady\n ? new IntakeRoutes({\n auth: deps.auth,\n audit: deps.audit,\n intake: deps.domains.intake,\n projects: deps.domains.projects,\n boardRegistry: deps.boardRegistry,\n // Relocation reads and writes work items, which init fail-soft separately from intake.\n ...(deps.factoryReady ? { workItems: deps.domains.workItems } : {}),\n integrations: (deps.integrations ?? []).flatMap(({ integration }) =>\n integration.intake ? [{ id: integration.id, intake: integration.intake }] : [],\n ),\n }).routes()\n : []),\n ...(deps.factoryReady && deps.knowledgeEnabled\n ? new KnowledgeRoutes({\n auth: deps.auth,\n projects: deps.domains.projects,\n knowledge: async key => deps.controller.getMastra()?.getKnowledge(key),\n defaultKnowledgeKey: deps.knowledgeKey,\n threadTitle: async threadId => {\n const memory = await deps.controller.getMastra()?.getStorage()?.getStore('memory');\n return (await memory?.getThreadById({ threadId }))?.title;\n },\n }).routes()\n : []),\n ...(deps.factoryReady\n ? new WorkItemRoutes({\n auth: deps.auth,\n audit: deps.audit,\n projects: deps.domains.projects,\n workItems: deps.domains.workItems,\n boardRegistry: deps.boardRegistry,\n comments: deps.domains.comments,\n queueHealth: deps.domains.queueHealth,\n transitionService,\n startCoordinator,\n liveSessions: deps.liveSessions,\n }).routes()\n : []),\n ...(deps.factoryReady\n ? buildAutomationRunRoutes({\n auth: deps.auth,\n audit: deps.audit,\n projects: deps.domains.projects,\n workItems: deps.domains.workItems,\n configVersion: deps.configVersion,\n })\n : []),\n ];\n}\n"],"mappings":"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"}
|
|
@@ -10,6 +10,25 @@ export interface FactorySessionSourceLookup {
|
|
|
10
10
|
}
|
|
11
11
|
export declare function getFactorySessionCoordinates(requestContext: RequestContext | undefined): FactoryRunBindingSessionAddress | null;
|
|
12
12
|
export declare function getFactorySessionAddress(requestContext: RequestContext | undefined): FactoryRunBindingAddress | null;
|
|
13
|
+
/**
|
|
14
|
+
* Read the session's factory scoping off controller state: the project whose
|
|
15
|
+
* shared settings row applies to its runs, plus the org rung that row is keyed
|
|
16
|
+
* by (`factoryOrgId` is seeded at session start and is authoritative for
|
|
17
|
+
* downstream identity reads — the owner id is a user, never an org).
|
|
18
|
+
*/
|
|
19
|
+
export declare function readFactorySessionScope(requestContext: RequestContext | undefined): {
|
|
20
|
+
factoryProjectId: string;
|
|
21
|
+
factoryOrgId?: string;
|
|
22
|
+
} | null;
|
|
23
|
+
/**
|
|
24
|
+
* Read the active run binding for this session when controller state has lost
|
|
25
|
+
* `factoryProjectId` — a crash-recovered session ("Continue") is recreated with
|
|
26
|
+
* empty state, so the binding table is the only remaining source of the project
|
|
27
|
+
* whose shared settings row applies to the run. Read-only, unlike
|
|
28
|
+
* `resolveFactorySessionAddress`: it neither heals state nor touches source
|
|
29
|
+
* control, so input processors can call it before any tool has run.
|
|
30
|
+
*/
|
|
31
|
+
export declare function findSessionRunBinding(requestContext: RequestContext | undefined, storage: Pick<WorkItemsStorage, 'findActiveRunBindingByThread'>): Promise<FactoryRunBindingRecord | null>;
|
|
13
32
|
export interface FactorySessionAddressResolution {
|
|
14
33
|
address: FactoryRunBindingAddress;
|
|
15
34
|
/** Present only when the address was recovered from the binding table. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"binding-context.d.ts","sourceRoot":"","sources":["../../src/rules/binding-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAGnE,OAAO,KAAK,EACV,wBAAwB,EACxB,uBAAuB,EACvB,+BAA+B,EAC/B,gBAAgB,EACjB,MAAM,uCAAuC,CAAC;AAY/C,kFAAkF;AAClF,MAAM,WAAW,0BAA0B;IACzC,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,mBAAmB,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;CACvH;AAED,wBAAgB,4BAA4B,CAC1C,cAAc,EAAE,cAAc,GAAG,SAAS,GACzC,+BAA+B,GAAG,IAAI,CAWxC;AAED,wBAAgB,wBAAwB,CAAC,cAAc,EAAE,cAAc,GAAG,SAAS,GAAG,wBAAwB,GAAG,IAAI,CAOpH;AAED,MAAM,WAAW,+BAA+B;IAC9C,OAAO,EAAE,wBAAwB,CAAC;IAClC,0EAA0E;IAC1E,OAAO,CAAC,EAAE,uBAAuB,CAAC;CACnC;AAED;;;;;;;;GAQG;AACH,wBAAsB,4BAA4B,CAAC,OAAO,EAAE;IAC1D,cAAc,EAAE,cAAc,GAAG,SAAS,CAAC;IAC3C,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,8BAA8B,GAAG,KAAK,CAAC,CAAC;IACxE,QAAQ,CAAC,EAAE,0BAA0B,CAAC;IACtC;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,GAAG,OAAO,CAAC,+BAA+B,GAAG,IAAI,CAAC,CAgClD"}
|
|
1
|
+
{"version":3,"file":"binding-context.d.ts","sourceRoot":"","sources":["../../src/rules/binding-context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAGnE,OAAO,KAAK,EACV,wBAAwB,EACxB,uBAAuB,EACvB,+BAA+B,EAC/B,gBAAgB,EACjB,MAAM,uCAAuC,CAAC;AAY/C,kFAAkF;AAClF,MAAM,WAAW,0BAA0B;IACzC,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,mBAAmB,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;CACvH;AAED,wBAAgB,4BAA4B,CAC1C,cAAc,EAAE,cAAc,GAAG,SAAS,GACzC,+BAA+B,GAAG,IAAI,CAWxC;AAED,wBAAgB,wBAAwB,CAAC,cAAc,EAAE,cAAc,GAAG,SAAS,GAAG,wBAAwB,GAAG,IAAI,CAOpH;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,cAAc,GAAG,SAAS,GACzC;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAW5D;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,cAAc,EAAE,cAAc,GAAG,SAAS,EAC1C,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,8BAA8B,CAAC,GAC9D,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAYzC;AAED,MAAM,WAAW,+BAA+B;IAC9C,OAAO,EAAE,wBAAwB,CAAC;IAClC,0EAA0E;IAC1E,OAAO,CAAC,EAAE,uBAAuB,CAAC;CACnC;AAED;;;;;;;;GAQG;AACH,wBAAsB,4BAA4B,CAAC,OAAO,EAAE;IAC1D,cAAc,EAAE,cAAc,GAAG,SAAS,CAAC;IAC3C,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,8BAA8B,GAAG,KAAK,CAAC,CAAC;IACxE,QAAQ,CAAC,EAAE,0BAA0B,CAAC;IACtC;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,GAAG,OAAO,CAAC,+BAA+B,GAAG,IAAI,CAAC,CAgClD"}
|
|
@@ -23,6 +23,44 @@ function getFactorySessionAddress(requestContext) {
|
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
+
* Read the session's factory scoping off controller state: the project whose
|
|
27
|
+
* shared settings row applies to its runs, plus the org rung that row is keyed
|
|
28
|
+
* by (`factoryOrgId` is seeded at session start and is authoritative for
|
|
29
|
+
* downstream identity reads — the owner id is a user, never an org).
|
|
30
|
+
*/
|
|
31
|
+
function readFactorySessionScope(requestContext) {
|
|
32
|
+
if (!requestContext || typeof requestContext.get !== "function") return null;
|
|
33
|
+
const state = requestContext.get("controller")?.getState();
|
|
34
|
+
const factoryProjectId = state?.factoryProjectId;
|
|
35
|
+
if (typeof factoryProjectId !== "string" || factoryProjectId.length === 0) return null;
|
|
36
|
+
const factoryOrgId = state?.factoryOrgId;
|
|
37
|
+
return {
|
|
38
|
+
factoryProjectId,
|
|
39
|
+
...typeof factoryOrgId === "string" && factoryOrgId.length > 0 ? { factoryOrgId } : {}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Read the active run binding for this session when controller state has lost
|
|
44
|
+
* `factoryProjectId` — a crash-recovered session ("Continue") is recreated with
|
|
45
|
+
* empty state, so the binding table is the only remaining source of the project
|
|
46
|
+
* whose shared settings row applies to the run. Read-only, unlike
|
|
47
|
+
* `resolveFactorySessionAddress`: it neither heals state nor touches source
|
|
48
|
+
* control, so input processors can call it before any tool has run.
|
|
49
|
+
*/
|
|
50
|
+
async function findSessionRunBinding(requestContext, storage) {
|
|
51
|
+
if (!requestContext || typeof requestContext.get !== "function") return null;
|
|
52
|
+
const context = requestContext.get("controller");
|
|
53
|
+
if (!context?.threadId || !context.resourceId) return null;
|
|
54
|
+
const orgId = getFactoryAuthOrgId(getFactoryAuthUserFromContext(requestContext));
|
|
55
|
+
if (!orgId) return null;
|
|
56
|
+
return storage.findActiveRunBindingByThread({
|
|
57
|
+
orgId,
|
|
58
|
+
threadId: context.threadId,
|
|
59
|
+
resourceId: context.resourceId,
|
|
60
|
+
sessionId: context.resourceId
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
26
64
|
* Resolve the bound session address, falling back to the active binding row
|
|
27
65
|
* when the in-memory session state is missing `factoryProjectId` — a server
|
|
28
66
|
* crash drops controller sessions, and a resumed session ("Continue") is
|
|
@@ -91,6 +129,6 @@ async function healRecoveredSessionState(options) {
|
|
|
91
129
|
} catch {}
|
|
92
130
|
}
|
|
93
131
|
//#endregion
|
|
94
|
-
export { getFactorySessionAddress, getFactorySessionCoordinates, resolveFactorySessionAddress };
|
|
132
|
+
export { findSessionRunBinding, getFactorySessionAddress, getFactorySessionCoordinates, readFactorySessionScope, resolveFactorySessionAddress };
|
|
95
133
|
|
|
96
134
|
//# sourceMappingURL=binding-context.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"binding-context.js","names":[],"sources":["../../src/rules/binding-context.ts"],"sourcesContent":["import type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport type { RequestContext } from '@mastra/core/request-context';\n\nimport { getFactoryAuthOrgId, getFactoryAuthUserFromContext } from '../auth.js';\nimport type {\n FactoryRunBindingAddress,\n FactoryRunBindingRecord,\n FactoryRunBindingSessionAddress,\n WorkItemsStorage,\n} from '../storage/domains/work-items/base.js';\n\ninterface FactorySessionState {\n factoryProjectId?: string;\n factoryOrgId?: string;\n projectRepositoryId?: string;\n untrustedCheckout?: boolean;\n baseRef?: string;\n}\n\ntype FactorySessionControllerContext = AgentControllerRequestContext<FactorySessionState>;\n\n/** Minimal source-control session lookup used to heal recovered session state. */\nexport interface FactorySessionSourceLookup {\n getBySessionId(sessionId: string): Promise<{ orgId: string; projectRepositoryId: string; baseBranch: string } | null>;\n}\n\nexport function getFactorySessionCoordinates(\n requestContext: RequestContext | undefined,\n): FactoryRunBindingSessionAddress | null {\n if (!requestContext || typeof requestContext.get !== 'function') return null;\n const context = requestContext.get('controller') as FactorySessionControllerContext | undefined;\n const factoryProjectId = context?.getState().factoryProjectId;\n if (!context?.threadId || !context.resourceId || !factoryProjectId) return null;\n return {\n factoryProjectId,\n threadId: context.threadId,\n resourceId: context.resourceId,\n sessionId: context.resourceId,\n };\n}\n\nexport function getFactorySessionAddress(requestContext: RequestContext | undefined): FactoryRunBindingAddress | null {\n const coordinates = getFactorySessionCoordinates(requestContext);\n if (!coordinates || !requestContext || typeof requestContext.get !== 'function') return null;\n const user = getFactoryAuthUserFromContext(requestContext);\n const orgId = getFactoryAuthOrgId(user);\n if (!orgId) return null;\n return { orgId, ...coordinates };\n}\n\nexport interface FactorySessionAddressResolution {\n address: FactoryRunBindingAddress;\n /** Present only when the address was recovered from the binding table. */\n binding?: FactoryRunBindingRecord;\n}\n\n/**\n * Resolve the bound session address, falling back to the active binding row\n * when the in-memory session state is missing `factoryProjectId` — a server\n * crash drops controller sessions, and a resumed session (\"Continue\") is\n * recreated with empty state, which silently unregistered the transition\n * tool. On recovery the lost state is healed back onto the session (including\n * the `untrustedCheckout`/`baseRef` security posture the start coordinator\n * originally seeded) so later reads resolve directly.\n */\nexport async function resolveFactorySessionAddress(options: {\n requestContext: RequestContext | undefined;\n storage: Pick<WorkItemsStorage, 'findActiveRunBindingByThread' | 'get'>;\n sessions?: FactorySessionSourceLookup;\n /**\n * Resolve through the binding table even when state already carries\n * `factoryProjectId`, so the row heals the rest of the session state. Prompt\n * creation uses this: a partially persisted state can keep the project id\n * while the untrusted-checkout posture is gone, and the direct short-circuit\n * would take that id as proof the session is intact.\n */\n forceBindingLookup?: boolean;\n}): Promise<FactorySessionAddressResolution | null> {\n const direct = options.forceBindingLookup ? null : getFactorySessionAddress(options.requestContext);\n if (direct) return { address: direct };\n\n const requestContext = options.requestContext;\n if (!requestContext || typeof requestContext.get !== 'function') return null;\n const context = requestContext.get('controller') as FactorySessionControllerContext | undefined;\n if (!context?.threadId || !context.resourceId) return null;\n const user = getFactoryAuthUserFromContext(requestContext);\n const orgId = getFactoryAuthOrgId(user);\n if (!orgId) return null;\n\n const binding = await options.storage.findActiveRunBindingByThread({\n orgId,\n threadId: context.threadId,\n resourceId: context.resourceId,\n sessionId: context.resourceId,\n });\n if (!binding) return null;\n\n await healRecoveredSessionState({ context, binding, storage: options.storage, sessions: options.sessions });\n\n return {\n address: {\n orgId,\n factoryProjectId: binding.factoryProjectId,\n threadId: context.threadId,\n resourceId: context.resourceId,\n sessionId: context.resourceId,\n },\n binding,\n };\n}\n\nasync function healRecoveredSessionState(options: {\n context: FactorySessionControllerContext;\n binding: FactoryRunBindingRecord;\n storage: Pick<WorkItemsStorage, 'get'>;\n sessions?: FactorySessionSourceLookup;\n}): Promise<void> {\n const { binding } = options;\n // `factoryOrgId` mirrors the start coordinator's seed: the binding row holds\n // the authoritative org id, so crash-recovered sessions heal it for free.\n const updates: FactorySessionState = { factoryProjectId: binding.factoryProjectId, factoryOrgId: binding.orgId };\n // Security posture first, from the binding row alone (no I/O): review-bound\n // sessions run against attacker-writable checkouts, so `untrustedCheckout`\n // must survive even if the enrichment lookups below fail transiently.\n if (binding.role === 'review') {\n updates.untrustedCheckout = true;\n }\n // Best-effort enrichment mirroring the start coordinator's original seed:\n // PR-sourced work items are untrusted regardless of role, and `baseRef`\n // restores the trusted instruction source for untrusted checkouts.\n try {\n const item = await options.storage.get({ orgId: binding.orgId, id: binding.workItemId });\n const foundSession = (await options.sessions?.getBySessionId(binding.sessionId)) ?? null;\n const sourceSession = foundSession?.orgId === binding.orgId ? foundSession : null;\n if (sourceSession) {\n updates.projectRepositoryId = sourceSession.projectRepositoryId;\n }\n const untrusted = updates.untrustedCheckout === true || item?.externalSource?.type === 'pull-request';\n if (untrusted) {\n updates.untrustedCheckout = true;\n const metadataBaseBranch = item?.metadata?.baseBranch;\n const baseRef =\n sourceSession?.baseBranch ||\n (typeof metadataBaseBranch === 'string' && metadataBaseBranch ? metadataBaseBranch : undefined);\n if (baseRef) updates.baseRef = baseRef;\n } else {\n // Record the trusted verdict explicitly so a healed session carries every\n // trust field; the prompt-time recovery check treats a missing flag as\n // \"not yet verified\" and would otherwise re-run on every prompt. Left\n // unset when enrichment fails so the next prompt retries the lookup.\n updates.untrustedCheckout = false;\n }\n } catch {\n // Enrichment is best-effort; the address itself only needs the binding.\n }\n try {\n await options.context.setState(updates);\n } catch {\n // State healing must never block tool registration on the recovered address.\n }\n}\n"],"mappings":";;AA0BA,SAAgB,6BACd,gBACwC;CACxC,IAAI,CAAC,kBAAkB,OAAO,eAAe,QAAQ,YAAY,OAAO;CACxE,MAAM,UAAU,eAAe,IAAI,YAAY;CAC/C,MAAM,mBAAmB,SAAS,SAAS,CAAC,CAAC;CAC7C,IAAI,CAAC,SAAS,YAAY,CAAC,QAAQ,cAAc,CAAC,kBAAkB,OAAO;CAC3E,OAAO;EACL;EACA,UAAU,QAAQ;EAClB,YAAY,QAAQ;EACpB,WAAW,QAAQ;CACrB;AACF;AAEA,SAAgB,yBAAyB,gBAA6E;CACpH,MAAM,cAAc,6BAA6B,cAAc;CAC/D,IAAI,CAAC,eAAe,CAAC,kBAAkB,OAAO,eAAe,QAAQ,YAAY,OAAO;CAExF,MAAM,QAAQ,oBADD,8BAA8B,cACN,CAAC;CACtC,IAAI,CAAC,OAAO,OAAO;CACnB,OAAO;EAAE;EAAO,GAAG;CAAY;AACjC;;;;;;;;;;AAiBA,eAAsB,6BAA6B,SAYC;CAClD,MAAM,SAAS,QAAQ,qBAAqB,OAAO,yBAAyB,QAAQ,cAAc;CAClG,IAAI,QAAQ,OAAO,EAAE,SAAS,OAAO;CAErC,MAAM,iBAAiB,QAAQ;CAC/B,IAAI,CAAC,kBAAkB,OAAO,eAAe,QAAQ,YAAY,OAAO;CACxE,MAAM,UAAU,eAAe,IAAI,YAAY;CAC/C,IAAI,CAAC,SAAS,YAAY,CAAC,QAAQ,YAAY,OAAO;CAEtD,MAAM,QAAQ,oBADD,8BAA8B,cACN,CAAC;CACtC,IAAI,CAAC,OAAO,OAAO;CAEnB,MAAM,UAAU,MAAM,QAAQ,QAAQ,6BAA6B;EACjE;EACA,UAAU,QAAQ;EAClB,YAAY,QAAQ;EACpB,WAAW,QAAQ;CACrB,CAAC;CACD,IAAI,CAAC,SAAS,OAAO;CAErB,MAAM,0BAA0B;EAAE;EAAS;EAAS,SAAS,QAAQ;EAAS,UAAU,QAAQ;CAAS,CAAC;CAE1G,OAAO;EACL,SAAS;GACP;GACA,kBAAkB,QAAQ;GAC1B,UAAU,QAAQ;GAClB,YAAY,QAAQ;GACpB,WAAW,QAAQ;EACrB;EACA;CACF;AACF;AAEA,eAAe,0BAA0B,SAKvB;CAChB,MAAM,EAAE,YAAY;CAGpB,MAAM,UAA+B;EAAE,kBAAkB,QAAQ;EAAkB,cAAc,QAAQ;CAAM;CAI/G,IAAI,QAAQ,SAAS,UACnB,QAAQ,oBAAoB;CAK9B,IAAI;EACF,MAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI;GAAE,OAAO,QAAQ;GAAO,IAAI,QAAQ;EAAW,CAAC;EACvF,MAAM,eAAgB,MAAM,QAAQ,UAAU,eAAe,QAAQ,SAAS,KAAM;EACpF,MAAM,gBAAgB,cAAc,UAAU,QAAQ,QAAQ,eAAe;EAC7E,IAAI,eACF,QAAQ,sBAAsB,cAAc;EAG9C,IADkB,QAAQ,sBAAsB,QAAQ,MAAM,gBAAgB,SAAS,gBACxE;GACb,QAAQ,oBAAoB;GAC5B,MAAM,qBAAqB,MAAM,UAAU;GAC3C,MAAM,UACJ,eAAe,eACd,OAAO,uBAAuB,YAAY,qBAAqB,qBAAqB,KAAA;GACvF,IAAI,SAAS,QAAQ,UAAU;EACjC,OAKE,QAAQ,oBAAoB;CAEhC,QAAQ,CAER;CACA,IAAI;EACF,MAAM,QAAQ,QAAQ,SAAS,OAAO;CACxC,QAAQ,CAER;AACF"}
|
|
1
|
+
{"version":3,"file":"binding-context.js","names":[],"sources":["../../src/rules/binding-context.ts"],"sourcesContent":["import type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport type { RequestContext } from '@mastra/core/request-context';\n\nimport { getFactoryAuthOrgId, getFactoryAuthUserFromContext } from '../auth.js';\nimport type {\n FactoryRunBindingAddress,\n FactoryRunBindingRecord,\n FactoryRunBindingSessionAddress,\n WorkItemsStorage,\n} from '../storage/domains/work-items/base.js';\n\ninterface FactorySessionState {\n factoryProjectId?: string;\n factoryOrgId?: string;\n projectRepositoryId?: string;\n untrustedCheckout?: boolean;\n baseRef?: string;\n}\n\ntype FactorySessionControllerContext = AgentControllerRequestContext<FactorySessionState>;\n\n/** Minimal source-control session lookup used to heal recovered session state. */\nexport interface FactorySessionSourceLookup {\n getBySessionId(sessionId: string): Promise<{ orgId: string; projectRepositoryId: string; baseBranch: string } | null>;\n}\n\nexport function getFactorySessionCoordinates(\n requestContext: RequestContext | undefined,\n): FactoryRunBindingSessionAddress | null {\n if (!requestContext || typeof requestContext.get !== 'function') return null;\n const context = requestContext.get('controller') as FactorySessionControllerContext | undefined;\n const factoryProjectId = context?.getState().factoryProjectId;\n if (!context?.threadId || !context.resourceId || !factoryProjectId) return null;\n return {\n factoryProjectId,\n threadId: context.threadId,\n resourceId: context.resourceId,\n sessionId: context.resourceId,\n };\n}\n\nexport function getFactorySessionAddress(requestContext: RequestContext | undefined): FactoryRunBindingAddress | null {\n const coordinates = getFactorySessionCoordinates(requestContext);\n if (!coordinates || !requestContext || typeof requestContext.get !== 'function') return null;\n const user = getFactoryAuthUserFromContext(requestContext);\n const orgId = getFactoryAuthOrgId(user);\n if (!orgId) return null;\n return { orgId, ...coordinates };\n}\n\n/**\n * Read the session's factory scoping off controller state: the project whose\n * shared settings row applies to its runs, plus the org rung that row is keyed\n * by (`factoryOrgId` is seeded at session start and is authoritative for\n * downstream identity reads — the owner id is a user, never an org).\n */\nexport function readFactorySessionScope(\n requestContext: RequestContext | undefined,\n): { factoryProjectId: string; factoryOrgId?: string } | null {\n if (!requestContext || typeof requestContext.get !== 'function') return null;\n const context = requestContext.get('controller') as FactorySessionControllerContext | undefined;\n const state = context?.getState();\n const factoryProjectId = state?.factoryProjectId;\n if (typeof factoryProjectId !== 'string' || factoryProjectId.length === 0) return null;\n const factoryOrgId = state?.factoryOrgId;\n return {\n factoryProjectId,\n ...(typeof factoryOrgId === 'string' && factoryOrgId.length > 0 ? { factoryOrgId } : {}),\n };\n}\n\n/**\n * Read the active run binding for this session when controller state has lost\n * `factoryProjectId` — a crash-recovered session (\"Continue\") is recreated with\n * empty state, so the binding table is the only remaining source of the project\n * whose shared settings row applies to the run. Read-only, unlike\n * `resolveFactorySessionAddress`: it neither heals state nor touches source\n * control, so input processors can call it before any tool has run.\n */\nexport async function findSessionRunBinding(\n requestContext: RequestContext | undefined,\n storage: Pick<WorkItemsStorage, 'findActiveRunBindingByThread'>,\n): Promise<FactoryRunBindingRecord | null> {\n if (!requestContext || typeof requestContext.get !== 'function') return null;\n const context = requestContext.get('controller') as FactorySessionControllerContext | undefined;\n if (!context?.threadId || !context.resourceId) return null;\n const orgId = getFactoryAuthOrgId(getFactoryAuthUserFromContext(requestContext));\n if (!orgId) return null;\n return storage.findActiveRunBindingByThread({\n orgId,\n threadId: context.threadId,\n resourceId: context.resourceId,\n sessionId: context.resourceId,\n });\n}\n\nexport interface FactorySessionAddressResolution {\n address: FactoryRunBindingAddress;\n /** Present only when the address was recovered from the binding table. */\n binding?: FactoryRunBindingRecord;\n}\n\n/**\n * Resolve the bound session address, falling back to the active binding row\n * when the in-memory session state is missing `factoryProjectId` — a server\n * crash drops controller sessions, and a resumed session (\"Continue\") is\n * recreated with empty state, which silently unregistered the transition\n * tool. On recovery the lost state is healed back onto the session (including\n * the `untrustedCheckout`/`baseRef` security posture the start coordinator\n * originally seeded) so later reads resolve directly.\n */\nexport async function resolveFactorySessionAddress(options: {\n requestContext: RequestContext | undefined;\n storage: Pick<WorkItemsStorage, 'findActiveRunBindingByThread' | 'get'>;\n sessions?: FactorySessionSourceLookup;\n /**\n * Resolve through the binding table even when state already carries\n * `factoryProjectId`, so the row heals the rest of the session state. Prompt\n * creation uses this: a partially persisted state can keep the project id\n * while the untrusted-checkout posture is gone, and the direct short-circuit\n * would take that id as proof the session is intact.\n */\n forceBindingLookup?: boolean;\n}): Promise<FactorySessionAddressResolution | null> {\n const direct = options.forceBindingLookup ? null : getFactorySessionAddress(options.requestContext);\n if (direct) return { address: direct };\n\n const requestContext = options.requestContext;\n if (!requestContext || typeof requestContext.get !== 'function') return null;\n const context = requestContext.get('controller') as FactorySessionControllerContext | undefined;\n if (!context?.threadId || !context.resourceId) return null;\n const user = getFactoryAuthUserFromContext(requestContext);\n const orgId = getFactoryAuthOrgId(user);\n if (!orgId) return null;\n\n const binding = await options.storage.findActiveRunBindingByThread({\n orgId,\n threadId: context.threadId,\n resourceId: context.resourceId,\n sessionId: context.resourceId,\n });\n if (!binding) return null;\n\n await healRecoveredSessionState({ context, binding, storage: options.storage, sessions: options.sessions });\n\n return {\n address: {\n orgId,\n factoryProjectId: binding.factoryProjectId,\n threadId: context.threadId,\n resourceId: context.resourceId,\n sessionId: context.resourceId,\n },\n binding,\n };\n}\n\nasync function healRecoveredSessionState(options: {\n context: FactorySessionControllerContext;\n binding: FactoryRunBindingRecord;\n storage: Pick<WorkItemsStorage, 'get'>;\n sessions?: FactorySessionSourceLookup;\n}): Promise<void> {\n const { binding } = options;\n // `factoryOrgId` mirrors the start coordinator's seed: the binding row holds\n // the authoritative org id, so crash-recovered sessions heal it for free.\n const updates: FactorySessionState = { factoryProjectId: binding.factoryProjectId, factoryOrgId: binding.orgId };\n // Security posture first, from the binding row alone (no I/O): review-bound\n // sessions run against attacker-writable checkouts, so `untrustedCheckout`\n // must survive even if the enrichment lookups below fail transiently.\n if (binding.role === 'review') {\n updates.untrustedCheckout = true;\n }\n // Best-effort enrichment mirroring the start coordinator's original seed:\n // PR-sourced work items are untrusted regardless of role, and `baseRef`\n // restores the trusted instruction source for untrusted checkouts.\n try {\n const item = await options.storage.get({ orgId: binding.orgId, id: binding.workItemId });\n const foundSession = (await options.sessions?.getBySessionId(binding.sessionId)) ?? null;\n const sourceSession = foundSession?.orgId === binding.orgId ? foundSession : null;\n if (sourceSession) {\n updates.projectRepositoryId = sourceSession.projectRepositoryId;\n }\n const untrusted = updates.untrustedCheckout === true || item?.externalSource?.type === 'pull-request';\n if (untrusted) {\n updates.untrustedCheckout = true;\n const metadataBaseBranch = item?.metadata?.baseBranch;\n const baseRef =\n sourceSession?.baseBranch ||\n (typeof metadataBaseBranch === 'string' && metadataBaseBranch ? metadataBaseBranch : undefined);\n if (baseRef) updates.baseRef = baseRef;\n } else {\n // Record the trusted verdict explicitly so a healed session carries every\n // trust field; the prompt-time recovery check treats a missing flag as\n // \"not yet verified\" and would otherwise re-run on every prompt. Left\n // unset when enrichment fails so the next prompt retries the lookup.\n updates.untrustedCheckout = false;\n }\n } catch {\n // Enrichment is best-effort; the address itself only needs the binding.\n }\n try {\n await options.context.setState(updates);\n } catch {\n // State healing must never block tool registration on the recovered address.\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import type { MastraCodeState } from '@mastra/code-sdk/schema';
|
|
2
|
-
import type { AgentController
|
|
2
|
+
import type { AgentController } from '@mastra/core/agent-controller';
|
|
3
3
|
import type { BoardRegistry } from '../boards/index.js';
|
|
4
4
|
import type { AuditRecorder } from '../storage/domains/audit/domain.js';
|
|
5
5
|
import type { FactoryFeedReader } from '../storage/domains/comments/feed-context.js';
|
|
6
|
-
import type { FactoryDeferredDecisionRecord,
|
|
6
|
+
import type { FactoryDeferredDecisionRecord, WorkItemRow, WorkItemsStorage } from '../storage/domains/work-items/base.js';
|
|
7
7
|
import type { FactoryTransitionService } from './transition-service.js';
|
|
8
8
|
import type { FactoryCommitDecision } from './types.js';
|
|
9
9
|
type FactoryController = Pick<AgentController<MastraCodeState>, 'getSessionByResource' | 'listActiveThreadRuns'>;
|
|
10
|
-
type BoundDispatcherSession = Session<MastraCodeState>;
|
|
11
10
|
export interface FactoryBindingPreparationInput {
|
|
12
11
|
record: FactoryDeferredDecisionRecord;
|
|
13
12
|
item: WorkItemRow;
|
|
@@ -33,16 +32,6 @@ export interface FactoryDecisionDispatcherOptions {
|
|
|
33
32
|
}) => Promise<boolean>;
|
|
34
33
|
reconcileToolResults?: () => Promise<void>;
|
|
35
34
|
prepareBinding?: (input: FactoryBindingPreparationInput) => Promise<void>;
|
|
36
|
-
/**
|
|
37
|
-
* Re-applies the factory project's current observational-memory settings to a
|
|
38
|
-
* reused session before it runs. Fresh preparation hydrates these settings,
|
|
39
|
-
* but a reused binding keeps the models it was created with; without this a
|
|
40
|
-
* project whose OM models changed keeps observing with the stale ones.
|
|
41
|
-
*/
|
|
42
|
-
refreshManagedMemorySettings?: (input: {
|
|
43
|
-
binding: FactoryRunBindingRecord;
|
|
44
|
-
session: BoundDispatcherSession;
|
|
45
|
-
}) => Promise<void>;
|
|
46
35
|
primeCredentials?: (tenant: {
|
|
47
36
|
orgId: string;
|
|
48
37
|
userId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/rules/dispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../src/rules/dispatcher.ts"],"names":[],"mappings":"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"}
|
package/dist/rules/dispatcher.js
CHANGED
|
@@ -244,7 +244,6 @@ var FactoryDecisionDispatcher = class {
|
|
|
244
244
|
#autoApprovePlans;
|
|
245
245
|
#reconcileToolResults;
|
|
246
246
|
#prepareBinding;
|
|
247
|
-
#refreshManagedMemorySettings;
|
|
248
247
|
#primeCredentials;
|
|
249
248
|
#feedReader;
|
|
250
249
|
#dismissStaleReviews;
|
|
@@ -277,7 +276,6 @@ var FactoryDecisionDispatcher = class {
|
|
|
277
276
|
this.#autoApprovePlans = options.autoApprovePlans;
|
|
278
277
|
this.#reconcileToolResults = options.reconcileToolResults;
|
|
279
278
|
this.#prepareBinding = options.prepareBinding;
|
|
280
|
-
this.#refreshManagedMemorySettings = options.refreshManagedMemorySettings;
|
|
281
279
|
this.#primeCredentials = options.primeCredentials;
|
|
282
280
|
this.#feedReader = options.feedReader;
|
|
283
281
|
this.#dismissStaleReviews = options.dismissStaleReviews;
|
|
@@ -983,10 +981,6 @@ var FactoryDecisionDispatcher = class {
|
|
|
983
981
|
const session = await this.#controller.getSessionByResource(binding.resourceId);
|
|
984
982
|
if (!session) return void 0;
|
|
985
983
|
await this.#switchThread(session, binding);
|
|
986
|
-
await this.#refreshManagedMemorySettings?.({
|
|
987
|
-
binding,
|
|
988
|
-
session
|
|
989
|
-
});
|
|
990
984
|
return session;
|
|
991
985
|
}
|
|
992
986
|
/** Unset means off: a plan nobody asked us to answer is a plan someone should see. */
|