Solari

VMs

solari creates GUI VMs with Client::createDesktop() and hands back the same Sandbox handle a sandbox uses, plus streamUrl() for the live view. Driving the GUI is not part of this surface. See the C++ SDK hub for install and configuration.

#include <solari/solari.hpp>  // umbrella header
Lifecycle and compute, not GUI control
You can create a VM, reach its stream URL, and use commands, files, code, and git on it. Mouse, keyboard, screenshot, display, and clipboard have no C++ binding. See What you cannot do.

Contents

Client

The same Client that creates sandboxes. Only the VM-specific calls are documented here.

Methods

createDesktop()

std::shared_ptr<Sandbox> createDesktop(const CreateSandboxOptions& opts = {})

POST /sandboxes with kind: "desktop": creates a GUI VM and returns a handle. Retry-safe: it sends a fresh idempotency key. Routes through the pre-existing SandboxKind::Desktop via a private createWithKind.

Parameters:

Returns: std::shared_ptr<Sandbox>, not connected; call connect() before any RPC. kind() is "desktop" and streamUrl() is set.

Throws: PlanError (402 FeatureRequiresPlan) when the org lacks the desktop entitlement; also AuthError, ConcurrencyLimitError, NoCapacityError, or GatewayError.

Example:

solari::ClientOptions co;
co.apiKey = "slr_live_...";
co.baseUrl = "https://api.getsolari.com";
solari::Client client(co);

solari::CreateSandboxOptions o;
o.template_ = "office";   // trailing underscore: "template" is a C++ keyword
o.cpu = 2;
o.memMb = 4096;

auto vm = client.createDesktop(o);
vm->connect();

std::cout << vm->kind() << "\n";              // "desktop"
std::cout << *vm->streamUrl() << "\n";        // wss://.../stream/<id>

// Core namespaces work on a VM exactly as on a sandbox.
solari::CommandOptions ro;
ro.args = {"getactivewindow"};
auto r = vm->commands.run("xdotool", ro);
std::cout << r.stdout_ << "\n";

vm->kill();
create() is unchanged
create() still sends SandboxKind::Sandbox. Existing code keeps its behaviour.

connect()

std::shared_ptr<Sandbox> connect(const std::string& sandboxId)

Re-attaches to a running VM by id. Reads its view, then derives both the control URL and the stream URL from the gateway origin.

Parameters:

  • sandboxId const std::string&: the session id.

Returns: std::shared_ptr<Sandbox>. streamUrl() holds a value when the session is a desktop, and is std::nullopt otherwise.

Throws: GatewayError if the id is unknown.

Example:

auto vm = client.connect("vm_abc123");
if (auto url = vm->streamUrl()) {
  std::cout << "live view: " << *url << "\n";
}
The stream URL is derived by design
SandboxView has no streamUrl field because the gateway’s toSandboxView never emits one. So connect() builds it as wsOrigin() + "/stream/" + id, the same way controlUrl has always been derived, and the result is identical to what createDesktop() parses off the wire. This is intentional: adding a field the wire never populates would always be empty. Do not "fix" it.

Sandbox

A live session, GUI or headless. Construct via createDesktop() or connect(); never directly.

Properties

kind()

const std::string& kind() const

The session flavour: "desktop" or "sandbox".

Returns: const std::string&

Example:

if (vm->kind() == "desktop") { /* has a display */ }

streamUrl()

const std::optional<std::string>& streamUrl() const

The wss:// RFB URL of the live view. Hand it to a noVNC client to render or embed the screen.

Returns: const std::optional<std::string>&: engaged for a desktop, std::nullopt for a sandbox. A headless sandbox has no display, so nullopt is the correct answer, not a gap.

Example:

const auto& url = vm->streamUrl();
if (!url) throw std::runtime_error("not a desktop");

Inherited members

Everything on the Sandbox page works unchanged on a VM: connect(), close(), kill(), pause(), resume(), id(), controlUrl(), expiresAt(), connected(), and the commands, files, code, and git members.

What you cannot do

There is no C++ GUI surface. These have no binding and no planned one on this page:

  • mouse.*, keyboard.*: pointer and key input.
  • screenshot(): capture the screen as bytes.
  • display.*, clipboard.*, open(): resolution, cursor, guest clipboard, launching apps.
  • record.*: in-guest capture (server-side recording via CreateSandboxOptions::record is separate and does work — see CreateSandboxOptions).
pause()/resume() DO work on a VM
Unlike the items above, session-level pause()/resume() are fully bound and work identically on a desktop: pause() snapshots RAM+disk and frees the host slot; resume() brings it back on a fresh slot and reopens the control channel. They are GUI-agnostic lifecycle calls, not GUI control, which is why they are documented on the Sandbox page rather than here.

To drive the GUI, use the TypeScript SDK (the complete reference surface) or the VM HTTP API. A split-process design works well: drive the VM from a language that has the binding, and keep C++ for the compute-heavy side against the same session id.