syntax = "proto3"; package agent; option go_package = "git.ipao.vip/rogee/go-sip/gen/agent;agentpb"; // AgentControl is the project-owned Unary gRPC boundary between the single // active Dispatcher and a Cell Agent. It carries metadata and facts, never // audio bytes or an internal message-bus replacement. service AgentControlService { rpc GetAgentStatus(GetAgentStatusRequest) returns (GetAgentStatusResponse); rpc ActivateAgent(ActivateAgentRequest) returns (ActivateAgentResponse); rpc ExecuteApproved(ExecuteApprovedRequest) returns (ExecuteApprovedResponse); rpc ApplyApprovedTaskControl(ApplyApprovedTaskControlRequest) returns (ApplyApprovedTaskControlResponse); rpc GetLoadedSIP(GetLoadedSIPRequest) returns (GetLoadedSIPResponse); // Only a pinned, activated Dispatcher may apply the complete approved SIP snapshot. rpc ApplySIP(ApplySIPRequest) returns (ApplySIPResponse); // Agent requests a fresh bounded token explicitly; the Dispatcher owns the original target. rpc RequestRecordingUpload(RequestRecordingUploadRequest) returns (RequestRecordingUploadResponse); rpc ReportCallEnded(ReportCallEndedRequest) returns (ReportCallEndedResponse); rpc ReportCallResult(ReportCallResultRequest) returns (ReportCallResultResponse); } enum ResultCode { RESULT_CODE_UNSPECIFIED = 0; RESULT_CODE_ACCEPTED = 1; RESULT_CODE_APPLIED = 2; RESULT_CODE_REJECTED = 3; RESULT_CODE_UNKNOWN = 4; RESULT_CODE_CONFLICT = 5; } enum FailureCode { FAILURE_CODE_UNSPECIFIED = 0; FAILURE_CODE_INVALID_ARGUMENT = 1; FAILURE_CODE_UNAUTHENTICATED = 2; FAILURE_CODE_PERMISSION_DENIED = 3; FAILURE_CODE_FAILED_PRECONDITION = 4; FAILURE_CODE_ABORTED = 5; FAILURE_CODE_RESOURCE_EXHAUSTED = 6; FAILURE_CODE_UNAVAILABLE = 7; FAILURE_CODE_DEADLINE_EXCEEDED = 8; FAILURE_CODE_NOT_FOUND = 9; FAILURE_CODE_ALREADY_EXISTS = 10; } enum ActivationState { ACTIVATION_STATE_UNSPECIFIED = 0; ACTIVATION_STATE_PENDING = 1; ACTIVATION_STATE_ACTIVE = 2; ACTIVATION_STATE_CONFLICT = 3; ACTIVATION_STATE_REVOKED = 4; } enum AdmissionState { ADMISSION_STATE_UNSPECIFIED = 0; ADMISSION_STATE_OPEN = 1; ADMISSION_STATE_CLOSED = 2; ADMISSION_STATE_DRAINING = 3; ADMISSION_STATE_QUARANTINED = 4; } enum ControlAction { CONTROL_ACTION_UNSPECIFIED = 0; CONTROL_ACTION_PAUSE = 1; CONTROL_ACTION_RESUME = 2; CONTROL_ACTION_STOP = 3; } enum ActiveCallPolicy { ACTIVE_CALL_POLICY_UNSPECIFIED = 0; ACTIVE_CALL_POLICY_DRAIN = 1; ACTIVE_CALL_POLICY_HANGUP = 2; } enum AssetKind { ASSET_KIND_UNSPECIFIED = 0; ASSET_KIND_RECORDING = 1; ASSET_KIND_TRANSCRIPT = 2; } message RequestMeta { string protocol_version = 1; string request_id = 2; string trace_id = 3; string operation_id = 4; int64 deadline_unix_ms = 5; string dispatcher_epoch = 6; string agent_id = 7; string cell_id = 8; string boot_id = 9; uint64 session_generation = 10; string idempotency_key = 11; } message ResponseMeta { string protocol_version = 1; string request_id = 2; string trace_id = 3; string operation_id = 4; int64 observed_at_unix_ms = 5; string dispatcher_epoch = 6; string agent_id = 7; string cell_id = 8; string boot_id = 9; uint64 session_generation = 10; } message Failure { FailureCode code = 1; bool retryable = 2; string detail = 3; string field = 4; } message OperationReceipt { ResponseMeta meta = 1; ResultCode result = 2; Failure failure = 3; string fact_id = 4; string content_sha256 = 5; int64 accepted_at_unix_ms = 6; } message AgentBinding { string agent_id = 1; string cell_id = 2; string expected_boot_id = 3; string dispatcher_epoch = 4; uint64 session_generation = 5; string endpoint_id = 6; string dispatcher_id = 7; // Bound to the active, authenticated D session. } message Capability { string name = 1; string version = 2; string value = 3; } message ResourceSample { int64 observed_at_unix_ms = 1; double cpu_used_ratio = 2; int64 memory_available_bytes = 3; int64 fd_used = 4; int64 fd_limit = 5; int64 spool_used_bytes = 6; int64 spool_capacity_bytes = 7; int64 media_ports_used = 8; int64 media_ports_capacity = 9; bool sample_fresh = 10; string missing_reason = 11; } // Optional status metadata is not an admission grant. The Dispatcher checks // GetLoadedSIP revisions separately; a Mock status cannot prove Asterisk loaded // the approved configuration. message AppliedConfig { string kind = 1; string revision = 2; string config_sha256 = 3; string state = 4; int64 observed_at_unix_ms = 5; } message AgentStatus { string agent_id = 1; string cell_id = 2; string boot_id = 3; string software_version = 4; string protocol_version = 5; string asterisk_version = 6; AdmissionState admission_state = 7; repeated Capability capabilities = 8; ResourceSample resources = 9; repeated AppliedConfig applied_configs = 10; bool mtls_authenticated = 11; bool session_active = 12; string status_reason = 13; } message Session { string dispatcher_epoch = 1; uint64 session_generation = 2; int64 expires_at_unix_ms = 3; bytes session_credential = 4; } message AssetDescriptor { AssetKind kind = 1; string asset_id = 2; string call_id = 3; string execution_id = 4; string format = 5; int64 size_bytes = 6; string checksum_sha256 = 7; int32 channels = 8; int32 sample_rate_hz = 9; int64 duration_ms = 10; } message Header { string name = 1; string value = 2; } message GetAgentStatusRequest { RequestMeta meta = 1; AgentBinding target = 2; } message GetAgentStatusResponse { ResponseMeta meta = 1; AgentStatus status = 2; Failure failure = 3; } message ActivateAgentRequest { RequestMeta meta = 1; AgentBinding binding = 2; string activation_operation_id = 3; bytes session_nonce = 4; int64 session_expires_at_unix_ms = 5; } message ActivateAgentResponse { ResponseMeta meta = 1; ActivationState state = 2; Session session = 3; Failure failure = 4; } // Exact, immutable task/provider bytes and SIP revision accompany each // authorized execution. Provider bytes may contain credentials: never log // or persist this request body. The Agent checks session, binding and // deadline, but does not recalculate the Dispatcher outbound policy. message ExecuteApprovedRequest { RequestMeta meta = 1; string dispatcher_id = 2; int64 tenant_id = 3; string task_id = 4; string source_event_id = 5; string call_id = 6; string selected_trunk_id = 7; string caller_id = 8; string callee = 9; string dialed_callee = 10; int64 ring_timeout_ms = 11; int64 max_call_duration_ms = 12; int64 dial_before_unix_ms = 13; int64 sip_revision = 14; bytes task_config_json = 15; bytes providers_json = 16; string binding_sha256 = 17; } message ExecuteApprovedResponse { string call_id = 1; bool accepted = 2; } message GetLoadedSIPRequest { RequestMeta meta = 1; } message GetLoadedSIPResponse { map trunk_revision = 1; } message ApplySIPRequest { RequestMeta meta = 1; bytes approved_snapshot_json = 2; } message ApplySIPResponse { map trunk_revision = 1; } // Current task-level control has no external command ID, revision CAS or // execution binding. The authenticated session must match dispatcher_id. message ApplyApprovedTaskControlRequest { RequestMeta meta = 1; string dispatcher_id = 2; int64 tenant_id = 3; string task_id = 4; ControlAction action = 5; ActiveCallPolicy active_call_policy = 6; } message ApplyApprovedTaskControlResponse { bool accepted = 1; } message UploadGrant { string upload_id = 1; string target_url = 2; repeated Header headers = 3; int64 expires_at_unix_ms = 4; string object_key = 5; string required_checksum_sha256 = 6; int64 max_bytes = 7; string bucket = 8; } // These facts refer only to the Dispatcher-approved execution identified by // source_event_id; no audio bytes or temporary credential is persisted in MQ. message RequestRecordingUploadRequest { RequestMeta meta = 1; string dispatcher_id = 2; int64 tenant_id = 3; string source_event_id = 4; string upload_id = 5; AssetDescriptor asset = 6; } message RequestRecordingUploadResponse { UploadGrant grant = 1; } message ReportCallEndedRequest { RequestMeta meta = 1; string dispatcher_id = 2; int64 tenant_id = 3; string source_event_id = 4; } message ReportCallEndedResponse { OperationReceipt receipt = 1; } message UploadObservation { string upload_id = 1; string recording_id = 2; int32 put_status_code = 3; int64 size_bytes = 4; string checksum_sha256 = 5; } message ReportCallResultRequest { RequestMeta meta = 1; string dispatcher_id = 2; int64 tenant_id = 3; string source_event_id = 4; bytes result_payload_json = 5; UploadObservation upload = 6; } message ReportCallResultResponse { OperationReceipt receipt = 1; }