@dbx-tools/appkit-mastra 0.6.10 → 0.6.12
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 +29 -32
- package/index.ts +2 -3
- package/lib/index.d.ts +2 -3
- package/lib/index.js +2 -2
- package/lib/src/config.d.ts +0 -21
- package/lib/src/config.js +2 -6
- package/lib/src/plugin.js +2 -14
- package/lib/src/remote-skills.d.ts +41 -20
- package/lib/src/remote-skills.js +127 -32
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -13
- package/src/config.ts +1 -28
- package/src/plugin.ts +1 -14
- package/src/remote-skills.ts +191 -52
- package/lib/src/databricks-aitools.d.ts +0 -73
- package/lib/src/databricks-aitools.js +0 -152
- package/src/databricks-aitools.ts +0 -216
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Startup provisioning of Databricks AI Tools skills for a Mastra workspace.
|
|
3
|
-
*
|
|
4
|
-
* Databricks AI Tools (`databricks aitools`) are Databricks-owned Agent-Skill
|
|
5
|
-
* (`SKILL.md`) trees installed and kept up to date through the Databricks CLI.
|
|
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.
|
|
12
|
-
*
|
|
13
|
-
* The option is `false | true | "auto" | DatabricksAIToolsOptions`:
|
|
14
|
-
*
|
|
15
|
-
* - `false` (default) - off.
|
|
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.
|
|
23
|
-
*
|
|
24
|
-
* @module
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
import { existsSync } from "node:fs";
|
|
28
|
-
import { exec } from "@dbx-tools/core";
|
|
29
|
-
import { localFS } from "@dbx-tools/fs";
|
|
30
|
-
import { error, log, string } from "@dbx-tools/shared-core";
|
|
31
|
-
|
|
32
|
-
const logger = log.logger("mastra/databricks-aitools");
|
|
33
|
-
|
|
34
|
-
/** The Databricks CLI binary name; resolved on `PATH`. */
|
|
35
|
-
const DATABRICKS_CLI = "databricks";
|
|
36
|
-
|
|
37
|
-
/** Stable temp directory the CLI's skill tree is rebuilt into each boot. */
|
|
38
|
-
const SKILLS_CACHE_DIR = "databricks-aitools";
|
|
39
|
-
|
|
40
|
-
/* -------------------------------- types -------------------------------- */
|
|
41
|
-
|
|
42
|
-
/** How aggressively to enable Databricks AI Tools skills. */
|
|
43
|
-
export type DatabricksAIToolsMode = "auto" | "require";
|
|
44
|
-
|
|
45
|
-
/** Options for {@link provisionDatabricksAITools}. */
|
|
46
|
-
export interface DatabricksAIToolsOptions {
|
|
47
|
-
/**
|
|
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.
|
|
50
|
-
*/
|
|
51
|
-
mode?: DatabricksAIToolsMode;
|
|
52
|
-
/** Install only these skill names (comma/space list or array). */
|
|
53
|
-
skills?: string | string[];
|
|
54
|
-
/** Include experimental skills when the CLI has to fetch. */
|
|
55
|
-
experimental?: boolean;
|
|
56
|
-
/**
|
|
57
|
-
* Explicit directory to materialize skills into with the CLI. Defaults to a
|
|
58
|
-
* fresh {@link localFS.tmpFS} root.
|
|
59
|
-
*/
|
|
60
|
-
path?: string;
|
|
61
|
-
/** Absolute path to the `databricks` CLI. Defaults to `databricks` on PATH. */
|
|
62
|
-
cli?: string;
|
|
63
|
-
/**
|
|
64
|
-
* Fail app startup when required skills can't be provisioned. Defaults to
|
|
65
|
-
* `true` for `mode: "require"` and `false` for `"auto"`.
|
|
66
|
-
*/
|
|
67
|
-
failOnError?: boolean;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/** The `databricksAITools` config option: a toggle, `"auto"`, or an options bag. */
|
|
71
|
-
export type DatabricksAIToolsOption = boolean | "auto" | DatabricksAIToolsOptions;
|
|
72
|
-
|
|
73
|
-
/** What {@link provisionDatabricksAITools} resolved. */
|
|
74
|
-
export interface ProvisionedDatabricksAITools {
|
|
75
|
-
/** Extra LOCAL skill scan paths to hand Mastra. Empty when disabled/unresolved. */
|
|
76
|
-
localSkillPaths: string[];
|
|
77
|
-
/** How the skills were sourced, for logging. */
|
|
78
|
-
source?: "cli";
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/* ------------------------------- helpers ------------------------------- */
|
|
82
|
-
|
|
83
|
-
/** Normalize the `databricksAITools` option into a flat options bag, or `undefined` when off. */
|
|
84
|
-
export function normalizeDatabricksAIToolsOption(
|
|
85
|
-
option: DatabricksAIToolsOption | undefined,
|
|
86
|
-
): DatabricksAIToolsOptions | undefined {
|
|
87
|
-
if (option === undefined || option === false) return undefined;
|
|
88
|
-
if (option === true) return { mode: "require" };
|
|
89
|
-
if (option === "auto") return { mode: "auto" };
|
|
90
|
-
return { mode: option.mode ?? "auto", ...option };
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Materialize Databricks AI Tools skills at app startup and return them as
|
|
95
|
-
* extra local skill scan paths.
|
|
96
|
-
*
|
|
97
|
-
* Resolution: reuse the installed global tree when present (no CLI call) unless
|
|
98
|
-
* `refresh`/`skills`/`path` ask for a fresh CLI materialization; otherwise run
|
|
99
|
-
* `databricks aitools install --path <dir> --skills-only` when the CLI resolves.
|
|
100
|
-
* A `"require"` provision that yields nothing fails startup unless
|
|
101
|
-
* `failOnError: false`.
|
|
102
|
-
*/
|
|
103
|
-
export async function provisionDatabricksAITools(
|
|
104
|
-
option: DatabricksAIToolsOption | undefined,
|
|
105
|
-
): Promise<ProvisionedDatabricksAITools> {
|
|
106
|
-
const options = normalizeDatabricksAIToolsOption(option);
|
|
107
|
-
const empty: ProvisionedDatabricksAITools = { localSkillPaths: [] };
|
|
108
|
-
if (!options) return empty;
|
|
109
|
-
|
|
110
|
-
const mode = options.mode ?? "auto";
|
|
111
|
-
const failOnError = options.failOnError ?? mode === "require";
|
|
112
|
-
|
|
113
|
-
try {
|
|
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.
|
|
117
|
-
const cliPath = await resolveCli(options.cli);
|
|
118
|
-
if (cliPath) {
|
|
119
|
-
const dir = await materializeViaCli(cliPath, options);
|
|
120
|
-
if (dir) return { localSkillPaths: [dir], source: "cli" };
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// CLI not installed (or produced nothing). "auto" logs and moves on;
|
|
124
|
-
// "require" fails startup unless `failOnError: false`.
|
|
125
|
-
if (failOnError) {
|
|
126
|
-
throw new Error(
|
|
127
|
-
`Databricks AI Tools required but the "${DATABRICKS_CLI}" CLI is not available. Install the Databricks CLI (\`databricks aitools install\`), or set databricksAITools: "auto".`,
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
logger.info("databricks CLI not available; skipping AI Tools skills");
|
|
131
|
-
return empty;
|
|
132
|
-
} catch (err) {
|
|
133
|
-
if (failOnError) {
|
|
134
|
-
throw new Error(
|
|
135
|
-
`failed to provision Databricks AI Tools skills: ${error.errorMessage(err)}`,
|
|
136
|
-
{ cause: error.toError(err) },
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
logger.warn("skipped", { error: error.errorMessage(err) });
|
|
140
|
-
return empty;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/** Resolve the `databricks` CLI, returning its invocation path or `undefined`. */
|
|
145
|
-
async function resolveCli(cli: string | undefined): Promise<string | undefined> {
|
|
146
|
-
const command = string.trimToNull(cli) ?? DATABRICKS_CLI;
|
|
147
|
-
try {
|
|
148
|
-
const result = await exec.spawn(command, ["aitools", "version"], {
|
|
149
|
-
stdout: "capture",
|
|
150
|
-
stderr: "capture",
|
|
151
|
-
check: false,
|
|
152
|
-
});
|
|
153
|
-
if (result.exitCode === 0) return command;
|
|
154
|
-
} catch {
|
|
155
|
-
// CLI absent or `aitools` unsupported - caller falls back / fails.
|
|
156
|
-
}
|
|
157
|
-
return undefined;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
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.
|
|
164
|
-
*/
|
|
165
|
-
async function materializeViaCli(
|
|
166
|
-
cli: string,
|
|
167
|
-
options: DatabricksAIToolsOptions,
|
|
168
|
-
): Promise<string | undefined> {
|
|
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];
|
|
202
|
-
const skills = string.parseList(options.skills);
|
|
203
|
-
if (skills.length > 0) args.push("--skills", skills.join(","));
|
|
204
|
-
if (options.experimental) args.push("--experimental");
|
|
205
|
-
|
|
206
|
-
const result = await exec.spawn(cli, args, {
|
|
207
|
-
stdout: "capture",
|
|
208
|
-
stderr: "capture",
|
|
209
|
-
check: false,
|
|
210
|
-
});
|
|
211
|
-
if (result.exitCode !== 0) {
|
|
212
|
-
throw new Error(
|
|
213
|
-
`databricks aitools install failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`,
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
}
|