mastra-starter 1.0.9 → 1.0.10
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/chad.character.json +4 -1
- package/package.json +5 -5
- package/src/mastra/agents/index.ts +33 -19
- package/util.mjs +128 -104
- package/src/mastra/agents/util.ts +0 -23
- package/src/mastra/tools/index.ts +0 -102
- package/util.d.ts +0 -1
package/chad.character.json
CHANGED
@@ -8,7 +8,10 @@
|
|
8
8
|
"model": "en_US-male-medium"
|
9
9
|
}
|
10
10
|
},
|
11
|
-
"plugins": [
|
11
|
+
"plugins": [
|
12
|
+
"github:v-3/discordmcp",
|
13
|
+
"github:qpd-v/mcp-communicator-telegram"
|
14
|
+
],
|
12
15
|
"bio": [
|
13
16
|
"Just a chill guy living life to the fullest",
|
14
17
|
"Always down to help others out",
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "mastra-starter",
|
3
|
-
"version": "1.0.
|
3
|
+
"version": "1.0.10",
|
4
4
|
"main": "index.mjs",
|
5
5
|
"bin": {
|
6
6
|
"mastra-starter": "./index.mjs"
|
@@ -15,13 +15,13 @@
|
|
15
15
|
"type": "module",
|
16
16
|
"dependencies": {
|
17
17
|
"@ai-sdk/openai": "^1.2.2",
|
18
|
-
"@mastra/composio": "^0.1.
|
19
|
-
"@mastra/core": "^0.6.
|
20
|
-
"@mastra/mcp": "^0.3.
|
18
|
+
"@mastra/composio": "^0.1.12",
|
19
|
+
"@mastra/core": "^0.6.3",
|
20
|
+
"@mastra/mcp": "^0.3.4",
|
21
21
|
"commander": "^13.1.0",
|
22
22
|
"dedent": "^1.5.3",
|
23
23
|
"dotenv": "^16.4.7",
|
24
|
-
"mastra": "^0.3.
|
24
|
+
"mastra": "^0.3.1",
|
25
25
|
"mkdirp": "^3.0.1",
|
26
26
|
"pnpm-package-lookup": "^0.0.2",
|
27
27
|
"rimraf": "^6.0.1",
|
@@ -3,7 +3,7 @@ import path from "path";
|
|
3
3
|
import { createOpenAI } from "@ai-sdk/openai";
|
4
4
|
import { Agent, ToolsInput } from "@mastra/core/agent";
|
5
5
|
import dedent from "dedent";
|
6
|
-
import { PnpmPackageLookup } from
|
6
|
+
import { PnpmPackageLookup } from "pnpm-package-lookup";
|
7
7
|
import { MCPConfiguration } from "@mastra/mcp";
|
8
8
|
import { ComposioIntegration } from "@mastra/composio";
|
9
9
|
import { sortPlugins, getNpmPackageType } from "../../../util.mjs";
|
@@ -33,31 +33,44 @@ for (const pluginSpecifier of npmPlugins) {
|
|
33
33
|
let pluginSpecifier2;
|
34
34
|
const packagesDir = path.resolve(rootDir, "packages");
|
35
35
|
if (npmPackageType === "github") {
|
36
|
-
const packageBasename = path.basename(
|
36
|
+
const packageBasename = path.basename(
|
37
|
+
pluginSpecifier.replace("github:", "")
|
38
|
+
);
|
37
39
|
const packageResolvedName = `file:${path.resolve(packagesDir, packageBasename)}`;
|
38
|
-
pluginSpecifier2 =
|
40
|
+
pluginSpecifier2 =
|
41
|
+
await pnpmPackageLookup.getPackageNameBySpecifier(packageResolvedName);
|
39
42
|
if (!pluginSpecifier2) {
|
40
|
-
throw new Error(
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
43
|
+
throw new Error(
|
44
|
+
`Could not resolve package name for ${JSON.stringify(
|
45
|
+
{
|
46
|
+
pluginSpecifier,
|
47
|
+
packageBasename,
|
48
|
+
packageResolvedName,
|
49
|
+
},
|
50
|
+
null,
|
51
|
+
2
|
52
|
+
)}`
|
53
|
+
);
|
45
54
|
}
|
46
55
|
} else {
|
47
56
|
pluginSpecifier2 = pluginSpecifier;
|
48
57
|
}
|
49
58
|
const packagePath = path.resolve(rootDir, "node_modules", pluginSpecifier2);
|
50
|
-
// console.log('packagePath', {
|
51
|
-
// pluginSpecifier,
|
52
|
-
// pluginSpecifier2,
|
53
|
-
// packagePath,
|
54
|
-
// });
|
55
|
-
|
56
59
|
// check if start script exists
|
57
60
|
const packageJsonPath = path.resolve(packagePath, "package.json");
|
58
|
-
const packageJson = JSON.parse(
|
61
|
+
const packageJson = JSON.parse(
|
62
|
+
await fs.promises.readFile(packageJsonPath, "utf8")
|
63
|
+
);
|
64
|
+
const pluginName =
|
65
|
+
pluginSpecifier
|
66
|
+
// .replace(/^github:/, "")
|
67
|
+
.replace(/[\/:]+/g, "-")
|
68
|
+
.replace(/[^a-zA-Z0-9_-]/g, "");
|
69
|
+
if (!pluginName) {
|
70
|
+
throw new Error(`Could not clean up plugin name for ${pluginSpecifier}`);
|
71
|
+
}
|
59
72
|
if (packageJson.scripts.start) {
|
60
|
-
servers[
|
73
|
+
servers[pluginName] = {
|
61
74
|
command: "pnpm",
|
62
75
|
args: ["--dir", packagePath, "--silent", "start"],
|
63
76
|
env: process.env as any,
|
@@ -66,17 +79,18 @@ for (const pluginSpecifier of npmPlugins) {
|
|
66
79
|
// check if any bins exist; if so, use the first one
|
67
80
|
if (packageJson.bin && Object.keys(packageJson.bin).length > 0) {
|
68
81
|
const firstBin = Object.keys(packageJson.bin)[0];
|
69
|
-
servers[
|
82
|
+
servers[pluginName] = {
|
70
83
|
command: "pnpm",
|
71
84
|
args: ["--dir", packagePath, "--silent", "exec", firstBin],
|
72
85
|
env: process.env as any,
|
73
86
|
};
|
74
87
|
} else {
|
75
|
-
throw new Error(
|
88
|
+
throw new Error(
|
89
|
+
`No start script or bins found for ${pluginSpecifier} name ${pluginName}`
|
90
|
+
);
|
76
91
|
}
|
77
92
|
}
|
78
93
|
}
|
79
|
-
// console.log('servers', servers);
|
80
94
|
|
81
95
|
// mcp tools
|
82
96
|
const mcp = new MCPConfiguration({
|
package/util.mjs
CHANGED
@@ -81,8 +81,11 @@ export const sortNpmPackages = (packageSpecifiers) => {
|
|
81
81
|
const installNpmGithubPackages = async (packageSpecifiers) => {
|
82
82
|
console.log(`Installing github packages: ${packageSpecifiers.join(", ")}`);
|
83
83
|
|
84
|
-
//
|
84
|
+
// wipe packages directory
|
85
85
|
const packagesDir = path.resolve(process.cwd(), "packages");
|
86
|
+
await rimraf(packagesDir);
|
87
|
+
|
88
|
+
// Ensure packages directory exists
|
86
89
|
try {
|
87
90
|
await mkdirp(packagesDir);
|
88
91
|
} catch (error) {
|
@@ -90,130 +93,151 @@ const installNpmGithubPackages = async (packageSpecifiers) => {
|
|
90
93
|
return Promise.reject(error);
|
91
94
|
}
|
92
95
|
|
93
|
-
//
|
94
|
-
const
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
}
|
96
|
+
// Transform package specifiers to GitHub URLs
|
97
|
+
const repoNames = packageSpecifiers.map((specifier) => {
|
98
|
+
specifier = specifier.replace("github:", "");
|
99
|
+
specifier = `https://github.com/${specifier}`;
|
100
|
+
return specifier;
|
101
|
+
});
|
99
102
|
|
100
103
|
// git clone all packages
|
101
|
-
await
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
}
|
114
|
-
);
|
115
|
-
|
116
|
-
cp.on("error", (error) => {
|
117
|
-
console.error(`Error executing git clone: ${error.stack}`);
|
118
|
-
reject(error);
|
119
|
-
});
|
120
|
-
|
121
|
-
cp.on("close", (code) => {
|
122
|
-
if (code !== 0) {
|
123
|
-
console.error(`git clone exited with code ${code}`);
|
124
|
-
reject(new Error(`git clone exited with code ${code}`));
|
125
|
-
} else {
|
126
|
-
resolve();
|
127
|
-
}
|
128
|
-
});
|
129
|
-
});
|
104
|
+
await Promise.all(
|
105
|
+
repoNames.map(async (repoUrl) => {
|
106
|
+
return new Promise((resolveClone, rejectClone) => {
|
107
|
+
console.log(`Cloning ${repoUrl}...`);
|
108
|
+
const cp = child_process.spawn(
|
109
|
+
"git",
|
110
|
+
["clone", "--depth", "1", repoUrl],
|
111
|
+
{
|
112
|
+
stdio: "inherit",
|
113
|
+
cwd: packagesDir,
|
114
|
+
}
|
115
|
+
);
|
130
116
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
117
|
+
cp.on("error", (error) => {
|
118
|
+
console.error(
|
119
|
+
`Error executing git clone for ${repoUrl}: ${error.stack}`
|
120
|
+
);
|
121
|
+
rejectClone(error);
|
122
|
+
});
|
135
123
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
124
|
+
cp.on("close", (code) => {
|
125
|
+
if (code !== 0) {
|
126
|
+
console.error(`git clone for ${repoUrl} exited with code ${code}`);
|
127
|
+
rejectClone(new Error(`git clone exited with code ${code}`));
|
128
|
+
} else {
|
129
|
+
console.log(`Successfully cloned ${repoUrl}`);
|
130
|
+
resolveClone();
|
131
|
+
}
|
132
|
+
});
|
141
133
|
});
|
134
|
+
})
|
135
|
+
);
|
142
136
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
137
|
+
// build and install all plugins into local packages
|
138
|
+
await Promise.all(
|
139
|
+
packageSpecifiers.map(async (packageSpecifier) => {
|
140
|
+
const packageBasename = path.basename(
|
141
|
+
packageSpecifier.replace("github:", "")
|
142
|
+
);
|
143
|
+
const packagePath = path.resolve(packagesDir, packageBasename);
|
144
|
+
|
145
|
+
// pnpm install in local directory
|
146
|
+
await new Promise((resolveInstall, rejectInstall) => {
|
147
|
+
const cp = child_process.spawn("pnpm", ["install"], {
|
148
|
+
stdio: "inherit",
|
149
|
+
cwd: packagePath,
|
150
|
+
env: { ...process.env },
|
151
|
+
});
|
157
152
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
153
|
+
cp.on("error", (error) => {
|
154
|
+
console.error(
|
155
|
+
`Error executing pnpm install for ${packageBasename}: ${error.stack}`
|
156
|
+
);
|
157
|
+
rejectInstall(error);
|
158
|
+
});
|
159
|
+
cp.on("close", (code) => {
|
160
|
+
if (code !== 0) {
|
161
|
+
rejectInstall(new Error(`pnpm install exited with code ${code}`));
|
162
|
+
} else {
|
163
|
+
resolveInstall();
|
164
|
+
}
|
165
|
+
});
|
165
166
|
});
|
166
167
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
error: error.stack,
|
168
|
+
// pnpm build
|
169
|
+
// note: this is advisory and allowed to fail
|
170
|
+
await new Promise((resolveSpawn, rejectSpawn) => {
|
171
|
+
const cp = child_process.spawn("pnpm", ["build"], {
|
172
|
+
stdio: "inherit",
|
173
|
+
cwd: packagePath,
|
174
|
+
env: { ...process.env },
|
175
175
|
});
|
176
|
-
|
177
|
-
|
178
|
-
if (code !== 0) {
|
176
|
+
|
177
|
+
cp.on("error", (error) => {
|
179
178
|
console.error(
|
180
|
-
`pnpm build for ${packageBasename}
|
179
|
+
`Error executing pnpm build for ${packageBasename}: ${error.stack}`
|
181
180
|
);
|
182
181
|
resolveSpawn({
|
183
182
|
success: false,
|
184
183
|
package: packageBasename,
|
185
|
-
error:
|
184
|
+
error: error.stack,
|
186
185
|
});
|
187
|
-
}
|
188
|
-
|
189
|
-
|
190
|
-
|
186
|
+
});
|
187
|
+
cp.on("close", (code) => {
|
188
|
+
if (code !== 0) {
|
189
|
+
console.error(
|
190
|
+
`pnpm build for ${packageBasename} exited with code ${code}`
|
191
|
+
);
|
192
|
+
resolveSpawn({
|
193
|
+
success: false,
|
194
|
+
package: packageBasename,
|
195
|
+
error: `exited with code ${code}`,
|
196
|
+
});
|
197
|
+
} else {
|
198
|
+
console.log(`Build completed successfully for ${packageBasename}`);
|
199
|
+
resolveSpawn({ success: true, package: packageBasename });
|
200
|
+
}
|
201
|
+
});
|
191
202
|
});
|
192
|
-
})
|
203
|
+
})
|
204
|
+
);
|
193
205
|
|
194
|
-
|
195
|
-
|
196
|
-
|
206
|
+
// install all plugins into app
|
207
|
+
// pnpm install to app
|
208
|
+
await new Promise((resolveInstall, rejectInstall) => {
|
209
|
+
const packageRefs = packageSpecifiers.map((packageSpecifier) => {
|
210
|
+
const packageBasename = path.basename(
|
211
|
+
packageSpecifier.replace("github:", "")
|
212
|
+
);
|
213
|
+
const packagePath = path.resolve(packagesDir, packageBasename);
|
214
|
+
return `file:${packagePath}`;
|
215
|
+
});
|
216
|
+
console.log(`Installing ${JSON.stringify(packageRefs)} to app`);
|
217
|
+
const cp = child_process.spawn(
|
218
|
+
"pnpm",
|
219
|
+
["install", ...packageRefs],
|
220
|
+
{
|
197
221
|
stdio: "inherit",
|
198
222
|
cwd: process.cwd(),
|
199
223
|
env: { ...process.env },
|
200
|
-
}
|
224
|
+
}
|
225
|
+
);
|
201
226
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
});
|
227
|
+
cp.on("error", (error) => {
|
228
|
+
console.error(
|
229
|
+
`Error executing pnpm install for ${packageBasename}: ${error.stack}`
|
230
|
+
);
|
231
|
+
rejectInstall(error);
|
232
|
+
});
|
233
|
+
cp.on("close", (code) => {
|
234
|
+
if (code !== 0) {
|
235
|
+
rejectInstall(new Error(`pnpm install exited with code ${code}`));
|
236
|
+
} else {
|
237
|
+
resolveInstall();
|
238
|
+
}
|
215
239
|
});
|
216
|
-
})
|
240
|
+
});
|
217
241
|
};
|
218
242
|
const installNpmBasicPackages = async (packageSpecifiers) => {
|
219
243
|
// packageSpecifiers = uniquify(packageSpecifiers);
|
@@ -244,6 +268,6 @@ export const installNpmPackages = async (packageSpecifiers) => {
|
|
244
268
|
const { github, npm } = sortNpmPackages(packageSpecifiers);
|
245
269
|
await Promise.all([
|
246
270
|
installNpmGithubPackages(github),
|
247
|
-
installNpmBasicPackages(npm)
|
271
|
+
installNpmBasicPackages(npm),
|
248
272
|
]);
|
249
|
-
};
|
273
|
+
};
|
@@ -1,23 +0,0 @@
|
|
1
|
-
export const getPluginType = (plugin: string) => {
|
2
|
-
if (plugin.startsWith('composio:')) {
|
3
|
-
return 'composio';
|
4
|
-
} else {
|
5
|
-
return 'npm';
|
6
|
-
}
|
7
|
-
};
|
8
|
-
export const sortPlugins = (plugins: string[]) => {
|
9
|
-
const npm: string[] = [];
|
10
|
-
const composio: string[] = [];
|
11
|
-
for (const plugin of plugins) {
|
12
|
-
const pluginType = getPluginType(plugin);
|
13
|
-
if (pluginType === 'npm') {
|
14
|
-
npm.push(plugin);
|
15
|
-
} else if (pluginType === 'composio') {
|
16
|
-
composio.push(plugin);
|
17
|
-
}
|
18
|
-
}
|
19
|
-
return {
|
20
|
-
npm,
|
21
|
-
composio,
|
22
|
-
};
|
23
|
-
};
|
@@ -1,102 +0,0 @@
|
|
1
|
-
import { createTool } from '@mastra/core/tools';
|
2
|
-
import { z } from 'zod';
|
3
|
-
|
4
|
-
interface GeocodingResponse {
|
5
|
-
results: {
|
6
|
-
latitude: number;
|
7
|
-
longitude: number;
|
8
|
-
name: string;
|
9
|
-
}[];
|
10
|
-
}
|
11
|
-
interface WeatherResponse {
|
12
|
-
current: {
|
13
|
-
time: string;
|
14
|
-
temperature_2m: number;
|
15
|
-
apparent_temperature: number;
|
16
|
-
relative_humidity_2m: number;
|
17
|
-
wind_speed_10m: number;
|
18
|
-
wind_gusts_10m: number;
|
19
|
-
weather_code: number;
|
20
|
-
};
|
21
|
-
}
|
22
|
-
|
23
|
-
export const weatherTool = createTool({
|
24
|
-
id: 'get-weather',
|
25
|
-
description: 'Get current weather for a location',
|
26
|
-
inputSchema: z.object({
|
27
|
-
location: z.string().describe('City name'),
|
28
|
-
}),
|
29
|
-
outputSchema: z.object({
|
30
|
-
temperature: z.number(),
|
31
|
-
feelsLike: z.number(),
|
32
|
-
humidity: z.number(),
|
33
|
-
windSpeed: z.number(),
|
34
|
-
windGust: z.number(),
|
35
|
-
conditions: z.string(),
|
36
|
-
location: z.string(),
|
37
|
-
}),
|
38
|
-
execute: async ({ context }) => {
|
39
|
-
return await getWeather(context.location);
|
40
|
-
},
|
41
|
-
});
|
42
|
-
|
43
|
-
const getWeather = async (location: string) => {
|
44
|
-
const geocodingUrl = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(location)}&count=1`;
|
45
|
-
const geocodingResponse = await fetch(geocodingUrl);
|
46
|
-
const geocodingData = (await geocodingResponse.json()) as GeocodingResponse;
|
47
|
-
|
48
|
-
if (!geocodingData.results?.[0]) {
|
49
|
-
throw new Error(`Location '${location}' not found`);
|
50
|
-
}
|
51
|
-
|
52
|
-
const { latitude, longitude, name } = geocodingData.results[0];
|
53
|
-
|
54
|
-
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`;
|
55
|
-
|
56
|
-
const response = await fetch(weatherUrl);
|
57
|
-
const data = (await response.json()) as WeatherResponse;
|
58
|
-
|
59
|
-
return {
|
60
|
-
temperature: data.current.temperature_2m,
|
61
|
-
feelsLike: data.current.apparent_temperature,
|
62
|
-
humidity: data.current.relative_humidity_2m,
|
63
|
-
windSpeed: data.current.wind_speed_10m,
|
64
|
-
windGust: data.current.wind_gusts_10m,
|
65
|
-
conditions: getWeatherCondition(data.current.weather_code),
|
66
|
-
location: name,
|
67
|
-
};
|
68
|
-
};
|
69
|
-
|
70
|
-
function getWeatherCondition(code: number): string {
|
71
|
-
const conditions: Record<number, string> = {
|
72
|
-
0: 'Clear sky',
|
73
|
-
1: 'Mainly clear',
|
74
|
-
2: 'Partly cloudy',
|
75
|
-
3: 'Overcast',
|
76
|
-
45: 'Foggy',
|
77
|
-
48: 'Depositing rime fog',
|
78
|
-
51: 'Light drizzle',
|
79
|
-
53: 'Moderate drizzle',
|
80
|
-
55: 'Dense drizzle',
|
81
|
-
56: 'Light freezing drizzle',
|
82
|
-
57: 'Dense freezing drizzle',
|
83
|
-
61: 'Slight rain',
|
84
|
-
63: 'Moderate rain',
|
85
|
-
65: 'Heavy rain',
|
86
|
-
66: 'Light freezing rain',
|
87
|
-
67: 'Heavy freezing rain',
|
88
|
-
71: 'Slight snow fall',
|
89
|
-
73: 'Moderate snow fall',
|
90
|
-
75: 'Heavy snow fall',
|
91
|
-
77: 'Snow grains',
|
92
|
-
80: 'Slight rain showers',
|
93
|
-
81: 'Moderate rain showers',
|
94
|
-
82: 'Violent rain showers',
|
95
|
-
85: 'Slight snow showers',
|
96
|
-
86: 'Heavy snow showers',
|
97
|
-
95: 'Thunderstorm',
|
98
|
-
96: 'Thunderstorm with slight hail',
|
99
|
-
99: 'Thunderstorm with heavy hail',
|
100
|
-
};
|
101
|
-
return conditions[code] || 'Unknown';
|
102
|
-
}
|
package/util.d.ts
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
declare module "util.mjs";
|