neckbeard-agent 0.0.4 → 0.0.7
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 +18 -1
- package/dist/index.cjs +32 -6
- package/dist/index.d.cts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +32 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,6 +41,9 @@ const agent = new Agent({
|
|
|
41
41
|
summary: z.string(),
|
|
42
42
|
keyPoints: z.array(z.string()),
|
|
43
43
|
}),
|
|
44
|
+
envs: {
|
|
45
|
+
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,
|
|
46
|
+
},
|
|
44
47
|
run: async (input) => {
|
|
45
48
|
for await (const message of query({
|
|
46
49
|
prompt: `Research "${input.topic}" and return JSON`,
|
|
@@ -67,7 +70,7 @@ npm install neckbeard-agent
|
|
|
67
70
|
|
|
68
71
|
```bash
|
|
69
72
|
export E2B_API_KEY=your-key
|
|
70
|
-
export ANTHROPIC_API_KEY=your-key
|
|
73
|
+
export ANTHROPIC_API_KEY=your-key # Pass via envs config, not auto-forwarded
|
|
71
74
|
```
|
|
72
75
|
|
|
73
76
|
## The Details
|
|
@@ -87,6 +90,7 @@ new Agent({
|
|
|
87
90
|
},
|
|
88
91
|
files?: [{ url, path }], // pre-download into sandbox
|
|
89
92
|
claudeDir?: string, // upload .claude/ skills directory
|
|
93
|
+
envs?: Record<string, string | undefined>, // environment variables for sandbox
|
|
90
94
|
})
|
|
91
95
|
```
|
|
92
96
|
|
|
@@ -102,6 +106,19 @@ The `files` option downloads things into the sandbox before your agent runs—us
|
|
|
102
106
|
|
|
103
107
|
The `claudeDir` option uploads a local `.claude/` directory to the sandbox, enabling Claude Agent SDK skills. Point it at a directory containing `.claude/skills/*/SKILL.md` files.
|
|
104
108
|
|
|
109
|
+
The `envs` option passes environment variables to the sandbox. These are available to your agent code via `process.env` and `ctx.env`. Undefined values are filtered out:
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
const agent = new Agent({
|
|
113
|
+
template: 'code-interpreter-v1',
|
|
114
|
+
envs: {
|
|
115
|
+
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,
|
|
116
|
+
MY_API_KEY: process.env.MY_API_KEY,
|
|
117
|
+
},
|
|
118
|
+
// ...
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
105
122
|
Some packages can't be bundled because they spawn child processes or have native modules. The Claude Agent SDK is like this. These get automatically marked as external and installed via npm in the sandbox.
|
|
106
123
|
|
|
107
124
|
The `run` function gets a context object with an `executionId`, an `AbortSignal`, environment variables, and a logger.
|
package/dist/index.cjs
CHANGED
|
@@ -144,6 +144,25 @@ async function runSandboxCommand(sandbox, cmd, timeoutMs) {
|
|
|
144
144
|
};
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
|
+
function isWorkspacePackage(pkg, searchPaths) {
|
|
148
|
+
for (const basePath of searchPaths) {
|
|
149
|
+
try {
|
|
150
|
+
const pkgJsonPath = require.resolve(`${pkg}/package.json`, { paths: [basePath] });
|
|
151
|
+
if (!pkgJsonPath.includes("node_modules")) {
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
const pkgJson = JSON.parse((0, import_node_fs.readFileSync)(pkgJsonPath, "utf-8"));
|
|
155
|
+
const version = pkgJson.version || "";
|
|
156
|
+
if (version.startsWith("workspace:")) {
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
return false;
|
|
160
|
+
} catch {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
147
166
|
async function resolvePackageVersion(pkg, sourceFileDir) {
|
|
148
167
|
try {
|
|
149
168
|
const pkgJsonPath = require.resolve(`${pkg}/package.json`, { paths: [sourceFileDir] });
|
|
@@ -232,6 +251,7 @@ var Agent = class {
|
|
|
232
251
|
dependencies;
|
|
233
252
|
files;
|
|
234
253
|
claudeDir;
|
|
254
|
+
envs;
|
|
235
255
|
/** @internal Used by the sandbox runner - must be public for bundled code access */
|
|
236
256
|
_run;
|
|
237
257
|
_sourceFile;
|
|
@@ -246,6 +266,7 @@ var Agent = class {
|
|
|
246
266
|
this.dependencies = config.dependencies ?? DEFAULT_DEPENDENCIES;
|
|
247
267
|
this.files = config.files ?? [];
|
|
248
268
|
this.claudeDir = config.claudeDir;
|
|
269
|
+
this.envs = config.envs ?? {};
|
|
249
270
|
}
|
|
250
271
|
get sandboxId() {
|
|
251
272
|
return this._sandboxId;
|
|
@@ -274,6 +295,7 @@ var Agent = class {
|
|
|
274
295
|
const esbuild = await getEsbuild();
|
|
275
296
|
const { Sandbox } = await getE2b();
|
|
276
297
|
const collectedExternals = /* @__PURE__ */ new Set();
|
|
298
|
+
const sourceFileDir = (0, import_node_path.dirname)(this._sourceFile);
|
|
277
299
|
const result = await esbuild.build({
|
|
278
300
|
entryPoints: [this._sourceFile],
|
|
279
301
|
bundle: true,
|
|
@@ -320,9 +342,14 @@ var __dirname = __neckbeard_dirname(__filename);
|
|
|
320
342
|
return null;
|
|
321
343
|
}
|
|
322
344
|
const match = args.path.match(/^(@[^/]+\/[^/]+|[^/]+)/);
|
|
323
|
-
if (match) {
|
|
324
|
-
|
|
345
|
+
if (!match) {
|
|
346
|
+
return { external: true };
|
|
325
347
|
}
|
|
348
|
+
const pkgName = match[1];
|
|
349
|
+
if (isWorkspacePackage(pkgName, [sourceFileDir, process.cwd()])) {
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
352
|
+
collectedExternals.add(pkgName);
|
|
326
353
|
return { external: true };
|
|
327
354
|
});
|
|
328
355
|
}
|
|
@@ -447,7 +474,6 @@ try {
|
|
|
447
474
|
await sandbox.files.write(SANDBOX_PATHS.runnerModule, runnerCode);
|
|
448
475
|
if (collectedExternals.size > 0) {
|
|
449
476
|
const dependencies = {};
|
|
450
|
-
const sourceFileDir = (0, import_node_path.dirname)(this._sourceFile);
|
|
451
477
|
for (const pkg of collectedExternals) {
|
|
452
478
|
try {
|
|
453
479
|
dependencies[pkg] = await resolvePackageVersion(pkg, sourceFileDir);
|
|
@@ -520,9 +546,9 @@ try {
|
|
|
520
546
|
let capturedStderr = "";
|
|
521
547
|
const result = await sandbox.commands.run(`cd ${SANDBOX_PATHS.agentDir} && node runner.mjs`, {
|
|
522
548
|
timeoutMs: this.maxDuration * 1e3,
|
|
523
|
-
envs:
|
|
524
|
-
|
|
525
|
-
|
|
549
|
+
envs: Object.fromEntries(
|
|
550
|
+
Object.entries(this.envs).filter(([_, v]) => v !== void 0).map(([k, v]) => [k, v])
|
|
551
|
+
),
|
|
526
552
|
onStdout: (data) => {
|
|
527
553
|
capturedStdout += data;
|
|
528
554
|
},
|
package/dist/index.d.cts
CHANGED
|
@@ -124,6 +124,20 @@ interface AgentConfig<TInput, TOutput> {
|
|
|
124
124
|
* - allowedTools includes 'Skill'
|
|
125
125
|
*/
|
|
126
126
|
claudeDir?: string;
|
|
127
|
+
/**
|
|
128
|
+
* Environment variables to pass to the sandbox.
|
|
129
|
+
* These will be available to the agent code via process.env and ctx.env.
|
|
130
|
+
* Undefined values are filtered out.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```typescript
|
|
134
|
+
* envs: {
|
|
135
|
+
* ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,
|
|
136
|
+
* MY_API_KEY: process.env.MY_API_KEY,
|
|
137
|
+
* }
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
envs?: Record<string, string | undefined>;
|
|
127
141
|
}
|
|
128
142
|
declare class Agent<TInput, TOutput> {
|
|
129
143
|
readonly template: string;
|
|
@@ -133,6 +147,7 @@ declare class Agent<TInput, TOutput> {
|
|
|
133
147
|
readonly dependencies: OsDependencies;
|
|
134
148
|
readonly files: FileDownload[];
|
|
135
149
|
readonly claudeDir?: string;
|
|
150
|
+
readonly envs: Record<string, string | undefined>;
|
|
136
151
|
/** @internal Used by the sandbox runner - must be public for bundled code access */
|
|
137
152
|
_run: (input: TInput, ctx: AgentRunContext) => Promise<TOutput>;
|
|
138
153
|
private _sourceFile;
|
package/dist/index.d.ts
CHANGED
|
@@ -124,6 +124,20 @@ interface AgentConfig<TInput, TOutput> {
|
|
|
124
124
|
* - allowedTools includes 'Skill'
|
|
125
125
|
*/
|
|
126
126
|
claudeDir?: string;
|
|
127
|
+
/**
|
|
128
|
+
* Environment variables to pass to the sandbox.
|
|
129
|
+
* These will be available to the agent code via process.env and ctx.env.
|
|
130
|
+
* Undefined values are filtered out.
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* ```typescript
|
|
134
|
+
* envs: {
|
|
135
|
+
* ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,
|
|
136
|
+
* MY_API_KEY: process.env.MY_API_KEY,
|
|
137
|
+
* }
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
envs?: Record<string, string | undefined>;
|
|
127
141
|
}
|
|
128
142
|
declare class Agent<TInput, TOutput> {
|
|
129
143
|
readonly template: string;
|
|
@@ -133,6 +147,7 @@ declare class Agent<TInput, TOutput> {
|
|
|
133
147
|
readonly dependencies: OsDependencies;
|
|
134
148
|
readonly files: FileDownload[];
|
|
135
149
|
readonly claudeDir?: string;
|
|
150
|
+
readonly envs: Record<string, string | undefined>;
|
|
136
151
|
/** @internal Used by the sandbox runner - must be public for bundled code access */
|
|
137
152
|
_run: (input: TInput, ctx: AgentRunContext) => Promise<TOutput>;
|
|
138
153
|
private _sourceFile;
|
package/dist/index.js
CHANGED
|
@@ -111,6 +111,25 @@ async function runSandboxCommand(sandbox, cmd, timeoutMs) {
|
|
|
111
111
|
};
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
|
+
function isWorkspacePackage(pkg, searchPaths) {
|
|
115
|
+
for (const basePath of searchPaths) {
|
|
116
|
+
try {
|
|
117
|
+
const pkgJsonPath = __require.resolve(`${pkg}/package.json`, { paths: [basePath] });
|
|
118
|
+
if (!pkgJsonPath.includes("node_modules")) {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
const pkgJson = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
|
|
122
|
+
const version = pkgJson.version || "";
|
|
123
|
+
if (version.startsWith("workspace:")) {
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
return false;
|
|
127
|
+
} catch {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
114
133
|
async function resolvePackageVersion(pkg, sourceFileDir) {
|
|
115
134
|
try {
|
|
116
135
|
const pkgJsonPath = __require.resolve(`${pkg}/package.json`, { paths: [sourceFileDir] });
|
|
@@ -199,6 +218,7 @@ var Agent = class {
|
|
|
199
218
|
dependencies;
|
|
200
219
|
files;
|
|
201
220
|
claudeDir;
|
|
221
|
+
envs;
|
|
202
222
|
/** @internal Used by the sandbox runner - must be public for bundled code access */
|
|
203
223
|
_run;
|
|
204
224
|
_sourceFile;
|
|
@@ -213,6 +233,7 @@ var Agent = class {
|
|
|
213
233
|
this.dependencies = config.dependencies ?? DEFAULT_DEPENDENCIES;
|
|
214
234
|
this.files = config.files ?? [];
|
|
215
235
|
this.claudeDir = config.claudeDir;
|
|
236
|
+
this.envs = config.envs ?? {};
|
|
216
237
|
}
|
|
217
238
|
get sandboxId() {
|
|
218
239
|
return this._sandboxId;
|
|
@@ -241,6 +262,7 @@ var Agent = class {
|
|
|
241
262
|
const esbuild = await getEsbuild();
|
|
242
263
|
const { Sandbox } = await getE2b();
|
|
243
264
|
const collectedExternals = /* @__PURE__ */ new Set();
|
|
265
|
+
const sourceFileDir = dirname(this._sourceFile);
|
|
244
266
|
const result = await esbuild.build({
|
|
245
267
|
entryPoints: [this._sourceFile],
|
|
246
268
|
bundle: true,
|
|
@@ -287,9 +309,14 @@ var __dirname = __neckbeard_dirname(__filename);
|
|
|
287
309
|
return null;
|
|
288
310
|
}
|
|
289
311
|
const match = args.path.match(/^(@[^/]+\/[^/]+|[^/]+)/);
|
|
290
|
-
if (match) {
|
|
291
|
-
|
|
312
|
+
if (!match) {
|
|
313
|
+
return { external: true };
|
|
292
314
|
}
|
|
315
|
+
const pkgName = match[1];
|
|
316
|
+
if (isWorkspacePackage(pkgName, [sourceFileDir, process.cwd()])) {
|
|
317
|
+
return null;
|
|
318
|
+
}
|
|
319
|
+
collectedExternals.add(pkgName);
|
|
293
320
|
return { external: true };
|
|
294
321
|
});
|
|
295
322
|
}
|
|
@@ -414,7 +441,6 @@ try {
|
|
|
414
441
|
await sandbox.files.write(SANDBOX_PATHS.runnerModule, runnerCode);
|
|
415
442
|
if (collectedExternals.size > 0) {
|
|
416
443
|
const dependencies = {};
|
|
417
|
-
const sourceFileDir = dirname(this._sourceFile);
|
|
418
444
|
for (const pkg of collectedExternals) {
|
|
419
445
|
try {
|
|
420
446
|
dependencies[pkg] = await resolvePackageVersion(pkg, sourceFileDir);
|
|
@@ -487,9 +513,9 @@ try {
|
|
|
487
513
|
let capturedStderr = "";
|
|
488
514
|
const result = await sandbox.commands.run(`cd ${SANDBOX_PATHS.agentDir} && node runner.mjs`, {
|
|
489
515
|
timeoutMs: this.maxDuration * 1e3,
|
|
490
|
-
envs:
|
|
491
|
-
|
|
492
|
-
|
|
516
|
+
envs: Object.fromEntries(
|
|
517
|
+
Object.entries(this.envs).filter(([_, v]) => v !== void 0).map(([k, v]) => [k, v])
|
|
518
|
+
),
|
|
493
519
|
onStdout: (data) => {
|
|
494
520
|
capturedStdout += data;
|
|
495
521
|
},
|