create-mastra 0.0.0-share-agent-metadata-with-cloud-20250718123411 → 0.0.0-span-scorring-test-20251124132129

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,26 +1,26 @@
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 fs from 'node:fs/promises';
16
16
  import child_process from 'node:child_process';
17
17
  import tty from 'node:tty';
18
+ import fsExtra, { readJSON, ensureFile, writeJSON } from 'fs-extra/esm';
19
+ import prettier from 'prettier';
20
+ import { execa } from 'execa';
18
21
  import pino from 'pino';
19
22
  import pretty from 'pino-pretty';
20
- import { execa } from 'execa';
21
- import fsExtra3, { readJSON, ensureFile, writeJSON } from 'fs-extra/esm';
22
- import prettier from 'prettier';
23
- import fsExtra from 'fs-extra';
23
+ import fsExtra$1 from 'fs-extra';
24
24
 
25
25
  var __filename = fileURLToPath(import.meta.url);
26
26
  var __dirname = path3.dirname(__filename);
@@ -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,194 +1187,21 @@ 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
- function getPackageManagerInstallCommand(pm) {
1190
+ var package_default = {
1191
+ version: "1.0.0-beta.3"};
1192
+ function getPackageManagerAddCommand(pm) {
1200
1193
  switch (pm) {
1201
1194
  case "npm":
1202
- return "install";
1195
+ return "install --audit=false --fund=false --loglevel=error --progress=false --update-notifier=false";
1203
1196
  case "yarn":
1204
1197
  return "add";
1205
1198
  case "pnpm":
1199
+ return "add --loglevel=error";
1200
+ case "bun":
1206
1201
  return "add";
1207
1202
  default:
1208
- return "install";
1209
- }
1210
- }
1211
- var logger = new PinoLogger({
1212
- name: "Mastra CLI",
1213
- level: "info"
1214
- });
1215
- var exec = util.promisify(child_process.exec);
1216
- async function cloneTemplate(options) {
1217
- const { template, projectName, targetDir } = options;
1218
- const projectPath = targetDir ? path3.resolve(targetDir, projectName) : path3.resolve(projectName);
1219
- const spinner4 = yoctoSpinner({ text: `Cloning template "${template.title}"...` }).start();
1220
- try {
1221
- if (await directoryExists(projectPath)) {
1222
- spinner4.error(`Directory ${projectName} already exists`);
1223
- throw new Error(`Directory ${projectName} already exists`);
1224
- }
1225
- await cloneRepositoryWithoutGit(template.githubUrl, projectPath);
1226
- await updatePackageJson(projectPath, projectName);
1227
- const envExamplePath = path3.join(projectPath, ".env.example");
1228
- if (await fileExists(envExamplePath)) {
1229
- await fs.copyFile(envExamplePath, path3.join(projectPath, ".env"));
1230
- }
1231
- spinner4.success(`Template "${template.title}" cloned successfully to ${projectName}`);
1232
- return projectPath;
1233
- } catch (error) {
1234
- spinner4.error(`Failed to clone template: ${error instanceof Error ? error.message : "Unknown error"}`);
1235
- throw error;
1236
- }
1237
- }
1238
- async function directoryExists(dirPath) {
1239
- try {
1240
- const stat = await fs.stat(dirPath);
1241
- return stat.isDirectory();
1242
- } catch {
1243
- return false;
1244
- }
1245
- }
1246
- async function fileExists(filePath) {
1247
- try {
1248
- const stat = await fs.stat(filePath);
1249
- return stat.isFile();
1250
- } catch {
1251
- return false;
1252
- }
1253
- }
1254
- async function cloneRepositoryWithoutGit(repoUrl, targetPath) {
1255
- await fs.mkdir(targetPath, { recursive: true });
1256
- try {
1257
- const degitRepo = repoUrl.replace("https://github.com/", "");
1258
- const degitCommand = shellQuote.quote(["npx", "degit", degitRepo, targetPath]);
1259
- await exec(degitCommand, {
1260
- cwd: process.cwd()
1261
- });
1262
- } catch {
1263
- try {
1264
- const gitCommand = shellQuote.quote(["git", "clone", repoUrl, targetPath]);
1265
- await exec(gitCommand, {
1266
- cwd: process.cwd()
1267
- });
1268
- const gitDir = path3.join(targetPath, ".git");
1269
- if (await directoryExists(gitDir)) {
1270
- await fs.rm(gitDir, { recursive: true, force: true });
1271
- }
1272
- } catch (gitError) {
1273
- throw new Error(`Failed to clone repository: ${gitError instanceof Error ? gitError.message : "Unknown error"}`);
1274
- }
1275
- }
1276
- }
1277
- async function updatePackageJson(projectPath, projectName) {
1278
- const packageJsonPath = path3.join(projectPath, "package.json");
1279
- try {
1280
- const packageJsonContent = await fs.readFile(packageJsonPath, "utf-8");
1281
- const packageJson = JSON.parse(packageJsonContent);
1282
- packageJson.name = projectName;
1283
- await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf-8");
1284
- } catch (error) {
1285
- logger.warn(`Could not update package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
1286
- }
1287
- }
1288
- async function installDependencies(projectPath, packageManager) {
1289
- const spinner4 = yoctoSpinner({ text: "Installing dependencies..." }).start();
1290
- try {
1291
- const pm = packageManager || getPackageManager();
1292
- const installCommand = shellQuote.quote([pm, "install"]);
1293
- await exec(installCommand, {
1294
- cwd: projectPath
1295
- });
1296
- spinner4.success("Dependencies installed successfully");
1297
- } catch (error) {
1298
- spinner4.error(`Failed to install dependencies: ${error instanceof Error ? error.message : "Unknown error"}`);
1299
- throw error;
1300
- }
1301
- }
1302
- var TEMPLATES_API_URL = process.env.MASTRA_TEMPLATES_API_URL || "https://mastra.ai/api/templates.json";
1303
- async function loadTemplates() {
1304
- try {
1305
- const response = await fetch(TEMPLATES_API_URL);
1306
- if (!response.ok) {
1307
- throw new Error(`Failed to fetch templates: ${response.statusText}`);
1308
- }
1309
- const templates = await response.json();
1310
- return templates;
1311
- } catch (error) {
1312
- console.error("Error loading templates:", error);
1313
- throw new Error("Failed to load templates. Please check your internet connection and try again.");
1314
- }
1315
- }
1316
- function pluralize(count, singular, plural) {
1317
- return count === 1 ? singular : plural || `${singular}s`;
1318
- }
1319
- async function selectTemplate(templates) {
1320
- const choices = templates.map((template) => {
1321
- const parts = [];
1322
- if (template.agents?.length) {
1323
- parts.push(`${template.agents.length} ${pluralize(template.agents.length, "agent")}`);
1324
- }
1325
- if (template.tools?.length) {
1326
- parts.push(`${template.tools.length} ${pluralize(template.tools.length, "tool")}`);
1327
- }
1328
- if (template.workflows?.length) {
1329
- parts.push(`${template.workflows.length} ${pluralize(template.workflows.length, "workflow")}`);
1330
- }
1331
- if (template.mcp?.length) {
1332
- parts.push(`${template.mcp.length} ${pluralize(template.mcp.length, "MCP server")}`);
1333
- }
1334
- if (template.networks?.length) {
1335
- parts.push(`${template.networks.length} ${pluralize(template.networks.length, "agent network")}`);
1336
- }
1337
- return {
1338
- value: template,
1339
- label: template.title,
1340
- hint: parts.join(", ") || "Template components"
1341
- };
1342
- });
1343
- const selected = await ve({
1344
- message: "Select a template:",
1345
- options: choices
1346
- });
1347
- if (pD(selected)) {
1348
- return null;
1203
+ return "add";
1349
1204
  }
1350
- return selected;
1351
- }
1352
- function findTemplateByName(templates, templateName) {
1353
- let template = templates.find((t) => t.slug === templateName);
1354
- if (template) return template;
1355
- const slugWithPrefix = `template-${templateName}`;
1356
- template = templates.find((t) => t.slug === slugWithPrefix);
1357
- if (template) return template;
1358
- template = templates.find((t) => t.title.toLowerCase() === templateName.toLowerCase());
1359
- if (template) return template;
1360
- return null;
1361
- }
1362
- function getDefaultProjectName(template) {
1363
- return template.slug.replace(/^template-/, "");
1364
1205
  }
1365
1206
  var DepsService = class {
1366
1207
  packageManager;
@@ -1370,7 +1211,7 @@ var DepsService = class {
1370
1211
  findLockFile(dir) {
1371
1212
  const lockFiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lock"];
1372
1213
  for (const file of lockFiles) {
1373
- if (fs4__default__default.existsSync(path3.join(dir, file))) {
1214
+ if (fs3__default__default.existsSync(path3.join(dir, file))) {
1374
1215
  return file;
1375
1216
  }
1376
1217
  }
@@ -1396,14 +1237,10 @@ var DepsService = class {
1396
1237
  }
1397
1238
  }
1398
1239
  async installPackages(packages) {
1399
- let runCommand = this.packageManager;
1400
- if (this.packageManager === "npm") {
1401
- runCommand = `${this.packageManager} i`;
1402
- } else {
1403
- runCommand = `${this.packageManager} add`;
1404
- }
1240
+ const pm = this.packageManager;
1241
+ const installCommand = getPackageManagerAddCommand(pm);
1405
1242
  const packageList = packages.join(" ");
1406
- return execa(`${runCommand} ${packageList}`, {
1243
+ return execa(`${pm} ${installCommand} ${packageList}`, {
1407
1244
  all: true,
1408
1245
  shell: true,
1409
1246
  stdio: "inherit"
@@ -1413,11 +1250,11 @@ var DepsService = class {
1413
1250
  try {
1414
1251
  const packageJsonPath = path3.join(process.cwd(), "package.json");
1415
1252
  try {
1416
- await fs.access(packageJsonPath);
1253
+ await fs4.access(packageJsonPath);
1417
1254
  } catch {
1418
1255
  return "No package.json file found in the current directory";
1419
1256
  }
1420
- const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf-8"));
1257
+ const packageJson = JSON.parse(await fs4.readFile(packageJsonPath, "utf-8"));
1421
1258
  for (const dependency of dependencies) {
1422
1259
  if (!packageJson.dependencies || !packageJson.dependencies[dependency]) {
1423
1260
  return `Please install ${dependency} before running this command (${this.packageManager} install ${dependency})`;
@@ -1432,164 +1269,45 @@ var DepsService = class {
1432
1269
  async getProjectName() {
1433
1270
  try {
1434
1271
  const packageJsonPath = path3.join(process.cwd(), "package.json");
1435
- const packageJson = await fs.readFile(packageJsonPath, "utf-8");
1272
+ const packageJson = await fs4.readFile(packageJsonPath, "utf-8");
1436
1273
  const pkg = JSON.parse(packageJson);
1437
1274
  return pkg.name;
1438
1275
  } catch (err) {
1439
1276
  throw err;
1440
1277
  }
1441
1278
  }
1442
- async getPackageVersion() {
1443
- const __filename = fileURLToPath(import.meta.url);
1444
- const __dirname = dirname(__filename);
1445
- const pkgJsonPath = path3.join(__dirname, "..", "package.json");
1446
- const content = await fsExtra3.readJSON(pkgJsonPath);
1447
- return content.version;
1448
- }
1449
1279
  async addScriptsToPackageJson(scripts) {
1450
- const packageJson = JSON.parse(await fs.readFile("package.json", "utf-8"));
1280
+ const packageJson = JSON.parse(await fs4.readFile("package.json", "utf-8"));
1451
1281
  packageJson.scripts = {
1452
1282
  ...packageJson.scripts,
1453
1283
  ...scripts
1454
1284
  };
1455
- await fs.writeFile("package.json", JSON.stringify(packageJson, null, 2));
1285
+ await fs4.writeFile("package.json", JSON.stringify(packageJson, null, 2));
1456
1286
  }
1457
1287
  };
1458
- var args = ["-y", "@mastra/mcp-docs-server"];
1459
- var createMcpConfig = (editor) => {
1460
- if (editor === "vscode") {
1461
- return {
1462
- servers: {
1463
- mastra: process.platform === `win32` ? {
1464
- command: "cmd",
1465
- args: ["/c", "npx", ...args],
1466
- type: "stdio"
1467
- } : {
1468
- command: "npx",
1469
- args,
1470
- type: "stdio"
1471
- }
1472
- }
1473
- };
1474
- }
1475
- return {
1476
- mcpServers: {
1477
- mastra: {
1478
- command: "npx",
1479
- args
1480
- }
1481
- }
1482
- };
1288
+ var EnvService = class {
1483
1289
  };
1484
- function makeConfig(original, editor) {
1485
- if (editor === "vscode") {
1486
- return {
1487
- ...original,
1488
- servers: {
1489
- ...original?.servers || {},
1490
- ...createMcpConfig(editor).servers
1491
- }
1492
- };
1493
- }
1494
- return {
1495
- ...original,
1496
- mcpServers: {
1497
- ...original?.mcpServers || {},
1498
- ...createMcpConfig(editor).mcpServers
1499
- }
1500
- };
1501
- }
1502
- async function writeMergedConfig(configPath, editor) {
1503
- const configExists = existsSync(configPath);
1504
- const config = makeConfig(configExists ? await readJSON(configPath) : {}, editor);
1505
- await ensureFile(configPath);
1506
- await writeJSON(configPath, config, {
1507
- spaces: 2
1508
- });
1509
- }
1510
- var windsurfGlobalMCPConfigPath = path3.join(os.homedir(), ".codeium", "windsurf", "mcp_config.json");
1511
- var cursorGlobalMCPConfigPath = path3.join(os.homedir(), ".cursor", "mcp.json");
1512
- path3.join(process.cwd(), ".vscode", "mcp.json");
1513
- var vscodeGlobalMCPConfigPath = path3.join(
1514
- os.homedir(),
1515
- 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")
1516
- );
1517
- async function installMastraDocsMCPServer({ editor, directory }) {
1518
- if (editor === `cursor`) {
1519
- await writeMergedConfig(path3.join(directory, ".cursor", "mcp.json"), "cursor");
1520
- }
1521
- if (editor === `vscode`) {
1522
- await writeMergedConfig(path3.join(directory, ".vscode", "mcp.json"), "vscode");
1290
+ var FileEnvService = class extends EnvService {
1291
+ filePath;
1292
+ constructor(filePath) {
1293
+ super();
1294
+ this.filePath = filePath;
1523
1295
  }
1524
- if (editor === `cursor-global`) {
1525
- const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor);
1526
- if (alreadyInstalled) {
1527
- return;
1528
- }
1529
- await writeMergedConfig(cursorGlobalMCPConfigPath, "cursor-global");
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
+ });
1530
1303
  }
1531
- if (editor === `windsurf`) {
1532
- const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor);
1533
- if (alreadyInstalled) {
1534
- return;
1535
- }
1536
- await writeMergedConfig(windsurfGlobalMCPConfigPath, editor);
1537
- }
1538
- }
1539
- async function globalMCPIsAlreadyInstalled(editor) {
1540
- let configPath = ``;
1541
- if (editor === "windsurf") {
1542
- configPath = windsurfGlobalMCPConfigPath;
1543
- } else if (editor === "cursor-global") {
1544
- configPath = cursorGlobalMCPConfigPath;
1545
- } else if (editor === "vscode") {
1546
- configPath = vscodeGlobalMCPConfigPath;
1547
- }
1548
- if (!configPath || !existsSync(configPath)) {
1549
- return false;
1550
- }
1551
- try {
1552
- const configContents = await readJSON(configPath);
1553
- if (!configContents) return false;
1554
- if (editor === "vscode") {
1555
- if (!configContents.servers) return false;
1556
- const hasMastraMCP2 = Object.values(configContents.servers).some(
1557
- (server) => server?.args?.find((arg) => arg?.includes(`@mastra/mcp-docs-server`))
1558
- );
1559
- return hasMastraMCP2;
1560
- }
1561
- if (!configContents?.mcpServers) return false;
1562
- const hasMastraMCP = Object.values(configContents.mcpServers).some(
1563
- (server) => server?.args?.find((arg) => arg?.includes(`@mastra/mcp-docs-server`))
1564
- );
1565
- return hasMastraMCP;
1566
- } catch {
1567
- return false;
1568
- }
1569
- }
1570
- var EnvService = class {
1571
- };
1572
- var FileEnvService = class extends EnvService {
1573
- filePath;
1574
- constructor(filePath) {
1575
- super();
1576
- this.filePath = filePath;
1577
- }
1578
- readFile(filePath) {
1579
- return new Promise((resolve, reject) => {
1580
- fs4__default.readFile(filePath, "utf8", (err, data) => {
1581
- if (err) reject(err);
1582
- else resolve(data);
1583
- });
1584
- });
1585
- }
1586
- writeFile({ filePath, data }) {
1587
- return new Promise((resolve, reject) => {
1588
- fs4__default.writeFile(filePath, data, "utf8", (err) => {
1589
- if (err) reject(err);
1590
- else resolve();
1591
- });
1592
- });
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
+ });
1593
1311
  }
1594
1312
  async updateEnvData({
1595
1313
  key,
@@ -1605,7 +1323,7 @@ var FileEnvService = class extends EnvService {
1605
1323
  ${key}=${value}`;
1606
1324
  }
1607
1325
  await this.writeFile({ filePath, data });
1608
- console.log(`${key} set to ${value} in ENV file.`);
1326
+ console.info(`${key} set to ${value} in ENV file.`);
1609
1327
  return data;
1610
1328
  }
1611
1329
  async getEnvValue(key) {
@@ -1640,23 +1358,23 @@ var FileService = class {
1640
1358
  const __filename = fileURLToPath(import.meta.url);
1641
1359
  const __dirname = path3.dirname(__filename);
1642
1360
  const filePath = path3.resolve(__dirname, "starter-files", inputFile);
1643
- const fileString = fs4__default__default.readFileSync(filePath, "utf8");
1644
- if (fs4__default__default.existsSync(outputFilePath) && !replaceIfExists) {
1645
- 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`);
1646
1364
  return false;
1647
1365
  }
1648
- await fsExtra3.outputFile(outputFilePath, fileString);
1366
+ await fsExtra.outputFile(outputFilePath, fileString);
1649
1367
  return true;
1650
1368
  }
1651
1369
  async setupEnvFile({ dbUrl }) {
1652
1370
  const envPath = path3.join(process.cwd(), ".env.development");
1653
- await fsExtra3.ensureFile(envPath);
1371
+ await fsExtra.ensureFile(envPath);
1654
1372
  const fileEnvService = new FileEnvService(envPath);
1655
1373
  await fileEnvService.setEnvValue("DB_URL", dbUrl);
1656
1374
  }
1657
1375
  getFirstExistingFile(files) {
1658
1376
  for (const f of files) {
1659
- if (fs4__default__default.existsSync(f)) {
1377
+ if (fs3__default__default.existsSync(f)) {
1660
1378
  return f;
1661
1379
  }
1662
1380
  }
@@ -1666,53 +1384,152 @@ var FileService = class {
1666
1384
  filePath,
1667
1385
  replacements
1668
1386
  }) {
1669
- let fileContent = fs4__default__default.readFileSync(filePath, "utf8");
1387
+ let fileContent = fs3__default__default.readFileSync(filePath, "utf8");
1670
1388
  replacements.forEach(({ search, replace }) => {
1671
1389
  fileContent = fileContent.replaceAll(search, replace);
1672
1390
  });
1673
- fs4__default__default.writeFileSync(filePath, fileContent);
1391
+ fs3__default__default.writeFileSync(filePath, fileContent);
1674
1392
  }
1675
1393
  };
1676
- var exec2 = util.promisify(child_process.exec);
1677
- var getAISDKPackage = (llmProvider) => {
1678
- switch (llmProvider) {
1679
- case "openai":
1680
- return "@ai-sdk/openai";
1681
- case "anthropic":
1682
- return "@ai-sdk/anthropic";
1683
- case "groq":
1684
- return "@ai-sdk/groq";
1685
- case "google":
1686
- return "@ai-sdk/google";
1687
- case "cerebras":
1688
- return "@ai-sdk/cerebras";
1689
- default:
1690
- return "@ai-sdk/openai";
1394
+ var createArgs = (versionTag) => {
1395
+ const packageName = versionTag ? `@mastra/mcp-docs-server@${versionTag}` : "@mastra/mcp-docs-server";
1396
+ return ["-y", packageName];
1397
+ };
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
+ };
1691
1414
  }
1415
+ return {
1416
+ mcpServers: {
1417
+ mastra: {
1418
+ command: "npx",
1419
+ args
1420
+ }
1421
+ }
1422
+ };
1692
1423
  };
1693
- var getProviderImportAndModelItem = (llmProvider) => {
1694
- let providerImport = "";
1695
- let modelItem = "";
1696
- if (llmProvider === "openai") {
1697
- providerImport = `import { openai } from '${getAISDKPackage(llmProvider)}';`;
1698
- modelItem = `openai('gpt-4o-mini')`;
1699
- } else if (llmProvider === "anthropic") {
1700
- providerImport = `import { anthropic } from '${getAISDKPackage(llmProvider)}';`;
1701
- 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";
1702
1520
  } else if (llmProvider === "groq") {
1703
- providerImport = `import { groq } from '${getAISDKPackage(llmProvider)}';`;
1704
- modelItem = `groq('llama-3.3-70b-versatile')`;
1521
+ model = "groq/llama-3.3-70b-versatile";
1705
1522
  } else if (llmProvider === "google") {
1706
- providerImport = `import { google } from '${getAISDKPackage(llmProvider)}';`;
1707
- modelItem = `google('gemini-2.5-pro-exp-03-25')`;
1523
+ model = "google/gemini-2.5-pro";
1708
1524
  } else if (llmProvider === "cerebras") {
1709
- providerImport = `import { cerebras } from '${getAISDKPackage(llmProvider)}';`;
1710
- modelItem = `cerebras('llama-3.3-70b')`;
1525
+ model = "cerebras/llama-3.3-70b";
1526
+ } else if (llmProvider === "mistral") {
1527
+ model = "mistral/mistral-medium-2508";
1711
1528
  }
1712
- return { providerImport, modelItem };
1529
+ return model;
1713
1530
  };
1714
- async function writeAgentSample(llmProvider, destPath, addExampleTool) {
1715
- const { providerImport, modelItem } = getProviderImportAndModelItem(llmProvider);
1531
+ async function writeAgentSample(llmProvider, destPath, addExampleTool, addScorers) {
1532
+ const modelString = getModelIdentifier(llmProvider);
1716
1533
  const instructions = `
1717
1534
  You are a helpful weather assistant that provides accurate weather information and can help planning activities based on the weather.
1718
1535
 
@@ -1728,19 +1545,44 @@ async function writeAgentSample(llmProvider, destPath, addExampleTool) {
1728
1545
  ${addExampleTool ? "Use the weatherTool to fetch current weather data." : ""}
1729
1546
  `;
1730
1547
  const content = `
1731
- ${providerImport}
1732
1548
  import { Agent } from '@mastra/core/agent';
1733
1549
  import { Memory } from '@mastra/memory';
1734
1550
  import { LibSQLStore } from '@mastra/libsql';
1735
1551
  ${addExampleTool ? `import { weatherTool } from '../tools/weather-tool';` : ""}
1552
+ ${addScorers ? `import { scorers } from '../scorers/weather-scorer';` : ""}
1736
1553
 
1737
1554
  export const weatherAgent = new Agent({
1555
+ id: 'weather-agent',
1738
1556
  name: 'Weather Agent',
1739
1557
  instructions: \`${instructions}\`,
1740
- model: ${modelItem},
1558
+ model: '${modelString}',
1741
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
+ },` : ""}
1742
1583
  memory: new Memory({
1743
1584
  storage: new LibSQLStore({
1585
+ id: "memory-storage",
1744
1586
  url: "file:../mastra.db", // path is relative to the .mastra/output directory
1745
1587
  })
1746
1588
  })
@@ -1750,8 +1592,8 @@ export const weatherAgent = new Agent({
1750
1592
  parser: "typescript",
1751
1593
  singleQuote: true
1752
1594
  });
1753
- await fs.writeFile(destPath, "");
1754
- await fs.writeFile(destPath, formattedContent);
1595
+ await fs4.writeFile(destPath, "");
1596
+ await fs4.writeFile(destPath, formattedContent);
1755
1597
  }
1756
1598
  async function writeWorkflowSample(destPath) {
1757
1599
  const content = `import { createStep, createWorkflow } from '@mastra/core/workflows';
@@ -1944,72 +1786,176 @@ export { weatherWorkflow };`;
1944
1786
  semi: true,
1945
1787
  singleQuote: true
1946
1788
  });
1947
- await fs.writeFile(destPath, formattedContent);
1789
+ await fs4.writeFile(destPath, formattedContent);
1948
1790
  }
1949
1791
  async function writeToolSample(destPath) {
1950
1792
  const fileService = new FileService();
1951
1793
  await fileService.copyStarterFile("tools.ts", destPath);
1952
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
+ }
1953
1883
  async function writeCodeSampleForComponents(llmprovider, component, destPath, importComponents) {
1954
1884
  switch (component) {
1955
1885
  case "agents":
1956
- return writeAgentSample(llmprovider, destPath, importComponents.includes("tools"));
1886
+ return writeAgentSample(
1887
+ llmprovider,
1888
+ destPath,
1889
+ importComponents.includes("tools"),
1890
+ importComponents.includes("scorers")
1891
+ );
1957
1892
  case "tools":
1958
1893
  return writeToolSample(destPath);
1959
1894
  case "workflows":
1960
1895
  return writeWorkflowSample(destPath);
1896
+ case "scorers":
1897
+ return writeScorersSample(llmprovider, destPath);
1961
1898
  default:
1962
1899
  return "";
1963
1900
  }
1964
1901
  }
1965
1902
  var createComponentsDir = async (dirPath, component) => {
1966
1903
  const componentPath = dirPath + `/${component}`;
1967
- await fsExtra3.ensureDir(componentPath);
1904
+ await fsExtra.ensureDir(componentPath);
1968
1905
  };
1969
1906
  var writeIndexFile = async ({
1970
1907
  dirPath,
1971
1908
  addAgent,
1972
1909
  addExample,
1973
- addWorkflow
1910
+ addWorkflow,
1911
+ addScorers
1974
1912
  }) => {
1975
1913
  const indexPath = dirPath + "/index.ts";
1976
1914
  const destPath = path3.join(indexPath);
1977
1915
  try {
1978
- await fs.writeFile(destPath, "");
1916
+ await fs4.writeFile(destPath, "");
1979
1917
  const filteredExports = [
1980
1918
  addWorkflow ? `workflows: { weatherWorkflow },` : "",
1981
- addAgent ? `agents: { weatherAgent },` : ""
1919
+ addAgent ? `agents: { weatherAgent },` : "",
1920
+ addScorers ? `scorers: { toolCallAppropriatenessScorer, completenessScorer, translationScorer },` : ""
1982
1921
  ].filter(Boolean);
1983
1922
  if (!addExample) {
1984
- await fs.writeFile(
1923
+ await fs4.writeFile(
1985
1924
  destPath,
1986
1925
  `
1987
- import { Mastra } from '@mastra/core';
1926
+ import { Mastra } from '@mastra/core/mastra';
1988
1927
 
1989
1928
  export const mastra = new Mastra()
1990
1929
  `
1991
1930
  );
1992
1931
  return;
1993
1932
  }
1994
- await fs.writeFile(
1933
+ await fs4.writeFile(
1995
1934
  destPath,
1996
1935
  `
1997
1936
  import { Mastra } from '@mastra/core/mastra';
1998
1937
  import { PinoLogger } from '@mastra/loggers';
1999
1938
  import { LibSQLStore } from '@mastra/libsql';
1939
+ import { Observability } from '@mastra/observability';
2000
1940
  ${addWorkflow ? `import { weatherWorkflow } from './workflows/weather-workflow';` : ""}
2001
1941
  ${addAgent ? `import { weatherAgent } from './agents/weather-agent';` : ""}
1942
+ ${addScorers ? `import { toolCallAppropriatenessScorer, completenessScorer, translationScorer } from './scorers/weather-scorer';` : ""}
2002
1943
 
2003
1944
  export const mastra = new Mastra({
2004
1945
  ${filteredExports.join("\n ")}
2005
1946
  storage: new LibSQLStore({
2006
- // 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
2007
1949
  url: ":memory:",
2008
1950
  }),
2009
1951
  logger: new PinoLogger({
2010
1952
  name: 'Mastra',
2011
1953
  level: 'info',
2012
1954
  }),
1955
+ observability: new Observability({
1956
+ // Enables DefaultExporter and CloudExporter for tracing
1957
+ default: { enabled: true },
1958
+ }),
2013
1959
  });
2014
1960
  `
2015
1961
  );
@@ -2017,7 +1963,6 @@ export const mastra = new Mastra({
2017
1963
  throw err;
2018
1964
  }
2019
1965
  };
2020
- yoctoSpinner({ text: "Installing Mastra core dependencies\n" });
2021
1966
  var getAPIKey = async (provider) => {
2022
1967
  let key = "OPENAI_API_KEY";
2023
1968
  switch (provider) {
@@ -2033,27 +1978,28 @@ var getAPIKey = async (provider) => {
2033
1978
  case "cerebras":
2034
1979
  key = "CEREBRAS_API_KEY";
2035
1980
  return key;
1981
+ case "mistral":
1982
+ key = "MISTRAL_API_KEY";
1983
+ return key;
2036
1984
  default:
2037
1985
  return key;
2038
1986
  }
2039
1987
  };
2040
- var writeAPIKey = async ({
2041
- provider,
2042
- apiKey = "your-api-key"
2043
- }) => {
1988
+ var writeAPIKey = async ({ provider, apiKey }) => {
1989
+ const envFileName = apiKey ? ".env" : ".env.example";
2044
1990
  const key = await getAPIKey(provider);
2045
- const escapedKey = shellQuote.quote([key]);
2046
- const escapedApiKey = shellQuote.quote([apiKey]);
2047
- 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}`);
2048
1994
  };
2049
1995
  var createMastraDir = async (directory) => {
2050
1996
  let dir = directory.trim().split("/").filter((item) => item !== "");
2051
1997
  const dirPath = path3.join(process.cwd(), ...dir, "mastra");
2052
1998
  try {
2053
- await fs.access(dirPath);
1999
+ await fs4.access(dirPath);
2054
2000
  return { ok: false };
2055
2001
  } catch {
2056
- await fsExtra3.ensureDir(dirPath);
2002
+ await fsExtra.ensureDir(dirPath);
2057
2003
  return { ok: true, dirPath };
2058
2004
  }
2059
2005
  };
@@ -2065,8 +2011,19 @@ var writeCodeSample = async (dirPath, component, llmProvider, importComponents)
2065
2011
  throw err;
2066
2012
  }
2067
2013
  };
2068
- var interactivePrompt = async () => {
2069
- 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
+ }
2070
2027
  const mastraProject = await Ce(
2071
2028
  {
2072
2029
  directory: () => he({
@@ -2074,19 +2031,15 @@ var interactivePrompt = async () => {
2074
2031
  placeholder: "src/",
2075
2032
  defaultValue: "src/"
2076
2033
  }),
2077
- llmProvider: () => ve({
2078
- message: "Select default provider:",
2079
- options: [
2080
- { value: "openai", label: "OpenAI", hint: "recommended" },
2081
- { value: "anthropic", label: "Anthropic" },
2082
- { value: "groq", label: "Groq" },
2083
- { value: "google", label: "Google" },
2084
- { value: "cerebras", label: "Cerebras" }
2085
- ]
2034
+ llmProvider: () => skip?.llmProvider ? void 0 : ve({
2035
+ message: "Select a default provider:",
2036
+ options: LLM_PROVIDERS
2086
2037
  }),
2087
2038
  llmApiKey: async ({ results: { llmProvider } }) => {
2039
+ if (skip?.llmApiKey) return void 0;
2040
+ const llmName = LLM_PROVIDERS.find((p6) => p6.value === llmProvider)?.label || "provider";
2088
2041
  const keyChoice = await ve({
2089
- message: `Enter your ${llmProvider} API key?`,
2042
+ message: `Enter your ${llmName} API key?`,
2090
2043
  options: [
2091
2044
  { value: "skip", label: "Skip for now", hint: "default" },
2092
2045
  { value: "enter", label: "Enter API key" }
@@ -2096,52 +2049,38 @@ var interactivePrompt = async () => {
2096
2049
  if (keyChoice === "enter") {
2097
2050
  return he({
2098
2051
  message: "Enter your API key:",
2099
- placeholder: "sk-..."
2052
+ placeholder: "sk-...",
2053
+ validate: (value) => {
2054
+ if (value.length === 0) return "API key cannot be empty";
2055
+ }
2100
2056
  });
2101
2057
  }
2102
2058
  return void 0;
2103
2059
  },
2104
2060
  configureEditorWithDocsMCP: async () => {
2105
- const windsurfIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`windsurf`);
2106
- const cursorIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`cursor`);
2107
- const vscodeIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`vscode`);
2108
2061
  const editor = await ve({
2109
- 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)`,
2110
2063
  options: [
2111
2064
  { value: "skip", label: "Skip for now", hint: "default" },
2112
2065
  {
2113
2066
  value: "cursor",
2114
- label: "Cursor (project only)",
2115
- hint: cursorIsAlreadyInstalled ? `Already installed globally` : void 0
2067
+ label: "Cursor (project only)"
2116
2068
  },
2117
2069
  {
2118
2070
  value: "cursor-global",
2119
- label: "Cursor (global, all projects)",
2120
- hint: cursorIsAlreadyInstalled ? `Already installed` : void 0
2071
+ label: "Cursor (global, all projects)"
2121
2072
  },
2122
2073
  {
2123
2074
  value: "windsurf",
2124
- label: "Windsurf",
2125
- hint: windsurfIsAlreadyInstalled ? `Already installed` : void 0
2075
+ label: "Windsurf"
2126
2076
  },
2127
2077
  {
2128
2078
  value: "vscode",
2129
- label: "VSCode",
2130
- hint: vscodeIsAlreadyInstalled ? `Already installed` : void 0
2079
+ label: "VSCode"
2131
2080
  }
2132
2081
  ]
2133
2082
  });
2134
2083
  if (editor === `skip`) return void 0;
2135
- if (editor === `windsurf` && windsurfIsAlreadyInstalled) {
2136
- M.message(`
2137
- Windsurf is already installed, skipping.`);
2138
- return void 0;
2139
- }
2140
- if (editor === `vscode` && vscodeIsAlreadyInstalled) {
2141
- M.message(`
2142
- VSCode is already installed, skipping.`);
2143
- return void 0;
2144
- }
2145
2084
  if (editor === `cursor`) {
2146
2085
  M.message(
2147
2086
  `
@@ -2150,19 +2089,19 @@ Note: you will need to go into Cursor Settings -> MCP Settings and manually enab
2150
2089
  );
2151
2090
  }
2152
2091
  if (editor === `cursor-global`) {
2153
- const confirm2 = await ve({
2092
+ const confirm = await ve({
2154
2093
  message: `Global install will add/update ${cursorGlobalMCPConfigPath} and make the Mastra docs MCP server available in all your Cursor projects. Continue?`,
2155
2094
  options: [
2156
2095
  { value: "yes", label: "Yes, I understand" },
2157
2096
  { value: "skip", label: "No, skip for now" }
2158
2097
  ]
2159
2098
  });
2160
- if (confirm2 !== `yes`) {
2099
+ if (confirm !== `yes`) {
2161
2100
  return void 0;
2162
2101
  }
2163
2102
  }
2164
2103
  if (editor === `windsurf`) {
2165
- const confirm2 = await ve({
2104
+ const confirm = await ve({
2166
2105
  message: `Windsurf only supports a global MCP config (at ${windsurfGlobalMCPConfigPath}) is it ok to add/update that global config?
2167
2106
  This means the Mastra docs MCP server will be available in all your Windsurf projects.`,
2168
2107
  options: [
@@ -2170,7 +2109,7 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
2170
2109
  { value: "skip", label: "No, skip for now" }
2171
2110
  ]
2172
2111
  });
2173
- if (confirm2 !== `yes`) {
2112
+ if (confirm !== `yes`) {
2174
2113
  return void 0;
2175
2114
  }
2176
2115
  }
@@ -2186,17 +2125,230 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
2186
2125
  );
2187
2126
  return mastraProject;
2188
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
+ }
2189
2340
  var s = Y();
2190
- var exec3 = util.promisify(child_process.exec);
2191
2341
  var init = async ({
2192
- directory,
2193
- addExample = false,
2342
+ directory = "src/",
2194
2343
  components,
2195
2344
  llmProvider = "openai",
2196
2345
  llmApiKey,
2197
- configureEditorWithDocsMCP
2346
+ addExample = false,
2347
+ configureEditorWithDocsMCP,
2348
+ versionTag
2198
2349
  }) => {
2199
2350
  s.start("Initializing Mastra");
2351
+ const packageVersionTag = versionTag ? `@${versionTag}` : "";
2200
2352
  try {
2201
2353
  const result = await createMastraDir(directory);
2202
2354
  if (!result.ok) {
@@ -2209,7 +2361,8 @@ var init = async ({
2209
2361
  dirPath,
2210
2362
  addExample,
2211
2363
  addWorkflow: components.includes("workflows"),
2212
- addAgent: components.includes("agents")
2364
+ addAgent: components.includes("agents"),
2365
+ addScorers: components.includes("scorers")
2213
2366
  }),
2214
2367
  ...components.map((component) => createComponentsDir(dirPath, component)),
2215
2368
  writeAPIKey({ provider: llmProvider, apiKey: llmApiKey })
@@ -2223,27 +2376,31 @@ var init = async ({
2223
2376
  const depService = new DepsService();
2224
2377
  const needsLibsql = await depService.checkDependencies(["@mastra/libsql"]) !== `ok`;
2225
2378
  if (needsLibsql) {
2226
- await depService.installPackages(["@mastra/libsql"]);
2379
+ await depService.installPackages([`@mastra/libsql${packageVersionTag}`]);
2227
2380
  }
2228
2381
  const needsMemory = components.includes(`agents`) && await depService.checkDependencies(["@mastra/memory"]) !== `ok`;
2229
2382
  if (needsMemory) {
2230
- await depService.installPackages(["@mastra/memory"]);
2383
+ await depService.installPackages([`@mastra/memory${packageVersionTag}`]);
2231
2384
  }
2232
2385
  const needsLoggers = await depService.checkDependencies(["@mastra/loggers"]) !== `ok`;
2233
2386
  if (needsLoggers) {
2234
- 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}`]);
2235
2396
  }
2236
2397
  }
2237
2398
  const key = await getAPIKey(llmProvider || "openai");
2238
- const aiSdkPackage = getAISDKPackage(llmProvider);
2239
- const depsService = new DepsService();
2240
- const pm = depsService.packageManager;
2241
- const installCommand = getPackageManagerInstallCommand(pm);
2242
- await exec3(`${pm} ${installCommand} ${aiSdkPackage}`);
2243
2399
  if (configureEditorWithDocsMCP) {
2244
2400
  await installMastraDocsMCPServer({
2245
2401
  editor: configureEditorWithDocsMCP,
2246
- directory: process.cwd()
2402
+ directory: process.cwd(),
2403
+ versionTag
2247
2404
  });
2248
2405
  }
2249
2406
  s.stop();
@@ -2266,10 +2423,10 @@ var init = async ({
2266
2423
  return { success: false };
2267
2424
  }
2268
2425
  };
2269
- var exec4 = util.promisify(child_process.exec);
2426
+ var exec3 = util.promisify(child_process.exec);
2270
2427
  var execWithTimeout = async (command, timeoutMs) => {
2271
2428
  try {
2272
- const promise = exec4(command, { killSignal: "SIGTERM" });
2429
+ const promise = exec3(command, { killSignal: "SIGTERM" });
2273
2430
  if (!timeoutMs) {
2274
2431
  return await promise;
2275
2432
  }
@@ -2292,10 +2449,36 @@ var execWithTimeout = async (command, timeoutMs) => {
2292
2449
  throw error;
2293
2450
  }
2294
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
+ }
2295
2478
  async function installMastraDependency(pm, dependency, versionTag, isDev, timeout) {
2296
- let installCommand = getPackageManagerInstallCommand(pm);
2479
+ let installCommand = getPackageManagerAddCommand(pm);
2297
2480
  if (isDev) {
2298
- installCommand = `${installCommand} --save-dev`;
2481
+ installCommand = `${installCommand} -D`;
2299
2482
  }
2300
2483
  try {
2301
2484
  await execWithTimeout(`${pm} ${installCommand} ${dependency}${versionTag}`, timeout);
@@ -2317,23 +2500,42 @@ async function installMastraDependency(pm, dependency, versionTag, isDev, timeou
2317
2500
  var createMastraProject = async ({
2318
2501
  projectName: name,
2319
2502
  createVersionTag,
2320
- timeout
2503
+ timeout,
2504
+ llmProvider,
2505
+ llmApiKey,
2506
+ needsInteractive
2321
2507
  }) => {
2322
2508
  Ie(color2.inverse(" Mastra Create "));
2323
2509
  const projectName = name ?? await he({
2324
2510
  message: "What do you want to name your project?",
2325
2511
  placeholder: "my-mastra-app",
2326
- 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
+ }
2327
2519
  });
2328
2520
  if (pD(projectName)) {
2329
2521
  xe("Operation cancelled");
2330
2522
  process.exit(0);
2331
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
+ }
2332
2531
  const s2 = Y();
2532
+ const originalCwd = process.cwd();
2533
+ let projectPath = null;
2333
2534
  try {
2334
2535
  s2.start("Creating project");
2335
2536
  try {
2336
- await fs.mkdir(projectName);
2537
+ await fs4.mkdir(projectName);
2538
+ projectPath = path3.resolve(originalCwd, projectName);
2337
2539
  } catch (error) {
2338
2540
  if (error instanceof Error && "code" in error && error.code === "EEXIST") {
2339
2541
  s2.stop(`A directory named "${projectName}" already exists. Please choose a different name.`);
@@ -2345,12 +2547,10 @@ var createMastraProject = async ({
2345
2547
  }
2346
2548
  process.chdir(projectName);
2347
2549
  const pm = getPackageManager();
2348
- const installCommand = getPackageManagerInstallCommand(pm);
2550
+ const installCommand = getPackageManagerAddCommand(pm);
2349
2551
  s2.message("Initializing project structure");
2350
2552
  try {
2351
- await exec4(`npm init -y`);
2352
- await exec4(`npm pkg set type="module"`);
2353
- await exec4(`npm pkg set engines.node=">=20.9.0"`);
2553
+ await initializePackageJson(pm);
2354
2554
  const depsService = new DepsService();
2355
2555
  await depsService.addScriptsToPackageJson({
2356
2556
  dev: "mastra dev",
@@ -2365,9 +2565,9 @@ var createMastraProject = async ({
2365
2565
  s2.stop("Project structure created");
2366
2566
  s2.start(`Installing ${pm} dependencies`);
2367
2567
  try {
2368
- await exec4(`${pm} ${installCommand} zod@^3`);
2369
- await exec4(`${pm} ${installCommand} typescript @types/node --save-dev`);
2370
- await exec4(`echo '{
2568
+ await exec3(`${pm} ${installCommand} zod@^4`);
2569
+ await exec3(`${pm} ${installCommand} -D typescript @types/node`);
2570
+ await exec3(`echo '{
2371
2571
  "compilerOptions": {
2372
2572
  "target": "ES2022",
2373
2573
  "module": "ES2022",
@@ -2389,15 +2589,15 @@ var createMastraProject = async ({
2389
2589
  );
2390
2590
  }
2391
2591
  s2.stop(`${pm} dependencies installed`);
2392
- s2.start("Installing mastra");
2592
+ s2.start("Installing Mastra CLI");
2393
2593
  const versionTag = createVersionTag ? `@${createVersionTag}` : "@latest";
2394
2594
  try {
2395
2595
  await installMastraDependency(pm, "mastra", versionTag, true, timeout);
2396
2596
  } catch (error) {
2397
2597
  throw new Error(`Failed to install Mastra CLI: ${error instanceof Error ? error.message : "Unknown error"}`);
2398
2598
  }
2399
- s2.stop("mastra installed");
2400
- s2.start("Installing dependencies");
2599
+ s2.stop("Mastra CLI installed");
2600
+ s2.start("Installing Mastra dependencies");
2401
2601
  try {
2402
2602
  await installMastraDependency(pm, "@mastra/core", versionTag, false, timeout);
2403
2603
  await installMastraDependency(pm, "@mastra/libsql", versionTag, false, timeout);
@@ -2410,58 +2610,80 @@ var createMastraProject = async ({
2410
2610
  s2.stop("Mastra dependencies installed");
2411
2611
  s2.start("Adding .gitignore");
2412
2612
  try {
2413
- await exec4(`echo output.txt >> .gitignore`);
2414
- await exec4(`echo node_modules >> .gitignore`);
2415
- await exec4(`echo dist >> .gitignore`);
2416
- await exec4(`echo .mastra >> .gitignore`);
2417
- await exec4(`echo .env.development >> .gitignore`);
2418
- await exec4(`echo .env >> .gitignore`);
2419
- await exec4(`echo *.db >> .gitignore`);
2420
- 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`);
2421
2621
  } catch (error) {
2422
2622
  throw new Error(`Failed to create .gitignore: ${error instanceof Error ? error.message : "Unknown error"}`);
2423
2623
  }
2424
2624
  s2.stop(".gitignore added");
2425
2625
  Se("Project created successfully");
2426
- console.log("");
2427
- return { projectName };
2626
+ console.info("");
2627
+ return { projectName, result };
2428
2628
  } catch (error) {
2429
2629
  s2.stop();
2430
2630
  const errorMessage = error instanceof Error ? error.message : "An unexpected error occurred";
2431
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
+ }
2432
2642
  process.exit(1);
2433
2643
  }
2434
2644
  };
2435
- var create = async (args2) => {
2436
- if (args2.template !== void 0) {
2437
- await createFromTemplate(args2);
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
+ });
2438
2655
  return;
2439
2656
  }
2440
- const { projectName } = await createMastraProject({
2441
- projectName: args2?.projectName,
2442
- createVersionTag: args2?.createVersionTag,
2443
- 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
2444
2665
  });
2445
- const directory = args2.directory || "src/";
2446
- if (args2.components === void 0 || args2.llmProvider === void 0 || args2.addExample === void 0) {
2447
- const result = await interactivePrompt();
2666
+ const directory = args.directory || "src/";
2667
+ if (needsInteractive && result) {
2448
2668
  await init({
2449
2669
  ...result,
2450
2670
  llmApiKey: result?.llmApiKey,
2451
- components: ["agents", "tools", "workflows"],
2452
- addExample: true
2671
+ components: ["agents", "tools", "workflows", "scorers"],
2672
+ addExample: true,
2673
+ versionTag: args.createVersionTag
2453
2674
  });
2454
2675
  postCreate({ projectName });
2455
2676
  return;
2456
2677
  }
2457
- const { components = [], llmProvider = "openai", addExample = false, llmApiKey } = args2;
2678
+ const { components = [], llmProvider = "openai", addExample = false, llmApiKey } = args;
2458
2679
  await init({
2459
2680
  directory,
2460
2681
  components,
2461
2682
  llmProvider,
2462
2683
  addExample,
2463
2684
  llmApiKey,
2464
- configureEditorWithDocsMCP: args2.mcpServer
2685
+ configureEditorWithDocsMCP: args.mcpServer,
2686
+ versionTag: args.createVersionTag
2465
2687
  });
2466
2688
  postCreate({ projectName });
2467
2689
  };
@@ -2474,27 +2696,122 @@ var postCreate = ({ projectName }) => {
2474
2696
  ${color2.cyan(`${packageManager} run dev`)}
2475
2697
  `);
2476
2698
  };
2477
- async function createFromTemplate(args2) {
2478
- const templates = await loadTemplates();
2699
+ function isGitHubUrl(url) {
2700
+ try {
2701
+ const parsedUrl = new URL(url);
2702
+ return parsedUrl.hostname === "github.com" && parsedUrl.pathname.split("/").length >= 3;
2703
+ } catch {
2704
+ return false;
2705
+ }
2706
+ }
2707
+ async function validateGitHubProject(githubUrl) {
2708
+ const errors = [];
2709
+ try {
2710
+ const urlParts = new URL(githubUrl).pathname.split("/").filter(Boolean);
2711
+ const owner = urlParts[0];
2712
+ const repo = urlParts[1]?.replace(".git", "");
2713
+ if (!owner || !repo) {
2714
+ throw new Error("Invalid GitHub URL format");
2715
+ }
2716
+ const branches = ["main", "master"];
2717
+ let packageJsonContent = null;
2718
+ let indexContent = null;
2719
+ for (const branch of branches) {
2720
+ try {
2721
+ const packageJsonUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/package.json`;
2722
+ const packageJsonResponse = await fetch(packageJsonUrl);
2723
+ if (packageJsonResponse.ok) {
2724
+ packageJsonContent = await packageJsonResponse.text();
2725
+ const indexUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/src/mastra/index.ts`;
2726
+ const indexResponse = await fetch(indexUrl);
2727
+ if (indexResponse.ok) {
2728
+ indexContent = await indexResponse.text();
2729
+ }
2730
+ break;
2731
+ }
2732
+ } catch {
2733
+ }
2734
+ }
2735
+ if (!packageJsonContent) {
2736
+ errors.push("Could not fetch package.json from repository");
2737
+ return { isValid: false, errors };
2738
+ }
2739
+ try {
2740
+ const packageJson = JSON.parse(packageJsonContent);
2741
+ const hasMastraCore = packageJson.dependencies?.["@mastra/core"] || packageJson.devDependencies?.["@mastra/core"] || packageJson.peerDependencies?.["@mastra/core"];
2742
+ if (!hasMastraCore) {
2743
+ errors.push("Missing @mastra/core dependency in package.json");
2744
+ }
2745
+ } catch {
2746
+ errors.push("Invalid package.json format");
2747
+ }
2748
+ if (!indexContent) {
2749
+ errors.push("Missing src/mastra/index.ts file");
2750
+ } else {
2751
+ const hasMastraExport = indexContent.includes("export") && (indexContent.includes("new Mastra") || indexContent.includes("Mastra("));
2752
+ if (!hasMastraExport) {
2753
+ errors.push("src/mastra/index.ts does not export a Mastra instance");
2754
+ }
2755
+ }
2756
+ return { isValid: errors.length === 0, errors };
2757
+ } catch (error) {
2758
+ errors.push(`Failed to validate GitHub repository: ${error instanceof Error ? error.message : "Unknown error"}`);
2759
+ return { isValid: false, errors };
2760
+ }
2761
+ }
2762
+ async function createFromGitHubUrl(url) {
2763
+ const urlParts = new URL(url).pathname.split("/").filter(Boolean);
2764
+ const owner = urlParts[0] || "unknown";
2765
+ const repo = urlParts[1] || "unknown";
2766
+ return {
2767
+ githubUrl: url,
2768
+ title: `${owner}/${repo}`,
2769
+ slug: repo,
2770
+ agents: [],
2771
+ mcp: [],
2772
+ tools: [],
2773
+ networks: [],
2774
+ workflows: []
2775
+ };
2776
+ }
2777
+ async function createFromTemplate(args) {
2479
2778
  let selectedTemplate;
2480
- if (args2.template === true) {
2481
- selectedTemplate = await selectTemplate(templates);
2482
- if (!selectedTemplate) {
2779
+ if (args.template === true) {
2780
+ const templates = await loadTemplates();
2781
+ const selected = await selectTemplate(templates);
2782
+ if (!selected) {
2483
2783
  M.info("No template selected. Exiting.");
2484
2784
  return;
2485
2785
  }
2486
- } else if (args2.template) {
2487
- selectedTemplate = findTemplateByName(templates, args2.template);
2488
- if (!selectedTemplate) {
2489
- M.error(`Template "${args2.template}" not found. Available templates:`);
2490
- templates.forEach((t) => M.info(` - ${t.title} (use: ${t.slug.replace("template-", "")})`));
2491
- throw new Error(`Template "${args2.template}" not found`);
2786
+ selectedTemplate = selected;
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);
2792
+ if (!validation.isValid) {
2793
+ spinner4.stop("Validation failed");
2794
+ M.error("This does not appear to be a valid Mastra project:");
2795
+ validation.errors.forEach((error) => M.error(` - ${error}`));
2796
+ throw new Error("Invalid Mastra project");
2797
+ }
2798
+ spinner4.stop("Valid Mastra project \u2713");
2799
+ selectedTemplate = await createFromGitHubUrl(args.template);
2800
+ } else {
2801
+ const templates = await loadTemplates();
2802
+ const found = findTemplateByName(templates, args.template);
2803
+ if (!found) {
2804
+ M.error(`Template "${args.template}" not found. Available templates:`);
2805
+ templates.forEach((t) => M.info(` - ${t.title} (use: ${t.slug.replace("template-", "")})`));
2806
+ throw new Error(`Template "${args.template}" not found`);
2807
+ }
2808
+ selectedTemplate = found;
2492
2809
  }
2493
2810
  }
2494
2811
  if (!selectedTemplate) {
2495
2812
  throw new Error("No template selected");
2496
2813
  }
2497
- let projectName = args2.projectName;
2814
+ let projectName = args.projectName;
2498
2815
  if (!projectName) {
2499
2816
  const defaultName = getDefaultProjectName(selectedTemplate);
2500
2817
  const response = await he({
@@ -2508,22 +2825,62 @@ async function createFromTemplate(args2) {
2508
2825
  }
2509
2826
  projectName = response;
2510
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;
2511
2841
  try {
2512
- const analytics = getAnalytics();
2513
- if (analytics) ;
2514
- const projectPath = await cloneTemplate({
2842
+ const analytics = args.injectedAnalytics || getAnalytics();
2843
+ if (analytics) {
2844
+ analytics.trackEvent("cli_template_used", {
2845
+ template_slug: selectedTemplate.slug,
2846
+ template_title: selectedTemplate.title
2847
+ });
2848
+ if (llmProvider) {
2849
+ analytics.trackEvent("cli_model_provider_selected", {
2850
+ provider: llmProvider,
2851
+ selection_method: args.llmProvider ? "cli_args" : "interactive"
2852
+ });
2853
+ }
2854
+ }
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({
2515
2859
  template: selectedTemplate,
2516
- projectName
2860
+ projectName,
2861
+ branch,
2862
+ llmProvider
2517
2863
  });
2518
2864
  await installDependencies(projectPath);
2519
2865
  Me(`
2520
2866
  ${color2.green("Mastra template installed!")}
2521
2867
 
2522
- Add the necessary environment
2868
+ Add the necessary environment
2523
2869
  variables in your ${color2.cyan(".env")} file
2524
2870
  `);
2525
2871
  postCreate({ projectName });
2526
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
+ }
2527
2884
  M.error(`Failed to create project from template: ${error instanceof Error ? error.message : "Unknown error"}`);
2528
2885
  throw error;
2529
2886
  }
@@ -2533,13 +2890,13 @@ async function getPackageVersion() {
2533
2890
  const __filename = fileURLToPath(import.meta.url);
2534
2891
  const __dirname = dirname(__filename);
2535
2892
  const pkgJsonPath = path3.join(__dirname, "..", "package.json");
2536
- const content = await fsExtra.readJSON(pkgJsonPath);
2893
+ const content = await fsExtra$1.readJSON(pkgJsonPath);
2537
2894
  return content.version;
2538
2895
  }
2539
2896
  async function getCreateVersionTag() {
2540
2897
  try {
2541
2898
  const pkgPath = fileURLToPath(import.meta.resolve("create-mastra/package.json"));
2542
- const json = await fsExtra.readJSON(pkgPath);
2899
+ const json = await fsExtra$1.readJSON(pkgPath);
2543
2900
  const { stdout } = await execa("npm", ["dist-tag", "create-mastra"]);
2544
2901
  const tagLine = stdout.split("\n").find((distLine) => distLine.endsWith(`: ${json.version}`));
2545
2902
  const tag = tagLine ? tagLine.split(":")[0].trim() : "latest";
@@ -2563,29 +2920,30 @@ program.version(`${version}`, "-v, --version").description(`create-mastra ${vers
2563
2920
  analytics.trackCommand({
2564
2921
  command: "version"
2565
2922
  });
2566
- console.log(`create-mastra ${version}`);
2923
+ console.info(`create-mastra ${version}`);
2567
2924
  } catch {
2568
2925
  }
2569
2926
  });
2570
2927
  program.name("create-mastra").description("Create a new Mastra project").argument("[project-name]", "Directory name of the project").option(
2571
2928
  "-p, --project-name <string>",
2572
2929
  "Project name that will be used in package.json and as the project directory name."
2573
- ).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(
2574
2931
  "--template [template-name]",
2575
- "Create project from a template (use template name or leave blank to select from list)"
2932
+ "Create project from a template (use template name, public GitHub URL, or leave blank to select from list)"
2576
2933
  ).action(async (projectNameArg, args) => {
2577
2934
  const projectName = projectNameArg || args.projectName;
2578
2935
  const timeout = args?.timeout ? args?.timeout === true ? 6e4 : parseInt(args?.timeout, 10) : void 0;
2579
2936
  if (args.default) {
2580
2937
  await create({
2581
- components: ["agents", "tools", "workflows"],
2938
+ components: ["agents", "tools", "workflows", "scorers"],
2582
2939
  llmProvider: "openai",
2583
2940
  addExample: true,
2584
2941
  createVersionTag,
2585
2942
  timeout,
2586
2943
  mcpServer: args.mcp,
2587
2944
  directory: "src/",
2588
- template: args.template
2945
+ template: args.template,
2946
+ analytics
2589
2947
  });
2590
2948
  return;
2591
2949
  }
@@ -2593,13 +2951,14 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
2593
2951
  components: args.components ? args.components.split(",") : [],
2594
2952
  llmProvider: args.llm,
2595
2953
  addExample: args.example,
2596
- llmApiKey: args["llm-api-key"],
2954
+ llmApiKey: args.llmApiKey,
2597
2955
  createVersionTag,
2598
2956
  timeout,
2599
2957
  projectName,
2600
2958
  directory: args.dir,
2601
2959
  mcpServer: args.mcp,
2602
- template: args.template
2960
+ template: args.template,
2961
+ analytics
2603
2962
  });
2604
2963
  });
2605
2964
  program.parse(process.argv);