Files
2026-08-21 16:00:13 +08:00

144 lines
3.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""沙箱执行请求 / 响应模型,与 Rust 端 JSON 契约对齐。"""
from __future__ import annotations
from pydantic import BaseModel, ConfigDict, Field, model_validator
class ExecRequest(BaseModel):
"""``POST /v1/exec`` 请求体。``argv``(命令式)与 ``code``+``language``(代码片段式)二选一。"""
model_config = ConfigDict(extra="forbid")
argv: list[str] | None = Field(None, min_length=1)
code: str | None = None
language: str | None = None # code 模式语言,默认 python
stdin: str | None = None
timeout_ms: int | None = None
workdir: str | None = None
env: dict[str, str] = Field(default_factory=dict)
max_output_bytes: int | None = None
trace_id: str | None = None
@model_validator(mode="after")
def _enforce_argv_code_mutex(self) -> ExecRequest:
has_argv = self.argv is not None
has_code = self.code is not None
if has_argv == has_code:
raise ValueError("必须且只能指定 argv 或 code 之一")
if has_code and self.language is None:
self.language = "python"
return self
class ExecResponse(BaseModel):
"""``POST /v1/exec`` 响应体。"""
model_config = ConfigDict(extra="ignore")
ok: bool
exit_code: int | None = None
stdout: str = ""
stderr: str = ""
duration_ms: int = 0
timeout: bool = False
cancelled: bool = False
truncated: bool = False
trace_id: str = ""
isolation_mode: str = "process" # 实际生效的隔离模式(process/container)
class CancelResponse(BaseModel):
"""``POST /v1/cancel`` 响应体。"""
model_config = ConfigDict(extra="ignore")
cancelled: bool
trace_id: str
# ---- 文件 IO(不经 shell,二进制安全;与 Rust fileio.rs 契约对齐) ----
class FileReadRequest(BaseModel):
"""``POST /v1/file/read`` 请求。``path`` 为 base 内相对路径。"""
model_config = ConfigDict(extra="forbid")
path: str
offset: int | None = None
limit: int | None = None
class FileReadResponse(BaseModel):
"""``POST /v1/file/read`` 响应。``content_b64`` 为 base64url-no-pad(二进制安全)。"""
model_config = ConfigDict(extra="ignore")
content_b64: str
size: int
offset: int
returned: int
truncated: bool
class FileWriteRequest(BaseModel):
"""``POST /v1/file/write`` 请求。``content_b64`` 为 base64url-no-pad。"""
model_config = ConfigDict(extra="forbid")
path: str
content_b64: str
class FileWriteResponse(BaseModel):
"""``POST /v1/file/write`` 响应。"""
model_config = ConfigDict(extra="ignore")
bytes_written: int
class FileListRequest(BaseModel):
"""``POST /v1/file/list`` 请求。``path`` 默认 base 根(``.``)。"""
model_config = ConfigDict(extra="forbid")
path: str = "."
class DirEntry(BaseModel):
"""目录条目。"""
model_config = ConfigDict(extra="ignore")
name: str
kind: str # "file" | "dir" | "other"
size: int
class FileListResponse(BaseModel):
"""``POST /v1/file/list`` 响应(条目按名字排序)。"""
model_config = ConfigDict(extra="ignore")
entries: list[DirEntry]
class FileStatRequest(BaseModel):
"""``POST /v1/file/stat`` 请求。"""
model_config = ConfigDict(extra="forbid")
path: str
class FileStatResponse(BaseModel):
"""``POST /v1/file/stat`` 响应。"""
model_config = ConfigDict(extra="ignore")
kind: str
size: int
modified_unix: int