syntax = "proto3"; option go_package = "github.com/modal-labs/modal/go/proto"; import "google/protobuf/empty.proto"; import "modal_proto/api.proto"; package modal.task_command_router; enum TaskExecStderrConfig { // The output will be discarded. TASK_EXEC_STDERR_CONFIG_DEVNULL = 0; // The output will be streamed to the client. TASK_EXEC_STDERR_CONFIG_PIPE = 1; // A special value that can be used to indicate that the stderr stream should // be merged with the stdout stream. TASK_EXEC_STDERR_CONFIG_STDOUT = 2; } enum TaskExecStdioFileDescriptor { // Read from stdout. TASK_EXEC_STDIO_FILE_DESCRIPTOR_STDOUT = 0; // Read from stderr. TASK_EXEC_STDIO_FILE_DESCRIPTOR_STDERR = 1; } enum TaskExecStdoutConfig { // The output will be discarded. TASK_EXEC_STDOUT_CONFIG_DEVNULL = 0; // The output will be streamed to the client. TASK_EXEC_STDOUT_CONFIG_PIPE = 1; } message TaskExecPollRequest { // The ID of the task running the exec'd command. string task_id = 1; // The execution ID of the command to wait on. string exec_id = 2; } // The response to a TaskExecPollRequest. If the exec'd command has not // completed, exit_status will be unset. message TaskExecPollResponse { oneof exit_status { // The exit code of the command. int32 code = 1; // The signal that terminated the command. int32 signal = 2; } // TODO(saltzm): Give a way for the user to distinguish between normal exit // and termination by Modal (due to task timeout, exec exceeded deadline, etc.) } message TaskExecStartRequest { // The ID of the task to execute the command in. string task_id = 1; // Execution ID. This ID will be used to identify the execution for other // requests and ensure exec commands are idempotent. string exec_id = 2; // Command arguments to execute. repeated string command_args= 3; // Configures how the stdout of the command will be handled. TaskExecStdoutConfig stdout_config = 4; // Configures how the stderr of the command will be handled. TaskExecStderrConfig stderr_config = 5; // Timeout in seconds for the exec'd command to exit. If the command does not // exit within this duration, the command will be killed. This is NOT the // timeout for the ExecStartRequest RPC to complete. optional uint32 timeout_secs = 6; // Working directory for the command. optional string workdir = 7; // Secret IDs to mount into the task. repeated string secret_ids = 8; // PTY info for the command. optional modal.client.PTYInfo pty_info = 9; // Enable debugging capabilities on the container runtime. Used only for // internal debugging. bool runtime_debug = 10; } message TaskExecStartResponse { } message TaskExecStdinWriteRequest { // The ID of the task running the exec'd command. string task_id = 1; // The execution ID of the command to write to. string exec_id = 2; // The offset to start writing to. This is used to resume writing from the // last write position if the connection is closed and reopened. uint64 offset = 3; bytes data = 4; // If true, close the stdin stream after writing any provided data. // This signals EOF to the exec'd process. bool eof = 5; } message TaskExecStdinWriteResponse { } message TaskExecStdioReadRequest { // The ID of the task running the exec'd command. string task_id = 1; // The execution ID of the command to read from. string exec_id = 2; // The offset to start reading from. This is used to resume reading from the // last read position if the connection is closed and reopened. uint64 offset = 3; // Which file descriptor to read from. TaskExecStdioFileDescriptor file_descriptor = 4; } message TaskExecStdioReadResponse { // The data read from the file descriptor. bytes data = 1; } message TaskExecWaitRequest { // The ID of the task running the exec'd command. string task_id = 1; // The execution ID of the command to wait on. string exec_id = 2; } message TaskExecWaitResponse { oneof exit_status { // The exit code of the command. int32 code = 1; // The signal that terminated the command. int32 signal = 2; } // TODO(saltzm): Give a way for the user to distinguish between normal exit // and termination by Modal (due to task timeout, exec exceeded deadline, etc.) } message TaskMountDirectoryRequest { string task_id = 1; bytes path = 2; string image_id = 3; } message TaskSnapshotDirectoryRequest { string task_id = 1; bytes path = 2; } message TaskSnapshotDirectoryResponse { string image_id = 1; } service TaskCommandRouter { // Poll for the exit status of an exec'd command. rpc TaskExecPoll(TaskExecPollRequest) returns (TaskExecPollResponse); // Execute a command in the task. rpc TaskExecStart(TaskExecStartRequest) returns (TaskExecStartResponse); // Write to the stdin stream of an exec'd command. rpc TaskExecStdinWrite(TaskExecStdinWriteRequest) returns (TaskExecStdinWriteResponse); // Get a stream of output from the stdout or stderr stream of an exec'd command. rpc TaskExecStdioRead(TaskExecStdioReadRequest) returns (stream TaskExecStdioReadResponse); // Wait for an exec'd command to exit and return the exit code. rpc TaskExecWait(TaskExecWaitRequest) returns (TaskExecWaitResponse); // Mount an image at a directory in the container. rpc TaskMountDirectory(TaskMountDirectoryRequest) returns (google.protobuf.Empty); // Snapshot a directory with a mounted image, including any local changes, into a new image. rpc TaskSnapshotDirectory(TaskSnapshotDirectoryRequest) returns (TaskSnapshotDirectoryResponse); }