@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.
- package/README.md +96 -4
- package/index.ts +9 -3
- package/lib/index.d.ts +9 -3
- package/lib/index.js +6 -2
- package/lib/src/agents.d.ts +4 -3
- package/lib/src/agents.js +10 -5
- package/lib/src/config.d.ts +8 -0
- package/lib/src/config.js +5 -1
- package/lib/src/model.d.ts +2 -0
- package/lib/src/model.js +21 -22
- package/lib/src/monty-sandbox.d.ts +51 -0
- package/lib/src/monty-sandbox.js +331 -0
- package/lib/src/plugin.d.ts +1 -1
- package/lib/src/sandbox.d.ts +100 -0
- package/lib/src/sandbox.js +418 -0
- package/lib/src/serving-sanitize.d.ts +18 -1
- package/lib/src/serving-sanitize.js +41 -3
- package/lib/src/workspaces.d.ts +19 -6
- package/lib/src/workspaces.js +70 -7
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +23 -22
- package/src/agents.ts +13 -5
- package/src/config.ts +13 -0
- package/src/model.ts +21 -23
- package/src/monty-sandbox.ts +406 -0
- package/src/sandbox.ts +515 -0
- package/src/serving-sanitize.ts +50 -2
- package/src/workspaces.ts +105 -6
package/src/workspaces.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Mastra workspace factory for Databricks Apps.
|
|
3
3
|
*
|
|
4
|
-
* Builds a per-request {@link Workspace}
|
|
5
|
-
* {@link CompositeFilesystem} over the NAMED skill folders
|
|
6
|
-
* request. A skill folder maps a name to a location plus its
|
|
7
|
-
* writable policy: a Databricks path mounted through the OBO client
|
|
8
|
-
* {@link MASTRA_USER_KEY}, or any {@link WorkspaceFilesystem} a consuming
|
|
4
|
+
* Builds a per-request {@link Workspace} with Databricks Sandbox command
|
|
5
|
+
* execution plus a {@link CompositeFilesystem} over the NAMED skill folders
|
|
6
|
+
* resolved for that request. A skill folder maps a name to a location plus its
|
|
7
|
+
* readable / writable policy: a Databricks path mounted through the OBO client
|
|
8
|
+
* on {@link MASTRA_USER_KEY}, or any {@link WorkspaceFilesystem} a consuming
|
|
9
9
|
* library already owns. {@link DEFAULT_SKILL_FOLDERS} supplies the Assistant
|
|
10
10
|
* trees, and `skillFolders` merges over it - same name overrides, `false`
|
|
11
11
|
* disables, a new name adds. Optional mount resolvers contribute further
|
|
@@ -18,9 +18,11 @@
|
|
|
18
18
|
* @module
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
+
import { createHash } from "node:crypto";
|
|
22
|
+
import { ConfigurationError, createWorkspaceClient } from "@databricks/appkit";
|
|
21
23
|
import type { WorkspaceClient } from "@databricks/appkit";
|
|
22
24
|
import { DatabricksFileSystem, workspace as databricksWorkspace } from "@dbx-tools/databricks";
|
|
23
|
-
import { error, log, string, token } from "@dbx-tools/shared-core";
|
|
25
|
+
import { error, log, object, string, token } from "@dbx-tools/shared-core";
|
|
24
26
|
import type { RequestContext } from "@mastra/core/request-context";
|
|
25
27
|
import {
|
|
26
28
|
CompositeFilesystem,
|
|
@@ -28,10 +30,14 @@ import {
|
|
|
28
30
|
type SkillsContext,
|
|
29
31
|
type SkillsResolver,
|
|
30
32
|
type WorkspaceFilesystem,
|
|
33
|
+
type WorkspaceSandbox,
|
|
34
|
+
type WorkspaceSandboxResolver,
|
|
31
35
|
} from "@mastra/core/workspace";
|
|
32
36
|
|
|
33
37
|
import { MASTRA_SCOPES_KEY, MASTRA_USER_EMAIL_KEY, MASTRA_USER_KEY, type User } from "./config.ts";
|
|
34
38
|
import { scratchFilesystem, filesystems } from "./filesystems.ts";
|
|
39
|
+
import { MontySandbox } from "./monty-sandbox.ts";
|
|
40
|
+
import { DatabricksSandbox, type DatabricksWorkspaceSandboxOptions } from "./sandbox.ts";
|
|
35
41
|
import { ASSISTANT_SHARED_SKILLS_PATH, userAssistantSkillsPath } from "./skill-paths.ts";
|
|
36
42
|
|
|
37
43
|
/* ------------------------------ constants ------------------------------ */
|
|
@@ -97,6 +103,19 @@ export type WorkspaceMountResolver = (
|
|
|
97
103
|
/** Names carried by {@link DEFAULT_SKILL_FOLDERS}. */
|
|
98
104
|
export type DefaultSkillFolderName = "workspace-team" | "workspace-team-app";
|
|
99
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Sandbox selection for {@link createWorkspace}. Databricks is the default;
|
|
108
|
+
* `false` disables command execution, and a Mastra provider or resolver is an
|
|
109
|
+
* explicit replacement.
|
|
110
|
+
*/
|
|
111
|
+
export type WorkspaceSandboxSelection =
|
|
112
|
+
| false
|
|
113
|
+
| "databricks"
|
|
114
|
+
| "monty"
|
|
115
|
+
| DatabricksWorkspaceSandboxOptions
|
|
116
|
+
| WorkspaceSandbox
|
|
117
|
+
| WorkspaceSandboxResolver;
|
|
118
|
+
|
|
100
119
|
/** Options for {@link createWorkspace}. */
|
|
101
120
|
export interface CreateWorkspaceOptions {
|
|
102
121
|
/** Workspace id; derived from `name` or `"workspace"` when omitted. */
|
|
@@ -122,6 +141,12 @@ export interface CreateWorkspaceOptions {
|
|
|
122
141
|
checkSkillFileMtime?: boolean;
|
|
123
142
|
/** Enable BM25 keyword search over indexed workspace content. */
|
|
124
143
|
bm25?: boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Command sandbox. Defaults to Databricks Sandbox. Pass `false` to disable
|
|
146
|
+
* command execution, or an explicit Mastra sandbox/provider resolver to
|
|
147
|
+
* replace Databricks for this workspace.
|
|
148
|
+
*/
|
|
149
|
+
sandbox?: WorkspaceSandboxSelection;
|
|
125
150
|
/**
|
|
126
151
|
* Extra LOCAL skill scan paths added to every request's skill discovery.
|
|
127
152
|
* Used by the plugin to surface remote skills provisioned to a local temp
|
|
@@ -204,6 +229,7 @@ export function createWorkspace(options: CreateWorkspaceOptions = {}): Workspace
|
|
|
204
229
|
: undefined);
|
|
205
230
|
const checkSkillFileMtime = options.checkSkillFileMtime ?? folderNames.length > 0;
|
|
206
231
|
const bm25 = options.bm25 !== false;
|
|
232
|
+
const sandbox = resolveWorkspaceSandbox(options.sandbox, id, name);
|
|
207
233
|
logger.debug("workspace:create", {
|
|
208
234
|
id,
|
|
209
235
|
name,
|
|
@@ -214,6 +240,7 @@ export function createWorkspace(options: CreateWorkspaceOptions = {}): Workspace
|
|
|
214
240
|
checkSkillFileMtime,
|
|
215
241
|
bm25,
|
|
216
242
|
extraSkillPaths: extraSkillPaths.length,
|
|
243
|
+
sandbox: sandbox ? sandboxName(options.sandbox) : "disabled",
|
|
217
244
|
});
|
|
218
245
|
|
|
219
246
|
return new Workspace({
|
|
@@ -226,6 +253,12 @@ export function createWorkspace(options: CreateWorkspaceOptions = {}): Workspace
|
|
|
226
253
|
checkSkillFileMtime,
|
|
227
254
|
}
|
|
228
255
|
: {}),
|
|
256
|
+
...(sandbox
|
|
257
|
+
? {
|
|
258
|
+
sandbox,
|
|
259
|
+
instructions: { dynamicSandbox: "resolve" as const },
|
|
260
|
+
}
|
|
261
|
+
: {}),
|
|
229
262
|
bm25,
|
|
230
263
|
});
|
|
231
264
|
}
|
|
@@ -253,6 +286,72 @@ export function resolveSkillFolders(
|
|
|
253
286
|
|
|
254
287
|
/* ---------------------------- private helpers ---------------------------- */
|
|
255
288
|
|
|
289
|
+
function resolveWorkspaceSandbox(
|
|
290
|
+
selection: WorkspaceSandboxSelection | undefined,
|
|
291
|
+
workspaceId: string,
|
|
292
|
+
workspaceName: string,
|
|
293
|
+
): WorkspaceSandbox | WorkspaceSandboxResolver | undefined {
|
|
294
|
+
const configured = selection ?? "databricks";
|
|
295
|
+
if (configured === false) return undefined;
|
|
296
|
+
if (configured === "monty") return new MontySandbox();
|
|
297
|
+
if (typeof configured === "function" || isSandbox(configured)) return configured;
|
|
298
|
+
|
|
299
|
+
const options: DatabricksWorkspaceSandboxOptions =
|
|
300
|
+
configured === "databricks" ? { provider: "databricks" } : configured;
|
|
301
|
+
return ({ requestContext }) => {
|
|
302
|
+
const user = requestContext.get(MASTRA_USER_KEY) as User | undefined;
|
|
303
|
+
if (!user) {
|
|
304
|
+
throw ConfigurationError.resourceNotFound(
|
|
305
|
+
"Databricks sandbox user context",
|
|
306
|
+
"Invoke command tools from an agent turn served by the Mastra plugin.",
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
const configuredId =
|
|
310
|
+
typeof options.sandboxId === "function"
|
|
311
|
+
? options.sandboxId({ requestContext })
|
|
312
|
+
: options.sandboxId;
|
|
313
|
+
const sandboxId = configuredId ?? defaultSandboxId(workspaceId, user.id);
|
|
314
|
+
const client =
|
|
315
|
+
typeof options.client === "function"
|
|
316
|
+
? options.client({ requestContext })
|
|
317
|
+
: (options.client ?? createWorkspaceClient());
|
|
318
|
+
const {
|
|
319
|
+
provider: _provider,
|
|
320
|
+
sandboxId: _sandboxId,
|
|
321
|
+
client: _client,
|
|
322
|
+
...sandboxOptions
|
|
323
|
+
} = options;
|
|
324
|
+
return new DatabricksSandbox({
|
|
325
|
+
...sandboxOptions,
|
|
326
|
+
client,
|
|
327
|
+
sandboxId,
|
|
328
|
+
displayName: options.displayName ?? `Mastra ${workspaceName}`,
|
|
329
|
+
});
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function defaultSandboxId(workspaceId: string, userId: string): string {
|
|
334
|
+
const digest = createHash("sha256")
|
|
335
|
+
.update(object.toStableKey({ workspaceId, userId }))
|
|
336
|
+
.digest("hex")
|
|
337
|
+
.slice(0, 32);
|
|
338
|
+
return `mastra-${digest}`;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function isSandbox(value: unknown): value is WorkspaceSandbox {
|
|
342
|
+
return Boolean(
|
|
343
|
+
value && typeof value === "object" && "id" in value && "provider" in value && "status" in value,
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function sandboxName(selection: WorkspaceSandboxSelection | undefined): string {
|
|
348
|
+
if (selection === undefined || selection === "databricks") return "databricks";
|
|
349
|
+
if (selection === "monty") return "monty";
|
|
350
|
+
if (selection === false) return "disabled";
|
|
351
|
+
if (typeof selection === "function") return "resolver";
|
|
352
|
+
return isSandbox(selection) ? selection.provider : (selection.provider ?? "databricks");
|
|
353
|
+
}
|
|
354
|
+
|
|
256
355
|
/**
|
|
257
356
|
* Return whether the request token carries a scope that allows workspace
|
|
258
357
|
* file API access (`workspace` or `all-apis` on {@link MASTRA_SCOPES_KEY}).
|