create-mastra 0.0.0-fix-thread-list-20251105222841 → 0.0.0-fix-issue-10434-concurrent-write-corruption-20251124213939

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
@@ -4,15 +4,15 @@ import { randomUUID } from 'node:crypto';
4
4
  import * as fs3__default from 'node:fs';
5
5
  import fs3__default__default, { existsSync, readFileSync, writeFileSync } from 'node:fs';
6
6
  import os from 'node:os';
7
- import path, { dirname } from 'node:path';
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 fs4 from 'node:fs/promises';
16
16
  import child_process from 'node:child_process';
17
17
  import tty from 'node:tty';
18
18
  import fsExtra, { readJSON, ensureFile, writeJSON } from 'fs-extra/esm';
@@ -23,7 +23,7 @@ import pretty from 'pino-pretty';
23
23
  import fsExtra$1 from 'fs-extra';
24
24
 
25
25
  var __filename = fileURLToPath(import.meta.url);
26
- var __dirname = path.dirname(__filename);
26
+ var __dirname = path3.dirname(__filename);
27
27
  var analyticsInstance = null;
28
28
  function getAnalytics() {
29
29
  return analyticsInstance;
@@ -39,7 +39,7 @@ var PosthogAnalytics = class {
39
39
  host = "https://app.posthog.com"
40
40
  }) {
41
41
  this.version = version;
42
- const cliConfigPath = path.join(__dirname, "mastra-cli.json");
42
+ const cliConfigPath = path3.join(__dirname, "mastra-cli.json");
43
43
  if (existsSync(cliConfigPath)) {
44
44
  try {
45
45
  const { distinctId, sessionId } = JSON.parse(readFileSync(cliConfigPath, "utf-8"));
@@ -67,7 +67,7 @@ var PosthogAnalytics = class {
67
67
  }
68
68
  writeCliConfig({ distinctId, sessionId }) {
69
69
  try {
70
- writeFileSync(path.join(__dirname, "mastra-cli.json"), JSON.stringify({ distinctId, sessionId }));
70
+ writeFileSync(path3.join(__dirname, "mastra-cli.json"), JSON.stringify({ distinctId, sessionId }));
71
71
  } catch {
72
72
  }
73
73
  }
@@ -887,6 +887,7 @@ class YoctoSpinner {
887
887
  #exitHandlerBound;
888
888
  #isInteractive;
889
889
  #lastSpinnerFrameTime = 0;
890
+ #isSpinning = false;
890
891
 
891
892
  constructor(options = {}) {
892
893
  const spinner = options.spinner ?? defaultSpinner;
@@ -908,13 +909,17 @@ class YoctoSpinner {
908
909
  return this;
909
910
  }
910
911
 
912
+ this.#isSpinning = true;
911
913
  this.#hideCursor();
912
914
  this.#render();
913
915
  this.#subscribeToProcessEvents();
914
916
 
915
- this.#timer = setInterval(() => {
916
- this.#render();
917
- }, 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
+ }
918
923
 
919
924
  return this;
920
925
  }
@@ -924,8 +929,12 @@ class YoctoSpinner {
924
929
  return this;
925
930
  }
926
931
 
927
- clearInterval(this.#timer);
928
- this.#timer = undefined;
932
+ this.#isSpinning = false;
933
+ if (this.#timer) {
934
+ clearInterval(this.#timer);
935
+ this.#timer = undefined;
936
+ }
937
+
929
938
  this.#showCursor();
930
939
  this.clear();
931
940
  this.#unsubscribeFromProcessEvents();
@@ -958,7 +967,7 @@ class YoctoSpinner {
958
967
  }
959
968
 
960
969
  get isSpinning() {
961
- return this.#timer !== undefined;
970
+ return this.#isSpinning;
962
971
  }
963
972
 
964
973
  get text() {
@@ -1178,118 +1187,8 @@ var PinoLogger = class extends MastraLogger {
1178
1187
  }
1179
1188
  };
1180
1189
 
1181
- var args = ["-y", "@mastra/mcp-docs-server"];
1182
- var createMcpConfig = (editor) => {
1183
- if (editor === "vscode") {
1184
- return {
1185
- servers: {
1186
- mastra: process.platform === `win32` ? {
1187
- command: "cmd",
1188
- args: ["/c", "npx", ...args],
1189
- type: "stdio"
1190
- } : {
1191
- command: "npx",
1192
- args,
1193
- type: "stdio"
1194
- }
1195
- }
1196
- };
1197
- }
1198
- return {
1199
- mcpServers: {
1200
- mastra: {
1201
- command: "npx",
1202
- args
1203
- }
1204
- }
1205
- };
1206
- };
1207
- function makeConfig(original, editor) {
1208
- if (editor === "vscode") {
1209
- return {
1210
- ...original,
1211
- servers: {
1212
- ...original?.servers || {},
1213
- ...createMcpConfig(editor).servers
1214
- }
1215
- };
1216
- }
1217
- return {
1218
- ...original,
1219
- mcpServers: {
1220
- ...original?.mcpServers || {},
1221
- ...createMcpConfig(editor).mcpServers
1222
- }
1223
- };
1224
- }
1225
- async function writeMergedConfig(configPath, editor) {
1226
- const configExists = existsSync(configPath);
1227
- const config = makeConfig(configExists ? await readJSON(configPath) : {}, editor);
1228
- await ensureFile(configPath);
1229
- await writeJSON(configPath, config, {
1230
- spaces: 2
1231
- });
1232
- }
1233
- var windsurfGlobalMCPConfigPath = path.join(os.homedir(), ".codeium", "windsurf", "mcp_config.json");
1234
- var cursorGlobalMCPConfigPath = path.join(os.homedir(), ".cursor", "mcp.json");
1235
- path.join(process.cwd(), ".vscode", "mcp.json");
1236
- var vscodeGlobalMCPConfigPath = path.join(
1237
- os.homedir(),
1238
- process.platform === "win32" ? path.join("AppData", "Roaming", "Code", "User", "settings.json") : process.platform === "darwin" ? path.join("Library", "Application Support", "Code", "User", "settings.json") : path.join(".config", "Code", "User", "settings.json")
1239
- );
1240
- async function installMastraDocsMCPServer({ editor, directory }) {
1241
- if (editor === `cursor`) {
1242
- await writeMergedConfig(path.join(directory, ".cursor", "mcp.json"), "cursor");
1243
- }
1244
- if (editor === `vscode`) {
1245
- await writeMergedConfig(path.join(directory, ".vscode", "mcp.json"), "vscode");
1246
- }
1247
- if (editor === `cursor-global`) {
1248
- const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor);
1249
- if (alreadyInstalled) {
1250
- return;
1251
- }
1252
- await writeMergedConfig(cursorGlobalMCPConfigPath, "cursor-global");
1253
- }
1254
- if (editor === `windsurf`) {
1255
- const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor);
1256
- if (alreadyInstalled) {
1257
- return;
1258
- }
1259
- await writeMergedConfig(windsurfGlobalMCPConfigPath, editor);
1260
- }
1261
- }
1262
- async function globalMCPIsAlreadyInstalled(editor) {
1263
- let configPath = ``;
1264
- if (editor === "windsurf") {
1265
- configPath = windsurfGlobalMCPConfigPath;
1266
- } else if (editor === "cursor-global") {
1267
- configPath = cursorGlobalMCPConfigPath;
1268
- } else if (editor === "vscode") {
1269
- configPath = vscodeGlobalMCPConfigPath;
1270
- }
1271
- if (!configPath || !existsSync(configPath)) {
1272
- return false;
1273
- }
1274
- try {
1275
- const configContents = await readJSON(configPath);
1276
- if (!configContents) return false;
1277
- if (editor === "vscode") {
1278
- if (!configContents.servers) return false;
1279
- const hasMastraMCP2 = Object.values(configContents.servers).some(
1280
- (server) => server?.args?.find((arg) => arg?.includes(`@mastra/mcp-docs-server`))
1281
- );
1282
- return hasMastraMCP2;
1283
- }
1284
- if (!configContents?.mcpServers) return false;
1285
- const hasMastraMCP = Object.values(configContents.mcpServers).some(
1286
- (server) => server?.args?.find((arg) => arg?.includes(`@mastra/mcp-docs-server`))
1287
- );
1288
- return hasMastraMCP;
1289
- } catch {
1290
- return false;
1291
- }
1292
- }
1190
+ var package_default = {
1191
+ version: "1.0.0-beta.3"};
1293
1192
  function getPackageManagerAddCommand(pm) {
1294
1193
  switch (pm) {
1295
1194
  case "npm":
@@ -1312,11 +1211,11 @@ var DepsService = class {
1312
1211
  findLockFile(dir) {
1313
1212
  const lockFiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lock"];
1314
1213
  for (const file of lockFiles) {
1315
- if (fs3__default__default.existsSync(path.join(dir, file))) {
1214
+ if (fs3__default__default.existsSync(path3.join(dir, file))) {
1316
1215
  return file;
1317
1216
  }
1318
1217
  }
1319
- const parentDir = path.resolve(dir, "..");
1218
+ const parentDir = path3.resolve(dir, "..");
1320
1219
  if (parentDir !== dir) {
1321
1220
  return this.findLockFile(parentDir);
1322
1221
  }
@@ -1349,7 +1248,7 @@ var DepsService = class {
1349
1248
  }
1350
1249
  async checkDependencies(dependencies) {
1351
1250
  try {
1352
- const packageJsonPath = path.join(process.cwd(), "package.json");
1251
+ const packageJsonPath = path3.join(process.cwd(), "package.json");
1353
1252
  try {
1354
1253
  await fs4.access(packageJsonPath);
1355
1254
  } catch {
@@ -1369,7 +1268,7 @@ var DepsService = class {
1369
1268
  }
1370
1269
  async getProjectName() {
1371
1270
  try {
1372
- const packageJsonPath = path.join(process.cwd(), "package.json");
1271
+ const packageJsonPath = path3.join(process.cwd(), "package.json");
1373
1272
  const packageJson = await fs4.readFile(packageJsonPath, "utf-8");
1374
1273
  const pkg = JSON.parse(packageJson);
1375
1274
  return pkg.name;
@@ -1457,8 +1356,8 @@ var FileService = class {
1457
1356
  */
1458
1357
  async copyStarterFile(inputFile, outputFilePath, replaceIfExists) {
1459
1358
  const __filename = fileURLToPath(import.meta.url);
1460
- const __dirname = path.dirname(__filename);
1461
- const filePath = path.resolve(__dirname, "starter-files", inputFile);
1359
+ const __dirname = path3.dirname(__filename);
1360
+ const filePath = path3.resolve(__dirname, "starter-files", inputFile);
1462
1361
  const fileString = fs3__default__default.readFileSync(filePath, "utf8");
1463
1362
  if (fs3__default__default.existsSync(outputFilePath) && !replaceIfExists) {
1464
1363
  console.info(`${outputFilePath} already exists`);
@@ -1468,7 +1367,7 @@ var FileService = class {
1468
1367
  return true;
1469
1368
  }
1470
1369
  async setupEnvFile({ dbUrl }) {
1471
- const envPath = path.join(process.cwd(), ".env.development");
1370
+ const envPath = path3.join(process.cwd(), ".env.development");
1472
1371
  await fsExtra.ensureFile(envPath);
1473
1372
  const fileEnvService = new FileEnvService(envPath);
1474
1373
  await fileEnvService.setEnvValue("DB_URL", dbUrl);
@@ -1492,21 +1391,142 @@ var FileService = class {
1492
1391
  fs3__default__default.writeFileSync(filePath, fileContent);
1493
1392
  }
1494
1393
  };
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
+ };
1414
+ }
1415
+ return {
1416
+ mcpServers: {
1417
+ mastra: {
1418
+ command: "npx",
1419
+ args
1420
+ }
1421
+ }
1422
+ };
1423
+ };
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
+ }
1495
1515
  var exec = util.promisify(child_process.exec);
1496
1516
  var getModelIdentifier = (llmProvider) => {
1497
- if (llmProvider === "openai") {
1498
- return `'openai/gpt-4o-mini'`;
1499
- } else if (llmProvider === "anthropic") {
1500
- return `'anthropic/claude-sonnet-4-5-20250929'`;
1517
+ let model = "openai/gpt-4o";
1518
+ if (llmProvider === "anthropic") {
1519
+ model = "anthropic/claude-sonnet-4-5";
1501
1520
  } else if (llmProvider === "groq") {
1502
- return `'groq/llama-3.3-70b-versatile'`;
1521
+ model = "groq/llama-3.3-70b-versatile";
1503
1522
  } else if (llmProvider === "google") {
1504
- return `'google/gemini-2.5-pro'`;
1523
+ model = "google/gemini-2.5-pro";
1505
1524
  } else if (llmProvider === "cerebras") {
1506
- return `'cerebras/llama-3.3-70b'`;
1525
+ model = "cerebras/llama-3.3-70b";
1507
1526
  } else if (llmProvider === "mistral") {
1508
- return `'mistral/mistral-medium-2508'`;
1527
+ model = "mistral/mistral-medium-2508";
1509
1528
  }
1529
+ return model;
1510
1530
  };
1511
1531
  async function writeAgentSample(llmProvider, destPath, addExampleTool, addScorers) {
1512
1532
  const modelString = getModelIdentifier(llmProvider);
@@ -1535,7 +1555,7 @@ export const weatherAgent = new Agent({
1535
1555
  id: 'weather-agent',
1536
1556
  name: 'Weather Agent',
1537
1557
  instructions: \`${instructions}\`,
1538
- model: ${modelString},
1558
+ model: '${modelString}',
1539
1559
  ${addExampleTool ? "tools: { weatherTool }," : ""}
1540
1560
  ${addScorers ? `scorers: {
1541
1561
  toolCallAppropriateness: {
@@ -1562,6 +1582,7 @@ export const weatherAgent = new Agent({
1562
1582
  },` : ""}
1563
1583
  memory: new Memory({
1564
1584
  storage: new LibSQLStore({
1585
+ id: "memory-storage",
1565
1586
  url: "file:../mastra.db", // path is relative to the .mastra/output directory
1566
1587
  })
1567
1588
  })
@@ -1776,6 +1797,7 @@ async function writeScorersSample(llmProvider, destPath) {
1776
1797
  const content = `import { z } from 'zod';
1777
1798
  import { createToolCallAccuracyScorerCode } from '@mastra/evals/scorers/prebuilt';
1778
1799
  import { createCompletenessScorer } from '@mastra/evals/scorers/prebuilt';
1800
+ import { getAssistantMessageFromRunOutput, getUserMessageFromRunInput } from '@mastra/evals/scorers/utils';
1779
1801
  import { createScorer } from '@mastra/core/evals';
1780
1802
 
1781
1803
  export const toolCallAppropriatenessScorer = createToolCallAccuracyScorerCode({
@@ -1792,7 +1814,7 @@ export const translationScorer = createScorer({
1792
1814
  description: 'Checks that non-English location names are translated and used correctly',
1793
1815
  type: 'agent',
1794
1816
  judge: {
1795
- model: ${modelString},
1817
+ model: '${modelString}',
1796
1818
  instructions:
1797
1819
  'You are an expert evaluator of translation quality for geographic locations. ' +
1798
1820
  'Determine whether the user text mentions a non-English location and whether the assistant correctly uses an English translation of that location. ' +
@@ -1801,8 +1823,8 @@ export const translationScorer = createScorer({
1801
1823
  },
1802
1824
  })
1803
1825
  .preprocess(({ run }) => {
1804
- const userText = (run.input?.inputMessages?.[0]?.content as string) || '';
1805
- const assistantText = (run.output?.[0]?.content as string) || '';
1826
+ const userText = getUserMessageFromRunInput(run.input) || '';
1827
+ const assistantText = getAssistantMessageFromRunOutput(run.output) || '';
1806
1828
  return { userText, assistantText };
1807
1829
  })
1808
1830
  .analyze({
@@ -1889,7 +1911,7 @@ var writeIndexFile = async ({
1889
1911
  addScorers
1890
1912
  }) => {
1891
1913
  const indexPath = dirPath + "/index.ts";
1892
- const destPath = path.join(indexPath);
1914
+ const destPath = path3.join(indexPath);
1893
1915
  try {
1894
1916
  await fs4.writeFile(destPath, "");
1895
1917
  const filteredExports = [
@@ -1922,6 +1944,7 @@ ${addScorers ? `import { toolCallAppropriatenessScorer, completenessScorer, tran
1922
1944
  export const mastra = new Mastra({
1923
1945
  ${filteredExports.join("\n ")}
1924
1946
  storage: new LibSQLStore({
1947
+ id: "mastra-storage",
1925
1948
  // stores observability, scores, ... into memory storage, if it needs to persist, change to file:../mastra.db
1926
1949
  url: ":memory:",
1927
1950
  }),
@@ -1971,7 +1994,7 @@ var writeAPIKey = async ({ provider, apiKey }) => {
1971
1994
  };
1972
1995
  var createMastraDir = async (directory) => {
1973
1996
  let dir = directory.trim().split("/").filter((item) => item !== "");
1974
- const dirPath = path.join(process.cwd(), ...dir, "mastra");
1997
+ const dirPath = path3.join(process.cwd(), ...dir, "mastra");
1975
1998
  try {
1976
1999
  await fs4.access(dirPath);
1977
2000
  return { ok: false };
@@ -1996,8 +2019,8 @@ var LLM_PROVIDERS = [
1996
2019
  { value: "cerebras", label: "Cerebras" },
1997
2020
  { value: "mistral", label: "Mistral" }
1998
2021
  ];
1999
- var interactivePrompt = async (args2 = {}) => {
2000
- const { skip = {}, options: { showBanner = true } = {} } = args2;
2022
+ var interactivePrompt = async (args = {}) => {
2023
+ const { skip = {}, options: { showBanner = true } = {} } = args;
2001
2024
  if (showBanner) {
2002
2025
  Ie(color2.inverse(" Mastra Init "));
2003
2026
  }
@@ -2035,46 +2058,29 @@ var interactivePrompt = async (args2 = {}) => {
2035
2058
  return void 0;
2036
2059
  },
2037
2060
  configureEditorWithDocsMCP: async () => {
2038
- const windsurfIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`windsurf`);
2039
- const cursorIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`cursor`);
2040
- const vscodeIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`vscode`);
2041
2061
  const editor = await ve({
2042
2062
  message: `Make your IDE into a Mastra expert? (Installs Mastra's MCP server)`,
2043
2063
  options: [
2044
2064
  { value: "skip", label: "Skip for now", hint: "default" },
2045
2065
  {
2046
2066
  value: "cursor",
2047
- label: "Cursor (project only)",
2048
- hint: cursorIsAlreadyInstalled ? `Already installed globally` : void 0
2067
+ label: "Cursor (project only)"
2049
2068
  },
2050
2069
  {
2051
2070
  value: "cursor-global",
2052
- label: "Cursor (global, all projects)",
2053
- hint: cursorIsAlreadyInstalled ? `Already installed` : void 0
2071
+ label: "Cursor (global, all projects)"
2054
2072
  },
2055
2073
  {
2056
2074
  value: "windsurf",
2057
- label: "Windsurf",
2058
- hint: windsurfIsAlreadyInstalled ? `Already installed` : void 0
2075
+ label: "Windsurf"
2059
2076
  },
2060
2077
  {
2061
2078
  value: "vscode",
2062
- label: "VSCode",
2063
- hint: vscodeIsAlreadyInstalled ? `Already installed` : void 0
2079
+ label: "VSCode"
2064
2080
  }
2065
2081
  ]
2066
2082
  });
2067
2083
  if (editor === `skip`) return void 0;
2068
- if (editor === `windsurf` && windsurfIsAlreadyInstalled) {
2069
- M.message(`
2070
- Windsurf is already installed, skipping.`);
2071
- return void 0;
2072
- }
2073
- if (editor === `vscode` && vscodeIsAlreadyInstalled) {
2074
- M.message(`
2075
- VSCode is already installed, skipping.`);
2076
- return void 0;
2077
- }
2078
2084
  if (editor === `cursor`) {
2079
2085
  M.message(
2080
2086
  `
@@ -2122,6 +2128,9 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
2122
2128
  function getPackageManager() {
2123
2129
  const userAgent = process.env.npm_config_user_agent || "";
2124
2130
  const execPath = process.env.npm_execpath || "";
2131
+ if (userAgent.includes("bun")) {
2132
+ return "bun";
2133
+ }
2125
2134
  if (userAgent.includes("yarn")) {
2126
2135
  return "yarn";
2127
2136
  }
@@ -2131,6 +2140,9 @@ function getPackageManager() {
2131
2140
  if (userAgent.includes("npm")) {
2132
2141
  return "npm";
2133
2142
  }
2143
+ if (execPath.includes("bun")) {
2144
+ return "bun";
2145
+ }
2134
2146
  if (execPath.includes("yarn")) {
2135
2147
  return "yarn";
2136
2148
  }
@@ -2151,19 +2163,23 @@ function createLogger(debug = false) {
2151
2163
  }
2152
2164
  var exec2 = util.promisify(child_process.exec);
2153
2165
  async function cloneTemplate(options) {
2154
- const { template, projectName, targetDir } = options;
2155
- const projectPath = targetDir ? path.resolve(targetDir, projectName) : path.resolve(projectName);
2166
+ const { template, projectName, targetDir, branch, llmProvider } = options;
2167
+ const projectPath = targetDir ? path3.resolve(targetDir, projectName) : path3.resolve(projectName);
2156
2168
  const spinner4 = yoctoSpinner({ text: `Cloning template "${template.title}"...` }).start();
2157
2169
  try {
2158
2170
  if (await directoryExists(projectPath)) {
2159
2171
  spinner4.error(`Directory ${projectName} already exists`);
2160
2172
  throw new Error(`Directory ${projectName} already exists`);
2161
2173
  }
2162
- await cloneRepositoryWithoutGit(template.githubUrl, projectPath);
2174
+ await cloneRepositoryWithoutGit(template.githubUrl, projectPath, branch);
2163
2175
  await updatePackageJson(projectPath, projectName);
2164
- const envExamplePath = path.join(projectPath, ".env.example");
2176
+ const envExamplePath = path3.join(projectPath, ".env.example");
2165
2177
  if (await fileExists(envExamplePath)) {
2166
- await fs4.copyFile(envExamplePath, path.join(projectPath, ".env"));
2178
+ const envPath = path3.join(projectPath, ".env");
2179
+ await fs4.copyFile(envExamplePath, envPath);
2180
+ if (llmProvider) {
2181
+ await updateEnvFile(envPath, llmProvider);
2182
+ }
2167
2183
  }
2168
2184
  spinner4.success(`Template "${template.title}" cloned successfully to ${projectName}`);
2169
2185
  return projectPath;
@@ -2188,21 +2204,27 @@ async function fileExists(filePath) {
2188
2204
  return false;
2189
2205
  }
2190
2206
  }
2191
- async function cloneRepositoryWithoutGit(repoUrl, targetPath) {
2207
+ async function cloneRepositoryWithoutGit(repoUrl, targetPath, branch) {
2192
2208
  await fs4.mkdir(targetPath, { recursive: true });
2193
2209
  try {
2194
2210
  const degitRepo = repoUrl.replace("https://github.com/", "");
2195
- const degitCommand = shellQuote2.quote(["npx", "degit", degitRepo, targetPath]);
2211
+ const degitRepoWithBranch = branch ? `${degitRepo}#${branch}` : degitRepo;
2212
+ const degitCommand = shellQuote2.quote(["npx", "degit", degitRepoWithBranch, targetPath]);
2196
2213
  await exec2(degitCommand, {
2197
2214
  cwd: process.cwd()
2198
2215
  });
2199
2216
  } catch {
2200
2217
  try {
2201
- const gitCommand = shellQuote2.quote(["git", "clone", repoUrl, targetPath]);
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);
2202
2224
  await exec2(gitCommand, {
2203
2225
  cwd: process.cwd()
2204
2226
  });
2205
- const gitDir = path.join(targetPath, ".git");
2227
+ const gitDir = path3.join(targetPath, ".git");
2206
2228
  if (await directoryExists(gitDir)) {
2207
2229
  await fs4.rm(gitDir, { recursive: true, force: true });
2208
2230
  }
@@ -2212,7 +2234,7 @@ async function cloneRepositoryWithoutGit(repoUrl, targetPath) {
2212
2234
  }
2213
2235
  }
2214
2236
  async function updatePackageJson(projectPath, projectName) {
2215
- const packageJsonPath = path.join(projectPath, "package.json");
2237
+ const packageJsonPath = path3.join(projectPath, "package.json");
2216
2238
  try {
2217
2239
  const packageJsonContent = await fs4.readFile(packageJsonPath, "utf-8");
2218
2240
  const packageJson = JSON.parse(packageJsonContent);
@@ -2222,6 +2244,22 @@ async function updatePackageJson(projectPath, projectName) {
2222
2244
  logger.warn(`Could not update package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
2223
2245
  }
2224
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
+ }
2225
2263
  async function installDependencies(projectPath, packageManager) {
2226
2264
  const spinner4 = yoctoSpinner({ text: "Installing dependencies..." }).start();
2227
2265
  try {
@@ -2361,7 +2399,8 @@ var init = async ({
2361
2399
  if (configureEditorWithDocsMCP) {
2362
2400
  await installMastraDocsMCPServer({
2363
2401
  editor: configureEditorWithDocsMCP,
2364
- directory: process.cwd()
2402
+ directory: process.cwd(),
2403
+ versionTag
2365
2404
  });
2366
2405
  }
2367
2406
  s.stop();
@@ -2410,6 +2449,32 @@ var execWithTimeout = async (command, timeoutMs) => {
2410
2449
  throw error;
2411
2450
  }
2412
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
+ }
2413
2478
  async function installMastraDependency(pm, dependency, versionTag, isDev, timeout) {
2414
2479
  let installCommand = getPackageManagerAddCommand(pm);
2415
2480
  if (isDev) {
@@ -2464,10 +2529,13 @@ var createMastraProject = async ({
2464
2529
  });
2465
2530
  }
2466
2531
  const s2 = Y();
2532
+ const originalCwd = process.cwd();
2533
+ let projectPath = null;
2467
2534
  try {
2468
2535
  s2.start("Creating project");
2469
2536
  try {
2470
2537
  await fs4.mkdir(projectName);
2538
+ projectPath = path3.resolve(originalCwd, projectName);
2471
2539
  } catch (error) {
2472
2540
  if (error instanceof Error && "code" in error && error.code === "EEXIST") {
2473
2541
  s2.stop(`A directory named "${projectName}" already exists. Please choose a different name.`);
@@ -2482,9 +2550,7 @@ var createMastraProject = async ({
2482
2550
  const installCommand = getPackageManagerAddCommand(pm);
2483
2551
  s2.message("Initializing project structure");
2484
2552
  try {
2485
- await exec3(`npm init -y`);
2486
- await exec3(`npm pkg set type="module"`);
2487
- await exec3(`npm pkg set engines.node=">=20.9.0"`);
2553
+ await initializePackageJson(pm);
2488
2554
  const depsService = new DepsService();
2489
2555
  await depsService.addScriptsToPackageJson({
2490
2556
  dev: "mastra dev",
@@ -2500,7 +2566,7 @@ var createMastraProject = async ({
2500
2566
  s2.start(`Installing ${pm} dependencies`);
2501
2567
  try {
2502
2568
  await exec3(`${pm} ${installCommand} zod@^4`);
2503
- await exec3(`${pm} ${installCommand} typescript @types/node --save-dev`);
2569
+ await exec3(`${pm} ${installCommand} -D typescript @types/node`);
2504
2570
  await exec3(`echo '{
2505
2571
  "compilerOptions": {
2506
2572
  "target": "ES2022",
@@ -2563,44 +2629,61 @@ var createMastraProject = async ({
2563
2629
  s2.stop();
2564
2630
  const errorMessage = error instanceof Error ? error.message : "An unexpected error occurred";
2565
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
+ }
2566
2642
  process.exit(1);
2567
2643
  }
2568
2644
  };
2569
- var create = async (args2) => {
2570
- if (args2.template !== void 0) {
2571
- 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
+ });
2572
2655
  return;
2573
2656
  }
2574
- const needsInteractive = args2.components === void 0 || args2.llmProvider === void 0 || args2.addExample === void 0;
2657
+ const needsInteractive = args.components === void 0 || args.llmProvider === void 0 || args.addExample === void 0;
2575
2658
  const { projectName, result } = await createMastraProject({
2576
- projectName: args2?.projectName,
2577
- createVersionTag: args2?.createVersionTag,
2578
- timeout: args2?.timeout,
2579
- llmProvider: args2?.llmProvider,
2580
- llmApiKey: args2?.llmApiKey,
2659
+ projectName: args?.projectName,
2660
+ createVersionTag: args?.createVersionTag,
2661
+ timeout: args?.timeout,
2662
+ llmProvider: args?.llmProvider,
2663
+ llmApiKey: args?.llmApiKey,
2581
2664
  needsInteractive
2582
2665
  });
2583
- const directory = args2.directory || "src/";
2666
+ const directory = args.directory || "src/";
2584
2667
  if (needsInteractive && result) {
2585
2668
  await init({
2586
2669
  ...result,
2587
2670
  llmApiKey: result?.llmApiKey,
2588
2671
  components: ["agents", "tools", "workflows", "scorers"],
2589
2672
  addExample: true,
2590
- versionTag: args2.createVersionTag
2673
+ versionTag: args.createVersionTag
2591
2674
  });
2592
2675
  postCreate({ projectName });
2593
2676
  return;
2594
2677
  }
2595
- const { components = [], llmProvider = "openai", addExample = false, llmApiKey } = args2;
2678
+ const { components = [], llmProvider = "openai", addExample = false, llmApiKey } = args;
2596
2679
  await init({
2597
2680
  directory,
2598
2681
  components,
2599
2682
  llmProvider,
2600
2683
  addExample,
2601
2684
  llmApiKey,
2602
- configureEditorWithDocsMCP: args2.mcpServer,
2603
- versionTag: args2.createVersionTag
2685
+ configureEditorWithDocsMCP: args.mcpServer,
2686
+ versionTag: args.createVersionTag
2604
2687
  });
2605
2688
  postCreate({ projectName });
2606
2689
  };
@@ -2691,9 +2774,9 @@ async function createFromGitHubUrl(url) {
2691
2774
  workflows: []
2692
2775
  };
2693
2776
  }
2694
- async function createFromTemplate(args2) {
2777
+ async function createFromTemplate(args) {
2695
2778
  let selectedTemplate;
2696
- if (args2.template === true) {
2779
+ if (args.template === true) {
2697
2780
  const templates = await loadTemplates();
2698
2781
  const selected = await selectTemplate(templates);
2699
2782
  if (!selected) {
@@ -2701,11 +2784,11 @@ async function createFromTemplate(args2) {
2701
2784
  return;
2702
2785
  }
2703
2786
  selectedTemplate = selected;
2704
- } else if (args2.template && typeof args2.template === "string") {
2705
- if (isGitHubUrl(args2.template)) {
2787
+ } else if (args.template && typeof args.template === "string") {
2788
+ if (isGitHubUrl(args.template)) {
2706
2789
  const spinner4 = Y();
2707
2790
  spinner4.start("Validating GitHub repository...");
2708
- const validation = await validateGitHubProject(args2.template);
2791
+ const validation = await validateGitHubProject(args.template);
2709
2792
  if (!validation.isValid) {
2710
2793
  spinner4.stop("Validation failed");
2711
2794
  M.error("This does not appear to be a valid Mastra project:");
@@ -2713,14 +2796,14 @@ async function createFromTemplate(args2) {
2713
2796
  throw new Error("Invalid Mastra project");
2714
2797
  }
2715
2798
  spinner4.stop("Valid Mastra project \u2713");
2716
- selectedTemplate = await createFromGitHubUrl(args2.template);
2799
+ selectedTemplate = await createFromGitHubUrl(args.template);
2717
2800
  } else {
2718
2801
  const templates = await loadTemplates();
2719
- const found = findTemplateByName(templates, args2.template);
2802
+ const found = findTemplateByName(templates, args.template);
2720
2803
  if (!found) {
2721
- M.error(`Template "${args2.template}" not found. Available templates:`);
2804
+ M.error(`Template "${args.template}" not found. Available templates:`);
2722
2805
  templates.forEach((t) => M.info(` - ${t.title} (use: ${t.slug.replace("template-", "")})`));
2723
- throw new Error(`Template "${args2.template}" not found`);
2806
+ throw new Error(`Template "${args.template}" not found`);
2724
2807
  }
2725
2808
  selectedTemplate = found;
2726
2809
  }
@@ -2728,7 +2811,7 @@ async function createFromTemplate(args2) {
2728
2811
  if (!selectedTemplate) {
2729
2812
  throw new Error("No template selected");
2730
2813
  }
2731
- let projectName = args2.projectName;
2814
+ let projectName = args.projectName;
2732
2815
  if (!projectName) {
2733
2816
  const defaultName = getDefaultProjectName(selectedTemplate);
2734
2817
  const response = await he({
@@ -2742,17 +2825,41 @@ async function createFromTemplate(args2) {
2742
2825
  }
2743
2826
  projectName = response;
2744
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;
2745
2841
  try {
2746
- const analytics = args2.injectedAnalytics || getAnalytics();
2842
+ const analytics = args.injectedAnalytics || getAnalytics();
2747
2843
  if (analytics) {
2748
2844
  analytics.trackEvent("cli_template_used", {
2749
2845
  template_slug: selectedTemplate.slug,
2750
2846
  template_title: selectedTemplate.title
2751
2847
  });
2848
+ if (llmProvider) {
2849
+ analytics.trackEvent("cli_model_provider_selected", {
2850
+ provider: llmProvider,
2851
+ selection_method: args.llmProvider ? "cli_args" : "interactive"
2852
+ });
2853
+ }
2752
2854
  }
2753
- 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({
2754
2859
  template: selectedTemplate,
2755
- projectName
2860
+ projectName,
2861
+ branch,
2862
+ llmProvider
2756
2863
  });
2757
2864
  await installDependencies(projectPath);
2758
2865
  Me(`
@@ -2763,6 +2870,17 @@ async function createFromTemplate(args2) {
2763
2870
  `);
2764
2871
  postCreate({ projectName });
2765
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
+ }
2766
2884
  M.error(`Failed to create project from template: ${error instanceof Error ? error.message : "Unknown error"}`);
2767
2885
  throw error;
2768
2886
  }
@@ -2771,7 +2889,7 @@ async function createFromTemplate(args2) {
2771
2889
  async function getPackageVersion() {
2772
2890
  const __filename = fileURLToPath(import.meta.url);
2773
2891
  const __dirname = dirname(__filename);
2774
- const pkgJsonPath = path.join(__dirname, "..", "package.json");
2892
+ const pkgJsonPath = path3.join(__dirname, "..", "package.json");
2775
2893
  const content = await fsExtra$1.readJSON(pkgJsonPath);
2776
2894
  return content.version;
2777
2895
  }