From 9ad7c1aee9b10ff2954f6f5f3951c46cd16bfae0 Mon Sep 17 00:00:00 2001 From: Josako Date: Thu, 3 Apr 2025 14:07:23 +0200 Subject: [PATCH] Introduction of Partner Model, adding code to Tenant model --- common/models/user.py | 91 +++++++- common/utils/cache/config_cache.py | 14 +- common/utils/eveai_exceptions.py | 11 + common/utils/form_assistants.py | 11 + common/utils/log_utils.py | 57 +++++ common/utils/startup_eveai.py | 3 +- .../MANAGEMENT_SERVICE/1.0.0.yaml | 15 ++ config/type_defs/partner_service_types.py | 24 ++ .../administration/edit_partner.html | 18 ++ .../administration/edit_partner_service.html | 18 ++ .../administration/partner_service.html | 18 ++ .../administration/partner_services.html | 26 +++ .../templates/administration/partners.html | 26 +++ .../administration/trigger_actions.html | 1 + .../templates/basic/session_defaults.html | 2 +- eveai_app/templates/navbar.html | 9 + eveai_app/templates/user/edit_tenant.html | 2 +- eveai_app/templates/user/tenant.html | 2 +- eveai_app/views/administration_forms.py | 41 +++- eveai_app/views/administration_views.py | 218 +++++++++++++++++- eveai_app/views/basic_forms.py | 7 + eveai_app/views/document_forms.py | 10 +- eveai_app/views/document_views.py | 1 - eveai_app/views/dynamic_form_base.py | 2 +- eveai_app/views/user_forms.py | 4 + eveai_app/views/user_views.py | 9 +- migrations/.DS_Store | Bin 6148 -> 0 bytes migrations/public/.DS_Store | Bin 10244 -> 0 bytes .../public/__pycache__/env.cpython-312.pyc | Bin 4578 -> 0 bytes ...deef0888b_initialize_empty_tenant_codes.py | 82 +++++++ .../98adf66ce189_add_partner_models.py | 86 +++++++ ...refactor_to_flask_security.cpython-312.pyc | Bin 4008 -> 0 bytes ..._security_active_attribute.cpython-312.pyc | Bin 2838 -> 0 bytes ...dded_user_to_public_schema.cpython-312.pyc | Bin 3249 -> 0 bytes ..._adding_timezone_to_tenant.cpython-312.pyc | Bin 4390 -> 0 bytes ...471ed_2024_07_04t09_42_15z.cpython-312.pyc | Bin 3781 -> 0 bytes ...size_definition_at_tenant_.cpython-312.pyc | Bin 4628 -> 0 bytes ...18d34_2024_07_04t09_21_49z.cpython-312.pyc | Bin 3781 -> 0 bytes ..._additions_to_tenants_cors.cpython-312.pyc | Bin 2562 -> 0 bytes ...7d1a4_2024_07_04t09_43_14z.cpython-312.pyc | Bin 3781 -> 0 bytes ..._rag_context_and_fallback_.cpython-312.pyc | Bin 4764 -> 0 bytes ...d847f_2024_07_04t09_38_14z.cpython-312.pyc | Bin 3781 -> 0 bytes ...5_flask_security_trackable.cpython-312.pyc | Bin 4313 -> 0 bytes ...defined_interaction_domain.cpython-312.pyc | Bin 3793 -> 0 bytes ...needed_is_active_as_it_is_.cpython-312.pyc | Bin 4126 -> 0 bytes ...ow_for_more_than_1_api_key.cpython-312.pyc | Bin 4710 -> 0 bytes ...000cb_2024_07_04t12_47_41z.cpython-312.pyc | Bin 3781 -> 0 bytes ...ation_date_to_tenantdomain.cpython-312.pyc | Bin 3458 -> 0 bytes ...erature_variables_defaults.cpython-312.pyc | Bin 3811 -> 0 bytes ...bd574_2024_07_04t12_28_00z.cpython-312.pyc | Bin 3781 -> 0 bytes ...23ee4_2024_07_04t12_51_36z.cpython-312.pyc | Bin 3781 -> 0 bytes ...versioning_information_to_.cpython-312.pyc | Bin 4535 -> 0 bytes ...dd69_initial_public_schema.cpython-312.pyc | Bin 2248 -> 0 bytes ...urity_additions_to_tenants.cpython-312.pyc | Bin 3158 -> 0 bytes ...s_for_html_embeddings_and_.cpython-312.pyc | Bin 5471 -> 0 bytes ...d_user_to_include_is_super.cpython-312.pyc | Bin 2047 -> 0 bytes ...mbedding_search_parameters.cpython-312.pyc | Bin 4612 -> 0 bytes ...ions_to_tenants_cors_part_.cpython-312.pyc | Bin 3405 -> 0 bytes ..._language_llm_fields_added.cpython-312.pyc | Bin 4542 -> 0 bytes ...a11ec_2024_07_04t09_59_04z.cpython-312.pyc | Bin 3781 -> 0 bytes ...parameters_added_to_tenant.cpython-312.pyc | Bin 4601 -> 0 bytes ..._add_temperature_variables.cpython-312.pyc | Bin 4610 -> 0 bytes ...ce138_2024_07_04t09_36_42z.cpython-312.pyc | Bin 3781 -> 0 bytes ...s_do_not_need_to_be_unique.cpython-312.pyc | Bin 4026 -> 0 bytes ...b7ae8_2024_07_04t09_08_45z.cpython-312.pyc | Bin 3781 -> 0 bytes ...a6489_2024_07_04t09_40_45z.cpython-312.pyc | Bin 3781 -> 0 bytes ...d_tags_for_html_embeddings.cpython-312.pyc | Bin 3264 -> 0 bytes ...e3438_2024_07_04t08_18_50z.cpython-312.pyc | Bin 3781 -> 0 bytes ...32c49_2024_07_04t07_39_16z.cpython-312.pyc | Bin 3781 -> 0 bytes ...2492b_2024_07_04t09_28_42z.cpython-312.pyc | Bin 3781 -> 0 bytes .../cab899dbb213_add_code_to_tenant.py | 34 +++ migrations/tenant/.DS_Store | Bin 10244 -> 0 bytes .../tenant/__pycache__/env.cpython-312.pyc | Bin 5109 -> 0 bytes migrations/tenant/versions/.DS_Store | Bin 10244 -> 0 bytes ...mentlanguage_user_context_.cpython-312.pyc | Bin 4854 -> 0 bytes ...rmation_added_to_document_.cpython-312.pyc | Bin 1860 -> 0 bytes ...est_version_id_is_nullable.cpython-312.pyc | Bin 1126 -> 0 bytes ...rocessing_fields_added_to_.cpython-312.pyc | Bin 1900 -> 0 bytes ...60e3_embeddings_for_openai.cpython-312.pyc | Bin 1696 -> 0 bytes ...defined_interaction_domain.cpython-312.pyc | Bin 765 -> 0 bytes ...fined_interaction_domain_2.cpython-312.pyc | Bin 3476 -> 0 bytes ...ing_for_latest_version_in_.cpython-312.pyc | Bin 1361 -> 0 bytes ...ng_model_for_openai_large_.cpython-312.pyc | Bin 1487 -> 0 bytes ...orithm_information_in_the_.cpython-312.pyc | Bin 1142 -> 0 bytes ...tial_document_models_added.cpython-312.pyc | Bin 4502 -> 0 bytes ...d_question_information_to_.cpython-312.pyc | Bin 1378 -> 0 bytes ...preciation_should_be_null_.cpython-312.pyc | Bin 812 -> 0 bytes ..._information_of_chat_user_.cpython-312.pyc | Bin 1397 -> 0 bytes ...defined_interaction_domain.cpython-312.pyc | Bin 765 -> 0 bytes ...ngs_according_to_pgvector_.cpython-312.pyc | Bin 4375 -> 0 bytes ..._session_id_to_chatsession.cpython-312.pyc | Bin 1112 -> 0 bytes ...rt_for_multiple_embedding_.cpython-312.pyc | Bin 4680 -> 0 bytes requirements.txt | 3 +- 93 files changed, 823 insertions(+), 22 deletions(-) create mode 100644 common/utils/form_assistants.py create mode 100644 common/utils/log_utils.py create mode 100644 config/partner_services/MANAGEMENT_SERVICE/1.0.0.yaml create mode 100644 config/type_defs/partner_service_types.py create mode 100644 eveai_app/templates/administration/edit_partner.html create mode 100644 eveai_app/templates/administration/edit_partner_service.html create mode 100644 eveai_app/templates/administration/partner_service.html create mode 100644 eveai_app/templates/administration/partner_services.html create mode 100644 eveai_app/templates/administration/partners.html delete mode 100644 migrations/.DS_Store delete mode 100644 migrations/public/.DS_Store delete mode 100644 migrations/public/__pycache__/env.cpython-312.pyc create mode 100644 migrations/public/versions/867deef0888b_initialize_empty_tenant_codes.py create mode 100644 migrations/public/versions/98adf66ce189_add_partner_models.py delete mode 100644 migrations/public/versions/__pycache__/07c7128c166e_refactor_to_flask_security.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/08e334d64cab_flask_security_active_attribute.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/090e8ec0fcad_added_user_to_public_schema.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/0cab60b47683_adding_timezone_to_tenant.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/167d821471ed_2024_07_04t09_42_15z.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/1716099b62f0_enable_chunk_size_definition_at_tenant_.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/1751a5318d34_2024_07_04t09_21_49z.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/29c9d981a10b_security_additions_to_tenants_cors.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/2a18dab7d1a4_2024_07_04t09_43_14z.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/358bb5f8ebf1_adding_rag_context_and_fallback_.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/38b9e73d847f_2024_07_04t09_38_14z.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/3ebec5c5b065_flask_security_trackable.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/445db8db7cbc_defined_interaction_domain.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/4701b1283750_remove_unneeded_is_active_as_it_is_.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/66739292fa56_allow_for_more_than_1_api_key.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/668e4a1000cb_2024_07_04t12_47_41z.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/6a34aecee578_added_validation_date_to_tenantdomain.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/884ac7420cc5_add_temperature_variables_defaults.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/89a287bbd574_2024_07_04t12_28_00z.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/8ab72fe23ee4_2024_07_04t12_51_36z.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/92cdb9c6f6b7_added_versioning_information_to_.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/92f0bd8ddd69_initial_public_schema.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/a8c1c8e9a31a_security_additions_to_tenants.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/ac7753aa8fa3_add_tags_for_html_embeddings_and_.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/b0ac53ab9d12_changed_user_to_include_is_super.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/b7258a741c2f_add_embedding_search_parameters.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/b79748d3aaae_security_additions_to_tenants_cors_part_.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/b853a06f4bf4_language_llm_fields_added.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/cda254aa11ec_2024_07_04t09_59_04z.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/ce68bccd110e_tuning_parameters_added_to_tenant.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/d4a45bf36bfc_add_temperature_variables.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/d93eab8ce138_2024_07_04t09_36_42z.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/dde18fb96c17_tenant_domains_do_not_need_to_be_unique.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/df7bd57b7ae8_2024_07_04t09_08_45z.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/e76f189a6489_2024_07_04t09_40_45z.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/ecf1215f61da_add_tags_for_html_embeddings.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/edb5953e3438_2024_07_04t08_18_50z.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/fdc9ac232c49_2024_07_04t07_39_16z.cpython-312.pyc delete mode 100644 migrations/public/versions/__pycache__/ff206102492b_2024_07_04t09_28_42z.cpython-312.pyc create mode 100644 migrations/public/versions/cab899dbb213_add_code_to_tenant.py delete mode 100644 migrations/tenant/.DS_Store delete mode 100644 migrations/tenant/__pycache__/env.cpython-312.pyc delete mode 100644 migrations/tenant/versions/.DS_Store delete mode 100644 migrations/tenant/versions/__pycache__/217938792642_removing_documentlanguage_user_context_.cpython-312.pyc delete mode 100644 migrations/tenant/versions/__pycache__/324ed734ed9b_chunking_information_added_to_document_.cpython-312.pyc delete mode 100644 migrations/tenant/versions/__pycache__/3bc7bbed1ec6_ensure_latest_version_id_is_nullable.cpython-312.pyc delete mode 100644 migrations/tenant/versions/__pycache__/45620002ae0d_additional_processing_fields_added_to_.cpython-312.pyc delete mode 100644 migrations/tenant/versions/__pycache__/4f22dd6260e3_embeddings_for_openai.cpython-312.pyc delete mode 100644 migrations/tenant/versions/__pycache__/505b61314bba_defined_interaction_domain.cpython-312.pyc delete mode 100644 migrations/tenant/versions/__pycache__/53fee8f13cdb_defined_interaction_domain_2.cpython-312.pyc delete mode 100644 migrations/tenant/versions/__pycache__/5c67abd3b371_add_caching_for_latest_version_in_.cpython-312.pyc delete mode 100644 migrations/tenant/versions/__pycache__/5d5437d81041_add_embedding_model_for_openai_large_.cpython-312.pyc delete mode 100644 migrations/tenant/versions/__pycache__/6fbceab656a8_adding_algorithm_information_in_the_.cpython-312.pyc delete mode 100644 migrations/tenant/versions/__pycache__/83b4a2aedbf1_initial_document_models_added.cpython-312.pyc delete mode 100644 migrations/tenant/versions/__pycache__/a3f3f5eaa3de_adding_detailed_question_information_to_.cpython-312.pyc delete mode 100644 migrations/tenant/versions/__pycache__/cb01c9192dc1_interaction_appreciation_should_be_null_.cpython-312.pyc delete mode 100644 migrations/tenant/versions/__pycache__/d173cea8d204_added_timezone_information_of_chat_user_.cpython-312.pyc delete mode 100644 migrations/tenant/versions/__pycache__/e2735d216d3c_defined_interaction_domain.cpython-312.pyc delete mode 100644 migrations/tenant/versions/__pycache__/f5bbaed3a9ee_embeddings_according_to_pgvector_.cpython-312.pyc delete mode 100644 migrations/tenant/versions/__pycache__/f6ecc306055a_adding_session_id_to_chatsession.cpython-312.pyc delete mode 100644 migrations/tenant/versions/__pycache__/f88854b2ac59_full_support_for_multiple_embedding_.cpython-312.pyc diff --git a/common/models/user.py b/common/models/user.py index 561cec9..9a2b78c 100644 --- a/common/models/user.py +++ b/common/models/user.py @@ -20,6 +20,7 @@ class Tenant(db.Model): # company Information id = db.Column(db.Integer, primary_key=True) + code = db.Column(db.String(50), unique=True, nullable=True) name = db.Column(db.String(80), unique=True, nullable=False) website = db.Column(db.String(255), nullable=True) timezone = db.Column(db.String(50), nullable=True, default='UTC') @@ -99,6 +100,7 @@ class User(db.Model, UserMixin): # User Information id = db.Column(db.Integer, primary_key=True) + tenant_id = db.Column(db.Integer, db.ForeignKey('public.tenant.id'), nullable=False) user_name = db.Column(db.String(80), unique=True, nullable=False) email = db.Column(db.String(255), unique=True, nullable=False) password = db.Column(db.String(255), nullable=True) @@ -120,7 +122,6 @@ class User(db.Model, UserMixin): # Relations roles = db.relationship('Role', secondary=RolesUsers.__table__, backref=db.backref('users', lazy='dynamic')) - tenant_id = db.Column(db.Integer, db.ForeignKey('public.tenant.id'), nullable=False) def __repr__(self): return '' % self.user_name @@ -176,3 +177,91 @@ class TenantProject(db.Model): def __repr__(self): return f"" + + +class Partner(db.Model): + __bind_key__ = 'public' + __table_args__ = {'schema': 'public'} + + id = db.Column(db.Integer, primary_key=True) + tenant_id = db.Column(db.Integer, db.ForeignKey('public.tenant.id'), nullable=False, unique=True) + code = db.Column(db.String(50), unique=True, nullable=False) + + # Basic information + logo_url = db.Column(db.String(255), nullable=True) + active = db.Column(db.Boolean, default=True) + + # Versioning Information + created_at = db.Column(db.DateTime, nullable=False, server_default=db.func.now()) + created_by = db.Column(db.Integer, db.ForeignKey('public.user.id'), nullable=True) + updated_at = db.Column(db.DateTime, nullable=False, server_default=db.func.now(), onupdate=db.func.now()) + updated_by = db.Column(db.Integer, db.ForeignKey('public.user.id'), nullable=True) + + # Relationships + services = db.relationship('PartnerService', back_populates='partner') + tenant = db.relationship('Tenant', backref=db.backref('partner', uselist=False)) + + def to_dict(self): + return { + 'id': self.id, + 'tenant_id': self.tenant_id, + 'code': self.code, + 'logo_url': self.logo_url, + 'active': self.active, + 'name': self.tenant.name + } + + +class PartnerService(db.Model): + __bind_key__ = 'public' + __table_args__ = {'schema': 'public'} + + id = db.Column(db.Integer, primary_key=True) + partner_id = db.Column(db.Integer, db.ForeignKey('public.partner.id'), nullable=False) + + # Basic info + name = db.Column(db.String(50), nullable=False) + description = db.Column(db.Text, nullable=True) + + # Service type with versioning (similar to your specialist/retriever pattern) + type = db.Column(db.String(50), nullable=False) # REFERRAL, KNOWLEDGE, SPECIALIST, IMPLEMENTATION, WHITE_LABEL + type_version = db.Column(db.String(20), nullable=False, default="1.0.0") + + # Status + active = db.Column(db.Boolean, default=True) + + # Dynamic configuration specific to this service - using JSONB like your other models + configuration = db.Column(db.JSON, nullable=True) + + # For services that need to track shared resources + system_metadata = db.Column(db.JSON, nullable=True) + user_metadata = db.Column(db.JSON, nullable=True) + + # Relationships + partner = db.relationship('Partner', back_populates='services') + + # Versioning Information + created_at = db.Column(db.DateTime, nullable=False, server_default=db.func.now()) + created_by = db.Column(db.Integer, db.ForeignKey('public.user.id'), nullable=True) + updated_at = db.Column(db.DateTime, nullable=False, server_default=db.func.now(), onupdate=db.func.now()) + updated_by = db.Column(db.Integer, db.ForeignKey('public.user.id'), nullable=True) + + +class PartnerTenant(db.Model): + __bind_key__ = 'public' + __table_args__ = {'schema': 'public'} + + partner_service_id = db.Column(db.Integer, db.ForeignKey('public.partner_service.id'), primary_key=True) + tenant_id = db.Column(db.Integer, db.ForeignKey('public.tenant.id'), primary_key=True) + + # Relationship type + relationship_type = db.Column(db.String(20), nullable=False) # REFERRED, MANAGED, WHITE_LABEL + + # JSONB for flexible configuration specific to this relationship + configuration = db.Column(db.JSON, nullable=True) + + # Tracking + created_at = db.Column(db.DateTime, nullable=False, server_default=db.func.now()) + created_by = db.Column(db.Integer, db.ForeignKey('public.user.id'), nullable=True) + updated_at = db.Column(db.DateTime, nullable=False, server_default=db.func.now(), onupdate=db.func.now()) + updated_by = db.Column(db.Integer, db.ForeignKey('public.user.id'), nullable=True) diff --git a/common/utils/cache/config_cache.py b/common/utils/cache/config_cache.py index 6db4c08..2756c1f 100644 --- a/common/utils/cache/config_cache.py +++ b/common/utils/cache/config_cache.py @@ -7,7 +7,7 @@ from flask import current_app from common.utils.cache.base import CacheHandler, CacheKey from config.type_defs import agent_types, task_types, tool_types, specialist_types, retriever_types, prompt_types, \ - catalog_types + catalog_types, partner_service_types def is_major_minor(version: str) -> bool: @@ -422,7 +422,6 @@ PromptConfigCacheHandler, PromptConfigVersionTreeCacheHandler, PromptConfigTypes config_type='prompts', config_dir='config/prompts', types_module=prompt_types.PROMPT_TYPES - )) CatalogConfigCacheHandler, CatalogConfigVersionTreeCacheHandler, CatalogConfigTypesCacheHandler = ( @@ -430,7 +429,14 @@ CatalogConfigCacheHandler, CatalogConfigVersionTreeCacheHandler, CatalogConfigTy config_type='catalogs', config_dir='config/catalogs', types_module=catalog_types.CATALOG_TYPES + )) +# Add to common/utils/cache/config_cache.py +PartnerServiceConfigCacheHandler, PartnerServiceConfigVersionTreeCacheHandler, PartnerServiceConfigTypesCacheHandler = ( + create_config_cache_handlers( + config_type='partner_services', + config_dir='config/partner_services', + types_module=partner_service_types.PARTNER_SERVICE_TYPES )) @@ -459,6 +465,9 @@ def register_config_cache_handlers(cache_manager) -> None: cache_manager.register_handler(AgentConfigCacheHandler, 'eveai_config') cache_manager.register_handler(AgentConfigTypesCacheHandler, 'eveai_config') cache_manager.register_handler(AgentConfigVersionTreeCacheHandler, 'eveai_config') + cache_manager.register_handler(PartnerServiceConfigCacheHandler, 'eveai_config') + cache_manager.register_handler(PartnerServiceConfigTypesCacheHandler, 'eveai_config') + cache_manager.register_handler(PartnerServiceConfigVersionTreeCacheHandler, 'eveai_config') cache_manager.agents_config_cache.set_version_tree_cache(cache_manager.agents_version_tree_cache) cache_manager.tasks_config_cache.set_version_tree_cache(cache_manager.tasks_version_tree_cache) @@ -466,3 +475,4 @@ def register_config_cache_handlers(cache_manager) -> None: cache_manager.specialists_config_cache.set_version_tree_cache(cache_manager.specialists_version_tree_cache) cache_manager.retrievers_config_cache.set_version_tree_cache(cache_manager.retrievers_version_tree_cache) cache_manager.prompts_config_cache.set_version_tree_cache(cache_manager.prompts_version_tree_cache) + cache_manager.partner_services_config_cache.set_version_tree_cache(cache_manager.partner_services_version_tree_cache) diff --git a/common/utils/eveai_exceptions.py b/common/utils/eveai_exceptions.py index 66db901..f24f42c 100644 --- a/common/utils/eveai_exceptions.py +++ b/common/utils/eveai_exceptions.py @@ -136,3 +136,14 @@ class EveAIInvalidEmbeddingModel(EveAIException): # Construct the message dynamically message = f"Tenant with ID '{tenant_id}' has no or an invalid embedding model in Catalog {catalog_id}." super().__init__(message, status_code, payload) + + +class EveAIDoublePartner(EveAIException): + """Raised when there is already a partner defined for a given tenant (while registering a partner)""" + + def __init__(self, tenant_id, status_code=400, payload=None): + self.tenant_id = tenant_id + # Construct the message dynamically + message = f"Tenant with ID '{tenant_id}' is already defined as a Partner." + super().__init__(message, status_code, payload) + diff --git a/common/utils/form_assistants.py b/common/utils/form_assistants.py new file mode 100644 index 0000000..85064b5 --- /dev/null +++ b/common/utils/form_assistants.py @@ -0,0 +1,11 @@ +import json + +from wtforms.validators import ValidationError + + +def validate_json(form, field): + if field.data: + try: + json.loads(field.data) + except json.JSONDecodeError: + raise ValidationError('Invalid JSON format') \ No newline at end of file diff --git a/common/utils/log_utils.py b/common/utils/log_utils.py new file mode 100644 index 0000000..ccec50d --- /dev/null +++ b/common/utils/log_utils.py @@ -0,0 +1,57 @@ +import pandas as pd +from sqlalchemy import inspect +from typing import Any, List, Union, Optional + + +def format_query_results(query_results: Any) -> str: + """ + Format query results as a readable string using pandas + + Args: + query_results: SQLAlchemy query, query results, or model instance(s) + + Returns: + Formatted string representation of the query results + """ + try: + # If it's a query object, execute it + if hasattr(query_results, 'all'): + results = query_results.all() + elif not isinstance(query_results, list): + results = [query_results] + else: + results = query_results + + # Handle different types of results + if results and hasattr(results[0], '__table__'): + # SQLAlchemy ORM objects + data = [] + for item in results: + row = {} + for column in inspect(item).mapper.column_attrs: + row[column.key] = getattr(item, column.key) + data.append(row) + df = pd.DataFrame(data) + elif results and isinstance(results[0], tuple): + # Join query results (tuples) + if hasattr(results[0], '_fields'): # Named tuples + df = pd.DataFrame(results) + else: + # Regular tuples - try to get column names from query + if hasattr(query_results, 'statement'): + columns = query_results.statement.columns.keys() + df = pd.DataFrame(results, columns=columns) + else: + df = pd.DataFrame(results) + else: + # Fallback for other types + df = pd.DataFrame(results) + + # Format the output with pandas + with pd.option_context('display.max_rows', 20, 'display.max_columns', None, + 'display.width', 1000): + formatted_output = f"Query returned {len(df)} results:\n{df}" + + return formatted_output + except Exception as e: + return f"Error formatting query results: {str(e)}" diff --git a/common/utils/startup_eveai.py b/common/utils/startup_eveai.py index f333424..77107be 100644 --- a/common/utils/startup_eveai.py +++ b/common/utils/startup_eveai.py @@ -44,4 +44,5 @@ def perform_startup_invalidation(app): except Exception as e: app.logger.error(f"Error during startup invalidation: {e}") # In case of error, we don't want to block the application startup - pass \ No newline at end of file + pass + diff --git a/config/partner_services/MANAGEMENT_SERVICE/1.0.0.yaml b/config/partner_services/MANAGEMENT_SERVICE/1.0.0.yaml new file mode 100644 index 0000000..186004b --- /dev/null +++ b/config/partner_services/MANAGEMENT_SERVICE/1.0.0.yaml @@ -0,0 +1,15 @@ +version: "1.0.0" +name: "Management Service" +configuration: + admin_roles: + name: "Administrative Roles" + type: "enum" + description: "Administrative Roles that can be assigned to the partner" + required: true + allowed_values: ["Partner Admin"] + default: "Partner Admin" +metadata: + author: "Josako" + date_added: "2025-04-02" + changes: "Initial version" + description: "Initial definition of the management service" diff --git a/config/type_defs/partner_service_types.py b/config/type_defs/partner_service_types.py new file mode 100644 index 0000000..47e2b9f --- /dev/null +++ b/config/type_defs/partner_service_types.py @@ -0,0 +1,24 @@ +# config/type_defs/partner_service_types.py +PARTNER_SERVICE_TYPES = { + "REFERRAL_SERVICE": { + "name": "Referral Service", + "description": "Partner referring new customers", + }, + "KNOWLEDGE_SERVICE": { + "name": "Knowledge Service", + "description": "Partner providing catalog content", + }, + "SPECIALIST_SERVICE": { + "name": "Specialist Service", + "description": "Partner providing specialist solutions", + }, + "MANAGEMENT_SERVICE": { + "name": "Management Service", + "description": "Partner managing customer instances", + }, + "WHITE_LABEL_SERVICE": { + "name": "White Label Service", + "description": "Partner reselling under their own brand", + } +} + diff --git a/eveai_app/templates/administration/edit_partner.html b/eveai_app/templates/administration/edit_partner.html new file mode 100644 index 0000000..41e0522 --- /dev/null +++ b/eveai_app/templates/administration/edit_partner.html @@ -0,0 +1,18 @@ +{% extends "base.html" %} +{% from "macros.html" import render_field %} +{% block title %}Update Partner{% endblock %} + +{% block content_title %}Update Partner{% endblock %} +{% block content_description %}Update partner{% endblock %} + +{% block content %} +
+ {{ form.hidden_tag() }} + {% set disabled_fields = ['tenant', 'code'] %} + {% set exclude_fields = [] %} + {% for field in form %} + {{ render_field(field, disabled_fields, exclude_fields) }} + {% endfor %} + +
+{% endblock %} diff --git a/eveai_app/templates/administration/edit_partner_service.html b/eveai_app/templates/administration/edit_partner_service.html new file mode 100644 index 0000000..04207fe --- /dev/null +++ b/eveai_app/templates/administration/edit_partner_service.html @@ -0,0 +1,18 @@ +{% extends "base.html" %} +{% from "macros.html" import render_field %} +{% block title %}Register Partner Service{% endblock %} + +{% block content_title %}Register Partner Service{% endblock %} +{% block content_description %}Register Partner Service{% endblock %} + +{% block content %} +
+ {{ form.hidden_tag() }} + {% set disabled_fields = ['type'] %} + {% set exclude_fields = [] %} + {% for field in form %} + {{ render_field(field, disabled_fields, exclude_fields) }} + {% endfor %} + +
+{% endblock %} diff --git a/eveai_app/templates/administration/partner_service.html b/eveai_app/templates/administration/partner_service.html new file mode 100644 index 0000000..022a94e --- /dev/null +++ b/eveai_app/templates/administration/partner_service.html @@ -0,0 +1,18 @@ +{% extends "base.html" %} +{% from "macros.html" import render_field %} +{% block title %}Register Partner Service{% endblock %} + +{% block content_title %}Register Partner Service{% endblock %} +{% block content_description %}Register Partner Service{% endblock %} + +{% block content %} +
+ {{ form.hidden_tag() }} + {% set disabled_fields = [] %} + {% set exclude_fields = [] %} + {% for field in form %} + {{ render_field(field, disabled_fields, exclude_fields) }} + {% endfor %} + +
+{% endblock %} diff --git a/eveai_app/templates/administration/partner_services.html b/eveai_app/templates/administration/partner_services.html new file mode 100644 index 0000000..a7b77e8 --- /dev/null +++ b/eveai_app/templates/administration/partner_services.html @@ -0,0 +1,26 @@ +{% extends 'base.html' %} +{% from 'macros.html' import render_selectable_table, render_pagination %} + +{% block title %}Partner Services{% endblock %} + +{% block content_title %}Partner Services{% endblock %} +{% block content_description %}View Partner Services for active Partner{% endblock %} +{% block content_class %}
{% endblock %} + +{% block content %} +
+
+ {{ render_selectable_table(headers=["Partner Service ID", "Name", "Type"], rows=rows, selectable=True, id="retrieversTable") }} +
+
+ +
+ +
+
+
+{% endblock %} + +{% block content_footer %} + {{ render_pagination(pagination, 'document_bp.retrievers') }} +{% endblock %} \ No newline at end of file diff --git a/eveai_app/templates/administration/partners.html b/eveai_app/templates/administration/partners.html new file mode 100644 index 0000000..e9d1c94 --- /dev/null +++ b/eveai_app/templates/administration/partners.html @@ -0,0 +1,26 @@ +{% extends 'base.html' %} +{% from 'macros.html' import render_selectable_table, render_pagination %} + +{% block title %}Partners{% endblock %} + +{% block content_title %}Partners{% endblock %} +{% block content_description %}View Partners{% endblock %} +{% block content_class %}
{% endblock %} + +{% block content %} +
+
+ {{ render_selectable_table(headers=["Partner ID", "Name"], rows=rows, selectable=True, id="partnersTable") }} +
+
+ + +
+
+
+
+{% endblock %} + +{% block content_footer %} + {{ render_pagination(pagination, 'document_bp.retrievers') }} +{% endblock %} \ No newline at end of file diff --git a/eveai_app/templates/administration/trigger_actions.html b/eveai_app/templates/administration/trigger_actions.html index 8e41619..5829012 100644 --- a/eveai_app/templates/administration/trigger_actions.html +++ b/eveai_app/templates/administration/trigger_actions.html @@ -8,6 +8,7 @@
+
diff --git a/eveai_app/templates/basic/session_defaults.html b/eveai_app/templates/basic/session_defaults.html index 5e94509..2e364f5 100644 --- a/eveai_app/templates/basic/session_defaults.html +++ b/eveai_app/templates/basic/session_defaults.html @@ -9,7 +9,7 @@ {% block content %}
{{ form.hidden_tag() }} - {% set disabled_fields = ['user_name', 'user_email', 'tenant_name'] %} + {% set disabled_fields = ['user_name', 'user_email', 'tenant_name', 'partner_name'] %} {% set exclude_fields = [] %} {% for field in form %} {{ render_field(field, disabled_fields, exclude_fields) }} diff --git a/eveai_app/templates/navbar.html b/eveai_app/templates/navbar.html index b9a6b6c..7b2ef81 100644 --- a/eveai_app/templates/navbar.html +++ b/eveai_app/templates/navbar.html @@ -101,6 +101,8 @@ {'name': 'Trigger Actions', 'url': '/administration/trigger_actions', 'roles': ['Super User']}, {'name': 'Licenses', 'url': '/entitlements/view_licenses', 'roles': ['Super User', 'Tenant Admin']}, {'name': 'Usage', 'url': '/entitlements/view_usages', 'roles': ['Super User', 'Tenant Admin']}, + {'name': 'Partners', 'url': '/administration/partners', 'roles': ['Super User']}, + {'name': 'Partner Services', 'url': '/administration/partner_services', 'roles': ['Super User']}, ]) }} {% endif %} {% if current_user.is_authenticated %} @@ -123,6 +125,13 @@ {% endif %} + {% if current_user.has_roles('Super User') and 'partner' in session %} + + {% endif %} {% endif %} diff --git a/eveai_app/templates/user/edit_tenant.html b/eveai_app/templates/user/edit_tenant.html index 095c4fd..b7bc825 100644 --- a/eveai_app/templates/user/edit_tenant.html +++ b/eveai_app/templates/user/edit_tenant.html @@ -9,7 +9,7 @@ {% block content %} {{ form.hidden_tag() }} - {% set disabled_fields = ['name', 'llm_model'] %} + {% set disabled_fields = ['name', 'code', 'llm_model'] %} {% set exclude_fields = [] %} {% for field in form %} {{ render_field(field, disabled_fields, exclude_fields) }} diff --git a/eveai_app/templates/user/tenant.html b/eveai_app/templates/user/tenant.html index 77601a1..5f80c59 100644 --- a/eveai_app/templates/user/tenant.html +++ b/eveai_app/templates/user/tenant.html @@ -9,7 +9,7 @@ {% block content %} {{ form.hidden_tag() }} - {% set disabled_fields = [] %} + {% set disabled_fields = ['code'] %} {% set exclude_fields = [] %} {% for field in form %} {{ render_field(field, disabled_fields, exclude_fields) }} diff --git a/eveai_app/views/administration_forms.py b/eveai_app/views/administration_forms.py index bf58bc8..1f572ae 100644 --- a/eveai_app/views/administration_forms.py +++ b/eveai_app/views/administration_forms.py @@ -1,7 +1,46 @@ from flask import current_app from flask_wtf import FlaskForm -from wtforms.fields.simple import SubmitField +from wtforms.fields.choices import SelectField +from wtforms.fields.simple import SubmitField, StringField, BooleanField, TextAreaField +from wtforms.validators import DataRequired, Optional, Length + +from common.extensions import cache_manager +from common.utils.form_assistants import validate_json +from eveai_app.views.dynamic_form_base import DynamicFormBase class TriggerActionForm(FlaskForm): submit = SubmitField('Submit') + + +class EditPartnerForm(FlaskForm): + tenant = StringField('Tenant', validators=[DataRequired()], render_kw={'readonly': True}) + code = StringField('Code', description="Referral Code", validators=[DataRequired()], render_kw={'readonly': True}) + logo_url = StringField('Logo URL', validators=[Optional(), Length(max=255)]) + active = BooleanField('Active', validators=[DataRequired()], default=True) + + +class PartnerServiceForm(FlaskForm): + name = StringField('Name', validators=[DataRequired(), Length(max=50)]) + description = TextAreaField('Description', validators=[Optional()]) + type = SelectField('Partner Service Type', validators=[DataRequired()]) + active = BooleanField('Active', validators=[DataRequired()], default=True) + + user_metadata = TextAreaField('User Metadata', validators=[Optional(), validate_json]) + system_metadata = TextAreaField('System Metadata', validators=[Optional(), validate_json]) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + # Dynamically populate the 'type' field + types_dict = cache_manager.partner_services_types_cache.get_types() + self.type.choices = [(key, value['name']) for key, value in types_dict.items()] + + +class EditPartnerServiceForm(DynamicFormBase): + name = StringField('Name', validators=[DataRequired(), Length(max=50)]) + description = TextAreaField('Description', validators=[Optional()]) + type = StringField('Partner Service Type', validators=[DataRequired()], render_kw={'readonly': True}) + active = BooleanField('Active', validators=[DataRequired()], default=True) + + user_metadata = TextAreaField('User Metadata', validators=[Optional(), validate_json]) + system_metadata = TextAreaField('System Metadata', validators=[Optional(), validate_json]) diff --git a/eveai_app/views/administration_views.py b/eveai_app/views/administration_views.py index add2960..2f19487 100644 --- a/eveai_app/views/administration_views.py +++ b/eveai_app/views/administration_views.py @@ -1,3 +1,4 @@ +import ast import uuid from datetime import datetime as dt, timezone as tz from flask import request, redirect, flash, render_template, Blueprint, session, current_app, jsonify @@ -5,10 +6,15 @@ from flask_security import hash_password, roles_required, roles_accepted, curren from itsdangerous import URLSafeTimedSerializer from sqlalchemy.exc import SQLAlchemyError +from common.extensions import db, cache_manager +from common.models.user import Partner, Tenant, PartnerService from common.utils.celery_utils import current_celery +from common.utils.eveai_exceptions import EveAIException +from common.utils.log_utils import format_query_results +from common.utils.model_logging_utils import update_logging_information, set_logging_information from common.utils.view_assistants import prepare_table_for_macro, form_validation_failed from common.utils.nginx_utils import prefixed_url_for -from .administration_forms import TriggerActionForm +from .administration_forms import TriggerActionForm, EditPartnerForm, PartnerServiceForm, EditPartnerServiceForm administration_bp = Blueprint('administration_bp', __name__, url_prefix='/administration') @@ -35,5 +41,215 @@ def handle_trigger_action(): except Exception as e: current_app.logger.error(f"Failed to trigger usage update task: {str(e)}") flash(f'Failed to trigger usage update: {str(e)}', 'danger') + case 'register_partner': + try: + partner_id = register_partner_from_tenant(session['tenant']['id']) + return redirect(prefixed_url_for('administration_bp.edit_partner', partner_id=partner_id, )) + except EveAIException as e: + current_app.logger.error(f'Error registering partner for tenant {session['tenant']['id']}: {str(e)}') + flash('Error Registering Partner for Selected Tenant', 'danger') + return redirect(prefixed_url_for('user_bp.select_tenant')) return redirect(prefixed_url_for('administration_bp.trigger_actions')) + + +@administration_bp.route('/partner/', methods=['GET', 'POST']) +@roles_accepted('Super User') +def edit_partner(partner_id): + partner = Partner.query.get_or_404(partner_id) # This will return a 404 if no partner is found + tenant = Tenant.query.get_or_404(partner.tenant_id) + form = EditPartnerForm(obj=partner) + form.tenant.data = tenant.name + + if form.validate_on_submit(): + # Populate the user with form data + form.populate_obj(partner) + update_logging_information(partner, dt.now(tz.utc)) + db.session.commit() + flash('Partner updated successfully.', 'success') + return redirect( + prefixed_url_for('administration_bp.edit_partner', + partner_id=partner.id)) # Assuming there's a user profile view to redirect to + else: + form_validation_failed(request, form) + + return render_template('administration/edit_partner.html', form=form, partner_id=partner_id) + + +@administration_bp.route('/partners', methods=['GET', 'POST']) +@roles_accepted('Super User') +def partners(): + page = request.args.get('page', 1, type=int) + per_page = request.args.get('per_page', 10, type=int) + + query = (db.session.query( + Partner.id, + Partner.code, + Partner.active, + Partner.logo_url, + # Include all needed Partner columns here + Tenant.name.label('name') + ).join(Tenant, Partner.tenant_id == Tenant.id).order_by(Partner.id)) + + current_app.logger.debug(f'{format_query_results(query)}') + + pagination = query.paginate(page=page, per_page=per_page) + the_partners = pagination.items + + # prepare table data + rows = prepare_table_for_macro(the_partners, [('id', ''), ('name', '')]) + + # Render the catalogs in a template + return render_template('administration/partners.html', rows=rows, pagination=pagination) + + +@administration_bp.route('/handle_partner_selection', methods=['POST']) +@roles_accepted('Super User') +def handle_partner_selection(): + action = request.form['action'] + partner_identification = request.form.get('selected_row') + partner_id = ast.literal_eval(partner_identification).get('value') + partner = Partner.query.get_or_404(partner_id) + + if action == 'set_session_partner': + current_app.logger.info(f"Setting session partner: {partner.id}") + session['partner'] = partner.to_dict() + elif action == 'edit_partner': + return redirect(prefixed_url_for('administration_bp.edit_partner', partner_id=partner_id)) + + return redirect(prefixed_url_for('administration_bp.partners')) + + +@administration_bp.route('/partner_service', methods=['GET', 'POST']) +@roles_accepted('Super User') +def partner_service(): + form = PartnerServiceForm() + + if form.validate_on_submit(): + partner_id = session.get('partner_id', None) + if not partner_id: + flash('No partner has been selected. Set partner before adding services.', 'warning') + return redirect(prefixed_url_for('administration_bp.partners')) + new_partner_service = PartnerService() + form.populate_obj(new_partner_service) + set_logging_information(new_partner_service, dt.now(tz.utc)) + new_partner_service.partner_id = partner_id + + try: + db.session.add(new_partner_service) + db.session.commit() + flash('Partner Service successfully added!', 'success') + current_app.logger.info(f"Partner Service {new_partner_service.name} added successfully for {partner_id}") + # Step 2 of the creation process (depending on type) + return redirect(prefixed_url_for('administration_bp.partner_service', + partner_service_id=new_partner_service.id)) + except SQLAlchemyError as e: + db.session.rollback() + flash(f'Failed to add Partner Service: {str(e)}', 'danger') + current_app.logger.error(f"Failed to add Partner Service {new_partner_service.name} " + f"for partner {partner_id}. Error: {str(e)}") + return render_template('administration/partner_service.html', form=form) + + +@administration_bp.route('/partner_service/', methods=['GET', 'POST']) +@roles_accepted('Super User') +def edit_partner_service(partner_service_id): + partner_service = PartnerService.query.get_or_404(partner_service_id) + partner_id = session.get('partner_id', None) + + form = EditPartnerServiceForm(obj=partner_service) + partner_service_config = cache_manager.partner_services_config_cache.get_config(partner_service.type, + partner_service.type_version) + configuration_config = partner_service_config.get('configuration') + current_app.logger.debug(f"Configuration config for {partner_service.type} {partner_service.type_version}: " + f"{configuration_config}") + form.add_dynamic_fields("configuration", configuration_config, partner_service.configuration) + + if form.validate_on_submit(): + form.populate_obj(partner_service) + partner_service.configuration = form.get_dynamic_data('configuration') + + # update partner relationship + partner_service.partner_id = partner_id + + update_logging_information(partner_service, dt.now(tz.utc)) + + try: + db.session.add(partner_service) + db.session.commit() + flash('Partner Service updated successfully.', 'success') + current_app.logger.info(f"Partner Service {partner_service.name} updated successfully! ") + except SQLAlchemyError as e: + db.session.rollback() + flash(f'Failed to update Partner Service: {str(e)}', 'danger') + current_app.logger.error(f"Failed to update Partner Service {partner_service.id} for partner {partner_id}. " + f"Error: {str(e)} ") + return render_template('administration/edit_partner_service.html', form=form, + partner_service_id=partner_service_id) + + return redirect(prefixed_url_for('administration_bp.partner_services')) + else: + form_validation_failed(request, form) + + return render_template('administration/edit_partner_service.html', form=form, + partner_service_id=partner_service_id) + + +@administration_bp.route('/partner_services', methods=['GET', 'POST']) +@roles_accepted('Super User') +def partner_services(): + page = request.args.get('page', 1, type=int) + per_page = request.args.get('per_page', 10, type=int) + partner_id = session.get('partner_id', None) + if not partner_id: + flash('No partner has been selected. Set partner before adding services.', 'warning') + return redirect(prefixed_url_for('administration_bp.partners')) + + query = PartnerService.query.filter(PartnerService.partner_id == partner_id) + + pagination = query.paginate(page=page, per_page=per_page) + the_partner_services = pagination.items + + # prepare table data + rows = prepare_table_for_macro(the_partner_services, [('id', ''), ('name', ''), ('type', '')]) + + return render_template('administration/partner_services.html', rows=rows, pagination=pagination) + + +@administration_bp.route('/handle_partner_service_selection', methods=['POST']) +@roles_accepted('Super User') +def handle_partner_service_selection(): + action = request.form['action'] + if action == 'create_partner_service': + return redirect(prefixed_url_for('administration_bp.partner_service')) + + partner_service_identification = request.form.get('selected_row') + partner_service_id = ast.literal_eval(partner_service_identification).get('value') + + if action == 'edit_partner_service': + return redirect(prefixed_url_for('administration_bp.edit_partner_service', + partner_service_id=partner_service_id)) + + return redirect(prefixed_url_for('administration_bp.partner_services')) + + +def register_partner_from_tenant(tenant_id): + # check if there is already a partner defined for the tenant + partner = Partner.query.filter_by(tenant_id=tenant_id).first() + if partner: + return partner.id + + try: + partner = Partner( + tenant_id=tenant_id, + code=f"PART-{str(uuid.uuid4())}", + ) + set_logging_information(partner, dt.now(tz.utc)) + db.session.add(partner) + db.session.commit() + return partner.id + except SQLAlchemyError as e: + db.session.rollback() + raise EveAIException(f"Failed to register partner for tenant {tenant_id}. Error: {str(e)}") + + diff --git a/eveai_app/views/basic_forms.py b/eveai_app/views/basic_forms.py index 62c467e..47ec19f 100644 --- a/eveai_app/views/basic_forms.py +++ b/eveai_app/views/basic_forms.py @@ -18,6 +18,9 @@ class SessionDefaultsForm(FlaskForm): tenant_name = StringField('Tenant Name', validators=[DataRequired()]) default_language = SelectField('Default Language', choices=[], validators=[DataRequired()]) + # Partner Defaults + partner_name = StringField('Partner Name', validators=[DataRequired()]) + # Default Catalog - initialize as a regular SelectField catalog = SelectField('Catalog', choices=[], validators=[Optional()]) @@ -28,6 +31,10 @@ class SessionDefaultsForm(FlaskForm): self.user_name.data = current_user.user_name self.user_email.data = current_user.email self.tenant_name.data = session.get('tenant').get('name') + if session.get('partner', None): + self.partner_name.data = session.get('partner').get('name') + else: + self.partner_name.data = "" self.default_language.choices = [(lang, lang.lower()) for lang in session.get('tenant').get('allowed_languages')] self.default_language.data = session.get('default_language') diff --git a/eveai_app/views/document_forms.py b/eveai_app/views/document_forms.py index 0392c0f..f120514 100644 --- a/eveai_app/views/document_forms.py +++ b/eveai_app/views/document_forms.py @@ -10,21 +10,13 @@ from wtforms_sqlalchemy.fields import QuerySelectField from common.extensions import cache_manager from common.models.document import Catalog +from common.utils.form_assistants import validate_json from config.type_defs.catalog_types import CATALOG_TYPES from config.type_defs.processor_types import PROCESSOR_TYPES -from config.type_defs.retriever_types import RETRIEVER_TYPES from .dynamic_form_base import DynamicFormBase -def validate_json(form, field): - if field.data: - try: - json.loads(field.data) - except json.JSONDecodeError: - raise ValidationError('Invalid JSON format') - - class CatalogForm(FlaskForm): name = StringField('Name', validators=[DataRequired(), Length(max=50)]) description = TextAreaField('Description', validators=[Optional()]) diff --git a/eveai_app/views/document_views.py b/eveai_app/views/document_views.py index ce676a1..f1e89ef 100644 --- a/eveai_app/views/document_views.py +++ b/eveai_app/views/document_views.py @@ -29,7 +29,6 @@ from common.utils.view_assistants import form_validation_failed, prepare_table_f from .document_list_view import DocumentListView from .document_version_list_view import DocumentVersionListView from config.type_defs.catalog_types import CATALOG_TYPES -from config.type_defs.retriever_types import RETRIEVER_TYPES document_bp = Blueprint('document_bp', __name__, url_prefix='/document') diff --git a/eveai_app/views/dynamic_form_base.py b/eveai_app/views/dynamic_form_base.py index e1078bd..32fda28 100644 --- a/eveai_app/views/dynamic_form_base.py +++ b/eveai_app/views/dynamic_form_base.py @@ -63,7 +63,7 @@ class DynamicFormBase(FlaskForm): # Required validator if field_def.get('required', False): - validators_list.append(validators.InputRequired()) + validators_list.append(validators.DataRequired()) else: validators_list.append(validators.Optional()) diff --git a/eveai_app/views/user_forms.py b/eveai_app/views/user_forms.py index 8396302..44c780a 100644 --- a/eveai_app/views/user_forms.py +++ b/eveai_app/views/user_forms.py @@ -11,6 +11,7 @@ from config.type_defs.service_types import SERVICE_TYPES class TenantForm(FlaskForm): name = StringField('Name', validators=[DataRequired(), Length(max=80)]) + code = StringField('Code', validators=[DataRequired()], render_kw={'readonly': True}) type = SelectField('Tenant Type', validators=[Optional()], default='Active') website = StringField('Website', validators=[DataRequired(), Length(max=255)]) # language fields @@ -125,3 +126,6 @@ class EditTenantProjectForm(FlaskForm): super().__init__(*args, **kwargs) # Initialize choices for the services field self.services.choices = [(key, value['description']) for key, value in SERVICE_TYPES.items()] + + + diff --git a/eveai_app/views/user_views.py b/eveai_app/views/user_views.py index ae8fd3f..45295b7 100644 --- a/eveai_app/views/user_views.py +++ b/eveai_app/views/user_views.py @@ -8,7 +8,7 @@ from itsdangerous import URLSafeTimedSerializer from sqlalchemy.exc import SQLAlchemyError import ast -from common.models.user import User, Tenant, Role, TenantDomain, TenantProject +from common.models.user import User, Tenant, Role, TenantDomain, TenantProject, Partner from common.extensions import db, security, minio_client, simple_encryption from common.utils.security_utils import send_confirmation_email, send_reset_email from config.type_defs.service_types import SERVICE_TYPES @@ -18,6 +18,8 @@ from common.utils.database import Database from common.utils.view_assistants import prepare_table_for_macro, form_validation_failed from common.utils.simple_encryption import generate_api_key from common.utils.nginx_utils import prefixed_url_for +from common.utils.eveai_exceptions import EveAIDoublePartner, EveAIException +from common.utils.document_utils import set_logging_information, update_logging_information user_bp = Blueprint('user_bp', __name__, url_prefix='/user') @@ -36,6 +38,10 @@ def log_after_request(response): @roles_required('Super User') def tenant(): form = TenantForm() + if request.method == 'GET': + code = f"TENANT-{str(uuid.uuid4())}" + form.code.data = code + if form.validate_on_submit(): # Handle the required attributes new_tenant = Tenant() @@ -244,6 +250,7 @@ def handle_tenant_selection(): return redirect(prefixed_url_for('user_bp.tenant_overview')) case 'new_tenant': return redirect(prefixed_url_for('user_bp.tenant')) + # Add more conditions for other actions return redirect(prefixed_url_for('select_tenant')) diff --git a/migrations/.DS_Store b/migrations/.DS_Store deleted file mode 100644 index 7c27f817c4e3704d21a6b133bcd4588f56a956d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKKX21O6o1#a!Jz_02&76~PGXI~$zJ!XcqSZa=-S2$wz5DZfx;q~Lu)#d;0<;0ZMJ04@WAPUu zJL!gO>6W{QO!kq$_(dwlQ7WPhZ`)uQunhcf4A9T<^9_vkHumj=6O7mv4JwUtyXK)-diqvUa#Nb`(AI=;mdBnzu)2A zp7&(6YPk;{K0bIg`j}?9_$((5438)&cQjtWDOQYSrAOUhEV4p6G!8$l+cPm7>Sep> zIY0Yx?>o_C^pT19pFYKLZJcdR!x?>?1k*ef`4P6$+?!Cs1ab&b%i1wZY5Iz4rm5z8 zlhRaMmXRhl&DJTZr|FB+`E|0V(^TuDo~Fxuj5IY~;xJ|^*3v}w>mhnWxI5Qlx^|Y9 z0n5M@GC=18M0>P6N9O6Z0Fj~ z*H|f3;lT9cgXxi(exWcqI`+?{J1}3NEiD6<0h57-`fStv|NQdzzZqn|ECZH-8^r)~ zhQV-vOVW4i#^UI%<*0|KB;;2qlp$E?>sVIkD&9qvf;LVSL|EbZ diff --git a/migrations/public/.DS_Store b/migrations/public/.DS_Store deleted file mode 100644 index 6b5d62d0110d184d454d175adf9055e62c5f4561..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10244 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 diff --git a/migrations/public/versions/867deef0888b_initialize_empty_tenant_codes.py b/migrations/public/versions/867deef0888b_initialize_empty_tenant_codes.py new file mode 100644 index 0000000..8654230 --- /dev/null +++ b/migrations/public/versions/867deef0888b_initialize_empty_tenant_codes.py @@ -0,0 +1,82 @@ +"""Initialize empty Tenant codes + +Revision ID: 867deef0888b +Revises: cab899dbb213 +Create Date: 2025-04-03 09:01:20.446536 + +""" +from alembic import op +import sqlalchemy as sa +import uuid +from sqlalchemy.sql import table, column, select, or_ +from sqlalchemy.orm import Session + + +# revision identifiers, used by Alembic. +revision = '867deef0888b' +down_revision = 'cab899dbb213' +branch_labels = None +depends_on = None + + +def upgrade(): + # Create a reference to the tenant table + tenant_table = table('tenant', + column('id', sa.Integer), + column('code', sa.String(50)), + schema='public' # Assuming the table is in the 'public' schema + ) + + # Get a connection + connection = op.get_bind() + session = Session(bind=connection) + + try: + # Find all tenants with empty or null code + # Note the updated select syntax for SQLAlchemy 2.0 + query = select(tenant_table.c.id).where( + or_( + tenant_table.c.code == None, + tenant_table.c.code == '' + ) + ) + + results = connection.execute(query) + + # Update each tenant with a UUID-based code + for row in results: + tenant_id = row[0] + code = f"TENANT-{str(uuid.uuid4())}" + + # Update the tenant record + update_stmt = tenant_table.update().where( + tenant_table.c.id == tenant_id + ).values( + code=code + ) + + connection.execute(update_stmt) + + # Commit changes + session.commit() + + # Log how many records were updated + count_query = select(sa.func.count()).select_from(tenant_table).where( + tenant_table.c.code.like('TENANT-%') + ) + + updated_count = connection.execute(count_query).scalar() + + print(f"Updated {updated_count} tenant records with UUID-based codes") + + except Exception as e: + session.rollback() + print(f"Error updating tenant codes: {str(e)}") + raise e + finally: + session.close() + + +def downgrade(): + # No downgrade needed for this data migration + pass \ No newline at end of file diff --git a/migrations/public/versions/98adf66ce189_add_partner_models.py b/migrations/public/versions/98adf66ce189_add_partner_models.py new file mode 100644 index 0000000..1d42be3 --- /dev/null +++ b/migrations/public/versions/98adf66ce189_add_partner_models.py @@ -0,0 +1,86 @@ +"""Add Partner Models + +Revision ID: 98adf66ce189 +Revises: 03a1e7633c01 +Create Date: 2025-03-31 14:43:06.833648 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '98adf66ce189' +down_revision = '03a1e7633c01' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('partner', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('tenant_id', sa.Integer(), nullable=False), + sa.Column('code', sa.String(length=50), nullable=False), + sa.Column('logo_url', sa.String(length=255), nullable=True), + sa.Column('active', sa.Boolean(), nullable=True), + sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False), + sa.Column('created_by', sa.Integer(), nullable=True), + sa.Column('updated_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False), + sa.Column('updated_by', sa.Integer(), nullable=True), + sa.ForeignKeyConstraint(['created_by'], ['public.user.id'], ), + sa.ForeignKeyConstraint(['tenant_id'], ['public.tenant.id'], ), + sa.ForeignKeyConstraint(['updated_by'], ['public.user.id'], ), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('code'), + sa.UniqueConstraint('tenant_id'), + schema='public' + ) + op.create_table('partner_service', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('partner_id', sa.Integer(), nullable=False), + sa.Column('name', sa.String(length=50), nullable=False), + sa.Column('description', sa.Text(), nullable=True), + sa.Column('type', sa.String(length=50), nullable=False), + sa.Column('type_version', sa.String(length=20), nullable=False), + sa.Column('active', sa.Boolean(), nullable=True), + sa.Column('configuration', sa.JSON(), nullable=True), + sa.Column('system_metadata', sa.JSON(), nullable=True), + sa.Column('user_metadata', sa.JSON(), nullable=True), + sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False), + sa.Column('created_by', sa.Integer(), nullable=True), + sa.Column('updated_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False), + sa.Column('updated_by', sa.Integer(), nullable=True), + sa.ForeignKeyConstraint(['created_by'], ['public.user.id'], ), + sa.ForeignKeyConstraint(['partner_id'], ['public.partner.id'], ), + sa.ForeignKeyConstraint(['updated_by'], ['public.user.id'], ), + sa.PrimaryKeyConstraint('id'), + schema='public' + ) + op.create_table('partner_tenant', + sa.Column('partner_service_id', sa.Integer(), nullable=False), + sa.Column('tenant_id', sa.Integer(), nullable=False), + sa.Column('relationship_type', sa.String(length=20), nullable=False), + sa.Column('configuration', sa.JSON(), nullable=True), + sa.Column('created_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False), + sa.Column('created_by', sa.Integer(), nullable=True), + sa.Column('updated_at', sa.DateTime(), server_default=sa.text('now()'), nullable=False), + sa.Column('updated_by', sa.Integer(), nullable=True), + sa.ForeignKeyConstraint(['created_by'], ['public.user.id'], ), + sa.ForeignKeyConstraint(['partner_service_id'], ['public.partner_service.id'], ), + sa.ForeignKeyConstraint(['tenant_id'], ['public.tenant.id'], ), + sa.ForeignKeyConstraint(['updated_by'], ['public.user.id'], ), + sa.PrimaryKeyConstraint('partner_service_id', 'tenant_id'), + schema='public' + ) + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + + op.drop_table('partner_tenant', schema='public') + op.drop_table('partner_service', schema='public') + op.drop_table('partner', schema='public') + # ### end Alembic commands ### diff --git a/migrations/public/versions/__pycache__/07c7128c166e_refactor_to_flask_security.cpython-312.pyc b/migrations/public/versions/__pycache__/07c7128c166e_refactor_to_flask_security.cpython-312.pyc deleted file mode 100644 index 5408f19c3e848b455b1eaa994bba5d7099290eb5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4008 zcmc&1OKcn0ahF_@OHvf|b7bpd)3MuzN+gQ3B`d5@KoVt?wq+TP(o}Mi#ggw)UTL|@ zyj{v+&;mA4pgr{9AOS3+2CSn35v>dxu#dX5FwhGHZ);=QTYK@%sS_CRrJc9j6<0O| zrAUD;vGeB5%$pg`JkAXN9EpS&c&dx#!XJVR^AEal9*>PY9|PnDgO~*dvB)E{MbCnV zrMOr2E^vrj@FCxVA9)u7@bbw2D`p{x0suo5Z=CMIFa70MfD4 zaO&jX@X5i{NGy3Oojj3FjSYd{UMv%A4ZBVQ5xK1?F=yUO{#MMtZ z5c#Wt4clkLe`l@1eYA%5)!O2C&{&bj@x-OQwZV5VsR312$ovyZdh|L#GnIUR> zm}5+m(by|cV&@qaJ{9Iu?>uvbjUPF0azvG}>5T-@r8erE*S|@?U|FmcNXPq8X+NHKD9wqL~4@2of>_lnTga zt@Q&#bU#EHQxoq^O=PC2byY!F#yZ{+qNk}4M-ekp0JVzrNm(jLusS#L9W)Dt zWn3{s1(jfFQ2`u$^68Zl7EFI#$PDfXgS9BZ1xzrUwH@arO%PF0QcQ|zQ?bz^Etqs2b<@_OQD)C|@VvmZ>IoJk4EL_6G)(SA&#qM-aY>i?P|M?B|8}r{wXi;C1XItLfNx;)@)N%8G2gq*_uiVkoxPb| zQ}2=cl{=M(UgOlc+6NyReIFV8$Cglhn~$#_-#k(qo-p`Hixk`DW3{8B59AsjGx)O> z?btSdY%R0?*5;+nnXSy$XzfzI#ve0yWO4hp`M%W!gMVwU-6eyMzlefsFQ|WCQ}9xY zK=S_NpB((@xcA|>FY62J8kk^atPf1ThgPxwzywXjqHW+@b*bKd1Y?kk(?x*jh?~Xq#*Mz*$hYTKDg~3&j zmhQcIf8fr*-FF`1+Q&JgFYlC+?;=AB)LPg2hgN+`@6@N-@pm7LZ7pwoRC|BEHV5VC zlEt#6e{M;SHY${0@Po7_4Smx=i}=j7nd^h={9o#=g6@8}cJQy5PQLd)vVOO1}f zt5f6CVecQqzUi(&JZuI80jYUGFax5Di#aJ@pAJIWC$cEhL8xM-!{mwmchro~_(GGb z|2s7!IU*|1-(lRsvId#KC9EJ#P!+4g5t@UqnCAc)D?cy!@uG^#GX4q40FAb3Ed}72 zmu1_2NT BNC*G` diff --git a/migrations/public/versions/__pycache__/08e334d64cab_flask_security_active_attribute.cpython-312.pyc b/migrations/public/versions/__pycache__/08e334d64cab_flask_security_active_attribute.cpython-312.pyc deleted file mode 100644 index 49a283c93a3b718499ef93cb895902956930b638..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2838 zcmb_eO>7%Q6rT0puGeW4!YF|-hg~X{aV1`w6T2-x>IO87AkR4lj$g*$iVRYhMuqmxvgrj3H6q>S_`krczA>15s@qWB?MP3vhb zE6v8Iq@f8iIvT~}(Ug+3SBO3(jgllujitttL*rv&j1t8lQXI&XG%_?2Ju?(NGcqX+ z4^2g*Q=?;N$A+UL;}fFzCktVaGhJHlvKef&Yz7-Grkqf%mmjDbo}ITL19y?Z)fSg( z8L0{24Ou`XSJ7D+L!Y5f(UP}8!C|o*drID#9(S0Q?*%QW%E5sV=CQEAVLv<~4wQmL zpRHrrZN4LfTbl0xYw)Xk_L6u*P2y!4J1~quO|TTKarHNDZCG!q%WGWGVQ{$AR%Eq+ zQFQ8XXztoyF?SufvzCd{k)l&8_?{2sp@90)Fw(hO@U7oO9Q?lc^0xaXy2Txo7mzI< zJbKv-P)#MeoYx7}A8@8mPc4#+VjgP{%Z!)PSe{=d1yh{YC`m75fd_rBQOFVbd39!M zU){qto4jMfbfvNB%jJ`5I%V>)nU7*K@r#2lvz3y0LP^$;o%01Pi-}4MVtSZ4lXr}o zKD!&QK$8gBys9cmFyCRV8YHWLg_@&2dv5yo<%1mUgu)C8l$FSAODaZcQC3s~{532? zt(a;#Ii+QFgDUB)VYa8N)|H*0Wh(;;#-O9-Gg;H6E2b}I^ZW%3VpXz`7Qr^H<#hHD zNPAyJt}z{=N8Z04i(VR$ha+(~DXHC#yrb#LvNoVgakA=6A{ST5%xol1a;jFyKvp7{ ztP)krS$rnFKotYfM~~QvjI2WKta&3~$QFvpH58NWyvh40b~aaltmeQLCUgM2?0`q_ z1%KDjAO64-fA5yRcRjNaulgsqk;j|oHg7x?!cPQgOOPrj&y~+t1gR=~aHy<*OX$BB zzkhmTa^tPCXLGf3U9K$Y6`{W>7}lo$QrPvg6Q2c<7<4?Dzkj9bAK6B3FX1*8Ed$+K zLiaZpzMcJg_TJ+6t{=pQ;&;KaQSEuJDqL!CYkX6+Tz$9k)HgQfHZGOpC z^31e-z;1{gZ->3N8>}zv>Bk{W>odn=)9#|r~#;3^nf2QEF5ZreAr({s)LyF5^NQlU~99xo~xqBaCN%YiKJYVJ7uj5Jh{LppTK)fS3UXo*4AdQy{V7 zg`Q@MeyrWf+U@)%%=_6g6#cn&t~b$u(?hJA?{(h)*y@m}{SK*|n%tZyFPA^5T)kPj zlBf!E)>6-w(6fG{Dx7A`GVn~Sw`UzFRvLlgfaya|n=bnvAAcOETuW50&Q<0$t0i*{ z?lf0mFtK9w=?b?S0GC+%4(#oUb@86gQonvK*6#jsWTq?D=YG`gjdk;n`n<6LelTG2 zvW&HqEStQdl1wt4vTp}bUr`m6-G&8vlI2&R&c8l0#4;_{r%9@0;Ua;%h^V?LVv-|S ztjk)~!d1$u@c``rMOLNug!35<=T$OIqacG4A)PVXZjR&ra``yVKP`ys`W1C;3n+ME gO?VpaTMIo6cLE8ut%-m80vzFXqyV?V(NWm=FHAF*n*aa+ diff --git a/migrations/public/versions/__pycache__/090e8ec0fcad_added_user_to_public_schema.cpython-312.pyc b/migrations/public/versions/__pycache__/090e8ec0fcad_added_user_to_public_schema.cpython-312.pyc deleted file mode 100644 index 98424bccb643e8eaf8c9d8ed366f1cdd489be8e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3249 zcmcguO>7iZ9G{te`!(II1qxd!nvtM&pmetjLU%=!c5Sl70^viG66NMyidZ9PP4FI+Z?rFm?D~IxY1d&8AY> z{#4(gOe&K}i{b<3zRVNBtehe-KQf8=5sR%bonII21N2)JX*Q-goA;QPyli*``iHz7 z^rn}n{Kf_aA3w5@%W(@Wl26K6jrEc+u+Z`Xg2mthaJfF6r&$j9`2Vlvu+MUAeI#t= z#Y|&~EU-+|=F@muEKwi7-PQ2-P+V;DWoWagv1g#hp9{79g`mFl4Ake#K*tL~-R48> z@UN3Qe!TwMH@*Hlwj8l@%Mo|_5Vvnh)Vq9$|8j!i=JS~FA#Tmebomhf`&sXNGEcCp z#KV_M{6g!t_2KV&igegJ_dYpxgKuaswn@3DCkJ;gb}#I7VR)|2$$L%_z#cFn7M=G8 zDylshG|a1S%EPii+9|7sumaJzTGee5F{-+*j_HVq)e59f6_Y1|24xy9qOUwJlS#_vwNGw+)OC86Q^LQBs65|)iO289_RB~84+NkYc>hz4I7oHU!ik0 z){GJf51OWqRD%E}Njis3jI@$*64i%H!?Lle88+!WgSE1X>+7i<7Yyx66|KqL;Z~_P z+@qVx51DmjB~O1eba*ta^e1!Jtc;o0k|U<2UN(CyDTivUN%H*~I+0K2P(?TEWtxg4 zL^Y(F6=z)5N?5gNQDPs$JgPjSD1(5I)bpT05t6CLEQ=RebD2j@;UPR@*ewfF0uFMGb}S;>wpUnn%e z#m!5=TZ7XhH%C7IVE(Np==bz4&!*=xjm-RDvpaeB^(J`FW0Y>;>H5w3e4v@=U8*+0 zJ09cG?A|%KAsW{GukS7;{-?lBV~-No)9!v`3XnZ^fcN21WY zYPdVBpU&AXv)IM%?y%A8qc`68qU(FG-%*j$bZq?)@&MYWv(=n_X#R-L8ZAiC>2vG$Y&{9mp+2WXavBAklkz-{OR&{h7XDF9d zvKC9x!vN3ozX~B9{NB#-i66Pd!w47KJr%j%@#<9ken%(m;@hUg-$DsKw0cC~4>(c$ E4ej-a<^TWy diff --git a/migrations/public/versions/__pycache__/0cab60b47683_adding_timezone_to_tenant.cpython-312.pyc b/migrations/public/versions/__pycache__/0cab60b47683_adding_timezone_to_tenant.cpython-312.pyc deleted file mode 100644 index 551e05a189a54300d14b530a8f241a6d64e89359..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4390 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‰?f>!;1 z4SVSok?d|tlXIk4QREa-bSy%YM>(iVYR=5_8ofdf!3vSUyke`uU{-}w3L4U4WQ>+6 zdX$J|mSLEu4j1G6dk1k#r8I3Od E59nKCIsgCw diff --git a/migrations/public/versions/__pycache__/29c9d981a10b_security_additions_to_tenants_cors.cpython-312.pyc b/migrations/public/versions/__pycache__/29c9d981a10b_security_additions_to_tenants_cors.cpython-312.pyc deleted file mode 100644 index 93e5d9efe554dffe55c728668a89b85ecc652719..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2562 zcmb_eO>7fK6rS;Vy+5%N8z=!P=+dCJX$y`+g5ne*MQaYU0xEuslWMiznFNQm*V$bM zTooyY9(ylGj-dDu^%V8wHW#E`Hc}+e_Sjx}OB>oqQ4f8yyNOL=N)8=sznz~qZ{C}k z?_2+zO34UHbEZB$D^tH zfJY>WZ%|Pp0-)UB2F0%)UZ+OgF1rn7f{?OXwyKWeTFMPt)vK z8#V$pV~f$qD0+y#Mzef}K~yCii8uLeJN!DU#2za+nB9dSA`o!~6A2!f^fZ%;iO?qS z+kHlg^md;C-r(1c><#&*_L*cjeZ0HBfx`a5gID|>+cK%6)g5X(PqCkHjJvd=`$syugF&rKwCQ`a;mgyOP0KS? zsDnN4HfmIR)tpV;F^{vBFGPKQtW5kwtzI(AhA*fS*VT!_#le{0XVYnF)2gdQ>x)*E zP?NgUkF(Hxfgw2c4+a%CAji%kiLmWUJN<*$J_HB;G;Xtd>Ss#2Yuwdz(*-ZCUV@PN zh;7w01K8%;db#TQ2aJF-T9ls_CMbq8t(wCwxw7>rd&@HG73yTK-d0C04{Nz>0UVXA z2iZ?8N55yi?QqDKG)Z zb`nu@B7xBKZGq5SOAB*#AO+hwQ)|E$)xaI0_PY@1L3o^h02a`1QqObg_^NdLQDv#H zCgs;roUh~MFJ6f0=c2MID&EOYTIW4cSrb2hZQsDEIPkdeNRG5m$=MrGHzD3@)h%w2Rgw(j zCaGp`TbN#xXCHhB(%tO$A!G}05VFh_`!MXA&Cb#8VUT3N&fh-D;247p1D1;2%b<@z zngL@AD8^f?&OZ2dKZCa!yaNzY-#!UdUn181YRI!w&}Lk7{s!peS^IWRb>8mBhn`FY zmwSBYa(k!p%VVv3tuMWscf1?LHF1*N>?!bdy#}Wh0bh*_ktSlYMC#e$3H*(T@J!_$ju%TDw`Y^(qLr zsh6nf_%fk2S|yHVRRfi?*%3TN8-OS{o-Ofw#Ugc+Ua+&!$0XYs0a)iS#(%^TIQ~~J q!u`LX{&f*0k1dEV(kB*DFVcqqQkez$&xDLA-Z&xSIc%SSiT?sXEMg%5 diff --git a/migrations/public/versions/__pycache__/2a18dab7d1a4_2024_07_04t09_43_14z.cpython-312.pyc b/migrations/public/versions/__pycache__/2a18dab7d1a4_2024_07_04t09_43_14z.cpython-312.pyc deleted file mode 100644 index e66e314d6ace656d2d393c4dbe8a1ecfa2fe2371..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3781 zcmb_fO>7fK6rS~Zz3YvgI6n|Vlh!CSU|QnXIKM<`L+q-wf>v#S;sjP}&jbu>ue0j} zOsSMZ)k8(4-r&d)lvMJehurG^M2ghQB1HmikL{(m(9l}Sq3X=;#@^Ttn2L?|dFIWV z_cycOd->Jt5&hww3#gv+oGyc=j zF@IPLjX*Im3`1hXTtVuXKQuH9N5Y}Va0o$uNlP z7sT7rV7$JXNa|&!wIQjt8mam*vao$8#+8m`%ieQxvJdWmDR~xl){}q946+So@IZr6 z?-50{S9#D2LO`W%;1Bj9pzzJ@Zw(o_jF8;SO&C2ZN}>Rhu_MtCHd2hjxv%_DT%dY3?uekerxjv0d^IQ)W80 zOTLQKw)!SM$a|Aru|E1I-zi5dO#c#kJ2pYD^)ay^yB20*C)u?L<~^3(Rc|@G%c!@G zS6OcXq*t7ks)nm_y_&&57i2M}<7&F>#D3rhw=*wS5#0^qd96qFD&qf@suvxPyOXBs z==R8j2g`aJlx=fkdQYB=^}(&38k43 zA0Y&0aY5Qg#-!C(_7l=c$RR?=*K3vv

_?ZYbZ#m?(V=&&jKPSB26Ql$o`o%>9lB zvj)hFl|e>3Ji0nkyk5Mdox7+_$2Yhcf-tkxGp>SJ6{JOWq^;6M%D{_R1ZK6vQ^oV^ z()wlXazeY5+~6uG`rM^c#rM}gUr(2J5p+en(6v&X=Izy~QMV?FuJx|beEKEKY>!yD^G&vp%&_9n) zcE$$jwQeTX$F2pKSeRWKWMUI+ph;&1+#e+cL1#q?r4y;7*@E!uyd+Ab!OQCoRn$4f z`hQLLk}D!qrU^yN;ATY<6G&2Z9-=JDKvj@4Mx9s46?zD^Fa^dH+vdj8GF*_*gffVE zq)kyHm~7G%MLl)6DCghJfa?4WbZ&CMb8v}!;(L9``^49QiMMr$|I5`zA!@6?jhd$v GvhhE!$Ya$2 diff --git a/migrations/public/versions/__pycache__/358bb5f8ebf1_adding_rag_context_and_fallback_.cpython-312.pyc b/migrations/public/versions/__pycache__/358bb5f8ebf1_adding_rag_context_and_fallback_.cpython-312.pyc deleted file mode 100644 index 844ee1d77ec4dbeb5d5b6b6944d166d816c053bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4764 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 diff --git a/migrations/public/versions/__pycache__/3ebec5c5b065_flask_security_trackable.cpython-312.pyc b/migrations/public/versions/__pycache__/3ebec5c5b065_flask_security_trackable.cpython-312.pyc deleted file mode 100644 index 8245e2978205ed9c5386ab6357f38e7d0488ed11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4313 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 DCLL~P diff --git a/migrations/public/versions/__pycache__/4701b1283750_remove_unneeded_is_active_as_it_is_.cpython-312.pyc b/migrations/public/versions/__pycache__/4701b1283750_remove_unneeded_is_active_as_it_is_.cpython-312.pyc deleted file mode 100644 index 190d476c40d98ac52d58a4386f86d6e57e625cf7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4126 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 G8TcPoh$5B% diff --git a/migrations/public/versions/__pycache__/668e4a1000cb_2024_07_04t12_47_41z.cpython-312.pyc b/migrations/public/versions/__pycache__/668e4a1000cb_2024_07_04t12_47_41z.cpython-312.pyc deleted file mode 100644 index b25884cf4e9fc3ca906718fe45070748d8486aef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3781 zcmb_fO>7fK6rS~Zz3a72oF53G2{j50n3niQj`Ks5HpH$J7MY1SOSx%&qQEq)5FiQY6s!*j{?6LPKjQhpIEXc5EjbFfAL+^URy~ z-n{pA_IocsdptbA&mZ@`ocYHEz^`OceQcG<#t@#|0T3hrq@YcrGPZ<`B6C`z6Lx4% zFpx<&Ae~_G;Gp9RkZ?j4Q@%j^xtnr07>*nd4jvCiCPU$o$lypMl;HV~(R^A>%UR#4 z*oZG09YPT?6buGaNplCOBfgu z{&(WHpVDn|?u_oPx2(JCEv72*89z=;X*@PMFueovRCV)eH4Rk;{>7n#CEH?UX8?Q- zZh@;zoj_#@X=qjrm&_pBWCr&) z8FiCh6+kZt0hPLrKiCU^!hg5_zCm9A*Qp(R(VAZXCg0z6Mt3Q)gj8WpMT+{6(j98* z3d)H3{yMg?DWst=a}5=AenwVM`f?V}u{@J6lobd#3&BAl7|DmiLS#^ggl_id3i!q5umOmaqu8}} zJk;;7lMCQCr|Yq^=aIALZl)Mpa}KWqJ2OWufBJ;;KIVLnIG=XtL}^sxd~4iCyYhM; zalQ9r5BiG3#Wzd#<$3MApj}lpu6K>g8%oa;C_BlC&)k4_S3Hr6aLsvQ9XJ?7E#Ig+ z^_^9>;mO%L-rJ>H25+*C*C@Aj_-L`e6e;y-iKO9Ls?oLQ?H(;o6;GF9rKmQQGIU|t zL%e(Dt$983U~wFRCEdjT$y&30#H-AQ7q-GS({I?`M2D~!$GOi+e)|pCSzEuMZg*Q((c52J z^S7#N=NY91-$R9b7Ygpgf#N2_N60}!UMHlLko|?5R; z5Q4S1D(xk6((fx?LJko^zFxCbC`a&AcS8Ak)8S~X0^i;rE{y&>Lu+` zQoER1<6xaTCrj_Gezuyi+S;zQ6J2Z7X|}#PHS5+`$+6nC>e9|7w6jy%jBJ2-uFg4Y z0aBZ04IG}O%3UOTPcgnvQ=4V30h4P|6-+)B@20;$G(H;l(?5=mcg6?km2M{9$FBI9 zc$i%oVB%w}-=(tx?vGM}ptGWcGRbtxY(aQ+RuU!B;1zV6D(ak4`F~CKkSik8mPtj- z;$}q>lSoo^9-m=v?Q3`@jPC#CveT^TgYMiKlge|I^V%A!?()jhdwtqWCY>@?(tv diff --git a/migrations/public/versions/__pycache__/6a34aecee578_added_validation_date_to_tenantdomain.cpython-312.pyc b/migrations/public/versions/__pycache__/6a34aecee578_added_validation_date_to_tenantdomain.cpython-312.pyc deleted file mode 100644 index 9f1eea09e7deec6ae30c21911f335e2bcf967fe1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3458 zcmb_fO>7fK6yEiEz3a6@{s}aJIt`GR0?v;U@`I>C)>2ant=a&^30I zTUzDNBX?4@QaOU+L#kG4jxGvPq+T4!5_EfPFTJG=m8G2eX1$J0*c7N(Yv0bidGqG| z%zSVBOHGYH!IPbtpWg6N)bFHIeq45AYY-ZDDMUpnL?f3%CtXn&P1=mYMBT_8Wf2?o zASTMe%OlTMRMd+&phAWT@}Dh^B7{-kvaBSKY$ViFK$Hy}Fx0>VPRS`lRFiTdB?uqk zg@jIq$Hn2mfZP|BaUA3R(}SfEtPclbr-x352T`9a%UBrGFwsMl4F`I=d&4KY`%m`t z2YUL4!+pcy@Tr0BzP|1rLHLt65~NL+n!afIt2LYcYK?K*Ve13Ypcr_!Oo+o>%Am`G zv*oyy8SsTzP+8ZqJ3UP>^p^+C}0r|52 zWlu@U((62<2JLg6fgrz#s#x{{e`_85B@x^87``%N)?aQ_zNoHhd|!oMZY|plRG)2F zCb@uT+0MhBv1@$E*fpW%awM|*m+f4^u70&Ra1L>B%6rS}wJJk(P(74R--L5`m7?Ky z=hs`zRq7`F9A9?kXQ&cCc;KSx(^LiP(!7o}{Q+%y^!Rn0l+6QGY->;3fdsg8ksbfo)srkcf{R9v&j((JktfQCp{li5^<9o8~u1}REz{&X03*&v4&HI zWUtSwDTEblVAD<1nVhZEtT8OykdOr&Cci+CMKaV0IOBY3UQy&2h_^i>CE2~Q3!YNn z^zQJ3wAKV0%xtvm++kZD2YHR`KeIk28}aLstQg>mVJ%aOG&L>7)s${%0Aq&P5Vvqi zvSTD!0h18|8D&11GF`fCdd5m^HvumQAz#v~rggHt1KZz(E)xN)hd#J67QWCc^@K!N zCZ^sBy{GE(4YgAbhP6}gukW$<(1!QW zQgTHsc!xGAH#<+Se)5E`d&~zm_&~mWBzGpy2MYX$d-6Iq_>Ozx{bMUbD{trAs|)!n zQhrv?^Bo1=uqOSNK+#K9eCnqJzio-Sf(qV|O^RVLy?V=1(7M65etYh_@vq14&Hnh- zPo3X){t(QeLfiQQ|9+KO@8oV+?2J(|}%O+Ihi0Y?8Wy$IL69sSY zCglSD%JnLZ1FMRq@%#%kvSemyezAo(R0`yF(NC5t`LbOUDpK3}QOLs5=)s7Wd001k zG}6qhHJymGGmpG%q=9?X%tj7#kJ{PDaqgKC$HOeE#C`cXOB{umth-W3pb$EhA{KcN z2LKEOY}pNV!1K!B>wQV^eL0H+CyT&(hq8uzl``~-1;hWpZFVXvFXtH)eNwgErbwM0z7XfZF0fY>Ij3iKwNv1Fam_M12KIzfD>@mjsd5H z!CDs?^dj|Us)TkYpx;S`CwHM;<-ku>ANYGs_ouA$KD=|@^GAkO2Xi-a*YcOH<|m>B zezFLMeTsg{SKy<9SV0@G2y{9sJC}QR{qyx?{?l0gTD-s`Yn`?YzHJFqcM)U?Rs&N7 zmFKEad6()vS38^YtRGzW25H?2_8;Q3B+NS93A`kWv zGz$WlRb;mHBM{`J<6d}OCu50tsZ0y{oFXga7L(CBNE&&~{%>K{kc3K=ZcLL?P|@MafEC>o5KiM1(j_%z zRX2?!{QlvdPdi{g=x_yZ_lo(JjAGEt@>$e`Aq< fQg?W<=1E->ked2M;crhZjp?nfT6&Jw`eEX~&(<5_ diff --git a/migrations/public/versions/__pycache__/884ac7420cc5_add_temperature_variables_defaults.cpython-312.pyc b/migrations/public/versions/__pycache__/884ac7420cc5_add_temperature_variables_defaults.cpython-312.pyc deleted file mode 100644 index b897278a3929121f079676dfe10f019ede1f5fa0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3811 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 diff --git a/migrations/public/versions/__pycache__/8ab72fe23ee4_2024_07_04t12_51_36z.cpython-312.pyc b/migrations/public/versions/__pycache__/8ab72fe23ee4_2024_07_04t12_51_36z.cpython-312.pyc deleted file mode 100644 index 2c217d7b6247fc242edb1a2c0010beaf7e650ef6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3781 zcmb_fO>7fK6rS~Zz3YuloF53GNoy1uFfH*Vx6#;pE`R0r1e;NSzjdnI3N2RegNE&wl1PK5c=unu9BjI3Zn^o9^6FL(d z-5*R!;@N3X{rm=yaTnHk1ZQMF0{^9_IpN5_QHKHg!jU>TKE@?ptsHl?yuA9 zUA)+CRRMH?FwmK6@f^!@56)<|>_Fd=8DB48~ASQ41Lo;vhtGNKtcU zJCnYo$$3KAdeAzR;2gOKX1|(cB}&dxXg~@@^Wlip7nXYaZ}j8}H(ssVu@OWEAHc~z{Npk@p{#+ zZ!ddHOU^uJ?5)yG6F0GS^O0gtDO&0_5=qmvRQ2qU;$-nuDOTz?CR64tte)*IZeLsW zQtO`jY^$g5Ppr5jtH8k_rg*u^!v00YwC4S4jXU=%b9AM(zT8P;Vx7f$*+aLo!m(cV z*{F5>b#jn*$J*oF><_*Zj(CLqDg0)9lwIoP;z52X!o`pCOQYO7JijI13S^a;Zyhf) z-vY=kIPI)PvU07Q!9f?~38#~6I`1TQkcX5rFP0JAb@KU6i)v-W|B9;Romk7eT_Vvy zDjCoANbG|35-hDI{!i5Ets`D$JbbVTHd}VXmO3hgy~IyiA<$ZD3x4|z*_m6vW^Q-X z&Z4)!sy)7$UE5A;`^Y`i=y#!!N*rh&D*RM*Qt>JkO;qfs;uR_mQ1KcS?NoG7L9c|i zhl)ljd{j`bC0S`NZPR*RYop>I74+-1QiXPyG_f11*RmE%A0>VI>fdf-X`5xHs#)e< z>-{N{WQI3M#yB*zI9R$`x?r3+Z%iasgh|RUQ_NGr<}90OQ8m+U(?-+4^M@$M8;4Gm z-d+B5Ib&Q*8W&P4g3Y4Fq4Cn$Wo7wdJyVoj(H3^Kv(rpqi0)Mpe~p#@$6J9HTf zTIK&W?4?&kvb#x5&XQt9k&{T#u?SHPWuY#qSu@XT^a?!yYeWL`imeMH85PbdXjJPX zW3)`sqeQH-48uHexESYOdjQk+D`;C4fakz1;j!=4Ti(aMRwBGjx5PhP%?x7JdYYLT IMxzV=1?D1Tl>h($ diff --git a/migrations/public/versions/__pycache__/92cdb9c6f6b7_added_versioning_information_to_.cpython-312.pyc b/migrations/public/versions/__pycache__/92cdb9c6f6b7_added_versioning_information_to_.cpython-312.pyc deleted file mode 100644 index 902b87f906f7dcadaec668858d7fcfbc3a834eb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4535 zcmd5=Pizxc8lSN}p7F#E37CYGgf$INT-q3dlO_SN3UQ(u3T?9~ZA{wH*zYA6#xrJS z9B{WQaj4V_EA_O?N|nkHlpI{O(&p%`+A64*iE0TnRWG}H*;`nsBIVTY&5YwAnUG|+ zEA2${`ThCc_rCYN_rBk6@_i)2Q}E2sl%{_SQ`A35rT+Mw!jl0g{Fy>jhC(#*Np!)N z@zJF0m;9Lk3S=0>WP-?_Vd3Ra@M9_yLM%wW?2mIFelm;@MzKp+)$)p*muF&md0J5m zq7K!VuEZv=EXsOHDTsNQ=g0AEo+!rBsiD|lZw_S#bN$o(+1KnItPREb#gj=9=P>Sj zZGaz9v8dx%3dB&X_jqse)#H7yp6H96=pQ=SKh)RPb3B%A&d-P8$6qi;Y`o}_5_`;@-@(@p;*b%S2tb35zZ zUZ(8!_<@UNld4Eq6G|E+?EADC)N)sFK{WTdngvo8@<^DzhRY@o*&OF*WGI6^qnC?V zcvhX*T2l{@!6xgNFnxJs28*Svl+T&$$nft*hEt<)pSerL(^$o_E;#dZij1&?b!-NR zIg@pani1W?4*^*KV)8i)5Rf41A2PCX<7j*g%r(Q1S#Sd3X|W{fCMTC9Nz8&HYx>!8 zoL2Y46*l=&5doYK6OD4VJYjY|GnL@foH)SfC>b5Jo6XQ#x4Fmib**lNEzYYXWtgp5 zQO{iwL`ettbjzh(NL7kLPLVZT1x(b<-S(OUC(wcwbrB)ZkxB*G^l73Q9I?wBLBffA z0pg_No4U!SWgX986}E=6r&5XjT(OEp4PNZ;AQpyF`nFPYKSW=2sxsabxEkxH6_GTs^+yuw9gd1uF@EQW^ z^Z^+VTx3Ad6``kChOI4vF@)6wxVZ;j?G#|@E$W}4riY=frBK(MLM2rT4K7mwrbI8i z_lRqG$ij#LIK$EtyaS>s*7xT+akca77nLC;fI z36U9}hABSmc%oELEp%#`;uu6P+_VhrU*h(EcJ}l1U($D_ug?DU{1@lHyigmTcsM?} zG(Kr$#2?19MnSE0YV{e{4LJA3xi8;X?5lOYUE{`oMT^N==UX-IZC7M|Tm8t2*2J?5 zKV9jmCaXt`Ox6lZ&fR;oa=CJ$nyU62mvdGxa`zsotRK75N+R<#+KAZny@^_=cbW1r zn66xLdDFijS>Bv?TiiI`3PVQP<5v!n{djDhgVmKVnabXZ)s<*NYgIc8hv?35M>_2P zx@Giey2HQN{!03=|3R2Zx3Ld8nDmS6gTqX^hkb_paWKjvf4v}oHS$Lx|9qf9v4A3a zku(Mc5euLM)UHlufOGGRo`tpvNEr(iuR&5Fa7mv^&}HXZ_;r4kKXNTWTO3|+6Grh zCHF`r-vBD1|LTiG#E3XZL@N>di1-Z=2Z-n*qLYXYBFGU^2_073i6D>wXuFq`$p@Oc ziwN>j5N9kx*KP=cGdRlOf|UJ zvDjo>${6olHl`H|Fp92Nc`Fc-?KI!61yi4M1qMf~3;nb9-scQiA`v)@ISu{Ji|WU>NK#hf6RtSI3^HlMS37_VKI zM2T?SvicG^7o6(+C&G-76CyOKSyhyQvH^d@l4kM<7qN^qL6I%OqLNc|pLzn4vQF44 zceB T-@z!2=_kEW`Z}$if`PvPn7H6b diff --git a/migrations/public/versions/__pycache__/92f0bd8ddd69_initial_public_schema.cpython-312.pyc b/migrations/public/versions/__pycache__/92f0bd8ddd69_initial_public_schema.cpython-312.pyc deleted file mode 100644 index e98fabc734840013c1b06f3fc5271b8adf7553e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2248 zcmcgtO>7%Q6y9Br*UrXv(BdoQVCK{arrm)r^w9D0G7U2n32h~|J8Y2Lh< z_vU*)GxO$QJT7sx)#od7PXNdL!X|zbn#}evW!5;z6*$O4LFWyjAn=S2>7fFEpb&}o-s~HGV_+yVC`nt) z*)&fCt2{|!L9|jc40kv{X^8giMM~E=hxdhxezg7q9UG3W88+S|wWe?|o( ze*OckEP#F3nXD9yo9g< z(VSY*9TGJwx~>*=M5Ia?(&x|giJ-wWk6Wl|0!-CFTho-KuU^!VIqxix$TBM0nuE6f zr0X-Jot7J9+DNe-6*~%pA#MH|GNHHfimL0@GBsdWrn8_|70q-IR!a`8O*RqBZq-_+ zMr^lmrCTw(*Cgh}p*XIWf~^v9)Y2=4NusP=&1eQ9z(MC663J7*d4!30#=)97PXJRO zozqw|R9qcL)lq86!74RO+Gb7dYz6JEtaIDc9QW)i`C|r;Y)6`g`paI_5Sx(;Sxt+R^x|zNU zcVRXX$Lqy!7uOeS`h%GU7^B)hf&ZWK2^Y!YV{l-+3&t7d6Iq3;#xHjyAI)5m2img!y(%)I!Ulh2}W8y2kS=oFTz zlzo6UOVQI1&-1?uA`gB~aD3NKT-Vbm7khan`naugCGL^H@F~N)5M+Lsujp8rU C)!YOC diff --git a/migrations/public/versions/__pycache__/a8c1c8e9a31a_security_additions_to_tenants.cpython-312.pyc b/migrations/public/versions/__pycache__/a8c1c8e9a31a_security_additions_to_tenants.cpython-312.pyc deleted file mode 100644 index 248a5ed006be9bb6d38a1f405149f9ebc946ba18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3158 zcmb_eO-vg{6yEiEf4sK&Pe>X_H-#plAu$-77!n~-Zw|D|j~bFRhHATb1~6Ign%y;t zt5)UELl3$2kW{MF9EtFO-l$ZmG~p1bmqoIaXnSlgz0pEtiBo5G*VutglU5yT-oAPB z=FOY;X1?d2qfwqftu#}Z{+uI-U-6*Y0v@xKM9h5x5NQICAfS-BKsrETo>HiE5CqdS zpwkSX(k$v6V7?&IA;2Qa7pWfZle^borl4odqA&_T*34?EA()yl4pmt-4W9o1E@TZP z6~@G2K~84+Gf6lk5A@6K3^b55bM9PXK$er!@&KRGp=?4yL}XZq_r(WK_a#pECxrgN z;do+raPZ7PB9Tb;@%-=j06nA~(DIk^PCmSr#QptaPt zjPrq7Rfg`~zw?^)@!Bs-2VOJ&jo@H4nx*z-&(eOcibNODPZ;DK^jdBaB>LT3xl7$5 z?vVTBvcJ4YxbmJum+i2wDbSD#2Gos5q|F$aS(uaULv>gOO1*bdjfW&4yU0GRa5fz=QI^S z1)9(fVskd@8MPVHdEj<4R5N-pZ$co+`K*Mz$!??MqIbzCP@OSn#}Uh^1x1mk(E3)# z0e9`LZ=v0B52?4ItI)&g_)^%-Q?i+vm1M<4UYm}AMxbkXDT7eP)a9&d+ASFeFeEP= z*aMrF0YExRA*b2_L$;Ze%QM$ZJ*&>3cyX>}EpOnPDC~R{yMa}p5xa6THFzm5^~XfC z(Uf*K_MT?Qx3v?7Ai@Q25WBblN5^6!%qv-r;lE8C`aOFy=-$wt$j~ zfiYH(Qj*~Tr-Zz9fm1Ry$&H0^CSOF^$|Fkv>L-zpt*9GUkhhD(Z=vwBQ0GRd^FeM! zEQf|Ri6C7dS3i8tH9g~m4NkC*onO0PaYC89`chff2G{jaTspoov~p@KxVm87l&m?! z;=0P5=`8vug-QtTxE&$*i08@dl35N7ZW1ItMXqv=fg>B-k#FApcI@jh>-f+Q@gIl2 zA9|W9pTBBNNac=?%bZ-Hu=X}nvogIjUJk`Ki2x1BmDxJq&#o%YdET#g?c~bD%B3}N z?W{GCaU2H~8n1NMS6Z=;Zftfc5xkY_-cE(7Y3&%@D6kJk4~qizxaoq}OFcQ&D<-LR zffjq%^qzhaSw{#!m4Y?2M%Bg-?`gmQ79kX>63ap42WtD# z=@m%N_+X|F(u2@{MrGb-2R~Haf9BWI@{3FuL_pMy3}`4d*0B2}k!(U0zS&QIZw2zf z`tSTP{oXx)`7YMCT-F;=#&mpxbX-VvTtoE^Ob%hviAggihcUtD)NvWr4`R}e3C02h zl?O17|KaIPSU@|VsUO9HH!%?qvBMre81hhMbe`n!?vu2-hgOqox7R+huHUl8(`9Y~zsE^(o2$L>8cxJLnCRHxI;_sV zGS`psAYKm#HF%q^hqpajW5nAd!q{bXkE}6I4?hiCH`3Pi32Rz&Fd|>)uD=2Xw|NIR z=E+JUJ^%)kNph#cA^$Lj#1VwlbUX-oCl#lDI@XdJp&qx4wu?OVBu=N!vrk57k!9C; zT5M%|!Zs^OK+8yy&B_YQO=UA~rQ?lxMOJXlFY0gM%y7E*zuAuB97(m|lrF2ND581_ z6~pEM%tI9zlBPOkLdSW0L~J2SI62Kxon-}>%nJ5X#t?no}PwIH#-(XGF)&Kwi diff --git a/migrations/public/versions/__pycache__/ac7753aa8fa3_add_tags_for_html_embeddings_and_.cpython-312.pyc b/migrations/public/versions/__pycache__/ac7753aa8fa3_add_tags_for_html_embeddings_and_.cpython-312.pyc deleted file mode 100644 index 7f7dc08c319bcd20a27070baaeb6c7f8ce8e9307..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5471 zcmc&&U2GHC6`rwUd&aTJF9`__F$CBRKXIIpgk&R%iCJ*Eu#oVxIHA*t?{#7rd(6x@ z5W1~+*hebu+fu1gd1Mtoq|!=dC8W((NK5ESI~F4aP1TpSFT9096)8_WcgD_monZr8 zx*coI+IqTyn=2iuwnslpaU1@FEI@&nQI2DMTZOK&KsX z2TjUO!5OcDZuzLCRC93C5(52Qkw$V&V0o>b!5> zZAuw>?R)sq7W*Ec4Stqoo6NVyX1?r38x`V3tSEo+B$TKS;5eEodU@2DZ) zI8WjMPl;#D^UX)y`hOXHCSrIPjC#HMD;6Q$X|MUQOzuWT!e(*MA=mY>YF ztyVNjCDdA)k+Ih7B(`rV5!h6s&60S-edw{-hj!=Aj@LXmqi<%$vTW>foQP=6pmfKVI{5i_xckVo`S4*ORWiBUUN&cMH-Ev|E zr+Ix_8QW;&Qiw}l#dEqB5)DpGXP^x7E@du@x$ldUuIu7eM6>Q86nMG=UUxP(C8QF% zXCyK{5{Vw~bm%n_PGSjX6s|ZvBW565VFl||M4j#_D%ITz&hQyUuUSuXoRQd`^}xy@ z6A*A_TA4WqxrfQ*1c9G|-mD;`O)=e1awLZ{h$C6^8Ohdqlfg@65<(7P#KE{}Fhwr% z@r_FUHeL|K>qN4YYE9*`UWag!&j|`=4cJ^_RS4_#B`xc+vfg0$$(-W43)%I0CoPeU z&{-{!^H{H&;+4b<#|sKLS21QW#2cYeQRc6T@5sR@o-I~F$7gXQ7K-AmAkGmVhY+5{f|xbR>D08uD*#I5khwxa zv#=QLm7RkXmj!JIOZ{MH1HAGHzzDaff3nrfY+HeC zyOUmsYV6<&RprXj_dj~d)Gjl@0uxkszPC86GC_?w^GaSvf$6v#y|;H^aAE&q)%{uZ zBBx%FRi;B@6rnmC^b5GIOLn{>P>b=hx{kIpG?Y}?vhuH68>fV6| z^`E0y!Hm*(~ z?JRzBG^t+8X@Oadx&Grj1qw_+Z5z;-!-fvC+O09+vTDD^43t&F8q>4d0FHXuWce?7 z@0`Z=tWXXYrWa-mX)}`j_XQ)8KR0;ApuD>oa!PZ$k5 z5VwBKcqPnh_+CWqbTn=%v2|04CQG6ca&59Jnr(K49T42OPhU^UZZ~g3EvVJp&1ic* zV8O*#?EW^mChxG5ubitby!6?_$lJfQ=dZ)d_R|vC;1W3_BytOt{DizqNDCpIgpk!P zy+g=$LIObEKL?o5&*u~oK$&EqF=+>B+)D^Ke5KulbP%$OkRT!LgtQXE5JHX_shN;% zgfs#H0M$gw*LTVWAON&5(6KOqMQIY>wsAt6G@fhmQ7=$;Fav5}LJF^RxUsTYU| zgrq*w$|CVP;3on*hM-Qg$io$|!%9|@<;m)9)g=9ru~MG}9lC9x!_b4#<>3zs!ykM*_Fa4_u5!F~YU;^wLX~f9Fjk2gpTKIr*s=*yu;W7>OX z)L&vXt7w6o#>{RIJo<3o^0BePu`zA@{POta!uVwsPix~dPmZP3x!-_MqmI*tQ6Cyc zoiU9vkwKrv^cxCos&_bzIk?_cvx5R4^R9o0+%o zy_xrWProD*GGL=ou9g0b0Pq{1v_~iq4zo=779danNI)S|sDuh3fy-etT!^4ZA&Q~} z5rqpe_CO?l0}2v~F_i1!B>dvb*(J>?W2Dp^Ocd8v3`;j_2rGu8I<+b$viv??H5|jX zl(~FPDW*03#<*6TLSq?!2Rk_>J(b2;tfx!5hU8g-H5V&+200~@&PkN;;d% zjOE6&qf?p5%v4sE|KMjx3N&O_=V`ptGL3gy)Pu8nFUT;=p2K?rKe)@#AIt44X)mxh zy9Uq*Z3jCyz}Mg_upI4B2t+s5UR&n&Ul}OevG1kiw8C~UMUh5yo5#k+b`Y2F-#m&P z9^<~nPW(rYJ)PRVjA95jr1o8SarK>{1(1xo$^weBC(-EM4sMH4%KM#sUkAfr3^>9X zquU)IuwNbA4c`H4Lb7L`MmV4D3siLUC0x-cZ1ZV>B^+8c)6|M4rg7c2N(QN5q-rib z&p%RKY-yIO8b~dz;5wB{Ho->OVluNAb?a5EQqfnU(y=lP8HkG2TG2Fg=Awt-5+<10 z@dHRoglC5K6*X61QZ>`%p1c@j4Ix#x&058xAxER)tS`rAY}>?|MIop1f>FV=2NAo< zbS=jvnqj&0obHib4PsRNAffNXt~#6r%F(^lN8BWKQnx>zow$`z$5MG_sA%6!y=yz# ziv6aeBGSOUCj!w!yY-$w~UY<^>vw~FJ zuWQx6Qd*~(p&aK`2?qqXOZ^GdgL@y=o`=uAba}SRk zUJ)BJLo+wSKi`bb!q}+>!Asd|5HFbUe>Dh3{%|95LVngpj#~zE6ATnZB8suXfn{Nv zb!f{ba`Wu5wN!IVF;u5y^lM)A8w%@J}Pr z>B(5Ki^fzH*}AIIm}cTi(a`<+mz~c|&E!3)PF~~3fF$^PqX~W>^<-Kkn#EcLYgE{D zsElwGTgXvu%PSYc4}BjTG6dd*9Kp9LHmaHUZ8FN%c;!3e3=YDAAUqF=LgcS*AYA+v lTs(jv{`xxH?;ToC?DzIFNc64CFGNwm!r=u`NRkou-QQqh;Zgtq diff --git a/migrations/public/versions/__pycache__/b7258a741c2f_add_embedding_search_parameters.cpython-312.pyc b/migrations/public/versions/__pycache__/b7258a741c2f_add_embedding_search_parameters.cpython-312.pyc deleted file mode 100644 index 6d034d89ca0df3557319cf48f9d3ae4a05ddd4cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4612 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 diff --git a/migrations/public/versions/__pycache__/b853a06f4bf4_language_llm_fields_added.cpython-312.pyc b/migrations/public/versions/__pycache__/b853a06f4bf4_language_llm_fields_added.cpython-312.pyc deleted file mode 100644 index 52504679532345aa316f278d9d5e6b8bb2efe521..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4542 zcmc&&O>7&-72f6FF8?f2k}b=oT-tK%&~3yY$+AQVP9;$RBuh>q*-1ppUN1RAit>_6 z?Jgy=XaOI3bkW|L00Ek#1L>fn0vL#r#;ENC$O>LS#uh!b7vJRCg#exUW=V<+NkT1yvFPn;C>57MbzrgGy&3>tr;5EZ8ojZ6ZaHN{Od zX`2Oe+yYOFV9na%HsD#~46?;pWRBb6b|B_=RNRSJpsu1hVE^^<6rW2M_%!yP@lQ=n z`%@V#Alc6&gptEBgO@XMM$GvqVo`r$;CwG1>QD70QhlWnEJyvJ0o>c$hx+@He8Mp% zVP3)h7?7wx5{mS_6*~V`DC`dnM*I4sp-4|C+}j(8I2_N&Rsytc67!eg;mC`!l9sT% zBa-RAv^&4stX2Sv7&J;x+<;e6M1UJ4^{b<7V@sOu9oeN+Sb}vi9g_~@Qi)_@L3Nl-jW`QT5PSf zs?XP7Q)L}L;@XZJFnh;OVv(c&l|^dS^b=U5^Z#OzWB(hA{J^)4Y4X-Ji!#SwGk&xn zUnLr>b*+{)K~%4c1x2cx3R5z@0$E^=qT%;P(_Qav^BlE8*N@yyH0Kwo5e zk}O2Ib!28{WDcCgmSz$2G704Vy*~usBXBGS-+h0qZ#u$-gE5#iA>Iy7iZXvoJS+QS zc)8pOjxXbpiC_%p1+ka~Uj-3f#)6nP+SyE6;uWYLm4awklO1 zoKb=F(|&{y^`0x#dd!ZyLV=NaQ)|-mW^fgeNJ7JRkmAW6+`Iz0K0ZF<4YIi zaFtiGa8J?feLIxRs?Zy(q2Txyd;H_kKTmu#p`IDIf9mtVXMu-dEjq1!Ft7QpYwV2% z)ZqQ-_RyuRp-bP4emn7KLcM-No8q1f-BfRhnlG=hOAQilf7SZe&M!LEnJe1JRrMy) zd{|>s4X|H+b#8lfW@~gto4vX{JHItMucDMTn|?C7pvo(n@3zJk8-xb$M?N3?Z1CZz zHuSCW!P)H2-8cp=OsfpQN$!uAA88rKf7E z)V(X3J+ecYte9S3Ff^9D*1sVbUb|%Q$_{vQ{o4BUW^A)xy_PiGgLbV%vLwITMLhA` zI01XRE;3cg346PqDr!%D1CGy!Bb}3!`Ag3`zDc+Fk@FXmo#w}sb<)8+c3UTpFpoQ} zlc$*PRGKVE8I|T!ICwu=rAZ<4nx$ILK|R{6BD5kKVju@V9l1(gT(}zJ{{gk2tw~mD zQk5Zlr8;<3-G&?oBAf>zTn8fD2O`4F|P zwN>-@D}3IL4x=N@@b!CblK1JmO!NGH_xH{D`+2|PvgCo&C6SXMk&gk%O~`3NItd{! zk3{Nmshf~fgq$SgXM~&}IRBg-f4_vVej65S6h z>gmCafz4Z+*VU_Y>Xo?0UL#Ruo_@(z<5V@Khsz<|x5fI@uCT^N3`M1GNMpk_-3uB! zP}A+#*b6n?I&e^9LnJ_kYvW@zt1Z=LwYpu9kXgqf5mP;Vants&^Py9HFRos_rlv$A zXy%PId>?@1v?U0hgzk0{TRevdJx}lLvami9RKpNctC(_3JvYvnzc@K^cD&vEm$M@s z<9_o4#yak09<*D>yO;-l>v(_(xOIl(keK8+o#6#2qB6-+rQ?9_eqJC&W>F#@)!V9! z9+UxWQjtq_3oDiXlF;4cByiPkLgI5!EoX0sNb7IaY9E{WQDfI%hQ^rZ! zV~3%%D+u_a^fvHF@grXVvSX%c`nkzQTmF5BqC5UZb^M(=w_~GR$L_FCJtywCpL*JX XxV?8A|FX5xn10dIN-xpUMUeduvjWW~ diff --git a/migrations/public/versions/__pycache__/cda254aa11ec_2024_07_04t09_59_04z.cpython-312.pyc b/migrations/public/versions/__pycache__/cda254aa11ec_2024_07_04t09_59_04z.cpython-312.pyc deleted file mode 100644 index 5ffa34881f04b79d6adf172b93b1eaa6d0cfc1a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3781 zcmb_fO-vg{6rS~Zz3asW^OF!#NF9-qIBl?T?GOl}CD>KdDrwb{q%kC`wP#42ti5K} zkT^{x4pk3TD)p8eb0mUFK60!3gM`$}MzWM>dTcMfk&@ODhpIEX3pQW~X|rfQ&%Al_ z=DoMO-+TPx^@@O8Y3-}Ye;NSzjZW4thdo$5MF#f)1PK5c=unu9BjI4^m{r(>6FL(d z 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 diff --git a/migrations/public/versions/__pycache__/d4a45bf36bfc_add_temperature_variables.cpython-312.pyc b/migrations/public/versions/__pycache__/d4a45bf36bfc_add_temperature_variables.cpython-312.pyc deleted file mode 100644 index 158f14799d4d67e39ea9fde6d0868aca2a50405b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4610 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 diff --git a/migrations/public/versions/__pycache__/df7bd57b7ae8_2024_07_04t09_08_45z.cpython-312.pyc b/migrations/public/versions/__pycache__/df7bd57b7ae8_2024_07_04t09_08_45z.cpython-312.pyc deleted file mode 100644 index 3bde0d58947ec750ca60394a0691dbd28125b569..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3781 zcmb_fO>7fK6rS~Zz3YuloF53G2{j50n3mWvHu)h+8)8?b6|`yt6eqA+d&Xc`d!1b; zU`izpRSy-FdV^azf|5!;=2rJ7QlwrMDH3RVY%jfqhSpLJRcCgc?8ezZXxV6=XWqQ` z=Djzw-+TGR@82-ISw|XzXZY;AkW^5g8he3=YTQDW3lr&F0jcTnL^@ z3ZW9nkz^h4kDP255Kw10r- z{~&&cDBUF&&*(n8W!-1Dn5oBS{CF{?@w?iN>0MBw))%j?r(vCee{tww-ZfWWiG$C< zEpU~w3Dk#>hVFT0U5?sL%Ckj^b+82>3%Sb_^x~I?P4m7vk11u?b=L61UCtU1A14Hs zXD^7id57@^wnXBTm6jbzwQiAej**3J>oLx^&(-&PPEK~iJufBC!VV|-m&_o$!wl}- zVbt41(dbnf^niY#QrGbZdjU}R@6O*h=nLRFwS_M_^UJ{GhdR&bO^PfbRhUtcqCTW_ zkD9rH@}j=i#ums}$Uz}{4V861D=R2>xq!!5o+*`!NZ2e+Y;B0U$xLVKJl&Opx~Djk zmU0=L9UuE-d@PX+x%6fQWs!mkC854QCl?@+PzmX7vb)aKebD_SR1mQol=EV)pm%SY z3NuBBu>=a~vgvHs=H>cqJ(LFJjDbd$GH)?Ll+upBOx+R>S70glF+ZFy?lY6$m&BkpUqRD@BHc$e<95-|Q=v@xd0c0f>~t z*tItNs^4QLZ-d{xO^?0ZkG$RY@|DE0cW4E;nHg%~($#tJ&|4X*yjgWG%xdQa?W(GAJ}S#D$VkxE}RR_)bNX~VUQ-L=D&$;#)9)UEl6ch3Tr*VzXX%iib;a50FgT(Nm`d_gii{J?H;>wYzcXqx)9Zjux8EY@m1 zvXz;RwOYWET2tS^2YGL-Gucc37&z%lM(LmX-%5_si@i)T%q~Wm*{^(yNvfb_iEs%p3@JJk#ZdLWB29aqyiH}(TRxSe^qis;=To^SQYsUrSYDW~Xo z+?_NvMz>8Sd`_9zM%It*l5XPvWNoK?#H-9l0Q=oy`VCv>+g{iqv_rGDl3r_*eB%w- zT3f%N?sPd<(K}x|^Eaw%#~Gy=-$R9b7Ygpgf#M@1NJuv!`w3|wWG^AF5zb2@c?d%0@BDKs-5`>weo^cjtSxAfQNZVkIlz|ts z2+V2+$E)X-q@_#RrL=Z2v&>m2svSI8eQ)WrrM%NpqZUC|vNIVyPCIpLwCY*v zTx!zJrL?n?T2?k7zG%ypvjC}0(*_PtQ?*W#y{8!8r>M0WM;s)WjPN92N!2m=NV1Fm z;lS8PGDQD0GS-od(~Dh9vX@;9G07;q7-y2BY^X_R1>7HH1VLv-3FXtdjM;+l>a-+E zq`@oeE>+YyrT+h#?k877u%>B6EZ}BE64OXhbsnN3DnM0`3r3w+$Q61BRxt&}69TR`cZT?SB PD}|`lzE*0QQi$TeK$B$t diff --git a/migrations/public/versions/__pycache__/e76f189a6489_2024_07_04t09_40_45z.cpython-312.pyc b/migrations/public/versions/__pycache__/e76f189a6489_2024_07_04t09_40_45z.cpython-312.pyc deleted file mode 100644 index 57fc05f5ef997a1f8af46ade3b10fa592464ef53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3781 zcmb_fO>7fK6rS~Zz3YuloF53G2{j50n3mWv&W}TsHpH$_By*x zz?4ckR6SHw>J5$@gOW-<=2rJ7QlwrMDH3RVY%jfqhSpLJRcChBStoHwC~UOP^YhJ{ z_ukBY@8wsomk0PcoclWcZvz0olTP(D z3vMtq0ILaU=v-i`IBF-9Ya5EKqYFS5a@Q#6#xD;W7CiGV6J_YFzrqXm)n5VeaYA5Q zwu`@wd-T`0&69djY1$L2c^j&}k1epZ>f^%xd27EH#Ds+hUJ~C{5C4)8WcL`sgRkcG zR;!Aj3-kh&x`jX3%Yedv_x`y}Uk10RZR2A7@ggwC1MTPa21S;TDom?LQ6EvdOHExz zSy4Y&Gc1s{kby$_CMxQDT2@fzS`N1{o+%XbNZ1S~x;EfW($iUMOm}3U?#fRmrA$g^ z$3{OJ8;!*S4!u!9X{4ZBL9q7cnAnn9f7Y zB~VBfO=GuArwqQar#m*Uwt7`hU1nc*Z;S^hr4@gmI&Uk|d3#U2#c*>2ZrJe1sSpy< zo04K7bzKmp0*+2WOk$@Rp(5vnl$=uw3U;QTH=B9|E5w2sW6oSD=T*XB{`GHy7iDQW zi`3x9m&PLJ!a{E_h7~2{+rbZIRlF%5Q~fbCV|9Y@88mt}7(;nUE@p9vgAmOiNzNPX zZ04FG7BFS2LGx6CGx#DH{aTh42ssO(0U;DAgrY(uBt-h|^yG{9VDnf3M9Oh&S_^*F zAFz?L;174h6L;rhcjtp_DYoK{t^y}BO)Y-@l=D5|{Es=mcI0$~ z9>(UnOVQHXW#{6Ic1h4~s2bO`!WE1~F9KBDWXIWzz;5GUM?fL_sHklEvlCh|1YYZcYHnXc8Ej+u4Fu0 zBe4V4i?O7dc$KK_wT^h5@$g~0n@qc5^Fqt66+$cAZ&V1R*4l*MdPBD7*6*l$9rd&5 zy>IJ}Z)DfD^GYMWhYI;F6kLe|#Y2Rjhz=q;iD)9?AQ5j6afpb+M6?s}CK2RHDEo-; z5kY7cXQKV2O-g;`01<6O93g^yy=JOVj^U>6hVreP$Foh0EG_VuhO^3^PeR=WNchnHJSD?G|k$4eUNdI9@w?ru@P3 z7t2}gYErwBTH$Pt)sBvpFD^^VSNAeS*cEMJS35gR)n=!?nl(~(Ew?W>XcrUOg$XS! z8x)_fiB)|7$xTxR4^L5*b`rg3nBOO<^$JG}B%F+J$7iD~PCgOupnp6vIvfwsKM#+# z#rx=`4kq5sE(Mr)m|f~);v;OJL1zVAAEg9AXGIBRlbMuRg7E5;Bub>fE9wqa)H%ia ze@*w2DD#$q_&nx5#JpyZ30^^FUbHiB~PD^M+>BD2B zOi?3PtkM)kJ#)Ay=imDP)%F``TjhY~&@A`VcX-zO)YpoIw`rFD%hgOFYOSZ4nxYi4 F@IQHpVs-!k diff --git a/migrations/public/versions/__pycache__/ecf1215f61da_add_tags_for_html_embeddings.cpython-312.pyc b/migrations/public/versions/__pycache__/ecf1215f61da_add_tags_for_html_embeddings.cpython-312.pyc deleted file mode 100644 index ff8404ee5f4506a40122a975b7cec345e30a53bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3264 zcmb_eO-vhC5Z<-DKVIA6HzEIZ3T*>PFgAaIL{yHK1Fe!)`NvSL7QbgOti9�-wa5$fdDqSKP%?-mSUg9vD3um*(R< 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 diff --git a/migrations/public/versions/__pycache__/fdc9ac232c49_2024_07_04t07_39_16z.cpython-312.pyc b/migrations/public/versions/__pycache__/fdc9ac232c49_2024_07_04t07_39_16z.cpython-312.pyc deleted file mode 100644 index 74ca18809b25cca3797e7aceaf84120847a68b17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3781 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 IhEj;)e-*4@V*mgE diff --git a/migrations/public/versions/cab899dbb213_add_code_to_tenant.py b/migrations/public/versions/cab899dbb213_add_code_to_tenant.py new file mode 100644 index 0000000..277f5b1 --- /dev/null +++ b/migrations/public/versions/cab899dbb213_add_code_to_tenant.py @@ -0,0 +1,34 @@ +"""Add code to Tenant + +Revision ID: cab899dbb213 +Revises: 98adf66ce189 +Create Date: 2025-04-02 16:08:06.597183 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'cab899dbb213' +down_revision = '98adf66ce189' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('tenant', schema=None) as batch_op: + batch_op.add_column(sa.Column('code', sa.String(length=50), nullable=True)) + batch_op.create_unique_constraint(None, ['code']) + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('tenant', schema=None) as batch_op: + batch_op.drop_constraint(None, type_='unique') + batch_op.drop_column('code') + + # ### end Alembic commands ### diff --git a/migrations/tenant/.DS_Store b/migrations/tenant/.DS_Store deleted file mode 100644 index 2cb5b56b7304d64d3171a58266a4b52f9f5bd948..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10244 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 Te#V8kag9RIANMsJo%H+%=tX#= diff --git a/migrations/tenant/versions/.DS_Store b/migrations/tenant/versions/.DS_Store deleted file mode 100644 index e793af55155ef87e8067a2c984e7b421d985372f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10244 zcmeI1&5k2A6op;gy=ZAzutG=(kqr_W!6^To-i4uAu$~8~NviTE@<+NeVpwI*1F+*2 z5aJzpgLxRl0={!yNopz%5~D#HAy-tsj?4BrKEA$=E6%y(={9dTS98u?bIZQ}9!cQR zbKNJ`MN#qrHle+9E!T55?$$M3_oQ|#hzdjnq5@HYs6bTUT~L5MTi5j?Z(|x2hzdjn z4hkqf)VO8)h242;p@YPZ0N5*v?IO=Pz}nOb+b`_STWd<6{`8O(O_Sn?k@)63uc58<< zJILnpD;PW}v1!9*$T)6Dht^+%G~@k7id{0&t!b2+4jSpbjr0Y%4f#EvnK7ABlG18R zZRs{79R*eSrNX0&A{|hhu5O zff>5`q{8J>xQt=aq?g<{bzw3>DQU7Objk}%jo8mn3ZFGKmN1@$MxA_IL3+%X>)b<7 z8uZ@)S@STUPtC4Iv&2dT<)r_Hr`bUZKkxDlJr9iT^4ALH=is&IdBmrO6>bKC{O?UL zQ*;X8UQ8;uO>pH`H*g(-B)@C%tpTo|C#@%qZE9oDTHNa@U-~ECTT(Z`A^EYwp$+~R zTzQRHbm7z`*E?|7`;mNX!hCMv@&Ka+HS{dB7FDiQIHlJxk3T9rz5r3q@8_rMTJcIVHLv)1K!J-_734=CXzjc_Xf4iZAZC@L#Fkof>_2=rN-xU|n*3SP$?e(<8B6&`?s5?O4vE3b;Ykikydtcknv&tT* zJwr{u&b}jh`6zdcZQ*(MaW|m4Q*K zW9+}j(^eK^6&Dn>k1;pwe~LS=^U1;1PUKfY4>pRt?Snr1on>bG;1A#_4xL{EE7aEd zof^~f9vRTb)@7N`WBP6ypN=tUuqqWHGWvXzm=wa)8Z2WrV64ciXsgk-u(#wi%5aod zY|@Uuq4wT?ybr9271|LMm-Re23lZ zf4xpX0gDA?eC={Q`*dvIQ6$R1zXg9>?BOY>Tk}MXOTTgUF?nG%cIT}%r`(!j{oDNi{Lg^H+sAnR V=RBi#J@NcsK5^;1|35$f{|!UB+j9T_ diff --git a/migrations/tenant/versions/__pycache__/217938792642_removing_documentlanguage_user_context_.cpython-312.pyc b/migrations/tenant/versions/__pycache__/217938792642_removing_documentlanguage_user_context_.cpython-312.pyc deleted file mode 100644 index ddc62de095c0882cd647cb33cd8c1c718e103f99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4854 zcmc&&U2GFa9$(wzuZ^AW4-x`3IY@BS#)%UW8d2Jigw{Edl*CFom(zCbnK&EPYj<`X zaE|MNbkg19o$e$+P*GGQsFH`AbPqvA0#qa--OHjbqT2g-xqInb@3_A7>1Niu_9k&@ zP+Q%~J3I6LoX_9>)_(~GS%zGz>HPe|0K@!~Hmu8OR-TQK$|VLe2?jc#Q*>mU38#bB zU7{-i$PK|a)FX=3V9lA4{n<5W3mz9+?M)Lcj9)mt-@Sz%YJta1J*`2)86wcGQT#vc3; z#$Npc<*wh}Z^)3{R0BO}2dqsyR@_C4O{>*d!OIEj$}3x7!u3=7K4>0TZmD?aI3nOg za(X!da`R_UL9g9vqO*9Inel0i zPnc(Pg1`ANGDqVeIWqmu=)h!@>x+z$UL>>UA`@AeKa=f}Lt|*kY(&PF&`2yYhH_%I zKw&Zh(Gn7~IisEt(wJ8W+Q|_GNj%Y-Ya&PNki=mVZ0S-NU~A1NXP-f?Cs)wD`5cJ} z5$+_NZ6LS&4^muU{slZwLGxqKthNlRN2b)dq= zVa<29<6ifj?oVGd5?bfG8aPdCo`TlLp!M>8H56T&xWDT@yAj_w zu7O$VK6P%uVZT^QjawVAEH^_1e|C();j5;?^s4 zj~mxwvsEiUtvzYWzN@UYYOrBb?ndjqV)LprrY4*IhnlD6|KoUCc08VH!spEMZS$!# zN4sqL=g-m3V^-N>wpnXfep+h|U2x|y+3y*%y`0~w!6t%Dt>kW7-EEL}LZDq7I>$3a@O(1IRZOxYTyAu&bZxIu4>S399kxQ@yxTIg(% zl|YVHmfceJ?7?u@MTio@geY(j&GUIt!3U{1%~>{27IZeBgXF7-x|ZuiUMCW%td!`V z0GF$C`J^bMdMKOdAzZ7>5lckF>PNC*a704zfW&9eGNolkzo}n`)i8(}WrQWhVv)<` zhLVlRb*SUPlCYF;TQ7^;v_jXcahhGzo3{tc5jGdDHAo}gO=pX4LcE7gnKw2SAAfUv z2DehtK3a58dBEg@MKbA~8<`n>Yh(t~)35vEvB~k-_{ikjI-p;XQ5A;aUsCMo_2O+1?tAK)oYwii2CzYvD82igqV9>ToqqzxO8iM}drf`)q&hpV3QOw3S#|jXweYL| zGK_n~Ste3y*N_Gdm)jqGpn*YKb6EpXTl1U-dTDd|;MQgE(vERZ!9=kO0`-wlC zSOe>M4UAjz%(a>8i7Sb#r`MY{nlvzN$rrD6T<^ZpeS1V}>sdz|NCR<8C0?6&+TQ!P zz4!C>=)>rvp$9`7L!Xb%s;LE4CdmtByJOcUu1s7#vF_e*YhbD@e{p}Hfl1R}t=@Mt zdTaQ`@W)5i^Ban-W74(c_4JkWRbefEpU6*?9QNLH-tyk?e(WcMY%KQVDcJoO?7n>Z z@|60@YwF8K)$s)l2*krw{QUCt?aXaX9ZhRsp(IxK^s4QB>Of5GpHNT!LIdYZs&5Z9 zrgpuqfj7Q>sn+c=_Ek8jdpYCVj?=xoh%!kbRs3pV$$uWam|8%Yf^iP?hO(ds3dA<0 z$iN?< zFfXE`_)Vgve|E@+Nb!}+;c)!h>2ZLss~JbjUzwJ_Gu>Z#m_XYF-xsxeF9g4+Z6rmo T?gINCkKZx)tgY2i9OC}~m$V8P diff --git a/migrations/tenant/versions/__pycache__/324ed734ed9b_chunking_information_added_to_document_.cpython-312.pyc b/migrations/tenant/versions/__pycache__/324ed734ed9b_chunking_information_added_to_document_.cpython-312.pyc deleted file mode 100644 index 9e7d12653829aabf9e4fe903a51be3b1f3cbc1ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1860 zcmcIlPiP!f7@wJ)*_lkTu}LedB4rSCT{NBSCh2a1C?%^kE+%3uhoa8w21Lk@8Uhj=77yek+2&*Y4gF+?O95|WH8 z$`~?C1!dpmj4>nws@+UcdHen4jnKQ^@|s%9yXq6y3R=FWSqNdI1-@4E?a;+upt(N6 z4pr3)xYMF+%lX=pHdmg29m1oQIGqVdb zvsJBBSt>0om8xgvE9L4!MOA-f1r_;N@Z0rxV$?HeBOdLv@Z_TaW?&xu!n0Ed0Q=+G z;Cu!P@I`ze4b*Gdfi(OgVZ_cn9~;}LjxsyqHj4^lJB`Et+t||o7&|-S`;Y3DN9=!A zxAG6_9vkufpU3WUMYSGJp|nX&$MTw?)x_~cNHH;O-wW`~U=_Mb@j}P38V-&pX_p4r z9T?*&>_V?1V1VhiXh19{mTbm}*W&!pL|w~qOuvmi(`pqZ!mdA7fhOR`30*H1s1;|I z`?9zSQEzictU(@pq+epInCfp_UY=hmn$+c{S`BwnMSrz}&z;w6 zxb65|Mm!zi4tD%@BD<|7NeD{y0DBf#JD4ywQhk&#W|BXvXoS;d!f7+`&45=`4C_CH>eJj^V z4ss_G48|GA4A_HD7zc|&zsJTAG)vlKWSUvoVUSY*@fh-Nc>UXZ0`#Y0(pLcbw^zSa z@11;cs~L%B*%>G5b6avG&JNYy^VLXP9O_$>cf?8(p*SAPCTkVbjAhFKCbaCd>*-sL z<=7k8?UKh>8VX7O32}}kWDeB^u{?VNXxV^&N30?Y{6W<8y`-o6rXmx+fsMQu3|7M&>PtUl>LC!4VoAh4JJZDh$f9m({{$CINR2lc4fV| zCMNy~L_K&W@Sk|$NJejZ@rG{nz{#2Yhy)KFon(IVKHB%*@4cCixttF8I&3CSZlwVD zB9zgRheGcL7xn-I7Jw3zvDA_+SrT#zrz{03RvMdpBIw=I=*{hQ!Xl$abw>nwXV zGRvNg=neVyj|@lN5YV$Y?15P7TRH5E+A=cmQ?w;cj|@BF-*f9=sKeBua-a+p33Na) zz0L|S^pX||VjDX_GjW=T75?hg*1pVgXxFE)A2jW_6CtLJdbh6-Q7X$iI7YZHHq#GLyuei3=J&(4nd)HFa(!`9*qp&56g*+_8-+HPT+0x0k{ZLrb85=08%>)`kf}Cs&hr3YRjz< zCK%l&Q`{@=J}q-NNlB9QUCv0#&v774egcyx8pvMlYRCEMZtgfg!68@Z>OV4yG~LT9 H(tyQp73>%u diff --git a/migrations/tenant/versions/__pycache__/45620002ae0d_additional_processing_fields_added_to_.cpython-312.pyc b/migrations/tenant/versions/__pycache__/45620002ae0d_additional_processing_fields_added_to_.cpython-312.pyc deleted file mode 100644 index b23bc199c0d02096e3b5da3824ef387928d155e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1900 zcmc&#U5Fc16rPz(CbP2}Nw>BuuF9ZwODNl9r<-VlwC-;F*}_J!tv^v1Cb>7sq&IWp zy_0Cfhb;(#@8XLO3WCV)gAcxlf{22YEi?~PD5G!s(zog&NMH2aWMalv&?4f6d+s^+ zoVn+md(U@fFP%0d7`x40<7-uteh|WBC=s*&C@}9zNUBOmMhcNTN>z~spCE~_OC2w`OU)bv}} z>`;V>VLXfbE{6}y&2q_HEflSMK5scVkH#9zVYgvf2oEFTWU*K@jO!w$tQ;z|TM6glCxa9_u^y#9T4sPIVDA4ai+k{a zjz@cPLz4|yk?bcYVq2SV(-kQ(y*}Naa61u$61(b-@Csum@+1FS-^rNo(Yue&pU^*i zYyW}o)c@#PkNKXPWIJ8a%&xH$y(;?4+y_#2wi0F#t@k?E^X)!nqCP`oTF*~HS?OMn z5T{0PcxbAyx$iI^Bir%Mg@v3<-KW!Ha$_~1y5V6W-7vMDBtAv6Fk zcAb)5#|stigxbcKPpwl*u;Ycg0Kqx8gG24C&j4p1OZy_zoA2eG6Q-Ewo_T&_b<46> za%D!lHTqia4CT%RdX$@G+>eCZ6Mek4nJeQip#za}4&go~v^(NEZj(6z(LCp4&jD?8 zAv_nylnuc~z_(-hje#$ekh@RqUH5rgxNh1>p__O9U$A%kE-_8*2S&i{E-i9 zAGsg6pUizx`?CF6`*SipUk#RC3e=aszr|#jf9mr5mBmYod-o3=94s{gwRyYE)0ZE- za_rKvz2#x85iB(WwROAA`Zw#}Zho~nJpV#aesPFe!IFDbZL`A=*`FE&G|q8@_!OAG zZxBfN=YU3uJFr#nz&1Ixh2qvKECsPM0S-1Rh-eQ?^rx&cuDn?U)e@B+J0!H?9@qkq za0by=z47}kf_xuLz6NCcewB-r;lYQ8M^6T7NnG+oJ{_o!$K_LjdU`6q|Hf5yb>t&E z8>Va}9>J&BL!cG?fu8_!BO%N3Pl_h1zuYCs3*Si#H*{(4-fjI_ d=7H_>wanc>(g(JUpS7fXLEfKF%7sxHzXQ{9p;iC@ diff --git a/migrations/tenant/versions/__pycache__/4f22dd6260e3_embeddings_for_openai.cpython-312.pyc b/migrations/tenant/versions/__pycache__/4f22dd6260e3_embeddings_for_openai.cpython-312.pyc deleted file mode 100644 index 4923fd93417bb5b07f182069a9a63f3ca5f172f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1696 zcmb_c&u<$=6y9C0*PD&qpOy--RJjrrvcPuYc&lI`ptV!vK;o*0BCSBHwP)gNy1Qd$ z*9P~LNJt=YLLjwOBK2D2960hPAaQZjRH+7T^un!Rdg+NbYj5o$5E5dv`{sLZX5P$u z@0IPkyQw#u7Dmg~8yIUxq5#{VCW%8bX54dZh}@;{t05%4UAZTm!orv3Km zDUJ|Q59S7wT>nEh&O~#kJ&LzQq_xGtq&72=q^GkYgrsPPL1JtZg}#uR-(cr(L`~Co zEypnlaMQGGCfVpJFi7>fj$<_)%;phknLSK>(?(3OT7lieZ0`ATTY#Fuf*7*hTW4Wz z*Tr5CE&zrXY?Pa)yv{7y3R!Fhp;yVbm{KK9*Y#MU?ghAwDN9@-#KD%w)K0sHTLGa= z^FMYhr?rLMK2vUtZRx9oV!Q3Vhx=9H`2n?TFJS3w)OIb}f5G~#Fye7P`?7e0?}hzh zy<{#GYm{`F?cvMyVhwj3(&yn65$<7!bVBUfZE6J& zoL>yEXTd1XPN>h`IP-amd=oBzm|)8;bowmO?SKb_X$FqQtLE>4*byGf%IA&U#xR}# z8Bl$<{ssEx%I&qU*1mrKzJ4SxMOJtJ`aR>WvG?J3t4DGrvTp55_q4m(Uh;nTNY*3k z&Ha_*OyMw7IL_#Y8U6cLh8g`q=ItLY9?92W&as?1lrwiey3-gIs>6Kkf&A{&3fhII zsYG0%FT?p>cr$oK`9CUv`1dy>VqwTWX@hby=AY@`*Q2 z)p^h_!0(>~F;3O`?)vb|YY*ku!xgzCOPD6-s>u?T1If2r;RcjvnDS-xEC{C3$?MBf z+`Tzfo7D1JTPDyRJ3iA8hAV-5lXzjFC_lnqPWViH(hzBGyD}##qXkLKhhh8)5`KO3 diff --git a/migrations/tenant/versions/__pycache__/505b61314bba_defined_interaction_domain.cpython-312.pyc b/migrations/tenant/versions/__pycache__/505b61314bba_defined_interaction_domain.cpython-312.pyc deleted file mode 100644 index d01f0fe80f7974c8d2a40447ee2f1ccb41e78747..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 765 zcmaJ<&2G~`5Z<+u*m0Ap2&4!O$TyTjYsdL%h!7I0ITVQ^aRA8|Ywex3R&B4@O#-PpxMAjJ)6C1q!{*ZdT5$(s;0S7V# z+m|r0J=YuTy2D-1wcYW=b0@urd;8;&HyBygcg4MnON|vrWoxr@+1l(FS2J#aF8x(a z!Z})?3w(5exT&^O$@NF)6-#Fs2^VMXMa14Y&zK-*?18X-nBN4>(>Xjj zbbKgMw#Xo#Iuz!RvZC^{XlWs`Y@`W4ng=_itibZM63fYDN z-;(@pE24D?OZ2s7@}~6uKOZ+_Nj2XZ)CsPBiLy!A+kD-5TgG=)qNPBUbhk<)lqBLX zEDe%E79}xP!j+bIlae$(g=|r3f|Mq|dEm0G8is$vh?6`%4O0?9DoTq&0XY>R%d1Ja zy7V7T*XE;)(OC+Qc}HfkT*8xZrDKeLXboKZwT*D+3+h~%sC92?Uhdpqwl8uJR| diff --git a/migrations/tenant/versions/__pycache__/53fee8f13cdb_defined_interaction_domain_2.cpython-312.pyc b/migrations/tenant/versions/__pycache__/53fee8f13cdb_defined_interaction_domain_2.cpython-312.pyc deleted file mode 100644 index 7a7c28405ae27a0c9f1a466c48820776d8924db1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3476 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 diff --git a/migrations/tenant/versions/__pycache__/6fbceab656a8_adding_algorithm_information_in_the_.cpython-312.pyc b/migrations/tenant/versions/__pycache__/6fbceab656a8_adding_algorithm_information_in_the_.cpython-312.pyc deleted file mode 100644 index eea460b8cde3d739a0397fa6e21f9fb9cbf3fd9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1142 zcmah|&1(}u6yM!!Hrs6?Z7r61D61C@(r&&D(F&#UP@xg4C=J58*_k9;_an}3qVbeM z!E0{?Z-OAw{sV&GRq)b7D`h?ErMGJE(vxpCiAlXU?7Vp&JMZiF=1VLlF|hV(&FWW< zVZKvgus{x0HxI`SgP1adSj3sE#g#dh@*y)+<`G{Gqi|V3p>hPah=eVsJcc4brFJMT zzT93y$gpd&X4V{Hcy&uQ?5aa7%`+Suc-gCCdByfH(eyxNIS8AQw1!)TOMh7@7UW#D zqGPR+%jUFv&w|~8T+Lx!PbYGTY*v$&3D!I;7l9PyR3ep`Pvqv4NjaG*q~J>|# zSAPJkXg5t$tC%<*Ce))ZX$YyhV>T_@=UmMfmV3N#-y;Cod!|dHp1xKdQayH+yN{ML zt0^_96p7QQI4_htj;lR&uDEg$xB7x|yM>ollp=1JPTRt^ry$(Irqc*`%czk6c~|kU zt%0?L35D5JMv+hKUIo%&e(=Jp)y>uI z`L|Q=X5Y;2U%T;f?bG^)_0N@q#e4gYpB!A$4*3e1grCpg%!4ApIRVW7aYo!3OhP3R zfqR5v8s~aV9!JotewWDvwbGzu3Wz_3oac5g{|g|`!gi^(mw#!qw7s~0Id#aVgFEqY zKccG0(N)!tXePEQhTaF#eP(K=UdL9O#HeGD^k0u3qaoCxSRtCN*HxGUY`VULa0A=O zRUJF%AfajeljW&+6P{$##J9*CSm|84X&@&dmSul(0?YqC$FMWsn3)riiC*l8M-y|M Y*wMr^kl18L`Xz9z&UT|5n+eMJ18v10jQ{`u diff --git a/migrations/tenant/versions/__pycache__/83b4a2aedbf1_initial_document_models_added.cpython-312.pyc b/migrations/tenant/versions/__pycache__/83b4a2aedbf1_initial_document_models_added.cpython-312.pyc deleted file mode 100644 index 920338c91a08a591545fa0404c90c51d7d4f5362..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4502 zcmdT|O>7%Q6yCMhKiT{=Y26Bsd~*F^Umr;RYOXE2O>j#GC!Gx0T6Hi4d$bvor6_ zym{Z7H*eqUcde}~1<%85VR{N$zmksqxU9y;Ff`^VM5QQ1BbP|$Tqze#+HTREVi1$^ zAa}|O#RtWYJfBdhCgg>hExJR#S#eAfG=Ud`aXC}SVMz-nWrRgF$RmUi%TD4MK^0^v zI2MluhX>O`e3Zv1Jw0G@uo?@pqYCCV9E?L13r72+L*f3RaC9g*Fccd+73)9IH`pKT zA3n*l>qO}gt-Iv>xZdKFma*U%uf0&ap=?}gBG@$AW?r{Z+XQ$cTJzZ5>t4H6e+<9 zyKUsnyDqV1dlDU^+Uf}G7HW0ayKR**>5e&#c5#n`zdQDBcSzjC-i}ebg{8wGb2BWB zce>rSWBrZxWNEZFORrid&LO|iXg`eJx9!m#e=D1u{O2CzviEk?vKGBnL*k}@!G6Ml5ZXhg|LoNdb&(xQ;*D}aDL0nN5seNzpf=p8l!PUNL*fzM*SxkduM-zKk<57=ytN9MNI z27+=Vw>733f(Sx)K@r!#HB`m9G)72}vg&N0Hp!L@qC(9I$r$w(6FsLHCUmL1?j4oI zLQc|sW0HomSkb-jY6=L_{Ul4C5^`W^4d2rAzq%K)s|0IbJC~ zOJy$!nHwUWD(3O$)CMd}J-ruspDcvc$ixSuL&+#N5Q!^tJ}uvhBxIGpA@``kIG(XO zk#jTn?XgH4=S8_llKlw6Ggy@KMmr~D6u|zJulo99;np=y=7cwMr_87rRZ|36k8lAAFVROHdS0YyL_Q^VKG^bSD8~b_4?A0 z<=#^7Vz~TTl{slsYh%AU@^#ObJ>T@K#S)eGQdQ=Pb3~$)SiD#Um1@#cV&>{8r_S(`(Gzu!cpwvXBH)rT5GlbGA-xJT|_@y!yDS&EtLCO?iC8fR#Xx zt!`rr=9VUxQ>E16)$+M26SKz>lY~m4m4Rw!_zO>!Ic+m`g3hwarszIgm{`fJaBIw& zIyM7EM-!k3)KI)`E3gw3`2OVl<-3<3WUBj*m!}-?2#RDWxj0cqRpw1w^iHsCXXgN0 zr7vCypIc+zc^2K1eXPf;90PZM<}ynH1SuOIL$&o~)=qY}OgL(3@s=aqb(s+UnQ`S1 zXrho$u|mGrA(t7%SOkH?3}H$SVG<}x2r9h^$u}kQNQa?60!1ZU^GGLeCo6m5lpQ5D zH#%@UjlG4=o#Q_+hYeAoX5Gh;puusvj~5}f3K?r<^&^oNGuLpgsC1L{{EGG0L2o51 zbM(I*YOGEg6`E$aV;}mTM#kZQnC&ui{e|MRMpH^Ik|ODsxrWuadeQ@JI9coPowG zsRLV?dP*$I#1ck)N1LTbKXnJCJG&4MwHpZrM=}c}SGcui> z%w$J({R=NEB{Ipc7Fc(?XV%^Bu^g8l9U36?N7(-f@LUMR=oa8!t4pm5II$RZwA6cQ zOFB5Q)Mn?N53RLW$MU+e#-qYoi{ps@8@r<|b~O8@{}%o^c0)+11=eLB42ty~8S5f6 zSMzF)gGvrzCyv-H6sAtZ^>*ed%@&GncRAg0bWWo419giPbZT(n*CM%d^1{di$s z<8~65SFX=ZETpY5Gf(|$$zL%q`vJP|p9zdSsmF?Wu})^^%{-|(e#0eRXkt<)j$e&r z*IuF#^8zy@9s+BfP)@kOZ0Cdp83K8&qgAw#*9v`Wq}pJKS{0mPLXShXdhd4A`XwL5g@ zoq}i|IQxy23S302ybZ$NS&5~8XAzbU-on(C0!=^+${9mBWm8gff?XH}5RZ`dax2f0 z9s^*V*ni+P8*&o#0oZ{7&}>NIQQ_J7ozvM}WttZstCR1POynZf#S)f<{jz1T1agR5 zvdb}Pf@KFe<-5df&~9+YG#dXaSdvGy4%8AwUiq#COe9XgbWEzm!-3^{(S#_^>QK@@ zv~#YHYYw?U2f@m}^I#lcPZmY-tE7s`_Z~s){~+}5X+rnFs`kEja5ee9_XI$)Z&m-M O%3?{}?~%o+sEl7t>P6Q8 diff --git a/migrations/tenant/versions/__pycache__/cb01c9192dc1_interaction_appreciation_should_be_null_.cpython-312.pyc b/migrations/tenant/versions/__pycache__/cb01c9192dc1_interaction_appreciation_should_be_null_.cpython-312.pyc deleted file mode 100644 index 4ee418c61d26fd36a8b8424e88f84d3e5086353a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 812 zcmaJfgc5M4WI;yI|2jSv!QI24s4AweZyR%`F1iCBBht{n)c z9QY0N#=R2%gg;Q33lb-8g^Ej0>^en_I55&a&)b=uoq6joosNx^eLgORM;Sya68?+WS)v{>g0}5NTsnDL*)~xp*_tP8% ziSsc}9g<}N;xVa+9PxrtCj#g2<-x&yC*`^0d!9q2Lt#h?mfQ9Vn2e=9xj*PTapd{& zuD=`5*q=v0_8qc0+#L3RkWC8qo&b`AGf>cX0x#HF_qNylEysJ%_qO{zZ=)9kez0TP zKlE^GMrrcwuxu|@F58P0<4S}Ds44%VuHXbs(W!BGiiD-Nbjsx?_Z4SF0@8hcw72yv zz`i>WJd5}{_bHd;HNPjF0Zgul`(y%-_uTq5*3|* z&{{}$v0XgA))z18i|6{{2yj|3hBvZl*(@?ul!91R-QLt~FDaOzZ*@zwl=uH>MN_3z z)6PMk5c&@)Ta>>|=ap9!zpVpp4LW6Qxol!gd5m${Bn*;h91AUDY0Ec^uy_Q?v@|6t zEpheSWk(mp*EA9&jYpV~2$(Ew3K^tSVxCr$2z}{4JzZK46HW^Tk3?5R4Yg#T;JjuS t#!s_h)PJuaqx%(g&n?uxGqcWC@6I}BtG5(%Zp`do4bx~{v=vlC`~fmC*iZlf diff --git a/migrations/tenant/versions/__pycache__/d173cea8d204_added_timezone_information_of_chat_user_.cpython-312.pyc b/migrations/tenant/versions/__pycache__/d173cea8d204_added_timezone_information_of_chat_user_.cpython-312.pyc deleted file mode 100644 index a0f5e48580305ebe7cd9943ee2377b6345a28310..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1397 zcmcIkO=uHA6yCpVHruAuDil4`)r&-EH%Y6lL50$IsM-oD7ShVH*_k%c-JLkIiN;d} z!E0~cq=iD2_96%(2wn?bdWayaH@);$EnYnNX0xHui(VX?0ZU3TS?f|ODMB}yuiOG(%oQXdPY6iR~B zn{q~bxHgFpMn+Ke@I&Hbqv|gb>e)e+_y$=toQfS7b%v=C5Mv6A8<;WfvwdVt`vIo5 z!{6%qb=;^%p6O!2K)LZz2ip@UpB-y^Fe?~NIh%9N<<8}ilhdatwgYSwK@^O9Ha|9; zJv*Gw8o68{mo1E*8OdkI$Fq4|-{qZV#84u&*|4`ea@gA)(TOJ#9Vw77GGSj4`FH}5 z?RBR!xXuNfNDLAk^N!ll4o)O>`L%=lj)vqdWi!rz5?ksf&kSob&L#dWf3hq7f63nz zG8znzqiL}=f}z&Ie0K zVs@xbwRQDIK&$@J3t^vk|MQu7i{E2rUYna5o5@=_vq(v;Odgn*3A68#Q_LvhMr@du z8hCQrEaI9=njZE86X6DSNiEX7>Jp7e$;<%zHh3GDa=J0In-LaNhLP3j%<5vZMHa27 zf6iuWq}B|R^%?|4m>z*@55s0xK`aYj74^x?qnVYF^^+T!waoL&Z>4vsH>vG`*2LAF zx%t+~g_d&rbNpy{ePHA0+R^8QSM+uBWpi6|DY_;0SNdTFBQ0mc)0+| z-+76of98iuw>B8>0w(C@|*Q9+s zi$>#rMVRLKtOK)5ZQrR_Kt1fTP)E3ieZ(x{M;K9F(;p@O)XsYZ)m?m%9tSV~3fU-# zJy{gRZ;~o1Kl%i5@RKmOrwP5smbH)lL(A!p{YOBg4=wB8Rav|(?)S-}8MW~X@P0=I diff --git a/migrations/tenant/versions/__pycache__/e2735d216d3c_defined_interaction_domain.cpython-312.pyc b/migrations/tenant/versions/__pycache__/e2735d216d3c_defined_interaction_domain.cpython-312.pyc deleted file mode 100644 index da04751ccf882e344b0170b0f5abc3a4f5606e37..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 765 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 diff --git a/migrations/tenant/versions/__pycache__/f6ecc306055a_adding_session_id_to_chatsession.cpython-312.pyc b/migrations/tenant/versions/__pycache__/f6ecc306055a_adding_session_id_to_chatsession.cpython-312.pyc deleted file mode 100644 index 1ccec0d438193bfbbe611effc92f734be36f16dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1112 zcmah|&ui0A9M6w7&9YWD6^9;17{bV5OWL*FTE<|s9wx4W6UBnYH1DnLOq2SOR;!l| z23~h^R|P?3`v*k9tKh}M1|uHzvfH$H*~#xqQ`UL$!T0ye_t)p;Ya$^raQ3RL^^Y9G z{Gi6*fE}FP0*D<3F=Ym^h_l!RSLRr%^A=x@ph!82qGbW`4zGyM zo-ZR*x2v*?UAOMoavjN@BNu9hx7PPa(kK|x`-;3;q6;O0f z*rk=>?1r^iro$*PXx@Z{>ERB2DOB`2I=TwCVMM{gcGauh2353MmSt2dtV9V-=Sv1c zy6IT0hV65%;R}VnF06S3pn1>qXvve8>K*FGu6pxsA-$T?lWLJT&5H9>z3#ZiBWK!` zi?|&c>a{jrUQvs9@eK57}OvW0S!c Fe*vQ*5H$b* diff --git a/migrations/tenant/versions/__pycache__/f88854b2ac59_full_support_for_multiple_embedding_.cpython-312.pyc b/migrations/tenant/versions/__pycache__/f88854b2ac59_full_support_for_multiple_embedding_.cpython-312.pyc deleted file mode 100644 index 770d81dbecd6be34ca153edc24242e71f7dcfb8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4680 zcmcgwU2NOd6(%L>kCy!Z(?m_n6-iwswPh<-<~Uu~#F7iAi5({vNU@kL=DKLmd0fj9G z3IUe#K_yt=pyiZMIa~8V8Oqd%T9nFr+W~5?v|Jn%F$ArC^5sZGh7s&ouew<**z(Nkln2;IDj0_BA2Zlz4 zOlE9vc5HZfa9?)+@X#pF-=(Whv35YKOhLm}G~Fl>tiP?;alaos?zdm8@0ruYfd=8d zPdK`P2I~$kxLfNAphc_^a=Qy*m-AW_@Qp`3xyvop85CURmZ(>Fd^4I^4Ee^LG+3ME zQWRc}EY)Lv0;^G<)t@KMn9m~J(+$rSR?hn@wr(&7-AydEKRN?NODt+Bu}k%n_1W)i zq8)Jeb*a8X>}J^!_gQRqmOp=XB#dr1@`YZP^V)@N9`ACfb-B%5*<&)M+1>?U@7lMp zclGb3VehuPv3M=&aARuFeA?4+In;@|Q1^0=`~5WNKjUh7En+|)u0)6*-lb;o2%fgf z!JMd@Ck-B&>+(;a8}oE)OsaRv=COO5>UKaz6L6D7Rk(VkSq0miQLEs)bX_10D_AWV z^L7i;iXy#UMH$&)sc6WH*bWuvtLo{8T`*QHW7TjJ;MN@ko!)g9qF$C1Mbs)-m1H}% zF2Bn_#(u`yK_r*oNvw-?I=gSZ>zggY^yj>RvaB0KQbb>5;@oLmvpXKqv3aN^ST3nB z3?4&tg<`6M&9He+G)=*hYI8IA ztYLRgtXX{x*TyxKMkA{rJx1iRL~4!FXr;7>i-tyQ9*Tve6z6fdW{2OX%Mj5j^$6M= zzUUe3tOrd@xjS-4p$VdMo%w|@FG^Uio=)X5|IozOFeDCxxr|?w(4nrnG@$AYs7lN z79l{@9ve?E$)CjP`-Nn+q37hO}$qda|e^iFbcH92@EnO#k0ukSRI*;~n9-`r(!$2`L`S0+9Y&7Ij>+^8pX zyv0J`El#~1J%7~f++%Un;T^7bmFqS84w%0>W}Za1IqV3xt#aG0>@FLVQ|G75uIH~MEN-8#8?m?{UpIQ28zzHr5DnNQ0Rjh`{O13PO`NI#9_i!V zRsSV2+62dV)%<_rJ?yK@{}G*R>b(gPfeOQ-$a1u4MQT<{W1!EYa2<^_t4Pi8$Y$uG zY>zP(p8Vk_KYOkak90tF;H9Pi6Y=*K4g) zSa$u9{HgY7ZRM%2GGC8rPf4cow$)E8P6w^E>UF^|cMM&R-{$g;h}JH1`^)AlC(PGN z=E50MK5M@F-aUqSmpvGGz%Zdh0qVf1xdW7IKn5$^btvo9k|SS-0M~nN_E_AsD_;iz zEBPA$4i3BW$5rX7DI&`$u8!Gtw6GGo5wf@mn7$D&n6E(`i{3!a><32^KGfiB