package controlplane import ( "encoding/json" "time" ) const ProtocolVersion = "v1" const MaxTaskResultBytes = 512 * 1024 type TaskStatus string const ( TaskPending TaskStatus = "Pending" TaskAccepted TaskStatus = "Accepted" TaskRunning TaskStatus = "Running" TaskSucceeded TaskStatus = "Succeeded" TaskFailed TaskStatus = "Failed" TaskCancelled TaskStatus = "Cancelled" TaskExpired TaskStatus = "Expired" TaskResultUnconfirmed TaskStatus = "ResultUnconfirmed" ) type NodeStatus string const ( NodeRegistered NodeStatus = "Registered" NodeOnline NodeStatus = "Online" NodeDegraded NodeStatus = "Degraded" NodeOffline NodeStatus = "Offline" NodeSessionLocked NodeStatus = "SessionLocked" NodeWechatNotRunning NodeStatus = "WechatNotRunning" NodeWechatNotLogged NodeStatus = "WechatNotLoggedIn" ) type ChatType string const ( ChatGroup ChatType = "Group" ChatPrivate ChatType = "Private" ) type NodeRegistration struct { NodeID string `json:"node_id"` AgentVersion string `json:"agent_version"` ProtocolVersion string `json:"protocol_version"` Capabilities []string `json:"capabilities"` ReportingConfigVersion int64 `json:"reporting_config_version"` Accounts []AccountSummary `json:"accounts"` } type AccountSummary struct { AccountID string `json:"account_id"` Active bool `json:"active"` Verified bool `json:"verified"` AllowedGroupCount int `json:"allowed_group_count"` AllowedPrivateCount int `json:"allowed_private_count"` } type Heartbeat struct { NodeID string `json:"node_id"` AgentVersion string `json:"agent_version"` ProtocolVersion string `json:"protocol_version"` NodeStatus NodeStatus `json:"node_status"` WechatRunning bool `json:"wechat_running"` WechatLoggedIn bool `json:"wechat_logged_in"` SessionLocked bool `json:"session_locked"` ActiveAccountID string `json:"active_account_id,omitempty"` QueueLength int `json:"queue_length"` ReportingConfigVersion int64 `json:"reporting_config_version"` CorrelationID string `json:"correlation_id"` LastErrorCode string `json:"last_error_code,omitempty"` } type Task struct { TaskID string `json:"task_id"` NodeID string `json:"node_id"` AccountID string `json:"account_id"` Kind string `json:"kind"` IdempotencyKey string `json:"idempotency_key"` Payload jsonRaw `json:"payload"` NotAfter *time.Time `json:"not_after,omitempty"` Status TaskStatus `json:"status"` StateVersion int64 `json:"state_version"` LeaseGeneration int64 `json:"lease_generation"` LeaseExpiresAt *time.Time `json:"lease_expires_at,omitempty"` LeaseOwner string `json:"lease_owner,omitempty"` CancelRequestedAt *time.Time `json:"cancel_requested_at,omitempty"` Result *TaskResult `json:"result,omitempty"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` LastCorrelationID string `json:"last_correlation_id,omitempty"` } // jsonRaw preserves task/content JSON without coupling the API to a concrete payload type. type jsonRaw = json.RawMessage type TaskSubmission struct { NodeID string `json:"node_id"` AccountID string `json:"account_id"` Kind string `json:"kind"` IdempotencyKey string `json:"idempotency_key"` Payload jsonRaw `json:"payload"` NotAfter *time.Time `json:"not_after,omitempty"` } type ReadTaskSubmission struct { NodeID string `json:"node_id"` AccountID string `json:"account_id"` IdempotencyKey string `json:"idempotency_key"` Limit int `json:"limit,omitempty"` Offset int `json:"offset,omitempty"` Contains string `json:"contains,omitempty"` GroupsOnly *bool `json:"groups_only,omitempty"` ChatID string `json:"chat_id,omitempty"` IncludeContent bool `json:"include_content,omitempty"` NotAfter *time.Time `json:"not_after,omitempty"` } type TaskResult struct { TaskID string `json:"task_id"` AccountID string `json:"account_id"` LeaseGeneration int64 `json:"lease_generation"` Status TaskStatus `json:"status"` ErrorCode string `json:"error_code,omitempty"` Message string `json:"message,omitempty"` HasSideEffect bool `json:"has_side_effect"` Content jsonRaw `json:"content,omitempty"` CorrelationID string `json:"correlation_id"` } type TaskAck struct { TaskID string `json:"task_id"` AccountID string `json:"account_id"` LeaseGeneration int64 `json:"lease_generation"` } type MessageEvent struct { NodeID string `json:"node_id"` AccountID string `json:"account_id"` ChatID string `json:"chat_id"` ChatType ChatType `json:"chat_type"` EventSeq int64 `json:"event_seq"` EventType string `json:"event_type"` OccurredAt time.Time `json:"occurred_at"` Content string `json:"content,omitempty"` ConfigVersion int64 `json:"config_version"` AuthorizationVersion int64 `json:"authorization_version"` CorrelationID string `json:"correlation_id"` Authorized bool `json:"authorized"` } type StoredEvent struct { MessageEvent EventID string `json:"event_id"` ContentHash string `json:"content_hash"` ReceivedAt time.Time `json:"received_at"` } type AuditEntry struct { ID string `json:"id"` At time.Time `json:"at"` Principal string `json:"principal"` Action string `json:"action"` Resource string `json:"resource"` CorrelationID string `json:"correlation_id"` Outcome string `json:"outcome"` } type Node struct { NodeID string `json:"node_id"` AgentVersion string `json:"agent_version"` ProtocolVersion string `json:"protocol_version"` Capabilities []string `json:"capabilities"` Status NodeStatus `json:"status"` LastHeartbeatAt *time.Time `json:"last_heartbeat_at,omitempty"` WechatRunning bool `json:"wechat_running"` WechatLoggedIn bool `json:"wechat_logged_in"` SessionLocked bool `json:"session_locked"` ActiveAccountID string `json:"active_account_id,omitempty"` QueueLength int `json:"queue_length"` ReportingConfigVersion int64 `json:"reporting_config_version"` Accounts []AccountSummary `json:"accounts"` LastErrorCode string `json:"last_error_code,omitempty"` LastCorrelationID string `json:"last_correlation_id,omitempty"` } type PersistedState struct { Nodes map[string]Node `json:"nodes"` Tasks map[string]Task `json:"tasks"` Events []StoredEvent `json:"events"` Audit []AuditEntry `json:"audit"` } type NodeResponse struct { NodeID string `json:"node_id"` Status NodeStatus `json:"status"` Authenticated bool `json:"authenticated,omitempty"` LastHeartbeatAt *time.Time `json:"last_heartbeat_at,omitempty"` CorrelationID string `json:"correlation_id"` } type TaskBatch struct { Tasks []Task `json:"tasks"` } type EventReceipt struct { Accepted bool `json:"accepted"` Duplicate bool `json:"duplicate"` EventID string `json:"event_id,omitempty"` Reason string `json:"reason,omitempty"` } type TaskSubmissionResponse struct { TaskID string `json:"task_id"` Status TaskStatus `json:"status"` Duplicate bool `json:"duplicate"` StateVersion int64 `json:"state_version"` } type APIError struct { Code string `json:"code"` Message string `json:"message"` CorrelationID string `json:"correlation_id"` }