chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:47:58 +08:00
commit b16403ea71
789 changed files with 115226 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
# buf.gen.yaml defines a local generation template.
# For details, see https://buf.build/docs/configuration/v1/buf-gen-yaml
version: v1
plugins:
- plugin: es
out: ../../packages/js-sdk/src/envd
opt:
- target=ts
- plugin: connect-es
out: ../../packages/js-sdk/src/envd
opt:
- target=ts
managed:
enabled: true
optimize_for: SPEED
+15
View File
@@ -0,0 +1,15 @@
# buf.gen.yaml defines a local generation template.
# For details, see https://buf.build/docs/configuration/v1/buf-gen-yaml
version: v1
plugins:
- plugin: python
out: ../../packages/python-sdk/e2b/envd
opt:
- pyi_out=../../packages/python-sdk/e2b/envd
- name: connect-python
out: ../../packages/python-sdk/e2b/envd
path: protoc-gen-connect-python
managed:
enabled: true
optimize_for: SPEED
+312
View File
@@ -0,0 +1,312 @@
openapi: 3.0.0
info:
title: envd
version: 0.1.3
description: API for managing files' content and controlling envd
tags:
- name: files
paths:
/health:
get:
summary: Check the health of the service
responses:
'204':
description: The service is healthy
/metrics:
get:
summary: Get the stats of the service
security:
- AccessTokenAuth: []
- {}
responses:
'200':
description: The resource usage metrics of the service
content:
application/json:
schema:
$ref: '#/components/schemas/Metrics'
/init:
post:
summary: Set initial vars, ensure the time and metadata is synced with the host
security:
- AccessTokenAuth: []
- {}
requestBody:
content:
application/json:
schema:
type: object
properties:
hyperloopIP:
type: string
description: IP address of the hyperloop server to connect to
envVars:
$ref: '#/components/schemas/EnvVars'
accessToken:
type: string
description: Access token for secure access to envd service
timestamp:
type: string
format: date-time
description: The current timestamp in RFC3339 format
defaultUser:
type: string
description: The default user to use for operations
defaultWorkdir:
type: string
description: The default working directory to use for operations
responses:
'204':
description: Env vars set, the time and metadata is synced with the host
/envs:
get:
summary: Get the environment variables
security:
- AccessTokenAuth: []
- {}
responses:
'200':
description: Environment variables
content:
application/json:
schema:
$ref: '#/components/schemas/EnvVars'
/files:
get:
summary: Download a file
tags: [files]
security:
- AccessTokenAuth: []
- {}
parameters:
- $ref: '#/components/parameters/FilePath'
- $ref: '#/components/parameters/User'
- $ref: '#/components/parameters/Signature'
- $ref: '#/components/parameters/SignatureExpiration'
responses:
'200':
$ref: '#/components/responses/DownloadSuccess'
'401':
$ref: '#/components/responses/InvalidUser'
'400':
$ref: '#/components/responses/InvalidPath'
'404':
$ref: '#/components/responses/FileNotFound'
'500':
$ref: '#/components/responses/InternalServerError'
post:
summary: Upload a file and ensure the parent directories exist. If the file exists, it will be overwritten.
description: |
Any request header of the form `X-Metadata-<key>: <value>` is persisted
as a user-defined extended attribute on the uploaded file. The
`X-Metadata-` prefix is stripped and the remaining header name is
lowercased to form the metadata key; the resulting map is returned on
`EntryInfo` lookups (e.g. `Stat`, `ListDir`).
Each upload replaces the file's metadata with the keys provided in
that request: keys previously stored but absent from the new request
are removed, and an upload that sends no `X-Metadata-*` header clears
all existing metadata.
Both keys and values must be printable US-ASCII (bytes `0x20`-`0x7E`)
and are rejected with HTTP 400 otherwise. Each key is capped at 246
bytes (the Linux VFS xattr-name limit minus the namespace prefix), and
the combined size of all metadata on a file (keys plus values, with the
namespace prefix counted per key) is capped at 4096 bytes to stay within
the filesystem's per-inode xattr budget. Multiple files in a single
multipart upload receive the same metadata. If the same
`X-Metadata-<key>` header is sent more than once, only the first
value is used.
tags: [files]
security:
- AccessTokenAuth: []
- {}
parameters:
- $ref: '#/components/parameters/FilePath'
- $ref: '#/components/parameters/User'
- $ref: '#/components/parameters/Signature'
- $ref: '#/components/parameters/SignatureExpiration'
requestBody:
$ref: '#/components/requestBodies/File'
responses:
'200':
$ref: '#/components/responses/UploadSuccess'
'400':
$ref: '#/components/responses/InvalidPath'
'401':
$ref: '#/components/responses/InvalidUser'
'500':
$ref: '#/components/responses/InternalServerError'
'507':
$ref: '#/components/responses/NotEnoughDiskSpace'
components:
securitySchemes:
AccessTokenAuth:
type: apiKey
scheme: header
name: X-Access-Token
parameters:
FilePath:
name: path
in: query
required: false
description: Path to the file, URL encoded. Can be relative to user's home directory.
schema:
type: string
User:
name: username
in: query
required: false
description: User used for setting the owner, or resolving relative paths.
schema:
type: string
Signature:
name: signature
in: query
required: false
description: Signature used for file access permission verification.
schema:
type: string
SignatureExpiration:
name: signature_expiration
in: query
required: false
description: Signature expiration used for defining the expiration time of the signature.
schema:
type: integer
requestBodies:
File:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
format: binary
responses:
UploadSuccess:
description: The file was uploaded successfully.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/EntryInfo'
DownloadSuccess:
description: Entire file downloaded successfully.
content:
application/octet-stream:
schema:
type: string
format: binary
description: The file content
InvalidPath:
description: Invalid path
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
InternalServerError:
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
FileNotFound:
description: File not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
InvalidUser:
description: Invalid user
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
NotEnoughDiskSpace:
description: Not enough disk space
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
schemas:
Error:
required:
- message
- code
properties:
message:
type: string
description: Error message
code:
type: integer
description: Error code
EntryInfo:
required:
- path
- name
- type
properties:
path:
type: string
description: Path to the file
name:
type: string
description: Name of the file
type:
type: string
description: Type of the file
enum:
- file
metadata:
type: object
description: User-defined metadata stored as extended attributes on the file.
additionalProperties:
type: string
EnvVars:
type: object
description: Environment variables to set
additionalProperties:
type: string
Metrics:
type: object
description: Resource usage metrics
properties:
ts:
type: integer
format: int64
description: Unix timestamp in UTC for current sandbox time
cpu_count:
type: integer
description: Number of CPU cores
cpu_used_pct:
type: number
format: float
description: CPU usage percentage
mem_total:
type: integer
description: Total virtual memory in bytes
mem_used:
type: integer
description: Used virtual memory in bytes
disk_used:
type: integer
description: Used disk space in bytes
disk_total:
type: integer
description: Total disk space in bytes
+152
View File
@@ -0,0 +1,152 @@
syntax = "proto3";
package filesystem;
import "google/protobuf/timestamp.proto";
service Filesystem {
rpc Stat(StatRequest) returns (StatResponse);
rpc MakeDir(MakeDirRequest) returns (MakeDirResponse);
rpc Move(MoveRequest) returns (MoveResponse);
rpc ListDir(ListDirRequest) returns (ListDirResponse);
rpc Remove(RemoveRequest) returns (RemoveResponse);
rpc WatchDir(WatchDirRequest) returns (stream WatchDirResponse);
// Non-streaming versions of WatchDir
rpc CreateWatcher(CreateWatcherRequest) returns (CreateWatcherResponse);
rpc GetWatcherEvents(GetWatcherEventsRequest) returns (GetWatcherEventsResponse);
rpc RemoveWatcher(RemoveWatcherRequest) returns (RemoveWatcherResponse);
}
message MoveRequest {
string source = 1;
string destination = 2;
}
message MoveResponse {
EntryInfo entry = 1;
}
message MakeDirRequest {
string path = 1;
}
message MakeDirResponse {
EntryInfo entry = 1;
}
message RemoveRequest {
string path = 1;
}
message RemoveResponse {}
message StatRequest {
string path = 1;
}
message StatResponse {
EntryInfo entry = 1;
}
message EntryInfo {
string name = 1;
FileType type = 2;
string path = 3;
int64 size = 4;
uint32 mode = 5;
string permissions = 6;
string owner = 7;
string group = 8;
google.protobuf.Timestamp modified_time = 9;
// If the entry is a symlink, this field contains the target of the symlink.
optional string symlink_target = 10;
// User-defined metadata stored as extended attributes (xattrs) on the file.
// Keys live under the `user.e2b.` xattr namespace; the prefix is stripped here.
// Plain `user.*` xattrs written by other tooling are not reflected.
map<string, string> metadata = 11;
}
enum FileType {
FILE_TYPE_UNSPECIFIED = 0;
FILE_TYPE_FILE = 1;
FILE_TYPE_DIRECTORY = 2;
}
message ListDirRequest {
string path = 1;
uint32 depth = 2;
}
message ListDirResponse {
repeated EntryInfo entries = 1;
}
message WatchDirRequest {
string path = 1;
bool recursive = 2;
// If true, each FilesystemEvent includes the EntryInfo of the affected entry, when available.
bool include_entry = 3;
// If true, allows watching paths on network filesystem mounts (NFS, CIFS, SMB, FUSE).
// Events on network mounts may be unreliable or not delivered at all.
bool allow_network_mounts = 4;
}
message FilesystemEvent {
string name = 1;
EventType type = 2;
// Info of the entry that triggered the event. Only populated when include_entry
// was requested and the entry could be stat-ed (e.g. not set for remove/rename-away
// events, where the entry no longer exists at this path).
optional EntryInfo entry = 3;
}
message WatchDirResponse {
oneof event {
StartEvent start = 1;
FilesystemEvent filesystem = 2;
KeepAlive keepalive = 3;
}
message StartEvent {}
message KeepAlive {}
}
message CreateWatcherRequest {
string path = 1;
bool recursive = 2;
// If true, each FilesystemEvent includes the EntryInfo of the affected entry, when available.
bool include_entry = 3;
// If true, allows watching paths on network filesystem mounts (NFS, CIFS, SMB, FUSE).
// Events on network mounts may be unreliable or not delivered at all.
bool allow_network_mounts = 4;
}
message CreateWatcherResponse {
string watcher_id = 1;
}
message GetWatcherEventsRequest {
string watcher_id = 1;
}
message GetWatcherEventsResponse {
repeated FilesystemEvent events = 1;
}
message RemoveWatcherRequest {
string watcher_id = 1;
}
message RemoveWatcherResponse {}
enum EventType {
EVENT_TYPE_UNSPECIFIED = 0;
EVENT_TYPE_CREATE = 1;
EVENT_TYPE_WRITE = 2;
EVENT_TYPE_REMOVE = 3;
EVENT_TYPE_RENAME = 4;
EVENT_TYPE_CHMOD = 5;
}
+169
View File
@@ -0,0 +1,169 @@
syntax = "proto3";
package process;
service Process {
rpc List(ListRequest) returns (ListResponse);
rpc Connect(ConnectRequest) returns (stream ConnectResponse);
rpc Start(StartRequest) returns (stream StartResponse);
rpc Update(UpdateRequest) returns (UpdateResponse);
// Client input stream ensures ordering of messages
rpc StreamInput(stream StreamInputRequest) returns (StreamInputResponse);
rpc SendInput(SendInputRequest) returns (SendInputResponse);
rpc SendSignal(SendSignalRequest) returns (SendSignalResponse);
// Close stdin to signal EOF to the process.
// Only works for non-PTY processes. For PTY, send Ctrl+D (0x04) instead.
rpc CloseStdin(CloseStdinRequest) returns (CloseStdinResponse);
}
message PTY {
Size size = 1;
message Size {
uint32 cols = 1;
uint32 rows = 2;
}
}
message ProcessConfig {
string cmd = 1;
repeated string args = 2;
map<string, string> envs = 3;
optional string cwd = 4;
}
message ListRequest {}
message ProcessInfo {
ProcessConfig config = 1;
uint32 pid = 2;
optional string tag = 3;
}
message ListResponse {
repeated ProcessInfo processes = 1;
}
message StartRequest {
ProcessConfig process = 1;
optional PTY pty = 2;
optional string tag = 3;
optional bool stdin = 4;
}
message UpdateRequest {
ProcessSelector process = 1;
optional PTY pty = 2;
}
message UpdateResponse {}
message ProcessEvent {
oneof event {
StartEvent start = 1;
DataEvent data = 2;
EndEvent end = 3;
KeepAlive keepalive = 4;
}
message StartEvent {
uint32 pid = 1;
}
message DataEvent {
oneof output {
bytes stdout = 1;
bytes stderr = 2;
bytes pty = 3;
}
}
message EndEvent {
sint32 exit_code = 1;
bool exited = 2;
string status = 3;
optional string error = 4;
}
message KeepAlive {}
}
message StartResponse {
ProcessEvent event = 1;
}
message ConnectResponse {
ProcessEvent event = 1;
}
message SendInputRequest {
ProcessSelector process = 1;
ProcessInput input = 2;
}
message SendInputResponse {}
message ProcessInput {
oneof input {
bytes stdin = 1;
bytes pty = 2;
}
}
message StreamInputRequest {
oneof event {
StartEvent start = 1;
DataEvent data = 2;
KeepAlive keepalive = 3;
}
message StartEvent {
ProcessSelector process = 1;
}
message DataEvent {
ProcessInput input = 2;
}
message KeepAlive {}
}
message StreamInputResponse {}
enum Signal {
SIGNAL_UNSPECIFIED = 0;
SIGNAL_SIGTERM = 15;
SIGNAL_SIGKILL = 9;
}
message SendSignalRequest {
ProcessSelector process = 1;
Signal signal = 2;
}
message SendSignalResponse {}
message CloseStdinRequest {
ProcessSelector process = 1;
}
message CloseStdinResponse {}
message ConnectRequest {
ProcessSelector process = 1;
}
message ProcessSelector {
oneof selector {
uint32 pid = 1;
string tag = 2;
}
}
+3746
View File
File diff suppressed because it is too large Load Diff
+329
View File
@@ -0,0 +1,329 @@
openapi: 3.0.0
info:
version: 0.1.0
title: E2B API
security:
- VolumeJWT: []
components:
securitySchemes:
VolumeJWT:
type: http
scheme: bearer
bearerFormat: JWT
parameters:
volumeID:
name: volumeID
in: path
required: true
schema:
type: string
path:
name: path
in: query
required: true
schema:
type: string
responses:
'400':
description: Bad request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Authentication error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'409':
description: Conflict
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
schemas:
Error:
required:
- code
- message
properties:
code:
type: string
description: Error code
message:
type: string
description: Error message
VolumeEntryStat:
type: object
properties:
name:
type: string
type:
type: string
enum: [unknown, file, directory, symlink]
path:
type: string
size:
type: integer
format: int64
mode:
type: integer
format: uint32
uid:
type: integer
format: uint32
gid:
type: integer
format: uint32
atime:
type: string
format: date-time
mtime:
type: string
format: date-time
ctime:
type: string
format: date-time
target:
type: string
required:
- name
- type
- path
- size
- mode
- uid
- gid
- atime
- mtime
- ctime
VolumeDirectoryListing:
type: array
items:
$ref: '#/components/schemas/VolumeEntryStat'
paths:
/volumecontent/{volumeID}/path:
get:
description: Get path information
tags: [volumes]
parameters:
- $ref: '#/components/parameters/volumeID'
- $ref: '#/components/parameters/path'
responses:
'200':
description: Successfully retrieved path information
content:
application/json:
schema:
$ref: '#/components/schemas/VolumeEntryStat'
'404':
$ref: '#/components/responses/404'
patch:
description: Update path metadata
tags: [volumes]
parameters:
- $ref: '#/components/parameters/volumeID'
- $ref: '#/components/parameters/path'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
uid:
type: integer
format: uint32
gid:
type: integer
format: uint32
mode:
type: integer
format: uint32
responses:
'200':
description: "Successfully updated a file's metadata"
content:
application/json:
schema:
$ref: '#/components/schemas/VolumeEntryStat'
'400':
description: 'Invalid metadata provided'
'404':
description: 'path not found'
'500':
description: 'Internal server error'
delete:
description: Delete a path
tags: [volumes]
parameters:
- $ref: '#/components/parameters/volumeID'
- $ref: '#/components/parameters/path'
responses:
'204':
description: Successfully deleted a path
'404':
$ref: '#/components/responses/404'
/volumecontent/{volumeID}/dir:
get:
description: List directory contents
tags: [volumes]
parameters:
- $ref: '#/components/parameters/volumeID'
- $ref: '#/components/parameters/path'
- name: depth
in: query
description: Number of layers deep to recurse into the directory
schema:
type: integer
format: uint32
default: 1
responses:
'200':
description: 'Successfully retrieved a directory listing'
content:
application/json:
schema:
$ref: '#/components/schemas/VolumeDirectoryListing'
'400':
description: 'Invalid path provided'
'404':
description: 'path not found'
'500':
$ref: '#/components/responses/500'
post:
description: 'Create a directory'
tags: [volumes]
parameters:
- $ref: '#/components/parameters/volumeID'
- $ref: '#/components/parameters/path'
- name: uid
in: query
description: User ID of the created directory
schema:
type: integer
format: uint32
- name: gid
in: query
description: Group ID of the created directory
schema:
type: integer
format: uint32
- name: mode
in: query
description: Mode of the created directory
schema:
type: integer
format: uint32
- name: force
in: query
description: Create the parents of a directory if they don't exist
schema:
type: boolean
responses:
'201':
description: 'Successfully created a directory'
content:
application/json:
schema:
$ref: '#/components/schemas/VolumeEntryStat'
'404':
description: 'path not found'
'500':
$ref: '#/components/responses/500'
/volumecontent/{volumeID}/file:
get:
description: Download file
tags: [volumes]
parameters:
- $ref: '#/components/parameters/volumeID'
- $ref: '#/components/parameters/path'
responses:
'200':
description: 'Successfully downloaded a file'
content:
application/octet-stream:
schema:
type: string
format: binary
'404':
description: 'path not found'
'500':
$ref: '#/components/responses/500'
put:
description: Upload file
tags: [volumes]
parameters:
- $ref: '#/components/parameters/volumeID'
- $ref: '#/components/parameters/path'
- name: uid
in: query
description: User ID of the uploaded file
schema:
type: integer
format: uint32
- name: gid
in: query
description: Group ID of the uploaded file
schema:
type: integer
format: uint32
- name: mode
in: query
description: Mode of the uploaded file
schema:
type: integer
format: uint32
- name: force
in: query
description: Force overwrite of an existing file
schema:
type: boolean
requestBody:
content:
application/octet-stream:
schema:
type: string
format: binary
responses:
'201':
description: 'Successfully created a file'
content:
application/json:
schema:
$ref: '#/components/schemas/VolumeEntryStat'
'404':
description: 'path not found'
'500':
$ref: '#/components/responses/500'
+3653
View File
File diff suppressed because it is too large Load Diff
+11
View File
@@ -0,0 +1,11 @@
{
"name": "@e2b/spec",
"private": true,
"scripts": {
"lint": "prettier --check openapi.yml envd/envd.yaml",
"format": "prettier --write openapi.yml envd/envd.yaml"
},
"devDependencies": {
"prettier": "^3.3.3"
}
}
+45
View File
@@ -0,0 +1,45 @@
import os
import sys
import yaml
# Get directory of this script
directory = os.path.dirname(os.path.abspath(__file__))
path = os.path.join(directory, "openapi.yml")
# Load OpenAPI spec
with open(path, "r") as file:
spec = yaml.safe_load(file)
tags_to_keep = sys.argv[1:] if len(sys.argv) > 1 else None
filtered_paths = {}
for path, methods in spec.get("paths", {}).items():
# Store path-level parameters if they exist
path_level_params = methods.get("parameters")
for method, operation in methods.items():
# Skip path-level parameters key as it's not a method
if method == "parameters":
continue
if "tags" in operation:
for tag in tags_to_keep:
if tag in operation["tags"]:
if path in filtered_paths:
filtered_paths[path][method] = operation
else:
filtered_paths[path] = {method: operation}
# Add path-level parameters if they exist
if path_level_params:
filtered_paths[path]["parameters"] = path_level_params
break
# Create a new spec with only the filtered paths
filtered_spec = spec.copy()
filtered_spec["paths"] = filtered_paths
# Save the filtered spec
with open(os.path.join(directory, "openapi_generated.yml"), "w") as file:
yaml.dump(filtered_spec, file)