/** * Sprites lifecycle activities (#762, #766) — imperative, checkpointable sandbox * primitives ([sprites.dev](https://sprites.dev)) as chant Op activities, wired * to the faithful Sprites API. * * Unlike a resource lexicon, Sprites have no desired state to reconcile: they * are runtime-orchestration primitives (the same category as `k3dUp` / * `httpCheck`). Most activities are a direct call over an injectable HTTP client * (`SpritesHttp`); `spriteExec` is the exception — it speaks the control * WebSocket exec protocol (non-PTY stream framing, per superfly/sprites-go), so * it opens a `ws` connection instead. Exported pure helpers (endpoint * resolution, the exec frame accumulator, NDJSON parsers, the comment picker) * keep the logic unit-testable without a socket or an HTTP server. * * The headline capability is checkpoint-as-compensation (S5): an Op checkpoints * before a risky phase and, on failure, `spriteRestore`s the labeled checkpoint * instead of unwinding with an inverse action — the environment itself is the * transaction. * * S3: endpoint override via `SPRITES_BASE_URL` (an explicit `endpoint` arg wins, * then the env, then the real Sprites base), so the same Op targets real Sprites * or the in-process fake with no code change. */ export declare const DEFAULT_SPRITES_BASE_URL = "https://api.sprites.dev"; /** * Resolve the Sprites base URL (S3): an explicit `endpoint` arg wins, then the * `SPRITES_BASE_URL` env, then the real-Sprites default. The trailing slash is * stripped so `${base}/v1/...` never doubles up. Pure — mirrors fly's * `resolveEndpoint`. */ export declare function resolveSpritesEndpoint(args?: { endpoint?: string; }, env?: NodeJS.ProcessEnv): string; export declare const STREAM_STDIN = 0; export declare const STREAM_STDOUT = 1; export declare const STREAM_STDERR = 2; export declare const STREAM_EXIT = 3; export declare const STREAM_STDIN_EOF = 4; /** * Accumulate a stream of exec frames into `{ stdout, stderr, exitCode }`. Pure * and socket-free so the framing is unit-testable: feed `[1]"hi\n"`, `[3]\x00` * and get `{ stdout: "hi\n", exitCode: 0 }`. Per-stream payloads are collected * as bytes and decoded once, so a multi-byte character split across frames is * preserved. The exit code is the first byte of the `[3]` frame (0 when absent). */ export declare function accumulateExecFrames(frames: Iterable): SpriteExecResult; /** * Tokenize a command string into an argv, respecting single/double quotes so * `sh -c "exit 7"` becomes `["sh", "-c", "exit 7"]`. Each element is sent as a * `cmd` query param; `path` is `argv[0]`. Pure. */ export declare function splitCommand(cmd: string): string[]; /** * Build the `wss://.../exec?cmd=...&path=...&stdin=false&cc=true` URL for a * command (http→ws, https→wss). Pure. */ export declare function spriteExecWsUrl(base: string, id: string, cmd: string): string; /** * Parse a checkpoint create NDJSON body (line-delimited JSON progress events) * and capture the created version id. Real Sprites tags each event with a * `type` and a human `data` string — the version id rides inside the text * (" ID: v1" and "Checkpoint v1 created successfully"), not a structured * field. The in-process fake mirrors that. An older shape (`{event, id}`) is * still honored so a structured id always wins. Pure; blank/unparseable lines * are skipped; `checkpointId` is "" when the stream carries no id. */ export declare function parseCheckpointNdjson(text: string): SpriteCheckpointResult; /** * Pick the newest checkpoint whose `comment` matches, so a comment-tagged * restore rewinds to the most recent labeled snapshot. Newest is by * `create_time`; array order breaks ties (the list is chronological). Pure. */ export declare function pickCheckpointByComment(list: Checkpoint[], comment: string): Checkpoint | undefined; export interface SpriteCreateArgs { /** Caller-chosen name, used as the sprite `id` (S4). Every later activity keys on it. */ name: string; /** Base image for the sandbox. */ image?: string; /** Sandbox size (vCPU/memory class). */ size?: string; /** Network / execution policy passed through to the sprite. */ policy?: unknown; /** Endpoint override (S3). Default: `SPRITES_BASE_URL`, else real Sprites. */ endpoint?: string; /** Bearer token. Default: `SPRITES_API_TOKEN`. The fake ignores it. */ token?: string; } export interface SpriteCreateResult { id: string; url: string; } export interface SpriteExecArgs { /** Target sprite id (the `name` passed to `spriteCreate`). */ id: string; /** Command to run inside the sprite (tokenized into argv, quotes respected). */ cmd: string; /** Per-exec timeout in ms. */ timeoutMs?: number; endpoint?: string; token?: string; } export interface SpriteExecResult { stdout: string; stderr: string; exitCode: number; } export interface SpriteCheckpointArgs { id: string; /** Caller-chosen checkpoint comment (S4); a comment-tagged `spriteRestore` matches it. */ comment?: string; endpoint?: string; token?: string; } export interface SpriteCheckpointResult { /** The server checkpoint version (e.g. `v3`) captured from the `complete` event. */ checkpointId: string; } export interface Checkpoint { id: string; comment: string; create_time: string; is_auto: boolean; } export interface SpriteRestoreArgs { id: string; /** Explicit checkpoint id (e.g. `v3`); wins over `comment`. */ checkpoint?: string; /** Restore the newest checkpoint carrying this comment. */ comment?: string; endpoint?: string; token?: string; } export interface ListCheckpointsArgs { id: string; endpoint?: string; token?: string; } export interface SpriteDestroyArgs { id: string; endpoint?: string; token?: string; } /** Build the `POST /v1/sprites` body. Pure. */ export declare function spriteCreateBody(args: SpriteCreateArgs): Record; /** Parse the create response; the caller-chosen `name` is the id fallback (S4). Pure. */ export declare function parseCreateResponse(text: string, name: string): SpriteCreateResult; /** * Injectable HTTP client — mirrors fly's `FlyHttp`. Tests inject a fake; the * default hits `fetch`. Used by create/destroy/checkpoint/list/restore; exec * goes over the control WebSocket instead. */ export type SpritesHttp = (method: string, url: string, body?: unknown, headers?: Record, signal?: AbortSignal) => Promise<{ status: number; text: string; }>; /** * Default `fetch`-based client. Sends `Authorization: Bearer ` when a * token is set (real Sprites); the fake ignores it. The token defaults to * `SPRITES_API_TOKEN` at call time. `fetchImpl` is injectable for tests. */ export declare function defaultSpritesHttp(token?: string, fetchImpl?: typeof fetch): SpritesHttp; /** Create a sprite with the caller-chosen `name` as its id (S4). `POST /v1/sprites`. */ export declare function spriteCreate(args: SpriteCreateArgs, signal?: AbortSignal, http?: SpritesHttp): Promise; /** * Run a command in the sprite over the control WebSocket (non-PTY stream * framing, per superfly/sprites-go). Connects to `wss://.../exec`, sends a * single `[4]` (stdin EOF), accumulates stdout/stderr frames, and reads the * exit code from the `[3]` frame. A non-zero exit is a failed activity (it * throws) so a risky step fails its phase and triggers `onFailure` * compensation (S5). */ export declare function spriteExec(args: SpriteExecArgs, signal?: AbortSignal): Promise; /** * Checkpoint the sprite. `POST /v1/sprites/{id}/checkpoint` (singular); the * `comment` key is omitted when empty. The response is an NDJSON progress * stream; the created version id is mined from the message text (see * `parseCheckpointNdjson`). */ export declare function spriteCheckpoint(args: SpriteCheckpointArgs, signal?: AbortSignal, http?: SpritesHttp): Promise; /** * List a sprite's checkpoints. `GET /v1/sprites/{id}/checkpoints` → a bare array * `[{ id, comment, create_time, is_auto }]` (auto checkpoints excluded by * default on the server). */ export declare function listCheckpoints(args: ListCheckpointsArgs, signal?: AbortSignal, http?: SpritesHttp): Promise; /** * Restore the sprite to a checkpoint (S5, the compensation path). Resolution * order: an explicit `checkpoint` id wins; otherwise the newest checkpoint * carrying `comment`; otherwise the newest checkpoint overall. Restore is * `POST /v1/sprites/{id}/checkpoints/{cp}/restore` and returns an NDJSON stream. */ export declare function spriteRestore(args: SpriteRestoreArgs, signal?: AbortSignal, http?: SpritesHttp): Promise>; /** Destroy the sprite (idempotent; a 404 means it is already gone). `DELETE /v1/sprites/{id}`. */ export declare function spriteDestroy(args: SpriteDestroyArgs, signal?: AbortSignal, http?: SpritesHttp): Promise>; //# sourceMappingURL=sprites.d.ts.map