@mastra/factory 0.1.0-alpha.6 → 0.1.0-alpha.8

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 (47) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/factory.d.ts.map +1 -1
  3. package/dist/factory.js +161 -15
  4. package/dist/factory.js.map +1 -1
  5. package/dist/index.js +161 -15
  6. package/dist/index.js.map +1 -1
  7. package/dist/integrations/github/integration.js +108 -1
  8. package/dist/integrations/github/integration.js.map +1 -1
  9. package/dist/integrations/github/pat.d.ts +38 -0
  10. package/dist/integrations/github/pat.d.ts.map +1 -0
  11. package/dist/integrations/github/pat.js +48 -0
  12. package/dist/integrations/github/pat.js.map +1 -0
  13. package/dist/integrations/github/provenance.js.map +1 -1
  14. package/dist/integrations/github/routes.d.ts.map +1 -1
  15. package/dist/integrations/github/routes.js +94 -1
  16. package/dist/integrations/github/routes.js.map +1 -1
  17. package/dist/integrations/github/session-subscriptions.d.ts.map +1 -1
  18. package/dist/integrations/github/session-subscriptions.js +30 -0
  19. package/dist/integrations/github/session-subscriptions.js.map +1 -1
  20. package/dist/integrations/github/token-refresh.d.ts +6 -0
  21. package/dist/integrations/github/token-refresh.d.ts.map +1 -1
  22. package/dist/integrations/github/token-refresh.js +10 -0
  23. package/dist/integrations/github/token-refresh.js.map +1 -1
  24. package/dist/integrations/platform/github/integration.d.ts.map +1 -1
  25. package/dist/integrations/platform/github/integration.js +110 -2
  26. package/dist/integrations/platform/github/integration.js.map +1 -1
  27. package/dist/routes/surface.js +7 -1
  28. package/dist/routes/surface.js.map +1 -1
  29. package/dist/routes/work-items.js.map +1 -1
  30. package/dist/rules/defaults.d.ts.map +1 -1
  31. package/dist/rules/defaults.js +20 -6
  32. package/dist/rules/defaults.js.map +1 -1
  33. package/dist/rules/index.js +20 -6
  34. package/dist/rules/index.js.map +1 -1
  35. package/dist/rules/start-coordinator.d.ts.map +1 -1
  36. package/dist/rules/start-coordinator.js +7 -1
  37. package/dist/rules/start-coordinator.js.map +1 -1
  38. package/dist/workspace.d.ts +5 -0
  39. package/dist/workspace.d.ts.map +1 -1
  40. package/dist/workspace.js +65 -6
  41. package/dist/workspace.js.map +1 -1
  42. package/factory-skills/factory-plan/SKILL.md +61 -0
  43. package/factory-skills/factory-review/SKILL.md +73 -0
  44. package/factory-skills/factory-triage/SKILL.md +77 -0
  45. package/package.json +6 -6
  46. package/factory-skills/understand-issue/SKILL.md +0 -251
  47. package/factory-skills/understand-pr/SKILL.md +0 -270
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @mastra/factory
2
2
 
3
+ ## 0.1.0-alpha.8
4
+
5
+ ### Minor Changes
6
+
7
+ - Added autonomous first-pass skills to the Software Factory. Work items now get an automatic investigation, planning, or review pass as soon as they enter the matching board column — no human input needed mid-run: ([#20058](https://github.com/mastra-ai/mastra/pull/20058))
8
+
9
+ - **factory-triage** runs when an issue enters triage: it investigates the issue, diagnoses the root cause, and requests a move to planning (or done if the issue should be closed).
10
+ - **factory-plan** runs when an item enters planning: it produces a phased implementation plan and requests a move to execute.
11
+ - **factory-review** runs when a pull request enters review: it reviews the changes, posts a verdict, and requests completion.
12
+
13
+ Instead of stopping to ask questions, the skills decide and record each decision as an assumption, batching assumptions and genuinely-human questions into one terminal handoff message. The superseded interactive skills (understand-issue, understand-pr) were removed.
14
+
15
+ ## 0.1.0-alpha.7
16
+
17
+ ### Patch Changes
18
+
19
+ - Updated dependencies:
20
+ - @mastra/code-sdk@1.0.0-alpha.18
21
+
3
22
  ## 0.1.0-alpha.6
4
23
 
5
24
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAGlD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAS/D,OAAO,KAAK,EAAE,kBAAkB,EAAgD,MAAM,wBAAwB,CAAC;AAmB/G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAwBrD,8EAA8E;AAC9E,MAAM,MAAM,UAAU,GAAG,WAAW,CAAC,qBAAqB,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9E,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;;;;;;;OAcG;IACH,IAAI,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAClC;;;;;;;OAOG;IACH,OAAO,EAAE,cAAc,CAAC;IACxB;;;;OAIG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,0EAA0E;IAC1E,OAAO,CAAC,EAAE,0BAA0B,CAAC;IACrC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACpC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,WAAW,0BAA0B;IACzC;;;;;;OAMG;IACH,OAAO,EAAE,gBAAgB,CAAC;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAwFD,qBAAa,aAAa;;gBAOZ,MAAM,EAAE,mBAAmB;IAWvC;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC;IA6dpC;;;;OAIG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAS/B,iFAAiF;IAC3E,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAGhC"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAGlD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAS/D,OAAO,KAAK,EAAE,kBAAkB,EAAgD,MAAM,wBAAwB,CAAC;AAmB/G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAwBrD,8EAA8E;AAC9E,MAAM,MAAM,UAAU,GAAG,WAAW,CAAC,qBAAqB,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAE9E,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;;;;;;;OAcG;IACH,IAAI,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAClC;;;;;;;OAOG;IACH,OAAO,EAAE,cAAc,CAAC;IACxB;;;;OAIG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,0EAA0E;IAC1E,OAAO,CAAC,EAAE,0BAA0B,CAAC;IACrC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACpC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,WAAW,0BAA0B;IACzC;;;;;;OAMG;IACH,OAAO,EAAE,gBAAgB,CAAC;IAC1B;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAwFD,qBAAa,aAAa;;gBAOZ,MAAM,EAAE,mBAAmB;IAWvC;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC;IA8dpC;;;;OAIG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAS/B,iFAAiF;IAC3E,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAGhC"}
package/dist/factory.js CHANGED
@@ -24778,6 +24778,48 @@ function createFactoryAuthGate(provider) {
24778
24778
  import { createTool } from "@mastra/core/tools";
24779
24779
  import { z } from "zod";
24780
24780
 
24781
+ // src/integrations/github/pat.ts
24782
+ var PAT_SETTINGS_USER_ID = "__github_org_settings__";
24783
+ var FIELD_FOR_KIND = {
24784
+ default: "pat",
24785
+ reviewer: "reviewerPat"
24786
+ };
24787
+ function asToken(value) {
24788
+ return typeof value === "string" && value.length > 0 ? value : null;
24789
+ }
24790
+ async function getGithubPat(getStorage, orgId, kind = "default") {
24791
+ try {
24792
+ const settings = await getStorage().settings.get(orgId, PAT_SETTINGS_USER_ID);
24793
+ if (!settings) return null;
24794
+ if (kind === "reviewer") return asToken(settings.reviewerPat) ?? asToken(settings.pat);
24795
+ return asToken(settings.pat);
24796
+ } catch {
24797
+ return null;
24798
+ }
24799
+ }
24800
+ async function getGithubPatStatus(getStorage, orgId) {
24801
+ try {
24802
+ const settings = await getStorage().settings.get(orgId, PAT_SETTINGS_USER_ID);
24803
+ return {
24804
+ configured: asToken(settings?.pat) !== null,
24805
+ reviewerConfigured: asToken(settings?.reviewerPat) !== null
24806
+ };
24807
+ } catch {
24808
+ return { configured: false, reviewerConfigured: false };
24809
+ }
24810
+ }
24811
+ async function setGithubPat(storage, orgId, pat, kind = "default") {
24812
+ const existing = await storage.settings.get(orgId, PAT_SETTINGS_USER_ID) ?? {};
24813
+ await storage.settings.save(orgId, PAT_SETTINGS_USER_ID, { ...existing, [FIELD_FOR_KIND[kind]]: pat });
24814
+ }
24815
+ async function clearGithubPat(storage, orgId, kind = "default") {
24816
+ const existing = await storage.settings.get(orgId, PAT_SETTINGS_USER_ID);
24817
+ const field = FIELD_FOR_KIND[kind];
24818
+ if (!existing?.[field]) return;
24819
+ const { [field]: _removed, ...rest } = existing;
24820
+ await storage.settings.save(orgId, PAT_SETTINGS_USER_ID, rest);
24821
+ }
24822
+
24781
24823
  // src/integrations/github/subscriptions.ts
24782
24824
  function changeRequestTargetKey(input) {
24783
24825
  return `change-request:${input.installationExternalId}:${input.repositoryExternalId}:${input.changeRequestId}`;
@@ -24832,9 +24874,17 @@ function retirePullRequestSubscription(id, status, storage) {
24832
24874
 
24833
24875
  // src/integrations/github/token-refresh.ts
24834
24876
  var GITHUB_TOKEN_INJECTOR_CONTEXT_KEY = "factoryGithubTokenInjector";
24877
+ var GITHUB_PAT_KIND_CONTEXT_KEY = "factoryGithubPatKind";
24835
24878
  function registerGithubTokenInjector(requestContext, injector) {
24836
24879
  requestContext.set(GITHUB_TOKEN_INJECTOR_CONTEXT_KEY, injector);
24837
24880
  }
24881
+ function registerGithubPatKind(requestContext, kind) {
24882
+ requestContext.set(GITHUB_PAT_KIND_CONTEXT_KEY, kind);
24883
+ }
24884
+ function getRegisteredGithubPatKind(requestContext) {
24885
+ const kind = requestContext.get(GITHUB_PAT_KIND_CONTEXT_KEY);
24886
+ return kind === "reviewer" ? "reviewer" : "default";
24887
+ }
24838
24888
  function injectGithubToken(requestContext, token) {
24839
24889
  const injector = requestContext.get(GITHUB_TOKEN_INJECTOR_CONTEXT_KEY);
24840
24890
  if (!injector) {
@@ -24932,6 +24982,15 @@ async function unsubscribeCurrentSessionFromPullRequest(requestContext, pullRequ
24932
24982
  }
24933
24983
  async function refreshGithubToken(requestContext, github) {
24934
24984
  const target = await resolveSessionTarget(requestContext, github);
24985
+ const pat = await getGithubPat(
24986
+ () => github.integrationStorage,
24987
+ target.orgId,
24988
+ getRegisteredGithubPatKind(requestContext)
24989
+ );
24990
+ if (pat) {
24991
+ injectGithubToken(requestContext, pat);
24992
+ return;
24993
+ }
24935
24994
  const access = await github.versionControl.getRepositoryAccess({
24936
24995
  orgId: target.orgId,
24937
24996
  repositoryId: target.repository.id
@@ -26659,6 +26718,56 @@ function buildGithubRoutes(options) {
26659
26718
  }
26660
26719
  })
26661
26720
  );
26721
+ const parsePatKind = (value) => {
26722
+ if (value === void 0 || value === null || value === "default") return "default";
26723
+ if (value === "reviewer") return "reviewer";
26724
+ return null;
26725
+ };
26726
+ routes.push(
26727
+ registerApiRoute2("/web/github/pat", {
26728
+ method: "GET",
26729
+ requiresAuth: false,
26730
+ handler: async (c) => {
26731
+ const resolved = await resolveOrgTenant(loose(c), auth);
26732
+ if ("response" in resolved) return resolved.response;
26733
+ return c.json(await getGithubPatStatus(() => github.integrationStorage, resolved.tenant.orgId));
26734
+ }
26735
+ }),
26736
+ registerApiRoute2("/web/github/pat", {
26737
+ method: "POST",
26738
+ requiresAuth: false,
26739
+ handler: async (c) => {
26740
+ const resolved = await resolveOrgTenant(loose(c), auth);
26741
+ if ("response" in resolved) return resolved.response;
26742
+ let body;
26743
+ try {
26744
+ body = await c.req.json();
26745
+ } catch {
26746
+ return c.json({ error: "Invalid JSON body" }, 400);
26747
+ }
26748
+ const kind = parsePatKind(body.kind);
26749
+ if (!kind) return c.json({ error: "kind must be 'default' or 'reviewer'" }, 400);
26750
+ const token = typeof body.token === "string" ? body.token.trim() : "";
26751
+ if (!token) return c.json({ error: "A token is required" }, 400);
26752
+ if (token.length > 500) return c.json({ error: "Token too long (max 500 characters)" }, 400);
26753
+ if (/\s/.test(token)) return c.json({ error: "Token must not contain whitespace" }, 400);
26754
+ await setGithubPat(github.integrationStorage, resolved.tenant.orgId, token, kind);
26755
+ return c.json(await getGithubPatStatus(() => github.integrationStorage, resolved.tenant.orgId));
26756
+ }
26757
+ }),
26758
+ registerApiRoute2("/web/github/pat", {
26759
+ method: "DELETE",
26760
+ requiresAuth: false,
26761
+ handler: async (c) => {
26762
+ const resolved = await resolveOrgTenant(loose(c), auth);
26763
+ if ("response" in resolved) return resolved.response;
26764
+ const kind = parsePatKind(c.req.query("kind"));
26765
+ if (!kind) return c.json({ error: "kind must be 'default' or 'reviewer'" }, 400);
26766
+ await clearGithubPat(github.integrationStorage, resolved.tenant.orgId, kind);
26767
+ return c.json(await getGithubPatStatus(() => github.integrationStorage, resolved.tenant.orgId));
26768
+ }
26769
+ })
26770
+ );
26662
26771
  routes.push(...buildProjectGitRoutes({ github, auth, fleet, storage, emitAudit }));
26663
26772
  return routes;
26664
26773
  }
@@ -26701,11 +26810,12 @@ async function prepareProject(options) {
26701
26810
  if (!access.authorization) {
26702
26811
  throw new MaterializeError("Repository access did not include a bearer token.", "clone-failed");
26703
26812
  }
26813
+ const ghCliToken = await getGithubPat(() => github.integrationStorage, project.installation.orgId) ?? access.authorization.token;
26704
26814
  const sandbox = await ensureProjectSandbox({
26705
26815
  fleet,
26706
26816
  row: sandboxRow,
26707
26817
  storage: github.sourceControlStorage.sandboxes,
26708
- token: access.authorization.token,
26818
+ token: ghCliToken,
26709
26819
  onProgress
26710
26820
  });
26711
26821
  const fresh = await github.sourceControlStorage.sandboxes.getById({ id: sandboxRow.id });
@@ -27739,6 +27849,7 @@ var PlatformGithubIntegration = class {
27739
27849
  getRepositoryAccess: async ({ orgId, repositoryId }) => {
27740
27850
  const repository = await this.storage.repositories.get({ orgId, id: repositoryId });
27741
27851
  if (!repository) throw new Error("Version-control repository not found.");
27852
+ const cloneUrl = `https://github.com/${repository.slug}.git`;
27742
27853
  const installation = await this.storage.installations.get({ orgId, id: repository.installationId });
27743
27854
  if (!installation) throw new Error("Version-control installation not found.");
27744
27855
  const installationId = parsePositiveInteger(installation.externalId);
@@ -27750,7 +27861,7 @@ var PlatformGithubIntegration = class {
27750
27861
  { repositories: [repositoryName], permissions: REPOSITORY_TOKEN_PERMISSIONS }
27751
27862
  );
27752
27863
  return {
27753
- cloneUrl: `https://github.com/${repository.slug}.git`,
27864
+ cloneUrl,
27754
27865
  authorization: { scheme: "bearer", token: token.token }
27755
27866
  };
27756
27867
  },
@@ -30558,13 +30669,19 @@ var FactoryStartCoordinator = class {
30558
30669
  if (!request.requestContext) {
30559
30670
  requestContext.set("user", { workosId: request.userId, organizationId: request.orgId });
30560
30671
  }
30672
+ const sessionState = {
30673
+ factoryProjectId: request.factoryProjectId,
30674
+ projectRepositoryId: sourceSession.projectRepositoryId
30675
+ };
30561
30676
  const session = await this.#controller.createSession({
30562
30677
  id: sourceSession.sessionId,
30563
30678
  ownerId: request.userId,
30564
30679
  resourceId: sourceSession.sessionId,
30565
30680
  threadId: sourceSession.sessionId,
30566
- requestContext
30681
+ requestContext,
30682
+ tags: sessionState
30567
30683
  });
30684
+ await session.state.set(sessionState);
30568
30685
  const threadId = await configureThread(session, request);
30569
30686
  const kickoffMessage = await resolveKickoffMessage(session, request.invocation);
30570
30687
  const prepared = await storage.prepareRunStart({
@@ -35306,9 +35423,9 @@ function trustedGithubActor(context) {
35306
35423
  function invokeIssueInvestigation(context) {
35307
35424
  return {
35308
35425
  type: "invokeSkill",
35309
- idempotencyKey: `${context.ingress.id}:understand-issue`,
35426
+ idempotencyKey: `${context.ingress.id}:factory-triage`,
35310
35427
  role: "triage",
35311
- skillName: "understand-issue",
35428
+ skillName: "factory-triage",
35312
35429
  arguments: context.item.url ? `GitHub issue (${context.item.url})` : context.item.title
35313
35430
  };
35314
35431
  }
@@ -35319,18 +35436,27 @@ function investigateTriagedLinearIssue(context) {
35319
35436
  const identifier = context.item.sourceKey?.startsWith("linear:") ? context.item.sourceKey.slice("linear:".length) : context.item.title;
35320
35437
  return {
35321
35438
  type: "invokeSkill",
35322
- idempotencyKey: `${context.ingress.id}:understand-linear-issue`,
35439
+ idempotencyKey: `${context.ingress.id}:factory-triage-linear`,
35323
35440
  role: "triage",
35324
- skillName: "understand-issue",
35441
+ skillName: "factory-triage",
35325
35442
  arguments: `Linear issue ${identifier}${context.item.url ? ` (${context.item.url})` : ""}`
35326
35443
  };
35327
35444
  }
35445
+ function planWorkItem(context) {
35446
+ return {
35447
+ type: "invokeSkill",
35448
+ idempotencyKey: `${context.ingress.id}:factory-plan`,
35449
+ role: "plan",
35450
+ skillName: "factory-plan",
35451
+ arguments: context.item.url ? `Work item (${context.item.url})` : context.item.title
35452
+ };
35453
+ }
35328
35454
  function reviewPullRequest(context) {
35329
35455
  return {
35330
35456
  type: "invokeSkill",
35331
- idempotencyKey: `${context.ingress.id}:understand-pr`,
35457
+ idempotencyKey: `${context.ingress.id}:factory-review`,
35332
35458
  role: "review",
35333
- skillName: "understand-pr",
35459
+ skillName: "factory-review",
35334
35460
  arguments: context.item.url ? `GitHub pull request (${context.item.url})` : context.item.title
35335
35461
  };
35336
35462
  }
@@ -35428,6 +35554,11 @@ var BUILT_IN_DEFAULTS = {
35428
35554
  triage: {
35429
35555
  issue: { onEnter: investigateTriagedIssue },
35430
35556
  linearIssue: { onEnter: investigateTriagedLinearIssue }
35557
+ },
35558
+ planning: {
35559
+ issue: { onEnter: planWorkItem },
35560
+ linearIssue: { onEnter: planWorkItem },
35561
+ manual: { onEnter: planWorkItem }
35431
35562
  }
35432
35563
  },
35433
35564
  review: { review: { pullRequest: { onEnter: reviewPullRequest } } },
@@ -38345,7 +38476,7 @@ var FACTORY_SKILLS_SOURCE_PATH = [
38345
38476
  join3(process.cwd(), "src", "mastra", "public", "factory-skills")
38346
38477
  ].find(existsSync2) ?? bundledFactorySkillsPath;
38347
38478
  var FACTORY_SKILLS_MOUNT = path2.resolve(path2.parse(process.cwd()).root, "__mastracode_factory_skills__");
38348
- var FACTORY_SKILL_NAMES = /* @__PURE__ */ new Set(["configure-factory-rules", "understand-issue", "understand-pr"]);
38479
+ var FACTORY_SKILL_NAMES = /* @__PURE__ */ new Set(["configure-factory-rules", "factory-plan", "factory-review", "factory-triage"]);
38349
38480
  var FactorySkillSource = class {
38350
38481
  constructor(fallback, fallbackSkillRoots) {
38351
38482
  this.fallback = fallback;
@@ -38391,7 +38522,7 @@ var factorySkillExtension = {
38391
38522
  createSource: (fallback, fallbackSkillRoots) => new FactorySkillSource(fallback, fallbackSkillRoots)
38392
38523
  };
38393
38524
  function createWorkspaceFactory(options = {}) {
38394
- const { sandbox: sandboxConfig, github, fleet } = options;
38525
+ const { sandbox: sandboxConfig, github, fleet, workItems } = options;
38395
38526
  const isLocalSandbox = sandboxConfig?.machine instanceof LocalSandbox;
38396
38527
  const githubTokenInjectors = /* @__PURE__ */ new Map();
38397
38528
  return async ({ requestContext, mastra, skillExtension }) => {
@@ -38445,8 +38576,11 @@ function createWorkspaceFactory(options = {}) {
38445
38576
  const existing = mastra?.getWorkspaceById(workspaceId);
38446
38577
  if (existing) {
38447
38578
  existing.setToolsConfig(MASTRACODE_WORKSPACE_TOOLS);
38448
- const injectGithubToken3 = githubTokenInjectors.get(workspaceId);
38449
- if (injectGithubToken3) registerGithubTokenInjector(requestContext, injectGithubToken3);
38579
+ const registered = githubTokenInjectors.get(workspaceId);
38580
+ if (registered) {
38581
+ registerGithubTokenInjector(requestContext, registered.inject);
38582
+ registerGithubPatKind(requestContext, registered.patKind);
38583
+ }
38450
38584
  return existing;
38451
38585
  }
38452
38586
  } catch {
@@ -38457,9 +38591,19 @@ function createWorkspaceFactory(options = {}) {
38457
38591
  });
38458
38592
  const token = access.authorization?.token;
38459
38593
  if (!token) throw new Error("Repository access did not include a bearer token for the Factory session");
38594
+ let patKind = "default";
38595
+ if (workItems) {
38596
+ try {
38597
+ const address = getFactorySessionAddress(requestContext);
38598
+ const runBinding = address ? await workItems.findRunBindingBySession(address) : null;
38599
+ if (runBinding?.role === "review" && runBinding.orgId === session.orgId) patKind = "reviewer";
38600
+ } catch {
38601
+ }
38602
+ }
38603
+ const ghCliToken = await getGithubPat(() => github.integrationStorage, session.orgId, patKind) ?? token;
38460
38604
  const sandbox = await fleet.ensureSandbox(
38461
38605
  binding,
38462
- { GH_TOKEN: token },
38606
+ { GH_TOKEN: ghCliToken },
38463
38607
  void 0,
38464
38608
  isLocalSandbox ? { workingDirectory: workdir } : {}
38465
38609
  );
@@ -38483,8 +38627,9 @@ function createWorkspaceFactory(options = {}) {
38483
38627
  }
38484
38628
  sandbox.setEnvironmentVariable("GH_TOKEN", freshToken);
38485
38629
  };
38486
- githubTokenInjectors.set(workspaceId, injectGithubToken2);
38630
+ githubTokenInjectors.set(workspaceId, { inject: injectGithubToken2, patKind });
38487
38631
  registerGithubTokenInjector(requestContext, injectGithubToken2);
38632
+ registerGithubPatKind(requestContext, patKind);
38488
38633
  const filesystem = new SandboxFilesystem({ sandbox, workdir });
38489
38634
  const projectSkillPaths = [path2.join(configDir, "skills"), ".claude/skills", ".agents/skills"];
38490
38635
  const skillPaths = [...effectiveSkillExtension?.paths ?? [], ...projectSkillPaths];
@@ -38721,6 +38866,7 @@ var MastraFactory = class {
38721
38866
  workspace: createWorkspaceFactory({
38722
38867
  ...this.#config.sandbox ? { sandbox: this.#config.sandbox } : {},
38723
38868
  ...githubIntegration ? { github: githubIntegration } : {},
38869
+ ...workItemsStorage ? { workItems: workItemsStorage } : {},
38724
38870
  fleet
38725
38871
  }),
38726
38872
  disableGithubSignals: true,