@mastra/factory 0.2.0 → 0.2.1-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/dist/capabilities/intake.d.ts +45 -0
- package/dist/capabilities/intake.d.ts.map +1 -1
- package/dist/factory.js +920 -549
- package/dist/factory.js.map +1 -1
- package/dist/index.js +920 -549
- package/dist/index.js.map +1 -1
- package/dist/integrations/github/integration.d.ts.map +1 -1
- package/dist/integrations/github/integration.js +126 -11
- package/dist/integrations/github/integration.js.map +1 -1
- package/dist/integrations/github/project-lock.d.ts +24 -2
- package/dist/integrations/github/project-lock.d.ts.map +1 -1
- package/dist/integrations/github/project-lock.js +43 -10
- package/dist/integrations/github/project-lock.js.map +1 -1
- package/dist/integrations/github/routes.js +41 -10
- package/dist/integrations/github/routes.js.map +1 -1
- package/dist/integrations/linear/agent-tools.js.map +1 -1
- package/dist/integrations/linear/integration.d.ts.map +1 -1
- package/dist/integrations/linear/integration.js +60 -1
- package/dist/integrations/linear/integration.js.map +1 -1
- package/dist/integrations/linear/routes.js.map +1 -1
- package/dist/integrations/platform/github/event-worker.d.ts.map +1 -1
- package/dist/integrations/platform/github/event-worker.js +7 -1
- package/dist/integrations/platform/github/event-worker.js.map +1 -1
- package/dist/integrations/platform/github/integration.d.ts.map +1 -1
- package/dist/integrations/platform/github/integration.js +104 -12
- package/dist/integrations/platform/github/integration.js.map +1 -1
- package/dist/integrations/platform/linear/integration.d.ts.map +1 -1
- package/dist/integrations/platform/linear/integration.js +91 -0
- package/dist/integrations/platform/linear/integration.js.map +1 -1
- package/dist/routes/fs.d.ts +16 -0
- package/dist/routes/fs.d.ts.map +1 -1
- package/dist/routes/fs.js +103 -3
- package/dist/routes/fs.js.map +1 -1
- package/dist/routes/oauth.js +564 -478
- package/dist/routes/oauth.js.map +1 -1
- package/dist/routes/projects.d.ts.map +1 -1
- package/dist/routes/projects.js +1 -0
- package/dist/routes/projects.js.map +1 -1
- package/dist/routes/surface.d.ts.map +1 -1
- package/dist/routes/surface.js +717 -526
- package/dist/routes/surface.js.map +1 -1
- package/dist/storage/domains/source-control/base.d.ts +0 -1
- package/dist/storage/domains/source-control/base.d.ts.map +1 -1
- package/dist/storage/domains/source-control/base.js +6 -7
- package/dist/storage/domains/source-control/base.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/integrations/platform/github/integration.ts","../../../../src/integrations/github/routes.ts","../../../../src/sandbox/fleet.ts","../../../../src/integrations/github/config.ts","../../../../src/integrations/github/pat.ts","../../../../src/integrations/github/project-lock.ts","../../../../src/integrations/github/sandbox.ts","../../../../src/integrations/github/subscriptions.ts","../../../../src/integrations/github/webhook.ts","../../../../src/integrations/github/session-subscriptions.ts","../../../../src/integrations/github/token-refresh.ts","../../../../src/integrations/platform/api-client.ts","../../../../src/integrations/platform/github/event-worker.ts"],"sourcesContent":["import type { RequestContext } from '@mastra/core/request-context';\nimport type { ApiRoute } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\nimport type { Context } from 'hono';\n\nimport type { IntegrationConnection } from '../../../capabilities/connection.js';\nimport type { CreateIntakeCommentInput, Intake, IntakeIssue, IntakeIssueDetail } from '../../../capabilities/intake.js';\nimport type {\n CreatePullRequestCommentInput,\n CreatePullRequestInput,\n CreateReviewCommentInput,\n CreateReviewInput,\n DeletePullRequestCommentInput,\n DismissReviewInput,\n ListPullRequestCommentsInput,\n ListPullRequestsInput,\n ListReviewCommentsInput,\n ListReviewsInput,\n MergePullRequestInput,\n PullRequest,\n PullRequestComment,\n PullRequestRef,\n Review,\n ReviewComment,\n ReviewRef,\n SubmitReviewInput,\n UpdatePullRequestCommentInput,\n UpdatePullRequestInput,\n UpdateReviewInput,\n UpdateReviewersInput,\n VersionControl,\n} from '../../../capabilities/version-control.js';\nimport type { IntegrationStorageHandle } from '../../../storage/domains/integrations/base.js';\nimport type {\n SourceControlInstallation,\n SourceControlStorageHandle,\n} from '../../../storage/domains/source-control/base.js';\nimport type { FactoryIntegration, IntegrationContext, IntegrationTools } from '../../base.js';\nimport type { GithubIntegration, GithubRepositoryPermission, RepoSummary } from '../../github/integration.js';\nimport { buildGithubRoutes } from '../../github/routes.js';\nimport {\n createGithubSubscriptionTools,\n parseCreatedPullRequest,\n subscribeCurrentSessionToPullRequest,\n} from '../../github/session-subscriptions.js';\nimport type { GithubSubscriptionStorage } from '../../github/subscriptions.js';\nimport {\n logPlatformInfo,\n logPlatformWarn,\n PlatformApiClient,\n PlatformApiError,\n platformApiClientConfigFromEnv,\n} from '../api-client.js';\nimport { PlatformGithubEventWorker } from './event-worker.js';\nimport type { PlatformGithubEventStorage } from './event-worker.js';\n\ntype GithubActor = { login: string; avatarUrl: string | null; htmlUrl: string | null } | null;\n\ntype PlatformGithubInstallation = {\n installationId: number;\n accountLogin: string;\n accountType: string;\n suspendedAt: string | null;\n usable: boolean;\n};\n\ntype PlatformGithubUserConnection = {\n connected: boolean;\n githubUsername: string | null;\n reason?: 'token-invalid' | 'no-accessible-installation' | 'missing-permissions' | 'verification-unavailable' | null;\n};\n\ntype GithubIssue = {\n number: number;\n state: 'open' | 'closed';\n title: string;\n body: string | null;\n htmlUrl: string;\n labels: string[];\n assignees: string[];\n commentCount: number;\n user: GithubActor;\n createdAt: string;\n updatedAt: string;\n};\n\ntype GithubComment = {\n id: number;\n body: string;\n htmlUrl: string;\n user: GithubActor;\n createdAt: string;\n updatedAt: string;\n};\n\ntype GithubPullRequest = {\n number: number;\n title: string;\n body: string | null;\n state: 'open' | 'closed';\n htmlUrl: string;\n merged: boolean;\n mergeable: boolean | null;\n draft: boolean;\n head: { ref: string; sha: string };\n base: { ref: string; repo: { id: number; fullName: string } };\n user: GithubActor;\n createdAt: string;\n updatedAt: string;\n};\n\ntype GithubReview = {\n id: number;\n htmlUrl: string | null;\n body: string | null;\n state: 'PENDING' | 'COMMENTED' | 'APPROVED' | 'CHANGES_REQUESTED' | 'DISMISSED';\n commitId: string | null;\n submittedAt: string | null;\n user: GithubActor;\n};\n\ntype GithubReviewComment = GithubComment & {\n path: string;\n line: number | null;\n side: 'LEFT' | 'RIGHT' | null;\n commitId: string;\n replyToId: number | null;\n};\n\nconst PAGE_SIZE = 30;\nconst API_PREFIX = '/v1/server';\nconst REPOSITORY_TOKEN_PERMISSIONS = {\n contents: 'write',\n issues: 'write',\n pull_requests: 'write',\n} as const;\n\nfunction loose(c: unknown): Context {\n return c as Context;\n}\n\nfunction routeBaseUrl(ctx: IntegrationContext, requestUrl: string): string {\n return (ctx.baseUrl || new URL(requestUrl).origin).replace(/\\/+$/, '');\n}\n\nexport class PlatformGithubIntegration implements FactoryIntegration {\n readonly id = 'github';\n readonly #client: PlatformApiClient;\n readonly #endpointHost: string;\n readonly #pollingEnabled: boolean;\n readonly #pollingIntervalMs: number | undefined;\n #storage: SourceControlStorageHandle | undefined;\n #integrationStorage: GithubSubscriptionStorage | undefined;\n\n readonly intake: Intake = {\n listSources: async ({ orgId, userId }) => {\n const installations = await this.#client.request<{\n installations: Array<{\n installationId: number;\n accountLogin: string;\n accountType: string;\n suspendedAt: string | null;\n usable: boolean;\n }>;\n }>('GET', `${API_PREFIX}/github-app/installations`);\n const usable = installations.installations.filter(\n installation => installation.usable && !installation.suspendedAt,\n );\n const repositories = await Promise.all(\n usable.map(async installation => {\n const storedInstallation = await this.versionControl.registerInstallation({\n orgId,\n userId,\n installation: {\n externalId: String(installation.installationId),\n accountName: installation.accountLogin,\n accountType: installation.accountType,\n },\n });\n const result = await this.#client.request<{\n repositories: Array<{\n id: number;\n fullName: string;\n private: boolean;\n defaultBranch: string;\n htmlUrl: string;\n }>;\n }>('GET', `${API_PREFIX}/github-app/installations/${installation.installationId}/repositories`);\n await this.versionControl.registerRepositories({\n orgId,\n installationId: storedInstallation.id,\n repositories: result.repositories.map(repository => ({\n externalId: String(repository.id),\n slug: repository.fullName,\n defaultBranch: repository.defaultBranch,\n metadata: { private: repository.private, url: repository.htmlUrl },\n })),\n });\n return result.repositories.map(repository => ({ repository, installation }));\n }),\n );\n return repositories.flat().map(({ repository, installation }) => ({\n id: repository.fullName,\n name: repository.fullName,\n type: 'repository',\n metadata: {\n installationId: installation.installationId,\n accountLogin: installation.accountLogin,\n accountType: installation.accountType,\n repositoryId: repository.id,\n defaultBranch: repository.defaultBranch,\n private: repository.private,\n url: repository.htmlUrl,\n },\n }));\n },\n listItems: async ({ sourceIds, cursor }) => {\n const page = parsePositiveCursor(cursor);\n const pages = await Promise.all(\n sourceIds.map(async sourceId => {\n const connection = { type: 'app-installation' as const, installationId: 1 };\n const [issues, pullRequests] = await Promise.all([\n this.#listIssues(connection, sourceId, page),\n this.#listPullRequests({ connection, sourceId, includeDrafts: false, cursor: String(page) }),\n ]);\n return {\n items: [\n ...issues.issues.map(issue => ({\n source: { type: 'issue', externalId: `${sourceId}:${issue.id}`, url: issue.url },\n sourceId,\n title: issue.title,\n status: issue.state ?? undefined,\n labels: issue.labels,\n assignee: issue.assignee,\n createdAt: issue.createdAt,\n updatedAt: issue.updatedAt,\n metadata: { repository: sourceId, number: Number(issue.id), author: issue.author },\n })),\n ...pullRequests.pullRequests.map(pullRequest => ({\n source: { type: 'pull-request', externalId: `${sourceId}:${pullRequest.id}`, url: pullRequest.url },\n sourceId,\n title: pullRequest.title,\n status: pullRequest.state,\n createdAt: pullRequest.createdAt,\n updatedAt: pullRequest.updatedAt,\n metadata: {\n repository: sourceId,\n number: Number(pullRequest.id),\n author: pullRequest.author,\n baseBranch: pullRequest.baseBranch,\n headBranch: pullRequest.headBranch,\n },\n })),\n ],\n hasNextPage: issues.nextCursor !== null || pullRequests.nextCursor !== null,\n };\n }),\n );\n return {\n items: pages.flatMap(result => result.items),\n nextCursor: pages.some(result => result.hasNextPage) ? String(page + 1) : null,\n };\n },\n listIssues: async input => {\n requireGithubConnection(input.connection);\n const sourceId = requireSingleSource(input.sourceIds, 'GitHub Intake requires exactly one repository source.');\n return this.#listIssues(input.connection, sourceId, parsePositiveCursor(input.cursor), input.labels);\n },\n getIssue: input => this.#getIssue(input.connection, input.sourceId, input.issueId),\n createComment: input => this.#createIssueComment(input),\n };\n\n readonly versionControl: VersionControl = {\n initialize: ({ storage }) => {\n this.#storage = storage;\n },\n registerInstallation: ({ orgId, userId, installation }) =>\n this.storage.installations.upsert({\n orgId,\n connectedByUserId: userId,\n externalId: installation.externalId,\n accountName: installation.accountName,\n accountType: installation.accountType,\n providerMetadata: installation.metadata,\n }),\n registerRepositories: ({ orgId, installationId, repositories }) =>\n Promise.all(\n repositories.map(repository =>\n this.storage.repositories.upsert({\n orgId,\n input: {\n installationId,\n externalId: repository.externalId,\n slug: repository.slug,\n defaultBranch: repository.defaultBranch,\n providerMetadata: repository.metadata,\n },\n }),\n ),\n ),\n getRepositoryAccess: async ({ orgId, repositoryId }) => {\n const repository = await this.storage.repositories.get({ orgId, id: repositoryId });\n if (!repository) throw new Error('Version-control repository not found.');\n const cloneUrl = `https://github.com/${repository.slug}.git`;\n const installation = await this.storage.installations.get({ orgId, id: repository.installationId });\n if (!installation) throw new Error('Version-control installation not found.');\n const installationId = parsePositiveInteger(installation.externalId);\n if (installationId === null) throw new Error('GitHub installation id is invalid.');\n const repositoryName = splitRepository(repository.slug).repo;\n const token = await this.#client.request<{ token: string }>(\n 'POST',\n `${API_PREFIX}/github-app/installations/${installationId}/token`,\n { repositories: [repositoryName], permissions: REPOSITORY_TOKEN_PERMISSIONS },\n );\n return {\n cloneUrl,\n authorization: { scheme: 'bearer', token: token.token },\n };\n },\n listPullRequests: input => this.#listPullRequests(input),\n getPullRequest: input => this.#getPullRequest(input),\n createPullRequest: input => this.#createPullRequest(input),\n updatePullRequest: input => this.#updatePullRequest(input),\n closePullRequest: input => this.#updatePullRequest({ ...input, state: 'closed' }),\n mergePullRequest: input => this.#mergePullRequest(input),\n listComments: input => this.#listComments(input),\n createComment: input => this.#createComment(input),\n updateComment: input => this.#updateComment(input),\n deleteComment: input => this.#deleteComment(input),\n listReviews: input => this.#listReviews(input),\n getReview: input => this.#getReview(input),\n createReview: input => this.#createReview(input),\n updateReview: input => this.#updateReview(input),\n submitReview: input => this.#submitReview(input),\n dismissReview: input => this.#dismissReview(input),\n deletePendingReview: input => this.#deletePendingReview(input),\n listReviewComments: input => this.#listReviewComments(input),\n createReviewComment: input => this.#createReviewComment(input),\n updateReviewComment: input => this.#updateReviewComment(input),\n deleteReviewComment: input => this.#deleteReviewComment(input),\n listRequestedReviewers: input => this.#requestedReviewers('GET', input),\n requestReviewers: input => this.#requestedReviewers('POST', input),\n removeRequestedReviewers: input => this.#requestedReviewers('DELETE', input),\n };\n\n constructor() {\n const config = platformApiClientConfigFromEnv();\n this.#client = new PlatformApiClient(config);\n this.#endpointHost = new URL(config.baseUrl).host;\n this.#pollingEnabled = process.env.MASTRA_PLATFORM_GITHUB_POLLING_ENABLED?.trim().toLowerCase() !== 'false';\n this.#pollingIntervalMs = optionalPositiveIntegerEnv('MASTRA_PLATFORM_GITHUB_POLLING_INTERVAL_MS');\n }\n\n get storage(): SourceControlStorageHandle {\n if (!this.#storage) throw new Error('PlatformGithubIntegration source-control storage has not been initialized.');\n return this.#storage;\n }\n\n get sourceControlStorage(): SourceControlStorageHandle {\n return this.storage;\n }\n\n get integrationStorage(): GithubSubscriptionStorage {\n if (!this.#integrationStorage) {\n throw new Error('PlatformGithubIntegration generic storage has not been initialized.');\n }\n return this.#integrationStorage;\n }\n\n initialize({ storage }: { storage: IntegrationStorageHandle }): void {\n this.#integrationStorage = storage as unknown as GithubSubscriptionStorage;\n logPlatformInfo('Platform GitHub integration initialized', {\n endpointHost: this.#endpointHost,\n pollingEnabled: this.#pollingEnabled,\n pollingIntervalMs: this.#pollingIntervalMs,\n });\n }\n\n routes(ctx: IntegrationContext): ApiRoute[] {\n return [\n this.#statusRoute(ctx),\n this.#connectRoute(ctx),\n this.#connectUserRoute(ctx),\n ...buildGithubRoutes({\n auth: ctx.auth,\n fleet: ctx.fleet,\n storage: ctx.factoryStorage,\n github: this as unknown as GithubIntegration,\n stateSigner: ctx.stateSigner,\n baseUrl: ctx.baseUrl,\n controller: ctx.controller,\n projects: ctx.storage.projects,\n emitAudit: ctx.hooks?.emitAudit,\n ingestFactoryEvent: ctx.hooks?.ingestGithubEvent,\n }).filter(\n route =>\n route.path !== '/web/github/status' &&\n route.path !== '/web/github/webhook' &&\n !route.path.startsWith('/auth/github/'),\n ),\n ];\n }\n\n #statusRoute(ctx: IntegrationContext): ApiRoute {\n return registerApiRoute('/web/github/status', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n await ctx.auth.ensureUser(loose(c));\n const tenant = ctx.auth.tenant(loose(c));\n if (!tenant) return c.json({ error: 'unauthorized', reason: 'auth_required' }, 401);\n if (!tenant.orgId) {\n return c.json({\n enabled: true,\n sandboxEnabled: ctx.fleet.enabled,\n organizationRequired: true,\n connected: false,\n installations: [],\n userConnected: false,\n userGithubUsername: null,\n reason: 'organization_required',\n diagnostics: this.diagnostics(),\n });\n }\n\n const [installations, userConnection] = await Promise.all([\n this.#syncInstallations(tenant.orgId, tenant.userId),\n this.#fetchUserConnection(tenant.userId),\n ]);\n return c.json({\n enabled: true,\n sandboxEnabled: ctx.fleet.enabled,\n connected: installations.length > 0,\n installations: installations.map(installation => ({\n installationId: Number(installation.externalId),\n accountLogin: installation.accountName,\n accountType: installation.accountType,\n })),\n userConnected: userConnection.connected,\n userGithubUsername: userConnection.githubUsername,\n reason: installations.length > 0 ? 'ready' : 'not_connected',\n diagnostics: this.diagnostics(),\n });\n },\n });\n }\n\n #connectRoute(ctx: IntegrationContext): ApiRoute {\n return registerApiRoute('/auth/github/connect', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n await ctx.auth.ensureUser(loose(c));\n const tenant = ctx.auth.tenant(loose(c));\n if (!tenant?.orgId) return c.json({ error: 'unauthorized' }, 401);\n\n const redirectTo = c.req.query('redirectTo') || c.req.query('return_to') || '/';\n const originator = routeBaseUrl(ctx, c.req.url);\n logPlatformInfo('Starting Platform GitHub connect flow', {\n orgId: tenant.orgId,\n redirectTo,\n originator,\n });\n const query = new URLSearchParams({\n action: 'install',\n redirectTo,\n originator,\n });\n const { url } = await this.#client.request<{ url: string }>(\n 'GET',\n `${API_PREFIX}/github-app/install-url?${query}`,\n );\n return c.redirect(url);\n },\n });\n }\n\n #connectUserRoute(ctx: IntegrationContext): ApiRoute {\n return registerApiRoute('/auth/github/connect-user', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n await ctx.auth.ensureUser(loose(c));\n const tenant = ctx.auth.tenant(loose(c));\n if (!tenant?.orgId) return c.json({ error: 'unauthorized' }, 401);\n\n const redirectTo = c.req.query('redirectTo') || c.req.query('return_to') || '/';\n const originator = routeBaseUrl(ctx, c.req.url);\n logPlatformInfo('Starting Platform GitHub user authorization flow', {\n orgId: tenant.orgId,\n redirectTo,\n originator,\n });\n const query = new URLSearchParams({\n userId: tenant.userId,\n redirectTo,\n originator,\n });\n const { url } = await this.#client.request<{ url: string }>(\n 'GET',\n `${API_PREFIX}/github-app/authenticate?${query}`,\n );\n return c.redirect(url);\n },\n });\n }\n\n /**\n * Personal GitHub connection status for the acting user. Returns\n * not-connected when the platform predates the user-connection endpoint.\n */\n async #fetchUserConnection(userId: string): Promise<PlatformGithubUserConnection> {\n try {\n const connection = await this.#client.request<PlatformGithubUserConnection>(\n 'GET',\n `${API_PREFIX}/github-app/user-connection?${new URLSearchParams({ userId })}`,\n );\n if (!connection.connected && connection.reason) {\n logPlatformWarn('Platform GitHub user connection verification failed', {\n userId,\n reason: connection.reason,\n });\n }\n return connection;\n } catch {\n return { connected: false, githubUsername: null };\n }\n }\n\n async #syncInstallations(orgId: string, userId: string): Promise<SourceControlInstallation[]> {\n const result = await this.#client.request<{ installations: PlatformGithubInstallation[] }>(\n 'GET',\n `${API_PREFIX}/github-app/installations`,\n );\n const usableInstallations = result.installations.filter(\n installation => installation.usable && !installation.suspendedAt,\n );\n return Promise.all(\n usableInstallations.map(installation =>\n this.versionControl.registerInstallation({\n orgId,\n userId,\n installation: {\n externalId: String(installation.installationId),\n accountName: installation.accountLogin,\n accountType: installation.accountType,\n },\n }),\n ),\n );\n }\n\n workers(ctx: IntegrationContext): PlatformGithubEventWorker[] {\n if (!this.#pollingEnabled) return [];\n if (!ctx.controller) {\n throw new Error('Platform GitHub event polling requires the mounted Mastra Code controller.');\n }\n return [\n new PlatformGithubEventWorker({\n client: this.#client,\n controller: ctx.controller,\n github: this,\n storage: ctx.storage.generic as unknown as PlatformGithubEventStorage,\n ingestFactoryEvent: ctx.hooks?.ingestGithubEvent,\n intervalMs: this.#pollingIntervalMs,\n }),\n ];\n }\n\n sessionTools({ requestContext }: { requestContext: RequestContext }): IntegrationTools {\n return createGithubSubscriptionTools(requestContext, this as unknown as GithubIntegration);\n }\n\n async postToolObserver({\n toolContext,\n requestContext,\n }: Parameters<NonNullable<FactoryIntegration['postToolObserver']>>[0]): Promise<void> {\n const pullRequestUrl = parseCreatedPullRequest(toolContext);\n if (!pullRequestUrl || !requestContext) return;\n await subscribeCurrentSessionToPullRequest(\n requestContext,\n pullRequestUrl,\n 'auto-gh-pr-create',\n this as unknown as GithubIntegration,\n );\n }\n\n diagnostics(): Record<string, unknown> {\n return {\n mode: 'platform',\n endpointHost: this.#endpointHost,\n polling: {\n enabled: this.#pollingEnabled,\n ...(this.#pollingIntervalMs === undefined ? {} : { intervalMs: this.#pollingIntervalMs }),\n },\n };\n }\n\n async getRepositoryCollaboratorPermission(\n _installationId: number,\n repoFullName: string,\n username: string,\n signal?: AbortSignal,\n ): Promise<GithubRepositoryPermission | undefined> {\n let repository: { owner: string; repo: string };\n try {\n repository = splitRepository(repoFullName);\n } catch {\n return undefined;\n }\n try {\n const result = await this.#client.request<{ permission: GithubRepositoryPermission }>(\n 'GET',\n `${API_PREFIX}/github/repos/${encodeURIComponent(repository.owner)}/${encodeURIComponent(repository.repo)}/collaborators/${encodeURIComponent(username)}/permission`,\n undefined,\n { signal },\n );\n return result.permission;\n } catch {\n return undefined;\n }\n }\n\n async listInstallationRepos(installationId: number): Promise<RepoSummary[]> {\n const result = await this.#client.request<{\n repositories: Array<{\n id: number;\n owner: string;\n name: string;\n fullName: string;\n private: boolean;\n defaultBranch: string;\n }>;\n }>('GET', `${API_PREFIX}/github-app/installations/${installationId}/repositories`);\n return result.repositories.map(repository => ({ ...repository, installationId }));\n }\n\n async mintInstallationToken(installationId: number): Promise<string> {\n const repositories = await this.listInstallationRepos(installationId);\n if (repositories.length === 0 || repositories.length > 10) {\n throw new Error('Platform GitHub token minting requires between one and ten installation repositories.');\n }\n const result = await this.#client.request<{ token: string }>(\n 'POST',\n `${API_PREFIX}/github-app/installations/${installationId}/token`,\n { repositories: repositories.map(repository => repository.name), permissions: REPOSITORY_TOKEN_PERMISSIONS },\n );\n return result.token;\n }\n\n async addIssueLabels(\n _installationId: number,\n sourceId: string,\n issueNumber: number,\n labels: string[],\n ): Promise<string[]> {\n const result = await this.#client.request<{ labels: string[] }>(\n 'POST',\n repositoryPath(sourceId, `issues/${issueNumber}/labels`),\n { labels },\n );\n return result.labels;\n }\n\n getInstallationOctokit(_installationId: number): ReturnType<GithubIntegration['getInstallationOctokit']> {\n return {\n pulls: {\n get: async ({ owner, repo, pull_number }: { owner: string; repo: string; pull_number: number }) => {\n const data = await this.#client.request<GithubPullRequest>(\n 'GET',\n repositoryPath(`${owner}/${repo}`, `pulls/${pull_number}`),\n );\n return { data: { base: { repo: { id: data.base.repo.id } } } };\n },\n },\n } as unknown as ReturnType<GithubIntegration['getInstallationOctokit']>;\n }\n\n async #listIssues(connection: IntegrationConnection, sourceId: string, page: number, labels?: string[]) {\n requireGithubConnection(connection);\n const path = repositoryPath(sourceId, 'issues');\n const query = new URLSearchParams({ state: 'open', page: String(page), per_page: String(PAGE_SIZE) });\n const normalizedLabels = normalizeLabels(labels);\n if (normalizedLabels.length > 0) query.set('label', normalizedLabels.join(','));\n const result = await this.#client.request<{ issues: GithubIssue[] }>('GET', `${path}?${query}`);\n return {\n issues: result.issues.map(issue => parseIntakeIssue(sourceId, issue)),\n nextCursor: result.issues.length === PAGE_SIZE ? String(page + 1) : null,\n };\n }\n\n async #getIssue(connection: IntegrationConnection, sourceId: string | undefined, issueId: string) {\n requireGithubConnection(connection);\n const repository = requireSource(sourceId, 'GitHub Intake requires a repository source.');\n const issueNumber = requirePositiveId(issueId, 'issue');\n try {\n const [issue, comments] = await Promise.all([\n this.#client.request<GithubIssue>('GET', repositoryPath(repository, `issues/${issueNumber}`)),\n this.#client.request<{ comments: GithubComment[] }>(\n 'GET',\n `${repositoryPath(repository, `issues/${issueNumber}/comments`)}?per_page=100`,\n ),\n ]);\n return parseIntakeIssueDetail(repository, issue, comments.comments);\n } catch (error) {\n if (isNotFound(error)) return null;\n throw error;\n }\n }\n\n async #createIssueComment(input: CreateIntakeCommentInput) {\n requireGithubConnection(input.connection);\n const repository = requireSource(input.sourceId, 'GitHub Intake requires a repository source.');\n const issueNumber = requirePositiveId(input.issueId, 'issue');\n try {\n const comment = await this.#client.request<GithubComment>(\n 'POST',\n repositoryPath(repository, `issues/${issueNumber}/comments`),\n { body: input.body },\n { actingUserId: input.actingUserId },\n );\n return { id: String(comment.id), url: comment.htmlUrl };\n } catch (error) {\n if (isNotFound(error)) return null;\n throw error;\n }\n }\n\n async #listPullRequests(input: ListPullRequestsInput) {\n requireGithubConnection(input.connection);\n const page = parsePositiveCursor(input.cursor);\n const query = new URLSearchParams({\n state: input.state ?? 'open',\n page: String(page),\n per_page: String(PAGE_SIZE),\n });\n const result = await this.#client.request<{ pullRequests: GithubPullRequest[] }>(\n 'GET',\n `${repositoryPath(input.sourceId, 'pulls')}?${query}`,\n );\n return {\n pullRequests: result.pullRequests\n .filter(pullRequest => input.includeDrafts !== false || !pullRequest.draft)\n .map(parsePullRequest),\n nextCursor: result.pullRequests.length === PAGE_SIZE ? String(page + 1) : null,\n };\n }\n\n async #getPullRequest(input: PullRequestRef) {\n try {\n return parsePullRequest(\n await this.#client.request<GithubPullRequest>('GET', pullRequestPath(input, input.pullRequestId)),\n );\n } catch (error) {\n if (isNotFound(error)) return null;\n throw error;\n }\n }\n\n async #createPullRequest(input: CreatePullRequestInput) {\n requireGithubConnection(input.connection);\n const result = await this.#client.request<GithubPullRequest>(\n 'POST',\n repositoryPath(input.sourceId, 'pulls'),\n {\n head: input.headBranch,\n base: input.baseBranch,\n title: input.title,\n body: input.body,\n draft: input.draft,\n },\n { actingUserId: input.actingUserId },\n );\n return parsePullRequest(result);\n }\n\n async #updatePullRequest(input: UpdatePullRequestInput) {\n const result = await this.#client.request<GithubPullRequest>(\n 'PATCH',\n pullRequestPath(input, input.pullRequestId),\n {\n title: input.title,\n body: input.body === null ? '' : input.body,\n base: input.baseBranch,\n state: input.state,\n },\n { actingUserId: input.actingUserId },\n );\n return parsePullRequest(result);\n }\n\n #mergePullRequest(input: MergePullRequestInput) {\n return this.#client.request<{ merged: boolean; message: string; sha: string | null }>(\n 'PUT',\n `${pullRequestPath(input, input.pullRequestId)}/merge`,\n { commitTitle: input.commitTitle, commitMessage: input.commitMessage, method: input.method },\n { actingUserId: input.actingUserId },\n );\n }\n\n async #listComments(input: ListPullRequestCommentsInput) {\n const page = parsePositiveCursor(input.cursor);\n const result = await this.#client.request<{ comments: GithubComment[] }>(\n 'GET',\n `${repositoryPath(input.sourceId, `issues/${requirePositiveId(input.pullRequestId, 'pull request')}/comments`)}?page=${page}&per_page=${PAGE_SIZE}`,\n );\n return {\n comments: result.comments.map(parseComment),\n nextCursor: result.comments.length === PAGE_SIZE ? String(page + 1) : null,\n };\n }\n\n async #createComment(input: CreatePullRequestCommentInput) {\n const comment = await this.#client.request<GithubComment>(\n 'POST',\n repositoryPath(input.sourceId, `issues/${requirePositiveId(input.pullRequestId, 'pull request')}/comments`),\n { body: input.body },\n { actingUserId: input.actingUserId },\n );\n return parseComment(comment);\n }\n\n async #updateComment(input: UpdatePullRequestCommentInput) {\n requireGithubConnection(input.connection);\n const comment = await this.#client.request<GithubComment>(\n 'PATCH',\n repositoryPath(input.sourceId, `issues/comments/${requirePositiveId(input.commentId, 'comment')}`),\n { body: input.body },\n { actingUserId: input.actingUserId },\n );\n return parseComment(comment);\n }\n\n async #deleteComment(input: DeletePullRequestCommentInput) {\n requireGithubConnection(input.connection);\n await this.#client.request<void>(\n 'DELETE',\n repositoryPath(input.sourceId, `issues/comments/${requirePositiveId(input.commentId, 'comment')}`),\n undefined,\n { actingUserId: input.actingUserId },\n );\n }\n\n async #listReviews(input: ListReviewsInput) {\n const page = parsePositiveCursor(input.cursor);\n const result = await this.#client.request<{ reviews: GithubReview[] }>(\n 'GET',\n `${pullRequestPath(input, input.pullRequestId)}/reviews?page=${page}&per_page=${PAGE_SIZE}`,\n );\n return {\n reviews: result.reviews.map(parseReview),\n nextCursor: result.reviews.length === PAGE_SIZE ? String(page + 1) : null,\n };\n }\n\n async #getReview(input: ReviewRef) {\n try {\n return parseReview(\n await this.#client.request<GithubReview>(\n 'GET',\n `${pullRequestPath(input, input.pullRequestId)}/reviews/${requirePositiveId(input.reviewId, 'review')}`,\n ),\n );\n } catch (error) {\n if (isNotFound(error)) return null;\n throw error;\n }\n }\n\n async #createReview(input: CreateReviewInput) {\n const review = await this.#client.request<GithubReview>(\n 'POST',\n `${pullRequestPath(input, input.pullRequestId)}/reviews`,\n { body: input.body, commitId: input.commitId, event: input.event ? reviewEvent(input.event) : undefined },\n { actingUserId: input.actingUserId },\n );\n return parseReview(review);\n }\n\n async #updateReview(input: UpdateReviewInput) {\n const review = await this.#client.request<GithubReview>(\n 'PUT',\n `${pullRequestPath(input, input.pullRequestId)}/reviews/${requirePositiveId(input.reviewId, 'review')}`,\n { body: input.body },\n { actingUserId: input.actingUserId },\n );\n return parseReview(review);\n }\n\n async #submitReview(input: SubmitReviewInput) {\n const review = await this.#client.request<GithubReview>(\n 'POST',\n `${pullRequestPath(input, input.pullRequestId)}/reviews/${requirePositiveId(input.reviewId, 'review')}/events`,\n { body: input.body, event: reviewEvent(input.event) },\n { actingUserId: input.actingUserId },\n );\n return parseReview(review);\n }\n\n async #dismissReview(input: DismissReviewInput) {\n const review = await this.#client.request<GithubReview>(\n 'PUT',\n `${pullRequestPath(input, input.pullRequestId)}/reviews/${requirePositiveId(input.reviewId, 'review')}/dismissals`,\n { message: input.message },\n { actingUserId: input.actingUserId },\n );\n return parseReview(review);\n }\n\n async #deletePendingReview(input: ReviewRef) {\n await this.#client.request<void>(\n 'DELETE',\n `${pullRequestPath(input, input.pullRequestId)}/reviews/${requirePositiveId(input.reviewId, 'review')}`,\n undefined,\n { actingUserId: input.actingUserId },\n );\n }\n\n async #listReviewComments(input: ListReviewCommentsInput) {\n const page = parsePositiveCursor(input.cursor);\n const result = await this.#client.request<{ comments: GithubReviewComment[] }>(\n 'GET',\n `${pullRequestPath(input, input.pullRequestId)}/comments?page=${page}&per_page=${PAGE_SIZE}`,\n );\n return {\n comments: result.comments.map(parseReviewComment),\n nextCursor: result.comments.length === PAGE_SIZE ? String(page + 1) : null,\n };\n }\n\n async #createReviewComment(input: CreateReviewCommentInput) {\n let body: Record<string, unknown>;\n if (input.replyToId !== undefined) {\n body = { body: input.body, replyToId: requirePositiveId(input.replyToId, 'review comment') };\n } else {\n if (!input.commitId || !input.path || input.line === undefined || !input.side) {\n throw new Error('A review comment requires commitId, path, line, and side unless it is a reply.');\n }\n body = {\n body: input.body,\n commitId: input.commitId,\n path: input.path,\n line: input.line,\n side: input.side.toUpperCase(),\n startLine: input.startLine,\n startSide: input.startSide?.toUpperCase(),\n };\n }\n return parseReviewComment(\n await this.#client.request<GithubReviewComment>(\n 'POST',\n `${pullRequestPath(input, input.pullRequestId)}/comments`,\n body,\n { actingUserId: input.actingUserId },\n ),\n );\n }\n\n async #updateReviewComment(input: UpdatePullRequestCommentInput) {\n requireGithubConnection(input.connection);\n return parseReviewComment(\n await this.#client.request<GithubReviewComment>(\n 'PATCH',\n repositoryPath(input.sourceId, `pulls/comments/${requirePositiveId(input.commentId, 'review comment')}`),\n { body: input.body },\n { actingUserId: input.actingUserId },\n ),\n );\n }\n\n async #deleteReviewComment(input: DeletePullRequestCommentInput) {\n requireGithubConnection(input.connection);\n await this.#client.request<void>(\n 'DELETE',\n repositoryPath(input.sourceId, `pulls/comments/${requirePositiveId(input.commentId, 'review comment')}`),\n undefined,\n { actingUserId: input.actingUserId },\n );\n }\n\n #requestedReviewers(method: 'GET' | 'POST' | 'DELETE', input: UpdateReviewersInput) {\n requireGithubConnection(input.connection);\n return this.#client.request<{ users: string[]; teams: string[] }>(\n method,\n `${pullRequestPath(input, input.pullRequestId)}/requested-reviewers`,\n method === 'GET' ? undefined : { users: input.users, teams: input.teams },\n method === 'GET' ? undefined : { actingUserId: input.actingUserId },\n );\n }\n}\n\nfunction repositoryPath(sourceId: string, suffix: string): string {\n const { owner, repo } = splitRepository(sourceId);\n return `${API_PREFIX}/github/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/${suffix}`;\n}\n\nfunction pullRequestPath(\n input: { connection: IntegrationConnection; sourceId: string },\n pullRequestId: string,\n): string {\n requireGithubConnection(input.connection);\n return repositoryPath(input.sourceId, `pulls/${requirePositiveId(pullRequestId, 'pull request')}`);\n}\n\nfunction splitRepository(sourceId: string): { owner: string; repo: string } {\n const slash = sourceId.indexOf('/');\n if (slash <= 0 || slash === sourceId.length - 1) {\n throw new Error('GitHub capabilities require an owner/repository source.');\n }\n return { owner: sourceId.slice(0, slash), repo: sourceId.slice(slash + 1) };\n}\n\nfunction parseIntakeIssue(sourceId: string, issue: GithubIssue): IntakeIssue {\n return {\n id: String(issue.number),\n identifier: `#${issue.number}`,\n title: issue.title,\n url: issue.htmlUrl,\n author: issue.user?.login ?? null,\n state: issue.state,\n stateType: issue.state,\n priority: null,\n assignee: issue.assignees[0] ?? null,\n source: sourceId,\n labels: issue.labels,\n commentCount: issue.commentCount,\n createdAt: issue.createdAt,\n updatedAt: issue.updatedAt,\n };\n}\n\nfunction parseIntakeIssueDetail(sourceId: string, issue: GithubIssue, comments: GithubComment[]): IntakeIssueDetail {\n return {\n ...parseIntakeIssue(sourceId, issue),\n description: issue.body?.trim() ? issue.body : null,\n comments: comments.map(comment => ({\n author: comment.user?.login ?? null,\n body: comment.body,\n createdAt: comment.createdAt,\n })),\n };\n}\n\nfunction parsePullRequest(pullRequest: GithubPullRequest): PullRequest {\n return {\n id: String(pullRequest.number),\n title: pullRequest.title,\n url: pullRequest.htmlUrl,\n author: pullRequest.user?.login ?? null,\n body: pullRequest.body?.trim() ? pullRequest.body : null,\n state: pullRequest.state,\n draft: pullRequest.draft,\n merged: pullRequest.merged,\n mergeable: pullRequest.mergeable,\n baseBranch: pullRequest.base.ref,\n headBranch: pullRequest.head.ref,\n headSha: pullRequest.head.sha,\n createdAt: pullRequest.createdAt,\n updatedAt: pullRequest.updatedAt,\n };\n}\n\nfunction parseComment(comment: GithubComment): PullRequestComment {\n return {\n id: String(comment.id),\n url: comment.htmlUrl,\n author: comment.user?.login ?? null,\n body: comment.body,\n createdAt: comment.createdAt,\n updatedAt: comment.updatedAt,\n };\n}\n\nfunction parseReview(review: GithubReview): Review {\n const states: Record<GithubReview['state'], Review['state']> = {\n PENDING: 'pending',\n COMMENTED: 'commented',\n APPROVED: 'approved',\n CHANGES_REQUESTED: 'changes-requested',\n DISMISSED: 'dismissed',\n };\n return {\n id: String(review.id),\n url: review.htmlUrl,\n author: review.user?.login ?? null,\n body: review.body?.trim() ? review.body : null,\n state: states[review.state],\n commitId: review.commitId,\n submittedAt: review.submittedAt,\n };\n}\n\nfunction parseReviewComment(comment: GithubReviewComment): ReviewComment {\n return {\n ...parseComment(comment),\n path: comment.path,\n line: comment.line,\n side: comment.side?.toLowerCase() as 'left' | 'right' | null,\n commitId: comment.commitId,\n replyToId: comment.replyToId === null ? null : String(comment.replyToId),\n };\n}\n\nfunction requireGithubConnection(connection: IntegrationConnection): void {\n if (connection.type !== 'app-installation' && connection.type !== 'oauth') {\n throw new Error('GitHub capabilities require a GitHub connection.');\n }\n}\n\nfunction requireSingleSource(sourceIds: string[], message: string): string {\n if (sourceIds.length !== 1) throw new Error(message);\n return sourceIds[0]!;\n}\n\nfunction requireSource(sourceId: string | undefined, message: string): string {\n if (!sourceId) throw new Error(message);\n return sourceId;\n}\n\nfunction normalizeLabels(labels: string[] | undefined): string[] {\n return [...new Set((labels ?? []).map(label => label.trim()).filter(Boolean))];\n}\n\nfunction parsePositiveCursor(cursor: string | undefined): number {\n if (cursor === undefined) return 1;\n const parsed = parsePositiveInteger(cursor);\n if (parsed === null) throw new Error('GitHub cursor must be a positive page number.');\n return parsed;\n}\n\nfunction parsePositiveInteger(value: string): number | null {\n if (!/^\\d+$/.test(value)) return null;\n const parsed = Number(value);\n return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : null;\n}\n\nfunction optionalPositiveIntegerEnv(name: 'MASTRA_PLATFORM_GITHUB_POLLING_INTERVAL_MS'): number | undefined {\n const value = process.env[name]?.trim();\n if (!value) return undefined;\n const parsed = parsePositiveInteger(value);\n if (parsed === null) throw new Error(`${name} must be a positive integer.`);\n return parsed;\n}\n\nfunction requirePositiveId(value: string, resource: string): number {\n const parsed = parsePositiveInteger(value);\n if (parsed === null) throw new Error(`GitHub ${resource} id must be a positive integer.`);\n return parsed;\n}\n\nfunction reviewEvent(event: 'approve' | 'request-changes' | 'comment') {\n if (event === 'approve') return 'APPROVE' as const;\n if (event === 'request-changes') return 'REQUEST_CHANGES' as const;\n return 'COMMENT' as const;\n}\n\nfunction isNotFound(error: unknown): boolean {\n return error instanceof PlatformApiError && error.status === 404;\n}\n","/**\n * Mastra `apiRoutes` for the GitHub App project feature.\n *\n * Registered alongside the other `/web/*` routes, behind the host auth gate.\n * Every route additionally re-checks the authenticated user via the injected\n * `RouteAuth` seam and scopes all rows by that user's stable id, so a user can\n * only ever see and operate on their own installations and projects.\n *\n * When the feature is disabled (`isGithubFeatureEnabled()` false), `buildGithubRoutes`\n * returns only `GET /web/github/status`, which reports `enabled:false`\n * so the SPA can cleanly hide all GitHub UI.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type { MountedMastraCode } from '@mastra/code-sdk';\nimport type { ApiRoute } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\nimport type { FactoryStorage } from '@mastra/core/storage';\nimport type { Context } from 'hono';\nimport { streamSSE } from 'hono/streaming';\nimport type { RouteAuth } from '../../routes/route.js';\nimport { SandboxBudgetError } from '../../sandbox/fleet.js';\nimport type { MaterializationSandbox, PrepareProgress, ProgressFn, SandboxFleet } from '../../sandbox/fleet.js';\nimport type { StateSigner } from '../../state-signing.js';\nimport type { AuditEmitter } from '../../storage/domains/audit/domain.js';\nimport type { FactoryProjectsStorage } from '../../storage/domains/projects/base.js';\nimport type {\n ProjectRepository,\n ProjectRepositorySandbox,\n ProjectSourceControlConnection,\n SourceControlInstallation,\n SourceControlRepository,\n} from '../../storage/domains/source-control/base.js';\nimport { getGithubFeatureDiagnostics, isGithubFeatureEnabled } from './config.js';\nimport type { GithubIntegration } from './integration.js';\nimport { clearGithubPat, getGithubPat, getGithubPatStatus, setGithubPat } from './pat.js';\nimport type { GithubPatKind } from './pat.js';\nimport { withProjectLock } from './project-lock.js';\n\nimport {\n commitAll,\n computeWorktreePath,\n ensureProjectSandbox,\n isValidGitRef as isValidGitRefSandbox,\n materializeRepo,\n MaterializeError,\n pushBranch,\n teardownProjectSandbox,\n WorktreeError,\n} from './sandbox.js';\nimport type { GitIdentity } from './sandbox.js';\nimport { listPullRequestSubscriptionsForThread, subscribeToPullRequest } from './subscriptions.js';\nimport { handleGithubWebhook } from './webhook.js';\nimport type { GithubIssueTriageRunInput, GithubIssueTriageRunResult, ParsedGithubWebhook } from './webhook.js';\n\n/**\n * Loose Hono context accepted by the shared GitHub route helpers. The\n * `registerApiRoute` handlers receive a path-parameterized context whose\n * `HonoRequest` literal-path generics are invariant and don't flow into a\n * shared helper signature. The helpers only ever touch cookies/query/tenant, so\n * we erase the path to a plain `Context` at the call boundary via `loose()`.\n */\ntype RouteContext = Context;\n\n/** Erase a route handler's path-parameterized context to a plain `Context`. */\nfunction loose(c: unknown): RouteContext {\n return c as RouteContext;\n}\n\nexport interface MountGithubRoutesOptions {\n /** Host auth seam — resolves the signed-in user/tenant for each request. */\n auth: RouteAuth;\n /**\n * Sandbox fleet for per-project sandboxes. A fleet constructed without a\n * machine config reports `enabled: false` and the sandbox-backed routes\n * respond 503.\n */\n fleet: SandboxFleet;\n /**\n * Factory storage backend. Supplies the cross-replica `withDistributedLock`\n * capability for git write routes and the `appDbConfigured` diagnostic.\n */\n storage?: FactoryStorage;\n /**\n * The GitHub App integration the handlers operate on (Octokit access, token\n * minting, OAuth URLs). Normally supplied by `GithubIntegration.routes()`;\n * when absent, only the disabled `status` route is served.\n */\n github?: GithubIntegration;\n /**\n * Shared OAuth/install `state` signer (created once per boot by the\n * factory). Required for the OAuth/install flow; when absent, only the\n * disabled `status` route is served.\n */\n stateSigner?: StateSigner;\n /**\n * Absolute base URL of the web server (e.g. `http://localhost:4111`), used to\n * build the OAuth/install redirect URI when one isn't explicitly configured.\n */\n baseUrl?: string;\n /** Explicit OAuth callback URI; defaults to `<baseUrl>/auth/github/callback`. */\n redirectUri?: string;\n /** Controller used to route verified webhook notifications to exact subscribed sessions. */\n controller?: MountedMastraCode['controller'];\n /** Run seam used by GitHub webhooks and manual Intake triage. */\n runIssueTriage?: (input: GithubIssueTriageRunInput) => Promise<GithubIssueTriageRunResult>;\n /** Best-effort audit emission supplied by the factory-owned audit domain. */\n emitAudit?: AuditEmitter['emit'];\n /** Factory projects domain — resolves a project's default triage model. */\n projects?: FactoryProjectsStorage;\n /** Authoritative Factory rule ingress for normalized, signature-verified GitHub deliveries. */\n ingestFactoryEvent?: (event: ParsedGithubWebhook) => Promise<unknown>;\n}\n\n/**\n * Resolve the Factory project's default model for a triage run. Best-effort:\n * a missing project or an uninitialized storage domain simply means \"no\n * default\", never a failed run.\n */\nasync function resolveFactoryDefaultModelId(\n projects: FactoryProjectsStorage | undefined,\n factoryProjectId: string | undefined,\n): Promise<string | undefined> {\n if (!projects || !factoryProjectId) return undefined;\n try {\n const project = await projects.getById({ id: factoryProjectId });\n return project?.defaultModelId ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction pullRequestNumberFromUrl(value: string, expectedRepo: string): number | undefined {\n try {\n const url = new URL(value);\n const match = url.pathname.match(/^\\/([^/]+\\/[^/]+)\\/pull\\/(\\d+)\\/?$/);\n if (\n url.protocol !== 'https:' ||\n url.hostname !== 'github.com' ||\n match?.[1]?.toLowerCase() !== expectedRepo.toLowerCase()\n ) {\n return undefined;\n }\n const number = Number(match[2]);\n return Number.isInteger(number) && number > 0 ? number : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction isCanonicalGithubIssueUrl(value: string, repoFullName: string, issueNumber: number): boolean {\n try {\n const url = new URL(value);\n const [owner, repo] = repoFullName.split('/');\n return (\n url.protocol === 'https:' &&\n url.hostname === 'github.com' &&\n url.pathname === `/${owner}/${repo}/issues/${issueNumber}` &&\n url.search === '' &&\n url.hash === ''\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Validate a git branch/ref name against a strict whitelist. The value is later\n * interpolated into a shell `git clone --branch` command, so it must never\n * contain shell metacharacters. We accept only git-ref-safe characters and\n * reject anything else rather than relying on shell quoting alone.\n */\nfunction isValidGitRef(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0 && value.length <= 255 && /^[A-Za-z0-9_./-]+$/.test(value);\n}\n\n/**\n * Resolve the org-scoped tenant for a GitHub request. GitHub project features\n * are org-owned, so they require both a signed-in user and a WorkOS\n * organization. Returns the `(orgId, userId)` tenant (with `orgId` narrowed to a\n * non-null string) or a ready-to-return error response: 401 when unauthenticated,\n * 403 when the user has no organization (personal account).\n *\n * Resolves the session from the request cookie itself (via `auth.ensureUser`)\n * instead of relying on the auth gate's context stash: on platform deploys\n * custom `apiRoutes` run on an isolated sub-app context where the gate's\n * `c.set(...)` is invisible. When the gate stash IS visible (local Hono\n * server), `auth.ensureUser` returns the cached user and this is a no-op.\n */\nasync function resolveOrgTenant(\n c: RouteContext,\n auth: RouteAuth,\n): Promise<{ tenant: { orgId: string; userId: string } } | { response: Response }> {\n await auth.ensureUser(c);\n const tenant = auth.tenant(c);\n if (!tenant) return { response: c.json({ error: 'unauthorized' }, 401) };\n if (!tenant.orgId) {\n return {\n response: c.json(\n {\n error: 'organization_required',\n message: 'GitHub projects require a WorkOS organization. Personal accounts cannot connect repositories.',\n },\n 403,\n ),\n };\n }\n return { tenant: { orgId: tenant.orgId, userId: tenant.userId } };\n}\n\n/**\n * Parse a 1-based `page` query param. Missing means page 1; anything that is\n * not a small positive integer is rejected (`null`).\n */\nfunction parseListPage(raw: string | undefined): number | null {\n if (raw === undefined) return 1;\n if (!/^\\d{1,5}$/.test(raw)) return null;\n const page = Number(raw);\n return page >= 1 ? page : null;\n}\n\nconst VALID_ISSUE_LABEL_FILTERS = new Set(['auto-triaged', 'needs-approval']);\n\nfunction parseIssueLabelFilter(raw: string | undefined): string | undefined | null {\n if (raw === undefined || raw === '') return undefined;\n if (VALID_ISSUE_LABEL_FILTERS.has(raw)) return raw;\n return null;\n}\n\nfunction parseIssueNumberParam(raw: string | undefined): number | null {\n if (!raw || !/^\\d{1,10}$/.test(raw)) return null;\n const issueNumber = Number(raw);\n return Number.isSafeInteger(issueNumber) && issueNumber > 0 ? issueNumber : null;\n}\n\nfunction parseStringList(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.filter((item): item is string => typeof item === 'string' && item.length > 0);\n}\n\ninterface ResolvedProjectRepository extends ProjectRepository {\n connection: ProjectSourceControlConnection;\n installation: SourceControlInstallation;\n repository: SourceControlRepository;\n factoryProjectId: string;\n defaultBranch: string;\n}\n\nasync function resolveProjectRepository(args: {\n github: GithubIntegration;\n orgId: string;\n projectRepositoryId: string;\n}): Promise<ResolvedProjectRepository | null> {\n const projectRepository = await args.github.sourceControlStorage.projectRepositories.get({\n orgId: args.orgId,\n id: args.projectRepositoryId,\n });\n if (!projectRepository) return null;\n const connection = await args.github.sourceControlStorage.connections.get({\n orgId: args.orgId,\n id: projectRepository.connectionId,\n });\n if (!connection) return null;\n const repository = await args.github.sourceControlStorage.repositories.get({\n orgId: args.orgId,\n id: projectRepository.repositoryId,\n });\n if (!repository) return null;\n const installation = await args.github.sourceControlStorage.installations.get({\n orgId: args.orgId,\n id: connection.installationId,\n });\n if (!installation) return null;\n return {\n ...projectRepository,\n connection,\n installation,\n repository,\n factoryProjectId: connection.factoryProjectId,\n defaultBranch: projectRepository.branch ?? repository.defaultBranch,\n };\n}\n\nfunction polledIssueEvent(\n project: ResolvedProjectRepository,\n issue: {\n number: number;\n title: string;\n url: string;\n author: string | null;\n labels: string[];\n createdAt: string;\n },\n): ParsedGithubWebhook {\n const repositoryId = Number(project.repository.externalId);\n return {\n event: 'issues',\n deliveryId: `poll:${repositoryId}:issue:${issue.number}:${issue.createdAt}`,\n payload: {\n action: 'opened',\n installation: { id: Number(project.installation.externalId) },\n repository: { id: repositoryId, full_name: project.repository.slug },\n sender: { login: issue.author ?? '__unknown__' },\n issue: {\n number: issue.number,\n title: issue.title,\n html_url: issue.url,\n created_at: issue.createdAt,\n labels: issue.labels.map(name => ({ name })),\n },\n },\n };\n}\n\nfunction polledPullRequestEvent(\n project: ResolvedProjectRepository,\n pullRequest: {\n number: number;\n title: string;\n url: string;\n author: string | null;\n headBranch: string;\n baseBranch: string;\n createdAt: string;\n },\n): ParsedGithubWebhook {\n const repositoryId = Number(project.repository.externalId);\n return {\n event: 'pull_request',\n deliveryId: `poll:${repositoryId}:pull-request:${pullRequest.number}:${pullRequest.createdAt}`,\n payload: {\n action: 'opened',\n installation: { id: Number(project.installation.externalId) },\n repository: { id: repositoryId, full_name: project.repository.slug },\n sender: { login: pullRequest.author ?? '__unknown__' },\n pull_request: {\n number: pullRequest.number,\n title: pullRequest.title,\n html_url: pullRequest.url,\n created_at: pullRequest.createdAt,\n state: 'open',\n merged: false,\n head: { ref: pullRequest.headBranch },\n base: { ref: pullRequest.baseBranch },\n },\n },\n };\n}\n\nasync function ingestPolledEvents(\n events: ParsedGithubWebhook[],\n ingestFactoryEvent: MountGithubRoutesOptions['ingestFactoryEvent'],\n): Promise<void> {\n if (!ingestFactoryEvent) return;\n const results = await Promise.allSettled(events.map(event => ingestFactoryEvent(event)));\n const rejected = results.find((result): result is PromiseRejectedResult => result.status === 'rejected');\n if (rejected) throw rejected.reason;\n}\n\n/**\n * Build the GitHub routes as Mastra `apiRoutes`. When the feature is disabled,\n * returns only the `status` route so the SPA can detect the disabled state.\n */\nexport function buildGithubRoutes(options: MountGithubRoutesOptions): ApiRoute[] {\n const routes: ApiRoute[] = [];\n const { auth, fleet, storage, github, stateSigner, emitAudit } = options;\n const diagnostics = () =>\n getGithubFeatureDiagnostics({ github, auth, appDbConfigured: storage !== undefined, stateSigner, fleet });\n\n // The status route is always registered so the SPA can detect the disabled state.\n routes.push(\n registerApiRoute('/web/github/status', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n if (!isGithubFeatureEnabled({ github, auth }) || !github || !stateSigner) {\n return c.json({\n enabled: false,\n connected: false,\n installations: [],\n reason: 'missing_config',\n diagnostics: diagnostics(),\n });\n }\n // Resolve the session from the request cookie: on platform deploys custom\n // apiRoutes run on an isolated context where the gate's stash is invisible.\n await auth.ensureUser(loose(c));\n const tenant = auth.tenant(loose(c));\n if (!tenant) return c.json({ error: 'unauthorized', reason: 'auth_required' }, 401);\n\n // Org-scoped: personal (no-org) users have GitHub projects disabled. Report\n // enabled (so the SPA can show the org-required hint) but never connected.\n if (!tenant.orgId) {\n return c.json({\n enabled: true,\n sandboxEnabled: fleet.enabled,\n organizationRequired: true,\n connected: false,\n installations: [],\n reason: 'organization_required',\n diagnostics: diagnostics(),\n });\n }\n\n const rows = options.github\n ? await options.github.sourceControlStorage.installations.list({ orgId: tenant.orgId })\n : [];\n\n const connected = rows.length > 0;\n return c.json({\n enabled: true,\n sandboxEnabled: fleet.enabled,\n connected,\n installations: rows.map(r => ({\n installationId: Number(r.externalId),\n accountLogin: r.accountName,\n accountType: r.accountType,\n })),\n reason: connected ? 'ready' : 'not_connected',\n diagnostics: diagnostics(),\n });\n },\n }),\n );\n\n // Without an integration instance + state signer there is nothing the\n // remaining handlers can do — serve only the disabled `status` route\n // (mirrors the feature gate).\n if (!isGithubFeatureEnabled({ github, auth }) || !github || !stateSigner) {\n return routes;\n }\n const signState = (orgId: string, userId: string): string => stateSigner.sign(orgId, userId);\n const verifyState = (state: string | undefined) => stateSigner.verify(state);\n\n const { runIssueTriage } = options;\n const runBoardIssueTriage = runIssueTriage\n ? async (input: GithubIssueTriageRunInput): Promise<GithubIssueTriageRunResult> => {\n if (!input.resourceId || !input.projectPath) {\n throw new Error('GitHub issue triage requires an explicit Factory project repository');\n }\n await github.addIssueLabels(input.installationId, input.repository, input.issueNumber, ['auto-triaged']);\n return runIssueTriage({\n ...input,\n defaultModelId:\n input.defaultModelId ?? (await resolveFactoryDefaultModelId(options.projects, input.resourceId)),\n labels: input.labels.includes('auto-triaged') ? input.labels : [...input.labels, 'auto-triaged'],\n });\n }\n : undefined;\n\n routes.push(\n registerApiRoute('/web/github/subscriptions', {\n method: 'GET',\n handler: async c => {\n await auth.ensureUser(loose(c));\n const tenant = auth.tenant(loose(c));\n if (!tenant?.orgId) return c.json({ error: 'unauthorized' }, 401);\n\n const resourceId = c.req.query('resourceId');\n const threadId = c.req.query('threadId');\n const sessionScope = c.req.query('scope');\n if (!resourceId || !threadId) return c.json({ error: 'resourceId and threadId are required' }, 400);\n\n const subscriptions = await listPullRequestSubscriptionsForThread(\n {\n orgId: tenant.orgId,\n resourceId,\n threadId,\n sessionScope,\n },\n github.integrationStorage,\n );\n return c.json({\n subscriptions: subscriptions.map(subscription => ({\n id: subscription.id,\n repoFullName: subscription.data.repositorySlug,\n pullRequestNumber: Number(subscription.data.changeRequestId),\n status: subscription.status,\n url: `https://github.com/${subscription.data.repositorySlug}/pull/${subscription.data.changeRequestId}`,\n })),\n });\n },\n }),\n registerApiRoute('/web/github/webhook', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const result = await handleGithubWebhook(loose(c), {\n github,\n runIssueTriage: runBoardIssueTriage,\n ingestFactoryEvent: options.ingestFactoryEvent,\n ...(options.controller\n ? {\n controller: options.controller,\n onTargetError: (subscription, error) => {\n console.warn(\n `[GitHub Webhook] Delivery failed for subscription ${subscription.id} (${subscription.resourceId}/${subscription.threadId}).`,\n error,\n );\n },\n }\n : {}),\n });\n return c.json(result.body, result.status);\n },\n }),\n );\n\n const redirectUri = options.redirectUri ?? `${(options.baseUrl ?? '').replace(/\\/$/, '')}/auth/github/callback`;\n\n // ── Connect: bounce through the OAuth identify flow ─────────────────────\n // Identify-first (rather than install-first) so an app that is *already*\n // installed on the org re-syncs into our DB: GitHub's install page dead-ends\n // on the installation settings screen for existing installs and never\n // redirects back to us. The callback persists whatever installations the\n // verified user token can see, and only redirects to the install URL when\n // there are none.\n //\n // `?manage=1` skips the identify bounce and sends the user straight to\n // GitHub's installation page — used by \"Manage GitHub connection\" to\n // add/remove accounts and repo access. For an already-authorized user the\n // identify flow completes instantly and invisibly, so without this the\n // manage button would appear to do nothing. GitHub's post-install \"Save\"\n // redirect lands back on the callback, which re-syncs installations.\n routes.push(\n registerApiRoute('/auth/github/connect', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const state = signState(resolved.tenant.orgId, resolved.tenant.userId);\n if (c.req.query('manage')) return c.redirect(github.buildInstallUrl(state));\n return c.redirect(github.buildOAuthIdentifyUrl(state, redirectUri));\n },\n }),\n );\n\n // ── Callback: confirm identity, persist the installation against the org ──\n routes.push(\n registerApiRoute('/auth/github/callback', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const { orgId, userId } = resolved.tenant;\n\n const state = c.req.query('state');\n if (!state) {\n // GitHub's \"Save\"/update redirect from the installation settings page\n // arrives with `installation_id` + `setup_action` but no state. We\n // never trust the raw installation_id; start a fresh identify bounce\n // bound to the current session so the update re-syncs installations.\n return c.redirect(github.buildOAuthIdentifyUrl(signState(orgId, userId), redirectUri));\n }\n const stateTenant = verifyState(state);\n if (!stateTenant || stateTenant.userId !== userId || stateTenant.orgId !== orgId) {\n // CSRF / cross-user/org linking protection: the signed state must belong\n // to the same logged-in user *and* their current org.\n console.warn(\n '[GitHub] Install callback rejected: state/tenant mismatch.',\n JSON.stringify({\n stateValid: Boolean(stateTenant),\n stateOrgId: stateTenant?.orgId,\n stateUserId: stateTenant?.userId,\n sessionOrgId: orgId,\n sessionUserId: userId,\n }),\n );\n return c.redirect('/?github=error');\n }\n\n const code = c.req.query('code');\n // We only ever persist installations that GitHub confirms belong to *this*\n // user via the OAuth code path. The raw `installation_id` from the install\n // redirect is not trusted on its own — anyone with a valid state could pass\n // an arbitrary id — so when no code is present we bounce through the OAuth\n // identify flow to obtain a verified user token first.\n if (!code) {\n return c.redirect(github.buildOAuthIdentifyUrl(signState(orgId, userId), redirectUri));\n }\n\n try {\n const userToken = await github.exchangeOAuthCode(code, redirectUri);\n const installations = await github.listUserInstallations(userToken);\n if (installations.length === 0) {\n // Verified user has no installations yet — send them to the actual\n // install page. After installing, GitHub redirects back here with\n // the same state (and no code), which bounces through identify\n // again and lands in the persist path below.\n return c.redirect(github.buildInstallUrl(signState(orgId, userId)));\n }\n for (const inst of installations) {\n // The installation is org-owned; `userId` records who connected it.\n await github.sourceControlStorage.installations.upsert({\n orgId,\n connectedByUserId: userId,\n externalId: inst.installationId.toString(),\n accountName: inst.accountLogin,\n accountType: inst.accountType,\n });\n }\n } catch (error) {\n console.warn(\n `[GitHub] Install callback failed to persist installations for org ${orgId} / user ${userId}.`,\n error,\n );\n return c.redirect('/?github=error');\n }\n\n return c.redirect('/?github=connected');\n },\n }),\n );\n\n // ── List repos across the org's installations ───────────────────────────\n routes.push(\n registerApiRoute('/web/github/repos', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n\n const installs = await github.sourceControlStorage.installations.list({ orgId: resolved.tenant.orgId });\n\n const query = (c.req.query('q') ?? '').toLowerCase();\n const repos = [];\n const seenRepositoryIds = new Set<number>();\n for (const inst of installs) {\n let list;\n try {\n list = await github.listInstallationRepos(Number(inst.externalId));\n } catch (err) {\n // GitHub 404s when the installation no longer exists for this app\n // (app uninstalled/reinstalled, or the row was recorded under\n // different app credentials). Prune the stale row so `/status`\n // reflects reality and the UI prompts a reconnect, then keep\n // listing the remaining installations.\n if ((err as { status?: number }).status !== 404) throw err;\n console.error(`[Mastra Factory] pruning stale GitHub installation ${inst.externalId} (404 from GitHub)`);\n await github.sourceControlStorage.installations.delete({ orgId: resolved.tenant.orgId, id: inst.id });\n continue;\n }\n for (const repo of list) {\n if (query && !repo.fullName.toLowerCase().includes(query)) continue;\n if (seenRepositoryIds.has(repo.id)) continue;\n seenRepositoryIds.add(repo.id);\n const repository = await github.sourceControlStorage.repositories.upsert({\n orgId: resolved.tenant.orgId,\n input: {\n installationId: inst.id,\n externalId: repo.id.toString(),\n slug: repo.fullName,\n defaultBranch: isValidGitRef(repo.defaultBranch) ? repo.defaultBranch : 'main',\n providerMetadata: { private: repo.private, owner: repo.owner },\n },\n });\n repos.push({\n ...repo,\n installationStorageId: inst.id,\n repositoryStorageId: repository.id,\n sandboxProvider: fleet.provider,\n sandboxWorkdir: fleet.computeWorkdir(repo.fullName),\n });\n }\n }\n return c.json({ repos });\n },\n }),\n );\n\n // ── Materialize a project into the caller's per-user sandbox ─────────────\n routes.push(\n registerApiRoute('/web/github/projects/:id/ensure', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const { orgId, userId } = resolved.tenant;\n\n if (!fleet.enabled) {\n return c.json({ error: 'sandbox_not_configured', message: 'No sandbox provider is configured.' }, 503);\n }\n\n const projectRepositoryId = c.req.param('id');\n if (!projectRepositoryId) return c.json({ error: 'Project repository not found' }, 404);\n const project = await resolveProjectRepository({ github, orgId, projectRepositoryId });\n if (!project) {\n return c.json({ error: 'Project repository not found' }, 404);\n }\n\n // Stream live server-side progress when the client asks for it (EventSource\n // / fetch with `Accept: text/event-stream`); otherwise fall back to a single\n // JSON response so non-streaming callers and tests keep working unchanged.\n const wantsStream = (c.req.header('accept') ?? '').includes('text/event-stream');\n if (wantsStream) {\n return streamSSE(loose(c), async stream => {\n try {\n const result = await prepareProject({\n github,\n fleet,\n project,\n userId,\n onProgress: ev => void stream.writeSSE({ event: 'progress', data: JSON.stringify(ev) }),\n });\n await stream.writeSSE({ event: 'done', data: JSON.stringify(result) });\n } catch (err) {\n await stream.writeSSE({ event: 'error', data: JSON.stringify(ensureErrorPayload(err).body) });\n }\n });\n }\n\n try {\n const result = await prepareProject({ github, fleet, project, userId });\n return c.json(result);\n } catch (err) {\n const { status, body } = ensureErrorPayload(err);\n return c.json(body, status);\n }\n },\n }),\n );\n\n // ── List a project's open GitHub issues ──────────────────────────────────\n routes.push(\n registerApiRoute('/web/github/projects/:id/issues', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n const page = parseListPage(c.req.query('page'));\n if (page === null) return c.json({ error: 'invalid_page' }, 400);\n const label = parseIssueLabelFilter(c.req.query('label'));\n if (label === null) return c.json({ error: 'invalid_label' }, 400);\n try {\n const { issues, nextCursor } = await github.intake.listIssues({\n connection: {\n type: 'app-installation',\n installationId: Number(loaded.project.installation.externalId),\n },\n sourceIds: [loaded.project.repository.slug],\n labels: label ? [label] : undefined,\n cursor: String(page),\n });\n const responseIssues = issues.map(issue => ({\n number: Number(issue.id),\n title: issue.title,\n url: issue.url,\n author: issue.author,\n labels: issue.labels,\n comments: issue.commentCount ?? 0,\n createdAt: issue.createdAt,\n updatedAt: issue.updatedAt,\n }));\n await ingestPolledEvents(\n responseIssues.map(issue => polledIssueEvent(loaded.project, issue)),\n options.ingestFactoryEvent,\n );\n return c.json({\n issues: responseIssues,\n nextPage: nextCursor === null ? null : Number(nextCursor),\n });\n } catch (err) {\n return c.json(\n { error: 'github_fetch_failed', message: err instanceof Error ? err.message : String(err) },\n 502,\n );\n }\n },\n }),\n );\n\n // ── Manually run issue triage using the same run seam as webhooks ──\n routes.push(\n registerApiRoute('/web/github/projects/:id/issues/:number/triage', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const owned = await loadOwnedProject({ github, auth, fleet, c: loose(c) });\n if ('response' in owned) return owned.response;\n const { project, sandboxRow } = owned;\n const issueNumber = parseIssueNumberParam(c.req.param('number'));\n if (issueNumber === null) return c.json({ error: 'invalid_issue_number' }, 400);\n\n let body: { title?: unknown; url?: unknown; labels?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (typeof body.title !== 'string' || body.title.trim().length === 0 || body.title.length > 5000) {\n return c.json({ error: 'invalid_title' }, 400);\n }\n if (\n typeof body.url !== 'string' ||\n body.url.trim().length === 0 ||\n body.url.length > 2048 ||\n !isCanonicalGithubIssueUrl(body.url, project.repository.slug, issueNumber)\n ) {\n return c.json({ error: 'invalid_url' }, 400);\n }\n\n if (!runIssueTriage) return c.json({ error: 'triage_unavailable' }, 503);\n const branch = `factory/issue-${issueNumber}`;\n const projectPath = computeWorktreePath(sandboxRow.sandboxWorkdir, branch);\n await github.addIssueLabels(Number(project.installation.externalId), project.repository.slug, issueNumber, [\n 'auto-triaged',\n ]);\n const result = await runIssueTriage({\n repository: project.repository.slug,\n issueNumber,\n issueTitle: body.title,\n issueUrl: body.url,\n labels: parseStringList(body.labels),\n installationId: Number(project.installation.externalId),\n resourceId: project.factoryProjectId,\n projectPath,\n branch,\n defaultModelId: await resolveFactoryDefaultModelId(options.projects, project.factoryProjectId),\n });\n await emitAudit?.({\n context: loose(c),\n input: {\n action: 'factory.triage.started',\n factoryProjectId: project.factoryProjectId,\n projectRepositoryId: project.id,\n targets: [{ type: 'issue', id: String(issueNumber), name: body.title }],\n metadata: { issueNumber, branch, threadId: result.threadId },\n },\n });\n return c.json(\n {\n ok: true,\n threadId: result.threadId,\n projectPath: result.projectPath ?? projectPath,\n branch: result.branch ?? branch,\n },\n 202,\n );\n },\n }),\n );\n\n // ── List a project's open (non-draft) pull requests ─────────────────────\n routes.push(\n registerApiRoute('/web/github/projects/:id/prs', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n const page = parseListPage(c.req.query('page'));\n if (page === null) return c.json({ error: 'invalid_page' }, 400);\n try {\n const { pullRequests, nextCursor } = await github.versionControl.listPullRequests({\n connection: {\n type: 'app-installation',\n installationId: Number(loaded.project.installation.externalId),\n },\n sourceId: loaded.project.repository.slug,\n includeDrafts: false,\n cursor: String(page),\n });\n const responsePullRequests = pullRequests.map(pr => ({\n number: Number(pr.id),\n title: pr.title,\n url: pr.url,\n author: pr.author,\n baseBranch: pr.baseBranch,\n headBranch: pr.headBranch,\n createdAt: pr.createdAt,\n updatedAt: pr.updatedAt,\n }));\n await ingestPolledEvents(\n responsePullRequests.map(pullRequest => polledPullRequestEvent(loaded.project, pullRequest)),\n options.ingestFactoryEvent,\n );\n return c.json({\n pullRequests: responsePullRequests,\n nextPage: nextCursor === null ? null : Number(nextCursor),\n });\n } catch (err) {\n return c.json(\n { error: 'github_fetch_failed', message: err instanceof Error ? err.message : String(err) },\n 502,\n );\n }\n },\n }),\n );\n\n // ── Read per-project settings ────────────────────────────────────────────\n routes.push(\n registerApiRoute('/web/github/projects/:id/settings', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n return c.json({ setupCommand: loaded.project.setupCommand });\n },\n }),\n );\n\n // ── Update per-project settings ──────────────────────────────────────────\n routes.push(\n registerApiRoute('/web/github/projects/:id/settings', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n\n let body: { setupCommand?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (body.setupCommand !== null && typeof body.setupCommand !== 'string') {\n return c.json({ error: 'Invalid setupCommand' }, 400);\n }\n if (typeof body.setupCommand === 'string' && body.setupCommand.length > 2000) {\n return c.json({ error: 'setupCommand too long (max 2000 characters)' }, 400);\n }\n // Reject control characters (except newline/tab). The command is a\n // shell script by design, but escape sequences and NULs have no\n // legitimate use and can spoof logs or confuse the sandbox shell.\n if (typeof body.setupCommand === 'string' && /[\\0-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]/.test(body.setupCommand)) {\n return c.json({ error: 'setupCommand contains control characters' }, 400);\n }\n // An empty/whitespace command means \"no setup step\".\n const setupCommand =\n typeof body.setupCommand === 'string' && body.setupCommand.trim().length > 0\n ? body.setupCommand.trim()\n : null;\n\n await github.sourceControlStorage.projectRepositories.update({\n orgId: loaded.project.installation.orgId,\n id: loaded.project.id,\n input: { setupCommand },\n });\n return c.json({ setupCommand });\n },\n }),\n );\n\n // ── Org GitHub PATs ──────────────────────────────────────────────────────\n // Installation tokens are the wrong credential for the `gh` CLI (integration\n // -restricted endpoints 403 regardless of permissions), so orgs paste\n // classic PATs the sandboxes use instead: a `default` worker token, and an\n // optional `reviewer` token that review-board sessions use so PR reviews\n // come from a different account. Tokens are never sent back to the browser —\n // only whether each is configured.\n const parsePatKind = (value: unknown): GithubPatKind | null => {\n if (value === undefined || value === null || value === 'default') return 'default';\n if (value === 'reviewer') return 'reviewer';\n return null;\n };\n routes.push(\n registerApiRoute('/web/github/pat', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n return c.json(await getGithubPatStatus(() => github.integrationStorage, resolved.tenant.orgId));\n },\n }),\n registerApiRoute('/web/github/pat', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n\n let body: { token?: unknown; kind?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n const kind = parsePatKind(body.kind);\n if (!kind) return c.json({ error: \"kind must be 'default' or 'reviewer'\" }, 400);\n const token = typeof body.token === 'string' ? body.token.trim() : '';\n if (!token) return c.json({ error: 'A token is required' }, 400);\n if (token.length > 500) return c.json({ error: 'Token too long (max 500 characters)' }, 400);\n if (/\\s/.test(token)) return c.json({ error: 'Token must not contain whitespace' }, 400);\n\n await setGithubPat(github.integrationStorage, resolved.tenant.orgId, token, kind);\n return c.json(await getGithubPatStatus(() => github.integrationStorage, resolved.tenant.orgId));\n },\n }),\n registerApiRoute('/web/github/pat', {\n method: 'DELETE',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const kind = parsePatKind(c.req.query('kind'));\n if (!kind) return c.json({ error: \"kind must be 'default' or 'reviewer'\" }, 400);\n await clearGithubPat(github.integrationStorage, resolved.tenant.orgId, kind);\n return c.json(await getGithubPatStatus(() => github.integrationStorage, resolved.tenant.orgId));\n },\n }),\n );\n\n // ── Sessions / commit / push / PR ────────────────────────────────────────\n routes.push(...buildProjectGitRoutes({ github, auth, fleet, storage, emitAudit }));\n\n return routes;\n}\n\n/**\n * Load the org-owned project for a read-only GitHub API route. Unlike\n * `loadOwnedProject`, this never touches sandbox state — the issues/PR list\n * routes only need the repo + installation, so they work before a sandbox is\n * ever provisioned.\n */\nasync function loadOrgProject(options: {\n github: GithubIntegration;\n auth: RouteAuth;\n c: RouteContext;\n}): Promise<{ project: ResolvedProjectRepository; userId: string } | { response: Response }> {\n const { github, auth, c } = options;\n const resolved = await resolveOrgTenant(c, auth);\n if ('response' in resolved) return { response: resolved.response };\n const { orgId, userId } = resolved.tenant;\n\n const projectRepositoryId = c.req.param('id');\n if (!projectRepositoryId) {\n return { response: c.json({ error: 'Project repository not found' }, 404) };\n }\n const project = await resolveProjectRepository({ github, orgId, projectRepositoryId });\n if (!project) {\n return { response: c.json({ error: 'Project repository not found' }, 404) };\n }\n return { project, userId };\n}\n\n/** Derive a commit/author identity from the authenticated host user. */\nfunction identityFromUser(user: unknown): GitIdentity {\n const u = user as { name?: string; email?: string } | null | undefined;\n return { name: u?.name ?? null, email: u?.email ?? null };\n}\n\n/**\n * Resolve a live, started sandbox for the caller's per-user sandbox binding. The\n * sandbox must already have been provisioned (`sandboxId` set) — the git write\n * routes never clone, they operate on the existing checkout.\n */\nasync function resolveProjectSandbox(options: {\n fleet: SandboxFleet;\n sandboxRow: ProjectRepositorySandbox;\n}): Promise<MaterializationSandbox> {\n const { fleet, sandboxRow } = options;\n if (!sandboxRow.sandboxId) {\n throw new MaterializeError('Project sandbox is not provisioned. Open the project first.', 'clone-failed');\n }\n return fleet.reattachSandbox(sandboxRow.sandboxId);\n}\n\n/**\n * Load (or create) the caller's per-(project,user) sandbox binding row. The\n * binding inherits its workdir from the org-owned project, but `sandboxId` /\n * `materializedAt` stay null until the user first opens the project.\n */\nasync function loadOrCreateSandboxRow(\n github: GithubIntegration,\n project: ResolvedProjectRepository,\n userId: string,\n): Promise<ProjectRepositorySandbox> {\n return github.sourceControlStorage.sandboxes.getOrCreate({ projectRepository: project, userId });\n}\n\ninterface EnsureResult {\n resourceId: string;\n factoryProjectId: string;\n projectRepositoryId: string;\n sandboxId: string | null;\n sandboxWorkdir: string;\n}\n\n/**\n * Provision/reattach the caller's sandbox and materialize the repo into it,\n * emitting coarse progress events as each server step happens. Shared by both\n * the JSON and SSE variants of the `/ensure` route. Throws on failure so the\n * caller can shape the response (HTTP status vs SSE `error` event).\n */\nasync function prepareProject(options: {\n github: GithubIntegration;\n fleet: SandboxFleet;\n project: ResolvedProjectRepository;\n userId: string;\n onProgress?: ProgressFn;\n}): Promise<EnsureResult> {\n const { github, fleet, project, userId, onProgress } = options;\n const sandboxRow = await loadOrCreateSandboxRow(github, project, userId);\n const access = await github.versionControl.getRepositoryAccess({\n orgId: project.installation.orgId,\n repositoryId: project.repository.id,\n });\n if (!access.authorization) {\n throw new MaterializeError('Repository access did not include a bearer token.', 'clone-failed');\n }\n // The sandbox env token feeds the `gh` CLI — a configured org PAT wins\n // there. Git clone/pull below keep the minted installation token.\n const ghCliToken =\n (await getGithubPat(() => github.integrationStorage, project.installation.orgId)) ?? access.authorization.token;\n const sandbox = await ensureProjectSandbox({\n fleet,\n row: sandboxRow,\n storage: github.sourceControlStorage.sandboxes,\n token: ghCliToken,\n onProgress,\n });\n // Re-read the sandbox binding so we have the freshly persisted sandboxId.\n const fresh = await github.sourceControlStorage.sandboxes.getById({ id: sandboxRow.id });\n const finalRow = fresh ?? sandboxRow;\n await materializeRepo({\n row: finalRow,\n repoInfo: { repoFullName: project.repository.slug, defaultBranch: project.defaultBranch },\n sandbox,\n token: access.authorization.token,\n storage: github.sourceControlStorage.sandboxes,\n onProgress,\n });\n const result: EnsureResult = {\n resourceId: project.factoryProjectId,\n factoryProjectId: project.factoryProjectId,\n projectRepositoryId: project.id,\n sandboxId: finalRow.sandboxId,\n sandboxWorkdir: finalRow.sandboxWorkdir,\n };\n const done: PrepareProgress = { phase: 'done', message: 'Workspace ready.' };\n onProgress?.(done);\n return result;\n}\n\n/** Shape an /ensure failure into an HTTP status + JSON body (also used as the SSE error payload). */\nfunction ensureErrorPayload(err: unknown): {\n status: 429 | 502 | 500;\n body: { error: string; message: string };\n} {\n if (err instanceof SandboxBudgetError) {\n return { status: 429, body: { error: err.code, message: err.message } };\n }\n if (err instanceof MaterializeError) {\n return { status: 502, body: { error: err.code, message: err.message } };\n }\n return {\n status: 500,\n body: { error: 'materialize_failed', message: err instanceof Error ? err.message : String(err) },\n };\n}\n\n/** Map a sandbox/worktree error to an actionable HTTP response. */\nfunction gitErrorResponse(c: Context, err: unknown) {\n if (err instanceof WorktreeError) {\n return c.json({ error: err.code, message: err.message }, err.code === 'invalid-branch' ? 400 : 502);\n }\n if (err instanceof MaterializeError) {\n return c.json({ error: err.code, message: err.message }, 502);\n }\n return c.json({ error: 'git_failed', message: err instanceof Error ? err.message : String(err) }, 500);\n}\n\n/**\n * Load the org-owned project and the caller's per-user sandbox binding for a git\n * route. Centralizes the auth + org/ownership checks every git route shares:\n * the project is scoped by `(id, orgId)`, the sandbox binding by\n * `(projectRepositoryId, userId)`. Returns the tenant, project, and sandbox row, or\n * a ready-to-return error response.\n */\nasync function loadOwnedProject(options: {\n github: GithubIntegration;\n auth: RouteAuth;\n fleet: SandboxFleet;\n c: RouteContext;\n}): Promise<\n | { orgId: string; userId: string; project: ResolvedProjectRepository; sandboxRow: ProjectRepositorySandbox }\n | { response: Response }\n> {\n const { github, auth, fleet, c } = options;\n const resolved = await resolveOrgTenant(c, auth);\n if ('response' in resolved) return { response: resolved.response };\n const { orgId, userId } = resolved.tenant;\n\n if (!fleet.enabled) {\n return {\n response: c.json({ error: 'sandbox_not_configured', message: 'No sandbox provider is configured.' }, 503),\n };\n }\n\n const projectRepositoryId = c.req.param('id');\n if (!projectRepositoryId) {\n return { response: c.json({ error: 'Project repository not found' }, 404) };\n }\n const project = await resolveProjectRepository({ github, orgId, projectRepositoryId });\n if (!project) {\n return { response: c.json({ error: 'Project repository not found' }, 404) };\n }\n const sandboxRow = await loadOrCreateSandboxRow(github, project, userId);\n return { orgId, userId, project, sandboxRow };\n}\n\nfunction buildProjectGitRoutes({\n github,\n auth,\n fleet,\n storage,\n emitAudit,\n}: {\n github: GithubIntegration;\n auth: RouteAuth;\n fleet: SandboxFleet;\n storage?: FactoryStorage;\n emitAudit?: AuditEmitter['emit'];\n}): ApiRoute[] {\n return [\n // ── Create / list Factory sessions ──────────────────────────────────────\n registerApiRoute('/web/github/projects/:id/sessions', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const { orgId, userId } = resolved.tenant;\n const projectRepositoryId = c.req.param('id');\n const project = projectRepositoryId\n ? await resolveProjectRepository({ github, orgId, projectRepositoryId })\n : null;\n if (!project) return c.json({ error: 'Project repository not found' }, 404);\n const sessions = await github.sourceControlStorage.sessions.list({ projectRepositoryId: project.id, userId });\n return c.json({ sessions });\n },\n }),\n registerApiRoute('/web/github/projects/:id/sessions', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const { orgId, userId } = resolved.tenant;\n const projectRepositoryId = c.req.param('id');\n const project = projectRepositoryId\n ? await resolveProjectRepository({ github, orgId, projectRepositoryId })\n : null;\n if (!project) return c.json({ error: 'Project repository not found' }, 404);\n let body: { branch?: unknown; baseBranch?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (!isValidGitRefSandbox(body.branch)) return c.json({ error: 'Invalid branch' }, 400);\n const baseBranch = body.baseBranch === undefined ? project.defaultBranch : body.baseBranch;\n if (!isValidGitRefSandbox(baseBranch)) return c.json({ error: 'Invalid baseBranch' }, 400);\n const session = await github.sourceControlStorage.sessions.create({\n sessionId: randomUUID(),\n projectRepositoryId: project.id,\n orgId,\n userId,\n branch: body.branch,\n baseBranch,\n });\n return c.json({ session });\n },\n }),\n registerApiRoute('/web/user-sessions/:sessionId', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const session = await github.sourceControlStorage.sessions.getBySessionId(c.req.param('sessionId'));\n if (!session || session.orgId !== resolved.tenant.orgId || session.userId !== resolved.tenant.userId) {\n return c.json({ error: 'Session not found' }, 404);\n }\n return c.json({ session });\n },\n }),\n registerApiRoute('/web/user-sessions/:sessionId', {\n method: 'DELETE',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const session = await github.sourceControlStorage.sessions.getBySessionId(c.req.param('sessionId'));\n if (!session || session.orgId !== resolved.tenant.orgId || session.userId !== resolved.tenant.userId) {\n return c.json({ error: 'Session not found' }, 404);\n }\n let sandbox: MaterializationSandbox | undefined;\n if (session.sandboxId) {\n try {\n sandbox = await fleet.reattachSandbox(session.sandboxId);\n } catch {\n // The provider may already have reclaimed the sandbox.\n }\n await fleet.teardownSandbox(\n {\n sandboxId: session.sandboxId,\n setSandboxId: async () => {},\n clear: async () => {\n await github.sourceControlStorage.sessions.setSandbox({\n id: session.id,\n sandboxId: null,\n sandboxWorkdir: session.sandboxWorkdir ?? '',\n });\n },\n },\n sandbox,\n );\n }\n await github.sourceControlStorage.sessions.delete(session.id);\n return c.json({ removed: true });\n },\n }),\n\n // ── Stage all + commit inside a Factory session workspace ──────────────\n registerApiRoute('/web/github/projects/:id/commit', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const owned = await loadOwnedProject({ github, auth, fleet, c: loose(c) });\n if ('response' in owned) return owned.response;\n const { userId, project } = owned;\n\n let body: { message?: unknown; sessionId?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (typeof body.message !== 'string' || body.message.trim().length === 0 || body.message.length > 5000) {\n return c.json({ error: 'Invalid message' }, 400);\n }\n const sessionWorkspace = await resolveSessionWorkspace(github, project.id, userId, body.sessionId);\n if (!sessionWorkspace) {\n return c.json({ error: 'Invalid sessionId' }, 400);\n }\n const { workdir, sandboxBinding } = sessionWorkspace;\n\n try {\n return await withProjectLock({\n key: `${project.id}:${userId}`,\n storage,\n fn: async () => {\n const sandbox = await resolveProjectSandbox({ fleet, sandboxRow: sandboxBinding });\n const result = await commitAll(\n sandbox,\n workdir,\n body.message as string,\n identityFromUser(await auth.ensureUser(loose(c))),\n );\n if (result.committed) {\n await emitAudit?.({\n context: loose(c),\n input: {\n action: 'factory.git.commit',\n factoryProjectId: project.factoryProjectId,\n projectRepositoryId: project.id,\n targets: [{ type: 'session', id: sessionWorkspace.session.sessionId }],\n metadata: { sessionId: sessionWorkspace.session.sessionId },\n },\n });\n }\n return c.json({ committed: result.committed });\n },\n });\n } catch (err) {\n return gitErrorResponse(loose(c), err);\n }\n },\n }),\n\n // ── Push a branch back to GitHub ────────────────────────────────────────\n registerApiRoute('/web/github/projects/:id/push', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const owned = await loadOwnedProject({ github, auth, fleet, c: loose(c) });\n if ('response' in owned) return owned.response;\n const { orgId, userId, project } = owned;\n\n let body: { branch?: unknown; sessionId?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (!isValidGitRefSandbox(body.branch)) {\n return c.json({ error: 'Invalid branch' }, 400);\n }\n const branch = body.branch;\n const sessionWorkspace = await resolveSessionWorkspace(github, project.id, userId, body.sessionId);\n if (!sessionWorkspace) {\n return c.json({ error: 'Invalid sessionId' }, 400);\n }\n const { workdir, sandboxBinding } = sessionWorkspace;\n\n try {\n return await withProjectLock({\n key: `${project.id}:${userId}`,\n storage,\n fn: async () => {\n const sandbox = await resolveProjectSandbox({ fleet, sandboxRow: sandboxBinding });\n const access = await github.versionControl.getRepositoryAccess({\n orgId,\n repositoryId: project.repository.id,\n });\n if (!access.authorization) throw new Error('Repository access did not include a bearer token.');\n await pushBranch(sandbox, workdir, branch, access.authorization.token, project.repository.slug);\n await emitAudit?.({\n context: loose(c),\n input: {\n action: 'factory.git.push',\n factoryProjectId: project.factoryProjectId,\n projectRepositoryId: project.id,\n targets: [{ type: 'branch', id: branch }],\n metadata: { branch, sessionId: sessionWorkspace.session.sessionId },\n },\n });\n return c.json({ pushed: true, branch });\n },\n });\n } catch (err) {\n return gitErrorResponse(loose(c), err);\n }\n },\n }),\n\n // ── Open a pull request through the version-control capability ─────────\n registerApiRoute('/web/github/projects/:id/pr', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const owned = await loadOwnedProject({ github, auth, fleet, c: loose(c) });\n if ('response' in owned) return owned.response;\n const { orgId, userId, project } = owned;\n\n let body: {\n branch?: unknown;\n base?: unknown;\n title?: unknown;\n body?: unknown;\n sessionId?: unknown;\n };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (!isValidGitRefSandbox(body.branch)) {\n return c.json({ error: 'Invalid branch' }, 400);\n }\n const base = body.base === undefined ? project.defaultBranch : body.base;\n if (!isValidGitRefSandbox(base)) {\n return c.json({ error: 'Invalid base' }, 400);\n }\n if (typeof body.title !== 'string' || body.title.trim().length === 0 || body.title.length > 256) {\n return c.json({ error: 'Invalid title' }, 400);\n }\n if (body.body !== undefined && (typeof body.body !== 'string' || body.body.length > 65536)) {\n return c.json({ error: 'Invalid body' }, 400);\n }\n const head = body.branch;\n const title = body.title;\n const prBody = body.body as string | undefined;\n const sessionWorkspace = await resolveSessionWorkspace(github, project.id, userId, body.sessionId);\n if (!sessionWorkspace) {\n return c.json({ error: 'Invalid sessionId' }, 400);\n }\n\n try {\n return await withProjectLock({\n key: `${project.id}:${userId}`,\n storage,\n fn: async () => {\n const result = await github.versionControl.createPullRequest({\n connection: {\n type: 'app-installation',\n installationId: Number(project.installation.externalId),\n },\n sourceId: project.repository.slug,\n baseBranch: base,\n headBranch: head,\n title,\n body: prBody,\n actingUserId: userId,\n });\n await emitAudit?.({\n context: loose(c),\n input: {\n action: 'factory.git.pr_opened',\n factoryProjectId: project.factoryProjectId,\n projectRepositoryId: project.id,\n targets: [{ type: 'pull_request', id: result.url, name: title }],\n metadata: { branch: head, base, url: result.url },\n },\n });\n const pullRequestNumber = pullRequestNumberFromUrl(result.url, project.repository.slug);\n if (pullRequestNumber) {\n const sessionId = sessionWorkspace.session.sessionId;\n await subscribeToPullRequest(\n {\n orgId,\n installationExternalId: project.installation.externalId,\n projectRepositoryId: project.id,\n repositoryExternalId: project.repository.externalId,\n repositorySlug: project.repository.slug,\n changeRequestId: pullRequestNumber.toString(),\n sessionId,\n ownerId: userId,\n resourceId: sessionId,\n threadId: sessionId,\n source: 'factory-pr-create',\n subscribedByUserId: userId,\n },\n github.integrationStorage,\n ).catch((error: unknown) => {\n console.warn(\n `[GitHub] Pull request ${result.url} was created but automatic subscription failed.`,\n error,\n );\n });\n }\n return c.json({ url: result.url });\n },\n });\n } catch (err) {\n return c.json(\n { error: 'github_pr_create_failed', message: err instanceof Error ? err.message : String(err) },\n 502,\n );\n }\n },\n }),\n\n // ── Tear down the caller's sandbox for a project ────────────────────────\n // Per-user teardown only: drops the caller's `(project, user)` sandbox\n // binding and stops the VM, freeing a slot in the per-replica budget. Project\n // deletion at the org level is out of scope (org admin model is later).\n registerApiRoute('/web/github/projects/:id/sandbox', {\n method: 'DELETE',\n requiresAuth: false,\n handler: async c => {\n const owned = await loadOwnedProject({ github, auth, fleet, c: loose(c) });\n if ('response' in owned) return owned.response;\n const { userId, project, sandboxRow } = owned;\n\n if (!sandboxRow.sandboxId) {\n // Nothing provisioned for this user — idempotent success.\n return c.json({ tornDown: false });\n }\n\n try {\n return await withProjectLock({\n key: `${project.id}:${userId}`,\n storage,\n fn: async () => {\n const sandbox = await fleet.reattachSandbox(sandboxRow.sandboxId!);\n await teardownProjectSandbox({\n fleet,\n row: sandboxRow,\n storage: github.sourceControlStorage.sandboxes,\n sandbox,\n });\n return c.json({ tornDown: true });\n },\n });\n } catch (err) {\n return gitErrorResponse(loose(c), err);\n }\n },\n }),\n ];\n}\n\n/** Resolve the materialized workspace owned by a Factory session. */\nasync function resolveSessionWorkspace(\n github: GithubIntegration,\n projectId: string,\n userId: string,\n sessionId: unknown,\n) {\n if (typeof sessionId !== 'string') {\n return undefined;\n }\n const session = await github.sourceControlStorage.sessions.getBySessionId(sessionId);\n if (\n session?.projectRepositoryId !== projectId ||\n session.userId !== userId ||\n !session.sandboxId ||\n !session.sandboxWorkdir\n ) {\n return undefined;\n }\n return {\n session,\n workdir: session.sandboxWorkdir,\n sandboxBinding: {\n id: session.id,\n projectRepositoryId: session.projectRepositoryId,\n userId: session.userId,\n sandboxId: session.sandboxId,\n sandboxWorkdir: session.sandboxWorkdir,\n materializedAt: session.materializedAt,\n createdAt: session.createdAt,\n },\n };\n}\n","/**\n * Project sandbox fleet: provisioning, reattach, teardown, and budgeting.\n *\n * Server-hosted projects never run on the web host itself. Each project gets\n * its own isolated sandbox (a `WorkspaceSandbox`, e.g. a Railway VM) `clone()`d\n * from the machine the factory was configured with. This module owns everything\n * about that fleet — which provider is active, where checkouts live inside a\n * sandbox, the idle window, the per-replica budget, and the\n * provision/reattach/teardown lifecycle — but knows nothing about what runs\n * inside a sandbox (git materialization lives with its feature, e.g. the\n * GitHub integration's `sandbox.ts`).\n *\n * The fleet is constructed once at boot with the machine config (or none, when\n * sandboxes are disabled) and handed to consumers — no global registry.\n * Persistence of the provider's reattach id is delegated to the caller via\n * {@link SandboxBindingStore}, so the fleet stays storage-agnostic. Tests can\n * swap the low-level construction via {@link SandboxFleet.setFactory}.\n */\n\nimport path from 'node:path';\n\nimport type { WorkspaceSandbox } from '@mastra/core/workspace';\n\n/** Minimal command result shape sandbox consumers depend on. */\nexport interface SandboxCommandResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n}\n\n/**\n * Minimal live-sandbox surface fleet consumers need: an id, a way to start it,\n * a way to learn the provider's reattach id, and command execution.\n */\nexport interface MaterializationSandbox {\n readonly id: string;\n start(): Promise<void>;\n getInfo(): Promise<{ metadata?: Record<string, unknown> }>;\n executeCommand(\n command: string,\n args?: string[],\n options?: { timeout?: number; env?: Record<string, string | undefined> },\n ): Promise<SandboxCommandResult>;\n /** Update an environment variable for future commands in this sandbox. */\n setEnvironmentVariable?(name: string, value: string): void;\n /** Tear down the underlying VM. Optional: providers without it are no-ops. */\n stop?(): Promise<void>;\n}\n\n/** Options for building (or reattaching) one sandbox. */\nexport interface SandboxCreateOptions {\n /** Reattach to this existing provider VM instead of provisioning a new one. */\n providerSandboxId?: string;\n /** Environment variables baked into the sandbox. */\n env?: Record<string, string>;\n /** Provider working directory for this sandbox. */\n workingDirectory?: string;\n /** Idle teardown window (minutes). The provider stops the VM after this idle period. */\n idleTimeoutMinutes?: number;\n /** Provider checkpoint used to seed and preserve this sandbox's filesystem. */\n checkpointName?: string;\n}\n\n/**\n * A coarse-grained step of the sandbox-preparation flow, reported as it happens\n * so the UI can show the user what the server is doing instead of a static\n * \"Preparing…\" toast. `phase` is a stable machine token; `message` is\n * user-facing copy.\n */\nexport interface PrepareProgress {\n phase: 'reattaching' | 'provisioning' | 'preparing-workspace' | 'cloning' | 'pulling' | 'finalizing' | 'done';\n message: string;\n}\n\n/** Callback invoked with each preparation step. Best-effort; never throws. */\nexport type ProgressFn = (event: PrepareProgress) => void;\n\n/** Invoke a progress callback without letting it break the actual work. */\nexport function reportProgress(onProgress: ProgressFn | undefined, event: PrepareProgress): void {\n if (!onProgress) return;\n try {\n onProgress(event);\n } catch {\n // Progress reporting must never break the actual work.\n }\n}\n\n/**\n * Factory that builds a (not-yet-started) sandbox. When `providerSandboxId` is\n * provided the sandbox should reattach to that existing VM instead of\n * provisioning a new one.\n */\nexport type SandboxFactory = (opts: SandboxCreateOptions) => MaterializationSandbox;\n\n/** Raised when provisioning would exceed the per-replica sandbox budget. */\nexport class SandboxBudgetError extends Error {\n readonly code = 'sandbox-budget-exceeded' as const;\n constructor(readonly max: number) {\n super(\n `Sandbox budget exceeded: this server already has ${max} active sandbox(es), ` +\n `the configured per-replica maximum. Close an existing repository's sandbox and try again.`,\n );\n this.name = 'SandboxBudgetError';\n }\n}\n\n/** Optional knobs for provisioning/reattaching one sandbox. */\nexport interface EnsureSandboxOptions {\n /** Provider working directory for this sandbox. */\n workingDirectory?: string;\n}\n\n/**\n * Where a feature persists its sandbox binding. The fleet reads the stored\n * reattach id and writes updates through this seam so it stays agnostic of\n * the owning table (GitHub projects today, anything else tomorrow).\n */\nexport interface SandboxBindingStore {\n /** Stored provider reattach id from a previous provisioning, if any. */\n readonly sandboxId: string | null;\n /** Provider checkpoint used to seed and preserve this sandbox's filesystem. */\n readonly checkpointName?: string;\n /** Persist a freshly provisioned provider id, or clear a stale one with `null`. */\n setSandboxId(id: string | null): Promise<void>;\n /** Clear all stored sandbox state (reattach id + materialization mark) on teardown. */\n clear(): Promise<void>;\n}\n\n/**\n * Adapt a cloned `WorkspaceSandbox` to the minimal surface this module needs.\n * Lifecycle goes through the `_`-prefixed wrappers when present (they add\n * status tracking and concurrency safety on `MastraSandbox` subclasses),\n * falling back to the plain methods for interface-only implementations.\n */\nfunction toMaterializationSandbox(\n sandbox: WorkspaceSandbox,\n initialEnvironment: Record<string, string> = {},\n): MaterializationSandbox {\n if (typeof sandbox.executeCommand !== 'function') {\n throw new Error(\n `Sandbox provider '${sandbox.provider}' does not implement executeCommand() — cannot materialize repos.`,\n );\n }\n const lifecycle = sandbox as { _start?(): Promise<void>; _stop?(): Promise<void> };\n const environment = { ...initialEnvironment };\n return {\n id: sandbox.id,\n start: async () => {\n await (lifecycle._start ?? sandbox.start)?.call(sandbox);\n },\n getInfo: async () => (await sandbox.getInfo?.()) ?? {},\n executeCommand: (command, args, options) =>\n sandbox.executeCommand!(command, args, {\n ...options,\n env: { ...environment, ...options?.env },\n }),\n setEnvironmentVariable: (name, value) => {\n environment[name] = value;\n },\n stop: async () => {\n await (lifecycle._stop ?? sandbox.stop)?.call(sandbox);\n },\n };\n}\n\n/**\n * The provider's reattach id for a started sandbox. For Railway this is the\n * underlying `railwaySandboxId` in `getInfo().metadata`. Providers without a\n * provider-native id (e.g. local) reattach by construction id, so fall back\n * to the sandbox's own logical id.\n */\nasync function readProviderSandboxId(sandbox: MaterializationSandbox): Promise<string | undefined> {\n const info = await sandbox.getInfo();\n const id = info.metadata?.railwaySandboxId ?? info.metadata?.sandboxId;\n return typeof id === 'string' ? id : sandbox.id;\n}\n\n/** Keep each path piece a single safe segment (no separators or traversal). */\nfunction sanitizeSegment(segment: string): string {\n const cleaned = segment.replace(/[^A-Za-z0-9._-]/g, '-').replace(/^\\.+/, '');\n return cleaned || 'repo';\n}\n\n/** Resolve a workdir under `root`, refusing any path that escapes the configured root. */\nexport function resolveContainedLocalWorkdir(root: string, ...segments: string[]): string {\n const resolvedRoot = path.resolve(root);\n const resolved = path.resolve(resolvedRoot, ...segments);\n if (resolved !== resolvedRoot && resolved.startsWith(`${resolvedRoot}${path.sep}`)) return resolved;\n throw new Error(`Refusing to use local sandbox path outside configured root: ${resolved}`);\n}\n\n/**\n * Factory-resolved sandbox runtime the fleet is constructed with: the machine\n * projects clone their per-project sandboxes from, plus the knobs the factory\n * resolved around it.\n */\nexport interface SandboxFleetConfig {\n /**\n * Template machine (validated by the factory to implement `clone()`).\n * Never started — acts purely as the credential/default holder that\n * per-project sandboxes are cloned from.\n */\n machine: WorkspaceSandbox;\n /** In-sandbox base directory repos check out under (no trailing slash). */\n workdirBase: string;\n /** Per-replica cap on concurrently provisioned sandboxes. 0 = unlimited. */\n maxSandboxes?: number;\n}\n\n/**\n * The sandbox fleet for one deployment. Constructed once at boot — with a\n * config when a sandbox machine was configured, or without one when sandboxes\n * are disabled (every provisioning entry point then throws and\n * {@link enabled} reports `false` so features stay off).\n */\nexport class SandboxFleet {\n readonly #config: SandboxFleetConfig | undefined;\n #factory: SandboxFactory | undefined;\n #liveCount = 0;\n\n constructor(config?: SandboxFleetConfig) {\n this.#config = config;\n }\n\n /**\n * True when a sandbox machine was configured. The factory validates the\n * machine implements `clone()` at boot, so a configured fleet is usable —\n * sandbox-backed projects stay off only when the slot was omitted.\n */\n get enabled(): boolean {\n return this.#config !== undefined;\n }\n\n /**\n * Name of the active sandbox provider — the configured machine's `provider`\n * discriminator (`'railway'`, `'local'`, …), or `'none'` when the fleet was\n * constructed without a config. Diagnostic only; feature gating goes\n * through {@link enabled}.\n */\n get provider(): string {\n return this.#config?.machine.provider ?? 'none';\n }\n\n /**\n * Idle teardown window for provisioned sandboxes, in minutes; defaults to 30.\n * Read back from the machine's own config when it exposes one\n * (Railway's `idleTimeoutMinutes`) — the knob lives on the sandbox, the\n * fleet only needs it to schedule GC and stamp sandbox clones. Advisory:\n * providers without idle GC ignore it, and a re-open detects a torn-down VM\n * and re-provisions cleanly.\n */\n get idleMinutes(): number {\n const machine = this.#config?.machine as { idleTimeoutMinutes?: unknown } | undefined;\n const minutes = machine?.idleTimeoutMinutes;\n return typeof minutes === 'number' && Number.isFinite(minutes) && minutes > 0 ? minutes : 30;\n }\n\n /**\n * Per-replica cap on concurrently *provisioned* sandboxes. 0 means unlimited.\n * This is a lightweight per-process budget to keep a single replica from\n * exhausting provider quota — it is not a global, cross-replica scheduler\n * (that is a deferred follow-up).\n */\n get maxSandboxes(): number {\n return this.#config?.maxSandboxes ?? 0;\n }\n\n /**\n * Count of sandboxes this fleet has freshly provisioned and not yet torn\n * down. Reattaches to existing VMs do not count (they reuse an already-billed\n * sandbox). Used to enforce {@link maxSandboxes}.\n */\n get liveCount(): number {\n return this.#liveCount;\n }\n\n /** For tests: reset the live-sandbox counter to a known state. */\n __resetLiveCount(value = 0): void {\n this.#liveCount = value;\n }\n\n /** Override the sandbox factory (tests). */\n setFactory(factory: SandboxFactory): void {\n this.#factory = factory;\n }\n\n /** Reset to the default machine-cloning factory. */\n resetFactory(): void {\n this.#factory = undefined;\n }\n\n /**\n * Compute the in-sandbox working directory for a repo: a nested\n * `<base>/<owner>/<name>` layout under the factory-resolved checkout base.\n * Nesting keeps same-name repos apart (`acme/api` vs `other/api`) — cloud\n * sandboxes are one-per-project so it's merely tidy there, but local\n * checkouts share one host root where it prevents collisions. Server-side\n * only; never derived from client input.\n */\n computeWorkdir(repoFullName: string): string {\n if (!this.#config) throw new Error('No sandbox configured');\n const [owner, name] = repoFullName.split('/', 2);\n return `${this.#config.workdirBase}/${sanitizeSegment(owner || 'unknown')}/${sanitizeSegment(name || 'repo')}`;\n }\n\n /**\n * Compute the host working directory for a local GitHub session checkout.\n * This is server-derived only: repo pieces are sanitized and the trusted\n * session id is kept as a single path segment under the configured local root.\n */\n computeLocalSessionWorkdir(repoFullName: string, sessionId: string): string {\n if (!this.#config) throw new Error('No sandbox configured');\n if (this.#config.machine.provider !== 'local') {\n throw new Error('Local session workdirs require the local sandbox provider');\n }\n\n const localRoot = (this.#config.machine as { workingDirectory?: unknown }).workingDirectory;\n if (typeof localRoot !== 'string' || localRoot.length === 0) {\n throw new Error('Local sandbox working directory is not configured');\n }\n\n const [owner, name] = repoFullName.split('/', 2);\n return resolveContainedLocalWorkdir(\n localRoot,\n 'github-sessions',\n sanitizeSegment(owner || 'unknown'),\n sanitizeSegment(name || 'repo'),\n sanitizeSegment(sessionId),\n );\n }\n\n /**\n * Build a (not-yet-started) sandbox: the test-provided factory when set,\n * otherwise a per-project clone of the configured machine. The stored id is\n * passed both as the logical `id` (providers that reattach by construction\n * id, e.g. local) and as the provider-native `sandboxId` hint (Railway) so\n * reattach works across the provider matrix.\n */\n #build(opts: SandboxCreateOptions): MaterializationSandbox {\n if (this.#factory) return this.#factory(opts);\n if (!this.#config) throw new Error('No sandbox configured');\n const clone = this.#config.machine.clone!({\n ...(opts.providerSandboxId ? { id: opts.providerSandboxId, sandboxId: opts.providerSandboxId } : {}),\n ...(opts.env ? { env: opts.env } : {}),\n ...(opts.workingDirectory ? { workingDirectory: opts.workingDirectory } : {}),\n ...(opts.idleTimeoutMinutes !== undefined ? { idleTimeoutMinutes: opts.idleTimeoutMinutes } : {}),\n ...(opts.checkpointName ? { checkpointName: opts.checkpointName } : {}),\n });\n return toMaterializationSandbox(clone, opts.env);\n }\n\n /**\n * Provision a new sandbox (persisting its provider id on first open) or\n * reattach to the stored one. Returns a started, live sandbox.\n */\n async ensureSandbox(store: SandboxBindingStore, onProgress?: ProgressFn): Promise<MaterializationSandbox>;\n async ensureSandbox(\n store: SandboxBindingStore,\n env?: Record<string, string>,\n onProgress?: ProgressFn,\n options?: EnsureSandboxOptions,\n ): Promise<MaterializationSandbox>;\n async ensureSandbox(\n store: SandboxBindingStore,\n envOrProgress?: Record<string, string> | ProgressFn,\n progressOrOptions?: ProgressFn | EnsureSandboxOptions,\n maybeOptions: EnsureSandboxOptions = {},\n ): Promise<MaterializationSandbox> {\n const env = typeof envOrProgress === 'function' ? undefined : envOrProgress;\n const onProgress =\n typeof envOrProgress === 'function' ? envOrProgress : (progressOrOptions as ProgressFn | undefined);\n const options =\n typeof envOrProgress === 'function'\n ? ((progressOrOptions as EnsureSandboxOptions | undefined) ?? {})\n : maybeOptions;\n const idleTimeoutMinutes = this.idleMinutes;\n const checkpointName = store.checkpointName;\n\n // Reattach path: if we have a stored sandbox id, try to reattach. The VM may\n // have been torn down by the provider's idle GC (or otherwise died), in which\n // case `start()` fails. Recover by clearing the stale id and provisioning a\n // fresh sandbox so the next open succeeds instead of being permanently wedged.\n if (store.sandboxId) {\n reportProgress(onProgress, { phase: 'reattaching', message: 'Reconnecting to your sandbox…' });\n const reattached = this.#build({\n providerSandboxId: store.sandboxId,\n idleTimeoutMinutes,\n ...(checkpointName ? { checkpointName } : {}),\n ...(env ? { env } : {}),\n ...(options.workingDirectory ? { workingDirectory: options.workingDirectory } : {}),\n });\n try {\n await reattached.start();\n return reattached;\n } catch {\n await store.setSandboxId(null);\n // fall through to fresh provision below\n }\n }\n\n // Fresh provision: enforce the per-replica budget before spending quota.\n const max = this.maxSandboxes;\n if (max > 0 && this.#liveCount >= max) {\n throw new SandboxBudgetError(max);\n }\n\n reportProgress(onProgress, { phase: 'provisioning', message: 'Provisioning a new sandbox…' });\n const sandbox = this.#build({\n idleTimeoutMinutes,\n ...(checkpointName ? { checkpointName } : {}),\n ...(env ? { env } : {}),\n ...(options.workingDirectory ? { workingDirectory: options.workingDirectory } : {}),\n });\n await sandbox.start();\n this.#liveCount += 1;\n\n const providerSandboxId = await readProviderSandboxId(sandbox);\n if (providerSandboxId) {\n await store.setSandboxId(providerSandboxId);\n }\n\n return sandbox;\n }\n\n /**\n * Tear down a sandbox binding: stop the live VM (best-effort) and clear the\n * persisted state through the binding store so the next open re-provisions\n * cleanly. Decrements the per-replica live-sandbox counter.\n *\n * @param store the binding to tear down\n * @param sandbox an already-reattached live sandbox to stop, when available\n */\n async teardownSandbox(store: SandboxBindingStore, sandbox?: MaterializationSandbox): Promise<void> {\n if (sandbox?.stop) {\n try {\n await sandbox.stop();\n } catch {\n // Best-effort: the VM may already be gone (idle GC). Still clear the binding.\n }\n }\n if (store.sandboxId) {\n if (this.#liveCount > 0) this.#liveCount -= 1;\n await store.clear();\n }\n }\n\n /**\n * Reattach to an already-provisioned sandbox by its provider id and start it.\n * Used by the workspace seam when opening a project that was already\n * materialized (sandbox id + workdir carried on controller state), so no DB\n * round-trip is needed.\n */\n async reattachSandbox(\n providerSandboxId: string,\n options: EnsureSandboxOptions = {},\n ): Promise<MaterializationSandbox> {\n const sandbox = this.#build({\n providerSandboxId,\n idleTimeoutMinutes: this.idleMinutes,\n ...(options.workingDirectory ? { workingDirectory: options.workingDirectory } : {}),\n });\n await sandbox.start();\n return sandbox;\n }\n}\n","/**\n * Composite feature gate + diagnostics for the GitHub App project feature.\n *\n * The GitHub feature is enabled only when *all three* hold:\n * - a `GithubIntegration` instance is registered with the factory\n * (constructed by the deploy entry from the `GITHUB_APP_*` env vars),\n * - web auth is enabled (a per-user installation requires a logged-in user),\n * - the application database is configured.\n *\n * OAuth/install `state` signing lives in `../../state-signing.ts` — the factory\n * creates one shared signer at boot and hands it to every integration.\n *\n * Everything here is pure: callers pass the handles they already own (the\n * integration, auth seam, state signer, sandbox fleet) — there is no global\n * registry lookup.\n */\n\nimport type { RouteAuth } from '../../routes/route.js';\nimport type { SandboxFleet } from '../../sandbox/fleet.js';\nimport type { StateSigner } from '../../state-signing.js';\nimport type { GithubIntegration } from './integration.js';\n\n/**\n * Env vars the deploy entry reads to construct a `GithubIntegration`. Names\n * only — used by diagnostics to tell an operator what to set when the\n * integration is absent. The entry enforces all-or-nothing: partial config\n * fails the boot, so at runtime the integration is either fully configured or\n * not configured at all.\n */\nconst GITHUB_APP_ENV_VARS = [\n 'GITHUB_APP_ID',\n 'GITHUB_APP_PRIVATE_KEY',\n 'GITHUB_APP_CLIENT_ID',\n 'GITHUB_APP_CLIENT_SECRET',\n 'GITHUB_APP_SLUG',\n] as const;\n\n/** Handles the GitHub feature gate + diagnostics are computed from. */\nexport interface GithubFeatureGateOptions {\n /** The registered GitHub integration, when configured. */\n github: GithubIntegration | undefined;\n /** Web auth seam — the feature requires a logged-in user. */\n auth: RouteAuth;\n /** True when the application database is configured. */\n appDbConfigured: boolean;\n /** Shared OAuth/install `state` signer, when configured. */\n stateSigner?: StateSigner;\n /** Sandbox fleet, when sandboxes are configured. */\n fleet?: SandboxFleet;\n}\n\n/**\n * True when the GitHub App project feature should be active.\n */\nexport function isGithubFeatureEnabled(options: Pick<GithubFeatureGateOptions, 'github' | 'auth'>): boolean {\n return options.github !== undefined && options.auth.enabled();\n}\n\n/**\n * Non-secret diagnostic snapshot of every GitHub feature gate. Used by startup\n * logs, `/web/github/status`, and the SPA so all three explain the same state.\n *\n * Only env var *names* and booleans are exposed — never secret values.\n */\nexport interface GithubFeatureDiagnostics {\n githubAppConfigured: boolean;\n factoryAuthEnabled: boolean;\n appDbConfigured: boolean;\n stateSecretConfigured: boolean;\n sandboxEnabled: boolean;\n sandboxProvider: string;\n /** Names of the GitHub App env vars still needed (empty when configured). */\n missingGithubAppEnvVars: string[];\n}\n\n/**\n * Collect a non-secret diagnostic snapshot of every GitHub feature gate. Centralizes\n * the feature-gate reasoning so startup logs, the status API, and the SPA explain\n * the same state. Does not change `isGithubFeatureEnabled()` behavior.\n */\nexport function getGithubFeatureDiagnostics(options: GithubFeatureGateOptions): GithubFeatureDiagnostics {\n const { github, auth, appDbConfigured, stateSigner, fleet } = options;\n return {\n githubAppConfigured: github !== undefined,\n factoryAuthEnabled: auth.enabled(),\n appDbConfigured,\n stateSecretConfigured: stateSigner?.stable ?? false,\n sandboxEnabled: fleet?.enabled ?? false,\n sandboxProvider: fleet?.provider ?? 'none',\n missingGithubAppEnvVars: github ? [] : [...GITHUB_APP_ENV_VARS],\n };\n}\n","/**\n * Org-scoped GitHub Personal Access Token settings.\n *\n * GitHub App installation tokens are the wrong credential for the `gh` CLI —\n * they hit \"Resource not accessible by integration\" on endpoints the CLI\n * needs regardless of the minted permission set. When an org pastes a PAT in\n * Settings, the sandbox `GH_TOKEN` injection sites and the\n * `github_refresh_token` tool use it instead of a minted installation token.\n * Tokens must be classic PATs whose account has access to the linked repos.\n *\n * Two kinds:\n * - `default` — the worker token every sandbox gets.\n * - `reviewer` — optional second token for review-board sessions, so PR\n * reviews come from a different account than the author. When it isn't\n * configured, review sessions fall back to the worker token.\n *\n * Both live in the generic `integration_settings` collection for the\n * `github` integration under a sentinel user id (the settings are org-wide,\n * but the schema keys settings per `(org, user)`). Tokens are never returned\n * to the browser — the routes only report whether each is configured.\n */\n\nimport type { GithubSubscriptionStorage } from './subscriptions.js';\n\n/** Sentinel `user_id` for the org-wide settings row. */\nconst PAT_SETTINGS_USER_ID = '__github_org_settings__';\n\nexport type GithubPatKind = 'default' | 'reviewer';\n\ntype GithubOrgSettings = { pat?: string; reviewerPat?: string };\n\nconst FIELD_FOR_KIND: Record<GithubPatKind, keyof GithubOrgSettings> = {\n default: 'pat',\n reviewer: 'reviewerPat',\n};\n\nfunction asToken(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n\n/** The PAT to install for `kind`, or null. `reviewer` falls back to the\n * worker token so review sessions still authenticate when no dedicated\n * reviewer token is configured. Fail-soft: storage errors (e.g. integration\n * storage not initialized in a partial test harness) read as \"no PAT\n * configured\" so token minting still works. */\nexport async function getGithubPat(\n getStorage: () => GithubSubscriptionStorage,\n orgId: string,\n kind: GithubPatKind = 'default',\n): Promise<string | null> {\n try {\n const settings = (await getStorage().settings.get(orgId, PAT_SETTINGS_USER_ID)) as GithubOrgSettings | null;\n if (!settings) return null;\n if (kind === 'reviewer') return asToken(settings.reviewerPat) ?? asToken(settings.pat);\n return asToken(settings.pat);\n } catch {\n return null;\n }\n}\n\n/** Which tokens are configured, without fallback semantics — feeds the\n * settings UI status badges. */\nexport async function getGithubPatStatus(\n getStorage: () => GithubSubscriptionStorage,\n orgId: string,\n): Promise<{ configured: boolean; reviewerConfigured: boolean }> {\n try {\n const settings = (await getStorage().settings.get(orgId, PAT_SETTINGS_USER_ID)) as GithubOrgSettings | null;\n return {\n configured: asToken(settings?.pat) !== null,\n reviewerConfigured: asToken(settings?.reviewerPat) !== null,\n };\n } catch {\n return { configured: false, reviewerConfigured: false };\n }\n}\n\nexport async function setGithubPat(\n storage: GithubSubscriptionStorage,\n orgId: string,\n pat: string,\n kind: GithubPatKind = 'default',\n): Promise<void> {\n const existing = ((await storage.settings.get(orgId, PAT_SETTINGS_USER_ID)) ?? {}) as GithubOrgSettings;\n await storage.settings.save(orgId, PAT_SETTINGS_USER_ID, { ...existing, [FIELD_FOR_KIND[kind]]: pat });\n}\n\nexport async function clearGithubPat(\n storage: GithubSubscriptionStorage,\n orgId: string,\n kind: GithubPatKind = 'default',\n): Promise<void> {\n const existing = (await storage.settings.get(orgId, PAT_SETTINGS_USER_ID)) as GithubOrgSettings | null;\n const field = FIELD_FOR_KIND[kind];\n if (!existing?.[field]) return;\n const { [field]: _removed, ...rest } = existing;\n await storage.settings.save(orgId, PAT_SETTINGS_USER_ID, rest);\n}\n","/**\n * Per-(project, user) lock that serializes the worktree/commit/push/PR flows.\n *\n * The push/PR flows temporarily rewrite the sandbox git remote to a tokenized\n * URL and scrub it again in a `finally`; two concurrent operations on the same\n * `(project, user)` sandbox could interleave those rewrites and leak a tokenized\n * remote. Serializing per `(project, user)` removes that race.\n *\n * There are two layers:\n * 1. An **in-process** promise-chain mutex keyed by the lock key, so repeated\n * same-replica callers stay cheap and never touch the database for ordering.\n * 2. The factory storage backend's **`withDistributedLock` capability** (pg:\n * transaction-scoped advisory locks) so that *different replicas*\n * operating on the same key also serialize. Backends without the\n * capability (libsql: local single-writer) fall back to the in-process\n * mutex alone — correct for single-replica deployments.\n *\n * Set `MASTRACODE_DISTRIBUTED_LOCK=0` to force-disable the distributed layer\n * (local dev, single replica) and fall back to the pure in-process mutex.\n */\n\nimport { createHash } from 'node:crypto';\n\nimport type { FactoryStorage } from '@mastra/core/storage';\n\n/** Minimal pg pool surface used by the distributed lock (for testability). */\nexport interface LockPool {\n connect(): Promise<LockClient>;\n}\nexport interface LockClient {\n query(sql: string, params?: unknown[]): Promise<unknown>;\n release(): void;\n}\n\nconst inProcessLocks = new Map<string, Promise<unknown>>();\n\n/**\n * True when the cross-replica lock layer should be used: not force-disabled\n * via env, and the factory storage backend exposes the\n * `withDistributedLock` capability.\n */\nexport function isDistributedLockEnabled(storage: FactoryStorage | undefined): boolean {\n if (process.env.MASTRACODE_DISTRIBUTED_LOCK === '0') return false;\n return typeof storage?.withDistributedLock === 'function';\n}\n\n/**\n * Hash a lock key into the two signed 32-bit integers that the two-arg form of\n * `pg_advisory_xact_lock(int4, int4)` expects. Using two int4 args (rather than\n * one int8) keeps the key inside the GitHub-feature advisory-lock namespace and\n * avoids collisions with other single-int8 advisory locks.\n */\nexport function hashKey(key: string): [number, number] {\n const digest = createHash('sha256').update(key).digest();\n // Read two independent 32-bit halves as signed int4 values.\n const a = digest.readInt32BE(0);\n const b = digest.readInt32BE(4);\n return [a, b];\n}\n\n/**\n * Run `fn` while holding the lock for `key`. Same-replica callers serialize via\n * the in-process mutex; cross-replica callers additionally serialize via a\n * Postgres transaction-scoped advisory lock (unless disabled).\n *\n * The in-process chain swallows rejections so one failed operation does not\n * poison the lock for subsequent callers.\n */\nexport function withProjectLock<T>(options: {\n key: string;\n /** Factory storage backend supplying the `withDistributedLock` capability, when available. */\n storage?: FactoryStorage;\n fn: () => Promise<T>;\n /** Test seam: fake pg pool standing in for the distributed layer. */\n pool?: LockPool;\n}): Promise<T> {\n const { key, storage, fn, pool } = options;\n const prev = inProcessLocks.get(key) ?? Promise.resolve();\n const run = () => withDbAdvisoryLock({ key, storage, fn, pool });\n const next = prev.then(run, run);\n const tail = next.then(\n () => undefined,\n () => undefined,\n );\n inProcessLocks.set(key, tail);\n // Drop the entry once this operation settles, but only if no later caller has\n // chained onto it in the meantime — otherwise we'd evict a live waiter's tail.\n // This keeps the map from growing unbounded across many distinct project keys.\n void tail.then(() => {\n if (inProcessLocks.get(key) === tail) {\n inProcessLocks.delete(key);\n }\n });\n return next;\n}\n\n/**\n * Acquire only the cross-replica lock for `key` and run `fn` under it. This is\n * the distributed serialization layer; `withProjectLock` wraps it with an\n * in-process mutex for same-replica callers. Delegates to the factory storage\n * backend's `withDistributedLock` capability; backends without it (or a\n * force-disabled env) run `fn` directly — the in-process mutex still holds.\n *\n * `poolOverride` keeps the pg advisory-lock path directly testable with a fake\n * pool (each simulated replica has its own in-process state but shares one\n * database).\n */\nexport async function withDbAdvisoryLock<T>(options: {\n key: string;\n storage?: FactoryStorage;\n fn: () => Promise<T>;\n pool?: LockPool;\n}): Promise<T> {\n const { key, storage, fn, pool } = options;\n if (process.env.MASTRACODE_DISTRIBUTED_LOCK === '0') {\n return fn();\n }\n\n if (pool) return advisoryLockOver(pool, key, fn);\n\n if (typeof storage?.withDistributedLock !== 'function') {\n return fn();\n }\n return storage.withDistributedLock(key, fn);\n}\n\n/** The pg advisory-lock body, kept for the `poolOverride` test seam. */\nasync function advisoryLockOver<T>(pool: LockPool, key: string, fn: () => Promise<T>): Promise<T> {\n const [k1, k2] = hashKey(key);\n const client = await pool.connect();\n try {\n await client.query('BEGIN');\n // Blocks until no other transaction holds this advisory key. Auto-released\n // when the transaction ends below.\n await client.query('SELECT pg_advisory_xact_lock($1, $2)', [k1, k2]);\n try {\n const result = await fn();\n await client.query('COMMIT');\n return result;\n } catch (err) {\n await client.query('ROLLBACK');\n throw err;\n }\n } finally {\n client.release();\n }\n}\n\n/** For tests: clear the in-process lock chains. */\nexport function __resetProjectLocksForTests(): void {\n inProcessLocks.clear();\n}\n","/**\n * Repo materialization for GitHub-backed repositories.\n *\n * A GitHub repo is never cloned onto the server host. Instead each project gets\n * its own isolated sandbox (provisioned by the fleet in `../sandbox/fleet`) and\n * the repo is cloned *inside* that sandbox. The agent's file tools and command\n * tools then operate entirely against the remote checkout.\n *\n * - `ensureProjectSandbox(row)` / `teardownProjectSandbox(row)` bind the fleet's\n * provision/reattach/teardown lifecycle to the per-(project,user) sandbox row.\n * - `materializeRepo(row, token)` runs `git clone` (first open) or `git pull`\n * (re-open) inside the sandbox, using a short-lived installation token that is\n * scrubbed from the git remote afterwards so it never persists in the VM.\n *\n * This module owns everything git/GitHub: clone/pull, commit/push, worktrees,\n * and `gh pr create`. Sandbox provisioning, budgets, and workdir layout live in\n * the fleet module.\n */\n\nimport { createHash } from 'node:crypto';\nimport { reportProgress } from '../../sandbox/fleet.js';\nimport type {\n MaterializationSandbox,\n ProgressFn,\n SandboxBindingStore,\n SandboxCommandResult,\n SandboxFleet,\n} from '../../sandbox/fleet.js';\nimport type {\n ProjectRepositorySandbox,\n SourceControlStorageHandle,\n} from '../../storage/domains/source-control/base.js';\n\ntype SourceControlSandboxStorage = SourceControlStorageHandle['sandboxes'];\ntype MaterializationStore = Pick<SourceControlSandboxStorage, 'markMaterialized'>;\n\ninterface RepoMaterializationBinding {\n id: string;\n sandboxWorkdir: string;\n materializedAt: Date | null;\n}\n\n/** Adapt a per-(project,user) sandbox binding row to the fleet's persistence seam. */\nfunction bindingStore(row: ProjectRepositorySandbox, storage: SourceControlSandboxStorage): SandboxBindingStore {\n return {\n sandboxId: row.sandboxId,\n setSandboxId: id =>\n id === null ? storage.clearBinding({ id: row.id }) : storage.setSandboxId({ id: row.id, sandboxId: id }),\n clear: () => storage.clearBinding({ id: row.id }),\n };\n}\n\n/**\n * Provision a new sandbox (persisting its provider id on first open) or\n * reattach to the stored one. Returns a started, live sandbox.\n */\nexport async function ensureProjectSandbox(options: {\n fleet: SandboxFleet;\n row: ProjectRepositorySandbox;\n storage: SourceControlSandboxStorage;\n token: string;\n onProgress?: ProgressFn;\n}): Promise<MaterializationSandbox> {\n const { fleet, row, storage, token, onProgress } = options;\n return fleet.ensureSandbox(bindingStore(row, storage), { GH_TOKEN: token }, onProgress);\n}\n\n/**\n * Tear down a user's sandbox for a project: stop the live VM (best-effort) and\n * clear the persisted `sandboxId`/`materializedAt` on the per-(project,user)\n * binding row so the next open re-provisions cleanly.\n *\n * @param row the per-(project,user) sandbox binding to tear down\n * @param sandbox an already-reattached live sandbox to stop, when available\n */\nexport async function teardownProjectSandbox(options: {\n fleet: SandboxFleet;\n row: ProjectRepositorySandbox;\n storage: SourceControlSandboxStorage;\n sandbox?: MaterializationSandbox;\n}): Promise<void> {\n const { fleet, row, storage, sandbox } = options;\n return fleet.teardownSandbox(bindingStore(row, storage), sandbox);\n}\n\n/**\n * Single-quote a string for safe POSIX shell interpolation. Wraps the value in\n * single quotes and escapes any embedded single quote using the canonical\n * close-quote / escaped-quote / reopen-quote sequence (`'\\''`). This is the\n * standard POSIX-safe construction and prevents the quoted string from being\n * terminated early.\n */\nexport function shellQuote(value: string): string {\n // Replace each ' with the four-character sequence: ' \\ ' '\n return `'` + value.split(`'`).join(`'\\\\''`) + `'`;\n}\n\n/** Run a shell script in the sandbox via `sh -c`. */\nasync function sh(sandbox: MaterializationSandbox, script: string): Promise<SandboxCommandResult> {\n return sandbox.executeCommand('sh', ['-c', script]);\n}\n\n/** Error raised when the sandbox cannot materialize the repo (actionable). */\nexport class MaterializeError extends Error {\n constructor(\n message: string,\n readonly code:\n | 'git-missing'\n | 'egress-blocked'\n | 'clone-failed'\n | 'pull-failed'\n | 'push-failed'\n | 'commit-failed'\n | 'gh-missing'\n | 'pr-failed',\n ) {\n super(message);\n this.name = 'MaterializeError';\n }\n}\n\n/**\n * Build the token-auth clone/pull URL for a repo. The token lives only inside\n * this URL and is scrubbed from the remote after the operation.\n */\nfunction tokenUrl(repoFullName: string, token: string): string {\n return `https://x-access-token:${token}@github.com/${repoFullName}.git`;\n}\n\nfunction cleanUrl(repoFullName: string): string {\n return `https://github.com/${repoFullName}.git`;\n}\n\n/** Repo metadata needed to materialize, read from the org-owned project row. */\nexport interface RepoMaterializeInfo {\n repoFullName: string;\n defaultBranch: string;\n}\n\n/**\n * Materialize the repo inside the user's sandbox. Clones on first open, pulls on\n * re-open. Always scrubs the install token from the remote afterwards and sets\n * `materialized_at` on the per-user sandbox binding row.\n *\n */\nexport async function materializeRepo(options: {\n /** The per-(project,user) sandbox binding (provisioned via `ensureProjectSandbox`). */\n row: RepoMaterializationBinding;\n /** Repo metadata from the org-owned project row. */\n repoInfo: RepoMaterializeInfo;\n /** The live sandbox to run git inside. */\n sandbox: MaterializationSandbox;\n /** A freshly minted, short-lived installation access token. */\n token: string;\n storage: MaterializationStore;\n onProgress?: ProgressFn;\n}): Promise<void> {\n const { row: sandboxRow, repoInfo, sandbox, token, storage, onProgress } = options;\n const workdir = sandboxRow.sandboxWorkdir;\n const repo = repoInfo.repoFullName;\n\n // 0. Defense in depth: never build a git command from values that aren't\n // strictly shaped, even if a malformed row reached the DB. Inputs are also\n // validated at the route boundary before storage.\n if (!/^[\\w.-]+\\/[\\w.-]+$/.test(repo)) {\n throw new MaterializeError(`Refusing to materialize: invalid repo full name '${repo}'.`, 'clone-failed');\n }\n if (!/^[A-Za-z0-9_./-]+$/.test(repoInfo.defaultBranch)) {\n throw new MaterializeError(\n `Refusing to materialize: invalid default branch '${repoInfo.defaultBranch}'.`,\n 'clone-failed',\n );\n }\n\n // 1. Preflight: git must be installed in the sandbox template.\n const gitVersion = await sh(sandbox, 'git --version');\n if (gitVersion.exitCode !== 0) {\n throw new MaterializeError(\n 'git is not installed in the sandbox. The sandbox template must include git.',\n 'git-missing',\n );\n }\n\n const authUrl = tokenUrl(repo, token);\n\n // The DB's `materializedAt` can drift from disk — a fresh per-user binding\n // row over an already-populated workdir (local dev DB resets, repaired\n // rows, earlier flows) would make `git clone` fail on the non-empty\n // directory. Re-detect an existing checkout of this repo and pull instead.\n const alreadyMaterialized = Boolean(sandboxRow.materializedAt) || (await hasExistingCheckout(sandbox, workdir, repo));\n\n try {\n if (!alreadyMaterialized) {\n // 2a. First open: shallow-clone the default branch into the workdir. A\n // shallow single-branch clone is dramatically faster for large repos; the\n // later re-open uses `git pull --ff-only`, which works on shallow clones.\n reportProgress(onProgress, {\n phase: 'cloning',\n message: `Cloning ${repo} (first open can take a minute)…`,\n });\n const clone = await sh(\n sandbox,\n `git clone --depth=1 --single-branch --branch ${shellQuote(repoInfo.defaultBranch)} ${shellQuote(authUrl)} ${shellQuote(workdir)}`,\n );\n if (clone.exitCode !== 0) {\n throw classifyGitFailure(clone, 'clone-failed');\n }\n } else {\n // 2b. Re-open: refresh remote to the token URL and fast-forward pull.\n reportProgress(onProgress, { phase: 'pulling', message: `Updating ${repo} to the latest changes…` });\n const setUrl = await sh(sandbox, `git -C ${shellQuote(workdir)} remote set-url origin ${shellQuote(authUrl)}`);\n if (setUrl.exitCode !== 0) {\n throw new MaterializeError(`Failed to set git remote: ${setUrl.stderr}`, 'pull-failed');\n }\n const pull = await sh(sandbox, `git -C ${shellQuote(workdir)} pull --ff-only`);\n if (pull.exitCode !== 0) {\n throw classifyGitFailure(pull, 'pull-failed');\n }\n }\n } finally {\n // 3. Always scrub the token from the remote so it isn't left in the VM's\n // git config, even when the clone/pull above failed partway through. This\n // is best-effort on the failure path (the workdir may not exist yet after a\n // failed clone); on the success path the scrub must succeed or we surface it.\n await scrubRemote(sandbox, workdir, repo, alreadyMaterialized);\n }\n\n // 4. Mark materialized.\n reportProgress(onProgress, { phase: 'finalizing', message: 'Finalizing workspace…' });\n await storage.markMaterialized({ id: sandboxRow.id });\n}\n\n/** Check out a session's branch inside its isolated repository clone. */\nexport async function checkoutSessionBranch(\n sandbox: MaterializationSandbox,\n workdir: string,\n {\n branch,\n baseBranch,\n token,\n repoFullName,\n }: { branch: string; baseBranch: string; token: string; repoFullName: string },\n): Promise<void> {\n if (!isValidGitRef(branch) || !isValidGitRef(baseBranch)) {\n throw new MaterializeError('Refusing to create a session from an invalid branch name.', 'clone-failed');\n }\n\n const current = await sh(sandbox, `git -C ${shellQuote(workdir)} branch --show-current`);\n if (current.exitCode === 0 && current.stdout.trim() === branch) return;\n\n const local = await sh(\n sandbox,\n `git -C ${shellQuote(workdir)} show-ref --verify --quiet refs/heads/${shellQuote(branch)}`,\n );\n if (local.exitCode === 0) {\n const checkout = await sh(sandbox, `git -C ${shellQuote(workdir)} checkout ${shellQuote(branch)}`);\n if (checkout.exitCode !== 0) throw classifyGitFailure(checkout, 'clone-failed');\n return;\n }\n\n const authUrl = tokenUrl(repoFullName, token);\n try {\n const setUrl = await sh(sandbox, `git -C ${shellQuote(workdir)} remote set-url origin ${shellQuote(authUrl)}`);\n if (setUrl.exitCode !== 0) throw classifyGitFailure(setUrl, 'pull-failed');\n const fetch = await sh(\n sandbox,\n `git -C ${shellQuote(workdir)} fetch origin ${shellQuote(baseBranch)} && git -C ${shellQuote(workdir)} checkout -b ${shellQuote(branch)} FETCH_HEAD`,\n );\n if (fetch.exitCode !== 0) throw classifyGitFailure(fetch, 'clone-failed');\n } finally {\n await sh(sandbox, `git -C ${shellQuote(workdir)} remote set-url origin ${shellQuote(cleanUrl(repoFullName))}`);\n }\n}\n\n/**\n * True when the workdir already holds a git checkout whose `origin` points at\n * this exact repo. Matches both the clean and token-auth URL forms; any other\n * remote (or no git dir at all) falls back to the clone path.\n */\nasync function hasExistingCheckout(\n sandbox: MaterializationSandbox,\n workdir: string,\n repoFullName: string,\n): Promise<boolean> {\n const result = await sh(sandbox, `git -C ${shellQuote(workdir)} remote get-url origin`);\n if (result.exitCode !== 0) return false;\n const url = result.stdout.trim().toLowerCase();\n const suffix = `github.com/${repoFullName.toLowerCase()}`;\n return url.endsWith(`${suffix}.git`) || url.endsWith(suffix);\n}\n\n/**\n * Reset the git remote back to the tokenless URL. On a successful clone/pull the\n * workdir always has a `.git`, so a non-zero exit code here means the token may\n * still be persisted — surface it. On the failure path the workdir may not exist\n * (e.g. a failed clone), so a non-zero exit is tolerated.\n */\nasync function scrubRemote(\n sandbox: MaterializationSandbox,\n workdir: string,\n repoFullName: string,\n expectGitDir: boolean,\n): Promise<void> {\n const result = await sh(\n sandbox,\n `git -C ${shellQuote(workdir)} remote set-url origin ${shellQuote(cleanUrl(repoFullName))}`,\n );\n if (result.exitCode !== 0 && expectGitDir) {\n throw new MaterializeError(\n `Failed to scrub installation token from git remote: ${result.stderr.trim() || result.stdout.trim()}`,\n 'pull-failed',\n );\n }\n}\n\n/**\n * Turn a failed git command into an actionable error, detecting the common\n * \"cannot reach github.com\" egress failure.\n */\nfunction classifyGitFailure(\n result: SandboxCommandResult,\n fallback: 'clone-failed' | 'pull-failed' | 'push-failed',\n): MaterializeError {\n const stderr = result.stderr || '';\n if (/could not resolve host|failed to connect|network is unreachable|Connection timed out/i.test(stderr)) {\n return new MaterializeError(\n 'The sandbox could not reach github.com. The sandbox network must allow outbound egress to github.com.',\n 'egress-blocked',\n );\n }\n const verb = fallback === 'clone-failed' ? 'clone' : fallback === 'pull-failed' ? 'pull' : 'push';\n return new MaterializeError(`git ${verb} failed: ${stderr}`, fallback);\n}\n\n// ---------------------------------------------------------------------------\n// Phase 1 — git identity + token-scoped push primitive\n//\n// These helpers let the sandbox author and push commits safely. The install\n// token is short-lived, minted per-operation server-side, injected only into\n// the temporary remote URL inside the sandbox, and always scrubbed in a\n// `finally` so it never persists in `.git/config`.\n// ---------------------------------------------------------------------------\n\n/**\n * Validate a git ref (branch) name. Server-side defense-in-depth: only allow a\n * conservative character set so a branch can never be built into a shell\n * command in a way that escapes quoting. Mirrors the route-layer check.\n */\nexport function isValidGitRef(value: unknown): value is string {\n return (\n typeof value === 'string' &&\n value.length > 0 &&\n value.length <= 255 &&\n // Reject leading-dash refs (e.g. `--mirror`) so the value can never be\n // parsed as a git option when interpolated into a command.\n !value.startsWith('-') &&\n /^[A-Za-z0-9_./-]+$/.test(value)\n );\n}\n\n/** Identity used to author commits inside the sandbox. */\nexport interface GitIdentity {\n name?: string | null;\n email?: string | null;\n /** GitHub login, used to derive a stable noreply identity when name/email are absent. */\n login?: string | null;\n}\n\n/**\n * Resolve a concrete `{ name, email }` for git authorship from a possibly-sparse\n * identity. Falls back to a GitHub-style noreply identity so commits are never\n * authored with an empty or host-derived identity.\n */\nexport function resolveGitIdentity(identity: GitIdentity): { name: string; email: string } {\n const login = (identity.login || '').trim();\n const name = (identity.name || '').trim() || login || 'Mastra Code';\n const email =\n (identity.email || '').trim() ||\n (login ? `${login}@users.noreply.github.com` : 'mastra-code@users.noreply.github.com');\n return { name, email };\n}\n\n/**\n * Configure `user.name` / `user.email` for the given repo working tree inside\n * the sandbox so commits are authored correctly. Values are shell-quoted.\n */\nexport async function configureGitIdentity(\n sandbox: MaterializationSandbox,\n workdir: string,\n identity: GitIdentity,\n): Promise<void> {\n const { name, email } = resolveGitIdentity(identity);\n const setName = await sh(sandbox, `git -C ${shellQuote(workdir)} config user.name ${shellQuote(name)}`);\n if (setName.exitCode !== 0) {\n throw new MaterializeError(`Failed to set git user.name: ${setName.stderr.trim()}`, 'commit-failed');\n }\n const setEmail = await sh(sandbox, `git -C ${shellQuote(workdir)} config user.email ${shellQuote(email)}`);\n if (setEmail.exitCode !== 0) {\n throw new MaterializeError(`Failed to set git user.email: ${setEmail.stderr.trim()}`, 'commit-failed');\n }\n}\n\n/**\n * Temporarily rewrite `origin` to a tokenized URL, run `fn` (e.g. a push), and\n * **always** scrub the remote back to the tokenless URL in a `finally`. The\n * token therefore only ever lives in the remote URL for the duration of the\n * operation and is never left in the VM's git config.\n *\n * On the success path the scrub must succeed (a leaked token is a hard error);\n * if it fails we surface it. On the failure path the scrub is best-effort but\n * still attempted, and the original operation error is rethrown.\n */\nexport async function withInstallToken<T>(\n sandbox: MaterializationSandbox,\n workdir: string,\n repoFullName: string,\n token: string,\n fn: () => Promise<T>,\n): Promise<T> {\n if (!/^[\\w.-]+\\/[\\w.-]+$/.test(repoFullName)) {\n throw new MaterializeError(`Refusing to push: invalid repo full name '${repoFullName}'.`, 'push-failed');\n }\n\n const setUrl = await sh(\n sandbox,\n `git -C ${shellQuote(workdir)} remote set-url origin ${shellQuote(tokenUrl(repoFullName, token))}`,\n );\n if (setUrl.exitCode !== 0) {\n // Best-effort scrub even though set-url failed, then surface the failure.\n await scrubRemote(sandbox, workdir, repoFullName, false);\n throw new MaterializeError(`Failed to set git remote: ${setUrl.stderr.trim()}`, 'push-failed');\n }\n\n try {\n return await fn();\n } finally {\n // Always restore the tokenless remote. The workdir has a `.git` (we just\n // rewrote its remote) so a scrub failure means the token may still persist\n // — surface it.\n await scrubRemote(sandbox, workdir, repoFullName, true);\n }\n}\n\n/**\n * Push a branch back to GitHub from inside the sandbox using a short-lived\n * installation token. The branch is ref-validated, the token is injected only\n * into the remote URL via `withInstallToken`, and egress failures are\n * classified into actionable errors.\n */\nexport async function pushBranch(\n sandbox: MaterializationSandbox,\n workdir: string,\n branch: string,\n token: string,\n repoFullName: string,\n): Promise<void> {\n if (!isValidGitRef(branch)) {\n throw new MaterializeError(`Refusing to push: invalid branch name '${branch}'.`, 'push-failed');\n }\n\n await withInstallToken(sandbox, workdir, repoFullName, token, async () => {\n const push = await sh(sandbox, `git -C ${shellQuote(workdir)} push -u origin ${shellQuote(branch)}`);\n if (push.exitCode !== 0) {\n throw classifyGitFailure(push, 'push-failed');\n }\n });\n}\n\nexport interface CommitResult {\n /** True when a commit was created; false when there was nothing to commit. */\n committed: boolean;\n}\n\n/**\n * Stage every change in the working tree and create a commit inside the\n * sandbox. The git identity is configured first so authorship is correct. When\n * there is nothing to commit this is a no-op (`committed: false`) rather than an\n * error, so callers can safely commit-then-push without first diffing.\n *\n * @param sandbox the live sandbox containing the checkout\n * @param workdir the worktree (or repo) path to commit in\n * @param message the commit message (quoted; arbitrary text is safe)\n * @param identity authorship identity for the commit\n */\nexport async function commitAll(\n sandbox: MaterializationSandbox,\n workdir: string,\n message: string,\n identity: GitIdentity,\n): Promise<CommitResult> {\n await configureGitIdentity(sandbox, workdir, identity);\n\n const add = await sh(sandbox, `git -C ${shellQuote(workdir)} add -A`);\n if (add.exitCode !== 0) {\n throw new MaterializeError(`git add failed: ${add.stderr.trim() || add.stdout.trim()}`, 'commit-failed');\n }\n\n // Nothing staged → nothing to commit. `git diff --cached --quiet` exits 1 when\n // there are staged changes, 0 when the index is clean.\n const staged = await sh(sandbox, `git -C ${shellQuote(workdir)} diff --cached --quiet`);\n if (staged.exitCode === 0) {\n return { committed: false };\n }\n\n const commit = await sh(sandbox, `git -C ${shellQuote(workdir)} commit -m ${shellQuote(message)}`);\n if (commit.exitCode !== 0) {\n throw new MaterializeError(`git commit failed: ${commit.stderr.trim() || commit.stdout.trim()}`, 'commit-failed');\n }\n\n return { committed: true };\n}\n\n// ---------------------------------------------------------------------------\n// Phase 2 — worktree / branch lifecycle\n//\n// Each unit of work gets its own branch + working tree inside the same sandbox\n// as the base checkout. The worktree path is always computed server-side from a\n// sanitized branch name; client input never reaches a filesystem path.\n// ---------------------------------------------------------------------------\n\n/** Error raised when a worktree cannot be created/reused inside the sandbox. */\nexport class WorktreeError extends Error {\n constructor(\n message: string,\n readonly code: 'invalid-branch' | 'worktree-failed' | 'setup-failed',\n ) {\n super(message);\n this.name = 'WorktreeError';\n }\n}\n\n/**\n * Reduce a (already ref-validated) branch name to a filesystem-safe directory\n * segment for the worktree path: slashes/dots/unsafe chars collapsed to `-`.\n * This only affects the *directory name*, never the git branch itself.\n *\n * Sanitization is lossy (e.g. `feat/a` and `feat-a` both reduce to `feat-a`),\n * so an 8-char hash of the original branch is appended whenever the sanitized\n * form differs from the input. That keeps clean names (`main`) readable while\n * guaranteeing distinct branches never share a worktree directory.\n */\nexport function safeBranchDir(branch: string): string {\n const sanitized =\n branch\n .replace(/[^A-Za-z0-9._-]+/g, '-')\n .replace(/\\/+/g, '-')\n .replace(/^[-.]+|[-.]+$/g, '')\n .slice(0, 100) || 'work';\n if (sanitized === branch) return sanitized;\n const hash = createHash('sha256').update(branch).digest('hex').slice(0, 8);\n return `${sanitized}-${hash}`;\n}\n\n/**\n * Compute the absolute worktree path for a branch, server-side only. Worktrees\n * live alongside the repo checkout under a sibling `worktrees/` directory so the\n * repo's `.git` is shared. Never derived from client-supplied paths.\n */\nexport function computeWorktreePath(repoWorkdir: string, branch: string): string {\n const parent = repoWorkdir.replace(/\\/+$/, '').split('/').slice(0, -1).join('/') || '';\n return `${parent}/worktrees/${safeBranchDir(branch)}`;\n}\n\nexport interface EnsureWorktreeResult {\n worktreePath: string;\n branch: string;\n baseBranch: string;\n /** True when an existing worktree was reused rather than freshly created. */\n reused: boolean;\n}\n\n/**\n * Create (or reuse) a git worktree + branch inside the sandbox for a unit of\n * work. Idempotent: if a worktree already exists at the computed path it is\n * reused. The branch is created from the freshly fetched `origin/<baseBranch>`\n * — never the sandbox's possibly stale local ref — so new worktrees always\n * start from the latest remote state.\n *\n * @param sandbox live sandbox containing the base checkout\n * @param repoWorkdir the base repo checkout path inside the sandbox\n * @param branch the feature branch (ref-validated server-side)\n * @param baseBranch the branch to fork from (ref-validated; defaults to the repo's default branch)\n * @param token short-lived installation token used only for the base-branch fetch\n * @param repoFullName `owner/repo` used to build the tokenized remote URL\n */\nexport async function ensureWorktree(\n sandbox: MaterializationSandbox,\n repoWorkdir: string,\n {\n branch,\n baseBranch,\n token,\n repoFullName,\n }: { branch: string; baseBranch: string; token: string; repoFullName: string },\n): Promise<EnsureWorktreeResult> {\n if (!isValidGitRef(branch)) {\n throw new WorktreeError(`Invalid branch name '${branch}'.`, 'invalid-branch');\n }\n if (!isValidGitRef(baseBranch)) {\n throw new WorktreeError(`Invalid base branch name '${baseBranch}'.`, 'invalid-branch');\n }\n\n const worktreePath = computeWorktreePath(repoWorkdir, branch);\n\n // Idempotent reuse: a worktree already checked out at this path has a `.git`\n // file (worktrees use a gitfile, not a directory). Reuse it as-is.\n const exists = await sh(sandbox, `test -e ${shellQuote(`${worktreePath}/.git`)}`);\n if (exists.exitCode === 0) {\n return { worktreePath, branch, baseBranch, reused: true };\n }\n\n // Fetch the latest base ref from origin before forking. The explicit refspec\n // updates `refs/remotes/origin/<base>` even when the checkout was created as\n // a single-branch clone. The fetch needs the install token (the resting\n // remote is tokenless), and a failure is a hard error — silently forking a\n // stale local ref is worse than failing the request.\n const baseRef = `origin/${baseBranch}`;\n await withInstallToken(sandbox, repoWorkdir, repoFullName, token, async () => {\n const fetch = await sh(\n sandbox,\n `git -C ${shellQuote(repoWorkdir)} fetch origin ${shellQuote(`+refs/heads/${baseBranch}:refs/remotes/${baseRef}`)}`,\n );\n if (fetch.exitCode !== 0) {\n throw classifyGitFailure(fetch, 'pull-failed');\n }\n });\n\n // Create the worktree. If the branch already exists, check it out into the\n // worktree; otherwise create it from the fetched base. `git worktree add -B`\n // creates-or-resets the branch to the base, which keeps this idempotent for a\n // fresh worktree while still working when the branch already exists remotely.\n // `--no-track` keeps the feature branch from tracking origin/<base>; pushes\n // set their own upstream via `push -u`.\n const add = await sh(\n sandbox,\n `git -C ${shellQuote(repoWorkdir)} worktree add --no-track -B ${shellQuote(branch)} ${shellQuote(worktreePath)} ${shellQuote(baseRef)}`,\n );\n if (add.exitCode !== 0) {\n throw new WorktreeError(`git worktree add failed: ${add.stderr.trim() || add.stdout.trim()}`, 'worktree-failed');\n }\n\n return { worktreePath, branch, baseBranch, reused: false };\n}\n\n/**\n * Run the project's setup command (e.g. `pnpm i && pnpm build`) inside a\n * freshly created worktree. Called before the worktree is handed to any agent\n * run so the checkout is ready to build/test. A non-zero exit is a hard error —\n * starting agent work in a half-set-up tree is worse than failing the request.\n *\n * Security model: the command is intentionally arbitrary shell — that is the\n * feature (install deps, build, seed fixtures). It is only configurable by\n * authenticated org members (the settings route is gated by\n * `resolveOrgTenant` + org-scoped project lookup, with length and\n * control-character validation), and it executes exclusively inside the\n * project's isolated sandbox — the same environment where org members already\n * run arbitrary shell via the agent's command tool. It never runs on the web\n * server host, so it grants no privilege beyond what sandbox access already\n * provides.\n *\n * @param sandbox live sandbox containing the worktree\n * @param worktreePath the server-computed worktree path the command runs in\n * @param command the org-configured setup shell command\n */\nexport async function runWorktreeSetup(\n sandbox: MaterializationSandbox,\n worktreePath: string,\n command: string,\n): Promise<void> {\n const result = await sh(sandbox, `cd ${shellQuote(worktreePath)} && { ${command}\\n}`);\n if (result.exitCode !== 0) {\n const detail = (result.stderr.trim() || result.stdout.trim()).slice(-2000);\n throw new WorktreeError(`Setup command failed (exit ${result.exitCode}): ${detail}`, 'setup-failed');\n }\n}\n\n/**\n * Remove a worktree (and its local feature branch) from the sandbox. The\n * checkout is removed with `--force` — the caller owns confirming that any\n * uncommitted work in it can be discarded. Idempotent: a worktree whose\n * directory is already gone only has its metadata pruned.\n *\n * @param sandbox live sandbox containing the base checkout\n * @param repoWorkdir the base repo checkout path inside the sandbox\n * @param branch the worktree's feature branch (ref-validated)\n * @param worktreePath the persisted, server-computed worktree path\n */\nexport async function removeWorktree(\n sandbox: MaterializationSandbox,\n repoWorkdir: string,\n { branch, worktreePath }: { branch: string; worktreePath: string },\n): Promise<void> {\n if (!isValidGitRef(branch)) {\n throw new WorktreeError(`Invalid branch name '${branch}'.`, 'invalid-branch');\n }\n\n const remove = await sh(\n sandbox,\n `git -C ${shellQuote(repoWorkdir)} worktree remove --force ${shellQuote(worktreePath)}`,\n );\n if (remove.exitCode !== 0) {\n // Tolerate a checkout that's already gone (e.g. a fresh sandbox after\n // re-provisioning): prune stale metadata and only fail when the directory\n // still exists, meaning git genuinely refused to remove it.\n await sh(sandbox, `git -C ${shellQuote(repoWorkdir)} worktree prune`);\n const exists = await sh(sandbox, `test -e ${shellQuote(worktreePath)}`);\n if (exists.exitCode === 0) {\n throw new WorktreeError(\n `git worktree remove failed: ${remove.stderr.trim() || remove.stdout.trim()}`,\n 'worktree-failed',\n );\n }\n }\n\n // Best-effort local branch cleanup; the branch may not exist locally anymore\n // or may still be pushed remotely — neither should fail the removal.\n await sh(sandbox, `git -C ${shellQuote(repoWorkdir)} branch -D ${shellQuote(branch)}`);\n}\n\n// ---------------------------------------------------------------------------\n// Phase 3 — `gh` CLI pull-request creation primitive\n//\n// PRs are opened from inside the sandbox with the GitHub CLI. `gh` must be\n// present in the sandbox template (preflighted only on the PR path so clone /\n// open still work when it is absent). The token is passed to `gh` via a\n// per-invocation `GH_TOKEN` env that is scoped to the single `gh` process and\n// never written to git config, a shell rc, or the VM's environment.\n// ---------------------------------------------------------------------------\n\nexport interface CreatePullRequestArgs {\n /** Short-lived installation token, injected only into the `gh` process env. */\n token: string;\n /** Base branch the PR merges into. Ref-validated. */\n base: string;\n /** Head branch the PR is opened from. Ref-validated. */\n head: string;\n /** PR title. */\n title: string;\n /** PR body (optional). */\n body?: string;\n}\n\nexport interface CreatePullRequestResult {\n /** The PR URL parsed from `gh pr create` stdout. */\n url: string;\n}\n\n/**\n * Preflight that `gh` is installed in the sandbox. Only called on the PR path so\n * a missing `gh` never blocks clone/open. Surfaces an actionable error naming\n * the sandbox template requirement.\n */\nasync function assertGhAvailable(sandbox: MaterializationSandbox): Promise<void> {\n const version = await sh(sandbox, 'gh --version');\n if (version.exitCode !== 0) {\n throw new MaterializeError(\n 'The GitHub CLI (gh) is not installed in the sandbox. The sandbox template must include gh to open pull requests.',\n 'gh-missing',\n );\n }\n}\n\n/** Match the first GitHub PR URL in `gh pr create` output. */\nfunction parsePullRequestUrl(stdout: string): string | undefined {\n const match = stdout.match(/https:\\/\\/github\\.com\\/[^\\s]+\\/pull\\/\\d+/);\n return match?.[0];\n}\n\n/**\n * Open a pull request from inside the sandbox via `gh pr create`. The token is\n * passed only through a per-invocation `GH_TOKEN` env scoped to the single `gh`\n * process (never persisted), all arguments are shell-quoted, and the resulting\n * PR URL is parsed from stdout.\n *\n * @param sandbox live sandbox containing the checkout\n * @param workdir the worktree (or repo) path the PR head branch is checked out in\n */\nexport async function createPullRequest(\n sandbox: MaterializationSandbox,\n workdir: string,\n { token, base, head, title, body }: CreatePullRequestArgs,\n): Promise<CreatePullRequestResult> {\n if (!isValidGitRef(base)) {\n throw new MaterializeError(`Refusing to open PR: invalid base branch '${base}'.`, 'pr-failed');\n }\n if (!isValidGitRef(head)) {\n throw new MaterializeError(`Refusing to open PR: invalid head branch '${head}'.`, 'pr-failed');\n }\n\n await assertGhAvailable(sandbox);\n\n // GH_TOKEN is prefixed inline so it is exported only to the single `gh`\n // process and never to the wider shell session, git config, or VM env. `gh`\n // is run from inside the checkout so it targets the correct repo/head branch.\n const ghCommand = [\n `GH_TOKEN=${shellQuote(token)} gh pr create`,\n `--base ${shellQuote(base)}`,\n `--head ${shellQuote(head)}`,\n `--title ${shellQuote(title)}`,\n `--body ${shellQuote(body ?? '')}`,\n ].join(' ');\n const script = `cd ${shellQuote(workdir)} && ${ghCommand}`;\n\n const result = await sh(sandbox, script);\n if (result.exitCode !== 0) {\n const classified = classifyGitFailure(result, 'push-failed');\n if (classified.code === 'egress-blocked') {\n throw classified;\n }\n throw new MaterializeError(`gh pr create failed: ${result.stderr.trim() || result.stdout.trim()}`, 'pr-failed');\n }\n\n const url = parsePullRequestUrl(result.stdout);\n if (!url) {\n throw new MaterializeError(\n `gh pr create succeeded but no PR URL was found in its output: ${result.stdout.trim()}`,\n 'pr-failed',\n );\n }\n\n return { url };\n}\n","import type { IntegrationStorageHandle, IntegrationSubscription } from '../../storage/domains/integrations/base.js';\n\nexport type GithubSignalSubscriptionSource = 'auto-gh-pr-create' | 'factory-pr-create' | 'explicit-tool';\nexport type GithubSignalSubscriptionStatus = 'open' | 'closed' | 'merged';\n\nexport interface GithubSignalSubscriptionData {\n installationExternalId: string;\n projectRepositoryId: string;\n repositoryExternalId: string;\n repositorySlug: string;\n changeRequestId: string;\n ownerId: string;\n source: GithubSignalSubscriptionSource;\n subscribedByUserId: string | null;\n}\n\nexport type GithubSignalSubscriptionRow = IntegrationSubscription<GithubSignalSubscriptionData>;\nexport type GithubSubscriptionStorage = IntegrationStorageHandle<\n Record<string, unknown>,\n Record<string, unknown>,\n GithubSignalSubscriptionData\n>;\n\nexport interface SubscribeToPullRequestInput {\n orgId: string;\n installationExternalId: string;\n projectRepositoryId: string;\n repositoryExternalId: string;\n repositorySlug: string;\n changeRequestId: string;\n sessionId: string;\n ownerId: string;\n resourceId: string;\n threadId: string;\n sessionScope?: string;\n source: GithubSignalSubscriptionSource;\n subscribedByUserId?: string;\n}\n\nexport interface ThreadSubscriptionTarget {\n orgId: string;\n resourceId: string;\n threadId: string;\n sessionScope?: string;\n}\n\nexport interface PullRequestSubscriptionTarget {\n orgId: string;\n installationExternalId: string;\n repositoryExternalId: string;\n changeRequestId: string;\n}\n\nexport type GithubWebhookPullRequestTarget = Omit<PullRequestSubscriptionTarget, 'orgId'>;\n\nexport function changeRequestTargetKey(input: GithubWebhookPullRequestTarget): string {\n return `change-request:${input.installationExternalId}:${input.repositoryExternalId}:${input.changeRequestId}`;\n}\n\nfunction sameSession(row: GithubSignalSubscriptionRow, input: SubscribeToPullRequestInput): boolean {\n return (\n row.orgId === input.orgId &&\n row.sessionId === input.sessionId &&\n row.resourceId === input.resourceId &&\n row.threadId === input.threadId &&\n (row.sessionScope ?? '') === (input.sessionScope ?? '')\n );\n}\n\nexport async function subscribeToPullRequest(\n input: SubscribeToPullRequestInput,\n storage: GithubSubscriptionStorage,\n): Promise<GithubSignalSubscriptionRow> {\n const targetKey = changeRequestTargetKey(input);\n const existing = (await storage.subscriptions.listByTarget(targetKey)).find(row => sameSession(row, input));\n if (existing) {\n if (existing.status !== 'open') await storage.subscriptions.updateStatus(existing.id, 'open');\n return { ...existing, status: 'open' };\n }\n\n return storage.subscriptions.create({\n orgId: input.orgId,\n targetKey,\n sessionId: input.sessionId,\n resourceId: input.resourceId,\n threadId: input.threadId,\n sessionScope: input.sessionScope ?? '',\n status: 'open',\n data: {\n installationExternalId: input.installationExternalId,\n projectRepositoryId: input.projectRepositoryId,\n repositoryExternalId: input.repositoryExternalId,\n repositorySlug: input.repositorySlug,\n changeRequestId: input.changeRequestId,\n ownerId: input.ownerId,\n source: input.source,\n subscribedByUserId: input.subscribedByUserId ?? null,\n },\n });\n}\n\nexport async function unsubscribeFromPullRequest(\n input: SubscribeToPullRequestInput,\n storage: GithubSubscriptionStorage,\n): Promise<void> {\n const rows = await storage.subscriptions.listByTarget(changeRequestTargetKey(input));\n await Promise.all(rows.filter(row => sameSession(row, input)).map(row => storage.subscriptions.delete(row.id)));\n}\n\nexport async function listPullRequestSubscriptionsForThread(\n input: ThreadSubscriptionTarget,\n storage: GithubSubscriptionStorage,\n): Promise<GithubSignalSubscriptionRow[]> {\n const rows = await storage.subscriptions.listByThread(input.resourceId, input.threadId);\n return rows.filter(\n row =>\n row.orgId === input.orgId &&\n row.resourceId === input.resourceId &&\n row.threadId === input.threadId &&\n (row.sessionScope ?? '') === (input.sessionScope ?? ''),\n );\n}\n\nexport async function listPullRequestSubscriptions(\n input: PullRequestSubscriptionTarget,\n storage: GithubSubscriptionStorage,\n): Promise<GithubSignalSubscriptionRow[]> {\n const rows = await storage.subscriptions.listByTarget(changeRequestTargetKey(input));\n return rows.filter(row => row.orgId === input.orgId && row.status === 'open');\n}\n\nexport async function listPullRequestSubscriptionsForWebhook(\n input: GithubWebhookPullRequestTarget,\n options: { includeTerminal?: boolean } | undefined,\n storage: GithubSubscriptionStorage,\n): Promise<GithubSignalSubscriptionRow[]> {\n const rows = await storage.subscriptions.listByTarget(changeRequestTargetKey(input));\n return options?.includeTerminal ? rows : rows.filter(row => row.status === 'open');\n}\n\nexport function retirePullRequestSubscription(\n id: string,\n status: GithubSignalSubscriptionStatus,\n storage: GithubSubscriptionStorage,\n): Promise<void> {\n return storage.subscriptions.updateStatus(id, status);\n}\n\nexport async function retirePullRequestSubscriptions(\n input: PullRequestSubscriptionTarget,\n storage: GithubSubscriptionStorage,\n): Promise<void> {\n const rows = await listPullRequestSubscriptions(input, storage);\n await Promise.all(rows.map(row => storage.subscriptions.updateStatus(row.id, 'closed')));\n}\n","import { createHmac, timingSafeEqual } from 'node:crypto';\nimport type { MountedMastraCode } from '@mastra/code-sdk';\nimport type { NotificationPriority } from '@mastra/core/notifications';\nimport type { Context } from 'hono';\nimport type { GithubIntegration } from './integration.js';\nimport type { GithubIssueTriageInput, GithubIssueTriageResult } from './issue-triage.js';\nimport { listPullRequestSubscriptionsForWebhook, retirePullRequestSubscription } from './subscriptions.js';\nimport type { GithubSignalSubscriptionRow, GithubWebhookPullRequestTarget } from './subscriptions.js';\n\nexport type GithubIssueTriageRunInput = GithubIssueTriageInput;\nexport type GithubIssueTriageRunResult = GithubIssueTriageResult;\n\nexport interface GithubWebhookHandlerOptions {\n /** Integration providing webhook-secret verification + collaborator permission checks. */\n github: GithubIntegration;\n runIssueTriage?: (input: GithubIssueTriageRunInput) => Promise<GithubIssueTriageRunResult>;\n ingestFactoryEvent?: (event: ParsedGithubWebhook) => Promise<unknown>;\n}\n\nconst SUPPORTED_GITHUB_WEBHOOK_EVENTS = new Set([\n 'issues',\n 'issue_comment',\n 'pull_request',\n 'pull_request_review',\n 'pull_request_review_comment',\n]);\n\nexport interface GithubWebhookMetadata {\n event: string;\n action?: string;\n deliveryId: string;\n repository?: string;\n repositoryId?: number;\n issueNumber?: number;\n pullRequestNumber?: number;\n sender?: string;\n senderType?: string;\n installationId?: number;\n}\n\nexport interface ParsedGithubWebhook {\n event: string;\n deliveryId: string;\n payload: Record<string, unknown>;\n}\n\nexport type GithubWebhookResult =\n | { status: 202; body: { ok: true; ignored?: true } }\n | { status: 400; body: { error: 'bad_request'; message: string } }\n | { status: 401; body: { error: 'unauthorized'; message: string } };\n\nexport interface GithubWebhookNotification {\n action: string;\n kind: string;\n priority: NotificationPriority;\n summary: string;\n terminal: boolean;\n metadata: GithubWebhookMetadata & { pullRequestNumber: number; repositoryId: number; installationId: number };\n payload: Record<string, unknown>;\n}\n\nexport interface GithubWebhookDispatchDependencies {\n controller: MountedMastraCode['controller'];\n /**\n * Integration used by the default sender-authorization check (collaborator\n * permission lookup). Author-gated notifications fail closed when neither\n * this nor an `isAuthorizedSender` override is supplied.\n */\n github?: GithubIntegration;\n listSubscriptions?: (\n target: GithubWebhookPullRequestTarget,\n options?: { includeTerminal?: boolean },\n ) => Promise<GithubSignalSubscriptionRow[]>;\n retireSubscription?: (id: string, status: 'open' | 'closed' | 'merged') => Promise<void>;\n isAuthorizedSender?: (notification: GithubWebhookNotification) => Promise<boolean>;\n onTargetError?: (subscription: GithubSignalSubscriptionRow, error: unknown) => void;\n}\n\nfunction normalizeHeader(value: string | undefined | null): string | null {\n if (!value) return null;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction verifySignature(rawBody: string, signature: string, secret: string): boolean {\n if (!signature.startsWith('sha256=')) return false;\n const signatureHex = signature.slice('sha256='.length);\n if (!/^[a-fA-F0-9]{64}$/.test(signatureHex)) return false;\n\n const expectedHex = createHmac('sha256', secret).update(rawBody).digest('hex');\n const received = Buffer.from(signatureHex, 'hex');\n const expected = Buffer.from(expectedHex, 'hex');\n return received.length === expected.length && timingSafeEqual(received, expected);\n}\n\nasync function parseGithubWebhook(\n c: Context,\n secret: string | undefined,\n): Promise<ParsedGithubWebhook | GithubWebhookResult> {\n if (!secret) {\n return { status: 401, body: { error: 'unauthorized', message: 'GitHub webhook secret is not configured' } };\n }\n\n const event = normalizeHeader(c.req.header('x-github-event'));\n const deliveryId = normalizeHeader(c.req.header('x-github-delivery'));\n const signature = normalizeHeader(c.req.header('x-hub-signature-256'));\n\n if (!event) return { status: 400, body: { error: 'bad_request', message: 'Missing x-github-event header' } };\n if (!deliveryId) return { status: 400, body: { error: 'bad_request', message: 'Missing x-github-delivery header' } };\n if (!signature)\n return { status: 401, body: { error: 'unauthorized', message: 'Missing x-hub-signature-256 header' } };\n\n const rawBody = await c.req.text();\n if (!verifySignature(rawBody, signature, secret)) {\n return { status: 401, body: { error: 'unauthorized', message: 'Invalid GitHub webhook signature' } };\n }\n\n let payload: unknown;\n try {\n payload = JSON.parse(rawBody);\n } catch {\n return { status: 400, body: { error: 'bad_request', message: 'Malformed JSON payload' } };\n }\n\n if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {\n return { status: 400, body: { error: 'bad_request', message: 'Payload must be a JSON object' } };\n }\n\n return { event, deliveryId, payload: payload as Record<string, unknown> };\n}\n\nfunction getObject(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === 'object' && !Array.isArray(value) ? (value as Record<string, unknown>) : undefined;\n}\n\nfunction getString(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction getNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction getBoolean(value: unknown): boolean | undefined {\n return typeof value === 'boolean' ? value : undefined;\n}\n\nfunction getLabels(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value\n .map(label => (typeof label === 'string' ? label : getString(getObject(label)?.name)))\n .filter((label): label is string => Boolean(label));\n}\n\nfunction getIssueTriageRunInput(parsed: ParsedGithubWebhook): GithubIssueTriageRunInput | null {\n if (parsed.event !== 'issues' || getString(parsed.payload.action) !== 'opened') return null;\n const repository = getString(getObject(parsed.payload.repository)?.full_name);\n const issue = getObject(parsed.payload.issue);\n const sender = getString(getObject(parsed.payload.sender)?.login);\n const installationId = getNumber(getObject(parsed.payload.installation)?.id);\n const issueNumber = getNumber(issue?.number);\n const issueTitle = getString(issue?.title);\n const issueUrl = getString(issue?.html_url);\n if (!repository || !installationId || !issueNumber || !issueTitle || !issueUrl) return null;\n return {\n repository,\n issueNumber,\n issueTitle,\n issueUrl,\n labels: getLabels(issue?.labels),\n sender,\n installationId,\n };\n}\n\nexport function normalizeGithubWebhookMetadata(parsed: ParsedGithubWebhook): GithubWebhookMetadata {\n const { event, deliveryId, payload } = parsed;\n const repository = getObject(payload.repository);\n const issue = getObject(payload.issue);\n const pullRequest = getObject(payload.pull_request);\n const sender = getObject(payload.sender);\n const installation = getObject(payload.installation);\n const issuePullRequest = getObject(issue?.pull_request);\n\n return {\n event,\n action: getString(payload.action),\n deliveryId,\n repository: getString(repository?.full_name),\n repositoryId: getNumber(repository?.id),\n issueNumber: getNumber(issue?.number),\n pullRequestNumber:\n getNumber(pullRequest?.number) ??\n (event === 'issue_comment' && issuePullRequest ? getNumber(issue?.number) : undefined),\n sender: getString(sender?.login),\n senderType: getString(sender?.type),\n installationId: getNumber(installation?.id),\n };\n}\n\nfunction notificationSummary(metadata: GithubWebhookMetadata, label: string): string {\n const actor = metadata.sender ? `${metadata.sender} ` : '';\n return `${actor}${label} on ${metadata.repository}#${metadata.pullRequestNumber}`;\n}\n\nfunction notificationTargetUrl(event: string, payload: Record<string, unknown>): string | undefined {\n if (event === 'issue_comment' || event === 'pull_request_review_comment') {\n return getString(getObject(payload.comment)?.html_url);\n }\n if (event === 'pull_request_review') {\n return getString(getObject(payload.review)?.html_url);\n }\n return getString(getObject(payload.pull_request)?.html_url);\n}\n\nexport function classifyGithubWebhook(parsed: ParsedGithubWebhook): GithubWebhookNotification | undefined {\n const metadata = normalizeGithubWebhookMetadata(parsed);\n const { event, payload } = parsed;\n const action = metadata.action;\n if (\n !action ||\n !metadata.repositoryId ||\n !metadata.installationId ||\n !metadata.pullRequestNumber ||\n !metadata.repository\n ) {\n return undefined;\n }\n\n let priority: NotificationPriority;\n let kind: string;\n let label: string;\n let terminal = false;\n\n if (event === 'pull_request_review' && action === 'submitted') {\n const state = getString(getObject(payload.review)?.state)?.toLowerCase().replaceAll('_', '-');\n priority = state === 'approved' || state === 'changes-requested' ? 'urgent' : 'high';\n kind =\n state === 'approved'\n ? 'review-approved'\n : state === 'changes-requested'\n ? 'review-changes-requested'\n : 'review-submitted';\n label =\n state === 'approved'\n ? 'approved the pull request'\n : state === 'changes-requested'\n ? 'requested changes'\n : 'submitted a review';\n } else if (event === 'pull_request' && action === 'closed') {\n const merged = getBoolean(getObject(payload.pull_request)?.merged) === true;\n priority = 'urgent';\n kind = merged ? 'pull-request-merged' : 'pull-request-closed';\n label = merged ? 'merged the pull request' : 'closed the pull request';\n terminal = true;\n } else if (event === 'issue_comment' && action === 'created') {\n priority = 'high';\n kind = 'issue-comment-created';\n label = 'commented';\n } else if (event === 'pull_request_review_comment' && action === 'created') {\n priority = 'high';\n kind = 'review-comment-created';\n label = 'left a review comment';\n } else if (event === 'pull_request' && action === 'reopened') {\n priority = 'high';\n kind = 'pull-request-reopened';\n label = 'reopened the pull request';\n } else if (event === 'pull_request_review' && action === 'dismissed') {\n priority = 'high';\n kind = 'review-dismissed';\n label = 'dismissed a review';\n } else if (\n event === 'pull_request' &&\n [\n 'synchronize',\n 'ready_for_review',\n 'converted_to_draft',\n 'assigned',\n 'unassigned',\n 'review_requested',\n 'review_request_removed',\n ].includes(action)\n ) {\n priority = 'medium';\n kind = `pull-request-${action.replaceAll('_', '-')}`;\n label = action.replaceAll('_', ' ');\n } else if (\n event === 'pull_request' &&\n ['edited', 'labeled', 'unlabeled', 'milestoned', 'demilestoned'].includes(action)\n ) {\n priority = 'low';\n kind = `pull-request-${action.replaceAll('_', '-')}`;\n label = action.replaceAll('_', ' ');\n } else {\n return undefined;\n }\n\n return {\n action,\n kind,\n priority,\n summary: notificationSummary(metadata, label),\n terminal,\n metadata: {\n ...metadata,\n pullRequestNumber: metadata.pullRequestNumber,\n repositoryId: metadata.repositoryId,\n installationId: metadata.installationId,\n },\n payload,\n };\n}\n\nasync function resolveSubscriptionSession(\n controller: MountedMastraCode['controller'],\n subscription: GithubSignalSubscriptionRow,\n) {\n const { sessionId, resourceId, threadId } = subscription;\n if (!sessionId || !resourceId || !threadId) {\n throw new Error(`GitHub subscription ${subscription.id} is missing its session binding.`);\n }\n const scope = subscription.sessionScope || undefined;\n let session = await controller.getSessionByResource(resourceId, scope);\n if (!session) {\n const tags = {\n factoryProjectId: resourceId,\n projectRepositoryId: subscription.data.projectRepositoryId,\n ...(scope ? { worktreePath: scope } : {}),\n };\n session = await controller.createSession({\n id: sessionId,\n ownerId: subscription.data.ownerId,\n resourceId,\n scope,\n tags,\n });\n }\n if (session.thread.getId() !== threadId) {\n await session.thread.switch({ threadId, emitEvent: false });\n }\n if (session.thread.getId() !== threadId) {\n throw new Error(`Session ${sessionId} did not bind thread ${threadId}.`);\n }\n return session;\n}\n\nconst AUTHORIZED_BOTS = new Set(['coderabbitai[bot]', 'devin-ai-integration[bot]']);\nconst AUTHORIZED_PERMISSIONS = new Set(['admin', 'maintain', 'write']);\nconst PERMISSION_CHECK_TIMEOUT_MS = 5_000;\nconst AUTHOR_GATED_KINDS = new Set([\n 'issue-comment-created',\n 'review-comment-created',\n 'review-submitted',\n 'review-approved',\n 'review-changes-requested',\n 'review-dismissed',\n]);\n\nasync function isAuthorizedGithubSender(\n notification: GithubWebhookNotification,\n github: GithubIntegration | undefined,\n): Promise<boolean> {\n if (!AUTHOR_GATED_KINDS.has(notification.kind)) return true;\n const sender = notification.metadata.sender;\n const repository = notification.metadata.repository;\n if (!sender || !repository) return false;\n const normalizedSender = sender.toLowerCase();\n if (notification.metadata.senderType?.toLowerCase() === 'bot' || normalizedSender.endsWith('[bot]')) {\n return AUTHORIZED_BOTS.has(normalizedSender);\n }\n if (!github) return false;\n const abortController = new AbortController();\n let timeout: ReturnType<typeof setTimeout> | undefined;\n try {\n const permission = await Promise.race([\n github.getRepositoryCollaboratorPermission(\n notification.metadata.installationId,\n repository,\n sender,\n abortController.signal,\n ),\n new Promise<undefined>(resolve => {\n timeout = setTimeout(() => {\n abortController.abort();\n resolve(undefined);\n }, PERMISSION_CHECK_TIMEOUT_MS);\n }),\n ]);\n return permission !== undefined && AUTHORIZED_PERMISSIONS.has(permission);\n } catch {\n return false;\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n}\n\nexport async function dispatchGithubWebhook(\n parsed: ParsedGithubWebhook,\n dependencies: GithubWebhookDispatchDependencies,\n): Promise<{ delivered: number; failed: number; ignored: boolean }> {\n const notification = classifyGithubWebhook(parsed);\n if (!notification) return { delivered: 0, failed: 0, ignored: true };\n const isAuthorizedSender =\n dependencies.isAuthorizedSender ??\n ((n: GithubWebhookNotification) => isAuthorizedGithubSender(n, dependencies.github));\n if (!(await isAuthorizedSender(notification))) {\n return { delivered: 0, failed: 0, ignored: true };\n }\n\n const target = {\n installationExternalId: notification.metadata.installationId.toString(),\n repositoryExternalId: notification.metadata.repositoryId.toString(),\n changeRequestId: notification.metadata.pullRequestNumber.toString(),\n };\n const listSubscriptions =\n dependencies.listSubscriptions ??\n ((subscriptionTarget: GithubWebhookPullRequestTarget, options?: { includeTerminal?: boolean }) => {\n if (!dependencies.github) throw new Error('GitHub integration is required to load webhook subscriptions.');\n return listPullRequestSubscriptionsForWebhook(\n subscriptionTarget,\n options,\n dependencies.github.integrationStorage,\n );\n });\n const retireSubscription =\n dependencies.retireSubscription ??\n ((id: string, status: 'open' | 'closed' | 'merged') => {\n if (!dependencies.github) throw new Error('GitHub integration is required to retire webhook subscriptions.');\n return retirePullRequestSubscription(id, status, dependencies.github.integrationStorage);\n });\n const subscriptions = await listSubscriptions(target, { includeTerminal: notification.action === 'reopened' });\n let delivered = 0;\n let failed = 0;\n\n for (const subscription of subscriptions) {\n try {\n const session = await resolveSubscriptionSession(dependencies.controller, subscription);\n const result = await session.sendNotificationSignal({\n source: 'github',\n kind: notification.kind,\n summary: notification.summary,\n priority: notification.priority,\n payload: notification.payload,\n sourceId: parsed.deliveryId,\n dedupeKey: `${parsed.deliveryId}:${subscription.sessionId}:${subscription.threadId}`,\n coalesceKey: `github:${subscription.data.repositoryExternalId}:pull-request:${subscription.data.changeRequestId}`,\n metadata: {\n event: notification.metadata.event,\n action: notification.action,\n repository: notification.metadata.repository,\n issueNumber: notification.metadata.issueNumber,\n pullRequestNumber: notification.metadata.pullRequestNumber,\n targetUrl: notificationTargetUrl(parsed.event, parsed.payload),\n deliveryId: parsed.deliveryId,\n },\n });\n await Promise.all([result.persisted, result.accepted].filter(Boolean));\n if (notification.terminal) {\n await retireSubscription(subscription.id, notification.kind === 'pull-request-merged' ? 'merged' : 'closed');\n } else if (notification.action === 'reopened') {\n await retireSubscription(subscription.id, 'open');\n }\n delivered += 1;\n } catch (error) {\n failed += 1;\n dependencies.onTargetError?.(subscription, error);\n }\n }\n\n return { delivered, failed, ignored: false };\n}\n\nexport async function handleGithubWebhook(\n c: Context,\n options: GithubWebhookHandlerOptions & Partial<Omit<GithubWebhookDispatchDependencies, 'github'>>,\n): Promise<GithubWebhookResult> {\n const parsed = await parseGithubWebhook(c, options.github.webhookSecret);\n if ('status' in parsed) return parsed;\n\n if (!SUPPORTED_GITHUB_WEBHOOK_EVENTS.has(parsed.event)) {\n return { status: 202, body: { ok: true, ignored: true } };\n }\n\n const metadata = normalizeGithubWebhookMetadata(parsed);\n console.info('[GitHub Webhook]', metadata);\n\n if (options.ingestFactoryEvent) {\n await options.ingestFactoryEvent(parsed);\n } else {\n const issueTriageRun = getIssueTriageRunInput(parsed);\n if (issueTriageRun && options.runIssueTriage) {\n void options.runIssueTriage(issueTriageRun).catch((error: unknown) => {\n console.error('[GitHub Webhook] Failed to run issue triage', {\n deliveryId: metadata.deliveryId,\n repository: metadata.repository,\n issueNumber: metadata.issueNumber,\n error: error instanceof Error ? error.message : String(error),\n });\n });\n }\n }\n\n if (!options.controller) {\n return { status: 202, body: { ok: true } };\n }\n\n const result = await dispatchGithubWebhook(parsed, options as GithubWebhookDispatchDependencies);\n if (result.failed > 0) {\n console.warn(`[GitHub Webhook] ${result.failed} subscribed target(s) failed for delivery ${parsed.deliveryId}.`);\n }\n return { status: 202, body: { ok: true, ...(result.ignored ? { ignored: true as const } : {}) } };\n}\n","import type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport type { RequestContext } from '@mastra/core/request-context';\nimport { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\nimport type {\n ProjectRepository,\n ProjectSourceControlConnection,\n SourceControlInstallation,\n SourceControlRepository,\n} from '../../storage/domains/source-control/base.js';\nimport type { GithubIntegration } from './integration.js';\nimport { getGithubPat } from './pat.js';\nimport { subscribeToPullRequest, unsubscribeFromPullRequest } from './subscriptions.js';\nimport { getRegisteredGithubPatKind, injectGithubToken } from './token-refresh.js';\n\ntype RepositorySessionState = { factoryProjectId?: string; projectRepositoryId?: string };\n\n/**\n * Minimal shape of the host-authenticated user placed on the request context\n * under the `user` key. Mirrors the host's auth user without importing it:\n * `workosId` (stable external id) wins over the row `id`, and `organizationId`\n * scopes org tenancy.\n */\ninterface SessionAuthUser {\n workosId?: string;\n id?: string;\n organizationId?: string;\n}\n\nfunction sessionUserId(user: SessionAuthUser | undefined): string | undefined {\n return user?.workosId ?? user?.id;\n}\n\nfunction sessionOrgId(user: SessionAuthUser | undefined): string | undefined {\n return user?.organizationId;\n}\n\nconst pullRequestInputSchema = z.object({\n pullRequest: z.union([z.number().int().positive(), z.string().min(1)]),\n});\n\ninterface SessionTarget {\n context: AgentControllerRequestContext<RepositorySessionState>;\n projectRepository: ProjectRepository;\n connection: ProjectSourceControlConnection;\n installation: SourceControlInstallation;\n repository: SourceControlRepository;\n orgId: string;\n userId: string;\n}\n\nfunction parsePullRequest(value: number | string, expectedRepo: string): number {\n if (typeof value === 'number') return value;\n if (/^\\d+$/.test(value)) return Number(value);\n const match = value.match(/^https:\\/\\/github\\.com\\/([^/]+\\/[^/]+)\\/pull\\/(\\d+)\\/?$/i);\n if (!match || match[1]!.toLowerCase() !== expectedRepo.toLowerCase()) {\n throw new Error(`Pull request must belong to ${expectedRepo}.`);\n }\n return Number(match[2]);\n}\n\n/**\n * Whether the current request comes from a session that GitHub subscriptions\n * can ever apply to: an authenticated org user on a GitHub-project session\n * with an active thread. Mirrors the gate in `resolveSessionTarget` without\n * throwing, for passive callers that should no-op instead of erroring.\n */\nfunction isGithubProjectSession(requestContext: RequestContext): boolean {\n const context = requestContext.get('controller') as AgentControllerRequestContext<RepositorySessionState> | undefined;\n const user = requestContext.get('user') as SessionAuthUser | undefined;\n return Boolean(\n context?.threadId && context.getState().projectRepositoryId && sessionOrgId(user) && sessionUserId(user),\n );\n}\n\nasync function resolveSessionTarget(requestContext: RequestContext, github: GithubIntegration): Promise<SessionTarget> {\n const context = requestContext.get('controller') as AgentControllerRequestContext<RepositorySessionState> | undefined;\n const user = requestContext.get('user') as SessionAuthUser | undefined;\n const orgId = sessionOrgId(user);\n const userId = sessionUserId(user);\n const projectRepositoryId = context?.getState().projectRepositoryId;\n if (!context || !context.threadId || !projectRepositoryId || !orgId || !userId) {\n throw new Error('GitHub subscriptions require an authenticated repository session with an active thread.');\n }\n\n const projectRepository = await github.sourceControlStorage.projectRepositories.get({\n orgId,\n id: projectRepositoryId,\n });\n if (!projectRepository) throw new Error('Project repository not found for this organization.');\n const connection = await github.sourceControlStorage.connections.get({ orgId, id: projectRepository.connectionId });\n if (!connection) throw new Error('Source-control connection not found for this organization.');\n const repository = await github.sourceControlStorage.repositories.get({ orgId, id: projectRepository.repositoryId });\n if (!repository) throw new Error('Repository not found for this organization.');\n const installation = await github.sourceControlStorage.installations.get({ orgId, id: connection.installationId });\n if (!installation) throw new Error('Source-control installation not found for this organization.');\n return { context, projectRepository, connection, installation, repository, orgId, userId };\n}\n\nasync function verifyPullRequest(target: SessionTarget, pullRequest: number, github: GithubIntegration) {\n const [owner, repo] = target.repository.slug.split('/');\n if (!owner || !repo) throw new Error('GitHub repository is invalid.');\n const octokit = github.getInstallationOctokit(Number(target.installation.externalId));\n const { data } = await octokit.pulls.get({ owner, repo, pull_number: pullRequest });\n if (String(data.base.repo.id) !== target.repository.externalId)\n throw new Error('Pull request repository does not match the active project repository.');\n}\n\nasync function subscriptionInput(target: SessionTarget, pullRequestNumber: number) {\n return {\n orgId: target.orgId,\n installationExternalId: target.installation.externalId,\n projectRepositoryId: target.projectRepository.id,\n repositoryExternalId: target.repository.externalId,\n repositorySlug: target.repository.slug,\n changeRequestId: String(pullRequestNumber),\n sessionId: target.context.session.id,\n ownerId: target.context.session.ownerId,\n resourceId: target.connection.factoryProjectId,\n threadId: target.context.threadId!,\n sessionScope: target.context.scope,\n source: 'explicit-tool' as const,\n subscribedByUserId: target.userId,\n };\n}\n\nexport async function subscribeCurrentSessionToPullRequest(\n requestContext: RequestContext,\n pullRequest: number | string,\n source: 'auto-gh-pr-create' | 'explicit-tool',\n github: GithubIntegration,\n) {\n // The auto path observes every successful `gh pr create` in every session,\n // including local and non-GitHub-project sessions where subscriptions can\n // never apply. Skip silently there; only the explicit tool should surface\n // \"this session cannot subscribe\" as an error.\n if (source === 'auto-gh-pr-create' && !isGithubProjectSession(requestContext)) return undefined;\n const target = await resolveSessionTarget(requestContext, github);\n const number = parsePullRequest(pullRequest, target.repository.slug);\n await verifyPullRequest(target, number, github);\n await subscribeToPullRequest({ ...(await subscriptionInput(target, number)), source }, github.integrationStorage);\n return number;\n}\n\nexport async function unsubscribeCurrentSessionFromPullRequest(\n requestContext: RequestContext,\n pullRequest: number | string,\n github: GithubIntegration,\n) {\n const target = await resolveSessionTarget(requestContext, github);\n const number = parsePullRequest(pullRequest, target.repository.slug);\n await unsubscribeFromPullRequest(await subscriptionInput(target, number), github.integrationStorage);\n return number;\n}\n\nexport async function refreshGithubToken(requestContext: RequestContext, github: GithubIntegration): Promise<void> {\n const target = await resolveSessionTarget(requestContext, github);\n // `GH_TOKEN` feeds the `gh` CLI, so a configured org PAT wins over a minted\n // installation token (which 403s on integration-restricted endpoints). The\n // workspace records which PAT kind the sandbox was provisioned with, so a\n // review-board sandbox keeps its reviewer token on refresh.\n const pat = await getGithubPat(\n () => github.integrationStorage,\n target.orgId,\n getRegisteredGithubPatKind(requestContext),\n );\n if (pat) {\n injectGithubToken(requestContext, pat);\n return;\n }\n const access = await github.versionControl.getRepositoryAccess({\n orgId: target.orgId,\n repositoryId: target.repository.id,\n });\n const token = access.authorization?.token;\n if (!token) throw new Error('Repository access did not include a bearer token for the Factory session.');\n injectGithubToken(requestContext, token);\n}\n\nexport function createGithubSubscriptionTools(requestContext: RequestContext, github: GithubIntegration) {\n const context = requestContext.get('controller') as AgentControllerRequestContext<RepositorySessionState> | undefined;\n const user = requestContext.get('user') as SessionAuthUser | undefined;\n if (!context?.getState().projectRepositoryId || !sessionOrgId(user) || !sessionUserId(user)) return {};\n\n return {\n github_refresh_token: createTool({\n id: 'github_refresh_token',\n description:\n 'Refresh GitHub CLI authentication in the active Factory sandbox. Use this after a gh command fails because authentication is expired, invalid, or missing. It installs a fresh GH_TOKEN for subsequent sandbox commands. After this tool succeeds, retry the failed gh command. Takes no arguments and never returns the token.',\n inputSchema: z.object({}),\n execute: async () => {\n await refreshGithubToken(requestContext, github);\n return { refreshed: true };\n },\n }),\n github_subscribe_pr: createTool({\n id: 'github_subscribe_pr',\n description:\n 'Subscribe this thread to GitHub pull request activity. You usually do not need this tool: successful gh pr create commands subscribe automatically. Use it for an existing PR or to recover when automatic subscription did not occur. Closed or merged PRs are unsubscribed automatically. Accepts a PR number or canonical URL for the active project.',\n inputSchema: pullRequestInputSchema,\n execute: async ({ pullRequest }) => {\n const number = await subscribeCurrentSessionToPullRequest(requestContext, pullRequest, 'explicit-tool', github);\n return { subscribed: true, pullRequestNumber: number };\n },\n }),\n github_unsubscribe_pr: createTool({\n id: 'github_unsubscribe_pr',\n description:\n 'Manually unsubscribe this thread from GitHub pull request activity. You usually do not need this tool because closed or merged PRs are unsubscribed automatically. Use it to stop notifications before then. Accepts a PR number or canonical URL for the active project.',\n inputSchema: pullRequestInputSchema,\n execute: async ({ pullRequest }) => {\n const number = await unsubscribeCurrentSessionFromPullRequest(requestContext, pullRequest, github);\n return { subscribed: false, pullRequestNumber: number };\n },\n }),\n };\n}\n\nexport function stripHeredocBodies(command: string): string {\n const lines = command.split('\\n');\n const executableLines: string[] = [];\n let delimiter: string | undefined;\n\n for (const line of lines) {\n if (delimiter) {\n if (line.trim() === delimiter) delimiter = undefined;\n continue;\n }\n executableLines.push(line);\n const heredoc = line.match(/<<-?\\s*(['\"]?)([A-Za-z_][A-Za-z0-9_]*)\\1/);\n delimiter = heredoc?.[2];\n }\n\n return executableLines.join('\\n');\n}\n\nexport function parseCreatedPullRequest(context: {\n toolName: string;\n input: unknown;\n output?: unknown;\n error?: unknown;\n}) {\n if (context.toolName !== 'execute_command' || context.error) return undefined;\n const command = (context.input as { command?: unknown } | undefined)?.command;\n if (\n typeof command !== 'string' ||\n !/(?:^|\\n|;|&&|\\|\\|)\\s*gh\\s+pr\\s+create(?:\\s|$)/.test(stripHeredocBodies(command))\n ) {\n return undefined;\n }\n const output = context.output as { stdout?: unknown; result?: unknown } | undefined;\n const stdout = typeof context.output === 'string' ? context.output : (output?.stdout ?? output?.result);\n if (typeof stdout !== 'string') return undefined;\n const urls = stdout.match(/https:\\/\\/github\\.com\\/[^\\s/]+\\/[^\\s/]+\\/pull\\/\\d+/g) ?? [];\n return urls.length === 1 ? urls[0] : undefined;\n}\n","import type { RequestContext } from '@mastra/core/request-context';\n\nimport type { GithubPatKind } from './pat.js';\n\nconst GITHUB_TOKEN_INJECTOR_CONTEXT_KEY = 'factoryGithubTokenInjector';\nconst GITHUB_PAT_KIND_CONTEXT_KEY = 'factoryGithubPatKind';\n\ntype GithubTokenInjector = (token: string) => void;\n\nexport function registerGithubTokenInjector(requestContext: RequestContext, injector: GithubTokenInjector): void {\n requestContext.set(GITHUB_TOKEN_INJECTOR_CONTEXT_KEY, injector);\n}\n\n/** Record which PAT kind the active sandbox was provisioned with, so token\n * refresh re-injects the same credential (review-board sandboxes keep the\n * reviewer token instead of being clobbered with the worker token). */\nexport function registerGithubPatKind(requestContext: RequestContext, kind: GithubPatKind): void {\n requestContext.set(GITHUB_PAT_KIND_CONTEXT_KEY, kind);\n}\n\nexport function getRegisteredGithubPatKind(requestContext: RequestContext): GithubPatKind {\n const kind = requestContext.get(GITHUB_PAT_KIND_CONTEXT_KEY);\n return kind === 'reviewer' ? 'reviewer' : 'default';\n}\n\nexport function injectGithubToken(requestContext: RequestContext, token: string): void {\n const injector = requestContext.get(GITHUB_TOKEN_INJECTOR_CONTEXT_KEY) as GithubTokenInjector | undefined;\n if (!injector) {\n throw new Error('GitHub token refresh requires an active Factory sandbox workspace.');\n }\n injector(token);\n}\n","export interface PlatformApiClientConfig {\n baseUrl: string;\n accessToken: string;\n fetchImpl?: typeof fetch;\n}\n\nexport function platformApiClientConfigFromEnv(): PlatformApiClientConfig {\n const sharedApiUrl = process.env.MASTRA_SHARED_API_URL?.trim() || 'https://platform.mastra.ai/v1';\n const accessToken = process.env.MASTRA_PLATFORM_SECRET_KEY?.trim();\n if (!accessToken) {\n throw new Error('Platform integration: missing required environment variable MASTRA_PLATFORM_SECRET_KEY.');\n }\n return { baseUrl: normalizeSharedApiUrl(sharedApiUrl), accessToken };\n}\n\nfunction normalizeSharedApiUrl(sharedApiUrl: string): string {\n return sharedApiUrl.replace(/\\/+$/, '').replace(/\\/v1$/, '');\n}\n\nexport class PlatformApiError extends Error {\n readonly status: number;\n readonly retryAfterSeconds: number | null;\n\n constructor(message: string, status: number, retryAfterSeconds: number | null = null) {\n super(message);\n this.name = 'PlatformApiError';\n this.status = status;\n this.retryAfterSeconds = retryAfterSeconds;\n }\n}\n\nexport class PlatformApiClient {\n readonly #baseUrl: string;\n readonly #accessToken: string;\n readonly #fetch: typeof fetch;\n\n constructor(config: PlatformApiClientConfig) {\n const missing = ['baseUrl', 'accessToken'].filter(field => !config[field as keyof PlatformApiClientConfig]);\n if (missing.length > 0) {\n throw new Error(`Platform integration: missing required config field(s): ${missing.join(', ')}.`);\n }\n this.#baseUrl = config.baseUrl.replace(/\\/+$/, '');\n this.#accessToken = config.accessToken;\n this.#fetch = config.fetchImpl ?? globalThis.fetch;\n }\n\n async request<T>(\n method: string,\n path: string,\n body?: unknown,\n options?: { signal?: AbortSignal; actingUserId?: string },\n ): Promise<T> {\n const response = await this.#send(method, path, body, options);\n if (!response.ok) {\n const message = redact(await extractError(response), this.#accessToken);\n const retryAfterSeconds = parseRetryAfter(response.headers.get('retry-after'));\n logPlatformError('Platform API request failed', {\n method,\n path,\n status: response.status,\n retryAfterSeconds,\n message,\n });\n throw new PlatformApiError(message, response.status, retryAfterSeconds);\n }\n if (response.status === 204) return undefined as T;\n return (await response.json()) as T;\n }\n\n async requestRedirect(method: string, path: string, options?: { signal?: AbortSignal }): Promise<string> {\n const response = await this.#send(method, path, undefined, options, 'manual');\n if (response.status >= 300 && response.status < 400) {\n const location = response.headers.get('location');\n if (location) return location;\n }\n if (!response.ok) {\n const message = redact(await extractError(response), this.#accessToken);\n const retryAfterSeconds = parseRetryAfter(response.headers.get('retry-after'));\n logPlatformError('Platform API redirect request failed', {\n method,\n path,\n status: response.status,\n retryAfterSeconds,\n message,\n });\n throw new PlatformApiError(message, response.status, retryAfterSeconds);\n }\n logPlatformError('Platform API request did not return a redirect', { method, path, status: response.status });\n throw new PlatformApiError('Platform API request did not return a redirect.', response.status);\n }\n\n async #send(\n method: string,\n path: string,\n body?: unknown,\n options?: { signal?: AbortSignal; actingUserId?: string },\n redirect?: RequestInit['redirect'],\n ): Promise<Response> {\n const headers: Record<string, string> = {\n accept: 'application/json',\n authorization: `Bearer ${this.#accessToken}`,\n };\n // Acting end-user for platform GitHub writes: the platform resolves this\n // user's GitHub OAuth connection (org-scoped) so issues/PRs are authored\n // by the human instead of the App bot. Ignored by older platforms.\n if (options?.actingUserId) {\n headers['x-acting-user-id'] = options.actingUserId;\n }\n const timeoutSignal = AbortSignal.timeout(15_000);\n const init: RequestInit = {\n method,\n headers,\n redirect,\n signal: options?.signal ? AbortSignal.any([options.signal, timeoutSignal]) : timeoutSignal,\n };\n if (body !== undefined) {\n headers['content-type'] = 'application/json';\n init.body = JSON.stringify(body);\n }\n\n try {\n return await this.#fetch(`${this.#baseUrl}${path}`, init);\n } catch (error) {\n if (error instanceof Error && error.message.includes(this.#accessToken)) {\n const redacted = new Error(redact(error.message, this.#accessToken));\n redacted.name = error.name;\n logPlatformError('Platform API transport error', {\n method,\n path,\n name: redacted.name,\n message: redacted.message,\n });\n throw redacted;\n }\n logPlatformError('Platform API transport error', {\n method,\n path,\n name: error instanceof Error ? error.name : undefined,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n}\n\nasync function extractError(response: Response): Promise<string> {\n try {\n const data = (await response.clone().json()) as Record<string, unknown>;\n for (const field of ['detail', 'error', 'title']) {\n if (typeof data[field] === 'string' && data[field]) return data[field];\n }\n } catch {\n // Fall through to the status-based message.\n }\n return `Platform API request failed (${response.status})`;\n}\n\nfunction redact(message: string, accessToken: string): string {\n return message.split(accessToken).join('[REDACTED]');\n}\n\nexport function logPlatformInfo(message: string, fields?: Record<string, unknown>): void {\n writePlatformLog('info', message, fields);\n}\n\nexport function logPlatformWarn(message: string, fields?: Record<string, unknown>): void {\n writePlatformLog('warn', message, fields);\n}\n\nexport function logPlatformError(message: string, fields?: Record<string, unknown>): void {\n writePlatformLog('error', message, fields);\n}\n\nfunction writePlatformLog(level: 'info' | 'warn' | 'error', message: string, fields?: Record<string, unknown>): void {\n const metadata = fields ? ` ${JSON.stringify(stripUndefined(fields))}` : '';\n process.stderr.write(`[Mastra Factory] ${level.toUpperCase()} ${message}${metadata}\\n`);\n}\n\nfunction stripUndefined(fields: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(Object.entries(fields).filter(([, value]) => value !== undefined));\n}\n\nfunction parseRetryAfter(value: string | null): number | null {\n if (!value) return null;\n const seconds = Number.parseInt(value, 10);\n return Number.isSafeInteger(seconds) && seconds >= 0 ? seconds : null;\n}\n","import { randomUUID } from 'node:crypto';\n\nimport type { MountedMastraCode } from '@mastra/code-sdk';\nimport { isLeaseProvider, NoopLeaseProvider } from '@mastra/core/events';\nimport type { LeaseProvider, PubSub } from '@mastra/core/events';\nimport { MastraWorker } from '@mastra/core/worker';\nimport type { WorkerDeps } from '@mastra/core/worker';\n\nimport type { IntegrationStorageHandle } from '../../../storage/domains/integrations/base.js';\nimport type { GithubRepositoryPermission } from '../../github/integration.js';\nimport { listPullRequestSubscriptionsForWebhook, retirePullRequestSubscription } from '../../github/subscriptions.js';\nimport type { GithubSubscriptionStorage } from '../../github/subscriptions.js';\nimport { dispatchGithubWebhook } from '../../github/webhook.js';\nimport type { GithubWebhookNotification, ParsedGithubWebhook } from '../../github/webhook.js';\nimport type { PlatformApiClient } from '../api-client.js';\nimport { PlatformApiError } from '../api-client.js';\n\nconst API_PREFIX = '/v1/server/github-app';\nconst DEFAULT_POLL_INTERVAL_MS = 5_000;\nconst EVENT_PAGE_SIZE = 500;\nconst MIN_LEASE_TTL_MS = 30_000;\nconst CURSOR_ORG_ID = '__platform_github_event_worker__';\nconst CURSOR_USER_ID = 'worker';\nconst SUPPORTED_EVENTS = new Set([\n 'issues',\n 'issue_comment',\n 'pull_request',\n 'pull_request_review',\n 'pull_request_review_comment',\n]);\nconst AUTHOR_GATED_KINDS = new Set([\n 'issue-comment',\n 'pull-request-comment',\n 'pull-request-review',\n 'pull-request-review-comment',\n]);\nconst AUTHORIZED_BOTS = new Set(['coderabbitai[bot]', 'devin-ai-integration[bot]']);\nconst AUTHORIZED_PERMISSIONS = new Set<GithubRepositoryPermission>(['admin', 'maintain', 'write']);\nconst PERMISSION_CHECK_TIMEOUT_MS = 5_000;\n\ntype EventCursor = { afterEventId: string } | { afterTimestamp: number };\ntype PlatformGithubEventWorkerSettings = {\n version: 1;\n repositories: Record<string, EventCursor>;\n};\n\nexport type PlatformGithubEventStorage = IntegrationStorageHandle<\n Record<string, unknown>,\n PlatformGithubEventWorkerSettings,\n Record<string, unknown>\n>;\n\ntype EventLogEntry = {\n id: string;\n deliveryId: string;\n event: string;\n payload: unknown;\n};\n\ntype Repository = { id: number };\n\nexport interface PlatformGithubEventDispatchIntegration {\n readonly integrationStorage: GithubSubscriptionStorage;\n getRepositoryCollaboratorPermission(\n installationId: number,\n repoFullName: string,\n username: string,\n signal?: AbortSignal,\n ): Promise<GithubRepositoryPermission | undefined>;\n}\n\nexport interface PlatformGithubEventWorkerConfig {\n client: PlatformApiClient;\n controller: MountedMastraCode['controller'];\n github: PlatformGithubEventDispatchIntegration;\n storage: PlatformGithubEventStorage;\n ingestFactoryEvent?: (event: ParsedGithubWebhook) => Promise<unknown>;\n intervalMs?: number;\n now?: () => number;\n dispatch?: typeof dispatchGithubWebhook;\n}\n\nexport class PlatformGithubEventWorker extends MastraWorker {\n readonly name = 'platform-github-events';\n\n readonly #client: PlatformApiClient;\n readonly #controller: MountedMastraCode['controller'];\n readonly #github: PlatformGithubEventDispatchIntegration;\n readonly #storage: PlatformGithubEventStorage;\n readonly #ingestFactoryEvent: ((event: ParsedGithubWebhook) => Promise<unknown>) | undefined;\n readonly #intervalMs: number;\n readonly #now: () => number;\n readonly #dispatch: typeof dispatchGithubWebhook;\n readonly #leaseOwner = randomUUID();\n\n #running = false;\n #timer: ReturnType<typeof setTimeout> | undefined;\n #leaseRenewalTimer: ReturnType<typeof setInterval> | undefined;\n #inFlight: Promise<void> | undefined;\n #leaseProvider: LeaseProvider = NoopLeaseProvider;\n #leaseTtlMs: number;\n #hasLease = false;\n #startedAt = 0;\n #settings: PlatformGithubEventWorkerSettings = { version: 1, repositories: {} };\n\n constructor(config: PlatformGithubEventWorkerConfig) {\n super();\n this.#client = config.client;\n this.#controller = config.controller;\n this.#github = config.github;\n this.#storage = config.storage;\n this.#ingestFactoryEvent = config.ingestFactoryEvent;\n this.#intervalMs = config.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n if (!Number.isFinite(this.#intervalMs) || this.#intervalMs <= 0) {\n throw new Error('Platform GitHub event polling interval must be a positive number.');\n }\n this.#leaseTtlMs = Math.max(MIN_LEASE_TTL_MS, this.#intervalMs * 3);\n this.#now = config.now ?? Date.now;\n this.#dispatch = config.dispatch ?? dispatchGithubWebhook;\n }\n\n async init(deps: WorkerDeps): Promise<void> {\n await super.init(deps);\n this.#leaseProvider = getLeaseProvider(deps.pubsub);\n }\n\n async start(): Promise<void> {\n if (this.#running) return;\n if (!this.deps) throw new Error('PlatformGithubEventWorker: call init() before start()');\n\n this.#startedAt = this.#now() - 1;\n this.#settings = normalizeSettings(await this.#storage.settings.get(CURSOR_ORG_ID, CURSOR_USER_ID));\n this.#running = true;\n this.deps.logger.info('Platform GitHub event polling started', {\n intervalMs: this.#intervalMs,\n leaseTtlMs: this.#leaseTtlMs,\n });\n this.#schedule(0);\n }\n\n async stop(): Promise<void> {\n if (!this.#running) return;\n this.#running = false;\n if (this.#timer) clearTimeout(this.#timer);\n this.#timer = undefined;\n this.#stopLeaseRenewal();\n await this.#inFlight;\n if (this.#hasLease) {\n await this.#leaseProvider.releaseLease(this.#leaseKey(), this.#leaseOwner).catch(() => undefined);\n this.#hasLease = false;\n }\n }\n\n get isRunning(): boolean {\n return this.#running;\n }\n\n #schedule(delayMs: number): void {\n if (!this.#running) return;\n this.#timer = setTimeout(() => {\n this.#timer = undefined;\n const run = this.#tick();\n this.#inFlight = run;\n void run.finally(() => {\n if (this.#inFlight === run) this.#inFlight = undefined;\n });\n }, delayMs);\n this.#timer.unref?.();\n }\n\n async #tick(): Promise<void> {\n let nextDelay = this.#intervalMs;\n try {\n if (!(await this.#ensureLease())) return;\n nextDelay = await this.#poll();\n } catch (error) {\n nextDelay = retryDelay(error, this.#intervalMs);\n this.deps?.logger.error('Platform GitHub event polling cycle failed', {\n error: error instanceof Error ? error.message : String(error),\n retryInMs: nextDelay,\n });\n } finally {\n this.#schedule(nextDelay);\n }\n }\n\n async #ensureLease(): Promise<boolean> {\n if (this.#hasLease) return true;\n const result = await this.#leaseProvider.acquireLease(this.#leaseKey(), this.#leaseOwner, this.#leaseTtlMs);\n this.#hasLease = result.acquired;\n if (this.#hasLease) this.#startLeaseRenewal();\n return this.#hasLease;\n }\n\n #startLeaseRenewal(): void {\n if (this.#leaseRenewalTimer) return;\n this.#leaseRenewalTimer = setInterval(\n () => {\n void this.#leaseProvider\n .renewLease(this.#leaseKey(), this.#leaseOwner, this.#leaseTtlMs)\n .then(renewed => {\n if (!renewed) {\n this.#hasLease = false;\n this.#stopLeaseRenewal();\n }\n })\n .catch(error => {\n this.#hasLease = false;\n this.#stopLeaseRenewal();\n this.deps?.logger.warn('Platform GitHub event polling lease renewal failed', {\n error: error instanceof Error ? error.message : String(error),\n });\n });\n },\n Math.floor(this.#leaseTtlMs / 3),\n );\n this.#leaseRenewalTimer.unref?.();\n }\n\n #stopLeaseRenewal(): void {\n if (this.#leaseRenewalTimer) clearInterval(this.#leaseRenewalTimer);\n this.#leaseRenewalTimer = undefined;\n }\n\n async #poll(): Promise<number> {\n const repositories = await this.#discoverRepositories();\n let retryInMs = this.#intervalMs;\n\n for (const repository of repositories) {\n if (!this.#running || !this.#hasLease) break;\n try {\n await this.#pollRepository(repository.id);\n } catch (error) {\n const delay = retryDelay(error, this.#intervalMs);\n retryInMs = Math.max(retryInMs, delay);\n this.deps?.logger.error('Platform GitHub repository event polling failed', {\n repositoryId: repository.id,\n error: error instanceof Error ? error.message : String(error),\n retryInMs: delay,\n });\n if (error instanceof PlatformApiError && error.status === 429) break;\n }\n }\n\n return retryInMs;\n }\n\n async #discoverRepositories(): Promise<Repository[]> {\n const result = await this.#client.request<{\n installations: Array<{\n installationId: number;\n usable: boolean;\n suspendedAt: string | null;\n }>;\n }>('GET', `${API_PREFIX}/installations`);\n const repositories = new Map<number, Repository>();\n\n for (const installation of result.installations) {\n if (!installation.usable || installation.suspendedAt) continue;\n const page = await this.#client.request<{ repositories: Repository[] }>(\n 'GET',\n `${API_PREFIX}/installations/${installation.installationId}/repositories`,\n );\n for (const repository of page.repositories) repositories.set(repository.id, repository);\n }\n\n return [...repositories.values()];\n }\n\n async #pollRepository(repositoryId: number): Promise<void> {\n const key = String(repositoryId);\n if (!this.#settings.repositories[key]) {\n this.#settings.repositories[key] = { afterTimestamp: this.#startedAt };\n await this.#saveSettings();\n }\n\n while (this.#running && this.#hasLease) {\n const cursor: EventCursor = this.#settings.repositories[key]!;\n const query = new URLSearchParams({ limit: String(EVENT_PAGE_SIZE) });\n if ('afterEventId' in cursor) query.set('afterEventId', cursor.afterEventId);\n else query.set('afterTimestamp', String(cursor.afterTimestamp));\n\n const page = await this.#client.request<{ events: EventLogEntry[]; nextCursor: string | null }>(\n 'GET',\n `${API_PREFIX}/repositories/${repositoryId}/events?${query}`,\n );\n if (page.events.length === 0 || !page.nextCursor) return;\n\n for (const event of page.events) {\n if (!this.#running || !this.#hasLease) return;\n const parsed = parseEvent(event);\n if (!parsed) {\n this.deps?.logger.warn('Platform GitHub event log returned a malformed event', {\n repositoryId,\n eventId: event.id,\n });\n continue;\n }\n if (isFactoryClosureEvent(parsed)) {\n await this.#ingestFactoryEvent?.(parsed);\n }\n const result = await this.#dispatch(parsed, {\n controller: this.#controller,\n listSubscriptions: (target, options) =>\n listPullRequestSubscriptionsForWebhook(target, options, this.#github.integrationStorage),\n retireSubscription: (id, status) =>\n retirePullRequestSubscription(id, status, this.#github.integrationStorage),\n isAuthorizedSender: notification => this.#isAuthorizedSender(notification),\n onTargetError: (subscription, error) => {\n this.deps?.logger.error('Platform GitHub event delivery failed for a subscription', {\n subscriptionId: subscription.id,\n resourceId: subscription.resourceId,\n threadId: subscription.threadId,\n error: error instanceof Error ? error.message : String(error),\n });\n },\n });\n if (result.failed > 0) {\n throw new Error(\n `Platform GitHub event ${event.deliveryId} failed for ${result.failed} subscribed target(s).`,\n );\n }\n }\n\n if (page.nextCursor === ('afterEventId' in cursor ? cursor.afterEventId : undefined)) return;\n this.#settings.repositories[key] = { afterEventId: page.nextCursor };\n await this.#saveSettings();\n }\n }\n\n async #isAuthorizedSender(notification: GithubWebhookNotification): Promise<boolean> {\n if (!AUTHOR_GATED_KINDS.has(notification.kind)) return true;\n const sender = notification.metadata.sender;\n const repository = notification.metadata.repository;\n if (!sender || !repository) return false;\n if (AUTHORIZED_BOTS.has(sender)) return true;\n\n const abortController = new AbortController();\n const timeout = setTimeout(() => abortController.abort(), PERMISSION_CHECK_TIMEOUT_MS);\n try {\n const permission = await this.#github.getRepositoryCollaboratorPermission(\n notification.metadata.installationId,\n repository,\n sender,\n abortController.signal,\n );\n return permission !== undefined && AUTHORIZED_PERMISSIONS.has(permission);\n } catch {\n return false;\n } finally {\n clearTimeout(timeout);\n }\n }\n\n async #saveSettings(): Promise<void> {\n await this.#storage.settings.save(CURSOR_ORG_ID, CURSOR_USER_ID, this.#settings);\n }\n\n #leaseKey(): string {\n return `${this.name}:${this.#storage.integrationId}`;\n }\n}\n\nfunction getLeaseProvider(pubsub: PubSub): LeaseProvider {\n const getProvider = (pubsub as PubSub & { getLeaseProvider?: () => LeaseProvider | undefined }).getLeaseProvider;\n if (typeof getProvider === 'function') return getProvider.call(pubsub) ?? NoopLeaseProvider;\n return isLeaseProvider(pubsub) ? pubsub : NoopLeaseProvider;\n}\n\nfunction normalizeSettings(value: PlatformGithubEventWorkerSettings | null): PlatformGithubEventWorkerSettings {\n if (!value || value.version !== 1 || !value.repositories || typeof value.repositories !== 'object') {\n return { version: 1, repositories: {} };\n }\n return { version: 1, repositories: { ...value.repositories } };\n}\n\nfunction isFactoryClosureEvent(event: ParsedGithubWebhook): boolean {\n return (event.event === 'issues' || event.event === 'pull_request') && event.payload.action === 'closed';\n}\n\nfunction parseEvent(event: EventLogEntry): ParsedGithubWebhook | null {\n if (\n !event.id ||\n !event.deliveryId ||\n !SUPPORTED_EVENTS.has(event.event) ||\n !event.payload ||\n typeof event.payload !== 'object' ||\n Array.isArray(event.payload)\n ) {\n return null;\n }\n return {\n event: event.event,\n deliveryId: event.deliveryId,\n payload: event.payload as Record<string, unknown>,\n };\n}\n\nfunction retryDelay(error: unknown, fallbackMs: number): number {\n if (error instanceof PlatformApiError && error.status === 429 && error.retryAfterSeconds !== null) {\n return Math.max(fallbackMs, error.retryAfterSeconds * 1_000);\n }\n return fallbackMs;\n}\n"],"mappings":"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","names":["registerApiRoute","createHash","createHash","isValidGitRef","path","randomUUID","AUTHOR_GATED_KINDS","AUTHORIZED_BOTS","AUTHORIZED_PERMISSIONS","PERMISSION_CHECK_TIMEOUT_MS","randomUUID","API_PREFIX","loose","registerApiRoute","path","parsePullRequest"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/integrations/platform/github/integration.ts","../../../../src/integrations/github/routes.ts","../../../../src/sandbox/fleet.ts","../../../../src/integrations/github/config.ts","../../../../src/integrations/github/pat.ts","../../../../src/integrations/github/project-lock.ts","../../../../src/integrations/github/sandbox.ts","../../../../src/integrations/github/subscriptions.ts","../../../../src/integrations/github/webhook.ts","../../../../src/integrations/github/session-subscriptions.ts","../../../../src/integrations/github/token-refresh.ts","../../../../src/integrations/platform/api-client.ts","../../../../src/integrations/platform/github/event-worker.ts"],"sourcesContent":["import type { RequestContext } from '@mastra/core/request-context';\nimport type { ApiRoute } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\nimport type { Context } from 'hono';\n\nimport type { IntegrationConnection } from '../../../capabilities/connection.js';\nimport type {\n CreateIntakeCommentInput,\n Intake,\n IntakeIssue,\n IntakeIssueDetail,\n UpdateIntakeIssueInput,\n} from '../../../capabilities/intake.js';\nimport type {\n CreatePullRequestCommentInput,\n CreatePullRequestInput,\n CreateReviewCommentInput,\n CreateReviewInput,\n DeletePullRequestCommentInput,\n DismissReviewInput,\n ListPullRequestCommentsInput,\n ListPullRequestsInput,\n ListReviewCommentsInput,\n ListReviewsInput,\n MergePullRequestInput,\n PullRequest,\n PullRequestComment,\n PullRequestRef,\n Review,\n ReviewComment,\n ReviewRef,\n SubmitReviewInput,\n UpdatePullRequestCommentInput,\n UpdatePullRequestInput,\n UpdateReviewInput,\n UpdateReviewersInput,\n VersionControl,\n} from '../../../capabilities/version-control.js';\nimport type { IntegrationStorageHandle } from '../../../storage/domains/integrations/base.js';\nimport type {\n SourceControlInstallation,\n SourceControlStorageHandle,\n} from '../../../storage/domains/source-control/base.js';\nimport type { FactoryIntegration, IntegrationContext, IntegrationTools } from '../../base.js';\nimport type { GithubIntegration, GithubRepositoryPermission, RepoSummary } from '../../github/integration.js';\nimport { buildGithubRoutes } from '../../github/routes.js';\nimport {\n createGithubSubscriptionTools,\n parseCreatedPullRequest,\n subscribeCurrentSessionToPullRequest,\n} from '../../github/session-subscriptions.js';\nimport type { GithubSubscriptionStorage } from '../../github/subscriptions.js';\nimport {\n logPlatformInfo,\n logPlatformWarn,\n PlatformApiClient,\n PlatformApiError,\n platformApiClientConfigFromEnv,\n} from '../api-client.js';\nimport { PlatformGithubEventWorker } from './event-worker.js';\nimport type { PlatformGithubEventStorage } from './event-worker.js';\n\ntype GithubActor = { login: string; avatarUrl: string | null; htmlUrl: string | null } | null;\n\ntype PlatformGithubInstallation = {\n installationId: number;\n accountLogin: string;\n accountType: string;\n suspendedAt: string | null;\n usable: boolean;\n};\n\ntype PlatformGithubUserConnection = {\n connected: boolean;\n githubUsername: string | null;\n reason?: 'token-invalid' | 'no-accessible-installation' | 'missing-permissions' | 'verification-unavailable' | null;\n};\n\ntype GithubIssue = {\n number: number;\n state: 'open' | 'closed';\n title: string;\n body: string | null;\n htmlUrl: string;\n labels: string[];\n assignees: string[];\n commentCount: number;\n user: GithubActor;\n createdAt: string;\n updatedAt: string;\n};\n\ntype GithubComment = {\n id: number;\n body: string;\n htmlUrl: string;\n user: GithubActor;\n createdAt: string;\n updatedAt: string;\n};\n\ntype GithubPullRequest = {\n number: number;\n title: string;\n body: string | null;\n state: 'open' | 'closed';\n htmlUrl: string;\n merged: boolean;\n mergeable: boolean | null;\n draft: boolean;\n head: { ref: string; sha: string };\n base: { ref: string; repo: { id: number; fullName: string } };\n user: GithubActor;\n createdAt: string;\n updatedAt: string;\n};\n\ntype GithubReview = {\n id: number;\n htmlUrl: string | null;\n body: string | null;\n state: 'PENDING' | 'COMMENTED' | 'APPROVED' | 'CHANGES_REQUESTED' | 'DISMISSED';\n commitId: string | null;\n submittedAt: string | null;\n user: GithubActor;\n};\n\ntype GithubReviewComment = GithubComment & {\n path: string;\n line: number | null;\n side: 'LEFT' | 'RIGHT' | null;\n commitId: string;\n replyToId: number | null;\n};\n\nconst PAGE_SIZE = 30;\nconst API_PREFIX = '/v1/server';\nconst REPOSITORY_TOKEN_PERMISSIONS = {\n contents: 'write',\n issues: 'write',\n pull_requests: 'write',\n} as const;\n\nfunction loose(c: unknown): Context {\n return c as Context;\n}\n\nfunction routeBaseUrl(ctx: IntegrationContext, requestUrl: string): string {\n return (ctx.baseUrl || new URL(requestUrl).origin).replace(/\\/+$/, '');\n}\n\nexport class PlatformGithubIntegration implements FactoryIntegration {\n readonly id = 'github';\n readonly #client: PlatformApiClient;\n readonly #endpointHost: string;\n readonly #pollingEnabled: boolean;\n readonly #pollingIntervalMs: number | undefined;\n #storage: SourceControlStorageHandle | undefined;\n #integrationStorage: GithubSubscriptionStorage | undefined;\n\n readonly intake: Intake = {\n resolveIntakeDispatch: input => this.#resolveIntakeDispatch(input),\n listSources: async ({ orgId, userId }) => {\n const installations = await this.#client.request<{\n installations: Array<{\n installationId: number;\n accountLogin: string;\n accountType: string;\n suspendedAt: string | null;\n usable: boolean;\n }>;\n }>('GET', `${API_PREFIX}/github-app/installations`);\n const usable = installations.installations.filter(\n installation => installation.usable && !installation.suspendedAt,\n );\n const repositories = await Promise.all(\n usable.map(async installation => {\n const storedInstallation = await this.versionControl.registerInstallation({\n orgId,\n userId,\n installation: {\n externalId: String(installation.installationId),\n accountName: installation.accountLogin,\n accountType: installation.accountType,\n },\n });\n const result = await this.#client.request<{\n repositories: Array<{\n id: number;\n fullName: string;\n private: boolean;\n defaultBranch: string;\n htmlUrl: string;\n }>;\n }>('GET', `${API_PREFIX}/github-app/installations/${installation.installationId}/repositories`);\n await this.versionControl.registerRepositories({\n orgId,\n installationId: storedInstallation.id,\n repositories: result.repositories.map(repository => ({\n externalId: String(repository.id),\n slug: repository.fullName,\n defaultBranch: repository.defaultBranch,\n metadata: { private: repository.private, url: repository.htmlUrl },\n })),\n });\n return result.repositories.map(repository => ({ repository, installation }));\n }),\n );\n return repositories.flat().map(({ repository, installation }) => ({\n id: repository.fullName,\n name: repository.fullName,\n type: 'repository',\n metadata: {\n installationId: installation.installationId,\n accountLogin: installation.accountLogin,\n accountType: installation.accountType,\n repositoryId: repository.id,\n defaultBranch: repository.defaultBranch,\n private: repository.private,\n url: repository.htmlUrl,\n },\n }));\n },\n listItems: async ({ sourceIds, cursor }) => {\n const page = parsePositiveCursor(cursor);\n const pages = await Promise.all(\n sourceIds.map(async sourceId => {\n const connection = { type: 'app-installation' as const, installationId: 1 };\n const [issues, pullRequests] = await Promise.all([\n this.#listIssues(connection, sourceId, page),\n this.#listPullRequests({ connection, sourceId, includeDrafts: false, cursor: String(page) }),\n ]);\n return {\n items: [\n ...issues.issues.map(issue => ({\n source: { type: 'issue', externalId: `${sourceId}:${issue.id}`, url: issue.url },\n sourceId,\n title: issue.title,\n status: issue.state ?? undefined,\n labels: issue.labels,\n assignee: issue.assignee,\n createdAt: issue.createdAt,\n updatedAt: issue.updatedAt,\n metadata: { repository: sourceId, number: Number(issue.id), author: issue.author },\n })),\n ...pullRequests.pullRequests.map(pullRequest => ({\n source: { type: 'pull-request', externalId: `${sourceId}:${pullRequest.id}`, url: pullRequest.url },\n sourceId,\n title: pullRequest.title,\n status: pullRequest.state,\n createdAt: pullRequest.createdAt,\n updatedAt: pullRequest.updatedAt,\n metadata: {\n repository: sourceId,\n number: Number(pullRequest.id),\n author: pullRequest.author,\n baseBranch: pullRequest.baseBranch,\n headBranch: pullRequest.headBranch,\n },\n })),\n ],\n hasNextPage: issues.nextCursor !== null || pullRequests.nextCursor !== null,\n };\n }),\n );\n return {\n items: pages.flatMap(result => result.items),\n nextCursor: pages.some(result => result.hasNextPage) ? String(page + 1) : null,\n };\n },\n listIssues: async input => {\n requireGithubConnection(input.connection);\n const sourceId = requireSingleSource(input.sourceIds, 'GitHub Intake requires exactly one repository source.');\n return this.#listIssues(input.connection, sourceId, parsePositiveCursor(input.cursor), input.labels);\n },\n getIssue: input => this.#getIssue(input.connection, input.sourceId, input.issueId),\n createComment: input => this.#createIssueComment(input),\n updateIssue: input => this.#updateIntakeIssue(input),\n };\n\n readonly versionControl: VersionControl = {\n initialize: ({ storage }) => {\n this.#storage = storage;\n },\n registerInstallation: ({ orgId, userId, installation }) =>\n this.storage.installations.upsert({\n orgId,\n connectedByUserId: userId,\n externalId: installation.externalId,\n accountName: installation.accountName,\n accountType: installation.accountType,\n providerMetadata: installation.metadata,\n }),\n registerRepositories: ({ orgId, installationId, repositories }) =>\n Promise.all(\n repositories.map(repository =>\n this.storage.repositories.upsert({\n orgId,\n input: {\n installationId,\n externalId: repository.externalId,\n slug: repository.slug,\n defaultBranch: repository.defaultBranch,\n providerMetadata: repository.metadata,\n },\n }),\n ),\n ),\n getRepositoryAccess: async ({ orgId, repositoryId }) => {\n const repository = await this.storage.repositories.get({ orgId, id: repositoryId });\n if (!repository) throw new Error('Version-control repository not found.');\n const cloneUrl = `https://github.com/${repository.slug}.git`;\n const installation = await this.storage.installations.get({ orgId, id: repository.installationId });\n if (!installation) throw new Error('Version-control installation not found.');\n const installationId = parsePositiveInteger(installation.externalId);\n if (installationId === null) throw new Error('GitHub installation id is invalid.');\n const repositoryName = splitRepository(repository.slug).repo;\n const token = await this.#client.request<{ token: string }>(\n 'POST',\n `${API_PREFIX}/github-app/installations/${installationId}/token`,\n { repositories: [repositoryName], permissions: REPOSITORY_TOKEN_PERMISSIONS },\n );\n return {\n cloneUrl,\n authorization: { scheme: 'bearer', token: token.token },\n };\n },\n listPullRequests: input => this.#listPullRequests(input),\n getPullRequest: input => this.#getPullRequest(input),\n createPullRequest: input => this.#createPullRequest(input),\n updatePullRequest: input => this.#updatePullRequest(input),\n closePullRequest: input => this.#updatePullRequest({ ...input, state: 'closed' }),\n mergePullRequest: input => this.#mergePullRequest(input),\n listComments: input => this.#listComments(input),\n createComment: input => this.#createComment(input),\n updateComment: input => this.#updateComment(input),\n deleteComment: input => this.#deleteComment(input),\n listReviews: input => this.#listReviews(input),\n getReview: input => this.#getReview(input),\n createReview: input => this.#createReview(input),\n updateReview: input => this.#updateReview(input),\n submitReview: input => this.#submitReview(input),\n dismissReview: input => this.#dismissReview(input),\n deletePendingReview: input => this.#deletePendingReview(input),\n listReviewComments: input => this.#listReviewComments(input),\n createReviewComment: input => this.#createReviewComment(input),\n updateReviewComment: input => this.#updateReviewComment(input),\n deleteReviewComment: input => this.#deleteReviewComment(input),\n listRequestedReviewers: input => this.#requestedReviewers('GET', input),\n requestReviewers: input => this.#requestedReviewers('POST', input),\n removeRequestedReviewers: input => this.#requestedReviewers('DELETE', input),\n };\n\n constructor() {\n const config = platformApiClientConfigFromEnv();\n this.#client = new PlatformApiClient(config);\n this.#endpointHost = new URL(config.baseUrl).host;\n this.#pollingEnabled = process.env.MASTRA_PLATFORM_GITHUB_POLLING_ENABLED?.trim().toLowerCase() !== 'false';\n this.#pollingIntervalMs = optionalPositiveIntegerEnv('MASTRA_PLATFORM_GITHUB_POLLING_INTERVAL_MS');\n }\n\n get storage(): SourceControlStorageHandle {\n if (!this.#storage) throw new Error('PlatformGithubIntegration source-control storage has not been initialized.');\n return this.#storage;\n }\n\n get sourceControlStorage(): SourceControlStorageHandle {\n return this.storage;\n }\n\n get integrationStorage(): GithubSubscriptionStorage {\n if (!this.#integrationStorage) {\n throw new Error('PlatformGithubIntegration generic storage has not been initialized.');\n }\n return this.#integrationStorage;\n }\n\n /** Resolve a stored GitHub locator without scanning installations or repositories. */\n async #resolveIntakeDispatch({\n orgId,\n externalSource,\n }: {\n orgId: string;\n externalSource: { type: string; externalId: string };\n }): Promise<{ connection: IntegrationConnection; sourceId: string; issueId: string } | null> {\n const target = parseGithubExternalTarget(externalSource.externalId);\n if (!target) return null;\n const repository = target.repository.includes('/')\n ? target.repository\n : (await this.storage.repositories.findByExternalId({ orgId, externalId: target.repository }))?.slug;\n if (!repository) return null;\n return {\n connection: { type: 'app-installation', installationId: 1 },\n sourceId: repository,\n issueId: target.issueId,\n };\n }\n\n initialize({ storage }: { storage: IntegrationStorageHandle }): void {\n this.#integrationStorage = storage as unknown as GithubSubscriptionStorage;\n logPlatformInfo('Platform GitHub integration initialized', {\n endpointHost: this.#endpointHost,\n pollingEnabled: this.#pollingEnabled,\n pollingIntervalMs: this.#pollingIntervalMs,\n });\n }\n\n routes(ctx: IntegrationContext): ApiRoute[] {\n return [\n this.#statusRoute(ctx),\n this.#connectRoute(ctx),\n this.#connectUserRoute(ctx),\n ...buildGithubRoutes({\n auth: ctx.auth,\n fleet: ctx.fleet,\n storage: ctx.factoryStorage,\n github: this as unknown as GithubIntegration,\n stateSigner: ctx.stateSigner,\n baseUrl: ctx.baseUrl,\n controller: ctx.controller,\n projects: ctx.storage.projects,\n emitAudit: ctx.hooks?.emitAudit,\n ingestFactoryEvent: ctx.hooks?.ingestGithubEvent,\n }).filter(\n route =>\n route.path !== '/web/github/status' &&\n route.path !== '/web/github/webhook' &&\n !route.path.startsWith('/auth/github/'),\n ),\n ];\n }\n\n #statusRoute(ctx: IntegrationContext): ApiRoute {\n return registerApiRoute('/web/github/status', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n await ctx.auth.ensureUser(loose(c));\n const tenant = ctx.auth.tenant(loose(c));\n if (!tenant) return c.json({ error: 'unauthorized', reason: 'auth_required' }, 401);\n if (!tenant.orgId) {\n return c.json({\n enabled: true,\n sandboxEnabled: ctx.fleet.enabled,\n organizationRequired: true,\n connected: false,\n installations: [],\n userConnected: false,\n userGithubUsername: null,\n reason: 'organization_required',\n diagnostics: this.diagnostics(),\n });\n }\n\n const [installations, userConnection] = await Promise.all([\n this.#syncInstallations(tenant.orgId, tenant.userId),\n this.#fetchUserConnection(tenant.userId),\n ]);\n return c.json({\n enabled: true,\n sandboxEnabled: ctx.fleet.enabled,\n connected: installations.length > 0,\n installations: installations.map(installation => ({\n installationId: Number(installation.externalId),\n accountLogin: installation.accountName,\n accountType: installation.accountType,\n })),\n userConnected: userConnection.connected,\n userGithubUsername: userConnection.githubUsername,\n reason: installations.length > 0 ? 'ready' : 'not_connected',\n diagnostics: this.diagnostics(),\n });\n },\n });\n }\n\n #connectRoute(ctx: IntegrationContext): ApiRoute {\n return registerApiRoute('/auth/github/connect', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n await ctx.auth.ensureUser(loose(c));\n const tenant = ctx.auth.tenant(loose(c));\n if (!tenant?.orgId) return c.json({ error: 'unauthorized' }, 401);\n\n const redirectTo = c.req.query('redirectTo') || c.req.query('return_to') || '/';\n const originator = routeBaseUrl(ctx, c.req.url);\n logPlatformInfo('Starting Platform GitHub connect flow', {\n orgId: tenant.orgId,\n redirectTo,\n originator,\n });\n const query = new URLSearchParams({\n action: 'install',\n redirectTo,\n originator,\n });\n const { url } = await this.#client.request<{ url: string }>(\n 'GET',\n `${API_PREFIX}/github-app/install-url?${query}`,\n );\n return c.redirect(url);\n },\n });\n }\n\n #connectUserRoute(ctx: IntegrationContext): ApiRoute {\n return registerApiRoute('/auth/github/connect-user', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n await ctx.auth.ensureUser(loose(c));\n const tenant = ctx.auth.tenant(loose(c));\n if (!tenant?.orgId) return c.json({ error: 'unauthorized' }, 401);\n\n const redirectTo = c.req.query('redirectTo') || c.req.query('return_to') || '/';\n const originator = routeBaseUrl(ctx, c.req.url);\n logPlatformInfo('Starting Platform GitHub user authorization flow', {\n orgId: tenant.orgId,\n redirectTo,\n originator,\n });\n const query = new URLSearchParams({\n userId: tenant.userId,\n redirectTo,\n originator,\n });\n const { url } = await this.#client.request<{ url: string }>(\n 'GET',\n `${API_PREFIX}/github-app/authenticate?${query}`,\n );\n return c.redirect(url);\n },\n });\n }\n\n /**\n * Personal GitHub connection status for the acting user. Returns\n * not-connected when the platform predates the user-connection endpoint.\n */\n async #fetchUserConnection(userId: string): Promise<PlatformGithubUserConnection> {\n try {\n const connection = await this.#client.request<PlatformGithubUserConnection>(\n 'GET',\n `${API_PREFIX}/github-app/user-connection?${new URLSearchParams({ userId })}`,\n );\n if (!connection.connected && connection.reason) {\n logPlatformWarn('Platform GitHub user connection verification failed', {\n userId,\n reason: connection.reason,\n });\n }\n return connection;\n } catch {\n return { connected: false, githubUsername: null };\n }\n }\n\n async #syncInstallations(orgId: string, userId: string): Promise<SourceControlInstallation[]> {\n const result = await this.#client.request<{ installations: PlatformGithubInstallation[] }>(\n 'GET',\n `${API_PREFIX}/github-app/installations`,\n );\n const usableInstallations = result.installations.filter(\n installation => installation.usable && !installation.suspendedAt,\n );\n return Promise.all(\n usableInstallations.map(installation =>\n this.versionControl.registerInstallation({\n orgId,\n userId,\n installation: {\n externalId: String(installation.installationId),\n accountName: installation.accountLogin,\n accountType: installation.accountType,\n },\n }),\n ),\n );\n }\n\n workers(ctx: IntegrationContext): PlatformGithubEventWorker[] {\n if (!this.#pollingEnabled) return [];\n if (!ctx.controller) {\n throw new Error('Platform GitHub event polling requires the mounted Mastra Code controller.');\n }\n return [\n new PlatformGithubEventWorker({\n client: this.#client,\n controller: ctx.controller,\n github: this,\n storage: ctx.storage.generic as unknown as PlatformGithubEventStorage,\n ingestFactoryEvent: ctx.hooks?.ingestGithubEvent,\n intervalMs: this.#pollingIntervalMs,\n }),\n ];\n }\n\n sessionTools({ requestContext }: { requestContext: RequestContext }): IntegrationTools {\n return createGithubSubscriptionTools(requestContext, this as unknown as GithubIntegration);\n }\n\n async postToolObserver({\n toolContext,\n requestContext,\n }: Parameters<NonNullable<FactoryIntegration['postToolObserver']>>[0]): Promise<void> {\n const pullRequestUrl = parseCreatedPullRequest(toolContext);\n if (!pullRequestUrl || !requestContext) return;\n await subscribeCurrentSessionToPullRequest(\n requestContext,\n pullRequestUrl,\n 'auto-gh-pr-create',\n this as unknown as GithubIntegration,\n );\n }\n\n diagnostics(): Record<string, unknown> {\n return {\n mode: 'platform',\n endpointHost: this.#endpointHost,\n polling: {\n enabled: this.#pollingEnabled,\n ...(this.#pollingIntervalMs === undefined ? {} : { intervalMs: this.#pollingIntervalMs }),\n },\n };\n }\n\n async getRepositoryCollaboratorPermission(\n _installationId: number,\n repoFullName: string,\n username: string,\n signal?: AbortSignal,\n ): Promise<GithubRepositoryPermission | undefined> {\n let repository: { owner: string; repo: string };\n try {\n repository = splitRepository(repoFullName);\n } catch {\n return undefined;\n }\n try {\n const result = await this.#client.request<{ permission: GithubRepositoryPermission }>(\n 'GET',\n `${API_PREFIX}/github/repos/${encodeURIComponent(repository.owner)}/${encodeURIComponent(repository.repo)}/collaborators/${encodeURIComponent(username)}/permission`,\n undefined,\n { signal },\n );\n return result.permission;\n } catch {\n return undefined;\n }\n }\n\n async listInstallationRepos(installationId: number): Promise<RepoSummary[]> {\n const result = await this.#client.request<{\n repositories: Array<{\n id: number;\n owner: string;\n name: string;\n fullName: string;\n private: boolean;\n defaultBranch: string;\n }>;\n }>('GET', `${API_PREFIX}/github-app/installations/${installationId}/repositories`);\n return result.repositories.map(repository => ({ ...repository, installationId }));\n }\n\n async mintInstallationToken(installationId: number): Promise<string> {\n const repositories = await this.listInstallationRepos(installationId);\n if (repositories.length === 0 || repositories.length > 10) {\n throw new Error('Platform GitHub token minting requires between one and ten installation repositories.');\n }\n const result = await this.#client.request<{ token: string }>(\n 'POST',\n `${API_PREFIX}/github-app/installations/${installationId}/token`,\n { repositories: repositories.map(repository => repository.name), permissions: REPOSITORY_TOKEN_PERMISSIONS },\n );\n return result.token;\n }\n\n async addIssueLabels(\n _installationId: number,\n sourceId: string,\n issueNumber: number,\n labels: string[],\n ): Promise<string[]> {\n const result = await this.#client.request<{ labels: string[] }>(\n 'POST',\n repositoryPath(sourceId, `issues/${issueNumber}/labels`),\n { labels },\n );\n return result.labels;\n }\n\n getInstallationOctokit(_installationId: number): ReturnType<GithubIntegration['getInstallationOctokit']> {\n return {\n pulls: {\n get: async ({ owner, repo, pull_number }: { owner: string; repo: string; pull_number: number }) => {\n const data = await this.#client.request<GithubPullRequest>(\n 'GET',\n repositoryPath(`${owner}/${repo}`, `pulls/${pull_number}`),\n );\n return { data: { base: { repo: { id: data.base.repo.id } } } };\n },\n },\n } as unknown as ReturnType<GithubIntegration['getInstallationOctokit']>;\n }\n\n async #listIssues(connection: IntegrationConnection, sourceId: string, page: number, labels?: string[]) {\n requireGithubConnection(connection);\n const path = repositoryPath(sourceId, 'issues');\n const query = new URLSearchParams({ state: 'open', page: String(page), per_page: String(PAGE_SIZE) });\n const normalizedLabels = normalizeLabels(labels);\n if (normalizedLabels.length > 0) query.set('label', normalizedLabels.join(','));\n const result = await this.#client.request<{ issues: GithubIssue[] }>('GET', `${path}?${query}`);\n return {\n issues: result.issues.map(issue => parseIntakeIssue(sourceId, issue)),\n nextCursor: result.issues.length === PAGE_SIZE ? String(page + 1) : null,\n };\n }\n\n async #getIssue(connection: IntegrationConnection, sourceId: string | undefined, issueId: string) {\n requireGithubConnection(connection);\n const repository = requireSource(sourceId, 'GitHub Intake requires a repository source.');\n const issueNumber = requirePositiveId(issueId, 'issue');\n try {\n const [issue, comments] = await Promise.all([\n this.#client.request<GithubIssue>('GET', repositoryPath(repository, `issues/${issueNumber}`)),\n this.#client.request<{ comments: GithubComment[] }>(\n 'GET',\n `${repositoryPath(repository, `issues/${issueNumber}/comments`)}?per_page=100`,\n ),\n ]);\n return parseIntakeIssueDetail(repository, issue, comments.comments);\n } catch (error) {\n if (isNotFound(error)) return null;\n throw error;\n }\n }\n\n async #updateIntakeIssue(input: UpdateIntakeIssueInput): Promise<IntakeIssue | null> {\n requireGithubConnection(input.connection);\n const repository = requireSource(input.sourceId, 'GitHub Intake requires a repository source.');\n const issueNumber = requirePositiveId(input.issueId, 'issue');\n if (input.state.kind === 'byName') {\n logPlatformWarn(`Platform GitHub: updateIssue byName is not supported (name=${input.state.name}); ignoring.`);\n return null;\n }\n const targetState: 'open' | 'closed' =\n input.state.stateType === 'unstarted' || input.state.stateType === 'started' ? 'open' : 'closed';\n const stateReason: 'completed' | 'not_planned' | null =\n targetState === 'closed' ? (input.state.stateType === 'canceled' ? 'not_planned' : 'completed') : null;\n // Reject PR targets: probe the pulls endpoint. A 200 means the number is a\n // pull request, not an issue. Factory does not close PRs via updateIssue —\n // PR merges/closes go through the version-control pipeline.\n try {\n await this.#client.request<GithubPullRequest>('GET', repositoryPath(repository, `pulls/${issueNumber}`));\n logPlatformWarn(`Platform GitHub: updateIssue rejected — target ${repository}#${issueNumber} is a pull request.`);\n return null;\n } catch (error) {\n if (!isNotFound(error)) throw error;\n // 404 on pulls means it's an issue (or nothing) — fall through to PATCH.\n }\n try {\n const issue = await this.#client.request<GithubIssue>(\n 'PATCH',\n repositoryPath(repository, `issues/${issueNumber}`),\n {\n state: targetState,\n ...(stateReason ? { state_reason: stateReason } : {}),\n },\n { actingUserId: input.actingUserId },\n );\n return parseIntakeIssue(repository, issue);\n } catch (error) {\n if (isNotFound(error)) return null;\n throw error;\n }\n }\n\n async #createIssueComment(input: CreateIntakeCommentInput) {\n requireGithubConnection(input.connection);\n const repository = requireSource(input.sourceId, 'GitHub Intake requires a repository source.');\n const issueNumber = requirePositiveId(input.issueId, 'issue');\n try {\n const comment = await this.#client.request<GithubComment>(\n 'POST',\n repositoryPath(repository, `issues/${issueNumber}/comments`),\n { body: input.body },\n { actingUserId: input.actingUserId },\n );\n return { id: String(comment.id), url: comment.htmlUrl };\n } catch (error) {\n if (isNotFound(error)) return null;\n throw error;\n }\n }\n\n async #listPullRequests(input: ListPullRequestsInput) {\n requireGithubConnection(input.connection);\n const page = parsePositiveCursor(input.cursor);\n const query = new URLSearchParams({\n state: input.state ?? 'open',\n page: String(page),\n per_page: String(PAGE_SIZE),\n });\n const result = await this.#client.request<{ pullRequests: GithubPullRequest[] }>(\n 'GET',\n `${repositoryPath(input.sourceId, 'pulls')}?${query}`,\n );\n return {\n pullRequests: result.pullRequests\n .filter(pullRequest => input.includeDrafts !== false || !pullRequest.draft)\n .map(parsePullRequest),\n nextCursor: result.pullRequests.length === PAGE_SIZE ? String(page + 1) : null,\n };\n }\n\n async #getPullRequest(input: PullRequestRef) {\n try {\n return parsePullRequest(\n await this.#client.request<GithubPullRequest>('GET', pullRequestPath(input, input.pullRequestId)),\n );\n } catch (error) {\n if (isNotFound(error)) return null;\n throw error;\n }\n }\n\n async #createPullRequest(input: CreatePullRequestInput) {\n requireGithubConnection(input.connection);\n const result = await this.#client.request<GithubPullRequest>(\n 'POST',\n repositoryPath(input.sourceId, 'pulls'),\n {\n head: input.headBranch,\n base: input.baseBranch,\n title: input.title,\n body: input.body,\n draft: input.draft,\n },\n { actingUserId: input.actingUserId },\n );\n return parsePullRequest(result);\n }\n\n async #updatePullRequest(input: UpdatePullRequestInput) {\n const result = await this.#client.request<GithubPullRequest>(\n 'PATCH',\n pullRequestPath(input, input.pullRequestId),\n {\n title: input.title,\n body: input.body === null ? '' : input.body,\n base: input.baseBranch,\n state: input.state,\n },\n { actingUserId: input.actingUserId },\n );\n return parsePullRequest(result);\n }\n\n #mergePullRequest(input: MergePullRequestInput) {\n return this.#client.request<{ merged: boolean; message: string; sha: string | null }>(\n 'PUT',\n `${pullRequestPath(input, input.pullRequestId)}/merge`,\n { commitTitle: input.commitTitle, commitMessage: input.commitMessage, method: input.method },\n { actingUserId: input.actingUserId },\n );\n }\n\n async #listComments(input: ListPullRequestCommentsInput) {\n const page = parsePositiveCursor(input.cursor);\n const result = await this.#client.request<{ comments: GithubComment[] }>(\n 'GET',\n `${repositoryPath(input.sourceId, `issues/${requirePositiveId(input.pullRequestId, 'pull request')}/comments`)}?page=${page}&per_page=${PAGE_SIZE}`,\n );\n return {\n comments: result.comments.map(parseComment),\n nextCursor: result.comments.length === PAGE_SIZE ? String(page + 1) : null,\n };\n }\n\n async #createComment(input: CreatePullRequestCommentInput) {\n const comment = await this.#client.request<GithubComment>(\n 'POST',\n repositoryPath(input.sourceId, `issues/${requirePositiveId(input.pullRequestId, 'pull request')}/comments`),\n { body: input.body },\n { actingUserId: input.actingUserId },\n );\n return parseComment(comment);\n }\n\n async #updateComment(input: UpdatePullRequestCommentInput) {\n requireGithubConnection(input.connection);\n const comment = await this.#client.request<GithubComment>(\n 'PATCH',\n repositoryPath(input.sourceId, `issues/comments/${requirePositiveId(input.commentId, 'comment')}`),\n { body: input.body },\n { actingUserId: input.actingUserId },\n );\n return parseComment(comment);\n }\n\n async #deleteComment(input: DeletePullRequestCommentInput) {\n requireGithubConnection(input.connection);\n await this.#client.request<void>(\n 'DELETE',\n repositoryPath(input.sourceId, `issues/comments/${requirePositiveId(input.commentId, 'comment')}`),\n undefined,\n { actingUserId: input.actingUserId },\n );\n }\n\n async #listReviews(input: ListReviewsInput) {\n const page = parsePositiveCursor(input.cursor);\n const result = await this.#client.request<{ reviews: GithubReview[] }>(\n 'GET',\n `${pullRequestPath(input, input.pullRequestId)}/reviews?page=${page}&per_page=${PAGE_SIZE}`,\n );\n return {\n reviews: result.reviews.map(parseReview),\n nextCursor: result.reviews.length === PAGE_SIZE ? String(page + 1) : null,\n };\n }\n\n async #getReview(input: ReviewRef) {\n try {\n return parseReview(\n await this.#client.request<GithubReview>(\n 'GET',\n `${pullRequestPath(input, input.pullRequestId)}/reviews/${requirePositiveId(input.reviewId, 'review')}`,\n ),\n );\n } catch (error) {\n if (isNotFound(error)) return null;\n throw error;\n }\n }\n\n async #createReview(input: CreateReviewInput) {\n const review = await this.#client.request<GithubReview>(\n 'POST',\n `${pullRequestPath(input, input.pullRequestId)}/reviews`,\n { body: input.body, commitId: input.commitId, event: input.event ? reviewEvent(input.event) : undefined },\n { actingUserId: input.actingUserId },\n );\n return parseReview(review);\n }\n\n async #updateReview(input: UpdateReviewInput) {\n const review = await this.#client.request<GithubReview>(\n 'PUT',\n `${pullRequestPath(input, input.pullRequestId)}/reviews/${requirePositiveId(input.reviewId, 'review')}`,\n { body: input.body },\n { actingUserId: input.actingUserId },\n );\n return parseReview(review);\n }\n\n async #submitReview(input: SubmitReviewInput) {\n const review = await this.#client.request<GithubReview>(\n 'POST',\n `${pullRequestPath(input, input.pullRequestId)}/reviews/${requirePositiveId(input.reviewId, 'review')}/events`,\n { body: input.body, event: reviewEvent(input.event) },\n { actingUserId: input.actingUserId },\n );\n return parseReview(review);\n }\n\n async #dismissReview(input: DismissReviewInput) {\n const review = await this.#client.request<GithubReview>(\n 'PUT',\n `${pullRequestPath(input, input.pullRequestId)}/reviews/${requirePositiveId(input.reviewId, 'review')}/dismissals`,\n { message: input.message },\n { actingUserId: input.actingUserId },\n );\n return parseReview(review);\n }\n\n async #deletePendingReview(input: ReviewRef) {\n await this.#client.request<void>(\n 'DELETE',\n `${pullRequestPath(input, input.pullRequestId)}/reviews/${requirePositiveId(input.reviewId, 'review')}`,\n undefined,\n { actingUserId: input.actingUserId },\n );\n }\n\n async #listReviewComments(input: ListReviewCommentsInput) {\n const page = parsePositiveCursor(input.cursor);\n const result = await this.#client.request<{ comments: GithubReviewComment[] }>(\n 'GET',\n `${pullRequestPath(input, input.pullRequestId)}/comments?page=${page}&per_page=${PAGE_SIZE}`,\n );\n return {\n comments: result.comments.map(parseReviewComment),\n nextCursor: result.comments.length === PAGE_SIZE ? String(page + 1) : null,\n };\n }\n\n async #createReviewComment(input: CreateReviewCommentInput) {\n let body: Record<string, unknown>;\n if (input.replyToId !== undefined) {\n body = { body: input.body, replyToId: requirePositiveId(input.replyToId, 'review comment') };\n } else {\n if (!input.commitId || !input.path || input.line === undefined || !input.side) {\n throw new Error('A review comment requires commitId, path, line, and side unless it is a reply.');\n }\n body = {\n body: input.body,\n commitId: input.commitId,\n path: input.path,\n line: input.line,\n side: input.side.toUpperCase(),\n startLine: input.startLine,\n startSide: input.startSide?.toUpperCase(),\n };\n }\n return parseReviewComment(\n await this.#client.request<GithubReviewComment>(\n 'POST',\n `${pullRequestPath(input, input.pullRequestId)}/comments`,\n body,\n { actingUserId: input.actingUserId },\n ),\n );\n }\n\n async #updateReviewComment(input: UpdatePullRequestCommentInput) {\n requireGithubConnection(input.connection);\n return parseReviewComment(\n await this.#client.request<GithubReviewComment>(\n 'PATCH',\n repositoryPath(input.sourceId, `pulls/comments/${requirePositiveId(input.commentId, 'review comment')}`),\n { body: input.body },\n { actingUserId: input.actingUserId },\n ),\n );\n }\n\n async #deleteReviewComment(input: DeletePullRequestCommentInput) {\n requireGithubConnection(input.connection);\n await this.#client.request<void>(\n 'DELETE',\n repositoryPath(input.sourceId, `pulls/comments/${requirePositiveId(input.commentId, 'review comment')}`),\n undefined,\n { actingUserId: input.actingUserId },\n );\n }\n\n #requestedReviewers(method: 'GET' | 'POST' | 'DELETE', input: UpdateReviewersInput) {\n requireGithubConnection(input.connection);\n return this.#client.request<{ users: string[]; teams: string[] }>(\n method,\n `${pullRequestPath(input, input.pullRequestId)}/requested-reviewers`,\n method === 'GET' ? undefined : { users: input.users, teams: input.teams },\n method === 'GET' ? undefined : { actingUserId: input.actingUserId },\n );\n }\n}\n\nfunction repositoryPath(sourceId: string, suffix: string): string {\n const { owner, repo } = splitRepository(sourceId);\n return `${API_PREFIX}/github/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/${suffix}`;\n}\n\nfunction pullRequestPath(\n input: { connection: IntegrationConnection; sourceId: string },\n pullRequestId: string,\n): string {\n requireGithubConnection(input.connection);\n return repositoryPath(input.sourceId, `pulls/${requirePositiveId(pullRequestId, 'pull request')}`);\n}\n\nfunction splitRepository(sourceId: string): { owner: string; repo: string } {\n const slash = sourceId.indexOf('/');\n if (slash <= 0 || slash === sourceId.length - 1) {\n throw new Error('GitHub capabilities require an owner/repository source.');\n }\n return { owner: sourceId.slice(0, slash), repo: sourceId.slice(slash + 1) };\n}\n\nfunction parseIntakeIssue(sourceId: string, issue: GithubIssue): IntakeIssue {\n return {\n id: String(issue.number),\n identifier: `#${issue.number}`,\n title: issue.title,\n url: issue.htmlUrl,\n author: issue.user?.login ?? null,\n state: issue.state,\n stateType: issue.state,\n priority: null,\n assignee: issue.assignees[0] ?? null,\n source: sourceId,\n labels: issue.labels,\n commentCount: issue.commentCount,\n createdAt: issue.createdAt,\n updatedAt: issue.updatedAt,\n };\n}\n\nfunction parseIntakeIssueDetail(sourceId: string, issue: GithubIssue, comments: GithubComment[]): IntakeIssueDetail {\n return {\n ...parseIntakeIssue(sourceId, issue),\n description: issue.body?.trim() ? issue.body : null,\n comments: comments.map(comment => ({\n author: comment.user?.login ?? null,\n body: comment.body,\n createdAt: comment.createdAt,\n })),\n };\n}\n\nfunction parsePullRequest(pullRequest: GithubPullRequest): PullRequest {\n return {\n id: String(pullRequest.number),\n title: pullRequest.title,\n url: pullRequest.htmlUrl,\n author: pullRequest.user?.login ?? null,\n body: pullRequest.body?.trim() ? pullRequest.body : null,\n state: pullRequest.state,\n draft: pullRequest.draft,\n merged: pullRequest.merged,\n mergeable: pullRequest.mergeable,\n baseBranch: pullRequest.base.ref,\n headBranch: pullRequest.head.ref,\n headSha: pullRequest.head.sha,\n createdAt: pullRequest.createdAt,\n updatedAt: pullRequest.updatedAt,\n };\n}\n\nfunction parseComment(comment: GithubComment): PullRequestComment {\n return {\n id: String(comment.id),\n url: comment.htmlUrl,\n author: comment.user?.login ?? null,\n body: comment.body,\n createdAt: comment.createdAt,\n updatedAt: comment.updatedAt,\n };\n}\n\nfunction parseReview(review: GithubReview): Review {\n const states: Record<GithubReview['state'], Review['state']> = {\n PENDING: 'pending',\n COMMENTED: 'commented',\n APPROVED: 'approved',\n CHANGES_REQUESTED: 'changes-requested',\n DISMISSED: 'dismissed',\n };\n return {\n id: String(review.id),\n url: review.htmlUrl,\n author: review.user?.login ?? null,\n body: review.body?.trim() ? review.body : null,\n state: states[review.state],\n commitId: review.commitId,\n submittedAt: review.submittedAt,\n };\n}\n\nfunction parseReviewComment(comment: GithubReviewComment): ReviewComment {\n return {\n ...parseComment(comment),\n path: comment.path,\n line: comment.line,\n side: comment.side?.toLowerCase() as 'left' | 'right' | null,\n commitId: comment.commitId,\n replyToId: comment.replyToId === null ? null : String(comment.replyToId),\n };\n}\n\nfunction requireGithubConnection(connection: IntegrationConnection): void {\n if (connection.type !== 'app-installation' && connection.type !== 'oauth') {\n throw new Error('GitHub capabilities require a GitHub connection.');\n }\n}\n\nfunction requireSingleSource(sourceIds: string[], message: string): string {\n if (sourceIds.length !== 1) throw new Error(message);\n return sourceIds[0]!;\n}\n\nfunction requireSource(sourceId: string | undefined, message: string): string {\n if (!sourceId) throw new Error(message);\n return sourceId;\n}\n\nfunction normalizeLabels(labels: string[] | undefined): string[] {\n return [...new Set((labels ?? []).map(label => label.trim()).filter(Boolean))];\n}\n\nfunction parsePositiveCursor(cursor: string | undefined): number {\n if (cursor === undefined) return 1;\n const parsed = parsePositiveInteger(cursor);\n if (parsed === null) throw new Error('GitHub cursor must be a positive page number.');\n return parsed;\n}\n\nfunction parsePositiveInteger(value: string): number | null {\n if (!/^\\d+$/.test(value)) return null;\n const parsed = Number(value);\n return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : null;\n}\n\nfunction parseGithubExternalTarget(externalId: string): { repository: string; issueId: string } | null {\n const match =\n externalId.match(/^(.+\\/.+):(\\d+)$/) ??\n externalId.match(/^github:(\\d+):(?:issue|pull-request):(\\d+)$/) ??\n externalId.match(/^(\\d+):(\\d+)$/);\n if (!match?.[1] || !match[2] || parsePositiveInteger(match[2]) === null) return null;\n return { repository: match[1], issueId: match[2] };\n}\n\nfunction optionalPositiveIntegerEnv(name: 'MASTRA_PLATFORM_GITHUB_POLLING_INTERVAL_MS'): number | undefined {\n const value = process.env[name]?.trim();\n if (!value) return undefined;\n const parsed = parsePositiveInteger(value);\n if (parsed === null) throw new Error(`${name} must be a positive integer.`);\n return parsed;\n}\n\nfunction requirePositiveId(value: string, resource: string): number {\n const parsed = parsePositiveInteger(value);\n if (parsed === null) throw new Error(`GitHub ${resource} id must be a positive integer.`);\n return parsed;\n}\n\nfunction reviewEvent(event: 'approve' | 'request-changes' | 'comment') {\n if (event === 'approve') return 'APPROVE' as const;\n if (event === 'request-changes') return 'REQUEST_CHANGES' as const;\n return 'COMMENT' as const;\n}\n\nfunction isNotFound(error: unknown): boolean {\n return error instanceof PlatformApiError && error.status === 404;\n}\n","/**\n * Mastra `apiRoutes` for the GitHub App project feature.\n *\n * Registered alongside the other `/web/*` routes, behind the host auth gate.\n * Every route additionally re-checks the authenticated user via the injected\n * `RouteAuth` seam and scopes all rows by that user's stable id, so a user can\n * only ever see and operate on their own installations and projects.\n *\n * When the feature is disabled (`isGithubFeatureEnabled()` false), `buildGithubRoutes`\n * returns only `GET /web/github/status`, which reports `enabled:false`\n * so the SPA can cleanly hide all GitHub UI.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type { MountedMastraCode } from '@mastra/code-sdk';\nimport type { ApiRoute } from '@mastra/core/server';\nimport { registerApiRoute } from '@mastra/core/server';\nimport type { FactoryStorage } from '@mastra/core/storage';\nimport type { Context } from 'hono';\nimport { streamSSE } from 'hono/streaming';\nimport type { RouteAuth } from '../../routes/route.js';\nimport { SandboxBudgetError } from '../../sandbox/fleet.js';\nimport type { MaterializationSandbox, PrepareProgress, ProgressFn, SandboxFleet } from '../../sandbox/fleet.js';\nimport type { StateSigner } from '../../state-signing.js';\nimport type { AuditEmitter } from '../../storage/domains/audit/domain.js';\nimport type { FactoryProjectsStorage } from '../../storage/domains/projects/base.js';\nimport type {\n ProjectRepository,\n ProjectRepositorySandbox,\n ProjectSourceControlConnection,\n SourceControlInstallation,\n SourceControlRepository,\n} from '../../storage/domains/source-control/base.js';\nimport { getGithubFeatureDiagnostics, isGithubFeatureEnabled } from './config.js';\nimport type { GithubIntegration } from './integration.js';\nimport { clearGithubPat, getGithubPat, getGithubPatStatus, setGithubPat } from './pat.js';\nimport type { GithubPatKind } from './pat.js';\nimport { withProjectLock } from './project-lock.js';\n\nimport {\n commitAll,\n computeWorktreePath,\n ensureProjectSandbox,\n isValidGitRef as isValidGitRefSandbox,\n materializeRepo,\n MaterializeError,\n pushBranch,\n teardownProjectSandbox,\n WorktreeError,\n} from './sandbox.js';\nimport type { GitIdentity } from './sandbox.js';\nimport { listPullRequestSubscriptionsForThread, subscribeToPullRequest } from './subscriptions.js';\nimport { handleGithubWebhook } from './webhook.js';\nimport type { GithubIssueTriageRunInput, GithubIssueTriageRunResult, ParsedGithubWebhook } from './webhook.js';\n\n/**\n * Loose Hono context accepted by the shared GitHub route helpers. The\n * `registerApiRoute` handlers receive a path-parameterized context whose\n * `HonoRequest` literal-path generics are invariant and don't flow into a\n * shared helper signature. The helpers only ever touch cookies/query/tenant, so\n * we erase the path to a plain `Context` at the call boundary via `loose()`.\n */\ntype RouteContext = Context;\n\n/** Erase a route handler's path-parameterized context to a plain `Context`. */\nfunction loose(c: unknown): RouteContext {\n return c as RouteContext;\n}\n\nexport interface MountGithubRoutesOptions {\n /** Host auth seam — resolves the signed-in user/tenant for each request. */\n auth: RouteAuth;\n /**\n * Sandbox fleet for per-project sandboxes. A fleet constructed without a\n * machine config reports `enabled: false` and the sandbox-backed routes\n * respond 503.\n */\n fleet: SandboxFleet;\n /**\n * Factory storage backend. Supplies the cross-replica `withDistributedLock`\n * capability for git write routes and the `appDbConfigured` diagnostic.\n */\n storage?: FactoryStorage;\n /**\n * The GitHub App integration the handlers operate on (Octokit access, token\n * minting, OAuth URLs). Normally supplied by `GithubIntegration.routes()`;\n * when absent, only the disabled `status` route is served.\n */\n github?: GithubIntegration;\n /**\n * Shared OAuth/install `state` signer (created once per boot by the\n * factory). Required for the OAuth/install flow; when absent, only the\n * disabled `status` route is served.\n */\n stateSigner?: StateSigner;\n /**\n * Absolute base URL of the web server (e.g. `http://localhost:4111`), used to\n * build the OAuth/install redirect URI when one isn't explicitly configured.\n */\n baseUrl?: string;\n /** Explicit OAuth callback URI; defaults to `<baseUrl>/auth/github/callback`. */\n redirectUri?: string;\n /** Controller used to route verified webhook notifications to exact subscribed sessions. */\n controller?: MountedMastraCode['controller'];\n /** Run seam used by GitHub webhooks and manual Intake triage. */\n runIssueTriage?: (input: GithubIssueTriageRunInput) => Promise<GithubIssueTriageRunResult>;\n /** Best-effort audit emission supplied by the factory-owned audit domain. */\n emitAudit?: AuditEmitter['emit'];\n /** Factory projects domain — resolves a project's default triage model. */\n projects?: FactoryProjectsStorage;\n /** Authoritative Factory rule ingress for normalized, signature-verified GitHub deliveries. */\n ingestFactoryEvent?: (event: ParsedGithubWebhook) => Promise<unknown>;\n}\n\n/**\n * Resolve the Factory project's default model for a triage run. Best-effort:\n * a missing project or an uninitialized storage domain simply means \"no\n * default\", never a failed run.\n */\nasync function resolveFactoryDefaultModelId(\n projects: FactoryProjectsStorage | undefined,\n factoryProjectId: string | undefined,\n): Promise<string | undefined> {\n if (!projects || !factoryProjectId) return undefined;\n try {\n const project = await projects.getById({ id: factoryProjectId });\n return project?.defaultModelId ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction pullRequestNumberFromUrl(value: string, expectedRepo: string): number | undefined {\n try {\n const url = new URL(value);\n const match = url.pathname.match(/^\\/([^/]+\\/[^/]+)\\/pull\\/(\\d+)\\/?$/);\n if (\n url.protocol !== 'https:' ||\n url.hostname !== 'github.com' ||\n match?.[1]?.toLowerCase() !== expectedRepo.toLowerCase()\n ) {\n return undefined;\n }\n const number = Number(match[2]);\n return Number.isInteger(number) && number > 0 ? number : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction isCanonicalGithubIssueUrl(value: string, repoFullName: string, issueNumber: number): boolean {\n try {\n const url = new URL(value);\n const [owner, repo] = repoFullName.split('/');\n return (\n url.protocol === 'https:' &&\n url.hostname === 'github.com' &&\n url.pathname === `/${owner}/${repo}/issues/${issueNumber}` &&\n url.search === '' &&\n url.hash === ''\n );\n } catch {\n return false;\n }\n}\n\n/**\n * Validate a git branch/ref name against a strict whitelist. The value is later\n * interpolated into a shell `git clone --branch` command, so it must never\n * contain shell metacharacters. We accept only git-ref-safe characters and\n * reject anything else rather than relying on shell quoting alone.\n */\nfunction isValidGitRef(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0 && value.length <= 255 && /^[A-Za-z0-9_./-]+$/.test(value);\n}\n\n/**\n * Resolve the org-scoped tenant for a GitHub request. GitHub project features\n * are org-owned, so they require both a signed-in user and a WorkOS\n * organization. Returns the `(orgId, userId)` tenant (with `orgId` narrowed to a\n * non-null string) or a ready-to-return error response: 401 when unauthenticated,\n * 403 when the user has no organization (personal account).\n *\n * Resolves the session from the request cookie itself (via `auth.ensureUser`)\n * instead of relying on the auth gate's context stash: on platform deploys\n * custom `apiRoutes` run on an isolated sub-app context where the gate's\n * `c.set(...)` is invisible. When the gate stash IS visible (local Hono\n * server), `auth.ensureUser` returns the cached user and this is a no-op.\n */\nasync function resolveOrgTenant(\n c: RouteContext,\n auth: RouteAuth,\n): Promise<{ tenant: { orgId: string; userId: string } } | { response: Response }> {\n await auth.ensureUser(c);\n const tenant = auth.tenant(c);\n if (!tenant) return { response: c.json({ error: 'unauthorized' }, 401) };\n if (!tenant.orgId) {\n return {\n response: c.json(\n {\n error: 'organization_required',\n message: 'GitHub projects require a WorkOS organization. Personal accounts cannot connect repositories.',\n },\n 403,\n ),\n };\n }\n return { tenant: { orgId: tenant.orgId, userId: tenant.userId } };\n}\n\n/**\n * Parse a 1-based `page` query param. Missing means page 1; anything that is\n * not a small positive integer is rejected (`null`).\n */\nfunction parseListPage(raw: string | undefined): number | null {\n if (raw === undefined) return 1;\n if (!/^\\d{1,5}$/.test(raw)) return null;\n const page = Number(raw);\n return page >= 1 ? page : null;\n}\n\nconst VALID_ISSUE_LABEL_FILTERS = new Set(['auto-triaged', 'needs-approval']);\n\nfunction parseIssueLabelFilter(raw: string | undefined): string | undefined | null {\n if (raw === undefined || raw === '') return undefined;\n if (VALID_ISSUE_LABEL_FILTERS.has(raw)) return raw;\n return null;\n}\n\nfunction parseIssueNumberParam(raw: string | undefined): number | null {\n if (!raw || !/^\\d{1,10}$/.test(raw)) return null;\n const issueNumber = Number(raw);\n return Number.isSafeInteger(issueNumber) && issueNumber > 0 ? issueNumber : null;\n}\n\nfunction parseStringList(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.filter((item): item is string => typeof item === 'string' && item.length > 0);\n}\n\ninterface ResolvedProjectRepository extends ProjectRepository {\n connection: ProjectSourceControlConnection;\n installation: SourceControlInstallation;\n repository: SourceControlRepository;\n factoryProjectId: string;\n defaultBranch: string;\n}\n\nasync function resolveProjectRepository(args: {\n github: GithubIntegration;\n orgId: string;\n projectRepositoryId: string;\n}): Promise<ResolvedProjectRepository | null> {\n const projectRepository = await args.github.sourceControlStorage.projectRepositories.get({\n orgId: args.orgId,\n id: args.projectRepositoryId,\n });\n if (!projectRepository) return null;\n const connection = await args.github.sourceControlStorage.connections.get({\n orgId: args.orgId,\n id: projectRepository.connectionId,\n });\n if (!connection) return null;\n const repository = await args.github.sourceControlStorage.repositories.get({\n orgId: args.orgId,\n id: projectRepository.repositoryId,\n });\n if (!repository) return null;\n const installation = await args.github.sourceControlStorage.installations.get({\n orgId: args.orgId,\n id: connection.installationId,\n });\n if (!installation) return null;\n return {\n ...projectRepository,\n connection,\n installation,\n repository,\n factoryProjectId: connection.factoryProjectId,\n defaultBranch: projectRepository.branch ?? repository.defaultBranch,\n };\n}\n\nfunction polledIssueEvent(\n project: ResolvedProjectRepository,\n issue: {\n number: number;\n title: string;\n url: string;\n author: string | null;\n labels: string[];\n createdAt: string;\n },\n): ParsedGithubWebhook {\n const repositoryId = Number(project.repository.externalId);\n return {\n event: 'issues',\n deliveryId: `poll:${repositoryId}:issue:${issue.number}:${issue.createdAt}`,\n payload: {\n action: 'opened',\n installation: { id: Number(project.installation.externalId) },\n repository: { id: repositoryId, full_name: project.repository.slug },\n sender: { login: issue.author ?? '__unknown__' },\n issue: {\n number: issue.number,\n title: issue.title,\n html_url: issue.url,\n created_at: issue.createdAt,\n labels: issue.labels.map(name => ({ name })),\n },\n },\n };\n}\n\nfunction polledPullRequestEvent(\n project: ResolvedProjectRepository,\n pullRequest: {\n number: number;\n title: string;\n url: string;\n author: string | null;\n headBranch: string;\n baseBranch: string;\n createdAt: string;\n },\n): ParsedGithubWebhook {\n const repositoryId = Number(project.repository.externalId);\n return {\n event: 'pull_request',\n deliveryId: `poll:${repositoryId}:pull-request:${pullRequest.number}:${pullRequest.createdAt}`,\n payload: {\n action: 'opened',\n installation: { id: Number(project.installation.externalId) },\n repository: { id: repositoryId, full_name: project.repository.slug },\n sender: { login: pullRequest.author ?? '__unknown__' },\n pull_request: {\n number: pullRequest.number,\n title: pullRequest.title,\n html_url: pullRequest.url,\n created_at: pullRequest.createdAt,\n state: 'open',\n merged: false,\n head: { ref: pullRequest.headBranch },\n base: { ref: pullRequest.baseBranch },\n },\n },\n };\n}\n\nasync function ingestPolledEvents(\n events: ParsedGithubWebhook[],\n ingestFactoryEvent: MountGithubRoutesOptions['ingestFactoryEvent'],\n): Promise<void> {\n if (!ingestFactoryEvent) return;\n const results = await Promise.allSettled(events.map(event => ingestFactoryEvent(event)));\n const rejected = results.find((result): result is PromiseRejectedResult => result.status === 'rejected');\n if (rejected) throw rejected.reason;\n}\n\n/**\n * Build the GitHub routes as Mastra `apiRoutes`. When the feature is disabled,\n * returns only the `status` route so the SPA can detect the disabled state.\n */\nexport function buildGithubRoutes(options: MountGithubRoutesOptions): ApiRoute[] {\n const routes: ApiRoute[] = [];\n const { auth, fleet, storage, github, stateSigner, emitAudit } = options;\n const diagnostics = () =>\n getGithubFeatureDiagnostics({ github, auth, appDbConfigured: storage !== undefined, stateSigner, fleet });\n\n // The status route is always registered so the SPA can detect the disabled state.\n routes.push(\n registerApiRoute('/web/github/status', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n if (!isGithubFeatureEnabled({ github, auth }) || !github || !stateSigner) {\n return c.json({\n enabled: false,\n connected: false,\n installations: [],\n reason: 'missing_config',\n diagnostics: diagnostics(),\n });\n }\n // Resolve the session from the request cookie: on platform deploys custom\n // apiRoutes run on an isolated context where the gate's stash is invisible.\n await auth.ensureUser(loose(c));\n const tenant = auth.tenant(loose(c));\n if (!tenant) return c.json({ error: 'unauthorized', reason: 'auth_required' }, 401);\n\n // Org-scoped: personal (no-org) users have GitHub projects disabled. Report\n // enabled (so the SPA can show the org-required hint) but never connected.\n if (!tenant.orgId) {\n return c.json({\n enabled: true,\n sandboxEnabled: fleet.enabled,\n organizationRequired: true,\n connected: false,\n installations: [],\n reason: 'organization_required',\n diagnostics: diagnostics(),\n });\n }\n\n const rows = options.github\n ? await options.github.sourceControlStorage.installations.list({ orgId: tenant.orgId })\n : [];\n\n const connected = rows.length > 0;\n return c.json({\n enabled: true,\n sandboxEnabled: fleet.enabled,\n connected,\n installations: rows.map(r => ({\n installationId: Number(r.externalId),\n accountLogin: r.accountName,\n accountType: r.accountType,\n })),\n reason: connected ? 'ready' : 'not_connected',\n diagnostics: diagnostics(),\n });\n },\n }),\n );\n\n // Without an integration instance + state signer there is nothing the\n // remaining handlers can do — serve only the disabled `status` route\n // (mirrors the feature gate).\n if (!isGithubFeatureEnabled({ github, auth }) || !github || !stateSigner) {\n return routes;\n }\n const signState = (orgId: string, userId: string): string => stateSigner.sign(orgId, userId);\n const verifyState = (state: string | undefined) => stateSigner.verify(state);\n\n const { runIssueTriage } = options;\n const runBoardIssueTriage = runIssueTriage\n ? async (input: GithubIssueTriageRunInput): Promise<GithubIssueTriageRunResult> => {\n if (!input.resourceId || !input.projectPath) {\n throw new Error('GitHub issue triage requires an explicit Factory project repository');\n }\n await github.addIssueLabels(input.installationId, input.repository, input.issueNumber, ['auto-triaged']);\n return runIssueTriage({\n ...input,\n defaultModelId:\n input.defaultModelId ?? (await resolveFactoryDefaultModelId(options.projects, input.resourceId)),\n labels: input.labels.includes('auto-triaged') ? input.labels : [...input.labels, 'auto-triaged'],\n });\n }\n : undefined;\n\n routes.push(\n registerApiRoute('/web/github/subscriptions', {\n method: 'GET',\n handler: async c => {\n await auth.ensureUser(loose(c));\n const tenant = auth.tenant(loose(c));\n if (!tenant?.orgId) return c.json({ error: 'unauthorized' }, 401);\n\n const resourceId = c.req.query('resourceId');\n const threadId = c.req.query('threadId');\n const sessionScope = c.req.query('scope');\n if (!resourceId || !threadId) return c.json({ error: 'resourceId and threadId are required' }, 400);\n\n const subscriptions = await listPullRequestSubscriptionsForThread(\n {\n orgId: tenant.orgId,\n resourceId,\n threadId,\n sessionScope,\n },\n github.integrationStorage,\n );\n return c.json({\n subscriptions: subscriptions.map(subscription => ({\n id: subscription.id,\n repoFullName: subscription.data.repositorySlug,\n pullRequestNumber: Number(subscription.data.changeRequestId),\n status: subscription.status,\n url: `https://github.com/${subscription.data.repositorySlug}/pull/${subscription.data.changeRequestId}`,\n })),\n });\n },\n }),\n registerApiRoute('/web/github/webhook', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const result = await handleGithubWebhook(loose(c), {\n github,\n runIssueTriage: runBoardIssueTriage,\n ingestFactoryEvent: options.ingestFactoryEvent,\n ...(options.controller\n ? {\n controller: options.controller,\n onTargetError: (subscription, error) => {\n console.warn(\n `[GitHub Webhook] Delivery failed for subscription ${subscription.id} (${subscription.resourceId}/${subscription.threadId}).`,\n error,\n );\n },\n }\n : {}),\n });\n return c.json(result.body, result.status);\n },\n }),\n );\n\n const redirectUri = options.redirectUri ?? `${(options.baseUrl ?? '').replace(/\\/$/, '')}/auth/github/callback`;\n\n // ── Connect: bounce through the OAuth identify flow ─────────────────────\n // Identify-first (rather than install-first) so an app that is *already*\n // installed on the org re-syncs into our DB: GitHub's install page dead-ends\n // on the installation settings screen for existing installs and never\n // redirects back to us. The callback persists whatever installations the\n // verified user token can see, and only redirects to the install URL when\n // there are none.\n //\n // `?manage=1` skips the identify bounce and sends the user straight to\n // GitHub's installation page — used by \"Manage GitHub connection\" to\n // add/remove accounts and repo access. For an already-authorized user the\n // identify flow completes instantly and invisibly, so without this the\n // manage button would appear to do nothing. GitHub's post-install \"Save\"\n // redirect lands back on the callback, which re-syncs installations.\n routes.push(\n registerApiRoute('/auth/github/connect', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const state = signState(resolved.tenant.orgId, resolved.tenant.userId);\n if (c.req.query('manage')) return c.redirect(github.buildInstallUrl(state));\n return c.redirect(github.buildOAuthIdentifyUrl(state, redirectUri));\n },\n }),\n );\n\n // ── Callback: confirm identity, persist the installation against the org ──\n routes.push(\n registerApiRoute('/auth/github/callback', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const { orgId, userId } = resolved.tenant;\n\n const state = c.req.query('state');\n if (!state) {\n // GitHub's \"Save\"/update redirect from the installation settings page\n // arrives with `installation_id` + `setup_action` but no state. We\n // never trust the raw installation_id; start a fresh identify bounce\n // bound to the current session so the update re-syncs installations.\n return c.redirect(github.buildOAuthIdentifyUrl(signState(orgId, userId), redirectUri));\n }\n const stateTenant = verifyState(state);\n if (!stateTenant || stateTenant.userId !== userId || stateTenant.orgId !== orgId) {\n // CSRF / cross-user/org linking protection: the signed state must belong\n // to the same logged-in user *and* their current org.\n console.warn(\n '[GitHub] Install callback rejected: state/tenant mismatch.',\n JSON.stringify({\n stateValid: Boolean(stateTenant),\n stateOrgId: stateTenant?.orgId,\n stateUserId: stateTenant?.userId,\n sessionOrgId: orgId,\n sessionUserId: userId,\n }),\n );\n return c.redirect('/?github=error');\n }\n\n const code = c.req.query('code');\n // We only ever persist installations that GitHub confirms belong to *this*\n // user via the OAuth code path. The raw `installation_id` from the install\n // redirect is not trusted on its own — anyone with a valid state could pass\n // an arbitrary id — so when no code is present we bounce through the OAuth\n // identify flow to obtain a verified user token first.\n if (!code) {\n return c.redirect(github.buildOAuthIdentifyUrl(signState(orgId, userId), redirectUri));\n }\n\n try {\n const userToken = await github.exchangeOAuthCode(code, redirectUri);\n const installations = await github.listUserInstallations(userToken);\n if (installations.length === 0) {\n // Verified user has no installations yet — send them to the actual\n // install page. After installing, GitHub redirects back here with\n // the same state (and no code), which bounces through identify\n // again and lands in the persist path below.\n return c.redirect(github.buildInstallUrl(signState(orgId, userId)));\n }\n for (const inst of installations) {\n // The installation is org-owned; `userId` records who connected it.\n await github.sourceControlStorage.installations.upsert({\n orgId,\n connectedByUserId: userId,\n externalId: inst.installationId.toString(),\n accountName: inst.accountLogin,\n accountType: inst.accountType,\n });\n }\n } catch (error) {\n console.warn(\n `[GitHub] Install callback failed to persist installations for org ${orgId} / user ${userId}.`,\n error,\n );\n return c.redirect('/?github=error');\n }\n\n return c.redirect('/?github=connected');\n },\n }),\n );\n\n // ── List repos across the org's installations ───────────────────────────\n routes.push(\n registerApiRoute('/web/github/repos', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n\n const installs = await github.sourceControlStorage.installations.list({ orgId: resolved.tenant.orgId });\n\n const query = (c.req.query('q') ?? '').toLowerCase();\n const repos = [];\n const seenRepositoryIds = new Set<number>();\n for (const inst of installs) {\n let list;\n try {\n list = await github.listInstallationRepos(Number(inst.externalId));\n } catch (err) {\n // GitHub 404s when the installation no longer exists for this app\n // (app uninstalled/reinstalled, or the row was recorded under\n // different app credentials). Prune the stale row so `/status`\n // reflects reality and the UI prompts a reconnect, then keep\n // listing the remaining installations.\n if ((err as { status?: number }).status !== 404) throw err;\n console.error(`[Mastra Factory] pruning stale GitHub installation ${inst.externalId} (404 from GitHub)`);\n await github.sourceControlStorage.installations.delete({ orgId: resolved.tenant.orgId, id: inst.id });\n continue;\n }\n for (const repo of list) {\n if (query && !repo.fullName.toLowerCase().includes(query)) continue;\n if (seenRepositoryIds.has(repo.id)) continue;\n seenRepositoryIds.add(repo.id);\n const repository = await github.sourceControlStorage.repositories.upsert({\n orgId: resolved.tenant.orgId,\n input: {\n installationId: inst.id,\n externalId: repo.id.toString(),\n slug: repo.fullName,\n defaultBranch: isValidGitRef(repo.defaultBranch) ? repo.defaultBranch : 'main',\n providerMetadata: { private: repo.private, owner: repo.owner },\n },\n });\n repos.push({\n ...repo,\n installationStorageId: inst.id,\n repositoryStorageId: repository.id,\n sandboxProvider: fleet.provider,\n sandboxWorkdir: fleet.computeWorkdir(repo.fullName),\n });\n }\n }\n return c.json({ repos });\n },\n }),\n );\n\n // ── Materialize a project into the caller's per-user sandbox ─────────────\n routes.push(\n registerApiRoute('/web/github/projects/:id/ensure', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const { orgId, userId } = resolved.tenant;\n\n if (!fleet.enabled) {\n return c.json({ error: 'sandbox_not_configured', message: 'No sandbox provider is configured.' }, 503);\n }\n\n const projectRepositoryId = c.req.param('id');\n if (!projectRepositoryId) return c.json({ error: 'Project repository not found' }, 404);\n const project = await resolveProjectRepository({ github, orgId, projectRepositoryId });\n if (!project) {\n return c.json({ error: 'Project repository not found' }, 404);\n }\n\n // Stream live server-side progress when the client asks for it (EventSource\n // / fetch with `Accept: text/event-stream`); otherwise fall back to a single\n // JSON response so non-streaming callers and tests keep working unchanged.\n const wantsStream = (c.req.header('accept') ?? '').includes('text/event-stream');\n if (wantsStream) {\n return streamSSE(loose(c), async stream => {\n try {\n const result = await prepareProject({\n github,\n fleet,\n project,\n userId,\n onProgress: ev => void stream.writeSSE({ event: 'progress', data: JSON.stringify(ev) }),\n });\n await stream.writeSSE({ event: 'done', data: JSON.stringify(result) });\n } catch (err) {\n await stream.writeSSE({ event: 'error', data: JSON.stringify(ensureErrorPayload(err).body) });\n }\n });\n }\n\n try {\n const result = await prepareProject({ github, fleet, project, userId });\n return c.json(result);\n } catch (err) {\n const { status, body } = ensureErrorPayload(err);\n return c.json(body, status);\n }\n },\n }),\n );\n\n // ── List a project's open GitHub issues ──────────────────────────────────\n routes.push(\n registerApiRoute('/web/github/projects/:id/issues', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n const page = parseListPage(c.req.query('page'));\n if (page === null) return c.json({ error: 'invalid_page' }, 400);\n const label = parseIssueLabelFilter(c.req.query('label'));\n if (label === null) return c.json({ error: 'invalid_label' }, 400);\n try {\n const { issues, nextCursor } = await github.intake.listIssues({\n connection: {\n type: 'app-installation',\n installationId: Number(loaded.project.installation.externalId),\n },\n sourceIds: [loaded.project.repository.slug],\n labels: label ? [label] : undefined,\n cursor: String(page),\n });\n const responseIssues = issues.map(issue => ({\n number: Number(issue.id),\n title: issue.title,\n url: issue.url,\n author: issue.author,\n labels: issue.labels,\n comments: issue.commentCount ?? 0,\n createdAt: issue.createdAt,\n updatedAt: issue.updatedAt,\n }));\n await ingestPolledEvents(\n responseIssues.map(issue => polledIssueEvent(loaded.project, issue)),\n options.ingestFactoryEvent,\n );\n return c.json({\n issues: responseIssues,\n nextPage: nextCursor === null ? null : Number(nextCursor),\n });\n } catch (err) {\n return c.json(\n { error: 'github_fetch_failed', message: err instanceof Error ? err.message : String(err) },\n 502,\n );\n }\n },\n }),\n );\n\n // ── Manually run issue triage using the same run seam as webhooks ──\n routes.push(\n registerApiRoute('/web/github/projects/:id/issues/:number/triage', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const owned = await loadOwnedProject({ github, auth, fleet, c: loose(c) });\n if ('response' in owned) return owned.response;\n const { project, sandboxRow } = owned;\n const issueNumber = parseIssueNumberParam(c.req.param('number'));\n if (issueNumber === null) return c.json({ error: 'invalid_issue_number' }, 400);\n\n let body: { title?: unknown; url?: unknown; labels?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (typeof body.title !== 'string' || body.title.trim().length === 0 || body.title.length > 5000) {\n return c.json({ error: 'invalid_title' }, 400);\n }\n if (\n typeof body.url !== 'string' ||\n body.url.trim().length === 0 ||\n body.url.length > 2048 ||\n !isCanonicalGithubIssueUrl(body.url, project.repository.slug, issueNumber)\n ) {\n return c.json({ error: 'invalid_url' }, 400);\n }\n\n if (!runIssueTriage) return c.json({ error: 'triage_unavailable' }, 503);\n const branch = `factory/issue-${issueNumber}`;\n const projectPath = computeWorktreePath(sandboxRow.sandboxWorkdir, branch);\n await github.addIssueLabels(Number(project.installation.externalId), project.repository.slug, issueNumber, [\n 'auto-triaged',\n ]);\n const result = await runIssueTriage({\n repository: project.repository.slug,\n issueNumber,\n issueTitle: body.title,\n issueUrl: body.url,\n labels: parseStringList(body.labels),\n installationId: Number(project.installation.externalId),\n resourceId: project.factoryProjectId,\n projectPath,\n branch,\n defaultModelId: await resolveFactoryDefaultModelId(options.projects, project.factoryProjectId),\n });\n await emitAudit?.({\n context: loose(c),\n input: {\n action: 'factory.triage.started',\n factoryProjectId: project.factoryProjectId,\n projectRepositoryId: project.id,\n targets: [{ type: 'issue', id: String(issueNumber), name: body.title }],\n metadata: { issueNumber, branch, threadId: result.threadId },\n },\n });\n return c.json(\n {\n ok: true,\n threadId: result.threadId,\n projectPath: result.projectPath ?? projectPath,\n branch: result.branch ?? branch,\n },\n 202,\n );\n },\n }),\n );\n\n // ── List a project's open (non-draft) pull requests ─────────────────────\n routes.push(\n registerApiRoute('/web/github/projects/:id/prs', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n const page = parseListPage(c.req.query('page'));\n if (page === null) return c.json({ error: 'invalid_page' }, 400);\n try {\n const { pullRequests, nextCursor } = await github.versionControl.listPullRequests({\n connection: {\n type: 'app-installation',\n installationId: Number(loaded.project.installation.externalId),\n },\n sourceId: loaded.project.repository.slug,\n includeDrafts: false,\n cursor: String(page),\n });\n const responsePullRequests = pullRequests.map(pr => ({\n number: Number(pr.id),\n title: pr.title,\n url: pr.url,\n author: pr.author,\n baseBranch: pr.baseBranch,\n headBranch: pr.headBranch,\n createdAt: pr.createdAt,\n updatedAt: pr.updatedAt,\n }));\n await ingestPolledEvents(\n responsePullRequests.map(pullRequest => polledPullRequestEvent(loaded.project, pullRequest)),\n options.ingestFactoryEvent,\n );\n return c.json({\n pullRequests: responsePullRequests,\n nextPage: nextCursor === null ? null : Number(nextCursor),\n });\n } catch (err) {\n return c.json(\n { error: 'github_fetch_failed', message: err instanceof Error ? err.message : String(err) },\n 502,\n );\n }\n },\n }),\n );\n\n // ── Read per-project settings ────────────────────────────────────────────\n routes.push(\n registerApiRoute('/web/github/projects/:id/settings', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n return c.json({ setupCommand: loaded.project.setupCommand });\n },\n }),\n );\n\n // ── Update per-project settings ──────────────────────────────────────────\n routes.push(\n registerApiRoute('/web/github/projects/:id/settings', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const loaded = await loadOrgProject({ github, auth, c: loose(c) });\n if ('response' in loaded) return loaded.response;\n\n let body: { setupCommand?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (body.setupCommand !== null && typeof body.setupCommand !== 'string') {\n return c.json({ error: 'Invalid setupCommand' }, 400);\n }\n if (typeof body.setupCommand === 'string' && body.setupCommand.length > 2000) {\n return c.json({ error: 'setupCommand too long (max 2000 characters)' }, 400);\n }\n // Reject control characters (except newline/tab). The command is a\n // shell script by design, but escape sequences and NULs have no\n // legitimate use and can spoof logs or confuse the sandbox shell.\n if (typeof body.setupCommand === 'string' && /[\\0-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]/.test(body.setupCommand)) {\n return c.json({ error: 'setupCommand contains control characters' }, 400);\n }\n // An empty/whitespace command means \"no setup step\".\n const setupCommand =\n typeof body.setupCommand === 'string' && body.setupCommand.trim().length > 0\n ? body.setupCommand.trim()\n : null;\n\n await github.sourceControlStorage.projectRepositories.update({\n orgId: loaded.project.installation.orgId,\n id: loaded.project.id,\n input: { setupCommand },\n });\n return c.json({ setupCommand });\n },\n }),\n );\n\n // ── Org GitHub PATs ──────────────────────────────────────────────────────\n // Installation tokens are the wrong credential for the `gh` CLI (integration\n // -restricted endpoints 403 regardless of permissions), so orgs paste\n // classic PATs the sandboxes use instead: a `default` worker token, and an\n // optional `reviewer` token that review-board sessions use so PR reviews\n // come from a different account. Tokens are never sent back to the browser —\n // only whether each is configured.\n const parsePatKind = (value: unknown): GithubPatKind | null => {\n if (value === undefined || value === null || value === 'default') return 'default';\n if (value === 'reviewer') return 'reviewer';\n return null;\n };\n routes.push(\n registerApiRoute('/web/github/pat', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n return c.json(await getGithubPatStatus(() => github.integrationStorage, resolved.tenant.orgId));\n },\n }),\n registerApiRoute('/web/github/pat', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n\n let body: { token?: unknown; kind?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n const kind = parsePatKind(body.kind);\n if (!kind) return c.json({ error: \"kind must be 'default' or 'reviewer'\" }, 400);\n const token = typeof body.token === 'string' ? body.token.trim() : '';\n if (!token) return c.json({ error: 'A token is required' }, 400);\n if (token.length > 500) return c.json({ error: 'Token too long (max 500 characters)' }, 400);\n if (/\\s/.test(token)) return c.json({ error: 'Token must not contain whitespace' }, 400);\n\n await setGithubPat(github.integrationStorage, resolved.tenant.orgId, token, kind);\n return c.json(await getGithubPatStatus(() => github.integrationStorage, resolved.tenant.orgId));\n },\n }),\n registerApiRoute('/web/github/pat', {\n method: 'DELETE',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const kind = parsePatKind(c.req.query('kind'));\n if (!kind) return c.json({ error: \"kind must be 'default' or 'reviewer'\" }, 400);\n await clearGithubPat(github.integrationStorage, resolved.tenant.orgId, kind);\n return c.json(await getGithubPatStatus(() => github.integrationStorage, resolved.tenant.orgId));\n },\n }),\n );\n\n // ── Sessions / commit / push / PR ────────────────────────────────────────\n routes.push(...buildProjectGitRoutes({ github, auth, fleet, storage, emitAudit }));\n\n return routes;\n}\n\n/**\n * Load the org-owned project for a read-only GitHub API route. Unlike\n * `loadOwnedProject`, this never touches sandbox state — the issues/PR list\n * routes only need the repo + installation, so they work before a sandbox is\n * ever provisioned.\n */\nasync function loadOrgProject(options: {\n github: GithubIntegration;\n auth: RouteAuth;\n c: RouteContext;\n}): Promise<{ project: ResolvedProjectRepository; userId: string } | { response: Response }> {\n const { github, auth, c } = options;\n const resolved = await resolveOrgTenant(c, auth);\n if ('response' in resolved) return { response: resolved.response };\n const { orgId, userId } = resolved.tenant;\n\n const projectRepositoryId = c.req.param('id');\n if (!projectRepositoryId) {\n return { response: c.json({ error: 'Project repository not found' }, 404) };\n }\n const project = await resolveProjectRepository({ github, orgId, projectRepositoryId });\n if (!project) {\n return { response: c.json({ error: 'Project repository not found' }, 404) };\n }\n return { project, userId };\n}\n\n/** Derive a commit/author identity from the authenticated host user. */\nfunction identityFromUser(user: unknown): GitIdentity {\n const u = user as { name?: string; email?: string } | null | undefined;\n return { name: u?.name ?? null, email: u?.email ?? null };\n}\n\n/**\n * Resolve a live, started sandbox for the caller's per-user sandbox binding. The\n * sandbox must already have been provisioned (`sandboxId` set) — the git write\n * routes never clone, they operate on the existing checkout.\n */\nasync function resolveProjectSandbox(options: {\n fleet: SandboxFleet;\n sandboxRow: ProjectRepositorySandbox;\n}): Promise<MaterializationSandbox> {\n const { fleet, sandboxRow } = options;\n if (!sandboxRow.sandboxId) {\n throw new MaterializeError('Project sandbox is not provisioned. Open the project first.', 'clone-failed');\n }\n return fleet.reattachSandbox(sandboxRow.sandboxId);\n}\n\n/**\n * Load (or create) the caller's per-(project,user) sandbox binding row. The\n * binding inherits its workdir from the org-owned project, but `sandboxId` /\n * `materializedAt` stay null until the user first opens the project.\n */\nasync function loadOrCreateSandboxRow(\n github: GithubIntegration,\n project: ResolvedProjectRepository,\n userId: string,\n): Promise<ProjectRepositorySandbox> {\n return github.sourceControlStorage.sandboxes.getOrCreate({ projectRepository: project, userId });\n}\n\ninterface EnsureResult {\n resourceId: string;\n factoryProjectId: string;\n projectRepositoryId: string;\n sandboxId: string | null;\n sandboxWorkdir: string;\n}\n\n/**\n * Provision/reattach the caller's sandbox and materialize the repo into it,\n * emitting coarse progress events as each server step happens. Shared by both\n * the JSON and SSE variants of the `/ensure` route. Throws on failure so the\n * caller can shape the response (HTTP status vs SSE `error` event).\n */\nasync function prepareProject(options: {\n github: GithubIntegration;\n fleet: SandboxFleet;\n project: ResolvedProjectRepository;\n userId: string;\n onProgress?: ProgressFn;\n}): Promise<EnsureResult> {\n const { github, fleet, project, userId, onProgress } = options;\n const sandboxRow = await loadOrCreateSandboxRow(github, project, userId);\n const access = await github.versionControl.getRepositoryAccess({\n orgId: project.installation.orgId,\n repositoryId: project.repository.id,\n });\n if (!access.authorization) {\n throw new MaterializeError('Repository access did not include a bearer token.', 'clone-failed');\n }\n // The sandbox env token feeds the `gh` CLI — a configured org PAT wins\n // there. Git clone/pull below keep the minted installation token.\n const ghCliToken =\n (await getGithubPat(() => github.integrationStorage, project.installation.orgId)) ?? access.authorization.token;\n const sandbox = await ensureProjectSandbox({\n fleet,\n row: sandboxRow,\n storage: github.sourceControlStorage.sandboxes,\n token: ghCliToken,\n onProgress,\n });\n // Re-read the sandbox binding so we have the freshly persisted sandboxId.\n const fresh = await github.sourceControlStorage.sandboxes.getById({ id: sandboxRow.id });\n const finalRow = fresh ?? sandboxRow;\n await materializeRepo({\n row: finalRow,\n repoInfo: { repoFullName: project.repository.slug, defaultBranch: project.defaultBranch },\n sandbox,\n token: access.authorization.token,\n storage: github.sourceControlStorage.sandboxes,\n onProgress,\n });\n const result: EnsureResult = {\n resourceId: project.factoryProjectId,\n factoryProjectId: project.factoryProjectId,\n projectRepositoryId: project.id,\n sandboxId: finalRow.sandboxId,\n sandboxWorkdir: finalRow.sandboxWorkdir,\n };\n const done: PrepareProgress = { phase: 'done', message: 'Workspace ready.' };\n onProgress?.(done);\n return result;\n}\n\n/** Shape an /ensure failure into an HTTP status + JSON body (also used as the SSE error payload). */\nfunction ensureErrorPayload(err: unknown): {\n status: 429 | 502 | 500;\n body: { error: string; message: string };\n} {\n if (err instanceof SandboxBudgetError) {\n return { status: 429, body: { error: err.code, message: err.message } };\n }\n if (err instanceof MaterializeError) {\n return { status: 502, body: { error: err.code, message: err.message } };\n }\n return {\n status: 500,\n body: { error: 'materialize_failed', message: err instanceof Error ? err.message : String(err) },\n };\n}\n\n/** Map a sandbox/worktree error to an actionable HTTP response. */\nfunction gitErrorResponse(c: Context, err: unknown) {\n if (err instanceof WorktreeError) {\n return c.json({ error: err.code, message: err.message }, err.code === 'invalid-branch' ? 400 : 502);\n }\n if (err instanceof MaterializeError) {\n return c.json({ error: err.code, message: err.message }, 502);\n }\n return c.json({ error: 'git_failed', message: err instanceof Error ? err.message : String(err) }, 500);\n}\n\n/**\n * Load the org-owned project and the caller's per-user sandbox binding for a git\n * route. Centralizes the auth + org/ownership checks every git route shares:\n * the project is scoped by `(id, orgId)`, the sandbox binding by\n * `(projectRepositoryId, userId)`. Returns the tenant, project, and sandbox row, or\n * a ready-to-return error response.\n */\nasync function loadOwnedProject(options: {\n github: GithubIntegration;\n auth: RouteAuth;\n fleet: SandboxFleet;\n c: RouteContext;\n}): Promise<\n | { orgId: string; userId: string; project: ResolvedProjectRepository; sandboxRow: ProjectRepositorySandbox }\n | { response: Response }\n> {\n const { github, auth, fleet, c } = options;\n const resolved = await resolveOrgTenant(c, auth);\n if ('response' in resolved) return { response: resolved.response };\n const { orgId, userId } = resolved.tenant;\n\n if (!fleet.enabled) {\n return {\n response: c.json({ error: 'sandbox_not_configured', message: 'No sandbox provider is configured.' }, 503),\n };\n }\n\n const projectRepositoryId = c.req.param('id');\n if (!projectRepositoryId) {\n return { response: c.json({ error: 'Project repository not found' }, 404) };\n }\n const project = await resolveProjectRepository({ github, orgId, projectRepositoryId });\n if (!project) {\n return { response: c.json({ error: 'Project repository not found' }, 404) };\n }\n const sandboxRow = await loadOrCreateSandboxRow(github, project, userId);\n return { orgId, userId, project, sandboxRow };\n}\n\nfunction buildProjectGitRoutes({\n github,\n auth,\n fleet,\n storage,\n emitAudit,\n}: {\n github: GithubIntegration;\n auth: RouteAuth;\n fleet: SandboxFleet;\n storage?: FactoryStorage;\n emitAudit?: AuditEmitter['emit'];\n}): ApiRoute[] {\n return [\n // ── Create / list Factory sessions ──────────────────────────────────────\n registerApiRoute('/web/github/projects/:id/sessions', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const { orgId, userId } = resolved.tenant;\n const projectRepositoryId = c.req.param('id');\n const project = projectRepositoryId\n ? await resolveProjectRepository({ github, orgId, projectRepositoryId })\n : null;\n if (!project) return c.json({ error: 'Project repository not found' }, 404);\n const sessions = await github.sourceControlStorage.sessions.list({ projectRepositoryId: project.id, userId });\n return c.json({ sessions });\n },\n }),\n registerApiRoute('/web/github/projects/:id/sessions', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const { orgId, userId } = resolved.tenant;\n const projectRepositoryId = c.req.param('id');\n const project = projectRepositoryId\n ? await resolveProjectRepository({ github, orgId, projectRepositoryId })\n : null;\n if (!project) return c.json({ error: 'Project repository not found' }, 404);\n let body: { branch?: unknown; baseBranch?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (!isValidGitRefSandbox(body.branch)) return c.json({ error: 'Invalid branch' }, 400);\n const baseBranch = body.baseBranch === undefined ? project.defaultBranch : body.baseBranch;\n if (!isValidGitRefSandbox(baseBranch)) return c.json({ error: 'Invalid baseBranch' }, 400);\n const session = await github.sourceControlStorage.sessions.create({\n sessionId: randomUUID(),\n projectRepositoryId: project.id,\n orgId,\n userId,\n branch: body.branch,\n baseBranch,\n });\n return c.json({ session });\n },\n }),\n registerApiRoute('/web/user-sessions/:sessionId', {\n method: 'GET',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const session = await github.sourceControlStorage.sessions.getBySessionId(c.req.param('sessionId'));\n if (!session || session.orgId !== resolved.tenant.orgId || session.userId !== resolved.tenant.userId) {\n return c.json({ error: 'Session not found' }, 404);\n }\n return c.json({ session });\n },\n }),\n registerApiRoute('/web/user-sessions/:sessionId', {\n method: 'DELETE',\n requiresAuth: false,\n handler: async c => {\n const resolved = await resolveOrgTenant(loose(c), auth);\n if ('response' in resolved) return resolved.response;\n const session = await github.sourceControlStorage.sessions.getBySessionId(c.req.param('sessionId'));\n if (!session || session.orgId !== resolved.tenant.orgId || session.userId !== resolved.tenant.userId) {\n return c.json({ error: 'Session not found' }, 404);\n }\n let sandbox: MaterializationSandbox | undefined;\n if (session.sandboxId) {\n try {\n sandbox = await fleet.reattachSandbox(session.sandboxId);\n } catch {\n // The provider may already have reclaimed the sandbox.\n }\n await fleet.teardownSandbox(\n {\n sandboxId: session.sandboxId,\n setSandboxId: async () => {},\n clear: async () => {\n await github.sourceControlStorage.sessions.setSandbox({\n id: session.id,\n sandboxId: null,\n sandboxWorkdir: session.sandboxWorkdir ?? '',\n });\n },\n },\n sandbox,\n );\n }\n await github.sourceControlStorage.sessions.delete(session.id);\n return c.json({ removed: true });\n },\n }),\n\n // ── Stage all + commit inside a Factory session workspace ──────────────\n registerApiRoute('/web/github/projects/:id/commit', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const owned = await loadOwnedProject({ github, auth, fleet, c: loose(c) });\n if ('response' in owned) return owned.response;\n const { userId, project } = owned;\n\n let body: { message?: unknown; sessionId?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (typeof body.message !== 'string' || body.message.trim().length === 0 || body.message.length > 5000) {\n return c.json({ error: 'Invalid message' }, 400);\n }\n const sessionWorkspace = await resolveSessionWorkspace(github, project.id, userId, body.sessionId);\n if (!sessionWorkspace) {\n return c.json({ error: 'Invalid sessionId' }, 400);\n }\n const { workdir, sandboxBinding } = sessionWorkspace;\n\n try {\n return await withProjectLock({\n key: `${project.id}:${userId}`,\n storage,\n fn: async () => {\n const sandbox = await resolveProjectSandbox({ fleet, sandboxRow: sandboxBinding });\n const result = await commitAll(\n sandbox,\n workdir,\n body.message as string,\n identityFromUser(await auth.ensureUser(loose(c))),\n );\n if (result.committed) {\n await emitAudit?.({\n context: loose(c),\n input: {\n action: 'factory.git.commit',\n factoryProjectId: project.factoryProjectId,\n projectRepositoryId: project.id,\n targets: [{ type: 'session', id: sessionWorkspace.session.sessionId }],\n metadata: { sessionId: sessionWorkspace.session.sessionId },\n },\n });\n }\n return c.json({ committed: result.committed });\n },\n });\n } catch (err) {\n return gitErrorResponse(loose(c), err);\n }\n },\n }),\n\n // ── Push a branch back to GitHub ────────────────────────────────────────\n registerApiRoute('/web/github/projects/:id/push', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const owned = await loadOwnedProject({ github, auth, fleet, c: loose(c) });\n if ('response' in owned) return owned.response;\n const { orgId, userId, project } = owned;\n\n let body: { branch?: unknown; sessionId?: unknown };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (!isValidGitRefSandbox(body.branch)) {\n return c.json({ error: 'Invalid branch' }, 400);\n }\n const branch = body.branch;\n const sessionWorkspace = await resolveSessionWorkspace(github, project.id, userId, body.sessionId);\n if (!sessionWorkspace) {\n return c.json({ error: 'Invalid sessionId' }, 400);\n }\n const { workdir, sandboxBinding } = sessionWorkspace;\n\n try {\n return await withProjectLock({\n key: `${project.id}:${userId}`,\n storage,\n fn: async () => {\n const sandbox = await resolveProjectSandbox({ fleet, sandboxRow: sandboxBinding });\n const access = await github.versionControl.getRepositoryAccess({\n orgId,\n repositoryId: project.repository.id,\n });\n if (!access.authorization) throw new Error('Repository access did not include a bearer token.');\n await pushBranch(sandbox, workdir, branch, access.authorization.token, project.repository.slug);\n await emitAudit?.({\n context: loose(c),\n input: {\n action: 'factory.git.push',\n factoryProjectId: project.factoryProjectId,\n projectRepositoryId: project.id,\n targets: [{ type: 'branch', id: branch }],\n metadata: { branch, sessionId: sessionWorkspace.session.sessionId },\n },\n });\n return c.json({ pushed: true, branch });\n },\n });\n } catch (err) {\n return gitErrorResponse(loose(c), err);\n }\n },\n }),\n\n // ── Open a pull request through the version-control capability ─────────\n registerApiRoute('/web/github/projects/:id/pr', {\n method: 'POST',\n requiresAuth: false,\n handler: async c => {\n const owned = await loadOwnedProject({ github, auth, fleet, c: loose(c) });\n if ('response' in owned) return owned.response;\n const { orgId, userId, project } = owned;\n\n let body: {\n branch?: unknown;\n base?: unknown;\n title?: unknown;\n body?: unknown;\n sessionId?: unknown;\n };\n try {\n body = await c.req.json();\n } catch {\n return c.json({ error: 'Invalid JSON body' }, 400);\n }\n if (!isValidGitRefSandbox(body.branch)) {\n return c.json({ error: 'Invalid branch' }, 400);\n }\n const base = body.base === undefined ? project.defaultBranch : body.base;\n if (!isValidGitRefSandbox(base)) {\n return c.json({ error: 'Invalid base' }, 400);\n }\n if (typeof body.title !== 'string' || body.title.trim().length === 0 || body.title.length > 256) {\n return c.json({ error: 'Invalid title' }, 400);\n }\n if (body.body !== undefined && (typeof body.body !== 'string' || body.body.length > 65536)) {\n return c.json({ error: 'Invalid body' }, 400);\n }\n const head = body.branch;\n const title = body.title;\n const prBody = body.body as string | undefined;\n const sessionWorkspace = await resolveSessionWorkspace(github, project.id, userId, body.sessionId);\n if (!sessionWorkspace) {\n return c.json({ error: 'Invalid sessionId' }, 400);\n }\n\n try {\n return await withProjectLock({\n key: `${project.id}:${userId}`,\n storage,\n fn: async () => {\n const result = await github.versionControl.createPullRequest({\n connection: {\n type: 'app-installation',\n installationId: Number(project.installation.externalId),\n },\n sourceId: project.repository.slug,\n baseBranch: base,\n headBranch: head,\n title,\n body: prBody,\n actingUserId: userId,\n });\n await emitAudit?.({\n context: loose(c),\n input: {\n action: 'factory.git.pr_opened',\n factoryProjectId: project.factoryProjectId,\n projectRepositoryId: project.id,\n targets: [{ type: 'pull_request', id: result.url, name: title }],\n metadata: { branch: head, base, url: result.url },\n },\n });\n const pullRequestNumber = pullRequestNumberFromUrl(result.url, project.repository.slug);\n if (pullRequestNumber) {\n const sessionId = sessionWorkspace.session.sessionId;\n await subscribeToPullRequest(\n {\n orgId,\n installationExternalId: project.installation.externalId,\n projectRepositoryId: project.id,\n repositoryExternalId: project.repository.externalId,\n repositorySlug: project.repository.slug,\n changeRequestId: pullRequestNumber.toString(),\n sessionId,\n ownerId: userId,\n resourceId: sessionId,\n threadId: sessionId,\n source: 'factory-pr-create',\n subscribedByUserId: userId,\n },\n github.integrationStorage,\n ).catch((error: unknown) => {\n console.warn(\n `[GitHub] Pull request ${result.url} was created but automatic subscription failed.`,\n error,\n );\n });\n }\n return c.json({ url: result.url });\n },\n });\n } catch (err) {\n return c.json(\n { error: 'github_pr_create_failed', message: err instanceof Error ? err.message : String(err) },\n 502,\n );\n }\n },\n }),\n\n // ── Tear down the caller's sandbox for a project ────────────────────────\n // Per-user teardown only: drops the caller's `(project, user)` sandbox\n // binding and stops the VM, freeing a slot in the per-replica budget. Project\n // deletion at the org level is out of scope (org admin model is later).\n registerApiRoute('/web/github/projects/:id/sandbox', {\n method: 'DELETE',\n requiresAuth: false,\n handler: async c => {\n const owned = await loadOwnedProject({ github, auth, fleet, c: loose(c) });\n if ('response' in owned) return owned.response;\n const { userId, project, sandboxRow } = owned;\n\n if (!sandboxRow.sandboxId) {\n // Nothing provisioned for this user — idempotent success.\n return c.json({ tornDown: false });\n }\n\n try {\n return await withProjectLock({\n key: `${project.id}:${userId}`,\n storage,\n fn: async () => {\n const sandbox = await fleet.reattachSandbox(sandboxRow.sandboxId!);\n await teardownProjectSandbox({\n fleet,\n row: sandboxRow,\n storage: github.sourceControlStorage.sandboxes,\n sandbox,\n });\n return c.json({ tornDown: true });\n },\n });\n } catch (err) {\n return gitErrorResponse(loose(c), err);\n }\n },\n }),\n ];\n}\n\n/** Resolve the materialized workspace owned by a Factory session. */\nasync function resolveSessionWorkspace(\n github: GithubIntegration,\n projectId: string,\n userId: string,\n sessionId: unknown,\n) {\n if (typeof sessionId !== 'string') {\n return undefined;\n }\n const session = await github.sourceControlStorage.sessions.getBySessionId(sessionId);\n if (\n session?.projectRepositoryId !== projectId ||\n session.userId !== userId ||\n !session.sandboxId ||\n !session.sandboxWorkdir\n ) {\n return undefined;\n }\n return {\n session,\n workdir: session.sandboxWorkdir,\n sandboxBinding: {\n id: session.id,\n projectRepositoryId: session.projectRepositoryId,\n userId: session.userId,\n sandboxId: session.sandboxId,\n sandboxWorkdir: session.sandboxWorkdir,\n materializedAt: session.materializedAt,\n createdAt: session.createdAt,\n },\n };\n}\n","/**\n * Project sandbox fleet: provisioning, reattach, teardown, and budgeting.\n *\n * Server-hosted projects never run on the web host itself. Each project gets\n * its own isolated sandbox (a `WorkspaceSandbox`, e.g. a Railway VM) `clone()`d\n * from the machine the factory was configured with. This module owns everything\n * about that fleet — which provider is active, where checkouts live inside a\n * sandbox, the idle window, the per-replica budget, and the\n * provision/reattach/teardown lifecycle — but knows nothing about what runs\n * inside a sandbox (git materialization lives with its feature, e.g. the\n * GitHub integration's `sandbox.ts`).\n *\n * The fleet is constructed once at boot with the machine config (or none, when\n * sandboxes are disabled) and handed to consumers — no global registry.\n * Persistence of the provider's reattach id is delegated to the caller via\n * {@link SandboxBindingStore}, so the fleet stays storage-agnostic. Tests can\n * swap the low-level construction via {@link SandboxFleet.setFactory}.\n */\n\nimport path from 'node:path';\n\nimport type { WorkspaceSandbox } from '@mastra/core/workspace';\n\n/** Minimal command result shape sandbox consumers depend on. */\nexport interface SandboxCommandResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n}\n\n/**\n * Minimal live-sandbox surface fleet consumers need: an id, a way to start it,\n * a way to learn the provider's reattach id, and command execution.\n */\nexport interface MaterializationSandbox {\n readonly id: string;\n start(): Promise<void>;\n getInfo(): Promise<{ metadata?: Record<string, unknown> }>;\n executeCommand(\n command: string,\n args?: string[],\n options?: { timeout?: number; env?: Record<string, string | undefined> },\n ): Promise<SandboxCommandResult>;\n /** Update an environment variable for future commands in this sandbox. */\n setEnvironmentVariable?(name: string, value: string): void;\n /** Tear down the underlying VM. Optional: providers without it are no-ops. */\n stop?(): Promise<void>;\n}\n\n/** Options for building (or reattaching) one sandbox. */\nexport interface SandboxCreateOptions {\n /** Reattach to this existing provider VM instead of provisioning a new one. */\n providerSandboxId?: string;\n /** Environment variables baked into the sandbox. */\n env?: Record<string, string>;\n /** Provider working directory for this sandbox. */\n workingDirectory?: string;\n /** Idle teardown window (minutes). The provider stops the VM after this idle period. */\n idleTimeoutMinutes?: number;\n /** Provider checkpoint used to seed and preserve this sandbox's filesystem. */\n checkpointName?: string;\n}\n\n/**\n * A coarse-grained step of the sandbox-preparation flow, reported as it happens\n * so the UI can show the user what the server is doing instead of a static\n * \"Preparing…\" toast. `phase` is a stable machine token; `message` is\n * user-facing copy.\n */\nexport interface PrepareProgress {\n phase: 'reattaching' | 'provisioning' | 'preparing-workspace' | 'cloning' | 'pulling' | 'finalizing' | 'done';\n message: string;\n}\n\n/** Callback invoked with each preparation step. Best-effort; never throws. */\nexport type ProgressFn = (event: PrepareProgress) => void;\n\n/** Invoke a progress callback without letting it break the actual work. */\nexport function reportProgress(onProgress: ProgressFn | undefined, event: PrepareProgress): void {\n if (!onProgress) return;\n try {\n onProgress(event);\n } catch {\n // Progress reporting must never break the actual work.\n }\n}\n\n/**\n * Factory that builds a (not-yet-started) sandbox. When `providerSandboxId` is\n * provided the sandbox should reattach to that existing VM instead of\n * provisioning a new one.\n */\nexport type SandboxFactory = (opts: SandboxCreateOptions) => MaterializationSandbox;\n\n/** Raised when provisioning would exceed the per-replica sandbox budget. */\nexport class SandboxBudgetError extends Error {\n readonly code = 'sandbox-budget-exceeded' as const;\n constructor(readonly max: number) {\n super(\n `Sandbox budget exceeded: this server already has ${max} active sandbox(es), ` +\n `the configured per-replica maximum. Close an existing repository's sandbox and try again.`,\n );\n this.name = 'SandboxBudgetError';\n }\n}\n\n/** Optional knobs for provisioning/reattaching one sandbox. */\nexport interface EnsureSandboxOptions {\n /** Provider working directory for this sandbox. */\n workingDirectory?: string;\n}\n\n/**\n * Where a feature persists its sandbox binding. The fleet reads the stored\n * reattach id and writes updates through this seam so it stays agnostic of\n * the owning table (GitHub projects today, anything else tomorrow).\n */\nexport interface SandboxBindingStore {\n /** Stored provider reattach id from a previous provisioning, if any. */\n readonly sandboxId: string | null;\n /** Provider checkpoint used to seed and preserve this sandbox's filesystem. */\n readonly checkpointName?: string;\n /** Persist a freshly provisioned provider id, or clear a stale one with `null`. */\n setSandboxId(id: string | null): Promise<void>;\n /** Clear all stored sandbox state (reattach id + materialization mark) on teardown. */\n clear(): Promise<void>;\n}\n\n/**\n * Adapt a cloned `WorkspaceSandbox` to the minimal surface this module needs.\n * Lifecycle goes through the `_`-prefixed wrappers when present (they add\n * status tracking and concurrency safety on `MastraSandbox` subclasses),\n * falling back to the plain methods for interface-only implementations.\n */\nfunction toMaterializationSandbox(\n sandbox: WorkspaceSandbox,\n initialEnvironment: Record<string, string> = {},\n): MaterializationSandbox {\n if (typeof sandbox.executeCommand !== 'function') {\n throw new Error(\n `Sandbox provider '${sandbox.provider}' does not implement executeCommand() — cannot materialize repos.`,\n );\n }\n const lifecycle = sandbox as { _start?(): Promise<void>; _stop?(): Promise<void> };\n const environment = { ...initialEnvironment };\n return {\n id: sandbox.id,\n start: async () => {\n await (lifecycle._start ?? sandbox.start)?.call(sandbox);\n },\n getInfo: async () => (await sandbox.getInfo?.()) ?? {},\n executeCommand: (command, args, options) =>\n sandbox.executeCommand!(command, args, {\n ...options,\n env: { ...environment, ...options?.env },\n }),\n setEnvironmentVariable: (name, value) => {\n environment[name] = value;\n },\n stop: async () => {\n await (lifecycle._stop ?? sandbox.stop)?.call(sandbox);\n },\n };\n}\n\n/**\n * The provider's reattach id for a started sandbox. For Railway this is the\n * underlying `railwaySandboxId` in `getInfo().metadata`. Providers without a\n * provider-native id (e.g. local) reattach by construction id, so fall back\n * to the sandbox's own logical id.\n */\nasync function readProviderSandboxId(sandbox: MaterializationSandbox): Promise<string | undefined> {\n const info = await sandbox.getInfo();\n const id = info.metadata?.railwaySandboxId ?? info.metadata?.sandboxId;\n return typeof id === 'string' ? id : sandbox.id;\n}\n\n/** Keep each path piece a single safe segment (no separators or traversal). */\nfunction sanitizeSegment(segment: string): string {\n const cleaned = segment.replace(/[^A-Za-z0-9._-]/g, '-').replace(/^\\.+/, '');\n return cleaned || 'repo';\n}\n\n/** Resolve a workdir under `root`, refusing any path that escapes the configured root. */\nexport function resolveContainedLocalWorkdir(root: string, ...segments: string[]): string {\n const resolvedRoot = path.resolve(root);\n const resolved = path.resolve(resolvedRoot, ...segments);\n if (resolved !== resolvedRoot && resolved.startsWith(`${resolvedRoot}${path.sep}`)) return resolved;\n throw new Error(`Refusing to use local sandbox path outside configured root: ${resolved}`);\n}\n\n/**\n * Factory-resolved sandbox runtime the fleet is constructed with: the machine\n * projects clone their per-project sandboxes from, plus the knobs the factory\n * resolved around it.\n */\nexport interface SandboxFleetConfig {\n /**\n * Template machine (validated by the factory to implement `clone()`).\n * Never started — acts purely as the credential/default holder that\n * per-project sandboxes are cloned from.\n */\n machine: WorkspaceSandbox;\n /** In-sandbox base directory repos check out under (no trailing slash). */\n workdirBase: string;\n /** Per-replica cap on concurrently provisioned sandboxes. 0 = unlimited. */\n maxSandboxes?: number;\n}\n\n/**\n * The sandbox fleet for one deployment. Constructed once at boot — with a\n * config when a sandbox machine was configured, or without one when sandboxes\n * are disabled (every provisioning entry point then throws and\n * {@link enabled} reports `false` so features stay off).\n */\nexport class SandboxFleet {\n readonly #config: SandboxFleetConfig | undefined;\n #factory: SandboxFactory | undefined;\n #liveCount = 0;\n\n constructor(config?: SandboxFleetConfig) {\n this.#config = config;\n }\n\n /**\n * True when a sandbox machine was configured. The factory validates the\n * machine implements `clone()` at boot, so a configured fleet is usable —\n * sandbox-backed projects stay off only when the slot was omitted.\n */\n get enabled(): boolean {\n return this.#config !== undefined;\n }\n\n /**\n * Name of the active sandbox provider — the configured machine's `provider`\n * discriminator (`'railway'`, `'local'`, …), or `'none'` when the fleet was\n * constructed without a config. Diagnostic only; feature gating goes\n * through {@link enabled}.\n */\n get provider(): string {\n return this.#config?.machine.provider ?? 'none';\n }\n\n /**\n * Idle teardown window for provisioned sandboxes, in minutes; defaults to 30.\n * Read back from the machine's own config when it exposes one\n * (Railway's `idleTimeoutMinutes`) — the knob lives on the sandbox, the\n * fleet only needs it to schedule GC and stamp sandbox clones. Advisory:\n * providers without idle GC ignore it, and a re-open detects a torn-down VM\n * and re-provisions cleanly.\n */\n get idleMinutes(): number {\n const machine = this.#config?.machine as { idleTimeoutMinutes?: unknown } | undefined;\n const minutes = machine?.idleTimeoutMinutes;\n return typeof minutes === 'number' && Number.isFinite(minutes) && minutes > 0 ? minutes : 30;\n }\n\n /**\n * Per-replica cap on concurrently *provisioned* sandboxes. 0 means unlimited.\n * This is a lightweight per-process budget to keep a single replica from\n * exhausting provider quota — it is not a global, cross-replica scheduler\n * (that is a deferred follow-up).\n */\n get maxSandboxes(): number {\n return this.#config?.maxSandboxes ?? 0;\n }\n\n /**\n * Count of sandboxes this fleet has freshly provisioned and not yet torn\n * down. Reattaches to existing VMs do not count (they reuse an already-billed\n * sandbox). Used to enforce {@link maxSandboxes}.\n */\n get liveCount(): number {\n return this.#liveCount;\n }\n\n /** For tests: reset the live-sandbox counter to a known state. */\n __resetLiveCount(value = 0): void {\n this.#liveCount = value;\n }\n\n /** Override the sandbox factory (tests). */\n setFactory(factory: SandboxFactory): void {\n this.#factory = factory;\n }\n\n /** Reset to the default machine-cloning factory. */\n resetFactory(): void {\n this.#factory = undefined;\n }\n\n /**\n * Compute the in-sandbox working directory for a repo: a nested\n * `<base>/<owner>/<name>` layout under the factory-resolved checkout base.\n * Nesting keeps same-name repos apart (`acme/api` vs `other/api`) — cloud\n * sandboxes are one-per-project so it's merely tidy there, but local\n * checkouts share one host root where it prevents collisions. Server-side\n * only; never derived from client input.\n */\n computeWorkdir(repoFullName: string): string {\n if (!this.#config) throw new Error('No sandbox configured');\n const [owner, name] = repoFullName.split('/', 2);\n return `${this.#config.workdirBase}/${sanitizeSegment(owner || 'unknown')}/${sanitizeSegment(name || 'repo')}`;\n }\n\n /**\n * Compute the host working directory for a local GitHub session checkout.\n * This is server-derived only: repo pieces are sanitized and the trusted\n * session id is kept as a single path segment under the configured local root.\n */\n computeLocalSessionWorkdir(repoFullName: string, sessionId: string): string {\n if (!this.#config) throw new Error('No sandbox configured');\n if (this.#config.machine.provider !== 'local') {\n throw new Error('Local session workdirs require the local sandbox provider');\n }\n\n const localRoot = (this.#config.machine as { workingDirectory?: unknown }).workingDirectory;\n if (typeof localRoot !== 'string' || localRoot.length === 0) {\n throw new Error('Local sandbox working directory is not configured');\n }\n\n const [owner, name] = repoFullName.split('/', 2);\n return resolveContainedLocalWorkdir(\n localRoot,\n 'github-sessions',\n sanitizeSegment(owner || 'unknown'),\n sanitizeSegment(name || 'repo'),\n sanitizeSegment(sessionId),\n );\n }\n\n /**\n * Build a (not-yet-started) sandbox: the test-provided factory when set,\n * otherwise a per-project clone of the configured machine. The stored id is\n * passed both as the logical `id` (providers that reattach by construction\n * id, e.g. local) and as the provider-native `sandboxId` hint (Railway) so\n * reattach works across the provider matrix.\n */\n #build(opts: SandboxCreateOptions): MaterializationSandbox {\n if (this.#factory) return this.#factory(opts);\n if (!this.#config) throw new Error('No sandbox configured');\n const clone = this.#config.machine.clone!({\n ...(opts.providerSandboxId ? { id: opts.providerSandboxId, sandboxId: opts.providerSandboxId } : {}),\n ...(opts.env ? { env: opts.env } : {}),\n ...(opts.workingDirectory ? { workingDirectory: opts.workingDirectory } : {}),\n ...(opts.idleTimeoutMinutes !== undefined ? { idleTimeoutMinutes: opts.idleTimeoutMinutes } : {}),\n ...(opts.checkpointName ? { checkpointName: opts.checkpointName } : {}),\n });\n return toMaterializationSandbox(clone, opts.env);\n }\n\n /**\n * Provision a new sandbox (persisting its provider id on first open) or\n * reattach to the stored one. Returns a started, live sandbox.\n */\n async ensureSandbox(store: SandboxBindingStore, onProgress?: ProgressFn): Promise<MaterializationSandbox>;\n async ensureSandbox(\n store: SandboxBindingStore,\n env?: Record<string, string>,\n onProgress?: ProgressFn,\n options?: EnsureSandboxOptions,\n ): Promise<MaterializationSandbox>;\n async ensureSandbox(\n store: SandboxBindingStore,\n envOrProgress?: Record<string, string> | ProgressFn,\n progressOrOptions?: ProgressFn | EnsureSandboxOptions,\n maybeOptions: EnsureSandboxOptions = {},\n ): Promise<MaterializationSandbox> {\n const env = typeof envOrProgress === 'function' ? undefined : envOrProgress;\n const onProgress =\n typeof envOrProgress === 'function' ? envOrProgress : (progressOrOptions as ProgressFn | undefined);\n const options =\n typeof envOrProgress === 'function'\n ? ((progressOrOptions as EnsureSandboxOptions | undefined) ?? {})\n : maybeOptions;\n const idleTimeoutMinutes = this.idleMinutes;\n const checkpointName = store.checkpointName;\n\n // Reattach path: if we have a stored sandbox id, try to reattach. The VM may\n // have been torn down by the provider's idle GC (or otherwise died), in which\n // case `start()` fails. Recover by clearing the stale id and provisioning a\n // fresh sandbox so the next open succeeds instead of being permanently wedged.\n if (store.sandboxId) {\n reportProgress(onProgress, { phase: 'reattaching', message: 'Reconnecting to your sandbox…' });\n const reattached = this.#build({\n providerSandboxId: store.sandboxId,\n idleTimeoutMinutes,\n ...(checkpointName ? { checkpointName } : {}),\n ...(env ? { env } : {}),\n ...(options.workingDirectory ? { workingDirectory: options.workingDirectory } : {}),\n });\n try {\n await reattached.start();\n return reattached;\n } catch {\n await store.setSandboxId(null);\n // fall through to fresh provision below\n }\n }\n\n // Fresh provision: enforce the per-replica budget before spending quota.\n const max = this.maxSandboxes;\n if (max > 0 && this.#liveCount >= max) {\n throw new SandboxBudgetError(max);\n }\n\n reportProgress(onProgress, { phase: 'provisioning', message: 'Provisioning a new sandbox…' });\n const sandbox = this.#build({\n idleTimeoutMinutes,\n ...(checkpointName ? { checkpointName } : {}),\n ...(env ? { env } : {}),\n ...(options.workingDirectory ? { workingDirectory: options.workingDirectory } : {}),\n });\n await sandbox.start();\n this.#liveCount += 1;\n\n const providerSandboxId = await readProviderSandboxId(sandbox);\n if (providerSandboxId) {\n await store.setSandboxId(providerSandboxId);\n }\n\n return sandbox;\n }\n\n /**\n * Tear down a sandbox binding: stop the live VM (best-effort) and clear the\n * persisted state through the binding store so the next open re-provisions\n * cleanly. Decrements the per-replica live-sandbox counter.\n *\n * @param store the binding to tear down\n * @param sandbox an already-reattached live sandbox to stop, when available\n */\n async teardownSandbox(store: SandboxBindingStore, sandbox?: MaterializationSandbox): Promise<void> {\n if (sandbox?.stop) {\n try {\n await sandbox.stop();\n } catch {\n // Best-effort: the VM may already be gone (idle GC). Still clear the binding.\n }\n }\n if (store.sandboxId) {\n if (this.#liveCount > 0) this.#liveCount -= 1;\n await store.clear();\n }\n }\n\n /**\n * Reattach to an already-provisioned sandbox by its provider id and start it.\n * Used by the workspace seam when opening a project that was already\n * materialized (sandbox id + workdir carried on controller state), so no DB\n * round-trip is needed.\n */\n async reattachSandbox(\n providerSandboxId: string,\n options: EnsureSandboxOptions = {},\n ): Promise<MaterializationSandbox> {\n const sandbox = this.#build({\n providerSandboxId,\n idleTimeoutMinutes: this.idleMinutes,\n ...(options.workingDirectory ? { workingDirectory: options.workingDirectory } : {}),\n });\n await sandbox.start();\n return sandbox;\n }\n}\n","/**\n * Composite feature gate + diagnostics for the GitHub App project feature.\n *\n * The GitHub feature is enabled only when *all three* hold:\n * - a `GithubIntegration` instance is registered with the factory\n * (constructed by the deploy entry from the `GITHUB_APP_*` env vars),\n * - web auth is enabled (a per-user installation requires a logged-in user),\n * - the application database is configured.\n *\n * OAuth/install `state` signing lives in `../../state-signing.ts` — the factory\n * creates one shared signer at boot and hands it to every integration.\n *\n * Everything here is pure: callers pass the handles they already own (the\n * integration, auth seam, state signer, sandbox fleet) — there is no global\n * registry lookup.\n */\n\nimport type { RouteAuth } from '../../routes/route.js';\nimport type { SandboxFleet } from '../../sandbox/fleet.js';\nimport type { StateSigner } from '../../state-signing.js';\nimport type { GithubIntegration } from './integration.js';\n\n/**\n * Env vars the deploy entry reads to construct a `GithubIntegration`. Names\n * only — used by diagnostics to tell an operator what to set when the\n * integration is absent. The entry enforces all-or-nothing: partial config\n * fails the boot, so at runtime the integration is either fully configured or\n * not configured at all.\n */\nconst GITHUB_APP_ENV_VARS = [\n 'GITHUB_APP_ID',\n 'GITHUB_APP_PRIVATE_KEY',\n 'GITHUB_APP_CLIENT_ID',\n 'GITHUB_APP_CLIENT_SECRET',\n 'GITHUB_APP_SLUG',\n] as const;\n\n/** Handles the GitHub feature gate + diagnostics are computed from. */\nexport interface GithubFeatureGateOptions {\n /** The registered GitHub integration, when configured. */\n github: GithubIntegration | undefined;\n /** Web auth seam — the feature requires a logged-in user. */\n auth: RouteAuth;\n /** True when the application database is configured. */\n appDbConfigured: boolean;\n /** Shared OAuth/install `state` signer, when configured. */\n stateSigner?: StateSigner;\n /** Sandbox fleet, when sandboxes are configured. */\n fleet?: SandboxFleet;\n}\n\n/**\n * True when the GitHub App project feature should be active.\n */\nexport function isGithubFeatureEnabled(options: Pick<GithubFeatureGateOptions, 'github' | 'auth'>): boolean {\n return options.github !== undefined && options.auth.enabled();\n}\n\n/**\n * Non-secret diagnostic snapshot of every GitHub feature gate. Used by startup\n * logs, `/web/github/status`, and the SPA so all three explain the same state.\n *\n * Only env var *names* and booleans are exposed — never secret values.\n */\nexport interface GithubFeatureDiagnostics {\n githubAppConfigured: boolean;\n factoryAuthEnabled: boolean;\n appDbConfigured: boolean;\n stateSecretConfigured: boolean;\n sandboxEnabled: boolean;\n sandboxProvider: string;\n /** Names of the GitHub App env vars still needed (empty when configured). */\n missingGithubAppEnvVars: string[];\n}\n\n/**\n * Collect a non-secret diagnostic snapshot of every GitHub feature gate. Centralizes\n * the feature-gate reasoning so startup logs, the status API, and the SPA explain\n * the same state. Does not change `isGithubFeatureEnabled()` behavior.\n */\nexport function getGithubFeatureDiagnostics(options: GithubFeatureGateOptions): GithubFeatureDiagnostics {\n const { github, auth, appDbConfigured, stateSigner, fleet } = options;\n return {\n githubAppConfigured: github !== undefined,\n factoryAuthEnabled: auth.enabled(),\n appDbConfigured,\n stateSecretConfigured: stateSigner?.stable ?? false,\n sandboxEnabled: fleet?.enabled ?? false,\n sandboxProvider: fleet?.provider ?? 'none',\n missingGithubAppEnvVars: github ? [] : [...GITHUB_APP_ENV_VARS],\n };\n}\n","/**\n * Org-scoped GitHub Personal Access Token settings.\n *\n * GitHub App installation tokens are the wrong credential for the `gh` CLI —\n * they hit \"Resource not accessible by integration\" on endpoints the CLI\n * needs regardless of the minted permission set. When an org pastes a PAT in\n * Settings, the sandbox `GH_TOKEN` injection sites and the\n * `github_refresh_token` tool use it instead of a minted installation token.\n * Tokens must be classic PATs whose account has access to the linked repos.\n *\n * Two kinds:\n * - `default` — the worker token every sandbox gets.\n * - `reviewer` — optional second token for review-board sessions, so PR\n * reviews come from a different account than the author. When it isn't\n * configured, review sessions fall back to the worker token.\n *\n * Both live in the generic `integration_settings` collection for the\n * `github` integration under a sentinel user id (the settings are org-wide,\n * but the schema keys settings per `(org, user)`). Tokens are never returned\n * to the browser — the routes only report whether each is configured.\n */\n\nimport type { GithubSubscriptionStorage } from './subscriptions.js';\n\n/** Sentinel `user_id` for the org-wide settings row. */\nconst PAT_SETTINGS_USER_ID = '__github_org_settings__';\n\nexport type GithubPatKind = 'default' | 'reviewer';\n\ntype GithubOrgSettings = { pat?: string; reviewerPat?: string };\n\nconst FIELD_FOR_KIND: Record<GithubPatKind, keyof GithubOrgSettings> = {\n default: 'pat',\n reviewer: 'reviewerPat',\n};\n\nfunction asToken(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null;\n}\n\n/** The PAT to install for `kind`, or null. `reviewer` falls back to the\n * worker token so review sessions still authenticate when no dedicated\n * reviewer token is configured. Fail-soft: storage errors (e.g. integration\n * storage not initialized in a partial test harness) read as \"no PAT\n * configured\" so token minting still works. */\nexport async function getGithubPat(\n getStorage: () => GithubSubscriptionStorage,\n orgId: string,\n kind: GithubPatKind = 'default',\n): Promise<string | null> {\n try {\n const settings = (await getStorage().settings.get(orgId, PAT_SETTINGS_USER_ID)) as GithubOrgSettings | null;\n if (!settings) return null;\n if (kind === 'reviewer') return asToken(settings.reviewerPat) ?? asToken(settings.pat);\n return asToken(settings.pat);\n } catch {\n return null;\n }\n}\n\n/** Which tokens are configured, without fallback semantics — feeds the\n * settings UI status badges. */\nexport async function getGithubPatStatus(\n getStorage: () => GithubSubscriptionStorage,\n orgId: string,\n): Promise<{ configured: boolean; reviewerConfigured: boolean }> {\n try {\n const settings = (await getStorage().settings.get(orgId, PAT_SETTINGS_USER_ID)) as GithubOrgSettings | null;\n return {\n configured: asToken(settings?.pat) !== null,\n reviewerConfigured: asToken(settings?.reviewerPat) !== null,\n };\n } catch {\n return { configured: false, reviewerConfigured: false };\n }\n}\n\nexport async function setGithubPat(\n storage: GithubSubscriptionStorage,\n orgId: string,\n pat: string,\n kind: GithubPatKind = 'default',\n): Promise<void> {\n const existing = ((await storage.settings.get(orgId, PAT_SETTINGS_USER_ID)) ?? {}) as GithubOrgSettings;\n await storage.settings.save(orgId, PAT_SETTINGS_USER_ID, { ...existing, [FIELD_FOR_KIND[kind]]: pat });\n}\n\nexport async function clearGithubPat(\n storage: GithubSubscriptionStorage,\n orgId: string,\n kind: GithubPatKind = 'default',\n): Promise<void> {\n const existing = (await storage.settings.get(orgId, PAT_SETTINGS_USER_ID)) as GithubOrgSettings | null;\n const field = FIELD_FOR_KIND[kind];\n if (!existing?.[field]) return;\n const { [field]: _removed, ...rest } = existing;\n await storage.settings.save(orgId, PAT_SETTINGS_USER_ID, rest);\n}\n","/**\n * Per-(project, user) lock that serializes the worktree/commit/push/PR flows.\n *\n * The push/PR flows temporarily rewrite the sandbox git remote to a tokenized\n * URL and scrub it again in a `finally`; two concurrent operations on the same\n * `(project, user)` sandbox could interleave those rewrites and leak a tokenized\n * remote. Serializing per `(project, user)` removes that race.\n *\n * There are two layers:\n * 1. An **in-process** promise-chain mutex keyed by the lock key, so repeated\n * same-replica callers stay cheap and never touch the database for ordering.\n * 2. The factory storage backend's **`withDistributedLock` capability** (pg:\n * transaction-scoped advisory locks) so that *different replicas*\n * operating on the same key also serialize. Backends without the\n * capability (libsql: local single-writer) fall back to the in-process\n * mutex alone — correct for single-replica deployments.\n *\n * Set `MASTRACODE_DISTRIBUTED_LOCK=0` to force-disable the distributed layer\n * (local dev, single replica) and fall back to the pure in-process mutex.\n */\n\nimport { createHash } from 'node:crypto';\n\nimport type { FactoryStorage } from '@mastra/core/storage';\n\n/** Minimal pg pool surface used by the distributed lock (for testability). */\nexport interface LockPool {\n connect(): Promise<LockClient>;\n}\nexport interface LockClient {\n query(sql: string, params?: unknown[]): Promise<unknown>;\n release(): void;\n}\n\nconst inProcessLocks = new Map<string, Promise<unknown>>();\n\n/**\n * Default hard cap on how long a critical section may run inside the project\n * lock. Prevents an untimed outbound call (sandbox HTTP, GitHub App API, git\n * push, etc.) from pinning both the advisory lock and the pg pool connection\n * indefinitely — the failure mode behind the 2025-07-23 shipyard 30s plateau\n * incident. Callers can override per call via `timeoutMs`.\n */\nexport const DEFAULT_PROJECT_LOCK_TIMEOUT_MS = 60_000;\n\n/** Thrown when the critical section under `withProjectLock` exceeds the timeout. */\nexport class ProjectLockTimeoutError extends Error {\n readonly key: string;\n readonly timeoutMs: number;\n constructor(key: string, timeoutMs: number) {\n super(`Project lock critical section for \"${key}\" exceeded ${timeoutMs}ms`);\n this.name = 'ProjectLockTimeoutError';\n this.key = key;\n this.timeoutMs = timeoutMs;\n }\n}\n\n/**\n * Race `fn()` against a timeout, throwing `ProjectLockTimeoutError` if the\n * timeout fires first. `fn()` receives an `AbortSignal` so it can (optionally)\n * abort in-flight outbound I/O when the timeout trips. If `fn()` ignores the\n * signal it will still resolve/reject eventually — but the caller sees the\n * timeout error immediately, which is what lets the outer lock wrapper roll\n * back and release the connection.\n */\nasync function runWithTimeout<T>(key: string, timeoutMs: number, fn: (signal: AbortSignal) => Promise<T>): Promise<T> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n const abortError = new Promise<never>((_, reject) => {\n controller.signal.addEventListener('abort', () => reject(new ProjectLockTimeoutError(key, timeoutMs)), {\n once: true,\n });\n });\n const work = fn(controller.signal);\n // If `fn` eventually rejects (e.g. its own fetch observes the abort signal\n // after we already rejected via timeout), swallow it — the outer caller\n // has already been rejected with our timeout error and we don't want an\n // unhandled rejection.\n work.catch(() => {});\n try {\n return await Promise.race([work, abortError]);\n } finally {\n clearTimeout(timer);\n }\n}\n\n/**\n * True when the cross-replica lock layer should be used: not force-disabled\n * via env, and the factory storage backend exposes the\n * `withDistributedLock` capability.\n */\nexport function isDistributedLockEnabled(storage: FactoryStorage | undefined): boolean {\n if (process.env.MASTRACODE_DISTRIBUTED_LOCK === '0') return false;\n return typeof storage?.withDistributedLock === 'function';\n}\n\n/**\n * Hash a lock key into the two signed 32-bit integers that the two-arg form of\n * `pg_advisory_xact_lock(int4, int4)` expects. Using two int4 args (rather than\n * one int8) keeps the key inside the GitHub-feature advisory-lock namespace and\n * avoids collisions with other single-int8 advisory locks.\n */\nexport function hashKey(key: string): [number, number] {\n const digest = createHash('sha256').update(key).digest();\n // Read two independent 32-bit halves as signed int4 values.\n const a = digest.readInt32BE(0);\n const b = digest.readInt32BE(4);\n return [a, b];\n}\n\n/**\n * Run `fn` while holding the lock for `key`. Same-replica callers serialize via\n * the in-process mutex; cross-replica callers additionally serialize via a\n * Postgres transaction-scoped advisory lock (unless disabled).\n *\n * The in-process chain swallows rejections so one failed operation does not\n * poison the lock for subsequent callers.\n */\nexport function withProjectLock<T>(options: {\n key: string;\n /** Factory storage backend supplying the `withDistributedLock` capability, when available. */\n storage?: FactoryStorage;\n fn: (signal: AbortSignal) => Promise<T>;\n /** Test seam: fake pg pool standing in for the distributed layer. */\n pool?: LockPool;\n /**\n * Hard cap on the critical section. Defaults to\n * {@link DEFAULT_PROJECT_LOCK_TIMEOUT_MS}. On timeout `fn`'s abort signal\n * fires and the outer lock throws `ProjectLockTimeoutError`, releasing the\n * advisory lock + pool connection.\n */\n timeoutMs?: number;\n}): Promise<T> {\n const { key, storage, fn, pool, timeoutMs = DEFAULT_PROJECT_LOCK_TIMEOUT_MS } = options;\n const prev = inProcessLocks.get(key) ?? Promise.resolve();\n const run = () => withDbAdvisoryLock({ key, storage, fn, pool, timeoutMs });\n const next = prev.then(run, run);\n const tail = next.then(\n () => undefined,\n () => undefined,\n );\n inProcessLocks.set(key, tail);\n // Drop the entry once this operation settles, but only if no later caller has\n // chained onto it in the meantime — otherwise we'd evict a live waiter's tail.\n // This keeps the map from growing unbounded across many distinct project keys.\n void tail.then(() => {\n if (inProcessLocks.get(key) === tail) {\n inProcessLocks.delete(key);\n }\n });\n return next;\n}\n\n/**\n * Acquire only the cross-replica lock for `key` and run `fn` under it. This is\n * the distributed serialization layer; `withProjectLock` wraps it with an\n * in-process mutex for same-replica callers. Delegates to the factory storage\n * backend's `withDistributedLock` capability; backends without it (or a\n * force-disabled env) run `fn` directly — the in-process mutex still holds.\n *\n * `poolOverride` keeps the pg advisory-lock path directly testable with a fake\n * pool (each simulated replica has its own in-process state but shares one\n * database).\n */\nexport async function withDbAdvisoryLock<T>(options: {\n key: string;\n storage?: FactoryStorage;\n fn: (signal: AbortSignal) => Promise<T>;\n pool?: LockPool;\n timeoutMs?: number;\n}): Promise<T> {\n const { key, storage, fn, pool, timeoutMs = DEFAULT_PROJECT_LOCK_TIMEOUT_MS } = options;\n if (process.env.MASTRACODE_DISTRIBUTED_LOCK === '0') {\n return runWithTimeout(key, timeoutMs, fn);\n }\n\n if (pool) return advisoryLockOver(pool, key, timeoutMs, fn);\n\n if (typeof storage?.withDistributedLock !== 'function') {\n return runWithTimeout(key, timeoutMs, fn);\n }\n // Wrap the backend-provided lock so the critical section is bounded\n // regardless of whether the backend implements its own timeout. The\n // backend still owns lock acquisition/release; we own the timeout on\n // `fn`.\n return storage.withDistributedLock(key, () => runWithTimeout(key, timeoutMs, fn));\n}\n\n/** The pg advisory-lock body, kept for the `poolOverride` test seam. */\nasync function advisoryLockOver<T>(\n pool: LockPool,\n key: string,\n timeoutMs: number,\n fn: (signal: AbortSignal) => Promise<T>,\n): Promise<T> {\n const [k1, k2] = hashKey(key);\n const client = await pool.connect();\n try {\n await client.query('BEGIN');\n // Blocks until no other transaction holds this advisory key. Auto-released\n // when the transaction ends below.\n await client.query('SELECT pg_advisory_xact_lock($1, $2)', [k1, k2]);\n try {\n const result = await runWithTimeout(key, timeoutMs, fn);\n await client.query('COMMIT');\n return result;\n } catch (err) {\n // COMMIT/ROLLBACK below releases the advisory lock. If the underlying\n // connection is already dead (e.g. Neon killed it after IIT), the\n // rollback throws — we swallow that specifically so the original error\n // reaches the caller.\n try {\n await client.query('ROLLBACK');\n } catch {\n /* connection already gone; nothing to roll back */\n }\n throw err;\n }\n } finally {\n client.release();\n }\n}\n\n/** For tests: clear the in-process lock chains. */\nexport function __resetProjectLocksForTests(): void {\n inProcessLocks.clear();\n}\n","/**\n * Repo materialization for GitHub-backed repositories.\n *\n * A GitHub repo is never cloned onto the server host. Instead each project gets\n * its own isolated sandbox (provisioned by the fleet in `../sandbox/fleet`) and\n * the repo is cloned *inside* that sandbox. The agent's file tools and command\n * tools then operate entirely against the remote checkout.\n *\n * - `ensureProjectSandbox(row)` / `teardownProjectSandbox(row)` bind the fleet's\n * provision/reattach/teardown lifecycle to the per-(project,user) sandbox row.\n * - `materializeRepo(row, token)` runs `git clone` (first open) or `git pull`\n * (re-open) inside the sandbox, using a short-lived installation token that is\n * scrubbed from the git remote afterwards so it never persists in the VM.\n *\n * This module owns everything git/GitHub: clone/pull, commit/push, worktrees,\n * and `gh pr create`. Sandbox provisioning, budgets, and workdir layout live in\n * the fleet module.\n */\n\nimport { createHash } from 'node:crypto';\nimport { reportProgress } from '../../sandbox/fleet.js';\nimport type {\n MaterializationSandbox,\n ProgressFn,\n SandboxBindingStore,\n SandboxCommandResult,\n SandboxFleet,\n} from '../../sandbox/fleet.js';\nimport type {\n ProjectRepositorySandbox,\n SourceControlStorageHandle,\n} from '../../storage/domains/source-control/base.js';\n\ntype SourceControlSandboxStorage = SourceControlStorageHandle['sandboxes'];\ntype MaterializationStore = Pick<SourceControlSandboxStorage, 'markMaterialized'>;\n\ninterface RepoMaterializationBinding {\n id: string;\n sandboxWorkdir: string;\n materializedAt: Date | null;\n}\n\n/** Adapt a per-(project,user) sandbox binding row to the fleet's persistence seam. */\nfunction bindingStore(row: ProjectRepositorySandbox, storage: SourceControlSandboxStorage): SandboxBindingStore {\n return {\n sandboxId: row.sandboxId,\n setSandboxId: id =>\n id === null ? storage.clearBinding({ id: row.id }) : storage.setSandboxId({ id: row.id, sandboxId: id }),\n clear: () => storage.clearBinding({ id: row.id }),\n };\n}\n\n/**\n * Provision a new sandbox (persisting its provider id on first open) or\n * reattach to the stored one. Returns a started, live sandbox.\n */\nexport async function ensureProjectSandbox(options: {\n fleet: SandboxFleet;\n row: ProjectRepositorySandbox;\n storage: SourceControlSandboxStorage;\n token: string;\n onProgress?: ProgressFn;\n}): Promise<MaterializationSandbox> {\n const { fleet, row, storage, token, onProgress } = options;\n return fleet.ensureSandbox(bindingStore(row, storage), { GH_TOKEN: token }, onProgress);\n}\n\n/**\n * Tear down a user's sandbox for a project: stop the live VM (best-effort) and\n * clear the persisted `sandboxId`/`materializedAt` on the per-(project,user)\n * binding row so the next open re-provisions cleanly.\n *\n * @param row the per-(project,user) sandbox binding to tear down\n * @param sandbox an already-reattached live sandbox to stop, when available\n */\nexport async function teardownProjectSandbox(options: {\n fleet: SandboxFleet;\n row: ProjectRepositorySandbox;\n storage: SourceControlSandboxStorage;\n sandbox?: MaterializationSandbox;\n}): Promise<void> {\n const { fleet, row, storage, sandbox } = options;\n return fleet.teardownSandbox(bindingStore(row, storage), sandbox);\n}\n\n/**\n * Single-quote a string for safe POSIX shell interpolation. Wraps the value in\n * single quotes and escapes any embedded single quote using the canonical\n * close-quote / escaped-quote / reopen-quote sequence (`'\\''`). This is the\n * standard POSIX-safe construction and prevents the quoted string from being\n * terminated early.\n */\nexport function shellQuote(value: string): string {\n // Replace each ' with the four-character sequence: ' \\ ' '\n return `'` + value.split(`'`).join(`'\\\\''`) + `'`;\n}\n\n/** Run a shell script in the sandbox via `sh -c`. */\nasync function sh(sandbox: MaterializationSandbox, script: string): Promise<SandboxCommandResult> {\n return sandbox.executeCommand('sh', ['-c', script]);\n}\n\n/** Error raised when the sandbox cannot materialize the repo (actionable). */\nexport class MaterializeError extends Error {\n constructor(\n message: string,\n readonly code:\n | 'git-missing'\n | 'egress-blocked'\n | 'clone-failed'\n | 'pull-failed'\n | 'push-failed'\n | 'commit-failed'\n | 'gh-missing'\n | 'pr-failed',\n ) {\n super(message);\n this.name = 'MaterializeError';\n }\n}\n\n/**\n * Build the token-auth clone/pull URL for a repo. The token lives only inside\n * this URL and is scrubbed from the remote after the operation.\n */\nfunction tokenUrl(repoFullName: string, token: string): string {\n return `https://x-access-token:${token}@github.com/${repoFullName}.git`;\n}\n\nfunction cleanUrl(repoFullName: string): string {\n return `https://github.com/${repoFullName}.git`;\n}\n\n/** Repo metadata needed to materialize, read from the org-owned project row. */\nexport interface RepoMaterializeInfo {\n repoFullName: string;\n defaultBranch: string;\n}\n\n/**\n * Materialize the repo inside the user's sandbox. Clones on first open, pulls on\n * re-open. Always scrubs the install token from the remote afterwards and sets\n * `materialized_at` on the per-user sandbox binding row.\n *\n */\nexport async function materializeRepo(options: {\n /** The per-(project,user) sandbox binding (provisioned via `ensureProjectSandbox`). */\n row: RepoMaterializationBinding;\n /** Repo metadata from the org-owned project row. */\n repoInfo: RepoMaterializeInfo;\n /** The live sandbox to run git inside. */\n sandbox: MaterializationSandbox;\n /** A freshly minted, short-lived installation access token. */\n token: string;\n storage: MaterializationStore;\n onProgress?: ProgressFn;\n}): Promise<void> {\n const { row: sandboxRow, repoInfo, sandbox, token, storage, onProgress } = options;\n const workdir = sandboxRow.sandboxWorkdir;\n const repo = repoInfo.repoFullName;\n\n // 0. Defense in depth: never build a git command from values that aren't\n // strictly shaped, even if a malformed row reached the DB. Inputs are also\n // validated at the route boundary before storage.\n if (!/^[\\w.-]+\\/[\\w.-]+$/.test(repo)) {\n throw new MaterializeError(`Refusing to materialize: invalid repo full name '${repo}'.`, 'clone-failed');\n }\n if (!/^[A-Za-z0-9_./-]+$/.test(repoInfo.defaultBranch)) {\n throw new MaterializeError(\n `Refusing to materialize: invalid default branch '${repoInfo.defaultBranch}'.`,\n 'clone-failed',\n );\n }\n\n // 1. Preflight: git must be installed in the sandbox template.\n const gitVersion = await sh(sandbox, 'git --version');\n if (gitVersion.exitCode !== 0) {\n throw new MaterializeError(\n 'git is not installed in the sandbox. The sandbox template must include git.',\n 'git-missing',\n );\n }\n\n const authUrl = tokenUrl(repo, token);\n\n // The DB's `materializedAt` can drift from disk — a fresh per-user binding\n // row over an already-populated workdir (local dev DB resets, repaired\n // rows, earlier flows) would make `git clone` fail on the non-empty\n // directory. Re-detect an existing checkout of this repo and pull instead.\n const alreadyMaterialized = Boolean(sandboxRow.materializedAt) || (await hasExistingCheckout(sandbox, workdir, repo));\n\n try {\n if (!alreadyMaterialized) {\n // 2a. First open: shallow-clone the default branch into the workdir. A\n // shallow single-branch clone is dramatically faster for large repos; the\n // later re-open uses `git pull --ff-only`, which works on shallow clones.\n reportProgress(onProgress, {\n phase: 'cloning',\n message: `Cloning ${repo} (first open can take a minute)…`,\n });\n const clone = await sh(\n sandbox,\n `git clone --depth=1 --single-branch --branch ${shellQuote(repoInfo.defaultBranch)} ${shellQuote(authUrl)} ${shellQuote(workdir)}`,\n );\n if (clone.exitCode !== 0) {\n throw classifyGitFailure(clone, 'clone-failed');\n }\n } else {\n // 2b. Re-open: refresh remote to the token URL and fast-forward pull.\n reportProgress(onProgress, { phase: 'pulling', message: `Updating ${repo} to the latest changes…` });\n const setUrl = await sh(sandbox, `git -C ${shellQuote(workdir)} remote set-url origin ${shellQuote(authUrl)}`);\n if (setUrl.exitCode !== 0) {\n throw new MaterializeError(`Failed to set git remote: ${setUrl.stderr}`, 'pull-failed');\n }\n const pull = await sh(sandbox, `git -C ${shellQuote(workdir)} pull --ff-only`);\n if (pull.exitCode !== 0) {\n throw classifyGitFailure(pull, 'pull-failed');\n }\n }\n } finally {\n // 3. Always scrub the token from the remote so it isn't left in the VM's\n // git config, even when the clone/pull above failed partway through. This\n // is best-effort on the failure path (the workdir may not exist yet after a\n // failed clone); on the success path the scrub must succeed or we surface it.\n await scrubRemote(sandbox, workdir, repo, alreadyMaterialized);\n }\n\n // 4. Mark materialized.\n reportProgress(onProgress, { phase: 'finalizing', message: 'Finalizing workspace…' });\n await storage.markMaterialized({ id: sandboxRow.id });\n}\n\n/** Check out a session's branch inside its isolated repository clone. */\nexport async function checkoutSessionBranch(\n sandbox: MaterializationSandbox,\n workdir: string,\n {\n branch,\n baseBranch,\n token,\n repoFullName,\n }: { branch: string; baseBranch: string; token: string; repoFullName: string },\n): Promise<void> {\n if (!isValidGitRef(branch) || !isValidGitRef(baseBranch)) {\n throw new MaterializeError('Refusing to create a session from an invalid branch name.', 'clone-failed');\n }\n\n const current = await sh(sandbox, `git -C ${shellQuote(workdir)} branch --show-current`);\n if (current.exitCode === 0 && current.stdout.trim() === branch) return;\n\n const local = await sh(\n sandbox,\n `git -C ${shellQuote(workdir)} show-ref --verify --quiet refs/heads/${shellQuote(branch)}`,\n );\n if (local.exitCode === 0) {\n const checkout = await sh(sandbox, `git -C ${shellQuote(workdir)} checkout ${shellQuote(branch)}`);\n if (checkout.exitCode !== 0) throw classifyGitFailure(checkout, 'clone-failed');\n return;\n }\n\n const authUrl = tokenUrl(repoFullName, token);\n try {\n const setUrl = await sh(sandbox, `git -C ${shellQuote(workdir)} remote set-url origin ${shellQuote(authUrl)}`);\n if (setUrl.exitCode !== 0) throw classifyGitFailure(setUrl, 'pull-failed');\n const fetch = await sh(\n sandbox,\n `git -C ${shellQuote(workdir)} fetch origin ${shellQuote(baseBranch)} && git -C ${shellQuote(workdir)} checkout -b ${shellQuote(branch)} FETCH_HEAD`,\n );\n if (fetch.exitCode !== 0) throw classifyGitFailure(fetch, 'clone-failed');\n } finally {\n await sh(sandbox, `git -C ${shellQuote(workdir)} remote set-url origin ${shellQuote(cleanUrl(repoFullName))}`);\n }\n}\n\n/**\n * True when the workdir already holds a git checkout whose `origin` points at\n * this exact repo. Matches both the clean and token-auth URL forms; any other\n * remote (or no git dir at all) falls back to the clone path.\n */\nasync function hasExistingCheckout(\n sandbox: MaterializationSandbox,\n workdir: string,\n repoFullName: string,\n): Promise<boolean> {\n const result = await sh(sandbox, `git -C ${shellQuote(workdir)} remote get-url origin`);\n if (result.exitCode !== 0) return false;\n const url = result.stdout.trim().toLowerCase();\n const suffix = `github.com/${repoFullName.toLowerCase()}`;\n return url.endsWith(`${suffix}.git`) || url.endsWith(suffix);\n}\n\n/**\n * Reset the git remote back to the tokenless URL. On a successful clone/pull the\n * workdir always has a `.git`, so a non-zero exit code here means the token may\n * still be persisted — surface it. On the failure path the workdir may not exist\n * (e.g. a failed clone), so a non-zero exit is tolerated.\n */\nasync function scrubRemote(\n sandbox: MaterializationSandbox,\n workdir: string,\n repoFullName: string,\n expectGitDir: boolean,\n): Promise<void> {\n const result = await sh(\n sandbox,\n `git -C ${shellQuote(workdir)} remote set-url origin ${shellQuote(cleanUrl(repoFullName))}`,\n );\n if (result.exitCode !== 0 && expectGitDir) {\n throw new MaterializeError(\n `Failed to scrub installation token from git remote: ${result.stderr.trim() || result.stdout.trim()}`,\n 'pull-failed',\n );\n }\n}\n\n/**\n * Turn a failed git command into an actionable error, detecting the common\n * \"cannot reach github.com\" egress failure.\n */\nfunction classifyGitFailure(\n result: SandboxCommandResult,\n fallback: 'clone-failed' | 'pull-failed' | 'push-failed',\n): MaterializeError {\n const stderr = result.stderr || '';\n if (/could not resolve host|failed to connect|network is unreachable|Connection timed out/i.test(stderr)) {\n return new MaterializeError(\n 'The sandbox could not reach github.com. The sandbox network must allow outbound egress to github.com.',\n 'egress-blocked',\n );\n }\n const verb = fallback === 'clone-failed' ? 'clone' : fallback === 'pull-failed' ? 'pull' : 'push';\n return new MaterializeError(`git ${verb} failed: ${stderr}`, fallback);\n}\n\n// ---------------------------------------------------------------------------\n// Phase 1 — git identity + token-scoped push primitive\n//\n// These helpers let the sandbox author and push commits safely. The install\n// token is short-lived, minted per-operation server-side, injected only into\n// the temporary remote URL inside the sandbox, and always scrubbed in a\n// `finally` so it never persists in `.git/config`.\n// ---------------------------------------------------------------------------\n\n/**\n * Validate a git ref (branch) name. Server-side defense-in-depth: only allow a\n * conservative character set so a branch can never be built into a shell\n * command in a way that escapes quoting. Mirrors the route-layer check.\n */\nexport function isValidGitRef(value: unknown): value is string {\n return (\n typeof value === 'string' &&\n value.length > 0 &&\n value.length <= 255 &&\n // Reject leading-dash refs (e.g. `--mirror`) so the value can never be\n // parsed as a git option when interpolated into a command.\n !value.startsWith('-') &&\n /^[A-Za-z0-9_./-]+$/.test(value)\n );\n}\n\n/** Identity used to author commits inside the sandbox. */\nexport interface GitIdentity {\n name?: string | null;\n email?: string | null;\n /** GitHub login, used to derive a stable noreply identity when name/email are absent. */\n login?: string | null;\n}\n\n/**\n * Resolve a concrete `{ name, email }` for git authorship from a possibly-sparse\n * identity. Falls back to a GitHub-style noreply identity so commits are never\n * authored with an empty or host-derived identity.\n */\nexport function resolveGitIdentity(identity: GitIdentity): { name: string; email: string } {\n const login = (identity.login || '').trim();\n const name = (identity.name || '').trim() || login || 'Mastra Code';\n const email =\n (identity.email || '').trim() ||\n (login ? `${login}@users.noreply.github.com` : 'mastra-code@users.noreply.github.com');\n return { name, email };\n}\n\n/**\n * Configure `user.name` / `user.email` for the given repo working tree inside\n * the sandbox so commits are authored correctly. Values are shell-quoted.\n */\nexport async function configureGitIdentity(\n sandbox: MaterializationSandbox,\n workdir: string,\n identity: GitIdentity,\n): Promise<void> {\n const { name, email } = resolveGitIdentity(identity);\n const setName = await sh(sandbox, `git -C ${shellQuote(workdir)} config user.name ${shellQuote(name)}`);\n if (setName.exitCode !== 0) {\n throw new MaterializeError(`Failed to set git user.name: ${setName.stderr.trim()}`, 'commit-failed');\n }\n const setEmail = await sh(sandbox, `git -C ${shellQuote(workdir)} config user.email ${shellQuote(email)}`);\n if (setEmail.exitCode !== 0) {\n throw new MaterializeError(`Failed to set git user.email: ${setEmail.stderr.trim()}`, 'commit-failed');\n }\n}\n\n/**\n * Temporarily rewrite `origin` to a tokenized URL, run `fn` (e.g. a push), and\n * **always** scrub the remote back to the tokenless URL in a `finally`. The\n * token therefore only ever lives in the remote URL for the duration of the\n * operation and is never left in the VM's git config.\n *\n * On the success path the scrub must succeed (a leaked token is a hard error);\n * if it fails we surface it. On the failure path the scrub is best-effort but\n * still attempted, and the original operation error is rethrown.\n */\nexport async function withInstallToken<T>(\n sandbox: MaterializationSandbox,\n workdir: string,\n repoFullName: string,\n token: string,\n fn: () => Promise<T>,\n): Promise<T> {\n if (!/^[\\w.-]+\\/[\\w.-]+$/.test(repoFullName)) {\n throw new MaterializeError(`Refusing to push: invalid repo full name '${repoFullName}'.`, 'push-failed');\n }\n\n const setUrl = await sh(\n sandbox,\n `git -C ${shellQuote(workdir)} remote set-url origin ${shellQuote(tokenUrl(repoFullName, token))}`,\n );\n if (setUrl.exitCode !== 0) {\n // Best-effort scrub even though set-url failed, then surface the failure.\n await scrubRemote(sandbox, workdir, repoFullName, false);\n throw new MaterializeError(`Failed to set git remote: ${setUrl.stderr.trim()}`, 'push-failed');\n }\n\n try {\n return await fn();\n } finally {\n // Always restore the tokenless remote. The workdir has a `.git` (we just\n // rewrote its remote) so a scrub failure means the token may still persist\n // — surface it.\n await scrubRemote(sandbox, workdir, repoFullName, true);\n }\n}\n\n/**\n * Push a branch back to GitHub from inside the sandbox using a short-lived\n * installation token. The branch is ref-validated, the token is injected only\n * into the remote URL via `withInstallToken`, and egress failures are\n * classified into actionable errors.\n */\nexport async function pushBranch(\n sandbox: MaterializationSandbox,\n workdir: string,\n branch: string,\n token: string,\n repoFullName: string,\n): Promise<void> {\n if (!isValidGitRef(branch)) {\n throw new MaterializeError(`Refusing to push: invalid branch name '${branch}'.`, 'push-failed');\n }\n\n await withInstallToken(sandbox, workdir, repoFullName, token, async () => {\n const push = await sh(sandbox, `git -C ${shellQuote(workdir)} push -u origin ${shellQuote(branch)}`);\n if (push.exitCode !== 0) {\n throw classifyGitFailure(push, 'push-failed');\n }\n });\n}\n\nexport interface CommitResult {\n /** True when a commit was created; false when there was nothing to commit. */\n committed: boolean;\n}\n\n/**\n * Stage every change in the working tree and create a commit inside the\n * sandbox. The git identity is configured first so authorship is correct. When\n * there is nothing to commit this is a no-op (`committed: false`) rather than an\n * error, so callers can safely commit-then-push without first diffing.\n *\n * @param sandbox the live sandbox containing the checkout\n * @param workdir the worktree (or repo) path to commit in\n * @param message the commit message (quoted; arbitrary text is safe)\n * @param identity authorship identity for the commit\n */\nexport async function commitAll(\n sandbox: MaterializationSandbox,\n workdir: string,\n message: string,\n identity: GitIdentity,\n): Promise<CommitResult> {\n await configureGitIdentity(sandbox, workdir, identity);\n\n const add = await sh(sandbox, `git -C ${shellQuote(workdir)} add -A`);\n if (add.exitCode !== 0) {\n throw new MaterializeError(`git add failed: ${add.stderr.trim() || add.stdout.trim()}`, 'commit-failed');\n }\n\n // Nothing staged → nothing to commit. `git diff --cached --quiet` exits 1 when\n // there are staged changes, 0 when the index is clean.\n const staged = await sh(sandbox, `git -C ${shellQuote(workdir)} diff --cached --quiet`);\n if (staged.exitCode === 0) {\n return { committed: false };\n }\n\n const commit = await sh(sandbox, `git -C ${shellQuote(workdir)} commit -m ${shellQuote(message)}`);\n if (commit.exitCode !== 0) {\n throw new MaterializeError(`git commit failed: ${commit.stderr.trim() || commit.stdout.trim()}`, 'commit-failed');\n }\n\n return { committed: true };\n}\n\n// ---------------------------------------------------------------------------\n// Phase 2 — worktree / branch lifecycle\n//\n// Each unit of work gets its own branch + working tree inside the same sandbox\n// as the base checkout. The worktree path is always computed server-side from a\n// sanitized branch name; client input never reaches a filesystem path.\n// ---------------------------------------------------------------------------\n\n/** Error raised when a worktree cannot be created/reused inside the sandbox. */\nexport class WorktreeError extends Error {\n constructor(\n message: string,\n readonly code: 'invalid-branch' | 'worktree-failed' | 'setup-failed',\n ) {\n super(message);\n this.name = 'WorktreeError';\n }\n}\n\n/**\n * Reduce a (already ref-validated) branch name to a filesystem-safe directory\n * segment for the worktree path: slashes/dots/unsafe chars collapsed to `-`.\n * This only affects the *directory name*, never the git branch itself.\n *\n * Sanitization is lossy (e.g. `feat/a` and `feat-a` both reduce to `feat-a`),\n * so an 8-char hash of the original branch is appended whenever the sanitized\n * form differs from the input. That keeps clean names (`main`) readable while\n * guaranteeing distinct branches never share a worktree directory.\n */\nexport function safeBranchDir(branch: string): string {\n const sanitized =\n branch\n .replace(/[^A-Za-z0-9._-]+/g, '-')\n .replace(/\\/+/g, '-')\n .replace(/^[-.]+|[-.]+$/g, '')\n .slice(0, 100) || 'work';\n if (sanitized === branch) return sanitized;\n const hash = createHash('sha256').update(branch).digest('hex').slice(0, 8);\n return `${sanitized}-${hash}`;\n}\n\n/**\n * Compute the absolute worktree path for a branch, server-side only. Worktrees\n * live alongside the repo checkout under a sibling `worktrees/` directory so the\n * repo's `.git` is shared. Never derived from client-supplied paths.\n */\nexport function computeWorktreePath(repoWorkdir: string, branch: string): string {\n const parent = repoWorkdir.replace(/\\/+$/, '').split('/').slice(0, -1).join('/') || '';\n return `${parent}/worktrees/${safeBranchDir(branch)}`;\n}\n\nexport interface EnsureWorktreeResult {\n worktreePath: string;\n branch: string;\n baseBranch: string;\n /** True when an existing worktree was reused rather than freshly created. */\n reused: boolean;\n}\n\n/**\n * Create (or reuse) a git worktree + branch inside the sandbox for a unit of\n * work. Idempotent: if a worktree already exists at the computed path it is\n * reused. The branch is created from the freshly fetched `origin/<baseBranch>`\n * — never the sandbox's possibly stale local ref — so new worktrees always\n * start from the latest remote state.\n *\n * @param sandbox live sandbox containing the base checkout\n * @param repoWorkdir the base repo checkout path inside the sandbox\n * @param branch the feature branch (ref-validated server-side)\n * @param baseBranch the branch to fork from (ref-validated; defaults to the repo's default branch)\n * @param token short-lived installation token used only for the base-branch fetch\n * @param repoFullName `owner/repo` used to build the tokenized remote URL\n */\nexport async function ensureWorktree(\n sandbox: MaterializationSandbox,\n repoWorkdir: string,\n {\n branch,\n baseBranch,\n token,\n repoFullName,\n }: { branch: string; baseBranch: string; token: string; repoFullName: string },\n): Promise<EnsureWorktreeResult> {\n if (!isValidGitRef(branch)) {\n throw new WorktreeError(`Invalid branch name '${branch}'.`, 'invalid-branch');\n }\n if (!isValidGitRef(baseBranch)) {\n throw new WorktreeError(`Invalid base branch name '${baseBranch}'.`, 'invalid-branch');\n }\n\n const worktreePath = computeWorktreePath(repoWorkdir, branch);\n\n // Idempotent reuse: a worktree already checked out at this path has a `.git`\n // file (worktrees use a gitfile, not a directory). Reuse it as-is.\n const exists = await sh(sandbox, `test -e ${shellQuote(`${worktreePath}/.git`)}`);\n if (exists.exitCode === 0) {\n return { worktreePath, branch, baseBranch, reused: true };\n }\n\n // Fetch the latest base ref from origin before forking. The explicit refspec\n // updates `refs/remotes/origin/<base>` even when the checkout was created as\n // a single-branch clone. The fetch needs the install token (the resting\n // remote is tokenless), and a failure is a hard error — silently forking a\n // stale local ref is worse than failing the request.\n const baseRef = `origin/${baseBranch}`;\n await withInstallToken(sandbox, repoWorkdir, repoFullName, token, async () => {\n const fetch = await sh(\n sandbox,\n `git -C ${shellQuote(repoWorkdir)} fetch origin ${shellQuote(`+refs/heads/${baseBranch}:refs/remotes/${baseRef}`)}`,\n );\n if (fetch.exitCode !== 0) {\n throw classifyGitFailure(fetch, 'pull-failed');\n }\n });\n\n // Create the worktree. If the branch already exists, check it out into the\n // worktree; otherwise create it from the fetched base. `git worktree add -B`\n // creates-or-resets the branch to the base, which keeps this idempotent for a\n // fresh worktree while still working when the branch already exists remotely.\n // `--no-track` keeps the feature branch from tracking origin/<base>; pushes\n // set their own upstream via `push -u`.\n const add = await sh(\n sandbox,\n `git -C ${shellQuote(repoWorkdir)} worktree add --no-track -B ${shellQuote(branch)} ${shellQuote(worktreePath)} ${shellQuote(baseRef)}`,\n );\n if (add.exitCode !== 0) {\n throw new WorktreeError(`git worktree add failed: ${add.stderr.trim() || add.stdout.trim()}`, 'worktree-failed');\n }\n\n return { worktreePath, branch, baseBranch, reused: false };\n}\n\n/**\n * Run the project's setup command (e.g. `pnpm i && pnpm build`) inside a\n * freshly created worktree. Called before the worktree is handed to any agent\n * run so the checkout is ready to build/test. A non-zero exit is a hard error —\n * starting agent work in a half-set-up tree is worse than failing the request.\n *\n * Security model: the command is intentionally arbitrary shell — that is the\n * feature (install deps, build, seed fixtures). It is only configurable by\n * authenticated org members (the settings route is gated by\n * `resolveOrgTenant` + org-scoped project lookup, with length and\n * control-character validation), and it executes exclusively inside the\n * project's isolated sandbox — the same environment where org members already\n * run arbitrary shell via the agent's command tool. It never runs on the web\n * server host, so it grants no privilege beyond what sandbox access already\n * provides.\n *\n * @param sandbox live sandbox containing the worktree\n * @param worktreePath the server-computed worktree path the command runs in\n * @param command the org-configured setup shell command\n */\nexport async function runWorktreeSetup(\n sandbox: MaterializationSandbox,\n worktreePath: string,\n command: string,\n): Promise<void> {\n const result = await sh(sandbox, `cd ${shellQuote(worktreePath)} && { ${command}\\n}`);\n if (result.exitCode !== 0) {\n const detail = (result.stderr.trim() || result.stdout.trim()).slice(-2000);\n throw new WorktreeError(`Setup command failed (exit ${result.exitCode}): ${detail}`, 'setup-failed');\n }\n}\n\n/**\n * Remove a worktree (and its local feature branch) from the sandbox. The\n * checkout is removed with `--force` — the caller owns confirming that any\n * uncommitted work in it can be discarded. Idempotent: a worktree whose\n * directory is already gone only has its metadata pruned.\n *\n * @param sandbox live sandbox containing the base checkout\n * @param repoWorkdir the base repo checkout path inside the sandbox\n * @param branch the worktree's feature branch (ref-validated)\n * @param worktreePath the persisted, server-computed worktree path\n */\nexport async function removeWorktree(\n sandbox: MaterializationSandbox,\n repoWorkdir: string,\n { branch, worktreePath }: { branch: string; worktreePath: string },\n): Promise<void> {\n if (!isValidGitRef(branch)) {\n throw new WorktreeError(`Invalid branch name '${branch}'.`, 'invalid-branch');\n }\n\n const remove = await sh(\n sandbox,\n `git -C ${shellQuote(repoWorkdir)} worktree remove --force ${shellQuote(worktreePath)}`,\n );\n if (remove.exitCode !== 0) {\n // Tolerate a checkout that's already gone (e.g. a fresh sandbox after\n // re-provisioning): prune stale metadata and only fail when the directory\n // still exists, meaning git genuinely refused to remove it.\n await sh(sandbox, `git -C ${shellQuote(repoWorkdir)} worktree prune`);\n const exists = await sh(sandbox, `test -e ${shellQuote(worktreePath)}`);\n if (exists.exitCode === 0) {\n throw new WorktreeError(\n `git worktree remove failed: ${remove.stderr.trim() || remove.stdout.trim()}`,\n 'worktree-failed',\n );\n }\n }\n\n // Best-effort local branch cleanup; the branch may not exist locally anymore\n // or may still be pushed remotely — neither should fail the removal.\n await sh(sandbox, `git -C ${shellQuote(repoWorkdir)} branch -D ${shellQuote(branch)}`);\n}\n\n// ---------------------------------------------------------------------------\n// Phase 3 — `gh` CLI pull-request creation primitive\n//\n// PRs are opened from inside the sandbox with the GitHub CLI. `gh` must be\n// present in the sandbox template (preflighted only on the PR path so clone /\n// open still work when it is absent). The token is passed to `gh` via a\n// per-invocation `GH_TOKEN` env that is scoped to the single `gh` process and\n// never written to git config, a shell rc, or the VM's environment.\n// ---------------------------------------------------------------------------\n\nexport interface CreatePullRequestArgs {\n /** Short-lived installation token, injected only into the `gh` process env. */\n token: string;\n /** Base branch the PR merges into. Ref-validated. */\n base: string;\n /** Head branch the PR is opened from. Ref-validated. */\n head: string;\n /** PR title. */\n title: string;\n /** PR body (optional). */\n body?: string;\n}\n\nexport interface CreatePullRequestResult {\n /** The PR URL parsed from `gh pr create` stdout. */\n url: string;\n}\n\n/**\n * Preflight that `gh` is installed in the sandbox. Only called on the PR path so\n * a missing `gh` never blocks clone/open. Surfaces an actionable error naming\n * the sandbox template requirement.\n */\nasync function assertGhAvailable(sandbox: MaterializationSandbox): Promise<void> {\n const version = await sh(sandbox, 'gh --version');\n if (version.exitCode !== 0) {\n throw new MaterializeError(\n 'The GitHub CLI (gh) is not installed in the sandbox. The sandbox template must include gh to open pull requests.',\n 'gh-missing',\n );\n }\n}\n\n/** Match the first GitHub PR URL in `gh pr create` output. */\nfunction parsePullRequestUrl(stdout: string): string | undefined {\n const match = stdout.match(/https:\\/\\/github\\.com\\/[^\\s]+\\/pull\\/\\d+/);\n return match?.[0];\n}\n\n/**\n * Open a pull request from inside the sandbox via `gh pr create`. The token is\n * passed only through a per-invocation `GH_TOKEN` env scoped to the single `gh`\n * process (never persisted), all arguments are shell-quoted, and the resulting\n * PR URL is parsed from stdout.\n *\n * @param sandbox live sandbox containing the checkout\n * @param workdir the worktree (or repo) path the PR head branch is checked out in\n */\nexport async function createPullRequest(\n sandbox: MaterializationSandbox,\n workdir: string,\n { token, base, head, title, body }: CreatePullRequestArgs,\n): Promise<CreatePullRequestResult> {\n if (!isValidGitRef(base)) {\n throw new MaterializeError(`Refusing to open PR: invalid base branch '${base}'.`, 'pr-failed');\n }\n if (!isValidGitRef(head)) {\n throw new MaterializeError(`Refusing to open PR: invalid head branch '${head}'.`, 'pr-failed');\n }\n\n await assertGhAvailable(sandbox);\n\n // GH_TOKEN is prefixed inline so it is exported only to the single `gh`\n // process and never to the wider shell session, git config, or VM env. `gh`\n // is run from inside the checkout so it targets the correct repo/head branch.\n const ghCommand = [\n `GH_TOKEN=${shellQuote(token)} gh pr create`,\n `--base ${shellQuote(base)}`,\n `--head ${shellQuote(head)}`,\n `--title ${shellQuote(title)}`,\n `--body ${shellQuote(body ?? '')}`,\n ].join(' ');\n const script = `cd ${shellQuote(workdir)} && ${ghCommand}`;\n\n const result = await sh(sandbox, script);\n if (result.exitCode !== 0) {\n const classified = classifyGitFailure(result, 'push-failed');\n if (classified.code === 'egress-blocked') {\n throw classified;\n }\n throw new MaterializeError(`gh pr create failed: ${result.stderr.trim() || result.stdout.trim()}`, 'pr-failed');\n }\n\n const url = parsePullRequestUrl(result.stdout);\n if (!url) {\n throw new MaterializeError(\n `gh pr create succeeded but no PR URL was found in its output: ${result.stdout.trim()}`,\n 'pr-failed',\n );\n }\n\n return { url };\n}\n","import type { IntegrationStorageHandle, IntegrationSubscription } from '../../storage/domains/integrations/base.js';\n\nexport type GithubSignalSubscriptionSource = 'auto-gh-pr-create' | 'factory-pr-create' | 'explicit-tool';\nexport type GithubSignalSubscriptionStatus = 'open' | 'closed' | 'merged';\n\nexport interface GithubSignalSubscriptionData {\n installationExternalId: string;\n projectRepositoryId: string;\n repositoryExternalId: string;\n repositorySlug: string;\n changeRequestId: string;\n ownerId: string;\n source: GithubSignalSubscriptionSource;\n subscribedByUserId: string | null;\n}\n\nexport type GithubSignalSubscriptionRow = IntegrationSubscription<GithubSignalSubscriptionData>;\nexport type GithubSubscriptionStorage = IntegrationStorageHandle<\n Record<string, unknown>,\n Record<string, unknown>,\n GithubSignalSubscriptionData\n>;\n\nexport interface SubscribeToPullRequestInput {\n orgId: string;\n installationExternalId: string;\n projectRepositoryId: string;\n repositoryExternalId: string;\n repositorySlug: string;\n changeRequestId: string;\n sessionId: string;\n ownerId: string;\n resourceId: string;\n threadId: string;\n sessionScope?: string;\n source: GithubSignalSubscriptionSource;\n subscribedByUserId?: string;\n}\n\nexport interface ThreadSubscriptionTarget {\n orgId: string;\n resourceId: string;\n threadId: string;\n sessionScope?: string;\n}\n\nexport interface PullRequestSubscriptionTarget {\n orgId: string;\n installationExternalId: string;\n repositoryExternalId: string;\n changeRequestId: string;\n}\n\nexport type GithubWebhookPullRequestTarget = Omit<PullRequestSubscriptionTarget, 'orgId'>;\n\nexport function changeRequestTargetKey(input: GithubWebhookPullRequestTarget): string {\n return `change-request:${input.installationExternalId}:${input.repositoryExternalId}:${input.changeRequestId}`;\n}\n\nfunction sameSession(row: GithubSignalSubscriptionRow, input: SubscribeToPullRequestInput): boolean {\n return (\n row.orgId === input.orgId &&\n row.sessionId === input.sessionId &&\n row.resourceId === input.resourceId &&\n row.threadId === input.threadId &&\n (row.sessionScope ?? '') === (input.sessionScope ?? '')\n );\n}\n\nexport async function subscribeToPullRequest(\n input: SubscribeToPullRequestInput,\n storage: GithubSubscriptionStorage,\n): Promise<GithubSignalSubscriptionRow> {\n const targetKey = changeRequestTargetKey(input);\n const existing = (await storage.subscriptions.listByTarget(targetKey)).find(row => sameSession(row, input));\n if (existing) {\n if (existing.status !== 'open') await storage.subscriptions.updateStatus(existing.id, 'open');\n return { ...existing, status: 'open' };\n }\n\n return storage.subscriptions.create({\n orgId: input.orgId,\n targetKey,\n sessionId: input.sessionId,\n resourceId: input.resourceId,\n threadId: input.threadId,\n sessionScope: input.sessionScope ?? '',\n status: 'open',\n data: {\n installationExternalId: input.installationExternalId,\n projectRepositoryId: input.projectRepositoryId,\n repositoryExternalId: input.repositoryExternalId,\n repositorySlug: input.repositorySlug,\n changeRequestId: input.changeRequestId,\n ownerId: input.ownerId,\n source: input.source,\n subscribedByUserId: input.subscribedByUserId ?? null,\n },\n });\n}\n\nexport async function unsubscribeFromPullRequest(\n input: SubscribeToPullRequestInput,\n storage: GithubSubscriptionStorage,\n): Promise<void> {\n const rows = await storage.subscriptions.listByTarget(changeRequestTargetKey(input));\n await Promise.all(rows.filter(row => sameSession(row, input)).map(row => storage.subscriptions.delete(row.id)));\n}\n\nexport async function listPullRequestSubscriptionsForThread(\n input: ThreadSubscriptionTarget,\n storage: GithubSubscriptionStorage,\n): Promise<GithubSignalSubscriptionRow[]> {\n const rows = await storage.subscriptions.listByThread(input.resourceId, input.threadId);\n return rows.filter(\n row =>\n row.orgId === input.orgId &&\n row.resourceId === input.resourceId &&\n row.threadId === input.threadId &&\n (row.sessionScope ?? '') === (input.sessionScope ?? ''),\n );\n}\n\nexport async function listPullRequestSubscriptions(\n input: PullRequestSubscriptionTarget,\n storage: GithubSubscriptionStorage,\n): Promise<GithubSignalSubscriptionRow[]> {\n const rows = await storage.subscriptions.listByTarget(changeRequestTargetKey(input));\n return rows.filter(row => row.orgId === input.orgId && row.status === 'open');\n}\n\nexport async function listPullRequestSubscriptionsForWebhook(\n input: GithubWebhookPullRequestTarget,\n options: { includeTerminal?: boolean } | undefined,\n storage: GithubSubscriptionStorage,\n): Promise<GithubSignalSubscriptionRow[]> {\n const rows = await storage.subscriptions.listByTarget(changeRequestTargetKey(input));\n return options?.includeTerminal ? rows : rows.filter(row => row.status === 'open');\n}\n\nexport function retirePullRequestSubscription(\n id: string,\n status: GithubSignalSubscriptionStatus,\n storage: GithubSubscriptionStorage,\n): Promise<void> {\n return storage.subscriptions.updateStatus(id, status);\n}\n\nexport async function retirePullRequestSubscriptions(\n input: PullRequestSubscriptionTarget,\n storage: GithubSubscriptionStorage,\n): Promise<void> {\n const rows = await listPullRequestSubscriptions(input, storage);\n await Promise.all(rows.map(row => storage.subscriptions.updateStatus(row.id, 'closed')));\n}\n","import { createHmac, timingSafeEqual } from 'node:crypto';\nimport type { MountedMastraCode } from '@mastra/code-sdk';\nimport type { NotificationPriority } from '@mastra/core/notifications';\nimport type { Context } from 'hono';\nimport type { GithubIntegration } from './integration.js';\nimport type { GithubIssueTriageInput, GithubIssueTriageResult } from './issue-triage.js';\nimport { listPullRequestSubscriptionsForWebhook, retirePullRequestSubscription } from './subscriptions.js';\nimport type { GithubSignalSubscriptionRow, GithubWebhookPullRequestTarget } from './subscriptions.js';\n\nexport type GithubIssueTriageRunInput = GithubIssueTriageInput;\nexport type GithubIssueTriageRunResult = GithubIssueTriageResult;\n\nexport interface GithubWebhookHandlerOptions {\n /** Integration providing webhook-secret verification + collaborator permission checks. */\n github: GithubIntegration;\n runIssueTriage?: (input: GithubIssueTriageRunInput) => Promise<GithubIssueTriageRunResult>;\n ingestFactoryEvent?: (event: ParsedGithubWebhook) => Promise<unknown>;\n}\n\nconst SUPPORTED_GITHUB_WEBHOOK_EVENTS = new Set([\n 'issues',\n 'issue_comment',\n 'pull_request',\n 'pull_request_review',\n 'pull_request_review_comment',\n]);\n\nexport interface GithubWebhookMetadata {\n event: string;\n action?: string;\n deliveryId: string;\n repository?: string;\n repositoryId?: number;\n issueNumber?: number;\n pullRequestNumber?: number;\n sender?: string;\n senderType?: string;\n installationId?: number;\n}\n\nexport interface ParsedGithubWebhook {\n event: string;\n deliveryId: string;\n payload: Record<string, unknown>;\n}\n\nexport type GithubWebhookResult =\n | { status: 202; body: { ok: true; ignored?: true } }\n | { status: 400; body: { error: 'bad_request'; message: string } }\n | { status: 401; body: { error: 'unauthorized'; message: string } };\n\nexport interface GithubWebhookNotification {\n action: string;\n kind: string;\n priority: NotificationPriority;\n summary: string;\n terminal: boolean;\n metadata: GithubWebhookMetadata & { pullRequestNumber: number; repositoryId: number; installationId: number };\n payload: Record<string, unknown>;\n}\n\nexport interface GithubWebhookDispatchDependencies {\n controller: MountedMastraCode['controller'];\n /**\n * Integration used by the default sender-authorization check (collaborator\n * permission lookup). Author-gated notifications fail closed when neither\n * this nor an `isAuthorizedSender` override is supplied.\n */\n github?: GithubIntegration;\n listSubscriptions?: (\n target: GithubWebhookPullRequestTarget,\n options?: { includeTerminal?: boolean },\n ) => Promise<GithubSignalSubscriptionRow[]>;\n retireSubscription?: (id: string, status: 'open' | 'closed' | 'merged') => Promise<void>;\n isAuthorizedSender?: (notification: GithubWebhookNotification) => Promise<boolean>;\n onTargetError?: (subscription: GithubSignalSubscriptionRow, error: unknown) => void;\n}\n\nfunction normalizeHeader(value: string | undefined | null): string | null {\n if (!value) return null;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction verifySignature(rawBody: string, signature: string, secret: string): boolean {\n if (!signature.startsWith('sha256=')) return false;\n const signatureHex = signature.slice('sha256='.length);\n if (!/^[a-fA-F0-9]{64}$/.test(signatureHex)) return false;\n\n const expectedHex = createHmac('sha256', secret).update(rawBody).digest('hex');\n const received = Buffer.from(signatureHex, 'hex');\n const expected = Buffer.from(expectedHex, 'hex');\n return received.length === expected.length && timingSafeEqual(received, expected);\n}\n\nasync function parseGithubWebhook(\n c: Context,\n secret: string | undefined,\n): Promise<ParsedGithubWebhook | GithubWebhookResult> {\n if (!secret) {\n return { status: 401, body: { error: 'unauthorized', message: 'GitHub webhook secret is not configured' } };\n }\n\n const event = normalizeHeader(c.req.header('x-github-event'));\n const deliveryId = normalizeHeader(c.req.header('x-github-delivery'));\n const signature = normalizeHeader(c.req.header('x-hub-signature-256'));\n\n if (!event) return { status: 400, body: { error: 'bad_request', message: 'Missing x-github-event header' } };\n if (!deliveryId) return { status: 400, body: { error: 'bad_request', message: 'Missing x-github-delivery header' } };\n if (!signature)\n return { status: 401, body: { error: 'unauthorized', message: 'Missing x-hub-signature-256 header' } };\n\n const rawBody = await c.req.text();\n if (!verifySignature(rawBody, signature, secret)) {\n return { status: 401, body: { error: 'unauthorized', message: 'Invalid GitHub webhook signature' } };\n }\n\n let payload: unknown;\n try {\n payload = JSON.parse(rawBody);\n } catch {\n return { status: 400, body: { error: 'bad_request', message: 'Malformed JSON payload' } };\n }\n\n if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {\n return { status: 400, body: { error: 'bad_request', message: 'Payload must be a JSON object' } };\n }\n\n return { event, deliveryId, payload: payload as Record<string, unknown> };\n}\n\nfunction getObject(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === 'object' && !Array.isArray(value) ? (value as Record<string, unknown>) : undefined;\n}\n\nfunction getString(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction getNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction getBoolean(value: unknown): boolean | undefined {\n return typeof value === 'boolean' ? value : undefined;\n}\n\nfunction getLabels(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value\n .map(label => (typeof label === 'string' ? label : getString(getObject(label)?.name)))\n .filter((label): label is string => Boolean(label));\n}\n\nfunction getIssueTriageRunInput(parsed: ParsedGithubWebhook): GithubIssueTriageRunInput | null {\n if (parsed.event !== 'issues' || getString(parsed.payload.action) !== 'opened') return null;\n const repository = getString(getObject(parsed.payload.repository)?.full_name);\n const issue = getObject(parsed.payload.issue);\n const sender = getString(getObject(parsed.payload.sender)?.login);\n const installationId = getNumber(getObject(parsed.payload.installation)?.id);\n const issueNumber = getNumber(issue?.number);\n const issueTitle = getString(issue?.title);\n const issueUrl = getString(issue?.html_url);\n if (!repository || !installationId || !issueNumber || !issueTitle || !issueUrl) return null;\n return {\n repository,\n issueNumber,\n issueTitle,\n issueUrl,\n labels: getLabels(issue?.labels),\n sender,\n installationId,\n };\n}\n\nexport function normalizeGithubWebhookMetadata(parsed: ParsedGithubWebhook): GithubWebhookMetadata {\n const { event, deliveryId, payload } = parsed;\n const repository = getObject(payload.repository);\n const issue = getObject(payload.issue);\n const pullRequest = getObject(payload.pull_request);\n const sender = getObject(payload.sender);\n const installation = getObject(payload.installation);\n const issuePullRequest = getObject(issue?.pull_request);\n\n return {\n event,\n action: getString(payload.action),\n deliveryId,\n repository: getString(repository?.full_name),\n repositoryId: getNumber(repository?.id),\n issueNumber: getNumber(issue?.number),\n pullRequestNumber:\n getNumber(pullRequest?.number) ??\n (event === 'issue_comment' && issuePullRequest ? getNumber(issue?.number) : undefined),\n sender: getString(sender?.login),\n senderType: getString(sender?.type),\n installationId: getNumber(installation?.id),\n };\n}\n\nfunction notificationSummary(metadata: GithubWebhookMetadata, label: string): string {\n const actor = metadata.sender ? `${metadata.sender} ` : '';\n return `${actor}${label} on ${metadata.repository}#${metadata.pullRequestNumber}`;\n}\n\nfunction notificationTargetUrl(event: string, payload: Record<string, unknown>): string | undefined {\n if (event === 'issue_comment' || event === 'pull_request_review_comment') {\n return getString(getObject(payload.comment)?.html_url);\n }\n if (event === 'pull_request_review') {\n return getString(getObject(payload.review)?.html_url);\n }\n return getString(getObject(payload.pull_request)?.html_url);\n}\n\nexport function classifyGithubWebhook(parsed: ParsedGithubWebhook): GithubWebhookNotification | undefined {\n const metadata = normalizeGithubWebhookMetadata(parsed);\n const { event, payload } = parsed;\n const action = metadata.action;\n if (\n !action ||\n !metadata.repositoryId ||\n !metadata.installationId ||\n !metadata.pullRequestNumber ||\n !metadata.repository\n ) {\n return undefined;\n }\n\n let priority: NotificationPriority;\n let kind: string;\n let label: string;\n let terminal = false;\n\n if (event === 'pull_request_review' && action === 'submitted') {\n const state = getString(getObject(payload.review)?.state)?.toLowerCase().replaceAll('_', '-');\n priority = state === 'approved' || state === 'changes-requested' ? 'urgent' : 'high';\n kind =\n state === 'approved'\n ? 'review-approved'\n : state === 'changes-requested'\n ? 'review-changes-requested'\n : 'review-submitted';\n label =\n state === 'approved'\n ? 'approved the pull request'\n : state === 'changes-requested'\n ? 'requested changes'\n : 'submitted a review';\n } else if (event === 'pull_request' && action === 'closed') {\n const merged = getBoolean(getObject(payload.pull_request)?.merged) === true;\n priority = 'urgent';\n kind = merged ? 'pull-request-merged' : 'pull-request-closed';\n label = merged ? 'merged the pull request' : 'closed the pull request';\n terminal = true;\n } else if (event === 'issue_comment' && action === 'created') {\n priority = 'high';\n kind = 'issue-comment-created';\n label = 'commented';\n } else if (event === 'pull_request_review_comment' && action === 'created') {\n priority = 'high';\n kind = 'review-comment-created';\n label = 'left a review comment';\n } else if (event === 'pull_request' && action === 'reopened') {\n priority = 'high';\n kind = 'pull-request-reopened';\n label = 'reopened the pull request';\n } else if (event === 'pull_request_review' && action === 'dismissed') {\n priority = 'high';\n kind = 'review-dismissed';\n label = 'dismissed a review';\n } else if (\n event === 'pull_request' &&\n [\n 'synchronize',\n 'ready_for_review',\n 'converted_to_draft',\n 'assigned',\n 'unassigned',\n 'review_requested',\n 'review_request_removed',\n ].includes(action)\n ) {\n priority = 'medium';\n kind = `pull-request-${action.replaceAll('_', '-')}`;\n label = action.replaceAll('_', ' ');\n } else if (\n event === 'pull_request' &&\n ['edited', 'labeled', 'unlabeled', 'milestoned', 'demilestoned'].includes(action)\n ) {\n priority = 'low';\n kind = `pull-request-${action.replaceAll('_', '-')}`;\n label = action.replaceAll('_', ' ');\n } else {\n return undefined;\n }\n\n return {\n action,\n kind,\n priority,\n summary: notificationSummary(metadata, label),\n terminal,\n metadata: {\n ...metadata,\n pullRequestNumber: metadata.pullRequestNumber,\n repositoryId: metadata.repositoryId,\n installationId: metadata.installationId,\n },\n payload,\n };\n}\n\nasync function resolveSubscriptionSession(\n controller: MountedMastraCode['controller'],\n subscription: GithubSignalSubscriptionRow,\n) {\n const { sessionId, resourceId, threadId } = subscription;\n if (!sessionId || !resourceId || !threadId) {\n throw new Error(`GitHub subscription ${subscription.id} is missing its session binding.`);\n }\n const scope = subscription.sessionScope || undefined;\n let session = await controller.getSessionByResource(resourceId, scope);\n if (!session) {\n const tags = {\n factoryProjectId: resourceId,\n projectRepositoryId: subscription.data.projectRepositoryId,\n ...(scope ? { worktreePath: scope } : {}),\n };\n session = await controller.createSession({\n id: sessionId,\n ownerId: subscription.data.ownerId,\n resourceId,\n scope,\n tags,\n });\n }\n if (session.thread.getId() !== threadId) {\n await session.thread.switch({ threadId, emitEvent: false });\n }\n if (session.thread.getId() !== threadId) {\n throw new Error(`Session ${sessionId} did not bind thread ${threadId}.`);\n }\n return session;\n}\n\nconst AUTHORIZED_BOTS = new Set(['coderabbitai[bot]', 'devin-ai-integration[bot]']);\nconst AUTHORIZED_PERMISSIONS = new Set(['admin', 'maintain', 'write']);\nconst PERMISSION_CHECK_TIMEOUT_MS = 5_000;\nconst AUTHOR_GATED_KINDS = new Set([\n 'issue-comment-created',\n 'review-comment-created',\n 'review-submitted',\n 'review-approved',\n 'review-changes-requested',\n 'review-dismissed',\n]);\n\nasync function isAuthorizedGithubSender(\n notification: GithubWebhookNotification,\n github: GithubIntegration | undefined,\n): Promise<boolean> {\n if (!AUTHOR_GATED_KINDS.has(notification.kind)) return true;\n const sender = notification.metadata.sender;\n const repository = notification.metadata.repository;\n if (!sender || !repository) return false;\n const normalizedSender = sender.toLowerCase();\n if (notification.metadata.senderType?.toLowerCase() === 'bot' || normalizedSender.endsWith('[bot]')) {\n return AUTHORIZED_BOTS.has(normalizedSender);\n }\n if (!github) return false;\n const abortController = new AbortController();\n let timeout: ReturnType<typeof setTimeout> | undefined;\n try {\n const permission = await Promise.race([\n github.getRepositoryCollaboratorPermission(\n notification.metadata.installationId,\n repository,\n sender,\n abortController.signal,\n ),\n new Promise<undefined>(resolve => {\n timeout = setTimeout(() => {\n abortController.abort();\n resolve(undefined);\n }, PERMISSION_CHECK_TIMEOUT_MS);\n }),\n ]);\n return permission !== undefined && AUTHORIZED_PERMISSIONS.has(permission);\n } catch {\n return false;\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n}\n\nexport async function dispatchGithubWebhook(\n parsed: ParsedGithubWebhook,\n dependencies: GithubWebhookDispatchDependencies,\n): Promise<{ delivered: number; failed: number; ignored: boolean }> {\n const notification = classifyGithubWebhook(parsed);\n if (!notification) return { delivered: 0, failed: 0, ignored: true };\n const isAuthorizedSender =\n dependencies.isAuthorizedSender ??\n ((n: GithubWebhookNotification) => isAuthorizedGithubSender(n, dependencies.github));\n if (!(await isAuthorizedSender(notification))) {\n return { delivered: 0, failed: 0, ignored: true };\n }\n\n const target = {\n installationExternalId: notification.metadata.installationId.toString(),\n repositoryExternalId: notification.metadata.repositoryId.toString(),\n changeRequestId: notification.metadata.pullRequestNumber.toString(),\n };\n const listSubscriptions =\n dependencies.listSubscriptions ??\n ((subscriptionTarget: GithubWebhookPullRequestTarget, options?: { includeTerminal?: boolean }) => {\n if (!dependencies.github) throw new Error('GitHub integration is required to load webhook subscriptions.');\n return listPullRequestSubscriptionsForWebhook(\n subscriptionTarget,\n options,\n dependencies.github.integrationStorage,\n );\n });\n const retireSubscription =\n dependencies.retireSubscription ??\n ((id: string, status: 'open' | 'closed' | 'merged') => {\n if (!dependencies.github) throw new Error('GitHub integration is required to retire webhook subscriptions.');\n return retirePullRequestSubscription(id, status, dependencies.github.integrationStorage);\n });\n const subscriptions = await listSubscriptions(target, { includeTerminal: notification.action === 'reopened' });\n let delivered = 0;\n let failed = 0;\n\n for (const subscription of subscriptions) {\n try {\n const session = await resolveSubscriptionSession(dependencies.controller, subscription);\n const result = await session.sendNotificationSignal({\n source: 'github',\n kind: notification.kind,\n summary: notification.summary,\n priority: notification.priority,\n payload: notification.payload,\n sourceId: parsed.deliveryId,\n dedupeKey: `${parsed.deliveryId}:${subscription.sessionId}:${subscription.threadId}`,\n coalesceKey: `github:${subscription.data.repositoryExternalId}:pull-request:${subscription.data.changeRequestId}`,\n metadata: {\n event: notification.metadata.event,\n action: notification.action,\n repository: notification.metadata.repository,\n issueNumber: notification.metadata.issueNumber,\n pullRequestNumber: notification.metadata.pullRequestNumber,\n targetUrl: notificationTargetUrl(parsed.event, parsed.payload),\n deliveryId: parsed.deliveryId,\n },\n });\n await Promise.all([result.persisted, result.accepted].filter(Boolean));\n if (notification.terminal) {\n await retireSubscription(subscription.id, notification.kind === 'pull-request-merged' ? 'merged' : 'closed');\n } else if (notification.action === 'reopened') {\n await retireSubscription(subscription.id, 'open');\n }\n delivered += 1;\n } catch (error) {\n failed += 1;\n dependencies.onTargetError?.(subscription, error);\n }\n }\n\n return { delivered, failed, ignored: false };\n}\n\nexport async function handleGithubWebhook(\n c: Context,\n options: GithubWebhookHandlerOptions & Partial<Omit<GithubWebhookDispatchDependencies, 'github'>>,\n): Promise<GithubWebhookResult> {\n const parsed = await parseGithubWebhook(c, options.github.webhookSecret);\n if ('status' in parsed) return parsed;\n\n if (!SUPPORTED_GITHUB_WEBHOOK_EVENTS.has(parsed.event)) {\n return { status: 202, body: { ok: true, ignored: true } };\n }\n\n const metadata = normalizeGithubWebhookMetadata(parsed);\n console.info('[GitHub Webhook]', metadata);\n\n if (options.ingestFactoryEvent) {\n await options.ingestFactoryEvent(parsed);\n } else {\n const issueTriageRun = getIssueTriageRunInput(parsed);\n if (issueTriageRun && options.runIssueTriage) {\n void options.runIssueTriage(issueTriageRun).catch((error: unknown) => {\n console.error('[GitHub Webhook] Failed to run issue triage', {\n deliveryId: metadata.deliveryId,\n repository: metadata.repository,\n issueNumber: metadata.issueNumber,\n error: error instanceof Error ? error.message : String(error),\n });\n });\n }\n }\n\n if (!options.controller) {\n return { status: 202, body: { ok: true } };\n }\n\n const result = await dispatchGithubWebhook(parsed, options as GithubWebhookDispatchDependencies);\n if (result.failed > 0) {\n console.warn(`[GitHub Webhook] ${result.failed} subscribed target(s) failed for delivery ${parsed.deliveryId}.`);\n }\n return { status: 202, body: { ok: true, ...(result.ignored ? { ignored: true as const } : {}) } };\n}\n","import type { AgentControllerRequestContext } from '@mastra/core/agent-controller';\nimport type { RequestContext } from '@mastra/core/request-context';\nimport { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\nimport type {\n ProjectRepository,\n ProjectSourceControlConnection,\n SourceControlInstallation,\n SourceControlRepository,\n} from '../../storage/domains/source-control/base.js';\nimport type { GithubIntegration } from './integration.js';\nimport { getGithubPat } from './pat.js';\nimport { subscribeToPullRequest, unsubscribeFromPullRequest } from './subscriptions.js';\nimport { getRegisteredGithubPatKind, injectGithubToken } from './token-refresh.js';\n\ntype RepositorySessionState = { factoryProjectId?: string; projectRepositoryId?: string };\n\n/**\n * Minimal shape of the host-authenticated user placed on the request context\n * under the `user` key. Mirrors the host's auth user without importing it:\n * `workosId` (stable external id) wins over the row `id`, and `organizationId`\n * scopes org tenancy.\n */\ninterface SessionAuthUser {\n workosId?: string;\n id?: string;\n organizationId?: string;\n}\n\nfunction sessionUserId(user: SessionAuthUser | undefined): string | undefined {\n return user?.workosId ?? user?.id;\n}\n\nfunction sessionOrgId(user: SessionAuthUser | undefined): string | undefined {\n return user?.organizationId;\n}\n\nconst pullRequestInputSchema = z.object({\n pullRequest: z.union([z.number().int().positive(), z.string().min(1)]),\n});\n\ninterface SessionTarget {\n context: AgentControllerRequestContext<RepositorySessionState>;\n projectRepository: ProjectRepository;\n connection: ProjectSourceControlConnection;\n installation: SourceControlInstallation;\n repository: SourceControlRepository;\n orgId: string;\n userId: string;\n}\n\nfunction parsePullRequest(value: number | string, expectedRepo: string): number {\n if (typeof value === 'number') return value;\n if (/^\\d+$/.test(value)) return Number(value);\n const match = value.match(/^https:\\/\\/github\\.com\\/([^/]+\\/[^/]+)\\/pull\\/(\\d+)\\/?$/i);\n if (!match || match[1]!.toLowerCase() !== expectedRepo.toLowerCase()) {\n throw new Error(`Pull request must belong to ${expectedRepo}.`);\n }\n return Number(match[2]);\n}\n\n/**\n * Whether the current request comes from a session that GitHub subscriptions\n * can ever apply to: an authenticated org user on a GitHub-project session\n * with an active thread. Mirrors the gate in `resolveSessionTarget` without\n * throwing, for passive callers that should no-op instead of erroring.\n */\nfunction isGithubProjectSession(requestContext: RequestContext): boolean {\n const context = requestContext.get('controller') as AgentControllerRequestContext<RepositorySessionState> | undefined;\n const user = requestContext.get('user') as SessionAuthUser | undefined;\n return Boolean(\n context?.threadId && context.getState().projectRepositoryId && sessionOrgId(user) && sessionUserId(user),\n );\n}\n\nasync function resolveSessionTarget(requestContext: RequestContext, github: GithubIntegration): Promise<SessionTarget> {\n const context = requestContext.get('controller') as AgentControllerRequestContext<RepositorySessionState> | undefined;\n const user = requestContext.get('user') as SessionAuthUser | undefined;\n const orgId = sessionOrgId(user);\n const userId = sessionUserId(user);\n const projectRepositoryId = context?.getState().projectRepositoryId;\n if (!context || !context.threadId || !projectRepositoryId || !orgId || !userId) {\n throw new Error('GitHub subscriptions require an authenticated repository session with an active thread.');\n }\n\n const projectRepository = await github.sourceControlStorage.projectRepositories.get({\n orgId,\n id: projectRepositoryId,\n });\n if (!projectRepository) throw new Error('Project repository not found for this organization.');\n const connection = await github.sourceControlStorage.connections.get({ orgId, id: projectRepository.connectionId });\n if (!connection) throw new Error('Source-control connection not found for this organization.');\n const repository = await github.sourceControlStorage.repositories.get({ orgId, id: projectRepository.repositoryId });\n if (!repository) throw new Error('Repository not found for this organization.');\n const installation = await github.sourceControlStorage.installations.get({ orgId, id: connection.installationId });\n if (!installation) throw new Error('Source-control installation not found for this organization.');\n return { context, projectRepository, connection, installation, repository, orgId, userId };\n}\n\nasync function verifyPullRequest(target: SessionTarget, pullRequest: number, github: GithubIntegration) {\n const [owner, repo] = target.repository.slug.split('/');\n if (!owner || !repo) throw new Error('GitHub repository is invalid.');\n const octokit = github.getInstallationOctokit(Number(target.installation.externalId));\n const { data } = await octokit.pulls.get({ owner, repo, pull_number: pullRequest });\n if (String(data.base.repo.id) !== target.repository.externalId)\n throw new Error('Pull request repository does not match the active project repository.');\n}\n\nasync function subscriptionInput(target: SessionTarget, pullRequestNumber: number) {\n return {\n orgId: target.orgId,\n installationExternalId: target.installation.externalId,\n projectRepositoryId: target.projectRepository.id,\n repositoryExternalId: target.repository.externalId,\n repositorySlug: target.repository.slug,\n changeRequestId: String(pullRequestNumber),\n sessionId: target.context.session.id,\n ownerId: target.context.session.ownerId,\n resourceId: target.connection.factoryProjectId,\n threadId: target.context.threadId!,\n sessionScope: target.context.scope,\n source: 'explicit-tool' as const,\n subscribedByUserId: target.userId,\n };\n}\n\nexport async function subscribeCurrentSessionToPullRequest(\n requestContext: RequestContext,\n pullRequest: number | string,\n source: 'auto-gh-pr-create' | 'explicit-tool',\n github: GithubIntegration,\n) {\n // The auto path observes every successful `gh pr create` in every session,\n // including local and non-GitHub-project sessions where subscriptions can\n // never apply. Skip silently there; only the explicit tool should surface\n // \"this session cannot subscribe\" as an error.\n if (source === 'auto-gh-pr-create' && !isGithubProjectSession(requestContext)) return undefined;\n const target = await resolveSessionTarget(requestContext, github);\n const number = parsePullRequest(pullRequest, target.repository.slug);\n await verifyPullRequest(target, number, github);\n await subscribeToPullRequest({ ...(await subscriptionInput(target, number)), source }, github.integrationStorage);\n return number;\n}\n\nexport async function unsubscribeCurrentSessionFromPullRequest(\n requestContext: RequestContext,\n pullRequest: number | string,\n github: GithubIntegration,\n) {\n const target = await resolveSessionTarget(requestContext, github);\n const number = parsePullRequest(pullRequest, target.repository.slug);\n await unsubscribeFromPullRequest(await subscriptionInput(target, number), github.integrationStorage);\n return number;\n}\n\nexport async function refreshGithubToken(requestContext: RequestContext, github: GithubIntegration): Promise<void> {\n const target = await resolveSessionTarget(requestContext, github);\n // `GH_TOKEN` feeds the `gh` CLI, so a configured org PAT wins over a minted\n // installation token (which 403s on integration-restricted endpoints). The\n // workspace records which PAT kind the sandbox was provisioned with, so a\n // review-board sandbox keeps its reviewer token on refresh.\n const pat = await getGithubPat(\n () => github.integrationStorage,\n target.orgId,\n getRegisteredGithubPatKind(requestContext),\n );\n if (pat) {\n injectGithubToken(requestContext, pat);\n return;\n }\n const access = await github.versionControl.getRepositoryAccess({\n orgId: target.orgId,\n repositoryId: target.repository.id,\n });\n const token = access.authorization?.token;\n if (!token) throw new Error('Repository access did not include a bearer token for the Factory session.');\n injectGithubToken(requestContext, token);\n}\n\nexport function createGithubSubscriptionTools(requestContext: RequestContext, github: GithubIntegration) {\n const context = requestContext.get('controller') as AgentControllerRequestContext<RepositorySessionState> | undefined;\n const user = requestContext.get('user') as SessionAuthUser | undefined;\n if (!context?.getState().projectRepositoryId || !sessionOrgId(user) || !sessionUserId(user)) return {};\n\n return {\n github_refresh_token: createTool({\n id: 'github_refresh_token',\n description:\n 'Refresh GitHub CLI authentication in the active Factory sandbox. Use this after a gh command fails because authentication is expired, invalid, or missing. It installs a fresh GH_TOKEN for subsequent sandbox commands. After this tool succeeds, retry the failed gh command. Takes no arguments and never returns the token.',\n inputSchema: z.object({}),\n execute: async () => {\n await refreshGithubToken(requestContext, github);\n return { refreshed: true };\n },\n }),\n github_subscribe_pr: createTool({\n id: 'github_subscribe_pr',\n description:\n 'Subscribe this thread to GitHub pull request activity. You usually do not need this tool: successful gh pr create commands subscribe automatically. Use it for an existing PR or to recover when automatic subscription did not occur. Closed or merged PRs are unsubscribed automatically. Accepts a PR number or canonical URL for the active project.',\n inputSchema: pullRequestInputSchema,\n execute: async ({ pullRequest }) => {\n const number = await subscribeCurrentSessionToPullRequest(requestContext, pullRequest, 'explicit-tool', github);\n return { subscribed: true, pullRequestNumber: number };\n },\n }),\n github_unsubscribe_pr: createTool({\n id: 'github_unsubscribe_pr',\n description:\n 'Manually unsubscribe this thread from GitHub pull request activity. You usually do not need this tool because closed or merged PRs are unsubscribed automatically. Use it to stop notifications before then. Accepts a PR number or canonical URL for the active project.',\n inputSchema: pullRequestInputSchema,\n execute: async ({ pullRequest }) => {\n const number = await unsubscribeCurrentSessionFromPullRequest(requestContext, pullRequest, github);\n return { subscribed: false, pullRequestNumber: number };\n },\n }),\n };\n}\n\nexport function stripHeredocBodies(command: string): string {\n const lines = command.split('\\n');\n const executableLines: string[] = [];\n let delimiter: string | undefined;\n\n for (const line of lines) {\n if (delimiter) {\n if (line.trim() === delimiter) delimiter = undefined;\n continue;\n }\n executableLines.push(line);\n const heredoc = line.match(/<<-?\\s*(['\"]?)([A-Za-z_][A-Za-z0-9_]*)\\1/);\n delimiter = heredoc?.[2];\n }\n\n return executableLines.join('\\n');\n}\n\nexport function parseCreatedPullRequest(context: {\n toolName: string;\n input: unknown;\n output?: unknown;\n error?: unknown;\n}) {\n if (context.toolName !== 'execute_command' || context.error) return undefined;\n const command = (context.input as { command?: unknown } | undefined)?.command;\n if (\n typeof command !== 'string' ||\n !/(?:^|\\n|;|&&|\\|\\|)\\s*gh\\s+pr\\s+create(?:\\s|$)/.test(stripHeredocBodies(command))\n ) {\n return undefined;\n }\n const output = context.output as { stdout?: unknown; result?: unknown } | undefined;\n const stdout = typeof context.output === 'string' ? context.output : (output?.stdout ?? output?.result);\n if (typeof stdout !== 'string') return undefined;\n const urls = stdout.match(/https:\\/\\/github\\.com\\/[^\\s/]+\\/[^\\s/]+\\/pull\\/\\d+/g) ?? [];\n return urls.length === 1 ? urls[0] : undefined;\n}\n","import type { RequestContext } from '@mastra/core/request-context';\n\nimport type { GithubPatKind } from './pat.js';\n\nconst GITHUB_TOKEN_INJECTOR_CONTEXT_KEY = 'factoryGithubTokenInjector';\nconst GITHUB_PAT_KIND_CONTEXT_KEY = 'factoryGithubPatKind';\n\ntype GithubTokenInjector = (token: string) => void;\n\nexport function registerGithubTokenInjector(requestContext: RequestContext, injector: GithubTokenInjector): void {\n requestContext.set(GITHUB_TOKEN_INJECTOR_CONTEXT_KEY, injector);\n}\n\n/** Record which PAT kind the active sandbox was provisioned with, so token\n * refresh re-injects the same credential (review-board sandboxes keep the\n * reviewer token instead of being clobbered with the worker token). */\nexport function registerGithubPatKind(requestContext: RequestContext, kind: GithubPatKind): void {\n requestContext.set(GITHUB_PAT_KIND_CONTEXT_KEY, kind);\n}\n\nexport function getRegisteredGithubPatKind(requestContext: RequestContext): GithubPatKind {\n const kind = requestContext.get(GITHUB_PAT_KIND_CONTEXT_KEY);\n return kind === 'reviewer' ? 'reviewer' : 'default';\n}\n\nexport function injectGithubToken(requestContext: RequestContext, token: string): void {\n const injector = requestContext.get(GITHUB_TOKEN_INJECTOR_CONTEXT_KEY) as GithubTokenInjector | undefined;\n if (!injector) {\n throw new Error('GitHub token refresh requires an active Factory sandbox workspace.');\n }\n injector(token);\n}\n","export interface PlatformApiClientConfig {\n baseUrl: string;\n accessToken: string;\n fetchImpl?: typeof fetch;\n}\n\nexport function platformApiClientConfigFromEnv(): PlatformApiClientConfig {\n const sharedApiUrl = process.env.MASTRA_SHARED_API_URL?.trim() || 'https://platform.mastra.ai/v1';\n const accessToken = process.env.MASTRA_PLATFORM_SECRET_KEY?.trim();\n if (!accessToken) {\n throw new Error('Platform integration: missing required environment variable MASTRA_PLATFORM_SECRET_KEY.');\n }\n return { baseUrl: normalizeSharedApiUrl(sharedApiUrl), accessToken };\n}\n\nfunction normalizeSharedApiUrl(sharedApiUrl: string): string {\n return sharedApiUrl.replace(/\\/+$/, '').replace(/\\/v1$/, '');\n}\n\nexport class PlatformApiError extends Error {\n readonly status: number;\n readonly retryAfterSeconds: number | null;\n\n constructor(message: string, status: number, retryAfterSeconds: number | null = null) {\n super(message);\n this.name = 'PlatformApiError';\n this.status = status;\n this.retryAfterSeconds = retryAfterSeconds;\n }\n}\n\nexport class PlatformApiClient {\n readonly #baseUrl: string;\n readonly #accessToken: string;\n readonly #fetch: typeof fetch;\n\n constructor(config: PlatformApiClientConfig) {\n const missing = ['baseUrl', 'accessToken'].filter(field => !config[field as keyof PlatformApiClientConfig]);\n if (missing.length > 0) {\n throw new Error(`Platform integration: missing required config field(s): ${missing.join(', ')}.`);\n }\n this.#baseUrl = config.baseUrl.replace(/\\/+$/, '');\n this.#accessToken = config.accessToken;\n this.#fetch = config.fetchImpl ?? globalThis.fetch;\n }\n\n async request<T>(\n method: string,\n path: string,\n body?: unknown,\n options?: { signal?: AbortSignal; actingUserId?: string },\n ): Promise<T> {\n const response = await this.#send(method, path, body, options);\n if (!response.ok) {\n const message = redact(await extractError(response), this.#accessToken);\n const retryAfterSeconds = parseRetryAfter(response.headers.get('retry-after'));\n logPlatformError('Platform API request failed', {\n method,\n path,\n status: response.status,\n retryAfterSeconds,\n message,\n });\n throw new PlatformApiError(message, response.status, retryAfterSeconds);\n }\n if (response.status === 204) return undefined as T;\n return (await response.json()) as T;\n }\n\n async requestRedirect(method: string, path: string, options?: { signal?: AbortSignal }): Promise<string> {\n const response = await this.#send(method, path, undefined, options, 'manual');\n if (response.status >= 300 && response.status < 400) {\n const location = response.headers.get('location');\n if (location) return location;\n }\n if (!response.ok) {\n const message = redact(await extractError(response), this.#accessToken);\n const retryAfterSeconds = parseRetryAfter(response.headers.get('retry-after'));\n logPlatformError('Platform API redirect request failed', {\n method,\n path,\n status: response.status,\n retryAfterSeconds,\n message,\n });\n throw new PlatformApiError(message, response.status, retryAfterSeconds);\n }\n logPlatformError('Platform API request did not return a redirect', { method, path, status: response.status });\n throw new PlatformApiError('Platform API request did not return a redirect.', response.status);\n }\n\n async #send(\n method: string,\n path: string,\n body?: unknown,\n options?: { signal?: AbortSignal; actingUserId?: string },\n redirect?: RequestInit['redirect'],\n ): Promise<Response> {\n const headers: Record<string, string> = {\n accept: 'application/json',\n authorization: `Bearer ${this.#accessToken}`,\n };\n // Acting end-user for platform GitHub writes: the platform resolves this\n // user's GitHub OAuth connection (org-scoped) so issues/PRs are authored\n // by the human instead of the App bot. Ignored by older platforms.\n if (options?.actingUserId) {\n headers['x-acting-user-id'] = options.actingUserId;\n }\n const timeoutSignal = AbortSignal.timeout(15_000);\n const init: RequestInit = {\n method,\n headers,\n redirect,\n signal: options?.signal ? AbortSignal.any([options.signal, timeoutSignal]) : timeoutSignal,\n };\n if (body !== undefined) {\n headers['content-type'] = 'application/json';\n init.body = JSON.stringify(body);\n }\n\n try {\n return await this.#fetch(`${this.#baseUrl}${path}`, init);\n } catch (error) {\n if (error instanceof Error && error.message.includes(this.#accessToken)) {\n const redacted = new Error(redact(error.message, this.#accessToken));\n redacted.name = error.name;\n logPlatformError('Platform API transport error', {\n method,\n path,\n name: redacted.name,\n message: redacted.message,\n });\n throw redacted;\n }\n logPlatformError('Platform API transport error', {\n method,\n path,\n name: error instanceof Error ? error.name : undefined,\n message: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n}\n\nasync function extractError(response: Response): Promise<string> {\n try {\n const data = (await response.clone().json()) as Record<string, unknown>;\n for (const field of ['detail', 'error', 'title']) {\n if (typeof data[field] === 'string' && data[field]) return data[field];\n }\n } catch {\n // Fall through to the status-based message.\n }\n return `Platform API request failed (${response.status})`;\n}\n\nfunction redact(message: string, accessToken: string): string {\n return message.split(accessToken).join('[REDACTED]');\n}\n\nexport function logPlatformInfo(message: string, fields?: Record<string, unknown>): void {\n writePlatformLog('info', message, fields);\n}\n\nexport function logPlatformWarn(message: string, fields?: Record<string, unknown>): void {\n writePlatformLog('warn', message, fields);\n}\n\nexport function logPlatformError(message: string, fields?: Record<string, unknown>): void {\n writePlatformLog('error', message, fields);\n}\n\nfunction writePlatformLog(level: 'info' | 'warn' | 'error', message: string, fields?: Record<string, unknown>): void {\n const metadata = fields ? ` ${JSON.stringify(stripUndefined(fields))}` : '';\n process.stderr.write(`[Mastra Factory] ${level.toUpperCase()} ${message}${metadata}\\n`);\n}\n\nfunction stripUndefined(fields: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(Object.entries(fields).filter(([, value]) => value !== undefined));\n}\n\nfunction parseRetryAfter(value: string | null): number | null {\n if (!value) return null;\n const seconds = Number.parseInt(value, 10);\n return Number.isSafeInteger(seconds) && seconds >= 0 ? seconds : null;\n}\n","import { randomUUID } from 'node:crypto';\n\nimport type { MountedMastraCode } from '@mastra/code-sdk';\nimport { isLeaseProvider, NoopLeaseProvider } from '@mastra/core/events';\nimport type { LeaseProvider, PubSub } from '@mastra/core/events';\nimport { MastraWorker } from '@mastra/core/worker';\nimport type { WorkerDeps } from '@mastra/core/worker';\n\nimport type { IntegrationStorageHandle } from '../../../storage/domains/integrations/base.js';\nimport type { GithubRepositoryPermission } from '../../github/integration.js';\nimport { listPullRequestSubscriptionsForWebhook, retirePullRequestSubscription } from '../../github/subscriptions.js';\nimport type { GithubSubscriptionStorage } from '../../github/subscriptions.js';\nimport { dispatchGithubWebhook } from '../../github/webhook.js';\nimport type { GithubWebhookNotification, ParsedGithubWebhook } from '../../github/webhook.js';\nimport type { PlatformApiClient } from '../api-client.js';\nimport { PlatformApiError } from '../api-client.js';\n\nconst API_PREFIX = '/v1/server/github-app';\nconst DEFAULT_POLL_INTERVAL_MS = 20_000;\nconst EVENT_PAGE_SIZE = 500;\nconst MIN_LEASE_TTL_MS = 30_000;\nconst CURSOR_ORG_ID = '__platform_github_event_worker__';\nconst CURSOR_USER_ID = 'worker';\nconst SUPPORTED_EVENTS = new Set([\n 'issues',\n 'issue_comment',\n 'pull_request',\n 'pull_request_review',\n 'pull_request_review_comment',\n]);\nconst AUTHOR_GATED_KINDS = new Set([\n 'issue-comment',\n 'pull-request-comment',\n 'pull-request-review',\n 'pull-request-review-comment',\n]);\nconst AUTHORIZED_BOTS = new Set(['coderabbitai[bot]', 'devin-ai-integration[bot]']);\nconst AUTHORIZED_PERMISSIONS = new Set<GithubRepositoryPermission>(['admin', 'maintain', 'write']);\nconst PERMISSION_CHECK_TIMEOUT_MS = 5_000;\n\ntype EventCursor = { afterEventId: string } | { afterTimestamp: number };\ntype PlatformGithubEventWorkerSettings = {\n version: 1;\n repositories: Record<string, EventCursor>;\n};\n\nexport type PlatformGithubEventStorage = IntegrationStorageHandle<\n Record<string, unknown>,\n PlatformGithubEventWorkerSettings,\n Record<string, unknown>\n>;\n\ntype EventLogEntry = {\n id: string;\n deliveryId: string;\n event: string;\n payload: unknown;\n};\n\ntype Repository = { id: number };\n\nexport interface PlatformGithubEventDispatchIntegration {\n readonly integrationStorage: GithubSubscriptionStorage;\n getRepositoryCollaboratorPermission(\n installationId: number,\n repoFullName: string,\n username: string,\n signal?: AbortSignal,\n ): Promise<GithubRepositoryPermission | undefined>;\n}\n\nexport interface PlatformGithubEventWorkerConfig {\n client: PlatformApiClient;\n controller: MountedMastraCode['controller'];\n github: PlatformGithubEventDispatchIntegration;\n storage: PlatformGithubEventStorage;\n ingestFactoryEvent?: (event: ParsedGithubWebhook) => Promise<unknown>;\n intervalMs?: number;\n now?: () => number;\n dispatch?: typeof dispatchGithubWebhook;\n}\n\nexport class PlatformGithubEventWorker extends MastraWorker {\n readonly name = 'platform-github-events';\n\n readonly #client: PlatformApiClient;\n readonly #controller: MountedMastraCode['controller'];\n readonly #github: PlatformGithubEventDispatchIntegration;\n readonly #storage: PlatformGithubEventStorage;\n readonly #ingestFactoryEvent: ((event: ParsedGithubWebhook) => Promise<unknown>) | undefined;\n readonly #intervalMs: number;\n readonly #now: () => number;\n readonly #dispatch: typeof dispatchGithubWebhook;\n readonly #leaseOwner = randomUUID();\n\n #running = false;\n #timer: ReturnType<typeof setTimeout> | undefined;\n #leaseRenewalTimer: ReturnType<typeof setInterval> | undefined;\n #inFlight: Promise<void> | undefined;\n #leaseProvider: LeaseProvider = NoopLeaseProvider;\n #leaseTtlMs: number;\n #hasLease = false;\n #startedAt = 0;\n #settings: PlatformGithubEventWorkerSettings = { version: 1, repositories: {} };\n\n constructor(config: PlatformGithubEventWorkerConfig) {\n super();\n this.#client = config.client;\n this.#controller = config.controller;\n this.#github = config.github;\n this.#storage = config.storage;\n this.#ingestFactoryEvent = config.ingestFactoryEvent;\n this.#intervalMs = config.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n if (!Number.isFinite(this.#intervalMs) || this.#intervalMs <= 0) {\n throw new Error('Platform GitHub event polling interval must be a positive number.');\n }\n this.#leaseTtlMs = Math.max(MIN_LEASE_TTL_MS, this.#intervalMs * 3);\n this.#now = config.now ?? Date.now;\n this.#dispatch = config.dispatch ?? dispatchGithubWebhook;\n }\n\n async init(deps: WorkerDeps): Promise<void> {\n await super.init(deps);\n this.#leaseProvider = getLeaseProvider(deps.pubsub);\n }\n\n async start(): Promise<void> {\n if (this.#running) return;\n if (!this.deps) throw new Error('PlatformGithubEventWorker: call init() before start()');\n\n this.#startedAt = this.#now() - 1;\n this.#settings = normalizeSettings(await this.#storage.settings.get(CURSOR_ORG_ID, CURSOR_USER_ID));\n this.#running = true;\n this.deps.logger.info('Platform GitHub event polling started', {\n intervalMs: this.#intervalMs,\n leaseTtlMs: this.#leaseTtlMs,\n });\n this.#schedule(0);\n }\n\n async stop(): Promise<void> {\n if (!this.#running) return;\n this.#running = false;\n if (this.#timer) clearTimeout(this.#timer);\n this.#timer = undefined;\n this.#stopLeaseRenewal();\n await this.#inFlight;\n if (this.#hasLease) {\n await this.#leaseProvider.releaseLease(this.#leaseKey(), this.#leaseOwner).catch(() => undefined);\n this.#hasLease = false;\n }\n }\n\n get isRunning(): boolean {\n return this.#running;\n }\n\n #schedule(delayMs: number): void {\n if (!this.#running) return;\n this.#timer = setTimeout(() => {\n this.#timer = undefined;\n const run = this.#tick();\n this.#inFlight = run;\n void run.finally(() => {\n if (this.#inFlight === run) this.#inFlight = undefined;\n });\n }, delayMs);\n this.#timer.unref?.();\n }\n\n async #tick(): Promise<void> {\n let nextDelay = this.#intervalMs;\n try {\n if (!(await this.#ensureLease())) return;\n nextDelay = await this.#poll();\n } catch (error) {\n nextDelay = retryDelay(error, this.#intervalMs);\n this.deps?.logger.error('Platform GitHub event polling cycle failed', {\n error: error instanceof Error ? error.message : String(error),\n retryInMs: nextDelay,\n });\n } finally {\n this.#schedule(nextDelay);\n }\n }\n\n async #ensureLease(): Promise<boolean> {\n if (this.#hasLease) return true;\n const result = await this.#leaseProvider.acquireLease(this.#leaseKey(), this.#leaseOwner, this.#leaseTtlMs);\n this.#hasLease = result.acquired;\n if (this.#hasLease) this.#startLeaseRenewal();\n return this.#hasLease;\n }\n\n #startLeaseRenewal(): void {\n if (this.#leaseRenewalTimer) return;\n this.#leaseRenewalTimer = setInterval(\n () => {\n void this.#leaseProvider\n .renewLease(this.#leaseKey(), this.#leaseOwner, this.#leaseTtlMs)\n .then(renewed => {\n if (!renewed) {\n this.#hasLease = false;\n this.#stopLeaseRenewal();\n }\n })\n .catch(error => {\n this.#hasLease = false;\n this.#stopLeaseRenewal();\n this.deps?.logger.warn('Platform GitHub event polling lease renewal failed', {\n error: error instanceof Error ? error.message : String(error),\n });\n });\n },\n Math.floor(this.#leaseTtlMs / 3),\n );\n this.#leaseRenewalTimer.unref?.();\n }\n\n #stopLeaseRenewal(): void {\n if (this.#leaseRenewalTimer) clearInterval(this.#leaseRenewalTimer);\n this.#leaseRenewalTimer = undefined;\n }\n\n async #poll(): Promise<number> {\n const repositories = await this.#discoverRepositories();\n let retryInMs = this.#intervalMs;\n\n for (const repository of repositories) {\n if (!this.#running || !this.#hasLease) break;\n try {\n await this.#pollRepository(repository.id);\n } catch (error) {\n const delay = retryDelay(error, this.#intervalMs);\n retryInMs = Math.max(retryInMs, delay);\n this.deps?.logger.error('Platform GitHub repository event polling failed', {\n repositoryId: repository.id,\n error: error instanceof Error ? error.message : String(error),\n retryInMs: delay,\n });\n if (error instanceof PlatformApiError && error.status === 429) break;\n }\n }\n\n return retryInMs;\n }\n\n async #discoverRepositories(): Promise<Repository[]> {\n const result = await this.#client.request<{\n installations: Array<{\n installationId: number;\n usable: boolean;\n suspendedAt: string | null;\n }>;\n }>('GET', `${API_PREFIX}/installations`);\n const repositories = new Map<number, Repository>();\n\n for (const installation of result.installations) {\n if (!installation.usable || installation.suspendedAt) continue;\n const page = await this.#client.request<{ repositories: Repository[] }>(\n 'GET',\n `${API_PREFIX}/installations/${installation.installationId}/repositories`,\n );\n for (const repository of page.repositories) repositories.set(repository.id, repository);\n }\n\n return [...repositories.values()];\n }\n\n async #pollRepository(repositoryId: number): Promise<void> {\n const key = String(repositoryId);\n if (!this.#settings.repositories[key]) {\n this.#settings.repositories[key] = { afterTimestamp: this.#startedAt };\n await this.#saveSettings();\n }\n\n while (this.#running && this.#hasLease) {\n const cursor: EventCursor = this.#settings.repositories[key]!;\n const query = new URLSearchParams({ limit: String(EVENT_PAGE_SIZE) });\n if ('afterEventId' in cursor) query.set('afterEventId', cursor.afterEventId);\n else query.set('afterTimestamp', String(cursor.afterTimestamp));\n\n const pollStartedAt = performance.now();\n const page = await this.#client.request<{ events: EventLogEntry[]; nextCursor: string | null }>(\n 'GET',\n `${API_PREFIX}/repositories/${repositoryId}/events?${query}`,\n );\n this.deps?.logger.info('Platform GitHub repository event poll completed', {\n repositoryId,\n eventCount: page.events.length,\n latencyMs: Math.round(performance.now() - pollStartedAt),\n });\n if (page.events.length === 0 || !page.nextCursor) return;\n\n for (const event of page.events) {\n if (!this.#running || !this.#hasLease) return;\n const parsed = parseEvent(event);\n if (!parsed) {\n this.deps?.logger.warn('Platform GitHub event log returned a malformed event', {\n repositoryId,\n eventId: event.id,\n });\n continue;\n }\n if (isFactoryClosureEvent(parsed)) {\n await this.#ingestFactoryEvent?.(parsed);\n }\n const result = await this.#dispatch(parsed, {\n controller: this.#controller,\n listSubscriptions: (target, options) =>\n listPullRequestSubscriptionsForWebhook(target, options, this.#github.integrationStorage),\n retireSubscription: (id, status) =>\n retirePullRequestSubscription(id, status, this.#github.integrationStorage),\n isAuthorizedSender: notification => this.#isAuthorizedSender(notification),\n onTargetError: (subscription, error) => {\n this.deps?.logger.error('Platform GitHub event delivery failed for a subscription', {\n subscriptionId: subscription.id,\n resourceId: subscription.resourceId,\n threadId: subscription.threadId,\n error: error instanceof Error ? error.message : String(error),\n });\n },\n });\n if (result.failed > 0) {\n throw new Error(\n `Platform GitHub event ${event.deliveryId} failed for ${result.failed} subscribed target(s).`,\n );\n }\n }\n\n if (page.nextCursor === ('afterEventId' in cursor ? cursor.afterEventId : undefined)) return;\n this.#settings.repositories[key] = { afterEventId: page.nextCursor };\n await this.#saveSettings();\n }\n }\n\n async #isAuthorizedSender(notification: GithubWebhookNotification): Promise<boolean> {\n if (!AUTHOR_GATED_KINDS.has(notification.kind)) return true;\n const sender = notification.metadata.sender;\n const repository = notification.metadata.repository;\n if (!sender || !repository) return false;\n if (AUTHORIZED_BOTS.has(sender)) return true;\n\n const abortController = new AbortController();\n const timeout = setTimeout(() => abortController.abort(), PERMISSION_CHECK_TIMEOUT_MS);\n try {\n const permission = await this.#github.getRepositoryCollaboratorPermission(\n notification.metadata.installationId,\n repository,\n sender,\n abortController.signal,\n );\n return permission !== undefined && AUTHORIZED_PERMISSIONS.has(permission);\n } catch {\n return false;\n } finally {\n clearTimeout(timeout);\n }\n }\n\n async #saveSettings(): Promise<void> {\n await this.#storage.settings.save(CURSOR_ORG_ID, CURSOR_USER_ID, this.#settings);\n }\n\n #leaseKey(): string {\n return `${this.name}:${this.#storage.integrationId}`;\n }\n}\n\nfunction getLeaseProvider(pubsub: PubSub): LeaseProvider {\n const getProvider = (pubsub as PubSub & { getLeaseProvider?: () => LeaseProvider | undefined }).getLeaseProvider;\n if (typeof getProvider === 'function') return getProvider.call(pubsub) ?? NoopLeaseProvider;\n return isLeaseProvider(pubsub) ? pubsub : NoopLeaseProvider;\n}\n\nfunction normalizeSettings(value: PlatformGithubEventWorkerSettings | null): PlatformGithubEventWorkerSettings {\n if (!value || value.version !== 1 || !value.repositories || typeof value.repositories !== 'object') {\n return { version: 1, repositories: {} };\n }\n return { version: 1, repositories: { ...value.repositories } };\n}\n\nfunction isFactoryClosureEvent(event: ParsedGithubWebhook): boolean {\n return (event.event === 'issues' || event.event === 'pull_request') && event.payload.action === 'closed';\n}\n\nfunction parseEvent(event: EventLogEntry): ParsedGithubWebhook | null {\n if (\n !event.id ||\n !event.deliveryId ||\n !SUPPORTED_EVENTS.has(event.event) ||\n !event.payload ||\n typeof event.payload !== 'object' ||\n Array.isArray(event.payload)\n ) {\n return null;\n }\n return {\n event: event.event,\n deliveryId: event.deliveryId,\n payload: event.payload as Record<string, unknown>,\n };\n}\n\nfunction retryDelay(error: unknown, fallbackMs: number): number {\n if (error instanceof PlatformApiError && error.status === 429 && error.retryAfterSeconds !== null) {\n return Math.max(fallbackMs, error.retryAfterSeconds * 1_000);\n }\n return fallbackMs;\n}\n"],"mappings":";AAEA,SAAS,oBAAAA,yBAAwB;;;ACWjC,SAAS,kBAAkB;AAG3B,SAAS,wBAAwB;AAGjC,SAAS,iBAAiB;;;ACA1B,OAAO,UAAU;AA2DV,SAAS,eAAe,YAAoC,OAA8B;AAC/F,MAAI,CAAC,WAAY;AACjB,MAAI;AACF,eAAW,KAAK;AAAA,EAClB,QAAQ;AAAA,EAER;AACF;AAUO,IAAM,qBAAN,cAAiC,MAAM;AAAA,EAE5C,YAAqB,KAAa;AAChC;AAAA,MACE,oDAAoD,GAAG;AAAA,IAEzD;AAJmB;AAKnB,SAAK,OAAO;AAAA,EACd;AAAA,EANqB;AAAA,EADZ,OAAO;AAQlB;;;AC3EA,IAAM,sBAAsB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAmBO,SAAS,uBAAuB,SAAqE;AAC1G,SAAO,QAAQ,WAAW,UAAa,QAAQ,KAAK,QAAQ;AAC9D;AAwBO,SAAS,4BAA4B,SAA6D;AACvG,QAAM,EAAE,QAAQ,MAAM,iBAAiB,aAAa,MAAM,IAAI;AAC9D,SAAO;AAAA,IACL,qBAAqB,WAAW;AAAA,IAChC,oBAAoB,KAAK,QAAQ;AAAA,IACjC;AAAA,IACA,uBAAuB,aAAa,UAAU;AAAA,IAC9C,gBAAgB,OAAO,WAAW;AAAA,IAClC,iBAAiB,OAAO,YAAY;AAAA,IACpC,yBAAyB,SAAS,CAAC,IAAI,CAAC,GAAG,mBAAmB;AAAA,EAChE;AACF;;;AClEA,IAAM,uBAAuB;AAM7B,IAAM,iBAAiE;AAAA,EACrE,SAAS;AAAA,EACT,UAAU;AACZ;AAEA,SAAS,QAAQ,OAA+B;AAC9C,SAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ;AACjE;AAOA,eAAsB,aACpB,YACA,OACA,OAAsB,WACE;AACxB,MAAI;AACF,UAAM,WAAY,MAAM,WAAW,EAAE,SAAS,IAAI,OAAO,oBAAoB;AAC7E,QAAI,CAAC,SAAU,QAAO;AACtB,QAAI,SAAS,WAAY,QAAO,QAAQ,SAAS,WAAW,KAAK,QAAQ,SAAS,GAAG;AACrF,WAAO,QAAQ,SAAS,GAAG;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAIA,eAAsB,mBACpB,YACA,OAC+D;AAC/D,MAAI;AACF,UAAM,WAAY,MAAM,WAAW,EAAE,SAAS,IAAI,OAAO,oBAAoB;AAC7E,WAAO;AAAA,MACL,YAAY,QAAQ,UAAU,GAAG,MAAM;AAAA,MACvC,oBAAoB,QAAQ,UAAU,WAAW,MAAM;AAAA,IACzD;AAAA,EACF,QAAQ;AACN,WAAO,EAAE,YAAY,OAAO,oBAAoB,MAAM;AAAA,EACxD;AACF;AAEA,eAAsB,aACpB,SACA,OACA,KACA,OAAsB,WACP;AACf,QAAM,WAAa,MAAM,QAAQ,SAAS,IAAI,OAAO,oBAAoB,KAAM,CAAC;AAChF,QAAM,QAAQ,SAAS,KAAK,OAAO,sBAAsB,EAAE,GAAG,UAAU,CAAC,eAAe,IAAI,CAAC,GAAG,IAAI,CAAC;AACvG;AAEA,eAAsB,eACpB,SACA,OACA,OAAsB,WACP;AACf,QAAM,WAAY,MAAM,QAAQ,SAAS,IAAI,OAAO,oBAAoB;AACxE,QAAM,QAAQ,eAAe,IAAI;AACjC,MAAI,CAAC,WAAW,KAAK,EAAG;AACxB,QAAM,EAAE,CAAC,KAAK,GAAG,UAAU,GAAG,KAAK,IAAI;AACvC,QAAM,QAAQ,SAAS,KAAK,OAAO,sBAAsB,IAAI;AAC/D;;;AC5EA,SAAS,kBAAkB;AAa3B,IAAM,iBAAiB,oBAAI,IAA8B;AASlD,IAAM,kCAAkC;AAGxC,IAAM,0BAAN,cAAsC,MAAM;AAAA,EACxC;AAAA,EACA;AAAA,EACT,YAAY,KAAa,WAAmB;AAC1C,UAAM,sCAAsC,GAAG,cAAc,SAAS,IAAI;AAC1E,SAAK,OAAO;AACZ,SAAK,MAAM;AACX,SAAK,YAAY;AAAA,EACnB;AACF;AAUA,eAAe,eAAkB,KAAa,WAAmB,IAAqD;AACpH,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,SAAS;AAC5D,QAAM,aAAa,IAAI,QAAe,CAAC,GAAG,WAAW;AACnD,eAAW,OAAO,iBAAiB,SAAS,MAAM,OAAO,IAAI,wBAAwB,KAAK,SAAS,CAAC,GAAG;AAAA,MACrG,MAAM;AAAA,IACR,CAAC;AAAA,EACH,CAAC;AACD,QAAM,OAAO,GAAG,WAAW,MAAM;AAKjC,OAAK,MAAM,MAAM;AAAA,EAAC,CAAC;AACnB,MAAI;AACF,WAAO,MAAM,QAAQ,KAAK,CAAC,MAAM,UAAU,CAAC;AAAA,EAC9C,UAAE;AACA,iBAAa,KAAK;AAAA,EACpB;AACF;AAkBO,SAAS,QAAQ,KAA+B;AACrD,QAAM,SAAS,WAAW,QAAQ,EAAE,OAAO,GAAG,EAAE,OAAO;AAEvD,QAAM,IAAI,OAAO,YAAY,CAAC;AAC9B,QAAM,IAAI,OAAO,YAAY,CAAC;AAC9B,SAAO,CAAC,GAAG,CAAC;AACd;AAUO,SAAS,gBAAmB,SAcpB;AACb,QAAM,EAAE,KAAK,SAAS,IAAI,MAAM,YAAY,gCAAgC,IAAI;AAChF,QAAM,OAAO,eAAe,IAAI,GAAG,KAAK,QAAQ,QAAQ;AACxD,QAAM,MAAM,MAAM,mBAAmB,EAAE,KAAK,SAAS,IAAI,MAAM,UAAU,CAAC;AAC1E,QAAM,OAAO,KAAK,KAAK,KAAK,GAAG;AAC/B,QAAM,OAAO,KAAK;AAAA,IAChB,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AACA,iBAAe,IAAI,KAAK,IAAI;AAI5B,OAAK,KAAK,KAAK,MAAM;AACnB,QAAI,eAAe,IAAI,GAAG,MAAM,MAAM;AACpC,qBAAe,OAAO,GAAG;AAAA,IAC3B;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAaA,eAAsB,mBAAsB,SAM7B;AACb,QAAM,EAAE,KAAK,SAAS,IAAI,MAAM,YAAY,gCAAgC,IAAI;AAChF,MAAI,QAAQ,IAAI,gCAAgC,KAAK;AACnD,WAAO,eAAe,KAAK,WAAW,EAAE;AAAA,EAC1C;AAEA,MAAI,KAAM,QAAO,iBAAiB,MAAM,KAAK,WAAW,EAAE;AAE1D,MAAI,OAAO,SAAS,wBAAwB,YAAY;AACtD,WAAO,eAAe,KAAK,WAAW,EAAE;AAAA,EAC1C;AAKA,SAAO,QAAQ,oBAAoB,KAAK,MAAM,eAAe,KAAK,WAAW,EAAE,CAAC;AAClF;AAGA,eAAe,iBACb,MACA,KACA,WACA,IACY;AACZ,QAAM,CAAC,IAAI,EAAE,IAAI,QAAQ,GAAG;AAC5B,QAAM,SAAS,MAAM,KAAK,QAAQ;AAClC,MAAI;AACF,UAAM,OAAO,MAAM,OAAO;AAG1B,UAAM,OAAO,MAAM,wCAAwC,CAAC,IAAI,EAAE,CAAC;AACnE,QAAI;AACF,YAAM,SAAS,MAAM,eAAe,KAAK,WAAW,EAAE;AACtD,YAAM,OAAO,MAAM,QAAQ;AAC3B,aAAO;AAAA,IACT,SAAS,KAAK;AAKZ,UAAI;AACF,cAAM,OAAO,MAAM,UAAU;AAAA,MAC/B,QAAQ;AAAA,MAER;AACA,YAAM;AAAA,IACR;AAAA,EACF,UAAE;AACA,WAAO,QAAQ;AAAA,EACjB;AACF;;;AC1MA,SAAS,cAAAC,mBAAkB;AAwB3B,SAAS,aAAa,KAA+B,SAA2D;AAC9G,SAAO;AAAA,IACL,WAAW,IAAI;AAAA,IACf,cAAc,QACZ,OAAO,OAAO,QAAQ,aAAa,EAAE,IAAI,IAAI,GAAG,CAAC,IAAI,QAAQ,aAAa,EAAE,IAAI,IAAI,IAAI,WAAW,GAAG,CAAC;AAAA,IACzG,OAAO,MAAM,QAAQ,aAAa,EAAE,IAAI,IAAI,GAAG,CAAC;AAAA,EAClD;AACF;AAMA,eAAsB,qBAAqB,SAMP;AAClC,QAAM,EAAE,OAAO,KAAK,SAAS,OAAO,WAAW,IAAI;AACnD,SAAO,MAAM,cAAc,aAAa,KAAK,OAAO,GAAG,EAAE,UAAU,MAAM,GAAG,UAAU;AACxF;AAUA,eAAsB,uBAAuB,SAK3B;AAChB,QAAM,EAAE,OAAO,KAAK,SAAS,QAAQ,IAAI;AACzC,SAAO,MAAM,gBAAgB,aAAa,KAAK,OAAO,GAAG,OAAO;AAClE;AASO,SAAS,WAAW,OAAuB;AAEhD,SAAO,MAAM,MAAM,MAAM,GAAG,EAAE,KAAK,OAAO,IAAI;AAChD;AAGA,eAAe,GAAG,SAAiC,QAA+C;AAChG,SAAO,QAAQ,eAAe,MAAM,CAAC,MAAM,MAAM,CAAC;AACpD;AAGO,IAAM,mBAAN,cAA+B,MAAM;AAAA,EAC1C,YACE,SACS,MAST;AACA,UAAM,OAAO;AAVJ;AAWT,SAAK,OAAO;AAAA,EACd;AAAA,EAZW;AAab;AAMA,SAAS,SAAS,cAAsB,OAAuB;AAC7D,SAAO,0BAA0B,KAAK,eAAe,YAAY;AACnE;AAEA,SAAS,SAAS,cAA8B;AAC9C,SAAO,sBAAsB,YAAY;AAC3C;AAcA,eAAsB,gBAAgB,SAWpB;AAChB,QAAM,EAAE,KAAK,YAAY,UAAU,SAAS,OAAO,SAAS,WAAW,IAAI;AAC3E,QAAM,UAAU,WAAW;AAC3B,QAAM,OAAO,SAAS;AAKtB,MAAI,CAAC,qBAAqB,KAAK,IAAI,GAAG;AACpC,UAAM,IAAI,iBAAiB,oDAAoD,IAAI,MAAM,cAAc;AAAA,EACzG;AACA,MAAI,CAAC,qBAAqB,KAAK,SAAS,aAAa,GAAG;AACtD,UAAM,IAAI;AAAA,MACR,oDAAoD,SAAS,aAAa;AAAA,MAC1E;AAAA,IACF;AAAA,EACF;AAGA,QAAM,aAAa,MAAM,GAAG,SAAS,eAAe;AACpD,MAAI,WAAW,aAAa,GAAG;AAC7B,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,SAAS,MAAM,KAAK;AAMpC,QAAM,sBAAsB,QAAQ,WAAW,cAAc,KAAM,MAAM,oBAAoB,SAAS,SAAS,IAAI;AAEnH,MAAI;AACF,QAAI,CAAC,qBAAqB;AAIxB,qBAAe,YAAY;AAAA,QACzB,OAAO;AAAA,QACP,SAAS,WAAW,IAAI;AAAA,MAC1B,CAAC;AACD,YAAM,QAAQ,MAAM;AAAA,QAClB;AAAA,QACA,gDAAgD,WAAW,SAAS,aAAa,CAAC,IAAI,WAAW,OAAO,CAAC,IAAI,WAAW,OAAO,CAAC;AAAA,MAClI;AACA,UAAI,MAAM,aAAa,GAAG;AACxB,cAAM,mBAAmB,OAAO,cAAc;AAAA,MAChD;AAAA,IACF,OAAO;AAEL,qBAAe,YAAY,EAAE,OAAO,WAAW,SAAS,YAAY,IAAI,+BAA0B,CAAC;AACnG,YAAM,SAAS,MAAM,GAAG,SAAS,UAAU,WAAW,OAAO,CAAC,0BAA0B,WAAW,OAAO,CAAC,EAAE;AAC7G,UAAI,OAAO,aAAa,GAAG;AACzB,cAAM,IAAI,iBAAiB,6BAA6B,OAAO,MAAM,IAAI,aAAa;AAAA,MACxF;AACA,YAAM,OAAO,MAAM,GAAG,SAAS,UAAU,WAAW,OAAO,CAAC,iBAAiB;AAC7E,UAAI,KAAK,aAAa,GAAG;AACvB,cAAM,mBAAmB,MAAM,aAAa;AAAA,MAC9C;AAAA,IACF;AAAA,EACF,UAAE;AAKA,UAAM,YAAY,SAAS,SAAS,MAAM,mBAAmB;AAAA,EAC/D;AAGA,iBAAe,YAAY,EAAE,OAAO,cAAc,SAAS,6BAAwB,CAAC;AACpF,QAAM,QAAQ,iBAAiB,EAAE,IAAI,WAAW,GAAG,CAAC;AACtD;AAiDA,eAAe,oBACb,SACA,SACA,cACkB;AAClB,QAAM,SAAS,MAAM,GAAG,SAAS,UAAU,WAAW,OAAO,CAAC,wBAAwB;AACtF,MAAI,OAAO,aAAa,EAAG,QAAO;AAClC,QAAM,MAAM,OAAO,OAAO,KAAK,EAAE,YAAY;AAC7C,QAAM,SAAS,cAAc,aAAa,YAAY,CAAC;AACvD,SAAO,IAAI,SAAS,GAAG,MAAM,MAAM,KAAK,IAAI,SAAS,MAAM;AAC7D;AAQA,eAAe,YACb,SACA,SACA,cACA,cACe;AACf,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,IACA,UAAU,WAAW,OAAO,CAAC,0BAA0B,WAAW,SAAS,YAAY,CAAC,CAAC;AAAA,EAC3F;AACA,MAAI,OAAO,aAAa,KAAK,cAAc;AACzC,UAAM,IAAI;AAAA,MACR,uDAAuD,OAAO,OAAO,KAAK,KAAK,OAAO,OAAO,KAAK,CAAC;AAAA,MACnG;AAAA,IACF;AAAA,EACF;AACF;AAMA,SAAS,mBACP,QACA,UACkB;AAClB,QAAM,SAAS,OAAO,UAAU;AAChC,MAAI,wFAAwF,KAAK,MAAM,GAAG;AACxG,WAAO,IAAI;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,QAAM,OAAO,aAAa,iBAAiB,UAAU,aAAa,gBAAgB,SAAS;AAC3F,SAAO,IAAI,iBAAiB,OAAO,IAAI,YAAY,MAAM,IAAI,QAAQ;AACvE;AAgBO,SAAS,cAAc,OAAiC;AAC7D,SACE,OAAO,UAAU,YACjB,MAAM,SAAS,KACf,MAAM,UAAU;AAAA;AAAA,EAGhB,CAAC,MAAM,WAAW,GAAG,KACrB,qBAAqB,KAAK,KAAK;AAEnC;AAeO,SAAS,mBAAmB,UAAwD;AACzF,QAAM,SAAS,SAAS,SAAS,IAAI,KAAK;AAC1C,QAAM,QAAQ,SAAS,QAAQ,IAAI,KAAK,KAAK,SAAS;AACtD,QAAM,SACH,SAAS,SAAS,IAAI,KAAK,MAC3B,QAAQ,GAAG,KAAK,8BAA8B;AACjD,SAAO,EAAE,MAAM,MAAM;AACvB;AAMA,eAAsB,qBACpB,SACA,SACA,UACe;AACf,QAAM,EAAE,MAAM,MAAM,IAAI,mBAAmB,QAAQ;AACnD,QAAM,UAAU,MAAM,GAAG,SAAS,UAAU,WAAW,OAAO,CAAC,qBAAqB,WAAW,IAAI,CAAC,EAAE;AACtG,MAAI,QAAQ,aAAa,GAAG;AAC1B,UAAM,IAAI,iBAAiB,gCAAgC,QAAQ,OAAO,KAAK,CAAC,IAAI,eAAe;AAAA,EACrG;AACA,QAAM,WAAW,MAAM,GAAG,SAAS,UAAU,WAAW,OAAO,CAAC,sBAAsB,WAAW,KAAK,CAAC,EAAE;AACzG,MAAI,SAAS,aAAa,GAAG;AAC3B,UAAM,IAAI,iBAAiB,iCAAiC,SAAS,OAAO,KAAK,CAAC,IAAI,eAAe;AAAA,EACvG;AACF;AAYA,eAAsB,iBACpB,SACA,SACA,cACA,OACA,IACY;AACZ,MAAI,CAAC,qBAAqB,KAAK,YAAY,GAAG;AAC5C,UAAM,IAAI,iBAAiB,6CAA6C,YAAY,MAAM,aAAa;AAAA,EACzG;AAEA,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,IACA,UAAU,WAAW,OAAO,CAAC,0BAA0B,WAAW,SAAS,cAAc,KAAK,CAAC,CAAC;AAAA,EAClG;AACA,MAAI,OAAO,aAAa,GAAG;AAEzB,UAAM,YAAY,SAAS,SAAS,cAAc,KAAK;AACvD,UAAM,IAAI,iBAAiB,6BAA6B,OAAO,OAAO,KAAK,CAAC,IAAI,aAAa;AAAA,EAC/F;AAEA,MAAI;AACF,WAAO,MAAM,GAAG;AAAA,EAClB,UAAE;AAIA,UAAM,YAAY,SAAS,SAAS,cAAc,IAAI;AAAA,EACxD;AACF;AAQA,eAAsB,WACpB,SACA,SACA,QACA,OACA,cACe;AACf,MAAI,CAAC,cAAc,MAAM,GAAG;AAC1B,UAAM,IAAI,iBAAiB,0CAA0C,MAAM,MAAM,aAAa;AAAA,EAChG;AAEA,QAAM,iBAAiB,SAAS,SAAS,cAAc,OAAO,YAAY;AACxE,UAAM,OAAO,MAAM,GAAG,SAAS,UAAU,WAAW,OAAO,CAAC,mBAAmB,WAAW,MAAM,CAAC,EAAE;AACnG,QAAI,KAAK,aAAa,GAAG;AACvB,YAAM,mBAAmB,MAAM,aAAa;AAAA,IAC9C;AAAA,EACF,CAAC;AACH;AAkBA,eAAsB,UACpB,SACA,SACA,SACA,UACuB;AACvB,QAAM,qBAAqB,SAAS,SAAS,QAAQ;AAErD,QAAM,MAAM,MAAM,GAAG,SAAS,UAAU,WAAW,OAAO,CAAC,SAAS;AACpE,MAAI,IAAI,aAAa,GAAG;AACtB,UAAM,IAAI,iBAAiB,mBAAmB,IAAI,OAAO,KAAK,KAAK,IAAI,OAAO,KAAK,CAAC,IAAI,eAAe;AAAA,EACzG;AAIA,QAAM,SAAS,MAAM,GAAG,SAAS,UAAU,WAAW,OAAO,CAAC,wBAAwB;AACtF,MAAI,OAAO,aAAa,GAAG;AACzB,WAAO,EAAE,WAAW,MAAM;AAAA,EAC5B;AAEA,QAAM,SAAS,MAAM,GAAG,SAAS,UAAU,WAAW,OAAO,CAAC,cAAc,WAAW,OAAO,CAAC,EAAE;AACjG,MAAI,OAAO,aAAa,GAAG;AACzB,UAAM,IAAI,iBAAiB,sBAAsB,OAAO,OAAO,KAAK,KAAK,OAAO,OAAO,KAAK,CAAC,IAAI,eAAe;AAAA,EAClH;AAEA,SAAO,EAAE,WAAW,KAAK;AAC3B;AAWO,IAAM,gBAAN,cAA4B,MAAM;AAAA,EACvC,YACE,SACS,MACT;AACA,UAAM,OAAO;AAFJ;AAGT,SAAK,OAAO;AAAA,EACd;AAAA,EAJW;AAKb;AAYO,SAAS,cAAc,QAAwB;AACpD,QAAM,YACJ,OACG,QAAQ,qBAAqB,GAAG,EAChC,QAAQ,QAAQ,GAAG,EACnB,QAAQ,kBAAkB,EAAE,EAC5B,MAAM,GAAG,GAAG,KAAK;AACtB,MAAI,cAAc,OAAQ,QAAO;AACjC,QAAM,OAAOC,YAAW,QAAQ,EAAE,OAAO,MAAM,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,CAAC;AACzE,SAAO,GAAG,SAAS,IAAI,IAAI;AAC7B;AAOO,SAAS,oBAAoB,aAAqB,QAAwB;AAC/E,QAAM,SAAS,YAAY,QAAQ,QAAQ,EAAE,EAAE,MAAM,GAAG,EAAE,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG,KAAK;AACpF,SAAO,GAAG,MAAM,cAAc,cAAc,MAAM,CAAC;AACrD;;;AC1fO,SAAS,uBAAuB,OAA+C;AACpF,SAAO,kBAAkB,MAAM,sBAAsB,IAAI,MAAM,oBAAoB,IAAI,MAAM,eAAe;AAC9G;AAEA,SAAS,YAAY,KAAkC,OAA6C;AAClG,SACE,IAAI,UAAU,MAAM,SACpB,IAAI,cAAc,MAAM,aACxB,IAAI,eAAe,MAAM,cACzB,IAAI,aAAa,MAAM,aACtB,IAAI,gBAAgB,SAAS,MAAM,gBAAgB;AAExD;AAEA,eAAsB,uBACpB,OACA,SACsC;AACtC,QAAM,YAAY,uBAAuB,KAAK;AAC9C,QAAM,YAAY,MAAM,QAAQ,cAAc,aAAa,SAAS,GAAG,KAAK,SAAO,YAAY,KAAK,KAAK,CAAC;AAC1G,MAAI,UAAU;AACZ,QAAI,SAAS,WAAW,OAAQ,OAAM,QAAQ,cAAc,aAAa,SAAS,IAAI,MAAM;AAC5F,WAAO,EAAE,GAAG,UAAU,QAAQ,OAAO;AAAA,EACvC;AAEA,SAAO,QAAQ,cAAc,OAAO;AAAA,IAClC,OAAO,MAAM;AAAA,IACb;AAAA,IACA,WAAW,MAAM;AAAA,IACjB,YAAY,MAAM;AAAA,IAClB,UAAU,MAAM;AAAA,IAChB,cAAc,MAAM,gBAAgB;AAAA,IACpC,QAAQ;AAAA,IACR,MAAM;AAAA,MACJ,wBAAwB,MAAM;AAAA,MAC9B,qBAAqB,MAAM;AAAA,MAC3B,sBAAsB,MAAM;AAAA,MAC5B,gBAAgB,MAAM;AAAA,MACtB,iBAAiB,MAAM;AAAA,MACvB,SAAS,MAAM;AAAA,MACf,QAAQ,MAAM;AAAA,MACd,oBAAoB,MAAM,sBAAsB;AAAA,IAClD;AAAA,EACF,CAAC;AACH;AAEA,eAAsB,2BACpB,OACA,SACe;AACf,QAAM,OAAO,MAAM,QAAQ,cAAc,aAAa,uBAAuB,KAAK,CAAC;AACnF,QAAM,QAAQ,IAAI,KAAK,OAAO,SAAO,YAAY,KAAK,KAAK,CAAC,EAAE,IAAI,SAAO,QAAQ,cAAc,OAAO,IAAI,EAAE,CAAC,CAAC;AAChH;AAEA,eAAsB,sCACpB,OACA,SACwC;AACxC,QAAM,OAAO,MAAM,QAAQ,cAAc,aAAa,MAAM,YAAY,MAAM,QAAQ;AACtF,SAAO,KAAK;AAAA,IACV,SACE,IAAI,UAAU,MAAM,SACpB,IAAI,eAAe,MAAM,cACzB,IAAI,aAAa,MAAM,aACtB,IAAI,gBAAgB,SAAS,MAAM,gBAAgB;AAAA,EACxD;AACF;AAUA,eAAsB,uCACpB,OACA,SACA,SACwC;AACxC,QAAM,OAAO,MAAM,QAAQ,cAAc,aAAa,uBAAuB,KAAK,CAAC;AACnF,SAAO,SAAS,kBAAkB,OAAO,KAAK,OAAO,SAAO,IAAI,WAAW,MAAM;AACnF;AAEO,SAAS,8BACd,IACA,QACA,SACe;AACf,SAAO,QAAQ,cAAc,aAAa,IAAI,MAAM;AACtD;;;AClJA,SAAS,YAAY,uBAAuB;AAmB5C,IAAM,kCAAkC,oBAAI,IAAI;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAqDD,SAAS,gBAAgB,OAAiD;AACxE,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,UAAU,MAAM,KAAK;AAC3B,SAAO,QAAQ,SAAS,IAAI,UAAU;AACxC;AAEA,SAAS,gBAAgB,SAAiB,WAAmB,QAAyB;AACpF,MAAI,CAAC,UAAU,WAAW,SAAS,EAAG,QAAO;AAC7C,QAAM,eAAe,UAAU,MAAM,UAAU,MAAM;AACrD,MAAI,CAAC,oBAAoB,KAAK,YAAY,EAAG,QAAO;AAEpD,QAAM,cAAc,WAAW,UAAU,MAAM,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK;AAC7E,QAAM,WAAW,OAAO,KAAK,cAAc,KAAK;AAChD,QAAM,WAAW,OAAO,KAAK,aAAa,KAAK;AAC/C,SAAO,SAAS,WAAW,SAAS,UAAU,gBAAgB,UAAU,QAAQ;AAClF;AAEA,eAAe,mBACb,GACA,QACoD;AACpD,MAAI,CAAC,QAAQ;AACX,WAAO,EAAE,QAAQ,KAAK,MAAM,EAAE,OAAO,gBAAgB,SAAS,0CAA0C,EAAE;AAAA,EAC5G;AAEA,QAAM,QAAQ,gBAAgB,EAAE,IAAI,OAAO,gBAAgB,CAAC;AAC5D,QAAM,aAAa,gBAAgB,EAAE,IAAI,OAAO,mBAAmB,CAAC;AACpE,QAAM,YAAY,gBAAgB,EAAE,IAAI,OAAO,qBAAqB,CAAC;AAErE,MAAI,CAAC,MAAO,QAAO,EAAE,QAAQ,KAAK,MAAM,EAAE,OAAO,eAAe,SAAS,gCAAgC,EAAE;AAC3G,MAAI,CAAC,WAAY,QAAO,EAAE,QAAQ,KAAK,MAAM,EAAE,OAAO,eAAe,SAAS,mCAAmC,EAAE;AACnH,MAAI,CAAC;AACH,WAAO,EAAE,QAAQ,KAAK,MAAM,EAAE,OAAO,gBAAgB,SAAS,qCAAqC,EAAE;AAEvG,QAAM,UAAU,MAAM,EAAE,IAAI,KAAK;AACjC,MAAI,CAAC,gBAAgB,SAAS,WAAW,MAAM,GAAG;AAChD,WAAO,EAAE,QAAQ,KAAK,MAAM,EAAE,OAAO,gBAAgB,SAAS,mCAAmC,EAAE;AAAA,EACrG;AAEA,MAAI;AACJ,MAAI;AACF,cAAU,KAAK,MAAM,OAAO;AAAA,EAC9B,QAAQ;AACN,WAAO,EAAE,QAAQ,KAAK,MAAM,EAAE,OAAO,eAAe,SAAS,yBAAyB,EAAE;AAAA,EAC1F;AAEA,MAAI,CAAC,WAAW,OAAO,YAAY,YAAY,MAAM,QAAQ,OAAO,GAAG;AACrE,WAAO,EAAE,QAAQ,KAAK,MAAM,EAAE,OAAO,eAAe,SAAS,gCAAgC,EAAE;AAAA,EACjG;AAEA,SAAO,EAAE,OAAO,YAAY,QAA4C;AAC1E;AAEA,SAAS,UAAU,OAAqD;AACtE,SAAO,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAAK,QAAoC;AAC5G;AAEA,SAAS,UAAU,OAAoC;AACrD,SAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ;AACjE;AAEA,SAAS,UAAU,OAAoC;AACrD,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,QAAQ;AACvE;AAEA,SAAS,WAAW,OAAqC;AACvD,SAAO,OAAO,UAAU,YAAY,QAAQ;AAC9C;AAEA,SAAS,UAAU,OAA0B;AAC3C,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACnC,SAAO,MACJ,IAAI,WAAU,OAAO,UAAU,WAAW,QAAQ,UAAU,UAAU,KAAK,GAAG,IAAI,CAAE,EACpF,OAAO,CAAC,UAA2B,QAAQ,KAAK,CAAC;AACtD;AAEA,SAAS,uBAAuB,QAA+D;AAC7F,MAAI,OAAO,UAAU,YAAY,UAAU,OAAO,QAAQ,MAAM,MAAM,SAAU,QAAO;AACvF,QAAM,aAAa,UAAU,UAAU,OAAO,QAAQ,UAAU,GAAG,SAAS;AAC5E,QAAM,QAAQ,UAAU,OAAO,QAAQ,KAAK;AAC5C,QAAM,SAAS,UAAU,UAAU,OAAO,QAAQ,MAAM,GAAG,KAAK;AAChE,QAAM,iBAAiB,UAAU,UAAU,OAAO,QAAQ,YAAY,GAAG,EAAE;AAC3E,QAAM,cAAc,UAAU,OAAO,MAAM;AAC3C,QAAM,aAAa,UAAU,OAAO,KAAK;AACzC,QAAM,WAAW,UAAU,OAAO,QAAQ;AAC1C,MAAI,CAAC,cAAc,CAAC,kBAAkB,CAAC,eAAe,CAAC,cAAc,CAAC,SAAU,QAAO;AACvF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,UAAU,OAAO,MAAM;AAAA,IAC/B;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,+BAA+B,QAAoD;AACjG,QAAM,EAAE,OAAO,YAAY,QAAQ,IAAI;AACvC,QAAM,aAAa,UAAU,QAAQ,UAAU;AAC/C,QAAM,QAAQ,UAAU,QAAQ,KAAK;AACrC,QAAM,cAAc,UAAU,QAAQ,YAAY;AAClD,QAAM,SAAS,UAAU,QAAQ,MAAM;AACvC,QAAM,eAAe,UAAU,QAAQ,YAAY;AACnD,QAAM,mBAAmB,UAAU,OAAO,YAAY;AAEtD,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,UAAU,QAAQ,MAAM;AAAA,IAChC;AAAA,IACA,YAAY,UAAU,YAAY,SAAS;AAAA,IAC3C,cAAc,UAAU,YAAY,EAAE;AAAA,IACtC,aAAa,UAAU,OAAO,MAAM;AAAA,IACpC,mBACE,UAAU,aAAa,MAAM,MAC5B,UAAU,mBAAmB,mBAAmB,UAAU,OAAO,MAAM,IAAI;AAAA,IAC9E,QAAQ,UAAU,QAAQ,KAAK;AAAA,IAC/B,YAAY,UAAU,QAAQ,IAAI;AAAA,IAClC,gBAAgB,UAAU,cAAc,EAAE;AAAA,EAC5C;AACF;AAEA,SAAS,oBAAoB,UAAiC,OAAuB;AACnF,QAAM,QAAQ,SAAS,SAAS,GAAG,SAAS,MAAM,MAAM;AACxD,SAAO,GAAG,KAAK,GAAG,KAAK,OAAO,SAAS,UAAU,IAAI,SAAS,iBAAiB;AACjF;AAEA,SAAS,sBAAsB,OAAe,SAAsD;AAClG,MAAI,UAAU,mBAAmB,UAAU,+BAA+B;AACxE,WAAO,UAAU,UAAU,QAAQ,OAAO,GAAG,QAAQ;AAAA,EACvD;AACA,MAAI,UAAU,uBAAuB;AACnC,WAAO,UAAU,UAAU,QAAQ,MAAM,GAAG,QAAQ;AAAA,EACtD;AACA,SAAO,UAAU,UAAU,QAAQ,YAAY,GAAG,QAAQ;AAC5D;AAEO,SAAS,sBAAsB,QAAoE;AACxG,QAAM,WAAW,+BAA+B,MAAM;AACtD,QAAM,EAAE,OAAO,QAAQ,IAAI;AAC3B,QAAM,SAAS,SAAS;AACxB,MACE,CAAC,UACD,CAAC,SAAS,gBACV,CAAC,SAAS,kBACV,CAAC,SAAS,qBACV,CAAC,SAAS,YACV;AACA,WAAO;AAAA,EACT;AAEA,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI,WAAW;AAEf,MAAI,UAAU,yBAAyB,WAAW,aAAa;AAC7D,UAAM,QAAQ,UAAU,UAAU,QAAQ,MAAM,GAAG,KAAK,GAAG,YAAY,EAAE,WAAW,KAAK,GAAG;AAC5F,eAAW,UAAU,cAAc,UAAU,sBAAsB,WAAW;AAC9E,WACE,UAAU,aACN,oBACA,UAAU,sBACR,6BACA;AACR,YACE,UAAU,aACN,8BACA,UAAU,sBACR,sBACA;AAAA,EACV,WAAW,UAAU,kBAAkB,WAAW,UAAU;AAC1D,UAAM,SAAS,WAAW,UAAU,QAAQ,YAAY,GAAG,MAAM,MAAM;AACvE,eAAW;AACX,WAAO,SAAS,wBAAwB;AACxC,YAAQ,SAAS,4BAA4B;AAC7C,eAAW;AAAA,EACb,WAAW,UAAU,mBAAmB,WAAW,WAAW;AAC5D,eAAW;AACX,WAAO;AACP,YAAQ;AAAA,EACV,WAAW,UAAU,iCAAiC,WAAW,WAAW;AAC1E,eAAW;AACX,WAAO;AACP,YAAQ;AAAA,EACV,WAAW,UAAU,kBAAkB,WAAW,YAAY;AAC5D,eAAW;AACX,WAAO;AACP,YAAQ;AAAA,EACV,WAAW,UAAU,yBAAyB,WAAW,aAAa;AACpE,eAAW;AACX,WAAO;AACP,YAAQ;AAAA,EACV,WACE,UAAU,kBACV;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,SAAS,MAAM,GACjB;AACA,eAAW;AACX,WAAO,gBAAgB,OAAO,WAAW,KAAK,GAAG,CAAC;AAClD,YAAQ,OAAO,WAAW,KAAK,GAAG;AAAA,EACpC,WACE,UAAU,kBACV,CAAC,UAAU,WAAW,aAAa,cAAc,cAAc,EAAE,SAAS,MAAM,GAChF;AACA,eAAW;AACX,WAAO,gBAAgB,OAAO,WAAW,KAAK,GAAG,CAAC;AAClD,YAAQ,OAAO,WAAW,KAAK,GAAG;AAAA,EACpC,OAAO;AACL,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,oBAAoB,UAAU,KAAK;AAAA,IAC5C;AAAA,IACA,UAAU;AAAA,MACR,GAAG;AAAA,MACH,mBAAmB,SAAS;AAAA,MAC5B,cAAc,SAAS;AAAA,MACvB,gBAAgB,SAAS;AAAA,IAC3B;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAe,2BACb,YACA,cACA;AACA,QAAM,EAAE,WAAW,YAAY,SAAS,IAAI;AAC5C,MAAI,CAAC,aAAa,CAAC,cAAc,CAAC,UAAU;AAC1C,UAAM,IAAI,MAAM,uBAAuB,aAAa,EAAE,kCAAkC;AAAA,EAC1F;AACA,QAAM,QAAQ,aAAa,gBAAgB;AAC3C,MAAI,UAAU,MAAM,WAAW,qBAAqB,YAAY,KAAK;AACrE,MAAI,CAAC,SAAS;AACZ,UAAM,OAAO;AAAA,MACX,kBAAkB;AAAA,MAClB,qBAAqB,aAAa,KAAK;AAAA,MACvC,GAAI,QAAQ,EAAE,cAAc,MAAM,IAAI,CAAC;AAAA,IACzC;AACA,cAAU,MAAM,WAAW,cAAc;AAAA,MACvC,IAAI;AAAA,MACJ,SAAS,aAAa,KAAK;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACA,MAAI,QAAQ,OAAO,MAAM,MAAM,UAAU;AACvC,UAAM,QAAQ,OAAO,OAAO,EAAE,UAAU,WAAW,MAAM,CAAC;AAAA,EAC5D;AACA,MAAI,QAAQ,OAAO,MAAM,MAAM,UAAU;AACvC,UAAM,IAAI,MAAM,WAAW,SAAS,wBAAwB,QAAQ,GAAG;AAAA,EACzE;AACA,SAAO;AACT;AAEA,IAAM,kBAAkB,oBAAI,IAAI,CAAC,qBAAqB,2BAA2B,CAAC;AAClF,IAAM,yBAAyB,oBAAI,IAAI,CAAC,SAAS,YAAY,OAAO,CAAC;AACrE,IAAM,8BAA8B;AACpC,IAAM,qBAAqB,oBAAI,IAAI;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,eAAe,yBACb,cACA,QACkB;AAClB,MAAI,CAAC,mBAAmB,IAAI,aAAa,IAAI,EAAG,QAAO;AACvD,QAAM,SAAS,aAAa,SAAS;AACrC,QAAM,aAAa,aAAa,SAAS;AACzC,MAAI,CAAC,UAAU,CAAC,WAAY,QAAO;AACnC,QAAM,mBAAmB,OAAO,YAAY;AAC5C,MAAI,aAAa,SAAS,YAAY,YAAY,MAAM,SAAS,iBAAiB,SAAS,OAAO,GAAG;AACnG,WAAO,gBAAgB,IAAI,gBAAgB;AAAA,EAC7C;AACA,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,kBAAkB,IAAI,gBAAgB;AAC5C,MAAI;AACJ,MAAI;AACF,UAAM,aAAa,MAAM,QAAQ,KAAK;AAAA,MACpC,OAAO;AAAA,QACL,aAAa,SAAS;AAAA,QACtB;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,MAClB;AAAA,MACA,IAAI,QAAmB,aAAW;AAChC,kBAAU,WAAW,MAAM;AACzB,0BAAgB,MAAM;AACtB,kBAAQ,MAAS;AAAA,QACnB,GAAG,2BAA2B;AAAA,MAChC,CAAC;AAAA,IACH,CAAC;AACD,WAAO,eAAe,UAAa,uBAAuB,IAAI,UAAU;AAAA,EAC1E,QAAQ;AACN,WAAO;AAAA,EACT,UAAE;AACA,QAAI,QAAS,cAAa,OAAO;AAAA,EACnC;AACF;AAEA,eAAsB,sBACpB,QACA,cACkE;AAClE,QAAM,eAAe,sBAAsB,MAAM;AACjD,MAAI,CAAC,aAAc,QAAO,EAAE,WAAW,GAAG,QAAQ,GAAG,SAAS,KAAK;AACnE,QAAM,qBACJ,aAAa,uBACZ,CAAC,MAAiC,yBAAyB,GAAG,aAAa,MAAM;AACpF,MAAI,CAAE,MAAM,mBAAmB,YAAY,GAAI;AAC7C,WAAO,EAAE,WAAW,GAAG,QAAQ,GAAG,SAAS,KAAK;AAAA,EAClD;AAEA,QAAM,SAAS;AAAA,IACb,wBAAwB,aAAa,SAAS,eAAe,SAAS;AAAA,IACtE,sBAAsB,aAAa,SAAS,aAAa,SAAS;AAAA,IAClE,iBAAiB,aAAa,SAAS,kBAAkB,SAAS;AAAA,EACpE;AACA,QAAM,oBACJ,aAAa,sBACZ,CAAC,oBAAoD,YAA4C;AAChG,QAAI,CAAC,aAAa,OAAQ,OAAM,IAAI,MAAM,+DAA+D;AACzG,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,aAAa,OAAO;AAAA,IACtB;AAAA,EACF;AACF,QAAM,qBACJ,aAAa,uBACZ,CAAC,IAAY,WAAyC;AACrD,QAAI,CAAC,aAAa,OAAQ,OAAM,IAAI,MAAM,iEAAiE;AAC3G,WAAO,8BAA8B,IAAI,QAAQ,aAAa,OAAO,kBAAkB;AAAA,EACzF;AACF,QAAM,gBAAgB,MAAM,kBAAkB,QAAQ,EAAE,iBAAiB,aAAa,WAAW,WAAW,CAAC;AAC7G,MAAI,YAAY;AAChB,MAAI,SAAS;AAEb,aAAW,gBAAgB,eAAe;AACxC,QAAI;AACF,YAAM,UAAU,MAAM,2BAA2B,aAAa,YAAY,YAAY;AACtF,YAAM,SAAS,MAAM,QAAQ,uBAAuB;AAAA,QAClD,QAAQ;AAAA,QACR,MAAM,aAAa;AAAA,QACnB,SAAS,aAAa;AAAA,QACtB,UAAU,aAAa;AAAA,QACvB,SAAS,aAAa;AAAA,QACtB,UAAU,OAAO;AAAA,QACjB,WAAW,GAAG,OAAO,UAAU,IAAI,aAAa,SAAS,IAAI,aAAa,QAAQ;AAAA,QAClF,aAAa,UAAU,aAAa,KAAK,oBAAoB,iBAAiB,aAAa,KAAK,eAAe;AAAA,QAC/G,UAAU;AAAA,UACR,OAAO,aAAa,SAAS;AAAA,UAC7B,QAAQ,aAAa;AAAA,UACrB,YAAY,aAAa,SAAS;AAAA,UAClC,aAAa,aAAa,SAAS;AAAA,UACnC,mBAAmB,aAAa,SAAS;AAAA,UACzC,WAAW,sBAAsB,OAAO,OAAO,OAAO,OAAO;AAAA,UAC7D,YAAY,OAAO;AAAA,QACrB;AAAA,MACF,CAAC;AACD,YAAM,QAAQ,IAAI,CAAC,OAAO,WAAW,OAAO,QAAQ,EAAE,OAAO,OAAO,CAAC;AACrE,UAAI,aAAa,UAAU;AACzB,cAAM,mBAAmB,aAAa,IAAI,aAAa,SAAS,wBAAwB,WAAW,QAAQ;AAAA,MAC7G,WAAW,aAAa,WAAW,YAAY;AAC7C,cAAM,mBAAmB,aAAa,IAAI,MAAM;AAAA,MAClD;AACA,mBAAa;AAAA,IACf,SAAS,OAAO;AACd,gBAAU;AACV,mBAAa,gBAAgB,cAAc,KAAK;AAAA,IAClD;AAAA,EACF;AAEA,SAAO,EAAE,WAAW,QAAQ,SAAS,MAAM;AAC7C;AAEA,eAAsB,oBACpB,GACA,SAC8B;AAC9B,QAAM,SAAS,MAAM,mBAAmB,GAAG,QAAQ,OAAO,aAAa;AACvE,MAAI,YAAY,OAAQ,QAAO;AAE/B,MAAI,CAAC,gCAAgC,IAAI,OAAO,KAAK,GAAG;AACtD,WAAO,EAAE,QAAQ,KAAK,MAAM,EAAE,IAAI,MAAM,SAAS,KAAK,EAAE;AAAA,EAC1D;AAEA,QAAM,WAAW,+BAA+B,MAAM;AACtD,UAAQ,KAAK,oBAAoB,QAAQ;AAEzC,MAAI,QAAQ,oBAAoB;AAC9B,UAAM,QAAQ,mBAAmB,MAAM;AAAA,EACzC,OAAO;AACL,UAAM,iBAAiB,uBAAuB,MAAM;AACpD,QAAI,kBAAkB,QAAQ,gBAAgB;AAC5C,WAAK,QAAQ,eAAe,cAAc,EAAE,MAAM,CAAC,UAAmB;AACpE,gBAAQ,MAAM,+CAA+C;AAAA,UAC3D,YAAY,SAAS;AAAA,UACrB,YAAY,SAAS;AAAA,UACrB,aAAa,SAAS;AAAA,UACtB,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAC9D,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,CAAC,QAAQ,YAAY;AACvB,WAAO,EAAE,QAAQ,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE;AAAA,EAC3C;AAEA,QAAM,SAAS,MAAM,sBAAsB,QAAQ,OAA4C;AAC/F,MAAI,OAAO,SAAS,GAAG;AACrB,YAAQ,KAAK,oBAAoB,OAAO,MAAM,6CAA6C,OAAO,UAAU,GAAG;AAAA,EACjH;AACA,SAAO,EAAE,QAAQ,KAAK,MAAM,EAAE,IAAI,MAAM,GAAI,OAAO,UAAU,EAAE,SAAS,KAAc,IAAI,CAAC,EAAG,EAAE;AAClG;;;AP9bA,SAAS,MAAM,GAA0B;AACvC,SAAO;AACT;AAoDA,eAAe,6BACb,UACA,kBAC6B;AAC7B,MAAI,CAAC,YAAY,CAAC,iBAAkB,QAAO;AAC3C,MAAI;AACF,UAAM,UAAU,MAAM,SAAS,QAAQ,EAAE,IAAI,iBAAiB,CAAC;AAC/D,WAAO,SAAS,kBAAkB;AAAA,EACpC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,yBAAyB,OAAe,cAA0C;AACzF,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,KAAK;AACzB,UAAM,QAAQ,IAAI,SAAS,MAAM,oCAAoC;AACrE,QACE,IAAI,aAAa,YACjB,IAAI,aAAa,gBACjB,QAAQ,CAAC,GAAG,YAAY,MAAM,aAAa,YAAY,GACvD;AACA,aAAO;AAAA,IACT;AACA,UAAM,SAAS,OAAO,MAAM,CAAC,CAAC;AAC9B,WAAO,OAAO,UAAU,MAAM,KAAK,SAAS,IAAI,SAAS;AAAA,EAC3D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,0BAA0B,OAAe,cAAsB,aAA8B;AACpG,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,KAAK;AACzB,UAAM,CAAC,OAAO,IAAI,IAAI,aAAa,MAAM,GAAG;AAC5C,WACE,IAAI,aAAa,YACjB,IAAI,aAAa,gBACjB,IAAI,aAAa,IAAI,KAAK,IAAI,IAAI,WAAW,WAAW,MACxD,IAAI,WAAW,MACf,IAAI,SAAS;AAAA,EAEjB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAQA,SAASC,eAAc,OAAiC;AACtD,SAAO,OAAO,UAAU,YAAY,MAAM,SAAS,KAAK,MAAM,UAAU,OAAO,qBAAqB,KAAK,KAAK;AAChH;AAeA,eAAe,iBACb,GACA,MACiF;AACjF,QAAM,KAAK,WAAW,CAAC;AACvB,QAAM,SAAS,KAAK,OAAO,CAAC;AAC5B,MAAI,CAAC,OAAQ,QAAO,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,eAAe,GAAG,GAAG,EAAE;AACvE,MAAI,CAAC,OAAO,OAAO;AACjB,WAAO;AAAA,MACL,UAAU,EAAE;AAAA,QACV;AAAA,UACE,OAAO;AAAA,UACP,SAAS;AAAA,QACX;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,EAAE,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAO,EAAE;AAClE;AAMA,SAAS,cAAc,KAAwC;AAC7D,MAAI,QAAQ,OAAW,QAAO;AAC9B,MAAI,CAAC,YAAY,KAAK,GAAG,EAAG,QAAO;AACnC,QAAM,OAAO,OAAO,GAAG;AACvB,SAAO,QAAQ,IAAI,OAAO;AAC5B;AAEA,IAAM,4BAA4B,oBAAI,IAAI,CAAC,gBAAgB,gBAAgB,CAAC;AAE5E,SAAS,sBAAsB,KAAoD;AACjF,MAAI,QAAQ,UAAa,QAAQ,GAAI,QAAO;AAC5C,MAAI,0BAA0B,IAAI,GAAG,EAAG,QAAO;AAC/C,SAAO;AACT;AAEA,SAAS,sBAAsB,KAAwC;AACrE,MAAI,CAAC,OAAO,CAAC,aAAa,KAAK,GAAG,EAAG,QAAO;AAC5C,QAAM,cAAc,OAAO,GAAG;AAC9B,SAAO,OAAO,cAAc,WAAW,KAAK,cAAc,IAAI,cAAc;AAC9E;AAEA,SAAS,gBAAgB,OAA0B;AACjD,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACnC,SAAO,MAAM,OAAO,CAAC,SAAyB,OAAO,SAAS,YAAY,KAAK,SAAS,CAAC;AAC3F;AAUA,eAAe,yBAAyB,MAIM;AAC5C,QAAM,oBAAoB,MAAM,KAAK,OAAO,qBAAqB,oBAAoB,IAAI;AAAA,IACvF,OAAO,KAAK;AAAA,IACZ,IAAI,KAAK;AAAA,EACX,CAAC;AACD,MAAI,CAAC,kBAAmB,QAAO;AAC/B,QAAM,aAAa,MAAM,KAAK,OAAO,qBAAqB,YAAY,IAAI;AAAA,IACxE,OAAO,KAAK;AAAA,IACZ,IAAI,kBAAkB;AAAA,EACxB,CAAC;AACD,MAAI,CAAC,WAAY,QAAO;AACxB,QAAM,aAAa,MAAM,KAAK,OAAO,qBAAqB,aAAa,IAAI;AAAA,IACzE,OAAO,KAAK;AAAA,IACZ,IAAI,kBAAkB;AAAA,EACxB,CAAC;AACD,MAAI,CAAC,WAAY,QAAO;AACxB,QAAM,eAAe,MAAM,KAAK,OAAO,qBAAqB,cAAc,IAAI;AAAA,IAC5E,OAAO,KAAK;AAAA,IACZ,IAAI,WAAW;AAAA,EACjB,CAAC;AACD,MAAI,CAAC,aAAc,QAAO;AAC1B,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA,kBAAkB,WAAW;AAAA,IAC7B,eAAe,kBAAkB,UAAU,WAAW;AAAA,EACxD;AACF;AAEA,SAAS,iBACP,SACA,OAQqB;AACrB,QAAM,eAAe,OAAO,QAAQ,WAAW,UAAU;AACzD,SAAO;AAAA,IACL,OAAO;AAAA,IACP,YAAY,QAAQ,YAAY,UAAU,MAAM,MAAM,IAAI,MAAM,SAAS;AAAA,IACzE,SAAS;AAAA,MACP,QAAQ;AAAA,MACR,cAAc,EAAE,IAAI,OAAO,QAAQ,aAAa,UAAU,EAAE;AAAA,MAC5D,YAAY,EAAE,IAAI,cAAc,WAAW,QAAQ,WAAW,KAAK;AAAA,MACnE,QAAQ,EAAE,OAAO,MAAM,UAAU,cAAc;AAAA,MAC/C,OAAO;AAAA,QACL,QAAQ,MAAM;AAAA,QACd,OAAO,MAAM;AAAA,QACb,UAAU,MAAM;AAAA,QAChB,YAAY,MAAM;AAAA,QAClB,QAAQ,MAAM,OAAO,IAAI,WAAS,EAAE,KAAK,EAAE;AAAA,MAC7C;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,uBACP,SACA,aASqB;AACrB,QAAM,eAAe,OAAO,QAAQ,WAAW,UAAU;AACzD,SAAO;AAAA,IACL,OAAO;AAAA,IACP,YAAY,QAAQ,YAAY,iBAAiB,YAAY,MAAM,IAAI,YAAY,SAAS;AAAA,IAC5F,SAAS;AAAA,MACP,QAAQ;AAAA,MACR,cAAc,EAAE,IAAI,OAAO,QAAQ,aAAa,UAAU,EAAE;AAAA,MAC5D,YAAY,EAAE,IAAI,cAAc,WAAW,QAAQ,WAAW,KAAK;AAAA,MACnE,QAAQ,EAAE,OAAO,YAAY,UAAU,cAAc;AAAA,MACrD,cAAc;AAAA,QACZ,QAAQ,YAAY;AAAA,QACpB,OAAO,YAAY;AAAA,QACnB,UAAU,YAAY;AAAA,QACtB,YAAY,YAAY;AAAA,QACxB,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,MAAM,EAAE,KAAK,YAAY,WAAW;AAAA,QACpC,MAAM,EAAE,KAAK,YAAY,WAAW;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAe,mBACb,QACA,oBACe;AACf,MAAI,CAAC,mBAAoB;AACzB,QAAM,UAAU,MAAM,QAAQ,WAAW,OAAO,IAAI,WAAS,mBAAmB,KAAK,CAAC,CAAC;AACvF,QAAM,WAAW,QAAQ,KAAK,CAAC,WAA4C,OAAO,WAAW,UAAU;AACvG,MAAI,SAAU,OAAM,SAAS;AAC/B;AAMO,SAAS,kBAAkB,SAA+C;AAC/E,QAAM,SAAqB,CAAC;AAC5B,QAAM,EAAE,MAAM,OAAO,SAAS,QAAQ,aAAa,UAAU,IAAI;AACjE,QAAM,cAAc,MAClB,4BAA4B,EAAE,QAAQ,MAAM,iBAAiB,YAAY,QAAW,aAAa,MAAM,CAAC;AAG1G,SAAO;AAAA,IACL,iBAAiB,sBAAsB;AAAA,MACrC,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,YAAI,CAAC,uBAAuB,EAAE,QAAQ,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,aAAa;AACxE,iBAAO,EAAE,KAAK;AAAA,YACZ,SAAS;AAAA,YACT,WAAW;AAAA,YACX,eAAe,CAAC;AAAA,YAChB,QAAQ;AAAA,YACR,aAAa,YAAY;AAAA,UAC3B,CAAC;AAAA,QACH;AAGA,cAAM,KAAK,WAAW,MAAM,CAAC,CAAC;AAC9B,cAAM,SAAS,KAAK,OAAO,MAAM,CAAC,CAAC;AACnC,YAAI,CAAC,OAAQ,QAAO,EAAE,KAAK,EAAE,OAAO,gBAAgB,QAAQ,gBAAgB,GAAG,GAAG;AAIlF,YAAI,CAAC,OAAO,OAAO;AACjB,iBAAO,EAAE,KAAK;AAAA,YACZ,SAAS;AAAA,YACT,gBAAgB,MAAM;AAAA,YACtB,sBAAsB;AAAA,YACtB,WAAW;AAAA,YACX,eAAe,CAAC;AAAA,YAChB,QAAQ;AAAA,YACR,aAAa,YAAY;AAAA,UAC3B,CAAC;AAAA,QACH;AAEA,cAAM,OAAO,QAAQ,SACjB,MAAM,QAAQ,OAAO,qBAAqB,cAAc,KAAK,EAAE,OAAO,OAAO,MAAM,CAAC,IACpF,CAAC;AAEL,cAAM,YAAY,KAAK,SAAS;AAChC,eAAO,EAAE,KAAK;AAAA,UACZ,SAAS;AAAA,UACT,gBAAgB,MAAM;AAAA,UACtB;AAAA,UACA,eAAe,KAAK,IAAI,QAAM;AAAA,YAC5B,gBAAgB,OAAO,EAAE,UAAU;AAAA,YACnC,cAAc,EAAE;AAAA,YAChB,aAAa,EAAE;AAAA,UACjB,EAAE;AAAA,UACF,QAAQ,YAAY,UAAU;AAAA,UAC9B,aAAa,YAAY;AAAA,QAC3B,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAKA,MAAI,CAAC,uBAAuB,EAAE,QAAQ,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,aAAa;AACxE,WAAO;AAAA,EACT;AACA,QAAM,YAAY,CAAC,OAAe,WAA2B,YAAY,KAAK,OAAO,MAAM;AAC3F,QAAM,cAAc,CAAC,UAA8B,YAAY,OAAO,KAAK;AAE3E,QAAM,EAAE,eAAe,IAAI;AAC3B,QAAM,sBAAsB,iBACxB,OAAO,UAA0E;AAC/E,QAAI,CAAC,MAAM,cAAc,CAAC,MAAM,aAAa;AAC3C,YAAM,IAAI,MAAM,qEAAqE;AAAA,IACvF;AACA,UAAM,OAAO,eAAe,MAAM,gBAAgB,MAAM,YAAY,MAAM,aAAa,CAAC,cAAc,CAAC;AACvG,WAAO,eAAe;AAAA,MACpB,GAAG;AAAA,MACH,gBACE,MAAM,kBAAmB,MAAM,6BAA6B,QAAQ,UAAU,MAAM,UAAU;AAAA,MAChG,QAAQ,MAAM,OAAO,SAAS,cAAc,IAAI,MAAM,SAAS,CAAC,GAAG,MAAM,QAAQ,cAAc;AAAA,IACjG,CAAC;AAAA,EACH,IACA;AAEJ,SAAO;AAAA,IACL,iBAAiB,6BAA6B;AAAA,MAC5C,QAAQ;AAAA,MACR,SAAS,OAAM,MAAK;AAClB,cAAM,KAAK,WAAW,MAAM,CAAC,CAAC;AAC9B,cAAM,SAAS,KAAK,OAAO,MAAM,CAAC,CAAC;AACnC,YAAI,CAAC,QAAQ,MAAO,QAAO,EAAE,KAAK,EAAE,OAAO,eAAe,GAAG,GAAG;AAEhE,cAAM,aAAa,EAAE,IAAI,MAAM,YAAY;AAC3C,cAAM,WAAW,EAAE,IAAI,MAAM,UAAU;AACvC,cAAM,eAAe,EAAE,IAAI,MAAM,OAAO;AACxC,YAAI,CAAC,cAAc,CAAC,SAAU,QAAO,EAAE,KAAK,EAAE,OAAO,uCAAuC,GAAG,GAAG;AAElG,cAAM,gBAAgB,MAAM;AAAA,UAC1B;AAAA,YACE,OAAO,OAAO;AAAA,YACd;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,UACA,OAAO;AAAA,QACT;AACA,eAAO,EAAE,KAAK;AAAA,UACZ,eAAe,cAAc,IAAI,mBAAiB;AAAA,YAChD,IAAI,aAAa;AAAA,YACjB,cAAc,aAAa,KAAK;AAAA,YAChC,mBAAmB,OAAO,aAAa,KAAK,eAAe;AAAA,YAC3D,QAAQ,aAAa;AAAA,YACrB,KAAK,sBAAsB,aAAa,KAAK,cAAc,SAAS,aAAa,KAAK,eAAe;AAAA,UACvG,EAAE;AAAA,QACJ,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,IACD,iBAAiB,uBAAuB;AAAA,MACtC,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,SAAS,MAAM,oBAAoB,MAAM,CAAC,GAAG;AAAA,UACjD;AAAA,UACA,gBAAgB;AAAA,UAChB,oBAAoB,QAAQ;AAAA,UAC5B,GAAI,QAAQ,aACR;AAAA,YACE,YAAY,QAAQ;AAAA,YACpB,eAAe,CAAC,cAAc,UAAU;AACtC,sBAAQ;AAAA,gBACN,qDAAqD,aAAa,EAAE,KAAK,aAAa,UAAU,IAAI,aAAa,QAAQ;AAAA,gBACzH;AAAA,cACF;AAAA,YACF;AAAA,UACF,IACA,CAAC;AAAA,QACP,CAAC;AACD,eAAO,EAAE,KAAK,OAAO,MAAM,OAAO,MAAM;AAAA,MAC1C;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,cAAc,QAAQ,eAAe,IAAI,QAAQ,WAAW,IAAI,QAAQ,OAAO,EAAE,CAAC;AAgBxF,SAAO;AAAA,IACL,iBAAiB,wBAAwB;AAAA,MACvC,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,WAAW,MAAM,iBAAiB,MAAM,CAAC,GAAG,IAAI;AACtD,YAAI,cAAc,SAAU,QAAO,SAAS;AAC5C,cAAM,QAAQ,UAAU,SAAS,OAAO,OAAO,SAAS,OAAO,MAAM;AACrE,YAAI,EAAE,IAAI,MAAM,QAAQ,EAAG,QAAO,EAAE,SAAS,OAAO,gBAAgB,KAAK,CAAC;AAC1E,eAAO,EAAE,SAAS,OAAO,sBAAsB,OAAO,WAAW,CAAC;AAAA,MACpE;AAAA,IACF,CAAC;AAAA,EACH;AAGA,SAAO;AAAA,IACL,iBAAiB,yBAAyB;AAAA,MACxC,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,WAAW,MAAM,iBAAiB,MAAM,CAAC,GAAG,IAAI;AACtD,YAAI,cAAc,SAAU,QAAO,SAAS;AAC5C,cAAM,EAAE,OAAO,OAAO,IAAI,SAAS;AAEnC,cAAM,QAAQ,EAAE,IAAI,MAAM,OAAO;AACjC,YAAI,CAAC,OAAO;AAKV,iBAAO,EAAE,SAAS,OAAO,sBAAsB,UAAU,OAAO,MAAM,GAAG,WAAW,CAAC;AAAA,QACvF;AACA,cAAM,cAAc,YAAY,KAAK;AACrC,YAAI,CAAC,eAAe,YAAY,WAAW,UAAU,YAAY,UAAU,OAAO;AAGhF,kBAAQ;AAAA,YACN;AAAA,YACA,KAAK,UAAU;AAAA,cACb,YAAY,QAAQ,WAAW;AAAA,cAC/B,YAAY,aAAa;AAAA,cACzB,aAAa,aAAa;AAAA,cAC1B,cAAc;AAAA,cACd,eAAe;AAAA,YACjB,CAAC;AAAA,UACH;AACA,iBAAO,EAAE,SAAS,gBAAgB;AAAA,QACpC;AAEA,cAAM,OAAO,EAAE,IAAI,MAAM,MAAM;AAM/B,YAAI,CAAC,MAAM;AACT,iBAAO,EAAE,SAAS,OAAO,sBAAsB,UAAU,OAAO,MAAM,GAAG,WAAW,CAAC;AAAA,QACvF;AAEA,YAAI;AACF,gBAAM,YAAY,MAAM,OAAO,kBAAkB,MAAM,WAAW;AAClE,gBAAM,gBAAgB,MAAM,OAAO,sBAAsB,SAAS;AAClE,cAAI,cAAc,WAAW,GAAG;AAK9B,mBAAO,EAAE,SAAS,OAAO,gBAAgB,UAAU,OAAO,MAAM,CAAC,CAAC;AAAA,UACpE;AACA,qBAAW,QAAQ,eAAe;AAEhC,kBAAM,OAAO,qBAAqB,cAAc,OAAO;AAAA,cACrD;AAAA,cACA,mBAAmB;AAAA,cACnB,YAAY,KAAK,eAAe,SAAS;AAAA,cACzC,aAAa,KAAK;AAAA,cAClB,aAAa,KAAK;AAAA,YACpB,CAAC;AAAA,UACH;AAAA,QACF,SAAS,OAAO;AACd,kBAAQ;AAAA,YACN,qEAAqE,KAAK,WAAW,MAAM;AAAA,YAC3F;AAAA,UACF;AACA,iBAAO,EAAE,SAAS,gBAAgB;AAAA,QACpC;AAEA,eAAO,EAAE,SAAS,oBAAoB;AAAA,MACxC;AAAA,IACF,CAAC;AAAA,EACH;AAGA,SAAO;AAAA,IACL,iBAAiB,qBAAqB;AAAA,MACpC,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,WAAW,MAAM,iBAAiB,MAAM,CAAC,GAAG,IAAI;AACtD,YAAI,cAAc,SAAU,QAAO,SAAS;AAE5C,cAAM,WAAW,MAAM,OAAO,qBAAqB,cAAc,KAAK,EAAE,OAAO,SAAS,OAAO,MAAM,CAAC;AAEtG,cAAM,SAAS,EAAE,IAAI,MAAM,GAAG,KAAK,IAAI,YAAY;AACnD,cAAM,QAAQ,CAAC;AACf,cAAM,oBAAoB,oBAAI,IAAY;AAC1C,mBAAW,QAAQ,UAAU;AAC3B,cAAI;AACJ,cAAI;AACF,mBAAO,MAAM,OAAO,sBAAsB,OAAO,KAAK,UAAU,CAAC;AAAA,UACnE,SAAS,KAAK;AAMZ,gBAAK,IAA4B,WAAW,IAAK,OAAM;AACvD,oBAAQ,MAAM,sDAAsD,KAAK,UAAU,oBAAoB;AACvG,kBAAM,OAAO,qBAAqB,cAAc,OAAO,EAAE,OAAO,SAAS,OAAO,OAAO,IAAI,KAAK,GAAG,CAAC;AACpG;AAAA,UACF;AACA,qBAAW,QAAQ,MAAM;AACvB,gBAAI,SAAS,CAAC,KAAK,SAAS,YAAY,EAAE,SAAS,KAAK,EAAG;AAC3D,gBAAI,kBAAkB,IAAI,KAAK,EAAE,EAAG;AACpC,8BAAkB,IAAI,KAAK,EAAE;AAC7B,kBAAM,aAAa,MAAM,OAAO,qBAAqB,aAAa,OAAO;AAAA,cACvE,OAAO,SAAS,OAAO;AAAA,cACvB,OAAO;AAAA,gBACL,gBAAgB,KAAK;AAAA,gBACrB,YAAY,KAAK,GAAG,SAAS;AAAA,gBAC7B,MAAM,KAAK;AAAA,gBACX,eAAeA,eAAc,KAAK,aAAa,IAAI,KAAK,gBAAgB;AAAA,gBACxE,kBAAkB,EAAE,SAAS,KAAK,SAAS,OAAO,KAAK,MAAM;AAAA,cAC/D;AAAA,YACF,CAAC;AACD,kBAAM,KAAK;AAAA,cACT,GAAG;AAAA,cACH,uBAAuB,KAAK;AAAA,cAC5B,qBAAqB,WAAW;AAAA,cAChC,iBAAiB,MAAM;AAAA,cACvB,gBAAgB,MAAM,eAAe,KAAK,QAAQ;AAAA,YACpD,CAAC;AAAA,UACH;AAAA,QACF;AACA,eAAO,EAAE,KAAK,EAAE,MAAM,CAAC;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACH;AAGA,SAAO;AAAA,IACL,iBAAiB,mCAAmC;AAAA,MAClD,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,WAAW,MAAM,iBAAiB,MAAM,CAAC,GAAG,IAAI;AACtD,YAAI,cAAc,SAAU,QAAO,SAAS;AAC5C,cAAM,EAAE,OAAO,OAAO,IAAI,SAAS;AAEnC,YAAI,CAAC,MAAM,SAAS;AAClB,iBAAO,EAAE,KAAK,EAAE,OAAO,0BAA0B,SAAS,qCAAqC,GAAG,GAAG;AAAA,QACvG;AAEA,cAAM,sBAAsB,EAAE,IAAI,MAAM,IAAI;AAC5C,YAAI,CAAC,oBAAqB,QAAO,EAAE,KAAK,EAAE,OAAO,+BAA+B,GAAG,GAAG;AACtF,cAAM,UAAU,MAAM,yBAAyB,EAAE,QAAQ,OAAO,oBAAoB,CAAC;AACrF,YAAI,CAAC,SAAS;AACZ,iBAAO,EAAE,KAAK,EAAE,OAAO,+BAA+B,GAAG,GAAG;AAAA,QAC9D;AAKA,cAAM,eAAe,EAAE,IAAI,OAAO,QAAQ,KAAK,IAAI,SAAS,mBAAmB;AAC/E,YAAI,aAAa;AACf,iBAAO,UAAU,MAAM,CAAC,GAAG,OAAM,WAAU;AACzC,gBAAI;AACF,oBAAM,SAAS,MAAM,eAAe;AAAA,gBAClC;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA,YAAY,QAAM,KAAK,OAAO,SAAS,EAAE,OAAO,YAAY,MAAM,KAAK,UAAU,EAAE,EAAE,CAAC;AAAA,cACxF,CAAC;AACD,oBAAM,OAAO,SAAS,EAAE,OAAO,QAAQ,MAAM,KAAK,UAAU,MAAM,EAAE,CAAC;AAAA,YACvE,SAAS,KAAK;AACZ,oBAAM,OAAO,SAAS,EAAE,OAAO,SAAS,MAAM,KAAK,UAAU,mBAAmB,GAAG,EAAE,IAAI,EAAE,CAAC;AAAA,YAC9F;AAAA,UACF,CAAC;AAAA,QACH;AAEA,YAAI;AACF,gBAAM,SAAS,MAAM,eAAe,EAAE,QAAQ,OAAO,SAAS,OAAO,CAAC;AACtE,iBAAO,EAAE,KAAK,MAAM;AAAA,QACtB,SAAS,KAAK;AACZ,gBAAM,EAAE,QAAQ,KAAK,IAAI,mBAAmB,GAAG;AAC/C,iBAAO,EAAE,KAAK,MAAM,MAAM;AAAA,QAC5B;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAGA,SAAO;AAAA,IACL,iBAAiB,mCAAmC;AAAA,MAClD,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,SAAS,MAAM,eAAe,EAAE,QAAQ,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;AACjE,YAAI,cAAc,OAAQ,QAAO,OAAO;AACxC,cAAM,OAAO,cAAc,EAAE,IAAI,MAAM,MAAM,CAAC;AAC9C,YAAI,SAAS,KAAM,QAAO,EAAE,KAAK,EAAE,OAAO,eAAe,GAAG,GAAG;AAC/D,cAAM,QAAQ,sBAAsB,EAAE,IAAI,MAAM,OAAO,CAAC;AACxD,YAAI,UAAU,KAAM,QAAO,EAAE,KAAK,EAAE,OAAO,gBAAgB,GAAG,GAAG;AACjE,YAAI;AACF,gBAAM,EAAE,QAAQ,WAAW,IAAI,MAAM,OAAO,OAAO,WAAW;AAAA,YAC5D,YAAY;AAAA,cACV,MAAM;AAAA,cACN,gBAAgB,OAAO,OAAO,QAAQ,aAAa,UAAU;AAAA,YAC/D;AAAA,YACA,WAAW,CAAC,OAAO,QAAQ,WAAW,IAAI;AAAA,YAC1C,QAAQ,QAAQ,CAAC,KAAK,IAAI;AAAA,YAC1B,QAAQ,OAAO,IAAI;AAAA,UACrB,CAAC;AACD,gBAAM,iBAAiB,OAAO,IAAI,YAAU;AAAA,YAC1C,QAAQ,OAAO,MAAM,EAAE;AAAA,YACvB,OAAO,MAAM;AAAA,YACb,KAAK,MAAM;AAAA,YACX,QAAQ,MAAM;AAAA,YACd,QAAQ,MAAM;AAAA,YACd,UAAU,MAAM,gBAAgB;AAAA,YAChC,WAAW,MAAM;AAAA,YACjB,WAAW,MAAM;AAAA,UACnB,EAAE;AACF,gBAAM;AAAA,YACJ,eAAe,IAAI,WAAS,iBAAiB,OAAO,SAAS,KAAK,CAAC;AAAA,YACnE,QAAQ;AAAA,UACV;AACA,iBAAO,EAAE,KAAK;AAAA,YACZ,QAAQ;AAAA,YACR,UAAU,eAAe,OAAO,OAAO,OAAO,UAAU;AAAA,UAC1D,CAAC;AAAA,QACH,SAAS,KAAK;AACZ,iBAAO,EAAE;AAAA,YACP,EAAE,OAAO,uBAAuB,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE;AAAA,YAC1F;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAGA,SAAO;AAAA,IACL,iBAAiB,kDAAkD;AAAA,MACjE,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,QAAQ,MAAM,iBAAiB,EAAE,QAAQ,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC;AACzE,YAAI,cAAc,MAAO,QAAO,MAAM;AACtC,cAAM,EAAE,SAAS,WAAW,IAAI;AAChC,cAAM,cAAc,sBAAsB,EAAE,IAAI,MAAM,QAAQ,CAAC;AAC/D,YAAI,gBAAgB,KAAM,QAAO,EAAE,KAAK,EAAE,OAAO,uBAAuB,GAAG,GAAG;AAE9E,YAAI;AACJ,YAAI;AACF,iBAAO,MAAM,EAAE,IAAI,KAAK;AAAA,QAC1B,QAAQ;AACN,iBAAO,EAAE,KAAK,EAAE,OAAO,oBAAoB,GAAG,GAAG;AAAA,QACnD;AACA,YAAI,OAAO,KAAK,UAAU,YAAY,KAAK,MAAM,KAAK,EAAE,WAAW,KAAK,KAAK,MAAM,SAAS,KAAM;AAChG,iBAAO,EAAE,KAAK,EAAE,OAAO,gBAAgB,GAAG,GAAG;AAAA,QAC/C;AACA,YACE,OAAO,KAAK,QAAQ,YACpB,KAAK,IAAI,KAAK,EAAE,WAAW,KAC3B,KAAK,IAAI,SAAS,QAClB,CAAC,0BAA0B,KAAK,KAAK,QAAQ,WAAW,MAAM,WAAW,GACzE;AACA,iBAAO,EAAE,KAAK,EAAE,OAAO,cAAc,GAAG,GAAG;AAAA,QAC7C;AAEA,YAAI,CAAC,eAAgB,QAAO,EAAE,KAAK,EAAE,OAAO,qBAAqB,GAAG,GAAG;AACvE,cAAM,SAAS,iBAAiB,WAAW;AAC3C,cAAM,cAAc,oBAAoB,WAAW,gBAAgB,MAAM;AACzE,cAAM,OAAO,eAAe,OAAO,QAAQ,aAAa,UAAU,GAAG,QAAQ,WAAW,MAAM,aAAa;AAAA,UACzG;AAAA,QACF,CAAC;AACD,cAAM,SAAS,MAAM,eAAe;AAAA,UAClC,YAAY,QAAQ,WAAW;AAAA,UAC/B;AAAA,UACA,YAAY,KAAK;AAAA,UACjB,UAAU,KAAK;AAAA,UACf,QAAQ,gBAAgB,KAAK,MAAM;AAAA,UACnC,gBAAgB,OAAO,QAAQ,aAAa,UAAU;AAAA,UACtD,YAAY,QAAQ;AAAA,UACpB;AAAA,UACA;AAAA,UACA,gBAAgB,MAAM,6BAA6B,QAAQ,UAAU,QAAQ,gBAAgB;AAAA,QAC/F,CAAC;AACD,cAAM,YAAY;AAAA,UAChB,SAAS,MAAM,CAAC;AAAA,UAChB,OAAO;AAAA,YACL,QAAQ;AAAA,YACR,kBAAkB,QAAQ;AAAA,YAC1B,qBAAqB,QAAQ;AAAA,YAC7B,SAAS,CAAC,EAAE,MAAM,SAAS,IAAI,OAAO,WAAW,GAAG,MAAM,KAAK,MAAM,CAAC;AAAA,YACtE,UAAU,EAAE,aAAa,QAAQ,UAAU,OAAO,SAAS;AAAA,UAC7D;AAAA,QACF,CAAC;AACD,eAAO,EAAE;AAAA,UACP;AAAA,YACE,IAAI;AAAA,YACJ,UAAU,OAAO;AAAA,YACjB,aAAa,OAAO,eAAe;AAAA,YACnC,QAAQ,OAAO,UAAU;AAAA,UAC3B;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAGA,SAAO;AAAA,IACL,iBAAiB,gCAAgC;AAAA,MAC/C,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,SAAS,MAAM,eAAe,EAAE,QAAQ,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;AACjE,YAAI,cAAc,OAAQ,QAAO,OAAO;AACxC,cAAM,OAAO,cAAc,EAAE,IAAI,MAAM,MAAM,CAAC;AAC9C,YAAI,SAAS,KAAM,QAAO,EAAE,KAAK,EAAE,OAAO,eAAe,GAAG,GAAG;AAC/D,YAAI;AACF,gBAAM,EAAE,cAAc,WAAW,IAAI,MAAM,OAAO,eAAe,iBAAiB;AAAA,YAChF,YAAY;AAAA,cACV,MAAM;AAAA,cACN,gBAAgB,OAAO,OAAO,QAAQ,aAAa,UAAU;AAAA,YAC/D;AAAA,YACA,UAAU,OAAO,QAAQ,WAAW;AAAA,YACpC,eAAe;AAAA,YACf,QAAQ,OAAO,IAAI;AAAA,UACrB,CAAC;AACD,gBAAM,uBAAuB,aAAa,IAAI,SAAO;AAAA,YACnD,QAAQ,OAAO,GAAG,EAAE;AAAA,YACpB,OAAO,GAAG;AAAA,YACV,KAAK,GAAG;AAAA,YACR,QAAQ,GAAG;AAAA,YACX,YAAY,GAAG;AAAA,YACf,YAAY,GAAG;AAAA,YACf,WAAW,GAAG;AAAA,YACd,WAAW,GAAG;AAAA,UAChB,EAAE;AACF,gBAAM;AAAA,YACJ,qBAAqB,IAAI,iBAAe,uBAAuB,OAAO,SAAS,WAAW,CAAC;AAAA,YAC3F,QAAQ;AAAA,UACV;AACA,iBAAO,EAAE,KAAK;AAAA,YACZ,cAAc;AAAA,YACd,UAAU,eAAe,OAAO,OAAO,OAAO,UAAU;AAAA,UAC1D,CAAC;AAAA,QACH,SAAS,KAAK;AACZ,iBAAO,EAAE;AAAA,YACP,EAAE,OAAO,uBAAuB,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE;AAAA,YAC1F;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAGA,SAAO;AAAA,IACL,iBAAiB,qCAAqC;AAAA,MACpD,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,SAAS,MAAM,eAAe,EAAE,QAAQ,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;AACjE,YAAI,cAAc,OAAQ,QAAO,OAAO;AACxC,eAAO,EAAE,KAAK,EAAE,cAAc,OAAO,QAAQ,aAAa,CAAC;AAAA,MAC7D;AAAA,IACF,CAAC;AAAA,EACH;AAGA,SAAO;AAAA,IACL,iBAAiB,qCAAqC;AAAA,MACpD,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,SAAS,MAAM,eAAe,EAAE,QAAQ,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;AACjE,YAAI,cAAc,OAAQ,QAAO,OAAO;AAExC,YAAI;AACJ,YAAI;AACF,iBAAO,MAAM,EAAE,IAAI,KAAK;AAAA,QAC1B,QAAQ;AACN,iBAAO,EAAE,KAAK,EAAE,OAAO,oBAAoB,GAAG,GAAG;AAAA,QACnD;AACA,YAAI,KAAK,iBAAiB,QAAQ,OAAO,KAAK,iBAAiB,UAAU;AACvE,iBAAO,EAAE,KAAK,EAAE,OAAO,uBAAuB,GAAG,GAAG;AAAA,QACtD;AACA,YAAI,OAAO,KAAK,iBAAiB,YAAY,KAAK,aAAa,SAAS,KAAM;AAC5E,iBAAO,EAAE,KAAK,EAAE,OAAO,8CAA8C,GAAG,GAAG;AAAA,QAC7E;AAIA,YAAI,OAAO,KAAK,iBAAiB,YAAY,iCAAiC,KAAK,KAAK,YAAY,GAAG;AACrG,iBAAO,EAAE,KAAK,EAAE,OAAO,2CAA2C,GAAG,GAAG;AAAA,QAC1E;AAEA,cAAM,eACJ,OAAO,KAAK,iBAAiB,YAAY,KAAK,aAAa,KAAK,EAAE,SAAS,IACvE,KAAK,aAAa,KAAK,IACvB;AAEN,cAAM,OAAO,qBAAqB,oBAAoB,OAAO;AAAA,UAC3D,OAAO,OAAO,QAAQ,aAAa;AAAA,UACnC,IAAI,OAAO,QAAQ;AAAA,UACnB,OAAO,EAAE,aAAa;AAAA,QACxB,CAAC;AACD,eAAO,EAAE,KAAK,EAAE,aAAa,CAAC;AAAA,MAChC;AAAA,IACF,CAAC;AAAA,EACH;AASA,QAAM,eAAe,CAAC,UAAyC;AAC7D,QAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,UAAW,QAAO;AACzE,QAAI,UAAU,WAAY,QAAO;AACjC,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,iBAAiB,mBAAmB;AAAA,MAClC,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,WAAW,MAAM,iBAAiB,MAAM,CAAC,GAAG,IAAI;AACtD,YAAI,cAAc,SAAU,QAAO,SAAS;AAC5C,eAAO,EAAE,KAAK,MAAM,mBAAmB,MAAM,OAAO,oBAAoB,SAAS,OAAO,KAAK,CAAC;AAAA,MAChG;AAAA,IACF,CAAC;AAAA,IACD,iBAAiB,mBAAmB;AAAA,MAClC,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,WAAW,MAAM,iBAAiB,MAAM,CAAC,GAAG,IAAI;AACtD,YAAI,cAAc,SAAU,QAAO,SAAS;AAE5C,YAAI;AACJ,YAAI;AACF,iBAAO,MAAM,EAAE,IAAI,KAAK;AAAA,QAC1B,QAAQ;AACN,iBAAO,EAAE,KAAK,EAAE,OAAO,oBAAoB,GAAG,GAAG;AAAA,QACnD;AACA,cAAM,OAAO,aAAa,KAAK,IAAI;AACnC,YAAI,CAAC,KAAM,QAAO,EAAE,KAAK,EAAE,OAAO,uCAAuC,GAAG,GAAG;AAC/E,cAAM,QAAQ,OAAO,KAAK,UAAU,WAAW,KAAK,MAAM,KAAK,IAAI;AACnE,YAAI,CAAC,MAAO,QAAO,EAAE,KAAK,EAAE,OAAO,sBAAsB,GAAG,GAAG;AAC/D,YAAI,MAAM,SAAS,IAAK,QAAO,EAAE,KAAK,EAAE,OAAO,sCAAsC,GAAG,GAAG;AAC3F,YAAI,KAAK,KAAK,KAAK,EAAG,QAAO,EAAE,KAAK,EAAE,OAAO,oCAAoC,GAAG,GAAG;AAEvF,cAAM,aAAa,OAAO,oBAAoB,SAAS,OAAO,OAAO,OAAO,IAAI;AAChF,eAAO,EAAE,KAAK,MAAM,mBAAmB,MAAM,OAAO,oBAAoB,SAAS,OAAO,KAAK,CAAC;AAAA,MAChG;AAAA,IACF,CAAC;AAAA,IACD,iBAAiB,mBAAmB;AAAA,MAClC,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,WAAW,MAAM,iBAAiB,MAAM,CAAC,GAAG,IAAI;AACtD,YAAI,cAAc,SAAU,QAAO,SAAS;AAC5C,cAAM,OAAO,aAAa,EAAE,IAAI,MAAM,MAAM,CAAC;AAC7C,YAAI,CAAC,KAAM,QAAO,EAAE,KAAK,EAAE,OAAO,uCAAuC,GAAG,GAAG;AAC/E,cAAM,eAAe,OAAO,oBAAoB,SAAS,OAAO,OAAO,IAAI;AAC3E,eAAO,EAAE,KAAK,MAAM,mBAAmB,MAAM,OAAO,oBAAoB,SAAS,OAAO,KAAK,CAAC;AAAA,MAChG;AAAA,IACF,CAAC;AAAA,EACH;AAGA,SAAO,KAAK,GAAG,sBAAsB,EAAE,QAAQ,MAAM,OAAO,SAAS,UAAU,CAAC,CAAC;AAEjF,SAAO;AACT;AAQA,eAAe,eAAe,SAI+D;AAC3F,QAAM,EAAE,QAAQ,MAAM,EAAE,IAAI;AAC5B,QAAM,WAAW,MAAM,iBAAiB,GAAG,IAAI;AAC/C,MAAI,cAAc,SAAU,QAAO,EAAE,UAAU,SAAS,SAAS;AACjE,QAAM,EAAE,OAAO,OAAO,IAAI,SAAS;AAEnC,QAAM,sBAAsB,EAAE,IAAI,MAAM,IAAI;AAC5C,MAAI,CAAC,qBAAqB;AACxB,WAAO,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,+BAA+B,GAAG,GAAG,EAAE;AAAA,EAC5E;AACA,QAAM,UAAU,MAAM,yBAAyB,EAAE,QAAQ,OAAO,oBAAoB,CAAC;AACrF,MAAI,CAAC,SAAS;AACZ,WAAO,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,+BAA+B,GAAG,GAAG,EAAE;AAAA,EAC5E;AACA,SAAO,EAAE,SAAS,OAAO;AAC3B;AAGA,SAAS,iBAAiB,MAA4B;AACpD,QAAM,IAAI;AACV,SAAO,EAAE,MAAM,GAAG,QAAQ,MAAM,OAAO,GAAG,SAAS,KAAK;AAC1D;AAOA,eAAe,sBAAsB,SAGD;AAClC,QAAM,EAAE,OAAO,WAAW,IAAI;AAC9B,MAAI,CAAC,WAAW,WAAW;AACzB,UAAM,IAAI,iBAAiB,+DAA+D,cAAc;AAAA,EAC1G;AACA,SAAO,MAAM,gBAAgB,WAAW,SAAS;AACnD;AAOA,eAAe,uBACb,QACA,SACA,QACmC;AACnC,SAAO,OAAO,qBAAqB,UAAU,YAAY,EAAE,mBAAmB,SAAS,OAAO,CAAC;AACjG;AAgBA,eAAe,eAAe,SAMJ;AACxB,QAAM,EAAE,QAAQ,OAAO,SAAS,QAAQ,WAAW,IAAI;AACvD,QAAM,aAAa,MAAM,uBAAuB,QAAQ,SAAS,MAAM;AACvE,QAAM,SAAS,MAAM,OAAO,eAAe,oBAAoB;AAAA,IAC7D,OAAO,QAAQ,aAAa;AAAA,IAC5B,cAAc,QAAQ,WAAW;AAAA,EACnC,CAAC;AACD,MAAI,CAAC,OAAO,eAAe;AACzB,UAAM,IAAI,iBAAiB,qDAAqD,cAAc;AAAA,EAChG;AAGA,QAAM,aACH,MAAM,aAAa,MAAM,OAAO,oBAAoB,QAAQ,aAAa,KAAK,KAAM,OAAO,cAAc;AAC5G,QAAM,UAAU,MAAM,qBAAqB;AAAA,IACzC;AAAA,IACA,KAAK;AAAA,IACL,SAAS,OAAO,qBAAqB;AAAA,IACrC,OAAO;AAAA,IACP;AAAA,EACF,CAAC;AAED,QAAM,QAAQ,MAAM,OAAO,qBAAqB,UAAU,QAAQ,EAAE,IAAI,WAAW,GAAG,CAAC;AACvF,QAAM,WAAW,SAAS;AAC1B,QAAM,gBAAgB;AAAA,IACpB,KAAK;AAAA,IACL,UAAU,EAAE,cAAc,QAAQ,WAAW,MAAM,eAAe,QAAQ,cAAc;AAAA,IACxF;AAAA,IACA,OAAO,OAAO,cAAc;AAAA,IAC5B,SAAS,OAAO,qBAAqB;AAAA,IACrC;AAAA,EACF,CAAC;AACD,QAAM,SAAuB;AAAA,IAC3B,YAAY,QAAQ;AAAA,IACpB,kBAAkB,QAAQ;AAAA,IAC1B,qBAAqB,QAAQ;AAAA,IAC7B,WAAW,SAAS;AAAA,IACpB,gBAAgB,SAAS;AAAA,EAC3B;AACA,QAAM,OAAwB,EAAE,OAAO,QAAQ,SAAS,mBAAmB;AAC3E,eAAa,IAAI;AACjB,SAAO;AACT;AAGA,SAAS,mBAAmB,KAG1B;AACA,MAAI,eAAe,oBAAoB;AACrC,WAAO,EAAE,QAAQ,KAAK,MAAM,EAAE,OAAO,IAAI,MAAM,SAAS,IAAI,QAAQ,EAAE;AAAA,EACxE;AACA,MAAI,eAAe,kBAAkB;AACnC,WAAO,EAAE,QAAQ,KAAK,MAAM,EAAE,OAAO,IAAI,MAAM,SAAS,IAAI,QAAQ,EAAE;AAAA,EACxE;AACA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,MAAM,EAAE,OAAO,sBAAsB,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE;AAAA,EACjG;AACF;AAGA,SAAS,iBAAiB,GAAY,KAAc;AAClD,MAAI,eAAe,eAAe;AAChC,WAAO,EAAE,KAAK,EAAE,OAAO,IAAI,MAAM,SAAS,IAAI,QAAQ,GAAG,IAAI,SAAS,mBAAmB,MAAM,GAAG;AAAA,EACpG;AACA,MAAI,eAAe,kBAAkB;AACnC,WAAO,EAAE,KAAK,EAAE,OAAO,IAAI,MAAM,SAAS,IAAI,QAAQ,GAAG,GAAG;AAAA,EAC9D;AACA,SAAO,EAAE,KAAK,EAAE,OAAO,cAAc,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,GAAG,GAAG;AACvG;AASA,eAAe,iBAAiB,SAQ9B;AACA,QAAM,EAAE,QAAQ,MAAM,OAAO,EAAE,IAAI;AACnC,QAAM,WAAW,MAAM,iBAAiB,GAAG,IAAI;AAC/C,MAAI,cAAc,SAAU,QAAO,EAAE,UAAU,SAAS,SAAS;AACjE,QAAM,EAAE,OAAO,OAAO,IAAI,SAAS;AAEnC,MAAI,CAAC,MAAM,SAAS;AAClB,WAAO;AAAA,MACL,UAAU,EAAE,KAAK,EAAE,OAAO,0BAA0B,SAAS,qCAAqC,GAAG,GAAG;AAAA,IAC1G;AAAA,EACF;AAEA,QAAM,sBAAsB,EAAE,IAAI,MAAM,IAAI;AAC5C,MAAI,CAAC,qBAAqB;AACxB,WAAO,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,+BAA+B,GAAG,GAAG,EAAE;AAAA,EAC5E;AACA,QAAM,UAAU,MAAM,yBAAyB,EAAE,QAAQ,OAAO,oBAAoB,CAAC;AACrF,MAAI,CAAC,SAAS;AACZ,WAAO,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,+BAA+B,GAAG,GAAG,EAAE;AAAA,EAC5E;AACA,QAAM,aAAa,MAAM,uBAAuB,QAAQ,SAAS,MAAM;AACvE,SAAO,EAAE,OAAO,QAAQ,SAAS,WAAW;AAC9C;AAEA,SAAS,sBAAsB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMe;AACb,SAAO;AAAA;AAAA,IAEL,iBAAiB,qCAAqC;AAAA,MACpD,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,WAAW,MAAM,iBAAiB,MAAM,CAAC,GAAG,IAAI;AACtD,YAAI,cAAc,SAAU,QAAO,SAAS;AAC5C,cAAM,EAAE,OAAO,OAAO,IAAI,SAAS;AACnC,cAAM,sBAAsB,EAAE,IAAI,MAAM,IAAI;AAC5C,cAAM,UAAU,sBACZ,MAAM,yBAAyB,EAAE,QAAQ,OAAO,oBAAoB,CAAC,IACrE;AACJ,YAAI,CAAC,QAAS,QAAO,EAAE,KAAK,EAAE,OAAO,+BAA+B,GAAG,GAAG;AAC1E,cAAM,WAAW,MAAM,OAAO,qBAAqB,SAAS,KAAK,EAAE,qBAAqB,QAAQ,IAAI,OAAO,CAAC;AAC5G,eAAO,EAAE,KAAK,EAAE,SAAS,CAAC;AAAA,MAC5B;AAAA,IACF,CAAC;AAAA,IACD,iBAAiB,qCAAqC;AAAA,MACpD,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,WAAW,MAAM,iBAAiB,MAAM,CAAC,GAAG,IAAI;AACtD,YAAI,cAAc,SAAU,QAAO,SAAS;AAC5C,cAAM,EAAE,OAAO,OAAO,IAAI,SAAS;AACnC,cAAM,sBAAsB,EAAE,IAAI,MAAM,IAAI;AAC5C,cAAM,UAAU,sBACZ,MAAM,yBAAyB,EAAE,QAAQ,OAAO,oBAAoB,CAAC,IACrE;AACJ,YAAI,CAAC,QAAS,QAAO,EAAE,KAAK,EAAE,OAAO,+BAA+B,GAAG,GAAG;AAC1E,YAAI;AACJ,YAAI;AACF,iBAAO,MAAM,EAAE,IAAI,KAAK;AAAA,QAC1B,QAAQ;AACN,iBAAO,EAAE,KAAK,EAAE,OAAO,oBAAoB,GAAG,GAAG;AAAA,QACnD;AACA,YAAI,CAAC,cAAqB,KAAK,MAAM,EAAG,QAAO,EAAE,KAAK,EAAE,OAAO,iBAAiB,GAAG,GAAG;AACtF,cAAM,aAAa,KAAK,eAAe,SAAY,QAAQ,gBAAgB,KAAK;AAChF,YAAI,CAAC,cAAqB,UAAU,EAAG,QAAO,EAAE,KAAK,EAAE,OAAO,qBAAqB,GAAG,GAAG;AACzF,cAAM,UAAU,MAAM,OAAO,qBAAqB,SAAS,OAAO;AAAA,UAChE,WAAW,WAAW;AAAA,UACtB,qBAAqB,QAAQ;AAAA,UAC7B;AAAA,UACA;AAAA,UACA,QAAQ,KAAK;AAAA,UACb;AAAA,QACF,CAAC;AACD,eAAO,EAAE,KAAK,EAAE,QAAQ,CAAC;AAAA,MAC3B;AAAA,IACF,CAAC;AAAA,IACD,iBAAiB,iCAAiC;AAAA,MAChD,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,WAAW,MAAM,iBAAiB,MAAM,CAAC,GAAG,IAAI;AACtD,YAAI,cAAc,SAAU,QAAO,SAAS;AAC5C,cAAM,UAAU,MAAM,OAAO,qBAAqB,SAAS,eAAe,EAAE,IAAI,MAAM,WAAW,CAAC;AAClG,YAAI,CAAC,WAAW,QAAQ,UAAU,SAAS,OAAO,SAAS,QAAQ,WAAW,SAAS,OAAO,QAAQ;AACpG,iBAAO,EAAE,KAAK,EAAE,OAAO,oBAAoB,GAAG,GAAG;AAAA,QACnD;AACA,eAAO,EAAE,KAAK,EAAE,QAAQ,CAAC;AAAA,MAC3B;AAAA,IACF,CAAC;AAAA,IACD,iBAAiB,iCAAiC;AAAA,MAChD,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,WAAW,MAAM,iBAAiB,MAAM,CAAC,GAAG,IAAI;AACtD,YAAI,cAAc,SAAU,QAAO,SAAS;AAC5C,cAAM,UAAU,MAAM,OAAO,qBAAqB,SAAS,eAAe,EAAE,IAAI,MAAM,WAAW,CAAC;AAClG,YAAI,CAAC,WAAW,QAAQ,UAAU,SAAS,OAAO,SAAS,QAAQ,WAAW,SAAS,OAAO,QAAQ;AACpG,iBAAO,EAAE,KAAK,EAAE,OAAO,oBAAoB,GAAG,GAAG;AAAA,QACnD;AACA,YAAI;AACJ,YAAI,QAAQ,WAAW;AACrB,cAAI;AACF,sBAAU,MAAM,MAAM,gBAAgB,QAAQ,SAAS;AAAA,UACzD,QAAQ;AAAA,UAER;AACA,gBAAM,MAAM;AAAA,YACV;AAAA,cACE,WAAW,QAAQ;AAAA,cACnB,cAAc,YAAY;AAAA,cAAC;AAAA,cAC3B,OAAO,YAAY;AACjB,sBAAM,OAAO,qBAAqB,SAAS,WAAW;AAAA,kBACpD,IAAI,QAAQ;AAAA,kBACZ,WAAW;AAAA,kBACX,gBAAgB,QAAQ,kBAAkB;AAAA,gBAC5C,CAAC;AAAA,cACH;AAAA,YACF;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,cAAM,OAAO,qBAAqB,SAAS,OAAO,QAAQ,EAAE;AAC5D,eAAO,EAAE,KAAK,EAAE,SAAS,KAAK,CAAC;AAAA,MACjC;AAAA,IACF,CAAC;AAAA;AAAA,IAGD,iBAAiB,mCAAmC;AAAA,MAClD,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,QAAQ,MAAM,iBAAiB,EAAE,QAAQ,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC;AACzE,YAAI,cAAc,MAAO,QAAO,MAAM;AACtC,cAAM,EAAE,QAAQ,QAAQ,IAAI;AAE5B,YAAI;AACJ,YAAI;AACF,iBAAO,MAAM,EAAE,IAAI,KAAK;AAAA,QAC1B,QAAQ;AACN,iBAAO,EAAE,KAAK,EAAE,OAAO,oBAAoB,GAAG,GAAG;AAAA,QACnD;AACA,YAAI,OAAO,KAAK,YAAY,YAAY,KAAK,QAAQ,KAAK,EAAE,WAAW,KAAK,KAAK,QAAQ,SAAS,KAAM;AACtG,iBAAO,EAAE,KAAK,EAAE,OAAO,kBAAkB,GAAG,GAAG;AAAA,QACjD;AACA,cAAM,mBAAmB,MAAM,wBAAwB,QAAQ,QAAQ,IAAI,QAAQ,KAAK,SAAS;AACjG,YAAI,CAAC,kBAAkB;AACrB,iBAAO,EAAE,KAAK,EAAE,OAAO,oBAAoB,GAAG,GAAG;AAAA,QACnD;AACA,cAAM,EAAE,SAAS,eAAe,IAAI;AAEpC,YAAI;AACF,iBAAO,MAAM,gBAAgB;AAAA,YAC3B,KAAK,GAAG,QAAQ,EAAE,IAAI,MAAM;AAAA,YAC5B;AAAA,YACA,IAAI,YAAY;AACd,oBAAM,UAAU,MAAM,sBAAsB,EAAE,OAAO,YAAY,eAAe,CAAC;AACjF,oBAAM,SAAS,MAAM;AAAA,gBACnB;AAAA,gBACA;AAAA,gBACA,KAAK;AAAA,gBACL,iBAAiB,MAAM,KAAK,WAAW,MAAM,CAAC,CAAC,CAAC;AAAA,cAClD;AACA,kBAAI,OAAO,WAAW;AACpB,sBAAM,YAAY;AAAA,kBAChB,SAAS,MAAM,CAAC;AAAA,kBAChB,OAAO;AAAA,oBACL,QAAQ;AAAA,oBACR,kBAAkB,QAAQ;AAAA,oBAC1B,qBAAqB,QAAQ;AAAA,oBAC7B,SAAS,CAAC,EAAE,MAAM,WAAW,IAAI,iBAAiB,QAAQ,UAAU,CAAC;AAAA,oBACrE,UAAU,EAAE,WAAW,iBAAiB,QAAQ,UAAU;AAAA,kBAC5D;AAAA,gBACF,CAAC;AAAA,cACH;AACA,qBAAO,EAAE,KAAK,EAAE,WAAW,OAAO,UAAU,CAAC;AAAA,YAC/C;AAAA,UACF,CAAC;AAAA,QACH,SAAS,KAAK;AACZ,iBAAO,iBAAiB,MAAM,CAAC,GAAG,GAAG;AAAA,QACvC;AAAA,MACF;AAAA,IACF,CAAC;AAAA;AAAA,IAGD,iBAAiB,iCAAiC;AAAA,MAChD,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,QAAQ,MAAM,iBAAiB,EAAE,QAAQ,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC;AACzE,YAAI,cAAc,MAAO,QAAO,MAAM;AACtC,cAAM,EAAE,OAAO,QAAQ,QAAQ,IAAI;AAEnC,YAAI;AACJ,YAAI;AACF,iBAAO,MAAM,EAAE,IAAI,KAAK;AAAA,QAC1B,QAAQ;AACN,iBAAO,EAAE,KAAK,EAAE,OAAO,oBAAoB,GAAG,GAAG;AAAA,QACnD;AACA,YAAI,CAAC,cAAqB,KAAK,MAAM,GAAG;AACtC,iBAAO,EAAE,KAAK,EAAE,OAAO,iBAAiB,GAAG,GAAG;AAAA,QAChD;AACA,cAAM,SAAS,KAAK;AACpB,cAAM,mBAAmB,MAAM,wBAAwB,QAAQ,QAAQ,IAAI,QAAQ,KAAK,SAAS;AACjG,YAAI,CAAC,kBAAkB;AACrB,iBAAO,EAAE,KAAK,EAAE,OAAO,oBAAoB,GAAG,GAAG;AAAA,QACnD;AACA,cAAM,EAAE,SAAS,eAAe,IAAI;AAEpC,YAAI;AACF,iBAAO,MAAM,gBAAgB;AAAA,YAC3B,KAAK,GAAG,QAAQ,EAAE,IAAI,MAAM;AAAA,YAC5B;AAAA,YACA,IAAI,YAAY;AACd,oBAAM,UAAU,MAAM,sBAAsB,EAAE,OAAO,YAAY,eAAe,CAAC;AACjF,oBAAM,SAAS,MAAM,OAAO,eAAe,oBAAoB;AAAA,gBAC7D;AAAA,gBACA,cAAc,QAAQ,WAAW;AAAA,cACnC,CAAC;AACD,kBAAI,CAAC,OAAO,cAAe,OAAM,IAAI,MAAM,mDAAmD;AAC9F,oBAAM,WAAW,SAAS,SAAS,QAAQ,OAAO,cAAc,OAAO,QAAQ,WAAW,IAAI;AAC9F,oBAAM,YAAY;AAAA,gBAChB,SAAS,MAAM,CAAC;AAAA,gBAChB,OAAO;AAAA,kBACL,QAAQ;AAAA,kBACR,kBAAkB,QAAQ;AAAA,kBAC1B,qBAAqB,QAAQ;AAAA,kBAC7B,SAAS,CAAC,EAAE,MAAM,UAAU,IAAI,OAAO,CAAC;AAAA,kBACxC,UAAU,EAAE,QAAQ,WAAW,iBAAiB,QAAQ,UAAU;AAAA,gBACpE;AAAA,cACF,CAAC;AACD,qBAAO,EAAE,KAAK,EAAE,QAAQ,MAAM,OAAO,CAAC;AAAA,YACxC;AAAA,UACF,CAAC;AAAA,QACH,SAAS,KAAK;AACZ,iBAAO,iBAAiB,MAAM,CAAC,GAAG,GAAG;AAAA,QACvC;AAAA,MACF;AAAA,IACF,CAAC;AAAA;AAAA,IAGD,iBAAiB,+BAA+B;AAAA,MAC9C,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,QAAQ,MAAM,iBAAiB,EAAE,QAAQ,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC;AACzE,YAAI,cAAc,MAAO,QAAO,MAAM;AACtC,cAAM,EAAE,OAAO,QAAQ,QAAQ,IAAI;AAEnC,YAAI;AAOJ,YAAI;AACF,iBAAO,MAAM,EAAE,IAAI,KAAK;AAAA,QAC1B,QAAQ;AACN,iBAAO,EAAE,KAAK,EAAE,OAAO,oBAAoB,GAAG,GAAG;AAAA,QACnD;AACA,YAAI,CAAC,cAAqB,KAAK,MAAM,GAAG;AACtC,iBAAO,EAAE,KAAK,EAAE,OAAO,iBAAiB,GAAG,GAAG;AAAA,QAChD;AACA,cAAM,OAAO,KAAK,SAAS,SAAY,QAAQ,gBAAgB,KAAK;AACpE,YAAI,CAAC,cAAqB,IAAI,GAAG;AAC/B,iBAAO,EAAE,KAAK,EAAE,OAAO,eAAe,GAAG,GAAG;AAAA,QAC9C;AACA,YAAI,OAAO,KAAK,UAAU,YAAY,KAAK,MAAM,KAAK,EAAE,WAAW,KAAK,KAAK,MAAM,SAAS,KAAK;AAC/F,iBAAO,EAAE,KAAK,EAAE,OAAO,gBAAgB,GAAG,GAAG;AAAA,QAC/C;AACA,YAAI,KAAK,SAAS,WAAc,OAAO,KAAK,SAAS,YAAY,KAAK,KAAK,SAAS,QAAQ;AAC1F,iBAAO,EAAE,KAAK,EAAE,OAAO,eAAe,GAAG,GAAG;AAAA,QAC9C;AACA,cAAM,OAAO,KAAK;AAClB,cAAM,QAAQ,KAAK;AACnB,cAAM,SAAS,KAAK;AACpB,cAAM,mBAAmB,MAAM,wBAAwB,QAAQ,QAAQ,IAAI,QAAQ,KAAK,SAAS;AACjG,YAAI,CAAC,kBAAkB;AACrB,iBAAO,EAAE,KAAK,EAAE,OAAO,oBAAoB,GAAG,GAAG;AAAA,QACnD;AAEA,YAAI;AACF,iBAAO,MAAM,gBAAgB;AAAA,YAC3B,KAAK,GAAG,QAAQ,EAAE,IAAI,MAAM;AAAA,YAC5B;AAAA,YACA,IAAI,YAAY;AACd,oBAAM,SAAS,MAAM,OAAO,eAAe,kBAAkB;AAAA,gBAC3D,YAAY;AAAA,kBACV,MAAM;AAAA,kBACN,gBAAgB,OAAO,QAAQ,aAAa,UAAU;AAAA,gBACxD;AAAA,gBACA,UAAU,QAAQ,WAAW;AAAA,gBAC7B,YAAY;AAAA,gBACZ,YAAY;AAAA,gBACZ;AAAA,gBACA,MAAM;AAAA,gBACN,cAAc;AAAA,cAChB,CAAC;AACD,oBAAM,YAAY;AAAA,gBAChB,SAAS,MAAM,CAAC;AAAA,gBAChB,OAAO;AAAA,kBACL,QAAQ;AAAA,kBACR,kBAAkB,QAAQ;AAAA,kBAC1B,qBAAqB,QAAQ;AAAA,kBAC7B,SAAS,CAAC,EAAE,MAAM,gBAAgB,IAAI,OAAO,KAAK,MAAM,MAAM,CAAC;AAAA,kBAC/D,UAAU,EAAE,QAAQ,MAAM,MAAM,KAAK,OAAO,IAAI;AAAA,gBAClD;AAAA,cACF,CAAC;AACD,oBAAM,oBAAoB,yBAAyB,OAAO,KAAK,QAAQ,WAAW,IAAI;AACtF,kBAAI,mBAAmB;AACrB,sBAAM,YAAY,iBAAiB,QAAQ;AAC3C,sBAAM;AAAA,kBACJ;AAAA,oBACE;AAAA,oBACA,wBAAwB,QAAQ,aAAa;AAAA,oBAC7C,qBAAqB,QAAQ;AAAA,oBAC7B,sBAAsB,QAAQ,WAAW;AAAA,oBACzC,gBAAgB,QAAQ,WAAW;AAAA,oBACnC,iBAAiB,kBAAkB,SAAS;AAAA,oBAC5C;AAAA,oBACA,SAAS;AAAA,oBACT,YAAY;AAAA,oBACZ,UAAU;AAAA,oBACV,QAAQ;AAAA,oBACR,oBAAoB;AAAA,kBACtB;AAAA,kBACA,OAAO;AAAA,gBACT,EAAE,MAAM,CAAC,UAAmB;AAC1B,0BAAQ;AAAA,oBACN,yBAAyB,OAAO,GAAG;AAAA,oBACnC;AAAA,kBACF;AAAA,gBACF,CAAC;AAAA,cACH;AACA,qBAAO,EAAE,KAAK,EAAE,KAAK,OAAO,IAAI,CAAC;AAAA,YACnC;AAAA,UACF,CAAC;AAAA,QACH,SAAS,KAAK;AACZ,iBAAO,EAAE;AAAA,YACP,EAAE,OAAO,2BAA2B,SAAS,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE;AAAA,YAC9F;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,IAMD,iBAAiB,oCAAoC;AAAA,MACnD,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,QAAQ,MAAM,iBAAiB,EAAE,QAAQ,MAAM,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC;AACzE,YAAI,cAAc,MAAO,QAAO,MAAM;AACtC,cAAM,EAAE,QAAQ,SAAS,WAAW,IAAI;AAExC,YAAI,CAAC,WAAW,WAAW;AAEzB,iBAAO,EAAE,KAAK,EAAE,UAAU,MAAM,CAAC;AAAA,QACnC;AAEA,YAAI;AACF,iBAAO,MAAM,gBAAgB;AAAA,YAC3B,KAAK,GAAG,QAAQ,EAAE,IAAI,MAAM;AAAA,YAC5B;AAAA,YACA,IAAI,YAAY;AACd,oBAAM,UAAU,MAAM,MAAM,gBAAgB,WAAW,SAAU;AACjE,oBAAM,uBAAuB;AAAA,gBAC3B;AAAA,gBACA,KAAK;AAAA,gBACL,SAAS,OAAO,qBAAqB;AAAA,gBACrC;AAAA,cACF,CAAC;AACD,qBAAO,EAAE,KAAK,EAAE,UAAU,KAAK,CAAC;AAAA,YAClC;AAAA,UACF,CAAC;AAAA,QACH,SAAS,KAAK;AACZ,iBAAO,iBAAiB,MAAM,CAAC,GAAG,GAAG;AAAA,QACvC;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAGA,eAAe,wBACb,QACA,WACA,QACA,WACA;AACA,MAAI,OAAO,cAAc,UAAU;AACjC,WAAO;AAAA,EACT;AACA,QAAM,UAAU,MAAM,OAAO,qBAAqB,SAAS,eAAe,SAAS;AACnF,MACE,SAAS,wBAAwB,aACjC,QAAQ,WAAW,UACnB,CAAC,QAAQ,aACT,CAAC,QAAQ,gBACT;AACA,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL;AAAA,IACA,SAAS,QAAQ;AAAA,IACjB,gBAAgB;AAAA,MACd,IAAI,QAAQ;AAAA,MACZ,qBAAqB,QAAQ;AAAA,MAC7B,QAAQ,QAAQ;AAAA,MAChB,WAAW,QAAQ;AAAA,MACnB,gBAAgB,QAAQ;AAAA,MACxB,gBAAgB,QAAQ;AAAA,MACxB,WAAW,QAAQ;AAAA,IACrB;AAAA,EACF;AACF;;;AQ7kDA,SAAS,kBAAkB;AAC3B,SAAS,SAAS;;;ACClB,IAAM,oCAAoC;AAC1C,IAAM,8BAA8B;AAe7B,SAAS,2BAA2B,gBAA+C;AACxF,QAAM,OAAO,eAAe,IAAI,2BAA2B;AAC3D,SAAO,SAAS,aAAa,aAAa;AAC5C;AAEO,SAAS,kBAAkB,gBAAgC,OAAqB;AACrF,QAAM,WAAW,eAAe,IAAI,iCAAiC;AACrE,MAAI,CAAC,UAAU;AACb,UAAM,IAAI,MAAM,oEAAoE;AAAA,EACtF;AACA,WAAS,KAAK;AAChB;;;ADFA,SAAS,cAAc,MAAuD;AAC5E,SAAO,MAAM,YAAY,MAAM;AACjC;AAEA,SAAS,aAAa,MAAuD;AAC3E,SAAO,MAAM;AACf;AAEA,IAAM,yBAAyB,EAAE,OAAO;AAAA,EACtC,aAAa,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;AACvE,CAAC;AAYD,SAAS,iBAAiB,OAAwB,cAA8B;AAC9E,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,QAAQ,KAAK,KAAK,EAAG,QAAO,OAAO,KAAK;AAC5C,QAAM,QAAQ,MAAM,MAAM,0DAA0D;AACpF,MAAI,CAAC,SAAS,MAAM,CAAC,EAAG,YAAY,MAAM,aAAa,YAAY,GAAG;AACpE,UAAM,IAAI,MAAM,+BAA+B,YAAY,GAAG;AAAA,EAChE;AACA,SAAO,OAAO,MAAM,CAAC,CAAC;AACxB;AAQA,SAAS,uBAAuB,gBAAyC;AACvE,QAAM,UAAU,eAAe,IAAI,YAAY;AAC/C,QAAM,OAAO,eAAe,IAAI,MAAM;AACtC,SAAO;AAAA,IACL,SAAS,YAAY,QAAQ,SAAS,EAAE,uBAAuB,aAAa,IAAI,KAAK,cAAc,IAAI;AAAA,EACzG;AACF;AAEA,eAAe,qBAAqB,gBAAgC,QAAmD;AACrH,QAAM,UAAU,eAAe,IAAI,YAAY;AAC/C,QAAM,OAAO,eAAe,IAAI,MAAM;AACtC,QAAM,QAAQ,aAAa,IAAI;AAC/B,QAAM,SAAS,cAAc,IAAI;AACjC,QAAM,sBAAsB,SAAS,SAAS,EAAE;AAChD,MAAI,CAAC,WAAW,CAAC,QAAQ,YAAY,CAAC,uBAAuB,CAAC,SAAS,CAAC,QAAQ;AAC9E,UAAM,IAAI,MAAM,yFAAyF;AAAA,EAC3G;AAEA,QAAM,oBAAoB,MAAM,OAAO,qBAAqB,oBAAoB,IAAI;AAAA,IAClF;AAAA,IACA,IAAI;AAAA,EACN,CAAC;AACD,MAAI,CAAC,kBAAmB,OAAM,IAAI,MAAM,qDAAqD;AAC7F,QAAM,aAAa,MAAM,OAAO,qBAAqB,YAAY,IAAI,EAAE,OAAO,IAAI,kBAAkB,aAAa,CAAC;AAClH,MAAI,CAAC,WAAY,OAAM,IAAI,MAAM,4DAA4D;AAC7F,QAAM,aAAa,MAAM,OAAO,qBAAqB,aAAa,IAAI,EAAE,OAAO,IAAI,kBAAkB,aAAa,CAAC;AACnH,MAAI,CAAC,WAAY,OAAM,IAAI,MAAM,6CAA6C;AAC9E,QAAM,eAAe,MAAM,OAAO,qBAAqB,cAAc,IAAI,EAAE,OAAO,IAAI,WAAW,eAAe,CAAC;AACjH,MAAI,CAAC,aAAc,OAAM,IAAI,MAAM,8DAA8D;AACjG,SAAO,EAAE,SAAS,mBAAmB,YAAY,cAAc,YAAY,OAAO,OAAO;AAC3F;AAEA,eAAe,kBAAkB,QAAuB,aAAqB,QAA2B;AACtG,QAAM,CAAC,OAAO,IAAI,IAAI,OAAO,WAAW,KAAK,MAAM,GAAG;AACtD,MAAI,CAAC,SAAS,CAAC,KAAM,OAAM,IAAI,MAAM,+BAA+B;AACpE,QAAM,UAAU,OAAO,uBAAuB,OAAO,OAAO,aAAa,UAAU,CAAC;AACpF,QAAM,EAAE,KAAK,IAAI,MAAM,QAAQ,MAAM,IAAI,EAAE,OAAO,MAAM,aAAa,YAAY,CAAC;AAClF,MAAI,OAAO,KAAK,KAAK,KAAK,EAAE,MAAM,OAAO,WAAW;AAClD,UAAM,IAAI,MAAM,uEAAuE;AAC3F;AAEA,eAAe,kBAAkB,QAAuB,mBAA2B;AACjF,SAAO;AAAA,IACL,OAAO,OAAO;AAAA,IACd,wBAAwB,OAAO,aAAa;AAAA,IAC5C,qBAAqB,OAAO,kBAAkB;AAAA,IAC9C,sBAAsB,OAAO,WAAW;AAAA,IACxC,gBAAgB,OAAO,WAAW;AAAA,IAClC,iBAAiB,OAAO,iBAAiB;AAAA,IACzC,WAAW,OAAO,QAAQ,QAAQ;AAAA,IAClC,SAAS,OAAO,QAAQ,QAAQ;AAAA,IAChC,YAAY,OAAO,WAAW;AAAA,IAC9B,UAAU,OAAO,QAAQ;AAAA,IACzB,cAAc,OAAO,QAAQ;AAAA,IAC7B,QAAQ;AAAA,IACR,oBAAoB,OAAO;AAAA,EAC7B;AACF;AAEA,eAAsB,qCACpB,gBACA,aACA,QACA,QACA;AAKA,MAAI,WAAW,uBAAuB,CAAC,uBAAuB,cAAc,EAAG,QAAO;AACtF,QAAM,SAAS,MAAM,qBAAqB,gBAAgB,MAAM;AAChE,QAAM,SAAS,iBAAiB,aAAa,OAAO,WAAW,IAAI;AACnE,QAAM,kBAAkB,QAAQ,QAAQ,MAAM;AAC9C,QAAM,uBAAuB,EAAE,GAAI,MAAM,kBAAkB,QAAQ,MAAM,GAAI,OAAO,GAAG,OAAO,kBAAkB;AAChH,SAAO;AACT;AAEA,eAAsB,yCACpB,gBACA,aACA,QACA;AACA,QAAM,SAAS,MAAM,qBAAqB,gBAAgB,MAAM;AAChE,QAAM,SAAS,iBAAiB,aAAa,OAAO,WAAW,IAAI;AACnE,QAAM,2BAA2B,MAAM,kBAAkB,QAAQ,MAAM,GAAG,OAAO,kBAAkB;AACnG,SAAO;AACT;AAEA,eAAsB,mBAAmB,gBAAgC,QAA0C;AACjH,QAAM,SAAS,MAAM,qBAAqB,gBAAgB,MAAM;AAKhE,QAAM,MAAM,MAAM;AAAA,IAChB,MAAM,OAAO;AAAA,IACb,OAAO;AAAA,IACP,2BAA2B,cAAc;AAAA,EAC3C;AACA,MAAI,KAAK;AACP,sBAAkB,gBAAgB,GAAG;AACrC;AAAA,EACF;AACA,QAAM,SAAS,MAAM,OAAO,eAAe,oBAAoB;AAAA,IAC7D,OAAO,OAAO;AAAA,IACd,cAAc,OAAO,WAAW;AAAA,EAClC,CAAC;AACD,QAAM,QAAQ,OAAO,eAAe;AACpC,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,2EAA2E;AACvG,oBAAkB,gBAAgB,KAAK;AACzC;AAEO,SAAS,8BAA8B,gBAAgC,QAA2B;AACvG,QAAM,UAAU,eAAe,IAAI,YAAY;AAC/C,QAAM,OAAO,eAAe,IAAI,MAAM;AACtC,MAAI,CAAC,SAAS,SAAS,EAAE,uBAAuB,CAAC,aAAa,IAAI,KAAK,CAAC,cAAc,IAAI,EAAG,QAAO,CAAC;AAErG,SAAO;AAAA,IACL,sBAAsB,WAAW;AAAA,MAC/B,IAAI;AAAA,MACJ,aACE;AAAA,MACF,aAAa,EAAE,OAAO,CAAC,CAAC;AAAA,MACxB,SAAS,YAAY;AACnB,cAAM,mBAAmB,gBAAgB,MAAM;AAC/C,eAAO,EAAE,WAAW,KAAK;AAAA,MAC3B;AAAA,IACF,CAAC;AAAA,IACD,qBAAqB,WAAW;AAAA,MAC9B,IAAI;AAAA,MACJ,aACE;AAAA,MACF,aAAa;AAAA,MACb,SAAS,OAAO,EAAE,YAAY,MAAM;AAClC,cAAM,SAAS,MAAM,qCAAqC,gBAAgB,aAAa,iBAAiB,MAAM;AAC9G,eAAO,EAAE,YAAY,MAAM,mBAAmB,OAAO;AAAA,MACvD;AAAA,IACF,CAAC;AAAA,IACD,uBAAuB,WAAW;AAAA,MAChC,IAAI;AAAA,MACJ,aACE;AAAA,MACF,aAAa;AAAA,MACb,SAAS,OAAO,EAAE,YAAY,MAAM;AAClC,cAAM,SAAS,MAAM,yCAAyC,gBAAgB,aAAa,MAAM;AACjG,eAAO,EAAE,YAAY,OAAO,mBAAmB,OAAO;AAAA,MACxD;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEO,SAAS,mBAAmB,SAAyB;AAC1D,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,QAAM,kBAA4B,CAAC;AACnC,MAAI;AAEJ,aAAW,QAAQ,OAAO;AACxB,QAAI,WAAW;AACb,UAAI,KAAK,KAAK,MAAM,UAAW,aAAY;AAC3C;AAAA,IACF;AACA,oBAAgB,KAAK,IAAI;AACzB,UAAM,UAAU,KAAK,MAAM,0CAA0C;AACrE,gBAAY,UAAU,CAAC;AAAA,EACzB;AAEA,SAAO,gBAAgB,KAAK,IAAI;AAClC;AAEO,SAAS,wBAAwB,SAKrC;AACD,MAAI,QAAQ,aAAa,qBAAqB,QAAQ,MAAO,QAAO;AACpE,QAAM,UAAW,QAAQ,OAA6C;AACtE,MACE,OAAO,YAAY,YACnB,CAAC,gDAAgD,KAAK,mBAAmB,OAAO,CAAC,GACjF;AACA,WAAO;AAAA,EACT;AACA,QAAM,SAAS,QAAQ;AACvB,QAAM,SAAS,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAU,QAAQ,UAAU,QAAQ;AAChG,MAAI,OAAO,WAAW,SAAU,QAAO;AACvC,QAAM,OAAO,OAAO,MAAM,qDAAqD,KAAK,CAAC;AACrF,SAAO,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI;AACvC;;;AEzPO,SAAS,iCAA0D;AACxE,QAAM,eAAe,QAAQ,IAAI,uBAAuB,KAAK,KAAK;AAClE,QAAM,cAAc,QAAQ,IAAI,4BAA4B,KAAK;AACjE,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI,MAAM,yFAAyF;AAAA,EAC3G;AACA,SAAO,EAAE,SAAS,sBAAsB,YAAY,GAAG,YAAY;AACrE;AAEA,SAAS,sBAAsB,cAA8B;AAC3D,SAAO,aAAa,QAAQ,QAAQ,EAAE,EAAE,QAAQ,SAAS,EAAE;AAC7D;AAEO,IAAM,mBAAN,cAA+B,MAAM;AAAA,EACjC;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,QAAgB,oBAAmC,MAAM;AACpF,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,oBAAoB;AAAA,EAC3B;AACF;AAEO,IAAM,oBAAN,MAAwB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,QAAiC;AAC3C,UAAM,UAAU,CAAC,WAAW,aAAa,EAAE,OAAO,WAAS,CAAC,OAAO,KAAsC,CAAC;AAC1G,QAAI,QAAQ,SAAS,GAAG;AACtB,YAAM,IAAI,MAAM,2DAA2D,QAAQ,KAAK,IAAI,CAAC,GAAG;AAAA,IAClG;AACA,SAAK,WAAW,OAAO,QAAQ,QAAQ,QAAQ,EAAE;AACjD,SAAK,eAAe,OAAO;AAC3B,SAAK,SAAS,OAAO,aAAa,WAAW;AAAA,EAC/C;AAAA,EAEA,MAAM,QACJ,QACAC,OACA,MACA,SACY;AACZ,UAAM,WAAW,MAAM,KAAK,MAAM,QAAQA,OAAM,MAAM,OAAO;AAC7D,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,UAAU,OAAO,MAAM,aAAa,QAAQ,GAAG,KAAK,YAAY;AACtE,YAAM,oBAAoB,gBAAgB,SAAS,QAAQ,IAAI,aAAa,CAAC;AAC7E,uBAAiB,+BAA+B;AAAA,QAC9C;AAAA,QACA,MAAAA;AAAA,QACA,QAAQ,SAAS;AAAA,QACjB;AAAA,QACA;AAAA,MACF,CAAC;AACD,YAAM,IAAI,iBAAiB,SAAS,SAAS,QAAQ,iBAAiB;AAAA,IACxE;AACA,QAAI,SAAS,WAAW,IAAK,QAAO;AACpC,WAAQ,MAAM,SAAS,KAAK;AAAA,EAC9B;AAAA,EAEA,MAAM,gBAAgB,QAAgBA,OAAc,SAAqD;AACvG,UAAM,WAAW,MAAM,KAAK,MAAM,QAAQA,OAAM,QAAW,SAAS,QAAQ;AAC5E,QAAI,SAAS,UAAU,OAAO,SAAS,SAAS,KAAK;AACnD,YAAM,WAAW,SAAS,QAAQ,IAAI,UAAU;AAChD,UAAI,SAAU,QAAO;AAAA,IACvB;AACA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,UAAU,OAAO,MAAM,aAAa,QAAQ,GAAG,KAAK,YAAY;AACtE,YAAM,oBAAoB,gBAAgB,SAAS,QAAQ,IAAI,aAAa,CAAC;AAC7E,uBAAiB,wCAAwC;AAAA,QACvD;AAAA,QACA,MAAAA;AAAA,QACA,QAAQ,SAAS;AAAA,QACjB;AAAA,QACA;AAAA,MACF,CAAC;AACD,YAAM,IAAI,iBAAiB,SAAS,SAAS,QAAQ,iBAAiB;AAAA,IACxE;AACA,qBAAiB,kDAAkD,EAAE,QAAQ,MAAAA,OAAM,QAAQ,SAAS,OAAO,CAAC;AAC5G,UAAM,IAAI,iBAAiB,mDAAmD,SAAS,MAAM;AAAA,EAC/F;AAAA,EAEA,MAAM,MACJ,QACAA,OACA,MACA,SACA,UACmB;AACnB,UAAM,UAAkC;AAAA,MACtC,QAAQ;AAAA,MACR,eAAe,UAAU,KAAK,YAAY;AAAA,IAC5C;AAIA,QAAI,SAAS,cAAc;AACzB,cAAQ,kBAAkB,IAAI,QAAQ;AAAA,IACxC;AACA,UAAM,gBAAgB,YAAY,QAAQ,IAAM;AAChD,UAAM,OAAoB;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ,SAAS,SAAS,YAAY,IAAI,CAAC,QAAQ,QAAQ,aAAa,CAAC,IAAI;AAAA,IAC/E;AACA,QAAI,SAAS,QAAW;AACtB,cAAQ,cAAc,IAAI;AAC1B,WAAK,OAAO,KAAK,UAAU,IAAI;AAAA,IACjC;AAEA,QAAI;AACF,aAAO,MAAM,KAAK,OAAO,GAAG,KAAK,QAAQ,GAAGA,KAAI,IAAI,IAAI;AAAA,IAC1D,SAAS,OAAO;AACd,UAAI,iBAAiB,SAAS,MAAM,QAAQ,SAAS,KAAK,YAAY,GAAG;AACvE,cAAM,WAAW,IAAI,MAAM,OAAO,MAAM,SAAS,KAAK,YAAY,CAAC;AACnE,iBAAS,OAAO,MAAM;AACtB,yBAAiB,gCAAgC;AAAA,UAC/C;AAAA,UACA,MAAAA;AAAA,UACA,MAAM,SAAS;AAAA,UACf,SAAS,SAAS;AAAA,QACpB,CAAC;AACD,cAAM;AAAA,MACR;AACA,uBAAiB,gCAAgC;AAAA,QAC/C;AAAA,QACA,MAAAA;AAAA,QACA,MAAM,iBAAiB,QAAQ,MAAM,OAAO;AAAA,QAC5C,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAChE,CAAC;AACD,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAEA,eAAe,aAAa,UAAqC;AAC/D,MAAI;AACF,UAAM,OAAQ,MAAM,SAAS,MAAM,EAAE,KAAK;AAC1C,eAAW,SAAS,CAAC,UAAU,SAAS,OAAO,GAAG;AAChD,UAAI,OAAO,KAAK,KAAK,MAAM,YAAY,KAAK,KAAK,EAAG,QAAO,KAAK,KAAK;AAAA,IACvE;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO,gCAAgC,SAAS,MAAM;AACxD;AAEA,SAAS,OAAO,SAAiB,aAA6B;AAC5D,SAAO,QAAQ,MAAM,WAAW,EAAE,KAAK,YAAY;AACrD;AAEO,SAAS,gBAAgB,SAAiB,QAAwC;AACvF,mBAAiB,QAAQ,SAAS,MAAM;AAC1C;AAEO,SAAS,gBAAgB,SAAiB,QAAwC;AACvF,mBAAiB,QAAQ,SAAS,MAAM;AAC1C;AAEO,SAAS,iBAAiB,SAAiB,QAAwC;AACxF,mBAAiB,SAAS,SAAS,MAAM;AAC3C;AAEA,SAAS,iBAAiB,OAAkC,SAAiB,QAAwC;AACnH,QAAM,WAAW,SAAS,IAAI,KAAK,UAAU,eAAe,MAAM,CAAC,CAAC,KAAK;AACzE,UAAQ,OAAO,MAAM,oBAAoB,MAAM,YAAY,CAAC,IAAI,OAAO,GAAG,QAAQ;AAAA,CAAI;AACxF;AAEA,SAAS,eAAe,QAA0D;AAChF,SAAO,OAAO,YAAY,OAAO,QAAQ,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,UAAU,MAAS,CAAC;AAC7F;AAEA,SAAS,gBAAgB,OAAqC;AAC5D,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,UAAU,OAAO,SAAS,OAAO,EAAE;AACzC,SAAO,OAAO,cAAc,OAAO,KAAK,WAAW,IAAI,UAAU;AACnE;;;AC1LA,SAAS,cAAAC,mBAAkB;AAG3B,SAAS,iBAAiB,yBAAyB;AAEnD,SAAS,oBAAoB;AAY7B,IAAM,aAAa;AACnB,IAAM,2BAA2B;AACjC,IAAM,kBAAkB;AACxB,IAAM,mBAAmB;AACzB,IAAM,gBAAgB;AACtB,IAAM,iBAAiB;AACvB,IAAM,mBAAmB,oBAAI,IAAI;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,IAAMC,sBAAqB,oBAAI,IAAI;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,IAAMC,mBAAkB,oBAAI,IAAI,CAAC,qBAAqB,2BAA2B,CAAC;AAClF,IAAMC,0BAAyB,oBAAI,IAAgC,CAAC,SAAS,YAAY,OAAO,CAAC;AACjG,IAAMC,+BAA8B;AA4C7B,IAAM,4BAAN,cAAwC,aAAa;AAAA,EACjD,OAAO;AAAA,EAEP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,cAAcC,YAAW;AAAA,EAElC,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAgC;AAAA,EAChC;AAAA,EACA,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,YAA+C,EAAE,SAAS,GAAG,cAAc,CAAC,EAAE;AAAA,EAE9E,YAAY,QAAyC;AACnD,UAAM;AACN,SAAK,UAAU,OAAO;AACtB,SAAK,cAAc,OAAO;AAC1B,SAAK,UAAU,OAAO;AACtB,SAAK,WAAW,OAAO;AACvB,SAAK,sBAAsB,OAAO;AAClC,SAAK,cAAc,OAAO,cAAc;AACxC,QAAI,CAAC,OAAO,SAAS,KAAK,WAAW,KAAK,KAAK,eAAe,GAAG;AAC/D,YAAM,IAAI,MAAM,mEAAmE;AAAA,IACrF;AACA,SAAK,cAAc,KAAK,IAAI,kBAAkB,KAAK,cAAc,CAAC;AAClE,SAAK,OAAO,OAAO,OAAO,KAAK;AAC/B,SAAK,YAAY,OAAO,YAAY;AAAA,EACtC;AAAA,EAEA,MAAM,KAAK,MAAiC;AAC1C,UAAM,MAAM,KAAK,IAAI;AACrB,SAAK,iBAAiB,iBAAiB,KAAK,MAAM;AAAA,EACpD;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,KAAK,SAAU;AACnB,QAAI,CAAC,KAAK,KAAM,OAAM,IAAI,MAAM,uDAAuD;AAEvF,SAAK,aAAa,KAAK,KAAK,IAAI;AAChC,SAAK,YAAY,kBAAkB,MAAM,KAAK,SAAS,SAAS,IAAI,eAAe,cAAc,CAAC;AAClG,SAAK,WAAW;AAChB,SAAK,KAAK,OAAO,KAAK,yCAAyC;AAAA,MAC7D,YAAY,KAAK;AAAA,MACjB,YAAY,KAAK;AAAA,IACnB,CAAC;AACD,SAAK,UAAU,CAAC;AAAA,EAClB;AAAA,EAEA,MAAM,OAAsB;AAC1B,QAAI,CAAC,KAAK,SAAU;AACpB,SAAK,WAAW;AAChB,QAAI,KAAK,OAAQ,cAAa,KAAK,MAAM;AACzC,SAAK,SAAS;AACd,SAAK,kBAAkB;AACvB,UAAM,KAAK;AACX,QAAI,KAAK,WAAW;AAClB,YAAM,KAAK,eAAe,aAAa,KAAK,UAAU,GAAG,KAAK,WAAW,EAAE,MAAM,MAAM,MAAS;AAChG,WAAK,YAAY;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,IAAI,YAAqB;AACvB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,UAAU,SAAuB;AAC/B,QAAI,CAAC,KAAK,SAAU;AACpB,SAAK,SAAS,WAAW,MAAM;AAC7B,WAAK,SAAS;AACd,YAAM,MAAM,KAAK,MAAM;AACvB,WAAK,YAAY;AACjB,WAAK,IAAI,QAAQ,MAAM;AACrB,YAAI,KAAK,cAAc,IAAK,MAAK,YAAY;AAAA,MAC/C,CAAC;AAAA,IACH,GAAG,OAAO;AACV,SAAK,OAAO,QAAQ;AAAA,EACtB;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,YAAY,KAAK;AACrB,QAAI;AACF,UAAI,CAAE,MAAM,KAAK,aAAa,EAAI;AAClC,kBAAY,MAAM,KAAK,MAAM;AAAA,IAC/B,SAAS,OAAO;AACd,kBAAY,WAAW,OAAO,KAAK,WAAW;AAC9C,WAAK,MAAM,OAAO,MAAM,8CAA8C;AAAA,QACpE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAC5D,WAAW;AAAA,MACb,CAAC;AAAA,IACH,UAAE;AACA,WAAK,UAAU,SAAS;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,MAAM,eAAiC;AACrC,QAAI,KAAK,UAAW,QAAO;AAC3B,UAAM,SAAS,MAAM,KAAK,eAAe,aAAa,KAAK,UAAU,GAAG,KAAK,aAAa,KAAK,WAAW;AAC1G,SAAK,YAAY,OAAO;AACxB,QAAI,KAAK,UAAW,MAAK,mBAAmB;AAC5C,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,qBAA2B;AACzB,QAAI,KAAK,mBAAoB;AAC7B,SAAK,qBAAqB;AAAA,MACxB,MAAM;AACJ,aAAK,KAAK,eACP,WAAW,KAAK,UAAU,GAAG,KAAK,aAAa,KAAK,WAAW,EAC/D,KAAK,aAAW;AACf,cAAI,CAAC,SAAS;AACZ,iBAAK,YAAY;AACjB,iBAAK,kBAAkB;AAAA,UACzB;AAAA,QACF,CAAC,EACA,MAAM,WAAS;AACd,eAAK,YAAY;AACjB,eAAK,kBAAkB;AACvB,eAAK,MAAM,OAAO,KAAK,sDAAsD;AAAA,YAC3E,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,UAC9D,CAAC;AAAA,QACH,CAAC;AAAA,MACL;AAAA,MACA,KAAK,MAAM,KAAK,cAAc,CAAC;AAAA,IACjC;AACA,SAAK,mBAAmB,QAAQ;AAAA,EAClC;AAAA,EAEA,oBAA0B;AACxB,QAAI,KAAK,mBAAoB,eAAc,KAAK,kBAAkB;AAClE,SAAK,qBAAqB;AAAA,EAC5B;AAAA,EAEA,MAAM,QAAyB;AAC7B,UAAM,eAAe,MAAM,KAAK,sBAAsB;AACtD,QAAI,YAAY,KAAK;AAErB,eAAW,cAAc,cAAc;AACrC,UAAI,CAAC,KAAK,YAAY,CAAC,KAAK,UAAW;AACvC,UAAI;AACF,cAAM,KAAK,gBAAgB,WAAW,EAAE;AAAA,MAC1C,SAAS,OAAO;AACd,cAAM,QAAQ,WAAW,OAAO,KAAK,WAAW;AAChD,oBAAY,KAAK,IAAI,WAAW,KAAK;AACrC,aAAK,MAAM,OAAO,MAAM,mDAAmD;AAAA,UACzE,cAAc,WAAW;AAAA,UACzB,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,UAC5D,WAAW;AAAA,QACb,CAAC;AACD,YAAI,iBAAiB,oBAAoB,MAAM,WAAW,IAAK;AAAA,MACjE;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,wBAA+C;AACnD,UAAM,SAAS,MAAM,KAAK,QAAQ,QAM/B,OAAO,GAAG,UAAU,gBAAgB;AACvC,UAAM,eAAe,oBAAI,IAAwB;AAEjD,eAAW,gBAAgB,OAAO,eAAe;AAC/C,UAAI,CAAC,aAAa,UAAU,aAAa,YAAa;AACtD,YAAM,OAAO,MAAM,KAAK,QAAQ;AAAA,QAC9B;AAAA,QACA,GAAG,UAAU,kBAAkB,aAAa,cAAc;AAAA,MAC5D;AACA,iBAAW,cAAc,KAAK,aAAc,cAAa,IAAI,WAAW,IAAI,UAAU;AAAA,IACxF;AAEA,WAAO,CAAC,GAAG,aAAa,OAAO,CAAC;AAAA,EAClC;AAAA,EAEA,MAAM,gBAAgB,cAAqC;AACzD,UAAM,MAAM,OAAO,YAAY;AAC/B,QAAI,CAAC,KAAK,UAAU,aAAa,GAAG,GAAG;AACrC,WAAK,UAAU,aAAa,GAAG,IAAI,EAAE,gBAAgB,KAAK,WAAW;AACrE,YAAM,KAAK,cAAc;AAAA,IAC3B;AAEA,WAAO,KAAK,YAAY,KAAK,WAAW;AACtC,YAAM,SAAsB,KAAK,UAAU,aAAa,GAAG;AAC3D,YAAM,QAAQ,IAAI,gBAAgB,EAAE,OAAO,OAAO,eAAe,EAAE,CAAC;AACpE,UAAI,kBAAkB,OAAQ,OAAM,IAAI,gBAAgB,OAAO,YAAY;AAAA,UACtE,OAAM,IAAI,kBAAkB,OAAO,OAAO,cAAc,CAAC;AAE9D,YAAM,gBAAgB,YAAY,IAAI;AACtC,YAAM,OAAO,MAAM,KAAK,QAAQ;AAAA,QAC9B;AAAA,QACA,GAAG,UAAU,iBAAiB,YAAY,WAAW,KAAK;AAAA,MAC5D;AACA,WAAK,MAAM,OAAO,KAAK,mDAAmD;AAAA,QACxE;AAAA,QACA,YAAY,KAAK,OAAO;AAAA,QACxB,WAAW,KAAK,MAAM,YAAY,IAAI,IAAI,aAAa;AAAA,MACzD,CAAC;AACD,UAAI,KAAK,OAAO,WAAW,KAAK,CAAC,KAAK,WAAY;AAElD,iBAAW,SAAS,KAAK,QAAQ;AAC/B,YAAI,CAAC,KAAK,YAAY,CAAC,KAAK,UAAW;AACvC,cAAM,SAAS,WAAW,KAAK;AAC/B,YAAI,CAAC,QAAQ;AACX,eAAK,MAAM,OAAO,KAAK,wDAAwD;AAAA,YAC7E;AAAA,YACA,SAAS,MAAM;AAAA,UACjB,CAAC;AACD;AAAA,QACF;AACA,YAAI,sBAAsB,MAAM,GAAG;AACjC,gBAAM,KAAK,sBAAsB,MAAM;AAAA,QACzC;AACA,cAAM,SAAS,MAAM,KAAK,UAAU,QAAQ;AAAA,UAC1C,YAAY,KAAK;AAAA,UACjB,mBAAmB,CAAC,QAAQ,YAC1B,uCAAuC,QAAQ,SAAS,KAAK,QAAQ,kBAAkB;AAAA,UACzF,oBAAoB,CAAC,IAAI,WACvB,8BAA8B,IAAI,QAAQ,KAAK,QAAQ,kBAAkB;AAAA,UAC3E,oBAAoB,kBAAgB,KAAK,oBAAoB,YAAY;AAAA,UACzE,eAAe,CAAC,cAAc,UAAU;AACtC,iBAAK,MAAM,OAAO,MAAM,4DAA4D;AAAA,cAClF,gBAAgB,aAAa;AAAA,cAC7B,YAAY,aAAa;AAAA,cACzB,UAAU,aAAa;AAAA,cACvB,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,YAC9D,CAAC;AAAA,UACH;AAAA,QACF,CAAC;AACD,YAAI,OAAO,SAAS,GAAG;AACrB,gBAAM,IAAI;AAAA,YACR,yBAAyB,MAAM,UAAU,eAAe,OAAO,MAAM;AAAA,UACvE;AAAA,QACF;AAAA,MACF;AAEA,UAAI,KAAK,gBAAgB,kBAAkB,SAAS,OAAO,eAAe,QAAY;AACtF,WAAK,UAAU,aAAa,GAAG,IAAI,EAAE,cAAc,KAAK,WAAW;AACnE,YAAM,KAAK,cAAc;AAAA,IAC3B;AAAA,EACF;AAAA,EAEA,MAAM,oBAAoB,cAA2D;AACnF,QAAI,CAACJ,oBAAmB,IAAI,aAAa,IAAI,EAAG,QAAO;AACvD,UAAM,SAAS,aAAa,SAAS;AACrC,UAAM,aAAa,aAAa,SAAS;AACzC,QAAI,CAAC,UAAU,CAAC,WAAY,QAAO;AACnC,QAAIC,iBAAgB,IAAI,MAAM,EAAG,QAAO;AAExC,UAAM,kBAAkB,IAAI,gBAAgB;AAC5C,UAAM,UAAU,WAAW,MAAM,gBAAgB,MAAM,GAAGE,4BAA2B;AACrF,QAAI;AACF,YAAM,aAAa,MAAM,KAAK,QAAQ;AAAA,QACpC,aAAa,SAAS;AAAA,QACtB;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,MAClB;AACA,aAAO,eAAe,UAAaD,wBAAuB,IAAI,UAAU;AAAA,IAC1E,QAAQ;AACN,aAAO;AAAA,IACT,UAAE;AACA,mBAAa,OAAO;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,MAAM,gBAA+B;AACnC,UAAM,KAAK,SAAS,SAAS,KAAK,eAAe,gBAAgB,KAAK,SAAS;AAAA,EACjF;AAAA,EAEA,YAAoB;AAClB,WAAO,GAAG,KAAK,IAAI,IAAI,KAAK,SAAS,aAAa;AAAA,EACpD;AACF;AAEA,SAAS,iBAAiB,QAA+B;AACvD,QAAM,cAAe,OAA2E;AAChG,MAAI,OAAO,gBAAgB,WAAY,QAAO,YAAY,KAAK,MAAM,KAAK;AAC1E,SAAO,gBAAgB,MAAM,IAAI,SAAS;AAC5C;AAEA,SAAS,kBAAkB,OAAoF;AAC7G,MAAI,CAAC,SAAS,MAAM,YAAY,KAAK,CAAC,MAAM,gBAAgB,OAAO,MAAM,iBAAiB,UAAU;AAClG,WAAO,EAAE,SAAS,GAAG,cAAc,CAAC,EAAE;AAAA,EACxC;AACA,SAAO,EAAE,SAAS,GAAG,cAAc,EAAE,GAAG,MAAM,aAAa,EAAE;AAC/D;AAEA,SAAS,sBAAsB,OAAqC;AAClE,UAAQ,MAAM,UAAU,YAAY,MAAM,UAAU,mBAAmB,MAAM,QAAQ,WAAW;AAClG;AAEA,SAAS,WAAW,OAAkD;AACpE,MACE,CAAC,MAAM,MACP,CAAC,MAAM,cACP,CAAC,iBAAiB,IAAI,MAAM,KAAK,KACjC,CAAC,MAAM,WACP,OAAO,MAAM,YAAY,YACzB,MAAM,QAAQ,MAAM,OAAO,GAC3B;AACA,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,OAAO,MAAM;AAAA,IACb,YAAY,MAAM;AAAA,IAClB,SAAS,MAAM;AAAA,EACjB;AACF;AAEA,SAAS,WAAW,OAAgB,YAA4B;AAC9D,MAAI,iBAAiB,oBAAoB,MAAM,WAAW,OAAO,MAAM,sBAAsB,MAAM;AACjG,WAAO,KAAK,IAAI,YAAY,MAAM,oBAAoB,GAAK;AAAA,EAC7D;AACA,SAAO;AACT;;;AZlRA,IAAM,YAAY;AAClB,IAAMG,cAAa;AACnB,IAAM,+BAA+B;AAAA,EACnC,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,eAAe;AACjB;AAEA,SAASC,OAAM,GAAqB;AAClC,SAAO;AACT;AAEA,SAAS,aAAa,KAAyB,YAA4B;AACzE,UAAQ,IAAI,WAAW,IAAI,IAAI,UAAU,EAAE,QAAQ,QAAQ,QAAQ,EAAE;AACvE;AAEO,IAAM,4BAAN,MAA8D;AAAA,EAC1D,KAAK;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA,EACA;AAAA,EAES,SAAiB;AAAA,IACxB,uBAAuB,WAAS,KAAK,uBAAuB,KAAK;AAAA,IACjE,aAAa,OAAO,EAAE,OAAO,OAAO,MAAM;AACxC,YAAM,gBAAgB,MAAM,KAAK,QAAQ,QAQtC,OAAO,GAAGD,WAAU,2BAA2B;AAClD,YAAM,SAAS,cAAc,cAAc;AAAA,QACzC,kBAAgB,aAAa,UAAU,CAAC,aAAa;AAAA,MACvD;AACA,YAAM,eAAe,MAAM,QAAQ;AAAA,QACjC,OAAO,IAAI,OAAM,iBAAgB;AAC/B,gBAAM,qBAAqB,MAAM,KAAK,eAAe,qBAAqB;AAAA,YACxE;AAAA,YACA;AAAA,YACA,cAAc;AAAA,cACZ,YAAY,OAAO,aAAa,cAAc;AAAA,cAC9C,aAAa,aAAa;AAAA,cAC1B,aAAa,aAAa;AAAA,YAC5B;AAAA,UACF,CAAC;AACD,gBAAM,SAAS,MAAM,KAAK,QAAQ,QAQ/B,OAAO,GAAGA,WAAU,6BAA6B,aAAa,cAAc,eAAe;AAC9F,gBAAM,KAAK,eAAe,qBAAqB;AAAA,YAC7C;AAAA,YACA,gBAAgB,mBAAmB;AAAA,YACnC,cAAc,OAAO,aAAa,IAAI,iBAAe;AAAA,cACnD,YAAY,OAAO,WAAW,EAAE;AAAA,cAChC,MAAM,WAAW;AAAA,cACjB,eAAe,WAAW;AAAA,cAC1B,UAAU,EAAE,SAAS,WAAW,SAAS,KAAK,WAAW,QAAQ;AAAA,YACnE,EAAE;AAAA,UACJ,CAAC;AACD,iBAAO,OAAO,aAAa,IAAI,iBAAe,EAAE,YAAY,aAAa,EAAE;AAAA,QAC7E,CAAC;AAAA,MACH;AACA,aAAO,aAAa,KAAK,EAAE,IAAI,CAAC,EAAE,YAAY,aAAa,OAAO;AAAA,QAChE,IAAI,WAAW;AAAA,QACf,MAAM,WAAW;AAAA,QACjB,MAAM;AAAA,QACN,UAAU;AAAA,UACR,gBAAgB,aAAa;AAAA,UAC7B,cAAc,aAAa;AAAA,UAC3B,aAAa,aAAa;AAAA,UAC1B,cAAc,WAAW;AAAA,UACzB,eAAe,WAAW;AAAA,UAC1B,SAAS,WAAW;AAAA,UACpB,KAAK,WAAW;AAAA,QAClB;AAAA,MACF,EAAE;AAAA,IACJ;AAAA,IACA,WAAW,OAAO,EAAE,WAAW,OAAO,MAAM;AAC1C,YAAM,OAAO,oBAAoB,MAAM;AACvC,YAAM,QAAQ,MAAM,QAAQ;AAAA,QAC1B,UAAU,IAAI,OAAM,aAAY;AAC9B,gBAAM,aAAa,EAAE,MAAM,oBAA6B,gBAAgB,EAAE;AAC1E,gBAAM,CAAC,QAAQ,YAAY,IAAI,MAAM,QAAQ,IAAI;AAAA,YAC/C,KAAK,YAAY,YAAY,UAAU,IAAI;AAAA,YAC3C,KAAK,kBAAkB,EAAE,YAAY,UAAU,eAAe,OAAO,QAAQ,OAAO,IAAI,EAAE,CAAC;AAAA,UAC7F,CAAC;AACD,iBAAO;AAAA,YACL,OAAO;AAAA,cACL,GAAG,OAAO,OAAO,IAAI,YAAU;AAAA,gBAC7B,QAAQ,EAAE,MAAM,SAAS,YAAY,GAAG,QAAQ,IAAI,MAAM,EAAE,IAAI,KAAK,MAAM,IAAI;AAAA,gBAC/E;AAAA,gBACA,OAAO,MAAM;AAAA,gBACb,QAAQ,MAAM,SAAS;AAAA,gBACvB,QAAQ,MAAM;AAAA,gBACd,UAAU,MAAM;AAAA,gBAChB,WAAW,MAAM;AAAA,gBACjB,WAAW,MAAM;AAAA,gBACjB,UAAU,EAAE,YAAY,UAAU,QAAQ,OAAO,MAAM,EAAE,GAAG,QAAQ,MAAM,OAAO;AAAA,cACnF,EAAE;AAAA,cACF,GAAG,aAAa,aAAa,IAAI,kBAAgB;AAAA,gBAC/C,QAAQ,EAAE,MAAM,gBAAgB,YAAY,GAAG,QAAQ,IAAI,YAAY,EAAE,IAAI,KAAK,YAAY,IAAI;AAAA,gBAClG;AAAA,gBACA,OAAO,YAAY;AAAA,gBACnB,QAAQ,YAAY;AAAA,gBACpB,WAAW,YAAY;AAAA,gBACvB,WAAW,YAAY;AAAA,gBACvB,UAAU;AAAA,kBACR,YAAY;AAAA,kBACZ,QAAQ,OAAO,YAAY,EAAE;AAAA,kBAC7B,QAAQ,YAAY;AAAA,kBACpB,YAAY,YAAY;AAAA,kBACxB,YAAY,YAAY;AAAA,gBAC1B;AAAA,cACF,EAAE;AAAA,YACJ;AAAA,YACA,aAAa,OAAO,eAAe,QAAQ,aAAa,eAAe;AAAA,UACzE;AAAA,QACF,CAAC;AAAA,MACH;AACA,aAAO;AAAA,QACL,OAAO,MAAM,QAAQ,YAAU,OAAO,KAAK;AAAA,QAC3C,YAAY,MAAM,KAAK,YAAU,OAAO,WAAW,IAAI,OAAO,OAAO,CAAC,IAAI;AAAA,MAC5E;AAAA,IACF;AAAA,IACA,YAAY,OAAM,UAAS;AACzB,8BAAwB,MAAM,UAAU;AACxC,YAAM,WAAW,oBAAoB,MAAM,WAAW,uDAAuD;AAC7G,aAAO,KAAK,YAAY,MAAM,YAAY,UAAU,oBAAoB,MAAM,MAAM,GAAG,MAAM,MAAM;AAAA,IACrG;AAAA,IACA,UAAU,WAAS,KAAK,UAAU,MAAM,YAAY,MAAM,UAAU,MAAM,OAAO;AAAA,IACjF,eAAe,WAAS,KAAK,oBAAoB,KAAK;AAAA,IACtD,aAAa,WAAS,KAAK,mBAAmB,KAAK;AAAA,EACrD;AAAA,EAES,iBAAiC;AAAA,IACxC,YAAY,CAAC,EAAE,QAAQ,MAAM;AAC3B,WAAK,WAAW;AAAA,IAClB;AAAA,IACA,sBAAsB,CAAC,EAAE,OAAO,QAAQ,aAAa,MACnD,KAAK,QAAQ,cAAc,OAAO;AAAA,MAChC;AAAA,MACA,mBAAmB;AAAA,MACnB,YAAY,aAAa;AAAA,MACzB,aAAa,aAAa;AAAA,MAC1B,aAAa,aAAa;AAAA,MAC1B,kBAAkB,aAAa;AAAA,IACjC,CAAC;AAAA,IACH,sBAAsB,CAAC,EAAE,OAAO,gBAAgB,aAAa,MAC3D,QAAQ;AAAA,MACN,aAAa;AAAA,QAAI,gBACf,KAAK,QAAQ,aAAa,OAAO;AAAA,UAC/B;AAAA,UACA,OAAO;AAAA,YACL;AAAA,YACA,YAAY,WAAW;AAAA,YACvB,MAAM,WAAW;AAAA,YACjB,eAAe,WAAW;AAAA,YAC1B,kBAAkB,WAAW;AAAA,UAC/B;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IACF,qBAAqB,OAAO,EAAE,OAAO,aAAa,MAAM;AACtD,YAAM,aAAa,MAAM,KAAK,QAAQ,aAAa,IAAI,EAAE,OAAO,IAAI,aAAa,CAAC;AAClF,UAAI,CAAC,WAAY,OAAM,IAAI,MAAM,uCAAuC;AACxE,YAAM,WAAW,sBAAsB,WAAW,IAAI;AACtD,YAAM,eAAe,MAAM,KAAK,QAAQ,cAAc,IAAI,EAAE,OAAO,IAAI,WAAW,eAAe,CAAC;AAClG,UAAI,CAAC,aAAc,OAAM,IAAI,MAAM,yCAAyC;AAC5E,YAAM,iBAAiB,qBAAqB,aAAa,UAAU;AACnE,UAAI,mBAAmB,KAAM,OAAM,IAAI,MAAM,oCAAoC;AACjF,YAAM,iBAAiB,gBAAgB,WAAW,IAAI,EAAE;AACxD,YAAM,QAAQ,MAAM,KAAK,QAAQ;AAAA,QAC/B;AAAA,QACA,GAAGA,WAAU,6BAA6B,cAAc;AAAA,QACxD,EAAE,cAAc,CAAC,cAAc,GAAG,aAAa,6BAA6B;AAAA,MAC9E;AACA,aAAO;AAAA,QACL;AAAA,QACA,eAAe,EAAE,QAAQ,UAAU,OAAO,MAAM,MAAM;AAAA,MACxD;AAAA,IACF;AAAA,IACA,kBAAkB,WAAS,KAAK,kBAAkB,KAAK;AAAA,IACvD,gBAAgB,WAAS,KAAK,gBAAgB,KAAK;AAAA,IACnD,mBAAmB,WAAS,KAAK,mBAAmB,KAAK;AAAA,IACzD,mBAAmB,WAAS,KAAK,mBAAmB,KAAK;AAAA,IACzD,kBAAkB,WAAS,KAAK,mBAAmB,EAAE,GAAG,OAAO,OAAO,SAAS,CAAC;AAAA,IAChF,kBAAkB,WAAS,KAAK,kBAAkB,KAAK;AAAA,IACvD,cAAc,WAAS,KAAK,cAAc,KAAK;AAAA,IAC/C,eAAe,WAAS,KAAK,eAAe,KAAK;AAAA,IACjD,eAAe,WAAS,KAAK,eAAe,KAAK;AAAA,IACjD,eAAe,WAAS,KAAK,eAAe,KAAK;AAAA,IACjD,aAAa,WAAS,KAAK,aAAa,KAAK;AAAA,IAC7C,WAAW,WAAS,KAAK,WAAW,KAAK;AAAA,IACzC,cAAc,WAAS,KAAK,cAAc,KAAK;AAAA,IAC/C,cAAc,WAAS,KAAK,cAAc,KAAK;AAAA,IAC/C,cAAc,WAAS,KAAK,cAAc,KAAK;AAAA,IAC/C,eAAe,WAAS,KAAK,eAAe,KAAK;AAAA,IACjD,qBAAqB,WAAS,KAAK,qBAAqB,KAAK;AAAA,IAC7D,oBAAoB,WAAS,KAAK,oBAAoB,KAAK;AAAA,IAC3D,qBAAqB,WAAS,KAAK,qBAAqB,KAAK;AAAA,IAC7D,qBAAqB,WAAS,KAAK,qBAAqB,KAAK;AAAA,IAC7D,qBAAqB,WAAS,KAAK,qBAAqB,KAAK;AAAA,IAC7D,wBAAwB,WAAS,KAAK,oBAAoB,OAAO,KAAK;AAAA,IACtE,kBAAkB,WAAS,KAAK,oBAAoB,QAAQ,KAAK;AAAA,IACjE,0BAA0B,WAAS,KAAK,oBAAoB,UAAU,KAAK;AAAA,EAC7E;AAAA,EAEA,cAAc;AACZ,UAAM,SAAS,+BAA+B;AAC9C,SAAK,UAAU,IAAI,kBAAkB,MAAM;AAC3C,SAAK,gBAAgB,IAAI,IAAI,OAAO,OAAO,EAAE;AAC7C,SAAK,kBAAkB,QAAQ,IAAI,wCAAwC,KAAK,EAAE,YAAY,MAAM;AACpG,SAAK,qBAAqB,2BAA2B,4CAA4C;AAAA,EACnG;AAAA,EAEA,IAAI,UAAsC;AACxC,QAAI,CAAC,KAAK,SAAU,OAAM,IAAI,MAAM,4EAA4E;AAChH,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,uBAAmD;AACrD,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,qBAAgD;AAClD,QAAI,CAAC,KAAK,qBAAqB;AAC7B,YAAM,IAAI,MAAM,qEAAqE;AAAA,IACvF;AACA,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,MAAM,uBAAuB;AAAA,IAC3B;AAAA,IACA;AAAA,EACF,GAG6F;AAC3F,UAAM,SAAS,0BAA0B,eAAe,UAAU;AAClE,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,aAAa,OAAO,WAAW,SAAS,GAAG,IAC7C,OAAO,cACN,MAAM,KAAK,QAAQ,aAAa,iBAAiB,EAAE,OAAO,YAAY,OAAO,WAAW,CAAC,IAAI;AAClG,QAAI,CAAC,WAAY,QAAO;AACxB,WAAO;AAAA,MACL,YAAY,EAAE,MAAM,oBAAoB,gBAAgB,EAAE;AAAA,MAC1D,UAAU;AAAA,MACV,SAAS,OAAO;AAAA,IAClB;AAAA,EACF;AAAA,EAEA,WAAW,EAAE,QAAQ,GAAgD;AACnE,SAAK,sBAAsB;AAC3B,oBAAgB,2CAA2C;AAAA,MACzD,cAAc,KAAK;AAAA,MACnB,gBAAgB,KAAK;AAAA,MACrB,mBAAmB,KAAK;AAAA,IAC1B,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,KAAqC;AAC1C,WAAO;AAAA,MACL,KAAK,aAAa,GAAG;AAAA,MACrB,KAAK,cAAc,GAAG;AAAA,MACtB,KAAK,kBAAkB,GAAG;AAAA,MAC1B,GAAG,kBAAkB;AAAA,QACnB,MAAM,IAAI;AAAA,QACV,OAAO,IAAI;AAAA,QACX,SAAS,IAAI;AAAA,QACb,QAAQ;AAAA,QACR,aAAa,IAAI;AAAA,QACjB,SAAS,IAAI;AAAA,QACb,YAAY,IAAI;AAAA,QAChB,UAAU,IAAI,QAAQ;AAAA,QACtB,WAAW,IAAI,OAAO;AAAA,QACtB,oBAAoB,IAAI,OAAO;AAAA,MACjC,CAAC,EAAE;AAAA,QACD,WACE,MAAM,SAAS,wBACf,MAAM,SAAS,yBACf,CAAC,MAAM,KAAK,WAAW,eAAe;AAAA,MAC1C;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aAAa,KAAmC;AAC9C,WAAOE,kBAAiB,sBAAsB;AAAA,MAC5C,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,IAAI,KAAK,WAAWD,OAAM,CAAC,CAAC;AAClC,cAAM,SAAS,IAAI,KAAK,OAAOA,OAAM,CAAC,CAAC;AACvC,YAAI,CAAC,OAAQ,QAAO,EAAE,KAAK,EAAE,OAAO,gBAAgB,QAAQ,gBAAgB,GAAG,GAAG;AAClF,YAAI,CAAC,OAAO,OAAO;AACjB,iBAAO,EAAE,KAAK;AAAA,YACZ,SAAS;AAAA,YACT,gBAAgB,IAAI,MAAM;AAAA,YAC1B,sBAAsB;AAAA,YACtB,WAAW;AAAA,YACX,eAAe,CAAC;AAAA,YAChB,eAAe;AAAA,YACf,oBAAoB;AAAA,YACpB,QAAQ;AAAA,YACR,aAAa,KAAK,YAAY;AAAA,UAChC,CAAC;AAAA,QACH;AAEA,cAAM,CAAC,eAAe,cAAc,IAAI,MAAM,QAAQ,IAAI;AAAA,UACxD,KAAK,mBAAmB,OAAO,OAAO,OAAO,MAAM;AAAA,UACnD,KAAK,qBAAqB,OAAO,MAAM;AAAA,QACzC,CAAC;AACD,eAAO,EAAE,KAAK;AAAA,UACZ,SAAS;AAAA,UACT,gBAAgB,IAAI,MAAM;AAAA,UAC1B,WAAW,cAAc,SAAS;AAAA,UAClC,eAAe,cAAc,IAAI,mBAAiB;AAAA,YAChD,gBAAgB,OAAO,aAAa,UAAU;AAAA,YAC9C,cAAc,aAAa;AAAA,YAC3B,aAAa,aAAa;AAAA,UAC5B,EAAE;AAAA,UACF,eAAe,eAAe;AAAA,UAC9B,oBAAoB,eAAe;AAAA,UACnC,QAAQ,cAAc,SAAS,IAAI,UAAU;AAAA,UAC7C,aAAa,KAAK,YAAY;AAAA,QAChC,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,cAAc,KAAmC;AAC/C,WAAOC,kBAAiB,wBAAwB;AAAA,MAC9C,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,IAAI,KAAK,WAAWD,OAAM,CAAC,CAAC;AAClC,cAAM,SAAS,IAAI,KAAK,OAAOA,OAAM,CAAC,CAAC;AACvC,YAAI,CAAC,QAAQ,MAAO,QAAO,EAAE,KAAK,EAAE,OAAO,eAAe,GAAG,GAAG;AAEhE,cAAM,aAAa,EAAE,IAAI,MAAM,YAAY,KAAK,EAAE,IAAI,MAAM,WAAW,KAAK;AAC5E,cAAM,aAAa,aAAa,KAAK,EAAE,IAAI,GAAG;AAC9C,wBAAgB,yCAAyC;AAAA,UACvD,OAAO,OAAO;AAAA,UACd;AAAA,UACA;AAAA,QACF,CAAC;AACD,cAAM,QAAQ,IAAI,gBAAgB;AAAA,UAChC,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,QACF,CAAC;AACD,cAAM,EAAE,IAAI,IAAI,MAAM,KAAK,QAAQ;AAAA,UACjC;AAAA,UACA,GAAGD,WAAU,2BAA2B,KAAK;AAAA,QAC/C;AACA,eAAO,EAAE,SAAS,GAAG;AAAA,MACvB;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,kBAAkB,KAAmC;AACnD,WAAOE,kBAAiB,6BAA6B;AAAA,MACnD,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,SAAS,OAAM,MAAK;AAClB,cAAM,IAAI,KAAK,WAAWD,OAAM,CAAC,CAAC;AAClC,cAAM,SAAS,IAAI,KAAK,OAAOA,OAAM,CAAC,CAAC;AACvC,YAAI,CAAC,QAAQ,MAAO,QAAO,EAAE,KAAK,EAAE,OAAO,eAAe,GAAG,GAAG;AAEhE,cAAM,aAAa,EAAE,IAAI,MAAM,YAAY,KAAK,EAAE,IAAI,MAAM,WAAW,KAAK;AAC5E,cAAM,aAAa,aAAa,KAAK,EAAE,IAAI,GAAG;AAC9C,wBAAgB,oDAAoD;AAAA,UAClE,OAAO,OAAO;AAAA,UACd;AAAA,UACA;AAAA,QACF,CAAC;AACD,cAAM,QAAQ,IAAI,gBAAgB;AAAA,UAChC,QAAQ,OAAO;AAAA,UACf;AAAA,UACA;AAAA,QACF,CAAC;AACD,cAAM,EAAE,IAAI,IAAI,MAAM,KAAK,QAAQ;AAAA,UACjC;AAAA,UACA,GAAGD,WAAU,4BAA4B,KAAK;AAAA,QAChD;AACA,eAAO,EAAE,SAAS,GAAG;AAAA,MACvB;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,qBAAqB,QAAuD;AAChF,QAAI;AACF,YAAM,aAAa,MAAM,KAAK,QAAQ;AAAA,QACpC;AAAA,QACA,GAAGA,WAAU,+BAA+B,IAAI,gBAAgB,EAAE,OAAO,CAAC,CAAC;AAAA,MAC7E;AACA,UAAI,CAAC,WAAW,aAAa,WAAW,QAAQ;AAC9C,wBAAgB,uDAAuD;AAAA,UACrE;AAAA,UACA,QAAQ,WAAW;AAAA,QACrB,CAAC;AAAA,MACH;AACA,aAAO;AAAA,IACT,QAAQ;AACN,aAAO,EAAE,WAAW,OAAO,gBAAgB,KAAK;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,MAAM,mBAAmB,OAAe,QAAsD;AAC5F,UAAM,SAAS,MAAM,KAAK,QAAQ;AAAA,MAChC;AAAA,MACA,GAAGA,WAAU;AAAA,IACf;AACA,UAAM,sBAAsB,OAAO,cAAc;AAAA,MAC/C,kBAAgB,aAAa,UAAU,CAAC,aAAa;AAAA,IACvD;AACA,WAAO,QAAQ;AAAA,MACb,oBAAoB;AAAA,QAAI,kBACtB,KAAK,eAAe,qBAAqB;AAAA,UACvC;AAAA,UACA;AAAA,UACA,cAAc;AAAA,YACZ,YAAY,OAAO,aAAa,cAAc;AAAA,YAC9C,aAAa,aAAa;AAAA,YAC1B,aAAa,aAAa;AAAA,UAC5B;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEA,QAAQ,KAAsD;AAC5D,QAAI,CAAC,KAAK,gBAAiB,QAAO,CAAC;AACnC,QAAI,CAAC,IAAI,YAAY;AACnB,YAAM,IAAI,MAAM,4EAA4E;AAAA,IAC9F;AACA,WAAO;AAAA,MACL,IAAI,0BAA0B;AAAA,QAC5B,QAAQ,KAAK;AAAA,QACb,YAAY,IAAI;AAAA,QAChB,QAAQ;AAAA,QACR,SAAS,IAAI,QAAQ;AAAA,QACrB,oBAAoB,IAAI,OAAO;AAAA,QAC/B,YAAY,KAAK;AAAA,MACnB,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,aAAa,EAAE,eAAe,GAAyD;AACrF,WAAO,8BAA8B,gBAAgB,IAAoC;AAAA,EAC3F;AAAA,EAEA,MAAM,iBAAiB;AAAA,IACrB;AAAA,IACA;AAAA,EACF,GAAsF;AACpF,UAAM,iBAAiB,wBAAwB,WAAW;AAC1D,QAAI,CAAC,kBAAkB,CAAC,eAAgB;AACxC,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,cAAuC;AACrC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,cAAc,KAAK;AAAA,MACnB,SAAS;AAAA,QACP,SAAS,KAAK;AAAA,QACd,GAAI,KAAK,uBAAuB,SAAY,CAAC,IAAI,EAAE,YAAY,KAAK,mBAAmB;AAAA,MACzF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,oCACJ,iBACA,cACA,UACA,QACiD;AACjD,QAAI;AACJ,QAAI;AACF,mBAAa,gBAAgB,YAAY;AAAA,IAC3C,QAAQ;AACN,aAAO;AAAA,IACT;AACA,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,QAAQ;AAAA,QAChC;AAAA,QACA,GAAGA,WAAU,iBAAiB,mBAAmB,WAAW,KAAK,CAAC,IAAI,mBAAmB,WAAW,IAAI,CAAC,kBAAkB,mBAAmB,QAAQ,CAAC;AAAA,QACvJ;AAAA,QACA,EAAE,OAAO;AAAA,MACX;AACA,aAAO,OAAO;AAAA,IAChB,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,sBAAsB,gBAAgD;AAC1E,UAAM,SAAS,MAAM,KAAK,QAAQ,QAS/B,OAAO,GAAGA,WAAU,6BAA6B,cAAc,eAAe;AACjF,WAAO,OAAO,aAAa,IAAI,iBAAe,EAAE,GAAG,YAAY,eAAe,EAAE;AAAA,EAClF;AAAA,EAEA,MAAM,sBAAsB,gBAAyC;AACnE,UAAM,eAAe,MAAM,KAAK,sBAAsB,cAAc;AACpE,QAAI,aAAa,WAAW,KAAK,aAAa,SAAS,IAAI;AACzD,YAAM,IAAI,MAAM,uFAAuF;AAAA,IACzG;AACA,UAAM,SAAS,MAAM,KAAK,QAAQ;AAAA,MAChC;AAAA,MACA,GAAGA,WAAU,6BAA6B,cAAc;AAAA,MACxD,EAAE,cAAc,aAAa,IAAI,gBAAc,WAAW,IAAI,GAAG,aAAa,6BAA6B;AAAA,IAC7G;AACA,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,MAAM,eACJ,iBACA,UACA,aACA,QACmB;AACnB,UAAM,SAAS,MAAM,KAAK,QAAQ;AAAA,MAChC;AAAA,MACA,eAAe,UAAU,UAAU,WAAW,SAAS;AAAA,MACvD,EAAE,OAAO;AAAA,IACX;AACA,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,uBAAuB,iBAAkF;AACvG,WAAO;AAAA,MACL,OAAO;AAAA,QACL,KAAK,OAAO,EAAE,OAAO,MAAM,YAAY,MAA4D;AACjG,gBAAM,OAAO,MAAM,KAAK,QAAQ;AAAA,YAC9B;AAAA,YACA,eAAe,GAAG,KAAK,IAAI,IAAI,IAAI,SAAS,WAAW,EAAE;AAAA,UAC3D;AACA,iBAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,KAAK,KAAK,KAAK,GAAG,EAAE,EAAE,EAAE;AAAA,QAC/D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,YAAmC,UAAkB,MAAc,QAAmB;AACtG,4BAAwB,UAAU;AAClC,UAAMG,QAAO,eAAe,UAAU,QAAQ;AAC9C,UAAM,QAAQ,IAAI,gBAAgB,EAAE,OAAO,QAAQ,MAAM,OAAO,IAAI,GAAG,UAAU,OAAO,SAAS,EAAE,CAAC;AACpG,UAAM,mBAAmB,gBAAgB,MAAM;AAC/C,QAAI,iBAAiB,SAAS,EAAG,OAAM,IAAI,SAAS,iBAAiB,KAAK,GAAG,CAAC;AAC9E,UAAM,SAAS,MAAM,KAAK,QAAQ,QAAmC,OAAO,GAAGA,KAAI,IAAI,KAAK,EAAE;AAC9F,WAAO;AAAA,MACL,QAAQ,OAAO,OAAO,IAAI,WAAS,iBAAiB,UAAU,KAAK,CAAC;AAAA,MACpE,YAAY,OAAO,OAAO,WAAW,YAAY,OAAO,OAAO,CAAC,IAAI;AAAA,IACtE;AAAA,EACF;AAAA,EAEA,MAAM,UAAU,YAAmC,UAA8B,SAAiB;AAChG,4BAAwB,UAAU;AAClC,UAAM,aAAa,cAAc,UAAU,6CAA6C;AACxF,UAAM,cAAc,kBAAkB,SAAS,OAAO;AACtD,QAAI;AACF,YAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,QAAQ,IAAI;AAAA,QAC1C,KAAK,QAAQ,QAAqB,OAAO,eAAe,YAAY,UAAU,WAAW,EAAE,CAAC;AAAA,QAC5F,KAAK,QAAQ;AAAA,UACX;AAAA,UACA,GAAG,eAAe,YAAY,UAAU,WAAW,WAAW,CAAC;AAAA,QACjE;AAAA,MACF,CAAC;AACD,aAAO,uBAAuB,YAAY,OAAO,SAAS,QAAQ;AAAA,IACpE,SAAS,OAAO;AACd,UAAI,WAAW,KAAK,EAAG,QAAO;AAC9B,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,mBAAmB,OAA4D;AACnF,4BAAwB,MAAM,UAAU;AACxC,UAAM,aAAa,cAAc,MAAM,UAAU,6CAA6C;AAC9F,UAAM,cAAc,kBAAkB,MAAM,SAAS,OAAO;AAC5D,QAAI,MAAM,MAAM,SAAS,UAAU;AACjC,sBAAgB,8DAA8D,MAAM,MAAM,IAAI,cAAc;AAC5G,aAAO;AAAA,IACT;AACA,UAAM,cACJ,MAAM,MAAM,cAAc,eAAe,MAAM,MAAM,cAAc,YAAY,SAAS;AAC1F,UAAM,cACJ,gBAAgB,WAAY,MAAM,MAAM,cAAc,aAAa,gBAAgB,cAAe;AAIpG,QAAI;AACF,YAAM,KAAK,QAAQ,QAA2B,OAAO,eAAe,YAAY,SAAS,WAAW,EAAE,CAAC;AACvG,sBAAgB,uDAAkD,UAAU,IAAI,WAAW,qBAAqB;AAChH,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,CAAC,WAAW,KAAK,EAAG,OAAM;AAAA,IAEhC;AACA,QAAI;AACF,YAAM,QAAQ,MAAM,KAAK,QAAQ;AAAA,QAC/B;AAAA,QACA,eAAe,YAAY,UAAU,WAAW,EAAE;AAAA,QAClD;AAAA,UACE,OAAO;AAAA,UACP,GAAI,cAAc,EAAE,cAAc,YAAY,IAAI,CAAC;AAAA,QACrD;AAAA,QACA,EAAE,cAAc,MAAM,aAAa;AAAA,MACrC;AACA,aAAO,iBAAiB,YAAY,KAAK;AAAA,IAC3C,SAAS,OAAO;AACd,UAAI,WAAW,KAAK,EAAG,QAAO;AAC9B,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,oBAAoB,OAAiC;AACzD,4BAAwB,MAAM,UAAU;AACxC,UAAM,aAAa,cAAc,MAAM,UAAU,6CAA6C;AAC9F,UAAM,cAAc,kBAAkB,MAAM,SAAS,OAAO;AAC5D,QAAI;AACF,YAAM,UAAU,MAAM,KAAK,QAAQ;AAAA,QACjC;AAAA,QACA,eAAe,YAAY,UAAU,WAAW,WAAW;AAAA,QAC3D,EAAE,MAAM,MAAM,KAAK;AAAA,QACnB,EAAE,cAAc,MAAM,aAAa;AAAA,MACrC;AACA,aAAO,EAAE,IAAI,OAAO,QAAQ,EAAE,GAAG,KAAK,QAAQ,QAAQ;AAAA,IACxD,SAAS,OAAO;AACd,UAAI,WAAW,KAAK,EAAG,QAAO;AAC9B,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,kBAAkB,OAA8B;AACpD,4BAAwB,MAAM,UAAU;AACxC,UAAM,OAAO,oBAAoB,MAAM,MAAM;AAC7C,UAAM,QAAQ,IAAI,gBAAgB;AAAA,MAChC,OAAO,MAAM,SAAS;AAAA,MACtB,MAAM,OAAO,IAAI;AAAA,MACjB,UAAU,OAAO,SAAS;AAAA,IAC5B,CAAC;AACD,UAAM,SAAS,MAAM,KAAK,QAAQ;AAAA,MAChC;AAAA,MACA,GAAG,eAAe,MAAM,UAAU,OAAO,CAAC,IAAI,KAAK;AAAA,IACrD;AACA,WAAO;AAAA,MACL,cAAc,OAAO,aAClB,OAAO,iBAAe,MAAM,kBAAkB,SAAS,CAAC,YAAY,KAAK,EACzE,IAAIC,iBAAgB;AAAA,MACvB,YAAY,OAAO,aAAa,WAAW,YAAY,OAAO,OAAO,CAAC,IAAI;AAAA,IAC5E;AAAA,EACF;AAAA,EAEA,MAAM,gBAAgB,OAAuB;AAC3C,QAAI;AACF,aAAOA;AAAA,QACL,MAAM,KAAK,QAAQ,QAA2B,OAAO,gBAAgB,OAAO,MAAM,aAAa,CAAC;AAAA,MAClG;AAAA,IACF,SAAS,OAAO;AACd,UAAI,WAAW,KAAK,EAAG,QAAO;AAC9B,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,mBAAmB,OAA+B;AACtD,4BAAwB,MAAM,UAAU;AACxC,UAAM,SAAS,MAAM,KAAK,QAAQ;AAAA,MAChC;AAAA,MACA,eAAe,MAAM,UAAU,OAAO;AAAA,MACtC;AAAA,QACE,MAAM,MAAM;AAAA,QACZ,MAAM,MAAM;AAAA,QACZ,OAAO,MAAM;AAAA,QACb,MAAM,MAAM;AAAA,QACZ,OAAO,MAAM;AAAA,MACf;AAAA,MACA,EAAE,cAAc,MAAM,aAAa;AAAA,IACrC;AACA,WAAOA,kBAAiB,MAAM;AAAA,EAChC;AAAA,EAEA,MAAM,mBAAmB,OAA+B;AACtD,UAAM,SAAS,MAAM,KAAK,QAAQ;AAAA,MAChC;AAAA,MACA,gBAAgB,OAAO,MAAM,aAAa;AAAA,MAC1C;AAAA,QACE,OAAO,MAAM;AAAA,QACb,MAAM,MAAM,SAAS,OAAO,KAAK,MAAM;AAAA,QACvC,MAAM,MAAM;AAAA,QACZ,OAAO,MAAM;AAAA,MACf;AAAA,MACA,EAAE,cAAc,MAAM,aAAa;AAAA,IACrC;AACA,WAAOA,kBAAiB,MAAM;AAAA,EAChC;AAAA,EAEA,kBAAkB,OAA8B;AAC9C,WAAO,KAAK,QAAQ;AAAA,MAClB;AAAA,MACA,GAAG,gBAAgB,OAAO,MAAM,aAAa,CAAC;AAAA,MAC9C,EAAE,aAAa,MAAM,aAAa,eAAe,MAAM,eAAe,QAAQ,MAAM,OAAO;AAAA,MAC3F,EAAE,cAAc,MAAM,aAAa;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,OAAqC;AACvD,UAAM,OAAO,oBAAoB,MAAM,MAAM;AAC7C,UAAM,SAAS,MAAM,KAAK,QAAQ;AAAA,MAChC;AAAA,MACA,GAAG,eAAe,MAAM,UAAU,UAAU,kBAAkB,MAAM,eAAe,cAAc,CAAC,WAAW,CAAC,SAAS,IAAI,aAAa,SAAS;AAAA,IACnJ;AACA,WAAO;AAAA,MACL,UAAU,OAAO,SAAS,IAAI,YAAY;AAAA,MAC1C,YAAY,OAAO,SAAS,WAAW,YAAY,OAAO,OAAO,CAAC,IAAI;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,MAAM,eAAe,OAAsC;AACzD,UAAM,UAAU,MAAM,KAAK,QAAQ;AAAA,MACjC;AAAA,MACA,eAAe,MAAM,UAAU,UAAU,kBAAkB,MAAM,eAAe,cAAc,CAAC,WAAW;AAAA,MAC1G,EAAE,MAAM,MAAM,KAAK;AAAA,MACnB,EAAE,cAAc,MAAM,aAAa;AAAA,IACrC;AACA,WAAO,aAAa,OAAO;AAAA,EAC7B;AAAA,EAEA,MAAM,eAAe,OAAsC;AACzD,4BAAwB,MAAM,UAAU;AACxC,UAAM,UAAU,MAAM,KAAK,QAAQ;AAAA,MACjC;AAAA,MACA,eAAe,MAAM,UAAU,mBAAmB,kBAAkB,MAAM,WAAW,SAAS,CAAC,EAAE;AAAA,MACjG,EAAE,MAAM,MAAM,KAAK;AAAA,MACnB,EAAE,cAAc,MAAM,aAAa;AAAA,IACrC;AACA,WAAO,aAAa,OAAO;AAAA,EAC7B;AAAA,EAEA,MAAM,eAAe,OAAsC;AACzD,4BAAwB,MAAM,UAAU;AACxC,UAAM,KAAK,QAAQ;AAAA,MACjB;AAAA,MACA,eAAe,MAAM,UAAU,mBAAmB,kBAAkB,MAAM,WAAW,SAAS,CAAC,EAAE;AAAA,MACjG;AAAA,MACA,EAAE,cAAc,MAAM,aAAa;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,OAAyB;AAC1C,UAAM,OAAO,oBAAoB,MAAM,MAAM;AAC7C,UAAM,SAAS,MAAM,KAAK,QAAQ;AAAA,MAChC;AAAA,MACA,GAAG,gBAAgB,OAAO,MAAM,aAAa,CAAC,iBAAiB,IAAI,aAAa,SAAS;AAAA,IAC3F;AACA,WAAO;AAAA,MACL,SAAS,OAAO,QAAQ,IAAI,WAAW;AAAA,MACvC,YAAY,OAAO,QAAQ,WAAW,YAAY,OAAO,OAAO,CAAC,IAAI;AAAA,IACvE;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,OAAkB;AACjC,QAAI;AACF,aAAO;AAAA,QACL,MAAM,KAAK,QAAQ;AAAA,UACjB;AAAA,UACA,GAAG,gBAAgB,OAAO,MAAM,aAAa,CAAC,YAAY,kBAAkB,MAAM,UAAU,QAAQ,CAAC;AAAA,QACvG;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,UAAI,WAAW,KAAK,EAAG,QAAO;AAC9B,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,cAAc,OAA0B;AAC5C,UAAM,SAAS,MAAM,KAAK,QAAQ;AAAA,MAChC;AAAA,MACA,GAAG,gBAAgB,OAAO,MAAM,aAAa,CAAC;AAAA,MAC9C,EAAE,MAAM,MAAM,MAAM,UAAU,MAAM,UAAU,OAAO,MAAM,QAAQ,YAAY,MAAM,KAAK,IAAI,OAAU;AAAA,MACxG,EAAE,cAAc,MAAM,aAAa;AAAA,IACrC;AACA,WAAO,YAAY,MAAM;AAAA,EAC3B;AAAA,EAEA,MAAM,cAAc,OAA0B;AAC5C,UAAM,SAAS,MAAM,KAAK,QAAQ;AAAA,MAChC;AAAA,MACA,GAAG,gBAAgB,OAAO,MAAM,aAAa,CAAC,YAAY,kBAAkB,MAAM,UAAU,QAAQ,CAAC;AAAA,MACrG,EAAE,MAAM,MAAM,KAAK;AAAA,MACnB,EAAE,cAAc,MAAM,aAAa;AAAA,IACrC;AACA,WAAO,YAAY,MAAM;AAAA,EAC3B;AAAA,EAEA,MAAM,cAAc,OAA0B;AAC5C,UAAM,SAAS,MAAM,KAAK,QAAQ;AAAA,MAChC;AAAA,MACA,GAAG,gBAAgB,OAAO,MAAM,aAAa,CAAC,YAAY,kBAAkB,MAAM,UAAU,QAAQ,CAAC;AAAA,MACrG,EAAE,MAAM,MAAM,MAAM,OAAO,YAAY,MAAM,KAAK,EAAE;AAAA,MACpD,EAAE,cAAc,MAAM,aAAa;AAAA,IACrC;AACA,WAAO,YAAY,MAAM;AAAA,EAC3B;AAAA,EAEA,MAAM,eAAe,OAA2B;AAC9C,UAAM,SAAS,MAAM,KAAK,QAAQ;AAAA,MAChC;AAAA,MACA,GAAG,gBAAgB,OAAO,MAAM,aAAa,CAAC,YAAY,kBAAkB,MAAM,UAAU,QAAQ,CAAC;AAAA,MACrG,EAAE,SAAS,MAAM,QAAQ;AAAA,MACzB,EAAE,cAAc,MAAM,aAAa;AAAA,IACrC;AACA,WAAO,YAAY,MAAM;AAAA,EAC3B;AAAA,EAEA,MAAM,qBAAqB,OAAkB;AAC3C,UAAM,KAAK,QAAQ;AAAA,MACjB;AAAA,MACA,GAAG,gBAAgB,OAAO,MAAM,aAAa,CAAC,YAAY,kBAAkB,MAAM,UAAU,QAAQ,CAAC;AAAA,MACrG;AAAA,MACA,EAAE,cAAc,MAAM,aAAa;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,MAAM,oBAAoB,OAAgC;AACxD,UAAM,OAAO,oBAAoB,MAAM,MAAM;AAC7C,UAAM,SAAS,MAAM,KAAK,QAAQ;AAAA,MAChC;AAAA,MACA,GAAG,gBAAgB,OAAO,MAAM,aAAa,CAAC,kBAAkB,IAAI,aAAa,SAAS;AAAA,IAC5F;AACA,WAAO;AAAA,MACL,UAAU,OAAO,SAAS,IAAI,kBAAkB;AAAA,MAChD,YAAY,OAAO,SAAS,WAAW,YAAY,OAAO,OAAO,CAAC,IAAI;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,MAAM,qBAAqB,OAAiC;AAC1D,QAAI;AACJ,QAAI,MAAM,cAAc,QAAW;AACjC,aAAO,EAAE,MAAM,MAAM,MAAM,WAAW,kBAAkB,MAAM,WAAW,gBAAgB,EAAE;AAAA,IAC7F,OAAO;AACL,UAAI,CAAC,MAAM,YAAY,CAAC,MAAM,QAAQ,MAAM,SAAS,UAAa,CAAC,MAAM,MAAM;AAC7E,cAAM,IAAI,MAAM,gFAAgF;AAAA,MAClG;AACA,aAAO;AAAA,QACL,MAAM,MAAM;AAAA,QACZ,UAAU,MAAM;AAAA,QAChB,MAAM,MAAM;AAAA,QACZ,MAAM,MAAM;AAAA,QACZ,MAAM,MAAM,KAAK,YAAY;AAAA,QAC7B,WAAW,MAAM;AAAA,QACjB,WAAW,MAAM,WAAW,YAAY;AAAA,MAC1C;AAAA,IACF;AACA,WAAO;AAAA,MACL,MAAM,KAAK,QAAQ;AAAA,QACjB;AAAA,QACA,GAAG,gBAAgB,OAAO,MAAM,aAAa,CAAC;AAAA,QAC9C;AAAA,QACA,EAAE,cAAc,MAAM,aAAa;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,qBAAqB,OAAsC;AAC/D,4BAAwB,MAAM,UAAU;AACxC,WAAO;AAAA,MACL,MAAM,KAAK,QAAQ;AAAA,QACjB;AAAA,QACA,eAAe,MAAM,UAAU,kBAAkB,kBAAkB,MAAM,WAAW,gBAAgB,CAAC,EAAE;AAAA,QACvG,EAAE,MAAM,MAAM,KAAK;AAAA,QACnB,EAAE,cAAc,MAAM,aAAa;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,qBAAqB,OAAsC;AAC/D,4BAAwB,MAAM,UAAU;AACxC,UAAM,KAAK,QAAQ;AAAA,MACjB;AAAA,MACA,eAAe,MAAM,UAAU,kBAAkB,kBAAkB,MAAM,WAAW,gBAAgB,CAAC,EAAE;AAAA,MACvG;AAAA,MACA,EAAE,cAAc,MAAM,aAAa;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,oBAAoB,QAAmC,OAA6B;AAClF,4BAAwB,MAAM,UAAU;AACxC,WAAO,KAAK,QAAQ;AAAA,MAClB;AAAA,MACA,GAAG,gBAAgB,OAAO,MAAM,aAAa,CAAC;AAAA,MAC9C,WAAW,QAAQ,SAAY,EAAE,OAAO,MAAM,OAAO,OAAO,MAAM,MAAM;AAAA,MACxE,WAAW,QAAQ,SAAY,EAAE,cAAc,MAAM,aAAa;AAAA,IACpE;AAAA,EACF;AACF;AAEA,SAAS,eAAe,UAAkB,QAAwB;AAChE,QAAM,EAAE,OAAO,KAAK,IAAI,gBAAgB,QAAQ;AAChD,SAAO,GAAGJ,WAAU,iBAAiB,mBAAmB,KAAK,CAAC,IAAI,mBAAmB,IAAI,CAAC,IAAI,MAAM;AACtG;AAEA,SAAS,gBACP,OACA,eACQ;AACR,0BAAwB,MAAM,UAAU;AACxC,SAAO,eAAe,MAAM,UAAU,SAAS,kBAAkB,eAAe,cAAc,CAAC,EAAE;AACnG;AAEA,SAAS,gBAAgB,UAAmD;AAC1E,QAAM,QAAQ,SAAS,QAAQ,GAAG;AAClC,MAAI,SAAS,KAAK,UAAU,SAAS,SAAS,GAAG;AAC/C,UAAM,IAAI,MAAM,yDAAyD;AAAA,EAC3E;AACA,SAAO,EAAE,OAAO,SAAS,MAAM,GAAG,KAAK,GAAG,MAAM,SAAS,MAAM,QAAQ,CAAC,EAAE;AAC5E;AAEA,SAAS,iBAAiB,UAAkB,OAAiC;AAC3E,SAAO;AAAA,IACL,IAAI,OAAO,MAAM,MAAM;AAAA,IACvB,YAAY,IAAI,MAAM,MAAM;AAAA,IAC5B,OAAO,MAAM;AAAA,IACb,KAAK,MAAM;AAAA,IACX,QAAQ,MAAM,MAAM,SAAS;AAAA,IAC7B,OAAO,MAAM;AAAA,IACb,WAAW,MAAM;AAAA,IACjB,UAAU;AAAA,IACV,UAAU,MAAM,UAAU,CAAC,KAAK;AAAA,IAChC,QAAQ;AAAA,IACR,QAAQ,MAAM;AAAA,IACd,cAAc,MAAM;AAAA,IACpB,WAAW,MAAM;AAAA,IACjB,WAAW,MAAM;AAAA,EACnB;AACF;AAEA,SAAS,uBAAuB,UAAkB,OAAoB,UAA8C;AAClH,SAAO;AAAA,IACL,GAAG,iBAAiB,UAAU,KAAK;AAAA,IACnC,aAAa,MAAM,MAAM,KAAK,IAAI,MAAM,OAAO;AAAA,IAC/C,UAAU,SAAS,IAAI,cAAY;AAAA,MACjC,QAAQ,QAAQ,MAAM,SAAS;AAAA,MAC/B,MAAM,QAAQ;AAAA,MACd,WAAW,QAAQ;AAAA,IACrB,EAAE;AAAA,EACJ;AACF;AAEA,SAASI,kBAAiB,aAA6C;AACrE,SAAO;AAAA,IACL,IAAI,OAAO,YAAY,MAAM;AAAA,IAC7B,OAAO,YAAY;AAAA,IACnB,KAAK,YAAY;AAAA,IACjB,QAAQ,YAAY,MAAM,SAAS;AAAA,IACnC,MAAM,YAAY,MAAM,KAAK,IAAI,YAAY,OAAO;AAAA,IACpD,OAAO,YAAY;AAAA,IACnB,OAAO,YAAY;AAAA,IACnB,QAAQ,YAAY;AAAA,IACpB,WAAW,YAAY;AAAA,IACvB,YAAY,YAAY,KAAK;AAAA,IAC7B,YAAY,YAAY,KAAK;AAAA,IAC7B,SAAS,YAAY,KAAK;AAAA,IAC1B,WAAW,YAAY;AAAA,IACvB,WAAW,YAAY;AAAA,EACzB;AACF;AAEA,SAAS,aAAa,SAA4C;AAChE,SAAO;AAAA,IACL,IAAI,OAAO,QAAQ,EAAE;AAAA,IACrB,KAAK,QAAQ;AAAA,IACb,QAAQ,QAAQ,MAAM,SAAS;AAAA,IAC/B,MAAM,QAAQ;AAAA,IACd,WAAW,QAAQ;AAAA,IACnB,WAAW,QAAQ;AAAA,EACrB;AACF;AAEA,SAAS,YAAY,QAA8B;AACjD,QAAM,SAAyD;AAAA,IAC7D,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,IACV,mBAAmB;AAAA,IACnB,WAAW;AAAA,EACb;AACA,SAAO;AAAA,IACL,IAAI,OAAO,OAAO,EAAE;AAAA,IACpB,KAAK,OAAO;AAAA,IACZ,QAAQ,OAAO,MAAM,SAAS;AAAA,IAC9B,MAAM,OAAO,MAAM,KAAK,IAAI,OAAO,OAAO;AAAA,IAC1C,OAAO,OAAO,OAAO,KAAK;AAAA,IAC1B,UAAU,OAAO;AAAA,IACjB,aAAa,OAAO;AAAA,EACtB;AACF;AAEA,SAAS,mBAAmB,SAA6C;AACvE,SAAO;AAAA,IACL,GAAG,aAAa,OAAO;AAAA,IACvB,MAAM,QAAQ;AAAA,IACd,MAAM,QAAQ;AAAA,IACd,MAAM,QAAQ,MAAM,YAAY;AAAA,IAChC,UAAU,QAAQ;AAAA,IAClB,WAAW,QAAQ,cAAc,OAAO,OAAO,OAAO,QAAQ,SAAS;AAAA,EACzE;AACF;AAEA,SAAS,wBAAwB,YAAyC;AACxE,MAAI,WAAW,SAAS,sBAAsB,WAAW,SAAS,SAAS;AACzE,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACpE;AACF;AAEA,SAAS,oBAAoB,WAAqB,SAAyB;AACzE,MAAI,UAAU,WAAW,EAAG,OAAM,IAAI,MAAM,OAAO;AACnD,SAAO,UAAU,CAAC;AACpB;AAEA,SAAS,cAAc,UAA8B,SAAyB;AAC5E,MAAI,CAAC,SAAU,OAAM,IAAI,MAAM,OAAO;AACtC,SAAO;AACT;AAEA,SAAS,gBAAgB,QAAwC;AAC/D,SAAO,CAAC,GAAG,IAAI,KAAK,UAAU,CAAC,GAAG,IAAI,WAAS,MAAM,KAAK,CAAC,EAAE,OAAO,OAAO,CAAC,CAAC;AAC/E;AAEA,SAAS,oBAAoB,QAAoC;AAC/D,MAAI,WAAW,OAAW,QAAO;AACjC,QAAM,SAAS,qBAAqB,MAAM;AAC1C,MAAI,WAAW,KAAM,OAAM,IAAI,MAAM,+CAA+C;AACpF,SAAO;AACT;AAEA,SAAS,qBAAqB,OAA8B;AAC1D,MAAI,CAAC,QAAQ,KAAK,KAAK,EAAG,QAAO;AACjC,QAAM,SAAS,OAAO,KAAK;AAC3B,SAAO,OAAO,cAAc,MAAM,KAAK,SAAS,IAAI,SAAS;AAC/D;AAEA,SAAS,0BAA0B,YAAoE;AACrG,QAAM,QACJ,WAAW,MAAM,kBAAkB,KACnC,WAAW,MAAM,6CAA6C,KAC9D,WAAW,MAAM,eAAe;AAClC,MAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,qBAAqB,MAAM,CAAC,CAAC,MAAM,KAAM,QAAO;AAChF,SAAO,EAAE,YAAY,MAAM,CAAC,GAAG,SAAS,MAAM,CAAC,EAAE;AACnD;AAEA,SAAS,2BAA2B,MAAwE;AAC1G,QAAM,QAAQ,QAAQ,IAAI,IAAI,GAAG,KAAK;AACtC,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,SAAS,qBAAqB,KAAK;AACzC,MAAI,WAAW,KAAM,OAAM,IAAI,MAAM,GAAG,IAAI,8BAA8B;AAC1E,SAAO;AACT;AAEA,SAAS,kBAAkB,OAAe,UAA0B;AAClE,QAAM,SAAS,qBAAqB,KAAK;AACzC,MAAI,WAAW,KAAM,OAAM,IAAI,MAAM,UAAU,QAAQ,iCAAiC;AACxF,SAAO;AACT;AAEA,SAAS,YAAY,OAAkD;AACrE,MAAI,UAAU,UAAW,QAAO;AAChC,MAAI,UAAU,kBAAmB,QAAO;AACxC,SAAO;AACT;AAEA,SAAS,WAAW,OAAyB;AAC3C,SAAO,iBAAiB,oBAAoB,MAAM,WAAW;AAC/D;","names":["registerApiRoute","createHash","createHash","isValidGitRef","path","randomUUID","AUTHOR_GATED_KINDS","AUTHORIZED_BOTS","AUTHORIZED_PERMISSIONS","PERMISSION_CHECK_TIMEOUT_MS","randomUUID","API_PREFIX","loose","registerApiRoute","path","parsePullRequest"]}
|