@mastra/code-sdk 1.0.3-alpha.0 → 1.1.0-alpha.2

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.
Files changed (258) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/acp/agent.js +155 -167
  3. package/dist/acp/agent.js.map +1 -1
  4. package/dist/acp/event-mapper.js +193 -168
  5. package/dist/acp/event-mapper.js.map +1 -1
  6. package/dist/acp/index.js +60 -49
  7. package/dist/acp/index.js.map +1 -1
  8. package/dist/acp/server.js +31 -30
  9. package/dist/acp/server.js.map +1 -1
  10. package/dist/acp.js +1 -4
  11. package/dist/agents/credential-resolver.js +40 -29
  12. package/dist/agents/credential-resolver.js.map +1 -1
  13. package/dist/agents/custom-provider-source.js +16 -9
  14. package/dist/agents/custom-provider-source.js.map +1 -1
  15. package/dist/agents/instructions.js +27 -36
  16. package/dist/agents/instructions.js.map +1 -1
  17. package/dist/agents/mastracode-gateway.js +355 -428
  18. package/dist/agents/mastracode-gateway.js.map +1 -1
  19. package/dist/agents/memory.js +87 -78
  20. package/dist/agents/memory.js.map +1 -1
  21. package/dist/agents/model.js +114 -119
  22. package/dist/agents/model.js.map +1 -1
  23. package/dist/agents/modes/build.js +12 -13
  24. package/dist/agents/modes/build.js.map +1 -1
  25. package/dist/agents/modes/explore.js +14 -13
  26. package/dist/agents/modes/explore.js.map +1 -1
  27. package/dist/agents/modes/plan.js +14 -15
  28. package/dist/agents/modes/plan.js.map +1 -1
  29. package/dist/agents/prompts/agent-instructions.js +78 -69
  30. package/dist/agents/prompts/agent-instructions.js.map +1 -1
  31. package/dist/agents/prompts/build.js +19 -16
  32. package/dist/agents/prompts/build.js.map +1 -1
  33. package/dist/agents/prompts/fast.js +8 -4
  34. package/dist/agents/prompts/fast.js.map +1 -1
  35. package/dist/agents/prompts/index.js +48 -47
  36. package/dist/agents/prompts/index.js.map +1 -1
  37. package/dist/agents/prompts/model.js +6 -5
  38. package/dist/agents/prompts/model.js.map +1 -1
  39. package/dist/agents/prompts/plan.js +20 -16
  40. package/dist/agents/prompts/plan.js.map +1 -1
  41. package/dist/agents/prompts/tool-guidance.js +77 -109
  42. package/dist/agents/prompts/tool-guidance.js.map +1 -1
  43. package/dist/agents/sandbox-filesystem.js +245 -259
  44. package/dist/agents/sandbox-filesystem.js.map +1 -1
  45. package/dist/agents/sandbox-reattach.js +9 -11
  46. package/dist/agents/sandbox-reattach.js.map +1 -1
  47. package/dist/agents/thread-caveman-state.js +92 -81
  48. package/dist/agents/thread-caveman-state.js.map +1 -1
  49. package/dist/agents/tool-availability.js +62 -80
  50. package/dist/agents/tool-availability.js.map +1 -1
  51. package/dist/agents/tools.js +99 -139
  52. package/dist/agents/tools.js.map +1 -1
  53. package/dist/agents/workspace.js +232 -225
  54. package/dist/agents/workspace.js.map +1 -1
  55. package/dist/analytics.js +139 -128
  56. package/dist/analytics.js.map +1 -1
  57. package/dist/auth/authorization-input.js +39 -25
  58. package/dist/auth/authorization-input.js.map +1 -1
  59. package/dist/auth/device-code.js +112 -80
  60. package/dist/auth/device-code.js.map +1 -1
  61. package/dist/auth/index.js +2 -9
  62. package/dist/auth/pkce.js +27 -16
  63. package/dist/auth/pkce.js.map +1 -1
  64. package/dist/auth/providers/anthropic.js +107 -93
  65. package/dist/auth/providers/anthropic.js.map +1 -1
  66. package/dist/auth/providers/github-copilot.js +304 -293
  67. package/dist/auth/providers/github-copilot.js.map +1 -1
  68. package/dist/auth/providers/openai-codex.js +442 -460
  69. package/dist/auth/providers/openai-codex.js.map +1 -1
  70. package/dist/auth/providers/xai.js +179 -145
  71. package/dist/auth/providers/xai.js.map +1 -1
  72. package/dist/auth/storage.js +182 -175
  73. package/dist/auth/storage.js.map +1 -1
  74. package/dist/auth/types.js +1 -1
  75. package/dist/clipboard/index.js +206 -172
  76. package/dist/clipboard/index.js.map +1 -1
  77. package/dist/constants.js +11 -16
  78. package/dist/constants.js.map +1 -1
  79. package/dist/error-classification.js +19 -11
  80. package/dist/error-classification.js.map +1 -1
  81. package/dist/evals/context-builder.js +145 -104
  82. package/dist/evals/context-builder.js.map +1 -1
  83. package/dist/evals/index.js +4 -7
  84. package/dist/evals/scorers/classify-command.js +62 -41
  85. package/dist/evals/scorers/classify-command.js.map +1 -1
  86. package/dist/evals/scorers/efficiency.js +239 -181
  87. package/dist/evals/scorers/efficiency.js.map +1 -1
  88. package/dist/evals/scorers/extract-tools.js +51 -47
  89. package/dist/evals/scorers/extract-tools.js.map +1 -1
  90. package/dist/evals/scorers/index.js +1 -5
  91. package/dist/evals/scorers/outcome.js +321 -212
  92. package/dist/evals/scorers/outcome.js.map +1 -1
  93. package/dist/goal-manager.js +266 -261
  94. package/dist/goal-manager.js.map +1 -1
  95. package/dist/goal-signal.js +14 -13
  96. package/dist/goal-signal.js.map +1 -1
  97. package/dist/headless/cli.js +153 -154
  98. package/dist/headless/cli.js.map +1 -1
  99. package/dist/headless/flags.js +180 -178
  100. package/dist/headless/flags.js.map +1 -1
  101. package/dist/headless/format.js +72 -71
  102. package/dist/headless/format.js.map +1 -1
  103. package/dist/headless/index.js +5 -31
  104. package/dist/headless/policy.js +35 -31
  105. package/dist/headless/policy.js.map +1 -1
  106. package/dist/headless/run-mc.js +332 -334
  107. package/dist/headless/run-mc.js.map +1 -1
  108. package/dist/headless/types.js +16 -7
  109. package/dist/headless/types.js.map +1 -1
  110. package/dist/hooks/config.js +56 -61
  111. package/dist/hooks/config.js.map +1 -1
  112. package/dist/hooks/executor.js +118 -116
  113. package/dist/hooks/executor.js.map +1 -1
  114. package/dist/hooks/index.js +4 -15
  115. package/dist/hooks/manager.js +221 -280
  116. package/dist/hooks/manager.js.map +1 -1
  117. package/dist/hooks/types.js +5 -4
  118. package/dist/hooks/types.js.map +1 -1
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/index.js +632 -712
  121. package/dist/index.js.map +1 -1
  122. package/dist/ipc/ipc-reporter.js +19 -22
  123. package/dist/ipc/ipc-reporter.js.map +1 -1
  124. package/dist/lsp/client.js +248 -306
  125. package/dist/lsp/client.js.map +1 -1
  126. package/dist/lsp/index.js +1 -6
  127. package/dist/lsp/language.js +39 -43
  128. package/dist/lsp/language.js.map +1 -1
  129. package/dist/lsp/manager.js +78 -93
  130. package/dist/lsp/manager.js.map +1 -1
  131. package/dist/lsp/server.js +151 -120
  132. package/dist/lsp/server.js.map +1 -1
  133. package/dist/lsp/workspace.js +50 -47
  134. package/dist/lsp/workspace.js.map +1 -1
  135. package/dist/mcp/config.js +210 -199
  136. package/dist/mcp/config.js.map +1 -1
  137. package/dist/mcp/index.js +2 -9
  138. package/dist/mcp/manager.js +482 -475
  139. package/dist/mcp/manager.js.map +1 -1
  140. package/dist/mcp/types.js +1 -1
  141. package/dist/onboarding/custom-packs.js +14 -17
  142. package/dist/onboarding/custom-packs.js.map +1 -1
  143. package/dist/onboarding/custom-providers.js +22 -20
  144. package/dist/onboarding/custom-providers.js.map +1 -1
  145. package/dist/onboarding/index.d.ts +1 -1
  146. package/dist/onboarding/index.d.ts.map +1 -1
  147. package/dist/onboarding/index.js +3 -21
  148. package/dist/onboarding/om-settings.d.ts +5 -0
  149. package/dist/onboarding/om-settings.d.ts.map +1 -1
  150. package/dist/onboarding/om-settings.js +41 -20
  151. package/dist/onboarding/om-settings.js.map +1 -1
  152. package/dist/onboarding/packs.d.ts +4 -6
  153. package/dist/onboarding/packs.d.ts.map +1 -1
  154. package/dist/onboarding/packs.js +154 -105
  155. package/dist/onboarding/packs.js.map +1 -1
  156. package/dist/onboarding/settings.js +575 -517
  157. package/dist/onboarding/settings.js.map +1 -1
  158. package/dist/permissions.js +112 -99
  159. package/dist/permissions.js.map +1 -1
  160. package/dist/plugin.js +21 -23
  161. package/dist/plugin.js.map +1 -1
  162. package/dist/plugins/dependencies.js +64 -87
  163. package/dist/plugins/dependencies.js.map +1 -1
  164. package/dist/plugins/install.js +159 -169
  165. package/dist/plugins/install.js.map +1 -1
  166. package/dist/plugins/loader.js +170 -185
  167. package/dist/plugins/loader.js.map +1 -1
  168. package/dist/plugins/manager.js +374 -380
  169. package/dist/plugins/manager.js.map +1 -1
  170. package/dist/plugins/manifest.js +38 -63
  171. package/dist/plugins/manifest.js.map +1 -1
  172. package/dist/plugins/package-link.js +48 -64
  173. package/dist/plugins/package-link.js.map +1 -1
  174. package/dist/plugins/paths.js +18 -19
  175. package/dist/plugins/paths.js.map +1 -1
  176. package/dist/plugins/registry.js +97 -81
  177. package/dist/plugins/registry.js.map +1 -1
  178. package/dist/plugins/scaffold.js +62 -98
  179. package/dist/plugins/scaffold.js.map +1 -1
  180. package/dist/plugins/types.js +1 -1
  181. package/dist/processors/plan-rejection-abort.js +45 -44
  182. package/dist/processors/plan-rejection-abort.js.map +1 -1
  183. package/dist/providers/amazon-bedrock-gateway.js +134 -125
  184. package/dist/providers/amazon-bedrock-gateway.js.map +1 -1
  185. package/dist/providers/amazon-bedrock.js +68 -47
  186. package/dist/providers/amazon-bedrock.js.map +1 -1
  187. package/dist/providers/claude-max.js +153 -133
  188. package/dist/providers/claude-max.js.map +1 -1
  189. package/dist/providers/github-copilot.js +232 -230
  190. package/dist/providers/github-copilot.js.map +1 -1
  191. package/dist/providers/openai-codex.js +271 -260
  192. package/dist/providers/openai-codex.js.map +1 -1
  193. package/dist/providers/xai.js +57 -50
  194. package/dist/providers/xai.js.map +1 -1
  195. package/dist/schema.js +91 -89
  196. package/dist/schema.js.map +1 -1
  197. package/dist/theme-palette.js +18 -14
  198. package/dist/theme-palette.js.map +1 -1
  199. package/dist/tool-names.js +46 -37
  200. package/dist/tool-names.js.map +1 -1
  201. package/dist/tools/index.js +2 -8
  202. package/dist/tools/request-sandbox-access.js +71 -80
  203. package/dist/tools/request-sandbox-access.js.map +1 -1
  204. package/dist/tools/utils.js +26 -16
  205. package/dist/tools/utils.js.map +1 -1
  206. package/dist/tools/web-search.js +51 -55
  207. package/dist/tools/web-search.js.map +1 -1
  208. package/dist/utils/binaries.js +65 -61
  209. package/dist/utils/binaries.js.map +1 -1
  210. package/dist/utils/debug-log.js +51 -47
  211. package/dist/utils/debug-log.js.map +1 -1
  212. package/dist/utils/errors.js +157 -192
  213. package/dist/utils/errors.js.map +1 -1
  214. package/dist/utils/gateway-sync.js +49 -37
  215. package/dist/utils/gateway-sync.js.map +1 -1
  216. package/dist/utils/path-security.js +7 -6
  217. package/dist/utils/path-security.js.map +1 -1
  218. package/dist/utils/plan-diff.js +58 -39
  219. package/dist/utils/plan-diff.js.map +1 -1
  220. package/dist/utils/plans.js +92 -74
  221. package/dist/utils/plans.js.map +1 -1
  222. package/dist/utils/project.js +318 -256
  223. package/dist/utils/project.js.map +1 -1
  224. package/dist/utils/signals-pubsub.js +117 -99
  225. package/dist/utils/signals-pubsub.js.map +1 -1
  226. package/dist/utils/slash-command-loader.js +118 -154
  227. package/dist/utils/slash-command-loader.js.map +1 -1
  228. package/dist/utils/slash-command-processor.js +92 -83
  229. package/dist/utils/slash-command-processor.js.map +1 -1
  230. package/dist/utils/stdin-pipe.js +87 -63
  231. package/dist/utils/stdin-pipe.js.map +1 -1
  232. package/dist/utils/storage-factory.js +104 -84
  233. package/dist/utils/storage-factory.js.map +1 -1
  234. package/dist/utils/storage-maintenance.js +249 -211
  235. package/dist/utils/storage-maintenance.js.map +1 -1
  236. package/dist/utils/thread-lock.js +96 -92
  237. package/dist/utils/thread-lock.js.map +1 -1
  238. package/dist/utils/token-estimator.js +12 -12
  239. package/dist/utils/token-estimator.js.map +1 -1
  240. package/dist/utils/update-check.d.ts +1 -1
  241. package/dist/utils/update-check.js +341 -259
  242. package/dist/utils/update-check.js.map +1 -1
  243. package/dist/voice/stt-registry.js +131 -113
  244. package/dist/voice/stt-registry.js.map +1 -1
  245. package/package.json +11 -11
  246. package/dist/acp.js.map +0 -1
  247. package/dist/auth/index.js.map +0 -1
  248. package/dist/auth/types.js.map +0 -1
  249. package/dist/evals/index.js.map +0 -1
  250. package/dist/evals/scorers/index.js.map +0 -1
  251. package/dist/headless/index.js.map +0 -1
  252. package/dist/hooks/index.js.map +0 -1
  253. package/dist/lsp/index.js.map +0 -1
  254. package/dist/mcp/index.js.map +0 -1
  255. package/dist/mcp/types.js.map +0 -1
  256. package/dist/onboarding/index.js.map +0 -1
  257. package/dist/plugins/types.js.map +0 -1
  258. package/dist/tools/index.js.map +0 -1
@@ -1,96 +1,112 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- const EMPTY_PLUGIN_REGISTRY = { plugins: {}, disabledPlugins: [] };
1
+ import fs from "fs";
2
+ import path from "path";
3
+ //#region src/plugins/registry.ts
4
+ const EMPTY_PLUGIN_REGISTRY = {
5
+ plugins: {},
6
+ disabledPlugins: []
7
+ };
4
8
  function loadPluginRegistry(registryPath) {
5
- try {
6
- if (!fs.existsSync(registryPath)) return { plugins: {}, disabledPlugins: [] };
7
- const raw = JSON.parse(fs.readFileSync(registryPath, "utf-8"));
8
- return validatePluginRegistry(raw);
9
- } catch {
10
- return { plugins: {}, disabledPlugins: [] };
11
- }
9
+ try {
10
+ if (!fs.existsSync(registryPath)) return {
11
+ plugins: {},
12
+ disabledPlugins: []
13
+ };
14
+ return validatePluginRegistry(JSON.parse(fs.readFileSync(registryPath, "utf-8")));
15
+ } catch {
16
+ return {
17
+ plugins: {},
18
+ disabledPlugins: []
19
+ };
20
+ }
12
21
  }
13
22
  function savePluginRegistry(registryPath, registry) {
14
- fs.mkdirSync(path.dirname(registryPath), { recursive: true });
15
- fs.writeFileSync(registryPath, `${JSON.stringify(validatePluginRegistry(registry), null, 2)}
16
- `);
23
+ fs.mkdirSync(path.dirname(registryPath), { recursive: true });
24
+ fs.writeFileSync(registryPath, `${JSON.stringify(validatePluginRegistry(registry), null, 2)}\n`);
17
25
  }
18
26
  function mergePluginRegistries(globalRegistry, projectRegistry) {
19
- const merged = /* @__PURE__ */ new Map();
20
- const disabledPlugins = /* @__PURE__ */ new Set([
21
- ...globalRegistry.disabledPlugins ?? [],
22
- ...projectRegistry.disabledPlugins ?? []
23
- ]);
24
- for (const [id, record] of Object.entries(globalRegistry.plugins)) {
25
- merged.set(id, { id, scope: "global", ...record });
26
- }
27
- for (const [id, record] of Object.entries(projectRegistry.plugins)) {
28
- merged.set(id, { id, scope: "project", ...record });
29
- }
30
- return [...merged.values()].map((record) => disabledPlugins.has(record.id) ? { ...record, blocked: true } : record).sort((a, b) => {
31
- if (a.scope !== b.scope) return a.scope === "project" ? -1 : 1;
32
- return a.id.localeCompare(b.id);
33
- });
27
+ const merged = /* @__PURE__ */ new Map();
28
+ const disabledPlugins = /* @__PURE__ */ new Set([...globalRegistry.disabledPlugins ?? [], ...projectRegistry.disabledPlugins ?? []]);
29
+ for (const [id, record] of Object.entries(globalRegistry.plugins)) merged.set(id, {
30
+ id,
31
+ scope: "global",
32
+ ...record
33
+ });
34
+ for (const [id, record] of Object.entries(projectRegistry.plugins)) merged.set(id, {
35
+ id,
36
+ scope: "project",
37
+ ...record
38
+ });
39
+ return [...merged.values()].map((record) => disabledPlugins.has(record.id) ? {
40
+ ...record,
41
+ blocked: true
42
+ } : record).sort((a, b) => {
43
+ if (a.scope !== b.scope) return a.scope === "project" ? -1 : 1;
44
+ return a.id.localeCompare(b.id);
45
+ });
34
46
  }
35
47
  function setPluginRecord(registry, pluginId, record) {
36
- return {
37
- plugins: {
38
- ...registry.plugins,
39
- [pluginId]: record
40
- },
41
- disabledPlugins: registry.disabledPlugins ?? []
42
- };
48
+ return {
49
+ plugins: {
50
+ ...registry.plugins,
51
+ [pluginId]: record
52
+ },
53
+ disabledPlugins: registry.disabledPlugins ?? []
54
+ };
43
55
  }
44
56
  function removePluginRecord(registry, pluginId) {
45
- const plugins = { ...registry.plugins };
46
- delete plugins[pluginId];
47
- return { plugins, disabledPlugins: registry.disabledPlugins ?? [] };
57
+ const plugins = { ...registry.plugins };
58
+ delete plugins[pluginId];
59
+ return {
60
+ plugins,
61
+ disabledPlugins: registry.disabledPlugins ?? []
62
+ };
48
63
  }
49
64
  function validatePluginRegistry(raw) {
50
- if (!raw || typeof raw !== "object") return { plugins: {}, disabledPlugins: [] };
51
- const plugins = raw.plugins;
52
- if (!plugins || typeof plugins !== "object" || Array.isArray(plugins)) return { plugins: {}, disabledPlugins: [] };
53
- const disabledPlugins = raw.disabledPlugins;
54
- const validated = {
55
- plugins: {},
56
- disabledPlugins: Array.isArray(disabledPlugins) ? [...new Set(disabledPlugins.filter((pluginId) => typeof pluginId === "string"))].sort() : []
57
- };
58
- for (const [id, value] of Object.entries(plugins)) {
59
- if (typeof id !== "string" || id.trim().length === 0) continue;
60
- if (!value || typeof value !== "object" || Array.isArray(value)) continue;
61
- const record = value;
62
- if (typeof record.enabled !== "boolean") continue;
63
- if (record.source !== "local" && record.source !== "github") continue;
64
- if (typeof record.specifier !== "string") continue;
65
- if (typeof record.path !== "string") continue;
66
- if (typeof record.entry !== "string") continue;
67
- validated.plugins[id] = {
68
- enabled: record.enabled,
69
- source: record.source,
70
- specifier: record.specifier,
71
- path: record.path,
72
- entry: record.entry,
73
- ...typeof record.ref === "string" ? { ref: record.ref } : {},
74
- ...typeof record.version === "string" ? { version: record.version } : {},
75
- ...record.config && typeof record.config === "object" && !Array.isArray(record.config) ? { config: validatePluginConfigValues(record.config) } : {}
76
- };
77
- }
78
- return validated;
65
+ if (!raw || typeof raw !== "object") return {
66
+ plugins: {},
67
+ disabledPlugins: []
68
+ };
69
+ const plugins = raw.plugins;
70
+ if (!plugins || typeof plugins !== "object" || Array.isArray(plugins)) return {
71
+ plugins: {},
72
+ disabledPlugins: []
73
+ };
74
+ const disabledPlugins = raw.disabledPlugins;
75
+ const validated = {
76
+ plugins: {},
77
+ disabledPlugins: Array.isArray(disabledPlugins) ? [...new Set(disabledPlugins.filter((pluginId) => typeof pluginId === "string"))].sort() : []
78
+ };
79
+ for (const [id, value] of Object.entries(plugins)) {
80
+ if (typeof id !== "string" || id.trim().length === 0) continue;
81
+ if (!value || typeof value !== "object" || Array.isArray(value)) continue;
82
+ const record = value;
83
+ if (typeof record.enabled !== "boolean") continue;
84
+ if (record.source !== "local" && record.source !== "github") continue;
85
+ if (typeof record.specifier !== "string") continue;
86
+ if (typeof record.path !== "string") continue;
87
+ if (typeof record.entry !== "string") continue;
88
+ validated.plugins[id] = {
89
+ enabled: record.enabled,
90
+ source: record.source,
91
+ specifier: record.specifier,
92
+ path: record.path,
93
+ entry: record.entry,
94
+ ...typeof record.ref === "string" ? { ref: record.ref } : {},
95
+ ...typeof record.version === "string" ? { version: record.version } : {},
96
+ ...record.config && typeof record.config === "object" && !Array.isArray(record.config) ? { config: validatePluginConfigValues(record.config) } : {}
97
+ };
98
+ }
99
+ return validated;
79
100
  }
80
101
  function validatePluginConfigValues(raw) {
81
- const values = {};
82
- for (const [key, value] of Object.entries(raw)) {
83
- if (typeof key !== "string" || key.trim().length === 0) continue;
84
- if (typeof value === "string" || typeof value === "boolean") values[key] = value;
85
- }
86
- return values;
102
+ const values = {};
103
+ for (const [key, value] of Object.entries(raw)) {
104
+ if (typeof key !== "string" || key.trim().length === 0) continue;
105
+ if (typeof value === "string" || typeof value === "boolean") values[key] = value;
106
+ }
107
+ return values;
87
108
  }
88
- export {
89
- EMPTY_PLUGIN_REGISTRY,
90
- loadPluginRegistry,
91
- mergePluginRegistries,
92
- removePluginRecord,
93
- savePluginRegistry,
94
- setPluginRecord
95
- };
109
+ //#endregion
110
+ export { EMPTY_PLUGIN_REGISTRY, loadPluginRegistry, mergePluginRegistries, removePluginRecord, savePluginRegistry, setPluginRecord };
111
+
96
112
  //# sourceMappingURL=registry.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plugins/registry.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { InstalledPluginRecord, PluginRegistry, ScopedInstalledPluginRecord } from './types.js';\n\nexport const EMPTY_PLUGIN_REGISTRY: PluginRegistry = { plugins: {}, disabledPlugins: [] };\n\nexport function loadPluginRegistry(registryPath: string): PluginRegistry {\n try {\n if (!fs.existsSync(registryPath)) return { plugins: {}, disabledPlugins: [] };\n const raw = JSON.parse(fs.readFileSync(registryPath, 'utf-8')) as unknown;\n return validatePluginRegistry(raw);\n } catch {\n return { plugins: {}, disabledPlugins: [] };\n }\n}\n\nexport function savePluginRegistry(registryPath: string, registry: PluginRegistry): void {\n fs.mkdirSync(path.dirname(registryPath), { recursive: true });\n fs.writeFileSync(registryPath, `${JSON.stringify(validatePluginRegistry(registry), null, 2)}\\n`);\n}\n\nexport function mergePluginRegistries(\n globalRegistry: PluginRegistry,\n projectRegistry: PluginRegistry,\n): ScopedInstalledPluginRecord[] {\n const merged = new Map<string, ScopedInstalledPluginRecord>();\n const disabledPlugins = new Set([\n ...(globalRegistry.disabledPlugins ?? []),\n ...(projectRegistry.disabledPlugins ?? []),\n ]);\n\n for (const [id, record] of Object.entries(globalRegistry.plugins)) {\n merged.set(id, { id, scope: 'global', ...record });\n }\n\n for (const [id, record] of Object.entries(projectRegistry.plugins)) {\n merged.set(id, { id, scope: 'project', ...record });\n }\n\n return [...merged.values()]\n .map(record => (disabledPlugins.has(record.id) ? { ...record, blocked: true } : record))\n .sort((a, b) => {\n if (a.scope !== b.scope) return a.scope === 'project' ? -1 : 1;\n return a.id.localeCompare(b.id);\n });\n}\n\nexport function setPluginRecord(\n registry: PluginRegistry,\n pluginId: string,\n record: InstalledPluginRecord,\n): PluginRegistry {\n return {\n plugins: {\n ...registry.plugins,\n [pluginId]: record,\n },\n disabledPlugins: registry.disabledPlugins ?? [],\n };\n}\n\nexport function removePluginRecord(registry: PluginRegistry, pluginId: string): PluginRegistry {\n const plugins = { ...registry.plugins };\n delete plugins[pluginId];\n return { plugins, disabledPlugins: registry.disabledPlugins ?? [] };\n}\n\nfunction validatePluginRegistry(raw: unknown): PluginRegistry {\n if (!raw || typeof raw !== 'object') return { plugins: {}, disabledPlugins: [] };\n const plugins = (raw as { plugins?: unknown }).plugins;\n if (!plugins || typeof plugins !== 'object' || Array.isArray(plugins)) return { plugins: {}, disabledPlugins: [] };\n\n const disabledPlugins = (raw as { disabledPlugins?: unknown }).disabledPlugins;\n const validated: PluginRegistry = {\n plugins: {},\n disabledPlugins: Array.isArray(disabledPlugins)\n ? [...new Set(disabledPlugins.filter((pluginId): pluginId is string => typeof pluginId === 'string'))].sort()\n : [],\n };\n for (const [id, value] of Object.entries(plugins)) {\n if (typeof id !== 'string' || id.trim().length === 0) continue;\n if (!value || typeof value !== 'object' || Array.isArray(value)) continue;\n const record = value as Record<string, unknown>;\n if (typeof record.enabled !== 'boolean') continue;\n if (record.source !== 'local' && record.source !== 'github') continue;\n if (typeof record.specifier !== 'string') continue;\n if (typeof record.path !== 'string') continue;\n if (typeof record.entry !== 'string') continue;\n\n validated.plugins[id] = {\n enabled: record.enabled,\n source: record.source,\n specifier: record.specifier,\n path: record.path,\n entry: record.entry,\n ...(typeof record.ref === 'string' ? { ref: record.ref } : {}),\n ...(typeof record.version === 'string' ? { version: record.version } : {}),\n ...(record.config && typeof record.config === 'object' && !Array.isArray(record.config)\n ? { config: validatePluginConfigValues(record.config) }\n : {}),\n };\n }\n\n return validated;\n}\n\nfunction validatePluginConfigValues(raw: object): Record<string, string | boolean> {\n const values: Record<string, string | boolean> = {};\n for (const [key, value] of Object.entries(raw)) {\n if (typeof key !== 'string' || key.trim().length === 0) continue;\n if (typeof value === 'string' || typeof value === 'boolean') values[key] = value;\n }\n return values;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"file":"registry.js","names":[],"sources":["../../src/plugins/registry.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport type { InstalledPluginRecord, PluginRegistry, ScopedInstalledPluginRecord } from './types.js';\n\nexport const EMPTY_PLUGIN_REGISTRY: PluginRegistry = { plugins: {}, disabledPlugins: [] };\n\nexport function loadPluginRegistry(registryPath: string): PluginRegistry {\n try {\n if (!fs.existsSync(registryPath)) return { plugins: {}, disabledPlugins: [] };\n const raw = JSON.parse(fs.readFileSync(registryPath, 'utf-8')) as unknown;\n return validatePluginRegistry(raw);\n } catch {\n return { plugins: {}, disabledPlugins: [] };\n }\n}\n\nexport function savePluginRegistry(registryPath: string, registry: PluginRegistry): void {\n fs.mkdirSync(path.dirname(registryPath), { recursive: true });\n fs.writeFileSync(registryPath, `${JSON.stringify(validatePluginRegistry(registry), null, 2)}\\n`);\n}\n\nexport function mergePluginRegistries(\n globalRegistry: PluginRegistry,\n projectRegistry: PluginRegistry,\n): ScopedInstalledPluginRecord[] {\n const merged = new Map<string, ScopedInstalledPluginRecord>();\n const disabledPlugins = new Set([\n ...(globalRegistry.disabledPlugins ?? []),\n ...(projectRegistry.disabledPlugins ?? []),\n ]);\n\n for (const [id, record] of Object.entries(globalRegistry.plugins)) {\n merged.set(id, { id, scope: 'global', ...record });\n }\n\n for (const [id, record] of Object.entries(projectRegistry.plugins)) {\n merged.set(id, { id, scope: 'project', ...record });\n }\n\n return [...merged.values()]\n .map(record => (disabledPlugins.has(record.id) ? { ...record, blocked: true } : record))\n .sort((a, b) => {\n if (a.scope !== b.scope) return a.scope === 'project' ? -1 : 1;\n return a.id.localeCompare(b.id);\n });\n}\n\nexport function setPluginRecord(\n registry: PluginRegistry,\n pluginId: string,\n record: InstalledPluginRecord,\n): PluginRegistry {\n return {\n plugins: {\n ...registry.plugins,\n [pluginId]: record,\n },\n disabledPlugins: registry.disabledPlugins ?? [],\n };\n}\n\nexport function removePluginRecord(registry: PluginRegistry, pluginId: string): PluginRegistry {\n const plugins = { ...registry.plugins };\n delete plugins[pluginId];\n return { plugins, disabledPlugins: registry.disabledPlugins ?? [] };\n}\n\nfunction validatePluginRegistry(raw: unknown): PluginRegistry {\n if (!raw || typeof raw !== 'object') return { plugins: {}, disabledPlugins: [] };\n const plugins = (raw as { plugins?: unknown }).plugins;\n if (!plugins || typeof plugins !== 'object' || Array.isArray(plugins)) return { plugins: {}, disabledPlugins: [] };\n\n const disabledPlugins = (raw as { disabledPlugins?: unknown }).disabledPlugins;\n const validated: PluginRegistry = {\n plugins: {},\n disabledPlugins: Array.isArray(disabledPlugins)\n ? [...new Set(disabledPlugins.filter((pluginId): pluginId is string => typeof pluginId === 'string'))].sort()\n : [],\n };\n for (const [id, value] of Object.entries(plugins)) {\n if (typeof id !== 'string' || id.trim().length === 0) continue;\n if (!value || typeof value !== 'object' || Array.isArray(value)) continue;\n const record = value as Record<string, unknown>;\n if (typeof record.enabled !== 'boolean') continue;\n if (record.source !== 'local' && record.source !== 'github') continue;\n if (typeof record.specifier !== 'string') continue;\n if (typeof record.path !== 'string') continue;\n if (typeof record.entry !== 'string') continue;\n\n validated.plugins[id] = {\n enabled: record.enabled,\n source: record.source,\n specifier: record.specifier,\n path: record.path,\n entry: record.entry,\n ...(typeof record.ref === 'string' ? { ref: record.ref } : {}),\n ...(typeof record.version === 'string' ? { version: record.version } : {}),\n ...(record.config && typeof record.config === 'object' && !Array.isArray(record.config)\n ? { config: validatePluginConfigValues(record.config) }\n : {}),\n };\n }\n\n return validated;\n}\n\nfunction validatePluginConfigValues(raw: object): Record<string, string | boolean> {\n const values: Record<string, string | boolean> = {};\n for (const [key, value] of Object.entries(raw)) {\n if (typeof key !== 'string' || key.trim().length === 0) continue;\n if (typeof value === 'string' || typeof value === 'boolean') values[key] = value;\n }\n return values;\n}\n"],"mappings":"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"}
@@ -1,107 +1,73 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import { DEFAULT_CONFIG_DIR } from "../constants.js";
1
+ import "../constants.js";
4
2
  import { upsertPluginManifestEntry } from "./manifest.js";
5
3
  import { ensureMastraCodePackageLink } from "./package-link.js";
4
+ import fs from "fs";
5
+ import path from "path";
6
+ //#region src/plugins/scaffold.ts
6
7
  function resolveScaffoldTarget(target, options = {}) {
7
- if (isBarePluginName(target)) {
8
- return path.join(
9
- options.projectRoot ?? process.cwd(),
10
- options.configDir ?? DEFAULT_CONFIG_DIR,
11
- "plugins",
12
- "sources",
13
- "local",
14
- target
15
- );
16
- }
17
- return path.resolve(options.projectRoot ?? process.cwd(), target);
8
+ if (isBarePluginName(target)) return path.join(options.projectRoot ?? process.cwd(), options.configDir ?? ".mastracode", "plugins", "sources", "local", target);
9
+ return path.resolve(options.projectRoot ?? process.cwd(), target);
18
10
  }
19
11
  function scaffoldPlugin(targetDir, options = {}) {
20
- const dir = resolveScaffoldTarget(targetDir, options);
21
- if (fs.existsSync(dir) && fs.readdirSync(dir).length > 0) {
22
- throw new Error(`Directory already exists and is not empty: ${targetDir}`);
23
- }
24
- const packageName = path.basename(dir).toLowerCase().replace(/[^a-z0-9_.-]+/g, "-").replace(/^-|-$/g, "") || "mastracode-plugin";
25
- const pluginId = options.id ?? packageName;
26
- const pluginName = options.name ?? humanizeName(packageName);
27
- fs.mkdirSync(path.join(dir, "src"), { recursive: true });
28
- fs.writeFileSync(
29
- path.join(dir, "package.json"),
30
- `${JSON.stringify(
31
- {
32
- name: packageName,
33
- type: "module",
34
- exports: "./src/index.ts",
35
- peerDependencies: {
36
- mastracode: "*"
37
- },
38
- devDependencies: {
39
- typescript: "^5.9.3"
40
- },
41
- scripts: {
42
- check: "tsc --noEmit"
43
- }
44
- },
45
- null,
46
- 2
47
- )}
48
- `
49
- );
50
- fs.writeFileSync(
51
- path.join(dir, "tsconfig.json"),
52
- `${JSON.stringify(
53
- {
54
- compilerOptions: {
55
- target: "ES2024",
56
- module: "NodeNext",
57
- moduleResolution: "NodeNext",
58
- strict: true,
59
- verbatimModuleSyntax: true,
60
- erasableSyntaxOnly: true,
61
- skipLibCheck: true,
62
- noEmit: true
63
- },
64
- include: ["src/**/*.ts"]
65
- },
66
- null,
67
- 2
68
- )}
69
- `
70
- );
71
- fs.writeFileSync(path.join(dir, "src/index.ts"), renderIndex(pluginId, pluginName));
72
- fs.writeFileSync(path.join(dir, "README.md"), renderReadme(pluginName, pluginId));
73
- writeScaffoldManifest(targetDir, dir, pluginId, pluginName, options);
74
- ensureMastraCodePackageLink(dir);
75
- return dir;
12
+ const dir = resolveScaffoldTarget(targetDir, options);
13
+ if (fs.existsSync(dir) && fs.readdirSync(dir).length > 0) throw new Error(`Directory already exists and is not empty: ${targetDir}`);
14
+ const packageName = path.basename(dir).toLowerCase().replace(/[^a-z0-9_.-]+/g, "-").replace(/^-|-$/g, "") || "mastracode-plugin";
15
+ const pluginId = options.id ?? packageName;
16
+ const pluginName = options.name ?? humanizeName(packageName);
17
+ fs.mkdirSync(path.join(dir, "src"), { recursive: true });
18
+ fs.writeFileSync(path.join(dir, "package.json"), `${JSON.stringify({
19
+ name: packageName,
20
+ type: "module",
21
+ exports: "./src/index.ts",
22
+ peerDependencies: { mastracode: "*" },
23
+ devDependencies: { typescript: "^5.9.3" },
24
+ scripts: { check: "tsc --noEmit" }
25
+ }, null, 2)}\n`);
26
+ fs.writeFileSync(path.join(dir, "tsconfig.json"), `${JSON.stringify({
27
+ compilerOptions: {
28
+ target: "ES2024",
29
+ module: "NodeNext",
30
+ moduleResolution: "NodeNext",
31
+ strict: true,
32
+ verbatimModuleSyntax: true,
33
+ erasableSyntaxOnly: true,
34
+ skipLibCheck: true,
35
+ noEmit: true
36
+ },
37
+ include: ["src/**/*.ts"]
38
+ }, null, 2)}\n`);
39
+ fs.writeFileSync(path.join(dir, "src/index.ts"), renderIndex(pluginId, pluginName));
40
+ fs.writeFileSync(path.join(dir, "README.md"), renderReadme(pluginName, pluginId));
41
+ writeScaffoldManifest(targetDir, dir, pluginId, pluginName, options);
42
+ ensureMastraCodePackageLink(dir);
43
+ return dir;
76
44
  }
77
45
  function writeScaffoldManifest(originalTarget, scaffoldDir, pluginId, pluginName, options) {
78
- const projectRoot = options.projectRoot ?? process.cwd();
79
- const manifestRoot = isBarePluginName(originalTarget) ? projectRoot : scaffoldDir;
80
- const entry = isBarePluginName(originalTarget) ? path.join(path.relative(projectRoot, scaffoldDir), "src/index.ts") : "src/index.ts";
81
- upsertPluginManifestEntry(manifestRoot, {
82
- id: pluginId,
83
- name: pluginName,
84
- entry: entry.split(path.sep).join("/")
85
- });
46
+ const projectRoot = options.projectRoot ?? process.cwd();
47
+ upsertPluginManifestEntry(isBarePluginName(originalTarget) ? projectRoot : scaffoldDir, {
48
+ id: pluginId,
49
+ name: pluginName,
50
+ entry: (isBarePluginName(originalTarget) ? path.join(path.relative(projectRoot, scaffoldDir), "src/index.ts") : "src/index.ts").split(path.sep).join("/")
51
+ });
86
52
  }
87
53
  function formatScaffoldSuccess(targetDir) {
88
- return [
89
- `Created Mastra Code plugin scaffold at ${targetDir}`,
90
- "",
91
- "Next steps:",
92
- ` cd ${targetDir}`,
93
- " pnpm install",
94
- " pnpm check",
95
- " mastracode",
96
- " /plugins",
97
- " Install new plugin \u2192 Local path"
98
- ].join("\n");
54
+ return [
55
+ `Created Mastra Code plugin scaffold at ${targetDir}`,
56
+ "",
57
+ "Next steps:",
58
+ ` cd ${targetDir}`,
59
+ " pnpm install",
60
+ " pnpm check",
61
+ " mastracode",
62
+ " /plugins",
63
+ " Install new plugin Local path"
64
+ ].join("\n");
99
65
  }
100
66
  function isBarePluginName(target) {
101
- return !path.isAbsolute(target) && !target.startsWith(".") && !target.includes("/") && !target.includes("\\");
67
+ return !path.isAbsolute(target) && !target.startsWith(".") && !target.includes("/") && !target.includes("\\");
102
68
  }
103
69
  function renderIndex(pluginId, pluginName) {
104
- return `import { createTool, defineMastraCodePlugin, z } from 'mastracode/plugin';
70
+ return `import { createTool, defineMastraCodePlugin, z } from 'mastracode/plugin';
105
71
 
106
72
  export default defineMastraCodePlugin({
107
73
  id: ${JSON.stringify(pluginId)},
@@ -125,7 +91,7 @@ export default defineMastraCodePlugin({
125
91
  `;
126
92
  }
127
93
  function renderReadme(pluginName, pluginId) {
128
- return `# ${pluginName}
94
+ return `# ${pluginName}
129
95
 
130
96
  Mastra Code tool plugin: \`${pluginId}\`.
131
97
 
@@ -142,11 +108,9 @@ Open Mastra Code, run \`/plugins\`, and install this directory as a local plugin
142
108
  `;
143
109
  }
144
110
  function humanizeName(value) {
145
- return value.split(/[-_.]+/g).filter(Boolean).map((part) => part[0]?.toUpperCase() + part.slice(1)).join(" ") || "Mastra Code Plugin";
111
+ return value.split(/[-_.]+/g).filter(Boolean).map((part) => part[0]?.toUpperCase() + part.slice(1)).join(" ") || "Mastra Code Plugin";
146
112
  }
147
- export {
148
- formatScaffoldSuccess,
149
- resolveScaffoldTarget,
150
- scaffoldPlugin
151
- };
113
+ //#endregion
114
+ export { formatScaffoldSuccess, resolveScaffoldTarget, scaffoldPlugin };
115
+
152
116
  //# sourceMappingURL=scaffold.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plugins/scaffold.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { DEFAULT_CONFIG_DIR } from '../constants.js';\nimport { upsertPluginManifestEntry } from './manifest.js';\nimport { ensureMastraCodePackageLink } from './package-link.js';\n\nexport type ScaffoldPluginOptions = {\n id?: string;\n name?: string;\n projectRoot?: string;\n configDir?: string;\n};\n\nexport function resolveScaffoldTarget(\n target: string,\n options: Pick<ScaffoldPluginOptions, 'projectRoot' | 'configDir'> = {},\n): string {\n if (isBarePluginName(target)) {\n return path.join(\n options.projectRoot ?? process.cwd(),\n options.configDir ?? DEFAULT_CONFIG_DIR,\n 'plugins',\n 'sources',\n 'local',\n target,\n );\n }\n return path.resolve(options.projectRoot ?? process.cwd(), target);\n}\n\nexport function scaffoldPlugin(targetDir: string, options: ScaffoldPluginOptions = {}): string {\n const dir = resolveScaffoldTarget(targetDir, options);\n if (fs.existsSync(dir) && fs.readdirSync(dir).length > 0) {\n throw new Error(`Directory already exists and is not empty: ${targetDir}`);\n }\n\n const packageName =\n path\n .basename(dir)\n .toLowerCase()\n .replace(/[^a-z0-9_.-]+/g, '-')\n .replace(/^-|-$/g, '') || 'mastracode-plugin';\n const pluginId = options.id ?? packageName;\n const pluginName = options.name ?? humanizeName(packageName);\n\n fs.mkdirSync(path.join(dir, 'src'), { recursive: true });\n fs.writeFileSync(\n path.join(dir, 'package.json'),\n `${JSON.stringify(\n {\n name: packageName,\n type: 'module',\n exports: './src/index.ts',\n peerDependencies: {\n mastracode: '*',\n },\n devDependencies: {\n typescript: '^5.9.3',\n },\n scripts: {\n check: 'tsc --noEmit',\n },\n },\n null,\n 2,\n )}\\n`,\n );\n fs.writeFileSync(\n path.join(dir, 'tsconfig.json'),\n `${JSON.stringify(\n {\n compilerOptions: {\n target: 'ES2024',\n module: 'NodeNext',\n moduleResolution: 'NodeNext',\n strict: true,\n verbatimModuleSyntax: true,\n erasableSyntaxOnly: true,\n skipLibCheck: true,\n noEmit: true,\n },\n include: ['src/**/*.ts'],\n },\n null,\n 2,\n )}\\n`,\n );\n fs.writeFileSync(path.join(dir, 'src/index.ts'), renderIndex(pluginId, pluginName));\n fs.writeFileSync(path.join(dir, 'README.md'), renderReadme(pluginName, pluginId));\n writeScaffoldManifest(targetDir, dir, pluginId, pluginName, options);\n ensureMastraCodePackageLink(dir);\n return dir;\n}\n\nfunction writeScaffoldManifest(\n originalTarget: string,\n scaffoldDir: string,\n pluginId: string,\n pluginName: string,\n options: ScaffoldPluginOptions,\n): void {\n const projectRoot = options.projectRoot ?? process.cwd();\n const manifestRoot = isBarePluginName(originalTarget) ? projectRoot : scaffoldDir;\n const entry = isBarePluginName(originalTarget)\n ? path.join(path.relative(projectRoot, scaffoldDir), 'src/index.ts')\n : 'src/index.ts';\n upsertPluginManifestEntry(manifestRoot, {\n id: pluginId,\n name: pluginName,\n entry: entry.split(path.sep).join('/'),\n });\n}\n\nexport function formatScaffoldSuccess(targetDir: string): string {\n return [\n `Created Mastra Code plugin scaffold at ${targetDir}`,\n '',\n 'Next steps:',\n ` cd ${targetDir}`,\n ' pnpm install',\n ' pnpm check',\n ' mastracode',\n ' /plugins',\n ' Install new plugin → Local path',\n ].join('\\n');\n}\n\nfunction isBarePluginName(target: string): boolean {\n return !path.isAbsolute(target) && !target.startsWith('.') && !target.includes('/') && !target.includes('\\\\');\n}\n\nfunction renderIndex(pluginId: string, pluginName: string): string {\n return `import { createTool, defineMastraCodePlugin, z } from 'mastracode/plugin';\n\nexport default defineMastraCodePlugin({\n id: ${JSON.stringify(pluginId)},\n name: ${JSON.stringify(pluginName)},\n description: 'A Mastra Code tool plugin.',\n tools: {\n example_tool: {\n tool: createTool({\n id: 'example_tool',\n description: 'Echo a message from the scaffolded plugin.',\n inputSchema: z.object({\n message: z.string(),\n }),\n execute: async context => {\n return { message: context.message };\n },\n }),\n },\n },\n});\n`;\n}\n\nfunction renderReadme(pluginName: string, pluginId: string): string {\n return `# ${pluginName}\n\nMastra Code tool plugin: \\`${pluginId}\\`.\n\n## Develop\n\n\\`\\`\\`sh\npnpm install\npnpm check\n\\`\\`\\`\n\n## Install locally\n\nOpen Mastra Code, run \\`/plugins\\`, and install this directory as a local plugin.\n`;\n}\n\nfunction humanizeName(value: string): string {\n return (\n value\n .split(/[-_.]+/g)\n .filter(Boolean)\n .map(part => part[0]?.toUpperCase() + part.slice(1))\n .join(' ') || 'Mastra Code Plugin'\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"file":"scaffold.js","names":[],"sources":["../../src/plugins/scaffold.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\n\nimport { DEFAULT_CONFIG_DIR } from '../constants.js';\nimport { upsertPluginManifestEntry } from './manifest.js';\nimport { ensureMastraCodePackageLink } from './package-link.js';\n\nexport type ScaffoldPluginOptions = {\n id?: string;\n name?: string;\n projectRoot?: string;\n configDir?: string;\n};\n\nexport function resolveScaffoldTarget(\n target: string,\n options: Pick<ScaffoldPluginOptions, 'projectRoot' | 'configDir'> = {},\n): string {\n if (isBarePluginName(target)) {\n return path.join(\n options.projectRoot ?? process.cwd(),\n options.configDir ?? DEFAULT_CONFIG_DIR,\n 'plugins',\n 'sources',\n 'local',\n target,\n );\n }\n return path.resolve(options.projectRoot ?? process.cwd(), target);\n}\n\nexport function scaffoldPlugin(targetDir: string, options: ScaffoldPluginOptions = {}): string {\n const dir = resolveScaffoldTarget(targetDir, options);\n if (fs.existsSync(dir) && fs.readdirSync(dir).length > 0) {\n throw new Error(`Directory already exists and is not empty: ${targetDir}`);\n }\n\n const packageName =\n path\n .basename(dir)\n .toLowerCase()\n .replace(/[^a-z0-9_.-]+/g, '-')\n .replace(/^-|-$/g, '') || 'mastracode-plugin';\n const pluginId = options.id ?? packageName;\n const pluginName = options.name ?? humanizeName(packageName);\n\n fs.mkdirSync(path.join(dir, 'src'), { recursive: true });\n fs.writeFileSync(\n path.join(dir, 'package.json'),\n `${JSON.stringify(\n {\n name: packageName,\n type: 'module',\n exports: './src/index.ts',\n peerDependencies: {\n mastracode: '*',\n },\n devDependencies: {\n typescript: '^5.9.3',\n },\n scripts: {\n check: 'tsc --noEmit',\n },\n },\n null,\n 2,\n )}\\n`,\n );\n fs.writeFileSync(\n path.join(dir, 'tsconfig.json'),\n `${JSON.stringify(\n {\n compilerOptions: {\n target: 'ES2024',\n module: 'NodeNext',\n moduleResolution: 'NodeNext',\n strict: true,\n verbatimModuleSyntax: true,\n erasableSyntaxOnly: true,\n skipLibCheck: true,\n noEmit: true,\n },\n include: ['src/**/*.ts'],\n },\n null,\n 2,\n )}\\n`,\n );\n fs.writeFileSync(path.join(dir, 'src/index.ts'), renderIndex(pluginId, pluginName));\n fs.writeFileSync(path.join(dir, 'README.md'), renderReadme(pluginName, pluginId));\n writeScaffoldManifest(targetDir, dir, pluginId, pluginName, options);\n ensureMastraCodePackageLink(dir);\n return dir;\n}\n\nfunction writeScaffoldManifest(\n originalTarget: string,\n scaffoldDir: string,\n pluginId: string,\n pluginName: string,\n options: ScaffoldPluginOptions,\n): void {\n const projectRoot = options.projectRoot ?? process.cwd();\n const manifestRoot = isBarePluginName(originalTarget) ? projectRoot : scaffoldDir;\n const entry = isBarePluginName(originalTarget)\n ? path.join(path.relative(projectRoot, scaffoldDir), 'src/index.ts')\n : 'src/index.ts';\n upsertPluginManifestEntry(manifestRoot, {\n id: pluginId,\n name: pluginName,\n entry: entry.split(path.sep).join('/'),\n });\n}\n\nexport function formatScaffoldSuccess(targetDir: string): string {\n return [\n `Created Mastra Code plugin scaffold at ${targetDir}`,\n '',\n 'Next steps:',\n ` cd ${targetDir}`,\n ' pnpm install',\n ' pnpm check',\n ' mastracode',\n ' /plugins',\n ' Install new plugin → Local path',\n ].join('\\n');\n}\n\nfunction isBarePluginName(target: string): boolean {\n return !path.isAbsolute(target) && !target.startsWith('.') && !target.includes('/') && !target.includes('\\\\');\n}\n\nfunction renderIndex(pluginId: string, pluginName: string): string {\n return `import { createTool, defineMastraCodePlugin, z } from 'mastracode/plugin';\n\nexport default defineMastraCodePlugin({\n id: ${JSON.stringify(pluginId)},\n name: ${JSON.stringify(pluginName)},\n description: 'A Mastra Code tool plugin.',\n tools: {\n example_tool: {\n tool: createTool({\n id: 'example_tool',\n description: 'Echo a message from the scaffolded plugin.',\n inputSchema: z.object({\n message: z.string(),\n }),\n execute: async context => {\n return { message: context.message };\n },\n }),\n },\n },\n});\n`;\n}\n\nfunction renderReadme(pluginName: string, pluginId: string): string {\n return `# ${pluginName}\n\nMastra Code tool plugin: \\`${pluginId}\\`.\n\n## Develop\n\n\\`\\`\\`sh\npnpm install\npnpm check\n\\`\\`\\`\n\n## Install locally\n\nOpen Mastra Code, run \\`/plugins\\`, and install this directory as a local plugin.\n`;\n}\n\nfunction humanizeName(value: string): string {\n return (\n value\n .split(/[-_.]+/g)\n .filter(Boolean)\n .map(part => part[0]?.toUpperCase() + part.slice(1))\n .join(' ') || 'Mastra Code Plugin'\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- //# sourceMappingURL=types.js.map
1
+ export {};
@@ -1,53 +1,54 @@
1
+ //#region src/processors/plan-rejection-abort.ts
1
2
  const PLAN_REJECTED_PREFIX = "Plan was not approved";
2
3
  function resultText(result) {
3
- if (typeof result === "string") return result;
4
- if (result && typeof result === "object") {
5
- const content = result.content;
6
- if (typeof content === "string") return content;
7
- }
8
- return "";
4
+ if (typeof result === "string") return result;
5
+ if (result && typeof result === "object") {
6
+ const content = result.content;
7
+ if (typeof content === "string") return content;
8
+ }
9
+ return "";
9
10
  }
11
+ /**
12
+ * Returns true when the invocation is a completed `submit_plan` rejection.
13
+ */
10
14
  function isPlanRejection(inv) {
11
- if (!inv || inv.state !== "result" || inv.toolName !== "submit_plan") return false;
12
- return resultText(inv.result).startsWith(PLAN_REJECTED_PREFIX);
15
+ if (!inv || inv.state !== "result" || inv.toolName !== "submit_plan") return false;
16
+ return resultText(inv.result).startsWith(PLAN_REJECTED_PREFIX);
13
17
  }
14
18
  function isPlanRejectionResultPart(part) {
15
- return part.type === "tool_result" && part.name === "submit_plan" && resultText(part.result).startsWith(PLAN_REJECTED_PREFIX);
19
+ return part.type === "tool_result" && part.name === "submit_plan" && resultText(part.result).startsWith(PLAN_REJECTED_PREFIX);
16
20
  }
17
- class PlanRejectionAbortProcessor {
18
- id = "plan-rejection-abort";
19
- async processInputStep({ messages, stepNumber, abort }) {
20
- if (stepNumber === 0) return void 0;
21
- for (let i = messages.length - 1; i >= 0; i--) {
22
- const msg = messages[i];
23
- if (!msg || msg.role !== "assistant") continue;
24
- const content = msg.content;
25
- const parts = Array.isArray(content) ? content : Array.isArray(content?.parts) ? content.parts : [];
26
- for (const part of parts) {
27
- if (!part || typeof part !== "object") continue;
28
- const p = part;
29
- if (p.type === "tool-invocation" && isPlanRejection(p.toolInvocation)) {
30
- abort("Plan rejected by user \u2014 no further response needed");
31
- return void 0;
32
- }
33
- if (isPlanRejectionResultPart(p)) {
34
- abort("Plan rejected by user \u2014 no further response needed");
35
- return void 0;
36
- }
37
- }
38
- const legacy = !Array.isArray(content) && Array.isArray(content?.toolInvocations) ? content.toolInvocations : [];
39
- for (const inv of legacy) {
40
- if (isPlanRejection(inv)) {
41
- abort("Plan rejected by user \u2014 no further response needed");
42
- return void 0;
43
- }
44
- }
45
- break;
46
- }
47
- return void 0;
48
- }
49
- }
50
- export {
51
- PlanRejectionAbortProcessor
21
+ var PlanRejectionAbortProcessor = class {
22
+ id = "plan-rejection-abort";
23
+ async processInputStep({ messages, stepNumber, abort }) {
24
+ if (stepNumber === 0) return void 0;
25
+ for (let i = messages.length - 1; i >= 0; i--) {
26
+ const msg = messages[i];
27
+ if (!msg || msg.role !== "assistant") continue;
28
+ const content = msg.content;
29
+ const parts = Array.isArray(content) ? content : Array.isArray(content?.parts) ? content.parts : [];
30
+ for (const part of parts) {
31
+ if (!part || typeof part !== "object") continue;
32
+ const p = part;
33
+ if (p.type === "tool-invocation" && isPlanRejection(p.toolInvocation)) {
34
+ abort("Plan rejected by user no further response needed");
35
+ return;
36
+ }
37
+ if (isPlanRejectionResultPart(p)) {
38
+ abort("Plan rejected by user no further response needed");
39
+ return;
40
+ }
41
+ }
42
+ const legacy = !Array.isArray(content) && Array.isArray(content?.toolInvocations) ? content.toolInvocations : [];
43
+ for (const inv of legacy) if (isPlanRejection(inv)) {
44
+ abort("Plan rejected by user — no further response needed");
45
+ return;
46
+ }
47
+ break;
48
+ }
49
+ }
52
50
  };
51
+ //#endregion
52
+ export { PlanRejectionAbortProcessor };
53
+
53
54
  //# sourceMappingURL=plan-rejection-abort.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/processors/plan-rejection-abort.ts"],"sourcesContent":["/**\n * Processor that aborts the agentic loop immediately after a `submit_plan` tool\n * returns a rejection result. This prevents the model from generating any text\n * after the user clicks \"Request Changes\" — the tool result is persisted in\n * thread history (for context on the next run) but no follow-up LLM call is made.\n */\nimport type { Processor, ProcessInputStepArgs } from '@mastra/core/processors';\n\nconst PLAN_REJECTED_PREFIX = 'Plan was not approved';\n\ntype ToolInvocation = {\n state?: string;\n toolName?: string;\n result?: unknown;\n};\n\ntype ToolResultPart = {\n type?: string;\n name?: string;\n result?: unknown;\n};\n\nfunction resultText(result: unknown): string {\n if (typeof result === 'string') return result;\n if (result && typeof result === 'object') {\n const content = (result as { content?: unknown }).content;\n if (typeof content === 'string') return content;\n }\n return '';\n}\n\n/**\n * Returns true when the invocation is a completed `submit_plan` rejection.\n */\nfunction isPlanRejection(inv: ToolInvocation | undefined): boolean {\n if (!inv || inv.state !== 'result' || inv.toolName !== 'submit_plan') return false;\n return resultText(inv.result).startsWith(PLAN_REJECTED_PREFIX);\n}\n\nfunction isPlanRejectionResultPart(part: ToolResultPart): boolean {\n return (\n part.type === 'tool_result' &&\n part.name === 'submit_plan' &&\n resultText(part.result).startsWith(PLAN_REJECTED_PREFIX)\n );\n}\n\nexport class PlanRejectionAbortProcessor implements Processor<'plan-rejection-abort'> {\n id = 'plan-rejection-abort' as const;\n\n async processInputStep({ messages, stepNumber, abort }: ProcessInputStepArgs): Promise<undefined> {\n // Only act on continuation steps (stepNumber > 0) — step 0 is the initial\n // prompt where the model hasn't responded yet. After tool resume, the tool\n // result is part of step 0 and the loop advances to step 1 for the next\n // model call.\n if (stepNumber === 0) return undefined;\n\n // Walk messages from the end to find the last assistant message.\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i];\n if (!msg || msg.role !== 'assistant') continue;\n\n // Check for a submit_plan rejection tool result. Handle the primary\n // `content.parts` shapes (tool-invocation and harness-style tool_result)\n // plus the legacy `content.toolInvocations` array.\n const content = msg.content as { parts?: unknown[]; toolInvocations?: unknown[] } | unknown[] | undefined;\n\n const parts = Array.isArray(content) ? content : Array.isArray(content?.parts) ? content.parts : [];\n for (const part of parts) {\n if (!part || typeof part !== 'object') continue;\n const p = part as { type?: string; toolInvocation?: ToolInvocation } & ToolResultPart;\n if (p.type === 'tool-invocation' && isPlanRejection(p.toolInvocation)) {\n abort('Plan rejected by user — no further response needed');\n return undefined;\n }\n if (isPlanRejectionResultPart(p)) {\n abort('Plan rejected by user — no further response needed');\n return undefined;\n }\n }\n\n const legacy = !Array.isArray(content) && Array.isArray(content?.toolInvocations) ? content.toolInvocations : [];\n for (const inv of legacy) {\n if (isPlanRejection(inv as ToolInvocation)) {\n abort('Plan rejected by user — no further response needed');\n return undefined;\n }\n }\n\n // Only check the most recent assistant message.\n break;\n }\n\n return undefined;\n }\n}\n"],"mappings":"AAQA,MAAM,uBAAuB;AAc7B,SAAS,WAAW,QAAyB;AAC3C,MAAI,OAAO,WAAW,SAAU,QAAO;AACvC,MAAI,UAAU,OAAO,WAAW,UAAU;AACxC,UAAM,UAAW,OAAiC;AAClD,QAAI,OAAO,YAAY,SAAU,QAAO;AAAA,EAC1C;AACA,SAAO;AACT;AAKA,SAAS,gBAAgB,KAA0C;AACjE,MAAI,CAAC,OAAO,IAAI,UAAU,YAAY,IAAI,aAAa,cAAe,QAAO;AAC7E,SAAO,WAAW,IAAI,MAAM,EAAE,WAAW,oBAAoB;AAC/D;AAEA,SAAS,0BAA0B,MAA+B;AAChE,SACE,KAAK,SAAS,iBACd,KAAK,SAAS,iBACd,WAAW,KAAK,MAAM,EAAE,WAAW,oBAAoB;AAE3D;AAEO,MAAM,4BAAyE;AAAA,EACpF,KAAK;AAAA,EAEL,MAAM,iBAAiB,EAAE,UAAU,YAAY,MAAM,GAA6C;AAKhG,QAAI,eAAe,EAAG,QAAO;AAG7B,aAAS,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;AAC7C,YAAM,MAAM,SAAS,CAAC;AACtB,UAAI,CAAC,OAAO,IAAI,SAAS,YAAa;AAKtC,YAAM,UAAU,IAAI;AAEpB,YAAM,QAAQ,MAAM,QAAQ,OAAO,IAAI,UAAU,MAAM,QAAQ,SAAS,KAAK,IAAI,QAAQ,QAAQ,CAAC;AAClG,iBAAW,QAAQ,OAAO;AACxB,YAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;AACvC,cAAM,IAAI;AACV,YAAI,EAAE,SAAS,qBAAqB,gBAAgB,EAAE,cAAc,GAAG;AACrE,gBAAM,yDAAoD;AAC1D,iBAAO;AAAA,QACT;AACA,YAAI,0BAA0B,CAAC,GAAG;AAChC,gBAAM,yDAAoD;AAC1D,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,YAAM,SAAS,CAAC,MAAM,QAAQ,OAAO,KAAK,MAAM,QAAQ,SAAS,eAAe,IAAI,QAAQ,kBAAkB,CAAC;AAC/G,iBAAW,OAAO,QAAQ;AACxB,YAAI,gBAAgB,GAAqB,GAAG;AAC1C,gBAAM,yDAAoD;AAC1D,iBAAO;AAAA,QACT;AAAA,MACF;AAGA;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;","names":[]}
1
+ {"version":3,"file":"plan-rejection-abort.js","names":[],"sources":["../../src/processors/plan-rejection-abort.ts"],"sourcesContent":["/**\n * Processor that aborts the agentic loop immediately after a `submit_plan` tool\n * returns a rejection result. This prevents the model from generating any text\n * after the user clicks \"Request Changes\" — the tool result is persisted in\n * thread history (for context on the next run) but no follow-up LLM call is made.\n */\nimport type { Processor, ProcessInputStepArgs } from '@mastra/core/processors';\n\nconst PLAN_REJECTED_PREFIX = 'Plan was not approved';\n\ntype ToolInvocation = {\n state?: string;\n toolName?: string;\n result?: unknown;\n};\n\ntype ToolResultPart = {\n type?: string;\n name?: string;\n result?: unknown;\n};\n\nfunction resultText(result: unknown): string {\n if (typeof result === 'string') return result;\n if (result && typeof result === 'object') {\n const content = (result as { content?: unknown }).content;\n if (typeof content === 'string') return content;\n }\n return '';\n}\n\n/**\n * Returns true when the invocation is a completed `submit_plan` rejection.\n */\nfunction isPlanRejection(inv: ToolInvocation | undefined): boolean {\n if (!inv || inv.state !== 'result' || inv.toolName !== 'submit_plan') return false;\n return resultText(inv.result).startsWith(PLAN_REJECTED_PREFIX);\n}\n\nfunction isPlanRejectionResultPart(part: ToolResultPart): boolean {\n return (\n part.type === 'tool_result' &&\n part.name === 'submit_plan' &&\n resultText(part.result).startsWith(PLAN_REJECTED_PREFIX)\n );\n}\n\nexport class PlanRejectionAbortProcessor implements Processor<'plan-rejection-abort'> {\n id = 'plan-rejection-abort' as const;\n\n async processInputStep({ messages, stepNumber, abort }: ProcessInputStepArgs): Promise<undefined> {\n // Only act on continuation steps (stepNumber > 0) — step 0 is the initial\n // prompt where the model hasn't responded yet. After tool resume, the tool\n // result is part of step 0 and the loop advances to step 1 for the next\n // model call.\n if (stepNumber === 0) return undefined;\n\n // Walk messages from the end to find the last assistant message.\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i];\n if (!msg || msg.role !== 'assistant') continue;\n\n // Check for a submit_plan rejection tool result. Handle the primary\n // `content.parts` shapes (tool-invocation and harness-style tool_result)\n // plus the legacy `content.toolInvocations` array.\n const content = msg.content as { parts?: unknown[]; toolInvocations?: unknown[] } | unknown[] | undefined;\n\n const parts = Array.isArray(content) ? content : Array.isArray(content?.parts) ? content.parts : [];\n for (const part of parts) {\n if (!part || typeof part !== 'object') continue;\n const p = part as { type?: string; toolInvocation?: ToolInvocation } & ToolResultPart;\n if (p.type === 'tool-invocation' && isPlanRejection(p.toolInvocation)) {\n abort('Plan rejected by user — no further response needed');\n return undefined;\n }\n if (isPlanRejectionResultPart(p)) {\n abort('Plan rejected by user — no further response needed');\n return undefined;\n }\n }\n\n const legacy = !Array.isArray(content) && Array.isArray(content?.toolInvocations) ? content.toolInvocations : [];\n for (const inv of legacy) {\n if (isPlanRejection(inv as ToolInvocation)) {\n abort('Plan rejected by user — no further response needed');\n return undefined;\n }\n }\n\n // Only check the most recent assistant message.\n break;\n }\n\n return undefined;\n }\n}\n"],"mappings":";AAQA,MAAM,uBAAuB;AAc7B,SAAS,WAAW,QAAyB;CAC3C,IAAI,OAAO,WAAW,UAAU,OAAO;CACvC,IAAI,UAAU,OAAO,WAAW,UAAU;EACxC,MAAM,UAAW,OAAiC;EAClD,IAAI,OAAO,YAAY,UAAU,OAAO;CAC1C;CACA,OAAO;AACT;;;;AAKA,SAAS,gBAAgB,KAA0C;CACjE,IAAI,CAAC,OAAO,IAAI,UAAU,YAAY,IAAI,aAAa,eAAe,OAAO;CAC7E,OAAO,WAAW,IAAI,MAAM,CAAC,CAAC,WAAW,oBAAoB;AAC/D;AAEA,SAAS,0BAA0B,MAA+B;CAChE,OACE,KAAK,SAAS,iBACd,KAAK,SAAS,iBACd,WAAW,KAAK,MAAM,CAAC,CAAC,WAAW,oBAAoB;AAE3D;AAEA,IAAa,8BAAb,MAAsF;CACpF,KAAK;CAEL,MAAM,iBAAiB,EAAE,UAAU,YAAY,SAAmD;EAKhG,IAAI,eAAe,GAAG,OAAO,KAAA;EAG7B,KAAK,IAAI,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;GAC7C,MAAM,MAAM,SAAS;GACrB,IAAI,CAAC,OAAO,IAAI,SAAS,aAAa;GAKtC,MAAM,UAAU,IAAI;GAEpB,MAAM,QAAQ,MAAM,QAAQ,OAAO,IAAI,UAAU,MAAM,QAAQ,SAAS,KAAK,IAAI,QAAQ,QAAQ,CAAC;GAClG,KAAK,MAAM,QAAQ,OAAO;IACxB,IAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;IACvC,MAAM,IAAI;IACV,IAAI,EAAE,SAAS,qBAAqB,gBAAgB,EAAE,cAAc,GAAG;KACrE,MAAM,oDAAoD;KAC1D;IACF;IACA,IAAI,0BAA0B,CAAC,GAAG;KAChC,MAAM,oDAAoD;KAC1D;IACF;GACF;GAEA,MAAM,SAAS,CAAC,MAAM,QAAQ,OAAO,KAAK,MAAM,QAAQ,SAAS,eAAe,IAAI,QAAQ,kBAAkB,CAAC;GAC/G,KAAK,MAAM,OAAO,QAChB,IAAI,gBAAgB,GAAqB,GAAG;IAC1C,MAAM,oDAAoD;IAC1D;GACF;GAIF;EACF;CAGF;AACF"}