iatoolkit 2.7.2__tar.gz → 2.9.0__tar.gz
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.
- {iatoolkit-2.7.2/src/iatoolkit.egg-info → iatoolkit-2.9.0}/PKG-INFO +1 -1
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/__init__.py +1 -1
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/common/routes.py +4 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/core.py +4 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/locales/en.yaml +61 -1
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/locales/es.yaml +61 -0
- iatoolkit-2.9.0/src/iatoolkit/repositories/mcp_personal_access_token_repo.py +63 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/repositories/models.py +28 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/knowledge_base_service.py +66 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/llm_client_service.py +5 -0
- iatoolkit-2.9.0/src/iatoolkit/services/mcp_personal_access_token_service.py +166 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/query_service.py +3 -0
- iatoolkit-2.9.0/src/iatoolkit/templates/account.html +604 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/templates/chat.html +11 -2
- iatoolkit-2.9.0/src/iatoolkit/views/account_view.py +178 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0/src/iatoolkit.egg-info}/PKG-INFO +1 -1
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit.egg-info/SOURCES.txt +4 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/LICENSE +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/LICENSE_COMMUNITY.md +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/pyproject.toml +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/readme.md +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/requirements.txt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/setup.cfg +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/base_company.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/cli_commands.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/common/__init__.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/common/exceptions.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/common/interfaces/__init__.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/common/interfaces/asset_storage.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/common/interfaces/database_provider.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/common/interfaces/memory_compilation_trigger.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/common/interfaces/memory_lint_trigger.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/common/interfaces/secret_provider.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/common/interfaces/signup_policy_resolver.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/common/interfaces/web_search_provider.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/common/model_registry.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/common/secret_resolver.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/common/session_manager.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/common/util.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/company_registry.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/__init__.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/llm_capabilities.yaml +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts/chat_state_rules.prompt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts/chat_user_profile.prompt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts/core_identity.prompt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts/email_output.prompt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts/file_download_output.prompt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts/format_styles.prompt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts/html_structures.prompt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts/links_documents.prompt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts/memory_usage.prompt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts/multimodal_basics.prompt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts/output_basics.prompt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts/presentation_formatting.prompt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts/query_main.prompt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts/sql_aggregation_scope.prompt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts/sql_casting.prompt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts/sql_core.prompt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts/sql_jsonb.prompt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts/sql_rules.prompt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts/tool_html_passthrough.prompt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_prompts_pack.yaml +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/config/system_tools_pack.yaml +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/__init__.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/call_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/connectors/__init__.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/google_auth_client.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/google_chat_app.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/inference_embeddings_client.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/inference_handler.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/jina_embeddings_client.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/llm_providers/__init__.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/llm_providers/anthropic_adapter.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/llm_providers/openai_adapter.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/llm_providers/openai_compatible_chat_adapter.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/llm_providers/openrouter_adapter.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/llm_proxy.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/llm_response.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/infra/redis_session_manager.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/repositories/__init__.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/repositories/api_key_repo.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/repositories/database_manager.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/repositories/document_repo.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/repositories/env_secret_provider.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/repositories/filesystem_asset_repository.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/repositories/memory_repo.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/repositories/profile_repo.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/repositories/prompt_resource_repo.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/repositories/sql_dataset_repo.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/repositories/sql_source_repo.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/repositories/vs_repo.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/__init__.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/api_key_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/attachment_policy_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/auth_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/benchmark_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/branding_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/company_context_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/configuration_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/context_builder_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/dispatcher_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/embedding_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/excel_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/file_processor_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/history_manager_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/http_tool_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/i18n_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/inference_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/jwt_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/language_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/license_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/mail_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/memory_compiler_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/memory_lint_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/memory_lookup_policy_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/memory_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/memory_wiki_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/noop_memory_compilation_trigger.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/noop_memory_lint_trigger.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/parsers/__init__.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/parsers/contracts.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/parsers/image_normalizer.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/parsers/parsing_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/parsers/pdf_ocr_detection.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/parsers/provider_factory.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/parsers/provider_resolver.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/parsers/providers/__init__.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/parsers/providers/basic_provider.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/parsers/providers/docling_provider.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/parsers/validator.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/pdf_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/profile_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/prompt_resource_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/prompt_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/signup_policy_resolver.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/sql_dataset_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/sql_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/sql_source_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/storage_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/structured_output_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/system_prompt_catalog.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/system_tools.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/telemetry_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/tool_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/user_feedback_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/user_session_context_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/visual_kb_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/visual_tool_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/warmup_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/web_search/__init__.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/web_search/provider_factory.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/web_search/providers/__init__.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/web_search/providers/brave_provider.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/services/web_search_service.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/images/fernando.jpeg +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/js/chat_filepond.js +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/js/chat_help_content.js +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/js/chat_history_button.js +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/js/chat_main.js +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/js/chat_memory_button.js +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/js/chat_reload_button.js +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/styles/chat_modal.css +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/styles/chat_public.css +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/styles/documents.css +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/styles/landing_page.css +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/styles/llm_output.css +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/static/styles/onboarding.css +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/system_prompts/__init__.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/templates/_company_header.html +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/templates/_login_widget.html +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/templates/base.html +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/templates/change_password.html +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/templates/chat_memory_modal.html +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/templates/chat_modals.html +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/templates/error.html +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/templates/forgot_password.html +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/templates/home_hosted_default.html +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/templates/memory/wiki_schema.md +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/templates/onboarding_shell.html +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/templates/pdf/base.html +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/templates/pdf/letter.html +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/templates/pdf/report.html +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/templates/pdf/simple.html +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/templates/signup.html +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/__init__.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/api_key_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/base_login_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/categories_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/change_password_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/chat_context_preview_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/chat_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/configuration_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/connectors_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/embedding_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/forgot_password_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/help_content_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/history_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/home_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/init_context_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/llmquery_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/load_document_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/login_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/logout_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/memory_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/profile_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/prompt_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/prompt_context_preview_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/prompt_resource_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/rag_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/root_redirect_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/signup_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/static_page_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/tool_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/users_api_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit/views/verify_user_view.py +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit.egg-info/requires.txt +0 -0
- {iatoolkit-2.7.2 → iatoolkit-2.9.0}/src/iatoolkit.egg-info/top_level.txt +0 -0
|
@@ -39,6 +39,7 @@ def register_views(app):
|
|
|
39
39
|
from iatoolkit.views.logout_api_view import LogoutApiView
|
|
40
40
|
from iatoolkit.views.home_view import HomeView
|
|
41
41
|
from iatoolkit.views.chat_view import ChatView
|
|
42
|
+
from iatoolkit.views.account_view import AccountView
|
|
42
43
|
from iatoolkit.views.static_page_view import StaticPageView
|
|
43
44
|
from iatoolkit.views.root_redirect_view import RootRedirectView
|
|
44
45
|
from iatoolkit.views.users_api_view import UsersApiView
|
|
@@ -69,6 +70,9 @@ def register_views(app):
|
|
|
69
70
|
# Chat Route (Direct Access)
|
|
70
71
|
app.add_url_rule('/<company_short_name>/chat',
|
|
71
72
|
view_func=ChatView.as_view('chat'))
|
|
73
|
+
app.add_url_rule('/<company_short_name>/account',
|
|
74
|
+
view_func=AccountView.as_view('account'),
|
|
75
|
+
methods=['GET', 'POST'])
|
|
72
76
|
|
|
73
77
|
# this endpoint is called when onboarding_shell finish the context load
|
|
74
78
|
app.add_url_rule(
|
|
@@ -355,6 +355,7 @@ class IAToolkit:
|
|
|
355
355
|
from iatoolkit.repositories.profile_repo import ProfileRepo
|
|
356
356
|
from iatoolkit.repositories.llm_query_repo import LLMQueryRepo
|
|
357
357
|
from iatoolkit.repositories.memory_repo import MemoryRepo
|
|
358
|
+
from iatoolkit.repositories.mcp_personal_access_token_repo import McpPersonalAccessTokenRepo
|
|
358
359
|
from iatoolkit.repositories.sql_dataset_repo import SqlDatasetRepo
|
|
359
360
|
from iatoolkit.repositories.sql_source_repo import SqlSourceRepo
|
|
360
361
|
from iatoolkit.repositories.vs_repo import VSRepo
|
|
@@ -371,6 +372,7 @@ class IAToolkit:
|
|
|
371
372
|
binder.bind(ProfileRepo, to=ProfileRepo)
|
|
372
373
|
binder.bind(LLMQueryRepo, to=LLMQueryRepo)
|
|
373
374
|
binder.bind(MemoryRepo, to=MemoryRepo)
|
|
375
|
+
binder.bind(McpPersonalAccessTokenRepo, to=McpPersonalAccessTokenRepo)
|
|
374
376
|
binder.bind(SqlDatasetRepo, to=SqlDatasetRepo)
|
|
375
377
|
binder.bind(SqlSourceRepo, to=SqlSourceRepo)
|
|
376
378
|
binder.bind(VSRepo, to=VSRepo)
|
|
@@ -403,6 +405,7 @@ class IAToolkit:
|
|
|
403
405
|
from iatoolkit.services.mail_service import MailService
|
|
404
406
|
from iatoolkit.services.memory_compiler_service import MemoryCompilerService
|
|
405
407
|
from iatoolkit.services.memory_service import MemoryService
|
|
408
|
+
from iatoolkit.services.mcp_personal_access_token_service import McpPersonalAccessTokenService
|
|
406
409
|
from iatoolkit.services.memory_wiki_service import MemoryWikiService
|
|
407
410
|
from iatoolkit.services.profile_service import ProfileService
|
|
408
411
|
from iatoolkit.services.jwt_service import JWTService
|
|
@@ -446,6 +449,7 @@ class IAToolkit:
|
|
|
446
449
|
binder.bind(MemoryWikiService, to=MemoryWikiService)
|
|
447
450
|
binder.bind(MemoryCompilerService, to=MemoryCompilerService)
|
|
448
451
|
binder.bind(MemoryService, to=MemoryService)
|
|
452
|
+
binder.bind(McpPersonalAccessTokenService, to=McpPersonalAccessTokenService)
|
|
449
453
|
binder.bind(ProfileService, to=ProfileService)
|
|
450
454
|
binder.bind(JWTService, to=JWTService)
|
|
451
455
|
binder.bind(SqlDatasetService, to=SqlDatasetService)
|
|
@@ -54,6 +54,8 @@ ui:
|
|
|
54
54
|
task_reconciliation_requeued: "Requeued"
|
|
55
55
|
task_reconciliation_normalized: "Normalized"
|
|
56
56
|
task_reconciliation_failed: "Recovered As Failed"
|
|
57
|
+
source_mcp: "MCP"
|
|
58
|
+
source_standard_ui: "Standard UI"
|
|
57
59
|
|
|
58
60
|
inspector:
|
|
59
61
|
title: "Interaction Inspector"
|
|
@@ -68,6 +70,7 @@ ui:
|
|
|
68
70
|
performance: "Performance"
|
|
69
71
|
latency: "Latency"
|
|
70
72
|
tokens: "Total Tokens"
|
|
73
|
+
source: "Source"
|
|
71
74
|
tools_executed: "Tools Executed"
|
|
72
75
|
no_tools: "No tools used in this session."
|
|
73
76
|
primary_input: "Primary Input"
|
|
@@ -131,6 +134,59 @@ ui:
|
|
|
131
134
|
prompts_available: "Available prompts"
|
|
132
135
|
init_context: "Initializing the context ..."
|
|
133
136
|
|
|
137
|
+
account:
|
|
138
|
+
title: "My Account"
|
|
139
|
+
back_to_chat: "Back to chat"
|
|
140
|
+
menu_general: "General"
|
|
141
|
+
menu_mcp_tokens: "MCP Tokens"
|
|
142
|
+
general_title: "Personal settings"
|
|
143
|
+
general_description: "Manage your personal access, integrations, and the settings connected to your account."
|
|
144
|
+
general_tag: "Personal workspace"
|
|
145
|
+
general_profile_label: "Profile"
|
|
146
|
+
general_tokens_label: "Integrations"
|
|
147
|
+
general_tokens_title: "MCP access tokens"
|
|
148
|
+
general_tokens_description: "Create and manage bearer tokens for MCP clients that do not complete the OAuth flow directly."
|
|
149
|
+
general_tokens_action: "Open MCP tokens"
|
|
150
|
+
mcp_tokens_create_title: "Create MCP token"
|
|
151
|
+
mcp_tokens_create_description: "Generate a personal access token for MCP clients that require a bearer token."
|
|
152
|
+
mcp_tokens_list_title: "MCP access tokens"
|
|
153
|
+
mcp_tokens_count_suffix: "tokens"
|
|
154
|
+
mcp_tokens_empty: "You have not created any MCP tokens yet."
|
|
155
|
+
mcp_connection_title: "Connection snippets"
|
|
156
|
+
mcp_connection_description: "Use these snippets with MCP clients that connect through a fixed bearer token instead of completing OAuth in-app."
|
|
157
|
+
mcp_connection_tag: "Ready to paste"
|
|
158
|
+
mcp_connection_server_url: "Server URL"
|
|
159
|
+
mcp_connection_json_label: "JSON config"
|
|
160
|
+
mcp_connection_copy_url_button: "Copy URL"
|
|
161
|
+
mcp_connection_copy_json_button: "Copy JSON"
|
|
162
|
+
mcp_connection_url_copy_success: "Server URL copied."
|
|
163
|
+
mcp_connection_json_copy_success: "JSON config copied."
|
|
164
|
+
mcp_connection_copy_error: "Could not copy the MCP connection snippet."
|
|
165
|
+
mcp_connection_placeholder_help: "Replace <YOUR_MCP_TOKEN> with one of your active MCP personal access tokens."
|
|
166
|
+
mcp_token_name: "Token name"
|
|
167
|
+
mcp_token_name_placeholder: "Claude Desktop, PyCharm, Codex..."
|
|
168
|
+
mcp_token_expiry_days: "Expires in (days)"
|
|
169
|
+
mcp_token_created_at: "Created"
|
|
170
|
+
mcp_token_expires_at: "Expires"
|
|
171
|
+
mcp_token_last_used_at: "Last used"
|
|
172
|
+
mcp_token_status: "Status"
|
|
173
|
+
mcp_token_actions: "Actions"
|
|
174
|
+
mcp_token_status_active: "Active"
|
|
175
|
+
mcp_token_status_revoked: "Revoked"
|
|
176
|
+
mcp_token_status_expired: "Expired"
|
|
177
|
+
mcp_token_create_button: "Create token"
|
|
178
|
+
mcp_token_copy_button: "Copy"
|
|
179
|
+
mcp_token_copy_success: "Token copied."
|
|
180
|
+
mcp_token_copy_error: "Could not copy the token."
|
|
181
|
+
mcp_token_revoke_button: "Revoke"
|
|
182
|
+
mcp_token_created_title: "Copy this token now"
|
|
183
|
+
mcp_token_created_help: "For security reasons, this token is shown only once."
|
|
184
|
+
mcp_token_created_token_label: "Bearer token"
|
|
185
|
+
mcp_token_created_json_label: "Ready-to-paste JSON config"
|
|
186
|
+
mcp_token_created_flash: "MCP token created."
|
|
187
|
+
mcp_token_revoked_flash: "MCP token revoked."
|
|
188
|
+
mcp_token_unknown_action: "Unknown account action."
|
|
189
|
+
|
|
134
190
|
memory:
|
|
135
191
|
title: "Memory"
|
|
136
192
|
capture_title: "Save something"
|
|
@@ -1417,8 +1473,12 @@ errors:
|
|
|
1417
1473
|
authentication_required: "Authentication required. No session cookie or API Key provided."
|
|
1418
1474
|
invalid_api_key: "Invalid or inactive API Key."
|
|
1419
1475
|
api_key_name_required: "api_key_name parameter is required."
|
|
1420
|
-
|
|
1421
1476
|
no_user_identifier_api: "No user_identifier provided for API call."
|
|
1477
|
+
mcp_pat_name_required: "Token name is required."
|
|
1478
|
+
mcp_pat_name_exists: "A token with that name already exists."
|
|
1479
|
+
mcp_pat_expiry_invalid: "Invalid expiration value."
|
|
1480
|
+
mcp_pat_invalid: "Invalid, expired, or revoked MCP token."
|
|
1481
|
+
mcp_pat_not_found: "MCP token not found."
|
|
1422
1482
|
no_company_permissions: "Do not have permissions to admin this company."
|
|
1423
1483
|
templates:
|
|
1424
1484
|
company_not_found: "Company not found."
|
|
@@ -55,6 +55,8 @@ ui:
|
|
|
55
55
|
task_reconciliation_requeued: "Reencoladas"
|
|
56
56
|
task_reconciliation_normalized: "Normalizadas"
|
|
57
57
|
task_reconciliation_failed: "Recuperadas como fallidas"
|
|
58
|
+
source_mcp: "MCP"
|
|
59
|
+
source_standard_ui: "UI estándar"
|
|
58
60
|
|
|
59
61
|
inspector:
|
|
60
62
|
title: "Inspector de Interacción"
|
|
@@ -69,6 +71,7 @@ ui:
|
|
|
69
71
|
performance: "Rendimiento"
|
|
70
72
|
latency: "Latencia"
|
|
71
73
|
tokens: "Tokens Totales"
|
|
74
|
+
source: "Origen"
|
|
72
75
|
tools_executed: "Herramientas Ejecutadas"
|
|
73
76
|
no_tools: "No se usaron herramientas en esta sesión."
|
|
74
77
|
primary_input: "Entrada Principal"
|
|
@@ -132,6 +135,59 @@ ui:
|
|
|
132
135
|
prompts_available: "Prompts disponibles"
|
|
133
136
|
init_context: "Inicializando el contexto de la IA ..."
|
|
134
137
|
|
|
138
|
+
account:
|
|
139
|
+
title: "Mi cuenta"
|
|
140
|
+
back_to_chat: "Volver al chat"
|
|
141
|
+
menu_general: "General"
|
|
142
|
+
menu_mcp_tokens: "Tokens MCP"
|
|
143
|
+
general_title: "Configuración personal"
|
|
144
|
+
general_description: "Administra tu acceso personal, tus integraciones y la configuración asociada a tu cuenta."
|
|
145
|
+
general_tag: "Espacio personal"
|
|
146
|
+
general_profile_label: "Perfil"
|
|
147
|
+
general_tokens_label: "Integraciones"
|
|
148
|
+
general_tokens_title: "Tokens de acceso MCP"
|
|
149
|
+
general_tokens_description: "Crea y administra bearer tokens para clientes MCP que no completan el flujo OAuth directamente."
|
|
150
|
+
general_tokens_action: "Abrir tokens MCP"
|
|
151
|
+
mcp_tokens_create_title: "Crear token MCP"
|
|
152
|
+
mcp_tokens_create_description: "Genera un token de acceso personal para clientes MCP que requieren un bearer token."
|
|
153
|
+
mcp_tokens_list_title: "Tokens de acceso MCP"
|
|
154
|
+
mcp_tokens_count_suffix: "tokens"
|
|
155
|
+
mcp_tokens_empty: "Todavía no has creado tokens MCP."
|
|
156
|
+
mcp_connection_title: "Snippets de conexión"
|
|
157
|
+
mcp_connection_description: "Usa estos snippets con clientes MCP que se conectan con un bearer token fijo en vez de completar OAuth dentro de la app."
|
|
158
|
+
mcp_connection_tag: "Listo para pegar"
|
|
159
|
+
mcp_connection_server_url: "URL del servidor"
|
|
160
|
+
mcp_connection_json_label: "Configuración JSON"
|
|
161
|
+
mcp_connection_copy_url_button: "Copiar URL"
|
|
162
|
+
mcp_connection_copy_json_button: "Copiar JSON"
|
|
163
|
+
mcp_connection_url_copy_success: "URL del servidor copiada."
|
|
164
|
+
mcp_connection_json_copy_success: "Configuración JSON copiada."
|
|
165
|
+
mcp_connection_copy_error: "No se pudo copiar el snippet de conexión MCP."
|
|
166
|
+
mcp_connection_placeholder_help: "Reemplaza <YOUR_MCP_TOKEN> por uno de tus tokens MCP activos."
|
|
167
|
+
mcp_token_name: "Nombre del token"
|
|
168
|
+
mcp_token_name_placeholder: "Claude Desktop, PyCharm, Codex..."
|
|
169
|
+
mcp_token_expiry_days: "Expira en (días)"
|
|
170
|
+
mcp_token_created_at: "Creado"
|
|
171
|
+
mcp_token_expires_at: "Expira"
|
|
172
|
+
mcp_token_last_used_at: "Último uso"
|
|
173
|
+
mcp_token_status: "Estado"
|
|
174
|
+
mcp_token_actions: "Acciones"
|
|
175
|
+
mcp_token_status_active: "Activo"
|
|
176
|
+
mcp_token_status_revoked: "Revocado"
|
|
177
|
+
mcp_token_status_expired: "Expirado"
|
|
178
|
+
mcp_token_create_button: "Crear token"
|
|
179
|
+
mcp_token_copy_button: "Copiar"
|
|
180
|
+
mcp_token_copy_success: "Token copiado."
|
|
181
|
+
mcp_token_copy_error: "No se pudo copiar el token."
|
|
182
|
+
mcp_token_revoke_button: "Revocar"
|
|
183
|
+
mcp_token_created_title: "Copia este token ahora"
|
|
184
|
+
mcp_token_created_help: "Por seguridad, este token se muestra solo una vez."
|
|
185
|
+
mcp_token_created_token_label: "Bearer token"
|
|
186
|
+
mcp_token_created_json_label: "Configuración JSON lista para pegar"
|
|
187
|
+
mcp_token_created_flash: "Token MCP creado."
|
|
188
|
+
mcp_token_revoked_flash: "Token MCP revocado."
|
|
189
|
+
mcp_token_unknown_action: "Acción de cuenta desconocida."
|
|
190
|
+
|
|
135
191
|
memory:
|
|
136
192
|
title: "Memoria"
|
|
137
193
|
capture_title: "Guardar algo"
|
|
@@ -1420,6 +1476,11 @@ errors:
|
|
|
1420
1476
|
no_user_identifier_api: "No se proporcionó user_identifier para la llamada a la API."
|
|
1421
1477
|
no_company_permissions: "No tiene permisos para administrar esta empresa."
|
|
1422
1478
|
api_key_name_required: "el parametro api_key_name es requerido."
|
|
1479
|
+
mcp_pat_name_required: "El nombre del token es obligatorio."
|
|
1480
|
+
mcp_pat_name_exists: "Ya existe un token con ese nombre."
|
|
1481
|
+
mcp_pat_expiry_invalid: "El valor de expiración es inválido."
|
|
1482
|
+
mcp_pat_invalid: "Token MCP inválido, expirado o revocado."
|
|
1483
|
+
mcp_pat_not_found: "Token MCP no encontrado."
|
|
1423
1484
|
|
|
1424
1485
|
templates:
|
|
1425
1486
|
company_not_found: "Empresa no encontrada."
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
|
|
5
|
+
from injector import inject
|
|
6
|
+
|
|
7
|
+
from iatoolkit.repositories.database_manager import DatabaseManager
|
|
8
|
+
from iatoolkit.repositories.models import McpPersonalAccessToken
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class McpPersonalAccessTokenRepo:
|
|
12
|
+
@inject
|
|
13
|
+
def __init__(self, db_manager: DatabaseManager):
|
|
14
|
+
self.db_manager = db_manager
|
|
15
|
+
self.session = db_manager.get_session()
|
|
16
|
+
|
|
17
|
+
def create_token(self, token: McpPersonalAccessToken) -> McpPersonalAccessToken:
|
|
18
|
+
self.session.add(token)
|
|
19
|
+
self.session.commit()
|
|
20
|
+
return token
|
|
21
|
+
|
|
22
|
+
def save_token(self, token: McpPersonalAccessToken) -> McpPersonalAccessToken:
|
|
23
|
+
self.session.add(token)
|
|
24
|
+
self.session.commit()
|
|
25
|
+
return token
|
|
26
|
+
|
|
27
|
+
def rollback(self) -> None:
|
|
28
|
+
self.session.rollback()
|
|
29
|
+
|
|
30
|
+
def list_tokens_for_user(self, company_id: int, user_identifier: str) -> list[McpPersonalAccessToken]:
|
|
31
|
+
return (
|
|
32
|
+
self.session.query(McpPersonalAccessToken)
|
|
33
|
+
.filter_by(company_id=company_id, user_identifier=user_identifier)
|
|
34
|
+
.order_by(McpPersonalAccessToken.created_at.desc())
|
|
35
|
+
.all()
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
def get_token_by_id(self, company_id: int, user_identifier: str, token_id: int) -> McpPersonalAccessToken | None:
|
|
39
|
+
return (
|
|
40
|
+
self.session.query(McpPersonalAccessToken)
|
|
41
|
+
.filter_by(company_id=company_id, user_identifier=user_identifier, id=token_id)
|
|
42
|
+
.first()
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
def get_token_by_name(self, company_id: int, user_identifier: str, name: str) -> McpPersonalAccessToken | None:
|
|
46
|
+
return (
|
|
47
|
+
self.session.query(McpPersonalAccessToken)
|
|
48
|
+
.filter_by(company_id=company_id, user_identifier=user_identifier, name=name)
|
|
49
|
+
.first()
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
def get_active_token_by_hash(self, company_id: int, token_hash: str) -> McpPersonalAccessToken | None:
|
|
53
|
+
now = datetime.now()
|
|
54
|
+
return (
|
|
55
|
+
self.session.query(McpPersonalAccessToken)
|
|
56
|
+
.filter(
|
|
57
|
+
McpPersonalAccessToken.company_id == company_id,
|
|
58
|
+
McpPersonalAccessToken.token_hash == token_hash,
|
|
59
|
+
McpPersonalAccessToken.revoked_at.is_(None),
|
|
60
|
+
McpPersonalAccessToken.expires_at > now,
|
|
61
|
+
)
|
|
62
|
+
.first()
|
|
63
|
+
)
|
|
@@ -153,6 +153,11 @@ class Company(Base):
|
|
|
153
153
|
back_populates="company",
|
|
154
154
|
cascade="all, delete-orphan",
|
|
155
155
|
)
|
|
156
|
+
mcp_personal_access_tokens = relationship(
|
|
157
|
+
"McpPersonalAccessToken",
|
|
158
|
+
back_populates="company",
|
|
159
|
+
cascade="all, delete-orphan",
|
|
160
|
+
)
|
|
156
161
|
memory_items = relationship(
|
|
157
162
|
"MemoryItem",
|
|
158
163
|
back_populates="company",
|
|
@@ -698,6 +703,29 @@ class SqlDataset(Base):
|
|
|
698
703
|
return {column.key: getattr(self, column.key) for column in class_mapper(self.__class__).columns}
|
|
699
704
|
|
|
700
705
|
|
|
706
|
+
class McpPersonalAccessToken(Base):
|
|
707
|
+
__tablename__ = "iat_mcp_personal_access_tokens"
|
|
708
|
+
|
|
709
|
+
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
710
|
+
company_id = Column(Integer, ForeignKey(f"{ORM_SCHEMA}.iat_companies.id", ondelete="CASCADE"), nullable=False, index=True)
|
|
711
|
+
user_identifier = Column(String, nullable=False, index=True)
|
|
712
|
+
name = Column(String, nullable=False)
|
|
713
|
+
token_hash = Column(String(64), nullable=False, unique=True, index=True)
|
|
714
|
+
created_at = Column(DateTime, default=datetime.now, nullable=False)
|
|
715
|
+
expires_at = Column(DateTime, nullable=False)
|
|
716
|
+
revoked_at = Column(DateTime, nullable=True)
|
|
717
|
+
last_used_at = Column(DateTime, nullable=True)
|
|
718
|
+
|
|
719
|
+
__table_args__ = (
|
|
720
|
+
UniqueConstraint("company_id", "user_identifier", "name", name="uix_mcp_pat_company_user_name"),
|
|
721
|
+
)
|
|
722
|
+
|
|
723
|
+
company = relationship("Company", back_populates="mcp_personal_access_tokens")
|
|
724
|
+
|
|
725
|
+
def to_dict(self):
|
|
726
|
+
return {column.key: getattr(self, column.key) for column in class_mapper(self.__class__).columns}
|
|
727
|
+
|
|
728
|
+
|
|
701
729
|
class AccessLog(Base):
|
|
702
730
|
# Modelo ORM para registrar cada intento de acceso a la plataforma.
|
|
703
731
|
__tablename__ = 'iat_access_log'
|
|
@@ -24,6 +24,7 @@ import os
|
|
|
24
24
|
from typing import List, Optional, Union
|
|
25
25
|
from datetime import datetime
|
|
26
26
|
from injector import inject
|
|
27
|
+
import mimetypes
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
class KnowledgeBaseService:
|
|
@@ -661,6 +662,71 @@ class KnowledgeBaseService:
|
|
|
661
662
|
)
|
|
662
663
|
return int(query.order_by(None).count() or 0)
|
|
663
664
|
|
|
665
|
+
def get_document_descriptor(
|
|
666
|
+
self,
|
|
667
|
+
company_short_name: str,
|
|
668
|
+
document_id: int,
|
|
669
|
+
collection_name: str | None = None,
|
|
670
|
+
) -> dict:
|
|
671
|
+
"""
|
|
672
|
+
Resolves a document descriptor suitable for MCP/API download workflows.
|
|
673
|
+
|
|
674
|
+
Validates tenant ownership and, when provided, that the document belongs
|
|
675
|
+
to the requested collection.
|
|
676
|
+
"""
|
|
677
|
+
if not company_short_name or not document_id:
|
|
678
|
+
raise IAToolkitException(
|
|
679
|
+
IAToolkitException.ErrorType.INVALID_PARAMETER,
|
|
680
|
+
"company_short_name and document_id are required.",
|
|
681
|
+
)
|
|
682
|
+
|
|
683
|
+
document = self.document_repo.get_by_id(document_id)
|
|
684
|
+
if not document:
|
|
685
|
+
raise IAToolkitException(
|
|
686
|
+
IAToolkitException.ErrorType.DOCUMENT_NOT_FOUND,
|
|
687
|
+
f"Document '{document_id}' not found.",
|
|
688
|
+
)
|
|
689
|
+
|
|
690
|
+
document_company_short_name = str(getattr(getattr(document, "company", None), "short_name", "") or "").strip()
|
|
691
|
+
if document_company_short_name != company_short_name:
|
|
692
|
+
raise IAToolkitException(
|
|
693
|
+
IAToolkitException.ErrorType.INVALID_OPERATION,
|
|
694
|
+
f"Document '{document_id}' does not belong to company '{company_short_name}'.",
|
|
695
|
+
)
|
|
696
|
+
|
|
697
|
+
normalized_collection_name = str(collection_name or "").strip().lower() or None
|
|
698
|
+
document_collection_name = str(
|
|
699
|
+
getattr(getattr(document, "collection_type", None), "name", "") or ""
|
|
700
|
+
).strip().lower() or None
|
|
701
|
+
if normalized_collection_name and document_collection_name != normalized_collection_name:
|
|
702
|
+
raise IAToolkitException(
|
|
703
|
+
IAToolkitException.ErrorType.INVALID_OPERATION,
|
|
704
|
+
f"Document '{document_id}' does not belong to collection '{collection_name}'.",
|
|
705
|
+
)
|
|
706
|
+
|
|
707
|
+
mime_type, _ = mimetypes.guess_type(str(document.filename or "").strip())
|
|
708
|
+
download_url = None
|
|
709
|
+
content_available = bool(document.storage_key)
|
|
710
|
+
if content_available:
|
|
711
|
+
download_url = self.storage_service.generate_presigned_url(
|
|
712
|
+
company_short_name,
|
|
713
|
+
document.storage_key,
|
|
714
|
+
)
|
|
715
|
+
|
|
716
|
+
return {
|
|
717
|
+
"document_id": document.id,
|
|
718
|
+
"company_short_name": company_short_name,
|
|
719
|
+
"collection_name": document_collection_name,
|
|
720
|
+
"filename": document.filename,
|
|
721
|
+
"mime_type": mime_type or "application/octet-stream",
|
|
722
|
+
"storage_key": document.storage_key,
|
|
723
|
+
"download_url": download_url,
|
|
724
|
+
"content_available": content_available,
|
|
725
|
+
"status": document.status.value if hasattr(document.status, "value") else str(document.status),
|
|
726
|
+
"metadata": document.meta or {},
|
|
727
|
+
"created_at": document.created_at.isoformat() if document.created_at else None,
|
|
728
|
+
}
|
|
729
|
+
|
|
664
730
|
def get_document_content(self, document_id: int) -> tuple[bytes, str]:
|
|
665
731
|
"""
|
|
666
732
|
Retrieves the raw content of a document and its filename.
|
|
@@ -306,7 +306,12 @@ class llmClient:
|
|
|
306
306
|
combined_stats = self.add_stats(stats, stats_fcall)
|
|
307
307
|
if isinstance(execution_metadata, dict):
|
|
308
308
|
combined_stats = dict(combined_stats or {})
|
|
309
|
+
request_source = str(execution_metadata.get("request_source") or "").strip().lower()
|
|
310
|
+
if request_source:
|
|
311
|
+
combined_stats["request_source"] = request_source
|
|
309
312
|
for key, value in execution_metadata.items():
|
|
313
|
+
if key == "request_source":
|
|
314
|
+
continue
|
|
310
315
|
if value is not None:
|
|
311
316
|
combined_stats[key] = value
|
|
312
317
|
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import hashlib
|
|
4
|
+
import secrets
|
|
5
|
+
from datetime import datetime, timedelta
|
|
6
|
+
|
|
7
|
+
from injector import inject
|
|
8
|
+
from sqlalchemy.exc import IntegrityError
|
|
9
|
+
|
|
10
|
+
from iatoolkit.repositories.mcp_personal_access_token_repo import McpPersonalAccessTokenRepo
|
|
11
|
+
from iatoolkit.repositories.models import McpPersonalAccessToken
|
|
12
|
+
from iatoolkit.repositories.profile_repo import ProfileRepo
|
|
13
|
+
from iatoolkit.services.i18n_service import I18nService
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class McpPersonalAccessTokenService:
|
|
17
|
+
TOKEN_PREFIX = "iatmcp_"
|
|
18
|
+
DEFAULT_EXPIRY_DAYS = 30
|
|
19
|
+
MAX_EXPIRY_DAYS = 365
|
|
20
|
+
|
|
21
|
+
@inject
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
i18n_service: I18nService,
|
|
25
|
+
profile_repo: ProfileRepo,
|
|
26
|
+
token_repo: McpPersonalAccessTokenRepo,
|
|
27
|
+
):
|
|
28
|
+
self.i18n_service = i18n_service
|
|
29
|
+
self.profile_repo = profile_repo
|
|
30
|
+
self.token_repo = token_repo
|
|
31
|
+
|
|
32
|
+
def list_tokens(self, company_short_name: str, user_identifier: str) -> dict:
|
|
33
|
+
company, error = self._get_company(company_short_name)
|
|
34
|
+
if error:
|
|
35
|
+
return error
|
|
36
|
+
|
|
37
|
+
tokens = self.token_repo.list_tokens_for_user(company.id, user_identifier)
|
|
38
|
+
return {"data": [self._token_to_dict(item) for item in tokens]}
|
|
39
|
+
|
|
40
|
+
def create_token(
|
|
41
|
+
self,
|
|
42
|
+
company_short_name: str,
|
|
43
|
+
user_identifier: str,
|
|
44
|
+
*,
|
|
45
|
+
name: str,
|
|
46
|
+
expires_in_days: int | None = None,
|
|
47
|
+
) -> dict:
|
|
48
|
+
company, error = self._get_company(company_short_name)
|
|
49
|
+
if error:
|
|
50
|
+
return error
|
|
51
|
+
|
|
52
|
+
normalized_name = str(name or "").strip()
|
|
53
|
+
if not normalized_name:
|
|
54
|
+
return {"error": self.i18n_service.t("errors.auth.mcp_pat_name_required"), "status_code": 400}
|
|
55
|
+
|
|
56
|
+
expiry_days = self._normalize_expiry_days(expires_in_days)
|
|
57
|
+
if expiry_days is None:
|
|
58
|
+
return {"error": self.i18n_service.t("errors.auth.mcp_pat_expiry_invalid"), "status_code": 400}
|
|
59
|
+
|
|
60
|
+
existing = self.token_repo.get_token_by_name(company.id, user_identifier, normalized_name)
|
|
61
|
+
if existing and existing.revoked_at is None and existing.expires_at > datetime.now():
|
|
62
|
+
return {"error": self.i18n_service.t("errors.auth.mcp_pat_name_exists"), "status_code": 409}
|
|
63
|
+
|
|
64
|
+
raw_token = self._generate_raw_token()
|
|
65
|
+
expires_at = datetime.now() + timedelta(days=expiry_days)
|
|
66
|
+
try:
|
|
67
|
+
if existing:
|
|
68
|
+
existing.token_hash = self._hash_token(raw_token)
|
|
69
|
+
existing.created_at = datetime.now()
|
|
70
|
+
existing.expires_at = expires_at
|
|
71
|
+
existing.revoked_at = None
|
|
72
|
+
existing.last_used_at = None
|
|
73
|
+
created = self.token_repo.save_token(existing)
|
|
74
|
+
else:
|
|
75
|
+
token = McpPersonalAccessToken(
|
|
76
|
+
company_id=company.id,
|
|
77
|
+
user_identifier=user_identifier,
|
|
78
|
+
name=normalized_name,
|
|
79
|
+
token_hash=self._hash_token(raw_token),
|
|
80
|
+
expires_at=expires_at,
|
|
81
|
+
)
|
|
82
|
+
created = self.token_repo.create_token(token)
|
|
83
|
+
except IntegrityError:
|
|
84
|
+
self.token_repo.rollback()
|
|
85
|
+
return {"error": self.i18n_service.t("errors.auth.mcp_pat_name_exists"), "status_code": 409}
|
|
86
|
+
payload = self._token_to_dict(created)
|
|
87
|
+
payload["token"] = raw_token
|
|
88
|
+
return {"data": payload}
|
|
89
|
+
|
|
90
|
+
def revoke_token(self, company_short_name: str, user_identifier: str, token_id: int) -> dict:
|
|
91
|
+
company, error = self._get_company(company_short_name)
|
|
92
|
+
if error:
|
|
93
|
+
return error
|
|
94
|
+
|
|
95
|
+
token = self.token_repo.get_token_by_id(company.id, user_identifier, token_id)
|
|
96
|
+
if not token:
|
|
97
|
+
return {"error": self.i18n_service.t("errors.auth.mcp_pat_not_found"), "status_code": 404}
|
|
98
|
+
|
|
99
|
+
if token.revoked_at is None:
|
|
100
|
+
token.revoked_at = datetime.now()
|
|
101
|
+
self.token_repo.save_token(token)
|
|
102
|
+
|
|
103
|
+
return {"data": self._token_to_dict(token)}
|
|
104
|
+
|
|
105
|
+
def authenticate_token(self, company_short_name: str, raw_token: str) -> dict:
|
|
106
|
+
company, error = self._get_company(company_short_name)
|
|
107
|
+
if error:
|
|
108
|
+
return error
|
|
109
|
+
|
|
110
|
+
normalized_token = str(raw_token or "").strip()
|
|
111
|
+
if not normalized_token:
|
|
112
|
+
return {"error": self.i18n_service.t("errors.auth.mcp_pat_invalid"), "status_code": 401}
|
|
113
|
+
|
|
114
|
+
token_hash = self._hash_token(normalized_token)
|
|
115
|
+
token = self.token_repo.get_active_token_by_hash(company.id, token_hash)
|
|
116
|
+
if not token:
|
|
117
|
+
return {"error": self.i18n_service.t("errors.auth.mcp_pat_invalid"), "status_code": 401}
|
|
118
|
+
|
|
119
|
+
token.last_used_at = datetime.now()
|
|
120
|
+
self.token_repo.save_token(token)
|
|
121
|
+
return {
|
|
122
|
+
"success": True,
|
|
123
|
+
"company_short_name": company.short_name,
|
|
124
|
+
"user_identifier": token.user_identifier,
|
|
125
|
+
"token_id": token.id,
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
def _get_company(self, company_short_name: str):
|
|
129
|
+
company = self.profile_repo.get_company_by_short_name(company_short_name)
|
|
130
|
+
if not company:
|
|
131
|
+
return None, {
|
|
132
|
+
"error": self.i18n_service.t("errors.company_not_found", company_short_name=company_short_name),
|
|
133
|
+
"status_code": 404,
|
|
134
|
+
}
|
|
135
|
+
return company, None
|
|
136
|
+
|
|
137
|
+
def _token_to_dict(self, token: McpPersonalAccessToken) -> dict:
|
|
138
|
+
return {
|
|
139
|
+
"id": token.id,
|
|
140
|
+
"name": token.name,
|
|
141
|
+
"user_identifier": token.user_identifier,
|
|
142
|
+
"created_at": token.created_at.isoformat() if token.created_at else None,
|
|
143
|
+
"expires_at": token.expires_at.isoformat() if token.expires_at else None,
|
|
144
|
+
"revoked_at": token.revoked_at.isoformat() if token.revoked_at else None,
|
|
145
|
+
"last_used_at": token.last_used_at.isoformat() if token.last_used_at else None,
|
|
146
|
+
"is_active": token.revoked_at is None and token.expires_at > datetime.now(),
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
def _normalize_expiry_days(self, raw_value: int | None) -> int | None:
|
|
150
|
+
if raw_value in (None, ""):
|
|
151
|
+
return self.DEFAULT_EXPIRY_DAYS
|
|
152
|
+
try:
|
|
153
|
+
expiry_days = int(raw_value)
|
|
154
|
+
except (TypeError, ValueError):
|
|
155
|
+
return None
|
|
156
|
+
if expiry_days <= 0 or expiry_days > self.MAX_EXPIRY_DAYS:
|
|
157
|
+
return None
|
|
158
|
+
return expiry_days
|
|
159
|
+
|
|
160
|
+
@classmethod
|
|
161
|
+
def _hash_token(cls, raw_token: str) -> str:
|
|
162
|
+
return hashlib.sha256(str(raw_token or "").encode("utf-8")).hexdigest()
|
|
163
|
+
|
|
164
|
+
@classmethod
|
|
165
|
+
def _generate_raw_token(cls) -> str:
|
|
166
|
+
return f"{cls.TOKEN_PREFIX}{secrets.token_urlsafe(32)}"
|
|
@@ -1393,6 +1393,9 @@ class QueryService:
|
|
|
1393
1393
|
request_metadata = self._resolve_prompt_request_metadata(prompt_output_contract)
|
|
1394
1394
|
|
|
1395
1395
|
execution_metadata = {"tool_router": tool_router_metrics}
|
|
1396
|
+
request_source = str((client_data if isinstance(client_data, dict) else {}).get("source") or "").strip().lower() or None
|
|
1397
|
+
if request_source:
|
|
1398
|
+
execution_metadata["request_source"] = request_source
|
|
1396
1399
|
if memory_lookup_decision.reason:
|
|
1397
1400
|
execution_metadata["tool_policy"] = {
|
|
1398
1401
|
"tool_choice_override": tool_choice_override,
|