792 lines
25 KiB
Rust
792 lines
25 KiB
Rust
//! Database Enum Types for Billion-Scale Schema
|
|
//!
|
|
//! This module defines Rust enums that map directly to PostgreSQL enum types.
|
|
//! Using enums instead of TEXT columns provides:
|
|
//! - Type safety at compile time
|
|
//! - Efficient storage (stored as integers internally)
|
|
//! - Fast comparisons and indexing
|
|
//! - Automatic validation
|
|
//!
|
|
//! All enums derive necessary traits for Diesel ORM integration.
|
|
|
|
use diesel::deserialize::{self, FromSql};
|
|
use diesel::pg::{Pg, PgValue};
|
|
use diesel::serialize::{self, Output, ToSql};
|
|
use diesel::sql_types::SmallInt;
|
|
// use diesel::{AsExpression, FromSqlRow}; // Removed to avoid conflict
|
|
use serde::{Deserialize, Serialize};
|
|
use std::io::Write;
|
|
|
|
// ============================================================================
|
|
// CHANNEL TYPES
|
|
// ============================================================================
|
|
|
|
/// Communication channel types for bot interactions
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, diesel::AsExpression, diesel::FromSqlRow)]
|
|
#[diesel(sql_type = SmallInt)]
|
|
#[serde(rename_all = "snake_case")]
|
|
#[repr(i16)]
|
|
#[derive(Default)]
|
|
pub enum ChannelType {
|
|
#[default]
|
|
Web = 0,
|
|
WhatsApp = 1,
|
|
Telegram = 2,
|
|
MsTeams = 3,
|
|
Slack = 4,
|
|
Email = 5,
|
|
Sms = 6,
|
|
Voice = 7,
|
|
Instagram = 8,
|
|
Api = 9,
|
|
}
|
|
|
|
|
|
impl ToSql<SmallInt, Pg> for ChannelType {
|
|
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
|
|
let v = *self as i16;
|
|
out.write_all(&v.to_be_bytes())?;
|
|
Ok(serialize::IsNull::No)
|
|
}
|
|
}
|
|
|
|
impl FromSql<SmallInt, Pg> for ChannelType {
|
|
fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
|
|
let value = <i16 as FromSql<SmallInt, Pg>>::from_sql(bytes)?;
|
|
match value {
|
|
0 => Ok(Self::Web),
|
|
1 => Ok(Self::WhatsApp),
|
|
2 => Ok(Self::Telegram),
|
|
3 => Ok(Self::MsTeams),
|
|
4 => Ok(Self::Slack),
|
|
5 => Ok(Self::Email),
|
|
6 => Ok(Self::Sms),
|
|
7 => Ok(Self::Voice),
|
|
8 => Ok(Self::Instagram),
|
|
9 => Ok(Self::Api),
|
|
_ => Err(format!("Unknown ChannelType: {}", value).into()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for ChannelType {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::Web => write!(f, "web"),
|
|
Self::WhatsApp => write!(f, "whatsapp"),
|
|
Self::Telegram => write!(f, "telegram"),
|
|
Self::MsTeams => write!(f, "msteams"),
|
|
Self::Slack => write!(f, "slack"),
|
|
Self::Email => write!(f, "email"),
|
|
Self::Sms => write!(f, "sms"),
|
|
Self::Voice => write!(f, "voice"),
|
|
Self::Instagram => write!(f, "instagram"),
|
|
Self::Api => write!(f, "api"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::str::FromStr for ChannelType {
|
|
type Err = String;
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
match s.to_lowercase().as_str() {
|
|
"web" => Ok(Self::Web),
|
|
"whatsapp" => Ok(Self::WhatsApp),
|
|
"telegram" => Ok(Self::Telegram),
|
|
"msteams" | "ms_teams" | "teams" => Ok(Self::MsTeams),
|
|
"slack" => Ok(Self::Slack),
|
|
"email" => Ok(Self::Email),
|
|
"sms" => Ok(Self::Sms),
|
|
"voice" => Ok(Self::Voice),
|
|
"instagram" => Ok(Self::Instagram),
|
|
"api" => Ok(Self::Api),
|
|
_ => Err(format!("Unknown channel type: {}", s)),
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// MESSAGE ROLE
|
|
// ============================================================================
|
|
|
|
/// Role of a message in a conversation
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, diesel::AsExpression, diesel::FromSqlRow)]
|
|
#[diesel(sql_type = SmallInt)]
|
|
#[serde(rename_all = "snake_case")]
|
|
#[repr(i16)]
|
|
#[derive(Default)]
|
|
pub enum MessageRole {
|
|
#[default]
|
|
User = 1,
|
|
Assistant = 2,
|
|
System = 3,
|
|
Tool = 4,
|
|
Episodic = 9,
|
|
Compact = 10,
|
|
}
|
|
|
|
|
|
impl ToSql<SmallInt, Pg> for MessageRole {
|
|
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
|
|
let v = *self as i16;
|
|
out.write_all(&v.to_be_bytes())?;
|
|
Ok(serialize::IsNull::No)
|
|
}
|
|
}
|
|
|
|
impl FromSql<SmallInt, Pg> for MessageRole {
|
|
fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
|
|
let value = <i16 as FromSql<SmallInt, Pg>>::from_sql(bytes)?;
|
|
match value {
|
|
1 => Ok(Self::User),
|
|
2 => Ok(Self::Assistant),
|
|
3 => Ok(Self::System),
|
|
4 => Ok(Self::Tool),
|
|
9 => Ok(Self::Episodic),
|
|
10 => Ok(Self::Compact),
|
|
_ => Err(format!("Unknown MessageRole: {}", value).into()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for MessageRole {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::User => write!(f, "user"),
|
|
Self::Assistant => write!(f, "assistant"),
|
|
Self::System => write!(f, "system"),
|
|
Self::Tool => write!(f, "tool"),
|
|
Self::Episodic => write!(f, "episodic"),
|
|
Self::Compact => write!(f, "compact"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::str::FromStr for MessageRole {
|
|
type Err = String;
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
match s.to_lowercase().as_str() {
|
|
"user" => Ok(Self::User),
|
|
"assistant" => Ok(Self::Assistant),
|
|
"system" => Ok(Self::System),
|
|
"tool" => Ok(Self::Tool),
|
|
"episodic" => Ok(Self::Episodic),
|
|
"compact" => Ok(Self::Compact),
|
|
_ => Err(format!("Unknown message role: {}", s)),
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// MESSAGE TYPE
|
|
// ============================================================================
|
|
|
|
/// Type of message content
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, diesel::AsExpression, diesel::FromSqlRow)]
|
|
#[diesel(sql_type = SmallInt)]
|
|
#[serde(rename_all = "snake_case")]
|
|
#[repr(i16)]
|
|
#[derive(Default)]
|
|
pub enum MessageType {
|
|
#[default]
|
|
Text = 0,
|
|
Image = 1,
|
|
Audio = 2,
|
|
Video = 3,
|
|
Document = 4,
|
|
Location = 5,
|
|
Contact = 6,
|
|
Sticker = 7,
|
|
Reaction = 8,
|
|
}
|
|
|
|
|
|
impl ToSql<SmallInt, Pg> for MessageType {
|
|
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
|
|
let v = *self as i16;
|
|
out.write_all(&v.to_be_bytes())?;
|
|
Ok(serialize::IsNull::No)
|
|
}
|
|
}
|
|
|
|
impl FromSql<SmallInt, Pg> for MessageType {
|
|
fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
|
|
let value = <i16 as FromSql<SmallInt, Pg>>::from_sql(bytes)?;
|
|
match value {
|
|
0 => Ok(Self::Text),
|
|
1 => Ok(Self::Image),
|
|
2 => Ok(Self::Audio),
|
|
3 => Ok(Self::Video),
|
|
4 => Ok(Self::Document),
|
|
5 => Ok(Self::Location),
|
|
6 => Ok(Self::Contact),
|
|
7 => Ok(Self::Sticker),
|
|
8 => Ok(Self::Reaction),
|
|
_ => Err(format!("Unknown MessageType: {}", value).into()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for MessageType {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::Text => write!(f, "text"),
|
|
Self::Image => write!(f, "image"),
|
|
Self::Audio => write!(f, "audio"),
|
|
Self::Video => write!(f, "video"),
|
|
Self::Document => write!(f, "document"),
|
|
Self::Location => write!(f, "location"),
|
|
Self::Contact => write!(f, "contact"),
|
|
Self::Sticker => write!(f, "sticker"),
|
|
Self::Reaction => write!(f, "reaction"),
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// LLM PROVIDER
|
|
// ============================================================================
|
|
|
|
/// Supported LLM providers
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, diesel::AsExpression, diesel::FromSqlRow)]
|
|
#[diesel(sql_type = SmallInt)]
|
|
#[serde(rename_all = "snake_case")]
|
|
#[repr(i16)]
|
|
#[derive(Default)]
|
|
pub enum LlmProvider {
|
|
#[default]
|
|
OpenAi = 0,
|
|
Anthropic = 1,
|
|
AzureOpenAi = 2,
|
|
AzureClaude = 3,
|
|
Google = 4,
|
|
Local = 5,
|
|
Ollama = 6,
|
|
Groq = 7,
|
|
Mistral = 8,
|
|
Cohere = 9,
|
|
}
|
|
|
|
|
|
impl ToSql<SmallInt, Pg> for LlmProvider {
|
|
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
|
|
let v = *self as i16;
|
|
out.write_all(&v.to_be_bytes())?;
|
|
Ok(serialize::IsNull::No)
|
|
}
|
|
}
|
|
|
|
impl FromSql<SmallInt, Pg> for LlmProvider {
|
|
fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
|
|
let value = <i16 as FromSql<SmallInt, Pg>>::from_sql(bytes)?;
|
|
match value {
|
|
0 => Ok(Self::OpenAi),
|
|
1 => Ok(Self::Anthropic),
|
|
2 => Ok(Self::AzureOpenAi),
|
|
3 => Ok(Self::AzureClaude),
|
|
4 => Ok(Self::Google),
|
|
5 => Ok(Self::Local),
|
|
6 => Ok(Self::Ollama),
|
|
7 => Ok(Self::Groq),
|
|
8 => Ok(Self::Mistral),
|
|
9 => Ok(Self::Cohere),
|
|
_ => Err(format!("Unknown LlmProvider: {}", value).into()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for LlmProvider {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::OpenAi => write!(f, "openai"),
|
|
Self::Anthropic => write!(f, "anthropic"),
|
|
Self::AzureOpenAi => write!(f, "azure_openai"),
|
|
Self::AzureClaude => write!(f, "azure_claude"),
|
|
Self::Google => write!(f, "google"),
|
|
Self::Local => write!(f, "local"),
|
|
Self::Ollama => write!(f, "ollama"),
|
|
Self::Groq => write!(f, "groq"),
|
|
Self::Mistral => write!(f, "mistral"),
|
|
Self::Cohere => write!(f, "cohere"),
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// CONTEXT PROVIDER (Vector DB)
|
|
// ============================================================================
|
|
|
|
/// Supported vector database providers
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, diesel::AsExpression, diesel::FromSqlRow)]
|
|
#[diesel(sql_type = SmallInt)]
|
|
#[serde(rename_all = "snake_case")]
|
|
#[repr(i16)]
|
|
#[derive(Default)]
|
|
pub enum ContextProvider {
|
|
None = 0,
|
|
#[default]
|
|
Qdrant = 1,
|
|
Pinecone = 2,
|
|
Weaviate = 3,
|
|
Milvus = 4,
|
|
PgVector = 5,
|
|
Elasticsearch = 6,
|
|
}
|
|
|
|
|
|
impl ToSql<SmallInt, Pg> for ContextProvider {
|
|
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
|
|
let v = *self as i16;
|
|
out.write_all(&v.to_be_bytes())?;
|
|
Ok(serialize::IsNull::No)
|
|
}
|
|
}
|
|
|
|
impl FromSql<SmallInt, Pg> for ContextProvider {
|
|
fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
|
|
let value = <i16 as FromSql<SmallInt, Pg>>::from_sql(bytes)?;
|
|
match value {
|
|
0 => Ok(Self::None),
|
|
1 => Ok(Self::Qdrant),
|
|
2 => Ok(Self::Pinecone),
|
|
3 => Ok(Self::Weaviate),
|
|
4 => Ok(Self::Milvus),
|
|
5 => Ok(Self::PgVector),
|
|
6 => Ok(Self::Elasticsearch),
|
|
_ => Err(format!("Unknown ContextProvider: {}", value).into()),
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// TASK STATUS
|
|
// ============================================================================
|
|
|
|
/// Status of a task (both regular tasks and auto-tasks)
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, diesel::AsExpression, diesel::FromSqlRow)]
|
|
#[diesel(sql_type = SmallInt)]
|
|
#[serde(rename_all = "snake_case")]
|
|
#[repr(i16)]
|
|
#[derive(Default)]
|
|
pub enum TaskStatus {
|
|
#[default]
|
|
Pending = 0,
|
|
Ready = 1,
|
|
Running = 2,
|
|
Paused = 3,
|
|
WaitingApproval = 4,
|
|
Completed = 5,
|
|
Failed = 6,
|
|
Cancelled = 7,
|
|
}
|
|
|
|
|
|
impl ToSql<SmallInt, Pg> for TaskStatus {
|
|
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
|
|
let v = *self as i16;
|
|
out.write_all(&v.to_be_bytes())?;
|
|
Ok(serialize::IsNull::No)
|
|
}
|
|
}
|
|
|
|
impl FromSql<SmallInt, Pg> for TaskStatus {
|
|
fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
|
|
let value = <i16 as FromSql<SmallInt, Pg>>::from_sql(bytes)?;
|
|
match value {
|
|
0 => Ok(Self::Pending),
|
|
1 => Ok(Self::Ready),
|
|
2 => Ok(Self::Running),
|
|
3 => Ok(Self::Paused),
|
|
4 => Ok(Self::WaitingApproval),
|
|
5 => Ok(Self::Completed),
|
|
6 => Ok(Self::Failed),
|
|
7 => Ok(Self::Cancelled),
|
|
_ => Err(format!("Unknown TaskStatus: {}", value).into()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for TaskStatus {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::Pending => write!(f, "pending"),
|
|
Self::Ready => write!(f, "ready"),
|
|
Self::Running => write!(f, "running"),
|
|
Self::Paused => write!(f, "paused"),
|
|
Self::WaitingApproval => write!(f, "waiting_approval"),
|
|
Self::Completed => write!(f, "completed"),
|
|
Self::Failed => write!(f, "failed"),
|
|
Self::Cancelled => write!(f, "cancelled"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::str::FromStr for TaskStatus {
|
|
type Err = String;
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
match s.to_lowercase().as_str() {
|
|
"pending" => Ok(Self::Pending),
|
|
"ready" => Ok(Self::Ready),
|
|
"running" => Ok(Self::Running),
|
|
"paused" => Ok(Self::Paused),
|
|
"waiting_approval" | "waitingapproval" => Ok(Self::WaitingApproval),
|
|
"completed" | "done" => Ok(Self::Completed),
|
|
"failed" | "error" => Ok(Self::Failed),
|
|
"cancelled" | "canceled" => Ok(Self::Cancelled),
|
|
_ => Err(format!("Unknown task status: {}", s)),
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// TASK PRIORITY
|
|
// ============================================================================
|
|
|
|
/// Priority level for tasks
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, diesel::AsExpression, diesel::FromSqlRow)]
|
|
#[diesel(sql_type = SmallInt)]
|
|
#[serde(rename_all = "snake_case")]
|
|
#[repr(i16)]
|
|
#[derive(Default)]
|
|
pub enum TaskPriority {
|
|
Low = 0,
|
|
#[default]
|
|
Normal = 1,
|
|
High = 2,
|
|
Urgent = 3,
|
|
Critical = 4,
|
|
}
|
|
|
|
|
|
impl ToSql<SmallInt, Pg> for TaskPriority {
|
|
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
|
|
let v = *self as i16;
|
|
out.write_all(&v.to_be_bytes())?;
|
|
Ok(serialize::IsNull::No)
|
|
}
|
|
}
|
|
|
|
impl FromSql<SmallInt, Pg> for TaskPriority {
|
|
fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
|
|
let value = <i16 as FromSql<SmallInt, Pg>>::from_sql(bytes)?;
|
|
match value {
|
|
0 => Ok(Self::Low),
|
|
1 => Ok(Self::Normal),
|
|
2 => Ok(Self::High),
|
|
3 => Ok(Self::Urgent),
|
|
4 => Ok(Self::Critical),
|
|
_ => Err(format!("Unknown TaskPriority: {}", value).into()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for TaskPriority {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::Low => write!(f, "low"),
|
|
Self::Normal => write!(f, "normal"),
|
|
Self::High => write!(f, "high"),
|
|
Self::Urgent => write!(f, "urgent"),
|
|
Self::Critical => write!(f, "critical"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::str::FromStr for TaskPriority {
|
|
type Err = String;
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
match s.to_lowercase().as_str() {
|
|
"low" => Ok(Self::Low),
|
|
"normal" | "medium" => Ok(Self::Normal),
|
|
"high" => Ok(Self::High),
|
|
"urgent" => Ok(Self::Urgent),
|
|
"critical" => Ok(Self::Critical),
|
|
_ => Err(format!("Unknown task priority: {}", s)),
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// EXECUTION MODE
|
|
// ============================================================================
|
|
|
|
/// Execution mode for autonomous tasks
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, diesel::AsExpression, diesel::FromSqlRow)]
|
|
#[diesel(sql_type = SmallInt)]
|
|
#[serde(rename_all = "snake_case")]
|
|
#[repr(i16)]
|
|
#[derive(Default)]
|
|
pub enum ExecutionMode {
|
|
Manual = 0,
|
|
#[default]
|
|
Supervised = 1,
|
|
Autonomous = 2,
|
|
}
|
|
|
|
|
|
impl ToSql<SmallInt, Pg> for ExecutionMode {
|
|
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
|
|
let v = *self as i16;
|
|
out.write_all(&v.to_be_bytes())?;
|
|
Ok(serialize::IsNull::No)
|
|
}
|
|
}
|
|
|
|
impl FromSql<SmallInt, Pg> for ExecutionMode {
|
|
fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
|
|
let value = <i16 as FromSql<SmallInt, Pg>>::from_sql(bytes)?;
|
|
match value {
|
|
0 => Ok(Self::Manual),
|
|
1 => Ok(Self::Supervised),
|
|
2 => Ok(Self::Autonomous),
|
|
_ => Err(format!("Unknown ExecutionMode: {}", value).into()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for ExecutionMode {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::Manual => write!(f, "manual"),
|
|
Self::Supervised => write!(f, "supervised"),
|
|
Self::Autonomous => write!(f, "autonomous"),
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// RISK LEVEL
|
|
// ============================================================================
|
|
|
|
/// Risk assessment level for actions
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, diesel::AsExpression, diesel::FromSqlRow)]
|
|
#[diesel(sql_type = SmallInt)]
|
|
#[serde(rename_all = "snake_case")]
|
|
#[repr(i16)]
|
|
#[derive(Default)]
|
|
pub enum RiskLevel {
|
|
None = 0,
|
|
#[default]
|
|
Low = 1,
|
|
Medium = 2,
|
|
High = 3,
|
|
Critical = 4,
|
|
}
|
|
|
|
|
|
impl ToSql<SmallInt, Pg> for RiskLevel {
|
|
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
|
|
let v = *self as i16;
|
|
out.write_all(&v.to_be_bytes())?;
|
|
Ok(serialize::IsNull::No)
|
|
}
|
|
}
|
|
|
|
impl FromSql<SmallInt, Pg> for RiskLevel {
|
|
fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
|
|
let value = <i16 as FromSql<SmallInt, Pg>>::from_sql(bytes)?;
|
|
match value {
|
|
0 => Ok(Self::None),
|
|
1 => Ok(Self::Low),
|
|
2 => Ok(Self::Medium),
|
|
3 => Ok(Self::High),
|
|
4 => Ok(Self::Critical),
|
|
_ => Err(format!("Unknown RiskLevel: {}", value).into()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for RiskLevel {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::None => write!(f, "none"),
|
|
Self::Low => write!(f, "low"),
|
|
Self::Medium => write!(f, "medium"),
|
|
Self::High => write!(f, "high"),
|
|
Self::Critical => write!(f, "critical"),
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// APPROVAL STATUS
|
|
// ============================================================================
|
|
|
|
/// Status of an approval request
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, diesel::AsExpression, diesel::FromSqlRow)]
|
|
#[diesel(sql_type = SmallInt)]
|
|
#[serde(rename_all = "snake_case")]
|
|
#[repr(i16)]
|
|
#[derive(Default)]
|
|
pub enum ApprovalStatus {
|
|
#[default]
|
|
Pending = 0,
|
|
Approved = 1,
|
|
Rejected = 2,
|
|
Expired = 3,
|
|
Skipped = 4,
|
|
}
|
|
|
|
|
|
impl ToSql<SmallInt, Pg> for ApprovalStatus {
|
|
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
|
|
let v = *self as i16;
|
|
out.write_all(&v.to_be_bytes())?;
|
|
Ok(serialize::IsNull::No)
|
|
}
|
|
}
|
|
|
|
impl FromSql<SmallInt, Pg> for ApprovalStatus {
|
|
fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
|
|
let value = <i16 as FromSql<SmallInt, Pg>>::from_sql(bytes)?;
|
|
match value {
|
|
0 => Ok(Self::Pending),
|
|
1 => Ok(Self::Approved),
|
|
2 => Ok(Self::Rejected),
|
|
3 => Ok(Self::Expired),
|
|
4 => Ok(Self::Skipped),
|
|
_ => Err(format!("Unknown ApprovalStatus: {}", value).into()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for ApprovalStatus {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::Pending => write!(f, "pending"),
|
|
Self::Approved => write!(f, "approved"),
|
|
Self::Rejected => write!(f, "rejected"),
|
|
Self::Expired => write!(f, "expired"),
|
|
Self::Skipped => write!(f, "skipped"),
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// APPROVAL DECISION
|
|
// ============================================================================
|
|
|
|
/// Decision made on an approval request
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, diesel::AsExpression, diesel::FromSqlRow)]
|
|
#[diesel(sql_type = SmallInt)]
|
|
#[serde(rename_all = "snake_case")]
|
|
#[repr(i16)]
|
|
pub enum ApprovalDecision {
|
|
Approve = 0,
|
|
Reject = 1,
|
|
Skip = 2,
|
|
}
|
|
|
|
impl ToSql<SmallInt, Pg> for ApprovalDecision {
|
|
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
|
|
let v = *self as i16;
|
|
out.write_all(&v.to_be_bytes())?;
|
|
Ok(serialize::IsNull::No)
|
|
}
|
|
}
|
|
|
|
impl FromSql<SmallInt, Pg> for ApprovalDecision {
|
|
fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
|
|
let value = <i16 as FromSql<SmallInt, Pg>>::from_sql(bytes)?;
|
|
match value {
|
|
0 => Ok(Self::Approve),
|
|
1 => Ok(Self::Reject),
|
|
2 => Ok(Self::Skip),
|
|
_ => Err(format!("Unknown ApprovalDecision: {}", value).into()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for ApprovalDecision {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::Approve => write!(f, "approve"),
|
|
Self::Reject => write!(f, "reject"),
|
|
Self::Skip => write!(f, "skip"),
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// INTENT TYPE
|
|
// ============================================================================
|
|
|
|
/// Classified intent type from user requests
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, diesel::AsExpression, diesel::FromSqlRow)]
|
|
#[diesel(sql_type = SmallInt)]
|
|
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
|
#[repr(i16)]
|
|
#[derive(Default)]
|
|
pub enum IntentType {
|
|
#[default]
|
|
Unknown = 0,
|
|
AppCreate = 1,
|
|
Todo = 2,
|
|
Monitor = 3,
|
|
Action = 4,
|
|
Schedule = 5,
|
|
Goal = 6,
|
|
Tool = 7,
|
|
Query = 8,
|
|
}
|
|
|
|
|
|
impl ToSql<SmallInt, Pg> for IntentType {
|
|
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
|
|
let v = *self as i16;
|
|
out.write_all(&v.to_be_bytes())?;
|
|
Ok(serialize::IsNull::No)
|
|
}
|
|
}
|
|
|
|
impl FromSql<SmallInt, Pg> for IntentType {
|
|
fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
|
|
let value = <i16 as FromSql<SmallInt, Pg>>::from_sql(bytes)?;
|
|
match value {
|
|
0 => Ok(Self::Unknown),
|
|
1 => Ok(Self::AppCreate),
|
|
2 => Ok(Self::Todo),
|
|
3 => Ok(Self::Monitor),
|
|
4 => Ok(Self::Action),
|
|
5 => Ok(Self::Schedule),
|
|
6 => Ok(Self::Goal),
|
|
7 => Ok(Self::Tool),
|
|
8 => Ok(Self::Query),
|
|
_ => Err(format!("Unknown IntentType: {}", value).into()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for IntentType {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Self::Unknown => write!(f, "UNKNOWN"),
|
|
Self::AppCreate => write!(f, "APP_CREATE"),
|
|
Self::Todo => write!(f, "TODO"),
|
|
Self::Monitor => write!(f, "MONITOR"),
|
|
Self::Action => write!(f, "ACTION"),
|
|
Self::Schedule => write!(f, "SCHEDULE"),
|
|
Self::Goal => write!(f, "GOAL"),
|
|
Self::Tool => write!(f, "TOOL"),
|
|
Self::Query => write!(f, "QUERY"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::str::FromStr for IntentType {
|
|
type Err = String;
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
match s.to_uppercase().as_str() {
|
|
"UNKNOWN" => Ok(Self::Unknown),
|
|
"APP_CREATE" | "APPCREATE" | "APP" | "APPLICATION" | "CREATE_APP" => Ok(Self::AppCreate),
|
|
"TODO" | "TASK" | "REMINDER" => Ok(Self::Todo),
|
|
"MONITOR" | "WATCH" | "ALERT" | "ON_CHANGE" => Ok(Self::Monitor),
|
|
"ACTION" | "DO" | "EXECUTE" | "RUN" => Ok(Self::Action),
|
|
"SCHEDULE" | "SCHEDULED" | "CRON" | "TIMER" => Ok(Self::Schedule),
|
|
"GOAL" | "OBJECTIVE" | "TARGET" => Ok(Self::Goal),
|
|
"TOOL" | "FUNCTION" | "UTILITY" => Ok(Self::Tool),
|
|
"QUERY" | "SEARCH" | "FIND" | "LOOKUP" => Ok(Self::Query),
|
|
_ => Ok(Self::Unknown),
|
|
}
|
|
}
|
|
}
|