@mastra/code-sdk 1.2.0-alpha.9 → 1.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 (132) hide show
  1. package/CHANGELOG.md +227 -0
  2. package/README.md +22 -0
  3. package/dist/agents/model.d.ts.map +1 -1
  4. package/dist/agents/model.js +5 -2
  5. package/dist/agents/model.js.map +1 -1
  6. package/dist/agents/modes/build.d.ts.map +1 -1
  7. package/dist/agents/modes/build.js +6 -1
  8. package/dist/agents/modes/build.js.map +1 -1
  9. package/dist/agents/modes/explore.d.ts.map +1 -1
  10. package/dist/agents/modes/explore.js +4 -1
  11. package/dist/agents/modes/explore.js.map +1 -1
  12. package/dist/agents/modes/plan.d.ts.map +1 -1
  13. package/dist/agents/modes/plan.js +8 -3
  14. package/dist/agents/modes/plan.js.map +1 -1
  15. package/dist/agents/prompts/index.d.ts.map +1 -1
  16. package/dist/agents/prompts/index.js +4 -1
  17. package/dist/agents/prompts/index.js.map +1 -1
  18. package/dist/agents/prompts/plan.d.ts +1 -1
  19. package/dist/agents/prompts/plan.d.ts.map +1 -1
  20. package/dist/agents/prompts/plan.js +2 -2
  21. package/dist/agents/prompts/plan.js.map +1 -1
  22. package/dist/agents/prompts/tool-guidance.d.ts +2 -0
  23. package/dist/agents/prompts/tool-guidance.d.ts.map +1 -1
  24. package/dist/agents/prompts/tool-guidance.js +3 -2
  25. package/dist/agents/prompts/tool-guidance.js.map +1 -1
  26. package/dist/agents/tool-availability.d.ts.map +1 -1
  27. package/dist/agents/tool-availability.js +15 -6
  28. package/dist/agents/tool-availability.js.map +1 -1
  29. package/dist/agents/tools.d.ts +16 -0
  30. package/dist/agents/tools.d.ts.map +1 -1
  31. package/dist/agents/tools.js +16 -3
  32. package/dist/agents/tools.js.map +1 -1
  33. package/dist/agents/workflow-builder-agent.d.ts +2 -0
  34. package/dist/agents/workflow-builder-agent.d.ts.map +1 -0
  35. package/dist/agents/workflow-builder-agent.js +80 -0
  36. package/dist/agents/workflow-builder-agent.js.map +1 -0
  37. package/dist/headless/cli.d.ts.map +1 -1
  38. package/dist/headless/cli.js +3 -0
  39. package/dist/headless/cli.js.map +1 -1
  40. package/dist/hooks/manager.d.ts +9 -2
  41. package/dist/hooks/manager.d.ts.map +1 -1
  42. package/dist/hooks/manager.js +19 -3
  43. package/dist/hooks/manager.js.map +1 -1
  44. package/dist/hooks/types.d.ts +20 -0
  45. package/dist/hooks/types.d.ts.map +1 -1
  46. package/dist/hooks/types.js.map +1 -1
  47. package/dist/index.d.ts +73 -0
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +204 -69
  50. package/dist/index.js.map +1 -1
  51. package/dist/permissions.d.ts.map +1 -1
  52. package/dist/permissions.js +6 -1
  53. package/dist/permissions.js.map +1 -1
  54. package/dist/plugin.d.ts +64 -1
  55. package/dist/plugin.d.ts.map +1 -1
  56. package/dist/plugin.js +3 -1
  57. package/dist/plugin.js.map +1 -1
  58. package/dist/plugins/loader.d.ts +7 -3
  59. package/dist/plugins/loader.d.ts.map +1 -1
  60. package/dist/plugins/loader.js +53 -1
  61. package/dist/plugins/loader.js.map +1 -1
  62. package/dist/plugins/manager.d.ts +36 -2
  63. package/dist/plugins/manager.d.ts.map +1 -1
  64. package/dist/plugins/manager.js +74 -2
  65. package/dist/plugins/manager.js.map +1 -1
  66. package/dist/plugins/signal-lane.d.ts +58 -0
  67. package/dist/plugins/signal-lane.d.ts.map +1 -0
  68. package/dist/plugins/signal-lane.js +166 -0
  69. package/dist/plugins/signal-lane.js.map +1 -0
  70. package/dist/plugins/types.d.ts +36 -0
  71. package/dist/plugins/types.d.ts.map +1 -1
  72. package/dist/tools/workflows/create-workflow.d.ts +7 -0
  73. package/dist/tools/workflows/create-workflow.d.ts.map +1 -0
  74. package/dist/tools/workflows/create-workflow.js +81 -0
  75. package/dist/tools/workflows/create-workflow.js.map +1 -0
  76. package/dist/tools/workflows/delete-workflow.d.ts +7 -0
  77. package/dist/tools/workflows/delete-workflow.d.ts.map +1 -0
  78. package/dist/tools/workflows/delete-workflow.js +21 -0
  79. package/dist/tools/workflows/delete-workflow.js.map +1 -0
  80. package/dist/tools/workflows/ephemeral-memory.d.ts +7 -0
  81. package/dist/tools/workflows/ephemeral-memory.d.ts.map +1 -0
  82. package/dist/tools/workflows/ephemeral-memory.js +45 -0
  83. package/dist/tools/workflows/ephemeral-memory.js.map +1 -0
  84. package/dist/tools/workflows/extract-json-schema.d.ts +12 -0
  85. package/dist/tools/workflows/extract-json-schema.d.ts.map +1 -0
  86. package/dist/tools/workflows/extract-json-schema.js +22 -0
  87. package/dist/tools/workflows/extract-json-schema.js.map +1 -0
  88. package/dist/tools/workflows/get-workflow.d.ts +11 -0
  89. package/dist/tools/workflows/get-workflow.d.ts.map +1 -0
  90. package/dist/tools/workflows/get-workflow.js +34 -0
  91. package/dist/tools/workflows/get-workflow.js.map +1 -0
  92. package/dist/tools/workflows/list-available-agents.d.ts +8 -0
  93. package/dist/tools/workflows/list-available-agents.d.ts.map +1 -0
  94. package/dist/tools/workflows/list-available-agents.js +32 -0
  95. package/dist/tools/workflows/list-available-agents.js.map +1 -0
  96. package/dist/tools/workflows/list-available-tools.d.ts +9 -0
  97. package/dist/tools/workflows/list-available-tools.d.ts.map +1 -0
  98. package/dist/tools/workflows/list-available-tools.js +40 -0
  99. package/dist/tools/workflows/list-available-tools.js.map +1 -0
  100. package/dist/tools/workflows/list-available-workflows.d.ts +9 -0
  101. package/dist/tools/workflows/list-available-workflows.d.ts.map +1 -0
  102. package/dist/tools/workflows/list-available-workflows.js +32 -0
  103. package/dist/tools/workflows/list-available-workflows.js.map +1 -0
  104. package/dist/tools/workflows/list-workflows.d.ts +9 -0
  105. package/dist/tools/workflows/list-workflows.d.ts.map +1 -0
  106. package/dist/tools/workflows/list-workflows.js +33 -0
  107. package/dist/tools/workflows/list-workflows.js.map +1 -0
  108. package/dist/tools/workflows/run-workflow.d.ts +9 -0
  109. package/dist/tools/workflows/run-workflow.d.ts.map +1 -0
  110. package/dist/tools/workflows/run-workflow.js +52 -0
  111. package/dist/tools/workflows/run-workflow.js.map +1 -0
  112. package/dist/tools/workflows/save-workflow.d.ts +369 -0
  113. package/dist/tools/workflows/save-workflow.d.ts.map +1 -0
  114. package/dist/tools/workflows/save-workflow.js +28 -0
  115. package/dist/tools/workflows/save-workflow.js.map +1 -0
  116. package/dist/tools/workflows/tool-ids.d.ts +15 -0
  117. package/dist/tools/workflows/tool-ids.d.ts.map +1 -0
  118. package/dist/tools/workflows/tool-ids.js +19 -0
  119. package/dist/tools/workflows/tool-ids.js.map +1 -0
  120. package/dist/utils/plans.d.ts +9 -6
  121. package/dist/utils/plans.d.ts.map +1 -1
  122. package/dist/utils/plans.js +11 -11
  123. package/dist/utils/plans.js.map +1 -1
  124. package/dist/workflows/register-primitives.d.ts +52 -0
  125. package/dist/workflows/register-primitives.d.ts.map +1 -0
  126. package/dist/workflows/register-primitives.js +39 -0
  127. package/dist/workflows/register-primitives.js.map +1 -0
  128. package/dist/workflows/service.d.ts +64 -0
  129. package/dist/workflows/service.d.ts.map +1 -0
  130. package/dist/workflows/service.js +53 -0
  131. package/dist/workflows/service.js.map +1 -0
  132. package/package.json +16 -16
package/dist/index.js CHANGED
@@ -29,6 +29,7 @@ import { hasExplicitOMConfiguration } from "./onboarding/om-settings.js";
29
29
  import { getAvailableModePacks, getAvailableOmPacks, selectPreferredOMPack } from "./onboarding/packs.js";
30
30
  import { getToolCategory } from "./permissions.js";
31
31
  import { PluginManager } from "./plugins/manager.js";
32
+ import { PluginSignalLane } from "./plugins/signal-lane.js";
32
33
  import { PlanRejectionAbortProcessor } from "./processors/plan-rejection-abort.js";
33
34
  import { stateSchema } from "./schema.js";
34
35
  import { mastraBrand } from "./theme-palette.js";
@@ -37,6 +38,7 @@ import { createSignalsPubSub } from "./utils/signals-pubsub.js";
37
38
  import { DEFAULT_RETENTION, createStorageMaintenance, resolveLocalDbFiles } from "./utils/storage-maintenance.js";
38
39
  import { createStorage, createVectorStore } from "./utils/storage-factory.js";
39
40
  import { acquireThreadLock, releaseThreadLock } from "./utils/thread-lock.js";
41
+ import { registerWorkflowBuilderPrimitives } from "./workflows/register-primitives.js";
40
42
  import { autoApprovePolicy, denyPolicy, permissionModeToPolicy } from "./headless/policy.js";
41
43
  import { runMC } from "./headless/run-mc.js";
42
44
  import { formatHuman, formatJsonl, renderJsonResult, renderTextResult } from "./headless/format.js";
@@ -50,6 +52,7 @@ import { AgentController } from "@mastra/core/agent-controller";
50
52
  import { createCodingAgent } from "@mastra/core/coding-agent";
51
53
  import { PROVIDER_REGISTRY } from "@mastra/core/llm";
52
54
  import { Mastra } from "@mastra/core/mastra";
55
+ import { defaultNotificationDeliveryDecision } from "@mastra/core/notifications";
53
56
  import { AgentsMDInjector, PrefillErrorHandler, ProviderHistoryCompat, StreamErrorRetryProcessor, isBadRequestError } from "@mastra/core/processors";
54
57
  import { RequestContext } from "@mastra/core/request-context";
55
58
  import { InMemoryHarness, MastraCompositeStore } from "@mastra/core/storage";
@@ -201,6 +204,7 @@ async function createMastraCodeAgentController(config) {
201
204
  const homeDir = config?.homeDir ?? config?.initialState?.homeDir;
202
205
  const configDir = config?.configDir ?? ".mastracode";
203
206
  let activeSession;
207
+ let pluginRuntimeController;
204
208
  if (configDir !== ".mastracode") validateConfigDirName(configDir);
205
209
  try {
206
210
  process.loadEnvFile(path.join(cwd, ".env"));
@@ -314,66 +318,136 @@ async function createMastraCodeAgentController(config) {
314
318
  });
315
319
  const memory = config?.memory === false ? void 0 : config?.memory ?? getDynamicMemory(storage, vector);
316
320
  const mcpManager = config?.disableMcp ? void 0 : createMcpManager(project.rootPath, configDir, config?.mcpServers);
317
- const hookManager = config?.disableHooks ? void 0 : new HookManager(project.rootPath, "session-init", configDir, homeDir);
321
+ const hookManager = config?.disableHooks ? void 0 : new HookManager(project.rootPath, "session-init", configDir, homeDir, project.isWorktree ? {
322
+ path: project.rootPath,
323
+ branch: project.gitBranch,
324
+ mainRepoPath: project.mainRepoPath
325
+ } : void 0);
318
326
  const pluginManager = config?.disablePlugins ? void 0 : config?.pluginManager ?? new PluginManager({
319
327
  projectRoot: project.rootPath,
320
328
  configDir,
321
329
  homeDir
322
330
  });
331
+ pluginManager?.setRuntime({
332
+ getController: () => pluginRuntimeController,
333
+ getActiveSession: () => activeSession
334
+ });
323
335
  const loadedPlugins = pluginManager ? await pluginManager.reload() : [];
324
336
  const pluginTools = pluginManager?.getPluginTools() ?? {};
325
337
  const outcomeScorer = createOutcomeScorer();
326
338
  const efficiencyScorer = createEfficiencyScorer();
339
+ const getNotificationStreamOptions = async ({ resourceId, threadId }) => {
340
+ const session = await controller.getSessionByResource(resourceId) ?? activeSession;
341
+ if (!session) return void 0;
342
+ const modeId = session.mode.get();
343
+ const defaultModeModelId = controller.listModes().find((mode) => mode.id === modeId)?.defaultModelId;
344
+ const modelId = session.model.get() || activeSession?.model.get() || defaultModeModelId || "";
345
+ const requestContext = new RequestContext();
346
+ const agentControllerContext = {
347
+ controllerId: controller.id,
348
+ state: session.state.get(),
349
+ getState: () => session.state.get(),
350
+ setState: (updates) => session.state.set(updates),
351
+ threadId,
352
+ resourceId,
353
+ session: {
354
+ id: session.identity.getId(),
355
+ ownerId: session.identity.getOwnerId(),
356
+ modeId,
357
+ modelId,
358
+ state: {
359
+ get: () => session.state.get(),
360
+ set: (updates) => session.state.set(updates),
361
+ update: (updater) => session.state.update(updater)
362
+ }
363
+ },
364
+ workspace: session.getWorkspace(),
365
+ getSubagentModelId: (params) => session.subagents.model.get(params ?? {})
366
+ };
367
+ requestContext.set("controller", agentControllerContext);
368
+ return {
369
+ memory: {
370
+ thread: threadId,
371
+ resource: resourceId
372
+ },
373
+ requestContext,
374
+ maxSteps: 1e3,
375
+ savePerStep: false,
376
+ requireToolApproval: session.state.get().yolo !== true,
377
+ modelSettings: { temperature: 1 }
378
+ };
379
+ };
327
380
  const githubSignals = globalSettings.signals?.experimentalGithubSignals && !config?.disableGithubSignals ? new GithubSignals({
328
381
  cwd: project.rootPath,
329
382
  gitcrawlCommand: process.env.MASTRACODE_GITCRAWL_BIN ?? process.env.GITCRAWL_BIN ?? process.env.MASTRACODE_GITCRAWL_COMMAND ?? process.env.GITCRAWL_COMMAND,
330
- getNotificationStreamOptions: async ({ resourceId, threadId }) => {
331
- const session = await controller.getSessionByResource(resourceId) ?? activeSession;
332
- const modeId = session.mode.get();
333
- const defaultModeModelId = controller.listModes().find((mode) => mode.id === modeId)?.defaultModelId;
334
- const modelId = session.model.get() || activeSession?.model.get() || defaultModeModelId || "";
335
- const requestContext = new RequestContext();
336
- const agentControllerContext = {
337
- controllerId: controller.id,
338
- state: session.state.get(),
339
- getState: () => session.state.get(),
340
- setState: (updates) => session.state.set(updates),
341
- threadId,
342
- resourceId,
343
- session: {
344
- id: session.identity.getId(),
345
- ownerId: session.identity.getOwnerId(),
346
- modeId,
347
- modelId,
348
- state: {
349
- get: () => session.state.get(),
350
- set: (updates) => session.state.set(updates),
351
- update: (updater) => session.state.update(updater)
352
- }
353
- },
354
- workspace: controller.getWorkspace(),
355
- getSubagentModelId: (params) => session.subagents.model.get(params ?? {})
356
- };
357
- requestContext.set("controller", agentControllerContext);
358
- return {
359
- memory: {
360
- thread: threadId,
361
- resource: resourceId
362
- },
363
- requestContext,
364
- maxSteps: 1e3,
365
- savePerStep: false,
366
- requireToolApproval: session.state.get().yolo !== true,
367
- modelSettings: { temperature: 1 }
368
- };
369
- }
383
+ getNotificationStreamOptions
370
384
  }) : void 0;
385
+ const mastraCodeInputProcessors = [
386
+ ...config?.inputProcessors ?? [],
387
+ new PlanRejectionAbortProcessor(),
388
+ new AgentsMDInjector({
389
+ isEnabled: ({ requestContext }) => {
390
+ const state = getInjectorSessionState(requestContext);
391
+ return state?.untrustedCheckout !== true || typeof state?.baseRef === "string";
392
+ },
393
+ getReader: ({ requestContext }) => {
394
+ const state = getInjectorSessionState(requestContext);
395
+ if (state?.untrustedCheckout !== true || typeof state?.baseRef !== "string") return void 0;
396
+ return createGitRefReminderReader(state?.projectPath ?? project.rootPath, state.baseRef);
397
+ },
398
+ getIgnoredInstructionPaths: ({ requestContext }) => {
399
+ const state = getInjectorSessionState(requestContext);
400
+ const projectPath = state?.projectPath ?? project.rootPath;
401
+ return getStaticallyLoadedInstructionPaths(projectPath, void 0, state?.untrustedCheckout === true && typeof state?.baseRef === "string" ? createGitRefInstructionReader(projectPath, state.baseRef) : void 0);
402
+ }
403
+ }),
404
+ new ProviderHistoryCompat()
405
+ ];
406
+ const taskSignalProvider = new TaskSignalProvider();
407
+ const NO_PLUGIN_PROCESSORS = {
408
+ input: [],
409
+ output: []
410
+ };
411
+ let pluginProcessorReadWarned = false;
412
+ const pluginSignalLane = pluginManager ? new PluginSignalLane({ reservedProviderIds: [taskSignalProvider.id, ...githubSignals ? [githubSignals.id] : []] }) : void 0;
413
+ let unsubscribePluginReload;
414
+ /**
415
+ * Plugin processors are read through a function so that enabling, disabling or
416
+ * updating a plugin takes effect on the next request rather than requiring a
417
+ * new agent. This runs before every LLM call, and also outside the request
418
+ * path when the Agent catalogues its configured processors — where a throw is
419
+ * swallowed into a debug log. So it only reads already-resolved state: no
420
+ * filesystem, no network, no construction, and it never throws.
421
+ */
422
+ const readPluginProcessors = () => {
423
+ try {
424
+ return pluginManager?.getPluginProcessors() ?? NO_PLUGIN_PROCESSORS;
425
+ } catch (error) {
426
+ if (!pluginProcessorReadWarned) {
427
+ pluginProcessorReadWarned = true;
428
+ console.warn("Failed to read plugin processors:", error);
429
+ }
430
+ return NO_PLUGIN_PROCESSORS;
431
+ }
432
+ };
371
433
  const codeAgent = createCodingAgent({
372
434
  id: CODE_AGENT_ID,
373
435
  name: "Code Agent",
374
436
  workspace: void 0,
375
437
  instructions: getDynamicInstructions,
376
438
  model: (ctx) => getDynamicModel(ctx, config?.settingsPath),
439
+ notifications: { deliveryPolicy: { decide: async (input) => {
440
+ const decision = defaultNotificationDeliveryDecision(input);
441
+ if (!input.record.resourceId) return decision;
442
+ const streamOptions = await getNotificationStreamOptions({
443
+ resourceId: input.record.resourceId,
444
+ threadId: input.record.threadId
445
+ });
446
+ return streamOptions ? {
447
+ ...decision,
448
+ streamOptions
449
+ } : decision;
450
+ } } },
377
451
  tools: createDynamicTools(mcpManager, config?.extraTools, config?.disabledTools, storage, pluginTools),
378
452
  hooks: createToolHooks(hookManager, config?.postToolObserver),
379
453
  scorers: {
@@ -389,7 +463,7 @@ async function createMastraCodeAgentController(config) {
389
463
  }
390
464
  }
391
465
  },
392
- signals: [new TaskSignalProvider(), ...githubSignals ? [githubSignals] : []],
466
+ signals: [taskSignalProvider, ...githubSignals ? [githubSignals] : []],
393
467
  goal: {
394
468
  judge: (ctx) => getGoalJudgeModel(ctx, config?.settingsPath),
395
469
  maxRuns: globalSettings.models.goalMaxTurns ?? 50,
@@ -397,27 +471,12 @@ async function createMastraCodeAgentController(config) {
397
471
  prompt: DEFAULT_GOAL_JUDGE_PROMPT,
398
472
  tools: getGoalJudgeTools
399
473
  },
400
- inputProcessors: [
401
- ...config?.inputProcessors ?? [],
402
- new PlanRejectionAbortProcessor(),
403
- new AgentsMDInjector({
404
- isEnabled: ({ requestContext }) => {
405
- const state = getInjectorSessionState(requestContext);
406
- return state?.untrustedCheckout !== true || typeof state?.baseRef === "string";
407
- },
408
- getReader: ({ requestContext }) => {
409
- const state = getInjectorSessionState(requestContext);
410
- if (state?.untrustedCheckout !== true || typeof state?.baseRef !== "string") return void 0;
411
- return createGitRefReminderReader(state?.projectPath ?? project.rootPath, state.baseRef);
412
- },
413
- getIgnoredInstructionPaths: ({ requestContext }) => {
414
- const state = getInjectorSessionState(requestContext);
415
- const projectPath = state?.projectPath ?? project.rootPath;
416
- return getStaticallyLoadedInstructionPaths(projectPath, void 0, state?.untrustedCheckout === true && typeof state?.baseRef === "string" ? createGitRefInstructionReader(projectPath, state.baseRef) : void 0);
417
- }
418
- }),
419
- new ProviderHistoryCompat()
474
+ inputProcessors: () => [
475
+ ...mastraCodeInputProcessors,
476
+ ...readPluginProcessors().input.map((entry) => entry.value),
477
+ ...pluginSignalLane?.getInputProcessors() ?? []
420
478
  ],
479
+ outputProcessors: () => [...readPluginProcessors().output.map((entry) => entry.value), ...pluginSignalLane?.getOutputProcessors() ?? []],
421
480
  errorProcessors: [
422
481
  new ProviderHistoryCompat(),
423
482
  new StreamErrorRetryProcessor({ matchers: [
@@ -566,6 +625,11 @@ async function createMastraCodeAgentController(config) {
566
625
  release: releaseThreadLock
567
626
  }
568
627
  });
628
+ pluginRuntimeController = controller;
629
+ if (pluginSignalLane && pluginManager) {
630
+ pluginSignalLane.sync(pluginManager.getPluginSignalProviders());
631
+ unsubscribePluginReload = pluginManager.onReload(() => pluginSignalLane.sync(pluginManager.getPluginSignalProviders()));
632
+ }
569
633
  return {
570
634
  controller,
571
635
  storage,
@@ -588,8 +652,59 @@ async function createMastraCodeAgentController(config) {
588
652
  githubSignals,
589
653
  sessionId,
590
654
  ownerId,
655
+ projectPath: project.rootPath,
656
+ codeAgent,
591
657
  setActiveSession: (session) => {
592
658
  activeSession = session;
659
+ },
660
+ /**
661
+ * Starts the signal providers contributed by plugins. Called by the
662
+ * composition layer once the controller is inited, because that is when a
663
+ * Mastra instance exists — a provider without one has no storage, and
664
+ * nothing else will hand it one: the Agent propagates Mastra only to the
665
+ * providers in its own `signals` array, which these deliberately are not in.
666
+ */
667
+ startPluginSignalProviders: () => {
668
+ const mastra = controller.getMastra();
669
+ if (!pluginSignalLane || !mastra) return;
670
+ pluginSignalLane.setMastra(mastra, codeAgent);
671
+ },
672
+ /**
673
+ * Stops every plugin-contributed signal provider and stops listening for
674
+ * plugin reloads. The inverse of `startPluginSignalProviders`, for an
675
+ * embedder that is done with this controller: a `pluginManager` shared
676
+ * across controllers (`MastraCodeConfig.pluginManager`) outlives any one of
677
+ * them, so without this its providers keep polling and its reload listener
678
+ * keeps firing for a controller that is gone.
679
+ */
680
+ stopPluginSignalProviders: () => {
681
+ unsubscribePluginReload?.();
682
+ unsubscribePluginReload = void 0;
683
+ pluginSignalLane?.stopAll();
684
+ },
685
+ /**
686
+ * Hands Mastra to the statically configured input processors.
687
+ *
688
+ * The Agent does this itself, but only for processors configured as a
689
+ * plain array (`Array.isArray` in `__registerMastra`). This lane is a
690
+ * function so plugins can contribute to it, which takes those processors
691
+ * out of that branch — including any an embedder passed as
692
+ * `config.inputProcessors`, some of which need Mastra to work at all
693
+ * (`CostGuardProcessor` reads observability storage there). Doing it here
694
+ * keeps that unchanged.
695
+ *
696
+ * Plugin processors are deliberately not included: they come and go with
697
+ * their plugin, and the registry keeps the first instance registered under
698
+ * an id forever, which would leave a retired instance behind. Plugins
699
+ * reach Mastra through `getController()` on the plugin context instead.
700
+ */
701
+ registerConfiguredProcessorsWithMastra: () => {
702
+ const mastra = controller.getMastra();
703
+ if (!mastra) return;
704
+ for (const processor of mastraCodeInputProcessors) {
705
+ mastra.addProcessor(processor);
706
+ mastra.addProcessorConfiguration(processor, CODE_AGENT_ID, "input");
707
+ }
593
708
  }
594
709
  };
595
710
  }
@@ -639,9 +754,17 @@ async function wireSessionConcerns(base, session) {
639
754
  */
640
755
  async function bootLocalAgentController(config) {
641
756
  const base = await createMastraCodeAgentController(config);
642
- const { controller, sessionId, ownerId } = base;
757
+ const { controller, sessionId, ownerId, projectPath, codeAgent, mcpManager } = base;
643
758
  await controller.init();
644
- await controller.getMastra()?.startWorkers();
759
+ const mastra = controller.getMastra();
760
+ if (mastra) await registerWorkflowBuilderPrimitives(mastra, {
761
+ projectPath,
762
+ codeAgent,
763
+ mcpManager
764
+ });
765
+ await mastra?.startWorkers();
766
+ base.registerConfiguredProcessorsWithMastra();
767
+ base.startPluginSignalProviders();
645
768
  const session = await controller.createSession({
646
769
  id: sessionId,
647
770
  ownerId
@@ -697,17 +820,19 @@ async function mountAgentControllerOnMastra(config) {
697
820
  */
698
821
  async function prepareAgentControllerMount(config) {
699
822
  const base = await createMastraCodeAgentController(config);
700
- const { controller, storage, authStorage } = base;
823
+ const { controller, storage, authStorage, projectPath, codeAgent, mcpManager } = base;
701
824
  const controllerId = config?.controllerId ?? controller.id;
702
825
  const apiRoutes = config?.buildApiRoutes?.({
703
826
  controller,
704
827
  authStorage
705
828
  });
829
+ const extraServerConfig = config?.buildServerConfig?.({
830
+ controller,
831
+ authStorage
832
+ });
833
+ const weOwnTheMastra = !config?.mastra;
706
834
  const serverConfig = {
707
- ...config?.buildServerConfig?.({
708
- controller,
709
- authStorage
710
- }),
835
+ ...extraServerConfig,
711
836
  ...apiRoutes?.length ? { apiRoutes } : {}
712
837
  };
713
838
  const mastraArgs = {
@@ -718,7 +843,17 @@ async function prepareAgentControllerMount(config) {
718
843
  };
719
844
  const finalize = async () => {
720
845
  await controller.init();
846
+ if (weOwnTheMastra) {
847
+ const mastra = controller.getMastra();
848
+ if (mastra) await registerWorkflowBuilderPrimitives(mastra, {
849
+ projectPath,
850
+ codeAgent,
851
+ mcpManager
852
+ });
853
+ }
721
854
  await controller.getMastra()?.startWorkers();
855
+ base.registerConfiguredProcessorsWithMastra();
856
+ base.startPluginSignalProviders();
722
857
  };
723
858
  return {
724
859
  base,