topos-node 1.3.37__tar.gz → 1.3.39__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.
- {topos_node-1.3.37/topos_node.egg-info → topos_node-1.3.39}/PKG-INFO +3 -3
- {topos_node-1.3.37 → topos_node-1.3.39}/README.md +2 -2
- {topos_node-1.3.37 → topos_node-1.3.39}/pyproject.toml +3 -3
- {topos_node-1.3.37 → topos_node-1.3.39}/tests/test_active_database_binding.py +2 -1
- {topos_node-1.3.37 → topos_node-1.3.39}/tests/test_profile_hygiene.py +2 -1
- {topos_node-1.3.37 → topos_node-1.3.39}/tests/test_profiles.py +4 -3
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/__version__.py +2 -2
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/signal.py +36 -16
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/cli/commands.py +3 -2
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/cli/profile_cmd.py +2 -1
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/cli/tray.py +39 -4
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/ingest.py +3 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/signal_features.py +4 -1
- topos_node-1.3.39/topos/defaults.py +9 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/entities_job.py +3 -1
- topos_node-1.3.39/topos/features/entities/chatgpt_declared.py +256 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/declared_mappings.py +48 -3
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/reads.py +123 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/ingest_helpers.py +10 -2
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/manager.py +8 -1
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/parser.py +43 -15
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/parsers/chatgpt_conversation_flattener.py +10 -2
- topos_node-1.3.39/topos/ingestion/parsers/chatgpt_export.py +652 -0
- topos_node-1.3.39/topos/ingestion/triggers/file_trigger.py +56 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/mcp_stdio_proxy.py +7 -5
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/pipeline/job_runner.py +5 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/profiles.py +4 -3
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/canonical/ai_chat/canonicalizer.py +20 -1
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/pipeline_jobs_v1.py +34 -1
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/upgrades/manifests.json +19 -0
- {topos_node-1.3.37 → topos_node-1.3.39/topos_node.egg-info}/PKG-INFO +3 -3
- {topos_node-1.3.37 → topos_node-1.3.39}/topos_node.egg-info/SOURCES.txt +3 -0
- topos_node-1.3.37/topos/ingestion/triggers/file_trigger.py +0 -36
- {topos_node-1.3.37 → topos_node-1.3.39}/LICENSE +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/MANIFEST.in +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/setup.cfg +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/shared/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/shared/filtering.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/shared/schema_registry.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/tests/test_active_ingestion_binding.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/tests/test_extensions.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/tests/test_gate_leg_hermeticity.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/tests/test_llm_integrations_storage.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/tests/test_local_gate_composition.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/tests/test_owner_database_hermeticity.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/tests/test_prewarm_first_run.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/tests/test_protocol_handled_types.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/tests/test_query_field_contract.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/tests/test_system_computer_name.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/analytics/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/analytics/dataset_resolution.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/analytics/duckdb_adapter.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/analytics/luck_surface.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/analytics/messenger_communities.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/analytics/messenger_directed.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/analytics/messenger_graph.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/analytics/messenger_labels.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/analytics/person_graph.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/analytics/person_overlay.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/analytics/profiles.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/analytics/query_engine.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/analytics/raw_queries.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/analytics/relationship_reads.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/analytics.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/app_registry.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/backup.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/community_naming_config.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/compute_remote.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/connected_apps.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/conversation_context.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/data_commit.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/data_explorer_table_prefs.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/database_explorer.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/db.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/device.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/disk_space_config.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/engine_run.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/enrichment.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/enrichment_lab.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/facts_llm_config.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/filter_lab.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/health.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/home_chat.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/ingestion_api.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/ingestion_compat.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/ingestion_sources.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/intelligence_lifecycle.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/llm.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/local_mcp.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/messenger_analytics.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/privacy_disclose.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/query_api.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/runtime_bootstrap.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/sanitization_ollama_config.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/shell.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/signal_extraction_config.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/source_install.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/source_scrub.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/sources.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/sources_overview.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/sync.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/tool_index.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/ui_config.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/uma_data.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/upgrades.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/usage.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/api/user_identity.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/app.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/auth.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/canonicalization/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/canonicalization/declared_field_map.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/canonicalization/mappers/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/canonicalization/mappers/base.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/canonicalization/mappers/browser_activity_mapper.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/canonicalization/mappers/chatgpt_mapper.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/canonicalization/mappers/demo_mappers.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/canonicalization/mappers/documents_mapper.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/canonicalization/mappers/github_activity_mapper.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/canonicalization/mappers/google_calendar_mapper.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/canonicalization/mappers/grok_mapper.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/canonicalization/mappers/messenger_mapper.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/canonicalization/models.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/canonicalization/resolver.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/cli/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/cli/__main__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/cli/assets/topos_blk_rounded.png +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/cli/assets/topos_white.png +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/cli/reprocess_cmd.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/cli/setup_models_cmd.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/config/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/config/conversation_context_llm.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/config/facts_llm.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/config/local_model_builds.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/config/model_packs.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/config/node_function_providers.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/config/sanitization_ollama.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/config/settings.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/config/signal_extraction.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/config/uvicorn_logging.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/contacts/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/contacts/identity.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/control_plane_client.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/api_models.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/connection_resilience.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/db_health.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/device_helpers.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/errors.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/events.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/common.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/complexity.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/config.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/contacts_import.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/database_explorer.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/derivation.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/device.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/enrichment.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/enrichment_lab.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/filter_lab.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/graph_query.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/home_chat.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/mcp_client_elevations.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/mcp_clients.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/messages.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/messenger_analytics.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/query.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/registry.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/routines.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/sources.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/timeline_daily.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/tool_index.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/handlers/uma.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/logging.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/metrics.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/routine_access.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/startup_banner.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/state.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/table_layers.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/core/types.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/data_explorer_row_delete.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/data_explorer_table_prefs.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/data_explorer_tables.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/disclosure/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/disclosure/canonical_writer.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/disclosure/content_policy.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/disclosure/field_registry.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/disclosure/privacy_layer.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/disclosure/tier.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/backends/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/backends/base.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/backends/generative_prompts.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/backends/generative_response.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/backends/huggingface.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/backends/ollama.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/backends/openai.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/backends/openai_compatible.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/backends/redpill.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/backends/stub.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/client.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/disk_space.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/engine.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/hosted_llm_wallet.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/intake.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/memory_utils.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/model_cache.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/model_manager.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/ollama_install.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/ollama_pull.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/ollama_runtime.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/ollama_setup_guidance.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/pipeline_memory.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/queue_manager.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/registration.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/result_formatter.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/router.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/scoped_token.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/tasks.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/torch_runtime.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/transport.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/usage_guard.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/usage_observation.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/engine/validator.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/catalog.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/derivation_recovery.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/derived_tables.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/job_readiness.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/job_writer.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/base.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/_batch_limits.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/_engine_runner.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/attention_triage_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/availability_scores_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/brief_fallback.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/complexity_snapshot_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/derivation_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/derived_object_embeddings_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/dimension_summary_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/embeddings_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/emo_27_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/fact_extraction_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/goal_extraction_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/pii_redaction_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/relationship_edges_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/sentiment_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/statistics_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/timeline_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/topic_clusters_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/canonical/topics_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/raw/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/raw/attachments_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/raw/language_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/raw/time_normalization_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/jobs/raw/tool_calls_job.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/model_overrides.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/models/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/models/manager.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/models/mvp_defaults.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/models/registry.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/models/versioning.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/orchestrator.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/pipeline_activity.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/processor.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/progress_bar.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/record_progress.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/registry_contract.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/signal_derivation_config.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment/source_overrides.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment_lab/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment_lab/bundles.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment_lab/model_resolve.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment_lab/schema.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment_lab/service.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment_lab/store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/enrichment_lab/worker.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/evals/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/evals/enrichment_eval.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/extensions.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/complexity/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/complexity/canonical.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/complexity/engine.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/complexity/entropy.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/complexity/focus.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/complexity/graph_metrics.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/complexity/influence.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/complexity/projection.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/complexity/snapshots.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/complexity/store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/complexity/topic_merge.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/complexity/topics.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/complexity/topics_daily.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/complexity/volatility.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/_scales.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/admin.legal.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/aspirations.goals.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/behavior.habits.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/behavior.preferences.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/beliefs.civic.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/beliefs.spiritual.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/communication.style.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/community.membership.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/craft.tooling.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/expertise.knowledge.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/finances.economics.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/health.lifestyle.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/health.mental.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/health.physical.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/household.pets.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/identity.core.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/interests.taste.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/life.events.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/narrative.self.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/net.capability.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/obligations.commitments.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/personality.traits.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/places.mobility.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/possessions.assets.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/relationships.social.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/values.motivation.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/vocab/dispositions.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/vocab/expertise.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/vocab/habits.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/vocab/interests.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/vocab/preferences.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/vocab/stances.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/vocab/tools.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/vocab/values.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/bundled_packs/work.career.yaml +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/candidates.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/guard.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/kernels.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/net_subject_policy.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/packs.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/person_bridge.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/prefilter.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/registry.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/report_card.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/router.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/social_bench.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/social_kernels.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/surfaces.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/synthesize.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/template.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/verify.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/derivation/writer.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/affinity.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/affinity_owner.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/affinity_quality.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/community_names.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/community_naming.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/consolidation.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/context_vectors.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/cypher.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/dossier.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/edges.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/fact_materializer.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/graph_enrichers.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/graph_refresh.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/graph_search.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/linking.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/maintenance.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/owner.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/rebuild_subprocess.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/resolver.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/entities/structured_fields.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/facts/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/facts/extract.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/facts/llm_extract.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/facts/reads.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/facts/store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/facts/verdicts.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/fit/evaluator.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/fit/opportunity_types.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/lifecycle/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/lifecycle/blackhole.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/lifecycle/blackhole_guard.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/lifecycle/blackhole_llm.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/lifecycle/blackhole_rebuild.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/lifecycle/derived_scrub.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/lifecycle/exclusions.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/lifecycle/gc.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/provenance/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/provenance/posture.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/provenance/roles.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/brief_canonical_loader.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/brief_ontology.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/brief_renderer.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/brief_schemas.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/chunking.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/cluster_labels.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/conversation_context.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/data_health.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/definitions/brief_ontologies.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/definitions/intentions.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/definitions/interests.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/definitions/memory.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/definitions/places.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/definitions/profile.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/definitions/relationships.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/definitions/resources.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/definitions/schema/dimension_definition.schema.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/definitions/time.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/definitions/wellbeing.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/definitions/work.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/derived_index.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/derived_spec.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/dimension_briefs.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/dimension_definition_loader.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/dimension_profiles.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/dimension_registry.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/embed_context.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/extraction/artifact_router.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/extraction/artifact_store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/extraction/rule_extractors.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/graph_sanitize.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/hybrid_search.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/incremental_clustering.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/model_recommendations.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/query_embed_cache.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/schemas.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/service.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/signal_object_store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/source_hydration.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/structured_signal.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/tool_index.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/topic_clustering.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/typed_stores/aggregates.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/typed_stores/commitments.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/typed_stores/rhythm.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/typed_stores/scope_materializer.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/vector_codec.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/vector_math.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/signal/vector_settings.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/stats/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/stats/definitions.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/stats/engine.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/stats/fold.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/stats/insights.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/timeline_projection.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/timeline_rollup.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/triage/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/triage/badges.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/triage/daily.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/triage/dashboard.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/triage/instruments.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/triage/intents.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/features/triage/readiness.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/filter_lab/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/filter_lab/bundles.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/filter_lab/schema.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/filter_lab/service.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/filter_lab/store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/filter_lab/worker.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/home_chat/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/home_chat/schema.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/home_chat/store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/hosted_pool_lease.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/canonical_pipeline.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/checkpoints/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/checkpoints/checkpoint_store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/checkpoints/sqlite_checkpoint_store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/inbox_crypto.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/inbox_drain.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/jobs.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/journal_location_fanout.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/journal_time_log_normalize.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/local_sync.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/log_preview.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/parsers/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/parsers/base.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/parsers/browser_parser.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/parsers/calendar_parser.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/parsers/chatgpt_parser.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/parsers/demo_file_parsers.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/parsers/documents_parser.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/parsers/github_activity_parser.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/parsers/google_calendar_parser.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/parsers/grok_parser.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/parsers/messenger_parser.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/parsers/voxterm_parser.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/progress.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/reprocess.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/sources/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/sources/base.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/sources/calendar.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/sources/chatgpt.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/sources/contact_importers.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/sources/grok.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/sources/imessage_reader.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/sources/signal_export_parser.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/sources/signal_reader.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/state_machine.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/triggers/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/triggers/sqlite_trigger.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/usage_inbox_dedupe.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/validation/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/validation/base.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/validation/schema_registry.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/ingestion/validation/schema_validator.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/lineage/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/lineage/provenance.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/lineage/tracker.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/llm_integrations_storage.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/mcp_clients.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/observability/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/observability/alerts.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/observability/metrics.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/observability/tracing.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/openai_client.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/owner_key.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/pipeline/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/pipeline/audit.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/pipeline/envelope.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/pipeline/job_store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/pipeline/stages.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/pipeline/stub_enqueue.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/principal.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/projections/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/projections/vector_index/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/projections/vector_index/base.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/projections/vector_index/builders.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/projections/vector_index/health_checks.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/protocol/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/protocol/handled_message_types.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/protocol/narrowing_vocabulary.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/protocol/query_field_contract.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/audit.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/closeness.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/cohort_resolvers.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/collaborators.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/ddr.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/disclosure.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/entity_window.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/exclusion.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/facts_direct.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/fingerprint.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/game_layer.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/grant_cache.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/inference.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/intent.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/manifest.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/manifest_validation.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/minimizer.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/narrowing.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/negotiation.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/packet_resolution.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/pipeline.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/planner.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/retrieval.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/runtime.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/scope_arbiter.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/scope_classifier.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/scope_head.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/scope_registry.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/scope_registry_loader.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/scope_shadow.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/session.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/session_utils.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/source_generation.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/truth_facts.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/truth_prompts.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/turn_classifier.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/types.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/verify.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/query/verify_modes.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/rate_limit.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/relay_stamp.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/routines/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/routines/schema.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/routines/store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/runtime_housekeeping.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/runtime_shutdown.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/runtime_update.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/sanitization/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/sanitization/nsfw_classifier.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/sanitization/ollama_transforms.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/sanitization/prewarm.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/sanitization/privacy_filter.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/scope_resolution.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/services/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/services/container.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/services/embeddings/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/services/embeddings/base.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/services/embeddings/local.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/services/embeddings/remote.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/services/interfaces.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/services/llm/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/services/llm/base.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/services/llm/openai.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/services/local.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/services/postgres.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/sources/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/sources/bundled_canonical_triples.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/sources/canonical_signal_defaults.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/sources/declared_field_map_spec.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/sources/definitions.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/sources/install_service.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/sources/registry.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/sources/runtime_install.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/sources/scrub_attribution.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/sources/scrub_service.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/startup_banner.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/adapters/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/adapters/factory.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/adapters/fakes.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/adapters/postgres/stores.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/adapters/protocols.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/adapters/sqlite/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/adapters/sqlite/stores.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/adapters/sqlite/vector_search.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/canonical/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/canonical/activity_tables.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/canonical/ai_chat/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/canonical/ai_chat/mapper.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/canonical/ai_chat/model.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/canonical/ai_chat/tables.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/canonical/calendar_contacts_tables.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/canonical/canonical_store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/canonical/conversations_tables.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/canonical/journal_repair.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/canonical/mapping_store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/canonical/postgres.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/client.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/connection_tuning.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/activity_events_content_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/actor_role_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/affinity_pair_labels_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/attention_triage_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/attention_triage_v2.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/backup.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/backup_custody.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/calendar_events_scheduling_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/canonical_address_book_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/canonical_disclosure_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/canonical_nsfw_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/community_names_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/complexity_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/conflict_provenance_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/conversation_context_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/derivation_factory_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/derivation_ledger_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/derivation_provenance_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/derived_row_identity_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/documents_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/enrichment_record_progress_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/enrichment_spec_version_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/entity_affinity_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/entity_blackhole_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/entity_context_vectors_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/entity_context_vectors_v2.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/entity_edges_validity_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/entity_mentions_authored_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/entity_review_candidate_bar_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/entity_review_dedup_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/entity_review_provenance_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/episodes_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/extraction_artifacts.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/fact_dimension_by_entity_type_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/journal_entries_duration_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/journal_entries_ends_at_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/journal_entries_people_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/journal_entries_place_name_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/journal_entries_starts_at_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/journal_origin_dimension_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/mention_table_stamp_backfill_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/message_emotions_role_backfill_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/message_emotions_role_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/net_subject_policy_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/pack_registry_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/query_artifacts_duration_ms_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/registry.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/registry_checksums.json +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/remediation_person_model.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/retire_url_classification_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/scope_source_generation.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/signal_dimension_backfill_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/signal_dimension_harness.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/signal_objects.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/signal_objects_period_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/signal_objects_updated_by_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/signal_summaries_drop_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/stage9_column_renames.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/vector_storage_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/vector_storage_v2.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/vector_storage_v3.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/vector_storage_v4.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/wiki_clusters_v2.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/wiki_entities_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/wiki_entity_review_v2.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/wiki_facts_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/wiki_lifecycle_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/wiki_mvp_phase0.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/wiki_mvp_phase1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/wiki_mvp_phase4_messages_cutover.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/wiki_mvp_phase5_topic_clusters.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/wiki_mvp_phase6_dimension_briefs.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/wiki_mvp_query_quality.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/wiki_mvp_topic_clusters_coordination.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/wiki_stats_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/migrations/wiki_timeline_v1.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/paths.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/postgres.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/schema.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/schema_probe.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/storage_breakdown.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/db/write_gate.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/derived_row_identity.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/enrichment/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/enrichment/canonical_enrichment_store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/enrichment/raw_enrichment_store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/normalized/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/normalized/normalized_store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/oplog/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/oplog/decision.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/oplog/oplog_store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/oplog/postgres.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/person/identity_resolver.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/projections/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/projections/index_ops_store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/projections/vector_index_store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/raw/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/raw/browser_flat_tables.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/raw/file_store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/raw/raw_store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/raw/raw_tables_manager.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/raw/sqlite_raw_store.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/security/encryption.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/signal_identity.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/source_settings.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/storage/user_identity.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/sync/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/sync/client.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/sync_handlers.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/testing/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/testing/lifespan.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/uds.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/uma_contact_enrichment.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/uma_filters.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/uma_resource_id.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/uma_rpt.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/upgrades/__init__.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/upgrades/runner.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/utils/base_object.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos/websocket_client.py +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos_node.egg-info/dependency_links.txt +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos_node.egg-info/entry_points.txt +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos_node.egg-info/requires.txt +0 -0
- {topos_node-1.3.37 → topos_node-1.3.39}/topos_node.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: topos-node
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.39
|
|
4
4
|
Summary: Topos personal AI engine (FastAPI): local data, sync, control plane WebSocket client
|
|
5
5
|
License-Expression: Apache-2.0
|
|
6
6
|
Project-URL: Homepage, https://topos.dialogues.ai
|
|
@@ -163,13 +163,13 @@ Optional:
|
|
|
163
163
|
### 3) Run
|
|
164
164
|
|
|
165
165
|
```bash
|
|
166
|
-
topos-node --host 0.0.0.0 --port
|
|
166
|
+
topos-node --host 0.0.0.0 --port 8676
|
|
167
167
|
```
|
|
168
168
|
|
|
169
169
|
### 4) Verify
|
|
170
170
|
|
|
171
171
|
```bash
|
|
172
|
-
curl http://localhost:
|
|
172
|
+
curl http://localhost:8676/health
|
|
173
173
|
```
|
|
174
174
|
|
|
175
175
|
## Common Commands
|
|
@@ -96,13 +96,13 @@ Optional:
|
|
|
96
96
|
### 3) Run
|
|
97
97
|
|
|
98
98
|
```bash
|
|
99
|
-
topos-node --host 0.0.0.0 --port
|
|
99
|
+
topos-node --host 0.0.0.0 --port 8676
|
|
100
100
|
```
|
|
101
101
|
|
|
102
102
|
### 4) Verify
|
|
103
103
|
|
|
104
104
|
```bash
|
|
105
|
-
curl http://localhost:
|
|
105
|
+
curl http://localhost:8676/health
|
|
106
106
|
```
|
|
107
107
|
|
|
108
108
|
## Common Commands
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "topos-node"
|
|
7
|
-
version = "1.3.
|
|
7
|
+
version = "1.3.39"
|
|
8
8
|
description = "Topos personal AI engine (FastAPI): local data, sync, control plane WebSocket client"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
@@ -112,7 +112,7 @@ tmp_path_retention_count = 1
|
|
|
112
112
|
tmp_path_retention_policy = "failed"
|
|
113
113
|
# The DEFAULT lane is hermetic. Without this, a plain `pytest tests/` selects
|
|
114
114
|
# every marker, and the three lanes below are the ones that read and WRITE the
|
|
115
|
-
# developer's own ~/.topos/database.db or drive the node running on :
|
|
115
|
+
# developer's own ~/.topos/database.db or drive the node running on :8676 —
|
|
116
116
|
# `tests/conftest.py::_no_live_db_guard` waives its protection for exactly these
|
|
117
117
|
# markers, which only makes sense if the ordinary gate never selects them.
|
|
118
118
|
# On 2026-08-19 it did: one `pytest tests/ -q` run inserted 71 rows into the
|
|
@@ -137,7 +137,7 @@ markers = [
|
|
|
137
137
|
"public: public-safe test lane for OSS CI",
|
|
138
138
|
"private: internal architecture or fixtures; excluded from public CI",
|
|
139
139
|
"e2e: end-to-end tests (live Keycloak + Control Plane; require config and running CP)",
|
|
140
|
-
"live: requires a running local engine (localhost:
|
|
140
|
+
"live: requires a running local engine (localhost:8676) and a real TOPOS_KEY; excluded from deterministic lanes",
|
|
141
141
|
"release_pressure: iteration-4 live pressure smoke; run explicitly before releases",
|
|
142
142
|
"p0: priority marker on release pressure tests",
|
|
143
143
|
"retrieval_eval: dense-intelligence retrieval eval (loads local embedding model; run explicitly)",
|
|
@@ -20,6 +20,7 @@ from pathlib import Path
|
|
|
20
20
|
|
|
21
21
|
import pytest
|
|
22
22
|
|
|
23
|
+
from topos.defaults import DEFAULT_NODE_PORT
|
|
23
24
|
from topos.storage.db import paths
|
|
24
25
|
|
|
25
26
|
pytestmark = [pytest.mark.public]
|
|
@@ -381,7 +382,7 @@ class TestSwitchPreflight:
|
|
|
381
382
|
def _no_running_node(self, monkeypatch):
|
|
382
383
|
from topos import profiles
|
|
383
384
|
|
|
384
|
-
monkeypatch.setattr(profiles, "node_is_running", lambda port=
|
|
385
|
+
monkeypatch.setattr(profiles, "node_is_running", lambda port=DEFAULT_NODE_PORT: False)
|
|
385
386
|
|
|
386
387
|
def test_refuses_a_topos_from_a_newer_engine(self, tmp_path):
|
|
387
388
|
from topos import profiles
|
|
@@ -22,6 +22,7 @@ from pathlib import Path
|
|
|
22
22
|
import pytest
|
|
23
23
|
|
|
24
24
|
from topos import profiles
|
|
25
|
+
from topos.defaults import DEFAULT_NODE_PORT
|
|
25
26
|
from topos.storage.db.migrations import backup as backup_mod
|
|
26
27
|
|
|
27
28
|
pytestmark = [pytest.mark.public]
|
|
@@ -70,7 +71,7 @@ def _seed_active(base: Path, *, key: str = "KEYAAA", real_db: bool = True) -> No
|
|
|
70
71
|
|
|
71
72
|
@pytest.fixture(autouse=True)
|
|
72
73
|
def _no_running_node(monkeypatch):
|
|
73
|
-
monkeypatch.setattr(profiles, "node_is_running", lambda port=
|
|
74
|
+
monkeypatch.setattr(profiles, "node_is_running", lambda port=DEFAULT_NODE_PORT: False)
|
|
74
75
|
|
|
75
76
|
|
|
76
77
|
class TestArchiveIsSelfContained:
|
|
@@ -17,6 +17,7 @@ from click.testing import CliRunner
|
|
|
17
17
|
|
|
18
18
|
from topos import profiles
|
|
19
19
|
from topos.cli.profile_cmd import profile_group
|
|
20
|
+
from topos.defaults import DEFAULT_NODE_PORT
|
|
20
21
|
|
|
21
22
|
pytestmark = [pytest.mark.public]
|
|
22
23
|
|
|
@@ -45,7 +46,7 @@ def _seed_profile(base: Path, slug: str, *, name: str | None = None, key: str =
|
|
|
45
46
|
|
|
46
47
|
@pytest.fixture(autouse=True)
|
|
47
48
|
def _no_running_node(monkeypatch):
|
|
48
|
-
monkeypatch.setattr(profiles, "node_is_running", lambda port=
|
|
49
|
+
monkeypatch.setattr(profiles, "node_is_running", lambda port=DEFAULT_NODE_PORT: False)
|
|
49
50
|
|
|
50
51
|
|
|
51
52
|
class TestNewProfile:
|
|
@@ -128,7 +129,7 @@ class TestSwitchProfile:
|
|
|
128
129
|
def test_refuses_while_node_running(self, tmp_path, monkeypatch):
|
|
129
130
|
_seed_active(tmp_path)
|
|
130
131
|
_seed_profile(tmp_path, "work")
|
|
131
|
-
monkeypatch.setattr(profiles, "node_is_running", lambda port=
|
|
132
|
+
monkeypatch.setattr(profiles, "node_is_running", lambda port=DEFAULT_NODE_PORT: True)
|
|
132
133
|
with pytest.raises(profiles.ProfileError, match="running"):
|
|
133
134
|
profiles.switch_profile("work", tmp_path)
|
|
134
135
|
# Nothing moved.
|
|
@@ -328,7 +329,7 @@ class TestRemoveProfile:
|
|
|
328
329
|
def test_does_not_require_the_node_to_be_stopped(self, tmp_path, monkeypatch):
|
|
329
330
|
# An archived Topos is not the one a running engine has open, so unlike
|
|
330
331
|
# new/switch this must work without asking anyone to quit Topos.
|
|
331
|
-
monkeypatch.setattr(profiles, "node_is_running", lambda port=
|
|
332
|
+
monkeypatch.setattr(profiles, "node_is_running", lambda port=DEFAULT_NODE_PORT: True)
|
|
332
333
|
_seed_profile(tmp_path, "work")
|
|
333
334
|
|
|
334
335
|
profiles.remove_profile("work", tmp_path)
|
|
@@ -682,28 +682,37 @@ async def blackhole_entity(
|
|
|
682
682
|
"""
|
|
683
683
|
import asyncio
|
|
684
684
|
|
|
685
|
+
from ..core.state import close_thread_db_connection
|
|
685
686
|
from ..features.lifecycle.blackhole import BlackholeStore
|
|
686
687
|
from ..features.lifecycle.blackhole_rebuild import rebuild_for_blackhole
|
|
687
688
|
|
|
688
|
-
|
|
689
|
+
_entities_conn() # fail fast with 503 before spawning the worker
|
|
690
|
+
processing_tier = body.processing_tier
|
|
691
|
+
note = body.note
|
|
692
|
+
|
|
693
|
+
def _blackhole():
|
|
694
|
+
try:
|
|
695
|
+
conn = _entities_conn()
|
|
696
|
+
result = BlackholeStore(conn).blackhole_entity(
|
|
697
|
+
entity_ref=entity_id,
|
|
698
|
+
processing_tier=processing_tier,
|
|
699
|
+
note=note,
|
|
700
|
+
)
|
|
701
|
+
# D4: the notification above was raised first, so the owner already
|
|
702
|
+
# knows the hide is incomplete; now do the rebuild that makes it
|
|
703
|
+
# true. Same worker / same connection — do not hop back to the loop
|
|
704
|
+
# with a write-gate hold still possible.
|
|
705
|
+
if not result.get("already_blackholed"):
|
|
706
|
+
result["rebuild"] = rebuild_for_blackhole(conn, entity_id).as_dict()
|
|
707
|
+
return result
|
|
708
|
+
finally:
|
|
709
|
+
close_thread_db_connection()
|
|
710
|
+
|
|
689
711
|
try:
|
|
690
|
-
|
|
691
|
-
entity_ref=entity_id,
|
|
692
|
-
processing_tier=body.processing_tier,
|
|
693
|
-
note=body.note,
|
|
694
|
-
)
|
|
712
|
+
return await asyncio.to_thread(_blackhole)
|
|
695
713
|
except ValueError as exc:
|
|
696
714
|
raise HTTPException(status_code=400, detail=str(exc))
|
|
697
715
|
|
|
698
|
-
# D4: the notification above was raised first, so the owner already knows the
|
|
699
|
-
# hide is incomplete; now do the rebuild that makes it true. Non-owners are
|
|
700
|
-
# withheld the prose artifacts for the duration, so this running late is safe
|
|
701
|
-
# while it running silently would not be.
|
|
702
|
-
if not result.get("already_blackholed"):
|
|
703
|
-
result["rebuild"] = await asyncio.to_thread(rebuild_for_blackhole, conn, entity_id)
|
|
704
|
-
result["rebuild"] = result["rebuild"].as_dict()
|
|
705
|
-
return result
|
|
706
|
-
|
|
707
716
|
|
|
708
717
|
@router.delete("/entities/{entity_id}/blackhole")
|
|
709
718
|
async def unblackhole_entity(
|
|
@@ -711,9 +720,20 @@ async def unblackhole_entity(
|
|
|
711
720
|
_api_key: str = Depends(require_api_key),
|
|
712
721
|
):
|
|
713
722
|
"""Lift a black hole. Existing grants are not restored — normal permissions resume."""
|
|
723
|
+
import asyncio
|
|
724
|
+
|
|
725
|
+
from ..core.state import close_thread_db_connection
|
|
714
726
|
from ..features.lifecycle.blackhole import BlackholeStore
|
|
715
727
|
|
|
716
|
-
|
|
728
|
+
_entities_conn() # fail fast with 503 before spawning the worker
|
|
729
|
+
|
|
730
|
+
def _unblackhole():
|
|
731
|
+
try:
|
|
732
|
+
return BlackholeStore(_entities_conn()).unblackhole_entity(entity_ref=entity_id)
|
|
733
|
+
finally:
|
|
734
|
+
close_thread_db_connection()
|
|
735
|
+
|
|
736
|
+
return await asyncio.to_thread(_unblackhole)
|
|
717
737
|
|
|
718
738
|
|
|
719
739
|
@router.get("/blackholes")
|
|
@@ -12,6 +12,7 @@ import uvicorn
|
|
|
12
12
|
# Add parent directory to path for imports
|
|
13
13
|
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
|
|
14
14
|
|
|
15
|
+
from topos.defaults import DEFAULT_NODE_PORT
|
|
15
16
|
from topos.runtime_update import (
|
|
16
17
|
DEFAULT_PACKAGE_NAME,
|
|
17
18
|
apply_package_update,
|
|
@@ -232,8 +233,8 @@ def _maybe_offer_self_update(
|
|
|
232
233
|
)
|
|
233
234
|
@click.option(
|
|
234
235
|
"--port",
|
|
235
|
-
default=
|
|
236
|
-
help="Server port (default:
|
|
236
|
+
default=DEFAULT_NODE_PORT,
|
|
237
|
+
help=f"Server port (default: {DEFAULT_NODE_PORT})",
|
|
237
238
|
)
|
|
238
239
|
@click.option(
|
|
239
240
|
"--host",
|
|
@@ -17,6 +17,7 @@ from typing import Optional
|
|
|
17
17
|
import click
|
|
18
18
|
|
|
19
19
|
from topos import profiles
|
|
20
|
+
from topos.defaults import DEFAULT_NODE_PORT
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
def _echo(payload: dict, as_json: bool, human: str) -> None:
|
|
@@ -41,7 +42,7 @@ _BASE_OPTION = click.option(
|
|
|
41
42
|
)
|
|
42
43
|
_JSON_OPTION = click.option("--json", "as_json", is_flag=True, help="Machine-readable output.")
|
|
43
44
|
_PORT_OPTION = click.option(
|
|
44
|
-
"--port", default=
|
|
45
|
+
"--port", default=DEFAULT_NODE_PORT, show_default=True, help="Port probed for a running node."
|
|
45
46
|
)
|
|
46
47
|
|
|
47
48
|
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
Port of the original open-source topos-cli ``menu_bar_app`` (pystray + PIL):
|
|
4
4
|
the Topos glyph with a status dot composited in the corner — yellow while
|
|
5
|
-
starting, green while the node answers ``/healthcheck``, red
|
|
6
|
-
|
|
5
|
+
starting, green while the node answers ``/healthcheck``, red only after
|
|
6
|
+
repeated misses (a single late probe is a busy node, not a dead one),
|
|
7
|
+
orange when a newer topos-node is published on PyPI. The menu offers
|
|
7
8
|
API docs, the hosted Topos app, a one-click update when one is available,
|
|
8
9
|
and Quit.
|
|
9
10
|
|
|
@@ -33,10 +34,36 @@ STATUS_COLORS = {
|
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
HEALTH_POLL_SECONDS = 5.0
|
|
37
|
+
#: Must sit above ``probe_db_health``'s 2s budget. A 3s client deadline raced
|
|
38
|
+
#: the probe under ingest load and painted the tray red for a live node.
|
|
39
|
+
HEALTH_TIMEOUT_SECONDS = 10.0
|
|
40
|
+
#: One missed probe is a stalled event loop, not a down node. Two in a row
|
|
41
|
+
#: is enough to go red; a single success clears the count (same shape as
|
|
42
|
+
#: the web app's ``HEALTH_FAILURE_THRESHOLD``).
|
|
43
|
+
HEALTH_FAILURE_THRESHOLD = 2
|
|
36
44
|
TOPOS_APP_URL = "https://topos.dialogues.ai"
|
|
37
45
|
TOPOS_DOCS_URL = "https://topos.dialogues.ai/docs/welcome"
|
|
38
46
|
|
|
39
47
|
|
|
48
|
+
def resolve_tray_health_status(
|
|
49
|
+
*,
|
|
50
|
+
probe_ok: bool,
|
|
51
|
+
consecutive_failures: int,
|
|
52
|
+
current_status: str,
|
|
53
|
+
failure_threshold: int = HEALTH_FAILURE_THRESHOLD,
|
|
54
|
+
) -> tuple[str, int]:
|
|
55
|
+
"""Map one ``/healthcheck`` result to (next_status, next_failure_count).
|
|
56
|
+
|
|
57
|
+
A single timeout must not flip a green (or still-starting) icon to red.
|
|
58
|
+
"""
|
|
59
|
+
if probe_ok:
|
|
60
|
+
return "healthy", 0
|
|
61
|
+
failures = consecutive_failures + 1
|
|
62
|
+
if failures >= failure_threshold:
|
|
63
|
+
return "down", failures
|
|
64
|
+
return current_status, failures
|
|
65
|
+
|
|
66
|
+
|
|
40
67
|
def tray_available() -> bool:
|
|
41
68
|
try:
|
|
42
69
|
import pystray # noqa: F401
|
|
@@ -214,16 +241,24 @@ class ToposTray:
|
|
|
214
241
|
def _poll_health(self) -> None:
|
|
215
242
|
import httpx
|
|
216
243
|
|
|
244
|
+
consecutive_failures = 0
|
|
217
245
|
while self._icon is not None and self._icon.visible:
|
|
218
246
|
try:
|
|
219
247
|
# 401/403 = health auth enabled; the node answered, so it's up.
|
|
220
|
-
healthy = httpx.get(
|
|
248
|
+
healthy = httpx.get(
|
|
249
|
+
self.health_url, timeout=HEALTH_TIMEOUT_SECONDS
|
|
250
|
+
).status_code in (200, 401, 403)
|
|
221
251
|
except Exception:
|
|
222
252
|
healthy = False
|
|
223
253
|
if healthy:
|
|
224
254
|
self._fetch_shell_status()
|
|
225
255
|
self._maybe_fetch_topos_name()
|
|
226
|
-
|
|
256
|
+
next_status, consecutive_failures = resolve_tray_health_status(
|
|
257
|
+
probe_ok=healthy,
|
|
258
|
+
consecutive_failures=consecutive_failures,
|
|
259
|
+
current_status=self.status,
|
|
260
|
+
)
|
|
261
|
+
self._set_status(next_status)
|
|
227
262
|
time.sleep(HEALTH_POLL_SECONDS)
|
|
228
263
|
|
|
229
264
|
def _fetch_shell_status(self) -> None:
|
|
@@ -408,10 +408,13 @@ async def handle_start_ingestion(message: Dict[str, Any]) -> Optional[Dict[str,
|
|
|
408
408
|
"payload": {"job_id": job_id, "status": "completed", "deduplicated": True},
|
|
409
409
|
}
|
|
410
410
|
|
|
411
|
+
# Import-time policy chosen in the UI (date window, inclusion flags).
|
|
412
|
+
ingest_options = payload.get("ingest_options")
|
|
411
413
|
job_payload: Dict[str, Any] = {
|
|
412
414
|
"dataset_id": dataset_id or "",
|
|
413
415
|
"schema_id": schema_id,
|
|
414
416
|
"file_format": file_format,
|
|
417
|
+
"ingest_options": ingest_options if isinstance(ingest_options, dict) else None,
|
|
415
418
|
"job_id": job_id,
|
|
416
419
|
"source_id": source_id,
|
|
417
420
|
"source_definition": source_definition,
|
|
@@ -1031,7 +1031,10 @@ async def handle_signal_unblackhole_entity(message: Dict[str, Any]) -> Optional[
|
|
|
1031
1031
|
try:
|
|
1032
1032
|
from ...features.lifecycle.blackhole import BlackholeStore
|
|
1033
1033
|
|
|
1034
|
-
|
|
1034
|
+
def _unblackhole(conn):
|
|
1035
|
+
return BlackholeStore(conn).unblackhole_entity(entity_ref=entity_id)
|
|
1036
|
+
|
|
1037
|
+
result = await run_db_write(_unblackhole)
|
|
1035
1038
|
return {"id": req_id, "status": "ok", "payload": result}
|
|
1036
1039
|
except Exception as exc: # noqa: BLE001
|
|
1037
1040
|
return {"id": req_id, "status": "error", "error": str(exc)}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""Stable defaults for a local Topos node.
|
|
2
|
+
|
|
3
|
+
8676 is TOPO on a phone keypad. Keep this the only Python source of the
|
|
4
|
+
listen port so CLI, probes, and the local MCP proxy cannot drift.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
DEFAULT_NODE_PORT = 8676
|
|
8
|
+
DEFAULT_NODE_HTTP_URL = f"http://127.0.0.1:{DEFAULT_NODE_PORT}"
|
|
9
|
+
DEFAULT_NODE_LOCALHOST_URL = f"http://localhost:{DEFAULT_NODE_PORT}"
|
|
@@ -266,7 +266,9 @@ class EntitiesJob(BaseEnrichmentJob):
|
|
|
266
266
|
resolver.record_mention(
|
|
267
267
|
entity_id,
|
|
268
268
|
record_id=record_id,
|
|
269
|
-
|
|
269
|
+
# A declared row may resolve on one string and be evidenced by
|
|
270
|
+
# another: a cited host is the node, the full URL is the proof.
|
|
271
|
+
surface_text=str(rec.get("surface_detail") or surface),
|
|
270
272
|
source_id=rec.get("source_id"),
|
|
271
273
|
canonical_table=rec.get("canonical_table"),
|
|
272
274
|
confidence=confidence,
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"""Declared entity minting for ChatGPT turns (PLAN_CHATGPT_IMPORT.md Sprint 4).
|
|
2
|
+
|
|
3
|
+
A ChatGPT turn carries more than its text. The export declares, per message,
|
|
4
|
+
which pages were cited, which searches were run, which canvas document was being
|
|
5
|
+
written and which files were attached — and the reader already lifts all of it
|
|
6
|
+
onto ``ai_chat_messages.metadata_json``. Until now none of it became a node, so
|
|
7
|
+
the graph could not answer "what sources inform me" even though the answer was
|
|
8
|
+
sitting in a column.
|
|
9
|
+
|
|
10
|
+
This is the same class the 1.3.36 density pass ranked strongest: read from a
|
|
11
|
+
structured column, no model, no confidence to discount.
|
|
12
|
+
|
|
13
|
+
Three judgements are encoded here, and each one is a decision not a detail:
|
|
14
|
+
|
|
15
|
+
**Hosts, not URLs.** 1,359 distinct URLs would mint 1,359 leaf nodes that
|
|
16
|
+
connect to nothing and say nothing. The *host* is the source — ``docs.python.org``
|
|
17
|
+
is a thing you read repeatedly — so hosts are minted and the full URL is kept as
|
|
18
|
+
the mention's surface text. Subdomains stay distinct: reading Google Cloud's
|
|
19
|
+
docs is not reading google.com.
|
|
20
|
+
|
|
21
|
+
**Search queries are not minted.** They are declared, and they are read — they
|
|
22
|
+
ride on the exposure edge and on the mention that the search produced — but a
|
|
23
|
+
sentence is not an entity. Minting "Google Cloud roles/compute.instanceAdmin.v1
|
|
24
|
+
permissions create start stop delete VM instances" as a node would add a row, not
|
|
25
|
+
density. The entities *inside* a query reach the graph through the citations the
|
|
26
|
+
query returned.
|
|
27
|
+
|
|
28
|
+
**Attachments must be named by a human.** A ChatGPT export names half its
|
|
29
|
+
attachments with a UUID. ``proposal-v3.pdf`` is a document; ``bb2b7a54-d935-4ac1
|
|
30
|
+
-82d2-af0ff5df204c.png`` is a filename the system made up, and minting it would
|
|
31
|
+
put a hash in the graph.
|
|
32
|
+
|
|
33
|
+
Pure stdlib. The registry in ``declared_mappings`` dispatches to this.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
from __future__ import annotations
|
|
37
|
+
|
|
38
|
+
import json
|
|
39
|
+
import re
|
|
40
|
+
from typing import Any, Dict, Iterable, List, Optional
|
|
41
|
+
from urllib.parse import urlsplit
|
|
42
|
+
|
|
43
|
+
# Spine entity types minted here. Both are new to the vocabulary in
|
|
44
|
+
# ``resolver._NER_TYPE_MAP``; declared rows keep their type verbatim, so no
|
|
45
|
+
# mapping is needed, but a UI that switches on entity_type should learn them.
|
|
46
|
+
TYPE_WEB_SOURCE = "web_source"
|
|
47
|
+
TYPE_DOCUMENT = "document"
|
|
48
|
+
|
|
49
|
+
# Owner edges. Exposure is not authorship: a page the assistant fetched and
|
|
50
|
+
# showed is something the owner was exposed to, and the provenance layer must
|
|
51
|
+
# never read it as something they said.
|
|
52
|
+
EDGE_EXPOSED_TO = "exposed_to"
|
|
53
|
+
EDGE_AUTHORED = "authored"
|
|
54
|
+
|
|
55
|
+
# Hosts that identify no source: loopback, bare addresses, and the redirectors
|
|
56
|
+
# a search tool leaves behind.
|
|
57
|
+
_HOST_DENYLIST = frozenset({"localhost", "127.0.0.1", "0.0.0.0", "example.com"})
|
|
58
|
+
_IPV4 = re.compile(r"^\d{1,3}(\.\d{1,3}){3}$")
|
|
59
|
+
|
|
60
|
+
# A filename a person chose, versus one a system generated.
|
|
61
|
+
_UUID_NAME = re.compile(r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$", re.IGNORECASE)
|
|
62
|
+
_HEX_NAME = re.compile(r"^[0-9a-f]{16,}$", re.IGNORECASE)
|
|
63
|
+
_MIN_DOCUMENT_NAME = 3
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def host_of(url: str) -> str:
|
|
67
|
+
"""The source a URL names: hostname, lowercased, without ``www.``.
|
|
68
|
+
|
|
69
|
+
Returns "" for anything that does not identify a readable source.
|
|
70
|
+
"""
|
|
71
|
+
text = str(url or "").strip()
|
|
72
|
+
if not text:
|
|
73
|
+
return ""
|
|
74
|
+
if "//" not in text:
|
|
75
|
+
text = "//" + text
|
|
76
|
+
try:
|
|
77
|
+
host = (urlsplit(text).hostname or "").lower()
|
|
78
|
+
except ValueError:
|
|
79
|
+
return ""
|
|
80
|
+
host = host.removeprefix("www.")
|
|
81
|
+
if not host or "." not in host or host in _HOST_DENYLIST or _IPV4.match(host):
|
|
82
|
+
return ""
|
|
83
|
+
return host
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def is_named_by_a_human(filename: str) -> bool:
|
|
87
|
+
"""Did a person choose this filename, or did a machine?"""
|
|
88
|
+
name = str(filename or "").strip()
|
|
89
|
+
if len(name) < _MIN_DOCUMENT_NAME:
|
|
90
|
+
return False
|
|
91
|
+
stem = name.rsplit(".", 1)[0] if "." in name else name
|
|
92
|
+
if _UUID_NAME.match(stem) or _HEX_NAME.match(stem):
|
|
93
|
+
return False
|
|
94
|
+
# "file_00000000abc" and friends: no letters a person would have typed.
|
|
95
|
+
return bool(re.search(r"[A-Za-z]{3,}", stem))
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _metadata(record: Dict[str, Any]) -> Dict[str, Any]:
|
|
99
|
+
"""``metadata_json`` arrives as a dict at map time and a string from SQL."""
|
|
100
|
+
value = record.get("metadata_json")
|
|
101
|
+
if value is None:
|
|
102
|
+
value = record.get("metadata")
|
|
103
|
+
if isinstance(value, str):
|
|
104
|
+
try:
|
|
105
|
+
value = json.loads(value)
|
|
106
|
+
except (TypeError, ValueError):
|
|
107
|
+
return {}
|
|
108
|
+
return value if isinstance(value, dict) else {}
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _row(
|
|
112
|
+
surface: str,
|
|
113
|
+
entity_type: str,
|
|
114
|
+
*,
|
|
115
|
+
record: Dict[str, Any],
|
|
116
|
+
record_id: str,
|
|
117
|
+
event_at: Optional[str],
|
|
118
|
+
self_edge: Optional[str] = None,
|
|
119
|
+
surface_detail: Optional[str] = None,
|
|
120
|
+
) -> Dict[str, Any]:
|
|
121
|
+
row: Dict[str, Any] = {
|
|
122
|
+
"message_id": record_id,
|
|
123
|
+
"record_id": record_id,
|
|
124
|
+
"source_id": record.get("source_id"),
|
|
125
|
+
"event_at": event_at,
|
|
126
|
+
"canonical_table": record.get("_table") or record.get("canonical_table") or "ai_chat_messages",
|
|
127
|
+
"entity_text": surface,
|
|
128
|
+
"entity_type": entity_type,
|
|
129
|
+
"confidence": 1.0,
|
|
130
|
+
"provider": "declared",
|
|
131
|
+
"model": None,
|
|
132
|
+
}
|
|
133
|
+
if self_edge:
|
|
134
|
+
row["self_edge"] = self_edge
|
|
135
|
+
if surface_detail:
|
|
136
|
+
# What the graph shows is the host; what the evidence says is the URL.
|
|
137
|
+
row["surface_detail"] = surface_detail
|
|
138
|
+
return row
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def _citation_urls(metadata: Dict[str, Any]) -> List[str]:
|
|
142
|
+
urls: List[str] = []
|
|
143
|
+
for citation in metadata.get("citation_urls") or []:
|
|
144
|
+
if isinstance(citation, str) and citation.strip():
|
|
145
|
+
urls.append(citation.strip())
|
|
146
|
+
return urls
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _canvas_title(metadata: Dict[str, Any]) -> str:
|
|
150
|
+
canvas = metadata.get("canvas")
|
|
151
|
+
if not isinstance(canvas, dict):
|
|
152
|
+
return ""
|
|
153
|
+
title = canvas.get("title")
|
|
154
|
+
if isinstance(title, str) and title.strip():
|
|
155
|
+
return title.strip()
|
|
156
|
+
return ""
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def _attachment_names(metadata: Dict[str, Any]) -> Iterable[str]:
|
|
160
|
+
for item in metadata.get("attachments") or []:
|
|
161
|
+
if isinstance(item, dict):
|
|
162
|
+
name = item.get("name")
|
|
163
|
+
if isinstance(name, str) and is_named_by_a_human(name):
|
|
164
|
+
yield name.strip()
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def declared_rows(
|
|
168
|
+
record: Dict[str, Any],
|
|
169
|
+
*,
|
|
170
|
+
record_id: str,
|
|
171
|
+
event_at: Optional[str] = None,
|
|
172
|
+
) -> List[Dict[str, Any]]:
|
|
173
|
+
"""NER-result-shaped rows minted from one turn's declared metadata.
|
|
174
|
+
|
|
175
|
+
Shape matches ``declared_mappings.extract_declared_entities`` exactly, so the
|
|
176
|
+
entities job resolves these through the same declared path — at declared
|
|
177
|
+
confidence, with the type kept verbatim.
|
|
178
|
+
"""
|
|
179
|
+
if not record_id:
|
|
180
|
+
return []
|
|
181
|
+
metadata = _metadata(record)
|
|
182
|
+
if not metadata:
|
|
183
|
+
return []
|
|
184
|
+
|
|
185
|
+
rows: List[Dict[str, Any]] = []
|
|
186
|
+
seen: set = set()
|
|
187
|
+
|
|
188
|
+
# Which search produced this message's citations, if any. Carried on the
|
|
189
|
+
# mention rather than minted: it is evidence, not an entity.
|
|
190
|
+
queries = [q for q in (metadata.get("search_queries") or []) if isinstance(q, str) and q.strip()]
|
|
191
|
+
query_note = queries[0].strip() if queries else ""
|
|
192
|
+
|
|
193
|
+
for url in _citation_urls(metadata):
|
|
194
|
+
host = host_of(url)
|
|
195
|
+
if not host:
|
|
196
|
+
continue
|
|
197
|
+
key = (host, TYPE_WEB_SOURCE)
|
|
198
|
+
if key in seen:
|
|
199
|
+
continue
|
|
200
|
+
seen.add(key)
|
|
201
|
+
detail = f"{url} — searched: {query_note}" if query_note else url
|
|
202
|
+
rows.append(_row(host, TYPE_WEB_SOURCE, record=record, record_id=record_id,
|
|
203
|
+
event_at=event_at, self_edge=EDGE_EXPOSED_TO, surface_detail=detail))
|
|
204
|
+
|
|
205
|
+
canvas = _canvas_title(metadata)
|
|
206
|
+
if canvas:
|
|
207
|
+
key = (canvas.lower(), TYPE_DOCUMENT)
|
|
208
|
+
if key not in seen:
|
|
209
|
+
seen.add(key)
|
|
210
|
+
rows.append(_row(canvas, TYPE_DOCUMENT, record=record, record_id=record_id,
|
|
211
|
+
event_at=event_at, self_edge=EDGE_AUTHORED))
|
|
212
|
+
|
|
213
|
+
for name in _attachment_names(metadata):
|
|
214
|
+
key = (name.lower(), TYPE_DOCUMENT)
|
|
215
|
+
if key in seen:
|
|
216
|
+
continue
|
|
217
|
+
seen.add(key)
|
|
218
|
+
rows.append(_row(name, TYPE_DOCUMENT, record=record, record_id=record_id,
|
|
219
|
+
event_at=event_at, self_edge=EDGE_AUTHORED))
|
|
220
|
+
|
|
221
|
+
return rows
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def coverage(records: Iterable[Dict[str, Any]]) -> Dict[str, int]:
|
|
225
|
+
"""What this lane would mint over a batch — the Sprint 4 measurement."""
|
|
226
|
+
hosts: set = set()
|
|
227
|
+
documents: set = set()
|
|
228
|
+
urls = 0
|
|
229
|
+
queries = 0
|
|
230
|
+
skipped_machine_names = 0
|
|
231
|
+
for record in records:
|
|
232
|
+
metadata = _metadata(record)
|
|
233
|
+
if not metadata:
|
|
234
|
+
continue
|
|
235
|
+
for url in _citation_urls(metadata):
|
|
236
|
+
urls += 1
|
|
237
|
+
host = host_of(url)
|
|
238
|
+
if host:
|
|
239
|
+
hosts.add(host)
|
|
240
|
+
queries += len([q for q in (metadata.get("search_queries") or []) if isinstance(q, str) and q.strip()])
|
|
241
|
+
title = _canvas_title(metadata)
|
|
242
|
+
if title:
|
|
243
|
+
documents.add(title.lower())
|
|
244
|
+
for item in metadata.get("attachments") or []:
|
|
245
|
+
if isinstance(item, dict) and isinstance(item.get("name"), str):
|
|
246
|
+
if is_named_by_a_human(item["name"]):
|
|
247
|
+
documents.add(item["name"].strip().lower())
|
|
248
|
+
else:
|
|
249
|
+
skipped_machine_names += 1
|
|
250
|
+
return {
|
|
251
|
+
"citation_urls": urls,
|
|
252
|
+
"web_sources": len(hosts),
|
|
253
|
+
"documents": len(documents),
|
|
254
|
+
"search_queries_read": queries,
|
|
255
|
+
"attachments_skipped_machine_named": skipped_machine_names,
|
|
256
|
+
}
|