ai-evaluate 2.1.4 → 2.1.6
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/.turbo/turbo-build.log +1 -1
- package/README.md +121 -72
- package/dist/evaluate.d.ts +7 -24
- package/dist/evaluate.d.ts.map +1 -1
- package/dist/evaluate.js +26 -113
- package/dist/evaluate.js.map +1 -1
- package/dist/node.d.ts +17 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +171 -0
- package/dist/node.js.map +1 -0
- package/dist/repl.d.ts +77 -0
- package/dist/repl.d.ts.map +1 -0
- package/dist/repl.js +145 -0
- package/dist/repl.js.map +1 -0
- package/dist/types.d.ts +12 -10
- package/dist/types.d.ts.map +1 -1
- package/dist/worker-template.d.ts +11 -10
- package/dist/worker-template.d.ts.map +1 -1
- package/dist/worker-template.js +107 -20
- package/dist/worker-template.js.map +1 -1
- package/example/package.json +16 -0
- package/example/src/index.ts +67 -0
- package/example/wrangler.jsonc +9 -0
- package/package.json +11 -3
- package/src/evaluate.ts +28 -127
- package/src/node.d.ts +17 -0
- package/src/node.d.ts.map +1 -0
- package/src/node.js +168 -0
- package/src/node.js.map +1 -0
- package/src/node.ts +200 -0
- package/src/repl.ts +228 -0
- package/src/types.d.ts +172 -0
- package/src/types.d.ts.map +1 -0
- package/src/types.js.map +1 -0
- package/src/types.ts +15 -16
- package/src/worker-template.d.ts +41 -0
- package/src/worker-template.d.ts.map +1 -0
- package/src/worker-template.js.map +1 -0
- package/src/worker-template.ts +113 -31
- package/vitest.config.js +6 -0
- package/vitest.config.ts +14 -2
package/.turbo/turbo-build.log
CHANGED
package/README.md
CHANGED
|
@@ -17,60 +17,81 @@ const result = eval(userCode) // Could do ANYTHING
|
|
|
17
17
|
// After: Sandboxed execution
|
|
18
18
|
import { evaluate } from 'ai-evaluate'
|
|
19
19
|
|
|
20
|
-
const result = await evaluate({
|
|
21
|
-
script: userCode
|
|
22
|
-
})
|
|
20
|
+
const result = await evaluate({ script: userCode }, env)
|
|
23
21
|
// Runs in isolated V8 context - your system is protected
|
|
24
22
|
```
|
|
25
23
|
|
|
26
24
|
## Quick Start
|
|
27
25
|
|
|
26
|
+
### Ready-to-Deploy Example
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
cd example
|
|
30
|
+
pnpm install
|
|
31
|
+
pnpm deploy
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
See [`example/`](./example) for a complete working Worker.
|
|
35
|
+
|
|
36
|
+
### Cloudflare Workers (Production)
|
|
37
|
+
|
|
28
38
|
**1. Install**
|
|
29
39
|
|
|
30
40
|
```bash
|
|
31
41
|
pnpm add ai-evaluate
|
|
32
42
|
```
|
|
33
43
|
|
|
34
|
-
**2.
|
|
44
|
+
**2. Configure wrangler.jsonc**
|
|
45
|
+
|
|
46
|
+
> **Important**: Requires wrangler v4+ (`pnpm add -D wrangler@4`)
|
|
47
|
+
|
|
48
|
+
```jsonc
|
|
49
|
+
{
|
|
50
|
+
"name": "my-worker",
|
|
51
|
+
"main": "src/index.ts",
|
|
52
|
+
"compatibility_date": "2026-01-01",
|
|
53
|
+
"worker_loaders": [
|
|
54
|
+
{ "binding": "loader" }
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**3. Use in your Worker**
|
|
35
60
|
|
|
36
61
|
```typescript
|
|
37
62
|
import { evaluate } from 'ai-evaluate'
|
|
38
63
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
})
|
|
42
|
-
|
|
64
|
+
export default {
|
|
65
|
+
async fetch(request: Request, env: Env) {
|
|
66
|
+
const result = await evaluate({ script: '1 + 1' }, env)
|
|
67
|
+
return Response.json(result)
|
|
68
|
+
// { success: true, value: 2, logs: [], duration: 5 }
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
interface Env {
|
|
73
|
+
loader: unknown
|
|
74
|
+
}
|
|
43
75
|
```
|
|
44
76
|
|
|
45
|
-
|
|
77
|
+
### Node.js / Local Development
|
|
46
78
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
`,
|
|
52
|
-
tests: `
|
|
53
|
-
describe('add', () => {
|
|
54
|
-
it('adds numbers', () => {
|
|
55
|
-
expect(add(2, 3)).toBe(5)
|
|
56
|
-
})
|
|
57
|
-
})
|
|
58
|
-
`
|
|
59
|
-
})
|
|
60
|
-
// result.testResults.passed === 1
|
|
79
|
+
For local development, import from the `/node` subpath which uses Miniflare:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
pnpm add ai-evaluate miniflare
|
|
61
83
|
```
|
|
62
84
|
|
|
63
|
-
|
|
85
|
+
```typescript
|
|
86
|
+
import { evaluate } from 'ai-evaluate/node'
|
|
64
87
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
- **Production-ready** - Cloudflare Workers in production, Miniflare locally
|
|
69
|
-
- **Network blocked** - External access disabled by default
|
|
88
|
+
const result = await evaluate({ script: '1 + 1' })
|
|
89
|
+
// { success: true, value: 2, logs: [], duration: 50 }
|
|
90
|
+
```
|
|
70
91
|
|
|
71
92
|
## API Reference
|
|
72
93
|
|
|
73
|
-
### evaluate(options)
|
|
94
|
+
### evaluate(options, env?)
|
|
74
95
|
|
|
75
96
|
```typescript
|
|
76
97
|
interface EvaluateOptions {
|
|
@@ -94,7 +115,7 @@ interface EvaluateResult {
|
|
|
94
115
|
|
|
95
116
|
### createEvaluator(env)
|
|
96
117
|
|
|
97
|
-
Bind to a Cloudflare Workers environment
|
|
118
|
+
Bind to a Cloudflare Workers environment for cleaner syntax:
|
|
98
119
|
|
|
99
120
|
```typescript
|
|
100
121
|
import { createEvaluator } from 'ai-evaluate'
|
|
@@ -119,7 +140,7 @@ const result = await evaluate({
|
|
|
119
140
|
const y = 20
|
|
120
141
|
return x + y
|
|
121
142
|
`
|
|
122
|
-
})
|
|
143
|
+
}, env)
|
|
123
144
|
// result.value === 30
|
|
124
145
|
```
|
|
125
146
|
|
|
@@ -128,14 +149,14 @@ const result = await evaluate({
|
|
|
128
149
|
```typescript
|
|
129
150
|
const result = await evaluate({
|
|
130
151
|
module: `
|
|
131
|
-
|
|
132
|
-
|
|
152
|
+
export const greet = (name) => \`Hello, \${name}!\`
|
|
153
|
+
export const sum = (...nums) => nums.reduce((a, b) => a + b, 0)
|
|
133
154
|
`,
|
|
134
155
|
script: `
|
|
135
156
|
console.log(greet('World'))
|
|
136
157
|
return sum(1, 2, 3, 4, 5)
|
|
137
158
|
`
|
|
138
|
-
})
|
|
159
|
+
}, env)
|
|
139
160
|
// result.value === 15
|
|
140
161
|
// result.logs[0].message === 'Hello, World!'
|
|
141
162
|
```
|
|
@@ -145,7 +166,7 @@ const result = await evaluate({
|
|
|
145
166
|
```typescript
|
|
146
167
|
const result = await evaluate({
|
|
147
168
|
module: `
|
|
148
|
-
|
|
169
|
+
export const isPrime = (n) => {
|
|
149
170
|
if (n < 2) return false
|
|
150
171
|
for (let i = 2; i <= Math.sqrt(n); i++) {
|
|
151
172
|
if (n % i === 0) return false
|
|
@@ -171,7 +192,7 @@ const result = await evaluate({
|
|
|
171
192
|
})
|
|
172
193
|
})
|
|
173
194
|
`
|
|
174
|
-
})
|
|
195
|
+
}, env)
|
|
175
196
|
|
|
176
197
|
// result.testResults = { total: 3, passed: 3, failed: 0, ... }
|
|
177
198
|
```
|
|
@@ -257,59 +278,60 @@ await expect(promise).resolves.toBe(value)
|
|
|
257
278
|
await expect(promise).rejects.toThrow('error')
|
|
258
279
|
```
|
|
259
280
|
|
|
260
|
-
##
|
|
281
|
+
## REPL Sessions
|
|
261
282
|
|
|
262
|
-
|
|
283
|
+
For interactive or multi-step evaluations, use the `/repl` export:
|
|
263
284
|
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
main = "src/index.ts"
|
|
285
|
+
```typescript
|
|
286
|
+
import { createReplSession } from 'ai-evaluate/repl'
|
|
267
287
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
```
|
|
288
|
+
// Create a persistent session
|
|
289
|
+
const session = await createReplSession({ local: true })
|
|
271
290
|
|
|
272
|
-
|
|
291
|
+
// Evaluate multiple expressions with shared context
|
|
292
|
+
await session.eval('const sum = (a, b) => a + b')
|
|
293
|
+
const result = await session.eval('sum(1, 2)')
|
|
294
|
+
console.log(result.value) // 3
|
|
273
295
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
LOADER: unknown
|
|
279
|
-
}
|
|
296
|
+
// Context persists across evaluations
|
|
297
|
+
await session.eval('const x = 10')
|
|
298
|
+
const result2 = await session.eval('sum(x, 5)')
|
|
299
|
+
console.log(result2.value) // 15
|
|
280
300
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
const { code, tests } = await request.json()
|
|
301
|
+
// Clean up
|
|
302
|
+
await session.close()
|
|
303
|
+
```
|
|
285
304
|
|
|
286
|
-
|
|
287
|
-
module: code,
|
|
288
|
-
tests: tests
|
|
289
|
-
})
|
|
305
|
+
### REPL Configuration
|
|
290
306
|
|
|
291
|
-
|
|
292
|
-
|
|
307
|
+
```typescript
|
|
308
|
+
interface ReplSessionConfig {
|
|
309
|
+
local?: boolean // Use Miniflare (default: false, uses remote)
|
|
310
|
+
auth?: string // Auth token for remote execution
|
|
311
|
+
sdk?: SDKConfig | boolean // Enable platform primitives ($, db, ai)
|
|
312
|
+
prelude?: string // Code to run at session start
|
|
313
|
+
timeout?: number // Eval timeout in ms (default: 5000)
|
|
314
|
+
allowNetwork?: boolean // Allow fetch (default: true)
|
|
293
315
|
}
|
|
294
316
|
```
|
|
295
317
|
|
|
296
|
-
|
|
318
|
+
### Quick Eval
|
|
297
319
|
|
|
298
|
-
|
|
320
|
+
For one-off evaluations without session management:
|
|
299
321
|
|
|
300
322
|
```typescript
|
|
301
|
-
import {
|
|
323
|
+
import { quickEval } from 'ai-evaluate/repl'
|
|
302
324
|
|
|
303
|
-
const result = await
|
|
304
|
-
|
|
305
|
-
})
|
|
325
|
+
const result = await quickEval('1 + 2 * 3')
|
|
326
|
+
console.log(result.value) // 7
|
|
306
327
|
```
|
|
307
328
|
|
|
308
|
-
|
|
329
|
+
## Requirements
|
|
309
330
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
331
|
+
| Environment | Requirement |
|
|
332
|
+
|-------------|-------------|
|
|
333
|
+
| Cloudflare Workers | wrangler v4+, `worker_loaders` binding |
|
|
334
|
+
| Node.js | miniflare (peer dependency) |
|
|
313
335
|
|
|
314
336
|
## Security Model
|
|
315
337
|
|
|
@@ -321,6 +343,33 @@ pnpm add miniflare
|
|
|
321
343
|
| Memory Limits | Standard Worker limits apply |
|
|
322
344
|
| CPU Limits | Execution time bounded |
|
|
323
345
|
|
|
346
|
+
## Troubleshooting
|
|
347
|
+
|
|
348
|
+
### "Unexpected fields found in top-level field: worker_loaders"
|
|
349
|
+
|
|
350
|
+
Upgrade wrangler to v4+:
|
|
351
|
+
```bash
|
|
352
|
+
pnpm add -D wrangler@4
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### "Code generation from strings disallowed"
|
|
356
|
+
|
|
357
|
+
User code must be embedded at build time, not evaluated with `new Function()` or `eval()`. This is handled automatically by ai-evaluate - just pass your code as strings to `evaluate()`.
|
|
358
|
+
|
|
359
|
+
### "No loader binding"
|
|
360
|
+
|
|
361
|
+
Ensure your wrangler.jsonc has the worker_loaders config and you're passing `env` to `evaluate()`:
|
|
362
|
+
|
|
363
|
+
```jsonc
|
|
364
|
+
{
|
|
365
|
+
"worker_loaders": [{ "binding": "loader" }]
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
```typescript
|
|
370
|
+
await evaluate({ script: code }, env) // Don't forget env!
|
|
371
|
+
```
|
|
372
|
+
|
|
324
373
|
## Types
|
|
325
374
|
|
|
326
375
|
```typescript
|
package/dist/evaluate.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Evaluate code in a sandboxed environment
|
|
3
3
|
*
|
|
4
|
-
* Uses Cloudflare worker_loaders
|
|
5
|
-
*
|
|
4
|
+
* Uses Cloudflare worker_loaders for secure code execution.
|
|
5
|
+
* For Node.js/local development, import from 'ai-evaluate/node' instead.
|
|
6
6
|
*
|
|
7
|
-
* Requires
|
|
7
|
+
* Requires:
|
|
8
|
+
* - LOADER binding (worker_loaders)
|
|
9
|
+
* - TEST binding (ai-tests service)
|
|
8
10
|
*/
|
|
9
11
|
import type { EvaluateOptions, EvaluateResult, SandboxEnv } from './types.js';
|
|
10
12
|
/**
|
|
@@ -12,32 +14,13 @@ import type { EvaluateOptions, EvaluateResult, SandboxEnv } from './types.js';
|
|
|
12
14
|
*
|
|
13
15
|
* @example
|
|
14
16
|
* ```ts
|
|
15
|
-
* import { evaluate } from 'ai-
|
|
17
|
+
* import { evaluate } from 'ai-evaluate'
|
|
16
18
|
*
|
|
17
19
|
* // Run a simple script
|
|
18
20
|
* const result = await evaluate({
|
|
19
21
|
* script: 'return 1 + 1'
|
|
20
|
-
* })
|
|
22
|
+
* }, env)
|
|
21
23
|
* // { success: true, value: 2, logs: [], duration: ... }
|
|
22
|
-
*
|
|
23
|
-
* // With a module and tests
|
|
24
|
-
* const result = await evaluate({
|
|
25
|
-
* module: `
|
|
26
|
-
* exports.add = (a, b) => a + b;
|
|
27
|
-
* exports.multiply = (a, b) => a * b;
|
|
28
|
-
* `,
|
|
29
|
-
* tests: `
|
|
30
|
-
* describe('math', () => {
|
|
31
|
-
* it('adds numbers', () => {
|
|
32
|
-
* expect(add(2, 3)).toBe(5);
|
|
33
|
-
* });
|
|
34
|
-
* it('multiplies numbers', () => {
|
|
35
|
-
* expect(multiply(2, 3)).toBe(6);
|
|
36
|
-
* });
|
|
37
|
-
* });
|
|
38
|
-
* `,
|
|
39
|
-
* script: 'return add(10, 20)'
|
|
40
|
-
* })
|
|
41
24
|
* ```
|
|
42
25
|
*/
|
|
43
26
|
export declare function evaluate(options: EvaluateOptions, env?: SandboxEnv): Promise<EvaluateResult>;
|
package/dist/evaluate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../src/evaluate.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../src/evaluate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAgB,UAAU,EAAE,MAAM,YAAY,CAAA;AAG3F;;;;;;;;;;;;;GAaG;AACH,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,eAAe,EACxB,GAAG,CAAC,EAAE,UAAU,GACf,OAAO,CAAC,cAAc,CAAC,CAyBzB;AA4CD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,UAAU,IACrC,SAAS,eAAe,6BACjC"}
|
package/dist/evaluate.js
CHANGED
|
@@ -1,102 +1,49 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Evaluate code in a sandboxed environment
|
|
3
3
|
*
|
|
4
|
-
* Uses Cloudflare worker_loaders
|
|
5
|
-
*
|
|
4
|
+
* Uses Cloudflare worker_loaders for secure code execution.
|
|
5
|
+
* For Node.js/local development, import from 'ai-evaluate/node' instead.
|
|
6
6
|
*
|
|
7
|
-
* Requires
|
|
7
|
+
* Requires:
|
|
8
|
+
* - LOADER binding (worker_loaders)
|
|
9
|
+
* - TEST binding (ai-tests service)
|
|
8
10
|
*/
|
|
9
|
-
import { generateWorkerCode
|
|
10
|
-
/**
|
|
11
|
-
* Check if code contains JSX syntax that needs transformation
|
|
12
|
-
*/
|
|
13
|
-
function containsJSX(code) {
|
|
14
|
-
if (!code)
|
|
15
|
-
return false;
|
|
16
|
-
// Look for JSX patterns
|
|
17
|
-
const jsxPattern = /<[A-Z][a-zA-Z0-9]*[\s/>]|<[a-z][a-z0-9-]*[\s/>]|<>|<\/>/;
|
|
18
|
-
const jsxReturnPattern = /return\s*\(\s*<|return\s+<[A-Za-z]/;
|
|
19
|
-
return jsxPattern.test(code) || jsxReturnPattern.test(code);
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Transform JSX in code using esbuild
|
|
23
|
-
*/
|
|
24
|
-
async function transformJSX(code) {
|
|
25
|
-
if (!code || !containsJSX(code))
|
|
26
|
-
return code;
|
|
27
|
-
try {
|
|
28
|
-
const { transform } = await import('esbuild');
|
|
29
|
-
const result = await transform(code, {
|
|
30
|
-
loader: 'tsx',
|
|
31
|
-
jsxFactory: 'h',
|
|
32
|
-
jsxFragment: 'Fragment',
|
|
33
|
-
target: 'esnext',
|
|
34
|
-
format: 'esm',
|
|
35
|
-
});
|
|
36
|
-
return result.code;
|
|
37
|
-
}
|
|
38
|
-
catch (error) {
|
|
39
|
-
// If transform fails, return original code and let sandbox handle the error
|
|
40
|
-
console.error('JSX transform failed:', error);
|
|
41
|
-
return code;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
11
|
+
import { generateWorkerCode } from './worker-template.js';
|
|
44
12
|
/**
|
|
45
13
|
* Evaluate code in a sandboxed worker
|
|
46
14
|
*
|
|
47
15
|
* @example
|
|
48
16
|
* ```ts
|
|
49
|
-
* import { evaluate } from 'ai-
|
|
17
|
+
* import { evaluate } from 'ai-evaluate'
|
|
50
18
|
*
|
|
51
19
|
* // Run a simple script
|
|
52
20
|
* const result = await evaluate({
|
|
53
21
|
* script: 'return 1 + 1'
|
|
54
|
-
* })
|
|
22
|
+
* }, env)
|
|
55
23
|
* // { success: true, value: 2, logs: [], duration: ... }
|
|
56
|
-
*
|
|
57
|
-
* // With a module and tests
|
|
58
|
-
* const result = await evaluate({
|
|
59
|
-
* module: `
|
|
60
|
-
* exports.add = (a, b) => a + b;
|
|
61
|
-
* exports.multiply = (a, b) => a * b;
|
|
62
|
-
* `,
|
|
63
|
-
* tests: `
|
|
64
|
-
* describe('math', () => {
|
|
65
|
-
* it('adds numbers', () => {
|
|
66
|
-
* expect(add(2, 3)).toBe(5);
|
|
67
|
-
* });
|
|
68
|
-
* it('multiplies numbers', () => {
|
|
69
|
-
* expect(multiply(2, 3)).toBe(6);
|
|
70
|
-
* });
|
|
71
|
-
* });
|
|
72
|
-
* `,
|
|
73
|
-
* script: 'return add(10, 20)'
|
|
74
|
-
* })
|
|
75
24
|
* ```
|
|
76
25
|
*/
|
|
77
26
|
export async function evaluate(options, env) {
|
|
78
27
|
const start = Date.now();
|
|
79
28
|
try {
|
|
80
|
-
//
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return await evaluateWithWorkerLoader(transformedOptions, env.LOADER, env.TEST, start);
|
|
29
|
+
// Require worker_loaders binding (check lowercase first, then legacy uppercase)
|
|
30
|
+
const loader = env?.loader || env?.LOADER;
|
|
31
|
+
if (!loader) {
|
|
32
|
+
return {
|
|
33
|
+
success: false,
|
|
34
|
+
logs: [],
|
|
35
|
+
error: 'Sandbox requires worker_loaders binding. Add to wrangler.jsonc: "worker_loaders": [{ "binding": "loader" }]. For Node.js, use: import { evaluate } from "ai-evaluate/node"',
|
|
36
|
+
duration: Date.now() - start,
|
|
37
|
+
};
|
|
90
38
|
}
|
|
91
|
-
|
|
92
|
-
return await evaluateWithMiniflare(transformedOptions, start);
|
|
39
|
+
return await evaluateWithWorkerLoader(options, loader, env?.TEST, start);
|
|
93
40
|
}
|
|
94
41
|
catch (error) {
|
|
95
42
|
return {
|
|
96
43
|
success: false,
|
|
97
44
|
logs: [],
|
|
98
45
|
error: error instanceof Error ? error.message : String(error),
|
|
99
|
-
duration: Date.now() - start
|
|
46
|
+
duration: Date.now() - start,
|
|
100
47
|
};
|
|
101
48
|
}
|
|
102
49
|
}
|
|
@@ -109,64 +56,30 @@ async function evaluateWithWorkerLoader(options, loader, testService, start) {
|
|
|
109
56
|
tests: options.tests,
|
|
110
57
|
script: options.script,
|
|
111
58
|
sdk: options.sdk,
|
|
112
|
-
imports: options.imports
|
|
59
|
+
imports: options.imports,
|
|
113
60
|
});
|
|
114
61
|
const id = `sandbox-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
115
62
|
const worker = loader.get(id, async () => ({
|
|
116
63
|
mainModule: 'worker.js',
|
|
117
64
|
modules: {
|
|
118
|
-
'worker.js': workerCode
|
|
65
|
+
'worker.js': workerCode,
|
|
119
66
|
},
|
|
120
|
-
compatibilityDate: '
|
|
67
|
+
compatibilityDate: '2026-01-01',
|
|
121
68
|
// Block network access only if fetch: null
|
|
122
69
|
globalOutbound: options.fetch === null ? null : undefined,
|
|
123
70
|
bindings: {
|
|
124
|
-
TEST: testService
|
|
125
|
-
}
|
|
71
|
+
TEST: testService,
|
|
72
|
+
},
|
|
126
73
|
}));
|
|
127
74
|
// Get the entrypoint and call fetch (required by Cloudflare worker_loaders API)
|
|
128
75
|
const entrypoint = worker.getEntrypoint();
|
|
129
76
|
const response = await entrypoint.fetch(new Request('http://sandbox/execute'));
|
|
130
|
-
const result = await response.json();
|
|
77
|
+
const result = (await response.json());
|
|
131
78
|
return {
|
|
132
79
|
...result,
|
|
133
|
-
duration: Date.now() - start
|
|
80
|
+
duration: Date.now() - start,
|
|
134
81
|
};
|
|
135
82
|
}
|
|
136
|
-
/**
|
|
137
|
-
* Evaluate using Miniflare (for Node.js/development)
|
|
138
|
-
*
|
|
139
|
-
* For local dev, we use generateDevWorkerCode which bundles the test
|
|
140
|
-
* framework directly. In production, the sandbox worker uses RPC to
|
|
141
|
-
* a deployed ai-tests worker.
|
|
142
|
-
*/
|
|
143
|
-
async function evaluateWithMiniflare(options, start) {
|
|
144
|
-
// Dynamic import to avoid bundling in production
|
|
145
|
-
const { Miniflare } = await import('miniflare');
|
|
146
|
-
const workerCode = generateDevWorkerCode({
|
|
147
|
-
module: options.module,
|
|
148
|
-
tests: options.tests,
|
|
149
|
-
script: options.script,
|
|
150
|
-
sdk: options.sdk,
|
|
151
|
-
imports: options.imports
|
|
152
|
-
});
|
|
153
|
-
const mf = new Miniflare({
|
|
154
|
-
modules: true,
|
|
155
|
-
script: workerCode,
|
|
156
|
-
compatibilityDate: '2024-01-01'
|
|
157
|
-
});
|
|
158
|
-
try {
|
|
159
|
-
const response = await mf.dispatchFetch('http://sandbox/execute');
|
|
160
|
-
const result = await response.json();
|
|
161
|
-
return {
|
|
162
|
-
...result,
|
|
163
|
-
duration: Date.now() - start
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
finally {
|
|
167
|
-
await mf.dispose();
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
83
|
/**
|
|
171
84
|
* Create an evaluate function bound to a specific environment
|
|
172
85
|
*
|
package/dist/evaluate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evaluate.js","sourceRoot":"","sources":["../src/evaluate.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"evaluate.js","sourceRoot":"","sources":["../src/evaluate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAEzD;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,OAAwB,EACxB,GAAgB;IAEhB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IAExB,IAAI,CAAC;QACH,gFAAgF;QAChF,MAAM,MAAM,GAAG,GAAG,EAAE,MAAM,IAAI,GAAG,EAAE,MAAM,CAAA;QACzC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,EAAE;gBACR,KAAK,EACH,4KAA4K;gBAC9K,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;aAC7B,CAAA;QACH,CAAC;QAED,OAAO,MAAM,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;IAC1E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,IAAI,EAAE,EAAE;YACR,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YAC7D,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;SAC7B,CAAA;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,wBAAwB,CACrC,OAAwB,EACxB,MAAoB,EACpB,WAAoB,EACpB,KAAa;IAEb,MAAM,UAAU,GAAG,kBAAkB,CAAC;QACpC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,OAAO,EAAE,OAAO,CAAC,OAAO;KACzB,CAAC,CAAA;IACF,MAAM,EAAE,GAAG,WAAW,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;IAEzE,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QACzC,UAAU,EAAE,WAAW;QACvB,OAAO,EAAE;YACP,WAAW,EAAE,UAAU;SACxB;QACD,iBAAiB,EAAE,YAAY;QAC/B,2CAA2C;QAC3C,cAAc,EAAE,OAAO,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QACzD,QAAQ,EAAE;YACR,IAAI,EAAE,WAAW;SAClB;KACF,CAAC,CAAC,CAAA;IAEH,gFAAgF;IAChF,MAAM,UAAU,GAAG,MAAM,CAAC,aAAa,EAAE,CAAA;IACzC,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,wBAAwB,CAAC,CAAC,CAAA;IAC9E,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAmB,CAAA;IAExD,OAAO;QACL,GAAG,MAAM;QACT,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;KAC7B,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,eAAe,CAAC,GAAe;IAC7C,OAAO,CAAC,OAAwB,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;AAC7D,CAAC"}
|
package/dist/node.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Evaluate code in a sandboxed environment (Node.js version)
|
|
3
|
+
*
|
|
4
|
+
* Uses Cloudflare worker_loaders when available, falls back to Miniflare for local dev.
|
|
5
|
+
* For Workers-only builds, import from 'ai-evaluate' instead.
|
|
6
|
+
*/
|
|
7
|
+
import type { EvaluateOptions, EvaluateResult, SandboxEnv } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Evaluate code in a sandboxed worker (Node.js version with Miniflare fallback)
|
|
10
|
+
*/
|
|
11
|
+
export declare function evaluate(options: EvaluateOptions, env?: SandboxEnv): Promise<EvaluateResult>;
|
|
12
|
+
/**
|
|
13
|
+
* Create an evaluate function bound to a specific environment
|
|
14
|
+
*/
|
|
15
|
+
export declare function createEvaluator(env?: SandboxEnv): (options: EvaluateOptions) => Promise<EvaluateResult>;
|
|
16
|
+
export type { EvaluateOptions, EvaluateResult, SandboxEnv } from './types.js';
|
|
17
|
+
//# sourceMappingURL=node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAgB,UAAU,EAAE,MAAM,YAAY,CAAA;AAmC3F;;GAEG;AACH,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,eAAe,EACxB,GAAG,CAAC,EAAE,UAAU,GACf,OAAO,CAAC,cAAc,CAAC,CAkCzB;AA6GD;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,CAAC,EAAE,UAAU,IACtC,SAAS,eAAe,6BACjC;AAGD,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA"}
|