create-mastra 0.0.0-unified-sidebar-20251010130811 → 0.0.0-unified-workspace-snapshot-20260128233410
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 +381 -1
- package/README.md +10 -32
- package/dist/index.js +894 -473
- package/dist/index.js.map +1 -1
- package/dist/starter-files/tools.ts +2 -2
- package/dist/templates/dev.entry.js +3 -46
- package/package.json +20 -21
package/dist/index.js
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
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
|
-
var __filename = fileURLToPath(import.meta.url);
|
|
26
|
-
var __dirname = path3.dirname(__filename);
|
|
25
|
+
var __filename$1 = fileURLToPath(import.meta.url);
|
|
26
|
+
var __dirname$1 = path3.dirname(__filename$1);
|
|
27
27
|
var analyticsInstance = null;
|
|
28
28
|
function getAnalytics() {
|
|
29
29
|
return analyticsInstance;
|
|
@@ -39,7 +39,7 @@ var PosthogAnalytics = class {
|
|
|
39
39
|
host = "https://app.posthog.com"
|
|
40
40
|
}) {
|
|
41
41
|
this.version = version;
|
|
42
|
-
const cliConfigPath = path3.join(__dirname, "mastra-cli.json");
|
|
42
|
+
const cliConfigPath = path3.join(__dirname$1, "mastra-cli.json");
|
|
43
43
|
if (existsSync(cliConfigPath)) {
|
|
44
44
|
try {
|
|
45
45
|
const { distinctId, sessionId } = JSON.parse(readFileSync(cliConfigPath, "utf-8"));
|
|
@@ -67,7 +67,7 @@ var PosthogAnalytics = class {
|
|
|
67
67
|
}
|
|
68
68
|
writeCliConfig({ distinctId, sessionId }) {
|
|
69
69
|
try {
|
|
70
|
-
writeFileSync(path3.join(__dirname, "mastra-cli.json"), JSON.stringify({ distinctId, sessionId }));
|
|
70
|
+
writeFileSync(path3.join(__dirname$1, "mastra-cli.json"), JSON.stringify({ distinctId, sessionId }));
|
|
71
71
|
} catch {
|
|
72
72
|
}
|
|
73
73
|
}
|
|
@@ -105,6 +105,10 @@ var PosthogAnalytics = class {
|
|
|
105
105
|
machine_id: os.hostname()
|
|
106
106
|
};
|
|
107
107
|
}
|
|
108
|
+
getDurationMs(startTime) {
|
|
109
|
+
const [seconds, nanoseconds] = process.hrtime(startTime);
|
|
110
|
+
return seconds * 1e3 + nanoseconds / 1e6;
|
|
111
|
+
}
|
|
108
112
|
captureSessionStart() {
|
|
109
113
|
if (!this.client) {
|
|
110
114
|
return;
|
|
@@ -173,8 +177,7 @@ var PosthogAnalytics = class {
|
|
|
173
177
|
const startTime = process.hrtime();
|
|
174
178
|
try {
|
|
175
179
|
const result = await execution();
|
|
176
|
-
const
|
|
177
|
-
const durationMs = seconds * 1e3 + nanoseconds / 1e6;
|
|
180
|
+
const durationMs = this.getDurationMs(startTime);
|
|
178
181
|
this.trackCommand({
|
|
179
182
|
command,
|
|
180
183
|
args,
|
|
@@ -184,8 +187,7 @@ var PosthogAnalytics = class {
|
|
|
184
187
|
});
|
|
185
188
|
return result;
|
|
186
189
|
} catch (error) {
|
|
187
|
-
const
|
|
188
|
-
const durationMs = seconds * 1e3 + nanoseconds / 1e6;
|
|
190
|
+
const durationMs = this.getDurationMs(startTime);
|
|
189
191
|
this.trackCommand({
|
|
190
192
|
command,
|
|
191
193
|
args,
|
|
@@ -382,7 +384,7 @@ function DD({onlyFirst:e=false}={}){const t=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:
|
|
|
382
384
|
`).length-1;this.output.write(srcExports.cursor.move(-999,u*-1));}render(){const u=Y$1(this._render(this)??"",process.stdout.columns,{hard:true});if(u!==this._prevFrame){if(this.state==="initial")this.output.write(srcExports.cursor.hide);else {const t=BD(this._prevFrame,u);if(this.restoreCursor(),t&&t?.length===1){const F=t[0];this.output.write(srcExports.cursor.move(0,F)),this.output.write(srcExports.erase.lines(1));const s=u.split(`
|
|
383
385
|
`);this.output.write(s[F]),this._prevFrame=u,this.output.write(srcExports.cursor.move(0,s.length-F-1));return}if(t&&t?.length>1){const F=t[0];this.output.write(srcExports.cursor.move(0,F)),this.output.write(srcExports.erase.down());const s=u.split(`
|
|
384
386
|
`).slice(F);this.output.write(s.join(`
|
|
385
|
-
`)),this._prevFrame=u;return}this.output.write(srcExports.erase.down());}this.output.write(u),this.state==="initial"&&(this.state="active"),this._prevFrame=u;}}}var OD=Object.defineProperty,PD=(e,u,t)=>u in e?OD(e,u,{enumerable:true,configurable:true,writable:true,value:t}):e[u]=t,J=(e,u,t)=>(PD(e,typeof u!="symbol"?u+"":u,t),t);class LD extends x{constructor(u){super(u,false),J(this,"options"),J(this,"cursor",0),this.options=u.options,this.cursor=this.options.findIndex(({value:t})=>t===u.initialValue),this.cursor===-1&&(this.cursor=0),this.changeValue(),this.on("cursor",t=>{switch(t){case "left":case "up":this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;break;case "down":case "right":this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;break}this.changeValue();});}get _value(){return this.options[this.cursor]}changeValue(){this.value=this._value.value;}}class RD extends x{get valueWithCursor(){if(this.state==="submit")return this.value;if(this.cursor>=this.value.length)return `${this.value}\u2588`;const u=this.value.slice(0,this.cursor),[t,...F]=this.value.slice(this.cursor);return `${u}${color2.inverse(t)}${F.join("")}`}get cursor(){return this._cursor}constructor(u){super(u),this.on("finalize",()=>{this.value||(this.value=u.defaultValue);});}}
|
|
387
|
+
`)),this._prevFrame=u;return}this.output.write(srcExports.erase.down());}this.output.write(u),this.state==="initial"&&(this.state="active"),this._prevFrame=u;}}}class dD extends x{get cursor(){return this.value?0:1}get _value(){return this.cursor===0}constructor(u){super(u,false),this.value=!!u.initialValue,this.on("value",()=>{this.value=this._value;}),this.on("confirm",t=>{this.output.write(srcExports.cursor.move(0,-1)),this.value=t,this.state="submit",this.close();}),this.on("cursor",()=>{this.value=!this.value;});}}var OD=Object.defineProperty,PD=(e,u,t)=>u in e?OD(e,u,{enumerable:true,configurable:true,writable:true,value:t}):e[u]=t,J=(e,u,t)=>(PD(e,typeof u!="symbol"?u+"":u,t),t);class LD extends x{constructor(u){super(u,false),J(this,"options"),J(this,"cursor",0),this.options=u.options,this.cursor=this.options.findIndex(({value:t})=>t===u.initialValue),this.cursor===-1&&(this.cursor=0),this.changeValue(),this.on("cursor",t=>{switch(t){case "left":case "up":this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;break;case "down":case "right":this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;break}this.changeValue();});}get _value(){return this.options[this.cursor]}changeValue(){this.value=this._value.value;}}class RD extends x{get valueWithCursor(){if(this.state==="submit")return this.value;if(this.cursor>=this.value.length)return `${this.value}\u2588`;const u=this.value.slice(0,this.cursor),[t,...F]=this.value.slice(this.cursor);return `${u}${color2.inverse(t)}${F.join("")}`}get cursor(){return this._cursor}constructor(u){super(u),this.on("finalize",()=>{this.value||(this.value=u.defaultValue);});}}
|
|
386
388
|
|
|
387
389
|
function ce(){return y$1.platform!=="win32"?y$1.env.TERM!=="linux":!!y$1.env.CI||!!y$1.env.WT_SESSION||!!y$1.env.TERMINUS_SUBLIME||y$1.env.ConEmuTask==="{cmd::Cmder}"||y$1.env.TERM_PROGRAM==="Terminus-Sublime"||y$1.env.TERM_PROGRAM==="vscode"||y$1.env.TERM==="xterm-256color"||y$1.env.TERM==="alacritty"||y$1.env.TERMINAL_EMULATOR==="JetBrains-JediTerm"}const V=ce(),u=(t,n)=>V?t:n,le=u("\u25C6","*"),L=u("\u25A0","x"),W=u("\u25B2","x"),C=u("\u25C7","o"),ue=u("\u250C","T"),o=u("\u2502","|"),d=u("\u2514","\u2014"),k=u("\u25CF",">"),P=u("\u25CB"," "),_=u("\u2500","-"),me=u("\u256E","+"),de=u("\u251C","+"),pe=u("\u256F","+"),q=u("\u25CF","\u2022"),D=u("\u25C6","*"),U=u("\u25B2","!"),K=u("\u25A0","x"),b=t=>{switch(t){case "initial":case "active":return color2.cyan(le);case "cancel":return color2.red(L);case "error":return color2.yellow(W);case "submit":return color2.green(C)}},G=t=>{const{cursor:n,options:r,style:i}=t,s=t.maxItems??Number.POSITIVE_INFINITY,c=Math.max(process.stdout.rows-4,0),a=Math.min(c,Math.max(s,5));let l=0;n>=l+a-3?l=Math.max(Math.min(n-a+3,r.length-a),0):n<l+2&&(l=Math.max(n-2,0));const $=a<r.length&&l>0,g=a<r.length&&l+a<r.length;return r.slice(l,l+a).map((p,v,f)=>{const j=v===0&&$,E=v===f.length-1&&g;return j||E?color2.dim("..."):i(p,v+l===n)})},he=t=>new RD({validate:t.validate,placeholder:t.placeholder,defaultValue:t.defaultValue,initialValue:t.initialValue,render(){const n=`${color2.gray(o)}
|
|
388
390
|
${b(this.state)} ${t.message}
|
|
@@ -392,7 +394,12 @@ ${color2.yellow(d)} ${color2.yellow(this.error)}
|
|
|
392
394
|
`;case "submit":return `${n}${color2.gray(o)} ${color2.dim(this.value||t.placeholder)}`;case "cancel":return `${n}${color2.gray(o)} ${color2.strikethrough(color2.dim(this.value??""))}${this.value?.trim()?`
|
|
393
395
|
${color2.gray(o)}`:""}`;default:return `${n}${color2.cyan(o)} ${i}
|
|
394
396
|
${color2.cyan(d)}
|
|
395
|
-
`}}}).prompt(),
|
|
397
|
+
`}}}).prompt(),ye=t=>{const n=t.active??"Yes",r=t.inactive??"No";return new dD({active:n,inactive:r,initialValue:t.initialValue??true,render(){const i=`${color2.gray(o)}
|
|
398
|
+
${b(this.state)} ${t.message}
|
|
399
|
+
`,s=this.value?n:r;switch(this.state){case "submit":return `${i}${color2.gray(o)} ${color2.dim(s)}`;case "cancel":return `${i}${color2.gray(o)} ${color2.strikethrough(color2.dim(s))}
|
|
400
|
+
${color2.gray(o)}`;default:return `${i}${color2.cyan(o)} ${this.value?`${color2.green(k)} ${n}`:`${color2.dim(P)} ${color2.dim(n)}`} ${color2.dim("/")} ${this.value?`${color2.dim(P)} ${color2.dim(r)}`:`${color2.green(k)} ${r}`}
|
|
401
|
+
${color2.cyan(d)}
|
|
402
|
+
`}}}).prompt()},ve=t=>{const n=(r,i)=>{const s=r.label??String(r.value);switch(i){case "selected":return `${color2.dim(s)}`;case "active":return `${color2.green(k)} ${s} ${r.hint?color2.dim(`(${r.hint})`):""}`;case "cancelled":return `${color2.strikethrough(color2.dim(s))}`;default:return `${color2.dim(P)} ${color2.dim(s)}`}};return new LD({options:t.options,initialValue:t.initialValue,render(){const r=`${color2.gray(o)}
|
|
396
403
|
${b(this.state)} ${t.message}
|
|
397
404
|
`;switch(this.state){case "submit":return `${r}${color2.gray(o)} ${n(this.options[this.cursor],"selected")}`;case "cancel":return `${r}${color2.gray(o)} ${n(this.options[this.cursor],"cancelled")}
|
|
398
405
|
${color2.gray(o)}`;default:return `${r}${color2.cyan(o)} ${G({cursor:this.cursor,options:this.options,maxItems:t.maxItems,style:(i,s)=>n(i,s?"active":"inactive")}).join(`
|
|
@@ -422,7 +429,7 @@ ${color2.gray(d)} ${t}
|
|
|
422
429
|
`):process.stdout.write(`${w} ${l}
|
|
423
430
|
`),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
431
|
|
|
425
|
-
var shellQuote
|
|
432
|
+
var shellQuote = {};
|
|
426
433
|
|
|
427
434
|
var quote;
|
|
428
435
|
var hasRequiredQuote;
|
|
@@ -688,16 +695,16 @@ function requireParse () {
|
|
|
688
695
|
var hasRequiredShellQuote;
|
|
689
696
|
|
|
690
697
|
function requireShellQuote () {
|
|
691
|
-
if (hasRequiredShellQuote) return shellQuote
|
|
698
|
+
if (hasRequiredShellQuote) return shellQuote;
|
|
692
699
|
hasRequiredShellQuote = 1;
|
|
693
700
|
|
|
694
|
-
shellQuote
|
|
695
|
-
shellQuote
|
|
696
|
-
return shellQuote
|
|
701
|
+
shellQuote.quote = requireQuote();
|
|
702
|
+
shellQuote.parse = requireParse();
|
|
703
|
+
return shellQuote;
|
|
697
704
|
}
|
|
698
705
|
|
|
699
706
|
var shellQuoteExports = requireShellQuote();
|
|
700
|
-
var
|
|
707
|
+
var shellQuote2 = /*@__PURE__*/getDefaultExportFromCjs(shellQuoteExports);
|
|
701
708
|
|
|
702
709
|
// eslint-disable-next-line no-warning-comments
|
|
703
710
|
// TODO: Use a better method when it's added to Node.js (https://github.com/nodejs/node/pull/40240)
|
|
@@ -724,13 +731,18 @@ const format = (open, close) => {
|
|
|
724
731
|
// Handle nested colors.
|
|
725
732
|
|
|
726
733
|
// We could have done this, but it's too slow (as of Node.js 22).
|
|
727
|
-
// return openCode + string.replaceAll(closeCode, openCode) + closeCode;
|
|
734
|
+
// return openCode + string.replaceAll(closeCode, (close === 22 ? closeCode : '') + openCode) + closeCode;
|
|
728
735
|
|
|
729
736
|
let result = openCode;
|
|
730
737
|
let lastIndex = 0;
|
|
731
738
|
|
|
739
|
+
// SGR 22 resets both bold (1) and dim (2). When we encounter a nested
|
|
740
|
+
// close for styles that use 22, we need to re-open the outer style.
|
|
741
|
+
const reopenOnNestedClose = close === 22;
|
|
742
|
+
const replaceCode = (reopenOnNestedClose ? closeCode : '') + openCode;
|
|
743
|
+
|
|
732
744
|
while (index !== -1) {
|
|
733
|
-
result += string.slice(lastIndex, index) +
|
|
745
|
+
result += string.slice(lastIndex, index) + replaceCode;
|
|
734
746
|
lastIndex = index + closeCode.length;
|
|
735
747
|
index = string.indexOf(closeCode, lastIndex);
|
|
736
748
|
}
|
|
@@ -882,6 +894,7 @@ class YoctoSpinner {
|
|
|
882
894
|
#exitHandlerBound;
|
|
883
895
|
#isInteractive;
|
|
884
896
|
#lastSpinnerFrameTime = 0;
|
|
897
|
+
#isSpinning = false;
|
|
885
898
|
|
|
886
899
|
constructor(options = {}) {
|
|
887
900
|
const spinner = options.spinner ?? defaultSpinner;
|
|
@@ -903,13 +916,17 @@ class YoctoSpinner {
|
|
|
903
916
|
return this;
|
|
904
917
|
}
|
|
905
918
|
|
|
919
|
+
this.#isSpinning = true;
|
|
906
920
|
this.#hideCursor();
|
|
907
921
|
this.#render();
|
|
908
922
|
this.#subscribeToProcessEvents();
|
|
909
923
|
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
924
|
+
// Only start the timer in interactive mode
|
|
925
|
+
if (this.#isInteractive) {
|
|
926
|
+
this.#timer = setInterval(() => {
|
|
927
|
+
this.#render();
|
|
928
|
+
}, this.#interval);
|
|
929
|
+
}
|
|
913
930
|
|
|
914
931
|
return this;
|
|
915
932
|
}
|
|
@@ -919,8 +936,12 @@ class YoctoSpinner {
|
|
|
919
936
|
return this;
|
|
920
937
|
}
|
|
921
938
|
|
|
922
|
-
|
|
923
|
-
this.#timer
|
|
939
|
+
this.#isSpinning = false;
|
|
940
|
+
if (this.#timer) {
|
|
941
|
+
clearInterval(this.#timer);
|
|
942
|
+
this.#timer = undefined;
|
|
943
|
+
}
|
|
944
|
+
|
|
924
945
|
this.#showCursor();
|
|
925
946
|
this.clear();
|
|
926
947
|
this.#unsubscribeFromProcessEvents();
|
|
@@ -953,7 +974,7 @@ class YoctoSpinner {
|
|
|
953
974
|
}
|
|
954
975
|
|
|
955
976
|
get isSpinning() {
|
|
956
|
-
return this.#
|
|
977
|
+
return this.#isSpinning;
|
|
957
978
|
}
|
|
958
979
|
|
|
959
980
|
get text() {
|
|
@@ -1090,11 +1111,11 @@ var MastraLogger = class {
|
|
|
1090
1111
|
}
|
|
1091
1112
|
trackException(_error) {
|
|
1092
1113
|
}
|
|
1093
|
-
async
|
|
1114
|
+
async listLogs(transportId, params) {
|
|
1094
1115
|
if (!transportId || !this.transports.has(transportId)) {
|
|
1095
1116
|
return { logs: [], total: 0, page: params?.page ?? 1, perPage: params?.perPage ?? 100, hasMore: false };
|
|
1096
1117
|
}
|
|
1097
|
-
return this.transports.get(transportId).
|
|
1118
|
+
return this.transports.get(transportId).listLogs(params) ?? {
|
|
1098
1119
|
logs: [],
|
|
1099
1120
|
total: 0,
|
|
1100
1121
|
page: params?.page ?? 1,
|
|
@@ -1102,7 +1123,7 @@ var MastraLogger = class {
|
|
|
1102
1123
|
hasMore: false
|
|
1103
1124
|
};
|
|
1104
1125
|
}
|
|
1105
|
-
async
|
|
1126
|
+
async listLogsByRunId({
|
|
1106
1127
|
transportId,
|
|
1107
1128
|
runId,
|
|
1108
1129
|
fromDate,
|
|
@@ -1115,7 +1136,7 @@ var MastraLogger = class {
|
|
|
1115
1136
|
if (!transportId || !this.transports.has(transportId) || !runId) {
|
|
1116
1137
|
return { logs: [], total: 0, page: page ?? 1, perPage: perPage ?? 100, hasMore: false };
|
|
1117
1138
|
}
|
|
1118
|
-
return this.transports.get(transportId).
|
|
1139
|
+
return this.transports.get(transportId).listLogsByRunId({ runId, fromDate, toDate, logLevel, filters, page, perPage }) ?? {
|
|
1119
1140
|
logs: [],
|
|
1120
1141
|
total: 0,
|
|
1121
1142
|
page: page ?? 1,
|
|
@@ -1125,10 +1146,15 @@ var MastraLogger = class {
|
|
|
1125
1146
|
}
|
|
1126
1147
|
};
|
|
1127
1148
|
|
|
1128
|
-
var PinoLogger = class extends MastraLogger {
|
|
1149
|
+
var PinoLogger = class _PinoLogger extends MastraLogger {
|
|
1129
1150
|
logger;
|
|
1130
1151
|
constructor(options = {}) {
|
|
1131
1152
|
super(options);
|
|
1153
|
+
const internalOptions = options;
|
|
1154
|
+
if (internalOptions._logger) {
|
|
1155
|
+
this.logger = internalOptions._logger;
|
|
1156
|
+
return;
|
|
1157
|
+
}
|
|
1132
1158
|
let prettyStream = void 0;
|
|
1133
1159
|
if (!options.overrideDefaultTransports) {
|
|
1134
1160
|
prettyStream = pretty({
|
|
@@ -1145,7 +1171,8 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1145
1171
|
{
|
|
1146
1172
|
name: options.name || "app",
|
|
1147
1173
|
level: options.level || LogLevel.INFO,
|
|
1148
|
-
formatters: options.formatters
|
|
1174
|
+
formatters: options.formatters,
|
|
1175
|
+
redact: options.redact
|
|
1149
1176
|
},
|
|
1150
1177
|
options.overrideDefaultTransports ? options?.transports?.default : transportsAry.length === 0 ? prettyStream : pino.multistream([
|
|
1151
1178
|
...transportsAry.map(([, transport]) => ({
|
|
@@ -1159,6 +1186,38 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1159
1186
|
])
|
|
1160
1187
|
);
|
|
1161
1188
|
}
|
|
1189
|
+
/**
|
|
1190
|
+
* Creates a child logger with additional bound context.
|
|
1191
|
+
* All logs from the child logger will include the bound context.
|
|
1192
|
+
*
|
|
1193
|
+
* @param bindings - Key-value pairs to include in all logs from this child logger
|
|
1194
|
+
* @returns A new PinoLogger instance with the bound context
|
|
1195
|
+
*
|
|
1196
|
+
* @example
|
|
1197
|
+
* ```typescript
|
|
1198
|
+
* const baseLogger = new PinoLogger({ name: 'MyApp' });
|
|
1199
|
+
*
|
|
1200
|
+
* // Create module-scoped logger
|
|
1201
|
+
* const serviceLogger = baseLogger.child({ module: 'UserService' });
|
|
1202
|
+
* serviceLogger.info('User created', { userId: '123' });
|
|
1203
|
+
* // Output includes: { module: 'UserService', userId: '123', msg: 'User created' }
|
|
1204
|
+
*
|
|
1205
|
+
* // Create request-scoped logger
|
|
1206
|
+
* const requestLogger = baseLogger.child({ requestId: req.id });
|
|
1207
|
+
* requestLogger.error('Request failed', { err: error });
|
|
1208
|
+
* // Output includes: { requestId: 'abc', msg: 'Request failed', err: {...} }
|
|
1209
|
+
* ```
|
|
1210
|
+
*/
|
|
1211
|
+
child(bindings) {
|
|
1212
|
+
const childPino = this.logger.child(bindings);
|
|
1213
|
+
const childOptions = {
|
|
1214
|
+
name: this.name,
|
|
1215
|
+
level: this.level,
|
|
1216
|
+
transports: Object.fromEntries(this.transports),
|
|
1217
|
+
_logger: childPino
|
|
1218
|
+
};
|
|
1219
|
+
return new _PinoLogger(childOptions);
|
|
1220
|
+
}
|
|
1162
1221
|
debug(message, args = {}) {
|
|
1163
1222
|
this.logger.debug(args, message);
|
|
1164
1223
|
}
|
|
@@ -1173,183 +1232,8 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1173
1232
|
}
|
|
1174
1233
|
};
|
|
1175
1234
|
|
|
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
|
-
}
|
|
1235
|
+
var package_default = {
|
|
1236
|
+
version: "1.0.1"};
|
|
1353
1237
|
function getPackageManagerAddCommand(pm) {
|
|
1354
1238
|
switch (pm) {
|
|
1355
1239
|
case "npm":
|
|
@@ -1370,9 +1254,9 @@ var DepsService = class {
|
|
|
1370
1254
|
this.packageManager = this.getPackageManager();
|
|
1371
1255
|
}
|
|
1372
1256
|
findLockFile(dir) {
|
|
1373
|
-
const lockFiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lock"];
|
|
1257
|
+
const lockFiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lock", "bun.lockb"];
|
|
1374
1258
|
for (const file of lockFiles) {
|
|
1375
|
-
if (
|
|
1259
|
+
if (fs3__default__default.existsSync(path3.join(dir, file))) {
|
|
1376
1260
|
return file;
|
|
1377
1261
|
}
|
|
1378
1262
|
}
|
|
@@ -1392,6 +1276,7 @@ var DepsService = class {
|
|
|
1392
1276
|
case "yarn.lock":
|
|
1393
1277
|
return "yarn";
|
|
1394
1278
|
case "bun.lock":
|
|
1279
|
+
case "bun.lockb":
|
|
1395
1280
|
return "bun";
|
|
1396
1281
|
default:
|
|
1397
1282
|
return "npm";
|
|
@@ -1411,11 +1296,11 @@ var DepsService = class {
|
|
|
1411
1296
|
try {
|
|
1412
1297
|
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1413
1298
|
try {
|
|
1414
|
-
await
|
|
1299
|
+
await fs4.access(packageJsonPath);
|
|
1415
1300
|
} catch {
|
|
1416
1301
|
return "No package.json file found in the current directory";
|
|
1417
1302
|
}
|
|
1418
|
-
const packageJson = JSON.parse(await
|
|
1303
|
+
const packageJson = JSON.parse(await fs4.readFile(packageJsonPath, "utf-8"));
|
|
1419
1304
|
for (const dependency of dependencies) {
|
|
1420
1305
|
if (!packageJson.dependencies || !packageJson.dependencies[dependency]) {
|
|
1421
1306
|
return `Please install ${dependency} before running this command (${this.packageManager} install ${dependency})`;
|
|
@@ -1430,7 +1315,7 @@ var DepsService = class {
|
|
|
1430
1315
|
async getProjectName() {
|
|
1431
1316
|
try {
|
|
1432
1317
|
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1433
|
-
const packageJson = await
|
|
1318
|
+
const packageJson = await fs4.readFile(packageJsonPath, "utf-8");
|
|
1434
1319
|
const pkg = JSON.parse(packageJson);
|
|
1435
1320
|
return pkg.name;
|
|
1436
1321
|
} catch (err) {
|
|
@@ -1438,149 +1323,37 @@ var DepsService = class {
|
|
|
1438
1323
|
}
|
|
1439
1324
|
}
|
|
1440
1325
|
async addScriptsToPackageJson(scripts) {
|
|
1441
|
-
const packageJson = JSON.parse(await
|
|
1326
|
+
const packageJson = JSON.parse(await fs4.readFile("package.json", "utf-8"));
|
|
1442
1327
|
packageJson.scripts = {
|
|
1443
1328
|
...packageJson.scripts,
|
|
1444
1329
|
...scripts
|
|
1445
1330
|
};
|
|
1446
|
-
await
|
|
1331
|
+
await fs4.writeFile("package.json", JSON.stringify(packageJson, null, 2));
|
|
1447
1332
|
}
|
|
1448
1333
|
};
|
|
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
|
-
};
|
|
1334
|
+
var EnvService = class {
|
|
1474
1335
|
};
|
|
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");
|
|
1336
|
+
var FileEnvService = class extends EnvService {
|
|
1337
|
+
filePath;
|
|
1338
|
+
constructor(filePath) {
|
|
1339
|
+
super();
|
|
1340
|
+
this.filePath = filePath;
|
|
1514
1341
|
}
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1342
|
+
readFile(filePath) {
|
|
1343
|
+
return new Promise((resolve, reject) => {
|
|
1344
|
+
fs3__default.readFile(filePath, "utf8", (err, data) => {
|
|
1345
|
+
if (err) reject(err);
|
|
1346
|
+
else resolve(data);
|
|
1347
|
+
});
|
|
1348
|
+
});
|
|
1521
1349
|
}
|
|
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
|
-
});
|
|
1350
|
+
writeFile({ filePath, data }) {
|
|
1351
|
+
return new Promise((resolve, reject) => {
|
|
1352
|
+
fs3__default.writeFile(filePath, data, "utf8", (err) => {
|
|
1353
|
+
if (err) reject(err);
|
|
1354
|
+
else resolve();
|
|
1355
|
+
});
|
|
1356
|
+
});
|
|
1584
1357
|
}
|
|
1585
1358
|
async updateEnvData({
|
|
1586
1359
|
key,
|
|
@@ -1631,8 +1404,8 @@ var FileService = class {
|
|
|
1631
1404
|
const __filename = fileURLToPath(import.meta.url);
|
|
1632
1405
|
const __dirname = path3.dirname(__filename);
|
|
1633
1406
|
const filePath = path3.resolve(__dirname, "starter-files", inputFile);
|
|
1634
|
-
const fileString =
|
|
1635
|
-
if (
|
|
1407
|
+
const fileString = fs3__default__default.readFileSync(filePath, "utf8");
|
|
1408
|
+
if (fs3__default__default.existsSync(outputFilePath) && !replaceIfExists) {
|
|
1636
1409
|
console.info(`${outputFilePath} already exists`);
|
|
1637
1410
|
return false;
|
|
1638
1411
|
}
|
|
@@ -1647,7 +1420,7 @@ var FileService = class {
|
|
|
1647
1420
|
}
|
|
1648
1421
|
getFirstExistingFile(files) {
|
|
1649
1422
|
for (const f of files) {
|
|
1650
|
-
if (
|
|
1423
|
+
if (fs3__default__default.existsSync(f)) {
|
|
1651
1424
|
return f;
|
|
1652
1425
|
}
|
|
1653
1426
|
}
|
|
@@ -1657,30 +1430,161 @@ var FileService = class {
|
|
|
1657
1430
|
filePath,
|
|
1658
1431
|
replacements
|
|
1659
1432
|
}) {
|
|
1660
|
-
let fileContent =
|
|
1433
|
+
let fileContent = fs3__default__default.readFileSync(filePath, "utf8");
|
|
1661
1434
|
replacements.forEach(({ search, replace }) => {
|
|
1662
1435
|
fileContent = fileContent.replaceAll(search, replace);
|
|
1663
1436
|
});
|
|
1664
|
-
|
|
1437
|
+
fs3__default__default.writeFileSync(filePath, fileContent);
|
|
1665
1438
|
}
|
|
1666
1439
|
};
|
|
1667
|
-
var
|
|
1440
|
+
var createArgs = (versionTag) => {
|
|
1441
|
+
const packageName = versionTag ? `@mastra/mcp-docs-server@${versionTag}` : "@mastra/mcp-docs-server";
|
|
1442
|
+
return ["-y", packageName];
|
|
1443
|
+
};
|
|
1444
|
+
var createMcpConfig = (editor, versionTag) => {
|
|
1445
|
+
const args = createArgs(versionTag);
|
|
1446
|
+
if (editor === "vscode") {
|
|
1447
|
+
return {
|
|
1448
|
+
servers: {
|
|
1449
|
+
mastra: process.platform === `win32` ? {
|
|
1450
|
+
command: "cmd",
|
|
1451
|
+
args: ["/c", "npx", ...args],
|
|
1452
|
+
type: "stdio"
|
|
1453
|
+
} : {
|
|
1454
|
+
command: "npx",
|
|
1455
|
+
args,
|
|
1456
|
+
type: "stdio"
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
return {
|
|
1462
|
+
mcpServers: {
|
|
1463
|
+
mastra: {
|
|
1464
|
+
command: "npx",
|
|
1465
|
+
args
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
};
|
|
1469
|
+
};
|
|
1470
|
+
function makeConfig(original, editor, versionTag) {
|
|
1471
|
+
if (editor === "vscode") {
|
|
1472
|
+
return {
|
|
1473
|
+
...original,
|
|
1474
|
+
servers: {
|
|
1475
|
+
...original?.servers || {},
|
|
1476
|
+
...createMcpConfig(editor, versionTag).servers
|
|
1477
|
+
}
|
|
1478
|
+
};
|
|
1479
|
+
}
|
|
1480
|
+
return {
|
|
1481
|
+
...original,
|
|
1482
|
+
mcpServers: {
|
|
1483
|
+
...original?.mcpServers || {},
|
|
1484
|
+
...createMcpConfig(editor, versionTag).mcpServers
|
|
1485
|
+
}
|
|
1486
|
+
};
|
|
1487
|
+
}
|
|
1488
|
+
async function writeMergedConfig(configPath, editor, versionTag) {
|
|
1489
|
+
const configExists = existsSync(configPath);
|
|
1490
|
+
const config = makeConfig(configExists ? await readJSON(configPath) : {}, editor, versionTag);
|
|
1491
|
+
await ensureFile(configPath);
|
|
1492
|
+
await writeJSON(configPath, config, {
|
|
1493
|
+
spaces: 2
|
|
1494
|
+
});
|
|
1495
|
+
}
|
|
1496
|
+
var windsurfGlobalMCPConfigPath = path3.join(os.homedir(), ".codeium", "windsurf", "mcp_config.json");
|
|
1497
|
+
var antigravityGlobalMCPConfigPath = path3.join(os.homedir(), ".gemini", "antigravity", "mcp_config.json");
|
|
1498
|
+
var cursorGlobalMCPConfigPath = path3.join(os.homedir(), ".cursor", "mcp.json");
|
|
1499
|
+
path3.join(process.cwd(), ".vscode", "mcp.json");
|
|
1500
|
+
var vscodeGlobalMCPConfigPath = path3.join(
|
|
1501
|
+
os.homedir(),
|
|
1502
|
+
process.platform === "win32" ? path3.join("AppData", "Roaming", "Code", "User", "settings.json") : process.platform === "darwin" ? path3.join("Library", "Application Support", "Code", "User", "settings.json") : path3.join(".config", "Code", "User", "settings.json")
|
|
1503
|
+
);
|
|
1504
|
+
async function installMastraDocsMCPServer({
|
|
1505
|
+
editor,
|
|
1506
|
+
directory,
|
|
1507
|
+
versionTag
|
|
1508
|
+
}) {
|
|
1509
|
+
if (editor === `cursor`) {
|
|
1510
|
+
await writeMergedConfig(path3.join(directory, ".cursor", "mcp.json"), "cursor", versionTag);
|
|
1511
|
+
}
|
|
1512
|
+
if (editor === `vscode`) {
|
|
1513
|
+
await writeMergedConfig(path3.join(directory, ".vscode", "mcp.json"), "vscode", versionTag);
|
|
1514
|
+
}
|
|
1515
|
+
if (editor === `cursor-global`) {
|
|
1516
|
+
const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor, versionTag);
|
|
1517
|
+
if (alreadyInstalled) {
|
|
1518
|
+
return;
|
|
1519
|
+
}
|
|
1520
|
+
await writeMergedConfig(cursorGlobalMCPConfigPath, "cursor-global", versionTag);
|
|
1521
|
+
}
|
|
1522
|
+
if (editor === `windsurf`) {
|
|
1523
|
+
const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor, versionTag);
|
|
1524
|
+
if (alreadyInstalled) {
|
|
1525
|
+
return;
|
|
1526
|
+
}
|
|
1527
|
+
await writeMergedConfig(windsurfGlobalMCPConfigPath, editor, versionTag);
|
|
1528
|
+
}
|
|
1529
|
+
if (editor === `antigravity`) {
|
|
1530
|
+
const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor, versionTag);
|
|
1531
|
+
if (alreadyInstalled) {
|
|
1532
|
+
return;
|
|
1533
|
+
}
|
|
1534
|
+
await writeMergedConfig(antigravityGlobalMCPConfigPath, editor, versionTag);
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
async function globalMCPIsAlreadyInstalled(editor, versionTag) {
|
|
1538
|
+
let configPath = ``;
|
|
1539
|
+
if (editor === "windsurf") {
|
|
1540
|
+
configPath = windsurfGlobalMCPConfigPath;
|
|
1541
|
+
} else if (editor === "antigravity") {
|
|
1542
|
+
configPath = antigravityGlobalMCPConfigPath;
|
|
1543
|
+
} else if (editor === "cursor-global") {
|
|
1544
|
+
configPath = cursorGlobalMCPConfigPath;
|
|
1545
|
+
} else if (editor === "vscode") {
|
|
1546
|
+
configPath = vscodeGlobalMCPConfigPath;
|
|
1547
|
+
}
|
|
1548
|
+
if (!configPath || !existsSync(configPath)) {
|
|
1549
|
+
return false;
|
|
1550
|
+
}
|
|
1551
|
+
try {
|
|
1552
|
+
const configContents = await readJSON(configPath);
|
|
1553
|
+
if (!configContents) return false;
|
|
1554
|
+
const expectedPackage = versionTag ? `@mastra/mcp-docs-server@${versionTag}` : "@mastra/mcp-docs-server";
|
|
1555
|
+
if (editor === "vscode") {
|
|
1556
|
+
if (!configContents.servers) return false;
|
|
1557
|
+
const hasMastraMCP2 = Object.values(configContents.servers).some(
|
|
1558
|
+
(server) => server?.args?.find((arg) => arg === expectedPackage)
|
|
1559
|
+
);
|
|
1560
|
+
return hasMastraMCP2;
|
|
1561
|
+
}
|
|
1562
|
+
if (!configContents?.mcpServers) return false;
|
|
1563
|
+
const hasMastraMCP = Object.values(configContents.mcpServers).some(
|
|
1564
|
+
(server) => server?.args?.find((arg) => arg === expectedPackage)
|
|
1565
|
+
);
|
|
1566
|
+
return hasMastraMCP;
|
|
1567
|
+
} catch {
|
|
1568
|
+
return false;
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
var exec = util.promisify(child_process.exec);
|
|
1668
1572
|
var getModelIdentifier = (llmProvider) => {
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
return `'anthropic/claude-3-5-sonnet-20241022'`;
|
|
1573
|
+
let model = "openai/gpt-4o";
|
|
1574
|
+
if (llmProvider === "anthropic") {
|
|
1575
|
+
model = "anthropic/claude-sonnet-4-5";
|
|
1673
1576
|
} else if (llmProvider === "groq") {
|
|
1674
|
-
|
|
1577
|
+
model = "groq/llama-3.3-70b-versatile";
|
|
1675
1578
|
} else if (llmProvider === "google") {
|
|
1676
|
-
|
|
1579
|
+
model = "google/gemini-2.5-pro";
|
|
1677
1580
|
} else if (llmProvider === "cerebras") {
|
|
1678
|
-
|
|
1581
|
+
model = "cerebras/llama-3.3-70b";
|
|
1679
1582
|
} else if (llmProvider === "mistral") {
|
|
1680
|
-
|
|
1583
|
+
model = "mistral/mistral-medium-2508";
|
|
1681
1584
|
}
|
|
1585
|
+
return model;
|
|
1682
1586
|
};
|
|
1683
|
-
async function writeAgentSample(llmProvider, destPath, addExampleTool) {
|
|
1587
|
+
async function writeAgentSample(llmProvider, destPath, addExampleTool, addScorers) {
|
|
1684
1588
|
const modelString = getModelIdentifier(llmProvider);
|
|
1685
1589
|
const instructions = `
|
|
1686
1590
|
You are a helpful weather assistant that provides accurate weather information and can help planning activities based on the weather.
|
|
@@ -1699,27 +1603,47 @@ async function writeAgentSample(llmProvider, destPath, addExampleTool) {
|
|
|
1699
1603
|
const content = `
|
|
1700
1604
|
import { Agent } from '@mastra/core/agent';
|
|
1701
1605
|
import { Memory } from '@mastra/memory';
|
|
1702
|
-
import { LibSQLStore } from '@mastra/libsql';
|
|
1703
1606
|
${addExampleTool ? `import { weatherTool } from '../tools/weather-tool';` : ""}
|
|
1607
|
+
${addScorers ? `import { scorers } from '../scorers/weather-scorer';` : ""}
|
|
1704
1608
|
|
|
1705
1609
|
export const weatherAgent = new Agent({
|
|
1610
|
+
id: 'weather-agent',
|
|
1706
1611
|
name: 'Weather Agent',
|
|
1707
1612
|
instructions: \`${instructions}\`,
|
|
1708
|
-
model: ${modelString},
|
|
1613
|
+
model: '${modelString}',
|
|
1709
1614
|
${addExampleTool ? "tools: { weatherTool }," : ""}
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1615
|
+
${addScorers ? `scorers: {
|
|
1616
|
+
toolCallAppropriateness: {
|
|
1617
|
+
scorer: scorers.toolCallAppropriatenessScorer,
|
|
1618
|
+
sampling: {
|
|
1619
|
+
type: 'ratio',
|
|
1620
|
+
rate: 1,
|
|
1621
|
+
},
|
|
1622
|
+
},
|
|
1623
|
+
completeness: {
|
|
1624
|
+
scorer: scorers.completenessScorer,
|
|
1625
|
+
sampling: {
|
|
1626
|
+
type: 'ratio',
|
|
1627
|
+
rate: 1,
|
|
1628
|
+
},
|
|
1629
|
+
},
|
|
1630
|
+
translation: {
|
|
1631
|
+
scorer: scorers.translationScorer,
|
|
1632
|
+
sampling: {
|
|
1633
|
+
type: 'ratio',
|
|
1634
|
+
rate: 1,
|
|
1635
|
+
},
|
|
1636
|
+
},
|
|
1637
|
+
},` : ""}
|
|
1638
|
+
memory: new Memory()
|
|
1715
1639
|
});
|
|
1716
1640
|
`;
|
|
1717
1641
|
const formattedContent = await prettier.format(content, {
|
|
1718
1642
|
parser: "typescript",
|
|
1719
1643
|
singleQuote: true
|
|
1720
1644
|
});
|
|
1721
|
-
await
|
|
1722
|
-
await
|
|
1645
|
+
await fs4.writeFile(destPath, "");
|
|
1646
|
+
await fs4.writeFile(destPath, formattedContent);
|
|
1723
1647
|
}
|
|
1724
1648
|
async function writeWorkflowSample(destPath) {
|
|
1725
1649
|
const content = `import { createStep, createWorkflow } from '@mastra/core/workflows';
|
|
@@ -1912,20 +1836,115 @@ export { weatherWorkflow };`;
|
|
|
1912
1836
|
semi: true,
|
|
1913
1837
|
singleQuote: true
|
|
1914
1838
|
});
|
|
1915
|
-
await
|
|
1839
|
+
await fs4.writeFile(destPath, formattedContent);
|
|
1916
1840
|
}
|
|
1917
1841
|
async function writeToolSample(destPath) {
|
|
1918
1842
|
const fileService = new FileService();
|
|
1919
1843
|
await fileService.copyStarterFile("tools.ts", destPath);
|
|
1920
1844
|
}
|
|
1845
|
+
async function writeScorersSample(llmProvider, destPath) {
|
|
1846
|
+
const modelString = getModelIdentifier(llmProvider);
|
|
1847
|
+
const content = `import { z } from 'zod';
|
|
1848
|
+
import { createToolCallAccuracyScorerCode } from '@mastra/evals/scorers/prebuilt';
|
|
1849
|
+
import { createCompletenessScorer } from '@mastra/evals/scorers/prebuilt';
|
|
1850
|
+
import { getAssistantMessageFromRunOutput, getUserMessageFromRunInput } from '@mastra/evals/scorers/utils';
|
|
1851
|
+
import { createScorer } from '@mastra/core/evals';
|
|
1852
|
+
|
|
1853
|
+
export const toolCallAppropriatenessScorer = createToolCallAccuracyScorerCode({
|
|
1854
|
+
expectedTool: 'weatherTool',
|
|
1855
|
+
strictMode: false,
|
|
1856
|
+
});
|
|
1857
|
+
|
|
1858
|
+
export const completenessScorer = createCompletenessScorer();
|
|
1859
|
+
|
|
1860
|
+
// Custom LLM-judged scorer: evaluates if non-English locations are translated appropriately
|
|
1861
|
+
export const translationScorer = createScorer({
|
|
1862
|
+
id: 'translation-quality-scorer',
|
|
1863
|
+
name: 'Translation Quality',
|
|
1864
|
+
description: 'Checks that non-English location names are translated and used correctly',
|
|
1865
|
+
type: 'agent',
|
|
1866
|
+
judge: {
|
|
1867
|
+
model: '${modelString}',
|
|
1868
|
+
instructions:
|
|
1869
|
+
'You are an expert evaluator of translation quality for geographic locations. ' +
|
|
1870
|
+
'Determine whether the user text mentions a non-English location and whether the assistant correctly uses an English translation of that location. ' +
|
|
1871
|
+
'Be lenient with transliteration differences and diacritics. ' +
|
|
1872
|
+
'Return only the structured JSON matching the provided schema.',
|
|
1873
|
+
},
|
|
1874
|
+
})
|
|
1875
|
+
.preprocess(({ run }) => {
|
|
1876
|
+
const userText = getUserMessageFromRunInput(run.input) || '';
|
|
1877
|
+
const assistantText = getAssistantMessageFromRunOutput(run.output) || '';
|
|
1878
|
+
return { userText, assistantText };
|
|
1879
|
+
})
|
|
1880
|
+
.analyze({
|
|
1881
|
+
description: 'Extract location names and detect language/translation adequacy',
|
|
1882
|
+
outputSchema: z.object({
|
|
1883
|
+
nonEnglish: z.boolean(),
|
|
1884
|
+
translated: z.boolean(),
|
|
1885
|
+
confidence: z.number().min(0).max(1).default(1),
|
|
1886
|
+
explanation: z.string().default(''),
|
|
1887
|
+
}),
|
|
1888
|
+
createPrompt: ({ results }) => \`
|
|
1889
|
+
You are evaluating if a weather assistant correctly handled translation of a non-English location.
|
|
1890
|
+
User text:
|
|
1891
|
+
"""
|
|
1892
|
+
\${results.preprocessStepResult.userText}
|
|
1893
|
+
"""
|
|
1894
|
+
Assistant response:
|
|
1895
|
+
"""
|
|
1896
|
+
\${results.preprocessStepResult.assistantText}
|
|
1897
|
+
"""
|
|
1898
|
+
Tasks:
|
|
1899
|
+
1) Identify if the user mentioned a location that appears non-English.
|
|
1900
|
+
2) If non-English, check whether the assistant used a correct English translation of that location in its response.
|
|
1901
|
+
3) Be lenient with transliteration differences (e.g., accents/diacritics).
|
|
1902
|
+
Return JSON with fields:
|
|
1903
|
+
{
|
|
1904
|
+
"nonEnglish": boolean,
|
|
1905
|
+
"translated": boolean,
|
|
1906
|
+
"confidence": number, // 0-1
|
|
1907
|
+
"explanation": string
|
|
1908
|
+
}
|
|
1909
|
+
\`,
|
|
1910
|
+
})
|
|
1911
|
+
.generateScore(({ results }) => {
|
|
1912
|
+
const r = (results as any)?.analyzeStepResult || {};
|
|
1913
|
+
if (!r.nonEnglish) return 1; // If not applicable, full credit
|
|
1914
|
+
if (r.translated) return Math.max(0, Math.min(1, 0.7 + 0.3 * (r.confidence ?? 1)));
|
|
1915
|
+
return 0; // Non-English but not translated
|
|
1916
|
+
})
|
|
1917
|
+
.generateReason(({ results, score }) => {
|
|
1918
|
+
const r = (results as any)?.analyzeStepResult || {};
|
|
1919
|
+
return \`Translation scoring: nonEnglish=\${r.nonEnglish ?? false}, translated=\${r.translated ?? false}, confidence=\${r.confidence ?? 0}. Score=\${score}. \${r.explanation ?? ''}\`;
|
|
1920
|
+
});
|
|
1921
|
+
|
|
1922
|
+
export const scorers = {
|
|
1923
|
+
toolCallAppropriatenessScorer,
|
|
1924
|
+
completenessScorer,
|
|
1925
|
+
translationScorer,
|
|
1926
|
+
};`;
|
|
1927
|
+
const formattedContent = await prettier.format(content, {
|
|
1928
|
+
parser: "typescript",
|
|
1929
|
+
singleQuote: true
|
|
1930
|
+
});
|
|
1931
|
+
await fs4.writeFile(destPath, formattedContent);
|
|
1932
|
+
}
|
|
1921
1933
|
async function writeCodeSampleForComponents(llmprovider, component, destPath, importComponents) {
|
|
1922
1934
|
switch (component) {
|
|
1923
1935
|
case "agents":
|
|
1924
|
-
return writeAgentSample(
|
|
1936
|
+
return writeAgentSample(
|
|
1937
|
+
llmprovider,
|
|
1938
|
+
destPath,
|
|
1939
|
+
importComponents.includes("tools"),
|
|
1940
|
+
importComponents.includes("scorers")
|
|
1941
|
+
);
|
|
1925
1942
|
case "tools":
|
|
1926
1943
|
return writeToolSample(destPath);
|
|
1927
1944
|
case "workflows":
|
|
1928
1945
|
return writeWorkflowSample(destPath);
|
|
1946
|
+
case "scorers":
|
|
1947
|
+
return writeScorersSample(llmprovider, destPath);
|
|
1929
1948
|
default:
|
|
1930
1949
|
return "";
|
|
1931
1950
|
}
|
|
@@ -1938,39 +1957,44 @@ var writeIndexFile = async ({
|
|
|
1938
1957
|
dirPath,
|
|
1939
1958
|
addAgent,
|
|
1940
1959
|
addExample,
|
|
1941
|
-
addWorkflow
|
|
1960
|
+
addWorkflow,
|
|
1961
|
+
addScorers
|
|
1942
1962
|
}) => {
|
|
1943
1963
|
const indexPath = dirPath + "/index.ts";
|
|
1944
1964
|
const destPath = path3.join(indexPath);
|
|
1945
1965
|
try {
|
|
1946
|
-
await
|
|
1966
|
+
await fs4.writeFile(destPath, "");
|
|
1947
1967
|
const filteredExports = [
|
|
1948
1968
|
addWorkflow ? `workflows: { weatherWorkflow },` : "",
|
|
1949
|
-
addAgent ? `agents: { weatherAgent },` : ""
|
|
1969
|
+
addAgent ? `agents: { weatherAgent },` : "",
|
|
1970
|
+
addScorers ? `scorers: { toolCallAppropriatenessScorer, completenessScorer, translationScorer },` : ""
|
|
1950
1971
|
].filter(Boolean);
|
|
1951
1972
|
if (!addExample) {
|
|
1952
|
-
await
|
|
1973
|
+
await fs4.writeFile(
|
|
1953
1974
|
destPath,
|
|
1954
1975
|
`
|
|
1955
|
-
import { Mastra } from '@mastra/core';
|
|
1976
|
+
import { Mastra } from '@mastra/core/mastra';
|
|
1956
1977
|
|
|
1957
1978
|
export const mastra = new Mastra()
|
|
1958
1979
|
`
|
|
1959
1980
|
);
|
|
1960
1981
|
return;
|
|
1961
1982
|
}
|
|
1962
|
-
await
|
|
1983
|
+
await fs4.writeFile(
|
|
1963
1984
|
destPath,
|
|
1964
1985
|
`
|
|
1965
1986
|
import { Mastra } from '@mastra/core/mastra';
|
|
1966
1987
|
import { PinoLogger } from '@mastra/loggers';
|
|
1967
1988
|
import { LibSQLStore } from '@mastra/libsql';
|
|
1989
|
+
import { Observability, DefaultExporter, CloudExporter, SensitiveDataFilter } from '@mastra/observability';
|
|
1968
1990
|
${addWorkflow ? `import { weatherWorkflow } from './workflows/weather-workflow';` : ""}
|
|
1969
1991
|
${addAgent ? `import { weatherAgent } from './agents/weather-agent';` : ""}
|
|
1992
|
+
${addScorers ? `import { toolCallAppropriatenessScorer, completenessScorer, translationScorer } from './scorers/weather-scorer';` : ""}
|
|
1970
1993
|
|
|
1971
1994
|
export const mastra = new Mastra({
|
|
1972
1995
|
${filteredExports.join("\n ")}
|
|
1973
1996
|
storage: new LibSQLStore({
|
|
1997
|
+
id: "mastra-storage",
|
|
1974
1998
|
// stores observability, scores, ... into memory storage, if it needs to persist, change to file:../mastra.db
|
|
1975
1999
|
url: ":memory:",
|
|
1976
2000
|
}),
|
|
@@ -1978,14 +2002,20 @@ export const mastra = new Mastra({
|
|
|
1978
2002
|
name: 'Mastra',
|
|
1979
2003
|
level: 'info',
|
|
1980
2004
|
}),
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
2005
|
+
observability: new Observability({
|
|
2006
|
+
configs: {
|
|
2007
|
+
default: {
|
|
2008
|
+
serviceName: 'mastra',
|
|
2009
|
+
exporters: [
|
|
2010
|
+
new DefaultExporter(), // Persists traces to storage for Mastra Studio
|
|
2011
|
+
new CloudExporter(), // Sends traces to Mastra Cloud (if MASTRA_CLOUD_ACCESS_TOKEN is set)
|
|
2012
|
+
],
|
|
2013
|
+
spanOutputProcessors: [
|
|
2014
|
+
new SensitiveDataFilter(), // Redacts sensitive data like passwords, tokens, keys
|
|
2015
|
+
],
|
|
2016
|
+
},
|
|
2017
|
+
},
|
|
2018
|
+
}),
|
|
1989
2019
|
});
|
|
1990
2020
|
`
|
|
1991
2021
|
);
|
|
@@ -1993,7 +2023,6 @@ export const mastra = new Mastra({
|
|
|
1993
2023
|
throw err;
|
|
1994
2024
|
}
|
|
1995
2025
|
};
|
|
1996
|
-
yoctoSpinner({ text: "Installing Mastra core dependencies\n" });
|
|
1997
2026
|
var getAPIKey = async (provider) => {
|
|
1998
2027
|
let key = "OPENAI_API_KEY";
|
|
1999
2028
|
switch (provider) {
|
|
@@ -2019,15 +2048,15 @@ var getAPIKey = async (provider) => {
|
|
|
2019
2048
|
var writeAPIKey = async ({ provider, apiKey }) => {
|
|
2020
2049
|
const envFileName = apiKey ? ".env" : ".env.example";
|
|
2021
2050
|
const key = await getAPIKey(provider);
|
|
2022
|
-
const escapedKey =
|
|
2023
|
-
const escapedApiKey =
|
|
2024
|
-
await
|
|
2051
|
+
const escapedKey = shellQuote2.quote([key]);
|
|
2052
|
+
const escapedApiKey = shellQuote2.quote([apiKey ? apiKey : "your-api-key"]);
|
|
2053
|
+
await exec(`echo ${escapedKey}=${escapedApiKey} >> ${envFileName}`);
|
|
2025
2054
|
};
|
|
2026
2055
|
var createMastraDir = async (directory) => {
|
|
2027
2056
|
let dir = directory.trim().split("/").filter((item) => item !== "");
|
|
2028
2057
|
const dirPath = path3.join(process.cwd(), ...dir, "mastra");
|
|
2029
2058
|
try {
|
|
2030
|
-
await
|
|
2059
|
+
await fs4.access(dirPath);
|
|
2031
2060
|
return { ok: false };
|
|
2032
2061
|
} catch {
|
|
2033
2062
|
await fsExtra.ensureDir(dirPath);
|
|
@@ -2050,8 +2079,8 @@ var LLM_PROVIDERS = [
|
|
|
2050
2079
|
{ value: "cerebras", label: "Cerebras" },
|
|
2051
2080
|
{ value: "mistral", label: "Mistral" }
|
|
2052
2081
|
];
|
|
2053
|
-
var interactivePrompt = async (
|
|
2054
|
-
const { skip = {}, options: { showBanner = true } = {} } =
|
|
2082
|
+
var interactivePrompt = async (args = {}) => {
|
|
2083
|
+
const { skip = {}, options: { showBanner = true } = {} } = args;
|
|
2055
2084
|
if (showBanner) {
|
|
2056
2085
|
Ie(color2.inverse(" Mastra Init "));
|
|
2057
2086
|
}
|
|
@@ -2089,46 +2118,33 @@ var interactivePrompt = async (args2 = {}) => {
|
|
|
2089
2118
|
return void 0;
|
|
2090
2119
|
},
|
|
2091
2120
|
configureEditorWithDocsMCP: async () => {
|
|
2092
|
-
const windsurfIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`windsurf`);
|
|
2093
|
-
const cursorIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`cursor`);
|
|
2094
|
-
const vscodeIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`vscode`);
|
|
2095
2121
|
const editor = await ve({
|
|
2096
2122
|
message: `Make your IDE into a Mastra expert? (Installs Mastra's MCP server)`,
|
|
2097
2123
|
options: [
|
|
2098
2124
|
{ value: "skip", label: "Skip for now", hint: "default" },
|
|
2099
2125
|
{
|
|
2100
2126
|
value: "cursor",
|
|
2101
|
-
label: "Cursor (project only)"
|
|
2102
|
-
hint: cursorIsAlreadyInstalled ? `Already installed globally` : void 0
|
|
2127
|
+
label: "Cursor (project only)"
|
|
2103
2128
|
},
|
|
2104
2129
|
{
|
|
2105
2130
|
value: "cursor-global",
|
|
2106
|
-
label: "Cursor (global, all projects)"
|
|
2107
|
-
hint: cursorIsAlreadyInstalled ? `Already installed` : void 0
|
|
2131
|
+
label: "Cursor (global, all projects)"
|
|
2108
2132
|
},
|
|
2109
2133
|
{
|
|
2110
2134
|
value: "windsurf",
|
|
2111
|
-
label: "Windsurf"
|
|
2112
|
-
hint: windsurfIsAlreadyInstalled ? `Already installed` : void 0
|
|
2135
|
+
label: "Windsurf"
|
|
2113
2136
|
},
|
|
2114
2137
|
{
|
|
2115
2138
|
value: "vscode",
|
|
2116
|
-
label: "VSCode"
|
|
2117
|
-
|
|
2139
|
+
label: "VSCode"
|
|
2140
|
+
},
|
|
2141
|
+
{
|
|
2142
|
+
value: "antigravity",
|
|
2143
|
+
label: "Antigravity"
|
|
2118
2144
|
}
|
|
2119
2145
|
]
|
|
2120
2146
|
});
|
|
2121
2147
|
if (editor === `skip`) return void 0;
|
|
2122
|
-
if (editor === `windsurf` && windsurfIsAlreadyInstalled) {
|
|
2123
|
-
M.message(`
|
|
2124
|
-
Windsurf is already installed, skipping.`);
|
|
2125
|
-
return void 0;
|
|
2126
|
-
}
|
|
2127
|
-
if (editor === `vscode` && vscodeIsAlreadyInstalled) {
|
|
2128
|
-
M.message(`
|
|
2129
|
-
VSCode is already installed, skipping.`);
|
|
2130
|
-
return void 0;
|
|
2131
|
-
}
|
|
2132
2148
|
if (editor === `cursor`) {
|
|
2133
2149
|
M.message(
|
|
2134
2150
|
`
|
|
@@ -2137,19 +2153,19 @@ Note: you will need to go into Cursor Settings -> MCP Settings and manually enab
|
|
|
2137
2153
|
);
|
|
2138
2154
|
}
|
|
2139
2155
|
if (editor === `cursor-global`) {
|
|
2140
|
-
const
|
|
2156
|
+
const confirm3 = await ve({
|
|
2141
2157
|
message: `Global install will add/update ${cursorGlobalMCPConfigPath} and make the Mastra docs MCP server available in all your Cursor projects. Continue?`,
|
|
2142
2158
|
options: [
|
|
2143
2159
|
{ value: "yes", label: "Yes, I understand" },
|
|
2144
2160
|
{ value: "skip", label: "No, skip for now" }
|
|
2145
2161
|
]
|
|
2146
2162
|
});
|
|
2147
|
-
if (
|
|
2163
|
+
if (confirm3 !== `yes`) {
|
|
2148
2164
|
return void 0;
|
|
2149
2165
|
}
|
|
2150
2166
|
}
|
|
2151
2167
|
if (editor === `windsurf`) {
|
|
2152
|
-
const
|
|
2168
|
+
const confirm3 = await ve({
|
|
2153
2169
|
message: `Windsurf only supports a global MCP config (at ${windsurfGlobalMCPConfigPath}) is it ok to add/update that global config?
|
|
2154
2170
|
This means the Mastra docs MCP server will be available in all your Windsurf projects.`,
|
|
2155
2171
|
options: [
|
|
@@ -2157,11 +2173,31 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
2157
2173
|
{ value: "skip", label: "No, skip for now" }
|
|
2158
2174
|
]
|
|
2159
2175
|
});
|
|
2160
|
-
if (
|
|
2176
|
+
if (confirm3 !== `yes`) {
|
|
2177
|
+
return void 0;
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
if (editor === `antigravity`) {
|
|
2181
|
+
const confirm3 = await ve({
|
|
2182
|
+
message: `Antigravity only supports a global MCP config (at ${antigravityGlobalMCPConfigPath}). Is it ok to add/update that global config?
|
|
2183
|
+
This will make the Mastra docs MCP server available in all Antigravity projects.`,
|
|
2184
|
+
options: [
|
|
2185
|
+
{ value: "yes", label: "Yes, I understand" },
|
|
2186
|
+
{ value: "skip", label: "No, skip for now" }
|
|
2187
|
+
]
|
|
2188
|
+
});
|
|
2189
|
+
if (confirm3 !== `yes`) {
|
|
2161
2190
|
return void 0;
|
|
2162
2191
|
}
|
|
2163
2192
|
}
|
|
2164
2193
|
return editor;
|
|
2194
|
+
},
|
|
2195
|
+
initGit: async () => {
|
|
2196
|
+
if (skip?.gitInit) return false;
|
|
2197
|
+
return ye({
|
|
2198
|
+
message: "Initialize a new git repository?",
|
|
2199
|
+
initialValue: true
|
|
2200
|
+
});
|
|
2165
2201
|
}
|
|
2166
2202
|
},
|
|
2167
2203
|
{
|
|
@@ -2173,16 +2209,245 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
2173
2209
|
);
|
|
2174
2210
|
return mastraProject;
|
|
2175
2211
|
};
|
|
2212
|
+
function getPackageManager() {
|
|
2213
|
+
const userAgent = process.env.npm_config_user_agent || "";
|
|
2214
|
+
const execPath = process.env.npm_execpath || "";
|
|
2215
|
+
if (userAgent.includes("bun")) {
|
|
2216
|
+
return "bun";
|
|
2217
|
+
}
|
|
2218
|
+
if (userAgent.includes("yarn")) {
|
|
2219
|
+
return "yarn";
|
|
2220
|
+
}
|
|
2221
|
+
if (userAgent.includes("pnpm")) {
|
|
2222
|
+
return "pnpm";
|
|
2223
|
+
}
|
|
2224
|
+
if (userAgent.includes("npm")) {
|
|
2225
|
+
return "npm";
|
|
2226
|
+
}
|
|
2227
|
+
if (execPath.includes("bun")) {
|
|
2228
|
+
return "bun";
|
|
2229
|
+
}
|
|
2230
|
+
if (execPath.includes("yarn")) {
|
|
2231
|
+
return "yarn";
|
|
2232
|
+
}
|
|
2233
|
+
if (execPath.includes("pnpm")) {
|
|
2234
|
+
return "pnpm";
|
|
2235
|
+
}
|
|
2236
|
+
if (execPath.includes("npm")) {
|
|
2237
|
+
return "npm";
|
|
2238
|
+
}
|
|
2239
|
+
return "npm";
|
|
2240
|
+
}
|
|
2241
|
+
async function gitInit({ cwd }) {
|
|
2242
|
+
await execa("git", ["init"], { cwd, stdio: "ignore" });
|
|
2243
|
+
await execa("git", ["add", "-A"], { cwd, stdio: "ignore" });
|
|
2244
|
+
await execa(
|
|
2245
|
+
"git",
|
|
2246
|
+
[
|
|
2247
|
+
"commit",
|
|
2248
|
+
"-m",
|
|
2249
|
+
'"Initial commit from Mastra"',
|
|
2250
|
+
'--author="dane-ai-mastra[bot] <dane-ai-mastra[bot]@users.noreply.github.com>"'
|
|
2251
|
+
],
|
|
2252
|
+
{ cwd, stdio: "ignore" }
|
|
2253
|
+
);
|
|
2254
|
+
}
|
|
2255
|
+
var logger = createLogger(false);
|
|
2256
|
+
function createLogger(debug = false) {
|
|
2257
|
+
return new PinoLogger({
|
|
2258
|
+
name: "Mastra CLI",
|
|
2259
|
+
level: debug ? "debug" : "info"
|
|
2260
|
+
});
|
|
2261
|
+
}
|
|
2262
|
+
var exec2 = util.promisify(child_process.exec);
|
|
2263
|
+
async function cloneTemplate(options) {
|
|
2264
|
+
const { template, projectName, targetDir, branch, llmProvider } = options;
|
|
2265
|
+
const projectPath = targetDir ? path3.resolve(targetDir, projectName) : path3.resolve(projectName);
|
|
2266
|
+
const spinner4 = yoctoSpinner({ text: `Cloning template "${template.title}"...` }).start();
|
|
2267
|
+
try {
|
|
2268
|
+
if (await directoryExists(projectPath)) {
|
|
2269
|
+
spinner4.error(`Directory ${projectName} already exists`);
|
|
2270
|
+
throw new Error(`Directory ${projectName} already exists`);
|
|
2271
|
+
}
|
|
2272
|
+
await cloneRepositoryWithoutGit(template.githubUrl, projectPath, branch);
|
|
2273
|
+
await updatePackageJson(projectPath, projectName);
|
|
2274
|
+
const envExamplePath = path3.join(projectPath, ".env.example");
|
|
2275
|
+
if (await fileExists(envExamplePath)) {
|
|
2276
|
+
const envPath = path3.join(projectPath, ".env");
|
|
2277
|
+
await fs4.copyFile(envExamplePath, envPath);
|
|
2278
|
+
if (llmProvider) {
|
|
2279
|
+
await updateEnvFile(envPath, llmProvider);
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
spinner4.success(`Template "${template.title}" cloned successfully to ${projectName}`);
|
|
2283
|
+
return projectPath;
|
|
2284
|
+
} catch (error) {
|
|
2285
|
+
spinner4.error(`Failed to clone template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2286
|
+
throw error;
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
async function directoryExists(dirPath) {
|
|
2290
|
+
try {
|
|
2291
|
+
const stat = await fs4.stat(dirPath);
|
|
2292
|
+
return stat.isDirectory();
|
|
2293
|
+
} catch {
|
|
2294
|
+
return false;
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
async function fileExists(filePath) {
|
|
2298
|
+
try {
|
|
2299
|
+
const stat = await fs4.stat(filePath);
|
|
2300
|
+
return stat.isFile();
|
|
2301
|
+
} catch {
|
|
2302
|
+
return false;
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
async function cloneRepositoryWithoutGit(repoUrl, targetPath, branch) {
|
|
2306
|
+
await fs4.mkdir(targetPath, { recursive: true });
|
|
2307
|
+
try {
|
|
2308
|
+
const degitRepo = repoUrl.replace("https://github.com/", "");
|
|
2309
|
+
const degitRepoWithBranch = branch ? `${degitRepo}#${branch}` : degitRepo;
|
|
2310
|
+
const degitCommand = shellQuote2.quote(["npx", "degit", degitRepoWithBranch, targetPath]);
|
|
2311
|
+
await exec2(degitCommand, {
|
|
2312
|
+
cwd: process.cwd()
|
|
2313
|
+
});
|
|
2314
|
+
} catch {
|
|
2315
|
+
try {
|
|
2316
|
+
const gitArgs = ["git", "clone"];
|
|
2317
|
+
if (branch) {
|
|
2318
|
+
gitArgs.push("--branch", branch);
|
|
2319
|
+
}
|
|
2320
|
+
gitArgs.push(repoUrl, targetPath);
|
|
2321
|
+
const gitCommand = shellQuote2.quote(gitArgs);
|
|
2322
|
+
await exec2(gitCommand, {
|
|
2323
|
+
cwd: process.cwd()
|
|
2324
|
+
});
|
|
2325
|
+
const gitDir = path3.join(targetPath, ".git");
|
|
2326
|
+
if (await directoryExists(gitDir)) {
|
|
2327
|
+
await fs4.rm(gitDir, { recursive: true, force: true });
|
|
2328
|
+
}
|
|
2329
|
+
} catch (gitError) {
|
|
2330
|
+
throw new Error(`Failed to clone repository: ${gitError instanceof Error ? gitError.message : "Unknown error"}`);
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
async function updatePackageJson(projectPath, projectName) {
|
|
2335
|
+
const packageJsonPath = path3.join(projectPath, "package.json");
|
|
2336
|
+
try {
|
|
2337
|
+
const packageJsonContent = await fs4.readFile(packageJsonPath, "utf-8");
|
|
2338
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
2339
|
+
packageJson.name = projectName;
|
|
2340
|
+
await fs4.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf-8");
|
|
2341
|
+
} catch (error) {
|
|
2342
|
+
logger.warn(`Could not update package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
2345
|
+
async function updateEnvFile(envPath, llmProvider) {
|
|
2346
|
+
try {
|
|
2347
|
+
const envContent = await fs4.readFile(envPath, "utf-8");
|
|
2348
|
+
const modelString = getModelIdentifier(llmProvider);
|
|
2349
|
+
if (!modelString) {
|
|
2350
|
+
logger.warn(`Could not get model identifier for provider: ${llmProvider}`);
|
|
2351
|
+
return;
|
|
2352
|
+
}
|
|
2353
|
+
const modelValue = modelString.replace(/'/g, "");
|
|
2354
|
+
const updatedContent = envContent.replace(/^MODEL=.*/m, `MODEL=${modelValue}`);
|
|
2355
|
+
await fs4.writeFile(envPath, updatedContent, "utf-8");
|
|
2356
|
+
logger.info(`Updated MODEL in .env to ${modelValue}`);
|
|
2357
|
+
} catch (error) {
|
|
2358
|
+
logger.warn(`Could not update .env file: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
async function installDependencies(projectPath, packageManager) {
|
|
2362
|
+
const spinner4 = yoctoSpinner({ text: "Installing dependencies..." }).start();
|
|
2363
|
+
try {
|
|
2364
|
+
const pm = packageManager || getPackageManager();
|
|
2365
|
+
const installCommand = shellQuote2.quote([pm, "install"]);
|
|
2366
|
+
await exec2(installCommand, {
|
|
2367
|
+
cwd: projectPath
|
|
2368
|
+
});
|
|
2369
|
+
spinner4.success("Dependencies installed successfully");
|
|
2370
|
+
} catch (error) {
|
|
2371
|
+
spinner4.error(`Failed to install dependencies: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2372
|
+
throw error;
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
var TEMPLATES_API_URL = process.env.MASTRA_TEMPLATES_API_URL || "https://mastra.ai/api/templates.json";
|
|
2376
|
+
async function loadTemplates() {
|
|
2377
|
+
try {
|
|
2378
|
+
const response = await fetch(TEMPLATES_API_URL);
|
|
2379
|
+
if (!response.ok) {
|
|
2380
|
+
throw new Error(`Failed to fetch templates: ${response.statusText}`);
|
|
2381
|
+
}
|
|
2382
|
+
const templates = await response.json();
|
|
2383
|
+
return templates;
|
|
2384
|
+
} catch (error) {
|
|
2385
|
+
console.error("Error loading templates:", error);
|
|
2386
|
+
throw new Error("Failed to load templates. Please check your internet connection and try again.");
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
2389
|
+
function pluralize(count, singular, plural) {
|
|
2390
|
+
return count === 1 ? singular : plural || `${singular}s`;
|
|
2391
|
+
}
|
|
2392
|
+
async function selectTemplate(templates) {
|
|
2393
|
+
const choices = templates.map((template) => {
|
|
2394
|
+
const parts = [];
|
|
2395
|
+
if (template.agents?.length) {
|
|
2396
|
+
parts.push(`${template.agents.length} ${pluralize(template.agents.length, "agent")}`);
|
|
2397
|
+
}
|
|
2398
|
+
if (template.tools?.length) {
|
|
2399
|
+
parts.push(`${template.tools.length} ${pluralize(template.tools.length, "tool")}`);
|
|
2400
|
+
}
|
|
2401
|
+
if (template.workflows?.length) {
|
|
2402
|
+
parts.push(`${template.workflows.length} ${pluralize(template.workflows.length, "workflow")}`);
|
|
2403
|
+
}
|
|
2404
|
+
if (template.mcp?.length) {
|
|
2405
|
+
parts.push(`${template.mcp.length} ${pluralize(template.mcp.length, "MCP server")}`);
|
|
2406
|
+
}
|
|
2407
|
+
if (template.networks?.length) {
|
|
2408
|
+
parts.push(`${template.networks.length} ${pluralize(template.networks.length, "agent network")}`);
|
|
2409
|
+
}
|
|
2410
|
+
return {
|
|
2411
|
+
value: template,
|
|
2412
|
+
label: template.title,
|
|
2413
|
+
hint: parts.join(", ") || "Template components"
|
|
2414
|
+
};
|
|
2415
|
+
});
|
|
2416
|
+
const selected = await ve({
|
|
2417
|
+
message: "Select a template:",
|
|
2418
|
+
options: choices
|
|
2419
|
+
});
|
|
2420
|
+
if (pD(selected)) {
|
|
2421
|
+
return null;
|
|
2422
|
+
}
|
|
2423
|
+
return selected;
|
|
2424
|
+
}
|
|
2425
|
+
function findTemplateByName(templates, templateName) {
|
|
2426
|
+
let template = templates.find((t) => t.slug === templateName);
|
|
2427
|
+
if (template) return template;
|
|
2428
|
+
const slugWithPrefix = `template-${templateName}`;
|
|
2429
|
+
template = templates.find((t) => t.slug === slugWithPrefix);
|
|
2430
|
+
if (template) return template;
|
|
2431
|
+
template = templates.find((t) => t.title.toLowerCase() === templateName.toLowerCase());
|
|
2432
|
+
if (template) return template;
|
|
2433
|
+
return null;
|
|
2434
|
+
}
|
|
2435
|
+
function getDefaultProjectName(template) {
|
|
2436
|
+
return template.slug.replace(/^template-/, "");
|
|
2437
|
+
}
|
|
2176
2438
|
var s = Y();
|
|
2177
2439
|
var init = async ({
|
|
2178
|
-
directory,
|
|
2179
|
-
addExample = false,
|
|
2440
|
+
directory = "src/",
|
|
2180
2441
|
components,
|
|
2181
2442
|
llmProvider = "openai",
|
|
2182
2443
|
llmApiKey,
|
|
2183
|
-
|
|
2444
|
+
addExample = false,
|
|
2445
|
+
configureEditorWithDocsMCP,
|
|
2446
|
+
versionTag,
|
|
2447
|
+
initGit = false
|
|
2184
2448
|
}) => {
|
|
2185
2449
|
s.start("Initializing Mastra");
|
|
2450
|
+
const packageVersionTag = versionTag ? `@${versionTag}` : "";
|
|
2186
2451
|
try {
|
|
2187
2452
|
const result = await createMastraDir(directory);
|
|
2188
2453
|
if (!result.ok) {
|
|
@@ -2195,7 +2460,8 @@ var init = async ({
|
|
|
2195
2460
|
dirPath,
|
|
2196
2461
|
addExample,
|
|
2197
2462
|
addWorkflow: components.includes("workflows"),
|
|
2198
|
-
addAgent: components.includes("agents")
|
|
2463
|
+
addAgent: components.includes("agents"),
|
|
2464
|
+
addScorers: components.includes("scorers")
|
|
2199
2465
|
}),
|
|
2200
2466
|
...components.map((component) => createComponentsDir(dirPath, component)),
|
|
2201
2467
|
writeAPIKey({ provider: llmProvider, apiKey: llmApiKey })
|
|
@@ -2209,25 +2475,44 @@ var init = async ({
|
|
|
2209
2475
|
const depService = new DepsService();
|
|
2210
2476
|
const needsLibsql = await depService.checkDependencies(["@mastra/libsql"]) !== `ok`;
|
|
2211
2477
|
if (needsLibsql) {
|
|
2212
|
-
await depService.installPackages([
|
|
2478
|
+
await depService.installPackages([`@mastra/libsql${packageVersionTag}`]);
|
|
2213
2479
|
}
|
|
2214
2480
|
const needsMemory = components.includes(`agents`) && await depService.checkDependencies(["@mastra/memory"]) !== `ok`;
|
|
2215
2481
|
if (needsMemory) {
|
|
2216
|
-
await depService.installPackages([
|
|
2482
|
+
await depService.installPackages([`@mastra/memory${packageVersionTag}`]);
|
|
2217
2483
|
}
|
|
2218
2484
|
const needsLoggers = await depService.checkDependencies(["@mastra/loggers"]) !== `ok`;
|
|
2219
2485
|
if (needsLoggers) {
|
|
2220
|
-
await depService.installPackages([
|
|
2486
|
+
await depService.installPackages([`@mastra/loggers${packageVersionTag}`]);
|
|
2487
|
+
}
|
|
2488
|
+
const needsObservability = await depService.checkDependencies(["@mastra/observability"]) !== `ok`;
|
|
2489
|
+
if (needsObservability) {
|
|
2490
|
+
await depService.installPackages([`@mastra/observability${packageVersionTag}`]);
|
|
2491
|
+
}
|
|
2492
|
+
const needsEvals = components.includes(`scorers`) && await depService.checkDependencies(["@mastra/evals"]) !== `ok`;
|
|
2493
|
+
if (needsEvals) {
|
|
2494
|
+
await depService.installPackages([`@mastra/evals${packageVersionTag}`]);
|
|
2221
2495
|
}
|
|
2222
2496
|
}
|
|
2223
2497
|
const key = await getAPIKey(llmProvider || "openai");
|
|
2224
2498
|
if (configureEditorWithDocsMCP) {
|
|
2225
2499
|
await installMastraDocsMCPServer({
|
|
2226
2500
|
editor: configureEditorWithDocsMCP,
|
|
2227
|
-
directory: process.cwd()
|
|
2501
|
+
directory: process.cwd(),
|
|
2502
|
+
versionTag
|
|
2228
2503
|
});
|
|
2229
2504
|
}
|
|
2230
2505
|
s.stop();
|
|
2506
|
+
if (initGit) {
|
|
2507
|
+
const s2 = Y();
|
|
2508
|
+
try {
|
|
2509
|
+
s2.start("Initializing git repository");
|
|
2510
|
+
await gitInit({ cwd: process.cwd() });
|
|
2511
|
+
s2.stop("Git repository initialized");
|
|
2512
|
+
} catch {
|
|
2513
|
+
s2.stop();
|
|
2514
|
+
}
|
|
2515
|
+
}
|
|
2231
2516
|
if (!llmApiKey) {
|
|
2232
2517
|
Me(`
|
|
2233
2518
|
${color2.green("Mastra initialized successfully!")}
|
|
@@ -2273,6 +2558,68 @@ var execWithTimeout = async (command, timeoutMs) => {
|
|
|
2273
2558
|
throw error;
|
|
2274
2559
|
}
|
|
2275
2560
|
};
|
|
2561
|
+
async function getInitCommand(pm) {
|
|
2562
|
+
switch (pm) {
|
|
2563
|
+
case "npm":
|
|
2564
|
+
return "npm init -y";
|
|
2565
|
+
case "pnpm":
|
|
2566
|
+
return "pnpm init";
|
|
2567
|
+
case "yarn":
|
|
2568
|
+
return "yarn init -y";
|
|
2569
|
+
case "bun":
|
|
2570
|
+
return "bun init -y";
|
|
2571
|
+
default:
|
|
2572
|
+
return "npm init -y";
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
async function initializePackageJson(pm) {
|
|
2576
|
+
const initCommand = await getInitCommand(pm);
|
|
2577
|
+
await exec3(initCommand);
|
|
2578
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
2579
|
+
const packageJson = JSON.parse(await fs4.readFile(packageJsonPath, "utf-8"));
|
|
2580
|
+
packageJson.type = "module";
|
|
2581
|
+
packageJson.engines = {
|
|
2582
|
+
...packageJson.engines,
|
|
2583
|
+
node: ">=22.13.0"
|
|
2584
|
+
};
|
|
2585
|
+
await fs4.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
2586
|
+
}
|
|
2587
|
+
var writeReadmeFile = async ({ dirPath, projectName }) => {
|
|
2588
|
+
const packageManager = getPackageManager();
|
|
2589
|
+
const readmePath = path3.join(dirPath, "README.md");
|
|
2590
|
+
const content = `# ${projectName}
|
|
2591
|
+
|
|
2592
|
+
Welcome to your new [Mastra](https://mastra.ai/) project! We're excited to see what you'll build.
|
|
2593
|
+
|
|
2594
|
+
## Getting Started
|
|
2595
|
+
|
|
2596
|
+
Start the development server:
|
|
2597
|
+
|
|
2598
|
+
\`\`\`shell
|
|
2599
|
+
${packageManager} run dev
|
|
2600
|
+
\`\`\`
|
|
2601
|
+
|
|
2602
|
+
Open [http://localhost:4111](http://localhost:4111) in your browser to access [Mastra Studio](https://mastra.ai/docs/getting-started/studio). It provides an interactive UI for building and testing your agents, along with a REST API that exposes your Mastra application as a local service. This lets you start building without worrying about integration right away.
|
|
2603
|
+
|
|
2604
|
+
You can start editing files inside the \`src/mastra\` directory. The development server will automatically reload whenever you make changes.
|
|
2605
|
+
|
|
2606
|
+
## Learn more
|
|
2607
|
+
|
|
2608
|
+
To learn more about Mastra, visit our [documentation](https://mastra.ai/docs/). Your bootstrapped project includes example code for [agents](https://mastra.ai/docs/agents/overview), [tools](https://mastra.ai/docs/agents/using-tools), [workflows](https://mastra.ai/docs/workflows/overview), [scorers](https://mastra.ai/docs/evals/overview), and [observability](https://mastra.ai/docs/observability/overview).
|
|
2609
|
+
|
|
2610
|
+
If you're new to AI agents, check out our [course](https://mastra.ai/course) and [YouTube videos](https://youtube.com/@mastra-ai). You can also join our [Discord](https://discord.gg/BTYqqHKUrf) community to get help and share your projects.
|
|
2611
|
+
|
|
2612
|
+
## Deploy on Mastra Cloud
|
|
2613
|
+
|
|
2614
|
+
[Mastra Cloud](https://cloud.mastra.ai/) gives you a serverless agent environment with atomic deployments. Access your agents from anywhere and monitor performance. Make sure they don't go off the rails with evals and tracing.
|
|
2615
|
+
|
|
2616
|
+
Check out the [deployment guide](https://mastra.ai/docs/deployment/overview) for more details.`;
|
|
2617
|
+
const formattedContent = await prettier.format(content, {
|
|
2618
|
+
parser: "markdown",
|
|
2619
|
+
singleQuote: true
|
|
2620
|
+
});
|
|
2621
|
+
await fs4.writeFile(readmePath, formattedContent);
|
|
2622
|
+
};
|
|
2276
2623
|
async function installMastraDependency(pm, dependency, versionTag, isDev, timeout) {
|
|
2277
2624
|
let installCommand = getPackageManagerAddCommand(pm);
|
|
2278
2625
|
if (isDev) {
|
|
@@ -2310,7 +2657,7 @@ var createMastraProject = async ({
|
|
|
2310
2657
|
defaultValue: "my-mastra-app",
|
|
2311
2658
|
validate: (value) => {
|
|
2312
2659
|
if (value.length === 0) return "Project name cannot be empty";
|
|
2313
|
-
if (
|
|
2660
|
+
if (fs3__default__default.existsSync(value)) {
|
|
2314
2661
|
return `A directory named "${value}" already exists. Please choose a different name.`;
|
|
2315
2662
|
}
|
|
2316
2663
|
}
|
|
@@ -2319,7 +2666,7 @@ var createMastraProject = async ({
|
|
|
2319
2666
|
xe("Operation cancelled");
|
|
2320
2667
|
process.exit(0);
|
|
2321
2668
|
}
|
|
2322
|
-
let result;
|
|
2669
|
+
let result = void 0;
|
|
2323
2670
|
if (needsInteractive) {
|
|
2324
2671
|
result = await interactivePrompt({
|
|
2325
2672
|
options: { showBanner: false },
|
|
@@ -2327,10 +2674,13 @@ var createMastraProject = async ({
|
|
|
2327
2674
|
});
|
|
2328
2675
|
}
|
|
2329
2676
|
const s2 = Y();
|
|
2677
|
+
const originalCwd = process.cwd();
|
|
2678
|
+
let projectPath = null;
|
|
2330
2679
|
try {
|
|
2331
2680
|
s2.start("Creating project");
|
|
2332
2681
|
try {
|
|
2333
|
-
await
|
|
2682
|
+
await fs4.mkdir(projectName);
|
|
2683
|
+
projectPath = path3.resolve(originalCwd, projectName);
|
|
2334
2684
|
} catch (error) {
|
|
2335
2685
|
if (error instanceof Error && "code" in error && error.code === "EEXIST") {
|
|
2336
2686
|
s2.stop(`A directory named "${projectName}" already exists. Please choose a different name.`);
|
|
@@ -2345,15 +2695,14 @@ var createMastraProject = async ({
|
|
|
2345
2695
|
const installCommand = getPackageManagerAddCommand(pm);
|
|
2346
2696
|
s2.message("Initializing project structure");
|
|
2347
2697
|
try {
|
|
2348
|
-
await
|
|
2349
|
-
await exec3(`npm pkg set type="module"`);
|
|
2350
|
-
await exec3(`npm pkg set engines.node=">=20.9.0"`);
|
|
2698
|
+
await initializePackageJson(pm);
|
|
2351
2699
|
const depsService = new DepsService();
|
|
2352
2700
|
await depsService.addScriptsToPackageJson({
|
|
2353
2701
|
dev: "mastra dev",
|
|
2354
2702
|
build: "mastra build",
|
|
2355
2703
|
start: "mastra start"
|
|
2356
2704
|
});
|
|
2705
|
+
await writeReadmeFile({ dirPath: process.cwd(), projectName });
|
|
2357
2706
|
} catch (error) {
|
|
2358
2707
|
throw new Error(
|
|
2359
2708
|
`Failed to initialize project structure: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
@@ -2362,8 +2711,8 @@ var createMastraProject = async ({
|
|
|
2362
2711
|
s2.stop("Project structure created");
|
|
2363
2712
|
s2.start(`Installing ${pm} dependencies`);
|
|
2364
2713
|
try {
|
|
2365
|
-
await exec3(`${pm} ${installCommand} zod@^
|
|
2366
|
-
await exec3(`${pm} ${installCommand} typescript @types/node
|
|
2714
|
+
await exec3(`${pm} ${installCommand} zod@^4`);
|
|
2715
|
+
await exec3(`${pm} ${installCommand} -D typescript @types/node`);
|
|
2367
2716
|
await exec3(`echo '{
|
|
2368
2717
|
"compilerOptions": {
|
|
2369
2718
|
"target": "ES2022",
|
|
@@ -2426,42 +2775,61 @@ var createMastraProject = async ({
|
|
|
2426
2775
|
s2.stop();
|
|
2427
2776
|
const errorMessage = error instanceof Error ? error.message : "An unexpected error occurred";
|
|
2428
2777
|
xe(`Project creation failed: ${errorMessage}`);
|
|
2778
|
+
if (projectPath && fs3__default__default.existsSync(projectPath)) {
|
|
2779
|
+
try {
|
|
2780
|
+
process.chdir(originalCwd);
|
|
2781
|
+
await fs4.rm(projectPath, { recursive: true, force: true });
|
|
2782
|
+
} catch (cleanupError) {
|
|
2783
|
+
console.error(
|
|
2784
|
+
`Warning: Failed to clean up project directory: ${cleanupError instanceof Error ? cleanupError.message : "Unknown error"}`
|
|
2785
|
+
);
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2429
2788
|
process.exit(1);
|
|
2430
2789
|
}
|
|
2431
2790
|
};
|
|
2432
|
-
var
|
|
2433
|
-
|
|
2434
|
-
|
|
2791
|
+
var version$1 = package_default.version;
|
|
2792
|
+
var create = async (args) => {
|
|
2793
|
+
if (args.template !== void 0) {
|
|
2794
|
+
await createFromTemplate({
|
|
2795
|
+
projectName: args.projectName,
|
|
2796
|
+
template: args.template,
|
|
2797
|
+
timeout: args.timeout,
|
|
2798
|
+
injectedAnalytics: args.analytics,
|
|
2799
|
+
llmProvider: args.llmProvider
|
|
2800
|
+
});
|
|
2435
2801
|
return;
|
|
2436
2802
|
}
|
|
2437
|
-
const needsInteractive =
|
|
2803
|
+
const needsInteractive = args.components === void 0 || args.llmProvider === void 0 || args.addExample === void 0;
|
|
2438
2804
|
const { projectName, result } = await createMastraProject({
|
|
2439
|
-
projectName:
|
|
2440
|
-
createVersionTag:
|
|
2441
|
-
timeout:
|
|
2442
|
-
llmProvider:
|
|
2443
|
-
llmApiKey:
|
|
2805
|
+
projectName: args?.projectName,
|
|
2806
|
+
createVersionTag: args?.createVersionTag,
|
|
2807
|
+
timeout: args?.timeout,
|
|
2808
|
+
llmProvider: args?.llmProvider,
|
|
2809
|
+
llmApiKey: args?.llmApiKey,
|
|
2444
2810
|
needsInteractive
|
|
2445
2811
|
});
|
|
2446
|
-
const directory =
|
|
2812
|
+
const directory = args.directory || "src/";
|
|
2447
2813
|
if (needsInteractive && result) {
|
|
2448
2814
|
await init({
|
|
2449
2815
|
...result,
|
|
2450
2816
|
llmApiKey: result?.llmApiKey,
|
|
2451
|
-
components: ["agents", "tools", "workflows"],
|
|
2452
|
-
addExample: true
|
|
2817
|
+
components: ["agents", "tools", "workflows", "scorers"],
|
|
2818
|
+
addExample: true,
|
|
2819
|
+
versionTag: args.createVersionTag
|
|
2453
2820
|
});
|
|
2454
2821
|
postCreate({ projectName });
|
|
2455
2822
|
return;
|
|
2456
2823
|
}
|
|
2457
|
-
const { components = [], llmProvider = "openai", addExample = false, llmApiKey } =
|
|
2824
|
+
const { components = [], llmProvider = "openai", addExample = false, llmApiKey } = args;
|
|
2458
2825
|
await init({
|
|
2459
2826
|
directory,
|
|
2460
2827
|
components,
|
|
2461
2828
|
llmProvider,
|
|
2462
2829
|
addExample,
|
|
2463
2830
|
llmApiKey,
|
|
2464
|
-
configureEditorWithDocsMCP:
|
|
2831
|
+
configureEditorWithDocsMCP: args.mcpServer,
|
|
2832
|
+
versionTag: args.createVersionTag
|
|
2465
2833
|
});
|
|
2466
2834
|
postCreate({ projectName });
|
|
2467
2835
|
};
|
|
@@ -2552,9 +2920,9 @@ async function createFromGitHubUrl(url) {
|
|
|
2552
2920
|
workflows: []
|
|
2553
2921
|
};
|
|
2554
2922
|
}
|
|
2555
|
-
async function createFromTemplate(
|
|
2923
|
+
async function createFromTemplate(args) {
|
|
2556
2924
|
let selectedTemplate;
|
|
2557
|
-
if (
|
|
2925
|
+
if (args.template === true) {
|
|
2558
2926
|
const templates = await loadTemplates();
|
|
2559
2927
|
const selected = await selectTemplate(templates);
|
|
2560
2928
|
if (!selected) {
|
|
@@ -2562,26 +2930,26 @@ async function createFromTemplate(args2) {
|
|
|
2562
2930
|
return;
|
|
2563
2931
|
}
|
|
2564
2932
|
selectedTemplate = selected;
|
|
2565
|
-
} else if (
|
|
2566
|
-
if (isGitHubUrl(
|
|
2567
|
-
const
|
|
2568
|
-
|
|
2569
|
-
const validation = await validateGitHubProject(
|
|
2933
|
+
} else if (args.template && typeof args.template === "string") {
|
|
2934
|
+
if (isGitHubUrl(args.template)) {
|
|
2935
|
+
const spinner4 = Y();
|
|
2936
|
+
spinner4.start("Validating GitHub repository...");
|
|
2937
|
+
const validation = await validateGitHubProject(args.template);
|
|
2570
2938
|
if (!validation.isValid) {
|
|
2571
|
-
|
|
2939
|
+
spinner4.stop("Validation failed");
|
|
2572
2940
|
M.error("This does not appear to be a valid Mastra project:");
|
|
2573
2941
|
validation.errors.forEach((error) => M.error(` - ${error}`));
|
|
2574
2942
|
throw new Error("Invalid Mastra project");
|
|
2575
2943
|
}
|
|
2576
|
-
|
|
2577
|
-
selectedTemplate = await createFromGitHubUrl(
|
|
2944
|
+
spinner4.stop("Valid Mastra project \u2713");
|
|
2945
|
+
selectedTemplate = await createFromGitHubUrl(args.template);
|
|
2578
2946
|
} else {
|
|
2579
2947
|
const templates = await loadTemplates();
|
|
2580
|
-
const found = findTemplateByName(templates,
|
|
2948
|
+
const found = findTemplateByName(templates, args.template);
|
|
2581
2949
|
if (!found) {
|
|
2582
|
-
M.error(`Template "${
|
|
2950
|
+
M.error(`Template "${args.template}" not found. Available templates:`);
|
|
2583
2951
|
templates.forEach((t) => M.info(` - ${t.title} (use: ${t.slug.replace("template-", "")})`));
|
|
2584
|
-
throw new Error(`Template "${
|
|
2952
|
+
throw new Error(`Template "${args.template}" not found`);
|
|
2585
2953
|
}
|
|
2586
2954
|
selectedTemplate = found;
|
|
2587
2955
|
}
|
|
@@ -2589,7 +2957,7 @@ async function createFromTemplate(args2) {
|
|
|
2589
2957
|
if (!selectedTemplate) {
|
|
2590
2958
|
throw new Error("No template selected");
|
|
2591
2959
|
}
|
|
2592
|
-
let projectName =
|
|
2960
|
+
let projectName = args.projectName;
|
|
2593
2961
|
if (!projectName) {
|
|
2594
2962
|
const defaultName = getDefaultProjectName(selectedTemplate);
|
|
2595
2963
|
const response = await he({
|
|
@@ -2603,19 +2971,61 @@ async function createFromTemplate(args2) {
|
|
|
2603
2971
|
}
|
|
2604
2972
|
projectName = response;
|
|
2605
2973
|
}
|
|
2974
|
+
let llmProvider = args.llmProvider;
|
|
2975
|
+
if (!llmProvider) {
|
|
2976
|
+
const providerResponse = await ve({
|
|
2977
|
+
message: "Select a default provider:",
|
|
2978
|
+
options: LLM_PROVIDERS
|
|
2979
|
+
});
|
|
2980
|
+
if (pD(providerResponse)) {
|
|
2981
|
+
M.info("Project creation cancelled.");
|
|
2982
|
+
return;
|
|
2983
|
+
}
|
|
2984
|
+
llmProvider = providerResponse;
|
|
2985
|
+
}
|
|
2986
|
+
let initGit = false;
|
|
2987
|
+
const gitConfirmResult = await ye({
|
|
2988
|
+
message: "Initialize a new git repository?",
|
|
2989
|
+
initialValue: true
|
|
2990
|
+
});
|
|
2991
|
+
if (!pD(gitConfirmResult)) {
|
|
2992
|
+
initGit = gitConfirmResult;
|
|
2993
|
+
}
|
|
2994
|
+
let projectPath = null;
|
|
2606
2995
|
try {
|
|
2607
|
-
const analytics =
|
|
2996
|
+
const analytics = args.injectedAnalytics || getAnalytics();
|
|
2608
2997
|
if (analytics) {
|
|
2609
2998
|
analytics.trackEvent("cli_template_used", {
|
|
2610
2999
|
template_slug: selectedTemplate.slug,
|
|
2611
3000
|
template_title: selectedTemplate.title
|
|
2612
3001
|
});
|
|
3002
|
+
if (llmProvider) {
|
|
3003
|
+
analytics.trackEvent("cli_model_provider_selected", {
|
|
3004
|
+
provider: llmProvider,
|
|
3005
|
+
selection_method: args.llmProvider ? "cli_args" : "interactive"
|
|
3006
|
+
});
|
|
3007
|
+
}
|
|
2613
3008
|
}
|
|
2614
|
-
const
|
|
3009
|
+
const isBeta = version$1?.includes("beta") ?? false;
|
|
3010
|
+
const isMastraTemplate = selectedTemplate.githubUrl.includes("github.com/mastra-ai/");
|
|
3011
|
+
const branch = isBeta && isMastraTemplate ? "beta" : void 0;
|
|
3012
|
+
projectPath = await cloneTemplate({
|
|
2615
3013
|
template: selectedTemplate,
|
|
2616
|
-
projectName
|
|
3014
|
+
projectName,
|
|
3015
|
+
branch,
|
|
3016
|
+
llmProvider
|
|
2617
3017
|
});
|
|
2618
3018
|
await installDependencies(projectPath);
|
|
3019
|
+
if (initGit) {
|
|
3020
|
+
const s2 = Y();
|
|
3021
|
+
try {
|
|
3022
|
+
s2.start("Initializing git repository");
|
|
3023
|
+
await gitInit({ cwd: projectPath });
|
|
3024
|
+
s2.stop("Git repository initialized");
|
|
3025
|
+
} catch {
|
|
3026
|
+
s2.stop();
|
|
3027
|
+
}
|
|
3028
|
+
}
|
|
2619
3029
|
Me(`
|
|
2620
3030
|
${color2.green("Mastra template installed!")}
|
|
2621
3031
|
|
|
@@ -2624,6 +3034,17 @@ async function createFromTemplate(args2) {
|
|
|
2624
3034
|
`);
|
|
2625
3035
|
postCreate({ projectName });
|
|
2626
3036
|
} catch (error) {
|
|
3037
|
+
if (projectPath) {
|
|
3038
|
+
try {
|
|
3039
|
+
if (fs3__default__default.existsSync(projectPath)) {
|
|
3040
|
+
await fs4.rm(projectPath, { recursive: true, force: true });
|
|
3041
|
+
}
|
|
3042
|
+
} catch (cleanupError) {
|
|
3043
|
+
console.error(
|
|
3044
|
+
`Warning: Failed to clean up project directory: ${cleanupError instanceof Error ? cleanupError.message : "Unknown error"}`
|
|
3045
|
+
);
|
|
3046
|
+
}
|
|
3047
|
+
}
|
|
2627
3048
|
M.error(`Failed to create project from template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2628
3049
|
throw error;
|
|
2629
3050
|
}
|
|
@@ -2670,7 +3091,7 @@ program.version(`${version}`, "-v, --version").description(`create-mastra ${vers
|
|
|
2670
3091
|
program.name("create-mastra").description("Create a new Mastra project").argument("[project-name]", "Directory name of the project").option(
|
|
2671
3092
|
"-p, --project-name <string>",
|
|
2672
3093
|
"Project name that will be used in package.json and as the project directory name."
|
|
2673
|
-
).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(
|
|
3094
|
+
).option("--default", "Quick start with defaults (src, OpenAI, examples)").option("-c, --components <components>", "Comma-separated list of components (agents, tools, workflows, scorers)").option("-l, --llm <model-provider>", "Default model provider (openai, anthropic, groq, google, or cerebras)").option("-k, --llm-api-key <api-key>", "API key for the model provider").option("-e, --example", "Include example code").option("-n, --no-example", "Do not include example code").option("-t, --timeout [timeout]", "Configurable timeout for package installation, defaults to 60000 ms").option("-d, --dir <directory>", "Target directory for Mastra source code (default: src/)").option("-m, --mcp <mcp>", "MCP Server for code editor (cursor, cursor-global, windsurf, vscode, antigravity)").option(
|
|
2674
3095
|
"--template [template-name]",
|
|
2675
3096
|
"Create project from a template (use template name, public GitHub URL, or leave blank to select from list)"
|
|
2676
3097
|
).action(async (projectNameArg, args) => {
|
|
@@ -2678,7 +3099,7 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
|
|
|
2678
3099
|
const timeout = args?.timeout ? args?.timeout === true ? 6e4 : parseInt(args?.timeout, 10) : void 0;
|
|
2679
3100
|
if (args.default) {
|
|
2680
3101
|
await create({
|
|
2681
|
-
components: ["agents", "tools", "workflows"],
|
|
3102
|
+
components: ["agents", "tools", "workflows", "scorers"],
|
|
2682
3103
|
llmProvider: "openai",
|
|
2683
3104
|
addExample: true,
|
|
2684
3105
|
createVersionTag,
|