@mastra/editor 0.8.2-alpha.0 → 0.9.0-alpha.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,55 @@
1
1
  # @mastra/editor
2
2
 
3
+ ## 0.9.0-alpha.2
4
+
5
+ ### Minor Changes
6
+
7
+ - Added an `editor.favorites` namespace so direct (non-HTTP) callers can favorite, unfavorite, and query favorited stored agents/skills through the editor instance. ([#16749](https://github.com/mastra-ai/mastra/pull/16749))
8
+
9
+ ```ts
10
+ import { MastraEditor } from '@mastra/editor';
11
+
12
+ const editor = new MastraEditor({ mastra });
13
+
14
+ // Toggle
15
+ await editor.favorites.favorite({ userId, entityType: 'agent', entityId });
16
+ await editor.favorites.unfavorite({ userId, entityType: 'agent', entityId });
17
+
18
+ // Lookups
19
+ const isFav = await editor.favorites.isFavorited({ userId, entityType: 'agent', entityId });
20
+ const favSet = await editor.favorites.isFavoritedBatch({ userId, entityType: 'agent', entityIds });
21
+ const ids = await editor.favorites.listFavoritedIds({ userId, entityType: 'agent' });
22
+ ```
23
+
24
+ The namespace performs the storage mutation only — visibility and ownership enforcement still belong to the caller (the HTTP route handlers in `@mastra/server` already do this).
25
+
26
+ ### Patch Changes
27
+
28
+ - Updated dependencies [[`5556cc1`](https://github.com/mastra-ai/mastra/commit/5556cc1befec71518d84f826b3bfe3a079a9daf7), [`5499303`](https://github.com/mastra-ai/mastra/commit/54993032c1ebc09642625b78d2014e0cf84a3cae), [`e47bca7`](https://github.com/mastra-ai/mastra/commit/e47bca7b72866d3abd173b9f530ac4318113a8ff), [`0031d0f`](https://github.com/mastra-ai/mastra/commit/0031d0f13831d7843ac5d498734a7d92862e2ce3), [`3498b49`](https://github.com/mastra-ai/mastra/commit/3498b4946be94f4313cd817733589680dcda5278), [`359439b`](https://github.com/mastra-ai/mastra/commit/359439bb8c635e048176306828195f8297f50021)]:
29
+ - @mastra/core@1.36.0-alpha.3
30
+
31
+ ## 0.9.0-alpha.1
32
+
33
+ ### Minor Changes
34
+
35
+ - `EditorWorkspaceNamespace` can now snapshot a live `Workspace` for persistence — the reverse of `hydrateSnapshotToWorkspace()`: ([#16673](https://github.com/mastra-ai/mastra/pull/16673))
36
+
37
+ ```ts
38
+ const snapshot = await editor.workspace.snapshotFromWorkspace(runtimeWorkspace);
39
+ await editor.workspace.create({ id: 'my-workspace', ...snapshot });
40
+ ```
41
+
42
+ `snapshotFromWorkspace()` is `async` and awaits `sandbox.getInfo()` and `filesystem.getInfo()` so async providers like `CompositeFilesystem` keep their mount metadata in the stored config.
43
+
44
+ Also includes two smaller behavioral fixes:
45
+ - `EditorSkillNamespace.publishSkillFromSource()` stores the new `files` field on the published skill version and strips `undefined` keys before calling `update()` (libsql/pg adapters reject `undefined` bind arguments).
46
+ - `CrudEditorNamespace.clearCache(id)` always calls `onCacheEvict(id)`, even when the entity wasn't cached, so subclasses can clean up runtime registries for version-specific lookups that bypass the editor cache.
47
+
48
+ ### Patch Changes
49
+
50
+ - Updated dependencies [[`5ba7253`](https://github.com/mastra-ai/mastra/commit/5ba7253745c85e8df8012a76d954c640ffa336f7), [`f73980d`](https://github.com/mastra-ai/mastra/commit/f73980d651eb5f7f1ab20582de4615a1b6f10fce), [`9c88701`](https://github.com/mastra-ai/mastra/commit/9c8870195b41a38dc40b6ba2aa55eda04df8fa69), [`4e88dc6`](https://github.com/mastra-ai/mastra/commit/4e88dc6b89f154c0eae37221c8126be0c23c569f), [`19018f0`](https://github.com/mastra-ai/mastra/commit/19018f05722af74a5978781a7731a654b26f7f2a)]:
51
+ - @mastra/core@1.36.0-alpha.2
52
+
3
53
  ## 0.8.2-alpha.0
4
54
 
5
55
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -32,6 +32,7 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  CrudEditorNamespace: () => CrudEditorNamespace,
34
34
  EditorAgentNamespace: () => EditorAgentNamespace,
35
+ EditorFavoritesNamespace: () => EditorFavoritesNamespace,
35
36
  EditorMCPNamespace: () => EditorMCPNamespace,
36
37
  EditorMCPServerNamespace: () => EditorMCPServerNamespace,
37
38
  EditorNamespace: () => EditorNamespace,
@@ -154,11 +155,8 @@ var CrudEditorNamespace = class extends EditorNamespace {
154
155
  */
155
156
  clearCache(id) {
156
157
  if (id) {
157
- const wasCached = this._cache.has(id);
158
158
  this._cache.delete(id);
159
- if (wasCached) {
160
- this.onCacheEvict(id);
161
- }
159
+ this.onCacheEvict(id);
162
160
  this.logger?.debug(`[clearCache] Cleared cache for "${id}"`);
163
161
  } else {
164
162
  for (const cachedId of Array.from(this._cache.keys())) {
@@ -1804,6 +1802,59 @@ var EditorWorkspaceNamespace = class extends CrudEditorNamespace {
1804
1802
  }
1805
1803
  return new import_workspace2.Workspace(config);
1806
1804
  }
1805
+ /**
1806
+ * Serialize a runtime Workspace instance into a StorageWorkspaceSnapshotType.
1807
+ * The reverse of hydrateSnapshotToWorkspace — extracts provider IDs and config
1808
+ * from live filesystem/sandbox instances so the workspace can be persisted to the DB.
1809
+ */
1810
+ async snapshotFromWorkspace(workspace) {
1811
+ const snapshot = {
1812
+ name: workspace.name
1813
+ };
1814
+ const fs = workspace.filesystem;
1815
+ if (fs) {
1816
+ if (fs instanceof import_workspace2.CompositeFilesystem) {
1817
+ const mounts = {};
1818
+ for (const [mountPath, mountedFs] of fs.mounts) {
1819
+ mounts[mountPath] = await this.serializeFilesystem(mountedFs);
1820
+ }
1821
+ snapshot.mounts = mounts;
1822
+ } else {
1823
+ snapshot.filesystem = await this.serializeFilesystem(fs);
1824
+ }
1825
+ }
1826
+ const sandbox = workspace.sandbox;
1827
+ if (sandbox) {
1828
+ const info = typeof sandbox.getInfo === "function" ? await sandbox.getInfo() : void 0;
1829
+ snapshot.sandbox = {
1830
+ provider: sandbox.provider,
1831
+ config: info?.metadata ?? {}
1832
+ };
1833
+ }
1834
+ const tools = workspace.getToolsConfig();
1835
+ if (tools) {
1836
+ const storageTools = {};
1837
+ if (typeof tools.enabled === "boolean") storageTools.enabled = tools.enabled;
1838
+ if (typeof tools.requireApproval === "boolean") storageTools.requireApproval = tools.requireApproval;
1839
+ if (Object.keys(storageTools).length > 0) {
1840
+ snapshot.tools = storageTools;
1841
+ }
1842
+ }
1843
+ return snapshot;
1844
+ }
1845
+ /**
1846
+ * Serialize a runtime WorkspaceFilesystem into a StorageFilesystemConfig.
1847
+ * Awaits getInfo() so async providers like CompositeFilesystem keep their mount metadata.
1848
+ */
1849
+ async serializeFilesystem(fs) {
1850
+ const info = typeof fs.getInfo === "function" ? await fs.getInfo() : void 0;
1851
+ const metadata = info && typeof info === "object" && "metadata" in info ? info.metadata : void 0;
1852
+ return {
1853
+ provider: fs.provider,
1854
+ config: metadata ?? {},
1855
+ readOnly: fs.readOnly
1856
+ };
1857
+ }
1807
1858
  /**
1808
1859
  * Resolve a stored filesystem config to a runtime WorkspaceFilesystem instance.
1809
1860
  * Looks up the provider by ID in the editor's registry (which includes built-in providers).
@@ -1880,11 +1931,16 @@ var EditorSkillNamespace = class extends CrudEditorNamespace {
1880
1931
  const blobStore = await this.editor.resolveBlobStore();
1881
1932
  if (!blobStore)
1882
1933
  throw new Error("No blob store is configured. Register one via new MastraEditor({ blobStores: [...] })");
1883
- const { snapshot, tree } = await (0, import_workspace3.publishSkillFromSource)(source, skillPath, blobStore);
1934
+ const { snapshot, tree, files } = await (0, import_workspace3.publishSkillFromSource)(source, skillPath, blobStore);
1935
+ const snapshotUpdate = {};
1936
+ for (const [key, value] of Object.entries(snapshot)) {
1937
+ if (value !== void 0) snapshotUpdate[key] = value;
1938
+ }
1884
1939
  await skillStore.update({
1885
1940
  id: skillId,
1886
- ...snapshot,
1941
+ ...snapshotUpdate,
1887
1942
  tree,
1943
+ files,
1888
1944
  status: "published"
1889
1945
  });
1890
1946
  const latestVersion = await skillStore.getLatestVersion(skillId);
@@ -1903,6 +1959,59 @@ var EditorSkillNamespace = class extends CrudEditorNamespace {
1903
1959
  }
1904
1960
  };
1905
1961
 
1962
+ // src/namespaces/favorites.ts
1963
+ var EditorFavoritesNamespace = class extends EditorNamespace {
1964
+ async favorite(input) {
1965
+ this.ensureRegistered();
1966
+ const store = await this.getFavoritesStore();
1967
+ return store.favorite({
1968
+ userId: input.userId,
1969
+ entityType: input.entityType,
1970
+ entityId: input.entityId
1971
+ });
1972
+ }
1973
+ async unfavorite(input) {
1974
+ this.ensureRegistered();
1975
+ const store = await this.getFavoritesStore();
1976
+ return store.unfavorite({
1977
+ userId: input.userId,
1978
+ entityType: input.entityType,
1979
+ entityId: input.entityId
1980
+ });
1981
+ }
1982
+ async isFavorited(input) {
1983
+ this.ensureRegistered();
1984
+ const store = await this.getFavoritesStore();
1985
+ return store.isFavorited({
1986
+ userId: input.userId,
1987
+ entityType: input.entityType,
1988
+ entityId: input.entityId
1989
+ });
1990
+ }
1991
+ async isFavoritedBatch(input) {
1992
+ this.ensureRegistered();
1993
+ if (input.entityIds.length === 0) return /* @__PURE__ */ new Set();
1994
+ const store = await this.getFavoritesStore();
1995
+ return store.isFavoritedBatch({
1996
+ userId: input.userId,
1997
+ entityType: input.entityType,
1998
+ entityIds: input.entityIds
1999
+ });
2000
+ }
2001
+ async listFavoritedIds(input) {
2002
+ this.ensureRegistered();
2003
+ const store = await this.getFavoritesStore();
2004
+ return store.listFavoritedIds({ userId: input.userId, entityType: input.entityType });
2005
+ }
2006
+ async getFavoritesStore() {
2007
+ const storage = this.mastra?.getStorage();
2008
+ if (!storage) throw new Error("Storage is not configured");
2009
+ const store = await storage.getStore("favorites");
2010
+ if (!store) throw new Error("Favorites storage domain is not available");
2011
+ return store;
2012
+ }
2013
+ };
2014
+
1906
2015
  // src/providers.ts
1907
2016
  var import_workspace5 = require("@mastra/core/workspace");
1908
2017
  var import_workspace6 = require("@mastra/core/workspace");
@@ -1981,6 +2090,7 @@ var MastraEditor = class {
1981
2090
  this.scorer = new EditorScorerNamespace(this);
1982
2091
  this.workspace = new EditorWorkspaceNamespace(this);
1983
2092
  this.skill = new EditorSkillNamespace(this);
2093
+ this.favorites = new EditorFavoritesNamespace(this);
1984
2094
  }
1985
2095
  /**
1986
2096
  * Register this editor with a Mastra instance.
@@ -2053,6 +2163,7 @@ var MastraEditor = class {
2053
2163
  0 && (module.exports = {
2054
2164
  CrudEditorNamespace,
2055
2165
  EditorAgentNamespace,
2166
+ EditorFavoritesNamespace,
2056
2167
  EditorMCPNamespace,
2057
2168
  EditorMCPServerNamespace,
2058
2169
  EditorNamespace,
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Mastra } from '@mastra/core';
2
- import { GetByIdOptions, FilesystemProvider, SandboxProvider, IMastraEditor, BlobStoreProvider, MastraEditorConfig } from '@mastra/core/editor';
2
+ import { GetByIdOptions, IEditorFavoritesNamespace, EditorFavoriteTargetInput, EditorFavoriteToggleResult, EditorIsFavoritedBatchInput, EditorListFavoritedIdsInput, FilesystemProvider, SandboxProvider, IMastraEditor, BlobStoreProvider, MastraEditorConfig } from '@mastra/core/editor';
3
3
  export { MastraEditorConfig } from '@mastra/core/editor';
4
4
  import { IMastraLogger } from '@mastra/core/logger';
5
5
  import { ProcessorProvider } from '@mastra/core/processor-provider';
@@ -275,6 +275,17 @@ declare class EditorWorkspaceNamespace extends CrudEditorNamespace<StorageCreate
275
275
  hydrateSnapshotToWorkspace(id: string, snapshot: StorageWorkspaceSnapshotType, options?: {
276
276
  skillSource?: SkillSource;
277
277
  }): Promise<Workspace<WorkspaceFilesystem | undefined, WorkspaceSandbox | undefined, Record<string, WorkspaceFilesystem> | undefined>>;
278
+ /**
279
+ * Serialize a runtime Workspace instance into a StorageWorkspaceSnapshotType.
280
+ * The reverse of hydrateSnapshotToWorkspace — extracts provider IDs and config
281
+ * from live filesystem/sandbox instances so the workspace can be persisted to the DB.
282
+ */
283
+ snapshotFromWorkspace(workspace: Workspace): Promise<StorageWorkspaceSnapshotType>;
284
+ /**
285
+ * Serialize a runtime WorkspaceFilesystem into a StorageFilesystemConfig.
286
+ * Awaits getInfo() so async providers like CompositeFilesystem keep their mount metadata.
287
+ */
288
+ private serializeFilesystem;
278
289
  /**
279
290
  * Resolve a stored filesystem config to a runtime WorkspaceFilesystem instance.
280
291
  * Looks up the provider by ID in the editor's registry (which includes built-in providers).
@@ -299,6 +310,23 @@ declare class EditorSkillNamespace extends CrudEditorNamespace<StorageCreateSkil
299
310
  publish(skillId: string, source: SkillSource, skillPath: string): Promise<StorageResolvedSkillType>;
300
311
  }
301
312
 
313
+ /**
314
+ * Favorites namespace.
315
+ *
316
+ * Verifies the target entity exists and performs the storage mutation.
317
+ * Visibility / ownership enforcement (`assertReadAccess`) lives at the
318
+ * route handler in `@mastra/server`. Direct callers of this namespace must
319
+ * perform their own access check before invoking these methods.
320
+ */
321
+ declare class EditorFavoritesNamespace extends EditorNamespace implements IEditorFavoritesNamespace {
322
+ favorite(input: EditorFavoriteTargetInput): Promise<EditorFavoriteToggleResult>;
323
+ unfavorite(input: EditorFavoriteTargetInput): Promise<EditorFavoriteToggleResult>;
324
+ isFavorited(input: EditorFavoriteTargetInput): Promise<boolean>;
325
+ isFavoritedBatch(input: EditorIsFavoritedBatchInput): Promise<Set<string>>;
326
+ listFavoritedIds(input: EditorListFavoritedIdsInput): Promise<string[]>;
327
+ private getFavoritesStore;
328
+ }
329
+
302
330
  /**
303
331
  * TemplateEngine: Simple variable interpolation for prompt block content.
304
332
  *
@@ -417,6 +445,7 @@ declare class MastraEditor implements IMastraEditor {
417
445
  readonly scorer: EditorScorerNamespace;
418
446
  readonly workspace: EditorWorkspaceNamespace;
419
447
  readonly skill: EditorSkillNamespace;
448
+ readonly favorites: EditorFavoritesNamespace;
420
449
  constructor(config?: MastraEditorConfig);
421
450
  /**
422
451
  * Register this editor with a Mastra instance.
@@ -450,4 +479,4 @@ declare class MastraEditor implements IMastraEditor {
450
479
  resolveBlobStore(providerId?: string, providerConfig?: Record<string, unknown>): Promise<BlobStore>;
451
480
  }
452
481
 
453
- export { CrudEditorNamespace, EditorAgentNamespace, EditorMCPNamespace, EditorMCPServerNamespace, EditorNamespace, EditorPromptNamespace, EditorScorerNamespace, EditorSkillNamespace, EditorWorkspaceNamespace, MastraEditor, type StorageAdapter, evaluateRuleGroup, localFilesystemProvider, localSandboxProvider, renderTemplate, resolveInstructionBlocks };
482
+ export { CrudEditorNamespace, EditorAgentNamespace, EditorFavoritesNamespace, EditorMCPNamespace, EditorMCPServerNamespace, EditorNamespace, EditorPromptNamespace, EditorScorerNamespace, EditorSkillNamespace, EditorWorkspaceNamespace, MastraEditor, type StorageAdapter, evaluateRuleGroup, localFilesystemProvider, localSandboxProvider, renderTemplate, resolveInstructionBlocks };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Mastra } from '@mastra/core';
2
- import { GetByIdOptions, FilesystemProvider, SandboxProvider, IMastraEditor, BlobStoreProvider, MastraEditorConfig } from '@mastra/core/editor';
2
+ import { GetByIdOptions, IEditorFavoritesNamespace, EditorFavoriteTargetInput, EditorFavoriteToggleResult, EditorIsFavoritedBatchInput, EditorListFavoritedIdsInput, FilesystemProvider, SandboxProvider, IMastraEditor, BlobStoreProvider, MastraEditorConfig } from '@mastra/core/editor';
3
3
  export { MastraEditorConfig } from '@mastra/core/editor';
4
4
  import { IMastraLogger } from '@mastra/core/logger';
5
5
  import { ProcessorProvider } from '@mastra/core/processor-provider';
@@ -275,6 +275,17 @@ declare class EditorWorkspaceNamespace extends CrudEditorNamespace<StorageCreate
275
275
  hydrateSnapshotToWorkspace(id: string, snapshot: StorageWorkspaceSnapshotType, options?: {
276
276
  skillSource?: SkillSource;
277
277
  }): Promise<Workspace<WorkspaceFilesystem | undefined, WorkspaceSandbox | undefined, Record<string, WorkspaceFilesystem> | undefined>>;
278
+ /**
279
+ * Serialize a runtime Workspace instance into a StorageWorkspaceSnapshotType.
280
+ * The reverse of hydrateSnapshotToWorkspace — extracts provider IDs and config
281
+ * from live filesystem/sandbox instances so the workspace can be persisted to the DB.
282
+ */
283
+ snapshotFromWorkspace(workspace: Workspace): Promise<StorageWorkspaceSnapshotType>;
284
+ /**
285
+ * Serialize a runtime WorkspaceFilesystem into a StorageFilesystemConfig.
286
+ * Awaits getInfo() so async providers like CompositeFilesystem keep their mount metadata.
287
+ */
288
+ private serializeFilesystem;
278
289
  /**
279
290
  * Resolve a stored filesystem config to a runtime WorkspaceFilesystem instance.
280
291
  * Looks up the provider by ID in the editor's registry (which includes built-in providers).
@@ -299,6 +310,23 @@ declare class EditorSkillNamespace extends CrudEditorNamespace<StorageCreateSkil
299
310
  publish(skillId: string, source: SkillSource, skillPath: string): Promise<StorageResolvedSkillType>;
300
311
  }
301
312
 
313
+ /**
314
+ * Favorites namespace.
315
+ *
316
+ * Verifies the target entity exists and performs the storage mutation.
317
+ * Visibility / ownership enforcement (`assertReadAccess`) lives at the
318
+ * route handler in `@mastra/server`. Direct callers of this namespace must
319
+ * perform their own access check before invoking these methods.
320
+ */
321
+ declare class EditorFavoritesNamespace extends EditorNamespace implements IEditorFavoritesNamespace {
322
+ favorite(input: EditorFavoriteTargetInput): Promise<EditorFavoriteToggleResult>;
323
+ unfavorite(input: EditorFavoriteTargetInput): Promise<EditorFavoriteToggleResult>;
324
+ isFavorited(input: EditorFavoriteTargetInput): Promise<boolean>;
325
+ isFavoritedBatch(input: EditorIsFavoritedBatchInput): Promise<Set<string>>;
326
+ listFavoritedIds(input: EditorListFavoritedIdsInput): Promise<string[]>;
327
+ private getFavoritesStore;
328
+ }
329
+
302
330
  /**
303
331
  * TemplateEngine: Simple variable interpolation for prompt block content.
304
332
  *
@@ -417,6 +445,7 @@ declare class MastraEditor implements IMastraEditor {
417
445
  readonly scorer: EditorScorerNamespace;
418
446
  readonly workspace: EditorWorkspaceNamespace;
419
447
  readonly skill: EditorSkillNamespace;
448
+ readonly favorites: EditorFavoritesNamespace;
420
449
  constructor(config?: MastraEditorConfig);
421
450
  /**
422
451
  * Register this editor with a Mastra instance.
@@ -450,4 +479,4 @@ declare class MastraEditor implements IMastraEditor {
450
479
  resolveBlobStore(providerId?: string, providerConfig?: Record<string, unknown>): Promise<BlobStore>;
451
480
  }
452
481
 
453
- export { CrudEditorNamespace, EditorAgentNamespace, EditorMCPNamespace, EditorMCPServerNamespace, EditorNamespace, EditorPromptNamespace, EditorScorerNamespace, EditorSkillNamespace, EditorWorkspaceNamespace, MastraEditor, type StorageAdapter, evaluateRuleGroup, localFilesystemProvider, localSandboxProvider, renderTemplate, resolveInstructionBlocks };
482
+ export { CrudEditorNamespace, EditorAgentNamespace, EditorFavoritesNamespace, EditorMCPNamespace, EditorMCPServerNamespace, EditorNamespace, EditorPromptNamespace, EditorScorerNamespace, EditorSkillNamespace, EditorWorkspaceNamespace, MastraEditor, type StorageAdapter, evaluateRuleGroup, localFilesystemProvider, localSandboxProvider, renderTemplate, resolveInstructionBlocks };
package/dist/index.js CHANGED
@@ -106,11 +106,8 @@ var CrudEditorNamespace = class extends EditorNamespace {
106
106
  */
107
107
  clearCache(id) {
108
108
  if (id) {
109
- const wasCached = this._cache.has(id);
110
109
  this._cache.delete(id);
111
- if (wasCached) {
112
- this.onCacheEvict(id);
113
- }
110
+ this.onCacheEvict(id);
114
111
  this.logger?.debug(`[clearCache] Cleared cache for "${id}"`);
115
112
  } else {
116
113
  for (const cachedId of Array.from(this._cache.keys())) {
@@ -1683,7 +1680,7 @@ Explain your reasoning for this score in a clear, concise paragraph.`;
1683
1680
  };
1684
1681
 
1685
1682
  // src/namespaces/workspace.ts
1686
- import { Workspace as Workspace2 } from "@mastra/core/workspace";
1683
+ import { Workspace as Workspace2, CompositeFilesystem } from "@mastra/core/workspace";
1687
1684
  var EditorWorkspaceNamespace = class extends CrudEditorNamespace {
1688
1685
  onCacheEvict(_id) {
1689
1686
  }
@@ -1756,6 +1753,59 @@ var EditorWorkspaceNamespace = class extends CrudEditorNamespace {
1756
1753
  }
1757
1754
  return new Workspace2(config);
1758
1755
  }
1756
+ /**
1757
+ * Serialize a runtime Workspace instance into a StorageWorkspaceSnapshotType.
1758
+ * The reverse of hydrateSnapshotToWorkspace — extracts provider IDs and config
1759
+ * from live filesystem/sandbox instances so the workspace can be persisted to the DB.
1760
+ */
1761
+ async snapshotFromWorkspace(workspace) {
1762
+ const snapshot = {
1763
+ name: workspace.name
1764
+ };
1765
+ const fs = workspace.filesystem;
1766
+ if (fs) {
1767
+ if (fs instanceof CompositeFilesystem) {
1768
+ const mounts = {};
1769
+ for (const [mountPath, mountedFs] of fs.mounts) {
1770
+ mounts[mountPath] = await this.serializeFilesystem(mountedFs);
1771
+ }
1772
+ snapshot.mounts = mounts;
1773
+ } else {
1774
+ snapshot.filesystem = await this.serializeFilesystem(fs);
1775
+ }
1776
+ }
1777
+ const sandbox = workspace.sandbox;
1778
+ if (sandbox) {
1779
+ const info = typeof sandbox.getInfo === "function" ? await sandbox.getInfo() : void 0;
1780
+ snapshot.sandbox = {
1781
+ provider: sandbox.provider,
1782
+ config: info?.metadata ?? {}
1783
+ };
1784
+ }
1785
+ const tools = workspace.getToolsConfig();
1786
+ if (tools) {
1787
+ const storageTools = {};
1788
+ if (typeof tools.enabled === "boolean") storageTools.enabled = tools.enabled;
1789
+ if (typeof tools.requireApproval === "boolean") storageTools.requireApproval = tools.requireApproval;
1790
+ if (Object.keys(storageTools).length > 0) {
1791
+ snapshot.tools = storageTools;
1792
+ }
1793
+ }
1794
+ return snapshot;
1795
+ }
1796
+ /**
1797
+ * Serialize a runtime WorkspaceFilesystem into a StorageFilesystemConfig.
1798
+ * Awaits getInfo() so async providers like CompositeFilesystem keep their mount metadata.
1799
+ */
1800
+ async serializeFilesystem(fs) {
1801
+ const info = typeof fs.getInfo === "function" ? await fs.getInfo() : void 0;
1802
+ const metadata = info && typeof info === "object" && "metadata" in info ? info.metadata : void 0;
1803
+ return {
1804
+ provider: fs.provider,
1805
+ config: metadata ?? {},
1806
+ readOnly: fs.readOnly
1807
+ };
1808
+ }
1759
1809
  /**
1760
1810
  * Resolve a stored filesystem config to a runtime WorkspaceFilesystem instance.
1761
1811
  * Looks up the provider by ID in the editor's registry (which includes built-in providers).
@@ -1832,11 +1882,16 @@ var EditorSkillNamespace = class extends CrudEditorNamespace {
1832
1882
  const blobStore = await this.editor.resolveBlobStore();
1833
1883
  if (!blobStore)
1834
1884
  throw new Error("No blob store is configured. Register one via new MastraEditor({ blobStores: [...] })");
1835
- const { snapshot, tree } = await publishSkillFromSource(source, skillPath, blobStore);
1885
+ const { snapshot, tree, files } = await publishSkillFromSource(source, skillPath, blobStore);
1886
+ const snapshotUpdate = {};
1887
+ for (const [key, value] of Object.entries(snapshot)) {
1888
+ if (value !== void 0) snapshotUpdate[key] = value;
1889
+ }
1836
1890
  await skillStore.update({
1837
1891
  id: skillId,
1838
- ...snapshot,
1892
+ ...snapshotUpdate,
1839
1893
  tree,
1894
+ files,
1840
1895
  status: "published"
1841
1896
  });
1842
1897
  const latestVersion = await skillStore.getLatestVersion(skillId);
@@ -1855,6 +1910,59 @@ var EditorSkillNamespace = class extends CrudEditorNamespace {
1855
1910
  }
1856
1911
  };
1857
1912
 
1913
+ // src/namespaces/favorites.ts
1914
+ var EditorFavoritesNamespace = class extends EditorNamespace {
1915
+ async favorite(input) {
1916
+ this.ensureRegistered();
1917
+ const store = await this.getFavoritesStore();
1918
+ return store.favorite({
1919
+ userId: input.userId,
1920
+ entityType: input.entityType,
1921
+ entityId: input.entityId
1922
+ });
1923
+ }
1924
+ async unfavorite(input) {
1925
+ this.ensureRegistered();
1926
+ const store = await this.getFavoritesStore();
1927
+ return store.unfavorite({
1928
+ userId: input.userId,
1929
+ entityType: input.entityType,
1930
+ entityId: input.entityId
1931
+ });
1932
+ }
1933
+ async isFavorited(input) {
1934
+ this.ensureRegistered();
1935
+ const store = await this.getFavoritesStore();
1936
+ return store.isFavorited({
1937
+ userId: input.userId,
1938
+ entityType: input.entityType,
1939
+ entityId: input.entityId
1940
+ });
1941
+ }
1942
+ async isFavoritedBatch(input) {
1943
+ this.ensureRegistered();
1944
+ if (input.entityIds.length === 0) return /* @__PURE__ */ new Set();
1945
+ const store = await this.getFavoritesStore();
1946
+ return store.isFavoritedBatch({
1947
+ userId: input.userId,
1948
+ entityType: input.entityType,
1949
+ entityIds: input.entityIds
1950
+ });
1951
+ }
1952
+ async listFavoritedIds(input) {
1953
+ this.ensureRegistered();
1954
+ const store = await this.getFavoritesStore();
1955
+ return store.listFavoritedIds({ userId: input.userId, entityType: input.entityType });
1956
+ }
1957
+ async getFavoritesStore() {
1958
+ const storage = this.mastra?.getStorage();
1959
+ if (!storage) throw new Error("Storage is not configured");
1960
+ const store = await storage.getStore("favorites");
1961
+ if (!store) throw new Error("Favorites storage domain is not available");
1962
+ return store;
1963
+ }
1964
+ };
1965
+
1858
1966
  // src/providers.ts
1859
1967
  import { LocalFilesystem } from "@mastra/core/workspace";
1860
1968
  import { LocalSandbox } from "@mastra/core/workspace";
@@ -1933,6 +2041,7 @@ var MastraEditor = class {
1933
2041
  this.scorer = new EditorScorerNamespace(this);
1934
2042
  this.workspace = new EditorWorkspaceNamespace(this);
1935
2043
  this.skill = new EditorSkillNamespace(this);
2044
+ this.favorites = new EditorFavoritesNamespace(this);
1936
2045
  }
1937
2046
  /**
1938
2047
  * Register this editor with a Mastra instance.
@@ -2004,6 +2113,7 @@ var MastraEditor = class {
2004
2113
  export {
2005
2114
  CrudEditorNamespace,
2006
2115
  EditorAgentNamespace,
2116
+ EditorFavoritesNamespace,
2007
2117
  EditorMCPNamespace,
2008
2118
  EditorMCPServerNamespace,
2009
2119
  EditorNamespace,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/editor",
3
- "version": "0.8.2-alpha.0",
3
+ "version": "0.9.0-alpha.2",
4
4
  "description": "Mastra Editor for agent management and instantiation",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -65,8 +65,8 @@
65
65
  "@arcadeai/arcadejs": "^2.3.0",
66
66
  "@composio/core": "^0.6.5",
67
67
  "@composio/mastra": "^0.6.5",
68
- "@mastra/schema-compat": "1.2.10",
69
- "@mastra/memory": "1.18.3-alpha.0"
68
+ "@mastra/memory": "1.18.3-alpha.0",
69
+ "@mastra/schema-compat": "1.2.10"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@hono/node-server": "^1.19.11",
@@ -76,12 +76,12 @@
76
76
  "vitest": "4.1.5",
77
77
  "zod": "^3.25.76",
78
78
  "@internal/ai-sdk-v4": "0.0.43",
79
- "@internal/ai-v6": "0.0.43",
80
79
  "@internal/ai-sdk-v5": "0.0.43",
81
- "@mastra/hono": "1.4.18-alpha.0",
80
+ "@internal/ai-v6": "0.0.43",
81
+ "@mastra/hono": "1.4.18-alpha.3",
82
82
  "@mastra/libsql": "1.11.0",
83
- "@mastra/core": "1.36.0-alpha.0",
84
- "@mastra/mcp": "1.7.1-alpha.0"
83
+ "@mastra/mcp": "1.7.1-alpha.0",
84
+ "@mastra/core": "1.36.0-alpha.3"
85
85
  },
86
86
  "peerDependencies": {
87
87
  "@mastra/core": ">=1.13.2-0 <2.0.0-0",