topos-node 1.3.36__tar.gz → 1.3.38__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.36/topos_node.egg-info → topos_node-1.3.38}/PKG-INFO +1 -1
- {topos_node-1.3.36 → topos_node-1.3.38}/pyproject.toml +1 -1
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/__version__.py +2 -2
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/ingestion_sources.py +18 -6
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/signal.py +36 -16
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/cli/tray.py +39 -4
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/signal_features.py +4 -1
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/sources.py +12 -5
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/backends/ollama.py +9 -0
- topos_node-1.3.38/topos/engine/ollama_runtime.py +142 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/reads.py +123 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/local_sync.py +66 -23
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/sources/imessage_reader.py +96 -10
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/services/llm/openai.py +13 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/pipeline_jobs_v1.py +34 -1
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/source_settings.py +56 -22
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/upgrades/manifests.json +18 -0
- {topos_node-1.3.36 → topos_node-1.3.38/topos_node.egg-info}/PKG-INFO +1 -1
- {topos_node-1.3.36 → topos_node-1.3.38}/topos_node.egg-info/SOURCES.txt +1 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/LICENSE +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/MANIFEST.in +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/README.md +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/setup.cfg +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/shared/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/shared/filtering.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/shared/schema_registry.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/tests/test_active_database_binding.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/tests/test_active_ingestion_binding.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/tests/test_extensions.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/tests/test_gate_leg_hermeticity.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/tests/test_llm_integrations_storage.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/tests/test_local_gate_composition.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/tests/test_owner_database_hermeticity.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/tests/test_prewarm_first_run.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/tests/test_profile_hygiene.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/tests/test_profiles.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/tests/test_protocol_handled_types.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/tests/test_query_field_contract.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/tests/test_system_computer_name.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/analytics/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/analytics/dataset_resolution.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/analytics/duckdb_adapter.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/analytics/luck_surface.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/analytics/messenger_communities.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/analytics/messenger_directed.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/analytics/messenger_graph.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/analytics/messenger_labels.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/analytics/person_graph.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/analytics/person_overlay.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/analytics/profiles.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/analytics/query_engine.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/analytics/raw_queries.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/analytics/relationship_reads.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/analytics.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/app_registry.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/backup.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/community_naming_config.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/compute_remote.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/connected_apps.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/conversation_context.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/data_commit.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/data_explorer_table_prefs.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/database_explorer.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/db.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/device.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/disk_space_config.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/engine_run.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/enrichment.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/enrichment_lab.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/facts_llm_config.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/filter_lab.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/health.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/home_chat.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/ingestion_api.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/ingestion_compat.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/intelligence_lifecycle.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/llm.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/local_mcp.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/messenger_analytics.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/privacy_disclose.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/query_api.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/runtime_bootstrap.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/sanitization_ollama_config.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/shell.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/signal_extraction_config.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/source_install.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/source_scrub.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/sources.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/sources_overview.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/sync.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/tool_index.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/ui_config.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/uma_data.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/upgrades.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/usage.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/api/user_identity.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/app.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/auth.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/canonicalization/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/canonicalization/declared_field_map.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/canonicalization/mappers/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/canonicalization/mappers/base.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/canonicalization/mappers/browser_activity_mapper.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/canonicalization/mappers/chatgpt_mapper.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/canonicalization/mappers/demo_mappers.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/canonicalization/mappers/documents_mapper.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/canonicalization/mappers/github_activity_mapper.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/canonicalization/mappers/google_calendar_mapper.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/canonicalization/mappers/grok_mapper.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/canonicalization/mappers/messenger_mapper.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/canonicalization/models.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/canonicalization/resolver.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/cli/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/cli/__main__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/cli/assets/topos_blk_rounded.png +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/cli/assets/topos_white.png +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/cli/commands.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/cli/profile_cmd.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/cli/reprocess_cmd.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/cli/setup_models_cmd.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/config/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/config/conversation_context_llm.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/config/facts_llm.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/config/local_model_builds.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/config/model_packs.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/config/node_function_providers.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/config/sanitization_ollama.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/config/settings.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/config/signal_extraction.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/config/uvicorn_logging.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/contacts/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/contacts/identity.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/control_plane_client.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/api_models.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/connection_resilience.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/db_health.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/device_helpers.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/errors.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/events.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/common.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/complexity.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/config.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/contacts_import.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/database_explorer.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/derivation.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/device.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/enrichment.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/enrichment_lab.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/filter_lab.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/graph_query.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/home_chat.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/ingest.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/mcp_client_elevations.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/mcp_clients.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/messages.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/messenger_analytics.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/query.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/registry.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/routines.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/timeline_daily.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/tool_index.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/handlers/uma.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/logging.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/metrics.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/routine_access.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/startup_banner.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/state.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/table_layers.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/core/types.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/data_explorer_row_delete.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/data_explorer_table_prefs.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/data_explorer_tables.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/disclosure/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/disclosure/canonical_writer.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/disclosure/content_policy.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/disclosure/field_registry.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/disclosure/privacy_layer.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/disclosure/tier.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/backends/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/backends/base.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/backends/generative_prompts.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/backends/generative_response.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/backends/huggingface.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/backends/openai.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/backends/openai_compatible.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/backends/redpill.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/backends/stub.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/client.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/disk_space.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/engine.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/hosted_llm_wallet.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/intake.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/memory_utils.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/model_cache.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/model_manager.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/ollama_install.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/ollama_pull.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/ollama_setup_guidance.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/pipeline_memory.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/queue_manager.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/registration.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/result_formatter.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/router.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/scoped_token.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/tasks.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/torch_runtime.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/transport.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/usage_guard.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/usage_observation.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/engine/validator.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/catalog.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/derivation_recovery.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/derived_tables.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/job_readiness.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/job_writer.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/base.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/_batch_limits.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/_engine_runner.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/attention_triage_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/availability_scores_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/brief_fallback.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/complexity_snapshot_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/derivation_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/derived_object_embeddings_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/dimension_summary_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/embeddings_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/emo_27_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/entities_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/fact_extraction_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/goal_extraction_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/pii_redaction_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/relationship_edges_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/sentiment_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/statistics_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/timeline_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/topic_clusters_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/canonical/topics_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/raw/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/raw/attachments_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/raw/language_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/raw/time_normalization_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/jobs/raw/tool_calls_job.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/model_overrides.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/models/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/models/manager.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/models/mvp_defaults.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/models/registry.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/models/versioning.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/orchestrator.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/pipeline_activity.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/processor.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/progress_bar.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/record_progress.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/registry_contract.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/signal_derivation_config.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment/source_overrides.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment_lab/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment_lab/bundles.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment_lab/model_resolve.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment_lab/schema.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment_lab/service.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment_lab/store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/enrichment_lab/worker.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/evals/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/evals/enrichment_eval.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/extensions.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/complexity/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/complexity/canonical.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/complexity/engine.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/complexity/entropy.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/complexity/focus.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/complexity/graph_metrics.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/complexity/influence.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/complexity/projection.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/complexity/snapshots.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/complexity/store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/complexity/topic_merge.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/complexity/topics.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/complexity/topics_daily.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/complexity/volatility.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/_scales.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/admin.legal.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/aspirations.goals.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/behavior.habits.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/behavior.preferences.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/beliefs.civic.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/beliefs.spiritual.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/communication.style.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/community.membership.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/craft.tooling.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/expertise.knowledge.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/finances.economics.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/health.lifestyle.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/health.mental.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/health.physical.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/household.pets.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/identity.core.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/interests.taste.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/life.events.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/narrative.self.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/net.capability.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/obligations.commitments.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/personality.traits.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/places.mobility.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/possessions.assets.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/relationships.social.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/values.motivation.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/vocab/dispositions.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/vocab/expertise.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/vocab/habits.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/vocab/interests.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/vocab/preferences.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/vocab/stances.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/vocab/tools.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/vocab/values.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/bundled_packs/work.career.yaml +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/candidates.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/guard.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/kernels.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/net_subject_policy.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/packs.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/person_bridge.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/prefilter.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/registry.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/report_card.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/router.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/social_bench.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/social_kernels.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/surfaces.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/synthesize.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/template.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/verify.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/derivation/writer.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/affinity.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/affinity_owner.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/affinity_quality.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/community_names.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/community_naming.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/consolidation.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/context_vectors.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/cypher.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/declared_mappings.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/dossier.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/edges.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/fact_materializer.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/graph_enrichers.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/graph_refresh.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/graph_search.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/linking.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/maintenance.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/owner.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/rebuild_subprocess.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/resolver.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/entities/structured_fields.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/facts/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/facts/extract.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/facts/llm_extract.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/facts/reads.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/facts/store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/facts/verdicts.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/fit/evaluator.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/fit/opportunity_types.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/lifecycle/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/lifecycle/blackhole.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/lifecycle/blackhole_guard.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/lifecycle/blackhole_llm.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/lifecycle/blackhole_rebuild.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/lifecycle/derived_scrub.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/lifecycle/exclusions.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/lifecycle/gc.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/provenance/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/provenance/posture.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/provenance/roles.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/brief_canonical_loader.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/brief_ontology.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/brief_renderer.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/brief_schemas.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/chunking.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/cluster_labels.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/conversation_context.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/data_health.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/definitions/brief_ontologies.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/definitions/intentions.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/definitions/interests.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/definitions/memory.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/definitions/places.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/definitions/profile.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/definitions/relationships.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/definitions/resources.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/definitions/schema/dimension_definition.schema.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/definitions/time.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/definitions/wellbeing.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/definitions/work.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/derived_index.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/derived_spec.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/dimension_briefs.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/dimension_definition_loader.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/dimension_profiles.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/dimension_registry.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/embed_context.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/extraction/artifact_router.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/extraction/artifact_store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/extraction/rule_extractors.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/graph_sanitize.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/hybrid_search.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/incremental_clustering.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/model_recommendations.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/query_embed_cache.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/schemas.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/service.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/signal_object_store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/source_hydration.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/structured_signal.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/tool_index.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/topic_clustering.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/typed_stores/aggregates.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/typed_stores/commitments.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/typed_stores/rhythm.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/typed_stores/scope_materializer.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/vector_codec.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/vector_math.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/signal/vector_settings.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/stats/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/stats/definitions.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/stats/engine.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/stats/fold.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/stats/insights.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/timeline_projection.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/timeline_rollup.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/triage/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/triage/badges.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/triage/daily.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/triage/dashboard.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/triage/instruments.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/triage/intents.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/features/triage/readiness.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/filter_lab/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/filter_lab/bundles.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/filter_lab/schema.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/filter_lab/service.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/filter_lab/store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/filter_lab/worker.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/home_chat/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/home_chat/schema.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/home_chat/store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/hosted_pool_lease.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/canonical_pipeline.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/checkpoints/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/checkpoints/checkpoint_store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/checkpoints/sqlite_checkpoint_store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/inbox_crypto.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/inbox_drain.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/ingest_helpers.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/jobs.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/journal_location_fanout.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/journal_time_log_normalize.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/log_preview.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/manager.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/parser.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/parsers/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/parsers/base.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/parsers/browser_parser.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/parsers/calendar_parser.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/parsers/chatgpt_conversation_flattener.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/parsers/chatgpt_parser.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/parsers/demo_file_parsers.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/parsers/documents_parser.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/parsers/github_activity_parser.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/parsers/google_calendar_parser.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/parsers/grok_parser.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/parsers/messenger_parser.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/parsers/voxterm_parser.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/progress.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/reprocess.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/sources/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/sources/base.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/sources/calendar.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/sources/chatgpt.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/sources/contact_importers.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/sources/grok.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/sources/signal_export_parser.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/sources/signal_reader.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/state_machine.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/triggers/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/triggers/file_trigger.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/triggers/sqlite_trigger.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/usage_inbox_dedupe.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/validation/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/validation/base.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/validation/schema_registry.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/ingestion/validation/schema_validator.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/lineage/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/lineage/provenance.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/lineage/tracker.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/llm_integrations_storage.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/mcp_clients.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/mcp_stdio_proxy.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/observability/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/observability/alerts.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/observability/metrics.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/observability/tracing.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/openai_client.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/owner_key.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/pipeline/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/pipeline/audit.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/pipeline/envelope.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/pipeline/job_runner.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/pipeline/job_store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/pipeline/stages.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/pipeline/stub_enqueue.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/principal.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/profiles.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/projections/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/projections/vector_index/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/projections/vector_index/base.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/projections/vector_index/builders.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/projections/vector_index/health_checks.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/protocol/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/protocol/handled_message_types.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/protocol/narrowing_vocabulary.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/protocol/query_field_contract.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/audit.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/closeness.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/cohort_resolvers.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/collaborators.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/ddr.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/disclosure.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/entity_window.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/exclusion.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/facts_direct.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/fingerprint.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/game_layer.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/grant_cache.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/inference.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/intent.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/manifest.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/manifest_validation.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/minimizer.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/narrowing.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/negotiation.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/packet_resolution.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/pipeline.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/planner.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/retrieval.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/runtime.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/scope_arbiter.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/scope_classifier.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/scope_head.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/scope_registry.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/scope_registry_loader.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/scope_shadow.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/session.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/session_utils.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/source_generation.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/truth_facts.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/truth_prompts.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/turn_classifier.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/types.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/verify.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/query/verify_modes.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/rate_limit.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/relay_stamp.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/routines/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/routines/schema.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/routines/store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/runtime_housekeeping.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/runtime_shutdown.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/runtime_update.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/sanitization/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/sanitization/nsfw_classifier.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/sanitization/ollama_transforms.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/sanitization/prewarm.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/sanitization/privacy_filter.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/scope_resolution.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/services/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/services/container.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/services/embeddings/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/services/embeddings/base.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/services/embeddings/local.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/services/embeddings/remote.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/services/interfaces.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/services/llm/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/services/llm/base.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/services/local.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/services/postgres.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/sources/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/sources/bundled_canonical_triples.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/sources/canonical_signal_defaults.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/sources/declared_field_map_spec.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/sources/definitions.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/sources/install_service.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/sources/registry.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/sources/runtime_install.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/sources/scrub_attribution.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/sources/scrub_service.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/startup_banner.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/adapters/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/adapters/factory.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/adapters/fakes.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/adapters/postgres/stores.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/adapters/protocols.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/adapters/sqlite/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/adapters/sqlite/stores.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/adapters/sqlite/vector_search.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/canonical/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/canonical/activity_tables.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/canonical/ai_chat/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/canonical/ai_chat/canonicalizer.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/canonical/ai_chat/mapper.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/canonical/ai_chat/model.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/canonical/ai_chat/tables.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/canonical/calendar_contacts_tables.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/canonical/canonical_store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/canonical/conversations_tables.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/canonical/journal_repair.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/canonical/mapping_store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/canonical/postgres.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/client.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/connection_tuning.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/activity_events_content_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/actor_role_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/affinity_pair_labels_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/attention_triage_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/attention_triage_v2.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/backup.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/backup_custody.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/calendar_events_scheduling_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/canonical_address_book_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/canonical_disclosure_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/canonical_nsfw_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/community_names_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/complexity_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/conflict_provenance_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/conversation_context_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/derivation_factory_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/derivation_ledger_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/derivation_provenance_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/derived_row_identity_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/documents_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/enrichment_record_progress_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/enrichment_spec_version_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/entity_affinity_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/entity_blackhole_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/entity_context_vectors_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/entity_context_vectors_v2.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/entity_edges_validity_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/entity_mentions_authored_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/entity_review_candidate_bar_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/entity_review_dedup_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/entity_review_provenance_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/episodes_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/extraction_artifacts.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/fact_dimension_by_entity_type_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/journal_entries_duration_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/journal_entries_ends_at_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/journal_entries_people_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/journal_entries_place_name_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/journal_entries_starts_at_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/journal_origin_dimension_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/mention_table_stamp_backfill_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/message_emotions_role_backfill_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/message_emotions_role_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/net_subject_policy_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/pack_registry_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/query_artifacts_duration_ms_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/registry.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/registry_checksums.json +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/remediation_person_model.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/retire_url_classification_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/scope_source_generation.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/signal_dimension_backfill_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/signal_dimension_harness.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/signal_objects.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/signal_objects_period_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/signal_objects_updated_by_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/signal_summaries_drop_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/stage9_column_renames.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/vector_storage_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/vector_storage_v2.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/vector_storage_v3.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/vector_storage_v4.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/wiki_clusters_v2.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/wiki_entities_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/wiki_entity_review_v2.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/wiki_facts_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/wiki_lifecycle_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/wiki_mvp_phase0.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/wiki_mvp_phase1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/wiki_mvp_phase4_messages_cutover.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/wiki_mvp_phase5_topic_clusters.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/wiki_mvp_phase6_dimension_briefs.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/wiki_mvp_query_quality.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/wiki_mvp_topic_clusters_coordination.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/wiki_stats_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/migrations/wiki_timeline_v1.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/paths.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/postgres.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/schema.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/schema_probe.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/storage_breakdown.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/db/write_gate.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/derived_row_identity.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/enrichment/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/enrichment/canonical_enrichment_store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/enrichment/raw_enrichment_store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/normalized/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/normalized/normalized_store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/oplog/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/oplog/decision.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/oplog/oplog_store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/oplog/postgres.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/person/identity_resolver.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/projections/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/projections/index_ops_store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/projections/vector_index_store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/raw/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/raw/browser_flat_tables.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/raw/file_store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/raw/raw_store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/raw/raw_tables_manager.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/raw/sqlite_raw_store.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/security/encryption.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/signal_identity.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/storage/user_identity.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/sync/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/sync/client.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/sync_handlers.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/testing/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/testing/lifespan.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/uds.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/uma_contact_enrichment.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/uma_filters.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/uma_resource_id.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/uma_rpt.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/upgrades/__init__.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/upgrades/runner.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/utils/base_object.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos/websocket_client.py +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos_node.egg-info/dependency_links.txt +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos_node.egg-info/entry_points.txt +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos_node.egg-info/requires.txt +0 -0
- {topos_node-1.3.36 → topos_node-1.3.38}/topos_node.egg-info/top_level.txt +0 -0
|
@@ -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.38"
|
|
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"
|
|
@@ -158,7 +158,7 @@ async def put_source_settings_endpoint(
|
|
|
158
158
|
dataset_id: Optional[str] = Query(default=None),
|
|
159
159
|
body: Optional[dict] = Body(default=None),
|
|
160
160
|
):
|
|
161
|
-
"""Set source settings (e.g. enabled). Valid for local_sync sources (imessage, signal)."""
|
|
161
|
+
"""Set source settings (e.g. enabled, exclude_spam). Valid for local_sync sources (imessage, signal)."""
|
|
162
162
|
source = REGISTRY.get(source_id)
|
|
163
163
|
if not source:
|
|
164
164
|
return {"status": "error", "error": "unknown source_id"}
|
|
@@ -167,14 +167,26 @@ async def put_source_settings_endpoint(
|
|
|
167
167
|
dataset_id = dataset_id or (body.get("dataset_id") if body else None)
|
|
168
168
|
if not dataset_id:
|
|
169
169
|
return {"status": "error", "error": "dataset_id required"}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
170
|
+
body = body or {}
|
|
171
|
+
enabled = body.get("enabled")
|
|
172
|
+
posture_provided = "posture" in body
|
|
173
|
+
exclude_spam_provided = "exclude_spam" in body
|
|
174
|
+
if enabled is None and not posture_provided and not exclude_spam_provided:
|
|
175
|
+
return {"status": "error", "error": "enabled, posture, or exclude_spam required in body"}
|
|
173
176
|
conn = get_db_connection()
|
|
174
177
|
if not conn:
|
|
175
178
|
return {"status": "error", "error": "Database not available"}
|
|
176
|
-
|
|
177
|
-
|
|
179
|
+
put_kwargs: dict = {"enabled": enabled}
|
|
180
|
+
if posture_provided:
|
|
181
|
+
put_kwargs["posture"] = body.get("posture")
|
|
182
|
+
if exclude_spam_provided:
|
|
183
|
+
put_kwargs["exclude_spam"] = bool(body.get("exclude_spam"))
|
|
184
|
+
try:
|
|
185
|
+
put_source_settings(conn, dataset_id, source_id, **put_kwargs)
|
|
186
|
+
except ValueError as exc:
|
|
187
|
+
return {"status": "error", "error": str(exc)}
|
|
188
|
+
settings = get_source_settings(conn, dataset_id, source_id) or {}
|
|
189
|
+
return {"status": "ok", "dataset_id": dataset_id, "source_id": source_id, **settings}
|
|
178
190
|
|
|
179
191
|
|
|
180
192
|
@router.post("/sources/{source_id}/sync", dependencies=[Depends(require_api_key)])
|
|
@@ -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")
|
|
@@ -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:
|
|
@@ -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)}
|
|
@@ -198,6 +198,8 @@ async def handle_put_source_settings(message: Dict[str, Any]) -> Optional[Dict[s
|
|
|
198
198
|
# present in the body — absent means "leave unchanged".
|
|
199
199
|
posture_provided = "posture" in payload
|
|
200
200
|
posture = payload.get("posture")
|
|
201
|
+
exclude_spam_provided = "exclude_spam" in payload
|
|
202
|
+
exclude_spam = payload.get("exclude_spam")
|
|
201
203
|
if not source_id or not dataset_id:
|
|
202
204
|
return {"id": req_id, "status": "error", "error": "source_id and dataset_id required"}
|
|
203
205
|
source = REGISTRY.get(source_id)
|
|
@@ -208,16 +210,20 @@ async def handle_put_source_settings(message: Dict[str, Any]) -> Optional[Dict[s
|
|
|
208
210
|
# enabled toggle is being set.
|
|
209
211
|
if enabled is not None and getattr(source, "source_type", None) != "local_sync":
|
|
210
212
|
return {"id": req_id, "status": "error", "error": "enabled only applies to local_sync sources"}
|
|
211
|
-
if
|
|
212
|
-
return {"id": req_id, "status": "error", "error": "
|
|
213
|
+
if exclude_spam_provided and getattr(source, "source_type", None) != "local_sync":
|
|
214
|
+
return {"id": req_id, "status": "error", "error": "exclude_spam only applies to local_sync sources"}
|
|
215
|
+
if enabled is None and not posture_provided and not exclude_spam_provided:
|
|
216
|
+
return {"id": req_id, "status": "error", "error": "enabled, posture, or exclude_spam required in body"}
|
|
213
217
|
conn = hub.get_db_connection()
|
|
214
218
|
if not conn:
|
|
215
219
|
return {"id": req_id, "status": "error", "error": "Database not available"}
|
|
216
220
|
try:
|
|
221
|
+
put_kwargs: Dict[str, Any] = {"enabled": enabled}
|
|
217
222
|
if posture_provided:
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
223
|
+
put_kwargs["posture"] = posture
|
|
224
|
+
if exclude_spam_provided:
|
|
225
|
+
put_kwargs["exclude_spam"] = bool(exclude_spam)
|
|
226
|
+
put_source_settings(conn, dataset_id, source_id, **put_kwargs)
|
|
221
227
|
except ValueError as exc:
|
|
222
228
|
return {"id": req_id, "status": "error", "error": str(exc)}
|
|
223
229
|
# Echo the effective settings back (posture reflects what was persisted /
|
|
@@ -229,6 +235,7 @@ async def handle_put_source_settings(message: Dict[str, Any]) -> Optional[Dict[s
|
|
|
229
235
|
else:
|
|
230
236
|
result_payload["enabled"] = bool(settings_data.get("enabled", True))
|
|
231
237
|
result_payload["posture"] = settings_data.get("posture")
|
|
238
|
+
result_payload["exclude_spam"] = bool(settings_data.get("exclude_spam", True))
|
|
232
239
|
return {"id": req_id, "status": "ok", "payload": result_payload}
|
|
233
240
|
|
|
234
241
|
@handles("get_source_contacts")
|
|
@@ -110,6 +110,12 @@ class OllamaAdapter:
|
|
|
110
110
|
except Exception:
|
|
111
111
|
return False
|
|
112
112
|
|
|
113
|
+
def _ensure_server(self) -> None:
|
|
114
|
+
"""Start a local Ollama if this request needs one and :11434 is down."""
|
|
115
|
+
from ..ollama_runtime import ensure_running
|
|
116
|
+
|
|
117
|
+
ensure_running(base_url=self._base_url)
|
|
118
|
+
|
|
113
119
|
def model_supports_thinking(self, model: str) -> bool:
|
|
114
120
|
"""True when /api/show lists the 'thinking' capability for ``model``.
|
|
115
121
|
|
|
@@ -172,6 +178,7 @@ class OllamaAdapter:
|
|
|
172
178
|
curated table — Ollama has no size for a tag that is not on disk
|
|
173
179
|
(PLAN_LOCAL_MODEL_QUICKSTART D4).
|
|
174
180
|
"""
|
|
181
|
+
self._ensure_server()
|
|
175
182
|
req = urllib.request.Request(f"{self._base_url}/api/tags", method="GET")
|
|
176
183
|
try:
|
|
177
184
|
with urllib.request.urlopen(req, timeout=10) as resp:
|
|
@@ -211,6 +218,7 @@ class OllamaAdapter:
|
|
|
211
218
|
show the download to a human. A callback that raises must not abort a
|
|
212
219
|
multi-gigabyte transfer that is otherwise healthy.
|
|
213
220
|
"""
|
|
221
|
+
self._ensure_server()
|
|
214
222
|
body = {"model": model_name, "stream": stream}
|
|
215
223
|
req = urllib.request.Request(
|
|
216
224
|
f"{self._base_url}/api/pull",
|
|
@@ -361,6 +369,7 @@ class OllamaAdapter:
|
|
|
361
369
|
# rejected think=false before keep thinking but get a wider output
|
|
362
370
|
# budget so the CoT cannot starve the answer (Ollama returns thinking
|
|
363
371
|
# in a separate field, so 'response' stays clean either way).
|
|
372
|
+
self._ensure_server()
|
|
364
373
|
requested_think = think
|
|
365
374
|
think = self.resolve_think(model, think)
|
|
366
375
|
if (
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"""Start a local Ollama server when a request needs it and :11434 is down.
|
|
2
|
+
|
|
3
|
+
Reachability is already probed everywhere; nothing on the product path used
|
|
4
|
+
to spawn the server. Install opens Ollama.app after a one-click install —
|
|
5
|
+
this module does the same (or ``ollama serve``) at request time, only for a
|
|
6
|
+
localhost base URL, and only once under a process lock.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import logging
|
|
12
|
+
import shutil
|
|
13
|
+
import subprocess
|
|
14
|
+
import threading
|
|
15
|
+
import time
|
|
16
|
+
from typing import Callable, Optional
|
|
17
|
+
from urllib.parse import urlparse
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger("topos.engine.ollama_runtime")
|
|
20
|
+
|
|
21
|
+
_LOCAL_HOSTS = frozenset({"localhost", "127.0.0.1", "::1"})
|
|
22
|
+
_WAIT_SEC = 20.0
|
|
23
|
+
_POLL_INTERVAL = 0.5
|
|
24
|
+
|
|
25
|
+
_LOCK = threading.Lock()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _default_base_url() -> str:
|
|
29
|
+
try:
|
|
30
|
+
from ..config.settings import settings
|
|
31
|
+
|
|
32
|
+
return str(getattr(settings, "engine_ollama_base_url", None) or "http://localhost:11434").rstrip("/")
|
|
33
|
+
except Exception:
|
|
34
|
+
return "http://localhost:11434"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def is_local_base_url(url: str) -> bool:
|
|
38
|
+
raw = str(url or "").strip()
|
|
39
|
+
if not raw:
|
|
40
|
+
return False
|
|
41
|
+
parsed = urlparse(raw if "://" in raw else f"http://{raw}")
|
|
42
|
+
host = (parsed.hostname or "").lower()
|
|
43
|
+
return host in _LOCAL_HOSTS
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def default_is_reachable(base_url: str) -> bool:
|
|
47
|
+
from .backends.ollama import OllamaAdapter
|
|
48
|
+
|
|
49
|
+
return bool(OllamaAdapter(base_url=base_url).is_reachable())
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def default_app_present() -> bool:
|
|
53
|
+
from .ollama_install import default_app_present as _app_present
|
|
54
|
+
|
|
55
|
+
return bool(_app_present())
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def default_open_app() -> None:
|
|
59
|
+
from .ollama_install import default_open_app as _open_app
|
|
60
|
+
|
|
61
|
+
_open_app()
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def default_cli_present() -> bool:
|
|
65
|
+
return shutil.which("ollama") is not None
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def default_spawn_serve() -> None:
|
|
69
|
+
subprocess.Popen(
|
|
70
|
+
["ollama", "serve"],
|
|
71
|
+
stdout=subprocess.DEVNULL,
|
|
72
|
+
stderr=subprocess.DEVNULL,
|
|
73
|
+
start_new_session=True,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def ensure_running(
|
|
78
|
+
*,
|
|
79
|
+
base_url: Optional[str] = None,
|
|
80
|
+
is_reachable: Optional[Callable[[], bool]] = None,
|
|
81
|
+
is_local: Optional[Callable[[str], bool]] = None,
|
|
82
|
+
app_present: Optional[Callable[[], bool]] = None,
|
|
83
|
+
open_app: Optional[Callable[[], None]] = None,
|
|
84
|
+
cli_present: Optional[Callable[[], bool]] = None,
|
|
85
|
+
spawn_serve: Optional[Callable[[], None]] = None,
|
|
86
|
+
sleep: Optional[Callable[[float], None]] = None,
|
|
87
|
+
wait_sec: float = _WAIT_SEC,
|
|
88
|
+
poll_interval: float = _POLL_INTERVAL,
|
|
89
|
+
) -> bool:
|
|
90
|
+
"""Bring a local Ollama up if a request needs it.
|
|
91
|
+
|
|
92
|
+
Returns True when the server answers ``/api/tags`` (already up, or up
|
|
93
|
+
after we launched). Returns False when the URL is remote, nothing is
|
|
94
|
+
installed, or the wait timed out — callers then hit the existing 502 /
|
|
95
|
+
deferred path.
|
|
96
|
+
"""
|
|
97
|
+
url = (base_url if base_url is not None else _default_base_url()).rstrip("/")
|
|
98
|
+
local_check = is_local if is_local is not None else is_local_base_url
|
|
99
|
+
if not local_check(url):
|
|
100
|
+
return False
|
|
101
|
+
|
|
102
|
+
reachable = is_reachable if is_reachable is not None else (lambda: default_is_reachable(url))
|
|
103
|
+
if reachable():
|
|
104
|
+
return True
|
|
105
|
+
|
|
106
|
+
with _LOCK:
|
|
107
|
+
if reachable():
|
|
108
|
+
return True
|
|
109
|
+
|
|
110
|
+
launched = False
|
|
111
|
+
present = app_present if app_present is not None else default_app_present
|
|
112
|
+
if present():
|
|
113
|
+
try:
|
|
114
|
+
(open_app if open_app is not None else default_open_app)()
|
|
115
|
+
launched = True
|
|
116
|
+
logger.info("opened Ollama.app; waiting for %s", url)
|
|
117
|
+
except Exception as exc: # noqa: BLE001 — launch is best-effort
|
|
118
|
+
logger.warning("failed to open Ollama.app: %s", exc)
|
|
119
|
+
|
|
120
|
+
if not launched:
|
|
121
|
+
has_cli = cli_present if cli_present is not None else default_cli_present
|
|
122
|
+
if has_cli():
|
|
123
|
+
try:
|
|
124
|
+
(spawn_serve if spawn_serve is not None else default_spawn_serve)()
|
|
125
|
+
launched = True
|
|
126
|
+
logger.info("spawned `ollama serve`; waiting for %s", url)
|
|
127
|
+
except Exception as exc: # noqa: BLE001
|
|
128
|
+
logger.warning("failed to spawn ollama serve: %s", exc)
|
|
129
|
+
|
|
130
|
+
if not launched:
|
|
131
|
+
logger.info("ollama is down and nothing on this machine can start it")
|
|
132
|
+
return False
|
|
133
|
+
|
|
134
|
+
sleeper = sleep if sleep is not None else time.sleep
|
|
135
|
+
deadline = time.monotonic() + float(wait_sec)
|
|
136
|
+
interval = max(0.0, float(poll_interval))
|
|
137
|
+
while time.monotonic() < deadline:
|
|
138
|
+
if reachable():
|
|
139
|
+
return True
|
|
140
|
+
sleeper(interval)
|
|
141
|
+
logger.warning("ollama did not become reachable at %s within %.1fs", url, wait_sec)
|
|
142
|
+
return False
|
|
@@ -106,6 +106,123 @@ def list_entities(
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
|
|
109
|
+
def entity_card_aggregates(
|
|
110
|
+
conn: sqlite3.Connection,
|
|
111
|
+
entity_id: str,
|
|
112
|
+
*,
|
|
113
|
+
guard: BlackholeGuard,
|
|
114
|
+
) -> Dict[str, Any]:
|
|
115
|
+
"""Full-population counts a type-specific entity card reads.
|
|
116
|
+
|
|
117
|
+
Separate from ``recent_mentions`` because they answer a different question.
|
|
118
|
+
``recent_mentions`` is a SAMPLE — twenty rows, newest first — and a card that
|
|
119
|
+
derived "83% of this came from browsing" by counting a sample would be
|
|
120
|
+
stating a measurement it had not made. Every count here is over the whole
|
|
121
|
+
mention set.
|
|
122
|
+
|
|
123
|
+
Two aggregates, because the card designs turn on two distinctions the spine
|
|
124
|
+
already records and nothing has ever read:
|
|
125
|
+
|
|
126
|
+
``mention_sources``
|
|
127
|
+
Mentions grouped by canonical table, with the owner-authored share. This
|
|
128
|
+
is what separates an organization the owner *writes about* from one whose
|
|
129
|
+
name appeared in a page title, a place they have *been* (``location_events``)
|
|
130
|
+
from one they only ever talked about, and a project they *work on*
|
|
131
|
+
(``activity_events``) from one they have only planned. The whole judgement
|
|
132
|
+
line of six of the ten cards rests on it.
|
|
133
|
+
|
|
134
|
+
``neighbor_counts``
|
|
135
|
+
Edges grouped by ``(edge_type, direction, neighbour type)``. The card needs
|
|
136
|
+
"6 people around this" and "14 goals point at it", and ``connections`` is
|
|
137
|
+
capped at twelve rows ordered by weight — a cap is the right answer for a
|
|
138
|
+
list and the wrong one for a count.
|
|
139
|
+
|
|
140
|
+
Direction is kept because it is load-bearing for at least one type: a
|
|
141
|
+
conversation's ``participates_in`` (inbound, someone was there) and its
|
|
142
|
+
``mentions`` (outbound, someone was named) are different claims about a
|
|
143
|
+
person, and a card that merged them would say a person who was discussed was
|
|
144
|
+
in the room.
|
|
145
|
+
"""
|
|
146
|
+
eid = str(entity_id)
|
|
147
|
+
|
|
148
|
+
# A record that names a protected entity is withheld whole, so its mentions
|
|
149
|
+
# of THIS entity cannot be counted either — otherwise the total silently
|
|
150
|
+
# disagrees with the records the reader is allowed to open, and the size of
|
|
151
|
+
# the disagreement is a signal about what was hidden. Inert for the owner UI,
|
|
152
|
+
# where `sees_everything` short-circuits `blocked_record_ids` to an empty set.
|
|
153
|
+
blocked_records = guard.blocked_record_ids()
|
|
154
|
+
|
|
155
|
+
mention_rows = conn.execute(
|
|
156
|
+
"""
|
|
157
|
+
SELECT record_id, COALESCE(canonical_table, ''), COALESCE(authored_by_owner, 0)
|
|
158
|
+
FROM entity_mentions WHERE entity_id = ?
|
|
159
|
+
""",
|
|
160
|
+
(eid,),
|
|
161
|
+
).fetchall()
|
|
162
|
+
|
|
163
|
+
by_table: Dict[str, Dict[str, int]] = {}
|
|
164
|
+
for record_id, table, authored in mention_rows:
|
|
165
|
+
if blocked_records and str(record_id) in blocked_records:
|
|
166
|
+
continue
|
|
167
|
+
# An unattributed mention is its own fact — bucketed under "" rather than
|
|
168
|
+
# dropped, so the card's percentages are over the same denominator as its
|
|
169
|
+
# total and cannot quietly exceed 100%.
|
|
170
|
+
slot = by_table.setdefault(str(table), {"count": 0, "owner_authored": 0})
|
|
171
|
+
slot["count"] += 1
|
|
172
|
+
if int(authored or 0) == 1:
|
|
173
|
+
slot["owner_authored"] += 1
|
|
174
|
+
|
|
175
|
+
mention_sources = sorted(
|
|
176
|
+
(
|
|
177
|
+
{"table": table, "count": v["count"], "owner_authored": v["owner_authored"]}
|
|
178
|
+
for table, v in by_table.items()
|
|
179
|
+
),
|
|
180
|
+
key=lambda r: (-int(r["count"]), str(r["table"])),
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
# Counted in Python rather than pushed into a GROUP BY so the guard applies
|
|
184
|
+
# per neighbour: a protected entity must not be counted, and a SQL count
|
|
185
|
+
# would include it while the neighbour LIST beside it does not.
|
|
186
|
+
edge_rows = conn.execute(
|
|
187
|
+
"""
|
|
188
|
+
SELECT e.src_entity_id, e.dst_entity_id, e.edge_type,
|
|
189
|
+
COALESCE(s.entity_type, ''), COALESCE(t.entity_type, ''),
|
|
190
|
+
s.canonical_name, t.canonical_name
|
|
191
|
+
FROM entity_edges e
|
|
192
|
+
LEFT JOIN entities s ON s.entity_id = e.src_entity_id
|
|
193
|
+
LEFT JOIN entities t ON t.entity_id = e.dst_entity_id
|
|
194
|
+
WHERE (e.src_entity_id = ? OR e.dst_entity_id = ?) AND e.valid_to IS NULL
|
|
195
|
+
""",
|
|
196
|
+
(eid, eid),
|
|
197
|
+
).fetchall()
|
|
198
|
+
|
|
199
|
+
tally: Dict[tuple, int] = {}
|
|
200
|
+
for src, dst, edge_type, src_type, dst_type, src_name, dst_name in edge_rows:
|
|
201
|
+
outbound = str(src) == eid
|
|
202
|
+
other_id = dst if outbound else src
|
|
203
|
+
other_type = dst_type if outbound else src_type
|
|
204
|
+
other_name = dst_name if outbound else src_name
|
|
205
|
+
if guard.blocks_entity_id(other_id) or guard.blocks_name(other_name):
|
|
206
|
+
continue
|
|
207
|
+
key = (str(edge_type), "out" if outbound else "in", str(other_type))
|
|
208
|
+
tally[key] = tally.get(key, 0) + 1
|
|
209
|
+
|
|
210
|
+
neighbor_counts = sorted(
|
|
211
|
+
(
|
|
212
|
+
{
|
|
213
|
+
"edge_type": edge_type,
|
|
214
|
+
"direction": direction,
|
|
215
|
+
"entity_type": other_type,
|
|
216
|
+
"count": count,
|
|
217
|
+
}
|
|
218
|
+
for (edge_type, direction, other_type), count in tally.items()
|
|
219
|
+
),
|
|
220
|
+
key=lambda r: (-int(r["count"]), str(r["edge_type"]), str(r["entity_type"])),
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
return {"mention_sources": mention_sources, "neighbor_counts": neighbor_counts}
|
|
224
|
+
|
|
225
|
+
|
|
109
226
|
def get_entity_detail(
|
|
110
227
|
conn: sqlite3.Connection,
|
|
111
228
|
entity_id: str,
|
|
@@ -175,6 +292,12 @@ def get_entity_detail(
|
|
|
175
292
|
entity["affinity_connections"] = guard.filter_rows(
|
|
176
293
|
affinity, id_keys=id_keys, name_keys=name_keys
|
|
177
294
|
)
|
|
295
|
+
# Full-population counts for the type-specific cards. Attached to every
|
|
296
|
+
# entity rather than branching on type here: the card layer decides what a
|
|
297
|
+
# place does with `location_events` and what an org does with the
|
|
298
|
+
# owner-authored share, and a read that guessed for it would have to be
|
|
299
|
+
# changed every time a card learns a new question.
|
|
300
|
+
entity.update(entity_card_aggregates(conn, str(entity_id), guard=guard))
|
|
178
301
|
dossier = load_dossier_for_entity(conn, str(entity_id))
|
|
179
302
|
if isinstance(dossier, dict) and not guard.sees_everything:
|
|
180
303
|
dossier = dict(dossier)
|