@mastra/daytona 0.9.1 → 0.10.0-alpha.1
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 +9 -343
- package/dist/index.cjs +13 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +13 -4
- package/dist/index.js.map +1 -1
- package/dist/sandbox/index.d.ts +8 -1
- package/dist/sandbox/index.d.ts.map +1 -1
- package/dist/sandbox/process-manager.d.ts.map +1 -1
- package/package.json +9 -10
- package/CHANGELOG.md +0 -773
package/README.md
CHANGED
|
@@ -4,13 +4,10 @@ Daytona cloud sandbox provider for [Mastra](https://mastra.ai) workspaces.
|
|
|
4
4
|
|
|
5
5
|
Implements the `WorkspaceSandbox` interface using [Daytona](https://www.daytona.io/) sandboxes. Supports multiple runtimes, resource configuration, volumes, snapshots, streaming output, sandbox reconnection, and filesystem mounting (S3, GCS, Azure Blob).
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Installation
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
# For filesystem mounting (optional)
|
|
13
|
-
pnpm add @mastra/s3 @mastra/gcs @mastra/azure
|
|
10
|
+
npm install @mastra/daytona
|
|
14
11
|
```
|
|
15
12
|
|
|
16
13
|
## Usage
|
|
@@ -35,346 +32,15 @@ console.log(result.stdout); // "Hello!"
|
|
|
35
32
|
await workspace.destroy();
|
|
36
33
|
```
|
|
37
34
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
Use a pre-built snapshot to skip environment setup time:
|
|
41
|
-
|
|
42
|
-
```typescript
|
|
43
|
-
const sandbox = new DaytonaSandbox({
|
|
44
|
-
snapshot: 'my-snapshot-id',
|
|
45
|
-
timeout: 60_000,
|
|
46
|
-
});
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### Custom image with resources
|
|
50
|
-
|
|
51
|
-
Use a custom Docker image with specific resource allocation:
|
|
52
|
-
|
|
53
|
-
```typescript
|
|
54
|
-
const sandbox = new DaytonaSandbox({
|
|
55
|
-
image: 'node:20-slim',
|
|
56
|
-
resources: { cpu: 2, memory: 4, disk: 6 },
|
|
57
|
-
language: 'typescript',
|
|
58
|
-
});
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### Ephemeral sandbox
|
|
62
|
-
|
|
63
|
-
For one-shot tasks — sandbox is deleted immediately on stop:
|
|
64
|
-
|
|
65
|
-
```typescript
|
|
66
|
-
const sandbox = new DaytonaSandbox({
|
|
67
|
-
ephemeral: true,
|
|
68
|
-
language: 'python',
|
|
69
|
-
});
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
### Streaming output
|
|
35
|
+
## Documentation
|
|
73
36
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
```typescript
|
|
77
|
-
await sandbox.executeCommand('bash', ['-c', 'for i in 1 2 3; do echo "line $i"; sleep 1; done'], {
|
|
78
|
-
onStdout: chunk => process.stdout.write(chunk),
|
|
79
|
-
onStderr: chunk => process.stderr.write(chunk),
|
|
80
|
-
});
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### Reconnection
|
|
84
|
-
|
|
85
|
-
Reconnect to an existing sandbox by providing the same `id`. The sandbox resumes with its files and state intact:
|
|
86
|
-
|
|
87
|
-
```typescript
|
|
88
|
-
const sandbox = new DaytonaSandbox({ id: 'my-persistent-sandbox' });
|
|
37
|
+
- [Daytona integration guide](https://mastra.ai/integrations/sandboxes/daytona)
|
|
38
|
+
- [Workspace documentation](https://mastra.ai/docs/mastra-platform/workspaces)
|
|
89
39
|
|
|
90
|
-
|
|
91
|
-
await sandbox._start();
|
|
92
|
-
await sandbox.executeCommand('sh', ['-c', 'echo "session 1" > /tmp/state.txt']);
|
|
93
|
-
await sandbox._stop();
|
|
40
|
+
## Changelog
|
|
94
41
|
|
|
95
|
-
|
|
96
|
-
const sandbox2 = new DaytonaSandbox({ id: 'my-persistent-sandbox' });
|
|
97
|
-
await sandbox2._start();
|
|
98
|
-
const result = await sandbox2.executeCommand('cat', ['/tmp/state.txt']);
|
|
99
|
-
console.log(result.stdout); // "session 1"
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### Filesystem mounting
|
|
103
|
-
|
|
104
|
-
Mount S3, GCS, or Azure Blob containers as local directories inside the sandbox.
|
|
105
|
-
|
|
106
|
-
#### Via workspace mounts config
|
|
107
|
-
|
|
108
|
-
The simplest way — filesystems are mounted automatically when the sandbox starts:
|
|
109
|
-
|
|
110
|
-
```typescript
|
|
111
|
-
import { Workspace } from '@mastra/core/workspace';
|
|
112
|
-
import { DaytonaSandbox } from '@mastra/daytona';
|
|
113
|
-
import { GCSFilesystem } from '@mastra/gcs';
|
|
114
|
-
import { S3Filesystem } from '@mastra/s3';
|
|
115
|
-
import { AzureBlobFilesystem } from '@mastra/azure/blob';
|
|
116
|
-
|
|
117
|
-
const workspace = new Workspace({
|
|
118
|
-
mounts: {
|
|
119
|
-
'/s3-data': new S3Filesystem({
|
|
120
|
-
bucket: process.env.S3_BUCKET!,
|
|
121
|
-
region: 'auto',
|
|
122
|
-
accessKeyId: process.env.S3_ACCESS_KEY_ID,
|
|
123
|
-
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
|
|
124
|
-
endpoint: process.env.S3_ENDPOINT, // e.g. https://<account-id>.r2.cloudflarestorage.com
|
|
125
|
-
}),
|
|
126
|
-
'/gcs-data': new GCSFilesystem({
|
|
127
|
-
bucket: process.env.GCS_BUCKET!,
|
|
128
|
-
projectId: 'my-project-id',
|
|
129
|
-
credentials: JSON.parse(process.env.GCS_SERVICE_ACCOUNT_KEY!),
|
|
130
|
-
}),
|
|
131
|
-
'/azure-data': new AzureBlobFilesystem({
|
|
132
|
-
container: process.env.AZURE_STORAGE_CONTAINER!,
|
|
133
|
-
connectionString: process.env.AZURE_STORAGE_CONNECTION_STRING,
|
|
134
|
-
prefix: 'workspace/data',
|
|
135
|
-
}),
|
|
136
|
-
},
|
|
137
|
-
sandbox: new DaytonaSandbox({ language: 'python' }),
|
|
138
|
-
});
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
#### Via sandbox.mount()
|
|
142
|
-
|
|
143
|
-
Mount manually at any point after the sandbox has started:
|
|
144
|
-
|
|
145
|
-
#### S3
|
|
146
|
-
|
|
147
|
-
```typescript
|
|
148
|
-
import { DaytonaSandbox } from '@mastra/daytona';
|
|
149
|
-
import { S3Filesystem } from '@mastra/s3';
|
|
150
|
-
|
|
151
|
-
const sandbox = new DaytonaSandbox({ language: 'python' });
|
|
152
|
-
await sandbox._start();
|
|
153
|
-
|
|
154
|
-
await sandbox.mount(
|
|
155
|
-
new S3Filesystem({
|
|
156
|
-
bucket: process.env.S3_BUCKET!,
|
|
157
|
-
region: 'us-east-1',
|
|
158
|
-
accessKeyId: process.env.S3_ACCESS_KEY_ID,
|
|
159
|
-
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
|
|
160
|
-
}),
|
|
161
|
-
'/data',
|
|
162
|
-
);
|
|
163
|
-
|
|
164
|
-
// Files in the bucket are now accessible at /data
|
|
165
|
-
const result = await sandbox.executeCommand('ls', ['/data']);
|
|
166
|
-
console.log(result.stdout);
|
|
167
|
-
|
|
168
|
-
await sandbox._stop(); // Unmounts automatically before stopping
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
#### S3-compatible (Cloudflare R2, MinIO)
|
|
172
|
-
|
|
173
|
-
```typescript
|
|
174
|
-
import { S3Filesystem } from '@mastra/s3';
|
|
175
|
-
|
|
176
|
-
await sandbox.mount(
|
|
177
|
-
new S3Filesystem({
|
|
178
|
-
bucket: process.env.S3_BUCKET!,
|
|
179
|
-
region: 'auto',
|
|
180
|
-
accessKeyId: process.env.S3_ACCESS_KEY_ID,
|
|
181
|
-
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY,
|
|
182
|
-
endpoint: process.env.S3_ENDPOINT, // e.g. https://<account-id>.r2.cloudflarestorage.com
|
|
183
|
-
}),
|
|
184
|
-
'/data',
|
|
185
|
-
);
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
#### GCS
|
|
189
|
-
|
|
190
|
-
```typescript
|
|
191
|
-
import { GCSFilesystem } from '@mastra/gcs';
|
|
192
|
-
|
|
193
|
-
await sandbox.mount(
|
|
194
|
-
new GCSFilesystem({
|
|
195
|
-
bucket: process.env.GCS_BUCKET!,
|
|
196
|
-
projectId: 'my-project-id',
|
|
197
|
-
credentials: JSON.parse(process.env.GCS_SERVICE_ACCOUNT_KEY!),
|
|
198
|
-
}),
|
|
199
|
-
'/data',
|
|
200
|
-
);
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
#### Azure Blob
|
|
204
|
-
|
|
205
|
-
```typescript
|
|
206
|
-
import { AzureBlobFilesystem } from '@mastra/azure/blob';
|
|
207
|
-
|
|
208
|
-
await sandbox.mount(
|
|
209
|
-
new AzureBlobFilesystem({
|
|
210
|
-
container: process.env.AZURE_STORAGE_CONTAINER!,
|
|
211
|
-
connectionString: process.env.AZURE_STORAGE_CONNECTION_STRING,
|
|
212
|
-
prefix: 'workspace/data',
|
|
213
|
-
}),
|
|
214
|
-
'/data',
|
|
215
|
-
);
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
### Network isolation
|
|
219
|
-
|
|
220
|
-
Restrict outbound network access:
|
|
221
|
-
|
|
222
|
-
```typescript
|
|
223
|
-
const sandbox = new DaytonaSandbox({
|
|
224
|
-
networkBlockAll: true,
|
|
225
|
-
networkAllowList: '10.0.0.0/8,192.168.0.0/16',
|
|
226
|
-
});
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
### With Agent
|
|
230
|
-
|
|
231
|
-
Wire a Daytona sandbox into a Mastra agent to give it code execution in an isolated sandbox:
|
|
232
|
-
|
|
233
|
-
```typescript
|
|
234
|
-
import { Agent } from '@mastra/core/agent';
|
|
235
|
-
import { Workspace } from '@mastra/core/workspace';
|
|
236
|
-
import { DaytonaSandbox } from '@mastra/daytona';
|
|
237
|
-
|
|
238
|
-
const sandbox = new DaytonaSandbox({
|
|
239
|
-
language: 'typescript',
|
|
240
|
-
timeout: 120_000,
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
const workspace = new Workspace({ sandbox });
|
|
244
|
-
|
|
245
|
-
const agent = new Agent({
|
|
246
|
-
id: 'code-agent',
|
|
247
|
-
name: 'Code Agent',
|
|
248
|
-
instructions: 'You are a coding assistant working in this workspace.',
|
|
249
|
-
model: 'anthropic/claude-sonnet-4-6',
|
|
250
|
-
workspace,
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
const response = await agent.generate('Print "Hello, world!" and show the current working directory.');
|
|
254
|
-
|
|
255
|
-
console.log(response.text);
|
|
256
|
-
// I'll run both commands simultaneously!
|
|
257
|
-
//
|
|
258
|
-
// Here are the results:
|
|
259
|
-
//
|
|
260
|
-
// 1. **Hello, world!** — Successfully printed the message.
|
|
261
|
-
// 2. **Current Working Directory** — `/home/daytona`
|
|
262
|
-
//
|
|
263
|
-
// Both commands ran in parallel and completed successfully!
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
## Configuration
|
|
267
|
-
|
|
268
|
-
| Option | Type | Default | Description |
|
|
269
|
-
| --------------------- | --------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
270
|
-
| `id` | `string` | auto-generated | Sandbox identifier |
|
|
271
|
-
| `apiKey` | `string` | `DAYTONA_API_KEY` env | API key |
|
|
272
|
-
| `apiUrl` | `string` | `DAYTONA_API_URL` env | API endpoint |
|
|
273
|
-
| `target` | `string` | `DAYTONA_TARGET` env | Runner region |
|
|
274
|
-
| `timeout` | `number` | `300000` | Default execution timeout (ms) |
|
|
275
|
-
| `language` | `string` | `'typescript'` | Runtime language |
|
|
276
|
-
| `snapshot` | `string` | — | Pre-built snapshot ID. Takes precedence over `image`. |
|
|
277
|
-
| `image` | `string` | — | Docker image for sandbox creation. Triggers image-based creation when set. Can be combined with `resources`. Ignored when `snapshot` is set. |
|
|
278
|
-
| `resources` | `object` | SDK defaults | `{ cpu, memory, disk }`. Only used with `image`. |
|
|
279
|
-
| `env` | `object` | `{}` | Environment variables |
|
|
280
|
-
| `labels` | `object` | `{}` | Custom metadata labels |
|
|
281
|
-
| `name` | `string` | sandbox `id` | Sandbox display name |
|
|
282
|
-
| `user` | `string` | `daytona` | OS user to run commands as |
|
|
283
|
-
| `public` | `boolean` | `false` | Make port previews public |
|
|
284
|
-
| `ephemeral` | `boolean` | `false` | Delete sandbox immediately on stop |
|
|
285
|
-
| `autoStopInterval` | `number` | `15` | Auto-stop interval in minutes (0 = disabled) |
|
|
286
|
-
| `autoArchiveInterval` | `number` | `7 days` | Auto-archive interval in minutes (0 = 7 days) |
|
|
287
|
-
| `autoDeleteInterval` | `number` | `disabled` | Auto-delete interval in minutes (negative = disabled, 0 = delete on stop) |
|
|
288
|
-
| `volumes` | `array` | — | `[{ volumeId, mountPath }]` |
|
|
289
|
-
| `networkBlockAll` | `boolean` | `false` | Block all network access |
|
|
290
|
-
| `networkAllowList` | `string` | — | Comma-separated allowed CIDR addresses |
|
|
291
|
-
|
|
292
|
-
## Mount Configuration
|
|
293
|
-
|
|
294
|
-
Pass `S3Filesystem`, `GCSFilesystem`, or `AzureBlobFilesystem` instances via the workspace `mounts` config or directly to `sandbox.mount()`.
|
|
295
|
-
|
|
296
|
-
### S3 environment variables
|
|
297
|
-
|
|
298
|
-
| Variable | Description |
|
|
299
|
-
| ---------------------- | --------------------------------- |
|
|
300
|
-
| `S3_BUCKET` | Bucket name |
|
|
301
|
-
| `S3_REGION` | AWS region or `auto` for R2/MinIO |
|
|
302
|
-
| `S3_ACCESS_KEY_ID` | Access key ID |
|
|
303
|
-
| `S3_SECRET_ACCESS_KEY` | Secret access key |
|
|
304
|
-
| `S3_ENDPOINT` | Endpoint URL (S3-compatible only) |
|
|
305
|
-
|
|
306
|
-
### GCS environment variables
|
|
307
|
-
|
|
308
|
-
| Variable | Description |
|
|
309
|
-
| ------------------------- | ------------------------------------------------------- |
|
|
310
|
-
| `GCS_BUCKET` | Bucket name |
|
|
311
|
-
| `GCS_SERVICE_ACCOUNT_KEY` | Service account key JSON (full JSON string, not a path) |
|
|
312
|
-
|
|
313
|
-
### Azure Blob environment variables
|
|
314
|
-
|
|
315
|
-
| Variable | Description |
|
|
316
|
-
| --------------------------------- | ------------------------- |
|
|
317
|
-
| `AZURE_STORAGE_CONTAINER` | Container name |
|
|
318
|
-
| `AZURE_STORAGE_CONNECTION_STRING` | Storage connection string |
|
|
319
|
-
|
|
320
|
-
### Reducing cold start latency with a snapshot
|
|
321
|
-
|
|
322
|
-
By default, `s3fs`, `gcsfuse`, and `blobfuse2` are installed at first mount, which adds startup time. To eliminate this, prebake them into a Daytona snapshot and pass the snapshot name via the `snapshot` option.
|
|
323
|
-
|
|
324
|
-
Create the snapshot once:
|
|
325
|
-
|
|
326
|
-
```typescript
|
|
327
|
-
import { Daytona, Image } from '@daytonaio/sdk';
|
|
328
|
-
|
|
329
|
-
const template = Image.base('daytonaio/sandbox')
|
|
330
|
-
.runCommands('sudo apt-get update -qq')
|
|
331
|
-
.runCommands('sudo apt-get install -y s3fs')
|
|
332
|
-
// gcsfuse requires the Google Cloud apt repository
|
|
333
|
-
.runCommands(
|
|
334
|
-
'sudo mkdir -p /etc/apt/keyrings && ' +
|
|
335
|
-
'curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg -o /tmp/gcsfuse-key.gpg && ' +
|
|
336
|
-
'sudo gpg --batch --yes --dearmor -o /etc/apt/keyrings/gcsfuse.gpg /tmp/gcsfuse-key.gpg && ' +
|
|
337
|
-
// Use gcsfuse-jammy for Ubuntu, gcsfuse-bookworm for Debian
|
|
338
|
-
'echo "deb [signed-by=/etc/apt/keyrings/gcsfuse.gpg] https://packages.cloud.google.com/apt gcsfuse-jammy main" | sudo tee /etc/apt/sources.list.d/gcsfuse.list',
|
|
339
|
-
)
|
|
340
|
-
.runCommands('sudo apt-get update -qq && sudo apt-get install -y gcsfuse');
|
|
341
|
-
|
|
342
|
-
const daytona = new Daytona();
|
|
343
|
-
await daytona.snapshot.create(
|
|
344
|
-
{
|
|
345
|
-
name: 'cloud-fs-mounting',
|
|
346
|
-
image: template,
|
|
347
|
-
},
|
|
348
|
-
{ onLogs: console.log },
|
|
349
|
-
);
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
If you use Azure Blob mounts, also pre-install `blobfuse2` in the snapshot using Azure's supported package for your base image. See Azure's [BlobFuse2 installation guide](https://learn.microsoft.com/en-us/azure/storage/blobs/blobfuse2-how-to-deploy) for supported install options.
|
|
353
|
-
|
|
354
|
-
Then use the snapshot name in your sandbox config:
|
|
355
|
-
|
|
356
|
-
```typescript
|
|
357
|
-
const workspace = new Workspace({
|
|
358
|
-
mounts: {
|
|
359
|
-
'/s3-data': new S3Filesystem({/* ... */}),
|
|
360
|
-
'/gcs-data': new GCSFilesystem({/* ... */}),
|
|
361
|
-
},
|
|
362
|
-
sandbox: new DaytonaSandbox({ snapshot: 'cloud-fs-mounting' }),
|
|
363
|
-
});
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
## Direct SDK Access
|
|
367
|
-
|
|
368
|
-
Access the underlying Daytona `Sandbox` instance for filesystem, git, and other operations not exposed through WorkspaceSandbox:
|
|
369
|
-
|
|
370
|
-
```typescript
|
|
371
|
-
const daytonaSandbox = sandbox.instance;
|
|
372
|
-
|
|
373
|
-
await daytonaSandbox.fs.uploadFile(Buffer.from('data'), '/tmp/file.txt');
|
|
374
|
-
|
|
375
|
-
await daytonaSandbox.git.clone('https://github.com/org/repo', '/workspace/repo');
|
|
376
|
-
```
|
|
42
|
+
See the [package changelog](https://github.com/mastra-ai/mastra/blob/main/workspaces/daytona/CHANGELOG.md) for version history and release notes.
|
|
377
43
|
|
|
378
|
-
##
|
|
44
|
+
## Support
|
|
379
45
|
|
|
380
|
-
|
|
46
|
+
We have an [open community Discord](https://discord.gg/mastra-ai). Come and say hello and let us know if you have any questions or need any help getting things running.
|
package/dist/index.cjs
CHANGED
|
@@ -532,7 +532,7 @@ var DaytonaProcessManager = class extends _mastra_core_workspace.SandboxProcessM
|
|
|
532
532
|
const effectiveOptions = {
|
|
533
533
|
...options,
|
|
534
534
|
timeout: options.timeout ?? this._defaultTimeout,
|
|
535
|
-
cwd: options.cwd ?? this.sandbox.mounts?.entries?.keys().next().value
|
|
535
|
+
cwd: options.cwd ?? this.sandbox.explicitWorkingDirectory ?? this.sandbox.mounts?.entries?.keys().next().value
|
|
536
536
|
};
|
|
537
537
|
const envs = Object.fromEntries(Object.entries(effectiveOptions.env ?? {}).filter((entry) => entry[1] !== void 0));
|
|
538
538
|
const sessionCommand = buildSpawnCommand(command, effectiveOptions.cwd, envs);
|
|
@@ -690,7 +690,6 @@ var DaytonaSandbox = class DaytonaSandbox extends _mastra_core_workspace.MastraS
|
|
|
690
690
|
_daytona = null;
|
|
691
691
|
_sandbox = null;
|
|
692
692
|
_createdAt = null;
|
|
693
|
-
_workingDir = null;
|
|
694
693
|
_isRetrying = false;
|
|
695
694
|
_computerUseStarted = null;
|
|
696
695
|
computerUseAutoStart;
|
|
@@ -716,6 +715,14 @@ var DaytonaSandbox = class DaytonaSandbox extends _mastra_core_workspace.MastraS
|
|
|
716
715
|
secrets;
|
|
717
716
|
connectionOpts;
|
|
718
717
|
_constructorOptions;
|
|
718
|
+
/**
|
|
719
|
+
* The `workingDirectory` option as explicitly configured, as distinct from
|
|
720
|
+
* the probe-filled base field. The process manager's cwd fallback uses only
|
|
721
|
+
* this value so the runtime probe (which just reports the session home)
|
|
722
|
+
* never displaces the FUSE-mount default for relative paths.
|
|
723
|
+
* @internal
|
|
724
|
+
*/
|
|
725
|
+
explicitWorkingDirectory;
|
|
719
726
|
constructor(options = {}) {
|
|
720
727
|
super({
|
|
721
728
|
...options,
|
|
@@ -723,6 +730,7 @@ var DaytonaSandbox = class DaytonaSandbox extends _mastra_core_workspace.MastraS
|
|
|
723
730
|
processes: new DaytonaProcessManager({ defaultTimeout: options.timeout ?? 3e5 })
|
|
724
731
|
});
|
|
725
732
|
this.id = options.id ?? this.generateId();
|
|
733
|
+
this.explicitWorkingDirectory = options.workingDirectory;
|
|
726
734
|
this.timeout = options.timeout ?? 3e5;
|
|
727
735
|
this.language = options.language ?? "typescript";
|
|
728
736
|
this.resources = options.resources;
|
|
@@ -948,7 +956,7 @@ var DaytonaSandbox = class DaytonaSandbox extends _mastra_core_workspace.MastraS
|
|
|
948
956
|
const mountCount = this.mounts.entries.size;
|
|
949
957
|
const mountInfo = mountCount > 0 ? ` ${mountCount} filesystem(s) mounted via FUSE.` : "";
|
|
950
958
|
parts.push(`Cloud sandbox with isolated execution (${this.language} runtime).${mountInfo}`);
|
|
951
|
-
if (this.
|
|
959
|
+
if (this.workingDirectory) parts.push(`Default working directory: ${this.workingDirectory}.`);
|
|
952
960
|
parts.push(`Command timeout: ${Math.ceil(this.timeout / 1e3)}s.`);
|
|
953
961
|
parts.push(`Running as user: ${this.sandboxUser ?? "daytona"}.`);
|
|
954
962
|
if (this.volumeConfigs.length > 0) parts.push(`${this.volumeConfigs.length} volume(s) attached.`);
|
|
@@ -1363,10 +1371,11 @@ var DaytonaSandbox = class DaytonaSandbox extends _mastra_core_workspace.MastraS
|
|
|
1363
1371
|
*/
|
|
1364
1372
|
async detectWorkingDir() {
|
|
1365
1373
|
if (!this._sandbox) return;
|
|
1374
|
+
if (this.explicitWorkingDirectory !== void 0) return;
|
|
1366
1375
|
try {
|
|
1367
1376
|
const dir = (await runCommand(this._sandbox, "pwd", { timeout: MOUNT_COMMAND_TIMEOUT_MS })).output?.trim();
|
|
1368
1377
|
if (dir) {
|
|
1369
|
-
this.
|
|
1378
|
+
this.setWorkingDirectory(dir);
|
|
1370
1379
|
this.logger.debug(`${LOG_PREFIX} Detected working directory: ${dir}`);
|
|
1371
1380
|
}
|
|
1372
1381
|
} catch {
|