package controlplane import ( "encoding/json" "time" ) const ProtocolVersion = "v1" const MaxTaskResultBytes = 512 * 1024 type TaskStatus string const ( TaskPending TaskStatus = "Pending" TaskWaitingForClient TaskStatus = "WaitingForClient" 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"` ConnectionID string `json:"connection_id,omitempty"` 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"` AllowedChats []AllowedChatSummary `json:"allowed_chats,omitempty"` } type AllowedChatSummary struct { ChatID string `json:"chat_id"` ChatType ChatType `json:"chat_type"` } type Heartbeat struct { NodeID string `json:"node_id"` ConnectionID string `json:"connection_id,omitempty"` 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"` ConnectionID string `json:"connection_id,omitempty"` 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"` AIFlows map[string]AIFlow `json:"ai_flows,omitempty"` AIRuns map[string]AIRun `json:"ai_runs,omitempty"` AIPullTasks map[string]AIPullTask `json:"ai_pull_tasks,omitempty"` AIMessageKeys map[string]string `json:"ai_message_keys,omitempty"` } type AITriggerType string const ( AITriggerRealtime AITriggerType = "realtime" AITriggerInterval AITriggerType = "interval" ) type AIRunStatus string const ( AIRunPending AIRunStatus = "Pending" AIRunRunning AIRunStatus = "Running" AIRunSucceeded AIRunStatus = "Succeeded" AIRunFailed AIRunStatus = "Failed" ) type AITarget struct { NodeID string `json:"node_id"` AccountID string `json:"account_id"` ChatID string `json:"chat_id"` ChatType ChatType `json:"chat_type"` } type AITrigger struct { Type AITriggerType `json:"type"` IntervalSeconds int `json:"interval_seconds,omitempty"` BatchLimit int `json:"batch_limit,omitempty"` } type AIFlowRequest struct { Name string `json:"name"` Targets []AITarget `json:"targets"` Trigger AITrigger `json:"trigger"` Instruction string `json:"instruction"` OutputSchema jsonRaw `json:"output_schema"` Tools []string `json:"tools"` Enabled bool `json:"enabled"` } type AIFlow struct { AIFlowRequest FlowID string `json:"flow_id"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` NextRunAt *time.Time `json:"next_run_at,omitempty"` LastRunAt *time.Time `json:"last_run_at,omitempty"` LastError string `json:"last_error,omitempty"` } type AIMessage struct { MessageID string `json:"message_id,omitempty"` Fingerprint string `json:"fingerprint,omitempty"` Type string `json:"type,omitempty"` Sender string `json:"sender,omitempty"` OccurredAt time.Time `json:"occurred_at,omitempty"` Content string `json:"content,omitempty"` } type AIPullTask struct { FlowID string `json:"flow_id"` TaskID string `json:"task_id"` Target AITarget `json:"target"` CreatedAt time.Time `json:"created_at"` } type AIRun struct { RunID string `json:"run_id"` FlowID string `json:"flow_id"` TriggerType AITriggerType `json:"trigger_type"` MessageKey string `json:"message_key"` SourceEventID string `json:"source_event_id,omitempty"` SourceTaskID string `json:"source_task_id,omitempty"` Target AITarget `json:"target"` Messages []AIMessage `json:"messages"` Status AIRunStatus `json:"status"` Output jsonRaw `json:"output,omitempty"` RawOutput string `json:"raw_output,omitempty"` ToolCalls []AIToolCallRecord `json:"tool_calls,omitempty"` ErrorCode string `json:"error_code,omitempty"` Error string `json:"error,omitempty"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } type AIToolDefinition struct { Name string `json:"name"` Description string `json:"description"` Parameters jsonRaw `json:"parameters"` } type AIToolCall struct { ID string `json:"id"` Name string `json:"name"` Arguments jsonRaw `json:"arguments"` } type AIToolCallRecord struct { ID string `json:"id"` Name string `json:"name"` Arguments jsonRaw `json:"arguments"` Result jsonRaw `json:"result,omitempty"` Status string `json:"status"` } type AIChatMessage struct { Role string `json:"role"` Content string `json:"content,omitempty"` Name string `json:"name,omitempty"` ToolCallID string `json:"tool_call_id,omitempty"` ToolCalls []AIToolCall `json:"tool_calls,omitempty"` } type AICompletionRequest struct { System string Messages []AIChatMessage Schema jsonRaw Tools []AIToolDefinition } type AICompletionResponse struct { Content string ToolCalls []AIToolCall } type PersistedAIConfig struct { ProviderConfigured bool `json:"provider_configured"` Model string `json:"model"` } type NodeResponse struct { NodeID string `json:"node_id"` ConnectionID string `json:"connection_id,omitempty"` 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"` }