@mastra/editor 0.4.0-alpha.0 → 0.5.0-alpha.0

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.js CHANGED
@@ -48,7 +48,7 @@ var CrudEditorNamespace = class extends EditorNamespace {
48
48
  }
49
49
  async getById(id, options) {
50
50
  this.ensureRegistered();
51
- const isVersionRequest = options?.versionId || options?.versionNumber;
51
+ const isVersionRequest = options?.versionId || options?.versionNumber || options?.status;
52
52
  if (!isVersionRequest) {
53
53
  const cached = this._cache.get(id);
54
54
  if (cached) {
@@ -117,8 +117,10 @@ var CrudEditorNamespace = class extends EditorNamespace {
117
117
  };
118
118
 
119
119
  // src/namespaces/agent.ts
120
+ import { createHash } from "crypto";
120
121
  import { Memory } from "@mastra/memory";
121
122
  import { Agent } from "@mastra/core/agent";
123
+ import { CompositeVersionedSkillSource } from "@mastra/core/workspace";
122
124
  import { convertSchemaToZod } from "@mastra/schema-compat";
123
125
  import { RequestContext } from "@mastra/core/request-context";
124
126
 
@@ -290,7 +292,7 @@ var EditorMCPNamespace = class _EditorMCPNamespace extends CrudEditorNamespace {
290
292
  onCacheEvict(_id) {
291
293
  }
292
294
  async getStorageAdapter() {
293
- const storage = this.mastra.getStorage();
295
+ const storage = this.mastra?.getStorage();
294
296
  if (!storage) throw new Error("Storage is not configured");
295
297
  const store = await storage.getStore("mcpClients");
296
298
  if (!store) throw new Error("MCP clients storage domain is not available");
@@ -337,7 +339,7 @@ var EditorMCPNamespace = class _EditorMCPNamespace extends CrudEditorNamespace {
337
339
  // src/namespaces/agent.ts
338
340
  var EditorAgentNamespace = class extends CrudEditorNamespace {
339
341
  async getStorageAdapter() {
340
- const storage = this.mastra.getStorage();
342
+ const storage = this.mastra?.getStorage();
341
343
  if (!storage) throw new Error("Storage is not configured");
342
344
  const store = await storage.getStore("agents");
343
345
  if (!store) throw new Error("Agents storage domain is not available");
@@ -350,7 +352,7 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
350
352
  const version = options.versionId ? await store.getVersion(options.versionId) : await store.getVersionByNumber(id, options.versionNumber);
351
353
  if (!version) return null;
352
354
  const {
353
- id: _vId,
355
+ id: versionId,
354
356
  agentId: _aId,
355
357
  versionNumber: _vn,
356
358
  changedFields: _cf,
@@ -358,9 +360,9 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
358
360
  createdAt: _ca,
359
361
  ...snapshotConfig
360
362
  } = version;
361
- return { ...agent, ...snapshotConfig };
363
+ return { ...agent, ...snapshotConfig, resolvedVersionId: versionId };
362
364
  }
363
- return store.getByIdResolved(id);
365
+ return store.getByIdResolved(id, options?.status ? { status: options.status } : void 0);
364
366
  },
365
367
  update: (input) => store.update(input),
366
368
  delete: (id) => store.delete(id),
@@ -377,6 +379,33 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
377
379
  onCacheEvict(id) {
378
380
  this.mastra?.removeAgent(id);
379
381
  }
382
+ /**
383
+ * Evict all cached agents that reference a given skill ID.
384
+ * Called by EditorSkillNamespace after a skill is published so that
385
+ * subsequent agent.getById() calls re-hydrate with the updated skill version.
386
+ */
387
+ invalidateAgentsReferencingSkill(skillId) {
388
+ for (const [agentId, agent] of this._cache.entries()) {
389
+ const raw = agent.toRawConfig?.();
390
+ if (!raw?.skills) continue;
391
+ const skillsField = raw.skills;
392
+ let found = false;
393
+ if (Array.isArray(skillsField)) {
394
+ found = skillsField.some(
395
+ (variant) => variant?.value && skillId in variant.value
396
+ );
397
+ } else if (typeof skillsField === "object" && skillsField !== null) {
398
+ found = skillId in skillsField;
399
+ }
400
+ if (found) {
401
+ this.logger?.debug(
402
+ `[invalidateAgentsReferencingSkill] Evicting agent "${agentId}" (references skill "${skillId}")`
403
+ );
404
+ this._cache.delete(agentId);
405
+ this.onCacheEvict(agentId);
406
+ }
407
+ }
408
+ }
380
409
  // ============================================================================
381
410
  // Private helpers
382
411
  // ============================================================================
@@ -433,6 +462,7 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
433
462
  const hasConditionalOutputProcessors = storedAgent.outputProcessors != null && this.isConditionalVariants(storedAgent.outputProcessors);
434
463
  const hasConditionalDefaultOptions = storedAgent.defaultOptions != null && this.isConditionalVariants(storedAgent.defaultOptions);
435
464
  const hasConditionalModel = this.isConditionalVariants(storedAgent.model);
465
+ const hasConditionalWorkspace = storedAgent.workspace != null && this.isConditionalVariants(storedAgent.workspace);
436
466
  const isDynamicTools = hasConditionalTools || hasConditionalMCPClients || hasConditionalIntegrationTools;
437
467
  let tools;
438
468
  if (isDynamicTools) {
@@ -467,16 +497,20 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
467
497
  }
468
498
  const workflows = hasConditionalWorkflows ? ({ requestContext }) => {
469
499
  const ctx = requestContext.toJSON();
470
- const resolved = this.accumulateArrayVariants(
471
- storedAgent.workflows,
500
+ const variants = storedAgent.workflows;
501
+ const isArrayVariant = Array.isArray(variants[0]?.value);
502
+ const resolved = isArrayVariant ? this.accumulateArrayVariants(variants, ctx) : this.accumulateObjectVariants(
503
+ variants,
472
504
  ctx
473
505
  );
474
506
  return this.resolveStoredWorkflows(resolved);
475
507
  } : this.resolveStoredWorkflows(storedAgent.workflows);
476
508
  const agents = hasConditionalAgents ? ({ requestContext }) => {
477
509
  const ctx = requestContext.toJSON();
478
- const resolved = this.accumulateArrayVariants(
479
- storedAgent.agents,
510
+ const variants = storedAgent.agents;
511
+ const isArrayVariant = Array.isArray(variants[0]?.value);
512
+ const resolved = isArrayVariant ? this.accumulateArrayVariants(variants, ctx) : this.accumulateObjectVariants(
513
+ variants,
480
514
  ctx
481
515
  );
482
516
  return this.resolveStoredAgents(resolved);
@@ -580,6 +614,16 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
580
614
  };
581
615
  }
582
616
  const requestContextSchema = storedAgent.requestContextSchema ? convertSchemaToZod(storedAgent.requestContextSchema) : void 0;
617
+ const skillSource = await this.resolveAgentSkillSource(storedAgent.skills);
618
+ const workspace = hasConditionalWorkspace ? async ({ requestContext }) => {
619
+ const ctx = requestContext.toJSON();
620
+ const resolvedRef = this.accumulateObjectVariants(
621
+ storedAgent.workspace,
622
+ ctx
623
+ );
624
+ return this.resolveStoredWorkspace(resolvedRef, skillSource);
625
+ } : await this.resolveStoredWorkspace(storedAgent.workspace, skillSource);
626
+ const skillsFormat = storedAgent.skillsFormat;
583
627
  const agent = new Agent({
584
628
  id: storedAgent.id,
585
629
  name: storedAgent.name,
@@ -596,7 +640,9 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
596
640
  outputProcessors,
597
641
  rawConfig: storedAgent,
598
642
  defaultOptions,
599
- requestContextSchema
643
+ requestContextSchema,
644
+ workspace,
645
+ ...skillsFormat && { skillsFormat }
600
646
  });
601
647
  this.mastra?.addAgent(agent, storedAgent.id, { source: "stored" });
602
648
  this.logger?.debug(`[createAgentFromStoredConfig] Successfully created agent "${storedAgent.id}"`);
@@ -765,10 +811,13 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
765
811
  return allTools;
766
812
  }
767
813
  resolveStoredWorkflows(storedWorkflows) {
768
- if (!storedWorkflows || storedWorkflows.length === 0) return {};
814
+ if (!storedWorkflows || (Array.isArray(storedWorkflows) ? storedWorkflows.length === 0 : Object.keys(storedWorkflows).length === 0)) {
815
+ return {};
816
+ }
769
817
  if (!this.mastra) return {};
818
+ const normalized = Array.isArray(storedWorkflows) ? Object.fromEntries(storedWorkflows.map((key) => [key, {}])) : storedWorkflows;
770
819
  const resolvedWorkflows = {};
771
- for (const workflowKey of storedWorkflows) {
820
+ for (const workflowKey of Object.keys(normalized)) {
772
821
  try {
773
822
  resolvedWorkflows[workflowKey] = this.mastra.getWorkflow(workflowKey);
774
823
  } catch {
@@ -782,10 +831,13 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
782
831
  return resolvedWorkflows;
783
832
  }
784
833
  resolveStoredAgents(storedAgents) {
785
- if (!storedAgents || storedAgents.length === 0) return {};
834
+ if (!storedAgents || (Array.isArray(storedAgents) ? storedAgents.length === 0 : Object.keys(storedAgents).length === 0)) {
835
+ return {};
836
+ }
786
837
  if (!this.mastra) return {};
838
+ const normalized = Array.isArray(storedAgents) ? Object.fromEntries(storedAgents.map((key) => [key, {}])) : storedAgents;
787
839
  const resolvedAgents = {};
788
- for (const agentKey of storedAgents) {
840
+ for (const agentKey of Object.keys(normalized)) {
789
841
  try {
790
842
  resolvedAgents[agentKey] = this.mastra.getAgent(agentKey);
791
843
  } catch {
@@ -962,8 +1014,8 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
962
1014
  const toolKeys = Object.keys(tools || {});
963
1015
  const workflows = await agent.listWorkflows({ requestContext });
964
1016
  const workflowKeys = Object.keys(workflows || {});
965
- const agents = await agent.listAgents({ requestContext });
966
- const agentKeys = Object.keys(agents || {});
1017
+ const agentsResolved = await agent.listAgents({ requestContext });
1018
+ const agentKeys = Object.keys(agentsResolved || {});
967
1019
  const memory = await agent.getMemory({ requestContext });
968
1020
  const memoryConfig = memory?.getConfig();
969
1021
  const { inputProcessorIds, outputProcessorIds } = await agent.getConfiguredProcessorIds(requestContext);
@@ -1000,8 +1052,8 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
1000
1052
  instructions: instructionsStr,
1001
1053
  model,
1002
1054
  tools: toolKeys.length > 0 ? Object.fromEntries(toolKeys.map((key) => [key, {}])) : void 0,
1003
- workflows: workflowKeys.length > 0 ? workflowKeys : void 0,
1004
- agents: agentKeys.length > 0 ? agentKeys : void 0,
1055
+ workflows: workflowKeys.length > 0 ? Object.fromEntries(workflowKeys.map((key) => [key, {}])) : void 0,
1056
+ agents: agentKeys.length > 0 ? Object.fromEntries(agentKeys.map((key) => [key, {}])) : void 0,
1005
1057
  memory: memoryConfig,
1006
1058
  inputProcessors: inputProcessorKeys,
1007
1059
  outputProcessors: outputProcessorKeys,
@@ -1018,6 +1070,105 @@ var EditorAgentNamespace = class extends CrudEditorNamespace {
1018
1070
  }
1019
1071
  return resolved;
1020
1072
  }
1073
+ // ============================================================================
1074
+ // Workspace Resolution
1075
+ // ============================================================================
1076
+ /**
1077
+ * Resolve a stored workspace reference to a runtime Workspace instance.
1078
+ * Handles both ID-based references (looked up from editor.workspace) and
1079
+ * inline workspace configurations (hydrated directly).
1080
+ *
1081
+ * When a skillSource is provided (from resolveAgentSkillSource), it is passed
1082
+ * to the workspace hydration so the workspace uses versioned blob-backed skills
1083
+ * instead of filesystem-based discovery.
1084
+ */
1085
+ async resolveStoredWorkspace(workspaceRef, skillSource) {
1086
+ if (!workspaceRef) return void 0;
1087
+ const workspaceNs = this.editor.workspace;
1088
+ if (!workspaceNs) {
1089
+ this.logger?.warn("[resolveStoredWorkspace] No workspace namespace available on editor");
1090
+ return void 0;
1091
+ }
1092
+ const hydrateOptions = skillSource ? { skillSource } : void 0;
1093
+ if (workspaceRef.type === "id") {
1094
+ const resolved = await workspaceNs.getById(workspaceRef.workspaceId);
1095
+ if (!resolved) {
1096
+ this.logger?.warn(
1097
+ `[resolveStoredWorkspace] Workspace '${workspaceRef.workspaceId}' not found in storage, skipping`
1098
+ );
1099
+ return void 0;
1100
+ }
1101
+ return workspaceNs.hydrateSnapshotToWorkspace(workspaceRef.workspaceId, resolved, hydrateOptions);
1102
+ }
1103
+ if (workspaceRef.type === "inline") {
1104
+ const configHash = createHash("sha256").update(JSON.stringify(workspaceRef.config)).digest("hex").slice(0, 12);
1105
+ return workspaceNs.hydrateSnapshotToWorkspace(`inline-${configHash}`, workspaceRef.config, hydrateOptions);
1106
+ }
1107
+ return void 0;
1108
+ }
1109
+ /**
1110
+ * Resolve agent-level skill configurations into a CompositeVersionedSkillSource.
1111
+ *
1112
+ * For each skill in the agent's `skills` map, checks the resolution strategy:
1113
+ * - `pin: '<versionId>'` → reads the specific version's tree from the DB
1114
+ * - `strategy: 'latest'` → reads the skill's active version tree
1115
+ * - `strategy: 'live'` or no strategy → skips (uses filesystem-based discovery)
1116
+ *
1117
+ * Returns a CompositeVersionedSkillSource if any versioned skills were resolved,
1118
+ * or undefined if all skills use filesystem-based discovery.
1119
+ */
1120
+ async resolveAgentSkillSource(skills) {
1121
+ if (!skills || typeof skills !== "object") return void 0;
1122
+ const skillConfigs = Array.isArray(skills) ? void 0 : skills;
1123
+ if (!skillConfigs || Object.keys(skillConfigs).length === 0) return void 0;
1124
+ const storage = this.mastra?.getStorage();
1125
+ if (!storage) return void 0;
1126
+ const skillStore = await storage.getStore("skills");
1127
+ if (!skillStore) return void 0;
1128
+ const blobStore = await this.editor.resolveBlobStore();
1129
+ if (!blobStore) return void 0;
1130
+ const versionedEntries = [];
1131
+ for (const [skillId, config] of Object.entries(skillConfigs)) {
1132
+ if (!config) continue;
1133
+ const isPinned = !!config.pin;
1134
+ const isLatest = config.strategy === "latest";
1135
+ if (!isPinned && !isLatest) {
1136
+ continue;
1137
+ }
1138
+ try {
1139
+ let version;
1140
+ let dirName;
1141
+ if (isPinned) {
1142
+ version = await skillStore.getVersion(config.pin);
1143
+ dirName = version?.name || skillId;
1144
+ } else {
1145
+ const resolved = await skillStore.getByIdResolved(skillId);
1146
+ if (resolved?.activeVersionId) {
1147
+ version = await skillStore.getVersion(resolved.activeVersionId);
1148
+ }
1149
+ if (!version) {
1150
+ version = await skillStore.getLatestVersion(skillId);
1151
+ }
1152
+ dirName = resolved?.name || version?.name || skillId;
1153
+ }
1154
+ if (!version?.tree) {
1155
+ this.logger?.warn(
1156
+ `[resolveAgentSkillSource] Skill '${skillId}' version has no tree manifest, skipping versioned resolution`
1157
+ );
1158
+ continue;
1159
+ }
1160
+ versionedEntries.push({
1161
+ dirName,
1162
+ tree: version.tree,
1163
+ versionCreatedAt: version.createdAt
1164
+ });
1165
+ } catch (error) {
1166
+ this.logger?.warn(`[resolveAgentSkillSource] Failed to resolve version for skill '${skillId}': ${error}`);
1167
+ }
1168
+ }
1169
+ if (versionedEntries.length === 0) return void 0;
1170
+ return new CompositeVersionedSkillSource(versionedEntries, blobStore);
1171
+ }
1021
1172
  };
1022
1173
 
1023
1174
  // src/namespaces/prompt.ts
@@ -1026,7 +1177,7 @@ var EditorPromptNamespace = class extends CrudEditorNamespace {
1026
1177
  this.mastra?.removePromptBlock(id);
1027
1178
  }
1028
1179
  async getStorageAdapter() {
1029
- const storage = this.mastra.getStorage();
1180
+ const storage = this.mastra?.getStorage();
1030
1181
  if (!storage) throw new Error("Storage is not configured");
1031
1182
  const store = await storage.getStore("promptBlocks");
1032
1183
  if (!store) throw new Error("Prompt blocks storage domain is not available");
@@ -1041,7 +1192,7 @@ var EditorPromptNamespace = class extends CrudEditorNamespace {
1041
1192
  }
1042
1193
  async preview(blocks, context) {
1043
1194
  this.ensureRegistered();
1044
- const storage = this.mastra.getStorage();
1195
+ const storage = this.mastra?.getStorage();
1045
1196
  if (!storage) throw new Error("Storage is not configured");
1046
1197
  const store = await storage.getStore("promptBlocks");
1047
1198
  if (!store) throw new Error("Prompt blocks storage domain is not available");
@@ -1068,7 +1219,7 @@ var EditorScorerNamespace = class extends CrudEditorNamespace {
1068
1219
  return storedScorer;
1069
1220
  }
1070
1221
  async getStorageAdapter() {
1071
- const storage = this.mastra.getStorage();
1222
+ const storage = this.mastra?.getStorage();
1072
1223
  if (!storage) throw new Error("Storage is not configured");
1073
1224
  const store = await storage.getStore("scorerDefinitions");
1074
1225
  if (!store) throw new Error("Scorer definitions storage domain is not available");
@@ -1149,15 +1300,255 @@ Explain your reasoning for this score in a clear, concise paragraph.`;
1149
1300
  }
1150
1301
  };
1151
1302
 
1303
+ // src/namespaces/workspace.ts
1304
+ import { Workspace as Workspace2 } from "@mastra/core/workspace";
1305
+ var EditorWorkspaceNamespace = class extends CrudEditorNamespace {
1306
+ onCacheEvict(_id) {
1307
+ }
1308
+ /**
1309
+ * Hydrate a stored workspace snapshot config into a runtime Workspace instance.
1310
+ * Resolves provider strings to actual instances using the editor's registries.
1311
+ *
1312
+ * This is NOT called from the CrudEditorNamespace flow — it is a public utility
1313
+ * used by EditorAgentNamespace during agent hydration.
1314
+ */
1315
+ async hydrateSnapshotToWorkspace(id, snapshot, options) {
1316
+ const config = {
1317
+ id,
1318
+ name: snapshot.name
1319
+ };
1320
+ if (snapshot.filesystem) {
1321
+ config.filesystem = await this.resolveFilesystem(snapshot.filesystem);
1322
+ }
1323
+ if (snapshot.sandbox) {
1324
+ config.sandbox = await this.resolveSandbox(snapshot.sandbox);
1325
+ }
1326
+ if (snapshot.mounts) {
1327
+ const mounts = {};
1328
+ for (const [path, fsConfig] of Object.entries(snapshot.mounts)) {
1329
+ mounts[path] = await this.resolveFilesystem(fsConfig);
1330
+ }
1331
+ config.mounts = mounts;
1332
+ }
1333
+ if (snapshot.search) {
1334
+ if (snapshot.search.bm25) {
1335
+ config.bm25 = snapshot.search.bm25;
1336
+ }
1337
+ if (snapshot.search.searchIndexName) {
1338
+ config.searchIndexName = snapshot.search.searchIndexName;
1339
+ }
1340
+ if (snapshot.search.autoIndexPaths) {
1341
+ config.autoIndexPaths = snapshot.search.autoIndexPaths;
1342
+ }
1343
+ if (snapshot.search.vectorProvider && this.mastra) {
1344
+ const vectors = this.mastra.listVectors();
1345
+ const vectorStore = vectors?.[snapshot.search.vectorProvider];
1346
+ if (vectorStore) {
1347
+ config.vectorStore = vectorStore;
1348
+ } else {
1349
+ this.logger?.warn(
1350
+ `Vector provider "${snapshot.search.vectorProvider}" not found in Mastra instance. Workspace search will be limited to BM25 only.`
1351
+ );
1352
+ }
1353
+ }
1354
+ if (config.vectorStore && !config.embedder) {
1355
+ this.logger?.warn(
1356
+ `Workspace has a vector store configured but no embedder. Vector/hybrid search will not be available. Configure an embedder to enable semantic search.`
1357
+ );
1358
+ }
1359
+ }
1360
+ if (options?.skillSource) {
1361
+ config.skillSource = options.skillSource;
1362
+ config.skills = ["."];
1363
+ } else if (snapshot.skills && snapshot.skills.length > 0) {
1364
+ config.skills = snapshot.skills;
1365
+ }
1366
+ if (snapshot.tools) {
1367
+ config.tools = snapshot.tools;
1368
+ }
1369
+ if (snapshot.autoSync !== void 0) {
1370
+ config.autoSync = snapshot.autoSync;
1371
+ }
1372
+ if (snapshot.operationTimeout !== void 0) {
1373
+ config.operationTimeout = snapshot.operationTimeout;
1374
+ }
1375
+ return new Workspace2(config);
1376
+ }
1377
+ /**
1378
+ * Resolve a stored filesystem config to a runtime WorkspaceFilesystem instance.
1379
+ * Looks up the provider by ID in the editor's registry (which includes built-in providers).
1380
+ */
1381
+ async resolveFilesystem(fsConfig) {
1382
+ const provider = this.editor.__filesystems.get(fsConfig.provider);
1383
+ if (!provider) {
1384
+ throw new Error(
1385
+ `Filesystem provider "${fsConfig.provider}" is not registered. Register it via new MastraEditor({ filesystems: [yourProvider] })`
1386
+ );
1387
+ }
1388
+ const config = { ...fsConfig.config, readOnly: fsConfig.readOnly };
1389
+ return await provider.createFilesystem(config);
1390
+ }
1391
+ /**
1392
+ * Resolve a stored sandbox config to a runtime WorkspaceSandbox instance.
1393
+ * Looks up the provider by ID in the editor's registry (which includes built-in providers).
1394
+ */
1395
+ async resolveSandbox(sandboxConfig) {
1396
+ const provider = this.editor.__sandboxes.get(sandboxConfig.provider);
1397
+ if (!provider) {
1398
+ throw new Error(
1399
+ `Sandbox provider "${sandboxConfig.provider}" is not registered. Register it via new MastraEditor({ sandboxes: [yourProvider] })`
1400
+ );
1401
+ }
1402
+ return await provider.createSandbox(sandboxConfig.config);
1403
+ }
1404
+ async getStorageAdapter() {
1405
+ const storage = this.mastra?.getStorage();
1406
+ if (!storage) throw new Error("Storage is not configured");
1407
+ const store = await storage.getStore("workspaces");
1408
+ if (!store) throw new Error("Workspaces storage domain is not available");
1409
+ return {
1410
+ create: (input) => store.create({ workspace: input }),
1411
+ getByIdResolved: (id) => store.getByIdResolved(id),
1412
+ update: (input) => store.update(input),
1413
+ delete: (id) => store.delete(id),
1414
+ list: (args) => store.list(args),
1415
+ listResolved: (args) => store.listResolved(args)
1416
+ };
1417
+ }
1418
+ };
1419
+
1420
+ // src/namespaces/skill.ts
1421
+ import { publishSkillFromSource } from "@mastra/core/workspace";
1422
+ var EditorSkillNamespace = class extends CrudEditorNamespace {
1423
+ onCacheEvict(_id) {
1424
+ }
1425
+ async getStorageAdapter() {
1426
+ const storage = this.mastra?.getStorage();
1427
+ if (!storage) throw new Error("Storage is not configured");
1428
+ const store = await storage.getStore("skills");
1429
+ if (!store) throw new Error("Skills storage domain is not available");
1430
+ return {
1431
+ create: (input) => store.create({ skill: input }),
1432
+ getByIdResolved: (id) => store.getByIdResolved(id),
1433
+ update: (input) => store.update(input),
1434
+ delete: (id) => store.delete(id),
1435
+ list: (args) => store.list(args),
1436
+ listResolved: (args) => store.listResolved(args)
1437
+ };
1438
+ }
1439
+ /**
1440
+ * Publish a skill from a live filesystem source.
1441
+ * Walks the skill directory, hashes files into the blob store,
1442
+ * creates a new version with the tree manifest, and sets activeVersionId.
1443
+ */
1444
+ async publish(skillId, source, skillPath) {
1445
+ this.ensureRegistered();
1446
+ const storage = this.mastra?.getStorage();
1447
+ if (!storage) throw new Error("Storage is not configured");
1448
+ const skillStore = await storage.getStore("skills");
1449
+ if (!skillStore) throw new Error("Skills storage domain is not available");
1450
+ const blobStore = await this.editor.resolveBlobStore();
1451
+ if (!blobStore)
1452
+ throw new Error("No blob store is configured. Register one via new MastraEditor({ blobStores: [...] })");
1453
+ const { snapshot, tree } = await publishSkillFromSource(source, skillPath, blobStore);
1454
+ await skillStore.update({
1455
+ id: skillId,
1456
+ ...snapshot,
1457
+ tree,
1458
+ status: "published"
1459
+ });
1460
+ const latestVersion = await skillStore.getLatestVersion(skillId);
1461
+ if (!latestVersion) {
1462
+ throw new Error(`Failed to retrieve version after publishing skill "${skillId}"`);
1463
+ }
1464
+ await skillStore.update({
1465
+ id: skillId,
1466
+ activeVersionId: latestVersion.id
1467
+ });
1468
+ const resolved = await skillStore.getByIdResolved(skillId);
1469
+ if (!resolved) throw new Error(`Failed to resolve skill ${skillId} after publish`);
1470
+ this.clearCache(skillId);
1471
+ this.editor.agent.invalidateAgentsReferencingSkill(skillId);
1472
+ return resolved;
1473
+ }
1474
+ };
1475
+
1476
+ // src/providers.ts
1477
+ import { LocalFilesystem } from "@mastra/core/workspace";
1478
+ import { LocalSandbox } from "@mastra/core/workspace";
1479
+ var localFilesystemProvider = {
1480
+ id: "local",
1481
+ name: "Local Filesystem",
1482
+ description: "A folder on the local disk",
1483
+ configSchema: {
1484
+ type: "object",
1485
+ required: ["basePath"],
1486
+ properties: {
1487
+ basePath: { type: "string", description: "Base directory path on disk" },
1488
+ contained: {
1489
+ type: "boolean",
1490
+ description: "Restrict operations to stay within basePath",
1491
+ default: true
1492
+ },
1493
+ readOnly: {
1494
+ type: "boolean",
1495
+ description: "Block all write operations",
1496
+ default: false
1497
+ }
1498
+ }
1499
+ },
1500
+ createFilesystem: (config) => new LocalFilesystem(config)
1501
+ };
1502
+ var localSandboxProvider = {
1503
+ id: "local",
1504
+ name: "Local Sandbox",
1505
+ description: "Execute commands on the local machine",
1506
+ configSchema: {
1507
+ type: "object",
1508
+ properties: {
1509
+ workingDirectory: { type: "string", description: "Working directory for command execution" },
1510
+ timeout: { type: "number", description: "Default timeout for operations in ms" },
1511
+ isolation: {
1512
+ type: "string",
1513
+ enum: ["none", "seatbelt", "bwrap"],
1514
+ description: "Isolation backend for sandboxed execution",
1515
+ default: "none"
1516
+ },
1517
+ env: {
1518
+ type: "object",
1519
+ description: "Environment variables for command execution",
1520
+ additionalProperties: { type: "string" }
1521
+ }
1522
+ }
1523
+ },
1524
+ createSandbox: (config) => new LocalSandbox(config)
1525
+ };
1526
+
1152
1527
  // src/index.ts
1153
1528
  var MastraEditor = class {
1154
1529
  constructor(config) {
1155
1530
  this.__logger = config?.logger;
1156
1531
  this.__toolProviders = config?.toolProviders ?? {};
1532
+ this.__filesystems = /* @__PURE__ */ new Map();
1533
+ this.__filesystems.set(localFilesystemProvider.id, localFilesystemProvider);
1534
+ for (const [id, provider] of Object.entries(config?.filesystems ?? {})) {
1535
+ this.__filesystems.set(id, provider);
1536
+ }
1537
+ this.__sandboxes = /* @__PURE__ */ new Map();
1538
+ this.__sandboxes.set(localSandboxProvider.id, localSandboxProvider);
1539
+ for (const [id, provider] of Object.entries(config?.sandboxes ?? {})) {
1540
+ this.__sandboxes.set(id, provider);
1541
+ }
1542
+ this.__blobStores = /* @__PURE__ */ new Map();
1543
+ for (const [id, provider] of Object.entries(config?.blobStores ?? {})) {
1544
+ this.__blobStores.set(id, provider);
1545
+ }
1157
1546
  this.agent = new EditorAgentNamespace(this);
1158
1547
  this.mcp = new EditorMCPNamespace(this);
1159
1548
  this.prompt = new EditorPromptNamespace(this);
1160
1549
  this.scorer = new EditorScorerNamespace(this);
1550
+ this.workspace = new EditorWorkspaceNamespace(this);
1551
+ this.skill = new EditorSkillNamespace(this);
1161
1552
  }
1162
1553
  /**
1163
1554
  * Register this editor with a Mastra instance.
@@ -1177,6 +1568,46 @@ var MastraEditor = class {
1177
1568
  getToolProviders() {
1178
1569
  return this.__toolProviders;
1179
1570
  }
1571
+ /** List all registered filesystem providers */
1572
+ getFilesystemProviders() {
1573
+ return Array.from(this.__filesystems.values());
1574
+ }
1575
+ /** List all registered sandbox providers */
1576
+ getSandboxProviders() {
1577
+ return Array.from(this.__sandboxes.values());
1578
+ }
1579
+ /** List all registered blob store providers */
1580
+ getBlobStoreProviders() {
1581
+ return Array.from(this.__blobStores.values());
1582
+ }
1583
+ /**
1584
+ * Resolve a blob store from the provider registry, or fall back to the
1585
+ * storage backend's blobs domain.
1586
+ *
1587
+ * @param providerId - If specified, look up a registered provider by ID
1588
+ * and create a blob store from the given config. If omitted, falls back
1589
+ * to `storage.getStore('blobs')`.
1590
+ * @param providerConfig - Provider-specific configuration (only used when
1591
+ * `providerId` is specified).
1592
+ */
1593
+ async resolveBlobStore(providerId, providerConfig) {
1594
+ if (providerId) {
1595
+ const provider = this.__blobStores.get(providerId);
1596
+ if (!provider) {
1597
+ throw new Error(
1598
+ `Blob store provider "${providerId}" is not registered. Register it via new MastraEditor({ blobStores: { '${providerId}': yourProvider } })`
1599
+ );
1600
+ }
1601
+ const blobStore2 = await provider.createBlobStore(providerConfig ?? {});
1602
+ await blobStore2.init();
1603
+ return blobStore2;
1604
+ }
1605
+ const storage = this.__mastra?.getStorage();
1606
+ if (!storage) throw new Error("Storage is not configured");
1607
+ const blobStore = await storage.getStore("blobs");
1608
+ if (!blobStore) throw new Error("Blob storage domain is not available");
1609
+ return blobStore;
1610
+ }
1180
1611
  };
1181
1612
  export {
1182
1613
  CrudEditorNamespace,
@@ -1185,8 +1616,12 @@ export {
1185
1616
  EditorNamespace,
1186
1617
  EditorPromptNamespace,
1187
1618
  EditorScorerNamespace,
1619
+ EditorSkillNamespace,
1620
+ EditorWorkspaceNamespace,
1188
1621
  MastraEditor,
1189
1622
  evaluateRuleGroup,
1623
+ localFilesystemProvider,
1624
+ localSandboxProvider,
1190
1625
  renderTemplate,
1191
1626
  resolveInstructionBlocks
1192
1627
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/editor",
3
- "version": "0.4.0-alpha.0",
3
+ "version": "0.5.0-alpha.0",
4
4
  "description": "Mastra Editor for agent management and instantiation",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -55,7 +55,7 @@
55
55
  "@arcadeai/arcadejs": "^2.2.0",
56
56
  "@composio/core": "^0.6.3",
57
57
  "@composio/mastra": "^0.6.3",
58
- "@mastra/memory": "1.3.0-alpha.0",
58
+ "@mastra/memory": "1.4.0-alpha.0",
59
59
  "@mastra/schema-compat": "1.1.0"
60
60
  },
61
61
  "devDependencies": {
@@ -63,11 +63,11 @@
63
63
  "typescript": "^5.9.3",
64
64
  "vitest": "4.0.16",
65
65
  "zod": "^3.25.76",
66
- "@internal/ai-v6": "0.0.5",
67
- "@internal/ai-sdk-v5": "0.0.5",
68
- "@internal/ai-sdk-v4": "0.0.5",
69
- "@mastra/core": "1.4.0-alpha.0",
70
- "@mastra/libsql": "1.4.0-alpha.0"
66
+ "@internal/ai-sdk-v4": "0.0.6",
67
+ "@internal/ai-sdk-v5": "0.0.6",
68
+ "@internal/ai-v6": "0.0.6",
69
+ "@mastra/core": "1.5.0-alpha.0",
70
+ "@mastra/libsql": "1.5.0-alpha.0"
71
71
  },
72
72
  "peerDependencies": {
73
73
  "@mastra/core": ">=1.0.0-0 <2.0.0-0",