@dbx-tools/appkit-mastra 0.6.211 → 0.6.213
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/LICENSE +202 -0
- package/README.md +13 -0
- package/index.ts +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +2 -2
- package/lib/src/_agent-route-context.d.ts +46 -0
- package/lib/src/_agent-route-context.js +47 -0
- package/lib/src/config.d.ts +7 -0
- package/lib/src/config.js +5 -1
- package/lib/src/genie.js +20 -13
- package/lib/src/history.d.ts +2 -7
- package/lib/src/history.js +5 -41
- package/lib/src/plugin.d.ts +12 -0
- package/lib/src/plugin.js +25 -1
- package/lib/src/threads.d.ts +2 -7
- package/lib/src/threads.js +10 -47
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +15 -14
- package/src/_agent-route-context.ts +100 -0
- package/src/config.ts +12 -0
- package/src/genie.ts +25 -13
- package/src/history.ts +9 -46
- package/src/plugin.ts +25 -0
- package/src/threads.ts +14 -52
package/src/plugin.ts
CHANGED
|
@@ -455,6 +455,16 @@ export class MastraPlugin extends Plugin<MastraPluginConfig> {
|
|
|
455
455
|
}
|
|
456
456
|
|
|
457
457
|
override injectRoutes(router: IAppRouter): void {
|
|
458
|
+
this.registerMcpRoutes(router);
|
|
459
|
+
this.registerModelRoutes(router);
|
|
460
|
+
this.registerEmbedRoutes(router);
|
|
461
|
+
this.registerSuggestionRoutes(router);
|
|
462
|
+
this.registerFeedbackRoutes(router);
|
|
463
|
+
this.registerAgentRoutes(router);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/** Register URL aliases for Mastra's MCP transports. */
|
|
467
|
+
private registerMcpRoutes(router: IAppRouter): void {
|
|
458
468
|
// Expose the MCP transport at the clean `/mcp` (plus the legacy
|
|
459
469
|
// `/sse` + `/messages`) under the plugin mount. `@mastra/express`
|
|
460
470
|
// mounts MCP under `/mcp/<serverId>/<transport>`, and the serverId
|
|
@@ -475,7 +485,10 @@ export class MastraPlugin extends Plugin<MastraPluginConfig> {
|
|
|
475
485
|
}
|
|
476
486
|
next();
|
|
477
487
|
});
|
|
488
|
+
}
|
|
478
489
|
|
|
490
|
+
/** Register model catalogue and per-agent default-model routes. */
|
|
491
|
+
private registerModelRoutes(router: IAppRouter): void {
|
|
479
492
|
// `GET /models` exposes the cached endpoint list so clients can
|
|
480
493
|
// populate model pickers, validate `?model=` choices, etc. Must
|
|
481
494
|
// be registered before the catch-all that forwards everything to
|
|
@@ -537,7 +550,10 @@ export class MastraPlugin extends Plugin<MastraPluginConfig> {
|
|
|
537
550
|
path: `${routes.MASTRA_ROUTES.defaultModel}/:agentId`,
|
|
538
551
|
handler: handleDefaultModel,
|
|
539
552
|
});
|
|
553
|
+
}
|
|
540
554
|
|
|
555
|
+
/** Register the generic chart and statement embed resolver. */
|
|
556
|
+
private registerEmbedRoutes(router: IAppRouter): void {
|
|
541
557
|
// `GET /embed/:type/:id` is the single resolver for every embed
|
|
542
558
|
// marker the agent emits in prose (`[chart:<id>]`,
|
|
543
559
|
// `[data:<id>]`, ...). `:type` selects a resolver from the
|
|
@@ -647,7 +663,10 @@ export class MastraPlugin extends Plugin<MastraPluginConfig> {
|
|
|
647
663
|
res.json(result.data);
|
|
648
664
|
},
|
|
649
665
|
});
|
|
666
|
+
}
|
|
650
667
|
|
|
668
|
+
/** Register default and agent-qualified suggestion routes. */
|
|
669
|
+
private registerSuggestionRoutes(router: IAppRouter): void {
|
|
651
670
|
// `GET /suggestions` (and `/suggestions/:agentId`) returns the
|
|
652
671
|
// curated starter questions for the agent's Genie space(s) - the
|
|
653
672
|
// author-configured `sample_questions`, surfaced as one-tap
|
|
@@ -691,7 +710,10 @@ export class MastraPlugin extends Plugin<MastraPluginConfig> {
|
|
|
691
710
|
path: `${routes.MASTRA_ROUTES.suggestions}/:agentId`,
|
|
692
711
|
handler: handleSuggestions,
|
|
693
712
|
});
|
|
713
|
+
}
|
|
694
714
|
|
|
715
|
+
/** Register MLflow feedback submission when configured. */
|
|
716
|
+
private registerFeedbackRoutes(router: IAppRouter): void {
|
|
695
717
|
// `POST /route/feedback` logs a thumbs / comment assessment against
|
|
696
718
|
// a turn's MLflow trace (the `traceId` the client captured from the
|
|
697
719
|
// stream response's trace-id header). Registered on the AppKit
|
|
@@ -735,7 +757,10 @@ export class MastraPlugin extends Plugin<MastraPluginConfig> {
|
|
|
735
757
|
});
|
|
736
758
|
},
|
|
737
759
|
});
|
|
760
|
+
}
|
|
738
761
|
|
|
762
|
+
/** Register the gated Mastra catch-all after every explicit route. */
|
|
763
|
+
private registerAgentRoutes(router: IAppRouter): void {
|
|
739
764
|
// Middleware rather than `this.route`: this is the catch-all that hands
|
|
740
765
|
// every remaining method / path pair to the Mastra sub-app, so it has no
|
|
741
766
|
// single method or path to register under.
|
package/src/threads.ts
CHANGED
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
* @module
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import { ValidationError } from "@databricks/appkit";
|
|
25
24
|
import { log } from "@dbx-tools/shared-core";
|
|
26
25
|
import {
|
|
27
26
|
wire,
|
|
@@ -32,10 +31,14 @@ import {
|
|
|
32
31
|
} from "@dbx-tools/shared-mastra";
|
|
33
32
|
import type { Agent } from "@mastra/core/agent";
|
|
34
33
|
import type { StorageThreadType } from "@mastra/core/memory";
|
|
35
|
-
import { MASTRA_RESOURCE_ID_KEY, MASTRA_THREAD_ID_KEY } from "@mastra/core/request-context";
|
|
36
34
|
import type { ContextWithMastra } from "@mastra/core/server";
|
|
37
35
|
import { registerApiRoute } from "@mastra/core/server";
|
|
38
36
|
|
|
37
|
+
import {
|
|
38
|
+
resolveAgentRequestContext,
|
|
39
|
+
resolveAgentRouteOptions,
|
|
40
|
+
type AgentRouteOptions,
|
|
41
|
+
} from "./_agent-route-context.ts";
|
|
39
42
|
import { clampPerPage, parseIntParam } from "./pagination.ts";
|
|
40
43
|
import { invalidFields } from "./validation.ts";
|
|
41
44
|
|
|
@@ -196,8 +199,7 @@ export async function renameThread(opts: RenameThreadOptions): Promise<MastraThr
|
|
|
196
199
|
}
|
|
197
200
|
|
|
198
201
|
/** Options accepted by {@link threadsRoute}. */
|
|
199
|
-
export type ThreadsRouteOptions =
|
|
200
|
-
{ path: `${string}:agentId${string}`; agent?: never } | { path: string; agent: string };
|
|
202
|
+
export type ThreadsRouteOptions = AgentRouteOptions;
|
|
201
203
|
|
|
202
204
|
/**
|
|
203
205
|
* Register the `<path>` Mastra custom API route. Handles three methods
|
|
@@ -221,45 +223,13 @@ export type ThreadsRouteOptions =
|
|
|
221
223
|
* agent) and `/route/threads/:agentId`.
|
|
222
224
|
*/
|
|
223
225
|
export function threadsRoute(options: ThreadsRouteOptions) {
|
|
224
|
-
const { path } = options;
|
|
225
|
-
const fixedAgent = "agent" in options ? options.agent : undefined;
|
|
226
|
-
if (!fixedAgent && !path.includes(":agentId")) {
|
|
227
|
-
throw ValidationError.invalidValue(
|
|
228
|
-
"threadsRoute.path",
|
|
229
|
-
path,
|
|
230
|
-
"a path containing `:agentId`, or an explicit `agent`",
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
|
-
// Shared by GET / DELETE: resolve the active agent and the caller's
|
|
234
|
-
// resource id, returning a JSON error response when either is
|
|
235
|
-
// missing. Keeps both handlers thin with identical validation.
|
|
236
|
-
const resolveContext = (c: ContextWithMastra) => {
|
|
237
|
-
const mastra = c.get("mastra");
|
|
238
|
-
const requestContext = c.get("requestContext");
|
|
239
|
-
const agentId = fixedAgent ?? c.req.param("agentId");
|
|
240
|
-
if (!agentId) {
|
|
241
|
-
return { error: c.json({ error: "agentId is required" }, 400) } as const;
|
|
242
|
-
}
|
|
243
|
-
const agent = mastra.getAgentById(agentId);
|
|
244
|
-
if (!agent) {
|
|
245
|
-
return {
|
|
246
|
-
error: c.json({ error: `Unknown agent "${agentId}"` }, 404),
|
|
247
|
-
} as const;
|
|
248
|
-
}
|
|
249
|
-
const resourceId = requestContext.get(MASTRA_RESOURCE_ID_KEY) as string | undefined;
|
|
250
|
-
if (!resourceId) {
|
|
251
|
-
return {
|
|
252
|
-
error: c.json({ error: "resource id missing from request context" }, 400),
|
|
253
|
-
} as const;
|
|
254
|
-
}
|
|
255
|
-
return { agentId, agent, requestContext, resourceId } as const;
|
|
256
|
-
};
|
|
226
|
+
const { path, fixedAgent } = resolveAgentRouteOptions(options, "threadsRoute.path");
|
|
257
227
|
|
|
258
228
|
return [
|
|
259
229
|
registerApiRoute(path, {
|
|
260
230
|
method: "GET",
|
|
261
231
|
handler: async (c: ContextWithMastra) => {
|
|
262
|
-
const ctx =
|
|
232
|
+
const ctx = resolveAgentRequestContext(c, { fixedAgent });
|
|
263
233
|
if ("error" in ctx) return ctx.error;
|
|
264
234
|
const payload = await listThreads({
|
|
265
235
|
agent: ctx.agent,
|
|
@@ -273,21 +243,17 @@ export function threadsRoute(options: ThreadsRouteOptions) {
|
|
|
273
243
|
registerApiRoute(path, {
|
|
274
244
|
method: "DELETE",
|
|
275
245
|
handler: async (c: ContextWithMastra) => {
|
|
276
|
-
const ctx =
|
|
246
|
+
const ctx = resolveAgentRequestContext(c, { fixedAgent, threadId: "required" });
|
|
277
247
|
if ("error" in ctx) return ctx.error;
|
|
278
|
-
const threadId = ctx.requestContext.get(MASTRA_THREAD_ID_KEY) as string | undefined;
|
|
279
|
-
if (!threadId) {
|
|
280
|
-
return c.json({ error: "thread id missing from request context" }, 400);
|
|
281
|
-
}
|
|
282
248
|
const { deleted } = await deleteThread({
|
|
283
249
|
agent: ctx.agent,
|
|
284
|
-
threadId,
|
|
250
|
+
threadId: ctx.threadId,
|
|
285
251
|
resourceId: ctx.resourceId,
|
|
286
252
|
});
|
|
287
253
|
const payload: MastraDeleteThreadResponse = {
|
|
288
254
|
ok: true,
|
|
289
255
|
agentId: ctx.agentId,
|
|
290
|
-
threadId,
|
|
256
|
+
threadId: ctx.threadId,
|
|
291
257
|
deleted,
|
|
292
258
|
};
|
|
293
259
|
return c.json(payload);
|
|
@@ -296,12 +262,8 @@ export function threadsRoute(options: ThreadsRouteOptions) {
|
|
|
296
262
|
registerApiRoute(path, {
|
|
297
263
|
method: "PATCH",
|
|
298
264
|
handler: async (c: ContextWithMastra) => {
|
|
299
|
-
const ctx =
|
|
265
|
+
const ctx = resolveAgentRequestContext(c, { fixedAgent, threadId: "required" });
|
|
300
266
|
if ("error" in ctx) return ctx.error;
|
|
301
|
-
const threadId = ctx.requestContext.get(MASTRA_THREAD_ID_KEY) as string | undefined;
|
|
302
|
-
if (!threadId) {
|
|
303
|
-
return c.json({ error: "thread id missing from request context" }, 400);
|
|
304
|
-
}
|
|
305
267
|
const body = wire.MastraUpdateThreadRequestSchema.safeParse(await c.req.json());
|
|
306
268
|
if (!body.success) {
|
|
307
269
|
logger.warn("rename:invalid", { error: body.error.message });
|
|
@@ -309,12 +271,12 @@ export function threadsRoute(options: ThreadsRouteOptions) {
|
|
|
309
271
|
}
|
|
310
272
|
const thread = await renameThread({
|
|
311
273
|
agent: ctx.agent,
|
|
312
|
-
threadId,
|
|
274
|
+
threadId: ctx.threadId,
|
|
313
275
|
resourceId: ctx.resourceId,
|
|
314
276
|
title: body.data.title,
|
|
315
277
|
});
|
|
316
278
|
if (!thread) {
|
|
317
|
-
return c.json({ error: `Unknown thread "${threadId}"` }, 404);
|
|
279
|
+
return c.json({ error: `Unknown thread "${ctx.threadId}"` }, 404);
|
|
318
280
|
}
|
|
319
281
|
const payload: MastraUpdateThreadResponse = {
|
|
320
282
|
ok: true,
|