@salesforce/sfdx-agent-harness-mastra 0.11.0 → 0.12.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.
package/README.md CHANGED
@@ -46,15 +46,15 @@ Linux and macOS release the handle eagerly; the retry options are no-ops on thos
46
46
 
47
47
  ### Core
48
48
 
49
- | Export | Kind | Description |
50
- | ------------------------------------- | --------- | ------------------------------------------------------------------------------------------- |
51
- | `MastraHarnessFactory` | class | `HarnessFactory` that produces a Mastra-backed `AgentHarness` bound to a storage root. |
52
- | `MastraHarnessFactoryConfig` | interface | Configuration for `MastraHarnessFactory` (`modelConfigFactory?`, `toolApprovalTimeoutMs?`). |
53
- | `MastraModelConfigFactory` | interface | Strategy for creating model configurations; injected into `MastraHarnessFactory`. |
54
- | `ResolvedModelConfig` | type | Return type of `MastraModelConfigFactory.create()` — wraps a `MastraModelConfig`. |
55
- | `DefaultMastraModelConfigFactory` | class | Default factory using the Salesforce LLM Gateway (`SalesforceMastraModelGateway`). |
56
- | `LLMGExpressMastraModelConfigFactory` | class | Factory for LLM Gateway Express (API-key-authenticated, OpenAI-compatible endpoint). |
57
- | `LLMGExpressConfig` | type | Configuration for `LLMGExpressMastraModelConfigFactory` (`apiKey`, `baseUrl`, `modelId`). |
49
+ | Export | Kind | Description |
50
+ | ------------------------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
51
+ | `MastraHarnessFactory` | class | `HarnessFactory` that produces a Mastra-backed `AgentHarness` bound to a storage root. |
52
+ | `MastraHarnessFactoryConfig` | interface | Configuration for `MastraHarnessFactory` (`modelConfigFactory?`, `toolApprovalTimeoutMs?`). |
53
+ | `MastraModelConfigFactory` | interface | Strategy for creating model configurations; injected into `MastraHarnessFactory`. |
54
+ | `ResolvedModelConfig` | type | Return type of `MastraModelConfigFactory.create()` — a `MastraModelConfig` plus a `validateFiles(files)` hook the harness calls for pre-flight multimodal (`image`/`file`) validation. |
55
+ | `DefaultMastraModelConfigFactory` | class | Default factory using the Salesforce LLM Gateway (`SalesforceMastraModelGateway`). |
56
+ | `LLMGExpressMastraModelConfigFactory` | class | Factory for LLM Gateway Express (API-key-authenticated, OpenAI-compatible endpoint). |
57
+ | `LLMGExpressConfig` | type | Configuration for `LLMGExpressMastraModelConfigFactory` (`apiKey`, `baseUrl`, `modelId`). |
58
58
 
59
59
  ### Extension surface
60
60
 
@@ -62,14 +62,16 @@ These types let consumers reach Mastra-specific features through the SDK's typed
62
62
  `MastraAgentHarness` from `MastraHarnessFactory.create()`, so consumers usually don't reference these types explicitly —
63
63
  they show up via inference at the call site.
64
64
 
65
- | Export | Kind | Description |
66
- | ------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
67
- | `MastraAgentHarness` | type | Branded `AgentHarness` subtype; carries the Mastra-specific `extensions` namespace and the inferred config type. |
68
- | `MastraAgentConfig` | type | `AgentConfig` extended with Mastra-only fields (currently `toolSearch`). Inferred at `manager.createAgent` automatically — annotation rarely needed. |
69
- | `MastraToolSearchConfig` | type | Shape of `MastraAgentConfig.toolSearch` (`pool`, `alwaysActive`, `topK`, `ttl`). |
70
- | `formatMcpToolName` | function | `(serverName: string, toolName: string) => string` — builds the namespaced MCP tool name (`${serverName}_${toolName}`) used in `toolSearch.alwaysActive`. |
71
- | `ToolSearchHandle` | type | Stable interface for the tool-search runtime: `id`, `getStateStats`, `clearState`, `clearAllState`, `cleanupNow`. Wraps Mastra's internal processor. |
72
- | `SkillSearchHandle` | type | Stable interface for the skill-search runtime: `id` (Mastra's processor has no other public methods today; the harness owns lifecycle). |
65
+ | Export | Kind | Description |
66
+ | ------------------------ | ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
67
+ | `MastraAgentHarness` | type | Branded `AgentHarness` subtype; carries the Mastra-specific `extensions` namespace and the inferred config type. |
68
+ | `MastraAgentConfig` | type | `AgentConfig` extended with Mastra-only fields (currently `toolSearch`). Inferred at `manager.createAgent` automatically — annotation rarely needed. |
69
+ | `MastraToolSearchConfig` | type | Shape of `MastraAgentConfig.toolSearch` (`pool`, `alwaysActive`, `topK`, `ttl`). |
70
+ | `ToolSearchHandle` | type | Stable interface for the tool-search runtime: `id`, `getStateStats`, `clearState`, `clearAllState`, `cleanupNow`. Wraps Mastra's internal processor. |
71
+ | `SkillSearchHandle` | type | Stable interface for the skill-search runtime: `id` (Mastra's processor has no other public methods today; the harness owns lifecycle). |
72
+
73
+ The Mastra-specific accessors live on `manager.extensions.mastra` (`getToolSearchProcessor(agentId)`,
74
+ `getSkillSearchProcessor(agentId)`, `formatMcpToolName(serverName, toolName)`) and require no separate import.
73
75
 
74
76
  #### Tool search
75
77
 
@@ -77,7 +79,7 @@ Hide a large tool catalog behind Mastra's `search_tools` / `load_tool` meta-tool
77
79
 
78
80
  ```ts
79
81
  import { createAgentManager } from '@salesforce/sfdx-agent-sdk';
80
- import { MastraHarnessFactory, formatMcpToolName } from '@salesforce/sfdx-agent-harness-mastra';
82
+ import { MastraHarnessFactory } from '@salesforce/sfdx-agent-harness-mastra';
81
83
 
82
84
  const manager = await createAgentManager(storageRoot, new MastraHarnessFactory());
83
85
 
@@ -87,7 +89,14 @@ const agent = await manager.createAgent(projectRoot, {
87
89
  mcpServers: { sfdx: { type: 'stdio', command: 'npx', args: ['@salesforce/mcp'] } },
88
90
  toolSearch: {
89
91
  pool: '*', // or an explicit name list
90
- alwaysActive: ['lookup_account', formatMcpToolName('sfdx', 'deploy_metadata')],
92
+ alwaysActive: [
93
+ 'lookup_account',
94
+ // Build the Mastra-specific namespaced name for an MCP tool that hasn't
95
+ // been discovered yet. The output format is harness-specific
96
+ // (Mastra: `${server}_${tool}`); for cross-harness tool identification
97
+ // anywhere else, prefer the `(serverName, toolName)` pair on `McpToolInfo`.
98
+ manager.extensions.mastra.formatMcpToolName('sfdx', 'deploy_metadata'),
99
+ ],
91
100
  topK: 5, // advisory; defaults to Mastra's 5
92
101
  ttl: 3_600_000, // ms; advisory; defaults to Mastra's 1h
93
102
  },
@@ -1,10 +1,11 @@
1
- import type { LLMGatewayClient } from '@salesforce/llm-gateway-sdk';
1
+ import { type LLMGatewayClient } from '@salesforce/llm-gateway-sdk';
2
2
  import type { MastraModelConfigFactory, ResolvedModelConfig } from './model-config-factory.js';
3
3
  /**
4
4
  * Default model configuration factory that uses the Salesforce LLM Gateway.
5
5
  *
6
6
  * Wraps the LLMGatewayClient in a SalesforceMastraModelGateway and calls
7
7
  * resolveLanguageModel() to produce the LanguageModelV2 that Mastra consumes.
8
+ * Captures the gateway model at creation time to provide multimodal validation.
8
9
  */
9
10
  export declare class DefaultMastraModelConfigFactory implements MastraModelConfigFactory {
10
11
  create(llmGatewayClient: LLMGatewayClient): ResolvedModelConfig;
@@ -2,17 +2,24 @@
2
2
  * Copyright 2026, Salesforce, Inc. All rights reserved.
3
3
  * See LICENSE.txt for license terms.
4
4
  */
5
+ import { validateMultimodalFiles } from '@salesforce/llm-gateway-sdk';
5
6
  import { SalesforceMastraModelGateway } from './salesforce-llm-gateway.js';
6
7
  /**
7
8
  * Default model configuration factory that uses the Salesforce LLM Gateway.
8
9
  *
9
10
  * Wraps the LLMGatewayClient in a SalesforceMastraModelGateway and calls
10
11
  * resolveLanguageModel() to produce the LanguageModelV2 that Mastra consumes.
12
+ * Captures the gateway model at creation time to provide multimodal validation.
11
13
  */
12
14
  export class DefaultMastraModelConfigFactory {
13
15
  create(llmGatewayClient) {
14
16
  const agentGateway = new SalesforceMastraModelGateway(llmGatewayClient);
15
- return { model: agentGateway.resolveLanguageModel() };
17
+ const model = agentGateway.resolveLanguageModel();
18
+ const gatewayModel = llmGatewayClient.getModel();
19
+ return {
20
+ model,
21
+ validateFiles: (files) => validateMultimodalFiles(files, gatewayModel),
22
+ };
16
23
  }
17
24
  }
18
25
  //# sourceMappingURL=default-model-config-factory.js.map
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Buffered async generator wrapper used by `MastraStreamBroker` to deliver
3
+ * `ChatEvent`s to a consumer's `ChatStreamResult.eventStream`.
4
+ *
5
+ * The buffer holds events pushed before the consumer starts iterating, so the
6
+ * broker can begin populating the sink eagerly without coordinating with the
7
+ * consumer's `for await` loop. Events pushed after iteration starts unblock
8
+ * the awaiting consumer via an internal Promise waiter.
9
+ *
10
+ * Internal to `@salesforce/sfdx-agent-harness-mastra`; not part of the public
11
+ * harness surface. Mirrors the same primitive in `@salesforce/sfdx-agent-harness-claude`
12
+ * to keep each harness's broker self-contained without forcing a shared
13
+ * cross-package surface.
14
+ */
15
+ export declare class GenSink<T> {
16
+ private readonly buffered;
17
+ private ended;
18
+ private waiter;
19
+ push(event: T): void;
20
+ end(): void;
21
+ generator(): AsyncGenerator<T, void>;
22
+ private wake;
23
+ }
@@ -0,0 +1,56 @@
1
+ /*
2
+ * Copyright 2026, Salesforce, Inc. All rights reserved.
3
+ * See LICENSE.txt for license terms.
4
+ */
5
+ /**
6
+ * Buffered async generator wrapper used by `MastraStreamBroker` to deliver
7
+ * `ChatEvent`s to a consumer's `ChatStreamResult.eventStream`.
8
+ *
9
+ * The buffer holds events pushed before the consumer starts iterating, so the
10
+ * broker can begin populating the sink eagerly without coordinating with the
11
+ * consumer's `for await` loop. Events pushed after iteration starts unblock
12
+ * the awaiting consumer via an internal Promise waiter.
13
+ *
14
+ * Internal to `@salesforce/sfdx-agent-harness-mastra`; not part of the public
15
+ * harness surface. Mirrors the same primitive in `@salesforce/sfdx-agent-harness-claude`
16
+ * to keep each harness's broker self-contained without forcing a shared
17
+ * cross-package surface.
18
+ */
19
+ export class GenSink {
20
+ buffered = [];
21
+ ended = false;
22
+ waiter = null;
23
+ push(event) {
24
+ if (this.ended)
25
+ return;
26
+ this.buffered.push(event);
27
+ this.wake();
28
+ }
29
+ end() {
30
+ if (this.ended)
31
+ return;
32
+ this.ended = true;
33
+ this.wake();
34
+ }
35
+ async *generator() {
36
+ while (true) {
37
+ if (this.buffered.length > 0) {
38
+ yield this.buffered.shift();
39
+ continue;
40
+ }
41
+ if (this.ended)
42
+ return;
43
+ await new Promise((resolve) => {
44
+ this.waiter = { resolve };
45
+ });
46
+ }
47
+ }
48
+ wake() {
49
+ const w = this.waiter;
50
+ if (w) {
51
+ this.waiter = null;
52
+ w.resolve();
53
+ }
54
+ }
55
+ }
56
+ //# sourceMappingURL=gen-sink.js.map
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { MastraHarnessFactory, type MastraHarnessFactoryConfig } from './mastra-harness-factory.js';
2
2
  export type { MastraAgentHarness } from './mastra-harness.js';
3
- export { type MastraAgentConfig, type MastraToolSearchConfig, type SkillSearchHandle, type ToolSearchHandle, formatMcpToolName, } from './tool-search.js';
3
+ export { type MastraAgentConfig, type MastraToolSearchConfig, type SkillSearchHandle, type ToolSearchHandle, } from './tool-search.js';
4
4
  export type { MastraModelConfigFactory, ResolvedModelConfig } from './model-config-factory.js';
5
5
  export { DefaultMastraModelConfigFactory } from './default-model-config-factory.js';
6
6
  export { LLMGExpressMastraModelConfigFactory, type LLMGExpressConfig } from './llmg-express-model-config-factory.js';
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * See LICENSE.txt for license terms.
4
4
  */
5
5
  export { MastraHarnessFactory } from './mastra-harness-factory.js';
6
- export { formatMcpToolName, } from './tool-search.js';
6
+ export {} from './tool-search.js';
7
7
  export { DefaultMastraModelConfigFactory } from './default-model-config-factory.js';
8
8
  export { LLMGExpressMastraModelConfigFactory } from './llmg-express-model-config-factory.js';
9
9
  //# sourceMappingURL=index.js.map
@@ -1,4 +1,4 @@
1
- import type { LLMGatewayClient } from '@salesforce/llm-gateway-sdk';
1
+ import { type LLMGatewayClient } from '@salesforce/llm-gateway-sdk';
2
2
  import type { MastraModelConfigFactory, ResolvedModelConfig } from './model-config-factory.js';
3
3
  export interface LLMGExpressConfig {
4
4
  /** API key for authenticating with LLM Gateway Express. */
@@ -12,12 +12,14 @@ export interface LLMGExpressConfig {
12
12
  * Model configuration factory for LLM Gateway Express (non-production,
13
13
  * API-key-authenticated, OpenAI-compatible endpoint).
14
14
  *
15
- * This factory ignores the LLMGatewayClient parameter entirely and produces
16
- * a Mastra OpenAICompatibleConfig that Mastra resolves internally using its
17
- * built-in OpenAI-compatible provider support.
15
+ * Routing is via a Mastra OpenAICompatibleConfig that Mastra resolves
16
+ * internally using its built-in OpenAI-compatible provider support.
17
+ * Multimodal validation uses the gateway client's model as a proxy for
18
+ * the express endpoint's capabilities (the express endpoint does not
19
+ * publish its own file-format caps).
18
20
  */
19
21
  export declare class LLMGExpressMastraModelConfigFactory implements MastraModelConfigFactory {
20
22
  private readonly config;
21
23
  constructor(config: LLMGExpressConfig);
22
- create(_llmGatewayClient: LLMGatewayClient): ResolvedModelConfig;
24
+ create(llmGatewayClient: LLMGatewayClient): ResolvedModelConfig;
23
25
  }
@@ -2,27 +2,34 @@
2
2
  * Copyright 2026, Salesforce, Inc. All rights reserved.
3
3
  * See LICENSE.txt for license terms.
4
4
  */
5
+ import { validateMultimodalFiles } from '@salesforce/llm-gateway-sdk';
5
6
  /**
6
7
  * Model configuration factory for LLM Gateway Express (non-production,
7
8
  * API-key-authenticated, OpenAI-compatible endpoint).
8
9
  *
9
- * This factory ignores the LLMGatewayClient parameter entirely and produces
10
- * a Mastra OpenAICompatibleConfig that Mastra resolves internally using its
11
- * built-in OpenAI-compatible provider support.
10
+ * Routing is via a Mastra OpenAICompatibleConfig that Mastra resolves
11
+ * internally using its built-in OpenAI-compatible provider support.
12
+ * Multimodal validation uses the gateway client's model as a proxy for
13
+ * the express endpoint's capabilities (the express endpoint does not
14
+ * publish its own file-format caps).
12
15
  */
13
16
  export class LLMGExpressMastraModelConfigFactory {
14
17
  config;
15
18
  constructor(config) {
16
19
  this.config = config;
17
20
  }
18
- create(_llmGatewayClient) {
21
+ create(llmGatewayClient) {
19
22
  const model = {
20
23
  providerId: 'llmg-express',
21
24
  modelId: this.config.modelId,
22
25
  url: this.config.baseUrl,
23
26
  apiKey: this.config.apiKey,
24
27
  };
25
- return { model };
28
+ const gatewayModel = llmGatewayClient.getModel();
29
+ return {
30
+ model,
31
+ validateFiles: (files) => validateMultimodalFiles(files, gatewayModel),
32
+ };
26
33
  }
27
34
  }
28
35
  //# sourceMappingURL=llmg-express-model-config-factory.js.map
@@ -1,5 +1,5 @@
1
1
  import type { ChunkType } from '@mastra/core/stream';
2
- import { type LogBus } from '@salesforce/agentic-common';
2
+ import type { LogBus } from '@salesforce/agentic-common';
3
3
  import type { ChatEvent } from '@salesforce/sfdx-agent-sdk';
4
4
  /**
5
5
  * Adapts Mastra `ChunkType` stream events to our {@link ChatEvent} discriminated union.
@@ -2,7 +2,6 @@
2
2
  * Copyright 2026, Salesforce, Inc. All rights reserved.
3
3
  * See LICENSE.txt for license terms.
4
4
  */
5
- import { getErrorMessage } from '@salesforce/agentic-common';
6
5
  /**
7
6
  * Adapts Mastra `ChunkType` stream events to our {@link ChatEvent} discriminated union.
8
7
  *
@@ -103,14 +102,17 @@ export class MastraEventAdapter {
103
102
  result: chunk.payload.result,
104
103
  isError: false,
105
104
  };
106
- case 'tool-error':
105
+ case 'tool-error': {
106
+ const error = chunk.payload.error instanceof Error ? chunk.payload.error : new Error(String(chunk.payload.error));
107
107
  return {
108
108
  type: 'tool-result',
109
109
  toolCallId: chunk.payload.toolCallId,
110
110
  toolName: chunk.payload.toolName,
111
- result: getErrorMessage(chunk.payload.error),
111
+ result: error.message,
112
112
  isError: true,
113
+ error,
113
114
  };
115
+ }
114
116
  case 'step-start':
115
117
  return { type: 'step-start', stepIndex: this.stepIndex++ };
116
118
  case 'step-finish':
@@ -199,6 +201,7 @@ function mapUsage(usage) {
199
201
  totalTokens: usage.totalTokens ?? undefined,
200
202
  reasoningTokens: usage.reasoningTokens,
201
203
  cachedInputTokens: usage.cachedInputTokens,
204
+ cacheWriteInputTokens: usage.cacheCreationInputTokens ? usage.cacheCreationInputTokens : undefined,
202
205
  };
203
206
  }
204
207
  //# sourceMappingURL=mastra-event-adapter.js.map
@@ -2,10 +2,11 @@ import { Agent } from '@mastra/core/agent';
2
2
  import { SkillSearchProcessor, ToolSearchProcessor } from '@mastra/core/processors';
3
3
  import type { ChunkType } from '@mastra/core/stream';
4
4
  import { MCPClient } from '@mastra/mcp';
5
- import { McpServerStatus, type AgentHarness, type WithAgentConfig, type ChatStreamResult, type HarnessAgentConfig, type MCPConfiguration, type McpServerErrorDetail, type McpServerInfo, type Message, type StreamOptions, type TelemetryEventCallback, type ToolResultInfo } from '@salesforce/sfdx-agent-sdk';
5
+ import { McpServerStatus, type AgentHarness, type WithAgentConfig, type ChatStreamResult, type HarnessAgentConfig, type MCPConfiguration, type McpServerErrorDetail, type McpServerInfo, type Message, type MessagePart, type StreamOptions, type TelemetryEventCallback, type ToolResultInfo } from '@salesforce/sfdx-agent-sdk';
6
+ import { MastraStreamBroker } from './mastra-stream-broker.js';
6
7
  import type { MastraModelConfigFactory } from './model-config-factory.js';
7
8
  import { type MastraAgentConfig, type SkillSearchHandle, type ToolSearchHandle } from './tool-search.js';
8
- import type { LLMGatewayClient } from '@salesforce/llm-gateway-sdk';
9
+ import { type LLMGatewayClient, type MultimodalFile } from '@salesforce/llm-gateway-sdk';
9
10
  import { Clock, type LogRecord, type UniqueIDGenerator, type Unsubscribe } from '@salesforce/agentic-common';
10
11
  import { type ToolsInput } from './utils.js';
11
12
  import { Workspace } from '@mastra/core/workspace';
@@ -103,6 +104,13 @@ interface McpServerState {
103
104
  interface MastraAgentState {
104
105
  /** Mastra Agent instance. */
105
106
  agent: Agent;
107
+ /**
108
+ * Pre-flight multimodal validation for this agent's model configuration.
109
+ * Captured from {@link ResolvedModelConfig.validateFiles} at `createAgent`
110
+ * time. Called by `toMastraStreamInput` before every stream that carries
111
+ * `image` or `file` parts. Throws `LLMGClientError` on violation.
112
+ */
113
+ validateFiles: (files: readonly MultimodalFile[]) => void;
106
114
  /** Per-server MCP state, keyed by server name. Empty map when no MCP servers are configured. */
107
115
  mcpServers: Map<string, McpServerState>;
108
116
  /** Original MCP configuration, retained so getMcpServerInfo can report disabled servers. */
@@ -111,6 +119,16 @@ interface MastraAgentState {
111
119
  mastraWorkspace?: Workspace;
112
120
  /** Tracks the active workflow run per thread for tool approval. */
113
121
  activeRuns: Map<string, ActiveRun>;
122
+ /**
123
+ * Per-thread MastraStreamBroker, allocated when a `stream()` call sets
124
+ * `requireToolApproval: true`. Owns the parallel-approval UX (#447):
125
+ * front-loaded `tool-approval-request` emission, decision buffering,
126
+ * Mastra suspend/resume coordination, per-tool sink routing, and the
127
+ * approval-timeout/abort lifecycle. When approval gating is off, the
128
+ * entry is absent and `stream()` falls through to `toChatStreamResult` /
129
+ * `createEventStream` (the pre-#447 path).
130
+ */
131
+ streamBrokers: Map<string, MastraStreamBroker>;
114
132
  /** Tool-search processor instance, when `toolSearch` is configured on the factory. */
115
133
  toolSearchProcessor?: ToolSearchProcessor;
116
134
  /** Skill-search processor instance, when both `skills` and `toolSearch` are configured. */
@@ -156,6 +174,25 @@ export type MastraAgentHarness = WithAgentConfig<AgentHarness & {
156
174
  * Mastra falls back to eager skill loading).
157
175
  */
158
176
  getSkillSearchProcessor(agentId: string): SkillSearchHandle | undefined;
177
+ /**
178
+ * Build the namespaced tool name Mastra registers for an
179
+ * MCP-discovered tool: `${serverName}_${toolName}`. Reach for
180
+ * this when constructing `MastraAgentConfig.toolSearch.alwaysActive`
181
+ * entries that reference MCP tools at agent-creation time, before
182
+ * MCP discovery has settled — without it you'd have to hard-code
183
+ * the namespaced string (brittle if the server name changes) or
184
+ * wait for discovery (which defeats the point of `alwaysActive`).
185
+ *
186
+ * Custom tools listed in `alwaysActive` should use their declared
187
+ * name directly; do NOT wrap them with this helper.
188
+ *
189
+ * The output format is **Mastra-specific** — Claude uses a
190
+ * different namespacing shape (`mcp__${server}__${tool}`). For
191
+ * cross-harness tool identification, use {@link McpToolInfo.serverName}
192
+ * + {@link McpToolInfo.toolName} (both populated identically by
193
+ * every harness) instead.
194
+ */
195
+ formatMcpToolName(serverName: string, toolName: string): string;
159
196
  };
160
197
  };
161
198
  }, MastraAgentConfig>;
@@ -332,7 +369,28 @@ export declare class MastraHarness implements MastraAgentHarness {
332
369
  * the thread's `ActiveRun` entry. See ARCHITECTURE.md → "Tool Approval Flow → Abort
333
370
  * during pending approval (#409)".
334
371
  */
335
- stream(agentId: string, threadId: string, message: string, options?: StreamOptions): Promise<ChatStreamResult>;
372
+ /**
373
+ * Maps an SDK `MessagePart[]` into the single AI SDK v5 user `ModelMessage` that
374
+ * `agent.stream()` accepts.
375
+ *
376
+ * `text` parts collapse into text content blocks; `image` / `file` parts become v5 `file`
377
+ * content blocks (`mediaType` + base64 `data` + optional `filename`) that Mastra forwards to the
378
+ * gateway bridge, which collects them into `ChatMessageIn.files[]`. Pre-stream validation and the
379
+ * input-part guard live in the SDK's {@link lowerStreamInput}, so file caps and the
380
+ * `MULTIMODAL_NOT_SUPPORTED` / `INVALID_MESSAGE_CONTENT` semantics are identical to the Claude
381
+ * harness; this method only supplies the Mastra-specific lowering of each part.
382
+ */
383
+ private toMastraStreamInput;
384
+ stream(agentId: string, threadId: string, message: string | MessagePart[], options?: StreamOptions): Promise<ChatStreamResult>;
385
+ /**
386
+ * Allocate a `MastraStreamBroker` for the (agentId, threadId) pair,
387
+ * dispose any prior broker on the same thread, hand the initial Mastra
388
+ * `output` to it, and wire the consumer's `abortSignal` (if any) to
389
+ * `broker.abort()`. The returned `ChatStreamResult.eventStream` reads
390
+ * from the broker's initial sink, where parallel
391
+ * `tool-approval-request` events surface for batch-style consumer UI.
392
+ */
393
+ private startBrokerStream;
336
394
  /**
337
395
  * @requirements
338
396
  * - MUST throw an error if the specified `agentId` is not found in `activeAgents`.