Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a06def-6490-7033-8448-2eab2d12ed44
245 lines
6.8 KiB
Python
245 lines
6.8 KiB
Python
"""Pydantic schemas for profiles, extensions, and sandbox lifecycle."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
from enum import StrEnum
|
|
from typing import Any, Literal
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class ActorType(StrEnum):
|
|
ADM = "adm"
|
|
AGT = "agt"
|
|
ATM = "atm"
|
|
|
|
|
|
class SandboxState(StrEnum):
|
|
REQUESTED = "requested"
|
|
PROVISIONING = "provisioning"
|
|
READY = "ready"
|
|
ACTIVE = "active"
|
|
EXPIRED = "expired"
|
|
FAILED = "failed"
|
|
DESTROYING = "destroying"
|
|
DESTROYED = "destroyed"
|
|
|
|
|
|
class RouteStrategy(StrEnum):
|
|
PREFER_SELF_HOSTED = "prefer-self-hosted"
|
|
LOWEST_COST = "lowest-cost"
|
|
LOWEST_LATENCY = "lowest-latency"
|
|
EXPLICIT = "explicit"
|
|
|
|
|
|
class Consumer(BaseModel):
|
|
actor: ActorType
|
|
project: str
|
|
session_id: str | None = None
|
|
run_id: str | None = None
|
|
|
|
|
|
class IsolationSpec(BaseModel):
|
|
level: Literal["container", "microvm", "policy", "process"] = "container"
|
|
|
|
|
|
class NetworkSpec(BaseModel):
|
|
default: Literal["deny", "allow"] = "deny"
|
|
egress: list[str] = Field(default_factory=list)
|
|
|
|
|
|
class WorkspaceSpec(BaseModel):
|
|
mode: Literal["mirror", "remote-canonical"] = "remote-canonical"
|
|
access: Literal["none", "ro", "rw"] = "rw"
|
|
|
|
|
|
class TtlSpec(BaseModel):
|
|
default: str = "4h"
|
|
max: str = "24h"
|
|
idle_reap: str | None = None
|
|
|
|
|
|
class ResourceSpec(BaseModel):
|
|
cpu: str | None = None
|
|
memory_mb: int | None = None
|
|
|
|
|
|
class SetupSpec(BaseModel):
|
|
instructions: str = ""
|
|
secret_refs: list[str] = Field(default_factory=list)
|
|
|
|
|
|
class PlacementSpec(BaseModel):
|
|
prefer: list[str] = Field(default_factory=list)
|
|
fallback: list[str] = Field(default_factory=list)
|
|
|
|
|
|
class ReachabilitySpec(BaseModel):
|
|
tunnel: str = "ops-bridge"
|
|
identity: str = "ops-warden"
|
|
|
|
|
|
class ProfileMetadata(BaseModel):
|
|
cost_class: Literal["self-hosted", "saas-metered"] = "self-hosted"
|
|
latency_class: str = "standard"
|
|
observability: Literal["none", "canary"] = "none"
|
|
|
|
|
|
class RouteSpec(BaseModel):
|
|
strategy: RouteStrategy = RouteStrategy.EXPLICIT
|
|
extensions: list[str] = Field(default_factory=list)
|
|
max_cost_per_hour_usd: float | None = None
|
|
|
|
|
|
class MeterQuote(BaseModel):
|
|
extension_id: str
|
|
estimated_usd: float
|
|
unit: Literal["per_hour", "per_session"] = "per_hour"
|
|
duration_s: int = 3600
|
|
|
|
|
|
class MeterRecord(BaseModel):
|
|
pricing_model: Literal["self-hosted", "metered"] = "self-hosted"
|
|
estimate_usd: float | None = None
|
|
actual_usd: float | None = None
|
|
duration_s: float | None = None
|
|
currency: str = "USD"
|
|
|
|
|
|
class Profile(BaseModel):
|
|
id: str
|
|
version: str
|
|
extension: str
|
|
route: RouteSpec | None = None
|
|
isolation: IsolationSpec = Field(default_factory=IsolationSpec)
|
|
network: NetworkSpec = Field(default_factory=NetworkSpec)
|
|
workspace: WorkspaceSpec = Field(default_factory=WorkspaceSpec)
|
|
scope_default: Literal["session", "agent", "shared"] = "session"
|
|
ttl: TtlSpec = Field(default_factory=TtlSpec)
|
|
resources: ResourceSpec = Field(default_factory=ResourceSpec)
|
|
setup: SetupSpec = Field(default_factory=SetupSpec)
|
|
placement: PlacementSpec = Field(default_factory=PlacementSpec)
|
|
reachability: ReachabilitySpec = Field(default_factory=ReachabilitySpec)
|
|
metadata: ProfileMetadata = Field(default_factory=ProfileMetadata)
|
|
|
|
|
|
class ExtensionCapabilities(BaseModel):
|
|
isolation_levels: list[str] = Field(default_factory=lambda: ["container"])
|
|
regions: list[str] = Field(default_factory=list)
|
|
persistence: bool = False
|
|
pricing_model: Literal["self-hosted", "metered"] = "self-hosted"
|
|
|
|
|
|
class Extension(BaseModel):
|
|
id: str
|
|
title: str
|
|
description: str = ""
|
|
handler: str
|
|
capabilities: ExtensionCapabilities = Field(default_factory=ExtensionCapabilities)
|
|
config: dict[str, Any] = Field(default_factory=dict)
|
|
|
|
|
|
class SandboxCreateRequest(BaseModel):
|
|
profile: str
|
|
inputs: dict[str, str] = Field(default_factory=dict)
|
|
consumer: Consumer
|
|
ttl: str | None = None
|
|
|
|
|
|
class SandboxExecRequest(BaseModel):
|
|
"""A command grant bound to the consumer recorded at sandbox creation."""
|
|
|
|
command: list[str] = Field(min_length=1, max_length=256)
|
|
consumer: Consumer
|
|
credential_route_refs: list[str] = Field(default_factory=list, max_length=32)
|
|
stdin_text: str | None = Field(default=None, max_length=1_000_000)
|
|
timeout_seconds: int = Field(default=900, ge=1, le=3600)
|
|
max_output_bytes: int = Field(default=262_144, ge=1, le=1_048_576)
|
|
|
|
|
|
class SandboxExecResult(BaseModel):
|
|
sandbox_id: str
|
|
profile_id: str
|
|
extension_id: str
|
|
consumer: Consumer
|
|
command_name: str
|
|
exit_code: int
|
|
timed_out: bool = False
|
|
stdout: str = ""
|
|
stderr: str = ""
|
|
output_truncated: bool = False
|
|
duration_seconds: float
|
|
workspace_dir: str
|
|
network_default: Literal["deny", "allow"]
|
|
network_egress: list[str] = Field(default_factory=list)
|
|
credential_route_refs: list[str] = Field(default_factory=list)
|
|
started_at: datetime
|
|
completed_at: datetime
|
|
|
|
|
|
class Reachability(BaseModel):
|
|
ssh: str | None = None
|
|
remote_dir: str | None = None
|
|
compose_project: str | None = None
|
|
host: str | None = None
|
|
endpoint: str | None = None
|
|
tunnel: str | None = None
|
|
tunnel_via: str | None = None
|
|
identity: str | None = None
|
|
# Local (no-SSH-hop) descriptor — populated for same-host extensions
|
|
# like ext.bwrap. A consumer execs into the sandbox directly
|
|
# (e.g. `nsenter --target <pid> ...`) rather than over SSH.
|
|
pid: str | None = None
|
|
workspace_dir: str | None = None
|
|
|
|
|
|
class SandboxStatus(BaseModel):
|
|
sandbox_id: str
|
|
profile_id: str
|
|
extension_id: str
|
|
state: SandboxState
|
|
consumer: Consumer
|
|
host: str | None = None
|
|
reachability: Reachability | None = None
|
|
inputs: dict[str, str] = Field(default_factory=dict)
|
|
ttl: str | None = None
|
|
expires_at: datetime | None = None
|
|
error: str | None = None
|
|
meter: MeterRecord | None = None
|
|
telemetry: dict | None = None # IntrospectionReport JSON when canary
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
ready_at: datetime | None = None
|
|
destroyed_at: datetime | None = None
|
|
|
|
|
|
class ExtendTtlRequest(BaseModel):
|
|
duration: str
|
|
|
|
|
|
class ExpireActionResult(BaseModel):
|
|
sandbox_id: str
|
|
reason: Literal["ttl", "idle"]
|
|
action: Literal["dry-run", "expired", "destroyed", "failed"]
|
|
error: str | None = None
|
|
|
|
|
|
class SnapshotRestoreRequest(BaseModel):
|
|
host: str | None = None
|
|
consumer: Consumer | None = None
|
|
|
|
|
|
class SnapshotRecord(BaseModel):
|
|
snapshot_id: str
|
|
sandbox_id: str
|
|
profile_id: str
|
|
extension_id: str
|
|
host: str
|
|
artifact_path: str = ""
|
|
handle: dict[str, str] = Field(default_factory=dict)
|
|
inputs: dict[str, str] = Field(default_factory=dict)
|
|
consumer: Consumer | None = None
|
|
name: str | None = None
|
|
size_bytes: int | None = None
|
|
created_at: datetime
|