create-mastra 0.1.3-alpha.0 → 0.1.4-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.
- package/dist/index.js +23 -6
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/starter-files/workflow.ts +0 -182
- package/starter-files/config.ts +0 -28
- package/starter-files/mastra-pg.docker-compose.yaml +0 -15
- package/starter-files/tools.ts +0 -95
- package/starter-files/workflow.ts +0 -183
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-mastra",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4-alpha.0",
|
|
4
4
|
"description": "Create Mastra apps with one command",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"rollup-plugin-node-externals": "^8.0.0",
|
|
53
53
|
"typescript": "^5.7.3",
|
|
54
54
|
"@internal/lint": "0.0.0",
|
|
55
|
-
"mastra": "^0.2.
|
|
55
|
+
"mastra": "^0.2.4-alpha.0"
|
|
56
56
|
},
|
|
57
57
|
"engines": {
|
|
58
58
|
"node": ">=20"
|
|
@@ -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 };
|
package/starter-files/config.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
// @ts-ignore
|
|
2
|
-
import { Config } from '@mastra/core';
|
|
3
|
-
|
|
4
|
-
export const config: Config = {
|
|
5
|
-
name: 'PROJECT_NAME',
|
|
6
|
-
integrations: [],
|
|
7
|
-
db: {
|
|
8
|
-
provider: 'postgres',
|
|
9
|
-
uri: process.env.DB_URL!,
|
|
10
|
-
},
|
|
11
|
-
runner: {
|
|
12
|
-
provider: 'inngest',
|
|
13
|
-
uri: process.env.INNGEST_URL!,
|
|
14
|
-
signingKey: process.env.INNGEST_SIGNING_KEY!,
|
|
15
|
-
eventKey: process.env.INNGEST_EVENT_KEY!,
|
|
16
|
-
},
|
|
17
|
-
workflows: {
|
|
18
|
-
blueprintDirPath: '/mastra/blueprints',
|
|
19
|
-
systemEvents: {},
|
|
20
|
-
systemApis: [],
|
|
21
|
-
},
|
|
22
|
-
agents: {
|
|
23
|
-
agentDirPath: '/mastra/agents',
|
|
24
|
-
vectorProvider: [],
|
|
25
|
-
},
|
|
26
|
-
systemHostURL: process.env.APP_URL!,
|
|
27
|
-
routeRegistrationPath: '/api/mastra',
|
|
28
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
services:
|
|
2
|
-
db:
|
|
3
|
-
image: pgvector/pgvector:pg16
|
|
4
|
-
container_name: 'REPLACE_PROJECT_NAME-db'
|
|
5
|
-
ports:
|
|
6
|
-
- 'REPLACE_DB_PORT:5432'
|
|
7
|
-
environment:
|
|
8
|
-
POSTGRES_USER: ${POSTGRES_USER:-postgres}
|
|
9
|
-
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
|
|
10
|
-
POSTGRES_DB: ${POSTGRES_DB:-mastra}
|
|
11
|
-
volumes:
|
|
12
|
-
- pgdata:/var/lib/postgresql/data
|
|
13
|
-
|
|
14
|
-
volumes:
|
|
15
|
-
pgdata:
|
package/starter-files/tools.ts
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { createTool } from '@mastra/core';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
|
|
4
|
-
interface WeatherResponse {
|
|
5
|
-
current: {
|
|
6
|
-
time: string;
|
|
7
|
-
temperature_2m: number;
|
|
8
|
-
apparent_temperature: number;
|
|
9
|
-
relative_humidity_2m: number;
|
|
10
|
-
wind_speed_10m: number;
|
|
11
|
-
wind_gusts_10m: number;
|
|
12
|
-
weather_code: number;
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export const weatherTool = createTool({
|
|
17
|
-
id: 'get-weather',
|
|
18
|
-
description: 'Get current weather for a location',
|
|
19
|
-
inputSchema: z.object({
|
|
20
|
-
location: z.string().describe('City name'),
|
|
21
|
-
}),
|
|
22
|
-
outputSchema: z.object({
|
|
23
|
-
temperature: z.number(),
|
|
24
|
-
feelsLike: z.number(),
|
|
25
|
-
humidity: z.number(),
|
|
26
|
-
windSpeed: z.number(),
|
|
27
|
-
windGust: z.number(),
|
|
28
|
-
conditions: z.string(),
|
|
29
|
-
location: z.string(),
|
|
30
|
-
}),
|
|
31
|
-
execute: async ({ context }) => {
|
|
32
|
-
return await getWeather(context.location);
|
|
33
|
-
},
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
const getWeather = async (location: string) => {
|
|
37
|
-
const geocodingUrl = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(location)}&count=1`;
|
|
38
|
-
const geocodingResponse = await fetch(geocodingUrl);
|
|
39
|
-
const geocodingData = await geocodingResponse.json();
|
|
40
|
-
|
|
41
|
-
if (!geocodingData.results?.[0]) {
|
|
42
|
-
throw new Error(`Location '${location}' not found`);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const { latitude, longitude, name } = geocodingData.results[0];
|
|
46
|
-
|
|
47
|
-
const weatherUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}¤t=temperature_2m,apparent_temperature,relative_humidity_2m,wind_speed_10m,wind_gusts_10m,weather_code`;
|
|
48
|
-
|
|
49
|
-
const response = await fetch(weatherUrl);
|
|
50
|
-
const data: WeatherResponse = await response.json();
|
|
51
|
-
|
|
52
|
-
return {
|
|
53
|
-
temperature: data.current.temperature_2m,
|
|
54
|
-
feelsLike: data.current.apparent_temperature,
|
|
55
|
-
humidity: data.current.relative_humidity_2m,
|
|
56
|
-
windSpeed: data.current.wind_speed_10m,
|
|
57
|
-
windGust: data.current.wind_gusts_10m,
|
|
58
|
-
conditions: getWeatherCondition(data.current.weather_code),
|
|
59
|
-
location: name,
|
|
60
|
-
};
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
function getWeatherCondition(code: number): string {
|
|
64
|
-
const conditions: Record<number, string> = {
|
|
65
|
-
0: 'Clear sky',
|
|
66
|
-
1: 'Mainly clear',
|
|
67
|
-
2: 'Partly cloudy',
|
|
68
|
-
3: 'Overcast',
|
|
69
|
-
45: 'Foggy',
|
|
70
|
-
48: 'Depositing rime fog',
|
|
71
|
-
51: 'Light drizzle',
|
|
72
|
-
53: 'Moderate drizzle',
|
|
73
|
-
55: 'Dense drizzle',
|
|
74
|
-
56: 'Light freezing drizzle',
|
|
75
|
-
57: 'Dense freezing drizzle',
|
|
76
|
-
61: 'Slight rain',
|
|
77
|
-
63: 'Moderate rain',
|
|
78
|
-
65: 'Heavy rain',
|
|
79
|
-
66: 'Light freezing rain',
|
|
80
|
-
67: 'Heavy freezing rain',
|
|
81
|
-
71: 'Slight snow fall',
|
|
82
|
-
73: 'Moderate snow fall',
|
|
83
|
-
75: 'Heavy snow fall',
|
|
84
|
-
77: 'Snow grains',
|
|
85
|
-
80: 'Slight rain showers',
|
|
86
|
-
81: 'Moderate rain showers',
|
|
87
|
-
82: 'Violent rain showers',
|
|
88
|
-
85: 'Slight snow showers',
|
|
89
|
-
86: 'Heavy snow showers',
|
|
90
|
-
95: 'Thunderstorm',
|
|
91
|
-
96: 'Thunderstorm with slight hail',
|
|
92
|
-
99: 'Thunderstorm with heavy hail',
|
|
93
|
-
};
|
|
94
|
-
return conditions[code] || 'Unknown';
|
|
95
|
-
}
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
import { Step, Workflow } from '@mastra/core';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
|
|
4
|
-
const fetchWeather = new Step({
|
|
5
|
-
id: 'fetch-weather',
|
|
6
|
-
description: 'Fetches weather forecast for a given city',
|
|
7
|
-
inputSchema: z.object({
|
|
8
|
-
city: z.string().describe('The city to get the weather for'),
|
|
9
|
-
}),
|
|
10
|
-
execute: async ({ context }) => {
|
|
11
|
-
const triggerData = context.machineContext?.getStepPayload<{ city: string }>('trigger');
|
|
12
|
-
|
|
13
|
-
if (!triggerData) {
|
|
14
|
-
throw new Error('Trigger data not found');
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const geocodingUrl = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(triggerData.city)}&count=1`;
|
|
18
|
-
const geocodingResponse = await fetch(geocodingUrl);
|
|
19
|
-
const geocodingData = (await geocodingResponse.json()) as {
|
|
20
|
-
results: { latitude: number; longitude: number; name: string }[];
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
if (!geocodingData.results?.[0]) {
|
|
24
|
-
throw new Error(`Location '${triggerData.city}' not found`);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const { latitude, longitude, name } = geocodingData.results[0];
|
|
28
|
-
|
|
29
|
-
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`;
|
|
30
|
-
const response = await fetch(weatherUrl);
|
|
31
|
-
const data = (await response.json()) as {
|
|
32
|
-
daily: {
|
|
33
|
-
time: string[];
|
|
34
|
-
temperature_2m_max: number[];
|
|
35
|
-
temperature_2m_min: number[];
|
|
36
|
-
precipitation_probability_mean: number[];
|
|
37
|
-
weathercode: number[];
|
|
38
|
-
};
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
const forecast = data.daily.time.map((date: string, index: number) => ({
|
|
42
|
-
date,
|
|
43
|
-
maxTemp: data.daily.temperature_2m_max[index],
|
|
44
|
-
minTemp: data.daily.temperature_2m_min[index],
|
|
45
|
-
precipitationChance: data.daily.precipitation_probability_mean[index],
|
|
46
|
-
condition: getWeatherCondition(data.daily.weathercode[index]!),
|
|
47
|
-
location: name,
|
|
48
|
-
}));
|
|
49
|
-
|
|
50
|
-
return forecast;
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
const forecastSchema = z.array(
|
|
55
|
-
z.object({
|
|
56
|
-
date: z.string(),
|
|
57
|
-
maxTemp: z.number(),
|
|
58
|
-
minTemp: z.number(),
|
|
59
|
-
precipitationChance: z.number(),
|
|
60
|
-
condition: z.string(),
|
|
61
|
-
location: z.string(),
|
|
62
|
-
}),
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
const planActivities = new Step({
|
|
66
|
-
id: 'plan-activities',
|
|
67
|
-
description: 'Suggests activities based on weather conditions',
|
|
68
|
-
inputSchema: forecastSchema,
|
|
69
|
-
execute: async ({ context, mastra }) => {
|
|
70
|
-
const forecast = context.machineContext?.getStepPayload<z.infer<typeof forecastSchema>>('fetch-weather');
|
|
71
|
-
|
|
72
|
-
if (!forecast) {
|
|
73
|
-
throw new Error('Forecast data not found');
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const prompt = `Based on the following weather forecast for ${forecast[0].location}, suggest appropriate activities:
|
|
77
|
-
${JSON.stringify(forecast, null, 2)}
|
|
78
|
-
`;
|
|
79
|
-
|
|
80
|
-
if (!mastra?.llm) {
|
|
81
|
-
throw new Error('Mastra not found');
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const llm = mastra.llm({
|
|
85
|
-
provider: 'OPEN_AI',
|
|
86
|
-
name: 'gpt-4o',
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
const response = await llm.stream([
|
|
90
|
-
{
|
|
91
|
-
role: 'system',
|
|
92
|
-
content: `You are a local activities and travel expert who excels at weather-based planning. Analyze the weather data and provide practical activity recommendations.
|
|
93
|
-
|
|
94
|
-
For each day in the forecast, structure your response exactly as follows:
|
|
95
|
-
|
|
96
|
-
📅 [Day, Month Date, Year]
|
|
97
|
-
═══════════════════════════
|
|
98
|
-
|
|
99
|
-
🌡️ WEATHER SUMMARY
|
|
100
|
-
• Conditions: [brief description]
|
|
101
|
-
• Temperature: [X°C/Y°F to A°C/B°F]
|
|
102
|
-
• Precipitation: [X% chance]
|
|
103
|
-
|
|
104
|
-
🌅 MORNING ACTIVITIES
|
|
105
|
-
Outdoor:
|
|
106
|
-
• [Activity Name] - [Brief description including specific location/route]
|
|
107
|
-
Best timing: [specific time range]
|
|
108
|
-
Note: [relevant weather consideration]
|
|
109
|
-
|
|
110
|
-
🌞 AFTERNOON ACTIVITIES
|
|
111
|
-
Outdoor:
|
|
112
|
-
• [Activity Name] - [Brief description including specific location/route]
|
|
113
|
-
Best timing: [specific time range]
|
|
114
|
-
Note: [relevant weather consideration]
|
|
115
|
-
|
|
116
|
-
🏠 INDOOR ALTERNATIVES
|
|
117
|
-
• [Activity Name] - [Brief description including specific venue]
|
|
118
|
-
Ideal for: [weather condition that would trigger this alternative]
|
|
119
|
-
|
|
120
|
-
⚠️ SPECIAL CONSIDERATIONS
|
|
121
|
-
• [Any relevant weather warnings, UV index, wind conditions, etc.]
|
|
122
|
-
|
|
123
|
-
Guidelines:
|
|
124
|
-
- Suggest 2-3 time-specific outdoor activities per day
|
|
125
|
-
- Include 1-2 indoor backup options
|
|
126
|
-
- For precipitation >50%, lead with indoor activities
|
|
127
|
-
- All activities must be specific to the location
|
|
128
|
-
- Include specific venues, trails, or locations
|
|
129
|
-
- Consider activity intensity based on temperature
|
|
130
|
-
- Keep descriptions concise but informative
|
|
131
|
-
|
|
132
|
-
Maintain this exact formatting for consistency, using the emoji and section headers as shown.`,
|
|
133
|
-
},
|
|
134
|
-
{
|
|
135
|
-
role: 'user',
|
|
136
|
-
content: prompt,
|
|
137
|
-
},
|
|
138
|
-
]);
|
|
139
|
-
|
|
140
|
-
for await (const chunk of response.textStream) {
|
|
141
|
-
process.stdout.write(chunk);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return {
|
|
145
|
-
activities: response.text,
|
|
146
|
-
};
|
|
147
|
-
},
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
function getWeatherCondition(code: number): string {
|
|
151
|
-
const conditions: Record<number, string> = {
|
|
152
|
-
0: 'Clear sky',
|
|
153
|
-
1: 'Mainly clear',
|
|
154
|
-
2: 'Partly cloudy',
|
|
155
|
-
3: 'Overcast',
|
|
156
|
-
45: 'Foggy',
|
|
157
|
-
48: 'Depositing rime fog',
|
|
158
|
-
51: 'Light drizzle',
|
|
159
|
-
53: 'Moderate drizzle',
|
|
160
|
-
55: 'Dense drizzle',
|
|
161
|
-
61: 'Slight rain',
|
|
162
|
-
63: 'Moderate rain',
|
|
163
|
-
65: 'Heavy rain',
|
|
164
|
-
71: 'Slight snow fall',
|
|
165
|
-
73: 'Moderate snow fall',
|
|
166
|
-
75: 'Heavy snow fall',
|
|
167
|
-
95: 'Thunderstorm',
|
|
168
|
-
};
|
|
169
|
-
return conditions[code] || 'Unknown';
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const weatherWorkflow = new Workflow({
|
|
173
|
-
name: 'weather-workflow',
|
|
174
|
-
triggerSchema: z.object({
|
|
175
|
-
city: z.string().describe('The city to get the weather for'),
|
|
176
|
-
}),
|
|
177
|
-
})
|
|
178
|
-
.step(fetchWeather)
|
|
179
|
-
.then(planActivities);
|
|
180
|
-
|
|
181
|
-
weatherWorkflow.commit();
|
|
182
|
-
|
|
183
|
-
export { weatherWorkflow };
|