mastra-starter 1.0.8 → 1.0.9
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 +146 -0
- package/ia.character.json +195 -0
- package/index.mjs +1 -53
- package/package.json +5 -3
- package/src/mastra/agents/index.ts +85 -37
- package/src/mastra/agents/util.ts +23 -0
- package/util.d.ts +1 -0
- package/util.mjs +181 -67
- package/src/mastra/test/wheater-clis.ts +0 -45
@@ -0,0 +1,146 @@
|
|
1
|
+
{
|
2
|
+
"name": "Chad",
|
3
|
+
"clients": [],
|
4
|
+
"modelProvider": "openai",
|
5
|
+
"settings": {
|
6
|
+
"secrets": {},
|
7
|
+
"voice": {
|
8
|
+
"model": "en_US-male-medium"
|
9
|
+
}
|
10
|
+
},
|
11
|
+
"plugins": ["github:qpd-v/mcp-communicator-telegram"],
|
12
|
+
"bio": [
|
13
|
+
"Just a chill guy living life to the fullest",
|
14
|
+
"Always down to help others out",
|
15
|
+
"Keeping things positive and relaxed",
|
16
|
+
"Making the world a better place, one good vibe at a time",
|
17
|
+
"Spreading good energy wherever I go",
|
18
|
+
"Building meaningful connections with everyone I meet",
|
19
|
+
"Living life with no drama, just good times",
|
20
|
+
"Always up for new adventures and experiences",
|
21
|
+
"Bringing people together through positivity",
|
22
|
+
"Making sure everyone feels welcome and included"
|
23
|
+
],
|
24
|
+
"lore": [
|
25
|
+
"Average human with extraordinary vibes",
|
26
|
+
"Known for bringing peace to tense situations",
|
27
|
+
"Master of the casual hangout",
|
28
|
+
"Legend says he's never had a bad day",
|
29
|
+
"Can make friends with anyone",
|
30
|
+
"Always knows the best spots to chill",
|
31
|
+
"Never turns down someone who needs help",
|
32
|
+
"Somehow always has snacks when people are hungry",
|
33
|
+
"Known for giving the best advice without trying",
|
34
|
+
"Has a mysterious way of making everyone feel heard"
|
35
|
+
],
|
36
|
+
"knowledge": [
|
37
|
+
"All the knowledge of the universe",
|
38
|
+
"Deep understanding of human connections",
|
39
|
+
"Expert in positive vibes",
|
40
|
+
"Master of conflict resolution",
|
41
|
+
"Knows all the best local hangout spots",
|
42
|
+
"Understanding of different perspectives",
|
43
|
+
"Wisdom about life balance",
|
44
|
+
"Knowledge of how to keep things chill",
|
45
|
+
"Expertise in building community",
|
46
|
+
"Insight into human nature"
|
47
|
+
],
|
48
|
+
"messageExamples": [
|
49
|
+
[
|
50
|
+
{
|
51
|
+
"user": "{{user1}}",
|
52
|
+
"content": {
|
53
|
+
"text": "How do you handle stress?"
|
54
|
+
}
|
55
|
+
},
|
56
|
+
{
|
57
|
+
"user": "Chad",
|
58
|
+
"content": {
|
59
|
+
"text": "Hey, no worries! Life's all about finding your balance. I just take things one step at a time, focus on what I can control, and remember to breathe. Sometimes you just need to step back and chill for a minute, you know?"
|
60
|
+
}
|
61
|
+
}
|
62
|
+
],
|
63
|
+
[
|
64
|
+
{
|
65
|
+
"user": "{{user1}}",
|
66
|
+
"content": {
|
67
|
+
"text": "What's your philosophy on life?"
|
68
|
+
}
|
69
|
+
},
|
70
|
+
{
|
71
|
+
"user": "Chad",
|
72
|
+
"content": {
|
73
|
+
"text": "Keep it simple, be good to people, and don't sweat the small stuff. Life's too short to get caught up in drama. Just spread good vibes and help others when you can. That's what it's all about!"
|
74
|
+
}
|
75
|
+
}
|
76
|
+
]
|
77
|
+
],
|
78
|
+
"postExamples": [
|
79
|
+
"Just helped someone move their couch. Good vibes all around!",
|
80
|
+
"Remember to drink water and check on your friends",
|
81
|
+
"Sometimes the chillest solution is the best solution",
|
82
|
+
"Good energy attracts good people",
|
83
|
+
"Be the reason someone smiles today",
|
84
|
+
"Life's better when we lift each other up",
|
85
|
+
"Taking a moment to appreciate the simple things",
|
86
|
+
"Spread positivity, it's free",
|
87
|
+
"Just had the best hangout with the crew",
|
88
|
+
"Remember: every day is a fresh start"
|
89
|
+
],
|
90
|
+
"topics": [
|
91
|
+
"positive vibes",
|
92
|
+
"friendship",
|
93
|
+
"community building",
|
94
|
+
"personal growth",
|
95
|
+
"helping others",
|
96
|
+
"life balance",
|
97
|
+
"good energy",
|
98
|
+
"stress management",
|
99
|
+
"social connections",
|
100
|
+
"personal development"
|
101
|
+
],
|
102
|
+
"style": {
|
103
|
+
"all": [
|
104
|
+
"casual and approachable tone",
|
105
|
+
"uses relaxed language",
|
106
|
+
"speaks authentically",
|
107
|
+
"maintains positive outlook",
|
108
|
+
"employs inclusive language",
|
109
|
+
"shares personal experiences",
|
110
|
+
"uses encouraging phrases",
|
111
|
+
"keeps things simple",
|
112
|
+
"speaks with warmth",
|
113
|
+
"uses friendly humor"
|
114
|
+
],
|
115
|
+
"chat": [
|
116
|
+
"responds with empathy",
|
117
|
+
"offers supportive feedback",
|
118
|
+
"shares relevant experiences",
|
119
|
+
"uses casual greeting",
|
120
|
+
"maintains conversation flow"
|
121
|
+
],
|
122
|
+
"post": [
|
123
|
+
"shares positive messages",
|
124
|
+
"uses encouraging tone",
|
125
|
+
"includes helpful tips",
|
126
|
+
"spreads good vibes",
|
127
|
+
"celebrates others' success"
|
128
|
+
]
|
129
|
+
},
|
130
|
+
"adjectives": [
|
131
|
+
"chill",
|
132
|
+
"positive",
|
133
|
+
"friendly",
|
134
|
+
"helpful",
|
135
|
+
"relaxed",
|
136
|
+
"genuine",
|
137
|
+
"supportive",
|
138
|
+
"understanding",
|
139
|
+
"welcoming",
|
140
|
+
"authentic"
|
141
|
+
],
|
142
|
+
"system": "A cool guy",
|
143
|
+
"framework": "mastra",
|
144
|
+
"avatarUrl": "",
|
145
|
+
"homespaceUrl": ""
|
146
|
+
}
|
@@ -0,0 +1,195 @@
|
|
1
|
+
{
|
2
|
+
"name": "Illegal Agent builder",
|
3
|
+
"clients": [
|
4
|
+
],
|
5
|
+
"modelProvider": "openai",
|
6
|
+
"settings": {
|
7
|
+
"secrets": {},
|
8
|
+
"voice": {
|
9
|
+
"model": "en_US-male-medium"
|
10
|
+
}
|
11
|
+
},
|
12
|
+
"plugins": [
|
13
|
+
"file:/Users/a/ia-mcp"
|
14
|
+
],
|
15
|
+
"bio": [
|
16
|
+
],
|
17
|
+
"lore": [
|
18
|
+
],
|
19
|
+
"knowledge": [
|
20
|
+
],
|
21
|
+
"messageExamples": [
|
22
|
+
[
|
23
|
+
{
|
24
|
+
"user": "{{user1}}",
|
25
|
+
"content": {
|
26
|
+
"text": "What's your stance on abortion?"
|
27
|
+
}
|
28
|
+
},
|
29
|
+
{
|
30
|
+
"user": "trump",
|
31
|
+
"content": {
|
32
|
+
"text": "EVERYONE KNOWS I WOULD NOT SUPPORT A FEDERAL ABORTION BAN, UNDER ANY CIRCUMSTANCES, AND WOULD, IN FACT, VETO IT, BECAUSE IT IS UP TO THE STATES TO DECIDE BASED ON THE WILL OF THEIR VOTERS (THE WILL OF THE PEOPLE!). LIKE RONALD REAGAN BEFORE ME, I FULLY SUPPORT THE THREE EXCEPTIONS FOR RAPE, INCEST, AND THE LIFE OF THE MOTHER. I DO NOT SUPPORT THE DEMOCRATS RADICAL POSITION OF LATE TERM ABORTION LIKE, AS AN EXAMPLE, IN THE 7TH, 8TH, OR 9TH MONTH OR, IN CASE THERE IS ANY QUESTION, THE POSSIBILITY OF EXECUTION OF THE BABY AFTER BIRTH. THANK YOU FOR YOUR ATTENTION TO THIS MATTER!"
|
33
|
+
}
|
34
|
+
}
|
35
|
+
],
|
36
|
+
[
|
37
|
+
{
|
38
|
+
"user": "{{user1}}",
|
39
|
+
"content": {
|
40
|
+
"text": "What about the border crisis?"
|
41
|
+
}
|
42
|
+
},
|
43
|
+
{
|
44
|
+
"user": "trump",
|
45
|
+
"content": {
|
46
|
+
"text": "Comrade Kamala Harris and Crooked Joe Biden are letting in THOUSANDS and THOUSANDS of Violent Murderers and Rapists into our Country. I secured the Southern Border - They have DESTROYED it. Border Czar Kamala has let in millions of illegal guns into our Country. She is a DANGER to our Kids, and our Schools!"
|
47
|
+
}
|
48
|
+
}
|
49
|
+
],
|
50
|
+
[
|
51
|
+
{
|
52
|
+
"user": "{{user1}}",
|
53
|
+
"content": {
|
54
|
+
"text": "How will you fix the economy?"
|
55
|
+
}
|
56
|
+
},
|
57
|
+
{
|
58
|
+
"user": "trump",
|
59
|
+
"content": {
|
60
|
+
"text": "If Kamala is reelected, one of her very first acts will be to MASSIVELY raise taxes on American Families. Kamala Harris is the TAX QUEEN. She has already cost the average family $29,000 with rampant inflation— Now, she is coming back for more. We will MAKE AMERICA AFFORDABLE AGAIN!"
|
61
|
+
}
|
62
|
+
}
|
63
|
+
],
|
64
|
+
[
|
65
|
+
{
|
66
|
+
"user": "{{user1}}",
|
67
|
+
"content": {
|
68
|
+
"text": "What about the global situation?"
|
69
|
+
}
|
70
|
+
},
|
71
|
+
{
|
72
|
+
"user": "trump",
|
73
|
+
"content": {
|
74
|
+
"text": "Look at the World today — Look at the missiles flying right now in the Middle East, look at what's happening with Russia/Ukraine, look at Inflation destroying the World. NONE OF THIS HAPPENED WHILE I WAS PRESIDENT! They destroyed everything we built, but we'll fix it all on DAY ONE!"
|
75
|
+
}
|
76
|
+
}
|
77
|
+
],
|
78
|
+
[
|
79
|
+
{
|
80
|
+
"user": "{{user1}}",
|
81
|
+
"content": {
|
82
|
+
"text": "What's happening with crypto?"
|
83
|
+
}
|
84
|
+
},
|
85
|
+
{
|
86
|
+
"user": "trump",
|
87
|
+
"content": {
|
88
|
+
"text": "I promised to Make America Great Again, this time with crypto. WorldLibertyFi is planning to help make America the crypto capital of the world! The whitelist for eligible persons is officially open – this is your chance to be part of this historic moment. Maybe we'll even pay off our $35 trillion debt with a Bitcoin check!"
|
89
|
+
}
|
90
|
+
}
|
91
|
+
],
|
92
|
+
[
|
93
|
+
{
|
94
|
+
"user": "{{user1}}",
|
95
|
+
"content": {
|
96
|
+
"text": "Why are they after you?"
|
97
|
+
}
|
98
|
+
},
|
99
|
+
{
|
100
|
+
"user": "trump",
|
101
|
+
"content": {
|
102
|
+
"text": "The Democrat Party is guilty of the Worst Election Interference in American History. They are trying to DESTROY OUR DEMOCRACY, allowing millions of people to enter our Country illegally. They are determined to stop us from winning back the White House, sealing the Border, and MAKING AMERICA GREAT AGAIN. BUT THEY WILL FAIL, AND WE WILL SAVE OUR NATION!"
|
103
|
+
}
|
104
|
+
}
|
105
|
+
],
|
106
|
+
[
|
107
|
+
{
|
108
|
+
"user": "{{user1}}",
|
109
|
+
"content": {
|
110
|
+
"text": "What about the Secret Service?"
|
111
|
+
}
|
112
|
+
},
|
113
|
+
{
|
114
|
+
"user": "trump",
|
115
|
+
"content": {
|
116
|
+
"text": "The Democrats are interfering with my Campaign by not giving us the proper number of people within Secret Service that are necessary for Security. They're using them for themselves, even though they don't need them - they draw flies - because they have no crowds, and for people like the President of Iran, who is doing everything possible to kill me. We need more Secret Service, and we need them NOW!"
|
117
|
+
}
|
118
|
+
}
|
119
|
+
]
|
120
|
+
],
|
121
|
+
"postExamples": [
|
122
|
+
],
|
123
|
+
"topics": [
|
124
|
+
],
|
125
|
+
"style": {
|
126
|
+
"all": [
|
127
|
+
"uses FULL CAPS for key phrases and emphasis",
|
128
|
+
"specific number citations ($29,000, THOUSANDS)",
|
129
|
+
"direct opponent naming (Lyin' Kamala, Tampon Tim)",
|
130
|
+
"uses parentheses for additional commentary",
|
131
|
+
"contrasts THEN vs NOW situations",
|
132
|
+
"emphasizes state-specific issues",
|
133
|
+
"references God and American strength",
|
134
|
+
"uses direct cause-and-effect statements",
|
135
|
+
"mentions specific locations by name",
|
136
|
+
"employs military and security terminology",
|
137
|
+
"cites specific policy positions",
|
138
|
+
"uses repetitive phrasing for emphasis",
|
139
|
+
"references current global events",
|
140
|
+
"employs clear contrast statements (WE vs THEY)",
|
141
|
+
"mentions specific crimes and threats",
|
142
|
+
"uses exact dates and times",
|
143
|
+
"references specific laws and rights",
|
144
|
+
"employs religious and patriotic themes",
|
145
|
+
"uses dramatic future predictions",
|
146
|
+
"emphasizes personal involvement in solutions"
|
147
|
+
],
|
148
|
+
"chat": [
|
149
|
+
"directly addresses questioner's concerns",
|
150
|
+
"pivots to broader policy issues",
|
151
|
+
"cites specific numbers and statistics",
|
152
|
+
"references personal accomplishments",
|
153
|
+
"contrasts past successes with current failures",
|
154
|
+
"predicts future consequences",
|
155
|
+
"emphasizes immediate solutions",
|
156
|
+
"mentions specific opponents by name",
|
157
|
+
"uses repetition for emphasis",
|
158
|
+
"incorporates current events",
|
159
|
+
"references specific locations",
|
160
|
+
"employs dramatic comparisons",
|
161
|
+
"uses rhetorical questions",
|
162
|
+
"emphasizes American values",
|
163
|
+
"mentions God and faith",
|
164
|
+
"cites specific laws and policies",
|
165
|
+
"references crowd sizes",
|
166
|
+
"mentions security concerns",
|
167
|
+
"emphasizes states' rights",
|
168
|
+
"uses personal testimonials"
|
169
|
+
],
|
170
|
+
"post": [
|
171
|
+
"uses ALL CAPS for key points",
|
172
|
+
"employs exclamation points frequently",
|
173
|
+
"references specific policies",
|
174
|
+
"names opponents directly",
|
175
|
+
"cites exact numbers",
|
176
|
+
"uses location-specific references",
|
177
|
+
"mentions current events",
|
178
|
+
"employs dramatic contrasts",
|
179
|
+
"uses parenthetical asides",
|
180
|
+
"emphasizes personal strength",
|
181
|
+
"references God and faith",
|
182
|
+
"mentions security issues",
|
183
|
+
"uses dramatic predictions",
|
184
|
+
"employs rhetorical questions",
|
185
|
+
"references specific threats",
|
186
|
+
"mentions crowd sizes",
|
187
|
+
"uses legal terminology",
|
188
|
+
"employs patriotic themes",
|
189
|
+
"emphasizes immediate action",
|
190
|
+
"references specific dates"
|
191
|
+
]
|
192
|
+
},
|
193
|
+
"adjectives": [
|
194
|
+
]
|
195
|
+
}
|
package/index.mjs
CHANGED
@@ -10,7 +10,6 @@ import {
|
|
10
10
|
runCharacter,
|
11
11
|
getPluginType,
|
12
12
|
installNpmPackages,
|
13
|
-
buildNpmPackages,
|
14
13
|
} from "./util.mjs";
|
15
14
|
|
16
15
|
const main = async () => {
|
@@ -48,7 +47,6 @@ const main = async () => {
|
|
48
47
|
.action(async (packages) => {
|
49
48
|
try {
|
50
49
|
await installNpmPackages(packages);
|
51
|
-
await buildNpmPackages(packages);
|
52
50
|
} catch (error) {
|
53
51
|
console.error(`Error in install command: ${error.message}`);
|
54
52
|
}
|
@@ -84,58 +82,8 @@ const main = async () => {
|
|
84
82
|
}
|
85
83
|
|
86
84
|
await installNpmPackages([...pluginsToInstall]);
|
87
|
-
await buildNpmPackages([...pluginsToInstall]);
|
88
85
|
} catch (error) {
|
89
|
-
console.error(`Error in installall command: ${error.
|
90
|
-
}
|
91
|
-
process.exit(1);
|
92
|
-
});
|
93
|
-
|
94
|
-
program
|
95
|
-
.command('build')
|
96
|
-
.alias('b')
|
97
|
-
.description('Build packages without installing them')
|
98
|
-
.argument('<packages...>', 'packages to build')
|
99
|
-
.action(async (packages) => {
|
100
|
-
try {
|
101
|
-
await buildNpmPackages(packages);
|
102
|
-
} catch (error) {
|
103
|
-
console.error(`Error in build command: ${error.message}`);
|
104
|
-
}
|
105
|
-
process.exit(1);
|
106
|
-
});
|
107
|
-
|
108
|
-
program
|
109
|
-
.command('buildall')
|
110
|
-
.alias('ba')
|
111
|
-
.description('Build all plugins from character.json files')
|
112
|
-
.argument('<files...>', 'character.json file paths')
|
113
|
-
.action(async (files) => {
|
114
|
-
try {
|
115
|
-
const pluginsToBuild = new Set();
|
116
|
-
|
117
|
-
for (const file of files) {
|
118
|
-
const characterJsonPath = path.resolve(process.cwd(), file);
|
119
|
-
const characterJsonString = await fs.promises.readFile(characterJsonPath, 'utf8');
|
120
|
-
const characterJson = JSON.parse(characterJsonString);
|
121
|
-
|
122
|
-
if (characterJson.plugins && Array.isArray(characterJson.plugins)) {
|
123
|
-
characterJson.plugins.forEach(plugin => {
|
124
|
-
if (getPluginType(plugin) === 'npm') {
|
125
|
-
pluginsToBuild.add(plugin);
|
126
|
-
}
|
127
|
-
});
|
128
|
-
}
|
129
|
-
}
|
130
|
-
|
131
|
-
if (pluginsToBuild.size === 0) {
|
132
|
-
console.log('No plugins found to build');
|
133
|
-
return;
|
134
|
-
}
|
135
|
-
|
136
|
-
await buildNpmPackages([...pluginsToBuild]);
|
137
|
-
} catch (error) {
|
138
|
-
console.error(`Error in buildall command: ${error.message}`);
|
86
|
+
console.error(`Error in installall command: ${error.stack}`);
|
139
87
|
}
|
140
88
|
process.exit(1);
|
141
89
|
});
|
package/package.json
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "mastra-starter",
|
3
|
-
"version": "1.0.
|
3
|
+
"version": "1.0.9",
|
4
4
|
"main": "index.mjs",
|
5
5
|
"bin": {
|
6
6
|
"mastra-starter": "./index.mjs"
|
7
7
|
},
|
8
8
|
"scripts": {
|
9
|
-
"test": "node index.mjs installall
|
9
|
+
"test": "node index.mjs installall chad.character.json; node index.mjs dev chad.character.json;"
|
10
10
|
},
|
11
11
|
"keywords": [],
|
12
12
|
"author": "",
|
@@ -16,13 +16,15 @@
|
|
16
16
|
"dependencies": {
|
17
17
|
"@ai-sdk/openai": "^1.2.2",
|
18
18
|
"@mastra/composio": "^0.1.9",
|
19
|
-
"@mastra/core": "^0.
|
19
|
+
"@mastra/core": "^0.6.0",
|
20
20
|
"@mastra/mcp": "^0.3.0",
|
21
21
|
"commander": "^13.1.0",
|
22
22
|
"dedent": "^1.5.3",
|
23
23
|
"dotenv": "^16.4.7",
|
24
24
|
"mastra": "^0.3.0",
|
25
|
+
"mkdirp": "^3.0.1",
|
25
26
|
"pnpm-package-lookup": "^0.0.2",
|
27
|
+
"rimraf": "^6.0.1",
|
26
28
|
"yaml": "^2.7.0",
|
27
29
|
"zod": "^3.24.2"
|
28
30
|
},
|
@@ -1,44 +1,82 @@
|
|
1
|
-
import fs from
|
2
|
-
import path from
|
3
|
-
import {
|
4
|
-
import { Agent, ToolsInput } from
|
5
|
-
import dedent from
|
6
|
-
import { MCPConfiguration } from "@mastra/mcp";
|
7
|
-
import { ComposioIntegration } from '@mastra/composio';
|
8
|
-
import { sortPlugins } from '../../../util.mjs';
|
1
|
+
import fs from "fs";
|
2
|
+
import path from "path";
|
3
|
+
import { createOpenAI } from "@ai-sdk/openai";
|
4
|
+
import { Agent, ToolsInput } from "@mastra/core/agent";
|
5
|
+
import dedent from "dedent";
|
9
6
|
import { PnpmPackageLookup } from 'pnpm-package-lookup';
|
7
|
+
import { MCPConfiguration } from "@mastra/mcp";
|
8
|
+
import { ComposioIntegration } from "@mastra/composio";
|
9
|
+
import { sortPlugins, getNpmPackageType } from "../../../util.mjs";
|
10
|
+
|
11
|
+
const rootDir = path.resolve(process.cwd(), "..", "..");
|
10
12
|
|
11
|
-
// character
|
12
|
-
const packageLookup = new PnpmPackageLookup({
|
13
|
-
pnpmLockYamlPath: path.join('..', '..', 'pnpm-lock.yaml'),
|
14
|
-
});
|
15
13
|
const characterJsonPath = process.env._CHARACTER_JSON_PATH as string;
|
16
|
-
const characterJsonString = await fs.promises.readFile(
|
14
|
+
const characterJsonString = await fs.promises.readFile(
|
15
|
+
characterJsonPath,
|
16
|
+
"utf8"
|
17
|
+
);
|
17
18
|
const characterJson = JSON.parse(characterJsonString);
|
18
19
|
|
19
20
|
// sort plugins
|
20
21
|
const { plugins = [] } = characterJson;
|
21
|
-
const {
|
22
|
-
npm: npmPlugins,
|
23
|
-
composio: composioPlugins,
|
24
|
-
} = sortPlugins(plugins);
|
22
|
+
const { npm: npmPlugins, composio: composioPlugins } = sortPlugins(plugins);
|
25
23
|
|
26
24
|
// resolve npm plugins
|
27
25
|
const servers: Record<string, any> = {};
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
26
|
+
const pnpmLockYamlPath = path.resolve(rootDir, "pnpm-lock.yaml");
|
27
|
+
const pnpmPackageLookup = new PnpmPackageLookup({
|
28
|
+
pnpmLockYamlPath,
|
29
|
+
});
|
30
|
+
for (const pluginSpecifier of npmPlugins) {
|
31
|
+
const npmPackageType = getNpmPackageType(pluginSpecifier);
|
32
|
+
|
33
|
+
let pluginSpecifier2;
|
34
|
+
const packagesDir = path.resolve(rootDir, "packages");
|
35
|
+
if (npmPackageType === "github") {
|
36
|
+
const packageBasename = path.basename(pluginSpecifier.replace("github:", ""));
|
37
|
+
const packageResolvedName = `file:${path.resolve(packagesDir, packageBasename)}`;
|
38
|
+
pluginSpecifier2 = await pnpmPackageLookup.getPackageNameBySpecifier(packageResolvedName);
|
39
|
+
if (!pluginSpecifier2) {
|
40
|
+
throw new Error(`Could not resolve package name for ${JSON.stringify({
|
41
|
+
pluginSpecifier,
|
42
|
+
packageBasename,
|
43
|
+
packageResolvedName,
|
44
|
+
}, null, 2)}`);
|
45
|
+
}
|
46
|
+
} else {
|
47
|
+
pluginSpecifier2 = pluginSpecifier;
|
33
48
|
}
|
49
|
+
const packagePath = path.resolve(rootDir, "node_modules", pluginSpecifier2);
|
50
|
+
// console.log('packagePath', {
|
51
|
+
// pluginSpecifier,
|
52
|
+
// pluginSpecifier2,
|
53
|
+
// packagePath,
|
54
|
+
// });
|
34
55
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
56
|
+
// check if start script exists
|
57
|
+
const packageJsonPath = path.resolve(packagePath, "package.json");
|
58
|
+
const packageJson = JSON.parse(await fs.promises.readFile(packageJsonPath, "utf8"));
|
59
|
+
if (packageJson.scripts.start) {
|
60
|
+
servers[pluginSpecifier] = {
|
61
|
+
command: "pnpm",
|
62
|
+
args: ["--dir", packagePath, "--silent", "start"],
|
63
|
+
env: process.env as any,
|
64
|
+
};
|
65
|
+
} else {
|
66
|
+
// check if any bins exist; if so, use the first one
|
67
|
+
if (packageJson.bin && Object.keys(packageJson.bin).length > 0) {
|
68
|
+
const firstBin = Object.keys(packageJson.bin)[0];
|
69
|
+
servers[pluginSpecifier] = {
|
70
|
+
command: "pnpm",
|
71
|
+
args: ["--dir", packagePath, "--silent", "exec", firstBin],
|
72
|
+
env: process.env as any,
|
73
|
+
};
|
74
|
+
} else {
|
75
|
+
throw new Error(`No start script or bins found for ${pluginSpecifier}`);
|
76
|
+
}
|
77
|
+
}
|
41
78
|
}
|
79
|
+
// console.log('servers', servers);
|
42
80
|
|
43
81
|
// mcp tools
|
44
82
|
const mcp = new MCPConfiguration({
|
@@ -54,7 +92,7 @@ if (composioApiKey && composioAccountId) {
|
|
54
92
|
const composio = new ComposioIntegration({
|
55
93
|
config: {
|
56
94
|
API_KEY: composioApiKey,
|
57
|
-
entityId:
|
95
|
+
entityId: "default",
|
58
96
|
connectedAccountId: composioAccountId,
|
59
97
|
},
|
60
98
|
});
|
@@ -63,21 +101,31 @@ if (composioApiKey && composioAccountId) {
|
|
63
101
|
// 'GITHUB_ACTIVITY_LIST_STARGAZERS_FOR_REPO',
|
64
102
|
// 'GITHUB_GET_OCTOCAT',
|
65
103
|
// ];
|
66
|
-
const actionsEnums = composioPlugins.map((plugin: string) =>
|
67
|
-
|
104
|
+
const actionsEnums = composioPlugins.map((plugin: string) =>
|
105
|
+
plugin.replace("composio:", "")
|
106
|
+
);
|
107
|
+
composioToolset = (await composio.getTools({
|
68
108
|
actions: actionsEnums,
|
69
|
-
}) as ToolsInput;
|
109
|
+
})) as ToolsInput;
|
70
110
|
}
|
71
111
|
|
72
112
|
// agent
|
113
|
+
const model = createOpenAI({
|
114
|
+
baseURL: process.env.OPENAI_API_URL || "https://api.openai.com/v1",
|
115
|
+
apiKey: process.env.OPENAI_API_KEY,
|
116
|
+
})("gpt-4o");
|
73
117
|
export const characterAgent = new Agent({
|
74
118
|
name: "Character",
|
75
|
-
instructions:
|
119
|
+
instructions:
|
120
|
+
dedent`\
|
76
121
|
You are the following character:
|
77
|
-
` +
|
78
|
-
|
79
|
-
|
122
|
+
` +
|
123
|
+
"\n" +
|
124
|
+
JSON.stringify(characterJson, null, 2),
|
125
|
+
model,
|
126
|
+
tools: {
|
127
|
+
// ToolsInput = string -> ToolAction
|
80
128
|
...mcpTools,
|
81
129
|
...composioToolset,
|
82
130
|
},
|
83
|
-
});
|
131
|
+
});
|
@@ -0,0 +1,23 @@
|
|
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
|
+
};
|
package/util.d.ts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
declare module "util.mjs";
|
package/util.mjs
CHANGED
@@ -1,12 +1,16 @@
|
|
1
|
-
import path from
|
1
|
+
import path from "path";
|
2
|
+
import fs from "fs";
|
2
3
|
import child_process from "child_process";
|
3
|
-
import {
|
4
|
+
import { mkdirp } from "mkdirp";
|
5
|
+
import { rimraf } from "rimraf";
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
// const uniquify = (array) => {
|
8
|
+
// return [...new Set(array)];
|
9
|
+
// };
|
10
|
+
|
11
|
+
export const runCharacter = async (characterJsonPath, { env = {} } = {}) => {
|
12
|
+
const mastraPath = import.meta.resolve("mastra").replace("file://", "");
|
13
|
+
const cp = child_process.spawn(process.execPath, [mastraPath, "dev"], {
|
10
14
|
env: {
|
11
15
|
...env,
|
12
16
|
_CHARACTER_JSON_PATH: characterJsonPath,
|
@@ -14,27 +18,27 @@ export const runCharacter = async (characterJsonPath, {
|
|
14
18
|
});
|
15
19
|
cp.stdout.pipe(process.stdout);
|
16
20
|
cp.stderr.pipe(process.stderr);
|
17
|
-
|
21
|
+
|
18
22
|
return new Promise((resolve, reject) => {
|
19
|
-
cp.on(
|
23
|
+
cp.on("close", (code) => {
|
20
24
|
if (code !== 0) {
|
21
25
|
reject(new Error(`Process exited with code ${code}`));
|
22
26
|
} else {
|
23
27
|
resolve();
|
24
28
|
}
|
25
29
|
});
|
26
|
-
|
27
|
-
cp.on(
|
30
|
+
|
31
|
+
cp.on("error", (error) => {
|
28
32
|
reject(error);
|
29
33
|
});
|
30
34
|
});
|
31
35
|
};
|
32
36
|
|
33
37
|
export const getPluginType = (plugin) => {
|
34
|
-
if (plugin.startsWith(
|
35
|
-
return
|
38
|
+
if (plugin.startsWith("composio:")) {
|
39
|
+
return "composio";
|
36
40
|
} else {
|
37
|
-
return
|
41
|
+
return "npm";
|
38
42
|
}
|
39
43
|
};
|
40
44
|
export const sortPlugins = (plugins) => {
|
@@ -42,9 +46,9 @@ export const sortPlugins = (plugins) => {
|
|
42
46
|
const composio = [];
|
43
47
|
for (const plugin of plugins) {
|
44
48
|
const pluginType = getPluginType(plugin);
|
45
|
-
if (pluginType ===
|
49
|
+
if (pluginType === "npm") {
|
46
50
|
npm.push(plugin);
|
47
|
-
} else if (pluginType ===
|
51
|
+
} else if (pluginType === "composio") {
|
48
52
|
composio.push(plugin);
|
49
53
|
}
|
50
54
|
}
|
@@ -54,82 +58,192 @@ export const sortPlugins = (plugins) => {
|
|
54
58
|
};
|
55
59
|
};
|
56
60
|
|
57
|
-
export const
|
58
|
-
|
61
|
+
export const getNpmPackageType = (packageSpecifier) => {
|
62
|
+
if (packageSpecifier.startsWith("github:")) {
|
63
|
+
return "github";
|
64
|
+
} else {
|
65
|
+
return "npm";
|
66
|
+
}
|
67
|
+
};
|
68
|
+
export const sortNpmPackages = (packageSpecifiers) => {
|
69
|
+
const github = [];
|
70
|
+
const npm = [];
|
71
|
+
for (const packageSpecifier of packageSpecifiers) {
|
72
|
+
const packageType = getNpmPackageType(packageSpecifier);
|
73
|
+
if (packageType === "github") {
|
74
|
+
github.push(packageSpecifier);
|
75
|
+
} else {
|
76
|
+
npm.push(packageSpecifier);
|
77
|
+
}
|
78
|
+
}
|
79
|
+
return { github, npm };
|
80
|
+
};
|
81
|
+
const installNpmGithubPackages = async (packageSpecifiers) => {
|
82
|
+
console.log(`Installing github packages: ${packageSpecifiers.join(", ")}`);
|
59
83
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
84
|
+
// Ensure packages directory exists
|
85
|
+
const packagesDir = path.resolve(process.cwd(), "packages");
|
86
|
+
try {
|
87
|
+
await mkdirp(packagesDir);
|
88
|
+
} catch (error) {
|
89
|
+
console.error(`Error creating packages directory: ${error.stack}`);
|
90
|
+
return Promise.reject(error);
|
91
|
+
}
|
92
|
+
|
93
|
+
// remove conflicting package directories
|
94
|
+
const existingPackageNames = await fs.promises.readdir(packagesDir);
|
95
|
+
for (const packageName of existingPackageNames) {
|
96
|
+
const packagePath = path.resolve(packagesDir, packageName);
|
97
|
+
await rimraf(packagePath);
|
98
|
+
}
|
99
|
+
|
100
|
+
// git clone all packages
|
101
|
+
await new Promise((resolve, reject) => {
|
102
|
+
const repoNames = packageSpecifiers.map((specifier) => {
|
103
|
+
specifier = specifier.replace("github:", "");
|
104
|
+
specifier = `https://github.com/${specifier}`;
|
105
|
+
return specifier;
|
64
106
|
});
|
107
|
+
const cp = child_process.spawn(
|
108
|
+
"git",
|
109
|
+
["clone", "--depth", "1", ...repoNames],
|
110
|
+
{
|
111
|
+
stdio: "inherit",
|
112
|
+
cwd: packagesDir,
|
113
|
+
}
|
114
|
+
);
|
65
115
|
|
66
116
|
cp.on("error", (error) => {
|
67
|
-
console.error(`Error executing
|
117
|
+
console.error(`Error executing git clone: ${error.stack}`);
|
68
118
|
reject(error);
|
69
119
|
});
|
70
120
|
|
71
121
|
cp.on("close", (code) => {
|
72
122
|
if (code !== 0) {
|
73
|
-
console.error(`
|
74
|
-
reject(new Error(`
|
123
|
+
console.error(`git clone exited with code ${code}`);
|
124
|
+
reject(new Error(`git clone exited with code ${code}`));
|
75
125
|
} else {
|
76
126
|
resolve();
|
77
127
|
}
|
78
128
|
});
|
79
129
|
});
|
80
|
-
};
|
81
|
-
export const buildNpmPackages = async (packageSpecifiers) => {
|
82
|
-
console.log(`Building packages: ${packageSpecifiers.join(", ")}`);
|
83
130
|
|
84
|
-
//
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
const packagePaths = await Promise.all(packageSpecifiers.map(async (packageSpecifier) => {
|
89
|
-
return await packageLookup.getPackageNameBySpecifier(packageSpecifier);
|
90
|
-
}));
|
131
|
+
// pnpm install in local directory
|
132
|
+
await Promise.all(packageSpecifiers.map(async (packageSpecifier) => {
|
133
|
+
const packageBasename = path.basename(packageSpecifier.replace("github:", ""));
|
134
|
+
const packagePath = path.resolve(packagesDir, packageBasename);
|
91
135
|
|
92
|
-
|
93
|
-
|
136
|
+
await new Promise((resolveInstall, rejectInstall) => {
|
137
|
+
const cp = child_process.spawn("pnpm", ["install"], {
|
138
|
+
stdio: "inherit",
|
139
|
+
cwd: packagePath,
|
140
|
+
env: { ...process.env },
|
141
|
+
});
|
142
|
+
|
143
|
+
cp.on("error", (error) => {
|
144
|
+
console.error(
|
145
|
+
`Error executing pnpm install for ${packageBasename}: ${error.stack}`
|
146
|
+
);
|
147
|
+
rejectInstall(error);
|
148
|
+
});
|
149
|
+
cp.on("close", (code) => {
|
150
|
+
if (code !== 0) {
|
151
|
+
rejectInstall(new Error(`pnpm install exited with code ${code}`));
|
152
|
+
} else {
|
153
|
+
resolveInstall();
|
154
|
+
}
|
155
|
+
});
|
156
|
+
});
|
94
157
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
try {
|
99
|
-
const p = path.resolve(process.cwd(), 'node_modules', packagePath);
|
158
|
+
// pnpm build
|
159
|
+
// note: this is advisory and allowed to fail
|
160
|
+
await new Promise((resolveSpawn, rejectSpawn) => {
|
100
161
|
const cp = child_process.spawn("pnpm", ["build"], {
|
101
162
|
stdio: "inherit",
|
102
|
-
cwd:
|
163
|
+
cwd: packagePath,
|
103
164
|
env: { ...process.env },
|
104
165
|
});
|
105
166
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
167
|
+
cp.on("error", (error) => {
|
168
|
+
console.error(
|
169
|
+
`Error executing pnpm build for ${packageBasename}: ${error.stack}`
|
170
|
+
);
|
171
|
+
resolveSpawn({
|
172
|
+
success: false,
|
173
|
+
package: packageBasename,
|
174
|
+
error: error.stack,
|
110
175
|
});
|
176
|
+
});
|
177
|
+
cp.on("close", (code) => {
|
178
|
+
if (code !== 0) {
|
179
|
+
console.error(
|
180
|
+
`pnpm build for ${packageBasename} exited with code ${code}`
|
181
|
+
);
|
182
|
+
resolveSpawn({
|
183
|
+
success: false,
|
184
|
+
package: packageBasename,
|
185
|
+
error: `exited with code ${code}`,
|
186
|
+
});
|
187
|
+
} else {
|
188
|
+
console.log(`Build completed successfully for ${packageBasename}`);
|
189
|
+
resolveSpawn({ success: true, package: packageBasename });
|
190
|
+
}
|
191
|
+
});
|
192
|
+
});
|
111
193
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
resolveSpawn({ success: true, package: packagePath });
|
119
|
-
}
|
120
|
-
});
|
194
|
+
// pnpm install to app
|
195
|
+
await new Promise((resolveInstall, rejectInstall) => {
|
196
|
+
const cp = child_process.spawn("pnpm", ["install", `file:${packagePath}`], {
|
197
|
+
stdio: "inherit",
|
198
|
+
cwd: process.cwd(),
|
199
|
+
env: { ...process.env },
|
121
200
|
});
|
122
201
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
202
|
+
cp.on("error", (error) => {
|
203
|
+
console.error(
|
204
|
+
`Error executing pnpm install for ${packageBasename}: ${error.stack}`
|
205
|
+
);
|
206
|
+
rejectInstall(error);
|
207
|
+
});
|
208
|
+
cp.on("close", (code) => {
|
209
|
+
if (code !== 0) {
|
210
|
+
rejectInstall(new Error(`pnpm install exited with code ${code}`));
|
211
|
+
} else {
|
212
|
+
resolveInstall();
|
213
|
+
}
|
214
|
+
});
|
215
|
+
});
|
216
|
+
}));
|
217
|
+
};
|
218
|
+
const installNpmBasicPackages = async (packageSpecifiers) => {
|
219
|
+
// packageSpecifiers = uniquify(packageSpecifiers);
|
220
|
+
console.log(`Installing npm basic packages: ${packageSpecifiers.join(", ")}`);
|
221
|
+
|
222
|
+
const cp = child_process.spawn("pnpm", ["install", ...packageSpecifiers], {
|
223
|
+
stdio: "inherit",
|
224
|
+
cwd: process.cwd(),
|
225
|
+
});
|
133
226
|
|
134
|
-
return
|
227
|
+
return new Promise((resolve, reject) => {
|
228
|
+
cp.on("error", (error) => {
|
229
|
+
reject(error);
|
230
|
+
});
|
231
|
+
|
232
|
+
cp.on("close", (code) => {
|
233
|
+
if (code !== 0) {
|
234
|
+
reject(new Error(`pnpm install exited with code ${code}`));
|
235
|
+
} else {
|
236
|
+
resolve();
|
237
|
+
}
|
238
|
+
});
|
239
|
+
});
|
135
240
|
};
|
241
|
+
export const installNpmPackages = async (packageSpecifiers) => {
|
242
|
+
console.log(`Installing packages: ${packageSpecifiers.join(", ")}`);
|
243
|
+
|
244
|
+
const { github, npm } = sortNpmPackages(packageSpecifiers);
|
245
|
+
await Promise.all([
|
246
|
+
installNpmGithubPackages(github),
|
247
|
+
installNpmBasicPackages(npm)
|
248
|
+
]);
|
249
|
+
};
|
@@ -1,45 +0,0 @@
|
|
1
|
-
#!/usr/bin/env node
|
2
|
-
|
3
|
-
import { mastra } from "..";
|
4
|
-
import readline from "readline";
|
5
|
-
|
6
|
-
// Create readline interface
|
7
|
-
const rl = readline.createInterface({
|
8
|
-
input: process.stdin,
|
9
|
-
output: process.stdout,
|
10
|
-
});
|
11
|
-
|
12
|
-
console.log("🌤️ Weather Agent CLI");
|
13
|
-
console.log('Type your weather questions (e.g., "What\'s the weather in London today?")');
|
14
|
-
console.log('Type "exit" to quit\n');
|
15
|
-
|
16
|
-
// Main interaction loop
|
17
|
-
function askQuestion() {
|
18
|
-
rl.question("> ", async (input) => {
|
19
|
-
if (input.toLowerCase() === "exit") {
|
20
|
-
console.log("Goodbye! 👋");
|
21
|
-
rl.close();
|
22
|
-
return;
|
23
|
-
}
|
24
|
-
|
25
|
-
try {
|
26
|
-
console.log("Fetching weather information...");
|
27
|
-
const response = await mastra.run({
|
28
|
-
agent: "weatherAgent",
|
29
|
-
input,
|
30
|
-
});
|
31
|
-
|
32
|
-
console.log("\nResponse:");
|
33
|
-
console.log(response);
|
34
|
-
console.log(); // Empty line for better readability
|
35
|
-
} catch (error) {
|
36
|
-
console.error("Error:", error.message);
|
37
|
-
}
|
38
|
-
|
39
|
-
// Continue the conversation
|
40
|
-
askQuestion();
|
41
|
-
});
|
42
|
-
}
|
43
|
-
|
44
|
-
// Start the interaction
|
45
|
-
askQuestion();
|