mastra 0.10.12 → 0.10.13-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/analytics/index.d.ts +4 -1
- package/dist/analytics/index.js +1 -1
- package/dist/{chunk-SLWIYYJN.js → chunk-C56DSM55.js} +364 -136
- package/dist/{chunk-7OXWUU2Q.js → chunk-US7IPLZ2.js} +24 -1
- package/dist/commands/create/create.d.ts +1 -0
- package/dist/commands/create/create.js +2 -1
- package/dist/index.js +13 -7
- package/package.json +9 -9
- package/src/playground/dist/assets/{index-DnOJ6cef.js → index-B_Qdb7Wa.js} +1 -1
- package/src/playground/dist/assets/{index-D23GwWJx.js → index-CQUZzE3V.js} +264 -274
- package/src/playground/dist/assets/{index-BfLjjKvL.js → index-Q_5l7c_H.js} +1 -1
- package/src/playground/dist/assets/style-DclaXp-L.css +1 -0
- package/src/playground/dist/index.html +2 -2
- package/src/playground/dist/assets/style-6HJW2DLD.css +0 -1
|
@@ -1,21 +1,213 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { getAnalytics } from './chunk-US7IPLZ2.js';
|
|
2
|
+
import * as p2 from '@clack/prompts';
|
|
2
3
|
import color2 from 'picocolors';
|
|
4
|
+
import fs from 'fs/promises';
|
|
3
5
|
import child_process from 'child_process';
|
|
4
6
|
import util from 'util';
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
7
|
+
import path3, { dirname } from 'path';
|
|
8
|
+
import shellQuote from 'shell-quote';
|
|
9
|
+
import yoctoSpinner from 'yocto-spinner';
|
|
10
|
+
import { PinoLogger } from '@mastra/loggers';
|
|
11
|
+
import * as fs4 from 'fs';
|
|
12
|
+
import fs4__default, { existsSync } from 'fs';
|
|
9
13
|
import { fileURLToPath } from 'url';
|
|
10
14
|
import { execa } from 'execa';
|
|
11
15
|
import fsExtra3, { readJSON, ensureFile, writeJSON } from 'fs-extra/esm';
|
|
12
16
|
import os from 'os';
|
|
13
17
|
import prettier from 'prettier';
|
|
14
|
-
import shellQuote from 'shell-quote';
|
|
15
|
-
import yoctoSpinner from 'yocto-spinner';
|
|
16
|
-
import { PinoLogger } from '@mastra/loggers';
|
|
17
18
|
|
|
18
|
-
// src/commands/
|
|
19
|
+
// src/commands/utils.ts
|
|
20
|
+
function getPackageManager() {
|
|
21
|
+
const userAgent = process.env.npm_config_user_agent || "";
|
|
22
|
+
const execPath = process.env.npm_execpath || "";
|
|
23
|
+
if (userAgent.includes("yarn")) {
|
|
24
|
+
return "yarn";
|
|
25
|
+
}
|
|
26
|
+
if (userAgent.includes("pnpm")) {
|
|
27
|
+
return "pnpm";
|
|
28
|
+
}
|
|
29
|
+
if (userAgent.includes("npm")) {
|
|
30
|
+
return "npm";
|
|
31
|
+
}
|
|
32
|
+
if (execPath.includes("yarn")) {
|
|
33
|
+
return "yarn";
|
|
34
|
+
}
|
|
35
|
+
if (execPath.includes("pnpm")) {
|
|
36
|
+
return "pnpm";
|
|
37
|
+
}
|
|
38
|
+
if (execPath.includes("npm")) {
|
|
39
|
+
return "npm";
|
|
40
|
+
}
|
|
41
|
+
return "npm";
|
|
42
|
+
}
|
|
43
|
+
function getPackageManagerInstallCommand(pm) {
|
|
44
|
+
switch (pm) {
|
|
45
|
+
case "npm":
|
|
46
|
+
return "install";
|
|
47
|
+
case "yarn":
|
|
48
|
+
return "add";
|
|
49
|
+
case "pnpm":
|
|
50
|
+
return "add";
|
|
51
|
+
default:
|
|
52
|
+
return "install";
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
var logger = new PinoLogger({
|
|
56
|
+
name: "Mastra CLI",
|
|
57
|
+
level: "info"
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// src/utils/clone-template.ts
|
|
61
|
+
var exec = util.promisify(child_process.exec);
|
|
62
|
+
async function cloneTemplate(options) {
|
|
63
|
+
const { template, projectName, targetDir } = options;
|
|
64
|
+
const projectPath = targetDir ? path3.resolve(targetDir, projectName) : path3.resolve(projectName);
|
|
65
|
+
const spinner4 = yoctoSpinner({ text: `Cloning template "${template.title}"...` }).start();
|
|
66
|
+
try {
|
|
67
|
+
if (await directoryExists(projectPath)) {
|
|
68
|
+
spinner4.error(`Directory ${projectName} already exists`);
|
|
69
|
+
throw new Error(`Directory ${projectName} already exists`);
|
|
70
|
+
}
|
|
71
|
+
await cloneRepositoryWithoutGit(template.githubUrl, projectPath);
|
|
72
|
+
await updatePackageJson(projectPath, projectName);
|
|
73
|
+
const envExamplePath = path3.join(projectPath, ".env.example");
|
|
74
|
+
if (await fileExists(envExamplePath)) {
|
|
75
|
+
await fs.copyFile(envExamplePath, path3.join(projectPath, ".env"));
|
|
76
|
+
}
|
|
77
|
+
spinner4.success(`Template "${template.title}" cloned successfully to ${projectName}`);
|
|
78
|
+
return projectPath;
|
|
79
|
+
} catch (error) {
|
|
80
|
+
spinner4.error(`Failed to clone template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async function directoryExists(dirPath) {
|
|
85
|
+
try {
|
|
86
|
+
const stat = await fs.stat(dirPath);
|
|
87
|
+
return stat.isDirectory();
|
|
88
|
+
} catch {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async function fileExists(filePath) {
|
|
93
|
+
try {
|
|
94
|
+
const stat = await fs.stat(filePath);
|
|
95
|
+
return stat.isFile();
|
|
96
|
+
} catch {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async function cloneRepositoryWithoutGit(repoUrl, targetPath) {
|
|
101
|
+
await fs.mkdir(targetPath, { recursive: true });
|
|
102
|
+
try {
|
|
103
|
+
const degitRepo = repoUrl.replace("https://github.com/", "");
|
|
104
|
+
const degitCommand = shellQuote.quote(["npx", "degit", degitRepo, targetPath]);
|
|
105
|
+
await exec(degitCommand, {
|
|
106
|
+
cwd: process.cwd()
|
|
107
|
+
});
|
|
108
|
+
} catch {
|
|
109
|
+
try {
|
|
110
|
+
const gitCommand = shellQuote.quote(["git", "clone", repoUrl, targetPath]);
|
|
111
|
+
await exec(gitCommand, {
|
|
112
|
+
cwd: process.cwd()
|
|
113
|
+
});
|
|
114
|
+
const gitDir = path3.join(targetPath, ".git");
|
|
115
|
+
if (await directoryExists(gitDir)) {
|
|
116
|
+
await fs.rm(gitDir, { recursive: true, force: true });
|
|
117
|
+
}
|
|
118
|
+
} catch (gitError) {
|
|
119
|
+
throw new Error(`Failed to clone repository: ${gitError instanceof Error ? gitError.message : "Unknown error"}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async function updatePackageJson(projectPath, projectName) {
|
|
124
|
+
const packageJsonPath = path3.join(projectPath, "package.json");
|
|
125
|
+
try {
|
|
126
|
+
const packageJsonContent = await fs.readFile(packageJsonPath, "utf-8");
|
|
127
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
128
|
+
packageJson.name = projectName;
|
|
129
|
+
await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf-8");
|
|
130
|
+
} catch (error) {
|
|
131
|
+
logger.warn(`Could not update package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async function installDependencies(projectPath, packageManager) {
|
|
135
|
+
const spinner4 = yoctoSpinner({ text: "Installing dependencies..." }).start();
|
|
136
|
+
try {
|
|
137
|
+
const pm = packageManager || getPackageManager();
|
|
138
|
+
const installCommand = shellQuote.quote([pm, "install"]);
|
|
139
|
+
await exec(installCommand, {
|
|
140
|
+
cwd: projectPath
|
|
141
|
+
});
|
|
142
|
+
spinner4.success("Dependencies installed successfully");
|
|
143
|
+
} catch (error) {
|
|
144
|
+
spinner4.error(`Failed to install dependencies: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
var TEMPLATES_API_URL = process.env.MASTRA_TEMPLATES_API_URL || "https://mastra.ai/api/templates.json";
|
|
149
|
+
async function loadTemplates() {
|
|
150
|
+
try {
|
|
151
|
+
const response = await fetch(TEMPLATES_API_URL);
|
|
152
|
+
if (!response.ok) {
|
|
153
|
+
throw new Error(`Failed to fetch templates: ${response.statusText}`);
|
|
154
|
+
}
|
|
155
|
+
const templates = await response.json();
|
|
156
|
+
return templates;
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.error("Error loading templates:", error);
|
|
159
|
+
throw new Error("Failed to load templates. Please check your internet connection and try again.");
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function pluralize(count, singular, plural) {
|
|
163
|
+
return count === 1 ? singular : plural || `${singular}s`;
|
|
164
|
+
}
|
|
165
|
+
async function selectTemplate(templates) {
|
|
166
|
+
const choices = templates.map((template) => {
|
|
167
|
+
const parts = [];
|
|
168
|
+
if (template.agents?.length) {
|
|
169
|
+
parts.push(`${template.agents.length} ${pluralize(template.agents.length, "agent")}`);
|
|
170
|
+
}
|
|
171
|
+
if (template.tools?.length) {
|
|
172
|
+
parts.push(`${template.tools.length} ${pluralize(template.tools.length, "tool")}`);
|
|
173
|
+
}
|
|
174
|
+
if (template.workflows?.length) {
|
|
175
|
+
parts.push(`${template.workflows.length} ${pluralize(template.workflows.length, "workflow")}`);
|
|
176
|
+
}
|
|
177
|
+
if (template.mcp?.length) {
|
|
178
|
+
parts.push(`${template.mcp.length} ${pluralize(template.mcp.length, "MCP server")}`);
|
|
179
|
+
}
|
|
180
|
+
if (template.networks?.length) {
|
|
181
|
+
parts.push(`${template.networks.length} ${pluralize(template.networks.length, "agent network")}`);
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
value: template,
|
|
185
|
+
label: template.title,
|
|
186
|
+
hint: parts.join(", ") || "Template components"
|
|
187
|
+
};
|
|
188
|
+
});
|
|
189
|
+
const selected = await p2.select({
|
|
190
|
+
message: "Select a template:",
|
|
191
|
+
options: choices
|
|
192
|
+
});
|
|
193
|
+
if (p2.isCancel(selected)) {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
return selected;
|
|
197
|
+
}
|
|
198
|
+
function findTemplateByName(templates, templateName) {
|
|
199
|
+
let template = templates.find((t) => t.slug === templateName);
|
|
200
|
+
if (template) return template;
|
|
201
|
+
const slugWithPrefix = `template-${templateName}`;
|
|
202
|
+
template = templates.find((t) => t.slug === slugWithPrefix);
|
|
203
|
+
if (template) return template;
|
|
204
|
+
template = templates.find((t) => t.title.toLowerCase() === templateName.toLowerCase());
|
|
205
|
+
if (template) return template;
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
function getDefaultProjectName(template) {
|
|
209
|
+
return template.slug.replace(/^template-/, "");
|
|
210
|
+
}
|
|
19
211
|
var DepsService = class {
|
|
20
212
|
packageManager;
|
|
21
213
|
constructor() {
|
|
@@ -24,11 +216,11 @@ var DepsService = class {
|
|
|
24
216
|
findLockFile(dir) {
|
|
25
217
|
const lockFiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lock"];
|
|
26
218
|
for (const file of lockFiles) {
|
|
27
|
-
if (
|
|
219
|
+
if (fs4__default.existsSync(path3.join(dir, file))) {
|
|
28
220
|
return file;
|
|
29
221
|
}
|
|
30
222
|
}
|
|
31
|
-
const parentDir =
|
|
223
|
+
const parentDir = path3.resolve(dir, "..");
|
|
32
224
|
if (parentDir !== dir) {
|
|
33
225
|
return this.findLockFile(parentDir);
|
|
34
226
|
}
|
|
@@ -65,13 +257,13 @@ var DepsService = class {
|
|
|
65
257
|
}
|
|
66
258
|
async checkDependencies(dependencies) {
|
|
67
259
|
try {
|
|
68
|
-
const packageJsonPath =
|
|
260
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
69
261
|
try {
|
|
70
|
-
await
|
|
262
|
+
await fs.access(packageJsonPath);
|
|
71
263
|
} catch {
|
|
72
264
|
return "No package.json file found in the current directory";
|
|
73
265
|
}
|
|
74
|
-
const packageJson = JSON.parse(await
|
|
266
|
+
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf-8"));
|
|
75
267
|
for (const dependency of dependencies) {
|
|
76
268
|
if (!packageJson.dependencies || !packageJson.dependencies[dependency]) {
|
|
77
269
|
return `Please install ${dependency} before running this command (${this.packageManager} install ${dependency})`;
|
|
@@ -85,8 +277,8 @@ var DepsService = class {
|
|
|
85
277
|
}
|
|
86
278
|
async getProjectName() {
|
|
87
279
|
try {
|
|
88
|
-
const packageJsonPath =
|
|
89
|
-
const packageJson = await
|
|
280
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
281
|
+
const packageJson = await fs.readFile(packageJsonPath, "utf-8");
|
|
90
282
|
const pkg = JSON.parse(packageJson);
|
|
91
283
|
return pkg.name;
|
|
92
284
|
} catch (err) {
|
|
@@ -96,56 +288,19 @@ var DepsService = class {
|
|
|
96
288
|
async getPackageVersion() {
|
|
97
289
|
const __filename = fileURLToPath(import.meta.url);
|
|
98
290
|
const __dirname = dirname(__filename);
|
|
99
|
-
const pkgJsonPath =
|
|
291
|
+
const pkgJsonPath = path3.join(__dirname, "..", "package.json");
|
|
100
292
|
const content = await fsExtra3.readJSON(pkgJsonPath);
|
|
101
293
|
return content.version;
|
|
102
294
|
}
|
|
103
295
|
async addScriptsToPackageJson(scripts) {
|
|
104
|
-
const packageJson = JSON.parse(await
|
|
296
|
+
const packageJson = JSON.parse(await fs.readFile("package.json", "utf-8"));
|
|
105
297
|
packageJson.scripts = {
|
|
106
298
|
...packageJson.scripts,
|
|
107
299
|
...scripts
|
|
108
300
|
};
|
|
109
|
-
await
|
|
301
|
+
await fs.writeFile("package.json", JSON.stringify(packageJson, null, 2));
|
|
110
302
|
}
|
|
111
303
|
};
|
|
112
|
-
|
|
113
|
-
// src/commands/utils.ts
|
|
114
|
-
function getPackageManager() {
|
|
115
|
-
const userAgent = process.env.npm_config_user_agent || "";
|
|
116
|
-
const execPath = process.env.npm_execpath || "";
|
|
117
|
-
if (userAgent.includes("yarn")) {
|
|
118
|
-
return "yarn";
|
|
119
|
-
}
|
|
120
|
-
if (userAgent.includes("pnpm")) {
|
|
121
|
-
return "pnpm";
|
|
122
|
-
}
|
|
123
|
-
if (userAgent.includes("npm")) {
|
|
124
|
-
return "npm";
|
|
125
|
-
}
|
|
126
|
-
if (execPath.includes("yarn")) {
|
|
127
|
-
return "yarn";
|
|
128
|
-
}
|
|
129
|
-
if (execPath.includes("pnpm")) {
|
|
130
|
-
return "pnpm";
|
|
131
|
-
}
|
|
132
|
-
if (execPath.includes("npm")) {
|
|
133
|
-
return "npm";
|
|
134
|
-
}
|
|
135
|
-
return "npm";
|
|
136
|
-
}
|
|
137
|
-
function getPackageManagerInstallCommand(pm) {
|
|
138
|
-
switch (pm) {
|
|
139
|
-
case "npm":
|
|
140
|
-
return "install";
|
|
141
|
-
case "yarn":
|
|
142
|
-
return "add";
|
|
143
|
-
case "pnpm":
|
|
144
|
-
return "add";
|
|
145
|
-
default:
|
|
146
|
-
return "install";
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
304
|
var args = ["-y", "@mastra/mcp-docs-server"];
|
|
150
305
|
var createMcpConfig = (editor) => {
|
|
151
306
|
if (editor === "vscode") {
|
|
@@ -198,19 +353,19 @@ async function writeMergedConfig(configPath, editor) {
|
|
|
198
353
|
spaces: 2
|
|
199
354
|
});
|
|
200
355
|
}
|
|
201
|
-
var windsurfGlobalMCPConfigPath =
|
|
202
|
-
var cursorGlobalMCPConfigPath =
|
|
203
|
-
|
|
204
|
-
var vscodeGlobalMCPConfigPath =
|
|
356
|
+
var windsurfGlobalMCPConfigPath = path3.join(os.homedir(), ".codeium", "windsurf", "mcp_config.json");
|
|
357
|
+
var cursorGlobalMCPConfigPath = path3.join(os.homedir(), ".cursor", "mcp.json");
|
|
358
|
+
path3.join(process.cwd(), ".vscode", "mcp.json");
|
|
359
|
+
var vscodeGlobalMCPConfigPath = path3.join(
|
|
205
360
|
os.homedir(),
|
|
206
|
-
process.platform === "win32" ?
|
|
361
|
+
process.platform === "win32" ? path3.join("AppData", "Roaming", "Code", "User", "settings.json") : process.platform === "darwin" ? path3.join("Library", "Application Support", "Code", "User", "settings.json") : path3.join(".config", "Code", "User", "settings.json")
|
|
207
362
|
);
|
|
208
363
|
async function installMastraDocsMCPServer({ editor, directory }) {
|
|
209
364
|
if (editor === `cursor`) {
|
|
210
|
-
await writeMergedConfig(
|
|
365
|
+
await writeMergedConfig(path3.join(directory, ".cursor", "mcp.json"), "cursor");
|
|
211
366
|
}
|
|
212
367
|
if (editor === `vscode`) {
|
|
213
|
-
await writeMergedConfig(
|
|
368
|
+
await writeMergedConfig(path3.join(directory, ".vscode", "mcp.json"), "vscode");
|
|
214
369
|
}
|
|
215
370
|
if (editor === `cursor-global`) {
|
|
216
371
|
const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor);
|
|
@@ -272,7 +427,7 @@ var FileEnvService = class extends EnvService {
|
|
|
272
427
|
}
|
|
273
428
|
readFile(filePath) {
|
|
274
429
|
return new Promise((resolve, reject) => {
|
|
275
|
-
|
|
430
|
+
fs4.readFile(filePath, "utf8", (err, data) => {
|
|
276
431
|
if (err) reject(err);
|
|
277
432
|
else resolve(data);
|
|
278
433
|
});
|
|
@@ -280,7 +435,7 @@ var FileEnvService = class extends EnvService {
|
|
|
280
435
|
}
|
|
281
436
|
writeFile({ filePath, data }) {
|
|
282
437
|
return new Promise((resolve, reject) => {
|
|
283
|
-
|
|
438
|
+
fs4.writeFile(filePath, data, "utf8", (err) => {
|
|
284
439
|
if (err) reject(err);
|
|
285
440
|
else resolve();
|
|
286
441
|
});
|
|
@@ -335,10 +490,10 @@ var FileService = class {
|
|
|
335
490
|
*/
|
|
336
491
|
async copyStarterFile(inputFile, outputFilePath, replaceIfExists) {
|
|
337
492
|
const __filename = fileURLToPath(import.meta.url);
|
|
338
|
-
const __dirname =
|
|
339
|
-
const filePath =
|
|
340
|
-
const fileString =
|
|
341
|
-
if (
|
|
493
|
+
const __dirname = path3.dirname(__filename);
|
|
494
|
+
const filePath = path3.resolve(__dirname, "starter-files", inputFile);
|
|
495
|
+
const fileString = fs4__default.readFileSync(filePath, "utf8");
|
|
496
|
+
if (fs4__default.existsSync(outputFilePath) && !replaceIfExists) {
|
|
342
497
|
console.log(`${outputFilePath} already exists`);
|
|
343
498
|
return false;
|
|
344
499
|
}
|
|
@@ -346,14 +501,14 @@ var FileService = class {
|
|
|
346
501
|
return true;
|
|
347
502
|
}
|
|
348
503
|
async setupEnvFile({ dbUrl }) {
|
|
349
|
-
const envPath =
|
|
504
|
+
const envPath = path3.join(process.cwd(), ".env.development");
|
|
350
505
|
await fsExtra3.ensureFile(envPath);
|
|
351
506
|
const fileEnvService = new FileEnvService(envPath);
|
|
352
507
|
await fileEnvService.setEnvValue("DB_URL", dbUrl);
|
|
353
508
|
}
|
|
354
509
|
getFirstExistingFile(files) {
|
|
355
510
|
for (const f of files) {
|
|
356
|
-
if (
|
|
511
|
+
if (fs4__default.existsSync(f)) {
|
|
357
512
|
return f;
|
|
358
513
|
}
|
|
359
514
|
}
|
|
@@ -363,20 +518,16 @@ var FileService = class {
|
|
|
363
518
|
filePath,
|
|
364
519
|
replacements
|
|
365
520
|
}) {
|
|
366
|
-
let fileContent =
|
|
521
|
+
let fileContent = fs4__default.readFileSync(filePath, "utf8");
|
|
367
522
|
replacements.forEach(({ search, replace }) => {
|
|
368
523
|
fileContent = fileContent.replaceAll(search, replace);
|
|
369
524
|
});
|
|
370
|
-
|
|
525
|
+
fs4__default.writeFileSync(filePath, fileContent);
|
|
371
526
|
}
|
|
372
527
|
};
|
|
373
|
-
var logger = new PinoLogger({
|
|
374
|
-
name: "Mastra CLI",
|
|
375
|
-
level: "info"
|
|
376
|
-
});
|
|
377
528
|
|
|
378
529
|
// src/commands/init/utils.ts
|
|
379
|
-
var
|
|
530
|
+
var exec2 = util.promisify(child_process.exec);
|
|
380
531
|
var getAISDKPackage = (llmProvider) => {
|
|
381
532
|
switch (llmProvider) {
|
|
382
533
|
case "openai":
|
|
@@ -453,8 +604,8 @@ export const weatherAgent = new Agent({
|
|
|
453
604
|
parser: "typescript",
|
|
454
605
|
singleQuote: true
|
|
455
606
|
});
|
|
456
|
-
await
|
|
457
|
-
await
|
|
607
|
+
await fs.writeFile(destPath, "");
|
|
608
|
+
await fs.writeFile(destPath, formattedContent);
|
|
458
609
|
}
|
|
459
610
|
async function writeWorkflowSample(destPath) {
|
|
460
611
|
const content = `import { createStep, createWorkflow } from '@mastra/core/workflows';
|
|
@@ -647,7 +798,7 @@ export { weatherWorkflow };`;
|
|
|
647
798
|
semi: true,
|
|
648
799
|
singleQuote: true
|
|
649
800
|
});
|
|
650
|
-
await
|
|
801
|
+
await fs.writeFile(destPath, formattedContent);
|
|
651
802
|
}
|
|
652
803
|
async function writeToolSample(destPath) {
|
|
653
804
|
const fileService = new FileService();
|
|
@@ -676,15 +827,15 @@ var writeIndexFile = async ({
|
|
|
676
827
|
addWorkflow
|
|
677
828
|
}) => {
|
|
678
829
|
const indexPath = dirPath + "/index.ts";
|
|
679
|
-
const destPath =
|
|
830
|
+
const destPath = path3.join(indexPath);
|
|
680
831
|
try {
|
|
681
|
-
await
|
|
832
|
+
await fs.writeFile(destPath, "");
|
|
682
833
|
const filteredExports = [
|
|
683
834
|
addWorkflow ? `workflows: { weatherWorkflow },` : "",
|
|
684
835
|
addAgent ? `agents: { weatherAgent },` : ""
|
|
685
836
|
].filter(Boolean);
|
|
686
837
|
if (!addExample) {
|
|
687
|
-
await
|
|
838
|
+
await fs.writeFile(
|
|
688
839
|
destPath,
|
|
689
840
|
`
|
|
690
841
|
import { Mastra } from '@mastra/core';
|
|
@@ -694,7 +845,7 @@ export const mastra = new Mastra()
|
|
|
694
845
|
);
|
|
695
846
|
return;
|
|
696
847
|
}
|
|
697
|
-
await
|
|
848
|
+
await fs.writeFile(
|
|
698
849
|
destPath,
|
|
699
850
|
`
|
|
700
851
|
import { Mastra } from '@mastra/core/mastra';
|
|
@@ -736,16 +887,16 @@ var checkAndInstallCoreDeps = async (addExample) => {
|
|
|
736
887
|
var spinner = yoctoSpinner({ text: "Installing Mastra core dependencies\n" });
|
|
737
888
|
async function installCoreDeps(pkg) {
|
|
738
889
|
try {
|
|
739
|
-
const confirm2 = await
|
|
890
|
+
const confirm2 = await p2.confirm({
|
|
740
891
|
message: `You do not have the ${pkg} package installed. Would you like to install it?`,
|
|
741
892
|
initialValue: false
|
|
742
893
|
});
|
|
743
|
-
if (
|
|
744
|
-
|
|
894
|
+
if (p2.isCancel(confirm2)) {
|
|
895
|
+
p2.cancel("Installation Cancelled");
|
|
745
896
|
process.exit(0);
|
|
746
897
|
}
|
|
747
898
|
if (!confirm2) {
|
|
748
|
-
|
|
899
|
+
p2.cancel("Installation Cancelled");
|
|
749
900
|
process.exit(0);
|
|
750
901
|
}
|
|
751
902
|
spinner.start();
|
|
@@ -782,13 +933,13 @@ var writeAPIKey = async ({
|
|
|
782
933
|
const key = await getAPIKey(provider);
|
|
783
934
|
const escapedKey = shellQuote.quote([key]);
|
|
784
935
|
const escapedApiKey = shellQuote.quote([apiKey]);
|
|
785
|
-
await
|
|
936
|
+
await exec2(`echo ${escapedKey}=${escapedApiKey} >> .env`);
|
|
786
937
|
};
|
|
787
938
|
var createMastraDir = async (directory) => {
|
|
788
939
|
let dir = directory.trim().split("/").filter((item) => item !== "");
|
|
789
|
-
const dirPath =
|
|
940
|
+
const dirPath = path3.join(process.cwd(), ...dir, "mastra");
|
|
790
941
|
try {
|
|
791
|
-
await
|
|
942
|
+
await fs.access(dirPath);
|
|
792
943
|
return { ok: false };
|
|
793
944
|
} catch {
|
|
794
945
|
await fsExtra3.ensureDir(dirPath);
|
|
@@ -804,15 +955,15 @@ var writeCodeSample = async (dirPath, component, llmProvider, importComponents)
|
|
|
804
955
|
}
|
|
805
956
|
};
|
|
806
957
|
var interactivePrompt = async () => {
|
|
807
|
-
|
|
808
|
-
const mastraProject = await
|
|
958
|
+
p2.intro(color2.inverse(" Mastra Init "));
|
|
959
|
+
const mastraProject = await p2.group(
|
|
809
960
|
{
|
|
810
|
-
directory: () =>
|
|
961
|
+
directory: () => p2.text({
|
|
811
962
|
message: "Where should we create the Mastra files? (default: src/)",
|
|
812
963
|
placeholder: "src/",
|
|
813
964
|
defaultValue: "src/"
|
|
814
965
|
}),
|
|
815
|
-
llmProvider: () =>
|
|
966
|
+
llmProvider: () => p2.select({
|
|
816
967
|
message: "Select default provider:",
|
|
817
968
|
options: [
|
|
818
969
|
{ value: "openai", label: "OpenAI", hint: "recommended" },
|
|
@@ -823,7 +974,7 @@ var interactivePrompt = async () => {
|
|
|
823
974
|
]
|
|
824
975
|
}),
|
|
825
976
|
llmApiKey: async ({ results: { llmProvider } }) => {
|
|
826
|
-
const keyChoice = await
|
|
977
|
+
const keyChoice = await p2.select({
|
|
827
978
|
message: `Enter your ${llmProvider} API key?`,
|
|
828
979
|
options: [
|
|
829
980
|
{ value: "skip", label: "Skip for now", hint: "default" },
|
|
@@ -832,7 +983,7 @@ var interactivePrompt = async () => {
|
|
|
832
983
|
initialValue: "skip"
|
|
833
984
|
});
|
|
834
985
|
if (keyChoice === "enter") {
|
|
835
|
-
return
|
|
986
|
+
return p2.text({
|
|
836
987
|
message: "Enter your API key:",
|
|
837
988
|
placeholder: "sk-..."
|
|
838
989
|
});
|
|
@@ -843,7 +994,7 @@ var interactivePrompt = async () => {
|
|
|
843
994
|
const windsurfIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`windsurf`);
|
|
844
995
|
const cursorIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`cursor`);
|
|
845
996
|
const vscodeIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`vscode`);
|
|
846
|
-
const editor = await
|
|
997
|
+
const editor = await p2.select({
|
|
847
998
|
message: `Make your AI IDE into a Mastra expert? (installs Mastra docs MCP server)`,
|
|
848
999
|
options: [
|
|
849
1000
|
{ value: "skip", label: "Skip for now", hint: "default" },
|
|
@@ -871,24 +1022,24 @@ var interactivePrompt = async () => {
|
|
|
871
1022
|
});
|
|
872
1023
|
if (editor === `skip`) return void 0;
|
|
873
1024
|
if (editor === `windsurf` && windsurfIsAlreadyInstalled) {
|
|
874
|
-
|
|
1025
|
+
p2.log.message(`
|
|
875
1026
|
Windsurf is already installed, skipping.`);
|
|
876
1027
|
return void 0;
|
|
877
1028
|
}
|
|
878
1029
|
if (editor === `vscode` && vscodeIsAlreadyInstalled) {
|
|
879
|
-
|
|
1030
|
+
p2.log.message(`
|
|
880
1031
|
VSCode is already installed, skipping.`);
|
|
881
1032
|
return void 0;
|
|
882
1033
|
}
|
|
883
1034
|
if (editor === `cursor`) {
|
|
884
|
-
|
|
1035
|
+
p2.log.message(
|
|
885
1036
|
`
|
|
886
1037
|
Note: you will need to go into Cursor Settings -> MCP Settings and manually enable the installed Mastra MCP server.
|
|
887
1038
|
`
|
|
888
1039
|
);
|
|
889
1040
|
}
|
|
890
1041
|
if (editor === `cursor-global`) {
|
|
891
|
-
const confirm2 = await
|
|
1042
|
+
const confirm2 = await p2.select({
|
|
892
1043
|
message: `Global install will add/update ${cursorGlobalMCPConfigPath} and make the Mastra docs MCP server available in all your Cursor projects. Continue?`,
|
|
893
1044
|
options: [
|
|
894
1045
|
{ value: "yes", label: "Yes, I understand" },
|
|
@@ -900,7 +1051,7 @@ Note: you will need to go into Cursor Settings -> MCP Settings and manually enab
|
|
|
900
1051
|
}
|
|
901
1052
|
}
|
|
902
1053
|
if (editor === `windsurf`) {
|
|
903
|
-
const confirm2 = await
|
|
1054
|
+
const confirm2 = await p2.select({
|
|
904
1055
|
message: `Windsurf only supports a global MCP config (at ${windsurfGlobalMCPConfigPath}) is it ok to add/update that global config?
|
|
905
1056
|
This means the Mastra docs MCP server will be available in all your Windsurf projects.`,
|
|
906
1057
|
options: [
|
|
@@ -917,7 +1068,7 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
917
1068
|
},
|
|
918
1069
|
{
|
|
919
1070
|
onCancel: () => {
|
|
920
|
-
|
|
1071
|
+
p2.cancel("Operation cancelled.");
|
|
921
1072
|
process.exit(0);
|
|
922
1073
|
}
|
|
923
1074
|
}
|
|
@@ -926,7 +1077,7 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
926
1077
|
};
|
|
927
1078
|
var checkPkgJson = async () => {
|
|
928
1079
|
const cwd = process.cwd();
|
|
929
|
-
const pkgJsonPath =
|
|
1080
|
+
const pkgJsonPath = path3.join(cwd, "package.json");
|
|
930
1081
|
let isPkgJsonPresent = false;
|
|
931
1082
|
try {
|
|
932
1083
|
await fsExtra3.readJSON(pkgJsonPath);
|
|
@@ -942,8 +1093,8 @@ var checkPkgJson = async () => {
|
|
|
942
1093
|
};
|
|
943
1094
|
|
|
944
1095
|
// src/commands/init/init.ts
|
|
945
|
-
var s =
|
|
946
|
-
var
|
|
1096
|
+
var s = p2.spinner();
|
|
1097
|
+
var exec3 = util.promisify(child_process.exec);
|
|
947
1098
|
var init = async ({
|
|
948
1099
|
directory,
|
|
949
1100
|
addExample = false,
|
|
@@ -995,7 +1146,7 @@ var init = async ({
|
|
|
995
1146
|
const depsService = new DepsService();
|
|
996
1147
|
const pm = depsService.packageManager;
|
|
997
1148
|
const installCommand = getPackageManagerInstallCommand(pm);
|
|
998
|
-
await
|
|
1149
|
+
await exec3(`${pm} ${installCommand} ${aiSdkPackage}`);
|
|
999
1150
|
if (configureEditorWithDocsMCP) {
|
|
1000
1151
|
await installMastraDocsMCPServer({
|
|
1001
1152
|
editor: configureEditorWithDocsMCP,
|
|
@@ -1004,14 +1155,14 @@ var init = async ({
|
|
|
1004
1155
|
}
|
|
1005
1156
|
s.stop();
|
|
1006
1157
|
if (!llmApiKey) {
|
|
1007
|
-
|
|
1158
|
+
p2.note(`
|
|
1008
1159
|
${color2.green("Mastra initialized successfully!")}
|
|
1009
1160
|
|
|
1010
1161
|
Add your ${color2.cyan(key)} as an environment variable
|
|
1011
1162
|
in your ${color2.cyan(".env")} file
|
|
1012
1163
|
`);
|
|
1013
1164
|
} else {
|
|
1014
|
-
|
|
1165
|
+
p2.note(`
|
|
1015
1166
|
${color2.green("Mastra initialized successfully!")}
|
|
1016
1167
|
`);
|
|
1017
1168
|
}
|
|
@@ -1022,10 +1173,10 @@ var init = async ({
|
|
|
1022
1173
|
return { success: false };
|
|
1023
1174
|
}
|
|
1024
1175
|
};
|
|
1025
|
-
var
|
|
1176
|
+
var exec4 = util.promisify(child_process.exec);
|
|
1026
1177
|
var execWithTimeout = async (command, timeoutMs) => {
|
|
1027
1178
|
try {
|
|
1028
|
-
const promise =
|
|
1179
|
+
const promise = exec4(command, { killSignal: "SIGTERM" });
|
|
1029
1180
|
if (!timeoutMs) {
|
|
1030
1181
|
return await promise;
|
|
1031
1182
|
}
|
|
@@ -1075,21 +1226,21 @@ var createMastraProject = async ({
|
|
|
1075
1226
|
createVersionTag,
|
|
1076
1227
|
timeout
|
|
1077
1228
|
}) => {
|
|
1078
|
-
|
|
1079
|
-
const projectName = name ?? await
|
|
1229
|
+
p2.intro(color2.inverse(" Mastra Create "));
|
|
1230
|
+
const projectName = name ?? await p2.text({
|
|
1080
1231
|
message: "What do you want to name your project?",
|
|
1081
1232
|
placeholder: "my-mastra-app",
|
|
1082
1233
|
defaultValue: "my-mastra-app"
|
|
1083
1234
|
});
|
|
1084
|
-
if (
|
|
1085
|
-
|
|
1235
|
+
if (p2.isCancel(projectName)) {
|
|
1236
|
+
p2.cancel("Operation cancelled");
|
|
1086
1237
|
process.exit(0);
|
|
1087
1238
|
}
|
|
1088
|
-
const s2 =
|
|
1239
|
+
const s2 = p2.spinner();
|
|
1089
1240
|
try {
|
|
1090
1241
|
s2.start("Creating project");
|
|
1091
1242
|
try {
|
|
1092
|
-
await
|
|
1243
|
+
await fs.mkdir(projectName);
|
|
1093
1244
|
} catch (error) {
|
|
1094
1245
|
if (error instanceof Error && "code" in error && error.code === "EEXIST") {
|
|
1095
1246
|
s2.stop(`A directory named "${projectName}" already exists. Please choose a different name.`);
|
|
@@ -1104,9 +1255,9 @@ var createMastraProject = async ({
|
|
|
1104
1255
|
const installCommand = getPackageManagerInstallCommand(pm);
|
|
1105
1256
|
s2.message("Initializing project structure");
|
|
1106
1257
|
try {
|
|
1107
|
-
await
|
|
1108
|
-
await
|
|
1109
|
-
await
|
|
1258
|
+
await exec4(`npm init -y`);
|
|
1259
|
+
await exec4(`npm pkg set type="module"`);
|
|
1260
|
+
await exec4(`npm pkg set engines.node=">=20.9.0"`);
|
|
1110
1261
|
const depsService = new DepsService();
|
|
1111
1262
|
await depsService.addScriptsToPackageJson({
|
|
1112
1263
|
dev: "mastra dev",
|
|
@@ -1121,9 +1272,9 @@ var createMastraProject = async ({
|
|
|
1121
1272
|
s2.stop("Project structure created");
|
|
1122
1273
|
s2.start(`Installing ${pm} dependencies`);
|
|
1123
1274
|
try {
|
|
1124
|
-
await
|
|
1125
|
-
await
|
|
1126
|
-
await
|
|
1275
|
+
await exec4(`${pm} ${installCommand} zod@^3`);
|
|
1276
|
+
await exec4(`${pm} ${installCommand} typescript @types/node --save-dev`);
|
|
1277
|
+
await exec4(`echo '{
|
|
1127
1278
|
"compilerOptions": {
|
|
1128
1279
|
"target": "ES2022",
|
|
1129
1280
|
"module": "ES2022",
|
|
@@ -1166,31 +1317,35 @@ var createMastraProject = async ({
|
|
|
1166
1317
|
s2.stop("Mastra dependencies installed");
|
|
1167
1318
|
s2.start("Adding .gitignore");
|
|
1168
1319
|
try {
|
|
1169
|
-
await
|
|
1170
|
-
await
|
|
1171
|
-
await
|
|
1172
|
-
await
|
|
1173
|
-
await
|
|
1174
|
-
await
|
|
1175
|
-
await
|
|
1176
|
-
await
|
|
1320
|
+
await exec4(`echo output.txt >> .gitignore`);
|
|
1321
|
+
await exec4(`echo node_modules >> .gitignore`);
|
|
1322
|
+
await exec4(`echo dist >> .gitignore`);
|
|
1323
|
+
await exec4(`echo .mastra >> .gitignore`);
|
|
1324
|
+
await exec4(`echo .env.development >> .gitignore`);
|
|
1325
|
+
await exec4(`echo .env >> .gitignore`);
|
|
1326
|
+
await exec4(`echo *.db >> .gitignore`);
|
|
1327
|
+
await exec4(`echo *.db-* >> .gitignore`);
|
|
1177
1328
|
} catch (error) {
|
|
1178
1329
|
throw new Error(`Failed to create .gitignore: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1179
1330
|
}
|
|
1180
1331
|
s2.stop(".gitignore added");
|
|
1181
|
-
|
|
1332
|
+
p2.outro("Project created successfully");
|
|
1182
1333
|
console.log("");
|
|
1183
1334
|
return { projectName };
|
|
1184
1335
|
} catch (error) {
|
|
1185
1336
|
s2.stop();
|
|
1186
1337
|
const errorMessage = error instanceof Error ? error.message : "An unexpected error occurred";
|
|
1187
|
-
|
|
1338
|
+
p2.cancel(`Project creation failed: ${errorMessage}`);
|
|
1188
1339
|
process.exit(1);
|
|
1189
1340
|
}
|
|
1190
1341
|
};
|
|
1191
1342
|
|
|
1192
1343
|
// src/commands/create/create.ts
|
|
1193
1344
|
var create = async (args2) => {
|
|
1345
|
+
if (args2.template !== void 0) {
|
|
1346
|
+
await createFromTemplate(args2);
|
|
1347
|
+
return;
|
|
1348
|
+
}
|
|
1194
1349
|
const { projectName } = await createMastraProject({
|
|
1195
1350
|
projectName: args2?.projectName,
|
|
1196
1351
|
createVersionTag: args2?.createVersionTag,
|
|
@@ -1199,6 +1354,13 @@ var create = async (args2) => {
|
|
|
1199
1354
|
const directory = args2.directory || "src/";
|
|
1200
1355
|
if (args2.components === void 0 || args2.llmProvider === void 0 || args2.addExample === void 0) {
|
|
1201
1356
|
const result = await interactivePrompt();
|
|
1357
|
+
const analytics2 = getAnalytics();
|
|
1358
|
+
if (analytics2 && result?.llmProvider) {
|
|
1359
|
+
analytics2.trackEvent("cli_model_provider_selected", {
|
|
1360
|
+
provider: result.llmProvider,
|
|
1361
|
+
selection_method: "interactive"
|
|
1362
|
+
});
|
|
1363
|
+
}
|
|
1202
1364
|
await init({
|
|
1203
1365
|
...result,
|
|
1204
1366
|
llmApiKey: result?.llmApiKey,
|
|
@@ -1209,6 +1371,13 @@ var create = async (args2) => {
|
|
|
1209
1371
|
return;
|
|
1210
1372
|
}
|
|
1211
1373
|
const { components = [], llmProvider = "openai", addExample = false, llmApiKey } = args2;
|
|
1374
|
+
const analytics = getAnalytics();
|
|
1375
|
+
if (analytics) {
|
|
1376
|
+
analytics.trackEvent("cli_model_provider_selected", {
|
|
1377
|
+
provider: llmProvider,
|
|
1378
|
+
selection_method: "cli_args"
|
|
1379
|
+
});
|
|
1380
|
+
}
|
|
1212
1381
|
await init({
|
|
1213
1382
|
directory,
|
|
1214
1383
|
components,
|
|
@@ -1221,12 +1390,71 @@ var create = async (args2) => {
|
|
|
1221
1390
|
};
|
|
1222
1391
|
var postCreate = ({ projectName }) => {
|
|
1223
1392
|
const packageManager = getPackageManager();
|
|
1224
|
-
|
|
1393
|
+
p2.outro(`
|
|
1225
1394
|
${color2.green("To start your project:")}
|
|
1226
1395
|
|
|
1227
1396
|
${color2.cyan("cd")} ${projectName}
|
|
1228
1397
|
${color2.cyan(`${packageManager} run dev`)}
|
|
1229
1398
|
`);
|
|
1230
1399
|
};
|
|
1400
|
+
async function createFromTemplate(args2) {
|
|
1401
|
+
const templates = await loadTemplates();
|
|
1402
|
+
let selectedTemplate;
|
|
1403
|
+
if (args2.template === true) {
|
|
1404
|
+
selectedTemplate = await selectTemplate(templates);
|
|
1405
|
+
if (!selectedTemplate) {
|
|
1406
|
+
p2.log.info("No template selected. Exiting.");
|
|
1407
|
+
return;
|
|
1408
|
+
}
|
|
1409
|
+
} else if (args2.template) {
|
|
1410
|
+
selectedTemplate = findTemplateByName(templates, args2.template);
|
|
1411
|
+
if (!selectedTemplate) {
|
|
1412
|
+
p2.log.error(`Template "${args2.template}" not found. Available templates:`);
|
|
1413
|
+
templates.forEach((t) => p2.log.info(` - ${t.title} (use: ${t.slug.replace("template-", "")})`));
|
|
1414
|
+
throw new Error(`Template "${args2.template}" not found`);
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
if (!selectedTemplate) {
|
|
1418
|
+
throw new Error("No template selected");
|
|
1419
|
+
}
|
|
1420
|
+
let projectName = args2.projectName;
|
|
1421
|
+
if (!projectName) {
|
|
1422
|
+
const defaultName = getDefaultProjectName(selectedTemplate);
|
|
1423
|
+
const response = await p2.text({
|
|
1424
|
+
message: "What is your project name?",
|
|
1425
|
+
defaultValue: defaultName,
|
|
1426
|
+
placeholder: defaultName
|
|
1427
|
+
});
|
|
1428
|
+
if (p2.isCancel(response)) {
|
|
1429
|
+
p2.log.info("Project creation cancelled.");
|
|
1430
|
+
return;
|
|
1431
|
+
}
|
|
1432
|
+
projectName = response;
|
|
1433
|
+
}
|
|
1434
|
+
try {
|
|
1435
|
+
const analytics = getAnalytics();
|
|
1436
|
+
if (analytics) {
|
|
1437
|
+
analytics.trackEvent("cli_template_used", {
|
|
1438
|
+
template_slug: selectedTemplate.slug,
|
|
1439
|
+
template_title: selectedTemplate.title
|
|
1440
|
+
});
|
|
1441
|
+
}
|
|
1442
|
+
const projectPath = await cloneTemplate({
|
|
1443
|
+
template: selectedTemplate,
|
|
1444
|
+
projectName
|
|
1445
|
+
});
|
|
1446
|
+
await installDependencies(projectPath);
|
|
1447
|
+
p2.note(`
|
|
1448
|
+
${color2.green("Mastra template installed!")}
|
|
1449
|
+
|
|
1450
|
+
Add the necessary environment
|
|
1451
|
+
variables in your ${color2.cyan(".env")} file
|
|
1452
|
+
`);
|
|
1453
|
+
postCreate({ projectName });
|
|
1454
|
+
} catch (error) {
|
|
1455
|
+
p2.log.error(`Failed to create project from template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1456
|
+
throw error;
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1231
1459
|
|
|
1232
1460
|
export { DepsService, FileService, checkAndInstallCoreDeps, checkPkgJson, create, init, interactivePrompt, logger };
|