create-mastra 0.17.1-alpha.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 CHANGED
@@ -1,5 +1,13 @@
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
+
3
11
  ## 0.17.1-alpha.0
4
12
 
5
13
  ## 0.17.0
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) + openCode;
738
+ result += string.slice(lastIndex, index) + replaceCode;
734
739
  lastIndex = index + closeCode.length;
735
740
  index = string.indexOf(closeCode, lastIndex);
736
741
  }
@@ -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(llmprovider, destPath, importComponents.includes("tools"));
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,