mastra-starter 1.0.5 → 1.0.6

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/.env.example ADDED
@@ -0,0 +1,2 @@
1
+ OPENAI_API_KEY=
2
+ COMPOSIO_API_KEY=
package/index.mjs CHANGED
@@ -6,7 +6,7 @@ import fs from 'fs';
6
6
  import { Command } from 'commander';
7
7
  import dotenv from 'dotenv';
8
8
 
9
- import { runCharacter, installPackages } from './util.mjs';
9
+ import { runCharacter, installPackages, buildPackages } from './util.mjs';
10
10
 
11
11
  const main = async () => {
12
12
  dotenv.config();
@@ -43,6 +43,7 @@ const main = async () => {
43
43
  .action(async (packages) => {
44
44
  try {
45
45
  await installPackages(packages);
46
+ await buildPackages(packages);
46
47
  } catch (error) {
47
48
  console.error(`Error in install command: ${error.message}`);
48
49
  }
@@ -74,12 +75,58 @@ const main = async () => {
74
75
  }
75
76
 
76
77
  await installPackages([...pluginsToInstall]);
78
+ await buildPackages([...pluginsToInstall]);
77
79
  } catch (error) {
78
80
  console.error(`Error in installall command: ${error.message}`);
79
81
  }
80
82
  process.exit(1);
81
83
  });
82
84
 
85
+ program
86
+ .command('build')
87
+ .alias('b')
88
+ .description('Build packages without installing them')
89
+ .argument('<packages...>', 'packages to build')
90
+ .action(async (packages) => {
91
+ try {
92
+ await buildPackages(packages);
93
+ } catch (error) {
94
+ console.error(`Error in build command: ${error.message}`);
95
+ }
96
+ process.exit(1);
97
+ });
98
+
99
+ program
100
+ .command('buildall')
101
+ .alias('ba')
102
+ .description('Build all plugins from character.json files')
103
+ .argument('<files...>', 'character.json file paths')
104
+ .action(async (files) => {
105
+ try {
106
+ const pluginsToBuild = new Set();
107
+
108
+ for (const file of files) {
109
+ const characterJsonPath = path.resolve(process.cwd(), file);
110
+ const characterJsonString = await fs.promises.readFile(characterJsonPath, 'utf8');
111
+ const characterJson = JSON.parse(characterJsonString);
112
+
113
+ if (characterJson.plugins && Array.isArray(characterJson.plugins)) {
114
+ characterJson.plugins.forEach(plugin => pluginsToBuild.add(plugin));
115
+ }
116
+ }
117
+
118
+ if (pluginsToBuild.size === 0) {
119
+ console.log('No plugins found to build');
120
+ return;
121
+ }
122
+
123
+ await buildPackages([...pluginsToBuild]);
124
+ } catch (error) {
125
+ console.error(`Error in buildall command: ${error.message}`);
126
+ }
127
+ process.exit(1);
128
+ });
129
+
83
130
  program.parse(process.argv);
84
131
  };
85
132
  (async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mastra-starter",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "main": "index.mjs",
5
5
  "bin": {
6
6
  "mastra-starter": "./index.mjs"
@@ -15,13 +15,14 @@
15
15
  "type": "module",
16
16
  "dependencies": {
17
17
  "@ai-sdk/openai": "^1.2.2",
18
+ "@mastra/composio": "^0.1.9",
18
19
  "@mastra/core": "^0.5.0",
19
20
  "@mastra/mcp": "^0.3.0",
20
21
  "commander": "^13.1.0",
21
22
  "dedent": "^1.5.3",
22
23
  "dotenv": "^16.4.7",
23
24
  "mastra": "^0.3.0",
24
- "pnpm-package-lookup": "^0.0.1",
25
+ "pnpm-package-lookup": "^0.0.2",
25
26
  "yaml": "^2.7.0",
26
27
  "zod": "^3.24.2"
27
28
  },
@@ -1,22 +1,35 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
3
  import { openai } from '@ai-sdk/openai';
4
- import { Agent } from '@mastra/core/agent';
4
+ import { Agent, ToolsInput } from '@mastra/core/agent';
5
5
  import dedent from 'dedent';
6
6
  import { MCPConfiguration } from "@mastra/mcp";
7
+ import { ComposioIntegration } from '@mastra/composio';
7
8
  import { PnpmPackageLookup } from 'pnpm-package-lookup';
8
9
 
10
+ // character
9
11
  const packageLookup = new PnpmPackageLookup({
10
12
  pnpmLockYamlPath: path.join('..', '..', 'pnpm-lock.yaml'),
11
13
  });
12
-
13
14
  const characterJsonPath = process.env._CHARACTER_JSON_PATH as string;
14
15
  const characterJsonString = await fs.promises.readFile(characterJsonPath, 'utf8');
15
16
  const characterJson = JSON.parse(characterJsonString);
17
+
18
+ // sort plugins
16
19
  const { plugins = [] } = characterJson;
20
+ const npmPlugins: string[] = [];
21
+ const composioPlugins: string[] = [];
22
+ for (const plugin of plugins) {
23
+ if (plugin.startsWith('composio:')) {
24
+ composioPlugins.push(plugin);
25
+ } else {
26
+ npmPlugins.push(plugin);
27
+ }
28
+ }
17
29
 
30
+ // resolve npm plugins
18
31
  const servers: Record<string, any> = {};
19
- for (const plugin of plugins) {
32
+ for (const plugin of npmPlugins) {
20
33
  // find the package name matching this specifier
21
34
  const packageName = await packageLookup.getPackageNameBySpecifier(plugin);
22
35
  if (!packageName) {
@@ -30,15 +43,41 @@ for (const plugin of plugins) {
30
43
  env: process.env as any,
31
44
  };
32
45
  }
46
+
47
+ // mcp tools
33
48
  const mcp = new MCPConfiguration({
34
49
  servers,
35
50
  });
51
+ const mcpTools = await mcp.getTools();
52
+
53
+ // composio tools
54
+ const composio = new ComposioIntegration({
55
+ config: {
56
+ API_KEY: process.env.COMPOSIO_API_KEY!,
57
+ entityId: 'default',
58
+ // connectedAccountId: '899144e5-a466-428b-8a00-7c931fb57f9f',
59
+ connectedAccountId: '4d79004e-320a-4dc9-be1a-1037a6fe9866',
60
+ },
61
+ });
62
+ // const actionsEnums = [
63
+ // 'GITHUB_STAR_A_REPOSITORY_FOR_THE_AUTHENTICATED_USER',
64
+ // 'GITHUB_ACTIVITY_LIST_STARGAZERS_FOR_REPO',
65
+ // 'GITHUB_GET_OCTOCAT',
66
+ // ];
67
+ const actionsEnums = composioPlugins.map((plugin) => plugin.replace('composio:', ''));
68
+ const composioToolset = await composio.getTools({
69
+ actions: actionsEnums,
70
+ }) as ToolsInput;
36
71
 
72
+ // agent
37
73
  export const characterAgent = new Agent({
38
74
  name: "Character",
39
75
  instructions: dedent`\
40
76
  You are the following character:
41
77
  ` + '\n' + JSON.stringify(characterJson, null, 2),
42
78
  model: openai("gpt-4o"),
43
- tools: { ...(await mcp.getTools()) },
79
+ tools: { // ToolsInput = string -> ToolAction
80
+ ...mcpTools,
81
+ ...composioToolset,
82
+ },
44
83
  });
package/util.mjs CHANGED
@@ -1,4 +1,6 @@
1
+ import path from 'path';
1
2
  import child_process from "child_process";
3
+ import { PnpmPackageLookup } from 'pnpm-package-lookup';
2
4
 
3
5
  export const runCharacter = async (characterJsonPath, {
4
6
  env = {},
@@ -27,7 +29,7 @@ export const runCharacter = async (characterJsonPath, {
27
29
  });
28
30
  });
29
31
  };
30
- export const installPackages = async (packageSpecifiers) => {
32
+ export const installPackages = (packageSpecifiers) => {
31
33
  console.log(`Installing packages: ${packageSpecifiers.join(", ")}`);
32
34
 
33
35
  return new Promise((resolve, reject) => {
@@ -51,3 +53,58 @@ export const installPackages = async (packageSpecifiers) => {
51
53
  });
52
54
  });
53
55
  };
56
+ export const buildPackages = async (packageSpecifiers) => {
57
+ console.log(`Building packages: ${packageSpecifiers.join(", ")}`);
58
+
59
+ // get the packagePaths from the packageSpecifiers
60
+ const packageLookup = new PnpmPackageLookup({
61
+ pnpmLockYamlPath: path.resolve(process.cwd(), 'pnpm-lock.yaml'),
62
+ });
63
+ const packagePaths = await Promise.all(packageSpecifiers.map(async (packageSpecifier) => {
64
+ return await packageLookup.getPackageNameBySpecifier(packageSpecifier);
65
+ }));
66
+
67
+ const results = [];
68
+ let allSuccessful = true;
69
+
70
+ for (const packagePath of packagePaths) {
71
+ console.log(`Building package: ${packagePath}`);
72
+
73
+ try {
74
+ const p = path.resolve(process.cwd(), 'node_modules', packagePath);
75
+ const cp = child_process.spawn("pnpm", ["build"], {
76
+ stdio: "inherit",
77
+ cwd: p,
78
+ env: { ...process.env },
79
+ });
80
+
81
+ const result = await new Promise((resolveSpawn, rejectSpawn) => {
82
+ cp.on("error", (error) => {
83
+ console.error(`Error executing pnpm build for ${packagePath}: ${error.message}`);
84
+ resolveSpawn({ success: false, package: packagePath, error: error.message });
85
+ });
86
+
87
+ cp.on("close", (code) => {
88
+ if (code !== 0) {
89
+ console.error(`pnpm build for ${packagePath} exited with code ${code}`);
90
+ resolveSpawn({ success: false, package: packagePath, error: `exited with code ${code}` });
91
+ } else {
92
+ console.log(`Build completed successfully for ${packagePath}`);
93
+ resolveSpawn({ success: true, package: packagePath });
94
+ }
95
+ });
96
+ });
97
+
98
+ results.push(result);
99
+ if (!result.success) {
100
+ allSuccessful = false;
101
+ }
102
+ } catch (error) {
103
+ console.log('error', error);
104
+ results.push({ success: false, package: packagePath, error: error.message });
105
+ allSuccessful = false;
106
+ }
107
+ }
108
+
109
+ return { success: allSuccessful, results };
110
+ };