+
     iH                     j    ^ RI Ht RtR R ltR R ltR R ltR R	 ltR
 R ltR R ltR R lt	R# )    )connectionsc                0    V ^8  d   QhR\         R\         /# )   namereturnstr)formats   "IE:\live-kit-agent\livekit_voicebot\backend\apps\cluster\dynamic_tables.py__annotate__r   +   s     * *3 *3 *    c                 .    R V P                  R R4       R 2# )`z``)replace)r   s   &r   _q_identr   +   s    t||C&'q))r   c                f    V ^8  d   QhR\         R\        \        \        \        \        3,          /# )r   bidr   )inttupler	   )r
   s   "r   r   r   /   s(     	: 	:c 	:eCc3$67 	:r   c                2    V  R2pV  R2pV  R2pV  R2pWW43# )zS
Returns:
  agents_table, bots_table, call_history_table, legacy_callhistory_table
_agents_bots_call_history_callhistory )r   agentsbotscall_historylegacy_callhistorys   &    r   _table_namesr    /   s>    
 uG_FU%=DU-(L5-99r   c                (    V ^8  d   QhR\         RR/# r   business_idr   Nr   )r
   s   "r   r   r   ;   s     P Pc Pd Pr   c                   V f   R# \        V 4      pV^ 8:  d   R# \        V4      w  r#rE\        R,          pVP                  4       ;_uu_ 4       pVP	                  R\        V4       R24       VP	                  R\        V4       R24       VP	                  R\        V4       R24       VP	                  R\        V4       R24       RRR4       R#   + '       g   i     R# ; i)zs
Drop per-business tables in the cluster DB (if they exist).
Also drops the legacy `{bid}_callhistory` table name.
NclusterzDROP TABLE IF EXISTS ;)r   r    r   cursorexecuter   )r#   r   r   r   r   r   connr(   s   &       r   drop_business_cluster_tablesr+   ;   s    
 
k
C
ax5A#5F2F,y!D	&.x/?.@BC.x~.>a@A.x/E.FaHI.x8J/K.LANO	 
s   A9CC"	c                (    V ^8  d   QhR\         RR/# r"   r$   )r
   s   "r   r   r   O   s"     Q@ Q@ Q@ Q@r   c                "   V f   R# \        V 4      pV^ 8:  d   R# \        V4      w  r#rEV R2pV R2pV R2pV R2p	R\        V4       R2p
R\        V4       R2pR\        V4       R	2pR\        V4       R
2pR\        V4       R2pR\        V4       R2pR\        V	4       R2p\        R,          pVP	                  4       ;_uu_ 4       pVP                  V
4       VP                  V4       VP                  V4       VP                  V4       VP                  V4       VP                  V4       VP                  V4       \        VV4       \        VV4       \        VV4       \        VV4       RRR4       R#   + '       g   i     R# ; i)aB  
Create per-business tables in the `cluster` database:
  {business_id}_agents
  {business_id}_bots
  {business_id}_call_history
  {business_id}_knowledgebase
  {business_id}_audit_logs
  {business_id}_campaigns
  {business_id}_campaign_contacts

These tables are created on demand when a Business is created in master DB.
N_knowledgebase_audit_logs
_campaigns_campaign_contactsz 
    CREATE TABLE IF NOT EXISTS a   (
      id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
      name VARCHAR(255) NOT NULL DEFAULT '',
      email VARCHAR(255) NOT NULL DEFAULT '',
      email_verified_at DATETIME NULL,
      password VARCHAR(255) NOT NULL DEFAULT '',
      role VARCHAR(50) NOT NULL DEFAULT 'agent',
      phone VARCHAR(64) NOT NULL DEFAULT '',
      department VARCHAR(255) NOT NULL DEFAULT '',
      status VARCHAR(50) NOT NULL DEFAULT '',
      reports_to BIGINT UNSIGNED NULL,
      last_login DATETIME NULL,
      remember_token VARCHAR(255) NULL,
      created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
      updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
      business_id BIGINT UNSIGNED NOT NULL,
      permissions JSON NULL,
      PRIMARY KEY (id),
      KEY idx_business_id (business_id),
      KEY idx_email (email)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    a
   (
      bot_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
      -- LiveKit Cloud agent IDs look like "sb_..." (string), so store as varchar.
      agent_id VARCHAR(128) NULL,
      agent_name VARCHAR(255) NULL,
      is_active TINYINT(1) NOT NULL DEFAULT 1,
      voice_name VARCHAR(255) NOT NULL DEFAULT '',
      llm_model VARCHAR(255) NOT NULL DEFAULT '',
      prompt LONGTEXT NULL,
      business_id BIGINT UNSIGNED NOT NULL,
      bot_name VARCHAR(255) NOT NULL DEFAULT '',
      default_language VARCHAR(32) NULL,
      platform_settings JSON NULL,
      concurrent_calls INT UNSIGNED NULL,
      voice JSON NULL,
      advanced_settings JSON NULL,
      conversation_behavior JSON NULL,
      extraction JSON NULL,
      detect_language TINYINT(1) NOT NULL DEFAULT 1,
      skip_turn TINYINT(1) NOT NULL DEFAULT 0,
      voicemail_detection TINYINT(1) NOT NULL DEFAULT 0,
      transfer_to_number VARCHAR(64) NULL,
      end_conversation TINYINT(1) NOT NULL DEFAULT 0,
      filler_keywords LONGTEXT NULL,
      transfer_enabled TINYINT(1) NOT NULL DEFAULT 0,
      skip_turn_prompt LONGTEXT NULL,
      detect_language_prompt LONGTEXT NULL,
      end_conversation_prompt LONGTEXT NULL,
      transfer_to_number_prompt LONGTEXT NULL,
      voicemail_detection_prompt LONGTEXT NULL,
      skip_turn_description TEXT NULL,
      detect_language_description TEXT NULL,
      end_conversation_description TEXT NULL,
      transfer_number_description TEXT NULL,
      voicemail_description TEXT NULL,
      end_conversation_timeout INT UNSIGNED NULL,
      transfer_destination_type VARCHAR(32) NULL,
      transfer_destinations JSON NULL,
      skip_turn_disable_interruptions TINYINT(1) NOT NULL DEFAULT 0,
      detect_language_disable_interruptions TINYINT(1) NOT NULL DEFAULT 0,
      end_conversation_disable_interruptions TINYINT(1) NOT NULL DEFAULT 0,
      transfer_to_number_disable_interruptions TINYINT(1) NOT NULL DEFAULT 0,
      voicemail_detection_disable_interruptions TINYINT(1) NOT NULL DEFAULT 0,
      stt_provider VARCHAR(50) NOT NULL DEFAULT 'deepgram',
      tts_provider VARCHAR(50) NOT NULL DEFAULT 'elevenlabs',
      llm_provider VARCHAR(255) NULL,
      mcube_exenumber VARCHAR(64) NOT NULL DEFAULT '',
      mcube_gid VARCHAR(64) NOT NULL DEFAULT '1',
      message_inbound LONGTEXT NULL,
      message_outbound LONGTEXT NULL,
      guardrails JSON NULL,
      system_tools JSON NULL,
      created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
      updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
      PRIMARY KEY (bot_id),
      KEY idx_business_id (business_id),
      KEY idx_agent_id (agent_id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    a%   (
      id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
      conversation_id VARCHAR(255) NULL,
      agent_id VARCHAR(128) NULL,
      transcript LONGTEXT NULL,
      conversation_data JSON NULL,
      phone_number VARCHAR(64) NULL,
      agent_phone_number VARCHAR(64) NULL,
      customer_name VARCHAR(255) NULL,
      agent_name VARCHAR(255) NULL,
      call_start_time DATETIME NULL,
      call_end_time DATETIME NULL,
      call_duration_secs INT UNSIGNED NULL,
      call_successful TINYINT(1) NULL,
      call_status VARCHAR(50) NULL,
      ongoing TINYINT(1) NOT NULL DEFAULT 0,
      transferred TINYINT(1) NOT NULL DEFAULT 0,
      status VARCHAR(50) NOT NULL DEFAULT '',
      sentiment VARCHAR(50) NULL,
      summary LONGTEXT NULL,
      recording_url LONGTEXT NULL,
      dynamic_variables JSON NULL,
      campaign_id BIGINT UNSIGNED NULL,
      business_id BIGINT UNSIGNED NOT NULL,
      created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
      updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
      PRIMARY KEY (id),
      KEY idx_business_id (business_id),
      KEY idx_conversation_id (conversation_id),
      KEY idx_agent_id (agent_id),
      KEY idx_campaign_id (campaign_id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    a#   (
      id INT NOT NULL AUTO_INCREMENT,
      doc_id VARCHAR(255) NULL,
      doc_name VARCHAR(255) NULL,
      doc_url LONGTEXT NOT NULL,
      bot_id INT NULL,
      business_id INT NULL,
      created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
      updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
      PRIMARY KEY (id),
      KEY idx_business_id (business_id),
      KEY idx_bot_id (bot_id),
      KEY idx_doc_id (doc_id)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    a   (
      id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
      timestamp DATETIME NULL,
      user_id VARCHAR(64) NOT NULL DEFAULT '',
      user_name VARCHAR(255) NOT NULL DEFAULT '',
      user_role VARCHAR(64) NOT NULL DEFAULT '',
      action VARCHAR(64) NOT NULL DEFAULT '',
      module VARCHAR(64) NOT NULL DEFAULT '',
      resource_type VARCHAR(128) NOT NULL DEFAULT '',
      resource_name VARCHAR(255) NULL,
      description TEXT NULL,
      severity VARCHAR(16) NOT NULL DEFAULT 'low',
      status VARCHAR(16) NOT NULL DEFAULT 'success',
      ip_address VARCHAR(64) NULL,
      user_agent TEXT NULL,
      business_id BIGINT UNSIGNED NOT NULL,
      created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
      PRIMARY KEY (id),
      KEY idx_business_id (business_id),
      KEY idx_timestamp (timestamp)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    a   (
      id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
      name VARCHAR(255) NOT NULL DEFAULT '',
      description TEXT NULL,
      autodailer_id BIGINT UNSIGNED NULL,
      business_id BIGINT UNSIGNED NOT NULL,
      status VARCHAR(32) NOT NULL DEFAULT 'processing',
      call_status VARCHAR(32) NOT NULL DEFAULT 'pending',
      listname VARCHAR(255) NOT NULL DEFAULT '',
      total_count INT UNSIGNED NOT NULL DEFAULT 0,
      total_calls INT UNSIGNED NOT NULL DEFAULT 0,
      successful_calls INT UNSIGNED NOT NULL DEFAULT 0,
      failed_calls INT UNSIGNED NOT NULL DEFAULT 0,
      processing_count INT UNSIGNED NOT NULL DEFAULT 0,
      pending_count INT UNSIGNED NOT NULL DEFAULT 0,
      waiting_time INT UNSIGNED NOT NULL DEFAULT 0,
      waiting_time_count INT UNSIGNED NOT NULL DEFAULT 0,
      createdon DATETIME NULL,
      start_time DATETIME NULL,
      end_time DATETIME NULL,
      did VARCHAR(64) NOT NULL DEFAULT '',
      start_date DATE NULL,
      end_date DATE NULL,
      autodailer_type VARCHAR(64) NOT NULL DEFAULT '',
      retry_attempt INT UNSIGNED NOT NULL DEFAULT 0,
      retry_time INT UNSIGNED NOT NULL DEFAULT 0,
      bot_name VARCHAR(255) NOT NULL DEFAULT '',
      exeuctive_number VARCHAR(64) NOT NULL DEFAULT '',
      refurl LONGTEXT NULL,
      run_now TINYINT(1) NOT NULL DEFAULT 0,
      batch_size INT UNSIGNED NULL,
      batch_interval INT UNSIGNED NULL,
      no_of_attempt INT UNSIGNED NULL,
      total_attempts INT UNSIGNED NULL,
      interval_time INT UNSIGNED NULL,
      automated_callbacks_enabled TINYINT(1) NOT NULL DEFAULT 0,
      pending_callbacks_count INT UNSIGNED NOT NULL DEFAULT 0,
      callback_requested TINYINT(1) NOT NULL DEFAULT 0,
      created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
      updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
      PRIMARY KEY (id),
      KEY idx_business_id (business_id),
      KEY idx_status (status)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    a   (
      id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
      business_id BIGINT UNSIGNED NOT NULL,
      campaign_id BIGINT UNSIGNED NOT NULL,
      status VARCHAR(32) NOT NULL DEFAULT 'pending',
      call_status VARCHAR(32) NOT NULL DEFAULT 'pending',
      contact_name VARCHAR(255) NOT NULL DEFAULT '',
      number VARCHAR(64) NOT NULL DEFAULT '',
      source VARCHAR(255) NOT NULL DEFAULT '',
      retry TINYINT(1) NOT NULL DEFAULT 0,
      retry_attempt INT UNSIGNED NOT NULL DEFAULT 0,
      callback_requested TINYINT(1) NOT NULL DEFAULT 0,
      callback_time DATETIME NULL,
      callback_status TINYINT(1) NOT NULL DEFAULT 0,
      callback_retry_attempts INT UNSIGNED NOT NULL DEFAULT 0,
      callback_last_attempt_time DATETIME NULL,
      callback_failure_reason TEXT NULL,
      created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
      updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
      PRIMARY KEY (id),
      KEY idx_business_id (business_id),
      KEY idx_campaign_id (campaign_id),
      KEY idx_status (status)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    r&   )	r   r    r   r   r(   r)   _ensure_bots_table_columns_ensure_agent_id_varchar _ensure_knowledgebase_timestamps)r#   r   r   r   calls_legacy_callhistoryknowledgebase
audit_logs	campaignscampaign_contacts
ddl_agentsddl_bots	ddl_callsddl_knowledgebaseddl_audit_logsddl_campaignsddl_campaign_contactsr*   r(   s   &                  r   ensure_business_cluster_tablesrB   O   s    
k
C
ax/;C/@,F%e>*M5$J%z"I%12  ( 01 2J0  (/ :0;Hz  (0  1!IF  ( 78 9"  ( 45 6N0  ( 34 ,5-M^!  (): ;< =6 y!D	&z"x y!()~&}%,-"640 . /(? 
s   B(E==F	c                (    V ^8  d   QhR\         RR/# r   tabler   Nr   )r
   s   "r   r   r   c  s     ! !C !D !r   c           	        V P                  R4       V P                  4       pV'       d   V^ ,          '       g   R# V^ ,          pRpV Fm  w  rVV P                  RW1V.4       V P                  4       pV'       g   K3  V^ ,          e   K@   V P                  R\        V4       R\        V4       RV 24       Ko  	  R#   \         d     K  i ; i)zULegacy `{bid}_knowledgebase` tables may define created_at/updated_at without DEFAULT.SELECT DATABASE()Nz
            SELECT COLUMN_DEFAULT
            FROM INFORMATION_SCHEMA.COLUMNS
            WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s
            ALTER TABLE z MODIFY COLUMN  ))
created_atz,TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP)
updated_atzHTIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP)r)   fetchoner   	Exception)r(   rE   rowdb_namefixescol_namecol_defrs   &&      r   r4   r4   c  s    
NN&'
//
Cc!ff!fGE #
 X&	
 OOQ4	NNx/x?Q>RRST[S\] #$  		s   	,B;;C
	C
c                (    V ^8  d   QhR\         RR/# rD   r   )r
   s   "r   r   r     s      c d r   c           	        V P                  R4       V P                  4       pV'       d   V^ ,          '       g   R# V^ ,          pV P                  RW1.4       V P                  4        Uu0 uF  qD^ ,          kK  	  pp\         F:  w  rgWe9   d   K   V P                  R\	        V4       R\	        V4       RV 24       K<  	  R# u upi   \
         d     KS  i ; i)zJALTER `{bid}_bots` to add API/legacy columns missing on older deployments.rG   Nzx
        SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s
        rH   z ADD COLUMN rI   )r)   rL   fetchallCLUSTER_BOTS_EXTRA_COLUMNSr   rM   )r(   rE   rN   rO   rS   existingrQ   rR   s   &&      r   r2   r2     s    
NN&'
//
Cc!ff!fG
NN	 
 %oo/0/!/H07	NNx/|HX<N;OqQXPYZ	 8 1  		s   )C,CCCc                (    V ^8  d   QhR\         RR/# rD   r   )r
   s   "r   r   r     s     % %C %D %r   c                n   V P                  R4       V P                  4       pV'       d   V^ ,          '       g   R# V^ ,          pV P                  RW1.4       V P                  4       pV'       g   R# V^ ,          ;'       g    RP                  4       pVR9   d   R#  V P                  R\        V4       R24        T P                  R\        T4       R24       T P                  4       pT'       g!   T P                  R	\        T4       R
24       R# R#   \         d     R# i ; i  \         d     R# i ; i)z~
Older deployments created agent_id as BIGINT; migrate to VARCHAR(128) so we can store
LiveKit Cloud agent IDs like "sb_...".
rG   Nz
        SELECT DATA_TYPE
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = 'agent_id'
        LIMIT 1
         rH   z) MODIFY COLUMN agent_id VARCHAR(128) NULLzSHOW INDEX FROM z  WHERE Key_name = 'idx_agent_id'zCREATE INDEX idx_agent_id ON z (agent_id))varcharchartextlongtext)r)   rL   lowerr   rM   )r(   rE   rN   rO   rS   	data_typeidxs   &&     r   r3   r3     s   
 NN&'
//
Cc!ff!fG
NN	 
 	A1""$I;;8E?++TU	

)(5/)::Z[\ooNN:8E?:K;WX     s%   D ;AD% D"!D"%D43D4N) )default_languageVARCHAR(32) NULL)stt_providerz'VARCHAR(50) NOT NULL DEFAULT 'deepgram')tts_providerz)VARCHAR(50) NOT NULL DEFAULT 'elevenlabs')llm_providerVARCHAR(255) NULL)mcube_exenumberzVARCHAR(64) NOT NULL DEFAULT '')	mcube_gidz VARCHAR(64) NOT NULL DEFAULT '1')message_inboundLONGTEXT NULL)message_outboundrl   )
guardrails	JSON NULL)system_toolsro   )filler_keywordsrl   )conversation_behaviorro   )transfer_enabledTINYINT(1) NOT NULL DEFAULT 0)skip_turn_promptrl   )detect_language_promptrl   )end_conversation_promptrl   )transfer_to_number_promptrl   )voicemail_detection_promptrl   )skip_turn_description	TEXT NULL)detect_language_descriptionr{   )end_conversation_descriptionr{   )transfer_number_descriptionr{   )voicemail_descriptionr{   )end_conversation_timeoutzINT UNSIGNED NULL)transfer_destination_typerd   )transfer_destinationsro   )skip_turn_disable_interruptionsrt   )%detect_language_disable_interruptionsrt   )&end_conversation_disable_interruptionsrt   )(transfer_to_number_disable_interruptionsrt   ))voicemail_detection_disable_interruptionsrt   )
agent_namerh   )
	django.dbr   rW   r   r    r+   rB   r4   r2   r3   r   r   r   <module>r      s9    !$ N*	:P(Q@h!H6%r   