syntax = "proto3";

package flare.common.v1;

import "sync.proto";

// DATA 通道载荷（不占 conversation_seq）。payload oneof 是唯一类型判别。

message CustomData {
  string type = 1;       // 业务类型标识，如 "badge" / "config"
  bytes payload = 2;     // 业务载荷
  map<string, string> attributes = 3;
}

message CapabilityPacket {
  string capability_id = 1;  // e.g. rtc.call | bot.command | workflow.approval
  string packet_type = 2;    // plugin-owned action/type
  string version = 3;
  bytes payload = 4;         // plugin-owned protobuf/JSON bytes
  map<string, string> attributes = 5;
  optional string correlation_id = 6;
}

message TypingStatePacket {
  string conversation_id = 1;
  string user_id = 2;
  bool typing = 3;
  optional string device_id = 4;
  optional int64 occurred_at = 5;
}

// 网关聚合的"N 人正在输入"（超大群 typing 风暴防护）：服务端按会话聚合当前正在输入的用户，
// 节流后下发一条，替代逐用户 TypingStatePacket。客户端按 typing_user_ids 采样渲染姓名 + 用 typing_count 显示总数。
message TypingAggregatePacket {
  string conversation_id = 1;
  repeated string typing_user_ids = 2;  // 当前正在输入用户的**采样**（有上限），用于显示姓名
  uint32 typing_count = 3;              // 当前正在输入的**总人数**（可大于采样数）
  optional int64 occurred_at = 4;
}

message PresenceHintPacket {
  string user_id = 1;
  string status = 2;  // online | offline | away | busy | custom
  optional string device_id = 3;
  map<string, string> attributes = 4;
  optional int64 occurred_at = 5;
}

message RealtimeControlPacket {
  string control_type = 1;  // typing | presence | custom
  optional string conversation_id = 2;
  optional string correlation_id = 3;
  map<string, string> attributes = 4;

  oneof payload {
    TypingStatePacket typing = 10;
    PresenceHintPacket presence = 11;
    CustomData custom = 12;
    TypingAggregatePacket typing_aggregate = 13;  // 网关聚合下发（上行仍用 typing）
  }
}

/// DATA 统一包：SDK 与网关按 payload oneof 解析。
message DataPacket {
  oneof payload {
    Sync sync_request = 10;
    SyncRes sync_response = 11;
    CustomData user_custom = 12;
    CapabilityPacket capability = 13;
    RealtimeControlPacket realtime_control = 14;
  }
}
