@dbx-tools/appkit-mastra 0.1.28 → 0.1.30
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/dist/index.d.ts +4 -4
- package/dist/index.js +4 -4
- package/dist/src/agents.d.ts +1 -1
- package/dist/src/agents.js +5 -2
- package/dist/src/chart.js +1 -1
- package/dist/src/genie.js +1 -1
- package/dist/src/history.d.ts +1 -1
- package/dist/src/memory.js +1 -3
- package/dist/src/model.js +2 -2
- package/dist/src/observability.js +1 -3
- package/dist/src/plugin.js +1 -40
- package/dist/src/processor.d.ts +8 -0
- package/dist/src/processor.js +40 -0
- package/dist/src/processors/strip-stale-charts.js +1 -2
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/index.ts +14 -14
- package/package.json +5 -5
- package/src/agents.ts +7 -4
- package/src/chart.ts +1 -1
- package/src/genie.ts +2 -2
- package/src/history.ts +7 -9
- package/src/memory.ts +4 -12
- package/src/model.ts +2 -7
- package/src/observability.ts +1 -3
- package/src/plugin.ts +2 -43
- package/src/processor.ts +46 -0
- package/src/processors/strip-stale-charts.ts +3 -9
- package/src/tools/email.ts +29 -17
package/index.ts
CHANGED
|
@@ -10,30 +10,30 @@
|
|
|
10
10
|
* is the right surface for browser bundles and `usePluginClientConfig`
|
|
11
11
|
* consumers.
|
|
12
12
|
*/
|
|
13
|
-
export * from "./src/plugin.js";
|
|
14
13
|
export * from "@dbx-tools/appkit-mastra-shared";
|
|
15
|
-
export * from "./src/config.js";
|
|
16
14
|
export * from "./src/agents.js";
|
|
17
15
|
export * from "./src/chart.js";
|
|
16
|
+
export * from "./src/config.js";
|
|
18
17
|
export * from "./src/genie.js";
|
|
19
|
-
export * from "./src/tools/email.js";
|
|
20
18
|
export {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
FALLBACK_MODEL_IDS,
|
|
20
|
+
MODEL_CATALOG,
|
|
21
|
+
ModelTier,
|
|
22
|
+
modelForTier,
|
|
23
|
+
modelsForTier,
|
|
24
|
+
} from "./src/model.js";
|
|
25
|
+
export * from "./src/plugin.js";
|
|
26
|
+
export {
|
|
24
27
|
MASTRA_MODEL_OVERRIDE_KEY,
|
|
25
28
|
MODEL_OVERRIDE_BODY_FIELDS,
|
|
26
29
|
MODEL_OVERRIDE_HEADER,
|
|
27
30
|
MODEL_OVERRIDE_QUERY,
|
|
31
|
+
clearServingEndpointsCache,
|
|
32
|
+
extractModelOverride,
|
|
33
|
+
listServingEndpoints,
|
|
28
34
|
resolveModelId,
|
|
29
|
-
type ResolvedModel,
|
|
30
35
|
type ResolveModelOptions,
|
|
36
|
+
type ResolvedModel,
|
|
31
37
|
type ServingEndpointSummary,
|
|
32
38
|
} from "./src/serving.js";
|
|
33
|
-
export
|
|
34
|
-
FALLBACK_MODEL_IDS,
|
|
35
|
-
MODEL_CATALOG,
|
|
36
|
-
modelForTier,
|
|
37
|
-
modelsForTier,
|
|
38
|
-
ModelTier,
|
|
39
|
-
} from "./src/model.js";
|
|
39
|
+
export * from "./src/tools/email.js";
|
package/package.json
CHANGED
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
}
|
|
10
10
|
},
|
|
11
11
|
"name": "@dbx-tools/appkit-mastra",
|
|
12
|
-
"version": "0.1.
|
|
12
|
+
"version": "0.1.30",
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@databricks/sdk-experimental": "^0.17",
|
|
15
|
-
"@dbx-tools/appkit-mastra-shared": "0.1.
|
|
16
|
-
"@dbx-tools/genie": "0.1.
|
|
17
|
-
"@dbx-tools/genie-shared": "0.1.
|
|
18
|
-
"@dbx-tools/shared": "0.1.
|
|
15
|
+
"@dbx-tools/appkit-mastra-shared": "0.1.30",
|
|
16
|
+
"@dbx-tools/genie": "0.1.30",
|
|
17
|
+
"@dbx-tools/genie-shared": "0.1.30",
|
|
18
|
+
"@dbx-tools/shared": "0.1.30",
|
|
19
19
|
"@mastra/ai-sdk": "^1",
|
|
20
20
|
"@mastra/core": "^1",
|
|
21
21
|
"@mastra/express": "^1",
|
package/src/agents.ts
CHANGED
|
@@ -14,18 +14,19 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import { appkitUtils, logUtils, stringUtils } from "@dbx-tools/shared";
|
|
17
|
-
import { Agent } from "@mastra/core/agent";
|
|
18
17
|
import type { AgentConfig, ToolsInput } from "@mastra/core/agent";
|
|
19
|
-
import {
|
|
18
|
+
import { Agent } from "@mastra/core/agent";
|
|
20
19
|
import type { Tool } from "@mastra/core/tools";
|
|
20
|
+
import { createTool } from "@mastra/core/tools";
|
|
21
21
|
import type { PgVectorConfig, PostgresStoreConfig } from "@mastra/pg";
|
|
22
22
|
|
|
23
|
+
import { buildRenderDataTool } from "./chart.js";
|
|
23
24
|
import type { MastraPluginConfig } from "./config.js";
|
|
24
25
|
import { buildGenieToolkitProvider, resolveGenieSpaces } from "./genie.js";
|
|
25
26
|
import type { MemoryBuilder } from "./memory.js";
|
|
26
27
|
import { buildModel, FALLBACK_MODEL_IDS } from "./model.js";
|
|
28
|
+
import { ResultProcessor } from "./processor.js";
|
|
27
29
|
import { stripStaleChartsProcessor } from "./processors/strip-stale-charts.js";
|
|
28
|
-
import { buildRenderDataTool } from "./chart.js";
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
32
|
* Tool record accepted by every Mastra `Agent.tools` field and by the
|
|
@@ -433,6 +434,7 @@ export async function buildAgents(opts: {
|
|
|
433
434
|
// chartIds from prior assistant tool results into the new
|
|
434
435
|
// turn's `[chart:<id>]` markers. Opt out per-plugin via
|
|
435
436
|
// `config.stripStaleCharts: false`.
|
|
437
|
+
const outputProcessors = [new ResultProcessor()];
|
|
436
438
|
const inputProcessors =
|
|
437
439
|
config.stripStaleCharts === false ? [] : [stripStaleChartsProcessor];
|
|
438
440
|
const agents: Record<string, Agent> = {};
|
|
@@ -451,7 +453,8 @@ export async function buildAgents(opts: {
|
|
|
451
453
|
},
|
|
452
454
|
tools,
|
|
453
455
|
...(memory ? { memory } : {}),
|
|
454
|
-
|
|
456
|
+
inputProcessors,
|
|
457
|
+
outputProcessors,
|
|
455
458
|
});
|
|
456
459
|
// Surface the effective default model per agent so operators can
|
|
457
460
|
// see at a glance which endpoint each agent points at without
|
package/src/chart.ts
CHANGED
|
@@ -39,7 +39,7 @@ import { createTool } from "@mastra/core/tools";
|
|
|
39
39
|
import { z } from "zod";
|
|
40
40
|
|
|
41
41
|
import type { MastraPluginConfig } from "./config.js";
|
|
42
|
-
import { buildModel,
|
|
42
|
+
import { buildModel, modelForTier, ModelTier } from "./model.js";
|
|
43
43
|
|
|
44
44
|
const log = logUtils.logger("mastra/chart");
|
|
45
45
|
|
package/src/genie.ts
CHANGED
|
@@ -36,13 +36,13 @@
|
|
|
36
36
|
|
|
37
37
|
import { CacheManager, genie } from "@databricks/appkit";
|
|
38
38
|
import { ApiError, HttpError, WorkspaceClient } from "@databricks/sdk-experimental";
|
|
39
|
-
import { genieEventChat } from "@dbx-tools/genie";
|
|
40
|
-
import { type GenieMessage } from "@dbx-tools/genie-shared";
|
|
41
39
|
import {
|
|
42
40
|
ChartSchema,
|
|
43
41
|
type MinimalWriter,
|
|
44
42
|
type StartedEvent,
|
|
45
43
|
} from "@dbx-tools/appkit-mastra-shared";
|
|
44
|
+
import { genieEventChat } from "@dbx-tools/genie";
|
|
45
|
+
import { type GenieMessage } from "@dbx-tools/genie-shared";
|
|
46
46
|
import {
|
|
47
47
|
apiUtils,
|
|
48
48
|
appkitUtils,
|
package/src/history.ts
CHANGED
|
@@ -16,6 +16,11 @@
|
|
|
16
16
|
* session-cookie logic stays the single source of truth in `server.ts`.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
+
import type {
|
|
20
|
+
MastraClearHistoryResponse,
|
|
21
|
+
MastraHistoryResponse,
|
|
22
|
+
MastraHistoryUIMessage,
|
|
23
|
+
} from "@dbx-tools/appkit-mastra-shared";
|
|
19
24
|
import { commonUtils, logUtils } from "@dbx-tools/shared";
|
|
20
25
|
import { toAISdkV5Messages } from "@mastra/ai-sdk/ui";
|
|
21
26
|
import type { Agent } from "@mastra/core/agent";
|
|
@@ -24,13 +29,8 @@ import {
|
|
|
24
29
|
MASTRA_RESOURCE_ID_KEY,
|
|
25
30
|
MASTRA_THREAD_ID_KEY,
|
|
26
31
|
} from "@mastra/core/request-context";
|
|
27
|
-
import { registerApiRoute } from "@mastra/core/server";
|
|
28
32
|
import type { ContextWithMastra } from "@mastra/core/server";
|
|
29
|
-
import
|
|
30
|
-
MastraClearHistoryResponse,
|
|
31
|
-
MastraHistoryResponse,
|
|
32
|
-
MastraHistoryUIMessage,
|
|
33
|
-
} from "@dbx-tools/appkit-mastra-shared";
|
|
33
|
+
import { registerApiRoute } from "@mastra/core/server";
|
|
34
34
|
|
|
35
35
|
const log = logUtils.logger("mastra/history");
|
|
36
36
|
|
|
@@ -237,9 +237,7 @@ export function historyRoute(options: HistoryRouteOptions) {
|
|
|
237
237
|
error: c.json({ error: "thread id missing from request context" }, 400),
|
|
238
238
|
} as const;
|
|
239
239
|
}
|
|
240
|
-
const resourceId = requestContext.get(MASTRA_RESOURCE_ID_KEY) as
|
|
241
|
-
| string
|
|
242
|
-
| undefined;
|
|
240
|
+
const resourceId = requestContext.get(MASTRA_RESOURCE_ID_KEY) as string | undefined;
|
|
243
241
|
return { agentId, agent, threadId, resourceId } as const;
|
|
244
242
|
};
|
|
245
243
|
|
package/src/memory.ts
CHANGED
|
@@ -35,10 +35,7 @@ import { PgVector, PostgresStore } from "@mastra/pg";
|
|
|
35
35
|
import { randomUUID } from "node:crypto";
|
|
36
36
|
import type { Pool } from "pg";
|
|
37
37
|
|
|
38
|
-
import type {
|
|
39
|
-
MastraAgentDefinition,
|
|
40
|
-
MastraMemoryConfigOverride,
|
|
41
|
-
} from "./agents.js";
|
|
38
|
+
import type { MastraAgentDefinition, MastraMemoryConfigOverride } from "./agents.js";
|
|
42
39
|
import type { MastraPluginConfig } from "./config.js";
|
|
43
40
|
|
|
44
41
|
const log = logUtils.logger("mastra/memory");
|
|
@@ -63,8 +60,7 @@ export function needsLakebase(config: MastraPluginConfig): boolean {
|
|
|
63
60
|
if (settingNeedsSharedPool(config.memory)) return true;
|
|
64
61
|
const defs = collectAgentDefinitions(config);
|
|
65
62
|
return defs.some(
|
|
66
|
-
(d) =>
|
|
67
|
-
settingNeedsSharedPool(d.storage) || settingNeedsSharedPool(d.memory),
|
|
63
|
+
(d) => settingNeedsSharedPool(d.storage) || settingNeedsSharedPool(d.memory),
|
|
68
64
|
);
|
|
69
65
|
}
|
|
70
66
|
|
|
@@ -169,9 +165,7 @@ export class MemoryBuilder {
|
|
|
169
165
|
...(vector ? { vector, embedder: fastembed } : {}),
|
|
170
166
|
options: {
|
|
171
167
|
lastMessages: 10,
|
|
172
|
-
...(vector
|
|
173
|
-
? { semanticRecall: { topK: 3, messageRange: 2 } }
|
|
174
|
-
: {}),
|
|
168
|
+
...(vector ? { semanticRecall: { topK: 3, messageRange: 2 } } : {}),
|
|
175
169
|
},
|
|
176
170
|
});
|
|
177
171
|
}
|
|
@@ -280,9 +274,7 @@ function settingNeedsSharedPool(
|
|
|
280
274
|
}
|
|
281
275
|
|
|
282
276
|
/** Walk the three shapes of `config.agents` into a flat list. */
|
|
283
|
-
function collectAgentDefinitions(
|
|
284
|
-
config: MastraPluginConfig,
|
|
285
|
-
): MastraAgentDefinition[] {
|
|
277
|
+
function collectAgentDefinitions(config: MastraPluginConfig): MastraAgentDefinition[] {
|
|
286
278
|
const agents = config.agents;
|
|
287
279
|
if (!agents) return [];
|
|
288
280
|
if (Array.isArray(agents)) return agents;
|
package/src/model.ts
CHANGED
|
@@ -25,12 +25,7 @@
|
|
|
25
25
|
* the input verbatim and let Databricks return the canonical error.
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
|
-
import {
|
|
29
|
-
commonUtils,
|
|
30
|
-
logUtils,
|
|
31
|
-
netUtils,
|
|
32
|
-
stringUtils,
|
|
33
|
-
} from "@dbx-tools/shared";
|
|
28
|
+
import { commonUtils, logUtils, netUtils, stringUtils } from "@dbx-tools/shared";
|
|
34
29
|
import type { MastraModelConfig } from "@mastra/core/llm";
|
|
35
30
|
import type { RequestContext } from "@mastra/core/request-context";
|
|
36
31
|
|
|
@@ -390,7 +385,7 @@ const setupFetchInterceptor = commonUtils.memoize((): void => {
|
|
|
390
385
|
const log = logUtils.logger("mastra/llm");
|
|
391
386
|
const original = globalThis.fetch.bind(globalThis);
|
|
392
387
|
globalThis.fetch = (async (input, init) => {
|
|
393
|
-
const url = netUtils.
|
|
388
|
+
const url = netUtils.urlBuilder(input);
|
|
394
389
|
if (
|
|
395
390
|
!url ||
|
|
396
391
|
!url.pathname.startsWith(SERVING_ENDPOINTS_PATH_PREFIX) ||
|
package/src/observability.ts
CHANGED
|
@@ -76,9 +76,7 @@ export async function buildObservability(
|
|
|
76
76
|
options?: BuildObservabilityOptions,
|
|
77
77
|
): Promise<Observability | undefined> {
|
|
78
78
|
const serviceName =
|
|
79
|
-
options?.serviceName ??
|
|
80
|
-
(await projectUtils.name()) ??
|
|
81
|
-
DEFAULT_SERVICE_NAME;
|
|
79
|
+
options?.serviceName ?? (await projectUtils.name()) ?? DEFAULT_SERVICE_NAME;
|
|
82
80
|
const requestContextKeys = [
|
|
83
81
|
...(options?.requestContextKeys ?? TRACE_REQUEST_CONTEXT_KEYS),
|
|
84
82
|
];
|
package/src/plugin.ts
CHANGED
|
@@ -37,27 +37,23 @@ import {
|
|
|
37
37
|
type PluginManifest,
|
|
38
38
|
type ResourceRequirement,
|
|
39
39
|
} from "@databricks/appkit";
|
|
40
|
-
import { appkitUtils,
|
|
40
|
+
import { appkitUtils, logUtils } from "@dbx-tools/shared";
|
|
41
41
|
import { chatRoute } from "@mastra/ai-sdk";
|
|
42
42
|
import type { Agent } from "@mastra/core/agent";
|
|
43
43
|
import { Mastra } from "@mastra/core/mastra";
|
|
44
44
|
import express from "express";
|
|
45
45
|
|
|
46
|
-
import { buildAgents, FALLBACK_AGENT_ID, type BuiltAgents } from "./agents.js";
|
|
47
46
|
import type {
|
|
48
47
|
MastraClientConfig,
|
|
49
48
|
StatementData,
|
|
50
49
|
} from "@dbx-tools/appkit-mastra-shared";
|
|
50
|
+
import { buildAgents, FALLBACK_AGENT_ID, type BuiltAgents } from "./agents.js";
|
|
51
51
|
import { fetchChart } from "./chart.js";
|
|
52
52
|
import type { MastraPluginConfig } from "./config.js";
|
|
53
53
|
import { historyRoute } from "./history.js";
|
|
54
54
|
import { createMemoryBuilder, needsLakebase } from "./memory.js";
|
|
55
55
|
import { buildObservability } from "./observability.js";
|
|
56
56
|
import { attachRoutePatchMiddleware, MastraServer } from "./server.js";
|
|
57
|
-
import {
|
|
58
|
-
installStreamEventInterceptor,
|
|
59
|
-
type StreamFrameInterceptor,
|
|
60
|
-
} from "./intercept.js";
|
|
61
57
|
import {
|
|
62
58
|
clearServingEndpointsCache,
|
|
63
59
|
listServingEndpoints,
|
|
@@ -311,11 +307,6 @@ export class MastraPlugin extends Plugin<MastraPluginConfig> {
|
|
|
311
307
|
|
|
312
308
|
router.use("", (req, res, next) => {
|
|
313
309
|
if (!this.mastraApp) return res.status(503).end();
|
|
314
|
-
// Run each Mastra `/stream` SSE frame through the interceptor
|
|
315
|
-
// (keep / rewrite / drop). Only engages on a
|
|
316
|
-
// `200 text/event-stream` body, so the JSON routes above and any
|
|
317
|
-
// error response are untouched.
|
|
318
|
-
installStreamEventInterceptor(res, interceptStreamFrame);
|
|
319
310
|
return this.userScopedSelf(req).mastraApp!(req, res, next);
|
|
320
311
|
});
|
|
321
312
|
}
|
|
@@ -502,36 +493,4 @@ function parseStatementLimit(raw: unknown): number | undefined {
|
|
|
502
493
|
return Math.floor(n);
|
|
503
494
|
}
|
|
504
495
|
|
|
505
|
-
/**
|
|
506
|
-
* {@link StreamFrameInterceptor} for Mastra `/stream` responses.
|
|
507
|
-
*
|
|
508
|
-
* Removes large, redundant payloads from terminal `step-finish`,
|
|
509
|
-
* `finish`, and `tool-result` frames before they reach the browser.
|
|
510
|
-
* These frames often repeat information already delivered incrementally
|
|
511
|
-
* via streamed text and tool events, including full tool outputs,
|
|
512
|
-
* accumulated responses, message history, SQL results, chart data, and
|
|
513
|
-
* other large result payloads.
|
|
514
|
-
*
|
|
515
|
-
* The interceptor deletes heavyweight payload properties
|
|
516
|
-
* (`output`, `messages`, `response`, and `result`) while preserving the
|
|
517
|
-
* event envelope and lifecycle metadata required by the client.
|
|
518
|
-
*
|
|
519
|
-
* Deletion is key based, so streams that do not contain these
|
|
520
|
-
* fields are passed through unchanged.
|
|
521
|
-
*/
|
|
522
|
-
const interceptStreamFrame: StreamFrameInterceptor = (chunk) => {
|
|
523
|
-
if (!commonUtils.isRecord(chunk)) return true;
|
|
524
|
-
if (!["step-finish", "finish", "tool-result"].find((type) => type === chunk.type))
|
|
525
|
-
return true;
|
|
526
|
-
const payload = chunk.payload;
|
|
527
|
-
if (!commonUtils.isRecord(payload)) return true;
|
|
528
|
-
const trimmedPayload = commonUtils.deleteKeys(payload, [
|
|
529
|
-
"output",
|
|
530
|
-
"messages",
|
|
531
|
-
"response",
|
|
532
|
-
"result",
|
|
533
|
-
]);
|
|
534
|
-
return trimmedPayload ? { replace: chunk } : true;
|
|
535
|
-
};
|
|
536
|
-
|
|
537
496
|
export const mastra = toPlugin(MastraPlugin);
|
package/src/processor.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Processor } from "@mastra/core/processors";
|
|
2
|
+
|
|
3
|
+
export class ResultProcessor implements Processor {
|
|
4
|
+
id = "result-processor";
|
|
5
|
+
|
|
6
|
+
// Tell Mastra to also route tool/data parts to this processor method
|
|
7
|
+
processDataParts = true;
|
|
8
|
+
|
|
9
|
+
async processOutputStream({ part }: { part: any }): Promise<any | null> {
|
|
10
|
+
// 1. Guard clause: Ensure the chunk is a valid object
|
|
11
|
+
if (!part || typeof part !== "object") {
|
|
12
|
+
return part;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// 2. Filter for the targeted frame types
|
|
16
|
+
const targetedTypes = ["step-finish", "finish", "tool-result", "data-tool-agent"];
|
|
17
|
+
if (!targetedTypes.includes(part.type)) {
|
|
18
|
+
return part; // Return unchanged to pass-through
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// 3. Check for the presence of a payload object
|
|
22
|
+
const payload = part.payload;
|
|
23
|
+
if (!payload || typeof payload !== "object") {
|
|
24
|
+
return part;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// 4. Safely delete the unwanted keys from the payload reference
|
|
28
|
+
const keysToDelete = ["output", "messages", "response", "result"];
|
|
29
|
+
for (const key of keysToDelete) {
|
|
30
|
+
if (key in payload) {
|
|
31
|
+
const value = payload[key];
|
|
32
|
+
if (typeof value === "object") {
|
|
33
|
+
payload[key] = {};
|
|
34
|
+
} else if (Array.isArray(value)) {
|
|
35
|
+
payload[key] = [];
|
|
36
|
+
} else {
|
|
37
|
+
delete payload[key];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 5. Return the modified part object. Mastra handles re-serialization
|
|
43
|
+
// for the outbound SSE client stream automatically.
|
|
44
|
+
return part;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -24,10 +24,7 @@
|
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
import { logUtils } from "@dbx-tools/shared";
|
|
27
|
-
import type {
|
|
28
|
-
InputProcessor,
|
|
29
|
-
ProcessInputArgs,
|
|
30
|
-
} from "@mastra/core/processors";
|
|
27
|
+
import type { InputProcessor, ProcessInputArgs } from "@mastra/core/processors";
|
|
31
28
|
|
|
32
29
|
const log = logUtils.logger("mastra/processor/strip-stale-charts");
|
|
33
30
|
|
|
@@ -76,13 +73,10 @@ export const stripStaleChartsProcessor: InputProcessor = {
|
|
|
76
73
|
// the chartId there is the model's outgoing claim, not
|
|
77
74
|
// anything it could re-reference; only `result` carries
|
|
78
75
|
// ids that subsequent turns might copy.
|
|
79
|
-
if (
|
|
80
|
-
(part as { type?: unknown }).type !== "tool-invocation"
|
|
81
|
-
) {
|
|
76
|
+
if ((part as { type?: unknown }).type !== "tool-invocation") {
|
|
82
77
|
continue;
|
|
83
78
|
}
|
|
84
|
-
const inv = (part as { toolInvocation?: { result?: unknown } })
|
|
85
|
-
.toolInvocation;
|
|
79
|
+
const inv = (part as { toolInvocation?: { result?: unknown } }).toolInvocation;
|
|
86
80
|
if (!inv || inv.result === undefined) continue;
|
|
87
81
|
const before = inv.result;
|
|
88
82
|
const after = stripChartIds(before);
|
package/src/tools/email.ts
CHANGED
|
@@ -33,41 +33,55 @@ import { z } from "zod";
|
|
|
33
33
|
const log = logUtils.logger("mastra/tool/send-email");
|
|
34
34
|
|
|
35
35
|
const emailInputSchema = z.object({
|
|
36
|
-
to: z.string().describe(
|
|
36
|
+
to: z.string().describe(
|
|
37
|
+
stringUtils.toDescription(`
|
|
37
38
|
Single recipient email address (e.g. "alice@example.com"). For
|
|
38
39
|
multiple recipients, comma-separate them yourself.
|
|
39
|
-
`)
|
|
40
|
-
|
|
40
|
+
`),
|
|
41
|
+
),
|
|
42
|
+
subject: z.string().describe(
|
|
43
|
+
stringUtils.toDescription(`
|
|
41
44
|
Subject line.
|
|
42
|
-
`)
|
|
43
|
-
|
|
45
|
+
`),
|
|
46
|
+
),
|
|
47
|
+
body: z.string().describe(
|
|
48
|
+
stringUtils.toDescription(`
|
|
44
49
|
Email body. Plain text or markdown; the renderer downstream decides
|
|
45
50
|
which to honour. Be specific - the recipient may not have any
|
|
46
51
|
context the model has from prior chat turns.
|
|
47
|
-
`)
|
|
52
|
+
`),
|
|
53
|
+
),
|
|
48
54
|
cc: z
|
|
49
55
|
.array(z.string())
|
|
50
56
|
.optional()
|
|
51
|
-
.describe(
|
|
57
|
+
.describe(
|
|
58
|
+
stringUtils.toDescription(`
|
|
52
59
|
Optional CC recipients.
|
|
53
|
-
`)
|
|
60
|
+
`),
|
|
61
|
+
),
|
|
54
62
|
bcc: z
|
|
55
63
|
.array(z.string())
|
|
56
64
|
.optional()
|
|
57
|
-
.describe(
|
|
65
|
+
.describe(
|
|
66
|
+
stringUtils.toDescription(`
|
|
58
67
|
Optional BCC recipients.
|
|
59
|
-
`)
|
|
68
|
+
`),
|
|
69
|
+
),
|
|
60
70
|
});
|
|
61
71
|
|
|
62
72
|
const emailOutputSchema = z.object({
|
|
63
|
-
sent: z.boolean().describe(
|
|
73
|
+
sent: z.boolean().describe(
|
|
74
|
+
stringUtils.toDescription(`
|
|
64
75
|
True when the email was dispatched. The current implementation
|
|
65
76
|
always returns true after console-logging the would-be email; swap
|
|
66
77
|
in a real provider to make this meaningful.
|
|
67
|
-
`)
|
|
68
|
-
|
|
78
|
+
`),
|
|
79
|
+
),
|
|
80
|
+
recipient: z.string().describe(
|
|
81
|
+
stringUtils.toDescription(`
|
|
69
82
|
Echo of the \`to\` field for confirmation.
|
|
70
|
-
`)
|
|
83
|
+
`),
|
|
84
|
+
),
|
|
71
85
|
});
|
|
72
86
|
|
|
73
87
|
/** Options accepted by {@link buildEmailTool}. */
|
|
@@ -123,9 +137,7 @@ export function buildEmailTool(opts: BuildEmailToolOptions = {}) {
|
|
|
123
137
|
outputSchema: emailOutputSchema,
|
|
124
138
|
requireApproval: true,
|
|
125
139
|
execute: async (input) => {
|
|
126
|
-
const { to, subject, body, cc, bcc } = input as z.infer<
|
|
127
|
-
typeof emailInputSchema
|
|
128
|
-
>;
|
|
140
|
+
const { to, subject, body, cc, bcc } = input as z.infer<typeof emailInputSchema>;
|
|
129
141
|
// Default behaviour: dump the email to the server console so
|
|
130
142
|
// demos can see the gate fire end-to-end without a real
|
|
131
143
|
// provider. Replace by passing `opts.send`.
|