@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
package/lib/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/agents.ts","../src/chart.ts","../src/chat.ts","../src/config.ts","../src/defaults.ts","../src/evaluation.ts","../src/filesystems.ts","../src/genie.ts","../src/identity.ts","../src/mcp.ts","../src/memory.ts","../src/mlflow.ts","../src/model.ts","../src/monty-sandbox.ts","../src/observability.ts","../src/openapi-tool.ts","../src/plugin.ts","../src/processors.ts","../src/remote-skills.ts","../src/rest.ts","../src/sandbox.ts","../src/server.ts","../src/serving-sanitize.ts","../src/serving.ts","../src/skill-cache.ts","../src/skill-paths.ts","../src/statement.ts","../src/storage-schema.ts","../src/style.ts","../src/summarize.ts","../src/telemetry.ts","../src/trace-attributes.ts","../src/validation.ts","../src/workspaces.ts","../src/writer.ts","../index.ts"],"version":"5.9.3"}
|
|
1
|
+
{"root":["../src/agents.ts","../src/chart.ts","../src/chat.ts","../src/config.ts","../src/defaults.ts","../src/evaluation.ts","../src/filesystems.ts","../src/genie.ts","../src/identity.ts","../src/mcp.ts","../src/memory.ts","../src/mlflow.ts","../src/model.ts","../src/monty-sandbox.ts","../src/observability.ts","../src/openapi-tool.ts","../src/plugin.ts","../src/processors.ts","../src/remote-skills.ts","../src/rest.ts","../src/sandbox.ts","../src/server.ts","../src/serving-sanitize.ts","../src/serving.ts","../src/skill-cache.ts","../src/skill-paths.ts","../src/skill-search.ts","../src/statement.ts","../src/storage-schema.ts","../src/style.ts","../src/summarize.ts","../src/telemetry.ts","../src/trace-attributes.ts","../src/validation.ts","../src/workspaces.ts","../src/writer.ts","../index.ts"],"version":"5.9.3"}
|
package/package.json
CHANGED
|
@@ -34,19 +34,19 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@databricks/appkit": "0.81.0",
|
|
37
|
-
"@dbx-tools/appkit": "^0.9.
|
|
38
|
-
"@dbx-tools/core": "^0.9.
|
|
39
|
-
"@dbx-tools/databricks": "^0.9.
|
|
40
|
-
"@dbx-tools/fs": "^0.9.
|
|
41
|
-
"@dbx-tools/genie": "^0.9.
|
|
42
|
-
"@dbx-tools/model": "^0.9.
|
|
43
|
-
"@dbx-tools/path": "^0.9.
|
|
44
|
-
"@dbx-tools/postgres": "^0.9.
|
|
45
|
-
"@dbx-tools/shared-core": "^0.9.
|
|
46
|
-
"@dbx-tools/shared-fs": "^0.9.
|
|
47
|
-
"@dbx-tools/shared-genie": "^0.9.
|
|
48
|
-
"@dbx-tools/shared-mastra": "^0.9.
|
|
49
|
-
"@dbx-tools/shared-model": "^0.9.
|
|
37
|
+
"@dbx-tools/appkit": "^0.9.93",
|
|
38
|
+
"@dbx-tools/core": "^0.9.93",
|
|
39
|
+
"@dbx-tools/databricks": "^0.9.93",
|
|
40
|
+
"@dbx-tools/fs": "^0.9.93",
|
|
41
|
+
"@dbx-tools/genie": "^0.9.93",
|
|
42
|
+
"@dbx-tools/model": "^0.9.93",
|
|
43
|
+
"@dbx-tools/path": "^0.9.93",
|
|
44
|
+
"@dbx-tools/postgres": "^0.9.93",
|
|
45
|
+
"@dbx-tools/shared-core": "^0.9.93",
|
|
46
|
+
"@dbx-tools/shared-fs": "^0.9.93",
|
|
47
|
+
"@dbx-tools/shared-genie": "^0.9.93",
|
|
48
|
+
"@dbx-tools/shared-mastra": "^0.9.93",
|
|
49
|
+
"@dbx-tools/shared-model": "^0.9.93",
|
|
50
50
|
"@mastra/ai-sdk": "1.10.5",
|
|
51
51
|
"@mastra/core": "1.71.0",
|
|
52
52
|
"@mastra/express": "1.5.15",
|
|
@@ -61,9 +61,12 @@
|
|
|
61
61
|
"@opentelemetry/core": "2.11.0",
|
|
62
62
|
"@opentelemetry/sdk-trace-base": "2.8.0",
|
|
63
63
|
"@opentelemetry/sdk-trace-node": "2.8.0",
|
|
64
|
-
"@pydantic/monty": "0.0
|
|
64
|
+
"@pydantic/monty": "1.0.0",
|
|
65
65
|
"express": "^5.1.0",
|
|
66
|
+
"fuse.js": "^7.4.2",
|
|
67
|
+
"lru-cache": "11.5.3",
|
|
66
68
|
"pg": "^8.22.0",
|
|
69
|
+
"yaml": "^2.9.0",
|
|
67
70
|
"zod": "4.3.6"
|
|
68
71
|
},
|
|
69
72
|
"main": "./lib/index.js",
|
|
@@ -181,6 +184,10 @@
|
|
|
181
184
|
"types": "./lib/src/skill-paths.d.ts",
|
|
182
185
|
"default": "./lib/src/skill-paths.js"
|
|
183
186
|
},
|
|
187
|
+
"./skill-search": {
|
|
188
|
+
"types": "./lib/src/skill-search.d.ts",
|
|
189
|
+
"default": "./lib/src/skill-search.js"
|
|
190
|
+
},
|
|
184
191
|
"./statement": {
|
|
185
192
|
"types": "./lib/src/statement.d.ts",
|
|
186
193
|
"default": "./lib/src/statement.js"
|
|
@@ -220,7 +227,7 @@
|
|
|
220
227
|
"./package.json": "./package.json"
|
|
221
228
|
}
|
|
222
229
|
},
|
|
223
|
-
"version": "0.9.
|
|
230
|
+
"version": "0.9.93",
|
|
224
231
|
"types": "./lib/index.d.ts",
|
|
225
232
|
"dbxToolsConfig": {
|
|
226
233
|
"tags": [
|
|
@@ -337,6 +344,10 @@
|
|
|
337
344
|
"types": "./lib/src/skill-paths.d.ts",
|
|
338
345
|
"default": "./lib/src/skill-paths.js"
|
|
339
346
|
},
|
|
347
|
+
"./skill-search": {
|
|
348
|
+
"types": "./lib/src/skill-search.d.ts",
|
|
349
|
+
"default": "./lib/src/skill-search.js"
|
|
350
|
+
},
|
|
340
351
|
"./statement": {
|
|
341
352
|
"types": "./lib/src/statement.d.ts",
|
|
342
353
|
"default": "./lib/src/statement.js"
|
package/src/agents.ts
CHANGED
|
@@ -25,7 +25,7 @@ import type {
|
|
|
25
25
|
} from "@databricks/appkit/beta";
|
|
26
26
|
import { pluginRegistry, toolkitEntries } from "@dbx-tools/appkit";
|
|
27
27
|
import type { AgentToolExecutionContext } from "@dbx-tools/appkit/tool-provider";
|
|
28
|
-
import { log, object, stringUtils } from "@dbx-tools/shared-core";
|
|
28
|
+
import { errorUtils, log, object, stringUtils } from "@dbx-tools/shared-core";
|
|
29
29
|
import { TOOL_PROGRESS_PART_TYPE, ToolProgressEventSchema } from "@dbx-tools/shared-mastra/wire";
|
|
30
30
|
import type {
|
|
31
31
|
AgentConfig,
|
|
@@ -35,6 +35,7 @@ import type {
|
|
|
35
35
|
} from "@mastra/core/agent";
|
|
36
36
|
import { Agent } from "@mastra/core/agent";
|
|
37
37
|
import { SkillSearchProcessor } from "@mastra/core/processors";
|
|
38
|
+
import type { OutputProcessor } from "@mastra/core/processors";
|
|
38
39
|
import { MASTRA_RESOURCE_ID_KEY } from "@mastra/core/request-context";
|
|
39
40
|
import type { Tool } from "@mastra/core/tools";
|
|
40
41
|
import { createTool } from "@mastra/core/tools";
|
|
@@ -48,9 +49,10 @@ import type { MemoryBuilder } from "./memory.ts";
|
|
|
48
49
|
import { buildModel, RESPONSES_PROVIDER_OPTIONS } from "./model.ts";
|
|
49
50
|
import { stripStaleChartsProcessor } from "./processors.ts";
|
|
50
51
|
import { MASTRA_RESOLVED_MODEL_KEY } from "./serving.ts";
|
|
52
|
+
import { CatalogueSkillSearchProcessor } from "./skill-search.ts";
|
|
51
53
|
import { TYPOGRAPHY_RULE } from "./style.ts";
|
|
52
54
|
import { buildSummarizeTool } from "./summarize.ts";
|
|
53
|
-
import { createWorkspace } from "./workspaces.ts";
|
|
55
|
+
import { createWorkspace, workspaceSkillCatalogueResolver } from "./workspaces.ts";
|
|
54
56
|
|
|
55
57
|
/**
|
|
56
58
|
* Tool record accepted by every Mastra `Agent.tools` field and by the
|
|
@@ -583,8 +585,7 @@ export async function buildAgents(opts: {
|
|
|
583
585
|
...(config.workspaceSkillRefreshTtlMs !== undefined
|
|
584
586
|
? { workspaceSkillRefreshTtlMs: config.workspaceSkillRefreshTtlMs }
|
|
585
587
|
: {}),
|
|
586
|
-
sandbox:
|
|
587
|
-
config.sandbox === undefined || config.sandbox === true ? "databricks" : config.sandbox,
|
|
588
|
+
sandbox: config.sandbox === true ? "databricks" : config.sandbox,
|
|
588
589
|
});
|
|
589
590
|
markDefaultWorkspace(workspace);
|
|
590
591
|
}
|
|
@@ -613,6 +614,7 @@ export async function buildAgents(opts: {
|
|
|
613
614
|
...(memory ? { memory } : {}),
|
|
614
615
|
...(workspace ? { workspace } : {}),
|
|
615
616
|
inputProcessors: [...inputProcessors, ...workspaceSkillInputProcessors(workspace, config)],
|
|
617
|
+
outputProcessors: [toolErrorLoggingProcessor(log)],
|
|
616
618
|
});
|
|
617
619
|
// Surface the effective default model per agent so operators can
|
|
618
620
|
// see at a glance which endpoint each agent points at without
|
|
@@ -644,13 +646,44 @@ export async function buildAgents(opts: {
|
|
|
644
646
|
return { agents, defaultAgentId, defaultModels, ambientTools };
|
|
645
647
|
}
|
|
646
648
|
|
|
649
|
+
/** Log failed tool calls without changing the chunks returned to the client. */
|
|
650
|
+
function toolErrorLoggingProcessor(logger: log.Logger): OutputProcessor {
|
|
651
|
+
return {
|
|
652
|
+
id: "tool-error-logger",
|
|
653
|
+
async processOutputStream({ part }) {
|
|
654
|
+
if (part.type === "tool-error") {
|
|
655
|
+
const error = errorUtils.toError(part.payload.error);
|
|
656
|
+
logger.error("tool execution failed", {
|
|
657
|
+
toolName: part.payload.toolName,
|
|
658
|
+
toolCallId: part.payload.toolCallId,
|
|
659
|
+
error: error.message,
|
|
660
|
+
stack: error.stack,
|
|
661
|
+
});
|
|
662
|
+
}
|
|
663
|
+
return part;
|
|
664
|
+
},
|
|
665
|
+
};
|
|
666
|
+
}
|
|
667
|
+
|
|
647
668
|
function workspaceSkillInputProcessors(
|
|
648
669
|
workspace: Workspace | undefined,
|
|
649
670
|
config: MastraPluginConfig,
|
|
650
|
-
): SkillSearchProcessor
|
|
651
|
-
if (!workspace
|
|
671
|
+
): Array<SkillSearchProcessor | CatalogueSkillSearchProcessor> {
|
|
672
|
+
if (!workspace || config.workspaceSkillSearch === false) return [];
|
|
652
673
|
const options =
|
|
653
674
|
typeof config.workspaceSkillSearch === "object" ? config.workspaceSkillSearch : undefined;
|
|
675
|
+
const catalogue = workspaceSkillCatalogueResolver(workspace);
|
|
676
|
+
if (catalogue) {
|
|
677
|
+
return [
|
|
678
|
+
new CatalogueSkillSearchProcessor({
|
|
679
|
+
resolve: catalogue,
|
|
680
|
+
topK: options?.topK ?? 5,
|
|
681
|
+
minScore: options?.minScore ?? 0.1,
|
|
682
|
+
...(options?.ttlMs !== undefined ? { ttlMs: options.ttlMs } : {}),
|
|
683
|
+
}),
|
|
684
|
+
];
|
|
685
|
+
}
|
|
686
|
+
if (!workspace.skills) return [];
|
|
654
687
|
return [
|
|
655
688
|
new SkillSearchProcessor({
|
|
656
689
|
workspace,
|
package/src/config.ts
CHANGED
|
@@ -211,20 +211,20 @@ export interface MastraPluginConfig extends BasePluginConfig {
|
|
|
211
211
|
*/
|
|
212
212
|
memory?: boolean | MastraMemoryConfig;
|
|
213
213
|
/**
|
|
214
|
-
* Sandbox for auto-created agent workspaces. Defaults to
|
|
215
|
-
* `
|
|
216
|
-
*
|
|
214
|
+
* Sandbox for auto-created agent workspaces. Defaults to Monty. `true`,
|
|
215
|
+
* `"databricks"`, or an object selects/configures Databricks Sandbox, and
|
|
216
|
+
* `false` disables workspace command execution. An agent with an explicit
|
|
217
217
|
* custom `workspace` keeps that workspace and its sandbox.
|
|
218
218
|
*/
|
|
219
219
|
sandbox?: boolean | "databricks" | "monty" | DatabricksWorkspaceSandboxOptions;
|
|
220
220
|
/**
|
|
221
|
-
*
|
|
222
|
-
* Defaults to five minutes.
|
|
221
|
+
* Refresh TTL for the complete user-scoped workspace skill catalogue.
|
|
222
|
+
* Defaults to five minutes; auxiliary files remain uncached.
|
|
223
223
|
*/
|
|
224
224
|
workspaceSkillRefreshTtlMs?: number;
|
|
225
225
|
/**
|
|
226
|
-
* Use
|
|
227
|
-
*
|
|
226
|
+
* Use dbx-tools catalogue-backed on-demand skill search. Defaults to true.
|
|
227
|
+
* Pass an object to tune search.
|
|
228
228
|
*/
|
|
229
229
|
workspaceSkillSearch?: boolean | MastraSkillSearchConfig;
|
|
230
230
|
/**
|
|
@@ -665,17 +665,17 @@ export const MASTRA_CONFIG_SCHEMA: ConfigSchema = {
|
|
|
665
665
|
sandbox: {
|
|
666
666
|
type: ["boolean", "string", "object"],
|
|
667
667
|
description:
|
|
668
|
-
'Command sandbox for auto-created agent workspaces. Defaults to
|
|
668
|
+
'Command sandbox for auto-created agent workspaces. Defaults to Monty; false disables command execution, and true, "databricks", or an object selects/configures Databricks Sandbox with optional fallback.',
|
|
669
669
|
},
|
|
670
670
|
workspaceSkillRefreshTtlMs: {
|
|
671
671
|
type: "number",
|
|
672
672
|
description:
|
|
673
|
-
"
|
|
673
|
+
"Refresh TTL in milliseconds for the complete user-scoped workspace skill catalogue. Defaults to 5 minutes; auxiliary file reads stay fresh.",
|
|
674
674
|
},
|
|
675
675
|
workspaceSkillSearch: {
|
|
676
676
|
type: ["boolean", "object"],
|
|
677
677
|
description:
|
|
678
|
-
"Use
|
|
678
|
+
"Use dbx-tools catalogue-backed on-demand skill search with lazy auxiliary reads. Defaults to true.",
|
|
679
679
|
},
|
|
680
680
|
defaultAgent: {
|
|
681
681
|
type: "string",
|
package/src/genie.ts
CHANGED
|
@@ -52,6 +52,7 @@ import type { StartedEvent } from "@dbx-tools/shared-mastra";
|
|
|
52
52
|
import type { RequestContext } from "@mastra/core/request-context";
|
|
53
53
|
import { MASTRA_THREAD_ID_KEY } from "@mastra/core/request-context";
|
|
54
54
|
import { createTool, type ToolExecutionContext } from "@mastra/core/tools";
|
|
55
|
+
import { LRUCache } from "lru-cache";
|
|
55
56
|
import { z } from "zod";
|
|
56
57
|
|
|
57
58
|
import type { MastraTools } from "./agents.ts";
|
|
@@ -1089,26 +1090,20 @@ const SUGGESTION_LIMIT = 6;
|
|
|
1089
1090
|
*/
|
|
1090
1091
|
const SUGGESTION_CACHE_TTL_MS = 10 * 60_000;
|
|
1091
1092
|
|
|
1092
|
-
/**
|
|
1093
|
-
const _suggestionCache = new
|
|
1093
|
+
/** Bounded process-local cache of parsed sample questions by Genie space id. */
|
|
1094
|
+
const _suggestionCache = new LRUCache<string, string[]>({
|
|
1095
|
+
max: 128,
|
|
1096
|
+
ttl: SUGGESTION_CACHE_TTL_MS,
|
|
1097
|
+
});
|
|
1094
1098
|
|
|
1095
1099
|
/** Read a space's cached questions, or `undefined` on miss / expiry. */
|
|
1096
1100
|
function readSuggestionCache(spaceId: string): string[] | undefined {
|
|
1097
|
-
|
|
1098
|
-
if (!entry) return undefined;
|
|
1099
|
-
if (entry.expires <= Date.now()) {
|
|
1100
|
-
_suggestionCache.delete(spaceId);
|
|
1101
|
-
return undefined;
|
|
1102
|
-
}
|
|
1103
|
-
return entry.questions;
|
|
1101
|
+
return _suggestionCache.get(spaceId);
|
|
1104
1102
|
}
|
|
1105
1103
|
|
|
1106
1104
|
/** Cache a space's parsed questions for {@link SUGGESTION_CACHE_TTL_MS}. */
|
|
1107
1105
|
function writeSuggestionCache(spaceId: string, questions: string[]): void {
|
|
1108
|
-
_suggestionCache.set(spaceId,
|
|
1109
|
-
questions,
|
|
1110
|
-
expires: Date.now() + SUGGESTION_CACHE_TTL_MS,
|
|
1111
|
-
});
|
|
1106
|
+
_suggestionCache.set(spaceId, questions);
|
|
1112
1107
|
}
|
|
1113
1108
|
|
|
1114
1109
|
/**
|
package/src/mlflow.ts
CHANGED
|
@@ -30,8 +30,8 @@ import { appkit } from "@dbx-tools/appkit";
|
|
|
30
30
|
import { asyncUtils, errorUtils, log, object } from "@dbx-tools/shared-core";
|
|
31
31
|
import { feedback } from "@dbx-tools/shared-mastra";
|
|
32
32
|
import { TraceLocationType, TraceMetadataKey } from "@mlflow/core";
|
|
33
|
-
import { TraceInfo } from "@mlflow/core/dist/core/entities/trace_info";
|
|
34
|
-
import { TraceState } from "@mlflow/core/dist/core/entities/trace_state";
|
|
33
|
+
import { TraceInfo } from "@mlflow/core/dist/core/entities/trace_info.js";
|
|
34
|
+
import { TraceState } from "@mlflow/core/dist/core/entities/trace_state.js";
|
|
35
35
|
import type { Context } from "@opentelemetry/api";
|
|
36
36
|
import type { ReadableSpan, Span as SdkSpan, SpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
37
37
|
import type { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
|
|
@@ -455,7 +455,7 @@ async function detectedDirectMlflowTraceLocation(
|
|
|
455
455
|
const client = new mlflow.MlflowClient({ trackingUri, authProvider });
|
|
456
456
|
const experiment = await client.getExperiment(experimentId);
|
|
457
457
|
if (!experiment) return undefined;
|
|
458
|
-
const { ucLocationFromExperimentTags } = await import("@mlflow/core/dist/core/destination");
|
|
458
|
+
const { ucLocationFromExperimentTags } = await import("@mlflow/core/dist/core/destination.js");
|
|
459
459
|
const location = ucLocationFromExperimentTags(experiment.tags);
|
|
460
460
|
if (!location?.tablePrefix) return undefined;
|
|
461
461
|
return {
|
|
@@ -505,7 +505,7 @@ export async function initializeDirectMlflowTracing(): Promise<boolean> {
|
|
|
505
505
|
}
|
|
506
506
|
const [{ DatabricksUCTableSpanExporter, DatabricksUCTableSpanProcessor }, sdk] =
|
|
507
507
|
await Promise.all([
|
|
508
|
-
import("@mlflow/core/dist/exporters/uc_table"),
|
|
508
|
+
import("@mlflow/core/dist/exporters/uc_table.js"),
|
|
509
509
|
import("@opentelemetry/sdk-trace-node"),
|
|
510
510
|
]);
|
|
511
511
|
const authProvider = mlflow.createAuthProvider({
|
package/src/monty-sandbox.ts
CHANGED
|
@@ -1,33 +1,70 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pydantic Monty fallback for Mastra command execution.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Prefers Monty's native Node subprocess workers and falls back to its WASM
|
|
5
|
+
* workers when the native package is unavailable. It executes Python source
|
|
5
6
|
* with no host filesystem, network, environment, shell, or third-party package
|
|
6
|
-
* access
|
|
7
|
+
* access.
|
|
7
8
|
*
|
|
8
9
|
* @module
|
|
9
10
|
*/
|
|
10
11
|
|
|
11
|
-
import {
|
|
12
|
+
import { configUtils } from "@dbx-tools/core";
|
|
13
|
+
import { errorUtils, functionUtils, log } from "@dbx-tools/shared-core";
|
|
12
14
|
import type {
|
|
13
15
|
CommandResult,
|
|
14
16
|
ExecuteCommandOptions,
|
|
15
17
|
SandboxInfo,
|
|
16
18
|
WorkspaceSandbox,
|
|
17
19
|
} from "@mastra/core/workspace";
|
|
18
|
-
import type { CheckoutOptions, Monty
|
|
20
|
+
import type { CheckoutOptions, Monty, MontyCrashedError, MontySession } from "@pydantic/monty";
|
|
19
21
|
|
|
20
22
|
const DEFAULT_COMMAND_TIMEOUT_MS = 30_000;
|
|
21
23
|
const DEFAULT_MAX_MEMORY_BYTES = 10_000_000;
|
|
24
|
+
const NATIVE_MONTY_TARGET = {
|
|
25
|
+
name: "native Monty",
|
|
26
|
+
load: () => import("@pydantic/monty/node"),
|
|
27
|
+
} as const;
|
|
28
|
+
const WASM_MONTY_TARGET = {
|
|
29
|
+
name: "WASM Monty",
|
|
30
|
+
load: () => import("@pydantic/monty/wasm"),
|
|
31
|
+
} as const;
|
|
32
|
+
const logger = log.logger("mastra/monty");
|
|
33
|
+
|
|
34
|
+
type MontyPool = Pick<Monty, "checkout">;
|
|
35
|
+
|
|
36
|
+
interface MontyContext {
|
|
37
|
+
crashedError: typeof MontyCrashedError;
|
|
38
|
+
pool: MontyPool;
|
|
39
|
+
}
|
|
22
40
|
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
41
|
+
const montyContext = functionUtils.memoize(async (): Promise<MontyContext> => {
|
|
42
|
+
const errors: Error[] = [];
|
|
43
|
+
const targets = configUtils.boolean(undefined, "MONTY_FORCE_WASM")
|
|
44
|
+
? [WASM_MONTY_TARGET]
|
|
45
|
+
: [NATIVE_MONTY_TARGET, WASM_MONTY_TARGET];
|
|
46
|
+
for (const target of targets) {
|
|
47
|
+
try {
|
|
48
|
+
const module = await target.load();
|
|
49
|
+
logger.debug(`${target.name} module available`);
|
|
50
|
+
const pool = await module.Monty.create({
|
|
51
|
+
minProcesses: 1,
|
|
52
|
+
maxProcesses: 4,
|
|
53
|
+
requestTimeout: 35,
|
|
54
|
+
});
|
|
55
|
+
logger.debug(`${target.name} pool created`);
|
|
56
|
+
return {
|
|
57
|
+
crashedError: module.MontyCrashedError,
|
|
58
|
+
pool,
|
|
59
|
+
};
|
|
60
|
+
} catch (error) {
|
|
61
|
+
errors.push(errorUtils.toError(error));
|
|
62
|
+
logger.debug(`${target.name} unavailable`, {
|
|
63
|
+
error: errorUtils.errorMessage(error),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
throw new AggregateError(errors, "Failed to create Monty pool");
|
|
31
68
|
});
|
|
32
69
|
|
|
33
70
|
/** Resource controls for the Monty Python fallback. */
|
|
@@ -44,7 +81,7 @@ export interface MontySandboxOptions {
|
|
|
44
81
|
typeCheck?: boolean;
|
|
45
82
|
}
|
|
46
83
|
|
|
47
|
-
/** Python-only, deny-by-default sandbox backed by Monty's
|
|
84
|
+
/** Python-only, deny-by-default sandbox backed by Monty's selected worker pool. */
|
|
48
85
|
export class MontySandbox implements WorkspaceSandbox {
|
|
49
86
|
readonly id: string;
|
|
50
87
|
readonly name: string;
|
|
@@ -72,7 +109,7 @@ export class MontySandbox implements WorkspaceSandbox {
|
|
|
72
109
|
this.status = "starting";
|
|
73
110
|
this.error = undefined;
|
|
74
111
|
try {
|
|
75
|
-
await
|
|
112
|
+
await montyContext();
|
|
76
113
|
this.status = "running";
|
|
77
114
|
} catch (caught) {
|
|
78
115
|
this.status = "error";
|
|
@@ -135,12 +172,12 @@ export class MontySandbox implements WorkspaceSandbox {
|
|
|
135
172
|
|
|
136
173
|
await this.start();
|
|
137
174
|
const timeout = options.timeout ?? this.commandTimeoutMs;
|
|
138
|
-
const pool = await
|
|
175
|
+
const pool = (await montyContext()).pool;
|
|
139
176
|
const session = await checkoutSession(
|
|
140
177
|
pool,
|
|
141
178
|
{
|
|
142
179
|
limits: {
|
|
143
|
-
|
|
180
|
+
maxFeedDurationSecs: Math.max(0.001, timeout / 1_000),
|
|
144
181
|
maxMemory: this.maxMemoryBytes,
|
|
145
182
|
},
|
|
146
183
|
typeCheck: this.typeCheck,
|
|
@@ -183,8 +220,8 @@ export class MontySandbox implements WorkspaceSandbox {
|
|
|
183
220
|
}
|
|
184
221
|
const message = errorUtils.errorMessage(caught);
|
|
185
222
|
output.emit("stderr", output.stderr.value ? `\n${message}` : message);
|
|
186
|
-
const {
|
|
187
|
-
const timedOut = caught instanceof
|
|
223
|
+
const { crashedError } = await montyContext();
|
|
224
|
+
const timedOut = caught instanceof crashedError && caught.timedOut;
|
|
188
225
|
return {
|
|
189
226
|
command,
|
|
190
227
|
args,
|
|
@@ -404,3 +441,10 @@ function failedResult(
|
|
|
404
441
|
executionTimeMs: performance.now() - started,
|
|
405
442
|
};
|
|
406
443
|
}
|
|
444
|
+
|
|
445
|
+
if (import.meta.main) {
|
|
446
|
+
const sandbox = new MontySandbox();
|
|
447
|
+
await sandbox.start();
|
|
448
|
+
console.log(await sandbox.executeCommand("print('Hello, world!')"));
|
|
449
|
+
await sandbox.stop();
|
|
450
|
+
}
|
package/src/remote-skills.ts
CHANGED
|
@@ -74,6 +74,7 @@ import type { OneOrMany } from "@dbx-tools/shared-core";
|
|
|
74
74
|
import type { FileSystem } from "@dbx-tools/shared-fs";
|
|
75
75
|
|
|
76
76
|
import { ASSISTANT_SHARED_SKILLS_PATH, userAssistantSkillsPath } from "./skill-paths.ts";
|
|
77
|
+
import { clearWorkspaceSkillCache } from "./skill-cache.ts";
|
|
77
78
|
|
|
78
79
|
const logger = log.logger("mastra/remote-skills");
|
|
79
80
|
|
|
@@ -441,6 +442,7 @@ export async function provisionRemoteSkills(
|
|
|
441
442
|
const localSkillPaths: string[] = [];
|
|
442
443
|
const skillNames: string[] = [];
|
|
443
444
|
let staging: LocalFileSystem | undefined;
|
|
445
|
+
let workspaceUpdated = false;
|
|
444
446
|
|
|
445
447
|
try {
|
|
446
448
|
const sources = Array.isArray(options.sources) ? options.sources : [options.sources];
|
|
@@ -452,7 +454,8 @@ export async function provisionRemoteSkills(
|
|
|
452
454
|
// the source's own stable local dir.
|
|
453
455
|
const key = cacheKey(sourceOptions);
|
|
454
456
|
const cacheFS = destination ?? localSkillsFS(key);
|
|
455
|
-
const
|
|
457
|
+
const metadata = await readMetadata(cacheFS);
|
|
458
|
+
const cached = metadata?.sources[key];
|
|
456
459
|
if (cached && isFresh(cached, resolveRefreshTtl(sourceOptions, options))) {
|
|
457
460
|
skillNames.push(...cached.skills);
|
|
458
461
|
if (!destination) localSkillPaths.push(cacheFS.root);
|
|
@@ -483,10 +486,12 @@ export async function provisionRemoteSkills(
|
|
|
483
486
|
...(policy ? { policy } : {}),
|
|
484
487
|
};
|
|
485
488
|
if (destination && databricksBasePath) {
|
|
489
|
+
await removeDeletedSkills(destination, key, metadata, record.skills);
|
|
486
490
|
await copySkillDirs(destination, staged);
|
|
487
491
|
// Only after the copy lands: a metadata entry written first would
|
|
488
492
|
// mark a failed provision as fresh and suppress the retry for a day.
|
|
489
493
|
await writeMetadata(destination, key, record);
|
|
494
|
+
workspaceUpdated = true;
|
|
490
495
|
} else {
|
|
491
496
|
localSkillPaths.push(await persistLocally(key, staged, record));
|
|
492
497
|
}
|
|
@@ -515,9 +520,35 @@ export async function provisionRemoteSkills(
|
|
|
515
520
|
}
|
|
516
521
|
}
|
|
517
522
|
|
|
523
|
+
if (workspaceUpdated && client?.config?.getHost) {
|
|
524
|
+
await clearWorkspaceSkillCache({
|
|
525
|
+
host: (await client.config.getHost()).toString(),
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
|
|
518
529
|
return { localSkillPaths, databricksBasePath, skillNames };
|
|
519
530
|
}
|
|
520
531
|
|
|
532
|
+
/** Remove directories dropped by one source unless another source still owns them. */
|
|
533
|
+
async function removeDeletedSkills(
|
|
534
|
+
destination: FileSystem,
|
|
535
|
+
key: string,
|
|
536
|
+
metadata: RemoteSkillsMetadata | undefined,
|
|
537
|
+
nextSkills: readonly string[],
|
|
538
|
+
): Promise<void> {
|
|
539
|
+
const previous = metadata?.sources[key]?.skills ?? [];
|
|
540
|
+
const retained = new Set(nextSkills);
|
|
541
|
+
for (const [sourceKey, entry] of Object.entries(metadata?.sources ?? {})) {
|
|
542
|
+
if (sourceKey === key) continue;
|
|
543
|
+
for (const skill of entry.skills) retained.add(skill);
|
|
544
|
+
}
|
|
545
|
+
await Promise.all(
|
|
546
|
+
previous
|
|
547
|
+
.filter((skill) => !retained.has(skill))
|
|
548
|
+
.map((skill) => destination.rmdir(skill, { force: true, recursive: true })),
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
|
|
521
552
|
/** Probe file {@link openWritableWorkspace} writes and removes. */
|
|
522
553
|
const WRITE_PROBE_FILE = ".dbx-tools-write-probe";
|
|
523
554
|
|