@mastra/agent-builder 0.0.0-experimental-agent-builder-20250815195917 → 0.0.1-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.
- package/CHANGELOG.md +22 -16
- package/README.md +4 -17
- package/dist/agent/index.d.ts +5885 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/defaults.d.ts +6529 -0
- package/dist/defaults.d.ts.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2943 -591
- package/dist/index.js.map +1 -0
- package/dist/processors/tool-summary.d.ts +29 -0
- package/dist/processors/tool-summary.d.ts.map +1 -0
- package/dist/processors/write-file.d.ts +10 -0
- package/dist/processors/write-file.d.ts.map +1 -0
- package/dist/types.d.ts +1121 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils.d.ts +63 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/workflows/index.d.ts +5 -0
- package/dist/workflows/index.d.ts.map +1 -0
- package/dist/workflows/shared/schema.d.ts +139 -0
- package/dist/workflows/shared/schema.d.ts.map +1 -0
- package/dist/workflows/task-planning/prompts.d.ts +37 -0
- package/dist/workflows/task-planning/prompts.d.ts.map +1 -0
- package/dist/workflows/task-planning/schema.d.ts +548 -0
- package/dist/workflows/task-planning/schema.d.ts.map +1 -0
- package/dist/workflows/task-planning/task-planning.d.ts +992 -0
- package/dist/workflows/task-planning/task-planning.d.ts.map +1 -0
- package/dist/workflows/template-builder/template-builder.d.ts +1910 -0
- package/dist/workflows/template-builder/template-builder.d.ts.map +1 -0
- package/dist/workflows/workflow-builder/prompts.d.ts +44 -0
- package/dist/workflows/workflow-builder/prompts.d.ts.map +1 -0
- package/dist/workflows/workflow-builder/schema.d.ts +1170 -0
- package/dist/workflows/workflow-builder/schema.d.ts.map +1 -0
- package/dist/workflows/workflow-builder/tools.d.ts +309 -0
- package/dist/workflows/workflow-builder/tools.d.ts.map +1 -0
- package/dist/workflows/workflow-builder/workflow-builder.d.ts +2714 -0
- package/dist/workflows/workflow-builder/workflow-builder.d.ts.map +1 -0
- package/dist/workflows/workflow-map.d.ts +3735 -0
- package/dist/workflows/workflow-map.d.ts.map +1 -0
- package/package.json +21 -9
- package/dist/_tsup-dts-rollup.d.cts +0 -13109
- package/dist/_tsup-dts-rollup.d.ts +0 -13109
- package/dist/index.cjs +0 -3772
- package/dist/index.d.cts +0 -1
- package/eslint.config.js +0 -11
- package/integration-tests/CHANGELOG.md +0 -20
- package/integration-tests/README.md +0 -154
- package/integration-tests/docker-compose.yml +0 -39
- package/integration-tests/package.json +0 -38
- package/integration-tests/src/agent-template-behavior.test.ts +0 -103
- package/integration-tests/src/fixtures/minimal-mastra-project/env.example +0 -6
- package/integration-tests/src/fixtures/minimal-mastra-project/package.json +0 -17
- package/integration-tests/src/fixtures/minimal-mastra-project/src/mastra/agents/weather.ts +0 -34
- package/integration-tests/src/fixtures/minimal-mastra-project/src/mastra/index.ts +0 -15
- package/integration-tests/src/fixtures/minimal-mastra-project/src/mastra/mcp/index.ts +0 -46
- package/integration-tests/src/fixtures/minimal-mastra-project/src/mastra/tools/weather.ts +0 -13
- package/integration-tests/src/fixtures/minimal-mastra-project/tsconfig.json +0 -17
- package/integration-tests/src/template-integration.test.ts +0 -312
- package/integration-tests/tsconfig.json +0 -13
- package/integration-tests/vitest.config.ts +0 -17
- package/src/agent-builder.test.ts +0 -291
- package/src/defaults.ts +0 -2728
- package/src/index.ts +0 -187
- package/src/processors/tool-summary.ts +0 -136
- package/src/processors/write-file.ts +0 -17
- package/src/types.ts +0 -120
- package/src/utils.ts +0 -133
- package/src/workflows/index.ts +0 -1541
- package/tsconfig.json +0 -5
- package/vitest.config.ts +0 -11
package/src/index.ts
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
import type { CoreMessage } from '@mastra/core';
|
|
2
|
-
import { Agent } from '@mastra/core/agent';
|
|
3
|
-
import type { AiMessageType, AgentGenerateOptions, AgentStreamOptions } from '@mastra/core/agent';
|
|
4
|
-
import { Memory } from '@mastra/memory';
|
|
5
|
-
import { TokenLimiter } from '@mastra/memory/processors';
|
|
6
|
-
import { AgentBuilderDefaults } from './defaults';
|
|
7
|
-
import { ToolSummaryProcessor } from './processors/tool-summary';
|
|
8
|
-
import { WriteToDiskProcessor } from './processors/write-file';
|
|
9
|
-
import type { AgentBuilderConfig, GenerateAgentOptions } from './types';
|
|
10
|
-
import { mergeTemplateWorkflow } from './workflows';
|
|
11
|
-
|
|
12
|
-
// =============================================================================
|
|
13
|
-
// Template Merge Workflow Implementation
|
|
14
|
-
// =============================================================================
|
|
15
|
-
//
|
|
16
|
-
// This workflow implements a comprehensive template merging system that:
|
|
17
|
-
// 1. Clones template repositories at specific refs (tags/commits)
|
|
18
|
-
// 2. Discovers units (agents, workflows, MCP servers/tools) in templates
|
|
19
|
-
// 3. Topologically orders units based on dependencies
|
|
20
|
-
// 4. Analyzes conflicts and creates safety classifications
|
|
21
|
-
// 5. Applies changes with git branching and checkpoints per unit
|
|
22
|
-
//
|
|
23
|
-
// The workflow follows the "auto-decide vs ask" principles:
|
|
24
|
-
// - Auto: adding new files, missing deps, appending arrays, new scripts with template:slug:* namespace
|
|
25
|
-
// - Prompt: overwriting files, major upgrades, renaming conflicts, new ports, postInstall commands
|
|
26
|
-
// - Block: removing files, downgrading deps, changing TS target/module, modifying CI/CD secrets
|
|
27
|
-
//
|
|
28
|
-
// Usage with Mastra templates (see https://mastra.ai/api/templates.json):
|
|
29
|
-
// const run = await mergeTemplateWorkflow.createRunAsync();
|
|
30
|
-
// const result = await run.start({
|
|
31
|
-
// inputData: {
|
|
32
|
-
// repo: 'https://github.com/mastra-ai/template-pdf-questions',
|
|
33
|
-
// ref: 'main', // optional
|
|
34
|
-
// targetPath: './my-project', // optional, defaults to cwd
|
|
35
|
-
// }
|
|
36
|
-
// });
|
|
37
|
-
// // The workflow will automatically analyze and merge the template structure
|
|
38
|
-
//
|
|
39
|
-
// =============================================================================
|
|
40
|
-
|
|
41
|
-
export class AgentBuilder extends Agent {
|
|
42
|
-
private builderConfig: AgentBuilderConfig;
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Private constructor - use AgentBuilder.create() instead
|
|
46
|
-
*/
|
|
47
|
-
constructor(config: AgentBuilderConfig) {
|
|
48
|
-
const additionalInstructions = config.instructions ? `## Priority Instructions \n\n${config.instructions}` : '';
|
|
49
|
-
const combinedInstructions = additionalInstructions + AgentBuilderDefaults.DEFAULT_INSTRUCTIONS(config.projectPath);
|
|
50
|
-
|
|
51
|
-
const agentConfig = {
|
|
52
|
-
name: 'agent-builder',
|
|
53
|
-
description:
|
|
54
|
-
'An AI agent specialized in generating Mastra agents, tools, and workflows from natural language requirements.',
|
|
55
|
-
instructions: combinedInstructions,
|
|
56
|
-
model: config.model,
|
|
57
|
-
tools: async () => {
|
|
58
|
-
return {
|
|
59
|
-
...(await AgentBuilderDefaults.DEFAULT_TOOLS(config.projectPath, config.mode)),
|
|
60
|
-
...(config.tools || {}),
|
|
61
|
-
};
|
|
62
|
-
},
|
|
63
|
-
workflows: {
|
|
64
|
-
'merge-template': mergeTemplateWorkflow,
|
|
65
|
-
},
|
|
66
|
-
memory: new Memory({
|
|
67
|
-
options: AgentBuilderDefaults.DEFAULT_MEMORY_CONFIG,
|
|
68
|
-
processors: [
|
|
69
|
-
new WriteToDiskProcessor({ prefix: 'before-filter' }),
|
|
70
|
-
new ToolSummaryProcessor({ summaryModel: config.summaryModel || config.model }),
|
|
71
|
-
new TokenLimiter(100000),
|
|
72
|
-
new WriteToDiskProcessor({ prefix: 'after-filter' }),
|
|
73
|
-
],
|
|
74
|
-
}),
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
super(agentConfig);
|
|
78
|
-
this.builderConfig = config;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Enhanced generate method with AgentBuilder-specific configuration
|
|
83
|
-
* Overrides the base Agent generate method to provide additional project context
|
|
84
|
-
*/
|
|
85
|
-
generate: Agent['generate'] = async (
|
|
86
|
-
messages: string | string[] | CoreMessage[] | AiMessageType[],
|
|
87
|
-
generateOptions: (GenerateAgentOptions & AgentGenerateOptions<any, any>) | undefined = {},
|
|
88
|
-
): Promise<any> => {
|
|
89
|
-
const { ...baseOptions } = generateOptions;
|
|
90
|
-
|
|
91
|
-
const originalInstructions = await this.getInstructions({ runtimeContext: generateOptions?.runtimeContext });
|
|
92
|
-
const additionalInstructions = baseOptions.instructions;
|
|
93
|
-
|
|
94
|
-
let enhancedInstructions = originalInstructions as string;
|
|
95
|
-
if (additionalInstructions) {
|
|
96
|
-
enhancedInstructions = `${originalInstructions}\n\n${additionalInstructions}`;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const enhancedContext = [...(baseOptions.context || [])];
|
|
100
|
-
|
|
101
|
-
const enhancedOptions = {
|
|
102
|
-
...baseOptions,
|
|
103
|
-
maxSteps: 300, // Higher default for code generation
|
|
104
|
-
temperature: 0.3, // Lower temperature for more consistent code generation
|
|
105
|
-
instructions: enhancedInstructions,
|
|
106
|
-
context: enhancedContext,
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
this.logger.debug(`[AgentBuilder:${this.name}] Starting generation with enhanced context`, {
|
|
110
|
-
projectPath: this.builderConfig.projectPath,
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
return super.generate(messages, enhancedOptions);
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Enhanced stream method with AgentBuilder-specific configuration
|
|
118
|
-
* Overrides the base Agent stream method to provide additional project context
|
|
119
|
-
*/
|
|
120
|
-
stream: Agent['stream'] = async (
|
|
121
|
-
messages: string | string[] | CoreMessage[] | AiMessageType[],
|
|
122
|
-
streamOptions: (GenerateAgentOptions & AgentStreamOptions<any, any>) | undefined = {},
|
|
123
|
-
): Promise<any> => {
|
|
124
|
-
const { ...baseOptions } = streamOptions;
|
|
125
|
-
|
|
126
|
-
const originalInstructions = await this.getInstructions({ runtimeContext: streamOptions?.runtimeContext });
|
|
127
|
-
const additionalInstructions = baseOptions.instructions;
|
|
128
|
-
|
|
129
|
-
let enhancedInstructions = originalInstructions as string;
|
|
130
|
-
if (additionalInstructions) {
|
|
131
|
-
enhancedInstructions = `${originalInstructions}\n\n${additionalInstructions}`;
|
|
132
|
-
}
|
|
133
|
-
const enhancedContext = [...(baseOptions.context || [])];
|
|
134
|
-
|
|
135
|
-
const enhancedOptions = {
|
|
136
|
-
...baseOptions,
|
|
137
|
-
maxSteps: 100, // Higher default for code generation
|
|
138
|
-
temperature: 0.3, // Lower temperature for more consistent code generation
|
|
139
|
-
instructions: enhancedInstructions,
|
|
140
|
-
context: enhancedContext,
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
this.logger.debug(`[AgentBuilder:${this.name}] Starting streaming with enhanced context`, {
|
|
144
|
-
projectPath: this.builderConfig.projectPath,
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
return super.stream(messages, enhancedOptions);
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Generate a Mastra agent from natural language requirements
|
|
152
|
-
*/
|
|
153
|
-
async generateAgent(
|
|
154
|
-
requirements: string,
|
|
155
|
-
options?: {
|
|
156
|
-
outputFormat?: 'code' | 'explanation' | 'both';
|
|
157
|
-
runtimeContext?: any;
|
|
158
|
-
},
|
|
159
|
-
) {
|
|
160
|
-
const prompt = `Generate a Mastra agent based on these requirements: ${requirements}
|
|
161
|
-
|
|
162
|
-
Please provide:
|
|
163
|
-
1. Complete agent code with proper configuration
|
|
164
|
-
2. Any custom tools the agent needs
|
|
165
|
-
3. Example usage
|
|
166
|
-
4. Testing recommendations
|
|
167
|
-
|
|
168
|
-
${options?.outputFormat === 'explanation' ? 'Focus on explaining the approach and architecture.' : ''}
|
|
169
|
-
${options?.outputFormat === 'code' ? 'Focus on providing complete, working code.' : ''}
|
|
170
|
-
${!options?.outputFormat || options.outputFormat === 'both' ? 'Provide both explanation and complete code.' : ''}`;
|
|
171
|
-
|
|
172
|
-
return this.generate(prompt, {
|
|
173
|
-
runtimeContext: options?.runtimeContext,
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Get the default configuration for AgentBuilder
|
|
179
|
-
*/
|
|
180
|
-
static defaultConfig(projectPath?: string) {
|
|
181
|
-
return {
|
|
182
|
-
instructions: AgentBuilderDefaults.DEFAULT_INSTRUCTIONS(projectPath),
|
|
183
|
-
memoryConfig: AgentBuilderDefaults.DEFAULT_MEMORY_CONFIG,
|
|
184
|
-
tools: AgentBuilderDefaults.DEFAULT_TOOLS,
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
}
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import type { CoreMessage, MastraLanguageModel } from '@mastra/core';
|
|
2
|
-
import { Agent, MemoryProcessor } from '@mastra/core';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Summarizes tool calls and caches results to avoid re-summarizing identical calls
|
|
6
|
-
*/
|
|
7
|
-
export class ToolSummaryProcessor extends MemoryProcessor {
|
|
8
|
-
private summaryAgent: Agent;
|
|
9
|
-
private summaryCache: Map<string, string> = new Map();
|
|
10
|
-
|
|
11
|
-
constructor({ summaryModel }: { summaryModel: MastraLanguageModel }) {
|
|
12
|
-
super({ name: 'ToolSummaryProcessor' });
|
|
13
|
-
this.summaryAgent = new Agent({
|
|
14
|
-
name: 'ToolSummaryAgent',
|
|
15
|
-
description: 'A summary agent that summarizes tool calls and results',
|
|
16
|
-
instructions: 'You are a summary agent that summarizes tool calls and results',
|
|
17
|
-
model: summaryModel,
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Creates a cache key from tool call arguments
|
|
23
|
-
*/
|
|
24
|
-
public createCacheKey(toolCall: any): string {
|
|
25
|
-
if (!toolCall) return 'unknown';
|
|
26
|
-
|
|
27
|
-
// Create a deterministic key from tool name and arguments
|
|
28
|
-
const toolName = toolCall.toolName || 'unknown';
|
|
29
|
-
const args = toolCall.args || {};
|
|
30
|
-
|
|
31
|
-
// Sort keys for consistent hashing
|
|
32
|
-
const sortedArgs = Object.keys(args)
|
|
33
|
-
.sort()
|
|
34
|
-
.reduce((result: Record<string, any>, key) => {
|
|
35
|
-
result[key] = args[key];
|
|
36
|
-
return result;
|
|
37
|
-
}, {});
|
|
38
|
-
|
|
39
|
-
return `${toolName}:${JSON.stringify(sortedArgs)}`;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Clears the summary cache
|
|
44
|
-
*/
|
|
45
|
-
public clearCache(): void {
|
|
46
|
-
this.summaryCache.clear();
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Gets cache statistics
|
|
51
|
-
*/
|
|
52
|
-
public getCacheStats(): { size: number; keys: string[] } {
|
|
53
|
-
return {
|
|
54
|
-
size: this.summaryCache.size,
|
|
55
|
-
keys: Array.from(this.summaryCache.keys()),
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async process(messages: CoreMessage[]): Promise<CoreMessage[]> {
|
|
60
|
-
// Collect all tool calls that need summarization
|
|
61
|
-
const summaryTasks: Array<{
|
|
62
|
-
content: any;
|
|
63
|
-
promise: Promise<any>;
|
|
64
|
-
cacheKey: string;
|
|
65
|
-
}> = [];
|
|
66
|
-
|
|
67
|
-
// First pass: collect all tool results that need summarization
|
|
68
|
-
for (const message of messages) {
|
|
69
|
-
if (
|
|
70
|
-
message.role === 'tool' &&
|
|
71
|
-
Array.isArray(message.content) &&
|
|
72
|
-
message.content.length > 0 &&
|
|
73
|
-
message.content?.some(content => content.type === 'tool-result')
|
|
74
|
-
) {
|
|
75
|
-
for (const content of message.content) {
|
|
76
|
-
if (content.type === 'tool-result') {
|
|
77
|
-
const assistantMessageWithToolCall = messages.find(
|
|
78
|
-
message =>
|
|
79
|
-
message.role === 'assistant' &&
|
|
80
|
-
Array.isArray(message.content) &&
|
|
81
|
-
message.content.length > 0 &&
|
|
82
|
-
message.content?.some(
|
|
83
|
-
assistantContent =>
|
|
84
|
-
assistantContent.type === 'tool-call' && assistantContent.toolCallId === content.toolCallId,
|
|
85
|
-
),
|
|
86
|
-
);
|
|
87
|
-
const toolCall = Array.isArray(assistantMessageWithToolCall?.content)
|
|
88
|
-
? assistantMessageWithToolCall?.content.find(
|
|
89
|
-
assistantContent =>
|
|
90
|
-
assistantContent.type === 'tool-call' && assistantContent.toolCallId === content.toolCallId,
|
|
91
|
-
)
|
|
92
|
-
: null;
|
|
93
|
-
|
|
94
|
-
const cacheKey = this.createCacheKey(toolCall);
|
|
95
|
-
const cachedSummary = this.summaryCache.get(cacheKey);
|
|
96
|
-
|
|
97
|
-
if (cachedSummary) {
|
|
98
|
-
// Use cached summary immediately
|
|
99
|
-
content.result = `Tool call summary: ${cachedSummary}`;
|
|
100
|
-
} else {
|
|
101
|
-
// Create a promise for this summary (but don't await yet)
|
|
102
|
-
const summaryPromise = this.summaryAgent.generate(
|
|
103
|
-
`Summarize the following tool call: ${JSON.stringify(toolCall)} and result: ${JSON.stringify(content)}`,
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
summaryTasks.push({
|
|
107
|
-
content,
|
|
108
|
-
promise: summaryPromise,
|
|
109
|
-
cacheKey,
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Execute all non-cached summaries in parallel
|
|
118
|
-
if (summaryTasks.length > 0) {
|
|
119
|
-
const summaryResults = await Promise.all(summaryTasks.map(task => task.promise));
|
|
120
|
-
|
|
121
|
-
// Apply the results back to the content and cache them
|
|
122
|
-
summaryTasks.forEach((task, index) => {
|
|
123
|
-
const summaryResult = summaryResults[index];
|
|
124
|
-
const summaryText = summaryResult.text;
|
|
125
|
-
|
|
126
|
-
// Cache the summary for future use
|
|
127
|
-
this.summaryCache.set(task.cacheKey, summaryText);
|
|
128
|
-
|
|
129
|
-
// Apply to content
|
|
130
|
-
task.content.result = `Tool call summary: ${summaryText}`;
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return messages;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { writeFile } from 'fs/promises';
|
|
2
|
-
import { MemoryProcessor } from '@mastra/core';
|
|
3
|
-
import type { CoreMessage } from '@mastra/core';
|
|
4
|
-
|
|
5
|
-
export class WriteToDiskProcessor extends MemoryProcessor {
|
|
6
|
-
private prefix: string;
|
|
7
|
-
|
|
8
|
-
constructor({ prefix = 'messages' }: { prefix?: string } = {}) {
|
|
9
|
-
super({ name: 'WriteToDiskProcessor' });
|
|
10
|
-
this.prefix = prefix;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
async process(messages: CoreMessage[]): Promise<CoreMessage[]> {
|
|
14
|
-
await writeFile(`${this.prefix}-${Date.now()}.json`, JSON.stringify(messages, null, 2));
|
|
15
|
-
return messages;
|
|
16
|
-
}
|
|
17
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import type { MastraLanguageModel, ToolsInput } from '@mastra/core/agent';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Configuration options for the AgentBuilder
|
|
6
|
-
*/
|
|
7
|
-
export interface AgentBuilderConfig {
|
|
8
|
-
/** The language model to use for agent generation */
|
|
9
|
-
model: MastraLanguageModel;
|
|
10
|
-
/** Storage provider for memory (optional) */
|
|
11
|
-
storage?: any;
|
|
12
|
-
/** Vector provider for memory (optional) */
|
|
13
|
-
vectorProvider?: any;
|
|
14
|
-
/** Additional tools to include beyond the default set */
|
|
15
|
-
tools?: ToolsInput;
|
|
16
|
-
/** Custom instructions to append to the default system prompt */
|
|
17
|
-
instructions?: string;
|
|
18
|
-
/** Memory configuration options */
|
|
19
|
-
memoryConfig?: {
|
|
20
|
-
maxMessages?: number;
|
|
21
|
-
tokenLimit?: number;
|
|
22
|
-
};
|
|
23
|
-
/** Project path */
|
|
24
|
-
projectPath: string;
|
|
25
|
-
/** Summary model */
|
|
26
|
-
summaryModel?: MastraLanguageModel;
|
|
27
|
-
/** Mode */
|
|
28
|
-
mode?: 'template' | 'code-editor';
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Options for generating agents with AgentBuilder
|
|
33
|
-
*/
|
|
34
|
-
export interface GenerateAgentOptions {
|
|
35
|
-
/** Runtime context for the generation */
|
|
36
|
-
runtimeContext?: any;
|
|
37
|
-
/** Output format preference */
|
|
38
|
-
outputFormat?: 'code' | 'explanation' | 'both';
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Project management action types
|
|
43
|
-
*/
|
|
44
|
-
export type ProjectAction = 'create' | 'install' | 'upgrade' | 'check';
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Project types that can be created
|
|
48
|
-
*/
|
|
49
|
-
export type ProjectType = 'standalone' | 'api' | 'nextjs';
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Package manager options
|
|
53
|
-
*/
|
|
54
|
-
export type PackageManager = 'npm' | 'pnpm' | 'yarn';
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Validation types for code validation
|
|
58
|
-
*/
|
|
59
|
-
export type ValidationType = 'types' | 'schemas' | 'tests' | 'integration';
|
|
60
|
-
|
|
61
|
-
// Processing order for units (lower index = higher priority)
|
|
62
|
-
export const UNIT_KINDS = ['mcp-server', 'tool', 'workflow', 'agent', 'integration', 'network', 'other'] as const;
|
|
63
|
-
|
|
64
|
-
// Types for the merge template workflow
|
|
65
|
-
export type UnitKind = (typeof UNIT_KINDS)[number];
|
|
66
|
-
|
|
67
|
-
export interface TemplateUnit {
|
|
68
|
-
kind: UnitKind;
|
|
69
|
-
id: string;
|
|
70
|
-
file: string;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export interface TemplateManifest {
|
|
74
|
-
slug: string;
|
|
75
|
-
ref?: string;
|
|
76
|
-
description?: string;
|
|
77
|
-
units: TemplateUnit[];
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export interface MergePlan {
|
|
81
|
-
slug: string;
|
|
82
|
-
commitSha: string;
|
|
83
|
-
templateDir: string;
|
|
84
|
-
units: TemplateUnit[];
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Schema definitions
|
|
88
|
-
export const TemplateUnitSchema = z.object({
|
|
89
|
-
kind: z.enum(UNIT_KINDS),
|
|
90
|
-
id: z.string(),
|
|
91
|
-
file: z.string(),
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
export const TemplateManifestSchema = z.object({
|
|
95
|
-
slug: z.string(),
|
|
96
|
-
ref: z.string().optional(),
|
|
97
|
-
description: z.string().optional(),
|
|
98
|
-
units: z.array(TemplateUnitSchema),
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
export const MergeInputSchema = z.object({
|
|
102
|
-
repo: z.string().describe('Git URL or local path of the template repo'),
|
|
103
|
-
ref: z.string().optional().describe('Tag/branch/commit to checkout (defaults to main/master)'),
|
|
104
|
-
slug: z.string().optional().describe('Slug for branch/scripts; defaults to inferred from repo'),
|
|
105
|
-
targetPath: z.string().optional().describe('Project path to merge into; defaults to current directory'),
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
export const MergePlanSchema = z.object({
|
|
109
|
-
slug: z.string(),
|
|
110
|
-
commitSha: z.string(),
|
|
111
|
-
templateDir: z.string(),
|
|
112
|
-
units: z.array(TemplateUnitSchema),
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
export const ApplyResultSchema = z.object({
|
|
116
|
-
success: z.boolean(),
|
|
117
|
-
applied: z.boolean(),
|
|
118
|
-
branchName: z.string().optional(),
|
|
119
|
-
error: z.string().optional(),
|
|
120
|
-
});
|
package/src/utils.ts
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { exec as execNodejs, spawn as nodeSpawn } from 'child_process';
|
|
2
|
-
import { existsSync } from 'fs';
|
|
3
|
-
import { copyFile } from 'fs/promises';
|
|
4
|
-
import { createRequire } from 'module';
|
|
5
|
-
import { dirname, basename, extname, resolve } from 'path';
|
|
6
|
-
import { promisify } from 'util';
|
|
7
|
-
import { UNIT_KINDS } from './types';
|
|
8
|
-
import type { UnitKind } from './types';
|
|
9
|
-
|
|
10
|
-
export const exec = promisify(execNodejs);
|
|
11
|
-
|
|
12
|
-
export function spawn(command: string, args: string[], options: any) {
|
|
13
|
-
return new Promise((resolve, reject) => {
|
|
14
|
-
const childProcess = nodeSpawn(command, args, {
|
|
15
|
-
// stdio: 'inherit',
|
|
16
|
-
...options,
|
|
17
|
-
});
|
|
18
|
-
childProcess.on('error', error => {
|
|
19
|
-
reject(error);
|
|
20
|
-
});
|
|
21
|
-
let stderr = '';
|
|
22
|
-
childProcess.stderr?.on('data', message => {
|
|
23
|
-
stderr += message;
|
|
24
|
-
});
|
|
25
|
-
childProcess.on('close', code => {
|
|
26
|
-
if (code === 0) {
|
|
27
|
-
resolve(void 0);
|
|
28
|
-
} else {
|
|
29
|
-
reject(new Error(stderr));
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export async function spawnSWPM(cwd: string, command: string, packageNames: string[]) {
|
|
36
|
-
await spawn(createRequire(import.meta.filename).resolve('swpm'), [command, ...packageNames], {
|
|
37
|
-
cwd,
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Utility functions
|
|
42
|
-
export function kindWeight(kind: UnitKind): number {
|
|
43
|
-
const idx = UNIT_KINDS.indexOf(kind as any);
|
|
44
|
-
return idx === -1 ? UNIT_KINDS.length : idx;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Utility functions to work with Mastra templates
|
|
48
|
-
export async function fetchMastraTemplates(): Promise<
|
|
49
|
-
Array<{
|
|
50
|
-
slug: string;
|
|
51
|
-
title: string;
|
|
52
|
-
description: string;
|
|
53
|
-
githubUrl: string;
|
|
54
|
-
tags: string[];
|
|
55
|
-
agents: string[];
|
|
56
|
-
workflows: string[];
|
|
57
|
-
tools: string[];
|
|
58
|
-
}>
|
|
59
|
-
> {
|
|
60
|
-
try {
|
|
61
|
-
const response = await fetch('https://mastra.ai/api/templates.json');
|
|
62
|
-
const data = (await response.json()) as Array<{
|
|
63
|
-
slug: string;
|
|
64
|
-
title: string;
|
|
65
|
-
description: string;
|
|
66
|
-
githubUrl: string;
|
|
67
|
-
tags: string[];
|
|
68
|
-
agents: string[];
|
|
69
|
-
workflows: string[];
|
|
70
|
-
tools: string[];
|
|
71
|
-
}>;
|
|
72
|
-
return data;
|
|
73
|
-
} catch (error) {
|
|
74
|
-
throw new Error(`Failed to fetch Mastra templates: ${error instanceof Error ? error.message : String(error)}`);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Helper to get a specific template by slug
|
|
79
|
-
export async function getMastraTemplate(slug: string) {
|
|
80
|
-
const templates = await fetchMastraTemplates();
|
|
81
|
-
const template = templates.find(t => t.slug === slug);
|
|
82
|
-
if (!template) {
|
|
83
|
-
throw new Error(`Template "${slug}" not found. Available templates: ${templates.map(t => t.slug).join(', ')}`);
|
|
84
|
-
}
|
|
85
|
-
return template;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Git commit tracking utility
|
|
89
|
-
export async function logGitState(targetPath: string, label: string): Promise<void> {
|
|
90
|
-
try {
|
|
91
|
-
const gitStatusResult = await exec('git status --porcelain', { cwd: targetPath });
|
|
92
|
-
const gitLogResult = await exec('git log --oneline -3', { cwd: targetPath });
|
|
93
|
-
const gitCountResult = await exec('git rev-list --count HEAD', { cwd: targetPath });
|
|
94
|
-
|
|
95
|
-
console.log(`📊 Git state ${label}:`);
|
|
96
|
-
console.log('Status:', gitStatusResult.stdout.trim() || 'Clean working directory');
|
|
97
|
-
console.log('Recent commits:', gitLogResult.stdout.trim());
|
|
98
|
-
console.log('Total commits:', gitCountResult.stdout.trim());
|
|
99
|
-
} catch (gitError) {
|
|
100
|
-
console.warn(`Could not get git state ${label}:`, gitError);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// File conflict resolution utilities (for future use)
|
|
105
|
-
export async function backupAndReplaceFile(sourceFile: string, targetFile: string): Promise<void> {
|
|
106
|
-
// Create backup of existing file
|
|
107
|
-
const backupFile = `${targetFile}.backup-${Date.now()}`;
|
|
108
|
-
await copyFile(targetFile, backupFile);
|
|
109
|
-
console.log(`📦 Created backup: ${basename(backupFile)}`);
|
|
110
|
-
|
|
111
|
-
// Replace with template file
|
|
112
|
-
await copyFile(sourceFile, targetFile);
|
|
113
|
-
console.log(`🔄 Replaced file with template version (backup created)`);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export async function renameAndCopyFile(sourceFile: string, targetFile: string): Promise<string> {
|
|
117
|
-
// Find unique filename
|
|
118
|
-
let counter = 1;
|
|
119
|
-
let uniqueTargetFile = targetFile;
|
|
120
|
-
const baseName = basename(targetFile, extname(targetFile));
|
|
121
|
-
const extension = extname(targetFile);
|
|
122
|
-
const directory = dirname(targetFile);
|
|
123
|
-
|
|
124
|
-
while (existsSync(uniqueTargetFile)) {
|
|
125
|
-
const uniqueName = `${baseName}.template-${counter}${extension}`;
|
|
126
|
-
uniqueTargetFile = resolve(directory, uniqueName);
|
|
127
|
-
counter++;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
await copyFile(sourceFile, uniqueTargetFile);
|
|
131
|
-
console.log(`📝 Copied with unique name: ${basename(uniqueTargetFile)}`);
|
|
132
|
-
return uniqueTargetFile;
|
|
133
|
-
}
|