@dbx-tools/appkit-mastra 0.6.9 → 0.6.10
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 +21 -20
- package/index.ts +12 -27
- package/lib/index.d.ts +12 -27
- package/lib/index.js +12 -27
- package/lib/src/config.d.ts +8 -9
- package/lib/src/config.js +2 -2
- package/lib/src/databricks-aitools.d.ts +17 -27
- package/lib/src/databricks-aitools.js +56 -54
- package/lib/src/filesystems.d.ts +52 -170
- package/lib/src/filesystems.js +168 -888
- package/lib/src/plugin.js +2 -2
- package/lib/src/remote-skills.d.ts +4 -4
- package/lib/src/remote-skills.js +63 -35
- package/lib/src/workspaces.d.ts +4 -0
- package/lib/src/workspaces.js +37 -13
- package/package.json +13 -10
- package/src/config.ts +9 -10
- package/src/databricks-aitools.ts +67 -67
- package/src/filesystems.ts +225 -970
- package/src/plugin.ts +1 -1
- package/src/remote-skills.ts +69 -38
- package/src/workspaces.ts +41 -16
package/src/config.ts
CHANGED
|
@@ -23,10 +23,10 @@ import { MASTRA_RESOURCE_ID_KEY, MASTRA_THREAD_ID_KEY } from "@mastra/core/reque
|
|
|
23
23
|
import type { PgVectorConfig, PostgresStoreConfig } from "@mastra/pg";
|
|
24
24
|
|
|
25
25
|
import type { MastraAgentDefinition, MastraTools } from "./agents.ts";
|
|
26
|
+
import type { DatabricksAIToolsOption } from "./databricks-aitools.ts";
|
|
26
27
|
import type { GenieSpacesConfig } from "./genie.ts";
|
|
27
28
|
import type { MastraIdentityMode } from "./identity.ts";
|
|
28
29
|
import type { RemoteSkillsOption } from "./remote-skills.ts";
|
|
29
|
-
import type { DatabricksAIToolsOption } from "./databricks-aitools.ts";
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* `RequestContext` key under which {@link MastraServer} stores the
|
|
@@ -586,15 +586,14 @@ export interface MastraPluginConfig extends BasePluginConfig {
|
|
|
586
586
|
* Fold Databricks AI Tools skills (`databricks aitools`) into every
|
|
587
587
|
* default-workspace agent as extra local skill scan paths.
|
|
588
588
|
*
|
|
589
|
-
* `false` (default) off; `"auto"`
|
|
590
|
-
*
|
|
591
|
-
*
|
|
592
|
-
*
|
|
593
|
-
* `experimental` skills, `refresh` from the CLI, or set an explicit `path`.
|
|
589
|
+
* `false` (default) off; `"auto"` runs the `databricks` CLI when it's
|
|
590
|
+
* installed and logs-and-continues when it isn't (never fails startup);
|
|
591
|
+
* `true` requires the CLI and fails startup otherwise. Pass an options bag to
|
|
592
|
+
* select `skills`, include `experimental` skills, or set an explicit `path`.
|
|
594
593
|
*
|
|
595
|
-
*
|
|
596
|
-
*
|
|
597
|
-
*
|
|
594
|
+
* Runs `databricks aitools install --path <dir>` to materialize a resolved,
|
|
595
|
+
* agent-agnostic set (`<name>/SKILL.md` trees) into a temp dir the agents
|
|
596
|
+
* then scan. The CLI is the source of truth.
|
|
598
597
|
*
|
|
599
598
|
* @example
|
|
600
599
|
* ```ts
|
|
@@ -629,7 +628,7 @@ export const MASTRA_CONFIG_SCHEMA: ConfigSchema = {
|
|
|
629
628
|
databricksAITools: {
|
|
630
629
|
type: ["boolean", "string", "object"],
|
|
631
630
|
description:
|
|
632
|
-
'Fold Databricks AI Tools skills (databricks aitools) into agents as extra local skill paths. false (default) off; "auto"
|
|
631
|
+
'Fold Databricks AI Tools skills (databricks aitools) into agents as extra local skill paths. false (default) off; "auto" runs the databricks CLI when installed and logs-and-continues otherwise; true requires the CLI and fails startup otherwise. An object selects skills, experimental, or path.',
|
|
633
632
|
},
|
|
634
633
|
storage: {
|
|
635
634
|
type: ["boolean", "object"],
|
|
@@ -3,47 +3,40 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Databricks AI Tools (`databricks aitools`) are Databricks-owned Agent-Skill
|
|
5
5
|
* (`SKILL.md`) trees installed and kept up to date through the Databricks CLI.
|
|
6
|
-
*
|
|
7
|
-
* (
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* as extra LOCAL skill scan paths so an agent can use them without anyone
|
|
13
|
-
* hand-copying `SKILL.md` files. It never reimplements the CLI's sourcing: it
|
|
14
|
-
* either points Mastra at the already-installed global tree, or shells out to
|
|
15
|
-
* the CLI to materialize a curated subset into a temp dir.
|
|
6
|
+
* {@link provisionDatabricksAITools} shells out to the CLI
|
|
7
|
+
* (`databricks aitools install --path <dir>`) to materialize a resolved,
|
|
8
|
+
* agent-agnostic skill set into a directory, then hands it to Mastra as an
|
|
9
|
+
* extra LOCAL skill scan path - so an agent gets first-class Databricks skills
|
|
10
|
+
* without anyone hand-copying `SKILL.md` files. It never reimplements the CLI's
|
|
11
|
+
* sourcing; the CLI is the source of truth.
|
|
16
12
|
*
|
|
17
13
|
* The option is `false | true | "auto" | DatabricksAIToolsOptions`:
|
|
18
14
|
*
|
|
19
15
|
* - `false` (default) - off.
|
|
20
|
-
* - `"auto"` -
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* - `true` -
|
|
24
|
-
*
|
|
25
|
-
* - an options bag for a specific `skills` subset, `experimental` skills,
|
|
26
|
-
*
|
|
27
|
-
* `path`.
|
|
16
|
+
* - `"auto"` - run the CLI when it's installed; if the `databricks` CLI isn't
|
|
17
|
+
* available, log and move on (never fails startup). The "on if the CLI is
|
|
18
|
+
* around" default.
|
|
19
|
+
* - `true` (`"require"`) - require the CLI: fail startup (subject to
|
|
20
|
+
* `failOnError`) when it isn't available or produces nothing.
|
|
21
|
+
* - an options bag for a specific `skills` subset, `experimental` skills, an
|
|
22
|
+
* explicit output `path`, or a custom `cli` path.
|
|
28
23
|
*
|
|
29
24
|
* @module
|
|
30
25
|
*/
|
|
31
26
|
|
|
32
|
-
import { mkdtemp } from "node:fs/promises";
|
|
33
27
|
import { existsSync } from "node:fs";
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import { spawn } from "@dbx-tools/core";
|
|
28
|
+
import { exec } from "@dbx-tools/core";
|
|
29
|
+
import { localFS } from "@dbx-tools/fs";
|
|
37
30
|
import { error, log, string } from "@dbx-tools/shared-core";
|
|
38
31
|
|
|
39
32
|
const logger = log.logger("mastra/databricks-aitools");
|
|
40
33
|
|
|
41
|
-
/** Global skills tree the `databricks aitools` CLI installs into. */
|
|
42
|
-
const GLOBAL_AITOOLS_SKILLS_PATH = join(homedir(), ".databricks", "aitools", "skills");
|
|
43
|
-
|
|
44
34
|
/** The Databricks CLI binary name; resolved on `PATH`. */
|
|
45
35
|
const DATABRICKS_CLI = "databricks";
|
|
46
36
|
|
|
37
|
+
/** Stable temp directory the CLI's skill tree is rebuilt into each boot. */
|
|
38
|
+
const SKILLS_CACHE_DIR = "databricks-aitools";
|
|
39
|
+
|
|
47
40
|
/* -------------------------------- types -------------------------------- */
|
|
48
41
|
|
|
49
42
|
/** How aggressively to enable Databricks AI Tools skills. */
|
|
@@ -52,22 +45,17 @@ export type DatabricksAIToolsMode = "auto" | "require";
|
|
|
52
45
|
/** Options for {@link provisionDatabricksAITools}. */
|
|
53
46
|
export interface DatabricksAIToolsOptions {
|
|
54
47
|
/**
|
|
55
|
-
* `"auto"` (default)
|
|
56
|
-
*
|
|
48
|
+
* `"auto"` (default) runs the CLI when installed and logs-and-continues when
|
|
49
|
+
* it isn't; `"require"` fails startup when the CLI can't supply skills.
|
|
57
50
|
*/
|
|
58
51
|
mode?: DatabricksAIToolsMode;
|
|
59
52
|
/** Install only these skill names (comma/space list or array). */
|
|
60
53
|
skills?: string | string[];
|
|
61
54
|
/** Include experimental skills when the CLI has to fetch. */
|
|
62
55
|
experimental?: boolean;
|
|
63
|
-
/**
|
|
64
|
-
* Re-run the CLI to (re)materialize skills into a fresh dir even when the
|
|
65
|
-
* global tree already exists. Defaults to `false` (reuse the installed tree).
|
|
66
|
-
*/
|
|
67
|
-
refresh?: boolean;
|
|
68
56
|
/**
|
|
69
57
|
* Explicit directory to materialize skills into with the CLI. Defaults to a
|
|
70
|
-
*
|
|
58
|
+
* fresh {@link localFS.tmpFS} root.
|
|
71
59
|
*/
|
|
72
60
|
path?: string;
|
|
73
61
|
/** Absolute path to the `databricks` CLI. Defaults to `databricks` on PATH. */
|
|
@@ -87,7 +75,7 @@ export interface ProvisionedDatabricksAITools {
|
|
|
87
75
|
/** Extra LOCAL skill scan paths to hand Mastra. Empty when disabled/unresolved. */
|
|
88
76
|
localSkillPaths: string[];
|
|
89
77
|
/** How the skills were sourced, for logging. */
|
|
90
|
-
source?: "
|
|
78
|
+
source?: "cli";
|
|
91
79
|
}
|
|
92
80
|
|
|
93
81
|
/* ------------------------------- helpers ------------------------------- */
|
|
@@ -121,36 +109,25 @@ export async function provisionDatabricksAITools(
|
|
|
121
109
|
|
|
122
110
|
const mode = options.mode ?? "auto";
|
|
123
111
|
const failOnError = options.failOnError ?? mode === "require";
|
|
124
|
-
const wantsCliFetch =
|
|
125
|
-
options.refresh === true ||
|
|
126
|
-
options.path !== undefined ||
|
|
127
|
-
string.parseList(options.skills).length > 0 ||
|
|
128
|
-
options.experimental === true;
|
|
129
112
|
|
|
130
113
|
try {
|
|
131
|
-
//
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
return { localSkillPaths: [GLOBAL_AITOOLS_SKILLS_PATH], source: "installed" };
|
|
135
|
-
}
|
|
136
|
-
|
|
114
|
+
// The `databricks` CLI is the source of truth. When it's resolvable, run
|
|
115
|
+
// `databricks aitools install --path <dir>` to materialize a fresh,
|
|
116
|
+
// agent-agnostic skill set into a dir Mastra can scan.
|
|
137
117
|
const cliPath = await resolveCli(options.cli);
|
|
138
118
|
if (cliPath) {
|
|
139
119
|
const dir = await materializeViaCli(cliPath, options);
|
|
140
120
|
if (dir) return { localSkillPaths: [dir], source: "cli" };
|
|
141
121
|
}
|
|
142
122
|
|
|
143
|
-
//
|
|
144
|
-
|
|
145
|
-
return { localSkillPaths: [GLOBAL_AITOOLS_SKILLS_PATH], source: "installed" };
|
|
146
|
-
}
|
|
147
|
-
|
|
123
|
+
// CLI not installed (or produced nothing). "auto" logs and moves on;
|
|
124
|
+
// "require" fails startup unless `failOnError: false`.
|
|
148
125
|
if (failOnError) {
|
|
149
126
|
throw new Error(
|
|
150
|
-
`Databricks AI Tools
|
|
127
|
+
`Databricks AI Tools required but the "${DATABRICKS_CLI}" CLI is not available. Install the Databricks CLI (\`databricks aitools install\`), or set databricksAITools: "auto".`,
|
|
151
128
|
);
|
|
152
129
|
}
|
|
153
|
-
logger.
|
|
130
|
+
logger.info("databricks CLI not available; skipping AI Tools skills");
|
|
154
131
|
return empty;
|
|
155
132
|
} catch (err) {
|
|
156
133
|
if (failOnError) {
|
|
@@ -164,16 +141,11 @@ export async function provisionDatabricksAITools(
|
|
|
164
141
|
}
|
|
165
142
|
}
|
|
166
143
|
|
|
167
|
-
/** Whether the CLI's global skills tree exists and holds at least one skill. */
|
|
168
|
-
function installedTreeExists(): boolean {
|
|
169
|
-
return existsSync(GLOBAL_AITOOLS_SKILLS_PATH);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
144
|
/** Resolve the `databricks` CLI, returning its invocation path or `undefined`. */
|
|
173
145
|
async function resolveCli(cli: string | undefined): Promise<string | undefined> {
|
|
174
146
|
const command = string.trimToNull(cli) ?? DATABRICKS_CLI;
|
|
175
147
|
try {
|
|
176
|
-
const result = await spawn(command, ["aitools", "version"], {
|
|
148
|
+
const result = await exec.spawn(command, ["aitools", "version"], {
|
|
177
149
|
stdout: "capture",
|
|
178
150
|
stderr: "capture",
|
|
179
151
|
check: false,
|
|
@@ -186,21 +158,52 @@ async function resolveCli(cli: string | undefined): Promise<string | undefined>
|
|
|
186
158
|
}
|
|
187
159
|
|
|
188
160
|
/**
|
|
189
|
-
* Run `databricks aitools install --path <dir
|
|
190
|
-
*
|
|
161
|
+
* Run `databricks aitools install --path <dir>` to materialize a resolved,
|
|
162
|
+
* agent-agnostic skill set into a directory (writes `<name>/SKILL.md` trees,
|
|
163
|
+
* no agents, no state) Mastra can then scan.
|
|
191
164
|
*/
|
|
192
165
|
async function materializeViaCli(
|
|
193
166
|
cli: string,
|
|
194
167
|
options: DatabricksAIToolsOptions,
|
|
195
168
|
): Promise<string | undefined> {
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
169
|
+
const explicit = string.trimToNull(options.path);
|
|
170
|
+
let dir: string;
|
|
171
|
+
|
|
172
|
+
if (explicit) {
|
|
173
|
+
// An explicit path is the caller's to own - install straight into it.
|
|
174
|
+
await installSkills(cli, options, explicit);
|
|
175
|
+
dir = explicit;
|
|
176
|
+
} else {
|
|
177
|
+
// The resolved skill set is the same on almost every boot, so rebuild ONE
|
|
178
|
+
// stable temp tree rather than leaving a fresh scratch dir behind each
|
|
179
|
+
// time. The CLI writes into a throwaway root that only replaces the stable
|
|
180
|
+
// one on success, so a failed install keeps the previous skills usable.
|
|
181
|
+
const stable = await localFS.rebuildFS(SKILLS_CACHE_DIR, (scratch) =>
|
|
182
|
+
installSkills(cli, options, scratch.root),
|
|
183
|
+
);
|
|
184
|
+
dir = stable.root;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (!existsSync(dir)) return undefined;
|
|
188
|
+
logger.debug("materialized aitools skills via CLI", {
|
|
189
|
+
path: dir,
|
|
190
|
+
skills: string.parseList(options.skills),
|
|
191
|
+
});
|
|
192
|
+
return dir;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** Run `databricks aitools install --path <dir>`, failing loudly on a non-zero exit. */
|
|
196
|
+
async function installSkills(
|
|
197
|
+
cli: string,
|
|
198
|
+
options: DatabricksAIToolsOptions,
|
|
199
|
+
dir: string,
|
|
200
|
+
): Promise<void> {
|
|
201
|
+
const args = ["aitools", "install", "--path", dir];
|
|
199
202
|
const skills = string.parseList(options.skills);
|
|
200
203
|
if (skills.length > 0) args.push("--skills", skills.join(","));
|
|
201
204
|
if (options.experimental) args.push("--experimental");
|
|
202
205
|
|
|
203
|
-
const result = await spawn(cli, args, {
|
|
206
|
+
const result = await exec.spawn(cli, args, {
|
|
204
207
|
stdout: "capture",
|
|
205
208
|
stderr: "capture",
|
|
206
209
|
check: false,
|
|
@@ -210,7 +213,4 @@ async function materializeViaCli(
|
|
|
210
213
|
`databricks aitools install failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`,
|
|
211
214
|
);
|
|
212
215
|
}
|
|
213
|
-
if (!existsSync(dir)) return undefined;
|
|
214
|
-
logger.debug("materialized aitools skills via CLI", { path: dir, skills });
|
|
215
|
-
return dir;
|
|
216
216
|
}
|