@dbx-tools/appkit-mastra 0.3.44 → 0.4.1

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 (56) hide show
  1. package/lib/index.d.ts +71 -0
  2. package/lib/index.js +56 -0
  3. package/lib/src/agents.d.ts +347 -0
  4. package/lib/src/agents.js +554 -0
  5. package/lib/src/chart.d.ts +192 -0
  6. package/lib/src/chart.js +638 -0
  7. package/lib/src/config.d.ts +479 -0
  8. package/lib/src/config.js +190 -0
  9. package/lib/src/defaults.d.ts +68 -0
  10. package/lib/src/defaults.js +107 -0
  11. package/lib/src/filesystems.d.ts +208 -0
  12. package/lib/src/filesystems.js +958 -0
  13. package/lib/src/genie.d.ts +166 -0
  14. package/lib/src/genie.js +969 -0
  15. package/lib/src/history.d.ts +97 -0
  16. package/lib/src/history.js +264 -0
  17. package/lib/src/mcp.d.ts +66 -0
  18. package/lib/src/mcp.js +65 -0
  19. package/lib/src/memory.d.ts +111 -0
  20. package/lib/src/memory.js +275 -0
  21. package/lib/src/mlflow.d.ts +63 -0
  22. package/lib/src/mlflow.js +117 -0
  23. package/lib/src/model.d.ts +62 -0
  24. package/lib/src/model.js +168 -0
  25. package/lib/src/observability.d.ts +81 -0
  26. package/lib/src/observability.js +98 -0
  27. package/lib/src/pagination.d.ts +23 -0
  28. package/lib/src/pagination.js +31 -0
  29. package/lib/src/plugin.d.ts +352 -0
  30. package/lib/src/plugin.js +1015 -0
  31. package/lib/src/processors.d.ts +62 -0
  32. package/lib/src/processors.js +162 -0
  33. package/lib/src/rest.d.ts +36 -0
  34. package/lib/src/rest.js +46 -0
  35. package/lib/src/server.d.ts +155 -0
  36. package/lib/src/server.js +336 -0
  37. package/lib/src/serving-sanitize.d.ts +104 -0
  38. package/lib/src/serving-sanitize.js +228 -0
  39. package/lib/src/serving.d.ts +61 -0
  40. package/lib/src/serving.js +78 -0
  41. package/lib/src/statement.d.ts +51 -0
  42. package/lib/src/statement.js +83 -0
  43. package/lib/src/storage-schema.d.ts +14 -0
  44. package/lib/src/storage-schema.js +34 -0
  45. package/lib/src/summarize.d.ts +70 -0
  46. package/lib/src/summarize.js +142 -0
  47. package/lib/src/threads.d.ts +109 -0
  48. package/lib/src/threads.js +301 -0
  49. package/lib/src/validation.d.ts +19 -0
  50. package/lib/src/validation.js +17 -0
  51. package/lib/src/workspaces.d.ts +68 -0
  52. package/lib/src/workspaces.js +246 -0
  53. package/lib/src/writer.d.ts +25 -0
  54. package/lib/src/writer.js +40 -0
  55. package/lib/tsconfig.tsbuildinfo +1 -0
  56. package/package.json +17 -13
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Mastra stream processors wired onto the plugin's agents.
3
+ *
4
+ * Two complementary processors live here:
5
+ *
6
+ * - An **input** processor ({@link stripStaleChartsProcessor}) that
7
+ * scrubs turn-scoped `chartId` fields out of prior tool results
8
+ * replayed from Memory, so the model can't copy a stale id into the
9
+ * new turn's `[chart:<id>]` markers.
10
+ * - An **output** processor ({@link ResultProcessor}) that trims the
11
+ * bulky, redundant payload fields off targeted outbound stream frames
12
+ * before they're serialized to the SSE client.
13
+ *
14
+ * @module
15
+ */
16
+ import type { InputProcessor, Processor } from "@mastra/core/processors";
17
+ /**
18
+ * Mastra input processor that strips `chartId` fields from every
19
+ * tool-invocation result in prior assistant messages before they
20
+ * reach the model.
21
+ *
22
+ * Why: chartIds are turn-scoped from the model's point of view -
23
+ * each `prepare_chart` / `render_data` call mints a fresh id and
24
+ * the host UI binds it to that turn's reply. Mastra Memory
25
+ * replays prior tool results into the prompt; if old chartIds
26
+ * leak through, the model is tempted to copy them verbatim into
27
+ * the new turn's `[chart:<id>]` markers and the host UI ends up
28
+ * rendering an unrelated chart from the chart cache (or
29
+ * a 404 once the 1h TTL elapsed). This processor removes the
30
+ * temptation by deleting `chartId` keys from every assistant
31
+ * message's tool results before the prompt is built. The current
32
+ * turn's tool results don't exist yet at `processInput` time, so
33
+ * they pass through unmodified.
34
+ *
35
+ * The strip is recursive - any nested `chartId` field is removed,
36
+ * regardless of which tool produced the result. This covers
37
+ * `prepare_chart` / `render_data` top-level chartIds and any
38
+ * legacy `datasets[].chartId` payloads uniformly without coupling
39
+ * to specific tool ids.
40
+ *
41
+ * Wired onto every agent by default via `buildAgents`; opt out with
42
+ * `MastraPluginConfig.stripStaleCharts: false`.
43
+ */
44
+ export declare const stripStaleChartsProcessor: InputProcessor;
45
+ /**
46
+ * Mastra output processor that trims the bulky, redundant payload
47
+ * fields off targeted outbound stream frames.
48
+ *
49
+ * Mastra emits step / finish / tool-result frames whose payloads
50
+ * echo the full tool `output` / `result` / assistant `messages` /
51
+ * `response` - data the chat client already received inline and
52
+ * doesn't need re-sent. This processor empties those keys on the
53
+ * targeted frame types so the outbound SSE stream stays lean;
54
+ * every other frame passes through untouched.
55
+ */
56
+ export declare class ResultProcessor implements Processor {
57
+ id: string;
58
+ processDataParts: boolean;
59
+ processOutputStream({ part }: {
60
+ part: any;
61
+ }): Promise<any | null>;
62
+ }
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Mastra stream processors wired onto the plugin's agents.
3
+ *
4
+ * Two complementary processors live here:
5
+ *
6
+ * - An **input** processor ({@link stripStaleChartsProcessor}) that
7
+ * scrubs turn-scoped `chartId` fields out of prior tool results
8
+ * replayed from Memory, so the model can't copy a stale id into the
9
+ * new turn's `[chart:<id>]` markers.
10
+ * - An **output** processor ({@link ResultProcessor}) that trims the
11
+ * bulky, redundant payload fields off targeted outbound stream frames
12
+ * before they're serialized to the SSE client.
13
+ *
14
+ * @module
15
+ */
16
+ import { log } from "@dbx-tools/shared-core";
17
+ const logger = log.logger("mastra/processors");
18
+ /**
19
+ * Recursively clone `value`, omitting any property whose key is
20
+ * `chartId`. Arrays are mapped element-wise; primitives are
21
+ * returned as-is. The result is structurally identical to the
22
+ * input minus chartIds, so downstream message-shape consumers
23
+ * keep working.
24
+ */
25
+ function stripChartIds(value) {
26
+ if (Array.isArray(value)) {
27
+ return value.map(stripChartIds);
28
+ }
29
+ if (value && typeof value === "object") {
30
+ const obj = value;
31
+ const out = {};
32
+ for (const [key, val] of Object.entries(obj)) {
33
+ if (key === "chartId")
34
+ continue;
35
+ out[key] = stripChartIds(val);
36
+ }
37
+ return out;
38
+ }
39
+ return value;
40
+ }
41
+ /**
42
+ * Mastra input processor that strips `chartId` fields from every
43
+ * tool-invocation result in prior assistant messages before they
44
+ * reach the model.
45
+ *
46
+ * Why: chartIds are turn-scoped from the model's point of view -
47
+ * each `prepare_chart` / `render_data` call mints a fresh id and
48
+ * the host UI binds it to that turn's reply. Mastra Memory
49
+ * replays prior tool results into the prompt; if old chartIds
50
+ * leak through, the model is tempted to copy them verbatim into
51
+ * the new turn's `[chart:<id>]` markers and the host UI ends up
52
+ * rendering an unrelated chart from the chart cache (or
53
+ * a 404 once the 1h TTL elapsed). This processor removes the
54
+ * temptation by deleting `chartId` keys from every assistant
55
+ * message's tool results before the prompt is built. The current
56
+ * turn's tool results don't exist yet at `processInput` time, so
57
+ * they pass through unmodified.
58
+ *
59
+ * The strip is recursive - any nested `chartId` field is removed,
60
+ * regardless of which tool produced the result. This covers
61
+ * `prepare_chart` / `render_data` top-level chartIds and any
62
+ * legacy `datasets[].chartId` payloads uniformly without coupling
63
+ * to specific tool ids.
64
+ *
65
+ * Wired onto every agent by default via `buildAgents`; opt out with
66
+ * `MastraPluginConfig.stripStaleCharts: false`.
67
+ */
68
+ export const stripStaleChartsProcessor = {
69
+ id: "strip-stale-charts",
70
+ description: "Removes chartId fields from prior tool-invocation results so the model can't reuse turn-scoped ids from memory.",
71
+ processInput(args) {
72
+ let stripped = 0;
73
+ for (const message of args.messages) {
74
+ if (message.role !== "assistant")
75
+ continue;
76
+ const parts = message.content?.parts;
77
+ if (!Array.isArray(parts))
78
+ continue;
79
+ for (const part of parts) {
80
+ // Tool-invocation parts hold the persisted tool result.
81
+ // We don't scrub the input args (`rawInput` / `args`) because
82
+ // the chartId there is the model's outgoing claim, not
83
+ // anything it could re-reference; only `result` carries
84
+ // ids that subsequent turns might copy.
85
+ if (part.type !== "tool-invocation") {
86
+ continue;
87
+ }
88
+ const inv = part.toolInvocation;
89
+ if (!inv || inv.result === undefined)
90
+ continue;
91
+ const before = inv.result;
92
+ const after = stripChartIds(before);
93
+ // Cheap structural check via JSON length - the actual
94
+ // strip writes a fresh object only when chartId keys
95
+ // existed, so different stringification length is a
96
+ // reliable signal that something was removed.
97
+ if (typeof before === "object" &&
98
+ before !== null &&
99
+ JSON.stringify(before).length !== JSON.stringify(after).length) {
100
+ inv.result = after;
101
+ stripped += 1;
102
+ }
103
+ }
104
+ }
105
+ if (stripped > 0) {
106
+ logger.debug("stripped", { results: stripped });
107
+ }
108
+ return args.messages;
109
+ },
110
+ };
111
+ /**
112
+ * Mastra output processor that trims the bulky, redundant payload
113
+ * fields off targeted outbound stream frames.
114
+ *
115
+ * Mastra emits step / finish / tool-result frames whose payloads
116
+ * echo the full tool `output` / `result` / assistant `messages` /
117
+ * `response` - data the chat client already received inline and
118
+ * doesn't need re-sent. This processor empties those keys on the
119
+ * targeted frame types so the outbound SSE stream stays lean;
120
+ * every other frame passes through untouched.
121
+ */
122
+ export class ResultProcessor {
123
+ id = "result-processor";
124
+ // Tell Mastra to also route tool/data parts to this processor method
125
+ processDataParts = true;
126
+ async processOutputStream({ part }) {
127
+ // 1. Guard clause: Ensure the chunk is a valid object
128
+ if (!part || typeof part !== "object") {
129
+ return part;
130
+ }
131
+ // 2. Filter for the targeted frame types
132
+ const targetedTypes = ["step-finish", "finish", "tool-result", "data-tool-agent"];
133
+ if (!targetedTypes.includes(part.type)) {
134
+ return part; // Return unchanged to pass-through
135
+ }
136
+ // 3. Check for the presence of a payload object
137
+ const payload = part.payload;
138
+ if (!payload || typeof payload !== "object") {
139
+ return part;
140
+ }
141
+ // 4. Safely delete the unwanted keys from the payload reference
142
+ const keysToDelete = ["output", "messages", "response", "result"];
143
+ for (const key of keysToDelete) {
144
+ if (key in payload) {
145
+ const value = payload[key];
146
+ if (typeof value === "object") {
147
+ payload[key] = {};
148
+ }
149
+ else if (Array.isArray(value)) {
150
+ payload[key] = [];
151
+ }
152
+ else {
153
+ delete payload[key];
154
+ }
155
+ }
156
+ }
157
+ // 5. Return the modified part object. Mastra handles re-serialization
158
+ // for the outbound SSE client stream automatically.
159
+ return part;
160
+ }
161
+ }
162
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvY2Vzc29ycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wcm9jZXNzb3JzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBRUgsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRzdDLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsbUJBQW1CLENBQUMsQ0FBQztBQUUvQzs7Ozs7O0dBTUc7QUFDSCxTQUFTLGFBQWEsQ0FBQyxLQUFjO0lBQ25DLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3pCLE9BQU8sS0FBSyxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBQ0QsSUFBSSxLQUFLLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDdkMsTUFBTSxHQUFHLEdBQUcsS0FBZ0MsQ0FBQztRQUM3QyxNQUFNLEdBQUcsR0FBNEIsRUFBRSxDQUFDO1FBQ3hDLEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDN0MsSUFBSSxHQUFHLEtBQUssU0FBUztnQkFBRSxTQUFTO1lBQ2hDLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDaEMsQ0FBQztRQUNELE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztJQUNELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTBCRztBQUNILE1BQU0sQ0FBQyxNQUFNLHlCQUF5QixHQUFtQjtJQUN2RCxFQUFFLEVBQUUsb0JBQW9CO0lBQ3hCLFdBQVcsRUFDVCxpSEFBaUg7SUFDbkgsWUFBWSxDQUFDLElBQXNCO1FBQ2pDLElBQUksUUFB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QUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztnQkFDbkIsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUMzQixJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRSxDQUFDO29CQUM5QixPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDO2dCQUNwQixDQUFDO3FCQUFNLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO29CQUNoQyxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDO2dCQUNwQixDQUFDO3FCQUFNLENBQUM7b0JBQ04sT0FBTyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ3RCLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUVELHNFQUFzRTtRQUN0RSxvREFBb0Q7UUFDcEQsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIE1hc3RyYSBzdHJlYW0gcHJvY2Vzc29ycyB3aXJlZCBvbnRvIHRoZSBwbHVnaW4ncyBhZ2VudHMuXG4gKlxuICogVHdvIGNvbXBsZW1lbnRhcnkgcHJvY2Vzc29ycyBsaXZlIGhlcmU6XG4gKlxuICogLSBBbiAqKmlucHV0KiogcHJvY2Vzc29yICh7QGxpbmsgc3RyaXBTdGFsZUNoYXJ0c1Byb2Nlc3Nvcn0pIHRoYXRcbiAqICAgc2NydWJzIHR1cm4tc2NvcGVkIGBjaGFydElkYCBmaWVsZHMgb3V0IG9mIHByaW9yIHRvb2wgcmVzdWx0c1xuICogICByZXBsYXllZCBmcm9tIE1lbW9yeSwgc28gdGhlIG1vZGVsIGNhbid0IGNvcHkgYSBzdGFsZSBpZCBpbnRvIHRoZVxuICogICBuZXcgdHVybidzIGBbY2hhcnQ6PGlkPl1gIG1hcmtlcnMuXG4gKiAtIEFuICoqb3V0cHV0KiogcHJvY2Vzc29yICh7QGxpbmsgUmVzdWx0UHJvY2Vzc29yfSkgdGhhdCB0cmltcyB0aGVcbiAqICAgYnVsa3ksIHJlZHVuZGFudCBwYXlsb2FkIGZpZWxkcyBvZmYgdGFyZ2V0ZWQgb3V0Ym91bmQgc3RyZWFtIGZyYW1lc1xuICogICBiZWZvcmUgdGhleSdyZSBzZXJpYWxpemVkIHRvIHRoZSBTU0UgY2xpZW50LlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBsb2cgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHR5cGUgeyBJbnB1dFByb2Nlc3NvciwgUHJvY2Vzc0lucHV0QXJncywgUHJvY2Vzc29yIH0gZnJvbSBcIkBtYXN0cmEvY29yZS9wcm9jZXNzb3JzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJtYXN0cmEvcHJvY2Vzc29yc1wiKTtcblxuLyoqXG4gKiBSZWN1cnNpdmVseSBjbG9uZSBgdmFsdWVgLCBvbWl0dGluZyBhbnkgcHJvcGVydHkgd2hvc2Uga2V5IGlzXG4gKiBgY2hhcnRJZGAuIEFycmF5cyBhcmUgbWFwcGVkIGVsZW1lbnQtd2lzZTsgcHJpbWl0aXZlcyBhcmVcbiAqIHJldHVybmVkIGFzLWlzLiBUaGUgcmVzdWx0IGlzIHN0cnVjdHVyYWxseSBpZGVudGljYWwgdG8gdGhlXG4gKiBpbnB1dCBtaW51cyBjaGFydElkcywgc28gZG93bnN0cmVhbSBtZXNzYWdlLXNoYXBlIGNvbnN1bWVyc1xuICoga2VlcCB3b3JraW5nLlxuICovXG5mdW5jdGlvbiBzdHJpcENoYXJ0SWRzKHZhbHVlOiB1bmtub3duKTogdW5rbm93biB7XG4gIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgIHJldHVybiB2YWx1ZS5tYXAoc3RyaXBDaGFydElkcyk7XG4gIH1cbiAgaWYgKHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PT0gXCJvYmplY3RcIikge1xuICAgIGNvbnN0IG9iaiA9IHZhbHVlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgIGNvbnN0IG91dDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbF0gb2YgT2JqZWN0LmVudHJpZXMob2JqKSkge1xuICAgICAgaWYgKGtleSA9PT0gXCJjaGFydElkXCIpIGNvbnRpbnVlO1xuICAgICAgb3V0W2tleV0gPSBzdHJpcENoYXJ0SWRzKHZhbCk7XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG4gIH1cbiAgcmV0dXJuIHZhbHVlO1xufVxuXG4vKipcbiAqIE1hc3RyYSBpbnB1dCBwcm9jZXNzb3IgdGhhdCBzdHJpcHMgYGNoYXJ0SWRgIGZpZWxkcyBmcm9tIGV2ZXJ5XG4gKiB0b29sLWludm9jYXRpb24gcmVzdWx0IGluIHByaW9yIGFzc2lzdGFudCBtZXNzYWdlcyBiZWZvcmUgdGhleVxuICogcmVhY2ggdGhlIG1vZGVsLlxuICpcbiAqIFdoeTogY2hhcnRJZHMgYXJlIHR1cm4tc2NvcGVkIGZyb20gdGhlIG1vZGVsJ3MgcG9pbnQgb2YgdmlldyAtXG4gKiBlYWNoIGBwcmVwYXJlX2NoYXJ0YCAvIGByZW5kZXJfZGF0YWAgY2FsbCBtaW50cyBhIGZyZXNoIGlkIGFuZFxuICogdGhlIGhvc3QgVUkgYmluZHMgaXQgdG8gdGhhdCB0dXJuJ3MgcmVwbHkuIE1hc3RyYSBNZW1vcnlcbiAqIHJlcGxheXMgcHJpb3IgdG9vbCByZXN1bHRzIGludG8gdGhlIHByb21wdDsgaWYgb2xkIGNoYXJ0SWRzXG4gKiBsZWFrIHRocm91Z2gsIHRoZSBtb2RlbCBpcyB0ZW1wdGVkIHRvIGNvcHkgdGhlbSB2ZXJiYXRpbSBpbnRvXG4gKiB0aGUgbmV3IHR1cm4ncyBgW2NoYXJ0OjxpZD5dYCBtYXJrZXJzIGFuZCB0aGUgaG9zdCBVSSBlbmRzIHVwXG4gKiByZW5kZXJpbmcgYW4gdW5yZWxhdGVkIGNoYXJ0IGZyb20gdGhlIGNoYXJ0IGNhY2hlIChvclxuICogYSA0MDQgb25jZSB0aGUgMWggVFRMIGVsYXBzZWQpLiBUaGlzIHByb2Nlc3NvciByZW1vdmVzIHRoZVxuICogdGVtcHRhdGlvbiBieSBkZWxldGluZyBgY2hhcnRJZGAga2V5cyBmcm9tIGV2ZXJ5IGFzc2lzdGFudFxuICogbWVzc2FnZSdzIHRvb2wgcmVzdWx0cyBiZWZvcmUgdGhlIHByb21wdCBpcyBidWlsdC4gVGhlIGN1cnJlbnRcbiAqIHR1cm4ncyB0b29sIHJlc3VsdHMgZG9uJ3QgZXhpc3QgeWV0IGF0IGBwcm9jZXNzSW5wdXRgIHRpbWUsIHNvXG4gKiB0aGV5IHBhc3MgdGhyb3VnaCB1bm1vZGlmaWVkLlxuICpcbiAqIFRoZSBzdHJpcCBpcyByZWN1cnNpdmUgLSBhbnkgbmVzdGVkIGBjaGFydElkYCBmaWVsZCBpcyByZW1vdmVkLFxuICogcmVnYXJkbGVzcyBvZiB3aGljaCB0b29sIHByb2R1Y2VkIHRoZSByZXN1bHQuIFRoaXMgY292ZXJzXG4gKiBgcHJlcGFyZV9jaGFydGAgLyBgcmVuZGVyX2RhdGFgIHRvcC1sZXZlbCBjaGFydElkcyBhbmQgYW55XG4gKiBsZWdhY3kgYGRhdGFzZXRzW10uY2hhcnRJZGAgcGF5bG9hZHMgdW5pZm9ybWx5IHdpdGhvdXQgY291cGxpbmdcbiAqIHRvIHNwZWNpZmljIHRvb2wgaWRzLlxuICpcbiAqIFdpcmVkIG9udG8gZXZlcnkgYWdlbnQgYnkgZGVmYXVsdCB2aWEgYGJ1aWxkQWdlbnRzYDsgb3B0IG91dCB3aXRoXG4gKiBgTWFzdHJhUGx1Z2luQ29uZmlnLnN0cmlwU3RhbGVDaGFydHM6IGZhbHNlYC5cbiAqL1xuZXhwb3J0IGNvbnN0IHN0cmlwU3RhbGVDaGFydHNQcm9jZXNzb3I6IElucHV0UHJvY2Vzc29yID0ge1xuICBpZDogXCJzdHJpcC1zdGFsZS1jaGFydHNcIixcbiAgZGVzY3JpcHRpb246XG4gICAgXCJSZW1vdmVzIGNoYXJ0SWQgZmllbGRzIGZyb20gcHJpb3IgdG9vbC1pbnZvY2F0aW9uIHJlc3VsdHMgc28gdGhlIG1vZGVsIGNhbid0IHJldXNlIHR1cm4tc2NvcGVkIGlkcyBmcm9tIG1lbW9yeS5cIixcbiAgcHJvY2Vzc0lucHV0KGFyZ3M6IFByb2Nlc3NJbnB1dEFyZ3MpIHtcbiAgICBsZXQgc3RyaXBwZWQgPSAwO1xuICAgIGZvciAoY29uc3QgbWVzc2FnZSBvZiBhcmdzLm1lc3NhZ2VzKSB7XG4gICAgICBpZiAobWVzc2FnZS5yb2xlICE9PSBcImFzc2lzdGFudFwiKSBjb250aW51ZTtcbiAgICAgIGNvbnN0IHBhcnRzID0gbWVzc2FnZS5jb250ZW50Py5wYXJ0cztcbiAgICAgIGlmICghQXJyYXkuaXNBcnJheShwYXJ0cykpIGNvbnRpbnVlO1xuICAgICAgZm9yIChjb25zdCBwYXJ0IG9mIHBhcnRzKSB7XG4gICAgICAgIC8vIFRvb2wtaW52b2NhdGlvbiBwYXJ0cyBob2xkIHRoZSBwZXJzaXN0ZWQgdG9vbCByZXN1bHQuXG4gICAgICAgIC8vIFdlIGRvbid0IHNjcnViIHRoZSBpbnB1dCBhcmdzIChgcmF3SW5wdXRgIC8gYGFyZ3NgKSBiZWNhdXNlXG4gICAgICAgIC8vIHRoZSBjaGFydElkIHRoZXJlIGlzIHRoZSBtb2RlbCdzIG91dGdvaW5nIGNsYWltLCBub3RcbiAgICAgICAgLy8gYW55dGhpbmcgaXQgY291bGQgcmUtcmVmZXJlbmNlOyBvbmx5IGByZXN1bHRgIGNhcnJpZXNcbiAgICAgICAgLy8gaWRzIHRoYXQgc3Vic2VxdWVudCB0dXJucyBtaWdodCBjb3B5LlxuICAgICAgICBpZiAoKHBhcnQgYXMgeyB0eXBlPzogdW5rbm93biB9KS50eXBlICE9PSBcInRvb2wtaW52b2NhdGlvblwiKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgaW52ID0gKHBhcnQgYXMgeyB0b29sSW52b2NhdGlvbj86IHsgcmVzdWx0PzogdW5rbm93biB9IH0pLnRvb2xJbnZvY2F0aW9uO1xuICAgICAgICBpZiAoIWludiB8fCBpbnYucmVzdWx0ID09PSB1bmRlZmluZWQpIGNvbnRpbnVlO1xuICAgICAgICBjb25zdCBiZWZvcmUgPSBpbnYucmVzdWx0O1xuICAgICAgICBjb25zdCBhZnRlciA9IHN0cmlwQ2hhcnRJZHMoYmVmb3JlKTtcbiAgICAgICAgLy8gQ2hlYXAgc3RydWN0dXJhbCBjaGVjayB2aWEgSlNPTiBsZW5ndGggLSB0aGUgYWN0dWFsXG4gICAgICAgIC8vIHN0cmlwIHdyaXRlcyBhIGZyZXNoIG9iamVjdCBvbmx5IHdoZW4gY2hhcnRJZCBrZXlzXG4gICAgICAgIC8vIGV4aXN0ZWQsIHNvIGRpZmZlcmVudCBzdHJpbmdpZmljYXRpb24gbGVuZ3RoIGlzIGFcbiAgICAgICAgLy8gcmVsaWFibGUgc2lnbmFsIHRoYXQgc29tZXRoaW5nIHdhcyByZW1vdmVkLlxuICAgICAgICBpZiAoXG4gICAgICAgICAgdHlwZW9mIGJlZm9yZSA9PT0gXCJvYmplY3RcIiAmJlxuICAgICAgICAgIGJlZm9yZSAhPT0gbnVsbCAmJlxuICAgICAgICAgIEpTT04uc3RyaW5naWZ5KGJlZm9yZSkubGVuZ3RoICE9PSBKU09OLnN0cmluZ2lmeShhZnRlcikubGVuZ3RoXG4gICAgICAgICkge1xuICAgICAgICAgIGludi5yZXN1bHQgPSBhZnRlcjtcbiAgICAgICAgICBzdHJpcHBlZCArPSAxO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChzdHJpcHBlZCA+IDApIHtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhcInN0cmlwcGVkXCIsIHsgcmVzdWx0czogc3RyaXBwZWQgfSk7XG4gICAgfVxuICAgIHJldHVybiBhcmdzLm1lc3NhZ2VzO1xuICB9LFxufTtcblxuLyoqXG4gKiBNYXN0cmEgb3V0cHV0IHByb2Nlc3NvciB0aGF0IHRyaW1zIHRoZSBidWxreSwgcmVkdW5kYW50IHBheWxvYWRcbiAqIGZpZWxkcyBvZmYgdGFyZ2V0ZWQgb3V0Ym91bmQgc3RyZWFtIGZyYW1lcy5cbiAqXG4gKiBNYXN0cmEgZW1pdHMgc3RlcCAvIGZpbmlzaCAvIHRvb2wtcmVzdWx0IGZyYW1lcyB3aG9zZSBwYXlsb2Fkc1xuICogZWNobyB0aGUgZnVsbCB0b29sIGBvdXRwdXRgIC8gYHJlc3VsdGAgLyBhc3Npc3RhbnQgYG1lc3NhZ2VzYCAvXG4gKiBgcmVzcG9uc2VgIC0gZGF0YSB0aGUgY2hhdCBjbGllbnQgYWxyZWFkeSByZWNlaXZlZCBpbmxpbmUgYW5kXG4gKiBkb2Vzbid0IG5lZWQgcmUtc2VudC4gVGhpcyBwcm9jZXNzb3IgZW1wdGllcyB0aG9zZSBrZXlzIG9uIHRoZVxuICogdGFyZ2V0ZWQgZnJhbWUgdHlwZXMgc28gdGhlIG91dGJvdW5kIFNTRSBzdHJlYW0gc3RheXMgbGVhbjtcbiAqIGV2ZXJ5IG90aGVyIGZyYW1lIHBhc3NlcyB0aHJvdWdoIHVudG91Y2hlZC5cbiAqL1xuZXhwb3J0IGNsYXNzIFJlc3VsdFByb2Nlc3NvciBpbXBsZW1lbnRzIFByb2Nlc3NvciB7XG4gIGlkID0gXCJyZXN1bHQtcHJvY2Vzc29yXCI7XG5cbiAgLy8gVGVsbCBNYXN0cmEgdG8gYWxzbyByb3V0ZSB0b29sL2RhdGEgcGFydHMgdG8gdGhpcyBwcm9jZXNzb3IgbWV0aG9kXG4gIHByb2Nlc3NEYXRhUGFydHMgPSB0cnVlO1xuXG4gIGFzeW5jIHByb2Nlc3NPdXRwdXRTdHJlYW0oeyBwYXJ0IH06IHsgcGFydDogYW55IH0pOiBQcm9taXNlPGFueSB8IG51bGw+IHtcbiAgICAvLyAxLiBHdWFyZCBjbGF1c2U6IEVuc3VyZSB0aGUgY2h1bmsgaXMgYSB2YWxpZCBvYmplY3RcbiAgICBpZiAoIXBhcnQgfHwgdHlwZW9mIHBhcnQgIT09IFwib2JqZWN0XCIpIHtcbiAgICAgIHJldHVybiBwYXJ0O1xuICAgIH1cblxuICAgIC8vIDIuIEZpbHRlciBmb3IgdGhlIHRhcmdldGVkIGZyYW1lIHR5cGVzXG4gICAgY29uc3QgdGFyZ2V0ZWRUeXBlcyA9IFtcInN0ZXAtZmluaXNoXCIsIFwiZmluaXNoXCIsIFwidG9vbC1yZXN1bHRcIiwgXCJkYXRhLXRvb2wtYWdlbnRcIl07XG4gICAgaWYgKCF0YXJnZXRlZFR5cGVzLmluY2x1ZGVzKHBhcnQudHlwZSkpIHtcbiAgICAgIHJldHVybiBwYXJ0OyAvLyBSZXR1cm4gdW5jaGFuZ2VkIHRvIHBhc3MtdGhyb3VnaFxuICAgIH1cblxuICAgIC8vIDMuIENoZWNrIGZvciB0aGUgcHJlc2VuY2Ugb2YgYSBwYXlsb2FkIG9iamVjdFxuICAgIGNvbnN0IHBheWxvYWQgPSBwYXJ0LnBheWxvYWQ7XG4gICAgaWYgKCFwYXlsb2FkIHx8IHR5cGVvZiBwYXlsb2FkICE9PSBcIm9iamVjdFwiKSB7XG4gICAgICByZXR1cm4gcGFydDtcbiAgICB9XG5cbiAgICAvLyA0LiBTYWZlbHkgZGVsZXRlIHRoZSB1bndhbnRlZCBrZXlzIGZyb20gdGhlIHBheWxvYWQgcmVmZXJlbmNlXG4gICAgY29uc3Qga2V5c1RvRGVsZXRlID0gW1wib3V0cHV0XCIsIFwibWVzc2FnZXNcIiwgXCJyZXNwb25zZVwiLCBcInJlc3VsdFwiXTtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzVG9EZWxldGUpIHtcbiAgICAgIGlmIChrZXkgaW4gcGF5bG9hZCkge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IHBheWxvYWRba2V5XTtcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICAgIHBheWxvYWRba2V5XSA9IHt9O1xuICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgICAgcGF5bG9hZFtrZXldID0gW107XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZGVsZXRlIHBheWxvYWRba2V5XTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIDUuIFJldHVybiB0aGUgbW9kaWZpZWQgcGFydCBvYmplY3QuIE1hc3RyYSBoYW5kbGVzIHJlLXNlcmlhbGl6YXRpb25cbiAgICAvLyBmb3IgdGhlIG91dGJvdW5kIFNTRSBjbGllbnQgc3RyZWFtIGF1dG9tYXRpY2FsbHkuXG4gICAgcmV0dXJuIHBhcnQ7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Minimal authenticated Databricks REST helper. Pulls the workspace
3
+ * host and a fresh bearer header off an OBO-scoped `WorkspaceClient`
4
+ * (`client.config.getHost()` + `authenticate()`), then issues a plain
5
+ * `fetch`. Used by modules that hit REST surfaces without a typed SDK
6
+ * method (e.g. the MLflow assessments API); returns the raw `Response`
7
+ * so callers decide how to treat status codes. Also carries the
8
+ * defensive `Response` body readers those callers share.
9
+ *
10
+ * @module
11
+ */
12
+ import { appkit } from "@dbx-tools/appkit";
13
+ /** Workspace client carried on an AppKit execution context. */
14
+ type WorkspaceClient = appkit.WorkspaceClientLike;
15
+ /** Request options for {@link databricksFetch}. */
16
+ export interface DatabricksFetchInit {
17
+ method: string;
18
+ /** JSON-serialized as the request body when present. */
19
+ body?: unknown;
20
+ /** Extra headers merged over the default `Content-Type: application/json`. */
21
+ headers?: Record<string, string>;
22
+ signal?: AbortSignal;
23
+ }
24
+ /**
25
+ * Resolve the workspace host + an authenticated header set off the
26
+ * client and issue a `fetch` against `path` (mounted on the host).
27
+ * Runs as whatever identity the client carries - the per-request OBO
28
+ * user when called from a request scope, the service principal
29
+ * otherwise.
30
+ */
31
+ export declare function databricksFetch(client: WorkspaceClient, path: string, init: DatabricksFetchInit): Promise<Response>;
32
+ /** Read a response body as text, swallowing read errors (returns `""`). */
33
+ export declare function readResponseText(res: Response): Promise<string>;
34
+ /** Parse a response body as JSON, returning `{}` on empty / invalid bodies. */
35
+ export declare function readResponseJson(res: Response): Promise<unknown>;
36
+ export {};
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Minimal authenticated Databricks REST helper. Pulls the workspace
3
+ * host and a fresh bearer header off an OBO-scoped `WorkspaceClient`
4
+ * (`client.config.getHost()` + `authenticate()`), then issues a plain
5
+ * `fetch`. Used by modules that hit REST surfaces without a typed SDK
6
+ * method (e.g. the MLflow assessments API); returns the raw `Response`
7
+ * so callers decide how to treat status codes. Also carries the
8
+ * defensive `Response` body readers those callers share.
9
+ *
10
+ * @module
11
+ */
12
+ import { json } from "@dbx-tools/shared-core";
13
+ /**
14
+ * Resolve the workspace host + an authenticated header set off the
15
+ * client and issue a `fetch` against `path` (mounted on the host).
16
+ * Runs as whatever identity the client carries - the per-request OBO
17
+ * user when called from a request scope, the service principal
18
+ * otherwise.
19
+ */
20
+ export async function databricksFetch(client, path, init) {
21
+ const host = (await client.config.getHost()).toString();
22
+ const headers = new Headers({ "Content-Type": "application/json", ...init.headers });
23
+ await client.config.authenticate(headers);
24
+ const url = new URL(path, host).toString();
25
+ return fetch(url, {
26
+ method: init.method,
27
+ headers,
28
+ ...(init.body !== undefined ? { body: JSON.stringify(init.body) } : {}),
29
+ ...(init.signal ? { signal: init.signal } : {}),
30
+ });
31
+ }
32
+ /** Read a response body as text, swallowing read errors (returns `""`). */
33
+ export async function readResponseText(res) {
34
+ try {
35
+ return await res.text();
36
+ }
37
+ catch {
38
+ return "";
39
+ }
40
+ }
41
+ /** Parse a response body as JSON, returning `{}` on empty / invalid bodies. */
42
+ export async function readResponseJson(res) {
43
+ const text = await readResponseText(res);
44
+ return json.parse(text, {});
45
+ }
46
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9yZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7O0dBVUc7QUFHSCxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFlOUM7Ozs7OztHQU1HO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxlQUFlLENBQ25DLE1BQXVCLEVBQ3ZCLElBQVksRUFDWixJQUF5QjtJQUV6QixNQUFNLElBQUksR0FBRyxDQUFDLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ3hELE1BQU0sT0FBTyxHQUFHLElBQUksT0FBTyxDQUFDLEVBQUUsY0FBYyxFQUFFLGtCQUFrQixFQUFFLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFDckYsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMxQyxNQUFNLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDM0MsT0FBTyxLQUFLLENBQUMsR0FBRyxFQUFFO1FBQ2hCLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTTtRQUNuQixPQUFPO1FBQ1AsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDdkUsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQ2hELENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCwyRUFBMkU7QUFDM0UsTUFBTSxDQUFDLEtBQUssVUFBVSxnQkFBZ0IsQ0FBQyxHQUFhO0lBQ2xELElBQUksQ0FBQztRQUNILE9BQU8sTUFBTSxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sRUFBRSxDQUFDO0lBQ1osQ0FBQztBQUNILENBQUM7QUFFRCwrRUFBK0U7QUFDL0UsTUFBTSxDQUFDLEtBQUssVUFBVSxnQkFBZ0IsQ0FBQyxHQUFhO0lBQ2xELE1BQU0sSUFBSSxHQUFHLE1BQU0sZ0JBQWdCLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDekMsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFVLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQztBQUN2QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBNaW5pbWFsIGF1dGhlbnRpY2F0ZWQgRGF0YWJyaWNrcyBSRVNUIGhlbHBlci4gUHVsbHMgdGhlIHdvcmtzcGFjZVxuICogaG9zdCBhbmQgYSBmcmVzaCBiZWFyZXIgaGVhZGVyIG9mZiBhbiBPQk8tc2NvcGVkIGBXb3Jrc3BhY2VDbGllbnRgXG4gKiAoYGNsaWVudC5jb25maWcuZ2V0SG9zdCgpYCArIGBhdXRoZW50aWNhdGUoKWApLCB0aGVuIGlzc3VlcyBhIHBsYWluXG4gKiBgZmV0Y2hgLiBVc2VkIGJ5IG1vZHVsZXMgdGhhdCBoaXQgUkVTVCBzdXJmYWNlcyB3aXRob3V0IGEgdHlwZWQgU0RLXG4gKiBtZXRob2QgKGUuZy4gdGhlIE1MZmxvdyBhc3Nlc3NtZW50cyBBUEkpOyByZXR1cm5zIHRoZSByYXcgYFJlc3BvbnNlYFxuICogc28gY2FsbGVycyBkZWNpZGUgaG93IHRvIHRyZWF0IHN0YXR1cyBjb2Rlcy4gQWxzbyBjYXJyaWVzIHRoZVxuICogZGVmZW5zaXZlIGBSZXNwb25zZWAgYm9keSByZWFkZXJzIHRob3NlIGNhbGxlcnMgc2hhcmUuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IGFwcGtpdCB9IGZyb20gXCJAZGJ4LXRvb2xzL2FwcGtpdFwiO1xuaW1wb3J0IHsganNvbiB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5cbi8qKiBXb3Jrc3BhY2UgY2xpZW50IGNhcnJpZWQgb24gYW4gQXBwS2l0IGV4ZWN1dGlvbiBjb250ZXh0LiAqL1xudHlwZSBXb3Jrc3BhY2VDbGllbnQgPSBhcHBraXQuV29ya3NwYWNlQ2xpZW50TGlrZTtcblxuLyoqIFJlcXVlc3Qgb3B0aW9ucyBmb3Ige0BsaW5rIGRhdGFicmlja3NGZXRjaH0uICovXG5leHBvcnQgaW50ZXJmYWNlIERhdGFicmlja3NGZXRjaEluaXQge1xuICBtZXRob2Q6IHN0cmluZztcbiAgLyoqIEpTT04tc2VyaWFsaXplZCBhcyB0aGUgcmVxdWVzdCBib2R5IHdoZW4gcHJlc2VudC4gKi9cbiAgYm9keT86IHVua25vd247XG4gIC8qKiBFeHRyYSBoZWFkZXJzIG1lcmdlZCBvdmVyIHRoZSBkZWZhdWx0IGBDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL2pzb25gLiAqL1xuICBoZWFkZXJzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbiAgc2lnbmFsPzogQWJvcnRTaWduYWw7XG59XG5cbi8qKlxuICogUmVzb2x2ZSB0aGUgd29ya3NwYWNlIGhvc3QgKyBhbiBhdXRoZW50aWNhdGVkIGhlYWRlciBzZXQgb2ZmIHRoZVxuICogY2xpZW50IGFuZCBpc3N1ZSBhIGBmZXRjaGAgYWdhaW5zdCBgcGF0aGAgKG1vdW50ZWQgb24gdGhlIGhvc3QpLlxuICogUnVucyBhcyB3aGF0ZXZlciBpZGVudGl0eSB0aGUgY2xpZW50IGNhcnJpZXMgLSB0aGUgcGVyLXJlcXVlc3QgT0JPXG4gKiB1c2VyIHdoZW4gY2FsbGVkIGZyb20gYSByZXF1ZXN0IHNjb3BlLCB0aGUgc2VydmljZSBwcmluY2lwYWxcbiAqIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRhdGFicmlja3NGZXRjaChcbiAgY2xpZW50OiBXb3Jrc3BhY2VDbGllbnQsXG4gIHBhdGg6IHN0cmluZyxcbiAgaW5pdDogRGF0YWJyaWNrc0ZldGNoSW5pdCxcbik6IFByb21pc2U8UmVzcG9uc2U+IHtcbiAgY29uc3QgaG9zdCA9IChhd2FpdCBjbGllbnQuY29uZmlnLmdldEhvc3QoKSkudG9TdHJpbmcoKTtcbiAgY29uc3QgaGVhZGVycyA9IG5ldyBIZWFkZXJzKHsgXCJDb250ZW50LVR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIsIC4uLmluaXQuaGVhZGVycyB9KTtcbiAgYXdhaXQgY2xpZW50LmNvbmZpZy5hdXRoZW50aWNhdGUoaGVhZGVycyk7XG4gIGNvbnN0IHVybCA9IG5ldyBVUkwocGF0aCwgaG9zdCkudG9TdHJpbmcoKTtcbiAgcmV0dXJuIGZldGNoKHVybCwge1xuICAgIG1ldGhvZDogaW5pdC5tZXRob2QsXG4gICAgaGVhZGVycyxcbiAgICAuLi4oaW5pdC5ib2R5ICE9PSB1bmRlZmluZWQgPyB7IGJvZHk6IEpTT04uc3RyaW5naWZ5KGluaXQuYm9keSkgfSA6IHt9KSxcbiAgICAuLi4oaW5pdC5zaWduYWwgPyB7IHNpZ25hbDogaW5pdC5zaWduYWwgfSA6IHt9KSxcbiAgfSk7XG59XG5cbi8qKiBSZWFkIGEgcmVzcG9uc2UgYm9keSBhcyB0ZXh0LCBzd2FsbG93aW5nIHJlYWQgZXJyb3JzIChyZXR1cm5zIGBcIlwiYCkuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZFJlc3BvbnNlVGV4dChyZXM6IFJlc3BvbnNlKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgcmVzLnRleHQoKTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIFwiXCI7XG4gIH1cbn1cblxuLyoqIFBhcnNlIGEgcmVzcG9uc2UgYm9keSBhcyBKU09OLCByZXR1cm5pbmcgYHt9YCBvbiBlbXB0eSAvIGludmFsaWQgYm9kaWVzLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRSZXNwb25zZUpzb24ocmVzOiBSZXNwb25zZSk6IFByb21pc2U8dW5rbm93bj4ge1xuICBjb25zdCB0ZXh0ID0gYXdhaXQgcmVhZFJlc3BvbnNlVGV4dChyZXMpO1xuICByZXR1cm4ganNvbi5wYXJzZTx1bmtub3duPih0ZXh0LCB7fSk7XG59XG4iXX0=
@@ -0,0 +1,155 @@
1
+ /**
2
+ * Express-layer plumbing for the Mastra plugin: a `MastraServer` that
3
+ * stamps the per-request `RequestContext`, and a route-patch middleware
4
+ * that lets the plugin's custom API routes (e.g. `historyRoute`) work
5
+ * behind an Express mount point.
6
+ *
7
+ * @module
8
+ */
9
+ import { RequestContext } from "@mastra/core/request-context";
10
+ import { MastraServer as MastraServerExpress } from "@mastra/express";
11
+ import type express from "express";
12
+ import { type MastraPluginConfig } from "./config.js";
13
+ /**
14
+ * Stamp the AppKit user (plus the resource id and trace metadata) onto
15
+ * `requestContext`.
16
+ *
17
+ * Split out of {@link MastraServer} because the HTTP middleware is not the only
18
+ * caller that needs it: an out-of-band turn (a Teams activity arriving on
19
+ * another plugin's route, a scheduled job) drives `agent.generate` directly, and
20
+ * without this stamp every user-scoped tool - `ask_genie` above all - fails with
21
+ * "invoke the tool from an agent turn served by the mastra plugin". Those
22
+ * callers build a context with {@link createRequestContext} instead of a
23
+ * request.
24
+ *
25
+ * Idempotent: returns immediately when the user and resource id are already
26
+ * present, so the middleware can call it over a context another layer stamped.
27
+ */
28
+ export declare function stampRequestContextUser(requestContext: RequestContext): Promise<void>;
29
+ /**
30
+ * Build the `RequestContext` a NON-HTTP agent turn needs.
31
+ *
32
+ * Everything Mastra's tools read off the context is stamped the same way the
33
+ * request middleware stamps it - the AppKit user (so `ask_genie` and the model
34
+ * resolver can mint user-scoped tokens), the memory thread / resource pair, and
35
+ * a request id so the turn's spans join up in traces. The result is passed as
36
+ * `requestContext` to `agent.generate` / `agent.stream`.
37
+ *
38
+ * This is what makes a card turn answer with the SAME data a chat turn does: the
39
+ * difference between the two endpoints is presentation, not capability.
40
+ */
41
+ export declare function createRequestContext(options?: {
42
+ threadId?: string;
43
+ resourceId?: string;
44
+ requestId?: string;
45
+ }): Promise<RequestContext>;
46
+ /**
47
+ * `@mastra/express` subclass that stamps `RequestContext` with the
48
+ * AppKit user, resource id, and a thread id backed by an HTTP-only
49
+ * session cookie (`appkit_<plugin-name>_session_id`).
50
+ */
51
+ export declare class MastraServer extends MastraServerExpress {
52
+ private config;
53
+ private log;
54
+ /**
55
+ * Whether to stamp the MLflow trace-id header on responses. Shares the
56
+ * plugin's feedback gate via {@link resolveFeedbackEnabled}.
57
+ */
58
+ private feedbackEnabled;
59
+ constructor(config: MastraPluginConfig, ...args: ConstructorParameters<typeof MastraServerExpress>);
60
+ registerAuthMiddleware(): void;
61
+ configureRequestContextUser(requestContext: RequestContext): Promise<void>;
62
+ /**
63
+ * Stamp a per-request id and echo it on the response so an upstream
64
+ * proxy / curl client / browser-side log line can pair its view of
65
+ * the request with the matching trace span. Reuses `X-Request-Id`
66
+ * when the upstream already supplies one so multi-hop traces stay
67
+ * joined; otherwise mints a UUIDv4.
68
+ *
69
+ * The id is surfaced as `mastra__requestId` span metadata via
70
+ * {@link TRACE_REQUEST_CONTEXT_KEYS} and as the `X-Request-Id`
71
+ * response header so dev tools can copy it from either side.
72
+ */
73
+ configureRequestContextRequestId(req: express.Request, res: express.Response, requestContext: RequestContext): void;
74
+ /**
75
+ * Stamp OAuth scopes from the forwarded access token on
76
+ * {@link MASTRA_SCOPES_KEY} for workspace mount gating.
77
+ */
78
+ configureRequestContextScopes(req: express.Request, requestContext: RequestContext): void;
79
+ /**
80
+ * Stamp the turn's MLflow trace id on the response so the chat client
81
+ * can attach thumbs / comment feedback to it later. MLflow derives
82
+ * its trace id from the OpenTelemetry trace id (`tr-<hex>`), and every
83
+ * Mastra span for this request inherits the ambient OTel context (see
84
+ * `observability.ts`), so the active span's trace id here is the id
85
+ * MLflow will record for the turn.
86
+ *
87
+ * No-op unless feedback is enabled, and when no live OTel span is
88
+ * active (e.g. the OTLP SDK isn't registered): in that case the header
89
+ * is simply absent and the client hides feedback for that message,
90
+ * degrading gracefully rather than emitting a bogus trace id.
91
+ */
92
+ configureMlflowTraceId(res: express.Response): void;
93
+ /**
94
+ * Resolve the thread id this request targets and pin it on
95
+ * `RequestContext` (consumed by the agent stream for persistence and
96
+ * by the history / threads routes). Resolution order:
97
+ *
98
+ * 1. A client-supplied thread id (the thread-selection header /
99
+ * `?threadId=` query). This is how the chat UI references a
100
+ * specific conversation among the many a user owns - it picks a
101
+ * thread id from the `/threads` listing (or mints one for a new
102
+ * conversation) and stamps it here. The id is scoped to the
103
+ * caller's resource by the recall / list routes, so a client
104
+ * can only ever read or write its own threads.
105
+ * 2. The per-session cookie (`appkit_<plugin-name>_session_id`),
106
+ * minted on first contact. This is the default single-thread
107
+ * fallback for clients that don't manage threads explicitly, so
108
+ * existing embeds keep one stable conversation per session with
109
+ * no client changes.
110
+ */
111
+ configureRequestContextThreadId(req: express.Request, res: express.Response, requestContext: RequestContext): void;
112
+ /**
113
+ * Read the client-selected thread id from the request, preferring
114
+ * the thread-selection header over the `?threadId=` query. Returns
115
+ * `null` when neither carries a non-empty value so the caller falls
116
+ * back to the session cookie.
117
+ */
118
+ private readRequestedThreadId;
119
+ configureRequestContextModelOverride(req: express.Request, requestContext: RequestContext): void;
120
+ }
121
+ /** Inputs for {@link isMastraRequestAllowed}. */
122
+ export interface MastraApiGateOptions {
123
+ /** `config.apiAccess`; `"full"` short-circuits to allow everything. */
124
+ access: "scoped" | "full";
125
+ /** Whether the MCP transport is mounted (so `/mcp/*` is legitimate). */
126
+ mcpEnabled: boolean;
127
+ }
128
+ /**
129
+ * Whether a request to the stock `@mastra/express` sub-app should be
130
+ * dispatched, given the configured {@link MastraApiGateOptions.access}.
131
+ *
132
+ * `path` is mount-relative (what the plugin's catch-all sees, e.g.
133
+ * `/agents/x/stream`, `/route/history/x`, `/mcp/...`). In `"scoped"`
134
+ * mode the allowlist is deliberately tight - the chat client only ever
135
+ * needs agent inference, read-only agent metadata, this plugin's own
136
+ * OBO/resource-scoped `/route/*` routes, and (when enabled) MCP - so the
137
+ * whole admin / mutating / bulk-export surface Mastra also exposes is
138
+ * denied by default rather than enumerated.
139
+ */
140
+ export declare function isMastraRequestAllowed(method: string, path: string, opts: MastraApiGateOptions): boolean;
141
+ /**
142
+ * Patches around `@mastra/express`'s custom-route dispatcher so the
143
+ * plugin's custom API routes (e.g. `historyRoute`) work when
144
+ * `MastraServer` is hosted on an Express subapp mounted under a parent
145
+ * path (e.g. `/api/mastra`).
146
+ *
147
+ * The adapter's `registerCustomApiRoutes` matches against `req.path`
148
+ * (mount-relative, correct) but dispatches to its internal Hono
149
+ * mini-app using `req.originalUrl`, which still contains the parent
150
+ * mount prefix. The Hono app registers the literal route paths
151
+ * (for example `/route/history`), so the absolute URL never matches
152
+ * until we overwrite `originalUrl` for `/route` and `/route/*` to the
153
+ * mount-relative path.
154
+ */
155
+ export declare function attachRoutePatchMiddleware(app: express.Express): void;