@mastra/daytona 0.9.0-alpha.1 → 0.9.0-alpha.2
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/CHANGELOG.md +21 -0
- package/dist/index.cjs +102 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +102 -0
- package/dist/index.js.map +1 -1
- package/dist/sandbox/index.d.ts +53 -1
- package/dist/sandbox/index.d.ts.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @mastra/daytona
|
|
2
2
|
|
|
3
|
+
## 0.9.0-alpha.2
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Added computer-use support to `DaytonaSandbox`. Workspaces backed by Daytona can now take screenshots, control the mouse and keyboard, inspect the display, and open a noVNC viewer through the standard computer tools. ([#21701](https://github.com/mastra-ai/mastra/pull/21701))
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
const sandbox = new DaytonaSandbox();
|
|
11
|
+
await sandbox.start();
|
|
12
|
+
|
|
13
|
+
await sandbox.computer.leftClick(100, 200);
|
|
14
|
+
const screenshot = await sandbox.computer.screenshot();
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Desktop services start lazily on the first computer operation. Set `computerUse: false` to disable the capability or `computerUse: { autoStart: false }` to manage those services directly.
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- Updated dependencies [[`48ef1f1`](https://github.com/mastra-ai/mastra/commit/48ef1f1d24eedafbb07f64e659a81b52b67b8bf6), [`63796ba`](https://github.com/mastra-ai/mastra/commit/63796ba0fda60253be17535e68f6bbbf1e6ffa09), [`3c19dce`](https://github.com/mastra-ai/mastra/commit/3c19dcef8e73062a80627a4927eae3ec11145afd)]:
|
|
22
|
+
- @mastra/core@1.62.0-alpha.12
|
|
23
|
+
|
|
3
24
|
## 0.9.0-alpha.1
|
|
4
25
|
|
|
5
26
|
### Minor Changes
|
package/dist/index.cjs
CHANGED
|
@@ -618,6 +618,8 @@ function validateMountPath(mountPath) {
|
|
|
618
618
|
}
|
|
619
619
|
/** Allowlist for marker filenames from ls output — e.g. "mount-abc123" */
|
|
620
620
|
const SAFE_MARKER_NAME = /^mount-[a-z0-9]+$/;
|
|
621
|
+
/** Default port of the noVNC web viewer started by Daytona computer use. */
|
|
622
|
+
const DEFAULT_NOVNC_PORT = 6080;
|
|
621
623
|
/** Patterns indicating the sandbox is dead/gone (@daytonaio/sdk@0.143.0). */
|
|
622
624
|
const SANDBOX_DEAD_PATTERNS = [
|
|
623
625
|
/sandbox is not running/i,
|
|
@@ -690,6 +692,9 @@ var DaytonaSandbox = class DaytonaSandbox extends _mastra_core_workspace.MastraS
|
|
|
690
692
|
_createdAt = null;
|
|
691
693
|
_workingDir = null;
|
|
692
694
|
_isRetrying = false;
|
|
695
|
+
_computerUseStarted = null;
|
|
696
|
+
computerUseAutoStart;
|
|
697
|
+
noVncPort;
|
|
693
698
|
timeout;
|
|
694
699
|
language;
|
|
695
700
|
resources;
|
|
@@ -742,6 +747,10 @@ var DaytonaSandbox = class DaytonaSandbox extends _mastra_core_workspace.MastraS
|
|
|
742
747
|
...options.target !== void 0 && { target: options.target }
|
|
743
748
|
};
|
|
744
749
|
this._constructorOptions = { ...options };
|
|
750
|
+
const computerUseOption = options.computerUse ?? true;
|
|
751
|
+
this.computerUseAutoStart = typeof computerUseOption === "object" ? computerUseOption.autoStart ?? true : true;
|
|
752
|
+
this.noVncPort = typeof computerUseOption === "object" ? computerUseOption.noVncPort ?? DEFAULT_NOVNC_PORT : DEFAULT_NOVNC_PORT;
|
|
753
|
+
if (computerUseOption !== false) this.computer = this.createComputer();
|
|
745
754
|
}
|
|
746
755
|
generateId() {
|
|
747
756
|
return `daytona-sandbox-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
@@ -876,6 +885,7 @@ var DaytonaSandbox = class DaytonaSandbox extends _mastra_core_workspace.MastraS
|
|
|
876
885
|
await this._daytona.stop(this._sandbox);
|
|
877
886
|
} catch {}
|
|
878
887
|
this._sandbox = null;
|
|
888
|
+
this._computerUseStarted = null;
|
|
879
889
|
}
|
|
880
890
|
/**
|
|
881
891
|
* Destroy the Daytona sandbox and clean up all resources.
|
|
@@ -892,6 +902,7 @@ var DaytonaSandbox = class DaytonaSandbox extends _mastra_core_workspace.MastraS
|
|
|
892
902
|
this._sandbox = null;
|
|
893
903
|
this._daytonaSandboxId = void 0;
|
|
894
904
|
this._daytona = null;
|
|
905
|
+
this._computerUseStarted = null;
|
|
895
906
|
this.mounts?.clear();
|
|
896
907
|
}
|
|
897
908
|
/**
|
|
@@ -955,6 +966,96 @@ var DaytonaSandbox = class DaytonaSandbox extends _mastra_core_workspace.MastraS
|
|
|
955
966
|
})));
|
|
956
967
|
}
|
|
957
968
|
/**
|
|
969
|
+
* Ensure the Daytona computer use processes (Xvfb, xfce4, x11vnc, noVNC)
|
|
970
|
+
* are running. Memoized per attached sandbox; the memo is reset when the
|
|
971
|
+
* sandbox stops, dies, or is destroyed so a fresh sandbox restarts them.
|
|
972
|
+
*/
|
|
973
|
+
async ensureComputerUseStarted() {
|
|
974
|
+
if (!this.computerUseAutoStart) return;
|
|
975
|
+
if (!this._computerUseStarted) this._computerUseStarted = this.daytona.computerUse.start().then(() => void 0).catch((error) => {
|
|
976
|
+
this._computerUseStarted = null;
|
|
977
|
+
throw error;
|
|
978
|
+
});
|
|
979
|
+
return this._computerUseStarted;
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* Build the {@link SandboxComputer} capability backed by Daytona's
|
|
983
|
+
* computer use API (`sandbox.computerUse`).
|
|
984
|
+
*
|
|
985
|
+
* Every operation ensures the sandbox is running and the desktop processes
|
|
986
|
+
* are started, and retries once if the sandbox died (mirroring command
|
|
987
|
+
* execution behavior).
|
|
988
|
+
*/
|
|
989
|
+
createComputer() {
|
|
990
|
+
const run = async (fn) => {
|
|
991
|
+
await this.ensureRunning();
|
|
992
|
+
return this.retryOnDead(async () => {
|
|
993
|
+
await this.ensureComputerUseStarted();
|
|
994
|
+
return fn(this.daytona.computerUse);
|
|
995
|
+
});
|
|
996
|
+
};
|
|
997
|
+
return {
|
|
998
|
+
screenshot: async () => {
|
|
999
|
+
const response = await run((computerUse) => computerUse.screenshot.takeFullScreen());
|
|
1000
|
+
if (!response.screenshot) throw new Error(`${LOG_PREFIX} Daytona returned an empty screenshot response`);
|
|
1001
|
+
return {
|
|
1002
|
+
data: new Uint8Array(Buffer.from(response.screenshot, "base64")),
|
|
1003
|
+
mediaType: "image/png"
|
|
1004
|
+
};
|
|
1005
|
+
},
|
|
1006
|
+
leftClick: async (x, y) => {
|
|
1007
|
+
await run((computerUse) => computerUse.mouse.click(x, y, "left"));
|
|
1008
|
+
},
|
|
1009
|
+
rightClick: async (x, y) => {
|
|
1010
|
+
await run((computerUse) => computerUse.mouse.click(x, y, "right"));
|
|
1011
|
+
},
|
|
1012
|
+
doubleClick: async (x, y) => {
|
|
1013
|
+
await run((computerUse) => computerUse.mouse.click(x, y, "left", true));
|
|
1014
|
+
},
|
|
1015
|
+
moveMouse: async (x, y) => {
|
|
1016
|
+
await run((computerUse) => computerUse.mouse.move(x, y));
|
|
1017
|
+
},
|
|
1018
|
+
drag: async (from, to) => {
|
|
1019
|
+
await run((computerUse) => computerUse.mouse.drag(from.x, from.y, to.x, to.y));
|
|
1020
|
+
},
|
|
1021
|
+
scroll: async (direction, amount) => {
|
|
1022
|
+
await run(async (computerUse) => {
|
|
1023
|
+
const position = await computerUse.mouse.getPosition();
|
|
1024
|
+
return computerUse.mouse.scroll(position.x ?? 0, position.y ?? 0, direction, amount);
|
|
1025
|
+
});
|
|
1026
|
+
},
|
|
1027
|
+
type: async (text) => {
|
|
1028
|
+
await run((computerUse) => computerUse.keyboard.type(text));
|
|
1029
|
+
},
|
|
1030
|
+
press: async (key) => {
|
|
1031
|
+
await run((computerUse) => Array.isArray(key) ? computerUse.keyboard.hotkey(key.join("+")) : computerUse.keyboard.press(key));
|
|
1032
|
+
},
|
|
1033
|
+
getScreenSize: async () => {
|
|
1034
|
+
const info = await run((computerUse) => computerUse.display.getInfo());
|
|
1035
|
+
const display = info.displays?.find((d) => d.isActive) ?? info.displays?.[0];
|
|
1036
|
+
if (!display || display.width === void 0 || display.height === void 0) throw new Error(`${LOG_PREFIX} Daytona did not return display information`);
|
|
1037
|
+
return {
|
|
1038
|
+
width: display.width,
|
|
1039
|
+
height: display.height
|
|
1040
|
+
};
|
|
1041
|
+
},
|
|
1042
|
+
getCursorPosition: async () => {
|
|
1043
|
+
const position = await run((computerUse) => computerUse.mouse.getPosition());
|
|
1044
|
+
return {
|
|
1045
|
+
x: position.x ?? 0,
|
|
1046
|
+
y: position.y ?? 0
|
|
1047
|
+
};
|
|
1048
|
+
},
|
|
1049
|
+
streamUrl: async () => {
|
|
1050
|
+
try {
|
|
1051
|
+
return (await run(() => this.daytona.getPreviewLink(this.noVncPort)))?.url ?? null;
|
|
1052
|
+
} catch {
|
|
1053
|
+
return null;
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
/**
|
|
958
1059
|
* Mount a filesystem at a path in the sandbox.
|
|
959
1060
|
* Uses FUSE tools (s3fs, gcsfuse) to mount cloud storage.
|
|
960
1061
|
*/
|
|
@@ -1389,6 +1490,7 @@ var DaytonaSandbox = class DaytonaSandbox extends _mastra_core_workspace.MastraS
|
|
|
1389
1490
|
*/
|
|
1390
1491
|
handleSandboxTimeout() {
|
|
1391
1492
|
this._sandbox = null;
|
|
1493
|
+
this._computerUseStarted = null;
|
|
1392
1494
|
if (this.mounts) {
|
|
1393
1495
|
for (const [path, entry] of this.mounts.entries) if (entry.state === "mounted" || entry.state === "mounting") this.mounts.set(path, { state: "pending" });
|
|
1394
1496
|
}
|