@dbx-tools/appkit-mastra 0.9.74 → 0.9.93
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 +50 -42
- package/index.ts +6 -3
- package/lib/index.d.ts +6 -3
- package/lib/index.js +5 -3
- package/lib/src/agents.js +38 -5
- package/lib/src/config.d.ts +7 -7
- package/lib/src/config.js +4 -4
- package/lib/src/genie.js +9 -15
- package/lib/src/mlflow.js +5 -5
- package/lib/src/monty-sandbox.d.ts +4 -3
- package/lib/src/monty-sandbox.js +55 -18
- package/lib/src/remote-skills.js +26 -2
- package/lib/src/skill-cache.d.ts +80 -56
- package/lib/src/skill-cache.js +215 -158
- package/lib/src/skill-search.d.ts +30 -0
- package/lib/src/skill-search.js +171 -0
- package/lib/src/workspaces.d.ts +10 -5
- package/lib/src/workspaces.js +132 -117
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +26 -15
- package/src/agents.ts +39 -6
- package/src/config.ts +10 -10
- package/src/genie.ts +8 -13
- package/src/mlflow.ts +4 -4
- package/src/monty-sandbox.ts +62 -18
- package/src/remote-skills.ts +32 -1
- package/src/skill-cache.ts +278 -243
- package/src/skill-search.ts +203 -0
- package/src/workspaces.ts +177 -139
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* On-demand skill discovery backed by a materialized workspace catalogue.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { errorUtils } from "@dbx-tools/shared-core";
|
|
7
|
+
import { MASTRA_THREAD_ID_KEY } from "@mastra/core/request-context";
|
|
8
|
+
import { createTool } from "@mastra/core/tools";
|
|
9
|
+
import Fuse from "fuse.js";
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
const DEFAULT_STATE_TTL_MS = 60 * 60 * 1000;
|
|
12
|
+
/** Mastra-compatible search, load, and lazy-read tools over one cached catalogue. */
|
|
13
|
+
export class CatalogueSkillSearchProcessor {
|
|
14
|
+
id = "skill-catalogue-search";
|
|
15
|
+
name = "Skill Catalogue Search";
|
|
16
|
+
providesSkillDiscovery = "on-demand";
|
|
17
|
+
minScore;
|
|
18
|
+
resolve;
|
|
19
|
+
states = new Map();
|
|
20
|
+
topK;
|
|
21
|
+
ttlMs;
|
|
22
|
+
constructor(options) {
|
|
23
|
+
this.resolve = options.resolve;
|
|
24
|
+
this.topK = options.topK ?? 5;
|
|
25
|
+
this.minScore = options.minScore ?? 0.1;
|
|
26
|
+
this.ttlMs = options.ttlMs ?? DEFAULT_STATE_TTL_MS;
|
|
27
|
+
}
|
|
28
|
+
async processInputStep(args) {
|
|
29
|
+
const owner = await this.resolve(args);
|
|
30
|
+
const catalogue = await owner.get(args.abortSignal);
|
|
31
|
+
const state = this.threadState(args);
|
|
32
|
+
args.messageList.addSystem("To discover available skills, call search_skills with a keyword query. " +
|
|
33
|
+
"To load a skill's instructions, call load_skill with the exact skill name. " +
|
|
34
|
+
"Use skill_read only after loading a skill when its instructions require a reference, script, or asset.");
|
|
35
|
+
for (const [skillName, instructions] of state.skills) {
|
|
36
|
+
args.messageList.addSystem(`[Skill: ${skillName}]\n\n${instructions}`);
|
|
37
|
+
}
|
|
38
|
+
const search = new Fuse(catalogue.skills, {
|
|
39
|
+
includeScore: true,
|
|
40
|
+
ignoreLocation: true,
|
|
41
|
+
threshold: 1,
|
|
42
|
+
keys: [
|
|
43
|
+
{ name: "name", weight: 0.5 },
|
|
44
|
+
{ name: "description", weight: 0.35 },
|
|
45
|
+
{ name: "instructions", weight: 0.15 },
|
|
46
|
+
],
|
|
47
|
+
});
|
|
48
|
+
return {
|
|
49
|
+
tools: {
|
|
50
|
+
...(args.tools ?? {}),
|
|
51
|
+
search_skills: createTool({
|
|
52
|
+
id: "search_skills",
|
|
53
|
+
description: "Search for available skills by keyword. Load a useful result with load_skill.",
|
|
54
|
+
inputSchema: z.object({
|
|
55
|
+
query: z.string().trim().min(1, "Query is required").describe("Search keywords."),
|
|
56
|
+
}),
|
|
57
|
+
outputSchema: z.object({
|
|
58
|
+
results: z.array(z.object({
|
|
59
|
+
name: z.string(),
|
|
60
|
+
description: z.string(),
|
|
61
|
+
score: z.number(),
|
|
62
|
+
})),
|
|
63
|
+
message: z.string(),
|
|
64
|
+
}),
|
|
65
|
+
execute: async ({ query }) => {
|
|
66
|
+
const results = search
|
|
67
|
+
.search(query)
|
|
68
|
+
.map((result) => ({
|
|
69
|
+
name: result.item.name,
|
|
70
|
+
description: result.item.description.length > 150
|
|
71
|
+
? `${result.item.description.slice(0, 147)}...`
|
|
72
|
+
: result.item.description,
|
|
73
|
+
score: Math.round((1 - (result.score ?? 1)) * 100) / 100,
|
|
74
|
+
}))
|
|
75
|
+
.filter(({ score }) => score >= this.minScore)
|
|
76
|
+
.slice(0, this.topK);
|
|
77
|
+
return {
|
|
78
|
+
results,
|
|
79
|
+
message: results.length === 0
|
|
80
|
+
? `No skills found matching "${query}". Try different keywords.`
|
|
81
|
+
: `Found ${results.length} skill(s). Use load_skill with the exact skill name to load its instructions.`,
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
}),
|
|
85
|
+
load_skill: createTool({
|
|
86
|
+
id: "load_skill",
|
|
87
|
+
description: "Load a skill's full instructions into the conversation.",
|
|
88
|
+
inputSchema: z.object({
|
|
89
|
+
skillName: z.string().describe("Exact skill name returned by search_skills."),
|
|
90
|
+
}),
|
|
91
|
+
outputSchema: z.object({
|
|
92
|
+
success: z.boolean(),
|
|
93
|
+
message: z.string(),
|
|
94
|
+
skillName: z.string().optional(),
|
|
95
|
+
}),
|
|
96
|
+
execute: async ({ skillName }) => {
|
|
97
|
+
if (state.skills.has(skillName)) {
|
|
98
|
+
return {
|
|
99
|
+
success: true,
|
|
100
|
+
message: `Skill "${skillName}" is already loaded.`,
|
|
101
|
+
skillName,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const skill = catalogue.skills.find(({ name }) => name === skillName);
|
|
105
|
+
if (!skill) {
|
|
106
|
+
return {
|
|
107
|
+
success: false,
|
|
108
|
+
message: `Skill "${skillName}" not found. Use search_skills to find available skills.`,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
state.skills.set(skillName, skill.instructions);
|
|
112
|
+
return {
|
|
113
|
+
success: true,
|
|
114
|
+
message: `Skill "${skillName}" loaded. Its instructions are now available as context.`,
|
|
115
|
+
skillName,
|
|
116
|
+
};
|
|
117
|
+
},
|
|
118
|
+
}),
|
|
119
|
+
skill_read: createTool({
|
|
120
|
+
id: "skill_read",
|
|
121
|
+
description: "Read a reference, script, template, or asset from a loaded skill. The path is relative to the skill root.",
|
|
122
|
+
inputSchema: z.object({
|
|
123
|
+
skillName: z.string().describe("Exact loaded skill name."),
|
|
124
|
+
path: z.string().describe("File path relative to the skill root."),
|
|
125
|
+
startLine: z.number().int().positive().optional(),
|
|
126
|
+
endLine: z.number().int().positive().optional(),
|
|
127
|
+
}),
|
|
128
|
+
execute: async ({ skillName, path, startLine, endLine }) => {
|
|
129
|
+
if (!state.skills.has(skillName)) {
|
|
130
|
+
return `Skill "${skillName}" is not loaded. Call load_skill first.`;
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
const source = await owner.readSkillFile(skillName, path, args.abortSignal);
|
|
134
|
+
return lineRange(source, path, startLine, endLine);
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
return `Could not read "${path}" from skill "${skillName}": ${errorUtils.errorMessage(error)}`;
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
}),
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
threadState(args) {
|
|
145
|
+
const now = Date.now();
|
|
146
|
+
for (const [key, state] of this.states) {
|
|
147
|
+
if (now - state.lastAccessed > this.ttlMs)
|
|
148
|
+
this.states.delete(key);
|
|
149
|
+
}
|
|
150
|
+
const key = args.requestContext?.get(MASTRA_THREAD_ID_KEY) ?? "default";
|
|
151
|
+
const current = this.states.get(String(key)) ?? {
|
|
152
|
+
lastAccessed: now,
|
|
153
|
+
skills: new Map(),
|
|
154
|
+
};
|
|
155
|
+
current.lastAccessed = now;
|
|
156
|
+
this.states.set(String(key), current);
|
|
157
|
+
return current;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function lineRange(source, path, startLine, endLine) {
|
|
161
|
+
if (startLine === undefined && endLine === undefined)
|
|
162
|
+
return source;
|
|
163
|
+
const lines = source.split(/\r?\n/);
|
|
164
|
+
const start = Math.max(1, startLine ?? 1);
|
|
165
|
+
const end = Math.min(lines.length, endLine ?? lines.length);
|
|
166
|
+
if (start > end || start > lines.length) {
|
|
167
|
+
return `File "${path}" has ${lines.length} lines; requested range ${start}-${end} is empty.`;
|
|
168
|
+
}
|
|
169
|
+
return `${path} (lines ${start}-${end} of ${lines.length})\n${lines.slice(start - 1, end).join("\n")}`;
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2tpbGwtc2VhcmNoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NraWxsLXNlYXJjaC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBRUgsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRXBELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ3BFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNoRCxPQUFPLElBQUksTUFBTSxTQUFTLENBQUM7QUFDM0IsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUd4QixNQUFNLG9CQUFvQixHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO0FBZTVDLHFGQUFxRjtBQUNyRixNQUFNLE9BQU8sNkJBQTZCO0lBQy9CLEVBQUUsR0FBRyx3QkFBd0IsQ0FBQztJQUM5QixJQUFJLEdBQUcsd0JBQXdCLENBQUM7SUFDaEMsc0JBQXNCLEdBQUcsV0FBb0IsQ0FBQztJQUV0QyxRQUFRLENBQVM7SUFDakIsT0FBTyxDQUF5QjtJQUNoQyxNQUFNLEdBQUcsSUFBSSxHQUFHLEVBQXVCLENBQUM7SUFDeEMsSUFBSSxDQUFTO0lBQ2IsS0FBSyxDQUFTO0lBRS9CLFlBQVksT0FBNkM7UUFDdkQsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDO1FBQy9CLElBQUksQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLElBQUksSUFBSSxDQUFDLENBQUM7UUFDOUIsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUMsUUFBUSxJQUFJLEdBQUcsQ0FBQztRQUN4QyxJQUFJLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLElBQUksb0JBQW9CLENBQUM7SUFDckQsQ0FBQztJQUVELEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxJQUEwQjtRQUMvQyxNQUFNLEtBQUss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Y292ZXJ5IGJhY2tlZCBieSBhIG1hdGVyaWFsaXplZCB3b3Jrc3BhY2UgY2F0YWxvZ3VlLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBlcnJvclV0aWxzIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB0eXBlIHsgUHJvY2Vzc0lucHV0U3RlcEFyZ3MsIFByb2Nlc3NvciB9IGZyb20gXCJAbWFzdHJhL2NvcmUvcHJvY2Vzc29yc1wiO1xuaW1wb3J0IHsgTUFTVFJBX1RIUkVBRF9JRF9LRVkgfSBmcm9tIFwiQG1hc3RyYS9jb3JlL3JlcXVlc3QtY29udGV4dFwiO1xuaW1wb3J0IHsgY3JlYXRlVG9vbCB9IGZyb20gXCJAbWFzdHJhL2NvcmUvdG9vbHNcIjtcbmltcG9ydCBGdXNlIGZyb20gXCJmdXNlLmpzXCI7XG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuaW1wb3J0IHR5cGUgeyBTa2lsbENhdGFsb2d1ZVJlc29sdmVyIH0gZnJvbSBcIi4vc2tpbGwtY2FjaGUudHNcIjtcblxuY29uc3QgREVGQVVMVF9TVEFURV9UVExfTVMgPSA2MCAqIDYwICogMTAwMDtcblxuaW50ZXJmYWNlIFRocmVhZFN0YXRlIHtcbiAgbGFzdEFjY2Vzc2VkOiBudW1iZXI7XG4gIHNraWxsczogTWFwPHN0cmluZywgc3RyaW5nPjtcbn1cblxuLyoqIENvbmZpZ3VyYXRpb24gZm9yIHtAbGluayBDYXRhbG9ndWVTa2lsbFNlYXJjaFByb2Nlc3Nvcn0uICovXG5leHBvcnQgaW50ZXJmYWNlIENhdGFsb2d1ZVNraWxsU2VhcmNoUHJvY2Vzc29yT3B0aW9ucyB7XG4gIG1pblNjb3JlPzogbnVtYmVyO1xuICByZXNvbHZlOiBTa2lsbENhdGFsb2d1ZVJlc29sdmVyO1xuICB0b3BLPzogbnVtYmVyO1xuICB0dGxNcz86IG51bWJlcjtcbn1cblxuLyoqIE1hc3RyYS1jb21wYXRpYmxlIHNlYXJjaCwgbG9hZCwgYW5kIGxhenktcmVhZCB0b29scyBvdmVyIG9uZSBjYWNoZWQgY2F0YWxvZ3VlLiAqL1xuZXhwb3J0IGNsYXNzIENhdGFsb2d1ZVNraWxsU2VhcmNoUHJvY2Vzc29yIGltcGxlbWVudHMgUHJvY2Vzc29yPFwic2tpbGwtY2F0YWxvZ3VlLXNlYXJjaFwiPiB7XG4gIHJlYWRvbmx5IGlkID0gXCJza2lsbC1jYXRhbG9ndWUtc2VhcmNoXCI7XG4gIHJlYWRvbmx5IG5hbWUgPSBcIlNraWxsIENhdGFsb2d1ZSBTZWFyY2hcIjtcbiAgcmVhZG9ubHkgcHJvdmlkZXNTa2lsbERpc2NvdmVyeSA9IFwib24tZGVtYW5kXCIgYXMgY29uc3Q7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBtaW5TY29yZTogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IHJlc29sdmU6IFNraWxsQ2F0YWxvZ3VlUmVzb2x2ZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgc3RhdGVzID0gbmV3IE1hcDxzdHJpbmcsIFRocmVhZFN0YXRlPigpO1xuICBwcml2YXRlIHJlYWRvbmx5IHRvcEs6IG51bWJlcjtcbiAgcHJpdmF0ZSByZWFkb25seSB0dGxNczogbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IENhdGFsb2d1ZVNraWxsU2VhcmNoUHJvY2Vzc29yT3B0aW9ucykge1xuICAgIHRoaXMucmVzb2x2ZSA9IG9wdGlvbnMucmVzb2x2ZTtcbiAgICB0aGlzLnRvcEsgPSBvcHRpb25zLnRvcEsgPz8gNTtcbiAgICB0aGlzLm1pblNjb3JlID0gb3B0aW9ucy5taW5TY29yZSA/PyAwLjE7XG4gICAgdGhpcy50dGxNcyA9IG9wdGlvbnMudHRsTXMgPz8gREVGQVVMVF9TVEFURV9UVExfTVM7XG4gIH1cblxuICBhc3luYyBwcm9jZXNzSW5wdXRTdGVwKGFyZ3M6IFByb2Nlc3NJbnB1dFN0ZXBBcmdzKTogUHJvbWlzZTx7IHRvb2xzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB9PiB7XG4gICAgY29uc3Qgb3duZXIgPSBhd2FpdCB0aGlzLnJlc29sdmUoYXJncyk7XG4gICAgY29uc3QgY2F0YWxvZ3VlID0gYXdhaXQgb3duZXIuZ2V0KGFyZ3MuYWJvcnRTaWduYWwpO1xuICAgIGNvbnN0IHN0YXRlID0gdGhpcy50aHJlYWRTdGF0ZShhcmdzKTtcbiAgICBhcmdzLm1lc3NhZ2VMaXN0LmFkZFN5c3RlbShcbiAgICAgIFwiVG8gZGlzY292ZXIgYXZhaWxhYmxlIHNraWxscywgY2FsbCBzZWFyY2hfc2tpbGxzIHdpdGggYSBrZXl3b3JkIHF1ZXJ5LiBcIiArXG4gICAgICAgIFwiVG8gbG9hZCBhIHNraWxsJ3MgaW5zdHJ1Y3Rpb25zLCBjYWxsIGxvYWRfc2tpbGwgd2l0aCB0aGUgZXhhY3Qgc2tpbGwgbmFtZS4gXCIgK1xuICAgICAgICBcIlVzZSBza2lsbF9yZWFkIG9ubHkgYWZ0ZXIgbG9hZGluZyBhIHNraWxsIHdoZW4gaXRzIGluc3RydWN0aW9ucyByZXF1aXJlIGEgcmVmZXJlbmNlLCBzY3JpcHQsIG9yIGFzc2V0LlwiLFxuICAgICk7XG4gICAgZm9yIChjb25zdCBbc2tpbGxOYW1lLCBpbnN0cnVjdGlvbnNdIG9mIHN0YXRlLnNraWxscykge1xuICAgICAgYXJncy5tZXNzYWdlTGlzdC5hZGRTeXN0ZW0oYFtTa2lsbDogJHtza2lsbE5hbWV9XVxcblxcbiR7aW5zdHJ1Y3Rpb25zfWApO1xuICAgIH1cbiAgICBjb25zdCBzZWFyY2ggPSBuZXcgRnVzZShjYXRhbG9ndWUuc2tpbGxzLCB7XG4gICAgICBpbmNsdWRlU2NvcmU6IHRydWUsXG4gICAgICBpZ25vcmVMb2NhdGlvbjogdHJ1ZSxcbiAgICAgIHRocmVzaG9sZDogMSxcbiAgICAgIGtleXM6IFtcbiAgICAgICAgeyBuYW1lOiBcIm5hbWVcIiwgd2VpZ2h0OiAwLjUgfSxcbiAgICAgICAgeyBuYW1lOiBcImRlc2NyaXB0aW9uXCIsIHdlaWdodDogMC4zNSB9LFxuICAgICAgICB7IG5hbWU6IFwiaW5zdHJ1Y3Rpb25zXCIsIHdlaWdodDogMC4xNSB9LFxuICAgICAgXSxcbiAgICB9KTtcbiAgICByZXR1cm4ge1xuICAgICAgdG9vbHM6IHtcbiAgICAgICAgLi4uKGFyZ3MudG9vbHMgPz8ge30pLFxuICAgICAgICBzZWFyY2hfc2tpbGxzOiBjcmVhdGVUb29sKHtcbiAgICAgICAgICBpZDogXCJzZWFyY2hfc2tpbGxzXCIsXG4gICAgICAgICAgZGVzY3JpcHRpb246XG4gICAgICAgICAgICBcIlNlYXJjaCBmb3IgYXZhaWxhYmxlIHNraWxscyBieSBrZXl3b3JkLiBMb2FkIGEgdXNlZnVsIHJlc3VsdCB3aXRoIGxvYWRfc2tpbGwuXCIsXG4gICAgICAgICAgaW5wdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgICAgICAgIHF1ZXJ5OiB6LnN0cmluZygpLnRyaW0oKS5taW4oMSwgXCJRdWVyeSBpcyByZXF1aXJlZFwiKS5kZXNjcmliZShcIlNlYXJjaCBrZXl3b3Jkcy5cIiksXG4gICAgICAgICAgfSksXG4gICAgICAgICAgb3V0cHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICAgICAgICByZXN1bHRzOiB6LmFycmF5KFxuICAgICAgICAgICAgICB6Lm9iamVjdCh7XG4gICAgICAgICAgICAgICAgbmFtZTogei5zdHJpbmcoKSxcbiAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbjogei5zdHJpbmcoKSxcbiAgICAgICAgICAgICAgICBzY29yZTogei5udW1iZXIoKSxcbiAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgbWVzc2FnZTogei5zdHJpbmcoKSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgICBleGVjdXRlOiBhc3luYyAoeyBxdWVyeSB9KSA9PiB7XG4gICAgICAgICAgICBjb25zdCByZXN1bHRzID0gc2VhcmNoXG4gICAgICAgICAgICAgIC5zZWFyY2gocXVlcnkpXG4gICAgICAgICAgICAgIC5tYXAoKHJlc3VsdCkgPT4gKHtcbiAgICAgICAgICAgICAgICBuYW1lOiByZXN1bHQuaXRlbS5uYW1lLFxuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICAgICAgICAgcmVzdWx0Lml0ZW0uZGVzY3JpcHRpb24ubGVuZ3RoID4gMTUwXG4gICAgICAgICAgICAgICAgICAgID8gYCR7cmVzdWx0Lml0ZW0uZGVzY3JpcHRpb24uc2xpY2UoMCwgMTQ3KX0uLi5gXG4gICAgICAgICAgICAgICAgICAgIDogcmVzdWx0Lml0ZW0uZGVzY3JpcHRpb24sXG4gICAgICAgICAgICAgICAgc2NvcmU6IE1hdGgucm91bmQoKDEgLSAocmVzdWx0LnNjb3JlID8/IDEpKSAqIDEwMCkgLyAxMDAsXG4gICAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgICAuZmlsdGVyKCh7IHNjb3JlIH0pID0+IHNjb3JlID49IHRoaXMubWluU2NvcmUpXG4gICAgICAgICAgICAgIC5zbGljZSgwLCB0aGlzLnRvcEspO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgcmVzdWx0cyxcbiAgICAgICAgICAgICAgbWVzc2FnZTpcbiAgICAgICAgICAgICAgICByZXN1bHRzLmxlbmd0aCA9PT0gMFxuICAgICAgICAgICAgICAgICAgPyBgTm8gc2tpbGxzIGZvdW5kIG1hdGNoaW5nIFwiJHtxdWVyeX1cIi4gVHJ5IGRpZmZlcmVudCBrZXl3b3Jkcy5gXG4gICAgICAgICAgICAgICAgICA6IGBGb3VuZCAke3Jlc3VsdHMubGVuZ3RofSBza2lsbChzKS4gVXNlIGxvYWRfc2tpbGwgd2l0aCB0aGUgZXhhY3Qgc2tpbGwgbmFtZSB0byBsb2FkIGl0cyBpbnN0cnVjdGlvbnMuYCxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfSxcbiAgICAgICAgfSksXG4gICAgICAgIGxvYWRfc2tpbGw6IGNyZWF0ZVRvb2woe1xuICAgICAgICAgIGlkOiBcImxvYWRfc2tpbGxcIixcbiAgICAgICAgICBkZXNjcmlwdGlvbjogXCJMb2FkIGEgc2tpbGwncyBmdWxsIGluc3RydWN0aW9ucyBpbnRvIHRoZSBjb252ZXJzYXRpb24uXCIsXG4gICAgICAgICAgaW5wdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICAgICAgICAgIHNraWxsTmFtZTogei5zdHJpbmcoKS5kZXNjcmliZShcIkV4YWN0IHNraWxsIG5hbWUgcmV0dXJuZWQgYnkgc2VhcmNoX3NraWxscy5cIiksXG4gICAgICAgICAgfSksXG4gICAgICAgICAgb3V0cHV0U2NoZW1hOiB6Lm9iamVjdCh7XG4gICAgICAgICAgICBzdWNjZXNzOiB6LmJvb2xlYW4oKSxcbiAgICAgICAgICAgIG1lc3NhZ2U6IHouc3RyaW5nKCksXG4gICAgICAgICAgICBza2lsbE5hbWU6IHouc3RyaW5nKCkub3B0aW9uYWwoKSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgICBleGVjdXRlOiBhc3luYyAoeyBza2lsbE5hbWUgfSkgPT4ge1xuICAgICAgICAgICAgaWYgKHN0YXRlLnNraWxscy5oYXMoc2tpbGxOYW1lKSkge1xuICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHN1Y2Nlc3M6IHRydWUsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogYFNraWxsIFwiJHtza2lsbE5hbWV9XCIgaXMgYWxyZWFkeSBsb2FkZWQuYCxcbiAgICAgICAgICAgICAgICBza2lsbE5hbWUsXG4gICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBza2lsbCA9IGNhdGFsb2d1ZS5za2lsbHMuZmluZCgoeyBuYW1lIH0pID0+IG5hbWUgPT09IHNraWxsTmFtZSk7XG4gICAgICAgICAgICBpZiAoIXNraWxsKSB7XG4gICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgc3VjY2VzczogZmFsc2UsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogYFNraWxsIFwiJHtza2lsbE5hbWV9XCIgbm90IGZvdW5kLiBVc2Ugc2VhcmNoX3NraWxscyB0byBmaW5kIGF2YWlsYWJsZSBza2lsbHMuYCxcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN0YXRlLnNraWxscy5zZXQoc2tpbGxOYW1lLCBza2lsbC5pbnN0cnVjdGlvbnMpO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgc3VjY2VzczogdHJ1ZSxcbiAgICAgICAgICAgICAgbWVzc2FnZTogYFNraWxsIFwiJHtza2lsbE5hbWV9XCIgbG9hZGVkLiBJdHMgaW5zdHJ1Y3Rpb25zIGFyZSBub3cgYXZhaWxhYmxlIGFzIGNvbnRleHQuYCxcbiAgICAgICAgICAgICAgc2tpbGxOYW1lLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9LFxuICAgICAgICB9KSxcbiAgICAgICAgc2tpbGxfcmVhZDogY3JlYXRlVG9vbCh7XG4gICAgICAgICAgaWQ6IFwic2tpbGxfcmVhZFwiLFxuICAgICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICAgXCJSZWFkIGEgcmVmZXJlbmNlLCBzY3JpcHQsIHRlbXBsYXRlLCBvciBhc3NldCBmcm9tIGEgbG9hZGVkIHNraWxsLiBUaGUgcGF0aCBpcyByZWxhdGl2ZSB0byB0aGUgc2tpbGwgcm9vdC5cIixcbiAgICAgICAgICBpbnB1dFNjaGVtYTogei5vYmplY3Qoe1xuICAgICAgICAgICAgc2tpbGxOYW1lOiB6LnN0cmluZygpLmRlc2NyaWJlKFwiRXhhY3QgbG9hZGVkIHNraWxsIG5hbWUuXCIpLFxuICAgICAgICAgICAgcGF0aDogei5zdHJpbmcoKS5kZXNjcmliZShcIkZpbGUgcGF0aCByZWxhdGl2ZSB0byB0aGUgc2tpbGwgcm9vdC5cIiksXG4gICAgICAgICAgICBzdGFydExpbmU6IHoubnVtYmVyKCkuaW50KCkucG9zaXRpdmUoKS5vcHRpb25hbCgpLFxuICAgICAgICAgICAgZW5kTGluZTogei5udW1iZXIoKS5pbnQoKS5wb3NpdGl2ZSgpLm9wdGlvbmFsKCksXG4gICAgICAgICAgfSksXG4gICAgICAgICAgZXhlY3V0ZTogYXN5bmMgKHsgc2tpbGxOYW1lLCBwYXRoLCBzdGFydExpbmUsIGVuZExpbmUgfSkgPT4ge1xuICAgICAgICAgICAgaWYgKCFzdGF0ZS5za2lsbHMuaGFzKHNraWxsTmFtZSkpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGBTa2lsbCBcIiR7c2tpbGxOYW1lfVwiIGlzIG5vdCBsb2FkZWQuIENhbGwgbG9hZF9za2lsbCBmaXJzdC5gO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgY29uc3Qgc291cmNlID0gYXdhaXQgb3duZXIucmVhZFNraWxsRmlsZShza2lsbE5hbWUsIHBhdGgsIGFyZ3MuYWJvcnRTaWduYWwpO1xuICAgICAgICAgICAgICByZXR1cm4gbGluZVJhbmdlKHNvdXJjZSwgcGF0aCwgc3RhcnRMaW5lLCBlbmRMaW5lKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgIHJldHVybiBgQ291bGQgbm90IHJlYWQgXCIke3BhdGh9XCIgZnJvbSBza2lsbCBcIiR7c2tpbGxOYW1lfVwiOiAke2Vycm9yVXRpbHMuZXJyb3JNZXNzYWdlKGVycm9yKX1gO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSB0aHJlYWRTdGF0ZShhcmdzOiBQcm9jZXNzSW5wdXRTdGVwQXJncyk6IFRocmVhZFN0YXRlIHtcbiAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgIGZvciAoY29uc3QgW2tleSwgc3RhdGVdIG9mIHRoaXMuc3RhdGVzKSB7XG4gICAgICBpZiAobm93IC0gc3RhdGUubGFzdEFjY2Vzc2VkID4gdGhpcy50dGxNcykgdGhpcy5zdGF0ZXMuZGVsZXRlKGtleSk7XG4gICAgfVxuICAgIGNvbnN0IGtleSA9IGFyZ3MucmVxdWVzdENvbnRleHQ/LmdldChNQVNUUkFfVEhSRUFEX0lEX0tFWSkgPz8gXCJkZWZhdWx0XCI7XG4gICAgY29uc3QgY3VycmVudCA9IHRoaXMuc3RhdGVzLmdldChTdHJpbmcoa2V5KSkgPz8ge1xuICAgICAgbGFzdEFjY2Vzc2VkOiBub3csXG4gICAgICBza2lsbHM6IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCksXG4gICAgfTtcbiAgICBjdXJyZW50Lmxhc3RBY2Nlc3NlZCA9IG5vdztcbiAgICB0aGlzLnN0YXRlcy5zZXQoU3RyaW5nKGtleSksIGN1cnJlbnQpO1xuICAgIHJldHVybiBjdXJyZW50O1xuICB9XG59XG5cbmZ1bmN0aW9uIGxpbmVSYW5nZShcbiAgc291cmNlOiBzdHJpbmcsXG4gIHBhdGg6IHN0cmluZyxcbiAgc3RhcnRMaW5lOiBudW1iZXIgfCB1bmRlZmluZWQsXG4gIGVuZExpbmU6IG51bWJlciB8IHVuZGVmaW5lZCxcbik6IHN0cmluZyB7XG4gIGlmIChzdGFydExpbmUgPT09IHVuZGVmaW5lZCAmJiBlbmRMaW5lID09PSB1bmRlZmluZWQpIHJldHVybiBzb3VyY2U7XG4gIGNvbnN0IGxpbmVzID0gc291cmNlLnNwbGl0KC9cXHI/XFxuLyk7XG4gIGNvbnN0IHN0YXJ0ID0gTWF0aC5tYXgoMSwgc3RhcnRMaW5lID8/IDEpO1xuICBjb25zdCBlbmQgPSBNYXRoLm1pbihsaW5lcy5sZW5ndGgsIGVuZExpbmUgPz8gbGluZXMubGVuZ3RoKTtcbiAgaWYgKHN0YXJ0ID4gZW5kIHx8IHN0YXJ0ID4gbGluZXMubGVuZ3RoKSB7XG4gICAgcmV0dXJuIGBGaWxlIFwiJHtwYXRofVwiIGhhcyAke2xpbmVzLmxlbmd0aH0gbGluZXM7IHJlcXVlc3RlZCByYW5nZSAke3N0YXJ0fS0ke2VuZH0gaXMgZW1wdHkuYDtcbiAgfVxuICByZXR1cm4gYCR7cGF0aH0gKGxpbmVzICR7c3RhcnR9LSR7ZW5kfSBvZiAke2xpbmVzLmxlbmd0aH0pXFxuJHtsaW5lcy5zbGljZShzdGFydCAtIDEsIGVuZCkuam9pbihcIlxcblwiKX1gO1xufVxuIl19
|
package/lib/src/workspaces.d.ts
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
import type { RequestContext } from "@mastra/core/request-context";
|
|
21
21
|
import { Workspace, type SkillsResolver, type WorkspaceFilesystem, type WorkspaceSandbox, type WorkspaceSandboxResolver } from "@mastra/core/workspace";
|
|
22
22
|
import { type DatabricksWorkspaceSandboxOptions } from "./sandbox.ts";
|
|
23
|
+
import { type SkillCatalogueResolver, type SkillCatalogueSource } from "./skill-cache.ts";
|
|
23
24
|
/** Per-request context for mount and skill-folder resolvers. */
|
|
24
25
|
export interface WorkspaceMountContext {
|
|
25
26
|
requestContext?: RequestContext;
|
|
@@ -58,6 +59,8 @@ export interface SkillFolderOptions {
|
|
|
58
59
|
/** Mount map plus optional Mastra skill scan roots for one resolver. */
|
|
59
60
|
export interface WorkspaceMountContribution {
|
|
60
61
|
mounts: Record<string, WorkspaceFilesystem>;
|
|
62
|
+
/** Ordered source roots included in catalogue discovery. */
|
|
63
|
+
skillSources?: SkillCatalogueSource[];
|
|
61
64
|
/** Paths within the composite namespace where `SKILL.md` files are scanned. */
|
|
62
65
|
skillPaths?: string[];
|
|
63
66
|
/**
|
|
@@ -100,16 +103,16 @@ export interface CreateWorkspaceOptions {
|
|
|
100
103
|
/** Forwarded to Mastra when skill discovery is enabled. */
|
|
101
104
|
checkSkillFileMtime?: boolean;
|
|
102
105
|
/**
|
|
103
|
-
*
|
|
104
|
-
* Defaults to five minutes.
|
|
106
|
+
* Refresh TTL for the complete parsed skill catalogue. Auxiliary reads are
|
|
107
|
+
* always fresh. Defaults to five minutes.
|
|
105
108
|
*/
|
|
106
109
|
workspaceSkillRefreshTtlMs?: number;
|
|
107
110
|
/** Enable BM25 keyword search over indexed workspace content. */
|
|
108
111
|
bm25?: boolean;
|
|
109
112
|
/**
|
|
110
|
-
* Command sandbox. Defaults to
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
+
* Command sandbox. Defaults to Monty. Pass `"databricks"` or an options
|
|
114
|
+
* object for Databricks Sandbox, `false` to disable command execution, or an
|
|
115
|
+
* explicit Mastra sandbox/provider resolver.
|
|
113
116
|
*/
|
|
114
117
|
sandbox?: WorkspaceSandboxSelection;
|
|
115
118
|
/**
|
|
@@ -164,6 +167,8 @@ export declare const DEFAULT_SKILL_FOLDERS: Readonly<Record<DefaultSkillFolderNa
|
|
|
164
167
|
* ```
|
|
165
168
|
*/
|
|
166
169
|
export declare function createWorkspace(options?: CreateWorkspaceOptions): Workspace;
|
|
170
|
+
/** Return the dbx-tools catalogue resolver attached to one workspace. */
|
|
171
|
+
export declare function workspaceSkillCatalogueResolver(workspace: Workspace | undefined): SkillCatalogueResolver | undefined;
|
|
167
172
|
/**
|
|
168
173
|
* Merge the configured skill folders over {@link DEFAULT_SKILL_FOLDERS}.
|
|
169
174
|
*
|