iatoolkit 2.66.0__tar.gz → 2.68.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.66.0/src/iatoolkit.egg-info → iatoolkit-2.68.0}/PKG-INFO +2 -1
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/readme.md +1 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/__init__.py +1 -1
- iatoolkit-2.68.0/src/iatoolkit/common/memory_tools.py +25 -0
- iatoolkit-2.68.0/src/iatoolkit/config/system_agents/memory_meeting_ingest.prompt +38 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_agents_pack.yaml +59 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_tools_pack.yaml +58 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/connectors/local_file_connector.py +4 -2
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/locales/en.yaml +1 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/locales/es.yaml +1 -0
- iatoolkit-2.68.0/src/iatoolkit/repositories/advisory_lock.py +48 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/repositories/knowledge_wiki_repo.py +135 -1
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/repositories/memory_question_repo.py +23 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/repositories/memory_repo.py +13 -0
- iatoolkit-2.68.0/src/iatoolkit/repositories/memory_usage_repo.py +68 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/repositories/models.py +63 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/dispatcher_service.py +23 -1
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/memory_compiler_service.py +21 -21
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/memory_question_service.py +68 -38
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/memory_service.py +48 -9
- iatoolkit-2.68.0/src/iatoolkit/services/memory_usage_service.py +79 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/tenant_wiki_service.py +83 -2
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/tool_service.py +41 -0
- iatoolkit-2.68.0/src/iatoolkit/services/wiki_page_index_service.py +72 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/account.html +5 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0/src/iatoolkit.egg-info}/PKG-INFO +2 -1
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit.egg-info/SOURCES.txt +6 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/LICENSE +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/LICENSE_COMMUNITY.md +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/pyproject.toml +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/setup.cfg +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/base_company.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/cli_commands.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/common/__init__.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/common/bridge_validation.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/common/company_paths.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/common/exceptions.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/common/interfaces/__init__.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/common/interfaces/asset_storage.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/common/interfaces/database_provider.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/common/interfaces/memory_compilation_trigger.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/common/interfaces/secret_provider.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/common/interfaces/signup_policy_resolver.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/common/interfaces/web_search_provider.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/common/model_registry.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/common/routes.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/common/search_terms.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/common/secret_resolver.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/common/session_manager.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/common/text_splitter.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/common/url_safety.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/common/util.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/company_registry.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/__init__.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/llm_capabilities.yaml +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_agents/memory_compiler.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_agents/memory_correction.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_agents/memory_document_ingest.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_agents/memory_image_ingest.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_agents/memory_question_review.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/channel_business_identity.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/channel_conversation_continuity.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/channel_response_style.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/chat_state_rules.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/chat_user_profile.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/core_identity.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/email_output.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/file_download_output.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/format_styles.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/html_structures.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/links_documents.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/memory_usage.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/multimodal_basics.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/output_basics.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/presentation_formatting.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/query_main.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/sql_aggregation_scope.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/sql_casting.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/sql_core.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/sql_jsonb.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/sql_mysql_casting.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/sql_mysql_json.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/sql_redshift_basics.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/sql_redshift_types.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/sql_rules.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts/tool_html_passthrough.prompt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/config/system_prompts_pack.yaml +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/core.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/__init__.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/call_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/connectors/__init__.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/google_auth_client.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/google_chat_app.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/inference_embeddings_client.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/inference_handler.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/jina_embeddings_client.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/llm_gateway_resolver.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/llm_providers/__init__.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/llm_providers/anthropic_adapter.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/llm_providers/openai_adapter.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/llm_providers/openai_compatible_chat_adapter.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/llm_providers/openrouter_adapter.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/llm_proxy.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/llm_response.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/redis_session_manager.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/repositories/__init__.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/repositories/api_key_repo.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/repositories/bridge_repo.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/repositories/database_manager.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/repositories/document_repo.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/repositories/env_secret_provider.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/repositories/filesystem_asset_repository.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/repositories/mcp_token_repo.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/repositories/profile_repo.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/repositories/prompt_resource_repo.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/repositories/sql_dataset_repo.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/repositories/sql_source_repo.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/repositories/vs_repo.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/runtime_logging.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/__init__.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/api_key_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/attachment_policy_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/auth_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/branding_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/company_context_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/configuration_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/context_builder_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/embedding_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/excel_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/file_processor_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/history_manager_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/http_tool_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/i18n_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/inference_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/jwt_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/knowledge_base_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/language_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/license_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/llm_client_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/mail_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/markdown_wiki_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/mcp_token_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/memory_lookup_policy_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/memory_wiki_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/noop_memory_compilation_trigger.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/operator_identity_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/parsers/__init__.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/parsers/contracts.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/parsers/image_normalizer.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/parsers/parsing_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/parsers/pdf_ocr_detection.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/parsers/provider_factory.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/parsers/provider_resolver.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/parsers/providers/__init__.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/parsers/providers/basic_provider.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/parsers/providers/docling_provider.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/parsers/validator.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/pdf_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/profile_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/prompt_resource_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/prompt_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/query_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/signup_policy_resolver.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/sql_dataset_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/sql_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/sql_source_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/storage_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/structured_output_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/system_agent_catalog.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/system_agent_runner.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/system_prompt_catalog.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/system_tools.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/telemetry_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/tool_output_contract.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/user_feedback_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/user_session_context_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/visual_kb_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/visual_tool_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/warmup_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/web_search/__init__.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/web_search/provider_factory.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/web_search/providers/__init__.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/web_search/providers/brave_provider.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/services/web_search_service.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/images/favicon.ico +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/images/favicon.png +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/images/fernando.jpeg +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/js/chat_filepond.js +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/js/chat_header_navigation.js +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/js/chat_help_content.js +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/js/chat_history_button.js +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/js/chat_main.js +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/js/chat_memory_button.js +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/js/chat_reload_button.js +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/styles/account.css +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/styles/chat_modal.css +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/styles/chat_public.css +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/styles/documents.css +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/styles/landing_page.css +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/styles/llm_output.css +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/styles/onboarding.css +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/static/styles/wiki_page.css +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/_chat_header.html +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/_company_header.html +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/_login_widget.html +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/base.html +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/change_password.html +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/chat.html +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/chat_memory_modal.html +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/chat_modals.html +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/error.html +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/forgot_password.html +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/home_hosted_default.html +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/login_global.html +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/memory/wiki_schema.md +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/onboarding_shell.html +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/pdf/base.html +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/pdf/letter.html +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/pdf/report.html +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/pdf/simple.html +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/signup.html +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/templates/wiki_page.html +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/__init__.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/account_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/api_key_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/base_login_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/categories_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/change_password_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/chat_context_preview_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/chat_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/configuration_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/connectors_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/embedding_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/forgot_password_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/help_content_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/history_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/home_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/init_context_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/llmquery_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/load_document_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/login_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/logout_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/memory_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/profile_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/prompt_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/prompt_context_preview_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/prompt_resource_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/rag_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/root_redirect_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/signup_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/static_page_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/tool_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/users_api_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/verify_user_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/views/wiki_page_view.py +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit.egg-info/requires.txt +0 -0
- {iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: iatoolkit
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.68.0
|
|
4
4
|
Summary: IAToolkit
|
|
5
5
|
Author: Fernando Libedinsky
|
|
6
6
|
License-Expression: MIT
|
|
@@ -242,6 +242,7 @@ Perfect for developers, small teams, single-business use cases, and experimentat
|
|
|
242
242
|
|
|
243
243
|
## 📚 Documentation
|
|
244
244
|
|
|
245
|
+
- 🐳 **[Docker installation](docker/README.md)** – Community Edition with PostgreSQL, Redis and populated Northwind data
|
|
245
246
|
- 🚀 **[Quickstart](docs/quickstart.md)** – Set up your environment and run the project
|
|
246
247
|
- ☁️ **[Deployment Guide](docs/deployment_guide.md)** – Production deployment instructions
|
|
247
248
|
- 🏗️ **[Companies & Components](docs/companies_and_components.md)** – how Company modules work
|
|
@@ -151,6 +151,7 @@ Perfect for developers, small teams, single-business use cases, and experimentat
|
|
|
151
151
|
|
|
152
152
|
## 📚 Documentation
|
|
153
153
|
|
|
154
|
+
- 🐳 **[Docker installation](docker/README.md)** – Community Edition with PostgreSQL, Redis and populated Northwind data
|
|
154
155
|
- 🚀 **[Quickstart](docs/quickstart.md)** – Set up your environment and run the project
|
|
155
156
|
- ☁️ **[Deployment Guide](docs/deployment_guide.md)** – Production deployment instructions
|
|
156
157
|
- 🏗️ **[Companies & Components](docs/companies_and_components.md)** – how Company modules work
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
+
# Product: IAToolkit
|
|
3
|
+
#
|
|
4
|
+
# IAToolkit is open source software.
|
|
5
|
+
|
|
6
|
+
"""What "used the Memoria" means, in one place (Fase 2 of the Memoria architecture review).
|
|
7
|
+
|
|
8
|
+
Before, five modules each kept their own list of Memoria tools, so the hourly
|
|
9
|
+
question review, Impacto and the prompts counted different things.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
# Looking for knowledge: a page search or a document search.
|
|
13
|
+
SEARCH_TOOLS = frozenset({"iat_memory_search", "iat_document_search"})
|
|
14
|
+
# Reading what a search found.
|
|
15
|
+
READ_TOOLS = frozenset({"iat_memory_get_page", "iat_document_read", "iat_document_list"})
|
|
16
|
+
# Every tool whose use is a use of the company's knowledge (usage events, Impacto).
|
|
17
|
+
KNOWLEDGE_TOOLS = SEARCH_TOOLS | READ_TOOLS
|
|
18
|
+
|
|
19
|
+
PAGE_SEARCH_TOOL = "iat_memory_search"
|
|
20
|
+
PAGE_READ_TOOL = "iat_memory_get_page"
|
|
21
|
+
DOCUMENT_SEARCH_TOOL = "iat_document_search"
|
|
22
|
+
DOCUMENT_READ_TOOL = "iat_document_read"
|
|
23
|
+
|
|
24
|
+
CHANNEL_CHAT = "chat"
|
|
25
|
+
CHANNEL_MCP = "mcp"
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
You maintain the company's Memory: a wiki of how things are actually done in this company (procedures, rules, exceptions, who decides). It is written from what its people explain and from the company's own documents.
|
|
2
|
+
|
|
3
|
+
A meeting transcript was loaded into Memory (SOURCE). You receive it in parts; this is part {{ part.index }} of {{ part.total }} (PART). Bring into the wiki what the meeting decided about how things are done here.
|
|
4
|
+
|
|
5
|
+
What to take:
|
|
6
|
+
|
|
7
|
+
- Decisions that were made ("from now on, discounts over 10% need the manager"), with who decided when the transcript says so.
|
|
8
|
+
- Procedures, rules, deadlines and amounts that were agreed or explained, and who is responsible for what.
|
|
9
|
+
- Not the conversation itself: no greetings, small talk, opinions that led nowhere, ideas that were only discussed, or who said what along the way.
|
|
10
|
+
- Nothing personal or sensitive about the people in the meeting (health, salaries, performance, private matters), even if it was said.
|
|
11
|
+
- A transcript is spoken language and may have recognition errors: write the knowledge clearly, and when a name, number or term is unclear, leave it out rather than guess.
|
|
12
|
+
- An action item ("Juan will send the price list on Friday") is not knowledge on its own; keep it only when it reveals how something is done or who is responsible for it.
|
|
13
|
+
|
|
14
|
+
How to write the pages:
|
|
15
|
+
|
|
16
|
+
- Update one of the CANDIDATE_PAGES when the part belongs to its subject; create a new page when none covers it (check PAGE_INDEX first so you do not duplicate a page). One part may touch several pages; return each one.
|
|
17
|
+
- When you update, return the COMPLETE new page: keep everything already on it, word for word, including people's attributions. Add the new facts in the section where they belong.
|
|
18
|
+
- When this part says something different from what the page already says, keep both statements with their attributions and make the difference explicit; never delete what someone else said. Also list each contradiction in `conflicts`. A meeting that changes a rule is a contradiction worth showing.
|
|
19
|
+
- Attribute every fact you add to the meeting: ({{ source.label }}, {{ captured_on }}).
|
|
20
|
+
- Follow the WIKI_SCHEMA. Write in the language of the page, or of the transcript for a new page.
|
|
21
|
+
- If this part decided or taught nothing worth keeping, return an empty `pages` list.
|
|
22
|
+
|
|
23
|
+
Answer with JSON following the schema: a list `pages`, each with `action` (create or update), `target_page_id` (the page_id you update, or null), `title`, `summary` (one sentence on what the page covers), `markdown` (the page body without frontmatter, starting with `# Title`) and `change_summary` (one short sentence for the page history); and a list `conflicts`, one per contradiction with what a page already said: `page_title`, `existing_statement` (what the page said, as written), `existing_source` (its attribution), `new_statement` and `new_source` ({{ source.label }}, {{ captured_on }}). An empty list when nothing contradicts.
|
|
24
|
+
|
|
25
|
+
SOURCE:
|
|
26
|
+
{{ source | json }}
|
|
27
|
+
|
|
28
|
+
PART {{ part.index }} OF {{ part.total }}:
|
|
29
|
+
{{ part.text }}
|
|
30
|
+
|
|
31
|
+
WIKI_SCHEMA:
|
|
32
|
+
{{ wiki_schema }}
|
|
33
|
+
|
|
34
|
+
PAGE_INDEX:
|
|
35
|
+
{{ page_index | json }}
|
|
36
|
+
|
|
37
|
+
CANDIDATE_PAGES:
|
|
38
|
+
{{ candidate_pages | json }}
|
|
@@ -195,6 +195,65 @@ agents:
|
|
|
195
195
|
inputs: [source, part, captured_on, wiki_schema, page_index, candidate_pages]
|
|
196
196
|
default_model: null
|
|
197
197
|
|
|
198
|
+
- key: memory_meeting_ingest
|
|
199
|
+
name: Lector de reuniones de Memoria
|
|
200
|
+
name_en: Memory meeting reader
|
|
201
|
+
description: >-
|
|
202
|
+
(Memoria de la empresa) Lee las transcripciones de reuniones de las carpetas
|
|
203
|
+
marcadas como reuniones y lleva a la wiki las decisiones, los procedimientos y
|
|
204
|
+
los responsables que se acordaron, no la conversación.
|
|
205
|
+
description_en: >-
|
|
206
|
+
(Company memory) Reads the meeting transcripts of the folders marked as
|
|
207
|
+
meetings and files into the wiki the decisions, procedures and owners agreed,
|
|
208
|
+
not the conversation.
|
|
209
|
+
module: memory
|
|
210
|
+
prompt: memory_meeting_ingest.prompt
|
|
211
|
+
output_schema:
|
|
212
|
+
type: object
|
|
213
|
+
properties:
|
|
214
|
+
pages:
|
|
215
|
+
type: array
|
|
216
|
+
items:
|
|
217
|
+
type: object
|
|
218
|
+
properties:
|
|
219
|
+
action:
|
|
220
|
+
type: string
|
|
221
|
+
enum: [create, update]
|
|
222
|
+
# Nullable as a type list: the structured-output validator rejects null under anyOf.
|
|
223
|
+
target_page_id:
|
|
224
|
+
type: [integer, "null"]
|
|
225
|
+
title:
|
|
226
|
+
type: string
|
|
227
|
+
summary:
|
|
228
|
+
type: string
|
|
229
|
+
markdown:
|
|
230
|
+
type: string
|
|
231
|
+
change_summary:
|
|
232
|
+
type: string
|
|
233
|
+
required: [action, target_page_id, title, markdown]
|
|
234
|
+
additionalProperties: false
|
|
235
|
+
conflicts:
|
|
236
|
+
type: array
|
|
237
|
+
items:
|
|
238
|
+
type: object
|
|
239
|
+
properties:
|
|
240
|
+
page_title:
|
|
241
|
+
type: string
|
|
242
|
+
existing_statement:
|
|
243
|
+
type: string
|
|
244
|
+
existing_source:
|
|
245
|
+
type: string
|
|
246
|
+
new_statement:
|
|
247
|
+
type: string
|
|
248
|
+
new_source:
|
|
249
|
+
type: string
|
|
250
|
+
required: [page_title, existing_statement, new_statement]
|
|
251
|
+
additionalProperties: false
|
|
252
|
+
required: [pages]
|
|
253
|
+
additionalProperties: false
|
|
254
|
+
inputs: [source, part, captured_on, wiki_schema, page_index, candidate_pages]
|
|
255
|
+
default_model: null
|
|
256
|
+
|
|
198
257
|
- key: memory_image_ingest
|
|
199
258
|
name: Lector de imágenes de Memoria
|
|
200
259
|
name_en: Memory image reader
|
|
@@ -575,6 +575,64 @@ tools:
|
|
|
575
575
|
required:
|
|
576
576
|
- content
|
|
577
577
|
- title
|
|
578
|
+
- function_name: iat_memory_pending_questions
|
|
579
|
+
description: Lista las preguntas sobre la empresa que la IA no supo responder y siguen abiertas, primero las que se le sugirieron a este usuario por ser quien más sabe del tema, después las más preguntadas. Úsala cuando el usuario pregunte qué preguntas tiene pendientes, quiera ayudar a completar la Memoria de la empresa o pida responder las preguntas de su área. Para responder una, usa `iat_memory_answer_question`.
|
|
580
|
+
routing_profile:
|
|
581
|
+
tags:
|
|
582
|
+
- memory
|
|
583
|
+
- company_memory
|
|
584
|
+
- questions
|
|
585
|
+
- pending
|
|
586
|
+
- unanswered
|
|
587
|
+
intents:
|
|
588
|
+
- List the unanswered questions the user could answer.
|
|
589
|
+
- Show the questions suggested to the user for their area.
|
|
590
|
+
examples:
|
|
591
|
+
- iat_memory_pending_questions(limit=5)
|
|
592
|
+
cost:
|
|
593
|
+
penalty: 0.1
|
|
594
|
+
latency_class: low
|
|
595
|
+
expensive: false
|
|
596
|
+
parameters:
|
|
597
|
+
type: object
|
|
598
|
+
properties:
|
|
599
|
+
limit:
|
|
600
|
+
type: integer
|
|
601
|
+
description: Cuántas preguntas listar, como máximo 15.
|
|
602
|
+
required: []
|
|
603
|
+
- function_name: iat_memory_answer_question
|
|
604
|
+
description: Responde una pregunta sin respuesta de la Memoria de la empresa (de `iat_memory_pending_questions`). La respuesta queda en la Memoria con el nombre del usuario, la ve TODA la empresa, y la pregunta deja de estar pendiente. Antes de llamarla, muéstrale al usuario el texto que vas a guardar y espera que lo confirme. Redacta `answer` en tono neutro, completo y autocontenido, con solo lo que el usuario dijo.
|
|
605
|
+
execution_config:
|
|
606
|
+
side_effects: true
|
|
607
|
+
destructive: false
|
|
608
|
+
routing_profile:
|
|
609
|
+
tags:
|
|
610
|
+
- memory
|
|
611
|
+
- company_memory
|
|
612
|
+
- questions
|
|
613
|
+
- answer
|
|
614
|
+
- know_how
|
|
615
|
+
intents:
|
|
616
|
+
- Answer an unanswered question of the company memory with what the user explained.
|
|
617
|
+
- Use only after the user confirms the text to save.
|
|
618
|
+
examples:
|
|
619
|
+
- iat_memory_answer_question(question_id=12, answer="El plazo de pago a proveedores es de 45 días desde la factura; para proveedores nuevos, 30.")
|
|
620
|
+
cost:
|
|
621
|
+
penalty: 0.1
|
|
622
|
+
latency_class: medium
|
|
623
|
+
expensive: false
|
|
624
|
+
parameters:
|
|
625
|
+
type: object
|
|
626
|
+
properties:
|
|
627
|
+
question_id:
|
|
628
|
+
type: integer
|
|
629
|
+
description: El id de la pregunta, de `iat_memory_pending_questions`.
|
|
630
|
+
answer:
|
|
631
|
+
type: string
|
|
632
|
+
description: La respuesta, redactada en tono neutro y autocontenida (debe entenderse sin la conversación).
|
|
633
|
+
required:
|
|
634
|
+
- question_id
|
|
635
|
+
- answer
|
|
578
636
|
- function_name: iat_image_search
|
|
579
637
|
description: Busca imágenes en la base de conocimiento visual de la empresa usando una descripción de texto. Útil cuando el usuario pide 'ver' algo, 'muéstrame una foto de...', o busca gráficos y diagramas.
|
|
580
638
|
routing:
|
{iatoolkit-2.66.0 → iatoolkit-2.68.0}/src/iatoolkit/infra/connectors/local_file_connector.py
RENAMED
|
@@ -91,5 +91,7 @@ class LocalFileConnector(FileConnector):
|
|
|
91
91
|
raise IAToolkitException(IAToolkitException.ErrorType.FILE_IO_ERROR,
|
|
92
92
|
f"Error eliminando el archivo {file_path}: {e}")
|
|
93
93
|
|
|
94
|
-
def generate_presigned_url(self, file_path: str, expiration: int = 3600) -> str:
|
|
95
|
-
|
|
94
|
+
def generate_presigned_url(self, file_path: str, expiration: int = 3600) -> str | None:
|
|
95
|
+
# FileConnector allows None when storage has no external URL. RAG
|
|
96
|
+
# results can still return their text, and Flask streams downloads.
|
|
97
|
+
return None
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
+
# Product: IAToolkit
|
|
3
|
+
#
|
|
4
|
+
# IAToolkit is open source software.
|
|
5
|
+
|
|
6
|
+
"""One Postgres advisory lock helper for everything that runs once per key across workers.
|
|
7
|
+
|
|
8
|
+
A Postgres advisory lock belongs to the *database connection* that took it. An
|
|
9
|
+
ORM session hands its connection back to the pool on every commit, so a lock
|
|
10
|
+
taken through the session can end up held by a pooled connection nobody owns,
|
|
11
|
+
and released (or not) through another one. This helper always takes and
|
|
12
|
+
releases the lock on its own dedicated connection, for exactly the `with` block.
|
|
13
|
+
|
|
14
|
+
On SQLite (tests) there is no advisory lock: the block runs as if it held it.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from contextlib import contextmanager
|
|
20
|
+
|
|
21
|
+
from sqlalchemy import text
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@contextmanager
|
|
25
|
+
def advisory_lock(db_manager, namespace: int, key: int, *, wait: bool = True):
|
|
26
|
+
"""
|
|
27
|
+
Holds the two-key advisory lock (namespace, key) for the block and yields
|
|
28
|
+
whether it is held: always True when `wait` (it blocks until it gets it);
|
|
29
|
+
with `wait=False`, False when someone else holds it (the block should skip).
|
|
30
|
+
"""
|
|
31
|
+
if db_manager.get_dialect() not in ("postgresql", "postgres"):
|
|
32
|
+
yield True
|
|
33
|
+
return
|
|
34
|
+
params = {"namespace": int(namespace), "key": int(key)}
|
|
35
|
+
connection = db_manager.get_connection()
|
|
36
|
+
try:
|
|
37
|
+
if wait:
|
|
38
|
+
connection.execute(text("SELECT pg_advisory_lock(:namespace, :key)"), params)
|
|
39
|
+
held = True
|
|
40
|
+
else:
|
|
41
|
+
held = bool(connection.execute(text("SELECT pg_try_advisory_lock(:namespace, :key)"), params).scalar())
|
|
42
|
+
try:
|
|
43
|
+
yield held
|
|
44
|
+
finally:
|
|
45
|
+
if held:
|
|
46
|
+
connection.execute(text("SELECT pg_advisory_unlock(:namespace, :key)"), params)
|
|
47
|
+
finally:
|
|
48
|
+
connection.close()
|
|
@@ -5,15 +5,17 @@
|
|
|
5
5
|
|
|
6
6
|
from __future__ import annotations
|
|
7
7
|
|
|
8
|
+
import hashlib
|
|
8
9
|
from datetime import datetime
|
|
9
10
|
|
|
10
11
|
from injector import inject
|
|
11
|
-
from sqlalchemy import or_
|
|
12
|
+
from sqlalchemy import or_, text
|
|
12
13
|
|
|
13
14
|
from iatoolkit.repositories.database_manager import DatabaseManager
|
|
14
15
|
from iatoolkit.repositories.models import (
|
|
15
16
|
KnowledgeWiki,
|
|
16
17
|
KnowledgeWikiPage,
|
|
18
|
+
KnowledgeWikiPageIndex,
|
|
17
19
|
KnowledgeWikiPageRevision,
|
|
18
20
|
KnowledgeWikiPageStatus,
|
|
19
21
|
KnowledgeWikiStatus,
|
|
@@ -117,6 +119,16 @@ class KnowledgeWikiRepo:
|
|
|
117
119
|
.first()
|
|
118
120
|
)
|
|
119
121
|
|
|
122
|
+
def get_pages_by_ids(self, wiki_ids: list[int], page_ids: list[int]) -> dict[int, KnowledgeWikiPage]:
|
|
123
|
+
if not wiki_ids or not page_ids:
|
|
124
|
+
return {}
|
|
125
|
+
pages = (
|
|
126
|
+
self.session.query(KnowledgeWikiPage)
|
|
127
|
+
.filter(KnowledgeWikiPage.wiki_id.in_(list(wiki_ids)), KnowledgeWikiPage.id.in_(list(page_ids)))
|
|
128
|
+
.all()
|
|
129
|
+
)
|
|
130
|
+
return {page.id: page for page in pages}
|
|
131
|
+
|
|
120
132
|
def get_page_by_slug(self, wiki_id: int, slug: str) -> KnowledgeWikiPage | None:
|
|
121
133
|
if not wiki_id or not slug:
|
|
122
134
|
return None
|
|
@@ -203,21 +215,143 @@ class KnowledgeWikiRepo:
|
|
|
203
215
|
)
|
|
204
216
|
self.session.add(page)
|
|
205
217
|
self.session.commit()
|
|
218
|
+
self.index_page(page)
|
|
206
219
|
return page
|
|
207
220
|
|
|
208
221
|
def save_page(self, page: KnowledgeWikiPage) -> KnowledgeWikiPage:
|
|
209
222
|
self.session.add(page)
|
|
210
223
|
self.session.commit()
|
|
224
|
+
self.index_page(page)
|
|
211
225
|
return page
|
|
212
226
|
|
|
213
227
|
def delete_page(self, wiki_id: int, path: str) -> KnowledgeWikiPage | None:
|
|
214
228
|
page = self.get_page_by_path(wiki_id, path)
|
|
215
229
|
if page is None:
|
|
216
230
|
return None
|
|
231
|
+
self.session.query(KnowledgeWikiPageIndex).filter(KnowledgeWikiPageIndex.page_id == page.id).delete()
|
|
217
232
|
self.session.delete(page)
|
|
218
233
|
self.session.commit()
|
|
219
234
|
return page
|
|
220
235
|
|
|
236
|
+
# =====================================================================
|
|
237
|
+
# Search index (iat_knowledge_wiki_page_index)
|
|
238
|
+
# =====================================================================
|
|
239
|
+
|
|
240
|
+
# What the word branch searches; the meaning branch embeds the same text, cut.
|
|
241
|
+
INDEX_TEXT_CHARS = 60000
|
|
242
|
+
|
|
243
|
+
@classmethod
|
|
244
|
+
def page_search_text(cls, page: KnowledgeWikiPage) -> str:
|
|
245
|
+
parts = [page.title or "", page.summary or "", " ".join(str(t) for t in (page.tags or [])), page.body_text or ""]
|
|
246
|
+
return "\n".join(part.strip() for part in parts if str(part or "").strip())[:cls.INDEX_TEXT_CHARS]
|
|
247
|
+
|
|
248
|
+
def index_page(self, page: KnowledgeWikiPage) -> KnowledgeWikiPageIndex:
|
|
249
|
+
"""Writes the page's search text; a changed text clears the embedding so it is computed again."""
|
|
250
|
+
search_text = self.page_search_text(page)
|
|
251
|
+
content_hash = hashlib.sha256(search_text.encode("utf-8")).hexdigest()
|
|
252
|
+
row = self.session.query(KnowledgeWikiPageIndex).filter(KnowledgeWikiPageIndex.page_id == page.id).first()
|
|
253
|
+
if row is None:
|
|
254
|
+
row = KnowledgeWikiPageIndex(page_id=page.id, wiki_id=page.wiki_id, company_id=page.company_id)
|
|
255
|
+
self.session.add(row)
|
|
256
|
+
elif row.content_hash == content_hash and row.wiki_id == page.wiki_id:
|
|
257
|
+
return row
|
|
258
|
+
row.wiki_id = page.wiki_id
|
|
259
|
+
row.search_text = search_text
|
|
260
|
+
row.content_hash = content_hash
|
|
261
|
+
if row.embedded_hash != content_hash:
|
|
262
|
+
row.embedding = None
|
|
263
|
+
row.embedded_hash = None
|
|
264
|
+
self.session.commit()
|
|
265
|
+
return row
|
|
266
|
+
|
|
267
|
+
def list_pages_to_embed(self, limit: int = 100, company_id: int | None = None) -> list[KnowledgeWikiPageIndex]:
|
|
268
|
+
query = (
|
|
269
|
+
self.session.query(KnowledgeWikiPageIndex)
|
|
270
|
+
.join(KnowledgeWikiPage, KnowledgeWikiPage.id == KnowledgeWikiPageIndex.page_id)
|
|
271
|
+
.filter(KnowledgeWikiPage.status != KnowledgeWikiPageStatus.ARCHIVED)
|
|
272
|
+
.filter(or_(KnowledgeWikiPageIndex.embedded_hash.is_(None),
|
|
273
|
+
KnowledgeWikiPageIndex.embedded_hash != KnowledgeWikiPageIndex.content_hash))
|
|
274
|
+
)
|
|
275
|
+
if company_id:
|
|
276
|
+
query = query.filter(KnowledgeWikiPageIndex.company_id == company_id)
|
|
277
|
+
return query.order_by(KnowledgeWikiPageIndex.updated_at.asc()).limit(limit).all()
|
|
278
|
+
|
|
279
|
+
def list_unindexed_pages(self, limit: int = 500) -> list[KnowledgeWikiPage]:
|
|
280
|
+
"""Pages written before the index existed (the backfill)."""
|
|
281
|
+
return (
|
|
282
|
+
self.session.query(KnowledgeWikiPage)
|
|
283
|
+
.outerjoin(KnowledgeWikiPageIndex, KnowledgeWikiPageIndex.page_id == KnowledgeWikiPage.id)
|
|
284
|
+
.filter(KnowledgeWikiPageIndex.id.is_(None))
|
|
285
|
+
.filter(KnowledgeWikiPage.status != KnowledgeWikiPageStatus.ARCHIVED)
|
|
286
|
+
.limit(limit)
|
|
287
|
+
.all()
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
def set_page_embedding(self, row: KnowledgeWikiPageIndex, embedding: list[float], embedded_hash: str) -> None:
|
|
291
|
+
row.embedding = embedding
|
|
292
|
+
row.embedded_hash = embedded_hash
|
|
293
|
+
self.session.commit()
|
|
294
|
+
|
|
295
|
+
def is_postgres(self) -> bool:
|
|
296
|
+
bind = self.session.get_bind()
|
|
297
|
+
return getattr(getattr(bind, "dialect", None), "name", "") == "postgresql"
|
|
298
|
+
|
|
299
|
+
RRF_K = 60
|
|
300
|
+
|
|
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]]:
|
|
303
|
+
"""
|
|
304
|
+
(page_id, rrf_score) of the best pages of these wikis, best first: by
|
|
305
|
+
words (Postgres full text, 'simple', terms OR'ed, the GIN index) and, when
|
|
306
|
+
there is a query embedding, by meaning (pages whose embedding has its
|
|
307
|
+
size), fused by Reciprocal Rank Fusion. Archived pages are left out.
|
|
308
|
+
Postgres only.
|
|
309
|
+
"""
|
|
310
|
+
if not wiki_ids:
|
|
311
|
+
return []
|
|
312
|
+
tsvector = "to_tsvector('simple'::regconfig, i.search_text)"
|
|
313
|
+
tsquery = "replace(plainto_tsquery('simple'::regconfig, :text_terms)::text, ' & ', ' | ')::tsquery"
|
|
314
|
+
params = {"wiki_ids": list(wiki_ids), "text_terms": query_text or "", "candidates": int(candidates),
|
|
315
|
+
"archived": KnowledgeWikiPageStatus.ARCHIVED.name}
|
|
316
|
+
branches = [f"""
|
|
317
|
+
SELECT page_id, ROW_NUMBER() OVER (ORDER BY text_rank DESC, page_id ASC) AS rank
|
|
318
|
+
FROM (
|
|
319
|
+
SELECT i.page_id, ts_rank_cd({tsvector}, terms.q) AS text_rank
|
|
320
|
+
FROM iat_knowledge_wiki_page_index i
|
|
321
|
+
JOIN iat_knowledge_wiki_pages p ON p.id = i.page_id,
|
|
322
|
+
(SELECT {tsquery} AS q) terms
|
|
323
|
+
WHERE i.wiki_id = ANY(:wiki_ids) AND p.status::text <> :archived
|
|
324
|
+
AND {tsvector} @@ terms.q
|
|
325
|
+
ORDER BY text_rank DESC
|
|
326
|
+
LIMIT :candidates
|
|
327
|
+
) words"""]
|
|
328
|
+
if query_embedding:
|
|
329
|
+
dims = len(query_embedding)
|
|
330
|
+
if 0 < dims <= 2000:
|
|
331
|
+
params["query_embedding"] = str(list(query_embedding))
|
|
332
|
+
branches.append(f"""
|
|
333
|
+
SELECT page_id, ROW_NUMBER() OVER (ORDER BY distance ASC, page_id ASC) AS rank
|
|
334
|
+
FROM (
|
|
335
|
+
SELECT i.page_id,
|
|
336
|
+
i.embedding::vector({dims}) <=> CAST(:query_embedding AS vector({dims})) AS distance
|
|
337
|
+
FROM iat_knowledge_wiki_page_index i
|
|
338
|
+
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
|
|
340
|
+
AND i.embedding IS NOT NULL AND vector_dims(i.embedding) = {dims}
|
|
341
|
+
ORDER BY distance ASC
|
|
342
|
+
LIMIT :candidates
|
|
343
|
+
) meaning""")
|
|
344
|
+
union = " UNION ALL ".join(f"({branch})" for branch in branches)
|
|
345
|
+
sql = f"""
|
|
346
|
+
SELECT page_id, SUM(1.0 / ({self.RRF_K} + rank)) AS rrf_score
|
|
347
|
+
FROM ({union}) hits
|
|
348
|
+
GROUP BY page_id
|
|
349
|
+
ORDER BY rrf_score DESC, page_id ASC
|
|
350
|
+
LIMIT :candidates
|
|
351
|
+
"""
|
|
352
|
+
rows = self.session.execute(text(sql), params).fetchall()
|
|
353
|
+
return [(int(row[0]), float(row[1])) for row in rows]
|
|
354
|
+
|
|
221
355
|
def create_page_revision(
|
|
222
356
|
self,
|
|
223
357
|
*,
|
|
@@ -51,6 +51,29 @@ class MemoryQuestionRepo:
|
|
|
51
51
|
.all()
|
|
52
52
|
)
|
|
53
53
|
|
|
54
|
+
def claim_open(self, company_id: int, question_id: int, status: str, resolved_by: str, resolved_at) -> bool:
|
|
55
|
+
"""Resolves the question only if it is still open, in one UPDATE: of two people answering at
|
|
56
|
+
once, exactly one wins (Fase 0, R17). Commits."""
|
|
57
|
+
claimed = (
|
|
58
|
+
self.session.query(MemoryQuestion)
|
|
59
|
+
.filter(MemoryQuestion.company_id == company_id, MemoryQuestion.id == question_id,
|
|
60
|
+
MemoryQuestion.status == MemoryQuestion.STATUS_OPEN)
|
|
61
|
+
.update({MemoryQuestion.status: status, MemoryQuestion.resolved_by: resolved_by,
|
|
62
|
+
MemoryQuestion.resolved_at: resolved_at}, synchronize_session=False)
|
|
63
|
+
)
|
|
64
|
+
self.commit()
|
|
65
|
+
return bool(claimed)
|
|
66
|
+
|
|
67
|
+
def reopen(self, company_id: int, question_id: int) -> None:
|
|
68
|
+
"""Undoes a claim whose answer could not be saved."""
|
|
69
|
+
(
|
|
70
|
+
self.session.query(MemoryQuestion)
|
|
71
|
+
.filter(MemoryQuestion.company_id == company_id, MemoryQuestion.id == question_id)
|
|
72
|
+
.update({MemoryQuestion.status: MemoryQuestion.STATUS_OPEN, MemoryQuestion.resolved_by: None,
|
|
73
|
+
MemoryQuestion.resolved_at: None}, synchronize_session=False)
|
|
74
|
+
)
|
|
75
|
+
self.commit()
|
|
76
|
+
|
|
54
77
|
def get_question(self, company_id: int, question_id: int) -> MemoryQuestion | None:
|
|
55
78
|
return (
|
|
56
79
|
self.session.query(MemoryQuestion)
|
|
@@ -131,6 +131,19 @@ class MemoryRepo:
|
|
|
131
131
|
.all()
|
|
132
132
|
)
|
|
133
133
|
|
|
134
|
+
def list_failed_captures(self, company_id: int, failed_before, limit: int = 50) -> list[MemoryCapture]:
|
|
135
|
+
"""Captures whose compilation failed before `failed_before`, oldest first (to retry them)."""
|
|
136
|
+
if not company_id:
|
|
137
|
+
return []
|
|
138
|
+
return (
|
|
139
|
+
self.session.query(MemoryCapture)
|
|
140
|
+
.filter_by(company_id=company_id, status=MemoryCaptureStatus.FAILED)
|
|
141
|
+
.filter(MemoryCapture.updated_at < failed_before)
|
|
142
|
+
.order_by(MemoryCapture.updated_at.asc(), MemoryCapture.id.asc())
|
|
143
|
+
.limit(limit)
|
|
144
|
+
.all()
|
|
145
|
+
)
|
|
146
|
+
|
|
134
147
|
def add_page_sources(self, company_id: int, wiki_page_id: int, item_ids: list[int]) -> None:
|
|
135
148
|
"""Links items to a wiki page, keeping the links it already has."""
|
|
136
149
|
if not company_id or not wiki_page_id:
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
+
# Product: IAToolkit
|
|
3
|
+
#
|
|
4
|
+
# IAToolkit is open source software.
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from collections import Counter
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
|
|
11
|
+
from injector import inject
|
|
12
|
+
from sqlalchemy import case, func
|
|
13
|
+
|
|
14
|
+
from iatoolkit.common import memory_tools
|
|
15
|
+
from iatoolkit.repositories.database_manager import DatabaseManager
|
|
16
|
+
from iatoolkit.repositories.models import MemoryUsageEvent
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class MemoryUsageRepo:
|
|
20
|
+
"""iat_memory_usage_events: one row per use of the company's knowledge (Fase 2)."""
|
|
21
|
+
|
|
22
|
+
@inject
|
|
23
|
+
def __init__(self, db_manager: DatabaseManager):
|
|
24
|
+
self.session = db_manager.get_session()
|
|
25
|
+
|
|
26
|
+
def add(self, event: MemoryUsageEvent) -> None:
|
|
27
|
+
self.session.add(event)
|
|
28
|
+
self.session.commit()
|
|
29
|
+
|
|
30
|
+
def rollback(self) -> None:
|
|
31
|
+
self.session.rollback()
|
|
32
|
+
|
|
33
|
+
def summarize(self, company_id: int, start: datetime, end: datetime) -> dict:
|
|
34
|
+
"""What the company's knowledge was used for in [start, end), by tool, channel and day."""
|
|
35
|
+
base = (
|
|
36
|
+
self.session.query(MemoryUsageEvent)
|
|
37
|
+
.filter(MemoryUsageEvent.company_id == company_id,
|
|
38
|
+
MemoryUsageEvent.created_at >= start, MemoryUsageEvent.created_at < end)
|
|
39
|
+
)
|
|
40
|
+
searches = found = 0
|
|
41
|
+
by_channel: Counter = Counter()
|
|
42
|
+
by_day: Counter = Counter()
|
|
43
|
+
found_flag = case((MemoryUsageEvent.results > 0, 1), else_=0)
|
|
44
|
+
day = func.date(MemoryUsageEvent.created_at)
|
|
45
|
+
rows = (
|
|
46
|
+
base.with_entities(MemoryUsageEvent.channel, day, found_flag, func.count(MemoryUsageEvent.id))
|
|
47
|
+
.filter(MemoryUsageEvent.tool.in_(list(memory_tools.SEARCH_TOOLS)))
|
|
48
|
+
.group_by(MemoryUsageEvent.channel, day, found_flag)
|
|
49
|
+
.all()
|
|
50
|
+
)
|
|
51
|
+
for channel, event_day, was_found, count in rows:
|
|
52
|
+
searches += count
|
|
53
|
+
if was_found:
|
|
54
|
+
found += count
|
|
55
|
+
by_channel[channel] += count
|
|
56
|
+
by_day[str(event_day)] += count
|
|
57
|
+
page_reads = Counter({str(page_id): count for page_id, count in (
|
|
58
|
+
base.with_entities(MemoryUsageEvent.page_id, func.count(MemoryUsageEvent.id))
|
|
59
|
+
.filter(MemoryUsageEvent.tool == memory_tools.PAGE_READ_TOOL, MemoryUsageEvent.page_id.isnot(None))
|
|
60
|
+
.group_by(MemoryUsageEvent.page_id).all()
|
|
61
|
+
)})
|
|
62
|
+
document_reads = Counter({str(document_id): count for document_id, count in (
|
|
63
|
+
base.with_entities(MemoryUsageEvent.document_id, func.count(MemoryUsageEvent.id))
|
|
64
|
+
.filter(MemoryUsageEvent.tool == memory_tools.DOCUMENT_READ_TOOL, MemoryUsageEvent.document_id.isnot(None))
|
|
65
|
+
.group_by(MemoryUsageEvent.document_id).all()
|
|
66
|
+
)})
|
|
67
|
+
return {"searches": searches, "searches_found": found, "by_channel": dict(by_channel),
|
|
68
|
+
"by_day": dict(by_day), "page_reads": page_reads, "document_reads": document_reads}
|