iatoolkit 1.4.2__py3-none-any.whl → 1.9.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. iatoolkit/__init__.py +1 -1
  2. iatoolkit/common/interfaces/database_provider.py +13 -8
  3. iatoolkit/common/routes.py +24 -6
  4. iatoolkit/common/util.py +21 -1
  5. iatoolkit/infra/connectors/file_connector_factory.py +1 -0
  6. iatoolkit/infra/connectors/s3_connector.py +4 -2
  7. iatoolkit/locales/en.yaml +72 -5
  8. iatoolkit/locales/es.yaml +71 -4
  9. iatoolkit/repositories/database_manager.py +27 -47
  10. iatoolkit/repositories/llm_query_repo.py +29 -7
  11. iatoolkit/repositories/models.py +16 -7
  12. iatoolkit/services/company_context_service.py +44 -20
  13. iatoolkit/services/configuration_service.py +227 -71
  14. iatoolkit/services/dispatcher_service.py +0 -3
  15. iatoolkit/services/knowledge_base_service.py +14 -1
  16. iatoolkit/services/load_documents_service.py +10 -3
  17. iatoolkit/services/prompt_service.py +210 -29
  18. iatoolkit/services/sql_service.py +17 -0
  19. iatoolkit/templates/chat.html +2 -1
  20. iatoolkit/views/categories_api_view.py +71 -0
  21. iatoolkit/views/configuration_api_view.py +163 -0
  22. iatoolkit/views/prompt_api_view.py +88 -7
  23. {iatoolkit-1.4.2.dist-info → iatoolkit-1.9.0.dist-info}/METADATA +1 -1
  24. {iatoolkit-1.4.2.dist-info → iatoolkit-1.9.0.dist-info}/RECORD +28 -27
  25. iatoolkit/views/load_company_configuration_api_view.py +0 -49
  26. {iatoolkit-1.4.2.dist-info → iatoolkit-1.9.0.dist-info}/WHEEL +0 -0
  27. {iatoolkit-1.4.2.dist-info → iatoolkit-1.9.0.dist-info}/licenses/LICENSE +0 -0
  28. {iatoolkit-1.4.2.dist-info → iatoolkit-1.9.0.dist-info}/licenses/LICENSE_COMMUNITY.md +0 -0
  29. {iatoolkit-1.4.2.dist-info → iatoolkit-1.9.0.dist-info}/top_level.txt +0 -0
iatoolkit/__init__.py CHANGED
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # IAToolkit is open source software.
5
5
 
6
- __version__ = "1.4.2"
6
+ __version__ = "1.9.0"
7
7
 
8
8
  # Expose main classes and functions at the top level of the package
9
9
 
@@ -9,14 +9,19 @@ class DatabaseProvider(abc.ABC):
9
9
 
10
10
  # --- Schema Methods ---
11
11
  @abc.abstractmethod
12
- def get_all_table_names(self) -> List[str]:
13
- pass
14
-
15
- @abc.abstractmethod
16
- def get_table_description(self,
17
- table_name: str,
18
- schema_object_name: str | None = None,
19
- exclude_columns: List[str] | None = None) -> str:
12
+ def get_database_structure(self) -> dict:
13
+ """
14
+ Returns the structure of the database (tables, columns, types)
15
+ Format:
16
+ {
17
+ "table_name": {
18
+ "columns": [
19
+ {"name": "col1", "type": "VARCHAR", "nullable": True, "pk": True},
20
+ ...
21
+ ]
22
+ }
23
+ }
24
+ """
20
25
  pass
21
26
 
22
27
  # --- Execution Methods ---
@@ -24,7 +24,7 @@ def register_views(app):
24
24
  from iatoolkit.views.profile_api_view import UserLanguageApiView
25
25
  from iatoolkit.views.embedding_api_view import EmbeddingApiView
26
26
  from iatoolkit.views.login_view import LoginView, FinalizeContextView
27
- from iatoolkit.views.load_company_configuration_api_view import LoadCompanyConfigurationApiView
27
+ from iatoolkit.views.configuration_api_view import ConfigurationApiView, ValidateConfigurationApiView
28
28
  from iatoolkit.views.logout_api_view import LogoutApiView
29
29
  from iatoolkit.views.home_view import HomeView
30
30
  from iatoolkit.views.chat_view import ChatView
@@ -32,6 +32,7 @@ def register_views(app):
32
32
  from iatoolkit.views.root_redirect_view import RootRedirectView
33
33
  from iatoolkit.views.users_api_view import UsersApiView
34
34
  from iatoolkit.views.rag_api_view import RagApiView
35
+ from iatoolkit.views.categories_api_view import CategoriesApiView
35
36
 
36
37
  # assign root '/' to our new redirect logic
37
38
  app.add_url_rule('/home', view_func=RootRedirectView.as_view('root_redirect'))
@@ -85,9 +86,21 @@ def register_views(app):
85
86
  # can be used also for executing iatoolkit prompts
86
87
  app.add_url_rule('/<company_short_name>/api/llm_query', view_func=LLMQueryApiView.as_view('llm_query_api'))
87
88
 
88
- # open the promt directory
89
- app.add_url_rule('/<company_short_name>/api/prompts', view_func=PromptApiView.as_view('prompt'))
90
-
89
+ # Categories Endpoint
90
+ app.add_url_rule('/<company_short_name>/api/categories',
91
+ view_func=CategoriesApiView.as_view('categories_api'),
92
+ methods=['GET'])
93
+
94
+ # open the promt directory and specific prompt management
95
+ prompt_view = PromptApiView.as_view('prompt')
96
+ app.add_url_rule('/<company_short_name>/api/prompts',
97
+ view_func=prompt_view,
98
+ methods=['GET', 'POST'],
99
+ defaults={'prompt_name': None})
100
+
101
+ app.add_url_rule('/<company_short_name>/api/prompts/<prompt_name>',
102
+ view_func=prompt_view,
103
+ methods=['GET', 'POST','PUT', 'DELETE'])
91
104
  # toolbar buttons
92
105
  app.add_url_rule('/<company_short_name>/api/feedback', view_func=UserFeedbackApiView.as_view('feedback'))
93
106
  app.add_url_rule('/<company_short_name>/api/history', view_func=HistoryApiView.as_view('history'))
@@ -128,8 +141,13 @@ def register_views(app):
128
141
  view_func=EmbeddingApiView.as_view('embedding_api'))
129
142
 
130
143
  # company configuration
131
- app.add_url_rule('/<company_short_name>/api/load_configuration',
132
- view_func=LoadCompanyConfigurationApiView.as_view('load-configuration'))
144
+ app.add_url_rule('/<company_short_name>/api/configuration',
145
+ view_func=ConfigurationApiView.as_view('configuration'),
146
+ methods=['GET', 'POST', 'PATCH'],)
147
+
148
+ app.add_url_rule('/<company_short_name>/api/configuration/validate',
149
+ view_func=ValidateConfigurationApiView.as_view('configuration-validate'),
150
+ methods=['GET'])
133
151
 
134
152
  # static pages
135
153
  # url: /pages/foundation o /pages/implementation_plan
iatoolkit/common/util.py CHANGED
@@ -168,6 +168,20 @@ class Utility:
168
168
  logging.error(f"Error parsing YAML string: {e}")
169
169
  return {}
170
170
 
171
+ def dump_yaml_to_string(self, config: dict) -> str:
172
+ """
173
+ Dumps a dictionary into a YAML formatted string.
174
+ It uses default flow style False to ensure block format (readable YAML).
175
+ """
176
+ try:
177
+ # default_flow_style=False ensures lists and dicts are expanded (not inline like JSON)
178
+ # allow_unicode=True ensures characters like accents are preserved
179
+ return yaml.safe_dump(config, default_flow_style=False, allow_unicode=True, sort_keys=False)
180
+ except yaml.YAMLError as e:
181
+ logging.error(f"Error dumping YAML to string: {e}")
182
+ raise IAToolkitException(IAToolkitException.ErrorType.FILE_IO_ERROR,
183
+ f"Failed to generate YAML: {e}")
184
+
171
185
  def generate_context_for_schema(self, entity_name: str, schema_file: str = None, schema: dict = {}) -> str:
172
186
  if not schema_file and not schema:
173
187
  raise IAToolkitException(IAToolkitException.ErrorType.FILE_IO_ERROR,
@@ -197,9 +211,13 @@ class Utility:
197
211
  root_name = list(schema.keys())[0]
198
212
  root_details = schema[root_name]
199
213
 
214
+ # support this format
215
+ if root_details.get('columns'):
216
+ root_details = root_details['columns']
217
+
200
218
  if isinstance(root_details, dict):
201
219
  # Las claves de metadatos describen el objeto en sí, no sus propiedades hijas.
202
- METADATA_KEYS = ['description', 'type', 'format', 'items', 'properties']
220
+ METADATA_KEYS = ['description', 'type', 'format', 'items', 'properties', 'pk']
203
221
 
204
222
  # Las propiedades son las claves restantes en el diccionario.
205
223
  properties = {
@@ -242,6 +260,8 @@ class Utility:
242
260
  description = details.get('description', '')
243
261
  data_type = details.get('type', 'any')
244
262
  output.append(f"{indent_str}- **`{name.lower()}`** ({data_type}): {description}")
263
+ # if 'pk' in details and details['pk']:
264
+ # output.append(f"{indent_str}- **Primary Key**: {details['pk']}")
245
265
 
246
266
  child_indent_str = ' ' * (indent_level + 1)
247
267
 
@@ -40,6 +40,7 @@ class FileConnectorFactory:
40
40
  return S3Connector(
41
41
  bucket=config['bucket'],
42
42
  prefix=config.get('prefix', ''),
43
+ folder=config.get('folder', ''),
43
44
  auth=auth
44
45
  )
45
46
 
@@ -9,14 +9,16 @@ from typing import List
9
9
 
10
10
 
11
11
  class S3Connector(FileConnector):
12
- def __init__(self, bucket: str, prefix: str, auth: dict):
12
+ def __init__(self, bucket: str, prefix: str, folder: str, auth: dict):
13
13
  self.bucket = bucket
14
14
  self.prefix = prefix
15
+ self.folder = folder
15
16
  self.s3 = boto3.client('s3', **auth)
16
17
 
17
18
  def list_files(self) -> List[dict]:
18
19
  # list all the files as dictionaries, with keys: 'path', 'name' y 'metadata'.
19
- response = self.s3.list_objects_v2(Bucket=self.bucket, Prefix=self.prefix)
20
+ prefix = f'{self.prefix}/{self.folder}/'
21
+ response = self.s3.list_objects_v2(Bucket=self.bucket, Prefix=prefix)
20
22
  files = response.get('Contents', [])
21
23
 
22
24
  return [
iatoolkit/locales/en.yaml CHANGED
@@ -52,8 +52,7 @@ ui:
52
52
  company_config: "Company Configuration (company.yaml)"
53
53
  prompts: "Prompts"
54
54
  prompts_description: "System Prompts"
55
- knowledge: "Knowledge Base"
56
- knowledge_rag: "RAG (Vector)"
55
+ knowledge_rag: "Knowledge Base (RAG)"
57
56
  knowledge_static: "Static Context"
58
57
  schemas: "Schemas"
59
58
  schemas_description: "Data Definitions (YAML)"
@@ -78,7 +77,6 @@ ui:
78
77
  saved_ok: "File saved successfully"
79
78
  save_file: "Save"
80
79
  credentials: "Email and password required for login."
81
- saved_ok: "Saved successfully"
82
80
  deleted_ok: "Deleted successfully"
83
81
  user_manager: "User management"
84
82
  admin_page_title: "Admin access"
@@ -87,6 +85,72 @@ ui:
87
85
  logout: "Close session"
88
86
  error_loading: "Error loading file content"
89
87
  loading: "Loading..."
88
+ add: "Add"
89
+ create: "Create"
90
+ delete: "Delete"
91
+
92
+
93
+ db_explorer:
94
+ data_explorer: "Data Explorer"
95
+ database_connection: "Database Connection"
96
+ tables: "Tables"
97
+ data_explorer_description: "Explore your database tables ."
98
+ select_database: "Please select a database above to view its tables."
99
+ not_table_selected: "No table selected"
100
+ view_yaml: "View YAML"
101
+ save_schema: "Save schema"
102
+ select_table: "Select a table from the left panel"
103
+ table_semantics: "Table Semantics"
104
+ table_description: "Description (AI Context)"
105
+ table_placeholder: "Describe what data this table contains (e.g., 'Active and inactive customer records including billing addresses')..."
106
+ column_metadata: "Column Metadata"
107
+ auto_detect: "Auto-detected from DB"
108
+ meta_column: "Column"
109
+ meta_type: "Type"
110
+ meta_description: "Description"
111
+ meta_synonyms: "Synonyms"
112
+ pii_sesitive: "PII Sensitive"
113
+
114
+ prompts:
115
+ title: "Prompts Manager"
116
+ subtitle: "Manage and test your AI personas and templates"
117
+ library: "Prompt Library"
118
+ new_btn: "New"
119
+ filter_placeholder: "Filter prompts..."
120
+ select_prompt: "Select a prompt"
121
+ toggle_settings: "Toggle Variables & Config"
122
+ settings_btn: "Settings"
123
+ save_btn: "Save"
124
+ tab_editor: "Editor"
125
+ tab_playground: "Playground"
126
+ config_title: "Config"
127
+ desc_label: "Description"
128
+ desc_placeholder: "Describe this prompt..."
129
+ vars_label: "Input Variables"
130
+ no_vars: "No inputs defined"
131
+ playground_inputs: "Variables & Inputs"
132
+ no_vars_detected: "No variables detected in prompt template."
133
+ model_override: "Model Override (Optional)"
134
+ default_model: "Default (from config)"
135
+ run_btn: "Run"
136
+ output_placeholder: "Output will appear here..."
137
+ new_modal_title: "Create New Prompt"
138
+ name_label: "Name (Slug)"
139
+ name_help: "Use lowercase, numbers, and underscores only."
140
+ category_label: "Category"
141
+ delete_confirmation: "Delete Prompt?"
142
+
143
+
144
+ config:
145
+ editor_description: "IAToolkit configuration file"
146
+ title: "Configuration Editor"
147
+ sections: "Sections"
148
+ refresh: "Refresh"
149
+ validate: "Validate"
150
+ select_section: "Select a section from the left panel"
151
+ no_section_selected: "No section selected"
152
+ view_yaml: "View YAML"
153
+
90
154
 
91
155
  rag:
92
156
  ingestion: "Ingestion"
@@ -115,8 +179,11 @@ ui:
115
179
  delete_message: "This action cannot be undone. The file will be permanently removed."
116
180
  delete_button: "Delete"
117
181
  delete_cancel: "Cancel"
118
-
119
-
182
+ target_collection: "Collection"
183
+ select_collection_placeholder: "Select a collection"
184
+ collection_required: "Collection is required"
185
+ collection: "Collection"
186
+ all_collections: "All collections"
120
187
 
121
188
  tooltips:
122
189
  history: "History of my queries"
iatoolkit/locales/es.yaml CHANGED
@@ -49,8 +49,7 @@ ui:
49
49
  workspace: "Recursos"
50
50
  configuration: "Configuración"
51
51
  company_config: "Configuración Empresa (company.yaml)"
52
- knowledge: "Conocimiento"
53
- knowledge_rag: "RAG (Vectorial)"
52
+ knowledge_rag: "Knowledge Base (RAG)"
54
53
  knowledge_static: "Contenido Estático"
55
54
  prompts: "Prompts"
56
55
  prompts_description: "Prompts de sistema"
@@ -62,7 +61,6 @@ ui:
62
61
  monitoring: "Monitoreo"
63
62
  teams: "Usuarios"
64
63
  billing: "Facturación"
65
- company: "Empresa"
66
64
  files: "Archivos"
67
65
  select_file: "Seleccione un archivo a editar"
68
66
  select_category: "Seleccione una categoría"
@@ -84,6 +82,70 @@ ui:
84
82
  load_configuration: "Guardar configuración"
85
83
  goto_chat: "Ir al chat"
86
84
  logout: "Cerrar sesión"
85
+ add: "Agregar"
86
+ create: "Crear"
87
+ delete: "Borrar"
88
+
89
+ db_explorer:
90
+ data_explorer: "Explorador de datos"
91
+ database_connection: "Bases de datos"
92
+ tables: "Tablas"
93
+ data_explorer_description: "Explora tus tablas de base de datos."
94
+ select_database: "Seleccione una base de datos para ver sus tablas."
95
+ not_table_selected: "No hay tabla seleccionada."
96
+ view_yaml: "Ver YAML"
97
+ save_schema: "Guardar esquema"
98
+ select_table: "Seleccionar una tabla del panel izquierdo"
99
+ table_semantics: "Significado de la tabla"
100
+ table_description: "Descripción de la tabla (Contexto IA)"
101
+ table_placeholder: "Describe el significado de la tabla, ejemplo: tabla de usuarios."
102
+ column_metadata: "Metadatos de columna"
103
+ auto_detect: "Auto-detectar desde la BD"
104
+ meta_column: "Columna"
105
+ meta_type: "Tipo"
106
+ meta_description: "Descripción"
107
+ meta_synonyms: "Sinonimos"
108
+ pii_sesitive: "IP Sensible"
109
+
110
+ prompts:
111
+ title: "Gestor de Prompts"
112
+ subtitle: "Gestiona y prueba tus plantillas y personas de IA"
113
+ library: "Biblioteca de Prompts"
114
+ new_btn: "Nuevo"
115
+ filter_placeholder: "Filtrar prompts..."
116
+ select_prompt: "Selecciona un prompt"
117
+ toggle_settings: "Alternar Variables y Configuración"
118
+ settings_btn: "Ajustes"
119
+ save_btn: "Guardar"
120
+ tab_editor: "Editor"
121
+ tab_playground: "Playground"
122
+ config_title: "Configuración"
123
+ desc_label: "Descripción"
124
+ desc_placeholder: "Describe este prompt..."
125
+ vars_label: "Variables de Entrada"
126
+ no_vars: "Sin variables definidas"
127
+ playground_inputs: "Variables y Entradas"
128
+ no_vars_detected: "No se detectaron variables en la plantilla."
129
+ model_override: "Modelo Específico (Opcional)"
130
+ default_model: "Por defecto (según config)"
131
+ run_btn: "Ejecutar"
132
+ output_placeholder: "El resultado aparecerá aquí..."
133
+ new_modal_title: "Crear Nuevo Prompt"
134
+ name_label: "Nombre (Slug)"
135
+ name_help: "Solo minúsculas, números y guiones bajos."
136
+ category_label: "Categoría"
137
+ delete_confirmation: "Eliminar el prompt?"
138
+
139
+ config:
140
+ editor_description: "Editor de configuración"
141
+ title: "Editor de configuraciones"
142
+ sections: "Secciones"
143
+ refresh: "Refrescar"
144
+ validate: "Validar"
145
+ select_section: "Seleccione una sección del panel izquierdo"
146
+ no_section_selected: "No hay sección seleccionada."
147
+ view_yaml: "Ver YAML"
148
+
87
149
 
88
150
  rag:
89
151
  ingestion: "Ingesta"
@@ -101,7 +163,7 @@ ui:
101
163
  filename_placeholder: "Contiene..."
102
164
  user: "Usuario"
103
165
  status: "Estado"
104
- all_status: "Todos los estados"
166
+ all_status: "Estados"
105
167
  status_active: "Activo"
106
168
  status_pending: "Pendiente"
107
169
  status_processing: "Procesando"
@@ -112,6 +174,11 @@ ui:
112
174
  delete_message: "Esta acción no se puede deshacer. El archivo se eliminará permanentemente."
113
175
  delete_button: "Eliminar"
114
176
  delete_cancel: "Cancelar"
177
+ target_collection: "Categoría"
178
+ select_collection_placeholder: "Selecciona una categoría"
179
+ collection_required: "Debe seleccionar una categoría"
180
+ all_collections: "Todas las categorías"
181
+ collection: "Categoría"
115
182
 
116
183
 
117
184
  tooltips:
@@ -11,6 +11,7 @@ from iatoolkit.repositories.models import Base
11
11
  from injector import inject
12
12
  from pgvector.psycopg2 import register_vector
13
13
  from iatoolkit.common.interfaces.database_provider import DatabaseProvider
14
+ import logging
14
15
 
15
16
 
16
17
  class DatabaseManager(DatabaseProvider):
@@ -135,51 +136,30 @@ class DatabaseManager(DatabaseProvider):
135
136
  self.get_session().rollback()
136
137
 
137
138
  # -- schema methods ----
138
- def get_all_table_names(self) -> list[str]:
139
- # Returns a list of all table names in the database
139
+ def get_database_structure(self) -> dict:
140
140
  inspector = inspect(self._engine)
141
- return inspector.get_table_names(schema=self.schema)
142
-
143
- def get_table_description(self,
144
- table_name: str,
145
- schema_object_name: str | None = None,
146
- exclude_columns: list[str] | None = None) -> str:
147
- inspector = inspect(self._engine)
148
-
149
- # search the table in the specified schema
150
- if table_name not in inspector.get_table_names(schema=self.schema):
151
- raise RuntimeError(f"Table '{table_name}' does not exist in database schema '{self.schema}'.")
152
-
153
- if exclude_columns is None:
154
- exclude_columns = []
155
-
156
- # get all the table columns
157
- columns = inspector.get_columns(table_name, schema=self.schema)
158
-
159
- # construct a json dictionary with the table definition
160
- json_dict = {
161
- "table": table_name,
162
- "schema": self.schema,
163
- "description": f"The table belongs to the **`{self.schema}`** schema.",
164
- "fields": []
165
- }
166
-
167
- if schema_object_name:
168
- json_dict["description"] += (
169
- f"The meaning of each field in this table is detailed in the **`{schema_object_name}`** object."
170
- )
171
-
172
- # now add every column to the json dictionary
173
- for col in columns:
174
- name = col["name"]
175
-
176
- # omit the excluded columns.
177
- if name in exclude_columns:
178
- continue
179
-
180
- json_dict["fields"].append({
181
- "name": name,
182
- "type": str(col["type"]),
183
- })
184
-
185
- return "\n\n" + str(json_dict)
141
+ structure = {}
142
+ for table in inspector.get_table_names(schema=self.schema):
143
+ columns_data = []
144
+
145
+ # get columns
146
+ try:
147
+ columns = inspector.get_columns(table, schema=self.schema)
148
+ # Obtener PKs para marcarlas
149
+ pks = inspector.get_pk_constraint(table, schema=self.schema).get('constrained_columns', [])
150
+
151
+ for col in columns:
152
+ columns_data.append({
153
+ "name": col['name'],
154
+ "type": str(col['type']),
155
+ "nullable": col.get('nullable', True),
156
+ "pk": col['name'] in pks
157
+ })
158
+ except Exception as e:
159
+ logging.warning(f"Could not inspect columns for table {table}: {e}")
160
+
161
+ structure[table] = {
162
+ "columns": columns_data
163
+ }
164
+
165
+ return structure
@@ -3,10 +3,13 @@
3
3
  #
4
4
  # IAToolkit is open source software.
5
5
 
6
- from iatoolkit.repositories.models import LLMQuery, Tool, Company, Prompt, PromptCategory
6
+ from iatoolkit.repositories.models import (LLMQuery, Tool,
7
+ Company, Prompt, PromptCategory, PromptType)
7
8
  from injector import inject
8
9
  from iatoolkit.repositories.database_manager import DatabaseManager
9
10
  from sqlalchemy import or_
11
+ from typing import List
12
+
10
13
 
11
14
  class LLMQueryRepo:
12
15
  @inject
@@ -54,7 +57,7 @@ class LLMQueryRepo:
54
57
  self.session.add(new_tool)
55
58
  tool = new_tool
56
59
 
57
- self.session.flush()
60
+ self.session.commit()
58
61
  return tool
59
62
 
60
63
  def delete_tool(self, tool: Tool):
@@ -67,14 +70,14 @@ class LLMQueryRepo:
67
70
  prompt.category_id = new_prompt.category_id
68
71
  prompt.description = new_prompt.description
69
72
  prompt.order = new_prompt.order
70
- prompt.is_system_prompt = new_prompt.is_system_prompt
73
+ prompt.prompt_type = new_prompt.prompt_type
71
74
  prompt.filename = new_prompt.filename
72
75
  prompt.custom_fields = new_prompt.custom_fields
73
76
  else:
74
77
  self.session.add(new_prompt)
75
78
  prompt = new_prompt
76
79
 
77
- self.session.flush()
80
+ self.session.commit()
78
81
  return prompt
79
82
 
80
83
  def create_or_update_prompt_category(self, new_category: PromptCategory):
@@ -94,12 +97,31 @@ class LLMQueryRepo:
94
97
  LLMQuery.user_identifier == user_identifier,
95
98
  ).filter_by(company_id=company.id).order_by(LLMQuery.created_at.desc()).limit(100).all()
96
99
 
97
- def get_prompts(self, company: Company) -> list[Prompt]:
98
- return self.session.query(Prompt).filter_by(company_id=company.id, is_system_prompt=False).all()
100
+ def get_prompts(self, company: Company, include_all: bool = False) -> list[Prompt]:
101
+ if include_all:
102
+ # Include all prompts: company, system, agent
103
+ return self.session.query(Prompt).filter(
104
+ Prompt.company_id == company.id,
105
+ ).all()
106
+ else:
107
+ # Only company prompts, excluding system (default behavior for end users)
108
+ return self.session.query(Prompt).filter(
109
+ Prompt.company_id == company.id,
110
+ Prompt.prompt_type == PromptType.COMPANY.value
111
+ ).all()
99
112
 
100
113
  def get_prompt_by_name(self, company: Company, prompt_name: str):
101
114
  return self.session.query(Prompt).filter_by(company_id=company.id, name=prompt_name).first()
102
115
 
116
+ def get_category_by_name(self, company_id: int, name: str) -> PromptCategory:
117
+ return self.session.query(PromptCategory).filter_by(company_id=company_id, name=name).first()
118
+
119
+ def get_all_categories(self, company_id: int) -> List[PromptCategory]:
120
+ return self.session.query(PromptCategory).filter_by(company_id=company_id).order_by(PromptCategory.order).all()
121
+
103
122
  def get_system_prompts(self) -> list[Prompt]:
104
- return self.session.query(Prompt).filter_by(is_system_prompt=True, active=True).order_by(Prompt.order).all()
123
+ return self.session.query(Prompt).filter_by(prompt_type=PromptType.SYSTEM.value, active=True).order_by(Prompt.order).all()
105
124
 
125
+ def delete_prompt(self, prompt: Prompt):
126
+ self.session.delete(prompt)
127
+ self.session.commit()
@@ -17,6 +17,19 @@ import enum
17
17
  class Base(DeclarativeBase):
18
18
  pass
19
19
 
20
+
21
+ class DocumentStatus(str, enum.Enum):
22
+ PENDING = "pending"
23
+ PROCESSING = "processing"
24
+ ACTIVE = "active"
25
+ FAILED = "failed"
26
+
27
+ class PromptType(str, enum.Enum):
28
+ SYSTEM = "system"
29
+ COMPANY = "company"
30
+ AGENT = "agent"
31
+
32
+
20
33
  # relation table for many-to-many relationship between companies and users
21
34
  user_company = Table('iat_user_company',
22
35
  Base.metadata,
@@ -149,11 +162,6 @@ class Tool(Base):
149
162
  return {column.key: getattr(self, column.key) for column in class_mapper(self.__class__).columns}
150
163
 
151
164
 
152
- class DocumentStatus(str, enum.Enum):
153
- PENDING = "pending"
154
- PROCESSING = "processing"
155
- ACTIVE = "active"
156
- FAILED = "failed"
157
165
 
158
166
 
159
167
  class CollectionType(Base):
@@ -290,12 +298,13 @@ class Prompt(Base):
290
298
  description = Column(String, nullable=False)
291
299
  filename = Column(String, nullable=False)
292
300
  active = Column(Boolean, default=True)
293
- is_system_prompt = Column(Boolean, default=False)
301
+ prompt_type = Column(String, default=PromptType.COMPANY.value, nullable=False)
294
302
  order = Column(Integer, nullable=True, default=0)
295
303
  category_id = Column(Integer, ForeignKey('iat_prompt_categories.id'), nullable=True)
296
304
  custom_fields = Column(JSON, nullable=False, default=[])
297
-
298
305
  created_at = Column(DateTime, default=datetime.now)
306
+ def to_dict(self):
307
+ return {column.key: getattr(self, column.key) for column in class_mapper(self.__class__).columns}
299
308
 
300
309
  company = relationship("Company", back_populates="prompts")
301
310
  category = relationship("PromptCategory", back_populates="prompts")