topos-node 1.2.7__tar.gz → 1.3.1__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.7/topos_node.egg-info → topos_node-1.3.1}/PKG-INFO +1 -1
- {topos_node-1.2.7 → topos_node-1.3.1}/pyproject.toml +8 -2
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/__version__.py +2 -2
- topos_node-1.3.1/topos/api/conversation_context.py +142 -0
- topos_node-1.3.1/topos/api/facts_llm_config.py +63 -0
- topos_node-1.3.1/topos/api/local_mcp.py +119 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/signal.py +47 -1
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/app.py +43 -13
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/canonicalization/mappers/browser_activity_mapper.py +8 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/cli/commands.py +4 -0
- topos_node-1.3.1/topos/config/conversation_context_llm.py +106 -0
- topos_node-1.3.1/topos/config/facts_llm.py +128 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/config/settings.py +6 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/control_plane_client.py +4 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/handlers/config.py +134 -0
- topos_node-1.3.1/topos/core/handlers/query.py +175 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/handlers/signal_features.py +62 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/backends/generative_prompts.py +34 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/backends/generative_response.py +4 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/backends/ollama.py +138 -1
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/usage_observation.py +8 -2
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/catalog.py +13 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/__init__.py +3 -0
- topos_node-1.3.1/topos/enrichment/jobs/canonical/attention_triage_job.py +66 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/dimension_summary_job.py +13 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/fact_extraction_job.py +5 -1
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/orchestrator.py +14 -3
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/entities/declared_mappings.py +55 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/facts/extract.py +12 -2
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/facts/llm_extract.py +15 -10
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/facts/reads.py +1 -0
- topos_node-1.3.1/topos/features/facts/verdicts.py +209 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/fit/evaluator.py +58 -4
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/fit/opportunity_types.json +9 -0
- topos_node-1.3.1/topos/features/signal/conversation_context.py +147 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/definitions/intentions.json +40 -9
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/definitions/time.json +16 -4
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/extraction/artifact_router.py +21 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/extraction/rule_extractors.py +28 -2
- topos_node-1.3.1/topos/features/signal/typed_stores/aggregates.py +347 -0
- topos_node-1.3.1/topos/features/signal/typed_stores/commitments.py +136 -0
- topos_node-1.3.1/topos/features/signal/typed_stores/rhythm.py +171 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/typed_stores/scope_materializer.py +6 -0
- topos_node-1.3.1/topos/features/triage/__init__.py +4 -0
- topos_node-1.3.1/topos/features/triage/badges.py +223 -0
- topos_node-1.3.1/topos/features/triage/daily.py +609 -0
- topos_node-1.3.1/topos/features/triage/dashboard.py +80 -0
- topos_node-1.3.1/topos/features/triage/instruments.py +216 -0
- topos_node-1.3.1/topos/features/triage/intents.py +102 -0
- topos_node-1.3.1/topos/features/triage/readiness.py +58 -0
- topos_node-1.3.1/topos/protocol/handled_message_types.json +194 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/retrieval.py +172 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/scope_registry.json +36 -5
- topos_node-1.3.1/topos/query/truth_facts.py +74 -0
- topos_node-1.3.1/topos/query/truth_prompts.py +131 -0
- topos_node-1.3.1/topos/query/verify.py +388 -0
- topos_node-1.3.1/topos/query/verify_modes.py +147 -0
- topos_node-1.3.1/topos/runtime_housekeeping.py +117 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/sources/bundled_canonical_triples.py +24 -5
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/sources/canonical_signal_defaults.py +1 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/sources/install_service.py +55 -1
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/__init__.py +23 -0
- topos_node-1.3.1/topos/storage/db/migrations/attention_triage_v1.py +60 -0
- topos_node-1.3.1/topos/storage/db/migrations/attention_triage_v2.py +44 -0
- topos_node-1.3.1/topos/storage/db/migrations/conversation_context_v1.py +52 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/upgrades/manifests.json +40 -2
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/upgrades/runner.py +206 -28
- {topos_node-1.2.7 → topos_node-1.3.1/topos_node.egg-info}/PKG-INFO +1 -1
- {topos_node-1.2.7 → topos_node-1.3.1}/topos_node.egg-info/SOURCES.txt +24 -0
- topos_node-1.2.7/topos/api/local_mcp.py +0 -46
- topos_node-1.2.7/topos/core/handlers/query.py +0 -86
- topos_node-1.2.7/topos/features/signal/typed_stores/aggregates.py +0 -108
- topos_node-1.2.7/topos/protocol/handled_message_types.json +0 -181
- {topos_node-1.2.7 → topos_node-1.3.1}/LICENSE +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/MANIFEST.in +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/README.md +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/setup.cfg +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/shared/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/shared/filtering.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/shared/schema_registry.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/tests/test_extensions.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/tests/test_llm_integrations_storage.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/tests/test_protocol_handled_types.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/analytics/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/analytics/duckdb_adapter.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/analytics/messenger_communities.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/analytics/messenger_graph.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/analytics/messenger_labels.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/analytics/profiles.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/analytics/query_engine.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/analytics/raw_queries.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/analytics.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/app_registry.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/backup.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/compute_remote.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/data_commit.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/data_explorer_table_prefs.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/database_explorer.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/db.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/device.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/engine_run.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/enrichment.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/enrichment_lab.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/filter_lab.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/health.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/home_chat.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/ingestion_api.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/ingestion_compat.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/ingestion_sources.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/intelligence_lifecycle.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/llm.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/messenger_analytics.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/privacy_disclose.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/query_api.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/runtime_bootstrap.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/sanitization_ollama_config.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/signal_extraction_config.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/source_install.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/source_scrub.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/sources.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/sources_overview.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/sync.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/tool_index.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/ui_config.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/uma_data.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/upgrades.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/usage.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/api/user_identity.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/auth.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/canonicalization/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/canonicalization/mappers/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/canonicalization/mappers/base.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/canonicalization/mappers/chatgpt_mapper.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/canonicalization/mappers/demo_mappers.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/canonicalization/mappers/documents_mapper.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/canonicalization/mappers/github_activity_mapper.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/canonicalization/mappers/google_calendar_mapper.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/canonicalization/mappers/grok_mapper.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/canonicalization/mappers/messenger_mapper.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/canonicalization/models.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/canonicalization/resolver.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/cli/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/cli/__main__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/config/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/config/sanitization_ollama.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/config/signal_extraction.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/config/uvicorn_logging.json +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/contacts/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/contacts/identity.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/api_models.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/connection_resilience.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/device_helpers.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/errors.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/events.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/handlers/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/handlers/common.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/handlers/contacts_import.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/handlers/database_explorer.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/handlers/device.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/handlers/enrichment.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/handlers/enrichment_lab.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/handlers/filter_lab.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/handlers/home_chat.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/handlers/ingest.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/handlers/messages.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/handlers/messenger_analytics.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/handlers/registry.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/handlers/routines.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/handlers/sources.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/handlers/tool_index.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/handlers/uma.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/logging.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/metrics.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/routine_access.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/startup_banner.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/state.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/table_layers.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/core/types.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/data_explorer_row_delete.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/data_explorer_table_prefs.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/data_explorer_tables.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/disclosure/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/disclosure/canonical_writer.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/disclosure/content_policy.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/disclosure/field_registry.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/disclosure/privacy_layer.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/disclosure/tier.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/backends/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/backends/base.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/backends/huggingface.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/backends/openai.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/backends/openai_compatible.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/backends/redpill.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/backends/stub.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/client.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/engine.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/intake.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/memory_utils.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/model_cache.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/pipeline_memory.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/queue_manager.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/registration.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/result_formatter.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/router.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/scoped_token.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/tasks.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/transport.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/usage_guard.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/engine/validator.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/derived_tables.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/job_writer.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/base.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/_batch_limits.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/_engine_runner.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/availability_scores_job.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/brief_fallback.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/embeddings_job.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/emo_27_job.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/entities_job.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/goal_extraction_job.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/pii_redaction_job.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/relationship_edges_job.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/sentiment_job.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/statistics_job.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/timeline_job.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/topic_clusters_job.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/topics_job.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/url_classification_core.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/url_classification_enrichment_job.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/canonical/url_classification_signal_job.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/raw/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/raw/attachments_job.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/raw/language_job.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/raw/time_normalization_job.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/jobs/raw/tool_calls_job.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/model_overrides.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/models/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/models/manager.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/models/mvp_defaults.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/models/registry.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/models/versioning.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/processor.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/progress_bar.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/registry_contract.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/signal_derivation_config.json +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/source_overrides.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment/website_classifier.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment_lab/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment_lab/bundles.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment_lab/model_resolve.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment_lab/schema.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment_lab/service.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment_lab/store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/enrichment_lab/worker.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/evals/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/evals/enrichment_eval.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/extensions.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/entities/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/entities/consolidation.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/entities/dossier.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/entities/edges.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/entities/fact_materializer.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/entities/graph_enrichers.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/entities/graph_refresh.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/entities/graph_search.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/entities/linking.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/entities/maintenance.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/entities/reads.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/entities/resolver.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/facts/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/facts/store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/lifecycle/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/lifecycle/derived_scrub.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/lifecycle/exclusions.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/lifecycle/gc.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/provenance/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/provenance/posture.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/provenance/roles.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/brief_canonical_loader.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/brief_ontology.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/brief_renderer.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/brief_schemas.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/chunking.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/cluster_labels.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/data_health.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/definitions/brief_ontologies.json +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/definitions/profile.json +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/definitions/relationships.json +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/definitions/schema/dimension_definition.schema.json +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/definitions/work.json +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/dimension_briefs.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/dimension_definition_loader.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/dimension_profiles.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/dimension_registry.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/embed_context.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/extraction/artifact_store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/graph_sanitize.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/hybrid_search.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/incremental_clustering.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/model_recommendations.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/query_embed_cache.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/schemas.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/service.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/signal_object_store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/source_hydration.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/structured_signal.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/tool_index.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/topic_clustering.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/vector_codec.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/vector_math.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/signal/vector_settings.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/stats/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/stats/definitions.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/stats/engine.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/stats/fold.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/stats/insights.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/features/timeline_projection.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/filter_lab/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/filter_lab/bundles.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/filter_lab/schema.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/filter_lab/service.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/filter_lab/store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/filter_lab/worker.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/home_chat/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/home_chat/schema.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/home_chat/store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/hosted_pool_lease.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/canonical_pipeline.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/checkpoints/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/checkpoints/checkpoint_store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/checkpoints/sqlite_checkpoint_store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/inbox_crypto.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/inbox_drain.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/ingest_helpers.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/jobs.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/journal_location_fanout.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/journal_time_log_normalize.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/local_sync.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/log_preview.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/manager.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/parser.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/parsers/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/parsers/base.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/parsers/browser_parser.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/parsers/calendar_parser.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/parsers/chatgpt_conversation_flattener.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/parsers/chatgpt_parser.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/parsers/demo_file_parsers.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/parsers/documents_parser.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/parsers/github_activity_parser.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/parsers/google_calendar_parser.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/parsers/grok_parser.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/parsers/messenger_parser.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/parsers/voxterm_parser.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/progress.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/reprocess.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/sources/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/sources/base.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/sources/calendar.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/sources/chatgpt.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/sources/contact_importers.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/sources/grok.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/sources/imessage_reader.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/sources/signal_export_parser.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/sources/signal_reader.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/state_machine.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/triggers/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/triggers/file_trigger.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/triggers/sqlite_trigger.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/usage_inbox_dedupe.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/validation/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/validation/base.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/validation/schema_registry.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/ingestion/validation/schema_validator.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/lineage/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/lineage/provenance.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/lineage/tracker.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/llm_integrations_storage.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/mcp_stdio_proxy.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/observability/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/observability/alerts.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/observability/metrics.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/observability/tracing.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/openai_client.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/pipeline/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/pipeline/audit.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/pipeline/envelope.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/pipeline/job_runner.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/pipeline/job_store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/pipeline/stages.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/pipeline/stub_enqueue.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/projections/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/projections/vector_index/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/projections/vector_index/base.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/projections/vector_index/builders.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/projections/vector_index/health_checks.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/protocol/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/audit.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/ddr.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/disclosure.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/fingerprint.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/game_layer.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/grant_cache.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/inference.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/intent.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/manifest.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/manifest_validation.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/minimizer.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/negotiation.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/pipeline.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/planner.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/runtime.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/scope_registry_loader.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/session.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/session_utils.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/source_generation.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/turn_classifier.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/query/types.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/rate_limit.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/routines/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/routines/schema.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/routines/store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/runtime_shutdown.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/runtime_update.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/sanitization/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/sanitization/nsfw_classifier.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/sanitization/ollama_transforms.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/sanitization/prewarm.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/sanitization/privacy_filter.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/scope_resolution.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/services/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/services/container.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/services/embeddings/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/services/embeddings/base.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/services/embeddings/local.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/services/embeddings/remote.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/services/interfaces.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/services/llm/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/services/llm/base.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/services/llm/openai.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/services/local.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/services/postgres.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/sources/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/sources/definitions.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/sources/registry.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/sources/runtime_install.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/sources/scrub_attribution.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/sources/scrub_service.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/startup_banner.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/adapters/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/adapters/factory.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/adapters/fakes.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/adapters/postgres/stores.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/adapters/protocols.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/adapters/sqlite/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/adapters/sqlite/stores.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/adapters/sqlite/vector_search.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/canonical/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/canonical/activity_tables.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/canonical/ai_chat/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/canonical/ai_chat/canonicalizer.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/canonical/ai_chat/mapper.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/canonical/ai_chat/model.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/canonical/ai_chat/tables.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/canonical/calendar_contacts_tables.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/canonical/canonical_store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/canonical/conversations_tables.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/canonical/mapping_store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/canonical/postgres.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/client.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/connection_tuning.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/activity_events_content_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/actor_role_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/calendar_events_scheduling_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/canonical_address_book_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/canonical_disclosure_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/canonical_nsfw_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/derivation_ledger_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/documents_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/entity_edges_validity_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/episodes_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/extraction_artifacts.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/journal_entries_duration_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/journal_entries_ends_at_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/journal_entries_people_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/journal_entries_place_name_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/journal_entries_starts_at_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/pipeline_jobs_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/remediation_person_model.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/scope_source_generation.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/signal_dimension_backfill_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/signal_dimension_harness.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/signal_objects.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/signal_objects_period_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/signal_objects_updated_by_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/stage9_column_renames.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/vector_storage_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/vector_storage_v2.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/vector_storage_v3.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/vector_storage_v4.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/wiki_clusters_v2.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/wiki_entities_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/wiki_entity_review_v2.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/wiki_facts_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/wiki_lifecycle_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/wiki_mvp_phase0.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/wiki_mvp_phase1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/wiki_mvp_phase4_messages_cutover.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/wiki_mvp_phase5_topic_clusters.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/wiki_mvp_phase6_dimension_briefs.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/wiki_mvp_query_quality.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/wiki_mvp_topic_clusters_coordination.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/wiki_stats_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/migrations/wiki_timeline_v1.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/paths.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/postgres.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/schema.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/storage_breakdown.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/db/write_gate.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/enrichment/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/enrichment/canonical_enrichment_store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/enrichment/raw_enrichment_store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/normalized/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/normalized/normalized_store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/oplog/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/oplog/decision.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/oplog/oplog_store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/oplog/postgres.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/person/identity_resolver.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/projections/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/projections/index_ops_store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/projections/vector_index_store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/raw/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/raw/browser_flat_tables.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/raw/file_store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/raw/raw_store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/raw/raw_tables_manager.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/raw/sqlite_raw_store.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/security/encryption.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/signal_identity.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/source_settings.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/storage/user_identity.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/sync/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/sync/client.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/sync_handlers.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/testing/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/testing/lifespan.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/uma_contact_enrichment.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/uma_filters.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/uma_resource_id.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/uma_rpt.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/upgrades/__init__.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/utils/base_object.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos/websocket_client.py +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos_node.egg-info/dependency_links.txt +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos_node.egg-info/entry_points.txt +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/topos_node.egg-info/requires.txt +0 -0
- {topos_node-1.2.7 → topos_node-1.3.1}/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.
|
|
7
|
+
version = "1.3.1"
|
|
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"
|
|
@@ -84,6 +84,12 @@ where = ["."]
|
|
|
84
84
|
include = ["topos*", "shared*"]
|
|
85
85
|
|
|
86
86
|
[tool.pytest.ini_options]
|
|
87
|
+
# tmp_path hygiene: this suite's fixtures build whole node DBs (100s of MB per
|
|
88
|
+
# run). Keep only the last run's FAILED dirs — passed dirs are removed as tests
|
|
89
|
+
# finish, so tmp never accumulates across runs. Killed runs can still leave
|
|
90
|
+
# locked roots behind; topos.runtime_housekeeping sweeps those on node start.
|
|
91
|
+
tmp_path_retention_count = 1
|
|
92
|
+
tmp_path_retention_policy = "failed"
|
|
87
93
|
filterwarnings = [
|
|
88
94
|
"ignore::DeprecationWarning:pydantic.*",
|
|
89
95
|
"ignore:on_event is deprecated.*:DeprecationWarning:fastapi.*",
|
|
@@ -106,5 +112,5 @@ markers = [
|
|
|
106
112
|
"eval_nightly: statistical privacy eval (attacker advantage, minimality, latency); nightly",
|
|
107
113
|
"eval_release: release-tier privacy eval (negotiation A/B, Pareto); run per release",
|
|
108
114
|
]
|
|
109
|
-
pythonpath = ["tests/gap/p3/engine", "tests/gap/p4/engine", "tests/gap/qq/engine", "tests/acceptance/wiki_mvp"]
|
|
115
|
+
pythonpath = ["tests/gap/p3/engine", "tests/gap/p4/engine", "tests/gap/qq/engine", "tests/acceptance/wiki_mvp", "tests/evals/time_signal"]
|
|
110
116
|
testpaths = ["tests"]
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"""Owner-set conversation context tag (work | personal).
|
|
2
|
+
|
|
3
|
+
Second labeling axis alongside source posture: posture says whose words the
|
|
4
|
+
content is; context_tag says which life domain the thread belongs to. Set at
|
|
5
|
+
the conversation level (the thread in `conversations`); every message in the
|
|
6
|
+
thread inherits it at read/derivation time. Owner-only; never inferred here.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from fastapi import APIRouter, Body, Depends, HTTPException
|
|
12
|
+
|
|
13
|
+
from ..auth import require_api_key
|
|
14
|
+
from ..core.state import get_db_connection
|
|
15
|
+
from ..storage.db.migrations.conversation_context_v1 import CONTEXT_TAG_VALUES
|
|
16
|
+
|
|
17
|
+
router = APIRouter()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _conversation_row(conn, conversation_id: str, dataset_id: str):
|
|
21
|
+
return conn.execute(
|
|
22
|
+
"SELECT conversation_id, dataset_id, context_tag, context_tag_source "
|
|
23
|
+
"FROM conversations WHERE conversation_id=? AND dataset_id=?",
|
|
24
|
+
(conversation_id, dataset_id),
|
|
25
|
+
).fetchone()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def read_conversation_context(conn, conversation_id: str, dataset_id: str) -> dict | None:
|
|
29
|
+
"""Context-tag payload for a conversation, or None when it is unknown.
|
|
30
|
+
|
|
31
|
+
Shared by the HTTP endpoint below and the WS handler
|
|
32
|
+
(core.handlers.config get_conversation_context) so both stay one source.
|
|
33
|
+
"""
|
|
34
|
+
row = _conversation_row(conn, conversation_id, dataset_id)
|
|
35
|
+
if row is None:
|
|
36
|
+
return None
|
|
37
|
+
return {
|
|
38
|
+
"status": "ok",
|
|
39
|
+
"conversation_id": row[0],
|
|
40
|
+
"dataset_id": row[1],
|
|
41
|
+
"context_tag": row[2],
|
|
42
|
+
"context_tag_source": row[3],
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def write_conversation_context(conn, conversation_id: str, dataset_id: str, raw_tag) -> dict:
|
|
47
|
+
"""Owner set/clear of the context tag.
|
|
48
|
+
|
|
49
|
+
Raises ValueError on an invalid tag, LookupError when the conversation is
|
|
50
|
+
unknown. Shared by the HTTP endpoint and the WS handler.
|
|
51
|
+
"""
|
|
52
|
+
tag = str(raw_tag).strip().lower() if raw_tag is not None else None
|
|
53
|
+
if tag is not None and tag not in CONTEXT_TAG_VALUES:
|
|
54
|
+
raise ValueError(f"context_tag must be one of {sorted(CONTEXT_TAG_VALUES)} or null")
|
|
55
|
+
if _conversation_row(conn, conversation_id, dataset_id) is None:
|
|
56
|
+
raise LookupError("Unknown conversation")
|
|
57
|
+
# Owner decisions always win: stamped 'owner' even when clearing, so the
|
|
58
|
+
# auto-classifier never refills a conversation the owner chose to untag.
|
|
59
|
+
conn.execute(
|
|
60
|
+
"UPDATE conversations SET context_tag=?, context_tag_source='owner', "
|
|
61
|
+
"updated_at=datetime('now') WHERE conversation_id=? AND dataset_id=?",
|
|
62
|
+
(tag, conversation_id, dataset_id),
|
|
63
|
+
)
|
|
64
|
+
conn.commit()
|
|
65
|
+
return {
|
|
66
|
+
"status": "ok",
|
|
67
|
+
"conversation_id": conversation_id,
|
|
68
|
+
"dataset_id": dataset_id,
|
|
69
|
+
"context_tag": tag,
|
|
70
|
+
"context_tag_source": "owner",
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@router.get(
|
|
75
|
+
"/conversations/{conversation_id}/context",
|
|
76
|
+
dependencies=[Depends(require_api_key)],
|
|
77
|
+
)
|
|
78
|
+
async def get_conversation_context(conversation_id: str, dataset_id: str) -> dict:
|
|
79
|
+
conn = get_db_connection()
|
|
80
|
+
if conn is None:
|
|
81
|
+
raise HTTPException(status_code=503, detail="Database not available")
|
|
82
|
+
data = read_conversation_context(conn, conversation_id, dataset_id)
|
|
83
|
+
if data is None:
|
|
84
|
+
raise HTTPException(status_code=404, detail="Unknown conversation")
|
|
85
|
+
return data
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@router.put(
|
|
89
|
+
"/conversations/{conversation_id}/context",
|
|
90
|
+
dependencies=[Depends(require_api_key)],
|
|
91
|
+
)
|
|
92
|
+
async def set_conversation_context(
|
|
93
|
+
conversation_id: str,
|
|
94
|
+
payload: dict = Body(default_factory=dict),
|
|
95
|
+
) -> dict:
|
|
96
|
+
dataset_id = str(payload.get("dataset_id") or "").strip()
|
|
97
|
+
if not dataset_id:
|
|
98
|
+
raise HTTPException(status_code=422, detail="dataset_id is required")
|
|
99
|
+
conn = get_db_connection()
|
|
100
|
+
if conn is None:
|
|
101
|
+
raise HTTPException(status_code=503, detail="Database not available")
|
|
102
|
+
try:
|
|
103
|
+
return write_conversation_context(conn, conversation_id, dataset_id, payload.get("context_tag"))
|
|
104
|
+
except ValueError as exc:
|
|
105
|
+
raise HTTPException(status_code=422, detail=str(exc)) from exc
|
|
106
|
+
except LookupError as exc:
|
|
107
|
+
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
# --- classifier model config (settings surface) -----------------------------------
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@router.get("/conversation-context-llm-config", dependencies=[Depends(require_api_key)])
|
|
114
|
+
async def get_context_llm_config() -> dict:
|
|
115
|
+
from ..config.conversation_context_llm import effective_config_for_api
|
|
116
|
+
from ..config.settings import settings
|
|
117
|
+
|
|
118
|
+
conn = get_db_connection()
|
|
119
|
+
if conn is None:
|
|
120
|
+
raise HTTPException(status_code=503, detail="Database not available")
|
|
121
|
+
return {"status": "ok", **effective_config_for_api(settings, conn)}
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@router.put("/conversation-context-llm-config", dependencies=[Depends(require_api_key)])
|
|
125
|
+
async def put_context_llm_config(payload: dict = Body(default=None)) -> dict:
|
|
126
|
+
from ..config.conversation_context_llm import (
|
|
127
|
+
ENGINE_CONFIG_KEY_CONVERSATION_CONTEXT_LLM_MODEL,
|
|
128
|
+
effective_config_for_api,
|
|
129
|
+
normalize_put_model,
|
|
130
|
+
)
|
|
131
|
+
from ..config.settings import settings
|
|
132
|
+
from ..core.state import set_engine_config_value
|
|
133
|
+
|
|
134
|
+
conn = get_db_connection()
|
|
135
|
+
if conn is None:
|
|
136
|
+
raise HTTPException(status_code=503, detail="Database not available")
|
|
137
|
+
try:
|
|
138
|
+
model = normalize_put_model(payload)
|
|
139
|
+
except ValueError as exc:
|
|
140
|
+
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
|
141
|
+
set_engine_config_value(conn, ENGINE_CONFIG_KEY_CONVERSATION_CONTEXT_LLM_MODEL, model)
|
|
142
|
+
return {"status": "ok", **effective_config_for_api(settings, conn)}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""Read/update the owner-selected facts-LLM extraction model (engine_config)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from fastapi import APIRouter, Body, Depends, HTTPException
|
|
9
|
+
|
|
10
|
+
from ..auth import require_api_key
|
|
11
|
+
from ..config.facts_llm import (
|
|
12
|
+
ENGINE_CONFIG_KEY_FACTS_LLM_MODEL,
|
|
13
|
+
effective_config_for_api,
|
|
14
|
+
normalize_put_model,
|
|
15
|
+
)
|
|
16
|
+
from ..config.settings import settings
|
|
17
|
+
from ..core.state import get_db_connection, set_engine_config_value
|
|
18
|
+
|
|
19
|
+
logger = logging.getLogger("topos.api.facts_llm_config")
|
|
20
|
+
|
|
21
|
+
router = APIRouter(tags=["facts-llm"])
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@router.get("/v1/facts-llm-config", dependencies=[Depends(require_api_key)])
|
|
25
|
+
async def get_facts_llm_config() -> dict[str, Any]:
|
|
26
|
+
conn = get_db_connection()
|
|
27
|
+
if not conn:
|
|
28
|
+
raise HTTPException(status_code=503, detail="Database not available")
|
|
29
|
+
try:
|
|
30
|
+
return {"status": "ok", **effective_config_for_api(settings, conn)}
|
|
31
|
+
except Exception as exc: # noqa: BLE001
|
|
32
|
+
logger.warning("get_facts_llm_config failed: %s", exc)
|
|
33
|
+
raise HTTPException(status_code=500, detail="Failed to read config") from exc
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@router.put("/v1/facts-llm-config", dependencies=[Depends(require_api_key)])
|
|
37
|
+
async def put_facts_llm_config(body: dict[str, Any] = Body(default=None)) -> dict[str, Any]:
|
|
38
|
+
conn = get_db_connection()
|
|
39
|
+
if not conn:
|
|
40
|
+
raise HTTPException(status_code=503, detail="Database not available")
|
|
41
|
+
try:
|
|
42
|
+
model = normalize_put_model(body)
|
|
43
|
+
set_engine_config_value(conn, ENGINE_CONFIG_KEY_FACTS_LLM_MODEL, model)
|
|
44
|
+
return {"status": "ok", **effective_config_for_api(settings, conn)}
|
|
45
|
+
except ValueError as exc:
|
|
46
|
+
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
|
47
|
+
except Exception as exc: # noqa: BLE001
|
|
48
|
+
logger.warning("put_facts_llm_config failed: %s", exc)
|
|
49
|
+
raise HTTPException(status_code=500, detail="Failed to save config") from exc
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@router.delete("/v1/facts-llm-config", dependencies=[Depends(require_api_key)])
|
|
53
|
+
async def delete_facts_llm_model_override() -> dict[str, Any]:
|
|
54
|
+
"""Clear the device override; the effective model reverts to env defaults."""
|
|
55
|
+
conn = get_db_connection()
|
|
56
|
+
if not conn:
|
|
57
|
+
raise HTTPException(status_code=503, detail="Database not available")
|
|
58
|
+
try:
|
|
59
|
+
set_engine_config_value(conn, ENGINE_CONFIG_KEY_FACTS_LLM_MODEL, "")
|
|
60
|
+
return {"status": "ok", **effective_config_for_api(settings, conn)}
|
|
61
|
+
except Exception as exc: # noqa: BLE001
|
|
62
|
+
logger.warning("delete facts_llm model override failed: %s", exc)
|
|
63
|
+
raise HTTPException(status_code=500, detail="Failed to clear config") from exc
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"""Local API for MCP-style tools (no Control Plane). Same auth as engine; for same-device/offline use."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import uuid
|
|
6
|
+
|
|
7
|
+
from fastapi import APIRouter, Body, Depends
|
|
8
|
+
|
|
9
|
+
from ..auth import require_api_key
|
|
10
|
+
from ..core.handlers import handle_control_plane_request
|
|
11
|
+
|
|
12
|
+
router = APIRouter(prefix="/api/local", tags=["local-mcp"])
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _local_mcp_payload(extra: dict | None = None) -> dict:
|
|
16
|
+
"""Payload for local MCP requests; source=claude_desktop so engine counts per source."""
|
|
17
|
+
p = {"mcp_source": "claude_desktop"}
|
|
18
|
+
if extra:
|
|
19
|
+
p.update(extra)
|
|
20
|
+
return p
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@router.post("/list_database_tables")
|
|
24
|
+
async def local_list_database_tables(_: None = Depends(require_api_key)) -> dict: # noqa: B008
|
|
25
|
+
"""List tables (same as CP-forwarded tool). Requires Bearer TOPOS_KEY."""
|
|
26
|
+
msg = {"id": str(uuid.uuid4()), "type": "list_database_tables", "payload": _local_mcp_payload()}
|
|
27
|
+
out = await handle_control_plane_request(msg)
|
|
28
|
+
if out.get("status") == "error":
|
|
29
|
+
return {"status": "error", "error": out.get("error", "unknown")}
|
|
30
|
+
return out.get("payload", {})
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@router.post("/verify_claim")
|
|
34
|
+
async def local_verify_claim(
|
|
35
|
+
body: dict = Body(default_factory=dict),
|
|
36
|
+
_: None = Depends(require_api_key), # noqa: B008
|
|
37
|
+
) -> dict:
|
|
38
|
+
"""Same-device truth check (PLAN_TRUTHFULNESS_PLUGIN.md). Owner-key only;
|
|
39
|
+
mirrors the CP door: `app_id` is mandatory and `mode` is pinned to fun —
|
|
40
|
+
this route cannot reach a mode the registry doesn't ship. Body:
|
|
41
|
+
{"statement": "...", "app_id": "truth-mirror"}."""
|
|
42
|
+
statement = str(body.get("statement") or "").strip()
|
|
43
|
+
app_id = str(body.get("app_id") or "").strip()
|
|
44
|
+
if not statement or not app_id:
|
|
45
|
+
return {"status": "error", "error": "statement and app_id required"}
|
|
46
|
+
msg = {
|
|
47
|
+
"id": str(uuid.uuid4()),
|
|
48
|
+
"type": "verify_claim",
|
|
49
|
+
"payload": {"statement": statement, "mode": "fun", "caller_app_id": app_id},
|
|
50
|
+
}
|
|
51
|
+
out = await handle_control_plane_request(msg)
|
|
52
|
+
if out.get("status") == "error":
|
|
53
|
+
return {"status": "error", "error": out.get("error", "unknown")}
|
|
54
|
+
return out.get("payload", {})
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@router.post("/truth_prompts")
|
|
58
|
+
async def local_truth_prompts(
|
|
59
|
+
body: dict = Body(default_factory=dict),
|
|
60
|
+
_: None = Depends(require_api_key), # noqa: B008
|
|
61
|
+
) -> dict:
|
|
62
|
+
"""Same-device "ask me" prompt seeds (fun aperture; topics only, no
|
|
63
|
+
stances). Body: {"app_id": "truth-mirror", "limit": 5}."""
|
|
64
|
+
app_id = str(body.get("app_id") or "").strip()
|
|
65
|
+
if not app_id:
|
|
66
|
+
return {"status": "error", "error": "app_id required"}
|
|
67
|
+
msg = {
|
|
68
|
+
"id": str(uuid.uuid4()),
|
|
69
|
+
"type": "truth_prompts",
|
|
70
|
+
"payload": {"mode": "fun", "caller_app_id": app_id,
|
|
71
|
+
"limit": int(body.get("limit") or 5)},
|
|
72
|
+
}
|
|
73
|
+
out = await handle_control_plane_request(msg)
|
|
74
|
+
if out.get("status") == "error":
|
|
75
|
+
return {"status": "error", "error": out.get("error", "unknown")}
|
|
76
|
+
return out.get("payload", {})
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@router.post("/truth_seed_fact")
|
|
80
|
+
async def local_truth_seed_fact(
|
|
81
|
+
body: dict = Body(default_factory=dict),
|
|
82
|
+
_: None = Depends(require_api_key), # noqa: B008
|
|
83
|
+
) -> dict:
|
|
84
|
+
"""Owner adds a fun fact to their own sheet (refused outside the fun
|
|
85
|
+
aperture). Body: {"predicate": "favorite_food", "value": "tacos",
|
|
86
|
+
"app_id": "truth-mirror"}."""
|
|
87
|
+
app_id = str(body.get("app_id") or "").strip()
|
|
88
|
+
if not app_id:
|
|
89
|
+
return {"status": "error", "error": "app_id required"}
|
|
90
|
+
msg = {
|
|
91
|
+
"id": str(uuid.uuid4()),
|
|
92
|
+
"type": "truth_seed_fact",
|
|
93
|
+
"payload": {
|
|
94
|
+
"mode": "fun",
|
|
95
|
+
"caller_app_id": app_id,
|
|
96
|
+
"predicate": str(body.get("predicate") or ""),
|
|
97
|
+
"value": str(body.get("value") or ""),
|
|
98
|
+
},
|
|
99
|
+
}
|
|
100
|
+
out = await handle_control_plane_request(msg)
|
|
101
|
+
if out.get("status") == "error":
|
|
102
|
+
return {"status": "error", "error": out.get("error", "unknown")}
|
|
103
|
+
return out.get("payload", {})
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@router.post("/get_table_schema")
|
|
107
|
+
async def local_get_table_schema(
|
|
108
|
+
body: dict = Body(default_factory=dict),
|
|
109
|
+
_: None = Depends(require_api_key), # noqa: B008
|
|
110
|
+
) -> dict:
|
|
111
|
+
"""Get table schema (same as CP-forwarded tool). Body: {"table_name": "..."}. Requires Bearer TOPOS_KEY."""
|
|
112
|
+
table_name = (body.get("table_name") or "").strip()
|
|
113
|
+
if not table_name:
|
|
114
|
+
return {"status": "error", "error": "table_name required"}
|
|
115
|
+
msg = {"id": str(uuid.uuid4()), "type": "get_table_schema", "payload": _local_mcp_payload({"table_name": table_name})}
|
|
116
|
+
out = await handle_control_plane_request(msg)
|
|
117
|
+
if out.get("status") == "error":
|
|
118
|
+
return {"status": "error", "error": out.get("error", "unknown")}
|
|
119
|
+
return out.get("payload", {})
|
|
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
import logging
|
|
6
6
|
from typing import Any, Dict, Optional
|
|
7
7
|
|
|
8
|
-
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
8
|
+
from fastapi import APIRouter, Body, Depends, HTTPException, Query
|
|
9
9
|
from pydantic import BaseModel, Field
|
|
10
10
|
|
|
11
11
|
from ..auth import require_api_key
|
|
@@ -480,6 +480,34 @@ async def list_facts(
|
|
|
480
480
|
)
|
|
481
481
|
|
|
482
482
|
|
|
483
|
+
@router.post("/facts/verdict")
|
|
484
|
+
async def post_fact_verdict(
|
|
485
|
+
object_id: str = Body(...),
|
|
486
|
+
action: str = Body(..., description="confirm | reject | edit"),
|
|
487
|
+
object_value: Optional[str] = Body(default=None),
|
|
488
|
+
asserted_by: Optional[str] = Body(default=None),
|
|
489
|
+
note: Optional[str] = Body(default=None),
|
|
490
|
+
_api_key: str = Depends(require_api_key),
|
|
491
|
+
):
|
|
492
|
+
"""Owner verdict on one fact: confirm (attest true), reject (close +
|
|
493
|
+
tombstone this value), or edit (correct the value and/or attribution)."""
|
|
494
|
+
from ..features.facts.verdicts import apply_fact_verdict
|
|
495
|
+
|
|
496
|
+
try:
|
|
497
|
+
return apply_fact_verdict(
|
|
498
|
+
_entities_conn(),
|
|
499
|
+
object_id=object_id,
|
|
500
|
+
action=action,
|
|
501
|
+
object_value=object_value,
|
|
502
|
+
asserted_by=asserted_by,
|
|
503
|
+
note=note,
|
|
504
|
+
)
|
|
505
|
+
except LookupError as exc:
|
|
506
|
+
raise HTTPException(status_code=404, detail=str(exc))
|
|
507
|
+
except ValueError as exc:
|
|
508
|
+
raise HTTPException(status_code=400, detail=str(exc))
|
|
509
|
+
|
|
510
|
+
|
|
483
511
|
@router.get("/insights")
|
|
484
512
|
async def list_stat_insights(
|
|
485
513
|
dimension: Optional[str] = Query(default=None, max_length=40),
|
|
@@ -623,3 +651,21 @@ async def refresh_dimension_brief(
|
|
|
623
651
|
return await service.refresh_brief(dimension, limit=limit)
|
|
624
652
|
except ValueError as exc:
|
|
625
653
|
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
|
654
|
+
|
|
655
|
+
|
|
656
|
+
# --------------------------------------------------------------- attention triage
|
|
657
|
+
|
|
658
|
+
@router.get("/attention/dashboard")
|
|
659
|
+
async def attention_dashboard(
|
|
660
|
+
_api_key: str = Depends(require_api_key),
|
|
661
|
+
days: int = Query(14, ge=1, le=90),
|
|
662
|
+
include_titles: bool = Query(True),
|
|
663
|
+
):
|
|
664
|
+
"""Data spine for the /data/attention tab (PLAN_ATTENTION_ANALYTICS_EXECUTION WS5.1)."""
|
|
665
|
+
from ..core.state import get_db_connection
|
|
666
|
+
from ..features.triage.dashboard import attention_dashboard_data
|
|
667
|
+
|
|
668
|
+
conn = get_db_connection()
|
|
669
|
+
if conn is None:
|
|
670
|
+
raise HTTPException(status_code=503, detail="database unavailable")
|
|
671
|
+
return attention_dashboard_data(conn, days=days, include_titles=include_titles)
|
|
@@ -5,6 +5,7 @@ import importlib.util
|
|
|
5
5
|
import logging
|
|
6
6
|
import os
|
|
7
7
|
import sys
|
|
8
|
+
import threading
|
|
8
9
|
|
|
9
10
|
from fastapi import FastAPI
|
|
10
11
|
from fastapi.middleware.cors import CORSMiddleware
|
|
@@ -15,6 +16,7 @@ from .api import (
|
|
|
15
16
|
app_registry as app_registry_routes,
|
|
16
17
|
backup as backup_routes,
|
|
17
18
|
compute_remote as compute_remote_routes,
|
|
19
|
+
conversation_context as conversation_context_routes,
|
|
18
20
|
engine_run as engine_run_routes,
|
|
19
21
|
data_commit as data_commit_routes,
|
|
20
22
|
db as db_routes,
|
|
@@ -39,6 +41,7 @@ from .api import (
|
|
|
39
41
|
ui_config as ui_config_routes,
|
|
40
42
|
data_explorer_table_prefs as data_explorer_table_prefs_routes,
|
|
41
43
|
sanitization_ollama_config as sanitization_ollama_config_routes,
|
|
44
|
+
facts_llm_config as facts_llm_config_routes,
|
|
42
45
|
signal_extraction_config as signal_extraction_config_routes,
|
|
43
46
|
filter_lab as filter_lab_routes,
|
|
44
47
|
enrichment_lab as enrichment_lab_routes,
|
|
@@ -106,6 +109,7 @@ app.include_router(device_routes.router)
|
|
|
106
109
|
app.include_router(backup_routes.router)
|
|
107
110
|
app.include_router(analytics_routes.router)
|
|
108
111
|
app.include_router(sources_routes.router)
|
|
112
|
+
app.include_router(conversation_context_routes.router, prefix="/v1")
|
|
109
113
|
app.include_router(source_install_routes.router, prefix="/v1")
|
|
110
114
|
app.include_router(source_scrub_routes.router, prefix="/v1")
|
|
111
115
|
app.include_router(intelligence_lifecycle_routes.router, prefix="/v1")
|
|
@@ -123,6 +127,7 @@ app.include_router(ui_config_routes.router)
|
|
|
123
127
|
app.include_router(data_explorer_table_prefs_routes.router)
|
|
124
128
|
app.include_router(user_identity_routes.router)
|
|
125
129
|
app.include_router(sanitization_ollama_config_routes.router)
|
|
130
|
+
app.include_router(facts_llm_config_routes.router)
|
|
126
131
|
app.include_router(signal_extraction_config_routes.router)
|
|
127
132
|
app.include_router(filter_lab_routes.router)
|
|
128
133
|
app.include_router(enrichment_lab_routes.router)
|
|
@@ -167,19 +172,9 @@ async def startup_event() -> None:
|
|
|
167
172
|
logger.info("Stage 9 migrations applied at startup: %d renames", len(result["applied"]))
|
|
168
173
|
except Exception as e:
|
|
169
174
|
logger.debug("Stage 9 migrations at startup (non-fatal): %s", e)
|
|
170
|
-
# Upgrade runner
|
|
171
|
-
#
|
|
172
|
-
#
|
|
173
|
-
# stale derived data meanwhile. Fresh installs stamp-and-skip.
|
|
174
|
-
try:
|
|
175
|
-
from .core.state import get_db_connection as _get_conn_for_upgrades
|
|
176
|
-
from .upgrades.runner import start_background as _start_upgrades
|
|
177
|
-
|
|
178
|
-
_upgrade_conn = state.db_conn if state.db_conn is not None else _get_conn_for_upgrades()
|
|
179
|
-
if _upgrade_conn is not None:
|
|
180
|
-
_start_upgrades(_upgrade_conn)
|
|
181
|
-
except Exception as e:
|
|
182
|
-
logger.warning("Upgrade runner at startup failed (non-fatal): %s", e)
|
|
175
|
+
# Upgrade runner is armed later — after control-plane / local readiness —
|
|
176
|
+
# so the React UI can fetch bootstrap data before enrichment reprocess
|
|
177
|
+
# contends for SQLite / Ollama / MPS. See _arm_upgrade_runner below.
|
|
183
178
|
try:
|
|
184
179
|
from .core.state import get_db_connection as _get_conn_for_pipeline
|
|
185
180
|
from .pipeline.job_runner import recover_pipeline_jobs, start_pipeline_worker
|
|
@@ -291,6 +286,41 @@ async def startup_event() -> None:
|
|
|
291
286
|
start_runtime_update_monitor()
|
|
292
287
|
start_update_hotkey_listener()
|
|
293
288
|
|
|
289
|
+
# Upgrade runner: plan/stamp cheaply, but defer heavy re-derivation until the
|
|
290
|
+
# UI can bootstrap (CP connected + grace). Fresh installs stamp-and-skip.
|
|
291
|
+
try:
|
|
292
|
+
from .core.state import get_db_connection as _get_conn_for_upgrades
|
|
293
|
+
from .upgrades.runner import (
|
|
294
|
+
ready_timeout_seconds as _upgrade_ready_timeout,
|
|
295
|
+
start_background as _start_upgrades,
|
|
296
|
+
ui_grace_seconds as _upgrade_ui_grace,
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
_upgrade_conn = state.db_conn if state.db_conn is not None else _get_conn_for_upgrades()
|
|
300
|
+
if _upgrade_conn is not None:
|
|
301
|
+
_upgrade_ready = threading.Event()
|
|
302
|
+
_start_upgrades(
|
|
303
|
+
_upgrade_conn,
|
|
304
|
+
ready_event=_upgrade_ready,
|
|
305
|
+
ui_grace_s=_upgrade_ui_grace(),
|
|
306
|
+
ready_timeout_s=_upgrade_ready_timeout(),
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
async def _signal_upgrade_ui_ready() -> None:
|
|
310
|
+
try:
|
|
311
|
+
if state.control_plane_client is not None:
|
|
312
|
+
await state.control_plane_client.wait_until_connected(
|
|
313
|
+
timeout_s=_upgrade_ready_timeout()
|
|
314
|
+
)
|
|
315
|
+
except Exception as ready_exc: # noqa: BLE001
|
|
316
|
+
logger.debug("Upgrade UI-ready wait ended: %s", ready_exc)
|
|
317
|
+
finally:
|
|
318
|
+
_upgrade_ready.set()
|
|
319
|
+
|
|
320
|
+
asyncio.create_task(_signal_upgrade_ui_ready())
|
|
321
|
+
except Exception as e:
|
|
322
|
+
logger.warning("Upgrade runner at startup failed (non-fatal): %s", e)
|
|
323
|
+
|
|
294
324
|
if settings.enable_sync and settings.topos_user_id:
|
|
295
325
|
state.sync_client = SyncClient(
|
|
296
326
|
sync_url=settings.get_sync_url(),
|
{topos_node-1.2.7 → topos_node-1.3.1}/topos/canonicalization/mappers/browser_activity_mapper.py
RENAMED
|
@@ -24,6 +24,7 @@ from __future__ import annotations
|
|
|
24
24
|
import json
|
|
25
25
|
from dataclasses import dataclass
|
|
26
26
|
from typing import Any, Optional
|
|
27
|
+
from urllib.parse import urlparse
|
|
27
28
|
|
|
28
29
|
from ...ingestion.parsers.base import NormalizedRecord
|
|
29
30
|
from .base import CanonicalMapper, CanonicalRecord, MappingMetadata
|
|
@@ -77,6 +78,13 @@ class BrowserActivityCanonicalMapper(CanonicalMapper):
|
|
|
77
78
|
"schema": payload.get("schema") or payload.get("schema_id"),
|
|
78
79
|
}
|
|
79
80
|
hostname = payload.get("hostname")
|
|
81
|
+
if not hostname and payload.get("url"):
|
|
82
|
+
# BT6 (PLAN_ATTENTION_TRIAGE.md): some plugin batches send url
|
|
83
|
+
# without hostname; derive it so downstream vocab never goes empty.
|
|
84
|
+
try:
|
|
85
|
+
hostname = urlparse(str(payload.get("url"))).hostname
|
|
86
|
+
except ValueError:
|
|
87
|
+
hostname = None
|
|
80
88
|
if hostname:
|
|
81
89
|
metadata["hostname"] = hostname
|
|
82
90
|
|
|
@@ -230,6 +230,10 @@ def main(db_path, topos_key, set_topos_key, discover, port, host, skip_update_ch
|
|
|
230
230
|
os.environ["TOPOS_DATABASE_PATH"] = db_path
|
|
231
231
|
click.echo(f"Database path: {db_path}")
|
|
232
232
|
|
|
233
|
+
from topos.runtime_housekeeping import start_background_housekeeping
|
|
234
|
+
|
|
235
|
+
start_background_housekeeping()
|
|
236
|
+
|
|
233
237
|
_emit_startup_banner(host=host, port=port)
|
|
234
238
|
uvicorn.run(app, host=host, port=port, log_config=get_uvicorn_log_config())
|
|
235
239
|
|