@solarisdk/daytona-compat 0.0.0-stage → 0.1.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/COMPAT.md +118 -0
- package/LICENSE +21 -0
- package/NOTICE +8 -0
- package/README.md +51 -2
- package/dist/client.d.ts +37 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +157 -0
- package/dist/client.js.map +1 -0
- package/dist/conn.d.ts +55 -0
- package/dist/conn.d.ts.map +1 -0
- package/dist/conn.js +197 -0
- package/dist/conn.js.map +1 -0
- package/dist/context.d.ts +47 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +236 -0
- package/dist/context.js.map +1 -0
- package/dist/dockerfile.d.ts +36 -0
- package/dist/dockerfile.d.ts.map +1 -0
- package/dist/dockerfile.js +361 -0
- package/dist/dockerfile.js.map +1 -0
- package/dist/errors.d.ts +25 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +79 -0
- package/dist/errors.js.map +1 -0
- package/dist/fs.d.ts +32 -0
- package/dist/fs.d.ts.map +1 -0
- package/dist/fs.js +196 -0
- package/dist/fs.js.map +1 -0
- package/dist/git.d.ts +34 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +204 -0
- package/dist/git.js.map +1 -0
- package/dist/image-ref.d.ts +35 -0
- package/dist/image-ref.d.ts.map +1 -0
- package/dist/image-ref.js +97 -0
- package/dist/image-ref.js.map +1 -0
- package/dist/image.d.ts +45 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +126 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/mapping.d.ts +55 -0
- package/dist/mapping.d.ts.map +1 -0
- package/dist/mapping.js +174 -0
- package/dist/mapping.js.map +1 -0
- package/dist/process.d.ts +35 -0
- package/dist/process.d.ts.map +1 -0
- package/dist/process.js +223 -0
- package/dist/process.js.map +1 -0
- package/dist/sandbox.d.ts +88 -0
- package/dist/sandbox.d.ts.map +1 -0
- package/dist/sandbox.js +395 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/snapshot.d.ts +68 -0
- package/dist/snapshot.d.ts.map +1 -0
- package/dist/snapshot.js +255 -0
- package/dist/snapshot.js.map +1 -0
- package/dist/types.d.ts +177 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +46 -4
package/COMPAT.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# COMPAT.md: Daytona SDK compatibility, TypeScript (target: `@daytona/sdk`, public docs as of 2026-10)
|
|
2
|
+
|
|
3
|
+
Legend: **OK** works and is tested live on staging; **DIFF** works with a behaviour difference; **NO** throws
|
|
4
|
+
`SolariCompatUnsupported` (a `DaytonaError`) naming the feature. Nothing is silently ignored.
|
|
5
|
+
|
|
6
|
+
## Setup
|
|
7
|
+
| Daytona | Here |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `new Daytona({ apiKey, apiUrl, target })`, env `DAYTONA_API_KEY`, `DAYTONA_API_URL`, `DAYTONA_TARGET` | OK. Key order: option, `SOLARI_API_KEY`, `DAYTONA_API_KEY`. **Only `slr_…` keys are used**: a non-`slr_` candidate (a real Daytona key in `DAYTONA_API_KEY`) is skipped with a warning and never sent anywhere; with no Solari key left the constructor throws. URL order: option, `SOLARI_BASE_URL`, `DAYTONA_API_URL` (only when it is `https://getsolari.com` or a subdomain, or loopback; otherwise ignored with a warning), default `https://api.getsolari.com`. The option and `SOLARI_BASE_URL` must point at Solari or loopback too, otherwise `DaytonaError` ("Refusing to send a Solari API key to …"): the key is never sent to a non-Solari host. |
|
|
10
|
+
| `target` | NO (throws): Solari has one region. An ambient `DAYTONA_TARGET` env var is ignored with a warning, since it is not a request made by the program. |
|
|
11
|
+
| `jwtToken`, `organizationId`, `DAYTONA_JWT_TOKEN` | NO. |
|
|
12
|
+
| `useDeprecatedPolling` | Accepted; lifecycle calls always poll. |
|
|
13
|
+
|
|
14
|
+
## Sandbox lifecycle (`Daytona`, `Sandbox`)
|
|
15
|
+
| Call | Status | Notes |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| `create(params)` | OK | Returns when the sandbox is running. See create parameters. |
|
|
18
|
+
| `get(idOrName)` | OK | By id; else by name (a metadata lookup). 404 is `DaytonaNotFoundError`. |
|
|
19
|
+
| `list({ labels, states, limit })` | DIFF | Returns the page object with `items` holding up to 1,000 sandboxes, and is async-iterable. Destroyed sandboxes are not listed. |
|
|
20
|
+
| `start(sandbox)` / `sandbox.start()` | OK | A paused sandbox is resumed (RAM and disk kept); a sandbox whose guest powered off is cold-started from its disk. |
|
|
21
|
+
| `stop(sandbox)` / `sandbox.stop()`, `pause()` | DIFF | A stop is a **Solari pause**: RAM, processes and disk are kept, which is stronger than Daytona's stop. State reads `stopped`. |
|
|
22
|
+
| `delete(sandbox, timeout, wait)` | OK | `wait` polls until gone. A fork's own snapshot is deleted with it (best effort). |
|
|
23
|
+
| `fork(sandbox, { name })`, `sandbox.fork()` | DIFF | A snapshot of the running sandbox (RAM and disk) plus a create from it, so processes keep running in the copy. Takes 25-40 s on staging. |
|
|
24
|
+
| `archive`, `recover`, `resize`, `waitForResizeComplete` | NO | Stop (pause) keeps everything; create a new sandbox for a different size. `waitForResizeComplete` returns at once. |
|
|
25
|
+
| `refreshData`, `waitUntilStarted/Stopped`, `refreshActivity` | OK | |
|
|
26
|
+
| `getUserHomeDir`, `getWorkDir`, `getUserRootDir` | DIFF | All return the guest's `$HOME`. |
|
|
27
|
+
| `getMetricsLatest` | OK | `getMetrics(start, end)` (history) NO. |
|
|
28
|
+
| `updateEnv(env)` | DIFF | Sets variables for later commands; `unset` NO. |
|
|
29
|
+
| `downloadUrl`, `uploadUrl` | OK | `ttlSeconds` NO (throws): the URL has Solari's own lifetime. |
|
|
30
|
+
| `setLabels` | OK | Replaces all labels (keys beginning `daytona.` are reserved). Needs a gateway with `PATCH /sandboxes/{id}`, otherwise NO. |
|
|
31
|
+
| `setAutostopInterval(min)` | OK | Sets Solari's idle window; `0` (never stop) is NO. |
|
|
32
|
+
| `setTtl(min)`, create `ttlMinutes` | NO (throws) | Solari has no hard wall-clock lifetime; use `autoStopInterval` (an idle window that resets on activity). |
|
|
33
|
+
| `setAutoArchiveInterval`, `setAutoDeleteInterval`, `setAutoPauseInterval` | NO | Except `setAutoArchiveInterval(0)`. Delete-on-stop is fixed at create (`ephemeral`). |
|
|
34
|
+
| `setPublic(bool)` | DIFF | Opens or removes the sandbox's open tunnel; preview links work either way (they carry a signed token). |
|
|
35
|
+
| `getPreviewLink(port)`, `getSignedPreviewUrl(port)` | DIFF | `https://<key>-<port>.preview…` URL with a signed token **in the URL** (treat it as a credential); `token` is returned too. `expiresInSeconds` NO (throws). |
|
|
36
|
+
| `expireSignedPreviewUrl(port, token)` | DIFF | Revokes **every** preview token of the sandbox. |
|
|
37
|
+
| `createSnapshot(name)` | DIFF | A Solari snapshot (RAM + disk) with that name, usable as `create({ snapshot: name })`. Takes 25-30 s; large (several GB; snapshot storage is billed). |
|
|
38
|
+
| `createSshAccess`, `validateSshAccess`, `revokeSshAccess`, `createLspServer`, `updateNetworkSettings`, `updateSecrets`, `rotateSigningKey` | NO | |
|
|
39
|
+
| `codeInterpreter`, `computerUse` | NO | Every call throws. |
|
|
40
|
+
|
|
41
|
+
States: `starting`→`starting`, `running`→`started`, `paused`/`stopped`→`stopped`, `archived`→`archived`, `releasing`→`destroying`,
|
|
42
|
+
`gone`→`destroyed`. Unknown states read `unknown`.
|
|
43
|
+
|
|
44
|
+
## Create parameters
|
|
45
|
+
| Daytona param | Mapping |
|
|
46
|
+
|---|---|
|
|
47
|
+
| `name` | metadata key `daytona.name` (hidden from `labels`); `get(name)` looks it up. |
|
|
48
|
+
| `labels` | Solari `metadata` (string values). Keys beginning `daytona.` are reserved and refused. |
|
|
49
|
+
| `envVars` | `envs`. |
|
|
50
|
+
| `language` | Recorded (`daytona.language`); selects the interpreter for `codeRun` (python, javascript, typescript). |
|
|
51
|
+
| `snapshot` | A name or id: a ready template (an image snapshot) or a Solari snapshot; the newest match wins. Resolves names created in this process at once, otherwise by listing the org's snapshots (the gateway lists at most 1,000). |
|
|
52
|
+
| `image` (string or `Image`), `resources` | Builds (or reuses) a Solari template named `daytona-img-<digest>` from the Dockerfile; the first create with a new image waits for the build. `onSnapshotCreateLogs` receives build output. |
|
|
53
|
+
| `resources` `{cpu, memory, disk}` | GiB. CPU rounds up; capped silently-with-a-warning at 8 vCPU / 16 GiB (never an error). `gpu` NO. |
|
|
54
|
+
| `autoStopInterval` | Minutes → idle window (default 15). `0` NO. |
|
|
55
|
+
| `ephemeral`, `autoDeleteInterval: 0` | The sandbox is killed instead of paused when idle. `autoDeleteInterval > 0` NO. |
|
|
56
|
+
| `autoArchiveInterval` | NO (any non-zero value). |
|
|
57
|
+
| `public` | See `setPublic`. |
|
|
58
|
+
| `user` | NO unless `root`. |
|
|
59
|
+
| `volumes`, `networkBlockAll`, `networkAllowList`, `domainAllowList`, `outboundProxyUrl`, `spot`, `kvm`, `secrets`, `linkedSandbox`, `otelEndpointOverride`, `queueTimeout`, `autoPauseInterval`, any unknown parameter | NO. |
|
|
60
|
+
| `target` | NO (throws). |
|
|
61
|
+
|
|
62
|
+
## Process (`sandbox.process`)
|
|
63
|
+
| Call | Status | Notes |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| `executeCommand(cmd, cwd, env, timeout)` | DIFF | Runs in a shell (`bash -lc`, or a non-login `bash -c` / `sh -c` on a `FROM <image>` sandbox so the image's `PATH` survives). `cwd` defaults to `$HOME`; a relative `cwd` is under `$HOME`. `result` is stdout and stderr interleaved in arrival order. `timeout` is seconds and kills the command (`DaytonaTimeoutError`); **unset means no limit** (Daytona documents 10 s). |
|
|
66
|
+
| `codeRun(code, { argv, env }, timeout)` | DIFF | Stateless; a temp file run by `python3`, `node` or `npx -y tsx` (needs network) by the sandbox's `language`. No `artifacts.charts`. |
|
|
67
|
+
| `createSession`, `getSession`, `listSessions`, `deleteSession` | DIFF | **Emulated in the guest** (files under `/tmp/.daytona-sessions/<id>`): `cd` and `export` carry over from one command to the next, but a session is not one long-lived shell process: a background process started by a command is not part of the session. Ids are letters, digits, `.`, `_`, `-`. |
|
|
68
|
+
| `executeSessionCommand(id, { command, runAsync }, timeout)` | OK | Sync returns `{ cmdId, stdout, stderr, output, exitCode }`. Async returns `{ cmdId }` while the command runs detached. |
|
|
69
|
+
| `getSessionCommand` | OK | `exitCode` appears when the command ends. |
|
|
70
|
+
| `getSessionCommandLogs(id, cmd)` and the callback form | OK | The callback form follows the output (polled every 300 ms) until the command exits. |
|
|
71
|
+
| `sendSessionCommandInput` | OK | Async commands only (a FIFO is the command's stdin). |
|
|
72
|
+
| `createPty`, `connectPty`, `listPtySessions`, `getPtySessionInfo`, `killPtySession`, `resizePtySession` | NO | |
|
|
73
|
+
|
|
74
|
+
## File system (`sandbox.fs`)
|
|
75
|
+
Relative paths resolve against `$HOME`. A missing path is `DaytonaNotFoundError`.
|
|
76
|
+
| Call | Status | Notes |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| `uploadFile` (buffer or local path), `uploadFiles`, `downloadFile` (buffer or local path), `downloadFiles` | OK | Per-file errors in `downloadFiles` are in `error`. Parent directories are created on upload. |
|
|
79
|
+
| `listFiles(path, { depth })`, `getFileDetails` | DIFF | `owner` and `group` read `root`; `mode` is octal (`"0644"`), `permissions` symbolic (`"-rw-r--r--"`); `modTime` ISO. |
|
|
80
|
+
| `createFolder(path, mode)`, `deleteFile`, `moveFiles`, `setFilePermissions` | OK | `mode` is octal digits; chmod/chown through exec. |
|
|
81
|
+
| `findFiles` (content search), `searchFiles` (file-name glob), `replaceInFiles` | OK | `replaceInFiles` replaces a literal string, not a regex. |
|
|
82
|
+
| `downloadFileStream`, `uploadFileStream` | NO | Use `downloadFile` / `uploadFile`, or `sandbox.downloadUrl` / `uploadUrl` for large files. |
|
|
83
|
+
|
|
84
|
+
## Git (`sandbox.git`)
|
|
85
|
+
Runs the guest's `git` as argv (never a shell string). Credentials (`username`, `password`) are passed to git through
|
|
86
|
+
`GIT_ASKPASS` and environment variables of that one command, never on a command line or in a URL, and are removed from
|
|
87
|
+
error messages. `dangerouslyAuthenticate` stores them in plaintext in `~/.git-credentials` (as Daytona's does).
|
|
88
|
+
| Call | Status |
|
|
89
|
+
|---|---|
|
|
90
|
+
| `clone`, `init`, `add`, `commit`, `branches`, `createBranch`, `deleteBranch`, `checkoutBranch`, `pull`, `push`, `status`, `reset`, `restore`, `remoteAdd`, `remoteGet`, `remotes`, `getConfig`, `setConfig`, `configureUser`, `dangerouslyAuthenticate` | OK (local operations live-tested; network operations are covered by offline tests of the exact git argv). |
|
|
91
|
+
|
|
92
|
+
`status()` follows `git status --porcelain`: `fileStatus[].staging` / `.worktree` read `Modified`, `Added`, `Deleted`, `Renamed`, `Untracked`, ….
|
|
93
|
+
|
|
94
|
+
## Snapshots and images (`daytona.snapshot`, `Image`)
|
|
95
|
+
A Daytona "snapshot" is a named image; here it is a Solari template built from a Dockerfile subset. A sandbox's own snapshot
|
|
96
|
+
(`createSnapshot`) is a Solari snapshot. `snapshot.list()` shows both.
|
|
97
|
+
| Call | Status | Notes |
|
|
98
|
+
|---|---|---|
|
|
99
|
+
| `snapshot.create({ name, image, entrypoint, resources }, { onLogs, timeout })` | DIFF | Builds a template and waits; deleted again if the build fails (`DaytonaError` with the log tail). `regionId`, `sandboxClass` NO. |
|
|
100
|
+
| `snapshot.get(idOrName)`, `list()`, `delete()`, `activate()` | DIFF | `activate` is a lookup (nothing to activate). `list` returns `{ items, total, page, totalPages }`. |
|
|
101
|
+
| `Image.base`, `debianSlim`, `fromDockerfile`, `pipInstall`, `pipInstallFromRequirements`, `addLocalFile`, `addLocalDir`, `runCommands`, `env`, `workdir`, `entrypoint`, `cmd`, `dockerfileCommands`, `dockerfile`, `contextList` | DIFF | Dockerfile subset: `FROM` (one stage; any public image from docker.io, ghcr.io, public.ecr.aws, gcr.io, quay.io), `RUN`, `ENV`, `ARG`, `WORKDIR`, `ENTRYPOINT`, `CMD`, `COPY`/`ADD` from the build context. Not multi-stage, `USER`, `VOLUME`, `HEALTHCHECK`, `ONBUILD`. Local files travel inside the build recipe (about 700 KB compressed at most) and are visible in the template's build record and logs: **never put secrets in them**. `debianSlim(v)` is `FROM python:<v>-slim-bookworm`. |
|
|
102
|
+
| `Image.pipInstallFromPyproject` | NO | |
|
|
103
|
+
|
|
104
|
+
## Other services
|
|
105
|
+
`daytona.volume`, `daytona.secret`, `daytona.warmPool`: every call throws `SolariCompatUnsupported`.
|
|
106
|
+
|
|
107
|
+
## Errors
|
|
108
|
+
HTTP 404 → `DaytonaNotFoundError`, 429 → `DaytonaRateLimitError`, 408/504 and client timeouts → `DaytonaTimeoutError`, anything else
|
|
109
|
+
→ `DaytonaError` (`statusCode` set). Unsupported features → `SolariCompatUnsupported` (a `DaytonaError`, with `.feature`).
|
|
110
|
+
Transient gateway 503s (`retryable`) on label, tunnel and create calls are retried for about 40 s.
|
|
111
|
+
|
|
112
|
+
## Test status
|
|
113
|
+
- `test/compat.test.mjs`: offline (fake gateway and fake guest): exports, auth and URL guards, state map, resources, create translation and the
|
|
114
|
+
unsupported list, name and label handling, snapshot name resolution, fork, the unsupported surface, the `Image` builder, `executeCommand`, file
|
|
115
|
+
system, git argv and credential handling, session id validation.
|
|
116
|
+
- `test-live/staging.test.mjs`: create / get / list, commands (output, exit, env, cwd, timeout), `codeRun`, sessions (state, async, follow logs, stdin),
|
|
117
|
+
file system, local git, labels, preview link, stop / start, auto-stop, named snapshot + create from it, fork, image build and reuse, `snapshot.create`,
|
|
118
|
+
failed build, unsupported errors, `delete(wait)`. It creates its own resources, logs every id and deletes only those.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Solari Desktop
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/NOTICE
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
@solarisdk/daytona-compat
|
|
2
|
+
|
|
3
|
+
This package offers an API shaped like the public Daytona SDK (`@daytona/sdk`) on top of Solari
|
|
4
|
+
Sandbox, so code written against that SDK can run on Solari after changing one import. It was written
|
|
5
|
+
from Daytona's public documentation; it contains no Daytona source code.
|
|
6
|
+
|
|
7
|
+
This package is not affiliated with, endorsed by, or sponsored by Daytona. "Daytona" is the name of
|
|
8
|
+
Daytona's product; it appears here only to describe API compatibility.
|
package/README.md
CHANGED
|
@@ -1,3 +1,52 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @solarisdk/daytona-compat
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A Daytona-compatible API on top of [Solari Sandbox](https://getsolari.com). Change the import, keep your sandbox code.
|
|
4
|
+
|
|
5
|
+
> **Not affiliated with, endorsed by, or sponsored by Daytona.** "Daytona" is the name of Daytona's product; it appears
|
|
6
|
+
> here only to describe API compatibility. This package was written from Daytona's public documentation and contains no
|
|
7
|
+
> Daytona source code, see [NOTICE](./NOTICE). Do not look for it under `@daytona/*`.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
// before: import { Daytona } from '@daytona/sdk';
|
|
11
|
+
import { Daytona } from '@solarisdk/daytona-compat';
|
|
12
|
+
|
|
13
|
+
const daytona = new Daytona({ apiKey: process.env.SOLARI_API_KEY });
|
|
14
|
+
const sandbox = await daytona.create({ labels: { project: 'demo' } });
|
|
15
|
+
const result = await sandbox.process.executeCommand('echo "Hello, World!"');
|
|
16
|
+
console.log(result.result, result.exitCode);
|
|
17
|
+
await sandbox.delete();
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Exports: `Daytona`, `Sandbox`, `Image`, the service classes (`Process`, `FileSystem`, `Git`, `SnapshotService`), the Daytona
|
|
21
|
+
error classes (`DaytonaError`, `DaytonaNotFoundError`, `DaytonaRateLimitError`, `DaytonaTimeoutError`),
|
|
22
|
+
`SolariCompatUnsupported`, and the types.
|
|
23
|
+
|
|
24
|
+
## Configuration
|
|
25
|
+
|
|
26
|
+
| | Order |
|
|
27
|
+
|---|---|
|
|
28
|
+
| API key | `apiKey` option, `SOLARI_API_KEY`, `DAYTONA_API_KEY`: only an `slr_…` Solari key is ever used. A non-`slr_` value (for example a real Daytona key) is skipped with a warning (the key is never printed or sent); with no Solari key the constructor throws |
|
|
29
|
+
| API URL | `apiUrl` option, `SOLARI_BASE_URL`, `DAYTONA_API_URL` (only if it points at getsolari.com or loopback; otherwise ignored with a warning), default `https://api.getsolari.com` |
|
|
30
|
+
|
|
31
|
+
A Daytona key does not work here: use a Solari API key. `target` throws (Solari has one region); an ambient `DAYTONA_TARGET` is ignored with a
|
|
32
|
+
warning (Solari has no regions). `jwtToken` / `organizationId` are not supported.
|
|
33
|
+
|
|
34
|
+
## What works, what does not
|
|
35
|
+
|
|
36
|
+
[COMPAT.md](./COMPAT.md) is the support matrix and the list of differences. Anything Solari cannot do raises
|
|
37
|
+
`SolariCompatUnsupported` (a `DaytonaError`) naming the feature; nothing is silently ignored. In short:
|
|
38
|
+
|
|
39
|
+
- **Works:** create / get / list / start / stop / delete / fork, labels, auto-stop, command execution, sessions (with
|
|
40
|
+
persistent `cd` / `export`, async commands, log streaming, stdin), code run, the file-system calls, git (through the
|
|
41
|
+
guest's git CLI), snapshots (a sandbox's own, and named images), the `Image` builder, preview links.
|
|
42
|
+
- **Not supported (throws):** PTY sessions, the code interpreter (contexts, charts), computer use, LSP, SSH access,
|
|
43
|
+
network allow-lists / block-all, volumes, GPU, regions, warm pools, archive / recover / resize.
|
|
44
|
+
|
|
45
|
+
The sibling Python package is `sdk/python-daytona-compat` (`solari-daytona-compat`, import `solari_daytona`).
|
|
46
|
+
|
|
47
|
+
## Tests
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
npm test # offline unit tests (a fake gateway and a fake guest)
|
|
51
|
+
SOLARI_API_KEY=… SOLARI_BASE_URL=https://api-sta.getsolari.com node --test test-live/*.test.mjs # staging; deletes what it creates
|
|
52
|
+
```
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Conn, type DaytonaConfig } from "./conn.js";
|
|
2
|
+
import { SolariCompatUnsupported } from "./errors.js";
|
|
3
|
+
import { Sandbox } from "./sandbox.js";
|
|
4
|
+
import { SnapshotService } from "./snapshot.js";
|
|
5
|
+
import type { CreateSandboxFromImageParams, CreateSandboxFromSnapshotParams, ForkSandboxParams, ListSandboxesQuery } from "./types.js";
|
|
6
|
+
export interface PaginatedSandboxes extends AsyncIterable<Sandbox> {
|
|
7
|
+
items: Sandbox[];
|
|
8
|
+
total: number;
|
|
9
|
+
page: number;
|
|
10
|
+
totalPages: number;
|
|
11
|
+
}
|
|
12
|
+
export declare class Daytona {
|
|
13
|
+
readonly snapshot: SnapshotService;
|
|
14
|
+
readonly volume: Record<string, never>;
|
|
15
|
+
readonly secret: Record<string, never>;
|
|
16
|
+
readonly warmPool: Record<string, never>;
|
|
17
|
+
/** @internal */
|
|
18
|
+
readonly conn: Conn;
|
|
19
|
+
constructor(config?: DaytonaConfig);
|
|
20
|
+
create(params?: CreateSandboxFromSnapshotParams | CreateSandboxFromImageParams, options?: {
|
|
21
|
+
timeout?: number;
|
|
22
|
+
onSnapshotCreateLogs?: (chunk: string) => void;
|
|
23
|
+
}): Promise<Sandbox>;
|
|
24
|
+
private getView;
|
|
25
|
+
/** A sandbox by id or by name. */
|
|
26
|
+
get(sandboxIdOrName: string): Promise<Sandbox>;
|
|
27
|
+
/** Sandboxes, optionally filtered by `labels` and `states`. Iterable with `for await`; `items` holds them all. */
|
|
28
|
+
list(query?: ListSandboxesQuery | Record<string, string>): Promise<PaginatedSandboxes>;
|
|
29
|
+
start(sandbox: Sandbox, timeout?: number): Promise<void>;
|
|
30
|
+
stop(sandbox: Sandbox): Promise<void>;
|
|
31
|
+
delete(sandbox: Sandbox, timeout?: number, wait?: boolean): Promise<void>;
|
|
32
|
+
fork(sandbox: Sandbox, params?: ForkSandboxParams, timeout?: number): Promise<Sandbox>;
|
|
33
|
+
_experimental_fork(sandbox: Sandbox, params?: ForkSandboxParams, timeout?: number): Promise<Sandbox>;
|
|
34
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
export { SolariCompatUnsupported };
|
|
37
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAS,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAsC,uBAAuB,EAAwC,MAAM,aAAa,CAAC;AAGhI,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,4BAA4B,EAAE,+BAA+B,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEvI,MAAM,WAAW,kBAAmB,SAAQ,aAAa,CAAC,OAAO,CAAC;IAChE,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,OAAO;IAClB,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,MAAM,wBAAyD;IACxE,QAAQ,CAAC,MAAM,wBAAyD;IACxE,QAAQ,CAAC,QAAQ,wBAA2D;IAC5E,gBAAgB;IAChB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;gBAER,MAAM,GAAE,aAAkB;IAKhC,MAAM,CAAC,MAAM,CAAC,EAAE,+BAA+B,GAAG,4BAA4B,EAAE,OAAO,GAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;KAAO,GAAG,OAAO,CAAC,OAAO,CAAC;YAsC7K,OAAO;IAcrB,kCAAkC;IAC5B,GAAG,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBpD,kHAAkH;IAC5G,IAAI,CAAC,KAAK,GAAE,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA8B1F,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAGxD,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAGrC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,SAAK,EAAE,IAAI,UAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAGnE,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,iBAAiB,EAAE,OAAO,SAAK,GAAG,OAAO,CAAC,OAAO,CAAC;IAGxF,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI9F,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7C;AAED,OAAO,EAAE,uBAAuB,EAAE,CAAC"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// `new Daytona(config)`: create / get / list / start / stop / delete / fork, plus the snapshot service.
|
|
2
|
+
import { GatewayError } from "@solarisdk/core";
|
|
3
|
+
import { Conn, sleep } from "./conn.js";
|
|
4
|
+
import { DaytonaError, DaytonaNotFoundError, SolariCompatUnsupported, translateError, unsupportedNamespace } from "./errors.js";
|
|
5
|
+
import { Image } from "./image.js";
|
|
6
|
+
import { K_NAME, mapState, translateCreate } from "./mapping.js";
|
|
7
|
+
import { Sandbox } from "./sandbox.js";
|
|
8
|
+
import { SnapshotService } from "./snapshot.js";
|
|
9
|
+
export class Daytona {
|
|
10
|
+
snapshot;
|
|
11
|
+
volume = unsupportedNamespace("volume");
|
|
12
|
+
secret = unsupportedNamespace("secret");
|
|
13
|
+
warmPool = unsupportedNamespace("warmPool");
|
|
14
|
+
/** @internal */
|
|
15
|
+
conn;
|
|
16
|
+
constructor(config = {}) {
|
|
17
|
+
this.conn = new Conn(config);
|
|
18
|
+
this.snapshot = new SnapshotService(this.conn);
|
|
19
|
+
}
|
|
20
|
+
async create(params, options = {}) {
|
|
21
|
+
const p = (params ?? {});
|
|
22
|
+
if (p.snapshot && p.image)
|
|
23
|
+
throw new DaytonaError("Pass either snapshot or image, not both");
|
|
24
|
+
const t = translateCreate(p);
|
|
25
|
+
const opts = { ...t.opts };
|
|
26
|
+
if (p.snapshot) {
|
|
27
|
+
const r = await this.snapshot.resolve(p.snapshot);
|
|
28
|
+
if (r.template)
|
|
29
|
+
opts.template = r.template;
|
|
30
|
+
if (r.fromSnapshot)
|
|
31
|
+
opts.fromSnapshot = r.fromSnapshot;
|
|
32
|
+
}
|
|
33
|
+
else if (p.image) {
|
|
34
|
+
const img = typeof p.image === "string" ? Image.base(p.image) : p.image;
|
|
35
|
+
opts.template = await this.snapshot.ensureImage(img, { resources: p.resources, onLogs: options.onSnapshotCreateLogs, timeoutSec: options.timeout });
|
|
36
|
+
}
|
|
37
|
+
// A template that just finished building can read as still "building" on another gateway replica for a few
|
|
38
|
+
// seconds: retry `TemplateNotReady` instead of failing a create that is about to work.
|
|
39
|
+
let sb;
|
|
40
|
+
for (let attempt = 0; sb === undefined; attempt++) {
|
|
41
|
+
try {
|
|
42
|
+
sb = await this.conn.solari.create(opts);
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
if (e instanceof GatewayError && e.code === "TemplateNotReady" && attempt < 20)
|
|
46
|
+
await sleep(2000);
|
|
47
|
+
else
|
|
48
|
+
throw translateError(e);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
this.conn.adopt(sb.sandboxId, sb);
|
|
52
|
+
try {
|
|
53
|
+
const box = Sandbox.fromView(this.conn, await this.getView(sb.sandboxId));
|
|
54
|
+
if (p.snapshot)
|
|
55
|
+
box.snapshot = p.snapshot;
|
|
56
|
+
if (t.isPublic)
|
|
57
|
+
await box.setPublic(true);
|
|
58
|
+
return box;
|
|
59
|
+
}
|
|
60
|
+
catch (e) {
|
|
61
|
+
// Never leave a running sandbox behind a failed create.
|
|
62
|
+
await this.conn.solari.kill(sb.sandboxId).catch(() => undefined);
|
|
63
|
+
this.conn.forget(sb.sandboxId);
|
|
64
|
+
throw translateError(e);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async getView(id) {
|
|
68
|
+
for (let i = 0;; i++) {
|
|
69
|
+
try {
|
|
70
|
+
return await this.conn.solari.get(id);
|
|
71
|
+
}
|
|
72
|
+
catch (e) {
|
|
73
|
+
if (e instanceof GatewayError && e.status === 404 && i < 5) {
|
|
74
|
+
await sleep(300 * (i + 1));
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
throw e;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** A sandbox by id or by name. */
|
|
82
|
+
async get(sandboxIdOrName) {
|
|
83
|
+
try {
|
|
84
|
+
const v = await this.conn.solari.get(sandboxIdOrName);
|
|
85
|
+
if (v.state !== "gone")
|
|
86
|
+
return Sandbox.fromView(this.conn, v);
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
if (!(e instanceof GatewayError && (e.status === 404 || e.status === 400)))
|
|
90
|
+
throw translateError(e);
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
const r = await this.conn.solari.list({ metadata: { [K_NAME]: sandboxIdOrName }, limit: 50 });
|
|
94
|
+
const hit = r.sandboxes.filter((s) => s.state !== "gone")[0];
|
|
95
|
+
if (hit)
|
|
96
|
+
return Sandbox.fromView(this.conn, hit);
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
throw translateError(e);
|
|
100
|
+
}
|
|
101
|
+
throw new DaytonaNotFoundError(`Sandbox with ID or name ${sandboxIdOrName} not found`, 404);
|
|
102
|
+
}
|
|
103
|
+
/** Sandboxes, optionally filtered by `labels` and `states`. Iterable with `for await`; `items` holds them all. */
|
|
104
|
+
async list(query = {}) {
|
|
105
|
+
const q = query;
|
|
106
|
+
const labels = "labels" in q || "states" in q || "limit" in q ? q.labels : query;
|
|
107
|
+
const items = [];
|
|
108
|
+
let cursor;
|
|
109
|
+
try {
|
|
110
|
+
do {
|
|
111
|
+
const r = await this.conn.solari.list({ ...(labels && Object.keys(labels).length ? { metadata: labels } : {}), limit: 100, ...(cursor ? { cursor } : {}) });
|
|
112
|
+
for (const v of r.sandboxes) {
|
|
113
|
+
if (v.state === "gone")
|
|
114
|
+
continue;
|
|
115
|
+
if (q.states && !q.states.includes(mapState(v.state)))
|
|
116
|
+
continue;
|
|
117
|
+
items.push(Sandbox.fromView(this.conn, v));
|
|
118
|
+
}
|
|
119
|
+
cursor = r.nextCursor;
|
|
120
|
+
} while (cursor && items.length < (q.limit ?? 1000));
|
|
121
|
+
}
|
|
122
|
+
catch (e) {
|
|
123
|
+
throw translateError(e);
|
|
124
|
+
}
|
|
125
|
+
const out = items.slice(0, q.limit ?? 1000);
|
|
126
|
+
return {
|
|
127
|
+
items: out,
|
|
128
|
+
total: out.length,
|
|
129
|
+
page: 1,
|
|
130
|
+
totalPages: 1,
|
|
131
|
+
async *[Symbol.asyncIterator]() {
|
|
132
|
+
for (const s of out)
|
|
133
|
+
yield s;
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
async start(sandbox, timeout) {
|
|
138
|
+
await sandbox.start(timeout);
|
|
139
|
+
}
|
|
140
|
+
async stop(sandbox) {
|
|
141
|
+
await sandbox.stop();
|
|
142
|
+
}
|
|
143
|
+
async delete(sandbox, timeout = 60, wait = false) {
|
|
144
|
+
await sandbox.delete(timeout, wait);
|
|
145
|
+
}
|
|
146
|
+
async fork(sandbox, params, timeout = 60) {
|
|
147
|
+
return sandbox.fork(params, timeout);
|
|
148
|
+
}
|
|
149
|
+
_experimental_fork(sandbox, params, timeout) {
|
|
150
|
+
return this.fork(sandbox, params, timeout);
|
|
151
|
+
}
|
|
152
|
+
async [Symbol.asyncDispose]() {
|
|
153
|
+
/* nothing to flush */
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
export { SolariCompatUnsupported };
|
|
157
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/conn.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { HttpTransport, type Sandbox } from "@solarisdk/core";
|
|
2
|
+
import { SandboxClient } from "@solarisdk/sandbox";
|
|
3
|
+
export declare const DEFAULT_BASE_URL = "https://api.getsolari.com";
|
|
4
|
+
export declare const DEFAULT_HOME = "/root";
|
|
5
|
+
/** A non-login bash when the image has one, else sh. The command is "$1", so the wrapper never re-parses it. */
|
|
6
|
+
export declare const NATIVE_SHELL_SCRIPT = "if [ -x /bin/bash ]; then exec /bin/bash -c \"$1\"; else exec /bin/sh -c \"$1\"; fi";
|
|
7
|
+
export declare function shellArgs(native: boolean, command: string): [string, string[]];
|
|
8
|
+
/** Whether an inherited base URL may receive a Solari key: https on getsolari.com or a subdomain, or loopback. */
|
|
9
|
+
export declare function isSolariBaseUrl(raw: string): boolean;
|
|
10
|
+
export declare const sleep: (ms: number) => Promise<void>;
|
|
11
|
+
export interface DaytonaConfig {
|
|
12
|
+
/** Daytona's API key option. Only a Solari key (`slr_…`) is ever used or sent. */
|
|
13
|
+
apiKey?: string | undefined;
|
|
14
|
+
/** Daytona's API URL option. Used as given. */
|
|
15
|
+
apiUrl?: string | undefined;
|
|
16
|
+
/** Not supported. */
|
|
17
|
+
jwtToken?: string | undefined;
|
|
18
|
+
/** Not supported. */
|
|
19
|
+
organizationId?: string | undefined;
|
|
20
|
+
/** Accepted; Solari has no regions, so it is ignored with a warning. */
|
|
21
|
+
target?: string | undefined;
|
|
22
|
+
/** Accepted and ignored: lifecycle calls always poll. */
|
|
23
|
+
useDeprecatedPolling?: boolean | undefined;
|
|
24
|
+
/** Test hook: a fetch implementation (fake gateway). */
|
|
25
|
+
fetch?: typeof fetch | undefined;
|
|
26
|
+
}
|
|
27
|
+
export declare class Conn {
|
|
28
|
+
readonly apiKey: string;
|
|
29
|
+
readonly baseURL: string;
|
|
30
|
+
readonly solari: SandboxClient;
|
|
31
|
+
readonly http: HttpTransport;
|
|
32
|
+
/** Snapshot names this client created → ids, so a name resolves without listing the whole org. */
|
|
33
|
+
readonly snapshotNames: Map<string, string>;
|
|
34
|
+
private readonly handles;
|
|
35
|
+
private readonly natives;
|
|
36
|
+
private readonly homes;
|
|
37
|
+
constructor(cfg?: DaytonaConfig);
|
|
38
|
+
/** Live control handle for a sandbox, cached per id. */
|
|
39
|
+
handle(id: string): Promise<Sandbox>;
|
|
40
|
+
adopt(id: string, sb: Sandbox): void;
|
|
41
|
+
setHandle(id: string, sb: Sandbox): void;
|
|
42
|
+
dropHandle(id: string): void;
|
|
43
|
+
/** Run `fn` on the live handle. If the control channel was closed under us (typically the first call after a resume), reconnect and retry. */
|
|
44
|
+
on<T>(id: string, fn: (sb: Sandbox) => Promise<T>): Promise<T>;
|
|
45
|
+
/** Retry a gateway call that answered a transient, explicitly retryable 503 (for about 40 s). */
|
|
46
|
+
retry<T>(fn: () => Promise<T>): Promise<T>;
|
|
47
|
+
/** Is this a native `FROM <image>` sandbox? Commands there use a non-login shell (a login shell resets PATH on Debian). */
|
|
48
|
+
isNative(id: string): Promise<boolean>;
|
|
49
|
+
shellFor(id: string, command: string): Promise<[string, string[]]>;
|
|
50
|
+
/** The guest's $HOME, created if missing (commands and relative paths start there). */
|
|
51
|
+
home(id: string): Promise<string>;
|
|
52
|
+
forget(id: string): void;
|
|
53
|
+
abs(id: string, p: string): Promise<string>;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=conn.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conn.d.ts","sourceRoot":"","sources":["../src/conn.ts"],"names":[],"mappings":"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"}
|