@alchemy.run/daytona 0.0.0 → 2.0.0-beta.86

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.
Files changed (274) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +76 -4
  3. package/lib/ApiKey.d.ts +99 -0
  4. package/lib/ApiKey.d.ts.map +1 -0
  5. package/lib/ApiKey.js +152 -0
  6. package/lib/ApiKey.js.map +1 -0
  7. package/lib/AuthProvider.d.ts +55 -0
  8. package/lib/AuthProvider.d.ts.map +1 -0
  9. package/lib/AuthProvider.js +280 -0
  10. package/lib/AuthProvider.js.map +1 -0
  11. package/lib/Bootstrap.d.ts +8 -0
  12. package/lib/Bootstrap.d.ts.map +1 -0
  13. package/lib/Bootstrap.js +28 -0
  14. package/lib/Bootstrap.js.map +1 -0
  15. package/lib/ConnectSandbox.d.ts +72 -0
  16. package/lib/ConnectSandbox.d.ts.map +1 -0
  17. package/lib/ConnectSandbox.js +3 -0
  18. package/lib/ConnectSandbox.js.map +1 -0
  19. package/lib/ConnectSandboxHttp.d.ts +5 -0
  20. package/lib/ConnectSandboxHttp.d.ts.map +1 -0
  21. package/lib/ConnectSandboxHttp.js +22 -0
  22. package/lib/ConnectSandboxHttp.js.map +1 -0
  23. package/lib/Contributions.d.ts +7 -0
  24. package/lib/Contributions.d.ts.map +1 -0
  25. package/lib/Contributions.js +6 -0
  26. package/lib/Contributions.js.map +1 -0
  27. package/lib/CreateSandbox.d.ts +86 -0
  28. package/lib/CreateSandbox.d.ts.map +1 -0
  29. package/lib/CreateSandbox.js +3 -0
  30. package/lib/CreateSandbox.js.map +1 -0
  31. package/lib/CreateSandboxHttp.d.ts +5 -0
  32. package/lib/CreateSandboxHttp.d.ts.map +1 -0
  33. package/lib/CreateSandboxHttp.js +65 -0
  34. package/lib/CreateSandboxHttp.js.map +1 -0
  35. package/lib/CreateSecret.d.ts +56 -0
  36. package/lib/CreateSecret.d.ts.map +1 -0
  37. package/lib/CreateSecret.js +3 -0
  38. package/lib/CreateSecret.js.map +1 -0
  39. package/lib/CreateSecretHttp.d.ts +5 -0
  40. package/lib/CreateSecretHttp.d.ts.map +1 -0
  41. package/lib/CreateSecretHttp.js +39 -0
  42. package/lib/CreateSecretHttp.js.map +1 -0
  43. package/lib/CreateSnapshot.d.ts +80 -0
  44. package/lib/CreateSnapshot.d.ts.map +1 -0
  45. package/lib/CreateSnapshot.js +3 -0
  46. package/lib/CreateSnapshot.js.map +1 -0
  47. package/lib/CreateSnapshotHttp.d.ts +5 -0
  48. package/lib/CreateSnapshotHttp.d.ts.map +1 -0
  49. package/lib/CreateSnapshotHttp.js +47 -0
  50. package/lib/CreateSnapshotHttp.js.map +1 -0
  51. package/lib/CreateVolume.d.ts +81 -0
  52. package/lib/CreateVolume.d.ts.map +1 -0
  53. package/lib/CreateVolume.js +10 -0
  54. package/lib/CreateVolume.js.map +1 -0
  55. package/lib/CreateVolumeHttp.d.ts +5 -0
  56. package/lib/CreateVolumeHttp.d.ts.map +1 -0
  57. package/lib/CreateVolumeHttp.js +31 -0
  58. package/lib/CreateVolumeHttp.js.map +1 -0
  59. package/lib/Credentials.d.ts +9 -0
  60. package/lib/Credentials.d.ts.map +1 -0
  61. package/lib/Credentials.js +18 -0
  62. package/lib/Credentials.js.map +1 -0
  63. package/lib/DaytonaBindings.d.ts +51 -0
  64. package/lib/DaytonaBindings.d.ts.map +1 -0
  65. package/lib/DaytonaBindings.js +61 -0
  66. package/lib/DaytonaBindings.js.map +1 -0
  67. package/lib/IdentityProvider.d.ts +80 -0
  68. package/lib/IdentityProvider.d.ts.map +1 -0
  69. package/lib/IdentityProvider.js +111 -0
  70. package/lib/IdentityProvider.js.map +1 -0
  71. package/lib/MountVolume.d.ts +86 -0
  72. package/lib/MountVolume.d.ts.map +1 -0
  73. package/lib/MountVolume.js +27 -0
  74. package/lib/MountVolume.js.map +1 -0
  75. package/lib/OAuthClient.d.ts +14 -0
  76. package/lib/OAuthClient.d.ts.map +1 -0
  77. package/lib/OAuthClient.js +23 -0
  78. package/lib/OAuthClient.js.map +1 -0
  79. package/lib/Organization.d.ts +40 -0
  80. package/lib/Organization.d.ts.map +1 -0
  81. package/lib/Organization.js +80 -0
  82. package/lib/Organization.js.map +1 -0
  83. package/lib/OrganizationInvitation.d.ts +70 -0
  84. package/lib/OrganizationInvitation.d.ts.map +1 -0
  85. package/lib/OrganizationInvitation.js +109 -0
  86. package/lib/OrganizationInvitation.js.map +1 -0
  87. package/lib/OrganizationMember.d.ts +86 -0
  88. package/lib/OrganizationMember.d.ts.map +1 -0
  89. package/lib/OrganizationMember.js +109 -0
  90. package/lib/OrganizationMember.js.map +1 -0
  91. package/lib/OrganizationOtelConfig.d.ts +59 -0
  92. package/lib/OrganizationOtelConfig.d.ts.map +1 -0
  93. package/lib/OrganizationOtelConfig.js +87 -0
  94. package/lib/OrganizationOtelConfig.js.map +1 -0
  95. package/lib/OrganizationRole.d.ts +66 -0
  96. package/lib/OrganizationRole.d.ts.map +1 -0
  97. package/lib/OrganizationRole.js +106 -0
  98. package/lib/OrganizationRole.js.map +1 -0
  99. package/lib/OrganizationSettings.d.ts +76 -0
  100. package/lib/OrganizationSettings.d.ts.map +1 -0
  101. package/lib/OrganizationSettings.js +107 -0
  102. package/lib/OrganizationSettings.js.map +1 -0
  103. package/lib/Providers.d.ts +14 -0
  104. package/lib/Providers.d.ts.map +1 -0
  105. package/lib/Providers.js +53 -0
  106. package/lib/Providers.js.map +1 -0
  107. package/lib/ReadAuditLogs.d.ts +30 -0
  108. package/lib/ReadAuditLogs.d.ts.map +1 -0
  109. package/lib/ReadAuditLogs.js +17 -0
  110. package/lib/ReadAuditLogs.js.map +1 -0
  111. package/lib/ReadOrganization.d.ts +39 -0
  112. package/lib/ReadOrganization.d.ts.map +1 -0
  113. package/lib/ReadOrganization.js +39 -0
  114. package/lib/ReadOrganization.js.map +1 -0
  115. package/lib/ReadUsage.d.ts +31 -0
  116. package/lib/ReadUsage.d.ts.map +1 -0
  117. package/lib/ReadUsage.js +17 -0
  118. package/lib/ReadUsage.js.map +1 -0
  119. package/lib/Region.d.ts +78 -0
  120. package/lib/Region.d.ts.map +1 -0
  121. package/lib/Region.js +169 -0
  122. package/lib/Region.js.map +1 -0
  123. package/lib/Registry.d.ts +84 -0
  124. package/lib/Registry.d.ts.map +1 -0
  125. package/lib/Registry.js +97 -0
  126. package/lib/Registry.js.map +1 -0
  127. package/lib/Runner.d.ts +66 -0
  128. package/lib/Runner.d.ts.map +1 -0
  129. package/lib/Runner.js +116 -0
  130. package/lib/Runner.js.map +1 -0
  131. package/lib/Sandbox.d.ts +376 -0
  132. package/lib/Sandbox.d.ts.map +1 -0
  133. package/lib/Sandbox.js +565 -0
  134. package/lib/Sandbox.js.map +1 -0
  135. package/lib/SandboxClient.d.ts +258 -0
  136. package/lib/SandboxClient.d.ts.map +1 -0
  137. package/lib/SandboxClient.js +233 -0
  138. package/lib/SandboxClient.js.map +1 -0
  139. package/lib/Secret.d.ts +93 -0
  140. package/lib/Secret.d.ts.map +1 -0
  141. package/lib/Secret.js +130 -0
  142. package/lib/Secret.js.map +1 -0
  143. package/lib/Snapshot.d.ts +327 -0
  144. package/lib/Snapshot.d.ts.map +1 -0
  145. package/lib/Snapshot.js +447 -0
  146. package/lib/Snapshot.js.map +1 -0
  147. package/lib/Volume.d.ts +99 -0
  148. package/lib/Volume.d.ts.map +1 -0
  149. package/lib/Volume.js +152 -0
  150. package/lib/Volume.js.map +1 -0
  151. package/lib/WarmPool.d.ts +61 -0
  152. package/lib/WarmPool.d.ts.map +1 -0
  153. package/lib/WarmPool.js +81 -0
  154. package/lib/WarmPool.js.map +1 -0
  155. package/lib/Webhooks.d.ts +58 -0
  156. package/lib/Webhooks.d.ts.map +1 -0
  157. package/lib/Webhooks.js +75 -0
  158. package/lib/Webhooks.js.map +1 -0
  159. package/lib/index.d.ts +37 -0
  160. package/lib/index.d.ts.map +1 -0
  161. package/lib/index.js +36 -0
  162. package/lib/index.js.map +1 -0
  163. package/lib/internal/BuildContext.d.ts +16 -0
  164. package/lib/internal/BuildContext.d.ts.map +1 -0
  165. package/lib/internal/BuildContext.js +50 -0
  166. package/lib/internal/BuildContext.js.map +1 -0
  167. package/lib/internal/Declared.d.ts +29 -0
  168. package/lib/internal/Declared.d.ts.map +1 -0
  169. package/lib/internal/Declared.js +31 -0
  170. package/lib/internal/Declared.js.map +1 -0
  171. package/lib/internal/Derived.d.ts +40 -0
  172. package/lib/internal/Derived.d.ts.map +1 -0
  173. package/lib/internal/Derived.js +64 -0
  174. package/lib/internal/Derived.js.map +1 -0
  175. package/lib/internal/Errors.d.ts +4 -0
  176. package/lib/internal/Errors.d.ts.map +1 -0
  177. package/lib/internal/Errors.js +1 -0
  178. package/lib/internal/Errors.js.map +1 -0
  179. package/lib/internal/Labels.d.ts +20 -0
  180. package/lib/internal/Labels.d.ts.map +1 -0
  181. package/lib/internal/Labels.js +22 -0
  182. package/lib/internal/Labels.js.map +1 -0
  183. package/lib/internal/Names.d.ts +18 -0
  184. package/lib/internal/Names.d.ts.map +1 -0
  185. package/lib/internal/Names.js +25 -0
  186. package/lib/internal/Names.js.map +1 -0
  187. package/lib/internal/Organization.d.ts +27 -0
  188. package/lib/internal/Organization.d.ts.map +1 -0
  189. package/lib/internal/Organization.js +32 -0
  190. package/lib/internal/Organization.js.map +1 -0
  191. package/lib/internal/Process.d.ts +14 -0
  192. package/lib/internal/Process.d.ts.map +1 -0
  193. package/lib/internal/Process.js +15 -0
  194. package/lib/internal/Process.js.map +1 -0
  195. package/lib/internal/Program.d.ts +83 -0
  196. package/lib/internal/Program.d.ts.map +1 -0
  197. package/lib/internal/Program.js +169 -0
  198. package/lib/internal/Program.js.map +1 -0
  199. package/lib/internal/Ref.d.ts +14 -0
  200. package/lib/internal/Ref.d.ts.map +1 -0
  201. package/lib/internal/Ref.js +7 -0
  202. package/lib/internal/Ref.js.map +1 -0
  203. package/lib/internal/Scoped.d.ts +31 -0
  204. package/lib/internal/Scoped.d.ts.map +1 -0
  205. package/lib/internal/Scoped.js +48 -0
  206. package/lib/internal/Scoped.js.map +1 -0
  207. package/lib/internal/Tar.d.ts +13 -0
  208. package/lib/internal/Tar.d.ts.map +1 -0
  209. package/lib/internal/Tar.js +62 -0
  210. package/lib/internal/Tar.js.map +1 -0
  211. package/lib/internal/Toolbox.d.ts +11 -0
  212. package/lib/internal/Toolbox.d.ts.map +1 -0
  213. package/lib/internal/Toolbox.js +20 -0
  214. package/lib/internal/Toolbox.js.map +1 -0
  215. package/lib/internal/Wait.d.ts +49 -0
  216. package/lib/internal/Wait.d.ts.map +1 -0
  217. package/lib/internal/Wait.js +57 -0
  218. package/lib/internal/Wait.js.map +1 -0
  219. package/package.json +64 -3
  220. package/src/ApiKey.ts +221 -0
  221. package/src/AuthProvider.ts +406 -0
  222. package/src/Bootstrap.ts +55 -0
  223. package/src/ConnectSandbox.ts +76 -0
  224. package/src/ConnectSandboxHttp.ts +26 -0
  225. package/src/Contributions.ts +9 -0
  226. package/src/CreateSandbox.ts +107 -0
  227. package/src/CreateSandboxHttp.ts +97 -0
  228. package/src/CreateSecret.ts +73 -0
  229. package/src/CreateSecretHttp.ts +58 -0
  230. package/src/CreateSnapshot.ts +133 -0
  231. package/src/CreateSnapshotHttp.ts +77 -0
  232. package/src/CreateVolume.ts +104 -0
  233. package/src/CreateVolumeHttp.ts +50 -0
  234. package/src/Credentials.ts +37 -0
  235. package/src/DaytonaBindings.ts +111 -0
  236. package/src/IdentityProvider.ts +181 -0
  237. package/src/MountVolume.ts +122 -0
  238. package/src/OAuthClient.ts +27 -0
  239. package/src/Organization.ts +121 -0
  240. package/src/OrganizationInvitation.ts +174 -0
  241. package/src/OrganizationMember.ts +174 -0
  242. package/src/OrganizationOtelConfig.ts +138 -0
  243. package/src/OrganizationRole.ts +167 -0
  244. package/src/OrganizationSettings.ts +187 -0
  245. package/src/Providers.ts +93 -0
  246. package/src/ReadAuditLogs.ts +50 -0
  247. package/src/ReadOrganization.ts +83 -0
  248. package/src/ReadUsage.ts +51 -0
  249. package/src/Region.ts +226 -0
  250. package/src/Registry.ts +164 -0
  251. package/src/Runner.ts +166 -0
  252. package/src/Sandbox.ts +927 -0
  253. package/src/SandboxClient.ts +625 -0
  254. package/src/Secret.ts +203 -0
  255. package/src/Snapshot.ts +685 -0
  256. package/src/Volume.ts +229 -0
  257. package/src/WarmPool.ts +128 -0
  258. package/src/Webhooks.ts +121 -0
  259. package/src/globals.d.ts +2 -0
  260. package/src/index.ts +46 -0
  261. package/src/internal/BuildContext.ts +62 -0
  262. package/src/internal/Declared.ts +80 -0
  263. package/src/internal/Derived.ts +97 -0
  264. package/src/internal/Errors.ts +4 -0
  265. package/src/internal/Labels.ts +39 -0
  266. package/src/internal/Names.ts +37 -0
  267. package/src/internal/Organization.ts +40 -0
  268. package/src/internal/Process.ts +25 -0
  269. package/src/internal/Program.ts +239 -0
  270. package/src/internal/Ref.ts +15 -0
  271. package/src/internal/Scoped.ts +102 -0
  272. package/src/internal/Tar.ts +72 -0
  273. package/src/internal/Toolbox.ts +27 -0
  274. package/src/internal/Wait.ts +105 -0
@@ -0,0 +1,625 @@
1
+ import * as computerUse from "@distilled.cloud/daytona/computer_use";
2
+ import type { Credentials } from "@distilled.cloud/daytona/Credentials";
3
+ import * as fileSystem from "@distilled.cloud/daytona/file_system";
4
+ import * as git from "@distilled.cloud/daytona/git";
5
+ import * as info from "@distilled.cloud/daytona/info";
6
+ import * as interpreter from "@distilled.cloud/daytona/interpreter";
7
+ import * as lsp from "@distilled.cloud/daytona/lsp";
8
+ import * as port from "@distilled.cloud/daytona/port";
9
+ import * as process from "@distilled.cloud/daytona/process";
10
+ import type { DaytonaOpError } from "@distilled.cloud/daytona/Protocol";
11
+ import * as sandboxes from "@distilled.cloud/daytona/sandbox";
12
+ import * as server from "@distilled.cloud/daytona/server";
13
+ import * as system from "@distilled.cloud/daytona/system";
14
+ import * as telemetry from "@distilled.cloud/daytona/telemetry";
15
+ import * as toolboxStreams from "@distilled.cloud/daytona/Toolbox";
16
+ import type { RuntimeContext } from "alchemy/RuntimeContext";
17
+ import * as Sandbox from "alchemy/Sandbox";
18
+ import * as SecureRandom from "effect/crypto/SecureRandom";
19
+ import * as Effect from "effect/Effect";
20
+ import * as HttpClient from "effect/http/HttpClient";
21
+ import type * as HttpClientError from "effect/http/HttpClientError";
22
+ import * as HttpClientRequest from "effect/http/HttpClientRequest";
23
+ import * as Redacted from "effect/Redacted";
24
+ import * as Schedule from "effect/Schedule";
25
+ import type * as Scope from "effect/Scope";
26
+ import * as Socket from "effect/socket/Socket";
27
+ import * as Stream from "effect/Stream";
28
+ import { pick, scopeModule, type ScopedModule } from "./internal/Scoped.ts";
29
+ import { inSandbox } from "./internal/Toolbox.ts";
30
+ import { toSeconds } from "./internal/Wait.ts";
31
+
32
+ /** Operations of the sandbox service that act on one sandbox. */
33
+ const SANDBOX_OPERATIONS = [
34
+ "getSandbox",
35
+ "deleteSandbox",
36
+ "startSandbox",
37
+ "stopSandbox",
38
+ "pauseSandbox",
39
+ "archiveSandbox",
40
+ "recoverSandbox",
41
+ "resizeSandbox",
42
+ "replaceLabels",
43
+ "setAutostopInterval",
44
+ "setAutoPauseInterval",
45
+ "setAutoArchiveInterval",
46
+ "setAutoDeleteInterval",
47
+ "setTtl",
48
+ "updateNetworkSettings",
49
+ "updatePublicStatus",
50
+ "updateSandboxSecrets",
51
+ "createSandboxSnapshot",
52
+ "forkSandbox",
53
+ "getSandboxForks",
54
+ "getSandboxParent",
55
+ "getSandboxAncestors",
56
+ "getRegionQuotaBySandboxId",
57
+ "getPortPreviewUrl",
58
+ "getSignedPortPreviewUrl",
59
+ "expireSignedPortPreviewUrl",
60
+ "getBuildLogsUrl",
61
+ "createSshAccess",
62
+ "revokeSshAccess",
63
+ "getSandboxSigningKey",
64
+ "rotateSigningKey",
65
+ "getSandboxLogs",
66
+ "getSandboxTraces",
67
+ "getSandboxTraceSpans",
68
+ "getSandboxMetrics",
69
+ ] as const;
70
+
71
+ type SandboxOperations = Pick<typeof sandboxes, (typeof SANDBOX_OPERATIONS)[number]>;
72
+
73
+ /**
74
+ * Every error a handle's shared calls (`exec`, `start`, `files`, `pty`,
75
+ * `fetch`) can fail with.
76
+ */
77
+ export type DaytonaError =
78
+ | DaytonaOpError
79
+ | process.SessionNotFound
80
+ | process.SessionCommandNotFound
81
+ | process.SessionInputNotReady
82
+ | sandboxes.SandboxNotFound
83
+ | toolboxStreams.PtyError
84
+ | toolboxStreams.ToolboxSocketError
85
+ | HttpClientError.HttpClientError;
86
+
87
+ /**
88
+ * What `exec` returns. Daytona runs a command with stdout and stderr on one
89
+ * stream, so the output is combined in `result`, as Daytona names it.
90
+ */
91
+ export interface ExecResult {
92
+ readonly exitCode: number;
93
+ readonly result: string;
94
+ }
95
+
96
+ /**
97
+ * `exec` and `start` options. Daytona's command API takes no stdin, so
98
+ * there is no `stdin` option: `start` a process and `write` to it instead.
99
+ */
100
+ export type ExecOptions = Omit<Sandbox.ExecOptions, "stdin">;
101
+
102
+ /** A command, as a shell line or as an argument vector run without a shell. */
103
+ export type Command = Sandbox.Command;
104
+
105
+ /**
106
+ * A command started with `start`, running in its own Daytona session.
107
+ * Its `id` is the session's; `kill` deletes the session, which ends the
108
+ * command whatever the signal (Daytona takes no signal).
109
+ */
110
+ export interface SandboxProcess extends Sandbox.Process<DaytonaError> {
111
+ /** The session the command runs in (also its `id`). */
112
+ readonly sessionId: string;
113
+ /** The command's ID in that session. */
114
+ readonly commandId: string;
115
+ }
116
+
117
+ /** Files in the sandbox, over Daytona's file API; entries are Daytona's `FileInfo`. */
118
+ export interface SandboxFiles extends Sandbox.Files<DaytonaError, fileSystem.FileInfo> {
119
+ /** Delete a file, or a directory (and what it holds). */
120
+ remove(path: string): Effect.Effect<void, DaytonaError, RuntimeContext>;
121
+ /** Create a directory and its parents, with `mode` (octal). */
122
+ makeDir(
123
+ path: string,
124
+ options?: { readonly mode?: string },
125
+ ): Effect.Effect<void, DaytonaError, RuntimeContext>;
126
+ }
127
+
128
+ /**
129
+ * `pty.open` options. Daytona starts the user's shell and takes no
130
+ * command, so there is no `command`: type it into the terminal.
131
+ */
132
+ export interface PtyOpenOptions {
133
+ /** Session ID. @default a generated one */
134
+ readonly id?: string;
135
+ /** @default 80 */
136
+ readonly cols?: number;
137
+ /** @default 24 */
138
+ readonly rows?: number;
139
+ /** Working directory. */
140
+ readonly cwd?: string;
141
+ /** Environment variables for the shell. */
142
+ readonly env?: Readonly<Record<string, string>>;
143
+ }
144
+
145
+ /** An open terminal, with Daytona's `kill` and `exit` next to the shared calls. */
146
+ export interface PtyConnection extends Sandbox.PtyConnection<DaytonaError> {
147
+ /** Kill the terminal's session. */
148
+ readonly kill: Effect.Effect<void, DaytonaError, RuntimeContext>;
149
+ /** Wait for the shell to exit. */
150
+ readonly exit: Effect.Effect<toolboxStreams.PtyExit, DaytonaError, RuntimeContext>;
151
+ }
152
+
153
+ /** Terminals. */
154
+ export interface SandboxPty extends Sandbox.Pty<DaytonaError, PtyOpenOptions | undefined> {
155
+ open(
156
+ options?: PtyOpenOptions,
157
+ ): Effect.Effect<PtyConnection, DaytonaError, RuntimeContext | Scope.Scope>;
158
+ /** Connect to a terminal that already runs. */
159
+ connect(
160
+ sessionId: string,
161
+ ): Effect.Effect<PtyConnection, DaytonaError, RuntimeContext | Scope.Scope>;
162
+ }
163
+
164
+ /**
165
+ * Terminals and followed logs: the process calls that stream over a
166
+ * WebSocket.
167
+ */
168
+ export interface SandboxProcessStreams {
169
+ /**
170
+ * Create a terminal session and connect to it. The connection closes
171
+ * with the scope; the session keeps running until it exits or is
172
+ * killed.
173
+ */
174
+ createPty(
175
+ request: toolboxStreams.CreatePtyRequest,
176
+ ): Effect.Effect<
177
+ toolboxStreams.PtyConnection,
178
+ toolboxStreams.PtyError,
179
+ RuntimeContext | Scope.Scope
180
+ >;
181
+ /** Connect to an existing terminal session. The connection closes with the scope. */
182
+ connectPty(request: {
183
+ readonly sessionId: string;
184
+ }): Effect.Effect<
185
+ toolboxStreams.PtyConnection,
186
+ toolboxStreams.PtyError,
187
+ RuntimeContext | Scope.Scope
188
+ >;
189
+ /**
190
+ * Follow a session command's output while it runs, as stdout and
191
+ * stderr pieces. The stream ends when the command exits.
192
+ */
193
+ followSessionCommandLogs(request: {
194
+ readonly sessionId: string;
195
+ readonly commandId: string;
196
+ }): Stream.Stream<
197
+ toolboxStreams.LogOutput,
198
+ toolboxStreams.ToolboxSocketOpenError,
199
+ RuntimeContext
200
+ >;
201
+ /** Follow the entrypoint's output. The stream ends when the entrypoint exits. */
202
+ followEntrypointLogs(): Stream.Stream<
203
+ toolboxStreams.LogOutput,
204
+ toolboxStreams.ToolboxSocketOpenError,
205
+ RuntimeContext
206
+ >;
207
+ }
208
+
209
+ /** Code runs in an interpreter context, streamed over a WebSocket. */
210
+ export interface SandboxInterpreterRuns {
211
+ /**
212
+ * Run code and wait for it: its stdout, stderr and the exception it
213
+ * raised, if any.
214
+ */
215
+ executeInterpreterCode(
216
+ request: toolboxStreams.InterpreterCodeRequest,
217
+ ): Effect.Effect<
218
+ toolboxStreams.InterpreterResult,
219
+ toolboxStreams.InterpreterCodeError,
220
+ RuntimeContext
221
+ >;
222
+ /** Run code and stream its output as it is produced. */
223
+ streamInterpreterCode(
224
+ request: toolboxStreams.InterpreterCodeRequest,
225
+ ): Stream.Stream<
226
+ toolboxStreams.InterpreterOutput,
227
+ toolboxStreams.InterpreterCodeError,
228
+ RuntimeContext
229
+ >;
230
+ }
231
+
232
+ /** Several files in one request. */
233
+ export interface SandboxBulkFiles {
234
+ /** Upload several files. Existing files are overwritten; parent directories are created. */
235
+ uploadFiles(request: {
236
+ readonly files: ReadonlyArray<toolboxStreams.UploadFileEntry>;
237
+ }): Effect.Effect<
238
+ toolboxStreams.UploadFilesResult,
239
+ toolboxStreams.BulkTransferError,
240
+ RuntimeContext
241
+ >;
242
+ /** Download several files. A path that can't be read is reported in `errors`. */
243
+ downloadFiles(request: {
244
+ readonly paths: ReadonlyArray<string>;
245
+ }): Effect.Effect<
246
+ toolboxStreams.DownloadFilesResult,
247
+ toolboxStreams.BulkTransferError,
248
+ RuntimeContext
249
+ >;
250
+ }
251
+
252
+ /**
253
+ * One Daytona sandbox, as a runtime client. Every Daytona operation that
254
+ * acts on a sandbox is a method here, with Daytona's own parameters and
255
+ * typed errors and the sandbox filled in: lifecycle on the handle itself
256
+ * (`startSandbox`, `forkSandbox`, `createSandboxSnapshot`,
257
+ * `getSignedPortPreviewUrl`, …) and the in-sandbox toolbox under
258
+ * `process`, `fs`, `git`, `lsp`, `interpreter`, `computerUse`, `ports`,
259
+ * `info`, `system` and `server`. Telemetry from Daytona's analytics API is
260
+ * under `telemetry`.
261
+ *
262
+ * Every method needs `RuntimeContext`: it runs in a deployed runtime, with
263
+ * the API key its binding minted.
264
+ */
265
+ export interface DaytonaSandbox
266
+ extends
267
+ ScopedModule<SandboxOperations>,
268
+ Sandbox.SandboxExec<DaytonaError, ExecResult, ExecOptions>,
269
+ Sandbox.SandboxProcesses<DaytonaError, ExecOptions>,
270
+ Sandbox.SandboxFiles<DaytonaError, fileSystem.FileInfo>,
271
+ Sandbox.SandboxPty<DaytonaError, PtyOpenOptions | undefined>,
272
+ Sandbox.SandboxPorts<DaytonaError, SandboxPort> {
273
+ /** Sandbox ID. */
274
+ readonly sandboxId: string;
275
+ /** Sandbox name. */
276
+ readonly name: string;
277
+ /** The sandbox's toolbox proxy. */
278
+ readonly toolboxProxyUrl: string;
279
+ /** Processes, sessions, terminals and code runs. */
280
+ readonly process: ScopedModule<typeof process> & SandboxProcessStreams;
281
+ /** Files: read, write, list, search, replace, permissions, bulk transfer. */
282
+ readonly fs: ScopedModule<typeof fileSystem> & SandboxBulkFiles;
283
+ /** Git: clone, branch, commit, push, pull, status. */
284
+ readonly git: ScopedModule<typeof git>;
285
+ /** Language servers: start, completions, symbols. */
286
+ readonly lsp: ScopedModule<typeof lsp>;
287
+ /** Stateful code interpreter contexts, and code runs in them. */
288
+ readonly interpreter: ScopedModule<typeof interpreter> & SandboxInterpreterRuns;
289
+ /** Desktop control: screenshots, mouse, keyboard, recordings, accessibility. */
290
+ readonly computerUse: ScopedModule<typeof computerUse>;
291
+ /** Listening ports. */
292
+ readonly ports: ScopedModule<typeof port>;
293
+ /** Home and working directory, daemon version. */
294
+ readonly info: ScopedModule<typeof info>;
295
+ /** System metrics. */
296
+ readonly system: ScopedModule<typeof system>;
297
+ /** Daemon environment. */
298
+ readonly server: ScopedModule<typeof server>;
299
+ /** Logs, traces and metrics the sandbox exported. */
300
+ readonly telemetry: ScopedModule<typeof telemetry>;
301
+ /**
302
+ * Run a command and wait for it. A string runs in a shell (pipes, quotes
303
+ * and `&&` work); an array runs as an argument vector. A non-zero exit
304
+ * is returned, not failed.
305
+ */
306
+ exec(
307
+ command: Command,
308
+ options?: ExecOptions,
309
+ ): Effect.Effect<ExecResult, DaytonaError, RuntimeContext>;
310
+ /**
311
+ * Start a command in its own session and return it while it runs. Closing
312
+ * the scope detaches; the command keeps running until it exits or is killed.
313
+ */
314
+ start(
315
+ command: Command,
316
+ options?: ExecOptions,
317
+ ): Effect.Effect<SandboxProcess, DaytonaError, RuntimeContext | Scope.Scope>;
318
+ /** Files: read, write, list, stat, remove, make directories. */
319
+ readonly files: SandboxFiles;
320
+ /** Terminals. */
321
+ readonly pty: SandboxPty;
322
+ /**
323
+ * A port in the sandbox, reached through its preview URL. `fetch` sends
324
+ * a client request (its URL is a path on the port) or proxies a server
325
+ * request, with the preview token.
326
+ */
327
+ getTcpPort(port: number): Effect.Effect<SandboxPort, DaytonaError, RuntimeContext>;
328
+ }
329
+
330
+ /**
331
+ * A port in a Daytona sandbox, as its preview URL serves it. `fetch` sends
332
+ * the preview token for you; use `url` and `token` to reach it any other
333
+ * way (a browser needs `getSignedPortPreviewUrl` instead).
334
+ */
335
+ export interface SandboxPort extends Sandbox.SandboxPort<DaytonaError> {
336
+ /** The port number. */
337
+ readonly port: number;
338
+ /** Preview URL of the port, as Daytona names it. */
339
+ readonly url: string;
340
+ /**
341
+ * Preview token, sent as `X-Daytona-Preview-Token`. A `public` sandbox's
342
+ * previews don't need it.
343
+ */
344
+ readonly token: Redacted.Redacted<string>;
345
+ }
346
+
347
+ /**
348
+ * The handle {@link ConnectSandbox} returns for a sandbox declared at
349
+ * deploy. Its methods are the same as {@link DaytonaSandbox}'s; its
350
+ * identity resolves at runtime, so `sandboxId`, `name` and
351
+ * `toolboxProxyUrl` are Effects.
352
+ */
353
+ export interface ConnectedSandbox extends Omit<
354
+ DaytonaSandbox,
355
+ "sandboxId" | "name" | "toolboxProxyUrl"
356
+ > {
357
+ /** Sandbox ID. */
358
+ readonly sandboxId: Effect.Effect<string, never, RuntimeContext>;
359
+ /** Sandbox name. */
360
+ readonly name: Effect.Effect<string, never, RuntimeContext>;
361
+ /** The sandbox's toolbox proxy. */
362
+ readonly toolboxProxyUrl: Effect.Effect<string, never, RuntimeContext>;
363
+ }
364
+
365
+ /** What a binding needs to build a handle. */
366
+ export interface SandboxIdentity {
367
+ readonly id: string;
368
+ readonly name: string;
369
+ readonly toolboxProxyUrl: string;
370
+ }
371
+
372
+ type Runner = <A, E, R>(
373
+ effect: Effect.Effect<A, E, R>,
374
+ ) => Effect.Effect<A, E, Exclude<R, Credentials | HttpClient.HttpClient> | RuntimeContext>;
375
+
376
+ /** Everything on a handle but its identity. */
377
+ export type SandboxMethods = Omit<DaytonaSandbox, "sandboxId" | "name" | "toolboxProxyUrl">;
378
+
379
+ /** POSIX single-quote one argument. */
380
+ const quote = (arg: string) =>
381
+ /^[\w@%+=:,./-]+$/.test(arg) ? arg : `'${arg.replaceAll("'", `'\\''`)}'`;
382
+
383
+ /** A shell line for a command: a string as is, an argument vector quoted. */
384
+ const shellLine = (command: Command) =>
385
+ typeof command === "string" ? command : command.map(quote).join(" ");
386
+
387
+ /** Run a shell line without quoting problems: pass it base64-encoded. */
388
+ const viaShell = (line: string) =>
389
+ Effect.sync(() => `sh -c "echo '${Buffer.from(line).toString("base64")}' | base64 -d | sh"`);
390
+
391
+ /** A fresh session ID, from WebCrypto (every runtime a handle runs on has it). */
392
+ const newSessionId = (prefix: string) =>
393
+ Effect.gen(function* () {
394
+ const random = yield* SecureRandom.SecureRandom;
395
+ return `${prefix}-${yield* random.uuidV4()}`;
396
+ }).pipe(Effect.provide(SecureRandom.layerWebCrypto));
397
+
398
+ /**
399
+ * Build the methods for one sandbox. `identity` resolves the sandbox (at
400
+ * runtime for a sandbox declared at deploy); `run` supplies the binding's
401
+ * credentials, and toolbox calls are additionally scoped to the sandbox.
402
+ */
403
+ export const makeSandboxMethods = (
404
+ identity: Effect.Effect<SandboxIdentity, never, RuntimeContext>,
405
+ organizationId: Effect.Effect<string, never, RuntimeContext>,
406
+ run: Runner,
407
+ ): SandboxMethods => {
408
+ const fixed = Effect.all({ id: identity, organizationId }).pipe(
409
+ Effect.map(({ id, organizationId }) => ({
410
+ sandboxIdOrName: id.id,
411
+ sandboxId: id.id,
412
+ organizationId,
413
+ })),
414
+ );
415
+ const toolbox: Runner = (effect) =>
416
+ Effect.flatMap(identity, (sandbox) =>
417
+ run(inSandbox(sandbox.id, sandbox.toolboxProxyUrl)(effect)),
418
+ );
419
+ // Sockets dial with the runtime's global WebSocket (Workers, Node 22+, Bun, Deno).
420
+ const socket = <A, E, R>(effect: Effect.Effect<A, E, R>) =>
421
+ toolbox(Effect.provide(effect, Socket.layerWebSocketConstructorGlobal));
422
+ const stream = <A, E, R>(body: Stream.Stream<A, E, R>) =>
423
+ Effect.context<Credentials | HttpClient.HttpClient | Socket.WebSocketConstructor>().pipe(
424
+ Effect.map((context) => Stream.provideContext(body, context)),
425
+ socket,
426
+ Stream.unwrap,
427
+ );
428
+
429
+ const exec = Effect.fn(function* (command: Command, options?: ExecOptions) {
430
+ const response = yield* toolbox(
431
+ process.executeCommand({
432
+ command: yield* viaShell(shellLine(command)),
433
+ cwd: options?.cwd,
434
+ envs: options?.env,
435
+ timeout: toSeconds(options?.timeout),
436
+ }),
437
+ );
438
+ return { exitCode: response.exitCode ?? 0, result: response.result } satisfies ExecResult;
439
+ });
440
+
441
+ const start = Effect.fn(function* (command: Command, options?: ExecOptions) {
442
+ const sessionId = yield* newSessionId("alchemy");
443
+ const env = Object.entries(options?.env ?? {})
444
+ .map(([key, value]) => `export ${key}=${quote(value)}`)
445
+ .join("; ");
446
+ const line = [env, options?.cwd ? `cd ${quote(options.cwd)}` : "", `exec ${shellLine(command)}`]
447
+ .filter(Boolean)
448
+ .join("; ");
449
+ yield* toolbox(process.createSession({ sessionId }));
450
+ // Quoted, not piped in: the command's stdin is the session's input.
451
+ const begun = yield* toolbox(
452
+ process.sessionExecuteCommand({
453
+ sessionId,
454
+ command: `sh -c ${quote(line)}`,
455
+ runAsync: true,
456
+ suppressInputEcho: true,
457
+ }),
458
+ );
459
+ const commandId = begun.cmdId;
460
+ const encoder = new TextEncoder();
461
+ return {
462
+ id: sessionId,
463
+ sessionId,
464
+ commandId,
465
+ output: stream(toolboxStreams.followSessionCommandLogs({ sessionId, commandId })).pipe(
466
+ Stream.map((piece) => ({ fd: piece.stream, data: encoder.encode(piece.text) })),
467
+ ),
468
+ write: (data: string | Uint8Array) =>
469
+ toolbox(
470
+ process.sendInput({
471
+ sessionId,
472
+ commandId,
473
+ data: typeof data === "string" ? data : new TextDecoder().decode(data),
474
+ }),
475
+ ).pipe(
476
+ // The daemon creates the command's input pipe just after it starts.
477
+ Effect.retry({
478
+ while: (e) => e._tag === "SessionInputNotReady",
479
+ schedule: Schedule.spaced("250 millis"),
480
+ times: 20,
481
+ }),
482
+ Effect.asVoid,
483
+ ),
484
+ // Daytona takes no signal: deleting the session ends the command.
485
+ kill: () => toolbox(process.deleteSession({ sessionId })).pipe(Effect.asVoid),
486
+ wait: toolbox(process.getSessionCommand({ sessionId, commandId })).pipe(
487
+ Effect.repeat({
488
+ schedule: Schedule.spaced("1 second"),
489
+ until: (c) => c.exitCode !== undefined,
490
+ }),
491
+ Effect.map((c) => ({ exitCode: c.exitCode ?? 0 })),
492
+ ),
493
+ } satisfies SandboxProcess;
494
+ });
495
+
496
+ const files: SandboxFiles = {
497
+ read: (path) => toolbox(fileSystem.downloadFile({ path })),
498
+ readText: (path) =>
499
+ toolbox(fileSystem.downloadFile({ path })).pipe(
500
+ Effect.map((bytes) => new TextDecoder().decode(bytes)),
501
+ ),
502
+ write: (path, content) =>
503
+ toolbox(fileSystem.uploadFile({ path, body: content })).pipe(Effect.asVoid),
504
+ list: (path) => toolbox(fileSystem.listFiles({ path })),
505
+ stat: (path) => toolbox(fileSystem.getFileInfo({ path })),
506
+ remove: (path) => toolbox(fileSystem.deleteFile({ path, recursive: true })).pipe(Effect.asVoid),
507
+ makeDir: (path, options) =>
508
+ toolbox(fileSystem.createFolder({ path, mode: options?.mode ?? "755" })).pipe(Effect.asVoid),
509
+ };
510
+
511
+ /** The shared terminal shape over Daytona's connection. */
512
+ const terminal = (connection: toolboxStreams.PtyConnection): PtyConnection => ({
513
+ id: connection.sessionId,
514
+ output: connection.output,
515
+ write: connection.write,
516
+ resize: ({ cols, rows }) => toolbox(connection.resize(cols, rows)),
517
+ kill: toolbox(connection.kill),
518
+ exit: connection.exit,
519
+ });
520
+
521
+ const pty: SandboxPty = {
522
+ open: (options) =>
523
+ Effect.flatMap(options?.id ? Effect.succeed(options.id) : newSessionId("alchemy-pty"), (id) =>
524
+ socket(
525
+ toolboxStreams.createPty({
526
+ id,
527
+ cols: options?.cols,
528
+ rows: options?.rows,
529
+ cwd: options?.cwd,
530
+ envs: options?.env,
531
+ }),
532
+ ).pipe(Effect.map(terminal)),
533
+ ),
534
+ connect: (sessionId) =>
535
+ socket(toolboxStreams.connectPty({ sessionId })).pipe(Effect.map(terminal)),
536
+ };
537
+
538
+ const getTcpPort = (port: number) =>
539
+ Effect.flatMap(fixed, ({ sandboxIdOrName }) =>
540
+ run(
541
+ Effect.gen(function* () {
542
+ const preview = yield* sandboxes.getPortPreviewUrl({ sandboxIdOrName, port });
543
+ const client = yield* HttpClient.HttpClient;
544
+ const base = preview.url.replace(/\/$/, "");
545
+ return {
546
+ port,
547
+ url: preview.url,
548
+ token: Redacted.make(preview.token),
549
+ fetch: Sandbox.portFetch<DaytonaError>((request) =>
550
+ Effect.suspend(() => {
551
+ // Only the path and query reach the port: a proxied server
552
+ // request carries its own absolute URL.
553
+ const target = new URL(request.url, "http://port");
554
+ return client.execute(
555
+ request.pipe(
556
+ HttpClientRequest.setUrl(`${base}${target.pathname}${target.search}`),
557
+ HttpClientRequest.setHeader("X-Daytona-Preview-Token", preview.token),
558
+ ),
559
+ );
560
+ }),
561
+ ),
562
+ } satisfies SandboxPort;
563
+ }),
564
+ ),
565
+ );
566
+
567
+ return {
568
+ ...scopeModule(pick(sandboxes, SANDBOX_OPERATIONS), fixed, run),
569
+ process: {
570
+ ...scopeModule(process, {}, toolbox),
571
+ createPty: (request) => socket(toolboxStreams.createPty(request)),
572
+ connectPty: (request) => socket(toolboxStreams.connectPty(request)),
573
+ followSessionCommandLogs: (request) =>
574
+ stream(toolboxStreams.followSessionCommandLogs(request)),
575
+ followEntrypointLogs: () => stream(toolboxStreams.followEntrypointLogs()),
576
+ },
577
+ fs: {
578
+ ...scopeModule(fileSystem, {}, toolbox),
579
+ uploadFiles: (request) => toolbox(toolboxStreams.uploadFiles(request)),
580
+ downloadFiles: (request) => toolbox(toolboxStreams.downloadFiles(request)),
581
+ },
582
+ git: scopeModule(git, {}, toolbox),
583
+ lsp: scopeModule(lsp, {}, toolbox),
584
+ interpreter: {
585
+ ...scopeModule(interpreter, {}, toolbox),
586
+ executeInterpreterCode: (request) => socket(toolboxStreams.executeInterpreterCode(request)),
587
+ streamInterpreterCode: (request) => stream(toolboxStreams.streamInterpreterCode(request)),
588
+ },
589
+ computerUse: scopeModule(computerUse, {}, toolbox),
590
+ ports: scopeModule(port, {}, toolbox),
591
+ info: scopeModule(info, {}, toolbox),
592
+ system: scopeModule(system, {}, toolbox),
593
+ server: scopeModule(server, {}, toolbox),
594
+ telemetry: scopeModule(telemetry, fixed, run),
595
+ exec,
596
+ start,
597
+ files,
598
+ pty,
599
+ getTcpPort,
600
+ };
601
+ };
602
+
603
+ /** The handle for a sandbox whose identity is known (one just created or listed). */
604
+ export const makeSandboxClient = (
605
+ sandbox: SandboxIdentity,
606
+ organizationId: Effect.Effect<string, never, RuntimeContext>,
607
+ run: Runner,
608
+ ): DaytonaSandbox => ({
609
+ ...makeSandboxMethods(Effect.succeed(sandbox), organizationId, run),
610
+ sandboxId: sandbox.id,
611
+ name: sandbox.name,
612
+ toolboxProxyUrl: sandbox.toolboxProxyUrl,
613
+ });
614
+
615
+ /** The handle for a sandbox declared at deploy, whose identity resolves at runtime. */
616
+ export const makeConnectedSandbox = (
617
+ identity: Effect.Effect<SandboxIdentity, never, RuntimeContext>,
618
+ organizationId: Effect.Effect<string, never, RuntimeContext>,
619
+ run: Runner,
620
+ ): ConnectedSandbox => ({
621
+ ...makeSandboxMethods(identity, organizationId, run),
622
+ sandboxId: Effect.map(identity, (s) => s.id),
623
+ name: Effect.map(identity, (s) => s.name),
624
+ toolboxProxyUrl: Effect.map(identity, (s) => s.toolboxProxyUrl),
625
+ });