@larkup/sandbox 0.1.4 → 0.1.5
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/.turbo/turbo-test.log +13 -21
- package/.turbo/turbo-type-check.log +1 -1
- package/CHANGELOG.md +6 -0
- package/dist/local-runner.js +27 -1
- package/package.json +3 -3
- package/src/local-runner.test.ts +11 -1
- package/src/local-runner.ts +40 -9
package/.turbo/turbo-build.log
CHANGED
package/.turbo/turbo-test.log
CHANGED
|
@@ -1,26 +1,18 @@
|
|
|
1
1
|
|
|
2
|
-
> @larkup/sandbox@0.1.
|
|
2
|
+
> @larkup/sandbox@0.1.5 test /Users/abdelrahmanabounida/Desktop/my-ai-startup/larkup/larkup/packages/sandbox
|
|
3
3
|
> vitest run
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
RUN
|
|
7
|
-
|
|
8
|
-
✓ src/registry.test.ts (9 tests) 3ms
|
|
9
|
-
✓ src/providers/modal.test.ts (4 tests) 10ms
|
|
10
|
-
✓ src/providers/e2b.test.ts (9 tests) 5ms
|
|
11
|
-
✓ src/providers/browserbase.test.ts (5 tests) 4ms
|
|
12
|
-
✓ src/remote-exec.test.ts (14 tests) 12ms
|
|
13
|
-
✓ src/providers/northflank.test.ts (7 tests) 26ms
|
|
14
|
-
✓ src/providers/flyio.test.ts (6 tests) 4ms
|
|
15
|
-
✓ src/providers/daytona.test.ts (5 tests) 9ms
|
|
16
|
-
✓ src/local-runner.test.ts (1 test) 191ms
|
|
17
|
-
✓ src/providers/webcontainers.test.ts (3 tests) 5ms
|
|
18
|
-
✓ src/providers/vercel.test.ts (6 tests) 35ms
|
|
19
|
-
✓ src/sandbox-manager.test.ts (2 tests) 5ms
|
|
20
|
-
✓ src/providers/cloudflare.test.ts (6 tests) 9ms
|
|
21
|
-
|
|
22
|
-
Test Files 13 passed (13)
|
|
23
|
-
Tests 77 passed (77)
|
|
24
|
-
Start at 02:57:15
|
|
25
|
-
Duration 1.60s (transform 2.39s, setup 0ms, import 4.20s, tests 320ms, environment 2ms)
|
|
6
|
+
[1m[30m[46m RUN [49m[39m[22m [36mv4.1.11 [39m[90m/Users/abdelrahmanabounida/Desktop/my-ai-startup/larkup/larkup/packages/sandbox[39m
|
|
26
7
|
|
|
8
|
+
[32m✓[39m src/remote-exec.test.ts [2m([22m[2m14 tests[22m[2m)[22m[32m 116[2mms[22m[39m
|
|
9
|
+
[32m✓[39m src/providers/flyio.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 9[2mms[22m[39m
|
|
10
|
+
[32m✓[39m src/providers/modal.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 10[2mms[22m[39m
|
|
11
|
+
[32m✓[39m src/providers/daytona.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 4[2mms[22m[39m
|
|
12
|
+
[32m✓[39m src/providers/vercel.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 36[2mms[22m[39m
|
|
13
|
+
[32m✓[39m src/providers/e2b.test.ts [2m([22m[2m9 tests[22m[2m)[22m[32m 45[2mms[22m[39m
|
|
14
|
+
[32m✓[39m src/providers/northflank.test.ts [2m([22m[2m7 tests[22m[2m)[22m[32m 39[2mms[22m[39m
|
|
15
|
+
[32m✓[39m src/local-runner.test.ts [2m([22m[2m2 tests[22m[2m)[22m[33m 505[2mms[22m[39m
|
|
16
|
+
[33m[2m✓[22m[39m runs JavaScript without Docker and returns output artifacts [33m 359[2mms[22m[39m
|
|
17
|
+
[32m✓[39m src/providers/cloudflare.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 14[2mms[22m[39m
|
|
18
|
+
ELIFECYCLE Test failed. See above for more details.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @larkup/sandbox
|
|
2
2
|
|
|
3
|
+
## 0.1.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 848cc4c: Route spreadsheet questions through structured table queries before optional code analysis, validate local Python analysis dependencies before exposing code tools, and index every non-empty Excel worksheet as a separate dataset.
|
|
8
|
+
|
|
3
9
|
## 0.1.4
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/dist/local-runner.js
CHANGED
|
@@ -5,6 +5,10 @@ import path from 'node:path';
|
|
|
5
5
|
import { spawn } from 'node:child_process';
|
|
6
6
|
import { getMimeType } from './mime.js';
|
|
7
7
|
let pythonCommand;
|
|
8
|
+
// Keep this list in sync with the capabilities advertised by executeAnalysis
|
|
9
|
+
// and analyzeCorpusWithCode. A bare Python installation is not an analysis
|
|
10
|
+
// runtime, so it must not make those tools appear available.
|
|
11
|
+
const ANALYSIS_PYTHON_MODULES = ['numpy', 'pandas', 'matplotlib', 'scipy', 'sklearn', 'seaborn'];
|
|
8
12
|
function run(command, args, cwd, timeoutMs = 10_000) {
|
|
9
13
|
return new Promise((resolve, reject) => {
|
|
10
14
|
const child = spawn(command.executable, [...command.args, ...args], {
|
|
@@ -38,7 +42,7 @@ function run(command, args, cwd, timeoutMs = 10_000) {
|
|
|
38
42
|
resolve({
|
|
39
43
|
stdout,
|
|
40
44
|
stderr: timedOut ? `${stderr}\nExecution timed out.`.trim() : stderr,
|
|
41
|
-
exitCode: timedOut ? 124 : code ?? 1,
|
|
45
|
+
exitCode: timedOut ? 124 : (code ?? 1),
|
|
42
46
|
});
|
|
43
47
|
});
|
|
44
48
|
});
|
|
@@ -115,6 +119,28 @@ export async function checkLocalRuntime() {
|
|
|
115
119
|
error: 'Local code execution needs Python 3. Install Python or choose Docker or a remote sandbox provider.',
|
|
116
120
|
};
|
|
117
121
|
}
|
|
122
|
+
try {
|
|
123
|
+
const dependencyCheck = await run(python, [
|
|
124
|
+
'-c',
|
|
125
|
+
`import importlib.util\nmodules = ${JSON.stringify(ANALYSIS_PYTHON_MODULES)}\nmissing = [name for name in modules if importlib.util.find_spec(name) is None]\nprint(','.join(missing))\nraise SystemExit(bool(missing))`,
|
|
126
|
+
]);
|
|
127
|
+
if (dependencyCheck.exitCode !== 0) {
|
|
128
|
+
const missing = dependencyCheck.stdout.trim() || 'required analysis packages';
|
|
129
|
+
return {
|
|
130
|
+
status: 'error',
|
|
131
|
+
backend: 'local',
|
|
132
|
+
error: `Local Python is missing ${missing}. Install the Larkup analysis dependencies ` +
|
|
133
|
+
`(for example: pip install ${ANALYSIS_PYTHON_MODULES.join(' ')}) or choose Docker or a remote sandbox provider.`,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return {
|
|
139
|
+
status: 'error',
|
|
140
|
+
backend: 'local',
|
|
141
|
+
error: 'Larkup could not verify the Python analysis dependencies. Choose Docker or a remote sandbox provider.',
|
|
142
|
+
};
|
|
143
|
+
}
|
|
118
144
|
return { status: 'ready', backend: 'local' };
|
|
119
145
|
}
|
|
120
146
|
/** Executes trusted code in a temporary host workspace and collects its output. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@larkup/sandbox",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"optionalDependencies": {
|
|
41
41
|
"e2b": "^2.39.0",
|
|
42
42
|
"@vercel/sandbox": "^3.0.0",
|
|
43
|
-
"modal": "^0.
|
|
44
|
-
"@daytona/sdk": "^0.
|
|
43
|
+
"modal": "^0.10.0",
|
|
44
|
+
"@daytona/sdk": "^0.207.0",
|
|
45
45
|
"@browserbasehq/sdk": "^2.17.0",
|
|
46
46
|
"playwright-core": "^1.62.1",
|
|
47
47
|
"@fly/sprites": "^0.2.0",
|
package/src/local-runner.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { executeLocally } from './local-runner.js';
|
|
2
|
+
import { checkLocalRuntime, executeLocally } from './local-runner.js';
|
|
3
3
|
|
|
4
4
|
describe('executeLocally', () => {
|
|
5
5
|
it('runs JavaScript without Docker and returns output artifacts', async () => {
|
|
@@ -19,4 +19,14 @@ describe('executeLocally', () => {
|
|
|
19
19
|
expect.objectContaining({ name: 'result.txt', mimeType: 'text/plain' }),
|
|
20
20
|
]);
|
|
21
21
|
});
|
|
22
|
+
|
|
23
|
+
it('does not mark a bare Python installation as analysis-ready', async () => {
|
|
24
|
+
const health = await checkLocalRuntime();
|
|
25
|
+
expect(health.backend).toBe('local');
|
|
26
|
+
if (health.status === 'ready') {
|
|
27
|
+
expect(health.error).toBeUndefined();
|
|
28
|
+
} else {
|
|
29
|
+
expect(health.error).toMatch(/Python|analysis dependenc/i);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
22
32
|
});
|
package/src/local-runner.ts
CHANGED
|
@@ -16,6 +16,11 @@ type Command = { executable: string; args: string[] };
|
|
|
16
16
|
|
|
17
17
|
let pythonCommand: Command | null | undefined;
|
|
18
18
|
|
|
19
|
+
// Keep this list in sync with the capabilities advertised by executeAnalysis
|
|
20
|
+
// and analyzeCorpusWithCode. A bare Python installation is not an analysis
|
|
21
|
+
// runtime, so it must not make those tools appear available.
|
|
22
|
+
const ANALYSIS_PYTHON_MODULES = ['numpy', 'pandas', 'matplotlib', 'scipy', 'sklearn', 'seaborn'];
|
|
23
|
+
|
|
19
24
|
function run(command: Command, args: string[], cwd?: string, timeoutMs = 10_000) {
|
|
20
25
|
return new Promise<{ stdout: string; stderr: string; exitCode: number }>((resolve, reject) => {
|
|
21
26
|
const child = spawn(command.executable, [...command.args, ...args], {
|
|
@@ -49,7 +54,7 @@ function run(command: Command, args: string[], cwd?: string, timeoutMs = 10_000)
|
|
|
49
54
|
resolve({
|
|
50
55
|
stdout,
|
|
51
56
|
stderr: timedOut ? `${stderr}\nExecution timed out.`.trim() : stderr,
|
|
52
|
-
exitCode: timedOut ? 124 : code ?? 1,
|
|
57
|
+
exitCode: timedOut ? 124 : (code ?? 1),
|
|
53
58
|
});
|
|
54
59
|
});
|
|
55
60
|
});
|
|
@@ -60,14 +65,14 @@ async function resolvePython(): Promise<Command | null> {
|
|
|
60
65
|
const candidates: Command[] = process.env.LARKUP_PYTHON
|
|
61
66
|
? [{ executable: process.env.LARKUP_PYTHON, args: [] }]
|
|
62
67
|
: process.platform === 'win32'
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
? [
|
|
69
|
+
{ executable: 'py', args: ['-3'] },
|
|
70
|
+
{ executable: 'python', args: [] },
|
|
71
|
+
]
|
|
72
|
+
: [
|
|
73
|
+
{ executable: 'python3', args: [] },
|
|
74
|
+
{ executable: 'python', args: [] },
|
|
75
|
+
];
|
|
71
76
|
|
|
72
77
|
for (const candidate of candidates) {
|
|
73
78
|
try {
|
|
@@ -134,6 +139,32 @@ export async function checkLocalRuntime(): Promise<SandboxHealthCheck> {
|
|
|
134
139
|
'Local code execution needs Python 3. Install Python or choose Docker or a remote sandbox provider.',
|
|
135
140
|
};
|
|
136
141
|
}
|
|
142
|
+
|
|
143
|
+
try {
|
|
144
|
+
const dependencyCheck = await run(python, [
|
|
145
|
+
'-c',
|
|
146
|
+
`import importlib.util\nmodules = ${JSON.stringify(
|
|
147
|
+
ANALYSIS_PYTHON_MODULES,
|
|
148
|
+
)}\nmissing = [name for name in modules if importlib.util.find_spec(name) is None]\nprint(','.join(missing))\nraise SystemExit(bool(missing))`,
|
|
149
|
+
]);
|
|
150
|
+
if (dependencyCheck.exitCode !== 0) {
|
|
151
|
+
const missing = dependencyCheck.stdout.trim() || 'required analysis packages';
|
|
152
|
+
return {
|
|
153
|
+
status: 'error',
|
|
154
|
+
backend: 'local',
|
|
155
|
+
error:
|
|
156
|
+
`Local Python is missing ${missing}. Install the Larkup analysis dependencies ` +
|
|
157
|
+
`(for example: pip install ${ANALYSIS_PYTHON_MODULES.join(' ')}) or choose Docker or a remote sandbox provider.`,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
} catch {
|
|
161
|
+
return {
|
|
162
|
+
status: 'error',
|
|
163
|
+
backend: 'local',
|
|
164
|
+
error:
|
|
165
|
+
'Larkup could not verify the Python analysis dependencies. Choose Docker or a remote sandbox provider.',
|
|
166
|
+
};
|
|
167
|
+
}
|
|
137
168
|
return { status: 'ready', backend: 'local' };
|
|
138
169
|
}
|
|
139
170
|
|