@dbx-tools/appkit-mastra 0.9.140 → 0.9.143

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/src/agents.ts CHANGED
@@ -45,10 +45,18 @@ import { createCodeMode, createTool } from "@mastra/core/tools";
45
45
  import type { Workspace } from "@mastra/core/workspace";
46
46
  import { createSkillTools, createWorkspaceTools } from "@mastra/core/workspace";
47
47
  import type { PgVectorConfig, PostgresStoreConfig } from "@mastra/pg";
48
- import { QuickJsCodeModeTransport } from "@mastra/quickjs";
49
48
 
50
49
  import { buildRenderDataTool } from "./chart.ts";
51
- import type { MastraPluginConfig } from "./config.ts";
50
+ import type {
51
+ MastraCodeModeConfig,
52
+ MastraCodeModeTransport,
53
+ MastraPluginConfig,
54
+ } from "./config.ts";
55
+ import {
56
+ buildFollowUpSuggestionsProcessor,
57
+ buildSuggestFollowUpsTool,
58
+ resolveFollowUpSuggestionsConfig,
59
+ } from "./follow-up-suggestions.ts";
52
60
  import { buildGenieToolkitProvider, resolveGenieSpaces } from "./genie.ts";
53
61
  import { withRequestMemoryScope, type MemoryBuilder } from "./memory.ts";
54
62
  import { buildModel, RESPONSES_PROVIDER_OPTIONS } from "./model.ts";
@@ -64,7 +72,28 @@ import {
64
72
  } from "./workspaces.ts";
65
73
 
66
74
  const codeModeLogger = log.logger("mastra/code-mode");
67
- let resolvedCodeModeTransport: Promise<CodeModeTransport> | undefined;
75
+ const ISOLATED_VM_PACKAGE = "@mastra/isolated-vm";
76
+ const QUICKJS_PACKAGE = "@mastra/quickjs";
77
+ let isolatedVmDependency: Promise<typeof import("@mastra/isolated-vm")> | undefined;
78
+ let quickJsDependency: Promise<typeof import("@mastra/quickjs")> | undefined;
79
+
80
+ type NormalizedCodeModeConfig = MastraCodeModeConfig;
81
+
82
+ interface ResolvedCodeModeConfig {
83
+ readonly id?: string;
84
+ readonly timeout?: number;
85
+ readonly provider: Exclude<MastraCodeModeTransport, "auto">;
86
+ readonly transport: CodeModeTransport;
87
+ }
88
+
89
+ type CodeModeFailureCategory =
90
+ "unsupported-runtime" | "dependency-unavailable" | "construction-failed";
91
+
92
+ interface CodeModeFailure {
93
+ readonly category: CodeModeFailureCategory;
94
+ readonly error?: Error;
95
+ readonly provider: Exclude<MastraCodeModeTransport, "auto">;
96
+ }
68
97
 
69
98
  /** Return whether this boot environment matches isolated-vm's supported app shape. */
70
99
  function supportsIsolatedVmTransport(): boolean {
@@ -77,6 +106,36 @@ function supportsIsolatedVmTransport(): boolean {
77
106
  return [...process.execArgv, ...nodeOptions].includes("--no-node-snapshot");
78
107
  }
79
108
 
109
+ /** Return whether the current runtime satisfies QuickJS' published engine floor. */
110
+ function supportsQuickJsTransport(): boolean {
111
+ if (process.versions.bun) return true;
112
+ if (process.release.name !== "node") return false;
113
+ const [majorText, minorText] = process.versions.node.split(".");
114
+ const major = Number.parseInt(majorText ?? "", 10);
115
+ const minor = Number.parseInt(minorText ?? "", 10);
116
+ return (
117
+ Number.isFinite(major) &&
118
+ Number.isFinite(minor) &&
119
+ (major > 20 || (major === 20 && minor >= 19))
120
+ );
121
+ }
122
+
123
+ /** Import the optional native transport at most once for this process. */
124
+ function loadIsolatedVmDependency(): Promise<typeof import("@mastra/isolated-vm")> {
125
+ isolatedVmDependency ??= import(/* @vite-ignore */ ISOLATED_VM_PACKAGE) as Promise<
126
+ typeof import("@mastra/isolated-vm")
127
+ >;
128
+ return isolatedVmDependency;
129
+ }
130
+
131
+ /** Import the optional portable transport at most once for this process. */
132
+ function loadQuickJsDependency(): Promise<typeof import("@mastra/quickjs")> {
133
+ quickJsDependency ??= import(/* @vite-ignore */ QUICKJS_PACKAGE) as Promise<
134
+ typeof import("@mastra/quickjs")
135
+ >;
136
+ return quickJsDependency;
137
+ }
138
+
80
139
  /**
81
140
  * Tool record accepted by every Mastra `Agent.tools` field and by the
82
141
  * `tools(plugins)` callback on {@link MastraAgentDefinition}.
@@ -607,26 +666,125 @@ function appendInstructionBlock(instructions: AgentInstructions, block: string):
607
666
  return [instructions, { role: "system", content: block }] as AgentInstructions;
608
667
  }
609
668
 
610
- /** Resolve one native Code Mode transport during plugin startup. */
611
- function codeModeTransport(): Promise<CodeModeTransport> {
612
- resolvedCodeModeTransport ??= (async () => {
669
+ /** Normalize the public Code Mode shorthand into one startup configuration. */
670
+ function normalizeCodeModeConfig(
671
+ codeMode: MastraPluginConfig["codeMode"],
672
+ ): NormalizedCodeModeConfig | undefined {
673
+ if (codeMode === undefined || codeMode === false) return undefined;
674
+ return typeof codeMode === "string" ? { transport: codeMode } : codeMode;
675
+ }
676
+
677
+ /** Try one optional Code Mode transport without applying fallback policy. */
678
+ async function tryCodeModeTransport(
679
+ provider: Exclude<MastraCodeModeTransport, "auto">,
680
+ ): Promise<ResolvedCodeModeConfig | CodeModeFailure> {
681
+ if (provider === "isolated-vm") {
613
682
  if (!supportsIsolatedVmTransport()) {
614
- codeModeLogger.info("transport selected", { provider: "quickjs" });
615
- return new QuickJsCodeModeTransport();
683
+ return { category: "unsupported-runtime", provider };
616
684
  }
685
+ let module: typeof import("@mastra/isolated-vm");
617
686
  try {
618
- const { IsolatedVmCodeModeTransport } = await import("@mastra/isolated-vm");
619
- const transport = new IsolatedVmCodeModeTransport();
620
- codeModeLogger.info("transport selected", { provider: "isolated-vm" });
621
- return transport;
687
+ module = await loadIsolatedVmDependency();
622
688
  } catch (caught) {
623
- codeModeLogger.warn("isolated-vm unavailable; using QuickJS", {
689
+ return {
690
+ category: "dependency-unavailable",
624
691
  error: errorUtils.toError(caught),
625
- });
626
- return new QuickJsCodeModeTransport();
692
+ provider,
693
+ };
627
694
  }
628
- })();
629
- return resolvedCodeModeTransport;
695
+ try {
696
+ return { provider, transport: new module.IsolatedVmCodeModeTransport() };
697
+ } catch (caught) {
698
+ return {
699
+ category: "construction-failed",
700
+ error: errorUtils.toError(caught),
701
+ provider,
702
+ };
703
+ }
704
+ }
705
+
706
+ if (!supportsQuickJsTransport()) {
707
+ return { category: "unsupported-runtime", provider };
708
+ }
709
+ let module: typeof import("@mastra/quickjs");
710
+ try {
711
+ module = await loadQuickJsDependency();
712
+ } catch (caught) {
713
+ return {
714
+ category: "dependency-unavailable",
715
+ error: errorUtils.toError(caught),
716
+ provider,
717
+ };
718
+ }
719
+ try {
720
+ return { provider, transport: new module.QuickJsCodeModeTransport() };
721
+ } catch (caught) {
722
+ return {
723
+ category: "construction-failed",
724
+ error: errorUtils.toError(caught),
725
+ provider,
726
+ };
727
+ }
728
+ }
729
+
730
+ function isCodeModeFailure(
731
+ result: ResolvedCodeModeConfig | CodeModeFailure,
732
+ ): result is CodeModeFailure {
733
+ return "category" in result;
734
+ }
735
+
736
+ /** Produce the actionable startup error for an explicitly required transport. */
737
+ function requiredCodeModeError(failure: CodeModeFailure): ConfigurationError {
738
+ const runtime = process.versions.bun
739
+ ? `Bun ${process.versions.bun}`
740
+ : `${process.release.name} ${process.versions.node}`;
741
+ const install = `bun add ${failure.provider === "isolated-vm" ? ISOLATED_VM_PACKAGE : QUICKJS_PACKAGE}`;
742
+ const reason =
743
+ failure.category === "unsupported-runtime"
744
+ ? `is not supported by ${runtime}`
745
+ : failure.category === "dependency-unavailable"
746
+ ? "could not be loaded"
747
+ : "could not be initialized";
748
+ return new ConfigurationError(
749
+ `mastra: codeMode transport "${failure.provider}" ${reason}. Install the optional transport with \`${install}\` and use a supported runtime.`,
750
+ failure.error ? { cause: failure.error } : undefined,
751
+ );
752
+ }
753
+
754
+ /** Resolve the configured optional transport once during plugin startup. */
755
+ async function resolveCodeModeConfig(
756
+ codeMode: MastraPluginConfig["codeMode"],
757
+ ): Promise<ResolvedCodeModeConfig | undefined> {
758
+ const config = normalizeCodeModeConfig(codeMode);
759
+ if (!config) return undefined;
760
+
761
+ const providers: readonly Exclude<MastraCodeModeTransport, "auto">[] =
762
+ config.transport === "auto" ? ["isolated-vm", "quickjs"] : [config.transport];
763
+ const failures: CodeModeFailure[] = [];
764
+ for (const provider of providers) {
765
+ const result = await tryCodeModeTransport(provider);
766
+ if (!isCodeModeFailure(result)) {
767
+ codeModeLogger.info("transport selected", { provider });
768
+ return { ...result, id: config.id, timeout: config.timeout };
769
+ }
770
+ failures.push(result);
771
+ if (config.transport !== "auto") throw requiredCodeModeError(result);
772
+ const fields = {
773
+ category: result.category,
774
+ provider,
775
+ ...(result.error ? { error: result.error } : {}),
776
+ };
777
+ if (result.category === "unsupported-runtime") {
778
+ codeModeLogger.info("automatic transport unsupported", fields);
779
+ } else {
780
+ codeModeLogger.warn("automatic transport unavailable", fields);
781
+ }
782
+ }
783
+
784
+ codeModeLogger.info("automatic Code Mode disabled", {
785
+ reasons: failures.map(({ category, provider }) => ({ category, provider })),
786
+ });
787
+ return undefined;
630
788
  }
631
789
 
632
790
  type CodeModeResolver<TRequestContext extends Record<string, unknown> | unknown = unknown> = (
@@ -640,12 +798,11 @@ type CodeModeResolver<TRequestContext extends Record<string, unknown> | unknown
640
798
 
641
799
  /** Build request-scoped native Code Mode over all executable context tools. */
642
800
  async function buildCodeMode<TRequestContext extends Record<string, unknown> | unknown>(
643
- config: MastraPluginConfig,
801
+ config: ResolvedCodeModeConfig,
644
802
  tools: MastraTools,
645
803
  workspace: Workspace | undefined,
646
804
  requestContext: RequestContext<TRequestContext>,
647
805
  ): Promise<ReturnType<typeof createCodeMode> | undefined> {
648
- if (config.codeMode === false) return undefined;
649
806
  const workspaceTools = workspace
650
807
  ? await createWorkspaceTools(workspace, { requestContext, workspace })
651
808
  : {};
@@ -660,10 +817,13 @@ async function buildCodeMode<TRequestContext extends Record<string, unknown> | u
660
817
  ),
661
818
  ) as ToolsInput;
662
819
  if (Object.keys(executableTools).length === 0) return undefined;
663
- const options = typeof config.codeMode === "object" ? config.codeMode : {};
664
820
  const codeMode = createCodeMode(
665
- { tools: executableTools, ...options },
666
- await codeModeTransport(),
821
+ {
822
+ tools: executableTools,
823
+ ...(config.id !== undefined ? { id: config.id } : {}),
824
+ ...(config.timeout !== undefined ? { timeout: config.timeout } : {}),
825
+ },
826
+ config.transport,
667
827
  );
668
828
  if (!("mastra_workspace_read_file" in workspaceTools)) return codeMode;
669
829
  return {
@@ -674,11 +834,11 @@ async function buildCodeMode<TRequestContext extends Record<string, unknown> | u
674
834
 
675
835
  /** Resolve Code Mode lazily so workspace and dynamic tool policy follow each request. */
676
836
  function codeModeResolver<TRequestContext extends Record<string, unknown> | unknown>(
677
- config: MastraPluginConfig,
837
+ config: ResolvedCodeModeConfig | undefined,
678
838
  tools: MastraTools,
679
839
  workspace: Workspace | undefined,
680
840
  ): CodeModeResolver<TRequestContext> | undefined {
681
- if (config.codeMode === false) return undefined;
841
+ if (!config) return undefined;
682
842
  return ({ requestContext }) => buildCodeMode(config, tools, workspace, requestContext);
683
843
  }
684
844
 
@@ -731,6 +891,7 @@ export async function buildAgents(opts: {
731
891
  standardSkills = [],
732
892
  excludedWorkspaceSkillNames = [],
733
893
  } = opts;
894
+ const codeModeConfig = await resolveCodeModeConfig(config.codeMode);
734
895
  const definitions = resolveDefinitions(config);
735
896
  const ids = Object.keys(definitions);
736
897
  const defaultAgentId = config.defaultAgent ?? ids[0] ?? FALLBACK_AGENT_ID;
@@ -742,9 +903,14 @@ export async function buildAgents(opts: {
742
903
  // user can shadow either by including a same-named tool in their own
743
904
  // `config.tools` or per-agent `tools`. Merge order is
744
905
  // `system -> standard skills -> user-ambient -> per-agent`, last write wins.
906
+ const followUps = resolveFollowUpSuggestionsConfig(config.followUpSuggestions);
907
+ const followUpProcessor = buildFollowUpSuggestionsProcessor(config);
745
908
  const systemTools: MastraTools = {
746
909
  render_data: buildRenderDataTool(config),
747
910
  summarize: buildSummarizeTool(config),
911
+ ...(followUps?.exposeTool && followUps.mode !== "genie"
912
+ ? { suggest_follow_ups: buildSuggestFollowUpsTool(config) }
913
+ : {}),
748
914
  };
749
915
  const standardSkillTools =
750
916
  standardSkills.length > 0 ? createSkillTools(resolveAgentSkills([...standardSkills])) : {};
@@ -798,7 +964,7 @@ export async function buildAgents(opts: {
798
964
  const gated = approvalGatedToolIds(tools);
799
965
  if (gated.length > 0) approvalGatedByAgent.push({ agentId: id, toolIds: gated });
800
966
  const memory = memoryBuilder?.forAgent(id, def);
801
- const resolveCodeMode = codeModeResolver(config, tools, workspace);
967
+ const resolveCodeMode = codeModeResolver(codeModeConfig, tools, workspace);
802
968
  const agent = new Agent({
803
969
  id,
804
970
  name: def.name ?? id,
@@ -832,6 +998,7 @@ export async function buildAgents(opts: {
832
998
  inputProcessors: [...inputProcessors, ...workspaceSkillInputProcessors(workspace, config)],
833
999
  outputProcessors: [
834
1000
  toolErrorLoggingProcessor(log),
1001
+ ...(followUpProcessor ? [followUpProcessor] : []),
835
1002
  ...outputProcessorFactories.flatMap((factory) => {
836
1003
  const processor = factory(id);
837
1004
  return processor ? [processor] : [];
package/src/chat.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * @module
5
5
  */
6
6
 
7
- import { errorUtils, log } from "@dbx-tools/shared-core";
7
+ import { errorUtils, log, object } from "@dbx-tools/shared-core";
8
8
  import { routes } from "@dbx-tools/shared-mastra";
9
9
  import {
10
10
  isStaleMastraResumeError,
@@ -15,6 +15,14 @@ import { isEventedAgent } from "@mastra/core/agent/durable";
15
15
  import { registerApiRoute } from "@mastra/core/server";
16
16
  import { createUIMessageStreamResponse } from "ai";
17
17
 
18
+ import type { MastraPluginConfig } from "./config.ts";
19
+ import {
20
+ buildFollowUpSuggestionsTransform,
21
+ FOLLOW_UP_NATIVE_QUESTIONS_KEY,
22
+ FOLLOW_UP_RUN_ID_KEY,
23
+ FOLLOW_UP_USER_TEXT_KEY,
24
+ resolveFollowUpSuggestionsConfig,
25
+ } from "./follow-up-suggestions.ts";
18
26
  import { withRequestMemoryScope } from "./memory.ts";
19
27
 
20
28
  const logger = log.logger("mastra/chat");
@@ -24,8 +32,31 @@ export function agentAbortSignal(agent: unknown, signal: AbortSignal): AbortSign
24
32
  return isEventedAgent(agent) ? undefined : signal;
25
33
  }
26
34
 
35
+ function latestUserText(value: unknown): string | undefined {
36
+ if (!Array.isArray(value)) return undefined;
37
+ for (let index = value.length - 1; index >= 0; index -= 1) {
38
+ const message = value[index];
39
+ if (!object.isRecord(message) || message.role !== "user") continue;
40
+ if (typeof message.content === "string" && message.content.trim()) {
41
+ return message.content.trim();
42
+ }
43
+ if (!Array.isArray(message.parts)) continue;
44
+ const text = message.parts
45
+ .flatMap((part) =>
46
+ object.isRecord(part) && part.type === "text" && typeof part.text === "string"
47
+ ? [part.text]
48
+ : [],
49
+ )
50
+ .join("\n")
51
+ .trim();
52
+ if (text) return text;
53
+ }
54
+ return undefined;
55
+ }
56
+
27
57
  /** Register detached chat, durable observation, and explicit abort routes. */
28
- export function agentChatRoutes() {
58
+ export function agentChatRoutes(config: MastraPluginConfig = {}) {
59
+ const followUps = resolveFollowUpSuggestionsConfig(config.followUpSuggestions);
29
60
  const chatPath = `${routes.MASTRA_ROUTES.chat}/:agentId` as `${string}:agentId`;
30
61
  const runPath =
31
62
  `${routes.MASTRA_ROUTES.chat}/:agentId${routes.MASTRA_ROUTES.runs}/:runId` as `${string}:agentId${string}:runId`;
@@ -56,6 +87,12 @@ export function agentChatRoutes() {
56
87
  }
57
88
  const status = rawStatus as "draft" | "published" | undefined;
58
89
  const abortSignal = agentAbortSignal(mastra.getAgentById(agentId), context.req.raw.signal);
90
+ const runId =
91
+ typeof params.runId === "string" && params.runId ? params.runId : crypto.randomUUID();
92
+ const userText = latestUserText(params.messages);
93
+ if (userText) requestContext.setRaw(FOLLOW_UP_USER_TEXT_KEY, userText);
94
+ requestContext.setRaw(FOLLOW_UP_NATIVE_QUESTIONS_KEY, []);
95
+ requestContext.setRaw(FOLLOW_UP_RUN_ID_KEY, runId);
59
96
  const stream = await handleChatStream({
60
97
  mastra,
61
98
  agentId,
@@ -67,11 +104,15 @@ export function agentChatRoutes() {
67
104
  params: withRequestMemoryScope(
68
105
  {
69
106
  ...params,
107
+ runId,
70
108
  requestContext,
71
109
  ...(abortSignal ? { abortSignal } : {}),
72
110
  },
73
111
  requestContext,
74
112
  ),
113
+ ...(followUps && followUps.mode !== "genie"
114
+ ? { experimentalTransform: buildFollowUpSuggestionsTransform(runId) }
115
+ : {}),
75
116
  version: "v7",
76
117
  sendReasoning: true,
77
118
  sendSources: true,
@@ -97,6 +138,9 @@ export function agentChatRoutes() {
97
138
  const observed = await agent.observe(runId);
98
139
  const stream = toAISdkStream(observed.output, {
99
140
  from: "agent",
141
+ ...(followUps && followUps.mode !== "genie"
142
+ ? { experimentalTransform: buildFollowUpSuggestionsTransform(runId) }
143
+ : {}),
100
144
  version: "v7",
101
145
  sendReasoning: true,
102
146
  sendSources: true,
package/src/config.ts CHANGED
@@ -166,8 +166,13 @@ export interface MastraWorkspaceSkillsConfig {
166
166
  ttlMs?: number;
167
167
  }
168
168
 
169
+ /** Native Mastra Code Mode execution transport. */
170
+ export type MastraCodeModeTransport = "auto" | "isolated-vm" | "quickjs";
171
+
169
172
  /** Native Mastra Code Mode settings for sandboxed multi-tool orchestration. */
170
173
  export interface MastraCodeModeConfig {
174
+ /** Code Mode execution transport. */
175
+ transport: MastraCodeModeTransport;
171
176
  /** Generated orchestration tool id. Defaults to `execute_typescript`. */
172
177
  id?: string;
173
178
  /** Maximum orchestration program runtime in milliseconds. Defaults to 30 seconds. */
@@ -213,6 +218,18 @@ export interface MastraMcpConfig {
213
218
  extraTools?: MastraTools;
214
219
  }
215
220
 
221
+ /** Optional post-turn follow-up suggestion policy. */
222
+ export interface FollowUpSuggestionsConfig {
223
+ /** Native Genie only, ChatFast generated only, or automatic selection when true. */
224
+ mode: true | "generated" | "genie";
225
+ /** Maximum questions emitted for one turn. Defaults to 3, maximum 10. */
226
+ limit?: number;
227
+ /** Tail-generation timeout in milliseconds. */
228
+ timeoutMs?: number;
229
+ /** Also expose the generator as an explicitly callable agent tool. */
230
+ exposeTool?: boolean;
231
+ }
232
+
216
233
  /** Configuration accepted by the Mastra AppKit plugin. */
217
234
  export interface MastraPluginConfig extends BasePluginConfig {
218
235
  /**
@@ -237,14 +254,14 @@ export interface MastraPluginConfig extends BasePluginConfig {
237
254
  memory?: boolean | MastraMemoryConfig;
238
255
  /**
239
256
  * Expose executable tools available to the current request through native
240
- * Mastra Code Mode. Defaults on whenever the request has executable tools.
241
- * The plugin selects Mastra's isolated-vm transport once during startup and
242
- * falls back to Mastra QuickJS when the native transport is unavailable.
243
- * These transports do not execute through the workspace command sandbox;
244
- * SSH is used only when an exposed SSH-backed tool is called. Set `false` to
245
- * opt out.
257
+ * Mastra Code Mode. Defaults to `false`. `auto` selects an installed,
258
+ * runtime-supported optional transport during startup and leaves Code Mode
259
+ * disabled when none is available. Explicit transport values fail startup
260
+ * when their optional dependency or runtime support is unavailable. These
261
+ * transports do not execute through the workspace command sandbox; SSH is
262
+ * used only when an exposed SSH-backed tool is called.
246
263
  */
247
- codeMode?: boolean | MastraCodeModeConfig;
264
+ codeMode?: false | MastraCodeModeTransport | MastraCodeModeConfig;
248
265
  /**
249
266
  * Sandbox for auto-created agent workspaces. Defaults to Monty. `false`
250
267
  * disables command execution; `true` or `"monty"` selects Monty; an explicit
@@ -503,6 +520,12 @@ export interface MastraPluginConfig extends BasePluginConfig {
503
520
  * to drill deep into a dataset within a single turn.
504
521
  */
505
522
  agentMaxSteps?: number;
523
+ /**
524
+ * Optional post-turn follow-up questions. `true` selects sources
525
+ * automatically; `"generated"` or `"genie"` pins one source; `false` or
526
+ * omission disables follow-ups.
527
+ */
528
+ followUpSuggestions?: false | true | "generated" | "genie" | FollowUpSuggestionsConfig;
506
529
  /**
507
530
  * Wire Mastra spans into AppKit's global OTel pipeline via
508
531
  * `@mastra/otel-bridge`.
@@ -700,9 +723,10 @@ export const MASTRA_CONFIG_SCHEMA: ConfigSchema = {
700
723
  "PgVector store for Mastra semantic recall. `true` captures the `lakebase` plugin's existing service-principal pool; an object opens a separately configured store. Auto-enabled when the `lakebase` plugin is registered.",
701
724
  },
702
725
  codeMode: {
703
- type: ["boolean", "object"],
726
+ type: ["boolean", "string", "object"],
727
+ default: false,
704
728
  description:
705
- "Expose all executable tools available to the current request through native Mastra Code Mode for TypeScript batching, aggregation, and arithmetic. The plugin uses Mastra isolated-vm with the existing QuickJS fallback; neither transport runs through the workspace command sandbox, so SSH is used only when an SSH-backed tool is called. False disables it.",
729
+ 'Expose executable request tools through native Mastra Code Mode for TypeScript batching, aggregation, and arithmetic. Defaults to false. Use "auto" to select an installed supported optional transport or stay disabled, "isolated-vm" to require the native transport, "quickjs" to require the portable transport, or an object with transport plus id and timeout. Neither transport runs through the workspace command sandbox.',
706
730
  },
707
731
  sandbox: {
708
732
  type: ["boolean", "string", "object"],
@@ -780,6 +804,11 @@ export const MASTRA_CONFIG_SCHEMA: ConfigSchema = {
780
804
  description:
781
805
  "Maximum LLM steps each agent gets per turn (a tool call and the final reply each consume one). Defaults to 25.",
782
806
  },
807
+ followUpSuggestions: {
808
+ type: ["boolean", "string", "object"],
809
+ description:
810
+ 'Optional post-turn follow-ups. True selects sources automatically; "generated" or "genie" pins one source; an object adds a limit, timeout, and optional tool exposure. Defaults off.',
811
+ },
783
812
  stripStaleCharts: {
784
813
  type: "boolean",
785
814
  description: