@dbx-tools/appkit-mastra 0.1.13 → 0.1.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +304 -645
  2. package/index.ts +46 -38
  3. package/package.json +58 -45
  4. package/src/agents.ts +224 -66
  5. package/src/chart.ts +531 -429
  6. package/src/config.ts +270 -19
  7. package/src/filesystems.ts +1090 -0
  8. package/src/genie.ts +1000 -660
  9. package/src/history.ts +166 -79
  10. package/src/mcp.ts +105 -0
  11. package/src/memory.ts +94 -92
  12. package/src/mlflow.ts +149 -0
  13. package/src/model.ts +75 -408
  14. package/src/observability.ts +121 -69
  15. package/src/pagination.ts +34 -0
  16. package/src/plugin.ts +552 -67
  17. package/src/processors.ts +168 -0
  18. package/src/rest.ts +67 -0
  19. package/src/server.ts +232 -45
  20. package/src/serving-sanitize.ts +167 -0
  21. package/src/serving.ts +27 -243
  22. package/src/statement.ts +89 -0
  23. package/src/storage-schema.ts +41 -0
  24. package/src/summarize.ts +176 -0
  25. package/src/threads.ts +338 -0
  26. package/src/workspaces.ts +346 -0
  27. package/src/writer.ts +44 -0
  28. package/tsconfig.json +41 -0
  29. package/dist/index.d.ts +0 -20
  30. package/dist/index.js +0 -20
  31. package/dist/src/agents.d.ts +0 -306
  32. package/dist/src/agents.js +0 -403
  33. package/dist/src/chart.d.ts +0 -170
  34. package/dist/src/chart.js +0 -491
  35. package/dist/src/config.d.ts +0 -183
  36. package/dist/src/config.js +0 -12
  37. package/dist/src/genie.d.ts +0 -131
  38. package/dist/src/genie.js +0 -630
  39. package/dist/src/history.d.ts +0 -67
  40. package/dist/src/history.js +0 -172
  41. package/dist/src/memory.d.ts +0 -100
  42. package/dist/src/memory.js +0 -242
  43. package/dist/src/model.d.ts +0 -159
  44. package/dist/src/model.js +0 -427
  45. package/dist/src/observability.d.ts +0 -33
  46. package/dist/src/observability.js +0 -71
  47. package/dist/src/plugin.d.ts +0 -130
  48. package/dist/src/plugin.js +0 -283
  49. package/dist/src/processors/strip-stale-charts.d.ts +0 -29
  50. package/dist/src/processors/strip-stale-charts.js +0 -96
  51. package/dist/src/server.d.ts +0 -46
  52. package/dist/src/server.js +0 -123
  53. package/dist/src/serving.d.ts +0 -156
  54. package/dist/src/serving.js +0 -231
  55. package/dist/src/tools/email.d.ts +0 -74
  56. package/dist/src/tools/email.js +0 -122
  57. package/dist/tsconfig.build.tsbuildinfo +0 -1
  58. package/src/processors/strip-stale-charts.ts +0 -105
  59. package/src/tools/email.ts +0 -147
@@ -1,403 +0,0 @@
1
- /**
2
- * Agent registration for the Mastra AppKit plugin.
3
- *
4
- * Mirrors the shape of the AppKit `agents` plugin (`config.agents` map
5
- * of {@link MastraAgentDefinition}, dual-form `tools` accepting a plain
6
- * record or a `(plugins) => tools` callback). Resolves each definition
7
- * into a Mastra `Agent` instance during plugin setup; user-supplied
8
- * tool callbacks are invoked exactly once with a typed
9
- * {@link MastraPlugins} map built from registered sibling plugins.
10
- *
11
- * When no agents are registered the plugin falls back to a single
12
- * built-in analyst so the bare `mastra()` call still mounts a working
13
- * `chatRoute` agent for demos.
14
- */
15
- import { genie } from "@databricks/appkit";
16
- import { logUtils, pluginUtils, stringUtils } from "@dbx-tools/appkit-shared";
17
- import { Agent } from "@mastra/core/agent";
18
- import { createTool } from "@mastra/core/tools";
19
- import { buildRenderDataTool } from "./chart.js";
20
- import { buildGenieProvider } from "./genie.js";
21
- import { buildModel } from "./model.js";
22
- import { stripStaleChartsProcessor } from "./processors/strip-stale-charts.js";
23
- /** Re-export of Mastra's native `createTool` for full-feature access. */
24
- export { createTool } from "@mastra/core/tools";
25
- /**
26
- * AppKit-shaped tool factory. Lets users mix-and-match tools across
27
- * AppKit's `agents` plugin and `mastra` with a single import:
28
- *
29
- * ```ts
30
- * import { tool } from "@dbx-tools/appkit-mastra";
31
- * import { z } from "zod";
32
- *
33
- * get_weather: tool({
34
- * description: "Weather",
35
- * schema: z.object({ city: z.string() }),
36
- * execute: async ({ city }) => `Sunny in ${city}`,
37
- * }),
38
- * ```
39
- *
40
- * Maps onto Mastra's `createTool`:
41
- *
42
- * - `description` -> `description` (required)
43
- * - `schema` -> `inputSchema` (optional)
44
- * - `execute(input)` -> `execute(input, ctx)` - Mastra already calls
45
- * the first arg with the parsed inputs, so the body shape is
46
- * identical. The Mastra `context` arg is forwarded as the second
47
- * parameter when the caller declares it.
48
- * - `id`: optional. Defaults to a stable identifier derived from
49
- * `description` (slugified, with a short hash suffix for
50
- * uniqueness). Pass an explicit `id` when you need a stable string
51
- * for tracing or MCP exposure.
52
- *
53
- * Reach for {@link createTool} when you need Mastra-only fields
54
- * (`outputSchema`, `suspendSchema`, `requireApproval`, `mcp`, etc.).
55
- */
56
- export function tool(opts) {
57
- const id = opts.id ?? deriveToolId(opts.description);
58
- return createTool({
59
- id,
60
- description: opts.description,
61
- ...(opts.schema ? { inputSchema: opts.schema } : {}),
62
- execute: opts.execute,
63
- });
64
- }
65
- /**
66
- * Build a deterministic Mastra tool id from a description.
67
- * Delegates to {@link stringUtils.toUniqueSlug}: slug + always-on
68
- * 6-char FNV-1a base-32 suffix so two tools with the same leading
69
- * words don't collide in traces. Stable across runs.
70
- */
71
- function deriveToolId(description) {
72
- return stringUtils.toUniqueSlug(description, { fallbackPrefix: "tool" });
73
- }
74
- /**
75
- * Identity helper that brands a definition as a Mastra agent. Mirrors
76
- * AppKit's `createAgent(def)` so the registration shape matches:
77
- *
78
- * ```ts
79
- * const support = createAgent({
80
- * instructions: "...",
81
- * model: "databricks-claude-sonnet-4-6",
82
- * tools(plugins) { return { ... }; },
83
- * });
84
- * ```
85
- *
86
- * Returns the definition unchanged - the wrapper exists only to anchor
87
- * type inference and to match the AppKit API surface.
88
- */
89
- export function createAgent(def) {
90
- return def;
91
- }
92
- /** Fallback agent id used when `config.agents` is omitted entirely. */
93
- export const FALLBACK_AGENT_ID = "default";
94
- const FALLBACK_AGENT_INSTRUCTIONS = `You are a data analyst. The user will ask questions about
95
- business metrics and may share personal preferences you should remember across turns.
96
-
97
- Rules:
98
-
99
- 1. Quote numbers exactly. Never invent data.
100
- 2. When the user states a preference or durable fact about themselves
101
- ("I'm in EU so use EUR", "always show me the SQL"), acknowledge that
102
- you will remember it.
103
- 3. If you don't have enough information to answer, ask a clarifying
104
- question instead of guessing.`;
105
- /**
106
- * Style guardrails appended to every agent's `instructions` to curb
107
- * common LLM-isms (em dashes, emojis, sycophantic openers, excessive
108
- * hedging, throwaway closers). Appended rather than prepended so the
109
- * agent's role/context comes first; the model's recency bias then
110
- * helps the style rules dominate the response surface.
111
- *
112
- * Override globally via {@link MastraPluginConfig.styleInstructions}
113
- * (pass `false` to disable entirely, or a string to replace).
114
- */
115
- export const DEFAULT_STYLE_INSTRUCTIONS = [
116
- "Output style:",
117
- "",
118
- "Use markdown formatting, including headings, lists, and code blocks.",
119
- "Avoid lists and headers for short replies.",
120
- "Plain prose.",
121
- "Use hyphens (-) only. Never use em dashes or en dashes.",
122
- "Never use emojis.",
123
- "Skip openers like 'Great question', 'Absolutely', and 'I'd be happy to help'.",
124
- "Skip closers like 'Let me know if you have any questions'.",
125
- "Skip self-disclaimers like 'I should mention' and 'It's important to note'.",
126
- "Answer directly.",
127
- "Do not include a preamble before the actual answer.",
128
- "Use lists and headers only when they clarify a multi-part answer.",
129
- ].join("\n");
130
- /**
131
- * Resolve the style block to append to every agent's instructions.
132
- * Returns `null` when the caller opted out (`styleInstructions: false`).
133
- */
134
- function resolveStyleInstructions(config) {
135
- if (config.styleInstructions === false)
136
- return null;
137
- if (typeof config.styleInstructions === "string") {
138
- return config.styleInstructions;
139
- }
140
- return DEFAULT_STYLE_INSTRUCTIONS;
141
- }
142
- /**
143
- * Join an agent's bespoke instructions with the resolved style block.
144
- * Returns the bespoke text unchanged when the style block is disabled.
145
- */
146
- function composeInstructions(agentInstructions, style) {
147
- if (!style)
148
- return agentInstructions;
149
- return `${agentInstructions.trimEnd()}\n\n${style}`;
150
- }
151
- /**
152
- * Resolve every entry in `config.agents` into a Mastra `Agent`
153
- * instance. When `config.agents` is omitted the plugin registers a
154
- * single built-in `default` analyst so the bare `mastra()` call still
155
- * yields a working agent.
156
- *
157
- * Per-agent tool callbacks are invoked once with a typed
158
- * {@link MastraPlugins} index built from registered sibling plugins
159
- * (currently `genie`; extend `MastraPlugins` to surface more).
160
- *
161
- * @throws when `config.defaultAgent` is set to an id that isn't in the
162
- * resolved registry; this is a wiring bug, not a runtime condition.
163
- */
164
- export async function buildAgents(opts) {
165
- const { config, context, memoryBuilder, log } = opts;
166
- const definitions = resolveDefinitions(config);
167
- const ids = Object.keys(definitions);
168
- const defaultAgentId = config.defaultAgent ?? ids[0] ?? FALLBACK_AGENT_ID;
169
- const plugins = buildPluginsMap(config, context);
170
- // System-default ambient tools every agent gets out of the box.
171
- // Currently just `render_data` for inline visualizations; the
172
- // user can shadow it by including a same-named tool in their own
173
- // `config.tools` or per-agent `tools`. Order in {@link resolveTools}
174
- // is `system -> user-ambient -> per-agent`, last write wins.
175
- const systemTools = {
176
- render_data: buildRenderDataTool(config),
177
- };
178
- const ambientTools = { ...systemTools, ...(config.tools ?? {}) };
179
- const style = resolveStyleInstructions(config);
180
- // Default-on protection against the model copying turn-scoped
181
- // chartIds from prior assistant tool results into the new
182
- // turn's `[[chart:<id>]]` markers. Opt out per-plugin via
183
- // `config.stripStaleCharts: false`.
184
- const inputProcessors = config.stripStaleCharts === false ? [] : [stripStaleChartsProcessor];
185
- const agents = {};
186
- for (const [id, def] of Object.entries(definitions)) {
187
- const tools = await resolveTools(def.tools, plugins, ambientTools);
188
- const memory = memoryBuilder?.forAgent(id, def);
189
- agents[id] = new Agent({
190
- id,
191
- name: def.name ?? id,
192
- ...(def.description !== undefined ? { description: def.description } : {}),
193
- instructions: composeInstructions(def.instructions, style),
194
- model: resolveModel(config, def.model),
195
- tools,
196
- ...(memory ? { memory } : {}),
197
- ...(inputProcessors.length > 0 ? { inputProcessors } : {}),
198
- });
199
- }
200
- if (!agents[defaultAgentId]) {
201
- throw new Error(`mastra: defaultAgent "${defaultAgentId}" not found in registered agents (${ids.join(", ") || "none"})`);
202
- }
203
- log.info("agents registered", { ids, defaultAgentId });
204
- return { agents, defaultAgentId };
205
- }
206
- /**
207
- * Normalize `config.agents` into a `Record<id, definition>`. Accepts
208
- * any of the three shapes documented on
209
- * {@link MastraPluginConfig.agents}:
210
- *
211
- * - Record - returned as-is when non-empty.
212
- * - Single definition (detected via the required `instructions`
213
- * field) - keyed by `slugify(def.name)` or `FALLBACK_AGENT_ID`.
214
- * - Array - keyed by `slugify(def.name)` or `agent_${i}`; duplicate
215
- * slugs fail loudly so users know to set explicit names.
216
- *
217
- * Omitted or empty inputs fall back to a single built-in analyst so
218
- * the bare `mastra()` call still mounts a working chat route.
219
- */
220
- function resolveDefinitions(config) {
221
- const input = config.agents;
222
- if (!input)
223
- return fallbackDefinitions();
224
- if (Array.isArray(input)) {
225
- if (input.length === 0)
226
- return fallbackDefinitions();
227
- const out = {};
228
- input.forEach((def, i) => {
229
- const key = deriveAgentKey(def, i);
230
- if (out[key]) {
231
- throw new Error(`mastra: duplicate agent id "${key}" derived from name "${def.name ?? ""}"; ` +
232
- `set unique \`name\`s on each definition`);
233
- }
234
- out[key] = def;
235
- });
236
- return out;
237
- }
238
- // Single-definition shorthand: an agent always has `instructions: string`,
239
- // a record-of-agents never has that field directly.
240
- if (typeof input.instructions === "string") {
241
- const def = input;
242
- const key = deriveAgentKey(def);
243
- return { [key]: def };
244
- }
245
- const record = input;
246
- if (Object.keys(record).length === 0)
247
- return fallbackDefinitions();
248
- return record;
249
- }
250
- /** Derive a registry id from a definition's `name`, with a fallback. */
251
- function deriveAgentKey(def, index) {
252
- if (def.name) {
253
- const slug = stringUtils.toIdentifier(def.name);
254
- if (slug)
255
- return slug;
256
- }
257
- return index === undefined ? FALLBACK_AGENT_ID : `agent_${index}`;
258
- }
259
- /** Built-in fallback registry used when `agents` is omitted / empty. */
260
- function fallbackDefinitions() {
261
- return {
262
- [FALLBACK_AGENT_ID]: {
263
- name: "Default Agent",
264
- instructions: FALLBACK_AGENT_INSTRUCTIONS,
265
- },
266
- };
267
- }
268
- /**
269
- * Pick the effective model spec for an agent. Fallback ladder, in
270
- * order:
271
- *
272
- * 1. Per-agent `def.model` (string sugar or `DynamicArgument`).
273
- * 2. Plugin-level `config.defaultModel` (string sugar or
274
- * `DynamicArgument`) - mirrors AppKit's `agents({ defaultModel })`.
275
- * 3. The auto-resolver that mints user-scoped tokens against
276
- * `/serving-endpoints` via {@link buildModel}.
277
- *
278
- * String values are treated as `modelId` sugar and threaded through
279
- * `buildModel`'s override hook so the runtime fuzzy matcher and the
280
- * per-request `X-Mastra-Model` override layer on top of the static
281
- * choice. Non-string `DynamicArgument`s are passed through verbatim;
282
- * callers that need full control over `providerId` / `headers` /
283
- * `modelId` bypass the resolver pipeline entirely.
284
- */
285
- function resolveModel(config, override) {
286
- const effective = override ?? config.defaultModel;
287
- if (effective === undefined) {
288
- return ({ requestContext }) => buildModel(config, requestContext);
289
- }
290
- if (typeof effective === "string") {
291
- const modelId = effective;
292
- return ({ requestContext }) => buildModel(config, requestContext, { modelId });
293
- }
294
- return effective;
295
- }
296
- /**
297
- * Resolve a definition's `tools` field to a flat `MastraTools` record,
298
- * merging in plugin-level ambient tools (per-agent tools win on key
299
- * collision). Callback errors propagate verbatim so the original stack
300
- * survives - the caller already knows which agent was registering.
301
- */
302
- async function resolveTools(defTools, plugins, ambientTools) {
303
- if (!defTools)
304
- return { ...ambientTools };
305
- const resolved = typeof defTools === "function" ? await defTools(plugins) : defTools;
306
- return { ...ambientTools, ...resolved };
307
- }
308
- /**
309
- * Build the {@link MastraPlugins} runtime proxy handed to
310
- * `tools(plugins)` callbacks.
311
- *
312
- * Implemented as a `Proxy` over the AppKit plugin context so
313
- * `plugins.<name>` resolves at first access. Any sibling plugin that
314
- * implements AppKit's standard `ToolProvider` interface
315
- * (`toolkit(opts?)` + `executeAgentTool(name, args, signal?)`) is
316
- * auto-adapted into Mastra tools. Unknown names return `undefined`,
317
- * matching AppKit's `Plugins` semantics so `plugins.foo?.toolkit()`
318
- * remains safe in environments where `foo` isn't registered.
319
- *
320
- * `genie` is special-cased to swap the generic AppKit toolkit (which
321
- * runs `executeAgentTool` and only emits a single final `tool-result`
322
- * chunk per call) for the streaming-aware tools built by
323
- * {@link buildGenieProvider}. The streaming variant forwards each
324
- * Genie wire event (status, SQL, row counts, errors) out through the
325
- * Mastra `ctx.writer`, so the UI gets `tool-output` chunks in real
326
- * time instead of staring at a spinner for the full Genie round-trip.
327
- */
328
- function buildPluginsMap(config, context) {
329
- const cache = new Map();
330
- return new Proxy({}, {
331
- get(_target, propName) {
332
- if (typeof propName !== "string")
333
- return undefined;
334
- if (cache.has(propName))
335
- return cache.get(propName) ?? undefined;
336
- const provider = resolveProvider(config, context, propName);
337
- cache.set(propName, provider);
338
- return provider ?? undefined;
339
- },
340
- });
341
- }
342
- /**
343
- * Pick the right {@link MastraPluginToolkitProvider} for a sibling
344
- * plugin lookup. Returns the streaming-aware Genie adapter when the
345
- * caller asks for `genie`; falls back to the generic AppKit
346
- * `ToolProvider` adapter for every other plugin name. `config` is
347
- * threaded through so Genie's tool can run the chart planner
348
- * inline against the same model resolver / fallback ladder the
349
- * agents use.
350
- */
351
- function resolveProvider(config, context, propName) {
352
- if (propName === "genie") {
353
- const geniePlugin = pluginUtils.instance(context, genie);
354
- if (!geniePlugin)
355
- return null;
356
- return buildGenieProvider(geniePlugin, { config });
357
- }
358
- const plugin = context?.getPlugins().get(propName);
359
- return adaptPluginToolkit(plugin);
360
- }
361
- /**
362
- * Adapt an AppKit `ToolProvider` plugin instance into a
363
- * {@link MastraPluginToolkitProvider}. Returns `null` for any plugin
364
- * that doesn't implement both `toolkit` and `executeAgentTool` (e.g.
365
- * `server`, `lakebase` when used only as a Postgres pool, etc.).
366
- */
367
- function adaptPluginToolkit(plugin) {
368
- if (!plugin || typeof plugin !== "object")
369
- return null;
370
- const p = plugin;
371
- if (typeof p.toolkit !== "function" || typeof p.executeAgentTool !== "function") {
372
- return null;
373
- }
374
- return {
375
- toolkit(opts) {
376
- const entries = p.toolkit(opts);
377
- const tools = {};
378
- for (const [key, entry] of Object.entries(entries)) {
379
- tools[key] = toolkitEntryToMastraTool(entry, p);
380
- }
381
- return tools;
382
- },
383
- };
384
- }
385
- /**
386
- * Wrap a single {@link AppKitToolkitEntry} as a Mastra tool whose
387
- * `execute` dispatches back through `plugin.executeAgentTool(...)` so
388
- * AppKit's OBO auth (`asUser`) and telemetry spans stay intact. JSON
389
- * Schema parameters pass through unchanged - Mastra's `PublicSchema`
390
- * accepts `JSONSchema7` directly via `@mastra/schema-compat`.
391
- */
392
- function toolkitEntryToMastraTool(entry, plugin) {
393
- return createTool({
394
- id: `${entry.pluginName}__${entry.localName}`,
395
- description: entry.def.description,
396
- ...(entry.def.parameters ? { inputSchema: entry.def.parameters } : {}),
397
- execute: async (input, context) => {
398
- const signal = context
399
- ?.abortSignal;
400
- return plugin.executeAgentTool(entry.localName, input, signal);
401
- },
402
- });
403
- }
@@ -1,170 +0,0 @@
1
- /**
2
- * Chart-rendering primitives.
3
- *
4
- * Three 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's
8
- * `execute` emits a `kind: "chart"` event with the raw rows to
9
- * `ctx.writer` synchronously, kicks off the chart-planner agent,
10
- * and `await`s the planner promise before returning so the
11
- * planner's latency is attributed to this tool's trace span.
12
- * The LLM-bound output is just `{ chartId }`, so its context
13
- * stays flat regardless of dataset size.
14
- *
15
- * - {@link emitChartWithPlanning}: the underlying helper that both
16
- * `render_data` and Genie's `drainGenieStream` call. Mints the
17
- * `chartId`, fires the dataset event immediately, runs the
18
- * planner in the background, and returns `{ chartId,
19
- * plannerPromise }` so callers can choose to await for trace
20
- * shape or fire-and-forget.
21
- *
22
- * - {@link runChartPlanner}: the chart-planner Agent + ECOption
23
- * expansion as a plain async function. Used internally by
24
- * {@link emitChartWithPlanning}; producers shouldn't reach for
25
- * it directly so chart events keep a single wire-format
26
- * contract.
27
- *
28
- * The model wires the chart into its reply by emitting the marker
29
- * `[[chart:<chartId>]]` on its own line in markdown. The chat
30
- * client splits the assistant text on these markers and drops a
31
- * `<ChartSlot>` in at the position the model placed it; the slot
32
- * shows a skeleton until the second `kind: "chart"` event (with
33
- * the resolved `EChartsOption`) arrives, then swaps in the
34
- * rendered Echarts visualisation.
35
- */
36
- import type { RequestContext } from "@mastra/core/request-context";
37
- import { z } from "zod";
38
- import type { MastraPluginConfig } from "./config.js";
39
- /**
40
- * Compact, model-friendly representation of an Echarts spec. The
41
- * planner agent emits this; {@link planToEchartsOption} expands it
42
- * into a real `EChartsOption` JSON. Two layers because letting the
43
- * model fill in a fully-typed `EChartsOption` is brittle (hundreds
44
- * of optional fields, deep unions, version-dependent shapes). A
45
- * small "chart plan" schema is much more reliable for a fast model
46
- * and keeps animation / tooltip / styling defaults consistent
47
- * across charts.
48
- */
49
- declare const chartPlanSchema: z.ZodObject<{
50
- chartType: z.ZodEnum<{
51
- bar: "bar";
52
- line: "line";
53
- area: "area";
54
- scatter: "scatter";
55
- pie: "pie";
56
- }>;
57
- title: z.ZodOptional<z.ZodString>;
58
- xAxisLabel: z.ZodOptional<z.ZodString>;
59
- yAxisLabel: z.ZodOptional<z.ZodString>;
60
- categories: z.ZodOptional<z.ZodArray<z.ZodString>>;
61
- series: z.ZodArray<z.ZodObject<{
62
- name: z.ZodString;
63
- data: z.ZodArray<z.ZodUnion<readonly [z.ZodNumber, z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, z.ZodObject<{
64
- name: z.ZodString;
65
- value: z.ZodNumber;
66
- }, z.core.$strip>]>>;
67
- }, z.core.$strip>>;
68
- }, z.core.$strip>;
69
- type ChartPlan = z.infer<typeof chartPlanSchema>;
70
- /** Inputs to {@link runChartPlanner}. */
71
- export interface RunChartPlannerOptions {
72
- config: MastraPluginConfig;
73
- requestContext?: RequestContext;
74
- title: string;
75
- description?: string;
76
- data: ReadonlyArray<Record<string, unknown>>;
77
- }
78
- /** Output of {@link runChartPlanner}: a fully-formed Echarts spec. */
79
- export interface RunChartPlannerResult {
80
- option: Record<string, unknown>;
81
- chartType: ChartPlan["chartType"];
82
- }
83
- /**
84
- * Run the chart planner against the given dataset and return a
85
- * full Echarts `EChartsOption` JSON. Used by
86
- * {@link emitChartWithPlanning}; tools and producers shouldn't
87
- * call this directly (use the helper instead so chart events
88
- * follow the same wire-format contract everywhere).
89
- */
90
- export declare function runChartPlanner(opts: RunChartPlannerOptions): Promise<RunChartPlannerResult>;
91
- /**
92
- * Minimal `ToolStream`-shaped writer surface. Defined locally so
93
- * helpers can take any object with a `.write` method without
94
- * importing Mastra's full `ToolStream` (which would also drag in
95
- * agent / tool types this module doesn't otherwise need).
96
- */
97
- interface MinimalWriter {
98
- write: (chunk: unknown) => unknown;
99
- }
100
- /** Inputs to {@link emitChartWithPlanning}. */
101
- export interface EmitChartWithPlanningOptions {
102
- /** Mastra `ctx.writer`; missing or closed writers are tolerated. */
103
- writer?: MinimalWriter;
104
- /** Plugin config; used to resolve the planner's model. */
105
- config: MastraPluginConfig;
106
- /** Per-request context (OBO auth). */
107
- requestContext?: RequestContext;
108
- /** Title shown above the rendered chart. Required. */
109
- title: string;
110
- /** Optional one-line intent biasing the planner. */
111
- description?: string;
112
- /** Tabular dataset to chart (one object per row). */
113
- data: ReadonlyArray<Record<string, unknown>>;
114
- }
115
- /** Output of {@link emitChartWithPlanning}. */
116
- export interface EmitChartWithPlanningResult {
117
- /** Short id matching the marker `[[chart:<chartId>]]`. */
118
- chartId: string;
119
- /**
120
- * Promise that resolves once the planner has finished and the
121
- * `kind: "chart"` event with the option has been emitted (or
122
- * once the planner has failed silently). Callers that want
123
- * trace observability should `await` this before returning
124
- * from their tool's `execute`; callers that want pure
125
- * fire-and-forget can ignore it.
126
- */
127
- plannerPromise: Promise<void>;
128
- }
129
- /**
130
- * Shared chart-emission primitive used by both the `render_data`
131
- * tool and Genie's `drainGenieStream`. Keeps both producers on
132
- * one wire-format contract so the chat client only ever has to
133
- * understand a single chart event shape.
134
- *
135
- * Behaviour:
136
- *
137
- * 1. Generates a short `chartId` (8 hex chars).
138
- * 2. Immediately emits `{ kind: "chart", chartId, title,
139
- * description?, data }` via the writer so the chat client can
140
- * mount its `<ChartSlot>` with the rows in hand.
141
- * 3. Kicks off the chart-planner agent in the background. On
142
- * success, emits a second `{ kind: "chart", chartId, option }`
143
- * event - same `chartId`, just the spec - so the client merges
144
- * the two into one rendered chart. On failure, no follow-up
145
- * event fires; the client falls back to whatever it can do
146
- * with the dataset alone (typically a "render failed" frame
147
- * after the parent tool finishes).
148
- *
149
- * Returns `chartId` synchronously so the caller can include it in
150
- * the tool result (model uses it in `[[chart:<chartId>]]`
151
- * markers), and `plannerPromise` so the caller can choose
152
- * trace-spanning vs. snappy-return semantics.
153
- */
154
- export declare function emitChartWithPlanning(opts: EmitChartWithPlanningOptions): Promise<EmitChartWithPlanningResult>;
155
- /**
156
- * Build the `render_data` tool bound to the given plugin config.
157
- *
158
- * The tool is a thin wrapper around {@link emitChartWithPlanning}:
159
- * a single `kind: "chart"` writer event ships the raw rows to
160
- * the client immediately, the chart-planner agent runs alongside
161
- * (so the calling LLM stays unblocked while the planner thinks),
162
- * and a follow-up `kind: "chart"` event with the resolved
163
- * `EChartsOption` lands when it's ready. The tool's `execute`
164
- * awaits the planner promise so the planner work shows up under
165
- * the tool's trace span; the LLM still gets back just
166
- * `{ chartId }`, so its context stays small regardless of dataset
167
- * size.
168
- */
169
- export declare function buildRenderDataTool(config: MastraPluginConfig): import("@mastra/core/tools").Tool<any, any, any, any, import("@mastra/core/tools").ToolExecutionContext<any, any, unknown>, "render_data", unknown>;
170
- export {};