226 lines
8.2 KiB
Go
226 lines
8.2 KiB
Go
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"`
|
|
}
|