@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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @larkup/sandbox@0.1.4 build /Users/abdelrahmanabounida/Desktop/my-ai-startup/larkup/larkup/packages/sandbox
2
+ > @larkup/sandbox@0.1.5 build /Users/abdelrahmanabounida/Desktop/my-ai-startup/larkup/larkup/packages/sandbox
3
3
  > tsc -p tsconfig.build.json --outDir dist
4
4
 
@@ -1,26 +1,18 @@
1
1
 
2
- > @larkup/sandbox@0.1.4 test /Users/abdelrahmanabounida/Desktop/my-ai-startup/larkup/larkup/packages/sandbox
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 v4.1.11 /Users/abdelrahmanabounida/Desktop/my-ai-startup/larkup/larkup/packages/sandbox
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
+  RUN  v4.1.11 /Users/abdelrahmanabounida/Desktop/my-ai-startup/larkup/larkup/packages/sandbox
26
7
 
8
+ ✓ src/remote-exec.test.ts (14 tests) 116ms
9
+ ✓ src/providers/flyio.test.ts (6 tests) 9ms
10
+ ✓ src/providers/modal.test.ts (4 tests) 10ms
11
+ ✓ src/providers/daytona.test.ts (5 tests) 4ms
12
+ ✓ src/providers/vercel.test.ts (6 tests) 36ms
13
+ ✓ src/providers/e2b.test.ts (9 tests) 45ms
14
+ ✓ src/providers/northflank.test.ts (7 tests) 39ms
15
+ ✓ src/local-runner.test.ts (2 tests) 505ms
16
+ ✓ runs JavaScript without Docker and returns output artifacts  359ms
17
+ ✓ src/providers/cloudflare.test.ts (6 tests) 14ms
18
+  ELIFECYCLE  Test failed. See above for more details.
@@ -1,4 +1,4 @@
1
1
 
2
- > @larkup/sandbox@0.1.4 type-check /Users/abdelrahmanabounida/Desktop/my-ai-startup/larkup/larkup/packages/sandbox
2
+ > @larkup/sandbox@0.1.5 type-check /Users/abdelrahmanabounida/Desktop/my-ai-startup/larkup/larkup/packages/sandbox
3
3
  > tsc --noEmit
4
4
 
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
@@ -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.4",
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.9.0",
44
- "@daytona/sdk": "^0.204.1",
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",
@@ -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
  });
@@ -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
- { executable: 'py', args: ['-3'] },
65
- { executable: 'python', args: [] },
66
- ]
67
- : [
68
- { executable: 'python3', args: [] },
69
- { executable: 'python', args: [] },
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