create-mastra 0.0.0-sidebar-window-undefined-fix-20251029233656 → 0.0.0-standard-schema-20260123120255
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 +283 -1
- package/README.md +1 -1
- package/dist/index.js +539 -250
- package/dist/index.js.map +1 -1
- package/dist/starter-files/tools.ts +2 -2
- package/dist/templates/dev.entry.js +3 -46
- package/package.json +19 -20
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
|
-
var __filename = fileURLToPath(import.meta.url);
|
|
26
|
-
var __dirname =
|
|
25
|
+
var __filename$1 = fileURLToPath(import.meta.url);
|
|
26
|
+
var __dirname$1 = path3.dirname(__filename$1);
|
|
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$1, "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$1, "mastra-cli.json"), JSON.stringify({ distinctId, sessionId }));
|
|
71
71
|
} catch {
|
|
72
72
|
}
|
|
73
73
|
}
|
|
@@ -105,6 +105,10 @@ var PosthogAnalytics = class {
|
|
|
105
105
|
machine_id: os.hostname()
|
|
106
106
|
};
|
|
107
107
|
}
|
|
108
|
+
getDurationMs(startTime) {
|
|
109
|
+
const [seconds, nanoseconds] = process.hrtime(startTime);
|
|
110
|
+
return seconds * 1e3 + nanoseconds / 1e6;
|
|
111
|
+
}
|
|
108
112
|
captureSessionStart() {
|
|
109
113
|
if (!this.client) {
|
|
110
114
|
return;
|
|
@@ -173,8 +177,7 @@ var PosthogAnalytics = class {
|
|
|
173
177
|
const startTime = process.hrtime();
|
|
174
178
|
try {
|
|
175
179
|
const result = await execution();
|
|
176
|
-
const
|
|
177
|
-
const durationMs = seconds * 1e3 + nanoseconds / 1e6;
|
|
180
|
+
const durationMs = this.getDurationMs(startTime);
|
|
178
181
|
this.trackCommand({
|
|
179
182
|
command,
|
|
180
183
|
args,
|
|
@@ -184,8 +187,7 @@ var PosthogAnalytics = class {
|
|
|
184
187
|
});
|
|
185
188
|
return result;
|
|
186
189
|
} catch (error) {
|
|
187
|
-
const
|
|
188
|
-
const durationMs = seconds * 1e3 + nanoseconds / 1e6;
|
|
190
|
+
const durationMs = this.getDurationMs(startTime);
|
|
189
191
|
this.trackCommand({
|
|
190
192
|
command,
|
|
191
193
|
args,
|
|
@@ -382,7 +384,7 @@ function DD({onlyFirst:e=false}={}){const t=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:
|
|
|
382
384
|
`).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
385
|
`);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
386
|
`).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);});}}
|
|
387
|
+
`)),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
388
|
|
|
387
389
|
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
390
|
${b(this.state)} ${t.message}
|
|
@@ -392,7 +394,12 @@ ${color2.yellow(d)} ${color2.yellow(this.error)}
|
|
|
392
394
|
`;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
395
|
${color2.gray(o)}`:""}`;default:return `${n}${color2.cyan(o)} ${i}
|
|
394
396
|
${color2.cyan(d)}
|
|
395
|
-
`}}}).prompt(),
|
|
397
|
+
`}}}).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)}
|
|
398
|
+
${b(this.state)} ${t.message}
|
|
399
|
+
`,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))}
|
|
400
|
+
${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}`}
|
|
401
|
+
${color2.cyan(d)}
|
|
402
|
+
`}}}).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
403
|
${b(this.state)} ${t.message}
|
|
397
404
|
`;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
405
|
${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 +894,7 @@ class YoctoSpinner {
|
|
|
887
894
|
#exitHandlerBound;
|
|
888
895
|
#isInteractive;
|
|
889
896
|
#lastSpinnerFrameTime = 0;
|
|
897
|
+
#isSpinning = false;
|
|
890
898
|
|
|
891
899
|
constructor(options = {}) {
|
|
892
900
|
const spinner = options.spinner ?? defaultSpinner;
|
|
@@ -908,13 +916,17 @@ class YoctoSpinner {
|
|
|
908
916
|
return this;
|
|
909
917
|
}
|
|
910
918
|
|
|
919
|
+
this.#isSpinning = true;
|
|
911
920
|
this.#hideCursor();
|
|
912
921
|
this.#render();
|
|
913
922
|
this.#subscribeToProcessEvents();
|
|
914
923
|
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
924
|
+
// Only start the timer in interactive mode
|
|
925
|
+
if (this.#isInteractive) {
|
|
926
|
+
this.#timer = setInterval(() => {
|
|
927
|
+
this.#render();
|
|
928
|
+
}, this.#interval);
|
|
929
|
+
}
|
|
918
930
|
|
|
919
931
|
return this;
|
|
920
932
|
}
|
|
@@ -924,8 +936,12 @@ class YoctoSpinner {
|
|
|
924
936
|
return this;
|
|
925
937
|
}
|
|
926
938
|
|
|
927
|
-
|
|
928
|
-
this.#timer
|
|
939
|
+
this.#isSpinning = false;
|
|
940
|
+
if (this.#timer) {
|
|
941
|
+
clearInterval(this.#timer);
|
|
942
|
+
this.#timer = undefined;
|
|
943
|
+
}
|
|
944
|
+
|
|
929
945
|
this.#showCursor();
|
|
930
946
|
this.clear();
|
|
931
947
|
this.#unsubscribeFromProcessEvents();
|
|
@@ -958,7 +974,7 @@ class YoctoSpinner {
|
|
|
958
974
|
}
|
|
959
975
|
|
|
960
976
|
get isSpinning() {
|
|
961
|
-
return this.#
|
|
977
|
+
return this.#isSpinning;
|
|
962
978
|
}
|
|
963
979
|
|
|
964
980
|
get text() {
|
|
@@ -1095,11 +1111,11 @@ var MastraLogger = class {
|
|
|
1095
1111
|
}
|
|
1096
1112
|
trackException(_error) {
|
|
1097
1113
|
}
|
|
1098
|
-
async
|
|
1114
|
+
async listLogs(transportId, params) {
|
|
1099
1115
|
if (!transportId || !this.transports.has(transportId)) {
|
|
1100
1116
|
return { logs: [], total: 0, page: params?.page ?? 1, perPage: params?.perPage ?? 100, hasMore: false };
|
|
1101
1117
|
}
|
|
1102
|
-
return this.transports.get(transportId).
|
|
1118
|
+
return this.transports.get(transportId).listLogs(params) ?? {
|
|
1103
1119
|
logs: [],
|
|
1104
1120
|
total: 0,
|
|
1105
1121
|
page: params?.page ?? 1,
|
|
@@ -1107,7 +1123,7 @@ var MastraLogger = class {
|
|
|
1107
1123
|
hasMore: false
|
|
1108
1124
|
};
|
|
1109
1125
|
}
|
|
1110
|
-
async
|
|
1126
|
+
async listLogsByRunId({
|
|
1111
1127
|
transportId,
|
|
1112
1128
|
runId,
|
|
1113
1129
|
fromDate,
|
|
@@ -1120,7 +1136,7 @@ var MastraLogger = class {
|
|
|
1120
1136
|
if (!transportId || !this.transports.has(transportId) || !runId) {
|
|
1121
1137
|
return { logs: [], total: 0, page: page ?? 1, perPage: perPage ?? 100, hasMore: false };
|
|
1122
1138
|
}
|
|
1123
|
-
return this.transports.get(transportId).
|
|
1139
|
+
return this.transports.get(transportId).listLogsByRunId({ runId, fromDate, toDate, logLevel, filters, page, perPage }) ?? {
|
|
1124
1140
|
logs: [],
|
|
1125
1141
|
total: 0,
|
|
1126
1142
|
page: page ?? 1,
|
|
@@ -1130,10 +1146,15 @@ var MastraLogger = class {
|
|
|
1130
1146
|
}
|
|
1131
1147
|
};
|
|
1132
1148
|
|
|
1133
|
-
var PinoLogger = class extends MastraLogger {
|
|
1149
|
+
var PinoLogger = class _PinoLogger extends MastraLogger {
|
|
1134
1150
|
logger;
|
|
1135
1151
|
constructor(options = {}) {
|
|
1136
1152
|
super(options);
|
|
1153
|
+
const internalOptions = options;
|
|
1154
|
+
if (internalOptions._logger) {
|
|
1155
|
+
this.logger = internalOptions._logger;
|
|
1156
|
+
return;
|
|
1157
|
+
}
|
|
1137
1158
|
let prettyStream = void 0;
|
|
1138
1159
|
if (!options.overrideDefaultTransports) {
|
|
1139
1160
|
prettyStream = pretty({
|
|
@@ -1150,7 +1171,8 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1150
1171
|
{
|
|
1151
1172
|
name: options.name || "app",
|
|
1152
1173
|
level: options.level || LogLevel.INFO,
|
|
1153
|
-
formatters: options.formatters
|
|
1174
|
+
formatters: options.formatters,
|
|
1175
|
+
redact: options.redact
|
|
1154
1176
|
},
|
|
1155
1177
|
options.overrideDefaultTransports ? options?.transports?.default : transportsAry.length === 0 ? prettyStream : pino.multistream([
|
|
1156
1178
|
...transportsAry.map(([, transport]) => ({
|
|
@@ -1164,6 +1186,38 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1164
1186
|
])
|
|
1165
1187
|
);
|
|
1166
1188
|
}
|
|
1189
|
+
/**
|
|
1190
|
+
* Creates a child logger with additional bound context.
|
|
1191
|
+
* All logs from the child logger will include the bound context.
|
|
1192
|
+
*
|
|
1193
|
+
* @param bindings - Key-value pairs to include in all logs from this child logger
|
|
1194
|
+
* @returns A new PinoLogger instance with the bound context
|
|
1195
|
+
*
|
|
1196
|
+
* @example
|
|
1197
|
+
* ```typescript
|
|
1198
|
+
* const baseLogger = new PinoLogger({ name: 'MyApp' });
|
|
1199
|
+
*
|
|
1200
|
+
* // Create module-scoped logger
|
|
1201
|
+
* const serviceLogger = baseLogger.child({ module: 'UserService' });
|
|
1202
|
+
* serviceLogger.info('User created', { userId: '123' });
|
|
1203
|
+
* // Output includes: { module: 'UserService', userId: '123', msg: 'User created' }
|
|
1204
|
+
*
|
|
1205
|
+
* // Create request-scoped logger
|
|
1206
|
+
* const requestLogger = baseLogger.child({ requestId: req.id });
|
|
1207
|
+
* requestLogger.error('Request failed', { err: error });
|
|
1208
|
+
* // Output includes: { requestId: 'abc', msg: 'Request failed', err: {...} }
|
|
1209
|
+
* ```
|
|
1210
|
+
*/
|
|
1211
|
+
child(bindings) {
|
|
1212
|
+
const childPino = this.logger.child(bindings);
|
|
1213
|
+
const childOptions = {
|
|
1214
|
+
name: this.name,
|
|
1215
|
+
level: this.level,
|
|
1216
|
+
transports: Object.fromEntries(this.transports),
|
|
1217
|
+
_logger: childPino
|
|
1218
|
+
};
|
|
1219
|
+
return new _PinoLogger(childOptions);
|
|
1220
|
+
}
|
|
1167
1221
|
debug(message, args = {}) {
|
|
1168
1222
|
this.logger.debug(args, message);
|
|
1169
1223
|
}
|
|
@@ -1178,118 +1232,8 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1178
1232
|
}
|
|
1179
1233
|
};
|
|
1180
1234
|
|
|
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
|
-
}
|
|
1235
|
+
var package_default = {
|
|
1236
|
+
version: "1.0.1"};
|
|
1293
1237
|
function getPackageManagerAddCommand(pm) {
|
|
1294
1238
|
switch (pm) {
|
|
1295
1239
|
case "npm":
|
|
@@ -1310,13 +1254,13 @@ var DepsService = class {
|
|
|
1310
1254
|
this.packageManager = this.getPackageManager();
|
|
1311
1255
|
}
|
|
1312
1256
|
findLockFile(dir) {
|
|
1313
|
-
const lockFiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lock"];
|
|
1257
|
+
const lockFiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lock", "bun.lockb"];
|
|
1314
1258
|
for (const file of lockFiles) {
|
|
1315
|
-
if (fs3__default__default.existsSync(
|
|
1259
|
+
if (fs3__default__default.existsSync(path3.join(dir, file))) {
|
|
1316
1260
|
return file;
|
|
1317
1261
|
}
|
|
1318
1262
|
}
|
|
1319
|
-
const parentDir =
|
|
1263
|
+
const parentDir = path3.resolve(dir, "..");
|
|
1320
1264
|
if (parentDir !== dir) {
|
|
1321
1265
|
return this.findLockFile(parentDir);
|
|
1322
1266
|
}
|
|
@@ -1332,6 +1276,7 @@ var DepsService = class {
|
|
|
1332
1276
|
case "yarn.lock":
|
|
1333
1277
|
return "yarn";
|
|
1334
1278
|
case "bun.lock":
|
|
1279
|
+
case "bun.lockb":
|
|
1335
1280
|
return "bun";
|
|
1336
1281
|
default:
|
|
1337
1282
|
return "npm";
|
|
@@ -1349,7 +1294,7 @@ var DepsService = class {
|
|
|
1349
1294
|
}
|
|
1350
1295
|
async checkDependencies(dependencies) {
|
|
1351
1296
|
try {
|
|
1352
|
-
const packageJsonPath =
|
|
1297
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1353
1298
|
try {
|
|
1354
1299
|
await fs4.access(packageJsonPath);
|
|
1355
1300
|
} catch {
|
|
@@ -1369,7 +1314,7 @@ var DepsService = class {
|
|
|
1369
1314
|
}
|
|
1370
1315
|
async getProjectName() {
|
|
1371
1316
|
try {
|
|
1372
|
-
const packageJsonPath =
|
|
1317
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1373
1318
|
const packageJson = await fs4.readFile(packageJsonPath, "utf-8");
|
|
1374
1319
|
const pkg = JSON.parse(packageJson);
|
|
1375
1320
|
return pkg.name;
|
|
@@ -1457,8 +1402,8 @@ var FileService = class {
|
|
|
1457
1402
|
*/
|
|
1458
1403
|
async copyStarterFile(inputFile, outputFilePath, replaceIfExists) {
|
|
1459
1404
|
const __filename = fileURLToPath(import.meta.url);
|
|
1460
|
-
const __dirname =
|
|
1461
|
-
const filePath =
|
|
1405
|
+
const __dirname = path3.dirname(__filename);
|
|
1406
|
+
const filePath = path3.resolve(__dirname, "starter-files", inputFile);
|
|
1462
1407
|
const fileString = fs3__default__default.readFileSync(filePath, "utf8");
|
|
1463
1408
|
if (fs3__default__default.existsSync(outputFilePath) && !replaceIfExists) {
|
|
1464
1409
|
console.info(`${outputFilePath} already exists`);
|
|
@@ -1468,7 +1413,7 @@ var FileService = class {
|
|
|
1468
1413
|
return true;
|
|
1469
1414
|
}
|
|
1470
1415
|
async setupEnvFile({ dbUrl }) {
|
|
1471
|
-
const envPath =
|
|
1416
|
+
const envPath = path3.join(process.cwd(), ".env.development");
|
|
1472
1417
|
await fsExtra.ensureFile(envPath);
|
|
1473
1418
|
const fileEnvService = new FileEnvService(envPath);
|
|
1474
1419
|
await fileEnvService.setEnvValue("DB_URL", dbUrl);
|
|
@@ -1492,21 +1437,152 @@ var FileService = class {
|
|
|
1492
1437
|
fs3__default__default.writeFileSync(filePath, fileContent);
|
|
1493
1438
|
}
|
|
1494
1439
|
};
|
|
1440
|
+
var createArgs = (versionTag) => {
|
|
1441
|
+
const packageName = versionTag ? `@mastra/mcp-docs-server@${versionTag}` : "@mastra/mcp-docs-server";
|
|
1442
|
+
return ["-y", packageName];
|
|
1443
|
+
};
|
|
1444
|
+
var createMcpConfig = (editor, versionTag) => {
|
|
1445
|
+
const args = createArgs(versionTag);
|
|
1446
|
+
if (editor === "vscode") {
|
|
1447
|
+
return {
|
|
1448
|
+
servers: {
|
|
1449
|
+
mastra: process.platform === `win32` ? {
|
|
1450
|
+
command: "cmd",
|
|
1451
|
+
args: ["/c", "npx", ...args],
|
|
1452
|
+
type: "stdio"
|
|
1453
|
+
} : {
|
|
1454
|
+
command: "npx",
|
|
1455
|
+
args,
|
|
1456
|
+
type: "stdio"
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
return {
|
|
1462
|
+
mcpServers: {
|
|
1463
|
+
mastra: {
|
|
1464
|
+
command: "npx",
|
|
1465
|
+
args
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
};
|
|
1469
|
+
};
|
|
1470
|
+
function makeConfig(original, editor, versionTag) {
|
|
1471
|
+
if (editor === "vscode") {
|
|
1472
|
+
return {
|
|
1473
|
+
...original,
|
|
1474
|
+
servers: {
|
|
1475
|
+
...original?.servers || {},
|
|
1476
|
+
...createMcpConfig(editor, versionTag).servers
|
|
1477
|
+
}
|
|
1478
|
+
};
|
|
1479
|
+
}
|
|
1480
|
+
return {
|
|
1481
|
+
...original,
|
|
1482
|
+
mcpServers: {
|
|
1483
|
+
...original?.mcpServers || {},
|
|
1484
|
+
...createMcpConfig(editor, versionTag).mcpServers
|
|
1485
|
+
}
|
|
1486
|
+
};
|
|
1487
|
+
}
|
|
1488
|
+
async function writeMergedConfig(configPath, editor, versionTag) {
|
|
1489
|
+
const configExists = existsSync(configPath);
|
|
1490
|
+
const config = makeConfig(configExists ? await readJSON(configPath) : {}, editor, versionTag);
|
|
1491
|
+
await ensureFile(configPath);
|
|
1492
|
+
await writeJSON(configPath, config, {
|
|
1493
|
+
spaces: 2
|
|
1494
|
+
});
|
|
1495
|
+
}
|
|
1496
|
+
var windsurfGlobalMCPConfigPath = path3.join(os.homedir(), ".codeium", "windsurf", "mcp_config.json");
|
|
1497
|
+
var antigravityGlobalMCPConfigPath = path3.join(os.homedir(), ".gemini", "antigravity", "mcp_config.json");
|
|
1498
|
+
var cursorGlobalMCPConfigPath = path3.join(os.homedir(), ".cursor", "mcp.json");
|
|
1499
|
+
path3.join(process.cwd(), ".vscode", "mcp.json");
|
|
1500
|
+
var vscodeGlobalMCPConfigPath = path3.join(
|
|
1501
|
+
os.homedir(),
|
|
1502
|
+
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")
|
|
1503
|
+
);
|
|
1504
|
+
async function installMastraDocsMCPServer({
|
|
1505
|
+
editor,
|
|
1506
|
+
directory,
|
|
1507
|
+
versionTag
|
|
1508
|
+
}) {
|
|
1509
|
+
if (editor === `cursor`) {
|
|
1510
|
+
await writeMergedConfig(path3.join(directory, ".cursor", "mcp.json"), "cursor", versionTag);
|
|
1511
|
+
}
|
|
1512
|
+
if (editor === `vscode`) {
|
|
1513
|
+
await writeMergedConfig(path3.join(directory, ".vscode", "mcp.json"), "vscode", versionTag);
|
|
1514
|
+
}
|
|
1515
|
+
if (editor === `cursor-global`) {
|
|
1516
|
+
const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor, versionTag);
|
|
1517
|
+
if (alreadyInstalled) {
|
|
1518
|
+
return;
|
|
1519
|
+
}
|
|
1520
|
+
await writeMergedConfig(cursorGlobalMCPConfigPath, "cursor-global", versionTag);
|
|
1521
|
+
}
|
|
1522
|
+
if (editor === `windsurf`) {
|
|
1523
|
+
const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor, versionTag);
|
|
1524
|
+
if (alreadyInstalled) {
|
|
1525
|
+
return;
|
|
1526
|
+
}
|
|
1527
|
+
await writeMergedConfig(windsurfGlobalMCPConfigPath, editor, versionTag);
|
|
1528
|
+
}
|
|
1529
|
+
if (editor === `antigravity`) {
|
|
1530
|
+
const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor, versionTag);
|
|
1531
|
+
if (alreadyInstalled) {
|
|
1532
|
+
return;
|
|
1533
|
+
}
|
|
1534
|
+
await writeMergedConfig(antigravityGlobalMCPConfigPath, editor, versionTag);
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
async function globalMCPIsAlreadyInstalled(editor, versionTag) {
|
|
1538
|
+
let configPath = ``;
|
|
1539
|
+
if (editor === "windsurf") {
|
|
1540
|
+
configPath = windsurfGlobalMCPConfigPath;
|
|
1541
|
+
} else if (editor === "antigravity") {
|
|
1542
|
+
configPath = antigravityGlobalMCPConfigPath;
|
|
1543
|
+
} else if (editor === "cursor-global") {
|
|
1544
|
+
configPath = cursorGlobalMCPConfigPath;
|
|
1545
|
+
} else if (editor === "vscode") {
|
|
1546
|
+
configPath = vscodeGlobalMCPConfigPath;
|
|
1547
|
+
}
|
|
1548
|
+
if (!configPath || !existsSync(configPath)) {
|
|
1549
|
+
return false;
|
|
1550
|
+
}
|
|
1551
|
+
try {
|
|
1552
|
+
const configContents = await readJSON(configPath);
|
|
1553
|
+
if (!configContents) return false;
|
|
1554
|
+
const expectedPackage = versionTag ? `@mastra/mcp-docs-server@${versionTag}` : "@mastra/mcp-docs-server";
|
|
1555
|
+
if (editor === "vscode") {
|
|
1556
|
+
if (!configContents.servers) return false;
|
|
1557
|
+
const hasMastraMCP2 = Object.values(configContents.servers).some(
|
|
1558
|
+
(server) => server?.args?.find((arg) => arg === expectedPackage)
|
|
1559
|
+
);
|
|
1560
|
+
return hasMastraMCP2;
|
|
1561
|
+
}
|
|
1562
|
+
if (!configContents?.mcpServers) return false;
|
|
1563
|
+
const hasMastraMCP = Object.values(configContents.mcpServers).some(
|
|
1564
|
+
(server) => server?.args?.find((arg) => arg === expectedPackage)
|
|
1565
|
+
);
|
|
1566
|
+
return hasMastraMCP;
|
|
1567
|
+
} catch {
|
|
1568
|
+
return false;
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1495
1571
|
var exec = util.promisify(child_process.exec);
|
|
1496
1572
|
var getModelIdentifier = (llmProvider) => {
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
return `'anthropic/claude-sonnet-4-5-20250929'`;
|
|
1573
|
+
let model = "openai/gpt-4o";
|
|
1574
|
+
if (llmProvider === "anthropic") {
|
|
1575
|
+
model = "anthropic/claude-sonnet-4-5";
|
|
1501
1576
|
} else if (llmProvider === "groq") {
|
|
1502
|
-
|
|
1577
|
+
model = "groq/llama-3.3-70b-versatile";
|
|
1503
1578
|
} else if (llmProvider === "google") {
|
|
1504
|
-
|
|
1579
|
+
model = "google/gemini-2.5-pro";
|
|
1505
1580
|
} else if (llmProvider === "cerebras") {
|
|
1506
|
-
|
|
1581
|
+
model = "cerebras/llama-3.3-70b";
|
|
1507
1582
|
} else if (llmProvider === "mistral") {
|
|
1508
|
-
|
|
1583
|
+
model = "mistral/mistral-medium-2508";
|
|
1509
1584
|
}
|
|
1585
|
+
return model;
|
|
1510
1586
|
};
|
|
1511
1587
|
async function writeAgentSample(llmProvider, destPath, addExampleTool, addScorers) {
|
|
1512
1588
|
const modelString = getModelIdentifier(llmProvider);
|
|
@@ -1527,14 +1603,14 @@ async function writeAgentSample(llmProvider, destPath, addExampleTool, addScorer
|
|
|
1527
1603
|
const content = `
|
|
1528
1604
|
import { Agent } from '@mastra/core/agent';
|
|
1529
1605
|
import { Memory } from '@mastra/memory';
|
|
1530
|
-
import { LibSQLStore } from '@mastra/libsql';
|
|
1531
1606
|
${addExampleTool ? `import { weatherTool } from '../tools/weather-tool';` : ""}
|
|
1532
1607
|
${addScorers ? `import { scorers } from '../scorers/weather-scorer';` : ""}
|
|
1533
1608
|
|
|
1534
1609
|
export const weatherAgent = new Agent({
|
|
1610
|
+
id: 'weather-agent',
|
|
1535
1611
|
name: 'Weather Agent',
|
|
1536
1612
|
instructions: \`${instructions}\`,
|
|
1537
|
-
model: ${modelString},
|
|
1613
|
+
model: '${modelString}',
|
|
1538
1614
|
${addExampleTool ? "tools: { weatherTool }," : ""}
|
|
1539
1615
|
${addScorers ? `scorers: {
|
|
1540
1616
|
toolCallAppropriateness: {
|
|
@@ -1559,11 +1635,7 @@ export const weatherAgent = new Agent({
|
|
|
1559
1635
|
},
|
|
1560
1636
|
},
|
|
1561
1637
|
},` : ""}
|
|
1562
|
-
memory: new Memory(
|
|
1563
|
-
storage: new LibSQLStore({
|
|
1564
|
-
url: "file:../mastra.db", // path is relative to the .mastra/output directory
|
|
1565
|
-
})
|
|
1566
|
-
})
|
|
1638
|
+
memory: new Memory()
|
|
1567
1639
|
});
|
|
1568
1640
|
`;
|
|
1569
1641
|
const formattedContent = await prettier.format(content, {
|
|
@@ -1773,9 +1845,10 @@ async function writeToolSample(destPath) {
|
|
|
1773
1845
|
async function writeScorersSample(llmProvider, destPath) {
|
|
1774
1846
|
const modelString = getModelIdentifier(llmProvider);
|
|
1775
1847
|
const content = `import { z } from 'zod';
|
|
1776
|
-
import { createToolCallAccuracyScorerCode } from '@mastra/evals/scorers/
|
|
1777
|
-
import { createCompletenessScorer } from '@mastra/evals/scorers/
|
|
1778
|
-
import {
|
|
1848
|
+
import { createToolCallAccuracyScorerCode } from '@mastra/evals/scorers/prebuilt';
|
|
1849
|
+
import { createCompletenessScorer } from '@mastra/evals/scorers/prebuilt';
|
|
1850
|
+
import { getAssistantMessageFromRunOutput, getUserMessageFromRunInput } from '@mastra/evals/scorers/utils';
|
|
1851
|
+
import { createScorer } from '@mastra/core/evals';
|
|
1779
1852
|
|
|
1780
1853
|
export const toolCallAppropriatenessScorer = createToolCallAccuracyScorerCode({
|
|
1781
1854
|
expectedTool: 'weatherTool',
|
|
@@ -1786,11 +1859,12 @@ export const completenessScorer = createCompletenessScorer();
|
|
|
1786
1859
|
|
|
1787
1860
|
// Custom LLM-judged scorer: evaluates if non-English locations are translated appropriately
|
|
1788
1861
|
export const translationScorer = createScorer({
|
|
1862
|
+
id: 'translation-quality-scorer',
|
|
1789
1863
|
name: 'Translation Quality',
|
|
1790
1864
|
description: 'Checks that non-English location names are translated and used correctly',
|
|
1791
1865
|
type: 'agent',
|
|
1792
1866
|
judge: {
|
|
1793
|
-
model: ${modelString},
|
|
1867
|
+
model: '${modelString}',
|
|
1794
1868
|
instructions:
|
|
1795
1869
|
'You are an expert evaluator of translation quality for geographic locations. ' +
|
|
1796
1870
|
'Determine whether the user text mentions a non-English location and whether the assistant correctly uses an English translation of that location. ' +
|
|
@@ -1799,8 +1873,8 @@ export const translationScorer = createScorer({
|
|
|
1799
1873
|
},
|
|
1800
1874
|
})
|
|
1801
1875
|
.preprocess(({ run }) => {
|
|
1802
|
-
const userText = (run.input
|
|
1803
|
-
const assistantText = (run.output
|
|
1876
|
+
const userText = getUserMessageFromRunInput(run.input) || '';
|
|
1877
|
+
const assistantText = getAssistantMessageFromRunOutput(run.output) || '';
|
|
1804
1878
|
return { userText, assistantText };
|
|
1805
1879
|
})
|
|
1806
1880
|
.analyze({
|
|
@@ -1887,7 +1961,7 @@ var writeIndexFile = async ({
|
|
|
1887
1961
|
addScorers
|
|
1888
1962
|
}) => {
|
|
1889
1963
|
const indexPath = dirPath + "/index.ts";
|
|
1890
|
-
const destPath =
|
|
1964
|
+
const destPath = path3.join(indexPath);
|
|
1891
1965
|
try {
|
|
1892
1966
|
await fs4.writeFile(destPath, "");
|
|
1893
1967
|
const filteredExports = [
|
|
@@ -1899,7 +1973,7 @@ var writeIndexFile = async ({
|
|
|
1899
1973
|
await fs4.writeFile(
|
|
1900
1974
|
destPath,
|
|
1901
1975
|
`
|
|
1902
|
-
import { Mastra } from '@mastra/core';
|
|
1976
|
+
import { Mastra } from '@mastra/core/mastra';
|
|
1903
1977
|
|
|
1904
1978
|
export const mastra = new Mastra()
|
|
1905
1979
|
`
|
|
@@ -1912,6 +1986,7 @@ export const mastra = new Mastra()
|
|
|
1912
1986
|
import { Mastra } from '@mastra/core/mastra';
|
|
1913
1987
|
import { PinoLogger } from '@mastra/loggers';
|
|
1914
1988
|
import { LibSQLStore } from '@mastra/libsql';
|
|
1989
|
+
import { Observability, DefaultExporter, CloudExporter, SensitiveDataFilter } from '@mastra/observability';
|
|
1915
1990
|
${addWorkflow ? `import { weatherWorkflow } from './workflows/weather-workflow';` : ""}
|
|
1916
1991
|
${addAgent ? `import { weatherAgent } from './agents/weather-agent';` : ""}
|
|
1917
1992
|
${addScorers ? `import { toolCallAppropriatenessScorer, completenessScorer, translationScorer } from './scorers/weather-scorer';` : ""}
|
|
@@ -1919,6 +1994,7 @@ ${addScorers ? `import { toolCallAppropriatenessScorer, completenessScorer, tran
|
|
|
1919
1994
|
export const mastra = new Mastra({
|
|
1920
1995
|
${filteredExports.join("\n ")}
|
|
1921
1996
|
storage: new LibSQLStore({
|
|
1997
|
+
id: "mastra-storage",
|
|
1922
1998
|
// stores observability, scores, ... into memory storage, if it needs to persist, change to file:../mastra.db
|
|
1923
1999
|
url: ":memory:",
|
|
1924
2000
|
}),
|
|
@@ -1926,10 +2002,20 @@ export const mastra = new Mastra({
|
|
|
1926
2002
|
name: 'Mastra',
|
|
1927
2003
|
level: 'info',
|
|
1928
2004
|
}),
|
|
1929
|
-
observability: {
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
2005
|
+
observability: new Observability({
|
|
2006
|
+
configs: {
|
|
2007
|
+
default: {
|
|
2008
|
+
serviceName: 'mastra',
|
|
2009
|
+
exporters: [
|
|
2010
|
+
new DefaultExporter(), // Persists traces to storage for Mastra Studio
|
|
2011
|
+
new CloudExporter(), // Sends traces to Mastra Cloud (if MASTRA_CLOUD_ACCESS_TOKEN is set)
|
|
2012
|
+
],
|
|
2013
|
+
spanOutputProcessors: [
|
|
2014
|
+
new SensitiveDataFilter(), // Redacts sensitive data like passwords, tokens, keys
|
|
2015
|
+
],
|
|
2016
|
+
},
|
|
2017
|
+
},
|
|
2018
|
+
}),
|
|
1933
2019
|
});
|
|
1934
2020
|
`
|
|
1935
2021
|
);
|
|
@@ -1968,7 +2054,7 @@ var writeAPIKey = async ({ provider, apiKey }) => {
|
|
|
1968
2054
|
};
|
|
1969
2055
|
var createMastraDir = async (directory) => {
|
|
1970
2056
|
let dir = directory.trim().split("/").filter((item) => item !== "");
|
|
1971
|
-
const dirPath =
|
|
2057
|
+
const dirPath = path3.join(process.cwd(), ...dir, "mastra");
|
|
1972
2058
|
try {
|
|
1973
2059
|
await fs4.access(dirPath);
|
|
1974
2060
|
return { ok: false };
|
|
@@ -1993,8 +2079,8 @@ var LLM_PROVIDERS = [
|
|
|
1993
2079
|
{ value: "cerebras", label: "Cerebras" },
|
|
1994
2080
|
{ value: "mistral", label: "Mistral" }
|
|
1995
2081
|
];
|
|
1996
|
-
var interactivePrompt = async (
|
|
1997
|
-
const { skip = {}, options: { showBanner = true } = {} } =
|
|
2082
|
+
var interactivePrompt = async (args = {}) => {
|
|
2083
|
+
const { skip = {}, options: { showBanner = true } = {} } = args;
|
|
1998
2084
|
if (showBanner) {
|
|
1999
2085
|
Ie(color2.inverse(" Mastra Init "));
|
|
2000
2086
|
}
|
|
@@ -2032,46 +2118,33 @@ var interactivePrompt = async (args2 = {}) => {
|
|
|
2032
2118
|
return void 0;
|
|
2033
2119
|
},
|
|
2034
2120
|
configureEditorWithDocsMCP: async () => {
|
|
2035
|
-
const windsurfIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`windsurf`);
|
|
2036
|
-
const cursorIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`cursor`);
|
|
2037
|
-
const vscodeIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`vscode`);
|
|
2038
2121
|
const editor = await ve({
|
|
2039
2122
|
message: `Make your IDE into a Mastra expert? (Installs Mastra's MCP server)`,
|
|
2040
2123
|
options: [
|
|
2041
2124
|
{ value: "skip", label: "Skip for now", hint: "default" },
|
|
2042
2125
|
{
|
|
2043
2126
|
value: "cursor",
|
|
2044
|
-
label: "Cursor (project only)"
|
|
2045
|
-
hint: cursorIsAlreadyInstalled ? `Already installed globally` : void 0
|
|
2127
|
+
label: "Cursor (project only)"
|
|
2046
2128
|
},
|
|
2047
2129
|
{
|
|
2048
2130
|
value: "cursor-global",
|
|
2049
|
-
label: "Cursor (global, all projects)"
|
|
2050
|
-
hint: cursorIsAlreadyInstalled ? `Already installed` : void 0
|
|
2131
|
+
label: "Cursor (global, all projects)"
|
|
2051
2132
|
},
|
|
2052
2133
|
{
|
|
2053
2134
|
value: "windsurf",
|
|
2054
|
-
label: "Windsurf"
|
|
2055
|
-
hint: windsurfIsAlreadyInstalled ? `Already installed` : void 0
|
|
2135
|
+
label: "Windsurf"
|
|
2056
2136
|
},
|
|
2057
2137
|
{
|
|
2058
2138
|
value: "vscode",
|
|
2059
|
-
label: "VSCode"
|
|
2060
|
-
|
|
2139
|
+
label: "VSCode"
|
|
2140
|
+
},
|
|
2141
|
+
{
|
|
2142
|
+
value: "antigravity",
|
|
2143
|
+
label: "Antigravity"
|
|
2061
2144
|
}
|
|
2062
2145
|
]
|
|
2063
2146
|
});
|
|
2064
2147
|
if (editor === `skip`) return void 0;
|
|
2065
|
-
if (editor === `windsurf` && windsurfIsAlreadyInstalled) {
|
|
2066
|
-
M.message(`
|
|
2067
|
-
Windsurf is already installed, skipping.`);
|
|
2068
|
-
return void 0;
|
|
2069
|
-
}
|
|
2070
|
-
if (editor === `vscode` && vscodeIsAlreadyInstalled) {
|
|
2071
|
-
M.message(`
|
|
2072
|
-
VSCode is already installed, skipping.`);
|
|
2073
|
-
return void 0;
|
|
2074
|
-
}
|
|
2075
2148
|
if (editor === `cursor`) {
|
|
2076
2149
|
M.message(
|
|
2077
2150
|
`
|
|
@@ -2080,19 +2153,19 @@ Note: you will need to go into Cursor Settings -> MCP Settings and manually enab
|
|
|
2080
2153
|
);
|
|
2081
2154
|
}
|
|
2082
2155
|
if (editor === `cursor-global`) {
|
|
2083
|
-
const
|
|
2156
|
+
const confirm3 = await ve({
|
|
2084
2157
|
message: `Global install will add/update ${cursorGlobalMCPConfigPath} and make the Mastra docs MCP server available in all your Cursor projects. Continue?`,
|
|
2085
2158
|
options: [
|
|
2086
2159
|
{ value: "yes", label: "Yes, I understand" },
|
|
2087
2160
|
{ value: "skip", label: "No, skip for now" }
|
|
2088
2161
|
]
|
|
2089
2162
|
});
|
|
2090
|
-
if (
|
|
2163
|
+
if (confirm3 !== `yes`) {
|
|
2091
2164
|
return void 0;
|
|
2092
2165
|
}
|
|
2093
2166
|
}
|
|
2094
2167
|
if (editor === `windsurf`) {
|
|
2095
|
-
const
|
|
2168
|
+
const confirm3 = await ve({
|
|
2096
2169
|
message: `Windsurf only supports a global MCP config (at ${windsurfGlobalMCPConfigPath}) is it ok to add/update that global config?
|
|
2097
2170
|
This means the Mastra docs MCP server will be available in all your Windsurf projects.`,
|
|
2098
2171
|
options: [
|
|
@@ -2100,11 +2173,31 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
2100
2173
|
{ value: "skip", label: "No, skip for now" }
|
|
2101
2174
|
]
|
|
2102
2175
|
});
|
|
2103
|
-
if (
|
|
2176
|
+
if (confirm3 !== `yes`) {
|
|
2177
|
+
return void 0;
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
if (editor === `antigravity`) {
|
|
2181
|
+
const confirm3 = await ve({
|
|
2182
|
+
message: `Antigravity only supports a global MCP config (at ${antigravityGlobalMCPConfigPath}). Is it ok to add/update that global config?
|
|
2183
|
+
This will make the Mastra docs MCP server available in all Antigravity projects.`,
|
|
2184
|
+
options: [
|
|
2185
|
+
{ value: "yes", label: "Yes, I understand" },
|
|
2186
|
+
{ value: "skip", label: "No, skip for now" }
|
|
2187
|
+
]
|
|
2188
|
+
});
|
|
2189
|
+
if (confirm3 !== `yes`) {
|
|
2104
2190
|
return void 0;
|
|
2105
2191
|
}
|
|
2106
2192
|
}
|
|
2107
2193
|
return editor;
|
|
2194
|
+
},
|
|
2195
|
+
initGit: async () => {
|
|
2196
|
+
if (skip?.gitInit) return false;
|
|
2197
|
+
return ye({
|
|
2198
|
+
message: "Initialize a new git repository?",
|
|
2199
|
+
initialValue: true
|
|
2200
|
+
});
|
|
2108
2201
|
}
|
|
2109
2202
|
},
|
|
2110
2203
|
{
|
|
@@ -2119,6 +2212,9 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
2119
2212
|
function getPackageManager() {
|
|
2120
2213
|
const userAgent = process.env.npm_config_user_agent || "";
|
|
2121
2214
|
const execPath = process.env.npm_execpath || "";
|
|
2215
|
+
if (userAgent.includes("bun")) {
|
|
2216
|
+
return "bun";
|
|
2217
|
+
}
|
|
2122
2218
|
if (userAgent.includes("yarn")) {
|
|
2123
2219
|
return "yarn";
|
|
2124
2220
|
}
|
|
@@ -2128,6 +2224,9 @@ function getPackageManager() {
|
|
|
2128
2224
|
if (userAgent.includes("npm")) {
|
|
2129
2225
|
return "npm";
|
|
2130
2226
|
}
|
|
2227
|
+
if (execPath.includes("bun")) {
|
|
2228
|
+
return "bun";
|
|
2229
|
+
}
|
|
2131
2230
|
if (execPath.includes("yarn")) {
|
|
2132
2231
|
return "yarn";
|
|
2133
2232
|
}
|
|
@@ -2139,6 +2238,20 @@ function getPackageManager() {
|
|
|
2139
2238
|
}
|
|
2140
2239
|
return "npm";
|
|
2141
2240
|
}
|
|
2241
|
+
async function gitInit({ cwd }) {
|
|
2242
|
+
await execa("git", ["init"], { cwd, stdio: "ignore" });
|
|
2243
|
+
await execa("git", ["add", "-A"], { cwd, stdio: "ignore" });
|
|
2244
|
+
await execa(
|
|
2245
|
+
"git",
|
|
2246
|
+
[
|
|
2247
|
+
"commit",
|
|
2248
|
+
"-m",
|
|
2249
|
+
'"Initial commit from Mastra"',
|
|
2250
|
+
'--author="dane-ai-mastra[bot] <dane-ai-mastra[bot]@users.noreply.github.com>"'
|
|
2251
|
+
],
|
|
2252
|
+
{ cwd, stdio: "ignore" }
|
|
2253
|
+
);
|
|
2254
|
+
}
|
|
2142
2255
|
var logger = createLogger(false);
|
|
2143
2256
|
function createLogger(debug = false) {
|
|
2144
2257
|
return new PinoLogger({
|
|
@@ -2148,19 +2261,23 @@ function createLogger(debug = false) {
|
|
|
2148
2261
|
}
|
|
2149
2262
|
var exec2 = util.promisify(child_process.exec);
|
|
2150
2263
|
async function cloneTemplate(options) {
|
|
2151
|
-
const { template, projectName, targetDir } = options;
|
|
2152
|
-
const projectPath = targetDir ?
|
|
2264
|
+
const { template, projectName, targetDir, branch, llmProvider } = options;
|
|
2265
|
+
const projectPath = targetDir ? path3.resolve(targetDir, projectName) : path3.resolve(projectName);
|
|
2153
2266
|
const spinner4 = yoctoSpinner({ text: `Cloning template "${template.title}"...` }).start();
|
|
2154
2267
|
try {
|
|
2155
2268
|
if (await directoryExists(projectPath)) {
|
|
2156
2269
|
spinner4.error(`Directory ${projectName} already exists`);
|
|
2157
2270
|
throw new Error(`Directory ${projectName} already exists`);
|
|
2158
2271
|
}
|
|
2159
|
-
await cloneRepositoryWithoutGit(template.githubUrl, projectPath);
|
|
2272
|
+
await cloneRepositoryWithoutGit(template.githubUrl, projectPath, branch);
|
|
2160
2273
|
await updatePackageJson(projectPath, projectName);
|
|
2161
|
-
const envExamplePath =
|
|
2274
|
+
const envExamplePath = path3.join(projectPath, ".env.example");
|
|
2162
2275
|
if (await fileExists(envExamplePath)) {
|
|
2163
|
-
|
|
2276
|
+
const envPath = path3.join(projectPath, ".env");
|
|
2277
|
+
await fs4.copyFile(envExamplePath, envPath);
|
|
2278
|
+
if (llmProvider) {
|
|
2279
|
+
await updateEnvFile(envPath, llmProvider);
|
|
2280
|
+
}
|
|
2164
2281
|
}
|
|
2165
2282
|
spinner4.success(`Template "${template.title}" cloned successfully to ${projectName}`);
|
|
2166
2283
|
return projectPath;
|
|
@@ -2185,21 +2302,27 @@ async function fileExists(filePath) {
|
|
|
2185
2302
|
return false;
|
|
2186
2303
|
}
|
|
2187
2304
|
}
|
|
2188
|
-
async function cloneRepositoryWithoutGit(repoUrl, targetPath) {
|
|
2305
|
+
async function cloneRepositoryWithoutGit(repoUrl, targetPath, branch) {
|
|
2189
2306
|
await fs4.mkdir(targetPath, { recursive: true });
|
|
2190
2307
|
try {
|
|
2191
2308
|
const degitRepo = repoUrl.replace("https://github.com/", "");
|
|
2192
|
-
const
|
|
2309
|
+
const degitRepoWithBranch = branch ? `${degitRepo}#${branch}` : degitRepo;
|
|
2310
|
+
const degitCommand = shellQuote2.quote(["npx", "degit", degitRepoWithBranch, targetPath]);
|
|
2193
2311
|
await exec2(degitCommand, {
|
|
2194
2312
|
cwd: process.cwd()
|
|
2195
2313
|
});
|
|
2196
2314
|
} catch {
|
|
2197
2315
|
try {
|
|
2198
|
-
const
|
|
2316
|
+
const gitArgs = ["git", "clone"];
|
|
2317
|
+
if (branch) {
|
|
2318
|
+
gitArgs.push("--branch", branch);
|
|
2319
|
+
}
|
|
2320
|
+
gitArgs.push(repoUrl, targetPath);
|
|
2321
|
+
const gitCommand = shellQuote2.quote(gitArgs);
|
|
2199
2322
|
await exec2(gitCommand, {
|
|
2200
2323
|
cwd: process.cwd()
|
|
2201
2324
|
});
|
|
2202
|
-
const gitDir =
|
|
2325
|
+
const gitDir = path3.join(targetPath, ".git");
|
|
2203
2326
|
if (await directoryExists(gitDir)) {
|
|
2204
2327
|
await fs4.rm(gitDir, { recursive: true, force: true });
|
|
2205
2328
|
}
|
|
@@ -2209,7 +2332,7 @@ async function cloneRepositoryWithoutGit(repoUrl, targetPath) {
|
|
|
2209
2332
|
}
|
|
2210
2333
|
}
|
|
2211
2334
|
async function updatePackageJson(projectPath, projectName) {
|
|
2212
|
-
const packageJsonPath =
|
|
2335
|
+
const packageJsonPath = path3.join(projectPath, "package.json");
|
|
2213
2336
|
try {
|
|
2214
2337
|
const packageJsonContent = await fs4.readFile(packageJsonPath, "utf-8");
|
|
2215
2338
|
const packageJson = JSON.parse(packageJsonContent);
|
|
@@ -2219,6 +2342,22 @@ async function updatePackageJson(projectPath, projectName) {
|
|
|
2219
2342
|
logger.warn(`Could not update package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2220
2343
|
}
|
|
2221
2344
|
}
|
|
2345
|
+
async function updateEnvFile(envPath, llmProvider) {
|
|
2346
|
+
try {
|
|
2347
|
+
const envContent = await fs4.readFile(envPath, "utf-8");
|
|
2348
|
+
const modelString = getModelIdentifier(llmProvider);
|
|
2349
|
+
if (!modelString) {
|
|
2350
|
+
logger.warn(`Could not get model identifier for provider: ${llmProvider}`);
|
|
2351
|
+
return;
|
|
2352
|
+
}
|
|
2353
|
+
const modelValue = modelString.replace(/'/g, "");
|
|
2354
|
+
const updatedContent = envContent.replace(/^MODEL=.*/m, `MODEL=${modelValue}`);
|
|
2355
|
+
await fs4.writeFile(envPath, updatedContent, "utf-8");
|
|
2356
|
+
logger.info(`Updated MODEL in .env to ${modelValue}`);
|
|
2357
|
+
} catch (error) {
|
|
2358
|
+
logger.warn(`Could not update .env file: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2222
2361
|
async function installDependencies(projectPath, packageManager) {
|
|
2223
2362
|
const spinner4 = yoctoSpinner({ text: "Installing dependencies..." }).start();
|
|
2224
2363
|
try {
|
|
@@ -2303,9 +2442,12 @@ var init = async ({
|
|
|
2303
2442
|
llmProvider = "openai",
|
|
2304
2443
|
llmApiKey,
|
|
2305
2444
|
addExample = false,
|
|
2306
|
-
configureEditorWithDocsMCP
|
|
2445
|
+
configureEditorWithDocsMCP,
|
|
2446
|
+
versionTag,
|
|
2447
|
+
initGit = false
|
|
2307
2448
|
}) => {
|
|
2308
2449
|
s.start("Initializing Mastra");
|
|
2450
|
+
const packageVersionTag = versionTag ? `@${versionTag}` : "";
|
|
2309
2451
|
try {
|
|
2310
2452
|
const result = await createMastraDir(directory);
|
|
2311
2453
|
if (!result.ok) {
|
|
@@ -2333,33 +2475,44 @@ var init = async ({
|
|
|
2333
2475
|
const depService = new DepsService();
|
|
2334
2476
|
const needsLibsql = await depService.checkDependencies(["@mastra/libsql"]) !== `ok`;
|
|
2335
2477
|
if (needsLibsql) {
|
|
2336
|
-
await depService.installPackages([
|
|
2478
|
+
await depService.installPackages([`@mastra/libsql${packageVersionTag}`]);
|
|
2337
2479
|
}
|
|
2338
2480
|
const needsMemory = components.includes(`agents`) && await depService.checkDependencies(["@mastra/memory"]) !== `ok`;
|
|
2339
2481
|
if (needsMemory) {
|
|
2340
|
-
await depService.installPackages([
|
|
2482
|
+
await depService.installPackages([`@mastra/memory${packageVersionTag}`]);
|
|
2341
2483
|
}
|
|
2342
2484
|
const needsLoggers = await depService.checkDependencies(["@mastra/loggers"]) !== `ok`;
|
|
2343
2485
|
if (needsLoggers) {
|
|
2344
|
-
await depService.installPackages([
|
|
2486
|
+
await depService.installPackages([`@mastra/loggers${packageVersionTag}`]);
|
|
2345
2487
|
}
|
|
2346
2488
|
const needsObservability = await depService.checkDependencies(["@mastra/observability"]) !== `ok`;
|
|
2347
2489
|
if (needsObservability) {
|
|
2348
|
-
await depService.installPackages([
|
|
2490
|
+
await depService.installPackages([`@mastra/observability${packageVersionTag}`]);
|
|
2349
2491
|
}
|
|
2350
2492
|
const needsEvals = components.includes(`scorers`) && await depService.checkDependencies(["@mastra/evals"]) !== `ok`;
|
|
2351
2493
|
if (needsEvals) {
|
|
2352
|
-
await depService.installPackages([
|
|
2494
|
+
await depService.installPackages([`@mastra/evals${packageVersionTag}`]);
|
|
2353
2495
|
}
|
|
2354
2496
|
}
|
|
2355
2497
|
const key = await getAPIKey(llmProvider || "openai");
|
|
2356
2498
|
if (configureEditorWithDocsMCP) {
|
|
2357
2499
|
await installMastraDocsMCPServer({
|
|
2358
2500
|
editor: configureEditorWithDocsMCP,
|
|
2359
|
-
directory: process.cwd()
|
|
2501
|
+
directory: process.cwd(),
|
|
2502
|
+
versionTag
|
|
2360
2503
|
});
|
|
2361
2504
|
}
|
|
2362
2505
|
s.stop();
|
|
2506
|
+
if (initGit) {
|
|
2507
|
+
const s2 = Y();
|
|
2508
|
+
try {
|
|
2509
|
+
s2.start("Initializing git repository");
|
|
2510
|
+
await gitInit({ cwd: process.cwd() });
|
|
2511
|
+
s2.stop("Git repository initialized");
|
|
2512
|
+
} catch {
|
|
2513
|
+
s2.stop();
|
|
2514
|
+
}
|
|
2515
|
+
}
|
|
2363
2516
|
if (!llmApiKey) {
|
|
2364
2517
|
Me(`
|
|
2365
2518
|
${color2.green("Mastra initialized successfully!")}
|
|
@@ -2405,6 +2558,68 @@ var execWithTimeout = async (command, timeoutMs) => {
|
|
|
2405
2558
|
throw error;
|
|
2406
2559
|
}
|
|
2407
2560
|
};
|
|
2561
|
+
async function getInitCommand(pm) {
|
|
2562
|
+
switch (pm) {
|
|
2563
|
+
case "npm":
|
|
2564
|
+
return "npm init -y";
|
|
2565
|
+
case "pnpm":
|
|
2566
|
+
return "pnpm init";
|
|
2567
|
+
case "yarn":
|
|
2568
|
+
return "yarn init -y";
|
|
2569
|
+
case "bun":
|
|
2570
|
+
return "bun init -y";
|
|
2571
|
+
default:
|
|
2572
|
+
return "npm init -y";
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
async function initializePackageJson(pm) {
|
|
2576
|
+
const initCommand = await getInitCommand(pm);
|
|
2577
|
+
await exec3(initCommand);
|
|
2578
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
2579
|
+
const packageJson = JSON.parse(await fs4.readFile(packageJsonPath, "utf-8"));
|
|
2580
|
+
packageJson.type = "module";
|
|
2581
|
+
packageJson.engines = {
|
|
2582
|
+
...packageJson.engines,
|
|
2583
|
+
node: ">=22.13.0"
|
|
2584
|
+
};
|
|
2585
|
+
await fs4.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
2586
|
+
}
|
|
2587
|
+
var writeReadmeFile = async ({ dirPath, projectName }) => {
|
|
2588
|
+
const packageManager = getPackageManager();
|
|
2589
|
+
const readmePath = path3.join(dirPath, "README.md");
|
|
2590
|
+
const content = `# ${projectName}
|
|
2591
|
+
|
|
2592
|
+
Welcome to your new [Mastra](https://mastra.ai/) project! We're excited to see what you'll build.
|
|
2593
|
+
|
|
2594
|
+
## Getting Started
|
|
2595
|
+
|
|
2596
|
+
Start the development server:
|
|
2597
|
+
|
|
2598
|
+
\`\`\`shell
|
|
2599
|
+
${packageManager} run dev
|
|
2600
|
+
\`\`\`
|
|
2601
|
+
|
|
2602
|
+
Open [http://localhost:4111](http://localhost:4111) in your browser to access [Mastra Studio](https://mastra.ai/docs/getting-started/studio). It provides an interactive UI for building and testing your agents, along with a REST API that exposes your Mastra application as a local service. This lets you start building without worrying about integration right away.
|
|
2603
|
+
|
|
2604
|
+
You can start editing files inside the \`src/mastra\` directory. The development server will automatically reload whenever you make changes.
|
|
2605
|
+
|
|
2606
|
+
## Learn more
|
|
2607
|
+
|
|
2608
|
+
To learn more about Mastra, visit our [documentation](https://mastra.ai/docs/). Your bootstrapped project includes example code for [agents](https://mastra.ai/docs/agents/overview), [tools](https://mastra.ai/docs/agents/using-tools), [workflows](https://mastra.ai/docs/workflows/overview), [scorers](https://mastra.ai/docs/evals/overview), and [observability](https://mastra.ai/docs/observability/overview).
|
|
2609
|
+
|
|
2610
|
+
If you're new to AI agents, check out our [course](https://mastra.ai/course) and [YouTube videos](https://youtube.com/@mastra-ai). You can also join our [Discord](https://discord.gg/BTYqqHKUrf) community to get help and share your projects.
|
|
2611
|
+
|
|
2612
|
+
## Deploy on Mastra Cloud
|
|
2613
|
+
|
|
2614
|
+
[Mastra Cloud](https://cloud.mastra.ai/) gives you a serverless agent environment with atomic deployments. Access your agents from anywhere and monitor performance. Make sure they don't go off the rails with evals and tracing.
|
|
2615
|
+
|
|
2616
|
+
Check out the [deployment guide](https://mastra.ai/docs/deployment/overview) for more details.`;
|
|
2617
|
+
const formattedContent = await prettier.format(content, {
|
|
2618
|
+
parser: "markdown",
|
|
2619
|
+
singleQuote: true
|
|
2620
|
+
});
|
|
2621
|
+
await fs4.writeFile(readmePath, formattedContent);
|
|
2622
|
+
};
|
|
2408
2623
|
async function installMastraDependency(pm, dependency, versionTag, isDev, timeout) {
|
|
2409
2624
|
let installCommand = getPackageManagerAddCommand(pm);
|
|
2410
2625
|
if (isDev) {
|
|
@@ -2451,7 +2666,7 @@ var createMastraProject = async ({
|
|
|
2451
2666
|
xe("Operation cancelled");
|
|
2452
2667
|
process.exit(0);
|
|
2453
2668
|
}
|
|
2454
|
-
let result;
|
|
2669
|
+
let result = void 0;
|
|
2455
2670
|
if (needsInteractive) {
|
|
2456
2671
|
result = await interactivePrompt({
|
|
2457
2672
|
options: { showBanner: false },
|
|
@@ -2459,10 +2674,13 @@ var createMastraProject = async ({
|
|
|
2459
2674
|
});
|
|
2460
2675
|
}
|
|
2461
2676
|
const s2 = Y();
|
|
2677
|
+
const originalCwd = process.cwd();
|
|
2678
|
+
let projectPath = null;
|
|
2462
2679
|
try {
|
|
2463
2680
|
s2.start("Creating project");
|
|
2464
2681
|
try {
|
|
2465
2682
|
await fs4.mkdir(projectName);
|
|
2683
|
+
projectPath = path3.resolve(originalCwd, projectName);
|
|
2466
2684
|
} catch (error) {
|
|
2467
2685
|
if (error instanceof Error && "code" in error && error.code === "EEXIST") {
|
|
2468
2686
|
s2.stop(`A directory named "${projectName}" already exists. Please choose a different name.`);
|
|
@@ -2477,15 +2695,14 @@ var createMastraProject = async ({
|
|
|
2477
2695
|
const installCommand = getPackageManagerAddCommand(pm);
|
|
2478
2696
|
s2.message("Initializing project structure");
|
|
2479
2697
|
try {
|
|
2480
|
-
await
|
|
2481
|
-
await exec3(`npm pkg set type="module"`);
|
|
2482
|
-
await exec3(`npm pkg set engines.node=">=20.9.0"`);
|
|
2698
|
+
await initializePackageJson(pm);
|
|
2483
2699
|
const depsService = new DepsService();
|
|
2484
2700
|
await depsService.addScriptsToPackageJson({
|
|
2485
2701
|
dev: "mastra dev",
|
|
2486
2702
|
build: "mastra build",
|
|
2487
2703
|
start: "mastra start"
|
|
2488
2704
|
});
|
|
2705
|
+
await writeReadmeFile({ dirPath: process.cwd(), projectName });
|
|
2489
2706
|
} catch (error) {
|
|
2490
2707
|
throw new Error(
|
|
2491
2708
|
`Failed to initialize project structure: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
@@ -2495,7 +2712,7 @@ var createMastraProject = async ({
|
|
|
2495
2712
|
s2.start(`Installing ${pm} dependencies`);
|
|
2496
2713
|
try {
|
|
2497
2714
|
await exec3(`${pm} ${installCommand} zod@^4`);
|
|
2498
|
-
await exec3(`${pm} ${installCommand} typescript @types/node
|
|
2715
|
+
await exec3(`${pm} ${installCommand} -D typescript @types/node`);
|
|
2499
2716
|
await exec3(`echo '{
|
|
2500
2717
|
"compilerOptions": {
|
|
2501
2718
|
"target": "ES2022",
|
|
@@ -2558,42 +2775,61 @@ var createMastraProject = async ({
|
|
|
2558
2775
|
s2.stop();
|
|
2559
2776
|
const errorMessage = error instanceof Error ? error.message : "An unexpected error occurred";
|
|
2560
2777
|
xe(`Project creation failed: ${errorMessage}`);
|
|
2778
|
+
if (projectPath && fs3__default__default.existsSync(projectPath)) {
|
|
2779
|
+
try {
|
|
2780
|
+
process.chdir(originalCwd);
|
|
2781
|
+
await fs4.rm(projectPath, { recursive: true, force: true });
|
|
2782
|
+
} catch (cleanupError) {
|
|
2783
|
+
console.error(
|
|
2784
|
+
`Warning: Failed to clean up project directory: ${cleanupError instanceof Error ? cleanupError.message : "Unknown error"}`
|
|
2785
|
+
);
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2561
2788
|
process.exit(1);
|
|
2562
2789
|
}
|
|
2563
2790
|
};
|
|
2564
|
-
var
|
|
2565
|
-
|
|
2566
|
-
|
|
2791
|
+
var version$1 = package_default.version;
|
|
2792
|
+
var create = async (args) => {
|
|
2793
|
+
if (args.template !== void 0) {
|
|
2794
|
+
await createFromTemplate({
|
|
2795
|
+
projectName: args.projectName,
|
|
2796
|
+
template: args.template,
|
|
2797
|
+
timeout: args.timeout,
|
|
2798
|
+
injectedAnalytics: args.analytics,
|
|
2799
|
+
llmProvider: args.llmProvider
|
|
2800
|
+
});
|
|
2567
2801
|
return;
|
|
2568
2802
|
}
|
|
2569
|
-
const needsInteractive =
|
|
2803
|
+
const needsInteractive = args.components === void 0 || args.llmProvider === void 0 || args.addExample === void 0;
|
|
2570
2804
|
const { projectName, result } = await createMastraProject({
|
|
2571
|
-
projectName:
|
|
2572
|
-
createVersionTag:
|
|
2573
|
-
timeout:
|
|
2574
|
-
llmProvider:
|
|
2575
|
-
llmApiKey:
|
|
2805
|
+
projectName: args?.projectName,
|
|
2806
|
+
createVersionTag: args?.createVersionTag,
|
|
2807
|
+
timeout: args?.timeout,
|
|
2808
|
+
llmProvider: args?.llmProvider,
|
|
2809
|
+
llmApiKey: args?.llmApiKey,
|
|
2576
2810
|
needsInteractive
|
|
2577
2811
|
});
|
|
2578
|
-
const directory =
|
|
2812
|
+
const directory = args.directory || "src/";
|
|
2579
2813
|
if (needsInteractive && result) {
|
|
2580
2814
|
await init({
|
|
2581
2815
|
...result,
|
|
2582
2816
|
llmApiKey: result?.llmApiKey,
|
|
2583
2817
|
components: ["agents", "tools", "workflows", "scorers"],
|
|
2584
|
-
addExample: true
|
|
2818
|
+
addExample: true,
|
|
2819
|
+
versionTag: args.createVersionTag
|
|
2585
2820
|
});
|
|
2586
2821
|
postCreate({ projectName });
|
|
2587
2822
|
return;
|
|
2588
2823
|
}
|
|
2589
|
-
const { components = [], llmProvider = "openai", addExample = false, llmApiKey } =
|
|
2824
|
+
const { components = [], llmProvider = "openai", addExample = false, llmApiKey } = args;
|
|
2590
2825
|
await init({
|
|
2591
2826
|
directory,
|
|
2592
2827
|
components,
|
|
2593
2828
|
llmProvider,
|
|
2594
2829
|
addExample,
|
|
2595
2830
|
llmApiKey,
|
|
2596
|
-
configureEditorWithDocsMCP:
|
|
2831
|
+
configureEditorWithDocsMCP: args.mcpServer,
|
|
2832
|
+
versionTag: args.createVersionTag
|
|
2597
2833
|
});
|
|
2598
2834
|
postCreate({ projectName });
|
|
2599
2835
|
};
|
|
@@ -2684,9 +2920,9 @@ async function createFromGitHubUrl(url) {
|
|
|
2684
2920
|
workflows: []
|
|
2685
2921
|
};
|
|
2686
2922
|
}
|
|
2687
|
-
async function createFromTemplate(
|
|
2923
|
+
async function createFromTemplate(args) {
|
|
2688
2924
|
let selectedTemplate;
|
|
2689
|
-
if (
|
|
2925
|
+
if (args.template === true) {
|
|
2690
2926
|
const templates = await loadTemplates();
|
|
2691
2927
|
const selected = await selectTemplate(templates);
|
|
2692
2928
|
if (!selected) {
|
|
@@ -2694,11 +2930,11 @@ async function createFromTemplate(args2) {
|
|
|
2694
2930
|
return;
|
|
2695
2931
|
}
|
|
2696
2932
|
selectedTemplate = selected;
|
|
2697
|
-
} else if (
|
|
2698
|
-
if (isGitHubUrl(
|
|
2933
|
+
} else if (args.template && typeof args.template === "string") {
|
|
2934
|
+
if (isGitHubUrl(args.template)) {
|
|
2699
2935
|
const spinner4 = Y();
|
|
2700
2936
|
spinner4.start("Validating GitHub repository...");
|
|
2701
|
-
const validation = await validateGitHubProject(
|
|
2937
|
+
const validation = await validateGitHubProject(args.template);
|
|
2702
2938
|
if (!validation.isValid) {
|
|
2703
2939
|
spinner4.stop("Validation failed");
|
|
2704
2940
|
M.error("This does not appear to be a valid Mastra project:");
|
|
@@ -2706,14 +2942,14 @@ async function createFromTemplate(args2) {
|
|
|
2706
2942
|
throw new Error("Invalid Mastra project");
|
|
2707
2943
|
}
|
|
2708
2944
|
spinner4.stop("Valid Mastra project \u2713");
|
|
2709
|
-
selectedTemplate = await createFromGitHubUrl(
|
|
2945
|
+
selectedTemplate = await createFromGitHubUrl(args.template);
|
|
2710
2946
|
} else {
|
|
2711
2947
|
const templates = await loadTemplates();
|
|
2712
|
-
const found = findTemplateByName(templates,
|
|
2948
|
+
const found = findTemplateByName(templates, args.template);
|
|
2713
2949
|
if (!found) {
|
|
2714
|
-
M.error(`Template "${
|
|
2950
|
+
M.error(`Template "${args.template}" not found. Available templates:`);
|
|
2715
2951
|
templates.forEach((t) => M.info(` - ${t.title} (use: ${t.slug.replace("template-", "")})`));
|
|
2716
|
-
throw new Error(`Template "${
|
|
2952
|
+
throw new Error(`Template "${args.template}" not found`);
|
|
2717
2953
|
}
|
|
2718
2954
|
selectedTemplate = found;
|
|
2719
2955
|
}
|
|
@@ -2721,7 +2957,7 @@ async function createFromTemplate(args2) {
|
|
|
2721
2957
|
if (!selectedTemplate) {
|
|
2722
2958
|
throw new Error("No template selected");
|
|
2723
2959
|
}
|
|
2724
|
-
let projectName =
|
|
2960
|
+
let projectName = args.projectName;
|
|
2725
2961
|
if (!projectName) {
|
|
2726
2962
|
const defaultName = getDefaultProjectName(selectedTemplate);
|
|
2727
2963
|
const response = await he({
|
|
@@ -2735,19 +2971,61 @@ async function createFromTemplate(args2) {
|
|
|
2735
2971
|
}
|
|
2736
2972
|
projectName = response;
|
|
2737
2973
|
}
|
|
2974
|
+
let llmProvider = args.llmProvider;
|
|
2975
|
+
if (!llmProvider) {
|
|
2976
|
+
const providerResponse = await ve({
|
|
2977
|
+
message: "Select a default provider:",
|
|
2978
|
+
options: LLM_PROVIDERS
|
|
2979
|
+
});
|
|
2980
|
+
if (pD(providerResponse)) {
|
|
2981
|
+
M.info("Project creation cancelled.");
|
|
2982
|
+
return;
|
|
2983
|
+
}
|
|
2984
|
+
llmProvider = providerResponse;
|
|
2985
|
+
}
|
|
2986
|
+
let initGit = false;
|
|
2987
|
+
const gitConfirmResult = await ye({
|
|
2988
|
+
message: "Initialize a new git repository?",
|
|
2989
|
+
initialValue: true
|
|
2990
|
+
});
|
|
2991
|
+
if (!pD(gitConfirmResult)) {
|
|
2992
|
+
initGit = gitConfirmResult;
|
|
2993
|
+
}
|
|
2994
|
+
let projectPath = null;
|
|
2738
2995
|
try {
|
|
2739
|
-
const analytics =
|
|
2996
|
+
const analytics = args.injectedAnalytics || getAnalytics();
|
|
2740
2997
|
if (analytics) {
|
|
2741
2998
|
analytics.trackEvent("cli_template_used", {
|
|
2742
2999
|
template_slug: selectedTemplate.slug,
|
|
2743
3000
|
template_title: selectedTemplate.title
|
|
2744
3001
|
});
|
|
3002
|
+
if (llmProvider) {
|
|
3003
|
+
analytics.trackEvent("cli_model_provider_selected", {
|
|
3004
|
+
provider: llmProvider,
|
|
3005
|
+
selection_method: args.llmProvider ? "cli_args" : "interactive"
|
|
3006
|
+
});
|
|
3007
|
+
}
|
|
2745
3008
|
}
|
|
2746
|
-
const
|
|
3009
|
+
const isBeta = version$1?.includes("beta") ?? false;
|
|
3010
|
+
const isMastraTemplate = selectedTemplate.githubUrl.includes("github.com/mastra-ai/");
|
|
3011
|
+
const branch = isBeta && isMastraTemplate ? "beta" : void 0;
|
|
3012
|
+
projectPath = await cloneTemplate({
|
|
2747
3013
|
template: selectedTemplate,
|
|
2748
|
-
projectName
|
|
3014
|
+
projectName,
|
|
3015
|
+
branch,
|
|
3016
|
+
llmProvider
|
|
2749
3017
|
});
|
|
2750
3018
|
await installDependencies(projectPath);
|
|
3019
|
+
if (initGit) {
|
|
3020
|
+
const s2 = Y();
|
|
3021
|
+
try {
|
|
3022
|
+
s2.start("Initializing git repository");
|
|
3023
|
+
await gitInit({ cwd: projectPath });
|
|
3024
|
+
s2.stop("Git repository initialized");
|
|
3025
|
+
} catch {
|
|
3026
|
+
s2.stop();
|
|
3027
|
+
}
|
|
3028
|
+
}
|
|
2751
3029
|
Me(`
|
|
2752
3030
|
${color2.green("Mastra template installed!")}
|
|
2753
3031
|
|
|
@@ -2756,6 +3034,17 @@ async function createFromTemplate(args2) {
|
|
|
2756
3034
|
`);
|
|
2757
3035
|
postCreate({ projectName });
|
|
2758
3036
|
} catch (error) {
|
|
3037
|
+
if (projectPath) {
|
|
3038
|
+
try {
|
|
3039
|
+
if (fs3__default__default.existsSync(projectPath)) {
|
|
3040
|
+
await fs4.rm(projectPath, { recursive: true, force: true });
|
|
3041
|
+
}
|
|
3042
|
+
} catch (cleanupError) {
|
|
3043
|
+
console.error(
|
|
3044
|
+
`Warning: Failed to clean up project directory: ${cleanupError instanceof Error ? cleanupError.message : "Unknown error"}`
|
|
3045
|
+
);
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
2759
3048
|
M.error(`Failed to create project from template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2760
3049
|
throw error;
|
|
2761
3050
|
}
|
|
@@ -2764,7 +3053,7 @@ async function createFromTemplate(args2) {
|
|
|
2764
3053
|
async function getPackageVersion() {
|
|
2765
3054
|
const __filename = fileURLToPath(import.meta.url);
|
|
2766
3055
|
const __dirname = dirname(__filename);
|
|
2767
|
-
const pkgJsonPath =
|
|
3056
|
+
const pkgJsonPath = path3.join(__dirname, "..", "package.json");
|
|
2768
3057
|
const content = await fsExtra$1.readJSON(pkgJsonPath);
|
|
2769
3058
|
return content.version;
|
|
2770
3059
|
}
|
|
@@ -2802,7 +3091,7 @@ program.version(`${version}`, "-v, --version").description(`create-mastra ${vers
|
|
|
2802
3091
|
program.name("create-mastra").description("Create a new Mastra project").argument("[project-name]", "Directory name of the project").option(
|
|
2803
3092
|
"-p, --project-name <string>",
|
|
2804
3093
|
"Project name that will be used in package.json and as the project directory name."
|
|
2805
|
-
).option("--default", "Quick start with defaults (src, OpenAI, examples)").option("-c, --components <components>", "Comma-separated list of components (agents, tools, workflows, scorers)").option("-l, --llm <model-provider>", "Default model provider (openai, anthropic, groq, google, or cerebras)").option("-k, --llm-api-key <api-key>", "API key for the model provider").option("-e, --example", "Include example code").option("-n, --no-example", "Do not include example code").option("-t, --timeout [timeout]", "Configurable timeout for package installation, defaults to 60000 ms").option("-d, --dir <directory>", "Target directory for Mastra source code (default: src/)").option("-m, --mcp <mcp>", "MCP Server for code editor (cursor, cursor-global, windsurf, vscode)").option(
|
|
3094
|
+
).option("--default", "Quick start with defaults (src, OpenAI, examples)").option("-c, --components <components>", "Comma-separated list of components (agents, tools, workflows, scorers)").option("-l, --llm <model-provider>", "Default model provider (openai, anthropic, groq, google, or cerebras)").option("-k, --llm-api-key <api-key>", "API key for the model provider").option("-e, --example", "Include example code").option("-n, --no-example", "Do not include example code").option("-t, --timeout [timeout]", "Configurable timeout for package installation, defaults to 60000 ms").option("-d, --dir <directory>", "Target directory for Mastra source code (default: src/)").option("-m, --mcp <mcp>", "MCP Server for code editor (cursor, cursor-global, windsurf, vscode, antigravity)").option(
|
|
2806
3095
|
"--template [template-name]",
|
|
2807
3096
|
"Create project from a template (use template name, public GitHub URL, or leave blank to select from list)"
|
|
2808
3097
|
).action(async (projectNameArg, args) => {
|