agent-neckbeard 0.0.2 → 0.0.3
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 +29 -3
- package/dist/index.d.ts +14 -1
- package/dist/index.js +50 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ E2B provides sandboxed environments, but wiring up the deployment, bundling, and
|
|
|
20
20
|
|
|
21
21
|
```typescript
|
|
22
22
|
import { Agent } from 'agent-neckbeard';
|
|
23
|
-
import { query } from '@anthropic-ai/claude-
|
|
23
|
+
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
24
24
|
import { z } from 'zod';
|
|
25
25
|
|
|
26
26
|
const summaryAgent = new Agent({
|
|
@@ -66,10 +66,11 @@ console.log(result.keyPoints); // string[] - validated
|
|
|
66
66
|
npm install agent-neckbeard
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
Set your
|
|
69
|
+
Set your API keys:
|
|
70
70
|
|
|
71
71
|
```bash
|
|
72
|
-
export E2B_API_KEY=your-api-key
|
|
72
|
+
export E2B_API_KEY=your-e2b-api-key
|
|
73
|
+
export ANTHROPIC_API_KEY=your-anthropic-api-key # Required for Claude Agent SDK
|
|
73
74
|
```
|
|
74
75
|
|
|
75
76
|
## Running Examples
|
|
@@ -92,6 +93,11 @@ const agent = new Agent({
|
|
|
92
93
|
run: (input, ctx) => Promise, // Your agent logic
|
|
93
94
|
maxDuration?: number, // Timeout in seconds (default: 300)
|
|
94
95
|
sandboxId?: string, // Reuse existing sandbox (skip deploy)
|
|
96
|
+
dependencies?: { // OS-level dependencies to install
|
|
97
|
+
apt?: string[], // APT packages (e.g., ['curl', 'git'])
|
|
98
|
+
npm?: string[], // Global npm packages
|
|
99
|
+
commands?: string[], // Custom shell commands
|
|
100
|
+
},
|
|
95
101
|
});
|
|
96
102
|
```
|
|
97
103
|
|
|
@@ -130,6 +136,26 @@ const agent = new Agent({
|
|
|
130
136
|
const result = await agent.run({ topic: 'hello' });
|
|
131
137
|
```
|
|
132
138
|
|
|
139
|
+
## Claude Agent SDK Support
|
|
140
|
+
|
|
141
|
+
When your agent uses `@anthropic-ai/claude-agent-sdk`, it's automatically detected and installed in the sandbox. The SDK's CLI is available for spawning Claude processes.
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
145
|
+
|
|
146
|
+
const agent = new Agent({
|
|
147
|
+
// ...
|
|
148
|
+
run: async (input, ctx) => {
|
|
149
|
+
for await (const message of query({
|
|
150
|
+
prompt: `Do something with ${input.topic}`,
|
|
151
|
+
options: { maxTurns: 10, allowedTools: ['Bash', 'Read', 'Write'] },
|
|
152
|
+
})) {
|
|
153
|
+
// Handle Claude's responses
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
```
|
|
158
|
+
|
|
133
159
|
## Context
|
|
134
160
|
|
|
135
161
|
The `run` function receives a context object:
|
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,16 @@ interface AgentRunContext {
|
|
|
15
15
|
interface SchemaLike<T> {
|
|
16
16
|
parse: (data: unknown) => T;
|
|
17
17
|
}
|
|
18
|
+
interface OsDependencies {
|
|
19
|
+
/** APT packages to install (e.g., ['curl', 'git']) */
|
|
20
|
+
apt?: string[];
|
|
21
|
+
/** NPM packages to install globally (e.g., ['typescript', '@anthropic-ai/claude-code']) */
|
|
22
|
+
npm?: string[];
|
|
23
|
+
/** Custom shell commands to run during setup */
|
|
24
|
+
commands?: string[];
|
|
25
|
+
}
|
|
26
|
+
/** Default dependencies - empty by default, specify what you need */
|
|
27
|
+
declare const DEFAULT_DEPENDENCIES: OsDependencies;
|
|
18
28
|
interface AgentConfig<TInput, TOutput> {
|
|
19
29
|
id: string;
|
|
20
30
|
inputSchema: SchemaLike<TInput>;
|
|
@@ -22,12 +32,15 @@ interface AgentConfig<TInput, TOutput> {
|
|
|
22
32
|
run: (input: TInput, ctx: AgentRunContext) => Promise<TOutput>;
|
|
23
33
|
maxDuration?: number;
|
|
24
34
|
sandboxId?: string;
|
|
35
|
+
/** OS-level dependencies to install in the sandbox. Defaults to Claude Code. Set to {} to skip. */
|
|
36
|
+
dependencies?: OsDependencies;
|
|
25
37
|
}
|
|
26
38
|
declare class Agent<TInput, TOutput> {
|
|
27
39
|
readonly id: string;
|
|
28
40
|
readonly inputSchema: SchemaLike<TInput>;
|
|
29
41
|
readonly outputSchema: SchemaLike<TOutput>;
|
|
30
42
|
readonly maxDuration: number;
|
|
43
|
+
readonly dependencies: OsDependencies;
|
|
31
44
|
/** @internal Used by the sandbox runner - must be public for bundled code access */
|
|
32
45
|
_run: (input: TInput, ctx: AgentRunContext) => Promise<TOutput>;
|
|
33
46
|
private _sourceFile;
|
|
@@ -38,4 +51,4 @@ declare class Agent<TInput, TOutput> {
|
|
|
38
51
|
run(input: TInput): Promise<TOutput>;
|
|
39
52
|
}
|
|
40
53
|
|
|
41
|
-
export { Agent, type AgentConfig, type AgentRunContext };
|
|
54
|
+
export { Agent, type AgentConfig, type AgentRunContext, DEFAULT_DEPENDENCIES, type OsDependencies };
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { fileURLToPath } from "url";
|
|
3
3
|
var getEsbuild = () => import("esbuild");
|
|
4
4
|
var getE2b = () => import("e2b");
|
|
5
|
+
var DEFAULT_DEPENDENCIES = {};
|
|
5
6
|
function getCallerFile() {
|
|
6
7
|
const stack = new Error().stack?.split("\n") ?? [];
|
|
7
8
|
for (const line of stack.slice(2)) {
|
|
@@ -19,6 +20,7 @@ var Agent = class {
|
|
|
19
20
|
inputSchema;
|
|
20
21
|
outputSchema;
|
|
21
22
|
maxDuration;
|
|
23
|
+
dependencies;
|
|
22
24
|
/** @internal Used by the sandbox runner - must be public for bundled code access */
|
|
23
25
|
_run;
|
|
24
26
|
_sourceFile;
|
|
@@ -31,6 +33,7 @@ var Agent = class {
|
|
|
31
33
|
this._run = config.run;
|
|
32
34
|
this._sourceFile = getCallerFile();
|
|
33
35
|
this._sandboxId = config.sandboxId;
|
|
36
|
+
this.dependencies = config.dependencies ?? DEFAULT_DEPENDENCIES;
|
|
34
37
|
}
|
|
35
38
|
get sandboxId() {
|
|
36
39
|
return this._sandboxId;
|
|
@@ -69,6 +72,9 @@ var Agent = class {
|
|
|
69
72
|
`,
|
|
70
73
|
loader: "js"
|
|
71
74
|
}));
|
|
75
|
+
build.onResolve({ filter: /^@anthropic-ai\/claude-agent-sdk/ }, () => ({
|
|
76
|
+
external: true
|
|
77
|
+
}));
|
|
72
78
|
}
|
|
73
79
|
}]
|
|
74
80
|
});
|
|
@@ -107,8 +113,46 @@ try {
|
|
|
107
113
|
const sandbox = await Sandbox.create("base", {
|
|
108
114
|
apiKey: process.env.E2B_API_KEY
|
|
109
115
|
});
|
|
116
|
+
const { apt, npm, commands } = this.dependencies;
|
|
117
|
+
if (apt && apt.length > 0) {
|
|
118
|
+
const aptCmd = `apt-get update && apt-get install -y ${apt.join(" ")}`;
|
|
119
|
+
const aptResult = await sandbox.commands.run(aptCmd, { timeoutMs: 3e5 });
|
|
120
|
+
if (aptResult.exitCode !== 0) {
|
|
121
|
+
throw new Error(`Failed to install apt packages: ${aptResult.stderr}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (npm && npm.length > 0) {
|
|
125
|
+
const npmCmd = `npm install -g ${npm.join(" ")}`;
|
|
126
|
+
const npmResult = await sandbox.commands.run(npmCmd, { timeoutMs: 3e5 });
|
|
127
|
+
if (npmResult.exitCode !== 0) {
|
|
128
|
+
throw new Error(`Failed to install npm packages: ${npmResult.stderr}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (commands && commands.length > 0) {
|
|
132
|
+
for (const cmd of commands) {
|
|
133
|
+
const cmdResult = await sandbox.commands.run(cmd, { timeoutMs: 3e5 });
|
|
134
|
+
if (cmdResult.exitCode !== 0) {
|
|
135
|
+
throw new Error(`Failed to run command "${cmd}": ${cmdResult.stderr}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
110
139
|
await sandbox.files.write("/home/user/agent.mjs", result.outputFiles[0].text);
|
|
111
140
|
await sandbox.files.write("/home/user/runner.mjs", runnerCode);
|
|
141
|
+
const bundledCode = result.outputFiles[0].text;
|
|
142
|
+
if (bundledCode.includes("@anthropic-ai/claude-agent-sdk")) {
|
|
143
|
+
const pkgJson = JSON.stringify({
|
|
144
|
+
name: "agent-sandbox",
|
|
145
|
+
type: "module",
|
|
146
|
+
dependencies: {
|
|
147
|
+
"@anthropic-ai/claude-agent-sdk": "*"
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
await sandbox.files.write("/home/user/package.json", pkgJson);
|
|
151
|
+
const installResult = await sandbox.commands.run("cd /home/user && npm install", { timeoutMs: 3e5 });
|
|
152
|
+
if (installResult.exitCode !== 0) {
|
|
153
|
+
throw new Error(`Failed to install claude-agent-sdk: ${installResult.stderr}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
112
156
|
this._sandboxId = sandbox.sandboxId;
|
|
113
157
|
}
|
|
114
158
|
async run(input) {
|
|
@@ -123,7 +167,10 @@ try {
|
|
|
123
167
|
});
|
|
124
168
|
await sandbox.files.write("/home/user/input/task.json", JSON.stringify({ input: validatedInput, executionId }));
|
|
125
169
|
const result = await sandbox.commands.run("node /home/user/runner.mjs", {
|
|
126
|
-
timeoutMs: this.maxDuration * 1e3
|
|
170
|
+
timeoutMs: this.maxDuration * 1e3,
|
|
171
|
+
envs: {
|
|
172
|
+
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY ?? ""
|
|
173
|
+
}
|
|
127
174
|
});
|
|
128
175
|
if (result.exitCode !== 0) throw new Error(`Agent failed: ${result.stderr}`);
|
|
129
176
|
const output = JSON.parse(await sandbox.files.read("/home/user/output/result.json"));
|
|
@@ -136,5 +183,6 @@ try {
|
|
|
136
183
|
}
|
|
137
184
|
};
|
|
138
185
|
export {
|
|
139
|
-
Agent
|
|
186
|
+
Agent,
|
|
187
|
+
DEFAULT_DEPENDENCIES
|
|
140
188
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-neckbeard",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Deploy AI agents to E2B sandboxes",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"esbuild": "^0.24.0"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"zod": "^3.0.0"
|
|
32
|
+
"zod": "^3.0.0 || ^4.0.0"
|
|
33
33
|
},
|
|
34
34
|
"peerDependenciesMeta": {
|
|
35
35
|
"zod": {
|