@dbx-tools/appkit-mastra 0.1.5 → 0.1.10
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 +394 -0
- package/index.ts +46 -37
- package/package.json +58 -47
- package/src/agents.ts +233 -62
- package/src/chart.ts +555 -285
- package/src/config.ts +282 -18
- package/src/filesystems.ts +1090 -0
- package/src/genie.ts +1004 -601
- package/src/history.ts +178 -79
- package/src/mcp.ts +105 -0
- package/src/memory.ts +129 -74
- package/src/mlflow.ts +149 -0
- package/src/model.ts +80 -408
- package/src/observability.ts +144 -0
- package/src/pagination.ts +34 -0
- package/src/plugin.ts +573 -59
- package/src/processors.ts +168 -0
- package/src/rest.ts +67 -0
- package/src/server.ts +243 -45
- package/src/serving-sanitize.ts +167 -0
- package/src/serving.ts +27 -224
- package/src/statement.ts +89 -0
- package/src/storage-schema.ts +41 -0
- package/src/summarize.ts +176 -0
- package/src/threads.ts +338 -0
- package/src/workspaces.ts +346 -0
- package/src/writer.ts +44 -0
- package/tsconfig.json +41 -0
- package/dist/index.d.ts +0 -19
- package/dist/index.js +0 -19
- package/dist/src/agents.d.ts +0 -306
- package/dist/src/agents.js +0 -393
- package/dist/src/chart.d.ts +0 -104
- package/dist/src/chart.js +0 -375
- package/dist/src/config.d.ts +0 -170
- package/dist/src/config.js +0 -12
- package/dist/src/genie.d.ts +0 -116
- package/dist/src/genie.js +0 -594
- package/dist/src/history.d.ts +0 -67
- package/dist/src/history.js +0 -158
- package/dist/src/memory.d.ts +0 -79
- package/dist/src/memory.js +0 -197
- package/dist/src/model.d.ts +0 -159
- package/dist/src/model.js +0 -423
- package/dist/src/plugin.d.ts +0 -130
- package/dist/src/plugin.js +0 -255
- package/dist/src/render-chart-route.d.ts +0 -33
- package/dist/src/render-chart-route.js +0 -120
- package/dist/src/server.d.ts +0 -46
- package/dist/src/server.js +0 -113
- package/dist/src/serving.d.ts +0 -156
- package/dist/src/serving.js +0 -214
- package/src/render-chart-route.ts +0 -141
package/dist/src/chart.d.ts
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Chart-rendering primitives.
|
|
3
|
-
*
|
|
4
|
-
* Two surfaces, one shared brain:
|
|
5
|
-
*
|
|
6
|
-
* - {@link buildRenderDataTool}: a Mastra tool the model calls
|
|
7
|
-
* ("here is a dataset, render it as a chart"). The tool is
|
|
8
|
-
* fire-and-forget by design - it generates a short `chartId`,
|
|
9
|
-
* pushes a single `kind: "chart"` event onto `ctx.writer` carrying
|
|
10
|
-
* the raw rows, and returns the id to the model immediately. No
|
|
11
|
-
* chart planning happens inside the agentic loop, so the model
|
|
12
|
-
* never blocks on a downstream LLM call to get its identifier.
|
|
13
|
-
*
|
|
14
|
-
* - {@link runChartPlanner}: the chart-planner Agent + ECOption
|
|
15
|
-
* expansion as a plain async function. The HTTP route in
|
|
16
|
-
* {@link ./render-chart-route.ts} calls this when the client
|
|
17
|
-
* POSTs the dataset back; the result is an `EChartsOption` JSON
|
|
18
|
-
* the React `<ChartSlot>` renders inline. Decoupling the planner
|
|
19
|
-
* from the tool means the planning latency lives entirely
|
|
20
|
-
* client-side: the model can finish writing its report while
|
|
21
|
-
* the client is still rendering the charts.
|
|
22
|
-
*
|
|
23
|
-
* The model wires the chart into its reply by emitting the marker
|
|
24
|
-
* `[[chart:<chartId>]]` on its own line in markdown. The chat
|
|
25
|
-
* client splits the assistant text on these markers and drops a
|
|
26
|
-
* `<ChartSlot>` in at the position the model placed it; the slot
|
|
27
|
-
* then fires the render-chart endpoint on mount and shows a
|
|
28
|
-
* skeleton until the option lands.
|
|
29
|
-
*/
|
|
30
|
-
import type { RequestContext } from "@mastra/core/request-context";
|
|
31
|
-
import { z } from "zod";
|
|
32
|
-
import type { MastraPluginConfig } from "./config.js";
|
|
33
|
-
/**
|
|
34
|
-
* Compact, model-friendly representation of an Echarts spec. The
|
|
35
|
-
* planner agent emits this; {@link planToEchartsOption} expands it
|
|
36
|
-
* into a real `EChartsOption` JSON. Two layers because letting the
|
|
37
|
-
* model fill in a fully-typed `EChartsOption` is brittle (hundreds
|
|
38
|
-
* of optional fields, deep unions, version-dependent shapes). A
|
|
39
|
-
* small "chart plan" schema is much more reliable for a fast model
|
|
40
|
-
* and keeps animation / tooltip / styling defaults consistent
|
|
41
|
-
* across charts.
|
|
42
|
-
*/
|
|
43
|
-
declare const chartPlanSchema: z.ZodObject<{
|
|
44
|
-
chartType: z.ZodEnum<{
|
|
45
|
-
bar: "bar";
|
|
46
|
-
line: "line";
|
|
47
|
-
area: "area";
|
|
48
|
-
scatter: "scatter";
|
|
49
|
-
pie: "pie";
|
|
50
|
-
}>;
|
|
51
|
-
title: z.ZodOptional<z.ZodString>;
|
|
52
|
-
xAxisLabel: z.ZodOptional<z.ZodString>;
|
|
53
|
-
yAxisLabel: z.ZodOptional<z.ZodString>;
|
|
54
|
-
categories: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
55
|
-
series: z.ZodArray<z.ZodObject<{
|
|
56
|
-
name: z.ZodString;
|
|
57
|
-
data: z.ZodArray<z.ZodUnion<readonly [z.ZodNumber, z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, z.ZodObject<{
|
|
58
|
-
name: z.ZodString;
|
|
59
|
-
value: z.ZodNumber;
|
|
60
|
-
}, z.core.$strip>]>>;
|
|
61
|
-
}, z.core.$strip>>;
|
|
62
|
-
}, z.core.$strip>;
|
|
63
|
-
type ChartPlan = z.infer<typeof chartPlanSchema>;
|
|
64
|
-
/** Inputs to {@link runChartPlanner}. */
|
|
65
|
-
export interface RunChartPlannerOptions {
|
|
66
|
-
config: MastraPluginConfig;
|
|
67
|
-
requestContext?: RequestContext;
|
|
68
|
-
title: string;
|
|
69
|
-
description?: string;
|
|
70
|
-
data: ReadonlyArray<Record<string, unknown>>;
|
|
71
|
-
}
|
|
72
|
-
/** Output of {@link runChartPlanner}: a fully-formed Echarts spec. */
|
|
73
|
-
export interface RunChartPlannerResult {
|
|
74
|
-
option: Record<string, unknown>;
|
|
75
|
-
chartType: ChartPlan["chartType"];
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Run the chart planner against the given dataset and return a
|
|
79
|
-
* full Echarts `EChartsOption` JSON. Used by the HTTP route the
|
|
80
|
-
* client hits when it sees a `[[chart:<chartId>]]` marker; the
|
|
81
|
-
* tool itself does not call this so the model never blocks on
|
|
82
|
-
* planning latency.
|
|
83
|
-
*/
|
|
84
|
-
export declare function runChartPlanner(opts: RunChartPlannerOptions): Promise<RunChartPlannerResult>;
|
|
85
|
-
/**
|
|
86
|
-
* Build the `render_data` tool bound to the given plugin config.
|
|
87
|
-
*
|
|
88
|
-
* Fire-and-forget by design: the tool returns immediately with a
|
|
89
|
-
* short `chartId` and emits a single `kind: "chart"` event over
|
|
90
|
-
* `ctx.writer` carrying the raw dataset for the client. The
|
|
91
|
-
* client's chart slot then POSTs the data to
|
|
92
|
-
* `/route/render-chart` to get an `EChartsOption` back from the
|
|
93
|
-
* planner agent. This keeps the calling LLM unblocked - it can
|
|
94
|
-
* write the report referencing the chart by id while the client
|
|
95
|
-
* is still rendering it.
|
|
96
|
-
*/
|
|
97
|
-
export declare function buildRenderDataTool(_config: MastraPluginConfig): import("@mastra/core/tools").Tool<{
|
|
98
|
-
title: string;
|
|
99
|
-
data: Record<string, unknown>[];
|
|
100
|
-
description?: string | undefined;
|
|
101
|
-
}, {
|
|
102
|
-
chartId: string;
|
|
103
|
-
}, unknown, unknown, import("@mastra/core/tools").ToolExecutionContext<unknown, unknown, unknown>, "render_data", unknown>;
|
|
104
|
-
export {};
|
package/dist/src/chart.js
DELETED
|
@@ -1,375 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Chart-rendering primitives.
|
|
3
|
-
*
|
|
4
|
-
* Two surfaces, one shared brain:
|
|
5
|
-
*
|
|
6
|
-
* - {@link buildRenderDataTool}: a Mastra tool the model calls
|
|
7
|
-
* ("here is a dataset, render it as a chart"). The tool is
|
|
8
|
-
* fire-and-forget by design - it generates a short `chartId`,
|
|
9
|
-
* pushes a single `kind: "chart"` event onto `ctx.writer` carrying
|
|
10
|
-
* the raw rows, and returns the id to the model immediately. No
|
|
11
|
-
* chart planning happens inside the agentic loop, so the model
|
|
12
|
-
* never blocks on a downstream LLM call to get its identifier.
|
|
13
|
-
*
|
|
14
|
-
* - {@link runChartPlanner}: the chart-planner Agent + ECOption
|
|
15
|
-
* expansion as a plain async function. The HTTP route in
|
|
16
|
-
* {@link ./render-chart-route.ts} calls this when the client
|
|
17
|
-
* POSTs the dataset back; the result is an `EChartsOption` JSON
|
|
18
|
-
* the React `<ChartSlot>` renders inline. Decoupling the planner
|
|
19
|
-
* from the tool means the planning latency lives entirely
|
|
20
|
-
* client-side: the model can finish writing its report while
|
|
21
|
-
* the client is still rendering the charts.
|
|
22
|
-
*
|
|
23
|
-
* The model wires the chart into its reply by emitting the marker
|
|
24
|
-
* `[[chart:<chartId>]]` on its own line in markdown. The chat
|
|
25
|
-
* client splits the assistant text on these markers and drops a
|
|
26
|
-
* `<ChartSlot>` in at the position the model placed it; the slot
|
|
27
|
-
* then fires the render-chart endpoint on mount and shows a
|
|
28
|
-
* skeleton until the option lands.
|
|
29
|
-
*/
|
|
30
|
-
import { randomUUID } from "node:crypto";
|
|
31
|
-
import { stringUtils } from "@dbx-tools/appkit-shared";
|
|
32
|
-
import { Agent } from "@mastra/core/agent";
|
|
33
|
-
import { createTool } from "@mastra/core/tools";
|
|
34
|
-
import { z } from "zod";
|
|
35
|
-
import { ModelTier, modelForTier, buildModel } from "./model.js";
|
|
36
|
-
/**
|
|
37
|
-
* Compact, model-friendly representation of an Echarts spec. The
|
|
38
|
-
* planner agent emits this; {@link planToEchartsOption} expands it
|
|
39
|
-
* into a real `EChartsOption` JSON. Two layers because letting the
|
|
40
|
-
* model fill in a fully-typed `EChartsOption` is brittle (hundreds
|
|
41
|
-
* of optional fields, deep unions, version-dependent shapes). A
|
|
42
|
-
* small "chart plan" schema is much more reliable for a fast model
|
|
43
|
-
* and keeps animation / tooltip / styling defaults consistent
|
|
44
|
-
* across charts.
|
|
45
|
-
*/
|
|
46
|
-
const chartPlanSchema = z.object({
|
|
47
|
-
chartType: z
|
|
48
|
-
.enum(["bar", "line", "area", "scatter", "pie"])
|
|
49
|
-
.describe(stringUtils.toDescription `
|
|
50
|
-
The chart shape that best matches the data and intent. Use
|
|
51
|
-
\`bar\` for category-vs-value comparisons, \`line\` for
|
|
52
|
-
trends over an ordered axis, \`area\` for stacked-trend
|
|
53
|
-
emphasis, \`scatter\` for two-numeric-axis correlations,
|
|
54
|
-
\`pie\` for parts-of-a-whole when categories are few.
|
|
55
|
-
`),
|
|
56
|
-
title: z.string().optional().describe(stringUtils.toDescription `
|
|
57
|
-
Short title shown above the chart. Optional; defaults to the
|
|
58
|
-
\`title\` argument the caller passed in.
|
|
59
|
-
`),
|
|
60
|
-
xAxisLabel: z.string().optional().describe(stringUtils.toDescription `
|
|
61
|
-
Axis label below the chart. Used for bar / line / area /
|
|
62
|
-
scatter; ignored for pie.
|
|
63
|
-
`),
|
|
64
|
-
yAxisLabel: z.string().optional().describe(stringUtils.toDescription `
|
|
65
|
-
Axis label to the left of the chart. Used for bar / line /
|
|
66
|
-
area / scatter; ignored for pie.
|
|
67
|
-
`),
|
|
68
|
-
categories: z
|
|
69
|
-
.array(z.string())
|
|
70
|
-
.optional()
|
|
71
|
-
.describe(stringUtils.toDescription `
|
|
72
|
-
X-axis category labels for \`bar\` / \`line\` / \`area\`
|
|
73
|
-
charts (one per data point in each series). Omit for
|
|
74
|
-
\`scatter\` (uses [x, y] tuples) and \`pie\` (each slice
|
|
75
|
-
carries its own \`name\`).
|
|
76
|
-
`),
|
|
77
|
-
series: z
|
|
78
|
-
.array(z.object({
|
|
79
|
-
name: z.string().describe(stringUtils.toDescription `
|
|
80
|
-
Legend name for this series.
|
|
81
|
-
`),
|
|
82
|
-
data: z
|
|
83
|
-
.array(z.union([
|
|
84
|
-
z.number(),
|
|
85
|
-
z.tuple([z.number(), z.number()]),
|
|
86
|
-
z.object({
|
|
87
|
-
name: z.string(),
|
|
88
|
-
value: z.number(),
|
|
89
|
-
}),
|
|
90
|
-
]))
|
|
91
|
-
.describe(stringUtils.toDescription `
|
|
92
|
-
Data points. For \`bar\` / \`line\` / \`area\`, an
|
|
93
|
-
array of numbers aligned to \`categories\`. For
|
|
94
|
-
\`scatter\`, an array of \`[x, y]\` numeric tuples.
|
|
95
|
-
For \`pie\`, an array of \`{name, value}\` objects.
|
|
96
|
-
`),
|
|
97
|
-
}))
|
|
98
|
-
.min(1)
|
|
99
|
-
.describe(stringUtils.toDescription `
|
|
100
|
-
One or more series to plot. Pie charts use exactly one
|
|
101
|
-
series; bar/line/area can stack multiple series sharing
|
|
102
|
-
the same \`categories\` axis.
|
|
103
|
-
`),
|
|
104
|
-
});
|
|
105
|
-
/**
|
|
106
|
-
* System prompt for the inner chart-planning agent. Tuned for a
|
|
107
|
-
* fast-tier model (Haiku, GPT-5-mini, Gemini Flash Lite).
|
|
108
|
-
*/
|
|
109
|
-
const CHART_PLANNER_INSTRUCTIONS = stringUtils.toDescription `
|
|
110
|
-
You design Apache Echarts visualizations. The user gives you a
|
|
111
|
-
tabular dataset (rows of objects) plus a title and an optional
|
|
112
|
-
description of the intent. You produce a small chart plan
|
|
113
|
-
(chart type, axis labels, categories, series) that best
|
|
114
|
-
conveys the data.
|
|
115
|
-
|
|
116
|
-
Decision guide:
|
|
117
|
-
|
|
118
|
-
- bar: comparing a numeric value across a small/medium set of
|
|
119
|
-
discrete categories (top-N, ranking, group-by).
|
|
120
|
-
- line: ordered-axis trend (time series, sequence).
|
|
121
|
-
- area: same as line but emphasises magnitude or stacked
|
|
122
|
-
composition.
|
|
123
|
-
- scatter: two numeric axes, correlation between fields.
|
|
124
|
-
- pie: parts of a whole when 2-7 categories sum to a
|
|
125
|
-
meaningful total.
|
|
126
|
-
|
|
127
|
-
When in doubt between bar and line, prefer bar for unordered
|
|
128
|
-
categories and line for ordered ones (dates, time buckets,
|
|
129
|
-
ranks). Never pick pie for more than 7 slices.
|
|
130
|
-
|
|
131
|
-
For bar / line / area: pick one column as the category axis
|
|
132
|
-
(usually the only string-valued column) and one or more
|
|
133
|
-
numeric columns as series. Sort categories by the primary
|
|
134
|
-
series value descending unless the data is naturally ordered
|
|
135
|
-
(dates, ranks).
|
|
136
|
-
|
|
137
|
-
For pie: pick the category column for slice names and one
|
|
138
|
-
numeric column for slice values. Emit a single series.
|
|
139
|
-
|
|
140
|
-
For scatter: pick two numeric columns and emit \`[x, y]\`
|
|
141
|
-
tuples in a single series.
|
|
142
|
-
|
|
143
|
-
Keep series names human-readable (use the column name; title
|
|
144
|
-
case it lightly if needed). Keep titles concise; do not
|
|
145
|
-
repeat the user's title in xAxisLabel / yAxisLabel.
|
|
146
|
-
`;
|
|
147
|
-
/**
|
|
148
|
-
* Lazily-constructed inner agent shared across all calls in this
|
|
149
|
-
* process. The agent is stateless (no memory, no tools) so a
|
|
150
|
-
* single instance per plugin config is safe; model resolution
|
|
151
|
-
* still happens per-call against the live `requestContext`, so
|
|
152
|
-
* OBO auth stays user-scoped.
|
|
153
|
-
*/
|
|
154
|
-
function createChartPlannerAgent(config) {
|
|
155
|
-
return new Agent({
|
|
156
|
-
id: "render_chart_planner",
|
|
157
|
-
name: "Chart Planner",
|
|
158
|
-
description: "Picks chart type and axis encodings for a dataset.",
|
|
159
|
-
instructions: CHART_PLANNER_INSTRUCTIONS,
|
|
160
|
-
model: ({ requestContext }) => buildModel(config, requestContext, {
|
|
161
|
-
modelId: modelForTier(ModelTier.Fast),
|
|
162
|
-
}),
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Module-level cache: one chart-planner agent per plugin config
|
|
167
|
-
* instance. Keyed on the config object identity since each plugin
|
|
168
|
-
* mount provides its own resolver / fallbacks. Re-used across
|
|
169
|
-
* tool invocations and the render-chart HTTP route.
|
|
170
|
-
*/
|
|
171
|
-
const _plannerByConfig = new WeakMap();
|
|
172
|
-
function getPlannerAgent(config) {
|
|
173
|
-
let agent = _plannerByConfig.get(config);
|
|
174
|
-
if (!agent) {
|
|
175
|
-
agent = createChartPlannerAgent(config);
|
|
176
|
-
_plannerByConfig.set(config, agent);
|
|
177
|
-
}
|
|
178
|
-
return agent;
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* Run the chart planner against the given dataset and return a
|
|
182
|
-
* full Echarts `EChartsOption` JSON. Used by the HTTP route the
|
|
183
|
-
* client hits when it sees a `[[chart:<chartId>]]` marker; the
|
|
184
|
-
* tool itself does not call this so the model never blocks on
|
|
185
|
-
* planning latency.
|
|
186
|
-
*/
|
|
187
|
-
export async function runChartPlanner(opts) {
|
|
188
|
-
const { config, requestContext, title, description, data } = opts;
|
|
189
|
-
const planner = getPlannerAgent(config);
|
|
190
|
-
const prompt = [
|
|
191
|
-
`Title: ${title}`,
|
|
192
|
-
description ? `Intent: ${description}` : null,
|
|
193
|
-
"",
|
|
194
|
-
"Dataset (JSON, one row per object):",
|
|
195
|
-
"```json",
|
|
196
|
-
JSON.stringify(data, null, 2),
|
|
197
|
-
"```",
|
|
198
|
-
]
|
|
199
|
-
.filter((line) => line !== null)
|
|
200
|
-
.join("\n");
|
|
201
|
-
const result = await planner.generate(prompt, {
|
|
202
|
-
structuredOutput: { schema: chartPlanSchema },
|
|
203
|
-
...(requestContext ? { requestContext } : {}),
|
|
204
|
-
});
|
|
205
|
-
const plan = result.object;
|
|
206
|
-
const option = planToEchartsOption(plan, title);
|
|
207
|
-
return { option, chartType: plan.chartType };
|
|
208
|
-
}
|
|
209
|
-
const renderDataInputSchema = z.object({
|
|
210
|
-
title: z.string().describe(stringUtils.toDescription `
|
|
211
|
-
Title shown above the rendered chart. Use a concise
|
|
212
|
-
sentence-case label (e.g. "Top 10 SKUs by On-Hand Units").
|
|
213
|
-
`),
|
|
214
|
-
description: z.string().optional().describe(stringUtils.toDescription `
|
|
215
|
-
Optional one-line intent describing what insight the chart
|
|
216
|
-
should convey (e.g. "highlight the steep drop-off after
|
|
217
|
-
position 5", "compare quarterly revenue across regions").
|
|
218
|
-
The chart-planner reads this when picking the chart type and
|
|
219
|
-
axis encodings; the user does not see it directly.
|
|
220
|
-
`),
|
|
221
|
-
data: z
|
|
222
|
-
.array(z.record(z.string(), z.unknown()))
|
|
223
|
-
.min(1)
|
|
224
|
-
.describe(stringUtils.toDescription `
|
|
225
|
-
Tabular dataset to chart. One object per row, keyed by
|
|
226
|
-
column name. Values may be strings, numbers, booleans, or
|
|
227
|
-
null. The chart-planner decides which columns are
|
|
228
|
-
categories vs. numeric series. Cap at a few hundred rows
|
|
229
|
-
for legibility; sample / aggregate larger datasets first.
|
|
230
|
-
`),
|
|
231
|
-
});
|
|
232
|
-
const renderDataOutputSchema = z.object({
|
|
233
|
-
chartId: z.string().describe(stringUtils.toDescription `
|
|
234
|
-
Identifier of the queued chart. The tool returned
|
|
235
|
-
immediately - actual chart planning happens client-side
|
|
236
|
-
asynchronously. To position the chart in your reply, embed
|
|
237
|
-
the marker \`[[chart:<chartId>]]\` on its own line (with
|
|
238
|
-
blank lines above and below) where the chart should appear.
|
|
239
|
-
The client renders a skeleton there until the chart is
|
|
240
|
-
ready, then swaps in the visualization in place. You can
|
|
241
|
-
keep writing prose around the marker; the agent does not
|
|
242
|
-
need to wait for the chart to render.
|
|
243
|
-
`),
|
|
244
|
-
});
|
|
245
|
-
/**
|
|
246
|
-
* Build the `render_data` tool bound to the given plugin config.
|
|
247
|
-
*
|
|
248
|
-
* Fire-and-forget by design: the tool returns immediately with a
|
|
249
|
-
* short `chartId` and emits a single `kind: "chart"` event over
|
|
250
|
-
* `ctx.writer` carrying the raw dataset for the client. The
|
|
251
|
-
* client's chart slot then POSTs the data to
|
|
252
|
-
* `/route/render-chart` to get an `EChartsOption` back from the
|
|
253
|
-
* planner agent. This keeps the calling LLM unblocked - it can
|
|
254
|
-
* write the report referencing the chart by id while the client
|
|
255
|
-
* is still rendering it.
|
|
256
|
-
*/
|
|
257
|
-
export function buildRenderDataTool(_config) {
|
|
258
|
-
return createTool({
|
|
259
|
-
id: "render_data",
|
|
260
|
-
description: stringUtils.toDescription `
|
|
261
|
-
Submit a tabular dataset for inline rendering as a chart in
|
|
262
|
-
the user's view. Pass a title, the raw rows (array of
|
|
263
|
-
objects keyed by column name), and an optional one-line
|
|
264
|
-
description of the insight to highlight. Returns a short
|
|
265
|
-
\`chartId\` immediately - chart planning happens
|
|
266
|
-
asynchronously in the client, not in this turn, so the tool
|
|
267
|
-
does not block your prose.
|
|
268
|
-
|
|
269
|
-
Placement contract: embed \`[[chart:<chartId>]]\` on its own
|
|
270
|
-
line (blank lines above and below) wherever you want the
|
|
271
|
-
chart to appear in your reply. The client shows a skeleton
|
|
272
|
-
at that spot until the chart is ready, then swaps in the
|
|
273
|
-
rendered Echarts visualization. You can call
|
|
274
|
-
\`render_data\` multiple times in the same turn (the tool
|
|
275
|
-
is parallel-safe) and interleave the markers with prose so
|
|
276
|
-
each chart sits next to its commentary. A chart whose
|
|
277
|
-
marker is omitted falls through to the end of your reply
|
|
278
|
-
as a fallback - safe but less polished.
|
|
279
|
-
|
|
280
|
-
Use whenever a SQL row set, API response, or hand-built
|
|
281
|
-
dataset would land better as a picture than as a list or
|
|
282
|
-
table. Cap input at a few hundred rows; sample or
|
|
283
|
-
aggregate larger datasets first.
|
|
284
|
-
`,
|
|
285
|
-
inputSchema: renderDataInputSchema,
|
|
286
|
-
outputSchema: renderDataOutputSchema,
|
|
287
|
-
execute: async (input, ctx) => {
|
|
288
|
-
const { title, description, data } = input;
|
|
289
|
-
// Short, marker-friendly id. The LLM has to type this
|
|
290
|
-
// verbatim into the `[[chart:<id>]]` marker; an 8-hex-char
|
|
291
|
-
// prefix is unique within a single assistant turn (collision
|
|
292
|
-
// odds ~1 in 4 billion) and much less error-prone for the
|
|
293
|
-
// model to reproduce.
|
|
294
|
-
const chartId = randomUUID().replace(/-/g, "").slice(0, 8);
|
|
295
|
-
const writer = ctx
|
|
296
|
-
?.writer;
|
|
297
|
-
try {
|
|
298
|
-
await writer?.write({
|
|
299
|
-
kind: "chart",
|
|
300
|
-
chartId,
|
|
301
|
-
title,
|
|
302
|
-
...(description ? { description } : {}),
|
|
303
|
-
data,
|
|
304
|
-
});
|
|
305
|
-
}
|
|
306
|
-
catch {
|
|
307
|
-
// Ignore: the parent stream may have closed downstream.
|
|
308
|
-
}
|
|
309
|
-
return { chartId };
|
|
310
|
-
},
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* Expand a {@link ChartPlan} into a full Echarts `EChartsOption`
|
|
315
|
-
* JSON. Centralized here so the planner agent only fills in the
|
|
316
|
-
* compact plan shape; tooltip / animation / color / grid defaults
|
|
317
|
-
* stay consistent across charts and are easy to tune without
|
|
318
|
-
* retraining model behaviour.
|
|
319
|
-
*/
|
|
320
|
-
function planToEchartsOption(plan, fallbackTitle) {
|
|
321
|
-
const baseTitle = plan.title ?? fallbackTitle;
|
|
322
|
-
const grid = { left: 48, right: 24, top: 56, bottom: 48, containLabel: true };
|
|
323
|
-
if (plan.chartType === "pie") {
|
|
324
|
-
return {
|
|
325
|
-
title: { text: baseTitle, left: "center" },
|
|
326
|
-
tooltip: { trigger: "item" },
|
|
327
|
-
legend: { bottom: 0 },
|
|
328
|
-
series: [
|
|
329
|
-
{
|
|
330
|
-
name: plan.series[0]?.name ?? baseTitle,
|
|
331
|
-
type: "pie",
|
|
332
|
-
radius: ["35%", "65%"],
|
|
333
|
-
data: plan.series[0]?.data ?? [],
|
|
334
|
-
},
|
|
335
|
-
],
|
|
336
|
-
};
|
|
337
|
-
}
|
|
338
|
-
if (plan.chartType === "scatter") {
|
|
339
|
-
return {
|
|
340
|
-
title: { text: baseTitle, left: "center" },
|
|
341
|
-
tooltip: { trigger: "item" },
|
|
342
|
-
legend: { bottom: 0 },
|
|
343
|
-
grid,
|
|
344
|
-
xAxis: { type: "value", name: plan.xAxisLabel },
|
|
345
|
-
yAxis: { type: "value", name: plan.yAxisLabel },
|
|
346
|
-
series: plan.series.map((s) => ({
|
|
347
|
-
name: s.name,
|
|
348
|
-
type: "scatter",
|
|
349
|
-
data: s.data,
|
|
350
|
-
})),
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
// bar / line / area share the same axis layout.
|
|
354
|
-
const isArea = plan.chartType === "area";
|
|
355
|
-
const seriesType = plan.chartType === "bar" ? "bar" : "line";
|
|
356
|
-
return {
|
|
357
|
-
title: { text: baseTitle, left: "center" },
|
|
358
|
-
tooltip: { trigger: "axis" },
|
|
359
|
-
legend: { bottom: 0 },
|
|
360
|
-
grid,
|
|
361
|
-
xAxis: {
|
|
362
|
-
type: "category",
|
|
363
|
-
data: plan.categories ?? [],
|
|
364
|
-
name: plan.xAxisLabel,
|
|
365
|
-
},
|
|
366
|
-
yAxis: { type: "value", name: plan.yAxisLabel },
|
|
367
|
-
series: plan.series.map((s) => ({
|
|
368
|
-
name: s.name,
|
|
369
|
-
type: seriesType,
|
|
370
|
-
data: s.data,
|
|
371
|
-
smooth: seriesType === "line",
|
|
372
|
-
...(isArea ? { areaStyle: {} } : {}),
|
|
373
|
-
})),
|
|
374
|
-
};
|
|
375
|
-
}
|
package/dist/src/config.d.ts
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Plugin configuration types and shared `RequestContext` keys.
|
|
3
|
-
*
|
|
4
|
-
* Kept in a leaf module so `plugin.ts`, `server.ts`, `model.ts`, and
|
|
5
|
-
* `memory.ts` can import them without creating a cycle.
|
|
6
|
-
*/
|
|
7
|
-
import type { BasePluginConfig, getExecutionContext } from "@databricks/appkit";
|
|
8
|
-
import type { AgentConfig } from "@mastra/core/agent";
|
|
9
|
-
import type { PgVectorConfig, PostgresStoreConfig } from "@mastra/pg";
|
|
10
|
-
import type { MastraAgentDefinition, MastraTools } from "./agents.js";
|
|
11
|
-
/**
|
|
12
|
-
* `RequestContext` key under which {@link MastraServer} stores the
|
|
13
|
-
* resolved AppKit user. `model.ts` reads it to mint user-scoped
|
|
14
|
-
* Databricks tokens.
|
|
15
|
-
*/
|
|
16
|
-
export declare const MASTRA_USER_KEY = "mastra__user";
|
|
17
|
-
/** AppKit execution context plus the canonical user id. */
|
|
18
|
-
export interface User {
|
|
19
|
-
id: string;
|
|
20
|
-
executionContext: ReturnType<typeof getExecutionContext>;
|
|
21
|
-
}
|
|
22
|
-
/** PgVector config with an optional Mastra store id. */
|
|
23
|
-
export type MastraMemoryConfig = PgVectorConfig & {
|
|
24
|
-
id?: string;
|
|
25
|
-
};
|
|
26
|
-
/** Configuration accepted by the Mastra AppKit plugin. */
|
|
27
|
-
export interface MastraPluginConfig extends BasePluginConfig {
|
|
28
|
-
/** Mastra OpenAI-compatible provider id. Defaults to `"databricks"`. */
|
|
29
|
-
providerId?: string;
|
|
30
|
-
/**
|
|
31
|
-
* PostgresStore for Mastra threads/messages. `true` reuses the
|
|
32
|
-
* `lakebase` plugin's pool; an object opens a dedicated store.
|
|
33
|
-
*/
|
|
34
|
-
storage?: boolean | PostgresStoreConfig;
|
|
35
|
-
/**
|
|
36
|
-
* PgVector store for Mastra memory recall. `true` reuses the
|
|
37
|
-
* `lakebase` plugin's pool; an object opens a dedicated store.
|
|
38
|
-
*/
|
|
39
|
-
memory?: boolean | MastraMemoryConfig;
|
|
40
|
-
/**
|
|
41
|
-
* Code-defined agents. Accepts three shapes for convenience:
|
|
42
|
-
*
|
|
43
|
-
* - **Record**: `{ analyst: def, helper: def }` - keys become the
|
|
44
|
-
* registered ids and the first key is the default.
|
|
45
|
-
* - **Single definition**: `def` - registered under
|
|
46
|
-
* `slugify(def.name)` (or `"default"` when `name` is omitted) and
|
|
47
|
-
* automatically marked as the default agent.
|
|
48
|
-
* - **Array**: `[def1, def2]` - each registered under
|
|
49
|
-
* `slugify(def.name)` (or `agent_${i}` when `name` is omitted);
|
|
50
|
-
* the first entry is the default.
|
|
51
|
-
*
|
|
52
|
-
* Each entry becomes a Mastra `Agent` reachable at
|
|
53
|
-
* `/api/<plugin>/route/chat/<id>` (the chat route also matches
|
|
54
|
-
* `:agentId`). When `agents` is omitted entirely, the plugin
|
|
55
|
-
* registers a single built-in `default` analyst so the bare
|
|
56
|
-
* `mastra()` call still mounts a working chat endpoint.
|
|
57
|
-
*
|
|
58
|
-
* @example Single-agent shorthand
|
|
59
|
-
* ```ts
|
|
60
|
-
* mastra({
|
|
61
|
-
* agents: createAgent({ instructions: "..." }),
|
|
62
|
-
* });
|
|
63
|
-
* ```
|
|
64
|
-
*
|
|
65
|
-
* @example Array
|
|
66
|
-
* ```ts
|
|
67
|
-
* mastra({
|
|
68
|
-
* agents: [
|
|
69
|
-
* createAgent({ name: "analyst", instructions: "..." }),
|
|
70
|
-
* createAgent({ name: "helper", instructions: "..." }),
|
|
71
|
-
* ],
|
|
72
|
-
* });
|
|
73
|
-
* ```
|
|
74
|
-
*
|
|
75
|
-
* @example Record (explicit ids)
|
|
76
|
-
* ```ts
|
|
77
|
-
* mastra({
|
|
78
|
-
* agents: {
|
|
79
|
-
* analyst: createAgent({ instructions: "..." }),
|
|
80
|
-
* helper: createAgent({ instructions: "..." }),
|
|
81
|
-
* },
|
|
82
|
-
* defaultAgent: "analyst",
|
|
83
|
-
* });
|
|
84
|
-
* ```
|
|
85
|
-
*/
|
|
86
|
-
agents?: Record<string, MastraAgentDefinition> | MastraAgentDefinition | MastraAgentDefinition[];
|
|
87
|
-
/**
|
|
88
|
-
* Ambient tools spread into every registered agent's tools record;
|
|
89
|
-
* per-agent tools win on key collision. Use for a small shared
|
|
90
|
-
* library; for per-agent tools set `agents[id].tools` instead.
|
|
91
|
-
*/
|
|
92
|
-
tools?: MastraTools;
|
|
93
|
-
/**
|
|
94
|
-
* Agent id used by `chatRoute` when the client doesn't specify one.
|
|
95
|
-
* Defaults to the first key in `agents` (or `"default"` when
|
|
96
|
-
* `agents` is omitted). Must match an id in `agents` when both are
|
|
97
|
-
* set; a mismatch throws at setup with the available candidates.
|
|
98
|
-
*/
|
|
99
|
-
defaultAgent?: string;
|
|
100
|
-
/**
|
|
101
|
-
* Plugin-level default model applied to every agent that omits its
|
|
102
|
-
* own `model`. Mirrors AppKit's `agents({ defaultModel })`.
|
|
103
|
-
*
|
|
104
|
-
* - `string`: shorthand for "use the OBO auto-resolver but swap the
|
|
105
|
-
* `modelId`" (e.g. `"databricks-claude-sonnet-4-6"`).
|
|
106
|
-
* - Any other Mastra `DynamicArgument<MastraModelConfig>`: passed
|
|
107
|
-
* through verbatim. Use this when you need full control over auth
|
|
108
|
-
* or `providerId`.
|
|
109
|
-
*
|
|
110
|
-
* Resolution order per agent: `def.model` → `defaultModel` →
|
|
111
|
-
* built-in `/serving-endpoints` resolver.
|
|
112
|
-
*/
|
|
113
|
-
defaultModel?: AgentConfig["model"] | string;
|
|
114
|
-
/**
|
|
115
|
-
* Allow loose model names (`"claude sonnet"`) to be fuzzy-matched
|
|
116
|
-
* against the workspace's Model Serving endpoints. Defaults to
|
|
117
|
-
* `true`; set `false` to require exact endpoint names everywhere.
|
|
118
|
-
*/
|
|
119
|
-
modelFuzzyMatch?: boolean;
|
|
120
|
-
/**
|
|
121
|
-
* Fuse.js score threshold for the fuzzy matcher (0 = exact match,
|
|
122
|
-
* 1 = anything matches). Defaults to `0.4`. Lower values reject
|
|
123
|
-
* loose matches; raise it if you have a sprawling endpoint
|
|
124
|
-
* catalogue with similar-looking names.
|
|
125
|
-
*/
|
|
126
|
-
modelFuzzyThreshold?: number;
|
|
127
|
-
/**
|
|
128
|
-
* TTL for the in-memory serving-endpoints list cache, in
|
|
129
|
-
* milliseconds. Defaults to 5 minutes. The cache is per workspace
|
|
130
|
-
* host and shared across users; concurrent callers coalesce on a
|
|
131
|
-
* single in-flight fetch.
|
|
132
|
-
*/
|
|
133
|
-
modelCacheTtlMs?: number;
|
|
134
|
-
/**
|
|
135
|
-
* Allow clients to override the active model per request via the
|
|
136
|
-
* `X-Mastra-Model` header, `?model=` query string, or `model` body
|
|
137
|
-
* field. Defaults to `true`. Disable when running multi-tenant
|
|
138
|
-
* where untrusted clients shouldn't pick the backing endpoint.
|
|
139
|
-
*/
|
|
140
|
-
modelOverride?: boolean;
|
|
141
|
-
/**
|
|
142
|
-
* Priority-ordered list of endpoint names tried when no agent /
|
|
143
|
-
* plugin / env / request-override model id is set. The resolver
|
|
144
|
-
* picks the first id that is actually present in the workspace's
|
|
145
|
-
* `/serving-endpoints` listing - this is what lets a workspace
|
|
146
|
-
* without Claude Opus still get a sensible default automatically.
|
|
147
|
-
*
|
|
148
|
-
* Defaults to the built-in list in `model.ts` (`FALLBACK_MODEL_IDS`):
|
|
149
|
-
* Claude (Opus -> Sonnet -> Haiku), then OpenAI GPT-5 family, then
|
|
150
|
-
* open weights (Llama 4, Llama 3.3, GPT-OSS, Qwen, Llama 3.1).
|
|
151
|
-
* Override here to pin a regulated workspace to an approved subset
|
|
152
|
-
* or to add custom endpoints in front of the public catalogue.
|
|
153
|
-
*/
|
|
154
|
-
defaultModelFallbacks?: readonly string[];
|
|
155
|
-
/**
|
|
156
|
-
* Style guardrails appended to every agent's `instructions` to curb
|
|
157
|
-
* common LLM-isms (em dashes, emojis, sycophantic openers, throwaway
|
|
158
|
-
* closers, excessive hedging).
|
|
159
|
-
*
|
|
160
|
-
* - `undefined` (default): use the built-in
|
|
161
|
-
* `DEFAULT_STYLE_INSTRUCTIONS` from `agents.ts`.
|
|
162
|
-
* - `string`: replace the default with the supplied block.
|
|
163
|
-
* - `false`: disable entirely (agents see only their bespoke
|
|
164
|
-
* `instructions`).
|
|
165
|
-
*
|
|
166
|
-
* Appended (not prepended) so the agent's role and rules come first
|
|
167
|
-
* and the style block leans on the model's recency bias.
|
|
168
|
-
*/
|
|
169
|
-
styleInstructions?: string | false;
|
|
170
|
-
}
|
package/dist/src/config.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Plugin configuration types and shared `RequestContext` keys.
|
|
3
|
-
*
|
|
4
|
-
* Kept in a leaf module so `plugin.ts`, `server.ts`, `model.ts`, and
|
|
5
|
-
* `memory.ts` can import them without creating a cycle.
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* `RequestContext` key under which {@link MastraServer} stores the
|
|
9
|
-
* resolved AppKit user. `model.ts` reads it to mint user-scoped
|
|
10
|
-
* Databricks tokens.
|
|
11
|
-
*/
|
|
12
|
-
export const MASTRA_USER_KEY = "mastra__user";
|