Three related bugs caused oneshot containers to run indefinitely:
1. watcher.go: switch b.policy had no case OneShot, so even when the
idle timeout fired, no remove action was emitted.
2. watcher.go + manager.go/recoverBoxes: idleTimeoutD was only set for
Session and LongRunning on recovery; OneShot defaulted to 0, which
caused the watcher to hit the `timeout <= 0` early-return and skip
all checks entirely.
3. agent/sandbox/v2/options.go: same gap — opts.IdleTimeout == 0 guard
only filled defaults for Session and LongRunning.
Fix: add DefaultOneShotIdleTimeout (30 min), wire it in recoverBoxes
and options.go, and add case OneShot → Remove in watcher.go.
Made-with: Cursor
- Renamed `buildInput` to `buildLastUserMessageJSONL` to better reflect its purpose of constructing JSONL from the last user message.
- Updated test cases to use the new function, ensuring they accurately verify the behavior of skipping system messages and only including the last user message.
- Removed the now redundant `buildFirstRequestJSONL` function, streamlining the input building process in the Claude command tests.
- Updated the BuildIdentifier function to use the ownerID as a fallback for workspaceID, improving identifier generation consistency.
- Enhanced ResolveNodeID to auto-select nodes based on filters and added detailed logging for better traceability.
- Modified GetComputer to include improved logging and streamlined node resolution logic.
- Introduced StringOrArray type for flexible handling of computer filter parameters in the SandboxConfig.
- Enriched workspace response structure to include detailed node information, enhancing API response clarity.
- Implemented default workspace ID generation based on owner and node, ensuring consistent workspace identification.
- Added locale support in CreateOptions for better internationalization.
- Replaced the previous file extension checks with a unified parsing function for sandbox configuration, improving code clarity and maintainability.
- Introduced a new HostExecConfig structure to manage local execution settings, allowing for more granular control over command execution permissions.
- Removed deprecated Moapi API files and related functionality, simplifying the codebase and reducing maintenance overhead.
- Updated the Tai node registration process to ensure local capabilities are accurately reflected based on the environment, enhancing overall system robustness.
- Updated BuildIdentifier to include assistant ID in session identifiers for better uniqueness.
- Implemented automatic starting of stopped boxes in resolveBox, improving recovery processes.
- Introduced status management for boxes, allowing for accurate tracking of their state (running, exited, stopped).
- Added idle timeout defaults based on lifecycle policy in BuildCreateOptions, enhancing configuration flexibility.
- Refactored tests to validate new box status behavior and lifecycle management improvements.
Made-with: Cursor
- Modified BuildGRPCEnv to accept the Tai node's gRPC port directly, enhancing flexibility for different modes.
- Updated test cases to reflect changes in gRPC address construction, ensuring accurate environment variable settings for local, direct, and tunnel modes.
- Added a new test for handling unknown modes, improving test coverage and robustness.
- Adjusted Docker configuration to ensure proper host resolution for gRPC communication.
Made-with: Cursor
- Introduced a human-readable display name for the sandbox, constructed from the agent and workspace names.
- Updated the BuildIdentifier function to include workspace ID in identifiers for long-running and persistent lifecycles.
- Modified sandbox creation options to incorporate the display name, improving clarity in sandbox management.
- Refactored related tests to ensure compatibility with the new identifier structure and display name integration.
Made-with: Cursor
- Added support for issuing and passing a sandbox token during stream execution in the Assistant.
- Updated StreamRequest to include a Token field for managing user authentication.
- Enhanced ClaudeRunner to set environment variables for the sandbox token and refresh token.
- Refactored SandboxToken structure to clarify its purpose and manage token credentials effectively.
- Modified sandbox management routes to enforce OAuth guard for improved security.
Made-with: Cursor
- Implemented a new endpoint to retrieve the absolute path of a workspace's root directory.
- Enhanced the workspace interface with a GetRoot method to facilitate this functionality.
- Updated the workspace manager to utilize the new method for improved path resolution.
Made-with: Cursor
- Refactored the sandbox initialization process to resolve the connector before obtaining the Computer, allowing for the injection of OPENAI_PROXY_* environment variables.
- Updated the GetComputer and BuildCreateOptions functions to accept an optional connector parameter for improved environment variable management.
- Standardized the VNC configuration by replacing SANDBOX_VNC_ENABLED with VNC_ENABLED across Dockerfiles and related scripts for consistency.
- Enhanced the VNC service startup script to check the new VNC_ENABLED variable, ensuring proper service initialization.
Made-with: Cursor
- Updated the registration process to utilize NodeID instead of TaiID, allowing for server-generated TaiIDs.
- Implemented additional fields in the registration request, including DisplayName and improved error handling for missing parameters.
- Enhanced the connection logic for registered nodes, ensuring proper client binding and logging for better traceability.
- Introduced new methods for extracting and managing extra claims in OAuth tokens, improving the flexibility of user identification.
Made-with: Cursor
- Implemented V2 sandbox initialization in the assistant loading process, allowing for standalone sandbox.yao configuration.
- Added support for V2 sandbox execution paths in the Assistant's Stream method, differentiating between V1 and V2 sandboxes.
- Introduced comprehensive tests for V2 sandbox configurations, ensuring correct loading and execution behavior.
- Updated the context and types to accommodate V2 sandbox features, including system information and workspace management.
Made-with: Cursor
- Added sandbox initialization in the load process to ensure proper setup of the sandbox manager.
- Implemented gRPC heartbeat handling to track container liveness, enhancing the monitoring capabilities of the sandbox.
- Updated related documentation to reflect the new integration and functionality.
Made-with: Cursor
- Updated benchmark and test functions to utilize node configurations instead of pool configurations for improved clarity and consistency.
- Refactored related setup functions and test cases to align with the new node-based architecture.
- Adjusted error messages and documentation to reflect the transition from pool to node terminology.
Made-with: Cursor
- Updated benchmark functions to utilize TaiID instead of pool names for improved consistency and accuracy in tests.
- Refactored test cases across various files to ensure compatibility with the new TaiID structure.
- Enhanced setup functions to accept pointers to poolConfig for better memory management.
- Removed deprecated config struct and adjusted related documentation to reflect the changes in the sandbox architecture.
Made-with: Cursor
- Change Docker image references in the unit-test workflow from yaoapp/tai:1.2.0 to yaoapp/tai:latest for consistency and to ensure the latest features and fixes are utilized.
- Update related documentation to reflect the unified Computer interface in the sandbox, replacing Box and Host references with Computer.
Made-with: Cursor
- Define Computer interface with Exec, Stream, VNC, Proxy, ComputerInfo,
BindWorkplace, and Workplace methods in types.go
- Implement Computer interface on Host (VNC and Proxy via Tai gRPC)
- Add VNC/Proxy stubs to Box (delegates to Tai HTTP endpoints)
- Update JSAPI bindings for unified computer.vnc() and computer.proxy()
- Extend host_test.go with __host__ VNC and HTTP proxy test cases
Made-with: Cursor
- Update CI (unit-test.yml, pr-test.yml) to use yaoapp/tai:1.2.0
with new default ports (gRPC:19100, HTTP:8099, VNC:16080, Docker:12375)
- Add explicit 0.0.0.0 bind for containerized Tai instances
- Fix sandbox/v2 grpc.go default port fallback (9100 → 19100)
- Fix tai/tunnel/proxy.go fallback ports (8080→8099, 6080→16080)
- Sync tai SDK and sandbox/v2 documentation with implementation
- Add new docs: api.md, registry.md, tunnel.md
Made-with: Cursor
Add HostExecStream type and Host.Stream method that wraps the HostExec
gRPC ExecStream RPC, providing separate stdout/stderr channels with
Wait and Cancel support. Includes 4 tests covering incremental output,
multi-line, stderr separation, and cancel behavior across k8s and
win-linux platforms. Update API.md documentation accordingly.
Made-with: Cursor
- Refactor GPT-5 test cases to improve clarity and maintainability.
- Comment out tests for temperature handling in GPT-5, indicating they are temporarily disabled.
- Remove the obsolete hostexec test file to clean up the codebase.
- Enhance the sandbox manager to support host execution capabilities and improve lifecycle management.
Made-with: Cursor
- Remove x-grpc-upstream metadata from gateway forwarding; use SetUpstream
- Remove YAO_GRPC_TAI / YAO_GRPC_UPSTREAM env vars from sandbox containers
- Delete benchmark-sandbox-v2 CI job (run benchmarks locally)
- Simplify sandbox-v2 CI to tai SDK + workspace tests only
- Add HostExec support to sandbox v2 box interface
- Add K8s semaphore and cleanup mutex for test stability
- Update design docs to reflect new architecture
Made-with: Cursor
Server lifecycle:
- Introduce service.Service to manage HTTP + gRPC startup/shutdown
- Fix gRPC mutex deadlock in StartServer when port is occupied
- Add GracefulStop with 5s timeout before forced Stop in grpc.go
- Pre-check HTTP and gRPC port availability in cmd/start.go
- Print gRPC server address in startup access-points block
gRPC client refactor:
- Move token manager and client from tai/grpc/ to grpc/client/
- Add backward-compatible aliases in tai/yao.go and tai/token.go
- Update cmd/run.go to import grpc/client directly (no tai dependency)
Sandbox v2 docker migration:
- Delete sandbox/v2/docker/ (moved to tai repo)
- Update sandbox/docker/build.sh hint to point to tai repo
- Clean up .gitignore entries for removed docker directory
- Temporarily disable SandboxV2Test and BenchmarkSandboxV2 in CI
(docker images need rebuild after tai repo migration)
Tai integration:
- Add direct-mode registration API handlers in tai/api/
- Add heartbeat handler and token management wrappers
- Update tai/registry and tai/tunnel for latest protocol
- Replace yao-grpc references with tai call in docs
Made-with: Cursor
- Introduce a new "tunnel" scheme for the Tai client, allowing connections through Yao's reverse proxy.
- Enhance the Tai registry to manage tunnel-connected nodes and their ports.
- Add WebSocket and reverse proxy routes for tunnel connections in the OpenAPI server.
- Implement tunnel-specific proxy and VNC handling to facilitate communication with containerized environments.
- Update gRPC environment variable handling to support tunnel connections.
These changes improve the Tai service's flexibility and connectivity options, enabling better integration with remote and containerized environments.
- Implement steps to generate kubeconfig for both the Tai K8s container and the test runner, ensuring proper configuration for Kubernetes interactions.
- Update the Docker run command to mount the generated kubeconfig, enhancing the integration of Tai with K8s.
- Remove the previous kubeconfig generation step for the Tai K8s proxy, streamlining the workflow.
These changes improve the CI workflows for the Tai service by ensuring accurate kubeconfig generation and integration with Kubernetes environments.
- Update the `testPools` function to include a new "containerized" pool configuration, allowing for testing with Tai running in a containerized environment.
- Revise comments to clarify the conditions under which each pool configuration is available, improving documentation for future reference.
These changes improve the flexibility of the testing framework by accommodating additional deployment scenarios for the Tai service.
- Rename and enhance the Docker instance startup steps for Tai in CI workflows, improving clarity and readiness checks for both HTTP and gRPC services.
- Update health check logic to ensure accurate reporting of service readiness, including specific error messages for failures.
- Modify environment variable configurations to streamline the setup for K8s and Docker instances, ensuring consistent port usage across tests.
These changes improve the reliability and clarity of the CI processes for the Tai service, enhancing overall testing and deployment workflows.
- Add workspace integration as a new feature in Sandbox V2, allowing for persistent user storage.
- Update the Manager API to include new methods for workspace management and image handling.
- Refactor the Pool struct to include additional options and improve lifecycle management.
- Revise implementation status in IMPL.md to reflect completed phases and optimizations, ensuring clarity on the current state of the project.
These changes enhance the functionality and documentation of Sandbox V2, improving user experience and system architecture.
- Introduce new unit test targets for Workspace and Sandbox V2 integration in the Makefile, ensuring comprehensive testing of the new features.
- Update CI workflows to support MongoDB service for Sandbox V2 tests and improve Docker image handling.
- Implement Workspace as a first-class entity, allowing for persistent storage decoupled from container lifecycles.
- Enhance the Box struct to manage workspace IDs and update related methods for improved functionality.
- Refactor tests to accommodate new Workspace features, ensuring robust testing of the integration.
These changes significantly improve the testing framework and functionality of the Sandbox V2, enhancing the overall architecture and user experience.
- Add new test cases for VNC URL generation and connection in `box_attach_test.go`, ensuring proper functionality of VNC features.
- Update the Docker test image to include VNC desktop components, enhancing the testing environment for graphical applications.
- Modify the entrypoint script to start a virtual framebuffer and VNC server, allowing for remote desktop access during tests.
- Increase the test timeout in the Makefile to accommodate longer-running VNC tests.
These changes improve the testing framework for Sandbox V2 by integrating VNC capabilities, facilitating better testing of graphical applications.
- Add new gRPC endpoint for Heartbeat in the Yao service, enabling communication with the sandbox.
- Update Makefile to include a dedicated unit test target for Sandbox V2, ensuring proper testing of new features.
- Enhance CI workflows to incorporate Sandbox V2 tests, allowing for dual-mode testing (local and remote) with Docker.
- Modify .gitignore to exclude specific Docker files while allowing shell scripts for Sandbox V2.
- Update documentation in DESIGN.md to reflect the new architecture and capabilities of the Sandbox V2.
These changes enhance the Yao SDK's functionality, providing improved support for sandbox operations and testing.
- Add gRPC server configuration to the application, allowing for gRPC communication.
- Introduce new Makefile targets for gRPC unit testing and proto code generation.
- Update CI workflows to include gRPC tests with SQLite as the transport layer.
- Refactor the sandbox design to support multi-node capabilities and improve isolation.
- Enhance the service layer to facilitate internal request forwarding for gRPC APIs.
This commit lays the groundwork for integrating gRPC into the Yao SDK, improving performance and scalability.
- Replace direct cleanup calls in the Close method with a sync.Once mechanism to guarantee that cleanup runs only once.
- Remove the cleanup method and integrate its functionality into the Close method, streamlining resource management.
- Update the serve method to call Close for cleanup, enhancing clarity and consistency in session termination.
- Modify the test for the Claude executor to check for the IPC socket at the new path "/run/yao.sock" instead of the previous "/tmp/yao.sock". This aligns the test with the updated default configuration for the IPC socket path, ensuring consistency across the codebase.
- Change the ContainerIPCSocket path from "/tmp/yao.sock" to "/run/yao.sock" to align with system conventions for IPC sockets.
This change improves the configuration's compatibility with standard practices for inter-process communication.
- Add support for increasing the shared memory size (/dev/shm) for Chrome rendering in VNC images, setting it to a quarter of MaxMemory with a minimum of 256MB.
- This change addresses Chrome renderer/GPU process crashes by ensuring adequate memory allocation for namespace-based process isolation.
- Ensure the existence of $HOME/.Xauthority for PyAutoGUI/Xlib compatibility.
- Adjust PYTHONPATH to maintain access to user-installed Python packages.
- Explicitly set XAUTHORITY to the correct path for X11 authentication.
- Pass secrets as environment variables for Claude CLI to ensure proper access.
- Refactor VNC image support check to utilize a centralized keyword list for better maintainability.
- Introduce a new Chrome image for the sandbox, enabling VNC access with real Chrome and CDP support (amd64 only).
- Update README to reflect the addition of the Chrome image and its build instructions.
- Modify build script to include a dedicated build process for the Chrome image.
- Enhance .gitignore to exclude the new Chrome plan file.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Fix ListDir to support BusyBox/Alpine ls by falling back from GNU
--time-style format, resolving CI test failures
- Update parseLS to handle both GNU (epoch) and BusyBox (date string) formats
- Fix claude-proxy streaming: always include usage in message_delta events
to prevent Claude CLI from falling back to non-streaming mode
- Fix claude-proxy non-streaming: ensure usage is always present in responses
- Add paragraph separators between text blocks in Claude executor stream parser
- Translate VNC proxy UI from Chinese to English
- Rename sandbox-claude-playwright to sandbox-claude-browser across
Dockerfiles, build scripts, and documentation
Co-authored-by: Cursor <cursoragent@cursor.com>
- Implement GetSandboxID method to return a mock sandbox ID for testing.
- Add GetVNCUrl method to return an empty string for VNC access in tests.
- Update SandboxExecutor interface to include new methods for sandbox identification and VNC URL retrieval.
- Enhance context creation to set sandbox ID and VNC URL properties in the sandbox instance.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Add passwordless sudo for sandbox user in playwright and desktop images
- Configure Yao branding for Fluxbox (CUI dark theme, centered logo)
- Configure Yao branding for XFCE (panel icons, wallpaper, workspace shortcut)
- Add D-Bus support for XFCE desktop environment
- Add dynamic wallpaper generation with configurable resolution and logo size
- Hide Fluxbox toolbar for cleaner Playwright automation view
- Create chromium wrapper script using Playwright's bundled browser
- Add feh and imagemagick for wallpaper management in Fluxbox
- Update .gitignore for config scripts and TODO file
Co-authored-by: Cursor <cursoragent@cursor.com>
- Add VNC-enabled Docker images (playwright, desktop) with Xvfb, x11vnc, noVNC
- Implement VNC proxy service for WebSocket-based VNC access
- Add API endpoints: /sandbox/{id}/vnc, /vnc/client, /vnc/ws
- Support dynamic VNC port mapping for Docker Desktop (macOS/Windows)
- Add YAO_SANDBOX_VNC_PORT_MAPPING config option for local development
- Update build.sh to support building VNC images
- Include design document and updated README
Co-authored-by: Cursor <cursoragent@cursor.com>
- Refactor BuildCommand to support session continuation using --continue flag.
- Introduce BuildCommandWithContinuation to handle both initial and continuation requests.
- Add BuildLastUserMessageJSONL for generating JSONL from the last user message in continuation scenarios.
- Enhance Executor to check for existing sessions and adjust command building accordingly.
- Update environment setup to ensure session data is stored correctly for persistence.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Update ReadFile method to read directly from the host's bind-mounted workspace instead of using Docker's CopyFromContainer, enhancing performance.
- Introduce containerPathToHost method to convert container paths to host paths, ensuring proper access to bind-mounted directories.
- Simplify idle container cleanup logic by storing the idle time in a variable for better readability.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Implement secure config file location (/tmp/.yao/proxy.json) instead of user-visible /workspace/
- Add generic options map support for backend-specific parameters (e.g., thinking for Volcengine GLM-4.7)
- Add secrets support for passing sensitive env vars (e.g., GITHUB_TOKEN) to sandbox container
- Remove excessive debug logs, keep critical ones with log.Printf("[Sandbox]...")
- Fix test assertions for system prompt passing via CLI args instead of env var
- Update i18n messages for sandbox loading states
Co-authored-by: Cursor <cursoragent@cursor.com>
- Update TestClaudeCommandBuilding to expect new command format
- Rename TestClaudeCCRConfigBuilding to TestClaudeProxyConfigBuilding
- Update assertions for claude-proxy env vars instead of CCR
- Apply gofmt formatting to proxy/types.go
Co-authored-by: Cursor <cursoragent@cursor.com>
- Add claude-proxy: lightweight Go proxy to translate between Anthropic
and OpenAI-compatible APIs with full streaming and tool-calling support
- Update Dockerfile to include claude-proxy binary (multi-arch)
- Add auto-start proxy via entrypoint when env vars are set
- Update executor.go to write proxy config and start proxy
- Simplify command.go to use direct Claude CLI with proxy
- Support both docker run -e and config file for proxy settings
Co-authored-by: Cursor <cursoragent@cursor.com>