@dbx-tools/appkit-mastra 0.9.61 → 0.9.64

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.
@@ -0,0 +1,194 @@
1
+ /**
2
+ * AppKit-backed caching for Databricks workspace skill mounts.
3
+ *
4
+ * @module
5
+ */
6
+ import { randomUUID } from "node:crypto";
7
+ import { CacheManager } from "@databricks/appkit";
8
+ import { hash, object } from "@dbx-tools/shared-core";
9
+ import { filesystems } from "./filesystems.js";
10
+ const CACHE_NAMESPACE = "mastra:workspace-skills";
11
+ const DEFAULT_MAX_SCOPED_MOUNTS = 256;
12
+ const scopedMounts = new Map();
13
+ /** Default remote skill metadata and content cache lifetime. */
14
+ export const DEFAULT_WORKSPACE_SKILL_CACHE_TTL_MS = 5 * 60 * 1000;
15
+ /**
16
+ * Cache read-only filesystem operations through AppKit while delegating
17
+ * mutations to the current request's source.
18
+ */
19
+ export class AppKitCachedFileSystem {
20
+ backend = "appkit-cache";
21
+ id;
22
+ readOnly;
23
+ root;
24
+ source;
25
+ host;
26
+ ttlSec;
27
+ userKey;
28
+ constructor(options) {
29
+ this.host = options.host;
30
+ this.source = options.source;
31
+ this.root = options.source.root;
32
+ this.readOnly = options.source.readOnly;
33
+ this.ttlSec = cacheTtlSec(options.ttlMs);
34
+ this.userKey = options.userKey;
35
+ this.id = `appkit-skill-cache-${hash.fnvHash(this.host, this.userKey, this.root)}`;
36
+ }
37
+ /** Rebind cache misses and writes to the current request's OBO filesystem. */
38
+ bind(source) {
39
+ if (source.root !== this.root || source.readOnly !== this.readOnly) {
40
+ throw new Error("Cannot rebind a workspace skill cache to a different filesystem scope");
41
+ }
42
+ this.source = source;
43
+ }
44
+ async init() {
45
+ await this.source.init();
46
+ }
47
+ /** Keep the shared scope alive when one request releases its workspace view. */
48
+ close() {
49
+ return Promise.resolve();
50
+ }
51
+ resolvePath(inputPath) {
52
+ return this.source.resolvePath(inputPath);
53
+ }
54
+ async readFile(inputPath, options) {
55
+ const value = await this.cached("readFile", inputPath, undefined, async (source) => ({
56
+ base64: Buffer.from(await source.readFile(inputPath)).toString("base64"),
57
+ }));
58
+ const bytes = Buffer.from(value.base64, "base64");
59
+ return options?.encoding ? bytes.toString(options.encoding) : bytes;
60
+ }
61
+ async writeFile(inputPath, content, options) {
62
+ await this.mutate((source) => source.writeFile(inputPath, content, options));
63
+ }
64
+ async appendFile(inputPath, content) {
65
+ await this.mutate((source) => source.appendFile(inputPath, content));
66
+ }
67
+ async deleteFile(inputPath, options) {
68
+ await this.mutate((source) => source.deleteFile(inputPath, options));
69
+ }
70
+ async copyFile(sourcePath, destinationPath, options) {
71
+ await this.mutate((source) => source.copyFile(sourcePath, destinationPath, options));
72
+ }
73
+ async moveFile(sourcePath, destinationPath, options) {
74
+ await this.mutate((source) => source.moveFile(sourcePath, destinationPath, options));
75
+ }
76
+ async mkdir(inputPath, options) {
77
+ await this.mutate((source) => source.mkdir(inputPath, options));
78
+ }
79
+ async rmdir(inputPath, options) {
80
+ await this.mutate((source) => source.rmdir(inputPath, options));
81
+ }
82
+ async readdir(inputPath, options) {
83
+ return this.cached("readdir", inputPath, options, (source) => source.readdir(inputPath, options));
84
+ }
85
+ async exists(inputPath) {
86
+ return this.cached("exists", inputPath, undefined, (source) => source.exists(inputPath));
87
+ }
88
+ async stat(inputPath) {
89
+ const value = await this.cached("stat", inputPath, undefined, async (source) => serializeStat(await source.stat(inputPath)));
90
+ return deserializeStat(value);
91
+ }
92
+ /** Rotate this scope's cache generation so the next read reloads it. */
93
+ async invalidate() {
94
+ const cache = await CacheManager.getInstance();
95
+ await cache.set(this.generationKey(cache), randomUUID(), {
96
+ ttl: this.ttlSec * 2,
97
+ });
98
+ }
99
+ async cached(operation, inputPath, options, load) {
100
+ const source = this.source;
101
+ const cache = await CacheManager.getInstance();
102
+ const generation = await this.generation(cache);
103
+ return cache.getOrExecute([
104
+ CACHE_NAMESPACE,
105
+ this.host,
106
+ this.root,
107
+ generation,
108
+ operation,
109
+ source.resolvePath(inputPath),
110
+ object.toStableKey(options ?? {}),
111
+ ], () => load(source), this.userKey, { ttl: this.ttlSec });
112
+ }
113
+ async generation(cache) {
114
+ return cache.getOrExecute([CACHE_NAMESPACE, "generation", this.host, this.root], async () => randomUUID(), this.userKey, { ttl: this.ttlSec * 2 });
115
+ }
116
+ generationKey(cache) {
117
+ return cache.generateKey([CACHE_NAMESPACE, "generation", this.host, this.root], this.userKey);
118
+ }
119
+ async mutate(run) {
120
+ const source = this.source;
121
+ await run(source);
122
+ await this.invalidate();
123
+ }
124
+ }
125
+ /** Return one stable Mastra mount per resolved user, host, and source root. */
126
+ export function cachedWorkspaceSkillMount(options) {
127
+ const cacheKey = object.toStableKey({
128
+ host: options.host,
129
+ readOnly: options.source.readOnly,
130
+ root: options.source.root,
131
+ userKey: options.userKey,
132
+ });
133
+ const existing = scopedMounts.get(cacheKey);
134
+ if (existing) {
135
+ existing.cache.bind(options.source);
136
+ scopedMounts.delete(cacheKey);
137
+ scopedMounts.set(cacheKey, existing);
138
+ return { cacheKey, filesystem: existing.adapter };
139
+ }
140
+ const cache = new AppKitCachedFileSystem(options);
141
+ const entry = {
142
+ adapter: filesystems(cache, {
143
+ id: cache.id,
144
+ readOnly: options.source.readOnly,
145
+ }),
146
+ cache,
147
+ host: options.host,
148
+ root: options.source.root,
149
+ userKey: options.userKey,
150
+ };
151
+ scopedMounts.set(cacheKey, entry);
152
+ trimScopedMounts();
153
+ return { cacheKey, filesystem: entry.adapter };
154
+ }
155
+ /** Invalidate one user's cached workspace skill scope. */
156
+ export async function clearWorkspaceSkillCache(options) {
157
+ const matches = [...scopedMounts.entries()].filter(([, entry]) => entry.host === options.host &&
158
+ entry.userKey === options.userKey &&
159
+ (options.root === undefined || entry.root === options.root));
160
+ await Promise.all(matches.map(([, entry]) => entry.cache.invalidate()));
161
+ }
162
+ function cacheTtlSec(ttlMs = DEFAULT_WORKSPACE_SKILL_CACHE_TTL_MS) {
163
+ if (!Number.isFinite(ttlMs) || ttlMs <= 0) {
164
+ throw new Error("Workspace skill cache ttlMs must be a positive finite number");
165
+ }
166
+ return Math.max(1, Math.ceil(ttlMs / 1000));
167
+ }
168
+ function serializeStat(value) {
169
+ const { accessedAt, createdAt, modifiedAt, ...stat } = value;
170
+ return {
171
+ ...stat,
172
+ ...(accessedAt ? { accessedAt: accessedAt.getTime() } : {}),
173
+ ...(createdAt ? { createdAt: createdAt.getTime() } : {}),
174
+ ...(modifiedAt ? { modifiedAt: modifiedAt.getTime() } : {}),
175
+ };
176
+ }
177
+ function deserializeStat(value) {
178
+ const { accessedAt, createdAt, modifiedAt, ...stat } = value;
179
+ return {
180
+ ...stat,
181
+ ...(accessedAt !== undefined ? { accessedAt: new Date(accessedAt) } : {}),
182
+ ...(createdAt !== undefined ? { createdAt: new Date(createdAt) } : {}),
183
+ ...(modifiedAt !== undefined ? { modifiedAt: new Date(modifiedAt) } : {}),
184
+ };
185
+ }
186
+ function trimScopedMounts() {
187
+ while (scopedMounts.size > DEFAULT_MAX_SCOPED_MOUNTS) {
188
+ const oldest = scopedMounts.keys().next().value;
189
+ if (oldest === undefined)
190
+ return;
191
+ scopedMounts.delete(oldest);
192
+ }
193
+ }
194
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2tpbGwtY2FjaGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2tpbGwtY2FjaGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7R0FJRztBQUVILE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDekMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFjdEQsT0FBTyxFQUFFLFdBQVcsRUFBZ0MsTUFBTSxrQkFBa0IsQ0FBQztBQUU3RSxNQUFNLGVBQWUsR0FBRyx5QkFBeUIsQ0FBQztBQUNsRCxNQUFNLHlCQUF5QixHQUFHLEdBQUcsQ0FBQztBQWdCdEMsTUFBTSxZQUFZLEdBQUcsSUFBSSxHQUFHLEVBQTRCLENBQUM7QUFFekQsZ0VBQWdFO0FBQ2hFLE1BQU0sQ0FBQyxNQUFNLG9DQUFvQyxHQUFHLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO0FBZ0JsRTs7O0dBR0c7QUFDSCxNQUFNLE9BQU8sc0JBQXNCO0lBQ3hCLE9BQU8sR0FBRyxjQUF1QixDQUFDO0lBQ2xDLEVBQUUsQ0FBUztJQUNYLFFBQVEsQ0FBVTtJQUNsQixJQUFJLENBQVM7SUFFZCxNQUFNLENBQWE7SUFDVixJQUFJLENBQVM7SUFDYixNQUFNLENBQVM7SUFDZixPQUFPLENBQVM7SUFFakMsWUFBWSxPQUFzQztRQUNoRCxJQUFJLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUM7UUFDekIsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDO1FBQzdCLElBQUksQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUM7UUFDaEMsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQztRQUN4QyxJQUFJLENBQUMs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QUM5QixDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQXBwS2l0LWJhY2tlZCBjYWNoaW5nIGZvciBEYXRhYnJpY2tzIHdvcmtzcGFjZSBza2lsbCBtb3VudHMuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IHJhbmRvbVVVSUQgfSBmcm9tIFwibm9kZTpjcnlwdG9cIjtcbmltcG9ydCB7IENhY2hlTWFuYWdlciB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7IGhhc2gsIG9iamVjdCB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgdHlwZSB7XG4gIENvcHlPcHRpb25zLFxuICBGaWxlQ29udGVudCxcbiAgRmlsZUVudHJ5LFxuICBGaWxlU3RhdCxcbiAgRmlsZVN5c3RlbSxcbiAgTGlzdE9wdGlvbnMsXG4gIE1ha2VEaXJlY3RvcnlPcHRpb25zLFxuICBSZWFkRmlsZU9wdGlvbnMsXG4gIFJlbW92ZU9wdGlvbnMsXG4gIFdyaXRlRmlsZU9wdGlvbnMsXG59IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1mc1wiO1xuXG5pbXBvcnQgeyBmaWxlc3lzdGVtcywgdHlwZSBNYXN0cmFGaWxlU3lzdGVtQWRhcHRlciB9IGZyb20gXCIuL2ZpbGVzeXN0ZW1zLnRzXCI7XG5cbmNvbnN0IENBQ0hFX05BTUVTUEFDRSA9IFwibWFzdHJhOndvcmtzcGFjZS1za2lsbHNcIjtcbmNvbnN0IERFRkFVTFRfTUFYX1NDT1BFRF9NT1VOVFMgPSAyNTY7XG5cbmludGVyZmFjZSBDYWNoZWRGaWxlU3RhdCBleHRlbmRzIE9taXQ8RmlsZVN0YXQsIFwiYWNjZXNzZWRBdFwiIHwgXCJjcmVhdGVkQXRcIiB8IFwibW9kaWZpZWRBdFwiPiB7XG4gIGFjY2Vzc2VkQXQ/OiBudW1iZXI7XG4gIGNyZWF0ZWRBdD86IG51bWJlcjtcbiAgbW9kaWZpZWRBdD86IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIFNjb3BlZE1vdW50RW50cnkge1xuICBhZGFwdGVyOiBNYXN0cmFGaWxlU3lzdGVtQWRhcHRlcjtcbiAgY2FjaGU6IEFwcEtpdENhY2hlZEZpbGVTeXN0ZW07XG4gIGhvc3Q6IHN0cmluZztcbiAgcm9vdDogc3RyaW5nO1xuICB1c2VyS2V5OiBzdHJpbmc7XG59XG5cbmNvbnN0IHNjb3BlZE1vdW50cyA9IG5ldyBNYXA8c3RyaW5nLCBTY29wZWRNb3VudEVudHJ5PigpO1xuXG4vKiogRGVmYXVsdCByZW1vdGUgc2tpbGwgbWV0YWRhdGEgYW5kIGNvbnRlbnQgY2FjaGUgbGlmZXRpbWUuICovXG5leHBvcnQgY29uc3QgREVGQVVMVF9XT1JLU1BBQ0VfU0tJTExfQ0FDSEVfVFRMX01TID0gNSAqIDYwICogMTAwMDtcblxuLyoqIE9wdGlvbnMgZm9yIG9uZSBBcHBLaXQtY2FjaGVkIHdvcmtzcGFjZSBza2lsbCBmaWxlc3lzdGVtLiAqL1xuZXhwb3J0IGludGVyZmFjZSBBcHBLaXRDYWNoZWRGaWxlU3lzdGVtT3B0aW9ucyB7XG4gIGhvc3Q6IHN0cmluZztcbiAgc291cmNlOiBGaWxlU3lzdGVtO1xuICB0dGxNcz86IG51bWJlcjtcbiAgdXNlcktleTogc3RyaW5nO1xufVxuXG4vKiogU3RhYmxlIE1hc3RyYSBtb3VudCBwbHVzIHRoZSBpZGVudGl0eSBrZXkgdXNlZCBmb3Igc291cmNlIHJldXNlLiAqL1xuZXhwb3J0IGludGVyZmFjZSBDYWNoZWRXb3Jrc3BhY2VTa2lsbE1vdW50IHtcbiAgY2FjaGVLZXk6IHN0cmluZztcbiAgZmlsZXN5c3RlbTogTWFzdHJhRmlsZVN5c3RlbUFkYXB0ZXI7XG59XG5cbi8qKlxuICogQ2FjaGUgcmVhZC1vbmx5IGZpbGVzeXN0ZW0gb3BlcmF0aW9ucyB0aHJvdWdoIEFwcEtpdCB3aGlsZSBkZWxlZ2F0aW5nXG4gKiBtdXRhdGlvbnMgdG8gdGhlIGN1cnJlbnQgcmVxdWVzdCdzIHNvdXJjZS5cbiAqL1xuZXhwb3J0IGNsYXNzIEFwcEtpdENhY2hlZEZpbGVTeXN0ZW0gaW1wbGVtZW50cyBGaWxlU3lzdGVtPFwiYXBwa2l0LWNhY2hlXCI+IHtcbiAgcmVhZG9ubHkgYmFja2VuZCA9IFwiYXBwa2l0LWNhY2hlXCIgYXMgY29uc3Q7XG4gIHJlYWRvbmx5IGlkOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHJlYWRPbmx5OiBib29sZWFuO1xuICByZWFkb25seSByb290OiBzdHJpbmc7XG5cbiAgcHJpdmF0ZSBzb3VyY2U6IEZpbGVTeXN0ZW07XG4gIHByaXZhdGUgcmVhZG9ubHkgaG9zdDogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IHR0bFNlYzogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IHVzZXJLZXk6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihvcHRpb25zOiBBcHBLaXRDYWNoZWRGaWxlU3lzdGVtT3B0aW9ucykge1xuICAgIHRoaXMuaG9zdCA9IG9wdGlvbnMuaG9zdDtcbiAgICB0aGlzLnNvdXJjZSA9IG9wdGlvbnMuc291cmNlO1xuICAgIHRoaXMucm9vdCA9IG9wdGlvbnMuc291cmNlLnJvb3Q7XG4gICAgdGhpcy5yZWFkT25seSA9IG9wdGlvbnMuc291cmNlLnJlYWRPbmx5O1xuICAgIHRoaXMudHRsU2VjID0gY2FjaGVUdGxTZWMob3B0aW9ucy50dGxNcyk7XG4gICAgdGhpcy51c2VyS2V5ID0gb3B0aW9ucy51c2VyS2V5O1xuICAgIHRoaXMuaWQgPSBgYXBwa2l0LXNraWxsLWNhY2hlLSR7aGFzaC5mbnZIYXNoKHRoaXMuaG9zdCwgdGhpcy51c2VyS2V5LCB0aGlzLnJvb3QpfWA7XG4gIH1cblxuICAvKiogUmViaW5kIGNhY2hlIG1pc3NlcyBhbmQgd3JpdGVzIHRvIHRoZSBjdXJyZW50IHJlcXVlc3QncyBPQk8gZmlsZXN5c3RlbS4gKi9cbiAgYmluZChzb3VyY2U6IEZpbGVTeXN0ZW0pOiB2b2lkIHtcbiAgICBpZiAoc291cmNlLnJvb3QgIT09IHRoaXMucm9vdCB8fCBzb3VyY2UucmVhZE9ubHkgIT09IHRoaXMucmVhZE9ubHkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCByZWJpbmQgYSB3b3Jrc3BhY2Ugc2tpbGwgY2FjaGUgdG8gYSBkaWZmZXJlbnQgZmlsZXN5c3RlbSBzY29wZVwiKTtcbiAgICB9XG4gICAgdGhpcy5zb3VyY2UgPSBzb3VyY2U7XG4gIH1cblxuICBhc3luYyBpbml0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuc291cmNlLmluaXQoKTtcbiAgfVxuXG4gIC8qKiBLZWVwIHRoZSBzaGFyZWQgc2NvcGUgYWxpdmUgd2hlbiBvbmUgcmVxdWVzdCByZWxlYXNlcyBpdHMgd29ya3NwYWNlIHZpZXcuICovXG4gIGNsb3NlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbiAgfVxuXG4gIHJlc29sdmVQYXRoKGlucHV0UGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5zb3VyY2UucmVzb2x2ZVBhdGgoaW5wdXRQYXRoKTtcbiAgfVxuXG4gIGFzeW5jIHJlYWRGaWxlKGlucHV0UGF0aDogc3RyaW5nKTogUHJvbWlzZTxVaW50OEFycmF5PjtcbiAgYXN5bmMgcmVhZEZpbGUoXG4gICAgaW5wdXRQYXRoOiBzdHJpbmcsXG4gICAgb3B0aW9uczogUmVhZEZpbGVPcHRpb25zICYgeyBlbmNvZGluZzogc3RyaW5nIH0sXG4gICk6IFByb21pc2U8c3RyaW5nPjtcbiAgYXN5bmMgcmVhZEZpbGUoaW5wdXRQYXRoOiBzdHJpbmcsIG9wdGlvbnM/OiBSZWFkRmlsZU9wdGlvbnMpOiBQcm9taXNlPHN0cmluZyB8IFVpbnQ4QXJyYXk+IHtcbiAgICBjb25zdCB2YWx1ZSA9IGF3YWl0IHRoaXMuY2FjaGVkKFwicmVhZEZpbGVcIiwgaW5wdXRQYXRoLCB1bmRlZmluZWQsIGFzeW5jIChzb3VyY2UpID0+ICh7XG4gICAgICBiYXNlNjQ6IEJ1ZmZlci5mcm9tKGF3YWl0IHNvdXJjZS5yZWFkRmlsZShpbnB1dFBhdGgpKS50b1N0cmluZyhcImJhc2U2NFwiKSxcbiAgICB9KSk7XG4gICAgY29uc3QgYnl0ZXMgPSBCdWZmZXIuZnJvbSh2YWx1ZS5iYXNlNjQsIFwiYmFzZTY0XCIpO1xuICAgIHJldHVybiBvcHRpb25zPy5lbmNvZGluZyA/IGJ5dGVzLnRvU3RyaW5nKG9wdGlvbnMuZW5jb2RpbmcgYXMgQnVmZmVyRW5jb2RpbmcpIDogYnl0ZXM7XG4gIH1cblxuICBhc3luYyB3cml0ZUZpbGUoXG4gICAgaW5wdXRQYXRoOiBzdHJpbmcsXG4gICAgY29udGVudDogRmlsZUNvbnRlbnQsXG4gICAgb3B0aW9ucz86IFdyaXRlRmlsZU9wdGlvbnMsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMubXV0YXRlKChzb3VyY2UpID0+IHNvdXJjZS53cml0ZUZpbGUoaW5wdXRQYXRoLCBjb250ZW50LCBvcHRpb25zKSk7XG4gIH1cblxuICBhc3luYyBhcHBlbmRGaWxlKGlucHV0UGF0aDogc3RyaW5nLCBjb250ZW50OiBGaWxlQ29udGVudCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMubXV0YXRlKChzb3VyY2UpID0+IHNvdXJjZS5hcHBlbmRGaWxlKGlucHV0UGF0aCwgY29udGVudCkpO1xuICB9XG5cbiAgYXN5bmMgZGVsZXRlRmlsZShpbnB1dFBhdGg6IHN0cmluZywgb3B0aW9ucz86IFJlbW92ZU9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLm11dGF0ZSgoc291cmNlKSA9PiBzb3VyY2UuZGVsZXRlRmlsZShpbnB1dFBhdGgsIG9wdGlvbnMpKTtcbiAgfVxuXG4gIGFzeW5jIGNvcHlGaWxlKFxuICAgIHNvdXJjZVBhdGg6IHN0cmluZyxcbiAgICBkZXN0aW5hdGlvblBhdGg6IHN0cmluZyxcbiAgICBvcHRpb25zPzogQ29weU9wdGlvbnMsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMubXV0YXRlKChzb3VyY2UpID0+IHNvdXJjZS5jb3B5RmlsZShzb3VyY2VQYXRoLCBkZXN0aW5hdGlvblBhdGgsIG9wdGlvbnMpKTtcbiAgfVxuXG4gIGFzeW5jIG1vdmVGaWxlKFxuICAgIHNvdXJjZVBhdGg6IHN0cmluZyxcbiAgICBkZXN0aW5hdGlvblBhdGg6IHN0cmluZyxcbiAgICBvcHRpb25zPzogQ29weU9wdGlvbnMsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMubXV0YXRlKChzb3VyY2UpID0+IHNvdXJjZS5tb3ZlRmlsZShzb3VyY2VQYXRoLCBkZXN0aW5hdGlvblBhdGgsIG9wdGlvbnMpKTtcbiAgfVxuXG4gIGFzeW5jIG1rZGlyKGlucHV0UGF0aDogc3RyaW5nLCBvcHRpb25zPzogTWFrZURpcmVjdG9yeU9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLm11dGF0ZSgoc291cmNlKSA9PiBzb3VyY2UubWtkaXIoaW5wdXRQYXRoLCBvcHRpb25zKSk7XG4gIH1cblxuICBhc3luYyBybWRpcihpbnB1dFBhdGg6IHN0cmluZywgb3B0aW9ucz86IFJlbW92ZU9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLm11dGF0ZSgoc291cmNlKSA9PiBzb3VyY2Uucm1kaXIoaW5wdXRQYXRoLCBvcHRpb25zKSk7XG4gIH1cblxuICBhc3luYyByZWFkZGlyKGlucHV0UGF0aDogc3RyaW5nLCBvcHRpb25zPzogTGlzdE9wdGlvbnMpOiBQcm9taXNlPEZpbGVFbnRyeVtdPiB7XG4gICAgcmV0dXJuIHRoaXMuY2FjaGVkKFwicmVhZGRpclwiLCBpbnB1dFBhdGgsIG9wdGlvbnMsIChzb3VyY2UpID0+XG4gICAgICBzb3VyY2UucmVhZGRpcihpbnB1dFBhdGgsIG9wdGlvbnMpLFxuICAgICk7XG4gIH1cblxuICBhc3luYyBleGlzdHMoaW5wdXRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gdGhpcy5jYWNoZWQoXCJleGlzdHNcIiwgaW5wdXRQYXRoLCB1bmRlZmluZWQsIChzb3VyY2UpID0+IHNvdXJjZS5leGlzdHMoaW5wdXRQYXRoKSk7XG4gIH1cblxuICBhc3luYyBzdGF0KGlucHV0UGF0aDogc3RyaW5nKTogUHJvbWlzZTxGaWxlU3RhdD4ge1xuICAgIGNvbnN0IHZhbHVlID0gYXdhaXQgdGhpcy5jYWNoZWQoXCJzdGF0XCIsIGlucHV0UGF0aCwgdW5kZWZpbmVkLCBhc3luYyAoc291cmNlKSA9PlxuICAgICAgc2VyaWFsaXplU3RhdChhd2FpdCBzb3VyY2Uuc3RhdChpbnB1dFBhdGgpKSxcbiAgICApO1xuICAgIHJldHVybiBkZXNlcmlhbGl6ZVN0YXQodmFsdWUpO1xuICB9XG5cbiAgLyoqIFJvdGF0ZSB0aGlzIHNjb3BlJ3MgY2FjaGUgZ2VuZXJhdGlvbiBzbyB0aGUgbmV4dCByZWFkIHJlbG9hZHMgaXQuICovXG4gIGFzeW5jIGludmFsaWRhdGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY2FjaGUgPSBhd2FpdCBDYWNoZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKTtcbiAgICBhd2FpdCBjYWNoZS5zZXQodGhpcy5nZW5lcmF0aW9uS2V5KGNhY2hlKSwgcmFuZG9tVVVJRCgpLCB7XG4gICAgICB0dGw6IHRoaXMudHRsU2VjICogMixcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY2FjaGVkPFQ+KFxuICAgIG9wZXJhdGlvbjogc3RyaW5nLFxuICAgIGlucHV0UGF0aDogc3RyaW5nLFxuICAgIG9wdGlvbnM6IHVua25vd24sXG4gICAgbG9hZDogKHNvdXJjZTogRmlsZVN5c3RlbSkgPT4gUHJvbWlzZTxUPixcbiAgKTogUHJvbWlzZTxUPiB7XG4gICAgY29uc3Qgc291cmNlID0gdGhpcy5zb3VyY2U7XG4gICAgY29uc3QgY2FjaGUgPSBhd2FpdCBDYWNoZU1hbmFnZXIuZ2V0SW5zdGFuY2UoKTtcbiAgICBjb25zdCBnZW5lcmF0aW9uID0gYXdhaXQgdGhpcy5nZW5lcmF0aW9uKGNhY2hlKTtcbiAgICByZXR1cm4gY2FjaGUuZ2V0T3JFeGVjdXRlKFxuICAgICAgW1xuICAgICAgICBDQUNIRV9OQU1FU1BBQ0UsXG4gICAgICAgIHRoaXMuaG9zdCxcbiAgICAgICAgdGhpcy5yb290LFxuICAgICAgICBnZW5lcmF0aW9uLFxuICAgICAgICBvcGVyYXRpb24sXG4gICAgICAgIHNvdXJjZS5yZXNvbHZlUGF0aChpbnB1dFBhdGgpLFxuICAgICAgICBvYmplY3QudG9TdGFibGVLZXkob3B0aW9ucyA/PyB7fSksXG4gICAgICBdLFxuICAgICAgKCkgPT4gbG9hZChzb3VyY2UpLFxuICAgICAgdGhpcy51c2VyS2V5LFxuICAgICAgeyB0dGw6IHRoaXMudHRsU2VjIH0sXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZ2VuZXJhdGlvbihjYWNoZTogQ2FjaGVNYW5hZ2VyKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gY2FjaGUuZ2V0T3JFeGVjdXRlKFxuICAgICAgW0NBQ0hFX05BTUVTUEFDRSwgXCJnZW5lcmF0aW9uXCIsIHRoaXMuaG9zdCwgdGhpcy5yb290XSxcbiAgICAgIGFzeW5jICgpID0+IHJhbmRvbVVVSUQoKSxcbiAgICAgIHRoaXMudXNlcktleSxcbiAgICAgIHsgdHRsOiB0aGlzLnR0bFNlYyAqIDIgfSxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0aW9uS2V5KGNhY2hlOiBDYWNoZU1hbmFnZXIpOiBzdHJpbmcge1xuICAgIHJldHVybiBjYWNoZS5nZW5lcmF0ZUtleShbQ0FDSEVfTkFNRVNQQUNFLCBcImdlbmVyYXRpb25cIiwgdGhpcy5ob3N0LCB0aGlzLnJvb3RdLCB0aGlzLnVzZXJLZXkpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBtdXRhdGUocnVuOiAoc291cmNlOiBGaWxlU3lzdGVtKSA9PiBQcm9taXNlPHZvaWQ+KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgc291cmNlID0gdGhpcy5zb3VyY2U7XG4gICAgYXdhaXQgcnVuKHNvdXJjZSk7XG4gICAgYXdhaXQgdGhpcy5pbnZhbGlkYXRlKCk7XG4gIH1cbn1cblxuLyoqIFJldHVybiBvbmUgc3RhYmxlIE1hc3RyYSBtb3VudCBwZXIgcmVzb2x2ZWQgdXNlciwgaG9zdCwgYW5kIHNvdXJjZSByb290LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNhY2hlZFdvcmtzcGFjZVNraWxsTW91bnQoXG4gIG9wdGlvbnM6IEFwcEtpdENhY2hlZEZpbGVTeXN0ZW1PcHRpb25zLFxuKTogQ2FjaGVkV29ya3NwYWNlU2tpbGxNb3VudCB7XG4gIGNvbnN0IGNhY2hlS2V5ID0gb2JqZWN0LnRvU3RhYmxlS2V5KHtcbiAgICBob3N0OiBvcHRpb25zLmhvc3QsXG4gICAgcmVhZE9ubHk6IG9wdGlvbnMuc291cmNlLnJlYWRPbmx5LFxuICAgIHJvb3Q6IG9wdGlvbnMuc291cmNlLnJvb3QsXG4gICAgdXNlcktleTogb3B0aW9ucy51c2VyS2V5LFxuICB9KTtcbiAgY29uc3QgZXhpc3RpbmcgPSBzY29wZWRNb3VudHMuZ2V0KGNhY2hlS2V5KTtcbiAgaWYgKGV4aXN0aW5nKSB7XG4gICAgZXhpc3RpbmcuY2FjaGUuYmluZChvcHRpb25zLnNvdXJjZSk7XG4gICAgc2NvcGVkTW91bnRzLmRlbGV0ZShjYWNoZUtleSk7XG4gICAgc2NvcGVkTW91bnRzLnNldChjYWNoZUtleSwgZXhpc3RpbmcpO1xuICAgIHJldHVybiB7IGNhY2hlS2V5LCBmaWxlc3lzdGVtOiBleGlzdGluZy5hZGFwdGVyIH07XG4gIH1cblxuICBjb25zdCBjYWNoZSA9IG5ldyBBcHBLaXRDYWNoZWRGaWxlU3lzdGVtKG9wdGlvbnMpO1xuICBjb25zdCBlbnRyeTogU2NvcGVkTW91bnRFbnRyeSA9IHtcbiAgICBhZGFwdGVyOiBmaWxlc3lzdGVtcyhjYWNoZSwge1xuICAgICAgaWQ6IGNhY2hlLmlkLFxuICAgICAgcmVhZE9ubHk6IG9wdGlvbnMuc291cmNlLnJlYWRPbmx5LFxuICAgIH0pLFxuICAgIGNhY2hlLFxuICAgIGhvc3Q6IG9wdGlvbnMuaG9zdCxcbiAgICByb290OiBvcHRpb25zLnNvdXJjZS5yb290LFxuICAgIHVzZXJLZXk6IG9wdGlvbnMudXNlcktleSxcbiAgfTtcbiAgc2NvcGVkTW91bnRzLnNldChjYWNoZUtleSwgZW50cnkpO1xuICB0cmltU2NvcGVkTW91bnRzKCk7XG4gIHJldHVybiB7IGNhY2hlS2V5LCBmaWxlc3lzdGVtOiBlbnRyeS5hZGFwdGVyIH07XG59XG5cbi8qKiBJbnZhbGlkYXRlIG9uZSB1c2VyJ3MgY2FjaGVkIHdvcmtzcGFjZSBza2lsbCBzY29wZS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjbGVhcldvcmtzcGFjZVNraWxsQ2FjaGUob3B0aW9uczoge1xuICBob3N0OiBzdHJpbmc7XG4gIHJvb3Q/OiBzdHJpbmc7XG4gIHVzZXJLZXk6IHN0cmluZztcbn0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgbWF0Y2hlcyA9IFsuLi5zY29wZWRNb3VudHMuZW50cmllcygpXS5maWx0ZXIoXG4gICAgKFssIGVudHJ5XSkgPT5cbiAgICAgIGVudHJ5Lmhvc3QgPT09IG9wdGlvbnMuaG9zdCAmJlxuICAgICAgZW50cnkudXNlcktleSA9PT0gb3B0aW9ucy51c2VyS2V5ICYmXG4gICAgICAob3B0aW9ucy5yb290ID09PSB1bmRlZmluZWQgfHwgZW50cnkucm9vdCA9PT0gb3B0aW9ucy5yb290KSxcbiAgKTtcbiAgYXdhaXQgUHJvbWlzZS5hbGwobWF0Y2hlcy5tYXAoKFssIGVudHJ5XSkgPT4gZW50cnkuY2FjaGUuaW52YWxpZGF0ZSgpKSk7XG59XG5cbmZ1bmN0aW9uIGNhY2hlVHRsU2VjKHR0bE1zID0gREVGQVVMVF9XT1JLU1BBQ0VfU0tJTExfQ0FDSEVfVFRMX01TKTogbnVtYmVyIHtcbiAgaWYgKCFOdW1iZXIuaXNGaW5pdGUodHRsTXMpIHx8IHR0bE1zIDw9IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJXb3Jrc3BhY2Ugc2tpbGwgY2FjaGUgdHRsTXMgbXVzdCBiZSBhIHBvc2l0aXZlIGZpbml0ZSBudW1iZXJcIik7XG4gIH1cbiAgcmV0dXJuIE1hdGgubWF4KDEsIE1hdGguY2VpbCh0dGxNcyAvIDEwMDApKTtcbn1cblxuZnVuY3Rpb24gc2VyaWFsaXplU3RhdCh2YWx1ZTogRmlsZVN0YXQpOiBDYWNoZWRGaWxlU3RhdCB7XG4gIGNvbnN0IHsgYWNjZXNzZWRBdCwgY3JlYXRlZEF0LCBtb2RpZmllZEF0LCAuLi5zdGF0IH0gPSB2YWx1ZTtcbiAgcmV0dXJuIHtcbiAgICAuLi5zdGF0LFxuICAgIC4uLihhY2Nlc3NlZEF0ID8geyBhY2Nlc3NlZEF0OiBhY2Nlc3NlZEF0LmdldFRpbWUoKSB9IDoge30pLFxuICAgIC4uLihjcmVhdGVkQXQgPyB7IGNyZWF0ZWRBdDogY3JlYXRlZEF0LmdldFRpbWUoKSB9IDoge30pLFxuICAgIC4uLihtb2RpZmllZEF0ID8geyBtb2RpZmllZEF0OiBtb2RpZmllZEF0LmdldFRpbWUoKSB9IDoge30pLFxuICB9O1xufVxuXG5mdW5jdGlvbiBkZXNlcmlhbGl6ZVN0YXQodmFsdWU6IENhY2hlZEZpbGVTdGF0KTogRmlsZVN0YXQge1xuICBjb25zdCB7IGFjY2Vzc2VkQXQsIGNyZWF0ZWRBdCwgbW9kaWZpZWRBdCwgLi4uc3RhdCB9ID0gdmFsdWU7XG4gIHJldHVybiB7XG4gICAgLi4uc3RhdCxcbiAgICAuLi4oYWNjZXNzZWRBdCAhPT0gdW5kZWZpbmVkID8geyBhY2Nlc3NlZEF0OiBuZXcgRGF0ZShhY2Nlc3NlZEF0KSB9IDoge30pLFxuICAgIC4uLihjcmVhdGVkQXQgIT09IHVuZGVmaW5lZCA/IHsgY3JlYXRlZEF0OiBuZXcgRGF0ZShjcmVhdGVkQXQpIH0gOiB7fSksXG4gICAgLi4uKG1vZGlmaWVkQXQgIT09IHVuZGVmaW5lZCA/IHsgbW9kaWZpZWRBdDogbmV3IERhdGUobW9kaWZpZWRBdCkgfSA6IHt9KSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gdHJpbVNjb3BlZE1vdW50cygpOiB2b2lkIHtcbiAgd2hpbGUgKHNjb3BlZE1vdW50cy5zaXplID4gREVGQVVMVF9NQVhfU0NPUEVEX01PVU5UUykge1xuICAgIGNvbnN0IG9sZGVzdCA9IHNjb3BlZE1vdW50cy5rZXlzKCkubmV4dCgpLnZhbHVlO1xuICAgIGlmIChvbGRlc3QgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICAgIHNjb3BlZE1vdW50cy5kZWxldGUob2xkZXN0KTtcbiAgfVxufVxuIl19
@@ -60,6 +60,11 @@ export interface WorkspaceMountContribution {
60
60
  mounts: Record<string, WorkspaceFilesystem>;
61
61
  /** Paths within the composite namespace where `SKILL.md` files are scanned. */
62
62
  skillPaths?: string[];
63
+ /**
64
+ * Stable identity for this contribution. When every non-empty contribution
65
+ * supplies one, Mastra reuses the resolved source across requests.
66
+ */
67
+ cacheKey?: string;
63
68
  }
64
69
  /** Contributes filesystem mounts (and optional skill paths) for one request. */
65
70
  export type WorkspaceMountResolver = (context: WorkspaceMountContext) => WorkspaceMountContribution | Promise<WorkspaceMountContribution>;
@@ -94,6 +99,11 @@ export interface CreateWorkspaceOptions {
94
99
  skills?: SkillsResolver;
95
100
  /** Forwarded to Mastra when skill discovery is enabled. */
96
101
  checkSkillFileMtime?: boolean;
102
+ /**
103
+ * AppKit cache TTL for Databricks skill metadata and content.
104
+ * Defaults to five minutes.
105
+ */
106
+ workspaceSkillRefreshTtlMs?: number;
97
107
  /** Enable BM25 keyword search over indexed workspace content. */
98
108
  bm25?: boolean;
99
109
  /**