Conversation
…unting
The agentOs() sandbox config previously only accepted static options,
meaning all actor instances shared a single sandbox container. This adds
createOptions as a mutually exclusive alternative that is called
per-actor-instance so each gets its own dedicated sandbox.
Core implementation:
- Add createOptions to Zod schema with XOR .refine() enforcement
- Create AgentOsActorOptionsConfig exclusive union type (?: never pattern)
- Rewrite ensureVm() to resolve options from createOptions(c) or config.options
- Add promise-caching guard (vmBootPromise) to prevent concurrent actions
from creating duplicate VMs via race condition
- Add defensive null-check on createOptions return with clear error message
- Wrap createOptions errors with context message and { cause } for stack traces
- Add debug log before factory invocation for slow-boot observability
- Clear vmBootPromise in onSleep and onDestroy
DX improvements:
- Add JSDoc to options and createOptions union members for IDE hover docs
- Fix any leak in AgentOsActorContext and AgentOsActionContext database
param (any -> DatabaseProvider<RawAccess>)
- Fix zFunction() Zod error message ('Expected a function' instead of
generic 'Invalid input')
- Export AgentOsActorContext, AgentOsCreateContext alias, AgentOsActorConfigInput
Example and docs:
- Rewrite sandbox example to use createOptions with context param
- Fix 'Sandbox extension' -> 'Sandbox mounting' terminology in client.ts
- Add missing deps to examples/agent-os/package.json
- Add 'Per-instance options' section to configuration.mdx
- Fix stale sandbox: { enabled: true } API in index.mdx crash course
- Fix missing .ts import extension in sandbox.mdx
Tests:
- Add agentOsCreateOptionsTestActor fixture to driver-test-suite
- Add 3 driver tests: writeFile round-trip, exec, two-instance isolation
- Add agent-os-config-validation.test.ts with 7 tests (Zod XOR
enforcement, runtime factory boot, context availability)
- Add 9 type-level assertions to actor-types.test.ts (exclusive union,
context typing, c.db not any, async callback, generic propagation)
Mirrors the sandbox actor pattern where the sandbox ID is stored in actor state so that after a sleep/wake cycle the createOptions callback can reconnect to the same container instead of provisioning a new one. State changes: - Add sandboxId: string | null to AgentOsActorState (persisted across sleep/wake). The createOptions callback reads c.state.sandboxId and passes it to SandboxAgent.start(), then persists the returned ID back. Config changes: - Add destroyOptions callback (only valid with createOptions, enforced by both TypeScript union and Zod refine). Called during onDestroy so the user can clean up external resources like sandbox containers. Lifecycle hardening: - Wrap dispose() in try/finally in both onSleep and onDestroy so vars are always cleaned up even if dispose throws, matching the sandbox actor's teardownAgentRuntime pattern. - Clear sandboxId in a finally block in onDestroy so state is always consistent regardless of whether destroyOptions succeeds or fails. Tests: - Type tests for sandboxId typing, destroyOptions union exclusivity - Zod schema tests for destroyOptions acceptance, rejection with options, and non-function rejection - Runtime tests for sandboxId state persistence and destroyOptions config acceptance Docs: - Update sandbox.mdx, configuration.mdx, and index.mdx with the sandboxId reuse pattern and destroyOptions documentation - Fix 'extension' -> 'sandbox mounting' terminology in sandbox.mdx
|
This PR was not deployed automatically as @brittianwarner does not have access to the Railway project. In order to get automatic PR deploys, please add @brittianwarner to your workspace on Railway. |
PR Review: Feat/agent os sandbox create optionsThis PR adds a Critical Issue:
|
rivetkit-typescript/packages/rivetkit/tests/agent-os-config-validation.test.ts
Outdated
Show resolved
Hide resolved
| @@ -51,6 +55,60 @@ export const registry = setup({ use: { vm } }); | |||
| registry.start(); | |||
There was a problem hiding this comment.
simplify to:
- static
vs - dynamic
then just include a brief snippet showing dynamic options. show using the key to dynamically determine what to do.
example: pass env var based on c.key
rivetkit-typescript/packages/rivetkit/src/agent-os/actor/index.ts
Outdated
Show resolved
Hide resolved
rivetkit-typescript/packages/rivetkit/src/agent-os/actor/index.ts
Outdated
Show resolved
Hide resolved
Remove destroyOptions (deferred to c.getSandbox() auto-destroy). Rename AgentOsActorContext to AgentOsContext, vmBootPromise to vmBootGuard. Fix any types in zFunction. Simplify docs to static vs dynamic sections with c.key example. Update sandbox docs and example to c.getSandbox() API. Delete config validation tests. Remove destroyOptions type tests and @rivet-dev/agent-os-sandbox dep.
Description
Please include a summary of the changes and the related issue. Please also include relevant motivation and context.
Type of change
How Has This Been Tested?
Please describe the tests that you ran to verify your changes.
Checklist: