create-mastra 0.0.0-tool-call-parts-20250630193309 → 0.0.0-tool-list-type-20250910134057
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 +1673 -0
- package/LICENSE.md +11 -42
- package/README.md +2 -8
- package/dist/index.js +529 -193
- package/dist/index.js.map +1 -1
- package/dist/templates/dev.entry.js +7 -2
- package/dist/templates/scorers/answer-relevancy-scorer.ts +15 -0
- package/dist/templates/scorers/bias-detection-scorer.ts +16 -0
- package/dist/templates/scorers/completeness-scorer.ts +16 -0
- package/dist/templates/scorers/content-similarity-scorer.ts +15 -0
- package/dist/templates/scorers/faithfulness-scorer.ts +21 -0
- package/dist/templates/scorers/hallucination-scorer.ts +21 -0
- package/dist/templates/scorers/keyword-coverage-scorer.ts +15 -0
- package/dist/templates/scorers/textual-difference-scorer.ts +16 -0
- package/dist/templates/scorers/tone-consistency-scorer.ts +16 -0
- package/dist/templates/scorers/toxicity-detection-scorer.ts +16 -0
- 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 fs 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';
|
|
20
|
+
import { execa } from 'execa';
|
|
21
|
+
import fsExtra2, { readJSON, ensureFile, writeJSON } from 'fs-extra/esm';
|
|
22
|
+
import prettier from 'prettier';
|
|
23
23
|
import fsExtra 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 fs.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 fs.stat(dirPath);
|
|
1229
|
+
return stat.isDirectory();
|
|
1230
|
+
} catch {
|
|
1231
|
+
return false;
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
async function fileExists(filePath) {
|
|
1235
|
+
try {
|
|
1236
|
+
const stat = await fs.stat(filePath);
|
|
1237
|
+
return stat.isFile();
|
|
1238
|
+
} catch {
|
|
1239
|
+
return false;
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
async function cloneRepositoryWithoutGit(repoUrl, targetPath) {
|
|
1243
|
+
await fs.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 fs.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 fs.readFile(packageJsonPath, "utf-8");
|
|
1269
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
1270
|
+
packageJson.name = projectName;
|
|
1271
|
+
await fs.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 fs.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 fs.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 fs.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 fs.readFile("package.json", "utf-8"));
|
|
1242
1442
|
packageJson.scripts = {
|
|
1243
1443
|
...packageJson.scripts,
|
|
1244
1444
|
...scripts
|
|
1245
1445
|
};
|
|
1246
|
-
await
|
|
1446
|
+
await fs.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
|
});
|
|
@@ -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 (
|
|
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) {
|
|
1471
1636
|
console.log(`${outputFilePath} already exists`);
|
|
1472
1637
|
return false;
|
|
1473
1638
|
}
|
|
1474
|
-
await
|
|
1639
|
+
await fsExtra2.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 fsExtra2.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,18 +1657,22 @@ 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
|
-
|
|
1664
|
+
fs4__default__default.writeFileSync(filePath, fileContent);
|
|
1665
|
+
}
|
|
1666
|
+
};
|
|
1667
|
+
var exec2 = util.promisify(child_process.exec);
|
|
1668
|
+
var getAISDKPackageVersion = (llmProvider) => {
|
|
1669
|
+
switch (llmProvider) {
|
|
1670
|
+
case "cerebras":
|
|
1671
|
+
return "^0.2.14";
|
|
1672
|
+
default:
|
|
1673
|
+
return "^1.0.0";
|
|
1500
1674
|
}
|
|
1501
1675
|
};
|
|
1502
|
-
new PinoLogger({
|
|
1503
|
-
name: "Mastra CLI",
|
|
1504
|
-
level: "info"
|
|
1505
|
-
});
|
|
1506
|
-
var exec = util.promisify(child_process.exec);
|
|
1507
1676
|
var getAISDKPackage = (llmProvider) => {
|
|
1508
1677
|
switch (llmProvider) {
|
|
1509
1678
|
case "openai":
|
|
@@ -1516,6 +1685,8 @@ var getAISDKPackage = (llmProvider) => {
|
|
|
1516
1685
|
return "@ai-sdk/google";
|
|
1517
1686
|
case "cerebras":
|
|
1518
1687
|
return "@ai-sdk/cerebras";
|
|
1688
|
+
case "mistral":
|
|
1689
|
+
return "@ai-sdk/mistral";
|
|
1519
1690
|
default:
|
|
1520
1691
|
return "@ai-sdk/openai";
|
|
1521
1692
|
}
|
|
@@ -1534,24 +1705,29 @@ var getProviderImportAndModelItem = (llmProvider) => {
|
|
|
1534
1705
|
modelItem = `groq('llama-3.3-70b-versatile')`;
|
|
1535
1706
|
} else if (llmProvider === "google") {
|
|
1536
1707
|
providerImport = `import { google } from '${getAISDKPackage(llmProvider)}';`;
|
|
1537
|
-
modelItem = `google('gemini-2.5-pro
|
|
1708
|
+
modelItem = `google('gemini-2.5-pro')`;
|
|
1538
1709
|
} else if (llmProvider === "cerebras") {
|
|
1539
1710
|
providerImport = `import { cerebras } from '${getAISDKPackage(llmProvider)}';`;
|
|
1540
1711
|
modelItem = `cerebras('llama-3.3-70b')`;
|
|
1712
|
+
} else if (llmProvider === "mistral") {
|
|
1713
|
+
providerImport = `import { mistral } from '${getAISDKPackage(llmProvider)}';`;
|
|
1714
|
+
modelItem = `mistral('mistral-medium-2508')`;
|
|
1541
1715
|
}
|
|
1542
1716
|
return { providerImport, modelItem };
|
|
1543
1717
|
};
|
|
1544
1718
|
async function writeAgentSample(llmProvider, destPath, addExampleTool) {
|
|
1545
1719
|
const { providerImport, modelItem } = getProviderImportAndModelItem(llmProvider);
|
|
1546
1720
|
const instructions = `
|
|
1547
|
-
You are a helpful weather assistant that provides accurate weather information.
|
|
1721
|
+
You are a helpful weather assistant that provides accurate weather information and can help planning activities based on the weather.
|
|
1548
1722
|
|
|
1549
1723
|
Your primary function is to help users get weather details for specific locations. When responding:
|
|
1550
1724
|
- Always ask for a location if none is provided
|
|
1551
|
-
- If the location name isn
|
|
1725
|
+
- If the location name isn't in English, please translate it
|
|
1552
1726
|
- If giving a location with multiple parts (e.g. "New York, NY"), use the most relevant part (e.g. "New York")
|
|
1553
1727
|
- Include relevant details like humidity, wind conditions, and precipitation
|
|
1554
1728
|
- Keep responses concise but informative
|
|
1729
|
+
- If the user asks for activities and provides the weather forecast, suggest activities based on the weather forecast.
|
|
1730
|
+
- If the user asks for activities, respond in the format they request.
|
|
1555
1731
|
|
|
1556
1732
|
${addExampleTool ? "Use the weatherTool to fetch current weather data." : ""}
|
|
1557
1733
|
`;
|
|
@@ -1578,66 +1754,13 @@ export const weatherAgent = new Agent({
|
|
|
1578
1754
|
parser: "typescript",
|
|
1579
1755
|
singleQuote: true
|
|
1580
1756
|
});
|
|
1581
|
-
await
|
|
1582
|
-
await
|
|
1757
|
+
await fs.writeFile(destPath, "");
|
|
1758
|
+
await fs.writeFile(destPath, formattedContent);
|
|
1583
1759
|
}
|
|
1584
|
-
async function writeWorkflowSample(destPath
|
|
1585
|
-
const {
|
|
1586
|
-
const content = `${providerImport}
|
|
1587
|
-
import { Agent } from '@mastra/core/agent';
|
|
1588
|
-
import { createStep, createWorkflow } from '@mastra/core/workflows';
|
|
1760
|
+
async function writeWorkflowSample(destPath) {
|
|
1761
|
+
const content = `import { createStep, createWorkflow } from '@mastra/core/workflows';
|
|
1589
1762
|
import { z } from 'zod';
|
|
1590
1763
|
|
|
1591
|
-
const llm = ${modelItem};
|
|
1592
|
-
|
|
1593
|
-
const agent = new Agent({
|
|
1594
|
-
name: 'Weather Agent',
|
|
1595
|
-
model: llm,
|
|
1596
|
-
instructions: \`
|
|
1597
|
-
You are a local activities and travel expert who excels at weather-based planning. Analyze the weather data and provide practical activity recommendations.
|
|
1598
|
-
|
|
1599
|
-
For each day in the forecast, structure your response exactly as follows:
|
|
1600
|
-
|
|
1601
|
-
\u{1F4C5} [Day, Month Date, Year]
|
|
1602
|
-
\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
1603
|
-
|
|
1604
|
-
\u{1F321}\uFE0F WEATHER SUMMARY
|
|
1605
|
-
\u2022 Conditions: [brief description]
|
|
1606
|
-
\u2022 Temperature: [X\xB0C/Y\xB0F to A\xB0C/B\xB0F]
|
|
1607
|
-
\u2022 Precipitation: [X% chance]
|
|
1608
|
-
|
|
1609
|
-
\u{1F305} MORNING ACTIVITIES
|
|
1610
|
-
Outdoor:
|
|
1611
|
-
\u2022 [Activity Name] - [Brief description including specific location/route]
|
|
1612
|
-
Best timing: [specific time range]
|
|
1613
|
-
Note: [relevant weather consideration]
|
|
1614
|
-
|
|
1615
|
-
\u{1F31E} AFTERNOON ACTIVITIES
|
|
1616
|
-
Outdoor:
|
|
1617
|
-
\u2022 [Activity Name] - [Brief description including specific location/route]
|
|
1618
|
-
Best timing: [specific time range]
|
|
1619
|
-
Note: [relevant weather consideration]
|
|
1620
|
-
|
|
1621
|
-
\u{1F3E0} INDOOR ALTERNATIVES
|
|
1622
|
-
\u2022 [Activity Name] - [Brief description including specific venue]
|
|
1623
|
-
Ideal for: [weather condition that would trigger this alternative]
|
|
1624
|
-
|
|
1625
|
-
\u26A0\uFE0F SPECIAL CONSIDERATIONS
|
|
1626
|
-
\u2022 [Any relevant weather warnings, UV index, wind conditions, etc.]
|
|
1627
|
-
|
|
1628
|
-
Guidelines:
|
|
1629
|
-
- Suggest 2-3 time-specific outdoor activities per day
|
|
1630
|
-
- Include 1-2 indoor backup options
|
|
1631
|
-
- For precipitation >50%, lead with indoor activities
|
|
1632
|
-
- All activities must be specific to the location
|
|
1633
|
-
- Include specific venues, trails, or locations
|
|
1634
|
-
- Consider activity intensity based on temperature
|
|
1635
|
-
- Keep descriptions concise but informative
|
|
1636
|
-
|
|
1637
|
-
Maintain this exact formatting for consistency, using the emoji and section headers as shown.
|
|
1638
|
-
\`,
|
|
1639
|
-
});
|
|
1640
|
-
|
|
1641
1764
|
const forecastSchema = z.object({
|
|
1642
1765
|
date: z.string(),
|
|
1643
1766
|
maxTemp: z.number(),
|
|
@@ -1731,16 +1854,59 @@ const planActivities = createStep({
|
|
|
1731
1854
|
outputSchema: z.object({
|
|
1732
1855
|
activities: z.string(),
|
|
1733
1856
|
}),
|
|
1734
|
-
execute: async ({ inputData }) => {
|
|
1857
|
+
execute: async ({ inputData, mastra }) => {
|
|
1735
1858
|
const forecast = inputData
|
|
1736
1859
|
|
|
1737
1860
|
if (!forecast) {
|
|
1738
1861
|
throw new Error('Forecast data not found')
|
|
1739
1862
|
}
|
|
1740
1863
|
|
|
1864
|
+
const agent = mastra?.getAgent('weatherAgent');
|
|
1865
|
+
if (!agent) {
|
|
1866
|
+
throw new Error('Weather agent not found');
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1741
1869
|
const prompt = \`Based on the following weather forecast for \${forecast.location}, suggest appropriate activities:
|
|
1742
1870
|
\${JSON.stringify(forecast, null, 2)}
|
|
1743
|
-
|
|
1871
|
+
For each day in the forecast, structure your response exactly as follows:
|
|
1872
|
+
|
|
1873
|
+
\u{1F4C5} [Day, Month Date, Year]
|
|
1874
|
+
\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
1875
|
+
|
|
1876
|
+
\u{1F321}\uFE0F WEATHER SUMMARY
|
|
1877
|
+
\u2022 Conditions: [brief description]
|
|
1878
|
+
\u2022 Temperature: [X\xB0C/Y\xB0F to A\xB0C/B\xB0F]
|
|
1879
|
+
\u2022 Precipitation: [X% chance]
|
|
1880
|
+
|
|
1881
|
+
\u{1F305} MORNING ACTIVITIES
|
|
1882
|
+
Outdoor:
|
|
1883
|
+
\u2022 [Activity Name] - [Brief description including specific location/route]
|
|
1884
|
+
Best timing: [specific time range]
|
|
1885
|
+
Note: [relevant weather consideration]
|
|
1886
|
+
|
|
1887
|
+
\u{1F31E} AFTERNOON ACTIVITIES
|
|
1888
|
+
Outdoor:
|
|
1889
|
+
\u2022 [Activity Name] - [Brief description including specific location/route]
|
|
1890
|
+
Best timing: [specific time range]
|
|
1891
|
+
Note: [relevant weather consideration]
|
|
1892
|
+
|
|
1893
|
+
\u{1F3E0} INDOOR ALTERNATIVES
|
|
1894
|
+
\u2022 [Activity Name] - [Brief description including specific venue]
|
|
1895
|
+
Ideal for: [weather condition that would trigger this alternative]
|
|
1896
|
+
|
|
1897
|
+
\u26A0\uFE0F SPECIAL CONSIDERATIONS
|
|
1898
|
+
\u2022 [Any relevant weather warnings, UV index, wind conditions, etc.]
|
|
1899
|
+
|
|
1900
|
+
Guidelines:
|
|
1901
|
+
- Suggest 2-3 time-specific outdoor activities per day
|
|
1902
|
+
- Include 1-2 indoor backup options
|
|
1903
|
+
- For precipitation >50%, lead with indoor activities
|
|
1904
|
+
- All activities must be specific to the location
|
|
1905
|
+
- Include specific venues, trails, or locations
|
|
1906
|
+
- Consider activity intensity based on temperature
|
|
1907
|
+
- Keep descriptions concise but informative
|
|
1908
|
+
|
|
1909
|
+
Maintain this exact formatting for consistency, using the emoji and section headers as shown.\`;
|
|
1744
1910
|
|
|
1745
1911
|
const response = await agent.stream([
|
|
1746
1912
|
{
|
|
@@ -1782,7 +1948,7 @@ export { weatherWorkflow };`;
|
|
|
1782
1948
|
semi: true,
|
|
1783
1949
|
singleQuote: true
|
|
1784
1950
|
});
|
|
1785
|
-
await
|
|
1951
|
+
await fs.writeFile(destPath, formattedContent);
|
|
1786
1952
|
}
|
|
1787
1953
|
async function writeToolSample(destPath) {
|
|
1788
1954
|
const fileService = new FileService();
|
|
@@ -1795,14 +1961,14 @@ async function writeCodeSampleForComponents(llmprovider, component, destPath, im
|
|
|
1795
1961
|
case "tools":
|
|
1796
1962
|
return writeToolSample(destPath);
|
|
1797
1963
|
case "workflows":
|
|
1798
|
-
return writeWorkflowSample(destPath
|
|
1964
|
+
return writeWorkflowSample(destPath);
|
|
1799
1965
|
default:
|
|
1800
1966
|
return "";
|
|
1801
1967
|
}
|
|
1802
1968
|
}
|
|
1803
1969
|
var createComponentsDir = async (dirPath, component) => {
|
|
1804
1970
|
const componentPath = dirPath + `/${component}`;
|
|
1805
|
-
await
|
|
1971
|
+
await fsExtra2.ensureDir(componentPath);
|
|
1806
1972
|
};
|
|
1807
1973
|
var writeIndexFile = async ({
|
|
1808
1974
|
dirPath,
|
|
@@ -1811,15 +1977,15 @@ var writeIndexFile = async ({
|
|
|
1811
1977
|
addWorkflow
|
|
1812
1978
|
}) => {
|
|
1813
1979
|
const indexPath = dirPath + "/index.ts";
|
|
1814
|
-
const destPath =
|
|
1980
|
+
const destPath = path3.join(indexPath);
|
|
1815
1981
|
try {
|
|
1816
|
-
await
|
|
1982
|
+
await fs.writeFile(destPath, "");
|
|
1817
1983
|
const filteredExports = [
|
|
1818
1984
|
addWorkflow ? `workflows: { weatherWorkflow },` : "",
|
|
1819
1985
|
addAgent ? `agents: { weatherAgent },` : ""
|
|
1820
1986
|
].filter(Boolean);
|
|
1821
1987
|
if (!addExample) {
|
|
1822
|
-
await
|
|
1988
|
+
await fs.writeFile(
|
|
1823
1989
|
destPath,
|
|
1824
1990
|
`
|
|
1825
1991
|
import { Mastra } from '@mastra/core';
|
|
@@ -1829,7 +1995,7 @@ export const mastra = new Mastra()
|
|
|
1829
1995
|
);
|
|
1830
1996
|
return;
|
|
1831
1997
|
}
|
|
1832
|
-
await
|
|
1998
|
+
await fs.writeFile(
|
|
1833
1999
|
destPath,
|
|
1834
2000
|
`
|
|
1835
2001
|
import { Mastra } from '@mastra/core/mastra';
|
|
@@ -1871,6 +2037,9 @@ var getAPIKey = async (provider) => {
|
|
|
1871
2037
|
case "cerebras":
|
|
1872
2038
|
key = "CEREBRAS_API_KEY";
|
|
1873
2039
|
return key;
|
|
2040
|
+
case "mistral":
|
|
2041
|
+
key = "MISTRAL_API_KEY";
|
|
2042
|
+
return key;
|
|
1874
2043
|
default:
|
|
1875
2044
|
return key;
|
|
1876
2045
|
}
|
|
@@ -1882,16 +2051,16 @@ var writeAPIKey = async ({
|
|
|
1882
2051
|
const key = await getAPIKey(provider);
|
|
1883
2052
|
const escapedKey = shellQuote.quote([key]);
|
|
1884
2053
|
const escapedApiKey = shellQuote.quote([apiKey]);
|
|
1885
|
-
await
|
|
2054
|
+
await exec2(`echo ${escapedKey}=${escapedApiKey} >> .env`);
|
|
1886
2055
|
};
|
|
1887
2056
|
var createMastraDir = async (directory) => {
|
|
1888
2057
|
let dir = directory.trim().split("/").filter((item) => item !== "");
|
|
1889
|
-
const dirPath =
|
|
2058
|
+
const dirPath = path3.join(process.cwd(), ...dir, "mastra");
|
|
1890
2059
|
try {
|
|
1891
|
-
await
|
|
2060
|
+
await fs.access(dirPath);
|
|
1892
2061
|
return { ok: false };
|
|
1893
2062
|
} catch {
|
|
1894
|
-
await
|
|
2063
|
+
await fsExtra2.ensureDir(dirPath);
|
|
1895
2064
|
return { ok: true, dirPath };
|
|
1896
2065
|
}
|
|
1897
2066
|
};
|
|
@@ -1919,7 +2088,8 @@ var interactivePrompt = async () => {
|
|
|
1919
2088
|
{ value: "anthropic", label: "Anthropic" },
|
|
1920
2089
|
{ value: "groq", label: "Groq" },
|
|
1921
2090
|
{ value: "google", label: "Google" },
|
|
1922
|
-
{ value: "cerebras", label: "Cerebras" }
|
|
2091
|
+
{ value: "cerebras", label: "Cerebras" },
|
|
2092
|
+
{ value: "mistral", label: "Mistral" }
|
|
1923
2093
|
]
|
|
1924
2094
|
}),
|
|
1925
2095
|
llmApiKey: async ({ results: { llmProvider } }) => {
|
|
@@ -2025,7 +2195,7 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
2025
2195
|
return mastraProject;
|
|
2026
2196
|
};
|
|
2027
2197
|
var s = Y();
|
|
2028
|
-
var
|
|
2198
|
+
var exec3 = util.promisify(child_process.exec);
|
|
2029
2199
|
var init = async ({
|
|
2030
2200
|
directory,
|
|
2031
2201
|
addExample = false,
|
|
@@ -2074,10 +2244,11 @@ var init = async ({
|
|
|
2074
2244
|
}
|
|
2075
2245
|
const key = await getAPIKey(llmProvider || "openai");
|
|
2076
2246
|
const aiSdkPackage = getAISDKPackage(llmProvider);
|
|
2247
|
+
const aiSdkPackageVersion = getAISDKPackageVersion(llmProvider);
|
|
2077
2248
|
const depsService = new DepsService();
|
|
2078
2249
|
const pm = depsService.packageManager;
|
|
2079
|
-
const installCommand =
|
|
2080
|
-
await
|
|
2250
|
+
const installCommand = getPackageManagerAddCommand(pm);
|
|
2251
|
+
await exec3(`${pm} ${installCommand} ${aiSdkPackage}@${aiSdkPackageVersion}`);
|
|
2081
2252
|
if (configureEditorWithDocsMCP) {
|
|
2082
2253
|
await installMastraDocsMCPServer({
|
|
2083
2254
|
editor: configureEditorWithDocsMCP,
|
|
@@ -2104,10 +2275,10 @@ var init = async ({
|
|
|
2104
2275
|
return { success: false };
|
|
2105
2276
|
}
|
|
2106
2277
|
};
|
|
2107
|
-
var
|
|
2278
|
+
var exec4 = util.promisify(child_process.exec);
|
|
2108
2279
|
var execWithTimeout = async (command, timeoutMs) => {
|
|
2109
2280
|
try {
|
|
2110
|
-
const promise =
|
|
2281
|
+
const promise = exec4(command, { killSignal: "SIGTERM" });
|
|
2111
2282
|
if (!timeoutMs) {
|
|
2112
2283
|
return await promise;
|
|
2113
2284
|
}
|
|
@@ -2131,9 +2302,9 @@ var execWithTimeout = async (command, timeoutMs) => {
|
|
|
2131
2302
|
}
|
|
2132
2303
|
};
|
|
2133
2304
|
async function installMastraDependency(pm, dependency, versionTag, isDev, timeout) {
|
|
2134
|
-
let installCommand =
|
|
2305
|
+
let installCommand = getPackageManagerAddCommand(pm);
|
|
2135
2306
|
if (isDev) {
|
|
2136
|
-
installCommand = `${installCommand}
|
|
2307
|
+
installCommand = `${installCommand} -D`;
|
|
2137
2308
|
}
|
|
2138
2309
|
try {
|
|
2139
2310
|
await execWithTimeout(`${pm} ${installCommand} ${dependency}${versionTag}`, timeout);
|
|
@@ -2171,7 +2342,7 @@ var createMastraProject = async ({
|
|
|
2171
2342
|
try {
|
|
2172
2343
|
s2.start("Creating project");
|
|
2173
2344
|
try {
|
|
2174
|
-
await
|
|
2345
|
+
await fs.mkdir(projectName);
|
|
2175
2346
|
} catch (error) {
|
|
2176
2347
|
if (error instanceof Error && "code" in error && error.code === "EEXIST") {
|
|
2177
2348
|
s2.stop(`A directory named "${projectName}" already exists. Please choose a different name.`);
|
|
@@ -2183,12 +2354,12 @@ var createMastraProject = async ({
|
|
|
2183
2354
|
}
|
|
2184
2355
|
process.chdir(projectName);
|
|
2185
2356
|
const pm = getPackageManager();
|
|
2186
|
-
const installCommand =
|
|
2357
|
+
const installCommand = getPackageManagerAddCommand(pm);
|
|
2187
2358
|
s2.message("Initializing project structure");
|
|
2188
2359
|
try {
|
|
2189
|
-
await
|
|
2190
|
-
await
|
|
2191
|
-
await
|
|
2360
|
+
await exec4(`npm init -y`);
|
|
2361
|
+
await exec4(`npm pkg set type="module"`);
|
|
2362
|
+
await exec4(`npm pkg set engines.node=">=20.9.0"`);
|
|
2192
2363
|
const depsService = new DepsService();
|
|
2193
2364
|
await depsService.addScriptsToPackageJson({
|
|
2194
2365
|
dev: "mastra dev",
|
|
@@ -2203,9 +2374,9 @@ var createMastraProject = async ({
|
|
|
2203
2374
|
s2.stop("Project structure created");
|
|
2204
2375
|
s2.start(`Installing ${pm} dependencies`);
|
|
2205
2376
|
try {
|
|
2206
|
-
await
|
|
2207
|
-
await
|
|
2208
|
-
await
|
|
2377
|
+
await exec4(`${pm} ${installCommand} zod@^3`);
|
|
2378
|
+
await exec4(`${pm} ${installCommand} typescript @types/node --save-dev`);
|
|
2379
|
+
await exec4(`echo '{
|
|
2209
2380
|
"compilerOptions": {
|
|
2210
2381
|
"target": "ES2022",
|
|
2211
2382
|
"module": "ES2022",
|
|
@@ -2248,14 +2419,14 @@ var createMastraProject = async ({
|
|
|
2248
2419
|
s2.stop("Mastra dependencies installed");
|
|
2249
2420
|
s2.start("Adding .gitignore");
|
|
2250
2421
|
try {
|
|
2251
|
-
await
|
|
2252
|
-
await
|
|
2253
|
-
await
|
|
2254
|
-
await
|
|
2255
|
-
await
|
|
2256
|
-
await
|
|
2257
|
-
await
|
|
2258
|
-
await
|
|
2422
|
+
await exec4(`echo output.txt >> .gitignore`);
|
|
2423
|
+
await exec4(`echo node_modules >> .gitignore`);
|
|
2424
|
+
await exec4(`echo dist >> .gitignore`);
|
|
2425
|
+
await exec4(`echo .mastra >> .gitignore`);
|
|
2426
|
+
await exec4(`echo .env.development >> .gitignore`);
|
|
2427
|
+
await exec4(`echo .env >> .gitignore`);
|
|
2428
|
+
await exec4(`echo *.db >> .gitignore`);
|
|
2429
|
+
await exec4(`echo *.db-* >> .gitignore`);
|
|
2259
2430
|
} catch (error) {
|
|
2260
2431
|
throw new Error(`Failed to create .gitignore: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2261
2432
|
}
|
|
@@ -2271,6 +2442,10 @@ var createMastraProject = async ({
|
|
|
2271
2442
|
}
|
|
2272
2443
|
};
|
|
2273
2444
|
var create = async (args2) => {
|
|
2445
|
+
if (args2.template !== void 0) {
|
|
2446
|
+
await createFromTemplate({ ...args2, injectedAnalytics: args2.analytics });
|
|
2447
|
+
return;
|
|
2448
|
+
}
|
|
2274
2449
|
const { projectName } = await createMastraProject({
|
|
2275
2450
|
projectName: args2?.projectName,
|
|
2276
2451
|
createVersionTag: args2?.createVersionTag,
|
|
@@ -2308,11 +2483,165 @@ var postCreate = ({ projectName }) => {
|
|
|
2308
2483
|
${color2.cyan(`${packageManager} run dev`)}
|
|
2309
2484
|
`);
|
|
2310
2485
|
};
|
|
2486
|
+
function isGitHubUrl(url) {
|
|
2487
|
+
try {
|
|
2488
|
+
const parsedUrl = new URL(url);
|
|
2489
|
+
return parsedUrl.hostname === "github.com" && parsedUrl.pathname.split("/").length >= 3;
|
|
2490
|
+
} catch {
|
|
2491
|
+
return false;
|
|
2492
|
+
}
|
|
2493
|
+
}
|
|
2494
|
+
async function validateGitHubProject(githubUrl) {
|
|
2495
|
+
const errors = [];
|
|
2496
|
+
try {
|
|
2497
|
+
const urlParts = new URL(githubUrl).pathname.split("/").filter(Boolean);
|
|
2498
|
+
const owner = urlParts[0];
|
|
2499
|
+
const repo = urlParts[1]?.replace(".git", "");
|
|
2500
|
+
if (!owner || !repo) {
|
|
2501
|
+
throw new Error("Invalid GitHub URL format");
|
|
2502
|
+
}
|
|
2503
|
+
const branches = ["main", "master"];
|
|
2504
|
+
let packageJsonContent = null;
|
|
2505
|
+
let indexContent = null;
|
|
2506
|
+
for (const branch of branches) {
|
|
2507
|
+
try {
|
|
2508
|
+
const packageJsonUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/package.json`;
|
|
2509
|
+
const packageJsonResponse = await fetch(packageJsonUrl);
|
|
2510
|
+
if (packageJsonResponse.ok) {
|
|
2511
|
+
packageJsonContent = await packageJsonResponse.text();
|
|
2512
|
+
const indexUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/src/mastra/index.ts`;
|
|
2513
|
+
const indexResponse = await fetch(indexUrl);
|
|
2514
|
+
if (indexResponse.ok) {
|
|
2515
|
+
indexContent = await indexResponse.text();
|
|
2516
|
+
}
|
|
2517
|
+
break;
|
|
2518
|
+
}
|
|
2519
|
+
} catch {
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
if (!packageJsonContent) {
|
|
2523
|
+
errors.push("Could not fetch package.json from repository");
|
|
2524
|
+
return { isValid: false, errors };
|
|
2525
|
+
}
|
|
2526
|
+
try {
|
|
2527
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
2528
|
+
const hasMastraCore = packageJson.dependencies?.["@mastra/core"] || packageJson.devDependencies?.["@mastra/core"] || packageJson.peerDependencies?.["@mastra/core"];
|
|
2529
|
+
if (!hasMastraCore) {
|
|
2530
|
+
errors.push("Missing @mastra/core dependency in package.json");
|
|
2531
|
+
}
|
|
2532
|
+
} catch {
|
|
2533
|
+
errors.push("Invalid package.json format");
|
|
2534
|
+
}
|
|
2535
|
+
if (!indexContent) {
|
|
2536
|
+
errors.push("Missing src/mastra/index.ts file");
|
|
2537
|
+
} else {
|
|
2538
|
+
const hasMastraExport = indexContent.includes("export") && (indexContent.includes("new Mastra") || indexContent.includes("Mastra("));
|
|
2539
|
+
if (!hasMastraExport) {
|
|
2540
|
+
errors.push("src/mastra/index.ts does not export a Mastra instance");
|
|
2541
|
+
}
|
|
2542
|
+
}
|
|
2543
|
+
return { isValid: errors.length === 0, errors };
|
|
2544
|
+
} catch (error) {
|
|
2545
|
+
errors.push(`Failed to validate GitHub repository: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2546
|
+
return { isValid: false, errors };
|
|
2547
|
+
}
|
|
2548
|
+
}
|
|
2549
|
+
async function createFromGitHubUrl(url) {
|
|
2550
|
+
const urlParts = new URL(url).pathname.split("/").filter(Boolean);
|
|
2551
|
+
const owner = urlParts[0] || "unknown";
|
|
2552
|
+
const repo = urlParts[1] || "unknown";
|
|
2553
|
+
return {
|
|
2554
|
+
githubUrl: url,
|
|
2555
|
+
title: `${owner}/${repo}`,
|
|
2556
|
+
slug: repo,
|
|
2557
|
+
agents: [],
|
|
2558
|
+
mcp: [],
|
|
2559
|
+
tools: [],
|
|
2560
|
+
networks: [],
|
|
2561
|
+
workflows: []
|
|
2562
|
+
};
|
|
2563
|
+
}
|
|
2564
|
+
async function createFromTemplate(args2) {
|
|
2565
|
+
let selectedTemplate;
|
|
2566
|
+
if (args2.template === true) {
|
|
2567
|
+
const templates = await loadTemplates();
|
|
2568
|
+
const selected = await selectTemplate(templates);
|
|
2569
|
+
if (!selected) {
|
|
2570
|
+
M.info("No template selected. Exiting.");
|
|
2571
|
+
return;
|
|
2572
|
+
}
|
|
2573
|
+
selectedTemplate = selected;
|
|
2574
|
+
} else if (args2.template && typeof args2.template === "string") {
|
|
2575
|
+
if (isGitHubUrl(args2.template)) {
|
|
2576
|
+
const spinner5 = Y();
|
|
2577
|
+
spinner5.start("Validating GitHub repository...");
|
|
2578
|
+
const validation = await validateGitHubProject(args2.template);
|
|
2579
|
+
if (!validation.isValid) {
|
|
2580
|
+
spinner5.stop("Validation failed");
|
|
2581
|
+
M.error("This does not appear to be a valid Mastra project:");
|
|
2582
|
+
validation.errors.forEach((error) => M.error(` - ${error}`));
|
|
2583
|
+
throw new Error("Invalid Mastra project");
|
|
2584
|
+
}
|
|
2585
|
+
spinner5.stop("Valid Mastra project \u2713");
|
|
2586
|
+
selectedTemplate = await createFromGitHubUrl(args2.template);
|
|
2587
|
+
} else {
|
|
2588
|
+
const templates = await loadTemplates();
|
|
2589
|
+
const found = findTemplateByName(templates, args2.template);
|
|
2590
|
+
if (!found) {
|
|
2591
|
+
M.error(`Template "${args2.template}" not found. Available templates:`);
|
|
2592
|
+
templates.forEach((t) => M.info(` - ${t.title} (use: ${t.slug.replace("template-", "")})`));
|
|
2593
|
+
throw new Error(`Template "${args2.template}" not found`);
|
|
2594
|
+
}
|
|
2595
|
+
selectedTemplate = found;
|
|
2596
|
+
}
|
|
2597
|
+
}
|
|
2598
|
+
if (!selectedTemplate) {
|
|
2599
|
+
throw new Error("No template selected");
|
|
2600
|
+
}
|
|
2601
|
+
let projectName = args2.projectName;
|
|
2602
|
+
if (!projectName) {
|
|
2603
|
+
const defaultName = getDefaultProjectName(selectedTemplate);
|
|
2604
|
+
const response = await he({
|
|
2605
|
+
message: "What is your project name?",
|
|
2606
|
+
defaultValue: defaultName,
|
|
2607
|
+
placeholder: defaultName
|
|
2608
|
+
});
|
|
2609
|
+
if (pD(response)) {
|
|
2610
|
+
M.info("Project creation cancelled.");
|
|
2611
|
+
return;
|
|
2612
|
+
}
|
|
2613
|
+
projectName = response;
|
|
2614
|
+
}
|
|
2615
|
+
try {
|
|
2616
|
+
const analytics = args2.injectedAnalytics || getAnalytics();
|
|
2617
|
+
if (analytics) {
|
|
2618
|
+
analytics.trackEvent("cli_template_used", {
|
|
2619
|
+
template_slug: selectedTemplate.slug,
|
|
2620
|
+
template_title: selectedTemplate.title
|
|
2621
|
+
});
|
|
2622
|
+
}
|
|
2623
|
+
const projectPath = await cloneTemplate({
|
|
2624
|
+
template: selectedTemplate,
|
|
2625
|
+
projectName
|
|
2626
|
+
});
|
|
2627
|
+
await installDependencies(projectPath);
|
|
2628
|
+
Me(`
|
|
2629
|
+
${color2.green("Mastra template installed!")}
|
|
2630
|
+
|
|
2631
|
+
Add the necessary environment
|
|
2632
|
+
variables in your ${color2.cyan(".env")} file
|
|
2633
|
+
`);
|
|
2634
|
+
postCreate({ projectName });
|
|
2635
|
+
} catch (error) {
|
|
2636
|
+
M.error(`Failed to create project from template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2637
|
+
throw error;
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2311
2640
|
|
|
2312
2641
|
async function getPackageVersion() {
|
|
2313
2642
|
const __filename = fileURLToPath(import.meta.url);
|
|
2314
2643
|
const __dirname = dirname(__filename);
|
|
2315
|
-
const pkgJsonPath =
|
|
2644
|
+
const pkgJsonPath = path3.join(__dirname, "..", "package.json");
|
|
2316
2645
|
const content = await fsExtra.readJSON(pkgJsonPath);
|
|
2317
2646
|
return content.version;
|
|
2318
2647
|
}
|
|
@@ -2350,7 +2679,10 @@ program.version(`${version}`, "-v, --version").description(`create-mastra ${vers
|
|
|
2350
2679
|
program.name("create-mastra").description("Create a new Mastra project").argument("[project-name]", "Directory name of the project").option(
|
|
2351
2680
|
"-p, --project-name <string>",
|
|
2352
2681
|
"Project name that will be used in package.json and as the project directory name."
|
|
2353
|
-
).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)").
|
|
2682
|
+
).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(
|
|
2683
|
+
"--template [template-name]",
|
|
2684
|
+
"Create project from a template (use template name, public GitHub URL, or leave blank to select from list)"
|
|
2685
|
+
).action(async (projectNameArg, args) => {
|
|
2354
2686
|
const projectName = projectNameArg || args.projectName;
|
|
2355
2687
|
const timeout = args?.timeout ? args?.timeout === true ? 6e4 : parseInt(args?.timeout, 10) : void 0;
|
|
2356
2688
|
if (args.default) {
|
|
@@ -2361,7 +2693,9 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
|
|
|
2361
2693
|
createVersionTag,
|
|
2362
2694
|
timeout,
|
|
2363
2695
|
mcpServer: args.mcp,
|
|
2364
|
-
directory: "src/"
|
|
2696
|
+
directory: "src/",
|
|
2697
|
+
template: args.template,
|
|
2698
|
+
analytics
|
|
2365
2699
|
});
|
|
2366
2700
|
return;
|
|
2367
2701
|
}
|
|
@@ -2374,7 +2708,9 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
|
|
|
2374
2708
|
timeout,
|
|
2375
2709
|
projectName,
|
|
2376
2710
|
directory: args.dir,
|
|
2377
|
-
mcpServer: args.mcp
|
|
2711
|
+
mcpServer: args.mcp,
|
|
2712
|
+
template: args.template,
|
|
2713
|
+
analytics
|
|
2378
2714
|
});
|
|
2379
2715
|
});
|
|
2380
2716
|
program.parse(process.argv);
|