@arker-ai/sdk 0.2.1 → 0.5.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 CHANGED
@@ -1,9 +1,6 @@
1
- # Arker TypeScript SDK
1
+ # Arker TypeScript SDK
2
2
 
3
- TypeScript client for the [Arker](https://arker.ai) virtual computer
4
- platform. Spawn isolated Linux sandboxes, run shell / Python / Node
5
- code in them, read and write files. Zero runtime dependencies (uses
6
- the platform's built-in `fetch` and `crypto`).
3
+ A small, typed wrapper around the Arker VM API: fork a machine, run commands, sync files.
7
4
 
8
5
  ## Install
9
6
 
@@ -11,126 +8,70 @@ the platform's built-in `fetch` and `crypto`).
11
8
  npm install @arker-ai/sdk
12
9
  ```
13
10
 
14
- Works in Node 18. ESM + CJS + types all included.
11
+ Node 18+. The client reads your key from `ARKER_API_KEY` get one in the [console](https://arker.ai/console).
15
12
 
16
13
  ## Quickstart
17
14
 
18
15
  ```ts
19
- import { Arker, ArkerError } from "@arker-ai/sdk";
16
+ import { Arker } from "@arker-ai/sdk";
20
17
 
21
- const arker = new Arker({ apiKey: "ark_live_..." });
22
- const vm = await arker.vm("arkuntu").fork({ name: "hello" });
18
+ const ar = new Arker({ region: "us-west-2" });
23
19
 
24
- const result = await vm.run("python3 -c 'print(2+2)'");
25
- console.log(new TextDecoder().decode(result.stdout)); // "4\n"
20
+ // Fork a public golden, run a command, read/write a file.
21
+ const vm = await ar.fork("ubuntu-full"); // public golden — org inferred
26
22
 
27
- await vm.sync.writeFile("/home/user/data.csv", "a,b\n1,2\n");
28
- const data = await vm.sync.readFile("/home/user/data.csv");
23
+ const run = await vm.run("python3 -c 'print(2 + 2)'");
24
+ if (run.type === "completed") console.log(new TextDecoder().decode(run.stdout));
25
+
26
+ await vm.sync("/tmp/data.txt", "hello\n"); // write
27
+ const data = await vm.sync("/tmp/data.txt"); // read -> Uint8Array
29
28
 
30
- const child = await vm.fork({ name: "branch" }); // constant-time copy-on-write
31
- await child.delete();
32
29
  await vm.delete();
33
30
  ```
34
31
 
35
- List your VMs:
32
+ ## Core API
36
33
 
37
34
  ```ts
38
- const page = await arker.list({ limit: 10, sort: "-created_at" });
39
- console.log(`${page.total} total`);
40
- for (const summary of page.items) {
41
- console.log(summary.vm_id, summary.name, summary.region, summary.created_at);
42
- }
43
- ```
44
-
45
- ## API
46
-
47
- ```
48
- new Arker({ apiKey, baseUrl? })
49
- .vm(vmId) -> Computer // open handle (no network call)
50
- .list({ limit?, offset?, q?, sort? }) -> Promise<VmList>
51
-
52
- Computer
53
- .id, .delete()
54
- .fork({ name?, isPublic?, region? }) -> Promise<Computer>
55
- .run(command, { sessionId?, timeout? }) -> Promise<RunResult>
56
- .sync.readFile(path) -> Promise<Uint8Array>
57
- .sync.writeFile(path, data: Uint8Array | string) -> Promise<void>
58
-
59
- RunResult: stdout, stderr (Uint8Array), exitCode, durationMs, sessionId, cwd
60
- VmSummary: vm_id, name, base_image, region, created_at (ISO 8601)
61
- VmList: items (VmSummary[]), total (number)
62
-
63
- ArkerError(code, message, status) extends Error // single error type
35
+ const ar = new Arker({ region, apiKey?, baseUrl?, retry? });
36
+
37
+ // VMs
38
+ await ar.fork("ubuntu-full"); // public golden by name (org inferred)
39
+ await ar.fork(vm, { name: "child" }); // an existing VM (uses its id)
40
+ await ar.fork({ sourceVmName, sourceOrgId, name?, durable? });
41
+ await ar.listVms({ state? });
42
+ ar.vm(vmId); // bare handle
43
+ await ar.vm(vmId).run(command, options?);
44
+ await ar.vm(vmId).resize({ vcpu_count, memory_mib });
45
+ await ar.vm(vmId).delete();
46
+
47
+ // Files inside a VM
48
+ await vm.sync(path); // read -> Uint8Array
49
+ await vm.sync(path, data); // write
50
+
51
+ // Filesystems standalone, persistent volumes
52
+ await ar.createFilesystem({ name });
53
+ await ar.listFilesystems();
54
+ await ar.deleteFilesystem(filesystemId);
55
+
56
+ // Syncs mount a filesystem into a VM at a path
57
+ await vm.createSync({ filesystemId, path });
58
+ await vm.listSyncs();
59
+ await vm.deleteSync(syncId);
64
60
  ```
65
61
 
66
- ### Routing
67
-
68
- `fork`, `run`, `sync`, and `delete` use the regional endpoint set on the
69
- client (default `https://aws-us-west-2.burst.arker.ai`).
62
+ `apiKey` falls back to `ARKER_API_KEY`; `region` to `ARKER_REGION`. Pass `baseUrl` for dev targets. Configure retries with `retry: { attempts, baseDelayMs, maxDelayMs }`, or `retry: false` to disable.
70
63
 
71
- `list` always goes through `https://arker.ai` regardless of `baseUrl`,
72
- because list data is served from a global host rather than a regional
73
- one.
64
+ ## Durability
74
65
 
75
- Public base-image names like `"arkuntu"` resolve to a ULID **client-side**
76
- (see `SOURCE_ALIASES` in `src/index.ts`), so `arker.vm("arkuntu").fork()`
77
- works on the default endpoint with no extra round-trip. Override
78
- `baseUrl` or set `ARKER_BASE_URL` to point at a different region or a
79
- self-hosted deployment.
80
-
81
- ### Errors
82
-
83
- Every server-side error becomes an `ArkerError`:
66
+ For long-running or non-idempotent work, fork with `durable: true` and pass an idempotency key when retrying a run:
84
67
 
85
68
  ```ts
86
- try {
87
- await vm.sync.readFile("/home/user/missing");
88
- } catch (err) {
89
- if (err instanceof ArkerError) {
90
- console.log(err.code); // "not_found"
91
- console.log(err.message); // "not_found: file not found: ..."
92
- console.log(err.status); // 404
93
- }
94
- }
69
+ const vm = await ar.fork("ubuntu-full", { durable: true });
70
+ await vm.run("python3 train.py", { background: true, idempotencyKey: crypto.randomUUID() });
95
71
  ```
96
72
 
97
- `code` is a stable enum: `bad_request`, `unauthorized`, `payment_required`,
98
- `forbidden`, `not_found`, `conflict`, `payload_too_large`, `internal`,
99
- `not_implemented`, `vm_busy`, `unsupported_*`, `command_not_found`.
100
-
101
- ### What the SDK does for you
102
-
103
- Hidden behind these six methods:
104
-
105
- - **Write strategy**: files up to 100 MB. Small payloads go in one call;
106
- larger ones use a direct upload path so the bytes don't traverse the
107
- API layer. `writeFile` resolves once the bytes are durably stored.
108
- - **Read coalescing**: `readFile` always resolves to a `Uint8Array`,
109
- regardless of whether the server inlined the content or returned a
110
- signed URL.
111
- - **Idempotent retry**: transient errors are retried with exponential
112
- backoff. Writes are server-side idempotent on `upload_id`, so retries
113
- never produce duplicates.
114
- - **Path validation**: only `/home/user/...` paths accepted; `..` rejected.
115
-
116
- ## Demo / smoke test
117
-
118
- Run the full surface against a live deployment:
119
-
120
- ```bash
121
- ARKER_API_KEY=ark_live_... npx tsx tests/demo.ts
122
- ```
123
-
124
- It exercises every method (`list`, `vm`, `fork`, `run`, `sync.writeFile`,
125
- `sync.readFile`, error path, child fork, `delete`) and prints what each
126
- call hits on the wire — useful as living documentation.
127
-
128
- To fork from a specific source VM instead of the default `arkuntu`:
129
-
130
- ```bash
131
- ARKER_API_KEY=ark_live_... ARKER_SOURCE_VM=01KQ... npx tsx tests/demo.ts
132
- ```
73
+ If the host fails mid-run, the run resumes on a healthy host with the VM's filesystem state preserved. Backends without durability return `ArkerError` code `unsupported_operation`.
133
74
 
134
75
  ## License
135
76
 
136
- Apache-2.0.
77
+ Apache-2.0