@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.
- package/README.md +304 -645
- package/index.ts +46 -38
- package/package.json +58 -45
- package/src/agents.ts +224 -66
- package/src/chart.ts +531 -429
- package/src/config.ts +270 -19
- package/src/filesystems.ts +1090 -0
- package/src/genie.ts +1000 -660
- package/src/history.ts +166 -79
- package/src/mcp.ts +105 -0
- package/src/memory.ts +94 -92
- package/src/mlflow.ts +149 -0
- package/src/model.ts +75 -408
- package/src/observability.ts +121 -69
- package/src/pagination.ts +34 -0
- package/src/plugin.ts +552 -67
- package/src/processors.ts +168 -0
- package/src/rest.ts +67 -0
- package/src/server.ts +232 -45
- package/src/serving-sanitize.ts +167 -0
- package/src/serving.ts +27 -243
- 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 -20
- package/dist/index.js +0 -20
- package/dist/src/agents.d.ts +0 -306
- package/dist/src/agents.js +0 -403
- package/dist/src/chart.d.ts +0 -170
- package/dist/src/chart.js +0 -491
- package/dist/src/config.d.ts +0 -183
- package/dist/src/config.js +0 -12
- package/dist/src/genie.d.ts +0 -131
- package/dist/src/genie.js +0 -630
- package/dist/src/history.d.ts +0 -67
- package/dist/src/history.js +0 -172
- package/dist/src/memory.d.ts +0 -100
- package/dist/src/memory.js +0 -242
- package/dist/src/model.d.ts +0 -159
- package/dist/src/model.js +0 -427
- package/dist/src/observability.d.ts +0 -33
- package/dist/src/observability.js +0 -71
- package/dist/src/plugin.d.ts +0 -130
- package/dist/src/plugin.js +0 -283
- package/dist/src/processors/strip-stale-charts.d.ts +0 -29
- package/dist/src/processors/strip-stale-charts.js +0 -96
- package/dist/src/server.d.ts +0 -46
- package/dist/src/server.js +0 -123
- package/dist/src/serving.d.ts +0 -156
- package/dist/src/serving.js +0 -231
- package/dist/src/tools/email.d.ts +0 -74
- package/dist/src/tools/email.js +0 -122
- package/dist/tsconfig.build.tsbuildinfo +0 -1
- package/src/processors/strip-stale-charts.ts +0 -105
- package/src/tools/email.ts +0 -147
package/src/agents.ts
CHANGED
|
@@ -10,23 +10,27 @@
|
|
|
10
10
|
*
|
|
11
11
|
* When no agents are registered the plugin falls back to a single
|
|
12
12
|
* built-in analyst so the bare `mastra()` call still mounts a working
|
|
13
|
-
*
|
|
13
|
+
* streamable agent for demos.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { genie } from "@databricks/appkit";
|
|
17
|
-
import { logUtils, pluginUtils, stringUtils } from "@dbx-tools/appkit-shared";
|
|
18
|
-
import { Agent } from "@mastra/core/agent";
|
|
19
16
|
import type { AgentConfig, ToolsInput } from "@mastra/core/agent";
|
|
20
|
-
import {
|
|
17
|
+
import { Agent } from "@mastra/core/agent";
|
|
21
18
|
import type { Tool } from "@mastra/core/tools";
|
|
19
|
+
import { createTool } from "@mastra/core/tools";
|
|
20
|
+
import type { Workspace } from "@mastra/core/workspace";
|
|
22
21
|
import type { PgVectorConfig, PostgresStoreConfig } from "@mastra/pg";
|
|
23
22
|
|
|
24
|
-
import { buildRenderDataTool } from "./chart
|
|
25
|
-
import type { MastraPluginConfig } from "./config
|
|
26
|
-
import {
|
|
27
|
-
import type { MemoryBuilder } from "./memory
|
|
28
|
-
import { buildModel } from "./model
|
|
29
|
-
import {
|
|
23
|
+
import { buildRenderDataTool } from "./chart";
|
|
24
|
+
import type { MastraPluginConfig } from "./config";
|
|
25
|
+
import { buildGenieToolkitProvider, resolveGenieSpaces } from "./genie";
|
|
26
|
+
import type { MemoryBuilder } from "./memory";
|
|
27
|
+
import { buildModel } from "./model";
|
|
28
|
+
import { fallback } from "@dbx-tools/model";
|
|
29
|
+
import { ResultProcessor, stripStaleChartsProcessor } from "./processors";
|
|
30
|
+
import { buildSummarizeTool } from "./summarize";
|
|
31
|
+
import { createWorkspace } from "./workspaces";
|
|
32
|
+
import { log, string } from "@dbx-tools/shared-core";
|
|
33
|
+
import { plugin } from "@dbx-tools/appkit";
|
|
30
34
|
|
|
31
35
|
/**
|
|
32
36
|
* Tool record accepted by every Mastra `Agent.tools` field and by the
|
|
@@ -122,12 +126,12 @@ export interface AppKitToolOptions {
|
|
|
122
126
|
|
|
123
127
|
/**
|
|
124
128
|
* Build a deterministic Mastra tool id from a description.
|
|
125
|
-
* Delegates to {@link
|
|
129
|
+
* Delegates to {@link string.toUniqueSlug}: slug + always-on
|
|
126
130
|
* 6-char FNV-1a base-32 suffix so two tools with the same leading
|
|
127
131
|
* words don't collide in traces. Stable across runs.
|
|
128
132
|
*/
|
|
129
133
|
function deriveToolId(description: string): string {
|
|
130
|
-
return
|
|
134
|
+
return string.toUniqueSlug(description, { fallbackPrefix: "tool" });
|
|
131
135
|
}
|
|
132
136
|
|
|
133
137
|
/**
|
|
@@ -146,7 +150,8 @@ function deriveToolId(description: string): string {
|
|
|
146
150
|
* type inference and to match the AppKit API surface.
|
|
147
151
|
*/
|
|
148
152
|
export function createAgent<T extends MastraAgentDefinition>(def: T): T {
|
|
149
|
-
|
|
153
|
+
const workspace = def.workspace ?? createWorkspace();
|
|
154
|
+
return { ...def, workspace };
|
|
150
155
|
}
|
|
151
156
|
|
|
152
157
|
/**
|
|
@@ -219,15 +224,16 @@ export interface MastraPluginToolkitProvider {
|
|
|
219
224
|
export type MastraPlugins = Record<string, MastraPluginToolkitProvider>;
|
|
220
225
|
|
|
221
226
|
/** Function form of {@link MastraAgentDefinition.tools}. */
|
|
222
|
-
export type MastraToolsFn = (
|
|
223
|
-
|
|
224
|
-
|
|
227
|
+
export type MastraToolsFn = (plugins: MastraPlugins) => MastraTools | Promise<MastraTools>;
|
|
228
|
+
|
|
229
|
+
/** Function form of {@link MastraAgentDefinition.workspace}. */
|
|
230
|
+
export type MastraAgentWorkspaceResolver = () => Workspace | undefined;
|
|
225
231
|
|
|
226
232
|
/**
|
|
227
233
|
* A code-defined Mastra agent. Mirrors the shape AppKit's `agents`
|
|
228
234
|
* plugin uses for `AgentDefinition`. The registry key under
|
|
229
|
-
* `config.agents` is
|
|
230
|
-
* informational (defaults to the key).
|
|
235
|
+
* `config.agents` is the `agentId` the client streams against; `name`
|
|
236
|
+
* is purely informational (defaults to the key).
|
|
231
237
|
*/
|
|
232
238
|
export interface MastraAgentDefinition {
|
|
233
239
|
/** Display name used as `Agent.name`. Defaults to the registry key. */
|
|
@@ -276,7 +282,7 @@ export interface MastraAgentDefinition {
|
|
|
276
282
|
*
|
|
277
283
|
* - `undefined` (default): inherit `config.storage`. When that's
|
|
278
284
|
* enabled, the agent gets its **own per-agent `PostgresStore`**
|
|
279
|
-
* keyed by
|
|
285
|
+
* keyed by {@link agentStorageSchemaName} so threads and
|
|
280
286
|
* messages stay isolated between agents in the same database.
|
|
281
287
|
* - `false`: disable storage for this agent only (purely in-memory).
|
|
282
288
|
* - `true`: enable with the per-agent default schema.
|
|
@@ -284,6 +290,12 @@ export interface MastraAgentDefinition {
|
|
|
284
290
|
* `PostgresStore` config (custom schema, connection, etc.).
|
|
285
291
|
*/
|
|
286
292
|
storage?: boolean | MastraStorageConfigOverride;
|
|
293
|
+
/**
|
|
294
|
+
* Mastra {@link Workspace} for this agent (filesystem, sandbox, or other
|
|
295
|
+
* providers). Assistant skills from Databricks workspace paths are wired
|
|
296
|
+
* via {@link createWorkspace}.
|
|
297
|
+
*/
|
|
298
|
+
workspace?: Workspace | MastraAgentWorkspaceResolver;
|
|
287
299
|
}
|
|
288
300
|
|
|
289
301
|
/**
|
|
@@ -292,19 +304,16 @@ export interface MastraAgentDefinition {
|
|
|
292
304
|
* strip `id`. The built-in `Omit` collapses unions to one shape with
|
|
293
305
|
* common fields only, which loses the connection-style discriminants.
|
|
294
306
|
*/
|
|
295
|
-
type DistributiveOmit<T, K extends keyof never> = T extends unknown
|
|
296
|
-
? Omit<T, K>
|
|
297
|
-
: never;
|
|
307
|
+
type DistributiveOmit<T, K extends keyof never> = T extends unknown ? Omit<T, K> : never;
|
|
298
308
|
|
|
299
309
|
/**
|
|
300
310
|
* `PostgresStoreConfig` minus `id` - per-agent overrides accept any
|
|
301
311
|
* Mastra-supported storage shape. `id` is filled in automatically
|
|
302
312
|
* from the agent registry key so traces stay stable.
|
|
303
313
|
*/
|
|
304
|
-
export type MastraStorageConfigOverride = DistributiveOmit<
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
> & { id?: string };
|
|
314
|
+
export type MastraStorageConfigOverride = DistributiveOmit<PostgresStoreConfig, "id"> & {
|
|
315
|
+
id?: string;
|
|
316
|
+
};
|
|
308
317
|
|
|
309
318
|
/**
|
|
310
319
|
* `PgVectorConfig` minus `id` - per-agent overrides accept any
|
|
@@ -319,11 +328,28 @@ export type MastraMemoryConfigOverride = DistributiveOmit<PgVectorConfig, "id">
|
|
|
319
328
|
export interface BuiltAgents {
|
|
320
329
|
agents: Record<string, Agent>;
|
|
321
330
|
defaultAgentId: string;
|
|
331
|
+
/**
|
|
332
|
+
* Ambient tools shared across every agent (the built-in system tools
|
|
333
|
+
* spread with `config.tools`). Surfaced so the optional MCP server
|
|
334
|
+
* can re-expose them when {@link MastraMcpConfig.tools} is enabled.
|
|
335
|
+
*/
|
|
336
|
+
ambientTools: MastraTools;
|
|
322
337
|
}
|
|
323
338
|
|
|
324
339
|
/** Fallback agent id used when `config.agents` is omitted entirely. */
|
|
325
340
|
export const FALLBACK_AGENT_ID = "default";
|
|
326
341
|
|
|
342
|
+
/**
|
|
343
|
+
* Default per-turn step ceiling applied to every registered agent
|
|
344
|
+
* when {@link MastraPluginConfig.agentMaxSteps} is unset. Sized to
|
|
345
|
+
* fit a decomposed Genie turn (grounding + several `ask_genie`
|
|
346
|
+
* calls + `prepare_chart` per dataset + the final-text reply) with
|
|
347
|
+
* headroom for the model to chain a couple of follow-ups before
|
|
348
|
+
* answering - well above Mastra's own `agent.generate` default of
|
|
349
|
+
* 5, which would cut multi-step orchestration off mid-loop.
|
|
350
|
+
*/
|
|
351
|
+
export const DEFAULT_AGENT_MAX_STEPS = 25;
|
|
352
|
+
|
|
327
353
|
const FALLBACK_AGENT_INSTRUCTIONS = `You are a data analyst. The user will ask questions about
|
|
328
354
|
business metrics and may share personal preferences you should remember across turns.
|
|
329
355
|
|
|
@@ -384,6 +410,16 @@ function composeInstructions(agentInstructions: string, style: string | null): s
|
|
|
384
410
|
return `${agentInstructions.trimEnd()}\n\n${style}`;
|
|
385
411
|
}
|
|
386
412
|
|
|
413
|
+
/**
|
|
414
|
+
* Generated description for an agent whose definition omits one. Kept
|
|
415
|
+
* generic (the agent's own name is the only reliable signal at build
|
|
416
|
+
* time) so it reads sensibly as the `ask_<id>` MCP tool's description
|
|
417
|
+
* and in agent metadata.
|
|
418
|
+
*/
|
|
419
|
+
function defaultAgentDescription(name: string): string {
|
|
420
|
+
return `Conversational AI agent "${name}".`;
|
|
421
|
+
}
|
|
422
|
+
|
|
387
423
|
/**
|
|
388
424
|
* Resolve every entry in `config.agents` into a Mastra `Agent`
|
|
389
425
|
* instance. When `config.agents` is omitted the plugin registers a
|
|
@@ -399,9 +435,9 @@ function composeInstructions(agentInstructions: string, style: string | null): s
|
|
|
399
435
|
*/
|
|
400
436
|
export async function buildAgents(opts: {
|
|
401
437
|
config: MastraPluginConfig;
|
|
402
|
-
context:
|
|
438
|
+
context: plugin.PluginContextLike | undefined;
|
|
403
439
|
memoryBuilder?: MemoryBuilder;
|
|
404
|
-
log:
|
|
440
|
+
log: log.Logger;
|
|
405
441
|
}): Promise<BuiltAgents> {
|
|
406
442
|
const { config, context, memoryBuilder, log } = opts;
|
|
407
443
|
const definitions = resolveDefinitions(config);
|
|
@@ -409,36 +445,68 @@ export async function buildAgents(opts: {
|
|
|
409
445
|
const defaultAgentId = config.defaultAgent ?? ids[0] ?? FALLBACK_AGENT_ID;
|
|
410
446
|
|
|
411
447
|
const plugins = buildPluginsMap(config, context);
|
|
412
|
-
// System-default ambient tools every agent gets out of the box
|
|
413
|
-
//
|
|
414
|
-
//
|
|
448
|
+
// System-default ambient tools every agent gets out of the box:
|
|
449
|
+
// `render_data` for inline visualizations and `summarize` for
|
|
450
|
+
// offloading text condensing to the fast / small chat tier. The
|
|
451
|
+
// user can shadow either by including a same-named tool in their own
|
|
415
452
|
// `config.tools` or per-agent `tools`. Order in {@link resolveTools}
|
|
416
453
|
// is `system -> user-ambient -> per-agent`, last write wins.
|
|
417
454
|
const systemTools: MastraTools = {
|
|
418
455
|
render_data: buildRenderDataTool(config),
|
|
456
|
+
summarize: buildSummarizeTool(config),
|
|
457
|
+
};
|
|
458
|
+
const ambientTools = {
|
|
459
|
+
...systemTools,
|
|
460
|
+
...(config.tools ?? {}),
|
|
419
461
|
};
|
|
420
|
-
const ambientTools = { ...systemTools, ...(config.tools ?? {}) };
|
|
421
462
|
const style = resolveStyleInstructions(config);
|
|
422
463
|
// Default-on protection against the model copying turn-scoped
|
|
423
464
|
// chartIds from prior assistant tool results into the new
|
|
424
|
-
// turn's `[
|
|
465
|
+
// turn's `[chart:<id>]` markers. Opt out per-plugin via
|
|
425
466
|
// `config.stripStaleCharts: false`.
|
|
426
|
-
const
|
|
427
|
-
|
|
467
|
+
const outputProcessors = [new ResultProcessor()];
|
|
468
|
+
const inputProcessors = [
|
|
469
|
+
...(config.stripStaleCharts === false ? [] : [stripStaleChartsProcessor]),
|
|
470
|
+
];
|
|
428
471
|
const agents: Record<string, Agent> = {};
|
|
472
|
+
const approvalGatedByAgent: Array<{ agentId: string; toolIds: string[] }> = [];
|
|
429
473
|
|
|
430
474
|
for (const [id, def] of Object.entries(definitions)) {
|
|
431
475
|
const tools = await resolveTools(def.tools, plugins, ambientTools);
|
|
476
|
+
const workspace = resolveAgentWorkspace(def.workspace);
|
|
477
|
+
const gated = approvalGatedToolIds(tools);
|
|
478
|
+
if (gated.length > 0) approvalGatedByAgent.push({ agentId: id, toolIds: gated });
|
|
432
479
|
const memory = memoryBuilder?.forAgent(id, def);
|
|
433
480
|
agents[id] = new Agent({
|
|
434
481
|
id,
|
|
435
482
|
name: def.name ?? id,
|
|
436
|
-
|
|
483
|
+
// Always carry a non-empty description: it's surfaced to MCP
|
|
484
|
+
// clients (which reject a description-less agent) and in agent
|
|
485
|
+
// metadata. Fall back to a generated one when the definition
|
|
486
|
+
// omits it.
|
|
487
|
+
description: def.description?.trim() || defaultAgentDescription(def.name ?? id),
|
|
437
488
|
instructions: composeInstructions(def.instructions, style),
|
|
438
489
|
model: resolveModel(config, def.model),
|
|
490
|
+
defaultOptions: {
|
|
491
|
+
maxSteps: config.agentMaxSteps ?? DEFAULT_AGENT_MAX_STEPS,
|
|
492
|
+
},
|
|
439
493
|
tools,
|
|
440
494
|
...(memory ? { memory } : {}),
|
|
441
|
-
...(
|
|
495
|
+
...(workspace ? { workspace } : {}),
|
|
496
|
+
inputProcessors,
|
|
497
|
+
outputProcessors,
|
|
498
|
+
});
|
|
499
|
+
// Surface the effective default model per agent so operators can
|
|
500
|
+
// see at a glance which endpoint each agent points at without
|
|
501
|
+
// having to fire a request and inspect a trace. The value is the
|
|
502
|
+
// *static* default; per-request overrides (header / query /
|
|
503
|
+
// body) and the workspace-catalogue fuzzy match still apply at
|
|
504
|
+
// call time.
|
|
505
|
+
log.info("agent registered", {
|
|
506
|
+
id,
|
|
507
|
+
name: def.name ?? id,
|
|
508
|
+
defaultModel: describeAgentDefaultModel(config, def),
|
|
509
|
+
tools: Object.keys(tools),
|
|
442
510
|
});
|
|
443
511
|
}
|
|
444
512
|
|
|
@@ -448,8 +516,88 @@ export async function buildAgents(opts: {
|
|
|
448
516
|
);
|
|
449
517
|
}
|
|
450
518
|
|
|
451
|
-
|
|
452
|
-
|
|
519
|
+
assertApprovalGatedToolsHaveStorage(approvalGatedByAgent, memoryBuilder);
|
|
520
|
+
|
|
521
|
+
log.info("agents ready", { ids, defaultAgentId });
|
|
522
|
+
return { agents, defaultAgentId, ambientTools };
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Tool ids on `tools` that are approval-gated (`requireApproval: true`).
|
|
527
|
+
* Keys are used as a fallback when a tool omits an explicit `id`.
|
|
528
|
+
*/
|
|
529
|
+
export function approvalGatedToolIds(tools: MastraTools): string[] {
|
|
530
|
+
if (!tools || typeof tools !== "object") return [];
|
|
531
|
+
const ids: string[] = [];
|
|
532
|
+
for (const [key, tool] of Object.entries(tools)) {
|
|
533
|
+
if (!isApprovalGatedTool(tool)) continue;
|
|
534
|
+
ids.push(resolveToolId(tool, key));
|
|
535
|
+
}
|
|
536
|
+
return ids;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/** True when a Mastra / AI SDK tool pauses for human approval before execute. */
|
|
540
|
+
function isApprovalGatedTool(tool: unknown): boolean {
|
|
541
|
+
if (!tool || typeof tool !== "object") return false;
|
|
542
|
+
return (tool as { requireApproval?: boolean }).requireApproval === true;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
function resolveToolId(tool: unknown, fallbackKey: string): string {
|
|
546
|
+
if (tool && typeof tool === "object" && typeof (tool as { id?: string }).id === "string") {
|
|
547
|
+
return (tool as { id: string }).id;
|
|
548
|
+
}
|
|
549
|
+
return fallbackKey;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Approval-gated tools suspend the agent loop until a human approves.
|
|
554
|
+
* Mastra persists those suspended runs in Mastra-instance-level storage
|
|
555
|
+
* (`memoryBuilder.instanceStorage()`), not per-agent memory - so boot
|
|
556
|
+
* must fail fast when such a tool is registered without storage.
|
|
557
|
+
*/
|
|
558
|
+
function assertApprovalGatedToolsHaveStorage(
|
|
559
|
+
gated: Array<{ agentId: string; toolIds: string[] }>,
|
|
560
|
+
memoryBuilder: MemoryBuilder | undefined,
|
|
561
|
+
): void {
|
|
562
|
+
if (gated.length === 0) return;
|
|
563
|
+
if (memoryBuilder?.instanceStorage()) return;
|
|
564
|
+
|
|
565
|
+
const detail = gated
|
|
566
|
+
.map(({ agentId, toolIds }) => `${agentId}: ${toolIds.join(", ")}`)
|
|
567
|
+
.join("; ");
|
|
568
|
+
throw new Error(
|
|
569
|
+
"mastra: approval-gated tools require plugin storage (PostgresStore) to persist suspended runs. " +
|
|
570
|
+
`Affected agents/tools: ${detail}. ` +
|
|
571
|
+
"Register lakebase() before mastra() so storage auto-enables, or pass storage: true explicitly.",
|
|
572
|
+
);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Best-effort description of the *static* default model an agent will
|
|
577
|
+
* resolve to at call time. Walks the same precedence ladder as
|
|
578
|
+
* {@link resolveModel} / {@link buildModel}:
|
|
579
|
+
*
|
|
580
|
+
* 1. Per-agent `def.model` (string sugar -> the literal id;
|
|
581
|
+
* function / `DynamicArgument` -> `"<dynamic>"` because the
|
|
582
|
+
* resolver decides at call time).
|
|
583
|
+
* 2. Plugin-level `config.defaultModel` (same rules).
|
|
584
|
+
* 3. `DATABRICKS_SERVING_ENDPOINT_NAME` env var.
|
|
585
|
+
* 4. First entry of `config.defaultModelFallbacks ?? fallback.FALLBACK_MODEL_IDS`.
|
|
586
|
+
*
|
|
587
|
+
* Used for the startup `agent registered` log so operators can see
|
|
588
|
+
* which endpoint each agent points at by default. Per-request
|
|
589
|
+
* overrides (`X-Mastra-Model` etc.) and the workspace-catalogue
|
|
590
|
+
* fuzzy match are still applied at runtime.
|
|
591
|
+
*/
|
|
592
|
+
function describeAgentDefaultModel(config: MastraPluginConfig, def: MastraAgentDefinition): string {
|
|
593
|
+
const effective = def.model ?? config.defaultModel;
|
|
594
|
+
if (typeof effective === "string") return effective;
|
|
595
|
+
if (effective !== undefined) return "<dynamic>";
|
|
596
|
+
return (
|
|
597
|
+
process.env.DATABRICKS_SERVING_ENDPOINT_NAME ??
|
|
598
|
+
config.defaultModelFallbacks?.[0] ??
|
|
599
|
+
fallback.FALLBACK_MODEL_IDS[0]!
|
|
600
|
+
);
|
|
453
601
|
}
|
|
454
602
|
|
|
455
603
|
/**
|
|
@@ -466,9 +614,7 @@ export async function buildAgents(opts: {
|
|
|
466
614
|
* Omitted or empty inputs fall back to a single built-in analyst so
|
|
467
615
|
* the bare `mastra()` call still mounts a working chat route.
|
|
468
616
|
*/
|
|
469
|
-
function resolveDefinitions(
|
|
470
|
-
config: MastraPluginConfig,
|
|
471
|
-
): Record<string, MastraAgentDefinition> {
|
|
617
|
+
function resolveDefinitions(config: MastraPluginConfig): Record<string, MastraAgentDefinition> {
|
|
472
618
|
const input = config.agents;
|
|
473
619
|
if (!input) return fallbackDefinitions();
|
|
474
620
|
|
|
@@ -504,7 +650,7 @@ function resolveDefinitions(
|
|
|
504
650
|
/** Derive a registry id from a definition's `name`, with a fallback. */
|
|
505
651
|
function deriveAgentKey(def: MastraAgentDefinition, index?: number): string {
|
|
506
652
|
if (def.name) {
|
|
507
|
-
const slug =
|
|
653
|
+
const slug = string.toIdentifier(def.name);
|
|
508
654
|
if (slug) return slug;
|
|
509
655
|
}
|
|
510
656
|
return index === undefined ? FALLBACK_AGENT_ID : `agent_${index}`;
|
|
@@ -568,6 +714,13 @@ async function resolveTools(
|
|
|
568
714
|
return { ...ambientTools, ...resolved };
|
|
569
715
|
}
|
|
570
716
|
|
|
717
|
+
function resolveAgentWorkspace(
|
|
718
|
+
workspace: MastraAgentDefinition["workspace"],
|
|
719
|
+
): Workspace | undefined {
|
|
720
|
+
if (!workspace) return undefined;
|
|
721
|
+
return typeof workspace === "function" ? workspace() : workspace;
|
|
722
|
+
}
|
|
723
|
+
|
|
571
724
|
/**
|
|
572
725
|
* Build the {@link MastraPlugins} runtime proxy handed to
|
|
573
726
|
* `tools(plugins)` callbacks.
|
|
@@ -590,7 +743,7 @@ async function resolveTools(
|
|
|
590
743
|
*/
|
|
591
744
|
function buildPluginsMap(
|
|
592
745
|
config: MastraPluginConfig,
|
|
593
|
-
context:
|
|
746
|
+
context: plugin.PluginContextLike | undefined,
|
|
594
747
|
): MastraPlugins {
|
|
595
748
|
const cache = new Map<string, MastraPluginToolkitProvider | null>();
|
|
596
749
|
return new Proxy({} as MastraPlugins, {
|
|
@@ -606,22 +759,35 @@ function buildPluginsMap(
|
|
|
606
759
|
|
|
607
760
|
/**
|
|
608
761
|
* Pick the right {@link MastraPluginToolkitProvider} for a sibling
|
|
609
|
-
* plugin lookup. Returns the
|
|
610
|
-
* caller asks for `genie
|
|
611
|
-
*
|
|
612
|
-
*
|
|
613
|
-
*
|
|
614
|
-
*
|
|
762
|
+
* plugin lookup. Returns the Genie agent-backed adapter when
|
|
763
|
+
* the caller asks for `genie` AND at least one space is reachable
|
|
764
|
+
* via {@link resolveGenieSpaces} (the explicit
|
|
765
|
+
* `config.genieSpaces`, the registered AppKit `genie()` plugin's
|
|
766
|
+
* `spaces` config, or the `DATABRICKS_GENIE_SPACE_ID` env var).
|
|
767
|
+
* Falls back to the generic AppKit `ToolProvider` adapter for
|
|
768
|
+
* every other plugin name. `config` is threaded through so the
|
|
769
|
+
* Genie agent inherits the same model resolver / fallback
|
|
770
|
+
* ladder the calling agents use.
|
|
771
|
+
*
|
|
772
|
+
* The Genie agent talks to Genie directly via `@dbx-tools/genie`
|
|
773
|
+
* (`genieEventChat`) and the workspace
|
|
774
|
+
* `statementExecution.getStatement` API. AppKit's stock `genie`
|
|
775
|
+
* plugin is honored only for its resource manifest and `spaces`
|
|
776
|
+
* config so existing `app.yaml` configs and `genie({ spaces })`
|
|
777
|
+
* wiring keep working without change.
|
|
615
778
|
*/
|
|
616
779
|
function resolveProvider(
|
|
617
780
|
config: MastraPluginConfig,
|
|
618
|
-
context:
|
|
781
|
+
context: plugin.PluginContextLike | undefined,
|
|
619
782
|
propName: string,
|
|
620
783
|
): MastraPluginToolkitProvider | null {
|
|
621
784
|
if (propName === "genie") {
|
|
622
|
-
const
|
|
623
|
-
if (
|
|
624
|
-
return
|
|
785
|
+
const spaces = resolveGenieSpaces(config, context);
|
|
786
|
+
if (Object.keys(spaces).length === 0) return null;
|
|
787
|
+
return buildGenieToolkitProvider({
|
|
788
|
+
spaces,
|
|
789
|
+
config,
|
|
790
|
+
}) as MastraPluginToolkitProvider;
|
|
625
791
|
}
|
|
626
792
|
const plugin = context?.getPlugins().get(propName);
|
|
627
793
|
return adaptPluginToolkit(plugin);
|
|
@@ -634,11 +800,7 @@ function resolveProvider(
|
|
|
634
800
|
*/
|
|
635
801
|
interface AppKitToolkitProvider {
|
|
636
802
|
toolkit?: (opts?: ToolkitOptions) => Record<string, AppKitToolkitEntry>;
|
|
637
|
-
executeAgentTool?: (
|
|
638
|
-
name: string,
|
|
639
|
-
args: unknown,
|
|
640
|
-
signal?: AbortSignal,
|
|
641
|
-
) => Promise<unknown>;
|
|
803
|
+
executeAgentTool?: (name: string, args: unknown, signal?: AbortSignal) => Promise<unknown>;
|
|
642
804
|
}
|
|
643
805
|
|
|
644
806
|
/** Single entry returned by an AppKit plugin's `.toolkit(opts)` call. */
|
|
@@ -683,17 +845,13 @@ function adaptPluginToolkit(plugin: unknown): MastraPluginToolkitProvider | null
|
|
|
683
845
|
* Schema parameters pass through unchanged - Mastra's `PublicSchema`
|
|
684
846
|
* accepts `JSONSchema7` directly via `@mastra/schema-compat`.
|
|
685
847
|
*/
|
|
686
|
-
function toolkitEntryToMastraTool(
|
|
687
|
-
entry: AppKitToolkitEntry,
|
|
688
|
-
plugin: AppKitToolkitProvider,
|
|
689
|
-
): Tool {
|
|
848
|
+
function toolkitEntryToMastraTool(entry: AppKitToolkitEntry, plugin: AppKitToolkitProvider): Tool {
|
|
690
849
|
return createTool({
|
|
691
850
|
id: `${entry.pluginName}__${entry.localName}`,
|
|
692
851
|
description: entry.def.description,
|
|
693
852
|
...(entry.def.parameters ? { inputSchema: entry.def.parameters as never } : {}),
|
|
694
853
|
execute: async (input: unknown, context: unknown) => {
|
|
695
|
-
const signal = (context as { abortSignal?: AbortSignal } | undefined)
|
|
696
|
-
?.abortSignal;
|
|
854
|
+
const signal = (context as { abortSignal?: AbortSignal } | undefined)?.abortSignal;
|
|
697
855
|
return plugin.executeAgentTool!(entry.localName, input, signal);
|
|
698
856
|
},
|
|
699
857
|
});
|