create-mastra 0.0.0-scorers-ui-refactored-20250916094952 → 0.0.0-scorers-logs-20251208093427
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 +467 -1
- package/README.md +10 -32
- package/dist/index.js +870 -530
- package/dist/index.js.map +1 -1
- package/dist/starter-files/tools.ts +2 -2
- package/dist/templates/dev.entry.js +4 -42
- package/package.json +14 -14
package/dist/index.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
#! /usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
|
-
import * as
|
|
5
|
-
import
|
|
4
|
+
import * as fs3__default from 'node:fs';
|
|
5
|
+
import fs3__default__default, { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
6
6
|
import os from 'node:os';
|
|
7
7
|
import path3, { dirname } from 'node:path';
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
9
|
import { PostHog } from 'posthog-node';
|
|
10
|
+
import fs4 from 'node:fs/promises';
|
|
10
11
|
import util, { stripVTControlCharacters } from 'node:util';
|
|
11
12
|
import y$1, { stdout, stdin } from 'node:process';
|
|
12
13
|
import * as g from 'node:readline';
|
|
13
14
|
import g__default from 'node:readline';
|
|
14
15
|
import { Writable } from 'node:stream';
|
|
15
|
-
import fs5 from 'node:fs/promises';
|
|
16
16
|
import child_process from 'node:child_process';
|
|
17
17
|
import tty from 'node:tty';
|
|
18
|
-
import pino from 'pino';
|
|
19
|
-
import pretty from 'pino-pretty';
|
|
20
|
-
import { execa } from 'execa';
|
|
21
18
|
import fsExtra, { readJSON, ensureFile, writeJSON } from 'fs-extra/esm';
|
|
22
19
|
import prettier from 'prettier';
|
|
20
|
+
import { execa } from 'execa';
|
|
23
21
|
import fsExtra$1 from 'fs-extra';
|
|
22
|
+
import pino from 'pino';
|
|
23
|
+
import pretty from 'pino-pretty';
|
|
24
24
|
|
|
25
25
|
var __filename = fileURLToPath(import.meta.url);
|
|
26
26
|
var __dirname = path3.dirname(__filename);
|
|
@@ -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(`
|
|
@@ -422,7 +427,7 @@ ${color2.gray(d)} ${t}
|
|
|
422
427
|
`):process.stdout.write(`${w} ${l}
|
|
423
428
|
`),E(),s();};return {start:H,stop:N,message:(m="")=>{l=R(m??l);}}},Ce=async(t,n)=>{const r={},i=Object.keys(t);for(const s of i){const c=t[s],a=await c({results:r})?.catch(l=>{throw l});if(typeof n?.onCancel=="function"&&pD(a)){r[s]="canceled",n.onCancel({results:r});continue}r[s]=a;}return r};
|
|
424
429
|
|
|
425
|
-
var shellQuote
|
|
430
|
+
var shellQuote = {};
|
|
426
431
|
|
|
427
432
|
var quote;
|
|
428
433
|
var hasRequiredQuote;
|
|
@@ -688,16 +693,16 @@ function requireParse () {
|
|
|
688
693
|
var hasRequiredShellQuote;
|
|
689
694
|
|
|
690
695
|
function requireShellQuote () {
|
|
691
|
-
if (hasRequiredShellQuote) return shellQuote
|
|
696
|
+
if (hasRequiredShellQuote) return shellQuote;
|
|
692
697
|
hasRequiredShellQuote = 1;
|
|
693
698
|
|
|
694
|
-
shellQuote
|
|
695
|
-
shellQuote
|
|
696
|
-
return shellQuote
|
|
699
|
+
shellQuote.quote = requireQuote();
|
|
700
|
+
shellQuote.parse = requireParse();
|
|
701
|
+
return shellQuote;
|
|
697
702
|
}
|
|
698
703
|
|
|
699
704
|
var shellQuoteExports = requireShellQuote();
|
|
700
|
-
var
|
|
705
|
+
var shellQuote2 = /*@__PURE__*/getDefaultExportFromCjs(shellQuoteExports);
|
|
701
706
|
|
|
702
707
|
// eslint-disable-next-line no-warning-comments
|
|
703
708
|
// TODO: Use a better method when it's added to Node.js (https://github.com/nodejs/node/pull/40240)
|
|
@@ -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,183 +1230,8 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1173
1230
|
}
|
|
1174
1231
|
};
|
|
1175
1232
|
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
const execPath = process.env.npm_execpath || "";
|
|
1179
|
-
if (userAgent.includes("yarn")) {
|
|
1180
|
-
return "yarn";
|
|
1181
|
-
}
|
|
1182
|
-
if (userAgent.includes("pnpm")) {
|
|
1183
|
-
return "pnpm";
|
|
1184
|
-
}
|
|
1185
|
-
if (userAgent.includes("npm")) {
|
|
1186
|
-
return "npm";
|
|
1187
|
-
}
|
|
1188
|
-
if (execPath.includes("yarn")) {
|
|
1189
|
-
return "yarn";
|
|
1190
|
-
}
|
|
1191
|
-
if (execPath.includes("pnpm")) {
|
|
1192
|
-
return "pnpm";
|
|
1193
|
-
}
|
|
1194
|
-
if (execPath.includes("npm")) {
|
|
1195
|
-
return "npm";
|
|
1196
|
-
}
|
|
1197
|
-
return "npm";
|
|
1198
|
-
}
|
|
1199
|
-
var logger = new PinoLogger({
|
|
1200
|
-
name: "Mastra CLI",
|
|
1201
|
-
level: "info"
|
|
1202
|
-
});
|
|
1203
|
-
var exec = util.promisify(child_process.exec);
|
|
1204
|
-
async function cloneTemplate(options) {
|
|
1205
|
-
const { template, projectName, targetDir } = options;
|
|
1206
|
-
const projectPath = targetDir ? path3.resolve(targetDir, projectName) : path3.resolve(projectName);
|
|
1207
|
-
const spinner5 = yoctoSpinner({ text: `Cloning template "${template.title}"...` }).start();
|
|
1208
|
-
try {
|
|
1209
|
-
if (await directoryExists(projectPath)) {
|
|
1210
|
-
spinner5.error(`Directory ${projectName} already exists`);
|
|
1211
|
-
throw new Error(`Directory ${projectName} already exists`);
|
|
1212
|
-
}
|
|
1213
|
-
await cloneRepositoryWithoutGit(template.githubUrl, projectPath);
|
|
1214
|
-
await updatePackageJson(projectPath, projectName);
|
|
1215
|
-
const envExamplePath = path3.join(projectPath, ".env.example");
|
|
1216
|
-
if (await fileExists(envExamplePath)) {
|
|
1217
|
-
await fs5.copyFile(envExamplePath, path3.join(projectPath, ".env"));
|
|
1218
|
-
}
|
|
1219
|
-
spinner5.success(`Template "${template.title}" cloned successfully to ${projectName}`);
|
|
1220
|
-
return projectPath;
|
|
1221
|
-
} catch (error) {
|
|
1222
|
-
spinner5.error(`Failed to clone template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1223
|
-
throw error;
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
async function directoryExists(dirPath) {
|
|
1227
|
-
try {
|
|
1228
|
-
const stat = await fs5.stat(dirPath);
|
|
1229
|
-
return stat.isDirectory();
|
|
1230
|
-
} catch {
|
|
1231
|
-
return false;
|
|
1232
|
-
}
|
|
1233
|
-
}
|
|
1234
|
-
async function fileExists(filePath) {
|
|
1235
|
-
try {
|
|
1236
|
-
const stat = await fs5.stat(filePath);
|
|
1237
|
-
return stat.isFile();
|
|
1238
|
-
} catch {
|
|
1239
|
-
return false;
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
async function cloneRepositoryWithoutGit(repoUrl, targetPath) {
|
|
1243
|
-
await fs5.mkdir(targetPath, { recursive: true });
|
|
1244
|
-
try {
|
|
1245
|
-
const degitRepo = repoUrl.replace("https://github.com/", "");
|
|
1246
|
-
const degitCommand = shellQuote.quote(["npx", "degit", degitRepo, targetPath]);
|
|
1247
|
-
await exec(degitCommand, {
|
|
1248
|
-
cwd: process.cwd()
|
|
1249
|
-
});
|
|
1250
|
-
} catch {
|
|
1251
|
-
try {
|
|
1252
|
-
const gitCommand = shellQuote.quote(["git", "clone", repoUrl, targetPath]);
|
|
1253
|
-
await exec(gitCommand, {
|
|
1254
|
-
cwd: process.cwd()
|
|
1255
|
-
});
|
|
1256
|
-
const gitDir = path3.join(targetPath, ".git");
|
|
1257
|
-
if (await directoryExists(gitDir)) {
|
|
1258
|
-
await fs5.rm(gitDir, { recursive: true, force: true });
|
|
1259
|
-
}
|
|
1260
|
-
} catch (gitError) {
|
|
1261
|
-
throw new Error(`Failed to clone repository: ${gitError instanceof Error ? gitError.message : "Unknown error"}`);
|
|
1262
|
-
}
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
async function updatePackageJson(projectPath, projectName) {
|
|
1266
|
-
const packageJsonPath = path3.join(projectPath, "package.json");
|
|
1267
|
-
try {
|
|
1268
|
-
const packageJsonContent = await fs5.readFile(packageJsonPath, "utf-8");
|
|
1269
|
-
const packageJson = JSON.parse(packageJsonContent);
|
|
1270
|
-
packageJson.name = projectName;
|
|
1271
|
-
await fs5.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf-8");
|
|
1272
|
-
} catch (error) {
|
|
1273
|
-
logger.warn(`Could not update package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1274
|
-
}
|
|
1275
|
-
}
|
|
1276
|
-
async function installDependencies(projectPath, packageManager) {
|
|
1277
|
-
const spinner5 = yoctoSpinner({ text: "Installing dependencies..." }).start();
|
|
1278
|
-
try {
|
|
1279
|
-
const pm = packageManager || getPackageManager();
|
|
1280
|
-
const installCommand = shellQuote.quote([pm, "install"]);
|
|
1281
|
-
await exec(installCommand, {
|
|
1282
|
-
cwd: projectPath
|
|
1283
|
-
});
|
|
1284
|
-
spinner5.success("Dependencies installed successfully");
|
|
1285
|
-
} catch (error) {
|
|
1286
|
-
spinner5.error(`Failed to install dependencies: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1287
|
-
throw error;
|
|
1288
|
-
}
|
|
1289
|
-
}
|
|
1290
|
-
var TEMPLATES_API_URL = process.env.MASTRA_TEMPLATES_API_URL || "https://mastra.ai/api/templates.json";
|
|
1291
|
-
async function loadTemplates() {
|
|
1292
|
-
try {
|
|
1293
|
-
const response = await fetch(TEMPLATES_API_URL);
|
|
1294
|
-
if (!response.ok) {
|
|
1295
|
-
throw new Error(`Failed to fetch templates: ${response.statusText}`);
|
|
1296
|
-
}
|
|
1297
|
-
const templates = await response.json();
|
|
1298
|
-
return templates;
|
|
1299
|
-
} catch (error) {
|
|
1300
|
-
console.error("Error loading templates:", error);
|
|
1301
|
-
throw new Error("Failed to load templates. Please check your internet connection and try again.");
|
|
1302
|
-
}
|
|
1303
|
-
}
|
|
1304
|
-
function pluralize(count, singular, plural) {
|
|
1305
|
-
return count === 1 ? singular : plural || `${singular}s`;
|
|
1306
|
-
}
|
|
1307
|
-
async function selectTemplate(templates) {
|
|
1308
|
-
const choices = templates.map((template) => {
|
|
1309
|
-
const parts = [];
|
|
1310
|
-
if (template.agents?.length) {
|
|
1311
|
-
parts.push(`${template.agents.length} ${pluralize(template.agents.length, "agent")}`);
|
|
1312
|
-
}
|
|
1313
|
-
if (template.tools?.length) {
|
|
1314
|
-
parts.push(`${template.tools.length} ${pluralize(template.tools.length, "tool")}`);
|
|
1315
|
-
}
|
|
1316
|
-
if (template.workflows?.length) {
|
|
1317
|
-
parts.push(`${template.workflows.length} ${pluralize(template.workflows.length, "workflow")}`);
|
|
1318
|
-
}
|
|
1319
|
-
if (template.mcp?.length) {
|
|
1320
|
-
parts.push(`${template.mcp.length} ${pluralize(template.mcp.length, "MCP server")}`);
|
|
1321
|
-
}
|
|
1322
|
-
if (template.networks?.length) {
|
|
1323
|
-
parts.push(`${template.networks.length} ${pluralize(template.networks.length, "agent network")}`);
|
|
1324
|
-
}
|
|
1325
|
-
return {
|
|
1326
|
-
value: template,
|
|
1327
|
-
label: template.title,
|
|
1328
|
-
hint: parts.join(", ") || "Template components"
|
|
1329
|
-
};
|
|
1330
|
-
});
|
|
1331
|
-
const selected = await ve({
|
|
1332
|
-
message: "Select a template:",
|
|
1333
|
-
options: choices
|
|
1334
|
-
});
|
|
1335
|
-
if (pD(selected)) {
|
|
1336
|
-
return null;
|
|
1337
|
-
}
|
|
1338
|
-
return selected;
|
|
1339
|
-
}
|
|
1340
|
-
function findTemplateByName(templates, templateName) {
|
|
1341
|
-
let template = templates.find((t) => t.slug === templateName);
|
|
1342
|
-
if (template) return template;
|
|
1343
|
-
const slugWithPrefix = `template-${templateName}`;
|
|
1344
|
-
template = templates.find((t) => t.slug === slugWithPrefix);
|
|
1345
|
-
if (template) return template;
|
|
1346
|
-
template = templates.find((t) => t.title.toLowerCase() === templateName.toLowerCase());
|
|
1347
|
-
if (template) return template;
|
|
1348
|
-
return null;
|
|
1349
|
-
}
|
|
1350
|
-
function getDefaultProjectName(template) {
|
|
1351
|
-
return template.slug.replace(/^template-/, "");
|
|
1352
|
-
}
|
|
1233
|
+
var package_default = {
|
|
1234
|
+
version: "1.0.0-beta.6"};
|
|
1353
1235
|
function getPackageManagerAddCommand(pm) {
|
|
1354
1236
|
switch (pm) {
|
|
1355
1237
|
case "npm":
|
|
@@ -1372,7 +1254,7 @@ var DepsService = class {
|
|
|
1372
1254
|
findLockFile(dir) {
|
|
1373
1255
|
const lockFiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lock"];
|
|
1374
1256
|
for (const file of lockFiles) {
|
|
1375
|
-
if (
|
|
1257
|
+
if (fs3__default__default.existsSync(path3.join(dir, file))) {
|
|
1376
1258
|
return file;
|
|
1377
1259
|
}
|
|
1378
1260
|
}
|
|
@@ -1411,11 +1293,11 @@ var DepsService = class {
|
|
|
1411
1293
|
try {
|
|
1412
1294
|
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1413
1295
|
try {
|
|
1414
|
-
await
|
|
1296
|
+
await fs4.access(packageJsonPath);
|
|
1415
1297
|
} catch {
|
|
1416
1298
|
return "No package.json file found in the current directory";
|
|
1417
1299
|
}
|
|
1418
|
-
const packageJson = JSON.parse(await
|
|
1300
|
+
const packageJson = JSON.parse(await fs4.readFile(packageJsonPath, "utf-8"));
|
|
1419
1301
|
for (const dependency of dependencies) {
|
|
1420
1302
|
if (!packageJson.dependencies || !packageJson.dependencies[dependency]) {
|
|
1421
1303
|
return `Please install ${dependency} before running this command (${this.packageManager} install ${dependency})`;
|
|
@@ -1430,7 +1312,7 @@ var DepsService = class {
|
|
|
1430
1312
|
async getProjectName() {
|
|
1431
1313
|
try {
|
|
1432
1314
|
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1433
|
-
const packageJson = await
|
|
1315
|
+
const packageJson = await fs4.readFile(packageJsonPath, "utf-8");
|
|
1434
1316
|
const pkg = JSON.parse(packageJson);
|
|
1435
1317
|
return pkg.name;
|
|
1436
1318
|
} catch (err) {
|
|
@@ -1438,149 +1320,37 @@ var DepsService = class {
|
|
|
1438
1320
|
}
|
|
1439
1321
|
}
|
|
1440
1322
|
async addScriptsToPackageJson(scripts) {
|
|
1441
|
-
const packageJson = JSON.parse(await
|
|
1323
|
+
const packageJson = JSON.parse(await fs4.readFile("package.json", "utf-8"));
|
|
1442
1324
|
packageJson.scripts = {
|
|
1443
1325
|
...packageJson.scripts,
|
|
1444
1326
|
...scripts
|
|
1445
1327
|
};
|
|
1446
|
-
await
|
|
1328
|
+
await fs4.writeFile("package.json", JSON.stringify(packageJson, null, 2));
|
|
1447
1329
|
}
|
|
1448
1330
|
};
|
|
1449
|
-
var
|
|
1450
|
-
var createMcpConfig = (editor) => {
|
|
1451
|
-
if (editor === "vscode") {
|
|
1452
|
-
return {
|
|
1453
|
-
servers: {
|
|
1454
|
-
mastra: process.platform === `win32` ? {
|
|
1455
|
-
command: "cmd",
|
|
1456
|
-
args: ["/c", "npx", ...args],
|
|
1457
|
-
type: "stdio"
|
|
1458
|
-
} : {
|
|
1459
|
-
command: "npx",
|
|
1460
|
-
args,
|
|
1461
|
-
type: "stdio"
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
};
|
|
1465
|
-
}
|
|
1466
|
-
return {
|
|
1467
|
-
mcpServers: {
|
|
1468
|
-
mastra: {
|
|
1469
|
-
command: "npx",
|
|
1470
|
-
args
|
|
1471
|
-
}
|
|
1472
|
-
}
|
|
1473
|
-
};
|
|
1331
|
+
var EnvService = class {
|
|
1474
1332
|
};
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
...original?.servers || {},
|
|
1481
|
-
...createMcpConfig(editor).servers
|
|
1482
|
-
}
|
|
1483
|
-
};
|
|
1484
|
-
}
|
|
1485
|
-
return {
|
|
1486
|
-
...original,
|
|
1487
|
-
mcpServers: {
|
|
1488
|
-
...original?.mcpServers || {},
|
|
1489
|
-
...createMcpConfig(editor).mcpServers
|
|
1490
|
-
}
|
|
1491
|
-
};
|
|
1492
|
-
}
|
|
1493
|
-
async function writeMergedConfig(configPath, editor) {
|
|
1494
|
-
const configExists = existsSync(configPath);
|
|
1495
|
-
const config = makeConfig(configExists ? await readJSON(configPath) : {}, editor);
|
|
1496
|
-
await ensureFile(configPath);
|
|
1497
|
-
await writeJSON(configPath, config, {
|
|
1498
|
-
spaces: 2
|
|
1499
|
-
});
|
|
1500
|
-
}
|
|
1501
|
-
var windsurfGlobalMCPConfigPath = path3.join(os.homedir(), ".codeium", "windsurf", "mcp_config.json");
|
|
1502
|
-
var cursorGlobalMCPConfigPath = path3.join(os.homedir(), ".cursor", "mcp.json");
|
|
1503
|
-
path3.join(process.cwd(), ".vscode", "mcp.json");
|
|
1504
|
-
var vscodeGlobalMCPConfigPath = path3.join(
|
|
1505
|
-
os.homedir(),
|
|
1506
|
-
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")
|
|
1507
|
-
);
|
|
1508
|
-
async function installMastraDocsMCPServer({ editor, directory }) {
|
|
1509
|
-
if (editor === `cursor`) {
|
|
1510
|
-
await writeMergedConfig(path3.join(directory, ".cursor", "mcp.json"), "cursor");
|
|
1511
|
-
}
|
|
1512
|
-
if (editor === `vscode`) {
|
|
1513
|
-
await writeMergedConfig(path3.join(directory, ".vscode", "mcp.json"), "vscode");
|
|
1333
|
+
var FileEnvService = class extends EnvService {
|
|
1334
|
+
filePath;
|
|
1335
|
+
constructor(filePath) {
|
|
1336
|
+
super();
|
|
1337
|
+
this.filePath = filePath;
|
|
1514
1338
|
}
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1339
|
+
readFile(filePath) {
|
|
1340
|
+
return new Promise((resolve, reject) => {
|
|
1341
|
+
fs3__default.readFile(filePath, "utf8", (err, data) => {
|
|
1342
|
+
if (err) reject(err);
|
|
1343
|
+
else resolve(data);
|
|
1344
|
+
});
|
|
1345
|
+
});
|
|
1521
1346
|
}
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
}
|
|
1530
|
-
async function globalMCPIsAlreadyInstalled(editor) {
|
|
1531
|
-
let configPath = ``;
|
|
1532
|
-
if (editor === "windsurf") {
|
|
1533
|
-
configPath = windsurfGlobalMCPConfigPath;
|
|
1534
|
-
} else if (editor === "cursor-global") {
|
|
1535
|
-
configPath = cursorGlobalMCPConfigPath;
|
|
1536
|
-
} else if (editor === "vscode") {
|
|
1537
|
-
configPath = vscodeGlobalMCPConfigPath;
|
|
1538
|
-
}
|
|
1539
|
-
if (!configPath || !existsSync(configPath)) {
|
|
1540
|
-
return false;
|
|
1541
|
-
}
|
|
1542
|
-
try {
|
|
1543
|
-
const configContents = await readJSON(configPath);
|
|
1544
|
-
if (!configContents) return false;
|
|
1545
|
-
if (editor === "vscode") {
|
|
1546
|
-
if (!configContents.servers) return false;
|
|
1547
|
-
const hasMastraMCP2 = Object.values(configContents.servers).some(
|
|
1548
|
-
(server) => server?.args?.find((arg) => arg?.includes(`@mastra/mcp-docs-server`))
|
|
1549
|
-
);
|
|
1550
|
-
return hasMastraMCP2;
|
|
1551
|
-
}
|
|
1552
|
-
if (!configContents?.mcpServers) return false;
|
|
1553
|
-
const hasMastraMCP = Object.values(configContents.mcpServers).some(
|
|
1554
|
-
(server) => server?.args?.find((arg) => arg?.includes(`@mastra/mcp-docs-server`))
|
|
1555
|
-
);
|
|
1556
|
-
return hasMastraMCP;
|
|
1557
|
-
} catch {
|
|
1558
|
-
return false;
|
|
1559
|
-
}
|
|
1560
|
-
}
|
|
1561
|
-
var EnvService = class {
|
|
1562
|
-
};
|
|
1563
|
-
var FileEnvService = class extends EnvService {
|
|
1564
|
-
filePath;
|
|
1565
|
-
constructor(filePath) {
|
|
1566
|
-
super();
|
|
1567
|
-
this.filePath = filePath;
|
|
1568
|
-
}
|
|
1569
|
-
readFile(filePath) {
|
|
1570
|
-
return new Promise((resolve, reject) => {
|
|
1571
|
-
fs4__default.readFile(filePath, "utf8", (err, data) => {
|
|
1572
|
-
if (err) reject(err);
|
|
1573
|
-
else resolve(data);
|
|
1574
|
-
});
|
|
1575
|
-
});
|
|
1576
|
-
}
|
|
1577
|
-
writeFile({ filePath, data }) {
|
|
1578
|
-
return new Promise((resolve, reject) => {
|
|
1579
|
-
fs4__default.writeFile(filePath, data, "utf8", (err) => {
|
|
1580
|
-
if (err) reject(err);
|
|
1581
|
-
else resolve();
|
|
1582
|
-
});
|
|
1583
|
-
});
|
|
1347
|
+
writeFile({ filePath, data }) {
|
|
1348
|
+
return new Promise((resolve, reject) => {
|
|
1349
|
+
fs3__default.writeFile(filePath, data, "utf8", (err) => {
|
|
1350
|
+
if (err) reject(err);
|
|
1351
|
+
else resolve();
|
|
1352
|
+
});
|
|
1353
|
+
});
|
|
1584
1354
|
}
|
|
1585
1355
|
async updateEnvData({
|
|
1586
1356
|
key,
|
|
@@ -1596,7 +1366,7 @@ var FileEnvService = class extends EnvService {
|
|
|
1596
1366
|
${key}=${value}`;
|
|
1597
1367
|
}
|
|
1598
1368
|
await this.writeFile({ filePath, data });
|
|
1599
|
-
console.
|
|
1369
|
+
console.info(`${key} set to ${value} in ENV file.`);
|
|
1600
1370
|
return data;
|
|
1601
1371
|
}
|
|
1602
1372
|
async getEnvValue(key) {
|
|
@@ -1631,9 +1401,9 @@ var FileService = class {
|
|
|
1631
1401
|
const __filename = fileURLToPath(import.meta.url);
|
|
1632
1402
|
const __dirname = path3.dirname(__filename);
|
|
1633
1403
|
const filePath = path3.resolve(__dirname, "starter-files", inputFile);
|
|
1634
|
-
const fileString =
|
|
1635
|
-
if (
|
|
1636
|
-
console.
|
|
1404
|
+
const fileString = fs3__default__default.readFileSync(filePath, "utf8");
|
|
1405
|
+
if (fs3__default__default.existsSync(outputFilePath) && !replaceIfExists) {
|
|
1406
|
+
console.info(`${outputFilePath} already exists`);
|
|
1637
1407
|
return false;
|
|
1638
1408
|
}
|
|
1639
1409
|
await fsExtra.outputFile(outputFilePath, fileString);
|
|
@@ -1647,7 +1417,7 @@ var FileService = class {
|
|
|
1647
1417
|
}
|
|
1648
1418
|
getFirstExistingFile(files) {
|
|
1649
1419
|
for (const f of files) {
|
|
1650
|
-
if (
|
|
1420
|
+
if (fs3__default__default.existsSync(f)) {
|
|
1651
1421
|
return f;
|
|
1652
1422
|
}
|
|
1653
1423
|
}
|
|
@@ -1657,66 +1427,152 @@ var FileService = class {
|
|
|
1657
1427
|
filePath,
|
|
1658
1428
|
replacements
|
|
1659
1429
|
}) {
|
|
1660
|
-
let fileContent =
|
|
1430
|
+
let fileContent = fs3__default__default.readFileSync(filePath, "utf8");
|
|
1661
1431
|
replacements.forEach(({ search, replace }) => {
|
|
1662
1432
|
fileContent = fileContent.replaceAll(search, replace);
|
|
1663
1433
|
});
|
|
1664
|
-
|
|
1434
|
+
fs3__default__default.writeFileSync(filePath, fileContent);
|
|
1665
1435
|
}
|
|
1666
1436
|
};
|
|
1667
|
-
var
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
case "cerebras":
|
|
1671
|
-
return "^0.2.14";
|
|
1672
|
-
default:
|
|
1673
|
-
return "^1.0.0";
|
|
1674
|
-
}
|
|
1437
|
+
var createArgs = (versionTag) => {
|
|
1438
|
+
const packageName = versionTag ? `@mastra/mcp-docs-server@${versionTag}` : "@mastra/mcp-docs-server";
|
|
1439
|
+
return ["-y", packageName];
|
|
1675
1440
|
};
|
|
1676
|
-
var
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
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
|
+
};
|
|
1692
1457
|
}
|
|
1458
|
+
return {
|
|
1459
|
+
mcpServers: {
|
|
1460
|
+
mastra: {
|
|
1461
|
+
command: "npx",
|
|
1462
|
+
args
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
};
|
|
1693
1466
|
};
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
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
|
+
}
|
|
1558
|
+
var exec = util.promisify(child_process.exec);
|
|
1559
|
+
var getModelIdentifier = (llmProvider) => {
|
|
1560
|
+
let model = "openai/gpt-4o";
|
|
1561
|
+
if (llmProvider === "anthropic") {
|
|
1562
|
+
model = "anthropic/claude-sonnet-4-5";
|
|
1703
1563
|
} else if (llmProvider === "groq") {
|
|
1704
|
-
|
|
1705
|
-
modelItem = `groq('llama-3.3-70b-versatile')`;
|
|
1564
|
+
model = "groq/llama-3.3-70b-versatile";
|
|
1706
1565
|
} else if (llmProvider === "google") {
|
|
1707
|
-
|
|
1708
|
-
modelItem = `google('gemini-2.5-pro')`;
|
|
1566
|
+
model = "google/gemini-2.5-pro";
|
|
1709
1567
|
} else if (llmProvider === "cerebras") {
|
|
1710
|
-
|
|
1711
|
-
modelItem = `cerebras('llama-3.3-70b')`;
|
|
1568
|
+
model = "cerebras/llama-3.3-70b";
|
|
1712
1569
|
} else if (llmProvider === "mistral") {
|
|
1713
|
-
|
|
1714
|
-
modelItem = `mistral('mistral-medium-2508')`;
|
|
1570
|
+
model = "mistral/mistral-medium-2508";
|
|
1715
1571
|
}
|
|
1716
|
-
return
|
|
1572
|
+
return model;
|
|
1717
1573
|
};
|
|
1718
|
-
async function writeAgentSample(llmProvider, destPath, addExampleTool) {
|
|
1719
|
-
const
|
|
1574
|
+
async function writeAgentSample(llmProvider, destPath, addExampleTool, addScorers) {
|
|
1575
|
+
const modelString = getModelIdentifier(llmProvider);
|
|
1720
1576
|
const instructions = `
|
|
1721
1577
|
You are a helpful weather assistant that provides accurate weather information and can help planning activities based on the weather.
|
|
1722
1578
|
|
|
@@ -1732,19 +1588,44 @@ async function writeAgentSample(llmProvider, destPath, addExampleTool) {
|
|
|
1732
1588
|
${addExampleTool ? "Use the weatherTool to fetch current weather data." : ""}
|
|
1733
1589
|
`;
|
|
1734
1590
|
const content = `
|
|
1735
|
-
${providerImport}
|
|
1736
1591
|
import { Agent } from '@mastra/core/agent';
|
|
1737
1592
|
import { Memory } from '@mastra/memory';
|
|
1738
1593
|
import { LibSQLStore } from '@mastra/libsql';
|
|
1739
1594
|
${addExampleTool ? `import { weatherTool } from '../tools/weather-tool';` : ""}
|
|
1595
|
+
${addScorers ? `import { scorers } from '../scorers/weather-scorer';` : ""}
|
|
1740
1596
|
|
|
1741
1597
|
export const weatherAgent = new Agent({
|
|
1598
|
+
id: 'weather-agent',
|
|
1742
1599
|
name: 'Weather Agent',
|
|
1743
1600
|
instructions: \`${instructions}\`,
|
|
1744
|
-
model: ${
|
|
1601
|
+
model: '${modelString}',
|
|
1745
1602
|
${addExampleTool ? "tools: { weatherTool }," : ""}
|
|
1603
|
+
${addScorers ? `scorers: {
|
|
1604
|
+
toolCallAppropriateness: {
|
|
1605
|
+
scorer: scorers.toolCallAppropriatenessScorer,
|
|
1606
|
+
sampling: {
|
|
1607
|
+
type: 'ratio',
|
|
1608
|
+
rate: 1,
|
|
1609
|
+
},
|
|
1610
|
+
},
|
|
1611
|
+
completeness: {
|
|
1612
|
+
scorer: scorers.completenessScorer,
|
|
1613
|
+
sampling: {
|
|
1614
|
+
type: 'ratio',
|
|
1615
|
+
rate: 1,
|
|
1616
|
+
},
|
|
1617
|
+
},
|
|
1618
|
+
translation: {
|
|
1619
|
+
scorer: scorers.translationScorer,
|
|
1620
|
+
sampling: {
|
|
1621
|
+
type: 'ratio',
|
|
1622
|
+
rate: 1,
|
|
1623
|
+
},
|
|
1624
|
+
},
|
|
1625
|
+
},` : ""}
|
|
1746
1626
|
memory: new Memory({
|
|
1747
1627
|
storage: new LibSQLStore({
|
|
1628
|
+
id: "memory-storage",
|
|
1748
1629
|
url: "file:../mastra.db", // path is relative to the .mastra/output directory
|
|
1749
1630
|
})
|
|
1750
1631
|
})
|
|
@@ -1754,8 +1635,8 @@ export const weatherAgent = new Agent({
|
|
|
1754
1635
|
parser: "typescript",
|
|
1755
1636
|
singleQuote: true
|
|
1756
1637
|
});
|
|
1757
|
-
await
|
|
1758
|
-
await
|
|
1638
|
+
await fs4.writeFile(destPath, "");
|
|
1639
|
+
await fs4.writeFile(destPath, formattedContent);
|
|
1759
1640
|
}
|
|
1760
1641
|
async function writeWorkflowSample(destPath) {
|
|
1761
1642
|
const content = `import { createStep, createWorkflow } from '@mastra/core/workflows';
|
|
@@ -1948,20 +1829,115 @@ export { weatherWorkflow };`;
|
|
|
1948
1829
|
semi: true,
|
|
1949
1830
|
singleQuote: true
|
|
1950
1831
|
});
|
|
1951
|
-
await
|
|
1832
|
+
await fs4.writeFile(destPath, formattedContent);
|
|
1952
1833
|
}
|
|
1953
1834
|
async function writeToolSample(destPath) {
|
|
1954
1835
|
const fileService = new FileService();
|
|
1955
1836
|
await fileService.copyStarterFile("tools.ts", destPath);
|
|
1956
1837
|
}
|
|
1838
|
+
async function writeScorersSample(llmProvider, destPath) {
|
|
1839
|
+
const modelString = getModelIdentifier(llmProvider);
|
|
1840
|
+
const content = `import { z } from 'zod';
|
|
1841
|
+
import { createToolCallAccuracyScorerCode } from '@mastra/evals/scorers/prebuilt';
|
|
1842
|
+
import { createCompletenessScorer } from '@mastra/evals/scorers/prebuilt';
|
|
1843
|
+
import { getAssistantMessageFromRunOutput, getUserMessageFromRunInput } from '@mastra/evals/scorers/utils';
|
|
1844
|
+
import { createScorer } from '@mastra/core/evals';
|
|
1845
|
+
|
|
1846
|
+
export const toolCallAppropriatenessScorer = createToolCallAccuracyScorerCode({
|
|
1847
|
+
expectedTool: 'weatherTool',
|
|
1848
|
+
strictMode: false,
|
|
1849
|
+
});
|
|
1850
|
+
|
|
1851
|
+
export const completenessScorer = createCompletenessScorer();
|
|
1852
|
+
|
|
1853
|
+
// Custom LLM-judged scorer: evaluates if non-English locations are translated appropriately
|
|
1854
|
+
export const translationScorer = createScorer({
|
|
1855
|
+
id: 'translation-quality-scorer',
|
|
1856
|
+
name: 'Translation Quality',
|
|
1857
|
+
description: 'Checks that non-English location names are translated and used correctly',
|
|
1858
|
+
type: 'agent',
|
|
1859
|
+
judge: {
|
|
1860
|
+
model: '${modelString}',
|
|
1861
|
+
instructions:
|
|
1862
|
+
'You are an expert evaluator of translation quality for geographic locations. ' +
|
|
1863
|
+
'Determine whether the user text mentions a non-English location and whether the assistant correctly uses an English translation of that location. ' +
|
|
1864
|
+
'Be lenient with transliteration differences and diacritics. ' +
|
|
1865
|
+
'Return only the structured JSON matching the provided schema.',
|
|
1866
|
+
},
|
|
1867
|
+
})
|
|
1868
|
+
.preprocess(({ run }) => {
|
|
1869
|
+
const userText = getUserMessageFromRunInput(run.input) || '';
|
|
1870
|
+
const assistantText = getAssistantMessageFromRunOutput(run.output) || '';
|
|
1871
|
+
return { userText, assistantText };
|
|
1872
|
+
})
|
|
1873
|
+
.analyze({
|
|
1874
|
+
description: 'Extract location names and detect language/translation adequacy',
|
|
1875
|
+
outputSchema: z.object({
|
|
1876
|
+
nonEnglish: z.boolean(),
|
|
1877
|
+
translated: z.boolean(),
|
|
1878
|
+
confidence: z.number().min(0).max(1).default(1),
|
|
1879
|
+
explanation: z.string().default(''),
|
|
1880
|
+
}),
|
|
1881
|
+
createPrompt: ({ results }) => \`
|
|
1882
|
+
You are evaluating if a weather assistant correctly handled translation of a non-English location.
|
|
1883
|
+
User text:
|
|
1884
|
+
"""
|
|
1885
|
+
\${results.preprocessStepResult.userText}
|
|
1886
|
+
"""
|
|
1887
|
+
Assistant response:
|
|
1888
|
+
"""
|
|
1889
|
+
\${results.preprocessStepResult.assistantText}
|
|
1890
|
+
"""
|
|
1891
|
+
Tasks:
|
|
1892
|
+
1) Identify if the user mentioned a location that appears non-English.
|
|
1893
|
+
2) If non-English, check whether the assistant used a correct English translation of that location in its response.
|
|
1894
|
+
3) Be lenient with transliteration differences (e.g., accents/diacritics).
|
|
1895
|
+
Return JSON with fields:
|
|
1896
|
+
{
|
|
1897
|
+
"nonEnglish": boolean,
|
|
1898
|
+
"translated": boolean,
|
|
1899
|
+
"confidence": number, // 0-1
|
|
1900
|
+
"explanation": string
|
|
1901
|
+
}
|
|
1902
|
+
\`,
|
|
1903
|
+
})
|
|
1904
|
+
.generateScore(({ results }) => {
|
|
1905
|
+
const r = (results as any)?.analyzeStepResult || {};
|
|
1906
|
+
if (!r.nonEnglish) return 1; // If not applicable, full credit
|
|
1907
|
+
if (r.translated) return Math.max(0, Math.min(1, 0.7 + 0.3 * (r.confidence ?? 1)));
|
|
1908
|
+
return 0; // Non-English but not translated
|
|
1909
|
+
})
|
|
1910
|
+
.generateReason(({ results, score }) => {
|
|
1911
|
+
const r = (results as any)?.analyzeStepResult || {};
|
|
1912
|
+
return \`Translation scoring: nonEnglish=\${r.nonEnglish ?? false}, translated=\${r.translated ?? false}, confidence=\${r.confidence ?? 0}. Score=\${score}. \${r.explanation ?? ''}\`;
|
|
1913
|
+
});
|
|
1914
|
+
|
|
1915
|
+
export const scorers = {
|
|
1916
|
+
toolCallAppropriatenessScorer,
|
|
1917
|
+
completenessScorer,
|
|
1918
|
+
translationScorer,
|
|
1919
|
+
};`;
|
|
1920
|
+
const formattedContent = await prettier.format(content, {
|
|
1921
|
+
parser: "typescript",
|
|
1922
|
+
singleQuote: true
|
|
1923
|
+
});
|
|
1924
|
+
await fs4.writeFile(destPath, formattedContent);
|
|
1925
|
+
}
|
|
1957
1926
|
async function writeCodeSampleForComponents(llmprovider, component, destPath, importComponents) {
|
|
1958
1927
|
switch (component) {
|
|
1959
1928
|
case "agents":
|
|
1960
|
-
return writeAgentSample(
|
|
1929
|
+
return writeAgentSample(
|
|
1930
|
+
llmprovider,
|
|
1931
|
+
destPath,
|
|
1932
|
+
importComponents.includes("tools"),
|
|
1933
|
+
importComponents.includes("scorers")
|
|
1934
|
+
);
|
|
1961
1935
|
case "tools":
|
|
1962
1936
|
return writeToolSample(destPath);
|
|
1963
1937
|
case "workflows":
|
|
1964
1938
|
return writeWorkflowSample(destPath);
|
|
1939
|
+
case "scorers":
|
|
1940
|
+
return writeScorersSample(llmprovider, destPath);
|
|
1965
1941
|
default:
|
|
1966
1942
|
return "";
|
|
1967
1943
|
}
|
|
@@ -1974,46 +1950,55 @@ var writeIndexFile = async ({
|
|
|
1974
1950
|
dirPath,
|
|
1975
1951
|
addAgent,
|
|
1976
1952
|
addExample,
|
|
1977
|
-
addWorkflow
|
|
1953
|
+
addWorkflow,
|
|
1954
|
+
addScorers
|
|
1978
1955
|
}) => {
|
|
1979
1956
|
const indexPath = dirPath + "/index.ts";
|
|
1980
1957
|
const destPath = path3.join(indexPath);
|
|
1981
1958
|
try {
|
|
1982
|
-
await
|
|
1959
|
+
await fs4.writeFile(destPath, "");
|
|
1983
1960
|
const filteredExports = [
|
|
1984
1961
|
addWorkflow ? `workflows: { weatherWorkflow },` : "",
|
|
1985
|
-
addAgent ? `agents: { weatherAgent },` : ""
|
|
1962
|
+
addAgent ? `agents: { weatherAgent },` : "",
|
|
1963
|
+
addScorers ? `scorers: { toolCallAppropriatenessScorer, completenessScorer, translationScorer },` : ""
|
|
1986
1964
|
].filter(Boolean);
|
|
1987
1965
|
if (!addExample) {
|
|
1988
|
-
await
|
|
1966
|
+
await fs4.writeFile(
|
|
1989
1967
|
destPath,
|
|
1990
1968
|
`
|
|
1991
|
-
import { Mastra } from '@mastra/core';
|
|
1969
|
+
import { Mastra } from '@mastra/core/mastra';
|
|
1992
1970
|
|
|
1993
1971
|
export const mastra = new Mastra()
|
|
1994
1972
|
`
|
|
1995
1973
|
);
|
|
1996
1974
|
return;
|
|
1997
1975
|
}
|
|
1998
|
-
await
|
|
1976
|
+
await fs4.writeFile(
|
|
1999
1977
|
destPath,
|
|
2000
1978
|
`
|
|
2001
1979
|
import { Mastra } from '@mastra/core/mastra';
|
|
2002
1980
|
import { PinoLogger } from '@mastra/loggers';
|
|
2003
1981
|
import { LibSQLStore } from '@mastra/libsql';
|
|
1982
|
+
import { Observability } from '@mastra/observability';
|
|
2004
1983
|
${addWorkflow ? `import { weatherWorkflow } from './workflows/weather-workflow';` : ""}
|
|
2005
1984
|
${addAgent ? `import { weatherAgent } from './agents/weather-agent';` : ""}
|
|
1985
|
+
${addScorers ? `import { toolCallAppropriatenessScorer, completenessScorer, translationScorer } from './scorers/weather-scorer';` : ""}
|
|
2006
1986
|
|
|
2007
1987
|
export const mastra = new Mastra({
|
|
2008
1988
|
${filteredExports.join("\n ")}
|
|
2009
1989
|
storage: new LibSQLStore({
|
|
2010
|
-
|
|
1990
|
+
id: "mastra-storage",
|
|
1991
|
+
// stores observability, scores, ... into memory storage, if it needs to persist, change to file:../mastra.db
|
|
2011
1992
|
url: ":memory:",
|
|
2012
1993
|
}),
|
|
2013
1994
|
logger: new PinoLogger({
|
|
2014
1995
|
name: 'Mastra',
|
|
2015
1996
|
level: 'info',
|
|
2016
1997
|
}),
|
|
1998
|
+
observability: new Observability({
|
|
1999
|
+
// Enables DefaultExporter and CloudExporter for tracing
|
|
2000
|
+
default: { enabled: true },
|
|
2001
|
+
}),
|
|
2017
2002
|
});
|
|
2018
2003
|
`
|
|
2019
2004
|
);
|
|
@@ -2021,7 +2006,6 @@ export const mastra = new Mastra({
|
|
|
2021
2006
|
throw err;
|
|
2022
2007
|
}
|
|
2023
2008
|
};
|
|
2024
|
-
yoctoSpinner({ text: "Installing Mastra core dependencies\n" });
|
|
2025
2009
|
var getAPIKey = async (provider) => {
|
|
2026
2010
|
let key = "OPENAI_API_KEY";
|
|
2027
2011
|
switch (provider) {
|
|
@@ -2044,20 +2028,18 @@ var getAPIKey = async (provider) => {
|
|
|
2044
2028
|
return key;
|
|
2045
2029
|
}
|
|
2046
2030
|
};
|
|
2047
|
-
var writeAPIKey = async ({
|
|
2048
|
-
|
|
2049
|
-
apiKey = "your-api-key"
|
|
2050
|
-
}) => {
|
|
2031
|
+
var writeAPIKey = async ({ provider, apiKey }) => {
|
|
2032
|
+
const envFileName = apiKey ? ".env" : ".env.example";
|
|
2051
2033
|
const key = await getAPIKey(provider);
|
|
2052
|
-
const escapedKey =
|
|
2053
|
-
const escapedApiKey =
|
|
2054
|
-
await
|
|
2034
|
+
const escapedKey = shellQuote2.quote([key]);
|
|
2035
|
+
const escapedApiKey = shellQuote2.quote([apiKey ? apiKey : "your-api-key"]);
|
|
2036
|
+
await exec(`echo ${escapedKey}=${escapedApiKey} >> ${envFileName}`);
|
|
2055
2037
|
};
|
|
2056
2038
|
var createMastraDir = async (directory) => {
|
|
2057
2039
|
let dir = directory.trim().split("/").filter((item) => item !== "");
|
|
2058
2040
|
const dirPath = path3.join(process.cwd(), ...dir, "mastra");
|
|
2059
2041
|
try {
|
|
2060
|
-
await
|
|
2042
|
+
await fs4.access(dirPath);
|
|
2061
2043
|
return { ok: false };
|
|
2062
2044
|
} catch {
|
|
2063
2045
|
await fsExtra.ensureDir(dirPath);
|
|
@@ -2072,8 +2054,19 @@ var writeCodeSample = async (dirPath, component, llmProvider, importComponents)
|
|
|
2072
2054
|
throw err;
|
|
2073
2055
|
}
|
|
2074
2056
|
};
|
|
2075
|
-
var
|
|
2076
|
-
|
|
2057
|
+
var LLM_PROVIDERS = [
|
|
2058
|
+
{ value: "openai", label: "OpenAI", hint: "recommended" },
|
|
2059
|
+
{ value: "anthropic", label: "Anthropic" },
|
|
2060
|
+
{ value: "groq", label: "Groq" },
|
|
2061
|
+
{ value: "google", label: "Google" },
|
|
2062
|
+
{ value: "cerebras", label: "Cerebras" },
|
|
2063
|
+
{ value: "mistral", label: "Mistral" }
|
|
2064
|
+
];
|
|
2065
|
+
var interactivePrompt = async (args = {}) => {
|
|
2066
|
+
const { skip = {}, options: { showBanner = true } = {} } = args;
|
|
2067
|
+
if (showBanner) {
|
|
2068
|
+
Ie(color2.inverse(" Mastra Init "));
|
|
2069
|
+
}
|
|
2077
2070
|
const mastraProject = await Ce(
|
|
2078
2071
|
{
|
|
2079
2072
|
directory: () => he({
|
|
@@ -2081,20 +2074,15 @@ var interactivePrompt = async () => {
|
|
|
2081
2074
|
placeholder: "src/",
|
|
2082
2075
|
defaultValue: "src/"
|
|
2083
2076
|
}),
|
|
2084
|
-
llmProvider: () => ve({
|
|
2085
|
-
message: "Select default provider:",
|
|
2086
|
-
options:
|
|
2087
|
-
{ value: "openai", label: "OpenAI", hint: "recommended" },
|
|
2088
|
-
{ value: "anthropic", label: "Anthropic" },
|
|
2089
|
-
{ value: "groq", label: "Groq" },
|
|
2090
|
-
{ value: "google", label: "Google" },
|
|
2091
|
-
{ value: "cerebras", label: "Cerebras" },
|
|
2092
|
-
{ value: "mistral", label: "Mistral" }
|
|
2093
|
-
]
|
|
2077
|
+
llmProvider: () => skip?.llmProvider ? void 0 : ve({
|
|
2078
|
+
message: "Select a default provider:",
|
|
2079
|
+
options: LLM_PROVIDERS
|
|
2094
2080
|
}),
|
|
2095
2081
|
llmApiKey: async ({ results: { llmProvider } }) => {
|
|
2082
|
+
if (skip?.llmApiKey) return void 0;
|
|
2083
|
+
const llmName = LLM_PROVIDERS.find((p6) => p6.value === llmProvider)?.label || "provider";
|
|
2096
2084
|
const keyChoice = await ve({
|
|
2097
|
-
message: `Enter your ${
|
|
2085
|
+
message: `Enter your ${llmName} API key?`,
|
|
2098
2086
|
options: [
|
|
2099
2087
|
{ value: "skip", label: "Skip for now", hint: "default" },
|
|
2100
2088
|
{ value: "enter", label: "Enter API key" }
|
|
@@ -2104,52 +2092,38 @@ var interactivePrompt = async () => {
|
|
|
2104
2092
|
if (keyChoice === "enter") {
|
|
2105
2093
|
return he({
|
|
2106
2094
|
message: "Enter your API key:",
|
|
2107
|
-
placeholder: "sk-..."
|
|
2095
|
+
placeholder: "sk-...",
|
|
2096
|
+
validate: (value) => {
|
|
2097
|
+
if (value.length === 0) return "API key cannot be empty";
|
|
2098
|
+
}
|
|
2108
2099
|
});
|
|
2109
2100
|
}
|
|
2110
2101
|
return void 0;
|
|
2111
2102
|
},
|
|
2112
2103
|
configureEditorWithDocsMCP: async () => {
|
|
2113
|
-
const windsurfIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`windsurf`);
|
|
2114
|
-
const cursorIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`cursor`);
|
|
2115
|
-
const vscodeIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`vscode`);
|
|
2116
2104
|
const editor = await ve({
|
|
2117
|
-
message: `Make your
|
|
2105
|
+
message: `Make your IDE into a Mastra expert? (Installs Mastra's MCP server)`,
|
|
2118
2106
|
options: [
|
|
2119
2107
|
{ value: "skip", label: "Skip for now", hint: "default" },
|
|
2120
2108
|
{
|
|
2121
2109
|
value: "cursor",
|
|
2122
|
-
label: "Cursor (project only)"
|
|
2123
|
-
hint: cursorIsAlreadyInstalled ? `Already installed globally` : void 0
|
|
2110
|
+
label: "Cursor (project only)"
|
|
2124
2111
|
},
|
|
2125
2112
|
{
|
|
2126
2113
|
value: "cursor-global",
|
|
2127
|
-
label: "Cursor (global, all projects)"
|
|
2128
|
-
hint: cursorIsAlreadyInstalled ? `Already installed` : void 0
|
|
2114
|
+
label: "Cursor (global, all projects)"
|
|
2129
2115
|
},
|
|
2130
2116
|
{
|
|
2131
2117
|
value: "windsurf",
|
|
2132
|
-
label: "Windsurf"
|
|
2133
|
-
hint: windsurfIsAlreadyInstalled ? `Already installed` : void 0
|
|
2118
|
+
label: "Windsurf"
|
|
2134
2119
|
},
|
|
2135
2120
|
{
|
|
2136
2121
|
value: "vscode",
|
|
2137
|
-
label: "VSCode"
|
|
2138
|
-
hint: vscodeIsAlreadyInstalled ? `Already installed` : void 0
|
|
2122
|
+
label: "VSCode"
|
|
2139
2123
|
}
|
|
2140
2124
|
]
|
|
2141
2125
|
});
|
|
2142
2126
|
if (editor === `skip`) return void 0;
|
|
2143
|
-
if (editor === `windsurf` && windsurfIsAlreadyInstalled) {
|
|
2144
|
-
M.message(`
|
|
2145
|
-
Windsurf is already installed, skipping.`);
|
|
2146
|
-
return void 0;
|
|
2147
|
-
}
|
|
2148
|
-
if (editor === `vscode` && vscodeIsAlreadyInstalled) {
|
|
2149
|
-
M.message(`
|
|
2150
|
-
VSCode is already installed, skipping.`);
|
|
2151
|
-
return void 0;
|
|
2152
|
-
}
|
|
2153
2127
|
if (editor === `cursor`) {
|
|
2154
2128
|
M.message(
|
|
2155
2129
|
`
|
|
@@ -2158,19 +2132,19 @@ Note: you will need to go into Cursor Settings -> MCP Settings and manually enab
|
|
|
2158
2132
|
);
|
|
2159
2133
|
}
|
|
2160
2134
|
if (editor === `cursor-global`) {
|
|
2161
|
-
const
|
|
2135
|
+
const confirm3 = await ve({
|
|
2162
2136
|
message: `Global install will add/update ${cursorGlobalMCPConfigPath} and make the Mastra docs MCP server available in all your Cursor projects. Continue?`,
|
|
2163
2137
|
options: [
|
|
2164
2138
|
{ value: "yes", label: "Yes, I understand" },
|
|
2165
2139
|
{ value: "skip", label: "No, skip for now" }
|
|
2166
2140
|
]
|
|
2167
2141
|
});
|
|
2168
|
-
if (
|
|
2142
|
+
if (confirm3 !== `yes`) {
|
|
2169
2143
|
return void 0;
|
|
2170
2144
|
}
|
|
2171
2145
|
}
|
|
2172
2146
|
if (editor === `windsurf`) {
|
|
2173
|
-
const
|
|
2147
|
+
const confirm3 = await ve({
|
|
2174
2148
|
message: `Windsurf only supports a global MCP config (at ${windsurfGlobalMCPConfigPath}) is it ok to add/update that global config?
|
|
2175
2149
|
This means the Mastra docs MCP server will be available in all your Windsurf projects.`,
|
|
2176
2150
|
options: [
|
|
@@ -2178,11 +2152,17 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
2178
2152
|
{ value: "skip", label: "No, skip for now" }
|
|
2179
2153
|
]
|
|
2180
2154
|
});
|
|
2181
|
-
if (
|
|
2155
|
+
if (confirm3 !== `yes`) {
|
|
2182
2156
|
return void 0;
|
|
2183
2157
|
}
|
|
2184
2158
|
}
|
|
2185
2159
|
return editor;
|
|
2160
|
+
},
|
|
2161
|
+
initGit: async () => {
|
|
2162
|
+
return ye({
|
|
2163
|
+
message: "Initialize a new git repository?",
|
|
2164
|
+
initialValue: true
|
|
2165
|
+
});
|
|
2186
2166
|
}
|
|
2187
2167
|
},
|
|
2188
2168
|
{
|
|
@@ -2194,17 +2174,245 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
2194
2174
|
);
|
|
2195
2175
|
return mastraProject;
|
|
2196
2176
|
};
|
|
2177
|
+
function getPackageManager() {
|
|
2178
|
+
const userAgent = process.env.npm_config_user_agent || "";
|
|
2179
|
+
const execPath = process.env.npm_execpath || "";
|
|
2180
|
+
if (userAgent.includes("bun")) {
|
|
2181
|
+
return "bun";
|
|
2182
|
+
}
|
|
2183
|
+
if (userAgent.includes("yarn")) {
|
|
2184
|
+
return "yarn";
|
|
2185
|
+
}
|
|
2186
|
+
if (userAgent.includes("pnpm")) {
|
|
2187
|
+
return "pnpm";
|
|
2188
|
+
}
|
|
2189
|
+
if (userAgent.includes("npm")) {
|
|
2190
|
+
return "npm";
|
|
2191
|
+
}
|
|
2192
|
+
if (execPath.includes("bun")) {
|
|
2193
|
+
return "bun";
|
|
2194
|
+
}
|
|
2195
|
+
if (execPath.includes("yarn")) {
|
|
2196
|
+
return "yarn";
|
|
2197
|
+
}
|
|
2198
|
+
if (execPath.includes("pnpm")) {
|
|
2199
|
+
return "pnpm";
|
|
2200
|
+
}
|
|
2201
|
+
if (execPath.includes("npm")) {
|
|
2202
|
+
return "npm";
|
|
2203
|
+
}
|
|
2204
|
+
return "npm";
|
|
2205
|
+
}
|
|
2206
|
+
async function gitInit({ cwd }) {
|
|
2207
|
+
await execa("git", ["init"], { cwd, stdio: "ignore" });
|
|
2208
|
+
await execa("git", ["add", "-A"], { cwd, stdio: "ignore" });
|
|
2209
|
+
await execa(
|
|
2210
|
+
"git",
|
|
2211
|
+
[
|
|
2212
|
+
"commit",
|
|
2213
|
+
"-m",
|
|
2214
|
+
'"Initial commit from Mastra"',
|
|
2215
|
+
'--author="dane-ai-mastra[bot] <dane-ai-mastra[bot]@users.noreply.github.com>"'
|
|
2216
|
+
],
|
|
2217
|
+
{ cwd, stdio: "ignore" }
|
|
2218
|
+
);
|
|
2219
|
+
}
|
|
2220
|
+
var logger = createLogger(false);
|
|
2221
|
+
function createLogger(debug = false) {
|
|
2222
|
+
return new PinoLogger({
|
|
2223
|
+
name: "Mastra CLI",
|
|
2224
|
+
level: debug ? "debug" : "info"
|
|
2225
|
+
});
|
|
2226
|
+
}
|
|
2227
|
+
var exec2 = util.promisify(child_process.exec);
|
|
2228
|
+
async function cloneTemplate(options) {
|
|
2229
|
+
const { template, projectName, targetDir, branch, llmProvider } = options;
|
|
2230
|
+
const projectPath = targetDir ? path3.resolve(targetDir, projectName) : path3.resolve(projectName);
|
|
2231
|
+
const spinner4 = yoctoSpinner({ text: `Cloning template "${template.title}"...` }).start();
|
|
2232
|
+
try {
|
|
2233
|
+
if (await directoryExists(projectPath)) {
|
|
2234
|
+
spinner4.error(`Directory ${projectName} already exists`);
|
|
2235
|
+
throw new Error(`Directory ${projectName} already exists`);
|
|
2236
|
+
}
|
|
2237
|
+
await cloneRepositoryWithoutGit(template.githubUrl, projectPath, branch);
|
|
2238
|
+
await updatePackageJson(projectPath, projectName);
|
|
2239
|
+
const envExamplePath = path3.join(projectPath, ".env.example");
|
|
2240
|
+
if (await fileExists(envExamplePath)) {
|
|
2241
|
+
const envPath = path3.join(projectPath, ".env");
|
|
2242
|
+
await fs4.copyFile(envExamplePath, envPath);
|
|
2243
|
+
if (llmProvider) {
|
|
2244
|
+
await updateEnvFile(envPath, llmProvider);
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
spinner4.success(`Template "${template.title}" cloned successfully to ${projectName}`);
|
|
2248
|
+
return projectPath;
|
|
2249
|
+
} catch (error) {
|
|
2250
|
+
spinner4.error(`Failed to clone template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2251
|
+
throw error;
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
async function directoryExists(dirPath) {
|
|
2255
|
+
try {
|
|
2256
|
+
const stat = await fs4.stat(dirPath);
|
|
2257
|
+
return stat.isDirectory();
|
|
2258
|
+
} catch {
|
|
2259
|
+
return false;
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2262
|
+
async function fileExists(filePath) {
|
|
2263
|
+
try {
|
|
2264
|
+
const stat = await fs4.stat(filePath);
|
|
2265
|
+
return stat.isFile();
|
|
2266
|
+
} catch {
|
|
2267
|
+
return false;
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
async function cloneRepositoryWithoutGit(repoUrl, targetPath, branch) {
|
|
2271
|
+
await fs4.mkdir(targetPath, { recursive: true });
|
|
2272
|
+
try {
|
|
2273
|
+
const degitRepo = repoUrl.replace("https://github.com/", "");
|
|
2274
|
+
const degitRepoWithBranch = branch ? `${degitRepo}#${branch}` : degitRepo;
|
|
2275
|
+
const degitCommand = shellQuote2.quote(["npx", "degit", degitRepoWithBranch, targetPath]);
|
|
2276
|
+
await exec2(degitCommand, {
|
|
2277
|
+
cwd: process.cwd()
|
|
2278
|
+
});
|
|
2279
|
+
} catch {
|
|
2280
|
+
try {
|
|
2281
|
+
const gitArgs = ["git", "clone"];
|
|
2282
|
+
if (branch) {
|
|
2283
|
+
gitArgs.push("--branch", branch);
|
|
2284
|
+
}
|
|
2285
|
+
gitArgs.push(repoUrl, targetPath);
|
|
2286
|
+
const gitCommand = shellQuote2.quote(gitArgs);
|
|
2287
|
+
await exec2(gitCommand, {
|
|
2288
|
+
cwd: process.cwd()
|
|
2289
|
+
});
|
|
2290
|
+
const gitDir = path3.join(targetPath, ".git");
|
|
2291
|
+
if (await directoryExists(gitDir)) {
|
|
2292
|
+
await fs4.rm(gitDir, { recursive: true, force: true });
|
|
2293
|
+
}
|
|
2294
|
+
} catch (gitError) {
|
|
2295
|
+
throw new Error(`Failed to clone repository: ${gitError instanceof Error ? gitError.message : "Unknown error"}`);
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
async function updatePackageJson(projectPath, projectName) {
|
|
2300
|
+
const packageJsonPath = path3.join(projectPath, "package.json");
|
|
2301
|
+
try {
|
|
2302
|
+
const packageJsonContent = await fs4.readFile(packageJsonPath, "utf-8");
|
|
2303
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
2304
|
+
packageJson.name = projectName;
|
|
2305
|
+
await fs4.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf-8");
|
|
2306
|
+
} catch (error) {
|
|
2307
|
+
logger.warn(`Could not update package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2310
|
+
async function updateEnvFile(envPath, llmProvider) {
|
|
2311
|
+
try {
|
|
2312
|
+
const envContent = await fs4.readFile(envPath, "utf-8");
|
|
2313
|
+
const modelString = getModelIdentifier(llmProvider);
|
|
2314
|
+
if (!modelString) {
|
|
2315
|
+
logger.warn(`Could not get model identifier for provider: ${llmProvider}`);
|
|
2316
|
+
return;
|
|
2317
|
+
}
|
|
2318
|
+
const modelValue = modelString.replace(/'/g, "");
|
|
2319
|
+
const updatedContent = envContent.replace(/^MODEL=.*/m, `MODEL=${modelValue}`);
|
|
2320
|
+
await fs4.writeFile(envPath, updatedContent, "utf-8");
|
|
2321
|
+
logger.info(`Updated MODEL in .env to ${modelValue}`);
|
|
2322
|
+
} catch (error) {
|
|
2323
|
+
logger.warn(`Could not update .env file: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2326
|
+
async function installDependencies(projectPath, packageManager) {
|
|
2327
|
+
const spinner4 = yoctoSpinner({ text: "Installing dependencies..." }).start();
|
|
2328
|
+
try {
|
|
2329
|
+
const pm = packageManager || getPackageManager();
|
|
2330
|
+
const installCommand = shellQuote2.quote([pm, "install"]);
|
|
2331
|
+
await exec2(installCommand, {
|
|
2332
|
+
cwd: projectPath
|
|
2333
|
+
});
|
|
2334
|
+
spinner4.success("Dependencies installed successfully");
|
|
2335
|
+
} catch (error) {
|
|
2336
|
+
spinner4.error(`Failed to install dependencies: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2337
|
+
throw error;
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
var TEMPLATES_API_URL = process.env.MASTRA_TEMPLATES_API_URL || "https://mastra.ai/api/templates.json";
|
|
2341
|
+
async function loadTemplates() {
|
|
2342
|
+
try {
|
|
2343
|
+
const response = await fetch(TEMPLATES_API_URL);
|
|
2344
|
+
if (!response.ok) {
|
|
2345
|
+
throw new Error(`Failed to fetch templates: ${response.statusText}`);
|
|
2346
|
+
}
|
|
2347
|
+
const templates = await response.json();
|
|
2348
|
+
return templates;
|
|
2349
|
+
} catch (error) {
|
|
2350
|
+
console.error("Error loading templates:", error);
|
|
2351
|
+
throw new Error("Failed to load templates. Please check your internet connection and try again.");
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
function pluralize(count, singular, plural) {
|
|
2355
|
+
return count === 1 ? singular : plural || `${singular}s`;
|
|
2356
|
+
}
|
|
2357
|
+
async function selectTemplate(templates) {
|
|
2358
|
+
const choices = templates.map((template) => {
|
|
2359
|
+
const parts = [];
|
|
2360
|
+
if (template.agents?.length) {
|
|
2361
|
+
parts.push(`${template.agents.length} ${pluralize(template.agents.length, "agent")}`);
|
|
2362
|
+
}
|
|
2363
|
+
if (template.tools?.length) {
|
|
2364
|
+
parts.push(`${template.tools.length} ${pluralize(template.tools.length, "tool")}`);
|
|
2365
|
+
}
|
|
2366
|
+
if (template.workflows?.length) {
|
|
2367
|
+
parts.push(`${template.workflows.length} ${pluralize(template.workflows.length, "workflow")}`);
|
|
2368
|
+
}
|
|
2369
|
+
if (template.mcp?.length) {
|
|
2370
|
+
parts.push(`${template.mcp.length} ${pluralize(template.mcp.length, "MCP server")}`);
|
|
2371
|
+
}
|
|
2372
|
+
if (template.networks?.length) {
|
|
2373
|
+
parts.push(`${template.networks.length} ${pluralize(template.networks.length, "agent network")}`);
|
|
2374
|
+
}
|
|
2375
|
+
return {
|
|
2376
|
+
value: template,
|
|
2377
|
+
label: template.title,
|
|
2378
|
+
hint: parts.join(", ") || "Template components"
|
|
2379
|
+
};
|
|
2380
|
+
});
|
|
2381
|
+
const selected = await ve({
|
|
2382
|
+
message: "Select a template:",
|
|
2383
|
+
options: choices
|
|
2384
|
+
});
|
|
2385
|
+
if (pD(selected)) {
|
|
2386
|
+
return null;
|
|
2387
|
+
}
|
|
2388
|
+
return selected;
|
|
2389
|
+
}
|
|
2390
|
+
function findTemplateByName(templates, templateName) {
|
|
2391
|
+
let template = templates.find((t) => t.slug === templateName);
|
|
2392
|
+
if (template) return template;
|
|
2393
|
+
const slugWithPrefix = `template-${templateName}`;
|
|
2394
|
+
template = templates.find((t) => t.slug === slugWithPrefix);
|
|
2395
|
+
if (template) return template;
|
|
2396
|
+
template = templates.find((t) => t.title.toLowerCase() === templateName.toLowerCase());
|
|
2397
|
+
if (template) return template;
|
|
2398
|
+
return null;
|
|
2399
|
+
}
|
|
2400
|
+
function getDefaultProjectName(template) {
|
|
2401
|
+
return template.slug.replace(/^template-/, "");
|
|
2402
|
+
}
|
|
2197
2403
|
var s = Y();
|
|
2198
|
-
var exec3 = util.promisify(child_process.exec);
|
|
2199
2404
|
var init = async ({
|
|
2200
|
-
directory,
|
|
2201
|
-
addExample = false,
|
|
2405
|
+
directory = "src/",
|
|
2202
2406
|
components,
|
|
2203
2407
|
llmProvider = "openai",
|
|
2204
2408
|
llmApiKey,
|
|
2205
|
-
|
|
2409
|
+
addExample = false,
|
|
2410
|
+
configureEditorWithDocsMCP,
|
|
2411
|
+
versionTag,
|
|
2412
|
+
initGit = false
|
|
2206
2413
|
}) => {
|
|
2207
2414
|
s.start("Initializing Mastra");
|
|
2415
|
+
const packageVersionTag = versionTag ? `@${versionTag}` : "";
|
|
2208
2416
|
try {
|
|
2209
2417
|
const result = await createMastraDir(directory);
|
|
2210
2418
|
if (!result.ok) {
|
|
@@ -2217,7 +2425,8 @@ var init = async ({
|
|
|
2217
2425
|
dirPath,
|
|
2218
2426
|
addExample,
|
|
2219
2427
|
addWorkflow: components.includes("workflows"),
|
|
2220
|
-
addAgent: components.includes("agents")
|
|
2428
|
+
addAgent: components.includes("agents"),
|
|
2429
|
+
addScorers: components.includes("scorers")
|
|
2221
2430
|
}),
|
|
2222
2431
|
...components.map((component) => createComponentsDir(dirPath, component)),
|
|
2223
2432
|
writeAPIKey({ provider: llmProvider, apiKey: llmApiKey })
|
|
@@ -2231,31 +2440,44 @@ var init = async ({
|
|
|
2231
2440
|
const depService = new DepsService();
|
|
2232
2441
|
const needsLibsql = await depService.checkDependencies(["@mastra/libsql"]) !== `ok`;
|
|
2233
2442
|
if (needsLibsql) {
|
|
2234
|
-
await depService.installPackages([
|
|
2443
|
+
await depService.installPackages([`@mastra/libsql${packageVersionTag}`]);
|
|
2235
2444
|
}
|
|
2236
2445
|
const needsMemory = components.includes(`agents`) && await depService.checkDependencies(["@mastra/memory"]) !== `ok`;
|
|
2237
2446
|
if (needsMemory) {
|
|
2238
|
-
await depService.installPackages([
|
|
2447
|
+
await depService.installPackages([`@mastra/memory${packageVersionTag}`]);
|
|
2239
2448
|
}
|
|
2240
2449
|
const needsLoggers = await depService.checkDependencies(["@mastra/loggers"]) !== `ok`;
|
|
2241
2450
|
if (needsLoggers) {
|
|
2242
|
-
await depService.installPackages([
|
|
2451
|
+
await depService.installPackages([`@mastra/loggers${packageVersionTag}`]);
|
|
2452
|
+
}
|
|
2453
|
+
const needsObservability = await depService.checkDependencies(["@mastra/observability"]) !== `ok`;
|
|
2454
|
+
if (needsObservability) {
|
|
2455
|
+
await depService.installPackages([`@mastra/observability${packageVersionTag}`]);
|
|
2456
|
+
}
|
|
2457
|
+
const needsEvals = components.includes(`scorers`) && await depService.checkDependencies(["@mastra/evals"]) !== `ok`;
|
|
2458
|
+
if (needsEvals) {
|
|
2459
|
+
await depService.installPackages([`@mastra/evals${packageVersionTag}`]);
|
|
2243
2460
|
}
|
|
2244
2461
|
}
|
|
2245
2462
|
const key = await getAPIKey(llmProvider || "openai");
|
|
2246
|
-
const aiSdkPackage = getAISDKPackage(llmProvider);
|
|
2247
|
-
const aiSdkPackageVersion = getAISDKPackageVersion(llmProvider);
|
|
2248
|
-
const depsService = new DepsService();
|
|
2249
|
-
const pm = depsService.packageManager;
|
|
2250
|
-
const installCommand = getPackageManagerAddCommand(pm);
|
|
2251
|
-
await exec3(`${pm} ${installCommand} ${aiSdkPackage}@${aiSdkPackageVersion}`);
|
|
2252
2463
|
if (configureEditorWithDocsMCP) {
|
|
2253
2464
|
await installMastraDocsMCPServer({
|
|
2254
2465
|
editor: configureEditorWithDocsMCP,
|
|
2255
|
-
directory: process.cwd()
|
|
2466
|
+
directory: process.cwd(),
|
|
2467
|
+
versionTag
|
|
2256
2468
|
});
|
|
2257
2469
|
}
|
|
2258
2470
|
s.stop();
|
|
2471
|
+
if (initGit) {
|
|
2472
|
+
const s2 = Y();
|
|
2473
|
+
try {
|
|
2474
|
+
s2.start("Initializing git repository");
|
|
2475
|
+
await gitInit({ cwd: process.cwd() });
|
|
2476
|
+
s2.stop("Git repository initialized");
|
|
2477
|
+
} catch {
|
|
2478
|
+
s2.stop();
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2259
2481
|
if (!llmApiKey) {
|
|
2260
2482
|
Me(`
|
|
2261
2483
|
${color2.green("Mastra initialized successfully!")}
|
|
@@ -2275,10 +2497,10 @@ var init = async ({
|
|
|
2275
2497
|
return { success: false };
|
|
2276
2498
|
}
|
|
2277
2499
|
};
|
|
2278
|
-
var
|
|
2500
|
+
var exec3 = util.promisify(child_process.exec);
|
|
2279
2501
|
var execWithTimeout = async (command, timeoutMs) => {
|
|
2280
2502
|
try {
|
|
2281
|
-
const promise =
|
|
2503
|
+
const promise = exec3(command, { killSignal: "SIGTERM" });
|
|
2282
2504
|
if (!timeoutMs) {
|
|
2283
2505
|
return await promise;
|
|
2284
2506
|
}
|
|
@@ -2301,6 +2523,32 @@ var execWithTimeout = async (command, timeoutMs) => {
|
|
|
2301
2523
|
throw error;
|
|
2302
2524
|
}
|
|
2303
2525
|
};
|
|
2526
|
+
async function getInitCommand(pm) {
|
|
2527
|
+
switch (pm) {
|
|
2528
|
+
case "npm":
|
|
2529
|
+
return "npm init -y";
|
|
2530
|
+
case "pnpm":
|
|
2531
|
+
return "pnpm init";
|
|
2532
|
+
case "yarn":
|
|
2533
|
+
return "yarn init -y";
|
|
2534
|
+
case "bun":
|
|
2535
|
+
return "bun init -y";
|
|
2536
|
+
default:
|
|
2537
|
+
return "npm init -y";
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
async function initializePackageJson(pm) {
|
|
2541
|
+
const initCommand = await getInitCommand(pm);
|
|
2542
|
+
await exec3(initCommand);
|
|
2543
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
2544
|
+
const packageJson = JSON.parse(await fs4.readFile(packageJsonPath, "utf-8"));
|
|
2545
|
+
packageJson.type = "module";
|
|
2546
|
+
packageJson.engines = {
|
|
2547
|
+
...packageJson.engines,
|
|
2548
|
+
node: ">=22.13.0"
|
|
2549
|
+
};
|
|
2550
|
+
await fs4.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
2551
|
+
}
|
|
2304
2552
|
async function installMastraDependency(pm, dependency, versionTag, isDev, timeout) {
|
|
2305
2553
|
let installCommand = getPackageManagerAddCommand(pm);
|
|
2306
2554
|
if (isDev) {
|
|
@@ -2326,23 +2574,42 @@ async function installMastraDependency(pm, dependency, versionTag, isDev, timeou
|
|
|
2326
2574
|
var createMastraProject = async ({
|
|
2327
2575
|
projectName: name,
|
|
2328
2576
|
createVersionTag,
|
|
2329
|
-
timeout
|
|
2577
|
+
timeout,
|
|
2578
|
+
llmProvider,
|
|
2579
|
+
llmApiKey,
|
|
2580
|
+
needsInteractive
|
|
2330
2581
|
}) => {
|
|
2331
2582
|
Ie(color2.inverse(" Mastra Create "));
|
|
2332
2583
|
const projectName = name ?? await he({
|
|
2333
2584
|
message: "What do you want to name your project?",
|
|
2334
2585
|
placeholder: "my-mastra-app",
|
|
2335
|
-
defaultValue: "my-mastra-app"
|
|
2586
|
+
defaultValue: "my-mastra-app",
|
|
2587
|
+
validate: (value) => {
|
|
2588
|
+
if (value.length === 0) return "Project name cannot be empty";
|
|
2589
|
+
if (fs3__default__default.existsSync(value)) {
|
|
2590
|
+
return `A directory named "${value}" already exists. Please choose a different name.`;
|
|
2591
|
+
}
|
|
2592
|
+
}
|
|
2336
2593
|
});
|
|
2337
2594
|
if (pD(projectName)) {
|
|
2338
2595
|
xe("Operation cancelled");
|
|
2339
2596
|
process.exit(0);
|
|
2340
2597
|
}
|
|
2598
|
+
let result = void 0;
|
|
2599
|
+
if (needsInteractive) {
|
|
2600
|
+
result = await interactivePrompt({
|
|
2601
|
+
options: { showBanner: false },
|
|
2602
|
+
skip: { llmProvider: llmProvider !== void 0, llmApiKey: llmApiKey !== void 0 }
|
|
2603
|
+
});
|
|
2604
|
+
}
|
|
2341
2605
|
const s2 = Y();
|
|
2606
|
+
const originalCwd = process.cwd();
|
|
2607
|
+
let projectPath = null;
|
|
2342
2608
|
try {
|
|
2343
2609
|
s2.start("Creating project");
|
|
2344
2610
|
try {
|
|
2345
|
-
await
|
|
2611
|
+
await fs4.mkdir(projectName);
|
|
2612
|
+
projectPath = path3.resolve(originalCwd, projectName);
|
|
2346
2613
|
} catch (error) {
|
|
2347
2614
|
if (error instanceof Error && "code" in error && error.code === "EEXIST") {
|
|
2348
2615
|
s2.stop(`A directory named "${projectName}" already exists. Please choose a different name.`);
|
|
@@ -2357,9 +2624,7 @@ var createMastraProject = async ({
|
|
|
2357
2624
|
const installCommand = getPackageManagerAddCommand(pm);
|
|
2358
2625
|
s2.message("Initializing project structure");
|
|
2359
2626
|
try {
|
|
2360
|
-
await
|
|
2361
|
-
await exec4(`npm pkg set type="module"`);
|
|
2362
|
-
await exec4(`npm pkg set engines.node=">=20.9.0"`);
|
|
2627
|
+
await initializePackageJson(pm);
|
|
2363
2628
|
const depsService = new DepsService();
|
|
2364
2629
|
await depsService.addScriptsToPackageJson({
|
|
2365
2630
|
dev: "mastra dev",
|
|
@@ -2374,9 +2639,9 @@ var createMastraProject = async ({
|
|
|
2374
2639
|
s2.stop("Project structure created");
|
|
2375
2640
|
s2.start(`Installing ${pm} dependencies`);
|
|
2376
2641
|
try {
|
|
2377
|
-
await
|
|
2378
|
-
await
|
|
2379
|
-
await
|
|
2642
|
+
await exec3(`${pm} ${installCommand} zod@^4`);
|
|
2643
|
+
await exec3(`${pm} ${installCommand} -D typescript @types/node`);
|
|
2644
|
+
await exec3(`echo '{
|
|
2380
2645
|
"compilerOptions": {
|
|
2381
2646
|
"target": "ES2022",
|
|
2382
2647
|
"module": "ES2022",
|
|
@@ -2398,15 +2663,15 @@ var createMastraProject = async ({
|
|
|
2398
2663
|
);
|
|
2399
2664
|
}
|
|
2400
2665
|
s2.stop(`${pm} dependencies installed`);
|
|
2401
|
-
s2.start("Installing
|
|
2666
|
+
s2.start("Installing Mastra CLI");
|
|
2402
2667
|
const versionTag = createVersionTag ? `@${createVersionTag}` : "@latest";
|
|
2403
2668
|
try {
|
|
2404
2669
|
await installMastraDependency(pm, "mastra", versionTag, true, timeout);
|
|
2405
2670
|
} catch (error) {
|
|
2406
2671
|
throw new Error(`Failed to install Mastra CLI: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2407
2672
|
}
|
|
2408
|
-
s2.stop("
|
|
2409
|
-
s2.start("Installing dependencies");
|
|
2673
|
+
s2.stop("Mastra CLI installed");
|
|
2674
|
+
s2.start("Installing Mastra dependencies");
|
|
2410
2675
|
try {
|
|
2411
2676
|
await installMastraDependency(pm, "@mastra/core", versionTag, false, timeout);
|
|
2412
2677
|
await installMastraDependency(pm, "@mastra/libsql", versionTag, false, timeout);
|
|
@@ -2419,58 +2684,80 @@ var createMastraProject = async ({
|
|
|
2419
2684
|
s2.stop("Mastra dependencies installed");
|
|
2420
2685
|
s2.start("Adding .gitignore");
|
|
2421
2686
|
try {
|
|
2422
|
-
await
|
|
2423
|
-
await
|
|
2424
|
-
await
|
|
2425
|
-
await
|
|
2426
|
-
await
|
|
2427
|
-
await
|
|
2428
|
-
await
|
|
2429
|
-
await
|
|
2687
|
+
await exec3(`echo output.txt >> .gitignore`);
|
|
2688
|
+
await exec3(`echo node_modules >> .gitignore`);
|
|
2689
|
+
await exec3(`echo dist >> .gitignore`);
|
|
2690
|
+
await exec3(`echo .mastra >> .gitignore`);
|
|
2691
|
+
await exec3(`echo .env.development >> .gitignore`);
|
|
2692
|
+
await exec3(`echo .env >> .gitignore`);
|
|
2693
|
+
await exec3(`echo *.db >> .gitignore`);
|
|
2694
|
+
await exec3(`echo *.db-* >> .gitignore`);
|
|
2430
2695
|
} catch (error) {
|
|
2431
2696
|
throw new Error(`Failed to create .gitignore: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2432
2697
|
}
|
|
2433
2698
|
s2.stop(".gitignore added");
|
|
2434
2699
|
Se("Project created successfully");
|
|
2435
|
-
console.
|
|
2436
|
-
return { projectName };
|
|
2700
|
+
console.info("");
|
|
2701
|
+
return { projectName, result };
|
|
2437
2702
|
} catch (error) {
|
|
2438
2703
|
s2.stop();
|
|
2439
2704
|
const errorMessage = error instanceof Error ? error.message : "An unexpected error occurred";
|
|
2440
2705
|
xe(`Project creation failed: ${errorMessage}`);
|
|
2706
|
+
if (projectPath && fs3__default__default.existsSync(projectPath)) {
|
|
2707
|
+
try {
|
|
2708
|
+
process.chdir(originalCwd);
|
|
2709
|
+
await fs4.rm(projectPath, { recursive: true, force: true });
|
|
2710
|
+
} catch (cleanupError) {
|
|
2711
|
+
console.error(
|
|
2712
|
+
`Warning: Failed to clean up project directory: ${cleanupError instanceof Error ? cleanupError.message : "Unknown error"}`
|
|
2713
|
+
);
|
|
2714
|
+
}
|
|
2715
|
+
}
|
|
2441
2716
|
process.exit(1);
|
|
2442
2717
|
}
|
|
2443
2718
|
};
|
|
2444
|
-
var
|
|
2445
|
-
|
|
2446
|
-
|
|
2719
|
+
var version$1 = package_default.version;
|
|
2720
|
+
var create = async (args) => {
|
|
2721
|
+
if (args.template !== void 0) {
|
|
2722
|
+
await createFromTemplate({
|
|
2723
|
+
projectName: args.projectName,
|
|
2724
|
+
template: args.template,
|
|
2725
|
+
timeout: args.timeout,
|
|
2726
|
+
injectedAnalytics: args.analytics,
|
|
2727
|
+
llmProvider: args.llmProvider
|
|
2728
|
+
});
|
|
2447
2729
|
return;
|
|
2448
2730
|
}
|
|
2449
|
-
const
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2731
|
+
const needsInteractive = args.components === void 0 || args.llmProvider === void 0 || args.addExample === void 0;
|
|
2732
|
+
const { projectName, result } = await createMastraProject({
|
|
2733
|
+
projectName: args?.projectName,
|
|
2734
|
+
createVersionTag: args?.createVersionTag,
|
|
2735
|
+
timeout: args?.timeout,
|
|
2736
|
+
llmProvider: args?.llmProvider,
|
|
2737
|
+
llmApiKey: args?.llmApiKey,
|
|
2738
|
+
needsInteractive
|
|
2453
2739
|
});
|
|
2454
|
-
const directory =
|
|
2455
|
-
if (
|
|
2456
|
-
const result = await interactivePrompt();
|
|
2740
|
+
const directory = args.directory || "src/";
|
|
2741
|
+
if (needsInteractive && result) {
|
|
2457
2742
|
await init({
|
|
2458
2743
|
...result,
|
|
2459
2744
|
llmApiKey: result?.llmApiKey,
|
|
2460
|
-
components: ["agents", "tools", "workflows"],
|
|
2461
|
-
addExample: true
|
|
2745
|
+
components: ["agents", "tools", "workflows", "scorers"],
|
|
2746
|
+
addExample: true,
|
|
2747
|
+
versionTag: args.createVersionTag
|
|
2462
2748
|
});
|
|
2463
2749
|
postCreate({ projectName });
|
|
2464
2750
|
return;
|
|
2465
2751
|
}
|
|
2466
|
-
const { components = [], llmProvider = "openai", addExample = false, llmApiKey } =
|
|
2752
|
+
const { components = [], llmProvider = "openai", addExample = false, llmApiKey } = args;
|
|
2467
2753
|
await init({
|
|
2468
2754
|
directory,
|
|
2469
2755
|
components,
|
|
2470
2756
|
llmProvider,
|
|
2471
2757
|
addExample,
|
|
2472
2758
|
llmApiKey,
|
|
2473
|
-
configureEditorWithDocsMCP:
|
|
2759
|
+
configureEditorWithDocsMCP: args.mcpServer,
|
|
2760
|
+
versionTag: args.createVersionTag
|
|
2474
2761
|
});
|
|
2475
2762
|
postCreate({ projectName });
|
|
2476
2763
|
};
|
|
@@ -2561,9 +2848,9 @@ async function createFromGitHubUrl(url) {
|
|
|
2561
2848
|
workflows: []
|
|
2562
2849
|
};
|
|
2563
2850
|
}
|
|
2564
|
-
async function createFromTemplate(
|
|
2851
|
+
async function createFromTemplate(args) {
|
|
2565
2852
|
let selectedTemplate;
|
|
2566
|
-
if (
|
|
2853
|
+
if (args.template === true) {
|
|
2567
2854
|
const templates = await loadTemplates();
|
|
2568
2855
|
const selected = await selectTemplate(templates);
|
|
2569
2856
|
if (!selected) {
|
|
@@ -2571,26 +2858,26 @@ async function createFromTemplate(args2) {
|
|
|
2571
2858
|
return;
|
|
2572
2859
|
}
|
|
2573
2860
|
selectedTemplate = selected;
|
|
2574
|
-
} else if (
|
|
2575
|
-
if (isGitHubUrl(
|
|
2576
|
-
const
|
|
2577
|
-
|
|
2578
|
-
const validation = await validateGitHubProject(
|
|
2861
|
+
} else if (args.template && typeof args.template === "string") {
|
|
2862
|
+
if (isGitHubUrl(args.template)) {
|
|
2863
|
+
const spinner4 = Y();
|
|
2864
|
+
spinner4.start("Validating GitHub repository...");
|
|
2865
|
+
const validation = await validateGitHubProject(args.template);
|
|
2579
2866
|
if (!validation.isValid) {
|
|
2580
|
-
|
|
2867
|
+
spinner4.stop("Validation failed");
|
|
2581
2868
|
M.error("This does not appear to be a valid Mastra project:");
|
|
2582
2869
|
validation.errors.forEach((error) => M.error(` - ${error}`));
|
|
2583
2870
|
throw new Error("Invalid Mastra project");
|
|
2584
2871
|
}
|
|
2585
|
-
|
|
2586
|
-
selectedTemplate = await createFromGitHubUrl(
|
|
2872
|
+
spinner4.stop("Valid Mastra project \u2713");
|
|
2873
|
+
selectedTemplate = await createFromGitHubUrl(args.template);
|
|
2587
2874
|
} else {
|
|
2588
2875
|
const templates = await loadTemplates();
|
|
2589
|
-
const found = findTemplateByName(templates,
|
|
2876
|
+
const found = findTemplateByName(templates, args.template);
|
|
2590
2877
|
if (!found) {
|
|
2591
|
-
M.error(`Template "${
|
|
2878
|
+
M.error(`Template "${args.template}" not found. Available templates:`);
|
|
2592
2879
|
templates.forEach((t) => M.info(` - ${t.title} (use: ${t.slug.replace("template-", "")})`));
|
|
2593
|
-
throw new Error(`Template "${
|
|
2880
|
+
throw new Error(`Template "${args.template}" not found`);
|
|
2594
2881
|
}
|
|
2595
2882
|
selectedTemplate = found;
|
|
2596
2883
|
}
|
|
@@ -2598,7 +2885,7 @@ async function createFromTemplate(args2) {
|
|
|
2598
2885
|
if (!selectedTemplate) {
|
|
2599
2886
|
throw new Error("No template selected");
|
|
2600
2887
|
}
|
|
2601
|
-
let projectName =
|
|
2888
|
+
let projectName = args.projectName;
|
|
2602
2889
|
if (!projectName) {
|
|
2603
2890
|
const defaultName = getDefaultProjectName(selectedTemplate);
|
|
2604
2891
|
const response = await he({
|
|
@@ -2612,19 +2899,61 @@ async function createFromTemplate(args2) {
|
|
|
2612
2899
|
}
|
|
2613
2900
|
projectName = response;
|
|
2614
2901
|
}
|
|
2902
|
+
let llmProvider = args.llmProvider;
|
|
2903
|
+
if (!llmProvider) {
|
|
2904
|
+
const providerResponse = await ve({
|
|
2905
|
+
message: "Select a default provider:",
|
|
2906
|
+
options: LLM_PROVIDERS
|
|
2907
|
+
});
|
|
2908
|
+
if (pD(providerResponse)) {
|
|
2909
|
+
M.info("Project creation cancelled.");
|
|
2910
|
+
return;
|
|
2911
|
+
}
|
|
2912
|
+
llmProvider = providerResponse;
|
|
2913
|
+
}
|
|
2914
|
+
let initGit = false;
|
|
2915
|
+
const gitConfirmResult = await ye({
|
|
2916
|
+
message: "Initialize a new git repository?",
|
|
2917
|
+
initialValue: true
|
|
2918
|
+
});
|
|
2919
|
+
if (!pD(gitConfirmResult)) {
|
|
2920
|
+
initGit = gitConfirmResult;
|
|
2921
|
+
}
|
|
2922
|
+
let projectPath = null;
|
|
2615
2923
|
try {
|
|
2616
|
-
const analytics =
|
|
2924
|
+
const analytics = args.injectedAnalytics || getAnalytics();
|
|
2617
2925
|
if (analytics) {
|
|
2618
2926
|
analytics.trackEvent("cli_template_used", {
|
|
2619
2927
|
template_slug: selectedTemplate.slug,
|
|
2620
2928
|
template_title: selectedTemplate.title
|
|
2621
2929
|
});
|
|
2930
|
+
if (llmProvider) {
|
|
2931
|
+
analytics.trackEvent("cli_model_provider_selected", {
|
|
2932
|
+
provider: llmProvider,
|
|
2933
|
+
selection_method: args.llmProvider ? "cli_args" : "interactive"
|
|
2934
|
+
});
|
|
2935
|
+
}
|
|
2622
2936
|
}
|
|
2623
|
-
const
|
|
2937
|
+
const isBeta = version$1?.includes("beta") ?? false;
|
|
2938
|
+
const isMastraTemplate = selectedTemplate.githubUrl.includes("github.com/mastra-ai/");
|
|
2939
|
+
const branch = isBeta && isMastraTemplate ? "beta" : void 0;
|
|
2940
|
+
projectPath = await cloneTemplate({
|
|
2624
2941
|
template: selectedTemplate,
|
|
2625
|
-
projectName
|
|
2942
|
+
projectName,
|
|
2943
|
+
branch,
|
|
2944
|
+
llmProvider
|
|
2626
2945
|
});
|
|
2627
2946
|
await installDependencies(projectPath);
|
|
2947
|
+
if (initGit) {
|
|
2948
|
+
const s2 = Y();
|
|
2949
|
+
try {
|
|
2950
|
+
s2.start("Initializing git repository");
|
|
2951
|
+
await gitInit({ cwd: projectPath });
|
|
2952
|
+
s2.stop("Git repository initialized");
|
|
2953
|
+
} catch {
|
|
2954
|
+
s2.stop();
|
|
2955
|
+
}
|
|
2956
|
+
}
|
|
2628
2957
|
Me(`
|
|
2629
2958
|
${color2.green("Mastra template installed!")}
|
|
2630
2959
|
|
|
@@ -2633,6 +2962,17 @@ async function createFromTemplate(args2) {
|
|
|
2633
2962
|
`);
|
|
2634
2963
|
postCreate({ projectName });
|
|
2635
2964
|
} catch (error) {
|
|
2965
|
+
if (projectPath) {
|
|
2966
|
+
try {
|
|
2967
|
+
if (fs3__default__default.existsSync(projectPath)) {
|
|
2968
|
+
await fs4.rm(projectPath, { recursive: true, force: true });
|
|
2969
|
+
}
|
|
2970
|
+
} catch (cleanupError) {
|
|
2971
|
+
console.error(
|
|
2972
|
+
`Warning: Failed to clean up project directory: ${cleanupError instanceof Error ? cleanupError.message : "Unknown error"}`
|
|
2973
|
+
);
|
|
2974
|
+
}
|
|
2975
|
+
}
|
|
2636
2976
|
M.error(`Failed to create project from template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2637
2977
|
throw error;
|
|
2638
2978
|
}
|
|
@@ -2672,14 +3012,14 @@ program.version(`${version}`, "-v, --version").description(`create-mastra ${vers
|
|
|
2672
3012
|
analytics.trackCommand({
|
|
2673
3013
|
command: "version"
|
|
2674
3014
|
});
|
|
2675
|
-
console.
|
|
3015
|
+
console.info(`create-mastra ${version}`);
|
|
2676
3016
|
} catch {
|
|
2677
3017
|
}
|
|
2678
3018
|
});
|
|
2679
3019
|
program.name("create-mastra").description("Create a new Mastra project").argument("[project-name]", "Directory name of the project").option(
|
|
2680
3020
|
"-p, --project-name <string>",
|
|
2681
3021
|
"Project name that will be used in package.json and as the project directory name."
|
|
2682
|
-
).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(
|
|
3022
|
+
).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(
|
|
2683
3023
|
"--template [template-name]",
|
|
2684
3024
|
"Create project from a template (use template name, public GitHub URL, or leave blank to select from list)"
|
|
2685
3025
|
).action(async (projectNameArg, args) => {
|
|
@@ -2687,7 +3027,7 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
|
|
|
2687
3027
|
const timeout = args?.timeout ? args?.timeout === true ? 6e4 : parseInt(args?.timeout, 10) : void 0;
|
|
2688
3028
|
if (args.default) {
|
|
2689
3029
|
await create({
|
|
2690
|
-
components: ["agents", "tools", "workflows"],
|
|
3030
|
+
components: ["agents", "tools", "workflows", "scorers"],
|
|
2691
3031
|
llmProvider: "openai",
|
|
2692
3032
|
addExample: true,
|
|
2693
3033
|
createVersionTag,
|
|
@@ -2703,7 +3043,7 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
|
|
|
2703
3043
|
components: args.components ? args.components.split(",") : [],
|
|
2704
3044
|
llmProvider: args.llm,
|
|
2705
3045
|
addExample: args.example,
|
|
2706
|
-
llmApiKey: args
|
|
3046
|
+
llmApiKey: args.llmApiKey,
|
|
2707
3047
|
createVersionTag,
|
|
2708
3048
|
timeout,
|
|
2709
3049
|
projectName,
|