@dbx-tools/appkit-mastra 0.9.79 → 0.9.95

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.
Files changed (42) hide show
  1. package/README.md +90 -48
  2. package/index.ts +4 -12
  3. package/lib/index.d.ts +4 -12
  4. package/lib/index.js +4 -9
  5. package/lib/src/agents.js +11 -23
  6. package/lib/src/chat.js +20 -1
  7. package/lib/src/config.d.ts +9 -11
  8. package/lib/src/config.js +7 -7
  9. package/lib/src/filesystems.d.ts +20 -2
  10. package/lib/src/filesystems.js +29 -2
  11. package/lib/src/monty-sandbox.d.ts +4 -3
  12. package/lib/src/monty-sandbox.js +54 -21
  13. package/lib/src/plugin.js +3 -2
  14. package/lib/src/remote-skills.d.ts +3 -4
  15. package/lib/src/remote-skills.js +5 -14
  16. package/lib/src/server.d.ts +7 -0
  17. package/lib/src/server.js +33 -2
  18. package/lib/src/skill-paths.d.ts +8 -4
  19. package/lib/src/skill-paths.js +12 -6
  20. package/lib/src/workspaces.d.ts +39 -33
  21. package/lib/src/workspaces.js +208 -168
  22. package/lib/tsconfig.tsbuildinfo +1 -1
  23. package/package.json +14 -38
  24. package/src/agents.ts +11 -24
  25. package/src/chat.ts +24 -0
  26. package/src/config.ts +15 -17
  27. package/src/filesystems.ts +43 -0
  28. package/src/monty-sandbox.ts +61 -22
  29. package/src/plugin.ts +2 -0
  30. package/src/remote-skills.ts +5 -15
  31. package/src/server.ts +33 -1
  32. package/src/skill-paths.ts +13 -5
  33. package/src/workspaces.ts +285 -210
  34. package/lib/src/monty-native.d.ts +0 -40
  35. package/lib/src/monty-native.js +0 -100
  36. package/lib/src/skill-cache.d.ts +0 -94
  37. package/lib/src/skill-cache.js +0 -251
  38. package/lib/src/skill-search.d.ts +0 -30
  39. package/lib/src/skill-search.js +0 -171
  40. package/src/monty-native.ts +0 -149
  41. package/src/skill-cache.ts +0 -347
  42. package/src/skill-search.ts +0 -203
@@ -1,171 +0,0 @@
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
@@ -1,149 +0,0 @@
1
- /**
2
- * Ensures Monty's platform native package is present before the Node addon loads.
3
- *
4
- * `@pydantic/monty` ships `@pydantic/monty-<platform>` as optionalDependencies.
5
- * npm can skip those (https://github.com/npm/cli/issues/4828), which surfaces as
6
- * "Cannot find native binding". This module installs only the current platform
7
- * package, at the already-installed `@pydantic/monty` version, without rewriting
8
- * package.json.
9
- *
10
- * @module
11
- */
12
-
13
- import { createRequire } from "node:module";
14
- import { COMMAND_NOT_FOUND_EXIT_CODE, exec } from "@dbx-tools/core";
15
- import { errorUtils, log } from "@dbx-tools/shared-core";
16
-
17
- const logger = log.logger("mastra/monty-native");
18
- const requireFromHere = createRequire(import.meta.url);
19
-
20
- /** Result of spawning the package installer. */
21
- export interface MontyNativeInstallResult {
22
- exitCode: number | null;
23
- stdout: string;
24
- stderr: string;
25
- }
26
-
27
- /** Installer used by {@link ensureMontyNativeBinding}. */
28
- export type MontyNativeInstaller = (
29
- command: string,
30
- args: readonly string[],
31
- options: { cwd: string },
32
- ) => Promise<MontyNativeInstallResult>;
33
-
34
- /** Overrides for {@link ensureMontyNativeBinding} (tests inject resolve/install). */
35
- export interface EnsureMontyNativeBindingOptions {
36
- /** Working directory for the in-place install. Defaults to `process.cwd()`. */
37
- cwd?: string;
38
- /** Module resolver; defaults to `createRequire(import.meta.url).resolve`. */
39
- resolve?: (specifier: string) => string;
40
- /** Package installer; defaults to npm, then bun when npm is missing. */
41
- install?: MontyNativeInstaller;
42
- }
43
-
44
- /**
45
- * npm package that ships Monty's `.node` addon and `monty` binary for this
46
- * process. Matches `@pydantic/monty`'s `platformTriple()` / optionalDependencies.
47
- */
48
- export function montyNativeBindingPackage(
49
- platform: NodeJS.Platform = process.platform,
50
- arch: string = process.arch,
51
- ): string | undefined {
52
- if (platform === "darwin" && (arch === "x64" || arch === "arm64")) {
53
- return `@pydantic/monty-darwin-${arch}`;
54
- }
55
- if (platform === "linux" && (arch === "x64" || arch === "arm64")) {
56
- return `@pydantic/monty-linux-${arch}-gnu`;
57
- }
58
- if (platform === "win32" && arch === "x64") {
59
- return "@pydantic/monty-win32-x64-msvc";
60
- }
61
- return undefined;
62
- }
63
-
64
- /**
65
- * Resolve the current platform's Monty native package, installing it in place
66
- * when npm omitted the optional dependency.
67
- */
68
- export async function ensureMontyNativeBinding(
69
- options: EnsureMontyNativeBindingOptions = {},
70
- ): Promise<void> {
71
- const pkg = montyNativeBindingPackage();
72
- if (!pkg) return;
73
-
74
- const resolve = options.resolve ?? ((specifier: string) => requireFromHere.resolve(specifier));
75
- if (isResolvable(pkg, resolve)) return;
76
-
77
- const version = montyPackageVersion(resolve);
78
- const spec = `${pkg}@${version}`;
79
- const cwd = options.cwd ?? process.cwd();
80
- logger.warn("native-binding:missing", { package: spec, cwd });
81
-
82
- const install = options.install ?? defaultInstaller;
83
- const output = await installNativePackage(spec, cwd, install);
84
- if (!isResolvable(pkg, resolve)) {
85
- throw new Error(
86
- `Monty native binding ${spec} is still missing after ${output.command}. ${output.detail}`,
87
- );
88
- }
89
- logger.info("native-binding:installed", { package: spec, command: output.command });
90
- }
91
-
92
- function isResolvable(specifier: string, resolve: (specifier: string) => string): boolean {
93
- try {
94
- resolve(`${specifier}/package.json`);
95
- return true;
96
- } catch {
97
- return false;
98
- }
99
- }
100
-
101
- function montyPackageVersion(resolve: (specifier: string) => string): string {
102
- const pkg = requireFromHere(resolve("@pydantic/monty/package.json")) as { version?: string };
103
- const version = pkg.version?.trim();
104
- if (!version) throw new Error("Installed @pydantic/monty has no version");
105
- return version;
106
- }
107
-
108
- async function installNativePackage(
109
- spec: string,
110
- cwd: string,
111
- install: MontyNativeInstaller,
112
- ): Promise<{ command: string; detail: string }> {
113
- const npm = await install("npm", ["install", spec, "--no-save", "--no-package-lock"], { cwd });
114
- if (npm.exitCode === 0) return { command: `npm install ${spec}`, detail: npm.stdout };
115
- if (npm.exitCode !== COMMAND_NOT_FOUND_EXIT_CODE) {
116
- throw new Error(
117
- `Failed to install ${spec} with npm (exit ${npm.exitCode}): ${installDetail(npm)}`,
118
- );
119
- }
120
-
121
- const bun = await install("bun", ["add", spec, "--no-save"], { cwd });
122
- if (bun.exitCode === 0) return { command: `bun add ${spec}`, detail: bun.stdout };
123
- throw new Error(
124
- `Failed to install ${spec}: npm was not found, bun add exited ${bun.exitCode}: ${installDetail(bun)}`,
125
- );
126
- }
127
-
128
- async function defaultInstaller(
129
- command: string,
130
- args: readonly string[],
131
- options: { cwd: string },
132
- ): Promise<MontyNativeInstallResult> {
133
- const result = await exec.spawn(command, [...args], {
134
- cwd: options.cwd,
135
- stdout: "capture",
136
- stderr: "capture",
137
- stdin: "ignore",
138
- check: false,
139
- });
140
- return {
141
- exitCode: result.exitCode,
142
- stdout: result.stdout,
143
- stderr: result.stderr,
144
- };
145
- }
146
-
147
- function installDetail(result: MontyNativeInstallResult): string {
148
- return errorUtils.errorMessage(result.stderr || result.stdout || `exit ${result.exitCode}`);
149
- }