create-mastra 0.0.0-tsconfig-compile-20250703214351 → 0.0.0-type-testing-20260120105120
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 +2355 -0
- package/LICENSE.md +11 -42
- package/README.md +11 -39
- package/dist/index.js +1152 -396
- package/dist/index.js.map +1 -1
- package/dist/starter-files/tools.ts +2 -2
- package/dist/templates/dev.entry.js +10 -43
- package/package.json +31 -24
- package/dist/starter-files/config.ts +0 -25
- package/dist/starter-files/mastra-pg.docker-compose.yaml +0 -15
package/dist/index.js
CHANGED
|
@@ -4,26 +4,30 @@ import { randomUUID } from 'node:crypto';
|
|
|
4
4
|
import * as fs3__default from 'node:fs';
|
|
5
5
|
import fs3__default__default, { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
6
6
|
import os from 'node:os';
|
|
7
|
-
import
|
|
7
|
+
import path3, { dirname } from 'node:path';
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
9
|
import { PostHog } from 'posthog-node';
|
|
10
|
+
import fs4 from 'node:fs/promises';
|
|
10
11
|
import util, { stripVTControlCharacters } from 'node:util';
|
|
11
12
|
import y$1, { stdout, stdin } from 'node:process';
|
|
12
13
|
import * as g from 'node:readline';
|
|
13
14
|
import g__default from 'node:readline';
|
|
14
15
|
import { Writable } from 'node:stream';
|
|
15
16
|
import child_process from 'node:child_process';
|
|
16
|
-
import fs4 from 'node:fs/promises';
|
|
17
|
-
import { execa } from 'execa';
|
|
18
|
-
import fsExtra3, { readJSON, ensureFile, writeJSON } from 'fs-extra/esm';
|
|
19
|
-
import prettier from 'prettier';
|
|
20
17
|
import tty from 'node:tty';
|
|
18
|
+
import fsExtra, { readJSON, ensureFile, writeJSON } from 'fs-extra/esm';
|
|
19
|
+
import prettier from 'prettier';
|
|
20
|
+
import { execa } from 'execa';
|
|
21
|
+
import fsExtra$1 from 'fs-extra';
|
|
21
22
|
import pino from 'pino';
|
|
22
23
|
import pretty from 'pino-pretty';
|
|
23
|
-
import fsExtra from 'fs-extra';
|
|
24
24
|
|
|
25
25
|
var __filename = fileURLToPath(import.meta.url);
|
|
26
|
-
var __dirname =
|
|
26
|
+
var __dirname = path3.dirname(__filename);
|
|
27
|
+
var analyticsInstance = null;
|
|
28
|
+
function getAnalytics() {
|
|
29
|
+
return analyticsInstance;
|
|
30
|
+
}
|
|
27
31
|
var PosthogAnalytics = class {
|
|
28
32
|
sessionId;
|
|
29
33
|
client;
|
|
@@ -35,7 +39,7 @@ var PosthogAnalytics = class {
|
|
|
35
39
|
host = "https://app.posthog.com"
|
|
36
40
|
}) {
|
|
37
41
|
this.version = version;
|
|
38
|
-
const cliConfigPath =
|
|
42
|
+
const cliConfigPath = path3.join(__dirname, "mastra-cli.json");
|
|
39
43
|
if (existsSync(cliConfigPath)) {
|
|
40
44
|
try {
|
|
41
45
|
const { distinctId, sessionId } = JSON.parse(readFileSync(cliConfigPath, "utf-8"));
|
|
@@ -63,7 +67,7 @@ var PosthogAnalytics = class {
|
|
|
63
67
|
}
|
|
64
68
|
writeCliConfig({ distinctId, sessionId }) {
|
|
65
69
|
try {
|
|
66
|
-
writeFileSync(
|
|
70
|
+
writeFileSync(path3.join(__dirname, "mastra-cli.json"), JSON.stringify({ distinctId, sessionId }));
|
|
67
71
|
} catch {
|
|
68
72
|
}
|
|
69
73
|
}
|
|
@@ -101,6 +105,10 @@ var PosthogAnalytics = class {
|
|
|
101
105
|
machine_id: os.hostname()
|
|
102
106
|
};
|
|
103
107
|
}
|
|
108
|
+
getDurationMs(startTime) {
|
|
109
|
+
const [seconds, nanoseconds] = process.hrtime(startTime);
|
|
110
|
+
return seconds * 1e3 + nanoseconds / 1e6;
|
|
111
|
+
}
|
|
104
112
|
captureSessionStart() {
|
|
105
113
|
if (!this.client) {
|
|
106
114
|
return;
|
|
@@ -113,6 +121,22 @@ var PosthogAnalytics = class {
|
|
|
113
121
|
}
|
|
114
122
|
});
|
|
115
123
|
}
|
|
124
|
+
trackEvent(eventName, properties) {
|
|
125
|
+
try {
|
|
126
|
+
if (!this.client) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
this.client.capture({
|
|
130
|
+
distinctId: this.distinctId,
|
|
131
|
+
event: eventName,
|
|
132
|
+
properties: {
|
|
133
|
+
...this.getSystemProperties(),
|
|
134
|
+
...properties
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
} catch {
|
|
138
|
+
}
|
|
139
|
+
}
|
|
116
140
|
trackCommand(options) {
|
|
117
141
|
try {
|
|
118
142
|
if (!this.client) {
|
|
@@ -153,8 +177,7 @@ var PosthogAnalytics = class {
|
|
|
153
177
|
const startTime = process.hrtime();
|
|
154
178
|
try {
|
|
155
179
|
const result = await execution();
|
|
156
|
-
const
|
|
157
|
-
const durationMs = seconds * 1e3 + nanoseconds / 1e6;
|
|
180
|
+
const durationMs = this.getDurationMs(startTime);
|
|
158
181
|
this.trackCommand({
|
|
159
182
|
command,
|
|
160
183
|
args,
|
|
@@ -164,8 +187,7 @@ var PosthogAnalytics = class {
|
|
|
164
187
|
});
|
|
165
188
|
return result;
|
|
166
189
|
} catch (error) {
|
|
167
|
-
const
|
|
168
|
-
const durationMs = seconds * 1e3 + nanoseconds / 1e6;
|
|
190
|
+
const durationMs = this.getDurationMs(startTime);
|
|
169
191
|
this.trackCommand({
|
|
170
192
|
command,
|
|
171
193
|
args,
|
|
@@ -362,7 +384,7 @@ function DD({onlyFirst:e=false}={}){const t=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:
|
|
|
362
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(`
|
|
363
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(`
|
|
364
386
|
`).slice(F);this.output.write(s.join(`
|
|
365
|
-
`)),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);});}}
|
|
366
388
|
|
|
367
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)}
|
|
368
390
|
${b(this.state)} ${t.message}
|
|
@@ -372,7 +394,12 @@ ${color2.yellow(d)} ${color2.yellow(this.error)}
|
|
|
372
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()?`
|
|
373
395
|
${color2.gray(o)}`:""}`;default:return `${n}${color2.cyan(o)} ${i}
|
|
374
396
|
${color2.cyan(d)}
|
|
375
|
-
`}}}).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)}
|
|
376
403
|
${b(this.state)} ${t.message}
|
|
377
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")}
|
|
378
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(`
|
|
@@ -402,7 +429,7 @@ ${color2.gray(d)} ${t}
|
|
|
402
429
|
`):process.stdout.write(`${w} ${l}
|
|
403
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};
|
|
404
431
|
|
|
405
|
-
var shellQuote
|
|
432
|
+
var shellQuote = {};
|
|
406
433
|
|
|
407
434
|
var quote;
|
|
408
435
|
var hasRequiredQuote;
|
|
@@ -668,16 +695,16 @@ function requireParse () {
|
|
|
668
695
|
var hasRequiredShellQuote;
|
|
669
696
|
|
|
670
697
|
function requireShellQuote () {
|
|
671
|
-
if (hasRequiredShellQuote) return shellQuote
|
|
698
|
+
if (hasRequiredShellQuote) return shellQuote;
|
|
672
699
|
hasRequiredShellQuote = 1;
|
|
673
700
|
|
|
674
|
-
shellQuote
|
|
675
|
-
shellQuote
|
|
676
|
-
return shellQuote
|
|
701
|
+
shellQuote.quote = requireQuote();
|
|
702
|
+
shellQuote.parse = requireParse();
|
|
703
|
+
return shellQuote;
|
|
677
704
|
}
|
|
678
705
|
|
|
679
706
|
var shellQuoteExports = requireShellQuote();
|
|
680
|
-
var
|
|
707
|
+
var shellQuote2 = /*@__PURE__*/getDefaultExportFromCjs(shellQuoteExports);
|
|
681
708
|
|
|
682
709
|
// eslint-disable-next-line no-warning-comments
|
|
683
710
|
// TODO: Use a better method when it's added to Node.js (https://github.com/nodejs/node/pull/40240)
|
|
@@ -704,13 +731,18 @@ const format = (open, close) => {
|
|
|
704
731
|
// Handle nested colors.
|
|
705
732
|
|
|
706
733
|
// We could have done this, but it's too slow (as of Node.js 22).
|
|
707
|
-
// return openCode + string.replaceAll(closeCode, openCode) + closeCode;
|
|
734
|
+
// return openCode + string.replaceAll(closeCode, (close === 22 ? closeCode : '') + openCode) + closeCode;
|
|
708
735
|
|
|
709
736
|
let result = openCode;
|
|
710
737
|
let lastIndex = 0;
|
|
711
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
|
+
|
|
712
744
|
while (index !== -1) {
|
|
713
|
-
result += string.slice(lastIndex, index) +
|
|
745
|
+
result += string.slice(lastIndex, index) + replaceCode;
|
|
714
746
|
lastIndex = index + closeCode.length;
|
|
715
747
|
index = string.indexOf(closeCode, lastIndex);
|
|
716
748
|
}
|
|
@@ -862,6 +894,7 @@ class YoctoSpinner {
|
|
|
862
894
|
#exitHandlerBound;
|
|
863
895
|
#isInteractive;
|
|
864
896
|
#lastSpinnerFrameTime = 0;
|
|
897
|
+
#isSpinning = false;
|
|
865
898
|
|
|
866
899
|
constructor(options = {}) {
|
|
867
900
|
const spinner = options.spinner ?? defaultSpinner;
|
|
@@ -883,13 +916,17 @@ class YoctoSpinner {
|
|
|
883
916
|
return this;
|
|
884
917
|
}
|
|
885
918
|
|
|
919
|
+
this.#isSpinning = true;
|
|
886
920
|
this.#hideCursor();
|
|
887
921
|
this.#render();
|
|
888
922
|
this.#subscribeToProcessEvents();
|
|
889
923
|
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
924
|
+
// Only start the timer in interactive mode
|
|
925
|
+
if (this.#isInteractive) {
|
|
926
|
+
this.#timer = setInterval(() => {
|
|
927
|
+
this.#render();
|
|
928
|
+
}, this.#interval);
|
|
929
|
+
}
|
|
893
930
|
|
|
894
931
|
return this;
|
|
895
932
|
}
|
|
@@ -899,8 +936,12 @@ class YoctoSpinner {
|
|
|
899
936
|
return this;
|
|
900
937
|
}
|
|
901
938
|
|
|
902
|
-
|
|
903
|
-
this.#timer
|
|
939
|
+
this.#isSpinning = false;
|
|
940
|
+
if (this.#timer) {
|
|
941
|
+
clearInterval(this.#timer);
|
|
942
|
+
this.#timer = undefined;
|
|
943
|
+
}
|
|
944
|
+
|
|
904
945
|
this.#showCursor();
|
|
905
946
|
this.clear();
|
|
906
947
|
this.#unsubscribeFromProcessEvents();
|
|
@@ -933,7 +974,7 @@ class YoctoSpinner {
|
|
|
933
974
|
}
|
|
934
975
|
|
|
935
976
|
get isSpinning() {
|
|
936
|
-
return this.#
|
|
977
|
+
return this.#isSpinning;
|
|
937
978
|
}
|
|
938
979
|
|
|
939
980
|
get text() {
|
|
@@ -1070,11 +1111,11 @@ var MastraLogger = class {
|
|
|
1070
1111
|
}
|
|
1071
1112
|
trackException(_error) {
|
|
1072
1113
|
}
|
|
1073
|
-
async
|
|
1114
|
+
async listLogs(transportId, params) {
|
|
1074
1115
|
if (!transportId || !this.transports.has(transportId)) {
|
|
1075
1116
|
return { logs: [], total: 0, page: params?.page ?? 1, perPage: params?.perPage ?? 100, hasMore: false };
|
|
1076
1117
|
}
|
|
1077
|
-
return this.transports.get(transportId).
|
|
1118
|
+
return this.transports.get(transportId).listLogs(params) ?? {
|
|
1078
1119
|
logs: [],
|
|
1079
1120
|
total: 0,
|
|
1080
1121
|
page: params?.page ?? 1,
|
|
@@ -1082,7 +1123,7 @@ var MastraLogger = class {
|
|
|
1082
1123
|
hasMore: false
|
|
1083
1124
|
};
|
|
1084
1125
|
}
|
|
1085
|
-
async
|
|
1126
|
+
async listLogsByRunId({
|
|
1086
1127
|
transportId,
|
|
1087
1128
|
runId,
|
|
1088
1129
|
fromDate,
|
|
@@ -1095,7 +1136,7 @@ var MastraLogger = class {
|
|
|
1095
1136
|
if (!transportId || !this.transports.has(transportId) || !runId) {
|
|
1096
1137
|
return { logs: [], total: 0, page: page ?? 1, perPage: perPage ?? 100, hasMore: false };
|
|
1097
1138
|
}
|
|
1098
|
-
return this.transports.get(transportId).
|
|
1139
|
+
return this.transports.get(transportId).listLogsByRunId({ runId, fromDate, toDate, logLevel, filters, page, perPage }) ?? {
|
|
1099
1140
|
logs: [],
|
|
1100
1141
|
total: 0,
|
|
1101
1142
|
page: page ?? 1,
|
|
@@ -1105,10 +1146,15 @@ var MastraLogger = class {
|
|
|
1105
1146
|
}
|
|
1106
1147
|
};
|
|
1107
1148
|
|
|
1108
|
-
var PinoLogger = class extends MastraLogger {
|
|
1149
|
+
var PinoLogger = class _PinoLogger extends MastraLogger {
|
|
1109
1150
|
logger;
|
|
1110
1151
|
constructor(options = {}) {
|
|
1111
1152
|
super(options);
|
|
1153
|
+
const internalOptions = options;
|
|
1154
|
+
if (internalOptions._logger) {
|
|
1155
|
+
this.logger = internalOptions._logger;
|
|
1156
|
+
return;
|
|
1157
|
+
}
|
|
1112
1158
|
let prettyStream = void 0;
|
|
1113
1159
|
if (!options.overrideDefaultTransports) {
|
|
1114
1160
|
prettyStream = pretty({
|
|
@@ -1125,7 +1171,8 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1125
1171
|
{
|
|
1126
1172
|
name: options.name || "app",
|
|
1127
1173
|
level: options.level || LogLevel.INFO,
|
|
1128
|
-
formatters: options.formatters
|
|
1174
|
+
formatters: options.formatters,
|
|
1175
|
+
redact: options.redact
|
|
1129
1176
|
},
|
|
1130
1177
|
options.overrideDefaultTransports ? options?.transports?.default : transportsAry.length === 0 ? prettyStream : pino.multistream([
|
|
1131
1178
|
...transportsAry.map(([, transport]) => ({
|
|
@@ -1139,6 +1186,38 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1139
1186
|
])
|
|
1140
1187
|
);
|
|
1141
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
|
+
}
|
|
1142
1221
|
debug(message, args = {}) {
|
|
1143
1222
|
this.logger.debug(args, message);
|
|
1144
1223
|
}
|
|
@@ -1153,19 +1232,35 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1153
1232
|
}
|
|
1154
1233
|
};
|
|
1155
1234
|
|
|
1235
|
+
var package_default = {
|
|
1236
|
+
version: "1.0.0-beta.16"};
|
|
1237
|
+
function getPackageManagerAddCommand(pm) {
|
|
1238
|
+
switch (pm) {
|
|
1239
|
+
case "npm":
|
|
1240
|
+
return "install --audit=false --fund=false --loglevel=error --progress=false --update-notifier=false";
|
|
1241
|
+
case "yarn":
|
|
1242
|
+
return "add";
|
|
1243
|
+
case "pnpm":
|
|
1244
|
+
return "add --loglevel=error";
|
|
1245
|
+
case "bun":
|
|
1246
|
+
return "add";
|
|
1247
|
+
default:
|
|
1248
|
+
return "add";
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1156
1251
|
var DepsService = class {
|
|
1157
1252
|
packageManager;
|
|
1158
1253
|
constructor() {
|
|
1159
1254
|
this.packageManager = this.getPackageManager();
|
|
1160
1255
|
}
|
|
1161
1256
|
findLockFile(dir) {
|
|
1162
|
-
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"];
|
|
1163
1258
|
for (const file of lockFiles) {
|
|
1164
|
-
if (fs3__default__default.existsSync(
|
|
1259
|
+
if (fs3__default__default.existsSync(path3.join(dir, file))) {
|
|
1165
1260
|
return file;
|
|
1166
1261
|
}
|
|
1167
1262
|
}
|
|
1168
|
-
const parentDir =
|
|
1263
|
+
const parentDir = path3.resolve(dir, "..");
|
|
1169
1264
|
if (parentDir !== dir) {
|
|
1170
1265
|
return this.findLockFile(parentDir);
|
|
1171
1266
|
}
|
|
@@ -1181,20 +1276,17 @@ var DepsService = class {
|
|
|
1181
1276
|
case "yarn.lock":
|
|
1182
1277
|
return "yarn";
|
|
1183
1278
|
case "bun.lock":
|
|
1279
|
+
case "bun.lockb":
|
|
1184
1280
|
return "bun";
|
|
1185
1281
|
default:
|
|
1186
1282
|
return "npm";
|
|
1187
1283
|
}
|
|
1188
1284
|
}
|
|
1189
1285
|
async installPackages(packages) {
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
runCommand = `${this.packageManager} i`;
|
|
1193
|
-
} else {
|
|
1194
|
-
runCommand = `${this.packageManager} add`;
|
|
1195
|
-
}
|
|
1286
|
+
const pm = this.packageManager;
|
|
1287
|
+
const installCommand = getPackageManagerAddCommand(pm);
|
|
1196
1288
|
const packageList = packages.join(" ");
|
|
1197
|
-
return execa(`${
|
|
1289
|
+
return execa(`${pm} ${installCommand} ${packageList}`, {
|
|
1198
1290
|
all: true,
|
|
1199
1291
|
shell: true,
|
|
1200
1292
|
stdio: "inherit"
|
|
@@ -1202,7 +1294,7 @@ var DepsService = class {
|
|
|
1202
1294
|
}
|
|
1203
1295
|
async checkDependencies(dependencies) {
|
|
1204
1296
|
try {
|
|
1205
|
-
const packageJsonPath =
|
|
1297
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1206
1298
|
try {
|
|
1207
1299
|
await fs4.access(packageJsonPath);
|
|
1208
1300
|
} catch {
|
|
@@ -1222,7 +1314,7 @@ var DepsService = class {
|
|
|
1222
1314
|
}
|
|
1223
1315
|
async getProjectName() {
|
|
1224
1316
|
try {
|
|
1225
|
-
const packageJsonPath =
|
|
1317
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1226
1318
|
const packageJson = await fs4.readFile(packageJsonPath, "utf-8");
|
|
1227
1319
|
const pkg = JSON.parse(packageJson);
|
|
1228
1320
|
return pkg.name;
|
|
@@ -1230,13 +1322,6 @@ var DepsService = class {
|
|
|
1230
1322
|
throw err;
|
|
1231
1323
|
}
|
|
1232
1324
|
}
|
|
1233
|
-
async getPackageVersion() {
|
|
1234
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
1235
|
-
const __dirname = dirname(__filename);
|
|
1236
|
-
const pkgJsonPath = path2.join(__dirname, "..", "package.json");
|
|
1237
|
-
const content = await fsExtra3.readJSON(pkgJsonPath);
|
|
1238
|
-
return content.version;
|
|
1239
|
-
}
|
|
1240
1325
|
async addScriptsToPackageJson(scripts) {
|
|
1241
1326
|
const packageJson = JSON.parse(await fs4.readFile("package.json", "utf-8"));
|
|
1242
1327
|
packageJson.scripts = {
|
|
@@ -1246,153 +1331,6 @@ var DepsService = class {
|
|
|
1246
1331
|
await fs4.writeFile("package.json", JSON.stringify(packageJson, null, 2));
|
|
1247
1332
|
}
|
|
1248
1333
|
};
|
|
1249
|
-
function getPackageManager() {
|
|
1250
|
-
const userAgent = process.env.npm_config_user_agent || "";
|
|
1251
|
-
const execPath = process.env.npm_execpath || "";
|
|
1252
|
-
if (userAgent.includes("yarn")) {
|
|
1253
|
-
return "yarn";
|
|
1254
|
-
}
|
|
1255
|
-
if (userAgent.includes("pnpm")) {
|
|
1256
|
-
return "pnpm";
|
|
1257
|
-
}
|
|
1258
|
-
if (userAgent.includes("npm")) {
|
|
1259
|
-
return "npm";
|
|
1260
|
-
}
|
|
1261
|
-
if (execPath.includes("yarn")) {
|
|
1262
|
-
return "yarn";
|
|
1263
|
-
}
|
|
1264
|
-
if (execPath.includes("pnpm")) {
|
|
1265
|
-
return "pnpm";
|
|
1266
|
-
}
|
|
1267
|
-
if (execPath.includes("npm")) {
|
|
1268
|
-
return "npm";
|
|
1269
|
-
}
|
|
1270
|
-
return "npm";
|
|
1271
|
-
}
|
|
1272
|
-
function getPackageManagerInstallCommand(pm) {
|
|
1273
|
-
switch (pm) {
|
|
1274
|
-
case "npm":
|
|
1275
|
-
return "install";
|
|
1276
|
-
case "yarn":
|
|
1277
|
-
return "add";
|
|
1278
|
-
case "pnpm":
|
|
1279
|
-
return "add";
|
|
1280
|
-
default:
|
|
1281
|
-
return "install";
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
var args = ["-y", "@mastra/mcp-docs-server"];
|
|
1285
|
-
var createMcpConfig = (editor) => {
|
|
1286
|
-
if (editor === "vscode") {
|
|
1287
|
-
return {
|
|
1288
|
-
servers: {
|
|
1289
|
-
mastra: process.platform === `win32` ? {
|
|
1290
|
-
command: "cmd",
|
|
1291
|
-
args: ["/c", "npx", ...args],
|
|
1292
|
-
type: "stdio"
|
|
1293
|
-
} : {
|
|
1294
|
-
command: "npx",
|
|
1295
|
-
args,
|
|
1296
|
-
type: "stdio"
|
|
1297
|
-
}
|
|
1298
|
-
}
|
|
1299
|
-
};
|
|
1300
|
-
}
|
|
1301
|
-
return {
|
|
1302
|
-
mcpServers: {
|
|
1303
|
-
mastra: {
|
|
1304
|
-
command: "npx",
|
|
1305
|
-
args
|
|
1306
|
-
}
|
|
1307
|
-
}
|
|
1308
|
-
};
|
|
1309
|
-
};
|
|
1310
|
-
function makeConfig(original, editor) {
|
|
1311
|
-
if (editor === "vscode") {
|
|
1312
|
-
return {
|
|
1313
|
-
...original,
|
|
1314
|
-
servers: {
|
|
1315
|
-
...original?.servers || {},
|
|
1316
|
-
...createMcpConfig(editor).servers
|
|
1317
|
-
}
|
|
1318
|
-
};
|
|
1319
|
-
}
|
|
1320
|
-
return {
|
|
1321
|
-
...original,
|
|
1322
|
-
mcpServers: {
|
|
1323
|
-
...original?.mcpServers || {},
|
|
1324
|
-
...createMcpConfig(editor).mcpServers
|
|
1325
|
-
}
|
|
1326
|
-
};
|
|
1327
|
-
}
|
|
1328
|
-
async function writeMergedConfig(configPath, editor) {
|
|
1329
|
-
const configExists = existsSync(configPath);
|
|
1330
|
-
const config = makeConfig(configExists ? await readJSON(configPath) : {}, editor);
|
|
1331
|
-
await ensureFile(configPath);
|
|
1332
|
-
await writeJSON(configPath, config, {
|
|
1333
|
-
spaces: 2
|
|
1334
|
-
});
|
|
1335
|
-
}
|
|
1336
|
-
var windsurfGlobalMCPConfigPath = path2.join(os.homedir(), ".codeium", "windsurf", "mcp_config.json");
|
|
1337
|
-
var cursorGlobalMCPConfigPath = path2.join(os.homedir(), ".cursor", "mcp.json");
|
|
1338
|
-
path2.join(process.cwd(), ".vscode", "mcp.json");
|
|
1339
|
-
var vscodeGlobalMCPConfigPath = path2.join(
|
|
1340
|
-
os.homedir(),
|
|
1341
|
-
process.platform === "win32" ? path2.join("AppData", "Roaming", "Code", "User", "settings.json") : process.platform === "darwin" ? path2.join("Library", "Application Support", "Code", "User", "settings.json") : path2.join(".config", "Code", "User", "settings.json")
|
|
1342
|
-
);
|
|
1343
|
-
async function installMastraDocsMCPServer({ editor, directory }) {
|
|
1344
|
-
if (editor === `cursor`) {
|
|
1345
|
-
await writeMergedConfig(path2.join(directory, ".cursor", "mcp.json"), "cursor");
|
|
1346
|
-
}
|
|
1347
|
-
if (editor === `vscode`) {
|
|
1348
|
-
await writeMergedConfig(path2.join(directory, ".vscode", "mcp.json"), "vscode");
|
|
1349
|
-
}
|
|
1350
|
-
if (editor === `cursor-global`) {
|
|
1351
|
-
const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor);
|
|
1352
|
-
if (alreadyInstalled) {
|
|
1353
|
-
return;
|
|
1354
|
-
}
|
|
1355
|
-
await writeMergedConfig(cursorGlobalMCPConfigPath, "cursor-global");
|
|
1356
|
-
}
|
|
1357
|
-
if (editor === `windsurf`) {
|
|
1358
|
-
const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor);
|
|
1359
|
-
if (alreadyInstalled) {
|
|
1360
|
-
return;
|
|
1361
|
-
}
|
|
1362
|
-
await writeMergedConfig(windsurfGlobalMCPConfigPath, editor);
|
|
1363
|
-
}
|
|
1364
|
-
}
|
|
1365
|
-
async function globalMCPIsAlreadyInstalled(editor) {
|
|
1366
|
-
let configPath = ``;
|
|
1367
|
-
if (editor === "windsurf") {
|
|
1368
|
-
configPath = windsurfGlobalMCPConfigPath;
|
|
1369
|
-
} else if (editor === "cursor-global") {
|
|
1370
|
-
configPath = cursorGlobalMCPConfigPath;
|
|
1371
|
-
} else if (editor === "vscode") {
|
|
1372
|
-
configPath = vscodeGlobalMCPConfigPath;
|
|
1373
|
-
}
|
|
1374
|
-
if (!configPath || !existsSync(configPath)) {
|
|
1375
|
-
return false;
|
|
1376
|
-
}
|
|
1377
|
-
try {
|
|
1378
|
-
const configContents = await readJSON(configPath);
|
|
1379
|
-
if (!configContents) return false;
|
|
1380
|
-
if (editor === "vscode") {
|
|
1381
|
-
if (!configContents.servers) return false;
|
|
1382
|
-
const hasMastraMCP2 = Object.values(configContents.servers).some(
|
|
1383
|
-
(server) => server?.args?.find((arg) => arg?.includes(`@mastra/mcp-docs-server`))
|
|
1384
|
-
);
|
|
1385
|
-
return hasMastraMCP2;
|
|
1386
|
-
}
|
|
1387
|
-
if (!configContents?.mcpServers) return false;
|
|
1388
|
-
const hasMastraMCP = Object.values(configContents.mcpServers).some(
|
|
1389
|
-
(server) => server?.args?.find((arg) => arg?.includes(`@mastra/mcp-docs-server`))
|
|
1390
|
-
);
|
|
1391
|
-
return hasMastraMCP;
|
|
1392
|
-
} catch {
|
|
1393
|
-
return false;
|
|
1394
|
-
}
|
|
1395
|
-
}
|
|
1396
1334
|
var EnvService = class {
|
|
1397
1335
|
};
|
|
1398
1336
|
var FileEnvService = class extends EnvService {
|
|
@@ -1431,7 +1369,7 @@ var FileEnvService = class extends EnvService {
|
|
|
1431
1369
|
${key}=${value}`;
|
|
1432
1370
|
}
|
|
1433
1371
|
await this.writeFile({ filePath, data });
|
|
1434
|
-
console.
|
|
1372
|
+
console.info(`${key} set to ${value} in ENV file.`);
|
|
1435
1373
|
return data;
|
|
1436
1374
|
}
|
|
1437
1375
|
async getEnvValue(key) {
|
|
@@ -1464,19 +1402,19 @@ var FileService = class {
|
|
|
1464
1402
|
*/
|
|
1465
1403
|
async copyStarterFile(inputFile, outputFilePath, replaceIfExists) {
|
|
1466
1404
|
const __filename = fileURLToPath(import.meta.url);
|
|
1467
|
-
const __dirname =
|
|
1468
|
-
const filePath =
|
|
1405
|
+
const __dirname = path3.dirname(__filename);
|
|
1406
|
+
const filePath = path3.resolve(__dirname, "starter-files", inputFile);
|
|
1469
1407
|
const fileString = fs3__default__default.readFileSync(filePath, "utf8");
|
|
1470
1408
|
if (fs3__default__default.existsSync(outputFilePath) && !replaceIfExists) {
|
|
1471
|
-
console.
|
|
1409
|
+
console.info(`${outputFilePath} already exists`);
|
|
1472
1410
|
return false;
|
|
1473
1411
|
}
|
|
1474
|
-
await
|
|
1412
|
+
await fsExtra.outputFile(outputFilePath, fileString);
|
|
1475
1413
|
return true;
|
|
1476
1414
|
}
|
|
1477
1415
|
async setupEnvFile({ dbUrl }) {
|
|
1478
|
-
const envPath =
|
|
1479
|
-
await
|
|
1416
|
+
const envPath = path3.join(process.cwd(), ".env.development");
|
|
1417
|
+
await fsExtra.ensureFile(envPath);
|
|
1480
1418
|
const fileEnvService = new FileEnvService(envPath);
|
|
1481
1419
|
await fileEnvService.setEnvValue("DB_URL", dbUrl);
|
|
1482
1420
|
}
|
|
@@ -1499,92 +1437,216 @@ var FileService = class {
|
|
|
1499
1437
|
fs3__default__default.writeFileSync(filePath, fileContent);
|
|
1500
1438
|
}
|
|
1501
1439
|
};
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
});
|
|
1506
|
-
var exec = util.promisify(child_process.exec);
|
|
1507
|
-
var getAISDKPackage = (llmProvider) => {
|
|
1508
|
-
switch (llmProvider) {
|
|
1509
|
-
case "openai":
|
|
1510
|
-
return "@ai-sdk/openai";
|
|
1511
|
-
case "anthropic":
|
|
1512
|
-
return "@ai-sdk/anthropic";
|
|
1513
|
-
case "groq":
|
|
1514
|
-
return "@ai-sdk/groq";
|
|
1515
|
-
case "google":
|
|
1516
|
-
return "@ai-sdk/google";
|
|
1517
|
-
case "cerebras":
|
|
1518
|
-
return "@ai-sdk/cerebras";
|
|
1519
|
-
default:
|
|
1520
|
-
return "@ai-sdk/openai";
|
|
1521
|
-
}
|
|
1440
|
+
var createArgs = (versionTag) => {
|
|
1441
|
+
const packageName = versionTag ? `@mastra/mcp-docs-server@${versionTag}` : "@mastra/mcp-docs-server";
|
|
1442
|
+
return ["-y", packageName];
|
|
1522
1443
|
};
|
|
1523
|
-
var
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
providerImport = `import { cerebras } from '${getAISDKPackage(llmProvider)}';`;
|
|
1540
|
-
modelItem = `cerebras('llama-3.3-70b')`;
|
|
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
|
+
};
|
|
1541
1460
|
}
|
|
1542
|
-
return {
|
|
1461
|
+
return {
|
|
1462
|
+
mcpServers: {
|
|
1463
|
+
mastra: {
|
|
1464
|
+
command: "npx",
|
|
1465
|
+
args
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
};
|
|
1543
1469
|
};
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
${providerImport}
|
|
1562
|
-
import { Agent } from '@mastra/core/agent';
|
|
1563
|
-
import { Memory } from '@mastra/memory';
|
|
1564
|
-
import { LibSQLStore } from '@mastra/libsql';
|
|
1565
|
-
${addExampleTool ? `import { weatherTool } from '../tools/weather-tool';` : ""}
|
|
1566
|
-
|
|
1567
|
-
export const weatherAgent = new Agent({
|
|
1568
|
-
name: 'Weather Agent',
|
|
1569
|
-
instructions: \`${instructions}\`,
|
|
1570
|
-
model: ${modelItem},
|
|
1571
|
-
${addExampleTool ? "tools: { weatherTool }," : ""}
|
|
1572
|
-
memory: new Memory({
|
|
1573
|
-
storage: new LibSQLStore({
|
|
1574
|
-
url: "file:../mastra.db", // path is relative to the .mastra/output directory
|
|
1575
|
-
})
|
|
1576
|
-
})
|
|
1577
|
-
});
|
|
1578
|
-
`;
|
|
1579
|
-
const formattedContent = await prettier.format(content, {
|
|
1580
|
-
parser: "typescript",
|
|
1581
|
-
singleQuote: true
|
|
1582
|
-
});
|
|
1583
|
-
await fs4.writeFile(destPath, "");
|
|
1584
|
-
await fs4.writeFile(destPath, formattedContent);
|
|
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
|
+
};
|
|
1585
1487
|
}
|
|
1586
|
-
async function
|
|
1587
|
-
const
|
|
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);
|
|
1572
|
+
var getModelIdentifier = (llmProvider) => {
|
|
1573
|
+
let model = "openai/gpt-4o";
|
|
1574
|
+
if (llmProvider === "anthropic") {
|
|
1575
|
+
model = "anthropic/claude-sonnet-4-5";
|
|
1576
|
+
} else if (llmProvider === "groq") {
|
|
1577
|
+
model = "groq/llama-3.3-70b-versatile";
|
|
1578
|
+
} else if (llmProvider === "google") {
|
|
1579
|
+
model = "google/gemini-2.5-pro";
|
|
1580
|
+
} else if (llmProvider === "cerebras") {
|
|
1581
|
+
model = "cerebras/llama-3.3-70b";
|
|
1582
|
+
} else if (llmProvider === "mistral") {
|
|
1583
|
+
model = "mistral/mistral-medium-2508";
|
|
1584
|
+
}
|
|
1585
|
+
return model;
|
|
1586
|
+
};
|
|
1587
|
+
async function writeAgentSample(llmProvider, destPath, addExampleTool, addScorers) {
|
|
1588
|
+
const modelString = getModelIdentifier(llmProvider);
|
|
1589
|
+
const instructions = `
|
|
1590
|
+
You are a helpful weather assistant that provides accurate weather information and can help planning activities based on the weather.
|
|
1591
|
+
|
|
1592
|
+
Your primary function is to help users get weather details for specific locations. When responding:
|
|
1593
|
+
- Always ask for a location if none is provided
|
|
1594
|
+
- If the location name isn't in English, please translate it
|
|
1595
|
+
- If giving a location with multiple parts (e.g. "New York, NY"), use the most relevant part (e.g. "New York")
|
|
1596
|
+
- Include relevant details like humidity, wind conditions, and precipitation
|
|
1597
|
+
- Keep responses concise but informative
|
|
1598
|
+
- If the user asks for activities and provides the weather forecast, suggest activities based on the weather forecast.
|
|
1599
|
+
- If the user asks for activities, respond in the format they request.
|
|
1600
|
+
|
|
1601
|
+
${addExampleTool ? "Use the weatherTool to fetch current weather data." : ""}
|
|
1602
|
+
`;
|
|
1603
|
+
const content = `
|
|
1604
|
+
import { Agent } from '@mastra/core/agent';
|
|
1605
|
+
import { Memory } from '@mastra/memory';
|
|
1606
|
+
${addExampleTool ? `import { weatherTool } from '../tools/weather-tool';` : ""}
|
|
1607
|
+
${addScorers ? `import { scorers } from '../scorers/weather-scorer';` : ""}
|
|
1608
|
+
|
|
1609
|
+
export const weatherAgent = new Agent({
|
|
1610
|
+
id: 'weather-agent',
|
|
1611
|
+
name: 'Weather Agent',
|
|
1612
|
+
instructions: \`${instructions}\`,
|
|
1613
|
+
model: '${modelString}',
|
|
1614
|
+
${addExampleTool ? "tools: { weatherTool }," : ""}
|
|
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()
|
|
1639
|
+
});
|
|
1640
|
+
`;
|
|
1641
|
+
const formattedContent = await prettier.format(content, {
|
|
1642
|
+
parser: "typescript",
|
|
1643
|
+
singleQuote: true
|
|
1644
|
+
});
|
|
1645
|
+
await fs4.writeFile(destPath, "");
|
|
1646
|
+
await fs4.writeFile(destPath, formattedContent);
|
|
1647
|
+
}
|
|
1648
|
+
async function writeWorkflowSample(destPath) {
|
|
1649
|
+
const content = `import { createStep, createWorkflow } from '@mastra/core/workflows';
|
|
1588
1650
|
import { z } from 'zod';
|
|
1589
1651
|
|
|
1590
1652
|
const forecastSchema = z.object({
|
|
@@ -1780,41 +1842,138 @@ async function writeToolSample(destPath) {
|
|
|
1780
1842
|
const fileService = new FileService();
|
|
1781
1843
|
await fileService.copyStarterFile("tools.ts", destPath);
|
|
1782
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
|
+
}
|
|
1783
1933
|
async function writeCodeSampleForComponents(llmprovider, component, destPath, importComponents) {
|
|
1784
1934
|
switch (component) {
|
|
1785
1935
|
case "agents":
|
|
1786
|
-
return writeAgentSample(
|
|
1936
|
+
return writeAgentSample(
|
|
1937
|
+
llmprovider,
|
|
1938
|
+
destPath,
|
|
1939
|
+
importComponents.includes("tools"),
|
|
1940
|
+
importComponents.includes("scorers")
|
|
1941
|
+
);
|
|
1787
1942
|
case "tools":
|
|
1788
1943
|
return writeToolSample(destPath);
|
|
1789
1944
|
case "workflows":
|
|
1790
1945
|
return writeWorkflowSample(destPath);
|
|
1946
|
+
case "scorers":
|
|
1947
|
+
return writeScorersSample(llmprovider, destPath);
|
|
1791
1948
|
default:
|
|
1792
1949
|
return "";
|
|
1793
1950
|
}
|
|
1794
1951
|
}
|
|
1795
1952
|
var createComponentsDir = async (dirPath, component) => {
|
|
1796
1953
|
const componentPath = dirPath + `/${component}`;
|
|
1797
|
-
await
|
|
1954
|
+
await fsExtra.ensureDir(componentPath);
|
|
1798
1955
|
};
|
|
1799
1956
|
var writeIndexFile = async ({
|
|
1800
1957
|
dirPath,
|
|
1801
1958
|
addAgent,
|
|
1802
1959
|
addExample,
|
|
1803
|
-
addWorkflow
|
|
1960
|
+
addWorkflow,
|
|
1961
|
+
addScorers
|
|
1804
1962
|
}) => {
|
|
1805
1963
|
const indexPath = dirPath + "/index.ts";
|
|
1806
|
-
const destPath =
|
|
1964
|
+
const destPath = path3.join(indexPath);
|
|
1807
1965
|
try {
|
|
1808
1966
|
await fs4.writeFile(destPath, "");
|
|
1809
1967
|
const filteredExports = [
|
|
1810
1968
|
addWorkflow ? `workflows: { weatherWorkflow },` : "",
|
|
1811
|
-
addAgent ? `agents: { weatherAgent },` : ""
|
|
1969
|
+
addAgent ? `agents: { weatherAgent },` : "",
|
|
1970
|
+
addScorers ? `scorers: { toolCallAppropriatenessScorer, completenessScorer, translationScorer },` : ""
|
|
1812
1971
|
].filter(Boolean);
|
|
1813
1972
|
if (!addExample) {
|
|
1814
1973
|
await fs4.writeFile(
|
|
1815
1974
|
destPath,
|
|
1816
1975
|
`
|
|
1817
|
-
import { Mastra } from '@mastra/core';
|
|
1976
|
+
import { Mastra } from '@mastra/core/mastra';
|
|
1818
1977
|
|
|
1819
1978
|
export const mastra = new Mastra()
|
|
1820
1979
|
`
|
|
@@ -1827,19 +1986,36 @@ export const mastra = new Mastra()
|
|
|
1827
1986
|
import { Mastra } from '@mastra/core/mastra';
|
|
1828
1987
|
import { PinoLogger } from '@mastra/loggers';
|
|
1829
1988
|
import { LibSQLStore } from '@mastra/libsql';
|
|
1989
|
+
import { Observability, DefaultExporter, CloudExporter, SensitiveDataFilter } from '@mastra/observability';
|
|
1830
1990
|
${addWorkflow ? `import { weatherWorkflow } from './workflows/weather-workflow';` : ""}
|
|
1831
1991
|
${addAgent ? `import { weatherAgent } from './agents/weather-agent';` : ""}
|
|
1992
|
+
${addScorers ? `import { toolCallAppropriatenessScorer, completenessScorer, translationScorer } from './scorers/weather-scorer';` : ""}
|
|
1832
1993
|
|
|
1833
1994
|
export const mastra = new Mastra({
|
|
1834
1995
|
${filteredExports.join("\n ")}
|
|
1835
1996
|
storage: new LibSQLStore({
|
|
1836
|
-
|
|
1997
|
+
id: "mastra-storage",
|
|
1998
|
+
// stores observability, scores, ... into memory storage, if it needs to persist, change to file:../mastra.db
|
|
1837
1999
|
url: ":memory:",
|
|
1838
2000
|
}),
|
|
1839
2001
|
logger: new PinoLogger({
|
|
1840
2002
|
name: 'Mastra',
|
|
1841
2003
|
level: 'info',
|
|
1842
2004
|
}),
|
|
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
|
+
}),
|
|
1843
2019
|
});
|
|
1844
2020
|
`
|
|
1845
2021
|
);
|
|
@@ -1847,7 +2023,6 @@ export const mastra = new Mastra({
|
|
|
1847
2023
|
throw err;
|
|
1848
2024
|
}
|
|
1849
2025
|
};
|
|
1850
|
-
yoctoSpinner({ text: "Installing Mastra core dependencies\n" });
|
|
1851
2026
|
var getAPIKey = async (provider) => {
|
|
1852
2027
|
let key = "OPENAI_API_KEY";
|
|
1853
2028
|
switch (provider) {
|
|
@@ -1863,27 +2038,28 @@ var getAPIKey = async (provider) => {
|
|
|
1863
2038
|
case "cerebras":
|
|
1864
2039
|
key = "CEREBRAS_API_KEY";
|
|
1865
2040
|
return key;
|
|
2041
|
+
case "mistral":
|
|
2042
|
+
key = "MISTRAL_API_KEY";
|
|
2043
|
+
return key;
|
|
1866
2044
|
default:
|
|
1867
2045
|
return key;
|
|
1868
2046
|
}
|
|
1869
2047
|
};
|
|
1870
|
-
var writeAPIKey = async ({
|
|
1871
|
-
|
|
1872
|
-
apiKey = "your-api-key"
|
|
1873
|
-
}) => {
|
|
2048
|
+
var writeAPIKey = async ({ provider, apiKey }) => {
|
|
2049
|
+
const envFileName = apiKey ? ".env" : ".env.example";
|
|
1874
2050
|
const key = await getAPIKey(provider);
|
|
1875
|
-
const escapedKey =
|
|
1876
|
-
const escapedApiKey =
|
|
1877
|
-
await exec(`echo ${escapedKey}=${escapedApiKey} >>
|
|
2051
|
+
const escapedKey = shellQuote2.quote([key]);
|
|
2052
|
+
const escapedApiKey = shellQuote2.quote([apiKey ? apiKey : "your-api-key"]);
|
|
2053
|
+
await exec(`echo ${escapedKey}=${escapedApiKey} >> ${envFileName}`);
|
|
1878
2054
|
};
|
|
1879
2055
|
var createMastraDir = async (directory) => {
|
|
1880
2056
|
let dir = directory.trim().split("/").filter((item) => item !== "");
|
|
1881
|
-
const dirPath =
|
|
2057
|
+
const dirPath = path3.join(process.cwd(), ...dir, "mastra");
|
|
1882
2058
|
try {
|
|
1883
2059
|
await fs4.access(dirPath);
|
|
1884
2060
|
return { ok: false };
|
|
1885
2061
|
} catch {
|
|
1886
|
-
await
|
|
2062
|
+
await fsExtra.ensureDir(dirPath);
|
|
1887
2063
|
return { ok: true, dirPath };
|
|
1888
2064
|
}
|
|
1889
2065
|
};
|
|
@@ -1895,8 +2071,19 @@ var writeCodeSample = async (dirPath, component, llmProvider, importComponents)
|
|
|
1895
2071
|
throw err;
|
|
1896
2072
|
}
|
|
1897
2073
|
};
|
|
1898
|
-
var
|
|
1899
|
-
|
|
2074
|
+
var LLM_PROVIDERS = [
|
|
2075
|
+
{ value: "openai", label: "OpenAI", hint: "recommended" },
|
|
2076
|
+
{ value: "anthropic", label: "Anthropic" },
|
|
2077
|
+
{ value: "groq", label: "Groq" },
|
|
2078
|
+
{ value: "google", label: "Google" },
|
|
2079
|
+
{ value: "cerebras", label: "Cerebras" },
|
|
2080
|
+
{ value: "mistral", label: "Mistral" }
|
|
2081
|
+
];
|
|
2082
|
+
var interactivePrompt = async (args = {}) => {
|
|
2083
|
+
const { skip = {}, options: { showBanner = true } = {} } = args;
|
|
2084
|
+
if (showBanner) {
|
|
2085
|
+
Ie(color2.inverse(" Mastra Init "));
|
|
2086
|
+
}
|
|
1900
2087
|
const mastraProject = await Ce(
|
|
1901
2088
|
{
|
|
1902
2089
|
directory: () => he({
|
|
@@ -1904,19 +2091,15 @@ var interactivePrompt = async () => {
|
|
|
1904
2091
|
placeholder: "src/",
|
|
1905
2092
|
defaultValue: "src/"
|
|
1906
2093
|
}),
|
|
1907
|
-
llmProvider: () => ve({
|
|
1908
|
-
message: "Select default provider:",
|
|
1909
|
-
options:
|
|
1910
|
-
{ value: "openai", label: "OpenAI", hint: "recommended" },
|
|
1911
|
-
{ value: "anthropic", label: "Anthropic" },
|
|
1912
|
-
{ value: "groq", label: "Groq" },
|
|
1913
|
-
{ value: "google", label: "Google" },
|
|
1914
|
-
{ value: "cerebras", label: "Cerebras" }
|
|
1915
|
-
]
|
|
2094
|
+
llmProvider: () => skip?.llmProvider ? void 0 : ve({
|
|
2095
|
+
message: "Select a default provider:",
|
|
2096
|
+
options: LLM_PROVIDERS
|
|
1916
2097
|
}),
|
|
1917
2098
|
llmApiKey: async ({ results: { llmProvider } }) => {
|
|
2099
|
+
if (skip?.llmApiKey) return void 0;
|
|
2100
|
+
const llmName = LLM_PROVIDERS.find((p6) => p6.value === llmProvider)?.label || "provider";
|
|
1918
2101
|
const keyChoice = await ve({
|
|
1919
|
-
message: `Enter your ${
|
|
2102
|
+
message: `Enter your ${llmName} API key?`,
|
|
1920
2103
|
options: [
|
|
1921
2104
|
{ value: "skip", label: "Skip for now", hint: "default" },
|
|
1922
2105
|
{ value: "enter", label: "Enter API key" }
|
|
@@ -1926,52 +2109,42 @@ var interactivePrompt = async () => {
|
|
|
1926
2109
|
if (keyChoice === "enter") {
|
|
1927
2110
|
return he({
|
|
1928
2111
|
message: "Enter your API key:",
|
|
1929
|
-
placeholder: "sk-..."
|
|
2112
|
+
placeholder: "sk-...",
|
|
2113
|
+
validate: (value) => {
|
|
2114
|
+
if (value.length === 0) return "API key cannot be empty";
|
|
2115
|
+
}
|
|
1930
2116
|
});
|
|
1931
2117
|
}
|
|
1932
2118
|
return void 0;
|
|
1933
2119
|
},
|
|
1934
2120
|
configureEditorWithDocsMCP: async () => {
|
|
1935
|
-
const windsurfIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`windsurf`);
|
|
1936
|
-
const cursorIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`cursor`);
|
|
1937
|
-
const vscodeIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`vscode`);
|
|
1938
2121
|
const editor = await ve({
|
|
1939
|
-
message: `Make your
|
|
2122
|
+
message: `Make your IDE into a Mastra expert? (Installs Mastra's MCP server)`,
|
|
1940
2123
|
options: [
|
|
1941
2124
|
{ value: "skip", label: "Skip for now", hint: "default" },
|
|
1942
2125
|
{
|
|
1943
2126
|
value: "cursor",
|
|
1944
|
-
label: "Cursor (project only)"
|
|
1945
|
-
hint: cursorIsAlreadyInstalled ? `Already installed globally` : void 0
|
|
2127
|
+
label: "Cursor (project only)"
|
|
1946
2128
|
},
|
|
1947
2129
|
{
|
|
1948
2130
|
value: "cursor-global",
|
|
1949
|
-
label: "Cursor (global, all projects)"
|
|
1950
|
-
hint: cursorIsAlreadyInstalled ? `Already installed` : void 0
|
|
2131
|
+
label: "Cursor (global, all projects)"
|
|
1951
2132
|
},
|
|
1952
2133
|
{
|
|
1953
2134
|
value: "windsurf",
|
|
1954
|
-
label: "Windsurf"
|
|
1955
|
-
hint: windsurfIsAlreadyInstalled ? `Already installed` : void 0
|
|
2135
|
+
label: "Windsurf"
|
|
1956
2136
|
},
|
|
1957
2137
|
{
|
|
1958
2138
|
value: "vscode",
|
|
1959
|
-
label: "VSCode"
|
|
1960
|
-
|
|
2139
|
+
label: "VSCode"
|
|
2140
|
+
},
|
|
2141
|
+
{
|
|
2142
|
+
value: "antigravity",
|
|
2143
|
+
label: "Antigravity"
|
|
1961
2144
|
}
|
|
1962
2145
|
]
|
|
1963
2146
|
});
|
|
1964
2147
|
if (editor === `skip`) return void 0;
|
|
1965
|
-
if (editor === `windsurf` && windsurfIsAlreadyInstalled) {
|
|
1966
|
-
M.message(`
|
|
1967
|
-
Windsurf is already installed, skipping.`);
|
|
1968
|
-
return void 0;
|
|
1969
|
-
}
|
|
1970
|
-
if (editor === `vscode` && vscodeIsAlreadyInstalled) {
|
|
1971
|
-
M.message(`
|
|
1972
|
-
VSCode is already installed, skipping.`);
|
|
1973
|
-
return void 0;
|
|
1974
|
-
}
|
|
1975
2148
|
if (editor === `cursor`) {
|
|
1976
2149
|
M.message(
|
|
1977
2150
|
`
|
|
@@ -1980,19 +2153,19 @@ Note: you will need to go into Cursor Settings -> MCP Settings and manually enab
|
|
|
1980
2153
|
);
|
|
1981
2154
|
}
|
|
1982
2155
|
if (editor === `cursor-global`) {
|
|
1983
|
-
const
|
|
2156
|
+
const confirm3 = await ve({
|
|
1984
2157
|
message: `Global install will add/update ${cursorGlobalMCPConfigPath} and make the Mastra docs MCP server available in all your Cursor projects. Continue?`,
|
|
1985
2158
|
options: [
|
|
1986
2159
|
{ value: "yes", label: "Yes, I understand" },
|
|
1987
2160
|
{ value: "skip", label: "No, skip for now" }
|
|
1988
2161
|
]
|
|
1989
2162
|
});
|
|
1990
|
-
if (
|
|
2163
|
+
if (confirm3 !== `yes`) {
|
|
1991
2164
|
return void 0;
|
|
1992
2165
|
}
|
|
1993
2166
|
}
|
|
1994
2167
|
if (editor === `windsurf`) {
|
|
1995
|
-
const
|
|
2168
|
+
const confirm3 = await ve({
|
|
1996
2169
|
message: `Windsurf only supports a global MCP config (at ${windsurfGlobalMCPConfigPath}) is it ok to add/update that global config?
|
|
1997
2170
|
This means the Mastra docs MCP server will be available in all your Windsurf projects.`,
|
|
1998
2171
|
options: [
|
|
@@ -2000,11 +2173,31 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
2000
2173
|
{ value: "skip", label: "No, skip for now" }
|
|
2001
2174
|
]
|
|
2002
2175
|
});
|
|
2003
|
-
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`) {
|
|
2004
2190
|
return void 0;
|
|
2005
2191
|
}
|
|
2006
2192
|
}
|
|
2007
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
|
+
});
|
|
2008
2201
|
}
|
|
2009
2202
|
},
|
|
2010
2203
|
{
|
|
@@ -2016,17 +2209,245 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
2016
2209
|
);
|
|
2017
2210
|
return mastraProject;
|
|
2018
2211
|
};
|
|
2019
|
-
|
|
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
|
+
}
|
|
2020
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
|
+
}
|
|
2438
|
+
var s = Y();
|
|
2021
2439
|
var init = async ({
|
|
2022
|
-
directory,
|
|
2023
|
-
addExample = false,
|
|
2440
|
+
directory = "src/",
|
|
2024
2441
|
components,
|
|
2025
2442
|
llmProvider = "openai",
|
|
2026
2443
|
llmApiKey,
|
|
2027
|
-
|
|
2444
|
+
addExample = false,
|
|
2445
|
+
configureEditorWithDocsMCP,
|
|
2446
|
+
versionTag,
|
|
2447
|
+
initGit = false
|
|
2028
2448
|
}) => {
|
|
2029
2449
|
s.start("Initializing Mastra");
|
|
2450
|
+
const packageVersionTag = versionTag ? `@${versionTag}` : "";
|
|
2030
2451
|
try {
|
|
2031
2452
|
const result = await createMastraDir(directory);
|
|
2032
2453
|
if (!result.ok) {
|
|
@@ -2039,7 +2460,8 @@ var init = async ({
|
|
|
2039
2460
|
dirPath,
|
|
2040
2461
|
addExample,
|
|
2041
2462
|
addWorkflow: components.includes("workflows"),
|
|
2042
|
-
addAgent: components.includes("agents")
|
|
2463
|
+
addAgent: components.includes("agents"),
|
|
2464
|
+
addScorers: components.includes("scorers")
|
|
2043
2465
|
}),
|
|
2044
2466
|
...components.map((component) => createComponentsDir(dirPath, component)),
|
|
2045
2467
|
writeAPIKey({ provider: llmProvider, apiKey: llmApiKey })
|
|
@@ -2053,30 +2475,44 @@ var init = async ({
|
|
|
2053
2475
|
const depService = new DepsService();
|
|
2054
2476
|
const needsLibsql = await depService.checkDependencies(["@mastra/libsql"]) !== `ok`;
|
|
2055
2477
|
if (needsLibsql) {
|
|
2056
|
-
await depService.installPackages([
|
|
2478
|
+
await depService.installPackages([`@mastra/libsql${packageVersionTag}`]);
|
|
2057
2479
|
}
|
|
2058
2480
|
const needsMemory = components.includes(`agents`) && await depService.checkDependencies(["@mastra/memory"]) !== `ok`;
|
|
2059
2481
|
if (needsMemory) {
|
|
2060
|
-
await depService.installPackages([
|
|
2482
|
+
await depService.installPackages([`@mastra/memory${packageVersionTag}`]);
|
|
2061
2483
|
}
|
|
2062
2484
|
const needsLoggers = await depService.checkDependencies(["@mastra/loggers"]) !== `ok`;
|
|
2063
2485
|
if (needsLoggers) {
|
|
2064
|
-
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}`]);
|
|
2065
2495
|
}
|
|
2066
2496
|
}
|
|
2067
2497
|
const key = await getAPIKey(llmProvider || "openai");
|
|
2068
|
-
const aiSdkPackage = getAISDKPackage(llmProvider);
|
|
2069
|
-
const depsService = new DepsService();
|
|
2070
|
-
const pm = depsService.packageManager;
|
|
2071
|
-
const installCommand = getPackageManagerInstallCommand(pm);
|
|
2072
|
-
await exec2(`${pm} ${installCommand} ${aiSdkPackage}`);
|
|
2073
2498
|
if (configureEditorWithDocsMCP) {
|
|
2074
2499
|
await installMastraDocsMCPServer({
|
|
2075
2500
|
editor: configureEditorWithDocsMCP,
|
|
2076
|
-
directory: process.cwd()
|
|
2501
|
+
directory: process.cwd(),
|
|
2502
|
+
versionTag
|
|
2077
2503
|
});
|
|
2078
2504
|
}
|
|
2079
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
|
+
}
|
|
2080
2516
|
if (!llmApiKey) {
|
|
2081
2517
|
Me(`
|
|
2082
2518
|
${color2.green("Mastra initialized successfully!")}
|
|
@@ -2122,10 +2558,72 @@ var execWithTimeout = async (command, timeoutMs) => {
|
|
|
2122
2558
|
throw error;
|
|
2123
2559
|
}
|
|
2124
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/v1/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/v1/). Your bootstrapped project includes example code for [agents](https://mastra.ai/docs/v1/agents/overview), [tools](https://mastra.ai/docs/v1/agents/using-tools), [workflows](https://mastra.ai/docs/v1/workflows/overview), [scorers](https://mastra.ai/docs/v1/evals/overview), and [observability](https://mastra.ai/docs/v1/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/v1/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
|
+
};
|
|
2125
2623
|
async function installMastraDependency(pm, dependency, versionTag, isDev, timeout) {
|
|
2126
|
-
let installCommand =
|
|
2624
|
+
let installCommand = getPackageManagerAddCommand(pm);
|
|
2127
2625
|
if (isDev) {
|
|
2128
|
-
installCommand = `${installCommand}
|
|
2626
|
+
installCommand = `${installCommand} -D`;
|
|
2129
2627
|
}
|
|
2130
2628
|
try {
|
|
2131
2629
|
await execWithTimeout(`${pm} ${installCommand} ${dependency}${versionTag}`, timeout);
|
|
@@ -2147,23 +2645,42 @@ async function installMastraDependency(pm, dependency, versionTag, isDev, timeou
|
|
|
2147
2645
|
var createMastraProject = async ({
|
|
2148
2646
|
projectName: name,
|
|
2149
2647
|
createVersionTag,
|
|
2150
|
-
timeout
|
|
2648
|
+
timeout,
|
|
2649
|
+
llmProvider,
|
|
2650
|
+
llmApiKey,
|
|
2651
|
+
needsInteractive
|
|
2151
2652
|
}) => {
|
|
2152
2653
|
Ie(color2.inverse(" Mastra Create "));
|
|
2153
2654
|
const projectName = name ?? await he({
|
|
2154
2655
|
message: "What do you want to name your project?",
|
|
2155
2656
|
placeholder: "my-mastra-app",
|
|
2156
|
-
defaultValue: "my-mastra-app"
|
|
2657
|
+
defaultValue: "my-mastra-app",
|
|
2658
|
+
validate: (value) => {
|
|
2659
|
+
if (value.length === 0) return "Project name cannot be empty";
|
|
2660
|
+
if (fs3__default__default.existsSync(value)) {
|
|
2661
|
+
return `A directory named "${value}" already exists. Please choose a different name.`;
|
|
2662
|
+
}
|
|
2663
|
+
}
|
|
2157
2664
|
});
|
|
2158
2665
|
if (pD(projectName)) {
|
|
2159
2666
|
xe("Operation cancelled");
|
|
2160
2667
|
process.exit(0);
|
|
2161
2668
|
}
|
|
2669
|
+
let result = void 0;
|
|
2670
|
+
if (needsInteractive) {
|
|
2671
|
+
result = await interactivePrompt({
|
|
2672
|
+
options: { showBanner: false },
|
|
2673
|
+
skip: { llmProvider: llmProvider !== void 0, llmApiKey: llmApiKey !== void 0 }
|
|
2674
|
+
});
|
|
2675
|
+
}
|
|
2162
2676
|
const s2 = Y();
|
|
2677
|
+
const originalCwd = process.cwd();
|
|
2678
|
+
let projectPath = null;
|
|
2163
2679
|
try {
|
|
2164
2680
|
s2.start("Creating project");
|
|
2165
2681
|
try {
|
|
2166
2682
|
await fs4.mkdir(projectName);
|
|
2683
|
+
projectPath = path3.resolve(originalCwd, projectName);
|
|
2167
2684
|
} catch (error) {
|
|
2168
2685
|
if (error instanceof Error && "code" in error && error.code === "EEXIST") {
|
|
2169
2686
|
s2.stop(`A directory named "${projectName}" already exists. Please choose a different name.`);
|
|
@@ -2175,18 +2692,17 @@ var createMastraProject = async ({
|
|
|
2175
2692
|
}
|
|
2176
2693
|
process.chdir(projectName);
|
|
2177
2694
|
const pm = getPackageManager();
|
|
2178
|
-
const installCommand =
|
|
2695
|
+
const installCommand = getPackageManagerAddCommand(pm);
|
|
2179
2696
|
s2.message("Initializing project structure");
|
|
2180
2697
|
try {
|
|
2181
|
-
await
|
|
2182
|
-
await exec3(`npm pkg set type="module"`);
|
|
2183
|
-
await exec3(`npm pkg set engines.node=">=20.9.0"`);
|
|
2698
|
+
await initializePackageJson(pm);
|
|
2184
2699
|
const depsService = new DepsService();
|
|
2185
2700
|
await depsService.addScriptsToPackageJson({
|
|
2186
2701
|
dev: "mastra dev",
|
|
2187
2702
|
build: "mastra build",
|
|
2188
2703
|
start: "mastra start"
|
|
2189
2704
|
});
|
|
2705
|
+
await writeReadmeFile({ dirPath: process.cwd(), projectName });
|
|
2190
2706
|
} catch (error) {
|
|
2191
2707
|
throw new Error(
|
|
2192
2708
|
`Failed to initialize project structure: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
@@ -2195,8 +2711,8 @@ var createMastraProject = async ({
|
|
|
2195
2711
|
s2.stop("Project structure created");
|
|
2196
2712
|
s2.start(`Installing ${pm} dependencies`);
|
|
2197
2713
|
try {
|
|
2198
|
-
await exec3(`${pm} ${installCommand} zod`);
|
|
2199
|
-
await exec3(`${pm} ${installCommand} typescript @types/node
|
|
2714
|
+
await exec3(`${pm} ${installCommand} zod@^4`);
|
|
2715
|
+
await exec3(`${pm} ${installCommand} -D typescript @types/node`);
|
|
2200
2716
|
await exec3(`echo '{
|
|
2201
2717
|
"compilerOptions": {
|
|
2202
2718
|
"target": "ES2022",
|
|
@@ -2219,15 +2735,15 @@ var createMastraProject = async ({
|
|
|
2219
2735
|
);
|
|
2220
2736
|
}
|
|
2221
2737
|
s2.stop(`${pm} dependencies installed`);
|
|
2222
|
-
s2.start("Installing
|
|
2738
|
+
s2.start("Installing Mastra CLI");
|
|
2223
2739
|
const versionTag = createVersionTag ? `@${createVersionTag}` : "@latest";
|
|
2224
2740
|
try {
|
|
2225
2741
|
await installMastraDependency(pm, "mastra", versionTag, true, timeout);
|
|
2226
2742
|
} catch (error) {
|
|
2227
2743
|
throw new Error(`Failed to install Mastra CLI: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2228
2744
|
}
|
|
2229
|
-
s2.stop("
|
|
2230
|
-
s2.start("Installing dependencies");
|
|
2745
|
+
s2.stop("Mastra CLI installed");
|
|
2746
|
+
s2.start("Installing Mastra dependencies");
|
|
2231
2747
|
try {
|
|
2232
2748
|
await installMastraDependency(pm, "@mastra/core", versionTag, false, timeout);
|
|
2233
2749
|
await installMastraDependency(pm, "@mastra/libsql", versionTag, false, timeout);
|
|
@@ -2253,41 +2769,67 @@ var createMastraProject = async ({
|
|
|
2253
2769
|
}
|
|
2254
2770
|
s2.stop(".gitignore added");
|
|
2255
2771
|
Se("Project created successfully");
|
|
2256
|
-
console.
|
|
2257
|
-
return { projectName };
|
|
2772
|
+
console.info("");
|
|
2773
|
+
return { projectName, result };
|
|
2258
2774
|
} catch (error) {
|
|
2259
2775
|
s2.stop();
|
|
2260
2776
|
const errorMessage = error instanceof Error ? error.message : "An unexpected error occurred";
|
|
2261
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
|
+
}
|
|
2262
2788
|
process.exit(1);
|
|
2263
2789
|
}
|
|
2264
2790
|
};
|
|
2265
|
-
var
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
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
|
+
});
|
|
2801
|
+
return;
|
|
2802
|
+
}
|
|
2803
|
+
const needsInteractive = args.components === void 0 || args.llmProvider === void 0 || args.addExample === void 0;
|
|
2804
|
+
const { projectName, result } = await createMastraProject({
|
|
2805
|
+
projectName: args?.projectName,
|
|
2806
|
+
createVersionTag: args?.createVersionTag,
|
|
2807
|
+
timeout: args?.timeout,
|
|
2808
|
+
llmProvider: args?.llmProvider,
|
|
2809
|
+
llmApiKey: args?.llmApiKey,
|
|
2810
|
+
needsInteractive
|
|
2270
2811
|
});
|
|
2271
|
-
const directory =
|
|
2272
|
-
if (
|
|
2273
|
-
const result = await interactivePrompt();
|
|
2812
|
+
const directory = args.directory || "src/";
|
|
2813
|
+
if (needsInteractive && result) {
|
|
2274
2814
|
await init({
|
|
2275
2815
|
...result,
|
|
2276
2816
|
llmApiKey: result?.llmApiKey,
|
|
2277
|
-
components: ["agents", "tools", "workflows"],
|
|
2278
|
-
addExample: true
|
|
2817
|
+
components: ["agents", "tools", "workflows", "scorers"],
|
|
2818
|
+
addExample: true,
|
|
2819
|
+
versionTag: args.createVersionTag
|
|
2279
2820
|
});
|
|
2280
2821
|
postCreate({ projectName });
|
|
2281
2822
|
return;
|
|
2282
2823
|
}
|
|
2283
|
-
const { components = [], llmProvider = "openai", addExample = false, llmApiKey } =
|
|
2824
|
+
const { components = [], llmProvider = "openai", addExample = false, llmApiKey } = args;
|
|
2284
2825
|
await init({
|
|
2285
2826
|
directory,
|
|
2286
2827
|
components,
|
|
2287
2828
|
llmProvider,
|
|
2288
2829
|
addExample,
|
|
2289
2830
|
llmApiKey,
|
|
2290
|
-
configureEditorWithDocsMCP:
|
|
2831
|
+
configureEditorWithDocsMCP: args.mcpServer,
|
|
2832
|
+
versionTag: args.createVersionTag
|
|
2291
2833
|
});
|
|
2292
2834
|
postCreate({ projectName });
|
|
2293
2835
|
};
|
|
@@ -2300,18 +2842,225 @@ var postCreate = ({ projectName }) => {
|
|
|
2300
2842
|
${color2.cyan(`${packageManager} run dev`)}
|
|
2301
2843
|
`);
|
|
2302
2844
|
};
|
|
2845
|
+
function isGitHubUrl(url) {
|
|
2846
|
+
try {
|
|
2847
|
+
const parsedUrl = new URL(url);
|
|
2848
|
+
return parsedUrl.hostname === "github.com" && parsedUrl.pathname.split("/").length >= 3;
|
|
2849
|
+
} catch {
|
|
2850
|
+
return false;
|
|
2851
|
+
}
|
|
2852
|
+
}
|
|
2853
|
+
async function validateGitHubProject(githubUrl) {
|
|
2854
|
+
const errors = [];
|
|
2855
|
+
try {
|
|
2856
|
+
const urlParts = new URL(githubUrl).pathname.split("/").filter(Boolean);
|
|
2857
|
+
const owner = urlParts[0];
|
|
2858
|
+
const repo = urlParts[1]?.replace(".git", "");
|
|
2859
|
+
if (!owner || !repo) {
|
|
2860
|
+
throw new Error("Invalid GitHub URL format");
|
|
2861
|
+
}
|
|
2862
|
+
const branches = ["main", "master"];
|
|
2863
|
+
let packageJsonContent = null;
|
|
2864
|
+
let indexContent = null;
|
|
2865
|
+
for (const branch of branches) {
|
|
2866
|
+
try {
|
|
2867
|
+
const packageJsonUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/package.json`;
|
|
2868
|
+
const packageJsonResponse = await fetch(packageJsonUrl);
|
|
2869
|
+
if (packageJsonResponse.ok) {
|
|
2870
|
+
packageJsonContent = await packageJsonResponse.text();
|
|
2871
|
+
const indexUrl = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/src/mastra/index.ts`;
|
|
2872
|
+
const indexResponse = await fetch(indexUrl);
|
|
2873
|
+
if (indexResponse.ok) {
|
|
2874
|
+
indexContent = await indexResponse.text();
|
|
2875
|
+
}
|
|
2876
|
+
break;
|
|
2877
|
+
}
|
|
2878
|
+
} catch {
|
|
2879
|
+
}
|
|
2880
|
+
}
|
|
2881
|
+
if (!packageJsonContent) {
|
|
2882
|
+
errors.push("Could not fetch package.json from repository");
|
|
2883
|
+
return { isValid: false, errors };
|
|
2884
|
+
}
|
|
2885
|
+
try {
|
|
2886
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
2887
|
+
const hasMastraCore = packageJson.dependencies?.["@mastra/core"] || packageJson.devDependencies?.["@mastra/core"] || packageJson.peerDependencies?.["@mastra/core"];
|
|
2888
|
+
if (!hasMastraCore) {
|
|
2889
|
+
errors.push("Missing @mastra/core dependency in package.json");
|
|
2890
|
+
}
|
|
2891
|
+
} catch {
|
|
2892
|
+
errors.push("Invalid package.json format");
|
|
2893
|
+
}
|
|
2894
|
+
if (!indexContent) {
|
|
2895
|
+
errors.push("Missing src/mastra/index.ts file");
|
|
2896
|
+
} else {
|
|
2897
|
+
const hasMastraExport = indexContent.includes("export") && (indexContent.includes("new Mastra") || indexContent.includes("Mastra("));
|
|
2898
|
+
if (!hasMastraExport) {
|
|
2899
|
+
errors.push("src/mastra/index.ts does not export a Mastra instance");
|
|
2900
|
+
}
|
|
2901
|
+
}
|
|
2902
|
+
return { isValid: errors.length === 0, errors };
|
|
2903
|
+
} catch (error) {
|
|
2904
|
+
errors.push(`Failed to validate GitHub repository: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2905
|
+
return { isValid: false, errors };
|
|
2906
|
+
}
|
|
2907
|
+
}
|
|
2908
|
+
async function createFromGitHubUrl(url) {
|
|
2909
|
+
const urlParts = new URL(url).pathname.split("/").filter(Boolean);
|
|
2910
|
+
const owner = urlParts[0] || "unknown";
|
|
2911
|
+
const repo = urlParts[1] || "unknown";
|
|
2912
|
+
return {
|
|
2913
|
+
githubUrl: url,
|
|
2914
|
+
title: `${owner}/${repo}`,
|
|
2915
|
+
slug: repo,
|
|
2916
|
+
agents: [],
|
|
2917
|
+
mcp: [],
|
|
2918
|
+
tools: [],
|
|
2919
|
+
networks: [],
|
|
2920
|
+
workflows: []
|
|
2921
|
+
};
|
|
2922
|
+
}
|
|
2923
|
+
async function createFromTemplate(args) {
|
|
2924
|
+
let selectedTemplate;
|
|
2925
|
+
if (args.template === true) {
|
|
2926
|
+
const templates = await loadTemplates();
|
|
2927
|
+
const selected = await selectTemplate(templates);
|
|
2928
|
+
if (!selected) {
|
|
2929
|
+
M.info("No template selected. Exiting.");
|
|
2930
|
+
return;
|
|
2931
|
+
}
|
|
2932
|
+
selectedTemplate = selected;
|
|
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);
|
|
2938
|
+
if (!validation.isValid) {
|
|
2939
|
+
spinner4.stop("Validation failed");
|
|
2940
|
+
M.error("This does not appear to be a valid Mastra project:");
|
|
2941
|
+
validation.errors.forEach((error) => M.error(` - ${error}`));
|
|
2942
|
+
throw new Error("Invalid Mastra project");
|
|
2943
|
+
}
|
|
2944
|
+
spinner4.stop("Valid Mastra project \u2713");
|
|
2945
|
+
selectedTemplate = await createFromGitHubUrl(args.template);
|
|
2946
|
+
} else {
|
|
2947
|
+
const templates = await loadTemplates();
|
|
2948
|
+
const found = findTemplateByName(templates, args.template);
|
|
2949
|
+
if (!found) {
|
|
2950
|
+
M.error(`Template "${args.template}" not found. Available templates:`);
|
|
2951
|
+
templates.forEach((t) => M.info(` - ${t.title} (use: ${t.slug.replace("template-", "")})`));
|
|
2952
|
+
throw new Error(`Template "${args.template}" not found`);
|
|
2953
|
+
}
|
|
2954
|
+
selectedTemplate = found;
|
|
2955
|
+
}
|
|
2956
|
+
}
|
|
2957
|
+
if (!selectedTemplate) {
|
|
2958
|
+
throw new Error("No template selected");
|
|
2959
|
+
}
|
|
2960
|
+
let projectName = args.projectName;
|
|
2961
|
+
if (!projectName) {
|
|
2962
|
+
const defaultName = getDefaultProjectName(selectedTemplate);
|
|
2963
|
+
const response = await he({
|
|
2964
|
+
message: "What is your project name?",
|
|
2965
|
+
defaultValue: defaultName,
|
|
2966
|
+
placeholder: defaultName
|
|
2967
|
+
});
|
|
2968
|
+
if (pD(response)) {
|
|
2969
|
+
M.info("Project creation cancelled.");
|
|
2970
|
+
return;
|
|
2971
|
+
}
|
|
2972
|
+
projectName = response;
|
|
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;
|
|
2995
|
+
try {
|
|
2996
|
+
const analytics = args.injectedAnalytics || getAnalytics();
|
|
2997
|
+
if (analytics) {
|
|
2998
|
+
analytics.trackEvent("cli_template_used", {
|
|
2999
|
+
template_slug: selectedTemplate.slug,
|
|
3000
|
+
template_title: selectedTemplate.title
|
|
3001
|
+
});
|
|
3002
|
+
if (llmProvider) {
|
|
3003
|
+
analytics.trackEvent("cli_model_provider_selected", {
|
|
3004
|
+
provider: llmProvider,
|
|
3005
|
+
selection_method: args.llmProvider ? "cli_args" : "interactive"
|
|
3006
|
+
});
|
|
3007
|
+
}
|
|
3008
|
+
}
|
|
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({
|
|
3013
|
+
template: selectedTemplate,
|
|
3014
|
+
projectName,
|
|
3015
|
+
branch,
|
|
3016
|
+
llmProvider
|
|
3017
|
+
});
|
|
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
|
+
}
|
|
3029
|
+
Me(`
|
|
3030
|
+
${color2.green("Mastra template installed!")}
|
|
3031
|
+
|
|
3032
|
+
Add the necessary environment
|
|
3033
|
+
variables in your ${color2.cyan(".env")} file
|
|
3034
|
+
`);
|
|
3035
|
+
postCreate({ projectName });
|
|
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
|
+
}
|
|
3048
|
+
M.error(`Failed to create project from template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3049
|
+
throw error;
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
2303
3052
|
|
|
2304
3053
|
async function getPackageVersion() {
|
|
2305
3054
|
const __filename = fileURLToPath(import.meta.url);
|
|
2306
3055
|
const __dirname = dirname(__filename);
|
|
2307
|
-
const pkgJsonPath =
|
|
2308
|
-
const content = await fsExtra.readJSON(pkgJsonPath);
|
|
3056
|
+
const pkgJsonPath = path3.join(__dirname, "..", "package.json");
|
|
3057
|
+
const content = await fsExtra$1.readJSON(pkgJsonPath);
|
|
2309
3058
|
return content.version;
|
|
2310
3059
|
}
|
|
2311
3060
|
async function getCreateVersionTag() {
|
|
2312
3061
|
try {
|
|
2313
3062
|
const pkgPath = fileURLToPath(import.meta.resolve("create-mastra/package.json"));
|
|
2314
|
-
const json = await fsExtra.readJSON(pkgPath);
|
|
3063
|
+
const json = await fsExtra$1.readJSON(pkgPath);
|
|
2315
3064
|
const { stdout } = await execa("npm", ["dist-tag", "create-mastra"]);
|
|
2316
3065
|
const tagLine = stdout.split("\n").find((distLine) => distLine.endsWith(`: ${json.version}`));
|
|
2317
3066
|
const tag = tagLine ? tagLine.split(":")[0].trim() : "latest";
|
|
@@ -2335,25 +3084,30 @@ program.version(`${version}`, "-v, --version").description(`create-mastra ${vers
|
|
|
2335
3084
|
analytics.trackCommand({
|
|
2336
3085
|
command: "version"
|
|
2337
3086
|
});
|
|
2338
|
-
console.
|
|
3087
|
+
console.info(`create-mastra ${version}`);
|
|
2339
3088
|
} catch {
|
|
2340
3089
|
}
|
|
2341
3090
|
});
|
|
2342
3091
|
program.name("create-mastra").description("Create a new Mastra project").argument("[project-name]", "Directory name of the project").option(
|
|
2343
3092
|
"-p, --project-name <string>",
|
|
2344
3093
|
"Project name that will be used in package.json and as the project directory name."
|
|
2345
|
-
).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)").
|
|
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(
|
|
3095
|
+
"--template [template-name]",
|
|
3096
|
+
"Create project from a template (use template name, public GitHub URL, or leave blank to select from list)"
|
|
3097
|
+
).action(async (projectNameArg, args) => {
|
|
2346
3098
|
const projectName = projectNameArg || args.projectName;
|
|
2347
3099
|
const timeout = args?.timeout ? args?.timeout === true ? 6e4 : parseInt(args?.timeout, 10) : void 0;
|
|
2348
3100
|
if (args.default) {
|
|
2349
3101
|
await create({
|
|
2350
|
-
components: ["agents", "tools", "workflows"],
|
|
3102
|
+
components: ["agents", "tools", "workflows", "scorers"],
|
|
2351
3103
|
llmProvider: "openai",
|
|
2352
3104
|
addExample: true,
|
|
2353
3105
|
createVersionTag,
|
|
2354
3106
|
timeout,
|
|
2355
3107
|
mcpServer: args.mcp,
|
|
2356
|
-
directory: "src/"
|
|
3108
|
+
directory: "src/",
|
|
3109
|
+
template: args.template,
|
|
3110
|
+
analytics
|
|
2357
3111
|
});
|
|
2358
3112
|
return;
|
|
2359
3113
|
}
|
|
@@ -2361,12 +3115,14 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
|
|
|
2361
3115
|
components: args.components ? args.components.split(",") : [],
|
|
2362
3116
|
llmProvider: args.llm,
|
|
2363
3117
|
addExample: args.example,
|
|
2364
|
-
llmApiKey: args
|
|
3118
|
+
llmApiKey: args.llmApiKey,
|
|
2365
3119
|
createVersionTag,
|
|
2366
3120
|
timeout,
|
|
2367
3121
|
projectName,
|
|
2368
3122
|
directory: args.dir,
|
|
2369
|
-
mcpServer: args.mcp
|
|
3123
|
+
mcpServer: args.mcp,
|
|
3124
|
+
template: args.template,
|
|
3125
|
+
analytics
|
|
2370
3126
|
});
|
|
2371
3127
|
});
|
|
2372
3128
|
program.parse(process.argv);
|