create-mastra 0.0.0-message-list-update-20250715150321 → 0.0.0-monorepo-binary-20251013210052
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 +2003 -0
- package/README.md +2 -8
- package/dist/index.js +531 -191
- package/dist/index.js.map +1 -1
- package/dist/templates/dev.entry.js +12 -2
- package/package.json +18 -10
- 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) {
|
|
@@ -704,13 +724,18 @@ const format = (open, close) => {
|
|
|
704
724
|
// Handle nested colors.
|
|
705
725
|
|
|
706
726
|
// We could have done this, but it's too slow (as of Node.js 22).
|
|
707
|
-
// return openCode + string.replaceAll(closeCode, openCode) + closeCode;
|
|
727
|
+
// return openCode + string.replaceAll(closeCode, (close === 22 ? closeCode : '') + openCode) + closeCode;
|
|
708
728
|
|
|
709
729
|
let result = openCode;
|
|
710
730
|
let lastIndex = 0;
|
|
711
731
|
|
|
732
|
+
// SGR 22 resets both bold (1) and dim (2). When we encounter a nested
|
|
733
|
+
// close for styles that use 22, we need to re-open the outer style.
|
|
734
|
+
const reopenOnNestedClose = close === 22;
|
|
735
|
+
const replaceCode = (reopenOnNestedClose ? closeCode : '') + openCode;
|
|
736
|
+
|
|
712
737
|
while (index !== -1) {
|
|
713
|
-
result += string.slice(lastIndex, index) +
|
|
738
|
+
result += string.slice(lastIndex, index) + replaceCode;
|
|
714
739
|
lastIndex = index + closeCode.length;
|
|
715
740
|
index = string.indexOf(closeCode, lastIndex);
|
|
716
741
|
}
|
|
@@ -1153,6 +1178,197 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1153
1178
|
}
|
|
1154
1179
|
};
|
|
1155
1180
|
|
|
1181
|
+
function getPackageManager() {
|
|
1182
|
+
const userAgent = process.env.npm_config_user_agent || "";
|
|
1183
|
+
const execPath = process.env.npm_execpath || "";
|
|
1184
|
+
if (userAgent.includes("yarn")) {
|
|
1185
|
+
return "yarn";
|
|
1186
|
+
}
|
|
1187
|
+
if (userAgent.includes("pnpm")) {
|
|
1188
|
+
return "pnpm";
|
|
1189
|
+
}
|
|
1190
|
+
if (userAgent.includes("npm")) {
|
|
1191
|
+
return "npm";
|
|
1192
|
+
}
|
|
1193
|
+
if (execPath.includes("yarn")) {
|
|
1194
|
+
return "yarn";
|
|
1195
|
+
}
|
|
1196
|
+
if (execPath.includes("pnpm")) {
|
|
1197
|
+
return "pnpm";
|
|
1198
|
+
}
|
|
1199
|
+
if (execPath.includes("npm")) {
|
|
1200
|
+
return "npm";
|
|
1201
|
+
}
|
|
1202
|
+
return "npm";
|
|
1203
|
+
}
|
|
1204
|
+
var logger = new PinoLogger({
|
|
1205
|
+
name: "Mastra CLI",
|
|
1206
|
+
level: "info"
|
|
1207
|
+
});
|
|
1208
|
+
var exec = util.promisify(child_process.exec);
|
|
1209
|
+
async function cloneTemplate(options) {
|
|
1210
|
+
const { template, projectName, targetDir } = options;
|
|
1211
|
+
const projectPath = targetDir ? path3.resolve(targetDir, projectName) : path3.resolve(projectName);
|
|
1212
|
+
const spinner5 = yoctoSpinner({ text: `Cloning template "${template.title}"...` }).start();
|
|
1213
|
+
try {
|
|
1214
|
+
if (await directoryExists(projectPath)) {
|
|
1215
|
+
spinner5.error(`Directory ${projectName} already exists`);
|
|
1216
|
+
throw new Error(`Directory ${projectName} already exists`);
|
|
1217
|
+
}
|
|
1218
|
+
await cloneRepositoryWithoutGit(template.githubUrl, projectPath);
|
|
1219
|
+
await updatePackageJson(projectPath, projectName);
|
|
1220
|
+
const envExamplePath = path3.join(projectPath, ".env.example");
|
|
1221
|
+
if (await fileExists(envExamplePath)) {
|
|
1222
|
+
await fs5.copyFile(envExamplePath, path3.join(projectPath, ".env"));
|
|
1223
|
+
}
|
|
1224
|
+
spinner5.success(`Template "${template.title}" cloned successfully to ${projectName}`);
|
|
1225
|
+
return projectPath;
|
|
1226
|
+
} catch (error) {
|
|
1227
|
+
spinner5.error(`Failed to clone template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1228
|
+
throw error;
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
async function directoryExists(dirPath) {
|
|
1232
|
+
try {
|
|
1233
|
+
const stat = await fs5.stat(dirPath);
|
|
1234
|
+
return stat.isDirectory();
|
|
1235
|
+
} catch {
|
|
1236
|
+
return false;
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
async function fileExists(filePath) {
|
|
1240
|
+
try {
|
|
1241
|
+
const stat = await fs5.stat(filePath);
|
|
1242
|
+
return stat.isFile();
|
|
1243
|
+
} catch {
|
|
1244
|
+
return false;
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
async function cloneRepositoryWithoutGit(repoUrl, targetPath) {
|
|
1248
|
+
await fs5.mkdir(targetPath, { recursive: true });
|
|
1249
|
+
try {
|
|
1250
|
+
const degitRepo = repoUrl.replace("https://github.com/", "");
|
|
1251
|
+
const degitCommand = shellQuote.quote(["npx", "degit", degitRepo, targetPath]);
|
|
1252
|
+
await exec(degitCommand, {
|
|
1253
|
+
cwd: process.cwd()
|
|
1254
|
+
});
|
|
1255
|
+
} catch {
|
|
1256
|
+
try {
|
|
1257
|
+
const gitCommand = shellQuote.quote(["git", "clone", repoUrl, targetPath]);
|
|
1258
|
+
await exec(gitCommand, {
|
|
1259
|
+
cwd: process.cwd()
|
|
1260
|
+
});
|
|
1261
|
+
const gitDir = path3.join(targetPath, ".git");
|
|
1262
|
+
if (await directoryExists(gitDir)) {
|
|
1263
|
+
await fs5.rm(gitDir, { recursive: true, force: true });
|
|
1264
|
+
}
|
|
1265
|
+
} catch (gitError) {
|
|
1266
|
+
throw new Error(`Failed to clone repository: ${gitError instanceof Error ? gitError.message : "Unknown error"}`);
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
async function updatePackageJson(projectPath, projectName) {
|
|
1271
|
+
const packageJsonPath = path3.join(projectPath, "package.json");
|
|
1272
|
+
try {
|
|
1273
|
+
const packageJsonContent = await fs5.readFile(packageJsonPath, "utf-8");
|
|
1274
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
1275
|
+
packageJson.name = projectName;
|
|
1276
|
+
await fs5.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf-8");
|
|
1277
|
+
} catch (error) {
|
|
1278
|
+
logger.warn(`Could not update package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
async function installDependencies(projectPath, packageManager) {
|
|
1282
|
+
const spinner5 = yoctoSpinner({ text: "Installing dependencies..." }).start();
|
|
1283
|
+
try {
|
|
1284
|
+
const pm = packageManager || getPackageManager();
|
|
1285
|
+
const installCommand = shellQuote.quote([pm, "install"]);
|
|
1286
|
+
await exec(installCommand, {
|
|
1287
|
+
cwd: projectPath
|
|
1288
|
+
});
|
|
1289
|
+
spinner5.success("Dependencies installed successfully");
|
|
1290
|
+
} catch (error) {
|
|
1291
|
+
spinner5.error(`Failed to install dependencies: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1292
|
+
throw error;
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
var TEMPLATES_API_URL = process.env.MASTRA_TEMPLATES_API_URL || "https://mastra.ai/api/templates.json";
|
|
1296
|
+
async function loadTemplates() {
|
|
1297
|
+
try {
|
|
1298
|
+
const response = await fetch(TEMPLATES_API_URL);
|
|
1299
|
+
if (!response.ok) {
|
|
1300
|
+
throw new Error(`Failed to fetch templates: ${response.statusText}`);
|
|
1301
|
+
}
|
|
1302
|
+
const templates = await response.json();
|
|
1303
|
+
return templates;
|
|
1304
|
+
} catch (error) {
|
|
1305
|
+
console.error("Error loading templates:", error);
|
|
1306
|
+
throw new Error("Failed to load templates. Please check your internet connection and try again.");
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
function pluralize(count, singular, plural) {
|
|
1310
|
+
return count === 1 ? singular : plural || `${singular}s`;
|
|
1311
|
+
}
|
|
1312
|
+
async function selectTemplate(templates) {
|
|
1313
|
+
const choices = templates.map((template) => {
|
|
1314
|
+
const parts = [];
|
|
1315
|
+
if (template.agents?.length) {
|
|
1316
|
+
parts.push(`${template.agents.length} ${pluralize(template.agents.length, "agent")}`);
|
|
1317
|
+
}
|
|
1318
|
+
if (template.tools?.length) {
|
|
1319
|
+
parts.push(`${template.tools.length} ${pluralize(template.tools.length, "tool")}`);
|
|
1320
|
+
}
|
|
1321
|
+
if (template.workflows?.length) {
|
|
1322
|
+
parts.push(`${template.workflows.length} ${pluralize(template.workflows.length, "workflow")}`);
|
|
1323
|
+
}
|
|
1324
|
+
if (template.mcp?.length) {
|
|
1325
|
+
parts.push(`${template.mcp.length} ${pluralize(template.mcp.length, "MCP server")}`);
|
|
1326
|
+
}
|
|
1327
|
+
if (template.networks?.length) {
|
|
1328
|
+
parts.push(`${template.networks.length} ${pluralize(template.networks.length, "agent network")}`);
|
|
1329
|
+
}
|
|
1330
|
+
return {
|
|
1331
|
+
value: template,
|
|
1332
|
+
label: template.title,
|
|
1333
|
+
hint: parts.join(", ") || "Template components"
|
|
1334
|
+
};
|
|
1335
|
+
});
|
|
1336
|
+
const selected = await ve({
|
|
1337
|
+
message: "Select a template:",
|
|
1338
|
+
options: choices
|
|
1339
|
+
});
|
|
1340
|
+
if (pD(selected)) {
|
|
1341
|
+
return null;
|
|
1342
|
+
}
|
|
1343
|
+
return selected;
|
|
1344
|
+
}
|
|
1345
|
+
function findTemplateByName(templates, templateName) {
|
|
1346
|
+
let template = templates.find((t) => t.slug === templateName);
|
|
1347
|
+
if (template) return template;
|
|
1348
|
+
const slugWithPrefix = `template-${templateName}`;
|
|
1349
|
+
template = templates.find((t) => t.slug === slugWithPrefix);
|
|
1350
|
+
if (template) return template;
|
|
1351
|
+
template = templates.find((t) => t.title.toLowerCase() === templateName.toLowerCase());
|
|
1352
|
+
if (template) return template;
|
|
1353
|
+
return null;
|
|
1354
|
+
}
|
|
1355
|
+
function getDefaultProjectName(template) {
|
|
1356
|
+
return template.slug.replace(/^template-/, "");
|
|
1357
|
+
}
|
|
1358
|
+
function getPackageManagerAddCommand(pm) {
|
|
1359
|
+
switch (pm) {
|
|
1360
|
+
case "npm":
|
|
1361
|
+
return "install --audit=false --fund=false --loglevel=error --progress=false --update-notifier=false";
|
|
1362
|
+
case "yarn":
|
|
1363
|
+
return "add";
|
|
1364
|
+
case "pnpm":
|
|
1365
|
+
return "add --loglevel=error";
|
|
1366
|
+
case "bun":
|
|
1367
|
+
return "add";
|
|
1368
|
+
default:
|
|
1369
|
+
return "add";
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1156
1372
|
var DepsService = class {
|
|
1157
1373
|
packageManager;
|
|
1158
1374
|
constructor() {
|
|
@@ -1161,11 +1377,11 @@ var DepsService = class {
|
|
|
1161
1377
|
findLockFile(dir) {
|
|
1162
1378
|
const lockFiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lock"];
|
|
1163
1379
|
for (const file of lockFiles) {
|
|
1164
|
-
if (
|
|
1380
|
+
if (fs4__default__default.existsSync(path3.join(dir, file))) {
|
|
1165
1381
|
return file;
|
|
1166
1382
|
}
|
|
1167
1383
|
}
|
|
1168
|
-
const parentDir =
|
|
1384
|
+
const parentDir = path3.resolve(dir, "..");
|
|
1169
1385
|
if (parentDir !== dir) {
|
|
1170
1386
|
return this.findLockFile(parentDir);
|
|
1171
1387
|
}
|
|
@@ -1187,14 +1403,10 @@ var DepsService = class {
|
|
|
1187
1403
|
}
|
|
1188
1404
|
}
|
|
1189
1405
|
async installPackages(packages) {
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
runCommand = `${this.packageManager} i`;
|
|
1193
|
-
} else {
|
|
1194
|
-
runCommand = `${this.packageManager} add`;
|
|
1195
|
-
}
|
|
1406
|
+
const pm = this.packageManager;
|
|
1407
|
+
const installCommand = getPackageManagerAddCommand(pm);
|
|
1196
1408
|
const packageList = packages.join(" ");
|
|
1197
|
-
return execa(`${
|
|
1409
|
+
return execa(`${pm} ${installCommand} ${packageList}`, {
|
|
1198
1410
|
all: true,
|
|
1199
1411
|
shell: true,
|
|
1200
1412
|
stdio: "inherit"
|
|
@@ -1202,13 +1414,13 @@ var DepsService = class {
|
|
|
1202
1414
|
}
|
|
1203
1415
|
async checkDependencies(dependencies) {
|
|
1204
1416
|
try {
|
|
1205
|
-
const packageJsonPath =
|
|
1417
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1206
1418
|
try {
|
|
1207
|
-
await
|
|
1419
|
+
await fs5.access(packageJsonPath);
|
|
1208
1420
|
} catch {
|
|
1209
1421
|
return "No package.json file found in the current directory";
|
|
1210
1422
|
}
|
|
1211
|
-
const packageJson = JSON.parse(await
|
|
1423
|
+
const packageJson = JSON.parse(await fs5.readFile(packageJsonPath, "utf-8"));
|
|
1212
1424
|
for (const dependency of dependencies) {
|
|
1213
1425
|
if (!packageJson.dependencies || !packageJson.dependencies[dependency]) {
|
|
1214
1426
|
return `Please install ${dependency} before running this command (${this.packageManager} install ${dependency})`;
|
|
@@ -1222,65 +1434,23 @@ var DepsService = class {
|
|
|
1222
1434
|
}
|
|
1223
1435
|
async getProjectName() {
|
|
1224
1436
|
try {
|
|
1225
|
-
const packageJsonPath =
|
|
1226
|
-
const packageJson = await
|
|
1437
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1438
|
+
const packageJson = await fs5.readFile(packageJsonPath, "utf-8");
|
|
1227
1439
|
const pkg = JSON.parse(packageJson);
|
|
1228
1440
|
return pkg.name;
|
|
1229
1441
|
} catch (err) {
|
|
1230
1442
|
throw err;
|
|
1231
1443
|
}
|
|
1232
1444
|
}
|
|
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
1445
|
async addScriptsToPackageJson(scripts) {
|
|
1241
|
-
const packageJson = JSON.parse(await
|
|
1446
|
+
const packageJson = JSON.parse(await fs5.readFile("package.json", "utf-8"));
|
|
1242
1447
|
packageJson.scripts = {
|
|
1243
1448
|
...packageJson.scripts,
|
|
1244
1449
|
...scripts
|
|
1245
1450
|
};
|
|
1246
|
-
await
|
|
1451
|
+
await fs5.writeFile("package.json", JSON.stringify(packageJson, null, 2));
|
|
1247
1452
|
}
|
|
1248
1453
|
};
|
|
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
1454
|
var args = ["-y", "@mastra/mcp-docs-server"];
|
|
1285
1455
|
var createMcpConfig = (editor) => {
|
|
1286
1456
|
if (editor === "vscode") {
|
|
@@ -1333,19 +1503,19 @@ async function writeMergedConfig(configPath, editor) {
|
|
|
1333
1503
|
spaces: 2
|
|
1334
1504
|
});
|
|
1335
1505
|
}
|
|
1336
|
-
var windsurfGlobalMCPConfigPath =
|
|
1337
|
-
var cursorGlobalMCPConfigPath =
|
|
1338
|
-
|
|
1339
|
-
var vscodeGlobalMCPConfigPath =
|
|
1506
|
+
var windsurfGlobalMCPConfigPath = path3.join(os.homedir(), ".codeium", "windsurf", "mcp_config.json");
|
|
1507
|
+
var cursorGlobalMCPConfigPath = path3.join(os.homedir(), ".cursor", "mcp.json");
|
|
1508
|
+
path3.join(process.cwd(), ".vscode", "mcp.json");
|
|
1509
|
+
var vscodeGlobalMCPConfigPath = path3.join(
|
|
1340
1510
|
os.homedir(),
|
|
1341
|
-
process.platform === "win32" ?
|
|
1511
|
+
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
1512
|
);
|
|
1343
1513
|
async function installMastraDocsMCPServer({ editor, directory }) {
|
|
1344
1514
|
if (editor === `cursor`) {
|
|
1345
|
-
await writeMergedConfig(
|
|
1515
|
+
await writeMergedConfig(path3.join(directory, ".cursor", "mcp.json"), "cursor");
|
|
1346
1516
|
}
|
|
1347
1517
|
if (editor === `vscode`) {
|
|
1348
|
-
await writeMergedConfig(
|
|
1518
|
+
await writeMergedConfig(path3.join(directory, ".vscode", "mcp.json"), "vscode");
|
|
1349
1519
|
}
|
|
1350
1520
|
if (editor === `cursor-global`) {
|
|
1351
1521
|
const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor);
|
|
@@ -1403,7 +1573,7 @@ var FileEnvService = class extends EnvService {
|
|
|
1403
1573
|
}
|
|
1404
1574
|
readFile(filePath) {
|
|
1405
1575
|
return new Promise((resolve, reject) => {
|
|
1406
|
-
|
|
1576
|
+
fs4__default.readFile(filePath, "utf8", (err, data) => {
|
|
1407
1577
|
if (err) reject(err);
|
|
1408
1578
|
else resolve(data);
|
|
1409
1579
|
});
|
|
@@ -1411,7 +1581,7 @@ var FileEnvService = class extends EnvService {
|
|
|
1411
1581
|
}
|
|
1412
1582
|
writeFile({ filePath, data }) {
|
|
1413
1583
|
return new Promise((resolve, reject) => {
|
|
1414
|
-
|
|
1584
|
+
fs4__default.writeFile(filePath, data, "utf8", (err) => {
|
|
1415
1585
|
if (err) reject(err);
|
|
1416
1586
|
else resolve();
|
|
1417
1587
|
});
|
|
@@ -1431,7 +1601,7 @@ var FileEnvService = class extends EnvService {
|
|
|
1431
1601
|
${key}=${value}`;
|
|
1432
1602
|
}
|
|
1433
1603
|
await this.writeFile({ filePath, data });
|
|
1434
|
-
console.
|
|
1604
|
+
console.info(`${key} set to ${value} in ENV file.`);
|
|
1435
1605
|
return data;
|
|
1436
1606
|
}
|
|
1437
1607
|
async getEnvValue(key) {
|
|
@@ -1464,25 +1634,25 @@ var FileService = class {
|
|
|
1464
1634
|
*/
|
|
1465
1635
|
async copyStarterFile(inputFile, outputFilePath, replaceIfExists) {
|
|
1466
1636
|
const __filename = fileURLToPath(import.meta.url);
|
|
1467
|
-
const __dirname =
|
|
1468
|
-
const filePath =
|
|
1469
|
-
const fileString =
|
|
1470
|
-
if (
|
|
1471
|
-
console.
|
|
1637
|
+
const __dirname = path3.dirname(__filename);
|
|
1638
|
+
const filePath = path3.resolve(__dirname, "starter-files", inputFile);
|
|
1639
|
+
const fileString = fs4__default__default.readFileSync(filePath, "utf8");
|
|
1640
|
+
if (fs4__default__default.existsSync(outputFilePath) && !replaceIfExists) {
|
|
1641
|
+
console.info(`${outputFilePath} already exists`);
|
|
1472
1642
|
return false;
|
|
1473
1643
|
}
|
|
1474
|
-
await
|
|
1644
|
+
await fsExtra.outputFile(outputFilePath, fileString);
|
|
1475
1645
|
return true;
|
|
1476
1646
|
}
|
|
1477
1647
|
async setupEnvFile({ dbUrl }) {
|
|
1478
|
-
const envPath =
|
|
1479
|
-
await
|
|
1648
|
+
const envPath = path3.join(process.cwd(), ".env.development");
|
|
1649
|
+
await fsExtra.ensureFile(envPath);
|
|
1480
1650
|
const fileEnvService = new FileEnvService(envPath);
|
|
1481
1651
|
await fileEnvService.setEnvValue("DB_URL", dbUrl);
|
|
1482
1652
|
}
|
|
1483
1653
|
getFirstExistingFile(files) {
|
|
1484
1654
|
for (const f of files) {
|
|
1485
|
-
if (
|
|
1655
|
+
if (fs4__default__default.existsSync(f)) {
|
|
1486
1656
|
return f;
|
|
1487
1657
|
}
|
|
1488
1658
|
}
|
|
@@ -1492,57 +1662,31 @@ var FileService = class {
|
|
|
1492
1662
|
filePath,
|
|
1493
1663
|
replacements
|
|
1494
1664
|
}) {
|
|
1495
|
-
let fileContent =
|
|
1665
|
+
let fileContent = fs4__default__default.readFileSync(filePath, "utf8");
|
|
1496
1666
|
replacements.forEach(({ search, replace }) => {
|
|
1497
1667
|
fileContent = fileContent.replaceAll(search, replace);
|
|
1498
1668
|
});
|
|
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";
|
|
1669
|
+
fs4__default__default.writeFileSync(filePath, fileContent);
|
|
1521
1670
|
}
|
|
1522
1671
|
};
|
|
1523
|
-
var
|
|
1524
|
-
|
|
1525
|
-
let modelItem = "";
|
|
1672
|
+
var exec2 = util.promisify(child_process.exec);
|
|
1673
|
+
var getModelIdentifier = (llmProvider) => {
|
|
1526
1674
|
if (llmProvider === "openai") {
|
|
1527
|
-
|
|
1528
|
-
modelItem = `openai('gpt-4o-mini')`;
|
|
1675
|
+
return `'openai/gpt-4o-mini'`;
|
|
1529
1676
|
} else if (llmProvider === "anthropic") {
|
|
1530
|
-
|
|
1531
|
-
modelItem = `anthropic('claude-3-5-sonnet-20241022')`;
|
|
1677
|
+
return `'anthropic/claude-3-5-sonnet-20241022'`;
|
|
1532
1678
|
} else if (llmProvider === "groq") {
|
|
1533
|
-
|
|
1534
|
-
modelItem = `groq('llama-3.3-70b-versatile')`;
|
|
1679
|
+
return `'groq/llama-3.3-70b-versatile'`;
|
|
1535
1680
|
} else if (llmProvider === "google") {
|
|
1536
|
-
|
|
1537
|
-
modelItem = `google('gemini-2.5-pro-exp-03-25')`;
|
|
1681
|
+
return `'google/gemini-2.5-pro'`;
|
|
1538
1682
|
} else if (llmProvider === "cerebras") {
|
|
1539
|
-
|
|
1540
|
-
|
|
1683
|
+
return `'cerebras/llama-3.3-70b'`;
|
|
1684
|
+
} else if (llmProvider === "mistral") {
|
|
1685
|
+
return `'mistral/mistral-medium-2508'`;
|
|
1541
1686
|
}
|
|
1542
|
-
return { providerImport, modelItem };
|
|
1543
1687
|
};
|
|
1544
1688
|
async function writeAgentSample(llmProvider, destPath, addExampleTool) {
|
|
1545
|
-
const
|
|
1689
|
+
const modelString = getModelIdentifier(llmProvider);
|
|
1546
1690
|
const instructions = `
|
|
1547
1691
|
You are a helpful weather assistant that provides accurate weather information and can help planning activities based on the weather.
|
|
1548
1692
|
|
|
@@ -1558,7 +1702,6 @@ async function writeAgentSample(llmProvider, destPath, addExampleTool) {
|
|
|
1558
1702
|
${addExampleTool ? "Use the weatherTool to fetch current weather data." : ""}
|
|
1559
1703
|
`;
|
|
1560
1704
|
const content = `
|
|
1561
|
-
${providerImport}
|
|
1562
1705
|
import { Agent } from '@mastra/core/agent';
|
|
1563
1706
|
import { Memory } from '@mastra/memory';
|
|
1564
1707
|
import { LibSQLStore } from '@mastra/libsql';
|
|
@@ -1567,7 +1710,7 @@ ${addExampleTool ? `import { weatherTool } from '../tools/weather-tool';` : ""}
|
|
|
1567
1710
|
export const weatherAgent = new Agent({
|
|
1568
1711
|
name: 'Weather Agent',
|
|
1569
1712
|
instructions: \`${instructions}\`,
|
|
1570
|
-
model: ${
|
|
1713
|
+
model: ${modelString},
|
|
1571
1714
|
${addExampleTool ? "tools: { weatherTool }," : ""}
|
|
1572
1715
|
memory: new Memory({
|
|
1573
1716
|
storage: new LibSQLStore({
|
|
@@ -1580,8 +1723,8 @@ export const weatherAgent = new Agent({
|
|
|
1580
1723
|
parser: "typescript",
|
|
1581
1724
|
singleQuote: true
|
|
1582
1725
|
});
|
|
1583
|
-
await
|
|
1584
|
-
await
|
|
1726
|
+
await fs5.writeFile(destPath, "");
|
|
1727
|
+
await fs5.writeFile(destPath, formattedContent);
|
|
1585
1728
|
}
|
|
1586
1729
|
async function writeWorkflowSample(destPath) {
|
|
1587
1730
|
const content = `import { createStep, createWorkflow } from '@mastra/core/workflows';
|
|
@@ -1774,7 +1917,7 @@ export { weatherWorkflow };`;
|
|
|
1774
1917
|
semi: true,
|
|
1775
1918
|
singleQuote: true
|
|
1776
1919
|
});
|
|
1777
|
-
await
|
|
1920
|
+
await fs5.writeFile(destPath, formattedContent);
|
|
1778
1921
|
}
|
|
1779
1922
|
async function writeToolSample(destPath) {
|
|
1780
1923
|
const fileService = new FileService();
|
|
@@ -1794,7 +1937,7 @@ async function writeCodeSampleForComponents(llmprovider, component, destPath, im
|
|
|
1794
1937
|
}
|
|
1795
1938
|
var createComponentsDir = async (dirPath, component) => {
|
|
1796
1939
|
const componentPath = dirPath + `/${component}`;
|
|
1797
|
-
await
|
|
1940
|
+
await fsExtra.ensureDir(componentPath);
|
|
1798
1941
|
};
|
|
1799
1942
|
var writeIndexFile = async ({
|
|
1800
1943
|
dirPath,
|
|
@@ -1803,15 +1946,15 @@ var writeIndexFile = async ({
|
|
|
1803
1946
|
addWorkflow
|
|
1804
1947
|
}) => {
|
|
1805
1948
|
const indexPath = dirPath + "/index.ts";
|
|
1806
|
-
const destPath =
|
|
1949
|
+
const destPath = path3.join(indexPath);
|
|
1807
1950
|
try {
|
|
1808
|
-
await
|
|
1951
|
+
await fs5.writeFile(destPath, "");
|
|
1809
1952
|
const filteredExports = [
|
|
1810
1953
|
addWorkflow ? `workflows: { weatherWorkflow },` : "",
|
|
1811
1954
|
addAgent ? `agents: { weatherAgent },` : ""
|
|
1812
1955
|
].filter(Boolean);
|
|
1813
1956
|
if (!addExample) {
|
|
1814
|
-
await
|
|
1957
|
+
await fs5.writeFile(
|
|
1815
1958
|
destPath,
|
|
1816
1959
|
`
|
|
1817
1960
|
import { Mastra } from '@mastra/core';
|
|
@@ -1821,7 +1964,7 @@ export const mastra = new Mastra()
|
|
|
1821
1964
|
);
|
|
1822
1965
|
return;
|
|
1823
1966
|
}
|
|
1824
|
-
await
|
|
1967
|
+
await fs5.writeFile(
|
|
1825
1968
|
destPath,
|
|
1826
1969
|
`
|
|
1827
1970
|
import { Mastra } from '@mastra/core/mastra';
|
|
@@ -1833,13 +1976,21 @@ ${addAgent ? `import { weatherAgent } from './agents/weather-agent';` : ""}
|
|
|
1833
1976
|
export const mastra = new Mastra({
|
|
1834
1977
|
${filteredExports.join("\n ")}
|
|
1835
1978
|
storage: new LibSQLStore({
|
|
1836
|
-
// stores
|
|
1979
|
+
// stores observability, scores, ... into memory storage, if it needs to persist, change to file:../mastra.db
|
|
1837
1980
|
url: ":memory:",
|
|
1838
1981
|
}),
|
|
1839
1982
|
logger: new PinoLogger({
|
|
1840
1983
|
name: 'Mastra',
|
|
1841
1984
|
level: 'info',
|
|
1842
1985
|
}),
|
|
1986
|
+
telemetry: {
|
|
1987
|
+
// Telemetry is deprecated and will be removed in the Nov 4th release
|
|
1988
|
+
enabled: false,
|
|
1989
|
+
},
|
|
1990
|
+
observability: {
|
|
1991
|
+
// Enables DefaultExporter and CloudExporter for AI tracing
|
|
1992
|
+
default: { enabled: true },
|
|
1993
|
+
},
|
|
1843
1994
|
});
|
|
1844
1995
|
`
|
|
1845
1996
|
);
|
|
@@ -1863,27 +2014,28 @@ var getAPIKey = async (provider) => {
|
|
|
1863
2014
|
case "cerebras":
|
|
1864
2015
|
key = "CEREBRAS_API_KEY";
|
|
1865
2016
|
return key;
|
|
2017
|
+
case "mistral":
|
|
2018
|
+
key = "MISTRAL_API_KEY";
|
|
2019
|
+
return key;
|
|
1866
2020
|
default:
|
|
1867
2021
|
return key;
|
|
1868
2022
|
}
|
|
1869
2023
|
};
|
|
1870
|
-
var writeAPIKey = async ({
|
|
1871
|
-
|
|
1872
|
-
apiKey = "your-api-key"
|
|
1873
|
-
}) => {
|
|
2024
|
+
var writeAPIKey = async ({ provider, apiKey }) => {
|
|
2025
|
+
const envFileName = apiKey ? ".env" : ".env.example";
|
|
1874
2026
|
const key = await getAPIKey(provider);
|
|
1875
2027
|
const escapedKey = shellQuote.quote([key]);
|
|
1876
|
-
const escapedApiKey = shellQuote.quote([apiKey]);
|
|
1877
|
-
await
|
|
2028
|
+
const escapedApiKey = shellQuote.quote([apiKey ? apiKey : "your-api-key"]);
|
|
2029
|
+
await exec2(`echo ${escapedKey}=${escapedApiKey} >> ${envFileName}`);
|
|
1878
2030
|
};
|
|
1879
2031
|
var createMastraDir = async (directory) => {
|
|
1880
2032
|
let dir = directory.trim().split("/").filter((item) => item !== "");
|
|
1881
|
-
const dirPath =
|
|
2033
|
+
const dirPath = path3.join(process.cwd(), ...dir, "mastra");
|
|
1882
2034
|
try {
|
|
1883
|
-
await
|
|
2035
|
+
await fs5.access(dirPath);
|
|
1884
2036
|
return { ok: false };
|
|
1885
2037
|
} catch {
|
|
1886
|
-
await
|
|
2038
|
+
await fsExtra.ensureDir(dirPath);
|
|
1887
2039
|
return { ok: true, dirPath };
|
|
1888
2040
|
}
|
|
1889
2041
|
};
|
|
@@ -1895,8 +2047,19 @@ var writeCodeSample = async (dirPath, component, llmProvider, importComponents)
|
|
|
1895
2047
|
throw err;
|
|
1896
2048
|
}
|
|
1897
2049
|
};
|
|
1898
|
-
var
|
|
1899
|
-
|
|
2050
|
+
var LLM_PROVIDERS = [
|
|
2051
|
+
{ value: "openai", label: "OpenAI", hint: "recommended" },
|
|
2052
|
+
{ value: "anthropic", label: "Anthropic" },
|
|
2053
|
+
{ value: "groq", label: "Groq" },
|
|
2054
|
+
{ value: "google", label: "Google" },
|
|
2055
|
+
{ value: "cerebras", label: "Cerebras" },
|
|
2056
|
+
{ value: "mistral", label: "Mistral" }
|
|
2057
|
+
];
|
|
2058
|
+
var interactivePrompt = async (args2 = {}) => {
|
|
2059
|
+
const { skip = {}, options: { showBanner = true } = {} } = args2;
|
|
2060
|
+
if (showBanner) {
|
|
2061
|
+
Ie(color2.inverse(" Mastra Init "));
|
|
2062
|
+
}
|
|
1900
2063
|
const mastraProject = await Ce(
|
|
1901
2064
|
{
|
|
1902
2065
|
directory: () => he({
|
|
@@ -1904,19 +2067,15 @@ var interactivePrompt = async () => {
|
|
|
1904
2067
|
placeholder: "src/",
|
|
1905
2068
|
defaultValue: "src/"
|
|
1906
2069
|
}),
|
|
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
|
-
]
|
|
2070
|
+
llmProvider: () => skip?.llmProvider ? void 0 : ve({
|
|
2071
|
+
message: "Select a default provider:",
|
|
2072
|
+
options: LLM_PROVIDERS
|
|
1916
2073
|
}),
|
|
1917
2074
|
llmApiKey: async ({ results: { llmProvider } }) => {
|
|
2075
|
+
if (skip?.llmApiKey) return void 0;
|
|
2076
|
+
const llmName = LLM_PROVIDERS.find((p6) => p6.value === llmProvider)?.label || "provider";
|
|
1918
2077
|
const keyChoice = await ve({
|
|
1919
|
-
message: `Enter your ${
|
|
2078
|
+
message: `Enter your ${llmName} API key?`,
|
|
1920
2079
|
options: [
|
|
1921
2080
|
{ value: "skip", label: "Skip for now", hint: "default" },
|
|
1922
2081
|
{ value: "enter", label: "Enter API key" }
|
|
@@ -1926,7 +2085,10 @@ var interactivePrompt = async () => {
|
|
|
1926
2085
|
if (keyChoice === "enter") {
|
|
1927
2086
|
return he({
|
|
1928
2087
|
message: "Enter your API key:",
|
|
1929
|
-
placeholder: "sk-..."
|
|
2088
|
+
placeholder: "sk-...",
|
|
2089
|
+
validate: (value) => {
|
|
2090
|
+
if (value.length === 0) return "API key cannot be empty";
|
|
2091
|
+
}
|
|
1930
2092
|
});
|
|
1931
2093
|
}
|
|
1932
2094
|
return void 0;
|
|
@@ -1936,7 +2098,7 @@ var interactivePrompt = async () => {
|
|
|
1936
2098
|
const cursorIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`cursor`);
|
|
1937
2099
|
const vscodeIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`vscode`);
|
|
1938
2100
|
const editor = await ve({
|
|
1939
|
-
message: `Make your
|
|
2101
|
+
message: `Make your IDE into a Mastra expert? (Installs Mastra's MCP server)`,
|
|
1940
2102
|
options: [
|
|
1941
2103
|
{ value: "skip", label: "Skip for now", hint: "default" },
|
|
1942
2104
|
{
|
|
@@ -2017,7 +2179,6 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
2017
2179
|
return mastraProject;
|
|
2018
2180
|
};
|
|
2019
2181
|
var s = Y();
|
|
2020
|
-
var exec2 = util.promisify(child_process.exec);
|
|
2021
2182
|
var init = async ({
|
|
2022
2183
|
directory,
|
|
2023
2184
|
addExample = false,
|
|
@@ -2065,11 +2226,6 @@ var init = async ({
|
|
|
2065
2226
|
}
|
|
2066
2227
|
}
|
|
2067
2228
|
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
2229
|
if (configureEditorWithDocsMCP) {
|
|
2074
2230
|
await installMastraDocsMCPServer({
|
|
2075
2231
|
editor: configureEditorWithDocsMCP,
|
|
@@ -2123,9 +2279,9 @@ var execWithTimeout = async (command, timeoutMs) => {
|
|
|
2123
2279
|
}
|
|
2124
2280
|
};
|
|
2125
2281
|
async function installMastraDependency(pm, dependency, versionTag, isDev, timeout) {
|
|
2126
|
-
let installCommand =
|
|
2282
|
+
let installCommand = getPackageManagerAddCommand(pm);
|
|
2127
2283
|
if (isDev) {
|
|
2128
|
-
installCommand = `${installCommand}
|
|
2284
|
+
installCommand = `${installCommand} -D`;
|
|
2129
2285
|
}
|
|
2130
2286
|
try {
|
|
2131
2287
|
await execWithTimeout(`${pm} ${installCommand} ${dependency}${versionTag}`, timeout);
|
|
@@ -2147,23 +2303,39 @@ async function installMastraDependency(pm, dependency, versionTag, isDev, timeou
|
|
|
2147
2303
|
var createMastraProject = async ({
|
|
2148
2304
|
projectName: name,
|
|
2149
2305
|
createVersionTag,
|
|
2150
|
-
timeout
|
|
2306
|
+
timeout,
|
|
2307
|
+
llmProvider,
|
|
2308
|
+
llmApiKey,
|
|
2309
|
+
needsInteractive
|
|
2151
2310
|
}) => {
|
|
2152
2311
|
Ie(color2.inverse(" Mastra Create "));
|
|
2153
2312
|
const projectName = name ?? await he({
|
|
2154
2313
|
message: "What do you want to name your project?",
|
|
2155
2314
|
placeholder: "my-mastra-app",
|
|
2156
|
-
defaultValue: "my-mastra-app"
|
|
2315
|
+
defaultValue: "my-mastra-app",
|
|
2316
|
+
validate: (value) => {
|
|
2317
|
+
if (value.length === 0) return "Project name cannot be empty";
|
|
2318
|
+
if (fs4__default__default.existsSync(value)) {
|
|
2319
|
+
return `A directory named "${value}" already exists. Please choose a different name.`;
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2157
2322
|
});
|
|
2158
2323
|
if (pD(projectName)) {
|
|
2159
2324
|
xe("Operation cancelled");
|
|
2160
2325
|
process.exit(0);
|
|
2161
2326
|
}
|
|
2327
|
+
let result;
|
|
2328
|
+
if (needsInteractive) {
|
|
2329
|
+
result = await interactivePrompt({
|
|
2330
|
+
options: { showBanner: false },
|
|
2331
|
+
skip: { llmProvider: llmProvider !== void 0, llmApiKey: llmApiKey !== void 0 }
|
|
2332
|
+
});
|
|
2333
|
+
}
|
|
2162
2334
|
const s2 = Y();
|
|
2163
2335
|
try {
|
|
2164
2336
|
s2.start("Creating project");
|
|
2165
2337
|
try {
|
|
2166
|
-
await
|
|
2338
|
+
await fs5.mkdir(projectName);
|
|
2167
2339
|
} catch (error) {
|
|
2168
2340
|
if (error instanceof Error && "code" in error && error.code === "EEXIST") {
|
|
2169
2341
|
s2.stop(`A directory named "${projectName}" already exists. Please choose a different name.`);
|
|
@@ -2175,7 +2347,7 @@ var createMastraProject = async ({
|
|
|
2175
2347
|
}
|
|
2176
2348
|
process.chdir(projectName);
|
|
2177
2349
|
const pm = getPackageManager();
|
|
2178
|
-
const installCommand =
|
|
2350
|
+
const installCommand = getPackageManagerAddCommand(pm);
|
|
2179
2351
|
s2.message("Initializing project structure");
|
|
2180
2352
|
try {
|
|
2181
2353
|
await exec3(`npm init -y`);
|
|
@@ -2219,15 +2391,15 @@ var createMastraProject = async ({
|
|
|
2219
2391
|
);
|
|
2220
2392
|
}
|
|
2221
2393
|
s2.stop(`${pm} dependencies installed`);
|
|
2222
|
-
s2.start("Installing
|
|
2394
|
+
s2.start("Installing Mastra CLI");
|
|
2223
2395
|
const versionTag = createVersionTag ? `@${createVersionTag}` : "@latest";
|
|
2224
2396
|
try {
|
|
2225
2397
|
await installMastraDependency(pm, "mastra", versionTag, true, timeout);
|
|
2226
2398
|
} catch (error) {
|
|
2227
2399
|
throw new Error(`Failed to install Mastra CLI: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2228
2400
|
}
|
|
2229
|
-
s2.stop("
|
|
2230
|
-
s2.start("Installing dependencies");
|
|
2401
|
+
s2.stop("Mastra CLI installed");
|
|
2402
|
+
s2.start("Installing Mastra dependencies");
|
|
2231
2403
|
try {
|
|
2232
2404
|
await installMastraDependency(pm, "@mastra/core", versionTag, false, timeout);
|
|
2233
2405
|
await installMastraDependency(pm, "@mastra/libsql", versionTag, false, timeout);
|
|
@@ -2253,8 +2425,8 @@ var createMastraProject = async ({
|
|
|
2253
2425
|
}
|
|
2254
2426
|
s2.stop(".gitignore added");
|
|
2255
2427
|
Se("Project created successfully");
|
|
2256
|
-
console.
|
|
2257
|
-
return { projectName };
|
|
2428
|
+
console.info("");
|
|
2429
|
+
return { projectName, result };
|
|
2258
2430
|
} catch (error) {
|
|
2259
2431
|
s2.stop();
|
|
2260
2432
|
const errorMessage = error instanceof Error ? error.message : "An unexpected error occurred";
|
|
@@ -2263,14 +2435,21 @@ var createMastraProject = async ({
|
|
|
2263
2435
|
}
|
|
2264
2436
|
};
|
|
2265
2437
|
var create = async (args2) => {
|
|
2266
|
-
|
|
2438
|
+
if (args2.template !== void 0) {
|
|
2439
|
+
await createFromTemplate({ ...args2, injectedAnalytics: args2.analytics });
|
|
2440
|
+
return;
|
|
2441
|
+
}
|
|
2442
|
+
const needsInteractive = args2.components === void 0 || args2.llmProvider === void 0 || args2.addExample === void 0;
|
|
2443
|
+
const { projectName, result } = await createMastraProject({
|
|
2267
2444
|
projectName: args2?.projectName,
|
|
2268
2445
|
createVersionTag: args2?.createVersionTag,
|
|
2269
|
-
timeout: args2?.timeout
|
|
2446
|
+
timeout: args2?.timeout,
|
|
2447
|
+
llmProvider: args2?.llmProvider,
|
|
2448
|
+
llmApiKey: args2?.llmApiKey,
|
|
2449
|
+
needsInteractive
|
|
2270
2450
|
});
|
|
2271
2451
|
const directory = args2.directory || "src/";
|
|
2272
|
-
if (
|
|
2273
|
-
const result = await interactivePrompt();
|
|
2452
|
+
if (needsInteractive && result) {
|
|
2274
2453
|
await init({
|
|
2275
2454
|
...result,
|
|
2276
2455
|
llmApiKey: result?.llmApiKey,
|
|
@@ -2300,18 +2479,172 @@ var postCreate = ({ projectName }) => {
|
|
|
2300
2479
|
${color2.cyan(`${packageManager} run dev`)}
|
|
2301
2480
|
`);
|
|
2302
2481
|
};
|
|
2482
|
+
function isGitHubUrl(url) {
|
|
2483
|
+
try {
|
|
2484
|
+
const parsedUrl = new URL(url);
|
|
2485
|
+
return parsedUrl.hostname === "github.com" && parsedUrl.pathname.split("/").length >= 3;
|
|
2486
|
+
} catch {
|
|
2487
|
+
return false;
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
async function validateGitHubProject(githubUrl) {
|
|
2491
|
+
const errors = [];
|
|
2492
|
+
try {
|
|
2493
|
+
const urlParts = new URL(githubUrl).pathname.split("/").filter(Boolean);
|
|
2494
|
+
const owner = urlParts[0];
|
|
2495
|
+
const repo = urlParts[1]?.replace(".git", "");
|
|
2496
|
+
if (!owner || !repo) {
|
|
2497
|
+
throw new Error("Invalid GitHub URL format");
|
|
2498
|
+
}
|
|
2499
|
+
const branches = ["main", "master"];
|
|
2500
|
+
let packageJsonContent = null;
|
|
2501
|
+
let indexContent = null;
|
|
2502
|
+
for (const branch of branches) {
|
|
2503
|
+
try {
|
|
2504
|
+
const packageJsonUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/package.json`;
|
|
2505
|
+
const packageJsonResponse = await fetch(packageJsonUrl);
|
|
2506
|
+
if (packageJsonResponse.ok) {
|
|
2507
|
+
packageJsonContent = await packageJsonResponse.text();
|
|
2508
|
+
const indexUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/src/mastra/index.ts`;
|
|
2509
|
+
const indexResponse = await fetch(indexUrl);
|
|
2510
|
+
if (indexResponse.ok) {
|
|
2511
|
+
indexContent = await indexResponse.text();
|
|
2512
|
+
}
|
|
2513
|
+
break;
|
|
2514
|
+
}
|
|
2515
|
+
} catch {
|
|
2516
|
+
}
|
|
2517
|
+
}
|
|
2518
|
+
if (!packageJsonContent) {
|
|
2519
|
+
errors.push("Could not fetch package.json from repository");
|
|
2520
|
+
return { isValid: false, errors };
|
|
2521
|
+
}
|
|
2522
|
+
try {
|
|
2523
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
2524
|
+
const hasMastraCore = packageJson.dependencies?.["@mastra/core"] || packageJson.devDependencies?.["@mastra/core"] || packageJson.peerDependencies?.["@mastra/core"];
|
|
2525
|
+
if (!hasMastraCore) {
|
|
2526
|
+
errors.push("Missing @mastra/core dependency in package.json");
|
|
2527
|
+
}
|
|
2528
|
+
} catch {
|
|
2529
|
+
errors.push("Invalid package.json format");
|
|
2530
|
+
}
|
|
2531
|
+
if (!indexContent) {
|
|
2532
|
+
errors.push("Missing src/mastra/index.ts file");
|
|
2533
|
+
} else {
|
|
2534
|
+
const hasMastraExport = indexContent.includes("export") && (indexContent.includes("new Mastra") || indexContent.includes("Mastra("));
|
|
2535
|
+
if (!hasMastraExport) {
|
|
2536
|
+
errors.push("src/mastra/index.ts does not export a Mastra instance");
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
return { isValid: errors.length === 0, errors };
|
|
2540
|
+
} catch (error) {
|
|
2541
|
+
errors.push(`Failed to validate GitHub repository: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2542
|
+
return { isValid: false, errors };
|
|
2543
|
+
}
|
|
2544
|
+
}
|
|
2545
|
+
async function createFromGitHubUrl(url) {
|
|
2546
|
+
const urlParts = new URL(url).pathname.split("/").filter(Boolean);
|
|
2547
|
+
const owner = urlParts[0] || "unknown";
|
|
2548
|
+
const repo = urlParts[1] || "unknown";
|
|
2549
|
+
return {
|
|
2550
|
+
githubUrl: url,
|
|
2551
|
+
title: `${owner}/${repo}`,
|
|
2552
|
+
slug: repo,
|
|
2553
|
+
agents: [],
|
|
2554
|
+
mcp: [],
|
|
2555
|
+
tools: [],
|
|
2556
|
+
networks: [],
|
|
2557
|
+
workflows: []
|
|
2558
|
+
};
|
|
2559
|
+
}
|
|
2560
|
+
async function createFromTemplate(args2) {
|
|
2561
|
+
let selectedTemplate;
|
|
2562
|
+
if (args2.template === true) {
|
|
2563
|
+
const templates = await loadTemplates();
|
|
2564
|
+
const selected = await selectTemplate(templates);
|
|
2565
|
+
if (!selected) {
|
|
2566
|
+
M.info("No template selected. Exiting.");
|
|
2567
|
+
return;
|
|
2568
|
+
}
|
|
2569
|
+
selectedTemplate = selected;
|
|
2570
|
+
} else if (args2.template && typeof args2.template === "string") {
|
|
2571
|
+
if (isGitHubUrl(args2.template)) {
|
|
2572
|
+
const spinner5 = Y();
|
|
2573
|
+
spinner5.start("Validating GitHub repository...");
|
|
2574
|
+
const validation = await validateGitHubProject(args2.template);
|
|
2575
|
+
if (!validation.isValid) {
|
|
2576
|
+
spinner5.stop("Validation failed");
|
|
2577
|
+
M.error("This does not appear to be a valid Mastra project:");
|
|
2578
|
+
validation.errors.forEach((error) => M.error(` - ${error}`));
|
|
2579
|
+
throw new Error("Invalid Mastra project");
|
|
2580
|
+
}
|
|
2581
|
+
spinner5.stop("Valid Mastra project \u2713");
|
|
2582
|
+
selectedTemplate = await createFromGitHubUrl(args2.template);
|
|
2583
|
+
} else {
|
|
2584
|
+
const templates = await loadTemplates();
|
|
2585
|
+
const found = findTemplateByName(templates, args2.template);
|
|
2586
|
+
if (!found) {
|
|
2587
|
+
M.error(`Template "${args2.template}" not found. Available templates:`);
|
|
2588
|
+
templates.forEach((t) => M.info(` - ${t.title} (use: ${t.slug.replace("template-", "")})`));
|
|
2589
|
+
throw new Error(`Template "${args2.template}" not found`);
|
|
2590
|
+
}
|
|
2591
|
+
selectedTemplate = found;
|
|
2592
|
+
}
|
|
2593
|
+
}
|
|
2594
|
+
if (!selectedTemplate) {
|
|
2595
|
+
throw new Error("No template selected");
|
|
2596
|
+
}
|
|
2597
|
+
let projectName = args2.projectName;
|
|
2598
|
+
if (!projectName) {
|
|
2599
|
+
const defaultName = getDefaultProjectName(selectedTemplate);
|
|
2600
|
+
const response = await he({
|
|
2601
|
+
message: "What is your project name?",
|
|
2602
|
+
defaultValue: defaultName,
|
|
2603
|
+
placeholder: defaultName
|
|
2604
|
+
});
|
|
2605
|
+
if (pD(response)) {
|
|
2606
|
+
M.info("Project creation cancelled.");
|
|
2607
|
+
return;
|
|
2608
|
+
}
|
|
2609
|
+
projectName = response;
|
|
2610
|
+
}
|
|
2611
|
+
try {
|
|
2612
|
+
const analytics = args2.injectedAnalytics || getAnalytics();
|
|
2613
|
+
if (analytics) {
|
|
2614
|
+
analytics.trackEvent("cli_template_used", {
|
|
2615
|
+
template_slug: selectedTemplate.slug,
|
|
2616
|
+
template_title: selectedTemplate.title
|
|
2617
|
+
});
|
|
2618
|
+
}
|
|
2619
|
+
const projectPath = await cloneTemplate({
|
|
2620
|
+
template: selectedTemplate,
|
|
2621
|
+
projectName
|
|
2622
|
+
});
|
|
2623
|
+
await installDependencies(projectPath);
|
|
2624
|
+
Me(`
|
|
2625
|
+
${color2.green("Mastra template installed!")}
|
|
2626
|
+
|
|
2627
|
+
Add the necessary environment
|
|
2628
|
+
variables in your ${color2.cyan(".env")} file
|
|
2629
|
+
`);
|
|
2630
|
+
postCreate({ projectName });
|
|
2631
|
+
} catch (error) {
|
|
2632
|
+
M.error(`Failed to create project from template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2633
|
+
throw error;
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2303
2636
|
|
|
2304
2637
|
async function getPackageVersion() {
|
|
2305
2638
|
const __filename = fileURLToPath(import.meta.url);
|
|
2306
2639
|
const __dirname = dirname(__filename);
|
|
2307
|
-
const pkgJsonPath =
|
|
2308
|
-
const content = await fsExtra.readJSON(pkgJsonPath);
|
|
2640
|
+
const pkgJsonPath = path3.join(__dirname, "..", "package.json");
|
|
2641
|
+
const content = await fsExtra$1.readJSON(pkgJsonPath);
|
|
2309
2642
|
return content.version;
|
|
2310
2643
|
}
|
|
2311
2644
|
async function getCreateVersionTag() {
|
|
2312
2645
|
try {
|
|
2313
2646
|
const pkgPath = fileURLToPath(import.meta.resolve("create-mastra/package.json"));
|
|
2314
|
-
const json = await fsExtra.readJSON(pkgPath);
|
|
2647
|
+
const json = await fsExtra$1.readJSON(pkgPath);
|
|
2315
2648
|
const { stdout } = await execa("npm", ["dist-tag", "create-mastra"]);
|
|
2316
2649
|
const tagLine = stdout.split("\n").find((distLine) => distLine.endsWith(`: ${json.version}`));
|
|
2317
2650
|
const tag = tagLine ? tagLine.split(":")[0].trim() : "latest";
|
|
@@ -2335,14 +2668,17 @@ program.version(`${version}`, "-v, --version").description(`create-mastra ${vers
|
|
|
2335
2668
|
analytics.trackCommand({
|
|
2336
2669
|
command: "version"
|
|
2337
2670
|
});
|
|
2338
|
-
console.
|
|
2671
|
+
console.info(`create-mastra ${version}`);
|
|
2339
2672
|
} catch {
|
|
2340
2673
|
}
|
|
2341
2674
|
});
|
|
2342
2675
|
program.name("create-mastra").description("Create a new Mastra project").argument("[project-name]", "Directory name of the project").option(
|
|
2343
2676
|
"-p, --project-name <string>",
|
|
2344
2677
|
"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)").
|
|
2678
|
+
).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(
|
|
2679
|
+
"--template [template-name]",
|
|
2680
|
+
"Create project from a template (use template name, public GitHub URL, or leave blank to select from list)"
|
|
2681
|
+
).action(async (projectNameArg, args) => {
|
|
2346
2682
|
const projectName = projectNameArg || args.projectName;
|
|
2347
2683
|
const timeout = args?.timeout ? args?.timeout === true ? 6e4 : parseInt(args?.timeout, 10) : void 0;
|
|
2348
2684
|
if (args.default) {
|
|
@@ -2353,7 +2689,9 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
|
|
|
2353
2689
|
createVersionTag,
|
|
2354
2690
|
timeout,
|
|
2355
2691
|
mcpServer: args.mcp,
|
|
2356
|
-
directory: "src/"
|
|
2692
|
+
directory: "src/",
|
|
2693
|
+
template: args.template,
|
|
2694
|
+
analytics
|
|
2357
2695
|
});
|
|
2358
2696
|
return;
|
|
2359
2697
|
}
|
|
@@ -2361,12 +2699,14 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
|
|
|
2361
2699
|
components: args.components ? args.components.split(",") : [],
|
|
2362
2700
|
llmProvider: args.llm,
|
|
2363
2701
|
addExample: args.example,
|
|
2364
|
-
llmApiKey: args
|
|
2702
|
+
llmApiKey: args.llmApiKey,
|
|
2365
2703
|
createVersionTag,
|
|
2366
2704
|
timeout,
|
|
2367
2705
|
projectName,
|
|
2368
2706
|
directory: args.dir,
|
|
2369
|
-
mcpServer: args.mcp
|
|
2707
|
+
mcpServer: args.mcp,
|
|
2708
|
+
template: args.template,
|
|
2709
|
+
analytics
|
|
2370
2710
|
});
|
|
2371
2711
|
});
|
|
2372
2712
|
program.parse(process.argv);
|