@dbx-tools/appkit-mastra 0.6.224 → 0.6.226
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 +21 -15
- package/index.ts +2 -2
- package/lib/index.d.ts +2 -2
- package/lib/index.js +2 -2
- package/lib/src/agents.d.ts +14 -6
- package/lib/src/agents.js +13 -18
- package/lib/src/config.d.ts +4 -5
- package/lib/src/config.js +2 -2
- package/lib/src/model.d.ts +9 -1
- package/lib/src/model.js +28 -12
- package/lib/src/plugin.js +23 -16
- package/package.json +14 -14
- package/src/agents.ts +24 -27
- package/src/config.ts +5 -6
- package/src/model.ts +43 -12
- package/src/plugin.ts +21 -15
package/src/agents.ts
CHANGED
|
@@ -24,7 +24,6 @@ import type {
|
|
|
24
24
|
ToolProvider,
|
|
25
25
|
} from "@databricks/appkit/beta";
|
|
26
26
|
import { plugin } from "@dbx-tools/appkit";
|
|
27
|
-
import { fallback } from "@dbx-tools/model";
|
|
28
27
|
import { log, object, string } from "@dbx-tools/shared-core";
|
|
29
28
|
import type {
|
|
30
29
|
AgentConfig,
|
|
@@ -368,18 +367,21 @@ export type MastraMemoryConfigOverride = DistributiveOmit<PgVectorConfig, "id">
|
|
|
368
367
|
id?: string;
|
|
369
368
|
};
|
|
370
369
|
|
|
370
|
+
/** How an agent's unpinned model is resolved. */
|
|
371
|
+
export type AgentDefaultModel =
|
|
372
|
+
{ kind: "auto" } | { kind: "configured"; model: string } | { kind: "dynamic" };
|
|
373
|
+
|
|
371
374
|
/** Output of {@link buildAgents}: resolved agents plus the default id. */
|
|
372
375
|
export interface BuiltAgents {
|
|
373
376
|
agents: Record<string, Agent>;
|
|
374
377
|
defaultAgentId: string;
|
|
375
378
|
/**
|
|
376
|
-
*
|
|
377
|
-
*
|
|
378
|
-
* function
|
|
379
|
-
* `GET /default-model` route
|
|
380
|
-
* its default option with the real endpoint's humanized name.
|
|
379
|
+
* Default model intent per agent id. An unconfigured agent is `"auto"` and
|
|
380
|
+
* resolves the highest-ranked live endpoint; a string is `"configured"`; a
|
|
381
|
+
* custom function is `"dynamic"`. Consumed by the plugin's
|
|
382
|
+
* `GET /default-model` route.
|
|
381
383
|
*/
|
|
382
|
-
defaultModels: Record<string,
|
|
384
|
+
defaultModels: Record<string, AgentDefaultModel>;
|
|
383
385
|
/**
|
|
384
386
|
* Ambient tools shared across every agent (the built-in system tools
|
|
385
387
|
* spread with `config.tools`). Surfaced so the optional MCP server
|
|
@@ -559,7 +561,7 @@ export async function buildAgents(opts: {
|
|
|
559
561
|
...(config.stripStaleCharts === false ? [] : [stripStaleChartsProcessor]),
|
|
560
562
|
];
|
|
561
563
|
const agents: Record<string, Agent> = {};
|
|
562
|
-
const defaultModels: Record<string,
|
|
564
|
+
const defaultModels: Record<string, AgentDefaultModel> = {};
|
|
563
565
|
const approvalGatedByAgent: Array<{ agentId: string; toolIds: string[] }> = [];
|
|
564
566
|
|
|
565
567
|
for (const [id, def] of Object.entries(definitions)) {
|
|
@@ -613,7 +615,8 @@ export async function buildAgents(opts: {
|
|
|
613
615
|
log.info("agent registered", {
|
|
614
616
|
id,
|
|
615
617
|
name: def.name ?? id,
|
|
616
|
-
defaultModel
|
|
618
|
+
defaultModel:
|
|
619
|
+
defaultModel.kind === "configured" ? defaultModel.model : `<${defaultModel.kind}>`,
|
|
617
620
|
tools: Object.keys(tools),
|
|
618
621
|
});
|
|
619
622
|
}
|
|
@@ -682,34 +685,28 @@ function assertApprovalGatedToolsHaveStorage(
|
|
|
682
685
|
}
|
|
683
686
|
|
|
684
687
|
/**
|
|
685
|
-
*
|
|
686
|
-
* resolve to at call time. Walks the same precedence ladder as
|
|
687
|
-
* {@link resolveModel} / {@link buildModel}:
|
|
688
|
+
* Describe how an agent resolves its unpinned model:
|
|
688
689
|
*
|
|
689
|
-
* 1. Per-agent `def.model` (string sugar
|
|
690
|
-
*
|
|
691
|
-
* resolver decides at call time).
|
|
690
|
+
* 1. Per-agent `def.model` (string sugar is configured; a function is
|
|
691
|
+
* dynamic).
|
|
692
692
|
* 2. Plugin-level `config.defaultModel` (same rules).
|
|
693
693
|
* 3. `DATABRICKS_SERVING_ENDPOINT_NAME` env var.
|
|
694
|
-
* 4.
|
|
694
|
+
* 4. Automatic live-catalogue ranking when none is set.
|
|
695
695
|
*
|
|
696
696
|
* Used for the startup `agent registered` log so operators can see
|
|
697
|
-
*
|
|
698
|
-
*
|
|
699
|
-
*
|
|
697
|
+
* `defaultModelFallbacks` remains an operator-pinned candidate list inside the
|
|
698
|
+
* automatic live lookup; it is not advertised as a model until availability is
|
|
699
|
+
* checked.
|
|
700
700
|
*/
|
|
701
701
|
function describeAgentDefaultModel(
|
|
702
702
|
config: MastraPluginConfig,
|
|
703
703
|
def: AnyMastraAgentDefinition,
|
|
704
|
-
):
|
|
704
|
+
): AgentDefaultModel {
|
|
705
705
|
const effective = def.model ?? config.defaultModel;
|
|
706
|
-
if (typeof effective === "string") return effective;
|
|
707
|
-
if (effective !== undefined) return "
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
config.defaultModelFallbacks?.[0] ??
|
|
711
|
-
fallback.FALLBACK_MODEL_IDS[0]!
|
|
712
|
-
);
|
|
706
|
+
if (typeof effective === "string") return { kind: "configured", model: effective };
|
|
707
|
+
if (effective !== undefined) return { kind: "dynamic" };
|
|
708
|
+
const environment = process.env.DATABRICKS_SERVING_ENDPOINT_NAME;
|
|
709
|
+
return environment ? { kind: "configured", model: environment } : { kind: "auto" };
|
|
713
710
|
}
|
|
714
711
|
|
|
715
712
|
/**
|
package/src/config.ts
CHANGED
|
@@ -327,11 +327,10 @@ export interface MastraPluginConfig extends BasePluginConfig {
|
|
|
327
327
|
* When unset, resolution is driven by the live Foundation Model API
|
|
328
328
|
* `quality` / `speed` / `cost` scores: endpoints are classified into
|
|
329
329
|
* chat classes (`classifyEndpoints`) and walked best-first
|
|
330
|
-
* (ChatThinking -> ChatBalanced -> ChatFast)
|
|
331
|
-
*
|
|
332
|
-
*
|
|
333
|
-
*
|
|
334
|
-
* endpoints in front of the auto-classified catalogue.
|
|
330
|
+
* (ChatThinking -> ChatBalanced -> ChatFast). The automatic default is
|
|
331
|
+
* live-only and fails when no matching endpoint is currently available.
|
|
332
|
+
* Set this to pin a regulated workspace to an approved subset, or to put
|
|
333
|
+
* custom endpoints in front of the auto-classified catalogue.
|
|
335
334
|
*/
|
|
336
335
|
defaultModelFallbacks?: readonly string[];
|
|
337
336
|
/**
|
|
@@ -654,7 +653,7 @@ export const MASTRA_CONFIG_SCHEMA: ConfigSchema = {
|
|
|
654
653
|
defaultModel: {
|
|
655
654
|
type: "string",
|
|
656
655
|
description:
|
|
657
|
-
"Serving endpoint applied to every agent that omits its own model. Falls back to DATABRICKS_SERVING_ENDPOINT_NAME, then the
|
|
656
|
+
"Serving endpoint applied to every agent that omits its own model. Falls back to DATABRICKS_SERVING_ENDPOINT_NAME, then the highest-ranked currently available catalogue endpoint.",
|
|
658
657
|
},
|
|
659
658
|
defaultModelFallbacks: {
|
|
660
659
|
type: "array",
|
package/src/model.ts
CHANGED
|
@@ -27,7 +27,7 @@ import { getExecutionContext } from "@databricks/appkit";
|
|
|
27
27
|
import { classes, invoke, resolve } from "@dbx-tools/model";
|
|
28
28
|
import { ModelServingApi, modelServingApi } from "@dbx-tools/model-rs";
|
|
29
29
|
import { functionModule, json, log, net } from "@dbx-tools/shared-core";
|
|
30
|
-
import { model } from "@dbx-tools/shared-model";
|
|
30
|
+
import { model, type ServingEndpointSummary } from "@dbx-tools/shared-model";
|
|
31
31
|
import type { MastraModelConfig } from "@mastra/core/llm";
|
|
32
32
|
import type { RequestContext } from "@mastra/core/request-context";
|
|
33
33
|
|
|
@@ -74,6 +74,43 @@ export interface BuildModelOverrides {
|
|
|
74
74
|
modelClass?: ModelClass;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
function selectionInput(
|
|
78
|
+
config: MastraPluginConfig,
|
|
79
|
+
requested: string | undefined,
|
|
80
|
+
defaultClass: ModelClass | undefined,
|
|
81
|
+
serving = resolveServingConfig(config),
|
|
82
|
+
) {
|
|
83
|
+
const requestedClass = requested !== undefined ? parseModelClass(requested) : null;
|
|
84
|
+
const explicit = requestedClass === null ? requested : undefined;
|
|
85
|
+
const modelClass = requestedClass ?? defaultClass;
|
|
86
|
+
return {
|
|
87
|
+
...(explicit !== undefined ? { explicit } : {}),
|
|
88
|
+
fuzzy: serving.fuzzy,
|
|
89
|
+
threshold: serving.threshold,
|
|
90
|
+
...(modelClass !== undefined ? { modelClass } : {}),
|
|
91
|
+
fallbacks: serving.fallbacks,
|
|
92
|
+
liveOnly: requested === undefined,
|
|
93
|
+
ttlMs: serving.ttlMs,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Resolve an agent's unpinned default against an already-loaded live catalogue.
|
|
99
|
+
*
|
|
100
|
+
* With no configured id/class/fallback, the generic model ranker selects the
|
|
101
|
+
* highest-ranked currently available GPT, then falls back to the highest-ranked
|
|
102
|
+
* live chat endpoint when the workspace has no GPT.
|
|
103
|
+
*/
|
|
104
|
+
export function resolveDefaultModelId(
|
|
105
|
+
config: MastraPluginConfig,
|
|
106
|
+
endpoints: readonly ServingEndpointSummary[],
|
|
107
|
+
overrides: BuildModelOverrides = {},
|
|
108
|
+
): string {
|
|
109
|
+
const requested = overrides.modelId ?? process.env.DATABRICKS_SERVING_ENDPOINT_NAME;
|
|
110
|
+
return resolve.resolveModel(endpoints, selectionInput(config, requested, overrides.modelClass))
|
|
111
|
+
.modelId;
|
|
112
|
+
}
|
|
113
|
+
|
|
77
114
|
/**
|
|
78
115
|
* Resolve a `MastraModelConfig` for the current agent step. Runs
|
|
79
116
|
* while `agent.stream` is inside the `asUser(req)` scope so tokens
|
|
@@ -122,18 +159,12 @@ export async function buildModel(
|
|
|
122
159
|
// internal `overrides.modelClass` (e.g. the chart planner) is the
|
|
123
160
|
// floor when nothing was requested.
|
|
124
161
|
const requested = override ?? overrides.modelId ?? process.env.DATABRICKS_SERVING_ENDPOINT_NAME;
|
|
125
|
-
const requestedClass = requested !== undefined ? parseModelClass(requested) : null;
|
|
126
|
-
const explicit = requestedClass === null ? requested : undefined;
|
|
127
|
-
const modelClass = requestedClass ?? overrides.modelClass;
|
|
128
162
|
|
|
129
|
-
const { modelId, source } = await selectModel(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
fallbacks: serving.fallbacks,
|
|
135
|
-
ttlMs: serving.ttlMs,
|
|
136
|
-
});
|
|
163
|
+
const { modelId, source } = await selectModel(
|
|
164
|
+
executionContext.client,
|
|
165
|
+
host,
|
|
166
|
+
selectionInput(config, requested, overrides.modelClass, serving),
|
|
167
|
+
);
|
|
137
168
|
logger.debug("model selected", { modelId, source, requested });
|
|
138
169
|
|
|
139
170
|
return {
|
package/src/plugin.ts
CHANGED
|
@@ -95,6 +95,7 @@ import {
|
|
|
95
95
|
import { buildMcpServer, type ResolvedMcp } from "./mcp.ts";
|
|
96
96
|
import { createMemoryBuilder, createServicePrincipalPool, needsLakebase } from "./memory.ts";
|
|
97
97
|
import { logFeedback, resolveFeedbackEnabled } from "./mlflow.ts";
|
|
98
|
+
import { resolveDefaultModelId } from "./model.ts";
|
|
98
99
|
import { buildObservability } from "./observability.ts";
|
|
99
100
|
import { provisionRemoteSkills } from "./remote-skills.ts";
|
|
100
101
|
import {
|
|
@@ -506,16 +507,12 @@ export class MastraPlugin extends Plugin<MastraPluginConfig> {
|
|
|
506
507
|
},
|
|
507
508
|
});
|
|
508
509
|
|
|
509
|
-
// `GET /default-model` (and `/default-model/:agentId`) reports
|
|
510
|
-
//
|
|
511
|
-
//
|
|
512
|
-
//
|
|
513
|
-
//
|
|
514
|
-
//
|
|
515
|
-
// static default (a dynamic, call-time model); an unknown agent id is a
|
|
516
|
-
// 404, matching the history / threads routes. Reads only in-memory build
|
|
517
|
-
// state, so it needs no OBO scoping. Registered before the catch-all,
|
|
518
|
-
// same as `/models`.
|
|
510
|
+
// `GET /default-model` (and `/default-model/:agentId`) reports what an
|
|
511
|
+
// unpinned turn will use. A configured string is returned directly; an
|
|
512
|
+
// automatic default resolves the highest-ranked currently available GPT
|
|
513
|
+
// (or general chat fallback) from the same OBO-scoped live catalogue as
|
|
514
|
+
// `/models`; a custom dynamic resolver remains null because it is call-time
|
|
515
|
+
// application code.
|
|
519
516
|
const handleDefaultModel = async (
|
|
520
517
|
req: express.Request,
|
|
521
518
|
res: express.Response,
|
|
@@ -526,11 +523,20 @@ export class MastraPlugin extends Plugin<MastraPluginConfig> {
|
|
|
526
523
|
return;
|
|
527
524
|
}
|
|
528
525
|
const agentId = requested ?? this.built?.defaultAgentId ?? FALLBACK_AGENT_ID;
|
|
529
|
-
const
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
526
|
+
const intent = this.built?.defaultModels[agentId];
|
|
527
|
+
let model: string | null = null;
|
|
528
|
+
if (intent?.kind === "configured") {
|
|
529
|
+
model = intent.model;
|
|
530
|
+
} else if (intent?.kind === "auto") {
|
|
531
|
+
const result = await this.scopedSelf(req).listModelsResult();
|
|
532
|
+
if (!result.ok) {
|
|
533
|
+
this.sendFailure(res, result, "default-model", MODEL_CATALOGUE_FAILED_MESSAGE);
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
if (result.data.length > 0) {
|
|
537
|
+
model = resolveDefaultModelId(this.config, result.data);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
534
540
|
res.json({
|
|
535
541
|
agentId,
|
|
536
542
|
model,
|