Saltar a contenido

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.

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).

text: str | None property

text/plain del execute_result (la última expresión de la celda).

to_json() -> str

El documento de E2B: logs va anidado como la cadena JSON de Logs.to_json(), no como objeto.

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.