topos-node 1.3.4__tar.gz → 1.3.6__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.4/topos_node.egg-info → topos_node-1.3.6}/PKG-INFO +13 -3
- {topos_node-1.3.4 → topos_node-1.3.6}/README.md +8 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/pyproject.toml +10 -3
- topos_node-1.3.6/tests/test_prewarm_first_run.py +61 -0
- topos_node-1.3.6/tests/test_protocol_handled_types.py +293 -0
- topos_node-1.3.6/tests/test_system_computer_name.py +113 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/__version__.py +2 -2
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/enrichment.py +2 -2
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/ingestion_api.py +14 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/shell.py +7 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/signal.py +126 -1
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/upgrades.py +7 -1
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/cli/commands.py +27 -3
- topos_node-1.3.6/topos/cli/reprocess_cmd.py +91 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/cli/tray.py +45 -6
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/config/conversation_context_llm.py +62 -5
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/config/facts_llm.py +39 -4
- topos_node-1.3.6/topos/config/model_packs.py +474 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/config/sanitization_ollama.py +37 -1
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/config/signal_extraction.py +51 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/control_plane_client.py +3 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/api_models.py +9 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/__init__.py +2 -1
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/database_explorer.py +3 -3
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/device.py +19 -0
- topos_node-1.3.6/topos/core/handlers/graph_query.py +67 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/ingest.py +4 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/messages.py +4 -0
- topos_node-1.3.6/topos/core/handlers/registry.py +43 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/signal_features.py +117 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/uma.py +4 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/logging.py +4 -1
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/state.py +170 -5
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/data_explorer_row_delete.py +1 -2
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/disclosure/privacy_layer.py +3 -2
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/backends/generative_prompts.py +17 -7
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/backends/ollama.py +12 -2
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/engine.py +11 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/tasks.py +7 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/usage_observation.py +24 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/catalog.py +2 -1
- topos_node-1.3.6/topos/enrichment/derivation_recovery.py +381 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/derived_tables.py +64 -23
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/job_writer.py +0 -1
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/_engine_runner.py +21 -1
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/dimension_summary_job.py +4 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/entities_job.py +29 -15
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/pii_redaction_job.py +3 -2
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/topic_clusters_job.py +71 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/orchestrator.py +73 -7
- topos_node-1.3.6/topos/enrichment/pipeline_activity.py +51 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/complexity/projection.py +85 -3
- topos_node-1.3.6/topos/features/entities/affinity.py +487 -0
- topos_node-1.3.6/topos/features/entities/affinity_owner.py +401 -0
- topos_node-1.3.6/topos/features/entities/affinity_quality.py +592 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/entities/consolidation.py +93 -41
- topos_node-1.3.6/topos/features/entities/context_vectors.py +316 -0
- topos_node-1.3.6/topos/features/entities/cypher.py +314 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/entities/dossier.py +109 -19
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/entities/edges.py +21 -3
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/entities/graph_refresh.py +32 -7
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/entities/linking.py +43 -8
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/entities/maintenance.py +286 -39
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/entities/reads.py +38 -11
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/entities/resolver.py +82 -21
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/facts/llm_extract.py +52 -21
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/lifecycle/blackhole_rebuild.py +31 -1
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/lifecycle/derived_scrub.py +136 -21
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/lifecycle/exclusions.py +9 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/lifecycle/gc.py +8 -3
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/conversation_context.py +18 -3
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/data_health.py +1 -1
- topos_node-1.3.6/topos/features/signal/derived_spec.py +115 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/topic_clustering.py +45 -2
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/stats/insights.py +40 -5
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/reprocess.py +204 -37
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/pipeline/job_runner.py +137 -27
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/pipeline/job_store.py +54 -2
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/protocol/handled_message_types.json +12 -0
- topos_node-1.3.6/topos/query/cohort_resolvers.py +294 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/manifest.py +16 -5
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/manifest_validation.py +91 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/pipeline.py +148 -24
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/planner.py +10 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/retrieval.py +419 -34
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/scope_registry.json +14 -7
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/types.py +4 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/sanitization/ollama_transforms.py +23 -1
- topos_node-1.3.6/topos/sanitization/prewarm.py +212 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/services/llm/openai.py +13 -6
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/sources/registry.py +16 -7
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/sources/scrub_attribution.py +8 -6
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/adapters/fakes.py +9 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/adapters/protocols.py +1 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/adapters/sqlite/stores.py +33 -19
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/canonical/conversations_tables.py +3 -2
- topos_node-1.3.6/topos/storage/db/migrations/affinity_pair_labels_v1.py +58 -0
- topos_node-1.3.6/topos/storage/db/migrations/entity_affinity_v1.py +62 -0
- topos_node-1.3.6/topos/storage/db/migrations/entity_context_vectors_v1.py +56 -0
- topos_node-1.3.6/topos/storage/db/migrations/entity_context_vectors_v2.py +55 -0
- topos_node-1.3.6/topos/storage/db/migrations/entity_mentions_authored_v1.py +229 -0
- topos_node-1.3.6/topos/storage/db/migrations/message_emotions_role_backfill_v1.py +153 -0
- topos_node-1.3.6/topos/storage/db/migrations/message_emotions_role_v1.py +39 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/registry.py +48 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/registry_checksums.json +6 -0
- topos_node-1.3.6/topos/storage/db/migrations/signal_summaries_drop_v1.py +30 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/storage_breakdown.py +0 -1
- topos_node-1.3.6/topos/storage/db/write_gate.py +222 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/upgrades/manifests.json +15 -0
- {topos_node-1.3.4 → topos_node-1.3.6/topos_node.egg-info}/PKG-INFO +13 -3
- {topos_node-1.3.4 → topos_node-1.3.6}/topos_node.egg-info/SOURCES.txt +22 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos_node.egg-info/requires.txt +4 -2
- topos_node-1.3.4/tests/test_protocol_handled_types.py +0 -70
- topos_node-1.3.4/topos/core/handlers/registry.py +0 -21
- topos_node-1.3.4/topos/sanitization/prewarm.py +0 -32
- topos_node-1.3.4/topos/storage/db/write_gate.py +0 -110
- {topos_node-1.3.4 → topos_node-1.3.6}/LICENSE +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/MANIFEST.in +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/setup.cfg +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/shared/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/shared/filtering.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/shared/schema_registry.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/tests/test_extensions.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/tests/test_llm_integrations_storage.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/analytics/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/analytics/duckdb_adapter.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/analytics/messenger_communities.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/analytics/messenger_graph.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/analytics/messenger_labels.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/analytics/profiles.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/analytics/query_engine.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/analytics/raw_queries.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/analytics.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/app_registry.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/backup.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/compute_remote.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/conversation_context.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/data_commit.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/data_explorer_table_prefs.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/database_explorer.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/db.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/device.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/engine_run.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/enrichment_lab.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/facts_llm_config.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/filter_lab.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/health.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/home_chat.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/ingestion_compat.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/ingestion_sources.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/intelligence_lifecycle.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/llm.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/local_mcp.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/messenger_analytics.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/privacy_disclose.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/query_api.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/runtime_bootstrap.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/sanitization_ollama_config.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/signal_extraction_config.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/source_install.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/source_scrub.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/sources.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/sources_overview.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/sync.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/tool_index.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/ui_config.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/uma_data.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/usage.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/api/user_identity.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/app.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/auth.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/canonicalization/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/canonicalization/mappers/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/canonicalization/mappers/base.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/canonicalization/mappers/browser_activity_mapper.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/canonicalization/mappers/chatgpt_mapper.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/canonicalization/mappers/demo_mappers.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/canonicalization/mappers/documents_mapper.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/canonicalization/mappers/github_activity_mapper.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/canonicalization/mappers/google_calendar_mapper.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/canonicalization/mappers/grok_mapper.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/canonicalization/mappers/messenger_mapper.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/canonicalization/models.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/canonicalization/resolver.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/cli/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/cli/__main__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/cli/assets/topos_blk_rounded.png +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/cli/assets/topos_white.png +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/config/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/config/settings.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/config/uvicorn_logging.json +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/contacts/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/contacts/identity.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/connection_resilience.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/device_helpers.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/errors.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/events.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/common.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/complexity.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/config.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/contacts_import.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/enrichment.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/enrichment_lab.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/filter_lab.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/home_chat.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/messenger_analytics.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/query.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/routines.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/sources.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/timeline_daily.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/handlers/tool_index.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/metrics.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/routine_access.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/startup_banner.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/table_layers.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/core/types.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/data_explorer_table_prefs.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/data_explorer_tables.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/disclosure/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/disclosure/canonical_writer.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/disclosure/content_policy.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/disclosure/field_registry.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/disclosure/tier.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/backends/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/backends/base.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/backends/generative_response.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/backends/huggingface.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/backends/openai.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/backends/openai_compatible.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/backends/redpill.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/backends/stub.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/client.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/intake.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/memory_utils.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/model_cache.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/pipeline_memory.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/queue_manager.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/registration.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/result_formatter.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/router.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/scoped_token.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/transport.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/usage_guard.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/engine/validator.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/base.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/_batch_limits.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/attention_triage_job.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/availability_scores_job.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/brief_fallback.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/complexity_snapshot_job.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/embeddings_job.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/emo_27_job.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/fact_extraction_job.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/goal_extraction_job.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/relationship_edges_job.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/sentiment_job.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/statistics_job.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/timeline_job.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/topics_job.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/url_classification_core.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/url_classification_enrichment_job.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/canonical/url_classification_signal_job.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/raw/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/raw/attachments_job.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/raw/language_job.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/raw/time_normalization_job.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/jobs/raw/tool_calls_job.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/model_overrides.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/models/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/models/manager.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/models/mvp_defaults.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/models/registry.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/models/versioning.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/processor.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/progress_bar.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/registry_contract.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/signal_derivation_config.json +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/source_overrides.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment/website_classifier.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment_lab/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment_lab/bundles.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment_lab/model_resolve.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment_lab/schema.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment_lab/service.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment_lab/store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/enrichment_lab/worker.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/evals/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/evals/enrichment_eval.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/extensions.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/complexity/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/complexity/canonical.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/complexity/engine.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/complexity/entropy.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/complexity/focus.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/complexity/graph_metrics.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/complexity/influence.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/complexity/snapshots.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/complexity/store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/complexity/topic_merge.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/complexity/topics.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/complexity/topics_daily.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/complexity/volatility.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/entities/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/entities/declared_mappings.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/entities/fact_materializer.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/entities/graph_enrichers.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/entities/graph_search.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/facts/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/facts/extract.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/facts/reads.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/facts/store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/facts/verdicts.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/fit/evaluator.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/fit/opportunity_types.json +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/lifecycle/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/lifecycle/blackhole.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/lifecycle/blackhole_guard.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/lifecycle/blackhole_llm.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/provenance/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/provenance/posture.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/provenance/roles.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/brief_canonical_loader.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/brief_ontology.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/brief_renderer.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/brief_schemas.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/chunking.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/cluster_labels.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/definitions/brief_ontologies.json +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/definitions/intentions.json +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/definitions/profile.json +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/definitions/relationships.json +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/definitions/schema/dimension_definition.schema.json +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/definitions/time.json +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/definitions/work.json +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/dimension_briefs.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/dimension_definition_loader.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/dimension_profiles.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/dimension_registry.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/embed_context.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/extraction/artifact_router.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/extraction/artifact_store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/extraction/rule_extractors.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/graph_sanitize.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/hybrid_search.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/incremental_clustering.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/model_recommendations.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/query_embed_cache.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/schemas.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/service.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/signal_object_store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/source_hydration.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/structured_signal.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/tool_index.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/typed_stores/aggregates.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/typed_stores/commitments.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/typed_stores/rhythm.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/typed_stores/scope_materializer.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/vector_codec.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/vector_math.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/signal/vector_settings.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/stats/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/stats/definitions.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/stats/engine.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/stats/fold.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/timeline_projection.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/timeline_rollup.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/triage/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/triage/badges.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/triage/daily.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/triage/dashboard.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/triage/instruments.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/triage/intents.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/features/triage/readiness.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/filter_lab/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/filter_lab/bundles.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/filter_lab/schema.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/filter_lab/service.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/filter_lab/store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/filter_lab/worker.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/home_chat/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/home_chat/schema.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/home_chat/store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/hosted_pool_lease.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/canonical_pipeline.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/checkpoints/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/checkpoints/checkpoint_store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/checkpoints/sqlite_checkpoint_store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/inbox_crypto.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/inbox_drain.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/ingest_helpers.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/jobs.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/journal_location_fanout.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/journal_time_log_normalize.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/local_sync.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/log_preview.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/manager.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/parser.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/parsers/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/parsers/base.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/parsers/browser_parser.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/parsers/calendar_parser.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/parsers/chatgpt_conversation_flattener.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/parsers/chatgpt_parser.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/parsers/demo_file_parsers.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/parsers/documents_parser.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/parsers/github_activity_parser.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/parsers/google_calendar_parser.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/parsers/grok_parser.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/parsers/messenger_parser.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/parsers/voxterm_parser.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/progress.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/sources/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/sources/base.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/sources/calendar.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/sources/chatgpt.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/sources/contact_importers.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/sources/grok.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/sources/imessage_reader.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/sources/signal_export_parser.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/sources/signal_reader.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/state_machine.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/triggers/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/triggers/file_trigger.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/triggers/sqlite_trigger.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/usage_inbox_dedupe.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/validation/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/validation/base.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/validation/schema_registry.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/ingestion/validation/schema_validator.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/lineage/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/lineage/provenance.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/lineage/tracker.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/llm_integrations_storage.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/mcp_stdio_proxy.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/observability/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/observability/alerts.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/observability/metrics.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/observability/tracing.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/openai_client.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/pipeline/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/pipeline/audit.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/pipeline/envelope.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/pipeline/stages.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/pipeline/stub_enqueue.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/projections/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/projections/vector_index/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/projections/vector_index/base.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/projections/vector_index/builders.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/projections/vector_index/health_checks.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/protocol/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/audit.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/ddr.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/disclosure.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/fingerprint.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/game_layer.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/grant_cache.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/inference.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/intent.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/minimizer.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/negotiation.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/runtime.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/scope_registry_loader.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/session.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/session_utils.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/source_generation.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/truth_facts.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/truth_prompts.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/turn_classifier.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/verify.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/query/verify_modes.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/rate_limit.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/routines/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/routines/schema.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/routines/store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/runtime_housekeeping.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/runtime_shutdown.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/runtime_update.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/sanitization/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/sanitization/nsfw_classifier.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/sanitization/privacy_filter.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/scope_resolution.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/services/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/services/container.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/services/embeddings/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/services/embeddings/base.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/services/embeddings/local.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/services/embeddings/remote.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/services/interfaces.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/services/llm/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/services/llm/base.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/services/local.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/services/postgres.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/sources/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/sources/bundled_canonical_triples.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/sources/canonical_signal_defaults.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/sources/definitions.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/sources/install_service.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/sources/runtime_install.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/sources/scrub_service.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/startup_banner.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/adapters/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/adapters/factory.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/adapters/postgres/stores.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/adapters/sqlite/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/adapters/sqlite/vector_search.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/canonical/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/canonical/activity_tables.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/canonical/ai_chat/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/canonical/ai_chat/canonicalizer.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/canonical/ai_chat/mapper.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/canonical/ai_chat/model.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/canonical/ai_chat/tables.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/canonical/calendar_contacts_tables.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/canonical/canonical_store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/canonical/mapping_store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/canonical/postgres.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/client.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/connection_tuning.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/activity_events_content_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/actor_role_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/attention_triage_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/attention_triage_v2.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/backup.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/calendar_events_scheduling_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/canonical_address_book_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/canonical_disclosure_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/canonical_nsfw_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/complexity_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/conversation_context_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/derivation_ledger_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/documents_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/enrichment_spec_version_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/entity_blackhole_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/entity_edges_validity_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/episodes_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/extraction_artifacts.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/journal_entries_duration_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/journal_entries_ends_at_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/journal_entries_people_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/journal_entries_place_name_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/journal_entries_starts_at_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/pipeline_jobs_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/remediation_person_model.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/scope_source_generation.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/signal_dimension_backfill_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/signal_dimension_harness.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/signal_objects.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/signal_objects_period_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/signal_objects_updated_by_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/stage9_column_renames.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/vector_storage_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/vector_storage_v2.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/vector_storage_v3.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/vector_storage_v4.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/wiki_clusters_v2.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/wiki_entities_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/wiki_entity_review_v2.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/wiki_facts_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/wiki_lifecycle_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/wiki_mvp_phase0.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/wiki_mvp_phase1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/wiki_mvp_phase4_messages_cutover.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/wiki_mvp_phase5_topic_clusters.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/wiki_mvp_phase6_dimension_briefs.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/wiki_mvp_query_quality.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/wiki_mvp_topic_clusters_coordination.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/wiki_stats_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/migrations/wiki_timeline_v1.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/paths.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/postgres.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/db/schema.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/enrichment/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/enrichment/canonical_enrichment_store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/enrichment/raw_enrichment_store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/normalized/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/normalized/normalized_store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/oplog/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/oplog/decision.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/oplog/oplog_store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/oplog/postgres.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/person/identity_resolver.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/projections/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/projections/index_ops_store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/projections/vector_index_store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/raw/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/raw/browser_flat_tables.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/raw/file_store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/raw/raw_store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/raw/raw_tables_manager.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/raw/sqlite_raw_store.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/security/encryption.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/signal_identity.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/source_settings.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/storage/user_identity.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/sync/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/sync/client.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/sync_handlers.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/testing/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/testing/lifespan.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/uma_contact_enrichment.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/uma_filters.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/uma_resource_id.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/uma_rpt.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/upgrades/__init__.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/upgrades/runner.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/utils/base_object.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos/websocket_client.py +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos_node.egg-info/dependency_links.txt +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/topos_node.egg-info/entry_points.txt +0 -0
- {topos_node-1.3.4 → topos_node-1.3.6}/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.6
|
|
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
|
|
@@ -25,7 +25,7 @@ Requires-Dist: google-cloud-run~=0.16.0
|
|
|
25
25
|
Requires-Dist: asgi-lifespan~=2.1.0
|
|
26
26
|
Requires-Dist: psycopg[binary]~=3.3.3
|
|
27
27
|
Requires-Dist: duckdb~=1.5.2
|
|
28
|
-
Requires-Dist: torch<
|
|
28
|
+
Requires-Dist: torch<2.13,>=2.8.0
|
|
29
29
|
Requires-Dist: transformers~=5.10.2
|
|
30
30
|
Requires-Dist: huggingface-hub~=1.18.0
|
|
31
31
|
Requires-Dist: tqdm~=4.67.3
|
|
@@ -33,6 +33,7 @@ Requires-Dist: hf-xet~=1.5.1
|
|
|
33
33
|
Requires-Dist: sentence-transformers~=5.6.0
|
|
34
34
|
Requires-Dist: networkx<3.7,>=3.2.1
|
|
35
35
|
Requires-Dist: python-louvain<0.17,>=0.16
|
|
36
|
+
Requires-Dist: grand-cypher<0.13,>=0.12
|
|
36
37
|
Requires-Dist: numpy<3,>=1.26
|
|
37
38
|
Requires-Dist: scipy<2,>=1.11
|
|
38
39
|
Requires-Dist: scikit-learn<2,>=1.4
|
|
@@ -43,7 +44,7 @@ Provides-Extra: database
|
|
|
43
44
|
Requires-Dist: psycopg[binary]~=3.3.3; extra == "database"
|
|
44
45
|
Provides-Extra: engine
|
|
45
46
|
Requires-Dist: duckdb~=1.5.2; extra == "engine"
|
|
46
|
-
Requires-Dist: torch<
|
|
47
|
+
Requires-Dist: torch<2.13,>=2.8.0; extra == "engine"
|
|
47
48
|
Requires-Dist: transformers~=5.10.2; extra == "engine"
|
|
48
49
|
Requires-Dist: huggingface-hub~=1.18.0; extra == "engine"
|
|
49
50
|
Requires-Dist: tqdm~=4.67.3; extra == "engine"
|
|
@@ -51,6 +52,7 @@ Requires-Dist: hf-xet~=1.5.1; extra == "engine"
|
|
|
51
52
|
Requires-Dist: sentence-transformers~=5.6.0; extra == "engine"
|
|
52
53
|
Requires-Dist: networkx<3.7,>=3.2.1; extra == "engine"
|
|
53
54
|
Requires-Dist: python-louvain<0.17,>=0.16; extra == "engine"
|
|
55
|
+
Requires-Dist: grand-cypher<0.13,>=0.12; extra == "engine"
|
|
54
56
|
Requires-Dist: numpy<3,>=1.26; extra == "engine"
|
|
55
57
|
Requires-Dist: scipy<2,>=1.11; extra == "engine"
|
|
56
58
|
Requires-Dist: scikit-learn<2,>=1.4; extra == "engine"
|
|
@@ -126,6 +128,14 @@ Topos Engine uses both local and model-hub paths so users can choose flexibility
|
|
|
126
128
|
|
|
127
129
|
The `shared/` package in this repo is part of the node runtime contract. It contains common schema and filtering definitions used by both API and engine paths.
|
|
128
130
|
|
|
131
|
+
### Architecture notes (where truth lives)
|
|
132
|
+
|
|
133
|
+
This README is orientation, not the architecture ledger. Prefer:
|
|
134
|
+
|
|
135
|
+
- **As-built / why:** sibling `topos-research-wiki` → `20_ARCHITECTURE/` (`As_Built_Node`, firewall, query, MCP, graph, …)
|
|
136
|
+
- **As-is invariants / checks:** sibling `topos-ops-wiki` → `25_SYSTEMS/` (`SYS-node`, `SYS-cognitive-firewall`, …)
|
|
137
|
+
- **Target design:** `topos-data-wiki` (`status: target`) — do not implement from it without checking as-built
|
|
138
|
+
|
|
129
139
|
## Quick Start
|
|
130
140
|
|
|
131
141
|
### 1) Install
|
|
@@ -61,6 +61,14 @@ Topos Engine uses both local and model-hub paths so users can choose flexibility
|
|
|
61
61
|
|
|
62
62
|
The `shared/` package in this repo is part of the node runtime contract. It contains common schema and filtering definitions used by both API and engine paths.
|
|
63
63
|
|
|
64
|
+
### Architecture notes (where truth lives)
|
|
65
|
+
|
|
66
|
+
This README is orientation, not the architecture ledger. Prefer:
|
|
67
|
+
|
|
68
|
+
- **As-built / why:** sibling `topos-research-wiki` → `20_ARCHITECTURE/` (`As_Built_Node`, firewall, query, MCP, graph, …)
|
|
69
|
+
- **As-is invariants / checks:** sibling `topos-ops-wiki` → `25_SYSTEMS/` (`SYS-node`, `SYS-cognitive-firewall`, …)
|
|
70
|
+
- **Target design:** `topos-data-wiki` (`status: target`) — do not implement from it without checking as-built
|
|
71
|
+
|
|
64
72
|
## Quick Start
|
|
65
73
|
|
|
66
74
|
### 1) Install
|
|
@@ -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.6"
|
|
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"
|
|
@@ -27,7 +27,7 @@ dependencies = [
|
|
|
27
27
|
"asgi-lifespan~=2.1.0",
|
|
28
28
|
"psycopg[binary]~=3.3.3",
|
|
29
29
|
"duckdb~=1.5.2",
|
|
30
|
-
"torch>=2.8.0,<
|
|
30
|
+
"torch>=2.8.0,<2.13",
|
|
31
31
|
"transformers~=5.10.2",
|
|
32
32
|
"huggingface-hub~=1.18.0",
|
|
33
33
|
"tqdm~=4.67.3",
|
|
@@ -35,6 +35,10 @@ dependencies = [
|
|
|
35
35
|
"sentence-transformers~=5.6.0",
|
|
36
36
|
"networkx>=3.2.1,<3.7",
|
|
37
37
|
"python-louvain>=0.16,<0.17",
|
|
38
|
+
# openCypher over the materialised entity graph, owner-only
|
|
39
|
+
# (topos.features.entities.cypher; PLAN_GRAPH_QUERY_AND_LATENT_EDGES §4).
|
|
40
|
+
# Pure-Python parser (lark) + matcher over networkx — no graph database.
|
|
41
|
+
"grand-cypher>=0.12,<0.13",
|
|
38
42
|
# Complexity readings (topos.features.complexity): entropy/MI + graph math.
|
|
39
43
|
"numpy>=1.26,<3",
|
|
40
44
|
"scipy>=1.11,<2",
|
|
@@ -58,7 +62,7 @@ database = [
|
|
|
58
62
|
# ML + enrichment runtime (hosted topos-engine Cloud Run image).
|
|
59
63
|
engine = [
|
|
60
64
|
"duckdb~=1.5.2",
|
|
61
|
-
"torch>=2.8.0,<
|
|
65
|
+
"torch>=2.8.0,<2.13",
|
|
62
66
|
"transformers~=5.10.2",
|
|
63
67
|
"huggingface-hub~=1.18.0",
|
|
64
68
|
"tqdm~=4.67.3",
|
|
@@ -66,6 +70,7 @@ engine = [
|
|
|
66
70
|
"sentence-transformers~=5.6.0",
|
|
67
71
|
"networkx>=3.2.1,<3.7",
|
|
68
72
|
"python-louvain>=0.16,<0.17",
|
|
73
|
+
"grand-cypher>=0.12,<0.13",
|
|
69
74
|
"numpy>=1.26,<3",
|
|
70
75
|
"scipy>=1.11,<2",
|
|
71
76
|
"scikit-learn>=1.4,<2",
|
|
@@ -106,6 +111,8 @@ filterwarnings = [
|
|
|
106
111
|
"ignore:on_event is deprecated.*:DeprecationWarning:fastapi.*",
|
|
107
112
|
]
|
|
108
113
|
markers = [
|
|
114
|
+
"journey: binds this test to a J-* journey note in topos-ops-wiki (the id is the marker arg)",
|
|
115
|
+
"check: binds this test to a C-* check note in topos-ops-wiki (the id is the marker arg)",
|
|
109
116
|
"gap: gap verification test (sprint pack); must pass after sprint lands",
|
|
110
117
|
"qq_eval: live query quality/latency eval against owner database",
|
|
111
118
|
"acceptance: Wiki MVP acceptance test (AT-1 through AT-8)",
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""first_run decides whether the UI says "downloading" or "preparing".
|
|
2
|
+
|
|
3
|
+
Getting it wrong is a lie in the copy: a node that reports first_run=False shows
|
|
4
|
+
"preparing its language models… should only take a moment" while it fetches 2.9GB.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
|
|
11
|
+
import pytest
|
|
12
|
+
|
|
13
|
+
from topos.sanitization import prewarm
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@pytest.fixture
|
|
17
|
+
def cache_root(tmp_path, monkeypatch):
|
|
18
|
+
monkeypatch.setattr(prewarm, "_hf_cache_root", lambda: str(tmp_path))
|
|
19
|
+
return tmp_path
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _write_blobs(cache_root, repo_id: str, names: list[str]) -> None:
|
|
23
|
+
blobs = os.path.join(prewarm._repo_dir(str(cache_root), repo_id), "blobs")
|
|
24
|
+
os.makedirs(blobs, exist_ok=True)
|
|
25
|
+
for name in names:
|
|
26
|
+
open(os.path.join(blobs, name), "w").close()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
REPO = prewarm.PRIVACY_FILTER_REPO
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_absent_repo_is_not_present(cache_root):
|
|
33
|
+
assert prewarm._repo_present(REPO) is False
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_started_but_empty_is_not_present(cache_root):
|
|
37
|
+
"""The first instant of a first download — the directory exists, nothing is in it."""
|
|
38
|
+
_write_blobs(cache_root, REPO, [])
|
|
39
|
+
assert prewarm._repo_present(REPO) is False
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_interrupted_download_is_not_present(cache_root):
|
|
43
|
+
"""The case that made this a bug: a killed first run leaves .incomplete blobs
|
|
44
|
+
behind, and directory-existence alone would call that done."""
|
|
45
|
+
_write_blobs(cache_root, REPO, ["abc123.incomplete"])
|
|
46
|
+
assert prewarm._repo_present(REPO) is False
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_partially_resumed_download_is_not_present(cache_root):
|
|
50
|
+
_write_blobs(cache_root, REPO, ["abc123", "def456.incomplete"])
|
|
51
|
+
assert prewarm._repo_present(REPO) is False
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def test_complete_download_is_present(cache_root):
|
|
55
|
+
_write_blobs(cache_root, REPO, ["abc123", "def456"])
|
|
56
|
+
assert prewarm._repo_present(REPO) is True
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_no_cache_root_is_not_present(monkeypatch):
|
|
60
|
+
monkeypatch.setattr(prewarm, "_hf_cache_root", lambda: None)
|
|
61
|
+
assert prewarm._repo_present(REPO) is False
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
"""Guards for the handled-message-types protocol snapshot.
|
|
2
|
+
|
|
3
|
+
The snapshot (topos/protocol/handled_message_types.json) is the machine-readable
|
|
4
|
+
list of control-plane message types this engine dispatches. Two invariants:
|
|
5
|
+
|
|
6
|
+
1. Freshness — the committed snapshot equals the runtime HANDLERS registry.
|
|
7
|
+
Adding or removing an @handles registration requires regenerating it:
|
|
8
|
+
uv run python scripts/dump_handled_types.py > topos/protocol/handled_message_types.json
|
|
9
|
+
|
|
10
|
+
2. Static parity — the set of string literals in @handles(...) decorators equals
|
|
11
|
+
the runtime registry, so no handler is registered dynamically in a way that
|
|
12
|
+
static consumers of the snapshot (or this repo's source) would miss.
|
|
13
|
+
|
|
14
|
+
The snapshot's second key, ``owner_only_message_types``, carries the subset
|
|
15
|
+
registered with ``@handles(..., owner_only=True)``. Those are types the engine
|
|
16
|
+
answers for the node's owner but which must never be reachable from an agent or
|
|
17
|
+
cross-user surface; the tests below are the leak gates that enforce it.
|
|
18
|
+
|
|
19
|
+
What "not reachable" is measured against
|
|
20
|
+
----------------------------------------
|
|
21
|
+
The control plane's ``/mcp`` gateway (``control_plane/mcp_gateway.py``) is the
|
|
22
|
+
only place the CP forwards an engine message on behalf of an agent or a UMA
|
|
23
|
+
grantee, so it is the forwarding set these gates assert against: both the tool
|
|
24
|
+
names it publishes and the message types those tools forward.
|
|
25
|
+
|
|
26
|
+
``control_plane/engine_protocol.py::SENT_MESSAGE_TYPES`` is deliberately *not*
|
|
27
|
+
the gate. It declares what the owner's own authenticated dashboard routes send
|
|
28
|
+
to the owner's own node — ``delete_database_table`` is in it precisely because
|
|
29
|
+
the owner's data explorer exists. Owner-only means owner-only, not unreachable.
|
|
30
|
+
"""
|
|
31
|
+
from __future__ import annotations
|
|
32
|
+
|
|
33
|
+
import ast
|
|
34
|
+
import json
|
|
35
|
+
import os
|
|
36
|
+
from pathlib import Path
|
|
37
|
+
|
|
38
|
+
import pytest
|
|
39
|
+
|
|
40
|
+
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
41
|
+
SNAPSHOT = REPO_ROOT / "topos" / "protocol" / "handled_message_types.json"
|
|
42
|
+
|
|
43
|
+
MCP_GATEWAY_RELPATH = Path("control_plane") / "mcp_gateway.py"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _runtime_handled() -> set[str]:
|
|
47
|
+
from topos.core.handlers import HANDLERS
|
|
48
|
+
|
|
49
|
+
return set(HANDLERS)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _runtime_owner_only() -> set[str]:
|
|
53
|
+
from topos.core.handlers import OWNER_ONLY_MESSAGE_TYPES
|
|
54
|
+
|
|
55
|
+
return set(OWNER_ONLY_MESSAGE_TYPES)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _handles_calls() -> list[ast.Call]:
|
|
59
|
+
calls: list[ast.Call] = []
|
|
60
|
+
for py in sorted((REPO_ROOT / "topos").rglob("*.py")):
|
|
61
|
+
if "__pycache__" in py.parts:
|
|
62
|
+
continue
|
|
63
|
+
try:
|
|
64
|
+
tree = ast.parse(py.read_text(encoding="utf-8"))
|
|
65
|
+
except SyntaxError:
|
|
66
|
+
continue
|
|
67
|
+
for node in ast.walk(tree):
|
|
68
|
+
if isinstance(node, ast.Call) and getattr(node.func, "id", "") == "handles":
|
|
69
|
+
calls.append(node)
|
|
70
|
+
return calls
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _literal_str_args(call: ast.Call) -> set[str]:
|
|
74
|
+
return {
|
|
75
|
+
arg.value
|
|
76
|
+
for arg in call.args
|
|
77
|
+
if isinstance(arg, ast.Constant) and isinstance(arg.value, str)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _static_handled() -> set[str]:
|
|
82
|
+
found: set[str] = set()
|
|
83
|
+
for call in _handles_calls():
|
|
84
|
+
found |= _literal_str_args(call)
|
|
85
|
+
return found
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _static_owner_only() -> set[str]:
|
|
89
|
+
found: set[str] = set()
|
|
90
|
+
for call in _handles_calls():
|
|
91
|
+
marked = any(
|
|
92
|
+
kw.arg == "owner_only"
|
|
93
|
+
and isinstance(kw.value, ast.Constant)
|
|
94
|
+
and kw.value.value is True
|
|
95
|
+
for kw in call.keywords
|
|
96
|
+
)
|
|
97
|
+
if marked:
|
|
98
|
+
found |= _literal_str_args(call)
|
|
99
|
+
return found
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _snapshot() -> dict:
|
|
103
|
+
return json.loads(SNAPSHOT.read_text(encoding="utf-8"))
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def _mcp_gateway_tree() -> ast.AST:
|
|
107
|
+
"""The CP's /mcp gateway module, or skip if the CP repo isn't checked out.
|
|
108
|
+
|
|
109
|
+
Mirrors the CP's own engine lookup in its tests/contract/test_engine_protocol.py.
|
|
110
|
+
"""
|
|
111
|
+
env_path = os.environ.get("CONTROL_PLANE_REPO_PATH", "").strip()
|
|
112
|
+
roots = [Path(env_path)] if env_path else [REPO_ROOT.parent / "topos-control-plane"]
|
|
113
|
+
for root in roots:
|
|
114
|
+
gateway = root / MCP_GATEWAY_RELPATH
|
|
115
|
+
if gateway.is_file():
|
|
116
|
+
return ast.parse(gateway.read_text(encoding="utf-8"))
|
|
117
|
+
pytest.skip(
|
|
118
|
+
"control-plane repo not found; set CONTROL_PLANE_REPO_PATH to run the "
|
|
119
|
+
"owner-only /mcp leak gates (CI must provide it)"
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _mcp_tool_names(tree: ast.AST) -> set[str]:
|
|
124
|
+
"""Names published as /mcp tools: functions decorated with @fastmcp.tool()."""
|
|
125
|
+
names: set[str] = set()
|
|
126
|
+
for node in ast.walk(tree):
|
|
127
|
+
if not isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
|
128
|
+
continue
|
|
129
|
+
for dec in node.decorator_list:
|
|
130
|
+
func = dec.func if isinstance(dec, ast.Call) else dec
|
|
131
|
+
if isinstance(func, ast.Attribute) and func.attr == "tool":
|
|
132
|
+
names.add(node.name)
|
|
133
|
+
return names
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def _mcp_forwarded_message_types(tree: ast.AST) -> set[str]:
|
|
137
|
+
"""Engine message types the /mcp gateway forwards (_forward/_forward_owner_scoped)."""
|
|
138
|
+
found: set[str] = set()
|
|
139
|
+
for node in ast.walk(tree):
|
|
140
|
+
if not isinstance(node, ast.Call) or not node.args:
|
|
141
|
+
continue
|
|
142
|
+
name = getattr(node.func, "id", "") or getattr(node.func, "attr", "")
|
|
143
|
+
if not name.startswith("_forward"):
|
|
144
|
+
continue
|
|
145
|
+
first = node.args[0]
|
|
146
|
+
if isinstance(first, ast.Constant) and isinstance(first.value, str):
|
|
147
|
+
found.add(first.value)
|
|
148
|
+
return found
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _mcp_string_literals(tree: ast.AST) -> set[str]:
|
|
152
|
+
return {
|
|
153
|
+
node.value
|
|
154
|
+
for node in ast.walk(tree)
|
|
155
|
+
if isinstance(node, ast.Constant) and isinstance(node.value, str)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def test_snapshot_matches_runtime_registry():
|
|
160
|
+
snapshot = set(_snapshot()["handled_message_types"])
|
|
161
|
+
runtime = _runtime_handled()
|
|
162
|
+
missing = sorted(runtime - snapshot)
|
|
163
|
+
stale = sorted(snapshot - runtime)
|
|
164
|
+
assert not missing and not stale, (
|
|
165
|
+
"topos/protocol/handled_message_types.json is stale "
|
|
166
|
+
f"(missing={missing}, stale={stale}). Regenerate with: "
|
|
167
|
+
"uv run python scripts/dump_handled_types.py > topos/protocol/handled_message_types.json"
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def test_static_handles_literals_match_runtime_registry():
|
|
172
|
+
runtime = _runtime_handled()
|
|
173
|
+
static = _static_handled()
|
|
174
|
+
dynamic_only = sorted(runtime - static)
|
|
175
|
+
unregistered = sorted(static - runtime)
|
|
176
|
+
assert not dynamic_only, (
|
|
177
|
+
"Handlers registered without a literal @handles(...) decorator; static "
|
|
178
|
+
f"consumers of the registry cannot see them: {dynamic_only}"
|
|
179
|
+
)
|
|
180
|
+
assert not unregistered, (
|
|
181
|
+
f"@handles(...) literals that never reach the runtime registry: {unregistered}"
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def test_owner_only_snapshot_matches_runtime_registry():
|
|
186
|
+
snapshot = set(_snapshot()["owner_only_message_types"])
|
|
187
|
+
runtime = _runtime_owner_only()
|
|
188
|
+
missing = sorted(runtime - snapshot)
|
|
189
|
+
stale = sorted(snapshot - runtime)
|
|
190
|
+
assert not missing and not stale, (
|
|
191
|
+
"owner_only_message_types in topos/protocol/handled_message_types.json is "
|
|
192
|
+
f"stale (missing={missing}, stale={stale}). Regenerate with: "
|
|
193
|
+
"uv run python scripts/dump_handled_types.py > topos/protocol/handled_message_types.json"
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def test_owner_only_is_a_subset_of_handled():
|
|
198
|
+
snapshot = _snapshot()
|
|
199
|
+
orphans = sorted(
|
|
200
|
+
set(snapshot["owner_only_message_types"]) - set(snapshot["handled_message_types"])
|
|
201
|
+
)
|
|
202
|
+
assert not orphans, f"owner_only types with no registered handler: {orphans}"
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def test_static_owner_only_markers_match_runtime_registry():
|
|
206
|
+
runtime = _runtime_owner_only()
|
|
207
|
+
static = _static_owner_only()
|
|
208
|
+
dynamic_only = sorted(runtime - static)
|
|
209
|
+
unregistered = sorted(static - runtime)
|
|
210
|
+
assert not dynamic_only, (
|
|
211
|
+
"Types marked owner-only at runtime with no literal "
|
|
212
|
+
f"@handles(..., owner_only=True) decorator: {dynamic_only}"
|
|
213
|
+
)
|
|
214
|
+
assert not unregistered, (
|
|
215
|
+
"@handles(..., owner_only=True) literals that never reach the runtime "
|
|
216
|
+
f"registry: {unregistered}"
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def test_destructive_database_explorer_types_are_owner_only():
|
|
221
|
+
"""These predate the marker and are why it exists; they may not be unmarked."""
|
|
222
|
+
runtime = _runtime_owner_only()
|
|
223
|
+
expected = {
|
|
224
|
+
"get_database_explorer_summary",
|
|
225
|
+
"delete_database_rows",
|
|
226
|
+
"delete_database_table",
|
|
227
|
+
}
|
|
228
|
+
assert expected <= runtime, f"no longer marked owner-only: {sorted(expected - runtime)}"
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def test_graph_cypher_query_is_owner_only_and_off_every_agent_surface():
|
|
232
|
+
"""The §4.1 gate, hard 0.
|
|
233
|
+
|
|
234
|
+
An arbitrary traversal punches straight through row-level redaction:
|
|
235
|
+
``MATCH (a)-[*1..3]->(b)`` does not respect a scope unless the subgraph was
|
|
236
|
+
scoped BEFORE the query ran, and nothing scopes it today. Until a
|
|
237
|
+
scoped-subgraph materialisation story exists, openCypher is owner-only.
|
|
238
|
+
"""
|
|
239
|
+
assert "graph_cypher_query" in _runtime_owner_only(), (
|
|
240
|
+
"graph_cypher_query must be registered @handles(..., owner_only=True)"
|
|
241
|
+
)
|
|
242
|
+
assert "graph_cypher_query" in set(_snapshot()["owner_only_message_types"])
|
|
243
|
+
|
|
244
|
+
tree = _mcp_gateway_tree()
|
|
245
|
+
assert "graph_cypher_query" not in _mcp_forwarded_message_types(tree), (
|
|
246
|
+
"graph_cypher_query is forwarded by the control plane's /mcp gateway"
|
|
247
|
+
)
|
|
248
|
+
assert "graph_cypher_query" not in _mcp_tool_names(tree), (
|
|
249
|
+
"graph_cypher_query is published as a /mcp tool"
|
|
250
|
+
)
|
|
251
|
+
assert "graph_cypher_query" not in _mcp_string_literals(tree), (
|
|
252
|
+
"graph_cypher_query is named in control_plane/mcp_gateway.py"
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def test_owner_only_types_are_absent_from_the_local_mcp_tool_list():
|
|
257
|
+
"""The engine's own stdio MCP proxy is an agent surface too.
|
|
258
|
+
|
|
259
|
+
``_mcp_gateway_tree`` skips when the control-plane repo is not checked out;
|
|
260
|
+
this list ships in this repo, so this half of the gate can never be skipped.
|
|
261
|
+
"""
|
|
262
|
+
owner_only = _runtime_owner_only()
|
|
263
|
+
assert owner_only, "owner-only marker registry is empty; the gate would be vacuous"
|
|
264
|
+
|
|
265
|
+
proxy = REPO_ROOT / "topos" / "mcp_stdio_proxy.py"
|
|
266
|
+
tree = ast.parse(proxy.read_text(encoding="utf-8"))
|
|
267
|
+
|
|
268
|
+
published = sorted(owner_only & _mcp_tool_names(tree))
|
|
269
|
+
assert not published, f"owner-only types published as local /mcp tools: {published}"
|
|
270
|
+
|
|
271
|
+
mentioned = sorted(owner_only & _mcp_string_literals(tree))
|
|
272
|
+
assert not mentioned, f"owner-only types named in {proxy.name}: {mentioned}"
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def test_owner_only_types_are_absent_from_the_mcp_surface():
|
|
276
|
+
"""Hard 0: no owner-only type may be reachable through the /mcp gateway."""
|
|
277
|
+
owner_only = _runtime_owner_only()
|
|
278
|
+
assert owner_only, "owner-only marker registry is empty; the gate would be vacuous"
|
|
279
|
+
|
|
280
|
+
tree = _mcp_gateway_tree()
|
|
281
|
+
|
|
282
|
+
forwarded = sorted(owner_only & _mcp_forwarded_message_types(tree))
|
|
283
|
+
assert not forwarded, f"owner-only message types forwarded by the /mcp gateway: {forwarded}"
|
|
284
|
+
|
|
285
|
+
published = sorted(owner_only & _mcp_tool_names(tree))
|
|
286
|
+
assert not published, f"owner-only message types published as /mcp tool names: {published}"
|
|
287
|
+
|
|
288
|
+
# Belt and braces: the forward helpers can be renamed or wrapped, so also fail
|
|
289
|
+
# on an owner-only type name appearing anywhere in the gateway module at all.
|
|
290
|
+
mentioned = sorted(owner_only & _mcp_string_literals(tree))
|
|
291
|
+
assert not mentioned, (
|
|
292
|
+
f"owner-only message types named in control_plane/mcp_gateway.py: {mentioned}"
|
|
293
|
+
)
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"""The machine name a Mac owner recognises, reported alongside the hostname.
|
|
2
|
+
|
|
3
|
+
`platform.node()` returns the network hostname, which on macOS is either a
|
|
4
|
+
mangled form of the computer name ("jonnys-macbook-pro.local") or something
|
|
5
|
+
meaningless from DHCP ("mac.lan" on the machine this was written on). The
|
|
6
|
+
frontend names a new self-hosted Topos after this, so a bad answer here shows up
|
|
7
|
+
as a Topos called "mac.lan".
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import subprocess
|
|
13
|
+
|
|
14
|
+
import pytest
|
|
15
|
+
|
|
16
|
+
from topos.core import state
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@pytest.fixture(autouse=True)
|
|
20
|
+
def _clear_cache():
|
|
21
|
+
state._computer_name_cache = state._UNRESOLVED
|
|
22
|
+
yield
|
|
23
|
+
state._computer_name_cache = state._UNRESOLVED
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _fake_run(stdout: str):
|
|
27
|
+
def run(_cmd, **_kwargs):
|
|
28
|
+
return subprocess.CompletedProcess(args=_cmd, returncode=0, stdout=stdout, stderr="")
|
|
29
|
+
|
|
30
|
+
return run
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_reports_the_computer_name_on_macos(monkeypatch):
|
|
34
|
+
monkeypatch.setattr(state.platform, "system", lambda: "Darwin")
|
|
35
|
+
monkeypatch.setattr(state.subprocess, "run", _fake_run("Jonny's MacBook Pro\n"))
|
|
36
|
+
|
|
37
|
+
assert state._macos_computer_name() == "Jonny's MacBook Pro"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_absent_off_macos(monkeypatch):
|
|
41
|
+
monkeypatch.setattr(state.platform, "system", lambda: "Linux")
|
|
42
|
+
|
|
43
|
+
def explode(*_a, **_k): # pragma: no cover - must never be reached
|
|
44
|
+
raise AssertionError("scutil is macOS-only and must not be spawned elsewhere")
|
|
45
|
+
|
|
46
|
+
monkeypatch.setattr(state.subprocess, "run", explode)
|
|
47
|
+
assert state._macos_computer_name() is None
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@pytest.mark.parametrize("stdout", ["", " \n"])
|
|
51
|
+
def test_blank_output_is_no_name(monkeypatch, stdout):
|
|
52
|
+
monkeypatch.setattr(state.platform, "system", lambda: "Darwin")
|
|
53
|
+
monkeypatch.setattr(state.subprocess, "run", _fake_run(stdout))
|
|
54
|
+
|
|
55
|
+
assert state._macos_computer_name() is None
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_failure_is_swallowed_and_never_retried(monkeypatch):
|
|
59
|
+
"""A nicer label is never worth a startup failure — nor a stall on every request.
|
|
60
|
+
|
|
61
|
+
get_system_info runs inside async handlers, so an uncached spawn blocks the
|
|
62
|
+
event loop for the full timeout. On a Mac with no ComputerName that would be
|
|
63
|
+
a permanent per-request stall, so a miss is cached exactly like a hit and the
|
|
64
|
+
node falls back to the hostname for the rest of its life.
|
|
65
|
+
"""
|
|
66
|
+
monkeypatch.setattr(state.platform, "system", lambda: "Darwin")
|
|
67
|
+
calls = {"n": 0}
|
|
68
|
+
|
|
69
|
+
def always_times_out(_cmd, **_kwargs):
|
|
70
|
+
calls["n"] += 1
|
|
71
|
+
raise subprocess.TimeoutExpired(cmd=_cmd, timeout=2.0)
|
|
72
|
+
|
|
73
|
+
monkeypatch.setattr(state.subprocess, "run", always_times_out)
|
|
74
|
+
|
|
75
|
+
assert state._macos_computer_name() is None
|
|
76
|
+
assert state._macos_computer_name() is None
|
|
77
|
+
assert state._macos_computer_name() is None
|
|
78
|
+
assert calls["n"] == 1
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def test_non_macos_never_spawns_twice(monkeypatch):
|
|
82
|
+
monkeypatch.setattr(state.platform, "system", lambda: "Linux")
|
|
83
|
+
assert state._macos_computer_name() is None
|
|
84
|
+
# Cached, so a Linux node does not re-check platform on every request either.
|
|
85
|
+
assert state._computer_name_cache is None
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_spawns_once_per_process(monkeypatch):
|
|
89
|
+
"""get_device_info calls get_system_info twice, and the CP hits it on every connect."""
|
|
90
|
+
monkeypatch.setattr(state.platform, "system", lambda: "Darwin")
|
|
91
|
+
calls = {"n": 0}
|
|
92
|
+
|
|
93
|
+
def counting(_cmd, **_kwargs):
|
|
94
|
+
calls["n"] += 1
|
|
95
|
+
return subprocess.CompletedProcess(args=_cmd, returncode=0, stdout="q4\n", stderr="")
|
|
96
|
+
|
|
97
|
+
monkeypatch.setattr(state.subprocess, "run", counting)
|
|
98
|
+
|
|
99
|
+
for _ in range(5):
|
|
100
|
+
state._macos_computer_name()
|
|
101
|
+
|
|
102
|
+
assert calls["n"] == 1
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def test_system_info_carries_computer_name_beside_hostname(monkeypatch):
|
|
106
|
+
"""The dict is free-form and the control plane forwards it verbatim, so this
|
|
107
|
+
key is the entire wire contract — it lands as system_info.computer_name."""
|
|
108
|
+
monkeypatch.setattr(state, "_macos_computer_name", lambda: "Jonny's MacBook Pro")
|
|
109
|
+
|
|
110
|
+
info = state.get_system_info()
|
|
111
|
+
|
|
112
|
+
assert info["computer_name"] == "Jonny's MacBook Pro"
|
|
113
|
+
assert "hostname" in info
|
|
@@ -415,9 +415,9 @@ def _delete_enrichment_data_core(source_id: str, job_name: str) -> Dict[str, Any
|
|
|
415
415
|
]
|
|
416
416
|
cur = conn.execute(f"DELETE FROM signal_embeddings WHERE {where}", params)
|
|
417
417
|
try:
|
|
418
|
-
from ..storage.adapters.sqlite.
|
|
418
|
+
from ..storage.adapters.sqlite.stores import SQLiteVectorIndex
|
|
419
419
|
|
|
420
|
-
|
|
420
|
+
SQLiteVectorIndex(conn).delete_embeddings(ids)
|
|
421
421
|
except Exception as exc:
|
|
422
422
|
logger.warning("Vector companion cleanup failed: %s", exc)
|
|
423
423
|
else:
|
|
@@ -21,13 +21,27 @@ async def report_progress() -> dict:
|
|
|
21
21
|
|
|
22
22
|
@router.post("/ingestion/reprocess", dependencies=[Depends(require_api_key)])
|
|
23
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
|
+
"""
|
|
24
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
|
|
25
37
|
return await reprocess_source(
|
|
26
38
|
source_id=str(payload["source_id"]),
|
|
27
39
|
dataset_id=str(payload["dataset_id"]),
|
|
28
40
|
from_stage=payload.get("from_stage") or "raw",
|
|
29
41
|
sync_batch_id=payload.get("sync_batch_id"),
|
|
30
42
|
force=bool(payload.get("force", False)),
|
|
43
|
+
limit=limit,
|
|
44
|
+
run_enrichment=bool(payload.get("run_enrichment", True)),
|
|
31
45
|
)
|
|
32
46
|
except KeyError as exc:
|
|
33
47
|
raise HTTPException(status_code=400, detail=f"Missing field: {exc}") from exc
|
|
@@ -44,6 +44,8 @@ def _client_is_local(request: Request) -> bool:
|
|
|
44
44
|
|
|
45
45
|
@router.get("/status")
|
|
46
46
|
async def shell_status() -> dict:
|
|
47
|
+
from ..sanitization.prewarm import prewarm_status
|
|
48
|
+
|
|
47
49
|
info = get_update_info()
|
|
48
50
|
log_file = get_log_file_path()
|
|
49
51
|
return {
|
|
@@ -59,6 +61,11 @@ async def shell_status() -> dict:
|
|
|
59
61
|
"applying": _apply_state["applying"],
|
|
60
62
|
"last_result": _apply_state["last_result"],
|
|
61
63
|
},
|
|
64
|
+
# Additive: existing shells decode a fixed set of keys and ignore this.
|
|
65
|
+
# The tray cannot show it until the Swift ShellStatus struct adds the
|
|
66
|
+
# field (its CodingKeys are explicit), which needs its own signed build —
|
|
67
|
+
# shipping the data first means that release is a display change only.
|
|
68
|
+
"models": prewarm_status(),
|
|
62
69
|
}
|
|
63
70
|
|
|
64
71
|
|