@mastra/code-sdk 0.0.0 → 0.1.0-alpha.1
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/CHANGELOG.md +24 -0
- package/LICENSE.md +30 -0
- package/dist/plugins/dependencies.d.ts +9 -0
- package/dist/plugins/dependencies.d.ts.map +1 -0
- package/dist/plugins/dependencies.js +141 -0
- package/dist/plugins/dependencies.js.map +1 -0
- package/dist/plugins/install.d.ts +2 -1
- package/dist/plugins/install.d.ts.map +1 -1
- package/dist/plugins/install.js +24 -3
- package/dist/plugins/install.js.map +1 -1
- package/dist/plugins/manager.d.ts +1 -1
- package/dist/plugins/manager.d.ts.map +1 -1
- package/dist/plugins/manager.js +9 -0
- package/dist/plugins/manager.js.map +1 -1
- package/dist/plugins/package-link.d.ts +1 -0
- package/dist/plugins/package-link.d.ts.map +1 -1
- package/dist/plugins/package-link.js +62 -5
- package/dist/plugins/package-link.js.map +1 -1
- package/package.json +28 -28
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# @mastra/code-sdk
|
|
2
|
+
|
|
3
|
+
## 0.1.0-alpha.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [[`aac3e5a`](https://github.com/mastra-ai/mastra/commit/aac3e5a098b08077c7d5020d782d6353b217797c), [`1b6e676`](https://github.com/mastra-ai/mastra/commit/1b6e67613c2a019df5920d4273d79bed09555807)]:
|
|
8
|
+
- @mastra/memory@1.23.0-alpha.1
|
|
9
|
+
|
|
10
|
+
## 0.1.0-alpha.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- Publish the Mastra Code agent core as `@mastra/code-sdk` (previously the internal `@internal/mastracode` package), so third parties can build their own UIs and surfaces on top of the Mastra Code coding agent. The `mastracode` CLI now consumes it as a regular runtime dependency instead of bundling it into its published output. ([#18986](https://github.com/mastra-ai/mastra/pull/18986))
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- Removed invalid CommonJS export entries from @mastra/code-sdk so package resolution matches the published ESM output. ([#19127](https://github.com/mastra-ai/mastra/pull/19127))
|
|
19
|
+
|
|
20
|
+
- Updated dependencies [[`6789ab4`](https://github.com/mastra-ai/mastra/commit/6789ab4191ddcd32a932898b360b191e80cee1a9)]:
|
|
21
|
+
- @mastra/schema-compat@1.3.4-alpha.0
|
|
22
|
+
- @mastra/core@1.50.2-alpha.1
|
|
23
|
+
- @mastra/mcp@1.13.1
|
|
24
|
+
- @mastra/memory@1.22.3-alpha.0
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
Portions of this software are licensed as follows:
|
|
2
|
+
|
|
3
|
+
- All content that resides under any directory named "ee/" within this
|
|
4
|
+
repository, including but not limited to:
|
|
5
|
+
- `packages/core/src/auth/ee/`
|
|
6
|
+
- `packages/server/src/server/auth/ee/`
|
|
7
|
+
is licensed under the license defined in `ee/LICENSE`.
|
|
8
|
+
|
|
9
|
+
- All third-party components incorporated into the Mastra Software are
|
|
10
|
+
licensed under the original license provided by the owner of the
|
|
11
|
+
applicable component.
|
|
12
|
+
|
|
13
|
+
- Content outside of the above-mentioned directories or restrictions is
|
|
14
|
+
available under the "Apache License 2.0" as defined below.
|
|
15
|
+
|
|
16
|
+
# Apache License 2.0
|
|
17
|
+
|
|
18
|
+
Copyright (c) 2025 Kepler Software, Inc.
|
|
19
|
+
|
|
20
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
21
|
+
you may not use this file except in compliance with the License.
|
|
22
|
+
You may obtain a copy of the License at
|
|
23
|
+
|
|
24
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
25
|
+
|
|
26
|
+
Unless required by applicable law or agreed to in writing, software
|
|
27
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
28
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
29
|
+
See the License for the specific language governing permissions and
|
|
30
|
+
limitations under the License.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type PluginInstallExecutionOptions = {
|
|
2
|
+
onOutput?: (chunk: Buffer | string) => void;
|
|
3
|
+
signal?: AbortSignal;
|
|
4
|
+
};
|
|
5
|
+
export declare function installPluginDependencies(pluginRoot: string, commandRoot?: string, options?: PluginInstallExecutionOptions): Promise<boolean>;
|
|
6
|
+
export declare function installPluginDependenciesForEntry(pluginRoot: string, entry: string, options?: PluginInstallExecutionOptions): Promise<void>;
|
|
7
|
+
export declare function getPluginDependencyRoots(pluginRoot: string, entry: string): string[];
|
|
8
|
+
export declare function getEntryPackageRoot(pluginRoot: string, entry: string): string;
|
|
9
|
+
//# sourceMappingURL=dependencies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../src/plugins/dependencies.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,6BAA6B,GAAG;IAC1C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IAC5C,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,MAAM,EAClB,WAAW,SAAa,EACxB,OAAO,GAAE,6BAAkC,GAC1C,OAAO,CAAC,OAAO,CAAC,CAsClB;AAED,wBAAsB,iCAAiC,CACrD,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,6BAAkC,GAC1C,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAOpF;AAED,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7E"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { execa } from "execa";
|
|
4
|
+
const NON_INTERACTIVE_INSTALL_ENV = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
|
|
5
|
+
async function installPluginDependencies(pluginRoot, commandRoot = pluginRoot, options = {}) {
|
|
6
|
+
const packageJsonPath = path.join(pluginRoot, "package.json");
|
|
7
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
const packageJson = readPackageJson(pluginRoot);
|
|
11
|
+
const commandPackageJson = commandRoot === pluginRoot ? packageJson : readPackageJson(commandRoot);
|
|
12
|
+
const installCommand2 = getInstallCommand(
|
|
13
|
+
pluginRoot,
|
|
14
|
+
typeof packageJson.packageManager === "string" ? packageJson.packageManager : void 0,
|
|
15
|
+
commandRoot,
|
|
16
|
+
typeof commandPackageJson.packageManager === "string" ? commandPackageJson.packageManager : void 0
|
|
17
|
+
);
|
|
18
|
+
const child = execa(installCommand2.command, installCommand2.args, {
|
|
19
|
+
cwd: pluginRoot,
|
|
20
|
+
env: NON_INTERACTIVE_INSTALL_ENV,
|
|
21
|
+
stdout: options.onOutput ? "pipe" : "ignore",
|
|
22
|
+
stderr: options.onOutput ? "pipe" : "ignore",
|
|
23
|
+
cancelSignal: options.signal
|
|
24
|
+
});
|
|
25
|
+
if (options.onOutput) {
|
|
26
|
+
child.stdout?.on("data", options.onOutput);
|
|
27
|
+
child.stderr?.on("data", options.onOutput);
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
await child;
|
|
31
|
+
} catch (error) {
|
|
32
|
+
if (isCommandNotFoundError(error)) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
`This plugin uses ${installCommand2.command}, but ${installCommand2.command} is not installed. Install ${installCommand2.command} and try again. Plugin path: ${pluginRoot}`,
|
|
35
|
+
{ cause: error }
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
async function installPluginDependenciesForEntry(pluginRoot, entry, options = {}) {
|
|
43
|
+
for (const dependencyRoot of getPluginDependencyRoots(pluginRoot, entry)) {
|
|
44
|
+
await installPluginDependencies(dependencyRoot, pluginRoot, options);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function getPluginDependencyRoots(pluginRoot, entry) {
|
|
48
|
+
const roots = fs.existsSync(path.join(pluginRoot, "package.json")) ? [pluginRoot] : [];
|
|
49
|
+
const entryPackageRoot = findEntryPackageRoot(pluginRoot, entry);
|
|
50
|
+
if (entryPackageRoot && entryPackageRoot !== pluginRoot) {
|
|
51
|
+
roots.push(entryPackageRoot);
|
|
52
|
+
}
|
|
53
|
+
return roots;
|
|
54
|
+
}
|
|
55
|
+
function getEntryPackageRoot(pluginRoot, entry) {
|
|
56
|
+
return findEntryPackageRoot(pluginRoot, entry) ?? pluginRoot;
|
|
57
|
+
}
|
|
58
|
+
function findEntryPackageRoot(pluginRoot, entry) {
|
|
59
|
+
const root = path.resolve(pluginRoot);
|
|
60
|
+
let current = path.dirname(path.resolve(pluginRoot, entry));
|
|
61
|
+
while (isInsideDirectory(current, root)) {
|
|
62
|
+
if (fs.existsSync(path.join(current, "package.json"))) {
|
|
63
|
+
return current;
|
|
64
|
+
}
|
|
65
|
+
if (current === root) break;
|
|
66
|
+
current = path.dirname(current);
|
|
67
|
+
}
|
|
68
|
+
return void 0;
|
|
69
|
+
}
|
|
70
|
+
function isInsideDirectory(targetPath, root) {
|
|
71
|
+
const resolvedTarget = path.resolve(targetPath);
|
|
72
|
+
const resolvedRoot = path.resolve(root);
|
|
73
|
+
return resolvedTarget === resolvedRoot || resolvedTarget.startsWith(resolvedRoot + path.sep);
|
|
74
|
+
}
|
|
75
|
+
function getInstallCommand(pluginRoot, packageManager, commandRoot = pluginRoot, commandPackageManager) {
|
|
76
|
+
const manager = packageManager ?? commandPackageManager;
|
|
77
|
+
if (manager?.startsWith("pnpm@")) {
|
|
78
|
+
return hasFile(pluginRoot, "pnpm-lock.yaml") ? installCommand("pnpm", ["install", "--ignore-workspace", "--frozen-lockfile", "--pm-on-fail=ignore"]) : installCommand("pnpm", ["install", "--ignore-workspace", "--pm-on-fail=ignore"]);
|
|
79
|
+
}
|
|
80
|
+
if (manager?.startsWith("npm@")) {
|
|
81
|
+
return hasNpmLockfile(pluginRoot) ? installCommand("npm", ["ci"]) : installCommand("npm", ["install"]);
|
|
82
|
+
}
|
|
83
|
+
if (manager?.startsWith("yarn@")) {
|
|
84
|
+
return hasFile(pluginRoot, "yarn.lock") ? installCommand("yarn", ["install", "--frozen-lockfile"]) : installCommand("yarn", ["install"]);
|
|
85
|
+
}
|
|
86
|
+
if (manager?.startsWith("bun@")) {
|
|
87
|
+
return hasFile(pluginRoot, "bun.lock") || hasFile(pluginRoot, "bun.lockb") ? installCommand("bun", ["install", "--frozen-lockfile"]) : installCommand("bun", ["install"]);
|
|
88
|
+
}
|
|
89
|
+
if (manager) {
|
|
90
|
+
return installCommand(manager.split("@")[0] ?? manager, ["install"]);
|
|
91
|
+
}
|
|
92
|
+
if (hasFile(pluginRoot, "pnpm-lock.yaml")) {
|
|
93
|
+
return installCommand("pnpm", ["install", "--ignore-workspace", "--frozen-lockfile", "--pm-on-fail=ignore"]);
|
|
94
|
+
}
|
|
95
|
+
if (hasFile(commandRoot, "pnpm-lock.yaml")) {
|
|
96
|
+
return installCommand("pnpm", ["install", "--ignore-workspace", "--pm-on-fail=ignore"]);
|
|
97
|
+
}
|
|
98
|
+
if (hasNpmLockfile(pluginRoot)) {
|
|
99
|
+
return installCommand("npm", ["ci"]);
|
|
100
|
+
}
|
|
101
|
+
if (hasNpmLockfile(commandRoot)) {
|
|
102
|
+
return installCommand("npm", ["install"]);
|
|
103
|
+
}
|
|
104
|
+
if (hasFile(pluginRoot, "yarn.lock")) {
|
|
105
|
+
return installCommand("yarn", ["install", "--frozen-lockfile"]);
|
|
106
|
+
}
|
|
107
|
+
if (hasFile(commandRoot, "yarn.lock")) {
|
|
108
|
+
return installCommand("yarn", ["install"]);
|
|
109
|
+
}
|
|
110
|
+
if (hasFile(pluginRoot, "bun.lock") || hasFile(pluginRoot, "bun.lockb")) {
|
|
111
|
+
return installCommand("bun", ["install", "--frozen-lockfile"]);
|
|
112
|
+
}
|
|
113
|
+
if (hasFile(commandRoot, "bun.lock") || hasFile(commandRoot, "bun.lockb")) {
|
|
114
|
+
return installCommand("bun", ["install"]);
|
|
115
|
+
}
|
|
116
|
+
return installCommand("npm", ["install"]);
|
|
117
|
+
}
|
|
118
|
+
function installCommand(command, args) {
|
|
119
|
+
return { command, args: [...args, "--ignore-scripts"] };
|
|
120
|
+
}
|
|
121
|
+
function isCommandNotFoundError(error) {
|
|
122
|
+
return typeof error === "object" && error !== null && error.code === "ENOENT";
|
|
123
|
+
}
|
|
124
|
+
function readPackageJson(pluginRoot) {
|
|
125
|
+
const packageJsonPath = path.join(pluginRoot, "package.json");
|
|
126
|
+
if (!fs.existsSync(packageJsonPath)) return {};
|
|
127
|
+
return JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
128
|
+
}
|
|
129
|
+
function hasNpmLockfile(pluginRoot) {
|
|
130
|
+
return hasFile(pluginRoot, "package-lock.json") || hasFile(pluginRoot, "npm-shrinkwrap.json");
|
|
131
|
+
}
|
|
132
|
+
function hasFile(pluginRoot, fileName) {
|
|
133
|
+
return fs.existsSync(path.join(pluginRoot, fileName));
|
|
134
|
+
}
|
|
135
|
+
export {
|
|
136
|
+
getEntryPackageRoot,
|
|
137
|
+
getPluginDependencyRoots,
|
|
138
|
+
installPluginDependencies,
|
|
139
|
+
installPluginDependenciesForEntry
|
|
140
|
+
};
|
|
141
|
+
//# sourceMappingURL=dependencies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/plugins/dependencies.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { execa } from 'execa';\n\nconst NON_INTERACTIVE_INSTALL_ENV = { ...process.env, GIT_TERMINAL_PROMPT: '0' };\n\ntype InstallCommand = {\n command: string;\n args: string[];\n};\n\nexport type PluginInstallExecutionOptions = {\n onOutput?: (chunk: Buffer | string) => void;\n signal?: AbortSignal;\n};\n\nexport async function installPluginDependencies(\n pluginRoot: string,\n commandRoot = pluginRoot,\n options: PluginInstallExecutionOptions = {},\n): Promise<boolean> {\n const packageJsonPath = path.join(pluginRoot, 'package.json');\n if (!fs.existsSync(packageJsonPath)) {\n return false;\n }\n\n const packageJson = readPackageJson(pluginRoot);\n const commandPackageJson = commandRoot === pluginRoot ? packageJson : readPackageJson(commandRoot);\n const installCommand = getInstallCommand(\n pluginRoot,\n typeof packageJson.packageManager === 'string' ? packageJson.packageManager : undefined,\n commandRoot,\n typeof commandPackageJson.packageManager === 'string' ? commandPackageJson.packageManager : undefined,\n );\n\n const child = execa(installCommand.command, installCommand.args, {\n cwd: pluginRoot,\n env: NON_INTERACTIVE_INSTALL_ENV,\n stdout: options.onOutput ? 'pipe' : 'ignore',\n stderr: options.onOutput ? 'pipe' : 'ignore',\n cancelSignal: options.signal,\n });\n if (options.onOutput) {\n child.stdout?.on('data', options.onOutput);\n child.stderr?.on('data', options.onOutput);\n }\n try {\n await child;\n } catch (error) {\n if (isCommandNotFoundError(error)) {\n throw new Error(\n `This plugin uses ${installCommand.command}, but ${installCommand.command} is not installed. Install ${installCommand.command} and try again. Plugin path: ${pluginRoot}`,\n { cause: error },\n );\n }\n throw error;\n }\n return true;\n}\n\nexport async function installPluginDependenciesForEntry(\n pluginRoot: string,\n entry: string,\n options: PluginInstallExecutionOptions = {},\n): Promise<void> {\n for (const dependencyRoot of getPluginDependencyRoots(pluginRoot, entry)) {\n await installPluginDependencies(dependencyRoot, pluginRoot, options);\n }\n}\n\nexport function getPluginDependencyRoots(pluginRoot: string, entry: string): string[] {\n const roots = fs.existsSync(path.join(pluginRoot, 'package.json')) ? [pluginRoot] : [];\n const entryPackageRoot = findEntryPackageRoot(pluginRoot, entry);\n if (entryPackageRoot && entryPackageRoot !== pluginRoot) {\n roots.push(entryPackageRoot);\n }\n return roots;\n}\n\nexport function getEntryPackageRoot(pluginRoot: string, entry: string): string {\n return findEntryPackageRoot(pluginRoot, entry) ?? pluginRoot;\n}\n\nfunction findEntryPackageRoot(pluginRoot: string, entry: string): string | undefined {\n const root = path.resolve(pluginRoot);\n let current = path.dirname(path.resolve(pluginRoot, entry));\n\n while (isInsideDirectory(current, root)) {\n if (fs.existsSync(path.join(current, 'package.json'))) {\n return current;\n }\n if (current === root) break;\n current = path.dirname(current);\n }\n\n return undefined;\n}\n\nfunction isInsideDirectory(targetPath: string, root: string): boolean {\n const resolvedTarget = path.resolve(targetPath);\n const resolvedRoot = path.resolve(root);\n return resolvedTarget === resolvedRoot || resolvedTarget.startsWith(resolvedRoot + path.sep);\n}\n\nfunction getInstallCommand(\n pluginRoot: string,\n packageManager?: string,\n commandRoot = pluginRoot,\n commandPackageManager?: string,\n): InstallCommand {\n const manager = packageManager ?? commandPackageManager;\n\n if (manager?.startsWith('pnpm@')) {\n return hasFile(pluginRoot, 'pnpm-lock.yaml')\n ? installCommand('pnpm', ['install', '--ignore-workspace', '--frozen-lockfile', '--pm-on-fail=ignore'])\n : installCommand('pnpm', ['install', '--ignore-workspace', '--pm-on-fail=ignore']);\n }\n\n if (manager?.startsWith('npm@')) {\n return hasNpmLockfile(pluginRoot) ? installCommand('npm', ['ci']) : installCommand('npm', ['install']);\n }\n\n if (manager?.startsWith('yarn@')) {\n return hasFile(pluginRoot, 'yarn.lock')\n ? installCommand('yarn', ['install', '--frozen-lockfile'])\n : installCommand('yarn', ['install']);\n }\n\n if (manager?.startsWith('bun@')) {\n return hasFile(pluginRoot, 'bun.lock') || hasFile(pluginRoot, 'bun.lockb')\n ? installCommand('bun', ['install', '--frozen-lockfile'])\n : installCommand('bun', ['install']);\n }\n\n if (manager) {\n return installCommand(manager.split('@')[0] ?? manager, ['install']);\n }\n\n if (hasFile(pluginRoot, 'pnpm-lock.yaml')) {\n return installCommand('pnpm', ['install', '--ignore-workspace', '--frozen-lockfile', '--pm-on-fail=ignore']);\n }\n\n if (hasFile(commandRoot, 'pnpm-lock.yaml')) {\n return installCommand('pnpm', ['install', '--ignore-workspace', '--pm-on-fail=ignore']);\n }\n\n if (hasNpmLockfile(pluginRoot)) {\n return installCommand('npm', ['ci']);\n }\n\n if (hasNpmLockfile(commandRoot)) {\n return installCommand('npm', ['install']);\n }\n\n if (hasFile(pluginRoot, 'yarn.lock')) {\n return installCommand('yarn', ['install', '--frozen-lockfile']);\n }\n\n if (hasFile(commandRoot, 'yarn.lock')) {\n return installCommand('yarn', ['install']);\n }\n\n if (hasFile(pluginRoot, 'bun.lock') || hasFile(pluginRoot, 'bun.lockb')) {\n return installCommand('bun', ['install', '--frozen-lockfile']);\n }\n\n if (hasFile(commandRoot, 'bun.lock') || hasFile(commandRoot, 'bun.lockb')) {\n return installCommand('bun', ['install']);\n }\n\n return installCommand('npm', ['install']);\n}\n\nfunction installCommand(command: string, args: string[]): InstallCommand {\n return { command, args: [...args, '--ignore-scripts'] };\n}\n\nfunction isCommandNotFoundError(error: unknown): boolean {\n return typeof error === 'object' && error !== null && (error as { code?: unknown }).code === 'ENOENT';\n}\n\nfunction readPackageJson(pluginRoot: string): { packageManager?: unknown } {\n const packageJsonPath = path.join(pluginRoot, 'package.json');\n if (!fs.existsSync(packageJsonPath)) return {};\n return JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) as { packageManager?: unknown };\n}\n\nfunction hasNpmLockfile(pluginRoot: string): boolean {\n return hasFile(pluginRoot, 'package-lock.json') || hasFile(pluginRoot, 'npm-shrinkwrap.json');\n}\n\nfunction hasFile(pluginRoot: string, fileName: string): boolean {\n return fs.existsSync(path.join(pluginRoot, fileName));\n}\n"],"mappings":"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","names":["installCommand"]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import type { PluginInstallExecutionOptions } from './dependencies.js';
|
|
1
2
|
import type { PluginPathOptions } from './paths.js';
|
|
2
3
|
import type { PluginScope } from './types.js';
|
|
3
|
-
export type InstallPluginOptions = PluginPathOptions & {
|
|
4
|
+
export type InstallPluginOptions = PluginPathOptions & PluginInstallExecutionOptions & {
|
|
4
5
|
entry?: string;
|
|
5
6
|
ref?: string;
|
|
6
7
|
githubCliPath?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/plugins/install.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/plugins/install.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,mBAAmB,CAAC;AAKvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,OAAO,KAAK,EAAyB,WAAW,EAAE,MAAM,YAAY,CAAC;AAErE,MAAM,MAAM,oBAAoB,GAAG,iBAAiB,GAClD,6BAA6B,GAAG;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEJ,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAIF,eAAO,MAAM,uBAAuB;;CAA+C,CAAC;AAIpF,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,MAAM,CAAC,CAsBjB;AAED,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,MAAM,CAAC,CAyCjB;AAED,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,GAAG,qBAAqB,EAAE,CAa5G;AA2BD,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAiC7E"}
|
package/dist/plugins/install.js
CHANGED
|
@@ -2,6 +2,7 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { execa } from "execa";
|
|
4
4
|
import { DEFAULT_CONFIG_DIR } from "../constants.js";
|
|
5
|
+
import { getEntryPackageRoot, installPluginDependenciesForEntry } from "./dependencies.js";
|
|
5
6
|
import { loadPluginFromEntry } from "./loader.js";
|
|
6
7
|
import { getSingleManifestPlugin } from "./manifest.js";
|
|
7
8
|
import { ensureMastraCodePackageLink } from "./package-link.js";
|
|
@@ -40,13 +41,20 @@ async function installGithubPlugin(url, scope, options) {
|
|
|
40
41
|
await assertGithubCliAuthenticated(githubCli);
|
|
41
42
|
fs.rmSync(checkoutDir, { recursive: true, force: true });
|
|
42
43
|
fs.mkdirSync(path.dirname(checkoutDir), { recursive: true });
|
|
43
|
-
await execa(githubCli, ["repo", "clone", parsed.repoSpec, checkoutDir], NON_INTERACTIVE_EXEC_OPTIONS);
|
|
44
44
|
const ref = options.ref ?? parsed.ref;
|
|
45
|
+
const cloneArgs = ["repo", "clone", parsed.repoSpec, checkoutDir, ...ref ? [] : ["--", "--depth", "1"]];
|
|
46
|
+
await runPluginInstallCommand(githubCli, cloneArgs, { env: NON_INTERACTIVE_GIT_ENV }, options);
|
|
45
47
|
if (ref) {
|
|
46
|
-
await
|
|
48
|
+
await runPluginInstallCommand(
|
|
49
|
+
"git",
|
|
50
|
+
["checkout", ref],
|
|
51
|
+
{ cwd: checkoutDir, env: NON_INTERACTIVE_GIT_ENV },
|
|
52
|
+
options
|
|
53
|
+
);
|
|
47
54
|
}
|
|
48
55
|
const entry = detectEntry(checkoutDir, options.entry);
|
|
49
|
-
|
|
56
|
+
await installPluginDependenciesForEntry(checkoutDir, entry, options);
|
|
57
|
+
ensureMastraCodePackageLink(getEntryPackageRoot(checkoutDir, entry));
|
|
50
58
|
const plugin = await loadPluginFromEntry(path.join(checkoutDir, entry));
|
|
51
59
|
const registry = removePluginRecord(loadPluginRegistry(paths.registryPath), plugin.id);
|
|
52
60
|
const relativePath = path.relative(getPluginRoot(scope, options), checkoutDir);
|
|
@@ -126,6 +134,19 @@ function detectEntry(pluginDir, explicitEntry) {
|
|
|
126
134
|
function isInsideDirectory(targetPath, root) {
|
|
127
135
|
return targetPath === root || targetPath.startsWith(root + path.sep);
|
|
128
136
|
}
|
|
137
|
+
async function runPluginInstallCommand(command, args, execaOptions, options) {
|
|
138
|
+
const child = execa(command, args, {
|
|
139
|
+
...execaOptions,
|
|
140
|
+
stdout: options.onOutput ? "pipe" : "ignore",
|
|
141
|
+
stderr: options.onOutput ? "pipe" : "ignore",
|
|
142
|
+
cancelSignal: options.signal
|
|
143
|
+
});
|
|
144
|
+
if (options.onOutput) {
|
|
145
|
+
child.stdout?.on("data", options.onOutput);
|
|
146
|
+
child.stderr?.on("data", options.onOutput);
|
|
147
|
+
}
|
|
148
|
+
await child;
|
|
149
|
+
}
|
|
129
150
|
async function assertGithubCliAvailable(githubCli) {
|
|
130
151
|
try {
|
|
131
152
|
await execa(githubCli, ["--version"], NON_INTERACTIVE_EXEC_OPTIONS);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugins/install.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { execa } from 'execa';\n\nimport { DEFAULT_CONFIG_DIR } from '../constants.js';\nimport { loadPluginFromEntry } from './loader.js';\nimport { getSingleManifestPlugin } from './manifest.js';\nimport { ensureMastraCodePackageLink } from './package-link.js';\nimport { getPluginRoot, getPluginScopePaths } from './paths.js';\nimport type { PluginPathOptions } from './paths.js';\nimport { loadPluginRegistry, removePluginRecord, savePluginRegistry, setPluginRecord } from './registry.js';\nimport type { InstalledPluginRecord, PluginScope } from './types.js';\n\nexport type InstallPluginOptions = PluginPathOptions & {\n entry?: string;\n ref?: string;\n githubCliPath?: string;\n};\n\nexport type DiscoveredLocalPlugin = {\n name: string;\n path: string;\n entry: string;\n};\n\nconst ENTRY_CANDIDATES = ['src/index.ts', 'index.ts'];\n\nexport const NON_INTERACTIVE_GIT_ENV = { ...process.env, GIT_TERMINAL_PROMPT: '0' };\n\nconst NON_INTERACTIVE_EXEC_OPTIONS = { env: NON_INTERACTIVE_GIT_ENV };\n\nexport async function installLocalPlugin(\n localPath: string,\n scope: PluginScope,\n options: InstallPluginOptions,\n): Promise<string> {\n const sourcePath = path.resolve(options.projectRoot, localPath);\n if (!fs.existsSync(sourcePath) || !fs.statSync(sourcePath).isDirectory()) {\n throw new Error(`Local plugin path does not exist or is not a directory: ${localPath}`);\n }\n\n const entry = detectEntry(sourcePath, options.entry);\n ensureMastraCodePackageLink(sourcePath);\n const plugin = await loadPluginFromEntry(path.join(sourcePath, entry));\n const registryPath = getPluginScopePaths(scope, options).registryPath;\n const registry = removePluginRecord(loadPluginRegistry(registryPath), plugin.id);\n const record: InstalledPluginRecord = {\n enabled: true,\n source: 'local',\n specifier: localPath,\n path: sourcePath,\n entry,\n ...(plugin.version ? { version: plugin.version } : {}),\n };\n\n savePluginRegistry(registryPath, setPluginRecord(registry, plugin.id, record));\n return plugin.id;\n}\n\nexport async function installGithubPlugin(\n url: string,\n scope: PluginScope,\n options: InstallPluginOptions,\n): Promise<string> {\n const parsed = parseGithubUrl(url);\n const paths = getPluginScopePaths(scope, options);\n const checkoutDir = path.join(paths.sourcesPath, 'github', `${parsed.owner}-${parsed.repo}`);\n\n const githubCli = options.githubCliPath ?? 'gh';\n await assertGithubCliAvailable(githubCli);\n await assertGithubCliAuthenticated(githubCli);\n\n fs.rmSync(checkoutDir, { recursive: true, force: true });\n fs.mkdirSync(path.dirname(checkoutDir), { recursive: true });\n await execa(githubCli, ['repo', 'clone', parsed.repoSpec, checkoutDir], NON_INTERACTIVE_EXEC_OPTIONS);\n const ref = options.ref ?? parsed.ref;\n if (ref) {\n await execa('git', ['checkout', ref], { cwd: checkoutDir, env: NON_INTERACTIVE_GIT_ENV });\n }\n\n const entry = detectEntry(checkoutDir, options.entry);\n ensureMastraCodePackageLink(checkoutDir);\n const plugin = await loadPluginFromEntry(path.join(checkoutDir, entry));\n const registry = removePluginRecord(loadPluginRegistry(paths.registryPath), plugin.id);\n const relativePath = path.relative(getPluginRoot(scope, options), checkoutDir);\n const record: InstalledPluginRecord = {\n enabled: true,\n source: 'github',\n specifier: url,\n path: relativePath,\n entry,\n ...(ref ? { ref } : {}),\n ...(plugin.version ? { version: plugin.version } : {}),\n };\n\n savePluginRegistry(paths.registryPath, setPluginRecord(registry, plugin.id, record));\n return plugin.id;\n}\n\nexport function discoverLocalPlugins(searchRoot: string, options: PluginPathOptions): DiscoveredLocalPlugin[] {\n const root = path.resolve(options.projectRoot, searchRoot);\n const localSourcesRoot = path.join(root, options.configDir ?? DEFAULT_CONFIG_DIR, 'plugins', 'sources', 'local');\n const scanRoot = isLocalSourcesDir(root) ? root : localSourcesRoot;\n\n const seen = new Set<string>();\n return discoverPluginDirs(scanRoot)\n .filter(candidate => {\n if (seen.has(candidate.path)) return false;\n seen.add(candidate.path);\n return true;\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\nfunction isLocalSourcesDir(dir: string): boolean {\n const normalized = dir.split(path.sep).join('/');\n return normalized.endsWith('/plugins/sources/local');\n}\n\nfunction discoverPluginDirs(root: string): DiscoveredLocalPlugin[] {\n if (!fs.existsSync(root) || !fs.statSync(root).isDirectory()) return [];\n return fs\n .readdirSync(root, { withFileTypes: true })\n .filter(entry => entry.isDirectory())\n .flatMap(entry => {\n const pluginDir = path.join(root, entry.name);\n const detectedEntry = tryDetectEntry(pluginDir);\n return detectedEntry ? [{ name: entry.name, path: pluginDir, entry: detectedEntry }] : [];\n });\n}\n\nfunction tryDetectEntry(pluginDir: string): string | undefined {\n try {\n return detectEntry(pluginDir);\n } catch {\n return undefined;\n }\n}\n\nexport function detectEntry(pluginDir: string, explicitEntry?: string): string {\n const root = path.resolve(pluginDir);\n if (explicitEntry) {\n const entryPath = path.resolve(pluginDir, explicitEntry);\n if (!isInsideDirectory(entryPath, root)) {\n throw new Error('Plugin entry must be inside the plugin directory');\n }\n if (fs.existsSync(entryPath) && fs.statSync(entryPath).isDirectory()) {\n const nestedEntry = detectEntry(entryPath);\n return path.relative(root, path.join(entryPath, nestedEntry));\n }\n if (path.extname(entryPath) !== '.ts') {\n throw new Error('Plugin entry must be a .ts file');\n }\n if (!fs.existsSync(entryPath) || !fs.statSync(entryPath).isFile()) {\n throw new Error(`Plugin entry file does not exist: ${explicitEntry}`);\n }\n return path.relative(root, entryPath);\n }\n\n const manifestPlugin = getSingleManifestPlugin(pluginDir);\n if (manifestPlugin) {\n return detectEntry(pluginDir, manifestPlugin.entry);\n }\n\n for (const candidate of ENTRY_CANDIDATES) {\n const entryPath = path.join(pluginDir, candidate);\n if (fs.existsSync(entryPath) && fs.statSync(entryPath).isFile()) {\n return candidate;\n }\n }\n\n throw new Error(`Could not find a plugin entry file. Tried: ${ENTRY_CANDIDATES.join(', ')}`);\n}\n\nfunction isInsideDirectory(targetPath: string, root: string): boolean {\n return targetPath === root || targetPath.startsWith(root + path.sep);\n}\n\nasync function assertGithubCliAvailable(githubCli: string): Promise<void> {\n try {\n await execa(githubCli, ['--version'], NON_INTERACTIVE_EXEC_OPTIONS);\n } catch {\n throw new Error('GitHub CLI is required to install GitHub plugins. Install gh and run gh auth login.');\n }\n}\n\nasync function assertGithubCliAuthenticated(githubCli: string): Promise<void> {\n try {\n await execa(githubCli, ['auth', 'status'], NON_INTERACTIVE_EXEC_OPTIONS);\n } catch {\n throw new Error('GitHub CLI is not authenticated. Run gh auth login, then install the plugin again.');\n }\n}\n\nfunction parseGithubUrl(specifier: string): { owner: string; repo: string; repoSpec: string; ref?: string } {\n const [urlPart, ref] = specifier.split('#', 2);\n if (!urlPart) {\n throw new Error(`Invalid GitHub URL: ${specifier}`);\n }\n let url: URL;\n try {\n url = new URL(urlPart);\n } catch {\n throw new Error(`Invalid GitHub URL: ${specifier}`);\n }\n\n if (url.hostname !== 'github.com') {\n throw new Error('Only github.com plugin URLs are supported');\n }\n\n const [owner, rawRepo, ...rest] = url.pathname.split('/').filter(Boolean);\n if (!owner || !rawRepo || rest.length > 0) {\n throw new Error('GitHub plugin URL must be in the form https://github.com/owner/repo');\n }\n\n const repo = rawRepo.replace(/\\.git$/, '');\n if (!/^[A-Za-z0-9_.-]+$/.test(owner) || !/^[A-Za-z0-9_.-]+$/.test(repo)) {\n throw new Error('GitHub owner and repo may only contain letters, numbers, dots, underscores, and dashes');\n }\n\n return {\n owner,\n repo,\n repoSpec: `${owner}/${repo}`,\n ...(ref ? { ref } : {}),\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/plugins/install.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { execa } from 'execa';\n\nimport { DEFAULT_CONFIG_DIR } from '../constants.js';\nimport { getEntryPackageRoot, installPluginDependenciesForEntry } from './dependencies.js';\nimport type { PluginInstallExecutionOptions } from './dependencies.js';\nimport { loadPluginFromEntry } from './loader.js';\nimport { getSingleManifestPlugin } from './manifest.js';\nimport { ensureMastraCodePackageLink } from './package-link.js';\nimport { getPluginRoot, getPluginScopePaths } from './paths.js';\nimport type { PluginPathOptions } from './paths.js';\nimport { loadPluginRegistry, removePluginRecord, savePluginRegistry, setPluginRecord } from './registry.js';\nimport type { InstalledPluginRecord, PluginScope } from './types.js';\n\nexport type InstallPluginOptions = PluginPathOptions &\n PluginInstallExecutionOptions & {\n entry?: string;\n ref?: string;\n githubCliPath?: string;\n };\n\nexport type DiscoveredLocalPlugin = {\n name: string;\n path: string;\n entry: string;\n};\n\nconst ENTRY_CANDIDATES = ['src/index.ts', 'index.ts'];\n\nexport const NON_INTERACTIVE_GIT_ENV = { ...process.env, GIT_TERMINAL_PROMPT: '0' };\n\nconst NON_INTERACTIVE_EXEC_OPTIONS = { env: NON_INTERACTIVE_GIT_ENV };\n\nexport async function installLocalPlugin(\n localPath: string,\n scope: PluginScope,\n options: InstallPluginOptions,\n): Promise<string> {\n const sourcePath = path.resolve(options.projectRoot, localPath);\n if (!fs.existsSync(sourcePath) || !fs.statSync(sourcePath).isDirectory()) {\n throw new Error(`Local plugin path does not exist or is not a directory: ${localPath}`);\n }\n\n const entry = detectEntry(sourcePath, options.entry);\n ensureMastraCodePackageLink(sourcePath);\n const plugin = await loadPluginFromEntry(path.join(sourcePath, entry));\n const registryPath = getPluginScopePaths(scope, options).registryPath;\n const registry = removePluginRecord(loadPluginRegistry(registryPath), plugin.id);\n const record: InstalledPluginRecord = {\n enabled: true,\n source: 'local',\n specifier: localPath,\n path: sourcePath,\n entry,\n ...(plugin.version ? { version: plugin.version } : {}),\n };\n\n savePluginRegistry(registryPath, setPluginRecord(registry, plugin.id, record));\n return plugin.id;\n}\n\nexport async function installGithubPlugin(\n url: string,\n scope: PluginScope,\n options: InstallPluginOptions,\n): Promise<string> {\n const parsed = parseGithubUrl(url);\n const paths = getPluginScopePaths(scope, options);\n const checkoutDir = path.join(paths.sourcesPath, 'github', `${parsed.owner}-${parsed.repo}`);\n\n const githubCli = options.githubCliPath ?? 'gh';\n await assertGithubCliAvailable(githubCli);\n await assertGithubCliAuthenticated(githubCli);\n\n fs.rmSync(checkoutDir, { recursive: true, force: true });\n fs.mkdirSync(path.dirname(checkoutDir), { recursive: true });\n const ref = options.ref ?? parsed.ref;\n const cloneArgs = ['repo', 'clone', parsed.repoSpec, checkoutDir, ...(ref ? [] : ['--', '--depth', '1'])];\n await runPluginInstallCommand(githubCli, cloneArgs, { env: NON_INTERACTIVE_GIT_ENV }, options);\n if (ref) {\n await runPluginInstallCommand(\n 'git',\n ['checkout', ref],\n { cwd: checkoutDir, env: NON_INTERACTIVE_GIT_ENV },\n options,\n );\n }\n\n const entry = detectEntry(checkoutDir, options.entry);\n await installPluginDependenciesForEntry(checkoutDir, entry, options);\n ensureMastraCodePackageLink(getEntryPackageRoot(checkoutDir, entry));\n const plugin = await loadPluginFromEntry(path.join(checkoutDir, entry));\n const registry = removePluginRecord(loadPluginRegistry(paths.registryPath), plugin.id);\n const relativePath = path.relative(getPluginRoot(scope, options), checkoutDir);\n const record: InstalledPluginRecord = {\n enabled: true,\n source: 'github',\n specifier: url,\n path: relativePath,\n entry,\n ...(ref ? { ref } : {}),\n ...(plugin.version ? { version: plugin.version } : {}),\n };\n\n savePluginRegistry(paths.registryPath, setPluginRecord(registry, plugin.id, record));\n return plugin.id;\n}\n\nexport function discoverLocalPlugins(searchRoot: string, options: PluginPathOptions): DiscoveredLocalPlugin[] {\n const root = path.resolve(options.projectRoot, searchRoot);\n const localSourcesRoot = path.join(root, options.configDir ?? DEFAULT_CONFIG_DIR, 'plugins', 'sources', 'local');\n const scanRoot = isLocalSourcesDir(root) ? root : localSourcesRoot;\n\n const seen = new Set<string>();\n return discoverPluginDirs(scanRoot)\n .filter(candidate => {\n if (seen.has(candidate.path)) return false;\n seen.add(candidate.path);\n return true;\n })\n .sort((a, b) => a.name.localeCompare(b.name));\n}\n\nfunction isLocalSourcesDir(dir: string): boolean {\n const normalized = dir.split(path.sep).join('/');\n return normalized.endsWith('/plugins/sources/local');\n}\n\nfunction discoverPluginDirs(root: string): DiscoveredLocalPlugin[] {\n if (!fs.existsSync(root) || !fs.statSync(root).isDirectory()) return [];\n return fs\n .readdirSync(root, { withFileTypes: true })\n .filter(entry => entry.isDirectory())\n .flatMap(entry => {\n const pluginDir = path.join(root, entry.name);\n const detectedEntry = tryDetectEntry(pluginDir);\n return detectedEntry ? [{ name: entry.name, path: pluginDir, entry: detectedEntry }] : [];\n });\n}\n\nfunction tryDetectEntry(pluginDir: string): string | undefined {\n try {\n return detectEntry(pluginDir);\n } catch {\n return undefined;\n }\n}\n\nexport function detectEntry(pluginDir: string, explicitEntry?: string): string {\n const root = path.resolve(pluginDir);\n if (explicitEntry) {\n const entryPath = path.resolve(pluginDir, explicitEntry);\n if (!isInsideDirectory(entryPath, root)) {\n throw new Error('Plugin entry must be inside the plugin directory');\n }\n if (fs.existsSync(entryPath) && fs.statSync(entryPath).isDirectory()) {\n const nestedEntry = detectEntry(entryPath);\n return path.relative(root, path.join(entryPath, nestedEntry));\n }\n if (path.extname(entryPath) !== '.ts') {\n throw new Error('Plugin entry must be a .ts file');\n }\n if (!fs.existsSync(entryPath) || !fs.statSync(entryPath).isFile()) {\n throw new Error(`Plugin entry file does not exist: ${explicitEntry}`);\n }\n return path.relative(root, entryPath);\n }\n\n const manifestPlugin = getSingleManifestPlugin(pluginDir);\n if (manifestPlugin) {\n return detectEntry(pluginDir, manifestPlugin.entry);\n }\n\n for (const candidate of ENTRY_CANDIDATES) {\n const entryPath = path.join(pluginDir, candidate);\n if (fs.existsSync(entryPath) && fs.statSync(entryPath).isFile()) {\n return candidate;\n }\n }\n\n throw new Error(`Could not find a plugin entry file. Tried: ${ENTRY_CANDIDATES.join(', ')}`);\n}\n\nfunction isInsideDirectory(targetPath: string, root: string): boolean {\n return targetPath === root || targetPath.startsWith(root + path.sep);\n}\n\nasync function runPluginInstallCommand(\n command: string,\n args: string[],\n execaOptions: typeof NON_INTERACTIVE_EXEC_OPTIONS & { cwd?: string },\n options: PluginInstallExecutionOptions,\n): Promise<void> {\n const child = execa(command, args, {\n ...execaOptions,\n stdout: options.onOutput ? 'pipe' : 'ignore',\n stderr: options.onOutput ? 'pipe' : 'ignore',\n cancelSignal: options.signal,\n });\n if (options.onOutput) {\n child.stdout?.on('data', options.onOutput);\n child.stderr?.on('data', options.onOutput);\n }\n await child;\n}\n\nasync function assertGithubCliAvailable(githubCli: string): Promise<void> {\n try {\n await execa(githubCli, ['--version'], NON_INTERACTIVE_EXEC_OPTIONS);\n } catch {\n throw new Error('GitHub CLI is required to install GitHub plugins. Install gh and run gh auth login.');\n }\n}\n\nasync function assertGithubCliAuthenticated(githubCli: string): Promise<void> {\n try {\n await execa(githubCli, ['auth', 'status'], NON_INTERACTIVE_EXEC_OPTIONS);\n } catch {\n throw new Error('GitHub CLI is not authenticated. Run gh auth login, then install the plugin again.');\n }\n}\n\nfunction parseGithubUrl(specifier: string): { owner: string; repo: string; repoSpec: string; ref?: string } {\n const [urlPart, ref] = specifier.split('#', 2);\n if (!urlPart) {\n throw new Error(`Invalid GitHub URL: ${specifier}`);\n }\n let url: URL;\n try {\n url = new URL(urlPart);\n } catch {\n throw new Error(`Invalid GitHub URL: ${specifier}`);\n }\n\n if (url.hostname !== 'github.com') {\n throw new Error('Only github.com plugin URLs are supported');\n }\n\n const [owner, rawRepo, ...rest] = url.pathname.split('/').filter(Boolean);\n if (!owner || !rawRepo || rest.length > 0) {\n throw new Error('GitHub plugin URL must be in the form https://github.com/owner/repo');\n }\n\n const repo = rawRepo.replace(/\\.git$/, '');\n if (!/^[A-Za-z0-9_.-]+$/.test(owner) || !/^[A-Za-z0-9_.-]+$/.test(repo)) {\n throw new Error('GitHub owner and repo may only contain letters, numbers, dots, underscores, and dashes');\n }\n\n return {\n owner,\n repo,\n repoSpec: `${owner}/${repo}`,\n ...(ref ? { ref } : {}),\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -51,7 +51,7 @@ export declare class PluginManager {
|
|
|
51
51
|
private readGitHead;
|
|
52
52
|
discoverLocal(searchRoot?: string): ReturnType<typeof discoverLocalPlugins>;
|
|
53
53
|
installLocal(localPath: string, scope: PluginScope, options?: Pick<InstallPluginOptions, 'entry'>): Promise<string>;
|
|
54
|
-
installGithub(url: string, scope: PluginScope, options?: Pick<InstallPluginOptions, 'entry' | 'ref'>): Promise<string>;
|
|
54
|
+
installGithub(url: string, scope: PluginScope, options?: Pick<InstallPluginOptions, 'entry' | 'ref' | 'onOutput' | 'signal'>): Promise<string>;
|
|
55
55
|
setEnabled(pluginId: string, scope: PluginScope, enabled: boolean): Promise<void>;
|
|
56
56
|
setConfigValue(pluginId: string, scope: PluginScope, key: string, value: MastraCodePluginConfigValue): Promise<void>;
|
|
57
57
|
uninstall(pluginId: string, scope: PluginScope): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/plugins/manager.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/plugins/manager.ts"],"names":[],"mappings":"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"}
|
package/dist/plugins/manager.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { execa } from "execa";
|
|
4
|
+
import { getEntryPackageRoot, installPluginDependenciesForEntry } from "./dependencies.js";
|
|
4
5
|
import { discoverLocalPlugins, installGithubPlugin, installLocalPlugin, NON_INTERACTIVE_GIT_ENV } from "./install.js";
|
|
5
6
|
import { collectActivePluginTools, isInsideDirectory, loadPlugins, resolvePluginEntryPath } from "./loader.js";
|
|
7
|
+
import { ensureMastraCodePackageLink } from "./package-link.js";
|
|
6
8
|
import { getPluginScopePaths } from "./paths.js";
|
|
7
9
|
import { loadPluginRegistry, removePluginRecord, savePluginRegistry, setPluginRecord } from "./registry.js";
|
|
8
10
|
const GITHUB_PLUGIN_POLL_INTERVAL_MS = 6e4;
|
|
@@ -215,6 +217,13 @@ class PluginManager {
|
|
|
215
217
|
}
|
|
216
218
|
if (remoteOnly > 0 || localOnly > 0 || hasLocalChanges) {
|
|
217
219
|
await execa("git", ["reset", "--hard", upstream], gitExecOptions(checkoutPath));
|
|
220
|
+
try {
|
|
221
|
+
await installPluginDependenciesForEntry(checkoutPath, plugin.entry);
|
|
222
|
+
ensureMastraCodePackageLink(getEntryPackageRoot(checkoutPath, plugin.entry));
|
|
223
|
+
} catch (error) {
|
|
224
|
+
await execa("git", ["reset", "--hard", currentHead], gitExecOptions(checkoutPath));
|
|
225
|
+
throw error;
|
|
226
|
+
}
|
|
218
227
|
return true;
|
|
219
228
|
}
|
|
220
229
|
return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugins/manager.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { execa } from 'execa';\n\nimport type { MastraCodePluginConfigValue } from '../plugin.js';\nimport { discoverLocalPlugins, installGithubPlugin, installLocalPlugin, NON_INTERACTIVE_GIT_ENV } from './install.js';\nimport type { InstallPluginOptions } from './install.js';\nimport { collectActivePluginTools, isInsideDirectory, loadPlugins, resolvePluginEntryPath } from './loader.js';\nimport { getPluginScopePaths } from './paths.js';\nimport type { PluginPathOptions } from './paths.js';\nimport { loadPluginRegistry, removePluginRecord, savePluginRegistry, setPluginRecord } from './registry.js';\nimport type { LoadedPlugin, PluginScope } from './types.js';\n\nconst GITHUB_PLUGIN_POLL_INTERVAL_MS = 60_000;\n\nfunction gitExecOptions(cwd: string) {\n return { cwd, env: NON_INTERACTIVE_GIT_ENV };\n}\n\nfunction getEntryVersion(entryPath: string): string {\n const stat = fs.statSync(entryPath, { bigint: true });\n return `${stat.mtimeNs}:${stat.size}`;\n}\n\ntype PluginManagerOptions = PluginPathOptions & {\n githubCliPath?: string;\n};\n\nexport class PluginManager {\n private loadedPlugins: LoadedPlugin[] = [];\n private readonly pluginTools: ReturnType<typeof collectActivePluginTools> = {};\n private readonly rawPluginTools: ReturnType<typeof collectActivePluginTools> = {};\n private readonly toolRenderConfigs = new Map<string, NonNullable<LoadedPlugin['renderConfigs']>[string]>();\n private readonly watchedLocalEntries = new Set<string>();\n private readonly localEntryVersions = new Map<string, string>();\n private githubPollTimer: ReturnType<typeof setInterval> | undefined;\n private githubPollInFlight: Promise<boolean> | undefined;\n private reloadInFlight: Promise<LoadedPlugin[]> | undefined;\n private readonly reloadListeners = new Set<(plugins: LoadedPlugin[]) => void | Promise<void>>();\n\n constructor(private readonly options: PluginManagerOptions) {}\n\n onReload(listener: (plugins: LoadedPlugin[]) => void | Promise<void>): () => void {\n this.reloadListeners.add(listener);\n return () => this.reloadListeners.delete(listener);\n }\n\n async reload(): Promise<LoadedPlugin[]> {\n if (this.reloadInFlight) return this.reloadInFlight;\n\n this.reloadInFlight = (async () => {\n this.loadedPlugins = await loadPlugins(this.options);\n this.updateLocalEntryWatchers(this.loadedPlugins);\n this.updateGithubPoller(this.loadedPlugins);\n this.updatePluginRenderConfigs(this.loadedPlugins);\n this.updatePluginTools(collectActivePluginTools(this.loadedPlugins));\n await this.notifyReloadListeners(this.loadedPlugins);\n return this.loadedPlugins;\n })().finally(() => {\n this.reloadInFlight = undefined;\n });\n\n return this.reloadInFlight;\n }\n\n async listPlugins(): Promise<LoadedPlugin[]> {\n if (this.loadedPlugins.length === 0) {\n await this.reload();\n }\n return this.loadedPlugins;\n }\n\n getLoadedPlugins(): LoadedPlugin[] {\n return this.loadedPlugins;\n }\n\n getPluginTools() {\n return this.pluginTools;\n }\n\n getToolRenderConfig(toolName: string) {\n return this.toolRenderConfigs.get(toolName);\n }\n\n getPluginSkillPaths(): string[] {\n return this.loadedPlugins.flatMap(plugin => (plugin.status === 'active' ? (plugin.skillPaths ?? []) : []));\n }\n\n getPluginCommandPaths(): string[] {\n return this.loadedPlugins.flatMap(plugin => (plugin.status === 'active' ? (plugin.commandPaths ?? []) : []));\n }\n\n getPluginInstructions(): string[] {\n return this.loadedPlugins.flatMap(plugin =>\n plugin.status === 'active' && plugin.instructions ? [plugin.instructions] : [],\n );\n }\n\n private async notifyReloadListeners(plugins: LoadedPlugin[]): Promise<void> {\n await Promise.all([...this.reloadListeners].map(listener => Promise.resolve(listener(plugins))));\n }\n\n private updatePluginRenderConfigs(plugins: LoadedPlugin[]): void {\n this.toolRenderConfigs.clear();\n for (const plugin of plugins) {\n if (plugin.status !== 'active') continue;\n for (const [toolName, renderConfig] of Object.entries(plugin.renderConfigs ?? {})) {\n if (!this.toolRenderConfigs.has(toolName)) {\n this.toolRenderConfigs.set(toolName, renderConfig);\n }\n }\n }\n }\n\n private updatePluginTools(nextTools: ReturnType<typeof collectActivePluginTools>): void {\n for (const name of Object.keys(this.rawPluginTools)) {\n if (!(name in nextTools)) {\n delete this.rawPluginTools[name];\n delete this.pluginTools[name];\n }\n }\n\n for (const [name, tool] of Object.entries(nextTools)) {\n this.rawPluginTools[name] = tool;\n if (!this.pluginTools[name]) {\n this.pluginTools[name] = this.createLiveToolProxy(name);\n }\n this.syncLiveToolProxy(name, tool);\n }\n }\n\n private createLiveToolProxy(toolName: string) {\n return {\n execute: async (...args: any[]) => {\n await this.reloadChangedLocalPlugins();\n const latestTool = this.rawPluginTools[toolName];\n if (!latestTool?.execute) {\n throw new Error(`Plugin tool \"${toolName}\" is no longer available`);\n }\n return (latestTool.execute as (...args: any[]) => unknown)(...args);\n },\n } as LoadedPlugin['tools'][string];\n }\n\n private syncLiveToolProxy(toolName: string, tool: LoadedPlugin['tools'][string]): void {\n const proxy = this.pluginTools[toolName];\n if (!proxy) return;\n const mutableProxy = proxy as unknown as Record<string, unknown>;\n for (const key of Object.keys(mutableProxy)) {\n delete mutableProxy[key];\n }\n Object.assign(proxy, tool);\n proxy.execute = this.createLiveToolProxy(toolName).execute;\n }\n\n private async reloadChangedLocalPlugins(): Promise<void> {\n for (const plugin of this.loadedPlugins) {\n if (plugin.source !== 'local' || plugin.status !== 'active') continue;\n const entryPath = resolvePluginEntryPath(plugin, this.options);\n const currentVersion = getEntryVersion(entryPath);\n if (this.localEntryVersions.get(entryPath) !== currentVersion) {\n await this.reload();\n return;\n }\n }\n }\n\n private updateLocalEntryWatchers(plugins: LoadedPlugin[]): void {\n const nextEntries = new Set<string>();\n for (const plugin of plugins) {\n if (plugin.source !== 'local' || plugin.status !== 'active') continue;\n let entryPath: string;\n let entryVersion: string;\n try {\n entryPath = resolvePluginEntryPath(plugin, this.options);\n entryVersion = getEntryVersion(entryPath);\n } catch {\n continue;\n }\n nextEntries.add(entryPath);\n this.localEntryVersions.set(entryPath, entryVersion);\n if (this.watchedLocalEntries.has(entryPath)) continue;\n\n const watcher = fs.watchFile(entryPath, { interval: 500 }, (current, previous) => {\n if (current.mtimeMs === previous.mtimeMs) return;\n void this.reload().catch(() => undefined);\n });\n watcher.unref?.();\n this.watchedLocalEntries.add(entryPath);\n }\n\n for (const entryPath of this.watchedLocalEntries) {\n if (nextEntries.has(entryPath)) continue;\n fs.unwatchFile(entryPath);\n this.watchedLocalEntries.delete(entryPath);\n this.localEntryVersions.delete(entryPath);\n }\n }\n\n private updateGithubPoller(plugins: LoadedPlugin[]): void {\n const hasGithubPlugin = plugins.some(\n plugin => plugin.source === 'github' && plugin.status !== 'inactive' && plugin.status !== 'blocked',\n );\n if (hasGithubPlugin && !this.githubPollTimer) {\n this.githubPollTimer = setInterval(() => {\n void this.pollGithubSourcesForUpdates().catch(() => undefined);\n }, GITHUB_PLUGIN_POLL_INTERVAL_MS);\n this.githubPollTimer.unref?.();\n }\n if (!hasGithubPlugin && this.githubPollTimer) {\n clearInterval(this.githubPollTimer);\n this.githubPollTimer = undefined;\n }\n }\n\n async pollGithubSourcesForUpdates(): Promise<boolean> {\n if (this.githubPollInFlight) return this.githubPollInFlight;\n this.githubPollInFlight = this.pollGithubSourcesForUpdatesOnce().finally(() => {\n this.githubPollInFlight = undefined;\n });\n return this.githubPollInFlight;\n }\n\n private async pollGithubSourcesForUpdatesOnce(): Promise<boolean> {\n let changed = false;\n const seen = new Set<string>();\n for (const plugin of this.loadedPlugins) {\n if (plugin.source !== 'github' || plugin.status === 'inactive' || plugin.status === 'blocked') continue;\n const checkoutPath = this.resolvePluginSourcePath(plugin);\n if (seen.has(checkoutPath) || !fs.existsSync(path.join(checkoutPath, '.git'))) continue;\n seen.add(checkoutPath);\n\n const before = await this.readGitHead(checkoutPath);\n const checkoutChanged = await this.refreshGithubCheckout(plugin, checkoutPath, before);\n const after = await this.readGitHead(checkoutPath);\n if (checkoutChanged || before !== after) changed = true;\n }\n\n if (changed) {\n await this.reload();\n }\n return changed;\n }\n\n private async refreshGithubCheckout(\n plugin: LoadedPlugin,\n checkoutPath: string,\n currentHead: string,\n ): Promise<boolean> {\n await execa('git', ['fetch', 'origin'], gitExecOptions(checkoutPath));\n const upstream = await this.resolveGitUpstream(checkoutPath, plugin.ref);\n if (!upstream) return false;\n const [localOnly, remoteOnly] = await this.readGitAheadBehind(checkoutPath, upstream);\n const hasLocalChanges = await this.hasGitWorkingTreeChanges(checkoutPath);\n\n if (localOnly > 0 || hasLocalChanges) {\n await this.backupGitCheckout(checkoutPath, currentHead, hasLocalChanges);\n }\n\n if (remoteOnly > 0 || localOnly > 0 || hasLocalChanges) {\n await execa('git', ['reset', '--hard', upstream], gitExecOptions(checkoutPath));\n return true;\n }\n\n return false;\n }\n\n private async backupGitCheckout(\n checkoutPath: string,\n currentHead: string,\n includeWorkingTree: boolean,\n ): Promise<void> {\n const backupBranch = this.createGitBackupBranchName(currentHead);\n\n if (includeWorkingTree) {\n const currentBranch = await this.readGitCurrentBranch(checkoutPath);\n await execa('git', ['switch', '-c', backupBranch], gitExecOptions(checkoutPath));\n await execa('git', ['add', '-A'], gitExecOptions(checkoutPath));\n const hasStagedChanges = await this.hasGitStagedChanges(checkoutPath);\n if (hasStagedChanges) {\n await execa(\n 'git',\n [\n '-c',\n 'user.name=Mastra Code',\n '-c',\n 'user.email=noreply@mastra.ai',\n 'commit',\n '-m',\n 'chore: backup local plugin checkout changes',\n ],\n gitExecOptions(checkoutPath),\n );\n }\n await this.restoreGitCheckout(checkoutPath, currentBranch, currentHead);\n return;\n }\n\n await execa('git', ['branch', backupBranch, 'HEAD'], gitExecOptions(checkoutPath));\n }\n\n private async resolveGitUpstream(cwd: string, installedRef?: string): Promise<string | undefined> {\n try {\n const { stdout } = await execa(\n 'git',\n ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'],\n gitExecOptions(cwd),\n );\n return stdout.trim();\n } catch {\n return installedRef ? undefined : 'origin/main';\n }\n }\n\n private async readGitAheadBehind(cwd: string, upstream: string): Promise<[number, number]> {\n const { stdout } = await execa(\n 'git',\n ['rev-list', '--left-right', '--count', `HEAD...${upstream}`],\n gitExecOptions(cwd),\n );\n const [ahead = '0', behind = '0'] = stdout.trim().split(/\\s+/);\n return [Number(ahead) || 0, Number(behind) || 0];\n }\n\n private async hasGitWorkingTreeChanges(cwd: string): Promise<boolean> {\n const { stdout } = await execa('git', ['status', '--porcelain'], gitExecOptions(cwd));\n return stdout.trim().length > 0;\n }\n\n private async hasGitStagedChanges(cwd: string): Promise<boolean> {\n try {\n await execa('git', ['diff', '--cached', '--quiet'], gitExecOptions(cwd));\n return false;\n } catch {\n return true;\n }\n }\n\n private async restoreGitCheckout(cwd: string, branch: string | undefined, fallbackHead: string): Promise<void> {\n if (branch) {\n await execa('git', ['switch', branch], gitExecOptions(cwd));\n return;\n }\n await execa('git', ['checkout', fallbackHead], gitExecOptions(cwd));\n }\n\n private async readGitCurrentBranch(cwd: string): Promise<string | undefined> {\n const { stdout } = await execa('git', ['branch', '--show-current'], gitExecOptions(cwd));\n const branch = stdout.trim();\n return branch.length > 0 ? branch : undefined;\n }\n\n private createGitBackupBranchName(currentHead: string): string {\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n return `mastracode/plugin-backup/${timestamp}-${currentHead.slice(0, 8)}`;\n }\n\n private resolvePluginSourcePath(plugin: LoadedPlugin): string {\n const paths = getPluginScopePaths(plugin.scope, this.options);\n return path.isAbsolute(plugin.path) ? plugin.path : path.join(paths.root, plugin.path);\n }\n\n private async readGitHead(cwd: string): Promise<string> {\n const { stdout } = await execa('git', ['rev-parse', 'HEAD'], gitExecOptions(cwd));\n return stdout.trim();\n }\n\n discoverLocal(searchRoot = '.'): ReturnType<typeof discoverLocalPlugins> {\n return discoverLocalPlugins(searchRoot, this.options);\n }\n\n async installLocal(\n localPath: string,\n scope: PluginScope,\n options: Pick<InstallPluginOptions, 'entry'> = {},\n ): Promise<string> {\n const id = await installLocalPlugin(localPath, scope, { ...this.options, ...options });\n await this.reload();\n return id;\n }\n\n async installGithub(\n url: string,\n scope: PluginScope,\n options: Pick<InstallPluginOptions, 'entry' | 'ref'> = {},\n ): Promise<string> {\n const id = await installGithubPlugin(url, scope, { ...this.options, ...options });\n await this.reload();\n return id;\n }\n\n async setEnabled(pluginId: string, scope: PluginScope, enabled: boolean): Promise<void> {\n const paths = getPluginScopePaths(scope, this.options);\n const registry = loadPluginRegistry(paths.registryPath);\n const record = registry.plugins[pluginId];\n if (!record) {\n throw new Error(`Plugin \"${pluginId}\" is not installed in ${scope} scope`);\n }\n savePluginRegistry(paths.registryPath, setPluginRecord(registry, pluginId, { ...record, enabled }));\n await this.reload();\n }\n\n async setConfigValue(\n pluginId: string,\n scope: PluginScope,\n key: string,\n value: MastraCodePluginConfigValue,\n ): Promise<void> {\n const paths = getPluginScopePaths(scope, this.options);\n const registry = loadPluginRegistry(paths.registryPath);\n const record = registry.plugins[pluginId];\n if (!record) {\n throw new Error(`Plugin \"${pluginId}\" is not installed in ${scope} scope`);\n }\n const config = { ...(record.config ?? {}) };\n if (value === undefined || value === '') {\n delete config[key];\n } else {\n config[key] = value;\n }\n const nextRecord = { ...record, config: Object.keys(config).length > 0 ? config : undefined };\n savePluginRegistry(paths.registryPath, setPluginRecord(registry, pluginId, nextRecord));\n await this.reload();\n }\n\n async uninstall(pluginId: string, scope: PluginScope): Promise<void> {\n const paths = getPluginScopePaths(scope, this.options);\n const registry = loadPluginRegistry(paths.registryPath);\n const record = registry.plugins[pluginId];\n if (!record) {\n throw new Error(`Plugin \"${pluginId}\" is not installed in ${scope} scope`);\n }\n\n savePluginRegistry(paths.registryPath, removePluginRecord(registry, pluginId));\n if (record.source === 'github') {\n const checkoutPath = path.resolve(\n path.isAbsolute(record.path) ? record.path : path.join(paths.root, record.path),\n );\n const githubSourcesPath = path.resolve(paths.sourcesPath, 'github');\n if (isInsideDirectory(checkoutPath, githubSourcesPath)) {\n fs.rmSync(checkoutPath, { recursive: true, force: true });\n }\n }\n await this.reload();\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/plugins/manager.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { execa } from 'execa';\n\nimport type { MastraCodePluginConfigValue } from '../plugin.js';\nimport { getEntryPackageRoot, installPluginDependenciesForEntry } from './dependencies.js';\nimport { discoverLocalPlugins, installGithubPlugin, installLocalPlugin, NON_INTERACTIVE_GIT_ENV } from './install.js';\nimport type { InstallPluginOptions } from './install.js';\nimport { collectActivePluginTools, isInsideDirectory, loadPlugins, resolvePluginEntryPath } from './loader.js';\nimport { ensureMastraCodePackageLink } from './package-link.js';\nimport { getPluginScopePaths } from './paths.js';\nimport type { PluginPathOptions } from './paths.js';\nimport { loadPluginRegistry, removePluginRecord, savePluginRegistry, setPluginRecord } from './registry.js';\nimport type { LoadedPlugin, PluginScope } from './types.js';\n\nconst GITHUB_PLUGIN_POLL_INTERVAL_MS = 60_000;\n\nfunction gitExecOptions(cwd: string) {\n return { cwd, env: NON_INTERACTIVE_GIT_ENV };\n}\n\nfunction getEntryVersion(entryPath: string): string {\n const stat = fs.statSync(entryPath, { bigint: true });\n return `${stat.mtimeNs}:${stat.size}`;\n}\n\ntype PluginManagerOptions = PluginPathOptions & {\n githubCliPath?: string;\n};\n\nexport class PluginManager {\n private loadedPlugins: LoadedPlugin[] = [];\n private readonly pluginTools: ReturnType<typeof collectActivePluginTools> = {};\n private readonly rawPluginTools: ReturnType<typeof collectActivePluginTools> = {};\n private readonly toolRenderConfigs = new Map<string, NonNullable<LoadedPlugin['renderConfigs']>[string]>();\n private readonly watchedLocalEntries = new Set<string>();\n private readonly localEntryVersions = new Map<string, string>();\n private githubPollTimer: ReturnType<typeof setInterval> | undefined;\n private githubPollInFlight: Promise<boolean> | undefined;\n private reloadInFlight: Promise<LoadedPlugin[]> | undefined;\n private readonly reloadListeners = new Set<(plugins: LoadedPlugin[]) => void | Promise<void>>();\n\n constructor(private readonly options: PluginManagerOptions) {}\n\n onReload(listener: (plugins: LoadedPlugin[]) => void | Promise<void>): () => void {\n this.reloadListeners.add(listener);\n return () => this.reloadListeners.delete(listener);\n }\n\n async reload(): Promise<LoadedPlugin[]> {\n if (this.reloadInFlight) return this.reloadInFlight;\n\n this.reloadInFlight = (async () => {\n this.loadedPlugins = await loadPlugins(this.options);\n this.updateLocalEntryWatchers(this.loadedPlugins);\n this.updateGithubPoller(this.loadedPlugins);\n this.updatePluginRenderConfigs(this.loadedPlugins);\n this.updatePluginTools(collectActivePluginTools(this.loadedPlugins));\n await this.notifyReloadListeners(this.loadedPlugins);\n return this.loadedPlugins;\n })().finally(() => {\n this.reloadInFlight = undefined;\n });\n\n return this.reloadInFlight;\n }\n\n async listPlugins(): Promise<LoadedPlugin[]> {\n if (this.loadedPlugins.length === 0) {\n await this.reload();\n }\n return this.loadedPlugins;\n }\n\n getLoadedPlugins(): LoadedPlugin[] {\n return this.loadedPlugins;\n }\n\n getPluginTools() {\n return this.pluginTools;\n }\n\n getToolRenderConfig(toolName: string) {\n return this.toolRenderConfigs.get(toolName);\n }\n\n getPluginSkillPaths(): string[] {\n return this.loadedPlugins.flatMap(plugin => (plugin.status === 'active' ? (plugin.skillPaths ?? []) : []));\n }\n\n getPluginCommandPaths(): string[] {\n return this.loadedPlugins.flatMap(plugin => (plugin.status === 'active' ? (plugin.commandPaths ?? []) : []));\n }\n\n getPluginInstructions(): string[] {\n return this.loadedPlugins.flatMap(plugin =>\n plugin.status === 'active' && plugin.instructions ? [plugin.instructions] : [],\n );\n }\n\n private async notifyReloadListeners(plugins: LoadedPlugin[]): Promise<void> {\n await Promise.all([...this.reloadListeners].map(listener => Promise.resolve(listener(plugins))));\n }\n\n private updatePluginRenderConfigs(plugins: LoadedPlugin[]): void {\n this.toolRenderConfigs.clear();\n for (const plugin of plugins) {\n if (plugin.status !== 'active') continue;\n for (const [toolName, renderConfig] of Object.entries(plugin.renderConfigs ?? {})) {\n if (!this.toolRenderConfigs.has(toolName)) {\n this.toolRenderConfigs.set(toolName, renderConfig);\n }\n }\n }\n }\n\n private updatePluginTools(nextTools: ReturnType<typeof collectActivePluginTools>): void {\n for (const name of Object.keys(this.rawPluginTools)) {\n if (!(name in nextTools)) {\n delete this.rawPluginTools[name];\n delete this.pluginTools[name];\n }\n }\n\n for (const [name, tool] of Object.entries(nextTools)) {\n this.rawPluginTools[name] = tool;\n if (!this.pluginTools[name]) {\n this.pluginTools[name] = this.createLiveToolProxy(name);\n }\n this.syncLiveToolProxy(name, tool);\n }\n }\n\n private createLiveToolProxy(toolName: string) {\n return {\n execute: async (...args: any[]) => {\n await this.reloadChangedLocalPlugins();\n const latestTool = this.rawPluginTools[toolName];\n if (!latestTool?.execute) {\n throw new Error(`Plugin tool \"${toolName}\" is no longer available`);\n }\n return (latestTool.execute as (...args: any[]) => unknown)(...args);\n },\n } as LoadedPlugin['tools'][string];\n }\n\n private syncLiveToolProxy(toolName: string, tool: LoadedPlugin['tools'][string]): void {\n const proxy = this.pluginTools[toolName];\n if (!proxy) return;\n const mutableProxy = proxy as unknown as Record<string, unknown>;\n for (const key of Object.keys(mutableProxy)) {\n delete mutableProxy[key];\n }\n Object.assign(proxy, tool);\n proxy.execute = this.createLiveToolProxy(toolName).execute;\n }\n\n private async reloadChangedLocalPlugins(): Promise<void> {\n for (const plugin of this.loadedPlugins) {\n if (plugin.source !== 'local' || plugin.status !== 'active') continue;\n const entryPath = resolvePluginEntryPath(plugin, this.options);\n const currentVersion = getEntryVersion(entryPath);\n if (this.localEntryVersions.get(entryPath) !== currentVersion) {\n await this.reload();\n return;\n }\n }\n }\n\n private updateLocalEntryWatchers(plugins: LoadedPlugin[]): void {\n const nextEntries = new Set<string>();\n for (const plugin of plugins) {\n if (plugin.source !== 'local' || plugin.status !== 'active') continue;\n let entryPath: string;\n let entryVersion: string;\n try {\n entryPath = resolvePluginEntryPath(plugin, this.options);\n entryVersion = getEntryVersion(entryPath);\n } catch {\n continue;\n }\n nextEntries.add(entryPath);\n this.localEntryVersions.set(entryPath, entryVersion);\n if (this.watchedLocalEntries.has(entryPath)) continue;\n\n const watcher = fs.watchFile(entryPath, { interval: 500 }, (current, previous) => {\n if (current.mtimeMs === previous.mtimeMs) return;\n void this.reload().catch(() => undefined);\n });\n watcher.unref?.();\n this.watchedLocalEntries.add(entryPath);\n }\n\n for (const entryPath of this.watchedLocalEntries) {\n if (nextEntries.has(entryPath)) continue;\n fs.unwatchFile(entryPath);\n this.watchedLocalEntries.delete(entryPath);\n this.localEntryVersions.delete(entryPath);\n }\n }\n\n private updateGithubPoller(plugins: LoadedPlugin[]): void {\n const hasGithubPlugin = plugins.some(\n plugin => plugin.source === 'github' && plugin.status !== 'inactive' && plugin.status !== 'blocked',\n );\n if (hasGithubPlugin && !this.githubPollTimer) {\n this.githubPollTimer = setInterval(() => {\n void this.pollGithubSourcesForUpdates().catch(() => undefined);\n }, GITHUB_PLUGIN_POLL_INTERVAL_MS);\n this.githubPollTimer.unref?.();\n }\n if (!hasGithubPlugin && this.githubPollTimer) {\n clearInterval(this.githubPollTimer);\n this.githubPollTimer = undefined;\n }\n }\n\n async pollGithubSourcesForUpdates(): Promise<boolean> {\n if (this.githubPollInFlight) return this.githubPollInFlight;\n this.githubPollInFlight = this.pollGithubSourcesForUpdatesOnce().finally(() => {\n this.githubPollInFlight = undefined;\n });\n return this.githubPollInFlight;\n }\n\n private async pollGithubSourcesForUpdatesOnce(): Promise<boolean> {\n let changed = false;\n const seen = new Set<string>();\n for (const plugin of this.loadedPlugins) {\n if (plugin.source !== 'github' || plugin.status === 'inactive' || plugin.status === 'blocked') continue;\n const checkoutPath = this.resolvePluginSourcePath(plugin);\n if (seen.has(checkoutPath) || !fs.existsSync(path.join(checkoutPath, '.git'))) continue;\n seen.add(checkoutPath);\n\n const before = await this.readGitHead(checkoutPath);\n const checkoutChanged = await this.refreshGithubCheckout(plugin, checkoutPath, before);\n const after = await this.readGitHead(checkoutPath);\n if (checkoutChanged || before !== after) changed = true;\n }\n\n if (changed) {\n await this.reload();\n }\n return changed;\n }\n\n private async refreshGithubCheckout(\n plugin: LoadedPlugin,\n checkoutPath: string,\n currentHead: string,\n ): Promise<boolean> {\n await execa('git', ['fetch', 'origin'], gitExecOptions(checkoutPath));\n const upstream = await this.resolveGitUpstream(checkoutPath, plugin.ref);\n if (!upstream) return false;\n const [localOnly, remoteOnly] = await this.readGitAheadBehind(checkoutPath, upstream);\n const hasLocalChanges = await this.hasGitWorkingTreeChanges(checkoutPath);\n\n if (localOnly > 0 || hasLocalChanges) {\n await this.backupGitCheckout(checkoutPath, currentHead, hasLocalChanges);\n }\n\n if (remoteOnly > 0 || localOnly > 0 || hasLocalChanges) {\n await execa('git', ['reset', '--hard', upstream], gitExecOptions(checkoutPath));\n try {\n await installPluginDependenciesForEntry(checkoutPath, plugin.entry);\n ensureMastraCodePackageLink(getEntryPackageRoot(checkoutPath, plugin.entry));\n } catch (error) {\n await execa('git', ['reset', '--hard', currentHead], gitExecOptions(checkoutPath));\n throw error;\n }\n return true;\n }\n\n return false;\n }\n\n private async backupGitCheckout(\n checkoutPath: string,\n currentHead: string,\n includeWorkingTree: boolean,\n ): Promise<void> {\n const backupBranch = this.createGitBackupBranchName(currentHead);\n\n if (includeWorkingTree) {\n const currentBranch = await this.readGitCurrentBranch(checkoutPath);\n await execa('git', ['switch', '-c', backupBranch], gitExecOptions(checkoutPath));\n await execa('git', ['add', '-A'], gitExecOptions(checkoutPath));\n const hasStagedChanges = await this.hasGitStagedChanges(checkoutPath);\n if (hasStagedChanges) {\n await execa(\n 'git',\n [\n '-c',\n 'user.name=Mastra Code',\n '-c',\n 'user.email=noreply@mastra.ai',\n 'commit',\n '-m',\n 'chore: backup local plugin checkout changes',\n ],\n gitExecOptions(checkoutPath),\n );\n }\n await this.restoreGitCheckout(checkoutPath, currentBranch, currentHead);\n return;\n }\n\n await execa('git', ['branch', backupBranch, 'HEAD'], gitExecOptions(checkoutPath));\n }\n\n private async resolveGitUpstream(cwd: string, installedRef?: string): Promise<string | undefined> {\n try {\n const { stdout } = await execa(\n 'git',\n ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}'],\n gitExecOptions(cwd),\n );\n return stdout.trim();\n } catch {\n return installedRef ? undefined : 'origin/main';\n }\n }\n\n private async readGitAheadBehind(cwd: string, upstream: string): Promise<[number, number]> {\n const { stdout } = await execa(\n 'git',\n ['rev-list', '--left-right', '--count', `HEAD...${upstream}`],\n gitExecOptions(cwd),\n );\n const [ahead = '0', behind = '0'] = stdout.trim().split(/\\s+/);\n return [Number(ahead) || 0, Number(behind) || 0];\n }\n\n private async hasGitWorkingTreeChanges(cwd: string): Promise<boolean> {\n const { stdout } = await execa('git', ['status', '--porcelain'], gitExecOptions(cwd));\n return stdout.trim().length > 0;\n }\n\n private async hasGitStagedChanges(cwd: string): Promise<boolean> {\n try {\n await execa('git', ['diff', '--cached', '--quiet'], gitExecOptions(cwd));\n return false;\n } catch {\n return true;\n }\n }\n\n private async restoreGitCheckout(cwd: string, branch: string | undefined, fallbackHead: string): Promise<void> {\n if (branch) {\n await execa('git', ['switch', branch], gitExecOptions(cwd));\n return;\n }\n await execa('git', ['checkout', fallbackHead], gitExecOptions(cwd));\n }\n\n private async readGitCurrentBranch(cwd: string): Promise<string | undefined> {\n const { stdout } = await execa('git', ['branch', '--show-current'], gitExecOptions(cwd));\n const branch = stdout.trim();\n return branch.length > 0 ? branch : undefined;\n }\n\n private createGitBackupBranchName(currentHead: string): string {\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n return `mastracode/plugin-backup/${timestamp}-${currentHead.slice(0, 8)}`;\n }\n\n private resolvePluginSourcePath(plugin: LoadedPlugin): string {\n const paths = getPluginScopePaths(plugin.scope, this.options);\n return path.isAbsolute(plugin.path) ? plugin.path : path.join(paths.root, plugin.path);\n }\n\n private async readGitHead(cwd: string): Promise<string> {\n const { stdout } = await execa('git', ['rev-parse', 'HEAD'], gitExecOptions(cwd));\n return stdout.trim();\n }\n\n discoverLocal(searchRoot = '.'): ReturnType<typeof discoverLocalPlugins> {\n return discoverLocalPlugins(searchRoot, this.options);\n }\n\n async installLocal(\n localPath: string,\n scope: PluginScope,\n options: Pick<InstallPluginOptions, 'entry'> = {},\n ): Promise<string> {\n const id = await installLocalPlugin(localPath, scope, { ...this.options, ...options });\n await this.reload();\n return id;\n }\n\n async installGithub(\n url: string,\n scope: PluginScope,\n options: Pick<InstallPluginOptions, 'entry' | 'ref' | 'onOutput' | 'signal'> = {},\n ): Promise<string> {\n const id = await installGithubPlugin(url, scope, { ...this.options, ...options });\n await this.reload();\n return id;\n }\n\n async setEnabled(pluginId: string, scope: PluginScope, enabled: boolean): Promise<void> {\n const paths = getPluginScopePaths(scope, this.options);\n const registry = loadPluginRegistry(paths.registryPath);\n const record = registry.plugins[pluginId];\n if (!record) {\n throw new Error(`Plugin \"${pluginId}\" is not installed in ${scope} scope`);\n }\n savePluginRegistry(paths.registryPath, setPluginRecord(registry, pluginId, { ...record, enabled }));\n await this.reload();\n }\n\n async setConfigValue(\n pluginId: string,\n scope: PluginScope,\n key: string,\n value: MastraCodePluginConfigValue,\n ): Promise<void> {\n const paths = getPluginScopePaths(scope, this.options);\n const registry = loadPluginRegistry(paths.registryPath);\n const record = registry.plugins[pluginId];\n if (!record) {\n throw new Error(`Plugin \"${pluginId}\" is not installed in ${scope} scope`);\n }\n const config = { ...(record.config ?? {}) };\n if (value === undefined || value === '') {\n delete config[key];\n } else {\n config[key] = value;\n }\n const nextRecord = { ...record, config: Object.keys(config).length > 0 ? config : undefined };\n savePluginRegistry(paths.registryPath, setPluginRecord(registry, pluginId, nextRecord));\n await this.reload();\n }\n\n async uninstall(pluginId: string, scope: PluginScope): Promise<void> {\n const paths = getPluginScopePaths(scope, this.options);\n const registry = loadPluginRegistry(paths.registryPath);\n const record = registry.plugins[pluginId];\n if (!record) {\n throw new Error(`Plugin \"${pluginId}\" is not installed in ${scope} scope`);\n }\n\n savePluginRegistry(paths.registryPath, removePluginRecord(registry, pluginId));\n if (record.source === 'github') {\n const checkoutPath = path.resolve(\n path.isAbsolute(record.path) ? record.path : path.join(paths.root, record.path),\n );\n const githubSourcesPath = path.resolve(paths.sourcesPath, 'github');\n if (isInsideDirectory(checkoutPath, githubSourcesPath)) {\n fs.rmSync(checkoutPath, { recursive: true, force: true });\n }\n }\n await this.reload();\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package-link.d.ts","sourceRoot":"","sources":["../../src/plugins/package-link.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"package-link.d.ts","sourceRoot":"","sources":["../../src/plugins/package-link.ts"],"names":[],"mappings":"AA+BA,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA4BlE;AAED,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAmBnE"}
|
|
@@ -1,20 +1,77 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
const
|
|
4
|
+
const MODULE_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
let cachedPackageRoot;
|
|
6
|
+
function mastraCodePackageRoot() {
|
|
7
|
+
if (cachedPackageRoot === void 0) {
|
|
8
|
+
try {
|
|
9
|
+
cachedPackageRoot = findMastraCodePackageRoot(MODULE_DIR);
|
|
10
|
+
} catch (error) {
|
|
11
|
+
const entryScript = process.argv[1];
|
|
12
|
+
if (!entryScript) throw error;
|
|
13
|
+
cachedPackageRoot = findMastraCodePackageRoot(path.dirname(fs.realpathSync(entryScript)));
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return cachedPackageRoot;
|
|
17
|
+
}
|
|
18
|
+
function readPackageName(dir) {
|
|
19
|
+
const packageJsonPath = path.join(dir, "package.json");
|
|
20
|
+
if (!fs.existsSync(packageJsonPath)) return void 0;
|
|
21
|
+
return JSON.parse(fs.readFileSync(packageJsonPath, "utf8")).name;
|
|
22
|
+
}
|
|
23
|
+
function findMastraCodePackageRoot(startDir) {
|
|
24
|
+
let currentDir = path.resolve(startDir);
|
|
25
|
+
while (true) {
|
|
26
|
+
const packageName = readPackageName(currentDir);
|
|
27
|
+
if (packageName === "mastracode") {
|
|
28
|
+
return currentDir;
|
|
29
|
+
}
|
|
30
|
+
if (packageName === "@mastra/code-sdk") {
|
|
31
|
+
for (const candidate of [
|
|
32
|
+
path.resolve(currentDir, "..", "tui"),
|
|
33
|
+
path.resolve(currentDir, "..", "..", "mastracode")
|
|
34
|
+
]) {
|
|
35
|
+
if (readPackageName(candidate) === "mastracode") {
|
|
36
|
+
return candidate;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const parentDir = path.dirname(currentDir);
|
|
41
|
+
if (parentDir === currentDir) {
|
|
42
|
+
throw new Error(`Could not find mastracode package root from ${startDir}`);
|
|
43
|
+
}
|
|
44
|
+
currentDir = parentDir;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
5
47
|
function ensureMastraCodePackageLink(pluginDir) {
|
|
48
|
+
if (declaresInstallableMastraCodeDependency(pluginDir)) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const packageRoot = mastraCodePackageRoot();
|
|
6
52
|
const nodeModulesDir = path.join(pluginDir, "node_modules");
|
|
7
53
|
const linkPath = path.join(nodeModulesDir, "mastracode");
|
|
8
54
|
try {
|
|
9
|
-
fs.
|
|
10
|
-
|
|
55
|
+
if (fs.realpathSync(linkPath) === fs.realpathSync(packageRoot)) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
fs.rmSync(linkPath, { recursive: true, force: true });
|
|
11
59
|
} catch (error) {
|
|
12
60
|
if (error.code !== "ENOENT") throw error;
|
|
13
61
|
}
|
|
14
62
|
fs.mkdirSync(nodeModulesDir, { recursive: true });
|
|
15
|
-
fs.symlinkSync(
|
|
63
|
+
fs.symlinkSync(packageRoot, linkPath, "dir");
|
|
64
|
+
}
|
|
65
|
+
function declaresInstallableMastraCodeDependency(pluginDir) {
|
|
66
|
+
const packageJsonPath = path.join(pluginDir, "package.json");
|
|
67
|
+
if (!fs.existsSync(packageJsonPath)) return false;
|
|
68
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
69
|
+
return Boolean(
|
|
70
|
+
packageJson.dependencies?.mastracode ?? packageJson.devDependencies?.mastracode ?? packageJson.optionalDependencies?.mastracode
|
|
71
|
+
);
|
|
16
72
|
}
|
|
17
73
|
export {
|
|
18
|
-
ensureMastraCodePackageLink
|
|
74
|
+
ensureMastraCodePackageLink,
|
|
75
|
+
findMastraCodePackageRoot
|
|
19
76
|
};
|
|
20
77
|
//# sourceMappingURL=package-link.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugins/package-link.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst
|
|
1
|
+
{"version":3,"sources":["../../src/plugins/package-link.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst MODULE_DIR = path.dirname(fileURLToPath(import.meta.url));\n\nlet cachedPackageRoot: string | undefined;\n\n// This module ships in @mastra/code-sdk, so the `mastracode` package root is\n// resolved lazily: from the module location (source tree / bundled dist), or —\n// for the published CLI where the sdk is an external dependency — from the\n// entry script, which lives inside the `mastracode` package.\nfunction mastraCodePackageRoot(): string {\n if (cachedPackageRoot === undefined) {\n try {\n cachedPackageRoot = findMastraCodePackageRoot(MODULE_DIR);\n } catch (error) {\n const entryScript = process.argv[1];\n if (!entryScript) throw error;\n cachedPackageRoot = findMastraCodePackageRoot(path.dirname(fs.realpathSync(entryScript)));\n }\n }\n return cachedPackageRoot;\n}\n\nfunction readPackageName(dir: string): string | undefined {\n const packageJsonPath = path.join(dir, 'package.json');\n if (!fs.existsSync(packageJsonPath)) return undefined;\n return (JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) as { name?: string }).name;\n}\n\nexport function findMastraCodePackageRoot(startDir: string): string {\n let currentDir = path.resolve(startDir);\n\n while (true) {\n const packageName = readPackageName(currentDir);\n if (packageName === 'mastracode') {\n return currentDir;\n }\n if (packageName === '@mastra/code-sdk') {\n // The `mastracode` package sits next to the sdk: mastracode/sdk ↔\n // mastracode/tui in the source tree, node_modules/@mastra/code-sdk ↔\n // node_modules/mastracode when installed.\n for (const candidate of [\n path.resolve(currentDir, '..', 'tui'),\n path.resolve(currentDir, '..', '..', 'mastracode'),\n ]) {\n if (readPackageName(candidate) === 'mastracode') {\n return candidate;\n }\n }\n }\n\n const parentDir = path.dirname(currentDir);\n if (parentDir === currentDir) {\n throw new Error(`Could not find mastracode package root from ${startDir}`);\n }\n currentDir = parentDir;\n }\n}\n\nexport function ensureMastraCodePackageLink(pluginDir: string): void {\n if (declaresInstallableMastraCodeDependency(pluginDir)) {\n return;\n }\n\n const packageRoot = mastraCodePackageRoot();\n const nodeModulesDir = path.join(pluginDir, 'node_modules');\n const linkPath = path.join(nodeModulesDir, 'mastracode');\n try {\n if (fs.realpathSync(linkPath) === fs.realpathSync(packageRoot)) {\n return;\n }\n fs.rmSync(linkPath, { recursive: true, force: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;\n }\n\n fs.mkdirSync(nodeModulesDir, { recursive: true });\n fs.symlinkSync(packageRoot, linkPath, 'dir');\n}\n\nfunction declaresInstallableMastraCodeDependency(pluginDir: string): boolean {\n const packageJsonPath = path.join(pluginDir, 'package.json');\n if (!fs.existsSync(packageJsonPath)) return false;\n\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')) as {\n dependencies?: Record<string, unknown>;\n devDependencies?: Record<string, unknown>;\n optionalDependencies?: Record<string, unknown>;\n };\n\n return Boolean(\n packageJson.dependencies?.mastracode ??\n packageJson.devDependencies?.mastracode ??\n packageJson.optionalDependencies?.mastracode,\n );\n}\n"],"mappings":"AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAE9B,MAAM,aAAa,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAE9D,IAAI;AAMJ,SAAS,wBAAgC;AACvC,MAAI,sBAAsB,QAAW;AACnC,QAAI;AACF,0BAAoB,0BAA0B,UAAU;AAAA,IAC1D,SAAS,OAAO;AACd,YAAM,cAAc,QAAQ,KAAK,CAAC;AAClC,UAAI,CAAC,YAAa,OAAM;AACxB,0BAAoB,0BAA0B,KAAK,QAAQ,GAAG,aAAa,WAAW,CAAC,CAAC;AAAA,IAC1F;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,KAAiC;AACxD,QAAM,kBAAkB,KAAK,KAAK,KAAK,cAAc;AACrD,MAAI,CAAC,GAAG,WAAW,eAAe,EAAG,QAAO;AAC5C,SAAQ,KAAK,MAAM,GAAG,aAAa,iBAAiB,MAAM,CAAC,EAAwB;AACrF;AAEO,SAAS,0BAA0B,UAA0B;AAClE,MAAI,aAAa,KAAK,QAAQ,QAAQ;AAEtC,SAAO,MAAM;AACX,UAAM,cAAc,gBAAgB,UAAU;AAC9C,QAAI,gBAAgB,cAAc;AAChC,aAAO;AAAA,IACT;AACA,QAAI,gBAAgB,oBAAoB;AAItC,iBAAW,aAAa;AAAA,QACtB,KAAK,QAAQ,YAAY,MAAM,KAAK;AAAA,QACpC,KAAK,QAAQ,YAAY,MAAM,MAAM,YAAY;AAAA,MACnD,GAAG;AACD,YAAI,gBAAgB,SAAS,MAAM,cAAc;AAC/C,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAEA,UAAM,YAAY,KAAK,QAAQ,UAAU;AACzC,QAAI,cAAc,YAAY;AAC5B,YAAM,IAAI,MAAM,+CAA+C,QAAQ,EAAE;AAAA,IAC3E;AACA,iBAAa;AAAA,EACf;AACF;AAEO,SAAS,4BAA4B,WAAyB;AACnE,MAAI,wCAAwC,SAAS,GAAG;AACtD;AAAA,EACF;AAEA,QAAM,cAAc,sBAAsB;AAC1C,QAAM,iBAAiB,KAAK,KAAK,WAAW,cAAc;AAC1D,QAAM,WAAW,KAAK,KAAK,gBAAgB,YAAY;AACvD,MAAI;AACF,QAAI,GAAG,aAAa,QAAQ,MAAM,GAAG,aAAa,WAAW,GAAG;AAC9D;AAAA,IACF;AACA,OAAG,OAAO,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EACtD,SAAS,OAAO;AACd,QAAK,MAAgC,SAAS,SAAU,OAAM;AAAA,EAChE;AAEA,KAAG,UAAU,gBAAgB,EAAE,WAAW,KAAK,CAAC;AAChD,KAAG,YAAY,aAAa,UAAU,KAAK;AAC7C;AAEA,SAAS,wCAAwC,WAA4B;AAC3E,QAAM,kBAAkB,KAAK,KAAK,WAAW,cAAc;AAC3D,MAAI,CAAC,GAAG,WAAW,eAAe,EAAG,QAAO;AAE5C,QAAM,cAAc,KAAK,MAAM,GAAG,aAAa,iBAAiB,MAAM,CAAC;AAMvE,SAAO;AAAA,IACL,YAAY,cAAc,cAC1B,YAAY,iBAAiB,cAC7B,YAAY,sBAAsB;AAAA,EACpC;AACF;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/code-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.1.0-alpha.1",
|
|
4
4
|
"description": "Mastra Code SDK: the agent core behind Mastra Code (everything except the TUI) — build your own UIs and surfaces on top of it",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -27,12 +27,6 @@
|
|
|
27
27
|
},
|
|
28
28
|
"./package.json": "./package.json"
|
|
29
29
|
},
|
|
30
|
-
"scripts": {
|
|
31
|
-
"build:lib": "tsup --silent --config tsup.config.ts",
|
|
32
|
-
"check": "tsc --noEmit",
|
|
33
|
-
"test": "vitest run",
|
|
34
|
-
"lint": "eslint ."
|
|
35
|
-
},
|
|
36
30
|
"keywords": [],
|
|
37
31
|
"author": "",
|
|
38
32
|
"license": "Apache-2.0",
|
|
@@ -40,7 +34,7 @@
|
|
|
40
34
|
"repository": {
|
|
41
35
|
"type": "git",
|
|
42
36
|
"url": "git+https://github.com/mastra-ai/mastra.git",
|
|
43
|
-
"directory": "mastracode/
|
|
37
|
+
"directory": "mastracode/sdk"
|
|
44
38
|
},
|
|
45
39
|
"bugs": {
|
|
46
40
|
"url": "https://github.com/mastra-ai/mastra/issues"
|
|
@@ -53,19 +47,6 @@
|
|
|
53
47
|
"@ai-sdk/openai-compatible": "^2.0.47",
|
|
54
48
|
"@ast-grep/napi": "^0.42.0",
|
|
55
49
|
"@aws-sdk/credential-providers": "^3.864.0",
|
|
56
|
-
"@mastra/agent-browser": "workspace:*",
|
|
57
|
-
"@mastra/core": "workspace:*",
|
|
58
|
-
"@mastra/duckdb": "workspace:*",
|
|
59
|
-
"@mastra/fastembed": "workspace:*",
|
|
60
|
-
"@mastra/github-signals": "workspace:*",
|
|
61
|
-
"@mastra/libsql": "workspace:*",
|
|
62
|
-
"@mastra/mcp": "workspace:*",
|
|
63
|
-
"@mastra/memory": "workspace:*",
|
|
64
|
-
"@mastra/observability": "workspace:*",
|
|
65
|
-
"@mastra/pg": "workspace:*",
|
|
66
|
-
"@mastra/schema-compat": "workspace:*",
|
|
67
|
-
"@mastra/stagehand": "workspace:*",
|
|
68
|
-
"@mastra/tavily": "workspace:*",
|
|
69
50
|
"ai": "^6.0.176",
|
|
70
51
|
"execa": "^9.6.1",
|
|
71
52
|
"posthog-node": "^5.37.0",
|
|
@@ -73,20 +54,39 @@
|
|
|
73
54
|
"vscode-jsonrpc": "^8.2.1",
|
|
74
55
|
"vscode-languageserver-protocol": "^3.17.5",
|
|
75
56
|
"yaml": "^2.7.1",
|
|
76
|
-
"zod": "^4.3.6"
|
|
57
|
+
"zod": "^4.3.6",
|
|
58
|
+
"@mastra/agent-browser": "0.4.1",
|
|
59
|
+
"@mastra/duckdb": "1.5.1",
|
|
60
|
+
"@mastra/fastembed": "1.2.0",
|
|
61
|
+
"@mastra/github-signals": "0.2.2",
|
|
62
|
+
"@mastra/core": "1.50.2-alpha.1",
|
|
63
|
+
"@mastra/mcp": "1.13.1",
|
|
64
|
+
"@mastra/memory": "1.23.0-alpha.1",
|
|
65
|
+
"@mastra/observability": "1.16.0",
|
|
66
|
+
"@mastra/pg": "1.15.1",
|
|
67
|
+
"@mastra/schema-compat": "1.3.4-alpha.0",
|
|
68
|
+
"@mastra/libsql": "1.15.1",
|
|
69
|
+
"@mastra/stagehand": "0.3.0",
|
|
70
|
+
"@mastra/tavily": "1.1.0"
|
|
77
71
|
},
|
|
78
72
|
"devDependencies": {
|
|
79
|
-
"@internal/lint": "workspace:*",
|
|
80
|
-
"@internal/types-builder": "workspace:*",
|
|
81
73
|
"@types/node": "22.19.21",
|
|
82
74
|
"eslint": "^10.4.1",
|
|
83
75
|
"tsup": "^8.5.1",
|
|
84
|
-
"tsx": "
|
|
85
|
-
"typescript": "
|
|
76
|
+
"tsx": "^4.22.4",
|
|
77
|
+
"typescript": "^6.0.3",
|
|
86
78
|
"typescript-eslint": "^8.57.0",
|
|
87
|
-
"vitest": "
|
|
79
|
+
"vitest": "4.1.9",
|
|
80
|
+
"@internal/lint": "0.0.113",
|
|
81
|
+
"@internal/types-builder": "0.0.88"
|
|
88
82
|
},
|
|
89
83
|
"engines": {
|
|
90
84
|
"node": ">=22.19.0"
|
|
85
|
+
},
|
|
86
|
+
"scripts": {
|
|
87
|
+
"build:lib": "tsup --silent --config tsup.config.ts",
|
|
88
|
+
"check": "tsc --noEmit",
|
|
89
|
+
"test": "vitest run",
|
|
90
|
+
"lint": "eslint ."
|
|
91
91
|
}
|
|
92
|
-
}
|
|
92
|
+
}
|