microsandbox-rb 0.5.9 → 0.5.10

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 045a5bf021edaf5afcfcf487cf0d980c38018560cc842c44018863570236f4ed
4
- data.tar.gz: 25791e8bab4051711794cb8c1e08bbabc2b4dbc79bf080b02908b620ee0bd06e
3
+ metadata.gz: d4d9e8db2dddac7a22c2910c82a56603e95ad702d328c6a020f514997d29859c
4
+ data.tar.gz: 5f19089f8d1d0f18d5d930cf49576d25862f02323495ffa02db683f57a3439cd
5
5
  SHA512:
6
- metadata.gz: 1b89148498194edb82241979432ee2e47599f2b657805b05718bfd18a8e1104318833ef84eb5f5e47a66f3cec8dc369f742897bbfe60cdb07fb613b597ef6ac5
7
- data.tar.gz: c25b033291b4fb5195349030dcf2296006fa8b3563c7e1f6804441ed5e554e496583b22ddbca32828dff1b36127082b4cb1e995ab654573afc46b09e012031fd
6
+ metadata.gz: 88e44654909dd3f39ac23c6cf682bd62519bbaf7f57ca24f611a66e05bb66c825919fc1f2be6f9044513c99508bfedd412e5c72c1f15fc8b66c3ac11ee2b78ac
7
+ data.tar.gz: 00b0f44a4568107891a2ce9a623950245457ea51d0700f45333b96fec7eb73e6572b8b9b67b4147490423687fa1ff7dcb96b6edd29c2aa28c3ed22807eab7bdb
data/CHANGELOG.md CHANGED
@@ -6,6 +6,83 @@ upstream microsandbox runtime.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.5.10] - 2026-06-22
10
+
11
+ ### Added
12
+
13
+ - **Streaming stdin pipe for `exec_stream`/`shell_stream`** (`stdin: :pipe`).
14
+ Opens a writable `ExecHandle#stdin` sink (`ExecStdin`) lifted out of the core
15
+ handle via `take_stdin`, distinct from the existing fixed-bytes `stdin:`
16
+ buffer. This is the load-bearing primitive for driving an interactive
17
+ long-running process (e.g. a `claude` CLI) over `exec_stream` from a host
18
+ reactor. The published `0.5.9` shipped without it (`stdin: :pipe` was fed as
19
+ the literal byte string `"pipe"`), so any consumer of the streaming sink must
20
+ require `>= 0.5.10`.
21
+
22
+ Adopts the upstream **microsandbox `v0.5.8`** runtime (was `v0.5.7`), whose
23
+ backend-routing rewrite (upstream PR #754) both adds new surface and reshapes the
24
+ sandbox lifecycle.
25
+
26
+ ### Changed
27
+
28
+ - **BREAKING — sandbox lifecycle split (mirrors the official Python/Node SDKs).**
29
+ Upstream `v0.5.8` split the lifecycle across a live `Sandbox` and a lightweight
30
+ `SandboxHandle`. The gem follows suit:
31
+ - The live `Microsandbox::Sandbox` (from `Sandbox.create`/`Sandbox.start`) now
32
+ exposes `#stop`, `#stop_and_wait`, `#kill`, `#drain`, `#wait`, `#status`,
33
+ `#detach`, and `#owns_lifecycle?`. `#stop` and `#kill` **no longer take a
34
+ `timeout:`** keyword; `#stop` performs the graceful SIGTERM→SIGKILL
35
+ escalation (10s default) the official SDKs use.
36
+ - `#request_stop`, `#request_kill`, `#request_drain`, `#wait_until_stopped`,
37
+ and a custom stop/kill timeout have **moved off** the live `Sandbox` onto the
38
+ controllable `Microsandbox::SandboxHandle` (see Added).
39
+ - **BREAKING — `Sandbox.get`/`.list`/`.list_with` now return a controllable
40
+ `Microsandbox::SandboxHandle`** instead of a read-only `SandboxInfo`. The
41
+ handle keeps the same metadata accessors (`name`, `status`, `created_at`,
42
+ `updated_at`, `running?`, `stopped?`). `Microsandbox::SandboxInfo` remains as a
43
+ deprecated constant alias for `SandboxHandle`.
44
+ - `SandboxStatus` gained two values, `:created` and `:starting` (cloud-only
45
+ today), so `#status` may now return them.
46
+
47
+ ### Added
48
+
49
+ - **Backend routing** — `Microsandbox.set_default_backend(kind, url:, api_key:,
50
+ profile:)`, `Microsandbox.with_backend(kind, …) { … }` (a scoped, restoring
51
+ override), and `Microsandbox.default_backend_kind`. Without configuration the
52
+ runtime resolves a backend lazily from `MSB_BACKEND`, `MSB_API_URL` +
53
+ `MSB_API_KEY`, `MSB_PROFILE`, and `~/.microsandbox/config.json` (honoring
54
+ `MSB_CONFIG_PATH`). The cloud backend supports a documented subset
55
+ (create/start/stop/remove/get/list, one-shot exec, follow log streaming);
56
+ unsupported operations raise `UnsupportedError`. Under a cloud backend,
57
+ `Sandbox.create`/`.start` skip local `msb`/`libkrunfw` runtime provisioning
58
+ (it isn't needed), so cloud-only hosts no longer trigger a spurious download.
59
+ - **`Microsandbox::SandboxHandle`** — the controllable handle returned by
60
+ `Sandbox.get`/`.list`/`.list_with`: `#stop`, `#stop_with_timeout(secs)`,
61
+ `#kill`, `#kill_with_timeout(secs)`, `#request_stop`, `#request_kill`,
62
+ `#request_drain`, `#wait_until_stopped` (→ `SandboxStopResult`), plus the
63
+ metadata accessors. Mirrors the official SDKs' `SandboxHandle`.
64
+ - **`Sandbox#stop_and_wait` / `Sandbox#wait`** — return a `Microsandbox::ExitStatus`
65
+ (`#exit_code`, `#success?`). **`Sandbox#drain`** triggers a graceful drain.
66
+ **`Sandbox#status`** fetches the live status from the backend.
67
+ - **`Microsandbox.libkrunfw_path=`** — overrides the `libkrunfw` shared-library
68
+ path (SDK tier of the resolver; `MSB_LIBKRUNFW_PATH` still wins). Mirrors
69
+ `runtime_path=`.
70
+ - **`Microsandbox::CloudHttpError`** (`cloud-http`) and
71
+ **`Microsandbox::UnsupportedError`** (`unsupported`) — distinct from the
72
+ existing `UnsupportedOperationError`.
73
+
74
+ ### Fixed
75
+
76
+ - **Reject invalid durations with a clear `ArgumentError`** — negative, `NaN`,
77
+ and infinite values passed to `timeout:` (`exec`/`shell`),
78
+ `SandboxHandle#stop_with_timeout`/`#kill_with_timeout`, `replace_with_timeout:`,
79
+ and `metrics_stream(interval:)` are rejected in Ruby before reaching the native
80
+ layer, where they would otherwise panic across the FFI boundary
81
+ (`Duration::from_secs_f64` panics on exactly those inputs).
82
+ - **Reject contradictory `image:` + `from_snapshot:`** — `Sandbox.create` now
83
+ raises `ArgumentError` when both are given (a sandbox boots from exactly one
84
+ rootfs source), failing fast instead of after a runtime round-trip.
85
+
9
86
  ## [0.5.9] - 2026-06-18
10
87
 
11
88
  Closes the remaining roadmap items, bringing the binding surface to parity with
data/Cargo.lock CHANGED
@@ -3003,8 +3003,8 @@ dependencies = [
3003
3003
 
3004
3004
  [[package]]
3005
3005
  name = "microsandbox"
3006
- version = "0.5.7"
3007
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.7#4dbb712bfd636f8964939a5317f749ba111e6a6d"
3006
+ version = "0.5.8"
3007
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3008
3008
  dependencies = [
3009
3009
  "anyhow",
3010
3010
  "astral-tokio-tar",
@@ -3031,6 +3031,7 @@ dependencies = [
3031
3031
  "microsandbox-network",
3032
3032
  "microsandbox-protocol",
3033
3033
  "microsandbox-runtime",
3034
+ "microsandbox-types",
3034
3035
  "microsandbox-utils",
3035
3036
  "nix 0.31.3",
3036
3037
  "notify",
@@ -3047,6 +3048,7 @@ dependencies = [
3047
3048
  "tempfile",
3048
3049
  "thiserror 2.0.18",
3049
3050
  "tokio",
3051
+ "tokio-tungstenite",
3050
3052
  "tracing",
3051
3053
  "typed-builder",
3052
3054
  "which",
@@ -3054,8 +3056,8 @@ dependencies = [
3054
3056
 
3055
3057
  [[package]]
3056
3058
  name = "microsandbox-agent-client"
3057
- version = "0.5.7"
3058
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.7#4dbb712bfd636f8964939a5317f749ba111e6a6d"
3059
+ version = "0.5.8"
3060
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3059
3061
  dependencies = [
3060
3062
  "ciborium",
3061
3063
  "microsandbox-protocol",
@@ -3067,8 +3069,8 @@ dependencies = [
3067
3069
 
3068
3070
  [[package]]
3069
3071
  name = "microsandbox-db"
3070
- version = "0.5.7"
3071
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.7#4dbb712bfd636f8964939a5317f749ba111e6a6d"
3072
+ version = "0.5.8"
3073
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3072
3074
  dependencies = [
3073
3075
  "async-trait",
3074
3076
  "sea-orm",
@@ -3079,8 +3081,8 @@ dependencies = [
3079
3081
 
3080
3082
  [[package]]
3081
3083
  name = "microsandbox-filesystem"
3082
- version = "0.5.7"
3083
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.7#4dbb712bfd636f8964939a5317f749ba111e6a6d"
3084
+ version = "0.5.8"
3085
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3084
3086
  dependencies = [
3085
3087
  "libc",
3086
3088
  "microsandbox-utils",
@@ -3092,8 +3094,8 @@ dependencies = [
3092
3094
 
3093
3095
  [[package]]
3094
3096
  name = "microsandbox-image"
3095
- version = "0.5.7"
3096
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.7#4dbb712bfd636f8964939a5317f749ba111e6a6d"
3097
+ version = "0.5.8"
3098
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3097
3099
  dependencies = [
3098
3100
  "astral-tokio-tar",
3099
3101
  "async-compression",
@@ -3118,8 +3120,8 @@ dependencies = [
3118
3120
 
3119
3121
  [[package]]
3120
3122
  name = "microsandbox-metrics"
3121
- version = "0.5.7"
3122
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.7#4dbb712bfd636f8964939a5317f749ba111e6a6d"
3123
+ version = "0.5.8"
3124
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3123
3125
  dependencies = [
3124
3126
  "chrono",
3125
3127
  "libc",
@@ -3129,8 +3131,8 @@ dependencies = [
3129
3131
 
3130
3132
  [[package]]
3131
3133
  name = "microsandbox-migration"
3132
- version = "0.5.7"
3133
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.7#4dbb712bfd636f8964939a5317f749ba111e6a6d"
3134
+ version = "0.5.8"
3135
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3134
3136
  dependencies = [
3135
3137
  "sea-orm-migration",
3136
3138
  "serde_json",
@@ -3138,8 +3140,8 @@ dependencies = [
3138
3140
 
3139
3141
  [[package]]
3140
3142
  name = "microsandbox-network"
3141
- version = "0.5.7"
3142
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.7#4dbb712bfd636f8964939a5317f749ba111e6a6d"
3143
+ version = "0.5.8"
3144
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3143
3145
  dependencies = [
3144
3146
  "base64",
3145
3147
  "bytes",
@@ -3178,11 +3180,12 @@ dependencies = [
3178
3180
 
3179
3181
  [[package]]
3180
3182
  name = "microsandbox-protocol"
3181
- version = "0.5.7"
3182
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.7#4dbb712bfd636f8964939a5317f749ba111e6a6d"
3183
+ version = "0.5.8"
3184
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3183
3185
  dependencies = [
3184
3186
  "chrono",
3185
3187
  "ciborium",
3188
+ "microsandbox-types",
3186
3189
  "serde",
3187
3190
  "serde_bytes",
3188
3191
  "strum 0.28.0",
@@ -3192,19 +3195,21 @@ dependencies = [
3192
3195
 
3193
3196
  [[package]]
3194
3197
  name = "microsandbox-runtime"
3195
- version = "0.5.7"
3196
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.7#4dbb712bfd636f8964939a5317f749ba111e6a6d"
3198
+ version = "0.5.8"
3199
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3197
3200
  dependencies = [
3198
3201
  "bytes",
3199
3202
  "chrono",
3200
3203
  "clap",
3201
3204
  "crossbeam-queue",
3202
3205
  "libc",
3206
+ "microsandbox-agent-client",
3203
3207
  "microsandbox-db",
3204
3208
  "microsandbox-filesystem",
3205
3209
  "microsandbox-metrics",
3206
3210
  "microsandbox-network",
3207
3211
  "microsandbox-protocol",
3212
+ "microsandbox-types",
3208
3213
  "microsandbox-utils",
3209
3214
  "msb_krun",
3210
3215
  "nix 0.31.3",
@@ -3218,10 +3223,22 @@ dependencies = [
3218
3223
  "tracing",
3219
3224
  ]
3220
3225
 
3226
+ [[package]]
3227
+ name = "microsandbox-types"
3228
+ version = "0.5.8"
3229
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3230
+ dependencies = [
3231
+ "chrono",
3232
+ "serde",
3233
+ "serde_json",
3234
+ "sha2 0.11.0",
3235
+ "thiserror 2.0.18",
3236
+ ]
3237
+
3221
3238
  [[package]]
3222
3239
  name = "microsandbox-utils"
3223
- version = "0.5.7"
3224
- source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.7#4dbb712bfd636f8964939a5317f749ba111e6a6d"
3240
+ version = "0.5.8"
3241
+ source = "git+https://github.com/superradcompany/microsandbox?tag=v0.5.8#47d0cdf1ef3b4b41885eb3efd67b759fd5540e9e"
3225
3242
  dependencies = [
3226
3243
  "dirs",
3227
3244
  "libc",
@@ -3232,7 +3249,7 @@ dependencies = [
3232
3249
 
3233
3250
  [[package]]
3234
3251
  name = "microsandbox_rb"
3235
- version = "0.5.9"
3252
+ version = "0.5.10"
3236
3253
  dependencies = [
3237
3254
  "chrono",
3238
3255
  "futures",
@@ -3306,9 +3323,9 @@ dependencies = [
3306
3323
 
3307
3324
  [[package]]
3308
3325
  name = "msb_krun"
3309
- version = "0.1.16"
3326
+ version = "0.1.17"
3310
3327
  source = "registry+https://github.com/rust-lang/crates.io-index"
3311
- checksum = "5df0f4dbc4771ed8df8a7ed584221e48bc3fe1726242378332a02ce27518ca53"
3328
+ checksum = "72a554acf513be16b336fbcd4a9bab29a78b06a5ddf94e917481cfeafc1078f5"
3312
3329
  dependencies = [
3313
3330
  "crossbeam-channel",
3314
3331
  "kvm-bindings",
@@ -3326,9 +3343,9 @@ dependencies = [
3326
3343
 
3327
3344
  [[package]]
3328
3345
  name = "msb_krun_arch"
3329
- version = "0.1.16"
3346
+ version = "0.1.17"
3330
3347
  source = "registry+https://github.com/rust-lang/crates.io-index"
3331
- checksum = "923b2f7ed0d299b37ea9bbc47e9d8fe1a46c44e1ecf1d9ecf306377b20f90762"
3348
+ checksum = "9d270d914cee3125cf71734b9a5aa60fe7d9648f09511999199424e0fe1a88c6"
3332
3349
  dependencies = [
3333
3350
  "kvm-bindings",
3334
3351
  "kvm-ioctls",
@@ -3342,15 +3359,15 @@ dependencies = [
3342
3359
 
3343
3360
  [[package]]
3344
3361
  name = "msb_krun_arch_gen"
3345
- version = "0.1.16"
3362
+ version = "0.1.17"
3346
3363
  source = "registry+https://github.com/rust-lang/crates.io-index"
3347
- checksum = "aff114cab67c406f051985749d7cd4aedab3fd445936f6759fd95de9c0352bb7"
3364
+ checksum = "8372d1e4e8c853e20ffb5568a4cc3f930a2bf1ce25bc346812ac7b84e84639d4"
3348
3365
 
3349
3366
  [[package]]
3350
3367
  name = "msb_krun_cpuid"
3351
- version = "0.1.16"
3368
+ version = "0.1.17"
3352
3369
  source = "registry+https://github.com/rust-lang/crates.io-index"
3353
- checksum = "9f4a5cf30e814f211c32c43ee88e9a711ed0b17b88396a80baf5360f49ade848"
3370
+ checksum = "179542321455c65a8e4b14c09bc8443227a89cd46ef2c9c06f0ee1ab11f510ea"
3354
3371
  dependencies = [
3355
3372
  "kvm-bindings",
3356
3373
  "kvm-ioctls",
@@ -3359,9 +3376,9 @@ dependencies = [
3359
3376
 
3360
3377
  [[package]]
3361
3378
  name = "msb_krun_devices"
3362
- version = "0.1.16"
3379
+ version = "0.1.17"
3363
3380
  source = "registry+https://github.com/rust-lang/crates.io-index"
3364
- checksum = "80f22c8cd187fc729c7f3b0922ae9e2e078809172f305dd343a6c4c71a219d68"
3381
+ checksum = "67350e76fd466e1a089b89fa548ba85a92f237c2d3dab179ba675cfd18eb9a39"
3365
3382
  dependencies = [
3366
3383
  "bitflags 1.3.2",
3367
3384
  "capng",
@@ -3387,9 +3404,9 @@ dependencies = [
3387
3404
 
3388
3405
  [[package]]
3389
3406
  name = "msb_krun_hvf"
3390
- version = "0.1.16"
3407
+ version = "0.1.17"
3391
3408
  source = "registry+https://github.com/rust-lang/crates.io-index"
3392
- checksum = "8c816c66f7eb6ccf751cb250a1c7ab0bc261cac6cef36ee68a8b673864ce5800"
3409
+ checksum = "13eaca12857149c3552007a18c7f863ccc6b4dddcf2863c0bcc8fbc2aa2d4c6e"
3393
3410
  dependencies = [
3394
3411
  "crossbeam-channel",
3395
3412
  "libloading",
@@ -3399,9 +3416,9 @@ dependencies = [
3399
3416
 
3400
3417
  [[package]]
3401
3418
  name = "msb_krun_kernel"
3402
- version = "0.1.16"
3419
+ version = "0.1.17"
3403
3420
  source = "registry+https://github.com/rust-lang/crates.io-index"
3404
- checksum = "294eaf9998761721183f080866ddca635f3186da8541d2a273f60cf719ee92c3"
3421
+ checksum = "514f7493860978b08819fdcc4ef3d1887fd4d2b5e26ad0a0eabcec005410df94"
3405
3422
  dependencies = [
3406
3423
  "msb_krun_utils",
3407
3424
  "vm-memory 0.16.2",
@@ -3409,9 +3426,9 @@ dependencies = [
3409
3426
 
3410
3427
  [[package]]
3411
3428
  name = "msb_krun_polly"
3412
- version = "0.1.16"
3429
+ version = "0.1.17"
3413
3430
  source = "registry+https://github.com/rust-lang/crates.io-index"
3414
- checksum = "778c4a9713517f131ae5b0c3e6c299a7e70ced97edeedd6e469639b9d7390fe2"
3431
+ checksum = "08ebbb0336b9cd8dcffa9c47d01a729de4f83c39fc099620f4f9c4d8ef69f460"
3415
3432
  dependencies = [
3416
3433
  "libc",
3417
3434
  "msb_krun_utils",
@@ -3419,18 +3436,18 @@ dependencies = [
3419
3436
 
3420
3437
  [[package]]
3421
3438
  name = "msb_krun_smbios"
3422
- version = "0.1.16"
3439
+ version = "0.1.17"
3423
3440
  source = "registry+https://github.com/rust-lang/crates.io-index"
3424
- checksum = "775c50a8ab2688083eaf8636af96bed12974d5be9e5811e4c5665cea4fd06ff8"
3441
+ checksum = "f25cb991386c6aca7c74d0bd8b327a807290830e439fbb473c5e1b62a7c66d32"
3425
3442
  dependencies = [
3426
3443
  "vm-memory 0.16.2",
3427
3444
  ]
3428
3445
 
3429
3446
  [[package]]
3430
3447
  name = "msb_krun_utils"
3431
- version = "0.1.16"
3448
+ version = "0.1.17"
3432
3449
  source = "registry+https://github.com/rust-lang/crates.io-index"
3433
- checksum = "0f620c8707cd19f6c67c004c2e80744a0bdab7349e18564ec982f8542712a375"
3450
+ checksum = "b7104f87f235ef5cc320ffa760b7cd3635960b58cdc5e1ec89df852fc538f042"
3434
3451
  dependencies = [
3435
3452
  "bitflags 1.3.2",
3436
3453
  "crossbeam-channel",
@@ -3443,9 +3460,9 @@ dependencies = [
3443
3460
 
3444
3461
  [[package]]
3445
3462
  name = "msb_krun_vmm"
3446
- version = "0.1.16"
3463
+ version = "0.1.17"
3447
3464
  source = "registry+https://github.com/rust-lang/crates.io-index"
3448
- checksum = "bb70c044c60e011e6f43c2e336687850b0910853a0efe37010e9649eff1395fe"
3465
+ checksum = "6742a7fba174849b924a370bfba0fe7be8435253bff26303aec34ac89641ae63"
3449
3466
  dependencies = [
3450
3467
  "bzip2",
3451
3468
  "crossbeam-channel",
@@ -6009,6 +6026,18 @@ dependencies = [
6009
6026
  "tokio",
6010
6027
  ]
6011
6028
 
6029
+ [[package]]
6030
+ name = "tokio-tungstenite"
6031
+ version = "0.29.0"
6032
+ source = "registry+https://github.com/rust-lang/crates.io-index"
6033
+ checksum = "8f72a05e828585856dacd553fba484c242c46e391fb0e58917c942ee9202915c"
6034
+ dependencies = [
6035
+ "futures-util",
6036
+ "log",
6037
+ "tokio",
6038
+ "tungstenite",
6039
+ ]
6040
+
6012
6041
  [[package]]
6013
6042
  name = "tokio-util"
6014
6043
  version = "0.7.18"
@@ -6151,6 +6180,22 @@ version = "0.2.5"
6151
6180
  source = "registry+https://github.com/rust-lang/crates.io-index"
6152
6181
  checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
6153
6182
 
6183
+ [[package]]
6184
+ name = "tungstenite"
6185
+ version = "0.29.0"
6186
+ source = "registry+https://github.com/rust-lang/crates.io-index"
6187
+ checksum = "6c01152af293afb9c7c2a57e4b559c5620b421f6d133261c60dd2d0cdb38e6b8"
6188
+ dependencies = [
6189
+ "bytes",
6190
+ "data-encoding",
6191
+ "http",
6192
+ "httparse",
6193
+ "log",
6194
+ "rand 0.9.4",
6195
+ "sha1 0.10.6",
6196
+ "thiserror 2.0.18",
6197
+ ]
6198
+
6154
6199
  [[package]]
6155
6200
  name = "typed-builder"
6156
6201
  version = "0.23.2"
data/DESIGN.md CHANGED
@@ -126,9 +126,13 @@ git. The override must never be committed — it would break container builds.
126
126
  ## Implemented surface (v1) vs roadmap
127
127
 
128
128
  **Implemented:** sandbox lifecycle (`create`/`start`/`get`/`list`/`list_with`/
129
- `remove`/`stop`/`kill`, the async `request_stop`/`request_kill`/`request_drain`/
130
- `wait_until_stopped` (→ `SandboxStopResult`) / `detach` / `owns_lifecycle?`
131
- controls, block form), `exec`/`shell` with collected `ExecOutput`,
129
+ `remove`; the live `Sandbox` exposes `stop`/`stop_and_wait`/`kill`/`drain`/
130
+ `wait` (→ `ExitStatus`) / `status` / `detach` / `owns_lifecycle?`, while the
131
+ controllable `SandboxHandle` from `get`/`list` carries the fine-grained
132
+ `stop_with_timeout`/`request_stop`/`request_kill`/`request_drain`/
133
+ `wait_until_stopped` (→ `SandboxStopResult`) controls — the v0.5.8 live-vs-handle
134
+ split that mirrors the official SDKs), backend routing (`set_default_backend`/
135
+ `with_backend`/`default_backend_kind`), block form), `exec`/`shell` with collected `ExecOutput`,
132
136
  **streaming** `exec_stream`/`shell_stream` (`ExecHandle` is `Enumerable` over
133
137
  `ExecEvent`s, with stdin sink + signal/kill/resize), the full guest filesystem
134
138
  API (`fs.read`/`write`/`list`/`mkdir`/`remove`/`stat`/…), `metrics`,
data/README.md CHANGED
@@ -4,7 +4,31 @@ Lightweight microVM sandboxes for Ruby — run AI agents and untrusted code with
4
4
 
5
5
  The `microsandbox-rb` gem provides native bindings to the [microsandbox](https://github.com/superradcompany/microsandbox) runtime via a Rust extension (magnus). It spins up real microVMs (not containers) in under 100 ms, runs standard OCI (Docker) images, and gives you full control over command execution, the guest filesystem, networking, and metrics — all from an idiomatic, **synchronous** Ruby API. There is no daemon to install and no server to connect to: the runtime is embedded directly in your process.
6
6
 
7
- This is an **unofficial, community-maintained** Ruby implementation — not part of the official SDK family ([Rust](https://github.com/superradcompany/microsandbox/tree/main/sdk), TypeScript, Python, Go) — though it wraps the same core engine.
7
+ This is an **unofficial, community-maintained** Ruby implementation — not part of the official SDK family — though it wraps the same core engine.
8
+
9
+ ## Upstream & acknowledgements
10
+
11
+ `microsandbox-rb` exists only because of the excellent work by the [Super Rad
12
+ Company](https://github.com/superradcompany) team on the upstream
13
+ **microsandbox** runtime. All the hard parts — the microVM engine, the guest
14
+ `agentd`, the networking stack — are theirs; this gem is a thin Ruby skin over
15
+ them. Our deepest thanks to the maintainers and community. 🙏
16
+
17
+ - **Website & docs** — <https://microsandbox.dev> · [documentation](https://docs.microsandbox.dev)
18
+ - **Official repository** — [superradcompany/microsandbox](https://github.com/superradcompany/microsandbox)
19
+ - **Official SDKs** —
20
+ [Rust](https://github.com/superradcompany/microsandbox/tree/main/sdk) ·
21
+ [Python](https://github.com/superradcompany/microsandbox/tree/main/sdk/python) ·
22
+ [TypeScript / Node](https://github.com/superradcompany/microsandbox/tree/main/sdk/node-ts) ·
23
+ [Go](https://github.com/superradcompany/microsandbox/tree/main/sdk/go)
24
+ - **Agents** — [Agent Skills](https://github.com/superradcompany/skills) · [MCP server](https://github.com/superradcompany/microsandbox-mcp)
25
+ - **Community** — [Discord](https://discord.gg/T95Y3XnEAK)
26
+
27
+ > **Not affiliated.** This gem is an independent, community-maintained project.
28
+ > It is **not** built, endorsed, or supported by Super Rad Company or the
29
+ > microsandbox team. Please don't direct questions about this gem to the
30
+ > upstream project — open an issue here instead. **Contributions are very
31
+ > welcome — PRs welcome!** See [Contributing](#contributing).
8
32
 
9
33
  ## Features
10
34
 
@@ -97,17 +121,33 @@ sb = Microsandbox::Sandbox.create("box", image: "public.ecr.aws/docker/library/a
97
121
  begin
98
122
  # ...
99
123
  ensure
100
- sb.stop # graceful (sb.stop(timeout: 5) to bound the wait)
101
- # sb.kill # force (SIGKILL)
124
+ sb.stop # graceful (SIGTERM→SIGKILL escalation, 10s default)
125
+ # sb.stop_and_wait # graceful, then wait → ExitStatus(#exit_code, #success?)
126
+ # sb.kill # force (SIGKILL); sb.drain for a graceful drain
102
127
  end
103
128
 
104
- # Inspect / manage existing sandboxes
105
- Microsandbox::Sandbox.list # => [Microsandbox::SandboxInfo, ...]
106
- Microsandbox::Sandbox.get("box") # => Microsandbox::SandboxInfo
129
+ # Inspect / manage existing sandboxes. `get`/`list` return a controllable
130
+ # SandboxHandle (the live `stop`/`kill`/`drain`/`wait` live on the object from
131
+ # `create`/`start`; fine-grained control lives on the handle).
132
+ Microsandbox::Sandbox.list # => [Microsandbox::SandboxHandle, ...]
133
+ h = Microsandbox::Sandbox.get("box") # => Microsandbox::SandboxHandle
134
+ h.status # :running, :stopped, :created, ...
135
+ h.stop_with_timeout(5) # custom escalation timeout
136
+ h.request_stop # fire-and-return; pair with #wait_until_stopped
137
+ h.request_kill
138
+ h.request_drain
139
+ h.wait_until_stopped # => Microsandbox::SandboxStopResult
107
140
  Microsandbox::Sandbox.start("box") # restart a stopped sandbox
108
141
  Microsandbox::Sandbox.remove("box") # remove a stopped sandbox
109
142
  ```
110
143
 
144
+ > **v0.5.8 lifecycle change.** Upstream split the lifecycle into the live
145
+ > `Sandbox` and a controllable `SandboxHandle`, and the gem mirrors it. The live
146
+ > `Sandbox#stop`/`#kill` no longer take a `timeout:`; `#request_stop`/
147
+ > `#request_kill`/`#request_drain`/`#wait_until_stopped` and a custom stop timeout
148
+ > now live on the `SandboxHandle` from `Sandbox.get`. `Sandbox.get`/`.list` return
149
+ > a `SandboxHandle` (was a read-only `SandboxInfo`, kept as a deprecated alias).
150
+
111
151
  ### Configuration
112
152
 
113
153
  ```ruby
@@ -197,8 +237,9 @@ Microsandbox::Sandbox.create("stream", image: "public.ecr.aws/docker/library/pyt
197
237
  print event.text if event.stdout?
198
238
  end
199
239
  # or: out = handle.collect → ExecOutput (drain to the end)
200
- # interactive stdin:
201
- # sink = handle.stdin; sink.write("data\n"); sink.close
240
+ # interactive stdin — create the stream with stdin: :pipe to get a writable sink:
241
+ # h = sb.exec_stream("cat", [], stdin: :pipe)
242
+ # sink = h.stdin; sink.write("data\n"); sink.close # close sends EOF
202
243
  # control: handle.signal(15), handle.kill, handle.resize(rows, cols)
203
244
  end
204
245
  ```
@@ -307,8 +348,32 @@ Microsandbox.installed? # => true/false
307
348
  Microsandbox.install # download + install the runtime (idempotent)
308
349
  Microsandbox.runtime_path # => "/Users/you/.microsandbox/bin/msb"
309
350
  Microsandbox.runtime_path = "/opt/microsandbox/bin/msb" # override
351
+ Microsandbox.libkrunfw_path = "/opt/microsandbox/lib/libkrunfw.dylib" # override (set-once)
352
+ ```
353
+
354
+ ### Backend routing
355
+
356
+ As of v0.5.8 every operation runs through a backend. The default is the local
357
+ libkrun backend; without any configuration nothing changes. A backend can be
358
+ selected programmatically or via the environment:
359
+
360
+ ```ruby
361
+ Microsandbox.default_backend_kind # => :local (or :cloud)
362
+ Microsandbox.set_default_backend(:cloud, url: "https://api.example.com", api_key: ENV["MSB_API_KEY"])
363
+ # or a named profile from ~/.microsandbox/config.json:
364
+ Microsandbox.set_default_backend(:cloud, profile: "prod")
365
+
366
+ # Scoped override (restored afterward, even on error):
367
+ Microsandbox.with_backend(:local) { Microsandbox::Sandbox.create("box", image: "alpine") { |sb| ... } }
310
368
  ```
311
369
 
370
+ Resolution order when no backend is set programmatically: `MSB_BACKEND`
371
+ (`local`/`cloud`) → `MSB_API_URL` + `MSB_API_KEY` → `MSB_PROFILE` → the
372
+ `active_profile` in `~/.microsandbox/config.json` (path overridable via
373
+ `MSB_CONFIG_PATH`) → local. The cloud backend currently supports a subset of
374
+ operations (create/start/stop/remove/get/list, one-shot exec, follow log
375
+ streaming); unsupported operations raise `Microsandbox::UnsupportedError`.
376
+
312
377
  ## Development
313
378
 
314
379
  ```bash
@@ -335,21 +400,9 @@ bundle exec rake compile
335
400
  ## Releasing
336
401
 
337
402
  Releases are automated by `.github/workflows/release.yml` via RubyGems
338
- **Trusted Publishing** (OIDC) — there is no API key to store as a secret.
339
-
340
- **One-time setup** (before the first release), create a *pending* trusted
341
- publisher at <https://rubygems.org/profile/oidc/pending_trusted_publishers>:
342
-
343
- | Field | Value |
344
- |-------|-------|
345
- | RubyGems gem name | `microsandbox-rb` |
346
- | Repository owner | `ya-luotao` |
347
- | Repository name | `microsandbox-rb` |
348
- | Workflow filename | `release.yml` |
349
- | Environment | *(leave blank)* |
350
-
351
- On the first successful push the pending publisher auto-converts to a permanent
352
- one bound to the gem.
403
+ **Trusted Publishing** (OIDC) — there is no API key to store as a secret. The
404
+ trusted publisher is already configured for this gem, so no per-release secret
405
+ or credential setup is needed.
353
406
 
354
407
  **Each release:**
355
408
 
@@ -377,9 +430,12 @@ one bound to the gem.
377
430
 
378
431
  See [DESIGN.md](DESIGN.md) for the architecture and the implemented-surface
379
432
  section. The binding now covers the full official-SDK surface: sandbox
380
- lifecycle (including the async `request_stop`/`request_kill`/`request_drain`/
381
- `wait_until_stopped`/`detach`/`owns_lifecycle?` controls and label-filtered
382
- `list_with`), `exec`/`shell` (collected and streaming), interactive `attach`/
433
+ lifecycle (the live `Sandbox` `stop`/`stop_and_wait`/`kill`/`drain`/`wait`/
434
+ `status`/`detach`/`owns_lifecycle?`, plus the `SandboxHandle` controls
435
+ `stop_with_timeout`/`request_stop`/`request_kill`/`request_drain`/
436
+ `wait_until_stopped` from `Sandbox.get`, and label-filtered `list_with`),
437
+ backend routing (`set_default_backend`/`with_backend`/`default_backend_kind`),
438
+ `exec`/`shell` (collected and streaming), interactive `attach`/
383
439
  `attach_shell`, the full guest filesystem, metrics (per-sandbox,
384
440
  `Microsandbox.all_sandbox_metrics`, and streaming `metrics_stream`/`log_stream`),
385
441
  logs, OCI image-cache management, named volumes, snapshots (create/list/verify/
@@ -393,6 +449,15 @@ export/import + boot-from-snapshot), **rootfs patches** (`Microsandbox::Patch`),
393
449
  `registry_auth`/`registry_insecure`/`registry_ca_certs` for private and
394
450
  authenticated registries.
395
451
 
452
+ ## Contributing
453
+
454
+ This is a community-maintained gem and **contributions are very welcome** —
455
+ bug reports, fixes, docs, and feature work alike. Open an
456
+ [issue](https://github.com/ya-luotao/microsandbox-rb/issues) or send a
457
+ [pull request](https://github.com/ya-luotao/microsandbox-rb/pulls); PRs target
458
+ `main`. Before pushing, run the local gate (Rust `fmt`/`clippy`, `standardrb`,
459
+ and unit specs) — see [Development](#development).
460
+
396
461
  ## License
397
462
 
398
463
  Apache-2.0. See [LICENSE](LICENSE).
@@ -6,8 +6,8 @@ name = "microsandbox_rb"
6
6
  description = "Ruby SDK native extension for microsandbox — secure, fast microVM-based sandboxing."
7
7
  # Must equal Microsandbox::VERSION (lib/microsandbox/version.rb) — Native.version
8
8
  # returns this via env!("CARGO_PKG_VERSION") and version_spec.rb asserts equality.
9
- # The core-crate dependency below stays pinned at its own tag (v0.5.7).
10
- version = "0.5.9"
9
+ # The core-crate dependency below stays pinned at its own tag (v0.5.8).
10
+ version = "0.5.10"
11
11
  authors = ["Super Rad Company <development@superrad.company>"]
12
12
  repository = "https://github.com/superradcompany/microsandbox"
13
13
  license = "Apache-2.0"
@@ -35,8 +35,8 @@ rb-sys = "0.9"
35
35
  # `.cargo/config.toml.example`). "ssh" matches the feature set the Python/Node
36
36
  # SDKs ship with; default features add "prebuilt" (provisions msb + libkrunfw at
37
37
  # build time), "net", and "keyring".
38
- microsandbox = { git = "https://github.com/superradcompany/microsandbox", tag = "v0.5.7", default-features = true, features = ["ssh"] }
39
- microsandbox-network = { git = "https://github.com/superradcompany/microsandbox", tag = "v0.5.7" }
38
+ microsandbox = { git = "https://github.com/superradcompany/microsandbox", tag = "v0.5.8", default-features = true, features = ["ssh"] }
39
+ microsandbox-network = { git = "https://github.com/superradcompany/microsandbox", tag = "v0.5.8" }
40
40
 
41
41
  # Async core bridged to Ruby's synchronous API via a blocking tokio runtime.
42
42
  tokio = { version = "1", features = ["rt-multi-thread", "sync", "time"] }