create-mastra 0.17.0 → 0.17.1-alpha.1
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 +10 -0
- package/dist/index.js +140 -11
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# create-mastra
|
|
2
2
|
|
|
3
|
+
## 0.17.1-alpha.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Add scorers to the default weather agent in the create command. ([#9042](https://github.com/mastra-ai/mastra/pull/9042))
|
|
8
|
+
|
|
9
|
+
- Fix tool result in playground ([#9087](https://github.com/mastra-ai/mastra/pull/9087))
|
|
10
|
+
|
|
11
|
+
## 0.17.1-alpha.0
|
|
12
|
+
|
|
3
13
|
## 0.17.0
|
|
4
14
|
|
|
5
15
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -724,13 +724,18 @@ const format = (open, close) => {
|
|
|
724
724
|
// Handle nested colors.
|
|
725
725
|
|
|
726
726
|
// We could have done this, but it's too slow (as of Node.js 22).
|
|
727
|
-
// return openCode + string.replaceAll(closeCode, openCode) + closeCode;
|
|
727
|
+
// return openCode + string.replaceAll(closeCode, (close === 22 ? closeCode : '') + openCode) + closeCode;
|
|
728
728
|
|
|
729
729
|
let result = openCode;
|
|
730
730
|
let lastIndex = 0;
|
|
731
731
|
|
|
732
|
+
// SGR 22 resets both bold (1) and dim (2). When we encounter a nested
|
|
733
|
+
// close for styles that use 22, we need to re-open the outer style.
|
|
734
|
+
const reopenOnNestedClose = close === 22;
|
|
735
|
+
const replaceCode = (reopenOnNestedClose ? closeCode : '') + openCode;
|
|
736
|
+
|
|
732
737
|
while (index !== -1) {
|
|
733
|
-
result += string.slice(lastIndex, index) +
|
|
738
|
+
result += string.slice(lastIndex, index) + replaceCode;
|
|
734
739
|
lastIndex = index + closeCode.length;
|
|
735
740
|
index = string.indexOf(closeCode, lastIndex);
|
|
736
741
|
}
|
|
@@ -1492,7 +1497,7 @@ var getModelIdentifier = (llmProvider) => {
|
|
|
1492
1497
|
if (llmProvider === "openai") {
|
|
1493
1498
|
return `'openai/gpt-4o-mini'`;
|
|
1494
1499
|
} else if (llmProvider === "anthropic") {
|
|
1495
|
-
return `'anthropic/claude-
|
|
1500
|
+
return `'anthropic/claude-sonnet-4-5-20250929'`;
|
|
1496
1501
|
} else if (llmProvider === "groq") {
|
|
1497
1502
|
return `'groq/llama-3.3-70b-versatile'`;
|
|
1498
1503
|
} else if (llmProvider === "google") {
|
|
@@ -1503,7 +1508,7 @@ var getModelIdentifier = (llmProvider) => {
|
|
|
1503
1508
|
return `'mistral/mistral-medium-2508'`;
|
|
1504
1509
|
}
|
|
1505
1510
|
};
|
|
1506
|
-
async function writeAgentSample(llmProvider, destPath, addExampleTool) {
|
|
1511
|
+
async function writeAgentSample(llmProvider, destPath, addExampleTool, addScorers) {
|
|
1507
1512
|
const modelString = getModelIdentifier(llmProvider);
|
|
1508
1513
|
const instructions = `
|
|
1509
1514
|
You are a helpful weather assistant that provides accurate weather information and can help planning activities based on the weather.
|
|
@@ -1524,12 +1529,36 @@ import { Agent } from '@mastra/core/agent';
|
|
|
1524
1529
|
import { Memory } from '@mastra/memory';
|
|
1525
1530
|
import { LibSQLStore } from '@mastra/libsql';
|
|
1526
1531
|
${addExampleTool ? `import { weatherTool } from '../tools/weather-tool';` : ""}
|
|
1532
|
+
${addScorers ? `import { scorers } from '../scorers/weather-scorer';` : ""}
|
|
1527
1533
|
|
|
1528
1534
|
export const weatherAgent = new Agent({
|
|
1529
1535
|
name: 'Weather Agent',
|
|
1530
1536
|
instructions: \`${instructions}\`,
|
|
1531
1537
|
model: ${modelString},
|
|
1532
1538
|
${addExampleTool ? "tools: { weatherTool }," : ""}
|
|
1539
|
+
${addScorers ? `scorers: {
|
|
1540
|
+
toolCallAppropriateness: {
|
|
1541
|
+
scorer: scorers.toolCallAppropriatenessScorer,
|
|
1542
|
+
sampling: {
|
|
1543
|
+
type: 'ratio',
|
|
1544
|
+
rate: 1,
|
|
1545
|
+
},
|
|
1546
|
+
},
|
|
1547
|
+
completeness: {
|
|
1548
|
+
scorer: scorers.completenessScorer,
|
|
1549
|
+
sampling: {
|
|
1550
|
+
type: 'ratio',
|
|
1551
|
+
rate: 1,
|
|
1552
|
+
},
|
|
1553
|
+
},
|
|
1554
|
+
translation: {
|
|
1555
|
+
scorer: scorers.translationScorer,
|
|
1556
|
+
sampling: {
|
|
1557
|
+
type: 'ratio',
|
|
1558
|
+
rate: 1,
|
|
1559
|
+
},
|
|
1560
|
+
},
|
|
1561
|
+
},` : ""}
|
|
1533
1562
|
memory: new Memory({
|
|
1534
1563
|
storage: new LibSQLStore({
|
|
1535
1564
|
url: "file:../mastra.db", // path is relative to the .mastra/output directory
|
|
@@ -1741,14 +1770,106 @@ async function writeToolSample(destPath) {
|
|
|
1741
1770
|
const fileService = new FileService();
|
|
1742
1771
|
await fileService.copyStarterFile("tools.ts", destPath);
|
|
1743
1772
|
}
|
|
1773
|
+
async function writeScorersSample(destPath) {
|
|
1774
|
+
const content = `import { z } from 'zod';
|
|
1775
|
+
import { createToolCallAccuracyScorerCode } from '@mastra/evals/scorers/code';
|
|
1776
|
+
import { createCompletenessScorer } from '@mastra/evals/scorers/code';
|
|
1777
|
+
import { createScorer } from '@mastra/core/scores';
|
|
1778
|
+
|
|
1779
|
+
export const toolCallAppropriatenessScorer = createToolCallAccuracyScorerCode({
|
|
1780
|
+
expectedTool: 'weatherTool',
|
|
1781
|
+
strictMode: false,
|
|
1782
|
+
});
|
|
1783
|
+
|
|
1784
|
+
export const completenessScorer = createCompletenessScorer();
|
|
1785
|
+
|
|
1786
|
+
// Custom LLM-judged scorer: evaluates if non-English locations are translated appropriately
|
|
1787
|
+
export const translationScorer = createScorer({
|
|
1788
|
+
name: 'Translation Quality',
|
|
1789
|
+
description: 'Checks that non-English location names are translated and used correctly',
|
|
1790
|
+
type: 'agent',
|
|
1791
|
+
judge: {
|
|
1792
|
+
model: 'openai/gpt-4o-mini',
|
|
1793
|
+
instructions:
|
|
1794
|
+
'You are an expert evaluator of translation quality for geographic locations. ' +
|
|
1795
|
+
'Determine whether the user text mentions a non-English location and whether the assistant correctly uses an English translation of that location. ' +
|
|
1796
|
+
'Be lenient with transliteration differences and diacritics. ' +
|
|
1797
|
+
'Return only the structured JSON matching the provided schema.',
|
|
1798
|
+
},
|
|
1799
|
+
})
|
|
1800
|
+
.preprocess(({ run }) => {
|
|
1801
|
+
const userText = (run.input?.inputMessages?.[0]?.content as string) || '';
|
|
1802
|
+
const assistantText = (run.output?.[0]?.content as string) || '';
|
|
1803
|
+
return { userText, assistantText };
|
|
1804
|
+
})
|
|
1805
|
+
.analyze({
|
|
1806
|
+
description: 'Extract location names and detect language/translation adequacy',
|
|
1807
|
+
outputSchema: z.object({
|
|
1808
|
+
nonEnglish: z.boolean(),
|
|
1809
|
+
translated: z.boolean(),
|
|
1810
|
+
confidence: z.number().min(0).max(1).default(1),
|
|
1811
|
+
explanation: z.string().default(''),
|
|
1812
|
+
}),
|
|
1813
|
+
createPrompt: ({ results }) => \`
|
|
1814
|
+
You are evaluating if a weather assistant correctly handled translation of a non-English location.
|
|
1815
|
+
User text:
|
|
1816
|
+
"""
|
|
1817
|
+
\${results.preprocessStepResult.userText}
|
|
1818
|
+
"""
|
|
1819
|
+
Assistant response:
|
|
1820
|
+
"""
|
|
1821
|
+
\${results.preprocessStepResult.assistantText}
|
|
1822
|
+
"""
|
|
1823
|
+
Tasks:
|
|
1824
|
+
1) Identify if the user mentioned a location that appears non-English.
|
|
1825
|
+
2) If non-English, check whether the assistant used a correct English translation of that location in its response.
|
|
1826
|
+
3) Be lenient with transliteration differences (e.g., accents/diacritics).
|
|
1827
|
+
Return JSON with fields:
|
|
1828
|
+
{
|
|
1829
|
+
"nonEnglish": boolean,
|
|
1830
|
+
"translated": boolean,
|
|
1831
|
+
"confidence": number, // 0-1
|
|
1832
|
+
"explanation": string
|
|
1833
|
+
}
|
|
1834
|
+
\`,
|
|
1835
|
+
})
|
|
1836
|
+
.generateScore(({ results }) => {
|
|
1837
|
+
const r = (results as any)?.analyzeStepResult || {};
|
|
1838
|
+
if (!r.nonEnglish) return 1; // If not applicable, full credit
|
|
1839
|
+
if (r.translated) return Math.max(0, Math.min(1, 0.7 + 0.3 * (r.confidence ?? 1)));
|
|
1840
|
+
return 0; // Non-English but not translated
|
|
1841
|
+
})
|
|
1842
|
+
.generateReason(({ results, score }) => {
|
|
1843
|
+
const r = (results as any)?.analyzeStepResult || {};
|
|
1844
|
+
return \`Translation scoring: nonEnglish=\${r.nonEnglish ?? false}, translated=\${r.translated ?? false}, confidence=\${r.confidence ?? 0}. Score=\${score}. \${r.explanation ?? ''}\`;
|
|
1845
|
+
});
|
|
1846
|
+
|
|
1847
|
+
export const scorers = {
|
|
1848
|
+
toolCallAppropriatenessScorer,
|
|
1849
|
+
completenessScorer,
|
|
1850
|
+
translationScorer,
|
|
1851
|
+
};`;
|
|
1852
|
+
const formattedContent = await prettier.format(content, {
|
|
1853
|
+
parser: "typescript",
|
|
1854
|
+
singleQuote: true
|
|
1855
|
+
});
|
|
1856
|
+
await fs4.writeFile(destPath, formattedContent);
|
|
1857
|
+
}
|
|
1744
1858
|
async function writeCodeSampleForComponents(llmprovider, component, destPath, importComponents) {
|
|
1745
1859
|
switch (component) {
|
|
1746
1860
|
case "agents":
|
|
1747
|
-
return writeAgentSample(
|
|
1861
|
+
return writeAgentSample(
|
|
1862
|
+
llmprovider,
|
|
1863
|
+
destPath,
|
|
1864
|
+
importComponents.includes("tools"),
|
|
1865
|
+
importComponents.includes("scorers")
|
|
1866
|
+
);
|
|
1748
1867
|
case "tools":
|
|
1749
1868
|
return writeToolSample(destPath);
|
|
1750
1869
|
case "workflows":
|
|
1751
1870
|
return writeWorkflowSample(destPath);
|
|
1871
|
+
case "scorers":
|
|
1872
|
+
return writeScorersSample(destPath);
|
|
1752
1873
|
default:
|
|
1753
1874
|
return "";
|
|
1754
1875
|
}
|
|
@@ -1761,7 +1882,8 @@ var writeIndexFile = async ({
|
|
|
1761
1882
|
dirPath,
|
|
1762
1883
|
addAgent,
|
|
1763
1884
|
addExample,
|
|
1764
|
-
addWorkflow
|
|
1885
|
+
addWorkflow,
|
|
1886
|
+
addScorers
|
|
1765
1887
|
}) => {
|
|
1766
1888
|
const indexPath = dirPath + "/index.ts";
|
|
1767
1889
|
const destPath = path.join(indexPath);
|
|
@@ -1769,7 +1891,8 @@ var writeIndexFile = async ({
|
|
|
1769
1891
|
await fs4.writeFile(destPath, "");
|
|
1770
1892
|
const filteredExports = [
|
|
1771
1893
|
addWorkflow ? `workflows: { weatherWorkflow },` : "",
|
|
1772
|
-
addAgent ? `agents: { weatherAgent },` : ""
|
|
1894
|
+
addAgent ? `agents: { weatherAgent },` : "",
|
|
1895
|
+
addScorers ? `scorers: { toolCallAppropriatenessScorer, completenessScorer, translationScorer },` : ""
|
|
1773
1896
|
].filter(Boolean);
|
|
1774
1897
|
if (!addExample) {
|
|
1775
1898
|
await fs4.writeFile(
|
|
@@ -1790,6 +1913,7 @@ import { PinoLogger } from '@mastra/loggers';
|
|
|
1790
1913
|
import { LibSQLStore } from '@mastra/libsql';
|
|
1791
1914
|
${addWorkflow ? `import { weatherWorkflow } from './workflows/weather-workflow';` : ""}
|
|
1792
1915
|
${addAgent ? `import { weatherAgent } from './agents/weather-agent';` : ""}
|
|
1916
|
+
${addScorers ? `import { toolCallAppropriatenessScorer, completenessScorer, translationScorer } from './scorers/weather-scorer';` : ""}
|
|
1793
1917
|
|
|
1794
1918
|
export const mastra = new Mastra({
|
|
1795
1919
|
${filteredExports.join("\n ")}
|
|
@@ -2198,7 +2322,8 @@ var init = async ({
|
|
|
2198
2322
|
dirPath,
|
|
2199
2323
|
addExample,
|
|
2200
2324
|
addWorkflow: components.includes("workflows"),
|
|
2201
|
-
addAgent: components.includes("agents")
|
|
2325
|
+
addAgent: components.includes("agents"),
|
|
2326
|
+
addScorers: components.includes("scorers")
|
|
2202
2327
|
}),
|
|
2203
2328
|
...components.map((component) => createComponentsDir(dirPath, component)),
|
|
2204
2329
|
writeAPIKey({ provider: llmProvider, apiKey: llmApiKey })
|
|
@@ -2222,6 +2347,10 @@ var init = async ({
|
|
|
2222
2347
|
if (needsLoggers) {
|
|
2223
2348
|
await depService.installPackages(["@mastra/loggers"]);
|
|
2224
2349
|
}
|
|
2350
|
+
const needsEvals = components.includes(`scorers`) && await depService.checkDependencies(["@mastra/evals"]) !== `ok`;
|
|
2351
|
+
if (needsEvals) {
|
|
2352
|
+
await depService.installPackages(["@mastra/evals"]);
|
|
2353
|
+
}
|
|
2225
2354
|
}
|
|
2226
2355
|
const key = await getAPIKey(llmProvider || "openai");
|
|
2227
2356
|
if (configureEditorWithDocsMCP) {
|
|
@@ -2451,7 +2580,7 @@ var create = async (args2) => {
|
|
|
2451
2580
|
await init({
|
|
2452
2581
|
...result,
|
|
2453
2582
|
llmApiKey: result?.llmApiKey,
|
|
2454
|
-
components: ["agents", "tools", "workflows"],
|
|
2583
|
+
components: ["agents", "tools", "workflows", "scorers"],
|
|
2455
2584
|
addExample: true
|
|
2456
2585
|
});
|
|
2457
2586
|
postCreate({ projectName });
|
|
@@ -2673,7 +2802,7 @@ program.version(`${version}`, "-v, --version").description(`create-mastra ${vers
|
|
|
2673
2802
|
program.name("create-mastra").description("Create a new Mastra project").argument("[project-name]", "Directory name of the project").option(
|
|
2674
2803
|
"-p, --project-name <string>",
|
|
2675
2804
|
"Project name that will be used in package.json and as the project directory name."
|
|
2676
|
-
).option("--default", "Quick start with defaults (src, OpenAI, examples)").option("-c, --components <components>", "Comma-separated list of components (agents, tools, workflows)").option("-l, --llm <model-provider>", "Default model provider (openai, anthropic, groq, google, or cerebras)").option("-k, --llm-api-key <api-key>", "API key for the model provider").option("-e, --example", "Include example code").option("-n, --no-example", "Do not include example code").option("-t, --timeout [timeout]", "Configurable timeout for package installation, defaults to 60000 ms").option("-d, --dir <directory>", "Target directory for Mastra source code (default: src/)").option("-m, --mcp <mcp>", "MCP Server for code editor (cursor, cursor-global, windsurf, vscode)").option(
|
|
2805
|
+
).option("--default", "Quick start with defaults (src, OpenAI, examples)").option("-c, --components <components>", "Comma-separated list of components (agents, tools, workflows, scorers)").option("-l, --llm <model-provider>", "Default model provider (openai, anthropic, groq, google, or cerebras)").option("-k, --llm-api-key <api-key>", "API key for the model provider").option("-e, --example", "Include example code").option("-n, --no-example", "Do not include example code").option("-t, --timeout [timeout]", "Configurable timeout for package installation, defaults to 60000 ms").option("-d, --dir <directory>", "Target directory for Mastra source code (default: src/)").option("-m, --mcp <mcp>", "MCP Server for code editor (cursor, cursor-global, windsurf, vscode)").option(
|
|
2677
2806
|
"--template [template-name]",
|
|
2678
2807
|
"Create project from a template (use template name, public GitHub URL, or leave blank to select from list)"
|
|
2679
2808
|
).action(async (projectNameArg, args) => {
|
|
@@ -2681,7 +2810,7 @@ program.name("create-mastra").description("Create a new Mastra project").argumen
|
|
|
2681
2810
|
const timeout = args?.timeout ? args?.timeout === true ? 6e4 : parseInt(args?.timeout, 10) : void 0;
|
|
2682
2811
|
if (args.default) {
|
|
2683
2812
|
await create({
|
|
2684
|
-
components: ["agents", "tools", "workflows"],
|
|
2813
|
+
components: ["agents", "tools", "workflows", "scorers"],
|
|
2685
2814
|
llmProvider: "openai",
|
|
2686
2815
|
addExample: true,
|
|
2687
2816
|
createVersionTag,
|