mastra 0.2.2-alpha.0 → 0.2.3-alpha.0

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.
@@ -14,6 +14,31 @@ import { fileURLToPath } from 'url';
14
14
  import { createLogger } from '@mastra/core/logger';
15
15
 
16
16
  // src/commands/create/create.ts
17
+
18
+ // src/commands/utils.ts
19
+ function getPackageManager() {
20
+ const userAgent = process.env.npm_config_user_agent || "";
21
+ const execPath = process.env.npm_execpath || "";
22
+ if (userAgent.includes("yarn")) {
23
+ return "yarn";
24
+ }
25
+ if (userAgent.includes("pnpm")) {
26
+ return "pnpm";
27
+ }
28
+ if (userAgent.includes("npm")) {
29
+ return "npm";
30
+ }
31
+ if (execPath.includes("yarn")) {
32
+ return "yarn";
33
+ }
34
+ if (execPath.includes("pnpm")) {
35
+ return "pnpm";
36
+ }
37
+ if (execPath.includes("npm")) {
38
+ return "npm";
39
+ }
40
+ return "npm";
41
+ }
17
42
  var DepsService = class {
18
43
  packageManager;
19
44
  constructor() {
@@ -238,7 +263,7 @@ var getAISDKPackage = (llmProvider) => {
238
263
  return "@ai-sdk/openai";
239
264
  }
240
265
  };
241
- async function writeAgentSample(llmProvider, destPath, addExampleTool) {
266
+ var getProviderImportAndModelItem = (llmProvider) => {
242
267
  let providerImport = "";
243
268
  let modelItem = "";
244
269
  if (llmProvider === "openai") {
@@ -251,6 +276,10 @@ async function writeAgentSample(llmProvider, destPath, addExampleTool) {
251
276
  providerImport = `import { groq } from '${getAISDKPackage(llmProvider)}';`;
252
277
  modelItem = `groq('llama3-groq-70b-8192-tool-use-preview')`;
253
278
  }
279
+ return { providerImport, modelItem };
280
+ };
281
+ async function writeAgentSample(llmProvider, destPath, addExampleTool) {
282
+ const { providerImport, modelItem } = getProviderImportAndModelItem(llmProvider);
254
283
  const instructions = `
255
284
  You are a helpful weather assistant that provides accurate weather information.
256
285
 
@@ -281,9 +310,196 @@ export const weatherAgent = new Agent({
281
310
  await fs4.writeFile(destPath, "");
282
311
  await fs4.writeFile(destPath, formattedContent);
283
312
  }
284
- async function writeWorkflowSample(destPath) {
285
- const fileService = new FileService();
286
- await fileService.copyStarterFile("workflow.ts", destPath);
313
+ async function writeWorkflowSample(destPath, llmProvider) {
314
+ const { providerImport, modelItem } = getProviderImportAndModelItem(llmProvider);
315
+ const content = `${providerImport}
316
+ import { Agent } from '@mastra/core/agent';
317
+ import { Step, Workflow } from '@mastra/core/workflows';
318
+ import { z } from 'zod';
319
+
320
+ const llm = ${modelItem};
321
+
322
+ const agent = new Agent({
323
+ name: 'Weather Agent',
324
+ model: llm,
325
+ instructions: \`
326
+ You are a local activities and travel expert who excels at weather-based planning. Analyze the weather data and provide practical activity recommendations.
327
+
328
+ For each day in the forecast, structure your response exactly as follows:
329
+
330
+ \u{1F4C5} [Day, Month Date, Year]
331
+ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
332
+
333
+ \u{1F321}\uFE0F WEATHER SUMMARY
334
+ \u2022 Conditions: [brief description]
335
+ \u2022 Temperature: [X\xB0C/Y\xB0F to A\xB0C/B\xB0F]
336
+ \u2022 Precipitation: [X% chance]
337
+
338
+ \u{1F305} MORNING ACTIVITIES
339
+ Outdoor:
340
+ \u2022 [Activity Name] - [Brief description including specific location/route]
341
+ Best timing: [specific time range]
342
+ Note: [relevant weather consideration]
343
+
344
+ \u{1F31E} AFTERNOON ACTIVITIES
345
+ Outdoor:
346
+ \u2022 [Activity Name] - [Brief description including specific location/route]
347
+ Best timing: [specific time range]
348
+ Note: [relevant weather consideration]
349
+
350
+ \u{1F3E0} INDOOR ALTERNATIVES
351
+ \u2022 [Activity Name] - [Brief description including specific venue]
352
+ Ideal for: [weather condition that would trigger this alternative]
353
+
354
+ \u26A0\uFE0F SPECIAL CONSIDERATIONS
355
+ \u2022 [Any relevant weather warnings, UV index, wind conditions, etc.]
356
+
357
+ Guidelines:
358
+ - Suggest 2-3 time-specific outdoor activities per day
359
+ - Include 1-2 indoor backup options
360
+ - For precipitation >50%, lead with indoor activities
361
+ - All activities must be specific to the location
362
+ - Include specific venues, trails, or locations
363
+ - Consider activity intensity based on temperature
364
+ - Keep descriptions concise but informative
365
+
366
+ Maintain this exact formatting for consistency, using the emoji and section headers as shown.
367
+ \`,
368
+ });
369
+
370
+ const fetchWeather = new Step({
371
+ id: 'fetch-weather',
372
+ description: 'Fetches weather forecast for a given city',
373
+ inputSchema: z.object({
374
+ city: z.string().describe('The city to get the weather for'),
375
+ }),
376
+ execute: async ({ context }) => {
377
+ const triggerData = context?.getStepPayload<{ city: string }>('trigger');
378
+
379
+ if (!triggerData) {
380
+ throw new Error('Trigger data not found');
381
+ }
382
+
383
+ const geocodingUrl = \`https://geocoding-api.open-meteo.com/v1/search?name=\${encodeURIComponent(triggerData.city)}&count=1\`;
384
+ const geocodingResponse = await fetch(geocodingUrl);
385
+ const geocodingData = (await geocodingResponse.json()) as {
386
+ results: { latitude: number; longitude: number; name: string }[];
387
+ };
388
+
389
+ if (!geocodingData.results?.[0]) {
390
+ throw new Error(\`Location '\${triggerData.city}' not found\`);
391
+ }
392
+
393
+ const { latitude, longitude, name } = geocodingData.results[0];
394
+
395
+ const weatherUrl = \`https://api.open-meteo.com/v1/forecast?latitude=\${latitude}&longitude=\${longitude}&daily=temperature_2m_max,temperature_2m_min,precipitation_probability_mean,weathercode&timezone=auto\`;
396
+ const response = await fetch(weatherUrl);
397
+ const data = (await response.json()) as {
398
+ daily: {
399
+ time: string[];
400
+ temperature_2m_max: number[];
401
+ temperature_2m_min: number[];
402
+ precipitation_probability_mean: number[];
403
+ weathercode: number[];
404
+ };
405
+ };
406
+
407
+ const forecast = data.daily.time.map((date: string, index: number) => ({
408
+ date,
409
+ maxTemp: data.daily.temperature_2m_max[index],
410
+ minTemp: data.daily.temperature_2m_min[index],
411
+ precipitationChance: data.daily.precipitation_probability_mean[index],
412
+ condition: getWeatherCondition(data.daily.weathercode[index]!),
413
+ location: name,
414
+ }));
415
+
416
+ return forecast;
417
+ },
418
+ });
419
+
420
+ const forecastSchema = z.array(
421
+ z.object({
422
+ date: z.string(),
423
+ maxTemp: z.number(),
424
+ minTemp: z.number(),
425
+ precipitationChance: z.number(),
426
+ condition: z.string(),
427
+ location: z.string(),
428
+ }),
429
+ );
430
+
431
+ const planActivities = new Step({
432
+ id: 'plan-activities',
433
+ description: 'Suggests activities based on weather conditions',
434
+ inputSchema: forecastSchema,
435
+ execute: async ({ context, mastra }) => {
436
+ const forecast = context?.getStepPayload<z.infer<typeof forecastSchema>>('fetch-weather');
437
+
438
+ if (!forecast || forecast.length === 0) {
439
+ throw new Error('Forecast data not found');
440
+ }
441
+
442
+ const prompt = \`Based on the following weather forecast for \${forecast[0]?.location}, suggest appropriate activities:
443
+ \${JSON.stringify(forecast, null, 2)}
444
+ \`;
445
+
446
+ const response = await agent.stream([
447
+ {
448
+ role: 'user',
449
+ content: prompt,
450
+ },
451
+ ]);
452
+
453
+ for await (const chunk of response.textStream) {
454
+ process.stdout.write(chunk);
455
+ }
456
+
457
+ return {
458
+ activities: response.text,
459
+ };
460
+ },
461
+ });
462
+
463
+ function getWeatherCondition(code: number): string {
464
+ const conditions: Record<number, string> = {
465
+ 0: 'Clear sky',
466
+ 1: 'Mainly clear',
467
+ 2: 'Partly cloudy',
468
+ 3: 'Overcast',
469
+ 45: 'Foggy',
470
+ 48: 'Depositing rime fog',
471
+ 51: 'Light drizzle',
472
+ 53: 'Moderate drizzle',
473
+ 55: 'Dense drizzle',
474
+ 61: 'Slight rain',
475
+ 63: 'Moderate rain',
476
+ 65: 'Heavy rain',
477
+ 71: 'Slight snow fall',
478
+ 73: 'Moderate snow fall',
479
+ 75: 'Heavy snow fall',
480
+ 95: 'Thunderstorm',
481
+ };
482
+ return conditions[code] || 'Unknown';
483
+ }
484
+
485
+ const weatherWorkflow = new Workflow({
486
+ name: 'weather-workflow',
487
+ triggerSchema: z.object({
488
+ city: z.string().describe('The city to get the weather for'),
489
+ }),
490
+ })
491
+ .step(fetchWeather)
492
+ .then(planActivities);
493
+
494
+ weatherWorkflow.commit();
495
+
496
+ export { weatherWorkflow };`;
497
+ const formattedContent = await prettier.format(content, {
498
+ parser: "typescript",
499
+ semi: true,
500
+ singleQuote: true
501
+ });
502
+ await fs4.writeFile(destPath, formattedContent);
287
503
  }
288
504
  async function writeToolSample(destPath) {
289
505
  const fileService = new FileService();
@@ -296,7 +512,7 @@ async function writeCodeSampleForComponents(llmprovider, component, destPath, im
296
512
  case "tools":
297
513
  return writeToolSample(destPath);
298
514
  case "workflows":
299
- return writeWorkflowSample(destPath);
515
+ return writeWorkflowSample(destPath, llmprovider);
300
516
  default:
301
517
  return "";
302
518
  }
@@ -538,7 +754,7 @@ var init = async ({
538
754
  }
539
755
  const key = await getAPIKey(llmProvider || "openai");
540
756
  const aiSdkPackage = getAISDKPackage(llmProvider);
541
- await exec2(`npm i ${aiSdkPackage}`);
757
+ await exec2(`${getPackageManager()} i ${aiSdkPackage}`);
542
758
  s.stop();
543
759
  if (!llmApiKey) {
544
760
  p.note(`
@@ -583,15 +799,6 @@ var execWithTimeout = async (command, timeoutMs = 18e4) => {
583
799
  throw error;
584
800
  }
585
801
  };
586
- function getPackageManager() {
587
- const userAgent = process.env.npm_config_user_agent || `npm`;
588
- if (userAgent.includes(`pnpm/`)) {
589
- return `pnpm`;
590
- } else if (userAgent.includes(`yarn/`)) {
591
- return `yarn`;
592
- }
593
- return `npm`;
594
- }
595
802
  var createMastraProject = async () => {
596
803
  p.intro(color2.inverse("Mastra Create"));
597
804
  const projectName = await p.text({
@@ -1 +1 @@
1
- export { create } from '../../chunk-NOF26LQY.js';
1
+ export { create } from '../../chunk-F6RK2UOG.js';
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #! /usr/bin/env node
2
2
  import { PosthogAnalytics } from './chunk-DHTLEROT.js';
3
3
  export { PosthogAnalytics } from './chunk-DHTLEROT.js';
4
- import { DepsService, create, checkPkgJson, checkAndInstallCoreDeps, interactivePrompt, init, logger, FileService as FileService$1 } from './chunk-NOF26LQY.js';
5
- export { create } from './chunk-NOF26LQY.js';
4
+ import { DepsService, create, checkPkgJson, checkAndInstallCoreDeps, interactivePrompt, init, logger, FileService as FileService$1 } from './chunk-F6RK2UOG.js';
5
+ export { create } from './chunk-F6RK2UOG.js';
6
6
  import { Command } from 'commander';
7
7
  import 'picocolors';
8
8
  import { join as join$1, dirname } from 'node:path';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mastra",
3
- "version": "0.2.2-alpha.0",
3
+ "version": "0.2.3-alpha.0",
4
4
  "license": "MIT",
5
5
  "description": "cli for mastra",
6
6
  "type": "module",
@@ -59,7 +59,6 @@
59
59
  "@mastra/core": "^0.2.1"
60
60
  },
61
61
  "devDependencies": {
62
- "@ai-sdk/openai": "^1.1.9",
63
62
  "@microsoft/api-extractor": "^7.49.2",
64
63
  "@types/express": "^5.0.0",
65
64
  "@types/fs-extra": "^11.0.4",
@@ -1,182 +0,0 @@
1
- import { openai } from '@ai-sdk/openai';
2
- import { Agent } from '@mastra/core/agent';
3
- import { Step, Workflow } from '@mastra/core/workflows';
4
- import { z } from 'zod';
5
-
6
- const llm = openai('gpt-4o');
7
-
8
- const agent = new Agent({
9
- name: 'Weather Agent',
10
- model: llm,
11
- instructions: `
12
- You are a local activities and travel expert who excels at weather-based planning. Analyze the weather data and provide practical activity recommendations.
13
-
14
- For each day in the forecast, structure your response exactly as follows:
15
-
16
- 📅 [Day, Month Date, Year]
17
- ═══════════════════════════
18
-
19
- 🌡️ WEATHER SUMMARY
20
- • Conditions: [brief description]
21
- • Temperature: [X°C/Y°F to A°C/B°F]
22
- • Precipitation: [X% chance]
23
-
24
- 🌅 MORNING ACTIVITIES
25
- Outdoor:
26
- • [Activity Name] - [Brief description including specific location/route]
27
- Best timing: [specific time range]
28
- Note: [relevant weather consideration]
29
-
30
- 🌞 AFTERNOON ACTIVITIES
31
- Outdoor:
32
- • [Activity Name] - [Brief description including specific location/route]
33
- Best timing: [specific time range]
34
- Note: [relevant weather consideration]
35
-
36
- 🏠 INDOOR ALTERNATIVES
37
- • [Activity Name] - [Brief description including specific venue]
38
- Ideal for: [weather condition that would trigger this alternative]
39
-
40
- ⚠️ SPECIAL CONSIDERATIONS
41
- • [Any relevant weather warnings, UV index, wind conditions, etc.]
42
-
43
- Guidelines:
44
- - Suggest 2-3 time-specific outdoor activities per day
45
- - Include 1-2 indoor backup options
46
- - For precipitation >50%, lead with indoor activities
47
- - All activities must be specific to the location
48
- - Include specific venues, trails, or locations
49
- - Consider activity intensity based on temperature
50
- - Keep descriptions concise but informative
51
-
52
- Maintain this exact formatting for consistency, using the emoji and section headers as shown.
53
- `,
54
- });
55
-
56
- const fetchWeather = new Step({
57
- id: 'fetch-weather',
58
- description: 'Fetches weather forecast for a given city',
59
- inputSchema: z.object({
60
- city: z.string().describe('The city to get the weather for'),
61
- }),
62
- execute: async ({ context }) => {
63
- const triggerData = context?.getStepPayload<{ city: string }>('trigger');
64
-
65
- if (!triggerData) {
66
- throw new Error('Trigger data not found');
67
- }
68
-
69
- const geocodingUrl = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(triggerData.city)}&count=1`;
70
- const geocodingResponse = await fetch(geocodingUrl);
71
- const geocodingData = (await geocodingResponse.json()) as {
72
- results: { latitude: number; longitude: number; name: string }[];
73
- };
74
-
75
- if (!geocodingData.results?.[0]) {
76
- throw new Error(`Location '${triggerData.city}' not found`);
77
- }
78
-
79
- const { latitude, longitude, name } = geocodingData.results[0];
80
-
81
- const weatherUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&daily=temperature_2m_max,temperature_2m_min,precipitation_probability_mean,weathercode&timezone=auto`;
82
- const response = await fetch(weatherUrl);
83
- const data = (await response.json()) as {
84
- daily: {
85
- time: string[];
86
- temperature_2m_max: number[];
87
- temperature_2m_min: number[];
88
- precipitation_probability_mean: number[];
89
- weathercode: number[];
90
- };
91
- };
92
-
93
- const forecast = data.daily.time.map((date: string, index: number) => ({
94
- date,
95
- maxTemp: data.daily.temperature_2m_max[index],
96
- minTemp: data.daily.temperature_2m_min[index],
97
- precipitationChance: data.daily.precipitation_probability_mean[index],
98
- condition: getWeatherCondition(data.daily.weathercode[index]!),
99
- location: name,
100
- }));
101
-
102
- return forecast;
103
- },
104
- });
105
-
106
- const forecastSchema = z.array(
107
- z.object({
108
- date: z.string(),
109
- maxTemp: z.number(),
110
- minTemp: z.number(),
111
- precipitationChance: z.number(),
112
- condition: z.string(),
113
- location: z.string(),
114
- }),
115
- );
116
-
117
- const planActivities = new Step({
118
- id: 'plan-activities',
119
- description: 'Suggests activities based on weather conditions',
120
- inputSchema: forecastSchema,
121
- execute: async ({ context, mastra }) => {
122
- const forecast = context?.getStepPayload<z.infer<typeof forecastSchema>>('fetch-weather');
123
-
124
- if (!forecast || forecast.length === 0) {
125
- throw new Error('Forecast data not found');
126
- }
127
-
128
- const prompt = `Based on the following weather forecast for ${forecast[0]?.location}, suggest appropriate activities:
129
- ${JSON.stringify(forecast, null, 2)}
130
- `;
131
-
132
- const response = await agent.stream([
133
- {
134
- role: 'user',
135
- content: prompt,
136
- },
137
- ]);
138
-
139
- for await (const chunk of response.textStream) {
140
- process.stdout.write(chunk);
141
- }
142
-
143
- return {
144
- activities: response.text,
145
- };
146
- },
147
- });
148
-
149
- function getWeatherCondition(code: number): string {
150
- const conditions: Record<number, string> = {
151
- 0: 'Clear sky',
152
- 1: 'Mainly clear',
153
- 2: 'Partly cloudy',
154
- 3: 'Overcast',
155
- 45: 'Foggy',
156
- 48: 'Depositing rime fog',
157
- 51: 'Light drizzle',
158
- 53: 'Moderate drizzle',
159
- 55: 'Dense drizzle',
160
- 61: 'Slight rain',
161
- 63: 'Moderate rain',
162
- 65: 'Heavy rain',
163
- 71: 'Slight snow fall',
164
- 73: 'Moderate snow fall',
165
- 75: 'Heavy snow fall',
166
- 95: 'Thunderstorm',
167
- };
168
- return conditions[code] || 'Unknown';
169
- }
170
-
171
- const weatherWorkflow = new Workflow({
172
- name: 'weather-workflow',
173
- triggerSchema: z.object({
174
- city: z.string().describe('The city to get the weather for'),
175
- }),
176
- })
177
- .step(fetchWeather)
178
- .then(planActivities);
179
-
180
- weatherWorkflow.commit();
181
-
182
- export { weatherWorkflow };