@declaw/sdk 1.0.4 → 1.1.0
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 +23 -0
- package/dist/index.cjs +119 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -1
- package/dist/index.d.ts +58 -1
- package/dist/index.js +115 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,29 @@ All notable changes to the Declaw TypeScript / JavaScript SDK are documented in
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.1.0]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Volumes API.** Upload a tarball once, attach it to one or many
|
|
13
|
+
sandboxes at create time. The server streams the blob from object
|
|
14
|
+
storage into each sandbox's overlay filesystem at boot — so N
|
|
15
|
+
parallel sandboxes share a dataset without N uploads.
|
|
16
|
+
- New `Volumes` class with static `create` / `get` / `list` /
|
|
17
|
+
`delete` methods. Body is a `Uint8Array` or `ArrayBuffer`;
|
|
18
|
+
streams end-to-end with no in-memory buffering on the server.
|
|
19
|
+
- New types: `VolumeInfo`, `VolumeAttachment`, `VolumeCreateOpts`,
|
|
20
|
+
`VolumeRequestOpts` — exported from the package root.
|
|
21
|
+
- `SandboxOpts.volumes?: VolumeAttachment[]` on `Sandbox.create` —
|
|
22
|
+
each attachment is `{ volumeId, mountPath }`. Multiple sandboxes
|
|
23
|
+
can attach the same `volumeId` in parallel.
|
|
24
|
+
- Helper functions `parseVolumeInfo` (wire → shape) and
|
|
25
|
+
`volumeAttachmentToJSON` (shape → wire).
|
|
26
|
+
- Phase 1 limits: upload body capped at 4 GiB; format must be
|
|
27
|
+
`application/gzip` (tar.gz); volumes are read-at-boot (sandbox
|
|
28
|
+
writes do not flow back). Symlinks, hardlinks, device nodes, and
|
|
29
|
+
entries containing `..` are dropped server-side for safety.
|
|
30
|
+
|
|
8
31
|
## [1.0.4]
|
|
9
32
|
|
|
10
33
|
### Changed
|
package/dist/index.cjs
CHANGED
|
@@ -54,6 +54,7 @@ __export(index_exports, {
|
|
|
54
54
|
TemplateError: () => TemplateError,
|
|
55
55
|
TimeoutError: () => TimeoutError,
|
|
56
56
|
TransformDirection: () => TransformDirection,
|
|
57
|
+
Volumes: () => Volumes,
|
|
57
58
|
WatchHandle: () => WatchHandle,
|
|
58
59
|
applyTransformation: () => applyTransformation,
|
|
59
60
|
codeSecurityConfigToJSON: () => codeSecurityConfigToJSON,
|
|
@@ -92,11 +93,13 @@ __export(index_exports, {
|
|
|
92
93
|
parseSnapshotInfo: () => parseSnapshotInfo,
|
|
93
94
|
parseTemplateBuildStatus: () => parseTemplateBuildStatus,
|
|
94
95
|
parseToxicityConfig: () => parseToxicityConfig,
|
|
96
|
+
parseVolumeInfo: () => parseVolumeInfo,
|
|
95
97
|
parseWriteInfo: () => parseWriteInfo,
|
|
96
98
|
requiresTlsInterception: () => requiresTlsInterception,
|
|
97
99
|
securityPolicyToJSON: () => securityPolicyToJSON,
|
|
98
100
|
toxicityConfigToJSON: () => toxicityConfigToJSON,
|
|
99
|
-
validateNetworkEntry: () => validateNetworkEntry
|
|
101
|
+
validateNetworkEntry: () => validateNetworkEntry,
|
|
102
|
+
volumeAttachmentToJSON: () => volumeAttachmentToJSON
|
|
100
103
|
});
|
|
101
104
|
module.exports = __toCommonJS(index_exports);
|
|
102
105
|
|
|
@@ -1795,6 +1798,23 @@ var Pty = class {
|
|
|
1795
1798
|
}
|
|
1796
1799
|
};
|
|
1797
1800
|
|
|
1801
|
+
// src/volumes/models.ts
|
|
1802
|
+
function parseVolumeInfo(data) {
|
|
1803
|
+
return {
|
|
1804
|
+
volumeId: String(data.volume_id ?? ""),
|
|
1805
|
+
ownerId: String(data.owner_id ?? ""),
|
|
1806
|
+
name: String(data.name ?? ""),
|
|
1807
|
+
blobKey: String(data.blob_key ?? ""),
|
|
1808
|
+
sizeBytes: Number(data.size_bytes ?? 0),
|
|
1809
|
+
contentType: String(data.content_type ?? ""),
|
|
1810
|
+
metadata: data.metadata ?? {},
|
|
1811
|
+
createdAt: String(data.created_at ?? "")
|
|
1812
|
+
};
|
|
1813
|
+
}
|
|
1814
|
+
function volumeAttachmentToJSON(att) {
|
|
1815
|
+
return { volume_id: att.volumeId, mount_path: att.mountPath };
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1798
1818
|
// src/sandbox/sandbox.ts
|
|
1799
1819
|
var DEFAULT_TEMPLATE = "base";
|
|
1800
1820
|
var DEFAULT_TIMEOUT = 300;
|
|
@@ -1951,6 +1971,9 @@ var Sandbox = class _Sandbox {
|
|
|
1951
1971
|
if (opts?.lifecycle) {
|
|
1952
1972
|
body.lifecycle = lifecycleToJSON(opts.lifecycle);
|
|
1953
1973
|
}
|
|
1974
|
+
if (opts?.volumes && opts.volumes.length > 0) {
|
|
1975
|
+
body.volumes = opts.volumes.map(volumeAttachmentToJSON);
|
|
1976
|
+
}
|
|
1954
1977
|
const data = await client.post("/sandboxes", {
|
|
1955
1978
|
json: body,
|
|
1956
1979
|
timeout: opts?.requestTimeout
|
|
@@ -2544,6 +2567,97 @@ var Template = class {
|
|
|
2544
2567
|
}
|
|
2545
2568
|
}
|
|
2546
2569
|
};
|
|
2570
|
+
|
|
2571
|
+
// src/volumes/volumes.ts
|
|
2572
|
+
var VALID_VOLUME_ID_RE = /^[a-zA-Z0-9_-]+$/;
|
|
2573
|
+
function assertValidVolumeId(id) {
|
|
2574
|
+
if (!id || !VALID_VOLUME_ID_RE.test(id)) {
|
|
2575
|
+
throw new InvalidArgumentError(
|
|
2576
|
+
`Invalid volume ID: "${id}". Must be alphanumeric with hyphens/underscores only.`
|
|
2577
|
+
);
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
var Volumes = class {
|
|
2581
|
+
/** Create a volume by streaming a tarball to the server. */
|
|
2582
|
+
static async create(name, data, opts) {
|
|
2583
|
+
if (!name) {
|
|
2584
|
+
throw new InvalidArgumentError("volume name is required");
|
|
2585
|
+
}
|
|
2586
|
+
const config = new ConnectionConfig({
|
|
2587
|
+
apiKey: opts?.apiKey,
|
|
2588
|
+
domain: opts?.domain,
|
|
2589
|
+
apiUrl: opts?.apiUrl,
|
|
2590
|
+
requestTimeout: opts?.requestTimeout
|
|
2591
|
+
});
|
|
2592
|
+
const client = new ApiClient(config);
|
|
2593
|
+
try {
|
|
2594
|
+
const body = data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
2595
|
+
const resp = await client.post("/volumes", {
|
|
2596
|
+
params: { name },
|
|
2597
|
+
body,
|
|
2598
|
+
headers: { "Content-Type": opts?.contentType ?? "application/gzip" },
|
|
2599
|
+
timeout: opts?.requestTimeout
|
|
2600
|
+
});
|
|
2601
|
+
return parseVolumeInfo(resp);
|
|
2602
|
+
} finally {
|
|
2603
|
+
client.close();
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
/** Fetch metadata for a single volume. */
|
|
2607
|
+
static async get(volumeId, opts) {
|
|
2608
|
+
assertValidVolumeId(volumeId);
|
|
2609
|
+
const config = new ConnectionConfig({
|
|
2610
|
+
apiKey: opts?.apiKey,
|
|
2611
|
+
domain: opts?.domain,
|
|
2612
|
+
apiUrl: opts?.apiUrl,
|
|
2613
|
+
requestTimeout: opts?.requestTimeout
|
|
2614
|
+
});
|
|
2615
|
+
const client = new ApiClient(config);
|
|
2616
|
+
try {
|
|
2617
|
+
const resp = await client.get(`/volumes/${volumeId}`, {
|
|
2618
|
+
timeout: opts?.requestTimeout
|
|
2619
|
+
});
|
|
2620
|
+
return parseVolumeInfo(resp);
|
|
2621
|
+
} finally {
|
|
2622
|
+
client.close();
|
|
2623
|
+
}
|
|
2624
|
+
}
|
|
2625
|
+
/** List all volumes owned by the caller, newest first. */
|
|
2626
|
+
static async list(opts) {
|
|
2627
|
+
const config = new ConnectionConfig({
|
|
2628
|
+
apiKey: opts?.apiKey,
|
|
2629
|
+
domain: opts?.domain,
|
|
2630
|
+
apiUrl: opts?.apiUrl,
|
|
2631
|
+
requestTimeout: opts?.requestTimeout
|
|
2632
|
+
});
|
|
2633
|
+
const client = new ApiClient(config);
|
|
2634
|
+
try {
|
|
2635
|
+
const resp = await client.get("/volumes", {
|
|
2636
|
+
timeout: opts?.requestTimeout
|
|
2637
|
+
});
|
|
2638
|
+
const rows = resp.volumes ?? [];
|
|
2639
|
+
return rows.map(parseVolumeInfo);
|
|
2640
|
+
} finally {
|
|
2641
|
+
client.close();
|
|
2642
|
+
}
|
|
2643
|
+
}
|
|
2644
|
+
/** Delete a volume and its blob. Idempotent on the wire. */
|
|
2645
|
+
static async delete(volumeId, opts) {
|
|
2646
|
+
assertValidVolumeId(volumeId);
|
|
2647
|
+
const config = new ConnectionConfig({
|
|
2648
|
+
apiKey: opts?.apiKey,
|
|
2649
|
+
domain: opts?.domain,
|
|
2650
|
+
apiUrl: opts?.apiUrl,
|
|
2651
|
+
requestTimeout: opts?.requestTimeout
|
|
2652
|
+
});
|
|
2653
|
+
const client = new ApiClient(config);
|
|
2654
|
+
try {
|
|
2655
|
+
await client.delete(`/volumes/${volumeId}`, { timeout: opts?.requestTimeout });
|
|
2656
|
+
} finally {
|
|
2657
|
+
client.close();
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2660
|
+
};
|
|
2547
2661
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2548
2662
|
0 && (module.exports = {
|
|
2549
2663
|
ALL_TRAFFIC,
|
|
@@ -2580,6 +2694,7 @@ var Template = class {
|
|
|
2580
2694
|
TemplateError,
|
|
2581
2695
|
TimeoutError,
|
|
2582
2696
|
TransformDirection,
|
|
2697
|
+
Volumes,
|
|
2583
2698
|
WatchHandle,
|
|
2584
2699
|
applyTransformation,
|
|
2585
2700
|
codeSecurityConfigToJSON,
|
|
@@ -2618,10 +2733,12 @@ var Template = class {
|
|
|
2618
2733
|
parseSnapshotInfo,
|
|
2619
2734
|
parseTemplateBuildStatus,
|
|
2620
2735
|
parseToxicityConfig,
|
|
2736
|
+
parseVolumeInfo,
|
|
2621
2737
|
parseWriteInfo,
|
|
2622
2738
|
requiresTlsInterception,
|
|
2623
2739
|
securityPolicyToJSON,
|
|
2624
2740
|
toxicityConfigToJSON,
|
|
2625
|
-
validateNetworkEntry
|
|
2741
|
+
validateNetworkEntry,
|
|
2742
|
+
volumeAttachmentToJSON
|
|
2626
2743
|
});
|
|
2627
2744
|
//# sourceMappingURL=index.cjs.map
|