create-mastra 1.0.0-beta.1 → 1.0.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +92 -0
- package/dist/index.js +425 -218
- package/dist/index.js.map +1 -1
- package/package.json +14 -15
package/dist/index.js
CHANGED
|
@@ -4,26 +4,26 @@ 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
|
|
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';
|
|
19
19
|
import prettier from 'prettier';
|
|
20
20
|
import { execa } from 'execa';
|
|
21
|
+
import fsExtra$1 from 'fs-extra';
|
|
21
22
|
import pino from 'pino';
|
|
22
23
|
import pretty from 'pino-pretty';
|
|
23
|
-
import fsExtra$1 from 'fs-extra';
|
|
24
24
|
|
|
25
25
|
var __filename = fileURLToPath(import.meta.url);
|
|
26
|
-
var __dirname =
|
|
26
|
+
var __dirname = path3.dirname(__filename);
|
|
27
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 =
|
|
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(
|
|
70
|
+
writeFileSync(path3.join(__dirname, "mastra-cli.json"), JSON.stringify({ distinctId, sessionId }));
|
|
71
71
|
} catch {
|
|
72
72
|
}
|
|
73
73
|
}
|
|
@@ -382,7 +382,7 @@ function DD({onlyFirst:e=false}={}){const t=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:
|
|
|
382
382
|
`).length-1;this.output.write(srcExports.cursor.move(-999,u*-1));}render(){const u=Y$1(this._render(this)??"",process.stdout.columns,{hard:true});if(u!==this._prevFrame){if(this.state==="initial")this.output.write(srcExports.cursor.hide);else {const t=BD(this._prevFrame,u);if(this.restoreCursor(),t&&t?.length===1){const F=t[0];this.output.write(srcExports.cursor.move(0,F)),this.output.write(srcExports.erase.lines(1));const s=u.split(`
|
|
383
383
|
`);this.output.write(s[F]),this._prevFrame=u,this.output.write(srcExports.cursor.move(0,s.length-F-1));return}if(t&&t?.length>1){const F=t[0];this.output.write(srcExports.cursor.move(0,F)),this.output.write(srcExports.erase.down());const s=u.split(`
|
|
384
384
|
`).slice(F);this.output.write(s.join(`
|
|
385
|
-
`)),this._prevFrame=u;return}this.output.write(srcExports.erase.down());}this.output.write(u),this.state==="initial"&&(this.state="active"),this._prevFrame=u;}}}var OD=Object.defineProperty,PD=(e,u,t)=>u in e?OD(e,u,{enumerable:true,configurable:true,writable:true,value:t}):e[u]=t,J=(e,u,t)=>(PD(e,typeof u!="symbol"?u+"":u,t),t);class LD extends x{constructor(u){super(u,false),J(this,"options"),J(this,"cursor",0),this.options=u.options,this.cursor=this.options.findIndex(({value:t})=>t===u.initialValue),this.cursor===-1&&(this.cursor=0),this.changeValue(),this.on("cursor",t=>{switch(t){case "left":case "up":this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;break;case "down":case "right":this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;break}this.changeValue();});}get _value(){return this.options[this.cursor]}changeValue(){this.value=this._value.value;}}class RD extends x{get valueWithCursor(){if(this.state==="submit")return this.value;if(this.cursor>=this.value.length)return `${this.value}\u2588`;const u=this.value.slice(0,this.cursor),[t,...F]=this.value.slice(this.cursor);return `${u}${color2.inverse(t)}${F.join("")}`}get cursor(){return this._cursor}constructor(u){super(u),this.on("finalize",()=>{this.value||(this.value=u.defaultValue);});}}
|
|
385
|
+
`)),this._prevFrame=u;return}this.output.write(srcExports.erase.down());}this.output.write(u),this.state==="initial"&&(this.state="active"),this._prevFrame=u;}}}class dD extends x{get cursor(){return this.value?0:1}get _value(){return this.cursor===0}constructor(u){super(u,false),this.value=!!u.initialValue,this.on("value",()=>{this.value=this._value;}),this.on("confirm",t=>{this.output.write(srcExports.cursor.move(0,-1)),this.value=t,this.state="submit",this.close();}),this.on("cursor",()=>{this.value=!this.value;});}}var OD=Object.defineProperty,PD=(e,u,t)=>u in e?OD(e,u,{enumerable:true,configurable:true,writable:true,value:t}):e[u]=t,J=(e,u,t)=>(PD(e,typeof u!="symbol"?u+"":u,t),t);class LD extends x{constructor(u){super(u,false),J(this,"options"),J(this,"cursor",0),this.options=u.options,this.cursor=this.options.findIndex(({value:t})=>t===u.initialValue),this.cursor===-1&&(this.cursor=0),this.changeValue(),this.on("cursor",t=>{switch(t){case "left":case "up":this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;break;case "down":case "right":this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;break}this.changeValue();});}get _value(){return this.options[this.cursor]}changeValue(){this.value=this._value.value;}}class RD extends x{get valueWithCursor(){if(this.state==="submit")return this.value;if(this.cursor>=this.value.length)return `${this.value}\u2588`;const u=this.value.slice(0,this.cursor),[t,...F]=this.value.slice(this.cursor);return `${u}${color2.inverse(t)}${F.join("")}`}get cursor(){return this._cursor}constructor(u){super(u),this.on("finalize",()=>{this.value||(this.value=u.defaultValue);});}}
|
|
386
386
|
|
|
387
387
|
function ce(){return y$1.platform!=="win32"?y$1.env.TERM!=="linux":!!y$1.env.CI||!!y$1.env.WT_SESSION||!!y$1.env.TERMINUS_SUBLIME||y$1.env.ConEmuTask==="{cmd::Cmder}"||y$1.env.TERM_PROGRAM==="Terminus-Sublime"||y$1.env.TERM_PROGRAM==="vscode"||y$1.env.TERM==="xterm-256color"||y$1.env.TERM==="alacritty"||y$1.env.TERMINAL_EMULATOR==="JetBrains-JediTerm"}const V=ce(),u=(t,n)=>V?t:n,le=u("\u25C6","*"),L=u("\u25A0","x"),W=u("\u25B2","x"),C=u("\u25C7","o"),ue=u("\u250C","T"),o=u("\u2502","|"),d=u("\u2514","\u2014"),k=u("\u25CF",">"),P=u("\u25CB"," "),_=u("\u2500","-"),me=u("\u256E","+"),de=u("\u251C","+"),pe=u("\u256F","+"),q=u("\u25CF","\u2022"),D=u("\u25C6","*"),U=u("\u25B2","!"),K=u("\u25A0","x"),b=t=>{switch(t){case "initial":case "active":return color2.cyan(le);case "cancel":return color2.red(L);case "error":return color2.yellow(W);case "submit":return color2.green(C)}},G=t=>{const{cursor:n,options:r,style:i}=t,s=t.maxItems??Number.POSITIVE_INFINITY,c=Math.max(process.stdout.rows-4,0),a=Math.min(c,Math.max(s,5));let l=0;n>=l+a-3?l=Math.max(Math.min(n-a+3,r.length-a),0):n<l+2&&(l=Math.max(n-2,0));const $=a<r.length&&l>0,g=a<r.length&&l+a<r.length;return r.slice(l,l+a).map((p,v,f)=>{const j=v===0&&$,E=v===f.length-1&&g;return j||E?color2.dim("..."):i(p,v+l===n)})},he=t=>new RD({validate:t.validate,placeholder:t.placeholder,defaultValue:t.defaultValue,initialValue:t.initialValue,render(){const n=`${color2.gray(o)}
|
|
388
388
|
${b(this.state)} ${t.message}
|
|
@@ -392,7 +392,12 @@ ${color2.yellow(d)} ${color2.yellow(this.error)}
|
|
|
392
392
|
`;case "submit":return `${n}${color2.gray(o)} ${color2.dim(this.value||t.placeholder)}`;case "cancel":return `${n}${color2.gray(o)} ${color2.strikethrough(color2.dim(this.value??""))}${this.value?.trim()?`
|
|
393
393
|
${color2.gray(o)}`:""}`;default:return `${n}${color2.cyan(o)} ${i}
|
|
394
394
|
${color2.cyan(d)}
|
|
395
|
-
`}}}).prompt(),
|
|
395
|
+
`}}}).prompt(),ye=t=>{const n=t.active??"Yes",r=t.inactive??"No";return new dD({active:n,inactive:r,initialValue:t.initialValue??true,render(){const i=`${color2.gray(o)}
|
|
396
|
+
${b(this.state)} ${t.message}
|
|
397
|
+
`,s=this.value?n:r;switch(this.state){case "submit":return `${i}${color2.gray(o)} ${color2.dim(s)}`;case "cancel":return `${i}${color2.gray(o)} ${color2.strikethrough(color2.dim(s))}
|
|
398
|
+
${color2.gray(o)}`;default:return `${i}${color2.cyan(o)} ${this.value?`${color2.green(k)} ${n}`:`${color2.dim(P)} ${color2.dim(n)}`} ${color2.dim("/")} ${this.value?`${color2.dim(P)} ${color2.dim(r)}`:`${color2.green(k)} ${r}`}
|
|
399
|
+
${color2.cyan(d)}
|
|
400
|
+
`}}}).prompt()},ve=t=>{const n=(r,i)=>{const s=r.label??String(r.value);switch(i){case "selected":return `${color2.dim(s)}`;case "active":return `${color2.green(k)} ${s} ${r.hint?color2.dim(`(${r.hint})`):""}`;case "cancelled":return `${color2.strikethrough(color2.dim(s))}`;default:return `${color2.dim(P)} ${color2.dim(s)}`}};return new LD({options:t.options,initialValue:t.initialValue,render(){const r=`${color2.gray(o)}
|
|
396
401
|
${b(this.state)} ${t.message}
|
|
397
402
|
`;switch(this.state){case "submit":return `${r}${color2.gray(o)} ${n(this.options[this.cursor],"selected")}`;case "cancel":return `${r}${color2.gray(o)} ${n(this.options[this.cursor],"cancelled")}
|
|
398
403
|
${color2.gray(o)}`;default:return `${r}${color2.cyan(o)} ${G({cursor:this.cursor,options:this.options,maxItems:t.maxItems,style:(i,s)=>n(i,s?"active":"inactive")}).join(`
|
|
@@ -887,6 +892,7 @@ class YoctoSpinner {
|
|
|
887
892
|
#exitHandlerBound;
|
|
888
893
|
#isInteractive;
|
|
889
894
|
#lastSpinnerFrameTime = 0;
|
|
895
|
+
#isSpinning = false;
|
|
890
896
|
|
|
891
897
|
constructor(options = {}) {
|
|
892
898
|
const spinner = options.spinner ?? defaultSpinner;
|
|
@@ -908,13 +914,17 @@ class YoctoSpinner {
|
|
|
908
914
|
return this;
|
|
909
915
|
}
|
|
910
916
|
|
|
917
|
+
this.#isSpinning = true;
|
|
911
918
|
this.#hideCursor();
|
|
912
919
|
this.#render();
|
|
913
920
|
this.#subscribeToProcessEvents();
|
|
914
921
|
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
922
|
+
// Only start the timer in interactive mode
|
|
923
|
+
if (this.#isInteractive) {
|
|
924
|
+
this.#timer = setInterval(() => {
|
|
925
|
+
this.#render();
|
|
926
|
+
}, this.#interval);
|
|
927
|
+
}
|
|
918
928
|
|
|
919
929
|
return this;
|
|
920
930
|
}
|
|
@@ -924,8 +934,12 @@ class YoctoSpinner {
|
|
|
924
934
|
return this;
|
|
925
935
|
}
|
|
926
936
|
|
|
927
|
-
|
|
928
|
-
this.#timer
|
|
937
|
+
this.#isSpinning = false;
|
|
938
|
+
if (this.#timer) {
|
|
939
|
+
clearInterval(this.#timer);
|
|
940
|
+
this.#timer = undefined;
|
|
941
|
+
}
|
|
942
|
+
|
|
929
943
|
this.#showCursor();
|
|
930
944
|
this.clear();
|
|
931
945
|
this.#unsubscribeFromProcessEvents();
|
|
@@ -958,7 +972,7 @@ class YoctoSpinner {
|
|
|
958
972
|
}
|
|
959
973
|
|
|
960
974
|
get isSpinning() {
|
|
961
|
-
return this.#
|
|
975
|
+
return this.#isSpinning;
|
|
962
976
|
}
|
|
963
977
|
|
|
964
978
|
get text() {
|
|
@@ -1130,10 +1144,15 @@ var MastraLogger = class {
|
|
|
1130
1144
|
}
|
|
1131
1145
|
};
|
|
1132
1146
|
|
|
1133
|
-
var PinoLogger = class extends MastraLogger {
|
|
1147
|
+
var PinoLogger = class _PinoLogger extends MastraLogger {
|
|
1134
1148
|
logger;
|
|
1135
1149
|
constructor(options = {}) {
|
|
1136
1150
|
super(options);
|
|
1151
|
+
const internalOptions = options;
|
|
1152
|
+
if (internalOptions._logger) {
|
|
1153
|
+
this.logger = internalOptions._logger;
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1137
1156
|
let prettyStream = void 0;
|
|
1138
1157
|
if (!options.overrideDefaultTransports) {
|
|
1139
1158
|
prettyStream = pretty({
|
|
@@ -1150,7 +1169,8 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1150
1169
|
{
|
|
1151
1170
|
name: options.name || "app",
|
|
1152
1171
|
level: options.level || LogLevel.INFO,
|
|
1153
|
-
formatters: options.formatters
|
|
1172
|
+
formatters: options.formatters,
|
|
1173
|
+
redact: options.redact
|
|
1154
1174
|
},
|
|
1155
1175
|
options.overrideDefaultTransports ? options?.transports?.default : transportsAry.length === 0 ? prettyStream : pino.multistream([
|
|
1156
1176
|
...transportsAry.map(([, transport]) => ({
|
|
@@ -1164,6 +1184,38 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1164
1184
|
])
|
|
1165
1185
|
);
|
|
1166
1186
|
}
|
|
1187
|
+
/**
|
|
1188
|
+
* Creates a child logger with additional bound context.
|
|
1189
|
+
* All logs from the child logger will include the bound context.
|
|
1190
|
+
*
|
|
1191
|
+
* @param bindings - Key-value pairs to include in all logs from this child logger
|
|
1192
|
+
* @returns A new PinoLogger instance with the bound context
|
|
1193
|
+
*
|
|
1194
|
+
* @example
|
|
1195
|
+
* ```typescript
|
|
1196
|
+
* const baseLogger = new PinoLogger({ name: 'MyApp' });
|
|
1197
|
+
*
|
|
1198
|
+
* // Create module-scoped logger
|
|
1199
|
+
* const serviceLogger = baseLogger.child({ module: 'UserService' });
|
|
1200
|
+
* serviceLogger.info('User created', { userId: '123' });
|
|
1201
|
+
* // Output includes: { module: 'UserService', userId: '123', msg: 'User created' }
|
|
1202
|
+
*
|
|
1203
|
+
* // Create request-scoped logger
|
|
1204
|
+
* const requestLogger = baseLogger.child({ requestId: req.id });
|
|
1205
|
+
* requestLogger.error('Request failed', { err: error });
|
|
1206
|
+
* // Output includes: { requestId: 'abc', msg: 'Request failed', err: {...} }
|
|
1207
|
+
* ```
|
|
1208
|
+
*/
|
|
1209
|
+
child(bindings) {
|
|
1210
|
+
const childPino = this.logger.child(bindings);
|
|
1211
|
+
const childOptions = {
|
|
1212
|
+
name: this.name,
|
|
1213
|
+
level: this.level,
|
|
1214
|
+
transports: Object.fromEntries(this.transports),
|
|
1215
|
+
_logger: childPino
|
|
1216
|
+
};
|
|
1217
|
+
return new _PinoLogger(childOptions);
|
|
1218
|
+
}
|
|
1167
1219
|
debug(message, args = {}) {
|
|
1168
1220
|
this.logger.debug(args, message);
|
|
1169
1221
|
}
|
|
@@ -1178,118 +1230,8 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1178
1230
|
}
|
|
1179
1231
|
};
|
|
1180
1232
|
|
|
1181
|
-
var
|
|
1182
|
-
|
|
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
|
-
}
|
|
1233
|
+
var package_default = {
|
|
1234
|
+
version: "1.0.0-beta.10"};
|
|
1293
1235
|
function getPackageManagerAddCommand(pm) {
|
|
1294
1236
|
switch (pm) {
|
|
1295
1237
|
case "npm":
|
|
@@ -1312,11 +1254,11 @@ var DepsService = class {
|
|
|
1312
1254
|
findLockFile(dir) {
|
|
1313
1255
|
const lockFiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lock"];
|
|
1314
1256
|
for (const file of lockFiles) {
|
|
1315
|
-
if (fs3__default__default.existsSync(
|
|
1257
|
+
if (fs3__default__default.existsSync(path3.join(dir, file))) {
|
|
1316
1258
|
return file;
|
|
1317
1259
|
}
|
|
1318
1260
|
}
|
|
1319
|
-
const parentDir =
|
|
1261
|
+
const parentDir = path3.resolve(dir, "..");
|
|
1320
1262
|
if (parentDir !== dir) {
|
|
1321
1263
|
return this.findLockFile(parentDir);
|
|
1322
1264
|
}
|
|
@@ -1349,7 +1291,7 @@ var DepsService = class {
|
|
|
1349
1291
|
}
|
|
1350
1292
|
async checkDependencies(dependencies) {
|
|
1351
1293
|
try {
|
|
1352
|
-
const packageJsonPath =
|
|
1294
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1353
1295
|
try {
|
|
1354
1296
|
await fs4.access(packageJsonPath);
|
|
1355
1297
|
} catch {
|
|
@@ -1369,7 +1311,7 @@ var DepsService = class {
|
|
|
1369
1311
|
}
|
|
1370
1312
|
async getProjectName() {
|
|
1371
1313
|
try {
|
|
1372
|
-
const packageJsonPath =
|
|
1314
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1373
1315
|
const packageJson = await fs4.readFile(packageJsonPath, "utf-8");
|
|
1374
1316
|
const pkg = JSON.parse(packageJson);
|
|
1375
1317
|
return pkg.name;
|
|
@@ -1457,8 +1399,8 @@ var FileService = class {
|
|
|
1457
1399
|
*/
|
|
1458
1400
|
async copyStarterFile(inputFile, outputFilePath, replaceIfExists) {
|
|
1459
1401
|
const __filename = fileURLToPath(import.meta.url);
|
|
1460
|
-
const __dirname =
|
|
1461
|
-
const filePath =
|
|
1402
|
+
const __dirname = path3.dirname(__filename);
|
|
1403
|
+
const filePath = path3.resolve(__dirname, "starter-files", inputFile);
|
|
1462
1404
|
const fileString = fs3__default__default.readFileSync(filePath, "utf8");
|
|
1463
1405
|
if (fs3__default__default.existsSync(outputFilePath) && !replaceIfExists) {
|
|
1464
1406
|
console.info(`${outputFilePath} already exists`);
|
|
@@ -1468,7 +1410,7 @@ var FileService = class {
|
|
|
1468
1410
|
return true;
|
|
1469
1411
|
}
|
|
1470
1412
|
async setupEnvFile({ dbUrl }) {
|
|
1471
|
-
const envPath =
|
|
1413
|
+
const envPath = path3.join(process.cwd(), ".env.development");
|
|
1472
1414
|
await fsExtra.ensureFile(envPath);
|
|
1473
1415
|
const fileEnvService = new FileEnvService(envPath);
|
|
1474
1416
|
await fileEnvService.setEnvValue("DB_URL", dbUrl);
|
|
@@ -1492,21 +1434,142 @@ var FileService = class {
|
|
|
1492
1434
|
fs3__default__default.writeFileSync(filePath, fileContent);
|
|
1493
1435
|
}
|
|
1494
1436
|
};
|
|
1437
|
+
var createArgs = (versionTag) => {
|
|
1438
|
+
const packageName = versionTag ? `@mastra/mcp-docs-server@${versionTag}` : "@mastra/mcp-docs-server";
|
|
1439
|
+
return ["-y", packageName];
|
|
1440
|
+
};
|
|
1441
|
+
var createMcpConfig = (editor, versionTag) => {
|
|
1442
|
+
const args = createArgs(versionTag);
|
|
1443
|
+
if (editor === "vscode") {
|
|
1444
|
+
return {
|
|
1445
|
+
servers: {
|
|
1446
|
+
mastra: process.platform === `win32` ? {
|
|
1447
|
+
command: "cmd",
|
|
1448
|
+
args: ["/c", "npx", ...args],
|
|
1449
|
+
type: "stdio"
|
|
1450
|
+
} : {
|
|
1451
|
+
command: "npx",
|
|
1452
|
+
args,
|
|
1453
|
+
type: "stdio"
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
};
|
|
1457
|
+
}
|
|
1458
|
+
return {
|
|
1459
|
+
mcpServers: {
|
|
1460
|
+
mastra: {
|
|
1461
|
+
command: "npx",
|
|
1462
|
+
args
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
};
|
|
1466
|
+
};
|
|
1467
|
+
function makeConfig(original, editor, versionTag) {
|
|
1468
|
+
if (editor === "vscode") {
|
|
1469
|
+
return {
|
|
1470
|
+
...original,
|
|
1471
|
+
servers: {
|
|
1472
|
+
...original?.servers || {},
|
|
1473
|
+
...createMcpConfig(editor, versionTag).servers
|
|
1474
|
+
}
|
|
1475
|
+
};
|
|
1476
|
+
}
|
|
1477
|
+
return {
|
|
1478
|
+
...original,
|
|
1479
|
+
mcpServers: {
|
|
1480
|
+
...original?.mcpServers || {},
|
|
1481
|
+
...createMcpConfig(editor, versionTag).mcpServers
|
|
1482
|
+
}
|
|
1483
|
+
};
|
|
1484
|
+
}
|
|
1485
|
+
async function writeMergedConfig(configPath, editor, versionTag) {
|
|
1486
|
+
const configExists = existsSync(configPath);
|
|
1487
|
+
const config = makeConfig(configExists ? await readJSON(configPath) : {}, editor, versionTag);
|
|
1488
|
+
await ensureFile(configPath);
|
|
1489
|
+
await writeJSON(configPath, config, {
|
|
1490
|
+
spaces: 2
|
|
1491
|
+
});
|
|
1492
|
+
}
|
|
1493
|
+
var windsurfGlobalMCPConfigPath = path3.join(os.homedir(), ".codeium", "windsurf", "mcp_config.json");
|
|
1494
|
+
var cursorGlobalMCPConfigPath = path3.join(os.homedir(), ".cursor", "mcp.json");
|
|
1495
|
+
path3.join(process.cwd(), ".vscode", "mcp.json");
|
|
1496
|
+
var vscodeGlobalMCPConfigPath = path3.join(
|
|
1497
|
+
os.homedir(),
|
|
1498
|
+
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")
|
|
1499
|
+
);
|
|
1500
|
+
async function installMastraDocsMCPServer({
|
|
1501
|
+
editor,
|
|
1502
|
+
directory,
|
|
1503
|
+
versionTag
|
|
1504
|
+
}) {
|
|
1505
|
+
if (editor === `cursor`) {
|
|
1506
|
+
await writeMergedConfig(path3.join(directory, ".cursor", "mcp.json"), "cursor", versionTag);
|
|
1507
|
+
}
|
|
1508
|
+
if (editor === `vscode`) {
|
|
1509
|
+
await writeMergedConfig(path3.join(directory, ".vscode", "mcp.json"), "vscode", versionTag);
|
|
1510
|
+
}
|
|
1511
|
+
if (editor === `cursor-global`) {
|
|
1512
|
+
const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor, versionTag);
|
|
1513
|
+
if (alreadyInstalled) {
|
|
1514
|
+
return;
|
|
1515
|
+
}
|
|
1516
|
+
await writeMergedConfig(cursorGlobalMCPConfigPath, "cursor-global", versionTag);
|
|
1517
|
+
}
|
|
1518
|
+
if (editor === `windsurf`) {
|
|
1519
|
+
const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor, versionTag);
|
|
1520
|
+
if (alreadyInstalled) {
|
|
1521
|
+
return;
|
|
1522
|
+
}
|
|
1523
|
+
await writeMergedConfig(windsurfGlobalMCPConfigPath, editor, versionTag);
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
async function globalMCPIsAlreadyInstalled(editor, versionTag) {
|
|
1527
|
+
let configPath = ``;
|
|
1528
|
+
if (editor === "windsurf") {
|
|
1529
|
+
configPath = windsurfGlobalMCPConfigPath;
|
|
1530
|
+
} else if (editor === "cursor-global") {
|
|
1531
|
+
configPath = cursorGlobalMCPConfigPath;
|
|
1532
|
+
} else if (editor === "vscode") {
|
|
1533
|
+
configPath = vscodeGlobalMCPConfigPath;
|
|
1534
|
+
}
|
|
1535
|
+
if (!configPath || !existsSync(configPath)) {
|
|
1536
|
+
return false;
|
|
1537
|
+
}
|
|
1538
|
+
try {
|
|
1539
|
+
const configContents = await readJSON(configPath);
|
|
1540
|
+
if (!configContents) return false;
|
|
1541
|
+
const expectedPackage = versionTag ? `@mastra/mcp-docs-server@${versionTag}` : "@mastra/mcp-docs-server";
|
|
1542
|
+
if (editor === "vscode") {
|
|
1543
|
+
if (!configContents.servers) return false;
|
|
1544
|
+
const hasMastraMCP2 = Object.values(configContents.servers).some(
|
|
1545
|
+
(server) => server?.args?.find((arg) => arg === expectedPackage)
|
|
1546
|
+
);
|
|
1547
|
+
return hasMastraMCP2;
|
|
1548
|
+
}
|
|
1549
|
+
if (!configContents?.mcpServers) return false;
|
|
1550
|
+
const hasMastraMCP = Object.values(configContents.mcpServers).some(
|
|
1551
|
+
(server) => server?.args?.find((arg) => arg === expectedPackage)
|
|
1552
|
+
);
|
|
1553
|
+
return hasMastraMCP;
|
|
1554
|
+
} catch {
|
|
1555
|
+
return false;
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1495
1558
|
var exec = util.promisify(child_process.exec);
|
|
1496
1559
|
var getModelIdentifier = (llmProvider) => {
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
return `'anthropic/claude-sonnet-4-5-20250929'`;
|
|
1560
|
+
let model = "openai/gpt-4o";
|
|
1561
|
+
if (llmProvider === "anthropic") {
|
|
1562
|
+
model = "anthropic/claude-sonnet-4-5";
|
|
1501
1563
|
} else if (llmProvider === "groq") {
|
|
1502
|
-
|
|
1564
|
+
model = "groq/llama-3.3-70b-versatile";
|
|
1503
1565
|
} else if (llmProvider === "google") {
|
|
1504
|
-
|
|
1566
|
+
model = "google/gemini-2.5-pro";
|
|
1505
1567
|
} else if (llmProvider === "cerebras") {
|
|
1506
|
-
|
|
1568
|
+
model = "cerebras/llama-3.3-70b";
|
|
1507
1569
|
} else if (llmProvider === "mistral") {
|
|
1508
|
-
|
|
1570
|
+
model = "mistral/mistral-medium-2508";
|
|
1509
1571
|
}
|
|
1572
|
+
return model;
|
|
1510
1573
|
};
|
|
1511
1574
|
async function writeAgentSample(llmProvider, destPath, addExampleTool, addScorers) {
|
|
1512
1575
|
const modelString = getModelIdentifier(llmProvider);
|
|
@@ -1535,7 +1598,7 @@ export const weatherAgent = new Agent({
|
|
|
1535
1598
|
id: 'weather-agent',
|
|
1536
1599
|
name: 'Weather Agent',
|
|
1537
1600
|
instructions: \`${instructions}\`,
|
|
1538
|
-
model: ${modelString},
|
|
1601
|
+
model: '${modelString}',
|
|
1539
1602
|
${addExampleTool ? "tools: { weatherTool }," : ""}
|
|
1540
1603
|
${addScorers ? `scorers: {
|
|
1541
1604
|
toolCallAppropriateness: {
|
|
@@ -1794,7 +1857,7 @@ export const translationScorer = createScorer({
|
|
|
1794
1857
|
description: 'Checks that non-English location names are translated and used correctly',
|
|
1795
1858
|
type: 'agent',
|
|
1796
1859
|
judge: {
|
|
1797
|
-
model: ${modelString},
|
|
1860
|
+
model: '${modelString}',
|
|
1798
1861
|
instructions:
|
|
1799
1862
|
'You are an expert evaluator of translation quality for geographic locations. ' +
|
|
1800
1863
|
'Determine whether the user text mentions a non-English location and whether the assistant correctly uses an English translation of that location. ' +
|
|
@@ -1891,7 +1954,7 @@ var writeIndexFile = async ({
|
|
|
1891
1954
|
addScorers
|
|
1892
1955
|
}) => {
|
|
1893
1956
|
const indexPath = dirPath + "/index.ts";
|
|
1894
|
-
const destPath =
|
|
1957
|
+
const destPath = path3.join(indexPath);
|
|
1895
1958
|
try {
|
|
1896
1959
|
await fs4.writeFile(destPath, "");
|
|
1897
1960
|
const filteredExports = [
|
|
@@ -1974,7 +2037,7 @@ var writeAPIKey = async ({ provider, apiKey }) => {
|
|
|
1974
2037
|
};
|
|
1975
2038
|
var createMastraDir = async (directory) => {
|
|
1976
2039
|
let dir = directory.trim().split("/").filter((item) => item !== "");
|
|
1977
|
-
const dirPath =
|
|
2040
|
+
const dirPath = path3.join(process.cwd(), ...dir, "mastra");
|
|
1978
2041
|
try {
|
|
1979
2042
|
await fs4.access(dirPath);
|
|
1980
2043
|
return { ok: false };
|
|
@@ -1999,8 +2062,8 @@ var LLM_PROVIDERS = [
|
|
|
1999
2062
|
{ value: "cerebras", label: "Cerebras" },
|
|
2000
2063
|
{ value: "mistral", label: "Mistral" }
|
|
2001
2064
|
];
|
|
2002
|
-
var interactivePrompt = async (
|
|
2003
|
-
const { skip = {}, options: { showBanner = true } = {} } =
|
|
2065
|
+
var interactivePrompt = async (args = {}) => {
|
|
2066
|
+
const { skip = {}, options: { showBanner = true } = {} } = args;
|
|
2004
2067
|
if (showBanner) {
|
|
2005
2068
|
Ie(color2.inverse(" Mastra Init "));
|
|
2006
2069
|
}
|
|
@@ -2038,46 +2101,29 @@ var interactivePrompt = async (args2 = {}) => {
|
|
|
2038
2101
|
return void 0;
|
|
2039
2102
|
},
|
|
2040
2103
|
configureEditorWithDocsMCP: async () => {
|
|
2041
|
-
const windsurfIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`windsurf`);
|
|
2042
|
-
const cursorIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`cursor`);
|
|
2043
|
-
const vscodeIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`vscode`);
|
|
2044
2104
|
const editor = await ve({
|
|
2045
2105
|
message: `Make your IDE into a Mastra expert? (Installs Mastra's MCP server)`,
|
|
2046
2106
|
options: [
|
|
2047
2107
|
{ value: "skip", label: "Skip for now", hint: "default" },
|
|
2048
2108
|
{
|
|
2049
2109
|
value: "cursor",
|
|
2050
|
-
label: "Cursor (project only)"
|
|
2051
|
-
hint: cursorIsAlreadyInstalled ? `Already installed globally` : void 0
|
|
2110
|
+
label: "Cursor (project only)"
|
|
2052
2111
|
},
|
|
2053
2112
|
{
|
|
2054
2113
|
value: "cursor-global",
|
|
2055
|
-
label: "Cursor (global, all projects)"
|
|
2056
|
-
hint: cursorIsAlreadyInstalled ? `Already installed` : void 0
|
|
2114
|
+
label: "Cursor (global, all projects)"
|
|
2057
2115
|
},
|
|
2058
2116
|
{
|
|
2059
2117
|
value: "windsurf",
|
|
2060
|
-
label: "Windsurf"
|
|
2061
|
-
hint: windsurfIsAlreadyInstalled ? `Already installed` : void 0
|
|
2118
|
+
label: "Windsurf"
|
|
2062
2119
|
},
|
|
2063
2120
|
{
|
|
2064
2121
|
value: "vscode",
|
|
2065
|
-
label: "VSCode"
|
|
2066
|
-
hint: vscodeIsAlreadyInstalled ? `Already installed` : void 0
|
|
2122
|
+
label: "VSCode"
|
|
2067
2123
|
}
|
|
2068
2124
|
]
|
|
2069
2125
|
});
|
|
2070
2126
|
if (editor === `skip`) return void 0;
|
|
2071
|
-
if (editor === `windsurf` && windsurfIsAlreadyInstalled) {
|
|
2072
|
-
M.message(`
|
|
2073
|
-
Windsurf is already installed, skipping.`);
|
|
2074
|
-
return void 0;
|
|
2075
|
-
}
|
|
2076
|
-
if (editor === `vscode` && vscodeIsAlreadyInstalled) {
|
|
2077
|
-
M.message(`
|
|
2078
|
-
VSCode is already installed, skipping.`);
|
|
2079
|
-
return void 0;
|
|
2080
|
-
}
|
|
2081
2127
|
if (editor === `cursor`) {
|
|
2082
2128
|
M.message(
|
|
2083
2129
|
`
|
|
@@ -2086,19 +2132,19 @@ Note: you will need to go into Cursor Settings -> MCP Settings and manually enab
|
|
|
2086
2132
|
);
|
|
2087
2133
|
}
|
|
2088
2134
|
if (editor === `cursor-global`) {
|
|
2089
|
-
const
|
|
2135
|
+
const confirm3 = await ve({
|
|
2090
2136
|
message: `Global install will add/update ${cursorGlobalMCPConfigPath} and make the Mastra docs MCP server available in all your Cursor projects. Continue?`,
|
|
2091
2137
|
options: [
|
|
2092
2138
|
{ value: "yes", label: "Yes, I understand" },
|
|
2093
2139
|
{ value: "skip", label: "No, skip for now" }
|
|
2094
2140
|
]
|
|
2095
2141
|
});
|
|
2096
|
-
if (
|
|
2142
|
+
if (confirm3 !== `yes`) {
|
|
2097
2143
|
return void 0;
|
|
2098
2144
|
}
|
|
2099
2145
|
}
|
|
2100
2146
|
if (editor === `windsurf`) {
|
|
2101
|
-
const
|
|
2147
|
+
const confirm3 = await ve({
|
|
2102
2148
|
message: `Windsurf only supports a global MCP config (at ${windsurfGlobalMCPConfigPath}) is it ok to add/update that global config?
|
|
2103
2149
|
This means the Mastra docs MCP server will be available in all your Windsurf projects.`,
|
|
2104
2150
|
options: [
|
|
@@ -2106,11 +2152,17 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
2106
2152
|
{ value: "skip", label: "No, skip for now" }
|
|
2107
2153
|
]
|
|
2108
2154
|
});
|
|
2109
|
-
if (
|
|
2155
|
+
if (confirm3 !== `yes`) {
|
|
2110
2156
|
return void 0;
|
|
2111
2157
|
}
|
|
2112
2158
|
}
|
|
2113
2159
|
return editor;
|
|
2160
|
+
},
|
|
2161
|
+
initGit: async () => {
|
|
2162
|
+
return ye({
|
|
2163
|
+
message: "Initialize a new git repository?",
|
|
2164
|
+
initialValue: true
|
|
2165
|
+
});
|
|
2114
2166
|
}
|
|
2115
2167
|
},
|
|
2116
2168
|
{
|
|
@@ -2125,6 +2177,9 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
2125
2177
|
function getPackageManager() {
|
|
2126
2178
|
const userAgent = process.env.npm_config_user_agent || "";
|
|
2127
2179
|
const execPath = process.env.npm_execpath || "";
|
|
2180
|
+
if (userAgent.includes("bun")) {
|
|
2181
|
+
return "bun";
|
|
2182
|
+
}
|
|
2128
2183
|
if (userAgent.includes("yarn")) {
|
|
2129
2184
|
return "yarn";
|
|
2130
2185
|
}
|
|
@@ -2134,6 +2189,9 @@ function getPackageManager() {
|
|
|
2134
2189
|
if (userAgent.includes("npm")) {
|
|
2135
2190
|
return "npm";
|
|
2136
2191
|
}
|
|
2192
|
+
if (execPath.includes("bun")) {
|
|
2193
|
+
return "bun";
|
|
2194
|
+
}
|
|
2137
2195
|
if (execPath.includes("yarn")) {
|
|
2138
2196
|
return "yarn";
|
|
2139
2197
|
}
|
|
@@ -2145,6 +2203,20 @@ function getPackageManager() {
|
|
|
2145
2203
|
}
|
|
2146
2204
|
return "npm";
|
|
2147
2205
|
}
|
|
2206
|
+
async function gitInit({ cwd }) {
|
|
2207
|
+
await execa("git", ["init"], { cwd, stdio: "ignore" });
|
|
2208
|
+
await execa("git", ["add", "-A"], { cwd, stdio: "ignore" });
|
|
2209
|
+
await execa(
|
|
2210
|
+
"git",
|
|
2211
|
+
[
|
|
2212
|
+
"commit",
|
|
2213
|
+
"-m",
|
|
2214
|
+
'"Initial commit from Mastra"',
|
|
2215
|
+
'--author="dane-ai-mastra[bot] <dane-ai-mastra[bot]@users.noreply.github.com>"'
|
|
2216
|
+
],
|
|
2217
|
+
{ cwd, stdio: "ignore" }
|
|
2218
|
+
);
|
|
2219
|
+
}
|
|
2148
2220
|
var logger = createLogger(false);
|
|
2149
2221
|
function createLogger(debug = false) {
|
|
2150
2222
|
return new PinoLogger({
|
|
@@ -2154,19 +2226,23 @@ function createLogger(debug = false) {
|
|
|
2154
2226
|
}
|
|
2155
2227
|
var exec2 = util.promisify(child_process.exec);
|
|
2156
2228
|
async function cloneTemplate(options) {
|
|
2157
|
-
const { template, projectName, targetDir } = options;
|
|
2158
|
-
const projectPath = targetDir ?
|
|
2229
|
+
const { template, projectName, targetDir, branch, llmProvider } = options;
|
|
2230
|
+
const projectPath = targetDir ? path3.resolve(targetDir, projectName) : path3.resolve(projectName);
|
|
2159
2231
|
const spinner4 = yoctoSpinner({ text: `Cloning template "${template.title}"...` }).start();
|
|
2160
2232
|
try {
|
|
2161
2233
|
if (await directoryExists(projectPath)) {
|
|
2162
2234
|
spinner4.error(`Directory ${projectName} already exists`);
|
|
2163
2235
|
throw new Error(`Directory ${projectName} already exists`);
|
|
2164
2236
|
}
|
|
2165
|
-
await cloneRepositoryWithoutGit(template.githubUrl, projectPath);
|
|
2237
|
+
await cloneRepositoryWithoutGit(template.githubUrl, projectPath, branch);
|
|
2166
2238
|
await updatePackageJson(projectPath, projectName);
|
|
2167
|
-
const envExamplePath =
|
|
2239
|
+
const envExamplePath = path3.join(projectPath, ".env.example");
|
|
2168
2240
|
if (await fileExists(envExamplePath)) {
|
|
2169
|
-
|
|
2241
|
+
const envPath = path3.join(projectPath, ".env");
|
|
2242
|
+
await fs4.copyFile(envExamplePath, envPath);
|
|
2243
|
+
if (llmProvider) {
|
|
2244
|
+
await updateEnvFile(envPath, llmProvider);
|
|
2245
|
+
}
|
|
2170
2246
|
}
|
|
2171
2247
|
spinner4.success(`Template "${template.title}" cloned successfully to ${projectName}`);
|
|
2172
2248
|
return projectPath;
|
|
@@ -2191,21 +2267,27 @@ async function fileExists(filePath) {
|
|
|
2191
2267
|
return false;
|
|
2192
2268
|
}
|
|
2193
2269
|
}
|
|
2194
|
-
async function cloneRepositoryWithoutGit(repoUrl, targetPath) {
|
|
2270
|
+
async function cloneRepositoryWithoutGit(repoUrl, targetPath, branch) {
|
|
2195
2271
|
await fs4.mkdir(targetPath, { recursive: true });
|
|
2196
2272
|
try {
|
|
2197
2273
|
const degitRepo = repoUrl.replace("https://github.com/", "");
|
|
2198
|
-
const
|
|
2274
|
+
const degitRepoWithBranch = branch ? `${degitRepo}#${branch}` : degitRepo;
|
|
2275
|
+
const degitCommand = shellQuote2.quote(["npx", "degit", degitRepoWithBranch, targetPath]);
|
|
2199
2276
|
await exec2(degitCommand, {
|
|
2200
2277
|
cwd: process.cwd()
|
|
2201
2278
|
});
|
|
2202
2279
|
} catch {
|
|
2203
2280
|
try {
|
|
2204
|
-
const
|
|
2281
|
+
const gitArgs = ["git", "clone"];
|
|
2282
|
+
if (branch) {
|
|
2283
|
+
gitArgs.push("--branch", branch);
|
|
2284
|
+
}
|
|
2285
|
+
gitArgs.push(repoUrl, targetPath);
|
|
2286
|
+
const gitCommand = shellQuote2.quote(gitArgs);
|
|
2205
2287
|
await exec2(gitCommand, {
|
|
2206
2288
|
cwd: process.cwd()
|
|
2207
2289
|
});
|
|
2208
|
-
const gitDir =
|
|
2290
|
+
const gitDir = path3.join(targetPath, ".git");
|
|
2209
2291
|
if (await directoryExists(gitDir)) {
|
|
2210
2292
|
await fs4.rm(gitDir, { recursive: true, force: true });
|
|
2211
2293
|
}
|
|
@@ -2215,7 +2297,7 @@ async function cloneRepositoryWithoutGit(repoUrl, targetPath) {
|
|
|
2215
2297
|
}
|
|
2216
2298
|
}
|
|
2217
2299
|
async function updatePackageJson(projectPath, projectName) {
|
|
2218
|
-
const packageJsonPath =
|
|
2300
|
+
const packageJsonPath = path3.join(projectPath, "package.json");
|
|
2219
2301
|
try {
|
|
2220
2302
|
const packageJsonContent = await fs4.readFile(packageJsonPath, "utf-8");
|
|
2221
2303
|
const packageJson = JSON.parse(packageJsonContent);
|
|
@@ -2225,6 +2307,22 @@ async function updatePackageJson(projectPath, projectName) {
|
|
|
2225
2307
|
logger.warn(`Could not update package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2226
2308
|
}
|
|
2227
2309
|
}
|
|
2310
|
+
async function updateEnvFile(envPath, llmProvider) {
|
|
2311
|
+
try {
|
|
2312
|
+
const envContent = await fs4.readFile(envPath, "utf-8");
|
|
2313
|
+
const modelString = getModelIdentifier(llmProvider);
|
|
2314
|
+
if (!modelString) {
|
|
2315
|
+
logger.warn(`Could not get model identifier for provider: ${llmProvider}`);
|
|
2316
|
+
return;
|
|
2317
|
+
}
|
|
2318
|
+
const modelValue = modelString.replace(/'/g, "");
|
|
2319
|
+
const updatedContent = envContent.replace(/^MODEL=.*/m, `MODEL=${modelValue}`);
|
|
2320
|
+
await fs4.writeFile(envPath, updatedContent, "utf-8");
|
|
2321
|
+
logger.info(`Updated MODEL in .env to ${modelValue}`);
|
|
2322
|
+
} catch (error) {
|
|
2323
|
+
logger.warn(`Could not update .env file: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2228
2326
|
async function installDependencies(projectPath, packageManager) {
|
|
2229
2327
|
const spinner4 = yoctoSpinner({ text: "Installing dependencies..." }).start();
|
|
2230
2328
|
try {
|
|
@@ -2310,7 +2408,8 @@ var init = async ({
|
|
|
2310
2408
|
llmApiKey,
|
|
2311
2409
|
addExample = false,
|
|
2312
2410
|
configureEditorWithDocsMCP,
|
|
2313
|
-
versionTag
|
|
2411
|
+
versionTag,
|
|
2412
|
+
initGit = false
|
|
2314
2413
|
}) => {
|
|
2315
2414
|
s.start("Initializing Mastra");
|
|
2316
2415
|
const packageVersionTag = versionTag ? `@${versionTag}` : "";
|
|
@@ -2364,10 +2463,21 @@ var init = async ({
|
|
|
2364
2463
|
if (configureEditorWithDocsMCP) {
|
|
2365
2464
|
await installMastraDocsMCPServer({
|
|
2366
2465
|
editor: configureEditorWithDocsMCP,
|
|
2367
|
-
directory: process.cwd()
|
|
2466
|
+
directory: process.cwd(),
|
|
2467
|
+
versionTag
|
|
2368
2468
|
});
|
|
2369
2469
|
}
|
|
2370
2470
|
s.stop();
|
|
2471
|
+
if (initGit) {
|
|
2472
|
+
const s2 = Y();
|
|
2473
|
+
try {
|
|
2474
|
+
s2.start("Initializing git repository");
|
|
2475
|
+
await gitInit({ cwd: process.cwd() });
|
|
2476
|
+
s2.stop("Git repository initialized");
|
|
2477
|
+
} catch {
|
|
2478
|
+
s2.stop();
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2371
2481
|
if (!llmApiKey) {
|
|
2372
2482
|
Me(`
|
|
2373
2483
|
${color2.green("Mastra initialized successfully!")}
|
|
@@ -2413,6 +2523,32 @@ var execWithTimeout = async (command, timeoutMs) => {
|
|
|
2413
2523
|
throw error;
|
|
2414
2524
|
}
|
|
2415
2525
|
};
|
|
2526
|
+
async function getInitCommand(pm) {
|
|
2527
|
+
switch (pm) {
|
|
2528
|
+
case "npm":
|
|
2529
|
+
return "npm init -y";
|
|
2530
|
+
case "pnpm":
|
|
2531
|
+
return "pnpm init";
|
|
2532
|
+
case "yarn":
|
|
2533
|
+
return "yarn init -y";
|
|
2534
|
+
case "bun":
|
|
2535
|
+
return "bun init -y";
|
|
2536
|
+
default:
|
|
2537
|
+
return "npm init -y";
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
async function initializePackageJson(pm) {
|
|
2541
|
+
const initCommand = await getInitCommand(pm);
|
|
2542
|
+
await exec3(initCommand);
|
|
2543
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
2544
|
+
const packageJson = JSON.parse(await fs4.readFile(packageJsonPath, "utf-8"));
|
|
2545
|
+
packageJson.type = "module";
|
|
2546
|
+
packageJson.engines = {
|
|
2547
|
+
...packageJson.engines,
|
|
2548
|
+
node: ">=22.13.0"
|
|
2549
|
+
};
|
|
2550
|
+
await fs4.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
2551
|
+
}
|
|
2416
2552
|
async function installMastraDependency(pm, dependency, versionTag, isDev, timeout) {
|
|
2417
2553
|
let installCommand = getPackageManagerAddCommand(pm);
|
|
2418
2554
|
if (isDev) {
|
|
@@ -2459,7 +2595,7 @@ var createMastraProject = async ({
|
|
|
2459
2595
|
xe("Operation cancelled");
|
|
2460
2596
|
process.exit(0);
|
|
2461
2597
|
}
|
|
2462
|
-
let result;
|
|
2598
|
+
let result = void 0;
|
|
2463
2599
|
if (needsInteractive) {
|
|
2464
2600
|
result = await interactivePrompt({
|
|
2465
2601
|
options: { showBanner: false },
|
|
@@ -2467,10 +2603,13 @@ var createMastraProject = async ({
|
|
|
2467
2603
|
});
|
|
2468
2604
|
}
|
|
2469
2605
|
const s2 = Y();
|
|
2606
|
+
const originalCwd = process.cwd();
|
|
2607
|
+
let projectPath = null;
|
|
2470
2608
|
try {
|
|
2471
2609
|
s2.start("Creating project");
|
|
2472
2610
|
try {
|
|
2473
2611
|
await fs4.mkdir(projectName);
|
|
2612
|
+
projectPath = path3.resolve(originalCwd, projectName);
|
|
2474
2613
|
} catch (error) {
|
|
2475
2614
|
if (error instanceof Error && "code" in error && error.code === "EEXIST") {
|
|
2476
2615
|
s2.stop(`A directory named "${projectName}" already exists. Please choose a different name.`);
|
|
@@ -2485,9 +2624,7 @@ var createMastraProject = async ({
|
|
|
2485
2624
|
const installCommand = getPackageManagerAddCommand(pm);
|
|
2486
2625
|
s2.message("Initializing project structure");
|
|
2487
2626
|
try {
|
|
2488
|
-
await
|
|
2489
|
-
await exec3(`npm pkg set type="module"`);
|
|
2490
|
-
await exec3(`npm pkg set engines.node=">=20.9.0"`);
|
|
2627
|
+
await initializePackageJson(pm);
|
|
2491
2628
|
const depsService = new DepsService();
|
|
2492
2629
|
await depsService.addScriptsToPackageJson({
|
|
2493
2630
|
dev: "mastra dev",
|
|
@@ -2566,44 +2703,61 @@ var createMastraProject = async ({
|
|
|
2566
2703
|
s2.stop();
|
|
2567
2704
|
const errorMessage = error instanceof Error ? error.message : "An unexpected error occurred";
|
|
2568
2705
|
xe(`Project creation failed: ${errorMessage}`);
|
|
2706
|
+
if (projectPath && fs3__default__default.existsSync(projectPath)) {
|
|
2707
|
+
try {
|
|
2708
|
+
process.chdir(originalCwd);
|
|
2709
|
+
await fs4.rm(projectPath, { recursive: true, force: true });
|
|
2710
|
+
} catch (cleanupError) {
|
|
2711
|
+
console.error(
|
|
2712
|
+
`Warning: Failed to clean up project directory: ${cleanupError instanceof Error ? cleanupError.message : "Unknown error"}`
|
|
2713
|
+
);
|
|
2714
|
+
}
|
|
2715
|
+
}
|
|
2569
2716
|
process.exit(1);
|
|
2570
2717
|
}
|
|
2571
2718
|
};
|
|
2572
|
-
var
|
|
2573
|
-
|
|
2574
|
-
|
|
2719
|
+
var version$1 = package_default.version;
|
|
2720
|
+
var create = async (args) => {
|
|
2721
|
+
if (args.template !== void 0) {
|
|
2722
|
+
await createFromTemplate({
|
|
2723
|
+
projectName: args.projectName,
|
|
2724
|
+
template: args.template,
|
|
2725
|
+
timeout: args.timeout,
|
|
2726
|
+
injectedAnalytics: args.analytics,
|
|
2727
|
+
llmProvider: args.llmProvider
|
|
2728
|
+
});
|
|
2575
2729
|
return;
|
|
2576
2730
|
}
|
|
2577
|
-
const needsInteractive =
|
|
2731
|
+
const needsInteractive = args.components === void 0 || args.llmProvider === void 0 || args.addExample === void 0;
|
|
2578
2732
|
const { projectName, result } = await createMastraProject({
|
|
2579
|
-
projectName:
|
|
2580
|
-
createVersionTag:
|
|
2581
|
-
timeout:
|
|
2582
|
-
llmProvider:
|
|
2583
|
-
llmApiKey:
|
|
2733
|
+
projectName: args?.projectName,
|
|
2734
|
+
createVersionTag: args?.createVersionTag,
|
|
2735
|
+
timeout: args?.timeout,
|
|
2736
|
+
llmProvider: args?.llmProvider,
|
|
2737
|
+
llmApiKey: args?.llmApiKey,
|
|
2584
2738
|
needsInteractive
|
|
2585
2739
|
});
|
|
2586
|
-
const directory =
|
|
2740
|
+
const directory = args.directory || "src/";
|
|
2587
2741
|
if (needsInteractive && result) {
|
|
2588
2742
|
await init({
|
|
2589
2743
|
...result,
|
|
2590
2744
|
llmApiKey: result?.llmApiKey,
|
|
2591
2745
|
components: ["agents", "tools", "workflows", "scorers"],
|
|
2592
2746
|
addExample: true,
|
|
2593
|
-
versionTag:
|
|
2747
|
+
versionTag: args.createVersionTag
|
|
2594
2748
|
});
|
|
2595
2749
|
postCreate({ projectName });
|
|
2596
2750
|
return;
|
|
2597
2751
|
}
|
|
2598
|
-
const { components = [], llmProvider = "openai", addExample = false, llmApiKey } =
|
|
2752
|
+
const { components = [], llmProvider = "openai", addExample = false, llmApiKey } = args;
|
|
2599
2753
|
await init({
|
|
2600
2754
|
directory,
|
|
2601
2755
|
components,
|
|
2602
2756
|
llmProvider,
|
|
2603
2757
|
addExample,
|
|
2604
2758
|
llmApiKey,
|
|
2605
|
-
configureEditorWithDocsMCP:
|
|
2606
|
-
versionTag:
|
|
2759
|
+
configureEditorWithDocsMCP: args.mcpServer,
|
|
2760
|
+
versionTag: args.createVersionTag
|
|
2607
2761
|
});
|
|
2608
2762
|
postCreate({ projectName });
|
|
2609
2763
|
};
|
|
@@ -2694,9 +2848,9 @@ async function createFromGitHubUrl(url) {
|
|
|
2694
2848
|
workflows: []
|
|
2695
2849
|
};
|
|
2696
2850
|
}
|
|
2697
|
-
async function createFromTemplate(
|
|
2851
|
+
async function createFromTemplate(args) {
|
|
2698
2852
|
let selectedTemplate;
|
|
2699
|
-
if (
|
|
2853
|
+
if (args.template === true) {
|
|
2700
2854
|
const templates = await loadTemplates();
|
|
2701
2855
|
const selected = await selectTemplate(templates);
|
|
2702
2856
|
if (!selected) {
|
|
@@ -2704,11 +2858,11 @@ async function createFromTemplate(args2) {
|
|
|
2704
2858
|
return;
|
|
2705
2859
|
}
|
|
2706
2860
|
selectedTemplate = selected;
|
|
2707
|
-
} else if (
|
|
2708
|
-
if (isGitHubUrl(
|
|
2861
|
+
} else if (args.template && typeof args.template === "string") {
|
|
2862
|
+
if (isGitHubUrl(args.template)) {
|
|
2709
2863
|
const spinner4 = Y();
|
|
2710
2864
|
spinner4.start("Validating GitHub repository...");
|
|
2711
|
-
const validation = await validateGitHubProject(
|
|
2865
|
+
const validation = await validateGitHubProject(args.template);
|
|
2712
2866
|
if (!validation.isValid) {
|
|
2713
2867
|
spinner4.stop("Validation failed");
|
|
2714
2868
|
M.error("This does not appear to be a valid Mastra project:");
|
|
@@ -2716,14 +2870,14 @@ async function createFromTemplate(args2) {
|
|
|
2716
2870
|
throw new Error("Invalid Mastra project");
|
|
2717
2871
|
}
|
|
2718
2872
|
spinner4.stop("Valid Mastra project \u2713");
|
|
2719
|
-
selectedTemplate = await createFromGitHubUrl(
|
|
2873
|
+
selectedTemplate = await createFromGitHubUrl(args.template);
|
|
2720
2874
|
} else {
|
|
2721
2875
|
const templates = await loadTemplates();
|
|
2722
|
-
const found = findTemplateByName(templates,
|
|
2876
|
+
const found = findTemplateByName(templates, args.template);
|
|
2723
2877
|
if (!found) {
|
|
2724
|
-
M.error(`Template "${
|
|
2878
|
+
M.error(`Template "${args.template}" not found. Available templates:`);
|
|
2725
2879
|
templates.forEach((t) => M.info(` - ${t.title} (use: ${t.slug.replace("template-", "")})`));
|
|
2726
|
-
throw new Error(`Template "${
|
|
2880
|
+
throw new Error(`Template "${args.template}" not found`);
|
|
2727
2881
|
}
|
|
2728
2882
|
selectedTemplate = found;
|
|
2729
2883
|
}
|
|
@@ -2731,7 +2885,7 @@ async function createFromTemplate(args2) {
|
|
|
2731
2885
|
if (!selectedTemplate) {
|
|
2732
2886
|
throw new Error("No template selected");
|
|
2733
2887
|
}
|
|
2734
|
-
let projectName =
|
|
2888
|
+
let projectName = args.projectName;
|
|
2735
2889
|
if (!projectName) {
|
|
2736
2890
|
const defaultName = getDefaultProjectName(selectedTemplate);
|
|
2737
2891
|
const response = await he({
|
|
@@ -2745,19 +2899,61 @@ async function createFromTemplate(args2) {
|
|
|
2745
2899
|
}
|
|
2746
2900
|
projectName = response;
|
|
2747
2901
|
}
|
|
2902
|
+
let llmProvider = args.llmProvider;
|
|
2903
|
+
if (!llmProvider) {
|
|
2904
|
+
const providerResponse = await ve({
|
|
2905
|
+
message: "Select a default provider:",
|
|
2906
|
+
options: LLM_PROVIDERS
|
|
2907
|
+
});
|
|
2908
|
+
if (pD(providerResponse)) {
|
|
2909
|
+
M.info("Project creation cancelled.");
|
|
2910
|
+
return;
|
|
2911
|
+
}
|
|
2912
|
+
llmProvider = providerResponse;
|
|
2913
|
+
}
|
|
2914
|
+
let initGit = false;
|
|
2915
|
+
const gitConfirmResult = await ye({
|
|
2916
|
+
message: "Initialize a new git repository?",
|
|
2917
|
+
initialValue: true
|
|
2918
|
+
});
|
|
2919
|
+
if (!pD(gitConfirmResult)) {
|
|
2920
|
+
initGit = gitConfirmResult;
|
|
2921
|
+
}
|
|
2922
|
+
let projectPath = null;
|
|
2748
2923
|
try {
|
|
2749
|
-
const analytics =
|
|
2924
|
+
const analytics = args.injectedAnalytics || getAnalytics();
|
|
2750
2925
|
if (analytics) {
|
|
2751
2926
|
analytics.trackEvent("cli_template_used", {
|
|
2752
2927
|
template_slug: selectedTemplate.slug,
|
|
2753
2928
|
template_title: selectedTemplate.title
|
|
2754
2929
|
});
|
|
2930
|
+
if (llmProvider) {
|
|
2931
|
+
analytics.trackEvent("cli_model_provider_selected", {
|
|
2932
|
+
provider: llmProvider,
|
|
2933
|
+
selection_method: args.llmProvider ? "cli_args" : "interactive"
|
|
2934
|
+
});
|
|
2935
|
+
}
|
|
2755
2936
|
}
|
|
2756
|
-
const
|
|
2937
|
+
const isBeta = version$1?.includes("beta") ?? false;
|
|
2938
|
+
const isMastraTemplate = selectedTemplate.githubUrl.includes("github.com/mastra-ai/");
|
|
2939
|
+
const branch = isBeta && isMastraTemplate ? "beta" : void 0;
|
|
2940
|
+
projectPath = await cloneTemplate({
|
|
2757
2941
|
template: selectedTemplate,
|
|
2758
|
-
projectName
|
|
2942
|
+
projectName,
|
|
2943
|
+
branch,
|
|
2944
|
+
llmProvider
|
|
2759
2945
|
});
|
|
2760
2946
|
await installDependencies(projectPath);
|
|
2947
|
+
if (initGit) {
|
|
2948
|
+
const s2 = Y();
|
|
2949
|
+
try {
|
|
2950
|
+
s2.start("Initializing git repository");
|
|
2951
|
+
await gitInit({ cwd: projectPath });
|
|
2952
|
+
s2.stop("Git repository initialized");
|
|
2953
|
+
} catch {
|
|
2954
|
+
s2.stop();
|
|
2955
|
+
}
|
|
2956
|
+
}
|
|
2761
2957
|
Me(`
|
|
2762
2958
|
${color2.green("Mastra template installed!")}
|
|
2763
2959
|
|
|
@@ -2766,6 +2962,17 @@ async function createFromTemplate(args2) {
|
|
|
2766
2962
|
`);
|
|
2767
2963
|
postCreate({ projectName });
|
|
2768
2964
|
} catch (error) {
|
|
2965
|
+
if (projectPath) {
|
|
2966
|
+
try {
|
|
2967
|
+
if (fs3__default__default.existsSync(projectPath)) {
|
|
2968
|
+
await fs4.rm(projectPath, { recursive: true, force: true });
|
|
2969
|
+
}
|
|
2970
|
+
} catch (cleanupError) {
|
|
2971
|
+
console.error(
|
|
2972
|
+
`Warning: Failed to clean up project directory: ${cleanupError instanceof Error ? cleanupError.message : "Unknown error"}`
|
|
2973
|
+
);
|
|
2974
|
+
}
|
|
2975
|
+
}
|
|
2769
2976
|
M.error(`Failed to create project from template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2770
2977
|
throw error;
|
|
2771
2978
|
}
|
|
@@ -2774,7 +2981,7 @@ async function createFromTemplate(args2) {
|
|
|
2774
2981
|
async function getPackageVersion() {
|
|
2775
2982
|
const __filename = fileURLToPath(import.meta.url);
|
|
2776
2983
|
const __dirname = dirname(__filename);
|
|
2777
|
-
const pkgJsonPath =
|
|
2984
|
+
const pkgJsonPath = path3.join(__dirname, "..", "package.json");
|
|
2778
2985
|
const content = await fsExtra$1.readJSON(pkgJsonPath);
|
|
2779
2986
|
return content.version;
|
|
2780
2987
|
}
|