topos-node 1.3.3__tar.gz → 1.3.4__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.3/topos_node.egg-info → topos_node-1.3.4}/PKG-INFO +1 -1
- {topos_node-1.3.3 → topos_node-1.3.4}/pyproject.toml +1 -1
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/__version__.py +2 -2
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/enrichment.py +72 -14
- topos_node-1.3.4/topos/api/upgrades.py +55 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/cli/commands.py +22 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/config/settings.py +6 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/api_models.py +5 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/config.py +31 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/catalog.py +13 -1
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/derived_tables.py +123 -84
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/job_writer.py +36 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/models/mvp_defaults.py +27 -0
- topos_node-1.3.4/topos/protocol/handled_message_types.json +208 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/llm/openai.py +49 -3
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/local.py +44 -1
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/adapters/sqlite/stores.py +100 -43
- topos_node-1.3.4/topos/storage/db/migrations/enrichment_spec_version_v1.py +50 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/registry.py +6 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/registry_checksums.json +1 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/upgrades/__init__.py +6 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/upgrades/manifests.json +19 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/upgrades/runner.py +183 -7
- {topos_node-1.3.3 → topos_node-1.3.4/topos_node.egg-info}/PKG-INFO +1 -1
- {topos_node-1.3.3 → topos_node-1.3.4}/topos_node.egg-info/SOURCES.txt +1 -0
- topos_node-1.3.3/topos/api/upgrades.py +0 -30
- topos_node-1.3.3/topos/protocol/handled_message_types.json +0 -207
- {topos_node-1.3.3 → topos_node-1.3.4}/LICENSE +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/MANIFEST.in +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/README.md +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/setup.cfg +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/shared/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/shared/filtering.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/shared/schema_registry.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/tests/test_extensions.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/tests/test_llm_integrations_storage.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/tests/test_protocol_handled_types.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/analytics/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/analytics/duckdb_adapter.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/analytics/messenger_communities.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/analytics/messenger_graph.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/analytics/messenger_labels.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/analytics/profiles.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/analytics/query_engine.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/analytics/raw_queries.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/analytics.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/app_registry.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/backup.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/compute_remote.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/conversation_context.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/data_commit.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/data_explorer_table_prefs.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/database_explorer.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/db.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/device.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/engine_run.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/enrichment_lab.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/facts_llm_config.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/filter_lab.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/health.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/home_chat.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/ingestion_api.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/ingestion_compat.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/ingestion_sources.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/intelligence_lifecycle.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/llm.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/local_mcp.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/messenger_analytics.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/privacy_disclose.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/query_api.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/runtime_bootstrap.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/sanitization_ollama_config.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/shell.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/signal.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/signal_extraction_config.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/source_install.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/source_scrub.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/sources.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/sources_overview.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/sync.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/tool_index.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/ui_config.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/uma_data.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/usage.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/api/user_identity.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/app.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/auth.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/base.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/browser_activity_mapper.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/chatgpt_mapper.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/demo_mappers.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/documents_mapper.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/github_activity_mapper.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/google_calendar_mapper.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/grok_mapper.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/mappers/messenger_mapper.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/models.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/canonicalization/resolver.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/cli/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/cli/__main__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/cli/assets/topos_blk_rounded.png +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/cli/assets/topos_white.png +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/cli/tray.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/config/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/config/conversation_context_llm.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/config/facts_llm.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/config/sanitization_ollama.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/config/signal_extraction.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/config/uvicorn_logging.json +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/contacts/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/contacts/identity.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/control_plane_client.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/connection_resilience.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/device_helpers.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/errors.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/events.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/common.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/complexity.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/contacts_import.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/database_explorer.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/device.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/enrichment.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/enrichment_lab.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/filter_lab.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/home_chat.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/ingest.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/messages.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/messenger_analytics.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/query.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/registry.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/routines.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/signal_features.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/sources.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/timeline_daily.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/tool_index.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/handlers/uma.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/logging.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/metrics.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/routine_access.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/startup_banner.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/state.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/table_layers.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/core/types.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/data_explorer_row_delete.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/data_explorer_table_prefs.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/data_explorer_tables.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/disclosure/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/disclosure/canonical_writer.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/disclosure/content_policy.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/disclosure/field_registry.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/disclosure/privacy_layer.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/disclosure/tier.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/base.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/generative_prompts.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/generative_response.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/huggingface.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/ollama.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/openai.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/openai_compatible.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/redpill.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/backends/stub.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/client.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/engine.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/intake.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/memory_utils.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/model_cache.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/pipeline_memory.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/queue_manager.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/registration.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/result_formatter.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/router.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/scoped_token.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/tasks.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/transport.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/usage_guard.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/usage_observation.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/engine/validator.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/base.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/_batch_limits.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/_engine_runner.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/attention_triage_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/availability_scores_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/brief_fallback.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/complexity_snapshot_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/dimension_summary_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/embeddings_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/emo_27_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/entities_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/fact_extraction_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/goal_extraction_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/pii_redaction_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/relationship_edges_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/sentiment_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/statistics_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/timeline_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/topic_clusters_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/topics_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/url_classification_core.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/url_classification_enrichment_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/canonical/url_classification_signal_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/raw/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/raw/attachments_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/raw/language_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/raw/time_normalization_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/jobs/raw/tool_calls_job.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/model_overrides.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/models/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/models/manager.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/models/registry.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/models/versioning.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/orchestrator.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/processor.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/progress_bar.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/registry_contract.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/signal_derivation_config.json +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/source_overrides.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment/website_classifier.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment_lab/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment_lab/bundles.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment_lab/model_resolve.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment_lab/schema.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment_lab/service.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment_lab/store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/enrichment_lab/worker.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/evals/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/evals/enrichment_eval.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/extensions.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/canonical.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/engine.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/entropy.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/focus.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/graph_metrics.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/influence.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/projection.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/snapshots.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/topic_merge.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/topics.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/topics_daily.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/complexity/volatility.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/consolidation.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/declared_mappings.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/dossier.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/edges.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/fact_materializer.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/graph_enrichers.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/graph_refresh.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/graph_search.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/linking.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/maintenance.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/reads.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/entities/resolver.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/facts/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/facts/extract.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/facts/llm_extract.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/facts/reads.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/facts/store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/facts/verdicts.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/fit/evaluator.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/fit/opportunity_types.json +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/lifecycle/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/lifecycle/blackhole.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/lifecycle/blackhole_guard.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/lifecycle/blackhole_llm.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/lifecycle/blackhole_rebuild.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/lifecycle/derived_scrub.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/lifecycle/exclusions.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/lifecycle/gc.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/provenance/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/provenance/posture.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/provenance/roles.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/brief_canonical_loader.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/brief_ontology.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/brief_renderer.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/brief_schemas.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/chunking.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/cluster_labels.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/conversation_context.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/data_health.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/definitions/brief_ontologies.json +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/definitions/intentions.json +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/definitions/profile.json +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/definitions/relationships.json +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/definitions/schema/dimension_definition.schema.json +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/definitions/time.json +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/definitions/work.json +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/dimension_briefs.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/dimension_definition_loader.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/dimension_profiles.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/dimension_registry.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/embed_context.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/extraction/artifact_router.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/extraction/artifact_store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/extraction/rule_extractors.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/graph_sanitize.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/hybrid_search.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/incremental_clustering.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/model_recommendations.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/query_embed_cache.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/schemas.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/service.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/signal_object_store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/source_hydration.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/structured_signal.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/tool_index.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/topic_clustering.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/typed_stores/aggregates.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/typed_stores/commitments.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/typed_stores/rhythm.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/typed_stores/scope_materializer.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/vector_codec.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/vector_math.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/signal/vector_settings.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/stats/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/stats/definitions.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/stats/engine.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/stats/fold.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/stats/insights.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/timeline_projection.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/timeline_rollup.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/triage/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/triage/badges.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/triage/daily.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/triage/dashboard.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/triage/instruments.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/triage/intents.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/features/triage/readiness.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/filter_lab/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/filter_lab/bundles.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/filter_lab/schema.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/filter_lab/service.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/filter_lab/store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/filter_lab/worker.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/home_chat/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/home_chat/schema.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/home_chat/store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/hosted_pool_lease.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/canonical_pipeline.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/checkpoints/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/checkpoints/checkpoint_store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/checkpoints/sqlite_checkpoint_store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/inbox_crypto.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/inbox_drain.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/ingest_helpers.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/jobs.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/journal_location_fanout.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/journal_time_log_normalize.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/local_sync.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/log_preview.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/manager.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parser.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/base.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/browser_parser.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/calendar_parser.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/chatgpt_conversation_flattener.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/chatgpt_parser.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/demo_file_parsers.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/documents_parser.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/github_activity_parser.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/google_calendar_parser.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/grok_parser.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/messenger_parser.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/parsers/voxterm_parser.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/progress.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/reprocess.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/sources/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/sources/base.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/sources/calendar.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/sources/chatgpt.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/sources/contact_importers.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/sources/grok.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/sources/imessage_reader.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/sources/signal_export_parser.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/sources/signal_reader.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/state_machine.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/triggers/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/triggers/file_trigger.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/triggers/sqlite_trigger.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/usage_inbox_dedupe.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/validation/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/validation/base.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/validation/schema_registry.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/ingestion/validation/schema_validator.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/lineage/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/lineage/provenance.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/lineage/tracker.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/llm_integrations_storage.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/mcp_stdio_proxy.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/observability/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/observability/alerts.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/observability/metrics.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/observability/tracing.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/openai_client.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/pipeline/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/pipeline/audit.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/pipeline/envelope.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/pipeline/job_runner.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/pipeline/job_store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/pipeline/stages.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/pipeline/stub_enqueue.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/projections/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/projections/vector_index/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/projections/vector_index/base.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/projections/vector_index/builders.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/projections/vector_index/health_checks.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/protocol/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/audit.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/ddr.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/disclosure.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/fingerprint.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/game_layer.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/grant_cache.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/inference.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/intent.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/manifest.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/manifest_validation.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/minimizer.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/negotiation.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/pipeline.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/planner.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/retrieval.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/runtime.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/scope_registry.json +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/scope_registry_loader.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/session.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/session_utils.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/source_generation.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/truth_facts.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/truth_prompts.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/turn_classifier.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/types.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/verify.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/query/verify_modes.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/rate_limit.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/routines/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/routines/schema.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/routines/store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/runtime_housekeeping.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/runtime_shutdown.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/runtime_update.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/sanitization/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/sanitization/nsfw_classifier.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/sanitization/ollama_transforms.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/sanitization/prewarm.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/sanitization/privacy_filter.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/scope_resolution.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/container.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/embeddings/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/embeddings/base.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/embeddings/local.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/embeddings/remote.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/interfaces.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/llm/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/llm/base.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/services/postgres.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/sources/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/sources/bundled_canonical_triples.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/sources/canonical_signal_defaults.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/sources/definitions.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/sources/install_service.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/sources/registry.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/sources/runtime_install.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/sources/scrub_attribution.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/sources/scrub_service.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/startup_banner.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/adapters/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/adapters/factory.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/adapters/fakes.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/adapters/postgres/stores.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/adapters/protocols.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/adapters/sqlite/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/adapters/sqlite/vector_search.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/activity_tables.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/ai_chat/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/ai_chat/canonicalizer.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/ai_chat/mapper.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/ai_chat/model.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/ai_chat/tables.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/calendar_contacts_tables.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/canonical_store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/conversations_tables.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/mapping_store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/canonical/postgres.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/client.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/connection_tuning.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/activity_events_content_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/actor_role_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/attention_triage_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/attention_triage_v2.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/backup.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/calendar_events_scheduling_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/canonical_address_book_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/canonical_disclosure_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/canonical_nsfw_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/complexity_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/conversation_context_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/derivation_ledger_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/documents_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/entity_blackhole_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/entity_edges_validity_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/episodes_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/extraction_artifacts.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/journal_entries_duration_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/journal_entries_ends_at_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/journal_entries_people_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/journal_entries_place_name_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/journal_entries_starts_at_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/pipeline_jobs_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/remediation_person_model.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/scope_source_generation.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/signal_dimension_backfill_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/signal_dimension_harness.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/signal_objects.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/signal_objects_period_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/signal_objects_updated_by_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/stage9_column_renames.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/vector_storage_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/vector_storage_v2.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/vector_storage_v3.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/vector_storage_v4.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_clusters_v2.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_entities_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_entity_review_v2.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_facts_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_lifecycle_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_phase0.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_phase1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_phase4_messages_cutover.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_phase5_topic_clusters.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_phase6_dimension_briefs.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_query_quality.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_mvp_topic_clusters_coordination.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_stats_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/migrations/wiki_timeline_v1.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/paths.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/postgres.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/schema.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/storage_breakdown.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/db/write_gate.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/enrichment/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/enrichment/canonical_enrichment_store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/enrichment/raw_enrichment_store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/normalized/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/normalized/normalized_store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/oplog/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/oplog/decision.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/oplog/oplog_store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/oplog/postgres.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/person/identity_resolver.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/projections/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/projections/index_ops_store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/projections/vector_index_store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/raw/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/raw/browser_flat_tables.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/raw/file_store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/raw/raw_store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/raw/raw_tables_manager.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/raw/sqlite_raw_store.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/security/encryption.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/signal_identity.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/source_settings.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/storage/user_identity.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/sync/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/sync/client.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/sync_handlers.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/testing/__init__.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/testing/lifespan.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/uma_contact_enrichment.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/uma_filters.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/uma_resource_id.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/uma_rpt.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/utils/base_object.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos/websocket_client.py +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos_node.egg-info/dependency_links.txt +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos_node.egg-info/entry_points.txt +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/topos_node.egg-info/requires.txt +0 -0
- {topos_node-1.3.3 → topos_node-1.3.4}/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.4"
|
|
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"
|
|
@@ -572,19 +572,33 @@ async def _generic_backfill_core(
|
|
|
572
572
|
"errors": [],
|
|
573
573
|
}
|
|
574
574
|
else:
|
|
575
|
+
from ..enrichment.catalog import catalog_spec_version
|
|
576
|
+
|
|
575
577
|
coverage_table = coverage_table_for_job(job_name)
|
|
576
578
|
if coverage_table and _table_exists(db_conn, coverage_table):
|
|
577
579
|
cols = _table_columns(db_conn, coverage_table)
|
|
578
580
|
id_col = "message_id" if "message_id" in cols else "record_id"
|
|
579
581
|
if "source_id" in cols and id_col in cols:
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
(
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
582
|
+
min_spec = catalog_spec_version(job_name)
|
|
583
|
+
if "spec_version" in cols:
|
|
584
|
+
done = {
|
|
585
|
+
str(row[0])
|
|
586
|
+
for row in db_conn.execute(
|
|
587
|
+
f"SELECT DISTINCT {id_col} FROM {coverage_table} "
|
|
588
|
+
f"WHERE source_id=? AND COALESCE(spec_version, 0) >= ?",
|
|
589
|
+
(source_id, min_spec),
|
|
590
|
+
).fetchall()
|
|
591
|
+
if row[0]
|
|
592
|
+
}
|
|
593
|
+
else:
|
|
594
|
+
done = {
|
|
595
|
+
str(row[0])
|
|
596
|
+
for row in db_conn.execute(
|
|
597
|
+
f"SELECT DISTINCT {id_col} FROM {coverage_table} WHERE source_id=?",
|
|
598
|
+
(source_id,),
|
|
599
|
+
).fetchall()
|
|
600
|
+
if row[0]
|
|
601
|
+
}
|
|
588
602
|
records = [r for r in records if _record_identifier(r) not in done]
|
|
589
603
|
|
|
590
604
|
if isinstance(limit, int) and limit > 0:
|
|
@@ -650,13 +664,45 @@ async def _generic_backfill_core(
|
|
|
650
664
|
}
|
|
651
665
|
|
|
652
666
|
|
|
653
|
-
def _get_enriched_message_ids(
|
|
654
|
-
|
|
667
|
+
def _get_enriched_message_ids(
|
|
668
|
+
table_name: str,
|
|
669
|
+
conn,
|
|
670
|
+
*,
|
|
671
|
+
min_spec_version: Optional[int] = None,
|
|
672
|
+
) -> set[str]:
|
|
673
|
+
"""Ids that already satisfy coverage for ``table_name``.
|
|
674
|
+
|
|
675
|
+
When ``min_spec_version`` is set and the table has ``spec_version``, only
|
|
676
|
+
rows with ``COALESCE(spec_version, 0) >= min_spec_version`` count as done
|
|
677
|
+
(PLAN M3 stale predicate). Otherwise presence-only.
|
|
678
|
+
"""
|
|
655
679
|
if not conn:
|
|
656
680
|
return set()
|
|
657
681
|
try:
|
|
658
|
-
|
|
659
|
-
|
|
682
|
+
cols = _table_columns(conn, table_name)
|
|
683
|
+
if not cols:
|
|
684
|
+
return set()
|
|
685
|
+
if "message_id" in cols and "record_id" in cols:
|
|
686
|
+
id_expr = "COALESCE(message_id, record_id)"
|
|
687
|
+
elif "message_id" in cols:
|
|
688
|
+
id_expr = "message_id"
|
|
689
|
+
elif "record_id" in cols:
|
|
690
|
+
id_expr = "record_id"
|
|
691
|
+
else:
|
|
692
|
+
return set()
|
|
693
|
+
if (
|
|
694
|
+
min_spec_version is not None
|
|
695
|
+
and "spec_version" in cols
|
|
696
|
+
and isinstance(min_spec_version, int)
|
|
697
|
+
):
|
|
698
|
+
cursor = conn.execute(
|
|
699
|
+
f"SELECT DISTINCT {id_expr} FROM {table_name} "
|
|
700
|
+
f"WHERE COALESCE(spec_version, 0) >= ?",
|
|
701
|
+
(int(min_spec_version),),
|
|
702
|
+
)
|
|
703
|
+
else:
|
|
704
|
+
cursor = conn.execute(f"SELECT DISTINCT {id_expr} FROM {table_name}")
|
|
705
|
+
return {str(row[0]) for row in cursor.fetchall() if row[0]}
|
|
660
706
|
except Exception as e:
|
|
661
707
|
logger.warning("Failed to query enriched message IDs from %s: %s", table_name, e)
|
|
662
708
|
return set()
|
|
@@ -758,12 +804,18 @@ async def _find_unprocessed_messages(
|
|
|
758
804
|
db_conn, source_def, dataset_id=dataset_id
|
|
759
805
|
)
|
|
760
806
|
if generic_messages:
|
|
807
|
+
from ..enrichment.catalog import catalog_spec_version
|
|
808
|
+
|
|
761
809
|
enriched: Optional[set[str]] = None
|
|
762
810
|
job_table_map = {job.get_job_name(): job.get_derived_table() for job in CANONICAL_JOBS}
|
|
763
811
|
for job_name in jobs_to_check:
|
|
764
812
|
table_name = job_table_map.get(job_name)
|
|
765
813
|
if table_name:
|
|
766
|
-
job_ids = _get_enriched_message_ids(
|
|
814
|
+
job_ids = _get_enriched_message_ids(
|
|
815
|
+
table_name,
|
|
816
|
+
db_conn,
|
|
817
|
+
min_spec_version=catalog_spec_version(job_name),
|
|
818
|
+
)
|
|
767
819
|
enriched = job_ids if enriched is None else (enriched & job_ids)
|
|
768
820
|
else:
|
|
769
821
|
logger.warning("Unknown enrichment job: %s (skipping check)", job_name)
|
|
@@ -947,6 +999,8 @@ async def _find_unprocessed_messages(
|
|
|
947
999
|
# row for it (intersection). The previous union behavior skipped messages
|
|
948
1000
|
# that had been enriched by any single job, leaving partial enrichment
|
|
949
1001
|
# permanently un-backfillable.
|
|
1002
|
+
from ..enrichment.catalog import catalog_spec_version
|
|
1003
|
+
|
|
950
1004
|
enriched_ids: Optional[set[str]] = None
|
|
951
1005
|
# Create a mapping from job name to table name using the job registry
|
|
952
1006
|
job_to_table = {job.get_job_name(): job.get_derived_table() for job in CANONICAL_JOBS}
|
|
@@ -954,7 +1008,11 @@ async def _find_unprocessed_messages(
|
|
|
954
1008
|
for job_name in jobs_to_check:
|
|
955
1009
|
table_name = job_to_table.get(job_name)
|
|
956
1010
|
if table_name:
|
|
957
|
-
job_ids = _get_enriched_message_ids(
|
|
1011
|
+
job_ids = _get_enriched_message_ids(
|
|
1012
|
+
table_name,
|
|
1013
|
+
db_conn,
|
|
1014
|
+
min_spec_version=catalog_spec_version(job_name),
|
|
1015
|
+
)
|
|
958
1016
|
enriched_ids = job_ids if enriched_ids is None else (enriched_ids & job_ids)
|
|
959
1017
|
else:
|
|
960
1018
|
logger.warning("Unknown enrichment job: %s (skipping check)", job_name)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Upgrade status + consent surface for schema/derived migration steps.
|
|
2
|
+
|
|
3
|
+
The UI shows "Upgrading your intelligence…" while auto steps run, and prompts
|
|
4
|
+
for ``pending_consent`` slow-lane steps (PLAN_NODE_RELEASE_MIGRATIONS M3).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any, Dict, Optional
|
|
10
|
+
|
|
11
|
+
from fastapi import APIRouter, Depends, HTTPException
|
|
12
|
+
from pydantic import BaseModel, Field
|
|
13
|
+
|
|
14
|
+
from ..auth import require_api_key
|
|
15
|
+
|
|
16
|
+
router = APIRouter()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _status_payload() -> Dict[str, Any]:
|
|
20
|
+
from ..core.state import get_db_connection
|
|
21
|
+
from ..features.entities.graph_refresh import status as refresh_status
|
|
22
|
+
from ..upgrades.runner import runner_status
|
|
23
|
+
|
|
24
|
+
conn = get_db_connection()
|
|
25
|
+
upgrade = runner_status(conn) if conn is not None else {"enabled": False, "error": "no database"}
|
|
26
|
+
return {"upgrade": upgrade, "graph_refresh": refresh_status()}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@router.get("/v1/upgrade/status", dependencies=[Depends(require_api_key)])
|
|
30
|
+
async def get_upgrade_status() -> Dict[str, Any]:
|
|
31
|
+
return _status_payload()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class UpgradeConsentBody(BaseModel):
|
|
35
|
+
step_id: str = Field(..., min_length=1)
|
|
36
|
+
# Optional: run the step immediately after consent (default true).
|
|
37
|
+
run_now: bool = True
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@router.post("/v1/upgrade/consent", dependencies=[Depends(require_api_key)])
|
|
41
|
+
async def post_upgrade_consent(body: UpgradeConsentBody) -> Dict[str, Any]:
|
|
42
|
+
from ..core.state import get_db_connection
|
|
43
|
+
from ..upgrades.runner import consent_upgrade_step, run_pending_upgrades
|
|
44
|
+
|
|
45
|
+
conn = get_db_connection()
|
|
46
|
+
if conn is None:
|
|
47
|
+
raise HTTPException(status_code=503, detail="database unavailable")
|
|
48
|
+
try:
|
|
49
|
+
result = consent_upgrade_step(conn, body.step_id.strip())
|
|
50
|
+
except ValueError as exc:
|
|
51
|
+
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
|
52
|
+
run_result: Optional[Dict[str, Any]] = None
|
|
53
|
+
if body.run_now:
|
|
54
|
+
run_result = run_pending_upgrades(conn)
|
|
55
|
+
return {"status": "ok", "consent": result, "run": run_result, **_status_payload()}
|
|
@@ -307,6 +307,28 @@ def main(db_path, topos_key, set_topos_key, discover, port, host, skip_update_ch
|
|
|
307
307
|
start_background_housekeeping()
|
|
308
308
|
|
|
309
309
|
_emit_startup_banner(host=host, port=port)
|
|
310
|
+
try:
|
|
311
|
+
from topos.core.state import get_db_connection
|
|
312
|
+
from topos.upgrades.runner import runner_status
|
|
313
|
+
|
|
314
|
+
_conn = get_db_connection()
|
|
315
|
+
if _conn is not None:
|
|
316
|
+
_pending = (runner_status(_conn).get("pending_consent_steps") or [])
|
|
317
|
+
if _pending:
|
|
318
|
+
click.echo("")
|
|
319
|
+
click.echo("Upgrade steps waiting for your consent:")
|
|
320
|
+
for step in _pending:
|
|
321
|
+
click.echo(
|
|
322
|
+
f" • {step.get('id')}: {step.get('title') or step.get('why') or ''}"
|
|
323
|
+
f" (cost={step.get('cost') or 'slow'})"
|
|
324
|
+
)
|
|
325
|
+
click.echo(
|
|
326
|
+
"Approve with: POST /v1/upgrade/consent {\"step_id\": \"...\"} "
|
|
327
|
+
"or the Engine settings banner."
|
|
328
|
+
)
|
|
329
|
+
click.echo("")
|
|
330
|
+
except Exception:
|
|
331
|
+
pass
|
|
310
332
|
|
|
311
333
|
from topos.cli import tray as tray_module
|
|
312
334
|
|
|
@@ -140,6 +140,12 @@ class Settings(BaseSettings):
|
|
|
140
140
|
sanitization_ollama_host: Optional[str] = Field(None, env="SANITIZATION_OLLAMA_HOST")
|
|
141
141
|
sanitization_ollama_default_model: str = Field("llama3.2", env="SANITIZATION_OLLAMA_DEFAULT_MODEL")
|
|
142
142
|
sanitization_ollama_timeout_sec: float = Field(120.0, env="SANITIZATION_OLLAMA_TIMEOUT_SEC")
|
|
143
|
+
# llm_generation / routine hops — must cover local thinking models. Do NOT
|
|
144
|
+
# reuse sanitization_ollama_timeout_sec (120s): that cuts digest synthesis
|
|
145
|
+
# mid-flight and surfaces as "Ollama unreachable".
|
|
146
|
+
engine_ollama_generate_timeout_sec: float = Field(
|
|
147
|
+
300.0, env="ENGINE_OLLAMA_GENERATE_TIMEOUT_SEC"
|
|
148
|
+
)
|
|
143
149
|
ollama_list_timeout_sec: float = Field(10.0, env="OLLAMA_LIST_TIMEOUT_SEC")
|
|
144
150
|
sanitization_ollama_auto_pull: bool = Field(True, env="SANITIZATION_OLLAMA_AUTO_PULL")
|
|
145
151
|
sanitization_ollama_max_input_chars: int = Field(8000, env="SANITIZATION_OLLAMA_MAX_INPUT_CHARS")
|
|
@@ -108,6 +108,11 @@ class DeviceInfoResponse(BaseModel):
|
|
|
108
108
|
oplog_bytes_since_last_sync: Optional[int] = None
|
|
109
109
|
database_size_bytes: Optional[int] = None
|
|
110
110
|
storage_breakdown: Optional[Dict[str, Any]] = None
|
|
111
|
+
# Upgrade runner summary (PLAN_NODE_RELEASE_MIGRATIONS M5). Optional for
|
|
112
|
+
# older clients / hosted paths without a SQLite upgrade ledger.
|
|
113
|
+
upgrade_baseline: Optional[str] = None
|
|
114
|
+
pending_upgrade_steps: Optional[List[str]] = None
|
|
115
|
+
pending_consent_steps: Optional[List[Any]] = None
|
|
111
116
|
|
|
112
117
|
|
|
113
118
|
class DeviceNameRequest(BaseModel):
|
|
@@ -467,6 +467,37 @@ async def handle_get_upgrade_status(message):
|
|
|
467
467
|
return {"id": req_id, "status": "error", "error": str(exc)}
|
|
468
468
|
|
|
469
469
|
|
|
470
|
+
@handles("consent_upgrade_step")
|
|
471
|
+
async def handle_consent_upgrade_step(message):
|
|
472
|
+
"""Approve a pending_consent upgrade step (PLAN M3)."""
|
|
473
|
+
req_id = message.get("id")
|
|
474
|
+
if not req_id:
|
|
475
|
+
return None
|
|
476
|
+
payload = message.get("payload") or {}
|
|
477
|
+
step_id = str(payload.get("step_id") or "").strip()
|
|
478
|
+
if not step_id:
|
|
479
|
+
return {"id": req_id, "status": "error", "error": "step_id required"}
|
|
480
|
+
run_now = bool(payload.get("run_now", True))
|
|
481
|
+
try:
|
|
482
|
+
from ...core.state import get_db_connection
|
|
483
|
+
from ...upgrades.runner import consent_upgrade_step, run_pending_upgrades
|
|
484
|
+
|
|
485
|
+
conn = get_db_connection()
|
|
486
|
+
if conn is None:
|
|
487
|
+
return {"id": req_id, "status": "error", "error": "database unavailable"}
|
|
488
|
+
result = consent_upgrade_step(conn, step_id)
|
|
489
|
+
run_result = run_pending_upgrades(conn) if run_now else None
|
|
490
|
+
return {
|
|
491
|
+
"id": req_id,
|
|
492
|
+
"status": "ok",
|
|
493
|
+
"payload": {"consent": result, "run": run_result},
|
|
494
|
+
}
|
|
495
|
+
except ValueError as exc:
|
|
496
|
+
return {"id": req_id, "status": "error", "error": str(exc)}
|
|
497
|
+
except Exception as exc: # noqa: BLE001
|
|
498
|
+
return {"id": req_id, "status": "error", "error": str(exc)}
|
|
499
|
+
|
|
500
|
+
|
|
470
501
|
@handles("get_exposure_profile_config")
|
|
471
502
|
async def handle_get_exposure_profile_config(message: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
472
503
|
req_id = message.get("id")
|
|
@@ -15,7 +15,7 @@ from dataclasses import dataclass, field
|
|
|
15
15
|
from typing import Any, Dict, List, Optional, Tuple
|
|
16
16
|
|
|
17
17
|
from .jobs import CANONICAL_JOBS, RAW_JOBS, SIGNAL_JOB_REGISTRY
|
|
18
|
-
from .models.mvp_defaults import MVP_JOB_SPECS
|
|
18
|
+
from .models.mvp_defaults import MVP_JOB_SPECS, job_spec_version
|
|
19
19
|
|
|
20
20
|
LANE_RAW = "raw"
|
|
21
21
|
LANE_CANONICAL = "canonical"
|
|
@@ -48,6 +48,8 @@ class EnrichmentCatalogEntry:
|
|
|
48
48
|
# Raw-lane stubs that currently produce no output.
|
|
49
49
|
stub: bool = False
|
|
50
50
|
value_props: Tuple[str, ...] = field(default_factory=tuple)
|
|
51
|
+
# Output-contract version; bump when prior coverage rows are stale (M3).
|
|
52
|
+
spec_version: int = 1
|
|
51
53
|
|
|
52
54
|
def to_dict(self) -> Dict[str, Any]:
|
|
53
55
|
return {
|
|
@@ -66,6 +68,7 @@ class EnrichmentCatalogEntry:
|
|
|
66
68
|
"baseline": self.baseline,
|
|
67
69
|
"stub": self.stub,
|
|
68
70
|
"value_props": list(self.value_props),
|
|
71
|
+
"spec_version": int(self.spec_version),
|
|
69
72
|
}
|
|
70
73
|
|
|
71
74
|
|
|
@@ -334,10 +337,19 @@ def _build_catalog() -> Dict[str, EnrichmentCatalogEntry]:
|
|
|
334
337
|
baseline=job_id in baseline,
|
|
335
338
|
stub=is_stub,
|
|
336
339
|
value_props=tuple(meta.get("value_props") or ()),
|
|
340
|
+
spec_version=job_spec_version(job_id),
|
|
337
341
|
)
|
|
338
342
|
return entries
|
|
339
343
|
|
|
340
344
|
|
|
345
|
+
def catalog_spec_version(job_id: str) -> int:
|
|
346
|
+
"""Return the catalog ``spec_version`` for ``job_id`` (default 1)."""
|
|
347
|
+
entry = get_catalog_entry(job_id)
|
|
348
|
+
if entry is not None:
|
|
349
|
+
return int(entry.spec_version)
|
|
350
|
+
return job_spec_version(job_id)
|
|
351
|
+
|
|
352
|
+
|
|
341
353
|
_CATALOG: Optional[Dict[str, EnrichmentCatalogEntry]] = None
|
|
342
354
|
|
|
343
355
|
|
|
@@ -38,6 +38,18 @@ def _insert_matching_columns(
|
|
|
38
38
|
)
|
|
39
39
|
|
|
40
40
|
|
|
41
|
+
def _record_spec_version(record: Dict[str, Any], job_id: str = "") -> int:
|
|
42
|
+
raw = record.get("spec_version")
|
|
43
|
+
if raw is not None:
|
|
44
|
+
try:
|
|
45
|
+
return int(raw)
|
|
46
|
+
except (TypeError, ValueError):
|
|
47
|
+
pass
|
|
48
|
+
from .models.mvp_defaults import job_spec_version
|
|
49
|
+
|
|
50
|
+
return job_spec_version(job_id or str(record.get("job_id") or ""))
|
|
51
|
+
|
|
52
|
+
|
|
41
53
|
class DerivedTablesManager(BaseObject):
|
|
42
54
|
"""Manages derived tables for enrichment data."""
|
|
43
55
|
|
|
@@ -210,26 +222,18 @@ class DerivedTablesManager(BaseObject):
|
|
|
210
222
|
if isinstance(all_emotions_val, list)
|
|
211
223
|
else (all_emotions_val if isinstance(all_emotions_val, str) else "[]")
|
|
212
224
|
)
|
|
213
|
-
|
|
214
|
-
(
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
)
|
|
224
|
-
|
|
225
|
-
"""
|
|
226
|
-
INSERT OR REPLACE INTO message_emotions (
|
|
227
|
-
message_id, source_id, emotion_label, confidence,
|
|
228
|
-
model_name, all_emotions_json, created_at
|
|
229
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
230
|
-
""",
|
|
231
|
-
values,
|
|
232
|
-
)
|
|
225
|
+
row = {
|
|
226
|
+
"message_id": record.get("message_id"),
|
|
227
|
+
"source_id": record.get("source_id"),
|
|
228
|
+
"emotion_label": record.get("emotion_label"),
|
|
229
|
+
"confidence": record.get("confidence"),
|
|
230
|
+
"model_name": record.get("model_name") or record.get("model"),
|
|
231
|
+
"all_emotions_json": all_emotions_str,
|
|
232
|
+
"created_at": extracted_at,
|
|
233
|
+
"spec_version": _record_spec_version(record, "emo_27"),
|
|
234
|
+
}
|
|
235
|
+
_insert_matching_columns(self.conn, "message_emotions", cols, row)
|
|
236
|
+
values.append(1)
|
|
233
237
|
elif use_wiki:
|
|
234
238
|
import json
|
|
235
239
|
import uuid
|
|
@@ -238,21 +242,17 @@ class DerivedTablesManager(BaseObject):
|
|
|
238
242
|
message_id = record.get("message_id") or record.get("record_id")
|
|
239
243
|
emotion_id = str(record.get("emotion_id") or uuid.uuid4())
|
|
240
244
|
payload = json.dumps({**record, "message_id": message_id})
|
|
241
|
-
|
|
242
|
-
""
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
)
|
|
246
|
-
""",
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
record.get("provider"),
|
|
253
|
-
payload,
|
|
254
|
-
),
|
|
255
|
-
)
|
|
245
|
+
row = {
|
|
246
|
+
"emotion_id": emotion_id,
|
|
247
|
+
"record_id": message_id,
|
|
248
|
+
"source_id": record.get("source_id"),
|
|
249
|
+
"model": record.get("model_name") or record.get("model"),
|
|
250
|
+
"provider": record.get("provider"),
|
|
251
|
+
"payload_json": payload,
|
|
252
|
+
"spec_version": _record_spec_version(record, "emo_27"),
|
|
253
|
+
}
|
|
254
|
+
_insert_matching_columns(self.conn, "message_emotions", cols, row)
|
|
255
|
+
values = [1] # noqa: F841 — keep written accounting below
|
|
256
256
|
else:
|
|
257
257
|
logger.warning("%s: message_emotions schema not recognized", self)
|
|
258
258
|
return 0
|
|
@@ -292,21 +292,20 @@ class DerivedTablesManager(BaseObject):
|
|
|
292
292
|
entity_id = str(record.get("entity_id") or uuid.uuid4())
|
|
293
293
|
payload = json.dumps({**record, "record_id": record_id, "entity_id": entity_id})
|
|
294
294
|
if "payload_json" in cols:
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
record.get("
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
record
|
|
308
|
-
|
|
309
|
-
),
|
|
295
|
+
_insert_matching_columns(
|
|
296
|
+
self.conn,
|
|
297
|
+
"message_entities",
|
|
298
|
+
cols,
|
|
299
|
+
{
|
|
300
|
+
"entity_id": entity_id,
|
|
301
|
+
"record_id": record_id,
|
|
302
|
+
"source_id": record.get("source_id"),
|
|
303
|
+
"entity_text": entity_text,
|
|
304
|
+
"model": record.get("model"),
|
|
305
|
+
"provider": record.get("provider"),
|
|
306
|
+
"payload_json": payload,
|
|
307
|
+
"spec_version": _record_spec_version(record, "entities"),
|
|
308
|
+
},
|
|
310
309
|
)
|
|
311
310
|
if "message_id" in cols:
|
|
312
311
|
try:
|
|
@@ -341,21 +340,20 @@ class DerivedTablesManager(BaseObject):
|
|
|
341
340
|
if not goal_text:
|
|
342
341
|
continue
|
|
343
342
|
goal_id = str(record.get("goal_id") or uuid.uuid4())
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
record.get("
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
record
|
|
357
|
-
|
|
358
|
-
),
|
|
343
|
+
_insert_matching_columns(
|
|
344
|
+
self.conn,
|
|
345
|
+
"user_goals",
|
|
346
|
+
cols,
|
|
347
|
+
{
|
|
348
|
+
"goal_id": goal_id,
|
|
349
|
+
"record_id": record_id,
|
|
350
|
+
"source_id": record.get("source_id"),
|
|
351
|
+
"goal_text": goal_text,
|
|
352
|
+
"model": record.get("model"),
|
|
353
|
+
"provider": record.get("provider"),
|
|
354
|
+
"payload_json": json.dumps({**record, "goal_id": goal_id}),
|
|
355
|
+
"spec_version": _record_spec_version(record, "goal_extraction"),
|
|
356
|
+
},
|
|
359
357
|
)
|
|
360
358
|
written += 1
|
|
361
359
|
commit_connection(self.conn)
|
|
@@ -406,6 +404,7 @@ class DerivedTablesManager(BaseObject):
|
|
|
406
404
|
"model": record.get("model"),
|
|
407
405
|
"provider": record.get("provider"),
|
|
408
406
|
"payload_json": json.dumps({**record, "topic_id": topic_id}),
|
|
407
|
+
"spec_version": _record_spec_version(record, "topics"),
|
|
409
408
|
}
|
|
410
409
|
if "message_id" in cols:
|
|
411
410
|
values["message_id"] = record.get("message_id") or record_id
|
|
@@ -435,6 +434,7 @@ class DerivedTablesManager(BaseObject):
|
|
|
435
434
|
"model": record.get("model"),
|
|
436
435
|
"provider": record.get("provider"),
|
|
437
436
|
"payload_json": json.dumps({**record, "sentiment_id": sentiment_id}),
|
|
437
|
+
"spec_version": _record_spec_version(record, "sentiment"),
|
|
438
438
|
}
|
|
439
439
|
if "message_id" in cols:
|
|
440
440
|
values["message_id"] = record.get("message_id") or record_id
|
|
@@ -464,6 +464,7 @@ class DerivedTablesManager(BaseObject):
|
|
|
464
464
|
"dims": record.get("dims") or (len(vector) if isinstance(vector, list) else None),
|
|
465
465
|
"vector_json": json.dumps(vector) if vector is not None else None,
|
|
466
466
|
"payload_json": json.dumps({**record, "embedding_id": embedding_id}),
|
|
467
|
+
"spec_version": _record_spec_version(record, "embeddings"),
|
|
467
468
|
}
|
|
468
469
|
if "message_id" in cols:
|
|
469
470
|
values["message_id"] = record.get("message_id") or record_id
|
|
@@ -487,32 +488,70 @@ class DerivedTablesManager(BaseObject):
|
|
|
487
488
|
for i in range(0, len(records), batch_size):
|
|
488
489
|
batch = records[i : i + batch_size]
|
|
489
490
|
values = []
|
|
491
|
+
cols = _table_columns(self.conn, "browser_url_classification")
|
|
490
492
|
for record in batch:
|
|
491
493
|
record_id = record.get("record_id") or record.get("event_id")
|
|
492
494
|
if not record_id:
|
|
493
495
|
continue
|
|
494
|
-
|
|
495
|
-
(
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
record.get("url_confidence")
|
|
503
|
-
record.get("
|
|
496
|
+
row = {
|
|
497
|
+
"enriched_from_table": record.get("enriched_from_table") or "activity_events",
|
|
498
|
+
"record_id": record_id,
|
|
499
|
+
"dataset_id": record.get("dataset_id"),
|
|
500
|
+
"url": record.get("url"),
|
|
501
|
+
"title": record.get("title"),
|
|
502
|
+
"url_category": record.get("url_category") or record.get("category"),
|
|
503
|
+
"url_confidence": (
|
|
504
|
+
record.get("url_confidence")
|
|
505
|
+
if record.get("url_confidence") is not None
|
|
506
|
+
else record.get("confidence")
|
|
507
|
+
),
|
|
508
|
+
"model_name": record.get("model_name") or record.get("model"),
|
|
509
|
+
"updated_at": "datetime('now')",
|
|
510
|
+
"spec_version": _record_spec_version(record, "url_classification"),
|
|
511
|
+
}
|
|
512
|
+
# updated_at uses SQL datetime — keep prior executemany path for that col
|
|
513
|
+
if "spec_version" in cols:
|
|
514
|
+
self.conn.execute(
|
|
515
|
+
"""
|
|
516
|
+
INSERT OR REPLACE INTO browser_url_classification
|
|
517
|
+
(enriched_from_table, record_id, dataset_id, url, title,
|
|
518
|
+
url_category, url_confidence, model_name, updated_at, spec_version)
|
|
519
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('now'), ?)
|
|
520
|
+
""",
|
|
521
|
+
(
|
|
522
|
+
row["enriched_from_table"],
|
|
523
|
+
row["record_id"],
|
|
524
|
+
row["dataset_id"],
|
|
525
|
+
row["url"],
|
|
526
|
+
row["title"],
|
|
527
|
+
row["url_category"],
|
|
528
|
+
row["url_confidence"],
|
|
529
|
+
row["model_name"],
|
|
530
|
+
row["spec_version"],
|
|
531
|
+
),
|
|
504
532
|
)
|
|
505
|
-
|
|
533
|
+
else:
|
|
534
|
+
self.conn.execute(
|
|
535
|
+
"""
|
|
536
|
+
INSERT OR REPLACE INTO browser_url_classification
|
|
537
|
+
(enriched_from_table, record_id, dataset_id, url, title,
|
|
538
|
+
url_category, url_confidence, model_name, updated_at)
|
|
539
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))
|
|
540
|
+
""",
|
|
541
|
+
(
|
|
542
|
+
row["enriched_from_table"],
|
|
543
|
+
row["record_id"],
|
|
544
|
+
row["dataset_id"],
|
|
545
|
+
row["url"],
|
|
546
|
+
row["title"],
|
|
547
|
+
row["url_category"],
|
|
548
|
+
row["url_confidence"],
|
|
549
|
+
row["model_name"],
|
|
550
|
+
),
|
|
551
|
+
)
|
|
552
|
+
values.append(1)
|
|
506
553
|
if not values:
|
|
507
554
|
continue
|
|
508
|
-
self.conn.executemany(
|
|
509
|
-
"""
|
|
510
|
-
INSERT OR REPLACE INTO browser_url_classification
|
|
511
|
-
(enriched_from_table, record_id, dataset_id, url, title, url_category, url_confidence, model_name, updated_at)
|
|
512
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, datetime('now'))
|
|
513
|
-
""",
|
|
514
|
-
values,
|
|
515
|
-
)
|
|
516
555
|
commit_connection(self.conn)
|
|
517
556
|
written += len(values)
|
|
518
557
|
except Exception as exc:
|