@mastra/factory 0.6.1-alpha.0 → 0.7.0-alpha.2

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.
Files changed (119) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/dist/factory.d.ts +2 -8
  3. package/dist/factory.d.ts.map +1 -1
  4. package/dist/factory.js +9 -5
  5. package/dist/factory.js.map +1 -1
  6. package/dist/integrations/github/integration.d.ts +2 -4
  7. package/dist/integrations/github/integration.d.ts.map +1 -1
  8. package/dist/integrations/github/integration.js +15 -17
  9. package/dist/integrations/github/integration.js.map +1 -1
  10. package/dist/integrations/github/issue-reconciler.js +4 -4
  11. package/dist/integrations/github/issue-reconciler.js.map +1 -1
  12. package/dist/integrations/github/reconcile-worker.d.ts +6 -10
  13. package/dist/integrations/github/reconcile-worker.d.ts.map +1 -1
  14. package/dist/integrations/github/reconcile-worker.js +62 -35
  15. package/dist/integrations/github/reconcile-worker.js.map +1 -1
  16. package/dist/integrations/github/reconciliation-config.d.ts +3 -0
  17. package/dist/integrations/github/reconciliation-config.d.ts.map +1 -0
  18. package/dist/integrations/github/reconciliation-config.js +19 -0
  19. package/dist/integrations/github/reconciliation-config.js.map +1 -0
  20. package/dist/integrations/github/routes.d.ts +1 -3
  21. package/dist/integrations/github/routes.d.ts.map +1 -1
  22. package/dist/integrations/github/routes.js +1 -95
  23. package/dist/integrations/github/routes.js.map +1 -1
  24. package/dist/integrations/github/rules.d.ts.map +1 -1
  25. package/dist/integrations/github/rules.js +2 -1
  26. package/dist/integrations/github/rules.js.map +1 -1
  27. package/dist/integrations/github/webhook.d.ts +0 -4
  28. package/dist/integrations/github/webhook.d.ts.map +1 -1
  29. package/dist/integrations/github/webhook.js +2 -2
  30. package/dist/integrations/github/webhook.js.map +1 -1
  31. package/dist/integrations/linear/integration.d.ts.map +1 -1
  32. package/dist/integrations/linear/integration.js +4 -3
  33. package/dist/integrations/linear/integration.js.map +1 -1
  34. package/dist/integrations/linear/reconciliation-config.d.ts +3 -0
  35. package/dist/integrations/linear/reconciliation-config.d.ts.map +1 -0
  36. package/dist/integrations/linear/reconciliation-config.js +27 -0
  37. package/dist/integrations/linear/reconciliation-config.js.map +1 -0
  38. package/dist/integrations/platform/github/event-worker.d.ts +4 -6
  39. package/dist/integrations/platform/github/event-worker.d.ts.map +1 -1
  40. package/dist/integrations/platform/github/event-worker.js +82 -61
  41. package/dist/integrations/platform/github/event-worker.js.map +1 -1
  42. package/dist/integrations/platform/github/integration.d.ts +0 -2
  43. package/dist/integrations/platform/github/integration.d.ts.map +1 -1
  44. package/dist/integrations/platform/github/integration.js +30 -16
  45. package/dist/integrations/platform/github/integration.js.map +1 -1
  46. package/dist/integrations/platform/linear/integration.d.ts.map +1 -1
  47. package/dist/integrations/platform/linear/integration.js +3 -2
  48. package/dist/integrations/platform/linear/integration.js.map +1 -1
  49. package/dist/integrations/reconciliation-config.d.ts +2 -0
  50. package/dist/integrations/reconciliation-config.d.ts.map +1 -0
  51. package/dist/integrations/reconciliation-config.js +9 -0
  52. package/dist/integrations/reconciliation-config.js.map +1 -0
  53. package/dist/routes/projects.d.ts.map +1 -1
  54. package/dist/routes/projects.js +4 -0
  55. package/dist/routes/projects.js.map +1 -1
  56. package/dist/routes/skills.d.ts.map +1 -1
  57. package/dist/routes/skills.js +30 -9
  58. package/dist/routes/skills.js.map +1 -1
  59. package/dist/routes/surface.d.ts.map +1 -1
  60. package/dist/routes/surface.js +4 -2
  61. package/dist/routes/surface.js.map +1 -1
  62. package/dist/routes/work-items.d.ts +3 -0
  63. package/dist/routes/work-items.d.ts.map +1 -1
  64. package/dist/routes/work-items.js +63 -4
  65. package/dist/routes/work-items.js.map +1 -1
  66. package/dist/rules/defaults.d.ts.map +1 -1
  67. package/dist/rules/defaults.js +19 -4
  68. package/dist/rules/defaults.js.map +1 -1
  69. package/dist/rules/dispatcher.d.ts +5 -0
  70. package/dist/rules/dispatcher.d.ts.map +1 -1
  71. package/dist/rules/dispatcher.js +15 -0
  72. package/dist/rules/dispatcher.js.map +1 -1
  73. package/dist/rules/start-coordinator.d.ts.map +1 -1
  74. package/dist/rules/start-coordinator.js +1 -1
  75. package/dist/rules/start-coordinator.js.map +1 -1
  76. package/dist/rules/types.d.ts +1 -0
  77. package/dist/rules/types.d.ts.map +1 -1
  78. package/dist/rules/types.js.map +1 -1
  79. package/dist/rules/validation.d.ts.map +1 -1
  80. package/dist/rules/validation.js +5 -2
  81. package/dist/rules/validation.js.map +1 -1
  82. package/dist/session/checkpoint-capture.d.ts.map +1 -1
  83. package/dist/session/checkpoint-capture.js +1 -1
  84. package/dist/session/checkpoint-capture.js.map +1 -1
  85. package/dist/session/live-sessions.d.ts +33 -0
  86. package/dist/session/live-sessions.d.ts.map +1 -0
  87. package/dist/session/live-sessions.js +28 -0
  88. package/dist/session/live-sessions.js.map +1 -0
  89. package/dist/skills/catalog.d.ts +9 -0
  90. package/dist/skills/catalog.d.ts.map +1 -0
  91. package/dist/skills/catalog.js +45 -0
  92. package/dist/skills/catalog.js.map +1 -0
  93. package/dist/storage/domains/audit/base.d.ts +0 -1
  94. package/dist/storage/domains/audit/base.d.ts.map +1 -1
  95. package/dist/storage/domains/audit/base.js +0 -1
  96. package/dist/storage/domains/audit/base.js.map +1 -1
  97. package/dist/storage/domains/projects/base.d.ts +3 -0
  98. package/dist/storage/domains/projects/base.d.ts.map +1 -1
  99. package/dist/storage/domains/projects/base.js +7 -0
  100. package/dist/storage/domains/projects/base.js.map +1 -1
  101. package/dist/storage/domains/work-items/base.d.ts +19 -14
  102. package/dist/storage/domains/work-items/base.d.ts.map +1 -1
  103. package/dist/storage/domains/work-items/base.js +75 -21
  104. package/dist/storage/domains/work-items/base.js.map +1 -1
  105. package/dist/storage/domains/work-items/metrics.d.ts +27 -22
  106. package/dist/storage/domains/work-items/metrics.d.ts.map +1 -1
  107. package/dist/storage/domains/work-items/metrics.js +79 -49
  108. package/dist/storage/domains/work-items/metrics.js.map +1 -1
  109. package/dist/workspace.d.ts +2 -0
  110. package/dist/workspace.d.ts.map +1 -1
  111. package/dist/workspace.js +2 -1
  112. package/dist/workspace.js.map +1 -1
  113. package/factory-skills/factory-rereview/SKILL.md +166 -0
  114. package/factory-skills/factory-triage/SKILL.md +64 -12
  115. package/package.json +4 -4
  116. package/dist/integrations/github/issue-triage.d.ts +0 -27
  117. package/dist/integrations/github/issue-triage.d.ts.map +0 -1
  118. package/dist/integrations/github/issue-triage.js +0 -82
  119. package/dist/integrations/github/issue-triage.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"event-worker.js","names":["#client","#controller","#github","#storage","#ingestFactoryEvent","#reconcileFactoryState","#reconcileIssuesFactoryState","#pollEventsEnabled","#reconcileIntervalMs","#intervalMs","#now","#dispatch","#leaseOwner","#leaseTtlMs","#leaseProvider","#running","#startedAt","#settings","#schedule","#timer","#stopLeaseRenewal","#inFlight","#hasLease","#leaseKey","#tick","#ensureLease","#poll","#startLeaseRenewal","#leaseRenewalTimer","#discoverRepositories","#pollRepository","#maybeReconcile","#lastReconcileAt","#saveSettings","#isAuthorizedSender"],"sources":["../../../../src/integrations/platform/github/event-worker.ts"],"sourcesContent":["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 type { GithubIssueReconciler } from '../../github/issue-reconciler.js';\nimport type { GithubPullRequestReconciler, ReconcileRepository } from '../../github/rules.js';\nimport { listPullRequestSubscriptionsForWebhook, retirePullRequestSubscription } from '../../github/subscriptions.js';\nimport type { GithubSubscriptionStorage } from '../../github/subscriptions.js';\nimport { dispatchGithubWebhook } from '../../github/webhook.js';\nimport type {\n GithubWebhookDispatchIntegration,\n GithubWebhookNotification,\n ParsedGithubWebhook,\n} 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 DEFAULT_RECONCILE_INTERVAL_MS = 5 * 60_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; fullName?: string; installationId: number };\n\nexport type PlatformGithubEventDispatchIntegration = GithubWebhookDispatchIntegration;\n\nexport interface PlatformGithubEventWorkerConfig {\n client: PlatformApiClient;\n controller: MountedMastraCode['controller'];\n github: PlatformGithubEventDispatchIntegration;\n storage: PlatformGithubEventStorage;\n ingestFactoryEvent?: (event: ParsedGithubWebhook) => Promise<unknown>;\n reconcileFactoryState?: GithubPullRequestReconciler;\n /**\n * Optional issue-metadata reconciler. When set, folded into the same\n * reconcile tick as `reconcileFactoryState` so a single lease covers both\n * writers of card state for the currently discovered repositories.\n */\n reconcileIssuesFactoryState?: GithubIssueReconciler;\n /** When false the worker skips event tailing and only runs the reconcile sweep. */\n pollEventsEnabled?: boolean;\n intervalMs?: number;\n reconcileIntervalMs?: 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 #reconcileFactoryState: GithubPullRequestReconciler | undefined;\n readonly #reconcileIssuesFactoryState: GithubIssueReconciler | undefined;\n readonly #pollEventsEnabled: boolean;\n readonly #reconcileIntervalMs: number;\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 #lastReconcileAt = 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.#reconcileFactoryState = config.reconcileFactoryState;\n this.#reconcileIssuesFactoryState = config.reconcileIssuesFactoryState;\n this.#pollEventsEnabled = config.pollEventsEnabled ?? true;\n this.#reconcileIntervalMs = config.reconcileIntervalMs ?? DEFAULT_RECONCILE_INTERVAL_MS;\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 // Reconcile-only mode has no event tail to keep fresh, so tick on the\n // slower reconcile cadence instead of the polling interval.\n let retryInMs = this.#pollEventsEnabled ? this.#intervalMs : this.#reconcileIntervalMs;\n\n if (this.#pollEventsEnabled) {\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\n await this.#maybeReconcile(repositories);\n\n return retryInMs;\n }\n\n /**\n * State-based safety net: event tailing can miss merges (cursor gaps,\n * downtime, terminally failed decisions), so on a slower cadence we compare\n * still-open PR cards against actual GitHub state and replay missed merges\n * through the normal ingress, which dedupes against the event path.\n */\n async #maybeReconcile(repositories: Repository[]): Promise<void> {\n if (!this.#reconcileFactoryState || !this.#running || !this.#hasLease) return;\n const now = this.#now();\n if (now - this.#lastReconcileAt < this.#reconcileIntervalMs) return;\n // Advance the clock before sweeping so a persistently failing sweep stays\n // on cadence instead of retrying every poll tick.\n this.#lastReconcileAt = now;\n const targets: ReconcileRepository[] = repositories.flatMap(repository =>\n repository.fullName\n ? [{ id: repository.id, fullName: repository.fullName, installationId: repository.installationId }]\n : [],\n );\n if (targets.length === 0) {\n this.deps?.logger.debug('Platform GitHub pull request reconcile skipped: no named repositories');\n return;\n }\n this.deps?.logger.debug('Platform GitHub pull request reconcile sweep starting', {\n candidateRepositories: targets.length,\n });\n const startedAt = Date.now();\n try {\n // `counts.repositories` is the factory-configured subset actually swept;\n // `candidateRepositories` is everything the installations exposed.\n const { errors, ...counts } = await this.#reconcileFactoryState(targets);\n const context = { ...counts, candidateRepositories: targets.length, durationMs: Date.now() - startedAt };\n if (counts.failed > 0) {\n this.deps?.logger.warn('Platform GitHub pull request reconcile sweep completed with failures', {\n ...context,\n errors,\n });\n } else if (counts.merged > 0 || counts.closed > 0) {\n this.deps?.logger.info('Platform GitHub pull request reconcile replayed missed merges/closes', context);\n } else {\n this.deps?.logger.info('Platform GitHub pull request reconcile sweep completed', context);\n }\n } catch (error) {\n this.deps?.logger.error('Platform GitHub pull request reconcile failed', {\n repositories: targets.length,\n durationMs: Date.now() - startedAt,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n\n // Same tick as the PR reconciler: repository set already discovered, lease\n // already held, cadence already gated. Issues have no closed-webhook replay\n // so this only patches drifted metadata (state/author/assignees/labels).\n if (!this.#reconcileIssuesFactoryState) return;\n const issueStartedAt = Date.now();\n try {\n const { errors, ...counts } = await this.#reconcileIssuesFactoryState(targets);\n const context = { ...counts, candidateRepositories: targets.length, durationMs: Date.now() - issueStartedAt };\n if (counts.failed > 0) {\n this.deps?.logger.warn('Platform GitHub issue reconcile sweep completed with failures', {\n ...context,\n errors,\n });\n } else if (counts.updated > 0) {\n this.deps?.logger.info('Platform GitHub issue reconcile patched stale metadata', context);\n } else {\n this.deps?.logger.debug('Platform GitHub issue reconcile sweep completed', context);\n }\n } catch (error) {\n this.deps?.logger.error('Platform GitHub issue reconcile failed', {\n repositories: targets.length,\n durationMs: Date.now() - issueStartedAt,\n error: error instanceof Error ? error.message : String(error),\n });\n }\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: Array<{ id: number; fullName?: string }> }>(\n 'GET',\n `${API_PREFIX}/installations/${installation.installationId}/repositories`,\n );\n for (const repository of page.repositories) {\n repositories.set(repository.id, { ...repository, installationId: installation.installationId });\n }\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.debug('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 github: this.#github,\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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"}
1
+ {"version":3,"file":"event-worker.js","names":["#client","#controller","#github","#storage","#ingestFactoryEvent","#reconcileFactoryState","#reconcileIssuesFactoryState","#pollEventsEnabled","#pullRequestReconcileIntervalMs","#issueReconcileIntervalMs","#intervalMs","#now","#dispatch","#leaseOwner","#leaseTtlMs","#leaseProvider","#running","#startedAt","#settings","#schedule","#timer","#stopLeaseRenewal","#inFlight","#hasLease","#leaseKey","#tick","#ensureLease","#poll","#startLeaseRenewal","#leaseRenewalTimer","#discoverRepositories","#reconcileCadence","#pollRepository","#maybeReconcile","#lastPullRequestReconcileAt","#lastIssueReconcileAt","#saveSettings","#isAuthorizedSender"],"sources":["../../../../src/integrations/platform/github/event-worker.ts"],"sourcesContent":["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 type { GithubIssueReconciler } from '../../github/issue-reconciler.js';\nimport type { GithubPullRequestReconciler, ReconcileRepository } from '../../github/rules.js';\nimport { listPullRequestSubscriptionsForWebhook, retirePullRequestSubscription } from '../../github/subscriptions.js';\nimport { dispatchGithubWebhook } from '../../github/webhook.js';\nimport type {\n GithubWebhookDispatchIntegration,\n GithubWebhookNotification,\n ParsedGithubWebhook,\n} 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 DEFAULT_RECONCILE_INTERVAL_MS = 5 * 60_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; fullName?: string; installationId: number };\n\nexport type PlatformGithubEventDispatchIntegration = GithubWebhookDispatchIntegration;\n\nexport interface PlatformGithubEventWorkerConfig {\n client: PlatformApiClient;\n controller: MountedMastraCode['controller'];\n github: PlatformGithubEventDispatchIntegration;\n storage: PlatformGithubEventStorage;\n ingestFactoryEvent?: (event: ParsedGithubWebhook) => Promise<unknown>;\n reconcileFactoryState?: GithubPullRequestReconciler;\n reconcileIssuesFactoryState?: GithubIssueReconciler;\n /** When false the worker skips event tailing and only runs enabled reconciliation sweeps. */\n pollEventsEnabled?: boolean;\n intervalMs?: number;\n /** Legacy shared reconciliation cadence. */\n reconcileIntervalMs?: number;\n pullRequestReconcileIntervalMs?: number;\n issueReconcileIntervalMs?: 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 #reconcileFactoryState: GithubPullRequestReconciler | undefined;\n readonly #reconcileIssuesFactoryState: GithubIssueReconciler | undefined;\n readonly #pollEventsEnabled: boolean;\n readonly #pullRequestReconcileIntervalMs: number;\n readonly #issueReconcileIntervalMs: number;\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 #lastPullRequestReconcileAt = 0;\n #lastIssueReconcileAt = 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.#reconcileFactoryState = config.reconcileFactoryState;\n this.#reconcileIssuesFactoryState = config.reconcileIssuesFactoryState;\n this.#pollEventsEnabled = config.pollEventsEnabled ?? true;\n const legacyReconcileIntervalMs = config.reconcileIntervalMs ?? DEFAULT_RECONCILE_INTERVAL_MS;\n this.#pullRequestReconcileIntervalMs = config.pullRequestReconcileIntervalMs ?? legacyReconcileIntervalMs;\n this.#issueReconcileIntervalMs = config.issueReconcileIntervalMs ?? legacyReconcileIntervalMs;\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 if (!Number.isFinite(this.#pullRequestReconcileIntervalMs) || this.#pullRequestReconcileIntervalMs <= 0) {\n throw new Error('Platform GitHub pull request reconcile interval must be a positive number.');\n }\n if (!Number.isFinite(this.#issueReconcileIntervalMs) || this.#issueReconcileIntervalMs <= 0) {\n throw new Error('Platform GitHub issue reconcile interval must be a positive number.');\n }\n this.#leaseTtlMs = Math.max(\n MIN_LEASE_TTL_MS,\n Math.min(this.#intervalMs, this.#pullRequestReconcileIntervalMs, this.#issueReconcileIntervalMs) * 3,\n );\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.#pollEventsEnabled ? this.#intervalMs : this.#reconcileCadence();\n\n if (this.#pollEventsEnabled) {\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\n await this.#maybeReconcile(repositories);\n return retryInMs;\n }\n\n #reconcileCadence(): number {\n const cadences = [\n this.#reconcileFactoryState ? this.#pullRequestReconcileIntervalMs : undefined,\n this.#reconcileIssuesFactoryState ? this.#issueReconcileIntervalMs : undefined,\n ].filter((interval): interval is number => interval !== undefined);\n return cadences.length > 0 ? Math.min(...cadences) : this.#intervalMs;\n }\n\n async #maybeReconcile(repositories: Repository[]): Promise<void> {\n if (!this.#running || !this.#hasLease) return;\n const now = this.#now();\n const reconcilePullRequests = Boolean(\n this.#reconcileFactoryState && now - this.#lastPullRequestReconcileAt >= this.#pullRequestReconcileIntervalMs,\n );\n const reconcileIssues = Boolean(\n this.#reconcileIssuesFactoryState && now - this.#lastIssueReconcileAt >= this.#issueReconcileIntervalMs,\n );\n if (!reconcilePullRequests && !reconcileIssues) return;\n if (reconcilePullRequests) this.#lastPullRequestReconcileAt = now;\n if (reconcileIssues) this.#lastIssueReconcileAt = now;\n\n const targets: ReconcileRepository[] = repositories.flatMap(repository =>\n repository.fullName\n ? [{ id: repository.id, fullName: repository.fullName, installationId: repository.installationId }]\n : [],\n );\n if (targets.length === 0) {\n this.deps?.logger.debug('Platform GitHub reconciliation skipped: no named repositories');\n return;\n }\n\n if (reconcilePullRequests && this.#reconcileFactoryState) {\n const startedAt = Date.now();\n try {\n const { errors, ...counts } = await this.#reconcileFactoryState(targets);\n const context = { ...counts, candidateRepositories: targets.length, durationMs: Date.now() - startedAt };\n if (counts.failed > 0) {\n this.deps?.logger.warn('Platform GitHub pull request reconcile sweep completed with failures', {\n ...context,\n errors,\n });\n } else if (counts.merged > 0 || counts.closed > 0) {\n this.deps?.logger.info('Platform GitHub pull request reconcile replayed missed merges/closes', context);\n } else {\n this.deps?.logger.info('Platform GitHub pull request reconcile sweep completed', context);\n }\n } catch (error) {\n this.deps?.logger.error('Platform GitHub pull request reconcile failed', {\n repositories: targets.length,\n durationMs: Date.now() - startedAt,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n if (reconcileIssues && this.#reconcileIssuesFactoryState && this.#hasLease) {\n const startedAt = Date.now();\n try {\n const { errors, ...counts } = await this.#reconcileIssuesFactoryState(targets);\n const context = { ...counts, candidateRepositories: targets.length, durationMs: Date.now() - startedAt };\n if (counts.failed > 0) {\n this.deps?.logger.warn('Platform GitHub issue reconcile sweep completed with failures', { ...context, errors });\n } else if (counts.closed > 0) {\n this.deps?.logger.info('Platform GitHub issue reconcile replayed closed work items', context);\n } else if (counts.updated > 0) {\n this.deps?.logger.info('Platform GitHub issue reconcile patched stale metadata', context);\n } else {\n this.deps?.logger.debug('Platform GitHub issue reconcile sweep completed', context);\n }\n } catch (error) {\n this.deps?.logger.error('Platform GitHub issue reconcile failed', {\n repositories: targets.length,\n durationMs: Date.now() - startedAt,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\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: Array<{ id: number; fullName?: string }> }>(\n 'GET',\n `${API_PREFIX}/installations/${installation.installationId}/repositories`,\n );\n for (const repository of page.repositories) {\n repositories.set(repository.id, { ...repository, installationId: installation.installationId });\n }\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.debug('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 (isFactoryIngestedEvent(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 github: this.#github,\n isAuthorizedSender: notification => this.#isAuthorizedSender(notification),\n onTargetError: (subscription, error) => {\n this.deps?.logger.error('Platform GitHub event delivery failed for a subscription', {\n deliveryId: event.deliveryId,\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 this.deps?.logger.warn('Platform GitHub event completed with failed subscription deliveries', {\n repositoryId,\n deliveryId: event.deliveryId,\n delivered: result.delivered,\n failed: result.failed,\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\n// Events the polling worker forwards to the factory rules engine. Closures\n// let the reconciler finalize cards; `synchronize` and `review_requested` on a\n// pull request are the two triggers the review board's re-review path listens\n// for. Direct-webhook consumers ingest every parsed event; the platform path\n// gates because most other events (comments, reviews, edits) only interest the\n// subscription dispatcher, not the factory rules.\nfunction isFactoryIngestedEvent(event: ParsedGithubWebhook): boolean {\n if ((event.event === 'issues' || event.event === 'pull_request') && event.payload.action === 'closed') {\n return true;\n }\n if (event.event === 'pull_request') {\n const action = event.payload.action;\n if (action === 'synchronize' || action === 'review_requested') return true;\n }\n return false;\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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"}
@@ -7,7 +7,6 @@ import type { IntegrationStorageHandle } from '../../../storage/domains/integrat
7
7
  import type { SourceControlStorageHandle } from '../../../storage/domains/source-control/base.js';
8
8
  import type { FactoryIntegration, IntegrationContext, IntegrationTools } from '../../base.js';
9
9
  import type { GithubIntegration, GithubRepositoryPermission, RepoSummary } from '../../github/integration.js';
10
- import type { GithubIssueTriageInput, GithubIssueTriageResult } from '../../github/issue-triage.js';
11
10
  import type { ReconcileIssueState, ReconcilePullRequestState } from '../../github/rules.js';
12
11
  import type { GithubSubscriptionStorage } from '../../github/subscriptions.js';
13
12
  export declare class PlatformGithubIntegration implements FactoryIntegration {
@@ -16,7 +15,6 @@ export declare class PlatformGithubIntegration implements FactoryIntegration {
16
15
  readonly intake: Intake;
17
16
  readonly versionControl: VersionControl;
18
17
  constructor(options?: {
19
- runIssueTriage?: (input: GithubIssueTriageInput) => Promise<GithubIssueTriageResult>;
20
18
  /** GitHub App slug used to recognize Factory's own webhook writes. */
21
19
  slug?: string;
22
20
  });
@@ -1 +1 @@
1
- {"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../../../src/integrations/platform/github/integration.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../../../src/integrations/platform/github/integration.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { createGithubSubscriptionTools, parseCreatedPullRequest, subscribeCurrentSessionToPullRequest } from "../../github/session-subscriptions.js";
2
2
  import { attachGithubReconciler, attachGithubRules } from "../../github/rules.js";
3
3
  import { attachGithubIssueReconciler } from "../../github/issue-reconciler.js";
4
- import { runGithubIssueTriage } from "../../github/issue-triage.js";
4
+ import { reconcileInterval, reconciliationEnabled } from "../../github/reconciliation-config.js";
5
5
  import { buildGithubRoutes } from "../../github/routes.js";
6
6
  import { PlatformApiClient, PlatformApiError, logPlatformInfo, logPlatformWarn, platformApiClientConfigFromEnv } from "../api-client.js";
7
7
  import { PlatformGithubEventWorker } from "./event-worker.js";
@@ -54,14 +54,16 @@ var PlatformGithubIntegration = class {
54
54
  #slug;
55
55
  #pollingEnabled;
56
56
  #pollingIntervalMs;
57
- #reconcileEnabled;
57
+ #pullRequestReconcileEnabled;
58
+ #issueReconcileEnabled;
59
+ #pullRequestReconcileIntervalMs;
60
+ #issueReconcileIntervalMs;
58
61
  #storage;
59
62
  #integrationStorage;
60
63
  /** installationId → cached repository listing (TTL-bounded). */
61
64
  #installationReposCache = /* @__PURE__ */ new Map();
62
65
  /** `orgId:repositoryId` → cached repository access (TTL-bounded). */
63
66
  #repositoryAccessCache = /* @__PURE__ */ new Map();
64
- #runIssueTriage;
65
67
  intake = {
66
68
  resolveIntakeDispatch: (input) => this.#resolveIntakeDispatch(input),
67
69
  listSources: async ({ orgId, userId }) => {
@@ -297,8 +299,12 @@ var PlatformGithubIntegration = class {
297
299
  this.#slug = options.slug;
298
300
  this.#pollingEnabled = process.env.MASTRA_PLATFORM_GITHUB_POLLING_ENABLED?.trim().toLowerCase() !== "false";
299
301
  this.#pollingIntervalMs = optionalPositiveIntegerEnv("MASTRA_PLATFORM_GITHUB_POLLING_INTERVAL_MS");
300
- this.#reconcileEnabled = process.env.MASTRA_PLATFORM_GITHUB_RECONCILE_ENABLED?.trim().toLowerCase() !== "false";
301
- this.#runIssueTriage = options.runIssueTriage;
302
+ const legacyReconcileEnabled = process.env.MASTRA_PLATFORM_GITHUB_RECONCILE_ENABLED;
303
+ this.#pullRequestReconcileEnabled = reconciliationEnabled(process.env.MASTRACODE_PLATFORM_GITHUB_PR_RECONCILE_ENABLED, legacyReconcileEnabled);
304
+ this.#issueReconcileEnabled = reconciliationEnabled(process.env.MASTRACODE_PLATFORM_GITHUB_ISSUE_RECONCILE_ENABLED, legacyReconcileEnabled);
305
+ const legacyReconcileIntervalMs = reconcileInterval(process.env.MASTRACODE_PLATFORM_GITHUB_RECONCILE_INTERVAL_MS);
306
+ this.#pullRequestReconcileIntervalMs = reconcileInterval(process.env.MASTRACODE_PLATFORM_GITHUB_PR_RECONCILE_INTERVAL_MS) ?? legacyReconcileIntervalMs;
307
+ this.#issueReconcileIntervalMs = reconcileInterval(process.env.MASTRACODE_PLATFORM_GITHUB_ISSUE_RECONCILE_INTERVAL_MS) ?? legacyReconcileIntervalMs;
302
308
  }
303
309
  /** GitHub App slug when the deployment explicitly provides it. */
304
310
  get slug() {
@@ -339,7 +345,8 @@ var PlatformGithubIntegration = class {
339
345
  endpointHost: this.#endpointHost,
340
346
  pollingEnabled: this.#pollingEnabled,
341
347
  pollingIntervalMs: this.#pollingIntervalMs,
342
- reconcileEnabled: this.#reconcileEnabled
348
+ pullRequestReconcileEnabled: this.#pullRequestReconcileEnabled,
349
+ issueReconcileEnabled: this.#issueReconcileEnabled
343
350
  });
344
351
  }
345
352
  routes(ctx) {
@@ -358,11 +365,7 @@ var PlatformGithubIntegration = class {
358
365
  controller: ctx.controller,
359
366
  projects: ctx.storage.projects,
360
367
  emitAudit: ctx.hooks?.emitAudit,
361
- ingestFactoryEvent,
362
- runIssueTriage: this.#runIssueTriage ?? (ctx.controller ? (input) => runGithubIssueTriage({
363
- controller: ctx.controller,
364
- input
365
- }) : void 0)
368
+ ingestFactoryEvent
366
369
  }).filter((route) => route.path !== "/web/github/status" && route.path !== "/web/github/webhook" && !route.path.startsWith("/auth/github/"))
367
370
  ];
368
371
  }
@@ -488,7 +491,7 @@ var PlatformGithubIntegration = class {
488
491
  })));
489
492
  }
490
493
  workers(ctx) {
491
- if (!this.#pollingEnabled && !this.#reconcileEnabled) return [];
494
+ if (!this.#pollingEnabled && !this.#pullRequestReconcileEnabled && !this.#issueReconcileEnabled) return [];
492
495
  if (!ctx.controller) throw new Error("Platform GitHub event polling requires the mounted Mastra Code controller.");
493
496
  return [new PlatformGithubEventWorker({
494
497
  client: this.#client,
@@ -496,10 +499,12 @@ var PlatformGithubIntegration = class {
496
499
  github: this,
497
500
  storage: ctx.storage.generic,
498
501
  ingestFactoryEvent: attachGithubRules(this, ctx),
499
- reconcileFactoryState: this.#reconcileEnabled ? attachGithubReconciler(this, ctx, (input) => this.fetchPullRequestState(input)) : void 0,
500
- reconcileIssuesFactoryState: this.#reconcileEnabled ? attachGithubIssueReconciler(this, ctx, (input) => this.fetchIssueState(input)) : void 0,
502
+ reconcileFactoryState: this.#pullRequestReconcileEnabled ? attachGithubReconciler(this, ctx, (input) => this.fetchPullRequestState(input)) : void 0,
503
+ reconcileIssuesFactoryState: this.#issueReconcileEnabled ? attachGithubIssueReconciler(this, ctx, (input) => this.fetchIssueState(input)) : void 0,
501
504
  pollEventsEnabled: this.#pollingEnabled,
502
- intervalMs: this.#pollingIntervalMs
505
+ intervalMs: this.#pollingIntervalMs,
506
+ pullRequestReconcileIntervalMs: this.#pullRequestReconcileIntervalMs,
507
+ issueReconcileIntervalMs: this.#issueReconcileIntervalMs
503
508
  })];
504
509
  }
505
510
  /**
@@ -581,7 +586,16 @@ var PlatformGithubIntegration = class {
581
586
  enabled: this.#pollingEnabled,
582
587
  ...this.#pollingIntervalMs === void 0 ? {} : { intervalMs: this.#pollingIntervalMs }
583
588
  },
584
- reconcile: { enabled: this.#reconcileEnabled }
589
+ reconcile: {
590
+ pullRequests: {
591
+ enabled: this.#pullRequestReconcileEnabled,
592
+ ...this.#pullRequestReconcileIntervalMs === void 0 ? {} : { intervalMs: this.#pullRequestReconcileIntervalMs }
593
+ },
594
+ issues: {
595
+ enabled: this.#issueReconcileEnabled,
596
+ ...this.#issueReconcileIntervalMs === void 0 ? {} : { intervalMs: this.#issueReconcileIntervalMs }
597
+ }
598
+ }
585
599
  };
586
600
  }
587
601
  async getRepositoryCollaboratorPermission(_installationId, repoFullName, username, signal) {