@dbx-tools/appkit-mastra 0.1.28 → 0.1.29

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.
@@ -19,6 +19,7 @@ import { buildGenieToolkitProvider, resolveGenieSpaces } from "./genie.js";
19
19
  import { buildModel, FALLBACK_MODEL_IDS } from "./model.js";
20
20
  import { stripStaleChartsProcessor } from "./processors/strip-stale-charts.js";
21
21
  import { buildRenderDataTool } from "./chart.js";
22
+ import { ResultProcessor } from "./processor.js";
22
23
  /** Re-export of Mastra's native `createTool` for full-feature access. */
23
24
  export { createTool } from "@mastra/core/tools";
24
25
  /**
@@ -190,6 +191,7 @@ export async function buildAgents(opts) {
190
191
  // chartIds from prior assistant tool results into the new
191
192
  // turn's `[chart:<id>]` markers. Opt out per-plugin via
192
193
  // `config.stripStaleCharts: false`.
194
+ const outputProcessors = [new ResultProcessor()];
193
195
  const inputProcessors = config.stripStaleCharts === false ? [] : [stripStaleChartsProcessor];
194
196
  const agents = {};
195
197
  for (const [id, def] of Object.entries(definitions)) {
@@ -206,7 +208,8 @@ export async function buildAgents(opts) {
206
208
  },
207
209
  tools,
208
210
  ...(memory ? { memory } : {}),
209
- ...(inputProcessors.length > 0 ? { inputProcessors } : {}),
211
+ inputProcessors,
212
+ outputProcessors,
210
213
  });
211
214
  // Surface the effective default model per agent so operators can
212
215
  // see at a glance which endpoint each agent points at without
package/dist/src/model.js CHANGED
@@ -24,7 +24,7 @@
24
24
  * (network blip, expired token at cache-fill time) we fall back to
25
25
  * the input verbatim and let Databricks return the canonical error.
26
26
  */
27
- import { commonUtils, logUtils, netUtils, stringUtils, } from "@dbx-tools/shared";
27
+ import { commonUtils, logUtils, netUtils, stringUtils } from "@dbx-tools/shared";
28
28
  import { MASTRA_USER_KEY } from "./config.js";
29
29
  import { listServingEndpoints, MASTRA_MODEL_OVERRIDE_KEY, resolveModelId, resolveServingConfig, } from "./serving.js";
30
30
  /**
@@ -325,7 +325,7 @@ const setupFetchInterceptor = commonUtils.memoize(() => {
325
325
  const log = logUtils.logger("mastra/llm");
326
326
  const original = globalThis.fetch.bind(globalThis);
327
327
  globalThis.fetch = (async (input, init) => {
328
- const url = netUtils.parseUrl(input);
328
+ const url = netUtils.urlBuilder(input);
329
329
  if (!url ||
330
330
  !url.pathname.startsWith(SERVING_ENDPOINTS_PATH_PREFIX) ||
331
331
  typeof init?.body !== "string") {
@@ -37,9 +37,9 @@ import { historyRoute } from "./history.js";
37
37
  import { createMemoryBuilder, needsLakebase } from "./memory.js";
38
38
  import { buildObservability } from "./observability.js";
39
39
  import { attachRoutePatchMiddleware, MastraServer } from "./server.js";
40
- import { installStreamEventInterceptor, } from "./intercept.js";
41
40
  import { clearServingEndpointsCache, listServingEndpoints, resolveServingConfig, } from "./serving.js";
42
41
  import { fetchStatementData, isStatementNotFoundError, STATEMENT_ROW_CAP, } from "./statement.js";
42
+ import { ResultProcessor } from "./processor.js";
43
43
  const GENIE_MANIFEST = appkitUtils.data(genie).plugin.manifest;
44
44
  const LAKEBASE_MANIFEST = appkitUtils.data(lakebase).plugin.manifest;
45
45
  /**
@@ -270,11 +270,6 @@ export class MastraPlugin extends Plugin {
270
270
  router.use("", (req, res, next) => {
271
271
  if (!this.mastraApp)
272
272
  return res.status(503).end();
273
- // Run each Mastra `/stream` SSE frame through the interceptor
274
- // (keep / rewrite / drop). Only engages on a
275
- // `200 text/event-stream` body, so the JSON routes above and any
276
- // error response are untouched.
277
- installStreamEventInterceptor(res, interceptStreamFrame);
278
273
  return this.userScopedSelf(req).mastraApp(req, res, next);
279
274
  });
280
275
  }
@@ -441,37 +436,4 @@ function parseStatementLimit(raw) {
441
436
  return undefined;
442
437
  return Math.floor(n);
443
438
  }
444
- /**
445
- * {@link StreamFrameInterceptor} for Mastra `/stream` responses.
446
- *
447
- * Removes large, redundant payloads from terminal `step-finish`,
448
- * `finish`, and `tool-result` frames before they reach the browser.
449
- * These frames often repeat information already delivered incrementally
450
- * via streamed text and tool events, including full tool outputs,
451
- * accumulated responses, message history, SQL results, chart data, and
452
- * other large result payloads.
453
- *
454
- * The interceptor deletes heavyweight payload properties
455
- * (`output`, `messages`, `response`, and `result`) while preserving the
456
- * event envelope and lifecycle metadata required by the client.
457
- *
458
- * Deletion is key based, so streams that do not contain these
459
- * fields are passed through unchanged.
460
- */
461
- const interceptStreamFrame = (chunk) => {
462
- if (!commonUtils.isRecord(chunk))
463
- return true;
464
- if (!["step-finish", "finish", "tool-result"].find((type) => type === chunk.type))
465
- return true;
466
- const payload = chunk.payload;
467
- if (!commonUtils.isRecord(payload))
468
- return true;
469
- const trimmedPayload = commonUtils.deleteKeys(payload, [
470
- "output",
471
- "messages",
472
- "response",
473
- "result",
474
- ]);
475
- return trimmedPayload ? { replace: chunk } : true;
476
- };
477
439
  export const mastra = toPlugin(MastraPlugin);
@@ -0,0 +1,8 @@
1
+ import type { Processor } from "@mastra/core/processors";
2
+ export declare class ResultProcessor implements Processor {
3
+ id: string;
4
+ processDataParts: boolean;
5
+ processOutputStream({ part }: {
6
+ part: any;
7
+ }): Promise<any | null>;
8
+ }
@@ -0,0 +1,40 @@
1
+ export class ResultProcessor {
2
+ id = "result-processor";
3
+ // Tell Mastra to also route tool/data parts to this processor method
4
+ processDataParts = true;
5
+ async processOutputStream({ part }) {
6
+ // 1. Guard clause: Ensure the chunk is a valid object
7
+ if (!part || typeof part !== "object") {
8
+ return part;
9
+ }
10
+ // 2. Filter for the targeted frame types
11
+ const targetedTypes = ["step-finish", "finish", "tool-result", "data-tool-agent"];
12
+ if (!targetedTypes.includes(part.type)) {
13
+ return part; // Return unchanged to pass-through
14
+ }
15
+ // 3. Check for the presence of a payload object
16
+ const payload = part.payload;
17
+ if (!payload || typeof payload !== "object") {
18
+ return part;
19
+ }
20
+ // 4. Safely delete the unwanted keys from the payload reference
21
+ const keysToDelete = ["output", "messages", "response", "result"];
22
+ for (const key of keysToDelete) {
23
+ if (key in payload) {
24
+ const value = payload[key];
25
+ if (typeof value === "object") {
26
+ payload[key] = {};
27
+ }
28
+ else if (Array.isArray(value)) {
29
+ payload[key] = [];
30
+ }
31
+ else {
32
+ delete payload[key];
33
+ }
34
+ }
35
+ }
36
+ // 5. Return the modified part object. Mastra handles re-serialization
37
+ // for the outbound SSE client stream automatically.
38
+ return part;
39
+ }
40
+ }