@mastra/factory 0.25.0-alpha.4 → 0.25.0-alpha.6
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/README.md +3 -1
- package/dist/auth.js +1 -2
- package/dist/boards/define-board.js +1 -2
- package/dist/boards/index.js +1 -2
- package/dist/boards/registry.js +1 -2
- package/dist/boards/relocate.js +1 -2
- package/dist/boards/review.js +1 -2
- package/dist/boards/semantics.js +1 -2
- package/dist/boards/transition-policy.js +1 -2
- package/dist/boards/work-tool-rules.js +1 -2
- package/dist/boards/work-transition-policy.js +1 -2
- package/dist/boards/work.js +1 -2
- package/dist/default-thinking-level.d.ts +3 -0
- package/dist/default-thinking-level.d.ts.map +1 -0
- package/dist/default-thinking-level.js +5 -0
- package/dist/default-thinking-level.js.map +1 -0
- package/dist/environment/build-runner.js +1 -2
- package/dist/environment/build-schedule.js +1 -2
- package/dist/environment/build-workflow.js +1 -2
- package/dist/environment/build.js +1 -2
- package/dist/environment/heads.js +1 -2
- package/dist/factory.d.ts +4 -2
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +62 -21
- package/dist/factory.js.map +1 -1
- package/dist/feed-events.js +1 -2
- package/dist/index.js +2 -2
- package/dist/integrations/channel-thread-announcements.d.ts +8 -0
- package/dist/integrations/channel-thread-announcements.d.ts.map +1 -0
- package/dist/integrations/channel-thread-announcements.js +16 -0
- package/dist/integrations/channel-thread-announcements.js.map +1 -0
- package/dist/integrations/github/acceptance-labels.js +1 -2
- package/dist/integrations/github/app-identity.js +1 -2
- package/dist/integrations/github/commits.js +1 -2
- package/dist/integrations/github/config.js +1 -2
- package/dist/integrations/github/default-rules.js +2 -3
- package/dist/integrations/github/integration.js +3 -4
- package/dist/integrations/github/issue-reconciler.js +1 -2
- package/dist/integrations/github/pat.js +1 -2
- package/dist/integrations/github/provenance.d.ts.map +1 -1
- package/dist/integrations/github/provenance.js +2 -5
- package/dist/integrations/github/provenance.js.map +1 -1
- package/dist/integrations/github/reconcile-worker.js +1 -2
- package/dist/integrations/github/reconciliation-config.js +1 -2
- package/dist/integrations/github/routes.js +4 -5
- package/dist/integrations/github/rules.d.ts.map +1 -1
- package/dist/integrations/github/rules.js +14 -3
- package/dist/integrations/github/rules.js.map +1 -1
- package/dist/integrations/github/sandbox-release.js +1 -2
- package/dist/integrations/github/sandbox.js +1 -2
- package/dist/integrations/github/session-subscriptions.js +1 -2
- package/dist/integrations/github/settle-or-abort.js +1 -2
- package/dist/integrations/github/stale-reviews.js +1 -2
- package/dist/integrations/github/subscriptions.js +1 -2
- package/dist/integrations/github/token-refresh.js +1 -2
- package/dist/integrations/github/webhook.d.ts.map +1 -1
- package/dist/integrations/github/webhook.js +17 -3
- package/dist/integrations/github/webhook.js.map +1 -1
- package/dist/integrations/gitlab/agent-tools.js +1 -2
- package/dist/integrations/gitlab/api.js +1 -2
- package/dist/integrations/gitlab/default-rules.js +1 -2
- package/dist/integrations/gitlab/integration.d.ts +4 -0
- package/dist/integrations/gitlab/integration.d.ts.map +1 -1
- package/dist/integrations/gitlab/integration.js +12 -4
- package/dist/integrations/gitlab/integration.js.map +1 -1
- package/dist/integrations/gitlab/issue-reconciler.js +1 -2
- package/dist/integrations/gitlab/merge-request-reconciler.js +1 -2
- package/dist/integrations/gitlab/reconciler.js +1 -2
- package/dist/integrations/gitlab/reconciliation-config.js +1 -2
- package/dist/integrations/gitlab/routes.d.ts +6 -0
- package/dist/integrations/gitlab/routes.d.ts.map +1 -1
- package/dist/integrations/gitlab/routes.js +154 -3
- package/dist/integrations/gitlab/routes.js.map +1 -1
- package/dist/integrations/gitlab/rules.d.ts.map +1 -1
- package/dist/integrations/gitlab/rules.js +5 -3
- package/dist/integrations/gitlab/rules.js.map +1 -1
- package/dist/integrations/gitlab/session-subscriptions.js +1 -2
- package/dist/integrations/gitlab/subscriptions.js +1 -2
- package/dist/integrations/gitlab/version-control.js +1 -2
- package/dist/integrations/gitlab/webhook-dispatch.js +1 -2
- package/dist/integrations/gitlab/webhook.js +1 -2
- package/dist/integrations/incidentio/agent-tools.js +1 -2
- package/dist/integrations/incidentio/api.js +1 -2
- package/dist/integrations/incidentio/claim.js +1 -2
- package/dist/integrations/incidentio/default-rules.js +1 -2
- package/dist/integrations/incidentio/intake.js +1 -2
- package/dist/integrations/incidentio/integration.js +1 -2
- package/dist/integrations/incidentio/issue-reconciler.js +1 -2
- package/dist/integrations/incidentio/reconciliation-config.js +1 -2
- package/dist/integrations/incidentio/routes.js +1 -2
- package/dist/integrations/incidentio/rules.js +1 -2
- package/dist/integrations/issue-reconcile-worker.js +1 -2
- package/dist/integrations/issue-reconciler.js +1 -2
- package/dist/integrations/jira/adf.js +1 -2
- package/dist/integrations/jira/agent-tools.js +1 -2
- package/dist/integrations/jira/api.d.ts +1 -1
- package/dist/integrations/jira/api.d.ts.map +1 -1
- package/dist/integrations/jira/api.js +2 -3
- package/dist/integrations/jira/api.js.map +1 -1
- package/dist/integrations/jira/claim.js +1 -2
- package/dist/integrations/jira/default-rules.js +1 -2
- package/dist/integrations/jira/integration.d.ts +3 -1
- package/dist/integrations/jira/integration.d.ts.map +1 -1
- package/dist/integrations/jira/integration.js +18 -4
- package/dist/integrations/jira/integration.js.map +1 -1
- package/dist/integrations/jira/issue-reconciler.js +1 -2
- package/dist/integrations/jira/reconciliation-config.js +1 -2
- package/dist/integrations/jira/routes.js +1 -2
- package/dist/integrations/jira/rules.js +1 -2
- package/dist/integrations/linear/agent-tools.d.ts +1 -1
- package/dist/integrations/linear/agent-tools.d.ts.map +1 -1
- package/dist/integrations/linear/agent-tools.js +5 -5
- package/dist/integrations/linear/agent-tools.js.map +1 -1
- package/dist/integrations/linear/claim.js +1 -2
- package/dist/integrations/linear/default-rules.js +1 -2
- package/dist/integrations/linear/integration.d.ts +2 -0
- package/dist/integrations/linear/integration.d.ts.map +1 -1
- package/dist/integrations/linear/integration.js +2 -2
- package/dist/integrations/linear/integration.js.map +1 -1
- package/dist/integrations/linear/issue-reconciler.js +1 -2
- package/dist/integrations/linear/reconciliation-config.js +1 -2
- package/dist/integrations/linear/routes.js +1 -2
- package/dist/integrations/linear/rules.js +1 -2
- package/dist/integrations/platform/api-client.js +1 -2
- package/dist/integrations/platform/connect/routes.js +1 -2
- package/dist/integrations/platform/github/event-worker.js +6 -2
- package/dist/integrations/platform/github/event-worker.js.map +1 -1
- package/dist/integrations/platform/github/integration.js +1 -2
- package/dist/integrations/platform/gitlab/event-worker.js +1 -2
- package/dist/integrations/platform/gitlab/integration.js +1 -2
- package/dist/integrations/platform/incidentio/integration.js +1 -2
- package/dist/integrations/platform/jira/agent-tools.js +1 -2
- package/dist/integrations/platform/jira/integration.js +1 -2
- package/dist/integrations/platform/jira/routes.js +1 -2
- package/dist/integrations/platform/linear/event-worker.js +1 -2
- package/dist/integrations/platform/linear/integration.d.ts.map +1 -1
- package/dist/integrations/platform/linear/integration.js +2 -2
- package/dist/integrations/platform/linear/integration.js.map +1 -1
- package/dist/integrations/pull-request-head.d.ts +1 -0
- package/dist/integrations/pull-request-head.d.ts.map +1 -1
- package/dist/integrations/pull-request-head.js +3 -3
- package/dist/integrations/pull-request-head.js.map +1 -1
- package/dist/integrations/reconciliation-config.js +1 -2
- package/dist/integrations/slack/channel-reply-processor.d.ts +1 -0
- package/dist/integrations/slack/channel-reply-processor.d.ts.map +1 -1
- package/dist/integrations/slack/channel-reply-processor.js +16 -6
- package/dist/integrations/slack/channel-reply-processor.js.map +1 -1
- package/dist/integrations/slack/channel-session-link-processor.d.ts +1 -0
- package/dist/integrations/slack/channel-session-link-processor.d.ts.map +1 -1
- package/dist/integrations/slack/channel-session-link-processor.js +2 -3
- package/dist/integrations/slack/channel-session-link-processor.js.map +1 -1
- package/dist/integrations/slack/connect-route.js +1 -2
- package/dist/integrations/slack/emoji-shortcodes.generated.js +1 -2
- package/dist/integrations/slack/emoji.js +1 -2
- package/dist/integrations/slack/feed-publisher.js +1 -2
- package/dist/integrations/slack/integration.d.ts +5 -0
- package/dist/integrations/slack/integration.d.ts.map +1 -1
- package/dist/integrations/slack/integration.js +13 -2
- package/dist/integrations/slack/integration.js.map +1 -1
- package/dist/integrations/slack/reply-reminder-processor.js +1 -2
- package/dist/integrations/slack/reply-tool.d.ts.map +1 -1
- package/dist/integrations/slack/reply-tool.js +4 -13
- package/dist/integrations/slack/reply-tool.js.map +1 -1
- package/dist/integrations/slack/run-error-card.d.ts +3 -0
- package/dist/integrations/slack/run-error-card.d.ts.map +1 -0
- package/dist/integrations/slack/run-error-card.js +44 -0
- package/dist/integrations/slack/run-error-card.js.map +1 -0
- package/dist/integrations/slack/share-file-tool.js +1 -2
- package/dist/integrations/slack/slack.d.ts.map +1 -1
- package/dist/integrations/slack/slack.js +7 -4
- package/dist/integrations/slack/slack.js.map +1 -1
- package/dist/integrations/subscription-session.js +1 -2
- package/dist/integrations/workos/integration.js +1 -2
- package/dist/mcp/disconnect.js +1 -2
- package/dist/mcp/events.js +2 -3
- package/dist/mcp/routes.js +1 -2
- package/dist/packages/_internals/workspace/dist/index.js +1 -2
- package/dist/packages/_internals/workspace/dist/index.js.map +1 -1
- package/dist/platform-auth-host.js +1 -2
- package/dist/provider-display-name.js +1 -2
- package/dist/review-verdict.d.ts +1 -0
- package/dist/review-verdict.d.ts.map +1 -1
- package/dist/review-verdict.js +9 -3
- package/dist/review-verdict.js.map +1 -1
- package/dist/routes/attention-activity.js +1 -2
- package/dist/routes/attention-parked.js +1 -2
- package/dist/routes/attention-proposed.js +1 -2
- package/dist/routes/attention-providers.js +1 -2
- package/dist/routes/attention.js +1 -2
- package/dist/routes/automation-runs.js +1 -2
- package/dist/routes/config.d.ts +7 -0
- package/dist/routes/config.d.ts.map +1 -1
- package/dist/routes/config.js +29 -3
- package/dist/routes/config.js.map +1 -1
- package/dist/routes/contracts.js +1 -2
- package/dist/routes/custom-provider-source.js +1 -2
- package/dist/routes/fs.js +1 -2
- package/dist/routes/intake.js +6 -4
- package/dist/routes/intake.js.map +1 -1
- package/dist/routes/knowledge.js +1 -2
- package/dist/routes/oauth.js +1 -2
- package/dist/routes/projects.js +1 -2
- package/dist/routes/provider-credentials.js +1 -2
- package/dist/routes/route.js +1 -2
- package/dist/routes/session-access.js +1 -2
- package/dist/routes/skills.js +1 -2
- package/dist/routes/source-control-sessions.js +5 -6
- package/dist/routes/source-control-settings.js +1 -2
- package/dist/routes/surface.js +3 -4
- package/dist/routes/surface.js.map +1 -1
- package/dist/routes/telemetry.js +1 -2
- package/dist/routes/tenant-credentials.js +1 -2
- package/dist/routes/work-items.js +2 -3
- package/dist/rules/binding-context.js +1 -2
- package/dist/rules/decision-applicability.js +1 -2
- package/dist/rules/dispatch-errors.js +1 -2
- package/dist/rules/dispatcher.d.ts.map +1 -1
- package/dist/rules/dispatcher.js +9 -3
- package/dist/rules/dispatcher.js.map +1 -1
- package/dist/rules/event-rules.js +1 -2
- package/dist/rules/processor.js +1 -2
- package/dist/rules/resolve.js +1 -2
- package/dist/rules/review-source-tool.js +1 -2
- package/dist/rules/start-coordinator.js +1 -2
- package/dist/rules/terminal-cleanup.js +1 -2
- package/dist/rules/tools.js +1 -2
- package/dist/rules/transition-service.js +1 -2
- package/dist/rules/types.d.ts +4 -1
- package/dist/rules/types.d.ts.map +1 -1
- package/dist/rules/types.js +1 -2
- package/dist/rules/types.js.map +1 -1
- package/dist/rules/validation.js +1 -2
- package/dist/run-error.d.ts +13 -0
- package/dist/run-error.d.ts.map +1 -0
- package/dist/run-error.js +81 -0
- package/dist/run-error.js.map +1 -0
- package/dist/sandbox/callback-factory-sandbox.js +1 -2
- package/dist/sandbox/git-ref.js +1 -2
- package/dist/sandbox/local-factory-sandbox.d.ts +12 -4
- package/dist/sandbox/local-factory-sandbox.d.ts.map +1 -1
- package/dist/sandbox/local-factory-sandbox.js +32 -7
- package/dist/sandbox/local-factory-sandbox.js.map +1 -1
- package/dist/sandbox/materialization.js +1 -2
- package/dist/sandbox/session-retirement.js +1 -2
- package/dist/sandbox/session-sandbox.js +1 -2
- package/dist/sandbox/workdir.js +1 -2
- package/dist/secret-encryption.js +1 -2
- package/dist/server-error.js +1 -2
- package/dist/session/credential-policy.js +1 -2
- package/dist/session/default-model-hydration.js +1 -2
- package/dist/session/environment-repositories.js +1 -2
- package/dist/session/environment-state-processor.d.ts +0 -1
- package/dist/session/environment-state-processor.d.ts.map +1 -1
- package/dist/session/environment-state-processor.js +2 -3
- package/dist/session/environment-state-processor.js.map +1 -1
- package/dist/session/factory-session.js +1 -2
- package/dist/session/filesystem-capture.js +2 -3
- package/dist/session/filesystem-capture.js.map +1 -1
- package/dist/session/first-exec-capture.js +2 -3
- package/dist/session/first-exec-capture.js.map +1 -1
- package/dist/session/first-message-capture.js +1 -2
- package/dist/session/live-sessions.js +1 -2
- package/dist/session/memory-settings-hydration.js +1 -2
- package/dist/session/org-seed.js +1 -2
- package/dist/session/reply-credential-processor.js +1 -2
- package/dist/session/resource-migration.js +1 -2
- package/dist/session/run-audit.js +1 -2
- package/dist/session/session-threads.js +1 -2
- package/dist/session/session-title.js +1 -2
- package/dist/session/shell-commands.js +1 -2
- package/dist/session/source-control-tools.js +2 -3
- package/dist/session/thinking-default.d.ts +1 -1
- package/dist/session/thinking-default.d.ts.map +1 -1
- package/dist/session/thinking-default.js +11 -13
- package/dist/session/thinking-default.js.map +1 -1
- package/dist/session/thread-session-stamp.js +1 -2
- package/dist/session/thread-title-mirror.js +1 -2
- package/dist/session/thread-title-mirror.js.map +1 -1
- package/dist/session/work-item-repository.js +1 -2
- package/dist/session-owner-signal.js +1 -2
- package/dist/skills/catalog.js +1 -2
- package/dist/skills/service.js +1 -2
- package/dist/spa-static.js +1 -2
- package/dist/state-signing.js +1 -2
- package/dist/storage/domains/audit/actions.js +1 -2
- package/dist/storage/domains/audit/actors.js +1 -2
- package/dist/storage/domains/audit/agent-audit.js +1 -2
- package/dist/storage/domains/audit/base.js +1 -2
- package/dist/storage/domains/audit/domain.js +1 -2
- package/dist/storage/domains/audit/wire.js +1 -2
- package/dist/storage/domains/channel-identity/base.js +1 -2
- package/dist/storage/domains/comments/activity.js +1 -2
- package/dist/storage/domains/comments/actor.js +1 -2
- package/dist/storage/domains/comments/base.js +1 -2
- package/dist/storage/domains/comments/domain.js +1 -2
- package/dist/storage/domains/comments/feed-context.js +1 -2
- package/dist/storage/domains/comments/parse.js +1 -2
- package/dist/storage/domains/comments/routes.js +1 -2
- package/dist/storage/domains/comments/schema.js +1 -2
- package/dist/storage/domains/comments/wire.js +1 -2
- package/dist/storage/domains/credentials/base.d.ts +4 -1
- package/dist/storage/domains/credentials/base.d.ts.map +1 -1
- package/dist/storage/domains/credentials/base.js +40 -44
- package/dist/storage/domains/credentials/base.js.map +1 -1
- package/dist/storage/domains/custom-providers/base.js +1 -2
- package/dist/storage/domains/filesystem/base.js +1 -2
- package/dist/storage/domains/intake/base.d.ts +5 -0
- package/dist/storage/domains/intake/base.d.ts.map +1 -1
- package/dist/storage/domains/intake/base.js +10 -2
- package/dist/storage/domains/intake/base.js.map +1 -1
- package/dist/storage/domains/integrations/base.js +1 -2
- package/dist/storage/domains/memory-settings/base.js +1 -2
- package/dist/storage/domains/model-defaults/base.js +1 -2
- package/dist/storage/domains/projects/base.d.ts +0 -1
- package/dist/storage/domains/projects/base.d.ts.map +1 -1
- package/dist/storage/domains/projects/base.js +5 -6
- package/dist/storage/domains/projects/base.js.map +1 -1
- package/dist/storage/domains/queue-health/base.js +1 -2
- package/dist/storage/domains/source-control/base.js +1 -2
- package/dist/storage/domains/source-control/inmemory.js +1 -2
- package/dist/storage/domains/work-items/base.js +1 -2
- package/dist/storage/domains/work-items/board-version.js +1 -2
- package/dist/storage/domains/work-items/metrics.js +1 -2
- package/dist/telemetry-types.js +1 -2
- package/dist/telemetry.js +1 -2
- package/dist/timing.js +1 -2
- package/dist/tools/annotations.js +1 -2
- package/dist/tools/approval-tools.js +1 -2
- package/dist/tools/deliver.js +2 -3
- package/dist/tools/index.js +1 -2
- package/dist/tools/messaging-tools.js +1 -2
- package/dist/tools/permissions.js +1 -2
- package/dist/tools/read-tools.js +1 -2
- package/dist/tools/reports.js +1 -2
- package/dist/tools/run-watch.d.ts +0 -2
- package/dist/tools/run-watch.d.ts.map +1 -1
- package/dist/tools/run-watch.js +4 -44
- package/dist/tools/run-watch.js.map +1 -1
- package/dist/tools/sandbox-tools.js +1 -2
- package/dist/tools/scope.js +2 -3
- package/dist/tools/session-tools.js +1 -2
- package/dist/tools/sessions-state-processor.js +1 -2
- package/dist/tools/side-sessions.js +1 -2
- package/dist/tools/work-item-tools.js +1 -2
- package/dist/work-item-branch.js +1 -2
- package/dist/work-item-branch.js.map +1 -1
- package/dist/work-items/create-work-item.js +1 -2
- package/dist/work-items/decision-actions.js +1 -2
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +1 -3
- package/dist/workspace.js.map +1 -1
- package/factory-skills/factory-gitlab-review/SKILL.md +1 -1
- package/factory-skills/factory-plan/SKILL.md +1 -1
- package/factory-skills/factory-rereview/SKILL.md +14 -3
- package/factory-skills/factory-review/SKILL.md +14 -3
- package/factory-skills/factory-self-review/SKILL.md +1 -1
- package/factory-skills/factory-triage/SKILL.md +52 -29
- package/package.json +19 -17
|
@@ -4,7 +4,7 @@ import "../../boards/index.js";
|
|
|
4
4
|
import { linearClaimKey } from "./claim.js";
|
|
5
5
|
import { LinearReauthRequiredError } from "./integration.js";
|
|
6
6
|
import { registerApiRoute } from "@mastra/core/server";
|
|
7
|
-
|
|
7
|
+
// src/integrations/linear/routes.ts
|
|
8
8
|
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
9
9
|
/** Erase a route handler's path-parameterized context to a plain `Context`. */
|
|
10
10
|
function loose(c) {
|
|
@@ -374,7 +374,6 @@ function buildLinearRoutes(options) {
|
|
|
374
374
|
}));
|
|
375
375
|
return routes;
|
|
376
376
|
}
|
|
377
|
-
//#endregion
|
|
378
377
|
export { buildLinearRoutes };
|
|
379
378
|
|
|
380
379
|
//# sourceMappingURL=routes.js.map
|
|
@@ -3,7 +3,7 @@ import { boardEventHandlers, boardForWorkItem, eventBoardId, isTerminalWorkItem,
|
|
|
3
3
|
import "../../boards/index.js";
|
|
4
4
|
import { selectEventRule } from "../../rules/event-rules.js";
|
|
5
5
|
import { linearClaimKey } from "./claim.js";
|
|
6
|
-
|
|
6
|
+
// src/integrations/linear/rules.ts
|
|
7
7
|
const RULE_TIMEOUT_MS = 5e3;
|
|
8
8
|
async function withRuleTimeout(promise) {
|
|
9
9
|
let timeout;
|
|
@@ -183,7 +183,6 @@ function attachLinearRules(linear, context) {
|
|
|
183
183
|
});
|
|
184
184
|
return (input) => rules.ingest(input);
|
|
185
185
|
}
|
|
186
|
-
//#endregion
|
|
187
186
|
export { LinearRules, attachLinearRules };
|
|
188
187
|
|
|
189
188
|
//# sourceMappingURL=rules.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/integrations/platform/api-client.ts
|
|
2
2
|
const DEFAULT_INTEGRATIONS_URL = "https://integrations.mastra.ai";
|
|
3
3
|
const REGIONAL_INTEGRATIONS_URLS = {
|
|
4
4
|
us: "https://integrations.us.mastra.ai",
|
|
@@ -176,7 +176,6 @@ function parseRetryAfter(value) {
|
|
|
176
176
|
const seconds = Number.parseInt(value, 10);
|
|
177
177
|
return Number.isSafeInteger(seconds) && seconds >= 0 ? seconds : null;
|
|
178
178
|
}
|
|
179
|
-
//#endregion
|
|
180
179
|
export { PlatformApiClient, PlatformApiError, logPlatformError, logPlatformInfo, logPlatformWarn, platformApiClientConfigFromEnv };
|
|
181
180
|
|
|
182
181
|
//# sourceMappingURL=api-client.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PlatformApiError } from "../api-client.js";
|
|
2
2
|
import { registerApiRoute } from "@mastra/core/server";
|
|
3
|
-
|
|
3
|
+
// src/integrations/platform/connect/routes.ts
|
|
4
4
|
/** Erase a route handler's path-parameterized context to a plain `Context`. */
|
|
5
5
|
function loose(c) {
|
|
6
6
|
return c;
|
|
@@ -127,7 +127,6 @@ function buildPlatformConnectRoutes(options) {
|
|
|
127
127
|
})
|
|
128
128
|
];
|
|
129
129
|
}
|
|
130
|
-
//#endregion
|
|
131
130
|
export { PLATFORM_CONNECT_PROVIDERS, buildPlatformConnectRoutes };
|
|
132
131
|
|
|
133
132
|
//# sourceMappingURL=routes.js.map
|
|
@@ -3,7 +3,7 @@ import { PlatformApiError } from "../api-client.js";
|
|
|
3
3
|
import { dispatchGithubWebhook, isFactoryAppSender, resolveAuthorizedBots } from "../../github/webhook.js";
|
|
4
4
|
import { NoopLeaseProvider, isLeaseProvider } from "@mastra/core/events";
|
|
5
5
|
import { MastraWorker } from "@mastra/core/worker";
|
|
6
|
-
|
|
6
|
+
// src/integrations/platform/github/event-worker.ts
|
|
7
7
|
const API_PREFIX = "/v1/server/github-app";
|
|
8
8
|
const DEFAULT_POLL_INTERVAL_MS = 2e4;
|
|
9
9
|
const DEFAULT_RECONCILE_INTERVAL_MS = 36e5;
|
|
@@ -428,6 +428,11 @@ function isFactoryIngestedEvent(event) {
|
|
|
428
428
|
if (event.event === "issues" && ISSUE_INGESTED_ACTIONS.has(String(event.payload.action))) return true;
|
|
429
429
|
if (event.event === "pull_request_review" && event.payload.action === "submitted") return true;
|
|
430
430
|
if (event.event === "issue_comment" && event.payload.action === "created") return true;
|
|
431
|
+
if (event.event === "pull_request_review" && event.payload.action === "edited") return true;
|
|
432
|
+
if (event.event === "issue_comment" && event.payload.action === "edited") {
|
|
433
|
+
const issue = event.payload.issue;
|
|
434
|
+
if (issue && typeof issue === "object" && "pull_request" in issue && issue.pull_request) return true;
|
|
435
|
+
}
|
|
431
436
|
if (event.event === "push") return true;
|
|
432
437
|
return false;
|
|
433
438
|
}
|
|
@@ -443,7 +448,6 @@ function retryDelay(error, fallbackMs) {
|
|
|
443
448
|
if (error instanceof PlatformApiError && error.status === 429 && error.retryAfterSeconds !== null) return Math.max(fallbackMs, error.retryAfterSeconds * 1e3);
|
|
444
449
|
return fallbackMs;
|
|
445
450
|
}
|
|
446
|
-
//#endregion
|
|
447
451
|
export { PlatformGithubEventWorker };
|
|
448
452
|
|
|
449
453
|
//# sourceMappingURL=event-worker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-worker.js","names":[],"sources":["../../../../src/integrations/platform/github/event-worker.ts"],"sourcesContent":["import 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 { GithubReconcileRepositorySource } from '../../github/reconcile-worker.js';\nimport type { GithubPullRequestReconciler, ReconcileRepository } from '../../github/rules.js';\nimport { listPullRequestSubscriptionsForWebhook, retirePullRequestSubscription } from '../../github/subscriptions.js';\nimport { dispatchGithubWebhook, isFactoryAppSender, resolveAuthorizedBots } 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;\n// Event polling is the primary sync; the sweeps only catch drift (missed\n// events, cards ingested before polling was linked), so they run hourly.\nconst DEFAULT_RECONCILE_INTERVAL_MS = 60 * 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 // Pushes never reach the subscription dispatcher; they feed the factory\n // ingest path so base checkpoints rebuild on default-branch updates.\n 'push',\n]);\n// Kinds emitted by `classifyGithubWebhook` that carry untrusted sender-authored\n// content and must pass the sender authorization gate below.\nconst AUTHOR_GATED_KINDS = new Set([\n 'issue-comment-created',\n 'review-comment-created',\n 'review-approved',\n 'review-changes-requested',\n 'review-submitted',\n 'review-dismissed',\n]);\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 /**\n * Source-control storage used to resolve the set of repositories the worker\n * should poll. The worker restricts itself to `(installation, repository)`\n * pairs linked to a factory project — the same set the reconciler uses —\n * so polling scales with Factory usage, not with the size of the underlying\n * GitHub org.\n */\n sourceControl: GithubReconcileRepositorySource;\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 #sourceControl: GithubReconcileRepositorySource;\n readonly #leaseOwner = globalThis.crypto.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 // Negative infinity so the first tick always sweeps, whatever the clock reads.\n #lastPullRequestReconcileAt = Number.NEGATIVE_INFINITY;\n #lastIssueReconcileAt = Number.NEGATIVE_INFINITY;\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 this.#sourceControl = config.sourceControl;\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', {\n ...context,\n errors,\n });\n } else if (counts.created > 0) {\n this.deps?.logger.info('Platform GitHub issue reconcile replayed missed opens', context);\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 /**\n * Configured `(installation, repository)` pairs — the same set the\n * reconciler sweeps — resolved to the numeric ids and slug the poll\n * addresses GitHub with. Repositories not linked to any factory project\n * cannot produce work for Factory, so polling and reconciling them is\n * wasted `/events` bandwidth and platform load.\n */\n async #discoverRepositories(): Promise<Repository[]> {\n const keys = await this.#sourceControl.projectRepositories.listConfiguredExternalKeys();\n const repositories = new Map<number, Repository>();\n for (const key of keys) {\n const installationId = Number(key.installationExternalId);\n const repositoryId = Number(key.repositoryExternalId);\n if (\n !Number.isSafeInteger(installationId) ||\n installationId <= 0 ||\n !Number.isSafeInteger(repositoryId) ||\n repositoryId <= 0\n ) {\n continue;\n }\n if (repositories.has(repositoryId)) continue;\n // A configured key exists per project link, so `listByExternalRepository`\n // always yields at least one row; the first row's orgId is enough to\n // look up the repository row for its slug.\n const projects = await this.#sourceControl.projectRepositories.listByExternalRepository(key);\n const orgId = projects[0]?.orgId;\n const repository = orgId\n ? await this.#sourceControl.repositories.findByExternalId({ orgId, externalId: key.repositoryExternalId })\n : null;\n repositories.set(repositoryId, {\n id: repositoryId,\n installationId,\n fullName: repository?.slug,\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 } else {\n this.deps?.logger.debug('Platform GitHub event not forwarded to Factory ingress', {\n repositoryId,\n deliveryId: parsed.deliveryId,\n event: parsed.event,\n action: parsed.payload.action,\n });\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 onTargetSkipped: subscription => {\n // Routine when a subscription's thread belongs to another\n // deployment, so this stays at debug rather than warning on a loop.\n this.deps?.logger.debug('Platform GitHub event skipped: thread is not held here', {\n deliveryId: event.deliveryId,\n subscriptionId: subscription.id,\n threadId: subscription.threadId,\n });\n },\n onSenderRejected: notification => {\n this.deps?.logger.debug('Platform GitHub event dropped: sender not authorized', {\n deliveryId: event.deliveryId,\n repository: notification.metadata.repository,\n sender: notification.metadata.sender,\n kind: notification.kind,\n });\n },\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 // Factory's own app has to clear the gate before the bot rules below, which\n // fail closed for every bot that is not explicitly allowlisted. GitHub\n // forbids an app from reviewing its own pull request, so `factory-review`\n // posts its verdict as a comment under this login and that comment is the\n // handoff the authoring agent wakes on.\n if (this.#github.identity?.matches(sender)) return true;\n if (isFactoryAppSender(sender, this.#github.slug)) return true;\n const normalizedSender = sender.toLowerCase();\n const authorizedBots = resolveAuthorizedBots(this.#github.authorizedBots);\n if (authorizedBots.has(normalizedSender)) return true;\n // Any other bot is gated purely by the allowlist: a GitHub App never holds a\n // collaborator permission under its sender login, so falling through to the\n // permission lookup would only fail closed after a wasted API call.\n if (notification.metadata.senderType?.toLowerCase() === 'bot' || normalizedSender.endsWith('[bot]')) {\n return false;\n }\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 triggers the review board's re-review path listens for;\n// submitted reviews and pull request comments are how review feedback reaches\n// the agent that authored the branch. Direct-webhook consumers ingest every\n// parsed event; the platform path gates because the remaining events (issue\n// edits, comment edits and deletions) only interest the subscription\n// dispatcher, not the factory rules.\nconst ISSUE_INGESTED_ACTIONS = new Set(['opened', 'reopened', 'edited', 'labeled', 'unlabeled']);\n\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 // `opened` is what mints the Review card for a pull request. Without it a\n // factory-authored PR never gets reviewed on the polling path, which is the\n // only path a local deployment has.\n if (action === 'opened' || action === 'synchronize' || action === 'review_requested') return true;\n }\n // Issue opens, reopens, edits and label changes mint and update Work cards.\n // Without them a new issue never becomes a card on the polling path (#24972).\n if (event.event === 'issues' && ISSUE_INGESTED_ACTIONS.has(String(event.payload.action))) return true;\n if (event.event === 'pull_request_review' && event.payload.action === 'submitted') return true;\n if (event.event === 'issue_comment' && event.payload.action === 'created') return true;\n // Default-branch pushes drive base-checkpoint rebuilds\n // (`withBaseCheckpointWebhookTrigger` wraps the ingest callback).\n if (event.event === 'push') return true;\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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"}
|
|
1
|
+
{"version":3,"file":"event-worker.js","names":[],"sources":["../../../../src/integrations/platform/github/event-worker.ts"],"sourcesContent":["import 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 { GithubReconcileRepositorySource } from '../../github/reconcile-worker.js';\nimport type { GithubPullRequestReconciler, ReconcileRepository } from '../../github/rules.js';\nimport { listPullRequestSubscriptionsForWebhook, retirePullRequestSubscription } from '../../github/subscriptions.js';\nimport { dispatchGithubWebhook, isFactoryAppSender, resolveAuthorizedBots } 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;\n// Event polling is the primary sync; the sweeps only catch drift (missed\n// events, cards ingested before polling was linked), so they run hourly.\nconst DEFAULT_RECONCILE_INTERVAL_MS = 60 * 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 // Pushes never reach the subscription dispatcher; they feed the factory\n // ingest path so base checkpoints rebuild on default-branch updates.\n 'push',\n]);\n// Kinds emitted by `classifyGithubWebhook` that carry untrusted sender-authored\n// content and must pass the sender authorization gate below.\nconst AUTHOR_GATED_KINDS = new Set([\n 'issue-comment-created',\n 'review-comment-created',\n 'review-approved',\n 'review-changes-requested',\n 'review-submitted',\n 'review-dismissed',\n]);\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 /**\n * Source-control storage used to resolve the set of repositories the worker\n * should poll. The worker restricts itself to `(installation, repository)`\n * pairs linked to a factory project — the same set the reconciler uses —\n * so polling scales with Factory usage, not with the size of the underlying\n * GitHub org.\n */\n sourceControl: GithubReconcileRepositorySource;\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 #sourceControl: GithubReconcileRepositorySource;\n readonly #leaseOwner = globalThis.crypto.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 // Negative infinity so the first tick always sweeps, whatever the clock reads.\n #lastPullRequestReconcileAt = Number.NEGATIVE_INFINITY;\n #lastIssueReconcileAt = Number.NEGATIVE_INFINITY;\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 this.#sourceControl = config.sourceControl;\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', {\n ...context,\n errors,\n });\n } else if (counts.created > 0) {\n this.deps?.logger.info('Platform GitHub issue reconcile replayed missed opens', context);\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 /**\n * Configured `(installation, repository)` pairs — the same set the\n * reconciler sweeps — resolved to the numeric ids and slug the poll\n * addresses GitHub with. Repositories not linked to any factory project\n * cannot produce work for Factory, so polling and reconciling them is\n * wasted `/events` bandwidth and platform load.\n */\n async #discoverRepositories(): Promise<Repository[]> {\n const keys = await this.#sourceControl.projectRepositories.listConfiguredExternalKeys();\n const repositories = new Map<number, Repository>();\n for (const key of keys) {\n const installationId = Number(key.installationExternalId);\n const repositoryId = Number(key.repositoryExternalId);\n if (\n !Number.isSafeInteger(installationId) ||\n installationId <= 0 ||\n !Number.isSafeInteger(repositoryId) ||\n repositoryId <= 0\n ) {\n continue;\n }\n if (repositories.has(repositoryId)) continue;\n // A configured key exists per project link, so `listByExternalRepository`\n // always yields at least one row; the first row's orgId is enough to\n // look up the repository row for its slug.\n const projects = await this.#sourceControl.projectRepositories.listByExternalRepository(key);\n const orgId = projects[0]?.orgId;\n const repository = orgId\n ? await this.#sourceControl.repositories.findByExternalId({ orgId, externalId: key.repositoryExternalId })\n : null;\n repositories.set(repositoryId, {\n id: repositoryId,\n installationId,\n fullName: repository?.slug,\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 } else {\n this.deps?.logger.debug('Platform GitHub event not forwarded to Factory ingress', {\n repositoryId,\n deliveryId: parsed.deliveryId,\n event: parsed.event,\n action: parsed.payload.action,\n });\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 onTargetSkipped: subscription => {\n // Routine when a subscription's thread belongs to another\n // deployment, so this stays at debug rather than warning on a loop.\n this.deps?.logger.debug('Platform GitHub event skipped: thread is not held here', {\n deliveryId: event.deliveryId,\n subscriptionId: subscription.id,\n threadId: subscription.threadId,\n });\n },\n onSenderRejected: notification => {\n this.deps?.logger.debug('Platform GitHub event dropped: sender not authorized', {\n deliveryId: event.deliveryId,\n repository: notification.metadata.repository,\n sender: notification.metadata.sender,\n kind: notification.kind,\n });\n },\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 // Factory's own app has to clear the gate before the bot rules below, which\n // fail closed for every bot that is not explicitly allowlisted. GitHub\n // forbids an app from reviewing its own pull request, so `factory-review`\n // posts its verdict as a comment under this login and that comment is the\n // handoff the authoring agent wakes on.\n if (this.#github.identity?.matches(sender)) return true;\n if (isFactoryAppSender(sender, this.#github.slug)) return true;\n const normalizedSender = sender.toLowerCase();\n const authorizedBots = resolveAuthorizedBots(this.#github.authorizedBots);\n if (authorizedBots.has(normalizedSender)) return true;\n // Any other bot is gated purely by the allowlist: a GitHub App never holds a\n // collaborator permission under its sender login, so falling through to the\n // permission lookup would only fail closed after a wasted API call.\n if (notification.metadata.senderType?.toLowerCase() === 'bot' || normalizedSender.endsWith('[bot]')) {\n return false;\n }\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 triggers the review board's re-review path listens for;\n// submitted reviews and pull request comments are how review feedback reaches\n// the agent that authored the branch. Direct-webhook consumers ingest every\n// parsed event; the platform path gates because the remaining events (issue\n// edits, comment edits and deletions) only interest the subscription\n// dispatcher, not the factory rules.\nconst ISSUE_INGESTED_ACTIONS = new Set(['opened', 'reopened', 'edited', 'labeled', 'unlabeled']);\n\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 // `opened` is what mints the Review card for a pull request. Without it a\n // factory-authored PR never gets reviewed on the polling path, which is the\n // only path a local deployment has.\n if (action === 'opened' || action === 'synchronize' || action === 'review_requested') return true;\n }\n // Issue opens, reopens, edits and label changes mint and update Work cards.\n // Without them a new issue never becomes a card on the polling path (#24972).\n if (event.event === 'issues' && ISSUE_INGESTED_ACTIONS.has(String(event.payload.action))) return true;\n if (event.event === 'pull_request_review' && event.payload.action === 'submitted') return true;\n if (event.event === 'issue_comment' && event.payload.action === 'created') return true;\n // `factory-review` edits its earlier verdict in place on a re-review. The rules\n // engine only acts on edits that leave a request-changes verdict behind.\n if (event.event === 'pull_request_review' && event.payload.action === 'edited') return true;\n if (event.event === 'issue_comment' && event.payload.action === 'edited') {\n const issue = event.payload.issue;\n if (issue && typeof issue === 'object' && 'pull_request' in issue && issue.pull_request) return true;\n }\n // Default-branch pushes drive base-checkpoint rebuilds\n // (`withBaseCheckpointWebhookTrigger` wraps the ingest callback).\n if (event.event === 'push') return true;\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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"}
|
|
@@ -11,7 +11,7 @@ import { settleOrAbort } from "../../github/settle-or-abort.js";
|
|
|
11
11
|
import { PlatformGithubEventWorker } from "./event-worker.js";
|
|
12
12
|
import { registerApiRoute } from "@mastra/core/server";
|
|
13
13
|
import { Octokit } from "@octokit/rest";
|
|
14
|
-
|
|
14
|
+
// src/integrations/platform/github/integration.ts
|
|
15
15
|
const PAGE_SIZE = 30;
|
|
16
16
|
const OPEN_ISSUE_DISCOVERY_MAX_PAGES = 5;
|
|
17
17
|
const API_PREFIX = "/v1/server";
|
|
@@ -1291,7 +1291,6 @@ function isNotFound(error) {
|
|
|
1291
1291
|
function isDeadInstallation(error) {
|
|
1292
1292
|
return error instanceof PlatformApiError && (error.status === 404 || error.status === 409);
|
|
1293
1293
|
}
|
|
1294
|
-
//#endregion
|
|
1295
1294
|
export { PlatformGithubIntegration };
|
|
1296
1295
|
|
|
1297
1296
|
//# sourceMappingURL=integration.js.map
|
|
@@ -2,7 +2,7 @@ import { PlatformApiError } from "../api-client.js";
|
|
|
2
2
|
import { parseGitLabWebhookBody, processGitLabWebhook } from "../../gitlab/webhook.js";
|
|
3
3
|
import { NoopLeaseProvider, isLeaseProvider } from "@mastra/core/events";
|
|
4
4
|
import { MastraWorker } from "@mastra/core/worker";
|
|
5
|
-
|
|
5
|
+
// src/integrations/platform/gitlab/event-worker.ts
|
|
6
6
|
const DEFAULT_POLL_INTERVAL_MS = 2e4;
|
|
7
7
|
const EVENT_PAGE_SIZE = 500;
|
|
8
8
|
/**
|
|
@@ -299,7 +299,6 @@ function retryDelay(error, fallbackMs) {
|
|
|
299
299
|
if (error instanceof PlatformApiError && error.status === 429 && error.retryAfterSeconds !== null) return Math.max(fallbackMs, error.retryAfterSeconds * 1e3);
|
|
300
300
|
return fallbackMs;
|
|
301
301
|
}
|
|
302
|
-
//#endregion
|
|
303
302
|
export { PlatformGitLabEventWorker };
|
|
304
303
|
|
|
305
304
|
//# sourceMappingURL=event-worker.js.map
|
|
@@ -3,7 +3,7 @@ import { GitLabApiClient, GitLabApiError } from "../../gitlab/api.js";
|
|
|
3
3
|
import { attachGitLabRules } from "../../gitlab/rules.js";
|
|
4
4
|
import { GitLabIntegrationBase, gitlabConnection } from "../../gitlab/integration.js";
|
|
5
5
|
import { PlatformGitLabEventWorker } from "./event-worker.js";
|
|
6
|
-
|
|
6
|
+
// src/integrations/platform/gitlab/integration.ts
|
|
7
7
|
/** The Platform's GitLab (OAuth) integration. It is the only GitLab credential flow Factory discovers. */
|
|
8
8
|
const GITLAB_INTEGRATION_ID = "gitlab";
|
|
9
9
|
var PlatformGitLabIntegration = class extends GitLabIntegrationBase {
|
|
@@ -107,7 +107,6 @@ function optionalPositiveIntegerEnv(name) {
|
|
|
107
107
|
if (!/^[1-9]\d*$/.test(value) || !Number.isSafeInteger(parsed)) throw new Error(`${name} must be a positive integer.`);
|
|
108
108
|
return parsed;
|
|
109
109
|
}
|
|
110
|
-
//#endregion
|
|
111
110
|
export { PlatformGitLabIntegration };
|
|
112
111
|
|
|
113
112
|
//# sourceMappingURL=integration.js.map
|
|
@@ -8,7 +8,7 @@ import { INCIDENTIO_FOLLOW_UPS_SOURCE_ID, INCIDENTIO_INCIDENTS_SOURCE_ID, create
|
|
|
8
8
|
import { attachIncidentioRules } from "../../incidentio/rules.js";
|
|
9
9
|
import { attachIncidentioIssueReconciler } from "../../incidentio/issue-reconciler.js";
|
|
10
10
|
import { incidentioReconciliationEnabled, incidentioReconciliationInterval } from "../../incidentio/reconciliation-config.js";
|
|
11
|
-
|
|
11
|
+
// src/integrations/platform/incidentio/integration.ts
|
|
12
12
|
/**
|
|
13
13
|
* Provider config key registered for incident.io in Mastra Platform's
|
|
14
14
|
* integrations catalog. Connections are discovered at runtime — no
|
|
@@ -402,7 +402,6 @@ var PlatformIncidentioIntegration = class {
|
|
|
402
402
|
};
|
|
403
403
|
}
|
|
404
404
|
};
|
|
405
|
-
//#endregion
|
|
406
405
|
export { PlatformIncidentioIntegration, decodeScopedSourceId, encodeScopedSourceId };
|
|
407
406
|
|
|
408
407
|
//# sourceMappingURL=integration.js.map
|
|
@@ -2,7 +2,7 @@ import { JiraApiError } from "../../jira/api.js";
|
|
|
2
2
|
import { JIRA_UNTRUSTED_CONTENT_NOTICE } from "../../jira/agent-tools.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { createTool } from "@mastra/core/tools";
|
|
5
|
-
|
|
5
|
+
// src/integrations/platform/jira/agent-tools.ts
|
|
6
6
|
/** The `Intake` contract requires a connection argument; the Platform adapter resolves the real connection. */
|
|
7
7
|
const PLATFORM_CONNECTION = {
|
|
8
8
|
type: "oauth",
|
|
@@ -79,7 +79,6 @@ async function buildPlatformJiraAgentTools({ requestContext, jira }) {
|
|
|
79
79
|
jira_create_comment: createJiraCommentTool(jira)
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
|
-
//#endregion
|
|
83
82
|
export { buildPlatformJiraAgentTools };
|
|
84
83
|
|
|
85
84
|
//# sourceMappingURL=agent-tools.js.map
|
|
@@ -8,7 +8,7 @@ import { attachJiraIssueReconciler } from "../../jira/issue-reconciler.js";
|
|
|
8
8
|
import { jiraReconciliationEnabled, jiraReconciliationInterval } from "../../jira/reconciliation-config.js";
|
|
9
9
|
import { buildPlatformJiraAgentTools } from "./agent-tools.js";
|
|
10
10
|
import { buildPlatformJiraRoutes } from "./routes.js";
|
|
11
|
-
|
|
11
|
+
// src/integrations/platform/jira/integration.ts
|
|
12
12
|
const ISSUE_COMMENTS_MAX_PAGES = 20;
|
|
13
13
|
/** Hard stop for project pagination so a misbehaving `isLast` can't loop forever. */
|
|
14
14
|
const PROJECT_SEARCH_MAX_PAGES = 50;
|
|
@@ -541,7 +541,6 @@ function resolveTransition(transitions, target) {
|
|
|
541
541
|
const category = STATE_TYPE_TO_CATEGORY[target.stateType];
|
|
542
542
|
return transitions.find((transition) => transition.to?.statusCategory?.key === category) ?? null;
|
|
543
543
|
}
|
|
544
|
-
//#endregion
|
|
545
544
|
export { PlatformJiraIntegration, decodeIssueReference, decodeSourceId, encodeIssueReference, encodeSourceId };
|
|
546
545
|
|
|
547
546
|
//# sourceMappingURL=integration.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { JiraApiError } from "../../jira/api.js";
|
|
2
2
|
import { registerApiRoute } from "@mastra/core/server";
|
|
3
|
-
|
|
3
|
+
// src/integrations/platform/jira/routes.ts
|
|
4
4
|
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
5
5
|
const ISSUE_KEY_RE = /^[A-Za-z][A-Za-z0-9_]*-\d+$/;
|
|
6
6
|
/** Erase a route handler's path-parameterized context to a plain `Context`. */
|
|
@@ -268,7 +268,6 @@ function buildPlatformJiraRoutes(options) {
|
|
|
268
268
|
}));
|
|
269
269
|
return routes;
|
|
270
270
|
}
|
|
271
|
-
//#endregion
|
|
272
271
|
export { buildPlatformJiraRoutes };
|
|
273
272
|
|
|
274
273
|
//# sourceMappingURL=routes.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { PlatformApiError } from "../api-client.js";
|
|
2
2
|
import { NoopLeaseProvider, isLeaseProvider } from "@mastra/core/events";
|
|
3
3
|
import { MastraWorker } from "@mastra/core/worker";
|
|
4
|
-
|
|
4
|
+
// src/integrations/platform/linear/event-worker.ts
|
|
5
5
|
const API_PREFIX = "/v1/server/linear";
|
|
6
6
|
const DEFAULT_POLL_INTERVAL_MS = 2e4;
|
|
7
7
|
const DEFAULT_RECONCILE_INTERVAL_MS = 3e5;
|
|
@@ -373,7 +373,6 @@ function optionalObject(value) {
|
|
|
373
373
|
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
374
374
|
return value;
|
|
375
375
|
}
|
|
376
|
-
//#endregion
|
|
377
376
|
export { PlatformLinearEventWorker };
|
|
378
377
|
|
|
379
378
|
//# sourceMappingURL=event-worker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../../../src/integrations/platform/linear/integration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAIxD,OAAO,KAAK,EAAE,MAAM,EAA0D,MAAM,iCAAiC,CAAC;AACtH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AACxF,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAE9F,OAAO,KAAK,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAE3F,OAAO,KAAK,EACV,qBAAqB,EAErB,iBAAiB,IAAI,sBAAsB,EAC5C,MAAM,6BAA6B,CAAC;AAQrC,OAAO,KAAK,EAAwB,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAgD9G,KAAK,eAAe,GAAG;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AACF,KAAK,aAAa,GAAG;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACzD,CAAC;AACF,KAAK,UAAU,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAyB5D,qBAAa,yBAA0B,YAAW,kBAAkB;;IAClE,QAAQ,CAAC,EAAE,YAAY;IAYvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAsJrB;IAIF,IAAI,KAAK,IAAI,gBAAgB,CAE5B;gBAEW,EAAE,KAAK,EAAE,GAAE;QAAE,KAAK,CAAC,EAAE,mBAAmB,CAAA;KAAO;IAO3D,IAAI,OAAO,IAAI,mBAAmB,CAuBjC;IAED,IAAI,QAAQ,IAAI,sBAAsB,CAGrC;IAED,UAAU,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;QAAE,QAAQ,EAAE,sBAAsB,CAAC;QAAC,IAAI,CAAC,EAAE,SAAS,CAAA;KAAE,GAAG,IAAI;IAM5F,IAAI,WAAW,IAAI,OAAO,CAEzB;IAEK,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IASxD,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAmBlE,mBAAmB,CAAC,WAAW,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC;IAyB5E,eAAe,CAAC,UAAU,EAAE,mBAAmB,GAAG,OAAO;IAKnD,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../../../src/integrations/platform/linear/integration.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@ import { buildLinearRoutes } from "../../linear/routes.js";
|
|
|
7
7
|
import { buildLinearAgentTools } from "../../linear/agent-tools.js";
|
|
8
8
|
import { PlatformLinearEventWorker } from "./event-worker.js";
|
|
9
9
|
import { registerApiRoute } from "@mastra/core/server";
|
|
10
|
-
|
|
10
|
+
// src/integrations/platform/linear/integration.ts
|
|
11
11
|
const API_PREFIX = "/v1/server/linear";
|
|
12
12
|
const PAGE_SIZE = 30;
|
|
13
13
|
const MAX_REFERENCE_PAGES = 20;
|
|
@@ -262,6 +262,7 @@ var PlatformLinearIntegration = class {
|
|
|
262
262
|
return {
|
|
263
263
|
connected: connection !== null,
|
|
264
264
|
canComment: connection !== null && this.canPostComments(connection),
|
|
265
|
+
workspaceUrlKey: connection?.workspaceUrlKey ?? null,
|
|
265
266
|
checkedAt: Date.now()
|
|
266
267
|
};
|
|
267
268
|
}
|
|
@@ -748,7 +749,6 @@ function optionalPositiveIntegerEnv(name) {
|
|
|
748
749
|
if (!Number.isSafeInteger(parsed) || parsed <= 0) throw new Error(`${name} must be a positive integer.`);
|
|
749
750
|
return parsed;
|
|
750
751
|
}
|
|
751
|
-
//#endregion
|
|
752
752
|
export { PlatformLinearIntegration, decodeTeamSourceId, encodeSourceId, encodeTeamSourceId, parseSourceId };
|
|
753
753
|
|
|
754
754
|
//# sourceMappingURL=integration.js.map
|