@dbx-tools/appkit-mastra 0.9.54 → 0.9.60

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/lib/src/mlflow.js CHANGED
@@ -20,8 +20,10 @@
20
20
  *
21
21
  * @module
22
22
  */
23
+ import { ConfigurationError } from "@databricks/appkit";
23
24
  import { asyncUtils, errorUtils, log } from "@dbx-tools/shared-core";
24
25
  import { feedback } from "@dbx-tools/shared-mastra";
26
+ import { z } from "zod";
25
27
  import { databricksFetch, readResponseJson, readResponseText } from "./rest.js";
26
28
  const logger = log.logger("mastra/mlflow");
27
29
  /** Assessments REST path for a trace. `3.0` is the current MLflow API version. */
@@ -30,6 +32,68 @@ const assessmentsPath = (traceId) => `/api/3.0/mlflow/traces/${encodeURIComponen
30
32
  const NOT_FOUND_RETRIES = 3;
31
33
  /** Base backoff between "trace not found" retries, in ms (grows linearly). */
32
34
  const NOT_FOUND_BACKOFF_MS = 1200;
35
+ const MlflowExperimentResponseSchema = z
36
+ .object({
37
+ experiment: z
38
+ .object({
39
+ experiment_id: z.string().min(1).describe("Workspace MLflow experiment identifier."),
40
+ })
41
+ .passthrough()
42
+ .describe("Configured MLflow experiment."),
43
+ })
44
+ .passthrough()
45
+ .describe("MLflow get-experiment response.");
46
+ const CurrentUserResponseSchema = z
47
+ .object({
48
+ userName: z.string().optional().describe("Current workspace user name."),
49
+ applicationId: z.string().optional().describe("Current service principal application id."),
50
+ displayName: z.string().optional().describe("Current principal display name."),
51
+ groups: z
52
+ .array(z
53
+ .object({
54
+ value: z.string().optional().describe("Workspace group identifier."),
55
+ display: z.string().optional().describe("Workspace group display name."),
56
+ })
57
+ .passthrough())
58
+ .optional()
59
+ .describe("Groups assigned to the current principal."),
60
+ })
61
+ .passthrough()
62
+ .describe("Databricks Current User API response.");
63
+ const ExperimentPermissionsResponseSchema = z
64
+ .object({
65
+ access_control_list: z
66
+ .array(z
67
+ .object({
68
+ user_name: z.string().optional().describe("User principal name."),
69
+ group_name: z.string().optional().describe("Group principal name."),
70
+ service_principal_name: z
71
+ .string()
72
+ .optional()
73
+ .describe("Service principal application id."),
74
+ all_permissions: z
75
+ .array(z
76
+ .object({
77
+ permission_level: z.string().describe("Effective experiment permission level."),
78
+ })
79
+ .passthrough())
80
+ .optional()
81
+ .describe("Direct and inherited permissions for this principal."),
82
+ })
83
+ .passthrough())
84
+ .optional()
85
+ .describe("Experiment access control entries."),
86
+ })
87
+ .passthrough()
88
+ .describe("Databricks experiment permissions response.");
89
+ function configuredExperiment() {
90
+ const id = process.env.MLFLOW_EXPERIMENT_ID?.trim();
91
+ const name = process.env.MLFLOW_EXPERIMENT_NAME?.trim();
92
+ return {
93
+ ...(id ? { id } : {}),
94
+ ...(name ? { name } : {}),
95
+ };
96
+ }
33
97
  /**
34
98
  * Whether MLflow feedback logging is available for this deployment.
35
99
  *
@@ -55,6 +119,75 @@ export function mlflowEnabled() {
55
119
  export function resolveFeedbackEnabled(explicit) {
56
120
  return explicit ?? mlflowEnabled();
57
121
  }
122
+ /**
123
+ * Reject an explicitly enabled feedback surface when no MLflow experiment is
124
+ * configured. Auto mode remains non-fatal and simply disables feedback.
125
+ */
126
+ export function validateFeedbackConfig(explicit) {
127
+ if (explicit !== true)
128
+ return;
129
+ const experiment = configuredExperiment();
130
+ if (experiment.id || experiment.name)
131
+ return;
132
+ throw new ConfigurationError("mastra: feedback is enabled but no MLflow experiment is configured. " +
133
+ "Set MLFLOW_EXPERIMENT_ID or MLFLOW_EXPERIMENT_NAME, use feedback: false, " +
134
+ "or omit feedback to use automatic detection.");
135
+ }
136
+ /**
137
+ * Return the configured experiment URL only when the active Databricks
138
+ * principal has effective `CAN_MANAGE` permission. Permission lookup is
139
+ * intentionally best-effort so Apps environments that do not expose the
140
+ * required APIs simply omit the debug affordance.
141
+ */
142
+ export async function mlflowExperimentManagerUrl(client) {
143
+ try {
144
+ return await resolveMlflowExperimentManagerUrl(client);
145
+ }
146
+ catch {
147
+ return undefined;
148
+ }
149
+ }
150
+ async function resolveMlflowExperimentManagerUrl(client) {
151
+ const experimentId = await resolveExperimentId(client);
152
+ if (!experimentId)
153
+ return undefined;
154
+ const [currentResponse, permissionsResponse] = await Promise.all([
155
+ databricksFetch(client, "/api/2.0/preview/scim/v2/Me", { method: "GET" }),
156
+ databricksFetch(client, `/api/2.0/permissions/experiments/${encodeURIComponent(experimentId)}`, { method: "GET" }),
157
+ ]);
158
+ if (!currentResponse.ok || !permissionsResponse.ok)
159
+ return undefined;
160
+ const current = CurrentUserResponseSchema.safeParse(await readResponseJson(currentResponse));
161
+ const permissions = ExperimentPermissionsResponseSchema.safeParse(await readResponseJson(permissionsResponse));
162
+ if (!current.success || !permissions.success)
163
+ return undefined;
164
+ const userNames = new Set([current.data.userName, current.data.applicationId, current.data.displayName].filter((value) => Boolean(value)));
165
+ const groupNames = new Set((current.data.groups ?? []).flatMap(({ value, display }) => [value, display].filter((entry) => Boolean(entry))));
166
+ const canManage = (permissions.data.access_control_list ?? []).some((entry) => {
167
+ const matches = (entry.user_name !== undefined && userNames.has(entry.user_name)) ||
168
+ (entry.service_principal_name !== undefined && userNames.has(entry.service_principal_name)) ||
169
+ (entry.group_name !== undefined && groupNames.has(entry.group_name));
170
+ return (matches &&
171
+ (entry.all_permissions ?? []).some((permission) => permission.permission_level === "CAN_MANAGE"));
172
+ });
173
+ if (!canManage)
174
+ return undefined;
175
+ const host = (await client.config.getHost()).toString();
176
+ return new URL(`/ml/experiments/${encodeURIComponent(experimentId)}`, host).toString();
177
+ }
178
+ async function resolveExperimentId(client) {
179
+ const experiment = configuredExperiment();
180
+ if (experiment.id)
181
+ return experiment.id;
182
+ if (!experiment.name)
183
+ return undefined;
184
+ const path = `/api/2.0/mlflow/experiments/get-by-name?experiment_name=${encodeURIComponent(experiment.name)}`;
185
+ const response = await databricksFetch(client, path, { method: "GET" });
186
+ if (!response.ok)
187
+ return undefined;
188
+ const parsed = MlflowExperimentResponseSchema.safeParse(await readResponseJson(response));
189
+ return parsed.success ? parsed.data.experiment.experiment_id : undefined;
190
+ }
58
191
  /**
59
192
  * Log a HUMAN feedback assessment to a trace. Returns the created
60
193
  * assessment id on success, or `undefined` when the trace can't be
@@ -116,4 +249,4 @@ export async function logFeedback(client, params) {
116
249
  }
117
250
  return undefined;
118
251
  }
119
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWxmbG93LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21sZmxvdy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBcUJHO0FBR0gsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDckUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxlQUFlLEVBQUUsZ0JBQWdCLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFaEYsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQztBQUszQyxrRkFBa0Y7QUFDbEYsTUFBTSxlQUFlLEdBQUcsQ0FBQyxPQUFlLEVBQVUsRUFBRSxDQUNsRCwwQkFBMEIsa0JBQWtCLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQztBQUV0RSw4RUFBOEU7QUFDOUUsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLENBQUM7QUFDNUIsOEVBQThFO0FBQzlFLE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxDQUFDO0FBRWxDOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxVQUFVLGFBQWE7SUFDM0IsTUFBTSxXQUFXLEdBQUcsT0FBTyxDQUN6QixPQUFPLENBQUMsR0FBRyxDQUFDLDJCQUEyQixFQUFFLElBQUksRUFBRTtRQUMvQyxPQUFPLENBQUMsR0FBRyxDQUFDLGtDQUFrQyxFQUFFLElBQUksRUFBRSxDQUN2RCxDQUFDO0lBQ0YsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUMzQixPQUFPLENBQUMsR0FBRyxDQUFDLG9CQUFvQixFQUFFLElBQUksRUFBRSxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0JBQXNCLEVBQUUsSUFBSSxFQUFFLENBQ3ZGLENBQUM7SUFDRixPQUFPLFdBQVcsSUFBSSxhQUFhLENBQUM7QUFDdEMsQ0FBQztBQUVE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QUN2QixNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU07WUFDbEIsSUFBSSxFQUFFLE1BQU0sZ0JBQWdCLENBQUMsR0FBRyxDQUFDO1NBQ2xDLENBQUMsQ0FBQztRQUNILE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFDRCxPQUFPLFNBQVMsQ0FBQztBQUNuQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBNTGZsb3cgdXNlci1mZWVkYmFjayBsb2dnaW5nOiBkZXRlY3Qgd2hldGhlciBNTGZsb3cgdHJhY2luZyBpcyB3aXJlZFxuICogZm9yIHRoaXMgZGVwbG95bWVudCwgYW5kIGxvZyBhIHRodW1icyAvIGNvbW1lbnQgYXMgYSB0cmFjZVxuICogKmFzc2Vzc21lbnQqIHZpYSB0aGUgRGF0YWJyaWNrcyBNTGZsb3cgUkVTVCBBUEkuXG4gKlxuICogRmVlZGJhY2sgYXR0YWNoZXMgdG8gYSB0cmFjZSwgYW5kIHRoZSBwbHVnaW4ncyBzcGFucyByZWFjaCBNTGZsb3dcbiAqIHRocm91Z2ggdGhlIHNhbWUgT1RlbCBwaXBlbGluZSBhcyBldmVyeSBvdGhlciBBcHBLaXQgc3BhbiAoc2VlXG4gKiBgb2JzZXJ2YWJpbGl0eS50c2ApLiBPbiBEYXRhYnJpY2tzIEFwcHMgdGhhdCBwaXBlbGluZSBpcyB0aGUgVUNcbiAqIHNpZGVjYXIgaW5qZWN0ZWQgYnkgYHRlbGVtZXRyeV9leHBvcnRfZGVzdGluYXRpb25zYCwgbm90IGEgZGlyZWN0XG4gKiB3b3Jrc3BhY2UgT1RMUCBVUkwuIE1MZmxvdyBkZXJpdmVzIGl0cyB0cmFjZSBpZCBmcm9tIHRoZSBPcGVuVGVsZW1ldHJ5XG4gKiB0cmFjZSBpZCAoYHRyLTxoZXgob3RlbFRyYWNlSWQpPmApLCBzbyB0aGUgc2VydmVyIHN0YW1wcyB0aGUgYWN0aXZlXG4gKiB0cmFjZSBpZCBvbiBlYWNoIHR1cm4ncyByZXNwb25zZSBhbmQgdGhlIGNsaWVudCBzZW5kcyBpdCBiYWNrIGhlcmUuXG4gKlxuICogVGhlcmUgaXMgbm8gTUxmbG93IEpTIFNESywgc28gdGhpcyBwb3N0cyB0byB0aGUgYXNzZXNzbWVudHMgUkVTVFxuICogZW5kcG9pbnQgZGlyZWN0bHkgdXNpbmcgdGhlIE9CTy1zY29wZWQgd29ya3NwYWNlIGNsaWVudCAodGhlIGZlZWRiYWNrXG4gKiBpcyB0aHVzIGF0dHJpYnV0ZWQgdG8gdGhlIHNpZ25lZC1pbiB1c2VyKS4gVHJhY2UgZXhwb3J0IGlzXG4gKiBhc3luY2hyb25vdXMsIHNvIHRoZSBqdXN0LWZpbmlzaGVkIHRyYWNlIG1heSBub3QgZXhpc3QgaW4gTUxmbG93IHlldFxuICogd2hlbiB0aGUgdXNlciByZWFjdHM7IHRoZSBsb2cgY2FsbCByZXRyaWVzIGJyaWVmbHkgb24gXCJub3QgZm91bmRcIlxuICogYmVmb3JlIGdpdmluZyB1cCBzb2Z0bHkuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IGFwcGtpdCB9IGZyb20gXCJAZGJ4LXRvb2xzL2FwcGtpdFwiO1xuaW1wb3J0IHsgYXN5bmNVdGlscywgZXJyb3JVdGlscywgbG9nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IGZlZWRiYWNrIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLW1hc3RyYVwiO1xuaW1wb3J0IHsgZGF0YWJyaWNrc0ZldGNoLCByZWFkUmVzcG9uc2VKc29uLCByZWFkUmVzcG9uc2VUZXh0IH0gZnJvbSBcIi4vcmVzdC50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwibWFzdHJhL21sZmxvd1wiKTtcblxuLyoqIFdvcmtzcGFjZSBjbGllbnQgY2FycmllZCBvbiBhbiBBcHBLaXQgZXhlY3V0aW9uIGNvbnRleHQuICovXG50eXBlIFdvcmtzcGFjZUNsaWVudCA9IGFwcGtpdC5Xb3Jrc3BhY2VDbGllbnRMaWtlO1xuXG4vKiogQXNzZXNzbWVudHMgUkVTVCBwYXRoIGZvciBhIHRyYWNlLiBgMy4wYCBpcyB0aGUgY3VycmVudCBNTGZsb3cgQVBJIHZlcnNpb24uICovXG5jb25zdCBhc3Nlc3NtZW50c1BhdGggPSAodHJhY2VJZDogc3RyaW5nKTogc3RyaW5nID0+XG4gIGAvYXBpLzMuMC9tbGZsb3cvdHJhY2VzLyR7ZW5jb2RlVVJJQ29tcG9uZW50KHRyYWNlSWQpfS9hc3Nlc3NtZW50c2A7XG5cbi8qKiBOdW1iZXIgb2YgdGltZXMgdG8gcmV0cnkgYSBcInRyYWNlIG5vdCBmb3VuZFwiIHJlc3BvbnNlIGJlZm9yZSBnaXZpbmcgdXAuICovXG5jb25zdCBOT1RfRk9VTkRfUkVUUklFUyA9IDM7XG4vKiogQmFzZSBiYWNrb2ZmIGJldHdlZW4gXCJ0cmFjZSBub3QgZm91bmRcIiByZXRyaWVzLCBpbiBtcyAoZ3Jvd3MgbGluZWFybHkpLiAqL1xuY29uc3QgTk9UX0ZPVU5EX0JBQ0tPRkZfTVMgPSAxMjAwO1xuXG4vKipcbiAqIFdoZXRoZXIgTUxmbG93IGZlZWRiYWNrIGxvZ2dpbmcgaXMgYXZhaWxhYmxlIGZvciB0aGlzIGRlcGxveW1lbnQuXG4gKlxuICogRW5hYmxlZCB3aGVuIGFuIE9UTFAgZXhwb3J0ZXIgZW5kcG9pbnQgaXMgY29uZmlndXJlZCAodHJhY2VzIGFyZVxuICogYWN0dWFsbHkgc2hpcHBlZCBzb21ld2hlcmUpIEFORCBhbiBNTGZsb3cgZXhwZXJpbWVudCBpcyBuYW1lZCAtIHRoZVxuICogdHdvIHNpZ25hbHMgdGhhdCB0aGUgT1RMUCBiYWNrZW5kIGlzIE1MZmxvdyBhbmQgdHJhY2VzIHdpbGxcbiAqIG1hdGVyaWFsaXplIHRoZXJlLiBCb3RoIGFyZSBzdGFuZGFyZCBlbnYgdmFycywgc28gbm8gcGx1Z2luIGNvbmZpZyBpc1xuICogcmVxdWlyZWQ7IGEgZGVwbG95bWVudCBvcHRzIGluIHNpbXBseSBieSB3aXJpbmcgTUxmbG93IHRyYWNpbmcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtbGZsb3dFbmFibGVkKCk6IGJvb2xlYW4ge1xuICBjb25zdCBoYXNFeHBvcnRlciA9IEJvb2xlYW4oXG4gICAgcHJvY2Vzcy5lbnYuT1RFTF9FWFBPUlRFUl9PVExQX0VORFBPSU5UPy50cmltKCkgfHxcbiAgICBwcm9jZXNzLmVudi5PVEVMX0VYUE9SVEVSX09UTFBfVFJBQ0VTX0VORFBPSU5UPy50cmltKCksXG4gICk7XG4gIGNvbnN0IGhhc0V4cGVyaW1lbnQgPSBCb29sZWFuKFxuICAgIHByb2Nlc3MuZW52Lk1MRkxPV19FWFBFUklNRU5UX0lEPy50cmltKCkgfHwgcHJvY2Vzcy5lbnYuTUxGTE9XX0VYUEVSSU1FTlRfTkFNRT8udHJpbSgpLFxuICApO1xuICByZXR1cm4gaGFzRXhwb3J0ZXIgJiYgaGFzRXhwZXJpbWVudDtcbn1cblxuLyoqXG4gKiBSZXNvbHZlIHdoZXRoZXIgdXNlciBmZWVkYmFjayBpcyBlbmFibGVkIGZyb20gdGhlIHBsdWdpbidzIG9wdGlvbmFsXG4gKiBgY29uZmlnLmZlZWRiYWNrYCBvdmVycmlkZTogdGhlIGV4cGxpY2l0IGJvb2xlYW4gd2lucywgb3RoZXJ3aXNlIGZhbGxcbiAqIGJhY2sgdG8gYXV0by1kZXRlY3RpbmcgTUxmbG93IHRyYWNpbmcgKHtAbGluayBtbGZsb3dFbmFibGVkfSkuIFNoYXJlZFxuICogYnkgdGhlIHBsdWdpbidzIGNsaWVudC1jb25maWcgZ2F0ZSBhbmQgdGhlIHNlcnZlcidzIHRyYWNlLWlkIGhlYWRlciBzb1xuICogdGhlIHR3byBuZXZlciBkaXNhZ3JlZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVGZWVkYmFja0VuYWJsZWQoZXhwbGljaXQ6IGJvb2xlYW4gfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgcmV0dXJuIGV4cGxpY2l0ID8/IG1sZmxvd0VuYWJsZWQoKTtcbn1cblxuLyoqIFBhcmFtZXRlcnMgZm9yIHtAbGluayBsb2dGZWVkYmFja30uICovXG5leHBvcnQgaW50ZXJmYWNlIExvZ0ZlZWRiYWNrUGFyYW1zIHtcbiAgLyoqIE1MZmxvdyB0cmFjZSBpZCB0aGUgYXNzZXNzbWVudCBhdHRhY2hlcyB0byAoYHRyLTxoZXg+YCkuICovXG4gIHRyYWNlSWQ6IHN0cmluZztcbiAgLyoqIEFzc2Vzc21lbnQgbmFtZTsgZGVmYXVsdHMgcGVyIHdoZXRoZXIgYSB2YWx1ZSBvciBhIGNvbW1lbnQgaXMgc2VudC4gKi9cbiAgbmFtZT86IHN0cmluZztcbiAgLyoqIFRodW1icyAvIHJhdGluZyAvIGxhYmVsIHZhbHVlLiBPbWl0IGZvciBhIGNvbW1lbnQtb25seSBzdWJtaXNzaW9uLiAqL1xuICB2YWx1ZT86IGJvb2xlYW4gfCBudW1iZXIgfCBzdHJpbmc7XG4gIC8qKiBGcmVlZm9ybSBjb21tZW50OiB0aGUgcmF0aW9uYWxlIGFsb25nc2lkZSBhIHZhbHVlLCBvciB0aGUgdmFsdWUgaXRzZWxmIHdoZW4gbm9uZS4gKi9cbiAgY29tbWVudD86IHN0cmluZztcbiAgLyoqIElkZW50aXR5IHRoZSBmZWVkYmFjayBpcyBhdHRyaWJ1dGVkIHRvICh1c2VyIGVtYWlsIC8gaWQpLiAqL1xuICBzb3VyY2VJZD86IHN0cmluZztcbn1cblxuLyoqXG4gKiBMb2cgYSBIVU1BTiBmZWVkYmFjayBhc3Nlc3NtZW50IHRvIGEgdHJhY2UuIFJldHVybnMgdGhlIGNyZWF0ZWRcbiAqIGFzc2Vzc21lbnQgaWQgb24gc3VjY2Vzcywgb3IgYHVuZGVmaW5lZGAgd2hlbiB0aGUgdHJhY2UgY2FuJ3QgYmVcbiAqIGZvdW5kIChldmVuIGFmdGVyIHJldHJ5aW5nIGZvciBleHBvcnQgbGFnKSBvciB0aGUgcmVxdWVzdCBvdGhlcndpc2VcbiAqIGZhaWxzIC0gY2FsbGVycyBzdXJmYWNlIHRoYXQgYXMgYSBzb2Z0IFwibm90IHJlY29yZGVkXCIgcmF0aGVyIHRoYW4gYW5cbiAqIGVycm9yLCBrZWVwaW5nIHRoZSBjaGF0IHVzYWJsZS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxvZ0ZlZWRiYWNrKFxuICBjbGllbnQ6IFdvcmtzcGFjZUNsaWVudCxcbiAgcGFyYW1zOiBMb2dGZWVkYmFja1BhcmFtcyxcbik6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiB7XG4gIC8vIEEgY29tbWVudCB3aXRoIG5vIHRodW1icyB2YWx1ZSBpcyBsb2dnZWQgYXMgdGV4dCBmZWVkYmFjazsgYSB2YWx1ZVxuICAvLyAod2l0aCBhbiBvcHRpb25hbCBjb21tZW50IGFzIHRoZSByYXRpb25hbGUpIGlzIHRoZSB0aHVtYnMgcGF0aC5cbiAgY29uc3QgaGFzVmFsdWUgPSBwYXJhbXMudmFsdWUgIT09IHVuZGVmaW5lZDtcbiAgY29uc3QgbmFtZSA9XG4gICAgcGFyYW1zLm5hbWU/LnRyaW0oKSB8fFxuICAgIChoYXNWYWx1ZSA/IGZlZWRiYWNrLkRFRkFVTFRfRkVFREJBQ0tfTkFNRSA6IGZlZWRiYWNrLkRFRkFVTFRfQ09NTUVOVF9OQU1FKTtcbiAgY29uc3QgdmFsdWUgPSBoYXNWYWx1ZSA/IHBhcmFtcy52YWx1ZSA6IHBhcmFtcy5jb21tZW50O1xuICBjb25zdCBhc3Nlc3NtZW50OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHtcbiAgICB0cmFjZV9pZDogcGFyYW1zLnRyYWNlSWQsXG4gICAgYXNzZXNzbWVudF9uYW1lOiBuYW1lLFxuICAgIHNvdXJjZToge1xuICAgICAgc291cmNlX3R5cGU6IFwiSFVNQU5cIixcbiAgICAgIHNvdXJjZV9pZDogcGFyYW1zLnNvdXJjZUlkPy50cmltKCkgfHwgXCJ1c2VyXCIsXG4gICAgfSxcbiAgICBmZWVkYmFjazogeyB2YWx1ZSB9LFxuICAgIC4uLihoYXNWYWx1ZSAmJiBwYXJhbXMuY29tbWVudD8udHJpbSgpID8geyByYXRpb25hbGU6IHBhcmFtcy5jb21tZW50IH0gOiB7fSksXG4gIH07XG4gIGNvbnN0IGJvZHkgPSB7IGFzc2Vzc21lbnQgfTtcblxuICBmb3IgKGxldCBhdHRlbXB0ID0gMDsgYXR0ZW1wdCA8PSBOT1RfRk9VTkRfUkVUUklFUzsgYXR0ZW1wdCsrKSB7XG4gICAgbGV0IHJlczogUmVzcG9uc2U7XG4gICAgdHJ5IHtcbiAgICAgIHJlcyA9IGF3YWl0IGRhdGFicmlja3NGZXRjaChjbGllbnQsIGFzc2Vzc21lbnRzUGF0aChwYXJhbXMudHJhY2VJZCksIHtcbiAgICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgICAgYm9keSxcbiAgICAgIH0pO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgbG9nZ2VyLndhcm4oXCJmZWVkYmFjayByZXF1ZXN0IGZhaWxlZFwiLCB7XG4gICAgICAgIHRyYWNlSWQ6IHBhcmFtcy50cmFjZUlkLFxuICAgICAgICBlcnJvcjogZXJyb3JVdGlscy5lcnJvck1lc3NhZ2UoZXJyKSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgaWYgKHJlcy5vaykge1xuICAgICAgY29uc3QgcGFyc2VkID0gYXdhaXQgcmVhZFJlc3BvbnNlSnNvbihyZXMpO1xuICAgICAgY29uc3QgYXNzZXNzbWVudElkID1cbiAgICAgICAgKHBhcnNlZCBhcyB7IGFzc2Vzc21lbnQ/OiB7IGFzc2Vzc21lbnRfaWQ/OiB1bmtub3duIH0gfSk/LmFzc2Vzc21lbnQ/LmFzc2Vzc21lbnRfaWQgPz9cbiAgICAgICAgKHBhcnNlZCBhcyB7IGFzc2Vzc21lbnRfaWQ/OiB1bmtub3duIH0pPy5hc3Nlc3NtZW50X2lkO1xuICAgICAgcmV0dXJuIHR5cGVvZiBhc3Nlc3NtZW50SWQgPT09IFwic3RyaW5nXCIgPyBhc3Nlc3NtZW50SWQgOiBcIlwiO1xuICAgIH1cbiAgICAvLyBUcmFjZSBleHBvcnQgaXMgYXN5bmM7IGEgZnJlc2ggdHJhY2UgbWF5IG5vdCBleGlzdCB5ZXQuIFJldHJ5IGFcbiAgICAvLyBmZXcgdGltZXMgd2l0aCBhIHNob3J0IGJhY2tvZmYgYmVmb3JlIGdpdmluZyB1cCBzb2Z0bHkuXG4gICAgaWYgKHJlcy5zdGF0dXMgPT09IDQwNCAmJiBhdHRlbXB0IDwgTk9UX0ZPVU5EX1JFVFJJRVMpIHtcbiAgICAgIGF3YWl0IGFzeW5jVXRpbHMuc2xlZXAoTk9UX0ZPVU5EX0JBQ0tPRkZfTVMgKiAoYXR0ZW1wdCArIDEpKTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBsb2dnZXIud2FybihcImZlZWRiYWNrIG5vdCByZWNvcmRlZFwiLCB7XG4gICAgICB0cmFjZUlkOiBwYXJhbXMudHJhY2VJZCxcbiAgICAgIHN0YXR1czogcmVzLnN0YXR1cyxcbiAgICAgIGJvZHk6IGF3YWl0IHJlYWRSZXNwb25zZVRleHQocmVzKSxcbiAgICB9KTtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG4iXX0=
252
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWxmbG93LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21sZmxvdy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBcUJHO0FBRUgsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFeEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDckUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxDQUFDLEVBQUUsTUFBTSxLQUFLLENBQUM7QUFDeEIsT0FBTyxFQUFFLGVBQWUsRUFBRSxnQkFBZ0IsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUVoRixNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDO0FBSzNDLGtGQUFrRjtBQUNsRixNQUFNLGVBQWUsR0FBRyxDQUFDLE9BQWUsRUFBVSxFQUFFLENBQ2xELDBCQUEwQixrQkFBa0IsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDO0FBRXRFLDhFQUE4RTtBQUM5RSxNQUFNLGlCQUFpQixHQUFHLENBQUMsQ0FBQztBQUM1Qiw4RUFBOEU7QUFDOUUsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLENBQUM7QUFFbEMsTUFBTSw4QkFBOEIsR0FBRyxDQUFDO0tBQ3JDLE1BQU0sQ0FBQztJQUNOLFVBQVUsRUFBRSxDQUFDO1NBQ1YsTUFBTSxDQUFDO1FBQ04sYUFBYSxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLHlDQUF5QyxDQUFDO0tBQ3JGLENBQUM7U0FDRCxXQUFXLEVBQUU7U0FDYixRQUFRLENBQUMsK0JBQStCLENBQUM7Q0FDN0MsQ0FBQztLQUNELFdBQVcsRUFBRTtLQUNiLFFBQVEsQ0FBQyxp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LEdBQUcsQ0FBQyxDQUFDO1lBQzNDLE1BQU0sWUFBWSxHQUNmLE1BQXVELEVBQUUsVUFBVSxFQUFFLGFBQWE7Z0JBQ2xGLE1BQXNDLEVBQUUsYUFBYSxDQUFDO1lBQ3pELE9BQU8sT0FBTyxZQUFZLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUM5RCxDQUFDO1FBQ0Qsa0VBQWtFO1FBQ2xFLDBEQUEwRDtRQUMxRCxJQUFJLEdBQUcsQ0FBQyxNQUFNLEtBQUssR0FBRyxJQUFJLE9BQU8sR0FBRyxpQkFBaUIsRUFBRSxDQUFDO1lBQ3RELE1BQU0sVUFBVSxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsR0FBRyxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzdELFNBQVM7UUFDWCxDQUFDO1FBQ0QsTUFBTSxDQUFDLElBQUksQ0FBQyx1QkFBdUIsRUFBRTtZQUNuQyxPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU87WUFDdkIsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNO1lBQ2xCLElBQUksRUFBRSxNQUFNLGdCQUFnQixDQUFDLEdBQUcsQ0FBQztTQUNsQyxDQUFDLENBQUM7UUFDSCxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBQ0QsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTUxmbG93IHVzZXItZmVlZGJhY2sgbG9nZ2luZzogZGV0ZWN0IHdoZXRoZXIgTUxmbG93IHRyYWNpbmcgaXMgd2lyZWRcbiAqIGZvciB0aGlzIGRlcGxveW1lbnQsIGFuZCBsb2cgYSB0aHVtYnMgLyBjb21tZW50IGFzIGEgdHJhY2VcbiAqICphc3Nlc3NtZW50KiB2aWEgdGhlIERhdGFicmlja3MgTUxmbG93IFJFU1QgQVBJLlxuICpcbiAqIEZlZWRiYWNrIGF0dGFjaGVzIHRvIGEgdHJhY2UsIGFuZCB0aGUgcGx1Z2luJ3Mgc3BhbnMgcmVhY2ggTUxmbG93XG4gKiB0aHJvdWdoIHRoZSBzYW1lIE9UZWwgcGlwZWxpbmUgYXMgZXZlcnkgb3RoZXIgQXBwS2l0IHNwYW4gKHNlZVxuICogYG9ic2VydmFiaWxpdHkudHNgKS4gT24gRGF0YWJyaWNrcyBBcHBzIHRoYXQgcGlwZWxpbmUgaXMgdGhlIFVDXG4gKiBzaWRlY2FyIGluamVjdGVkIGJ5IGB0ZWxlbWV0cnlfZXhwb3J0X2Rlc3RpbmF0aW9uc2AsIG5vdCBhIGRpcmVjdFxuICogd29ya3NwYWNlIE9UTFAgVVJMLiBNTGZsb3cgZGVyaXZlcyBpdHMgdHJhY2UgaWQgZnJvbSB0aGUgT3BlblRlbGVtZXRyeVxuICogdHJhY2UgaWQgKGB0ci08aGV4KG90ZWxUcmFjZUlkKT5gKSwgc28gdGhlIHNlcnZlciBzdGFtcHMgdGhlIGFjdGl2ZVxuICogdHJhY2UgaWQgb24gZWFjaCB0dXJuJ3MgcmVzcG9uc2UgYW5kIHRoZSBjbGllbnQgc2VuZHMgaXQgYmFjayBoZXJlLlxuICpcbiAqIFRoZXJlIGlzIG5vIE1MZmxvdyBKUyBTREssIHNvIHRoaXMgcG9zdHMgdG8gdGhlIGFzc2Vzc21lbnRzIFJFU1RcbiAqIGVuZHBvaW50IGRpcmVjdGx5IHVzaW5nIHRoZSBPQk8tc2NvcGVkIHdvcmtzcGFjZSBjbGllbnQgKHRoZSBmZWVkYmFja1xuICogaXMgdGh1cyBhdHRyaWJ1dGVkIHRvIHRoZSBzaWduZWQtaW4gdXNlcikuIFRyYWNlIGV4cG9ydCBpc1xuICogYXN5bmNocm9ub3VzLCBzbyB0aGUganVzdC1maW5pc2hlZCB0cmFjZSBtYXkgbm90IGV4aXN0IGluIE1MZmxvdyB5ZXRcbiAqIHdoZW4gdGhlIHVzZXIgcmVhY3RzOyB0aGUgbG9nIGNhbGwgcmV0cmllcyBicmllZmx5IG9uIFwibm90IGZvdW5kXCJcbiAqIGJlZm9yZSBnaXZpbmcgdXAgc29mdGx5LlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBDb25maWd1cmF0aW9uRXJyb3IgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyBhcHBraXQgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbmltcG9ydCB7IGFzeW5jVXRpbHMsIGVycm9yVXRpbHMsIGxvZyB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgeyBmZWVkYmFjayB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1tYXN0cmFcIjtcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5pbXBvcnQgeyBkYXRhYnJpY2tzRmV0Y2gsIHJlYWRSZXNwb25zZUpzb24sIHJlYWRSZXNwb25zZVRleHQgfSBmcm9tIFwiLi9yZXN0LnRzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJtYXN0cmEvbWxmbG93XCIpO1xuXG4vKiogV29ya3NwYWNlIGNsaWVudCBjYXJyaWVkIG9uIGFuIEFwcEtpdCBleGVjdXRpb24gY29udGV4dC4gKi9cbnR5cGUgV29ya3NwYWNlQ2xpZW50ID0gYXBwa2l0LldvcmtzcGFjZUNsaWVudExpa2U7XG5cbi8qKiBBc3Nlc3NtZW50cyBSRVNUIHBhdGggZm9yIGEgdHJhY2UuIGAzLjBgIGlzIHRoZSBjdXJyZW50IE1MZmxvdyBBUEkgdmVyc2lvbi4gKi9cbmNvbnN0IGFzc2Vzc21lbnRzUGF0aCA9ICh0cmFjZUlkOiBzdHJpbmcpOiBzdHJpbmcgPT5cbiAgYC9hcGkvMy4wL21sZmxvdy90cmFjZXMvJHtlbmNvZGVVUklDb21wb25lbnQodHJhY2VJZCl9L2Fzc2Vzc21lbnRzYDtcblxuLyoqIE51bWJlciBvZiB0aW1lcyB0byByZXRyeSBhIFwidHJhY2Ugbm90IGZvdW5kXCIgcmVzcG9uc2UgYmVmb3JlIGdpdmluZyB1cC4gKi9cbmNvbnN0IE5PVF9GT1VORF9SRVRSSUVTID0gMztcbi8qKiBCYXNlIGJhY2tvZmYgYmV0d2VlbiBcInRyYWNlIG5vdCBmb3VuZFwiIHJldHJpZXMsIGluIG1zIChncm93cyBsaW5lYXJseSkuICovXG5jb25zdCBOT1RfRk9VTkRfQkFDS09GRl9NUyA9IDEyMDA7XG5cbmNvbnN0IE1sZmxvd0V4cGVyaW1lbnRSZXNwb25zZVNjaGVtYSA9IHpcbiAgLm9iamVjdCh7XG4gICAgZXhwZXJpbWVudDogelxuICAgICAgLm9iamVjdCh7XG4gICAgICAgIGV4cGVyaW1lbnRfaWQ6IHouc3RyaW5nKCkubWluKDEpLmRlc2NyaWJlKFwiV29ya3NwYWNlIE1MZmxvdyBleHBlcmltZW50IGlkZW50aWZpZXIuXCIpLFxuICAgICAgfSlcbiAgICAgIC5wYXNzdGhyb3VnaCgpXG4gICAgICAuZGVzY3JpYmUoXCJDb25maWd1cmVkIE1MZmxvdyBleHBlcmltZW50LlwiKSxcbiAgfSlcbiAgLnBhc3N0aHJvdWdoKClcbiAgLmRlc2NyaWJlKFwiTUxmbG93IGdldC1leHBlcmltZW50IHJlc3BvbnNlLlwiKTtcblxuY29uc3QgQ3VycmVudFVzZXJSZXNwb25zZVNjaGVtYSA9IHpcbiAgLm9iamVjdCh7XG4gICAgdXNlck5hbWU6IHouc3RyaW5nKCkub3B0aW9uYWwoKS5kZXNjcmliZShcIkN1cnJlbnQgd29ya3NwYWNlIHVzZXIgbmFtZS5cIiksXG4gICAgYXBwbGljYXRpb25JZDogei5zdHJpbmcoKS5vcHRpb25hbCgpLmRlc2NyaWJlKFwiQ3VycmVudCBzZXJ2aWNlIHByaW5jaXBhbCBhcHBsaWNhdGlvbiBpZC5cIiksXG4gICAgZGlzcGxheU5hbWU6IHouc3RyaW5nKCkub3B0aW9uYWwoKS5kZXNjcmliZShcIkN1cnJlbnQgcHJpbmNpcGFsIGRpc3BsYXkgbmFtZS5cIiksXG4gICAgZ3JvdXBzOiB6XG4gICAgICAuYXJyYXkoXG4gICAgICAgIHpcbiAgICAgICAgICAub2JqZWN0KHtcbiAgICAgICAgICAgIHZhbHVlOiB6LnN0cmluZygpLm9wdGlvbmFsKCkuZGVzY3JpYmUoXCJXb3Jrc3BhY2UgZ3JvdXAgaWRlbnRpZmllci5cIiksXG4gICAgICAgICAgICBkaXNwbGF5OiB6LnN0cmluZygpLm9wdGlvbmFsKCkuZGVzY3JpYmUoXCJXb3Jrc3BhY2UgZ3JvdXAgZGlzcGxheSBuYW1lLlwiKSxcbiAgICAgICAgICB9KVxuICAgICAgICAgIC5wYXNzdGhyb3VnaCgpLFxuICAgICAgKVxuICAgICAgLm9wdGlvbmFsKClcbiAgICAgIC5kZXNjcmliZShcIkdyb3VwcyBhc3NpZ25lZCB0byB0aGUgY3VycmVudCBwcmluY2lwYWwuXCIpLFxuICB9KVxuICAucGFzc3Rocm91Z2goKVxuICAuZGVzY3JpYmUoXCJEYXRhYnJpY2tzIEN1cnJlbnQgVXNlciBBUEkgcmVzcG9uc2UuXCIpO1xuXG5jb25zdCBFeHBlcmltZW50UGVybWlzc2lvbnNSZXNwb25zZVNjaGVtYSA9IHpcbiAgLm9iamVjdCh7XG4gICAgYWNjZXNzX2NvbnRyb2xfbGlzdDogelxuICAgICAgLmFycmF5KFxuICAgICAgICB6XG4gICAgICAgICAgLm9iamVjdCh7XG4gICAgICAgICAgICB1c2VyX25hbWU6IHouc3RyaW5nKCkub3B0aW9uYWwoKS5kZXNjcmliZShcIlVzZXIgcHJpbmNpcGFsIG5hbWUuXCIpLFxuICAgICAgICAgICAgZ3JvdXBfbmFtZTogei5zdHJpbmcoKS5vcHRpb25hbCgpLmRlc2NyaWJlKFwiR3JvdXAgcHJpbmNpcGFsIG5hbWUuXCIpLFxuICAgICAgICAgICAgc2VydmljZV9wcmluY2lwYWxfbmFtZTogelxuICAgICAgICAgICAgICAuc3RyaW5nKClcbiAgICAgICAgICAgICAgLm9wdGlvbmFsKClcbiAgICAgICAgICAgICAgLmRlc2NyaWJlKFwiU2VydmljZSBwcmluY2lwYWwgYXBwbGljYXRpb24gaWQuXCIpLFxuICAgICAgICAgICAgYWxsX3Blcm1pc3Npb25zOiB6XG4gICAgICAgICAgICAgIC5hcnJheShcbiAgICAgICAgICAgICAgICB6XG4gICAgICAgICAgICAgICAgICAub2JqZWN0KHtcbiAgICAgICAgICAgICAgICAgICAgcGVybWlzc2lvbl9sZXZlbDogei5zdHJpbmcoKS5kZXNjcmliZShcIkVmZmVjdGl2ZSBleHBlcmltZW50IHBlcm1pc3Npb24gbGV2ZWwuXCIpLFxuICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgIC5wYXNzdGhyb3VnaCgpLFxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgIC5vcHRpb25hbCgpXG4gICAgICAgICAgICAgIC5kZXNjcmliZShcIkRpcmVjdCBhbmQgaW5oZXJpdGVkIHBlcm1pc3Npb25zIGZvciB0aGlzIHByaW5jaXBhbC5cIiksXG4gICAgICAgICAgfSlcbiAgICAgICAgICAucGFzc3Rocm91Z2goKSxcbiAgICAgIClcbiAgICAgIC5vcHRpb25hbCgpXG4gICAgICAuZGVzY3JpYmUoXCJFeHBlcmltZW50IGFjY2VzcyBjb250cm9sIGVudHJpZXMuXCIpLFxuICB9KVxuICAucGFzc3Rocm91Z2goKVxuICAuZGVzY3JpYmUoXCJEYXRhYnJpY2tzIGV4cGVyaW1lbnQgcGVybWlzc2lvbnMgcmVzcG9uc2UuXCIpO1xuXG5mdW5jdGlvbiBjb25maWd1cmVkRXhwZXJpbWVudCgpOiB7IGlkPzogc3RyaW5nOyBuYW1lPzogc3RyaW5nIH0ge1xuICBjb25zdCBpZCA9IHByb2Nlc3MuZW52Lk1MRkxPV19FWFBFUklNRU5UX0lEPy50cmltKCk7XG4gIGNvbnN0IG5hbWUgPSBwcm9jZXNzLmVudi5NTEZMT1dfRVhQRVJJTUVOVF9OQU1FPy50cmltKCk7XG4gIHJldHVybiB7XG4gICAgLi4uKGlkID8geyBpZCB9IDoge30pLFxuICAgIC4uLihuYW1lID8geyBuYW1lIH0gOiB7fSksXG4gIH07XG59XG5cbi8qKlxuICogV2hldGhlciBNTGZsb3cgZmVlZGJhY2sgbG9nZ2luZyBpcyBhdmFpbGFibGUgZm9yIHRoaXMgZGVwbG95bWVudC5cbiAqXG4gKiBFbmFibGVkIHdoZW4gYW4gT1RMUCBleHBvcnRlciBlbmRwb2ludCBpcyBjb25maWd1cmVkICh0cmFjZXMgYXJlXG4gKiBhY3R1YWxseSBzaGlwcGVkIHNvbWV3aGVyZSkgQU5EIGFuIE1MZmxvdyBleHBlcmltZW50IGlzIG5hbWVkIC0gdGhlXG4gKiB0d28gc2lnbmFscyB0aGF0IHRoZSBPVExQIGJhY2tlbmQgaXMgTUxmbG93IGFuZCB0cmFjZXMgd2lsbFxuICogbWF0ZXJpYWxpemUgdGhlcmUuIEJvdGggYXJlIHN0YW5kYXJkIGVudiB2YXJzLCBzbyBubyBwbHVnaW4gY29uZmlnIGlzXG4gKiByZXF1aXJlZDsgYSBkZXBsb3ltZW50IG9wdHMgaW4gc2ltcGx5IGJ5IHdpcmluZyBNTGZsb3cgdHJhY2luZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1sZmxvd0VuYWJsZWQoKTogYm9vbGVhbiB7XG4gIGNvbnN0IGhhc0V4cG9ydGVyID0gQm9vbGVhbihcbiAgICBwcm9jZXNzLmVudi5PVEVMX0VYUE9SVEVSX09UTFBfRU5EUE9JTlQ/LnRyaW0oKSB8fFxuICAgIHByb2Nlc3MuZW52Lk9URUxfRVhQT1JURVJfT1RMUF9UUkFDRVNfRU5EUE9JTlQ/LnRyaW0oKSxcbiAgKTtcbiAgY29uc3QgaGFzRXhwZXJpbWVudCA9IEJvb2xlYW4oXG4gICAgcHJvY2Vzcy5lbnYuTUxGTE9XX0VYUEVSSU1FTlRfSUQ/LnRyaW0oKSB8fCBwcm9jZXNzLmVudi5NTEZMT1dfRVhQRVJJTUVOVF9OQU1FPy50cmltKCksXG4gICk7XG4gIHJldHVybiBoYXNFeHBvcnRlciAmJiBoYXNFeHBlcmltZW50O1xufVxuXG4vKipcbiAqIFJlc29sdmUgd2hldGhlciB1c2VyIGZlZWRiYWNrIGlzIGVuYWJsZWQgZnJvbSB0aGUgcGx1Z2luJ3Mgb3B0aW9uYWxcbiAqIGBjb25maWcuZmVlZGJhY2tgIG92ZXJyaWRlOiB0aGUgZXhwbGljaXQgYm9vbGVhbiB3aW5zLCBvdGhlcndpc2UgZmFsbFxuICogYmFjayB0byBhdXRvLWRldGVjdGluZyBNTGZsb3cgdHJhY2luZyAoe0BsaW5rIG1sZmxvd0VuYWJsZWR9KS4gU2hhcmVkXG4gKiBieSB0aGUgcGx1Z2luJ3MgY2xpZW50LWNvbmZpZyBnYXRlIGFuZCB0aGUgc2VydmVyJ3MgdHJhY2UtaWQgaGVhZGVyIHNvXG4gKiB0aGUgdHdvIG5ldmVyIGRpc2FncmVlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZUZlZWRiYWNrRW5hYmxlZChleHBsaWNpdDogYm9vbGVhbiB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuICByZXR1cm4gZXhwbGljaXQgPz8gbWxmbG93RW5hYmxlZCgpO1xufVxuXG4vKipcbiAqIFJlamVjdCBhbiBleHBsaWNpdGx5IGVuYWJsZWQgZmVlZGJhY2sgc3VyZmFjZSB3aGVuIG5vIE1MZmxvdyBleHBlcmltZW50IGlzXG4gKiBjb25maWd1cmVkLiBBdXRvIG1vZGUgcmVtYWlucyBub24tZmF0YWwgYW5kIHNpbXBseSBkaXNhYmxlcyBmZWVkYmFjay5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlRmVlZGJhY2tDb25maWcoZXhwbGljaXQ6IGJvb2xlYW4gfCB1bmRlZmluZWQpOiB2b2lkIHtcbiAgaWYgKGV4cGxpY2l0ICE9PSB0cnVlKSByZXR1cm47XG4gIGNvbnN0IGV4cGVyaW1lbnQgPSBjb25maWd1cmVkRXhwZXJpbWVudCgpO1xuICBpZiAoZXhwZXJpbWVudC5pZCB8fCBleHBlcmltZW50Lm5hbWUpIHJldHVybjtcbiAgdGhyb3cgbmV3IENvbmZpZ3VyYXRpb25FcnJvcihcbiAgICBcIm1hc3RyYTogZmVlZGJhY2sgaXMgZW5hYmxlZCBidXQgbm8gTUxmbG93IGV4cGVyaW1lbnQgaXMgY29uZmlndXJlZC4gXCIgK1xuICAgICAgXCJTZXQgTUxGTE9XX0VYUEVSSU1FTlRfSUQgb3IgTUxGTE9XX0VYUEVSSU1FTlRfTkFNRSwgdXNlIGZlZWRiYWNrOiBmYWxzZSwgXCIgK1xuICAgICAgXCJvciBvbWl0IGZlZWRiYWNrIHRvIHVzZSBhdXRvbWF0aWMgZGV0ZWN0aW9uLlwiLFxuICApO1xufVxuXG4vKipcbiAqIFJldHVybiB0aGUgY29uZmlndXJlZCBleHBlcmltZW50IFVSTCBvbmx5IHdoZW4gdGhlIGFjdGl2ZSBEYXRhYnJpY2tzXG4gKiBwcmluY2lwYWwgaGFzIGVmZmVjdGl2ZSBgQ0FOX01BTkFHRWAgcGVybWlzc2lvbi4gUGVybWlzc2lvbiBsb29rdXAgaXNcbiAqIGludGVudGlvbmFsbHkgYmVzdC1lZmZvcnQgc28gQXBwcyBlbnZpcm9ubWVudHMgdGhhdCBkbyBub3QgZXhwb3NlIHRoZVxuICogcmVxdWlyZWQgQVBJcyBzaW1wbHkgb21pdCB0aGUgZGVidWcgYWZmb3JkYW5jZS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG1sZmxvd0V4cGVyaW1lbnRNYW5hZ2VyVXJsKFxuICBjbGllbnQ6IFdvcmtzcGFjZUNsaWVudCxcbik6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IHJlc29sdmVNbGZsb3dFeHBlcmltZW50TWFuYWdlclVybChjbGllbnQpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVNbGZsb3dFeHBlcmltZW50TWFuYWdlclVybChcbiAgY2xpZW50OiBXb3Jrc3BhY2VDbGllbnQsXG4pOiBQcm9taXNlPHN0cmluZyB8IHVuZGVmaW5lZD4ge1xuICBjb25zdCBleHBlcmltZW50SWQgPSBhd2FpdCByZXNvbHZlRXhwZXJpbWVudElkKGNsaWVudCk7XG4gIGlmICghZXhwZXJpbWVudElkKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gIGNvbnN0IFtjdXJyZW50UmVzcG9uc2UsIHBlcm1pc3Npb25zUmVzcG9uc2VdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgIGRhdGFicmlja3NGZXRjaChjbGllbnQsIFwiL2FwaS8yLjAvcHJldmlldy9zY2ltL3YyL01lXCIsIHsgbWV0aG9kOiBcIkdFVFwiIH0pLFxuICAgIGRhdGFicmlja3NGZXRjaChcbiAgICAgIGNsaWVudCxcbiAgICAgIGAvYXBpLzIuMC9wZXJtaXNzaW9ucy9leHBlcmltZW50cy8ke2VuY29kZVVSSUNvbXBvbmVudChleHBlcmltZW50SWQpfWAsXG4gICAgICB7IG1ldGhvZDogXCJHRVRcIiB9LFxuICAgICksXG4gIF0pO1xuICBpZiAoIWN1cnJlbnRSZXNwb25zZS5vayB8fCAhcGVybWlzc2lvbnNSZXNwb25zZS5vaykgcmV0dXJuIHVuZGVmaW5lZDtcblxuICBjb25zdCBjdXJyZW50ID0gQ3VycmVudFVzZXJSZXNwb25zZVNjaGVtYS5zYWZlUGFyc2UoYXdhaXQgcmVhZFJlc3BvbnNlSnNvbihjdXJyZW50UmVzcG9uc2UpKTtcbiAgY29uc3QgcGVybWlzc2lvbnMgPSBFeHBlcmltZW50UGVybWlzc2lvbnNSZXNwb25zZVNjaGVtYS5zYWZlUGFyc2UoXG4gICAgYXdhaXQgcmVhZFJlc3BvbnNlSnNvbihwZXJtaXNzaW9uc1Jlc3BvbnNlKSxcbiAgKTtcbiAgaWYgKCFjdXJyZW50LnN1Y2Nlc3MgfHwgIXBlcm1pc3Npb25zLnN1Y2Nlc3MpIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgY29uc3QgdXNlck5hbWVzID0gbmV3IFNldChcbiAgICBbY3VycmVudC5kYXRhLnVzZXJOYW1lLCBjdXJyZW50LmRhdGEuYXBwbGljYXRpb25JZCwgY3VycmVudC5kYXRhLmRpc3BsYXlOYW1lXS5maWx0ZXIoXG4gICAgICAodmFsdWUpOiB2YWx1ZSBpcyBzdHJpbmcgPT4gQm9vbGVhbih2YWx1ZSksXG4gICAgKSxcbiAgKTtcbiAgY29uc3QgZ3JvdXBOYW1lcyA9IG5ldyBTZXQoXG4gICAgKGN1cnJlbnQuZGF0YS5ncm91cHMgPz8gW10pLmZsYXRNYXAoKHsgdmFsdWUsIGRpc3BsYXkgfSkgPT5cbiAgICAgIFt2YWx1ZSwgZGlzcGxheV0uZmlsdGVyKChlbnRyeSk6IGVudHJ5IGlzIHN0cmluZyA9PiBCb29sZWFuKGVudHJ5KSksXG4gICAgKSxcbiAgKTtcbiAgY29uc3QgY2FuTWFuYWdlID0gKHBlcm1pc3Npb25zLmRhdGEuYWNjZXNzX2NvbnRyb2xfbGlzdCA/PyBbXSkuc29tZSgoZW50cnkpID0+IHtcbiAgICBjb25zdCBtYXRjaGVzID1cbiAgICAgIChlbnRyeS51c2VyX25hbWUgIT09IHVuZGVmaW5lZCAmJiB1c2VyTmFtZXMuaGFzKGVudHJ5LnVzZXJfbmFtZSkpIHx8XG4gICAgICAoZW50cnkuc2VydmljZV9wcmluY2lwYWxfbmFtZSAhPT0gdW5kZWZpbmVkICYmIHVzZXJOYW1lcy5oYXMoZW50cnkuc2VydmljZV9wcmluY2lwYWxfbmFtZSkpIHx8XG4gICAgICAoZW50cnkuZ3JvdXBfbmFtZSAhPT0gdW5kZWZpbmVkICYmIGdyb3VwTmFtZXMuaGFzKGVudHJ5Lmdyb3VwX25hbWUpKTtcbiAgICByZXR1cm4gKFxuICAgICAgbWF0Y2hlcyAmJlxuICAgICAgKGVudHJ5LmFsbF9wZXJtaXNzaW9ucyA/PyBbXSkuc29tZShcbiAgICAgICAgKHBlcm1pc3Npb24pID0+IHBlcm1pc3Npb24ucGVybWlzc2lvbl9sZXZlbCA9PT0gXCJDQU5fTUFOQUdFXCIsXG4gICAgICApXG4gICAgKTtcbiAgfSk7XG4gIGlmICghY2FuTWFuYWdlKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gIGNvbnN0IGhvc3QgPSAoYXdhaXQgY2xpZW50LmNvbmZpZy5nZXRIb3N0KCkpLnRvU3RyaW5nKCk7XG4gIHJldHVybiBuZXcgVVJMKGAvbWwvZXhwZXJpbWVudHMvJHtlbmNvZGVVUklDb21wb25lbnQoZXhwZXJpbWVudElkKX1gLCBob3N0KS50b1N0cmluZygpO1xufVxuXG5hc3luYyBmdW5jdGlvbiByZXNvbHZlRXhwZXJpbWVudElkKGNsaWVudDogV29ya3NwYWNlQ2xpZW50KTogUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+IHtcbiAgY29uc3QgZXhwZXJpbWVudCA9IGNvbmZpZ3VyZWRFeHBlcmltZW50KCk7XG4gIGlmIChleHBlcmltZW50LmlkKSByZXR1cm4gZXhwZXJpbWVudC5pZDtcbiAgaWYgKCFleHBlcmltZW50Lm5hbWUpIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgY29uc3QgcGF0aCA9IGAvYXBpLzIuMC9tbGZsb3cvZXhwZXJpbWVudHMvZ2V0LWJ5LW5hbWU/ZXhwZXJpbWVudF9uYW1lPSR7ZW5jb2RlVVJJQ29tcG9uZW50KFxuICAgIGV4cGVyaW1lbnQubmFtZSxcbiAgKX1gO1xuICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGRhdGFicmlja3NGZXRjaChjbGllbnQsIHBhdGgsIHsgbWV0aG9kOiBcIkdFVFwiIH0pO1xuICBpZiAoIXJlc3BvbnNlLm9rKSByZXR1cm4gdW5kZWZpbmVkO1xuICBjb25zdCBwYXJzZWQgPSBNbGZsb3dFeHBlcmltZW50UmVzcG9uc2VTY2hlbWEuc2FmZVBhcnNlKGF3YWl0IHJlYWRSZXNwb25zZUpzb24ocmVzcG9uc2UpKTtcbiAgcmV0dXJuIHBhcnNlZC5zdWNjZXNzID8gcGFyc2VkLmRhdGEuZXhwZXJpbWVudC5leHBlcmltZW50X2lkIDogdW5kZWZpbmVkO1xufVxuXG4vKiogUGFyYW1ldGVycyBmb3Ige0BsaW5rIGxvZ0ZlZWRiYWNrfS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTG9nRmVlZGJhY2tQYXJhbXMge1xuICAvKiogTUxmbG93IHRyYWNlIGlkIHRoZSBhc3Nlc3NtZW50IGF0dGFjaGVzIHRvIChgdHItPGhleD5gKS4gKi9cbiAgdHJhY2VJZDogc3RyaW5nO1xuICAvKiogQXNzZXNzbWVudCBuYW1lOyBkZWZhdWx0cyBwZXIgd2hldGhlciBhIHZhbHVlIG9yIGEgY29tbWVudCBpcyBzZW50LiAqL1xuICBuYW1lPzogc3RyaW5nO1xuICAvKiogVGh1bWJzIC8gcmF0aW5nIC8gbGFiZWwgdmFsdWUuIE9taXQgZm9yIGEgY29tbWVudC1vbmx5IHN1Ym1pc3Npb24uICovXG4gIHZhbHVlPzogYm9vbGVhbiB8IG51bWJlciB8IHN0cmluZztcbiAgLyoqIEZyZWVmb3JtIGNvbW1lbnQ6IHRoZSByYXRpb25hbGUgYWxvbmdzaWRlIGEgdmFsdWUsIG9yIHRoZSB2YWx1ZSBpdHNlbGYgd2hlbiBub25lLiAqL1xuICBjb21tZW50Pzogc3RyaW5nO1xuICAvKiogSWRlbnRpdHkgdGhlIGZlZWRiYWNrIGlzIGF0dHJpYnV0ZWQgdG8gKHVzZXIgZW1haWwgLyBpZCkuICovXG4gIHNvdXJjZUlkPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIExvZyBhIEhVTUFOIGZlZWRiYWNrIGFzc2Vzc21lbnQgdG8gYSB0cmFjZS4gUmV0dXJucyB0aGUgY3JlYXRlZFxuICogYXNzZXNzbWVudCBpZCBvbiBzdWNjZXNzLCBvciBgdW5kZWZpbmVkYCB3aGVuIHRoZSB0cmFjZSBjYW4ndCBiZVxuICogZm91bmQgKGV2ZW4gYWZ0ZXIgcmV0cnlpbmcgZm9yIGV4cG9ydCBsYWcpIG9yIHRoZSByZXF1ZXN0IG90aGVyd2lzZVxuICogZmFpbHMgLSBjYWxsZXJzIHN1cmZhY2UgdGhhdCBhcyBhIHNvZnQgXCJub3QgcmVjb3JkZWRcIiByYXRoZXIgdGhhbiBhblxuICogZXJyb3IsIGtlZXBpbmcgdGhlIGNoYXQgdXNhYmxlLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbG9nRmVlZGJhY2soXG4gIGNsaWVudDogV29ya3NwYWNlQ2xpZW50LFxuICBwYXJhbXM6IExvZ0ZlZWRiYWNrUGFyYW1zLFxuKTogUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+IHtcbiAgLy8gQSBjb21tZW50IHdpdGggbm8gdGh1bWJzIHZhbHVlIGlzIGxvZ2dlZCBhcyB0ZXh0IGZlZWRiYWNrOyBhIHZhbHVlXG4gIC8vICh3aXRoIGFuIG9wdGlvbmFsIGNvbW1lbnQgYXMgdGhlIHJhdGlvbmFsZSkgaXMgdGhlIHRodW1icyBwYXRoLlxuICBjb25zdCBoYXNWYWx1ZSA9IHBhcmFtcy52YWx1ZSAhPT0gdW5kZWZpbmVkO1xuICBjb25zdCBuYW1lID1cbiAgICBwYXJhbXMubmFtZT8udHJpbSgpIHx8XG4gICAgKGhhc1ZhbHVlID8gZmVlZGJhY2suREVGQVVMVF9GRUVEQkFDS19OQU1FIDogZmVlZGJhY2suREVGQVVMVF9DT01NRU5UX05BTUUpO1xuICBjb25zdCB2YWx1ZSA9IGhhc1ZhbHVlID8gcGFyYW1zLnZhbHVlIDogcGFyYW1zLmNvbW1lbnQ7XG4gIGNvbnN0IGFzc2Vzc21lbnQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge1xuICAgIHRyYWNlX2lkOiBwYXJhbXMudHJhY2VJZCxcbiAgICBhc3Nlc3NtZW50X25hbWU6IG5hbWUsXG4gICAgc291cmNlOiB7XG4gICAgICBzb3VyY2VfdHlwZTogXCJIVU1BTlwiLFxuICAgICAgc291cmNlX2lkOiBwYXJhbXMuc291cmNlSWQ/LnRyaW0oKSB8fCBcInVzZXJcIixcbiAgICB9LFxuICAgIGZlZWRiYWNrOiB7IHZhbHVlIH0sXG4gICAgLi4uKGhhc1ZhbHVlICYmIHBhcmFtcy5jb21tZW50Py50cmltKCkgPyB7IHJhdGlvbmFsZTogcGFyYW1zLmNvbW1lbnQgfSA6IHt9KSxcbiAgfTtcbiAgY29uc3QgYm9keSA9IHsgYXNzZXNzbWVudCB9O1xuXG4gIGZvciAobGV0IGF0dGVtcHQgPSAwOyBhdHRlbXB0IDw9IE5PVF9GT1VORF9SRVRSSUVTOyBhdHRlbXB0KyspIHtcbiAgICBsZXQgcmVzOiBSZXNwb25zZTtcbiAgICB0cnkge1xuICAgICAgcmVzID0gYXdhaXQgZGF0YWJyaWNrc0ZldGNoKGNsaWVudCwgYXNzZXNzbWVudHNQYXRoKHBhcmFtcy50cmFjZUlkKSwge1xuICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICBib2R5LFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBsb2dnZXIud2FybihcImZlZWRiYWNrIHJlcXVlc3QgZmFpbGVkXCIsIHtcbiAgICAgICAgdHJhY2VJZDogcGFyYW1zLnRyYWNlSWQsXG4gICAgICAgIGVycm9yOiBlcnJvclV0aWxzLmVycm9yTWVzc2FnZShlcnIpLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBpZiAocmVzLm9rKSB7XG4gICAgICBjb25zdCBwYXJzZWQgPSBhd2FpdCByZWFkUmVzcG9uc2VKc29uKHJlcyk7XG4gICAgICBjb25zdCBhc3Nlc3NtZW50SWQgPVxuICAgICAgICAocGFyc2VkIGFzIHsgYXNzZXNzbWVudD86IHsgYXNzZXNzbWVudF9pZD86IHVua25vd24gfSB9KT8uYXNzZXNzbWVudD8uYXNzZXNzbWVudF9pZCA/P1xuICAgICAgICAocGFyc2VkIGFzIHsgYXNzZXNzbWVudF9pZD86IHVua25vd24gfSk/LmFzc2Vzc21lbnRfaWQ7XG4gICAgICByZXR1cm4gdHlwZW9mIGFzc2Vzc21lbnRJZCA9PT0gXCJzdHJpbmdcIiA/IGFzc2Vzc21lbnRJZCA6IFwiXCI7XG4gICAgfVxuICAgIC8vIFRyYWNlIGV4cG9ydCBpcyBhc3luYzsgYSBmcmVzaCB0cmFjZSBtYXkgbm90IGV4aXN0IHlldC4gUmV0cnkgYVxuICAgIC8vIGZldyB0aW1lcyB3aXRoIGEgc2hvcnQgYmFja29mZiBiZWZvcmUgZ2l2aW5nIHVwIHNvZnRseS5cbiAgICBpZiAocmVzLnN0YXR1cyA9PT0gNDA0ICYmIGF0dGVtcHQgPCBOT1RfRk9VTkRfUkVUUklFUykge1xuICAgICAgYXdhaXQgYXN5bmNVdGlscy5zbGVlcChOT1RfRk9VTkRfQkFDS09GRl9NUyAqIChhdHRlbXB0ICsgMSkpO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGxvZ2dlci53YXJuKFwiZmVlZGJhY2sgbm90IHJlY29yZGVkXCIsIHtcbiAgICAgIHRyYWNlSWQ6IHBhcmFtcy50cmFjZUlkLFxuICAgICAgc3RhdHVzOiByZXMuc3RhdHVzLFxuICAgICAgYm9keTogYXdhaXQgcmVhZFJlc3BvbnNlVGV4dChyZXMpLFxuICAgIH0pO1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cbiJdfQ==
@@ -260,6 +260,8 @@ export declare class MastraPlugin extends Plugin<MastraPluginConfig> {
260
260
  private registerSuggestionRoutes;
261
261
  /** Register MLflow feedback submission when configured. */
262
262
  private registerFeedbackRoutes;
263
+ /** Register the best-effort per-viewer MLflow experiment debug link. */
264
+ private registerMlflowExperimentRoute;
263
265
  /** Register the gated Mastra catch-all after every explicit route. */
264
266
  private registerAgentRoutes;
265
267
  /**
@@ -307,6 +309,11 @@ export declare class MastraPlugin extends Plugin<MastraPluginConfig> {
307
309
  * (see {@link logFeedback} in `./mlflow.js`).
308
310
  */
309
311
  private logFeedback;
312
+ /**
313
+ * Resolve an experiment link under the active request identity. The helper
314
+ * returns no URL unless the viewer has effective `CAN_MANAGE` permission.
315
+ */
316
+ private fetchMlflowExperimentUrl;
310
317
  /**
311
318
  * Implementation backing the `data` embed resolver
312
319
  * (`GET /embed/data/:id`). Runs inside the AppKit user-context proxy so