create-mastra 0.0.0-tsconfig-compile-20250703214351 → 0.0.0-unified-sidebar-20251010130811
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1991 -0
- package/LICENSE.md +11 -42
- package/README.md +2 -8
- package/dist/index.js +525 -190
- package/dist/index.js.map +1 -1
- package/dist/templates/dev.entry.js +12 -2
- package/package.json +20 -12
- package/dist/starter-files/config.ts +0 -25
- package/dist/starter-files/mastra-pg.docker-compose.yaml +0 -15
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#! /usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
|
-
import * as
|
|
5
|
-
import
|
|
4
|
+
import * as fs4__default from 'node:fs';
|
|
5
|
+
import fs4__default__default, { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
6
6
|
import os from 'node:os';
|
|
7
|
-
import
|
|
7
|
+
import path3, { dirname } from 'node:path';
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
9
|
import { PostHog } from 'posthog-node';
|
|
10
10
|
import util, { stripVTControlCharacters } from 'node:util';
|
|
@@ -12,18 +12,22 @@ import y$1, { stdout, stdin } from 'node:process';
|
|
|
12
12
|
import * as g from 'node:readline';
|
|
13
13
|
import g__default from 'node:readline';
|
|
14
14
|
import { Writable } from 'node:stream';
|
|
15
|
+
import fs5 from 'node:fs/promises';
|
|
15
16
|
import child_process from 'node:child_process';
|
|
16
|
-
import fs4 from 'node:fs/promises';
|
|
17
|
-
import { execa } from 'execa';
|
|
18
|
-
import fsExtra3, { readJSON, ensureFile, writeJSON } from 'fs-extra/esm';
|
|
19
|
-
import prettier from 'prettier';
|
|
20
17
|
import tty from 'node:tty';
|
|
21
18
|
import pino from 'pino';
|
|
22
19
|
import pretty from 'pino-pretty';
|
|
23
|
-
import
|
|
20
|
+
import { execa } from 'execa';
|
|
21
|
+
import fsExtra, { readJSON, ensureFile, writeJSON } from 'fs-extra/esm';
|
|
22
|
+
import prettier from 'prettier';
|
|
23
|
+
import fsExtra$1 from 'fs-extra';
|
|
24
24
|
|
|
25
25
|
var __filename = fileURLToPath(import.meta.url);
|
|
26
|
-
var __dirname =
|
|
26
|
+
var __dirname = path3.dirname(__filename);
|
|
27
|
+
var analyticsInstance = null;
|
|
28
|
+
function getAnalytics() {
|
|
29
|
+
return analyticsInstance;
|
|
30
|
+
}
|
|
27
31
|
var PosthogAnalytics = class {
|
|
28
32
|
sessionId;
|
|
29
33
|
client;
|
|
@@ -35,7 +39,7 @@ var PosthogAnalytics = class {
|
|
|
35
39
|
host = "https://app.posthog.com"
|
|
36
40
|
}) {
|
|
37
41
|
this.version = version;
|
|
38
|
-
const cliConfigPath =
|
|
42
|
+
const cliConfigPath = path3.join(__dirname, "mastra-cli.json");
|
|
39
43
|
if (existsSync(cliConfigPath)) {
|
|
40
44
|
try {
|
|
41
45
|
const { distinctId, sessionId } = JSON.parse(readFileSync(cliConfigPath, "utf-8"));
|
|
@@ -63,7 +67,7 @@ var PosthogAnalytics = class {
|
|
|
63
67
|
}
|
|
64
68
|
writeCliConfig({ distinctId, sessionId }) {
|
|
65
69
|
try {
|
|
66
|
-
writeFileSync(
|
|
70
|
+
writeFileSync(path3.join(__dirname, "mastra-cli.json"), JSON.stringify({ distinctId, sessionId }));
|
|
67
71
|
} catch {
|
|
68
72
|
}
|
|
69
73
|
}
|
|
@@ -113,6 +117,22 @@ var PosthogAnalytics = class {
|
|
|
113
117
|
}
|
|
114
118
|
});
|
|
115
119
|
}
|
|
120
|
+
trackEvent(eventName, properties) {
|
|
121
|
+
try {
|
|
122
|
+
if (!this.client) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
this.client.capture({
|
|
126
|
+
distinctId: this.distinctId,
|
|
127
|
+
event: eventName,
|
|
128
|
+
properties: {
|
|
129
|
+
...this.getSystemProperties(),
|
|
130
|
+
...properties
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
} catch {
|
|
134
|
+
}
|
|
135
|
+
}
|
|
116
136
|
trackCommand(options) {
|
|
117
137
|
try {
|
|
118
138
|
if (!this.client) {
|
|
@@ -1153,6 +1173,197 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1153
1173
|
}
|
|
1154
1174
|
};
|
|
1155
1175
|
|
|
1176
|
+
function getPackageManager() {
|
|
1177
|
+
const userAgent = process.env.npm_config_user_agent || "";
|
|
1178
|
+
const execPath = process.env.npm_execpath || "";
|
|
1179
|
+
if (userAgent.includes("yarn")) {
|
|
1180
|
+
return "yarn";
|
|
1181
|
+
}
|
|
1182
|
+
if (userAgent.includes("pnpm")) {
|
|
1183
|
+
return "pnpm";
|
|
1184
|
+
}
|
|
1185
|
+
if (userAgent.includes("npm")) {
|
|
1186
|
+
return "npm";
|
|
1187
|
+
}
|
|
1188
|
+
if (execPath.includes("yarn")) {
|
|
1189
|
+
return "yarn";
|
|
1190
|
+
}
|
|
1191
|
+
if (execPath.includes("pnpm")) {
|
|
1192
|
+
return "pnpm";
|
|
1193
|
+
}
|
|
1194
|
+
if (execPath.includes("npm")) {
|
|
1195
|
+
return "npm";
|
|
1196
|
+
}
|
|
1197
|
+
return "npm";
|
|
1198
|
+
}
|
|
1199
|
+
var logger = new PinoLogger({
|
|
1200
|
+
name: "Mastra CLI",
|
|
1201
|
+
level: "info"
|
|
1202
|
+
});
|
|
1203
|
+
var exec = util.promisify(child_process.exec);
|
|
1204
|
+
async function cloneTemplate(options) {
|
|
1205
|
+
const { template, projectName, targetDir } = options;
|
|
1206
|
+
const projectPath = targetDir ? path3.resolve(targetDir, projectName) : path3.resolve(projectName);
|
|
1207
|
+
const spinner5 = yoctoSpinner({ text: `Cloning template "${template.title}"...` }).start();
|
|
1208
|
+
try {
|
|
1209
|
+
if (await directoryExists(projectPath)) {
|
|
1210
|
+
spinner5.error(`Directory ${projectName} already exists`);
|
|
1211
|
+
throw new Error(`Directory ${projectName} already exists`);
|
|
1212
|
+
}
|
|
1213
|
+
await cloneRepositoryWithoutGit(template.githubUrl, projectPath);
|
|
1214
|
+
await updatePackageJson(projectPath, projectName);
|
|
1215
|
+
const envExamplePath = path3.join(projectPath, ".env.example");
|
|
1216
|
+
if (await fileExists(envExamplePath)) {
|
|
1217
|
+
await fs5.copyFile(envExamplePath, path3.join(projectPath, ".env"));
|
|
1218
|
+
}
|
|
1219
|
+
spinner5.success(`Template "${template.title}" cloned successfully to ${projectName}`);
|
|
1220
|
+
return projectPath;
|
|
1221
|
+
} catch (error) {
|
|
1222
|
+
spinner5.error(`Failed to clone template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1223
|
+
throw error;
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
async function directoryExists(dirPath) {
|
|
1227
|
+
try {
|
|
1228
|
+
const stat = await fs5.stat(dirPath);
|
|
1229
|
+
return stat.isDirectory();
|
|
1230
|
+
} catch {
|
|
1231
|
+
return false;
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
async function fileExists(filePath) {
|
|
1235
|
+
try {
|
|
1236
|
+
const stat = await fs5.stat(filePath);
|
|
1237
|
+
return stat.isFile();
|
|
1238
|
+
} catch {
|
|
1239
|
+
return false;
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
async function cloneRepositoryWithoutGit(repoUrl, targetPath) {
|
|
1243
|
+
await fs5.mkdir(targetPath, { recursive: true });
|
|
1244
|
+
try {
|
|
1245
|
+
const degitRepo = repoUrl.replace("https://github.com/", "");
|
|
1246
|
+
const degitCommand = shellQuote.quote(["npx", "degit", degitRepo, targetPath]);
|
|
1247
|
+
await exec(degitCommand, {
|
|
1248
|
+
cwd: process.cwd()
|
|
1249
|
+
});
|
|
1250
|
+
} catch {
|
|
1251
|
+
try {
|
|
1252
|
+
const gitCommand = shellQuote.quote(["git", "clone", repoUrl, targetPath]);
|
|
1253
|
+
await exec(gitCommand, {
|
|
1254
|
+
cwd: process.cwd()
|
|
1255
|
+
});
|
|
1256
|
+
const gitDir = path3.join(targetPath, ".git");
|
|
1257
|
+
if (await directoryExists(gitDir)) {
|
|
1258
|
+
await fs5.rm(gitDir, { recursive: true, force: true });
|
|
1259
|
+
}
|
|
1260
|
+
} catch (gitError) {
|
|
1261
|
+
throw new Error(`Failed to clone repository: ${gitError instanceof Error ? gitError.message : "Unknown error"}`);
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
async function updatePackageJson(projectPath, projectName) {
|
|
1266
|
+
const packageJsonPath = path3.join(projectPath, "package.json");
|
|
1267
|
+
try {
|
|
1268
|
+
const packageJsonContent = await fs5.readFile(packageJsonPath, "utf-8");
|
|
1269
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
1270
|
+
packageJson.name = projectName;
|
|
1271
|
+
await fs5.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf-8");
|
|
1272
|
+
} catch (error) {
|
|
1273
|
+
logger.warn(`Could not update package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
async function installDependencies(projectPath, packageManager) {
|
|
1277
|
+
const spinner5 = yoctoSpinner({ text: "Installing dependencies..." }).start();
|
|
1278
|
+
try {
|
|
1279
|
+
const pm = packageManager || getPackageManager();
|
|
1280
|
+
const installCommand = shellQuote.quote([pm, "install"]);
|
|
1281
|
+
await exec(installCommand, {
|
|
1282
|
+
cwd: projectPath
|
|
1283
|
+
});
|
|
1284
|
+
spinner5.success("Dependencies installed successfully");
|
|
1285
|
+
} catch (error) {
|
|
1286
|
+
spinner5.error(`Failed to install dependencies: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1287
|
+
throw error;
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
var TEMPLATES_API_URL = process.env.MASTRA_TEMPLATES_API_URL || "https://mastra.ai/api/templates.json";
|
|
1291
|
+
async function loadTemplates() {
|
|
1292
|
+
try {
|
|
1293
|
+
const response = await fetch(TEMPLATES_API_URL);
|
|
1294
|
+
if (!response.ok) {
|
|
1295
|
+
throw new Error(`Failed to fetch templates: ${response.statusText}`);
|
|
1296
|
+
}
|
|
1297
|
+
const templates = await response.json();
|
|
1298
|
+
return templates;
|
|
1299
|
+
} catch (error) {
|
|
1300
|
+
console.error("Error loading templates:", error);
|
|
1301
|
+
throw new Error("Failed to load templates. Please check your internet connection and try again.");
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
function pluralize(count, singular, plural) {
|
|
1305
|
+
return count === 1 ? singular : plural || `${singular}s`;
|
|
1306
|
+
}
|
|
1307
|
+
async function selectTemplate(templates) {
|
|
1308
|
+
const choices = templates.map((template) => {
|
|
1309
|
+
const parts = [];
|
|
1310
|
+
if (template.agents?.length) {
|
|
1311
|
+
parts.push(`${template.agents.length} ${pluralize(template.agents.length, "agent")}`);
|
|
1312
|
+
}
|
|
1313
|
+
if (template.tools?.length) {
|
|
1314
|
+
parts.push(`${template.tools.length} ${pluralize(template.tools.length, "tool")}`);
|
|
1315
|
+
}
|
|
1316
|
+
if (template.workflows?.length) {
|
|
1317
|
+
parts.push(`${template.workflows.length} ${pluralize(template.workflows.length, "workflow")}`);
|
|
1318
|
+
}
|
|
1319
|
+
if (template.mcp?.length) {
|
|
1320
|
+
parts.push(`${template.mcp.length} ${pluralize(template.mcp.length, "MCP server")}`);
|
|
1321
|
+
}
|
|
1322
|
+
if (template.networks?.length) {
|
|
1323
|
+
parts.push(`${template.networks.length} ${pluralize(template.networks.length, "agent network")}`);
|
|
1324
|
+
}
|
|
1325
|
+
return {
|
|
1326
|
+
value: template,
|
|
1327
|
+
label: template.title,
|
|
1328
|
+
hint: parts.join(", ") || "Template components"
|
|
1329
|
+
};
|
|
1330
|
+
});
|
|
1331
|
+
const selected = await ve({
|
|
1332
|
+
message: "Select a template:",
|
|
1333
|
+
options: choices
|
|
1334
|
+
});
|
|
1335
|
+
if (pD(selected)) {
|
|
1336
|
+
return null;
|
|
1337
|
+
}
|
|
1338
|
+
return selected;
|
|
1339
|
+
}
|
|
1340
|
+
function findTemplateByName(templates, templateName) {
|
|
1341
|
+
let template = templates.find((t) => t.slug === templateName);
|
|
1342
|
+
if (template) return template;
|
|
1343
|
+
const slugWithPrefix = `template-${templateName}`;
|
|
1344
|
+
template = templates.find((t) => t.slug === slugWithPrefix);
|
|
1345
|
+
if (template) return template;
|
|
1346
|
+
template = templates.find((t) => t.title.toLowerCase() === templateName.toLowerCase());
|
|
1347
|
+
if (template) return template;
|
|
1348
|
+
return null;
|
|
1349
|
+
}
|
|
1350
|
+
function getDefaultProjectName(template) {
|
|
1351
|
+
return template.slug.replace(/^template-/, "");
|
|
1352
|
+
}
|
|
1353
|
+
function getPackageManagerAddCommand(pm) {
|
|
1354
|
+
switch (pm) {
|
|
1355
|
+
case "npm":
|
|
1356
|
+
return "install --audit=false --fund=false --loglevel=error --progress=false --update-notifier=false";
|
|
1357
|
+
case "yarn":
|
|
1358
|
+
return "add";
|
|
1359
|
+
case "pnpm":
|
|
1360
|
+
return "add --loglevel=error";
|
|
1361
|
+
case "bun":
|
|
1362
|
+
return "add";
|
|
1363
|
+
default:
|
|
1364
|
+
return "add";
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1156
1367
|
var DepsService = class {
|
|
1157
1368
|
packageManager;
|
|
1158
1369
|
constructor() {
|
|
@@ -1161,11 +1372,11 @@ var DepsService = class {
|
|
|
1161
1372
|
findLockFile(dir) {
|
|
1162
1373
|
const lockFiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lock"];
|
|
1163
1374
|
for (const file of lockFiles) {
|
|
1164
|
-
if (
|
|
1375
|
+
if (fs4__default__default.existsSync(path3.join(dir, file))) {
|
|
1165
1376
|
return file;
|
|
1166
1377
|
}
|
|
1167
1378
|
}
|
|
1168
|
-
const parentDir =
|
|
1379
|
+
const parentDir = path3.resolve(dir, "..");
|
|
1169
1380
|
if (parentDir !== dir) {
|
|
1170
1381
|
return this.findLockFile(parentDir);
|
|
1171
1382
|
}
|
|
@@ -1187,14 +1398,10 @@ var DepsService = class {
|
|
|
1187
1398
|
}
|
|
1188
1399
|
}
|
|
1189
1400
|
async installPackages(packages) {
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
runCommand = `${this.packageManager} i`;
|
|
1193
|
-
} else {
|
|
1194
|
-
runCommand = `${this.packageManager} add`;
|
|
1195
|
-
}
|
|
1401
|
+
const pm = this.packageManager;
|
|
1402
|
+
const installCommand = getPackageManagerAddCommand(pm);
|
|
1196
1403
|
const packageList = packages.join(" ");
|
|
1197
|
-
return execa(`${
|
|
1404
|
+
return execa(`${pm} ${installCommand} ${packageList}`, {
|
|
1198
1405
|
all: true,
|
|
1199
1406
|
shell: true,
|
|
1200
1407
|
stdio: "inherit"
|
|
@@ -1202,13 +1409,13 @@ var DepsService = class {
|
|
|
1202
1409
|
}
|
|
1203
1410
|
async checkDependencies(dependencies) {
|
|
1204
1411
|
try {
|
|
1205
|
-
const packageJsonPath =
|
|
1412
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1206
1413
|
try {
|
|
1207
|
-
await
|
|
1414
|
+
await fs5.access(packageJsonPath);
|
|
1208
1415
|
} catch {
|
|
1209
1416
|
return "No package.json file found in the current directory";
|
|
1210
1417
|
}
|
|
1211
|
-
const packageJson = JSON.parse(await
|
|
1418
|
+
const packageJson = JSON.parse(await fs5.readFile(packageJsonPath, "utf-8"));
|
|
1212
1419
|
for (const dependency of dependencies) {
|
|
1213
1420
|
if (!packageJson.dependencies || !packageJson.dependencies[dependency]) {
|
|
1214
1421
|
return `Please install ${dependency} before running this command (${this.packageManager} install ${dependency})`;
|
|
@@ -1222,65 +1429,23 @@ var DepsService = class {
|
|
|
1222
1429
|
}
|
|
1223
1430
|
async getProjectName() {
|
|
1224
1431
|
try {
|
|
1225
|
-
const packageJsonPath =
|
|
1226
|
-
const packageJson = await
|
|
1432
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1433
|
+
const packageJson = await fs5.readFile(packageJsonPath, "utf-8");
|
|
1227
1434
|
const pkg = JSON.parse(packageJson);
|
|
1228
1435
|
return pkg.name;
|
|
1229
1436
|
} catch (err) {
|
|
1230
1437
|
throw err;
|
|
1231
1438
|
}
|
|
1232
1439
|
}
|
|
1233
|
-
async getPackageVersion() {
|
|
1234
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
1235
|
-
const __dirname = dirname(__filename);
|
|
1236
|
-
const pkgJsonPath = path2.join(__dirname, "..", "package.json");
|
|
1237
|
-
const content = await fsExtra3.readJSON(pkgJsonPath);
|
|
1238
|
-
return content.version;
|
|
1239
|
-
}
|
|
1240
1440
|
async addScriptsToPackageJson(scripts) {
|
|
1241
|
-
const packageJson = JSON.parse(await
|
|
1441
|
+
const packageJson = JSON.parse(await fs5.readFile("package.json", "utf-8"));
|
|
1242
1442
|
packageJson.scripts = {
|
|
1243
1443
|
...packageJson.scripts,
|
|
1244
1444
|
...scripts
|
|
1245
1445
|
};
|
|
1246
|
-
await
|
|
1446
|
+
await fs5.writeFile("package.json", JSON.stringify(packageJson, null, 2));
|
|
1247
1447
|
}
|
|
1248
1448
|
};
|
|
1249
|
-
function getPackageManager() {
|
|
1250
|
-
const userAgent = process.env.npm_config_user_agent || "";
|
|
1251
|
-
const execPath = process.env.npm_execpath || "";
|
|
1252
|
-
if (userAgent.includes("yarn")) {
|
|
1253
|
-
return "yarn";
|
|
1254
|
-
}
|
|
1255
|
-
if (userAgent.includes("pnpm")) {
|
|
1256
|
-
return "pnpm";
|
|
1257
|
-
}
|
|
1258
|
-
if (userAgent.includes("npm")) {
|
|
1259
|
-
return "npm";
|
|
1260
|
-
}
|
|
1261
|
-
if (execPath.includes("yarn")) {
|
|
1262
|
-
return "yarn";
|
|
1263
|
-
}
|
|
1264
|
-
if (execPath.includes("pnpm")) {
|
|
1265
|
-
return "pnpm";
|
|
1266
|
-
}
|
|
1267
|
-
if (execPath.includes("npm")) {
|
|
1268
|
-
return "npm";
|
|
1269
|
-
}
|
|
1270
|
-
return "npm";
|
|
1271
|
-
}
|
|
1272
|
-
function getPackageManagerInstallCommand(pm) {
|
|
1273
|
-
switch (pm) {
|
|
1274
|
-
case "npm":
|
|
1275
|
-
return "install";
|
|
1276
|
-
case "yarn":
|
|
1277
|
-
return "add";
|
|
1278
|
-
case "pnpm":
|
|
1279
|
-
return "add";
|
|
1280
|
-
default:
|
|
1281
|
-
return "install";
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
1449
|
var args = ["-y", "@mastra/mcp-docs-server"];
|
|
1285
1450
|
var createMcpConfig = (editor) => {
|
|
1286
1451
|
if (editor === "vscode") {
|
|
@@ -1333,19 +1498,19 @@ async function writeMergedConfig(configPath, editor) {
|
|
|
1333
1498
|
spaces: 2
|
|
1334
1499
|
});
|
|
1335
1500
|
}
|
|
1336
|
-
var windsurfGlobalMCPConfigPath =
|
|
1337
|
-
var cursorGlobalMCPConfigPath =
|
|
1338
|
-
|
|
1339
|
-
var vscodeGlobalMCPConfigPath =
|
|
1501
|
+
var windsurfGlobalMCPConfigPath = path3.join(os.homedir(), ".codeium", "windsurf", "mcp_config.json");
|
|
1502
|
+
var cursorGlobalMCPConfigPath = path3.join(os.homedir(), ".cursor", "mcp.json");
|
|
1503
|
+
path3.join(process.cwd(), ".vscode", "mcp.json");
|
|
1504
|
+
var vscodeGlobalMCPConfigPath = path3.join(
|
|
1340
1505
|
os.homedir(),
|
|
1341
|
-
process.platform === "win32" ?
|
|
1506
|
+
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")
|
|
1342
1507
|
);
|
|
1343
1508
|
async function installMastraDocsMCPServer({ editor, directory }) {
|
|
1344
1509
|
if (editor === `cursor`) {
|
|
1345
|
-
await writeMergedConfig(
|
|
1510
|
+
await writeMergedConfig(path3.join(directory, ".cursor", "mcp.json"), "cursor");
|
|
1346
1511
|
}
|
|
1347
1512
|
if (editor === `vscode`) {
|
|
1348
|
-
await writeMergedConfig(
|
|
1513
|
+
await writeMergedConfig(path3.join(directory, ".vscode", "mcp.json"), "vscode");
|
|
1349
1514
|
}
|
|
1350
1515
|
if (editor === `cursor-global`) {
|
|
1351
1516
|
const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor);
|
|
@@ -1403,7 +1568,7 @@ var FileEnvService = class extends EnvService {
|
|
|
1403
1568
|
}
|
|
1404
1569
|
readFile(filePath) {
|
|
1405
1570
|
return new Promise((resolve, reject) => {
|
|
1406
|
-
|
|
1571
|
+
fs4__default.readFile(filePath, "utf8", (err, data) => {
|
|
1407
1572
|
if (err) reject(err);
|
|
1408
1573
|
else resolve(data);
|
|
1409
1574
|
});
|
|
@@ -1411,7 +1576,7 @@ var FileEnvService = class extends EnvService {
|
|
|
1411
1576
|
}
|
|
1412
1577
|
writeFile({ filePath, data }) {
|
|
1413
1578
|
return new Promise((resolve, reject) => {
|
|
1414
|
-
|
|
1579
|
+
fs4__default.writeFile(filePath, data, "utf8", (err) => {
|
|
1415
1580
|
if (err) reject(err);
|
|
1416
1581
|
else resolve();
|
|
1417
1582
|
});
|
|
@@ -1431,7 +1596,7 @@ var FileEnvService = class extends EnvService {
|
|
|
1431
1596
|
${key}=${value}`;
|
|
1432
1597
|
}
|
|
1433
1598
|
await this.writeFile({ filePath, data });
|
|
1434
|
-
console.
|
|
1599
|
+
console.info(`${key} set to ${value} in ENV file.`);
|
|
1435
1600
|
return data;
|
|
1436
1601
|
}
|
|
1437
1602
|
async getEnvValue(key) {
|
|
@@ -1464,25 +1629,25 @@ var FileService = class {
|
|
|
1464
1629
|
*/
|
|
1465
1630
|
async copyStarterFile(inputFile, outputFilePath, replaceIfExists) {
|
|
1466
1631
|
const __filename = fileURLToPath(import.meta.url);
|
|
1467
|
-
const __dirname =
|
|
1468
|
-
const filePath =
|
|
1469
|
-
const fileString =
|
|
1470
|
-
if (
|
|
1471
|
-
console.
|
|
1632
|
+
const __dirname = path3.dirname(__filename);
|
|
1633
|
+
const filePath = path3.resolve(__dirname, "starter-files", inputFile);
|
|
1634
|
+
const fileString = fs4__default__default.readFileSync(filePath, "utf8");
|
|
1635
|
+
if (fs4__default__default.existsSync(outputFilePath) && !replaceIfExists) {
|
|
1636
|
+
console.info(`${outputFilePath} already exists`);
|
|
1472
1637
|
return false;
|
|
1473
1638
|
}
|
|
1474
|
-
await
|
|
1639
|
+
await fsExtra.outputFile(outputFilePath, fileString);
|
|
1475
1640
|
return true;
|
|
1476
1641
|
}
|
|
1477
1642
|
async setupEnvFile({ dbUrl }) {
|
|
1478
|
-
const envPath =
|
|
1479
|
-
await
|
|
1643
|
+
const envPath = path3.join(process.cwd(), ".env.development");
|
|
1644
|
+
await fsExtra.ensureFile(envPath);
|
|
1480
1645
|
const fileEnvService = new FileEnvService(envPath);
|
|
1481
1646
|
await fileEnvService.setEnvValue("DB_URL", dbUrl);
|
|
1482
1647
|
}
|
|
1483
1648
|
getFirstExistingFile(files) {
|
|
1484
1649
|
for (const f of files) {
|
|
1485
|
-
if (
|
|
1650
|
+
if (fs4__default__default.existsSync(f)) {
|
|
1486
1651
|
return f;
|
|
1487
1652
|
}
|
|
1488
1653
|
}
|
|
@@ -1492,57 +1657,31 @@ var FileService = class {
|
|
|
1492
1657
|
filePath,
|
|
1493
1658
|
replacements
|
|
1494
1659
|
}) {
|
|
1495
|
-
let fileContent =
|
|
1660
|
+
let fileContent = fs4__default__default.readFileSync(filePath, "utf8");
|
|
1496
1661
|
replacements.forEach(({ search, replace }) => {
|
|
1497
1662
|
fileContent = fileContent.replaceAll(search, replace);
|
|
1498
1663
|
});
|
|
1499
|
-
|
|
1500
|
-
}
|
|
1501
|
-
};
|
|
1502
|
-
new PinoLogger({
|
|
1503
|
-
name: "Mastra CLI",
|
|
1504
|
-
level: "info"
|
|
1505
|
-
});
|
|
1506
|
-
var exec = util.promisify(child_process.exec);
|
|
1507
|
-
var getAISDKPackage = (llmProvider) => {
|
|
1508
|
-
switch (llmProvider) {
|
|
1509
|
-
case "openai":
|
|
1510
|
-
return "@ai-sdk/openai";
|
|
1511
|
-
case "anthropic":
|
|
1512
|
-
return "@ai-sdk/anthropic";
|
|
1513
|
-
case "groq":
|
|
1514
|
-
return "@ai-sdk/groq";
|
|
1515
|
-
case "google":
|
|
1516
|
-
return "@ai-sdk/google";
|
|
1517
|
-
case "cerebras":
|
|
1518
|
-
return "@ai-sdk/cerebras";
|
|
1519
|
-
default:
|
|
1520
|
-
return "@ai-sdk/openai";
|
|
1664
|
+
fs4__default__default.writeFileSync(filePath, fileContent);
|
|
1521
1665
|
}
|
|
1522
1666
|
};
|
|
1523
|
-
var
|
|
1524
|
-
|
|
1525
|
-
let modelItem = "";
|
|
1667
|
+
var exec2 = util.promisify(child_process.exec);
|
|
1668
|
+
var getModelIdentifier = (llmProvider) => {
|
|
1526
1669
|
if (llmProvider === "openai") {
|
|
1527
|
-
|
|
1528
|
-
modelItem = `openai('gpt-4o-mini')`;
|
|
1670
|
+
return `'openai/gpt-4o-mini'`;
|
|
1529
1671
|
} else if (llmProvider === "anthropic") {
|
|
1530
|
-
|
|
1531
|
-
modelItem = `anthropic('claude-3-5-sonnet-20241022')`;
|
|
1672
|
+
return `'anthropic/claude-3-5-sonnet-20241022'`;
|
|
1532
1673
|
} else if (llmProvider === "groq") {
|
|
1533
|
-
|
|
1534
|
-
modelItem = `groq('llama-3.3-70b-versatile')`;
|
|
1674
|
+
return `'groq/llama-3.3-70b-versatile'`;
|
|
1535
1675
|
} else if (llmProvider === "google") {
|
|
1536
|
-
|
|
1537
|
-
modelItem = `google('gemini-2.5-pro-exp-03-25')`;
|
|
1676
|
+
return `'google/gemini-2.5-pro'`;
|
|
1538
1677
|
} else if (llmProvider === "cerebras") {
|
|
1539
|
-
|
|
1540
|
-
|
|
1678
|
+
return `'cerebras/llama-3.3-70b'`;
|
|
1679
|
+
} else if (llmProvider === "mistral") {
|
|
1680
|
+
return `'mistral/mistral-medium-2508'`;
|
|
1541
1681
|
}
|
|
1542
|
-
return { providerImport, modelItem };
|
|
1543
1682
|
};
|
|
1544
1683
|
async function writeAgentSample(llmProvider, destPath, addExampleTool) {
|
|
1545
|
-
const
|
|
1684
|
+
const modelString = getModelIdentifier(llmProvider);
|
|
1546
1685
|
const instructions = `
|
|
1547
1686
|
You are a helpful weather assistant that provides accurate weather information and can help planning activities based on the weather.
|
|
1548
1687
|
|
|
@@ -1558,7 +1697,6 @@ async function writeAgentSample(llmProvider, destPath, addExampleTool) {
|
|
|
1558
1697
|
${addExampleTool ? "Use the weatherTool to fetch current weather data." : ""}
|
|
1559
1698
|
`;
|
|
1560
1699
|
const content = `
|
|
1561
|
-
${providerImport}
|
|
1562
1700
|
import { Agent } from '@mastra/core/agent';
|
|
1563
1701
|
import { Memory } from '@mastra/memory';
|
|
1564
1702
|
import { LibSQLStore } from '@mastra/libsql';
|
|
@@ -1567,7 +1705,7 @@ ${addExampleTool ? `import { weatherTool } from '../tools/weather-tool';` : ""}
|
|
|
1567
1705
|
export const weatherAgent = new Agent({
|
|
1568
1706
|
name: 'Weather Agent',
|
|
1569
1707
|
instructions: \`${instructions}\`,
|
|
1570
|
-
model: ${
|
|
1708
|
+
model: ${modelString},
|
|
1571
1709
|
${addExampleTool ? "tools: { weatherTool }," : ""}
|
|
1572
1710
|
memory: new Memory({
|
|
1573
1711
|
storage: new LibSQLStore({
|
|
@@ -1580,8 +1718,8 @@ export const weatherAgent = new Agent({
|
|
|
1580
1718
|
parser: "typescript",
|
|
1581
1719
|
singleQuote: true
|
|
1582
1720
|
});
|
|
1583
|
-
await
|
|
1584
|
-
await
|
|
1721
|
+
await fs5.writeFile(destPath, "");
|
|
1722
|
+
await fs5.writeFile(destPath, formattedContent);
|
|
1585
1723
|
}
|
|
1586
1724
|
async function writeWorkflowSample(destPath) {
|
|
1587
1725
|
const content = `import { createStep, createWorkflow } from '@mastra/core/workflows';
|
|
@@ -1774,7 +1912,7 @@ export { weatherWorkflow };`;
|
|
|
1774
1912
|
semi: true,
|
|
1775
1913
|
singleQuote: true
|
|
1776
1914
|
});
|
|
1777
|
-
await
|
|
1915
|
+
await fs5.writeFile(destPath, formattedContent);
|
|
1778
1916
|
}
|
|
1779
1917
|
async function writeToolSample(destPath) {
|
|
1780
1918
|
const fileService = new FileService();
|
|
@@ -1794,7 +1932,7 @@ async function writeCodeSampleForComponents(llmprovider, component, destPath, im
|
|
|
1794
1932
|
}
|
|
1795
1933
|
var createComponentsDir = async (dirPath, component) => {
|
|
1796
1934
|
const componentPath = dirPath + `/${component}`;
|
|
1797
|
-
await
|
|
1935
|
+
await fsExtra.ensureDir(componentPath);
|
|
1798
1936
|
};
|
|
1799
1937
|
var writeIndexFile = async ({
|
|
1800
1938
|
dirPath,
|
|
@@ -1803,15 +1941,15 @@ var writeIndexFile = async ({
|
|
|
1803
1941
|
addWorkflow
|
|
1804
1942
|
}) => {
|
|
1805
1943
|
const indexPath = dirPath + "/index.ts";
|
|
1806
|
-
const destPath =
|
|
1944
|
+
const destPath = path3.join(indexPath);
|
|
1807
1945
|
try {
|
|
1808
|
-
await
|
|
1946
|
+
await fs5.writeFile(destPath, "");
|
|
1809
1947
|
const filteredExports = [
|
|
1810
1948
|
addWorkflow ? `workflows: { weatherWorkflow },` : "",
|
|
1811
1949
|
addAgent ? `agents: { weatherAgent },` : ""
|
|
1812
1950
|
].filter(Boolean);
|
|
1813
1951
|
if (!addExample) {
|
|
1814
|
-
await
|
|
1952
|
+
await fs5.writeFile(
|
|
1815
1953
|
destPath,
|
|
1816
1954
|
`
|
|
1817
1955
|
import { Mastra } from '@mastra/core';
|
|
@@ -1821,7 +1959,7 @@ export const mastra = new Mastra()
|
|
|
1821
1959
|
);
|
|
1822
1960
|
return;
|
|
1823
1961
|
}
|
|
1824
|
-
await
|
|
1962
|
+
await fs5.writeFile(
|
|
1825
1963
|
destPath,
|
|
1826
1964
|
`
|
|
1827
1965
|
import { Mastra } from '@mastra/core/mastra';
|
|
@@ -1833,13 +1971,21 @@ ${addAgent ? `import { weatherAgent } from './agents/weather-agent';` : ""}
|
|
|
1833
1971
|
export const mastra = new Mastra({
|
|
1834
1972
|
${filteredExports.join("\n ")}
|
|
1835
1973
|
storage: new LibSQLStore({
|
|
1836
|
-
// stores
|
|
1974
|
+
// stores observability, scores, ... into memory storage, if it needs to persist, change to file:../mastra.db
|
|
1837
1975
|
url: ":memory:",
|
|
1838
1976
|
}),
|
|
1839
1977
|
logger: new PinoLogger({
|
|
1840
1978
|
name: 'Mastra',
|
|
1841
1979
|
level: 'info',
|
|
1842
1980
|
}),
|
|
1981
|
+
telemetry: {
|
|
1982
|
+
// Telemetry is deprecated and will be removed in the Nov 4th release
|
|
1983
|
+
enabled: false,
|
|
1984
|
+
},
|
|
1985
|
+
observability: {
|
|
1986
|
+
// Enables DefaultExporter and CloudExporter for AI tracing
|
|
1987
|
+
default: { enabled: true },
|
|
1988
|
+
},
|
|
1843
1989
|
});
|
|
1844
1990
|
`
|
|
1845
1991
|
);
|
|
@@ -1863,27 +2009,28 @@ var getAPIKey = async (provider) => {
|
|
|
1863
2009
|
case "cerebras":
|
|
1864
2010
|
key = "CEREBRAS_API_KEY";
|
|
1865
2011
|
return key;
|
|
2012
|
+
case "mistral":
|
|
2013
|
+
key = "MISTRAL_API_KEY";
|
|
2014
|
+
return key;
|
|
1866
2015
|
default:
|
|
1867
2016
|
return key;
|
|
1868
2017
|
}
|
|
1869
2018
|
};
|
|
1870
|
-
var writeAPIKey = async ({
|
|
1871
|
-
|
|
1872
|
-
apiKey = "your-api-key"
|
|
1873
|
-
}) => {
|
|
2019
|
+
var writeAPIKey = async ({ provider, apiKey }) => {
|
|
2020
|
+
const envFileName = apiKey ? ".env" : ".env.example";
|
|
1874
2021
|
const key = await getAPIKey(provider);
|
|
1875
2022
|
const escapedKey = shellQuote.quote([key]);
|
|
1876
|
-
const escapedApiKey = shellQuote.quote([apiKey]);
|
|
1877
|
-
await
|
|
2023
|
+
const escapedApiKey = shellQuote.quote([apiKey ? apiKey : "your-api-key"]);
|
|
2024
|
+
await exec2(`echo ${escapedKey}=${escapedApiKey} >> ${envFileName}`);
|
|
1878
2025
|
};
|
|
1879
2026
|
var createMastraDir = async (directory) => {
|
|
1880
2027
|
let dir = directory.trim().split("/").filter((item) => item !== "");
|
|
1881
|
-
const dirPath =
|
|
2028
|
+
const dirPath = path3.join(process.cwd(), ...dir, "mastra");
|
|
1882
2029
|
try {
|
|
1883
|
-
await
|
|
2030
|
+
await fs5.access(dirPath);
|
|
1884
2031
|
return { ok: false };
|
|
1885
2032
|
} catch {
|
|
1886
|
-
await
|
|
2033
|
+
await fsExtra.ensureDir(dirPath);
|
|
1887
2034
|
return { ok: true, dirPath };
|
|
1888
2035
|
}
|
|
1889
2036
|
};
|
|
@@ -1895,8 +2042,19 @@ var writeCodeSample = async (dirPath, component, llmProvider, importComponents)
|
|
|
1895
2042
|
throw err;
|
|
1896
2043
|
}
|
|
1897
2044
|
};
|
|
1898
|
-
var
|
|
1899
|
-
|
|
2045
|
+
var LLM_PROVIDERS = [
|
|
2046
|
+
{ value: "openai", label: "OpenAI", hint: "recommended" },
|
|
2047
|
+
{ value: "anthropic", label: "Anthropic" },
|
|
2048
|
+
{ value: "groq", label: "Groq" },
|
|
2049
|
+
{ value: "google", label: "Google" },
|
|
2050
|
+
{ value: "cerebras", label: "Cerebras" },
|
|
2051
|
+
{ value: "mistral", label: "Mistral" }
|
|
2052
|
+
];
|
|
2053
|
+
var interactivePrompt = async (args2 = {}) => {
|
|
2054
|
+
const { skip = {}, options: { showBanner = true } = {} } = args2;
|
|
2055
|
+
if (showBanner) {
|
|
2056
|
+
Ie(color2.inverse(" Mastra Init "));
|
|
2057
|
+
}
|
|
1900
2058
|
const mastraProject = await Ce(
|
|
1901
2059
|
{
|
|
1902
2060
|
directory: () => he({
|
|
@@ -1904,19 +2062,15 @@ var interactivePrompt = async () => {
|
|
|
1904
2062
|
placeholder: "src/",
|
|
1905
2063
|
defaultValue: "src/"
|
|
1906
2064
|
}),
|
|
1907
|
-
llmProvider: () => ve({
|
|
1908
|
-
message: "Select default provider:",
|
|
1909
|
-
options:
|
|
1910
|
-
{ value: "openai", label: "OpenAI", hint: "recommended" },
|
|
1911
|
-
{ value: "anthropic", label: "Anthropic" },
|
|
1912
|
-
{ value: "groq", label: "Groq" },
|
|
1913
|
-
{ value: "google", label: "Google" },
|
|
1914
|
-
{ value: "cerebras", label: "Cerebras" }
|
|
1915
|
-
]
|
|
2065
|
+
llmProvider: () => skip?.llmProvider ? void 0 : ve({
|
|
2066
|
+
message: "Select a default provider:",
|
|
2067
|
+
options: LLM_PROVIDERS
|
|
1916
2068
|
}),
|
|
1917
2069
|
llmApiKey: async ({ results: { llmProvider } }) => {
|
|
2070
|
+
if (skip?.llmApiKey) return void 0;
|
|
2071
|
+
const llmName = LLM_PROVIDERS.find((p6) => p6.value === llmProvider)?.label || "provider";
|
|
1918
2072
|
const keyChoice = await ve({
|
|
1919
|
-
message: `Enter your ${
|
|
2073
|
+
message: `Enter your ${llmName} API key?`,
|
|
1920
2074
|
options: [
|
|
1921
2075
|
{ value: "skip", label: "Skip for now", hint: "default" },
|
|
1922
2076
|
{ value: "enter", label: "Enter API key" }
|
|
@@ -1926,7 +2080,10 @@ var interactivePrompt = async () => {
|
|
|
1926
2080
|
if (keyChoice === "enter") {
|
|
1927
2081
|
return he({
|
|
1928
2082
|
message: "Enter your API key:",
|
|
1929
|
-
placeholder: "sk-..."
|
|
2083
|
+
placeholder: "sk-...",
|
|
2084
|
+
validate: (value) => {
|
|
2085
|
+
if (value.length === 0) return "API key cannot be empty";
|
|
2086
|
+
}
|
|
1930
2087
|
});
|
|
1931
2088
|
}
|
|
1932
2089
|
return void 0;
|
|
@@ -1936,7 +2093,7 @@ var interactivePrompt = async () => {
|
|
|
1936
2093
|
const cursorIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`cursor`);
|
|
1937
2094
|
const vscodeIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`vscode`);
|
|
1938
2095
|
const editor = await ve({
|
|
1939
|
-
message: `Make your
|
|
2096
|
+
message: `Make your IDE into a Mastra expert? (Installs Mastra's MCP server)`,
|
|
1940
2097
|
options: [
|
|
1941
2098
|
{ value: "skip", label: "Skip for now", hint: "default" },
|
|
1942
2099
|
{
|
|
@@ -2017,7 +2174,6 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
2017
2174
|
return mastraProject;
|
|
2018
2175
|
};
|
|
2019
2176
|
var s = Y();
|
|
2020
|
-
var exec2 = util.promisify(child_process.exec);
|
|
2021
2177
|
var init = async ({
|
|
2022
2178
|
directory,
|
|
2023
2179
|
addExample = false,
|
|
@@ -2065,11 +2221,6 @@ var init = async ({
|
|
|
2065
2221
|
}
|
|
2066
2222
|
}
|
|
2067
2223
|
const key = await getAPIKey(llmProvider || "openai");
|
|
2068
|
-
const aiSdkPackage = getAISDKPackage(llmProvider);
|
|
2069
|
-
const depsService = new DepsService();
|
|
2070
|
-
const pm = depsService.packageManager;
|
|
2071
|
-
const installCommand = getPackageManagerInstallCommand(pm);
|
|
2072
|
-
await exec2(`${pm} ${installCommand} ${aiSdkPackage}`);
|
|
2073
2224
|
if (configureEditorWithDocsMCP) {
|
|
2074
2225
|
await installMastraDocsMCPServer({
|
|
2075
2226
|
editor: configureEditorWithDocsMCP,
|
|
@@ -2123,9 +2274,9 @@ var execWithTimeout = async (command, timeoutMs) => {
|
|
|
2123
2274
|
}
|
|
2124
2275
|
};
|
|
2125
2276
|
async function installMastraDependency(pm, dependency, versionTag, isDev, timeout) {
|
|
2126
|
-
let installCommand =
|
|
2277
|
+
let installCommand = getPackageManagerAddCommand(pm);
|
|
2127
2278
|
if (isDev) {
|
|
2128
|
-
installCommand = `${installCommand}
|
|
2279
|
+
installCommand = `${installCommand} -D`;
|
|
2129
2280
|
}
|
|
2130
2281
|
try {
|
|
2131
2282
|
await execWithTimeout(`${pm} ${installCommand} ${dependency}${versionTag}`, timeout);
|
|
@@ -2147,23 +2298,39 @@ async function installMastraDependency(pm, dependency, versionTag, isDev, timeou
|
|
|
2147
2298
|
var createMastraProject = async ({
|
|
2148
2299
|
projectName: name,
|
|
2149
2300
|
createVersionTag,
|
|
2150
|
-
timeout
|
|
2301
|
+
timeout,
|
|
2302
|
+
llmProvider,
|
|
2303
|
+
llmApiKey,
|
|
2304
|
+
needsInteractive
|
|
2151
2305
|
}) => {
|
|
2152
2306
|
Ie(color2.inverse(" Mastra Create "));
|
|
2153
2307
|
const projectName = name ?? await he({
|
|
2154
2308
|
message: "What do you want to name your project?",
|
|
2155
2309
|
placeholder: "my-mastra-app",
|
|
2156
|
-
defaultValue: "my-mastra-app"
|
|
2310
|
+
defaultValue: "my-mastra-app",
|
|
2311
|
+
validate: (value) => {
|
|
2312
|
+
if (value.length === 0) return "Project name cannot be empty";
|
|
2313
|
+
if (fs4__default__default.existsSync(value)) {
|
|
2314
|
+
return `A directory named "${value}" already exists. Please choose a different name.`;
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2157
2317
|
});
|
|
2158
2318
|
if (pD(projectName)) {
|
|
2159
2319
|
xe("Operation cancelled");
|
|
2160
2320
|
process.exit(0);
|
|
2161
2321
|
}
|
|
2322
|
+
let result;
|
|
2323
|
+
if (needsInteractive) {
|
|
2324
|
+
result = await interactivePrompt({
|
|
2325
|
+
options: { showBanner: false },
|
|
2326
|
+
skip: { llmProvider: llmProvider !== void 0, llmApiKey: llmApiKey !== void 0 }
|
|
2327
|
+
});
|
|
2328
|
+
}
|
|
2162
2329
|
const s2 = Y();
|
|
2163
2330
|
try {
|
|
2164
2331
|
s2.start("Creating project");
|
|
2165
2332
|
try {
|
|
2166
|
-
await
|
|
2333
|
+
await fs5.mkdir(projectName);
|
|
2167
2334
|
} catch (error) {
|
|
2168
2335
|
if (error instanceof Error && "code" in error && error.code === "EEXIST") {
|
|
2169
2336
|
s2.stop(`A directory named "${projectName}" already exists. Please choose a different name.`);
|
|
@@ -2175,7 +2342,7 @@ var createMastraProject = async ({
|
|
|
2175
2342
|
}
|
|
2176
2343
|
process.chdir(projectName);
|
|
2177
2344
|
const pm = getPackageManager();
|
|
2178
|
-
const installCommand =
|
|
2345
|
+
const installCommand = getPackageManagerAddCommand(pm);
|
|
2179
2346
|
s2.message("Initializing project structure");
|
|
2180
2347
|
try {
|
|
2181
2348
|
await exec3(`npm init -y`);
|
|
@@ -2195,7 +2362,7 @@ var createMastraProject = async ({
|
|
|
2195
2362
|
s2.stop("Project structure created");
|
|
2196
2363
|
s2.start(`Installing ${pm} dependencies`);
|
|
2197
2364
|
try {
|
|
2198
|
-
await exec3(`${pm} ${installCommand} zod`);
|
|
2365
|
+
await exec3(`${pm} ${installCommand} zod@^3`);
|
|
2199
2366
|
await exec3(`${pm} ${installCommand} typescript @types/node --save-dev`);
|
|
2200
2367
|
await exec3(`echo '{
|
|
2201
2368
|
"compilerOptions": {
|
|
@@ -2219,15 +2386,15 @@ var createMastraProject = async ({
|
|
|
2219
2386
|
);
|
|
2220
2387
|
}
|
|
2221
2388
|
s2.stop(`${pm} dependencies installed`);
|
|
2222
|
-
s2.start("Installing
|
|
2389
|
+
s2.start("Installing Mastra CLI");
|
|
2223
2390
|
const versionTag = createVersionTag ? `@${createVersionTag}` : "@latest";
|
|
2224
2391
|
try {
|
|
2225
2392
|
await installMastraDependency(pm, "mastra", versionTag, true, timeout);
|
|
2226
2393
|
} catch (error) {
|
|
2227
2394
|
throw new Error(`Failed to install Mastra CLI: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2228
2395
|
}
|
|
2229
|
-
s2.stop("
|
|
2230
|
-
s2.start("Installing dependencies");
|
|
2396
|
+
s2.stop("Mastra CLI installed");
|
|
2397
|
+
s2.start("Installing Mastra dependencies");
|
|
2231
2398
|
try {
|
|
2232
2399
|
await installMastraDependency(pm, "@mastra/core", versionTag, false, timeout);
|
|
2233
2400
|
await installMastraDependency(pm, "@mastra/libsql", versionTag, false, timeout);
|
|
@@ -2253,8 +2420,8 @@ var createMastraProject = async ({
|
|
|
2253
2420
|
}
|
|
2254
2421
|
s2.stop(".gitignore added");
|
|
2255
2422
|
Se("Project created successfully");
|
|
2256
|
-
console.
|
|
2257
|
-
return { projectName };
|
|
2423
|
+
console.info("");
|
|
2424
|
+
return { projectName, result };
|
|
2258
2425
|
} catch (error) {
|
|
2259
2426
|
s2.stop();
|
|
2260
2427
|
const errorMessage = error instanceof Error ? error.message : "An unexpected error occurred";
|
|
@@ -2263,14 +2430,21 @@ var createMastraProject = async ({
|
|
|
2263
2430
|
}
|
|
2264
2431
|
};
|
|
2265
2432
|
var create = async (args2) => {
|
|
2266
|
-
|
|
2433
|
+
if (args2.template !== void 0) {
|
|
2434
|
+
await createFromTemplate({ ...args2, injectedAnalytics: args2.analytics });
|
|
2435
|
+
return;
|
|
2436
|
+
}
|
|
2437
|
+
const needsInteractive = args2.components === void 0 || args2.llmProvider === void 0 || args2.addExample === void 0;
|
|
2438
|
+
const { projectName, result } = await createMastraProject({
|
|
2267
2439
|
projectName: args2?.projectName,
|
|
2268
2440
|
createVersionTag: args2?.createVersionTag,
|
|
2269
|
-
timeout: args2?.timeout
|
|
2441
|
+
timeout: args2?.timeout,
|
|
2442
|
+
llmProvider: args2?.llmProvider,
|
|
2443
|
+
llmApiKey: args2?.llmApiKey,
|
|
2444
|
+
needsInteractive
|
|
2270
2445
|
});
|
|
2271
2446
|
const directory = args2.directory || "src/";
|
|
2272
|
-
if (
|
|
2273
|
-
const result = await interactivePrompt();
|
|
2447
|
+
if (needsInteractive && result) {
|
|
2274
2448
|
await init({
|
|
2275
2449
|
...result,
|
|
2276
2450
|
llmApiKey: result?.llmApiKey,
|
|
@@ -2300,18 +2474,172 @@ var postCreate = ({ projectName }) => {
|
|
|
2300
2474
|
${color2.cyan(`${packageManager} run dev`)}
|
|
2301
2475
|
`);
|
|
2302
2476
|
};
|
|
2477
|
+
function isGitHubUrl(url) {
|
|
2478
|
+
try {
|
|
2479
|
+
const parsedUrl = new URL(url);
|
|
2480
|
+
return parsedUrl.hostname === "github.com" && parsedUrl.pathname.split("/").length >= 3;
|
|
2481
|
+
} catch {
|
|
2482
|
+
return false;
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
async function validateGitHubProject(githubUrl) {
|
|
2486
|
+
const errors = [];
|
|
2487
|
+
try {
|
|
2488
|
+
const urlParts = new URL(githubUrl).pathname.split("/").filter(Boolean);
|
|
2489
|
+
const owner = urlParts[0];
|
|
2490
|
+
const repo = urlParts[1]?.replace(".git", "");
|
|
2491
|
+
if (!owner || !repo) {
|
|
2492
|
+
throw new Error("Invalid GitHub URL format");
|
|
2493
|
+
}
|
|
2494
|
+
const branches = ["main", "master"];
|
|
2495
|
+
let packageJsonContent = null;
|
|
2496
|
+
let indexContent = null;
|
|
2497
|
+
for (const branch of branches) {
|
|
2498
|
+
try {
|
|
2499
|
+
const packageJsonUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/package.json`;
|
|
2500
|
+
const packageJsonResponse = await fetch(packageJsonUrl);
|
|
2501
|
+
if (packageJsonResponse.ok) {
|
|
2502
|
+
packageJsonContent = await packageJsonResponse.text();
|
|
2503
|
+
const indexUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/src/mastra/index.ts`;
|
|
2504
|
+
const indexResponse = await fetch(indexUrl);
|
|
2505
|
+
if (indexResponse.ok) {
|
|
2506
|
+
indexContent = await indexResponse.text();
|
|
2507
|
+
}
|
|
2508
|
+
break;
|
|
2509
|
+
}
|
|
2510
|
+
} catch {
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
if (!packageJsonContent) {
|
|
2514
|
+
errors.push("Could not fetch package.json from repository");
|
|
2515
|
+
return { isValid: false, errors };
|
|
2516
|
+
}
|
|
2517
|
+
try {
|
|
2518
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
2519
|
+
const hasMastraCore = packageJson.dependencies?.["@mastra/core"] || packageJson.devDependencies?.["@mastra/core"] || packageJson.peerDependencies?.["@mastra/core"];
|
|
2520
|
+
if (!hasMastraCore) {
|
|
2521
|
+
errors.push("Missing @mastra/core dependency in package.json");
|
|
2522
|
+
}
|
|
2523
|
+
} catch {
|
|
2524
|
+
errors.push("Invalid package.json format");
|
|
2525
|
+
}
|
|
2526
|
+
if (!indexContent) {
|
|
2527
|
+
errors.push("Missing src/mastra/index.ts file");
|
|
2528
|
+
} else {
|
|
2529
|
+
const hasMastraExport = indexContent.includes("export") && (indexContent.includes("new Mastra") || indexContent.includes("Mastra("));
|
|
2530
|
+
if (!hasMastraExport) {
|
|
2531
|
+
errors.push("src/mastra/index.ts does not export a Mastra instance");
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
return { isValid: errors.length === 0, errors };
|
|
2535
|
+
} catch (error) {
|
|
2536
|
+
errors.push(`Failed to validate GitHub repository: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2537
|
+
return { isValid: false, errors };
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
async function createFromGitHubUrl(url) {
|
|
2541
|
+
const urlParts = new URL(url).pathname.split("/").filter(Boolean);
|
|
2542
|
+
const owner = urlParts[0] || "unknown";
|
|
2543
|
+
const repo = urlParts[1] || "unknown";
|
|
2544
|
+
return {
|
|
2545
|
+
githubUrl: url,
|
|
2546
|
+
title: `${owner}/${repo}`,
|
|
2547
|
+
slug: repo,
|
|
2548
|
+
agents: [],
|
|
2549
|
+
mcp: [],
|
|
2550
|
+
tools: [],
|
|
2551
|
+
networks: [],
|
|
2552
|
+
workflows: []
|
|
2553
|
+
};
|
|
2554
|
+
}
|
|
2555
|
+
async function createFromTemplate(args2) {
|
|
2556
|
+
let selectedTemplate;
|
|
2557
|
+
if (args2.template === true) {
|
|
2558
|
+
const templates = await loadTemplates();
|
|
2559
|
+
const selected = await selectTemplate(templates);
|
|
2560
|
+
if (!selected) {
|
|
2561
|
+
M.info("No template selected. Exiting.");
|
|
2562
|
+
return;
|
|
2563
|
+
}
|
|
2564
|
+
selectedTemplate = selected;
|
|
2565
|
+
} else if (args2.template && typeof args2.template === "string") {
|
|
2566
|
+
if (isGitHubUrl(args2.template)) {
|
|
2567
|
+
const spinner5 = Y();
|
|
2568
|
+
spinner5.start("Validating GitHub repository...");
|
|
2569
|
+
const validation = await validateGitHubProject(args2.template);
|
|
2570
|
+
if (!validation.isValid) {
|
|
2571
|
+
spinner5.stop("Validation failed");
|
|
2572
|
+
M.error("This does not appear to be a valid Mastra project:");
|
|
2573
|
+
validation.errors.forEach((error) => M.error(` - ${error}`));
|
|
2574
|
+
throw new Error("Invalid Mastra project");
|
|
2575
|
+
}
|
|
2576
|
+
spinner5.stop("Valid Mastra project \u2713");
|
|
2577
|
+
selectedTemplate = await createFromGitHubUrl(args2.template);
|
|
2578
|
+
} else {
|
|
2579
|
+
const templates = await loadTemplates();
|
|
2580
|
+
const found = findTemplateByName(templates, args2.template);
|
|
2581
|
+
if (!found) {
|
|
2582
|
+
M.error(`Template "${args2.template}" not found. Available templates:`);
|
|
2583
|
+
templates.forEach((t) => M.info(` - ${t.title} (use: ${t.slug.replace("template-", "")})`));
|
|
2584
|
+
throw new Error(`Template "${args2.template}" not found`);
|
|
2585
|
+
}
|
|
2586
|
+
selectedTemplate = found;
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
if (!selectedTemplate) {
|
|
2590
|
+
throw new Error("No template selected");
|
|
2591
|
+
}
|
|
2592
|
+
let projectName = args2.projectName;
|
|
2593
|
+
if (!projectName) {
|
|
2594
|
+
const defaultName = getDefaultProjectName(selectedTemplate);
|
|
2595
|
+
const response = await he({
|
|
2596
|
+
message: "What is your project name?",
|
|
2597
|
+
defaultValue: defaultName,
|
|
2598
|
+
placeholder: defaultName
|
|
2599
|
+
});
|
|
2600
|
+
if (pD(response)) {
|
|
2601
|
+
M.info("Project creation cancelled.");
|
|
2602
|
+
return;
|
|
2603
|
+
}
|
|
2604
|
+
projectName = response;
|
|
2605
|
+
}
|
|
2606
|
+
try {
|
|
2607
|
+
const analytics = args2.injectedAnalytics || getAnalytics();
|
|
2608
|
+
if (analytics) {
|
|
2609
|
+
analytics.trackEvent("cli_template_used", {
|
|
2610
|
+
template_slug: selectedTemplate.slug,
|
|
2611
|
+
template_title: selectedTemplate.title
|
|
2612
|
+
});
|
|
2613
|
+
}
|
|
2614
|
+
const projectPath = await cloneTemplate({
|
|
2615
|
+
template: selectedTemplate,
|
|
2616
|
+
projectName
|
|
2617
|
+
});
|
|
2618
|
+
await installDependencies(projectPath);
|
|
2619
|
+
Me(`
|
|
2620
|
+
${color2.green("Mastra template installed!")}
|
|
2621
|
+
|
|
2622
|
+
Add the necessary environment
|
|
2623
|
+
variables in your ${color2.cyan(".env")} file
|
|
2624
|
+
`);
|
|
2625
|
+
postCreate({ projectName });
|
|
2626
|
+
} catch (error) {
|
|
2627
|
+
M.error(`Failed to create project from template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2628
|
+
throw error;
|
|
2629
|
+
}
|
|
2630
|
+
}
|
|
2303
2631
|
|
|
2304
2632
|
async function getPackageVersion() {
|
|
2305
2633
|
const __filename = fileURLToPath(import.meta.url);
|
|
2306
2634
|
const __dirname = dirname(__filename);
|
|
2307
|
-
const pkgJsonPath =
|
|
2308
|
-
const content = await fsExtra.readJSON(pkgJsonPath);
|
|
2635
|
+
const pkgJsonPath = path3.join(__dirname, "..", "package.json");
|
|
2636
|
+
const content = await fsExtra$1.readJSON(pkgJsonPath);
|
|
2309
2637
|
return content.version;
|
|
2310
2638
|
}
|
|
2311
2639
|
async function getCreateVersionTag() {
|
|
2312
2640
|
try {
|
|
2313
2641
|
const pkgPath = fileURLToPath(import.meta.resolve("create-mastra/package.json"));
|
|
2314
|
-
const json = await fsExtra.readJSON(pkgPath);
|
|
2642
|
+
const json = await fsExtra$1.readJSON(pkgPath);
|
|
2315
2643
|
const { stdout } = await execa("npm", ["dist-tag", "create-mastra"]);
|
|
2316
2644
|
const tagLine = stdout.split("\n").find((distLine) => distLine.endsWith(`: ${json.version}`));
|
|
2317
2645
|
const tag = tagLine ? tagLine.split(":")[0].trim() : "latest";
|
|
@@ -2335,14 +2663,17 @@ program.version(`${version}`, "-v, --version").description(`create-mastra ${vers
|
|
|
2335
2663
|
analytics.trackCommand({
|
|
2336
2664
|
command: "version"
|
|
2337
2665
|
});
|
|
2338
|
-
console.
|
|
2666
|
+
console.info(`create-mastra ${version}`);
|
|
2339
2667
|
} catch {
|
|
2340
2668
|
}
|
|
2341
2669
|
});
|
|
2342
2670
|
program.name("create-mastra").description("Create a new Mastra project").argument("[project-name]", "Directory name of the project").option(
|
|
2343
2671
|
"-p, --project-name <string>",
|
|
2344
2672
|
"Project name that will be used in package.json and as the project directory name."
|
|
2345
|
-
).option("--default", "Quick start with defaults(src, OpenAI, examples)").option("-c, --components <components>", "Comma-separated list of components (agents, tools, workflows)").option("-l, --llm <model-provider>", "Default model provider (openai, anthropic, groq, google, or cerebras)").option("-k, --llm-api-key <api-key>", "API key for the model provider").option("-e, --example", "Include example code").option("-n, --no-example", "Do not include example code").option("-t, --timeout [timeout]", "Configurable timeout for package installation, defaults to 60000 ms").option("-d, --dir <directory>", "Target directory for Mastra source code (default: src/)").option("-m, --mcp <mcp>", "MCP Server for code editor (cursor, cursor-global, windsurf, vscode)").
|
|
2673
|
+
).option("--default", "Quick start with defaults (src, OpenAI, examples)").option("-c, --components <components>", "Comma-separated list of components (agents, tools, workflows)").option("-l, --llm <model-provider>", "Default model provider (openai, anthropic, groq, google, or cerebras)").option("-k, --llm-api-key <api-key>", "API key for the model provider").option("-e, --example", "Include example code").option("-n, --no-example", "Do not include example code").option("-t, --timeout [timeout]", "Configurable timeout for package installation, defaults to 60000 ms").option("-d, --dir <directory>", "Target directory for Mastra source code (default: src/)").option("-m, --mcp <mcp>", "MCP Server for code editor (cursor, cursor-global, windsurf, vscode)").option(
|
|
2674
|
+
"--template [template-name]",
|
|
2675
|
+
"Create project from a template (use template name, public GitHub URL, or leave blank to select from list)"
|
|
2676
|
+
).action(async (projectNameArg, args) => {
|
|
2346
2677
|
const projectName = projectNameArg || args.projectName;
|
|
2347
2678
|
const timeout = args?.timeout ? args?.timeout === true ? 6e4 : parseInt(args?.timeout, 10) : void 0;
|
|
2348
2679
|
if (args.default) {
|
|
@@ -2353,7 +2684,9 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
|
|
|
2353
2684
|
createVersionTag,
|
|
2354
2685
|
timeout,
|
|
2355
2686
|
mcpServer: args.mcp,
|
|
2356
|
-
directory: "src/"
|
|
2687
|
+
directory: "src/",
|
|
2688
|
+
template: args.template,
|
|
2689
|
+
analytics
|
|
2357
2690
|
});
|
|
2358
2691
|
return;
|
|
2359
2692
|
}
|
|
@@ -2361,12 +2694,14 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
|
|
|
2361
2694
|
components: args.components ? args.components.split(",") : [],
|
|
2362
2695
|
llmProvider: args.llm,
|
|
2363
2696
|
addExample: args.example,
|
|
2364
|
-
llmApiKey: args
|
|
2697
|
+
llmApiKey: args.llmApiKey,
|
|
2365
2698
|
createVersionTag,
|
|
2366
2699
|
timeout,
|
|
2367
2700
|
projectName,
|
|
2368
2701
|
directory: args.dir,
|
|
2369
|
-
mcpServer: args.mcp
|
|
2702
|
+
mcpServer: args.mcp,
|
|
2703
|
+
template: args.template,
|
|
2704
|
+
analytics
|
|
2370
2705
|
});
|
|
2371
2706
|
});
|
|
2372
2707
|
program.parse(process.argv);
|