@agentforge-ai/core 0.1.0
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/README.md +70 -0
- package/dist/agent.d.ts +93 -0
- package/dist/agent.js +48 -0
- package/dist/agent.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +212 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-server.d.ts +96 -0
- package/dist/mcp-server.js +89 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/sandbox.d.ts +85 -0
- package/dist/sandbox.js +79 -0
- package/dist/sandbox.js.map +1 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# @agentforge-ai/core
|
|
2
|
+
|
|
3
|
+
Core agent primitives, secure sandbox execution, and MCP server for the AgentForge framework.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @agentforge-ai/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { Agent, SandboxManager, MCPServer } from '@agentforge-ai/core';
|
|
15
|
+
|
|
16
|
+
// Create an agent
|
|
17
|
+
const agent = new Agent({
|
|
18
|
+
id: 'my-agent',
|
|
19
|
+
name: 'My Agent',
|
|
20
|
+
instructions: 'You are a helpful assistant.',
|
|
21
|
+
model: 'openai/gpt-4o-mini',
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Generate a response
|
|
25
|
+
const response = await agent.generate('Hello, world!');
|
|
26
|
+
|
|
27
|
+
// Execute code securely
|
|
28
|
+
const sandbox = new SandboxManager({ timeout: 10000 });
|
|
29
|
+
const result = await sandbox.runCode('console.log("Hello from sandbox!")');
|
|
30
|
+
|
|
31
|
+
// Register tools with MCP
|
|
32
|
+
const mcp = new MCPServer();
|
|
33
|
+
mcp.registerTool({
|
|
34
|
+
name: 'calculator',
|
|
35
|
+
inputSchema: z.object({ expression: z.string() }),
|
|
36
|
+
outputSchema: z.string(),
|
|
37
|
+
handler: async ({ expression }) => eval(expression).toString(),
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## API Reference
|
|
42
|
+
|
|
43
|
+
### Agent
|
|
44
|
+
|
|
45
|
+
The core agent class wrapping Mastra for AI orchestration.
|
|
46
|
+
|
|
47
|
+
- `new Agent(config)` - Create a new agent
|
|
48
|
+
- `agent.generate(prompt)` - Generate a response
|
|
49
|
+
- `agent.stream(prompt)` - Stream a response
|
|
50
|
+
|
|
51
|
+
### SandboxManager
|
|
52
|
+
|
|
53
|
+
Secure code execution via E2B sandboxes.
|
|
54
|
+
|
|
55
|
+
- `new SandboxManager(config)` - Create a sandbox manager
|
|
56
|
+
- `manager.runCode(code, options)` - Execute code securely
|
|
57
|
+
- `manager.cleanup()` - Clean up resources
|
|
58
|
+
|
|
59
|
+
### MCPServer
|
|
60
|
+
|
|
61
|
+
Model Context Protocol server for tool communication.
|
|
62
|
+
|
|
63
|
+
- `new MCPServer()` - Create an MCP server
|
|
64
|
+
- `server.registerTool(tool)` - Register a tool
|
|
65
|
+
- `server.listTools()` - List all tools
|
|
66
|
+
- `server.callTool(name, input)` - Call a tool
|
|
67
|
+
|
|
68
|
+
## License
|
|
69
|
+
|
|
70
|
+
Apache-2.0
|
package/dist/agent.d.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { LanguageModelV1 } from 'ai';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for creating an AgentForge Agent.
|
|
5
|
+
*/
|
|
6
|
+
interface AgentConfig {
|
|
7
|
+
/** A unique identifier for the agent. */
|
|
8
|
+
id: string;
|
|
9
|
+
/** A human-readable name for the agent. */
|
|
10
|
+
name: string;
|
|
11
|
+
/** The system prompt or instructions for the agent. */
|
|
12
|
+
instructions: string;
|
|
13
|
+
/**
|
|
14
|
+
* The language model to use. Pass a LanguageModelV1 instance
|
|
15
|
+
* (e.g., from `@ai-sdk/openai`, `@ai-sdk/anthropic`, etc.).
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* import { openai } from '@ai-sdk/openai';
|
|
20
|
+
* const agent = new Agent({
|
|
21
|
+
* model: openai('gpt-4o-mini'),
|
|
22
|
+
* // ...
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
model: LanguageModelV1;
|
|
27
|
+
/** A dictionary of tools available to the agent. */
|
|
28
|
+
tools?: Record<string, unknown>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Represents a structured response from an agent generation call.
|
|
32
|
+
*/
|
|
33
|
+
interface AgentResponse {
|
|
34
|
+
/** The text content of the response. */
|
|
35
|
+
text: string;
|
|
36
|
+
/** Optional tool call results. */
|
|
37
|
+
toolResults?: unknown[];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Represents a single chunk in a streaming response.
|
|
41
|
+
*/
|
|
42
|
+
interface StreamChunk {
|
|
43
|
+
/** The text content of this chunk. */
|
|
44
|
+
content: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The core Agent class for the AgentForge framework.
|
|
48
|
+
*
|
|
49
|
+
* Wraps the Mastra Agent to provide a simplified, curated API for
|
|
50
|
+
* creating and interacting with AI agents. Supports any AI SDK-compatible
|
|
51
|
+
* model provider (OpenAI, Anthropic, Google, etc.) via BYOK (Bring Your Own Key).
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* import { openai } from '@ai-sdk/openai';
|
|
56
|
+
*
|
|
57
|
+
* const agent = new Agent({
|
|
58
|
+
* id: 'my-agent',
|
|
59
|
+
* name: 'My Agent',
|
|
60
|
+
* instructions: 'You are a helpful assistant.',
|
|
61
|
+
* model: openai('gpt-4o-mini'),
|
|
62
|
+
* });
|
|
63
|
+
*
|
|
64
|
+
* const response = await agent.generate('Hello!');
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
declare class Agent {
|
|
68
|
+
/** The agent's unique ID. */
|
|
69
|
+
readonly id: string;
|
|
70
|
+
/** The agent's human-readable name. */
|
|
71
|
+
readonly name: string;
|
|
72
|
+
/** The underlying Mastra agent instance. */
|
|
73
|
+
private mastraAgent;
|
|
74
|
+
/**
|
|
75
|
+
* Creates a new AgentForge Agent.
|
|
76
|
+
* @param config - The configuration for the agent.
|
|
77
|
+
*/
|
|
78
|
+
constructor(config: AgentConfig);
|
|
79
|
+
/**
|
|
80
|
+
* Generates a structured response from the agent.
|
|
81
|
+
* @param prompt - The user's prompt or input.
|
|
82
|
+
* @returns A promise that resolves to the agent's response.
|
|
83
|
+
*/
|
|
84
|
+
generate(prompt: string): Promise<AgentResponse>;
|
|
85
|
+
/**
|
|
86
|
+
* Generates a streaming response from the agent.
|
|
87
|
+
* @param prompt - The user's prompt or input.
|
|
88
|
+
* @returns An async iterable that yields response chunks.
|
|
89
|
+
*/
|
|
90
|
+
stream(prompt: string): AsyncGenerator<StreamChunk>;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export { Agent, type AgentConfig, type AgentResponse, type StreamChunk };
|
package/dist/agent.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// src/agent.ts
|
|
2
|
+
import { Agent as MastraAgent } from "@mastra/core/agent";
|
|
3
|
+
var Agent = class {
|
|
4
|
+
/** The agent's unique ID. */
|
|
5
|
+
id;
|
|
6
|
+
/** The agent's human-readable name. */
|
|
7
|
+
name;
|
|
8
|
+
/** The underlying Mastra agent instance. */
|
|
9
|
+
mastraAgent;
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new AgentForge Agent.
|
|
12
|
+
* @param config - The configuration for the agent.
|
|
13
|
+
*/
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.id = config.id;
|
|
16
|
+
this.name = config.name;
|
|
17
|
+
this.mastraAgent = new MastraAgent({
|
|
18
|
+
name: config.name,
|
|
19
|
+
instructions: config.instructions,
|
|
20
|
+
model: config.model,
|
|
21
|
+
...config.tools ? { tools: config.tools } : {}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Generates a structured response from the agent.
|
|
26
|
+
* @param prompt - The user's prompt or input.
|
|
27
|
+
* @returns A promise that resolves to the agent's response.
|
|
28
|
+
*/
|
|
29
|
+
async generate(prompt) {
|
|
30
|
+
const result = await this.mastraAgent.generate(prompt);
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Generates a streaming response from the agent.
|
|
35
|
+
* @param prompt - The user's prompt or input.
|
|
36
|
+
* @returns An async iterable that yields response chunks.
|
|
37
|
+
*/
|
|
38
|
+
async *stream(prompt) {
|
|
39
|
+
const result = await this.mastraAgent.stream(prompt);
|
|
40
|
+
for await (const chunk of result.textStream) {
|
|
41
|
+
yield { content: typeof chunk === "string" ? chunk : String(chunk) };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
export {
|
|
46
|
+
Agent
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/agent.ts"],"sourcesContent":["import { Agent as MastraAgent } from '@mastra/core/agent';\nimport type { LanguageModelV1 } from 'ai';\n\n/**\n * Configuration for creating an AgentForge Agent.\n */\nexport interface AgentConfig {\n /** A unique identifier for the agent. */\n id: string;\n /** A human-readable name for the agent. */\n name: string;\n /** The system prompt or instructions for the agent. */\n instructions: string;\n /**\n * The language model to use. Pass a LanguageModelV1 instance\n * (e.g., from `@ai-sdk/openai`, `@ai-sdk/anthropic`, etc.).\n *\n * @example\n * ```typescript\n * import { openai } from '@ai-sdk/openai';\n * const agent = new Agent({\n * model: openai('gpt-4o-mini'),\n * // ...\n * });\n * ```\n */\n model: LanguageModelV1;\n /** A dictionary of tools available to the agent. */\n tools?: Record<string, unknown>;\n}\n\n/**\n * Represents a structured response from an agent generation call.\n */\nexport interface AgentResponse {\n /** The text content of the response. */\n text: string;\n /** Optional tool call results. */\n toolResults?: unknown[];\n}\n\n/**\n * Represents a single chunk in a streaming response.\n */\nexport interface StreamChunk {\n /** The text content of this chunk. */\n content: string;\n}\n\n/**\n * The core Agent class for the AgentForge framework.\n *\n * Wraps the Mastra Agent to provide a simplified, curated API for\n * creating and interacting with AI agents. Supports any AI SDK-compatible\n * model provider (OpenAI, Anthropic, Google, etc.) via BYOK (Bring Your Own Key).\n *\n * @example\n * ```typescript\n * import { openai } from '@ai-sdk/openai';\n *\n * const agent = new Agent({\n * id: 'my-agent',\n * name: 'My Agent',\n * instructions: 'You are a helpful assistant.',\n * model: openai('gpt-4o-mini'),\n * });\n *\n * const response = await agent.generate('Hello!');\n * ```\n */\nexport class Agent {\n /** The agent's unique ID. */\n public readonly id: string;\n\n /** The agent's human-readable name. */\n public readonly name: string;\n\n /** The underlying Mastra agent instance. */\n private mastraAgent: MastraAgent;\n\n /**\n * Creates a new AgentForge Agent.\n * @param config - The configuration for the agent.\n */\n constructor(config: AgentConfig) {\n this.id = config.id;\n this.name = config.name;\n\n this.mastraAgent = new MastraAgent({\n name: config.name,\n instructions: config.instructions,\n model: config.model,\n ...(config.tools ? { tools: config.tools as Record<string, never> } : {}),\n });\n }\n\n /**\n * Generates a structured response from the agent.\n * @param prompt - The user's prompt or input.\n * @returns A promise that resolves to the agent's response.\n */\n async generate(prompt: string): Promise<AgentResponse> {\n const result = await this.mastraAgent.generate(prompt);\n return result as unknown as AgentResponse;\n }\n\n /**\n * Generates a streaming response from the agent.\n * @param prompt - The user's prompt or input.\n * @returns An async iterable that yields response chunks.\n */\n async *stream(prompt: string): AsyncGenerator<StreamChunk> {\n const result = await this.mastraAgent.stream(prompt);\n for await (const chunk of result.textStream) {\n yield { content: typeof chunk === 'string' ? chunk : String(chunk) };\n }\n }\n}\n"],"mappings":";AAAA,SAAS,SAAS,mBAAmB;AAsE9B,IAAM,QAAN,MAAY;AAAA;AAAA,EAED;AAAA;AAAA,EAGA;AAAA;AAAA,EAGR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMR,YAAY,QAAqB;AAC/B,SAAK,KAAK,OAAO;AACjB,SAAK,OAAO,OAAO;AAEnB,SAAK,cAAc,IAAI,YAAY;AAAA,MACjC,MAAM,OAAO;AAAA,MACb,cAAc,OAAO;AAAA,MACrB,OAAO,OAAO;AAAA,MACd,GAAI,OAAO,QAAQ,EAAE,OAAO,OAAO,MAA+B,IAAI,CAAC;AAAA,IACzE,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,SAAS,QAAwC;AACrD,UAAM,SAAS,MAAM,KAAK,YAAY,SAAS,MAAM;AACrD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,OAAO,QAA6C;AACzD,UAAM,SAAS,MAAM,KAAK,YAAY,OAAO,MAAM;AACnD,qBAAiB,SAAS,OAAO,YAAY;AAC3C,YAAM,EAAE,SAAS,OAAO,UAAU,WAAW,QAAQ,OAAO,KAAK,EAAE;AAAA,IACrE;AAAA,EACF;AACF;","names":[]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { Agent, AgentConfig, AgentResponse, StreamChunk } from './agent.js';
|
|
2
|
+
export { SandboxConfig, SandboxExecutionError, SandboxManager, SandboxResult, SandboxRunOptions, TimeoutError } from './sandbox.js';
|
|
3
|
+
export { MCPServer, Tool, ToolSchema } from './mcp-server.js';
|
|
4
|
+
import 'ai';
|
|
5
|
+
import 'zod';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
// src/agent.ts
|
|
2
|
+
import { Agent as MastraAgent } from "@mastra/core/agent";
|
|
3
|
+
var Agent = class {
|
|
4
|
+
/** The agent's unique ID. */
|
|
5
|
+
id;
|
|
6
|
+
/** The agent's human-readable name. */
|
|
7
|
+
name;
|
|
8
|
+
/** The underlying Mastra agent instance. */
|
|
9
|
+
mastraAgent;
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new AgentForge Agent.
|
|
12
|
+
* @param config - The configuration for the agent.
|
|
13
|
+
*/
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.id = config.id;
|
|
16
|
+
this.name = config.name;
|
|
17
|
+
this.mastraAgent = new MastraAgent({
|
|
18
|
+
name: config.name,
|
|
19
|
+
instructions: config.instructions,
|
|
20
|
+
model: config.model,
|
|
21
|
+
...config.tools ? { tools: config.tools } : {}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Generates a structured response from the agent.
|
|
26
|
+
* @param prompt - The user's prompt or input.
|
|
27
|
+
* @returns A promise that resolves to the agent's response.
|
|
28
|
+
*/
|
|
29
|
+
async generate(prompt) {
|
|
30
|
+
const result = await this.mastraAgent.generate(prompt);
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Generates a streaming response from the agent.
|
|
35
|
+
* @param prompt - The user's prompt or input.
|
|
36
|
+
* @returns An async iterable that yields response chunks.
|
|
37
|
+
*/
|
|
38
|
+
async *stream(prompt) {
|
|
39
|
+
const result = await this.mastraAgent.stream(prompt);
|
|
40
|
+
for await (const chunk of result.textStream) {
|
|
41
|
+
yield { content: typeof chunk === "string" ? chunk : String(chunk) };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// src/sandbox.ts
|
|
47
|
+
import { Sandbox } from "@e2b/code-interpreter";
|
|
48
|
+
var TimeoutError = class extends Error {
|
|
49
|
+
constructor(message) {
|
|
50
|
+
super(message);
|
|
51
|
+
this.name = "TimeoutError";
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
var SandboxExecutionError = class extends Error {
|
|
55
|
+
/** The name of the execution error (e.g., 'SyntaxError'). */
|
|
56
|
+
errorName;
|
|
57
|
+
/** The raw traceback from the sandbox. */
|
|
58
|
+
traceback;
|
|
59
|
+
constructor(name, value, traceback) {
|
|
60
|
+
super(`${name}: ${value}`);
|
|
61
|
+
this.name = "SandboxExecutionError";
|
|
62
|
+
this.errorName = name;
|
|
63
|
+
this.traceback = traceback;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
var SandboxManager = class {
|
|
67
|
+
sandbox = null;
|
|
68
|
+
defaultTimeout;
|
|
69
|
+
/**
|
|
70
|
+
* Creates a new SandboxManager.
|
|
71
|
+
* @param config - The configuration for the sandbox manager.
|
|
72
|
+
*/
|
|
73
|
+
constructor(config = {}) {
|
|
74
|
+
this.defaultTimeout = config.timeout ?? 3e4;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Executes a snippet of code within a secure E2B sandbox.
|
|
78
|
+
*
|
|
79
|
+
* @param code - The code to execute.
|
|
80
|
+
* @param options - Options for this specific run.
|
|
81
|
+
* @returns A promise that resolves to the result of the code execution.
|
|
82
|
+
* @throws {SandboxExecutionError} If the code throws an error.
|
|
83
|
+
*/
|
|
84
|
+
async runCode(code, options) {
|
|
85
|
+
const timeoutMs = options?.timeout ?? this.defaultTimeout;
|
|
86
|
+
try {
|
|
87
|
+
this.sandbox = await Sandbox.create();
|
|
88
|
+
const execution = await this.sandbox.runCode(code, { timeoutMs });
|
|
89
|
+
if (execution.error) {
|
|
90
|
+
throw new SandboxExecutionError(
|
|
91
|
+
execution.error.name,
|
|
92
|
+
execution.error.value,
|
|
93
|
+
execution.error.traceback
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
output: execution.results,
|
|
98
|
+
stdout: execution.logs.stdout,
|
|
99
|
+
stderr: execution.logs.stderr
|
|
100
|
+
};
|
|
101
|
+
} finally {
|
|
102
|
+
if (this.sandbox) {
|
|
103
|
+
await this.sandbox.kill();
|
|
104
|
+
this.sandbox = null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Terminates the sandbox and releases all associated resources.
|
|
110
|
+
* @returns A promise that resolves when the cleanup is complete.
|
|
111
|
+
*/
|
|
112
|
+
async cleanup() {
|
|
113
|
+
if (this.sandbox) {
|
|
114
|
+
await this.sandbox.kill();
|
|
115
|
+
this.sandbox = null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// src/mcp-server.ts
|
|
121
|
+
import { z } from "zod";
|
|
122
|
+
var MCPServer = class {
|
|
123
|
+
tools = /* @__PURE__ */ new Map();
|
|
124
|
+
/**
|
|
125
|
+
* Registers a new tool with the MCP server.
|
|
126
|
+
*
|
|
127
|
+
* @param tool - The tool definition to register.
|
|
128
|
+
* @throws {Error} If a tool with the same name is already registered.
|
|
129
|
+
*/
|
|
130
|
+
registerTool(tool) {
|
|
131
|
+
if (this.tools.has(tool.name)) {
|
|
132
|
+
throw new Error(`Tool with name '${tool.name}' is already registered.`);
|
|
133
|
+
}
|
|
134
|
+
this.tools.set(tool.name, tool);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Retrieves a list of all registered tools and their schemas.
|
|
138
|
+
*
|
|
139
|
+
* @returns An array of tool schema descriptors.
|
|
140
|
+
*/
|
|
141
|
+
listTools() {
|
|
142
|
+
return Array.from(this.tools.values()).map((tool) => ({
|
|
143
|
+
name: tool.name,
|
|
144
|
+
description: tool.description,
|
|
145
|
+
inputSchema: this.zodToJsonSchema(tool.inputSchema),
|
|
146
|
+
outputSchema: this.zodToJsonSchema(tool.outputSchema)
|
|
147
|
+
}));
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Invokes a specified tool with the provided input.
|
|
151
|
+
*
|
|
152
|
+
* @param toolName - The name of the tool to invoke.
|
|
153
|
+
* @param input - The input to the tool (will be validated against the schema).
|
|
154
|
+
* @returns A promise that resolves with the validated result.
|
|
155
|
+
* @throws {Error} If the tool is not found or input/output validation fails.
|
|
156
|
+
*/
|
|
157
|
+
async callTool(toolName, input) {
|
|
158
|
+
const tool = this.tools.get(toolName);
|
|
159
|
+
if (!tool) {
|
|
160
|
+
throw new Error(`Tool with name '${toolName}' not found.`);
|
|
161
|
+
}
|
|
162
|
+
const parsedInput = tool.inputSchema.safeParse(input);
|
|
163
|
+
if (!parsedInput.success) {
|
|
164
|
+
throw new Error(
|
|
165
|
+
`Invalid input for tool '${toolName}': ${parsedInput.error.message}`
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
const result = await tool.handler(parsedInput.data);
|
|
169
|
+
const parsedOutput = tool.outputSchema.safeParse(result);
|
|
170
|
+
if (!parsedOutput.success) {
|
|
171
|
+
throw new Error(
|
|
172
|
+
`Invalid output from tool '${toolName}': ${parsedOutput.error.message}`
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
return parsedOutput.data;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Converts a Zod schema to a simplified JSON Schema representation.
|
|
179
|
+
* @param schema - The Zod schema to convert.
|
|
180
|
+
* @returns A simplified JSON Schema object.
|
|
181
|
+
*/
|
|
182
|
+
zodToJsonSchema(schema) {
|
|
183
|
+
if (schema instanceof z.ZodObject) {
|
|
184
|
+
const shape = schema.shape;
|
|
185
|
+
const properties = {};
|
|
186
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
187
|
+
properties[key] = { type: this.getZodTypeName(value) };
|
|
188
|
+
}
|
|
189
|
+
return { type: "object", properties };
|
|
190
|
+
}
|
|
191
|
+
return { type: this.getZodTypeName(schema) };
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Gets the type name for a Zod schema.
|
|
195
|
+
*/
|
|
196
|
+
getZodTypeName(schema) {
|
|
197
|
+
if (schema instanceof z.ZodString) return "string";
|
|
198
|
+
if (schema instanceof z.ZodNumber) return "number";
|
|
199
|
+
if (schema instanceof z.ZodBoolean) return "boolean";
|
|
200
|
+
if (schema instanceof z.ZodArray) return "array";
|
|
201
|
+
if (schema instanceof z.ZodObject) return "object";
|
|
202
|
+
return "unknown";
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
export {
|
|
206
|
+
Agent,
|
|
207
|
+
MCPServer,
|
|
208
|
+
SandboxExecutionError,
|
|
209
|
+
SandboxManager,
|
|
210
|
+
TimeoutError
|
|
211
|
+
};
|
|
212
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/agent.ts","../src/sandbox.ts","../src/mcp-server.ts"],"sourcesContent":["import { Agent as MastraAgent } from '@mastra/core/agent';\nimport type { LanguageModelV1 } from 'ai';\n\n/**\n * Configuration for creating an AgentForge Agent.\n */\nexport interface AgentConfig {\n /** A unique identifier for the agent. */\n id: string;\n /** A human-readable name for the agent. */\n name: string;\n /** The system prompt or instructions for the agent. */\n instructions: string;\n /**\n * The language model to use. Pass a LanguageModelV1 instance\n * (e.g., from `@ai-sdk/openai`, `@ai-sdk/anthropic`, etc.).\n *\n * @example\n * ```typescript\n * import { openai } from '@ai-sdk/openai';\n * const agent = new Agent({\n * model: openai('gpt-4o-mini'),\n * // ...\n * });\n * ```\n */\n model: LanguageModelV1;\n /** A dictionary of tools available to the agent. */\n tools?: Record<string, unknown>;\n}\n\n/**\n * Represents a structured response from an agent generation call.\n */\nexport interface AgentResponse {\n /** The text content of the response. */\n text: string;\n /** Optional tool call results. */\n toolResults?: unknown[];\n}\n\n/**\n * Represents a single chunk in a streaming response.\n */\nexport interface StreamChunk {\n /** The text content of this chunk. */\n content: string;\n}\n\n/**\n * The core Agent class for the AgentForge framework.\n *\n * Wraps the Mastra Agent to provide a simplified, curated API for\n * creating and interacting with AI agents. Supports any AI SDK-compatible\n * model provider (OpenAI, Anthropic, Google, etc.) via BYOK (Bring Your Own Key).\n *\n * @example\n * ```typescript\n * import { openai } from '@ai-sdk/openai';\n *\n * const agent = new Agent({\n * id: 'my-agent',\n * name: 'My Agent',\n * instructions: 'You are a helpful assistant.',\n * model: openai('gpt-4o-mini'),\n * });\n *\n * const response = await agent.generate('Hello!');\n * ```\n */\nexport class Agent {\n /** The agent's unique ID. */\n public readonly id: string;\n\n /** The agent's human-readable name. */\n public readonly name: string;\n\n /** The underlying Mastra agent instance. */\n private mastraAgent: MastraAgent;\n\n /**\n * Creates a new AgentForge Agent.\n * @param config - The configuration for the agent.\n */\n constructor(config: AgentConfig) {\n this.id = config.id;\n this.name = config.name;\n\n this.mastraAgent = new MastraAgent({\n name: config.name,\n instructions: config.instructions,\n model: config.model,\n ...(config.tools ? { tools: config.tools as Record<string, never> } : {}),\n });\n }\n\n /**\n * Generates a structured response from the agent.\n * @param prompt - The user's prompt or input.\n * @returns A promise that resolves to the agent's response.\n */\n async generate(prompt: string): Promise<AgentResponse> {\n const result = await this.mastraAgent.generate(prompt);\n return result as unknown as AgentResponse;\n }\n\n /**\n * Generates a streaming response from the agent.\n * @param prompt - The user's prompt or input.\n * @returns An async iterable that yields response chunks.\n */\n async *stream(prompt: string): AsyncGenerator<StreamChunk> {\n const result = await this.mastraAgent.stream(prompt);\n for await (const chunk of result.textStream) {\n yield { content: typeof chunk === 'string' ? chunk : String(chunk) };\n }\n }\n}\n","import { Sandbox } from '@e2b/code-interpreter';\n\n/**\n * Configuration for the SandboxManager.\n */\nexport interface SandboxConfig {\n /**\n * The default execution timeout in milliseconds.\n * @default 30000\n */\n timeout?: number;\n}\n\n/**\n * Options for a specific sandbox run.\n */\nexport interface SandboxRunOptions {\n /**\n * The execution timeout in milliseconds for this specific run.\n */\n timeout?: number;\n}\n\n/**\n * Represents the result of a sandbox code execution.\n */\nexport interface SandboxResult {\n /** The output/results from the code execution. */\n output: unknown;\n /** Stdout logs produced during execution. */\n stdout?: string[];\n /** Stderr logs produced during execution. */\n stderr?: string[];\n}\n\n/**\n * A custom error class for sandbox timeouts.\n */\nexport class TimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'TimeoutError';\n }\n}\n\n/**\n * A custom error class for sandbox execution errors.\n */\nexport class SandboxExecutionError extends Error {\n /** The name of the execution error (e.g., 'SyntaxError'). */\n public readonly errorName: string;\n /** The raw traceback from the sandbox. */\n public readonly traceback: string;\n\n constructor(name: string, value: string, traceback: string) {\n super(`${name}: ${value}`);\n this.name = 'SandboxExecutionError';\n this.errorName = name;\n this.traceback = traceback;\n }\n}\n\n/**\n * Manages the lifecycle of E2B sandboxes for secure code execution.\n *\n * All tool code execution in AgentForge MUST occur within an E2B sandbox\n * to ensure security isolation and prevent malicious code from affecting\n * the host system.\n *\n * @example\n * ```typescript\n * const manager = new SandboxManager({ timeout: 10000 });\n * const result = await manager.runCode('1 + 1');\n * console.log(result); // { output: [...], stdout: [], stderr: [] }\n * ```\n */\nexport class SandboxManager {\n private sandbox: Sandbox | null = null;\n private defaultTimeout: number;\n\n /**\n * Creates a new SandboxManager.\n * @param config - The configuration for the sandbox manager.\n */\n constructor(config: SandboxConfig = {}) {\n this.defaultTimeout = config.timeout ?? 30000;\n }\n\n /**\n * Executes a snippet of code within a secure E2B sandbox.\n *\n * @param code - The code to execute.\n * @param options - Options for this specific run.\n * @returns A promise that resolves to the result of the code execution.\n * @throws {SandboxExecutionError} If the code throws an error.\n */\n async runCode(code: string, options?: SandboxRunOptions): Promise<SandboxResult> {\n const timeoutMs = options?.timeout ?? this.defaultTimeout;\n\n try {\n this.sandbox = await Sandbox.create();\n const execution = await this.sandbox.runCode(code, { timeoutMs });\n\n if (execution.error) {\n throw new SandboxExecutionError(\n execution.error.name,\n execution.error.value,\n execution.error.traceback,\n );\n }\n\n return {\n output: execution.results,\n stdout: execution.logs.stdout,\n stderr: execution.logs.stderr,\n };\n } finally {\n if (this.sandbox) {\n await this.sandbox.kill();\n this.sandbox = null;\n }\n }\n }\n\n /**\n * Terminates the sandbox and releases all associated resources.\n * @returns A promise that resolves when the cleanup is complete.\n */\n async cleanup(): Promise<void> {\n if (this.sandbox) {\n await this.sandbox.kill();\n this.sandbox = null;\n }\n }\n}\n","import { z } from 'zod';\n\n/**\n * Schema descriptor for tool listing.\n */\nexport interface ToolSchema {\n /** The unique name of the tool. */\n name: string;\n /** A human-readable description of the tool. */\n description?: string;\n /** JSON Schema representation of the input. */\n inputSchema: Record<string, unknown>;\n /** JSON Schema representation of the output. */\n outputSchema: Record<string, unknown>;\n}\n\n/**\n * Represents a tool that can be registered and executed by the MCP server.\n *\n * @typeParam TInput - The Zod schema type for the tool's input.\n * @typeParam TOutput - The Zod schema type for the tool's output.\n */\nexport interface Tool<\n TInput extends z.ZodTypeAny = z.ZodTypeAny,\n TOutput extends z.ZodTypeAny = z.ZodTypeAny,\n> {\n /** The unique name of the tool. */\n name: string;\n /** A human-readable description of the tool. */\n description?: string;\n /** The Zod schema for the tool's input. */\n inputSchema: TInput;\n /** The Zod schema for the tool's output. */\n outputSchema: TOutput;\n /**\n * The function that implements the tool's logic.\n * @param input - The validated input matching the input schema.\n * @returns A promise that resolves with the tool's output.\n */\n handler: (input: z.infer<TInput>) => Promise<z.infer<TOutput>>;\n}\n\n/**\n * A server that implements the Model Context Protocol (MCP) for tool communication.\n *\n * Provides a central registry for tools that agents can discover and invoke.\n * All tool inputs and outputs are validated against their Zod schemas.\n *\n * @example\n * ```typescript\n * const server = new MCPServer();\n *\n * server.registerTool({\n * name: 'add',\n * description: 'Adds two numbers',\n * inputSchema: z.object({ a: z.number(), b: z.number() }),\n * outputSchema: z.number(),\n * handler: async ({ a, b }) => a + b,\n * });\n *\n * const result = await server.callTool('add', { a: 5, b: 3 });\n * // result === 8\n * ```\n */\nexport class MCPServer {\n private tools: Map<string, Tool> = new Map();\n\n /**\n * Registers a new tool with the MCP server.\n *\n * @param tool - The tool definition to register.\n * @throws {Error} If a tool with the same name is already registered.\n */\n public registerTool<\n TInput extends z.ZodTypeAny,\n TOutput extends z.ZodTypeAny,\n >(tool: Tool<TInput, TOutput>): void {\n if (this.tools.has(tool.name)) {\n throw new Error(`Tool with name '${tool.name}' is already registered.`);\n }\n this.tools.set(tool.name, tool as unknown as Tool);\n }\n\n /**\n * Retrieves a list of all registered tools and their schemas.\n *\n * @returns An array of tool schema descriptors.\n */\n public listTools(): ToolSchema[] {\n return Array.from(this.tools.values()).map((tool) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: this.zodToJsonSchema(tool.inputSchema),\n outputSchema: this.zodToJsonSchema(tool.outputSchema),\n }));\n }\n\n /**\n * Invokes a specified tool with the provided input.\n *\n * @param toolName - The name of the tool to invoke.\n * @param input - The input to the tool (will be validated against the schema).\n * @returns A promise that resolves with the validated result.\n * @throws {Error} If the tool is not found or input/output validation fails.\n */\n public async callTool(toolName: string, input: unknown): Promise<unknown> {\n const tool = this.tools.get(toolName);\n if (!tool) {\n throw new Error(`Tool with name '${toolName}' not found.`);\n }\n\n const parsedInput = tool.inputSchema.safeParse(input);\n if (!parsedInput.success) {\n throw new Error(\n `Invalid input for tool '${toolName}': ${parsedInput.error.message}`\n );\n }\n\n const result = await tool.handler(parsedInput.data);\n\n const parsedOutput = tool.outputSchema.safeParse(result);\n if (!parsedOutput.success) {\n throw new Error(\n `Invalid output from tool '${toolName}': ${parsedOutput.error.message}`\n );\n }\n\n return parsedOutput.data;\n }\n\n /**\n * Converts a Zod schema to a simplified JSON Schema representation.\n * @param schema - The Zod schema to convert.\n * @returns A simplified JSON Schema object.\n */\n private zodToJsonSchema(schema: z.ZodTypeAny): Record<string, unknown> {\n // Simple conversion - in production, use zod-to-json-schema\n if (schema instanceof z.ZodObject) {\n const shape = schema.shape;\n const properties: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(shape)) {\n properties[key] = { type: this.getZodTypeName(value as z.ZodTypeAny) };\n }\n return { type: 'object', properties };\n }\n return { type: this.getZodTypeName(schema) };\n }\n\n /**\n * Gets the type name for a Zod schema.\n */\n private getZodTypeName(schema: z.ZodTypeAny): string {\n if (schema instanceof z.ZodString) return 'string';\n if (schema instanceof z.ZodNumber) return 'number';\n if (schema instanceof z.ZodBoolean) return 'boolean';\n if (schema instanceof z.ZodArray) return 'array';\n if (schema instanceof z.ZodObject) return 'object';\n return 'unknown';\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Schema descriptor for tool listing.
|
|
5
|
+
*/
|
|
6
|
+
interface ToolSchema {
|
|
7
|
+
/** The unique name of the tool. */
|
|
8
|
+
name: string;
|
|
9
|
+
/** A human-readable description of the tool. */
|
|
10
|
+
description?: string;
|
|
11
|
+
/** JSON Schema representation of the input. */
|
|
12
|
+
inputSchema: Record<string, unknown>;
|
|
13
|
+
/** JSON Schema representation of the output. */
|
|
14
|
+
outputSchema: Record<string, unknown>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Represents a tool that can be registered and executed by the MCP server.
|
|
18
|
+
*
|
|
19
|
+
* @typeParam TInput - The Zod schema type for the tool's input.
|
|
20
|
+
* @typeParam TOutput - The Zod schema type for the tool's output.
|
|
21
|
+
*/
|
|
22
|
+
interface Tool<TInput extends z.ZodTypeAny = z.ZodTypeAny, TOutput extends z.ZodTypeAny = z.ZodTypeAny> {
|
|
23
|
+
/** The unique name of the tool. */
|
|
24
|
+
name: string;
|
|
25
|
+
/** A human-readable description of the tool. */
|
|
26
|
+
description?: string;
|
|
27
|
+
/** The Zod schema for the tool's input. */
|
|
28
|
+
inputSchema: TInput;
|
|
29
|
+
/** The Zod schema for the tool's output. */
|
|
30
|
+
outputSchema: TOutput;
|
|
31
|
+
/**
|
|
32
|
+
* The function that implements the tool's logic.
|
|
33
|
+
* @param input - The validated input matching the input schema.
|
|
34
|
+
* @returns A promise that resolves with the tool's output.
|
|
35
|
+
*/
|
|
36
|
+
handler: (input: z.infer<TInput>) => Promise<z.infer<TOutput>>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* A server that implements the Model Context Protocol (MCP) for tool communication.
|
|
40
|
+
*
|
|
41
|
+
* Provides a central registry for tools that agents can discover and invoke.
|
|
42
|
+
* All tool inputs and outputs are validated against their Zod schemas.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```typescript
|
|
46
|
+
* const server = new MCPServer();
|
|
47
|
+
*
|
|
48
|
+
* server.registerTool({
|
|
49
|
+
* name: 'add',
|
|
50
|
+
* description: 'Adds two numbers',
|
|
51
|
+
* inputSchema: z.object({ a: z.number(), b: z.number() }),
|
|
52
|
+
* outputSchema: z.number(),
|
|
53
|
+
* handler: async ({ a, b }) => a + b,
|
|
54
|
+
* });
|
|
55
|
+
*
|
|
56
|
+
* const result = await server.callTool('add', { a: 5, b: 3 });
|
|
57
|
+
* // result === 8
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
declare class MCPServer {
|
|
61
|
+
private tools;
|
|
62
|
+
/**
|
|
63
|
+
* Registers a new tool with the MCP server.
|
|
64
|
+
*
|
|
65
|
+
* @param tool - The tool definition to register.
|
|
66
|
+
* @throws {Error} If a tool with the same name is already registered.
|
|
67
|
+
*/
|
|
68
|
+
registerTool<TInput extends z.ZodTypeAny, TOutput extends z.ZodTypeAny>(tool: Tool<TInput, TOutput>): void;
|
|
69
|
+
/**
|
|
70
|
+
* Retrieves a list of all registered tools and their schemas.
|
|
71
|
+
*
|
|
72
|
+
* @returns An array of tool schema descriptors.
|
|
73
|
+
*/
|
|
74
|
+
listTools(): ToolSchema[];
|
|
75
|
+
/**
|
|
76
|
+
* Invokes a specified tool with the provided input.
|
|
77
|
+
*
|
|
78
|
+
* @param toolName - The name of the tool to invoke.
|
|
79
|
+
* @param input - The input to the tool (will be validated against the schema).
|
|
80
|
+
* @returns A promise that resolves with the validated result.
|
|
81
|
+
* @throws {Error} If the tool is not found or input/output validation fails.
|
|
82
|
+
*/
|
|
83
|
+
callTool(toolName: string, input: unknown): Promise<unknown>;
|
|
84
|
+
/**
|
|
85
|
+
* Converts a Zod schema to a simplified JSON Schema representation.
|
|
86
|
+
* @param schema - The Zod schema to convert.
|
|
87
|
+
* @returns A simplified JSON Schema object.
|
|
88
|
+
*/
|
|
89
|
+
private zodToJsonSchema;
|
|
90
|
+
/**
|
|
91
|
+
* Gets the type name for a Zod schema.
|
|
92
|
+
*/
|
|
93
|
+
private getZodTypeName;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export { MCPServer, type Tool, type ToolSchema };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// src/mcp-server.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var MCPServer = class {
|
|
4
|
+
tools = /* @__PURE__ */ new Map();
|
|
5
|
+
/**
|
|
6
|
+
* Registers a new tool with the MCP server.
|
|
7
|
+
*
|
|
8
|
+
* @param tool - The tool definition to register.
|
|
9
|
+
* @throws {Error} If a tool with the same name is already registered.
|
|
10
|
+
*/
|
|
11
|
+
registerTool(tool) {
|
|
12
|
+
if (this.tools.has(tool.name)) {
|
|
13
|
+
throw new Error(`Tool with name '${tool.name}' is already registered.`);
|
|
14
|
+
}
|
|
15
|
+
this.tools.set(tool.name, tool);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Retrieves a list of all registered tools and their schemas.
|
|
19
|
+
*
|
|
20
|
+
* @returns An array of tool schema descriptors.
|
|
21
|
+
*/
|
|
22
|
+
listTools() {
|
|
23
|
+
return Array.from(this.tools.values()).map((tool) => ({
|
|
24
|
+
name: tool.name,
|
|
25
|
+
description: tool.description,
|
|
26
|
+
inputSchema: this.zodToJsonSchema(tool.inputSchema),
|
|
27
|
+
outputSchema: this.zodToJsonSchema(tool.outputSchema)
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Invokes a specified tool with the provided input.
|
|
32
|
+
*
|
|
33
|
+
* @param toolName - The name of the tool to invoke.
|
|
34
|
+
* @param input - The input to the tool (will be validated against the schema).
|
|
35
|
+
* @returns A promise that resolves with the validated result.
|
|
36
|
+
* @throws {Error} If the tool is not found or input/output validation fails.
|
|
37
|
+
*/
|
|
38
|
+
async callTool(toolName, input) {
|
|
39
|
+
const tool = this.tools.get(toolName);
|
|
40
|
+
if (!tool) {
|
|
41
|
+
throw new Error(`Tool with name '${toolName}' not found.`);
|
|
42
|
+
}
|
|
43
|
+
const parsedInput = tool.inputSchema.safeParse(input);
|
|
44
|
+
if (!parsedInput.success) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
`Invalid input for tool '${toolName}': ${parsedInput.error.message}`
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
const result = await tool.handler(parsedInput.data);
|
|
50
|
+
const parsedOutput = tool.outputSchema.safeParse(result);
|
|
51
|
+
if (!parsedOutput.success) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
`Invalid output from tool '${toolName}': ${parsedOutput.error.message}`
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
return parsedOutput.data;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Converts a Zod schema to a simplified JSON Schema representation.
|
|
60
|
+
* @param schema - The Zod schema to convert.
|
|
61
|
+
* @returns A simplified JSON Schema object.
|
|
62
|
+
*/
|
|
63
|
+
zodToJsonSchema(schema) {
|
|
64
|
+
if (schema instanceof z.ZodObject) {
|
|
65
|
+
const shape = schema.shape;
|
|
66
|
+
const properties = {};
|
|
67
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
68
|
+
properties[key] = { type: this.getZodTypeName(value) };
|
|
69
|
+
}
|
|
70
|
+
return { type: "object", properties };
|
|
71
|
+
}
|
|
72
|
+
return { type: this.getZodTypeName(schema) };
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Gets the type name for a Zod schema.
|
|
76
|
+
*/
|
|
77
|
+
getZodTypeName(schema) {
|
|
78
|
+
if (schema instanceof z.ZodString) return "string";
|
|
79
|
+
if (schema instanceof z.ZodNumber) return "number";
|
|
80
|
+
if (schema instanceof z.ZodBoolean) return "boolean";
|
|
81
|
+
if (schema instanceof z.ZodArray) return "array";
|
|
82
|
+
if (schema instanceof z.ZodObject) return "object";
|
|
83
|
+
return "unknown";
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
export {
|
|
87
|
+
MCPServer
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=mcp-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mcp-server.ts"],"sourcesContent":["import { z } from 'zod';\n\n/**\n * Schema descriptor for tool listing.\n */\nexport interface ToolSchema {\n /** The unique name of the tool. */\n name: string;\n /** A human-readable description of the tool. */\n description?: string;\n /** JSON Schema representation of the input. */\n inputSchema: Record<string, unknown>;\n /** JSON Schema representation of the output. */\n outputSchema: Record<string, unknown>;\n}\n\n/**\n * Represents a tool that can be registered and executed by the MCP server.\n *\n * @typeParam TInput - The Zod schema type for the tool's input.\n * @typeParam TOutput - The Zod schema type for the tool's output.\n */\nexport interface Tool<\n TInput extends z.ZodTypeAny = z.ZodTypeAny,\n TOutput extends z.ZodTypeAny = z.ZodTypeAny,\n> {\n /** The unique name of the tool. */\n name: string;\n /** A human-readable description of the tool. */\n description?: string;\n /** The Zod schema for the tool's input. */\n inputSchema: TInput;\n /** The Zod schema for the tool's output. */\n outputSchema: TOutput;\n /**\n * The function that implements the tool's logic.\n * @param input - The validated input matching the input schema.\n * @returns A promise that resolves with the tool's output.\n */\n handler: (input: z.infer<TInput>) => Promise<z.infer<TOutput>>;\n}\n\n/**\n * A server that implements the Model Context Protocol (MCP) for tool communication.\n *\n * Provides a central registry for tools that agents can discover and invoke.\n * All tool inputs and outputs are validated against their Zod schemas.\n *\n * @example\n * ```typescript\n * const server = new MCPServer();\n *\n * server.registerTool({\n * name: 'add',\n * description: 'Adds two numbers',\n * inputSchema: z.object({ a: z.number(), b: z.number() }),\n * outputSchema: z.number(),\n * handler: async ({ a, b }) => a + b,\n * });\n *\n * const result = await server.callTool('add', { a: 5, b: 3 });\n * // result === 8\n * ```\n */\nexport class MCPServer {\n private tools: Map<string, Tool> = new Map();\n\n /**\n * Registers a new tool with the MCP server.\n *\n * @param tool - The tool definition to register.\n * @throws {Error} If a tool with the same name is already registered.\n */\n public registerTool<\n TInput extends z.ZodTypeAny,\n TOutput extends z.ZodTypeAny,\n >(tool: Tool<TInput, TOutput>): void {\n if (this.tools.has(tool.name)) {\n throw new Error(`Tool with name '${tool.name}' is already registered.`);\n }\n this.tools.set(tool.name, tool as unknown as Tool);\n }\n\n /**\n * Retrieves a list of all registered tools and their schemas.\n *\n * @returns An array of tool schema descriptors.\n */\n public listTools(): ToolSchema[] {\n return Array.from(this.tools.values()).map((tool) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: this.zodToJsonSchema(tool.inputSchema),\n outputSchema: this.zodToJsonSchema(tool.outputSchema),\n }));\n }\n\n /**\n * Invokes a specified tool with the provided input.\n *\n * @param toolName - The name of the tool to invoke.\n * @param input - The input to the tool (will be validated against the schema).\n * @returns A promise that resolves with the validated result.\n * @throws {Error} If the tool is not found or input/output validation fails.\n */\n public async callTool(toolName: string, input: unknown): Promise<unknown> {\n const tool = this.tools.get(toolName);\n if (!tool) {\n throw new Error(`Tool with name '${toolName}' not found.`);\n }\n\n const parsedInput = tool.inputSchema.safeParse(input);\n if (!parsedInput.success) {\n throw new Error(\n `Invalid input for tool '${toolName}': ${parsedInput.error.message}`\n );\n }\n\n const result = await tool.handler(parsedInput.data);\n\n const parsedOutput = tool.outputSchema.safeParse(result);\n if (!parsedOutput.success) {\n throw new Error(\n `Invalid output from tool '${toolName}': ${parsedOutput.error.message}`\n );\n }\n\n return parsedOutput.data;\n }\n\n /**\n * Converts a Zod schema to a simplified JSON Schema representation.\n * @param schema - The Zod schema to convert.\n * @returns A simplified JSON Schema object.\n */\n private zodToJsonSchema(schema: z.ZodTypeAny): Record<string, unknown> {\n // Simple conversion - in production, use zod-to-json-schema\n if (schema instanceof z.ZodObject) {\n const shape = schema.shape;\n const properties: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(shape)) {\n properties[key] = { type: this.getZodTypeName(value as z.ZodTypeAny) };\n }\n return { type: 'object', properties };\n }\n return { type: this.getZodTypeName(schema) };\n }\n\n /**\n * Gets the type name for a Zod schema.\n */\n private getZodTypeName(schema: z.ZodTypeAny): string {\n if (schema instanceof z.ZodString) return 'string';\n if (schema instanceof z.ZodNumber) return 'number';\n if (schema instanceof z.ZodBoolean) return 'boolean';\n if (schema instanceof z.ZodArray) return 'array';\n if (schema instanceof z.ZodObject) return 'object';\n return 'unknown';\n }\n}\n"],"mappings":";AAAA,SAAS,SAAS;AAgEX,IAAM,YAAN,MAAgB;AAAA,EACb,QAA2B,oBAAI,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQpC,aAGL,MAAmC;AACnC,QAAI,KAAK,MAAM,IAAI,KAAK,IAAI,GAAG;AAC7B,YAAM,IAAI,MAAM,mBAAmB,KAAK,IAAI,0BAA0B;AAAA,IACxE;AACA,SAAK,MAAM,IAAI,KAAK,MAAM,IAAuB;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,YAA0B;AAC/B,WAAO,MAAM,KAAK,KAAK,MAAM,OAAO,CAAC,EAAE,IAAI,CAAC,UAAU;AAAA,MACpD,MAAM,KAAK;AAAA,MACX,aAAa,KAAK;AAAA,MAClB,aAAa,KAAK,gBAAgB,KAAK,WAAW;AAAA,MAClD,cAAc,KAAK,gBAAgB,KAAK,YAAY;AAAA,IACtD,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,SAAS,UAAkB,OAAkC;AACxE,UAAM,OAAO,KAAK,MAAM,IAAI,QAAQ;AACpC,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,MAAM,mBAAmB,QAAQ,cAAc;AAAA,IAC3D;AAEA,UAAM,cAAc,KAAK,YAAY,UAAU,KAAK;AACpD,QAAI,CAAC,YAAY,SAAS;AACxB,YAAM,IAAI;AAAA,QACR,2BAA2B,QAAQ,MAAM,YAAY,MAAM,OAAO;AAAA,MACpE;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,KAAK,QAAQ,YAAY,IAAI;AAElD,UAAM,eAAe,KAAK,aAAa,UAAU,MAAM;AACvD,QAAI,CAAC,aAAa,SAAS;AACzB,YAAM,IAAI;AAAA,QACR,6BAA6B,QAAQ,MAAM,aAAa,MAAM,OAAO;AAAA,MACvE;AAAA,IACF;AAEA,WAAO,aAAa;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,gBAAgB,QAA+C;AAErE,QAAI,kBAAkB,EAAE,WAAW;AACjC,YAAM,QAAQ,OAAO;AACrB,YAAM,aAAsC,CAAC;AAC7C,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,mBAAW,GAAG,IAAI,EAAE,MAAM,KAAK,eAAe,KAAqB,EAAE;AAAA,MACvE;AACA,aAAO,EAAE,MAAM,UAAU,WAAW;AAAA,IACtC;AACA,WAAO,EAAE,MAAM,KAAK,eAAe,MAAM,EAAE;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,QAA8B;AACnD,QAAI,kBAAkB,EAAE,UAAW,QAAO;AAC1C,QAAI,kBAAkB,EAAE,UAAW,QAAO;AAC1C,QAAI,kBAAkB,EAAE,WAAY,QAAO;AAC3C,QAAI,kBAAkB,EAAE,SAAU,QAAO;AACzC,QAAI,kBAAkB,EAAE,UAAW,QAAO;AAC1C,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for the SandboxManager.
|
|
3
|
+
*/
|
|
4
|
+
interface SandboxConfig {
|
|
5
|
+
/**
|
|
6
|
+
* The default execution timeout in milliseconds.
|
|
7
|
+
* @default 30000
|
|
8
|
+
*/
|
|
9
|
+
timeout?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Options for a specific sandbox run.
|
|
13
|
+
*/
|
|
14
|
+
interface SandboxRunOptions {
|
|
15
|
+
/**
|
|
16
|
+
* The execution timeout in milliseconds for this specific run.
|
|
17
|
+
*/
|
|
18
|
+
timeout?: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Represents the result of a sandbox code execution.
|
|
22
|
+
*/
|
|
23
|
+
interface SandboxResult {
|
|
24
|
+
/** The output/results from the code execution. */
|
|
25
|
+
output: unknown;
|
|
26
|
+
/** Stdout logs produced during execution. */
|
|
27
|
+
stdout?: string[];
|
|
28
|
+
/** Stderr logs produced during execution. */
|
|
29
|
+
stderr?: string[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A custom error class for sandbox timeouts.
|
|
33
|
+
*/
|
|
34
|
+
declare class TimeoutError extends Error {
|
|
35
|
+
constructor(message: string);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* A custom error class for sandbox execution errors.
|
|
39
|
+
*/
|
|
40
|
+
declare class SandboxExecutionError extends Error {
|
|
41
|
+
/** The name of the execution error (e.g., 'SyntaxError'). */
|
|
42
|
+
readonly errorName: string;
|
|
43
|
+
/** The raw traceback from the sandbox. */
|
|
44
|
+
readonly traceback: string;
|
|
45
|
+
constructor(name: string, value: string, traceback: string);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Manages the lifecycle of E2B sandboxes for secure code execution.
|
|
49
|
+
*
|
|
50
|
+
* All tool code execution in AgentForge MUST occur within an E2B sandbox
|
|
51
|
+
* to ensure security isolation and prevent malicious code from affecting
|
|
52
|
+
* the host system.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* const manager = new SandboxManager({ timeout: 10000 });
|
|
57
|
+
* const result = await manager.runCode('1 + 1');
|
|
58
|
+
* console.log(result); // { output: [...], stdout: [], stderr: [] }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
declare class SandboxManager {
|
|
62
|
+
private sandbox;
|
|
63
|
+
private defaultTimeout;
|
|
64
|
+
/**
|
|
65
|
+
* Creates a new SandboxManager.
|
|
66
|
+
* @param config - The configuration for the sandbox manager.
|
|
67
|
+
*/
|
|
68
|
+
constructor(config?: SandboxConfig);
|
|
69
|
+
/**
|
|
70
|
+
* Executes a snippet of code within a secure E2B sandbox.
|
|
71
|
+
*
|
|
72
|
+
* @param code - The code to execute.
|
|
73
|
+
* @param options - Options for this specific run.
|
|
74
|
+
* @returns A promise that resolves to the result of the code execution.
|
|
75
|
+
* @throws {SandboxExecutionError} If the code throws an error.
|
|
76
|
+
*/
|
|
77
|
+
runCode(code: string, options?: SandboxRunOptions): Promise<SandboxResult>;
|
|
78
|
+
/**
|
|
79
|
+
* Terminates the sandbox and releases all associated resources.
|
|
80
|
+
* @returns A promise that resolves when the cleanup is complete.
|
|
81
|
+
*/
|
|
82
|
+
cleanup(): Promise<void>;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export { type SandboxConfig, SandboxExecutionError, SandboxManager, type SandboxResult, type SandboxRunOptions, TimeoutError };
|
package/dist/sandbox.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// src/sandbox.ts
|
|
2
|
+
import { Sandbox } from "@e2b/code-interpreter";
|
|
3
|
+
var TimeoutError = class extends Error {
|
|
4
|
+
constructor(message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "TimeoutError";
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
var SandboxExecutionError = class extends Error {
|
|
10
|
+
/** The name of the execution error (e.g., 'SyntaxError'). */
|
|
11
|
+
errorName;
|
|
12
|
+
/** The raw traceback from the sandbox. */
|
|
13
|
+
traceback;
|
|
14
|
+
constructor(name, value, traceback) {
|
|
15
|
+
super(`${name}: ${value}`);
|
|
16
|
+
this.name = "SandboxExecutionError";
|
|
17
|
+
this.errorName = name;
|
|
18
|
+
this.traceback = traceback;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
var SandboxManager = class {
|
|
22
|
+
sandbox = null;
|
|
23
|
+
defaultTimeout;
|
|
24
|
+
/**
|
|
25
|
+
* Creates a new SandboxManager.
|
|
26
|
+
* @param config - The configuration for the sandbox manager.
|
|
27
|
+
*/
|
|
28
|
+
constructor(config = {}) {
|
|
29
|
+
this.defaultTimeout = config.timeout ?? 3e4;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Executes a snippet of code within a secure E2B sandbox.
|
|
33
|
+
*
|
|
34
|
+
* @param code - The code to execute.
|
|
35
|
+
* @param options - Options for this specific run.
|
|
36
|
+
* @returns A promise that resolves to the result of the code execution.
|
|
37
|
+
* @throws {SandboxExecutionError} If the code throws an error.
|
|
38
|
+
*/
|
|
39
|
+
async runCode(code, options) {
|
|
40
|
+
const timeoutMs = options?.timeout ?? this.defaultTimeout;
|
|
41
|
+
try {
|
|
42
|
+
this.sandbox = await Sandbox.create();
|
|
43
|
+
const execution = await this.sandbox.runCode(code, { timeoutMs });
|
|
44
|
+
if (execution.error) {
|
|
45
|
+
throw new SandboxExecutionError(
|
|
46
|
+
execution.error.name,
|
|
47
|
+
execution.error.value,
|
|
48
|
+
execution.error.traceback
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
output: execution.results,
|
|
53
|
+
stdout: execution.logs.stdout,
|
|
54
|
+
stderr: execution.logs.stderr
|
|
55
|
+
};
|
|
56
|
+
} finally {
|
|
57
|
+
if (this.sandbox) {
|
|
58
|
+
await this.sandbox.kill();
|
|
59
|
+
this.sandbox = null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Terminates the sandbox and releases all associated resources.
|
|
65
|
+
* @returns A promise that resolves when the cleanup is complete.
|
|
66
|
+
*/
|
|
67
|
+
async cleanup() {
|
|
68
|
+
if (this.sandbox) {
|
|
69
|
+
await this.sandbox.kill();
|
|
70
|
+
this.sandbox = null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
export {
|
|
75
|
+
SandboxExecutionError,
|
|
76
|
+
SandboxManager,
|
|
77
|
+
TimeoutError
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=sandbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sandbox.ts"],"sourcesContent":["import { Sandbox } from '@e2b/code-interpreter';\n\n/**\n * Configuration for the SandboxManager.\n */\nexport interface SandboxConfig {\n /**\n * The default execution timeout in milliseconds.\n * @default 30000\n */\n timeout?: number;\n}\n\n/**\n * Options for a specific sandbox run.\n */\nexport interface SandboxRunOptions {\n /**\n * The execution timeout in milliseconds for this specific run.\n */\n timeout?: number;\n}\n\n/**\n * Represents the result of a sandbox code execution.\n */\nexport interface SandboxResult {\n /** The output/results from the code execution. */\n output: unknown;\n /** Stdout logs produced during execution. */\n stdout?: string[];\n /** Stderr logs produced during execution. */\n stderr?: string[];\n}\n\n/**\n * A custom error class for sandbox timeouts.\n */\nexport class TimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'TimeoutError';\n }\n}\n\n/**\n * A custom error class for sandbox execution errors.\n */\nexport class SandboxExecutionError extends Error {\n /** The name of the execution error (e.g., 'SyntaxError'). */\n public readonly errorName: string;\n /** The raw traceback from the sandbox. */\n public readonly traceback: string;\n\n constructor(name: string, value: string, traceback: string) {\n super(`${name}: ${value}`);\n this.name = 'SandboxExecutionError';\n this.errorName = name;\n this.traceback = traceback;\n }\n}\n\n/**\n * Manages the lifecycle of E2B sandboxes for secure code execution.\n *\n * All tool code execution in AgentForge MUST occur within an E2B sandbox\n * to ensure security isolation and prevent malicious code from affecting\n * the host system.\n *\n * @example\n * ```typescript\n * const manager = new SandboxManager({ timeout: 10000 });\n * const result = await manager.runCode('1 + 1');\n * console.log(result); // { output: [...], stdout: [], stderr: [] }\n * ```\n */\nexport class SandboxManager {\n private sandbox: Sandbox | null = null;\n private defaultTimeout: number;\n\n /**\n * Creates a new SandboxManager.\n * @param config - The configuration for the sandbox manager.\n */\n constructor(config: SandboxConfig = {}) {\n this.defaultTimeout = config.timeout ?? 30000;\n }\n\n /**\n * Executes a snippet of code within a secure E2B sandbox.\n *\n * @param code - The code to execute.\n * @param options - Options for this specific run.\n * @returns A promise that resolves to the result of the code execution.\n * @throws {SandboxExecutionError} If the code throws an error.\n */\n async runCode(code: string, options?: SandboxRunOptions): Promise<SandboxResult> {\n const timeoutMs = options?.timeout ?? this.defaultTimeout;\n\n try {\n this.sandbox = await Sandbox.create();\n const execution = await this.sandbox.runCode(code, { timeoutMs });\n\n if (execution.error) {\n throw new SandboxExecutionError(\n execution.error.name,\n execution.error.value,\n execution.error.traceback,\n );\n }\n\n return {\n output: execution.results,\n stdout: execution.logs.stdout,\n stderr: execution.logs.stderr,\n };\n } finally {\n if (this.sandbox) {\n await this.sandbox.kill();\n this.sandbox = null;\n }\n }\n }\n\n /**\n * Terminates the sandbox and releases all associated resources.\n * @returns A promise that resolves when the cleanup is complete.\n */\n async cleanup(): Promise<void> {\n if (this.sandbox) {\n await this.sandbox.kill();\n this.sandbox = null;\n }\n }\n}\n"],"mappings":";AAAA,SAAS,eAAe;AAsCjB,IAAM,eAAN,cAA2B,MAAM;AAAA,EACtC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAKO,IAAM,wBAAN,cAAoC,MAAM;AAAA;AAAA,EAE/B;AAAA;AAAA,EAEA;AAAA,EAEhB,YAAY,MAAc,OAAe,WAAmB;AAC1D,UAAM,GAAG,IAAI,KAAK,KAAK,EAAE;AACzB,SAAK,OAAO;AACZ,SAAK,YAAY;AACjB,SAAK,YAAY;AAAA,EACnB;AACF;AAgBO,IAAM,iBAAN,MAAqB;AAAA,EAClB,UAA0B;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMR,YAAY,SAAwB,CAAC,GAAG;AACtC,SAAK,iBAAiB,OAAO,WAAW;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,QAAQ,MAAc,SAAqD;AAC/E,UAAM,YAAY,SAAS,WAAW,KAAK;AAE3C,QAAI;AACF,WAAK,UAAU,MAAM,QAAQ,OAAO;AACpC,YAAM,YAAY,MAAM,KAAK,QAAQ,QAAQ,MAAM,EAAE,UAAU,CAAC;AAEhE,UAAI,UAAU,OAAO;AACnB,cAAM,IAAI;AAAA,UACR,UAAU,MAAM;AAAA,UAChB,UAAU,MAAM;AAAA,UAChB,UAAU,MAAM;AAAA,QAClB;AAAA,MACF;AAEA,aAAO;AAAA,QACL,QAAQ,UAAU;AAAA,QAClB,QAAQ,UAAU,KAAK;AAAA,QACvB,QAAQ,UAAU,KAAK;AAAA,MACzB;AAAA,IACF,UAAE;AACA,UAAI,KAAK,SAAS;AAChB,cAAM,KAAK,QAAQ,KAAK;AACxB,aAAK,UAAU;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,UAAyB;AAC7B,QAAI,KAAK,SAAS;AAChB,YAAM,KAAK,QAAQ,KAAK;AACxB,WAAK,UAAU;AAAA,IACjB;AAAA,EACF;AACF;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentforge-ai/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Core agent primitives, sandbox integration, and MCP server for AgentForge",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./agent": {
|
|
14
|
+
"types": "./dist/agent.d.ts",
|
|
15
|
+
"import": "./dist/agent.js"
|
|
16
|
+
},
|
|
17
|
+
"./sandbox": {
|
|
18
|
+
"types": "./dist/sandbox.d.ts",
|
|
19
|
+
"import": "./dist/sandbox.js"
|
|
20
|
+
},
|
|
21
|
+
"./mcp": {
|
|
22
|
+
"types": "./dist/mcp-server.d.ts",
|
|
23
|
+
"import": "./dist/mcp-server.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"README.md"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsup",
|
|
32
|
+
"test": "vitest run",
|
|
33
|
+
"test:watch": "vitest",
|
|
34
|
+
"typecheck": "tsc --noEmit",
|
|
35
|
+
"lint": "eslint src/",
|
|
36
|
+
"clean": "rm -rf dist"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@mastra/core": "^0.5.0",
|
|
40
|
+
"ai": "^4.0.0",
|
|
41
|
+
"@e2b/code-interpreter": "^1.0.0",
|
|
42
|
+
"zod": "^3.23.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"tsup": "^8.0.0",
|
|
46
|
+
"typescript": "^5.5.0",
|
|
47
|
+
"vitest": "^2.0.0"
|
|
48
|
+
},
|
|
49
|
+
"keywords": [
|
|
50
|
+
"ai",
|
|
51
|
+
"agents",
|
|
52
|
+
"mastra",
|
|
53
|
+
"mcp",
|
|
54
|
+
"e2b",
|
|
55
|
+
"sandbox",
|
|
56
|
+
"multi-agent"
|
|
57
|
+
],
|
|
58
|
+
"license": "Apache-2.0",
|
|
59
|
+
"repository": {
|
|
60
|
+
"type": "git",
|
|
61
|
+
"url": "https://github.com/Agentic-Engineering-Agency/agentforge.git",
|
|
62
|
+
"directory": "packages/core"
|
|
63
|
+
}
|
|
64
|
+
}
|