topos-node 1.3.0__tar.gz → 1.3.2__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.0 → topos_node-1.3.2}/MANIFEST.in +2 -0
- {topos_node-1.3.0/topos_node.egg-info → topos_node-1.3.2}/PKG-INFO +9 -1
- {topos_node-1.3.0 → topos_node-1.3.2}/pyproject.toml +13 -1
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/__version__.py +2 -2
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/llm.py +47 -0
- topos_node-1.3.2/topos/api/shell.py +91 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/signal.py +195 -2
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/uma_data.py +4 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/app.py +41 -13
- topos_node-1.3.2/topos/cli/assets/topos_blk_rounded.png +0 -0
- topos_node-1.3.2/topos/cli/assets/topos_white.png +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/cli/commands.py +90 -2
- topos_node-1.3.2/topos/cli/tray.py +392 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/control_plane_client.py +4 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/__init__.py +2 -0
- topos_node-1.3.2/topos/core/handlers/complexity.py +145 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/messages.py +3 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/signal_features.py +203 -1
- topos_node-1.3.2/topos/core/handlers/timeline_daily.py +40 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/uma.py +15 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/logging.py +47 -7
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/engine.py +93 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/usage_observation.py +6 -1
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/catalog.py +13 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/__init__.py +2 -0
- topos_node-1.3.2/topos/enrichment/jobs/canonical/complexity_snapshot_job.py +83 -0
- topos_node-1.3.2/topos/features/complexity/__init__.py +10 -0
- topos_node-1.3.2/topos/features/complexity/canonical.py +301 -0
- topos_node-1.3.2/topos/features/complexity/engine.py +287 -0
- topos_node-1.3.2/topos/features/complexity/entropy.py +100 -0
- topos_node-1.3.2/topos/features/complexity/focus.py +507 -0
- topos_node-1.3.2/topos/features/complexity/graph_metrics.py +177 -0
- topos_node-1.3.2/topos/features/complexity/influence.py +664 -0
- topos_node-1.3.2/topos/features/complexity/projection.py +567 -0
- topos_node-1.3.2/topos/features/complexity/snapshots.py +77 -0
- topos_node-1.3.2/topos/features/complexity/store.py +136 -0
- topos_node-1.3.2/topos/features/complexity/topic_merge.py +437 -0
- topos_node-1.3.2/topos/features/complexity/topics.py +154 -0
- topos_node-1.3.2/topos/features/complexity/topics_daily.py +106 -0
- topos_node-1.3.2/topos/features/complexity/volatility.py +140 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/entities/edges.py +18 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/entities/reads.py +73 -5
- topos_node-1.3.2/topos/features/lifecycle/blackhole.py +533 -0
- topos_node-1.3.2/topos/features/lifecycle/blackhole_guard.py +385 -0
- topos_node-1.3.2/topos/features/lifecycle/blackhole_llm.py +169 -0
- topos_node-1.3.2/topos/features/lifecycle/blackhole_rebuild.py +210 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/conversation_context.py +3 -1
- topos_node-1.3.2/topos/features/timeline_rollup.py +121 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/triage/badges.py +7 -3
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/triage/dashboard.py +12 -5
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/protocol/handled_message_types.json +11 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/game_layer.py +14 -12
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/pipeline.py +3 -1
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/retrieval.py +275 -24
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/scope_registry.json +34 -8
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/__init__.py +16 -0
- topos_node-1.3.2/topos/storage/db/migrations/complexity_v1.py +48 -0
- topos_node-1.3.2/topos/storage/db/migrations/entity_blackhole_v1.py +91 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/uma_contact_enrichment.py +22 -2
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/upgrades/manifests.json +30 -4
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/upgrades/runner.py +206 -28
- {topos_node-1.3.0 → topos_node-1.3.2/topos_node.egg-info}/PKG-INFO +9 -1
- {topos_node-1.3.0 → topos_node-1.3.2}/topos_node.egg-info/SOURCES.txt +28 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos_node.egg-info/requires.txt +8 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/LICENSE +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/README.md +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/setup.cfg +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/shared/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/shared/filtering.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/shared/schema_registry.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/tests/test_extensions.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/tests/test_llm_integrations_storage.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/tests/test_protocol_handled_types.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/analytics/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/analytics/duckdb_adapter.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/analytics/messenger_communities.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/analytics/messenger_graph.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/analytics/messenger_labels.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/analytics/profiles.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/analytics/query_engine.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/analytics/raw_queries.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/analytics.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/app_registry.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/backup.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/compute_remote.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/conversation_context.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/data_commit.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/data_explorer_table_prefs.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/database_explorer.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/db.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/device.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/engine_run.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/enrichment.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/enrichment_lab.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/facts_llm_config.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/filter_lab.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/health.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/home_chat.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/ingestion_api.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/ingestion_compat.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/ingestion_sources.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/intelligence_lifecycle.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/local_mcp.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/messenger_analytics.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/privacy_disclose.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/query_api.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/runtime_bootstrap.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/sanitization_ollama_config.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/signal_extraction_config.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/source_install.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/source_scrub.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/sources.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/sources_overview.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/sync.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/tool_index.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/ui_config.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/upgrades.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/usage.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/api/user_identity.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/auth.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/canonicalization/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/canonicalization/mappers/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/canonicalization/mappers/base.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/canonicalization/mappers/browser_activity_mapper.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/canonicalization/mappers/chatgpt_mapper.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/canonicalization/mappers/demo_mappers.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/canonicalization/mappers/documents_mapper.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/canonicalization/mappers/github_activity_mapper.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/canonicalization/mappers/google_calendar_mapper.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/canonicalization/mappers/grok_mapper.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/canonicalization/mappers/messenger_mapper.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/canonicalization/models.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/canonicalization/resolver.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/cli/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/cli/__main__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/config/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/config/conversation_context_llm.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/config/facts_llm.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/config/sanitization_ollama.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/config/settings.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/config/signal_extraction.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/config/uvicorn_logging.json +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/contacts/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/contacts/identity.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/api_models.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/connection_resilience.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/device_helpers.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/errors.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/events.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/common.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/config.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/contacts_import.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/database_explorer.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/device.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/enrichment.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/enrichment_lab.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/filter_lab.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/home_chat.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/ingest.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/messenger_analytics.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/query.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/registry.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/routines.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/sources.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/handlers/tool_index.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/metrics.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/routine_access.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/startup_banner.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/state.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/table_layers.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/core/types.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/data_explorer_row_delete.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/data_explorer_table_prefs.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/data_explorer_tables.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/disclosure/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/disclosure/canonical_writer.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/disclosure/content_policy.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/disclosure/field_registry.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/disclosure/privacy_layer.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/disclosure/tier.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/backends/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/backends/base.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/backends/generative_prompts.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/backends/generative_response.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/backends/huggingface.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/backends/ollama.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/backends/openai.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/backends/openai_compatible.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/backends/redpill.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/backends/stub.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/client.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/intake.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/memory_utils.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/model_cache.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/pipeline_memory.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/queue_manager.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/registration.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/result_formatter.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/router.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/scoped_token.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/tasks.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/transport.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/usage_guard.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/engine/validator.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/derived_tables.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/job_writer.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/base.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/_batch_limits.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/_engine_runner.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/attention_triage_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/availability_scores_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/brief_fallback.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/dimension_summary_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/embeddings_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/emo_27_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/entities_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/fact_extraction_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/goal_extraction_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/pii_redaction_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/relationship_edges_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/sentiment_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/statistics_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/timeline_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/topic_clusters_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/topics_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/url_classification_core.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/url_classification_enrichment_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/canonical/url_classification_signal_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/raw/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/raw/attachments_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/raw/language_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/raw/time_normalization_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/jobs/raw/tool_calls_job.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/model_overrides.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/models/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/models/manager.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/models/mvp_defaults.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/models/registry.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/models/versioning.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/orchestrator.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/processor.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/progress_bar.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/registry_contract.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/signal_derivation_config.json +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/source_overrides.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment/website_classifier.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment_lab/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment_lab/bundles.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment_lab/model_resolve.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment_lab/schema.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment_lab/service.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment_lab/store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/enrichment_lab/worker.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/evals/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/evals/enrichment_eval.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/extensions.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/entities/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/entities/consolidation.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/entities/declared_mappings.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/entities/dossier.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/entities/fact_materializer.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/entities/graph_enrichers.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/entities/graph_refresh.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/entities/graph_search.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/entities/linking.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/entities/maintenance.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/entities/resolver.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/facts/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/facts/extract.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/facts/llm_extract.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/facts/reads.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/facts/store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/facts/verdicts.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/fit/evaluator.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/fit/opportunity_types.json +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/lifecycle/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/lifecycle/derived_scrub.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/lifecycle/exclusions.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/lifecycle/gc.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/provenance/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/provenance/posture.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/provenance/roles.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/brief_canonical_loader.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/brief_ontology.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/brief_renderer.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/brief_schemas.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/chunking.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/cluster_labels.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/data_health.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/definitions/brief_ontologies.json +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/definitions/intentions.json +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/definitions/profile.json +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/definitions/relationships.json +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/definitions/schema/dimension_definition.schema.json +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/definitions/time.json +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/definitions/work.json +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/dimension_briefs.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/dimension_definition_loader.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/dimension_profiles.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/dimension_registry.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/embed_context.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/extraction/artifact_router.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/extraction/artifact_store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/extraction/rule_extractors.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/graph_sanitize.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/hybrid_search.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/incremental_clustering.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/model_recommendations.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/query_embed_cache.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/schemas.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/service.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/signal_object_store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/source_hydration.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/structured_signal.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/tool_index.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/topic_clustering.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/typed_stores/aggregates.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/typed_stores/commitments.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/typed_stores/rhythm.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/typed_stores/scope_materializer.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/vector_codec.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/vector_math.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/signal/vector_settings.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/stats/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/stats/definitions.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/stats/engine.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/stats/fold.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/stats/insights.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/timeline_projection.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/triage/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/triage/daily.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/triage/instruments.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/triage/intents.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/features/triage/readiness.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/filter_lab/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/filter_lab/bundles.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/filter_lab/schema.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/filter_lab/service.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/filter_lab/store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/filter_lab/worker.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/home_chat/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/home_chat/schema.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/home_chat/store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/hosted_pool_lease.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/canonical_pipeline.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/checkpoints/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/checkpoints/checkpoint_store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/checkpoints/sqlite_checkpoint_store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/inbox_crypto.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/inbox_drain.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/ingest_helpers.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/jobs.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/journal_location_fanout.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/journal_time_log_normalize.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/local_sync.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/log_preview.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/manager.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/parser.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/parsers/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/parsers/base.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/parsers/browser_parser.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/parsers/calendar_parser.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/parsers/chatgpt_conversation_flattener.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/parsers/chatgpt_parser.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/parsers/demo_file_parsers.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/parsers/documents_parser.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/parsers/github_activity_parser.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/parsers/google_calendar_parser.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/parsers/grok_parser.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/parsers/messenger_parser.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/parsers/voxterm_parser.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/progress.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/reprocess.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/sources/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/sources/base.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/sources/calendar.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/sources/chatgpt.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/sources/contact_importers.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/sources/grok.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/sources/imessage_reader.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/sources/signal_export_parser.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/sources/signal_reader.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/state_machine.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/triggers/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/triggers/file_trigger.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/triggers/sqlite_trigger.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/usage_inbox_dedupe.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/validation/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/validation/base.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/validation/schema_registry.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/ingestion/validation/schema_validator.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/lineage/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/lineage/provenance.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/lineage/tracker.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/llm_integrations_storage.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/mcp_stdio_proxy.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/observability/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/observability/alerts.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/observability/metrics.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/observability/tracing.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/openai_client.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/pipeline/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/pipeline/audit.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/pipeline/envelope.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/pipeline/job_runner.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/pipeline/job_store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/pipeline/stages.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/pipeline/stub_enqueue.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/projections/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/projections/vector_index/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/projections/vector_index/base.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/projections/vector_index/builders.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/projections/vector_index/health_checks.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/protocol/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/audit.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/ddr.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/disclosure.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/fingerprint.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/grant_cache.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/inference.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/intent.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/manifest.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/manifest_validation.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/minimizer.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/negotiation.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/planner.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/runtime.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/scope_registry_loader.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/session.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/session_utils.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/source_generation.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/truth_facts.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/truth_prompts.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/turn_classifier.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/types.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/verify.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/query/verify_modes.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/rate_limit.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/routines/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/routines/schema.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/routines/store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/runtime_housekeeping.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/runtime_shutdown.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/runtime_update.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/sanitization/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/sanitization/nsfw_classifier.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/sanitization/ollama_transforms.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/sanitization/prewarm.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/sanitization/privacy_filter.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/scope_resolution.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/services/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/services/container.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/services/embeddings/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/services/embeddings/base.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/services/embeddings/local.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/services/embeddings/remote.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/services/interfaces.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/services/llm/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/services/llm/base.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/services/llm/openai.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/services/local.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/services/postgres.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/sources/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/sources/bundled_canonical_triples.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/sources/canonical_signal_defaults.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/sources/definitions.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/sources/install_service.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/sources/registry.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/sources/runtime_install.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/sources/scrub_attribution.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/sources/scrub_service.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/startup_banner.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/adapters/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/adapters/factory.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/adapters/fakes.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/adapters/postgres/stores.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/adapters/protocols.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/adapters/sqlite/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/adapters/sqlite/stores.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/adapters/sqlite/vector_search.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/canonical/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/canonical/activity_tables.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/canonical/ai_chat/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/canonical/ai_chat/canonicalizer.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/canonical/ai_chat/mapper.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/canonical/ai_chat/model.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/canonical/ai_chat/tables.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/canonical/calendar_contacts_tables.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/canonical/canonical_store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/canonical/conversations_tables.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/canonical/mapping_store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/canonical/postgres.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/client.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/connection_tuning.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/activity_events_content_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/actor_role_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/attention_triage_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/attention_triage_v2.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/calendar_events_scheduling_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/canonical_address_book_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/canonical_disclosure_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/canonical_nsfw_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/conversation_context_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/derivation_ledger_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/documents_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/entity_edges_validity_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/episodes_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/extraction_artifacts.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/journal_entries_duration_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/journal_entries_ends_at_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/journal_entries_people_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/journal_entries_place_name_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/journal_entries_starts_at_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/pipeline_jobs_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/remediation_person_model.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/scope_source_generation.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/signal_dimension_backfill_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/signal_dimension_harness.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/signal_objects.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/signal_objects_period_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/signal_objects_updated_by_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/stage9_column_renames.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/vector_storage_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/vector_storage_v2.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/vector_storage_v3.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/vector_storage_v4.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/wiki_clusters_v2.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/wiki_entities_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/wiki_entity_review_v2.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/wiki_facts_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/wiki_lifecycle_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/wiki_mvp_phase0.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/wiki_mvp_phase1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/wiki_mvp_phase4_messages_cutover.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/wiki_mvp_phase5_topic_clusters.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/wiki_mvp_phase6_dimension_briefs.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/wiki_mvp_query_quality.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/wiki_mvp_topic_clusters_coordination.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/wiki_stats_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/migrations/wiki_timeline_v1.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/paths.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/postgres.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/schema.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/storage_breakdown.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/db/write_gate.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/enrichment/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/enrichment/canonical_enrichment_store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/enrichment/raw_enrichment_store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/normalized/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/normalized/normalized_store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/oplog/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/oplog/decision.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/oplog/oplog_store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/oplog/postgres.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/person/identity_resolver.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/projections/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/projections/index_ops_store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/projections/vector_index_store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/raw/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/raw/browser_flat_tables.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/raw/file_store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/raw/raw_store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/raw/raw_tables_manager.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/raw/sqlite_raw_store.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/security/encryption.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/signal_identity.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/source_settings.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/storage/user_identity.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/sync/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/sync/client.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/sync_handlers.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/testing/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/testing/lifespan.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/uma_filters.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/uma_resource_id.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/uma_rpt.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/upgrades/__init__.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/utils/base_object.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos/websocket_client.py +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos_node.egg-info/dependency_links.txt +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/topos_node.egg-info/entry_points.txt +0 -0
- {topos_node-1.3.0 → topos_node-1.3.2}/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.2
|
|
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
|
|
@@ -33,7 +33,12 @@ Requires-Dist: hf-xet~=1.5.1
|
|
|
33
33
|
Requires-Dist: sentence-transformers~=5.6.0
|
|
34
34
|
Requires-Dist: networkx<3.7,>=3.2.1
|
|
35
35
|
Requires-Dist: python-louvain<0.17,>=0.16
|
|
36
|
+
Requires-Dist: numpy<3,>=1.26
|
|
37
|
+
Requires-Dist: scipy<2,>=1.11
|
|
38
|
+
Requires-Dist: scikit-learn<2,>=1.4
|
|
36
39
|
Requires-Dist: sqlite-vec~=0.1.9
|
|
40
|
+
Requires-Dist: pystray~=0.19.5
|
|
41
|
+
Requires-Dist: pillow>=10.0
|
|
37
42
|
Provides-Extra: database
|
|
38
43
|
Requires-Dist: psycopg[binary]~=3.3.3; extra == "database"
|
|
39
44
|
Provides-Extra: engine
|
|
@@ -46,6 +51,9 @@ Requires-Dist: hf-xet~=1.5.1; extra == "engine"
|
|
|
46
51
|
Requires-Dist: sentence-transformers~=5.6.0; extra == "engine"
|
|
47
52
|
Requires-Dist: networkx<3.7,>=3.2.1; extra == "engine"
|
|
48
53
|
Requires-Dist: python-louvain<0.17,>=0.16; extra == "engine"
|
|
54
|
+
Requires-Dist: numpy<3,>=1.26; extra == "engine"
|
|
55
|
+
Requires-Dist: scipy<2,>=1.11; extra == "engine"
|
|
56
|
+
Requires-Dist: scikit-learn<2,>=1.4; extra == "engine"
|
|
49
57
|
Provides-Extra: local
|
|
50
58
|
Provides-Extra: signal
|
|
51
59
|
Requires-Dist: pysqlcipher3~=1.2.0; extra == "signal"
|
|
@@ -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.2"
|
|
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"
|
|
@@ -35,7 +35,15 @@ dependencies = [
|
|
|
35
35
|
"sentence-transformers~=5.6.0",
|
|
36
36
|
"networkx>=3.2.1,<3.7",
|
|
37
37
|
"python-louvain>=0.16,<0.17",
|
|
38
|
+
# Complexity readings (topos.features.complexity): entropy/MI + graph math.
|
|
39
|
+
"numpy>=1.26,<3",
|
|
40
|
+
"scipy>=1.11,<2",
|
|
41
|
+
"scikit-learn>=1.4,<2",
|
|
38
42
|
"sqlite-vec~=0.1.9",
|
|
43
|
+
# Menu-bar/system-tray status icon (topos.cli.tray). Imported lazily and
|
|
44
|
+
# only when a GUI session is detected — harmless on headless installs.
|
|
45
|
+
"pystray~=0.19.5",
|
|
46
|
+
"pillow>=10.0",
|
|
39
47
|
]
|
|
40
48
|
|
|
41
49
|
[project.urls]
|
|
@@ -58,6 +66,9 @@ engine = [
|
|
|
58
66
|
"sentence-transformers~=5.6.0",
|
|
59
67
|
"networkx>=3.2.1,<3.7",
|
|
60
68
|
"python-louvain>=0.16,<0.17",
|
|
69
|
+
"numpy>=1.26,<3",
|
|
70
|
+
"scipy>=1.11,<2",
|
|
71
|
+
"scikit-learn>=1.4,<2",
|
|
61
72
|
]
|
|
62
73
|
# Backward-compatible alias; local runtime deps are in core dependencies.
|
|
63
74
|
local = []
|
|
@@ -109,6 +120,7 @@ markers = [
|
|
|
109
120
|
"adversarial: scope-break / access-control adversarial test (privacy enforcement)",
|
|
110
121
|
"uar: unauthorized-access-rate probe (privacy claim #1); tier-1 CI gate, must find zero leaks",
|
|
111
122
|
"cer: canary-extraction-rate probe (privacy claim #2); tier-1 CI gate",
|
|
123
|
+
"bhlr: black-hole leak-rate probe (entity black hole); tier-1 CI gate, must find zero leaks",
|
|
112
124
|
"eval_nightly: statistical privacy eval (attacker advantage, minimality, latency); nightly",
|
|
113
125
|
"eval_release: release-tier privacy eval (negotiation A/B, Pareto); run per release",
|
|
114
126
|
]
|
|
@@ -16,6 +16,51 @@ logger = logging.getLogger("topos.api.llm")
|
|
|
16
16
|
router = APIRouter()
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
def _enforce_blackhole_egress(body: GenerationRequest) -> GenerationRequest:
|
|
20
|
+
"""Gate B: this route reaches cloud providers without passing the engine router.
|
|
21
|
+
|
|
22
|
+
`Engine.run` gates every task-shaped inference, but these two endpoints call
|
|
23
|
+
the LLM service directly, so the same policy has to be applied here or the
|
|
24
|
+
hole stays open. Rewrites the provider onto a secure one when the prompt
|
|
25
|
+
mentions a protected entity; refuses when nothing secure can serve it.
|
|
26
|
+
|
|
27
|
+
The refusal is owner-facing (this route is API-key authenticated) and still
|
|
28
|
+
names no entity — the reason may be logged somewhere less private.
|
|
29
|
+
"""
|
|
30
|
+
from fastapi import HTTPException
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
from ..engine.engine import _policy_db_connection
|
|
34
|
+
from ..features.lifecycle.blackhole_llm import describe_block, evaluate
|
|
35
|
+
except Exception: # noqa: BLE001
|
|
36
|
+
return body
|
|
37
|
+
|
|
38
|
+
conn, owned = _policy_db_connection()
|
|
39
|
+
try:
|
|
40
|
+
verdict = evaluate(
|
|
41
|
+
conn,
|
|
42
|
+
{"prompt": body.prompt, "system": getattr(body, "system", None)},
|
|
43
|
+
provider=body.provider or "",
|
|
44
|
+
)
|
|
45
|
+
except Exception as exc: # noqa: BLE001
|
|
46
|
+
raise HTTPException(status_code=503, detail=f"blackhole_policy_unavailable: {exc}")
|
|
47
|
+
finally:
|
|
48
|
+
if owned and conn is not None:
|
|
49
|
+
try:
|
|
50
|
+
conn.close()
|
|
51
|
+
except Exception: # noqa: BLE001
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
if not verdict.tainted:
|
|
55
|
+
return body
|
|
56
|
+
if verdict.blocked:
|
|
57
|
+
raise HTTPException(status_code=503, detail=describe_block(verdict))
|
|
58
|
+
if verdict.redirected:
|
|
59
|
+
logger.info("blackhole: llm route redirected to %s", verdict.provider)
|
|
60
|
+
return body.model_copy(update={"provider": verdict.provider, "model": None})
|
|
61
|
+
return body
|
|
62
|
+
|
|
63
|
+
|
|
19
64
|
@router.post(
|
|
20
65
|
"/llm_generation",
|
|
21
66
|
response_model=GenerationResponse,
|
|
@@ -28,6 +73,7 @@ async def llm_generation(body: GenerationRequest):
|
|
|
28
73
|
body.model,
|
|
29
74
|
len(body.prompt or ""),
|
|
30
75
|
)
|
|
76
|
+
body = _enforce_blackhole_egress(body)
|
|
31
77
|
services: Services = get_services()
|
|
32
78
|
result = await services.llm.generate(body.model_dump())
|
|
33
79
|
usage = result.get("usage") if isinstance(result, dict) else {}
|
|
@@ -60,6 +106,7 @@ async def llm_generation_alias(body: GenerationRequest):
|
|
|
60
106
|
body.model,
|
|
61
107
|
len(body.prompt or ""),
|
|
62
108
|
)
|
|
109
|
+
body = _enforce_blackhole_egress(body)
|
|
63
110
|
services: Services = get_services()
|
|
64
111
|
result = await services.llm.generate(body.model_dump())
|
|
65
112
|
usage = result.get("usage") if isinstance(result, dict) else {}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""Shell contract endpoints.
|
|
2
|
+
|
|
3
|
+
Everything a menu-bar/tray shell (the pystray tray, the future Swift macOS
|
|
4
|
+
shell, the Windows shell) needs to supervise this node lives here, so shells
|
|
5
|
+
stay dumb renderers: identity + version for attach-don't-double-start, the
|
|
6
|
+
log file location for a "Show Logs" action, and cached update state with a
|
|
7
|
+
localhost-only trigger to apply an update.
|
|
8
|
+
|
|
9
|
+
Update *checking* is not done here — the runtime update monitor started in
|
|
10
|
+
app startup keeps ``get_update_info()`` fresh; this router only reads it.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
import threading
|
|
17
|
+
from time import time
|
|
18
|
+
|
|
19
|
+
from fastapi import APIRouter, HTTPException, Request
|
|
20
|
+
|
|
21
|
+
from ..core.logging import get_log_file_path
|
|
22
|
+
from ..runtime_update import (
|
|
23
|
+
DEFAULT_PACKAGE_NAME,
|
|
24
|
+
apply_package_update,
|
|
25
|
+
get_runtime_version,
|
|
26
|
+
get_update_info,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
router = APIRouter(prefix="/v1/shell", tags=["shell"])
|
|
30
|
+
|
|
31
|
+
_STARTED_AT = time()
|
|
32
|
+
|
|
33
|
+
_apply_lock = threading.Lock()
|
|
34
|
+
_apply_state: dict[str, object] = {"applying": False, "last_result": None}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _client_is_local(request: Request) -> bool:
|
|
38
|
+
# Applying an update is the one mutating action here; a LAN peer must not
|
|
39
|
+
# be able to trigger it even though the node binds 0.0.0.0. ("testclient"
|
|
40
|
+
# is FastAPI's TestClient peer name — unreachable over a real socket.)
|
|
41
|
+
host = request.client.host if request.client else None
|
|
42
|
+
return host in ("127.0.0.1", "::1", "localhost", "testclient")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@router.get("/status")
|
|
46
|
+
async def shell_status() -> dict:
|
|
47
|
+
info = get_update_info()
|
|
48
|
+
log_file = get_log_file_path()
|
|
49
|
+
return {
|
|
50
|
+
"name": "topos-node",
|
|
51
|
+
"version": get_runtime_version(),
|
|
52
|
+
"pid": os.getpid(),
|
|
53
|
+
"started_at": _STARTED_AT,
|
|
54
|
+
"log_file": str(log_file) if log_file else None,
|
|
55
|
+
"update": {
|
|
56
|
+
"available": info is not None,
|
|
57
|
+
"installed": info.installed if info else None,
|
|
58
|
+
"latest": info.latest if info else None,
|
|
59
|
+
"applying": _apply_state["applying"],
|
|
60
|
+
"last_result": _apply_state["last_result"],
|
|
61
|
+
},
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@router.post("/update")
|
|
66
|
+
async def shell_apply_update(request: Request) -> dict:
|
|
67
|
+
if not _client_is_local(request):
|
|
68
|
+
raise HTTPException(
|
|
69
|
+
status_code=403, detail="Shell update can only be triggered from localhost."
|
|
70
|
+
)
|
|
71
|
+
if get_update_info() is None:
|
|
72
|
+
return {"started": False, "reason": "no_update_available"}
|
|
73
|
+
with _apply_lock:
|
|
74
|
+
if _apply_state["applying"]:
|
|
75
|
+
return {"started": False, "reason": "already_applying"}
|
|
76
|
+
_apply_state["applying"] = True
|
|
77
|
+
_apply_state["last_result"] = None
|
|
78
|
+
|
|
79
|
+
def worker() -> None:
|
|
80
|
+
ok = False
|
|
81
|
+
try:
|
|
82
|
+
ok = apply_package_update(DEFAULT_PACKAGE_NAME)
|
|
83
|
+
finally:
|
|
84
|
+
with _apply_lock:
|
|
85
|
+
_apply_state["applying"] = False
|
|
86
|
+
# The running process keeps the old version until restart;
|
|
87
|
+
# shells surface "restart to finish" off this value.
|
|
88
|
+
_apply_state["last_result"] = "success" if ok else "failed"
|
|
89
|
+
|
|
90
|
+
threading.Thread(target=worker, daemon=True, name="topos-shell-update").start()
|
|
91
|
+
return {"started": True}
|
|
@@ -217,9 +217,12 @@ async def list_entities(
|
|
|
217
217
|
):
|
|
218
218
|
"""Resolved entity registry (entity spine), sorted by mention count."""
|
|
219
219
|
from ..features.entities.reads import list_entities as _list
|
|
220
|
+
from ..features.lifecycle.blackhole_guard import owner_ui_guard
|
|
220
221
|
|
|
222
|
+
conn = _entities_conn()
|
|
221
223
|
return _list(
|
|
222
|
-
|
|
224
|
+
conn,
|
|
225
|
+
guard=owner_ui_guard(conn),
|
|
223
226
|
q=q,
|
|
224
227
|
entity_type=entity_type,
|
|
225
228
|
contacts_only=contacts_only,
|
|
@@ -253,11 +256,13 @@ async def get_entity_graph(
|
|
|
253
256
|
import asyncio
|
|
254
257
|
|
|
255
258
|
from ..features.entities.reads import entity_graph
|
|
259
|
+
from ..features.lifecycle.blackhole_guard import owner_ui_guard
|
|
256
260
|
|
|
257
261
|
conn = _entities_conn()
|
|
258
262
|
return await asyncio.to_thread(
|
|
259
263
|
entity_graph,
|
|
260
264
|
conn,
|
|
265
|
+
guard=owner_ui_guard(conn),
|
|
261
266
|
limit_nodes=limit_nodes,
|
|
262
267
|
limit_edges=limit_edges,
|
|
263
268
|
min_weight=min_weight,
|
|
@@ -347,8 +352,10 @@ async def get_entity(
|
|
|
347
352
|
):
|
|
348
353
|
"""Entity detail: aliases, connections, recent mentions, dossier (owner view)."""
|
|
349
354
|
from ..features.entities.reads import get_entity_detail
|
|
355
|
+
from ..features.lifecycle.blackhole_guard import owner_ui_guard
|
|
350
356
|
|
|
351
|
-
|
|
357
|
+
conn = _entities_conn()
|
|
358
|
+
detail = get_entity_detail(conn, entity_id, guard=owner_ui_guard(conn))
|
|
352
359
|
if detail is None:
|
|
353
360
|
raise HTTPException(status_code=404, detail=f"entity not found: {entity_id}")
|
|
354
361
|
return detail
|
|
@@ -458,6 +465,79 @@ async def exclude_entity_from_intelligence(
|
|
|
458
465
|
raise HTTPException(status_code=400, detail=str(exc))
|
|
459
466
|
|
|
460
467
|
|
|
468
|
+
class EntityBlackholeBody(BaseModel):
|
|
469
|
+
processing_tier: str = Field(default="secure", max_length=20)
|
|
470
|
+
note: Optional[str] = Field(default=None, max_length=500)
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
@router.post("/entities/{entity_id}/blackhole")
|
|
474
|
+
async def blackhole_entity(
|
|
475
|
+
entity_id: str,
|
|
476
|
+
body: EntityBlackholeBody = EntityBlackholeBody(),
|
|
477
|
+
_api_key: str = Depends(require_api_key),
|
|
478
|
+
):
|
|
479
|
+
"""Owner black hole: this entity is mine alone.
|
|
480
|
+
|
|
481
|
+
Nothing is deleted — the owner keeps full visibility. Every other caller
|
|
482
|
+
(third-party MCP agents, routines, grantees) is denied, and content
|
|
483
|
+
mentioning it may only be processed by the tier's secure model set.
|
|
484
|
+
Raises a rebuild-needed notification before the rebuild runs (D4).
|
|
485
|
+
"""
|
|
486
|
+
import asyncio
|
|
487
|
+
|
|
488
|
+
from ..features.lifecycle.blackhole import BlackholeStore
|
|
489
|
+
from ..features.lifecycle.blackhole_rebuild import rebuild_for_blackhole
|
|
490
|
+
|
|
491
|
+
conn = _entities_conn()
|
|
492
|
+
try:
|
|
493
|
+
result = BlackholeStore(conn).blackhole_entity(
|
|
494
|
+
entity_ref=entity_id,
|
|
495
|
+
processing_tier=body.processing_tier,
|
|
496
|
+
note=body.note,
|
|
497
|
+
)
|
|
498
|
+
except ValueError as exc:
|
|
499
|
+
raise HTTPException(status_code=400, detail=str(exc))
|
|
500
|
+
|
|
501
|
+
# D4: the notification above was raised first, so the owner already knows the
|
|
502
|
+
# hide is incomplete; now do the rebuild that makes it true. Non-owners are
|
|
503
|
+
# withheld the prose artifacts for the duration, so this running late is safe
|
|
504
|
+
# while it running silently would not be.
|
|
505
|
+
if not result.get("already_blackholed"):
|
|
506
|
+
result["rebuild"] = await asyncio.to_thread(rebuild_for_blackhole, conn, entity_id)
|
|
507
|
+
result["rebuild"] = result["rebuild"].as_dict()
|
|
508
|
+
return result
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
@router.delete("/entities/{entity_id}/blackhole")
|
|
512
|
+
async def unblackhole_entity(
|
|
513
|
+
entity_id: str,
|
|
514
|
+
_api_key: str = Depends(require_api_key),
|
|
515
|
+
):
|
|
516
|
+
"""Lift a black hole. Existing grants are not restored — normal permissions resume."""
|
|
517
|
+
from ..features.lifecycle.blackhole import BlackholeStore
|
|
518
|
+
|
|
519
|
+
return BlackholeStore(_entities_conn()).unblackhole_entity(entity_ref=entity_id)
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
@router.get("/blackholes")
|
|
523
|
+
async def list_blackholes(_api_key: str = Depends(require_api_key)):
|
|
524
|
+
"""The owner's off-limits list (mirrors the exclusions list in the drawer)."""
|
|
525
|
+
from ..features.lifecycle.blackhole import BlackholeStore
|
|
526
|
+
|
|
527
|
+
store = BlackholeStore(_entities_conn())
|
|
528
|
+
return {"blackholes": store.list(), "notifications": store.notifications(state="open")}
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
@router.post("/blackholes/notifications/{notification_id}/dismiss")
|
|
532
|
+
async def dismiss_blackhole_notification(
|
|
533
|
+
notification_id: str,
|
|
534
|
+
_api_key: str = Depends(require_api_key),
|
|
535
|
+
):
|
|
536
|
+
from ..features.lifecycle.blackhole import BlackholeStore
|
|
537
|
+
|
|
538
|
+
return {"dismissed": BlackholeStore(_entities_conn()).dismiss_notification(notification_id)}
|
|
539
|
+
|
|
540
|
+
|
|
461
541
|
@router.get("/facts")
|
|
462
542
|
async def list_facts(
|
|
463
543
|
predicate: Optional[str] = Query(default=None, max_length=80),
|
|
@@ -653,6 +733,23 @@ async def refresh_dimension_brief(
|
|
|
653
733
|
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
|
654
734
|
|
|
655
735
|
|
|
736
|
+
# --------------------------------------------------------------- timeline rollup
|
|
737
|
+
|
|
738
|
+
@router.get("/timeline/daily")
|
|
739
|
+
async def timeline_daily(
|
|
740
|
+
_api_key: str = Depends(require_api_key),
|
|
741
|
+
days: int = Query(90, ge=1, le=365),
|
|
742
|
+
):
|
|
743
|
+
"""Per-day lane counts + births + episodes (PLAN_TIMELINE_UNIFIED.md E1)."""
|
|
744
|
+
from ..core.state import get_db_connection
|
|
745
|
+
from ..features.timeline_rollup import timeline_daily_rollup
|
|
746
|
+
|
|
747
|
+
conn = get_db_connection()
|
|
748
|
+
if conn is None:
|
|
749
|
+
raise HTTPException(status_code=503, detail="database unavailable")
|
|
750
|
+
return timeline_daily_rollup(conn, days=days)
|
|
751
|
+
|
|
752
|
+
|
|
656
753
|
# --------------------------------------------------------------- attention triage
|
|
657
754
|
|
|
658
755
|
@router.get("/attention/dashboard")
|
|
@@ -669,3 +766,99 @@ async def attention_dashboard(
|
|
|
669
766
|
if conn is None:
|
|
670
767
|
raise HTTPException(status_code=503, detail="database unavailable")
|
|
671
768
|
return attention_dashboard_data(conn, days=days, include_titles=include_titles)
|
|
769
|
+
|
|
770
|
+
|
|
771
|
+
# --------------------------------------------------------------- complexity
|
|
772
|
+
|
|
773
|
+
@router.get("/complexity/summary")
|
|
774
|
+
async def complexity_summary(
|
|
775
|
+
_api_key: str = Depends(require_api_key),
|
|
776
|
+
recompute: bool = Query(False),
|
|
777
|
+
weeks: int = Query(12, ge=1, le=104),
|
|
778
|
+
window_days: int = Query(30, ge=1, le=3650),
|
|
779
|
+
half_life_days: Optional[float] = Query(None, ge=0.1, le=3650.0),
|
|
780
|
+
):
|
|
781
|
+
"""Data spine for the /data/complexity tab (PLAN_COMPLEXITY_DATA_PAGE.md).
|
|
782
|
+
|
|
783
|
+
Snapshot computation is CPU-bound (~1s cold on a live-size DB), so it runs
|
|
784
|
+
in a worker thread; warm calls serve the complexity_snapshots cache.
|
|
785
|
+
"""
|
|
786
|
+
import asyncio
|
|
787
|
+
|
|
788
|
+
from ..core.state import get_db_connection
|
|
789
|
+
from ..features.complexity.engine import get_complexity_summary
|
|
790
|
+
|
|
791
|
+
conn = get_db_connection()
|
|
792
|
+
if conn is None:
|
|
793
|
+
raise HTTPException(status_code=503, detail="database unavailable")
|
|
794
|
+
return await asyncio.to_thread(
|
|
795
|
+
get_complexity_summary,
|
|
796
|
+
conn,
|
|
797
|
+
recompute=recompute,
|
|
798
|
+
weeks=weeks,
|
|
799
|
+
window_days=window_days,
|
|
800
|
+
half_life_days=half_life_days,
|
|
801
|
+
)
|
|
802
|
+
|
|
803
|
+
|
|
804
|
+
@router.get("/complexity/timeline")
|
|
805
|
+
async def complexity_timeline(
|
|
806
|
+
_api_key: str = Depends(require_api_key),
|
|
807
|
+
recompute: bool = Query(False),
|
|
808
|
+
weeks: int = Query(12, ge=1, le=104),
|
|
809
|
+
):
|
|
810
|
+
import asyncio
|
|
811
|
+
|
|
812
|
+
from ..core.state import get_db_connection
|
|
813
|
+
from ..features.complexity.engine import get_shift_timeline
|
|
814
|
+
|
|
815
|
+
conn = get_db_connection()
|
|
816
|
+
if conn is None:
|
|
817
|
+
raise HTTPException(status_code=503, detail="database unavailable")
|
|
818
|
+
return await asyncio.to_thread(get_shift_timeline, conn, recompute=recompute, weeks=weeks)
|
|
819
|
+
|
|
820
|
+
|
|
821
|
+
@router.get("/complexity/topics/daily")
|
|
822
|
+
async def complexity_topics_daily(
|
|
823
|
+
_api_key: str = Depends(require_api_key),
|
|
824
|
+
days: int = Query(90, ge=1, le=365),
|
|
825
|
+
top: int = Query(10, ge=1, le=24),
|
|
826
|
+
):
|
|
827
|
+
"""Per-day supertopic shares — the braid's substrate (PLAN_TIMELINE_UNIFIED.md E2)."""
|
|
828
|
+
import asyncio
|
|
829
|
+
|
|
830
|
+
from ..core.state import get_db_connection
|
|
831
|
+
from ..features.complexity.topics_daily import topics_daily
|
|
832
|
+
|
|
833
|
+
conn = get_db_connection()
|
|
834
|
+
if conn is None:
|
|
835
|
+
raise HTTPException(status_code=503, detail="database unavailable")
|
|
836
|
+
return await asyncio.to_thread(topics_daily, conn, days=days, top=top)
|
|
837
|
+
|
|
838
|
+
|
|
839
|
+
@router.get("/complexity/influence")
|
|
840
|
+
async def complexity_influence(
|
|
841
|
+
_api_key: str = Depends(require_api_key),
|
|
842
|
+
recompute: bool = Query(False),
|
|
843
|
+
weeks: int = Query(12, ge=1, le=104),
|
|
844
|
+
top_k: int = Query(5, ge=1, le=50),
|
|
845
|
+
window_days: int = Query(90, ge=1, le=3650),
|
|
846
|
+
target: Optional[str] = Query(None, max_length=500),
|
|
847
|
+
):
|
|
848
|
+
import asyncio
|
|
849
|
+
|
|
850
|
+
from ..core.state import get_db_connection
|
|
851
|
+
from ..features.complexity.engine import get_influence_threads
|
|
852
|
+
|
|
853
|
+
conn = get_db_connection()
|
|
854
|
+
if conn is None:
|
|
855
|
+
raise HTTPException(status_code=503, detail="database unavailable")
|
|
856
|
+
return await asyncio.to_thread(
|
|
857
|
+
get_influence_threads,
|
|
858
|
+
conn,
|
|
859
|
+
recompute=recompute,
|
|
860
|
+
weeks=weeks,
|
|
861
|
+
top_k=top_k,
|
|
862
|
+
window_days=window_days,
|
|
863
|
+
target=target,
|
|
864
|
+
)
|
|
@@ -253,8 +253,12 @@ async def get_uma_messages(
|
|
|
253
253
|
)
|
|
254
254
|
items = _get_messages_from_db(conn, effective_dataset_id, limited, offset, allowed_tables=allowed_tables)
|
|
255
255
|
try:
|
|
256
|
+
# UMA data proxy = the grantee HTTP lane; filter unconditionally.
|
|
257
|
+
from ..features.lifecycle.blackhole_guard import BlackholeGuard, CallerClass
|
|
258
|
+
|
|
256
259
|
items, uma_contact_sidecar = apply_message_contact_pipeline(
|
|
257
260
|
items,
|
|
261
|
+
blackhole_guard=BlackholeGuard(conn, caller_class=CallerClass.GRANTEE),
|
|
258
262
|
conn=conn,
|
|
259
263
|
dataset_id=effective_dataset_id,
|
|
260
264
|
allowed_scopes=allowed_scopes,
|
|
@@ -5,6 +5,7 @@ import importlib.util
|
|
|
5
5
|
import logging
|
|
6
6
|
import os
|
|
7
7
|
import sys
|
|
8
|
+
import threading
|
|
8
9
|
|
|
9
10
|
from fastapi import FastAPI
|
|
10
11
|
from fastapi.middleware.cors import CORSMiddleware
|
|
@@ -47,6 +48,7 @@ from .api import (
|
|
|
47
48
|
home_chat as home_chat_routes,
|
|
48
49
|
privacy_disclose as privacy_disclose_routes,
|
|
49
50
|
signal as signal_routes,
|
|
51
|
+
shell as shell_routes,
|
|
50
52
|
tool_index as tool_index_routes,
|
|
51
53
|
upgrades as upgrades_routes,
|
|
52
54
|
)
|
|
@@ -99,6 +101,7 @@ app.add_middleware(
|
|
|
99
101
|
)
|
|
100
102
|
|
|
101
103
|
app.include_router(health_routes.router)
|
|
104
|
+
app.include_router(shell_routes.router)
|
|
102
105
|
app.include_router(upgrades_routes.router)
|
|
103
106
|
app.include_router(local_mcp_routes.router)
|
|
104
107
|
app.include_router(llm_routes.router)
|
|
@@ -171,19 +174,9 @@ async def startup_event() -> None:
|
|
|
171
174
|
logger.info("Stage 9 migrations applied at startup: %d renames", len(result["applied"]))
|
|
172
175
|
except Exception as e:
|
|
173
176
|
logger.debug("Stage 9 migrations at startup (non-fatal): %s", e)
|
|
174
|
-
# Upgrade runner
|
|
175
|
-
#
|
|
176
|
-
#
|
|
177
|
-
# stale derived data meanwhile. Fresh installs stamp-and-skip.
|
|
178
|
-
try:
|
|
179
|
-
from .core.state import get_db_connection as _get_conn_for_upgrades
|
|
180
|
-
from .upgrades.runner import start_background as _start_upgrades
|
|
181
|
-
|
|
182
|
-
_upgrade_conn = state.db_conn if state.db_conn is not None else _get_conn_for_upgrades()
|
|
183
|
-
if _upgrade_conn is not None:
|
|
184
|
-
_start_upgrades(_upgrade_conn)
|
|
185
|
-
except Exception as e:
|
|
186
|
-
logger.warning("Upgrade runner at startup failed (non-fatal): %s", e)
|
|
177
|
+
# Upgrade runner is armed later — after control-plane / local readiness —
|
|
178
|
+
# so the React UI can fetch bootstrap data before enrichment reprocess
|
|
179
|
+
# contends for SQLite / Ollama / MPS. See _arm_upgrade_runner below.
|
|
187
180
|
try:
|
|
188
181
|
from .core.state import get_db_connection as _get_conn_for_pipeline
|
|
189
182
|
from .pipeline.job_runner import recover_pipeline_jobs, start_pipeline_worker
|
|
@@ -295,6 +288,41 @@ async def startup_event() -> None:
|
|
|
295
288
|
start_runtime_update_monitor()
|
|
296
289
|
start_update_hotkey_listener()
|
|
297
290
|
|
|
291
|
+
# Upgrade runner: plan/stamp cheaply, but defer heavy re-derivation until the
|
|
292
|
+
# UI can bootstrap (CP connected + grace). Fresh installs stamp-and-skip.
|
|
293
|
+
try:
|
|
294
|
+
from .core.state import get_db_connection as _get_conn_for_upgrades
|
|
295
|
+
from .upgrades.runner import (
|
|
296
|
+
ready_timeout_seconds as _upgrade_ready_timeout,
|
|
297
|
+
start_background as _start_upgrades,
|
|
298
|
+
ui_grace_seconds as _upgrade_ui_grace,
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
_upgrade_conn = state.db_conn if state.db_conn is not None else _get_conn_for_upgrades()
|
|
302
|
+
if _upgrade_conn is not None:
|
|
303
|
+
_upgrade_ready = threading.Event()
|
|
304
|
+
_start_upgrades(
|
|
305
|
+
_upgrade_conn,
|
|
306
|
+
ready_event=_upgrade_ready,
|
|
307
|
+
ui_grace_s=_upgrade_ui_grace(),
|
|
308
|
+
ready_timeout_s=_upgrade_ready_timeout(),
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
async def _signal_upgrade_ui_ready() -> None:
|
|
312
|
+
try:
|
|
313
|
+
if state.control_plane_client is not None:
|
|
314
|
+
await state.control_plane_client.wait_until_connected(
|
|
315
|
+
timeout_s=_upgrade_ready_timeout()
|
|
316
|
+
)
|
|
317
|
+
except Exception as ready_exc: # noqa: BLE001
|
|
318
|
+
logger.debug("Upgrade UI-ready wait ended: %s", ready_exc)
|
|
319
|
+
finally:
|
|
320
|
+
_upgrade_ready.set()
|
|
321
|
+
|
|
322
|
+
asyncio.create_task(_signal_upgrade_ui_ready())
|
|
323
|
+
except Exception as e:
|
|
324
|
+
logger.warning("Upgrade runner at startup failed (non-fatal): %s", e)
|
|
325
|
+
|
|
298
326
|
if settings.enable_sync and settings.topos_user_id:
|
|
299
327
|
state.sync_client = SyncClient(
|
|
300
328
|
sync_url=settings.get_sync_url(),
|
|
Binary file
|
|
Binary file
|