@dbx-tools/appkit-mastra 0.6.216 → 0.6.217

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.
@@ -0,0 +1,331 @@
1
+ /**
2
+ * Pydantic Monty fallback for Mastra command execution.
3
+ *
4
+ * Uses the Node subprocess-worker build of Monty. It executes Python source
5
+ * with no host filesystem, network, environment, shell, or third-party package
6
+ * access unless a future caller explicitly adds those capabilities.
7
+ *
8
+ * @module
9
+ */
10
+ import { error, functionModule } from "@dbx-tools/shared-core";
11
+ const DEFAULT_COMMAND_TIMEOUT_MS = 30_000;
12
+ const DEFAULT_MAX_MEMORY_BYTES = 10_000_000;
13
+ const montyModule = functionModule.memoize(() => import("@pydantic/monty/node"));
14
+ const montyPool = functionModule.memoize(async () => {
15
+ const { Monty } = await montyModule();
16
+ return Monty.create({
17
+ minProcesses: 1,
18
+ maxProcesses: 4,
19
+ requestTimeout: 35,
20
+ });
21
+ });
22
+ /** Python-only, deny-by-default sandbox backed by Monty's Node worker pool. */
23
+ export class MontySandbox {
24
+ id;
25
+ name;
26
+ provider = "monty";
27
+ status = "pending";
28
+ error;
29
+ commandTimeoutMs;
30
+ maxMemoryBytes;
31
+ typeCheck;
32
+ createdAt = new Date();
33
+ lastUsedAt;
34
+ constructor(options = {}) {
35
+ this.id = options.id ?? "monty";
36
+ this.name = options.name ?? "Pydantic Monty";
37
+ this.commandTimeoutMs = options.commandTimeoutMs ?? DEFAULT_COMMAND_TIMEOUT_MS;
38
+ this.maxMemoryBytes = options.maxMemoryBytes ?? DEFAULT_MAX_MEMORY_BYTES;
39
+ this.typeCheck = options.typeCheck ?? false;
40
+ }
41
+ /** Warm the shared crash-isolated worker pool. */
42
+ async start() {
43
+ if (this.status === "running")
44
+ return;
45
+ this.status = "starting";
46
+ this.error = undefined;
47
+ try {
48
+ await montyPool();
49
+ this.status = "running";
50
+ }
51
+ catch (caught) {
52
+ this.status = "error";
53
+ this.error = error.errorMessage(caught);
54
+ throw caught;
55
+ }
56
+ }
57
+ /** The process-wide pool stays warm; this instance carries no open session. */
58
+ async stop() {
59
+ this.status = "stopped";
60
+ }
61
+ /** The process-wide pool stays warm; each command closes its own checkout. */
62
+ async destroy() {
63
+ this.status = "destroyed";
64
+ }
65
+ /** Monty sessions are ephemeral and do not provide persistent checkpoints. */
66
+ async snapshot() { }
67
+ supportsCheckpoints = false;
68
+ /** Execute Python source and map Monty output to Mastra's command result. */
69
+ async executeCommand(command, args = [], options = {}) {
70
+ const started = performance.now();
71
+ const code = montyCode(command, args);
72
+ if (code === undefined) {
73
+ return failedResult(command, args, started, "Monty fallback accepts Python source directly, or python/python3 with a single -c script.");
74
+ }
75
+ const environment = Object.entries(options.env ?? {}).filter(([, value]) => value !== undefined);
76
+ if (environment.length > 0) {
77
+ return failedResult(command, args, started, "Monty fallback does not expose host environment variables.");
78
+ }
79
+ if (options.cwd) {
80
+ return failedResult(command, args, started, "Monty fallback does not expose a host working directory.");
81
+ }
82
+ if (options.abortSignal?.aborted)
83
+ throw options.abortSignal.reason;
84
+ await this.start();
85
+ const timeout = options.timeout ?? this.commandTimeoutMs;
86
+ const pool = await montyPool();
87
+ const session = await checkoutSession(pool, {
88
+ limits: {
89
+ maxDurationSecs: Math.max(0.001, timeout / 1_000),
90
+ maxMemory: this.maxMemoryBytes,
91
+ },
92
+ typeCheck: this.typeCheck,
93
+ }, options.abortSignal);
94
+ const output = new RetainedOutput(options);
95
+ const workerPid = session.workerPid;
96
+ let aborted = false;
97
+ const onAbort = () => {
98
+ aborted = true;
99
+ terminateWorker(workerPid);
100
+ };
101
+ options.abortSignal?.addEventListener("abort", onAbort, { once: true });
102
+ if (options.abortSignal?.aborted)
103
+ onAbort();
104
+ try {
105
+ if (aborted)
106
+ throw abortReason(options.abortSignal);
107
+ const value = await session.feedRun(stripPythonFence(code), {
108
+ printCallback: (stream, text) => output.emit(stream, text),
109
+ });
110
+ const returned = formatResult(value);
111
+ if (returned) {
112
+ const suffix = returned.endsWith("\n") ? returned : `${returned}\n`;
113
+ output.emit("stdout", suffix);
114
+ }
115
+ this.lastUsedAt = new Date();
116
+ return {
117
+ command,
118
+ args,
119
+ success: true,
120
+ exitCode: 0,
121
+ stdout: output.stdout.value,
122
+ stderr: output.stderr.value,
123
+ executionTimeMs: performance.now() - started,
124
+ ...output.metadata(),
125
+ };
126
+ }
127
+ catch (caught) {
128
+ if (aborted || options.abortSignal?.aborted) {
129
+ throw abortReason(options.abortSignal);
130
+ }
131
+ const message = error.errorMessage(caught);
132
+ output.emit("stderr", output.stderr.value ? `\n${message}` : message);
133
+ const { MontyCrashedError } = await montyModule();
134
+ const timedOut = caught instanceof MontyCrashedError && caught.timedOut;
135
+ return {
136
+ command,
137
+ args,
138
+ success: false,
139
+ exitCode: timedOut ? -1 : 1,
140
+ stdout: output.stdout.value,
141
+ stderr: output.stderr.value,
142
+ executionTimeMs: performance.now() - started,
143
+ ...(timedOut ? { timedOut: true, killed: true } : {}),
144
+ ...output.metadata(),
145
+ };
146
+ }
147
+ finally {
148
+ options.abortSignal?.removeEventListener("abort", onAbort);
149
+ await session.close();
150
+ }
151
+ }
152
+ async isReady() {
153
+ return this.status === "running";
154
+ }
155
+ getInfo() {
156
+ return {
157
+ id: this.id,
158
+ name: this.name,
159
+ provider: this.provider,
160
+ status: this.status,
161
+ createdAt: this.createdAt,
162
+ ...(this.lastUsedAt ? { lastUsedAt: this.lastUsedAt } : {}),
163
+ metadata: {
164
+ language: "python",
165
+ hostAccess: false,
166
+ },
167
+ };
168
+ }
169
+ getInstructions() {
170
+ return [
171
+ "Commands run as Python source in the Pydantic Monty fallback.",
172
+ "Pass Python code directly rather than shell syntax.",
173
+ "There is no host filesystem, network, environment, shell, or third-party package access.",
174
+ ].join(" ");
175
+ }
176
+ }
177
+ function montyCode(command, args) {
178
+ if (args.length === 0)
179
+ return command;
180
+ if ((command === "python" || command === "python3") && args.length === 2 && args[0] === "-c") {
181
+ return args[1];
182
+ }
183
+ return undefined;
184
+ }
185
+ function stripPythonFence(code) {
186
+ const trimmed = code.trim();
187
+ const match = /^```(?:python|py)?\s*\n([\s\S]*?)\n```$/i.exec(trimmed);
188
+ return match?.[1] ?? code;
189
+ }
190
+ function formatResult(value) {
191
+ if (value === undefined || value === null)
192
+ return "";
193
+ if (typeof value === "string")
194
+ return value;
195
+ try {
196
+ return JSON.stringify(value, null, 2) ?? String(value);
197
+ }
198
+ catch {
199
+ return String(value);
200
+ }
201
+ }
202
+ class RetainedOutput {
203
+ stdout;
204
+ stderr;
205
+ onStdout;
206
+ onStderr;
207
+ constructor(options) {
208
+ this.stdout = new RetainedText(options.maxRetainedBytes);
209
+ this.stderr = new RetainedText(options.maxRetainedBytes);
210
+ this.onStdout = options.onStdout;
211
+ this.onStderr = options.onStderr;
212
+ }
213
+ emit(stream, text) {
214
+ if (stream === "stdout") {
215
+ this.onStdout?.(text);
216
+ this.stdout.append(text);
217
+ }
218
+ else {
219
+ this.onStderr?.(text);
220
+ this.stderr.append(text);
221
+ }
222
+ }
223
+ metadata() {
224
+ return {
225
+ ...(this.stdout.droppedBytes > 0
226
+ ? {
227
+ stdoutTruncated: true,
228
+ stdoutDroppedBytes: this.stdout.droppedBytes,
229
+ }
230
+ : {}),
231
+ ...(this.stderr.droppedBytes > 0
232
+ ? {
233
+ stderrTruncated: true,
234
+ stderrDroppedBytes: this.stderr.droppedBytes,
235
+ }
236
+ : {}),
237
+ };
238
+ }
239
+ }
240
+ class RetainedText {
241
+ value = "";
242
+ droppedBytes = 0;
243
+ maxBytes;
244
+ encoder = new TextEncoder();
245
+ decoder = new TextDecoder();
246
+ constructor(maxBytes) {
247
+ const resolved = maxBytes ?? Number.POSITIVE_INFINITY;
248
+ if (resolved !== Number.POSITIVE_INFINITY &&
249
+ (!Number.isSafeInteger(resolved) || resolved < 0)) {
250
+ throw new TypeError("maxRetainedBytes must be a non-negative safe integer or Infinity");
251
+ }
252
+ this.maxBytes = resolved;
253
+ }
254
+ append(text) {
255
+ if (!text)
256
+ return;
257
+ if (this.maxBytes === Number.POSITIVE_INFINITY) {
258
+ this.value += text;
259
+ return;
260
+ }
261
+ const combined = this.encoder.encode(this.value + text);
262
+ if (combined.length <= this.maxBytes) {
263
+ this.value += text;
264
+ return;
265
+ }
266
+ let start = combined.length - this.maxBytes;
267
+ while (start < combined.length && (combined[start] & 0xc0) === 0x80)
268
+ start++;
269
+ const retained = combined.subarray(start);
270
+ this.droppedBytes += combined.length - retained.length;
271
+ this.value = this.decoder.decode(retained);
272
+ }
273
+ }
274
+ function terminateWorker(workerPid) {
275
+ if (workerPid === undefined)
276
+ return;
277
+ try {
278
+ process.kill(workerPid, "SIGKILL");
279
+ }
280
+ catch {
281
+ // The command can finish between the abort event and the kill request.
282
+ }
283
+ }
284
+ async function checkoutSession(pool, options, signal) {
285
+ const checkout = pool.checkout(options);
286
+ if (!signal)
287
+ return checkout;
288
+ if (signal.aborted) {
289
+ void checkout.then((session) => session.close()).catch(() => undefined);
290
+ throw abortReason(signal);
291
+ }
292
+ return new Promise((resolve, reject) => {
293
+ let settled = false;
294
+ const onAbort = () => {
295
+ if (settled)
296
+ return;
297
+ settled = true;
298
+ reject(abortReason(signal));
299
+ void checkout.then((session) => session.close()).catch(() => undefined);
300
+ };
301
+ signal.addEventListener("abort", onAbort, { once: true });
302
+ checkout.then((session) => {
303
+ if (settled)
304
+ return;
305
+ settled = true;
306
+ signal.removeEventListener("abort", onAbort);
307
+ resolve(session);
308
+ }, (caught) => {
309
+ if (settled)
310
+ return;
311
+ settled = true;
312
+ signal.removeEventListener("abort", onAbort);
313
+ reject(caught);
314
+ });
315
+ });
316
+ }
317
+ function abortReason(signal) {
318
+ return signal?.reason ?? new DOMException("The command was aborted", "AbortError");
319
+ }
320
+ function failedResult(command, args, started, stderr) {
321
+ return {
322
+ command,
323
+ args,
324
+ success: false,
325
+ exitCode: 1,
326
+ stdout: "",
327
+ stderr,
328
+ executionTimeMs: performance.now() - started,
329
+ };
330
+ }
331
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9udHktc2FuZGJveC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9tb250eS1zYW5kYm94LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7OztHQVFHO0FBRUgsT0FBTyxFQUFFLEtBQUssRUFBRSxjQUFjLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQVMvRCxNQUFNLDBCQUEwQixHQUFHLE1BQU0sQ0FBQztBQUMxQyxNQUFNLHdCQUF3QixHQUFHLFVBQVUsQ0FBQztBQUU1QyxNQUFNLFdBQVcsR0FBRyxjQUFjLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUM7QUFDakYsTUFBTSxTQUFTLEdBQUcsY0FBYyxDQUFDLE9BQU8sQ0FBQyxLQUFLLElBQXdCLEVBQUU7SUFDdEUsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLE1BQU0sV0FBVyxFQUFFLENBQUM7SUFDdEMsT0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDO1FBQ2xCLFlBQVksRUFBRSxDQUFDO1FBQ2YsWUFBWSxFQUFFLENBQUM7UUFDZixjQUFjLEVBQUUsRUFBRTtLQUNuQixDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQztBQWdCSCwrRUFBK0U7QUFDL0UsTUFBTSxPQUFPLFlBQVk7SUFDZCxFQUFFLENBQVM7SUFDWCxJQUFJLENBQVM7SUFDYixRQUFRLEdBQUcsT0FBTyxDQUFDO0lBQzVCLE1BQU0sR0FBK0IsU0FBUyxDQUFDO0lBQy9DLEtBQUssQ0FBVTtJQUVFLGdCQUFnQixDQUFTO0lBQ3pCLGNBQWMsQ0FBUztJQUN2QixTQUFTLENBQVU7SUFDbkIsU0FBUyxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7SUFDaEMsVUFBVSxDQUFRO0lBRTFCLFlBQVksVUFBK0IsRUFBRTtRQUMzQyxJQUFJLENBQUMsRUFBRSxHQUFHLE9BQU8sQ0FBQyxFQUFFLElBQUksT0FBTyxDQUFDO1FBQ2hDLElBQUks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RUFBRSxPQUFPLENBQUMsQ0FBQztZQUM3QyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDakIsQ0FBQyxDQUNGLENBQUM7SUFDSixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxTQUFTLFdBQVcsQ0FBQyxNQUErQjtJQUNsRCxPQUFPLE1BQU0sRUFBRSxNQUFNLElBQUksSUFBSSxZQUFZLENBQUMseUJBQXlCLEVBQUUsWUFBWSxDQUFDLENBQUM7QUFDckYsQ0FBQztBQUVELFNBQVMsWUFBWSxDQUNuQixPQUFlLEVBQ2YsSUFBYyxFQUNkLE9BQWUsRUFDZixNQUFjO0lBRWQsT0FBTztRQUNMLE9BQU87UUFDUCxJQUFJO1FBQ0osT0FBTyxFQUFFLEtBQUs7UUFDZCxRQUFRLEVBQUUsQ0FBQztRQUNYLE1BQU0sRUFBRSxFQUFFO1FBQ1YsTUFBTTtRQUNOLGVBQWUsRUFBRSxXQUFXLENBQUMsR0FBRyxFQUFFLEdBQUcsT0FBTztLQUM3QyxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogUHlkYW50aWMgTW9udHkgZmFsbGJhY2sgZm9yIE1hc3RyYSBjb21tYW5kIGV4ZWN1dGlvbi5cbiAqXG4gKiBVc2VzIHRoZSBOb2RlIHN1YnByb2Nlc3Mtd29ya2VyIGJ1aWxkIG9mIE1vbnR5LiBJdCBleGVjdXRlcyBQeXRob24gc291cmNlXG4gKiB3aXRoIG5vIGhvc3QgZmlsZXN5c3RlbSwgbmV0d29yaywgZW52aXJvbm1lbnQsIHNoZWxsLCBvciB0aGlyZC1wYXJ0eSBwYWNrYWdlXG4gKiBhY2Nlc3MgdW5sZXNzIGEgZnV0dXJlIGNhbGxlciBleHBsaWNpdGx5IGFkZHMgdGhvc2UgY2FwYWJpbGl0aWVzLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBlcnJvciwgZnVuY3Rpb25Nb2R1bGUgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHR5cGUge1xuICBDb21tYW5kUmVzdWx0LFxuICBFeGVjdXRlQ29tbWFuZE9wdGlvbnMsXG4gIFNhbmRib3hJbmZvLFxuICBXb3Jrc3BhY2VTYW5kYm94LFxufSBmcm9tIFwiQG1hc3RyYS9jb3JlL3dvcmtzcGFjZVwiO1xuaW1wb3J0IHR5cGUgeyBDaGVja291dE9wdGlvbnMsIE1vbnR5IGFzIE1vbnR5UG9vbCwgTW9udHlTZXNzaW9uIH0gZnJvbSBcIkBweWRhbnRpYy9tb250eS9ub2RlXCI7XG5cbmNvbnN0IERFRkFVTFRfQ09NTUFORF9USU1FT1VUX01TID0gMzBfMDAwO1xuY29uc3QgREVGQVVMVF9NQVhfTUVNT1JZX0JZVEVTID0gMTBfMDAwXzAwMDtcblxuY29uc3QgbW9udHlNb2R1bGUgPSBmdW5jdGlvbk1vZHVsZS5tZW1vaXplKCgpID0+IGltcG9ydChcIkBweWRhbnRpYy9tb250eS9ub2RlXCIpKTtcbmNvbnN0IG1vbnR5UG9vbCA9IGZ1bmN0aW9uTW9kdWxlLm1lbW9pemUoYXN5bmMgKCk6IFByb21pc2U8TW9udHlQb29sPiA9PiB7XG4gIGNvbnN0IHsgTW9udHkgfSA9IGF3YWl0IG1vbnR5TW9kdWxlKCk7XG4gIHJldHVybiBNb250eS5jcmVhdGUoe1xuICAgIG1pblByb2Nlc3NlczogMSxcbiAgICBtYXhQcm9jZXNzZXM6IDQsXG4gICAgcmVxdWVzdFRpbWVvdXQ6IDM1LFxuICB9KTtcbn0pO1xuXG4vKiogUmVzb3VyY2UgY29udHJvbHMgZm9yIHRoZSBNb250eSBQeXRob24gZmFsbGJhY2suICovXG5leHBvcnQgaW50ZXJmYWNlIE1vbnR5U2FuZGJveE9wdGlvbnMge1xuICAvKiogTWFzdHJhIHByb3ZpZGVyIGlkLiAqL1xuICBpZD86IHN0cmluZztcbiAgLyoqIERpc3BsYXkgbmFtZS4gKi9cbiAgbmFtZT86IHN0cmluZztcbiAgLyoqIERlZmF1bHQgZXhlY3V0aW9uIHRpbWVvdXQuIFBlci1jYWxsIGBvcHRpb25zLnRpbWVvdXRgIHdpbnMuICovXG4gIGNvbW1hbmRUaW1lb3V0TXM/OiBudW1iZXI7XG4gIC8qKiBNYXhpbXVtIE1vbnR5IGhlYXAgYnl0ZXMgZm9yIG9uZSBjaGVja291dC4gKi9cbiAgbWF4TWVtb3J5Qnl0ZXM/OiBudW1iZXI7XG4gIC8qKiBUeXBlLWNoZWNrIGVhY2ggUHl0aG9uIHNuaXBwZXQgYmVmb3JlIHJ1bm5pbmcgaXQuIERlZmF1bHRzIHRvIGZhbHNlLiAqL1xuICB0eXBlQ2hlY2s/OiBib29sZWFuO1xufVxuXG4vKiogUHl0aG9uLW9ubHksIGRlbnktYnktZGVmYXVsdCBzYW5kYm94IGJhY2tlZCBieSBNb250eSdzIE5vZGUgd29ya2VyIHBvb2wuICovXG5leHBvcnQgY2xhc3MgTW9udHlTYW5kYm94IGltcGxlbWVudHMgV29ya3NwYWNlU2FuZGJveCB7XG4gIHJlYWRvbmx5IGlkOiBzdHJpbmc7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgcHJvdmlkZXIgPSBcIm1vbnR5XCI7XG4gIHN0YXR1czogV29ya3NwYWNlU2FuZGJveFtcInN0YXR1c1wiXSA9IFwicGVuZGluZ1wiO1xuICBlcnJvcj86IHN0cmluZztcblxuICBwcml2YXRlIHJlYWRvbmx5IGNvbW1hbmRUaW1lb3V0TXM6IG51bWJlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBtYXhNZW1vcnlCeXRlczogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IHR5cGVDaGVjazogYm9vbGVhbjtcbiAgcHJpdmF0ZSByZWFkb25seSBjcmVhdGVkQXQgPSBuZXcgRGF0ZSgpO1xuICBwcml2YXRlIGxhc3RVc2VkQXQ/OiBEYXRlO1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IE1vbnR5U2FuZGJveE9wdGlvbnMgPSB7fSkge1xuICAgIHRoaXMuaWQgPSBvcHRpb25zLmlkID8/IFwibW9udHlcIjtcbiAgICB0aGlzLm5hbWUgPSBvcHRpb25zLm5hbWUgPz8gXCJQeWRhbnRpYyBNb250eVwiO1xuICAgIHRoaXMuY29tbWFuZFRpbWVvdXRNcyA9IG9wdGlvbnMuY29tbWFuZFRpbWVvdXRNcyA/PyBERUZBVUxUX0NPTU1BTkRfVElNRU9VVF9NUztcbiAgICB0aGlzLm1heE1lbW9yeUJ5dGVzID0gb3B0aW9ucy5tYXhNZW1vcnlCeXRlcyA/PyBERUZBVUxUX01BWF9NRU1PUllfQllURVM7XG4gICAgdGhpcy50eXBlQ2hlY2sgPSBvcHRpb25zLnR5cGVDaGVjayA/PyBmYWxzZTtcbiAgfVxuXG4gIC8qKiBXYXJtIHRoZSBzaGFyZWQgY3Jhc2gtaXNvbGF0ZWQgd29ya2VyIHBvb2wuICovXG4gIGFzeW5jIHN0YXJ0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLnN0YXR1cyA9PT0gXCJydW5uaW5nXCIpIHJldHVybjtcbiAgICB0aGlzLnN0YXR1cyA9IFwic3RhcnRpbmdcIjtcbiAgICB0aGlzLmVycm9yID0gdW5kZWZpbmVkO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBtb250eVBvb2woKTtcbiAgICAgIHRoaXMuc3RhdHVzID0gXCJydW5uaW5nXCI7XG4gICAgfSBjYXRjaCAoY2F1Z2h0KSB7XG4gICAgICB0aGlzLnN0YXR1cyA9IFwiZXJyb3JcIjtcbiAgICAgIHRoaXMuZXJyb3IgPSBlcnJvci5lcnJvck1lc3NhZ2UoY2F1Z2h0KTtcbiAgICAgIHRocm93IGNhdWdodDtcbiAgICB9XG4gIH1cblxuICAvKiogVGhlIHByb2Nlc3Mtd2lkZSBwb29sIHN0YXlzIHdhcm07IHRoaXMgaW5zdGFuY2UgY2FycmllcyBubyBvcGVuIHNlc3Npb24uICovXG4gIGFzeW5jIHN0b3AoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5zdGF0dXMgPSBcInN0b3BwZWRcIjtcbiAgfVxuXG4gIC8qKiBUaGUgcHJvY2Vzcy13aWRlIHBvb2wgc3RheXMgd2FybTsgZWFjaCBjb21tYW5kIGNsb3NlcyBpdHMgb3duIGNoZWNrb3V0LiAqL1xuICBhc3luYyBkZXN0cm95KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuc3RhdHVzID0gXCJkZXN0cm95ZWRcIjtcbiAgfVxuXG4gIC8qKiBNb250eSBzZXNzaW9ucyBhcmUgZXBoZW1lcmFsIGFuZCBkbyBub3QgcHJvdmlkZSBwZXJzaXN0ZW50IGNoZWNrcG9pbnRzLiAqL1xuICBhc3luYyBzbmFwc2hvdCgpOiBQcm9taXNlPHZvaWQ+IHt9XG5cbiAgcmVhZG9ubHkgc3VwcG9ydHNDaGVja3BvaW50cyA9IGZhbHNlO1xuXG4gIC8qKiBFeGVjdXRlIFB5dGhvbiBzb3VyY2UgYW5kIG1hcCBNb250eSBvdXRwdXQgdG8gTWFzdHJhJ3MgY29tbWFuZCByZXN1bHQuICovXG4gIGFzeW5jIGV4ZWN1dGVDb21tYW5kKFxuICAgIGNvbW1hbmQ6IHN0cmluZyxcbiAgICBhcmdzOiBzdHJpbmdbXSA9IFtdLFxuICAgIG9wdGlvbnM6IEV4ZWN1dGVDb21tYW5kT3B0aW9ucyA9IHt9LFxuICApOiBQcm9taXNlPENvbW1hbmRSZXN1bHQ+IHtcbiAgICBjb25zdCBzdGFydGVkID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgY29uc3QgY29kZSA9IG1vbnR5Q29kZShjb21tYW5kLCBhcmdzKTtcbiAgICBpZiAoY29kZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gZmFpbGVkUmVzdWx0KFxuICAgICAgICBjb21tYW5kLFxuICAgICAgICBhcmdzLFxuICAgICAgICBzdGFydGVkLFxuICAgICAgICBcIk1vbnR5IGZhbGxiYWNrIGFjY2VwdHMgUHl0aG9uIHNvdXJjZSBkaXJlY3RseSwgb3IgcHl0aG9uL3B5dGhvbjMgd2l0aCBhIHNpbmdsZSAtYyBzY3JpcHQuXCIsXG4gICAgICApO1xuICAgIH1cbiAgICBjb25zdCBlbnZpcm9ubWVudCA9IE9iamVjdC5lbnRyaWVzKG9wdGlvbnMuZW52ID8/IHt9KS5maWx0ZXIoXG4gICAgICAoWywgdmFsdWVdKSA9PiB2YWx1ZSAhPT0gdW5kZWZpbmVkLFxuICAgICk7XG4gICAgaWYgKGVudmlyb25tZW50Lmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiBmYWlsZWRSZXN1bHQoXG4gICAgICAgIGNvbW1hbmQsXG4gICAgICAgIGFyZ3MsXG4gICAgICAgIHN0YXJ0ZWQsXG4gICAgICAgIFwiTW9udHkgZmFsbGJhY2sgZG9lcyBub3QgZXhwb3NlIGhvc3QgZW52aXJvbm1lbnQgdmFyaWFibGVzLlwiLFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMuY3dkKSB7XG4gICAgICByZXR1cm4gZmFpbGVkUmVzdWx0KFxuICAgICAgICBjb21tYW5kLFxuICAgICAgICBhcmdzLFxuICAgICAgICBzdGFydGVkLFxuICAgICAgICBcIk1vbnR5IGZhbGxiYWNrIGRvZXMgbm90IGV4cG9zZSBhIGhvc3Qgd29ya2luZyBkaXJlY3RvcnkuXCIsXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy5hYm9ydFNpZ25hbD8uYWJvcnRlZCkgdGhyb3cgb3B0aW9ucy5hYm9ydFNpZ25hbC5yZWFzb247XG5cbiAgICBhd2FpdCB0aGlzLnN0YXJ0KCk7XG4gICAgY29uc3QgdGltZW91dCA9IG9wdGlvbnMudGltZW91dCA/PyB0aGlzLmNvbW1hbmRUaW1lb3V0TXM7XG4gICAgY29uc3QgcG9vbCA9IGF3YWl0IG1vbnR5UG9vbCgpO1xuICAgIGNvbnN0IHNlc3Npb24gPSBhd2FpdCBjaGVja291dFNlc3Npb24oXG4gICAgICBwb29sLFxuICAgICAge1xuICAgICAgICBsaW1pdHM6IHtcbiAgICAgICAgICBtYXhEdXJhdGlvblNlY3M6IE1hdGgubWF4KDAuMDAxLCB0aW1lb3V0IC8gMV8wMDApLFxuICAgICAgICAgIG1heE1lbW9yeTogdGhpcy5tYXhNZW1vcnlCeXRlcyxcbiAgICAgICAgfSxcbiAgICAgICAgdHlwZUNoZWNrOiB0aGlzLnR5cGVDaGVjayxcbiAgICAgIH0sXG4gICAgICBvcHRpb25zLmFib3J0U2lnbmFsLFxuICAgICk7XG4gICAgY29uc3Qgb3V0cHV0ID0gbmV3IFJldGFpbmVkT3V0cHV0KG9wdGlvbnMpO1xuICAgIGNvbnN0IHdvcmtlclBpZCA9IHNlc3Npb24ud29ya2VyUGlkO1xuICAgIGxldCBhYm9ydGVkID0gZmFsc2U7XG4gICAgY29uc3Qgb25BYm9ydCA9ICgpOiB2b2lkID0+IHtcbiAgICAgIGFib3J0ZWQgPSB0cnVlO1xuICAgICAgdGVybWluYXRlV29ya2VyKHdvcmtlclBpZCk7XG4gICAgfTtcbiAgICBvcHRpb25zLmFib3J0U2lnbmFsPy5hZGRFdmVudExpc3RlbmVyKFwiYWJvcnRcIiwgb25BYm9ydCwgeyBvbmNlOiB0cnVlIH0pO1xuICAgIGlmIChvcHRpb25zLmFib3J0U2lnbmFsPy5hYm9ydGVkKSBvbkFib3J0KCk7XG4gICAgdHJ5IHtcbiAgICAgIGlmIChhYm9ydGVkKSB0aHJvdyBhYm9ydFJlYXNvbihvcHRpb25zLmFib3J0U2lnbmFsKTtcbiAgICAgIGNvbnN0IHZhbHVlID0gYXdhaXQgc2Vzc2lvbi5mZWVkUnVuKHN0cmlwUHl0aG9uRmVuY2UoY29kZSksIHtcbiAgICAgICAgcHJpbnRDYWxsYmFjazogKHN0cmVhbSwgdGV4dCkgPT4gb3V0cHV0LmVtaXQoc3RyZWFtLCB0ZXh0KSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgcmV0dXJuZWQgPSBmb3JtYXRSZXN1bHQodmFsdWUpO1xuICAgICAgaWYgKHJldHVybmVkKSB7XG4gICAgICAgIGNvbnN0IHN1ZmZpeCA9IHJldHVybmVkLmVuZHNXaXRoKFwiXFxuXCIpID8gcmV0dXJuZWQgOiBgJHtyZXR1cm5lZH1cXG5gO1xuICAgICAgICBvdXRwdXQuZW1pdChcInN0ZG91dFwiLCBzdWZmaXgpO1xuICAgICAgfVxuICAgICAgdGhpcy5sYXN0VXNlZEF0ID0gbmV3IERhdGUoKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGNvbW1hbmQsXG4gICAgICAgIGFyZ3MsXG4gICAgICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgICAgIGV4aXRDb2RlOiAwLFxuICAgICAgICBzdGRvdXQ6IG91dHB1dC5zdGRvdXQudmFsdWUsXG4gICAgICAgIHN0ZGVycjogb3V0cHV0LnN0ZGVyci52YWx1ZSxcbiAgICAgICAgZXhlY3V0aW9uVGltZU1zOiBwZXJmb3JtYW5jZS5ub3coKSAtIHN0YXJ0ZWQsXG4gICAgICAgIC4uLm91dHB1dC5tZXRhZGF0YSgpLFxuICAgICAgfTtcbiAgICB9IGNhdGNoIChjYXVnaHQpIHtcbiAgICAgIGlmIChhYm9ydGVkIHx8IG9wdGlvbnMuYWJvcnRTaWduYWw/LmFib3J0ZWQpIHtcbiAgICAgICAgdGhyb3cgYWJvcnRSZWFzb24ob3B0aW9ucy5hYm9ydFNpZ25hbCk7XG4gICAgICB9XG4gICAgICBjb25zdCBtZXNzYWdlID0gZXJyb3IuZXJyb3JNZXNzYWdlKGNhdWdodCk7XG4gICAgICBvdXRwdXQuZW1pdChcInN0ZGVyclwiLCBvdXRwdXQuc3RkZXJyLnZhbHVlID8gYFxcbiR7bWVzc2FnZX1gIDogbWVzc2FnZSk7XG4gICAgICBjb25zdCB7IE1vbnR5Q3Jhc2hlZEVycm9yIH0gPSBhd2FpdCBtb250eU1vZHVsZSgpO1xuICAgICAgY29uc3QgdGltZWRPdXQgPSBjYXVnaHQgaW5zdGFuY2VvZiBNb250eUNyYXNoZWRFcnJvciAmJiBjYXVnaHQudGltZWRPdXQ7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb21tYW5kLFxuICAgICAgICBhcmdzLFxuICAgICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgICAgZXhpdENvZGU6IHRpbWVkT3V0ID8gLTEgOiAxLFxuICAgICAgICBzdGRvdXQ6IG91dHB1dC5zdGRvdXQudmFsdWUsXG4gICAgICAgIHN0ZGVycjogb3V0cHV0LnN0ZGVyci52YWx1ZSxcbiAgICAgICAgZXhlY3V0aW9uVGltZU1zOiBwZXJmb3JtYW5jZS5ub3coKSAtIHN0YXJ0ZWQsXG4gICAgICAgIC4uLih0aW1lZE91dCA/IHsgdGltZWRPdXQ6IHRydWUsIGtpbGxlZDogdHJ1ZSB9IDoge30pLFxuICAgICAgICAuLi5vdXRwdXQubWV0YWRhdGEoKSxcbiAgICAgIH07XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIG9wdGlvbnMuYWJvcnRTaWduYWw/LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLCBvbkFib3J0KTtcbiAgICAgIGF3YWl0IHNlc3Npb24uY2xvc2UoKTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBpc1JlYWR5KCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLnN0YXR1cyA9PT0gXCJydW5uaW5nXCI7XG4gIH1cblxuICBnZXRJbmZvKCk6IFNhbmRib3hJbmZvIHtcbiAgICByZXR1cm4ge1xuICAgICAgaWQ6IHRoaXMuaWQsXG4gICAgICBuYW1lOiB0aGlzLm5hbWUsXG4gICAgICBwcm92aWRlcjogdGhpcy5wcm92aWRlcixcbiAgICAgIHN0YXR1czogdGhpcy5zdGF0dXMsXG4gICAgICBjcmVhdGVkQXQ6IHRoaXMuY3JlYXRlZEF0LFxuICAgICAgLi4uKHRoaXMubGFzdFVzZWRBdCA/IHsgbGFzdFVzZWRBdDogdGhpcy5sYXN0VXNlZEF0IH0gOiB7fSksXG4gICAgICBtZXRhZGF0YToge1xuICAgICAgICBsYW5ndWFnZTogXCJweXRob25cIixcbiAgICAgICAgaG9zdEFjY2VzczogZmFsc2UsXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICBnZXRJbnN0cnVjdGlvbnMoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gW1xuICAgICAgXCJDb21tYW5kcyBydW4gYXMgUHl0aG9uIHNvdXJjZSBpbiB0aGUgUHlkYW50aWMgTW9udHkgZmFsbGJhY2suXCIsXG4gICAgICBcIlBhc3MgUHl0aG9uIGNvZGUgZGlyZWN0bHkgcmF0aGVyIHRoYW4gc2hlbGwgc3ludGF4LlwiLFxuICAgICAgXCJUaGVyZSBpcyBubyBob3N0IGZpbGVzeXN0ZW0sIG5ldHdvcmssIGVudmlyb25tZW50LCBzaGVsbCwgb3IgdGhpcmQtcGFydHkgcGFja2FnZSBhY2Nlc3MuXCIsXG4gICAgXS5qb2luKFwiIFwiKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtb250eUNvZGUoY29tbWFuZDogc3RyaW5nLCBhcmdzOiByZWFkb25seSBzdHJpbmdbXSk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmIChhcmdzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIGNvbW1hbmQ7XG4gIGlmICgoY29tbWFuZCA9PT0gXCJweXRob25cIiB8fCBjb21tYW5kID09PSBcInB5dGhvbjNcIikgJiYgYXJncy5sZW5ndGggPT09IDIgJiYgYXJnc1swXSA9PT0gXCItY1wiKSB7XG4gICAgcmV0dXJuIGFyZ3NbMV07XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gc3RyaXBQeXRob25GZW5jZShjb2RlOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCB0cmltbWVkID0gY29kZS50cmltKCk7XG4gIGNvbnN0IG1hdGNoID0gL15gYGAoPzpweXRob258cHkpP1xccypcXG4oW1xcc1xcU10qPylcXG5gYGAkL2kuZXhlYyh0cmltbWVkKTtcbiAgcmV0dXJuIG1hdGNoPy5bMV0gPz8gY29kZTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0UmVzdWx0KHZhbHVlOiB1bmtub3duKTogc3RyaW5nIHtcbiAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQgfHwgdmFsdWUgPT09IG51bGwpIHJldHVybiBcIlwiO1xuICBpZiAodHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiKSByZXR1cm4gdmFsdWU7XG4gIHRyeSB7XG4gICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHZhbHVlLCBudWxsLCAyKSA/PyBTdHJpbmcodmFsdWUpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gU3RyaW5nKHZhbHVlKTtcbiAgfVxufVxuXG5jbGFzcyBSZXRhaW5lZE91dHB1dCB7XG4gIHJlYWRvbmx5IHN0ZG91dDogUmV0YWluZWRUZXh0O1xuICByZWFkb25seSBzdGRlcnI6IFJldGFpbmVkVGV4dDtcblxuICBwcml2YXRlIHJlYWRvbmx5IG9uU3Rkb3V0OiBFeGVjdXRlQ29tbWFuZE9wdGlvbnNbXCJvblN0ZG91dFwiXTtcbiAgcHJpdmF0ZSByZWFkb25seSBvblN0ZGVycjogRXhlY3V0ZUNvbW1hbmRPcHRpb25zW1wib25TdGRlcnJcIl07XG5cbiAgY29uc3RydWN0b3Iob3B0aW9uczogRXhlY3V0ZUNvbW1hbmRPcHRpb25zKSB7XG4gICAgdGhpcy5zdGRvdXQgPSBuZXcgUmV0YWluZWRUZXh0KG9wdGlvbnMubWF4UmV0YWluZWRCeXRlcyk7XG4gICAgdGhpcy5zdGRlcnIgPSBuZXcgUmV0YWluZWRUZXh0KG9wdGlvbnMubWF4UmV0YWluZWRCeXRlcyk7XG4gICAgdGhpcy5vblN0ZG91dCA9IG9wdGlvbnMub25TdGRvdXQ7XG4gICAgdGhpcy5vblN0ZGVyciA9IG9wdGlvbnMub25TdGRlcnI7XG4gIH1cblxuICBlbWl0KHN0cmVhbTogXCJzdGRvdXRcIiB8IFwic3RkZXJyXCIsIHRleHQ6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmIChzdHJlYW0gPT09IFwic3Rkb3V0XCIpIHtcbiAgICAgIHRoaXMub25TdGRvdXQ/Lih0ZXh0KTtcbiAgICAgIHRoaXMuc3Rkb3V0LmFwcGVuZCh0ZXh0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5vblN0ZGVycj8uKHRleHQpO1xuICAgICAgdGhpcy5zdGRlcnIuYXBwZW5kKHRleHQpO1xuICAgIH1cbiAgfVxuXG4gIG1ldGFkYXRhKCk6IFBpY2s8XG4gICAgQ29tbWFuZFJlc3VsdCxcbiAgICBcInN0ZG91dFRydW5jYXRlZFwiIHwgXCJzdGRlcnJUcnVuY2F0ZWRcIiB8IFwic3Rkb3V0RHJvcHBlZEJ5dGVzXCIgfCBcInN0ZGVyckRyb3BwZWRCeXRlc1wiXG4gID4ge1xuICAgIHJldHVybiB7XG4gICAgICAuLi4odGhpcy5zdGRvdXQuZHJvcHBlZEJ5dGVzID4gMFxuICAgICAgICA/IHtcbiAgICAgICAgICAgIHN0ZG91dFRydW5jYXRlZDogdHJ1ZSxcbiAgICAgICAgICAgIHN0ZG91dERyb3BwZWRCeXRlczogdGhpcy5zdGRvdXQuZHJvcHBlZEJ5dGVzLFxuICAgICAgICAgIH1cbiAgICAgICAgOiB7fSksXG4gICAgICAuLi4odGhpcy5zdGRlcnIuZHJvcHBlZEJ5dGVzID4gMFxuICAgICAgICA/IHtcbiAgICAgICAgICAgIHN0ZGVyclRydW5jYXRlZDogdHJ1ZSxcbiAgICAgICAgICAgIHN0ZGVyckRyb3BwZWRCeXRlczogdGhpcy5zdGRlcnIuZHJvcHBlZEJ5dGVzLFxuICAgICAgICAgIH1cbiAgICAgICAgOiB7fSksXG4gICAgfTtcbiAgfVxufVxuXG5jbGFzcyBSZXRhaW5lZFRleHQge1xuICB2YWx1ZSA9IFwiXCI7XG4gIGRyb3BwZWRCeXRlcyA9IDA7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBtYXhCeXRlczogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IGVuY29kZXIgPSBuZXcgVGV4dEVuY29kZXIoKTtcbiAgcHJpdmF0ZSByZWFkb25seSBkZWNvZGVyID0gbmV3IFRleHREZWNvZGVyKCk7XG5cbiAgY29uc3RydWN0b3IobWF4Qnl0ZXM6IG51bWJlciB8IHVuZGVmaW5lZCkge1xuICAgIGNvbnN0IHJlc29sdmVkID0gbWF4Qnl0ZXMgPz8gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZO1xuICAgIGlmIChcbiAgICAgIHJlc29sdmVkICE9PSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFkgJiZcbiAgICAgICghTnVtYmVyLmlzU2FmZUludGVnZXIocmVzb2x2ZWQpIHx8IHJlc29sdmVkIDwgMClcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJtYXhSZXRhaW5lZEJ5dGVzIG11c3QgYmUgYSBub24tbmVnYXRpdmUgc2FmZSBpbnRlZ2VyIG9yIEluZmluaXR5XCIpO1xuICAgIH1cbiAgICB0aGlzLm1heEJ5dGVzID0gcmVzb2x2ZWQ7XG4gIH1cblxuICBhcHBlbmQodGV4dDogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKCF0ZXh0KSByZXR1cm47XG4gICAgaWYgKHRoaXMubWF4Qnl0ZXMgPT09IE51bWJlci5QT1NJVElWRV9JTkZJTklUWSkge1xuICAgICAgdGhpcy52YWx1ZSArPSB0ZXh0O1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBjb21iaW5lZCA9IHRoaXMuZW5jb2Rlci5lbmNvZGUodGhpcy52YWx1ZSArIHRleHQpO1xuICAgIGlmIChjb21iaW5lZC5sZW5ndGggPD0gdGhpcy5tYXhCeXRlcykge1xuICAgICAgdGhpcy52YWx1ZSArPSB0ZXh0O1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsZXQgc3RhcnQgPSBjb21iaW5lZC5sZW5ndGggLSB0aGlzLm1heEJ5dGVzO1xuICAgIHdoaWxlIChzdGFydCA8IGNvbWJpbmVkLmxlbmd0aCAmJiAoY29tYmluZWRbc3RhcnRdISAmIDB4YzApID09PSAweDgwKSBzdGFydCsrO1xuICAgIGNvbnN0IHJldGFpbmVkID0gY29tYmluZWQuc3ViYXJyYXkoc3RhcnQpO1xuICAgIHRoaXMuZHJvcHBlZEJ5dGVzICs9IGNvbWJpbmVkLmxlbmd0aCAtIHJldGFpbmVkLmxlbmd0aDtcbiAgICB0aGlzLnZhbHVlID0gdGhpcy5kZWNvZGVyLmRlY29kZShyZXRhaW5lZCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdGVybWluYXRlV29ya2VyKHdvcmtlclBpZDogbnVtYmVyIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gIGlmICh3b3JrZXJQaWQgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICB0cnkge1xuICAgIHByb2Nlc3Mua2lsbCh3b3JrZXJQaWQsIFwiU0lHS0lMTFwiKTtcbiAgfSBjYXRjaCB7XG4gICAgLy8gVGhlIGNvbW1hbmQgY2FuIGZpbmlzaCBiZXR3ZWVuIHRoZSBhYm9ydCBldmVudCBhbmQgdGhlIGtpbGwgcmVxdWVzdC5cbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBjaGVja291dFNlc3Npb24oXG4gIHBvb2w6IE1vbnR5UG9vbCxcbiAgb3B0aW9uczogQ2hlY2tvdXRPcHRpb25zLFxuICBzaWduYWw6IEFib3J0U2lnbmFsIHwgdW5kZWZpbmVkLFxuKTogUHJvbWlzZTxNb250eVNlc3Npb24+IHtcbiAgY29uc3QgY2hlY2tvdXQgPSBwb29sLmNoZWNrb3V0KG9wdGlvbnMpO1xuICBpZiAoIXNpZ25hbCkgcmV0dXJuIGNoZWNrb3V0O1xuICBpZiAoc2lnbmFsLmFib3J0ZWQpIHtcbiAgICB2b2lkIGNoZWNrb3V0LnRoZW4oKHNlc3Npb24pID0+IHNlc3Npb24uY2xvc2UoKSkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB0aHJvdyBhYm9ydFJlYXNvbihzaWduYWwpO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBQcm9taXNlPE1vbnR5U2Vzc2lvbj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGxldCBzZXR0bGVkID0gZmFsc2U7XG4gICAgY29uc3Qgb25BYm9ydCA9ICgpOiB2b2lkID0+IHtcbiAgICAgIGlmIChzZXR0bGVkKSByZXR1cm47XG4gICAgICBzZXR0bGVkID0gdHJ1ZTtcbiAgICAgIHJlamVjdChhYm9ydFJlYXNvbihzaWduYWwpKTtcbiAgICAgIHZvaWQgY2hlY2tvdXQudGhlbigoc2Vzc2lvbikgPT4gc2Vzc2lvbi5jbG9zZSgpKS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgIH07XG4gICAgc2lnbmFsLmFkZEV2ZW50TGlzdGVuZXIoXCJhYm9ydFwiLCBvbkFib3J0LCB7IG9uY2U6IHRydWUgfSk7XG4gICAgY2hlY2tvdXQudGhlbihcbiAgICAgIChzZXNzaW9uKSA9PiB7XG4gICAgICAgIGlmIChzZXR0bGVkKSByZXR1cm47XG4gICAgICAgIHNldHRsZWQgPSB0cnVlO1xuICAgICAgICBzaWduYWwucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImFib3J0XCIsIG9uQWJvcnQpO1xuICAgICAgICByZXNvbHZlKHNlc3Npb24pO1xuICAgICAgfSxcbiAgICAgIChjYXVnaHQ6IHVua25vd24pID0+IHtcbiAgICAgICAgaWYgKHNldHRsZWQpIHJldHVybjtcbiAgICAgICAgc2V0dGxlZCA9IHRydWU7XG4gICAgICAgIHNpZ25hbC5yZW1vdmVFdmVudExpc3RlbmVyKFwiYWJvcnRcIiwgb25BYm9ydCk7XG4gICAgICAgIHJlamVjdChjYXVnaHQpO1xuICAgICAgfSxcbiAgICApO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gYWJvcnRSZWFzb24oc2lnbmFsOiBBYm9ydFNpZ25hbCB8IHVuZGVmaW5lZCk6IHVua25vd24ge1xuICByZXR1cm4gc2lnbmFsPy5yZWFzb24gPz8gbmV3IERPTUV4Y2VwdGlvbihcIlRoZSBjb21tYW5kIHdhcyBhYm9ydGVkXCIsIFwiQWJvcnRFcnJvclwiKTtcbn1cblxuZnVuY3Rpb24gZmFpbGVkUmVzdWx0KFxuICBjb21tYW5kOiBzdHJpbmcsXG4gIGFyZ3M6IHN0cmluZ1tdLFxuICBzdGFydGVkOiBudW1iZXIsXG4gIHN0ZGVycjogc3RyaW5nLFxuKTogQ29tbWFuZFJlc3VsdCB7XG4gIHJldHVybiB7XG4gICAgY29tbWFuZCxcbiAgICBhcmdzLFxuICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgIGV4aXRDb2RlOiAxLFxuICAgIHN0ZG91dDogXCJcIixcbiAgICBzdGRlcnIsXG4gICAgZXhlY3V0aW9uVGltZU1zOiBwZXJmb3JtYW5jZS5ub3coKSAtIHN0YXJ0ZWQsXG4gIH07XG59XG4iXX0=
@@ -176,7 +176,7 @@ export declare class MastraPlugin extends Plugin<MastraPluginConfig> {
176
176
  */
177
177
  getDefault: () => Agent | null;
178
178
  /** Underlying Mastra instance for advanced use (custom routes etc.). */
179
- getMastra: () => Mastra<Record<string, Agent<any, import("@mastra/core/agent").ToolsInput, undefined, unknown, import("@mastra/core/agent").AgentEditorConfig | undefined>>, Record<string, import("@mastra/core/workflows").AnyWorkflow>, Record<string, import("@mastra/core/vector").MastraVector<any>>, Record<string, import("@mastra/core/tts").MastraTTS>, import("@mastra/core/logger").IMastraLogger, Record<string, import("@mastra/core/mcp").MCPServerBase<any>>, Record<string, import("@mastra/core/evals").MastraScorer<any, any, any, any>>, Record<string, import("@mastra/core/tools").ToolAction<any, any, any, any, any, any, unknown>>, Record<string, import("@mastra/core/processors").Processor<any, unknown>>, Record<string, import("@mastra/core/memory").MastraMemory>, Record<string, import("@mastra/core/channels").ChannelProvider>> | null;
179
+ getMastra: () => Mastra<Record<string, Agent<any, import("@mastra/core/agent").ToolsInput, undefined, any, import("@mastra/core/agent").AgentEditorConfig | undefined>>, Record<string, import("@mastra/core/workflows").AnyWorkflow>, Record<string, import("@mastra/core/vector").MastraVector<any>>, Record<string, import("@mastra/core/tts").MastraTTS>, import("@mastra/core/logger").IMastraLogger, Record<string, import("@mastra/core/mcp").MCPServerBase<any>>, Record<string, import("@mastra/core/evals").MastraScorer<any, any, any, any>>, Record<string, import("@mastra/core/tools").ToolAction<any, any, any, any, any, any, unknown>>, Record<string, import("@mastra/core/processors").Processor<any, unknown>>, Record<string, import("@mastra/core/memory").MastraMemory>, Record<string, import("@mastra/core/channels").ChannelProvider>> | null;
180
180
  /**
181
181
  * Build the `RequestContext` an agent turn driven from OUTSIDE this
182
182
  * plugin's routes needs (a Teams activity on another plugin's endpoint, a
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Databricks Sandbox adapter for Mastra workspaces.
3
+ *
4
+ * Implements Mastra's foreground command surface over the Databricks Sandbox
5
+ * REST API. Sandboxes are created lazily, retain their home directory across
6
+ * inactivity stops, and execute untrusted shell commands outside the App
7
+ * container.
8
+ *
9
+ * @module
10
+ */
11
+ import type { WorkspaceClient } from "@databricks/appkit";
12
+ import type { RequestContext } from "@mastra/core/request-context";
13
+ import type { CommandResult, ExecuteCommandOptions, ProviderStatus, SandboxInfo, WorkspaceSandbox } from "@mastra/core/workspace";
14
+ import { type MontySandboxOptions } from "./monty-sandbox.ts";
15
+ /** Options for one Databricks-backed Mastra sandbox. */
16
+ export interface DatabricksSandboxOptions {
17
+ /** AppKit workspace client used for every sandbox API call. */
18
+ client: WorkspaceClient;
19
+ /** Resource id, with or without the `sandboxes/` prefix. */
20
+ sandboxId: string;
21
+ /** Human-readable Databricks label. */
22
+ displayName?: string;
23
+ /** Server-side idle timeout in protobuf duration form. Defaults to `900s`. */
24
+ inactivityTimeout?: string;
25
+ /** Maximum time to wait for the sandbox to become runnable. */
26
+ startupTimeoutMs?: number;
27
+ /** Default command timeout. Per-call `options.timeout` wins. */
28
+ commandTimeoutMs?: number;
29
+ /**
30
+ * Provider used only when Databricks Sandbox is definitively unavailable.
31
+ * Defaults to the Node Pydantic Monty runtime; `false` fails instead.
32
+ */
33
+ fallback?: false | "monty" | MontySandboxOptions | WorkspaceSandbox;
34
+ }
35
+ /** Databricks options accepted by the higher-level workspace factory. */
36
+ export interface DatabricksWorkspaceSandboxOptions extends Omit<DatabricksSandboxOptions, "client" | "sandboxId"> {
37
+ /** Provider discriminator. Defaults to `databricks`. */
38
+ provider?: "databricks";
39
+ /**
40
+ * Credential source. Defaults to a fresh AppKit client using the normal
41
+ * environment/profile chain, which is the app service principal in a
42
+ * Databricks App.
43
+ */
44
+ client?: WorkspaceClient | ((context: {
45
+ requestContext: RequestContext;
46
+ }) => WorkspaceClient);
47
+ /**
48
+ * Fixed id or per-request resolver. Omit to derive a stable, opaque id from
49
+ * the workspace and attributed user.
50
+ */
51
+ sandboxId?: string | ((context: {
52
+ requestContext: RequestContext;
53
+ }) => string);
54
+ }
55
+ /** Mastra sandbox backed by Databricks serverless Sandbox compute. */
56
+ export declare class DatabricksSandbox implements WorkspaceSandbox {
57
+ readonly id: string;
58
+ readonly name: string;
59
+ status: ProviderStatus;
60
+ error?: string;
61
+ private readonly client;
62
+ private readonly displayName;
63
+ private readonly inactivityTimeout;
64
+ private readonly startupTimeoutMs;
65
+ private readonly commandTimeoutMs;
66
+ private readonly fallbackConfig;
67
+ private readonly createdAt;
68
+ private remoteCreatedAt?;
69
+ private lastUsedAt?;
70
+ private activeFallback?;
71
+ private startPromise?;
72
+ constructor(options: DatabricksSandboxOptions);
73
+ get provider(): string;
74
+ /** Ensure the remote sandbox exists and has reached its running state. */
75
+ start(): Promise<void>;
76
+ private startWithSignal;
77
+ private performStart;
78
+ /** Databricks home persistence is not a cloneable Mastra checkpoint. */
79
+ snapshot(): Promise<void>;
80
+ get supportsCheckpoints(): boolean;
81
+ /** Stop compute while preserving the sandbox home directory. */
82
+ stop(): Promise<void>;
83
+ /** Permanently delete the sandbox and its persisted home directory. */
84
+ destroy(): Promise<void>;
85
+ /** Execute one foreground shell command in the remote sandbox. */
86
+ executeCommand(command: string, args?: string[], options?: ExecuteCommandOptions): Promise<CommandResult>;
87
+ /** Whether the adapter currently knows the remote sandbox to be running. */
88
+ isReady(): Promise<boolean>;
89
+ /** Report Mastra-facing sandbox metadata. */
90
+ getInfo(): Promise<SandboxInfo>;
91
+ /** Explain the Databricks execution boundary to the agent. */
92
+ getInstructions(): string;
93
+ private get resourcePath();
94
+ private getOrCreate;
95
+ private get;
96
+ private mutate;
97
+ private waitForState;
98
+ private rememberCreatedAt;
99
+ private request;
100
+ }