create-mastra 0.0.0-roamin-openaivoice-speak-options-passing-20250926163614 → 0.0.0-salesman-20260127182805
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 +581 -1
- package/README.md +10 -32
- package/dist/index.js +953 -541
- package/dist/index.js.map +1 -1
- package/dist/starter-files/tools.ts +2 -2
- package/dist/templates/dev.entry.js +3 -46
- package/package.json +20 -21
package/dist/index.js
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
#! /usr/bin/env node
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
|
-
import * as
|
|
5
|
-
import
|
|
4
|
+
import * as fs3__default from 'node:fs';
|
|
5
|
+
import fs3__default__default, { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
6
6
|
import os from 'node:os';
|
|
7
7
|
import path3, { dirname } from 'node:path';
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
9
|
import { PostHog } from 'posthog-node';
|
|
10
|
+
import fs4 from 'node:fs/promises';
|
|
10
11
|
import util, { stripVTControlCharacters } from 'node:util';
|
|
11
12
|
import y$1, { stdout, stdin } from 'node:process';
|
|
12
13
|
import * as g from 'node:readline';
|
|
13
14
|
import g__default from 'node:readline';
|
|
14
15
|
import { Writable } from 'node:stream';
|
|
15
|
-
import fs5 from 'node:fs/promises';
|
|
16
16
|
import child_process from 'node:child_process';
|
|
17
17
|
import tty from 'node:tty';
|
|
18
|
-
import pino from 'pino';
|
|
19
|
-
import pretty from 'pino-pretty';
|
|
20
|
-
import { execa } from 'execa';
|
|
21
18
|
import fsExtra, { readJSON, ensureFile, writeJSON } from 'fs-extra/esm';
|
|
22
19
|
import prettier from 'prettier';
|
|
20
|
+
import { execa } from 'execa';
|
|
23
21
|
import fsExtra$1 from 'fs-extra';
|
|
22
|
+
import pino from 'pino';
|
|
23
|
+
import pretty from 'pino-pretty';
|
|
24
24
|
|
|
25
|
-
var __filename = fileURLToPath(import.meta.url);
|
|
26
|
-
var __dirname = path3.dirname(__filename);
|
|
25
|
+
var __filename$1 = fileURLToPath(import.meta.url);
|
|
26
|
+
var __dirname$1 = path3.dirname(__filename$1);
|
|
27
27
|
var analyticsInstance = null;
|
|
28
28
|
function getAnalytics() {
|
|
29
29
|
return analyticsInstance;
|
|
@@ -39,7 +39,7 @@ var PosthogAnalytics = class {
|
|
|
39
39
|
host = "https://app.posthog.com"
|
|
40
40
|
}) {
|
|
41
41
|
this.version = version;
|
|
42
|
-
const cliConfigPath = path3.join(__dirname, "mastra-cli.json");
|
|
42
|
+
const cliConfigPath = path3.join(__dirname$1, "mastra-cli.json");
|
|
43
43
|
if (existsSync(cliConfigPath)) {
|
|
44
44
|
try {
|
|
45
45
|
const { distinctId, sessionId } = JSON.parse(readFileSync(cliConfigPath, "utf-8"));
|
|
@@ -67,7 +67,7 @@ var PosthogAnalytics = class {
|
|
|
67
67
|
}
|
|
68
68
|
writeCliConfig({ distinctId, sessionId }) {
|
|
69
69
|
try {
|
|
70
|
-
writeFileSync(path3.join(__dirname, "mastra-cli.json"), JSON.stringify({ distinctId, sessionId }));
|
|
70
|
+
writeFileSync(path3.join(__dirname$1, "mastra-cli.json"), JSON.stringify({ distinctId, sessionId }));
|
|
71
71
|
} catch {
|
|
72
72
|
}
|
|
73
73
|
}
|
|
@@ -105,6 +105,10 @@ var PosthogAnalytics = class {
|
|
|
105
105
|
machine_id: os.hostname()
|
|
106
106
|
};
|
|
107
107
|
}
|
|
108
|
+
getDurationMs(startTime) {
|
|
109
|
+
const [seconds, nanoseconds] = process.hrtime(startTime);
|
|
110
|
+
return seconds * 1e3 + nanoseconds / 1e6;
|
|
111
|
+
}
|
|
108
112
|
captureSessionStart() {
|
|
109
113
|
if (!this.client) {
|
|
110
114
|
return;
|
|
@@ -173,8 +177,7 @@ var PosthogAnalytics = class {
|
|
|
173
177
|
const startTime = process.hrtime();
|
|
174
178
|
try {
|
|
175
179
|
const result = await execution();
|
|
176
|
-
const
|
|
177
|
-
const durationMs = seconds * 1e3 + nanoseconds / 1e6;
|
|
180
|
+
const durationMs = this.getDurationMs(startTime);
|
|
178
181
|
this.trackCommand({
|
|
179
182
|
command,
|
|
180
183
|
args,
|
|
@@ -184,8 +187,7 @@ var PosthogAnalytics = class {
|
|
|
184
187
|
});
|
|
185
188
|
return result;
|
|
186
189
|
} catch (error) {
|
|
187
|
-
const
|
|
188
|
-
const durationMs = seconds * 1e3 + nanoseconds / 1e6;
|
|
190
|
+
const durationMs = this.getDurationMs(startTime);
|
|
189
191
|
this.trackCommand({
|
|
190
192
|
command,
|
|
191
193
|
args,
|
|
@@ -382,7 +384,7 @@ function DD({onlyFirst:e=false}={}){const t=["[\\u001B\\u009B][[\\]()#;?]*(?:(?:
|
|
|
382
384
|
`).length-1;this.output.write(srcExports.cursor.move(-999,u*-1));}render(){const u=Y$1(this._render(this)??"",process.stdout.columns,{hard:true});if(u!==this._prevFrame){if(this.state==="initial")this.output.write(srcExports.cursor.hide);else {const t=BD(this._prevFrame,u);if(this.restoreCursor(),t&&t?.length===1){const F=t[0];this.output.write(srcExports.cursor.move(0,F)),this.output.write(srcExports.erase.lines(1));const s=u.split(`
|
|
383
385
|
`);this.output.write(s[F]),this._prevFrame=u,this.output.write(srcExports.cursor.move(0,s.length-F-1));return}if(t&&t?.length>1){const F=t[0];this.output.write(srcExports.cursor.move(0,F)),this.output.write(srcExports.erase.down());const s=u.split(`
|
|
384
386
|
`).slice(F);this.output.write(s.join(`
|
|
385
|
-
`)),this._prevFrame=u;return}this.output.write(srcExports.erase.down());}this.output.write(u),this.state==="initial"&&(this.state="active"),this._prevFrame=u;}}}var OD=Object.defineProperty,PD=(e,u,t)=>u in e?OD(e,u,{enumerable:true,configurable:true,writable:true,value:t}):e[u]=t,J=(e,u,t)=>(PD(e,typeof u!="symbol"?u+"":u,t),t);class LD extends x{constructor(u){super(u,false),J(this,"options"),J(this,"cursor",0),this.options=u.options,this.cursor=this.options.findIndex(({value:t})=>t===u.initialValue),this.cursor===-1&&(this.cursor=0),this.changeValue(),this.on("cursor",t=>{switch(t){case "left":case "up":this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;break;case "down":case "right":this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;break}this.changeValue();});}get _value(){return this.options[this.cursor]}changeValue(){this.value=this._value.value;}}class RD extends x{get valueWithCursor(){if(this.state==="submit")return this.value;if(this.cursor>=this.value.length)return `${this.value}\u2588`;const u=this.value.slice(0,this.cursor),[t,...F]=this.value.slice(this.cursor);return `${u}${color2.inverse(t)}${F.join("")}`}get cursor(){return this._cursor}constructor(u){super(u),this.on("finalize",()=>{this.value||(this.value=u.defaultValue);});}}
|
|
387
|
+
`)),this._prevFrame=u;return}this.output.write(srcExports.erase.down());}this.output.write(u),this.state==="initial"&&(this.state="active"),this._prevFrame=u;}}}class dD extends x{get cursor(){return this.value?0:1}get _value(){return this.cursor===0}constructor(u){super(u,false),this.value=!!u.initialValue,this.on("value",()=>{this.value=this._value;}),this.on("confirm",t=>{this.output.write(srcExports.cursor.move(0,-1)),this.value=t,this.state="submit",this.close();}),this.on("cursor",()=>{this.value=!this.value;});}}var OD=Object.defineProperty,PD=(e,u,t)=>u in e?OD(e,u,{enumerable:true,configurable:true,writable:true,value:t}):e[u]=t,J=(e,u,t)=>(PD(e,typeof u!="symbol"?u+"":u,t),t);class LD extends x{constructor(u){super(u,false),J(this,"options"),J(this,"cursor",0),this.options=u.options,this.cursor=this.options.findIndex(({value:t})=>t===u.initialValue),this.cursor===-1&&(this.cursor=0),this.changeValue(),this.on("cursor",t=>{switch(t){case "left":case "up":this.cursor=this.cursor===0?this.options.length-1:this.cursor-1;break;case "down":case "right":this.cursor=this.cursor===this.options.length-1?0:this.cursor+1;break}this.changeValue();});}get _value(){return this.options[this.cursor]}changeValue(){this.value=this._value.value;}}class RD extends x{get valueWithCursor(){if(this.state==="submit")return this.value;if(this.cursor>=this.value.length)return `${this.value}\u2588`;const u=this.value.slice(0,this.cursor),[t,...F]=this.value.slice(this.cursor);return `${u}${color2.inverse(t)}${F.join("")}`}get cursor(){return this._cursor}constructor(u){super(u),this.on("finalize",()=>{this.value||(this.value=u.defaultValue);});}}
|
|
386
388
|
|
|
387
389
|
function ce(){return y$1.platform!=="win32"?y$1.env.TERM!=="linux":!!y$1.env.CI||!!y$1.env.WT_SESSION||!!y$1.env.TERMINUS_SUBLIME||y$1.env.ConEmuTask==="{cmd::Cmder}"||y$1.env.TERM_PROGRAM==="Terminus-Sublime"||y$1.env.TERM_PROGRAM==="vscode"||y$1.env.TERM==="xterm-256color"||y$1.env.TERM==="alacritty"||y$1.env.TERMINAL_EMULATOR==="JetBrains-JediTerm"}const V=ce(),u=(t,n)=>V?t:n,le=u("\u25C6","*"),L=u("\u25A0","x"),W=u("\u25B2","x"),C=u("\u25C7","o"),ue=u("\u250C","T"),o=u("\u2502","|"),d=u("\u2514","\u2014"),k=u("\u25CF",">"),P=u("\u25CB"," "),_=u("\u2500","-"),me=u("\u256E","+"),de=u("\u251C","+"),pe=u("\u256F","+"),q=u("\u25CF","\u2022"),D=u("\u25C6","*"),U=u("\u25B2","!"),K=u("\u25A0","x"),b=t=>{switch(t){case "initial":case "active":return color2.cyan(le);case "cancel":return color2.red(L);case "error":return color2.yellow(W);case "submit":return color2.green(C)}},G=t=>{const{cursor:n,options:r,style:i}=t,s=t.maxItems??Number.POSITIVE_INFINITY,c=Math.max(process.stdout.rows-4,0),a=Math.min(c,Math.max(s,5));let l=0;n>=l+a-3?l=Math.max(Math.min(n-a+3,r.length-a),0):n<l+2&&(l=Math.max(n-2,0));const $=a<r.length&&l>0,g=a<r.length&&l+a<r.length;return r.slice(l,l+a).map((p,v,f)=>{const j=v===0&&$,E=v===f.length-1&&g;return j||E?color2.dim("..."):i(p,v+l===n)})},he=t=>new RD({validate:t.validate,placeholder:t.placeholder,defaultValue:t.defaultValue,initialValue:t.initialValue,render(){const n=`${color2.gray(o)}
|
|
388
390
|
${b(this.state)} ${t.message}
|
|
@@ -392,7 +394,12 @@ ${color2.yellow(d)} ${color2.yellow(this.error)}
|
|
|
392
394
|
`;case "submit":return `${n}${color2.gray(o)} ${color2.dim(this.value||t.placeholder)}`;case "cancel":return `${n}${color2.gray(o)} ${color2.strikethrough(color2.dim(this.value??""))}${this.value?.trim()?`
|
|
393
395
|
${color2.gray(o)}`:""}`;default:return `${n}${color2.cyan(o)} ${i}
|
|
394
396
|
${color2.cyan(d)}
|
|
395
|
-
`}}}).prompt(),
|
|
397
|
+
`}}}).prompt(),ye=t=>{const n=t.active??"Yes",r=t.inactive??"No";return new dD({active:n,inactive:r,initialValue:t.initialValue??true,render(){const i=`${color2.gray(o)}
|
|
398
|
+
${b(this.state)} ${t.message}
|
|
399
|
+
`,s=this.value?n:r;switch(this.state){case "submit":return `${i}${color2.gray(o)} ${color2.dim(s)}`;case "cancel":return `${i}${color2.gray(o)} ${color2.strikethrough(color2.dim(s))}
|
|
400
|
+
${color2.gray(o)}`;default:return `${i}${color2.cyan(o)} ${this.value?`${color2.green(k)} ${n}`:`${color2.dim(P)} ${color2.dim(n)}`} ${color2.dim("/")} ${this.value?`${color2.dim(P)} ${color2.dim(r)}`:`${color2.green(k)} ${r}`}
|
|
401
|
+
${color2.cyan(d)}
|
|
402
|
+
`}}}).prompt()},ve=t=>{const n=(r,i)=>{const s=r.label??String(r.value);switch(i){case "selected":return `${color2.dim(s)}`;case "active":return `${color2.green(k)} ${s} ${r.hint?color2.dim(`(${r.hint})`):""}`;case "cancelled":return `${color2.strikethrough(color2.dim(s))}`;default:return `${color2.dim(P)} ${color2.dim(s)}`}};return new LD({options:t.options,initialValue:t.initialValue,render(){const r=`${color2.gray(o)}
|
|
396
403
|
${b(this.state)} ${t.message}
|
|
397
404
|
`;switch(this.state){case "submit":return `${r}${color2.gray(o)} ${n(this.options[this.cursor],"selected")}`;case "cancel":return `${r}${color2.gray(o)} ${n(this.options[this.cursor],"cancelled")}
|
|
398
405
|
${color2.gray(o)}`;default:return `${r}${color2.cyan(o)} ${G({cursor:this.cursor,options:this.options,maxItems:t.maxItems,style:(i,s)=>n(i,s?"active":"inactive")}).join(`
|
|
@@ -422,7 +429,7 @@ ${color2.gray(d)} ${t}
|
|
|
422
429
|
`):process.stdout.write(`${w} ${l}
|
|
423
430
|
`),E(),s();};return {start:H,stop:N,message:(m="")=>{l=R(m??l);}}},Ce=async(t,n)=>{const r={},i=Object.keys(t);for(const s of i){const c=t[s],a=await c({results:r})?.catch(l=>{throw l});if(typeof n?.onCancel=="function"&&pD(a)){r[s]="canceled",n.onCancel({results:r});continue}r[s]=a;}return r};
|
|
424
431
|
|
|
425
|
-
var shellQuote
|
|
432
|
+
var shellQuote = {};
|
|
426
433
|
|
|
427
434
|
var quote;
|
|
428
435
|
var hasRequiredQuote;
|
|
@@ -688,16 +695,16 @@ function requireParse () {
|
|
|
688
695
|
var hasRequiredShellQuote;
|
|
689
696
|
|
|
690
697
|
function requireShellQuote () {
|
|
691
|
-
if (hasRequiredShellQuote) return shellQuote
|
|
698
|
+
if (hasRequiredShellQuote) return shellQuote;
|
|
692
699
|
hasRequiredShellQuote = 1;
|
|
693
700
|
|
|
694
|
-
shellQuote
|
|
695
|
-
shellQuote
|
|
696
|
-
return shellQuote
|
|
701
|
+
shellQuote.quote = requireQuote();
|
|
702
|
+
shellQuote.parse = requireParse();
|
|
703
|
+
return shellQuote;
|
|
697
704
|
}
|
|
698
705
|
|
|
699
706
|
var shellQuoteExports = requireShellQuote();
|
|
700
|
-
var
|
|
707
|
+
var shellQuote2 = /*@__PURE__*/getDefaultExportFromCjs(shellQuoteExports);
|
|
701
708
|
|
|
702
709
|
// eslint-disable-next-line no-warning-comments
|
|
703
710
|
// TODO: Use a better method when it's added to Node.js (https://github.com/nodejs/node/pull/40240)
|
|
@@ -724,13 +731,18 @@ const format = (open, close) => {
|
|
|
724
731
|
// Handle nested colors.
|
|
725
732
|
|
|
726
733
|
// We could have done this, but it's too slow (as of Node.js 22).
|
|
727
|
-
// return openCode + string.replaceAll(closeCode, openCode) + closeCode;
|
|
734
|
+
// return openCode + string.replaceAll(closeCode, (close === 22 ? closeCode : '') + openCode) + closeCode;
|
|
728
735
|
|
|
729
736
|
let result = openCode;
|
|
730
737
|
let lastIndex = 0;
|
|
731
738
|
|
|
739
|
+
// SGR 22 resets both bold (1) and dim (2). When we encounter a nested
|
|
740
|
+
// close for styles that use 22, we need to re-open the outer style.
|
|
741
|
+
const reopenOnNestedClose = close === 22;
|
|
742
|
+
const replaceCode = (reopenOnNestedClose ? closeCode : '') + openCode;
|
|
743
|
+
|
|
732
744
|
while (index !== -1) {
|
|
733
|
-
result += string.slice(lastIndex, index) +
|
|
745
|
+
result += string.slice(lastIndex, index) + replaceCode;
|
|
734
746
|
lastIndex = index + closeCode.length;
|
|
735
747
|
index = string.indexOf(closeCode, lastIndex);
|
|
736
748
|
}
|
|
@@ -882,6 +894,7 @@ class YoctoSpinner {
|
|
|
882
894
|
#exitHandlerBound;
|
|
883
895
|
#isInteractive;
|
|
884
896
|
#lastSpinnerFrameTime = 0;
|
|
897
|
+
#isSpinning = false;
|
|
885
898
|
|
|
886
899
|
constructor(options = {}) {
|
|
887
900
|
const spinner = options.spinner ?? defaultSpinner;
|
|
@@ -903,13 +916,17 @@ class YoctoSpinner {
|
|
|
903
916
|
return this;
|
|
904
917
|
}
|
|
905
918
|
|
|
919
|
+
this.#isSpinning = true;
|
|
906
920
|
this.#hideCursor();
|
|
907
921
|
this.#render();
|
|
908
922
|
this.#subscribeToProcessEvents();
|
|
909
923
|
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
924
|
+
// Only start the timer in interactive mode
|
|
925
|
+
if (this.#isInteractive) {
|
|
926
|
+
this.#timer = setInterval(() => {
|
|
927
|
+
this.#render();
|
|
928
|
+
}, this.#interval);
|
|
929
|
+
}
|
|
913
930
|
|
|
914
931
|
return this;
|
|
915
932
|
}
|
|
@@ -919,8 +936,12 @@ class YoctoSpinner {
|
|
|
919
936
|
return this;
|
|
920
937
|
}
|
|
921
938
|
|
|
922
|
-
|
|
923
|
-
this.#timer
|
|
939
|
+
this.#isSpinning = false;
|
|
940
|
+
if (this.#timer) {
|
|
941
|
+
clearInterval(this.#timer);
|
|
942
|
+
this.#timer = undefined;
|
|
943
|
+
}
|
|
944
|
+
|
|
924
945
|
this.#showCursor();
|
|
925
946
|
this.clear();
|
|
926
947
|
this.#unsubscribeFromProcessEvents();
|
|
@@ -953,7 +974,7 @@ class YoctoSpinner {
|
|
|
953
974
|
}
|
|
954
975
|
|
|
955
976
|
get isSpinning() {
|
|
956
|
-
return this.#
|
|
977
|
+
return this.#isSpinning;
|
|
957
978
|
}
|
|
958
979
|
|
|
959
980
|
get text() {
|
|
@@ -1090,11 +1111,11 @@ var MastraLogger = class {
|
|
|
1090
1111
|
}
|
|
1091
1112
|
trackException(_error) {
|
|
1092
1113
|
}
|
|
1093
|
-
async
|
|
1114
|
+
async listLogs(transportId, params) {
|
|
1094
1115
|
if (!transportId || !this.transports.has(transportId)) {
|
|
1095
1116
|
return { logs: [], total: 0, page: params?.page ?? 1, perPage: params?.perPage ?? 100, hasMore: false };
|
|
1096
1117
|
}
|
|
1097
|
-
return this.transports.get(transportId).
|
|
1118
|
+
return this.transports.get(transportId).listLogs(params) ?? {
|
|
1098
1119
|
logs: [],
|
|
1099
1120
|
total: 0,
|
|
1100
1121
|
page: params?.page ?? 1,
|
|
@@ -1102,7 +1123,7 @@ var MastraLogger = class {
|
|
|
1102
1123
|
hasMore: false
|
|
1103
1124
|
};
|
|
1104
1125
|
}
|
|
1105
|
-
async
|
|
1126
|
+
async listLogsByRunId({
|
|
1106
1127
|
transportId,
|
|
1107
1128
|
runId,
|
|
1108
1129
|
fromDate,
|
|
@@ -1115,7 +1136,7 @@ var MastraLogger = class {
|
|
|
1115
1136
|
if (!transportId || !this.transports.has(transportId) || !runId) {
|
|
1116
1137
|
return { logs: [], total: 0, page: page ?? 1, perPage: perPage ?? 100, hasMore: false };
|
|
1117
1138
|
}
|
|
1118
|
-
return this.transports.get(transportId).
|
|
1139
|
+
return this.transports.get(transportId).listLogsByRunId({ runId, fromDate, toDate, logLevel, filters, page, perPage }) ?? {
|
|
1119
1140
|
logs: [],
|
|
1120
1141
|
total: 0,
|
|
1121
1142
|
page: page ?? 1,
|
|
@@ -1125,10 +1146,15 @@ var MastraLogger = class {
|
|
|
1125
1146
|
}
|
|
1126
1147
|
};
|
|
1127
1148
|
|
|
1128
|
-
var PinoLogger = class extends MastraLogger {
|
|
1149
|
+
var PinoLogger = class _PinoLogger extends MastraLogger {
|
|
1129
1150
|
logger;
|
|
1130
1151
|
constructor(options = {}) {
|
|
1131
1152
|
super(options);
|
|
1153
|
+
const internalOptions = options;
|
|
1154
|
+
if (internalOptions._logger) {
|
|
1155
|
+
this.logger = internalOptions._logger;
|
|
1156
|
+
return;
|
|
1157
|
+
}
|
|
1132
1158
|
let prettyStream = void 0;
|
|
1133
1159
|
if (!options.overrideDefaultTransports) {
|
|
1134
1160
|
prettyStream = pretty({
|
|
@@ -1145,7 +1171,8 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1145
1171
|
{
|
|
1146
1172
|
name: options.name || "app",
|
|
1147
1173
|
level: options.level || LogLevel.INFO,
|
|
1148
|
-
formatters: options.formatters
|
|
1174
|
+
formatters: options.formatters,
|
|
1175
|
+
redact: options.redact
|
|
1149
1176
|
},
|
|
1150
1177
|
options.overrideDefaultTransports ? options?.transports?.default : transportsAry.length === 0 ? prettyStream : pino.multistream([
|
|
1151
1178
|
...transportsAry.map(([, transport]) => ({
|
|
@@ -1159,6 +1186,38 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1159
1186
|
])
|
|
1160
1187
|
);
|
|
1161
1188
|
}
|
|
1189
|
+
/**
|
|
1190
|
+
* Creates a child logger with additional bound context.
|
|
1191
|
+
* All logs from the child logger will include the bound context.
|
|
1192
|
+
*
|
|
1193
|
+
* @param bindings - Key-value pairs to include in all logs from this child logger
|
|
1194
|
+
* @returns A new PinoLogger instance with the bound context
|
|
1195
|
+
*
|
|
1196
|
+
* @example
|
|
1197
|
+
* ```typescript
|
|
1198
|
+
* const baseLogger = new PinoLogger({ name: 'MyApp' });
|
|
1199
|
+
*
|
|
1200
|
+
* // Create module-scoped logger
|
|
1201
|
+
* const serviceLogger = baseLogger.child({ module: 'UserService' });
|
|
1202
|
+
* serviceLogger.info('User created', { userId: '123' });
|
|
1203
|
+
* // Output includes: { module: 'UserService', userId: '123', msg: 'User created' }
|
|
1204
|
+
*
|
|
1205
|
+
* // Create request-scoped logger
|
|
1206
|
+
* const requestLogger = baseLogger.child({ requestId: req.id });
|
|
1207
|
+
* requestLogger.error('Request failed', { err: error });
|
|
1208
|
+
* // Output includes: { requestId: 'abc', msg: 'Request failed', err: {...} }
|
|
1209
|
+
* ```
|
|
1210
|
+
*/
|
|
1211
|
+
child(bindings) {
|
|
1212
|
+
const childPino = this.logger.child(bindings);
|
|
1213
|
+
const childOptions = {
|
|
1214
|
+
name: this.name,
|
|
1215
|
+
level: this.level,
|
|
1216
|
+
transports: Object.fromEntries(this.transports),
|
|
1217
|
+
_logger: childPino
|
|
1218
|
+
};
|
|
1219
|
+
return new _PinoLogger(childOptions);
|
|
1220
|
+
}
|
|
1162
1221
|
debug(message, args = {}) {
|
|
1163
1222
|
this.logger.debug(args, message);
|
|
1164
1223
|
}
|
|
@@ -1173,183 +1232,8 @@ var PinoLogger = class extends MastraLogger {
|
|
|
1173
1232
|
}
|
|
1174
1233
|
};
|
|
1175
1234
|
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
const execPath = process.env.npm_execpath || "";
|
|
1179
|
-
if (userAgent.includes("yarn")) {
|
|
1180
|
-
return "yarn";
|
|
1181
|
-
}
|
|
1182
|
-
if (userAgent.includes("pnpm")) {
|
|
1183
|
-
return "pnpm";
|
|
1184
|
-
}
|
|
1185
|
-
if (userAgent.includes("npm")) {
|
|
1186
|
-
return "npm";
|
|
1187
|
-
}
|
|
1188
|
-
if (execPath.includes("yarn")) {
|
|
1189
|
-
return "yarn";
|
|
1190
|
-
}
|
|
1191
|
-
if (execPath.includes("pnpm")) {
|
|
1192
|
-
return "pnpm";
|
|
1193
|
-
}
|
|
1194
|
-
if (execPath.includes("npm")) {
|
|
1195
|
-
return "npm";
|
|
1196
|
-
}
|
|
1197
|
-
return "npm";
|
|
1198
|
-
}
|
|
1199
|
-
var logger = new PinoLogger({
|
|
1200
|
-
name: "Mastra CLI",
|
|
1201
|
-
level: "info"
|
|
1202
|
-
});
|
|
1203
|
-
var exec = util.promisify(child_process.exec);
|
|
1204
|
-
async function cloneTemplate(options) {
|
|
1205
|
-
const { template, projectName, targetDir } = options;
|
|
1206
|
-
const projectPath = targetDir ? path3.resolve(targetDir, projectName) : path3.resolve(projectName);
|
|
1207
|
-
const spinner5 = yoctoSpinner({ text: `Cloning template "${template.title}"...` }).start();
|
|
1208
|
-
try {
|
|
1209
|
-
if (await directoryExists(projectPath)) {
|
|
1210
|
-
spinner5.error(`Directory ${projectName} already exists`);
|
|
1211
|
-
throw new Error(`Directory ${projectName} already exists`);
|
|
1212
|
-
}
|
|
1213
|
-
await cloneRepositoryWithoutGit(template.githubUrl, projectPath);
|
|
1214
|
-
await updatePackageJson(projectPath, projectName);
|
|
1215
|
-
const envExamplePath = path3.join(projectPath, ".env.example");
|
|
1216
|
-
if (await fileExists(envExamplePath)) {
|
|
1217
|
-
await fs5.copyFile(envExamplePath, path3.join(projectPath, ".env"));
|
|
1218
|
-
}
|
|
1219
|
-
spinner5.success(`Template "${template.title}" cloned successfully to ${projectName}`);
|
|
1220
|
-
return projectPath;
|
|
1221
|
-
} catch (error) {
|
|
1222
|
-
spinner5.error(`Failed to clone template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1223
|
-
throw error;
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
|
-
async function directoryExists(dirPath) {
|
|
1227
|
-
try {
|
|
1228
|
-
const stat = await fs5.stat(dirPath);
|
|
1229
|
-
return stat.isDirectory();
|
|
1230
|
-
} catch {
|
|
1231
|
-
return false;
|
|
1232
|
-
}
|
|
1233
|
-
}
|
|
1234
|
-
async function fileExists(filePath) {
|
|
1235
|
-
try {
|
|
1236
|
-
const stat = await fs5.stat(filePath);
|
|
1237
|
-
return stat.isFile();
|
|
1238
|
-
} catch {
|
|
1239
|
-
return false;
|
|
1240
|
-
}
|
|
1241
|
-
}
|
|
1242
|
-
async function cloneRepositoryWithoutGit(repoUrl, targetPath) {
|
|
1243
|
-
await fs5.mkdir(targetPath, { recursive: true });
|
|
1244
|
-
try {
|
|
1245
|
-
const degitRepo = repoUrl.replace("https://github.com/", "");
|
|
1246
|
-
const degitCommand = shellQuote.quote(["npx", "degit", degitRepo, targetPath]);
|
|
1247
|
-
await exec(degitCommand, {
|
|
1248
|
-
cwd: process.cwd()
|
|
1249
|
-
});
|
|
1250
|
-
} catch {
|
|
1251
|
-
try {
|
|
1252
|
-
const gitCommand = shellQuote.quote(["git", "clone", repoUrl, targetPath]);
|
|
1253
|
-
await exec(gitCommand, {
|
|
1254
|
-
cwd: process.cwd()
|
|
1255
|
-
});
|
|
1256
|
-
const gitDir = path3.join(targetPath, ".git");
|
|
1257
|
-
if (await directoryExists(gitDir)) {
|
|
1258
|
-
await fs5.rm(gitDir, { recursive: true, force: true });
|
|
1259
|
-
}
|
|
1260
|
-
} catch (gitError) {
|
|
1261
|
-
throw new Error(`Failed to clone repository: ${gitError instanceof Error ? gitError.message : "Unknown error"}`);
|
|
1262
|
-
}
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
async function updatePackageJson(projectPath, projectName) {
|
|
1266
|
-
const packageJsonPath = path3.join(projectPath, "package.json");
|
|
1267
|
-
try {
|
|
1268
|
-
const packageJsonContent = await fs5.readFile(packageJsonPath, "utf-8");
|
|
1269
|
-
const packageJson = JSON.parse(packageJsonContent);
|
|
1270
|
-
packageJson.name = projectName;
|
|
1271
|
-
await fs5.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf-8");
|
|
1272
|
-
} catch (error) {
|
|
1273
|
-
logger.warn(`Could not update package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1274
|
-
}
|
|
1275
|
-
}
|
|
1276
|
-
async function installDependencies(projectPath, packageManager) {
|
|
1277
|
-
const spinner5 = yoctoSpinner({ text: "Installing dependencies..." }).start();
|
|
1278
|
-
try {
|
|
1279
|
-
const pm = packageManager || getPackageManager();
|
|
1280
|
-
const installCommand = shellQuote.quote([pm, "install"]);
|
|
1281
|
-
await exec(installCommand, {
|
|
1282
|
-
cwd: projectPath
|
|
1283
|
-
});
|
|
1284
|
-
spinner5.success("Dependencies installed successfully");
|
|
1285
|
-
} catch (error) {
|
|
1286
|
-
spinner5.error(`Failed to install dependencies: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1287
|
-
throw error;
|
|
1288
|
-
}
|
|
1289
|
-
}
|
|
1290
|
-
var TEMPLATES_API_URL = process.env.MASTRA_TEMPLATES_API_URL || "https://mastra.ai/api/templates.json";
|
|
1291
|
-
async function loadTemplates() {
|
|
1292
|
-
try {
|
|
1293
|
-
const response = await fetch(TEMPLATES_API_URL);
|
|
1294
|
-
if (!response.ok) {
|
|
1295
|
-
throw new Error(`Failed to fetch templates: ${response.statusText}`);
|
|
1296
|
-
}
|
|
1297
|
-
const templates = await response.json();
|
|
1298
|
-
return templates;
|
|
1299
|
-
} catch (error) {
|
|
1300
|
-
console.error("Error loading templates:", error);
|
|
1301
|
-
throw new Error("Failed to load templates. Please check your internet connection and try again.");
|
|
1302
|
-
}
|
|
1303
|
-
}
|
|
1304
|
-
function pluralize(count, singular, plural) {
|
|
1305
|
-
return count === 1 ? singular : plural || `${singular}s`;
|
|
1306
|
-
}
|
|
1307
|
-
async function selectTemplate(templates) {
|
|
1308
|
-
const choices = templates.map((template) => {
|
|
1309
|
-
const parts = [];
|
|
1310
|
-
if (template.agents?.length) {
|
|
1311
|
-
parts.push(`${template.agents.length} ${pluralize(template.agents.length, "agent")}`);
|
|
1312
|
-
}
|
|
1313
|
-
if (template.tools?.length) {
|
|
1314
|
-
parts.push(`${template.tools.length} ${pluralize(template.tools.length, "tool")}`);
|
|
1315
|
-
}
|
|
1316
|
-
if (template.workflows?.length) {
|
|
1317
|
-
parts.push(`${template.workflows.length} ${pluralize(template.workflows.length, "workflow")}`);
|
|
1318
|
-
}
|
|
1319
|
-
if (template.mcp?.length) {
|
|
1320
|
-
parts.push(`${template.mcp.length} ${pluralize(template.mcp.length, "MCP server")}`);
|
|
1321
|
-
}
|
|
1322
|
-
if (template.networks?.length) {
|
|
1323
|
-
parts.push(`${template.networks.length} ${pluralize(template.networks.length, "agent network")}`);
|
|
1324
|
-
}
|
|
1325
|
-
return {
|
|
1326
|
-
value: template,
|
|
1327
|
-
label: template.title,
|
|
1328
|
-
hint: parts.join(", ") || "Template components"
|
|
1329
|
-
};
|
|
1330
|
-
});
|
|
1331
|
-
const selected = await ve({
|
|
1332
|
-
message: "Select a template:",
|
|
1333
|
-
options: choices
|
|
1334
|
-
});
|
|
1335
|
-
if (pD(selected)) {
|
|
1336
|
-
return null;
|
|
1337
|
-
}
|
|
1338
|
-
return selected;
|
|
1339
|
-
}
|
|
1340
|
-
function findTemplateByName(templates, templateName) {
|
|
1341
|
-
let template = templates.find((t) => t.slug === templateName);
|
|
1342
|
-
if (template) return template;
|
|
1343
|
-
const slugWithPrefix = `template-${templateName}`;
|
|
1344
|
-
template = templates.find((t) => t.slug === slugWithPrefix);
|
|
1345
|
-
if (template) return template;
|
|
1346
|
-
template = templates.find((t) => t.title.toLowerCase() === templateName.toLowerCase());
|
|
1347
|
-
if (template) return template;
|
|
1348
|
-
return null;
|
|
1349
|
-
}
|
|
1350
|
-
function getDefaultProjectName(template) {
|
|
1351
|
-
return template.slug.replace(/^template-/, "");
|
|
1352
|
-
}
|
|
1235
|
+
var package_default = {
|
|
1236
|
+
version: "1.0.1"};
|
|
1353
1237
|
function getPackageManagerAddCommand(pm) {
|
|
1354
1238
|
switch (pm) {
|
|
1355
1239
|
case "npm":
|
|
@@ -1370,9 +1254,9 @@ var DepsService = class {
|
|
|
1370
1254
|
this.packageManager = this.getPackageManager();
|
|
1371
1255
|
}
|
|
1372
1256
|
findLockFile(dir) {
|
|
1373
|
-
const lockFiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lock"];
|
|
1257
|
+
const lockFiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lock", "bun.lockb"];
|
|
1374
1258
|
for (const file of lockFiles) {
|
|
1375
|
-
if (
|
|
1259
|
+
if (fs3__default__default.existsSync(path3.join(dir, file))) {
|
|
1376
1260
|
return file;
|
|
1377
1261
|
}
|
|
1378
1262
|
}
|
|
@@ -1392,6 +1276,7 @@ var DepsService = class {
|
|
|
1392
1276
|
case "yarn.lock":
|
|
1393
1277
|
return "yarn";
|
|
1394
1278
|
case "bun.lock":
|
|
1279
|
+
case "bun.lockb":
|
|
1395
1280
|
return "bun";
|
|
1396
1281
|
default:
|
|
1397
1282
|
return "npm";
|
|
@@ -1411,11 +1296,11 @@ var DepsService = class {
|
|
|
1411
1296
|
try {
|
|
1412
1297
|
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1413
1298
|
try {
|
|
1414
|
-
await
|
|
1299
|
+
await fs4.access(packageJsonPath);
|
|
1415
1300
|
} catch {
|
|
1416
1301
|
return "No package.json file found in the current directory";
|
|
1417
1302
|
}
|
|
1418
|
-
const packageJson = JSON.parse(await
|
|
1303
|
+
const packageJson = JSON.parse(await fs4.readFile(packageJsonPath, "utf-8"));
|
|
1419
1304
|
for (const dependency of dependencies) {
|
|
1420
1305
|
if (!packageJson.dependencies || !packageJson.dependencies[dependency]) {
|
|
1421
1306
|
return `Please install ${dependency} before running this command (${this.packageManager} install ${dependency})`;
|
|
@@ -1430,7 +1315,7 @@ var DepsService = class {
|
|
|
1430
1315
|
async getProjectName() {
|
|
1431
1316
|
try {
|
|
1432
1317
|
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
1433
|
-
const packageJson = await
|
|
1318
|
+
const packageJson = await fs4.readFile(packageJsonPath, "utf-8");
|
|
1434
1319
|
const pkg = JSON.parse(packageJson);
|
|
1435
1320
|
return pkg.name;
|
|
1436
1321
|
} catch (err) {
|
|
@@ -1438,149 +1323,37 @@ var DepsService = class {
|
|
|
1438
1323
|
}
|
|
1439
1324
|
}
|
|
1440
1325
|
async addScriptsToPackageJson(scripts) {
|
|
1441
|
-
const packageJson = JSON.parse(await
|
|
1326
|
+
const packageJson = JSON.parse(await fs4.readFile("package.json", "utf-8"));
|
|
1442
1327
|
packageJson.scripts = {
|
|
1443
1328
|
...packageJson.scripts,
|
|
1444
1329
|
...scripts
|
|
1445
1330
|
};
|
|
1446
|
-
await
|
|
1331
|
+
await fs4.writeFile("package.json", JSON.stringify(packageJson, null, 2));
|
|
1447
1332
|
}
|
|
1448
1333
|
};
|
|
1449
|
-
var
|
|
1450
|
-
var createMcpConfig = (editor) => {
|
|
1451
|
-
if (editor === "vscode") {
|
|
1452
|
-
return {
|
|
1453
|
-
servers: {
|
|
1454
|
-
mastra: process.platform === `win32` ? {
|
|
1455
|
-
command: "cmd",
|
|
1456
|
-
args: ["/c", "npx", ...args],
|
|
1457
|
-
type: "stdio"
|
|
1458
|
-
} : {
|
|
1459
|
-
command: "npx",
|
|
1460
|
-
args,
|
|
1461
|
-
type: "stdio"
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
};
|
|
1465
|
-
}
|
|
1466
|
-
return {
|
|
1467
|
-
mcpServers: {
|
|
1468
|
-
mastra: {
|
|
1469
|
-
command: "npx",
|
|
1470
|
-
args
|
|
1471
|
-
}
|
|
1472
|
-
}
|
|
1473
|
-
};
|
|
1334
|
+
var EnvService = class {
|
|
1474
1335
|
};
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
...original?.servers || {},
|
|
1481
|
-
...createMcpConfig(editor).servers
|
|
1482
|
-
}
|
|
1483
|
-
};
|
|
1484
|
-
}
|
|
1485
|
-
return {
|
|
1486
|
-
...original,
|
|
1487
|
-
mcpServers: {
|
|
1488
|
-
...original?.mcpServers || {},
|
|
1489
|
-
...createMcpConfig(editor).mcpServers
|
|
1490
|
-
}
|
|
1491
|
-
};
|
|
1492
|
-
}
|
|
1493
|
-
async function writeMergedConfig(configPath, editor) {
|
|
1494
|
-
const configExists = existsSync(configPath);
|
|
1495
|
-
const config = makeConfig(configExists ? await readJSON(configPath) : {}, editor);
|
|
1496
|
-
await ensureFile(configPath);
|
|
1497
|
-
await writeJSON(configPath, config, {
|
|
1498
|
-
spaces: 2
|
|
1499
|
-
});
|
|
1500
|
-
}
|
|
1501
|
-
var windsurfGlobalMCPConfigPath = path3.join(os.homedir(), ".codeium", "windsurf", "mcp_config.json");
|
|
1502
|
-
var cursorGlobalMCPConfigPath = path3.join(os.homedir(), ".cursor", "mcp.json");
|
|
1503
|
-
path3.join(process.cwd(), ".vscode", "mcp.json");
|
|
1504
|
-
var vscodeGlobalMCPConfigPath = path3.join(
|
|
1505
|
-
os.homedir(),
|
|
1506
|
-
process.platform === "win32" ? path3.join("AppData", "Roaming", "Code", "User", "settings.json") : process.platform === "darwin" ? path3.join("Library", "Application Support", "Code", "User", "settings.json") : path3.join(".config", "Code", "User", "settings.json")
|
|
1507
|
-
);
|
|
1508
|
-
async function installMastraDocsMCPServer({ editor, directory }) {
|
|
1509
|
-
if (editor === `cursor`) {
|
|
1510
|
-
await writeMergedConfig(path3.join(directory, ".cursor", "mcp.json"), "cursor");
|
|
1511
|
-
}
|
|
1512
|
-
if (editor === `vscode`) {
|
|
1513
|
-
await writeMergedConfig(path3.join(directory, ".vscode", "mcp.json"), "vscode");
|
|
1336
|
+
var FileEnvService = class extends EnvService {
|
|
1337
|
+
filePath;
|
|
1338
|
+
constructor(filePath) {
|
|
1339
|
+
super();
|
|
1340
|
+
this.filePath = filePath;
|
|
1514
1341
|
}
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1342
|
+
readFile(filePath) {
|
|
1343
|
+
return new Promise((resolve, reject) => {
|
|
1344
|
+
fs3__default.readFile(filePath, "utf8", (err, data) => {
|
|
1345
|
+
if (err) reject(err);
|
|
1346
|
+
else resolve(data);
|
|
1347
|
+
});
|
|
1348
|
+
});
|
|
1521
1349
|
}
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
}
|
|
1530
|
-
async function globalMCPIsAlreadyInstalled(editor) {
|
|
1531
|
-
let configPath = ``;
|
|
1532
|
-
if (editor === "windsurf") {
|
|
1533
|
-
configPath = windsurfGlobalMCPConfigPath;
|
|
1534
|
-
} else if (editor === "cursor-global") {
|
|
1535
|
-
configPath = cursorGlobalMCPConfigPath;
|
|
1536
|
-
} else if (editor === "vscode") {
|
|
1537
|
-
configPath = vscodeGlobalMCPConfigPath;
|
|
1538
|
-
}
|
|
1539
|
-
if (!configPath || !existsSync(configPath)) {
|
|
1540
|
-
return false;
|
|
1541
|
-
}
|
|
1542
|
-
try {
|
|
1543
|
-
const configContents = await readJSON(configPath);
|
|
1544
|
-
if (!configContents) return false;
|
|
1545
|
-
if (editor === "vscode") {
|
|
1546
|
-
if (!configContents.servers) return false;
|
|
1547
|
-
const hasMastraMCP2 = Object.values(configContents.servers).some(
|
|
1548
|
-
(server) => server?.args?.find((arg) => arg?.includes(`@mastra/mcp-docs-server`))
|
|
1549
|
-
);
|
|
1550
|
-
return hasMastraMCP2;
|
|
1551
|
-
}
|
|
1552
|
-
if (!configContents?.mcpServers) return false;
|
|
1553
|
-
const hasMastraMCP = Object.values(configContents.mcpServers).some(
|
|
1554
|
-
(server) => server?.args?.find((arg) => arg?.includes(`@mastra/mcp-docs-server`))
|
|
1555
|
-
);
|
|
1556
|
-
return hasMastraMCP;
|
|
1557
|
-
} catch {
|
|
1558
|
-
return false;
|
|
1559
|
-
}
|
|
1560
|
-
}
|
|
1561
|
-
var EnvService = class {
|
|
1562
|
-
};
|
|
1563
|
-
var FileEnvService = class extends EnvService {
|
|
1564
|
-
filePath;
|
|
1565
|
-
constructor(filePath) {
|
|
1566
|
-
super();
|
|
1567
|
-
this.filePath = filePath;
|
|
1568
|
-
}
|
|
1569
|
-
readFile(filePath) {
|
|
1570
|
-
return new Promise((resolve, reject) => {
|
|
1571
|
-
fs4__default.readFile(filePath, "utf8", (err, data) => {
|
|
1572
|
-
if (err) reject(err);
|
|
1573
|
-
else resolve(data);
|
|
1574
|
-
});
|
|
1575
|
-
});
|
|
1576
|
-
}
|
|
1577
|
-
writeFile({ filePath, data }) {
|
|
1578
|
-
return new Promise((resolve, reject) => {
|
|
1579
|
-
fs4__default.writeFile(filePath, data, "utf8", (err) => {
|
|
1580
|
-
if (err) reject(err);
|
|
1581
|
-
else resolve();
|
|
1582
|
-
});
|
|
1583
|
-
});
|
|
1350
|
+
writeFile({ filePath, data }) {
|
|
1351
|
+
return new Promise((resolve, reject) => {
|
|
1352
|
+
fs3__default.writeFile(filePath, data, "utf8", (err) => {
|
|
1353
|
+
if (err) reject(err);
|
|
1354
|
+
else resolve();
|
|
1355
|
+
});
|
|
1356
|
+
});
|
|
1584
1357
|
}
|
|
1585
1358
|
async updateEnvData({
|
|
1586
1359
|
key,
|
|
@@ -1631,8 +1404,8 @@ var FileService = class {
|
|
|
1631
1404
|
const __filename = fileURLToPath(import.meta.url);
|
|
1632
1405
|
const __dirname = path3.dirname(__filename);
|
|
1633
1406
|
const filePath = path3.resolve(__dirname, "starter-files", inputFile);
|
|
1634
|
-
const fileString =
|
|
1635
|
-
if (
|
|
1407
|
+
const fileString = fs3__default__default.readFileSync(filePath, "utf8");
|
|
1408
|
+
if (fs3__default__default.existsSync(outputFilePath) && !replaceIfExists) {
|
|
1636
1409
|
console.info(`${outputFilePath} already exists`);
|
|
1637
1410
|
return false;
|
|
1638
1411
|
}
|
|
@@ -1647,7 +1420,7 @@ var FileService = class {
|
|
|
1647
1420
|
}
|
|
1648
1421
|
getFirstExistingFile(files) {
|
|
1649
1422
|
for (const f of files) {
|
|
1650
|
-
if (
|
|
1423
|
+
if (fs3__default__default.existsSync(f)) {
|
|
1651
1424
|
return f;
|
|
1652
1425
|
}
|
|
1653
1426
|
}
|
|
@@ -1657,66 +1430,162 @@ var FileService = class {
|
|
|
1657
1430
|
filePath,
|
|
1658
1431
|
replacements
|
|
1659
1432
|
}) {
|
|
1660
|
-
let fileContent =
|
|
1433
|
+
let fileContent = fs3__default__default.readFileSync(filePath, "utf8");
|
|
1661
1434
|
replacements.forEach(({ search, replace }) => {
|
|
1662
1435
|
fileContent = fileContent.replaceAll(search, replace);
|
|
1663
1436
|
});
|
|
1664
|
-
|
|
1437
|
+
fs3__default__default.writeFileSync(filePath, fileContent);
|
|
1665
1438
|
}
|
|
1666
1439
|
};
|
|
1667
|
-
var
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
case "cerebras":
|
|
1671
|
-
return "^0.2.14";
|
|
1672
|
-
default:
|
|
1673
|
-
return "^1.0.0";
|
|
1674
|
-
}
|
|
1440
|
+
var createArgs = (versionTag) => {
|
|
1441
|
+
const packageName = versionTag ? `@mastra/mcp-docs-server@${versionTag}` : "@mastra/mcp-docs-server";
|
|
1442
|
+
return ["-y", packageName];
|
|
1675
1443
|
};
|
|
1676
|
-
var
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
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
|
+
};
|
|
1692
1460
|
}
|
|
1461
|
+
return {
|
|
1462
|
+
mcpServers: {
|
|
1463
|
+
mastra: {
|
|
1464
|
+
command: "npx",
|
|
1465
|
+
args
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
};
|
|
1693
1469
|
};
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1470
|
+
function makeConfig(original, editor, versionTag) {
|
|
1471
|
+
if (editor === "vscode") {
|
|
1472
|
+
return {
|
|
1473
|
+
...original,
|
|
1474
|
+
servers: {
|
|
1475
|
+
...original?.servers || {},
|
|
1476
|
+
...createMcpConfig(editor, versionTag).servers
|
|
1477
|
+
}
|
|
1478
|
+
};
|
|
1479
|
+
}
|
|
1480
|
+
return {
|
|
1481
|
+
...original,
|
|
1482
|
+
mcpServers: {
|
|
1483
|
+
...original?.mcpServers || {},
|
|
1484
|
+
...createMcpConfig(editor, versionTag).mcpServers
|
|
1485
|
+
}
|
|
1486
|
+
};
|
|
1487
|
+
}
|
|
1488
|
+
async function writeMergedConfig(configPath, editor, versionTag) {
|
|
1489
|
+
const configExists = existsSync(configPath);
|
|
1490
|
+
const config = makeConfig(configExists ? await readJSON(configPath) : {}, editor, versionTag);
|
|
1491
|
+
await ensureFile(configPath);
|
|
1492
|
+
await writeJSON(configPath, config, {
|
|
1493
|
+
spaces: 2
|
|
1494
|
+
});
|
|
1495
|
+
}
|
|
1496
|
+
var windsurfGlobalMCPConfigPath = path3.join(os.homedir(), ".codeium", "windsurf", "mcp_config.json");
|
|
1497
|
+
var antigravityGlobalMCPConfigPath = path3.join(os.homedir(), ".gemini", "antigravity", "mcp_config.json");
|
|
1498
|
+
var cursorGlobalMCPConfigPath = path3.join(os.homedir(), ".cursor", "mcp.json");
|
|
1499
|
+
path3.join(process.cwd(), ".vscode", "mcp.json");
|
|
1500
|
+
var vscodeGlobalMCPConfigPath = path3.join(
|
|
1501
|
+
os.homedir(),
|
|
1502
|
+
process.platform === "win32" ? path3.join("AppData", "Roaming", "Code", "User", "settings.json") : process.platform === "darwin" ? path3.join("Library", "Application Support", "Code", "User", "settings.json") : path3.join(".config", "Code", "User", "settings.json")
|
|
1503
|
+
);
|
|
1504
|
+
async function installMastraDocsMCPServer({
|
|
1505
|
+
editor,
|
|
1506
|
+
directory,
|
|
1507
|
+
versionTag
|
|
1508
|
+
}) {
|
|
1509
|
+
if (editor === `cursor`) {
|
|
1510
|
+
await writeMergedConfig(path3.join(directory, ".cursor", "mcp.json"), "cursor", versionTag);
|
|
1511
|
+
}
|
|
1512
|
+
if (editor === `vscode`) {
|
|
1513
|
+
await writeMergedConfig(path3.join(directory, ".vscode", "mcp.json"), "vscode", versionTag);
|
|
1514
|
+
}
|
|
1515
|
+
if (editor === `cursor-global`) {
|
|
1516
|
+
const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor, versionTag);
|
|
1517
|
+
if (alreadyInstalled) {
|
|
1518
|
+
return;
|
|
1519
|
+
}
|
|
1520
|
+
await writeMergedConfig(cursorGlobalMCPConfigPath, "cursor-global", versionTag);
|
|
1521
|
+
}
|
|
1522
|
+
if (editor === `windsurf`) {
|
|
1523
|
+
const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor, versionTag);
|
|
1524
|
+
if (alreadyInstalled) {
|
|
1525
|
+
return;
|
|
1526
|
+
}
|
|
1527
|
+
await writeMergedConfig(windsurfGlobalMCPConfigPath, editor, versionTag);
|
|
1528
|
+
}
|
|
1529
|
+
if (editor === `antigravity`) {
|
|
1530
|
+
const alreadyInstalled = await globalMCPIsAlreadyInstalled(editor, versionTag);
|
|
1531
|
+
if (alreadyInstalled) {
|
|
1532
|
+
return;
|
|
1533
|
+
}
|
|
1534
|
+
await writeMergedConfig(antigravityGlobalMCPConfigPath, editor, versionTag);
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
async function globalMCPIsAlreadyInstalled(editor, versionTag) {
|
|
1538
|
+
let configPath = ``;
|
|
1539
|
+
if (editor === "windsurf") {
|
|
1540
|
+
configPath = windsurfGlobalMCPConfigPath;
|
|
1541
|
+
} else if (editor === "antigravity") {
|
|
1542
|
+
configPath = antigravityGlobalMCPConfigPath;
|
|
1543
|
+
} else if (editor === "cursor-global") {
|
|
1544
|
+
configPath = cursorGlobalMCPConfigPath;
|
|
1545
|
+
} else if (editor === "vscode") {
|
|
1546
|
+
configPath = vscodeGlobalMCPConfigPath;
|
|
1547
|
+
}
|
|
1548
|
+
if (!configPath || !existsSync(configPath)) {
|
|
1549
|
+
return false;
|
|
1550
|
+
}
|
|
1551
|
+
try {
|
|
1552
|
+
const configContents = await readJSON(configPath);
|
|
1553
|
+
if (!configContents) return false;
|
|
1554
|
+
const expectedPackage = versionTag ? `@mastra/mcp-docs-server@${versionTag}` : "@mastra/mcp-docs-server";
|
|
1555
|
+
if (editor === "vscode") {
|
|
1556
|
+
if (!configContents.servers) return false;
|
|
1557
|
+
const hasMastraMCP2 = Object.values(configContents.servers).some(
|
|
1558
|
+
(server) => server?.args?.find((arg) => arg === expectedPackage)
|
|
1559
|
+
);
|
|
1560
|
+
return hasMastraMCP2;
|
|
1561
|
+
}
|
|
1562
|
+
if (!configContents?.mcpServers) return false;
|
|
1563
|
+
const hasMastraMCP = Object.values(configContents.mcpServers).some(
|
|
1564
|
+
(server) => server?.args?.find((arg) => arg === expectedPackage)
|
|
1565
|
+
);
|
|
1566
|
+
return hasMastraMCP;
|
|
1567
|
+
} catch {
|
|
1568
|
+
return false;
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
var exec = util.promisify(child_process.exec);
|
|
1572
|
+
var getModelIdentifier = (llmProvider) => {
|
|
1573
|
+
let model = "openai/gpt-4o";
|
|
1574
|
+
if (llmProvider === "anthropic") {
|
|
1575
|
+
model = "anthropic/claude-sonnet-4-5";
|
|
1703
1576
|
} else if (llmProvider === "groq") {
|
|
1704
|
-
|
|
1705
|
-
modelItem = `groq('llama-3.3-70b-versatile')`;
|
|
1577
|
+
model = "groq/llama-3.3-70b-versatile";
|
|
1706
1578
|
} else if (llmProvider === "google") {
|
|
1707
|
-
|
|
1708
|
-
modelItem = `google('gemini-2.5-pro')`;
|
|
1579
|
+
model = "google/gemini-2.5-pro";
|
|
1709
1580
|
} else if (llmProvider === "cerebras") {
|
|
1710
|
-
|
|
1711
|
-
modelItem = `cerebras('llama-3.3-70b')`;
|
|
1581
|
+
model = "cerebras/llama-3.3-70b";
|
|
1712
1582
|
} else if (llmProvider === "mistral") {
|
|
1713
|
-
|
|
1714
|
-
modelItem = `mistral('mistral-medium-2508')`;
|
|
1583
|
+
model = "mistral/mistral-medium-2508";
|
|
1715
1584
|
}
|
|
1716
|
-
return
|
|
1585
|
+
return model;
|
|
1717
1586
|
};
|
|
1718
|
-
async function writeAgentSample(llmProvider, destPath, addExampleTool) {
|
|
1719
|
-
const
|
|
1587
|
+
async function writeAgentSample(llmProvider, destPath, addExampleTool, addScorers) {
|
|
1588
|
+
const modelString = getModelIdentifier(llmProvider);
|
|
1720
1589
|
const instructions = `
|
|
1721
1590
|
You are a helpful weather assistant that provides accurate weather information and can help planning activities based on the weather.
|
|
1722
1591
|
|
|
@@ -1732,30 +1601,49 @@ async function writeAgentSample(llmProvider, destPath, addExampleTool) {
|
|
|
1732
1601
|
${addExampleTool ? "Use the weatherTool to fetch current weather data." : ""}
|
|
1733
1602
|
`;
|
|
1734
1603
|
const content = `
|
|
1735
|
-
${providerImport}
|
|
1736
1604
|
import { Agent } from '@mastra/core/agent';
|
|
1737
1605
|
import { Memory } from '@mastra/memory';
|
|
1738
|
-
import { LibSQLStore } from '@mastra/libsql';
|
|
1739
1606
|
${addExampleTool ? `import { weatherTool } from '../tools/weather-tool';` : ""}
|
|
1607
|
+
${addScorers ? `import { scorers } from '../scorers/weather-scorer';` : ""}
|
|
1740
1608
|
|
|
1741
1609
|
export const weatherAgent = new Agent({
|
|
1610
|
+
id: 'weather-agent',
|
|
1742
1611
|
name: 'Weather Agent',
|
|
1743
1612
|
instructions: \`${instructions}\`,
|
|
1744
|
-
model: ${
|
|
1613
|
+
model: '${modelString}',
|
|
1745
1614
|
${addExampleTool ? "tools: { weatherTool }," : ""}
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
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()
|
|
1751
1639
|
});
|
|
1752
1640
|
`;
|
|
1753
1641
|
const formattedContent = await prettier.format(content, {
|
|
1754
1642
|
parser: "typescript",
|
|
1755
1643
|
singleQuote: true
|
|
1756
1644
|
});
|
|
1757
|
-
await
|
|
1758
|
-
await
|
|
1645
|
+
await fs4.writeFile(destPath, "");
|
|
1646
|
+
await fs4.writeFile(destPath, formattedContent);
|
|
1759
1647
|
}
|
|
1760
1648
|
async function writeWorkflowSample(destPath) {
|
|
1761
1649
|
const content = `import { createStep, createWorkflow } from '@mastra/core/workflows';
|
|
@@ -1948,20 +1836,115 @@ export { weatherWorkflow };`;
|
|
|
1948
1836
|
semi: true,
|
|
1949
1837
|
singleQuote: true
|
|
1950
1838
|
});
|
|
1951
|
-
await
|
|
1839
|
+
await fs4.writeFile(destPath, formattedContent);
|
|
1952
1840
|
}
|
|
1953
1841
|
async function writeToolSample(destPath) {
|
|
1954
1842
|
const fileService = new FileService();
|
|
1955
1843
|
await fileService.copyStarterFile("tools.ts", destPath);
|
|
1956
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
|
+
}
|
|
1957
1933
|
async function writeCodeSampleForComponents(llmprovider, component, destPath, importComponents) {
|
|
1958
1934
|
switch (component) {
|
|
1959
1935
|
case "agents":
|
|
1960
|
-
return writeAgentSample(
|
|
1936
|
+
return writeAgentSample(
|
|
1937
|
+
llmprovider,
|
|
1938
|
+
destPath,
|
|
1939
|
+
importComponents.includes("tools"),
|
|
1940
|
+
importComponents.includes("scorers")
|
|
1941
|
+
);
|
|
1961
1942
|
case "tools":
|
|
1962
1943
|
return writeToolSample(destPath);
|
|
1963
1944
|
case "workflows":
|
|
1964
1945
|
return writeWorkflowSample(destPath);
|
|
1946
|
+
case "scorers":
|
|
1947
|
+
return writeScorersSample(llmprovider, destPath);
|
|
1965
1948
|
default:
|
|
1966
1949
|
return "";
|
|
1967
1950
|
}
|
|
@@ -1974,46 +1957,65 @@ var writeIndexFile = async ({
|
|
|
1974
1957
|
dirPath,
|
|
1975
1958
|
addAgent,
|
|
1976
1959
|
addExample,
|
|
1977
|
-
addWorkflow
|
|
1960
|
+
addWorkflow,
|
|
1961
|
+
addScorers
|
|
1978
1962
|
}) => {
|
|
1979
1963
|
const indexPath = dirPath + "/index.ts";
|
|
1980
1964
|
const destPath = path3.join(indexPath);
|
|
1981
1965
|
try {
|
|
1982
|
-
await
|
|
1966
|
+
await fs4.writeFile(destPath, "");
|
|
1983
1967
|
const filteredExports = [
|
|
1984
1968
|
addWorkflow ? `workflows: { weatherWorkflow },` : "",
|
|
1985
|
-
addAgent ? `agents: { weatherAgent },` : ""
|
|
1969
|
+
addAgent ? `agents: { weatherAgent },` : "",
|
|
1970
|
+
addScorers ? `scorers: { toolCallAppropriatenessScorer, completenessScorer, translationScorer },` : ""
|
|
1986
1971
|
].filter(Boolean);
|
|
1987
1972
|
if (!addExample) {
|
|
1988
|
-
await
|
|
1973
|
+
await fs4.writeFile(
|
|
1989
1974
|
destPath,
|
|
1990
1975
|
`
|
|
1991
|
-
import { Mastra } from '@mastra/core';
|
|
1976
|
+
import { Mastra } from '@mastra/core/mastra';
|
|
1992
1977
|
|
|
1993
1978
|
export const mastra = new Mastra()
|
|
1994
1979
|
`
|
|
1995
1980
|
);
|
|
1996
1981
|
return;
|
|
1997
1982
|
}
|
|
1998
|
-
await
|
|
1983
|
+
await fs4.writeFile(
|
|
1999
1984
|
destPath,
|
|
2000
1985
|
`
|
|
2001
1986
|
import { Mastra } from '@mastra/core/mastra';
|
|
2002
1987
|
import { PinoLogger } from '@mastra/loggers';
|
|
2003
1988
|
import { LibSQLStore } from '@mastra/libsql';
|
|
1989
|
+
import { Observability, DefaultExporter, CloudExporter, SensitiveDataFilter } from '@mastra/observability';
|
|
2004
1990
|
${addWorkflow ? `import { weatherWorkflow } from './workflows/weather-workflow';` : ""}
|
|
2005
1991
|
${addAgent ? `import { weatherAgent } from './agents/weather-agent';` : ""}
|
|
1992
|
+
${addScorers ? `import { toolCallAppropriatenessScorer, completenessScorer, translationScorer } from './scorers/weather-scorer';` : ""}
|
|
2006
1993
|
|
|
2007
1994
|
export const mastra = new Mastra({
|
|
2008
1995
|
${filteredExports.join("\n ")}
|
|
2009
1996
|
storage: new LibSQLStore({
|
|
2010
|
-
|
|
1997
|
+
id: "mastra-storage",
|
|
1998
|
+
// stores observability, scores, ... into memory storage, if it needs to persist, change to file:../mastra.db
|
|
2011
1999
|
url: ":memory:",
|
|
2012
2000
|
}),
|
|
2013
2001
|
logger: new PinoLogger({
|
|
2014
2002
|
name: 'Mastra',
|
|
2015
2003
|
level: 'info',
|
|
2016
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
|
+
}),
|
|
2017
2019
|
});
|
|
2018
2020
|
`
|
|
2019
2021
|
);
|
|
@@ -2021,7 +2023,6 @@ export const mastra = new Mastra({
|
|
|
2021
2023
|
throw err;
|
|
2022
2024
|
}
|
|
2023
2025
|
};
|
|
2024
|
-
yoctoSpinner({ text: "Installing Mastra core dependencies\n" });
|
|
2025
2026
|
var getAPIKey = async (provider) => {
|
|
2026
2027
|
let key = "OPENAI_API_KEY";
|
|
2027
2028
|
switch (provider) {
|
|
@@ -2044,20 +2045,18 @@ var getAPIKey = async (provider) => {
|
|
|
2044
2045
|
return key;
|
|
2045
2046
|
}
|
|
2046
2047
|
};
|
|
2047
|
-
var writeAPIKey = async ({
|
|
2048
|
-
|
|
2049
|
-
apiKey = "your-api-key"
|
|
2050
|
-
}) => {
|
|
2048
|
+
var writeAPIKey = async ({ provider, apiKey }) => {
|
|
2049
|
+
const envFileName = apiKey ? ".env" : ".env.example";
|
|
2051
2050
|
const key = await getAPIKey(provider);
|
|
2052
|
-
const escapedKey =
|
|
2053
|
-
const escapedApiKey =
|
|
2054
|
-
await
|
|
2051
|
+
const escapedKey = shellQuote2.quote([key]);
|
|
2052
|
+
const escapedApiKey = shellQuote2.quote([apiKey ? apiKey : "your-api-key"]);
|
|
2053
|
+
await exec(`echo ${escapedKey}=${escapedApiKey} >> ${envFileName}`);
|
|
2055
2054
|
};
|
|
2056
2055
|
var createMastraDir = async (directory) => {
|
|
2057
2056
|
let dir = directory.trim().split("/").filter((item) => item !== "");
|
|
2058
2057
|
const dirPath = path3.join(process.cwd(), ...dir, "mastra");
|
|
2059
2058
|
try {
|
|
2060
|
-
await
|
|
2059
|
+
await fs4.access(dirPath);
|
|
2061
2060
|
return { ok: false };
|
|
2062
2061
|
} catch {
|
|
2063
2062
|
await fsExtra.ensureDir(dirPath);
|
|
@@ -2072,8 +2071,19 @@ var writeCodeSample = async (dirPath, component, llmProvider, importComponents)
|
|
|
2072
2071
|
throw err;
|
|
2073
2072
|
}
|
|
2074
2073
|
};
|
|
2075
|
-
var
|
|
2076
|
-
|
|
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
|
+
}
|
|
2077
2087
|
const mastraProject = await Ce(
|
|
2078
2088
|
{
|
|
2079
2089
|
directory: () => he({
|
|
@@ -2081,20 +2091,15 @@ var interactivePrompt = async () => {
|
|
|
2081
2091
|
placeholder: "src/",
|
|
2082
2092
|
defaultValue: "src/"
|
|
2083
2093
|
}),
|
|
2084
|
-
llmProvider: () => ve({
|
|
2085
|
-
message: "Select default provider:",
|
|
2086
|
-
options:
|
|
2087
|
-
{ value: "openai", label: "OpenAI", hint: "recommended" },
|
|
2088
|
-
{ value: "anthropic", label: "Anthropic" },
|
|
2089
|
-
{ value: "groq", label: "Groq" },
|
|
2090
|
-
{ value: "google", label: "Google" },
|
|
2091
|
-
{ value: "cerebras", label: "Cerebras" },
|
|
2092
|
-
{ value: "mistral", label: "Mistral" }
|
|
2093
|
-
]
|
|
2094
|
+
llmProvider: () => skip?.llmProvider ? void 0 : ve({
|
|
2095
|
+
message: "Select a default provider:",
|
|
2096
|
+
options: LLM_PROVIDERS
|
|
2094
2097
|
}),
|
|
2095
2098
|
llmApiKey: async ({ results: { llmProvider } }) => {
|
|
2099
|
+
if (skip?.llmApiKey) return void 0;
|
|
2100
|
+
const llmName = LLM_PROVIDERS.find((p6) => p6.value === llmProvider)?.label || "provider";
|
|
2096
2101
|
const keyChoice = await ve({
|
|
2097
|
-
message: `Enter your ${
|
|
2102
|
+
message: `Enter your ${llmName} API key?`,
|
|
2098
2103
|
options: [
|
|
2099
2104
|
{ value: "skip", label: "Skip for now", hint: "default" },
|
|
2100
2105
|
{ value: "enter", label: "Enter API key" }
|
|
@@ -2104,52 +2109,42 @@ var interactivePrompt = async () => {
|
|
|
2104
2109
|
if (keyChoice === "enter") {
|
|
2105
2110
|
return he({
|
|
2106
2111
|
message: "Enter your API key:",
|
|
2107
|
-
placeholder: "sk-..."
|
|
2112
|
+
placeholder: "sk-...",
|
|
2113
|
+
validate: (value) => {
|
|
2114
|
+
if (value.length === 0) return "API key cannot be empty";
|
|
2115
|
+
}
|
|
2108
2116
|
});
|
|
2109
2117
|
}
|
|
2110
2118
|
return void 0;
|
|
2111
2119
|
},
|
|
2112
2120
|
configureEditorWithDocsMCP: async () => {
|
|
2113
|
-
const windsurfIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`windsurf`);
|
|
2114
|
-
const cursorIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`cursor`);
|
|
2115
|
-
const vscodeIsAlreadyInstalled = await globalMCPIsAlreadyInstalled(`vscode`);
|
|
2116
2121
|
const editor = await ve({
|
|
2117
|
-
message: `Make your
|
|
2122
|
+
message: `Make your IDE into a Mastra expert? (Installs Mastra's MCP server)`,
|
|
2118
2123
|
options: [
|
|
2119
2124
|
{ value: "skip", label: "Skip for now", hint: "default" },
|
|
2120
2125
|
{
|
|
2121
2126
|
value: "cursor",
|
|
2122
|
-
label: "Cursor (project only)"
|
|
2123
|
-
hint: cursorIsAlreadyInstalled ? `Already installed globally` : void 0
|
|
2127
|
+
label: "Cursor (project only)"
|
|
2124
2128
|
},
|
|
2125
2129
|
{
|
|
2126
2130
|
value: "cursor-global",
|
|
2127
|
-
label: "Cursor (global, all projects)"
|
|
2128
|
-
hint: cursorIsAlreadyInstalled ? `Already installed` : void 0
|
|
2131
|
+
label: "Cursor (global, all projects)"
|
|
2129
2132
|
},
|
|
2130
2133
|
{
|
|
2131
2134
|
value: "windsurf",
|
|
2132
|
-
label: "Windsurf"
|
|
2133
|
-
hint: windsurfIsAlreadyInstalled ? `Already installed` : void 0
|
|
2135
|
+
label: "Windsurf"
|
|
2134
2136
|
},
|
|
2135
2137
|
{
|
|
2136
2138
|
value: "vscode",
|
|
2137
|
-
label: "VSCode"
|
|
2138
|
-
|
|
2139
|
+
label: "VSCode"
|
|
2140
|
+
},
|
|
2141
|
+
{
|
|
2142
|
+
value: "antigravity",
|
|
2143
|
+
label: "Antigravity"
|
|
2139
2144
|
}
|
|
2140
2145
|
]
|
|
2141
2146
|
});
|
|
2142
2147
|
if (editor === `skip`) return void 0;
|
|
2143
|
-
if (editor === `windsurf` && windsurfIsAlreadyInstalled) {
|
|
2144
|
-
M.message(`
|
|
2145
|
-
Windsurf is already installed, skipping.`);
|
|
2146
|
-
return void 0;
|
|
2147
|
-
}
|
|
2148
|
-
if (editor === `vscode` && vscodeIsAlreadyInstalled) {
|
|
2149
|
-
M.message(`
|
|
2150
|
-
VSCode is already installed, skipping.`);
|
|
2151
|
-
return void 0;
|
|
2152
|
-
}
|
|
2153
2148
|
if (editor === `cursor`) {
|
|
2154
2149
|
M.message(
|
|
2155
2150
|
`
|
|
@@ -2158,19 +2153,19 @@ Note: you will need to go into Cursor Settings -> MCP Settings and manually enab
|
|
|
2158
2153
|
);
|
|
2159
2154
|
}
|
|
2160
2155
|
if (editor === `cursor-global`) {
|
|
2161
|
-
const
|
|
2156
|
+
const confirm3 = await ve({
|
|
2162
2157
|
message: `Global install will add/update ${cursorGlobalMCPConfigPath} and make the Mastra docs MCP server available in all your Cursor projects. Continue?`,
|
|
2163
2158
|
options: [
|
|
2164
2159
|
{ value: "yes", label: "Yes, I understand" },
|
|
2165
2160
|
{ value: "skip", label: "No, skip for now" }
|
|
2166
2161
|
]
|
|
2167
2162
|
});
|
|
2168
|
-
if (
|
|
2163
|
+
if (confirm3 !== `yes`) {
|
|
2169
2164
|
return void 0;
|
|
2170
2165
|
}
|
|
2171
2166
|
}
|
|
2172
2167
|
if (editor === `windsurf`) {
|
|
2173
|
-
const
|
|
2168
|
+
const confirm3 = await ve({
|
|
2174
2169
|
message: `Windsurf only supports a global MCP config (at ${windsurfGlobalMCPConfigPath}) is it ok to add/update that global config?
|
|
2175
2170
|
This means the Mastra docs MCP server will be available in all your Windsurf projects.`,
|
|
2176
2171
|
options: [
|
|
@@ -2178,11 +2173,31 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
2178
2173
|
{ value: "skip", label: "No, skip for now" }
|
|
2179
2174
|
]
|
|
2180
2175
|
});
|
|
2181
|
-
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`) {
|
|
2182
2190
|
return void 0;
|
|
2183
2191
|
}
|
|
2184
2192
|
}
|
|
2185
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
|
+
});
|
|
2186
2201
|
}
|
|
2187
2202
|
},
|
|
2188
2203
|
{
|
|
@@ -2194,17 +2209,245 @@ This means the Mastra docs MCP server will be available in all your Windsurf pro
|
|
|
2194
2209
|
);
|
|
2195
2210
|
return mastraProject;
|
|
2196
2211
|
};
|
|
2212
|
+
function getPackageManager() {
|
|
2213
|
+
const userAgent = process.env.npm_config_user_agent || "";
|
|
2214
|
+
const execPath = process.env.npm_execpath || "";
|
|
2215
|
+
if (userAgent.includes("bun")) {
|
|
2216
|
+
return "bun";
|
|
2217
|
+
}
|
|
2218
|
+
if (userAgent.includes("yarn")) {
|
|
2219
|
+
return "yarn";
|
|
2220
|
+
}
|
|
2221
|
+
if (userAgent.includes("pnpm")) {
|
|
2222
|
+
return "pnpm";
|
|
2223
|
+
}
|
|
2224
|
+
if (userAgent.includes("npm")) {
|
|
2225
|
+
return "npm";
|
|
2226
|
+
}
|
|
2227
|
+
if (execPath.includes("bun")) {
|
|
2228
|
+
return "bun";
|
|
2229
|
+
}
|
|
2230
|
+
if (execPath.includes("yarn")) {
|
|
2231
|
+
return "yarn";
|
|
2232
|
+
}
|
|
2233
|
+
if (execPath.includes("pnpm")) {
|
|
2234
|
+
return "pnpm";
|
|
2235
|
+
}
|
|
2236
|
+
if (execPath.includes("npm")) {
|
|
2237
|
+
return "npm";
|
|
2238
|
+
}
|
|
2239
|
+
return "npm";
|
|
2240
|
+
}
|
|
2241
|
+
async function gitInit({ cwd }) {
|
|
2242
|
+
await execa("git", ["init"], { cwd, stdio: "ignore" });
|
|
2243
|
+
await execa("git", ["add", "-A"], { cwd, stdio: "ignore" });
|
|
2244
|
+
await execa(
|
|
2245
|
+
"git",
|
|
2246
|
+
[
|
|
2247
|
+
"commit",
|
|
2248
|
+
"-m",
|
|
2249
|
+
'"Initial commit from Mastra"',
|
|
2250
|
+
'--author="dane-ai-mastra[bot] <dane-ai-mastra[bot]@users.noreply.github.com>"'
|
|
2251
|
+
],
|
|
2252
|
+
{ cwd, stdio: "ignore" }
|
|
2253
|
+
);
|
|
2254
|
+
}
|
|
2255
|
+
var logger = createLogger(false);
|
|
2256
|
+
function createLogger(debug = false) {
|
|
2257
|
+
return new PinoLogger({
|
|
2258
|
+
name: "Mastra CLI",
|
|
2259
|
+
level: debug ? "debug" : "info"
|
|
2260
|
+
});
|
|
2261
|
+
}
|
|
2262
|
+
var exec2 = util.promisify(child_process.exec);
|
|
2263
|
+
async function cloneTemplate(options) {
|
|
2264
|
+
const { template, projectName, targetDir, branch, llmProvider } = options;
|
|
2265
|
+
const projectPath = targetDir ? path3.resolve(targetDir, projectName) : path3.resolve(projectName);
|
|
2266
|
+
const spinner4 = yoctoSpinner({ text: `Cloning template "${template.title}"...` }).start();
|
|
2267
|
+
try {
|
|
2268
|
+
if (await directoryExists(projectPath)) {
|
|
2269
|
+
spinner4.error(`Directory ${projectName} already exists`);
|
|
2270
|
+
throw new Error(`Directory ${projectName} already exists`);
|
|
2271
|
+
}
|
|
2272
|
+
await cloneRepositoryWithoutGit(template.githubUrl, projectPath, branch);
|
|
2273
|
+
await updatePackageJson(projectPath, projectName);
|
|
2274
|
+
const envExamplePath = path3.join(projectPath, ".env.example");
|
|
2275
|
+
if (await fileExists(envExamplePath)) {
|
|
2276
|
+
const envPath = path3.join(projectPath, ".env");
|
|
2277
|
+
await fs4.copyFile(envExamplePath, envPath);
|
|
2278
|
+
if (llmProvider) {
|
|
2279
|
+
await updateEnvFile(envPath, llmProvider);
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
spinner4.success(`Template "${template.title}" cloned successfully to ${projectName}`);
|
|
2283
|
+
return projectPath;
|
|
2284
|
+
} catch (error) {
|
|
2285
|
+
spinner4.error(`Failed to clone template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2286
|
+
throw error;
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
async function directoryExists(dirPath) {
|
|
2290
|
+
try {
|
|
2291
|
+
const stat = await fs4.stat(dirPath);
|
|
2292
|
+
return stat.isDirectory();
|
|
2293
|
+
} catch {
|
|
2294
|
+
return false;
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
async function fileExists(filePath) {
|
|
2298
|
+
try {
|
|
2299
|
+
const stat = await fs4.stat(filePath);
|
|
2300
|
+
return stat.isFile();
|
|
2301
|
+
} catch {
|
|
2302
|
+
return false;
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
async function cloneRepositoryWithoutGit(repoUrl, targetPath, branch) {
|
|
2306
|
+
await fs4.mkdir(targetPath, { recursive: true });
|
|
2307
|
+
try {
|
|
2308
|
+
const degitRepo = repoUrl.replace("https://github.com/", "");
|
|
2309
|
+
const degitRepoWithBranch = branch ? `${degitRepo}#${branch}` : degitRepo;
|
|
2310
|
+
const degitCommand = shellQuote2.quote(["npx", "degit", degitRepoWithBranch, targetPath]);
|
|
2311
|
+
await exec2(degitCommand, {
|
|
2312
|
+
cwd: process.cwd()
|
|
2313
|
+
});
|
|
2314
|
+
} catch {
|
|
2315
|
+
try {
|
|
2316
|
+
const gitArgs = ["git", "clone"];
|
|
2317
|
+
if (branch) {
|
|
2318
|
+
gitArgs.push("--branch", branch);
|
|
2319
|
+
}
|
|
2320
|
+
gitArgs.push(repoUrl, targetPath);
|
|
2321
|
+
const gitCommand = shellQuote2.quote(gitArgs);
|
|
2322
|
+
await exec2(gitCommand, {
|
|
2323
|
+
cwd: process.cwd()
|
|
2324
|
+
});
|
|
2325
|
+
const gitDir = path3.join(targetPath, ".git");
|
|
2326
|
+
if (await directoryExists(gitDir)) {
|
|
2327
|
+
await fs4.rm(gitDir, { recursive: true, force: true });
|
|
2328
|
+
}
|
|
2329
|
+
} catch (gitError) {
|
|
2330
|
+
throw new Error(`Failed to clone repository: ${gitError instanceof Error ? gitError.message : "Unknown error"}`);
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
async function updatePackageJson(projectPath, projectName) {
|
|
2335
|
+
const packageJsonPath = path3.join(projectPath, "package.json");
|
|
2336
|
+
try {
|
|
2337
|
+
const packageJsonContent = await fs4.readFile(packageJsonPath, "utf-8");
|
|
2338
|
+
const packageJson = JSON.parse(packageJsonContent);
|
|
2339
|
+
packageJson.name = projectName;
|
|
2340
|
+
await fs4.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf-8");
|
|
2341
|
+
} catch (error) {
|
|
2342
|
+
logger.warn(`Could not update package.json: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2343
|
+
}
|
|
2344
|
+
}
|
|
2345
|
+
async function updateEnvFile(envPath, llmProvider) {
|
|
2346
|
+
try {
|
|
2347
|
+
const envContent = await fs4.readFile(envPath, "utf-8");
|
|
2348
|
+
const modelString = getModelIdentifier(llmProvider);
|
|
2349
|
+
if (!modelString) {
|
|
2350
|
+
logger.warn(`Could not get model identifier for provider: ${llmProvider}`);
|
|
2351
|
+
return;
|
|
2352
|
+
}
|
|
2353
|
+
const modelValue = modelString.replace(/'/g, "");
|
|
2354
|
+
const updatedContent = envContent.replace(/^MODEL=.*/m, `MODEL=${modelValue}`);
|
|
2355
|
+
await fs4.writeFile(envPath, updatedContent, "utf-8");
|
|
2356
|
+
logger.info(`Updated MODEL in .env to ${modelValue}`);
|
|
2357
|
+
} catch (error) {
|
|
2358
|
+
logger.warn(`Could not update .env file: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
async function installDependencies(projectPath, packageManager) {
|
|
2362
|
+
const spinner4 = yoctoSpinner({ text: "Installing dependencies..." }).start();
|
|
2363
|
+
try {
|
|
2364
|
+
const pm = packageManager || getPackageManager();
|
|
2365
|
+
const installCommand = shellQuote2.quote([pm, "install"]);
|
|
2366
|
+
await exec2(installCommand, {
|
|
2367
|
+
cwd: projectPath
|
|
2368
|
+
});
|
|
2369
|
+
spinner4.success("Dependencies installed successfully");
|
|
2370
|
+
} catch (error) {
|
|
2371
|
+
spinner4.error(`Failed to install dependencies: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2372
|
+
throw error;
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
var TEMPLATES_API_URL = process.env.MASTRA_TEMPLATES_API_URL || "https://mastra.ai/api/templates.json";
|
|
2376
|
+
async function loadTemplates() {
|
|
2377
|
+
try {
|
|
2378
|
+
const response = await fetch(TEMPLATES_API_URL);
|
|
2379
|
+
if (!response.ok) {
|
|
2380
|
+
throw new Error(`Failed to fetch templates: ${response.statusText}`);
|
|
2381
|
+
}
|
|
2382
|
+
const templates = await response.json();
|
|
2383
|
+
return templates;
|
|
2384
|
+
} catch (error) {
|
|
2385
|
+
console.error("Error loading templates:", error);
|
|
2386
|
+
throw new Error("Failed to load templates. Please check your internet connection and try again.");
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
2389
|
+
function pluralize(count, singular, plural) {
|
|
2390
|
+
return count === 1 ? singular : plural || `${singular}s`;
|
|
2391
|
+
}
|
|
2392
|
+
async function selectTemplate(templates) {
|
|
2393
|
+
const choices = templates.map((template) => {
|
|
2394
|
+
const parts = [];
|
|
2395
|
+
if (template.agents?.length) {
|
|
2396
|
+
parts.push(`${template.agents.length} ${pluralize(template.agents.length, "agent")}`);
|
|
2397
|
+
}
|
|
2398
|
+
if (template.tools?.length) {
|
|
2399
|
+
parts.push(`${template.tools.length} ${pluralize(template.tools.length, "tool")}`);
|
|
2400
|
+
}
|
|
2401
|
+
if (template.workflows?.length) {
|
|
2402
|
+
parts.push(`${template.workflows.length} ${pluralize(template.workflows.length, "workflow")}`);
|
|
2403
|
+
}
|
|
2404
|
+
if (template.mcp?.length) {
|
|
2405
|
+
parts.push(`${template.mcp.length} ${pluralize(template.mcp.length, "MCP server")}`);
|
|
2406
|
+
}
|
|
2407
|
+
if (template.networks?.length) {
|
|
2408
|
+
parts.push(`${template.networks.length} ${pluralize(template.networks.length, "agent network")}`);
|
|
2409
|
+
}
|
|
2410
|
+
return {
|
|
2411
|
+
value: template,
|
|
2412
|
+
label: template.title,
|
|
2413
|
+
hint: parts.join(", ") || "Template components"
|
|
2414
|
+
};
|
|
2415
|
+
});
|
|
2416
|
+
const selected = await ve({
|
|
2417
|
+
message: "Select a template:",
|
|
2418
|
+
options: choices
|
|
2419
|
+
});
|
|
2420
|
+
if (pD(selected)) {
|
|
2421
|
+
return null;
|
|
2422
|
+
}
|
|
2423
|
+
return selected;
|
|
2424
|
+
}
|
|
2425
|
+
function findTemplateByName(templates, templateName) {
|
|
2426
|
+
let template = templates.find((t) => t.slug === templateName);
|
|
2427
|
+
if (template) return template;
|
|
2428
|
+
const slugWithPrefix = `template-${templateName}`;
|
|
2429
|
+
template = templates.find((t) => t.slug === slugWithPrefix);
|
|
2430
|
+
if (template) return template;
|
|
2431
|
+
template = templates.find((t) => t.title.toLowerCase() === templateName.toLowerCase());
|
|
2432
|
+
if (template) return template;
|
|
2433
|
+
return null;
|
|
2434
|
+
}
|
|
2435
|
+
function getDefaultProjectName(template) {
|
|
2436
|
+
return template.slug.replace(/^template-/, "");
|
|
2437
|
+
}
|
|
2197
2438
|
var s = Y();
|
|
2198
|
-
var exec3 = util.promisify(child_process.exec);
|
|
2199
2439
|
var init = async ({
|
|
2200
|
-
directory,
|
|
2201
|
-
addExample = false,
|
|
2440
|
+
directory = "src/",
|
|
2202
2441
|
components,
|
|
2203
2442
|
llmProvider = "openai",
|
|
2204
2443
|
llmApiKey,
|
|
2205
|
-
|
|
2444
|
+
addExample = false,
|
|
2445
|
+
configureEditorWithDocsMCP,
|
|
2446
|
+
versionTag,
|
|
2447
|
+
initGit = false
|
|
2206
2448
|
}) => {
|
|
2207
2449
|
s.start("Initializing Mastra");
|
|
2450
|
+
const packageVersionTag = versionTag ? `@${versionTag}` : "";
|
|
2208
2451
|
try {
|
|
2209
2452
|
const result = await createMastraDir(directory);
|
|
2210
2453
|
if (!result.ok) {
|
|
@@ -2217,7 +2460,8 @@ var init = async ({
|
|
|
2217
2460
|
dirPath,
|
|
2218
2461
|
addExample,
|
|
2219
2462
|
addWorkflow: components.includes("workflows"),
|
|
2220
|
-
addAgent: components.includes("agents")
|
|
2463
|
+
addAgent: components.includes("agents"),
|
|
2464
|
+
addScorers: components.includes("scorers")
|
|
2221
2465
|
}),
|
|
2222
2466
|
...components.map((component) => createComponentsDir(dirPath, component)),
|
|
2223
2467
|
writeAPIKey({ provider: llmProvider, apiKey: llmApiKey })
|
|
@@ -2231,31 +2475,44 @@ var init = async ({
|
|
|
2231
2475
|
const depService = new DepsService();
|
|
2232
2476
|
const needsLibsql = await depService.checkDependencies(["@mastra/libsql"]) !== `ok`;
|
|
2233
2477
|
if (needsLibsql) {
|
|
2234
|
-
await depService.installPackages([
|
|
2478
|
+
await depService.installPackages([`@mastra/libsql${packageVersionTag}`]);
|
|
2235
2479
|
}
|
|
2236
2480
|
const needsMemory = components.includes(`agents`) && await depService.checkDependencies(["@mastra/memory"]) !== `ok`;
|
|
2237
2481
|
if (needsMemory) {
|
|
2238
|
-
await depService.installPackages([
|
|
2482
|
+
await depService.installPackages([`@mastra/memory${packageVersionTag}`]);
|
|
2239
2483
|
}
|
|
2240
2484
|
const needsLoggers = await depService.checkDependencies(["@mastra/loggers"]) !== `ok`;
|
|
2241
2485
|
if (needsLoggers) {
|
|
2242
|
-
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}`]);
|
|
2243
2495
|
}
|
|
2244
2496
|
}
|
|
2245
2497
|
const key = await getAPIKey(llmProvider || "openai");
|
|
2246
|
-
const aiSdkPackage = getAISDKPackage(llmProvider);
|
|
2247
|
-
const aiSdkPackageVersion = getAISDKPackageVersion(llmProvider);
|
|
2248
|
-
const depsService = new DepsService();
|
|
2249
|
-
const pm = depsService.packageManager;
|
|
2250
|
-
const installCommand = getPackageManagerAddCommand(pm);
|
|
2251
|
-
await exec3(`${pm} ${installCommand} ${aiSdkPackage}@${aiSdkPackageVersion}`);
|
|
2252
2498
|
if (configureEditorWithDocsMCP) {
|
|
2253
2499
|
await installMastraDocsMCPServer({
|
|
2254
2500
|
editor: configureEditorWithDocsMCP,
|
|
2255
|
-
directory: process.cwd()
|
|
2501
|
+
directory: process.cwd(),
|
|
2502
|
+
versionTag
|
|
2256
2503
|
});
|
|
2257
2504
|
}
|
|
2258
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
|
+
}
|
|
2259
2516
|
if (!llmApiKey) {
|
|
2260
2517
|
Me(`
|
|
2261
2518
|
${color2.green("Mastra initialized successfully!")}
|
|
@@ -2275,10 +2532,10 @@ var init = async ({
|
|
|
2275
2532
|
return { success: false };
|
|
2276
2533
|
}
|
|
2277
2534
|
};
|
|
2278
|
-
var
|
|
2535
|
+
var exec3 = util.promisify(child_process.exec);
|
|
2279
2536
|
var execWithTimeout = async (command, timeoutMs) => {
|
|
2280
2537
|
try {
|
|
2281
|
-
const promise =
|
|
2538
|
+
const promise = exec3(command, { killSignal: "SIGTERM" });
|
|
2282
2539
|
if (!timeoutMs) {
|
|
2283
2540
|
return await promise;
|
|
2284
2541
|
}
|
|
@@ -2301,6 +2558,68 @@ var execWithTimeout = async (command, timeoutMs) => {
|
|
|
2301
2558
|
throw error;
|
|
2302
2559
|
}
|
|
2303
2560
|
};
|
|
2561
|
+
async function getInitCommand(pm) {
|
|
2562
|
+
switch (pm) {
|
|
2563
|
+
case "npm":
|
|
2564
|
+
return "npm init -y";
|
|
2565
|
+
case "pnpm":
|
|
2566
|
+
return "pnpm init";
|
|
2567
|
+
case "yarn":
|
|
2568
|
+
return "yarn init -y";
|
|
2569
|
+
case "bun":
|
|
2570
|
+
return "bun init -y";
|
|
2571
|
+
default:
|
|
2572
|
+
return "npm init -y";
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
async function initializePackageJson(pm) {
|
|
2576
|
+
const initCommand = await getInitCommand(pm);
|
|
2577
|
+
await exec3(initCommand);
|
|
2578
|
+
const packageJsonPath = path3.join(process.cwd(), "package.json");
|
|
2579
|
+
const packageJson = JSON.parse(await fs4.readFile(packageJsonPath, "utf-8"));
|
|
2580
|
+
packageJson.type = "module";
|
|
2581
|
+
packageJson.engines = {
|
|
2582
|
+
...packageJson.engines,
|
|
2583
|
+
node: ">=22.13.0"
|
|
2584
|
+
};
|
|
2585
|
+
await fs4.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
2586
|
+
}
|
|
2587
|
+
var writeReadmeFile = async ({ dirPath, projectName }) => {
|
|
2588
|
+
const packageManager = getPackageManager();
|
|
2589
|
+
const readmePath = path3.join(dirPath, "README.md");
|
|
2590
|
+
const content = `# ${projectName}
|
|
2591
|
+
|
|
2592
|
+
Welcome to your new [Mastra](https://mastra.ai/) project! We're excited to see what you'll build.
|
|
2593
|
+
|
|
2594
|
+
## Getting Started
|
|
2595
|
+
|
|
2596
|
+
Start the development server:
|
|
2597
|
+
|
|
2598
|
+
\`\`\`shell
|
|
2599
|
+
${packageManager} run dev
|
|
2600
|
+
\`\`\`
|
|
2601
|
+
|
|
2602
|
+
Open [http://localhost:4111](http://localhost:4111) in your browser to access [Mastra Studio](https://mastra.ai/docs/getting-started/studio). It provides an interactive UI for building and testing your agents, along with a REST API that exposes your Mastra application as a local service. This lets you start building without worrying about integration right away.
|
|
2603
|
+
|
|
2604
|
+
You can start editing files inside the \`src/mastra\` directory. The development server will automatically reload whenever you make changes.
|
|
2605
|
+
|
|
2606
|
+
## Learn more
|
|
2607
|
+
|
|
2608
|
+
To learn more about Mastra, visit our [documentation](https://mastra.ai/docs/). Your bootstrapped project includes example code for [agents](https://mastra.ai/docs/agents/overview), [tools](https://mastra.ai/docs/agents/using-tools), [workflows](https://mastra.ai/docs/workflows/overview), [scorers](https://mastra.ai/docs/evals/overview), and [observability](https://mastra.ai/docs/observability/overview).
|
|
2609
|
+
|
|
2610
|
+
If you're new to AI agents, check out our [course](https://mastra.ai/course) and [YouTube videos](https://youtube.com/@mastra-ai). You can also join our [Discord](https://discord.gg/BTYqqHKUrf) community to get help and share your projects.
|
|
2611
|
+
|
|
2612
|
+
## Deploy on Mastra Cloud
|
|
2613
|
+
|
|
2614
|
+
[Mastra Cloud](https://cloud.mastra.ai/) gives you a serverless agent environment with atomic deployments. Access your agents from anywhere and monitor performance. Make sure they don't go off the rails with evals and tracing.
|
|
2615
|
+
|
|
2616
|
+
Check out the [deployment guide](https://mastra.ai/docs/deployment/overview) for more details.`;
|
|
2617
|
+
const formattedContent = await prettier.format(content, {
|
|
2618
|
+
parser: "markdown",
|
|
2619
|
+
singleQuote: true
|
|
2620
|
+
});
|
|
2621
|
+
await fs4.writeFile(readmePath, formattedContent);
|
|
2622
|
+
};
|
|
2304
2623
|
async function installMastraDependency(pm, dependency, versionTag, isDev, timeout) {
|
|
2305
2624
|
let installCommand = getPackageManagerAddCommand(pm);
|
|
2306
2625
|
if (isDev) {
|
|
@@ -2326,23 +2645,42 @@ async function installMastraDependency(pm, dependency, versionTag, isDev, timeou
|
|
|
2326
2645
|
var createMastraProject = async ({
|
|
2327
2646
|
projectName: name,
|
|
2328
2647
|
createVersionTag,
|
|
2329
|
-
timeout
|
|
2648
|
+
timeout,
|
|
2649
|
+
llmProvider,
|
|
2650
|
+
llmApiKey,
|
|
2651
|
+
needsInteractive
|
|
2330
2652
|
}) => {
|
|
2331
2653
|
Ie(color2.inverse(" Mastra Create "));
|
|
2332
2654
|
const projectName = name ?? await he({
|
|
2333
2655
|
message: "What do you want to name your project?",
|
|
2334
2656
|
placeholder: "my-mastra-app",
|
|
2335
|
-
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
|
+
}
|
|
2336
2664
|
});
|
|
2337
2665
|
if (pD(projectName)) {
|
|
2338
2666
|
xe("Operation cancelled");
|
|
2339
2667
|
process.exit(0);
|
|
2340
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
|
+
}
|
|
2341
2676
|
const s2 = Y();
|
|
2677
|
+
const originalCwd = process.cwd();
|
|
2678
|
+
let projectPath = null;
|
|
2342
2679
|
try {
|
|
2343
2680
|
s2.start("Creating project");
|
|
2344
2681
|
try {
|
|
2345
|
-
await
|
|
2682
|
+
await fs4.mkdir(projectName);
|
|
2683
|
+
projectPath = path3.resolve(originalCwd, projectName);
|
|
2346
2684
|
} catch (error) {
|
|
2347
2685
|
if (error instanceof Error && "code" in error && error.code === "EEXIST") {
|
|
2348
2686
|
s2.stop(`A directory named "${projectName}" already exists. Please choose a different name.`);
|
|
@@ -2357,15 +2695,14 @@ var createMastraProject = async ({
|
|
|
2357
2695
|
const installCommand = getPackageManagerAddCommand(pm);
|
|
2358
2696
|
s2.message("Initializing project structure");
|
|
2359
2697
|
try {
|
|
2360
|
-
await
|
|
2361
|
-
await exec4(`npm pkg set type="module"`);
|
|
2362
|
-
await exec4(`npm pkg set engines.node=">=20.9.0"`);
|
|
2698
|
+
await initializePackageJson(pm);
|
|
2363
2699
|
const depsService = new DepsService();
|
|
2364
2700
|
await depsService.addScriptsToPackageJson({
|
|
2365
2701
|
dev: "mastra dev",
|
|
2366
2702
|
build: "mastra build",
|
|
2367
2703
|
start: "mastra start"
|
|
2368
2704
|
});
|
|
2705
|
+
await writeReadmeFile({ dirPath: process.cwd(), projectName });
|
|
2369
2706
|
} catch (error) {
|
|
2370
2707
|
throw new Error(
|
|
2371
2708
|
`Failed to initialize project structure: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
@@ -2374,9 +2711,9 @@ var createMastraProject = async ({
|
|
|
2374
2711
|
s2.stop("Project structure created");
|
|
2375
2712
|
s2.start(`Installing ${pm} dependencies`);
|
|
2376
2713
|
try {
|
|
2377
|
-
await
|
|
2378
|
-
await
|
|
2379
|
-
await
|
|
2714
|
+
await exec3(`${pm} ${installCommand} zod@^4`);
|
|
2715
|
+
await exec3(`${pm} ${installCommand} -D typescript @types/node`);
|
|
2716
|
+
await exec3(`echo '{
|
|
2380
2717
|
"compilerOptions": {
|
|
2381
2718
|
"target": "ES2022",
|
|
2382
2719
|
"module": "ES2022",
|
|
@@ -2398,15 +2735,15 @@ var createMastraProject = async ({
|
|
|
2398
2735
|
);
|
|
2399
2736
|
}
|
|
2400
2737
|
s2.stop(`${pm} dependencies installed`);
|
|
2401
|
-
s2.start("Installing
|
|
2738
|
+
s2.start("Installing Mastra CLI");
|
|
2402
2739
|
const versionTag = createVersionTag ? `@${createVersionTag}` : "@latest";
|
|
2403
2740
|
try {
|
|
2404
2741
|
await installMastraDependency(pm, "mastra", versionTag, true, timeout);
|
|
2405
2742
|
} catch (error) {
|
|
2406
2743
|
throw new Error(`Failed to install Mastra CLI: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2407
2744
|
}
|
|
2408
|
-
s2.stop("
|
|
2409
|
-
s2.start("Installing dependencies");
|
|
2745
|
+
s2.stop("Mastra CLI installed");
|
|
2746
|
+
s2.start("Installing Mastra dependencies");
|
|
2410
2747
|
try {
|
|
2411
2748
|
await installMastraDependency(pm, "@mastra/core", versionTag, false, timeout);
|
|
2412
2749
|
await installMastraDependency(pm, "@mastra/libsql", versionTag, false, timeout);
|
|
@@ -2419,58 +2756,80 @@ var createMastraProject = async ({
|
|
|
2419
2756
|
s2.stop("Mastra dependencies installed");
|
|
2420
2757
|
s2.start("Adding .gitignore");
|
|
2421
2758
|
try {
|
|
2422
|
-
await
|
|
2423
|
-
await
|
|
2424
|
-
await
|
|
2425
|
-
await
|
|
2426
|
-
await
|
|
2427
|
-
await
|
|
2428
|
-
await
|
|
2429
|
-
await
|
|
2759
|
+
await exec3(`echo output.txt >> .gitignore`);
|
|
2760
|
+
await exec3(`echo node_modules >> .gitignore`);
|
|
2761
|
+
await exec3(`echo dist >> .gitignore`);
|
|
2762
|
+
await exec3(`echo .mastra >> .gitignore`);
|
|
2763
|
+
await exec3(`echo .env.development >> .gitignore`);
|
|
2764
|
+
await exec3(`echo .env >> .gitignore`);
|
|
2765
|
+
await exec3(`echo *.db >> .gitignore`);
|
|
2766
|
+
await exec3(`echo *.db-* >> .gitignore`);
|
|
2430
2767
|
} catch (error) {
|
|
2431
2768
|
throw new Error(`Failed to create .gitignore: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2432
2769
|
}
|
|
2433
2770
|
s2.stop(".gitignore added");
|
|
2434
2771
|
Se("Project created successfully");
|
|
2435
2772
|
console.info("");
|
|
2436
|
-
return { projectName };
|
|
2773
|
+
return { projectName, result };
|
|
2437
2774
|
} catch (error) {
|
|
2438
2775
|
s2.stop();
|
|
2439
2776
|
const errorMessage = error instanceof Error ? error.message : "An unexpected error occurred";
|
|
2440
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
|
+
}
|
|
2441
2788
|
process.exit(1);
|
|
2442
2789
|
}
|
|
2443
2790
|
};
|
|
2444
|
-
var
|
|
2445
|
-
|
|
2446
|
-
|
|
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
|
+
});
|
|
2447
2801
|
return;
|
|
2448
2802
|
}
|
|
2449
|
-
const
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
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
|
|
2453
2811
|
});
|
|
2454
|
-
const directory =
|
|
2455
|
-
if (
|
|
2456
|
-
const result = await interactivePrompt();
|
|
2812
|
+
const directory = args.directory || "src/";
|
|
2813
|
+
if (needsInteractive && result) {
|
|
2457
2814
|
await init({
|
|
2458
2815
|
...result,
|
|
2459
2816
|
llmApiKey: result?.llmApiKey,
|
|
2460
|
-
components: ["agents", "tools", "workflows"],
|
|
2461
|
-
addExample: true
|
|
2817
|
+
components: ["agents", "tools", "workflows", "scorers"],
|
|
2818
|
+
addExample: true,
|
|
2819
|
+
versionTag: args.createVersionTag
|
|
2462
2820
|
});
|
|
2463
2821
|
postCreate({ projectName });
|
|
2464
2822
|
return;
|
|
2465
2823
|
}
|
|
2466
|
-
const { components = [], llmProvider = "openai", addExample = false, llmApiKey } =
|
|
2824
|
+
const { components = [], llmProvider = "openai", addExample = false, llmApiKey } = args;
|
|
2467
2825
|
await init({
|
|
2468
2826
|
directory,
|
|
2469
2827
|
components,
|
|
2470
2828
|
llmProvider,
|
|
2471
2829
|
addExample,
|
|
2472
2830
|
llmApiKey,
|
|
2473
|
-
configureEditorWithDocsMCP:
|
|
2831
|
+
configureEditorWithDocsMCP: args.mcpServer,
|
|
2832
|
+
versionTag: args.createVersionTag
|
|
2474
2833
|
});
|
|
2475
2834
|
postCreate({ projectName });
|
|
2476
2835
|
};
|
|
@@ -2561,9 +2920,9 @@ async function createFromGitHubUrl(url) {
|
|
|
2561
2920
|
workflows: []
|
|
2562
2921
|
};
|
|
2563
2922
|
}
|
|
2564
|
-
async function createFromTemplate(
|
|
2923
|
+
async function createFromTemplate(args) {
|
|
2565
2924
|
let selectedTemplate;
|
|
2566
|
-
if (
|
|
2925
|
+
if (args.template === true) {
|
|
2567
2926
|
const templates = await loadTemplates();
|
|
2568
2927
|
const selected = await selectTemplate(templates);
|
|
2569
2928
|
if (!selected) {
|
|
@@ -2571,26 +2930,26 @@ async function createFromTemplate(args2) {
|
|
|
2571
2930
|
return;
|
|
2572
2931
|
}
|
|
2573
2932
|
selectedTemplate = selected;
|
|
2574
|
-
} else if (
|
|
2575
|
-
if (isGitHubUrl(
|
|
2576
|
-
const
|
|
2577
|
-
|
|
2578
|
-
const validation = await validateGitHubProject(
|
|
2933
|
+
} else if (args.template && typeof args.template === "string") {
|
|
2934
|
+
if (isGitHubUrl(args.template)) {
|
|
2935
|
+
const spinner4 = Y();
|
|
2936
|
+
spinner4.start("Validating GitHub repository...");
|
|
2937
|
+
const validation = await validateGitHubProject(args.template);
|
|
2579
2938
|
if (!validation.isValid) {
|
|
2580
|
-
|
|
2939
|
+
spinner4.stop("Validation failed");
|
|
2581
2940
|
M.error("This does not appear to be a valid Mastra project:");
|
|
2582
2941
|
validation.errors.forEach((error) => M.error(` - ${error}`));
|
|
2583
2942
|
throw new Error("Invalid Mastra project");
|
|
2584
2943
|
}
|
|
2585
|
-
|
|
2586
|
-
selectedTemplate = await createFromGitHubUrl(
|
|
2944
|
+
spinner4.stop("Valid Mastra project \u2713");
|
|
2945
|
+
selectedTemplate = await createFromGitHubUrl(args.template);
|
|
2587
2946
|
} else {
|
|
2588
2947
|
const templates = await loadTemplates();
|
|
2589
|
-
const found = findTemplateByName(templates,
|
|
2948
|
+
const found = findTemplateByName(templates, args.template);
|
|
2590
2949
|
if (!found) {
|
|
2591
|
-
M.error(`Template "${
|
|
2950
|
+
M.error(`Template "${args.template}" not found. Available templates:`);
|
|
2592
2951
|
templates.forEach((t) => M.info(` - ${t.title} (use: ${t.slug.replace("template-", "")})`));
|
|
2593
|
-
throw new Error(`Template "${
|
|
2952
|
+
throw new Error(`Template "${args.template}" not found`);
|
|
2594
2953
|
}
|
|
2595
2954
|
selectedTemplate = found;
|
|
2596
2955
|
}
|
|
@@ -2598,7 +2957,7 @@ async function createFromTemplate(args2) {
|
|
|
2598
2957
|
if (!selectedTemplate) {
|
|
2599
2958
|
throw new Error("No template selected");
|
|
2600
2959
|
}
|
|
2601
|
-
let projectName =
|
|
2960
|
+
let projectName = args.projectName;
|
|
2602
2961
|
if (!projectName) {
|
|
2603
2962
|
const defaultName = getDefaultProjectName(selectedTemplate);
|
|
2604
2963
|
const response = await he({
|
|
@@ -2612,19 +2971,61 @@ async function createFromTemplate(args2) {
|
|
|
2612
2971
|
}
|
|
2613
2972
|
projectName = response;
|
|
2614
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;
|
|
2615
2995
|
try {
|
|
2616
|
-
const analytics =
|
|
2996
|
+
const analytics = args.injectedAnalytics || getAnalytics();
|
|
2617
2997
|
if (analytics) {
|
|
2618
2998
|
analytics.trackEvent("cli_template_used", {
|
|
2619
2999
|
template_slug: selectedTemplate.slug,
|
|
2620
3000
|
template_title: selectedTemplate.title
|
|
2621
3001
|
});
|
|
3002
|
+
if (llmProvider) {
|
|
3003
|
+
analytics.trackEvent("cli_model_provider_selected", {
|
|
3004
|
+
provider: llmProvider,
|
|
3005
|
+
selection_method: args.llmProvider ? "cli_args" : "interactive"
|
|
3006
|
+
});
|
|
3007
|
+
}
|
|
2622
3008
|
}
|
|
2623
|
-
const
|
|
3009
|
+
const isBeta = version$1?.includes("beta") ?? false;
|
|
3010
|
+
const isMastraTemplate = selectedTemplate.githubUrl.includes("github.com/mastra-ai/");
|
|
3011
|
+
const branch = isBeta && isMastraTemplate ? "beta" : void 0;
|
|
3012
|
+
projectPath = await cloneTemplate({
|
|
2624
3013
|
template: selectedTemplate,
|
|
2625
|
-
projectName
|
|
3014
|
+
projectName,
|
|
3015
|
+
branch,
|
|
3016
|
+
llmProvider
|
|
2626
3017
|
});
|
|
2627
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
|
+
}
|
|
2628
3029
|
Me(`
|
|
2629
3030
|
${color2.green("Mastra template installed!")}
|
|
2630
3031
|
|
|
@@ -2633,6 +3034,17 @@ async function createFromTemplate(args2) {
|
|
|
2633
3034
|
`);
|
|
2634
3035
|
postCreate({ projectName });
|
|
2635
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
|
+
}
|
|
2636
3048
|
M.error(`Failed to create project from template: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2637
3049
|
throw error;
|
|
2638
3050
|
}
|
|
@@ -2679,7 +3091,7 @@ program.version(`${version}`, "-v, --version").description(`create-mastra ${vers
|
|
|
2679
3091
|
program.name("create-mastra").description("Create a new Mastra project").argument("[project-name]", "Directory name of the project").option(
|
|
2680
3092
|
"-p, --project-name <string>",
|
|
2681
3093
|
"Project name that will be used in package.json and as the project directory name."
|
|
2682
|
-
).option("--default", "Quick start with defaults(src, OpenAI, examples)").option("-c, --components <components>", "Comma-separated list of components (agents, tools, workflows)").option("-l, --llm <model-provider>", "Default model provider (openai, anthropic, groq, google, or cerebras)").option("-k, --llm-api-key <api-key>", "API key for the model provider").option("-e, --example", "Include example code").option("-n, --no-example", "Do not include example code").option("-t, --timeout [timeout]", "Configurable timeout for package installation, defaults to 60000 ms").option("-d, --dir <directory>", "Target directory for Mastra source code (default: src/)").option("-m, --mcp <mcp>", "MCP Server for code editor (cursor, cursor-global, windsurf, vscode)").option(
|
|
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(
|
|
2683
3095
|
"--template [template-name]",
|
|
2684
3096
|
"Create project from a template (use template name, public GitHub URL, or leave blank to select from list)"
|
|
2685
3097
|
).action(async (projectNameArg, args) => {
|
|
@@ -2687,7 +3099,7 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
|
|
|
2687
3099
|
const timeout = args?.timeout ? args?.timeout === true ? 6e4 : parseInt(args?.timeout, 10) : void 0;
|
|
2688
3100
|
if (args.default) {
|
|
2689
3101
|
await create({
|
|
2690
|
-
components: ["agents", "tools", "workflows"],
|
|
3102
|
+
components: ["agents", "tools", "workflows", "scorers"],
|
|
2691
3103
|
llmProvider: "openai",
|
|
2692
3104
|
addExample: true,
|
|
2693
3105
|
createVersionTag,
|
|
@@ -2703,7 +3115,7 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
|
|
|
2703
3115
|
components: args.components ? args.components.split(",") : [],
|
|
2704
3116
|
llmProvider: args.llm,
|
|
2705
3117
|
addExample: args.example,
|
|
2706
|
-
llmApiKey: args
|
|
3118
|
+
llmApiKey: args.llmApiKey,
|
|
2707
3119
|
createVersionTag,
|
|
2708
3120
|
timeout,
|
|
2709
3121
|
projectName,
|