Skip to content

feat: add auto pause and resume lifecycle options at box creation time#1009

Merged
DorianZheng merged 12 commits into
boxlite-ai:mainfrom
xhebox:auto-pause-resume
Jul 22, 2026
Merged

feat: add auto pause and resume lifecycle options at box creation time#1009
DorianZheng merged 12 commits into
boxlite-ai:mainfrom
xhebox:auto-pause-resume

Conversation

@xhebox

@xhebox xhebox commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Refs #1003

Summary

Adds create-time lifecycle options for AutoPause, AutoDelete, and AutoResume, and keeps the legacy autostop/autodelete endpoints working by converting minutes to seconds.

Changes

  • Box creation accepts auto_pause, auto_delete, and auto_resume in both the internal and BoxLite REST APIs.
  • Backend sweeper pauses idle boxes and deletes long-stopped boxes based on the new second-based fields.
  • Proxy and WebSocket paths auto-resume stopped boxes when auto_resume is true.
  • Legacy POST /box/{id}/autostop/{interval} and POST /box/{id}/autodelete/{interval} endpoints are retained; input is converted from minutes to seconds.
  • Dashboard, SDKs (Go/Node/Python/C), and Rust runtime expose the new options.
  • Added design doc and user guide under docs/.

How to verify

  • make fmt:check:rust
  • cd apps && ./node_modules/.bin/tsc -p api/tsconfig.app.json --noEmit
  • cd apps && ./node_modules/.bin/eslint "api/src/box/**/*.ts"

Risks / rollout

  • Old autodelete/0 no longer deletes immediately; it now disables auto-delete, consistent with the new 0 = disabled semantics. Existing clients relying on the old immediate-delete behavior need to migrate.

Summary by CodeRabbit

  • New Features
    • Added AutoPause, AutoDelete, and AutoResume controls with second-based intervals.
    • Boxes can automatically resume for supported proxy operations after pausing.
    • Dashboard creation now includes advanced lifecycle settings and validation.
    • Lifecycle settings are available across REST, C, Go, Node.js, and Python SDKs.
  • Bug Fixes
    • Improved concurrent auto-resume handling and prevented requests from reaching boxes that are not ready.
    • Activity tracking now distinguishes user operations from observation-only requests.
  • Documentation
    • Added lifecycle guides and updated API references, defaults, and migration behavior.

Copilot AI review requested due to automatic review settings July 20, 2026 08:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This change replaces minute-based auto-stop and auto-delete settings with second-based AutoPause and AutoDelete policies, adds AutoResume behavior, updates lifecycle persistence and sweepers, integrates proxy readiness handling, propagates contracts through SDKs and dashboards, and adds migration, tests, and documentation.

Changes

Box lifecycle automation

Layer / File(s) Summary
Lifecycle policy contracts and persistence
apps/api/src/box/..., src/boxlite/src/runtime/..., src/boxlite/src/rest/..., openapi/...
Introduces autoPause, autoDelete, and autoResume fields, defaults, validation, REST mappings, response fields, migration logic, and deprecated auto_remove compatibility behavior.
Lifecycle resolution and sweepers
apps/api/src/box/services/..., apps/api/src/box/managers/..., src/boxlite/src/litebox/...
Resolves lifecycle settings, applies conditional AutoPause and AutoDelete transitions, updates remove-on-stop handling, and validates concurrent state waiting.
AutoResume proxy flow
apps/api/src/boxlite-rest/..., apps/proxy/pkg/proxy/...
Adds Redis-serialized AutoResume readiness, multi-waiter state handling, proxy activity policies, and WebSocket organization-aware readiness checks.
Dashboard lifecycle controls
apps/dashboard/src/components/Box/..., apps/dashboard/src/lib/..., apps/dashboard/src/pages/...
Adds lifecycle inputs, validation, request mapping, formatting, defaults, and UI tests.
SDK and API client propagation
apps/api-client-go/..., apps/libs/api-client/..., sdks/...
Propagates lifecycle fields and option setters through generated models, API clients, C, Go, Node.js, and Python bindings.
Documentation and support updates
docs/..., openapi/reference-server/..., scripts/..., src/cli/..., src/test-utils/...
Documents lifecycle behavior, updates reference and stress payloads, adjusts CLI defaults, and updates supporting fixtures and build logic.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related issues

Possibly related PRs

Suggested labels: enhancement

Suggested reviewers: copilot

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 79.07% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding create-time lifecycle options for auto pause and auto resume.
Description check ✅ Passed The description matches the template with Summary, Changes, How to verify, and Risks/rollout sections filled in.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI review requested due to automatic review settings July 20, 2026 09:08
@xhebox
xhebox force-pushed the auto-pause-resume branch from 822442b to 1e7a1fb Compare July 20, 2026 09:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Comment thread src/boxlite/src/litebox/mod.rs Outdated
@xhebox
xhebox force-pushed the auto-pause-resume branch from 1e7a1fb to ccbc2c5 Compare July 20, 2026 10:14
Copilot AI review requested due to automatic review settings July 20, 2026 10:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI review requested due to automatic review settings July 20, 2026 11:10
@xhebox
xhebox force-pushed the auto-pause-resume branch from ccbc2c5 to 4af6de4 Compare July 20, 2026 11:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI review requested due to automatic review settings July 20, 2026 12:00
@xhebox
xhebox force-pushed the auto-pause-resume branch from 4af6de4 to 38f3b79 Compare July 20, 2026 12:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI review requested due to automatic review settings July 21, 2026 02:40
@xhebox
xhebox force-pushed the auto-pause-resume branch from 38f3b79 to 678402c Compare July 21, 2026 02:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI review requested due to automatic review settings July 21, 2026 04:04
@xhebox
xhebox force-pushed the auto-pause-resume branch from 678402c to 977f553 Compare July 21, 2026 04:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@xhebox xhebox changed the title feat: add auto pause and resume lifecycle with control-plane policy API feat: add auto pause and resume lifecycle options at box creation time Jul 21, 2026
Copilot AI review requested due to automatic review settings July 21, 2026 04:07
@xhebox
xhebox marked this pull request as ready for review July 21, 2026 04:07
@xhebox
xhebox force-pushed the auto-pause-resume branch from 977f553 to f44b01e Compare July 21, 2026 04:07
@xhebox
xhebox requested a review from a team as a code owner July 21, 2026 04:07
@boxlite-agent

boxlite-agent Bot commented Jul 21, 2026

Copy link
Copy Markdown

📦 BoxLite review — couldn't complete

claude exited 1

stdout:
{"type":"result","subtype":"success","is_error":true,"api_error_status":403,"duration_ms":468,"duration_api_ms":0,"num_turns":1,"result":"Your organization has disabled Claude subscription access for Claude Code · Use an Anthropic API key instead, or ask your admin to enable access","stop_reason":"stop_sequence","session_id":"5f8a8939-c25e-4d1f-8f2b-053a63a8af69","total_cost_usd":0,"usage":{"input_tokens":0,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":0,"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"inference_geo":"","iterations":[],"speed":"standard"},"modelUsage":{},"permission_denials":[],"terminal_reason":"api_error","fast_mode_state":"off","uuid":"3f2da9f0-54a1-4483-ac7a-c794426288a6"}

stderr:
<empty>

powered by BoxLite

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@xhebox
xhebox requested a review from DorianZheng July 21, 2026 04:07
Copilot AI review requested due to automatic review settings July 21, 2026 12:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@xhebox

xhebox commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

left some comments, rest LGTM

Done

@DorianZheng

Copy link
Copy Markdown
Member

left some comments, rest LGTM

Done

I mean auto_delete duplicates auto_remove.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/api/src/migrations/1741087887225-migration.ts`:
- Line 73: Revert the schema changes in the existing migration containing the
box table definition, restoring its previously executed column names and
structure. Implement the auto-delete column rename entirely in the new migration
1784250000000-add-box-lifecycle-seconds-migration.ts, ensuring existing
deployments migrate cleanly without altering migration history.

In
`@apps/api/src/migrations/pre-deploy/1784250000000-add-box-lifecycle-seconds-migration.ts`:
- Around line 6-26: Update the up method in the migration to add the new
lifecycle columns before removing legacy data, preserve existing
autoStopInterval values in autoPause and autoDeleteInterval values in autoDelete
by converting minutes to seconds (multiply by 60), then drop the legacy
autoStopInterval and autoDeleteInterval columns. Use the production legacy
column name autoDeleteInterval, and keep the constraints applied after the
converted values are populated.

In `@docs/architecture/auto-pause-resume-design.md`:
- Around line 86-93: Update the AutoDelete flow described in the design to
re-read the Redis-preferred latest activity through
BoxActivityService.getLastActivityAt after acquiring the per-box lock, before
deleting a candidate. Skip deletion when recent activity is detected, preserving
the existing AutoPause re-check and conditional state-write protections.
- Around line 11-20: Update the public wire-fields contract to document
auto_resume alongside auto_pause and auto_delete, specifying its type, default
value, semantics, and local-runtime behavior. Keep the existing public naming
and second-level conventions consistent, and ensure the lifecycle/API contract
clearly covers create-time AutoResume.
- Around line 95-99: Align the “Removed Fields and Endpoints” section with the
actual compatibility behavior: verify whether the legacy autostop and autodelete
endpoints remain supported with minute-to-second conversion, then document them
as deprecated/compatible endpoints or remove their support to match the stated
removal. Keep the endpoint documentation and implementation consistent.

In `@sdks/node/lib/native-contracts.ts`:
- Around line 176-178: Update the native return type fields autoPause,
autoDelete, and autoResume in the TypeScript contract to remove their optional
modifiers, matching the always-present primitive values serialized by the Rust
JsBoxInfo struct.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f506b888-b2d0-437e-9b56-b7c16adad0e3

📥 Commits

Reviewing files that changed from the base of the PR and between 49a5e41 and 299adb0.

📒 Files selected for processing (45)
  • apps/api-client-go/api/openapi.yaml
  • apps/api-client-go/model_box.go
  • apps/api/src/box/constants/box-lifecycle.constants.ts
  • apps/api/src/box/dto/box.dto.ts
  • apps/api/src/box/dto/create-box.dto.ts
  • apps/api/src/box/entities/box.entity.ts
  • apps/api/src/box/managers/box.manager.ts
  • apps/api/src/box/services/box.service.ts
  • apps/api/src/boxlite-rest/boxlite-box.controller.ts
  • apps/api/src/boxlite-rest/boxlite-proxy.controller.spec.ts
  • apps/api/src/boxlite-rest/boxlite-proxy.controller.ts
  • apps/api/src/boxlite-rest/boxlite-ws-proxy.service.ts
  • apps/api/src/boxlite-rest/dto/box-response.dto.ts
  • apps/api/src/boxlite-rest/dto/create-box.dto.spec.ts
  • apps/api/src/boxlite-rest/dto/create-box.dto.ts
  • apps/api/src/boxlite-rest/mappers/box-to-box.mapper.spec.ts
  • apps/api/src/boxlite-rest/mappers/box-to-box.mapper.ts
  • apps/api/src/migrations/1741087887225-migration.ts
  • apps/api/src/migrations/pre-deploy/1784250000000-add-box-lifecycle-seconds-migration.ts
  • apps/dashboard/src/components/Box/CreateBoxDialog.test.tsx
  • apps/dashboard/src/components/Box/CreateBoxDialog.tsx
  • apps/dashboard/src/lib/cloudBox.test.ts
  • apps/dashboard/src/lib/cloudBox.ts
  • apps/dashboard/src/pages/Boxes.tsx
  • apps/libs/api-client/src/docs/Box.md
  • apps/libs/api-client/src/models/box.ts
  • docs/architecture/auto-pause-resume-design.md
  • docs/guides/auto-pause-resume.md
  • openapi/box.openapi.yaml
  • sdks/c/include/boxlite.h
  • sdks/c/src/event_queue.rs
  • sdks/c/src/info.rs
  • sdks/c/src/options.rs
  • sdks/go/info.go
  • sdks/go/options.go
  • sdks/node/lib/native-contracts.ts
  • sdks/node/src/info.rs
  • sdks/node/src/options.rs
  • sdks/python/src/info.rs
  • sdks/python/src/options.rs
  • src/boxlite/src/rest/runtime.rs
  • src/boxlite/src/rest/types.rs
  • src/boxlite/src/runtime/options.rs
  • src/boxlite/src/runtime/rt_impl.rs
  • src/boxlite/src/runtime/types.rs
🚧 Files skipped from review as they are similar to previous changes (24)
  • apps/api/src/boxlite-rest/dto/create-box.dto.spec.ts
  • apps/api/src/boxlite-rest/boxlite-box.controller.ts
  • apps/api/src/boxlite-rest/mappers/box-to-box.mapper.spec.ts
  • apps/dashboard/src/components/Box/CreateBoxDialog.test.tsx
  • apps/api/src/box/constants/box-lifecycle.constants.ts
  • sdks/c/src/info.rs
  • apps/dashboard/src/pages/Boxes.tsx
  • sdks/c/include/boxlite.h
  • sdks/node/src/info.rs
  • sdks/c/src/event_queue.rs
  • apps/api/src/box/dto/create-box.dto.ts
  • src/boxlite/src/rest/runtime.rs
  • sdks/python/src/info.rs
  • apps/api/src/box/dto/box.dto.ts
  • src/boxlite/src/runtime/rt_impl.rs
  • apps/dashboard/src/components/Box/CreateBoxDialog.tsx
  • apps/dashboard/src/lib/cloudBox.ts
  • sdks/c/src/options.rs
  • docs/guides/auto-pause-resume.md
  • apps/api/src/boxlite-rest/boxlite-proxy.controller.spec.ts
  • apps/api/src/boxlite-rest/boxlite-ws-proxy.service.ts
  • apps/api/src/box/managers/box.manager.ts
  • apps/api/src/box/services/box.service.ts
  • apps/api/src/boxlite-rest/boxlite-proxy.controller.ts

Comment thread apps/api/src/migrations/1741087887225-migration.ts Outdated
Comment thread docs/architecture/auto-pause-resume-design.md
Comment thread docs/architecture/auto-pause-resume-design.md Outdated
Comment thread docs/architecture/auto-pause-resume-design.md Outdated
Comment thread sdks/node/lib/native-contracts.ts Outdated
Copilot AI review requested due to automatic review settings July 22, 2026 01:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

xhebox added 6 commits July 22, 2026 09:55
- Cap auto-pause/auto-delete cron queries at 100 boxes per tick with
  deterministic ordering to avoid burst load.
- Retry Redis subscription in BoxStateWaiter on transient failures.
- Reject directly if toBoxDto throws inside the waiter finish path.
- Guard WebSocket auto-resume behind box.autoResumeEnabled.
- Remove obsolete websocket activity test for reverted implementation.
Rename auto_pause_interval/auto_delete_interval/auto_resume_enabled to
auto_pause/auto_delete/auto_resume for consistency with the existing
auto_remove option.

Signed-off-by: xhe <xw897002528@gmail.com>
…uto_delete

Signed-off-by: xhe <xw897002528@gmail.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
sdks/node/lib/native-contracts.ts (1)

90-95: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document lifecycle option units and migration semantics.

These public fields should state that intervals are in seconds and that 0 disables them. Also explain how the deprecated boolean autoRemove maps to autoDelete; “Use autoDelete” alone can lead callers to pass the wrong value type or semantics.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sdks/node/lib/native-contracts.ts` around lines 90 - 95, Update the public
option documentation for autoPause and autoDelete to specify that their
intervals are measured in seconds and that 0 disables the behavior. Expand the
deprecated autoRemove documentation to explain its boolean-to-autoDelete
migration mapping and corresponding semantics, while preserving the existing
field types and declarations.
openapi/reference-server/server.py (1)

383-388: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep build_box_options under the documented 50-line limit.

This function spans Lines 346-410. Extract lifecycle-policy mapping or another cohesive block into a helper so the request conversion remains focused and testable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openapi/reference-server/server.py` around lines 383 - 388, Refactor
build_box_options to remain within the documented 50-line limit by extracting
the cohesive lifecycle-policy mapping for auto_pause, auto_delete, and
auto_resume into a dedicated helper. Have build_box_options invoke that helper
while preserving the existing behavior and keeping request-to-options conversion
focused.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@openapi/reference-server/server.py`:
- Around line 142-144: Update the auto_pause and auto_delete fields in the model
definition to enforce non-negative integer values by adding the ge=0 constraint,
while leaving auto_resume unchanged.

In `@sdks/python/tests/test_options.py`:
- Around line 62-70: Update test_auto_delete_overrides_auto_remove to stop the
created box before cleanup, then assert through the local runtime that the box
is removed immediately when auto_delete=60 despite auto_remove=False. Retain
explicit cleanup only if the box remains, ensuring the test detects precedence
regressions.

In `@src/cli/src/commands/serve/mod.rs`:
- Around line 677-678: Update the request-to-BoxOptions construction in the
serve command so an omitted detach value defaults to false when auto_delete is
enabled, while preserving the existing default for requests without auto-delete.
Ensure the resulting options satisfy BoxOptions::sanitize(), or return a clear
4xx validation error for incompatible explicitly provided values.

In `@src/cli/src/commands/serve/types.rs`:
- Line 39: Add auto_pause and auto_resume alongside auto_delete in the request
schema, then update build_box_options to propagate all three lifecycle fields
into the runtime options. Preserve the existing optional types and mapping
behavior so clients can send any combination without unknown-field rejection.

In `@src/test-utils/src/config_matrix.rs`:
- Around line 89-94: Update the matrix entries around the “default” and
“auto_delete_zero” cases so they test distinct policies: keep “default” using
BoxOptions::default() with auto_delete unset, and reserve auto_delete: Some(0)
exclusively for the explicitly named zero-value case. Preserve each case’s
unique name and avoid duplicate option configurations.

---

Nitpick comments:
In `@openapi/reference-server/server.py`:
- Around line 383-388: Refactor build_box_options to remain within the
documented 50-line limit by extracting the cohesive lifecycle-policy mapping for
auto_pause, auto_delete, and auto_resume into a dedicated helper. Have
build_box_options invoke that helper while preserving the existing behavior and
keeping request-to-options conversion focused.

In `@sdks/node/lib/native-contracts.ts`:
- Around line 90-95: Update the public option documentation for autoPause and
autoDelete to specify that their intervals are measured in seconds and that 0
disables the behavior. Expand the deprecated autoRemove documentation to explain
its boolean-to-autoDelete migration mapping and corresponding semantics, while
preserving the existing field types and declarations.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 66186f7c-5c95-47ea-b5c7-20503e1050fb

📥 Commits

Reviewing files that changed from the base of the PR and between 299adb0 and 12055c2.

📒 Files selected for processing (42)
  • apps/api/src/boxlite-rest/boxlite-box.controller.ts
  • apps/api/src/boxlite-rest/dto/create-box.dto.ts
  • apps/api/src/migrations/pre-deploy/1784250000000-add-box-lifecycle-seconds-migration.ts
  • docs/architecture/auto-pause-resume-design.md
  • openapi/box.openapi.yaml
  • openapi/reference-server/server.py
  • scripts/test/stress/api-create-box.k6.js
  • scripts/test/stress/api-vm-lifecycle.k6.js
  • sdks/c/include/boxlite.h
  • sdks/c/src/options.rs
  • sdks/c/src/tests.rs
  • sdks/go/boxlite_test.go
  • sdks/go/options.go
  • sdks/node/lib/native-contracts.ts
  • sdks/node/src/options.rs
  • sdks/python/src/options.rs
  • sdks/python/tests/test_options.py
  • src/boxlite/src/db/migration/mod.rs
  • src/boxlite/src/db/migration/v8_to_v9.rs
  • src/boxlite/src/db/schema.rs
  • src/boxlite/src/litebox/box_impl.rs
  • src/boxlite/src/rest/types.rs
  • src/boxlite/src/runtime/options.rs
  • src/boxlite/src/runtime/rt_impl.rs
  • src/boxlite/tests/common/mod.rs
  • src/boxlite/tests/execution_shutdown.rs
  • src/boxlite/tests/health_check.rs
  • src/boxlite/tests/lifecycle.rs
  • src/boxlite/tests/mount_security.rs
  • src/boxlite/tests/recovery.rs
  • src/boxlite/tests/rest_integration.rs
  • src/boxlite/tests/security_enforcement.rs
  • src/boxlite/tests/timing_profile.rs
  • src/boxlite/tests/zygote_integration.rs
  • src/cli/src/cli.rs
  • src/cli/src/commands/run.rs
  • src/cli/src/commands/serve/mod.rs
  • src/cli/src/commands/serve/types.rs
  • src/test-utils/src/box_test.rs
  • src/test-utils/src/cache.rs
  • src/test-utils/src/config_matrix.rs
  • src/test-utils/src/home.rs
💤 Files with no reviewable changes (5)
  • apps/api/src/boxlite-rest/dto/create-box.dto.ts
  • scripts/test/stress/api-vm-lifecycle.k6.js
  • apps/api/src/boxlite-rest/boxlite-box.controller.ts
  • scripts/test/stress/api-create-box.k6.js
  • src/boxlite/src/rest/types.rs
🚧 Files skipped from review as they are similar to previous changes (5)
  • sdks/c/include/boxlite.h
  • sdks/go/options.go
  • sdks/node/src/options.rs
  • sdks/python/src/options.rs
  • docs/architecture/auto-pause-resume-design.md

Comment thread openapi/reference-server/server.py Outdated
Comment thread sdks/python/tests/test_options.py
Comment thread src/cli/src/commands/serve/mod.rs Outdated
Comment thread src/cli/src/commands/serve/types.rs
Comment thread src/test-utils/src/config_matrix.rs
/// When false, the box is preserved after stop and can be restarted
/// with `runtime.get(box_id)`.
#[serde(default = "default_auto_remove")]
pub auto_remove: bool,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a hard break changing. Why remove it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean auto_delete duplicates auto_remove.

A direct change to this comment. SDK and APIs remains unchanged. I though you want that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could just keep the flag, and make them co-exist by prioritizing the new flag first.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

obviously you changed the Rust SDK

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could just keep the flag, and make them co-exist by prioritizing the new flag first.

I agree with this and mark it as deprecated but still support it for now

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean that Rust SDK relies on BoxOptions defined here?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct

Copilot AI review requested due to automatic review settings July 22, 2026 04:26
@xhebox
xhebox force-pushed the auto-pause-resume branch from 12055c2 to 138631f Compare July 22, 2026 04:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI review requested due to automatic review settings July 22, 2026 04:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/boxlite/src/runtime/types.rs (1)

386-401: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

exit_code missing from BoxInfo's PartialEq.

exit_code was added to BoxInfo (Line 352) but the hand-written PartialEq impl (Lines 386-401) only checks auto_pause/auto_delete/auto_resume/health_status. Two infos differing only in exit_code compare as equal, silently breaking equality-based change detection for this new, meaningful field.

🐛 Proposed fix
             && self.auto_pause == other.auto_pause
             && self.auto_delete == other.auto_delete
             && self.auto_resume == other.auto_resume
+            && self.exit_code == other.exit_code
             && self.health_status == other.health_status
     }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/boxlite/src/runtime/types.rs` around lines 386 - 401, Update the
hand-written PartialEq implementation for BoxInfo::eq to compare the exit_code
field as well, preserving the existing comparisons for all other fields so
instances differing only in exit_code are unequal.
src/boxlite/src/litebox/watcher.rs (1)

281-306: 🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win

Dead debounce guard in the Probe::Failed branch — persists on every failed probe.

new_failures is always last.failures + 1 (Line 283), so last.failures == new_failures (Line 289) can never be true. The early-return guard never fires, meaning every failed probe unconditionally writes to the DB via self.persist, unlike the Healthy branch's working debounce just above it.

♻️ Proposed fix
             Probe::Failed => {
                 tracing::warn!(box_id = %self.box_id, "Health check probe failed");
                 let new_failures = last.failures + 1;
                 let new_state = if new_failures >= retries {
                     HealthState::Unhealthy
                 } else {
                     last.state
                 };
-                if last.state == new_state && last.failures == new_failures {
+                if last.state == new_state && last.state == HealthState::Unhealthy {
+                    // Already unhealthy and staying unhealthy: nothing new to persist.
                     return Continue(());
                 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/boxlite/src/litebox/watcher.rs` around lines 281 - 306, Fix the debounce
logic in the Probe::Failed branch so repeated failed probes that do not change
the health snapshot return before calling self.persist. Replace the impossible
last.failures == new_failures comparison with a comparison against the
persisted/current health state, while preserving transition handling through
mark_health_check_failure and the existing Break/Continue behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/architecture/auto-pause-resume-design.md`:
- Line 7: Align the lifecycle semantics described in the architecture document
so local auto_delete behavior is consistent throughout. Update the rejection
statement and the sections around the local lifecycle behavior to clearly
distinguish cloud/REST unsupported configurations from supported local
auto_delete behavior, preserving one unambiguous meaning per runtime.

In `@sdks/c/include/boxlite.h`:
- Around line 586-590: Document the public lifecycle setters with comprehensive
API documentation: in sdks/c/include/boxlite.h lines 586-590, add comments for
boxlite_options_set_auto_pause_interval,
boxlite_options_set_auto_delete_interval, and
boxlite_options_set_auto_resume_enabled describing time units, zero-value
behavior, and accepted boolean values; in sdks/c/src/options.rs lines 170-186,
add Rust docstrings to the corresponding public helper functions, preserving
their existing behavior.

In `@sdks/c/src/options.rs`:
- Around line 176-179: Ensure explicit auto-delete settings deterministically
override the legacy auto-remove option: update options_set_auto_delete_interval
in sdks/c/src/options.rs to clear auto_remove, and update the Node conversion in
sdks/node/src/options.rs and Python conversion in sdks/python/src/options.rs to
apply the same precedence or reject configurations specifying both values.
Preserve the configured auto-delete delay instead of retaining auto_remove=true.

---

Outside diff comments:
In `@src/boxlite/src/litebox/watcher.rs`:
- Around line 281-306: Fix the debounce logic in the Probe::Failed branch so
repeated failed probes that do not change the health snapshot return before
calling self.persist. Replace the impossible last.failures == new_failures
comparison with a comparison against the persisted/current health state, while
preserving transition handling through mark_health_check_failure and the
existing Break/Continue behavior.

In `@src/boxlite/src/runtime/types.rs`:
- Around line 386-401: Update the hand-written PartialEq implementation for
BoxInfo::eq to compare the exit_code field as well, preserving the existing
comparisons for all other fields so instances differing only in exit_code are
unequal.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9354b173-47e0-4b9e-beef-fa984991fdfc

📥 Commits

Reviewing files that changed from the base of the PR and between 12055c2 and 138631f.

⛔ Files ignored due to path filters (1)
  • apps/go.work.sum is excluded by !**/*.sum
📒 Files selected for processing (92)
  • apps/api-client-go/api/openapi.yaml
  • apps/api-client-go/api_box.go
  • apps/api-client-go/model_box.go
  • apps/api/src/box/constants/box-lifecycle.constants.ts
  • apps/api/src/box/controllers/box.controller.ts
  • apps/api/src/box/dto/box.dto.ts
  • apps/api/src/box/dto/create-box.dto.ts
  • apps/api/src/box/entities/box.entity.ts
  • apps/api/src/box/managers/box.manager.ts
  • apps/api/src/box/repositories/box.repository.ts
  • apps/api/src/box/services/box-state-waiter.service.spec.ts
  • apps/api/src/box/services/box-state-waiter.service.ts
  • apps/api/src/box/services/box.service.ts
  • apps/api/src/boxlite-rest/box-auto-resume.service.spec.ts
  • apps/api/src/boxlite-rest/box-auto-resume.service.ts
  • apps/api/src/boxlite-rest/boxlite-box.controller.ts
  • apps/api/src/boxlite-rest/boxlite-proxy.controller.spec.ts
  • apps/api/src/boxlite-rest/boxlite-proxy.controller.ts
  • apps/api/src/boxlite-rest/boxlite-rest-routing.spec.ts
  • apps/api/src/boxlite-rest/boxlite-rest.module.ts
  • apps/api/src/boxlite-rest/boxlite-ws-proxy.service.spec.ts
  • apps/api/src/boxlite-rest/boxlite-ws-proxy.service.ts
  • apps/api/src/boxlite-rest/dto/box-response.dto.ts
  • apps/api/src/boxlite-rest/dto/create-box.dto.spec.ts
  • apps/api/src/boxlite-rest/dto/create-box.dto.ts
  • apps/api/src/boxlite-rest/mappers/box-to-box.mapper.spec.ts
  • apps/api/src/boxlite-rest/mappers/box-to-box.mapper.ts
  • apps/api/src/migrations/pre-deploy/1784250000000-add-box-lifecycle-seconds-migration.ts
  • apps/dashboard/src/components/Box/CreateBoxDialog.test.tsx
  • apps/dashboard/src/components/Box/CreateBoxDialog.tsx
  • apps/dashboard/src/lib/cloudBox.test.ts
  • apps/dashboard/src/lib/cloudBox.ts
  • apps/dashboard/src/pages/Boxes.tsx
  • apps/libs/api-client/src/api/box-api.ts
  • apps/libs/api-client/src/docs/Box.md
  • apps/libs/api-client/src/docs/BoxApi.md
  • apps/libs/api-client/src/models/box.ts
  • apps/proxy/pkg/proxy/get_box_target.go
  • apps/proxy/pkg/proxy/proxy.go
  • apps/scripts/e2e-dev-smoke.mjs
  • docs/README.md
  • docs/architecture/README.md
  • docs/architecture/auto-pause-resume-design.md
  • docs/guides/README.md
  • docs/guides/auto-pause-resume.md
  • openapi/box.openapi.yaml
  • openapi/reference-server/server.py
  • scripts/build/build-runtime.sh
  • scripts/test/stress/api-create-box.k6.js
  • scripts/test/stress/api-vm-lifecycle.k6.js
  • sdks/c/include/boxlite.h
  • sdks/c/src/event_queue.rs
  • sdks/c/src/info.rs
  • sdks/c/src/options.rs
  • sdks/c/src/tests.rs
  • sdks/go/boxlite_test.go
  • sdks/go/info.go
  • sdks/go/options.go
  • sdks/node/lib/native-contracts.ts
  • sdks/node/src/info.rs
  • sdks/node/src/options.rs
  • sdks/python/src/info.rs
  • sdks/python/src/options.rs
  • sdks/python/tests/test_options.py
  • src/boxlite/src/lib.rs
  • src/boxlite/src/litebox/box_impl.rs
  • src/boxlite/src/litebox/watcher.rs
  • src/boxlite/src/rest/runtime.rs
  • src/boxlite/src/rest/types.rs
  • src/boxlite/src/runtime/options.rs
  • src/boxlite/src/runtime/rt_impl.rs
  • src/boxlite/src/runtime/types.rs
  • src/boxlite/tests/common/mod.rs
  • src/boxlite/tests/execution_shutdown.rs
  • src/boxlite/tests/health_check.rs
  • src/boxlite/tests/lifecycle.rs
  • src/boxlite/tests/mount_security.rs
  • src/boxlite/tests/recovery.rs
  • src/boxlite/tests/rest_integration.rs
  • src/boxlite/tests/run_main_command.rs
  • src/boxlite/tests/security_enforcement.rs
  • src/boxlite/tests/timing_profile.rs
  • src/boxlite/tests/zygote_integration.rs
  • src/cli/src/cli.rs
  • src/cli/src/commands/create.rs
  • src/cli/src/commands/run.rs
  • src/cli/src/commands/serve/mod.rs
  • src/cli/src/commands/serve/types.rs
  • src/test-utils/src/box_test.rs
  • src/test-utils/src/cache.rs
  • src/test-utils/src/config_matrix.rs
  • src/test-utils/src/home.rs
💤 Files with no reviewable changes (3)
  • scripts/test/stress/api-create-box.k6.js
  • apps/proxy/pkg/proxy/get_box_target.go
  • scripts/test/stress/api-vm-lifecycle.k6.js
🚧 Files skipped from review as they are similar to previous changes (68)
  • docs/architecture/README.md
  • scripts/build/build-runtime.sh
  • src/boxlite/tests/timing_profile.rs
  • sdks/go/boxlite_test.go
  • apps/api/src/box/controllers/box.controller.ts
  • apps/api/src/box/constants/box-lifecycle.constants.ts
  • apps/api/src/box/services/box-state-waiter.service.spec.ts
  • src/boxlite/src/lib.rs
  • apps/api/src/boxlite-rest/boxlite-rest.module.ts
  • src/cli/src/commands/run.rs
  • apps/libs/api-client/src/models/box.ts
  • sdks/node/src/info.rs
  • src/test-utils/src/home.rs
  • docs/README.md
  • apps/dashboard/src/lib/cloudBox.test.ts
  • docs/guides/README.md
  • src/cli/src/cli.rs
  • sdks/python/src/info.rs
  • apps/api/src/boxlite-rest/box-auto-resume.service.spec.ts
  • apps/api/src/box/repositories/box.repository.ts
  • src/test-utils/src/box_test.rs
  • src/boxlite/tests/security_enforcement.rs
  • apps/api/src/boxlite-rest/dto/create-box.dto.spec.ts
  • apps/api/src/box/entities/box.entity.ts
  • apps/api/src/boxlite-rest/boxlite-rest-routing.spec.ts
  • src/boxlite/tests/rest_integration.rs
  • apps/api/src/boxlite-rest/dto/box-response.dto.ts
  • src/boxlite/tests/common/mod.rs
  • sdks/node/lib/native-contracts.ts
  • src/boxlite/tests/zygote_integration.rs
  • src/boxlite/tests/execution_shutdown.rs
  • src/boxlite/src/rest/runtime.rs
  • apps/libs/api-client/src/docs/Box.md
  • sdks/c/src/info.rs
  • apps/api/src/migrations/pre-deploy/1784250000000-add-box-lifecycle-seconds-migration.ts
  • apps/api/src/boxlite-rest/boxlite-ws-proxy.service.spec.ts
  • openapi/reference-server/server.py
  • apps/api/src/boxlite-rest/box-auto-resume.service.ts
  • apps/api/src/box/dto/box.dto.ts
  • apps/dashboard/src/components/Box/CreateBoxDialog.test.tsx
  • sdks/python/tests/test_options.py
  • src/boxlite/tests/lifecycle.rs
  • src/boxlite/tests/health_check.rs
  • apps/api/src/boxlite-rest/boxlite-box.controller.ts
  • apps/api/src/boxlite-rest/boxlite-ws-proxy.service.ts
  • sdks/c/src/event_queue.rs
  • apps/scripts/e2e-dev-smoke.mjs
  • apps/api/src/box/dto/create-box.dto.ts
  • src/boxlite/tests/recovery.rs
  • apps/api/src/boxlite-rest/boxlite-proxy.controller.spec.ts
  • apps/api-client-go/api_box.go
  • apps/dashboard/src/components/Box/CreateBoxDialog.tsx
  • apps/api/src/boxlite-rest/mappers/box-to-box.mapper.spec.ts
  • apps/api/src/boxlite-rest/dto/create-box.dto.ts
  • sdks/go/options.go
  • apps/libs/api-client/src/api/box-api.ts
  • apps/api-client-go/api/openapi.yaml
  • src/test-utils/src/config_matrix.rs
  • apps/dashboard/src/lib/cloudBox.ts
  • apps/api/src/box/services/box-state-waiter.service.ts
  • src/boxlite/src/runtime/rt_impl.rs
  • apps/api/src/box/services/box.service.ts
  • docs/guides/auto-pause-resume.md
  • openapi/box.openapi.yaml
  • apps/api/src/box/managers/box.manager.ts
  • apps/proxy/pkg/proxy/proxy.go
  • src/boxlite/src/rest/types.rs
  • apps/api/src/boxlite-rest/boxlite-proxy.controller.ts

Comment thread docs/architecture/auto-pause-resume-design.md
Comment thread sdks/c/include/boxlite.h
Comment thread sdks/c/src/options.rs
@DorianZheng DorianZheng added the e2e-local Triggers the local (in-process) E2E suite on the self-hosted runner label Jul 22, 2026
@DorianZheng
DorianZheng merged commit b00b29d into boxlite-ai:main Jul 22, 2026
58 of 60 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

e2e-local Triggers the local (in-process) E2E suite on the self-hosted runner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants