boxlite-ai / boxlite-ai/boxlite

Feature: AutoPause / AutoResume

Open
#1,003 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
2.3k
Forks
179
Avg merge
23h 25m
Merged PRs (30d)
121

Description

## Background

A Box is automatically paused after its idle TTL expires. When the next user operation reaches a paused Box, it is automatically resumed and the original request continues.

The first phase uses the existing Stop / Start behavior:

```text
Running
↓ idle for autoPauseInterval
Stop → Stopped
↓ next supported user operation
Start → Running

continue processing the original request
```

After Pause, only the Box configuration, persistent disk, and Volumes are preserved. RAM, processes, connections, terminal sessions, and running commands are not preserved. Resume is a cold start, so the image entrypoint and startup scripts run again.

Stop first sends `SIGTERM` to processes and containers. Processes that are still running after the grace period receive `SIGKILL`. Stop does not send `SIGINT`.

## Expected Behavior

### Configuration

- `autoPauseInterval` and `autoDeleteInterval` are both measured in seconds;
- `autoPauseInterval` defaults to `900` seconds, and `0` disables AutoPause;
- when both are enabled, `autoDeleteInterval > autoPauseInterval`;
- a Box can be automatically resumed before AutoDelete runs, but it cannot be recovered after deletion;
- the intervals can be configured when creating a Box, then read and updated after creation;
- the API and the Rust, Python, Node.js, Go, and C SDKs use the same names and units.

### Activity and AutoResume

The following platform operations refresh the Pause TTL and can trigger AutoResume when the Box is Stopped:

- Exec API: create, inspect, terminate, signal, or resize an execution, and attach over WebSocket;
- Files API: read, write, upload, download, list directories, or read metadata;
- an explicit `POST /box/{boxIdOrName}/last-activity` call.

The following operations do not refresh the TTL or trigger AutoResume:

- Metrics;
- commands and file I/O performed internally by the Guest;
- port previews and inbound or outbound network traffic;
- listing Boxes or performing ordinary metadata operations.

The first request that triggers AutoResume must wait for Start to succeed before continuing. Concurrent requests must share the same Start operation.

## Current Code Status

Existing foundations:

- the control plane already has `autoStopInterval`, `autoDeleteInterval`, and Auto Stop / Auto Delete sweepers that run every 10 seconds;
- Stop / Start is wired through the control plane, Runner, and BoxLite;
- a Stopped Box can restart using its persistent disk;
- Exec and Files requests already send a start hint;
- `ensureStartedForProxy()` can atomically change the desired state of a Stopped Box to Started;
- last-activity already uses a Redis cache and database persistence.

Gaps between the current implementation and the expected behavior:

- the current field is named `autoStopInterval` and is measured in minutes; the target field is `autoPauseInterval` and is measured in seconds;
- `POST /v1/boxes` and BoxLite `BoxOptions` do not accept AutoPause / AutoDelete configuration, and the language SDKs do not expose it;
- the legacy generated clients expose only response fields and some legacy endpoints, which does not make the public SDK creation flow usable;
- Metrics incorrectly sends a start hint and refreshes activity through the shared proxy path;
- the port proxy periodically refreshes activity;
- execution status, signal, resize, kill, and attach operations do not share a unified AutoResume gate;
- the current start hint waits for at most 2 seconds and continues proxying after failure, so it does not guarantee that the Box has started;
- the last-activity route declares only a Box ID and does not resolve a name to the canonical `box.id` before updating activity;
- after the sweeper decides that a Box has expired, it does not recheck the latest activity before writing the Stop intent, creating a race that can pause a recently active Box;
- AutoDelete currently uses `lastActivityAt` instead of starting its timer after a successful Stop;
- the Runner accepts a `force` parameter, but BoxLite Stop currently ignores it.

## Key Paths

- API contract: `openapi/box.openapi.yaml`, `apps/api/src/boxlite-rest/`;
- lifecycle: `apps/api/src/box/managers/box.manager.ts`, `apps/api/src/box/services/box.service.ts`;
- Activity / AutoResume: `apps/api/src/box/services/box-activity.service.ts`, `apps/api/src/boxlite-rest/boxlite-proxy.controller.ts`, `apps/api/src/boxlite-rest/boxlite-ws-proxy.service.ts`, `apps/proxy/pkg/proxy/get_box_target.go`;
- Runner / Runtime: `apps/runner/pkg/boxlite/client.go`, `src/boxlite/src/runtime/options.rs`, `src/boxlite/src/rest/types.rs`, `src/boxlite/src/litebox/box_impl.rs`;
- SDKs: `sdks/python/`, `sdks/node/`, `sdks/go/`, `sdks/c/`.

Contributor guide

Open the contributing guide

Research direction

Start with openapi/box.openapi.yaml and the lifecycle paths in apps/api/src/box/managers/box.manager.ts and apps/api/src/box/services/box.service.ts, then trace activity handling through the listed proxy, Runner, and BoxLite files. Done means the expected AutoPause, AutoResume, activity, deletion, API, runtime, and SDK behaviors are implemented consistently across the gaps described in the issue.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, go, node.js, openapi, python, rust, typescript
Domain
api, backend, devtools, infrastructure
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.