create-mastra 0.0.0-toolOptionTypes-20250917085558 → 0.0.0-trace-timeline-update-20251121092347

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,25 +1,25 @@
1
1
  #! /usr/bin/env node
2
2
  import { Command } from 'commander';
3
3
  import { randomUUID } from 'node:crypto';
4
- import * as fs4__default from 'node:fs';
5
- import fs4__default__default, { existsSync, readFileSync, writeFileSync } from 'node:fs';
4
+ import * as fs3__default from 'node:fs';
5
+ import fs3__default__default, { existsSync, readFileSync, writeFileSync } from 'node:fs';
6
6
  import os from 'node:os';
7
7
  import path3, { dirname } from 'node:path';
8
8
  import { fileURLToPath } from 'node:url';
9
9
  import { PostHog } from 'posthog-node';
10
+ import fs4 from 'node:fs/promises';
10
11
  import util, { stripVTControlCharacters } from 'node:util';
11
12
  import y$1, { stdout, stdin } from 'node:process';
12
13
  import * as g from 'node:readline';
13
14
  import g__default from 'node:readline';
14
15
  import { Writable } from 'node:stream';
15
- import fs5 from 'node:fs/promises';
16
16
  import child_process from 'node:child_process';
17
17
  import tty from 'node:tty';
18
- import pino from 'pino';
19
- import pretty from 'pino-pretty';
20
- import { execa } from 'execa';
21
18
  import fsExtra, { readJSON, ensureFile, writeJSON } from 'fs-extra/esm';
22
19
  import prettier from 'prettier';
20
+ import { execa } from 'execa';
21
+ import pino from 'pino';
22
+ import pretty from 'pino-pretty';
23
23
  import fsExtra$1 from 'fs-extra';
24
24
 
25
25
  var __filename = fileURLToPath(import.meta.url);
@@ -422,7 +422,7 @@ ${color2.gray(d)} ${t}
422
422
  `):process.stdout.write(`${w} ${l}
423
423
  `),E(),s();};return {start:H,stop:N,message:(m="")=>{l=R(m??l);}}},Ce=async(t,n)=>{const r={},i=Object.keys(t);for(const s of i){const c=t[s],a=await c({results:r})?.catch(l=>{throw l});if(typeof n?.onCancel=="function"&&pD(a)){r[s]="canceled",n.onCancel({results:r});continue}r[s]=a;}return r};
424
424
 
425
- var shellQuote$1 = {};
425
+ var shellQuote = {};
426
426
 
427
427
  var quote;
428
428
  var hasRequiredQuote;
@@ -688,16 +688,16 @@ function requireParse () {
688
688
  var hasRequiredShellQuote;
689
689
 
690
690
  function requireShellQuote () {
691
- if (hasRequiredShellQuote) return shellQuote$1;
691
+ if (hasRequiredShellQuote) return shellQuote;
692
692
  hasRequiredShellQuote = 1;
693
693
 
694
- shellQuote$1.quote = requireQuote();
695
- shellQuote$1.parse = requireParse();
696
- return shellQuote$1;
694
+ shellQuote.quote = requireQuote();
695
+ shellQuote.parse = requireParse();
696
+ return shellQuote;
697
697
  }
698
698
 
699
699
  var shellQuoteExports = requireShellQuote();
700
- var shellQuote = /*@__PURE__*/getDefaultExportFromCjs(shellQuoteExports);
700
+ var shellQuote2 = /*@__PURE__*/getDefaultExportFromCjs(shellQuoteExports);
701
701
 
702
702
  // eslint-disable-next-line no-warning-comments
703
703
  // TODO: Use a better method when it's added to Node.js (https://github.com/nodejs/node/pull/40240)
@@ -724,13 +724,18 @@ const format = (open, close) => {
724
724
  // Handle nested colors.
725
725
 
726
726
  // We could have done this, but it's too slow (as of Node.js 22).
727
- // return openCode + string.replaceAll(closeCode, openCode) + closeCode;
727
+ // return openCode + string.replaceAll(closeCode, (close === 22 ? closeCode : '') + openCode) + closeCode;
728
728
 
729
729
  let result = openCode;
730
730
  let lastIndex = 0;
731
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
+
732
737
  while (index !== -1) {
733
- result += string.slice(lastIndex, index) + openCode;
738
+ result += string.slice(lastIndex, index) + replaceCode;
734
739
  lastIndex = index + closeCode.length;
735
740
  index = string.indexOf(closeCode, lastIndex);
736
741
  }
@@ -882,6 +887,7 @@ class YoctoSpinner {
882
887
  #exitHandlerBound;
883
888
  #isInteractive;
884
889
  #lastSpinnerFrameTime = 0;
890
+ #isSpinning = false;
885
891
 
886
892
  constructor(options = {}) {
887
893
  const spinner = options.spinner ?? defaultSpinner;
@@ -903,13 +909,17 @@ class YoctoSpinner {
903
909
  return this;
904
910
  }
905
911
 
912
+ this.#isSpinning = true;
906
913
  this.#hideCursor();
907
914
  this.#render();
908
915
  this.#subscribeToProcessEvents();
909
916
 
910
- this.#timer = setInterval(() => {
911
- this.#render();
912
- }, this.#interval);
917
+ // Only start the timer in interactive mode
918
+ if (this.#isInteractive) {
919
+ this.#timer = setInterval(() => {
920
+ this.#render();
921
+ }, this.#interval);
922
+ }
913
923
 
914
924
  return this;
915
925
  }
@@ -919,8 +929,12 @@ class YoctoSpinner {
919
929
  return this;
920
930
  }
921
931
 
922
- clearInterval(this.#timer);
923
- this.#timer = undefined;
932
+ this.#isSpinning = false;
933
+ if (this.#timer) {
934
+ clearInterval(this.#timer);
935
+ this.#timer = undefined;
936
+ }
937
+
924
938
  this.#showCursor();
925
939
  this.clear();
926
940
  this.#unsubscribeFromProcessEvents();
@@ -953,7 +967,7 @@ class YoctoSpinner {
953
967
  }
954
968
 
955
969
  get isSpinning() {
956
- return this.#timer !== undefined;
970
+ return this.#isSpinning;
957
971
  }
958
972
 
959
973
  get text() {
@@ -1090,11 +1104,11 @@ var MastraLogger = class {
1090
1104
  }
1091
1105
  trackException(_error) {
1092
1106
  }
1093
- async getLogs(transportId, params) {
1107
+ async listLogs(transportId, params) {
1094
1108
  if (!transportId || !this.transports.has(transportId)) {
1095
1109
  return { logs: [], total: 0, page: params?.page ?? 1, perPage: params?.perPage ?? 100, hasMore: false };
1096
1110
  }
1097
- return this.transports.get(transportId).getLogs(params) ?? {
1111
+ return this.transports.get(transportId).listLogs(params) ?? {
1098
1112
  logs: [],
1099
1113
  total: 0,
1100
1114
  page: params?.page ?? 1,
@@ -1102,7 +1116,7 @@ var MastraLogger = class {
1102
1116
  hasMore: false
1103
1117
  };
1104
1118
  }
1105
- async getLogsByRunId({
1119
+ async listLogsByRunId({
1106
1120
  transportId,
1107
1121
  runId,
1108
1122
  fromDate,
@@ -1115,7 +1129,7 @@ var MastraLogger = class {
1115
1129
  if (!transportId || !this.transports.has(transportId) || !runId) {
1116
1130
  return { logs: [], total: 0, page: page ?? 1, perPage: perPage ?? 100, hasMore: false };
1117
1131
  }
1118
- return this.transports.get(transportId).getLogsByRunId({ runId, fromDate, toDate, logLevel, filters, page, perPage }) ?? {
1132
+ return this.transports.get(transportId).listLogsByRunId({ runId, fromDate, toDate, logLevel, filters, page, perPage }) ?? {
1119
1133
  logs: [],
1120
1134
  total: 0,
1121
1135
  page: page ?? 1,
@@ -1173,183 +1187,8 @@ var PinoLogger = class extends MastraLogger {
1173
1187
  }
1174
1188
  };
1175
1189
 
1176
- function getPackageManager() {
1177
- const userAgent = process.env.npm_config_user_agent || "";
1178
- const execPath = process.env.npm_execpath || "";
1179
- if (userAgent.includes("yarn")) {
1180
- return "yarn";
1181
- }
1182
- if (userAgent.includes("pnpm")) {
1183
- return "pnpm";
1184
- }
1185
- if (userAgent.includes("npm")) {
1186
- return "npm";
1187
- }
1188
- if (execPath.includes("yarn")) {
1189
- return "yarn";
1190
- }
1191
- if (execPath.includes("pnpm")) {
1192
- return "pnpm";
1193
- }
1194
- if (execPath.includes("npm")) {
1195
- return "npm";
1196
- }
1197
- return "npm";
1198
- }
1199
- var logger = new PinoLogger({
1200
- name: "Mastra CLI",
1201
- level: "info"
1202
- });
1203
- var exec = util.promisify(child_process.exec);
1204
- async function cloneTemplate(options) {
1205
- const { template, projectName, targetDir } = options;
1206
- const projectPath = targetDir ? path3.resolve(targetDir, projectName) : path3.resolve(projectName);
1207
- const spinner5 = yoctoSpinner({ text: `Cloning template "${template.title}"...` }).start();
1208
- try {
1209
- if (await directoryExists(projectPath)) {
1210
- spinner5.error(`Directory ${projectName} already exists`);
1211
- throw new Error(`Directory ${projectName} already exists`);
1212
- }
1213
- await cloneRepositoryWithoutGit(template.githubUrl, projectPath);
1214
- await updatePackageJson(projectPath, projectName);
1215
- const envExamplePath = path3.join(projectPath, ".env.example");
1216
- if (await fileExists(envExamplePath)) {
1217
- await fs5.copyFile(envExamplePath, path3.join(projectPath, ".env"));
1218
- }
1219
- spinner5.success(`Template "${template.title}" cloned successfully to ${projectName}`);
1220
- return projectPath;
1221
- } catch (error) {
1222
- spinner5.error(`Failed to clone template: ${error instanceof Error ? error.message : "Unknown error"}`);
1223
- throw error;
1224
- }
1225
- }
1226
- async function directoryExists(dirPath) {
1227
- try {
1228
- const stat = await fs5.stat(dirPath);
1229
- return stat.isDirectory();
1230
- } catch {
1231
- return false;
1232
- }
1233
- }
1234
- async function fileExists(filePath) {
1235
- try {
1236
- const stat = await fs5.stat(filePath);
1237
- return stat.isFile();
1238
- } catch {
1239
- return false;
1240
- }
1241
- }
1242
- async function cloneRepositoryWithoutGit(repoUrl, targetPath) {
1243
- await fs5.mkdir(targetPath, { recursive: true });
1244
- try {
1245
- const degitRepo = repoUrl.replace("https://github.com/", "");
1246
- const degitCommand = shellQuote.quote(["npx", "degit", degitRepo, targetPath]);
1247
- await exec(degitCommand, {
1248
- cwd: process.cwd()
1249
- });
1250
- } catch {
1251
- try {
1252
- const gitCommand = shellQuote.quote(["git", "clone", repoUrl, targetPath]);
1253
- await exec(gitCommand, {
1254
- cwd: process.cwd()
1255
- });
1256
- const gitDir = path3.join(targetPath, ".git");
1257
- if (await directoryExists(gitDir)) {
1258
- await fs5.rm(gitDir, { recursive: true, force: true });
1259
- }
1260
- } catch (gitError) {
1261
- throw new Error(`Failed to clone repository: ${gitError instanceof Error ? gitError.message : "Unknown error"}`);
1262
- }
1263
- }
1264
- }
1265
- async function updatePackageJson(projectPath, projectName) {
1266
- const packageJsonPath = path3.join(projectPath, "package.json");
1267
- try {
1268
- const packageJsonContent = await fs5.readFile(packageJsonPath, "utf-8");
1269
- const packageJson = JSON.parse(packageJsonContent);
1270
- packageJson.name = projectName;
1271
- await fs5.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf-8");
1272
- } catch (error) {
1273
- logger.warn(`Could not update package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
1274
- }
1275
- }
1276
- async function installDependencies(projectPath, packageManager) {
1277
- const spinner5 = yoctoSpinner({ text: "Installing dependencies..." }).start();
1278
- try {
1279
- const pm = packageManager || getPackageManager();
1280
- const installCommand = shellQuote.quote([pm, "install"]);
1281
- await exec(installCommand, {
1282
- cwd: projectPath
1283
- });
1284
- spinner5.success("Dependencies installed successfully");
1285
- } catch (error) {
1286
- spinner5.error(`Failed to install dependencies: ${error instanceof Error ? error.message : "Unknown error"}`);
1287
- throw error;
1288
- }
1289
- }
1290
- var TEMPLATES_API_URL = process.env.MASTRA_TEMPLATES_API_URL || "https://mastra.ai/api/templates.json";
1291
- async function loadTemplates() {
1292
- try {
1293
- const response = await fetch(TEMPLATES_API_URL);
1294
- if (!response.ok) {
1295
- throw new Error(`Failed to fetch templates: ${response.statusText}`);
1296
- }
1297
- const templates = await response.json();
1298
- return templates;
1299
- } catch (error) {
1300
- console.error("Error loading templates:", error);
1301
- throw new Error("Failed to load templates. Please check your internet connection and try again.");
1302
- }
1303
- }
1304
- function pluralize(count, singular, plural) {
1305
- return count === 1 ? singular : plural || `${singular}s`;
1306
- }
1307
- async function selectTemplate(templates) {
1308
- const choices = templates.map((template) => {
1309
- const parts = [];
1310
- if (template.agents?.length) {
1311
- parts.push(`${template.agents.length} ${pluralize(template.agents.length, "agent")}`);
1312
- }
1313
- if (template.tools?.length) {
1314
- parts.push(`${template.tools.length} ${pluralize(template.tools.length, "tool")}`);
1315
- }
1316
- if (template.workflows?.length) {
1317
- parts.push(`${template.workflows.length} ${pluralize(template.workflows.length, "workflow")}`);
1318
- }
1319
- if (template.mcp?.length) {
1320
- parts.push(`${template.mcp.length} ${pluralize(template.mcp.length, "MCP server")}`);
1321
- }
1322
- if (template.networks?.length) {
1323
- parts.push(`${template.networks.length} ${pluralize(template.networks.length, "agent network")}`);
1324
- }
1325
- return {
1326
- value: template,
1327
- label: template.title,
1328
- hint: parts.join(", ") || "Template components"
1329
- };
1330
- });
1331
- const selected = await ve({
1332
- message: "Select a template:",
1333
- options: choices
1334
- });
1335
- if (pD(selected)) {
1336
- return null;
1337
- }
1338
- return selected;
1339
- }
1340
- function findTemplateByName(templates, templateName) {
1341
- let template = templates.find((t) => t.slug === templateName);
1342
- if (template) return template;
1343
- const slugWithPrefix = `template-${templateName}`;
1344
- template = templates.find((t) => t.slug === slugWithPrefix);
1345
- if (template) return template;
1346
- template = templates.find((t) => t.title.toLowerCase() === templateName.toLowerCase());
1347
- if (template) return template;
1348
- return null;
1349
- }
1350
- function getDefaultProjectName(template) {
1351
- return template.slug.replace(/^template-/, "");
1352
- }
1190
+ var package_default = {
1191
+ version: "1.0.0-beta.3"};
1353
1192
  function getPackageManagerAddCommand(pm) {
1354
1193
  switch (pm) {
1355
1194
  case "npm":
@@ -1372,7 +1211,7 @@ var DepsService = class {
1372
1211
  findLockFile(dir) {
1373
1212
  const lockFiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lock"];
1374
1213
  for (const file of lockFiles) {
1375
- if (fs4__default__default.existsSync(path3.join(dir, file))) {
1214
+ if (fs3__default__default.existsSync(path3.join(dir, file))) {
1376
1215
  return file;
1377
1216
  }
1378
1217
  }
@@ -1411,11 +1250,11 @@ var DepsService = class {
1411
1250
  try {
1412
1251
  const packageJsonPath = path3.join(process.cwd(), "package.json");
1413
1252
  try {
1414
- await fs5.access(packageJsonPath);
1253
+ await fs4.access(packageJsonPath);
1415
1254
  } catch {
1416
1255
  return "No package.json file found in the current directory";
1417
1256
  }
1418
- const packageJson = JSON.parse(await fs5.readFile(packageJsonPath, "utf-8"));
1257
+ const packageJson = JSON.parse(await fs4.readFile(packageJsonPath, "utf-8"));
1419
1258
  for (const dependency of dependencies) {
1420
1259
  if (!packageJson.dependencies || !packageJson.dependencies[dependency]) {
1421
1260
  return `Please install ${dependency} before running this command (${this.packageManager} install ${dependency})`;
@@ -1430,7 +1269,7 @@ var DepsService = class {
1430
1269
  async getProjectName() {
1431
1270
  try {
1432
1271
  const packageJsonPath = path3.join(process.cwd(), "package.json");
1433
- const packageJson = await fs5.readFile(packageJsonPath, "utf-8");
1272
+ const packageJson = await fs4.readFile(packageJsonPath, "utf-8");
1434
1273
  const pkg = JSON.parse(packageJson);
1435
1274
  return pkg.name;
1436
1275
  } catch (err) {
@@ -1438,166 +1277,54 @@ var DepsService = class {
1438
1277
  }
1439
1278
  }
1440
1279
  async addScriptsToPackageJson(scripts) {
1441
- const packageJson = JSON.parse(await fs5.readFile("package.json", "utf-8"));
1280
+ const packageJson = JSON.parse(await fs4.readFile("package.json", "utf-8"));
1442
1281
  packageJson.scripts = {
1443
1282
  ...packageJson.scripts,
1444
1283
  ...scripts
1445
1284
  };
1446
- await fs5.writeFile("package.json", JSON.stringify(packageJson, null, 2));
1285
+ await fs4.writeFile("package.json", JSON.stringify(packageJson, null, 2));
1447
1286
  }
1448
1287
  };
1449
- var args = ["-y", "@mastra/mcp-docs-server"];
1450
- var createMcpConfig = (editor) => {
1451
- if (editor === "vscode") {
1452
- return {
1453
- servers: {
1454
- mastra: process.platform === `win32` ? {
1455
- command: "cmd",
1456
- args: ["/c", "npx", ...args],
1457
- type: "stdio"
1458
- } : {
1459
- command: "npx",
1460
- args,
1461
- type: "stdio"
1462
- }
1463
- }
1464
- };
1465
- }
1466
- return {
1467
- mcpServers: {
1468
- mastra: {
1469
- command: "npx",
1470
- args
1471
- }
1472
- }
1473
- };
1288
+ var EnvService = class {
1474
1289
  };
1475
- function makeConfig(original, editor) {
1476
- if (editor === "vscode") {
1477
- return {
1478
- ...original,
1479
- servers: {
1480
- ...original?.servers || {},
1481
- ...createMcpConfig(editor).servers
1482
- }
1483
- };
1484
- }
1485
- return {
1486
- ...original,
1487
- mcpServers: {
1488
- ...original?.mcpServers || {},
1489
- ...createMcpConfig(editor).mcpServers
1490
- }
1491
- };
1492
- }
1493
- async function writeMergedConfig(configPath, editor) {
1494
- const configExists = existsSync(configPath);
1495
- const config = makeConfig(configExists ? await readJSON(configPath) : {}, editor);
1496
- await ensureFile(configPath);
1497
- await writeJSON(configPath, config, {
1498
- spaces: 2
1499
- });
1500
- }
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(
1505
- os.homedir(),
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")
1507
- );
1508
- async function installMastraDocsMCPServer({ editor, directory }) {
1509
- if (editor === `cursor`) {
1510
- await writeMergedConfig(path3.join(directory, ".cursor", "mcp.json"), "cursor");
1290
+ var FileEnvService = class extends EnvService {
1291
+ filePath;
1292
+ constructor(filePath) {
1293
+ super();
1294
+ this.filePath = filePath;
1511
1295
  }
1512
- if (editor === `vscode`) {
1513
- await writeMergedConfig(path3.join(directory, ".vscode", "mcp.json"), "vscode");
1296
+ readFile(filePath) {
1297
+ return new Promise((resolve, reject) => {
1298
+ fs3__default.readFile(filePath, "utf8", (err, data) => {
1299
+ if (err) reject(err);
1300
+ else resolve(data);
1301
+ });
1302
+ });
1514
1303
  }
1515
- if (editor === `cursor-global`) {
1516
- const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor);
1517
- if (alreadyInstalled) {
1518
- return;
1519
- }
1520
- await writeMergedConfig(cursorGlobalMCPConfigPath, "cursor-global");
1304
+ writeFile({ filePath, data }) {
1305
+ return new Promise((resolve, reject) => {
1306
+ fs3__default.writeFile(filePath, data, "utf8", (err) => {
1307
+ if (err) reject(err);
1308
+ else resolve();
1309
+ });
1310
+ });
1521
1311
  }
1522
- if (editor === `windsurf`) {
1523
- const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor);
1524
- if (alreadyInstalled) {
1525
- return;
1312
+ async updateEnvData({
1313
+ key,
1314
+ value,
1315
+ filePath = this.filePath,
1316
+ data
1317
+ }) {
1318
+ const regex = new RegExp(`^${key}=.*$`, "m");
1319
+ if (data.match(regex)) {
1320
+ data = data.replace(regex, `${key}=${value}`);
1321
+ } else {
1322
+ data += `
1323
+ ${key}=${value}`;
1526
1324
  }
1527
- await writeMergedConfig(windsurfGlobalMCPConfigPath, editor);
1528
- }
1529
- }
1530
- async function globalMCPIsAlreadyInstalled(editor) {
1531
- let configPath = ``;
1532
- if (editor === "windsurf") {
1533
- configPath = windsurfGlobalMCPConfigPath;
1534
- } else if (editor === "cursor-global") {
1535
- configPath = cursorGlobalMCPConfigPath;
1536
- } else if (editor === "vscode") {
1537
- configPath = vscodeGlobalMCPConfigPath;
1538
- }
1539
- if (!configPath || !existsSync(configPath)) {
1540
- return false;
1541
- }
1542
- try {
1543
- const configContents = await readJSON(configPath);
1544
- if (!configContents) return false;
1545
- if (editor === "vscode") {
1546
- if (!configContents.servers) return false;
1547
- const hasMastraMCP2 = Object.values(configContents.servers).some(
1548
- (server) => server?.args?.find((arg) => arg?.includes(`@mastra/mcp-docs-server`))
1549
- );
1550
- return hasMastraMCP2;
1551
- }
1552
- if (!configContents?.mcpServers) return false;
1553
- const hasMastraMCP = Object.values(configContents.mcpServers).some(
1554
- (server) => server?.args?.find((arg) => arg?.includes(`@mastra/mcp-docs-server`))
1555
- );
1556
- return hasMastraMCP;
1557
- } catch {
1558
- return false;
1559
- }
1560
- }
1561
- var EnvService = class {
1562
- };
1563
- var FileEnvService = class extends EnvService {
1564
- filePath;
1565
- constructor(filePath) {
1566
- super();
1567
- this.filePath = filePath;
1568
- }
1569
- readFile(filePath) {
1570
- return new Promise((resolve, reject) => {
1571
- fs4__default.readFile(filePath, "utf8", (err, data) => {
1572
- if (err) reject(err);
1573
- else resolve(data);
1574
- });
1575
- });
1576
- }
1577
- writeFile({ filePath, data }) {
1578
- return new Promise((resolve, reject) => {
1579
- fs4__default.writeFile(filePath, data, "utf8", (err) => {
1580
- if (err) reject(err);
1581
- else resolve();
1582
- });
1583
- });
1584
- }
1585
- async updateEnvData({
1586
- key,
1587
- value,
1588
- filePath = this.filePath,
1589
- data
1590
- }) {
1591
- const regex = new RegExp(`^${key}=.*$`, "m");
1592
- if (data.match(regex)) {
1593
- data = data.replace(regex, `${key}=${value}`);
1594
- } else {
1595
- data += `
1596
- ${key}=${value}`;
1597
- }
1598
- await this.writeFile({ filePath, data });
1599
- console.log(`${key} set to ${value} in ENV file.`);
1600
- return data;
1325
+ await this.writeFile({ filePath, data });
1326
+ console.info(`${key} set to ${value} in ENV file.`);
1327
+ return data;
1601
1328
  }
1602
1329
  async getEnvValue(key) {
1603
1330
  try {
@@ -1631,9 +1358,9 @@ var FileService = class {
1631
1358
  const __filename = fileURLToPath(import.meta.url);
1632
1359
  const __dirname = path3.dirname(__filename);
1633
1360
  const filePath = path3.resolve(__dirname, "starter-files", inputFile);
1634
- const fileString = fs4__default__default.readFileSync(filePath, "utf8");
1635
- if (fs4__default__default.existsSync(outputFilePath) && !replaceIfExists) {
1636
- console.log(`${outputFilePath} already exists`);
1361
+ const fileString = fs3__default__default.readFileSync(filePath, "utf8");
1362
+ if (fs3__default__default.existsSync(outputFilePath) && !replaceIfExists) {
1363
+ console.info(`${outputFilePath} already exists`);
1637
1364
  return false;
1638
1365
  }
1639
1366
  await fsExtra.outputFile(outputFilePath, fileString);
@@ -1647,7 +1374,7 @@ var FileService = class {
1647
1374
  }
1648
1375
  getFirstExistingFile(files) {
1649
1376
  for (const f of files) {
1650
- if (fs4__default__default.existsSync(f)) {
1377
+ if (fs3__default__default.existsSync(f)) {
1651
1378
  return f;
1652
1379
  }
1653
1380
  }
@@ -1657,66 +1384,152 @@ var FileService = class {
1657
1384
  filePath,
1658
1385
  replacements
1659
1386
  }) {
1660
- let fileContent = fs4__default__default.readFileSync(filePath, "utf8");
1387
+ let fileContent = fs3__default__default.readFileSync(filePath, "utf8");
1661
1388
  replacements.forEach(({ search, replace }) => {
1662
1389
  fileContent = fileContent.replaceAll(search, replace);
1663
1390
  });
1664
- fs4__default__default.writeFileSync(filePath, fileContent);
1391
+ fs3__default__default.writeFileSync(filePath, fileContent);
1665
1392
  }
1666
1393
  };
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";
1674
- }
1394
+ var createArgs = (versionTag) => {
1395
+ const packageName = versionTag ? `@mastra/mcp-docs-server@${versionTag}` : "@mastra/mcp-docs-server";
1396
+ return ["-y", packageName];
1675
1397
  };
1676
- var getAISDKPackage = (llmProvider) => {
1677
- switch (llmProvider) {
1678
- case "openai":
1679
- return "@ai-sdk/openai";
1680
- case "anthropic":
1681
- return "@ai-sdk/anthropic";
1682
- case "groq":
1683
- return "@ai-sdk/groq";
1684
- case "google":
1685
- return "@ai-sdk/google";
1686
- case "cerebras":
1687
- return "@ai-sdk/cerebras";
1688
- case "mistral":
1689
- return "@ai-sdk/mistral";
1690
- default:
1691
- return "@ai-sdk/openai";
1398
+ var createMcpConfig = (editor, versionTag) => {
1399
+ const args = createArgs(versionTag);
1400
+ if (editor === "vscode") {
1401
+ return {
1402
+ servers: {
1403
+ mastra: process.platform === `win32` ? {
1404
+ command: "cmd",
1405
+ args: ["/c", "npx", ...args],
1406
+ type: "stdio"
1407
+ } : {
1408
+ command: "npx",
1409
+ args,
1410
+ type: "stdio"
1411
+ }
1412
+ }
1413
+ };
1692
1414
  }
1415
+ return {
1416
+ mcpServers: {
1417
+ mastra: {
1418
+ command: "npx",
1419
+ args
1420
+ }
1421
+ }
1422
+ };
1693
1423
  };
1694
- var getProviderImportAndModelItem = (llmProvider) => {
1695
- let providerImport = "";
1696
- let modelItem = "";
1697
- if (llmProvider === "openai") {
1698
- providerImport = `import { openai } from '${getAISDKPackage(llmProvider)}';`;
1699
- modelItem = `openai('gpt-4o-mini')`;
1700
- } else if (llmProvider === "anthropic") {
1701
- providerImport = `import { anthropic } from '${getAISDKPackage(llmProvider)}';`;
1702
- modelItem = `anthropic('claude-3-5-sonnet-20241022')`;
1424
+ function makeConfig(original, editor, versionTag) {
1425
+ if (editor === "vscode") {
1426
+ return {
1427
+ ...original,
1428
+ servers: {
1429
+ ...original?.servers || {},
1430
+ ...createMcpConfig(editor, versionTag).servers
1431
+ }
1432
+ };
1433
+ }
1434
+ return {
1435
+ ...original,
1436
+ mcpServers: {
1437
+ ...original?.mcpServers || {},
1438
+ ...createMcpConfig(editor, versionTag).mcpServers
1439
+ }
1440
+ };
1441
+ }
1442
+ async function writeMergedConfig(configPath, editor, versionTag) {
1443
+ const configExists = existsSync(configPath);
1444
+ const config = makeConfig(configExists ? await readJSON(configPath) : {}, editor, versionTag);
1445
+ await ensureFile(configPath);
1446
+ await writeJSON(configPath, config, {
1447
+ spaces: 2
1448
+ });
1449
+ }
1450
+ var windsurfGlobalMCPConfigPath = path3.join(os.homedir(), ".codeium", "windsurf", "mcp_config.json");
1451
+ var cursorGlobalMCPConfigPath = path3.join(os.homedir(), ".cursor", "mcp.json");
1452
+ path3.join(process.cwd(), ".vscode", "mcp.json");
1453
+ var vscodeGlobalMCPConfigPath = path3.join(
1454
+ os.homedir(),
1455
+ 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")
1456
+ );
1457
+ async function installMastraDocsMCPServer({
1458
+ editor,
1459
+ directory,
1460
+ versionTag
1461
+ }) {
1462
+ if (editor === `cursor`) {
1463
+ await writeMergedConfig(path3.join(directory, ".cursor", "mcp.json"), "cursor", versionTag);
1464
+ }
1465
+ if (editor === `vscode`) {
1466
+ await writeMergedConfig(path3.join(directory, ".vscode", "mcp.json"), "vscode", versionTag);
1467
+ }
1468
+ if (editor === `cursor-global`) {
1469
+ const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor, versionTag);
1470
+ if (alreadyInstalled) {
1471
+ return;
1472
+ }
1473
+ await writeMergedConfig(cursorGlobalMCPConfigPath, "cursor-global", versionTag);
1474
+ }
1475
+ if (editor === `windsurf`) {
1476
+ const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor, versionTag);
1477
+ if (alreadyInstalled) {
1478
+ return;
1479
+ }
1480
+ await writeMergedConfig(windsurfGlobalMCPConfigPath, editor, versionTag);
1481
+ }
1482
+ }
1483
+ async function globalMCPIsAlreadyInstalled(editor, versionTag) {
1484
+ let configPath = ``;
1485
+ if (editor === "windsurf") {
1486
+ configPath = windsurfGlobalMCPConfigPath;
1487
+ } else if (editor === "cursor-global") {
1488
+ configPath = cursorGlobalMCPConfigPath;
1489
+ } else if (editor === "vscode") {
1490
+ configPath = vscodeGlobalMCPConfigPath;
1491
+ }
1492
+ if (!configPath || !existsSync(configPath)) {
1493
+ return false;
1494
+ }
1495
+ try {
1496
+ const configContents = await readJSON(configPath);
1497
+ if (!configContents) return false;
1498
+ const expectedPackage = versionTag ? `@mastra/mcp-docs-server@${versionTag}` : "@mastra/mcp-docs-server";
1499
+ if (editor === "vscode") {
1500
+ if (!configContents.servers) return false;
1501
+ const hasMastraMCP2 = Object.values(configContents.servers).some(
1502
+ (server) => server?.args?.find((arg) => arg === expectedPackage)
1503
+ );
1504
+ return hasMastraMCP2;
1505
+ }
1506
+ if (!configContents?.mcpServers) return false;
1507
+ const hasMastraMCP = Object.values(configContents.mcpServers).some(
1508
+ (server) => server?.args?.find((arg) => arg === expectedPackage)
1509
+ );
1510
+ return hasMastraMCP;
1511
+ } catch {
1512
+ return false;
1513
+ }
1514
+ }
1515
+ var exec = util.promisify(child_process.exec);
1516
+ var getModelIdentifier = (llmProvider) => {
1517
+ let model = "openai/gpt-4o";
1518
+ if (llmProvider === "anthropic") {
1519
+ model = "anthropic/claude-sonnet-4-5";
1703
1520
  } else if (llmProvider === "groq") {
1704
- providerImport = `import { groq } from '${getAISDKPackage(llmProvider)}';`;
1705
- modelItem = `groq('llama-3.3-70b-versatile')`;
1521
+ model = "groq/llama-3.3-70b-versatile";
1706
1522
  } else if (llmProvider === "google") {
1707
- providerImport = `import { google } from '${getAISDKPackage(llmProvider)}';`;
1708
- modelItem = `google('gemini-2.5-pro')`;
1523
+ model = "google/gemini-2.5-pro";
1709
1524
  } else if (llmProvider === "cerebras") {
1710
- providerImport = `import { cerebras } from '${getAISDKPackage(llmProvider)}';`;
1711
- modelItem = `cerebras('llama-3.3-70b')`;
1525
+ model = "cerebras/llama-3.3-70b";
1712
1526
  } else if (llmProvider === "mistral") {
1713
- providerImport = `import { mistral } from '${getAISDKPackage(llmProvider)}';`;
1714
- modelItem = `mistral('mistral-medium-2508')`;
1527
+ model = "mistral/mistral-medium-2508";
1715
1528
  }
1716
- return { providerImport, modelItem };
1529
+ return model;
1717
1530
  };
1718
- async function writeAgentSample(llmProvider, destPath, addExampleTool) {
1719
- const { providerImport, modelItem } = getProviderImportAndModelItem(llmProvider);
1531
+ async function writeAgentSample(llmProvider, destPath, addExampleTool, addScorers) {
1532
+ const modelString = getModelIdentifier(llmProvider);
1720
1533
  const instructions = `
1721
1534
  You are a helpful weather assistant that provides accurate weather information and can help planning activities based on the weather.
1722
1535
 
@@ -1732,19 +1545,44 @@ async function writeAgentSample(llmProvider, destPath, addExampleTool) {
1732
1545
  ${addExampleTool ? "Use the weatherTool to fetch current weather data." : ""}
1733
1546
  `;
1734
1547
  const content = `
1735
- ${providerImport}
1736
1548
  import { Agent } from '@mastra/core/agent';
1737
1549
  import { Memory } from '@mastra/memory';
1738
1550
  import { LibSQLStore } from '@mastra/libsql';
1739
1551
  ${addExampleTool ? `import { weatherTool } from '../tools/weather-tool';` : ""}
1552
+ ${addScorers ? `import { scorers } from '../scorers/weather-scorer';` : ""}
1740
1553
 
1741
1554
  export const weatherAgent = new Agent({
1555
+ id: 'weather-agent',
1742
1556
  name: 'Weather Agent',
1743
1557
  instructions: \`${instructions}\`,
1744
- model: ${modelItem},
1558
+ model: '${modelString}',
1745
1559
  ${addExampleTool ? "tools: { weatherTool }," : ""}
1560
+ ${addScorers ? `scorers: {
1561
+ toolCallAppropriateness: {
1562
+ scorer: scorers.toolCallAppropriatenessScorer,
1563
+ sampling: {
1564
+ type: 'ratio',
1565
+ rate: 1,
1566
+ },
1567
+ },
1568
+ completeness: {
1569
+ scorer: scorers.completenessScorer,
1570
+ sampling: {
1571
+ type: 'ratio',
1572
+ rate: 1,
1573
+ },
1574
+ },
1575
+ translation: {
1576
+ scorer: scorers.translationScorer,
1577
+ sampling: {
1578
+ type: 'ratio',
1579
+ rate: 1,
1580
+ },
1581
+ },
1582
+ },` : ""}
1746
1583
  memory: new Memory({
1747
1584
  storage: new LibSQLStore({
1585
+ id: "memory-storage",
1748
1586
  url: "file:../mastra.db", // path is relative to the .mastra/output directory
1749
1587
  })
1750
1588
  })
@@ -1754,8 +1592,8 @@ export const weatherAgent = new Agent({
1754
1592
  parser: "typescript",
1755
1593
  singleQuote: true
1756
1594
  });
1757
- await fs5.writeFile(destPath, "");
1758
- await fs5.writeFile(destPath, formattedContent);
1595
+ await fs4.writeFile(destPath, "");
1596
+ await fs4.writeFile(destPath, formattedContent);
1759
1597
  }
1760
1598
  async function writeWorkflowSample(destPath) {
1761
1599
  const content = `import { createStep, createWorkflow } from '@mastra/core/workflows';
@@ -1948,20 +1786,115 @@ export { weatherWorkflow };`;
1948
1786
  semi: true,
1949
1787
  singleQuote: true
1950
1788
  });
1951
- await fs5.writeFile(destPath, formattedContent);
1789
+ await fs4.writeFile(destPath, formattedContent);
1952
1790
  }
1953
1791
  async function writeToolSample(destPath) {
1954
1792
  const fileService = new FileService();
1955
1793
  await fileService.copyStarterFile("tools.ts", destPath);
1956
1794
  }
1795
+ async function writeScorersSample(llmProvider, destPath) {
1796
+ const modelString = getModelIdentifier(llmProvider);
1797
+ const content = `import { z } from 'zod';
1798
+ import { createToolCallAccuracyScorerCode } from '@mastra/evals/scorers/prebuilt';
1799
+ import { createCompletenessScorer } from '@mastra/evals/scorers/prebuilt';
1800
+ import { getAssistantMessageFromRunOutput, getUserMessageFromRunInput } from '@mastra/evals/scorers/utils';
1801
+ import { createScorer } from '@mastra/core/evals';
1802
+
1803
+ export const toolCallAppropriatenessScorer = createToolCallAccuracyScorerCode({
1804
+ expectedTool: 'weatherTool',
1805
+ strictMode: false,
1806
+ });
1807
+
1808
+ export const completenessScorer = createCompletenessScorer();
1809
+
1810
+ // Custom LLM-judged scorer: evaluates if non-English locations are translated appropriately
1811
+ export const translationScorer = createScorer({
1812
+ id: 'translation-quality-scorer',
1813
+ name: 'Translation Quality',
1814
+ description: 'Checks that non-English location names are translated and used correctly',
1815
+ type: 'agent',
1816
+ judge: {
1817
+ model: '${modelString}',
1818
+ instructions:
1819
+ 'You are an expert evaluator of translation quality for geographic locations. ' +
1820
+ 'Determine whether the user text mentions a non-English location and whether the assistant correctly uses an English translation of that location. ' +
1821
+ 'Be lenient with transliteration differences and diacritics. ' +
1822
+ 'Return only the structured JSON matching the provided schema.',
1823
+ },
1824
+ })
1825
+ .preprocess(({ run }) => {
1826
+ const userText = getUserMessageFromRunInput(run.input) || '';
1827
+ const assistantText = getAssistantMessageFromRunOutput(run.output) || '';
1828
+ return { userText, assistantText };
1829
+ })
1830
+ .analyze({
1831
+ description: 'Extract location names and detect language/translation adequacy',
1832
+ outputSchema: z.object({
1833
+ nonEnglish: z.boolean(),
1834
+ translated: z.boolean(),
1835
+ confidence: z.number().min(0).max(1).default(1),
1836
+ explanation: z.string().default(''),
1837
+ }),
1838
+ createPrompt: ({ results }) => \`
1839
+ You are evaluating if a weather assistant correctly handled translation of a non-English location.
1840
+ User text:
1841
+ """
1842
+ \${results.preprocessStepResult.userText}
1843
+ """
1844
+ Assistant response:
1845
+ """
1846
+ \${results.preprocessStepResult.assistantText}
1847
+ """
1848
+ Tasks:
1849
+ 1) Identify if the user mentioned a location that appears non-English.
1850
+ 2) If non-English, check whether the assistant used a correct English translation of that location in its response.
1851
+ 3) Be lenient with transliteration differences (e.g., accents/diacritics).
1852
+ Return JSON with fields:
1853
+ {
1854
+ "nonEnglish": boolean,
1855
+ "translated": boolean,
1856
+ "confidence": number, // 0-1
1857
+ "explanation": string
1858
+ }
1859
+ \`,
1860
+ })
1861
+ .generateScore(({ results }) => {
1862
+ const r = (results as any)?.analyzeStepResult || {};
1863
+ if (!r.nonEnglish) return 1; // If not applicable, full credit
1864
+ if (r.translated) return Math.max(0, Math.min(1, 0.7 + 0.3 * (r.confidence ?? 1)));
1865
+ return 0; // Non-English but not translated
1866
+ })
1867
+ .generateReason(({ results, score }) => {
1868
+ const r = (results as any)?.analyzeStepResult || {};
1869
+ return \`Translation scoring: nonEnglish=\${r.nonEnglish ?? false}, translated=\${r.translated ?? false}, confidence=\${r.confidence ?? 0}. Score=\${score}. \${r.explanation ?? ''}\`;
1870
+ });
1871
+
1872
+ export const scorers = {
1873
+ toolCallAppropriatenessScorer,
1874
+ completenessScorer,
1875
+ translationScorer,
1876
+ };`;
1877
+ const formattedContent = await prettier.format(content, {
1878
+ parser: "typescript",
1879
+ singleQuote: true
1880
+ });
1881
+ await fs4.writeFile(destPath, formattedContent);
1882
+ }
1957
1883
  async function writeCodeSampleForComponents(llmprovider, component, destPath, importComponents) {
1958
1884
  switch (component) {
1959
1885
  case "agents":
1960
- return writeAgentSample(llmprovider, destPath, importComponents.includes("tools"));
1886
+ return writeAgentSample(
1887
+ llmprovider,
1888
+ destPath,
1889
+ importComponents.includes("tools"),
1890
+ importComponents.includes("scorers")
1891
+ );
1961
1892
  case "tools":
1962
1893
  return writeToolSample(destPath);
1963
1894
  case "workflows":
1964
1895
  return writeWorkflowSample(destPath);
1896
+ case "scorers":
1897
+ return writeScorersSample(llmprovider, destPath);
1965
1898
  default:
1966
1899
  return "";
1967
1900
  }
@@ -1974,46 +1907,55 @@ var writeIndexFile = async ({
1974
1907
  dirPath,
1975
1908
  addAgent,
1976
1909
  addExample,
1977
- addWorkflow
1910
+ addWorkflow,
1911
+ addScorers
1978
1912
  }) => {
1979
1913
  const indexPath = dirPath + "/index.ts";
1980
1914
  const destPath = path3.join(indexPath);
1981
1915
  try {
1982
- await fs5.writeFile(destPath, "");
1916
+ await fs4.writeFile(destPath, "");
1983
1917
  const filteredExports = [
1984
1918
  addWorkflow ? `workflows: { weatherWorkflow },` : "",
1985
- addAgent ? `agents: { weatherAgent },` : ""
1919
+ addAgent ? `agents: { weatherAgent },` : "",
1920
+ addScorers ? `scorers: { toolCallAppropriatenessScorer, completenessScorer, translationScorer },` : ""
1986
1921
  ].filter(Boolean);
1987
1922
  if (!addExample) {
1988
- await fs5.writeFile(
1923
+ await fs4.writeFile(
1989
1924
  destPath,
1990
1925
  `
1991
- import { Mastra } from '@mastra/core';
1926
+ import { Mastra } from '@mastra/core/mastra';
1992
1927
 
1993
1928
  export const mastra = new Mastra()
1994
1929
  `
1995
1930
  );
1996
1931
  return;
1997
1932
  }
1998
- await fs5.writeFile(
1933
+ await fs4.writeFile(
1999
1934
  destPath,
2000
1935
  `
2001
1936
  import { Mastra } from '@mastra/core/mastra';
2002
1937
  import { PinoLogger } from '@mastra/loggers';
2003
1938
  import { LibSQLStore } from '@mastra/libsql';
1939
+ import { Observability } from '@mastra/observability';
2004
1940
  ${addWorkflow ? `import { weatherWorkflow } from './workflows/weather-workflow';` : ""}
2005
1941
  ${addAgent ? `import { weatherAgent } from './agents/weather-agent';` : ""}
1942
+ ${addScorers ? `import { toolCallAppropriatenessScorer, completenessScorer, translationScorer } from './scorers/weather-scorer';` : ""}
2006
1943
 
2007
1944
  export const mastra = new Mastra({
2008
1945
  ${filteredExports.join("\n ")}
2009
1946
  storage: new LibSQLStore({
2010
- // stores telemetry, evals, ... into memory storage, if it needs to persist, change to file:../mastra.db
1947
+ id: "mastra-storage",
1948
+ // stores observability, scores, ... into memory storage, if it needs to persist, change to file:../mastra.db
2011
1949
  url: ":memory:",
2012
1950
  }),
2013
1951
  logger: new PinoLogger({
2014
1952
  name: 'Mastra',
2015
1953
  level: 'info',
2016
1954
  }),
1955
+ observability: new Observability({
1956
+ // Enables DefaultExporter and CloudExporter for tracing
1957
+ default: { enabled: true },
1958
+ }),
2017
1959
  });
2018
1960
  `
2019
1961
  );
@@ -2021,7 +1963,6 @@ export const mastra = new Mastra({
2021
1963
  throw err;
2022
1964
  }
2023
1965
  };
2024
- yoctoSpinner({ text: "Installing Mastra core dependencies\n" });
2025
1966
  var getAPIKey = async (provider) => {
2026
1967
  let key = "OPENAI_API_KEY";
2027
1968
  switch (provider) {
@@ -2044,20 +1985,18 @@ var getAPIKey = async (provider) => {
2044
1985
  return key;
2045
1986
  }
2046
1987
  };
2047
- var writeAPIKey = async ({
2048
- provider,
2049
- apiKey = "your-api-key"
2050
- }) => {
1988
+ var writeAPIKey = async ({ provider, apiKey }) => {
1989
+ const envFileName = apiKey ? ".env" : ".env.example";
2051
1990
  const key = await getAPIKey(provider);
2052
- const escapedKey = shellQuote.quote([key]);
2053
- const escapedApiKey = shellQuote.quote([apiKey]);
2054
- await exec2(`echo ${escapedKey}=${escapedApiKey} >> .env`);
1991
+ const escapedKey = shellQuote2.quote([key]);
1992
+ const escapedApiKey = shellQuote2.quote([apiKey ? apiKey : "your-api-key"]);
1993
+ await exec(`echo ${escapedKey}=${escapedApiKey} >> ${envFileName}`);
2055
1994
  };
2056
1995
  var createMastraDir = async (directory) => {
2057
1996
  let dir = directory.trim().split("/").filter((item) => item !== "");
2058
1997
  const dirPath = path3.join(process.cwd(), ...dir, "mastra");
2059
1998
  try {
2060
- await fs5.access(dirPath);
1999
+ await fs4.access(dirPath);
2061
2000
  return { ok: false };
2062
2001
  } catch {
2063
2002
  await fsExtra.ensureDir(dirPath);
@@ -2072,8 +2011,19 @@ var writeCodeSample = async (dirPath, component, llmProvider, importComponents)
2072
2011
  throw err;
2073
2012
  }
2074
2013
  };
2075
- var interactivePrompt = async () => {
2076
- Ie(color2.inverse(" Mastra Init "));
2014
+ var LLM_PROVIDERS = [
2015
+ { value: "openai", label: "OpenAI", hint: "recommended" },
2016
+ { value: "anthropic", label: "Anthropic" },
2017
+ { value: "groq", label: "Groq" },
2018
+ { value: "google", label: "Google" },
2019
+ { value: "cerebras", label: "Cerebras" },
2020
+ { value: "mistral", label: "Mistral" }
2021
+ ];
2022
+ var interactivePrompt = async (args = {}) => {
2023
+ const { skip = {}, options: { showBanner = true } = {} } = args;
2024
+ if (showBanner) {
2025
+ Ie(color2.inverse(" Mastra Init "));
2026
+ }
2077
2027
  const mastraProject = await Ce(
2078
2028
  {
2079
2029
  directory: () => he({
@@ -2081,20 +2031,15 @@ var interactivePrompt = async () => {
2081
2031
  placeholder: "src/",
2082
2032
  defaultValue: "src/"
2083
2033
  }),
2084
- llmProvider: () => ve({
2085
- message: "Select default provider:",
2086
- options: [
2087
- { value: "openai", label: "OpenAI", hint: "recommended" },
2088
- { value: "anthropic", label: "Anthropic" },
2089
- { value: "groq", label: "Groq" },
2090
- { value: "google", label: "Google" },
2091
- { value: "cerebras", label: "Cerebras" },
2092
- { value: "mistral", label: "Mistral" }
2093
- ]
2034
+ llmProvider: () => skip?.llmProvider ? void 0 : ve({
2035
+ message: "Select a default provider:",
2036
+ options: LLM_PROVIDERS
2094
2037
  }),
2095
2038
  llmApiKey: async ({ results: { llmProvider } }) => {
2039
+ if (skip?.llmApiKey) return void 0;
2040
+ const llmName = LLM_PROVIDERS.find((p6) => p6.value === llmProvider)?.label || "provider";
2096
2041
  const keyChoice = await ve({
2097
- message: `Enter your ${llmProvider} API key?`,
2042
+ message: `Enter your ${llmName} API key?`,
2098
2043
  options: [
2099
2044
  { value: "skip", label: "Skip for now", hint: "default" },
2100
2045
  { value: "enter", label: "Enter API key" }
@@ -2104,52 +2049,38 @@ var interactivePrompt = async () => {
2104
2049
  if (keyChoice === "enter") {
2105
2050
  return he({
2106
2051
  message: "Enter your API key:",
2107
- placeholder: "sk-..."
2052
+ placeholder: "sk-...",
2053
+ validate: (value) => {
2054
+ if (value.length === 0) return "API key cannot be empty";
2055
+ }
2108
2056
  });
2109
2057
  }
2110
2058
  return void 0;
2111
2059
  },
2112
2060
  configureEditorWithDocsMCP: async () => {
2113
- const windsurfIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`windsurf`);
2114
- const cursorIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`cursor`);
2115
- const vscodeIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`vscode`);
2116
2061
  const editor = await ve({
2117
- message: `Make your AI IDE into a Mastra expert? (installs Mastra docs MCP server)`,
2062
+ message: `Make your IDE into a Mastra expert? (Installs Mastra's MCP server)`,
2118
2063
  options: [
2119
2064
  { value: "skip", label: "Skip for now", hint: "default" },
2120
2065
  {
2121
2066
  value: "cursor",
2122
- label: "Cursor (project only)",
2123
- hint: cursorIsAlreadyInstalled ? `Already installed globally` : void 0
2067
+ label: "Cursor (project only)"
2124
2068
  },
2125
2069
  {
2126
2070
  value: "cursor-global",
2127
- label: "Cursor (global, all projects)",
2128
- hint: cursorIsAlreadyInstalled ? `Already installed` : void 0
2071
+ label: "Cursor (global, all projects)"
2129
2072
  },
2130
2073
  {
2131
2074
  value: "windsurf",
2132
- label: "Windsurf",
2133
- hint: windsurfIsAlreadyInstalled ? `Already installed` : void 0
2075
+ label: "Windsurf"
2134
2076
  },
2135
2077
  {
2136
2078
  value: "vscode",
2137
- label: "VSCode",
2138
- hint: vscodeIsAlreadyInstalled ? `Already installed` : void 0
2079
+ label: "VSCode"
2139
2080
  }
2140
2081
  ]
2141
2082
  });
2142
2083
  if (editor === `skip`) return void 0;
2143
- if (editor === `windsurf` && windsurfIsAlreadyInstalled) {
2144
- M.message(`
2145
- Windsurf is already installed, skipping.`);
2146
- return void 0;
2147
- }
2148
- if (editor === `vscode` && vscodeIsAlreadyInstalled) {
2149
- M.message(`
2150
- VSCode is already installed, skipping.`);
2151
- return void 0;
2152
- }
2153
2084
  if (editor === `cursor`) {
2154
2085
  M.message(
2155
2086
  `
@@ -2158,19 +2089,19 @@ Note: you will need to go into Cursor Settings -> MCP Settings and manually enab
2158
2089
  );
2159
2090
  }
2160
2091
  if (editor === `cursor-global`) {
2161
- const confirm2 = await ve({
2092
+ const confirm = await ve({
2162
2093
  message: `Global install will add/update ${cursorGlobalMCPConfigPath} and make the Mastra docs MCP server available in all your Cursor projects. Continue?`,
2163
2094
  options: [
2164
2095
  { value: "yes", label: "Yes, I understand" },
2165
2096
  { value: "skip", label: "No, skip for now" }
2166
2097
  ]
2167
2098
  });
2168
- if (confirm2 !== `yes`) {
2099
+ if (confirm !== `yes`) {
2169
2100
  return void 0;
2170
2101
  }
2171
2102
  }
2172
2103
  if (editor === `windsurf`) {
2173
- const confirm2 = await ve({
2104
+ const confirm = await ve({
2174
2105
  message: `Windsurf only supports a global MCP config (at ${windsurfGlobalMCPConfigPath}) is it ok to add/update that global config?
2175
2106
  This means the Mastra docs MCP server will be available in all your Windsurf projects.`,
2176
2107
  options: [
@@ -2178,7 +2109,7 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
2178
2109
  { value: "skip", label: "No, skip for now" }
2179
2110
  ]
2180
2111
  });
2181
- if (confirm2 !== `yes`) {
2112
+ if (confirm !== `yes`) {
2182
2113
  return void 0;
2183
2114
  }
2184
2115
  }
@@ -2194,17 +2125,230 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
2194
2125
  );
2195
2126
  return mastraProject;
2196
2127
  };
2128
+ function getPackageManager() {
2129
+ const userAgent = process.env.npm_config_user_agent || "";
2130
+ const execPath = process.env.npm_execpath || "";
2131
+ if (userAgent.includes("bun")) {
2132
+ return "bun";
2133
+ }
2134
+ if (userAgent.includes("yarn")) {
2135
+ return "yarn";
2136
+ }
2137
+ if (userAgent.includes("pnpm")) {
2138
+ return "pnpm";
2139
+ }
2140
+ if (userAgent.includes("npm")) {
2141
+ return "npm";
2142
+ }
2143
+ if (execPath.includes("bun")) {
2144
+ return "bun";
2145
+ }
2146
+ if (execPath.includes("yarn")) {
2147
+ return "yarn";
2148
+ }
2149
+ if (execPath.includes("pnpm")) {
2150
+ return "pnpm";
2151
+ }
2152
+ if (execPath.includes("npm")) {
2153
+ return "npm";
2154
+ }
2155
+ return "npm";
2156
+ }
2157
+ var logger = createLogger(false);
2158
+ function createLogger(debug = false) {
2159
+ return new PinoLogger({
2160
+ name: "Mastra CLI",
2161
+ level: debug ? "debug" : "info"
2162
+ });
2163
+ }
2164
+ var exec2 = util.promisify(child_process.exec);
2165
+ async function cloneTemplate(options) {
2166
+ const { template, projectName, targetDir, branch, llmProvider } = options;
2167
+ const projectPath = targetDir ? path3.resolve(targetDir, projectName) : path3.resolve(projectName);
2168
+ const spinner4 = yoctoSpinner({ text: `Cloning template "${template.title}"...` }).start();
2169
+ try {
2170
+ if (await directoryExists(projectPath)) {
2171
+ spinner4.error(`Directory ${projectName} already exists`);
2172
+ throw new Error(`Directory ${projectName} already exists`);
2173
+ }
2174
+ await cloneRepositoryWithoutGit(template.githubUrl, projectPath, branch);
2175
+ await updatePackageJson(projectPath, projectName);
2176
+ const envExamplePath = path3.join(projectPath, ".env.example");
2177
+ if (await fileExists(envExamplePath)) {
2178
+ const envPath = path3.join(projectPath, ".env");
2179
+ await fs4.copyFile(envExamplePath, envPath);
2180
+ if (llmProvider) {
2181
+ await updateEnvFile(envPath, llmProvider);
2182
+ }
2183
+ }
2184
+ spinner4.success(`Template "${template.title}" cloned successfully to ${projectName}`);
2185
+ return projectPath;
2186
+ } catch (error) {
2187
+ spinner4.error(`Failed to clone template: ${error instanceof Error ? error.message : "Unknown error"}`);
2188
+ throw error;
2189
+ }
2190
+ }
2191
+ async function directoryExists(dirPath) {
2192
+ try {
2193
+ const stat = await fs4.stat(dirPath);
2194
+ return stat.isDirectory();
2195
+ } catch {
2196
+ return false;
2197
+ }
2198
+ }
2199
+ async function fileExists(filePath) {
2200
+ try {
2201
+ const stat = await fs4.stat(filePath);
2202
+ return stat.isFile();
2203
+ } catch {
2204
+ return false;
2205
+ }
2206
+ }
2207
+ async function cloneRepositoryWithoutGit(repoUrl, targetPath, branch) {
2208
+ await fs4.mkdir(targetPath, { recursive: true });
2209
+ try {
2210
+ const degitRepo = repoUrl.replace("https://github.com/", "");
2211
+ const degitRepoWithBranch = branch ? `${degitRepo}#${branch}` : degitRepo;
2212
+ const degitCommand = shellQuote2.quote(["npx", "degit", degitRepoWithBranch, targetPath]);
2213
+ await exec2(degitCommand, {
2214
+ cwd: process.cwd()
2215
+ });
2216
+ } catch {
2217
+ try {
2218
+ const gitArgs = ["git", "clone"];
2219
+ if (branch) {
2220
+ gitArgs.push("--branch", branch);
2221
+ }
2222
+ gitArgs.push(repoUrl, targetPath);
2223
+ const gitCommand = shellQuote2.quote(gitArgs);
2224
+ await exec2(gitCommand, {
2225
+ cwd: process.cwd()
2226
+ });
2227
+ const gitDir = path3.join(targetPath, ".git");
2228
+ if (await directoryExists(gitDir)) {
2229
+ await fs4.rm(gitDir, { recursive: true, force: true });
2230
+ }
2231
+ } catch (gitError) {
2232
+ throw new Error(`Failed to clone repository: ${gitError instanceof Error ? gitError.message : "Unknown error"}`);
2233
+ }
2234
+ }
2235
+ }
2236
+ async function updatePackageJson(projectPath, projectName) {
2237
+ const packageJsonPath = path3.join(projectPath, "package.json");
2238
+ try {
2239
+ const packageJsonContent = await fs4.readFile(packageJsonPath, "utf-8");
2240
+ const packageJson = JSON.parse(packageJsonContent);
2241
+ packageJson.name = projectName;
2242
+ await fs4.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf-8");
2243
+ } catch (error) {
2244
+ logger.warn(`Could not update package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
2245
+ }
2246
+ }
2247
+ async function updateEnvFile(envPath, llmProvider) {
2248
+ try {
2249
+ const envContent = await fs4.readFile(envPath, "utf-8");
2250
+ const modelString = getModelIdentifier(llmProvider);
2251
+ if (!modelString) {
2252
+ logger.warn(`Could not get model identifier for provider: ${llmProvider}`);
2253
+ return;
2254
+ }
2255
+ const modelValue = modelString.replace(/'/g, "");
2256
+ const updatedContent = envContent.replace(/^MODEL=.*/m, `MODEL=${modelValue}`);
2257
+ await fs4.writeFile(envPath, updatedContent, "utf-8");
2258
+ logger.info(`Updated MODEL in .env to ${modelValue}`);
2259
+ } catch (error) {
2260
+ logger.warn(`Could not update .env file: ${error instanceof Error ? error.message : "Unknown error"}`);
2261
+ }
2262
+ }
2263
+ async function installDependencies(projectPath, packageManager) {
2264
+ const spinner4 = yoctoSpinner({ text: "Installing dependencies..." }).start();
2265
+ try {
2266
+ const pm = packageManager || getPackageManager();
2267
+ const installCommand = shellQuote2.quote([pm, "install"]);
2268
+ await exec2(installCommand, {
2269
+ cwd: projectPath
2270
+ });
2271
+ spinner4.success("Dependencies installed successfully");
2272
+ } catch (error) {
2273
+ spinner4.error(`Failed to install dependencies: ${error instanceof Error ? error.message : "Unknown error"}`);
2274
+ throw error;
2275
+ }
2276
+ }
2277
+ var TEMPLATES_API_URL = process.env.MASTRA_TEMPLATES_API_URL || "https://mastra.ai/api/templates.json";
2278
+ async function loadTemplates() {
2279
+ try {
2280
+ const response = await fetch(TEMPLATES_API_URL);
2281
+ if (!response.ok) {
2282
+ throw new Error(`Failed to fetch templates: ${response.statusText}`);
2283
+ }
2284
+ const templates = await response.json();
2285
+ return templates;
2286
+ } catch (error) {
2287
+ console.error("Error loading templates:", error);
2288
+ throw new Error("Failed to load templates. Please check your internet connection and try again.");
2289
+ }
2290
+ }
2291
+ function pluralize(count, singular, plural) {
2292
+ return count === 1 ? singular : plural || `${singular}s`;
2293
+ }
2294
+ async function selectTemplate(templates) {
2295
+ const choices = templates.map((template) => {
2296
+ const parts = [];
2297
+ if (template.agents?.length) {
2298
+ parts.push(`${template.agents.length} ${pluralize(template.agents.length, "agent")}`);
2299
+ }
2300
+ if (template.tools?.length) {
2301
+ parts.push(`${template.tools.length} ${pluralize(template.tools.length, "tool")}`);
2302
+ }
2303
+ if (template.workflows?.length) {
2304
+ parts.push(`${template.workflows.length} ${pluralize(template.workflows.length, "workflow")}`);
2305
+ }
2306
+ if (template.mcp?.length) {
2307
+ parts.push(`${template.mcp.length} ${pluralize(template.mcp.length, "MCP server")}`);
2308
+ }
2309
+ if (template.networks?.length) {
2310
+ parts.push(`${template.networks.length} ${pluralize(template.networks.length, "agent network")}`);
2311
+ }
2312
+ return {
2313
+ value: template,
2314
+ label: template.title,
2315
+ hint: parts.join(", ") || "Template components"
2316
+ };
2317
+ });
2318
+ const selected = await ve({
2319
+ message: "Select a template:",
2320
+ options: choices
2321
+ });
2322
+ if (pD(selected)) {
2323
+ return null;
2324
+ }
2325
+ return selected;
2326
+ }
2327
+ function findTemplateByName(templates, templateName) {
2328
+ let template = templates.find((t) => t.slug === templateName);
2329
+ if (template) return template;
2330
+ const slugWithPrefix = `template-${templateName}`;
2331
+ template = templates.find((t) => t.slug === slugWithPrefix);
2332
+ if (template) return template;
2333
+ template = templates.find((t) => t.title.toLowerCase() === templateName.toLowerCase());
2334
+ if (template) return template;
2335
+ return null;
2336
+ }
2337
+ function getDefaultProjectName(template) {
2338
+ return template.slug.replace(/^template-/, "");
2339
+ }
2197
2340
  var s = Y();
2198
- var exec3 = util.promisify(child_process.exec);
2199
2341
  var init = async ({
2200
- directory,
2201
- addExample = false,
2342
+ directory = "src/",
2202
2343
  components,
2203
2344
  llmProvider = "openai",
2204
2345
  llmApiKey,
2205
- configureEditorWithDocsMCP
2346
+ addExample = false,
2347
+ configureEditorWithDocsMCP,
2348
+ versionTag
2206
2349
  }) => {
2207
2350
  s.start("Initializing Mastra");
2351
+ const packageVersionTag = versionTag ? `@${versionTag}` : "";
2208
2352
  try {
2209
2353
  const result = await createMastraDir(directory);
2210
2354
  if (!result.ok) {
@@ -2217,7 +2361,8 @@ var init = async ({
2217
2361
  dirPath,
2218
2362
  addExample,
2219
2363
  addWorkflow: components.includes("workflows"),
2220
- addAgent: components.includes("agents")
2364
+ addAgent: components.includes("agents"),
2365
+ addScorers: components.includes("scorers")
2221
2366
  }),
2222
2367
  ...components.map((component) => createComponentsDir(dirPath, component)),
2223
2368
  writeAPIKey({ provider: llmProvider, apiKey: llmApiKey })
@@ -2231,28 +2376,31 @@ var init = async ({
2231
2376
  const depService = new DepsService();
2232
2377
  const needsLibsql = await depService.checkDependencies(["@mastra/libsql"]) !== `ok`;
2233
2378
  if (needsLibsql) {
2234
- await depService.installPackages(["@mastra/libsql"]);
2379
+ await depService.installPackages([`@mastra/libsql${packageVersionTag}`]);
2235
2380
  }
2236
2381
  const needsMemory = components.includes(`agents`) && await depService.checkDependencies(["@mastra/memory"]) !== `ok`;
2237
2382
  if (needsMemory) {
2238
- await depService.installPackages(["@mastra/memory"]);
2383
+ await depService.installPackages([`@mastra/memory${packageVersionTag}`]);
2239
2384
  }
2240
2385
  const needsLoggers = await depService.checkDependencies(["@mastra/loggers"]) !== `ok`;
2241
2386
  if (needsLoggers) {
2242
- await depService.installPackages(["@mastra/loggers"]);
2387
+ await depService.installPackages([`@mastra/loggers${packageVersionTag}`]);
2388
+ }
2389
+ const needsObservability = await depService.checkDependencies(["@mastra/observability"]) !== `ok`;
2390
+ if (needsObservability) {
2391
+ await depService.installPackages([`@mastra/observability${packageVersionTag}`]);
2392
+ }
2393
+ const needsEvals = components.includes(`scorers`) && await depService.checkDependencies(["@mastra/evals"]) !== `ok`;
2394
+ if (needsEvals) {
2395
+ await depService.installPackages([`@mastra/evals${packageVersionTag}`]);
2243
2396
  }
2244
2397
  }
2245
2398
  const key = await getAPIKey(llmProvider || "openai");
2246
- const aiSdkPackage = getAISDKPackage(llmProvider);
2247
- const aiSdkPackageVersion = getAISDKPackageVersion(llmProvider);
2248
- const depsService = new DepsService();
2249
- const pm = depsService.packageManager;
2250
- const installCommand = getPackageManagerAddCommand(pm);
2251
- await exec3(`${pm} ${installCommand} ${aiSdkPackage}@${aiSdkPackageVersion}`);
2252
2399
  if (configureEditorWithDocsMCP) {
2253
2400
  await installMastraDocsMCPServer({
2254
2401
  editor: configureEditorWithDocsMCP,
2255
- directory: process.cwd()
2402
+ directory: process.cwd(),
2403
+ versionTag
2256
2404
  });
2257
2405
  }
2258
2406
  s.stop();
@@ -2275,10 +2423,10 @@ var init = async ({
2275
2423
  return { success: false };
2276
2424
  }
2277
2425
  };
2278
- var exec4 = util.promisify(child_process.exec);
2426
+ var exec3 = util.promisify(child_process.exec);
2279
2427
  var execWithTimeout = async (command, timeoutMs) => {
2280
2428
  try {
2281
- const promise = exec4(command, { killSignal: "SIGTERM" });
2429
+ const promise = exec3(command, { killSignal: "SIGTERM" });
2282
2430
  if (!timeoutMs) {
2283
2431
  return await promise;
2284
2432
  }
@@ -2301,6 +2449,32 @@ var execWithTimeout = async (command, timeoutMs) => {
2301
2449
  throw error;
2302
2450
  }
2303
2451
  };
2452
+ async function getInitCommand(pm) {
2453
+ switch (pm) {
2454
+ case "npm":
2455
+ return "npm init -y";
2456
+ case "pnpm":
2457
+ return "pnpm init";
2458
+ case "yarn":
2459
+ return "yarn init -y";
2460
+ case "bun":
2461
+ return "bun init -y";
2462
+ default:
2463
+ return "npm init -y";
2464
+ }
2465
+ }
2466
+ async function initializePackageJson(pm) {
2467
+ const initCommand = await getInitCommand(pm);
2468
+ await exec3(initCommand);
2469
+ const packageJsonPath = path3.join(process.cwd(), "package.json");
2470
+ const packageJson = JSON.parse(await fs4.readFile(packageJsonPath, "utf-8"));
2471
+ packageJson.type = "module";
2472
+ packageJson.engines = {
2473
+ ...packageJson.engines,
2474
+ node: ">=22.13.0"
2475
+ };
2476
+ await fs4.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
2477
+ }
2304
2478
  async function installMastraDependency(pm, dependency, versionTag, isDev, timeout) {
2305
2479
  let installCommand = getPackageManagerAddCommand(pm);
2306
2480
  if (isDev) {
@@ -2326,23 +2500,42 @@ async function installMastraDependency(pm, dependency, versionTag, isDev, timeou
2326
2500
  var createMastraProject = async ({
2327
2501
  projectName: name,
2328
2502
  createVersionTag,
2329
- timeout
2503
+ timeout,
2504
+ llmProvider,
2505
+ llmApiKey,
2506
+ needsInteractive
2330
2507
  }) => {
2331
2508
  Ie(color2.inverse(" Mastra Create "));
2332
2509
  const projectName = name ?? await he({
2333
2510
  message: "What do you want to name your project?",
2334
2511
  placeholder: "my-mastra-app",
2335
- defaultValue: "my-mastra-app"
2512
+ defaultValue: "my-mastra-app",
2513
+ validate: (value) => {
2514
+ if (value.length === 0) return "Project name cannot be empty";
2515
+ if (fs3__default__default.existsSync(value)) {
2516
+ return `A directory named "${value}" already exists. Please choose a different name.`;
2517
+ }
2518
+ }
2336
2519
  });
2337
2520
  if (pD(projectName)) {
2338
2521
  xe("Operation cancelled");
2339
2522
  process.exit(0);
2340
2523
  }
2524
+ let result;
2525
+ if (needsInteractive) {
2526
+ result = await interactivePrompt({
2527
+ options: { showBanner: false },
2528
+ skip: { llmProvider: llmProvider !== void 0, llmApiKey: llmApiKey !== void 0 }
2529
+ });
2530
+ }
2341
2531
  const s2 = Y();
2532
+ const originalCwd = process.cwd();
2533
+ let projectPath = null;
2342
2534
  try {
2343
2535
  s2.start("Creating project");
2344
2536
  try {
2345
- await fs5.mkdir(projectName);
2537
+ await fs4.mkdir(projectName);
2538
+ projectPath = path3.resolve(originalCwd, projectName);
2346
2539
  } catch (error) {
2347
2540
  if (error instanceof Error && "code" in error && error.code === "EEXIST") {
2348
2541
  s2.stop(`A directory named "${projectName}" already exists. Please choose a different name.`);
@@ -2357,9 +2550,7 @@ var createMastraProject = async ({
2357
2550
  const installCommand = getPackageManagerAddCommand(pm);
2358
2551
  s2.message("Initializing project structure");
2359
2552
  try {
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"`);
2553
+ await initializePackageJson(pm);
2363
2554
  const depsService = new DepsService();
2364
2555
  await depsService.addScriptsToPackageJson({
2365
2556
  dev: "mastra dev",
@@ -2374,9 +2565,9 @@ var createMastraProject = async ({
2374
2565
  s2.stop("Project structure created");
2375
2566
  s2.start(`Installing ${pm} dependencies`);
2376
2567
  try {
2377
- await exec4(`${pm} ${installCommand} zod@^3`);
2378
- await exec4(`${pm} ${installCommand} typescript @types/node --save-dev`);
2379
- await exec4(`echo '{
2568
+ await exec3(`${pm} ${installCommand} zod@^4`);
2569
+ await exec3(`${pm} ${installCommand} -D typescript @types/node`);
2570
+ await exec3(`echo '{
2380
2571
  "compilerOptions": {
2381
2572
  "target": "ES2022",
2382
2573
  "module": "ES2022",
@@ -2398,15 +2589,15 @@ var createMastraProject = async ({
2398
2589
  );
2399
2590
  }
2400
2591
  s2.stop(`${pm} dependencies installed`);
2401
- s2.start("Installing mastra");
2592
+ s2.start("Installing Mastra CLI");
2402
2593
  const versionTag = createVersionTag ? `@${createVersionTag}` : "@latest";
2403
2594
  try {
2404
2595
  await installMastraDependency(pm, "mastra", versionTag, true, timeout);
2405
2596
  } catch (error) {
2406
2597
  throw new Error(`Failed to install Mastra CLI: ${error instanceof Error ? error.message : "Unknown error"}`);
2407
2598
  }
2408
- s2.stop("mastra installed");
2409
- s2.start("Installing dependencies");
2599
+ s2.stop("Mastra CLI installed");
2600
+ s2.start("Installing Mastra dependencies");
2410
2601
  try {
2411
2602
  await installMastraDependency(pm, "@mastra/core", versionTag, false, timeout);
2412
2603
  await installMastraDependency(pm, "@mastra/libsql", versionTag, false, timeout);
@@ -2419,58 +2610,80 @@ var createMastraProject = async ({
2419
2610
  s2.stop("Mastra dependencies installed");
2420
2611
  s2.start("Adding .gitignore");
2421
2612
  try {
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`);
2613
+ await exec3(`echo output.txt >> .gitignore`);
2614
+ await exec3(`echo node_modules >> .gitignore`);
2615
+ await exec3(`echo dist >> .gitignore`);
2616
+ await exec3(`echo .mastra >> .gitignore`);
2617
+ await exec3(`echo .env.development >> .gitignore`);
2618
+ await exec3(`echo .env >> .gitignore`);
2619
+ await exec3(`echo *.db >> .gitignore`);
2620
+ await exec3(`echo *.db-* >> .gitignore`);
2430
2621
  } catch (error) {
2431
2622
  throw new Error(`Failed to create .gitignore: ${error instanceof Error ? error.message : "Unknown error"}`);
2432
2623
  }
2433
2624
  s2.stop(".gitignore added");
2434
2625
  Se("Project created successfully");
2435
- console.log("");
2436
- return { projectName };
2626
+ console.info("");
2627
+ return { projectName, result };
2437
2628
  } catch (error) {
2438
2629
  s2.stop();
2439
2630
  const errorMessage = error instanceof Error ? error.message : "An unexpected error occurred";
2440
2631
  xe(`Project creation failed: ${errorMessage}`);
2632
+ if (projectPath && fs3__default__default.existsSync(projectPath)) {
2633
+ try {
2634
+ process.chdir(originalCwd);
2635
+ await fs4.rm(projectPath, { recursive: true, force: true });
2636
+ } catch (cleanupError) {
2637
+ console.error(
2638
+ `Warning: Failed to clean up project directory: ${cleanupError instanceof Error ? cleanupError.message : "Unknown error"}`
2639
+ );
2640
+ }
2641
+ }
2441
2642
  process.exit(1);
2442
2643
  }
2443
2644
  };
2444
- var create = async (args2) => {
2445
- if (args2.template !== void 0) {
2446
- await createFromTemplate({ ...args2, injectedAnalytics: args2.analytics });
2645
+ var version$1 = package_default.version;
2646
+ var create = async (args) => {
2647
+ if (args.template !== void 0) {
2648
+ await createFromTemplate({
2649
+ projectName: args.projectName,
2650
+ template: args.template,
2651
+ timeout: args.timeout,
2652
+ injectedAnalytics: args.analytics,
2653
+ llmProvider: args.llmProvider
2654
+ });
2447
2655
  return;
2448
2656
  }
2449
- const { projectName } = await createMastraProject({
2450
- projectName: args2?.projectName,
2451
- createVersionTag: args2?.createVersionTag,
2452
- timeout: args2?.timeout
2657
+ const needsInteractive = args.components === void 0 || args.llmProvider === void 0 || args.addExample === void 0;
2658
+ const { projectName, result } = await createMastraProject({
2659
+ projectName: args?.projectName,
2660
+ createVersionTag: args?.createVersionTag,
2661
+ timeout: args?.timeout,
2662
+ llmProvider: args?.llmProvider,
2663
+ llmApiKey: args?.llmApiKey,
2664
+ needsInteractive
2453
2665
  });
2454
- const directory = args2.directory || "src/";
2455
- if (args2.components === void 0 || args2.llmProvider === void 0 || args2.addExample === void 0) {
2456
- const result = await interactivePrompt();
2666
+ const directory = args.directory || "src/";
2667
+ if (needsInteractive && result) {
2457
2668
  await init({
2458
2669
  ...result,
2459
2670
  llmApiKey: result?.llmApiKey,
2460
- components: ["agents", "tools", "workflows"],
2461
- addExample: true
2671
+ components: ["agents", "tools", "workflows", "scorers"],
2672
+ addExample: true,
2673
+ versionTag: args.createVersionTag
2462
2674
  });
2463
2675
  postCreate({ projectName });
2464
2676
  return;
2465
2677
  }
2466
- const { components = [], llmProvider = "openai", addExample = false, llmApiKey } = args2;
2678
+ const { components = [], llmProvider = "openai", addExample = false, llmApiKey } = args;
2467
2679
  await init({
2468
2680
  directory,
2469
2681
  components,
2470
2682
  llmProvider,
2471
2683
  addExample,
2472
2684
  llmApiKey,
2473
- configureEditorWithDocsMCP: args2.mcpServer
2685
+ configureEditorWithDocsMCP: args.mcpServer,
2686
+ versionTag: args.createVersionTag
2474
2687
  });
2475
2688
  postCreate({ projectName });
2476
2689
  };
@@ -2561,9 +2774,9 @@ async function createFromGitHubUrl(url) {
2561
2774
  workflows: []
2562
2775
  };
2563
2776
  }
2564
- async function createFromTemplate(args2) {
2777
+ async function createFromTemplate(args) {
2565
2778
  let selectedTemplate;
2566
- if (args2.template === true) {
2779
+ if (args.template === true) {
2567
2780
  const templates = await loadTemplates();
2568
2781
  const selected = await selectTemplate(templates);
2569
2782
  if (!selected) {
@@ -2571,26 +2784,26 @@ async function createFromTemplate(args2) {
2571
2784
  return;
2572
2785
  }
2573
2786
  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);
2787
+ } else if (args.template && typeof args.template === "string") {
2788
+ if (isGitHubUrl(args.template)) {
2789
+ const spinner4 = Y();
2790
+ spinner4.start("Validating GitHub repository...");
2791
+ const validation = await validateGitHubProject(args.template);
2579
2792
  if (!validation.isValid) {
2580
- spinner5.stop("Validation failed");
2793
+ spinner4.stop("Validation failed");
2581
2794
  M.error("This does not appear to be a valid Mastra project:");
2582
2795
  validation.errors.forEach((error) => M.error(` - ${error}`));
2583
2796
  throw new Error("Invalid Mastra project");
2584
2797
  }
2585
- spinner5.stop("Valid Mastra project \u2713");
2586
- selectedTemplate = await createFromGitHubUrl(args2.template);
2798
+ spinner4.stop("Valid Mastra project \u2713");
2799
+ selectedTemplate = await createFromGitHubUrl(args.template);
2587
2800
  } else {
2588
2801
  const templates = await loadTemplates();
2589
- const found = findTemplateByName(templates, args2.template);
2802
+ const found = findTemplateByName(templates, args.template);
2590
2803
  if (!found) {
2591
- M.error(`Template "${args2.template}" not found. Available templates:`);
2804
+ M.error(`Template "${args.template}" not found. Available templates:`);
2592
2805
  templates.forEach((t) => M.info(` - ${t.title} (use: ${t.slug.replace("template-", "")})`));
2593
- throw new Error(`Template "${args2.template}" not found`);
2806
+ throw new Error(`Template "${args.template}" not found`);
2594
2807
  }
2595
2808
  selectedTemplate = found;
2596
2809
  }
@@ -2598,7 +2811,7 @@ async function createFromTemplate(args2) {
2598
2811
  if (!selectedTemplate) {
2599
2812
  throw new Error("No template selected");
2600
2813
  }
2601
- let projectName = args2.projectName;
2814
+ let projectName = args.projectName;
2602
2815
  if (!projectName) {
2603
2816
  const defaultName = getDefaultProjectName(selectedTemplate);
2604
2817
  const response = await he({
@@ -2612,17 +2825,41 @@ async function createFromTemplate(args2) {
2612
2825
  }
2613
2826
  projectName = response;
2614
2827
  }
2828
+ let llmProvider = args.llmProvider;
2829
+ if (!llmProvider) {
2830
+ const providerResponse = await ve({
2831
+ message: "Select a default provider:",
2832
+ options: LLM_PROVIDERS
2833
+ });
2834
+ if (pD(providerResponse)) {
2835
+ M.info("Project creation cancelled.");
2836
+ return;
2837
+ }
2838
+ llmProvider = providerResponse;
2839
+ }
2840
+ let projectPath = null;
2615
2841
  try {
2616
- const analytics = args2.injectedAnalytics || getAnalytics();
2842
+ const analytics = args.injectedAnalytics || getAnalytics();
2617
2843
  if (analytics) {
2618
2844
  analytics.trackEvent("cli_template_used", {
2619
2845
  template_slug: selectedTemplate.slug,
2620
2846
  template_title: selectedTemplate.title
2621
2847
  });
2848
+ if (llmProvider) {
2849
+ analytics.trackEvent("cli_model_provider_selected", {
2850
+ provider: llmProvider,
2851
+ selection_method: args.llmProvider ? "cli_args" : "interactive"
2852
+ });
2853
+ }
2622
2854
  }
2623
- const projectPath = await cloneTemplate({
2855
+ const isBeta = version$1?.includes("beta") ?? false;
2856
+ const isMastraTemplate = selectedTemplate.githubUrl.includes("github.com/mastra-ai/");
2857
+ const branch = isBeta && isMastraTemplate ? "beta" : void 0;
2858
+ projectPath = await cloneTemplate({
2624
2859
  template: selectedTemplate,
2625
- projectName
2860
+ projectName,
2861
+ branch,
2862
+ llmProvider
2626
2863
  });
2627
2864
  await installDependencies(projectPath);
2628
2865
  Me(`
@@ -2633,6 +2870,17 @@ async function createFromTemplate(args2) {
2633
2870
  `);
2634
2871
  postCreate({ projectName });
2635
2872
  } catch (error) {
2873
+ if (projectPath) {
2874
+ try {
2875
+ if (fs3__default__default.existsSync(projectPath)) {
2876
+ await fs4.rm(projectPath, { recursive: true, force: true });
2877
+ }
2878
+ } catch (cleanupError) {
2879
+ console.error(
2880
+ `Warning: Failed to clean up project directory: ${cleanupError instanceof Error ? cleanupError.message : "Unknown error"}`
2881
+ );
2882
+ }
2883
+ }
2636
2884
  M.error(`Failed to create project from template: ${error instanceof Error ? error.message : "Unknown error"}`);
2637
2885
  throw error;
2638
2886
  }
@@ -2672,14 +2920,14 @@ program.version(`${version}`, "-v, --version").description(`create-mastra ${vers
2672
2920
  analytics.trackCommand({
2673
2921
  command: "version"
2674
2922
  });
2675
- console.log(`create-mastra ${version}`);
2923
+ console.info(`create-mastra ${version}`);
2676
2924
  } catch {
2677
2925
  }
2678
2926
  });
2679
2927
  program.name("create-mastra").description("Create a new Mastra project").argument("[project-name]", "Directory name of the project").option(
2680
2928
  "-p, --project-name <string>",
2681
2929
  "Project name that will be used in package.json and as the project directory name."
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(
2930
+ ).option("--default", "Quick start with defaults (src, OpenAI, examples)").option("-c, --components <components>", "Comma-separated list of components (agents, tools, workflows, scorers)").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
2931
  "--template [template-name]",
2684
2932
  "Create project from a template (use template name, public GitHub URL, or leave blank to select from list)"
2685
2933
  ).action(async (projectNameArg, args) => {
@@ -2687,7 +2935,7 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
2687
2935
  const timeout = args?.timeout ? args?.timeout === true ? 6e4 : parseInt(args?.timeout, 10) : void 0;
2688
2936
  if (args.default) {
2689
2937
  await create({
2690
- components: ["agents", "tools", "workflows"],
2938
+ components: ["agents", "tools", "workflows", "scorers"],
2691
2939
  llmProvider: "openai",
2692
2940
  addExample: true,
2693
2941
  createVersionTag,
@@ -2703,7 +2951,7 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
2703
2951
  components: args.components ? args.components.split(",") : [],
2704
2952
  llmProvider: args.llm,
2705
2953
  addExample: args.example,
2706
- llmApiKey: args["llm-api-key"],
2954
+ llmApiKey: args.llmApiKey,
2707
2955
  createVersionTag,
2708
2956
  timeout,
2709
2957
  projectName,