Official Elixir SDK for MIOSA — the AI cloud platform for sandboxes, computers, deployments, and managed data.

Hex version Hex downloads License: MIT Docs

Elixir 1.15+. HTTP transport via Req, JSON via Jason.

Install

def deps do
  [
    {:miosa, "~> 0.3"}
  ]
end

Then run mix deps.get.

Quickstart

client = Miosa.client("msk_live_...")

{:ok, computer} = Miosa.Computers.create(client, %{
  name: "my-build",
  template_type: "miosa-sandbox",
  size: "small"
})

{:ok, result} = Miosa.Exec.bash(client, computer.id, "echo 'hello from miosa'")
IO.puts(result.output)  # hello from miosa

{:ok, _} = Miosa.Files.write_file(client, computer.id, "/workspace/app.exs", ~s(IO.puts("hi")))
{:ok, text} = Miosa.Files.read_file(client, computer.id, "/workspace/app.exs")

:ok = Miosa.Computers.delete(client, computer.id)

What's included

ModuleDescription
Miosa.ComputersCreate, list, get, delete computers
Miosa.ComputerBound handle — start, stop, restart, wait
Miosa.Execbash/4 and python/4 execution inside VMs
Miosa.FilesUpload, download, write, read, list, stat, mkdir
Miosa.ServicesBackground process management (start/stop/restart/logs)
Miosa.DesktopScreenshot, click, type, key, scroll
Miosa.EventsSSE event streaming per computer
Miosa.CheckpointsSnapshot and restore computer state
Miosa.CreditsCredit balance and transaction history
Miosa.OpenComputersBYOC host management
Miosa.WorkspacesWorkspace CRUD
Miosa.AdminAdmin-scoped operations

Exec

{:ok, result} = Miosa.Exec.bash(client, computer.id, "ls -la /workspace",
  timeout: 10_000,
  working_dir: "/workspace",
  env: %{"DEBUG" => "1"}
)
IO.puts(result.stdout)
IO.puts("exit: #{result.exit_code}")

{:ok, py} = Miosa.Exec.python(client, computer.id, """
  import json
  print(json.dumps({"status": "ok"}))
""")
IO.puts(py.output)

File operations

# Write / read
{:ok, _} = Miosa.Files.write_file(client, id, "/workspace/app.py", "print('hi')")
{:ok, text} = Miosa.Files.read_file(client, id, "/workspace/app.py")

# Upload binary
{:ok, _} = Miosa.Files.upload(client, id, "./local.txt", "/workspace/remote.txt")

# List / stat / mkdir / rename / delete
{:ok, entries} = Miosa.Files.list(client, id, "/workspace")
{:ok, stat}    = Miosa.Files.stat(client, id, "/workspace/app.py")
{:ok, _}       = Miosa.Files.mkdir(client, id, "/workspace/output")
{:ok, _}       = Miosa.Files.rename(client, id, "/workspace/old.py", "/workspace/new.py")
:ok            = Miosa.Files.delete(client, id, "/workspace/old.py")

Desktop control

{:ok, png} = Miosa.Desktop.screenshot(client, computer.id)
File.write!("screen.png", png)

:ok = Miosa.Desktop.click(client, computer.id, 640, 400)
:ok = Miosa.Desktop.double_click(client, computer.id, 640, 400)
:ok = Miosa.Desktop.right_click(client, computer.id, 640, 400)
:ok = Miosa.Desktop.type(client, computer.id, "hello world")
:ok = Miosa.Desktop.key(client, computer.id, "Return")
:ok = Miosa.Desktop.key(client, computer.id, "ctrl+c")
:ok = Miosa.Desktop.scroll(client, computer.id, 640, 400, "down", 3)
:ok = Miosa.Desktop.drag(client, computer.id, 100, 100, 400, 400)

{:ok, windows} = Miosa.Desktop.windows(client, computer.id)
{:ok, cursor}  = Miosa.Desktop.cursor(client, computer.id)
:ok            = Miosa.Desktop.launch(client, computer.id, "firefox")

SSE event streaming

:ok = Miosa.Events.stream(client, computer.id, fn event ->
  IO.inspect({event.type, event.data})
end)

OTP / Supervisor integration

children = [
  {Miosa.Client, api_key: System.fetch_env!("MIOSA_API_KEY")}
]

Supervisor.start_link(children, strategy: :one_for_one)

Phoenix / LiveView integration

defmodule MyAppWeb.SandboxLive do
  use Phoenix.LiveView

  def mount(_params, _session, socket) do
    client = Miosa.client(System.fetch_env!("MIOSA_API_KEY"))
    {:ok, assign(socket, client: client, output: nil)}
  end

  def handle_event("run", %{"cmd" => cmd}, socket) do
    {:ok, result} = Miosa.Exec.bash(
      socket.assigns.client,
      socket.assigns.computer_id,
      cmd
    )
    {:noreply, assign(socket, output: result.output)}
  end
end

White-label / multi-tenant

{:ok, computer} = Miosa.Computers.create(client, %{
  name: "customer-build",
  template_type: "miosa-sandbox",
  metadata: %{
    "external_workspace_id" => "acme-corp",
    "external_user_id"      => "user-99"
  }
})

Error handling

All functions return {:ok, result} or {:error, %Miosa.Error{}}:

case Miosa.Computers.get(client, "cmp_doesnt_exist") do
  {:ok, computer} ->
    computer

  {:error, %Miosa.Error{status: 404}} ->
    IO.puts("not found")

  {:error, %Miosa.Error{status: 429, message: msg}} ->
    IO.puts("rate limited: #{msg}")

  {:error, %Miosa.Error{message: msg}} ->
    IO.puts("error: #{msg}")
end

Miosa.Error fields: :message, :status, :code, :body.

Configuration

client = Miosa.client("msk_live_...",
  base_url:        "https://api.miosa.ai/api/v1",
  timeout:         30_000,
  receive_timeout: 60_000,
  retry:           false
)
OptionDefault
:api_keyrequired — pass explicitly; env var not auto-read
:base_urlhttps://api.miosa.ai/api/v1
:timeout30_000 ms
:receive_timeout60_000 ms
:retryfalse

License

MIT