@mastra/factory 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/factory.js +142 -35
  3. package/dist/factory.js.map +1 -1
  4. package/dist/index.js +142 -35
  5. package/dist/index.js.map +1 -1
  6. package/dist/integrations/github/integration.js +1 -1
  7. package/dist/integrations/github/integration.js.map +1 -1
  8. package/dist/integrations/github/routes.js +1 -1
  9. package/dist/integrations/github/routes.js.map +1 -1
  10. package/dist/integrations/platform/api-client.js +1 -1
  11. package/dist/integrations/platform/api-client.js.map +1 -1
  12. package/dist/integrations/platform/github/event-worker.js.map +1 -1
  13. package/dist/integrations/platform/github/integration.js +2 -2
  14. package/dist/integrations/platform/github/integration.js.map +1 -1
  15. package/dist/integrations/platform/linear/integration.js +1 -1
  16. package/dist/integrations/platform/linear/integration.js.map +1 -1
  17. package/dist/routes/config.d.ts +4 -0
  18. package/dist/routes/config.d.ts.map +1 -1
  19. package/dist/routes/config.js +89 -26
  20. package/dist/routes/config.js.map +1 -1
  21. package/dist/routes/surface.d.ts.map +1 -1
  22. package/dist/routes/surface.js +136 -31
  23. package/dist/routes/surface.js.map +1 -1
  24. package/dist/routes/work-items.d.ts.map +1 -1
  25. package/dist/routes/work-items.js +2 -1
  26. package/dist/routes/work-items.js.map +1 -1
  27. package/dist/rules/defaults.d.ts.map +1 -1
  28. package/dist/rules/defaults.js +3 -1
  29. package/dist/rules/defaults.js.map +1 -1
  30. package/dist/rules/github-service.d.ts.map +1 -1
  31. package/dist/rules/github-service.js +10 -2
  32. package/dist/rules/github-service.js.map +1 -1
  33. package/dist/rules/index.js +3 -1
  34. package/dist/rules/index.js.map +1 -1
  35. package/dist/rules/start-coordinator.d.ts +3 -1
  36. package/dist/rules/start-coordinator.d.ts.map +1 -1
  37. package/dist/rules/start-coordinator.js +33 -1
  38. package/dist/rules/start-coordinator.js.map +1 -1
  39. package/dist/server-error.js +1 -1
  40. package/dist/server-error.js.map +1 -1
  41. package/package.json +6 -6
package/CHANGELOG.md CHANGED
@@ -1,5 +1,43 @@
1
1
  # @mastra/factory
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Added guided model-provider setup to Factory onboarding with a recommended default model and provider-specific observational-memory defaults. ([#20079](https://github.com/mastra-ai/mastra/pull/20079))
8
+
9
+ ### Patch Changes
10
+
11
+ - Renamed Mastra Factory server log prefix from "[MastraCode Web]" to "[Mastra Factory]" ([#20088](https://github.com/mastra-ai/mastra/pull/20088))
12
+
13
+ - Link Factory Review cards to their work item when a PR opens without recorded provenance. GitHub PR-opened ingress now falls back to matching the PR head branch against work item session branches, and Review intake records `headBranch`/`baseBranch` metadata so the board and session views can relate the cards. ([#20074](https://github.com/mastra-ai/mastra/pull/20074))
14
+
15
+ - Fixed board-started work sessions to use the Factory's default coding model and persisted observational-memory settings. ([#20081](https://github.com/mastra-ai/mastra/pull/20081))
16
+
17
+ - Restored observational-memory settings so Factory users can choose models and preferences before opening a chat session. ([#20079](https://github.com/mastra-ai/mastra/pull/20079))
18
+
19
+ - Updated dependencies [[`55adddf`](https://github.com/mastra-ai/mastra/commit/55adddfda2a170b00c112bf37d677e8ce5b65d5a)]:
20
+ - @mastra/core@1.52.1
21
+ - @mastra/code-sdk@1.0.1
22
+
23
+ ## 0.2.0-alpha.0
24
+
25
+ ### Minor Changes
26
+
27
+ - Added guided model-provider setup to Factory onboarding with a recommended default model and provider-specific observational-memory defaults. ([#20079](https://github.com/mastra-ai/mastra/pull/20079))
28
+
29
+ ### Patch Changes
30
+
31
+ - Link Factory Review cards to their work item when a PR opens without recorded provenance. GitHub PR-opened ingress now falls back to matching the PR head branch against work item session branches, and Review intake records `headBranch`/`baseBranch` metadata so the board and session views can relate the cards. ([#20074](https://github.com/mastra-ai/mastra/pull/20074))
32
+
33
+ - Fixed board-started work sessions to use the Factory's default coding model and persisted observational-memory settings. ([#20081](https://github.com/mastra-ai/mastra/pull/20081))
34
+
35
+ - Restored observational-memory settings so Factory users can choose models and preferences before opening a chat session. ([#20079](https://github.com/mastra-ai/mastra/pull/20079))
36
+
37
+ - Updated dependencies [[`55adddf`](https://github.com/mastra-ai/mastra/commit/55adddfda2a170b00c112bf37d677e8ce5b65d5a)]:
38
+ - @mastra/core@1.52.1-alpha.0
39
+ - @mastra/code-sdk@1.0.1-alpha.0
40
+
3
41
  ## 0.1.0
4
42
 
5
43
  ### Minor Changes
package/dist/factory.js CHANGED
@@ -26444,7 +26444,7 @@ function buildGithubRoutes(options) {
26444
26444
  list = await github.listInstallationRepos(Number(inst.externalId));
26445
26445
  } catch (err) {
26446
26446
  if (err.status !== 404) throw err;
26447
- console.error(`[MastraCode Web] pruning stale GitHub installation ${inst.externalId} (404 from GitHub)`);
26447
+ console.error(`[Mastra Factory] pruning stale GitHub installation ${inst.externalId} (404 from GitHub)`);
26448
26448
  await github.sourceControlStorage.installations.delete({ orgId: resolved.tenant.orgId, id: inst.id });
26449
26449
  continue;
26450
26450
  }
@@ -27387,7 +27387,7 @@ function logPlatformError(message, fields) {
27387
27387
  }
27388
27388
  function writePlatformLog(level, message, fields) {
27389
27389
  const metadata = fields ? ` ${JSON.stringify(stripUndefined(fields))}` : "";
27390
- process.stderr.write(`[MastraCode Web] ${level.toUpperCase()} ${message}${metadata}
27390
+ process.stderr.write(`[Mastra Factory] ${level.toUpperCase()} ${message}${metadata}
27391
27391
  `);
27392
27392
  }
27393
27393
  function stripUndefined(fields) {
@@ -30392,6 +30392,7 @@ var FactoryGithubEventService = class {
30392
30392
  repositoryId,
30393
30393
  issueNumber,
30394
30394
  pullRequestNumber,
30395
+ string(object(pullRequest?.head)?.ref),
30395
30396
  provenance
30396
30397
  );
30397
30398
  const actor = await githubActor(this.options.github, {
@@ -30486,7 +30487,7 @@ var FactoryGithubEventService = class {
30486
30487
  });
30487
30488
  return { status: committed.status };
30488
30489
  }
30489
- async #relatedItem(orgId, projectId, repositoryId, issueNumber, pullRequestNumber, provenance) {
30490
+ async #relatedItem(orgId, projectId, repositoryId, issueNumber, pullRequestNumber, pullRequestHeadBranch, provenance) {
30490
30491
  const items = await this.options.storage.list({ orgId, factoryProjectId: projectId });
30491
30492
  if (provenance) return items.find((item) => item.id === provenance.workItemId);
30492
30493
  if (issueNumber) {
@@ -30495,7 +30496,14 @@ var FactoryGithubEventService = class {
30495
30496
  if (pullRequestNumber) {
30496
30497
  return items.find((item) => item.externalSource?.externalId === canonicalSourceKey("pull-request", pullRequestNumber)) ?? items.find(
30497
30498
  (item) => item.externalSource?.externalId === legacySourceKey(repositoryId, "pull-request", pullRequestNumber)
30498
- );
30499
+ ) ?? // Provenance fallback: a PR pushed from a work item's session branch
30500
+ // belongs to that item even when no gh-pr-create provenance was
30501
+ // recorded (session predating state seeding, or the PR was opened
30502
+ // outside the tracked tool call). Session branches are per-item
30503
+ // (`factory/issue-N`), so a head-branch match is unambiguous.
30504
+ (pullRequestHeadBranch ? items.find(
30505
+ (item) => item.externalSource?.type !== "pull-request" && Object.values(item.sessions).some((session) => session.branch === pullRequestHeadBranch)
30506
+ ) : void 0);
30499
30507
  }
30500
30508
  return void 0;
30501
30509
  }
@@ -30650,16 +30658,28 @@ async function configureThread(session, request) {
30650
30658
  await Promise.all(Object.entries(settings).map(([key, value]) => session.thread.setSetting({ key, value })));
30651
30659
  return threadId;
30652
30660
  }
30661
+ async function applyMemorySettings(session, record) {
30662
+ if (record?.observerModelId) await session.om.observer.switchModel({ modelId: record.observerModelId });
30663
+ if (record?.reflectorModelId) await session.om.reflector.switchModel({ modelId: record.reflectorModelId });
30664
+ const state = {
30665
+ ...record?.observationThreshold != null ? { observationThreshold: record.observationThreshold } : {},
30666
+ ...record?.reflectionThreshold != null ? { reflectionThreshold: record.reflectionThreshold } : {},
30667
+ ...record?.observeAttachments != null ? { observeAttachments: record.observeAttachments } : {}
30668
+ };
30669
+ if (Object.keys(state).length > 0) await session.state.set(state);
30670
+ }
30653
30671
  var FactoryStartCoordinator = class {
30654
30672
  #controller;
30655
30673
  #storage;
30656
30674
  #transitionService;
30657
30675
  #sourceControl;
30658
- constructor(controller, storage, transitionService, sourceControl) {
30676
+ #memorySettings;
30677
+ constructor(controller, storage, transitionService, sourceControl, memorySettings) {
30659
30678
  this.#controller = controller;
30660
30679
  this.#storage = storage;
30661
30680
  this.#transitionService = transitionService;
30662
30681
  this.#sourceControl = sourceControl;
30682
+ this.#memorySettings = memorySettings;
30663
30683
  }
30664
30684
  async prepare(request) {
30665
30685
  const storage = this.#storage;
@@ -30682,6 +30702,26 @@ var FactoryStartCoordinator = class {
30682
30702
  tags: sessionState
30683
30703
  });
30684
30704
  await session.state.set(sessionState);
30705
+ if (this.#memorySettings) {
30706
+ try {
30707
+ const record = await this.#memorySettings.get({ orgId: request.orgId, userId: request.userId });
30708
+ await applyMemorySettings(session, record);
30709
+ } catch (error) {
30710
+ console.warn("[Factory Start] Failed to apply observational-memory settings", {
30711
+ error: error instanceof Error ? error.message : String(error)
30712
+ });
30713
+ }
30714
+ }
30715
+ if (request.defaultModelId) {
30716
+ try {
30717
+ await session.model.switch({ modelId: request.defaultModelId });
30718
+ } catch (error) {
30719
+ console.warn("[Factory Start] Failed to apply factory default model", {
30720
+ modelId: request.defaultModelId,
30721
+ error: error instanceof Error ? error.message : String(error)
30722
+ });
30723
+ }
30724
+ }
30685
30725
  const threadId = await configureThread(session, request);
30686
30726
  const kickoffMessage = await resolveKickoffMessage(session, request.invocation);
30687
30727
  const prepared = await storage.prepareRunStart({
@@ -31167,6 +31207,16 @@ async function applyPackToSession({
31167
31207
  }
31168
31208
  var DEFAULT_OBSERVATION_THRESHOLD = 3e4;
31169
31209
  var DEFAULT_REFLECTION_THRESHOLD = 4e4;
31210
+ function providerOMModelId(providerId, factoryModelId) {
31211
+ switch (providerId) {
31212
+ case "anthropic":
31213
+ return "anthropic/claude-haiku-4-5";
31214
+ case "openai":
31215
+ return "openai/gpt-5.4-mini";
31216
+ default:
31217
+ return factoryModelId || DEFAULT_OM_MODEL_ID;
31218
+ }
31219
+ }
31170
31220
  function readOMConfig(session) {
31171
31221
  const state = session.state.get() ?? {};
31172
31222
  const observeAttachments = state.observeAttachments;
@@ -31178,6 +31228,15 @@ function readOMConfig(session) {
31178
31228
  observeAttachments: observeAttachments === true || observeAttachments === false ? observeAttachments : "auto"
31179
31229
  };
31180
31230
  }
31231
+ function readStoredOMConfig(record) {
31232
+ return {
31233
+ observerModelId: record?.observerModelId ?? DEFAULT_OM_MODEL_ID,
31234
+ reflectorModelId: record?.reflectorModelId ?? DEFAULT_OM_MODEL_ID,
31235
+ observationThreshold: record?.observationThreshold ?? DEFAULT_OBSERVATION_THRESHOLD,
31236
+ reflectionThreshold: record?.reflectionThreshold ?? DEFAULT_REFLECTION_THRESHOLD,
31237
+ observeAttachments: record?.observeAttachments ?? "auto"
31238
+ };
31239
+ }
31181
31240
  async function resolveMemorySettingsContext({
31182
31241
  c,
31183
31242
  auth,
@@ -31587,19 +31646,60 @@ var ConfigRoutes = class extends Route {
31587
31646
  }
31588
31647
  }
31589
31648
  }),
31649
+ registerApiRoute7("/web/config/om/provider-defaults", {
31650
+ method: "POST",
31651
+ requiresAuth: false,
31652
+ handler: async (c) => {
31653
+ let body;
31654
+ try {
31655
+ body = await c.req.json();
31656
+ } catch {
31657
+ return c.json({ error: "Invalid JSON body" }, 400);
31658
+ }
31659
+ const providerId = typeof body.providerId === "string" ? body.providerId.trim() : "";
31660
+ const factoryModelId = typeof body.factoryModelId === "string" ? body.factoryModelId.trim() : "";
31661
+ if (!providerId) return c.json({ error: "Missing required field: providerId" }, 400);
31662
+ const context = await resolveMemorySettingsContext({
31663
+ c: loose6(c),
31664
+ auth,
31665
+ memorySettings: options.memorySettings
31666
+ });
31667
+ if ("response" in context) return context.response;
31668
+ try {
31669
+ const tenantCredentials = await listTenantCredentialsForRequest({
31670
+ c: loose6(c),
31671
+ auth,
31672
+ credentials: options.modelCredentials
31673
+ });
31674
+ const access = await buildProviderAccess({
31675
+ controller,
31676
+ authStorage: tenantCredentials ? void 0 : authStorage,
31677
+ tenantCredentials
31678
+ });
31679
+ if (!access[providerId]) return c.json({ error: `Provider "${providerId}" is not configured` }, 400);
31680
+ const modelId = providerOMModelId(providerId, factoryModelId);
31681
+ const record = await context.storage.patch({
31682
+ orgId: context.orgId,
31683
+ userId: context.userId,
31684
+ patch: {},
31685
+ fillIfUnset: { observerModelId: modelId, reflectorModelId: modelId }
31686
+ });
31687
+ return c.json({ ok: true, config: readStoredOMConfig(record) });
31688
+ } catch (error) {
31689
+ return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);
31690
+ }
31691
+ }
31692
+ }),
31590
31693
  // ── Observational memory ──────────────────────────────────────────────────
31591
- // Mirrors the TUI's /om command. All five knobs are session-scoped (resolved
31592
- // from the session, persisted to its state + thread setting) and durably
31593
- // stored in the per-(org, user) `memory-settings` app table never
31594
- // settings.json. GET hydrates the session from the stored row first so the
31595
- // DB, not the SDK's boot-time seed, is the source of truth.
31694
+ // Mirrors the TUI's /om command. All five knobs are durably stored in the
31695
+ // per-(org, user) `memory-settings` app table never settings.json. When a
31696
+ // session is supplied, changes are also applied to its state and thread.
31596
31697
  registerApiRoute7("/web/config/om", {
31597
31698
  method: "GET",
31598
31699
  requiresAuth: false,
31599
31700
  handler: async (c) => {
31600
31701
  const resourceId = c.req.query("resourceId");
31601
31702
  const scope = c.req.query("scope") || void 0;
31602
- if (!resourceId) return c.json({ error: "Missing required query param: resourceId" }, 400);
31603
31703
  const context = await resolveMemorySettingsContext({
31604
31704
  c: loose6(c),
31605
31705
  auth,
@@ -31607,9 +31707,10 @@ var ConfigRoutes = class extends Route {
31607
31707
  });
31608
31708
  if ("response" in context) return context.response;
31609
31709
  try {
31710
+ const record = await context.storage.get({ orgId: context.orgId, userId: context.userId });
31711
+ if (!resourceId) return c.json({ config: readStoredOMConfig(record) });
31610
31712
  const session = await controller.getSessionByResource?.(resourceId, scope);
31611
31713
  if (!session) return c.json({ error: `No session for resourceId "${resourceId}"` }, 404);
31612
- const record = await context.storage.get({ orgId: context.orgId, userId: context.userId });
31613
31714
  await hydrateSessionMemorySettings(session, record);
31614
31715
  return c.json({ config: readOMConfig(session) });
31615
31716
  } catch (error) {
@@ -31634,7 +31735,6 @@ var ConfigRoutes = class extends Route {
31634
31735
  const resourceId = typeof body.resourceId === "string" ? body.resourceId : "";
31635
31736
  const scope = typeof body.scope === "string" && body.scope ? body.scope : void 0;
31636
31737
  const modelId = typeof body.modelId === "string" ? body.modelId.trim() : "";
31637
- if (!resourceId) return c.json({ error: "Missing required field: resourceId" }, 400);
31638
31738
  if (!modelId) return c.json({ error: "Missing required field: modelId" }, 400);
31639
31739
  const context = await resolveMemorySettingsContext({
31640
31740
  c: loose6(c),
@@ -31643,18 +31743,19 @@ var ConfigRoutes = class extends Route {
31643
31743
  });
31644
31744
  if ("response" in context) return context.response;
31645
31745
  try {
31646
- const session = await controller.getSessionByResource?.(resourceId, scope);
31647
- if (!session) return c.json({ error: `No session for resourceId "${resourceId}"` }, 404);
31648
- const otherRole = role === "observer" ? session.om.reflector : session.om.observer;
31649
- const otherRoleCurrentModelId = otherRole.modelId() ?? null;
31650
- await session.om[role].switchModel({ modelId });
31746
+ const session = resourceId ? await controller.getSessionByResource?.(resourceId, scope) : void 0;
31747
+ if (resourceId && !session) return c.json({ error: `No session for resourceId "${resourceId}"` }, 404);
31748
+ const otherRole = session ? role === "observer" ? session.om.reflector : session.om.observer : void 0;
31749
+ const otherRoleCurrentModelId = otherRole?.modelId() ?? null;
31750
+ await session?.om[role].switchModel({ modelId });
31651
31751
  const otherKey = role === "observer" ? "reflectorModelId" : "observerModelId";
31652
31752
  await persistMemorySettings(
31653
31753
  context,
31654
31754
  { [role === "observer" ? "observerModelId" : "reflectorModelId"]: modelId },
31655
31755
  otherRoleCurrentModelId ? { [otherKey]: otherRoleCurrentModelId } : void 0
31656
31756
  );
31657
- return c.json({ ok: true, config: readOMConfig(session) });
31757
+ const config = session ? readOMConfig(session) : readStoredOMConfig(await context.storage.get({ orgId: context.orgId, userId: context.userId }));
31758
+ return c.json({ ok: true, config });
31658
31759
  } catch (error) {
31659
31760
  return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);
31660
31761
  }
@@ -31672,7 +31773,6 @@ var ConfigRoutes = class extends Route {
31672
31773
  }
31673
31774
  const resourceId = typeof body.resourceId === "string" ? body.resourceId : "";
31674
31775
  const scope = typeof body.scope === "string" && body.scope ? body.scope : void 0;
31675
- if (!resourceId) return c.json({ error: "Missing required field: resourceId" }, 400);
31676
31776
  const observation = typeof body.observationThreshold === "number" && body.observationThreshold > 0 ? Math.round(body.observationThreshold) : void 0;
31677
31777
  const reflection = typeof body.reflectionThreshold === "number" && body.reflectionThreshold > 0 ? Math.round(body.reflectionThreshold) : void 0;
31678
31778
  if (observation === void 0 && reflection === void 0) {
@@ -31685,13 +31785,13 @@ var ConfigRoutes = class extends Route {
31685
31785
  });
31686
31786
  if ("response" in context) return context.response;
31687
31787
  try {
31688
- const session = await controller.getSessionByResource?.(resourceId, scope);
31689
- if (!session) return c.json({ error: `No session for resourceId "${resourceId}"` }, 404);
31690
- if (observation !== void 0) {
31788
+ const session = resourceId ? await controller.getSessionByResource?.(resourceId, scope) : void 0;
31789
+ if (resourceId && !session) return c.json({ error: `No session for resourceId "${resourceId}"` }, 404);
31790
+ if (observation !== void 0 && session) {
31691
31791
  await session.state.set({ observationThreshold: observation });
31692
31792
  await session.thread.setSetting({ key: "observationThreshold", value: observation });
31693
31793
  }
31694
- if (reflection !== void 0) {
31794
+ if (reflection !== void 0 && session) {
31695
31795
  await session.state.set({ reflectionThreshold: reflection });
31696
31796
  await session.thread.setSetting({ key: "reflectionThreshold", value: reflection });
31697
31797
  }
@@ -31699,7 +31799,8 @@ var ConfigRoutes = class extends Route {
31699
31799
  ...observation !== void 0 ? { observationThreshold: observation } : {},
31700
31800
  ...reflection !== void 0 ? { reflectionThreshold: reflection } : {}
31701
31801
  });
31702
- return c.json({ ok: true, config: readOMConfig(session) });
31802
+ const config = session ? readOMConfig(session) : readStoredOMConfig(await context.storage.get({ orgId: context.orgId, userId: context.userId }));
31803
+ return c.json({ ok: true, config });
31703
31804
  } catch (error) {
31704
31805
  return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);
31705
31806
  }
@@ -31717,7 +31818,6 @@ var ConfigRoutes = class extends Route {
31717
31818
  }
31718
31819
  const resourceId = typeof body.resourceId === "string" ? body.resourceId : "";
31719
31820
  const scope = typeof body.scope === "string" && body.scope ? body.scope : void 0;
31720
- if (!resourceId) return c.json({ error: "Missing required field: resourceId" }, 400);
31721
31821
  const raw = body.value;
31722
31822
  const value = raw === "auto" || raw === true || raw === false ? raw : "auto";
31723
31823
  if (raw !== "auto" && raw !== true && raw !== false) {
@@ -31730,12 +31830,15 @@ var ConfigRoutes = class extends Route {
31730
31830
  });
31731
31831
  if ("response" in context) return context.response;
31732
31832
  try {
31733
- const session = await controller.getSessionByResource?.(resourceId, scope);
31734
- if (!session) return c.json({ error: `No session for resourceId "${resourceId}"` }, 404);
31735
- await session.state.set({ observeAttachments: value });
31736
- await session.thread.setSetting({ key: "observeAttachments", value });
31833
+ const session = resourceId ? await controller.getSessionByResource?.(resourceId, scope) : void 0;
31834
+ if (resourceId && !session) return c.json({ error: `No session for resourceId "${resourceId}"` }, 404);
31835
+ if (session) {
31836
+ await session.state.set({ observeAttachments: value });
31837
+ await session.thread.setSetting({ key: "observeAttachments", value });
31838
+ }
31737
31839
  await persistMemorySettings(context, { observeAttachments: value });
31738
- return c.json({ ok: true, config: readOMConfig(session) });
31840
+ const config = session ? readOMConfig(session) : readStoredOMConfig(await context.storage.get({ orgId: context.orgId, userId: context.userId }));
31841
+ return c.json({ ok: true, config });
31739
31842
  } catch (error) {
31740
31843
  return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);
31741
31844
  }
@@ -34778,7 +34881,7 @@ var WorkItemRoutes = class extends Route {
34778
34881
  if (!project) {
34779
34882
  return { response: c.json({ error: "Project not found" }, 404) };
34780
34883
  }
34781
- return { ...tenant, factoryProjectId: projectId };
34884
+ return { ...tenant, factoryProjectId: projectId, defaultModelId: project.defaultModelId };
34782
34885
  }
34783
34886
  /**
34784
34887
  * Emit the audit events a successful work-item PATCH implies: always
@@ -35063,6 +35166,7 @@ var WorkItemRoutes = class extends Route {
35063
35166
  const input = parseStartBody(await readJson2(loose10(c)), resolved, resolved.factoryProjectId);
35064
35167
  if (!input) return c.json({ error: "invalid_factory_start" }, 400);
35065
35168
  input.requestContext = loose10(c).get("requestContext");
35169
+ input.defaultModelId = resolved.defaultModelId ?? void 0;
35066
35170
  if (!input.workItem.id && ((input.workItem.input.stages ?? ["intake"]).length !== 1 || (input.workItem.input.stages ?? ["intake"])[0] !== "intake")) {
35067
35171
  return c.json(
35068
35172
  { error: "governed_transition_required", message: "Create the work item in Intake before starting it." },
@@ -35357,7 +35461,8 @@ function assembleFactoryApiRoutes(deps) {
35357
35461
  deps.controller,
35358
35462
  deps.domains.workItems,
35359
35463
  transitionService,
35360
- githubIntegration?.sourceControlStorage
35464
+ githubIntegration?.sourceControlStorage,
35465
+ deps.domains.memorySettings
35361
35466
  ) : void 0;
35362
35467
  if (transitionService && startCoordinator) {
35363
35468
  deps.onFactoryRuntime?.({
@@ -35514,7 +35619,9 @@ function pullRequestOpened(context) {
35514
35619
  metadata: {
35515
35620
  githubRepositoryId: context.repository.id,
35516
35621
  githubPullRequestNumber: context.pullRequest.number,
35517
- factoryAuthored: context.actor.type === "github" && context.actor.factoryAuthored
35622
+ factoryAuthored: context.actor.type === "github" && context.actor.factoryAuthored,
35623
+ headBranch: context.pullRequest.headBranch,
35624
+ baseBranch: context.pullRequest.baseBranch
35518
35625
  }
35519
35626
  };
35520
35627
  }
@@ -36520,7 +36627,7 @@ function handleServerError(err, c) {
36520
36627
  return c.json({ error: err.message }, err.status);
36521
36628
  }
36522
36629
  const detail = err instanceof Error ? err.stack ?? err.message : String(err);
36523
- console.error(`[MastraCode Web] ${c.req.method} ${c.req.path} failed: ${detail}`);
36630
+ console.error(`[Mastra Factory] ${c.req.method} ${c.req.path} failed: ${detail}`);
36524
36631
  return c.json(
36525
36632
  {
36526
36633
  error: "internal_error",