diff --git a/proto/agynio/api/agents/v1/agents.proto b/proto/agynio/api/agents/v1/agents.proto index e6dee3f..744f75e 100644 --- a/proto/agynio/api/agents/v1/agents.proto +++ b/proto/agynio/api/agents/v1/agents.proto @@ -301,6 +301,10 @@ message Agent { // Vendor model name for native mode, opaque to the platform. Mutually // exclusive with model, which mode the environment is in decides. string model_name = 19; + // Whether this agent's idle workloads are hibernated. Defaults to true. + bool hibernate = 20; + optional string hibernate_after = 21; // Go duration string (e.g., "0s", "30s", "5m"). + optional string hibernation_ttl = 22; // Go duration string (e.g., "24h", "168h"). Minimum "1h". } message CreateAgentRequest { @@ -325,6 +329,10 @@ message CreateAgentRequest { optional string instance_idle_ttl = 17; // Go duration string (e.g., "30m", "6h"). // Required-and-exclusive against model, decided by the environment's llm_mode. string model_name = 18; + // Unset defaults to true. + optional bool hibernate = 19; + optional string hibernate_after = 20; // Go duration string (e.g., "0s", "30s", "5m"). + optional string hibernation_ttl = 21; // Go duration string (e.g., "24h", "168h"). Minimum "1h". } message CreateAgentResponse { @@ -371,6 +379,9 @@ message UpdateAgentRequest { optional AgentFinalMessage final_message = 16; optional string instance_idle_ttl = 17; // Go duration string (e.g., "30m", "6h"). optional string model_name = 18; + optional bool hibernate = 19; + optional string hibernate_after = 20; // Go duration string (e.g., "0s", "30s", "5m"). + optional string hibernation_ttl = 21; // Go duration string (e.g., "24h", "168h"). Minimum "1h". } message UpdateAgentResponse { @@ -770,6 +781,8 @@ enum SandboxStatus { SANDBOX_STATUS_STOPPED = 3; SANDBOX_STATUS_FAILED = 4; SANDBOX_STATUS_TERMINATED = 5; + // Workload state persisted on the runner, occupying no compute. + SANDBOX_STATUS_HIBERNATED = 6; } message Sandbox { diff --git a/proto/agynio/api/gateway/v1/runners.proto b/proto/agynio/api/gateway/v1/runners.proto index bfe2a29..dbe5342 100644 --- a/proto/agynio/api/gateway/v1/runners.proto +++ b/proto/agynio/api/gateway/v1/runners.proto @@ -34,6 +34,7 @@ service RunnersGateway { rpc ListWorkloadsByAgentInstance(agynio.api.runners.v1.ListWorkloadsByAgentInstanceRequest) returns (agynio.api.runners.v1.ListWorkloadsByAgentInstanceResponse); rpc GetWorkload(agynio.api.runners.v1.GetWorkloadRequest) returns (agynio.api.runners.v1.GetWorkloadResponse); rpc TouchWorkload(agynio.api.runners.v1.TouchWorkloadRequest) returns (agynio.api.runners.v1.TouchWorkloadResponse); + rpc ReportWorkloadIdle(agynio.api.runners.v1.ReportWorkloadIdleRequest) returns (agynio.api.runners.v1.ReportWorkloadIdleResponse); rpc StreamWorkloadLogs(agynio.api.runner.v1.StreamWorkloadLogsRequest) returns (stream agynio.api.runner.v1.StreamWorkloadLogsResponse); // --- Volumes --- diff --git a/proto/agynio/api/runner/v1/runner.proto b/proto/agynio/api/runner/v1/runner.proto index 4061e6b..3e17e53 100644 --- a/proto/agynio/api/runner/v1/runner.proto +++ b/proto/agynio/api/runner/v1/runner.proto @@ -15,6 +15,10 @@ service RunnerService { rpc StopWorkload(StopWorkloadRequest) returns (StopWorkloadResponse); rpc RemoveWorkload(RemoveWorkloadRequest) returns (RemoveWorkloadResponse); + // Unimplemented on a runner that does not advertise the hibernate capability. + rpc HibernateWorkload(HibernateWorkloadRequest) returns (HibernateWorkloadResponse); + rpc WakeWorkload(WakeWorkloadRequest) returns (WakeWorkloadResponse); + // Minimal inspect surface with EXACT fields required by platform today. rpc InspectWorkload(InspectWorkloadRequest) returns (InspectWorkloadResponse); @@ -221,6 +225,12 @@ enum WorkloadStatus { WORKLOAD_STATUS_STARTING = 2; WORKLOAD_STATUS_STOPPED = 3; WORKLOAD_STATUS_FAILED = 4; + // Being paused and persisted by the runner. + WORKLOAD_STATUS_HIBERNATING = 5; + // State persisted on the runner, occupying no compute. + WORKLOAD_STATUS_HIBERNATED = 6; + // Being resumed from its persisted state. + WORKLOAD_STATUS_WAKING = 7; } message WorkloadFailure { @@ -244,6 +254,20 @@ message RemoveWorkloadRequest { message RemoveWorkloadResponse {} +message HibernateWorkloadRequest { + string workload_id = 1; +} + +message HibernateWorkloadResponse {} + +message WakeWorkloadRequest { + string workload_id = 1; + + repeated ImagePullCredential image_pull_credentials = 2; +} + +message WakeWorkloadResponse {} + enum ContainerRole { CONTAINER_ROLE_UNSPECIFIED = 0; CONTAINER_ROLE_MAIN = 1; @@ -294,6 +318,11 @@ message InspectWorkloadResponse { string state_status = 7; bool state_running = 8; repeated WorkloadContainer containers = 9; + + WorkloadStatus status = 10; + + // Size of the persisted state in bytes. Present when status is HIBERNATED. + optional int64 snapshot_size_bytes = 11; } message TargetMount { @@ -316,6 +345,9 @@ message ListWorkloadsRequest {} message WorkloadListItem { string instance_id = 1; string workload_key = 2; + WorkloadStatus status = 3; + // Size of the persisted state in bytes. Present when status is HIBERNATED. + optional int64 snapshot_size_bytes = 4; } message ListWorkloadsResponse { diff --git a/proto/agynio/api/runners/v1/runners.proto b/proto/agynio/api/runners/v1/runners.proto index 75b2e07..b076cfc 100644 --- a/proto/agynio/api/runners/v1/runners.proto +++ b/proto/agynio/api/runners/v1/runners.proto @@ -49,6 +49,7 @@ service RunnersService { rpc UpdateWorkloadStatus(UpdateWorkloadStatusRequest) returns (UpdateWorkloadStatusResponse); rpc ReportWorkloadState(ReportWorkloadStateRequest) returns (ReportWorkloadStateResponse); rpc TouchWorkload(TouchWorkloadRequest) returns (TouchWorkloadResponse); + rpc ReportWorkloadIdle(ReportWorkloadIdleRequest) returns (ReportWorkloadIdleResponse); rpc DeleteWorkload(DeleteWorkloadRequest) returns (DeleteWorkloadResponse); rpc GetWorkload(GetWorkloadRequest) returns (GetWorkloadResponse); rpc ListWorkloadsByThread(ListWorkloadsByThreadRequest) returns (ListWorkloadsByThreadResponse); @@ -331,6 +332,12 @@ enum WorkloadStatus { WORKLOAD_STATUS_STOPPING = 3; WORKLOAD_STATUS_STOPPED = 4; WORKLOAD_STATUS_FAILED = 5; + // Being paused and persisted by the runner. + WORKLOAD_STATUS_HIBERNATING = 6; + // State persisted on the runner, occupying no compute. + WORKLOAD_STATUS_HIBERNATED = 7; + // Being resumed from its persisted state. + WORKLOAD_STATUS_WAKING = 8; } enum WorkloadAgentState { @@ -346,6 +353,10 @@ enum WorkloadFailureReason { WORKLOAD_FAILURE_REASON_CONFIG_INVALID = 3; WORKLOAD_FAILURE_REASON_CRASHLOOP = 4; WORKLOAD_FAILURE_REASON_RUNTIME_LOST = 5; + // A hibernated workload could not be woken. + WORKLOAD_FAILURE_REASON_WAKE_FAILED = 6; + // A hibernated workload's persisted state is gone from its runner. + WORKLOAD_FAILURE_REASON_SNAPSHOT_LOST = 7; } enum ContainerRole { @@ -400,6 +411,15 @@ message Workload { // Whether shells in this workload outlive the connections that reach them. // Resolved from the environment at start and fixed for the workload's life. bool persistent_shells = 27; + // When the workload most recently entered WORKLOAD_STATUS_HIBERNATED. Unset + // while it has never been hibernated or is awake. + optional google.protobuf.Timestamp hibernated_at = 28; + // When the workload most recently left WORKLOAD_STATUS_HIBERNATED for + // WORKLOAD_STATUS_RUNNING. Unset until its first wake. + optional google.protobuf.Timestamp woken_at = 29; + // Size of the persisted state in bytes. Set while status is + // WORKLOAD_STATUS_HIBERNATED; unset while the workload is awake. + optional int64 snapshot_size_bytes = 30; // Machine-readable reason for failures when status is WORKLOAD_STATUS_FAILED. // When status is not FAILED, this value may be unset or stale. optional WorkloadFailureReason failure_reason = 15; @@ -460,6 +480,9 @@ message UpdateWorkloadRequest { optional WorkloadFailureReason failure_reason = 7; // Human-readable failure detail; not intended for programmatic parsing. optional string failure_message = 8; + optional google.protobuf.Timestamp hibernated_at = 9; + optional google.protobuf.Timestamp woken_at = 10; + optional int64 snapshot_size_bytes = 11; } message UpdateWorkloadResponse { @@ -473,6 +496,8 @@ message ReportWorkloadStateRequest { WorkloadStatus status = 4; repeated Container containers = 5; google.protobuf.Timestamp observed_at = 6; + // Size of the persisted state in bytes. Set with WORKLOAD_STATUS_HIBERNATED. + optional int64 snapshot_size_bytes = 7; } message ReportWorkloadStateResponse { @@ -497,6 +522,12 @@ message TouchWorkloadRequest { message TouchWorkloadResponse {} +message ReportWorkloadIdleRequest { + string id = 1; +} + +message ReportWorkloadIdleResponse {} + message DeleteWorkloadRequest { string id = 1; }