@mastra/factory 0.21.0-alpha.7 → 0.21.0-alpha.9

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 (131) hide show
  1. package/README.md +72 -1
  2. package/dist/boards/define-board.d.ts +36 -1
  3. package/dist/boards/define-board.d.ts.map +1 -1
  4. package/dist/boards/define-board.js +46 -0
  5. package/dist/boards/define-board.js.map +1 -1
  6. package/dist/boards/index.d.ts +2 -2
  7. package/dist/boards/index.d.ts.map +1 -1
  8. package/dist/boards/index.js +2 -2
  9. package/dist/boards/index.js.map +1 -1
  10. package/dist/boards/semantics.d.ts +34 -1
  11. package/dist/boards/semantics.d.ts.map +1 -1
  12. package/dist/boards/semantics.js +65 -1
  13. package/dist/boards/semantics.js.map +1 -1
  14. package/dist/boards/work.d.ts.map +1 -1
  15. package/dist/boards/work.js +5 -1
  16. package/dist/boards/work.js.map +1 -1
  17. package/dist/factory.d.ts.map +1 -1
  18. package/dist/factory.js +8 -0
  19. package/dist/factory.js.map +1 -1
  20. package/dist/index.d.ts +1 -1
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/integrations/github/default-rules.d.ts +2 -2
  23. package/dist/integrations/github/default-rules.d.ts.map +1 -1
  24. package/dist/integrations/github/default-rules.js +11 -8
  25. package/dist/integrations/github/default-rules.js.map +1 -1
  26. package/dist/integrations/github/integration.d.ts +18 -0
  27. package/dist/integrations/github/integration.d.ts.map +1 -1
  28. package/dist/integrations/github/integration.js +53 -2
  29. package/dist/integrations/github/integration.js.map +1 -1
  30. package/dist/integrations/github/routes.d.ts +12 -0
  31. package/dist/integrations/github/routes.d.ts.map +1 -1
  32. package/dist/integrations/github/routes.js +63 -1
  33. package/dist/integrations/github/routes.js.map +1 -1
  34. package/dist/integrations/github/rules.d.ts +5 -2
  35. package/dist/integrations/github/rules.d.ts.map +1 -1
  36. package/dist/integrations/github/rules.js +72 -19
  37. package/dist/integrations/github/rules.js.map +1 -1
  38. package/dist/integrations/gitlab/default-rules.d.ts +3 -3
  39. package/dist/integrations/gitlab/default-rules.d.ts.map +1 -1
  40. package/dist/integrations/gitlab/default-rules.js +13 -6
  41. package/dist/integrations/gitlab/default-rules.js.map +1 -1
  42. package/dist/integrations/gitlab/rules.d.ts.map +1 -1
  43. package/dist/integrations/gitlab/rules.js +39 -8
  44. package/dist/integrations/gitlab/rules.js.map +1 -1
  45. package/dist/integrations/incidentio/default-rules.d.ts +3 -3
  46. package/dist/integrations/incidentio/default-rules.d.ts.map +1 -1
  47. package/dist/integrations/incidentio/default-rules.js +8 -6
  48. package/dist/integrations/incidentio/default-rules.js.map +1 -1
  49. package/dist/integrations/incidentio/rules.d.ts.map +1 -1
  50. package/dist/integrations/incidentio/rules.js +6 -3
  51. package/dist/integrations/incidentio/rules.js.map +1 -1
  52. package/dist/integrations/jira/default-rules.d.ts +3 -3
  53. package/dist/integrations/jira/default-rules.d.ts.map +1 -1
  54. package/dist/integrations/jira/default-rules.js +8 -6
  55. package/dist/integrations/jira/default-rules.js.map +1 -1
  56. package/dist/integrations/jira/rules.d.ts.map +1 -1
  57. package/dist/integrations/jira/rules.js +6 -3
  58. package/dist/integrations/jira/rules.js.map +1 -1
  59. package/dist/integrations/linear/default-rules.d.ts +3 -3
  60. package/dist/integrations/linear/default-rules.d.ts.map +1 -1
  61. package/dist/integrations/linear/default-rules.js +8 -6
  62. package/dist/integrations/linear/default-rules.js.map +1 -1
  63. package/dist/integrations/linear/routes.js +1 -1
  64. package/dist/integrations/linear/rules.d.ts.map +1 -1
  65. package/dist/integrations/linear/rules.js +6 -3
  66. package/dist/integrations/linear/rules.js.map +1 -1
  67. package/dist/integrations/pull-request-head.d.ts +18 -0
  68. package/dist/integrations/pull-request-head.d.ts.map +1 -0
  69. package/dist/integrations/pull-request-head.js +45 -0
  70. package/dist/integrations/pull-request-head.js.map +1 -0
  71. package/dist/routes/attention-providers.js +3 -3
  72. package/dist/routes/attention-providers.js.map +1 -1
  73. package/dist/routes/contracts.js +1 -1
  74. package/dist/routes/intake.d.ts +3 -0
  75. package/dist/routes/intake.d.ts.map +1 -1
  76. package/dist/routes/intake.js +47 -6
  77. package/dist/routes/intake.js.map +1 -1
  78. package/dist/routes/surface.d.ts.map +1 -1
  79. package/dist/routes/surface.js +3 -2
  80. package/dist/routes/surface.js.map +1 -1
  81. package/dist/routes/work-items.d.ts.map +1 -1
  82. package/dist/routes/work-items.js +3 -4
  83. package/dist/routes/work-items.js.map +1 -1
  84. package/dist/rules/decision-applicability.d.ts +6 -0
  85. package/dist/rules/decision-applicability.d.ts.map +1 -1
  86. package/dist/rules/decision-applicability.js +10 -1
  87. package/dist/rules/decision-applicability.js.map +1 -1
  88. package/dist/rules/dispatcher.d.ts.map +1 -1
  89. package/dist/rules/dispatcher.js +20 -15
  90. package/dist/rules/dispatcher.js.map +1 -1
  91. package/dist/rules/event-rules.d.ts +23 -0
  92. package/dist/rules/event-rules.d.ts.map +1 -0
  93. package/dist/rules/event-rules.js +46 -0
  94. package/dist/rules/event-rules.js.map +1 -0
  95. package/dist/rules/index.js +1 -1
  96. package/dist/rules/processor.js +1 -1
  97. package/dist/rules/review-source-tool.d.ts +5 -3
  98. package/dist/rules/review-source-tool.d.ts.map +1 -1
  99. package/dist/rules/review-source-tool.js.map +1 -1
  100. package/dist/rules/tools.js +1 -1
  101. package/dist/rules/transition-service.js +1 -1
  102. package/dist/rules/types.d.ts +47 -0
  103. package/dist/rules/types.d.ts.map +1 -1
  104. package/dist/rules/types.js.map +1 -1
  105. package/dist/storage/domains/comments/base.d.ts +3 -0
  106. package/dist/storage/domains/comments/base.d.ts.map +1 -1
  107. package/dist/storage/domains/comments/base.js +8 -1
  108. package/dist/storage/domains/comments/base.js.map +1 -1
  109. package/dist/storage/domains/work-items/base.d.ts +7 -3
  110. package/dist/storage/domains/work-items/base.d.ts.map +1 -1
  111. package/dist/storage/domains/work-items/base.js +66 -16
  112. package/dist/storage/domains/work-items/base.js.map +1 -1
  113. package/dist/storage/domains/work-items/board-version.d.ts +26 -0
  114. package/dist/storage/domains/work-items/board-version.d.ts.map +1 -0
  115. package/dist/storage/domains/work-items/board-version.js +110 -0
  116. package/dist/storage/domains/work-items/board-version.js.map +1 -0
  117. package/dist/supervisor/health.d.ts.map +1 -1
  118. package/dist/supervisor/health.js +17 -5
  119. package/dist/supervisor/health.js.map +1 -1
  120. package/dist/supervisor/read-tools.d.ts.map +1 -1
  121. package/dist/supervisor/read-tools.js +13 -8
  122. package/dist/supervisor/read-tools.js.map +1 -1
  123. package/dist/supervisor/write-tools.d.ts.map +1 -1
  124. package/dist/supervisor/write-tools.js +5 -1
  125. package/dist/supervisor/write-tools.js.map +1 -1
  126. package/dist/workspace.d.ts.map +1 -1
  127. package/dist/workspace.js +17 -1
  128. package/dist/workspace.js.map +1 -1
  129. package/factory-skills/factory-rereview/SKILL.md +4 -4
  130. package/factory-skills/factory-review/SKILL.md +2 -2
  131. package/package.json +7 -7
@@ -1,9 +1,11 @@
1
1
  import { assertFactoryDecisionTarget, validateFactoryRuleDecisions } from "../../rules/validation.js";
2
- import { boardForWorkItem, workItemPhaseSemantics } from "../../boards/semantics.js";
2
+ import { boardEventHandlers, boardForWorkItem, eventBoardId, rulePhaseField, withBoardClosure, workItemPhaseSemantics } from "../../boards/semantics.js";
3
3
  import "../../boards/index.js";
4
4
  import { FACTORY_PULL_REQUEST_RECONCILIATION_KEY, WorkItemUpdateConflictError } from "../../storage/domains/work-items/base.js";
5
5
  import { cardLabels, moveCardToBoard } from "../../boards/relocate.js";
6
+ import { selectEventRule } from "../../rules/event-rules.js";
6
7
  import { resolveIntakeLabelRoute } from "../../storage/domains/intake/base.js";
8
+ import { recordPullRequestHead } from "../pull-request-head.js";
7
9
  import { changeRequestTargetKey } from "./subscriptions.js";
8
10
  import { createHash } from "crypto";
9
11
  //#region src/integrations/github/rules.ts
@@ -23,6 +25,10 @@ async function withRuleTimeout(promise) {
23
25
  function object(value) {
24
26
  return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
25
27
  }
28
+ function timestamp(value) {
29
+ const parsed = typeof value === "string" ? Date.parse(value) : NaN;
30
+ return Number.isNaN(parsed) ? void 0 : parsed;
31
+ }
26
32
  function string(value) {
27
33
  return typeof value === "string" && value.length > 0 ? value : void 0;
28
34
  }
@@ -195,17 +201,32 @@ var GithubRules = class {
195
201
  return slug ? `${slug.toLowerCase()}[bot]` : void 0;
196
202
  }
197
203
  /**
198
- * Board an issue's labels select under the project's label routes, when that board is installed.
199
- * Undefined leaves built-in routing (Work) in charge.
204
+ * Board an issue lands on: the one its labels select under the project's label routes, else the
205
+ * board the repository's intake source binding names. Only installed boards count. Undefined
206
+ * leaves built-in routing (Work) in charge.
200
207
  */
201
- async #labelRouteTarget(orgId, factoryProjectId, labels) {
202
- if (!this.options.intake || labels.length === 0) return void 0;
203
- const route = resolveIntakeLabelRoute(await this.options.intake.listLabelRoutes({
208
+ async #intakeTarget(project, repositoryName, labels) {
209
+ const intake = this.options.intake;
210
+ if (!intake) return void 0;
211
+ const { orgId, factoryProjectId } = project;
212
+ if (labels.length > 0) {
213
+ const route = resolveIntakeLabelRoute(await intake.listLabelRoutes({
214
+ orgId,
215
+ factoryProjectId,
216
+ integrationId: "github"
217
+ }), labels);
218
+ const board = route ? this.options.boards.get(route.board) : void 0;
219
+ if (board) return {
220
+ board: board.id,
221
+ initialPhase: board.initialPhase
222
+ };
223
+ }
224
+ const slug = repositoryName.toLowerCase();
225
+ const binding = (await intake.listBindings({
204
226
  orgId,
205
- factoryProjectId,
206
227
  integrationId: "github"
207
- }), labels);
208
- const board = route ? this.options.boards.get(route.board) : void 0;
228
+ })).find((candidate) => candidate.factoryProjectId === factoryProjectId && (candidate.sourceId === project.projectRepository.repositoryId || candidate.sourceId.toLowerCase() === slug));
229
+ const board = binding?.board ? this.options.boards.get(binding.board) : void 0;
209
230
  return board ? {
210
231
  board: board.id,
211
232
  initialPhase: board.initialPhase
@@ -246,7 +267,7 @@ var GithubRules = class {
246
267
  item = updated.item;
247
268
  changed = true;
248
269
  }
249
- const target = await this.#labelRouteTarget(project.orgId, project.factoryProjectId, labels);
270
+ const target = await this.#intakeTarget(project, repositoryName, labels);
250
271
  const outcome = await moveCardToBoard({
251
272
  workItems: this.options.storage,
252
273
  boardRegistry: this.options.boards,
@@ -300,7 +321,7 @@ var GithubRules = class {
300
321
  const pullRequestFactoryAuthored = provenance !== null || this.#isFactoryLogin(pullRequestAuthor);
301
322
  const resolvedItem = await this.#relatedItem(project.orgId, project.factoryProjectId, repositoryId, repositoryName, issueNumber, pullRequestNumber, string(object(pullRequest?.head)?.ref), reReviewEvent ? null : provenance, senderIsResponder && !reviewEntryRequested);
302
323
  const relatedItem = reviewEntryRequested && resolvedItem?.externalSource?.type !== "pull-request" ? void 0 : resolvedItem;
303
- const intake = issueNumber ? await this.#labelRouteTarget(project.orgId, project.factoryProjectId, labelNames(issue?.labels)) : void 0;
324
+ const intake = issueNumber ? await this.#intakeTarget(project, repositoryName, labelNames(issue?.labels)) : void 0;
304
325
  const actor = await githubActor(this.options.github, {
305
326
  installationId,
306
327
  repository: repositoryName,
@@ -335,7 +356,9 @@ var GithubRules = class {
335
356
  metadata: item.metadata
336
357
  },
337
358
  board: boardForWorkItem(item),
338
- itemRevision: item.revision
359
+ itemRevision: item.revision,
360
+ ...withBoardClosure(this.options.boards, item),
361
+ ...rulePhaseField(this.options.boards, item)
339
362
  } : {},
340
363
  ...intake ? { intake } : {},
341
364
  ...pullRequestIntake ? { pullRequestIntake: true } : {},
@@ -400,7 +423,7 @@ var GithubRules = class {
400
423
  ...string(object(parsed.payload.review)?.body) ? { body: string(object(parsed.payload.review)?.body) } : {}
401
424
  } } : {}
402
425
  };
403
- const rule = this.options.github.rules[event];
426
+ const rule = selectEventRule(this.options.github.rules, boardEventHandlers(this.options.boards, eventBoardId(context), "github"), event);
404
427
  let decision;
405
428
  let decisions = [];
406
429
  let outcome = { status: "accepted" };
@@ -460,12 +483,21 @@ var GithubRules = class {
460
483
  const trusted = actor.type === "github" && actor.trusted || pullRequestFactoryAuthored;
461
484
  const reviewCard = authoringItem && trusted ? await this.#linkedClosureItem(project.orgId, project.factoryProjectId, repositoryId, repositoryName, pullRequestNumber, authoringItem) : void 0;
462
485
  const stillOpen = companionStatus === "replayed" ? reviewCard !== void 0 && reviewCard.metadata?.state !== "closed" : reviewCard?.metadata?.state !== "closed";
463
- if (authoringItem && trusted && stillOpen) await this.options.storage.update({
464
- orgId: authoringItem.orgId,
465
- id: authoringItem.id,
466
- userId: "factory-rule-dispatcher",
467
- patch: { metadata: { openPullRequestNumber: pullRequestNumber } }
468
- });
486
+ if (authoringItem && trusted && stillOpen) {
487
+ const head = authoringItem.metadata?.openPullRequestNumber !== pullRequestNumber ? {
488
+ pullRequestHeadSha: string(object(pullRequest?.head)?.sha)?.toLowerCase() ?? null,
489
+ pullRequestHeadAt: timestamp(pullRequest?.updated_at) ?? null
490
+ } : {};
491
+ await this.options.storage.update({
492
+ orgId: authoringItem.orgId,
493
+ id: authoringItem.id,
494
+ userId: "factory-rule-dispatcher",
495
+ patch: { metadata: {
496
+ openPullRequestNumber: pullRequestNumber,
497
+ ...head
498
+ } }
499
+ });
500
+ }
469
501
  return;
470
502
  }
471
503
  if (event !== "pullRequestMerged" && event !== "pullRequestClosed") return;
@@ -497,8 +529,29 @@ var GithubRules = class {
497
529
  }
498
530
  };
499
531
  const authoringItem = linked === void 0 && pullRequestOpened && relatedItem !== void 0 && relatedItem.externalSource?.type !== "pull-request" ? relatedItem : void 0;
532
+ const stampHead = async () => {
533
+ const headSha = string(object(pullRequest?.head)?.sha)?.toLowerCase();
534
+ if (event !== "pullRequestUpdated" || !headSha || !pullRequestNumber) return;
535
+ const headAt = timestamp(pullRequest?.updated_at);
536
+ if (relatedItem?.externalSource?.type !== "pull-request") return;
537
+ const parent = await this.#linkedClosureItem(project.orgId, project.factoryProjectId, repositoryId, repositoryName, pullRequestNumber, relatedItem);
538
+ await recordPullRequestHead(this.options.storage, {
539
+ orgId: relatedItem.orgId,
540
+ id: relatedItem.id,
541
+ headSha,
542
+ headAt
543
+ });
544
+ if (parent) await recordPullRequestHead(this.options.storage, {
545
+ orgId: parent.orgId,
546
+ id: parent.id,
547
+ headSha,
548
+ headAt,
549
+ ownedPullRequestNumber: pullRequestNumber
550
+ });
551
+ };
500
552
  if (linked === void 0 && authoringItem === void 0) {
501
553
  await stampClosed();
554
+ await stampHead();
502
555
  return primary;
503
556
  }
504
557
  const companion = linked ?? authoringItem;