create-mastra 0.0.0-bump-snapshot-attempt-20251015082400 → 0.0.0-bundle-studio-cloud-20251222034739
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 +229 -1
- package/dist/index.js +602 -261
- package/dist/index.js.map +1 -1
- package/dist/starter-files/tools.ts +2 -2
- package/dist/templates/dev.entry.js +2 -45
- package/package.json +18 -19
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(`
|
|
@@ -724,13 +729,18 @@ const format = (open, close) => {
|
|
|
724
729
|
// Handle nested colors.
|
|
725
730
|
|
|
726
731
|
// We could have done this, but it's too slow (as of Node.js 22).
|
|
727
|
-
// return openCode + string.replaceAll(closeCode, openCode) + closeCode;
|
|
732
|
+
// return openCode + string.replaceAll(closeCode, (close === 22 ? closeCode : '') + openCode) + closeCode;
|
|
728
733
|
|
|
729
734
|
let result = openCode;
|
|
730
735
|
let lastIndex = 0;
|
|
731
736
|
|
|
737
|
+
// SGR 22 resets both bold (1) and dim (2). When we encounter a nested
|
|
738
|
+
// close for styles that use 22, we need to re-open the outer style.
|
|
739
|
+
const reopenOnNestedClose = close === 22;
|
|
740
|
+
const replaceCode = (reopenOnNestedClose ? closeCode : '') + openCode;
|
|
741
|
+
|
|
732
742
|
while (index !== -1) {
|
|
733
|
-
result += string.slice(lastIndex, index) +
|
|
743
|
+
result += string.slice(lastIndex, index) + replaceCode;
|
|
734
744
|
lastIndex = index + closeCode.length;
|
|
735
745
|
index = string.indexOf(closeCode, lastIndex);
|
|
736
746
|
}
|
|
@@ -882,6 +892,7 @@ class YoctoSpinner {
|
|
|
882
892
|
#exitHandlerBound;
|
|
883
893
|
#isInteractive;
|
|
884
894
|
#lastSpinnerFrameTime = 0;
|
|
895
|
+
#isSpinning = false;
|
|
885
896
|
|
|
886
897
|
constructor(options = {}) {
|
|
887
898
|
const spinner = options.spinner ?? defaultSpinner;
|
|
@@ -903,13 +914,17 @@ class YoctoSpinner {
|
|
|
903
914
|
return this;
|
|
904
915
|
}
|
|
905
916
|
|
|
917
|
+
this.#isSpinning = true;
|
|
906
918
|
this.#hideCursor();
|
|
907
919
|
this.#render();
|
|
908
920
|
this.#subscribeToProcessEvents();
|
|
909
921
|
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
922
|
+
// Only start the timer in interactive mode
|
|
923
|
+
if (this.#isInteractive) {
|
|
924
|
+
this.#timer = setInterval(() => {
|
|
925
|
+
this.#render();
|
|
926
|
+
}, this.#interval);
|
|
927
|
+
}
|
|
913
928
|
|
|
914
929
|
return this;
|
|
915
930
|
}
|
|
@@ -919,8 +934,12 @@ class YoctoSpinner {
|
|
|
919
934
|
return this;
|
|
920
935
|
}
|
|
921
936
|
|
|
922
|
-
|
|
923
|
-
this.#timer
|
|
937
|
+
this.#isSpinning = false;
|
|
938
|
+
if (this.#timer) {
|
|
939
|
+
clearInterval(this.#timer);
|
|
940
|
+
this.#timer = undefined;
|
|
941
|
+
}
|
|
942
|
+
|
|
924
943
|
this.#showCursor();
|
|
925
944
|
this.clear();
|
|
926
945
|
this.#unsubscribeFromProcessEvents();
|
|
@@ -953,7 +972,7 @@ class YoctoSpinner {
|
|
|
953
972
|
}
|
|
954
973
|
|
|
955
974
|
get isSpinning() {
|
|
956
|
-
return this.#
|
|
975
|
+
return this.#isSpinning;
|
|
957
976
|
}
|
|
958
977
|
|
|
959
978
|
get text() {
|
|
@@ -1090,11 +1109,11 @@ var MastraLogger = class {
|
|
|
1090
1109
|
}
|
|
1091
1110
|
trackException(_error) {
|
|
1092
1111
|
}
|
|
1093
|
-
async
|
|
1112
|
+
async listLogs(transportId, params) {
|
|
1094
1113
|
if (!transportId || !this.transports.has(transportId)) {
|
|
1095
1114
|
return { logs: [], total: 0, page: params?.page ?? 1, perPage: params?.perPage ?? 100, hasMore: false };
|
|
1096
1115
|
}
|
|
1097
|
-
return this.transports.get(transportId).
|
|
1116
|
+
return this.transports.get(transportId).listLogs(params) ?? {
|
|
1098
1117
|
logs: [],
|
|
1099
1118
|
total: 0,
|
|
1100
1119
|
page: params?.page ?? 1,
|
|
@@ -1102,7 +1121,7 @@ var MastraLogger = class {
|
|
|
1102
1121
|
hasMore: false
|
|
1103
1122
|
};
|
|
1104
1123
|
}
|
|
1105
|
-
async
|
|
1124
|
+
async listLogsByRunId({
|
|
1106
1125
|
transportId,
|
|
1107
1126
|
runId,
|
|
1108
1127
|
fromDate,
|
|
@@ -1115,7 +1134,7 @@ var MastraLogger = class {
|
|
|
1115
1134
|
if (!transportId || !this.transports.has(transportId) || !runId) {
|
|
1116
1135
|
return { logs: [], total: 0, page: page ?? 1, perPage: perPage ?? 100, hasMore: false };
|
|
1117
1136
|
}
|
|
1118
|
-
return this.transports.get(transportId).
|
|
1137
|
+
return this.transports.get(transportId).listLogsByRunId({ runId, fromDate, toDate, logLevel, filters, page, perPage }) ?? {
|
|
1119
1138
|
logs: [],
|
|
1120
1139
|
total: 0,
|
|
1121
1140
|
page: page ?? 1,
|
|
@@ -1125,10 +1144,15 @@ var MastraLogger = class {
|
|
|
1125
1144
|
}
|
|
1126
1145
|
};
|
|
1127
1146
|
|
|
1128
|
-
var PinoLogger = class extends MastraLogger {
|
|
1147
|
+
var PinoLogger = class _PinoLogger extends MastraLogger {
|
|
1129
1148
|
logger;
|
|
1130
1149
|
constructor(options = {}) {
|
|
1131
1150
|
super(options);
|
|
1151
|
+
const internalOptions = options;
|
|
1152
|
+
if (internalOptions._logger) {
|
|
1153
|
+
this.logger = internalOptions._logger;
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1132
1156
|
let prettyStream = void 0;
|
|
1133
1157
|
if (!options.overrideDefaultTransports) {
|
|
1134
1158
|
prettyStream = pretty({
|
|
@@ -1145,7 +1169,8 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1145
1169
|
{
|
|
1146
1170
|
name: options.name || "app",
|
|
1147
1171
|
level: options.level || LogLevel.INFO,
|
|
1148
|
-
formatters: options.formatters
|
|
1172
|
+
formatters: options.formatters,
|
|
1173
|
+
redact: options.redact
|
|
1149
1174
|
},
|
|
1150
1175
|
options.overrideDefaultTransports ? options?.transports?.default : transportsAry.length === 0 ? prettyStream : pino.multistream([
|
|
1151
1176
|
...transportsAry.map(([, transport]) => ({
|
|
@@ -1159,6 +1184,38 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1159
1184
|
])
|
|
1160
1185
|
);
|
|
1161
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
|
+
}
|
|
1162
1219
|
debug(message, args = {}) {
|
|
1163
1220
|
this.logger.debug(args, message);
|
|
1164
1221
|
}
|
|
@@ -1173,118 +1230,8 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1173
1230
|
}
|
|
1174
1231
|
};
|
|
1175
1232
|
|
|
1176
|
-
var
|
|
1177
|
-
|
|
1178
|
-
if (editor === "vscode") {
|
|
1179
|
-
return {
|
|
1180
|
-
servers: {
|
|
1181
|
-
mastra: process.platform === `win32` ? {
|
|
1182
|
-
command: "cmd",
|
|
1183
|
-
args: ["/c", "npx", ...args],
|
|
1184
|
-
type: "stdio"
|
|
1185
|
-
} : {
|
|
1186
|
-
command: "npx",
|
|
1187
|
-
args,
|
|
1188
|
-
type: "stdio"
|
|
1189
|
-
}
|
|
1190
|
-
}
|
|
1191
|
-
};
|
|
1192
|
-
}
|
|
1193
|
-
return {
|
|
1194
|
-
mcpServers: {
|
|
1195
|
-
mastra: {
|
|
1196
|
-
command: "npx",
|
|
1197
|
-
args
|
|
1198
|
-
}
|
|
1199
|
-
}
|
|
1200
|
-
};
|
|
1201
|
-
};
|
|
1202
|
-
function makeConfig(original, editor) {
|
|
1203
|
-
if (editor === "vscode") {
|
|
1204
|
-
return {
|
|
1205
|
-
...original,
|
|
1206
|
-
servers: {
|
|
1207
|
-
...original?.servers || {},
|
|
1208
|
-
...createMcpConfig(editor).servers
|
|
1209
|
-
}
|
|
1210
|
-
};
|
|
1211
|
-
}
|
|
1212
|
-
return {
|
|
1213
|
-
...original,
|
|
1214
|
-
mcpServers: {
|
|
1215
|
-
...original?.mcpServers || {},
|
|
1216
|
-
...createMcpConfig(editor).mcpServers
|
|
1217
|
-
}
|
|
1218
|
-
};
|
|
1219
|
-
}
|
|
1220
|
-
async function writeMergedConfig(configPath, editor) {
|
|
1221
|
-
const configExists = existsSync(configPath);
|
|
1222
|
-
const config = makeConfig(configExists ? await readJSON(configPath) : {}, editor);
|
|
1223
|
-
await ensureFile(configPath);
|
|
1224
|
-
await writeJSON(configPath, config, {
|
|
1225
|
-
spaces: 2
|
|
1226
|
-
});
|
|
1227
|
-
}
|
|
1228
|
-
var windsurfGlobalMCPConfigPath = path.join(os.homedir(), ".codeium", "windsurf", "mcp_config.json");
|
|
1229
|
-
var cursorGlobalMCPConfigPath = path.join(os.homedir(), ".cursor", "mcp.json");
|
|
1230
|
-
path.join(process.cwd(), ".vscode", "mcp.json");
|
|
1231
|
-
var vscodeGlobalMCPConfigPath = path.join(
|
|
1232
|
-
os.homedir(),
|
|
1233
|
-
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")
|
|
1234
|
-
);
|
|
1235
|
-
async function installMastraDocsMCPServer({ editor, directory }) {
|
|
1236
|
-
if (editor === `cursor`) {
|
|
1237
|
-
await writeMergedConfig(path.join(directory, ".cursor", "mcp.json"), "cursor");
|
|
1238
|
-
}
|
|
1239
|
-
if (editor === `vscode`) {
|
|
1240
|
-
await writeMergedConfig(path.join(directory, ".vscode", "mcp.json"), "vscode");
|
|
1241
|
-
}
|
|
1242
|
-
if (editor === `cursor-global`) {
|
|
1243
|
-
const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor);
|
|
1244
|
-
if (alreadyInstalled) {
|
|
1245
|
-
return;
|
|
1246
|
-
}
|
|
1247
|
-
await writeMergedConfig(cursorGlobalMCPConfigPath, "cursor-global");
|
|
1248
|
-
}
|
|
1249
|
-
if (editor === `windsurf`) {
|
|
1250
|
-
const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor);
|
|
1251
|
-
if (alreadyInstalled) {
|
|
1252
|
-
return;
|
|
1253
|
-
}
|
|
1254
|
-
await writeMergedConfig(windsurfGlobalMCPConfigPath, editor);
|
|
1255
|
-
}
|
|
1256
|
-
}
|
|
1257
|
-
async function globalMCPIsAlreadyInstalled(editor) {
|
|
1258
|
-
let configPath = ``;
|
|
1259
|
-
if (editor === "windsurf") {
|
|
1260
|
-
configPath = windsurfGlobalMCPConfigPath;
|
|
1261
|
-
} else if (editor === "cursor-global") {
|
|
1262
|
-
configPath = cursorGlobalMCPConfigPath;
|
|
1263
|
-
} else if (editor === "vscode") {
|
|
1264
|
-
configPath = vscodeGlobalMCPConfigPath;
|
|
1265
|
-
}
|
|
1266
|
-
if (!configPath || !existsSync(configPath)) {
|
|
1267
|
-
return false;
|
|
1268
|
-
}
|
|
1269
|
-
try {
|
|
1270
|
-
const configContents = await readJSON(configPath);
|
|
1271
|
-
if (!configContents) return false;
|
|
1272
|
-
if (editor === "vscode") {
|
|
1273
|
-
if (!configContents.servers) return false;
|
|
1274
|
-
const hasMastraMCP2 = Object.values(configContents.servers).some(
|
|
1275
|
-
(server) => server?.args?.find((arg) => arg?.includes(`@mastra/mcp-docs-server`))
|
|
1276
|
-
);
|
|
1277
|
-
return hasMastraMCP2;
|
|
1278
|
-
}
|
|
1279
|
-
if (!configContents?.mcpServers) return false;
|
|
1280
|
-
const hasMastraMCP = Object.values(configContents.mcpServers).some(
|
|
1281
|
-
(server) => server?.args?.find((arg) => arg?.includes(`@mastra/mcp-docs-server`))
|
|
1282
|
-
);
|
|
1283
|
-
return hasMastraMCP;
|
|
1284
|
-
} catch {
|
|
1285
|
-
return false;
|
|
1286
|
-
}
|
|
1287
|
-
}
|
|
1233
|
+
var package_default = {
|
|
1234
|
+
version: "1.0.0-beta.11"};
|
|
1288
1235
|
function getPackageManagerAddCommand(pm) {
|
|
1289
1236
|
switch (pm) {
|
|
1290
1237
|
case "npm":
|
|
@@ -1307,11 +1254,11 @@ var DepsService = class {
|
|
|
1307
1254
|
findLockFile(dir) {
|
|
1308
1255
|
const lockFiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lock"];
|
|
1309
1256
|
for (const file of lockFiles) {
|
|
1310
|
-
if (fs3__default__default.existsSync(
|
|
1257
|
+
if (fs3__default__default.existsSync(path3.join(dir, file))) {
|
|
1311
1258
|
return file;
|
|
1312
1259
|
}
|
|
1313
1260
|
}
|
|
1314
|
-
const parentDir =
|
|
1261
|
+
const parentDir = path3.resolve(dir, "..");
|
|
1315
1262
|
if (parentDir !== dir) {
|
|
1316
1263
|
return this.findLockFile(parentDir);
|
|
1317
1264
|
}
|
|
@@ -1344,7 +1291,7 @@ var DepsService = class {
|
|
|
1344
1291
|
}
|
|
1345
1292
|
async checkDependencies(dependencies) {
|
|
1346
1293
|
try {
|
|
1347
|
-
const packageJsonPath =
|
|
1294
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1348
1295
|
try {
|
|
1349
1296
|
await fs4.access(packageJsonPath);
|
|
1350
1297
|
} catch {
|
|
@@ -1364,7 +1311,7 @@ var DepsService = class {
|
|
|
1364
1311
|
}
|
|
1365
1312
|
async getProjectName() {
|
|
1366
1313
|
try {
|
|
1367
|
-
const packageJsonPath =
|
|
1314
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1368
1315
|
const packageJson = await fs4.readFile(packageJsonPath, "utf-8");
|
|
1369
1316
|
const pkg = JSON.parse(packageJson);
|
|
1370
1317
|
return pkg.name;
|
|
@@ -1452,8 +1399,8 @@ var FileService = class {
|
|
|
1452
1399
|
*/
|
|
1453
1400
|
async copyStarterFile(inputFile, outputFilePath, replaceIfExists) {
|
|
1454
1401
|
const __filename = fileURLToPath(import.meta.url);
|
|
1455
|
-
const __dirname =
|
|
1456
|
-
const filePath =
|
|
1402
|
+
const __dirname = path3.dirname(__filename);
|
|
1403
|
+
const filePath = path3.resolve(__dirname, "starter-files", inputFile);
|
|
1457
1404
|
const fileString = fs3__default__default.readFileSync(filePath, "utf8");
|
|
1458
1405
|
if (fs3__default__default.existsSync(outputFilePath) && !replaceIfExists) {
|
|
1459
1406
|
console.info(`${outputFilePath} already exists`);
|
|
@@ -1463,7 +1410,7 @@ var FileService = class {
|
|
|
1463
1410
|
return true;
|
|
1464
1411
|
}
|
|
1465
1412
|
async setupEnvFile({ dbUrl }) {
|
|
1466
|
-
const envPath =
|
|
1413
|
+
const envPath = path3.join(process.cwd(), ".env.development");
|
|
1467
1414
|
await fsExtra.ensureFile(envPath);
|
|
1468
1415
|
const fileEnvService = new FileEnvService(envPath);
|
|
1469
1416
|
await fileEnvService.setEnvValue("DB_URL", dbUrl);
|
|
@@ -1487,23 +1434,144 @@ var FileService = class {
|
|
|
1487
1434
|
fs3__default__default.writeFileSync(filePath, fileContent);
|
|
1488
1435
|
}
|
|
1489
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
|
+
}
|
|
1490
1558
|
var exec = util.promisify(child_process.exec);
|
|
1491
1559
|
var getModelIdentifier = (llmProvider) => {
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
return `'anthropic/claude-3-5-sonnet-20241022'`;
|
|
1560
|
+
let model = "openai/gpt-4o";
|
|
1561
|
+
if (llmProvider === "anthropic") {
|
|
1562
|
+
model = "anthropic/claude-sonnet-4-5";
|
|
1496
1563
|
} else if (llmProvider === "groq") {
|
|
1497
|
-
|
|
1564
|
+
model = "groq/llama-3.3-70b-versatile";
|
|
1498
1565
|
} else if (llmProvider === "google") {
|
|
1499
|
-
|
|
1566
|
+
model = "google/gemini-2.5-pro";
|
|
1500
1567
|
} else if (llmProvider === "cerebras") {
|
|
1501
|
-
|
|
1568
|
+
model = "cerebras/llama-3.3-70b";
|
|
1502
1569
|
} else if (llmProvider === "mistral") {
|
|
1503
|
-
|
|
1570
|
+
model = "mistral/mistral-medium-2508";
|
|
1504
1571
|
}
|
|
1572
|
+
return model;
|
|
1505
1573
|
};
|
|
1506
|
-
async function writeAgentSample(llmProvider, destPath, addExampleTool) {
|
|
1574
|
+
async function writeAgentSample(llmProvider, destPath, addExampleTool, addScorers) {
|
|
1507
1575
|
const modelString = getModelIdentifier(llmProvider);
|
|
1508
1576
|
const instructions = `
|
|
1509
1577
|
You are a helpful weather assistant that provides accurate weather information and can help planning activities based on the weather.
|
|
@@ -1522,19 +1590,39 @@ async function writeAgentSample(llmProvider, destPath, addExampleTool) {
|
|
|
1522
1590
|
const content = `
|
|
1523
1591
|
import { Agent } from '@mastra/core/agent';
|
|
1524
1592
|
import { Memory } from '@mastra/memory';
|
|
1525
|
-
import { LibSQLStore } from '@mastra/libsql';
|
|
1526
1593
|
${addExampleTool ? `import { weatherTool } from '../tools/weather-tool';` : ""}
|
|
1594
|
+
${addScorers ? `import { scorers } from '../scorers/weather-scorer';` : ""}
|
|
1527
1595
|
|
|
1528
1596
|
export const weatherAgent = new Agent({
|
|
1597
|
+
id: 'weather-agent',
|
|
1529
1598
|
name: 'Weather Agent',
|
|
1530
1599
|
instructions: \`${instructions}\`,
|
|
1531
|
-
model: ${modelString},
|
|
1600
|
+
model: '${modelString}',
|
|
1532
1601
|
${addExampleTool ? "tools: { weatherTool }," : ""}
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1602
|
+
${addScorers ? `scorers: {
|
|
1603
|
+
toolCallAppropriateness: {
|
|
1604
|
+
scorer: scorers.toolCallAppropriatenessScorer,
|
|
1605
|
+
sampling: {
|
|
1606
|
+
type: 'ratio',
|
|
1607
|
+
rate: 1,
|
|
1608
|
+
},
|
|
1609
|
+
},
|
|
1610
|
+
completeness: {
|
|
1611
|
+
scorer: scorers.completenessScorer,
|
|
1612
|
+
sampling: {
|
|
1613
|
+
type: 'ratio',
|
|
1614
|
+
rate: 1,
|
|
1615
|
+
},
|
|
1616
|
+
},
|
|
1617
|
+
translation: {
|
|
1618
|
+
scorer: scorers.translationScorer,
|
|
1619
|
+
sampling: {
|
|
1620
|
+
type: 'ratio',
|
|
1621
|
+
rate: 1,
|
|
1622
|
+
},
|
|
1623
|
+
},
|
|
1624
|
+
},` : ""}
|
|
1625
|
+
memory: new Memory()
|
|
1538
1626
|
});
|
|
1539
1627
|
`;
|
|
1540
1628
|
const formattedContent = await prettier.format(content, {
|
|
@@ -1741,14 +1829,109 @@ async function writeToolSample(destPath) {
|
|
|
1741
1829
|
const fileService = new FileService();
|
|
1742
1830
|
await fileService.copyStarterFile("tools.ts", destPath);
|
|
1743
1831
|
}
|
|
1832
|
+
async function writeScorersSample(llmProvider, destPath) {
|
|
1833
|
+
const modelString = getModelIdentifier(llmProvider);
|
|
1834
|
+
const content = `import { z } from 'zod';
|
|
1835
|
+
import { createToolCallAccuracyScorerCode } from '@mastra/evals/scorers/prebuilt';
|
|
1836
|
+
import { createCompletenessScorer } from '@mastra/evals/scorers/prebuilt';
|
|
1837
|
+
import { getAssistantMessageFromRunOutput, getUserMessageFromRunInput } from '@mastra/evals/scorers/utils';
|
|
1838
|
+
import { createScorer } from '@mastra/core/evals';
|
|
1839
|
+
|
|
1840
|
+
export const toolCallAppropriatenessScorer = createToolCallAccuracyScorerCode({
|
|
1841
|
+
expectedTool: 'weatherTool',
|
|
1842
|
+
strictMode: false,
|
|
1843
|
+
});
|
|
1844
|
+
|
|
1845
|
+
export const completenessScorer = createCompletenessScorer();
|
|
1846
|
+
|
|
1847
|
+
// Custom LLM-judged scorer: evaluates if non-English locations are translated appropriately
|
|
1848
|
+
export const translationScorer = createScorer({
|
|
1849
|
+
id: 'translation-quality-scorer',
|
|
1850
|
+
name: 'Translation Quality',
|
|
1851
|
+
description: 'Checks that non-English location names are translated and used correctly',
|
|
1852
|
+
type: 'agent',
|
|
1853
|
+
judge: {
|
|
1854
|
+
model: '${modelString}',
|
|
1855
|
+
instructions:
|
|
1856
|
+
'You are an expert evaluator of translation quality for geographic locations. ' +
|
|
1857
|
+
'Determine whether the user text mentions a non-English location and whether the assistant correctly uses an English translation of that location. ' +
|
|
1858
|
+
'Be lenient with transliteration differences and diacritics. ' +
|
|
1859
|
+
'Return only the structured JSON matching the provided schema.',
|
|
1860
|
+
},
|
|
1861
|
+
})
|
|
1862
|
+
.preprocess(({ run }) => {
|
|
1863
|
+
const userText = getUserMessageFromRunInput(run.input) || '';
|
|
1864
|
+
const assistantText = getAssistantMessageFromRunOutput(run.output) || '';
|
|
1865
|
+
return { userText, assistantText };
|
|
1866
|
+
})
|
|
1867
|
+
.analyze({
|
|
1868
|
+
description: 'Extract location names and detect language/translation adequacy',
|
|
1869
|
+
outputSchema: z.object({
|
|
1870
|
+
nonEnglish: z.boolean(),
|
|
1871
|
+
translated: z.boolean(),
|
|
1872
|
+
confidence: z.number().min(0).max(1).default(1),
|
|
1873
|
+
explanation: z.string().default(''),
|
|
1874
|
+
}),
|
|
1875
|
+
createPrompt: ({ results }) => \`
|
|
1876
|
+
You are evaluating if a weather assistant correctly handled translation of a non-English location.
|
|
1877
|
+
User text:
|
|
1878
|
+
"""
|
|
1879
|
+
\${results.preprocessStepResult.userText}
|
|
1880
|
+
"""
|
|
1881
|
+
Assistant response:
|
|
1882
|
+
"""
|
|
1883
|
+
\${results.preprocessStepResult.assistantText}
|
|
1884
|
+
"""
|
|
1885
|
+
Tasks:
|
|
1886
|
+
1) Identify if the user mentioned a location that appears non-English.
|
|
1887
|
+
2) If non-English, check whether the assistant used a correct English translation of that location in its response.
|
|
1888
|
+
3) Be lenient with transliteration differences (e.g., accents/diacritics).
|
|
1889
|
+
Return JSON with fields:
|
|
1890
|
+
{
|
|
1891
|
+
"nonEnglish": boolean,
|
|
1892
|
+
"translated": boolean,
|
|
1893
|
+
"confidence": number, // 0-1
|
|
1894
|
+
"explanation": string
|
|
1895
|
+
}
|
|
1896
|
+
\`,
|
|
1897
|
+
})
|
|
1898
|
+
.generateScore(({ results }) => {
|
|
1899
|
+
const r = (results as any)?.analyzeStepResult || {};
|
|
1900
|
+
if (!r.nonEnglish) return 1; // If not applicable, full credit
|
|
1901
|
+
if (r.translated) return Math.max(0, Math.min(1, 0.7 + 0.3 * (r.confidence ?? 1)));
|
|
1902
|
+
return 0; // Non-English but not translated
|
|
1903
|
+
})
|
|
1904
|
+
.generateReason(({ results, score }) => {
|
|
1905
|
+
const r = (results as any)?.analyzeStepResult || {};
|
|
1906
|
+
return \`Translation scoring: nonEnglish=\${r.nonEnglish ?? false}, translated=\${r.translated ?? false}, confidence=\${r.confidence ?? 0}. Score=\${score}. \${r.explanation ?? ''}\`;
|
|
1907
|
+
});
|
|
1908
|
+
|
|
1909
|
+
export const scorers = {
|
|
1910
|
+
toolCallAppropriatenessScorer,
|
|
1911
|
+
completenessScorer,
|
|
1912
|
+
translationScorer,
|
|
1913
|
+
};`;
|
|
1914
|
+
const formattedContent = await prettier.format(content, {
|
|
1915
|
+
parser: "typescript",
|
|
1916
|
+
singleQuote: true
|
|
1917
|
+
});
|
|
1918
|
+
await fs4.writeFile(destPath, formattedContent);
|
|
1919
|
+
}
|
|
1744
1920
|
async function writeCodeSampleForComponents(llmprovider, component, destPath, importComponents) {
|
|
1745
1921
|
switch (component) {
|
|
1746
1922
|
case "agents":
|
|
1747
|
-
return writeAgentSample(
|
|
1923
|
+
return writeAgentSample(
|
|
1924
|
+
llmprovider,
|
|
1925
|
+
destPath,
|
|
1926
|
+
importComponents.includes("tools"),
|
|
1927
|
+
importComponents.includes("scorers")
|
|
1928
|
+
);
|
|
1748
1929
|
case "tools":
|
|
1749
1930
|
return writeToolSample(destPath);
|
|
1750
1931
|
case "workflows":
|
|
1751
1932
|
return writeWorkflowSample(destPath);
|
|
1933
|
+
case "scorers":
|
|
1934
|
+
return writeScorersSample(llmprovider, destPath);
|
|
1752
1935
|
default:
|
|
1753
1936
|
return "";
|
|
1754
1937
|
}
|
|
@@ -1761,21 +1944,23 @@ var writeIndexFile = async ({
|
|
|
1761
1944
|
dirPath,
|
|
1762
1945
|
addAgent,
|
|
1763
1946
|
addExample,
|
|
1764
|
-
addWorkflow
|
|
1947
|
+
addWorkflow,
|
|
1948
|
+
addScorers
|
|
1765
1949
|
}) => {
|
|
1766
1950
|
const indexPath = dirPath + "/index.ts";
|
|
1767
|
-
const destPath =
|
|
1951
|
+
const destPath = path3.join(indexPath);
|
|
1768
1952
|
try {
|
|
1769
1953
|
await fs4.writeFile(destPath, "");
|
|
1770
1954
|
const filteredExports = [
|
|
1771
1955
|
addWorkflow ? `workflows: { weatherWorkflow },` : "",
|
|
1772
|
-
addAgent ? `agents: { weatherAgent },` : ""
|
|
1956
|
+
addAgent ? `agents: { weatherAgent },` : "",
|
|
1957
|
+
addScorers ? `scorers: { toolCallAppropriatenessScorer, completenessScorer, translationScorer },` : ""
|
|
1773
1958
|
].filter(Boolean);
|
|
1774
1959
|
if (!addExample) {
|
|
1775
1960
|
await fs4.writeFile(
|
|
1776
1961
|
destPath,
|
|
1777
1962
|
`
|
|
1778
|
-
import { Mastra } from '@mastra/core';
|
|
1963
|
+
import { Mastra } from '@mastra/core/mastra';
|
|
1779
1964
|
|
|
1780
1965
|
export const mastra = new Mastra()
|
|
1781
1966
|
`
|
|
@@ -1788,12 +1973,15 @@ export const mastra = new Mastra()
|
|
|
1788
1973
|
import { Mastra } from '@mastra/core/mastra';
|
|
1789
1974
|
import { PinoLogger } from '@mastra/loggers';
|
|
1790
1975
|
import { LibSQLStore } from '@mastra/libsql';
|
|
1976
|
+
import { Observability } from '@mastra/observability';
|
|
1791
1977
|
${addWorkflow ? `import { weatherWorkflow } from './workflows/weather-workflow';` : ""}
|
|
1792
1978
|
${addAgent ? `import { weatherAgent } from './agents/weather-agent';` : ""}
|
|
1979
|
+
${addScorers ? `import { toolCallAppropriatenessScorer, completenessScorer, translationScorer } from './scorers/weather-scorer';` : ""}
|
|
1793
1980
|
|
|
1794
1981
|
export const mastra = new Mastra({
|
|
1795
1982
|
${filteredExports.join("\n ")}
|
|
1796
1983
|
storage: new LibSQLStore({
|
|
1984
|
+
id: "mastra-storage",
|
|
1797
1985
|
// stores observability, scores, ... into memory storage, if it needs to persist, change to file:../mastra.db
|
|
1798
1986
|
url: ":memory:",
|
|
1799
1987
|
}),
|
|
@@ -1801,14 +1989,10 @@ export const mastra = new Mastra({
|
|
|
1801
1989
|
name: 'Mastra',
|
|
1802
1990
|
level: 'info',
|
|
1803
1991
|
}),
|
|
1804
|
-
|
|
1805
|
-
//
|
|
1806
|
-
enabled:
|
|
1807
|
-
},
|
|
1808
|
-
observability: {
|
|
1809
|
-
// Enables DefaultExporter and CloudExporter for AI tracing
|
|
1810
|
-
default: { enabled: true },
|
|
1811
|
-
},
|
|
1992
|
+
observability: new Observability({
|
|
1993
|
+
// Enables DefaultExporter and CloudExporter for tracing
|
|
1994
|
+
default: { enabled: true },
|
|
1995
|
+
}),
|
|
1812
1996
|
});
|
|
1813
1997
|
`
|
|
1814
1998
|
);
|
|
@@ -1816,7 +2000,6 @@ export const mastra = new Mastra({
|
|
|
1816
2000
|
throw err;
|
|
1817
2001
|
}
|
|
1818
2002
|
};
|
|
1819
|
-
yoctoSpinner({ text: "Installing Mastra core dependencies\n" });
|
|
1820
2003
|
var getAPIKey = async (provider) => {
|
|
1821
2004
|
let key = "OPENAI_API_KEY";
|
|
1822
2005
|
switch (provider) {
|
|
@@ -1848,7 +2031,7 @@ var writeAPIKey = async ({ provider, apiKey }) => {
|
|
|
1848
2031
|
};
|
|
1849
2032
|
var createMastraDir = async (directory) => {
|
|
1850
2033
|
let dir = directory.trim().split("/").filter((item) => item !== "");
|
|
1851
|
-
const dirPath =
|
|
2034
|
+
const dirPath = path3.join(process.cwd(), ...dir, "mastra");
|
|
1852
2035
|
try {
|
|
1853
2036
|
await fs4.access(dirPath);
|
|
1854
2037
|
return { ok: false };
|
|
@@ -1873,8 +2056,8 @@ var LLM_PROVIDERS = [
|
|
|
1873
2056
|
{ value: "cerebras", label: "Cerebras" },
|
|
1874
2057
|
{ value: "mistral", label: "Mistral" }
|
|
1875
2058
|
];
|
|
1876
|
-
var interactivePrompt = async (
|
|
1877
|
-
const { skip = {}, options: { showBanner = true } = {} } =
|
|
2059
|
+
var interactivePrompt = async (args = {}) => {
|
|
2060
|
+
const { skip = {}, options: { showBanner = true } = {} } = args;
|
|
1878
2061
|
if (showBanner) {
|
|
1879
2062
|
Ie(color2.inverse(" Mastra Init "));
|
|
1880
2063
|
}
|
|
@@ -1912,46 +2095,29 @@ var interactivePrompt = async (args2 = {}) => {
|
|
|
1912
2095
|
return void 0;
|
|
1913
2096
|
},
|
|
1914
2097
|
configureEditorWithDocsMCP: async () => {
|
|
1915
|
-
const windsurfIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`windsurf`);
|
|
1916
|
-
const cursorIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`cursor`);
|
|
1917
|
-
const vscodeIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`vscode`);
|
|
1918
2098
|
const editor = await ve({
|
|
1919
2099
|
message: `Make your IDE into a Mastra expert? (Installs Mastra's MCP server)`,
|
|
1920
2100
|
options: [
|
|
1921
2101
|
{ value: "skip", label: "Skip for now", hint: "default" },
|
|
1922
2102
|
{
|
|
1923
2103
|
value: "cursor",
|
|
1924
|
-
label: "Cursor (project only)"
|
|
1925
|
-
hint: cursorIsAlreadyInstalled ? `Already installed globally` : void 0
|
|
2104
|
+
label: "Cursor (project only)"
|
|
1926
2105
|
},
|
|
1927
2106
|
{
|
|
1928
2107
|
value: "cursor-global",
|
|
1929
|
-
label: "Cursor (global, all projects)"
|
|
1930
|
-
hint: cursorIsAlreadyInstalled ? `Already installed` : void 0
|
|
2108
|
+
label: "Cursor (global, all projects)"
|
|
1931
2109
|
},
|
|
1932
2110
|
{
|
|
1933
2111
|
value: "windsurf",
|
|
1934
|
-
label: "Windsurf"
|
|
1935
|
-
hint: windsurfIsAlreadyInstalled ? `Already installed` : void 0
|
|
2112
|
+
label: "Windsurf"
|
|
1936
2113
|
},
|
|
1937
2114
|
{
|
|
1938
2115
|
value: "vscode",
|
|
1939
|
-
label: "VSCode"
|
|
1940
|
-
hint: vscodeIsAlreadyInstalled ? `Already installed` : void 0
|
|
2116
|
+
label: "VSCode"
|
|
1941
2117
|
}
|
|
1942
2118
|
]
|
|
1943
2119
|
});
|
|
1944
2120
|
if (editor === `skip`) return void 0;
|
|
1945
|
-
if (editor === `windsurf` && windsurfIsAlreadyInstalled) {
|
|
1946
|
-
M.message(`
|
|
1947
|
-
Windsurf is already installed, skipping.`);
|
|
1948
|
-
return void 0;
|
|
1949
|
-
}
|
|
1950
|
-
if (editor === `vscode` && vscodeIsAlreadyInstalled) {
|
|
1951
|
-
M.message(`
|
|
1952
|
-
VSCode is already installed, skipping.`);
|
|
1953
|
-
return void 0;
|
|
1954
|
-
}
|
|
1955
2121
|
if (editor === `cursor`) {
|
|
1956
2122
|
M.message(
|
|
1957
2123
|
`
|
|
@@ -1960,19 +2126,19 @@ Note: you will need to go into Cursor Settings -> MCP Settings and manually enab
|
|
|
1960
2126
|
);
|
|
1961
2127
|
}
|
|
1962
2128
|
if (editor === `cursor-global`) {
|
|
1963
|
-
const
|
|
2129
|
+
const confirm3 = await ve({
|
|
1964
2130
|
message: `Global install will add/update ${cursorGlobalMCPConfigPath} and make the Mastra docs MCP server available in all your Cursor projects. Continue?`,
|
|
1965
2131
|
options: [
|
|
1966
2132
|
{ value: "yes", label: "Yes, I understand" },
|
|
1967
2133
|
{ value: "skip", label: "No, skip for now" }
|
|
1968
2134
|
]
|
|
1969
2135
|
});
|
|
1970
|
-
if (
|
|
2136
|
+
if (confirm3 !== `yes`) {
|
|
1971
2137
|
return void 0;
|
|
1972
2138
|
}
|
|
1973
2139
|
}
|
|
1974
2140
|
if (editor === `windsurf`) {
|
|
1975
|
-
const
|
|
2141
|
+
const confirm3 = await ve({
|
|
1976
2142
|
message: `Windsurf only supports a global MCP config (at ${windsurfGlobalMCPConfigPath}) is it ok to add/update that global config?
|
|
1977
2143
|
This means the Mastra docs MCP server will be available in all your Windsurf projects.`,
|
|
1978
2144
|
options: [
|
|
@@ -1980,11 +2146,18 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
1980
2146
|
{ value: "skip", label: "No, skip for now" }
|
|
1981
2147
|
]
|
|
1982
2148
|
});
|
|
1983
|
-
if (
|
|
2149
|
+
if (confirm3 !== `yes`) {
|
|
1984
2150
|
return void 0;
|
|
1985
2151
|
}
|
|
1986
2152
|
}
|
|
1987
2153
|
return editor;
|
|
2154
|
+
},
|
|
2155
|
+
initGit: async () => {
|
|
2156
|
+
if (skip?.gitInit) return false;
|
|
2157
|
+
return ye({
|
|
2158
|
+
message: "Initialize a new git repository?",
|
|
2159
|
+
initialValue: true
|
|
2160
|
+
});
|
|
1988
2161
|
}
|
|
1989
2162
|
},
|
|
1990
2163
|
{
|
|
@@ -1999,6 +2172,9 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
1999
2172
|
function getPackageManager() {
|
|
2000
2173
|
const userAgent = process.env.npm_config_user_agent || "";
|
|
2001
2174
|
const execPath = process.env.npm_execpath || "";
|
|
2175
|
+
if (userAgent.includes("bun")) {
|
|
2176
|
+
return "bun";
|
|
2177
|
+
}
|
|
2002
2178
|
if (userAgent.includes("yarn")) {
|
|
2003
2179
|
return "yarn";
|
|
2004
2180
|
}
|
|
@@ -2008,6 +2184,9 @@ function getPackageManager() {
|
|
|
2008
2184
|
if (userAgent.includes("npm")) {
|
|
2009
2185
|
return "npm";
|
|
2010
2186
|
}
|
|
2187
|
+
if (execPath.includes("bun")) {
|
|
2188
|
+
return "bun";
|
|
2189
|
+
}
|
|
2011
2190
|
if (execPath.includes("yarn")) {
|
|
2012
2191
|
return "yarn";
|
|
2013
2192
|
}
|
|
@@ -2019,6 +2198,20 @@ function getPackageManager() {
|
|
|
2019
2198
|
}
|
|
2020
2199
|
return "npm";
|
|
2021
2200
|
}
|
|
2201
|
+
async function gitInit({ cwd }) {
|
|
2202
|
+
await execa("git", ["init"], { cwd, stdio: "ignore" });
|
|
2203
|
+
await execa("git", ["add", "-A"], { cwd, stdio: "ignore" });
|
|
2204
|
+
await execa(
|
|
2205
|
+
"git",
|
|
2206
|
+
[
|
|
2207
|
+
"commit",
|
|
2208
|
+
"-m",
|
|
2209
|
+
'"Initial commit from Mastra"',
|
|
2210
|
+
'--author="dane-ai-mastra[bot] <dane-ai-mastra[bot]@users.noreply.github.com>"'
|
|
2211
|
+
],
|
|
2212
|
+
{ cwd, stdio: "ignore" }
|
|
2213
|
+
);
|
|
2214
|
+
}
|
|
2022
2215
|
var logger = createLogger(false);
|
|
2023
2216
|
function createLogger(debug = false) {
|
|
2024
2217
|
return new PinoLogger({
|
|
@@ -2028,24 +2221,28 @@ function createLogger(debug = false) {
|
|
|
2028
2221
|
}
|
|
2029
2222
|
var exec2 = util.promisify(child_process.exec);
|
|
2030
2223
|
async function cloneTemplate(options) {
|
|
2031
|
-
const { template, projectName, targetDir } = options;
|
|
2032
|
-
const projectPath = targetDir ?
|
|
2033
|
-
const
|
|
2224
|
+
const { template, projectName, targetDir, branch, llmProvider } = options;
|
|
2225
|
+
const projectPath = targetDir ? path3.resolve(targetDir, projectName) : path3.resolve(projectName);
|
|
2226
|
+
const spinner4 = yoctoSpinner({ text: `Cloning template "${template.title}"...` }).start();
|
|
2034
2227
|
try {
|
|
2035
2228
|
if (await directoryExists(projectPath)) {
|
|
2036
|
-
|
|
2229
|
+
spinner4.error(`Directory ${projectName} already exists`);
|
|
2037
2230
|
throw new Error(`Directory ${projectName} already exists`);
|
|
2038
2231
|
}
|
|
2039
|
-
await cloneRepositoryWithoutGit(template.githubUrl, projectPath);
|
|
2232
|
+
await cloneRepositoryWithoutGit(template.githubUrl, projectPath, branch);
|
|
2040
2233
|
await updatePackageJson(projectPath, projectName);
|
|
2041
|
-
const envExamplePath =
|
|
2234
|
+
const envExamplePath = path3.join(projectPath, ".env.example");
|
|
2042
2235
|
if (await fileExists(envExamplePath)) {
|
|
2043
|
-
|
|
2236
|
+
const envPath = path3.join(projectPath, ".env");
|
|
2237
|
+
await fs4.copyFile(envExamplePath, envPath);
|
|
2238
|
+
if (llmProvider) {
|
|
2239
|
+
await updateEnvFile(envPath, llmProvider);
|
|
2240
|
+
}
|
|
2044
2241
|
}
|
|
2045
|
-
|
|
2242
|
+
spinner4.success(`Template "${template.title}" cloned successfully to ${projectName}`);
|
|
2046
2243
|
return projectPath;
|
|
2047
2244
|
} catch (error) {
|
|
2048
|
-
|
|
2245
|
+
spinner4.error(`Failed to clone template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2049
2246
|
throw error;
|
|
2050
2247
|
}
|
|
2051
2248
|
}
|
|
@@ -2065,21 +2262,27 @@ async function fileExists(filePath) {
|
|
|
2065
2262
|
return false;
|
|
2066
2263
|
}
|
|
2067
2264
|
}
|
|
2068
|
-
async function cloneRepositoryWithoutGit(repoUrl, targetPath) {
|
|
2265
|
+
async function cloneRepositoryWithoutGit(repoUrl, targetPath, branch) {
|
|
2069
2266
|
await fs4.mkdir(targetPath, { recursive: true });
|
|
2070
2267
|
try {
|
|
2071
2268
|
const degitRepo = repoUrl.replace("https://github.com/", "");
|
|
2072
|
-
const
|
|
2269
|
+
const degitRepoWithBranch = branch ? `${degitRepo}#${branch}` : degitRepo;
|
|
2270
|
+
const degitCommand = shellQuote2.quote(["npx", "degit", degitRepoWithBranch, targetPath]);
|
|
2073
2271
|
await exec2(degitCommand, {
|
|
2074
2272
|
cwd: process.cwd()
|
|
2075
2273
|
});
|
|
2076
2274
|
} catch {
|
|
2077
2275
|
try {
|
|
2078
|
-
const
|
|
2276
|
+
const gitArgs = ["git", "clone"];
|
|
2277
|
+
if (branch) {
|
|
2278
|
+
gitArgs.push("--branch", branch);
|
|
2279
|
+
}
|
|
2280
|
+
gitArgs.push(repoUrl, targetPath);
|
|
2281
|
+
const gitCommand = shellQuote2.quote(gitArgs);
|
|
2079
2282
|
await exec2(gitCommand, {
|
|
2080
2283
|
cwd: process.cwd()
|
|
2081
2284
|
});
|
|
2082
|
-
const gitDir =
|
|
2285
|
+
const gitDir = path3.join(targetPath, ".git");
|
|
2083
2286
|
if (await directoryExists(gitDir)) {
|
|
2084
2287
|
await fs4.rm(gitDir, { recursive: true, force: true });
|
|
2085
2288
|
}
|
|
@@ -2089,7 +2292,7 @@ async function cloneRepositoryWithoutGit(repoUrl, targetPath) {
|
|
|
2089
2292
|
}
|
|
2090
2293
|
}
|
|
2091
2294
|
async function updatePackageJson(projectPath, projectName) {
|
|
2092
|
-
const packageJsonPath =
|
|
2295
|
+
const packageJsonPath = path3.join(projectPath, "package.json");
|
|
2093
2296
|
try {
|
|
2094
2297
|
const packageJsonContent = await fs4.readFile(packageJsonPath, "utf-8");
|
|
2095
2298
|
const packageJson = JSON.parse(packageJsonContent);
|
|
@@ -2099,17 +2302,33 @@ async function updatePackageJson(projectPath, projectName) {
|
|
|
2099
2302
|
logger.warn(`Could not update package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2100
2303
|
}
|
|
2101
2304
|
}
|
|
2305
|
+
async function updateEnvFile(envPath, llmProvider) {
|
|
2306
|
+
try {
|
|
2307
|
+
const envContent = await fs4.readFile(envPath, "utf-8");
|
|
2308
|
+
const modelString = getModelIdentifier(llmProvider);
|
|
2309
|
+
if (!modelString) {
|
|
2310
|
+
logger.warn(`Could not get model identifier for provider: ${llmProvider}`);
|
|
2311
|
+
return;
|
|
2312
|
+
}
|
|
2313
|
+
const modelValue = modelString.replace(/'/g, "");
|
|
2314
|
+
const updatedContent = envContent.replace(/^MODEL=.*/m, `MODEL=${modelValue}`);
|
|
2315
|
+
await fs4.writeFile(envPath, updatedContent, "utf-8");
|
|
2316
|
+
logger.info(`Updated MODEL in .env to ${modelValue}`);
|
|
2317
|
+
} catch (error) {
|
|
2318
|
+
logger.warn(`Could not update .env file: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2319
|
+
}
|
|
2320
|
+
}
|
|
2102
2321
|
async function installDependencies(projectPath, packageManager) {
|
|
2103
|
-
const
|
|
2322
|
+
const spinner4 = yoctoSpinner({ text: "Installing dependencies..." }).start();
|
|
2104
2323
|
try {
|
|
2105
2324
|
const pm = packageManager || getPackageManager();
|
|
2106
2325
|
const installCommand = shellQuote2.quote([pm, "install"]);
|
|
2107
2326
|
await exec2(installCommand, {
|
|
2108
2327
|
cwd: projectPath
|
|
2109
2328
|
});
|
|
2110
|
-
|
|
2329
|
+
spinner4.success("Dependencies installed successfully");
|
|
2111
2330
|
} catch (error) {
|
|
2112
|
-
|
|
2331
|
+
spinner4.error(`Failed to install dependencies: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2113
2332
|
throw error;
|
|
2114
2333
|
}
|
|
2115
2334
|
}
|
|
@@ -2183,9 +2402,12 @@ var init = async ({
|
|
|
2183
2402
|
llmProvider = "openai",
|
|
2184
2403
|
llmApiKey,
|
|
2185
2404
|
addExample = false,
|
|
2186
|
-
configureEditorWithDocsMCP
|
|
2405
|
+
configureEditorWithDocsMCP,
|
|
2406
|
+
versionTag,
|
|
2407
|
+
initGit = false
|
|
2187
2408
|
}) => {
|
|
2188
2409
|
s.start("Initializing Mastra");
|
|
2410
|
+
const packageVersionTag = versionTag ? `@${versionTag}` : "";
|
|
2189
2411
|
try {
|
|
2190
2412
|
const result = await createMastraDir(directory);
|
|
2191
2413
|
if (!result.ok) {
|
|
@@ -2198,7 +2420,8 @@ var init = async ({
|
|
|
2198
2420
|
dirPath,
|
|
2199
2421
|
addExample,
|
|
2200
2422
|
addWorkflow: components.includes("workflows"),
|
|
2201
|
-
addAgent: components.includes("agents")
|
|
2423
|
+
addAgent: components.includes("agents"),
|
|
2424
|
+
addScorers: components.includes("scorers")
|
|
2202
2425
|
}),
|
|
2203
2426
|
...components.map((component) => createComponentsDir(dirPath, component)),
|
|
2204
2427
|
writeAPIKey({ provider: llmProvider, apiKey: llmApiKey })
|
|
@@ -2212,25 +2435,44 @@ var init = async ({
|
|
|
2212
2435
|
const depService = new DepsService();
|
|
2213
2436
|
const needsLibsql = await depService.checkDependencies(["@mastra/libsql"]) !== `ok`;
|
|
2214
2437
|
if (needsLibsql) {
|
|
2215
|
-
await depService.installPackages([
|
|
2438
|
+
await depService.installPackages([`@mastra/libsql${packageVersionTag}`]);
|
|
2216
2439
|
}
|
|
2217
2440
|
const needsMemory = components.includes(`agents`) && await depService.checkDependencies(["@mastra/memory"]) !== `ok`;
|
|
2218
2441
|
if (needsMemory) {
|
|
2219
|
-
await depService.installPackages([
|
|
2442
|
+
await depService.installPackages([`@mastra/memory${packageVersionTag}`]);
|
|
2220
2443
|
}
|
|
2221
2444
|
const needsLoggers = await depService.checkDependencies(["@mastra/loggers"]) !== `ok`;
|
|
2222
2445
|
if (needsLoggers) {
|
|
2223
|
-
await depService.installPackages([
|
|
2446
|
+
await depService.installPackages([`@mastra/loggers${packageVersionTag}`]);
|
|
2447
|
+
}
|
|
2448
|
+
const needsObservability = await depService.checkDependencies(["@mastra/observability"]) !== `ok`;
|
|
2449
|
+
if (needsObservability) {
|
|
2450
|
+
await depService.installPackages([`@mastra/observability${packageVersionTag}`]);
|
|
2451
|
+
}
|
|
2452
|
+
const needsEvals = components.includes(`scorers`) && await depService.checkDependencies(["@mastra/evals"]) !== `ok`;
|
|
2453
|
+
if (needsEvals) {
|
|
2454
|
+
await depService.installPackages([`@mastra/evals${packageVersionTag}`]);
|
|
2224
2455
|
}
|
|
2225
2456
|
}
|
|
2226
2457
|
const key = await getAPIKey(llmProvider || "openai");
|
|
2227
2458
|
if (configureEditorWithDocsMCP) {
|
|
2228
2459
|
await installMastraDocsMCPServer({
|
|
2229
2460
|
editor: configureEditorWithDocsMCP,
|
|
2230
|
-
directory: process.cwd()
|
|
2461
|
+
directory: process.cwd(),
|
|
2462
|
+
versionTag
|
|
2231
2463
|
});
|
|
2232
2464
|
}
|
|
2233
2465
|
s.stop();
|
|
2466
|
+
if (initGit) {
|
|
2467
|
+
const s2 = Y();
|
|
2468
|
+
try {
|
|
2469
|
+
s2.start("Initializing git repository");
|
|
2470
|
+
await gitInit({ cwd: process.cwd() });
|
|
2471
|
+
s2.stop("Git repository initialized");
|
|
2472
|
+
} catch {
|
|
2473
|
+
s2.stop();
|
|
2474
|
+
}
|
|
2475
|
+
}
|
|
2234
2476
|
if (!llmApiKey) {
|
|
2235
2477
|
Me(`
|
|
2236
2478
|
${color2.green("Mastra initialized successfully!")}
|
|
@@ -2276,6 +2518,32 @@ var execWithTimeout = async (command, timeoutMs) => {
|
|
|
2276
2518
|
throw error;
|
|
2277
2519
|
}
|
|
2278
2520
|
};
|
|
2521
|
+
async function getInitCommand(pm) {
|
|
2522
|
+
switch (pm) {
|
|
2523
|
+
case "npm":
|
|
2524
|
+
return "npm init -y";
|
|
2525
|
+
case "pnpm":
|
|
2526
|
+
return "pnpm init";
|
|
2527
|
+
case "yarn":
|
|
2528
|
+
return "yarn init -y";
|
|
2529
|
+
case "bun":
|
|
2530
|
+
return "bun init -y";
|
|
2531
|
+
default:
|
|
2532
|
+
return "npm init -y";
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
async function initializePackageJson(pm) {
|
|
2536
|
+
const initCommand = await getInitCommand(pm);
|
|
2537
|
+
await exec3(initCommand);
|
|
2538
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
2539
|
+
const packageJson = JSON.parse(await fs4.readFile(packageJsonPath, "utf-8"));
|
|
2540
|
+
packageJson.type = "module";
|
|
2541
|
+
packageJson.engines = {
|
|
2542
|
+
...packageJson.engines,
|
|
2543
|
+
node: ">=22.13.0"
|
|
2544
|
+
};
|
|
2545
|
+
await fs4.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
2546
|
+
}
|
|
2279
2547
|
async function installMastraDependency(pm, dependency, versionTag, isDev, timeout) {
|
|
2280
2548
|
let installCommand = getPackageManagerAddCommand(pm);
|
|
2281
2549
|
if (isDev) {
|
|
@@ -2322,7 +2590,7 @@ var createMastraProject = async ({
|
|
|
2322
2590
|
xe("Operation cancelled");
|
|
2323
2591
|
process.exit(0);
|
|
2324
2592
|
}
|
|
2325
|
-
let result;
|
|
2593
|
+
let result = void 0;
|
|
2326
2594
|
if (needsInteractive) {
|
|
2327
2595
|
result = await interactivePrompt({
|
|
2328
2596
|
options: { showBanner: false },
|
|
@@ -2330,10 +2598,13 @@ var createMastraProject = async ({
|
|
|
2330
2598
|
});
|
|
2331
2599
|
}
|
|
2332
2600
|
const s2 = Y();
|
|
2601
|
+
const originalCwd = process.cwd();
|
|
2602
|
+
let projectPath = null;
|
|
2333
2603
|
try {
|
|
2334
2604
|
s2.start("Creating project");
|
|
2335
2605
|
try {
|
|
2336
2606
|
await fs4.mkdir(projectName);
|
|
2607
|
+
projectPath = path3.resolve(originalCwd, projectName);
|
|
2337
2608
|
} catch (error) {
|
|
2338
2609
|
if (error instanceof Error && "code" in error && error.code === "EEXIST") {
|
|
2339
2610
|
s2.stop(`A directory named "${projectName}" already exists. Please choose a different name.`);
|
|
@@ -2348,9 +2619,7 @@ var createMastraProject = async ({
|
|
|
2348
2619
|
const installCommand = getPackageManagerAddCommand(pm);
|
|
2349
2620
|
s2.message("Initializing project structure");
|
|
2350
2621
|
try {
|
|
2351
|
-
await
|
|
2352
|
-
await exec3(`npm pkg set type="module"`);
|
|
2353
|
-
await exec3(`npm pkg set engines.node=">=20.9.0"`);
|
|
2622
|
+
await initializePackageJson(pm);
|
|
2354
2623
|
const depsService = new DepsService();
|
|
2355
2624
|
await depsService.addScriptsToPackageJson({
|
|
2356
2625
|
dev: "mastra dev",
|
|
@@ -2366,7 +2635,7 @@ var createMastraProject = async ({
|
|
|
2366
2635
|
s2.start(`Installing ${pm} dependencies`);
|
|
2367
2636
|
try {
|
|
2368
2637
|
await exec3(`${pm} ${installCommand} zod@^4`);
|
|
2369
|
-
await exec3(`${pm} ${installCommand} typescript @types/node
|
|
2638
|
+
await exec3(`${pm} ${installCommand} -D typescript @types/node`);
|
|
2370
2639
|
await exec3(`echo '{
|
|
2371
2640
|
"compilerOptions": {
|
|
2372
2641
|
"target": "ES2022",
|
|
@@ -2429,42 +2698,61 @@ var createMastraProject = async ({
|
|
|
2429
2698
|
s2.stop();
|
|
2430
2699
|
const errorMessage = error instanceof Error ? error.message : "An unexpected error occurred";
|
|
2431
2700
|
xe(`Project creation failed: ${errorMessage}`);
|
|
2701
|
+
if (projectPath && fs3__default__default.existsSync(projectPath)) {
|
|
2702
|
+
try {
|
|
2703
|
+
process.chdir(originalCwd);
|
|
2704
|
+
await fs4.rm(projectPath, { recursive: true, force: true });
|
|
2705
|
+
} catch (cleanupError) {
|
|
2706
|
+
console.error(
|
|
2707
|
+
`Warning: Failed to clean up project directory: ${cleanupError instanceof Error ? cleanupError.message : "Unknown error"}`
|
|
2708
|
+
);
|
|
2709
|
+
}
|
|
2710
|
+
}
|
|
2432
2711
|
process.exit(1);
|
|
2433
2712
|
}
|
|
2434
2713
|
};
|
|
2435
|
-
var
|
|
2436
|
-
|
|
2437
|
-
|
|
2714
|
+
var version$1 = package_default.version;
|
|
2715
|
+
var create = async (args) => {
|
|
2716
|
+
if (args.template !== void 0) {
|
|
2717
|
+
await createFromTemplate({
|
|
2718
|
+
projectName: args.projectName,
|
|
2719
|
+
template: args.template,
|
|
2720
|
+
timeout: args.timeout,
|
|
2721
|
+
injectedAnalytics: args.analytics,
|
|
2722
|
+
llmProvider: args.llmProvider
|
|
2723
|
+
});
|
|
2438
2724
|
return;
|
|
2439
2725
|
}
|
|
2440
|
-
const needsInteractive =
|
|
2726
|
+
const needsInteractive = args.components === void 0 || args.llmProvider === void 0 || args.addExample === void 0;
|
|
2441
2727
|
const { projectName, result } = await createMastraProject({
|
|
2442
|
-
projectName:
|
|
2443
|
-
createVersionTag:
|
|
2444
|
-
timeout:
|
|
2445
|
-
llmProvider:
|
|
2446
|
-
llmApiKey:
|
|
2728
|
+
projectName: args?.projectName,
|
|
2729
|
+
createVersionTag: args?.createVersionTag,
|
|
2730
|
+
timeout: args?.timeout,
|
|
2731
|
+
llmProvider: args?.llmProvider,
|
|
2732
|
+
llmApiKey: args?.llmApiKey,
|
|
2447
2733
|
needsInteractive
|
|
2448
2734
|
});
|
|
2449
|
-
const directory =
|
|
2735
|
+
const directory = args.directory || "src/";
|
|
2450
2736
|
if (needsInteractive && result) {
|
|
2451
2737
|
await init({
|
|
2452
2738
|
...result,
|
|
2453
2739
|
llmApiKey: result?.llmApiKey,
|
|
2454
|
-
components: ["agents", "tools", "workflows"],
|
|
2455
|
-
addExample: true
|
|
2740
|
+
components: ["agents", "tools", "workflows", "scorers"],
|
|
2741
|
+
addExample: true,
|
|
2742
|
+
versionTag: args.createVersionTag
|
|
2456
2743
|
});
|
|
2457
2744
|
postCreate({ projectName });
|
|
2458
2745
|
return;
|
|
2459
2746
|
}
|
|
2460
|
-
const { components = [], llmProvider = "openai", addExample = false, llmApiKey } =
|
|
2747
|
+
const { components = [], llmProvider = "openai", addExample = false, llmApiKey } = args;
|
|
2461
2748
|
await init({
|
|
2462
2749
|
directory,
|
|
2463
2750
|
components,
|
|
2464
2751
|
llmProvider,
|
|
2465
2752
|
addExample,
|
|
2466
2753
|
llmApiKey,
|
|
2467
|
-
configureEditorWithDocsMCP:
|
|
2754
|
+
configureEditorWithDocsMCP: args.mcpServer,
|
|
2755
|
+
versionTag: args.createVersionTag
|
|
2468
2756
|
});
|
|
2469
2757
|
postCreate({ projectName });
|
|
2470
2758
|
};
|
|
@@ -2555,9 +2843,9 @@ async function createFromGitHubUrl(url) {
|
|
|
2555
2843
|
workflows: []
|
|
2556
2844
|
};
|
|
2557
2845
|
}
|
|
2558
|
-
async function createFromTemplate(
|
|
2846
|
+
async function createFromTemplate(args) {
|
|
2559
2847
|
let selectedTemplate;
|
|
2560
|
-
if (
|
|
2848
|
+
if (args.template === true) {
|
|
2561
2849
|
const templates = await loadTemplates();
|
|
2562
2850
|
const selected = await selectTemplate(templates);
|
|
2563
2851
|
if (!selected) {
|
|
@@ -2565,26 +2853,26 @@ async function createFromTemplate(args2) {
|
|
|
2565
2853
|
return;
|
|
2566
2854
|
}
|
|
2567
2855
|
selectedTemplate = selected;
|
|
2568
|
-
} else if (
|
|
2569
|
-
if (isGitHubUrl(
|
|
2570
|
-
const
|
|
2571
|
-
|
|
2572
|
-
const validation = await validateGitHubProject(
|
|
2856
|
+
} else if (args.template && typeof args.template === "string") {
|
|
2857
|
+
if (isGitHubUrl(args.template)) {
|
|
2858
|
+
const spinner4 = Y();
|
|
2859
|
+
spinner4.start("Validating GitHub repository...");
|
|
2860
|
+
const validation = await validateGitHubProject(args.template);
|
|
2573
2861
|
if (!validation.isValid) {
|
|
2574
|
-
|
|
2862
|
+
spinner4.stop("Validation failed");
|
|
2575
2863
|
M.error("This does not appear to be a valid Mastra project:");
|
|
2576
2864
|
validation.errors.forEach((error) => M.error(` - ${error}`));
|
|
2577
2865
|
throw new Error("Invalid Mastra project");
|
|
2578
2866
|
}
|
|
2579
|
-
|
|
2580
|
-
selectedTemplate = await createFromGitHubUrl(
|
|
2867
|
+
spinner4.stop("Valid Mastra project \u2713");
|
|
2868
|
+
selectedTemplate = await createFromGitHubUrl(args.template);
|
|
2581
2869
|
} else {
|
|
2582
2870
|
const templates = await loadTemplates();
|
|
2583
|
-
const found = findTemplateByName(templates,
|
|
2871
|
+
const found = findTemplateByName(templates, args.template);
|
|
2584
2872
|
if (!found) {
|
|
2585
|
-
M.error(`Template "${
|
|
2873
|
+
M.error(`Template "${args.template}" not found. Available templates:`);
|
|
2586
2874
|
templates.forEach((t) => M.info(` - ${t.title} (use: ${t.slug.replace("template-", "")})`));
|
|
2587
|
-
throw new Error(`Template "${
|
|
2875
|
+
throw new Error(`Template "${args.template}" not found`);
|
|
2588
2876
|
}
|
|
2589
2877
|
selectedTemplate = found;
|
|
2590
2878
|
}
|
|
@@ -2592,7 +2880,7 @@ async function createFromTemplate(args2) {
|
|
|
2592
2880
|
if (!selectedTemplate) {
|
|
2593
2881
|
throw new Error("No template selected");
|
|
2594
2882
|
}
|
|
2595
|
-
let projectName =
|
|
2883
|
+
let projectName = args.projectName;
|
|
2596
2884
|
if (!projectName) {
|
|
2597
2885
|
const defaultName = getDefaultProjectName(selectedTemplate);
|
|
2598
2886
|
const response = await he({
|
|
@@ -2606,19 +2894,61 @@ async function createFromTemplate(args2) {
|
|
|
2606
2894
|
}
|
|
2607
2895
|
projectName = response;
|
|
2608
2896
|
}
|
|
2897
|
+
let llmProvider = args.llmProvider;
|
|
2898
|
+
if (!llmProvider) {
|
|
2899
|
+
const providerResponse = await ve({
|
|
2900
|
+
message: "Select a default provider:",
|
|
2901
|
+
options: LLM_PROVIDERS
|
|
2902
|
+
});
|
|
2903
|
+
if (pD(providerResponse)) {
|
|
2904
|
+
M.info("Project creation cancelled.");
|
|
2905
|
+
return;
|
|
2906
|
+
}
|
|
2907
|
+
llmProvider = providerResponse;
|
|
2908
|
+
}
|
|
2909
|
+
let initGit = false;
|
|
2910
|
+
const gitConfirmResult = await ye({
|
|
2911
|
+
message: "Initialize a new git repository?",
|
|
2912
|
+
initialValue: true
|
|
2913
|
+
});
|
|
2914
|
+
if (!pD(gitConfirmResult)) {
|
|
2915
|
+
initGit = gitConfirmResult;
|
|
2916
|
+
}
|
|
2917
|
+
let projectPath = null;
|
|
2609
2918
|
try {
|
|
2610
|
-
const analytics =
|
|
2919
|
+
const analytics = args.injectedAnalytics || getAnalytics();
|
|
2611
2920
|
if (analytics) {
|
|
2612
2921
|
analytics.trackEvent("cli_template_used", {
|
|
2613
2922
|
template_slug: selectedTemplate.slug,
|
|
2614
2923
|
template_title: selectedTemplate.title
|
|
2615
2924
|
});
|
|
2925
|
+
if (llmProvider) {
|
|
2926
|
+
analytics.trackEvent("cli_model_provider_selected", {
|
|
2927
|
+
provider: llmProvider,
|
|
2928
|
+
selection_method: args.llmProvider ? "cli_args" : "interactive"
|
|
2929
|
+
});
|
|
2930
|
+
}
|
|
2616
2931
|
}
|
|
2617
|
-
const
|
|
2932
|
+
const isBeta = version$1?.includes("beta") ?? false;
|
|
2933
|
+
const isMastraTemplate = selectedTemplate.githubUrl.includes("github.com/mastra-ai/");
|
|
2934
|
+
const branch = isBeta && isMastraTemplate ? "beta" : void 0;
|
|
2935
|
+
projectPath = await cloneTemplate({
|
|
2618
2936
|
template: selectedTemplate,
|
|
2619
|
-
projectName
|
|
2937
|
+
projectName,
|
|
2938
|
+
branch,
|
|
2939
|
+
llmProvider
|
|
2620
2940
|
});
|
|
2621
2941
|
await installDependencies(projectPath);
|
|
2942
|
+
if (initGit) {
|
|
2943
|
+
const s2 = Y();
|
|
2944
|
+
try {
|
|
2945
|
+
s2.start("Initializing git repository");
|
|
2946
|
+
await gitInit({ cwd: projectPath });
|
|
2947
|
+
s2.stop("Git repository initialized");
|
|
2948
|
+
} catch {
|
|
2949
|
+
s2.stop();
|
|
2950
|
+
}
|
|
2951
|
+
}
|
|
2622
2952
|
Me(`
|
|
2623
2953
|
${color2.green("Mastra template installed!")}
|
|
2624
2954
|
|
|
@@ -2627,6 +2957,17 @@ async function createFromTemplate(args2) {
|
|
|
2627
2957
|
`);
|
|
2628
2958
|
postCreate({ projectName });
|
|
2629
2959
|
} catch (error) {
|
|
2960
|
+
if (projectPath) {
|
|
2961
|
+
try {
|
|
2962
|
+
if (fs3__default__default.existsSync(projectPath)) {
|
|
2963
|
+
await fs4.rm(projectPath, { recursive: true, force: true });
|
|
2964
|
+
}
|
|
2965
|
+
} catch (cleanupError) {
|
|
2966
|
+
console.error(
|
|
2967
|
+
`Warning: Failed to clean up project directory: ${cleanupError instanceof Error ? cleanupError.message : "Unknown error"}`
|
|
2968
|
+
);
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2630
2971
|
M.error(`Failed to create project from template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2631
2972
|
throw error;
|
|
2632
2973
|
}
|
|
@@ -2635,7 +2976,7 @@ async function createFromTemplate(args2) {
|
|
|
2635
2976
|
async function getPackageVersion() {
|
|
2636
2977
|
const __filename = fileURLToPath(import.meta.url);
|
|
2637
2978
|
const __dirname = dirname(__filename);
|
|
2638
|
-
const pkgJsonPath =
|
|
2979
|
+
const pkgJsonPath = path3.join(__dirname, "..", "package.json");
|
|
2639
2980
|
const content = await fsExtra$1.readJSON(pkgJsonPath);
|
|
2640
2981
|
return content.version;
|
|
2641
2982
|
}
|
|
@@ -2673,7 +3014,7 @@ program.version(`${version}`, "-v, --version").description(`create-mastra ${vers
|
|
|
2673
3014
|
program.name("create-mastra").description("Create a new Mastra project").argument("[project-name]", "Directory name of the project").option(
|
|
2674
3015
|
"-p, --project-name <string>",
|
|
2675
3016
|
"Project name that will be used in package.json and as the project directory name."
|
|
2676
|
-
).option("--default", "Quick start with defaults (src, OpenAI, examples)").option("-c, --components <components>", "Comma-separated list of components (agents, tools, workflows)").option("-l, --llm <model-provider>", "Default model provider (openai, anthropic, groq, google, or cerebras)").option("-k, --llm-api-key <api-key>", "API key for the model provider").option("-e, --example", "Include example code").option("-n, --no-example", "Do not include example code").option("-t, --timeout [timeout]", "Configurable timeout for package installation, defaults to 60000 ms").option("-d, --dir <directory>", "Target directory for Mastra source code (default: src/)").option("-m, --mcp <mcp>", "MCP Server for code editor (cursor, cursor-global, windsurf, vscode)").option(
|
|
3017
|
+
).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(
|
|
2677
3018
|
"--template [template-name]",
|
|
2678
3019
|
"Create project from a template (use template name, public GitHub URL, or leave blank to select from list)"
|
|
2679
3020
|
).action(async (projectNameArg, args) => {
|
|
@@ -2681,7 +3022,7 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
|
|
|
2681
3022
|
const timeout = args?.timeout ? args?.timeout === true ? 6e4 : parseInt(args?.timeout, 10) : void 0;
|
|
2682
3023
|
if (args.default) {
|
|
2683
3024
|
await create({
|
|
2684
|
-
components: ["agents", "tools", "workflows"],
|
|
3025
|
+
components: ["agents", "tools", "workflows", "scorers"],
|
|
2685
3026
|
llmProvider: "openai",
|
|
2686
3027
|
addExample: true,
|
|
2687
3028
|
createVersionTag,
|