topos-node 1.2.3__tar.gz → 1.2.5__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.2.3/topos_node.egg-info → topos_node-1.2.5}/PKG-INFO +71 -1
- {topos_node-1.2.3 → topos_node-1.2.5}/README.md +70 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/pyproject.toml +1 -1
- topos_node-1.2.5/tests/test_extensions.py +32 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/__version__.py +2 -2
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/enrichment.py +105 -39
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/llm.py +15 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/signal.py +15 -4
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/source_install.py +2 -1
- topos_node-1.2.5/topos/api/tool_index.py +86 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/app.py +37 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/canonicalization/mappers/__init__.py +6 -0
- topos_node-1.2.5/topos/canonicalization/mappers/base.py +37 -0
- topos_node-1.2.5/topos/canonicalization/mappers/documents_mapper.py +43 -0
- topos_node-1.2.5/topos/canonicalization/mappers/github_activity_mapper.py +214 -0
- topos_node-1.2.5/topos/canonicalization/mappers/google_calendar_mapper.py +278 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/cli/commands.py +3 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/config/settings.py +2 -1
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/control_plane_client.py +52 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/handlers/__init__.py +12 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/handlers/common.py +9 -1
- topos_node-1.2.5/topos/core/handlers/enrichment.py +362 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/handlers/home_chat.py +3 -2
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/handlers/ingest.py +86 -133
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/handlers/query.py +12 -3
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/handlers/routines.py +27 -10
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/handlers/signal_features.py +10 -5
- topos_node-1.2.5/topos/core/handlers/tool_index.py +97 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/state.py +22 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/data_explorer_tables.py +1 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/disclosure/field_registry.py +3 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/backends/huggingface.py +13 -1
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/backends/ollama.py +19 -4
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/backends/openai_compatible.py +24 -6
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/engine.py +34 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/tasks.py +3 -0
- topos_node-1.2.5/topos/engine/usage_observation.py +406 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/catalog.py +4 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/derived_tables.py +13 -14
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/job_writer.py +43 -1
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/_batch_limits.py +1 -1
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/_engine_runner.py +2 -1
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/availability_scores_job.py +27 -2
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/entities_job.py +103 -17
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/fact_extraction_job.py +21 -2
- topos_node-1.2.5/topos/enrichment/jobs/canonical/timeline_job.py +44 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/models/mvp_defaults.py +5 -1
- topos_node-1.2.5/topos/extensions.py +41 -0
- topos_node-1.2.5/topos/features/entities/declared_mappings.py +156 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/entities/edges.py +60 -8
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/entities/fact_materializer.py +87 -2
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/entities/graph_enrichers.py +6 -27
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/entities/graph_refresh.py +63 -1
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/entities/reads.py +6 -2
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/entities/resolver.py +23 -2
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/facts/llm_extract.py +325 -91
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/lifecycle/derived_scrub.py +32 -14
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/brief_canonical_loader.py +2 -1
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/cluster_labels.py +3 -2
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/structured_signal.py +2 -0
- topos_node-1.2.5/topos/features/signal/tool_index.py +332 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/topic_clustering.py +51 -40
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/stats/definitions.py +10 -1
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/stats/engine.py +2 -0
- topos_node-1.2.5/topos/features/timeline_projection.py +353 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/canonical_pipeline.py +50 -9
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/ingest_helpers.py +20 -2
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/local_sync.py +11 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/manager.py +7 -2
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/parsers/__init__.py +8 -0
- topos_node-1.2.5/topos/ingestion/parsers/documents_parser.py +77 -0
- topos_node-1.2.5/topos/ingestion/parsers/google_calendar_parser.py +52 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/usage_inbox_dedupe.py +48 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/llm_integrations_storage.py +167 -50
- topos_node-1.2.5/topos/pipeline/job_runner.py +242 -0
- topos_node-1.2.5/topos/pipeline/job_store.py +310 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/protocol/handled_message_types.json +3 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/retrieval.py +5 -8
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/scope_registry.json +61 -7
- topos_node-1.2.5/topos/runtime_shutdown.py +86 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/sanitization/nsfw_classifier.py +12 -0
- topos_node-1.2.5/topos/sanitization/prewarm.py +32 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/sanitization/privacy_filter.py +10 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/scope_resolution.py +2 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/sources/bundled_canonical_triples.py +4 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/sources/definitions.py +48 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/sources/install_service.py +11 -5
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/sources/registry.py +118 -9
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/sources/scrub_attribution.py +88 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/adapters/factory.py +19 -2
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/adapters/sqlite/stores.py +18 -15
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/canonical/canonical_store.py +104 -6
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/canonical/conversations_tables.py +13 -3
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/connection_tuning.py +1 -1
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/__init__.py +30 -0
- topos_node-1.2.5/topos/storage/db/migrations/calendar_events_scheduling_v1.py +101 -0
- topos_node-1.2.5/topos/storage/db/migrations/canonical_address_book_v1.py +103 -0
- topos_node-1.2.5/topos/storage/db/migrations/documents_v1.py +58 -0
- topos_node-1.2.5/topos/storage/db/migrations/pipeline_jobs_v1.py +75 -0
- topos_node-1.2.5/topos/storage/db/write_gate.py +110 -0
- {topos_node-1.2.3 → topos_node-1.2.5/topos_node.egg-info}/PKG-INFO +71 -1
- {topos_node-1.2.3 → topos_node-1.2.5}/topos_node.egg-info/SOURCES.txt +20 -0
- topos_node-1.2.3/topos/canonicalization/mappers/base.py +0 -26
- topos_node-1.2.3/topos/canonicalization/mappers/github_activity_mapper.py +0 -112
- topos_node-1.2.3/topos/core/handlers/enrichment.py +0 -582
- topos_node-1.2.3/topos/engine/usage_observation.py +0 -129
- topos_node-1.2.3/topos/enrichment/jobs/canonical/timeline_job.py +0 -67
- {topos_node-1.2.3 → topos_node-1.2.5}/LICENSE +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/MANIFEST.in +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/setup.cfg +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/shared/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/shared/filtering.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/shared/schema_registry.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/tests/test_llm_integrations_storage.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/tests/test_protocol_handled_types.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/analytics/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/analytics/duckdb_adapter.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/analytics/messenger_communities.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/analytics/messenger_graph.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/analytics/messenger_labels.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/analytics/profiles.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/analytics/query_engine.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/analytics/raw_queries.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/analytics.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/app_registry.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/backup.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/compute_remote.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/data_commit.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/data_explorer_table_prefs.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/database_explorer.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/db.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/device.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/engine_run.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/enrichment_lab.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/filter_lab.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/health.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/home_chat.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/ingestion_api.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/ingestion_compat.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/ingestion_sources.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/intelligence_lifecycle.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/local_mcp.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/messenger_analytics.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/privacy_disclose.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/query_api.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/runtime_bootstrap.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/sanitization_ollama_config.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/signal_extraction_config.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/source_scrub.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/sources.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/sources_overview.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/sync.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/ui_config.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/uma_data.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/upgrades.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/usage.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/api/user_identity.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/auth.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/canonicalization/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/canonicalization/mappers/browser_activity_mapper.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/canonicalization/mappers/chatgpt_mapper.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/canonicalization/mappers/demo_mappers.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/canonicalization/mappers/grok_mapper.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/canonicalization/mappers/messenger_mapper.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/canonicalization/models.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/canonicalization/resolver.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/cli/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/cli/__main__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/config/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/config/sanitization_ollama.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/config/signal_extraction.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/config/uvicorn_logging.json +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/contacts/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/contacts/identity.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/api_models.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/connection_resilience.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/device_helpers.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/errors.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/events.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/handlers/config.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/handlers/contacts_import.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/handlers/database_explorer.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/handlers/device.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/handlers/enrichment_lab.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/handlers/filter_lab.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/handlers/messages.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/handlers/messenger_analytics.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/handlers/registry.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/handlers/sources.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/handlers/uma.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/logging.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/metrics.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/routine_access.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/startup_banner.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/table_layers.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/core/types.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/data_explorer_row_delete.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/data_explorer_table_prefs.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/disclosure/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/disclosure/canonical_writer.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/disclosure/content_policy.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/disclosure/privacy_layer.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/disclosure/tier.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/backends/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/backends/base.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/backends/generative_prompts.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/backends/generative_response.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/backends/openai.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/backends/redpill.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/backends/stub.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/client.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/intake.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/memory_utils.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/model_cache.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/pipeline_memory.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/queue_manager.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/registration.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/result_formatter.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/router.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/scoped_token.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/transport.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/usage_guard.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/engine/validator.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/base.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/brief_fallback.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/dimension_summary_job.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/embeddings_job.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/emo_27_job.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/goal_extraction_job.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/pii_redaction_job.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/relationship_edges_job.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/sentiment_job.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/statistics_job.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/topic_clusters_job.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/topics_job.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/url_classification_core.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/url_classification_enrichment_job.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/canonical/url_classification_signal_job.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/raw/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/raw/attachments_job.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/raw/language_job.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/raw/time_normalization_job.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/jobs/raw/tool_calls_job.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/model_overrides.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/models/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/models/manager.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/models/registry.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/models/versioning.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/orchestrator.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/processor.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/progress_bar.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/registry_contract.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/signal_derivation_config.json +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/source_overrides.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment/website_classifier.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment_lab/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment_lab/bundles.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment_lab/model_resolve.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment_lab/schema.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment_lab/service.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment_lab/store.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/enrichment_lab/worker.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/evals/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/evals/enrichment_eval.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/entities/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/entities/consolidation.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/entities/dossier.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/entities/graph_search.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/entities/linking.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/entities/maintenance.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/facts/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/facts/extract.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/facts/reads.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/facts/store.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/fit/evaluator.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/fit/opportunity_types.json +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/lifecycle/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/lifecycle/exclusions.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/lifecycle/gc.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/provenance/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/provenance/posture.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/provenance/roles.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/brief_ontology.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/brief_renderer.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/brief_schemas.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/chunking.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/data_health.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/definitions/brief_ontologies.json +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/definitions/intentions.json +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/definitions/profile.json +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/definitions/relationships.json +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/definitions/schema/dimension_definition.schema.json +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/definitions/time.json +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/definitions/work.json +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/dimension_briefs.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/dimension_definition_loader.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/dimension_profiles.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/dimension_registry.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/embed_context.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/extraction/artifact_router.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/extraction/artifact_store.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/extraction/rule_extractors.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/graph_sanitize.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/hybrid_search.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/incremental_clustering.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/model_recommendations.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/query_embed_cache.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/schemas.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/service.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/signal_object_store.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/source_hydration.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/typed_stores/aggregates.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/typed_stores/scope_materializer.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/vector_codec.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/vector_math.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/signal/vector_settings.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/stats/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/stats/fold.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/features/stats/insights.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/filter_lab/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/filter_lab/bundles.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/filter_lab/schema.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/filter_lab/service.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/filter_lab/store.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/filter_lab/worker.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/home_chat/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/home_chat/schema.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/home_chat/store.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/hosted_pool_lease.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/checkpoints/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/checkpoints/checkpoint_store.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/checkpoints/sqlite_checkpoint_store.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/inbox_crypto.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/inbox_drain.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/jobs.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/journal_location_fanout.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/journal_time_log_normalize.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/log_preview.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/parser.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/parsers/base.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/parsers/browser_parser.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/parsers/calendar_parser.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/parsers/chatgpt_conversation_flattener.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/parsers/chatgpt_parser.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/parsers/demo_file_parsers.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/parsers/github_activity_parser.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/parsers/grok_parser.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/parsers/messenger_parser.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/parsers/voxterm_parser.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/progress.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/reprocess.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/sources/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/sources/base.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/sources/calendar.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/sources/chatgpt.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/sources/contact_importers.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/sources/grok.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/sources/imessage_reader.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/sources/signal_export_parser.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/sources/signal_reader.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/state_machine.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/triggers/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/triggers/file_trigger.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/triggers/sqlite_trigger.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/validation/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/validation/base.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/validation/schema_registry.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/ingestion/validation/schema_validator.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/lineage/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/lineage/provenance.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/lineage/tracker.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/mcp_stdio_proxy.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/observability/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/observability/alerts.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/observability/metrics.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/observability/tracing.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/openai_client.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/pipeline/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/pipeline/audit.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/pipeline/envelope.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/pipeline/stages.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/pipeline/stub_enqueue.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/projections/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/projections/vector_index/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/projections/vector_index/base.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/projections/vector_index/builders.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/projections/vector_index/health_checks.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/protocol/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/audit.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/ddr.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/disclosure.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/fingerprint.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/game_layer.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/grant_cache.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/inference.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/intent.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/manifest.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/manifest_validation.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/minimizer.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/negotiation.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/pipeline.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/planner.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/runtime.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/scope_registry_loader.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/session.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/session_utils.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/source_generation.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/turn_classifier.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/query/types.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/rate_limit.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/routines/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/routines/schema.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/routines/store.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/runtime_update.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/sanitization/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/sanitization/ollama_transforms.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/services/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/services/container.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/services/embeddings/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/services/embeddings/base.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/services/embeddings/local.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/services/embeddings/remote.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/services/interfaces.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/services/llm/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/services/llm/base.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/services/llm/openai.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/services/local.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/services/postgres.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/sources/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/sources/canonical_signal_defaults.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/sources/runtime_install.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/sources/scrub_service.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/startup_banner.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/adapters/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/adapters/fakes.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/adapters/postgres/stores.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/adapters/protocols.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/adapters/sqlite/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/adapters/sqlite/vector_search.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/canonical/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/canonical/activity_tables.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/canonical/ai_chat/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/canonical/ai_chat/canonicalizer.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/canonical/ai_chat/mapper.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/canonical/ai_chat/model.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/canonical/ai_chat/tables.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/canonical/calendar_contacts_tables.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/canonical/mapping_store.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/canonical/postgres.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/client.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/activity_events_content_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/actor_role_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/canonical_disclosure_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/canonical_nsfw_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/derivation_ledger_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/entity_edges_validity_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/episodes_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/extraction_artifacts.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/journal_entries_duration_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/journal_entries_ends_at_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/journal_entries_people_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/journal_entries_place_name_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/journal_entries_starts_at_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/remediation_person_model.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/scope_source_generation.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/signal_dimension_backfill_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/signal_dimension_harness.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/signal_objects.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/signal_objects_period_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/signal_objects_updated_by_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/stage9_column_renames.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/vector_storage_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/vector_storage_v2.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/vector_storage_v3.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/vector_storage_v4.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/wiki_clusters_v2.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/wiki_entities_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/wiki_entity_review_v2.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/wiki_facts_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/wiki_lifecycle_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/wiki_mvp_phase0.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/wiki_mvp_phase1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/wiki_mvp_phase4_messages_cutover.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/wiki_mvp_phase5_topic_clusters.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/wiki_mvp_phase6_dimension_briefs.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/wiki_mvp_query_quality.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/wiki_mvp_topic_clusters_coordination.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/wiki_stats_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/migrations/wiki_timeline_v1.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/paths.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/postgres.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/schema.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/db/storage_breakdown.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/enrichment/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/enrichment/canonical_enrichment_store.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/enrichment/raw_enrichment_store.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/normalized/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/normalized/normalized_store.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/oplog/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/oplog/decision.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/oplog/oplog_store.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/oplog/postgres.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/person/identity_resolver.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/projections/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/projections/index_ops_store.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/projections/vector_index_store.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/raw/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/raw/browser_flat_tables.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/raw/file_store.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/raw/raw_store.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/raw/raw_tables_manager.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/raw/sqlite_raw_store.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/security/encryption.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/signal_identity.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/source_settings.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/storage/user_identity.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/sync/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/sync/client.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/sync_handlers.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/testing/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/testing/lifespan.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/uma_contact_enrichment.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/uma_filters.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/uma_resource_id.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/uma_rpt.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/upgrades/__init__.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/upgrades/manifests.json +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/upgrades/runner.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/utils/base_object.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos/websocket_client.py +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos_node.egg-info/dependency_links.txt +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos_node.egg-info/entry_points.txt +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/topos_node.egg-info/requires.txt +0 -0
- {topos_node-1.2.3 → topos_node-1.2.5}/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.2.
|
|
3
|
+
Version: 1.2.5
|
|
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
|
|
@@ -213,6 +213,76 @@ pip install -e ".[dev,engine]"
|
|
|
213
213
|
pytest tests -m "public and not e2e" -q
|
|
214
214
|
```
|
|
215
215
|
|
|
216
|
+
## Plugins
|
|
217
|
+
|
|
218
|
+
Topos Node supports **optional plugins**: separate Python packages installed alongside
|
|
219
|
+
`topos-node` that register handlers, connectors, or other runtime hooks. The core node
|
|
220
|
+
does not hardcode plugin names — discovery is entirely via setuptools entry points.
|
|
221
|
+
|
|
222
|
+
### Contract: `topos.extensions`
|
|
223
|
+
|
|
224
|
+
| Rule | Detail |
|
|
225
|
+
| --- | --- |
|
|
226
|
+
| **Entry-point group** | `topos.extensions` |
|
|
227
|
+
| **Entry-point target** | A callable, e.g. `my_plugin:register` |
|
|
228
|
+
| **When it runs** | At process startup, before the server accepts traffic (`topos/extensions.py`) |
|
|
229
|
+
| **Failure mode** | A broken plugin is logged and skipped; the node keeps running |
|
|
230
|
+
| **Dependencies** | Your plugin declares `topos-node` (or `topos-node[local]`) in its own `pyproject.toml` |
|
|
231
|
+
|
|
232
|
+
**Minimal plugin**
|
|
233
|
+
|
|
234
|
+
`pyproject.toml`:
|
|
235
|
+
|
|
236
|
+
```toml
|
|
237
|
+
[project]
|
|
238
|
+
name = "my-topos-plugin"
|
|
239
|
+
dependencies = ["topos-node[local]"]
|
|
240
|
+
|
|
241
|
+
[project.entry-points."topos.extensions"]
|
|
242
|
+
my_plugin = "my_topos_plugin:register"
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
`my_topos_plugin/__init__.py`:
|
|
246
|
+
|
|
247
|
+
```python
|
|
248
|
+
def register() -> None:
|
|
249
|
+
from my_topos_plugin.handlers import example # noqa: F401 — registers @handles
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
`my_topos_plugin/handlers/example.py`:
|
|
253
|
+
|
|
254
|
+
```python
|
|
255
|
+
from typing import Any, Dict, Optional
|
|
256
|
+
from topos.core.handlers.registry import handles
|
|
257
|
+
|
|
258
|
+
@handles("my_message_type")
|
|
259
|
+
async def handle_my_message(message: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
260
|
+
return {"status": "ok", "payload": {"received": message.get("type")}}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**Install and run**
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
pip install topos-node my-topos-plugin
|
|
267
|
+
topos-node
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Handlers registered in `register()` are available to the control-plane WebSocket
|
|
271
|
+
and local API paths that dispatch through `topos.core.handlers`.
|
|
272
|
+
|
|
273
|
+
### Starter template
|
|
274
|
+
|
|
275
|
+
Fork **[dialoguesai/topos-plugin-template](https://github.com/dialoguesai/topos-plugin-template)**
|
|
276
|
+
for a working package with tests and CI. It registers a sample `plugin_template_ping`
|
|
277
|
+
handler you can copy and rename.
|
|
278
|
+
|
|
279
|
+
### Guidelines
|
|
280
|
+
|
|
281
|
+
- Use **unique message type names** (prefix with your project) to avoid colliding with core handlers.
|
|
282
|
+
- Keep plugins in **separate repositories** — do not add proprietary logic to this repo.
|
|
283
|
+
- Message types your plugin handles do not need to appear in the public engine protocol
|
|
284
|
+
snapshot unless the hosted control plane will send them to all nodes.
|
|
285
|
+
|
|
216
286
|
## Contributing
|
|
217
287
|
|
|
218
288
|
See `CONTRIBUTING.md` for:
|
|
@@ -156,6 +156,76 @@ pip install -e ".[dev,engine]"
|
|
|
156
156
|
pytest tests -m "public and not e2e" -q
|
|
157
157
|
```
|
|
158
158
|
|
|
159
|
+
## Plugins
|
|
160
|
+
|
|
161
|
+
Topos Node supports **optional plugins**: separate Python packages installed alongside
|
|
162
|
+
`topos-node` that register handlers, connectors, or other runtime hooks. The core node
|
|
163
|
+
does not hardcode plugin names — discovery is entirely via setuptools entry points.
|
|
164
|
+
|
|
165
|
+
### Contract: `topos.extensions`
|
|
166
|
+
|
|
167
|
+
| Rule | Detail |
|
|
168
|
+
| --- | --- |
|
|
169
|
+
| **Entry-point group** | `topos.extensions` |
|
|
170
|
+
| **Entry-point target** | A callable, e.g. `my_plugin:register` |
|
|
171
|
+
| **When it runs** | At process startup, before the server accepts traffic (`topos/extensions.py`) |
|
|
172
|
+
| **Failure mode** | A broken plugin is logged and skipped; the node keeps running |
|
|
173
|
+
| **Dependencies** | Your plugin declares `topos-node` (or `topos-node[local]`) in its own `pyproject.toml` |
|
|
174
|
+
|
|
175
|
+
**Minimal plugin**
|
|
176
|
+
|
|
177
|
+
`pyproject.toml`:
|
|
178
|
+
|
|
179
|
+
```toml
|
|
180
|
+
[project]
|
|
181
|
+
name = "my-topos-plugin"
|
|
182
|
+
dependencies = ["topos-node[local]"]
|
|
183
|
+
|
|
184
|
+
[project.entry-points."topos.extensions"]
|
|
185
|
+
my_plugin = "my_topos_plugin:register"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
`my_topos_plugin/__init__.py`:
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
def register() -> None:
|
|
192
|
+
from my_topos_plugin.handlers import example # noqa: F401 — registers @handles
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
`my_topos_plugin/handlers/example.py`:
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
from typing import Any, Dict, Optional
|
|
199
|
+
from topos.core.handlers.registry import handles
|
|
200
|
+
|
|
201
|
+
@handles("my_message_type")
|
|
202
|
+
async def handle_my_message(message: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
203
|
+
return {"status": "ok", "payload": {"received": message.get("type")}}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**Install and run**
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
pip install topos-node my-topos-plugin
|
|
210
|
+
topos-node
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Handlers registered in `register()` are available to the control-plane WebSocket
|
|
214
|
+
and local API paths that dispatch through `topos.core.handlers`.
|
|
215
|
+
|
|
216
|
+
### Starter template
|
|
217
|
+
|
|
218
|
+
Fork **[dialoguesai/topos-plugin-template](https://github.com/dialoguesai/topos-plugin-template)**
|
|
219
|
+
for a working package with tests and CI. It registers a sample `plugin_template_ping`
|
|
220
|
+
handler you can copy and rename.
|
|
221
|
+
|
|
222
|
+
### Guidelines
|
|
223
|
+
|
|
224
|
+
- Use **unique message type names** (prefix with your project) to avoid colliding with core handlers.
|
|
225
|
+
- Keep plugins in **separate repositories** — do not add proprietary logic to this repo.
|
|
226
|
+
- Message types your plugin handles do not need to appear in the public engine protocol
|
|
227
|
+
snapshot unless the hosted control plane will send them to all nodes.
|
|
228
|
+
|
|
159
229
|
## Contributing
|
|
160
230
|
|
|
161
231
|
See `CONTRIBUTING.md` for:
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "topos-node"
|
|
7
|
-
version = "1.2.
|
|
7
|
+
version = "1.2.5"
|
|
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"
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from topos.core.handlers.registry import handles
|
|
6
|
+
from topos.extensions import load_extensions
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@pytest.mark.public
|
|
10
|
+
def test_load_extensions_does_not_raise_when_no_plugins_installed() -> None:
|
|
11
|
+
load_extensions()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@pytest.mark.public
|
|
15
|
+
def test_load_extensions_invokes_entry_point_callables(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
16
|
+
seen: list[str] = []
|
|
17
|
+
|
|
18
|
+
def _init() -> None:
|
|
19
|
+
seen.append("ran")
|
|
20
|
+
|
|
21
|
+
class _FakeEntryPoint:
|
|
22
|
+
name = "test"
|
|
23
|
+
|
|
24
|
+
def load(self) -> object:
|
|
25
|
+
return _init
|
|
26
|
+
|
|
27
|
+
monkeypatch.setattr(
|
|
28
|
+
"topos.extensions._iter_extension_entry_points",
|
|
29
|
+
lambda: [_FakeEntryPoint()],
|
|
30
|
+
)
|
|
31
|
+
load_extensions()
|
|
32
|
+
assert seen == ["ran"]
|
|
@@ -319,7 +319,14 @@ def _enrichment_coverage_core(source_id: str) -> Dict[str, Any]:
|
|
|
319
319
|
"output_rows": {},
|
|
320
320
|
}
|
|
321
321
|
coverage_table = coverage_table_for_job(job_id)
|
|
322
|
-
if
|
|
322
|
+
if job_id == "timeline":
|
|
323
|
+
from ..features.timeline_projection import timeline_coverage_for_source
|
|
324
|
+
|
|
325
|
+
timeline_stats = timeline_coverage_for_source(conn, source_id)
|
|
326
|
+
job_info["enriched_records"] = timeline_stats["enriched_records"]
|
|
327
|
+
job_info["coverage_percent"] = timeline_stats["coverage_percent"]
|
|
328
|
+
job_info["output_rows"]["timeline"] = timeline_stats["enriched_records"]
|
|
329
|
+
elif coverage_table and _table_exists(conn, coverage_table):
|
|
323
330
|
cols = _table_columns(conn, coverage_table)
|
|
324
331
|
id_col = "message_id" if "message_id" in cols else "record_id"
|
|
325
332
|
if "source_id" in cols and id_col in cols:
|
|
@@ -552,24 +559,50 @@ async def _generic_backfill_core(
|
|
|
552
559
|
scanned = len(records)
|
|
553
560
|
|
|
554
561
|
if only_missing:
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
if "
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
if row[0]
|
|
562
|
+
if job_name == "timeline":
|
|
563
|
+
from ..features.timeline_projection import timeline_coverage_for_source
|
|
564
|
+
|
|
565
|
+
stats = timeline_coverage_for_source(db_conn, source_id)
|
|
566
|
+
if stats["missing_records"] == 0:
|
|
567
|
+
return {
|
|
568
|
+
"rows_scanned": scanned,
|
|
569
|
+
"rows_processed": 0,
|
|
570
|
+
"rows_skipped": scanned,
|
|
571
|
+
"rows_failed": 0,
|
|
572
|
+
"errors": [],
|
|
567
573
|
}
|
|
568
|
-
|
|
574
|
+
else:
|
|
575
|
+
coverage_table = coverage_table_for_job(job_name)
|
|
576
|
+
if coverage_table and _table_exists(db_conn, coverage_table):
|
|
577
|
+
cols = _table_columns(db_conn, coverage_table)
|
|
578
|
+
id_col = "message_id" if "message_id" in cols else "record_id"
|
|
579
|
+
if "source_id" in cols and id_col in cols:
|
|
580
|
+
done = {
|
|
581
|
+
str(row[0])
|
|
582
|
+
for row in db_conn.execute(
|
|
583
|
+
f"SELECT DISTINCT {id_col} FROM {coverage_table} WHERE source_id=?",
|
|
584
|
+
(source_id,),
|
|
585
|
+
).fetchall()
|
|
586
|
+
if row[0]
|
|
587
|
+
}
|
|
588
|
+
records = [r for r in records if _record_identifier(r) not in done]
|
|
569
589
|
|
|
570
590
|
if isinstance(limit, int) and limit > 0:
|
|
571
591
|
records = records[:limit]
|
|
572
592
|
|
|
593
|
+
if job_name == "timeline":
|
|
594
|
+
from ..features.timeline_projection import repair_timeline_for_source
|
|
595
|
+
|
|
596
|
+
report = repair_timeline_for_source(db_conn, source_id, missing_only=True, dry_run=False)
|
|
597
|
+
processed = int(report.get("totals", {}).get("written", 0))
|
|
598
|
+
return {
|
|
599
|
+
"rows_scanned": scanned,
|
|
600
|
+
"rows_processed": processed,
|
|
601
|
+
"rows_skipped": max(scanned - processed, 0),
|
|
602
|
+
"rows_failed": 0,
|
|
603
|
+
"errors": [],
|
|
604
|
+
}
|
|
605
|
+
|
|
573
606
|
if not records:
|
|
574
607
|
return {
|
|
575
608
|
"rows_scanned": scanned,
|
|
@@ -950,6 +983,7 @@ async def _process_enrichment_core(
|
|
|
950
983
|
job_names: Optional[List[str]] = None,
|
|
951
984
|
force_reprocess: bool = False,
|
|
952
985
|
include_signal: bool = True,
|
|
986
|
+
progress_updater: Optional[Any] = None,
|
|
953
987
|
) -> Dict[str, Any]:
|
|
954
988
|
"""Core logic for processing enrichment (reusable from HTTP and WebSocket).
|
|
955
989
|
|
|
@@ -1024,32 +1058,64 @@ async def _process_enrichment_core(
|
|
|
1024
1058
|
|
|
1025
1059
|
# Define progress callback to update progress during execution
|
|
1026
1060
|
progress_callback = None
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1061
|
+
if progress_updater is not None:
|
|
1062
|
+
def progress_callback(
|
|
1063
|
+
processed_count: int,
|
|
1064
|
+
total_count: int,
|
|
1065
|
+
job_name: str,
|
|
1066
|
+
job_percent: float,
|
|
1067
|
+
current_job_progress: float,
|
|
1068
|
+
):
|
|
1069
|
+
estimated_messages_processed = int((job_percent / 100) * total_count) if total_count else 0
|
|
1070
|
+
jobs_complete = int((job_percent / 100) * len(jobs_to_run)) if jobs_to_run else 0
|
|
1071
|
+
progress_updater(
|
|
1072
|
+
{
|
|
1073
|
+
"status": "processing",
|
|
1074
|
+
"progress_percent": min(100.0, job_percent),
|
|
1075
|
+
"messages_processed": estimated_messages_processed,
|
|
1076
|
+
"messages_skipped": 0,
|
|
1077
|
+
"messages_total": total_count,
|
|
1078
|
+
"current_job_name": job_name,
|
|
1079
|
+
"current_job_progress_percent": current_job_progress,
|
|
1080
|
+
"jobs_complete": jobs_complete,
|
|
1081
|
+
"jobs_total": len(jobs_to_run),
|
|
1082
|
+
"jobs_progress_percent": (jobs_complete / len(jobs_to_run) * 100) if jobs_to_run else 0.0,
|
|
1083
|
+
}
|
|
1084
|
+
)
|
|
1085
|
+
else:
|
|
1086
|
+
try:
|
|
1087
|
+
from ..enrichment.progress import get_progress
|
|
1088
|
+
progress_obj = get_progress(source_id)
|
|
1089
|
+
if progress_obj:
|
|
1090
|
+
def progress_callback(
|
|
1091
|
+
processed_count: int,
|
|
1092
|
+
total_count: int,
|
|
1093
|
+
job_name: str,
|
|
1094
|
+
job_percent: float,
|
|
1095
|
+
current_job_progress: float,
|
|
1096
|
+
):
|
|
1097
|
+
estimated_messages_processed = int((job_percent / 100) * total_count)
|
|
1098
|
+
jobs_complete = int((job_percent / 100) * len(jobs_to_run))
|
|
1099
|
+
progress_obj.update(
|
|
1100
|
+
messages_processed=estimated_messages_processed,
|
|
1101
|
+
messages_skipped=0,
|
|
1102
|
+
current_job_name=job_name,
|
|
1103
|
+
current_job_progress_percent=current_job_progress,
|
|
1104
|
+
jobs_complete=jobs_complete,
|
|
1105
|
+
jobs_total=len(jobs_to_run),
|
|
1106
|
+
)
|
|
1107
|
+
except Exception:
|
|
1108
|
+
pass
|
|
1052
1109
|
|
|
1110
|
+
if progress_updater is not None:
|
|
1111
|
+
progress_updater(
|
|
1112
|
+
{
|
|
1113
|
+
"status": "processing",
|
|
1114
|
+
"messages_total": len(unprocessed_messages),
|
|
1115
|
+
"jobs_total": len(jobs_to_run),
|
|
1116
|
+
}
|
|
1117
|
+
)
|
|
1118
|
+
|
|
1053
1119
|
enrichment_result = await orchestrator.run_canonical(
|
|
1054
1120
|
unprocessed_messages,
|
|
1055
1121
|
job_names=jobs_to_run,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import hashlib
|
|
4
|
+
import logging
|
|
4
5
|
|
|
5
6
|
from fastapi import APIRouter, Depends
|
|
6
7
|
|
|
@@ -10,6 +11,8 @@ from ..engine.usage_observation import emit_usage_observation
|
|
|
10
11
|
from ..rate_limit import rate_limit
|
|
11
12
|
from ..services.container import Services, get_services
|
|
12
13
|
|
|
14
|
+
logger = logging.getLogger("topos.api.llm")
|
|
15
|
+
|
|
13
16
|
router = APIRouter()
|
|
14
17
|
|
|
15
18
|
|
|
@@ -19,6 +22,12 @@ router = APIRouter()
|
|
|
19
22
|
dependencies=[Depends(require_api_key), Depends(rate_limit)],
|
|
20
23
|
)
|
|
21
24
|
async def llm_generation(body: GenerationRequest):
|
|
25
|
+
logger.info(
|
|
26
|
+
"llm_generation request: provider=%r model=%r prompt_chars=%d",
|
|
27
|
+
body.provider,
|
|
28
|
+
body.model,
|
|
29
|
+
len(body.prompt or ""),
|
|
30
|
+
)
|
|
22
31
|
services: Services = get_services()
|
|
23
32
|
result = await services.llm.generate(body.model_dump())
|
|
24
33
|
usage = result.get("usage") if isinstance(result, dict) else {}
|
|
@@ -45,6 +54,12 @@ async def llm_generation(body: GenerationRequest):
|
|
|
45
54
|
dependencies=[Depends(require_api_key), Depends(rate_limit)],
|
|
46
55
|
)
|
|
47
56
|
async def llm_generation_alias(body: GenerationRequest):
|
|
57
|
+
logger.info(
|
|
58
|
+
"llm_generation request (alias): provider=%r model=%r prompt_chars=%d",
|
|
59
|
+
body.provider,
|
|
60
|
+
body.model,
|
|
61
|
+
len(body.prompt or ""),
|
|
62
|
+
)
|
|
48
63
|
services: Services = get_services()
|
|
49
64
|
result = await services.llm.generate(body.model_dump())
|
|
50
65
|
usage = result.get("usage") if isinstance(result, dict) else {}
|
|
@@ -232,11 +232,13 @@ async def list_entities(
|
|
|
232
232
|
# as an entity id.
|
|
233
233
|
@router.get("/entities/graph")
|
|
234
234
|
async def get_entity_graph(
|
|
235
|
-
limit_nodes: int = Query(default=100, ge=1, le=
|
|
236
|
-
limit_edges: int = Query(default=300, ge=1, le=
|
|
235
|
+
limit_nodes: int = Query(default=100, ge=1, le=5000),
|
|
236
|
+
limit_edges: int = Query(default=300, ge=1, le=20000),
|
|
237
237
|
min_weight: float = Query(default=0.0, ge=0.0),
|
|
238
238
|
include_closed: bool = Query(default=False),
|
|
239
239
|
as_of: Optional[str] = Query(default=None),
|
|
240
|
+
selection: str = Query(default="weight"),
|
|
241
|
+
offset: int = Query(default=0, ge=0),
|
|
240
242
|
_api_key: str = Depends(require_api_key),
|
|
241
243
|
):
|
|
242
244
|
"""Entity-spine graph (decayed typed edges) in list_graph node/edge shape.
|
|
@@ -244,16 +246,25 @@ async def get_entity_graph(
|
|
|
244
246
|
Each edge carries valid_from/valid_to/last_event_at. ``as_of`` (ISO date)
|
|
245
247
|
returns the graph as it stood at that instant (temporal scrubber);
|
|
246
248
|
``include_closed`` adds ended edges to the present view.
|
|
249
|
+
|
|
250
|
+
``selection=weight`` (default) ranks by weight for MCP/minimal slices;
|
|
251
|
+
``selection=all`` ranks by recency for the owner knowledge-graph UI.
|
|
247
252
|
"""
|
|
253
|
+
import asyncio
|
|
254
|
+
|
|
248
255
|
from ..features.entities.reads import entity_graph
|
|
249
256
|
|
|
250
|
-
|
|
251
|
-
|
|
257
|
+
conn = _entities_conn()
|
|
258
|
+
return await asyncio.to_thread(
|
|
259
|
+
entity_graph,
|
|
260
|
+
conn,
|
|
252
261
|
limit_nodes=limit_nodes,
|
|
253
262
|
limit_edges=limit_edges,
|
|
254
263
|
min_weight=min_weight,
|
|
255
264
|
include_closed=include_closed,
|
|
256
265
|
as_of=as_of,
|
|
266
|
+
selection=selection,
|
|
267
|
+
offset=offset,
|
|
257
268
|
)
|
|
258
269
|
|
|
259
270
|
|
|
@@ -11,6 +11,7 @@ from ..ingestion.ingest_helpers import ingest_file_payload, ingest_ui_payload
|
|
|
11
11
|
from ..api.enrichment import _process_enrichment_core
|
|
12
12
|
from ..engine.usage_observation import emit_usage_observation
|
|
13
13
|
from ..sources import install_service
|
|
14
|
+
from ..sources.definitions import with_source_capabilities
|
|
14
15
|
|
|
15
16
|
router = APIRouter()
|
|
16
17
|
logger = logging.getLogger("topos.api.source_install")
|
|
@@ -140,7 +141,7 @@ async def _list_sources_core(payload: Dict[str, Any]) -> Dict[str, Any]:
|
|
|
140
141
|
source_def = rec.source_definition_json if isinstance(rec.source_definition_json, dict) else {}
|
|
141
142
|
if not sid or sid in active_by_source or not source_def:
|
|
142
143
|
continue
|
|
143
|
-
active_by_source[sid] = source_def
|
|
144
|
+
active_by_source[sid] = with_source_capabilities(source_def)
|
|
144
145
|
sources = list(active_by_source.values())
|
|
145
146
|
return {"status": "ok", "sources": sources}
|
|
146
147
|
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""Tool-RAG endpoints: sync the tool index, retrieve top-K tools for a query.
|
|
2
|
+
|
|
3
|
+
PLAN_AGENT_QUALITY WS-3 (M2). The chat orchestration (topos-react-app) pushes
|
|
4
|
+
the gateway's tool list here after ``tools/list`` (hash-deduped upsert → cheap
|
|
5
|
+
no-op when unchanged) and calls ``/v1/tools/retrieve`` per turn to build a
|
|
6
|
+
focused tool doc sized to the model instead of a flat 52-tool dump.
|
|
7
|
+
|
|
8
|
+
Handlers are sync ``def`` on purpose: the embedding path is blocking HF
|
|
9
|
+
inference, and FastAPI runs sync handlers in its threadpool.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from typing import List, Optional
|
|
15
|
+
|
|
16
|
+
from fastapi import APIRouter, Depends, HTTPException
|
|
17
|
+
from pydantic import BaseModel, Field
|
|
18
|
+
|
|
19
|
+
from ..auth import require_api_key
|
|
20
|
+
from ..core.state import get_db_connection
|
|
21
|
+
from ..features.signal.tool_index import index_status, index_tools, retrieve_tools
|
|
22
|
+
from ..rate_limit import rate_limit
|
|
23
|
+
|
|
24
|
+
router = APIRouter()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ToolSpecIn(BaseModel):
|
|
28
|
+
name: str
|
|
29
|
+
description: str = ""
|
|
30
|
+
connector_id: Optional[str] = None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class IndexToolsRequest(BaseModel):
|
|
34
|
+
tools: List[ToolSpecIn] = Field(default_factory=list, max_length=2000)
|
|
35
|
+
# Prune index rows absent from this payload (full-list syncs only).
|
|
36
|
+
prune_missing: bool = False
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class RetrieveToolsRequest(BaseModel):
|
|
40
|
+
query: str
|
|
41
|
+
connector_scope: Optional[str] = None
|
|
42
|
+
k: int = 8
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _require_conn():
|
|
46
|
+
conn = get_db_connection()
|
|
47
|
+
if conn is None:
|
|
48
|
+
raise HTTPException(status_code=503, detail="Database unavailable")
|
|
49
|
+
return conn
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@router.post(
|
|
53
|
+
"/v1/tools/index",
|
|
54
|
+
dependencies=[Depends(require_api_key), Depends(rate_limit)],
|
|
55
|
+
)
|
|
56
|
+
def tools_index(body: IndexToolsRequest):
|
|
57
|
+
conn = _require_conn()
|
|
58
|
+
specs = [spec.model_dump() for spec in body.tools if str(spec.name or "").strip()]
|
|
59
|
+
if not specs and not body.prune_missing:
|
|
60
|
+
raise HTTPException(status_code=422, detail="tools must be a non-empty list")
|
|
61
|
+
return index_tools(conn, specs, prune_missing=body.prune_missing)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@router.post(
|
|
65
|
+
"/v1/tools/retrieve",
|
|
66
|
+
dependencies=[Depends(require_api_key), Depends(rate_limit)],
|
|
67
|
+
)
|
|
68
|
+
def tools_retrieve(body: RetrieveToolsRequest):
|
|
69
|
+
if not str(body.query or "").strip():
|
|
70
|
+
raise HTTPException(status_code=422, detail="query is required")
|
|
71
|
+
conn = _require_conn()
|
|
72
|
+
return retrieve_tools(
|
|
73
|
+
conn,
|
|
74
|
+
body.query,
|
|
75
|
+
connector_scope=body.connector_scope,
|
|
76
|
+
k=body.k,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@router.get(
|
|
81
|
+
"/v1/tools/index/status",
|
|
82
|
+
dependencies=[Depends(require_api_key), Depends(rate_limit)],
|
|
83
|
+
)
|
|
84
|
+
def tools_index_status():
|
|
85
|
+
conn = _require_conn()
|
|
86
|
+
return index_status(conn)
|
|
@@ -45,10 +45,12 @@ from .api import (
|
|
|
45
45
|
home_chat as home_chat_routes,
|
|
46
46
|
privacy_disclose as privacy_disclose_routes,
|
|
47
47
|
signal as signal_routes,
|
|
48
|
+
tool_index as tool_index_routes,
|
|
48
49
|
upgrades as upgrades_routes,
|
|
49
50
|
)
|
|
50
51
|
from .config.settings import settings
|
|
51
52
|
from .core.logging import align_uvicorn_loggers, configure_logging
|
|
53
|
+
from .extensions import load_extensions
|
|
52
54
|
from .core import state
|
|
53
55
|
from .core.handlers import handle_control_plane_request
|
|
54
56
|
from .control_plane_client import ControlPlaneClient
|
|
@@ -65,6 +67,7 @@ from .sync import SyncClient
|
|
|
65
67
|
from .sync_handlers import handle_sync_op
|
|
66
68
|
|
|
67
69
|
configure_logging()
|
|
70
|
+
load_extensions()
|
|
68
71
|
logger = logging.getLogger("topos.app")
|
|
69
72
|
|
|
70
73
|
app = FastAPI(
|
|
@@ -128,10 +131,15 @@ app.include_router(privacy_disclose_routes.router)
|
|
|
128
131
|
app.include_router(compute_remote_routes.router)
|
|
129
132
|
app.include_router(engine_run_routes.router)
|
|
130
133
|
app.include_router(data_commit_routes.router)
|
|
134
|
+
app.include_router(tool_index_routes.router)
|
|
131
135
|
|
|
132
136
|
|
|
133
137
|
@app.on_event("startup")
|
|
134
138
|
async def startup_event() -> None:
|
|
139
|
+
from .runtime_shutdown import clear_shutdown, install_shutdown_signal_hooks
|
|
140
|
+
|
|
141
|
+
clear_shutdown()
|
|
142
|
+
install_shutdown_signal_hooks()
|
|
135
143
|
align_uvicorn_loggers()
|
|
136
144
|
_log_runtime_banner()
|
|
137
145
|
logger.info("CORS allowed origins: %s", settings.allowed_origins)
|
|
@@ -172,6 +180,20 @@ async def startup_event() -> None:
|
|
|
172
180
|
_start_upgrades(_upgrade_conn)
|
|
173
181
|
except Exception as e:
|
|
174
182
|
logger.warning("Upgrade runner at startup failed (non-fatal): %s", e)
|
|
183
|
+
try:
|
|
184
|
+
from .core.state import get_db_connection as _get_conn_for_pipeline
|
|
185
|
+
from .pipeline.job_runner import recover_pipeline_jobs, start_pipeline_worker
|
|
186
|
+
from .features.entities.graph_refresh import reconcile_graph_on_startup
|
|
187
|
+
|
|
188
|
+
_pipeline_conn = state.db_conn if state.db_conn is not None else _get_conn_for_pipeline()
|
|
189
|
+
if _pipeline_conn is not None:
|
|
190
|
+
recovered = recover_pipeline_jobs(_pipeline_conn)
|
|
191
|
+
if recovered:
|
|
192
|
+
logger.info("Recovered stale pipeline jobs on startup: count=%s", recovered)
|
|
193
|
+
reconcile_graph_on_startup(_pipeline_conn)
|
|
194
|
+
start_pipeline_worker(_get_conn_for_pipeline)
|
|
195
|
+
except Exception as e:
|
|
196
|
+
logger.warning("Pipeline worker at startup failed (non-fatal): %s", e)
|
|
175
197
|
try:
|
|
176
198
|
from .sources import install_service
|
|
177
199
|
|
|
@@ -185,6 +207,16 @@ async def startup_event() -> None:
|
|
|
185
207
|
)
|
|
186
208
|
except Exception as e:
|
|
187
209
|
logger.warning("Active source install rehydration at startup failed (non-fatal): %s", e)
|
|
210
|
+
if getattr(settings, "sanitization_prewarm_on_startup", True):
|
|
211
|
+
async def _prewarm_sanitization() -> None:
|
|
212
|
+
try:
|
|
213
|
+
from .sanitization.prewarm import prewarm_sanitization_models
|
|
214
|
+
|
|
215
|
+
await asyncio.to_thread(prewarm_sanitization_models)
|
|
216
|
+
except Exception as prewarm_exc: # noqa: BLE001
|
|
217
|
+
logger.warning("Sanitization prewarm at startup failed (non-fatal): %s", prewarm_exc)
|
|
218
|
+
|
|
219
|
+
asyncio.create_task(_prewarm_sanitization())
|
|
188
220
|
if settings.topos_control_plane_url:
|
|
189
221
|
if settings.hosted_pool_lease_enabled:
|
|
190
222
|
try:
|
|
@@ -282,6 +314,11 @@ async def startup_event() -> None:
|
|
|
282
314
|
|
|
283
315
|
@app.on_event("shutdown")
|
|
284
316
|
async def shutdown_event() -> None:
|
|
317
|
+
from .runtime_shutdown import request_shutdown
|
|
318
|
+
|
|
319
|
+
# Wake cooperative workers (fact_llm / Ollama threads) before awaiting
|
|
320
|
+
# network teardown so Ctrl+C does not wait out a full enrichment batch.
|
|
321
|
+
request_shutdown("app_shutdown")
|
|
285
322
|
await stop_runtime_update_monitor()
|
|
286
323
|
if state.engine_presence_task:
|
|
287
324
|
state.engine_presence_task.cancel()
|