topos-node 1.3.38__tar.gz → 1.3.40__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {topos_node-1.3.38/topos_node.egg-info → topos_node-1.3.40}/PKG-INFO +3 -3
- {topos_node-1.3.38 → topos_node-1.3.40}/README.md +2 -2
- {topos_node-1.3.38 → topos_node-1.3.40}/pyproject.toml +3 -3
- {topos_node-1.3.38 → topos_node-1.3.40}/tests/test_active_database_binding.py +2 -1
- {topos_node-1.3.38 → topos_node-1.3.40}/tests/test_profile_hygiene.py +2 -1
- {topos_node-1.3.38 → topos_node-1.3.40}/tests/test_profiles.py +4 -3
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/__version__.py +2 -2
- topos_node-1.3.40/topos/api/ingestion_api.py +155 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/cli/commands.py +3 -2
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/cli/profile_cmd.py +2 -1
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/__init__.py +1 -0
- topos_node-1.3.40/topos/core/handlers/graph_summary.py +72 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/ingest.py +75 -0
- topos_node-1.3.40/topos/defaults.py +9 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/disclosure/privacy_layer.py +52 -7
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/entities_job.py +17 -2
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/orchestrator.py +35 -5
- topos_node-1.3.40/topos/features/entities/chatgpt_declared.py +256 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/declared_mappings.py +48 -3
- topos_node-1.3.40/topos/features/signal/conversation_windows.py +263 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/canonical_pipeline.py +71 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/ingest_helpers.py +26 -3
- topos_node-1.3.40/topos/ingestion/local_exports.py +713 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/manager.py +188 -7
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/parser.py +43 -15
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/parsers/chatgpt_conversation_flattener.py +10 -2
- topos_node-1.3.40/topos/ingestion/parsers/chatgpt_export.py +697 -0
- topos_node-1.3.40/topos/ingestion/triggers/file_trigger.py +77 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/mcp_stdio_proxy.py +7 -5
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/pipeline/job_runner.py +48 -1
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/profiles.py +4 -3
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/protocol/handled_message_types.json +3 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/retrieval.py +16 -1
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/canonical/ai_chat/canonicalizer.py +20 -1
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/raw/file_store.py +21 -1
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/upgrades/manifests.json +31 -0
- {topos_node-1.3.38 → topos_node-1.3.40/topos_node.egg-info}/PKG-INFO +3 -3
- {topos_node-1.3.38 → topos_node-1.3.40}/topos_node.egg-info/SOURCES.txt +6 -0
- topos_node-1.3.38/topos/api/ingestion_api.py +0 -80
- topos_node-1.3.38/topos/ingestion/triggers/file_trigger.py +0 -36
- {topos_node-1.3.38 → topos_node-1.3.40}/LICENSE +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/MANIFEST.in +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/setup.cfg +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/shared/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/shared/filtering.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/shared/schema_registry.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/tests/test_active_ingestion_binding.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/tests/test_extensions.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/tests/test_gate_leg_hermeticity.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/tests/test_llm_integrations_storage.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/tests/test_local_gate_composition.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/tests/test_owner_database_hermeticity.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/tests/test_prewarm_first_run.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/tests/test_protocol_handled_types.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/tests/test_query_field_contract.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/tests/test_system_computer_name.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/analytics/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/analytics/dataset_resolution.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/analytics/duckdb_adapter.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/analytics/luck_surface.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/analytics/messenger_communities.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/analytics/messenger_directed.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/analytics/messenger_graph.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/analytics/messenger_labels.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/analytics/person_graph.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/analytics/person_overlay.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/analytics/profiles.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/analytics/query_engine.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/analytics/raw_queries.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/analytics/relationship_reads.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/analytics.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/app_registry.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/backup.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/community_naming_config.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/compute_remote.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/connected_apps.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/conversation_context.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/data_commit.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/data_explorer_table_prefs.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/database_explorer.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/db.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/device.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/disk_space_config.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/engine_run.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/enrichment.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/enrichment_lab.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/facts_llm_config.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/filter_lab.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/health.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/home_chat.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/ingestion_compat.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/ingestion_sources.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/intelligence_lifecycle.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/llm.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/local_mcp.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/messenger_analytics.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/privacy_disclose.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/query_api.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/runtime_bootstrap.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/sanitization_ollama_config.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/shell.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/signal.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/signal_extraction_config.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/source_install.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/source_scrub.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/sources.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/sources_overview.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/sync.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/tool_index.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/ui_config.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/uma_data.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/upgrades.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/usage.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/api/user_identity.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/app.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/auth.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/canonicalization/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/canonicalization/declared_field_map.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/canonicalization/mappers/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/canonicalization/mappers/base.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/canonicalization/mappers/browser_activity_mapper.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/canonicalization/mappers/chatgpt_mapper.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/canonicalization/mappers/demo_mappers.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/canonicalization/mappers/documents_mapper.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/canonicalization/mappers/github_activity_mapper.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/canonicalization/mappers/google_calendar_mapper.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/canonicalization/mappers/grok_mapper.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/canonicalization/mappers/messenger_mapper.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/canonicalization/models.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/canonicalization/resolver.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/cli/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/cli/__main__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/cli/assets/topos_blk_rounded.png +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/cli/assets/topos_white.png +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/cli/reprocess_cmd.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/cli/setup_models_cmd.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/cli/tray.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/config/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/config/conversation_context_llm.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/config/facts_llm.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/config/local_model_builds.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/config/model_packs.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/config/node_function_providers.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/config/sanitization_ollama.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/config/settings.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/config/signal_extraction.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/config/uvicorn_logging.json +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/contacts/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/contacts/identity.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/control_plane_client.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/api_models.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/connection_resilience.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/db_health.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/device_helpers.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/errors.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/events.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/common.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/complexity.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/config.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/contacts_import.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/database_explorer.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/derivation.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/device.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/enrichment.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/enrichment_lab.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/filter_lab.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/graph_query.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/home_chat.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/mcp_client_elevations.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/mcp_clients.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/messages.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/messenger_analytics.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/query.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/registry.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/routines.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/signal_features.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/sources.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/timeline_daily.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/tool_index.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/handlers/uma.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/logging.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/metrics.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/routine_access.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/startup_banner.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/state.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/table_layers.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/core/types.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/data_explorer_row_delete.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/data_explorer_table_prefs.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/data_explorer_tables.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/disclosure/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/disclosure/canonical_writer.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/disclosure/content_policy.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/disclosure/field_registry.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/disclosure/tier.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/backends/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/backends/base.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/backends/generative_prompts.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/backends/generative_response.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/backends/huggingface.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/backends/ollama.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/backends/openai.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/backends/openai_compatible.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/backends/redpill.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/backends/stub.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/client.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/disk_space.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/engine.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/hosted_llm_wallet.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/intake.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/memory_utils.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/model_cache.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/model_manager.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/ollama_install.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/ollama_pull.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/ollama_runtime.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/ollama_setup_guidance.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/pipeline_memory.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/queue_manager.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/registration.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/result_formatter.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/router.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/scoped_token.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/tasks.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/torch_runtime.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/transport.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/usage_guard.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/usage_observation.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/engine/validator.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/catalog.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/derivation_recovery.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/derived_tables.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/job_readiness.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/job_writer.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/base.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/_batch_limits.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/_engine_runner.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/attention_triage_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/availability_scores_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/brief_fallback.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/complexity_snapshot_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/derivation_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/derived_object_embeddings_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/dimension_summary_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/embeddings_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/emo_27_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/fact_extraction_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/goal_extraction_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/pii_redaction_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/relationship_edges_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/sentiment_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/statistics_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/timeline_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/topic_clusters_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/canonical/topics_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/raw/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/raw/attachments_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/raw/language_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/raw/time_normalization_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/jobs/raw/tool_calls_job.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/model_overrides.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/models/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/models/manager.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/models/mvp_defaults.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/models/registry.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/models/versioning.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/pipeline_activity.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/processor.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/progress_bar.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/record_progress.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/registry_contract.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/signal_derivation_config.json +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment/source_overrides.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment_lab/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment_lab/bundles.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment_lab/model_resolve.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment_lab/schema.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment_lab/service.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment_lab/store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/enrichment_lab/worker.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/evals/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/evals/enrichment_eval.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/extensions.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/complexity/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/complexity/canonical.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/complexity/engine.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/complexity/entropy.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/complexity/focus.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/complexity/graph_metrics.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/complexity/influence.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/complexity/projection.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/complexity/snapshots.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/complexity/store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/complexity/topic_merge.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/complexity/topics.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/complexity/topics_daily.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/complexity/volatility.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/_scales.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/admin.legal.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/aspirations.goals.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/behavior.habits.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/behavior.preferences.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/beliefs.civic.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/beliefs.spiritual.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/communication.style.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/community.membership.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/craft.tooling.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/expertise.knowledge.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/finances.economics.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/health.lifestyle.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/health.mental.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/health.physical.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/household.pets.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/identity.core.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/interests.taste.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/life.events.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/narrative.self.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/net.capability.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/obligations.commitments.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/personality.traits.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/places.mobility.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/possessions.assets.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/relationships.social.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/values.motivation.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/vocab/dispositions.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/vocab/expertise.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/vocab/habits.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/vocab/interests.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/vocab/preferences.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/vocab/stances.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/vocab/tools.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/vocab/values.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/bundled_packs/work.career.yaml +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/candidates.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/guard.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/kernels.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/net_subject_policy.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/packs.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/person_bridge.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/prefilter.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/registry.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/report_card.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/router.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/social_bench.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/social_kernels.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/surfaces.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/synthesize.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/template.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/verify.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/derivation/writer.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/affinity.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/affinity_owner.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/affinity_quality.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/community_names.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/community_naming.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/consolidation.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/context_vectors.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/cypher.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/dossier.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/edges.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/fact_materializer.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/graph_enrichers.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/graph_refresh.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/graph_search.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/linking.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/maintenance.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/owner.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/reads.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/rebuild_subprocess.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/resolver.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/entities/structured_fields.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/facts/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/facts/extract.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/facts/llm_extract.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/facts/reads.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/facts/store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/facts/verdicts.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/fit/evaluator.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/fit/opportunity_types.json +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/lifecycle/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/lifecycle/blackhole.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/lifecycle/blackhole_guard.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/lifecycle/blackhole_llm.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/lifecycle/blackhole_rebuild.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/lifecycle/derived_scrub.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/lifecycle/exclusions.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/lifecycle/gc.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/provenance/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/provenance/posture.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/provenance/roles.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/brief_canonical_loader.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/brief_ontology.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/brief_renderer.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/brief_schemas.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/chunking.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/cluster_labels.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/conversation_context.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/data_health.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/definitions/brief_ontologies.json +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/definitions/intentions.json +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/definitions/interests.json +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/definitions/memory.json +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/definitions/places.json +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/definitions/profile.json +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/definitions/relationships.json +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/definitions/resources.json +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/definitions/schema/dimension_definition.schema.json +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/definitions/time.json +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/definitions/wellbeing.json +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/definitions/work.json +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/derived_index.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/derived_spec.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/dimension_briefs.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/dimension_definition_loader.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/dimension_profiles.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/dimension_registry.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/embed_context.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/extraction/artifact_router.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/extraction/artifact_store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/extraction/rule_extractors.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/graph_sanitize.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/hybrid_search.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/incremental_clustering.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/model_recommendations.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/query_embed_cache.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/schemas.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/service.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/signal_object_store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/source_hydration.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/structured_signal.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/tool_index.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/topic_clustering.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/typed_stores/aggregates.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/typed_stores/commitments.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/typed_stores/rhythm.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/typed_stores/scope_materializer.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/vector_codec.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/vector_math.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/signal/vector_settings.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/stats/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/stats/definitions.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/stats/engine.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/stats/fold.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/stats/insights.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/timeline_projection.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/timeline_rollup.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/triage/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/triage/badges.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/triage/daily.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/triage/dashboard.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/triage/instruments.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/triage/intents.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/features/triage/readiness.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/filter_lab/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/filter_lab/bundles.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/filter_lab/schema.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/filter_lab/service.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/filter_lab/store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/filter_lab/worker.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/home_chat/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/home_chat/schema.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/home_chat/store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/hosted_pool_lease.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/checkpoints/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/checkpoints/checkpoint_store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/checkpoints/sqlite_checkpoint_store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/inbox_crypto.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/inbox_drain.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/jobs.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/journal_location_fanout.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/journal_time_log_normalize.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/local_sync.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/log_preview.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/parsers/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/parsers/base.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/parsers/browser_parser.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/parsers/calendar_parser.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/parsers/chatgpt_parser.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/parsers/demo_file_parsers.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/parsers/documents_parser.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/parsers/github_activity_parser.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/parsers/google_calendar_parser.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/parsers/grok_parser.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/parsers/messenger_parser.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/parsers/voxterm_parser.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/progress.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/reprocess.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/sources/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/sources/base.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/sources/calendar.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/sources/chatgpt.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/sources/contact_importers.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/sources/grok.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/sources/imessage_reader.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/sources/signal_export_parser.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/sources/signal_reader.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/state_machine.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/triggers/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/triggers/sqlite_trigger.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/usage_inbox_dedupe.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/validation/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/validation/base.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/validation/schema_registry.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/ingestion/validation/schema_validator.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/lineage/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/lineage/provenance.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/lineage/tracker.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/llm_integrations_storage.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/mcp_clients.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/observability/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/observability/alerts.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/observability/metrics.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/observability/tracing.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/openai_client.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/owner_key.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/pipeline/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/pipeline/audit.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/pipeline/envelope.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/pipeline/job_store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/pipeline/stages.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/pipeline/stub_enqueue.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/principal.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/projections/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/projections/vector_index/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/projections/vector_index/base.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/projections/vector_index/builders.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/projections/vector_index/health_checks.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/protocol/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/protocol/narrowing_vocabulary.json +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/protocol/query_field_contract.json +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/audit.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/closeness.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/cohort_resolvers.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/collaborators.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/ddr.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/disclosure.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/entity_window.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/exclusion.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/facts_direct.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/fingerprint.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/game_layer.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/grant_cache.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/inference.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/intent.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/manifest.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/manifest_validation.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/minimizer.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/narrowing.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/negotiation.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/packet_resolution.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/pipeline.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/planner.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/runtime.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/scope_arbiter.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/scope_classifier.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/scope_head.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/scope_registry.json +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/scope_registry_loader.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/scope_shadow.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/session.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/session_utils.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/source_generation.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/truth_facts.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/truth_prompts.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/turn_classifier.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/types.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/verify.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/query/verify_modes.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/rate_limit.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/relay_stamp.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/routines/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/routines/schema.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/routines/store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/runtime_housekeeping.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/runtime_shutdown.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/runtime_update.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/sanitization/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/sanitization/nsfw_classifier.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/sanitization/ollama_transforms.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/sanitization/prewarm.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/sanitization/privacy_filter.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/scope_resolution.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/services/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/services/container.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/services/embeddings/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/services/embeddings/base.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/services/embeddings/local.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/services/embeddings/remote.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/services/interfaces.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/services/llm/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/services/llm/base.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/services/llm/openai.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/services/local.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/services/postgres.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/sources/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/sources/bundled_canonical_triples.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/sources/canonical_signal_defaults.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/sources/declared_field_map_spec.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/sources/definitions.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/sources/install_service.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/sources/registry.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/sources/runtime_install.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/sources/scrub_attribution.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/sources/scrub_service.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/startup_banner.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/adapters/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/adapters/factory.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/adapters/fakes.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/adapters/postgres/stores.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/adapters/protocols.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/adapters/sqlite/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/adapters/sqlite/stores.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/adapters/sqlite/vector_search.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/canonical/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/canonical/activity_tables.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/canonical/ai_chat/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/canonical/ai_chat/mapper.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/canonical/ai_chat/model.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/canonical/ai_chat/tables.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/canonical/calendar_contacts_tables.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/canonical/canonical_store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/canonical/conversations_tables.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/canonical/journal_repair.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/canonical/mapping_store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/canonical/postgres.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/client.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/connection_tuning.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/activity_events_content_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/actor_role_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/affinity_pair_labels_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/attention_triage_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/attention_triage_v2.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/backup.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/backup_custody.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/calendar_events_scheduling_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/canonical_address_book_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/canonical_disclosure_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/canonical_nsfw_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/community_names_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/complexity_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/conflict_provenance_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/conversation_context_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/derivation_factory_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/derivation_ledger_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/derivation_provenance_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/derived_row_identity_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/documents_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/enrichment_record_progress_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/enrichment_spec_version_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/entity_affinity_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/entity_blackhole_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/entity_context_vectors_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/entity_context_vectors_v2.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/entity_edges_validity_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/entity_mentions_authored_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/entity_review_candidate_bar_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/entity_review_dedup_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/entity_review_provenance_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/episodes_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/extraction_artifacts.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/fact_dimension_by_entity_type_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/journal_entries_duration_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/journal_entries_ends_at_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/journal_entries_people_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/journal_entries_place_name_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/journal_entries_starts_at_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/journal_origin_dimension_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/mention_table_stamp_backfill_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/message_emotions_role_backfill_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/message_emotions_role_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/net_subject_policy_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/pack_registry_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/pipeline_jobs_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/query_artifacts_duration_ms_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/registry.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/registry_checksums.json +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/remediation_person_model.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/retire_url_classification_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/scope_source_generation.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/signal_dimension_backfill_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/signal_dimension_harness.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/signal_objects.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/signal_objects_period_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/signal_objects_updated_by_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/signal_summaries_drop_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/stage9_column_renames.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/vector_storage_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/vector_storage_v2.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/vector_storage_v3.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/vector_storage_v4.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/wiki_clusters_v2.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/wiki_entities_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/wiki_entity_review_v2.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/wiki_facts_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/wiki_lifecycle_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/wiki_mvp_phase0.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/wiki_mvp_phase1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/wiki_mvp_phase4_messages_cutover.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/wiki_mvp_phase5_topic_clusters.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/wiki_mvp_phase6_dimension_briefs.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/wiki_mvp_query_quality.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/wiki_mvp_topic_clusters_coordination.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/wiki_stats_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/migrations/wiki_timeline_v1.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/paths.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/postgres.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/schema.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/schema_probe.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/storage_breakdown.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/db/write_gate.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/derived_row_identity.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/enrichment/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/enrichment/canonical_enrichment_store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/enrichment/raw_enrichment_store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/normalized/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/normalized/normalized_store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/oplog/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/oplog/decision.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/oplog/oplog_store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/oplog/postgres.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/person/identity_resolver.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/projections/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/projections/index_ops_store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/projections/vector_index_store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/raw/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/raw/browser_flat_tables.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/raw/raw_store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/raw/raw_tables_manager.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/raw/sqlite_raw_store.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/security/encryption.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/signal_identity.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/source_settings.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/storage/user_identity.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/sync/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/sync/client.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/sync_handlers.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/testing/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/testing/lifespan.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/uds.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/uma_contact_enrichment.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/uma_filters.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/uma_resource_id.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/uma_rpt.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/upgrades/__init__.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/upgrades/runner.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/utils/base_object.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos/websocket_client.py +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos_node.egg-info/dependency_links.txt +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos_node.egg-info/entry_points.txt +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos_node.egg-info/requires.txt +0 -0
- {topos_node-1.3.38 → topos_node-1.3.40}/topos_node.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: topos-node
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.40
|
|
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
|
|
@@ -163,13 +163,13 @@ Optional:
|
|
|
163
163
|
### 3) Run
|
|
164
164
|
|
|
165
165
|
```bash
|
|
166
|
-
topos-node --host 0.0.0.0 --port
|
|
166
|
+
topos-node --host 0.0.0.0 --port 8676
|
|
167
167
|
```
|
|
168
168
|
|
|
169
169
|
### 4) Verify
|
|
170
170
|
|
|
171
171
|
```bash
|
|
172
|
-
curl http://localhost:
|
|
172
|
+
curl http://localhost:8676/health
|
|
173
173
|
```
|
|
174
174
|
|
|
175
175
|
## Common Commands
|
|
@@ -96,13 +96,13 @@ Optional:
|
|
|
96
96
|
### 3) Run
|
|
97
97
|
|
|
98
98
|
```bash
|
|
99
|
-
topos-node --host 0.0.0.0 --port
|
|
99
|
+
topos-node --host 0.0.0.0 --port 8676
|
|
100
100
|
```
|
|
101
101
|
|
|
102
102
|
### 4) Verify
|
|
103
103
|
|
|
104
104
|
```bash
|
|
105
|
-
curl http://localhost:
|
|
105
|
+
curl http://localhost:8676/health
|
|
106
106
|
```
|
|
107
107
|
|
|
108
108
|
## Common Commands
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "topos-node"
|
|
7
|
-
version = "1.3.
|
|
7
|
+
version = "1.3.40"
|
|
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"
|
|
@@ -112,7 +112,7 @@ tmp_path_retention_count = 1
|
|
|
112
112
|
tmp_path_retention_policy = "failed"
|
|
113
113
|
# The DEFAULT lane is hermetic. Without this, a plain `pytest tests/` selects
|
|
114
114
|
# every marker, and the three lanes below are the ones that read and WRITE the
|
|
115
|
-
# developer's own ~/.topos/database.db or drive the node running on :
|
|
115
|
+
# developer's own ~/.topos/database.db or drive the node running on :8676 —
|
|
116
116
|
# `tests/conftest.py::_no_live_db_guard` waives its protection for exactly these
|
|
117
117
|
# markers, which only makes sense if the ordinary gate never selects them.
|
|
118
118
|
# On 2026-08-19 it did: one `pytest tests/ -q` run inserted 71 rows into the
|
|
@@ -137,7 +137,7 @@ markers = [
|
|
|
137
137
|
"public: public-safe test lane for OSS CI",
|
|
138
138
|
"private: internal architecture or fixtures; excluded from public CI",
|
|
139
139
|
"e2e: end-to-end tests (live Keycloak + Control Plane; require config and running CP)",
|
|
140
|
-
"live: requires a running local engine (localhost:
|
|
140
|
+
"live: requires a running local engine (localhost:8676) and a real TOPOS_KEY; excluded from deterministic lanes",
|
|
141
141
|
"release_pressure: iteration-4 live pressure smoke; run explicitly before releases",
|
|
142
142
|
"p0: priority marker on release pressure tests",
|
|
143
143
|
"retrieval_eval: dense-intelligence retrieval eval (loads local embedding model; run explicitly)",
|
|
@@ -20,6 +20,7 @@ from pathlib import Path
|
|
|
20
20
|
|
|
21
21
|
import pytest
|
|
22
22
|
|
|
23
|
+
from topos.defaults import DEFAULT_NODE_PORT
|
|
23
24
|
from topos.storage.db import paths
|
|
24
25
|
|
|
25
26
|
pytestmark = [pytest.mark.public]
|
|
@@ -381,7 +382,7 @@ class TestSwitchPreflight:
|
|
|
381
382
|
def _no_running_node(self, monkeypatch):
|
|
382
383
|
from topos import profiles
|
|
383
384
|
|
|
384
|
-
monkeypatch.setattr(profiles, "node_is_running", lambda port=
|
|
385
|
+
monkeypatch.setattr(profiles, "node_is_running", lambda port=DEFAULT_NODE_PORT: False)
|
|
385
386
|
|
|
386
387
|
def test_refuses_a_topos_from_a_newer_engine(self, tmp_path):
|
|
387
388
|
from topos import profiles
|
|
@@ -22,6 +22,7 @@ from pathlib import Path
|
|
|
22
22
|
import pytest
|
|
23
23
|
|
|
24
24
|
from topos import profiles
|
|
25
|
+
from topos.defaults import DEFAULT_NODE_PORT
|
|
25
26
|
from topos.storage.db.migrations import backup as backup_mod
|
|
26
27
|
|
|
27
28
|
pytestmark = [pytest.mark.public]
|
|
@@ -70,7 +71,7 @@ def _seed_active(base: Path, *, key: str = "KEYAAA", real_db: bool = True) -> No
|
|
|
70
71
|
|
|
71
72
|
@pytest.fixture(autouse=True)
|
|
72
73
|
def _no_running_node(monkeypatch):
|
|
73
|
-
monkeypatch.setattr(profiles, "node_is_running", lambda port=
|
|
74
|
+
monkeypatch.setattr(profiles, "node_is_running", lambda port=DEFAULT_NODE_PORT: False)
|
|
74
75
|
|
|
75
76
|
|
|
76
77
|
class TestArchiveIsSelfContained:
|
|
@@ -17,6 +17,7 @@ from click.testing import CliRunner
|
|
|
17
17
|
|
|
18
18
|
from topos import profiles
|
|
19
19
|
from topos.cli.profile_cmd import profile_group
|
|
20
|
+
from topos.defaults import DEFAULT_NODE_PORT
|
|
20
21
|
|
|
21
22
|
pytestmark = [pytest.mark.public]
|
|
22
23
|
|
|
@@ -45,7 +46,7 @@ def _seed_profile(base: Path, slug: str, *, name: str | None = None, key: str =
|
|
|
45
46
|
|
|
46
47
|
@pytest.fixture(autouse=True)
|
|
47
48
|
def _no_running_node(monkeypatch):
|
|
48
|
-
monkeypatch.setattr(profiles, "node_is_running", lambda port=
|
|
49
|
+
monkeypatch.setattr(profiles, "node_is_running", lambda port=DEFAULT_NODE_PORT: False)
|
|
49
50
|
|
|
50
51
|
|
|
51
52
|
class TestNewProfile:
|
|
@@ -128,7 +129,7 @@ class TestSwitchProfile:
|
|
|
128
129
|
def test_refuses_while_node_running(self, tmp_path, monkeypatch):
|
|
129
130
|
_seed_active(tmp_path)
|
|
130
131
|
_seed_profile(tmp_path, "work")
|
|
131
|
-
monkeypatch.setattr(profiles, "node_is_running", lambda port=
|
|
132
|
+
monkeypatch.setattr(profiles, "node_is_running", lambda port=DEFAULT_NODE_PORT: True)
|
|
132
133
|
with pytest.raises(profiles.ProfileError, match="running"):
|
|
133
134
|
profiles.switch_profile("work", tmp_path)
|
|
134
135
|
# Nothing moved.
|
|
@@ -328,7 +329,7 @@ class TestRemoveProfile:
|
|
|
328
329
|
def test_does_not_require_the_node_to_be_stopped(self, tmp_path, monkeypatch):
|
|
329
330
|
# An archived Topos is not the one a running engine has open, so unlike
|
|
330
331
|
# new/switch this must work without asking anyone to quit Topos.
|
|
331
|
-
monkeypatch.setattr(profiles, "node_is_running", lambda port=
|
|
332
|
+
monkeypatch.setattr(profiles, "node_is_running", lambda port=DEFAULT_NODE_PORT: True)
|
|
332
333
|
_seed_profile(tmp_path, "work")
|
|
333
334
|
|
|
334
335
|
profiles.remove_profile("work", tmp_path)
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from fastapi import APIRouter, Body, Depends, HTTPException, Request
|
|
4
|
+
|
|
5
|
+
from ..auth import require_api_key
|
|
6
|
+
from ..ingestion.reprocess import reprocess_source
|
|
7
|
+
from .ingestion_sources import ingest_source
|
|
8
|
+
|
|
9
|
+
router = APIRouter()
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@router.post("/ingestion/start")
|
|
13
|
+
async def start_ingestion() -> dict:
|
|
14
|
+
return {"status": "stub"}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@router.post("/ingestion/progress")
|
|
18
|
+
async def report_progress() -> dict:
|
|
19
|
+
return {"status": "stub"}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@router.post("/ingestion/reprocess", dependencies=[Depends(require_api_key)])
|
|
23
|
+
async def ingestion_reprocess(payload: dict = Body(default_factory=dict)) -> dict:
|
|
24
|
+
"""Re-run raw→canonical for a source (optional newest-N via ``limit``).
|
|
25
|
+
|
|
26
|
+
Body:
|
|
27
|
+
- source_id (required)
|
|
28
|
+
- dataset_id (required)
|
|
29
|
+
- from_stage: ``raw`` (default) | ``canonical``
|
|
30
|
+
- limit: optional int — newest N raw rows only
|
|
31
|
+
- run_enrichment: optional bool (default true)
|
|
32
|
+
- force / sync_batch_id: optional
|
|
33
|
+
"""
|
|
34
|
+
try:
|
|
35
|
+
limit_raw = payload.get("limit")
|
|
36
|
+
limit = int(limit_raw) if limit_raw is not None and str(limit_raw).strip() != "" else None
|
|
37
|
+
return await reprocess_source(
|
|
38
|
+
source_id=str(payload["source_id"]),
|
|
39
|
+
dataset_id=str(payload["dataset_id"]),
|
|
40
|
+
from_stage=payload.get("from_stage") or "raw",
|
|
41
|
+
sync_batch_id=payload.get("sync_batch_id"),
|
|
42
|
+
force=bool(payload.get("force", False)),
|
|
43
|
+
limit=limit,
|
|
44
|
+
run_enrichment=bool(payload.get("run_enrichment", True)),
|
|
45
|
+
)
|
|
46
|
+
except KeyError as exc:
|
|
47
|
+
raise HTTPException(status_code=400, detail=f"Missing field: {exc}") from exc
|
|
48
|
+
except ValueError as exc:
|
|
49
|
+
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@router.get("/ingestion/audit", dependencies=[Depends(require_api_key)])
|
|
53
|
+
async def get_ingestion_audit(sync_batch_id: str) -> dict:
|
|
54
|
+
from ..core.state import get_db_connection
|
|
55
|
+
from ..pipeline.audit import SQLiteIngestAuditStore
|
|
56
|
+
|
|
57
|
+
conn = get_db_connection()
|
|
58
|
+
if not conn:
|
|
59
|
+
raise HTTPException(status_code=503, detail="Database unavailable")
|
|
60
|
+
store = SQLiteIngestAuditStore(conn)
|
|
61
|
+
return {"sync_batch_id": sync_batch_id, "stages": store.query_by_batch(sync_batch_id)}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@router.post("/ingestion/upload", dependencies=[Depends(require_api_key)])
|
|
65
|
+
async def upload_ingestion_file(request: Request) -> dict:
|
|
66
|
+
return await ingest_source("chatgpt_file_ingestion", request)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@router.get("/ingestion/local-exports", dependencies=[Depends(require_api_key)])
|
|
70
|
+
async def list_local_exports() -> dict:
|
|
71
|
+
"""Exports sitting on this machine, for the import screen to offer.
|
|
72
|
+
|
|
73
|
+
The node is the only party that can answer this: a browser cannot read a
|
|
74
|
+
filesystem, and cannot produce an absolute path even for a file the user
|
|
75
|
+
picks. So the node looks, and hands back opaque handles plus labels a person
|
|
76
|
+
can recognise -- never the paths themselves.
|
|
77
|
+
|
|
78
|
+
Bounded and stateless by construction (see ``local_exports``): a few known
|
|
79
|
+
folders, shallow, symlinks skipped, time-boxed, nothing written down.
|
|
80
|
+
"""
|
|
81
|
+
import asyncio
|
|
82
|
+
|
|
83
|
+
from ..ingestion.local_exports import find_exports
|
|
84
|
+
|
|
85
|
+
result = await asyncio.to_thread(find_exports)
|
|
86
|
+
return result.as_payload()
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@router.get("/ingestion/local-exports/{handle}/describe", dependencies=[Depends(require_api_key)])
|
|
90
|
+
async def describe_local_export(handle: str) -> dict:
|
|
91
|
+
"""What is inside one discovered export: conversation count and date range.
|
|
92
|
+
|
|
93
|
+
Separate from discovery on purpose. Listing candidates reads only an
|
|
94
|
+
archive's central directory and stays in the low hundreds of milliseconds;
|
|
95
|
+
this opens the conversations file and parses it, which is about a second on
|
|
96
|
+
a 52 MB export. Paying that for every row of a scan to inform a choice about
|
|
97
|
+
one of them would be the wrong trade.
|
|
98
|
+
|
|
99
|
+
It exists because a window is measured against today while an export is
|
|
100
|
+
fixed in the past, and nothing in the UI could see the gap: a six-month
|
|
101
|
+
window against a fourteen-month-old export drops every conversation and
|
|
102
|
+
completes successfully with nothing imported.
|
|
103
|
+
"""
|
|
104
|
+
import asyncio
|
|
105
|
+
|
|
106
|
+
from ..ingestion.local_exports import describe_export, resolve
|
|
107
|
+
|
|
108
|
+
path = await asyncio.to_thread(resolve, handle)
|
|
109
|
+
if path is None:
|
|
110
|
+
raise HTTPException(
|
|
111
|
+
status_code=404,
|
|
112
|
+
detail="That export is no longer where we found it. Scan again and pick it.",
|
|
113
|
+
)
|
|
114
|
+
try:
|
|
115
|
+
return await asyncio.to_thread(describe_export, path)
|
|
116
|
+
except Exception as exc: # noqa: BLE001 — a describe failure must not block the import
|
|
117
|
+
raise HTTPException(status_code=422, detail=f"Could not read that export: {exc}") from exc
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@router.post("/ingestion/upload-local-path", dependencies=[Depends(require_api_key)])
|
|
121
|
+
async def upload_ingestion_local_path(
|
|
122
|
+
request: Request, payload: dict = Body(default_factory=dict)
|
|
123
|
+
) -> dict:
|
|
124
|
+
"""Ingest a file that is already on this machine. No bytes cross a network.
|
|
125
|
+
|
|
126
|
+
Accepts either a ``handle`` from ``/ingestion/local-exports`` -- the path
|
|
127
|
+
never leaves the node -- or an explicit ``file_path``, which is still how
|
|
128
|
+
someone points at an export outside the searched folders.
|
|
129
|
+
"""
|
|
130
|
+
from ..ingestion.local_exports import resolve
|
|
131
|
+
|
|
132
|
+
dataset_id = payload.get("dataset_id")
|
|
133
|
+
file_path = payload.get("file_path")
|
|
134
|
+
handle = str(payload.get("handle") or "").strip()
|
|
135
|
+
|
|
136
|
+
if handle and not file_path:
|
|
137
|
+
resolved = resolve(handle)
|
|
138
|
+
if resolved is None:
|
|
139
|
+
# Handles are re-found rather than remembered, so a stale one means
|
|
140
|
+
# the file moved or went away -- not that the user did anything odd.
|
|
141
|
+
raise HTTPException(
|
|
142
|
+
status_code=404,
|
|
143
|
+
detail="That export is no longer where we found it. Scan again and pick it.",
|
|
144
|
+
)
|
|
145
|
+
file_path = str(resolved)
|
|
146
|
+
|
|
147
|
+
if not file_path:
|
|
148
|
+
raise HTTPException(status_code=400, detail="Provide a handle or a file_path.")
|
|
149
|
+
|
|
150
|
+
return await ingest_source(
|
|
151
|
+
"chatgpt_file_ingestion",
|
|
152
|
+
request,
|
|
153
|
+
dataset_id=dataset_id,
|
|
154
|
+
file_path=file_path,
|
|
155
|
+
)
|
|
@@ -12,6 +12,7 @@ import uvicorn
|
|
|
12
12
|
# Add parent directory to path for imports
|
|
13
13
|
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
|
|
14
14
|
|
|
15
|
+
from topos.defaults import DEFAULT_NODE_PORT
|
|
15
16
|
from topos.runtime_update import (
|
|
16
17
|
DEFAULT_PACKAGE_NAME,
|
|
17
18
|
apply_package_update,
|
|
@@ -232,8 +233,8 @@ def _maybe_offer_self_update(
|
|
|
232
233
|
)
|
|
233
234
|
@click.option(
|
|
234
235
|
"--port",
|
|
235
|
-
default=
|
|
236
|
-
help="Server port (default:
|
|
236
|
+
default=DEFAULT_NODE_PORT,
|
|
237
|
+
help=f"Server port (default: {DEFAULT_NODE_PORT})",
|
|
237
238
|
)
|
|
238
239
|
@click.option(
|
|
239
240
|
"--host",
|
|
@@ -17,6 +17,7 @@ from typing import Optional
|
|
|
17
17
|
import click
|
|
18
18
|
|
|
19
19
|
from topos import profiles
|
|
20
|
+
from topos.defaults import DEFAULT_NODE_PORT
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
def _echo(payload: dict, as_json: bool, human: str) -> None:
|
|
@@ -41,7 +42,7 @@ _BASE_OPTION = click.option(
|
|
|
41
42
|
)
|
|
42
43
|
_JSON_OPTION = click.option("--json", "as_json", is_flag=True, help="Machine-readable output.")
|
|
43
44
|
_PORT_OPTION = click.option(
|
|
44
|
-
"--port", default=
|
|
45
|
+
"--port", default=DEFAULT_NODE_PORT, show_default=True, help="Port probed for a running node."
|
|
45
46
|
)
|
|
46
47
|
|
|
47
48
|
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""How much is in the graph — the smallest possible answer.
|
|
2
|
+
|
|
3
|
+
Why this exists rather than a count taken from ``/v1/signal/graph``: that
|
|
4
|
+
endpoint returns node and edge LISTS, capped at 200 and 500, and no totals. To
|
|
5
|
+
learn "how many" from it you would fetch rows you throw away, and still not
|
|
6
|
+
know the answer once the graph passed the cap.
|
|
7
|
+
|
|
8
|
+
Why not carry the number on the ingestion job instead: the progress channel is
|
|
9
|
+
a fixed set of columns on the control plane's ``ingestion_jobs`` table, with no
|
|
10
|
+
JSON field, and ``stage_event`` is filtered down to four keys. Adding it there
|
|
11
|
+
means a schema migration on the production database — a real cost to pay for a
|
|
12
|
+
reassurance line, and a change that is hard to take back.
|
|
13
|
+
|
|
14
|
+
So: three COUNT(*) queries, read on demand, owned by nothing.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import asyncio
|
|
20
|
+
from typing import Any, Dict, Optional
|
|
21
|
+
|
|
22
|
+
from .registry import handles
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _counts() -> Dict[str, Any]:
|
|
26
|
+
from ...core.state import get_db_connection
|
|
27
|
+
|
|
28
|
+
conn = get_db_connection()
|
|
29
|
+
if conn is None:
|
|
30
|
+
return {"available": False}
|
|
31
|
+
|
|
32
|
+
out: Dict[str, Any] = {"available": True}
|
|
33
|
+
# Each table is counted independently and a failure on one is not a failure
|
|
34
|
+
# of the reply: a missing table on an older node should cost that number,
|
|
35
|
+
# not the whole answer.
|
|
36
|
+
for key, table in (
|
|
37
|
+
("nodes", "graph_nodes"),
|
|
38
|
+
("edges", "graph_edges"),
|
|
39
|
+
("entities", "entities"),
|
|
40
|
+
):
|
|
41
|
+
try:
|
|
42
|
+
row = conn.execute(f"SELECT COUNT(*) FROM {table}").fetchone() # noqa: S608 — fixed names
|
|
43
|
+
out[key] = int(row[0]) if row else 0
|
|
44
|
+
except Exception: # noqa: BLE001
|
|
45
|
+
out[key] = None
|
|
46
|
+
try:
|
|
47
|
+
row = conn.execute(
|
|
48
|
+
"SELECT MAX(materialized_at) FROM graph_materialization_state"
|
|
49
|
+
).fetchone()
|
|
50
|
+
out["materialized_at"] = row[0] if row else None
|
|
51
|
+
except Exception: # noqa: BLE001
|
|
52
|
+
out["materialized_at"] = None
|
|
53
|
+
return out
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@handles("graph_summary")
|
|
57
|
+
async def handle_graph_summary(message: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
58
|
+
"""Node, edge and entity counts, for a screen that wants to show growth.
|
|
59
|
+
|
|
60
|
+
The reason it is worth showing during an import: entity data lands at the
|
|
61
|
+
third of twenty stages and the graph is materialised twice, so these numbers
|
|
62
|
+
move long before the import finishes. Watching them move is the difference
|
|
63
|
+
between a long wait and a long wait you can see the point of.
|
|
64
|
+
"""
|
|
65
|
+
req_id = message.get("id")
|
|
66
|
+
if not req_id:
|
|
67
|
+
return None
|
|
68
|
+
try:
|
|
69
|
+
payload = await asyncio.to_thread(_counts)
|
|
70
|
+
return {"id": req_id, "status": "ok", "payload": payload}
|
|
71
|
+
except Exception as exc: # noqa: BLE001
|
|
72
|
+
return {"id": req_id, "status": "error", "error": str(exc)}
|
|
@@ -365,6 +365,22 @@ async def handle_start_ingestion(message: Dict[str, Any]) -> Optional[Dict[str,
|
|
|
365
365
|
file_url = payload.get("file_url")
|
|
366
366
|
file_base64 = payload.get("file_base64")
|
|
367
367
|
file_path = payload.get("file_path")
|
|
368
|
+
local_handle = str(payload.get("local_export_handle") or "").strip()
|
|
369
|
+
if local_handle and not file_path:
|
|
370
|
+
# A handle from `list_local_exports`. The path was never sent to the
|
|
371
|
+
# browser, so it is resolved here — and only ever to something still
|
|
372
|
+
# inside a searched folder, which is what makes a handle safe to accept
|
|
373
|
+
# back over the relay.
|
|
374
|
+
from ...ingestion.local_exports import resolve as _resolve_local_export
|
|
375
|
+
|
|
376
|
+
resolved = _resolve_local_export(local_handle)
|
|
377
|
+
if resolved is None:
|
|
378
|
+
return {
|
|
379
|
+
"id": req_id,
|
|
380
|
+
"status": "error",
|
|
381
|
+
"error": "That export is no longer where we found it. Scan again and pick it.",
|
|
382
|
+
}
|
|
383
|
+
file_path = str(resolved)
|
|
368
384
|
job_id = payload.get("job_id")
|
|
369
385
|
source_id = payload.get("source_id") # Optional source_id from control plane
|
|
370
386
|
source_definition = payload.get("source_definition")
|
|
@@ -408,10 +424,13 @@ async def handle_start_ingestion(message: Dict[str, Any]) -> Optional[Dict[str,
|
|
|
408
424
|
"payload": {"job_id": job_id, "status": "completed", "deduplicated": True},
|
|
409
425
|
}
|
|
410
426
|
|
|
427
|
+
# Import-time policy chosen in the UI (date window, inclusion flags).
|
|
428
|
+
ingest_options = payload.get("ingest_options")
|
|
411
429
|
job_payload: Dict[str, Any] = {
|
|
412
430
|
"dataset_id": dataset_id or "",
|
|
413
431
|
"schema_id": schema_id,
|
|
414
432
|
"file_format": file_format,
|
|
433
|
+
"ingest_options": ingest_options if isinstance(ingest_options, dict) else None,
|
|
415
434
|
"job_id": job_id,
|
|
416
435
|
"source_id": source_id,
|
|
417
436
|
"source_definition": source_definition,
|
|
@@ -478,6 +497,62 @@ async def handle_ingestion_reprocess(message: Dict[str, Any]) -> Optional[Dict[s
|
|
|
478
497
|
except Exception as exc: # noqa: BLE001
|
|
479
498
|
return {"id": req_id, "status": "error", "error": str(exc)}
|
|
480
499
|
|
|
500
|
+
@handles("list_local_exports")
|
|
501
|
+
async def handle_list_local_exports(message: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
502
|
+
"""Exports sitting on this machine, for the import screen to offer.
|
|
503
|
+
|
|
504
|
+
Only the node can answer this. A browser cannot read a filesystem, and
|
|
505
|
+
cannot produce an absolute path even for a file the user picks — so without
|
|
506
|
+
this the only way to reach the free import path was to type one out by hand.
|
|
507
|
+
|
|
508
|
+
What comes back is opaque handles and labels a person can recognise, never
|
|
509
|
+
paths: the reply travels to the browser over the relay, and a home-directory
|
|
510
|
+
path carries the account name and whatever else lives beside it.
|
|
511
|
+
"""
|
|
512
|
+
req_id = message.get("id")
|
|
513
|
+
if not req_id:
|
|
514
|
+
return None
|
|
515
|
+
try:
|
|
516
|
+
import asyncio
|
|
517
|
+
|
|
518
|
+
from ...ingestion.local_exports import find_exports
|
|
519
|
+
|
|
520
|
+
result = await asyncio.to_thread(find_exports)
|
|
521
|
+
return {"id": req_id, "status": "ok", "payload": result.as_payload()}
|
|
522
|
+
except Exception as exc: # noqa: BLE001
|
|
523
|
+
return {"id": req_id, "status": "error", "error": str(exc)}
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
@handles("describe_local_export")
|
|
527
|
+
async def handle_describe_local_export(message: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
528
|
+
"""Conversation count and date range for one discovered export.
|
|
529
|
+
|
|
530
|
+
The window a person picks is measured from today; the export is fixed in
|
|
531
|
+
the past. Nothing in the UI could see that gap, so a six-month window
|
|
532
|
+
against a fourteen-month-old file imported nothing and said it succeeded.
|
|
533
|
+
This is the number that closes it, read where the dates are.
|
|
534
|
+
"""
|
|
535
|
+
req_id = message.get("id")
|
|
536
|
+
if not req_id:
|
|
537
|
+
return None
|
|
538
|
+
payload = message.get("payload") or {}
|
|
539
|
+
handle = str(payload.get("handle") or "").strip()
|
|
540
|
+
if not handle:
|
|
541
|
+
return {"id": req_id, "status": "error", "error": "handle required"}
|
|
542
|
+
try:
|
|
543
|
+
import asyncio
|
|
544
|
+
|
|
545
|
+
from ...ingestion.local_exports import describe_export, resolve
|
|
546
|
+
|
|
547
|
+
path = await asyncio.to_thread(resolve, handle)
|
|
548
|
+
if path is None:
|
|
549
|
+
return {"id": req_id, "status": "error", "error": "export no longer found"}
|
|
550
|
+
described = await asyncio.to_thread(describe_export, path)
|
|
551
|
+
return {"id": req_id, "status": "ok", "payload": described}
|
|
552
|
+
except Exception as exc: # noqa: BLE001
|
|
553
|
+
return {"id": req_id, "status": "error", "error": str(exc)}
|
|
554
|
+
|
|
555
|
+
|
|
481
556
|
@handles("get_ingestion_audit")
|
|
482
557
|
async def handle_get_ingestion_audit(message: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
483
558
|
req_id = message.get("id")
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""Stable defaults for a local Topos node.
|
|
2
|
+
|
|
3
|
+
8676 is TOPO on a phone keypad. Keep this the only Python source of the
|
|
4
|
+
listen port so CLI, probes, and the local MCP proxy cannot drift.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
DEFAULT_NODE_PORT = 8676
|
|
8
|
+
DEFAULT_NODE_HTTP_URL = f"http://127.0.0.1:{DEFAULT_NODE_PORT}"
|
|
9
|
+
DEFAULT_NODE_LOCALHOST_URL = f"http://localhost:{DEFAULT_NODE_PORT}"
|
|
@@ -169,13 +169,36 @@ class PrivacyLayerClient:
|
|
|
169
169
|
return {"status": "failed", "error": str(last_exc), "items": []}
|
|
170
170
|
|
|
171
171
|
|
|
172
|
+
# Names for the two model passes below. They are reported to the caller's
|
|
173
|
+
# progress callback and surface verbatim in the UI, so they are written for a
|
|
174
|
+
# person watching an import rather than for a log grep.
|
|
175
|
+
#
|
|
176
|
+
# "Filtering private information" rather than "checking for private details":
|
|
177
|
+
# this pass does not merely look. It detects PII spans and REDACTS them into
|
|
178
|
+
# the disclosure copy, which is the whole point of the layer — the node is
|
|
179
|
+
# preparing what it can safely show. A name that says "checking" describes an
|
|
180
|
+
# inspection and undersells the thing the product actually does for you.
|
|
181
|
+
PRIVACY_STAGE_REDACT = "filtering private information"
|
|
182
|
+
PRIVACY_STAGE_NSFW = "checking for sensitive content"
|
|
183
|
+
|
|
184
|
+
# How many records to send per call. NOT a throughput choice: both engine
|
|
185
|
+
# backends (redact_privacy_batch, classify_nsfw_batch) loop over `items` one at
|
|
186
|
+
# a time, so grouping 32 records buys no batched inference -- it is purely
|
|
187
|
+
# transport. The only thing the group size decides is how often progress can
|
|
188
|
+
# move. Measured on a live import: ~3.75s per record on CPU, so a group of 32
|
|
189
|
+
# meant the bar stepped once every two minutes and read as frozen; at 4 it
|
|
190
|
+
# moves about every fifteen seconds. The per-call overhead is a dict and a
|
|
191
|
+
# thread hop against ~15s of model work.
|
|
192
|
+
PRIVACY_PROGRESS_CHUNK = 4
|
|
193
|
+
|
|
194
|
+
|
|
172
195
|
async def run_privacy_disclosure_layer(
|
|
173
196
|
conn,
|
|
174
197
|
canonical_messages: List[Dict[str, Any]],
|
|
175
198
|
*,
|
|
176
199
|
source_group: Optional[str] = None,
|
|
177
200
|
client: Optional[PrivacyLayerClient] = None,
|
|
178
|
-
progress_callback: Optional[Callable[[int, int], None]] = None,
|
|
201
|
+
progress_callback: Optional[Callable[[int, int, str], None]] = None,
|
|
179
202
|
nsfw_only: bool = False,
|
|
180
203
|
) -> Dict[str, Any]:
|
|
181
204
|
"""Mandatory post-canonical Platform Privacy Layer: PII disclosure + NSFW tags.
|
|
@@ -242,7 +265,7 @@ async def run_privacy_disclosure_layer(
|
|
|
242
265
|
table = canonical_table_for_message(msg, source_group=source_group)
|
|
243
266
|
if not table:
|
|
244
267
|
if progress_callback:
|
|
245
|
-
progress_callback(idx + 1, total)
|
|
268
|
+
progress_callback(idx + 1, total, PRIVACY_STAGE_REDACT)
|
|
246
269
|
continue
|
|
247
270
|
record_id = (
|
|
248
271
|
msg.get("message_id")
|
|
@@ -252,7 +275,7 @@ async def run_privacy_disclosure_layer(
|
|
|
252
275
|
)
|
|
253
276
|
if not record_id:
|
|
254
277
|
if progress_callback:
|
|
255
|
-
progress_callback(idx + 1, total)
|
|
278
|
+
progress_callback(idx + 1, total, PRIVACY_STAGE_REDACT)
|
|
256
279
|
continue
|
|
257
280
|
record_id = str(record_id)
|
|
258
281
|
for field in fields_for_table(table):
|
|
@@ -284,10 +307,24 @@ async def run_privacy_disclosure_layer(
|
|
|
284
307
|
|
|
285
308
|
from ..sanitization.privacy_filter import PRIVACY_DISCLOSE_MAX_BATCH
|
|
286
309
|
|
|
287
|
-
|
|
288
|
-
|
|
310
|
+
# Report against the batched work, not the message list: this loop is
|
|
311
|
+
# where the model time goes, and the old callback fired only on the
|
|
312
|
+
# branches that SKIP a message -- so a run with nothing to skip
|
|
313
|
+
# reported nothing at all, for its entire duration.
|
|
314
|
+
_redact_total = len(flat_pending)
|
|
315
|
+
_redact_done = 0
|
|
316
|
+
_redact_chunk = min(PRIVACY_DISCLOSE_MAX_BATCH, PRIVACY_PROGRESS_CHUNK)
|
|
317
|
+
for i in range(0, len(flat_pending), _redact_chunk):
|
|
318
|
+
batch = flat_pending[i : i + _redact_chunk]
|
|
289
319
|
items = [{"id": e["batch_key"], "text": e["raw"]} for e in batch]
|
|
320
|
+
if progress_callback:
|
|
321
|
+
progress_callback(_redact_done, _redact_total, PRIVACY_STAGE_REDACT)
|
|
290
322
|
result = await privacy_client.redact_batch(items)
|
|
323
|
+
_redact_done += len(batch)
|
|
324
|
+
# Also after: without this the final group never reports, and the
|
|
325
|
+
# stage appears to stop one group short of its own total.
|
|
326
|
+
if progress_callback:
|
|
327
|
+
progress_callback(_redact_done, _redact_total, PRIVACY_STAGE_REDACT)
|
|
291
328
|
if result.get("status") in ("unavailable", "failed"):
|
|
292
329
|
failed_batches += 1
|
|
293
330
|
logger.warning(
|
|
@@ -349,10 +386,18 @@ async def run_privacy_disclosure_layer(
|
|
|
349
386
|
from ..sanitization.nsfw_classifier import NSFW_CLASSIFY_MAX_BATCH
|
|
350
387
|
|
|
351
388
|
nsfw_items = list(nsfw_pending.items())
|
|
352
|
-
|
|
353
|
-
|
|
389
|
+
_nsfw_total = len(nsfw_items)
|
|
390
|
+
_nsfw_done = 0
|
|
391
|
+
_nsfw_chunk = min(NSFW_CLASSIFY_MAX_BATCH, PRIVACY_PROGRESS_CHUNK)
|
|
392
|
+
for i in range(0, len(nsfw_items), _nsfw_chunk):
|
|
393
|
+
batch = nsfw_items[i : i + _nsfw_chunk]
|
|
354
394
|
items = [{"id": key, "text": entry["text"]} for key, entry in batch]
|
|
395
|
+
if progress_callback:
|
|
396
|
+
progress_callback(_nsfw_done, _nsfw_total, PRIVACY_STAGE_NSFW)
|
|
355
397
|
nsfw_result = await privacy_client.classify_nsfw_batch(items)
|
|
398
|
+
_nsfw_done += len(batch)
|
|
399
|
+
if progress_callback:
|
|
400
|
+
progress_callback(_nsfw_done, _nsfw_total, PRIVACY_STAGE_NSFW)
|
|
356
401
|
if nsfw_result.get("status") in ("failed",):
|
|
357
402
|
nsfw_failed_batches += 1
|
|
358
403
|
continue
|