iatoolkit 2.72.1__tar.gz → 2.73.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.72.1/src/iatoolkit.egg-info → iatoolkit-2.73.0}/PKG-INFO +1 -1
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/__init__.py +1 -1
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/access.py +91 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/locales/en.yaml +1 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/locales/es.yaml +1 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/knowledge_wiki_repo.py +12 -3
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/memory_repo.py +12 -3
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/models.py +7 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/company_context_service.py +17 -3
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/context_builder_service.py +5 -1
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/knowledge_base_service.py +5 -1
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/memory_compiler_service.py +38 -13
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/memory_service.py +79 -11
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/memory_sources.py +7 -3
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/memory_wiki_service.py +47 -10
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/query_service.py +19 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/resource_access_scope.py +42 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/tenant_wiki_service.py +56 -8
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/user_session_context_service.py +12 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/rag_api_view.py +55 -2
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/wiki_page_view.py +3 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0/src/iatoolkit.egg-info}/PKG-INFO +1 -1
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/LICENSE +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/LICENSE_COMMUNITY.md +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/pyproject.toml +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/readme.md +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/setup.cfg +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/base_company.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/cli_commands.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/__init__.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/bridge_validation.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/company_paths.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/exceptions.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/interfaces/__init__.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/interfaces/asset_storage.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/interfaces/database_provider.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/interfaces/memory_compilation_trigger.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/interfaces/secret_provider.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/interfaces/signup_policy_resolver.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/interfaces/web_search_provider.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/memory_tools.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/model_registry.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/routes.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/search_terms.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/secret_resolver.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/session_manager.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/text_splitter.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/url_safety.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/common/util.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/company_registry.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/__init__.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/llm_capabilities.yaml +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_agents/memory_compiler.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_agents/memory_correction.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_agents/memory_document_ingest.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_agents/memory_image_ingest.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_agents/memory_meeting_ingest.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_agents/memory_question_review.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_agents_pack.yaml +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/channel_business_identity.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/channel_conversation_continuity.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/channel_response_style.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/chat_state_rules.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/chat_user_profile.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/core_identity.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/email_output.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/file_download_output.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/format_styles.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/html_structures.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/links_documents.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/memory_usage.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/multimodal_basics.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/output_basics.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/presentation_formatting.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/query_main.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/sql_aggregation_scope.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/sql_casting.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/sql_core.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/sql_jsonb.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/sql_mysql_casting.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/sql_mysql_json.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/sql_redshift_basics.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/sql_redshift_types.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/sql_rules.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts/tool_html_passthrough.prompt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_prompts_pack.yaml +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/config/system_tools_pack.yaml +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/core.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/__init__.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/call_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/connectors/__init__.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/google_auth_client.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/google_chat_app.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/inference_embeddings_client.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/inference_handler.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/jina_embeddings_client.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/llm_gateway_resolver.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/llm_providers/__init__.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/llm_providers/anthropic_adapter.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/llm_providers/openai_adapter.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/llm_providers/openai_compatible_chat_adapter.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/llm_providers/openrouter_adapter.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/llm_proxy.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/llm_response.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/infra/redis_session_manager.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/__init__.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/advisory_lock.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/api_key_repo.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/bridge_repo.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/database_manager.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/document_repo.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/env_secret_provider.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/filesystem_asset_repository.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/mcp_token_repo.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/memory_question_repo.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/memory_usage_repo.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/profile_repo.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/prompt_resource_repo.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/sql_dataset_repo.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/sql_source_repo.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/repositories/vs_repo.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/runtime_logging.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/__init__.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/api_key_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/attachment_policy_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/auth_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/branding_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/configuration_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/dispatcher_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/embedding_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/excel_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/file_processor_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/history_manager_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/http_tool_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/i18n_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/inference_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/jwt_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/language_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/license_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/llm_client_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/mail_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/markdown_wiki_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/mcp_token_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/memory_lookup_policy_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/memory_question_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/memory_usage_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/noop_memory_compilation_trigger.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/operator_identity_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/parsers/__init__.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/parsers/contracts.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/parsers/image_normalizer.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/parsers/parsing_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/parsers/pdf_ocr_detection.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/parsers/provider_factory.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/parsers/provider_resolver.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/parsers/providers/__init__.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/parsers/providers/basic_provider.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/parsers/providers/docling_provider.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/parsers/validator.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/pdf_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/profile_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/prompt_resource_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/prompt_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/signup_policy_resolver.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/sql_dataset_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/sql_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/sql_source_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/storage_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/structured_output_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/system_agent_catalog.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/system_agent_runner.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/system_prompt_catalog.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/system_tools.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/telemetry_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/tool_output_contract.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/tool_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/user_feedback_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/visual_kb_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/visual_tool_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/warmup_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/web_search/__init__.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/web_search/provider_factory.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/web_search/providers/__init__.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/web_search/providers/brave_provider.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/web_search_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/services/wiki_page_index_service.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/images/favicon.ico +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/images/favicon.png +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/images/fernando.jpeg +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/js/chat_filepond.js +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/js/chat_header_navigation.js +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/js/chat_help_content.js +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/js/chat_history_button.js +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/js/chat_main.js +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/js/chat_memory_button.js +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/js/chat_reload_button.js +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/styles/account.css +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/styles/chat_modal.css +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/styles/chat_public.css +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/styles/documents.css +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/styles/landing_page.css +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/styles/llm_output.css +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/styles/onboarding.css +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/static/styles/wiki_page.css +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/_chat_header.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/_company_header.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/_login_widget.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/account.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/base.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/change_password.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/chat.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/chat_memory_modal.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/chat_modals.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/error.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/forgot_password.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/home_hosted_default.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/login_global.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/memory/wiki_schema.md +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/onboarding_shell.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/pdf/base.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/pdf/letter.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/pdf/report.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/pdf/simple.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/signup.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/templates/wiki_page.html +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/__init__.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/account_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/api_key_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/base_login_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/categories_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/change_password_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/chat_context_preview_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/chat_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/configuration_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/connectors_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/embedding_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/forgot_password_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/help_content_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/history_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/home_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/init_context_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/llmquery_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/load_document_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/login_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/logout_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/memory_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/profile_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/prompt_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/prompt_context_preview_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/prompt_resource_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/root_redirect_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/signup_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/static_page_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/tool_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/users_api_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit/views/verify_user_view.py +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit.egg-info/SOURCES.txt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit.egg-info/requires.txt +0 -0
- {iatoolkit-2.72.1 → iatoolkit-2.73.0}/src/iatoolkit.egg-info/top_level.txt +0 -0
|
@@ -192,6 +192,97 @@ def filter_llm_models(company_short_name: str, user_identifier: str | None, defa
|
|
|
192
192
|
return default_model, allowed
|
|
193
193
|
|
|
194
194
|
|
|
195
|
+
def stamp(company_short_name: str) -> str | None:
|
|
196
|
+
"""A value that changes whenever the company's groups, members or grants change.
|
|
197
|
+
|
|
198
|
+
A person's chat context is built once and cached; when this changes, it is rebuilt
|
|
199
|
+
so the tools, SQL schema and collections it describes follow the new access."""
|
|
200
|
+
decider = Access._decider
|
|
201
|
+
hook = getattr(decider, "stamp", None) if decider is not None else None
|
|
202
|
+
if not callable(hook):
|
|
203
|
+
return None
|
|
204
|
+
try:
|
|
205
|
+
return hook(company_short_name)
|
|
206
|
+
except Exception as exc:
|
|
207
|
+
logging.warning("Access stamp of %s not read: %s", company_short_name, exc)
|
|
208
|
+
return None
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def sql_table_filter(company_short_name: str, user_identifier: str | None):
|
|
212
|
+
"""`fn(database, table) -> bool` for the SQL schema shown to this person, or None.
|
|
213
|
+
|
|
214
|
+
Some SQL sources hold resources of their own (enterprise's knowledge tables): the
|
|
215
|
+
decider names their resource type, and each table needs level 1 over it."""
|
|
216
|
+
decider = Access._decider
|
|
217
|
+
hook = getattr(decider, "sql_table_resource", None) if decider is not None else None
|
|
218
|
+
if not user_identifier or not callable(hook):
|
|
219
|
+
return None
|
|
220
|
+
|
|
221
|
+
def allowed(database: str, table: str) -> bool:
|
|
222
|
+
resource_type = hook(company_short_name, database)
|
|
223
|
+
return not resource_type or can(company_short_name, user_identifier, USE, resource_type, table)
|
|
224
|
+
return allowed
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
# ---------------------------------------------------------------------- audiences
|
|
228
|
+
# Who may see a piece of Memoria content (BL-010, Fase 3). An audience key is None
|
|
229
|
+
# (the whole company) or names what decides it: "memory_folder:<id>", "group:<key>".
|
|
230
|
+
|
|
231
|
+
def audience_visible(company_short_name: str, user_identifier: str | None, audience_key: str | None) -> bool:
|
|
232
|
+
if not audience_key:
|
|
233
|
+
return True
|
|
234
|
+
decider = Access._decider
|
|
235
|
+
hook = getattr(decider, "audience_visible", None) if decider is not None else None
|
|
236
|
+
if not callable(hook):
|
|
237
|
+
return True
|
|
238
|
+
try:
|
|
239
|
+
return bool(hook(company_short_name, user_identifier, audience_key))
|
|
240
|
+
except Exception as exc:
|
|
241
|
+
logging.warning("Audience %s for %s not resolved: %s", audience_key, user_identifier, exc)
|
|
242
|
+
return False
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
def visible_audiences(company_short_name: str, user_identifier: str | None) -> list[str] | None:
|
|
246
|
+
"""The restricted audiences a person sees; None when they see every one (or nothing is restricted).
|
|
247
|
+
|
|
248
|
+
The whole company's content (audience None) is always visible besides these."""
|
|
249
|
+
decider = Access._decider
|
|
250
|
+
hook = getattr(decider, "visible_audiences", None) if decider is not None else None
|
|
251
|
+
if not callable(hook):
|
|
252
|
+
return None
|
|
253
|
+
try:
|
|
254
|
+
return hook(company_short_name, user_identifier)
|
|
255
|
+
except Exception as exc:
|
|
256
|
+
logging.warning("Visible audiences of %s not resolved: %s", user_identifier, exc)
|
|
257
|
+
return []
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def audience_label(company_short_name: str, audience_key: str | None) -> str | None:
|
|
261
|
+
"""The name people see for an audience (the folder's or group's name); None for the whole company."""
|
|
262
|
+
if not audience_key:
|
|
263
|
+
return None
|
|
264
|
+
decider = Access._decider
|
|
265
|
+
hook = getattr(decider, "audience_label", None) if decider is not None else None
|
|
266
|
+
try:
|
|
267
|
+
return (hook(company_short_name, audience_key) if callable(hook) else None) or audience_key
|
|
268
|
+
except Exception:
|
|
269
|
+
return audience_key
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def audience_for_folder(company_short_name: str, folder_id) -> str | None:
|
|
273
|
+
"""The audience new content from a Memoria folder takes: its own when the folder is restricted."""
|
|
274
|
+
decider = Access._decider
|
|
275
|
+
hook = getattr(decider, "audience_for_folder", None) if decider is not None else None
|
|
276
|
+
if not callable(hook) or folder_id in (None, ""):
|
|
277
|
+
return None
|
|
278
|
+
try:
|
|
279
|
+
return hook(company_short_name, folder_id)
|
|
280
|
+
except Exception as exc:
|
|
281
|
+
# Unknown: the folder's own audience, the restrictive side.
|
|
282
|
+
logging.warning("Audience of folder %s not resolved: %s", folder_id, exc)
|
|
283
|
+
return f"memory_folder:{folder_id}"
|
|
284
|
+
|
|
285
|
+
|
|
195
286
|
def person_can(company_short_name: str, auth_result: dict | None, level: int, resource_type: str = "company",
|
|
196
287
|
resource_key: str | None = None) -> bool:
|
|
197
288
|
"""A signed-in person's access, from an AuthService result.
|
|
@@ -794,6 +794,7 @@ ui:
|
|
|
794
794
|
access_add_group: "Add group"
|
|
795
795
|
access_reset: "Back to company access"
|
|
796
796
|
access_saved: "Access updated."
|
|
797
|
+
access_memory_restricted: "What Memoria knows from this folder ({count} pages) is now seen only by those with access to it."
|
|
797
798
|
access_group: "Group"
|
|
798
799
|
access_level: "Level"
|
|
799
800
|
team_invite_user: "Invite user"
|
|
@@ -808,6 +808,7 @@ ui:
|
|
|
808
808
|
access_add_group: "Agregar grupo"
|
|
809
809
|
access_reset: "Volver al acceso de la empresa"
|
|
810
810
|
access_saved: "Acceso actualizado."
|
|
811
|
+
access_memory_restricted: "Lo que Memoria sabe de esta carpeta ({count} páginas) ahora solo lo ven quienes tienen acceso a ella."
|
|
811
812
|
access_group: "Grupo"
|
|
812
813
|
access_level: "Nivel"
|
|
813
814
|
team_invite_user: "Invitar usuario"
|
|
@@ -299,7 +299,7 @@ class KnowledgeWikiRepo:
|
|
|
299
299
|
RRF_K = 60
|
|
300
300
|
|
|
301
301
|
def hybrid_search_pages(self, wiki_ids: list[int], query_text: str, query_embedding: list[float] | None,
|
|
302
|
-
candidates: int = 40) -> list[tuple[int, float]]:
|
|
302
|
+
candidates: int = 40, audience_keys: list | None = None) -> list[tuple[int, float]]:
|
|
303
303
|
"""
|
|
304
304
|
(page_id, rrf_score) of the best pages of these wikis, best first: by
|
|
305
305
|
words (Postgres full text, 'simple', terms OR'ed, the GIN index) and, when
|
|
@@ -313,6 +313,15 @@ class KnowledgeWikiRepo:
|
|
|
313
313
|
tsquery = "replace(plainto_tsquery('simple'::regconfig, :text_terms)::text, ' & ', ' | ')::tsquery"
|
|
314
314
|
params = {"wiki_ids": list(wiki_ids), "text_terms": query_text or "", "candidates": int(candidates),
|
|
315
315
|
"archived": KnowledgeWikiPageStatus.ARCHIVED.name}
|
|
316
|
+
# Audiences (BL-010, Fase 3): only pages whose audience is listed, None being the
|
|
317
|
+
# whole company. Filtered here, before the limit, not after the ranking.
|
|
318
|
+
audience_sql = ""
|
|
319
|
+
if audience_keys is not None:
|
|
320
|
+
keys = [k for k in audience_keys if k]
|
|
321
|
+
clauses = (["p.audience_key IS NULL"] if None in audience_keys else []) + \
|
|
322
|
+
(["p.audience_key = ANY(:audience_keys)"] if keys else [])
|
|
323
|
+
audience_sql = f" AND ({' OR '.join(clauses) or 'FALSE'})"
|
|
324
|
+
params["audience_keys"] = keys
|
|
316
325
|
branches = [f"""
|
|
317
326
|
SELECT page_id, ROW_NUMBER() OVER (ORDER BY text_rank DESC, page_id ASC) AS rank
|
|
318
327
|
FROM (
|
|
@@ -320,7 +329,7 @@ class KnowledgeWikiRepo:
|
|
|
320
329
|
FROM iat_knowledge_wiki_page_index i
|
|
321
330
|
JOIN iat_knowledge_wiki_pages p ON p.id = i.page_id,
|
|
322
331
|
(SELECT {tsquery} AS q) terms
|
|
323
|
-
WHERE i.wiki_id = ANY(:wiki_ids) AND p.status::text <> :archived
|
|
332
|
+
WHERE i.wiki_id = ANY(:wiki_ids) AND p.status::text <> :archived{audience_sql}
|
|
324
333
|
AND {tsvector} @@ terms.q
|
|
325
334
|
ORDER BY text_rank DESC
|
|
326
335
|
LIMIT :candidates
|
|
@@ -336,7 +345,7 @@ class KnowledgeWikiRepo:
|
|
|
336
345
|
i.embedding::vector({dims}) <=> CAST(:query_embedding AS vector({dims})) AS distance
|
|
337
346
|
FROM iat_knowledge_wiki_page_index i
|
|
338
347
|
JOIN iat_knowledge_wiki_pages p ON p.id = i.page_id
|
|
339
|
-
WHERE i.wiki_id = ANY(:wiki_ids) AND p.status::text <> :archived
|
|
348
|
+
WHERE i.wiki_id = ANY(:wiki_ids) AND p.status::text <> :archived{audience_sql}
|
|
340
349
|
AND i.embedding IS NOT NULL AND vector_dims(i.embedding) = {dims}
|
|
341
350
|
ORDER BY distance ASC
|
|
342
351
|
LIMIT :candidates
|
|
@@ -109,12 +109,21 @@ class MemoryRepo:
|
|
|
109
109
|
.all()
|
|
110
110
|
)
|
|
111
111
|
|
|
112
|
-
def list_recent_items(self, company_id: int, limit: int = 25) -> list[MemoryItem]:
|
|
112
|
+
def list_recent_items(self, company_id: int, limit: int = 25, audience_keys: list | None = None) -> list[MemoryItem]:
|
|
113
|
+
"""The company's latest items; with `audience_keys`, only those of captures of those
|
|
114
|
+
audiences (None in the list is the whole company; BL-010, Fase 3)."""
|
|
113
115
|
if not company_id:
|
|
114
116
|
return []
|
|
117
|
+
query = self.session.query(MemoryItem).filter(MemoryItem.company_id == company_id)
|
|
118
|
+
if audience_keys is not None:
|
|
119
|
+
from sqlalchemy import false, or_
|
|
120
|
+
keys = [k for k in audience_keys if k]
|
|
121
|
+
clauses = ([MemoryCapture.audience_key.is_(None)] if None in audience_keys else []) + \
|
|
122
|
+
([MemoryCapture.audience_key.in_(keys)] if keys else [])
|
|
123
|
+
query = query.join(MemoryCapture, MemoryCapture.id == MemoryItem.capture_id) \
|
|
124
|
+
.filter(or_(*clauses) if clauses else false())
|
|
115
125
|
return (
|
|
116
|
-
|
|
117
|
-
.filter_by(company_id=company_id)
|
|
126
|
+
query
|
|
118
127
|
.order_by(MemoryItem.created_at.desc(), MemoryItem.id.desc())
|
|
119
128
|
.limit(limit)
|
|
120
129
|
.all()
|
|
@@ -527,6 +527,10 @@ class MemoryCapture(Base):
|
|
|
527
527
|
title = Column(String, nullable=True)
|
|
528
528
|
status = Column(Enum(MemoryCaptureStatus), nullable=False, default=MemoryCaptureStatus.PENDING)
|
|
529
529
|
meta = Column(JSON_NATIVE, nullable=True)
|
|
530
|
+
# Who may see what this capture teaches (BL-010, Fase 3): NULL is the whole company,
|
|
531
|
+
# "memory_folder:<id>" a folder with its own access. The compiler writes it only into
|
|
532
|
+
# pages of the same audience. Migration: migrations/2026-10-18-memoria-audiencia.sql
|
|
533
|
+
audience_key = Column(String(255), nullable=True)
|
|
530
534
|
compile_error = Column(Text, nullable=True)
|
|
531
535
|
last_compiled_at = Column(DateTime, nullable=True)
|
|
532
536
|
created_at = Column(DateTime, default=datetime.now, nullable=False)
|
|
@@ -859,6 +863,9 @@ class KnowledgeWikiPage(Base):
|
|
|
859
863
|
# An empty list denies the page under access control, which is why the sync
|
|
860
864
|
# writes them from the wiki's access manifest and never from frontmatter.
|
|
861
865
|
access_tags = Column(JSON_NATIVE, nullable=False, default=list)
|
|
866
|
+
# A Memoria page's audience (BL-010, Fase 3): NULL is the whole company. A page never
|
|
867
|
+
# mixes audiences. Migration: migrations/2026-10-18-memoria-audiencia.sql
|
|
868
|
+
audience_key = Column(String(255), nullable=True)
|
|
862
869
|
owner = Column(String, nullable=True)
|
|
863
870
|
source_meta = Column(JSON_NATIVE, nullable=False, default=dict)
|
|
864
871
|
last_synced_at = Column(DateTime, nullable=True)
|
|
@@ -53,6 +53,7 @@ class CompanyContextService:
|
|
|
53
53
|
include_yaml_context: bool = True,
|
|
54
54
|
selected_context_files: List[str] | None = None,
|
|
55
55
|
allowed_databases: List[str] | None = None,
|
|
56
|
+
table_filter=None,
|
|
56
57
|
) -> dict[str, str]:
|
|
57
58
|
"""
|
|
58
59
|
Builds the full context by aggregating three sources:
|
|
@@ -81,7 +82,8 @@ class CompanyContextService:
|
|
|
81
82
|
try:
|
|
82
83
|
# allowed_databases: the sources this person may query (BL-010); None is all.
|
|
83
84
|
sql_context, db_tables = self._get_sql_enriched_context(company_short_name,
|
|
84
|
-
allowed_databases=allowed_databases
|
|
85
|
+
allowed_databases=allowed_databases,
|
|
86
|
+
table_filter=table_filter)
|
|
85
87
|
sql_context = sql_context.strip()
|
|
86
88
|
sql_source_table_scopes = self._get_sql_source_table_scopes(company_short_name)
|
|
87
89
|
except Exception as e:
|
|
@@ -138,11 +140,13 @@ class CompanyContextService:
|
|
|
138
140
|
)
|
|
139
141
|
return files
|
|
140
142
|
|
|
141
|
-
def get_sql_context(self, company_short_name: str, allowed_databases: List[str] | None = None
|
|
143
|
+
def get_sql_context(self, company_short_name: str, allowed_databases: List[str] | None = None,
|
|
144
|
+
table_filter=None) -> str:
|
|
142
145
|
try:
|
|
143
146
|
sql_context, _ = self._get_sql_enriched_context(
|
|
144
147
|
company_short_name,
|
|
145
148
|
allowed_databases=allowed_databases,
|
|
149
|
+
table_filter=table_filter,
|
|
146
150
|
)
|
|
147
151
|
return sql_context
|
|
148
152
|
except Exception as e:
|
|
@@ -177,7 +181,8 @@ class CompanyContextService:
|
|
|
177
181
|
return False
|
|
178
182
|
return bool(cls._table_name_candidates(table_name) & allowed_tables)
|
|
179
183
|
|
|
180
|
-
def _get_sql_enriched_context(self, company_short_name: str, allowed_databases: List[str] | None = None
|
|
184
|
+
def _get_sql_enriched_context(self, company_short_name: str, allowed_databases: List[str] | None = None,
|
|
185
|
+
table_filter=None):
|
|
181
186
|
"""
|
|
182
187
|
Generates the SQL context for the LLM using the enriched schema logic.
|
|
183
188
|
It iterates over configured databases, fetches their enriched structure,
|
|
@@ -221,6 +226,15 @@ class CompanyContextService:
|
|
|
221
226
|
}
|
|
222
227
|
if not enriched_structure:
|
|
223
228
|
continue
|
|
229
|
+
if table_filter is not None:
|
|
230
|
+
# Tables the person may not query (enterprise's knowledge tables, BL-010).
|
|
231
|
+
enriched_structure = {
|
|
232
|
+
table_name: table_data
|
|
233
|
+
for table_name, table_data in enriched_structure.items()
|
|
234
|
+
if table_filter(db_name, table_name)
|
|
235
|
+
}
|
|
236
|
+
if not enriched_structure:
|
|
237
|
+
continue
|
|
224
238
|
|
|
225
239
|
# 2. Build Header for this Database
|
|
226
240
|
dialect = self.sql_service.get_database_dialect(company_short_name, db_name)
|
|
@@ -19,6 +19,7 @@ from iatoolkit.services.prompt_service import PromptService
|
|
|
19
19
|
from iatoolkit.services.structured_output_service import StructuredOutputService
|
|
20
20
|
from iatoolkit.common.util import Utility
|
|
21
21
|
from iatoolkit.repositories.models import Company, PromptResourceType
|
|
22
|
+
from iatoolkit.common import access
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
class ContextBuilderService:
|
|
@@ -227,7 +228,8 @@ class ContextBuilderService:
|
|
|
227
228
|
# sources and collections this person may use (BL-010, Fase 2).
|
|
228
229
|
allowed_databases, allowed_collections = self._access_restrictions(company_short_name, user_identifier)
|
|
229
230
|
company_context_blocks = self.company_context_service.get_company_context_blocks(
|
|
230
|
-
company_short_name, allowed_databases=allowed_databases
|
|
231
|
+
company_short_name, allowed_databases=allowed_databases,
|
|
232
|
+
table_filter=access.sql_table_filter(company_short_name, user_identifier))
|
|
231
233
|
collection_context = "" if allowed_collections == [] else self._build_collection_context(
|
|
232
234
|
company_short_name, collection_names=allowed_collections)
|
|
233
235
|
|
|
@@ -386,6 +388,7 @@ class ContextBuilderService:
|
|
|
386
388
|
sql_context = self.company_context_service.get_sql_context(
|
|
387
389
|
company_short_name,
|
|
388
390
|
allowed_databases=sql_sources,
|
|
391
|
+
table_filter=access.sql_table_filter(company_short_name, user_identifier),
|
|
389
392
|
)
|
|
390
393
|
|
|
391
394
|
collection_context = ""
|
|
@@ -399,6 +402,7 @@ class ContextBuilderService:
|
|
|
399
402
|
company_context_blocks = self.company_context_service.get_company_context_blocks(
|
|
400
403
|
company_short_name,
|
|
401
404
|
allowed_databases=allowed_databases,
|
|
405
|
+
table_filter=access.sql_table_filter(company_short_name, user_identifier),
|
|
402
406
|
include_sql_context=bool(company_context_policy.get("sql_context")),
|
|
403
407
|
include_yaml_context=bool(company_context_policy.get("yaml_context")),
|
|
404
408
|
)
|
|
@@ -610,7 +610,11 @@ class KnowledgeBaseService:
|
|
|
610
610
|
else:
|
|
611
611
|
query = query.filter(Document.status == status)
|
|
612
612
|
|
|
613
|
-
if collection:
|
|
613
|
+
if isinstance(collection, (list, tuple, set)):
|
|
614
|
+
# Several collections: those a person may see (BL-010). An empty list is none.
|
|
615
|
+
names = [str(c).strip().lower() for c in collection if str(c or "").strip()]
|
|
616
|
+
query = query.join(Document.collection_type).filter(func.lower(CollectionType.name).in_(names or [""]))
|
|
617
|
+
elif collection:
|
|
614
618
|
normalized_collection = str(collection).strip().lower()
|
|
615
619
|
query = query.join(Document.collection_type).filter(
|
|
616
620
|
func.lower(CollectionType.name) == normalized_collection
|
|
@@ -26,11 +26,12 @@ from iatoolkit.repositories.models import (
|
|
|
26
26
|
Company, MemoryCapture, MemoryCaptureStatus, MemoryConflict, MemoryItem, MemoryItemStatus, MemoryItemType, VSDoc,
|
|
27
27
|
)
|
|
28
28
|
from iatoolkit.repositories.profile_repo import ProfileRepo
|
|
29
|
-
from iatoolkit.services.memory_sources import MemorySourceRegistry, register_core_sources
|
|
29
|
+
from iatoolkit.services.memory_sources import VISIBILITY_FOLDER, MemorySourceRegistry, register_core_sources
|
|
30
30
|
from iatoolkit.services.memory_wiki_service import MemoryWikiService
|
|
31
31
|
from iatoolkit.services.storage_service import StorageService
|
|
32
32
|
from iatoolkit.services.system_agent_runner import SystemAgentDisabled, SystemAgentRunner
|
|
33
33
|
from iatoolkit.services.tenant_wiki_service import TenantWikiService
|
|
34
|
+
from iatoolkit.common import access
|
|
34
35
|
|
|
35
36
|
|
|
36
37
|
class MemoryCompilerService:
|
|
@@ -222,6 +223,14 @@ class MemoryCompilerService:
|
|
|
222
223
|
def _compile_single_capture(self, company: Company, capture: MemoryCapture, items: list[MemoryItem]) -> bool:
|
|
223
224
|
"""Reads the capture with the step its source declares (memory_sources)."""
|
|
224
225
|
source = MemorySourceRegistry.for_capture(dict(capture.meta or {}))
|
|
226
|
+
if source.visibility == VISIBILITY_FOLDER and not getattr(capture, "audience_key", None):
|
|
227
|
+
# A document saved before its folder was restricted (or before audiences
|
|
228
|
+
# existed) takes the folder's audience now: the restrictive side.
|
|
229
|
+
folder_id = (dict(capture.meta or {}).get("source") or {}).get("folder_id")
|
|
230
|
+
audience = access.audience_for_folder(company.short_name, folder_id)
|
|
231
|
+
if audience:
|
|
232
|
+
capture.audience_key = audience
|
|
233
|
+
self.memory_repo.save_capture(capture)
|
|
225
234
|
return getattr(self, source.handler)(company, capture, items)
|
|
226
235
|
|
|
227
236
|
def _compile_person_capture(self, company: Company, capture: MemoryCapture, items: list[MemoryItem]) -> bool:
|
|
@@ -244,6 +253,7 @@ class MemoryCompilerService:
|
|
|
244
253
|
compiled,
|
|
245
254
|
candidates,
|
|
246
255
|
edited_by=capture.user_identifier,
|
|
256
|
+
audience_key=self._audience(capture)[0],
|
|
247
257
|
default_title=self._default_page_title(capture, items),
|
|
248
258
|
revision_metadata={
|
|
249
259
|
"source": self.COMPILER_SOURCE,
|
|
@@ -282,7 +292,8 @@ class MemoryCompilerService:
|
|
|
282
292
|
*,
|
|
283
293
|
edited_by: str,
|
|
284
294
|
default_title: str,
|
|
285
|
-
revision_metadata: dict
|
|
295
|
+
revision_metadata: dict,
|
|
296
|
+
audience_key: str | None = None) -> dict:
|
|
286
297
|
"""Creates or updates the page the model returned; the wiki's response (it may say the page changed)."""
|
|
287
298
|
target = self._resolve_target(compiled, candidates)
|
|
288
299
|
title = str(compiled.get("title") or (target or {}).get("title") or default_title).strip()
|
|
@@ -298,6 +309,7 @@ class MemoryCompilerService:
|
|
|
298
309
|
edited_by=edited_by,
|
|
299
310
|
change_summary=change_summary,
|
|
300
311
|
revision_metadata=revision_metadata,
|
|
312
|
+
audience_key=audience_key,
|
|
301
313
|
)
|
|
302
314
|
return self.memory_wiki_service.update_page(
|
|
303
315
|
company.short_name,
|
|
@@ -356,7 +368,7 @@ class MemoryCompilerService:
|
|
|
356
368
|
touched: list[int] = []
|
|
357
369
|
for index, (part_text, read) in enumerate(readers, start=1):
|
|
358
370
|
for attempt in range(1, self.MAX_SAVE_ATTEMPTS + 1):
|
|
359
|
-
candidates = self._document_candidates(company, source, part_text, touched)
|
|
371
|
+
candidates = self._document_candidates(company, source, part_text, touched, capture)
|
|
360
372
|
answer = read(candidates)
|
|
361
373
|
if answer is None:
|
|
362
374
|
raise RuntimeError(f"the model could not read part {index} of {len(readers)}")
|
|
@@ -367,6 +379,7 @@ class MemoryCompilerService:
|
|
|
367
379
|
response = self._write_page(
|
|
368
380
|
company, compiled, candidates,
|
|
369
381
|
edited_by=capture.user_identifier,
|
|
382
|
+
audience_key=self._audience(capture)[0],
|
|
370
383
|
default_title=label,
|
|
371
384
|
revision_metadata=revision_metadata,
|
|
372
385
|
)
|
|
@@ -535,30 +548,35 @@ class MemoryCompilerService:
|
|
|
535
548
|
parts.append("\n\n".join(current))
|
|
536
549
|
return parts
|
|
537
550
|
|
|
538
|
-
def _document_candidates(self, company: Company, source: dict, part_text: str, touched: list[int]
|
|
551
|
+
def _document_candidates(self, company: Company, source: dict, part_text: str, touched: list[int],
|
|
552
|
+
capture: MemoryCapture | None = None) -> list[dict]:
|
|
539
553
|
"""The pages this document already wrote first, then the ones its part is most likely about."""
|
|
554
|
+
audience = self._audience(capture) if capture is not None else [None]
|
|
540
555
|
ordered: list[int] = list(touched)
|
|
541
556
|
card = source.get("card") or {}
|
|
542
557
|
query = " ".join(part for part in (
|
|
543
558
|
str(source.get("label") or ""), str(card.get("summary") or ""), part_text[:300],
|
|
544
559
|
) if part).strip()
|
|
545
560
|
if query:
|
|
546
|
-
for result in self.memory_wiki_service.search_pages(company.short_name, query, limit=self.MAX_CANDIDATE_PAGES
|
|
561
|
+
for result in self.memory_wiki_service.search_pages(company.short_name, query, limit=self.MAX_CANDIDATE_PAGES,
|
|
562
|
+
audience_keys=audience):
|
|
547
563
|
if result.get("id") not in ordered:
|
|
548
564
|
ordered.append(result.get("id"))
|
|
549
565
|
candidates = []
|
|
550
566
|
for page_id in ordered[:self.MAX_CANDIDATE_PAGES + len(touched)]:
|
|
551
|
-
page = self.memory_wiki_service.get_page(company.short_name, page_id)
|
|
567
|
+
page = self.memory_wiki_service.get_page(company.short_name, page_id, audience_keys=audience)
|
|
552
568
|
if page:
|
|
553
569
|
candidates.append(page)
|
|
554
570
|
return candidates
|
|
555
571
|
|
|
556
|
-
def _wiki_context(self, company: Company, candidates: list[dict]) -> dict:
|
|
572
|
+
def _wiki_context(self, company: Company, candidates: list[dict], capture: MemoryCapture | None = None) -> dict:
|
|
557
573
|
return {
|
|
558
574
|
"wiki_schema": str(self.memory_wiki_service.read_schema() or "")[:7000],
|
|
559
575
|
"page_index": [
|
|
560
576
|
{"page_id": entry.get("id"), "title": entry.get("title"), "summary": entry.get("summary")}
|
|
561
|
-
for entry in (self.memory_wiki_service.list_pages(
|
|
577
|
+
for entry in (self.memory_wiki_service.list_pages(
|
|
578
|
+
company.short_name, audience_keys=self._audience(capture) if capture is not None else [None]) or []
|
|
579
|
+
)[:self.MAX_INDEX_ENTRIES_IN_PROMPT]
|
|
562
580
|
],
|
|
563
581
|
"candidate_pages": [
|
|
564
582
|
{"page_id": page.get("id"), "title": page.get("title"),
|
|
@@ -576,7 +594,7 @@ class MemoryCompilerService:
|
|
|
576
594
|
captured_on: str):
|
|
577
595
|
return self._ingest_with_llm(
|
|
578
596
|
company, capture, self._agent_for(capture) or self.DOCUMENT_AGENT,
|
|
579
|
-
{"source": source, "part": part, "captured_on": captured_on, **self._wiki_context(company, candidates)},
|
|
597
|
+
{"source": source, "part": part, "captured_on": captured_on, **self._wiki_context(company, candidates, capture)},
|
|
580
598
|
question=f"Read memory document {source.get('label')} (part {part['index']} of {part['total']})",
|
|
581
599
|
)
|
|
582
600
|
|
|
@@ -589,7 +607,7 @@ class MemoryCompilerService:
|
|
|
589
607
|
captured_on: str):
|
|
590
608
|
return self._ingest_with_llm(
|
|
591
609
|
company, capture, self.IMAGE_AGENT,
|
|
592
|
-
{"source": source, "captured_on": captured_on, **self._wiki_context(company, candidates)},
|
|
610
|
+
{"source": source, "captured_on": captured_on, **self._wiki_context(company, candidates, capture)},
|
|
593
611
|
question=f"Look at memory image {source.get('label')}",
|
|
594
612
|
images=images,
|
|
595
613
|
)
|
|
@@ -776,6 +794,11 @@ class MemoryCompilerService:
|
|
|
776
794
|
capture.last_compiled_at = datetime.now()
|
|
777
795
|
self.memory_repo.save_capture(capture)
|
|
778
796
|
|
|
797
|
+
@staticmethod
|
|
798
|
+
def _audience(capture: MemoryCapture) -> list:
|
|
799
|
+
"""The one audience a capture compiles into (BL-010, Fase 3): it sees and writes only its pages."""
|
|
800
|
+
return [getattr(capture, "audience_key", None) or None]
|
|
801
|
+
|
|
779
802
|
def _load_candidate_pages(self, company: Company, capture: MemoryCapture, items: list[MemoryItem]) -> list[dict]:
|
|
780
803
|
"""Pages the capture most likely belongs to, read in full (markdown and checksum)."""
|
|
781
804
|
ordered_ids: list[int] = []
|
|
@@ -788,15 +811,17 @@ class MemoryCompilerService:
|
|
|
788
811
|
for page_id in self.memory_repo.list_page_ids_for_items([item.id for item in items if getattr(item, "id", None)]):
|
|
789
812
|
add(page_id)
|
|
790
813
|
query = self._memory_capture_query(capture, items)
|
|
814
|
+
audience = self._audience(capture)
|
|
791
815
|
if query:
|
|
792
|
-
for result in self.memory_wiki_service.search_pages(company.short_name, query, limit=self.MAX_CANDIDATE_PAGES
|
|
816
|
+
for result in self.memory_wiki_service.search_pages(company.short_name, query, limit=self.MAX_CANDIDATE_PAGES,
|
|
817
|
+
audience_keys=audience):
|
|
793
818
|
add(result.get("id"))
|
|
794
819
|
|
|
795
820
|
candidates = []
|
|
796
821
|
for page_id in ordered_ids:
|
|
797
822
|
if len(candidates) >= self.MAX_CANDIDATE_PAGES:
|
|
798
823
|
break
|
|
799
|
-
page = self.memory_wiki_service.get_page(company.short_name, page_id)
|
|
824
|
+
page = self.memory_wiki_service.get_page(company.short_name, page_id, audience_keys=audience)
|
|
800
825
|
if page:
|
|
801
826
|
candidates.append(page)
|
|
802
827
|
return candidates
|
|
@@ -827,7 +852,7 @@ class MemoryCompilerService:
|
|
|
827
852
|
author=author,
|
|
828
853
|
captured_on=captured_on,
|
|
829
854
|
wiki_schema=self.memory_wiki_service.read_schema(),
|
|
830
|
-
index_entries=self.memory_wiki_service.list_pages(company.short_name),
|
|
855
|
+
index_entries=self.memory_wiki_service.list_pages(company.short_name, audience_keys=self._audience(capture)),
|
|
831
856
|
)
|
|
832
857
|
native_pdf_attachments = self._build_capture_native_pdf_attachments(company.short_name, items)
|
|
833
858
|
try:
|