Modelos¶
Los tipos de datos que devuelven y aceptan Sandbox y sus subclientes.
Todos se importan desde rayito.
Ciclo de vida¶
IdlePolicy(max_idle_seconds: int = 300, suspended_duration_seconds: int | None = None, auto_resume: bool = True)
dataclass
¶
Espejo de idlePolicy de run-microvm.
suspended_duration_seconds=None se resuelve en create() como
timeout - max_idle_seconds; 0 significa terminar al suspender.
Un ciclo suspend/resume cuesta ≈ $0,0049 a 2 GB (0,92 GB de snapshot
escritos y leídos, SPEC.md §7) ≈ 140 s de cómputo, así que un
max_idle_seconds menor que ≈ 150 s no ahorra dinero; el mínimo que
acepta la API es 60.
SandboxLifecycle(phase: LifecyclePhaseName, deadline: datetime | None, cap: datetime | None, timeout_seconds: float, on_timeout: TimeoutActionName | None, auto_resume: bool, extensions: int)
dataclass
¶
El plazo lógico que impone rayd, tal como lo reporta Health.
phase es unmanaged cuando el sandbox se creó sin max_lifetime ni
on_timeout (su vida es la de la plataforma), active con el
plazo corriendo, resume_grace durante los 30 s tras reanudarse pasado
el plazo (esperando a connect()) y expired con el plazo vencido.
deadline y cap son instantes de pared (None en unmanaged); cap
es max_lifetime - 60 s desde el arranque y el plazo nunca lo pasa.
extensions cuenta los SetTimeout que movieron el plazo en este
arranque del agente.
SandboxInfo(sandbox_id: str, state: str, endpoint: str, template: str, template_version: str, started_at: datetime, maximum_duration_seconds: int, terminated_at: datetime | None = None, state_reason: str | None = None, idle: IdlePolicy | None = None, execution_role_arn: str | None = None, metadata: dict[str, str] | None = None, ingress: tuple[str, ...] = (), egress: tuple[str, ...] = (), lifecycle: SandboxLifecycle | None = None, agent_version: str | None = None, cpu_count: int | None = None, memory_mb: int | None = None, size: str | None = None, baseline_memory_mib: int | None = None, baseline_cpu: int | None = None)
dataclass
¶
Lo que devuelve get-microvm (y run-microvm), normalizado.
endpoint es siempre el hostname pelado; endpoint_url le antepone
https://. template es el ARN de la imagen. metadata es None
cuando no se leyó del agente (get-microvm no lo conoce) y {} cuando
se leyó y estaba vacío. ingress/egress son los ARNs de conectores
que run-microvm/get-microvm reportan (ingressNetworkConnectors /
egressNetworkConnectors), vacíos si la respuesta no los trae.
lifecycle es el último plazo lógico leído del agente (None si no se
leyó o si la imagen es anterior a 0.3.0): expires_at es ese plazo cuando
el sandbox lo tiene y platform_expires_at siempre el tope de la
plataforma (started_at + maximum_duration_seconds).
agent_version, cpu_count y memory_mb son la vista del guest que
devuelve Health (None si no se leyó del agente o no se conoce):
cpu_count son las CPUs que rayd puede usar y memory_mb el
MemTotal del guest en MiB, no el minimumMemoryInMiB de la imagen.
size, baseline_memory_mib y baseline_cpu sólo se rellenan cuando
create(size=...) se usó (m15-sizes-catalog): size es el sufijo
resuelto ("4gb"), baseline_memory_mib el minimumMemoryInMiB
publicado de la imagen lanzada y baseline_cpu los vCPU del guest para
ese minimumMemoryInMiB (RES-2/Q88, _sizing.MIB_PER_VCPU_Q88, medido
exactamente para los cinco tamaños del catálogo). El guest real puede
ver hasta 4x baseline_memory_mib en memory_mb (también Q88).
timed_out: bool
property
¶
rayd salió por el plazo lógico en modo kill (código 124 en el
stateReason de get-microvm, AWS_API_NOTES.md Q63).
SandboxListItem(sandbox_id: str, state: str, template: str, template_version: str, started_at: datetime, metadata: dict[str, str] | None = None)
dataclass
¶
Un item de list-microvms: no trae endpoint ni stateReason.
metadata sólo viene relleno en Sandbox.list(metadata=...), que lo lee
del agente sandbox a sandbox; None significa que no se leyó.
MicrovmListPage(items: tuple[SandboxListItem, ...], next_token: str | None = None)
dataclass
¶
Una página cruda de list-microvms: todos sus items, sin filtrar por
estado, y el nextToken de AWS (None en la última).
LaunchOptions(template: str, template_version: str | None, timeout: int, idle: IdlePolicy | None, envs: dict[str, str] | None, metadata: dict[str, str] | None, cpu_time_limit: int | None, execution_role_arn: str | None, allowed_ports: tuple[Any, ...] | None, ingress: tuple[str, ...] | None, egress: tuple[str, ...] | None, logging: Any, access_token: str | None, ready_timeout: float, request_timeout: float, reconnect_timeout: float, keep_on_failure: bool, control_plane: Any, transport: Any, max_lifetime: int | None = None, on_timeout: TimeoutActionName | None = None, network: NetworkPolicy | None = None, index: DynamoDbIndex | None = None, features: FeatureOptions | None = None, size: ResolvedSize | None = None)
dataclass
¶
Lo que create() recibió, guardado en la instancia para que
reincarnate() lance el sandbox siguiente igual (menos el token de acceso
salvo que fuera explícito). template es el ARN ya resuelto.
access_token y los valores de envs son secretos y se redactan en
repr/str: sólo se muestra si hay token y cuántas variables hay.
Los secrets= no viajan aquí: reincarnate() relanza con los que el
handle tenga en ese momento (sólo referencias, nunca valores).
index es el DynamoDbIndex del create() (o None): el sucesor
escribe su propia fila y sigue apareciendo en el listado con índice.
SandboxHealth(agent_ready: bool, kernel_ready: bool, agent_version: str, uptime_ms: int, sandbox_id: str, resume_generation: int, clock_offset_ms: int, kernel_state_lost: bool, metadata: dict[str, str] = dict(), imds_blocked: bool = False, hook_anomalies: int = 0, lifecycle: SandboxLifecycle | None = None, egress_enforcement: EgressEnforcement = EgressEnforcement.UNSPECIFIED, cpu_count: int = 0, memory_total_bytes: int = 0)
dataclass
¶
HealthService.Health tal como lo expone get_health().
resume_generation cuenta los /resume aceptados desde el arranque del
agente; clock_offset_ms es wall_delta - monotonic_delta entre el
último /suspend y su /resume (0 si no hubo); kernel_state_lost es
True cuando algún kernel no respondió a la sonda de /resume y fue
reiniciado (su estado se perdió). uptime_ms incluye el tiempo suspendido.
metadata es el mapa del runHookPayload tal cual lo guardó rayd
(vacío antes de /run, si el payload no lo traía o si la imagen es
anterior a M6). imds_blocked es True sólo cuando rayd instaló y
verificó la regla de iptables que bloquea IMDS para uid 1000 (imagen
rayito-base-caps; False en la imagen por defecto, fail-open).
hook_anomalies cuenta las llamadas anómalas a los hooks en este
arranque (/run repetido, /suspend//resume rechazados por el
limitador, recuperaciones de un /suspend que nunca congeló la VM):
distinto de 0 significa que alguien posee un token allPorts de la VM.
lifecycle es el plazo lógico; None en un agente anterior
a 0.3.0, que no impone ningún timeout. egress_enforcement es la política
de egress que rayd verificó en el guest; UNSPECIFIED en un
agente anterior a 0.3.0. cpu_count y memory_total_bytes son la vista del
guest (CPUs que rayd puede usar y MemTotal en bytes), 0 en un agente
anterior a 0.3.0.
SandboxMetrics(cpu_used_pct: float, mem_used_bytes: int, mem_total_bytes: int, disk_used_bytes: int, disk_total_bytes: int, cpu_count: int, timestamp: datetime, mem_cache_bytes: int = 0)
dataclass
¶
Una muestra procfs del MicroVM: la instantánea de get_metrics() o un
punto de get_metrics_history(). mem_cache_bytes es el Cached de
/proc/meminfo (page cache), 0 en un agente anterior a 0.3.0.
HostAccess
¶
Bases: str
Resultado de get_host(port).
Es un str con el hostname del MicroVM para que f"https://{host}" siga
funcionando como en E2B, y además expone url, port y headers. Las
cabeceras se leen en cada acceso para reflejar el JWE renovado por el
refresher; nunca incluyen x-aws-proxy-force-h2 (eso es sólo para gRPC).
ListOrder es el alias Literal["asc", "desc"] del order= de
Sandbox.list() y Sandbox.paginate().
Comandos y terminal¶
CommandResult(stdout: str, stderr: str, exit_code: int, error: str | None = None, truncated: bool = False)
dataclass
¶
Salida de un comando que terminó con exit code 0.
Un exit code distinto de cero llega como CommandExitException, que lleva
los mismos campos; error queda reservado para futuros estados sin
excepción y es None en M2. truncated es True cuando stdout o
stderr superaron max_output_bytes y sólo conservan su final.
ProcessInfo(pid: int, cmd: str, args: tuple[str, ...] = (), envs: dict[str, str] = dict(), cwd: str | None = None, tag: str | None = None, kind: ProcessKindName = 'process')
dataclass
¶
Un item de ProcessService.List: cmd/args son los del wrapper
(/bin/bash -l -c <cmd>), no el comando que escribió el usuario.
PtySize(cols: int = DEFAULT_PTY_COLS, rows: int = DEFAULT_PTY_ROWS)
dataclass
¶
Tamaño de una terminal (PtyService PtySize): 1 <= cols, rows <= 4096.
Ficheros¶
EntryInfo(name: str, type: FileType | None, path: str, size: int, mode: int, permissions: str, owner: str, group: str, modified_time: datetime, symlink_target: str | None = None, metadata: Mapping[str, str] = (lambda: frozen_mapping({}))())
dataclass
¶
EntryInfo de FilesystemService, sin seguir enlaces simbólicos.
type es None para lo que no es fichero regular, directorio ni symlink
(FIFO, socket, dispositivo). path es la ruta pedida normalizada, nunca
la canónica. permissions tiene la forma de ls -l (-rw-r--r--) y
mode son los bits st_mode & 0o7777. symlink_target sólo en symlinks.
metadata son los metadatos de files.write(metadata=) (xattrs
user.rayito.*, claves en minúsculas), de sólo lectura y vacíos si no
hay o si la imagen es anterior a 0.3.0.
FileType
¶
Bases: StrEnum
Tipo de una entrada del sistema de ficheros del sandbox.
FilesystemEvent(name: str, type: FilesystemEventType, entry: EntryInfo | None = None)
dataclass
¶
Un evento de watch_dir: name es relativo al directorio observado
(sub/b.txt en modo recursivo) y entry sólo llega con include_entry
en CREATE/WRITE/CHMOD.
FilesystemEventType
¶
Bases: StrEnum
Tipos de evento de watch_dir (misma tabla que E2B).
WriteEntry(path: str, data: str | bytes | IO[bytes] | IO[str], mode: int | None = None)
dataclass
¶
Un fichero de files.write_files: data se materializa en memoria.
S3Staging(bucket: str, prefix: str = TRANSFER_DEFAULT_PREFIX, region: str | None = None, max_expires_in: int = TRANSFER_DEFAULT_MAX_EXPIRES_IN_SECONDS, threshold_bytes: int = TRANSFER_DEFAULT_THRESHOLD_BYTES, multipart_threshold_bytes: int = TRANSFER_DEFAULT_MULTIPART_THRESHOLD_BYTES)
dataclass
¶
El bucket de transferencias de upload_url/download_url y de los
ficheros grandes. El SDK firma cada URL con las credenciales
del llamante; rayd nunca guarda ninguna.
region=None usa la región del sandbox y debe ser la del bucket.
max_expires_in topa la vida de las URLs de usuario (el techo real es
también la caducidad de tus credenciales). threshold_bytes es el
tamaño a partir del cual files.write/files.read van por S3 y
multipart_threshold_bytes el de una exportación multiparte. No hay
bucket por defecto: from_env() lee RAYITO_TRANSFER_BUCKET,
RAYITO_TRANSFER_PREFIX y RAYITO_TRANSFER_REGION.
from_env(environ: Mapping[str, str] | None = None) -> S3Staging | None
classmethod
¶
None cuando RAYITO_TRANSFER_BUCKET falta o está vacía; los
campos que no vienen del entorno conservan su valor por defecto.
DownloadLink
¶
Bases: SignedUrl
Resultado de files.download_url: una foto del fichero tomada al
llamar (size y sha256 de los bytes exportados), servida por S3 hasta
expires_at con Content-Disposition: attachment.
TransferStatus(transfer_id: str, direction: TransferDirectionName, phase: TransferPhaseName, bytes_done: int, bytes_total: int, probes: int, error_code: str | None = None, error_reason: str | None = None)
dataclass
¶
Una foto de GetTransfer: bytes_total es 0 hasta que la importación
ve el objeto; probes cuenta los sondeos del GET; error_code y
error_reason sólo en failed/cancelled.
Código¶
CodeContext(id: str, language: str, cwd: str)
dataclass
¶
Un contexto de CodeService: un kernel con su propio scope y cwd.
from_json(data: Mapping[str, str]) -> CodeContext
classmethod
¶
El inverso del diccionario de E2B (id, language, cwd); una
clave ausente es InvalidArgumentException que la nombra.
Execution(results: list[Result] = list(), logs: Logs = Logs(), error: ExecutionError | None = None, execution_count: int | None = None)
dataclass
¶
Resultado de run_code. Un error del kernel es dato (error), nunca
excepción; execution_count es el de Jupyter (None si el kernel no
llegó a empezar la celda).
Result(*, text: str | None = None, html: str | None = None, markdown: str | None = None, svg: str | None = None, png: str | None = None, jpeg: str | None = None, pdf: str | None = None, latex: str | None = None, javascript: str | None = None, json: Any = None, data: Any = None, chart: Chart | None = None, is_main_result: bool = False, extra: dict[str, str] = dict(), raw: dict[str, str] = dict())
dataclass
¶
Un mime bundle de Jupyter (display_data o execute_result).
Las imágenes (png, jpeg, pdf) son base64 tal cual llegan; json y
data son el documento parseado (o la cadena original si no era JSON
válido); chart es el Chart de e2b/chart. raw conserva cada mime
como cadena y extra los mime types sin campo propio (incluido
rayito/omitted cuando el sidecar descartó un valor de más de 8 MiB).
formats() -> list[str]
¶
Campos presentes, en el orden de RESULT_FORMAT_ORDER, y después
las claves de extra (ordenadas alfabéticamente al leerlas del proto,
porque el orden de un mapa protobuf no está garantizado).
Logs(stdout: list[str] = list(), stderr: list[str] = list())
dataclass
¶
Salida de una ejecución, un elemento por OutputChunk recibido.
OutputMessage(line: str, timestamp: int, error: bool = False)
dataclass
¶
Un OutputChunk de Execute: timestamp en ns Unix del sidecar y
error=True cuando vino por stderr. Un chunk no es una línea.
ExecutionError(name: str, value: str, traceback: str = '')
dataclass
¶
Error del kernel (ZeroDivisionError...) o sintético del agente
(ExecutionTimeout, KernelDied, KernelRestarted, ContextDestroyed,
ExecutionAborted, OutputTruncated); traceback son las líneas de
Jupyter unidas con "
", vacío en los sintéticos.
Red¶
NetworkPolicy(allow_out: tuple[str, ...] = (), deny_out: tuple[str, ...] = (), egress_proxy: EgressProxy | None = None)
dataclass
¶
Política de egress resuelta (selectores ya evaluados). Una entrada
permitida gana siempre a una denegada; sin deny_out ni egress_proxy
no restringe nada.
NetworkOptions
¶
Bases: TypedDict
network= como dict, con las claves de E2B.
EgressProxy(address: str, username: str | None = None, password: str | None = None)
dataclass
¶
Proxy SOCKS5 del operador (egress_proxy de E2B): address es
host:puerto o [IPv6]:puerto; las credenciales RFC 1929 sólo viajan
en UpdateNetwork y el repr nunca muestra la contraseña.
NetworkState(allow_out: tuple[str, ...], deny_out: tuple[str, ...], egress_proxy_configured: bool, enforcement: EgressEnforcement, local_proxy_port: int | None)
dataclass
¶
NetworkService.GetNetwork/UpdateNetwork: las listas tal como se
enviaron y cómo se aplican. Nunca incluye la dirección ni las
credenciales del proxy; local_proxy_port es None cuando el proxy
local de rayd no está corriendo.
EgressEnforcement
¶
Bases: StrEnum
Cómo aplica rayd la política de egress en el guest, tal
como lo publican Health.egress_enforcement y NetworkState.enforcement.
UNSPECIFIED es un agente anterior a 0.3.0 y cuenta como NONE: ninguna
política en el guest, sólo el conector de la plataforma.
NetworkSelectorContext(all_traffic: str = ALL_TRAFFIC, rules: Mapping[str, tuple[object, ...]] = empty_rules())
dataclass
¶
Lo que recibe un selector invocable de allow_out/deny_out, con los
nombres de atributo de E2B (ctx.all_traffic, ctx.rules). rules
siempre está vacío: Rayito no tiene transformaciones de peticiones.
ALL_TRAFFIC es la constante "0.0.0.0/0", como en E2B:
NetworkPolicy(deny_out=[ALL_TRAFFIC]) corta todo el egress salvo lo que
abra allow_out.
Persistencia¶
S3Prefix(bucket: str, prefix: str = 'rayito', name: str | None = None, region: str | None = None)
dataclass
¶
Dónde vive un HOME persistido: s3://bucket/prefix/name/.
prefix es la base del operador (la que acota la política IAM del
execution role, infra/iam.yaml); name identifica un home concreto y
Sandbox.create(persist=) lo rellena con el sandbox_id si viene vacío.
region sólo si el bucket no está en la región del sandbox. Se valida en
cliente con las mismas reglas que aplica rayd.
key_prefix: str
property
¶
prefix/name; InvalidArgumentException mientras name sea None.
CheckpointResult(bucket: str, key_prefix: str, files: int, bytes_read: int, archive_bytes: int, sha256: str, skipped: int, duration: float)
dataclass
¶
CheckpointDone: qué se archivó y dónde. sha256 es el del home.tar.gz.
CheckpointProgress(files_done: int, bytes_read: int, bytes_uploaded: int)
dataclass
¶
Un CheckpointProgress del agente (como mucho uno por segundo).
RestoreResult(bucket: str, key_prefix: str, files: int, bytes_written: int, archive_bytes: int, sha256: str, skipped: int, duration: float)
dataclass
¶
RestoreDone: qué se extrajo en el HOME del sandbox.
RestoreProgress(files_done: int, bytes_downloaded: int)
dataclass
¶
Gráficos¶
Los gráficos que run_code() extrae de matplotlib en Result.chart, con la
forma de e2b-code-interpreter.
Chart(*, type: ChartType, title: str | None = None, elements: list[Any] = list())
dataclass
¶
Base de todos los gráficos; elements depende del tipo.
ChartType
¶
Bases: StrEnum
ScaleType
¶
Bases: StrEnum
LineChart(*, type: ChartType = ChartType.LINE, title: str | None = None, elements: list[PointData] = list(), x_label: str | None = None, y_label: str | None = None, x_unit: str | None = None, y_unit: str | None = None, x_ticks: list[Coordinate] = list(), x_tick_labels: list[str] = list(), x_scale: ScaleType | None = None, y_ticks: list[Coordinate] = list(), y_tick_labels: list[str] = list(), y_scale: ScaleType | None = None)
dataclass
¶
Bases: PointChart
ScatterChart(*, type: ChartType = ChartType.SCATTER, title: str | None = None, elements: list[PointData] = list(), x_label: str | None = None, y_label: str | None = None, x_unit: str | None = None, y_unit: str | None = None, x_ticks: list[Coordinate] = list(), x_tick_labels: list[str] = list(), x_scale: ScaleType | None = None, y_ticks: list[Coordinate] = list(), y_tick_labels: list[str] = list(), y_scale: ScaleType | None = None)
dataclass
¶
Bases: PointChart
PointData(*, label: str | None = None, points: list[Point] = list())
dataclass
¶
BarChart(*, type: ChartType = ChartType.BAR, title: str | None = None, elements: list[BarData] = list(), x_label: str | None = None, y_label: str | None = None, x_unit: str | None = None, y_unit: str | None = None)
dataclass
¶
Bases: Chart2D
BarData(*, label: str | None = None, group: str | None = None, value: Coordinate | None = None)
dataclass
¶
PieChart(*, type: ChartType = ChartType.PIE, title: str | None = None, elements: list[PieData] = list())
dataclass
¶
Bases: Chart
PieData(*, label: str | None = None, angle: float | None = None, radius: float | None = None, autopct: Coordinate | None = None)
dataclass
¶
BoxAndWhiskerChart(*, type: ChartType = ChartType.BOX_AND_WHISKER, title: str | None = None, elements: list[BoxAndWhiskerData] = list(), x_label: str | None = None, y_label: str | None = None, x_unit: str | None = None, y_unit: str | None = None)
dataclass
¶
Bases: Chart2D
BoxAndWhiskerData(*, label: str | None = None, min: float | None = None, first_quartile: float | None = None, median: float | None = None, third_quartile: float | None = None, max: float | None = None, outliers: list[float] = list())
dataclass
¶
SuperChart(*, type: ChartType = ChartType.SUPERCHART, title: str | None = None, elements: list[Chart] = list())
dataclass
¶
Bases: Chart
Clientes y transporte¶
ClientSettings lo usa el shim de E2B (retries=, proxy=,
ConnectionConfig.set_integration); TransportSettings es el transport=
de create()/connect(). rayito.__version__ es la versión del paquete.
ClientSettings(retries: int | None = None, proxy: str | None = None, integration: str | None = None)
dataclass
¶
Opciones del cliente boto3 que el shim de E2B expone como retries=,
proxy= y ConnectionConfig.set_integration: retries son reintentos
(intentos totales = retries + 1), proxy una URL http:// para
botocore (nunca en el repr) e integration un sufijo del User-Agent.
Es hashable: cada combinación distinta tiene su propio plano compartido.
TransportSettings(channel_credentials: grpc.ChannelCredentials = grpc.ssl_channel_credentials(), port: int = ENDPOINT_TLS_PORT, options: tuple[tuple[str, int | str], ...] = CHANNEL_OPTIONS, extra_metadata: MetadataPairs = (), http_proxy: str | None = None)
dataclass
¶
Cómo se abre el canal al MicroVM. El default es TLS al 443 del proxy.
Los tests apuntan a un rayd falso en loopback con
grpc.local_channel_credentials(). extra_metadata viaja en cada RPC
detrás de las cabeceras reservadas (cada ProxyAuthPlugin construido
con estos ajustes lo recibe) y http_proxy (http://host:puerto, sólo
HTTP CONNECT) se pasa a grpc-core como grpc.http_proxy; ninguno de los
dos se loguea.