Loading workspace insights... Statistics interval
7 days30 daysLatest CI Pipeline Executions
c3bb4b9b feat(ai-sandbox): Sprites sandbox provider (#868)
* feat(ai-sandbox-sprites): add Sprites (sprites.dev) sandbox provider
Add @tanstack/ai-sandbox-sprites, a SandboxProvider/SandboxHandle
implementation backed by Sprites (sprites.dev, Fly.io) cloud sandboxes,
following the @tanstack/ai-sandbox-daytona / -vercel shape.
- Dependency-free client (Sprites REST + exec control WebSocket); no SDK.
- exec with separate stdout/stderr, background spawn, native /fs I/O,
exec-backed git, env injection, durable filesystem, resume-by-id.
- ports.connect() exposes the Sprite's single proxied public-URL port
(default 8080), switching the URL to public auth.
- Hardened exec lifecycle: abnormal-close surfaces an error instead of a
false exit 0; control-message parses drained before reading the exit
code; exec URL (cmd/env) stripped from connection errors.
- Unit tests (fake client) + gated live tests against api.sprites.dev;
docs/sandbox/providers.md entry; changeset.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(ai-sandbox-sprites): add checkpoint (snapshot) support
Wire Sprite checkpoints through the SandboxHandle:
- capabilities.snapshots = true
- handle.snapshot(label?) creates a checkpoint, returns {id: "<name>#vN"}
- handle.listCheckpoints() / handle.restoreCheckpoint(idOrRef) for in-place
restore (restarts the Sprite; readiness polled via a fetch probe bounded by
an abort signal)
- client.createCheckpoint/listCheckpoints/restoreCheckpoint over the REST API
Restore is in-place and a checkpoint does not survive Sprite deletion, so the
provider intentionally does not implement reconstruct-after-gone
restoreSnapshot — the framework degrades to a fresh create when a Sprite is
gone. Unit tests cover the wiring; the gated live test covers create+list
(restore restarts the Sprite and can take minutes, so it's excluded from CI).
Docs + changeset updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(ai-sandbox-sprites): rebrand to "stateful sandboxes"; drop marketing domain
- Describe Sprites as "stateful sandboxes" (its own term) instead of "cloud
sandboxes".
- Remove the sprites.dev marketing link from the core README table, package
description, and JSDoc — matching the other providers there, which carry no
domain. Keep the link in docs/sandbox/providers.md, where Daytona/Vercel also
link, and keep the functional api.sprites.dev endpoint.
- Harden post-restore readiness: probe the workdir (not just root) and require
two consecutive successes, since the overlay can briefly return I/O errors
right after a restart; raise the default ready timeout to match observed
multi-minute restarts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(ai-sandbox-sprites): note post-restore filesystem settle window
Document that immediately after a checkpoint restore the overlay can be
listable while individual file reads briefly return an I/O error as it
settles — callers acting on the filesystem the instant restore returns
should retry reads.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(ai-sandbox-sprites): address adversarial-review findings
Lifecycle / cancellation (client.ts):
- exec(): parse control frames synchronously so an early kill/close can't read
a stale (undefined) session id; kill()/abort now reach the server-side kill
endpoint even before session_info arrives, instead of orphaning the remote
process (H4). Add a connect watchdog so a CONNECTING stall fails wait()
instead of hanging forever (M3). An explicit kill() resolves wait() with a
conventional 137 rather than rejecting (G3).
- restoreCheckpoint(): probe a write→read round-trip (not just a directory
list) so it resolves only once the restored overlay actually serves reads,
not while it is merely listable (H5); honor the caller's AbortSignal during
the multi-minute readiness wait (M5).
- createCheckpoint(): return the version THIS call created (pre/post diff +
stream parse) instead of the current max, which a concurrent or
eventually-consistent list could make wrong (M4).
Handle / provider:
- ports.connect() no longer silently downgrades URL auth to public; it returns
a token-authenticated channel for sprite-auth Sprites and never mutates the
mode (H3).
- create() runs the workspace mkdir from '/', so a non-default workdir is not
created with its own (not-yet-existent) dir as cwd (G2).
- fs error messages fall back to stdout, since the fast path folds stderr into
stdout for instant commands (M1).
- restoreCheckpoint(ref) validates the Sprite-name component of a name#vN ref
(L1).
Packaging / docs:
- Add engines node>=22.4 (global undici WebSocket); fix the Node-version
comment and the readyTimeoutMs JSDoc (M8/N1).
Tests: add deterministic client.test.ts (stub WebSocket + fetch: frame demux,
abnormal-close→throw, kill endpoint, early-abort kill, createCheckpoint id,
fsRead 404→throw, lifecycle) and provider.test.ts (create naming/urlAuth/mkdir,
resume branches); update handle.test.ts for the no-downgrade connect and ref
validation (H6).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci: apply automated fixes
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> c3bb4b9b feat(ai-sandbox): Sprites sandbox provider (#868)
* feat(ai-sandbox-sprites): add Sprites (sprites.dev) sandbox provider
Add @tanstack/ai-sandbox-sprites, a SandboxProvider/SandboxHandle
implementation backed by Sprites (sprites.dev, Fly.io) cloud sandboxes,
following the @tanstack/ai-sandbox-daytona / -vercel shape.
- Dependency-free client (Sprites REST + exec control WebSocket); no SDK.
- exec with separate stdout/stderr, background spawn, native /fs I/O,
exec-backed git, env injection, durable filesystem, resume-by-id.
- ports.connect() exposes the Sprite's single proxied public-URL port
(default 8080), switching the URL to public auth.
- Hardened exec lifecycle: abnormal-close surfaces an error instead of a
false exit 0; control-message parses drained before reading the exit
code; exec URL (cmd/env) stripped from connection errors.
- Unit tests (fake client) + gated live tests against api.sprites.dev;
docs/sandbox/providers.md entry; changeset.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(ai-sandbox-sprites): add checkpoint (snapshot) support
Wire Sprite checkpoints through the SandboxHandle:
- capabilities.snapshots = true
- handle.snapshot(label?) creates a checkpoint, returns {id: "<name>#vN"}
- handle.listCheckpoints() / handle.restoreCheckpoint(idOrRef) for in-place
restore (restarts the Sprite; readiness polled via a fetch probe bounded by
an abort signal)
- client.createCheckpoint/listCheckpoints/restoreCheckpoint over the REST API
Restore is in-place and a checkpoint does not survive Sprite deletion, so the
provider intentionally does not implement reconstruct-after-gone
restoreSnapshot — the framework degrades to a fresh create when a Sprite is
gone. Unit tests cover the wiring; the gated live test covers create+list
(restore restarts the Sprite and can take minutes, so it's excluded from CI).
Docs + changeset updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(ai-sandbox-sprites): rebrand to "stateful sandboxes"; drop marketing domain
- Describe Sprites as "stateful sandboxes" (its own term) instead of "cloud
sandboxes".
- Remove the sprites.dev marketing link from the core README table, package
description, and JSDoc — matching the other providers there, which carry no
domain. Keep the link in docs/sandbox/providers.md, where Daytona/Vercel also
link, and keep the functional api.sprites.dev endpoint.
- Harden post-restore readiness: probe the workdir (not just root) and require
two consecutive successes, since the overlay can briefly return I/O errors
right after a restart; raise the default ready timeout to match observed
multi-minute restarts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(ai-sandbox-sprites): note post-restore filesystem settle window
Document that immediately after a checkpoint restore the overlay can be
listable while individual file reads briefly return an I/O error as it
settles — callers acting on the filesystem the instant restore returns
should retry reads.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(ai-sandbox-sprites): address adversarial-review findings
Lifecycle / cancellation (client.ts):
- exec(): parse control frames synchronously so an early kill/close can't read
a stale (undefined) session id; kill()/abort now reach the server-side kill
endpoint even before session_info arrives, instead of orphaning the remote
process (H4). Add a connect watchdog so a CONNECTING stall fails wait()
instead of hanging forever (M3). An explicit kill() resolves wait() with a
conventional 137 rather than rejecting (G3).
- restoreCheckpoint(): probe a write→read round-trip (not just a directory
list) so it resolves only once the restored overlay actually serves reads,
not while it is merely listable (H5); honor the caller's AbortSignal during
the multi-minute readiness wait (M5).
- createCheckpoint(): return the version THIS call created (pre/post diff +
stream parse) instead of the current max, which a concurrent or
eventually-consistent list could make wrong (M4).
Handle / provider:
- ports.connect() no longer silently downgrades URL auth to public; it returns
a token-authenticated channel for sprite-auth Sprites and never mutates the
mode (H3).
- create() runs the workspace mkdir from '/', so a non-default workdir is not
created with its own (not-yet-existent) dir as cwd (G2).
- fs error messages fall back to stdout, since the fast path folds stderr into
stdout for instant commands (M1).
- restoreCheckpoint(ref) validates the Sprite-name component of a name#vN ref
(L1).
Packaging / docs:
- Add engines node>=22.4 (global undici WebSocket); fix the Node-version
comment and the readyTimeoutMs JSDoc (M8/N1).
Tests: add deterministic client.test.ts (stub WebSocket + fetch: frame demux,
abnormal-close→throw, kill endpoint, early-abort kill, createCheckpoint id,
fsRead 404→throw, lifecycle) and provider.test.ts (create naming/urlAuth/mkdir,
resume branches); update handle.test.ts for the no-downgrade connect and ref
validation (H6).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* ci: apply automated fixes
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> 38447e7a fix(ai-sandbox-sprites): address adversarial-review findings
Lifecycle / cancellation (client.ts):
- exec(): parse control frames synchronously so an early kill/close can't read
a stale (undefined) session id; kill()/abort now reach the server-side kill
endpoint even before session_info arrives, instead of orphaning the remote
process (H4). Add a connect watchdog so a CONNECTING stall fails wait()
instead of hanging forever (M3). An explicit kill() resolves wait() with a
conventional 137 rather than rejecting (G3).
- restoreCheckpoint(): probe a write→read round-trip (not just a directory
list) so it resolves only once the restored overlay actually serves reads,
not while it is merely listable (H5); honor the caller's AbortSignal during
the multi-minute readiness wait (M5).
- createCheckpoint(): return the version THIS call created (pre/post diff +
stream parse) instead of the current max, which a concurrent or
eventually-consistent list could make wrong (M4).
Handle / provider:
- ports.connect() no longer silently downgrades URL auth to public; it returns
a token-authenticated channel for sprite-auth Sprites and never mutates the
mode (H3).
- create() runs the workspace mkdir from '/', so a non-default workdir is not
created with its own (not-yet-existent) dir as cwd (G2).
- fs error messages fall back to stdout, since the fast path folds stderr into
stdout for instant commands (M1).
- restoreCheckpoint(ref) validates the Sprite-name component of a name#vN ref
(L1).
Packaging / docs:
- Add engines node>=22.4 (global undici WebSocket); fix the Node-version
comment and the readyTimeoutMs JSDoc (M8/N1).
Tests: add deterministic client.test.ts (stub WebSocket + fetch: frame demux,
abnormal-close→throw, kill endpoint, early-abort kill, createCheckpoint id,
fsRead 404→throw, lifecycle) and provider.test.ts (create naming/urlAuth/mkdir,
resume branches); update handle.test.ts for the no-downgrade connect and ref
validation (H6).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>