@mastra/deployer 1.54.0-alpha.0 → 1.54.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.
Files changed (211) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/analyze-C2q7jxbN.js +1308 -0
  3. package/dist/analyze-C2q7jxbN.js.map +1 -0
  4. package/dist/analyze-DhDZW9TS.cjs +1318 -0
  5. package/dist/analyze-DhDZW9TS.cjs.map +1 -0
  6. package/dist/arktype-aI7TBD0R-BsgjPZ4a.cjs +8 -0
  7. package/dist/arktype-aI7TBD0R-BsgjPZ4a.cjs.map +1 -0
  8. package/dist/arktype-aI7TBD0R-_UZl-wsH.js +8 -0
  9. package/dist/arktype-aI7TBD0R-_UZl-wsH.js.map +1 -0
  10. package/dist/build/analyze/constants.d.ts.map +1 -1
  11. package/dist/build/analyze.cjs +3 -12
  12. package/dist/build/analyze.js +2 -3
  13. package/dist/build/bundler.cjs +6 -24
  14. package/dist/build/bundler.js +2 -3
  15. package/dist/build/index.cjs +29 -101
  16. package/dist/build/index.js +7 -8
  17. package/dist/build-De4AZhfJ.cjs +908 -0
  18. package/dist/build-De4AZhfJ.cjs.map +1 -0
  19. package/dist/build-KCOeHd4N.js +834 -0
  20. package/dist/build-KCOeHd4N.js.map +1 -0
  21. package/dist/bundler/index.cjs +318 -13
  22. package/dist/bundler/index.cjs.map +1 -1
  23. package/dist/bundler/index.js +314 -2
  24. package/dist/bundler/index.js.map +1 -1
  25. package/dist/bundler-BqrDXofn.cjs +792 -0
  26. package/dist/bundler-BqrDXofn.cjs.map +1 -0
  27. package/dist/bundler-D86rFu2J.js +705 -0
  28. package/dist/bundler-D86rFu2J.js.map +1 -0
  29. package/dist/bundlerOptions-aFsEi86t.js +180 -0
  30. package/dist/bundlerOptions-aFsEi86t.js.map +1 -0
  31. package/dist/bundlerOptions-rBmtSyGe.cjs +194 -0
  32. package/dist/bundlerOptions-rBmtSyGe.cjs.map +1 -0
  33. package/dist/core-D0wEgdn3.cjs +790 -0
  34. package/dist/core-D0wEgdn3.cjs.map +1 -0
  35. package/dist/core-DF65PJXc.js +790 -0
  36. package/dist/core-DF65PJXc.js.map +1 -0
  37. package/dist/dist-BauTimif.js +532 -0
  38. package/dist/dist-BauTimif.js.map +1 -0
  39. package/dist/dist-Cv-mAEtr.cjs +532 -0
  40. package/dist/dist-Cv-mAEtr.cjs.map +1 -0
  41. package/dist/docs/SKILL.md +1 -1
  42. package/dist/docs/assets/SOURCE_MAP.json +2 -23
  43. package/dist/docs/references/docs-deployment-cloud-providers.md +1 -0
  44. package/dist/docs/references/docs-deployment-overview.md +1 -0
  45. package/dist/effect-QlVUlMFu-CwFnyS-g.cjs +14 -0
  46. package/dist/effect-QlVUlMFu-CwFnyS-g.cjs.map +1 -0
  47. package/dist/effect-QlVUlMFu-gyLQRCtQ.js +14 -0
  48. package/dist/effect-QlVUlMFu-gyLQRCtQ.js.map +1 -0
  49. package/dist/esm-BX-weMyC.js +4634 -0
  50. package/dist/esm-BX-weMyC.js.map +1 -0
  51. package/dist/esm-D81PZ_wJ.cjs +4634 -0
  52. package/dist/esm-D81PZ_wJ.cjs.map +1 -0
  53. package/dist/index-CLddUTqr-B5mOP6DC.cjs +145 -0
  54. package/dist/index-CLddUTqr-B5mOP6DC.cjs.map +1 -0
  55. package/dist/index-CLddUTqr-CkS6Y_hA.js +140 -0
  56. package/dist/index-CLddUTqr-CkS6Y_hA.js.map +1 -0
  57. package/dist/index.cjs +35 -48
  58. package/dist/index.cjs.map +1 -1
  59. package/dist/index.js +29 -30
  60. package/dist/index.js.map +1 -1
  61. package/dist/rolldown-runtime-emK7D4bc.cjs +35 -0
  62. package/dist/server/index.cjs +3141 -3874
  63. package/dist/server/index.cjs.map +1 -1
  64. package/dist/server/index.d.ts.map +1 -1
  65. package/dist/server/index.js +3131 -3842
  66. package/dist/server/index.js.map +1 -1
  67. package/dist/server/types.d.ts +1 -0
  68. package/dist/server/types.d.ts.map +1 -1
  69. package/dist/services/index.cjs +5 -20
  70. package/dist/services/index.js +2 -3
  71. package/dist/services-BxYMLS9-.cjs +430 -0
  72. package/dist/services-BxYMLS9-.cjs.map +1 -0
  73. package/dist/services-CLi56qqe.js +391 -0
  74. package/dist/services-CLi56qqe.js.map +1 -0
  75. package/dist/sury-CWZTCd75-B85M6878.js +14 -0
  76. package/dist/sury-CWZTCd75-B85M6878.js.map +1 -0
  77. package/dist/sury-CWZTCd75-DTj5HlK_.cjs +14 -0
  78. package/dist/sury-CWZTCd75-DTj5HlK_.cjs.map +1 -0
  79. package/dist/typebox-Dei93FPO-BeuT13_G.cjs +8 -0
  80. package/dist/typebox-Dei93FPO-BeuT13_G.cjs.map +1 -0
  81. package/dist/typebox-Dei93FPO-DovwMlVl.js +8 -0
  82. package/dist/typebox-Dei93FPO-DovwMlVl.js.map +1 -0
  83. package/dist/utils-FVOUvj-I.js +190 -0
  84. package/dist/utils-FVOUvj-I.js.map +1 -0
  85. package/dist/utils-O98BGdnP.cjs +267 -0
  86. package/dist/utils-O98BGdnP.cjs.map +1 -0
  87. package/dist/valibot--1zFm7rT-BqJHja5B.cjs +14 -0
  88. package/dist/valibot--1zFm7rT-BqJHja5B.cjs.map +1 -0
  89. package/dist/valibot--1zFm7rT-Y4Fhea0w.js +14 -0
  90. package/dist/valibot--1zFm7rT-Y4Fhea0w.js.map +1 -0
  91. package/dist/validator/custom-resolver.cjs +71 -73
  92. package/dist/validator/custom-resolver.cjs.map +1 -1
  93. package/dist/validator/custom-resolver.js +70 -71
  94. package/dist/validator/custom-resolver.js.map +1 -1
  95. package/dist/validator/loader.cjs +6 -7
  96. package/dist/validator/loader.cjs.map +1 -1
  97. package/dist/validator/loader.js +8 -4
  98. package/dist/validator/loader.js.map +1 -1
  99. package/dist/zod-Bwrt9trS-2JL6_UI_.cjs +23 -0
  100. package/dist/zod-Bwrt9trS-2JL6_UI_.cjs.map +1 -0
  101. package/dist/zod-Bwrt9trS-rVHICsmp.js +23 -0
  102. package/dist/zod-Bwrt9trS-rVHICsmp.js.map +1 -0
  103. package/package.json +7 -7
  104. package/dist/arktype-aI7TBD0R-K3QZAVE2.js +0 -8
  105. package/dist/arktype-aI7TBD0R-K3QZAVE2.js.map +0 -1
  106. package/dist/arktype-aI7TBD0R-WK5AZZMC.cjs +0 -10
  107. package/dist/arktype-aI7TBD0R-WK5AZZMC.cjs.map +0 -1
  108. package/dist/build/analyze.cjs.map +0 -1
  109. package/dist/build/analyze.js.map +0 -1
  110. package/dist/build/bundler.cjs.map +0 -1
  111. package/dist/build/bundler.js.map +0 -1
  112. package/dist/build/index.cjs.map +0 -1
  113. package/dist/build/index.js.map +0 -1
  114. package/dist/chunk-36AWZH7Z.cjs +0 -252
  115. package/dist/chunk-36AWZH7Z.cjs.map +0 -1
  116. package/dist/chunk-3XIMK24X.cjs +0 -765
  117. package/dist/chunk-3XIMK24X.cjs.map +0 -1
  118. package/dist/chunk-46M65MQG.cjs +0 -95
  119. package/dist/chunk-46M65MQG.cjs.map +0 -1
  120. package/dist/chunk-4ZNTNJ6T.js +0 -6
  121. package/dist/chunk-4ZNTNJ6T.js.map +0 -1
  122. package/dist/chunk-5PORNUPF.js +0 -739
  123. package/dist/chunk-5PORNUPF.js.map +0 -1
  124. package/dist/chunk-743HRNWT.cjs +0 -1546
  125. package/dist/chunk-743HRNWT.cjs.map +0 -1
  126. package/dist/chunk-AEQ7JHDB.cjs +0 -412
  127. package/dist/chunk-AEQ7JHDB.cjs.map +0 -1
  128. package/dist/chunk-E5SBYHQK.js +0 -244
  129. package/dist/chunk-E5SBYHQK.js.map +0 -1
  130. package/dist/chunk-FKKJQUGR.cjs +0 -497
  131. package/dist/chunk-FKKJQUGR.cjs.map +0 -1
  132. package/dist/chunk-FQHUOYYL.js +0 -1514
  133. package/dist/chunk-FQHUOYYL.js.map +0 -1
  134. package/dist/chunk-G7MIMGMX.js +0 -14
  135. package/dist/chunk-G7MIMGMX.js.map +0 -1
  136. package/dist/chunk-HZC3PTK2.cjs +0 -16
  137. package/dist/chunk-HZC3PTK2.cjs.map +0 -1
  138. package/dist/chunk-JZRFRUGM.cjs +0 -158
  139. package/dist/chunk-JZRFRUGM.cjs.map +0 -1
  140. package/dist/chunk-L45X3DJX.js +0 -385
  141. package/dist/chunk-L45X3DJX.js.map +0 -1
  142. package/dist/chunk-PC25XSK7.cjs +0 -8
  143. package/dist/chunk-PC25XSK7.cjs.map +0 -1
  144. package/dist/chunk-PZ5AY32C.js +0 -9
  145. package/dist/chunk-PZ5AY32C.js.map +0 -1
  146. package/dist/chunk-Q7SFCCGT.cjs +0 -11
  147. package/dist/chunk-Q7SFCCGT.cjs.map +0 -1
  148. package/dist/chunk-T4UT2QX7.js +0 -3
  149. package/dist/chunk-T4UT2QX7.js.map +0 -1
  150. package/dist/chunk-UBIDJOJA.js +0 -93
  151. package/dist/chunk-UBIDJOJA.js.map +0 -1
  152. package/dist/chunk-V3EKV6QB.cjs +0 -162
  153. package/dist/chunk-V3EKV6QB.cjs.map +0 -1
  154. package/dist/chunk-WHD2QQ3N.js +0 -783
  155. package/dist/chunk-WHD2QQ3N.js.map +0 -1
  156. package/dist/chunk-WP65JQAT.js +0 -144
  157. package/dist/chunk-WP65JQAT.js.map +0 -1
  158. package/dist/chunk-YO5OFXPN.cjs +0 -819
  159. package/dist/chunk-YO5OFXPN.cjs.map +0 -1
  160. package/dist/chunk-YUBKHO52.js +0 -465
  161. package/dist/chunk-YUBKHO52.js.map +0 -1
  162. package/dist/chunk-YWMYXUHX.cjs +0 -4
  163. package/dist/chunk-YWMYXUHX.cjs.map +0 -1
  164. package/dist/chunk-ZKZOVNT4.js +0 -159
  165. package/dist/chunk-ZKZOVNT4.js.map +0 -1
  166. package/dist/core-XIDAXLRB.js +0 -11866
  167. package/dist/core-XIDAXLRB.js.map +0 -1
  168. package/dist/core-XJNQ4AY6.cjs +0 -12141
  169. package/dist/core-XJNQ4AY6.cjs.map +0 -1
  170. package/dist/default-u_dwuiYb-HGUAHA6N.cjs +0 -9
  171. package/dist/default-u_dwuiYb-HGUAHA6N.cjs.map +0 -1
  172. package/dist/default-u_dwuiYb-MVPTVDCE.js +0 -3
  173. package/dist/default-u_dwuiYb-MVPTVDCE.js.map +0 -1
  174. package/dist/dist-UEE5OLII.cjs +0 -521
  175. package/dist/dist-UEE5OLII.cjs.map +0 -1
  176. package/dist/dist-X75F2Q36.js +0 -515
  177. package/dist/dist-X75F2Q36.js.map +0 -1
  178. package/dist/effect-QlVUlMFu-QNLZLGWO.js +0 -15
  179. package/dist/effect-QlVUlMFu-QNLZLGWO.js.map +0 -1
  180. package/dist/effect-QlVUlMFu-XUD6EH23.cjs +0 -17
  181. package/dist/effect-QlVUlMFu-XUD6EH23.cjs.map +0 -1
  182. package/dist/esm-DFCHSIJZ.cjs +0 -1589
  183. package/dist/esm-DFCHSIJZ.cjs.map +0 -1
  184. package/dist/esm-PXGQ5WB4.js +0 -1542
  185. package/dist/esm-PXGQ5WB4.js.map +0 -1
  186. package/dist/services/index.cjs.map +0 -1
  187. package/dist/services/index.js.map +0 -1
  188. package/dist/sury-CWZTCd75-3KQQJ22C.cjs +0 -17
  189. package/dist/sury-CWZTCd75-3KQQJ22C.cjs.map +0 -1
  190. package/dist/sury-CWZTCd75-DZQHKAZF.js +0 -15
  191. package/dist/sury-CWZTCd75-DZQHKAZF.js.map +0 -1
  192. package/dist/typebox-Dei93FPO-GOYJ5OUT.js +0 -8
  193. package/dist/typebox-Dei93FPO-GOYJ5OUT.js.map +0 -1
  194. package/dist/typebox-Dei93FPO-M7J7E57W.cjs +0 -10
  195. package/dist/typebox-Dei93FPO-M7J7E57W.cjs.map +0 -1
  196. package/dist/valibot--1zFm7rT-NVM3G3TI.cjs +0 -17
  197. package/dist/valibot--1zFm7rT-NVM3G3TI.cjs.map +0 -1
  198. package/dist/valibot--1zFm7rT-ZVGQI7WV.js +0 -15
  199. package/dist/valibot--1zFm7rT-ZVGQI7WV.js.map +0 -1
  200. package/dist/valibot-D_HTw1Gn-UCPEGDL7.cjs +0 -45
  201. package/dist/valibot-D_HTw1Gn-UCPEGDL7.cjs.map +0 -1
  202. package/dist/valibot-D_HTw1Gn-XPR4F6VS.js +0 -43
  203. package/dist/valibot-D_HTw1Gn-XPR4F6VS.js.map +0 -1
  204. package/dist/zod-Bwrt9trS-GN7ZXBMN.js +0 -29
  205. package/dist/zod-Bwrt9trS-GN7ZXBMN.js.map +0 -1
  206. package/dist/zod-Bwrt9trS-OVKARV6W.cjs +0 -31
  207. package/dist/zod-Bwrt9trS-OVKARV6W.cjs.map +0 -1
  208. package/dist/zod-DSgpEGAE-E7YZZ7VC.js +0 -37
  209. package/dist/zod-DSgpEGAE-E7YZZ7VC.js.map +0 -1
  210. package/dist/zod-DSgpEGAE-UNQNGL2W.cjs +0 -39
  211. package/dist/zod-DSgpEGAE-UNQNGL2W.cjs.map +0 -1
@@ -0,0 +1,834 @@
1
+ import { i as getWorkspaceInformation, n as checkConfigExport, r as aliasHono, t as analyzeBundle } from "./analyze-C2q7jxbN.js";
2
+ import { a as getPackageName, p as slash } from "./utils-FVOUvj-I.js";
3
+ import "./services-CLi56qqe.js";
4
+ import { a as tsConfigPaths, l as nodeModulesExtensionResolver, n as getInputOptions$1 } from "./bundler-D86rFu2J.js";
5
+ import { n as extractMastraOption } from "./bundlerOptions-aFsEi86t.js";
6
+ import { cp, lstat, mkdir, readFile, readdir, writeFile } from "fs/promises";
7
+ import { dirname, join, posix } from "path";
8
+ import * as pkg from "empathic/package";
9
+ import { transformAsync } from "@babel/core";
10
+ import { watch } from "rollup";
11
+ import { noopLogger } from "@mastra/core/logger";
12
+ import { MAX_FS_SUBAGENT_DEPTH } from "@mastra/core/agent";
13
+ import matter from "gray-matter";
14
+ //#region src/build/watcher.ts
15
+ async function getInputOptions(entryFile, platform, env, { sourcemap = false, bundlerOptions = {
16
+ enableSourcemap: false,
17
+ enableEsmShim: true,
18
+ externals: true
19
+ }, analysisEntries = [entryFile] } = {}) {
20
+ const closestPkgJson = pkg.up({ cwd: dirname(entryFile) });
21
+ const projectRoot = closestPkgJson ? dirname(slash(closestPkgJson)) : slash(process.cwd());
22
+ const { workspaceMap, workspaceRoot } = await getWorkspaceInformation({ mastraEntryFile: entryFile });
23
+ const analyzeEntryResult = await analyzeBundle(analysisEntries, entryFile, {
24
+ outputDir: posix.join(process.cwd(), ".mastra", ".build"),
25
+ projectRoot: workspaceRoot || process.cwd(),
26
+ platform,
27
+ isDev: true,
28
+ bundlerOptions
29
+ }, noopLogger);
30
+ const deps = /* @__PURE__ */ new Map();
31
+ for (const [dep, metadata] of analyzeEntryResult.dependencies.entries()) {
32
+ const pkgName = getPackageName(dep);
33
+ if (pkgName && workspaceMap.has(pkgName)) deps.set(dep, metadata);
34
+ }
35
+ const inputOptions = await getInputOptions$1(entryFile, {
36
+ dependencies: deps,
37
+ externalDependencies: /* @__PURE__ */ new Map(),
38
+ workspaceMap
39
+ }, platform, env, {
40
+ sourcemap,
41
+ isDev: true,
42
+ workspaceRoot,
43
+ projectRoot,
44
+ externalsPreset: bundlerOptions?.externals === true
45
+ });
46
+ if (Array.isArray(inputOptions.plugins)) {
47
+ const plugins = [];
48
+ inputOptions.plugins.forEach((plugin) => {
49
+ if (plugin?.name === "node-resolve") return;
50
+ if (plugin?.name === "tsconfig-paths") {
51
+ plugins.push(tsConfigPaths({ localResolve: true }));
52
+ return;
53
+ }
54
+ plugins.push(plugin);
55
+ });
56
+ inputOptions.plugins = plugins;
57
+ inputOptions.plugins.push(aliasHono());
58
+ inputOptions.plugins.push(nodeModulesExtensionResolver());
59
+ }
60
+ return inputOptions;
61
+ }
62
+ async function createWatcher(inputOptions, outputOptions) {
63
+ return await watch({
64
+ ...inputOptions,
65
+ output: {
66
+ ...outputOptions,
67
+ format: "esm",
68
+ entryFileNames: "[name].mjs",
69
+ chunkFileNames: "[name].mjs"
70
+ }
71
+ });
72
+ }
73
+ //#endregion
74
+ //#region src/build/analyzeEntryProjectType.ts
75
+ /**
76
+ * Lightweight entry analysis that returns the detected project type by running
77
+ * only the Babel check-config-export plugin on the Mastra entry file. This is
78
+ * intentionally cheaper than `analyzeBundle` and is used by the CLI before
79
+ * `prepare()` clears `.mastra` to decide whether Factory-specific assets
80
+ * should be copied.
81
+ *
82
+ * Returns `'factory'` when the entry imports `MastraFactory` and
83
+ * constructs it, or `undefined` for ordinary Mastra projects.
84
+ */
85
+ async function analyzeEntryProjectType(mastraEntry) {
86
+ const code = await readFile(mastraEntry, "utf-8");
87
+ const result = { hasValidConfig: false };
88
+ await transformAsync(code, {
89
+ filename: mastraEntry,
90
+ presets: [import.meta.resolve("@babel/preset-typescript")],
91
+ plugins: [() => checkConfigExport(result)]
92
+ });
93
+ return result.projectType;
94
+ }
95
+ //#endregion
96
+ //#region src/build/serverOptions.ts
97
+ async function getServerOptions(entryFile, outputDir, logger) {
98
+ const result = await extractMastraOption("server", entryFile, outputDir, logger);
99
+ if (!result) return null;
100
+ return result.getConfig();
101
+ }
102
+ //#endregion
103
+ //#region src/build/fs-routing/discover.ts
104
+ const CONFIG_BASENAMES = ["config.ts", "config.js"];
105
+ const WORKSPACE_BASENAMES = ["workspace.ts", "workspace.js"];
106
+ const MEMORY_BASENAMES = ["memory.ts", "memory.js"];
107
+ const INSTRUCTIONS_BASENAME = "instructions.md";
108
+ const TOOL_EXTENSIONS = [".ts", ".js"];
109
+ const SKILL_MODULE_EXTENSIONS = [".ts", ".js"];
110
+ const SKILL_MD_BASENAME = "SKILL.md";
111
+ /**
112
+ * Presence check that does NOT follow symlinks. Returns `false` for symlinks
113
+ * (and broken links) so a symlinked `config.ts`/`instructions.md`/`workspace.ts`/
114
+ * `memory.ts` is never inlined or imported into the generated bundle.
115
+ */
116
+ async function exists(path) {
117
+ try {
118
+ return !(await lstat(path)).isSymbolicLink();
119
+ } catch {
120
+ return false;
121
+ }
122
+ }
123
+ /**
124
+ * Returns the slash-normalized path when `path` is a real directory (not a
125
+ * symlink). Symlinked directories are rejected to prevent the build from
126
+ * following links out of the project tree during discovery.
127
+ */
128
+ async function realDirectory(path) {
129
+ try {
130
+ const info = await lstat(path);
131
+ if (info.isDirectory() && !info.isSymbolicLink()) return slash(path);
132
+ } catch {}
133
+ }
134
+ async function directoryExists(path) {
135
+ return realDirectory(path);
136
+ }
137
+ async function firstExisting(dir, basenames) {
138
+ for (const basename of basenames) {
139
+ const candidate = join(dir, basename);
140
+ if (await exists(candidate)) return slash(candidate);
141
+ }
142
+ }
143
+ function isTestFile(basename) {
144
+ return /\.(test|spec)\.(ts|js)$/.test(basename);
145
+ }
146
+ function toolKey(basename) {
147
+ return basename.replace(/\.(ts|js)$/, "");
148
+ }
149
+ /**
150
+ * Discover default-exporting `.ts`/`.js` modules directly under `dir`, returning
151
+ * `{ key, path }` entries in stable (sorted) order. Test files, symlinks, and
152
+ * subdirectories are skipped: a symlinked module could point anywhere on the
153
+ * build machine and be embedded into generated import code. Shared by the
154
+ * `tools/` and `scorers/` scanners.
155
+ */
156
+ async function discoverModuleDir(dir) {
157
+ if (!await exists(dir)) return [];
158
+ let entries;
159
+ try {
160
+ entries = await readdir(dir);
161
+ } catch {
162
+ return [];
163
+ }
164
+ const modules = [];
165
+ for (const basename of entries.sort()) {
166
+ if (isTestFile(basename)) continue;
167
+ if (!TOOL_EXTENSIONS.some((ext) => basename.endsWith(ext))) continue;
168
+ const path = join(dir, basename);
169
+ const stats = await lstat(path);
170
+ if (stats.isSymbolicLink() || stats.isDirectory()) continue;
171
+ modules.push({
172
+ key: toolKey(basename),
173
+ path: slash(path)
174
+ });
175
+ }
176
+ return modules;
177
+ }
178
+ async function discoverTools(toolsDir) {
179
+ return discoverModuleDir(toolsDir);
180
+ }
181
+ async function discoverProcessors(processorsDir) {
182
+ const result = {
183
+ input: [],
184
+ output: []
185
+ };
186
+ for (const type of ["input", "output"]) {
187
+ const typeDir = join(processorsDir, type);
188
+ if (!await exists(typeDir)) continue;
189
+ let entries;
190
+ try {
191
+ entries = await readdir(typeDir);
192
+ } catch {
193
+ continue;
194
+ }
195
+ for (const basename of entries.sort()) {
196
+ if (isTestFile(basename)) continue;
197
+ if (!TOOL_EXTENSIONS.some((ext) => basename.endsWith(ext))) continue;
198
+ const path = join(typeDir, basename);
199
+ const stats = await lstat(path);
200
+ if (stats.isSymbolicLink() || stats.isDirectory()) continue;
201
+ result[type].push({
202
+ key: toolKey(basename),
203
+ path: slash(path)
204
+ });
205
+ }
206
+ }
207
+ return result;
208
+ }
209
+ async function readReferences(referencesDir) {
210
+ if (!await exists(referencesDir)) return {};
211
+ const references = {};
212
+ let entries;
213
+ try {
214
+ entries = await readdir(referencesDir);
215
+ } catch {
216
+ return {};
217
+ }
218
+ for (const basename of entries.sort()) {
219
+ const path = join(referencesDir, basename);
220
+ const stats = await lstat(path);
221
+ if (stats.isSymbolicLink() || stats.isDirectory()) continue;
222
+ references[basename] = await readFile(path, "utf-8");
223
+ }
224
+ return references;
225
+ }
226
+ async function parsePackagedSkill(skillMdPath, fallbackName, references = {}) {
227
+ const parsed = matter(await readFile(skillMdPath, "utf-8"));
228
+ const frontmatter = parsed.data;
229
+ const name = frontmatter.name ?? fallbackName;
230
+ const description = frontmatter.description;
231
+ if (!description) throw new Error(`Skill "${name}" in ${skillMdPath} is missing a required "description". Add a YAML frontmatter block with a "description:" field. See https://agentskills.io/specification for the SKILL.md format.`);
232
+ return {
233
+ kind: "packaged",
234
+ name,
235
+ description,
236
+ instructions: parsed.content.trim(),
237
+ references
238
+ };
239
+ }
240
+ function skillModuleName(basename) {
241
+ return basename.replace(/\.(ts|js)$/, "");
242
+ }
243
+ async function discoverSkills(skillsDir) {
244
+ if (!await exists(skillsDir)) return [];
245
+ let entries;
246
+ try {
247
+ entries = await readdir(skillsDir);
248
+ } catch {
249
+ return [];
250
+ }
251
+ const skills = [];
252
+ for (const basename of entries.sort()) {
253
+ if (isTestFile(basename)) continue;
254
+ const path = join(skillsDir, basename);
255
+ const stats = await lstat(path);
256
+ if (stats.isSymbolicLink()) continue;
257
+ if (stats.isDirectory()) {
258
+ const skillMd = join(path, SKILL_MD_BASENAME);
259
+ if (await exists(skillMd)) {
260
+ const references = await readReferences(join(path, "references"));
261
+ skills.push(await parsePackagedSkill(skillMd, skillModuleName(basename), references));
262
+ }
263
+ continue;
264
+ }
265
+ if (SKILL_MODULE_EXTENSIONS.some((ext) => basename.endsWith(ext))) {
266
+ skills.push({
267
+ kind: "module",
268
+ path: slash(path)
269
+ });
270
+ continue;
271
+ }
272
+ if (basename.endsWith(".md")) {
273
+ const skill = await parsePackagedSkill(path, basename.replace(/\.md$/, ""));
274
+ skills.push(skill);
275
+ }
276
+ }
277
+ return skills;
278
+ }
279
+ /**
280
+ * Discover a single agent directory: its `config`/`instructions`/`workspace`
281
+ * files plus `tools/`, `skills/`, and declared `subagents/`. Returns
282
+ * `undefined` when `dir` is not an agent directory (no `config.(ts|js)` and no
283
+ * `instructions.md`).
284
+ *
285
+ * `depth` is the subagent nesting level (`0` for top-level agents). Discovery
286
+ * recurses into `subagents/` until `MAX_FS_SUBAGENT_DEPTH`; deeper directories
287
+ * are ignored with a warning.
288
+ */
289
+ async function discoverAgentDir(dir, name, depth, onWarn) {
290
+ const configPath = await firstExisting(dir, CONFIG_BASENAMES);
291
+ const instructionsPath = await exists(join(dir, INSTRUCTIONS_BASENAME)) ? slash(join(dir, INSTRUCTIONS_BASENAME)) : void 0;
292
+ if (!configPath && !instructionsPath) return;
293
+ const workspacePath = await firstExisting(dir, WORKSPACE_BASENAMES);
294
+ const memoryPath = await firstExisting(dir, MEMORY_BASENAMES);
295
+ const workspaceSeedDir = await directoryExists(join(dir, "workspace"));
296
+ const tools = await discoverTools(join(dir, "tools"));
297
+ const processors = await discoverProcessors(join(dir, "processors"));
298
+ const scorers = await discoverModuleDir(join(dir, "scorers"));
299
+ const skills = await discoverSkills(join(dir, "skills"));
300
+ const subagents = await discoverSubagents(dir, depth, onWarn);
301
+ return {
302
+ name,
303
+ dir: slash(dir),
304
+ configPath,
305
+ instructionsPath,
306
+ workspacePath,
307
+ memoryPath,
308
+ workspaceSeedDir,
309
+ tools,
310
+ inputProcessors: processors.input,
311
+ outputProcessors: processors.output,
312
+ scorers,
313
+ skills,
314
+ subagents
315
+ };
316
+ }
317
+ /**
318
+ * Discover declared subagents under `<dir>/subagents/*`. `parentDepth` is the
319
+ * parent agent's nesting level (`0` for top-level agents). Discovery recurses
320
+ * until `MAX_FS_SUBAGENT_DEPTH` levels of subagents; a `subagents/` directory
321
+ * that would exceed the cap is skipped with a warning.
322
+ */
323
+ async function discoverSubagents(parentDir, parentDepth, onWarn) {
324
+ const subagentsDir = join(parentDir, "subagents");
325
+ if (!await exists(subagentsDir)) return [];
326
+ if (parentDepth >= MAX_FS_SUBAGENT_DEPTH) {
327
+ onWarn?.(`Ignoring subagents in "${slash(subagentsDir)}": subagents may only nest ${MAX_FS_SUBAGENT_DEPTH} levels below a top-level agent.`);
328
+ return [];
329
+ }
330
+ let entries;
331
+ try {
332
+ entries = await readdir(subagentsDir);
333
+ } catch {
334
+ return [];
335
+ }
336
+ const subagents = [];
337
+ for (const name of entries.sort()) {
338
+ const dir = join(subagentsDir, name);
339
+ if (!await realDirectory(dir)) continue;
340
+ const child = await discoverAgentDir(dir, name, parentDepth + 1, onWarn);
341
+ if (child) subagents.push(child);
342
+ }
343
+ return subagents;
344
+ }
345
+ /**
346
+ * Scan `<mastraDir>/agents/*` for file-system routed agents. A directory is
347
+ * treated as an agent only when it contains a `config.(ts|js)` or an
348
+ * `instructions.md`; other directories are ignored. Each agent may declare
349
+ * `subagents/` up to `MAX_FS_SUBAGENT_DEPTH` levels deep. Returns descriptors
350
+ * with absolute, slash-normalized paths ready for codegen. Performs no module
351
+ * evaluation — only filesystem inspection.
352
+ */
353
+ async function discoverFsAgents(mastraDir, onWarn) {
354
+ const agentsDir = join(mastraDir, "agents");
355
+ if (!await exists(agentsDir)) return [];
356
+ let entries;
357
+ try {
358
+ entries = await readdir(agentsDir);
359
+ } catch {
360
+ return [];
361
+ }
362
+ const discovered = [];
363
+ for (const name of entries.sort()) {
364
+ const dir = join(agentsDir, name);
365
+ if (!await realDirectory(dir)) continue;
366
+ const agent = await discoverAgentDir(dir, name, 0, onWarn);
367
+ if (agent) discovered.push(agent);
368
+ }
369
+ return discovered;
370
+ }
371
+ /**
372
+ * Scan `<mastraDir>/workflows/` for file-system routed workflow modules. Only
373
+ * files whose source contains an `export default` are treated as fs-routed
374
+ * workflows — this convention distinguishes them from workflow files that are
375
+ * manually imported and registered programmatically. Returns descriptors with
376
+ * absolute, slash-normalized paths ready for codegen. Performs no module
377
+ * evaluation — only filesystem and source-text inspection.
378
+ */
379
+ async function discoverFsWorkflows(mastraDir) {
380
+ const workflowsDir = join(mastraDir, "workflows");
381
+ if (!await exists(workflowsDir)) return [];
382
+ let entries;
383
+ try {
384
+ entries = await readdir(workflowsDir);
385
+ } catch {
386
+ return [];
387
+ }
388
+ const discovered = [];
389
+ for (const basename of entries.sort()) {
390
+ if (isTestFile(basename)) continue;
391
+ if (!TOOL_EXTENSIONS.some((ext) => basename.endsWith(ext))) continue;
392
+ const path = join(workflowsDir, basename);
393
+ const stats = await lstat(path);
394
+ if (stats.isSymbolicLink() || stats.isDirectory()) continue;
395
+ const source = await readFile(path, "utf-8");
396
+ if (!/\bexport\s+default\b/.test(source)) continue;
397
+ discovered.push({
398
+ key: toolKey(basename),
399
+ path: slash(path)
400
+ });
401
+ }
402
+ return discovered;
403
+ }
404
+ const SINGLETON_EXTENSIONS = [
405
+ ".ts",
406
+ ".js",
407
+ ".mts",
408
+ ".mjs"
409
+ ];
410
+ /** Safe singleton identifier: no path separators, `..`, or other traversal. */
411
+ const SINGLETON_NAME_PATTERN = /^[a-zA-Z0-9_-]+$/;
412
+ /**
413
+ * Check for a singleton config file (e.g. `storage.ts`, `storage.js`) directly
414
+ * under `<mastraDir>`. Returns the first matching file path or `undefined`.
415
+ * Symlinks are rejected for security.
416
+ *
417
+ * Convention: only files with `export default` are fs-routed singletons. Files
418
+ * using named exports are assumed to be manually imported into the user's
419
+ * `index.ts`, so they are ignored to remain backward-compatible with existing
420
+ * project structures.
421
+ *
422
+ * `name` must be a bare identifier — path separators and traversal sequences are
423
+ * rejected so the lookup can never escape `<mastraDir>`.
424
+ */
425
+ async function discoverFsSingleton(mastraDir, name) {
426
+ if (!SINGLETON_NAME_PATTERN.test(name)) throw new Error(`Invalid fs-singleton name ${JSON.stringify(name)}: expected a bare identifier.`);
427
+ for (const ext of SINGLETON_EXTENSIONS) {
428
+ const candidate = join(mastraDir, `${name}${ext}`);
429
+ try {
430
+ const stats = await lstat(candidate);
431
+ if (!stats.isFile() || stats.isSymbolicLink()) continue;
432
+ const source = await readFile(candidate, "utf-8");
433
+ if (!/\bexport\s+default\b/.test(source)) continue;
434
+ return { path: slash(candidate) };
435
+ } catch {}
436
+ }
437
+ }
438
+ //#endregion
439
+ //#region src/build/fs-routing/codegen.ts
440
+ function sanitizeIdentifier(name, prefix, index) {
441
+ return `${prefix}_${index}_${name.replace(/[^a-zA-Z0-9_$]/g, "_")}`;
442
+ }
443
+ /**
444
+ * Emit the imports for a single discovered agent into `lines` and return the
445
+ * source of its `assembleAgentFromFsEntry` entry object (the `{ name, config,
446
+ * ... }` argument). `idPath` is a dot-free, unique path index (e.g. `0` for the
447
+ * first top-level agent, `0_1` for its second subagent) used to keep generated
448
+ * identifiers unique across the parent/child tree. `workspaceName` is the
449
+ * slash-joined workspace key (`<parent>/<child>` for subagents) so seed files
450
+ * don't collide. Discovered subagents are emitted recursively as a nested
451
+ * `subagents: [...]` field (discovery already enforces the depth cap).
452
+ */
453
+ async function emitAgentEntry(agent, idPath, workspaceName, lines) {
454
+ const configIdent = sanitizeIdentifier(agent.name, "config", idPath);
455
+ const toolIdents = [];
456
+ if (agent.configPath) lines.push(`import ${configIdent} from ${JSON.stringify(agent.configPath)};`);
457
+ let workspaceIdent;
458
+ if (agent.workspacePath) {
459
+ workspaceIdent = sanitizeIdentifier(`${agent.name}_workspace`, "workspace", idPath);
460
+ lines.push(`import ${workspaceIdent} from ${JSON.stringify(agent.workspacePath)};`);
461
+ }
462
+ let memoryIdent;
463
+ if (agent.memoryPath) {
464
+ memoryIdent = sanitizeIdentifier(`${agent.name}_memory`, "memory", idPath);
465
+ lines.push(`import ${memoryIdent} from ${JSON.stringify(agent.memoryPath)};`);
466
+ }
467
+ for (let t = 0; t < agent.tools.length; t++) {
468
+ const tool = agent.tools[t];
469
+ const ident = sanitizeIdentifier(`${agent.name}_${tool.key}`, "tool", `${idPath}_${t}`);
470
+ lines.push(`import ${ident} from ${JSON.stringify(tool.path)};`);
471
+ toolIdents.push({
472
+ key: tool.key,
473
+ ident
474
+ });
475
+ }
476
+ const inputProcessorIdents = [];
477
+ for (let p = 0; p < agent.inputProcessors.length; p++) {
478
+ const proc = agent.inputProcessors[p];
479
+ const ident = sanitizeIdentifier(`${agent.name}_inputProc_${proc.key}`, "proc", `${idPath}_ip${p}`);
480
+ lines.push(`import ${ident} from ${JSON.stringify(proc.path)};`);
481
+ inputProcessorIdents.push(ident);
482
+ }
483
+ const outputProcessorIdents = [];
484
+ for (let p = 0; p < agent.outputProcessors.length; p++) {
485
+ const proc = agent.outputProcessors[p];
486
+ const ident = sanitizeIdentifier(`${agent.name}_outputProc_${proc.key}`, "proc", `${idPath}_op${p}`);
487
+ lines.push(`import ${ident} from ${JSON.stringify(proc.path)};`);
488
+ outputProcessorIdents.push(ident);
489
+ }
490
+ const scorerIdents = [];
491
+ for (let s = 0; s < agent.scorers.length; s++) {
492
+ const scorer = agent.scorers[s];
493
+ const ident = sanitizeIdentifier(`${agent.name}_scorer_${scorer.key}`, "scorer", `${idPath}_${s}`);
494
+ lines.push(`import ${ident} from ${JSON.stringify(scorer.path)};`);
495
+ scorerIdents.push({
496
+ key: scorer.key,
497
+ ident
498
+ });
499
+ }
500
+ const skillExprs = [];
501
+ const agentSkills = agent.skills ?? [];
502
+ for (let s = 0; s < agentSkills.length; s++) {
503
+ const skill = agentSkills[s];
504
+ if (skill.kind === "module") {
505
+ const ident = sanitizeIdentifier(`${agent.name}_skill`, "skill", `${idPath}_${s}`);
506
+ lines.push(`import ${ident} from ${JSON.stringify(skill.path)};`);
507
+ skillExprs.push(ident);
508
+ } else {
509
+ const referenceFields = Object.entries(skill.references).map(([key, value]) => `${JSON.stringify(key)}: ${JSON.stringify(value)}`);
510
+ const skillFields = [
511
+ `name: ${JSON.stringify(skill.name)}`,
512
+ `description: ${JSON.stringify(skill.description)}`,
513
+ `instructions: ${JSON.stringify(skill.instructions)}`
514
+ ];
515
+ if (referenceFields.length > 0) skillFields.push(`references: { ${referenceFields.join(", ")} }`);
516
+ skillExprs.push(`__createSkill({ ${skillFields.join(", ")} })`);
517
+ }
518
+ }
519
+ let instructionsMd;
520
+ if (agent.instructionsPath) instructionsMd = await readFile(agent.instructionsPath, "utf-8");
521
+ const subagentExprs = [];
522
+ for (let c = 0; c < agent.subagents.length; c++) {
523
+ const child = agent.subagents[c];
524
+ const childExpr = await emitAgentEntry(child, `${idPath}_${c}`, `${workspaceName}/${child.name}`, lines);
525
+ subagentExprs.push(childExpr);
526
+ }
527
+ const entryFields = [`name: ${JSON.stringify(agent.name)}`];
528
+ if (agent.configPath) entryFields.push(`config: ${configIdent}`);
529
+ if (instructionsMd !== void 0) entryFields.push(`instructionsMd: ${JSON.stringify(instructionsMd)}`);
530
+ if (toolIdents.length > 0) {
531
+ const toolEntries = toolIdents.map(({ key, ident }) => `{ key: ${JSON.stringify(key)}, tool: ${ident} }`);
532
+ entryFields.push(`tools: [${toolEntries.join(", ")}]`);
533
+ }
534
+ if (skillExprs.length > 0) entryFields.push(`skills: [${skillExprs.join(", ")}]`);
535
+ if (inputProcessorIdents.length > 0) entryFields.push(`inputProcessors: [${inputProcessorIdents.join(", ")}]`);
536
+ if (outputProcessorIdents.length > 0) entryFields.push(`outputProcessors: [${outputProcessorIdents.join(", ")}]`);
537
+ if (scorerIdents.length > 0) {
538
+ const scorerEntries = scorerIdents.map(({ key, ident }) => `{ key: ${JSON.stringify(key)}, scorer: ${ident} }`);
539
+ entryFields.push(`scorers: [${scorerEntries.join(", ")}]`);
540
+ }
541
+ if (subagentExprs.length > 0) entryFields.push(`subagents: [${subagentExprs.join(", ")}]`);
542
+ if (workspaceIdent) entryFields.push(`workspace: ${workspaceIdent}`);
543
+ if (memoryIdent) entryFields.push(`memory: ${memoryIdent}`);
544
+ entryFields.push(`defaultWorkspaceBasePath: __workspaceBasePath(${JSON.stringify(workspaceName)})`);
545
+ return `{ ${entryFields.join(", ")} }`;
546
+ }
547
+ /**
548
+ * Generate the source of a wrapper module that:
549
+ * 1. imports the user's real Mastra entry,
550
+ * 2. imports each discovered `config.ts`, `tools/*.ts`, `skills/*.ts`
551
+ * (`createSkill(...)` modules), `workspace.ts`, and `memory.ts`, inlining
552
+ * packaged `SKILL.md` skills,
553
+ * 3. assembles `Agent` instances via `assembleAgentFromFsEntry`, wiring any
554
+ * declared `subagents/` into the parent (nested up to `MAX_FS_SUBAGENT_DEPTH`),
555
+ * 4. registers them onto the user's `mastra` instance (code-registered agents
556
+ * win on name collisions), and
557
+ * 5. re-exports everything from the user's entry so this module is a drop-in
558
+ * replacement for the original `#mastra` target.
559
+ *
560
+ * `instructions.md` is read into the generated wrapper. In dev, the CLI watcher
561
+ * regenerates that wrapper when the markdown file changes.
562
+ *
563
+ * @param userEntry slash-normalized absolute path to the user's mastra entry.
564
+ * @param agents discovered fs-routed agents (absolute, slash-normalized paths).
565
+ */
566
+ async function generateFsAgentsModule(userEntry, agents, options) {
567
+ const workflows = options?.workflows ?? [];
568
+ const storage = options?.storage;
569
+ const observability = options?.observability;
570
+ const logger = options?.logger;
571
+ const server = options?.server;
572
+ const studio = options?.studio;
573
+ const standalone = userEntry === void 0;
574
+ const lines = [];
575
+ const hasInlineSkills = (function check(list) {
576
+ return list.some((a) => (a.skills ?? []).some((s) => s.kind === "packaged") || check(a.subagents ?? []));
577
+ })(agents);
578
+ lines.push(`import { assembleAgentFromFsEntry } from '@mastra/core/agent';`);
579
+ if (hasInlineSkills) lines.push(`import { createSkill as __createSkill } from '@mastra/core/skills';`);
580
+ if (standalone) lines.push(`import { Mastra } from '@mastra/core';`);
581
+ lines.push(`import { fileURLToPath as __fileURLToPath } from 'node:url';`);
582
+ lines.push(`import { dirname as __dirname, join as __join } from 'node:path';`);
583
+ if (userEntry) {
584
+ lines.push(`import * as __userEntry from ${JSON.stringify(userEntry)};`);
585
+ lines.push(`export * from ${JSON.stringify(userEntry)};`);
586
+ }
587
+ lines.push(``);
588
+ lines.push(`const __bundleDir = __dirname(__fileURLToPath(import.meta.url));`);
589
+ lines.push(`const __workspaceBasePath = name => __join(__bundleDir, 'workspace', ...name.split('/'));`);
590
+ lines.push(``);
591
+ const singletonImports = [];
592
+ if (storage) singletonImports.push(`import __fsStorage from ${JSON.stringify(storage.path)};`);
593
+ if (observability) singletonImports.push(`import __fsObservability from ${JSON.stringify(observability.path)};`);
594
+ if (logger) singletonImports.push(`import __fsLogger from ${JSON.stringify(logger.path)};`);
595
+ if (server) singletonImports.push(`import __fsServer from ${JSON.stringify(server.path)};`);
596
+ if (studio) singletonImports.push(`import __fsStudio from ${JSON.stringify(studio.path)};`);
597
+ if (singletonImports.length > 0) {
598
+ lines.push(...singletonImports);
599
+ lines.push(``);
600
+ }
601
+ const wfCodegen = workflows.length > 0 ? generateFsWorkflowsCodegen(workflows) : void 0;
602
+ if (wfCodegen) {
603
+ for (const line of wfCodegen.importLines) lines.push(line);
604
+ lines.push(``);
605
+ }
606
+ const entryExprs = [];
607
+ for (let i = 0; i < agents.length; i++) {
608
+ const agent = agents[i];
609
+ const expr = await emitAgentEntry(agent, `${i}`, agent.name, lines);
610
+ entryExprs.push(expr);
611
+ }
612
+ if (standalone) {
613
+ lines.push(``);
614
+ lines.push(`const __mastra = new Mastra({});`);
615
+ } else {
616
+ lines.push(``);
617
+ lines.push(`const __mastra = __userEntry.mastra;`);
618
+ }
619
+ lines.push(``);
620
+ lines.push(`const __fsAgentEntries = [`);
621
+ for (const expr of entryExprs) lines.push(` ${expr},`);
622
+ lines.push(`];`);
623
+ lines.push(``);
624
+ lines.push(`const __fsAgents = Object.create(null);`);
625
+ lines.push(`for (const __entry of __fsAgentEntries) {`);
626
+ lines.push(` __fsAgents[__entry.name] = assembleAgentFromFsEntry(__entry, {`);
627
+ lines.push(` onWarn: msg => __mastra?.getLogger?.()?.warn?.(msg) ?? console.warn(msg),`);
628
+ lines.push(` });`);
629
+ lines.push(`}`);
630
+ lines.push(``);
631
+ if (logger) {
632
+ lines.push(`if (__mastra && typeof __mastra.__registerFsLogger === 'function') {`);
633
+ lines.push(` __mastra.__registerFsLogger(__fsLogger);`);
634
+ lines.push(`}`);
635
+ lines.push(``);
636
+ }
637
+ if (storage) {
638
+ lines.push(`if (__mastra && typeof __mastra.__registerFsStorage === 'function') {`);
639
+ lines.push(` __mastra.__registerFsStorage(__fsStorage);`);
640
+ lines.push(`}`);
641
+ lines.push(``);
642
+ }
643
+ if (observability) {
644
+ lines.push(`if (__mastra && typeof __mastra.__registerFsObservability === 'function') {`);
645
+ lines.push(` __mastra.__registerFsObservability(__fsObservability);`);
646
+ lines.push(`}`);
647
+ lines.push(``);
648
+ }
649
+ if (server) {
650
+ lines.push(`if (__mastra && typeof __mastra.__registerFsServer === 'function') {`);
651
+ lines.push(` __mastra.__registerFsServer(__fsServer);`);
652
+ lines.push(`}`);
653
+ lines.push(``);
654
+ }
655
+ if (studio) {
656
+ lines.push(`if (__mastra && typeof __mastra.__registerFsStudio === 'function') {`);
657
+ lines.push(` __mastra.__registerFsStudio(__fsStudio);`);
658
+ lines.push(`}`);
659
+ lines.push(``);
660
+ }
661
+ lines.push(`if (__mastra && typeof __mastra.__registerFsAgents === 'function') {`);
662
+ lines.push(` __mastra.__registerFsAgents(__fsAgents);`);
663
+ lines.push(`}`);
664
+ if (wfCodegen) {
665
+ lines.push(``);
666
+ for (const line of wfCodegen.registrationLines) lines.push(line);
667
+ }
668
+ lines.push(``);
669
+ lines.push(`export const mastra = __mastra;`);
670
+ return lines.join("\n");
671
+ }
672
+ /**
673
+ * Generate the workflow-registration lines to splice into the generated wrapper
674
+ * module. Emits import statements for each discovered workflow module and a
675
+ * registration block that calls `__registerFsWorkflows` on the user's mastra.
676
+ *
677
+ * Returns `{ importLines, registrationLines }` so the caller can place them at
678
+ * the correct positions in the wrapper source.
679
+ */
680
+ function generateFsWorkflowsCodegen(workflows) {
681
+ const importLines = [];
682
+ const registrationLines = [];
683
+ for (let i = 0; i < workflows.length; i++) {
684
+ const wf = workflows[i];
685
+ const ident = sanitizeIdentifier(wf.key, "workflow", `${i}`);
686
+ importLines.push(`import ${ident} from ${JSON.stringify(wf.path)};`);
687
+ }
688
+ registrationLines.push(`const __fsWorkflows = Object.create(null);`);
689
+ for (let i = 0; i < workflows.length; i++) {
690
+ const wf = workflows[i];
691
+ const ident = sanitizeIdentifier(wf.key, "workflow", `${i}`);
692
+ registrationLines.push(`__fsWorkflows[${JSON.stringify(wf.key)}] = ${ident};`);
693
+ }
694
+ registrationLines.push(``);
695
+ registrationLines.push(`if (__mastra && typeof __mastra.__registerFsWorkflows === 'function') {`);
696
+ registrationLines.push(` __mastra.__registerFsWorkflows(__fsWorkflows);`);
697
+ registrationLines.push(`}`);
698
+ return {
699
+ importLines,
700
+ registrationLines
701
+ };
702
+ }
703
+ //#endregion
704
+ //#region src/build/fs-routing/prepare.ts
705
+ /**
706
+ * Discover fs-routed agents under `<mastraDir>/agents/*`, workflows under
707
+ * `<mastraDir>/workflows/`, and singleton config files (e.g. `storage.ts`,
708
+ * `observability.ts`, `logger.ts`, `server.ts`, `studio.ts`).
709
+ * When any are found, generate a wrapper entry module that registers them onto
710
+ * the user's mastra instance. Returns the entry the bundler should use plus
711
+ * extra tool glob paths so `agents/*\/tools` are bundled.
712
+ *
713
+ * This does NOT write the wrapper to disk; call {@link writeFsAgentsEntry} with
714
+ * the result after `bundler.prepare()` so the generated file is not wiped when
715
+ * the output directory is emptied.
716
+ *
717
+ * When `entryFile` is `undefined` (no `index.ts`/`index.js`) and fs-routed
718
+ * primitives are found, a standalone Mastra instance is auto-constructed from
719
+ * them — no user code required.
720
+ *
721
+ * When no fs-routed primitives are present the original entry is returned
722
+ * unchanged, so existing code-only projects are completely unaffected.
723
+ */
724
+ async function prepareFsAgentsEntry(mastraDir, entryFile, outputDirectory) {
725
+ const [agents, workflows, storage, observability, logger, server, studio] = await Promise.all([
726
+ discoverFsAgents(mastraDir),
727
+ discoverFsWorkflows(mastraDir),
728
+ discoverFsSingleton(mastraDir, "storage"),
729
+ discoverFsSingleton(mastraDir, "observability"),
730
+ discoverFsSingleton(mastraDir, "logger"),
731
+ discoverFsSingleton(mastraDir, "server"),
732
+ discoverFsSingleton(mastraDir, "studio")
733
+ ]);
734
+ const standalone = entryFile === void 0;
735
+ const hasFsPrimitives = agents.length > 0 || workflows.length > 0 || !!storage || !!observability || !!logger || !!server || !!studio;
736
+ if (!hasFsPrimitives && entryFile !== void 0) return {
737
+ entryFile,
738
+ standalone: false,
739
+ toolPaths: [],
740
+ agentCount: 0,
741
+ workflowCount: 0,
742
+ hasStorage: false,
743
+ hasObservability: false,
744
+ hasLogger: false,
745
+ hasServer: false,
746
+ hasStudio: false
747
+ };
748
+ if (!hasFsPrimitives && standalone) throw new Error("No index.ts and no file-based primitives found. Create src/mastra/index.ts with a Mastra instance, or add file-based agents/workflows/storage.");
749
+ const moduleSource = await generateFsAgentsModule(entryFile ? slash(entryFile) : void 0, agents, {
750
+ workflows,
751
+ storage,
752
+ observability,
753
+ logger,
754
+ server,
755
+ studio
756
+ });
757
+ const generatedEntry = join(outputDirectory, ".mastra-fs-agents-entry.mjs");
758
+ const normalizedMastraDir = slash(mastraDir);
759
+ return {
760
+ entryFile: generatedEntry,
761
+ standalone,
762
+ toolPaths: agents.length > 0 ? [
763
+ posix.join(normalizedMastraDir, "agents/*/tools/**/*.{js,ts}"),
764
+ `!${posix.join(normalizedMastraDir, "agents/*/tools/**/*.{test,spec}.{js,ts}")}`,
765
+ `!${posix.join(normalizedMastraDir, "agents/*/tools/**/__tests__/**")}`
766
+ ] : [],
767
+ agentCount: agents.length,
768
+ workflowCount: workflows.length,
769
+ hasStorage: !!storage,
770
+ hasObservability: !!observability,
771
+ hasLogger: !!logger,
772
+ hasServer: !!server,
773
+ hasStudio: !!studio,
774
+ moduleSource
775
+ };
776
+ }
777
+ /**
778
+ * Write the generated fs-agents wrapper produced by {@link prepareFsAgentsEntry}
779
+ * to its `entryFile`. No-op when there are no fs-routed agents. Call this AFTER
780
+ * `bundler.prepare()` (which empties the output directory) so the wrapper
781
+ * survives for the bundler/watcher to read.
782
+ */
783
+ async function writeFsAgentsEntry(result) {
784
+ if (!result.moduleSource) return;
785
+ await mkdir(dirname(result.entryFile), { recursive: true });
786
+ await writeFile(result.entryFile, result.moduleSource, "utf-8");
787
+ }
788
+ //#endregion
789
+ //#region src/build/fs-routing/mirror.ts
790
+ /**
791
+ * Skip symlinks when copying workspace seeds. A symlink under
792
+ * `agents/<name>/workspace/` could point outside the workspace and be preserved
793
+ * in the bundle, letting the agent read arbitrary files at runtime. We copy only
794
+ * regular files and directories.
795
+ */
796
+ async function rejectSymlinks(source) {
797
+ return !(await lstat(source)).isSymbolicLink();
798
+ }
799
+ async function mirrorAgentSeeds(agent, workspaceName, bundleDir, mirrored) {
800
+ if (agent.workspaceSeedDir) {
801
+ const destination = join(bundleDir, "workspace", ...workspaceName.split("/"));
802
+ await mkdir(destination, { recursive: true });
803
+ await cp(agent.workspaceSeedDir, destination, {
804
+ recursive: true,
805
+ filter: rejectSymlinks
806
+ });
807
+ mirrored.push(workspaceName);
808
+ }
809
+ for (const child of agent.subagents ?? []) await mirrorAgentSeeds(child, `${workspaceName}/${child.name}`, bundleDir, mirrored);
810
+ }
811
+ /**
812
+ * Mirror authored `agents/<name>/workspace/**` seed files into the bundled
813
+ * output so each fs-routed agent starts with them on disk (Eve parity). Files
814
+ * are copied to `<bundleDir>/workspace/<name>`, which is exactly where the
815
+ * generated entry roots each agent's default workspace at runtime (resolved
816
+ * relative to the bundled module via `import.meta.url`). Declared subagents
817
+ * mirror to the nested `<bundleDir>/workspace/<parent>/<child>` path.
818
+ *
819
+ * Must run AFTER the bundle step, since bundling recreates the output dir.
820
+ *
821
+ * @param mastraDir The user's `src/mastra` directory (source of seeds).
822
+ * @param bundleDir The final bundle directory (e.g. `<outputDirectory>/output`).
823
+ * @returns the workspace names whose seeds were mirrored (`<parent>/<child>` for subagents).
824
+ */
825
+ async function mirrorFsAgentWorkspaces(mastraDir, bundleDir) {
826
+ const agents = await discoverFsAgents(mastraDir);
827
+ const mirrored = [];
828
+ for (const agent of agents) await mirrorAgentSeeds(agent, agent.name, bundleDir, mirrored);
829
+ return mirrored;
830
+ }
831
+ //#endregion
832
+ export { generateFsWorkflowsCodegen as a, discoverFsWorkflows as c, createWatcher as d, getInputOptions as f, generateFsAgentsModule as i, getServerOptions as l, prepareFsAgentsEntry as n, discoverFsAgents as o, writeFsAgentsEntry as r, discoverFsSingleton as s, mirrorFsAgentWorkspaces as t, analyzeEntryProjectType as u };
833
+
834
+ //# sourceMappingURL=build-KCOeHd4N.js.map