@mastra/editor 0.4.0 → 0.5.0-alpha.1

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/dist/index.cjs CHANGED
@@ -36,8 +36,12 @@ __export(index_exports, {
36
36
  EditorNamespace: () => EditorNamespace,
37
37
  EditorPromptNamespace: () => EditorPromptNamespace,
38
38
  EditorScorerNamespace: () => EditorScorerNamespace,
39
+ EditorSkillNamespace: () => EditorSkillNamespace,
40
+ EditorWorkspaceNamespace: () => EditorWorkspaceNamespace,
39
41
  MastraEditor: () => MastraEditor,
40
42
  evaluateRuleGroup: () => evaluateRuleGroup,
43
+ localFilesystemProvider: () => localFilesystemProvider,
44
+ localSandboxProvider: () => localSandboxProvider,
41
45
  renderTemplate: () => renderTemplate,
42
46
  resolveInstructionBlocks: () => resolveInstructionBlocks
43
47
  });
@@ -93,7 +97,7 @@ var CrudEditorNamespace = class extends EditorNamespace {
93
97
  }
94
98
  async getById(id, options) {
95
99
  this.ensureRegistered();
96
- const isVersionRequest = options?.versionId || options?.versionNumber;
100
+ const isVersionRequest = options?.versionId || options?.versionNumber || options?.status;
97
101
  if (!isVersionRequest) {
98
102
  const cached = this._cache.get(id);
99
103
  if (cached) {
@@ -162,8 +166,10 @@ var CrudEditorNamespace = class extends EditorNamespace {
162
166
  };
163
167
 
164
168
  // src/namespaces/agent.ts
169
+ var import_node_crypto = require("crypto");
165
170
  var import_memory = require("@mastra/memory");
166
171
  var import_agent = require("@mastra/core/agent");
172
+ var import_workspace = require("@mastra/core/workspace");
167
173
  var import_schema_compat = require("@mastra/schema-compat");
168
174
  var import_request_context = require("@mastra/core/request-context");
169
175
 
@@ -335,7 +341,7 @@ var EditorMCPNamespace = class _EditorMCPNamespace extends CrudEditorNamespace {
335
341
  onCacheEvict(_id) {
336
342
  }
337
343
  async getStorageAdapter() {
338
- const storage = this.mastra.getStorage();
344
+ const storage = this.mastra?.getStorage();
339
345
  if (!storage) throw new Error("Storage is not configured");
340
346
  const store = await storage.getStore("mcpClients");
341
347
  if (!store) throw new Error("MCP clients storage domain is not available");
@@ -382,7 +388,7 @@ var EditorMCPNamespace = class _EditorMCPNamespace extends CrudEditorNamespace {
382
388
  // src/namespaces/agent.ts
383
389
  var EditorAgentNamespace = class extends CrudEditorNamespace {
384
390
  async getStorageAdapter() {
385
- const storage = this.mastra.getStorage();
391
+ const storage = this.mastra?.getStorage();
386
392
  if (!storage) throw new Error("Storage is not configured");
387
393
  const store = await storage.getStore("agents");
388
394
  if (!store) throw new Error("Agents storage domain is not available");
@@ -395,7 +401,7 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
395
401
  const version = options.versionId ? await store.getVersion(options.versionId) : await store.getVersionByNumber(id, options.versionNumber);
396
402
  if (!version) return null;
397
403
  const {
398
- id: _vId,
404
+ id: versionId,
399
405
  agentId: _aId,
400
406
  versionNumber: _vn,
401
407
  changedFields: _cf,
@@ -403,9 +409,9 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
403
409
  createdAt: _ca,
404
410
  ...snapshotConfig
405
411
  } = version;
406
- return { ...agent, ...snapshotConfig };
412
+ return { ...agent, ...snapshotConfig, resolvedVersionId: versionId };
407
413
  }
408
- return store.getByIdResolved(id);
414
+ return store.getByIdResolved(id, options?.status ? { status: options.status } : void 0);
409
415
  },
410
416
  update: (input) => store.update(input),
411
417
  delete: (id) => store.delete(id),
@@ -422,6 +428,33 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
422
428
  onCacheEvict(id) {
423
429
  this.mastra?.removeAgent(id);
424
430
  }
431
+ /**
432
+ * Evict all cached agents that reference a given skill ID.
433
+ * Called by EditorSkillNamespace after a skill is published so that
434
+ * subsequent agent.getById() calls re-hydrate with the updated skill version.
435
+ */
436
+ invalidateAgentsReferencingSkill(skillId) {
437
+ for (const [agentId, agent] of this._cache.entries()) {
438
+ const raw = agent.toRawConfig?.();
439
+ if (!raw?.skills) continue;
440
+ const skillsField = raw.skills;
441
+ let found = false;
442
+ if (Array.isArray(skillsField)) {
443
+ found = skillsField.some(
444
+ (variant) => variant?.value && skillId in variant.value
445
+ );
446
+ } else if (typeof skillsField === "object" && skillsField !== null) {
447
+ found = skillId in skillsField;
448
+ }
449
+ if (found) {
450
+ this.logger?.debug(
451
+ `[invalidateAgentsReferencingSkill] Evicting agent "${agentId}" (references skill "${skillId}")`
452
+ );
453
+ this._cache.delete(agentId);
454
+ this.onCacheEvict(agentId);
455
+ }
456
+ }
457
+ }
425
458
  // ============================================================================
426
459
  // Private helpers
427
460
  // ============================================================================
@@ -478,6 +511,7 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
478
511
  const hasConditionalOutputProcessors = storedAgent.outputProcessors != null && this.isConditionalVariants(storedAgent.outputProcessors);
479
512
  const hasConditionalDefaultOptions = storedAgent.defaultOptions != null && this.isConditionalVariants(storedAgent.defaultOptions);
480
513
  const hasConditionalModel = this.isConditionalVariants(storedAgent.model);
514
+ const hasConditionalWorkspace = storedAgent.workspace != null && this.isConditionalVariants(storedAgent.workspace);
481
515
  const isDynamicTools = hasConditionalTools || hasConditionalMCPClients || hasConditionalIntegrationTools;
482
516
  let tools;
483
517
  if (isDynamicTools) {
@@ -512,16 +546,20 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
512
546
  }
513
547
  const workflows = hasConditionalWorkflows ? ({ requestContext }) => {
514
548
  const ctx = requestContext.toJSON();
515
- const resolved = this.accumulateArrayVariants(
516
- storedAgent.workflows,
549
+ const variants = storedAgent.workflows;
550
+ const isArrayVariant = Array.isArray(variants[0]?.value);
551
+ const resolved = isArrayVariant ? this.accumulateArrayVariants(variants, ctx) : this.accumulateObjectVariants(
552
+ variants,
517
553
  ctx
518
554
  );
519
555
  return this.resolveStoredWorkflows(resolved);
520
556
  } : this.resolveStoredWorkflows(storedAgent.workflows);
521
557
  const agents = hasConditionalAgents ? ({ requestContext }) => {
522
558
  const ctx = requestContext.toJSON();
523
- const resolved = this.accumulateArrayVariants(
524
- storedAgent.agents,
559
+ const variants = storedAgent.agents;
560
+ const isArrayVariant = Array.isArray(variants[0]?.value);
561
+ const resolved = isArrayVariant ? this.accumulateArrayVariants(variants, ctx) : this.accumulateObjectVariants(
562
+ variants,
525
563
  ctx
526
564
  );
527
565
  return this.resolveStoredAgents(resolved);
@@ -625,6 +663,16 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
625
663
  };
626
664
  }
627
665
  const requestContextSchema = storedAgent.requestContextSchema ? (0, import_schema_compat.convertSchemaToZod)(storedAgent.requestContextSchema) : void 0;
666
+ const skillSource = await this.resolveAgentSkillSource(storedAgent.skills);
667
+ const workspace = hasConditionalWorkspace ? async ({ requestContext }) => {
668
+ const ctx = requestContext.toJSON();
669
+ const resolvedRef = this.accumulateObjectVariants(
670
+ storedAgent.workspace,
671
+ ctx
672
+ );
673
+ return this.resolveStoredWorkspace(resolvedRef, skillSource);
674
+ } : await this.resolveStoredWorkspace(storedAgent.workspace, skillSource);
675
+ const skillsFormat = storedAgent.skillsFormat;
628
676
  const agent = new import_agent.Agent({
629
677
  id: storedAgent.id,
630
678
  name: storedAgent.name,
@@ -641,7 +689,9 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
641
689
  outputProcessors,
642
690
  rawConfig: storedAgent,
643
691
  defaultOptions,
644
- requestContextSchema
692
+ requestContextSchema,
693
+ workspace,
694
+ ...skillsFormat && { skillsFormat }
645
695
  });
646
696
  this.mastra?.addAgent(agent, storedAgent.id, { source: "stored" });
647
697
  this.logger?.debug(`[createAgentFromStoredConfig] Successfully created agent "${storedAgent.id}"`);
@@ -810,10 +860,13 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
810
860
  return allTools;
811
861
  }
812
862
  resolveStoredWorkflows(storedWorkflows) {
813
- if (!storedWorkflows || storedWorkflows.length === 0) return {};
863
+ if (!storedWorkflows || (Array.isArray(storedWorkflows) ? storedWorkflows.length === 0 : Object.keys(storedWorkflows).length === 0)) {
864
+ return {};
865
+ }
814
866
  if (!this.mastra) return {};
867
+ const normalized = Array.isArray(storedWorkflows) ? Object.fromEntries(storedWorkflows.map((key) => [key, {}])) : storedWorkflows;
815
868
  const resolvedWorkflows = {};
816
- for (const workflowKey of storedWorkflows) {
869
+ for (const workflowKey of Object.keys(normalized)) {
817
870
  try {
818
871
  resolvedWorkflows[workflowKey] = this.mastra.getWorkflow(workflowKey);
819
872
  } catch {
@@ -827,10 +880,13 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
827
880
  return resolvedWorkflows;
828
881
  }
829
882
  resolveStoredAgents(storedAgents) {
830
- if (!storedAgents || storedAgents.length === 0) return {};
883
+ if (!storedAgents || (Array.isArray(storedAgents) ? storedAgents.length === 0 : Object.keys(storedAgents).length === 0)) {
884
+ return {};
885
+ }
831
886
  if (!this.mastra) return {};
887
+ const normalized = Array.isArray(storedAgents) ? Object.fromEntries(storedAgents.map((key) => [key, {}])) : storedAgents;
832
888
  const resolvedAgents = {};
833
- for (const agentKey of storedAgents) {
889
+ for (const agentKey of Object.keys(normalized)) {
834
890
  try {
835
891
  resolvedAgents[agentKey] = this.mastra.getAgent(agentKey);
836
892
  } catch {
@@ -1007,8 +1063,8 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
1007
1063
  const toolKeys = Object.keys(tools || {});
1008
1064
  const workflows = await agent.listWorkflows({ requestContext });
1009
1065
  const workflowKeys = Object.keys(workflows || {});
1010
- const agents = await agent.listAgents({ requestContext });
1011
- const agentKeys = Object.keys(agents || {});
1066
+ const agentsResolved = await agent.listAgents({ requestContext });
1067
+ const agentKeys = Object.keys(agentsResolved || {});
1012
1068
  const memory = await agent.getMemory({ requestContext });
1013
1069
  const memoryConfig = memory?.getConfig();
1014
1070
  const { inputProcessorIds, outputProcessorIds } = await agent.getConfiguredProcessorIds(requestContext);
@@ -1045,8 +1101,8 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
1045
1101
  instructions: instructionsStr,
1046
1102
  model,
1047
1103
  tools: toolKeys.length > 0 ? Object.fromEntries(toolKeys.map((key) => [key, {}])) : void 0,
1048
- workflows: workflowKeys.length > 0 ? workflowKeys : void 0,
1049
- agents: agentKeys.length > 0 ? agentKeys : void 0,
1104
+ workflows: workflowKeys.length > 0 ? Object.fromEntries(workflowKeys.map((key) => [key, {}])) : void 0,
1105
+ agents: agentKeys.length > 0 ? Object.fromEntries(agentKeys.map((key) => [key, {}])) : void 0,
1050
1106
  memory: memoryConfig,
1051
1107
  inputProcessors: inputProcessorKeys,
1052
1108
  outputProcessors: outputProcessorKeys,
@@ -1063,6 +1119,105 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
1063
1119
  }
1064
1120
  return resolved;
1065
1121
  }
1122
+ // ============================================================================
1123
+ // Workspace Resolution
1124
+ // ============================================================================
1125
+ /**
1126
+ * Resolve a stored workspace reference to a runtime Workspace instance.
1127
+ * Handles both ID-based references (looked up from editor.workspace) and
1128
+ * inline workspace configurations (hydrated directly).
1129
+ *
1130
+ * When a skillSource is provided (from resolveAgentSkillSource), it is passed
1131
+ * to the workspace hydration so the workspace uses versioned blob-backed skills
1132
+ * instead of filesystem-based discovery.
1133
+ */
1134
+ async resolveStoredWorkspace(workspaceRef, skillSource) {
1135
+ if (!workspaceRef) return void 0;
1136
+ const workspaceNs = this.editor.workspace;
1137
+ if (!workspaceNs) {
1138
+ this.logger?.warn("[resolveStoredWorkspace] No workspace namespace available on editor");
1139
+ return void 0;
1140
+ }
1141
+ const hydrateOptions = skillSource ? { skillSource } : void 0;
1142
+ if (workspaceRef.type === "id") {
1143
+ const resolved = await workspaceNs.getById(workspaceRef.workspaceId);
1144
+ if (!resolved) {
1145
+ this.logger?.warn(
1146
+ `[resolveStoredWorkspace] Workspace '${workspaceRef.workspaceId}' not found in storage, skipping`
1147
+ );
1148
+ return void 0;
1149
+ }
1150
+ return workspaceNs.hydrateSnapshotToWorkspace(workspaceRef.workspaceId, resolved, hydrateOptions);
1151
+ }
1152
+ if (workspaceRef.type === "inline") {
1153
+ const configHash = (0, import_node_crypto.createHash)("sha256").update(JSON.stringify(workspaceRef.config)).digest("hex").slice(0, 12);
1154
+ return workspaceNs.hydrateSnapshotToWorkspace(`inline-${configHash}`, workspaceRef.config, hydrateOptions);
1155
+ }
1156
+ return void 0;
1157
+ }
1158
+ /**
1159
+ * Resolve agent-level skill configurations into a CompositeVersionedSkillSource.
1160
+ *
1161
+ * For each skill in the agent's `skills` map, checks the resolution strategy:
1162
+ * - `pin: '<versionId>'` → reads the specific version's tree from the DB
1163
+ * - `strategy: 'latest'` → reads the skill's active version tree
1164
+ * - `strategy: 'live'` or no strategy → skips (uses filesystem-based discovery)
1165
+ *
1166
+ * Returns a CompositeVersionedSkillSource if any versioned skills were resolved,
1167
+ * or undefined if all skills use filesystem-based discovery.
1168
+ */
1169
+ async resolveAgentSkillSource(skills) {
1170
+ if (!skills || typeof skills !== "object") return void 0;
1171
+ const skillConfigs = Array.isArray(skills) ? void 0 : skills;
1172
+ if (!skillConfigs || Object.keys(skillConfigs).length === 0) return void 0;
1173
+ const storage = this.mastra?.getStorage();
1174
+ if (!storage) return void 0;
1175
+ const skillStore = await storage.getStore("skills");
1176
+ if (!skillStore) return void 0;
1177
+ const blobStore = await this.editor.resolveBlobStore();
1178
+ if (!blobStore) return void 0;
1179
+ const versionedEntries = [];
1180
+ for (const [skillId, config] of Object.entries(skillConfigs)) {
1181
+ if (!config) continue;
1182
+ const isPinned = !!config.pin;
1183
+ const isLatest = config.strategy === "latest";
1184
+ if (!isPinned && !isLatest) {
1185
+ continue;
1186
+ }
1187
+ try {
1188
+ let version;
1189
+ let dirName;
1190
+ if (isPinned) {
1191
+ version = await skillStore.getVersion(config.pin);
1192
+ dirName = version?.name || skillId;
1193
+ } else {
1194
+ const resolved = await skillStore.getByIdResolved(skillId);
1195
+ if (resolved?.activeVersionId) {
1196
+ version = await skillStore.getVersion(resolved.activeVersionId);
1197
+ }
1198
+ if (!version) {
1199
+ version = await skillStore.getLatestVersion(skillId);
1200
+ }
1201
+ dirName = resolved?.name || version?.name || skillId;
1202
+ }
1203
+ if (!version?.tree) {
1204
+ this.logger?.warn(
1205
+ `[resolveAgentSkillSource] Skill '${skillId}' version has no tree manifest, skipping versioned resolution`
1206
+ );
1207
+ continue;
1208
+ }
1209
+ versionedEntries.push({
1210
+ dirName,
1211
+ tree: version.tree,
1212
+ versionCreatedAt: version.createdAt
1213
+ });
1214
+ } catch (error) {
1215
+ this.logger?.warn(`[resolveAgentSkillSource] Failed to resolve version for skill '${skillId}': ${error}`);
1216
+ }
1217
+ }
1218
+ if (versionedEntries.length === 0) return void 0;
1219
+ return new import_workspace.CompositeVersionedSkillSource(versionedEntries, blobStore);
1220
+ }
1066
1221
  };
1067
1222
 
1068
1223
  // src/namespaces/prompt.ts
@@ -1071,7 +1226,7 @@ var EditorPromptNamespace = class extends CrudEditorNamespace {
1071
1226
  this.mastra?.removePromptBlock(id);
1072
1227
  }
1073
1228
  async getStorageAdapter() {
1074
- const storage = this.mastra.getStorage();
1229
+ const storage = this.mastra?.getStorage();
1075
1230
  if (!storage) throw new Error("Storage is not configured");
1076
1231
  const store = await storage.getStore("promptBlocks");
1077
1232
  if (!store) throw new Error("Prompt blocks storage domain is not available");
@@ -1086,7 +1241,7 @@ var EditorPromptNamespace = class extends CrudEditorNamespace {
1086
1241
  }
1087
1242
  async preview(blocks, context) {
1088
1243
  this.ensureRegistered();
1089
- const storage = this.mastra.getStorage();
1244
+ const storage = this.mastra?.getStorage();
1090
1245
  if (!storage) throw new Error("Storage is not configured");
1091
1246
  const store = await storage.getStore("promptBlocks");
1092
1247
  if (!store) throw new Error("Prompt blocks storage domain is not available");
@@ -1113,7 +1268,7 @@ var EditorScorerNamespace = class extends CrudEditorNamespace {
1113
1268
  return storedScorer;
1114
1269
  }
1115
1270
  async getStorageAdapter() {
1116
- const storage = this.mastra.getStorage();
1271
+ const storage = this.mastra?.getStorage();
1117
1272
  if (!storage) throw new Error("Storage is not configured");
1118
1273
  const store = await storage.getStore("scorerDefinitions");
1119
1274
  if (!store) throw new Error("Scorer definitions storage domain is not available");
@@ -1194,15 +1349,255 @@ Explain your reasoning for this score in a clear, concise paragraph.`;
1194
1349
  }
1195
1350
  };
1196
1351
 
1352
+ // src/namespaces/workspace.ts
1353
+ var import_workspace2 = require("@mastra/core/workspace");
1354
+ var EditorWorkspaceNamespace = class extends CrudEditorNamespace {
1355
+ onCacheEvict(_id) {
1356
+ }
1357
+ /**
1358
+ * Hydrate a stored workspace snapshot config into a runtime Workspace instance.
1359
+ * Resolves provider strings to actual instances using the editor's registries.
1360
+ *
1361
+ * This is NOT called from the CrudEditorNamespace flow — it is a public utility
1362
+ * used by EditorAgentNamespace during agent hydration.
1363
+ */
1364
+ async hydrateSnapshotToWorkspace(id, snapshot, options) {
1365
+ const config = {
1366
+ id,
1367
+ name: snapshot.name
1368
+ };
1369
+ if (snapshot.filesystem) {
1370
+ config.filesystem = await this.resolveFilesystem(snapshot.filesystem);
1371
+ }
1372
+ if (snapshot.sandbox) {
1373
+ config.sandbox = await this.resolveSandbox(snapshot.sandbox);
1374
+ }
1375
+ if (snapshot.mounts) {
1376
+ const mounts = {};
1377
+ for (const [path, fsConfig] of Object.entries(snapshot.mounts)) {
1378
+ mounts[path] = await this.resolveFilesystem(fsConfig);
1379
+ }
1380
+ config.mounts = mounts;
1381
+ }
1382
+ if (snapshot.search) {
1383
+ if (snapshot.search.bm25) {
1384
+ config.bm25 = snapshot.search.bm25;
1385
+ }
1386
+ if (snapshot.search.searchIndexName) {
1387
+ config.searchIndexName = snapshot.search.searchIndexName;
1388
+ }
1389
+ if (snapshot.search.autoIndexPaths) {
1390
+ config.autoIndexPaths = snapshot.search.autoIndexPaths;
1391
+ }
1392
+ if (snapshot.search.vectorProvider && this.mastra) {
1393
+ const vectors = this.mastra.listVectors();
1394
+ const vectorStore = vectors?.[snapshot.search.vectorProvider];
1395
+ if (vectorStore) {
1396
+ config.vectorStore = vectorStore;
1397
+ } else {
1398
+ this.logger?.warn(
1399
+ `Vector provider "${snapshot.search.vectorProvider}" not found in Mastra instance. Workspace search will be limited to BM25 only.`
1400
+ );
1401
+ }
1402
+ }
1403
+ if (config.vectorStore && !config.embedder) {
1404
+ this.logger?.warn(
1405
+ `Workspace has a vector store configured but no embedder. Vector/hybrid search will not be available. Configure an embedder to enable semantic search.`
1406
+ );
1407
+ }
1408
+ }
1409
+ if (options?.skillSource) {
1410
+ config.skillSource = options.skillSource;
1411
+ config.skills = ["."];
1412
+ } else if (snapshot.skills && snapshot.skills.length > 0) {
1413
+ config.skills = snapshot.skills;
1414
+ }
1415
+ if (snapshot.tools) {
1416
+ config.tools = snapshot.tools;
1417
+ }
1418
+ if (snapshot.autoSync !== void 0) {
1419
+ config.autoSync = snapshot.autoSync;
1420
+ }
1421
+ if (snapshot.operationTimeout !== void 0) {
1422
+ config.operationTimeout = snapshot.operationTimeout;
1423
+ }
1424
+ return new import_workspace2.Workspace(config);
1425
+ }
1426
+ /**
1427
+ * Resolve a stored filesystem config to a runtime WorkspaceFilesystem instance.
1428
+ * Looks up the provider by ID in the editor's registry (which includes built-in providers).
1429
+ */
1430
+ async resolveFilesystem(fsConfig) {
1431
+ const provider = this.editor.__filesystems.get(fsConfig.provider);
1432
+ if (!provider) {
1433
+ throw new Error(
1434
+ `Filesystem provider "${fsConfig.provider}" is not registered. Register it via new MastraEditor({ filesystems: [yourProvider] })`
1435
+ );
1436
+ }
1437
+ const config = { ...fsConfig.config, readOnly: fsConfig.readOnly };
1438
+ return await provider.createFilesystem(config);
1439
+ }
1440
+ /**
1441
+ * Resolve a stored sandbox config to a runtime WorkspaceSandbox instance.
1442
+ * Looks up the provider by ID in the editor's registry (which includes built-in providers).
1443
+ */
1444
+ async resolveSandbox(sandboxConfig) {
1445
+ const provider = this.editor.__sandboxes.get(sandboxConfig.provider);
1446
+ if (!provider) {
1447
+ throw new Error(
1448
+ `Sandbox provider "${sandboxConfig.provider}" is not registered. Register it via new MastraEditor({ sandboxes: [yourProvider] })`
1449
+ );
1450
+ }
1451
+ return await provider.createSandbox(sandboxConfig.config);
1452
+ }
1453
+ async getStorageAdapter() {
1454
+ const storage = this.mastra?.getStorage();
1455
+ if (!storage) throw new Error("Storage is not configured");
1456
+ const store = await storage.getStore("workspaces");
1457
+ if (!store) throw new Error("Workspaces storage domain is not available");
1458
+ return {
1459
+ create: (input) => store.create({ workspace: input }),
1460
+ getByIdResolved: (id) => store.getByIdResolved(id),
1461
+ update: (input) => store.update(input),
1462
+ delete: (id) => store.delete(id),
1463
+ list: (args) => store.list(args),
1464
+ listResolved: (args) => store.listResolved(args)
1465
+ };
1466
+ }
1467
+ };
1468
+
1469
+ // src/namespaces/skill.ts
1470
+ var import_workspace3 = require("@mastra/core/workspace");
1471
+ var EditorSkillNamespace = class extends CrudEditorNamespace {
1472
+ onCacheEvict(_id) {
1473
+ }
1474
+ async getStorageAdapter() {
1475
+ const storage = this.mastra?.getStorage();
1476
+ if (!storage) throw new Error("Storage is not configured");
1477
+ const store = await storage.getStore("skills");
1478
+ if (!store) throw new Error("Skills storage domain is not available");
1479
+ return {
1480
+ create: (input) => store.create({ skill: input }),
1481
+ getByIdResolved: (id) => store.getByIdResolved(id),
1482
+ update: (input) => store.update(input),
1483
+ delete: (id) => store.delete(id),
1484
+ list: (args) => store.list(args),
1485
+ listResolved: (args) => store.listResolved(args)
1486
+ };
1487
+ }
1488
+ /**
1489
+ * Publish a skill from a live filesystem source.
1490
+ * Walks the skill directory, hashes files into the blob store,
1491
+ * creates a new version with the tree manifest, and sets activeVersionId.
1492
+ */
1493
+ async publish(skillId, source, skillPath) {
1494
+ this.ensureRegistered();
1495
+ const storage = this.mastra?.getStorage();
1496
+ if (!storage) throw new Error("Storage is not configured");
1497
+ const skillStore = await storage.getStore("skills");
1498
+ if (!skillStore) throw new Error("Skills storage domain is not available");
1499
+ const blobStore = await this.editor.resolveBlobStore();
1500
+ if (!blobStore)
1501
+ throw new Error("No blob store is configured. Register one via new MastraEditor({ blobStores: [...] })");
1502
+ const { snapshot, tree } = await (0, import_workspace3.publishSkillFromSource)(source, skillPath, blobStore);
1503
+ await skillStore.update({
1504
+ id: skillId,
1505
+ ...snapshot,
1506
+ tree,
1507
+ status: "published"
1508
+ });
1509
+ const latestVersion = await skillStore.getLatestVersion(skillId);
1510
+ if (!latestVersion) {
1511
+ throw new Error(`Failed to retrieve version after publishing skill "${skillId}"`);
1512
+ }
1513
+ await skillStore.update({
1514
+ id: skillId,
1515
+ activeVersionId: latestVersion.id
1516
+ });
1517
+ const resolved = await skillStore.getByIdResolved(skillId);
1518
+ if (!resolved) throw new Error(`Failed to resolve skill ${skillId} after publish`);
1519
+ this.clearCache(skillId);
1520
+ this.editor.agent.invalidateAgentsReferencingSkill(skillId);
1521
+ return resolved;
1522
+ }
1523
+ };
1524
+
1525
+ // src/providers.ts
1526
+ var import_workspace5 = require("@mastra/core/workspace");
1527
+ var import_workspace6 = require("@mastra/core/workspace");
1528
+ var localFilesystemProvider = {
1529
+ id: "local",
1530
+ name: "Local Filesystem",
1531
+ description: "A folder on the local disk",
1532
+ configSchema: {
1533
+ type: "object",
1534
+ required: ["basePath"],
1535
+ properties: {
1536
+ basePath: { type: "string", description: "Base directory path on disk" },
1537
+ contained: {
1538
+ type: "boolean",
1539
+ description: "Restrict operations to stay within basePath",
1540
+ default: true
1541
+ },
1542
+ readOnly: {
1543
+ type: "boolean",
1544
+ description: "Block all write operations",
1545
+ default: false
1546
+ }
1547
+ }
1548
+ },
1549
+ createFilesystem: (config) => new import_workspace5.LocalFilesystem(config)
1550
+ };
1551
+ var localSandboxProvider = {
1552
+ id: "local",
1553
+ name: "Local Sandbox",
1554
+ description: "Execute commands on the local machine",
1555
+ configSchema: {
1556
+ type: "object",
1557
+ properties: {
1558
+ workingDirectory: { type: "string", description: "Working directory for command execution" },
1559
+ timeout: { type: "number", description: "Default timeout for operations in ms" },
1560
+ isolation: {
1561
+ type: "string",
1562
+ enum: ["none", "seatbelt", "bwrap"],
1563
+ description: "Isolation backend for sandboxed execution",
1564
+ default: "none"
1565
+ },
1566
+ env: {
1567
+ type: "object",
1568
+ description: "Environment variables for command execution",
1569
+ additionalProperties: { type: "string" }
1570
+ }
1571
+ }
1572
+ },
1573
+ createSandbox: (config) => new import_workspace6.LocalSandbox(config)
1574
+ };
1575
+
1197
1576
  // src/index.ts
1198
1577
  var MastraEditor = class {
1199
1578
  constructor(config) {
1200
1579
  this.__logger = config?.logger;
1201
1580
  this.__toolProviders = config?.toolProviders ?? {};
1581
+ this.__filesystems = /* @__PURE__ */ new Map();
1582
+ this.__filesystems.set(localFilesystemProvider.id, localFilesystemProvider);
1583
+ for (const [id, provider] of Object.entries(config?.filesystems ?? {})) {
1584
+ this.__filesystems.set(id, provider);
1585
+ }
1586
+ this.__sandboxes = /* @__PURE__ */ new Map();
1587
+ this.__sandboxes.set(localSandboxProvider.id, localSandboxProvider);
1588
+ for (const [id, provider] of Object.entries(config?.sandboxes ?? {})) {
1589
+ this.__sandboxes.set(id, provider);
1590
+ }
1591
+ this.__blobStores = /* @__PURE__ */ new Map();
1592
+ for (const [id, provider] of Object.entries(config?.blobStores ?? {})) {
1593
+ this.__blobStores.set(id, provider);
1594
+ }
1202
1595
  this.agent = new EditorAgentNamespace(this);
1203
1596
  this.mcp = new EditorMCPNamespace(this);
1204
1597
  this.prompt = new EditorPromptNamespace(this);
1205
1598
  this.scorer = new EditorScorerNamespace(this);
1599
+ this.workspace = new EditorWorkspaceNamespace(this);
1600
+ this.skill = new EditorSkillNamespace(this);
1206
1601
  }
1207
1602
  /**
1208
1603
  * Register this editor with a Mastra instance.
@@ -1222,6 +1617,46 @@ var MastraEditor = class {
1222
1617
  getToolProviders() {
1223
1618
  return this.__toolProviders;
1224
1619
  }
1620
+ /** List all registered filesystem providers */
1621
+ getFilesystemProviders() {
1622
+ return Array.from(this.__filesystems.values());
1623
+ }
1624
+ /** List all registered sandbox providers */
1625
+ getSandboxProviders() {
1626
+ return Array.from(this.__sandboxes.values());
1627
+ }
1628
+ /** List all registered blob store providers */
1629
+ getBlobStoreProviders() {
1630
+ return Array.from(this.__blobStores.values());
1631
+ }
1632
+ /**
1633
+ * Resolve a blob store from the provider registry, or fall back to the
1634
+ * storage backend's blobs domain.
1635
+ *
1636
+ * @param providerId - If specified, look up a registered provider by ID
1637
+ * and create a blob store from the given config. If omitted, falls back
1638
+ * to `storage.getStore('blobs')`.
1639
+ * @param providerConfig - Provider-specific configuration (only used when
1640
+ * `providerId` is specified).
1641
+ */
1642
+ async resolveBlobStore(providerId, providerConfig) {
1643
+ if (providerId) {
1644
+ const provider = this.__blobStores.get(providerId);
1645
+ if (!provider) {
1646
+ throw new Error(
1647
+ `Blob store provider "${providerId}" is not registered. Register it via new MastraEditor({ blobStores: { '${providerId}': yourProvider } })`
1648
+ );
1649
+ }
1650
+ const blobStore2 = await provider.createBlobStore(providerConfig ?? {});
1651
+ await blobStore2.init();
1652
+ return blobStore2;
1653
+ }
1654
+ const storage = this.__mastra?.getStorage();
1655
+ if (!storage) throw new Error("Storage is not configured");
1656
+ const blobStore = await storage.getStore("blobs");
1657
+ if (!blobStore) throw new Error("Blob storage domain is not available");
1658
+ return blobStore;
1659
+ }
1225
1660
  };
1226
1661
  // Annotate the CommonJS export names for ESM import in node:
1227
1662
  0 && (module.exports = {
@@ -1231,8 +1666,12 @@ var MastraEditor = class {
1231
1666
  EditorNamespace,
1232
1667
  EditorPromptNamespace,
1233
1668
  EditorScorerNamespace,
1669
+ EditorSkillNamespace,
1670
+ EditorWorkspaceNamespace,
1234
1671
  MastraEditor,
1235
1672
  evaluateRuleGroup,
1673
+ localFilesystemProvider,
1674
+ localSandboxProvider,
1236
1675
  renderTemplate,
1237
1676
  resolveInstructionBlocks
1238
1677
  });