topos-node 1.2.4__tar.gz → 1.2.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.
Files changed (542) hide show
  1. {topos_node-1.2.4/topos_node.egg-info → topos_node-1.2.6}/PKG-INFO +71 -1
  2. {topos_node-1.2.4 → topos_node-1.2.6}/README.md +70 -0
  3. {topos_node-1.2.4 → topos_node-1.2.6}/pyproject.toml +1 -1
  4. topos_node-1.2.6/tests/test_extensions.py +32 -0
  5. {topos_node-1.2.4 → topos_node-1.2.6}/topos/__version__.py +2 -2
  6. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/llm.py +15 -0
  7. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/signal.py +15 -4
  8. topos_node-1.2.6/topos/api/tool_index.py +91 -0
  9. {topos_node-1.2.4 → topos_node-1.2.6}/topos/app.py +23 -0
  10. {topos_node-1.2.4 → topos_node-1.2.6}/topos/canonicalization/mappers/__init__.py +6 -0
  11. topos_node-1.2.6/topos/canonicalization/mappers/documents_mapper.py +43 -0
  12. {topos_node-1.2.4 → topos_node-1.2.6}/topos/canonicalization/mappers/github_activity_mapper.py +21 -0
  13. topos_node-1.2.6/topos/canonicalization/mappers/google_calendar_mapper.py +278 -0
  14. {topos_node-1.2.4 → topos_node-1.2.6}/topos/cli/commands.py +3 -0
  15. {topos_node-1.2.4 → topos_node-1.2.6}/topos/config/settings.py +1 -0
  16. {topos_node-1.2.4 → topos_node-1.2.6}/topos/control_plane_client.py +10 -0
  17. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/handlers/__init__.py +12 -0
  18. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/handlers/common.py +9 -1
  19. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/handlers/home_chat.py +3 -2
  20. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/handlers/query.py +12 -3
  21. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/handlers/routines.py +27 -10
  22. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/handlers/signal_features.py +10 -5
  23. topos_node-1.2.6/topos/core/handlers/tool_index.py +105 -0
  24. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/state.py +10 -0
  25. {topos_node-1.2.4 → topos_node-1.2.6}/topos/data_explorer_tables.py +1 -0
  26. {topos_node-1.2.4 → topos_node-1.2.6}/topos/disclosure/field_registry.py +3 -0
  27. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/backends/huggingface.py +13 -1
  28. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/backends/ollama.py +2 -1
  29. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/derived_tables.py +13 -14
  30. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/job_writer.py +43 -1
  31. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/_batch_limits.py +1 -1
  32. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/availability_scores_job.py +27 -2
  33. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/entities_job.py +103 -17
  34. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/fact_extraction_job.py +21 -2
  35. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/models/mvp_defaults.py +5 -1
  36. topos_node-1.2.6/topos/extensions.py +41 -0
  37. topos_node-1.2.6/topos/features/entities/declared_mappings.py +156 -0
  38. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/entities/edges.py +60 -8
  39. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/entities/fact_materializer.py +87 -2
  40. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/entities/graph_enrichers.py +6 -27
  41. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/entities/graph_refresh.py +21 -14
  42. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/entities/reads.py +6 -2
  43. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/entities/resolver.py +23 -2
  44. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/facts/llm_extract.py +296 -90
  45. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/lifecycle/derived_scrub.py +17 -2
  46. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/brief_canonical_loader.py +2 -1
  47. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/structured_signal.py +2 -0
  48. topos_node-1.2.6/topos/features/signal/tool_index.py +388 -0
  49. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/topic_clustering.py +51 -40
  50. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/canonical_pipeline.py +11 -2
  51. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/ingest_helpers.py +11 -2
  52. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/manager.py +7 -2
  53. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/parsers/__init__.py +8 -0
  54. topos_node-1.2.6/topos/ingestion/parsers/documents_parser.py +77 -0
  55. topos_node-1.2.6/topos/ingestion/parsers/google_calendar_parser.py +52 -0
  56. {topos_node-1.2.4 → topos_node-1.2.6}/topos/llm_integrations_storage.py +48 -45
  57. topos_node-1.2.6/topos/pipeline/job_store.py +310 -0
  58. {topos_node-1.2.4 → topos_node-1.2.6}/topos/protocol/handled_message_types.json +3 -0
  59. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/retrieval.py +5 -8
  60. topos_node-1.2.6/topos/runtime_shutdown.py +86 -0
  61. {topos_node-1.2.4 → topos_node-1.2.6}/topos/sanitization/nsfw_classifier.py +12 -0
  62. topos_node-1.2.6/topos/sanitization/prewarm.py +32 -0
  63. {topos_node-1.2.4 → topos_node-1.2.6}/topos/sanitization/privacy_filter.py +10 -0
  64. {topos_node-1.2.4 → topos_node-1.2.6}/topos/scope_resolution.py +2 -0
  65. {topos_node-1.2.4 → topos_node-1.2.6}/topos/sources/bundled_canonical_triples.py +4 -0
  66. {topos_node-1.2.4 → topos_node-1.2.6}/topos/sources/registry.py +104 -0
  67. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/adapters/factory.py +19 -2
  68. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/adapters/sqlite/stores.py +18 -15
  69. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/canonical/canonical_store.py +104 -6
  70. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/connection_tuning.py +1 -1
  71. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/__init__.py +17 -0
  72. topos_node-1.2.6/topos/storage/db/migrations/calendar_events_scheduling_v1.py +101 -0
  73. topos_node-1.2.6/topos/storage/db/migrations/documents_v1.py +58 -0
  74. topos_node-1.2.6/topos/storage/db/write_gate.py +110 -0
  75. {topos_node-1.2.4 → topos_node-1.2.6/topos_node.egg-info}/PKG-INFO +71 -1
  76. {topos_node-1.2.4 → topos_node-1.2.6}/topos_node.egg-info/SOURCES.txt +15 -0
  77. topos_node-1.2.4/topos/pipeline/job_store.py +0 -279
  78. {topos_node-1.2.4 → topos_node-1.2.6}/LICENSE +0 -0
  79. {topos_node-1.2.4 → topos_node-1.2.6}/MANIFEST.in +0 -0
  80. {topos_node-1.2.4 → topos_node-1.2.6}/setup.cfg +0 -0
  81. {topos_node-1.2.4 → topos_node-1.2.6}/shared/__init__.py +0 -0
  82. {topos_node-1.2.4 → topos_node-1.2.6}/shared/filtering.py +0 -0
  83. {topos_node-1.2.4 → topos_node-1.2.6}/shared/schema_registry.py +0 -0
  84. {topos_node-1.2.4 → topos_node-1.2.6}/tests/test_llm_integrations_storage.py +0 -0
  85. {topos_node-1.2.4 → topos_node-1.2.6}/tests/test_protocol_handled_types.py +0 -0
  86. {topos_node-1.2.4 → topos_node-1.2.6}/topos/__init__.py +0 -0
  87. {topos_node-1.2.4 → topos_node-1.2.6}/topos/analytics/__init__.py +0 -0
  88. {topos_node-1.2.4 → topos_node-1.2.6}/topos/analytics/duckdb_adapter.py +0 -0
  89. {topos_node-1.2.4 → topos_node-1.2.6}/topos/analytics/messenger_communities.py +0 -0
  90. {topos_node-1.2.4 → topos_node-1.2.6}/topos/analytics/messenger_graph.py +0 -0
  91. {topos_node-1.2.4 → topos_node-1.2.6}/topos/analytics/messenger_labels.py +0 -0
  92. {topos_node-1.2.4 → topos_node-1.2.6}/topos/analytics/profiles.py +0 -0
  93. {topos_node-1.2.4 → topos_node-1.2.6}/topos/analytics/query_engine.py +0 -0
  94. {topos_node-1.2.4 → topos_node-1.2.6}/topos/analytics/raw_queries.py +0 -0
  95. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/__init__.py +0 -0
  96. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/analytics.py +0 -0
  97. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/app_registry.py +0 -0
  98. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/backup.py +0 -0
  99. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/compute_remote.py +0 -0
  100. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/data_commit.py +0 -0
  101. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/data_explorer_table_prefs.py +0 -0
  102. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/database_explorer.py +0 -0
  103. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/db.py +0 -0
  104. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/device.py +0 -0
  105. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/engine_run.py +0 -0
  106. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/enrichment.py +0 -0
  107. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/enrichment_lab.py +0 -0
  108. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/filter_lab.py +0 -0
  109. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/health.py +0 -0
  110. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/home_chat.py +0 -0
  111. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/ingestion_api.py +0 -0
  112. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/ingestion_compat.py +0 -0
  113. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/ingestion_sources.py +0 -0
  114. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/intelligence_lifecycle.py +0 -0
  115. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/local_mcp.py +0 -0
  116. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/messenger_analytics.py +0 -0
  117. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/privacy_disclose.py +0 -0
  118. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/query_api.py +0 -0
  119. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/runtime_bootstrap.py +0 -0
  120. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/sanitization_ollama_config.py +0 -0
  121. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/signal_extraction_config.py +0 -0
  122. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/source_install.py +0 -0
  123. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/source_scrub.py +0 -0
  124. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/sources.py +0 -0
  125. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/sources_overview.py +0 -0
  126. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/sync.py +0 -0
  127. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/ui_config.py +0 -0
  128. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/uma_data.py +0 -0
  129. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/upgrades.py +0 -0
  130. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/usage.py +0 -0
  131. {topos_node-1.2.4 → topos_node-1.2.6}/topos/api/user_identity.py +0 -0
  132. {topos_node-1.2.4 → topos_node-1.2.6}/topos/auth.py +0 -0
  133. {topos_node-1.2.4 → topos_node-1.2.6}/topos/canonicalization/__init__.py +0 -0
  134. {topos_node-1.2.4 → topos_node-1.2.6}/topos/canonicalization/mappers/base.py +0 -0
  135. {topos_node-1.2.4 → topos_node-1.2.6}/topos/canonicalization/mappers/browser_activity_mapper.py +0 -0
  136. {topos_node-1.2.4 → topos_node-1.2.6}/topos/canonicalization/mappers/chatgpt_mapper.py +0 -0
  137. {topos_node-1.2.4 → topos_node-1.2.6}/topos/canonicalization/mappers/demo_mappers.py +0 -0
  138. {topos_node-1.2.4 → topos_node-1.2.6}/topos/canonicalization/mappers/grok_mapper.py +0 -0
  139. {topos_node-1.2.4 → topos_node-1.2.6}/topos/canonicalization/mappers/messenger_mapper.py +0 -0
  140. {topos_node-1.2.4 → topos_node-1.2.6}/topos/canonicalization/models.py +0 -0
  141. {topos_node-1.2.4 → topos_node-1.2.6}/topos/canonicalization/resolver.py +0 -0
  142. {topos_node-1.2.4 → topos_node-1.2.6}/topos/cli/__init__.py +0 -0
  143. {topos_node-1.2.4 → topos_node-1.2.6}/topos/cli/__main__.py +0 -0
  144. {topos_node-1.2.4 → topos_node-1.2.6}/topos/config/__init__.py +0 -0
  145. {topos_node-1.2.4 → topos_node-1.2.6}/topos/config/sanitization_ollama.py +0 -0
  146. {topos_node-1.2.4 → topos_node-1.2.6}/topos/config/signal_extraction.py +0 -0
  147. {topos_node-1.2.4 → topos_node-1.2.6}/topos/config/uvicorn_logging.json +0 -0
  148. {topos_node-1.2.4 → topos_node-1.2.6}/topos/contacts/__init__.py +0 -0
  149. {topos_node-1.2.4 → topos_node-1.2.6}/topos/contacts/identity.py +0 -0
  150. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/__init__.py +0 -0
  151. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/api_models.py +0 -0
  152. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/connection_resilience.py +0 -0
  153. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/device_helpers.py +0 -0
  154. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/errors.py +0 -0
  155. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/events.py +0 -0
  156. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/handlers/config.py +0 -0
  157. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/handlers/contacts_import.py +0 -0
  158. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/handlers/database_explorer.py +0 -0
  159. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/handlers/device.py +0 -0
  160. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/handlers/enrichment.py +0 -0
  161. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/handlers/enrichment_lab.py +0 -0
  162. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/handlers/filter_lab.py +0 -0
  163. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/handlers/ingest.py +0 -0
  164. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/handlers/messages.py +0 -0
  165. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/handlers/messenger_analytics.py +0 -0
  166. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/handlers/registry.py +0 -0
  167. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/handlers/sources.py +0 -0
  168. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/handlers/uma.py +0 -0
  169. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/logging.py +0 -0
  170. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/metrics.py +0 -0
  171. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/routine_access.py +0 -0
  172. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/startup_banner.py +0 -0
  173. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/table_layers.py +0 -0
  174. {topos_node-1.2.4 → topos_node-1.2.6}/topos/core/types.py +0 -0
  175. {topos_node-1.2.4 → topos_node-1.2.6}/topos/data_explorer_row_delete.py +0 -0
  176. {topos_node-1.2.4 → topos_node-1.2.6}/topos/data_explorer_table_prefs.py +0 -0
  177. {topos_node-1.2.4 → topos_node-1.2.6}/topos/disclosure/__init__.py +0 -0
  178. {topos_node-1.2.4 → topos_node-1.2.6}/topos/disclosure/canonical_writer.py +0 -0
  179. {topos_node-1.2.4 → topos_node-1.2.6}/topos/disclosure/content_policy.py +0 -0
  180. {topos_node-1.2.4 → topos_node-1.2.6}/topos/disclosure/privacy_layer.py +0 -0
  181. {topos_node-1.2.4 → topos_node-1.2.6}/topos/disclosure/tier.py +0 -0
  182. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/__init__.py +0 -0
  183. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/backends/__init__.py +0 -0
  184. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/backends/base.py +0 -0
  185. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/backends/generative_prompts.py +0 -0
  186. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/backends/generative_response.py +0 -0
  187. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/backends/openai.py +0 -0
  188. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/backends/openai_compatible.py +0 -0
  189. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/backends/redpill.py +0 -0
  190. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/backends/stub.py +0 -0
  191. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/client.py +0 -0
  192. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/engine.py +0 -0
  193. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/intake.py +0 -0
  194. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/memory_utils.py +0 -0
  195. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/model_cache.py +0 -0
  196. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/pipeline_memory.py +0 -0
  197. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/queue_manager.py +0 -0
  198. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/registration.py +0 -0
  199. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/result_formatter.py +0 -0
  200. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/router.py +0 -0
  201. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/scoped_token.py +0 -0
  202. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/tasks.py +0 -0
  203. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/transport.py +0 -0
  204. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/usage_guard.py +0 -0
  205. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/usage_observation.py +0 -0
  206. {topos_node-1.2.4 → topos_node-1.2.6}/topos/engine/validator.py +0 -0
  207. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/__init__.py +0 -0
  208. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/catalog.py +0 -0
  209. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/__init__.py +0 -0
  210. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/base.py +0 -0
  211. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/__init__.py +0 -0
  212. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/_engine_runner.py +0 -0
  213. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/brief_fallback.py +0 -0
  214. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/dimension_summary_job.py +0 -0
  215. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/embeddings_job.py +0 -0
  216. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/emo_27_job.py +0 -0
  217. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/goal_extraction_job.py +0 -0
  218. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/pii_redaction_job.py +0 -0
  219. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/relationship_edges_job.py +0 -0
  220. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/sentiment_job.py +0 -0
  221. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/statistics_job.py +0 -0
  222. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/timeline_job.py +0 -0
  223. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/topic_clusters_job.py +0 -0
  224. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/topics_job.py +0 -0
  225. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/url_classification_core.py +0 -0
  226. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/url_classification_enrichment_job.py +0 -0
  227. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/canonical/url_classification_signal_job.py +0 -0
  228. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/raw/__init__.py +0 -0
  229. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/raw/attachments_job.py +0 -0
  230. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/raw/language_job.py +0 -0
  231. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/raw/time_normalization_job.py +0 -0
  232. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/jobs/raw/tool_calls_job.py +0 -0
  233. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/model_overrides.py +0 -0
  234. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/models/__init__.py +0 -0
  235. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/models/manager.py +0 -0
  236. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/models/registry.py +0 -0
  237. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/models/versioning.py +0 -0
  238. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/orchestrator.py +0 -0
  239. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/processor.py +0 -0
  240. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/progress_bar.py +0 -0
  241. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/registry_contract.py +0 -0
  242. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/signal_derivation_config.json +0 -0
  243. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/source_overrides.py +0 -0
  244. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment/website_classifier.py +0 -0
  245. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment_lab/__init__.py +0 -0
  246. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment_lab/bundles.py +0 -0
  247. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment_lab/model_resolve.py +0 -0
  248. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment_lab/schema.py +0 -0
  249. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment_lab/service.py +0 -0
  250. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment_lab/store.py +0 -0
  251. {topos_node-1.2.4 → topos_node-1.2.6}/topos/enrichment_lab/worker.py +0 -0
  252. {topos_node-1.2.4 → topos_node-1.2.6}/topos/evals/__init__.py +0 -0
  253. {topos_node-1.2.4 → topos_node-1.2.6}/topos/evals/enrichment_eval.py +0 -0
  254. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/entities/__init__.py +0 -0
  255. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/entities/consolidation.py +0 -0
  256. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/entities/dossier.py +0 -0
  257. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/entities/graph_search.py +0 -0
  258. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/entities/linking.py +0 -0
  259. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/entities/maintenance.py +0 -0
  260. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/facts/__init__.py +0 -0
  261. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/facts/extract.py +0 -0
  262. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/facts/reads.py +0 -0
  263. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/facts/store.py +0 -0
  264. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/fit/evaluator.py +0 -0
  265. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/fit/opportunity_types.json +0 -0
  266. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/lifecycle/__init__.py +0 -0
  267. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/lifecycle/exclusions.py +0 -0
  268. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/lifecycle/gc.py +0 -0
  269. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/provenance/__init__.py +0 -0
  270. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/provenance/posture.py +0 -0
  271. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/provenance/roles.py +0 -0
  272. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/__init__.py +0 -0
  273. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/brief_ontology.py +0 -0
  274. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/brief_renderer.py +0 -0
  275. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/brief_schemas.py +0 -0
  276. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/chunking.py +0 -0
  277. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/cluster_labels.py +0 -0
  278. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/data_health.py +0 -0
  279. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/definitions/brief_ontologies.json +0 -0
  280. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/definitions/intentions.json +0 -0
  281. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/definitions/profile.json +0 -0
  282. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/definitions/relationships.json +0 -0
  283. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/definitions/schema/dimension_definition.schema.json +0 -0
  284. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/definitions/time.json +0 -0
  285. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/definitions/work.json +0 -0
  286. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/dimension_briefs.py +0 -0
  287. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/dimension_definition_loader.py +0 -0
  288. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/dimension_profiles.py +0 -0
  289. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/dimension_registry.py +0 -0
  290. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/embed_context.py +0 -0
  291. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/extraction/artifact_router.py +0 -0
  292. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/extraction/artifact_store.py +0 -0
  293. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/extraction/rule_extractors.py +0 -0
  294. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/graph_sanitize.py +0 -0
  295. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/hybrid_search.py +0 -0
  296. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/incremental_clustering.py +0 -0
  297. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/model_recommendations.py +0 -0
  298. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/query_embed_cache.py +0 -0
  299. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/schemas.py +0 -0
  300. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/service.py +0 -0
  301. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/signal_object_store.py +0 -0
  302. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/source_hydration.py +0 -0
  303. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/typed_stores/aggregates.py +0 -0
  304. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/typed_stores/scope_materializer.py +0 -0
  305. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/vector_codec.py +0 -0
  306. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/vector_math.py +0 -0
  307. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/signal/vector_settings.py +0 -0
  308. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/stats/__init__.py +0 -0
  309. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/stats/definitions.py +0 -0
  310. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/stats/engine.py +0 -0
  311. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/stats/fold.py +0 -0
  312. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/stats/insights.py +0 -0
  313. {topos_node-1.2.4 → topos_node-1.2.6}/topos/features/timeline_projection.py +0 -0
  314. {topos_node-1.2.4 → topos_node-1.2.6}/topos/filter_lab/__init__.py +0 -0
  315. {topos_node-1.2.4 → topos_node-1.2.6}/topos/filter_lab/bundles.py +0 -0
  316. {topos_node-1.2.4 → topos_node-1.2.6}/topos/filter_lab/schema.py +0 -0
  317. {topos_node-1.2.4 → topos_node-1.2.6}/topos/filter_lab/service.py +0 -0
  318. {topos_node-1.2.4 → topos_node-1.2.6}/topos/filter_lab/store.py +0 -0
  319. {topos_node-1.2.4 → topos_node-1.2.6}/topos/filter_lab/worker.py +0 -0
  320. {topos_node-1.2.4 → topos_node-1.2.6}/topos/home_chat/__init__.py +0 -0
  321. {topos_node-1.2.4 → topos_node-1.2.6}/topos/home_chat/schema.py +0 -0
  322. {topos_node-1.2.4 → topos_node-1.2.6}/topos/home_chat/store.py +0 -0
  323. {topos_node-1.2.4 → topos_node-1.2.6}/topos/hosted_pool_lease.py +0 -0
  324. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/__init__.py +0 -0
  325. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/checkpoints/__init__.py +0 -0
  326. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/checkpoints/checkpoint_store.py +0 -0
  327. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/checkpoints/sqlite_checkpoint_store.py +0 -0
  328. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/inbox_crypto.py +0 -0
  329. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/inbox_drain.py +0 -0
  330. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/jobs.py +0 -0
  331. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/journal_location_fanout.py +0 -0
  332. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/journal_time_log_normalize.py +0 -0
  333. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/local_sync.py +0 -0
  334. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/log_preview.py +0 -0
  335. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/parser.py +0 -0
  336. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/parsers/base.py +0 -0
  337. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/parsers/browser_parser.py +0 -0
  338. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/parsers/calendar_parser.py +0 -0
  339. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/parsers/chatgpt_conversation_flattener.py +0 -0
  340. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/parsers/chatgpt_parser.py +0 -0
  341. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/parsers/demo_file_parsers.py +0 -0
  342. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/parsers/github_activity_parser.py +0 -0
  343. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/parsers/grok_parser.py +0 -0
  344. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/parsers/messenger_parser.py +0 -0
  345. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/parsers/voxterm_parser.py +0 -0
  346. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/progress.py +0 -0
  347. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/reprocess.py +0 -0
  348. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/sources/__init__.py +0 -0
  349. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/sources/base.py +0 -0
  350. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/sources/calendar.py +0 -0
  351. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/sources/chatgpt.py +0 -0
  352. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/sources/contact_importers.py +0 -0
  353. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/sources/grok.py +0 -0
  354. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/sources/imessage_reader.py +0 -0
  355. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/sources/signal_export_parser.py +0 -0
  356. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/sources/signal_reader.py +0 -0
  357. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/state_machine.py +0 -0
  358. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/triggers/__init__.py +0 -0
  359. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/triggers/file_trigger.py +0 -0
  360. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/triggers/sqlite_trigger.py +0 -0
  361. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/usage_inbox_dedupe.py +0 -0
  362. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/validation/__init__.py +0 -0
  363. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/validation/base.py +0 -0
  364. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/validation/schema_registry.py +0 -0
  365. {topos_node-1.2.4 → topos_node-1.2.6}/topos/ingestion/validation/schema_validator.py +0 -0
  366. {topos_node-1.2.4 → topos_node-1.2.6}/topos/lineage/__init__.py +0 -0
  367. {topos_node-1.2.4 → topos_node-1.2.6}/topos/lineage/provenance.py +0 -0
  368. {topos_node-1.2.4 → topos_node-1.2.6}/topos/lineage/tracker.py +0 -0
  369. {topos_node-1.2.4 → topos_node-1.2.6}/topos/mcp_stdio_proxy.py +0 -0
  370. {topos_node-1.2.4 → topos_node-1.2.6}/topos/observability/__init__.py +0 -0
  371. {topos_node-1.2.4 → topos_node-1.2.6}/topos/observability/alerts.py +0 -0
  372. {topos_node-1.2.4 → topos_node-1.2.6}/topos/observability/metrics.py +0 -0
  373. {topos_node-1.2.4 → topos_node-1.2.6}/topos/observability/tracing.py +0 -0
  374. {topos_node-1.2.4 → topos_node-1.2.6}/topos/openai_client.py +0 -0
  375. {topos_node-1.2.4 → topos_node-1.2.6}/topos/pipeline/__init__.py +0 -0
  376. {topos_node-1.2.4 → topos_node-1.2.6}/topos/pipeline/audit.py +0 -0
  377. {topos_node-1.2.4 → topos_node-1.2.6}/topos/pipeline/envelope.py +0 -0
  378. {topos_node-1.2.4 → topos_node-1.2.6}/topos/pipeline/job_runner.py +0 -0
  379. {topos_node-1.2.4 → topos_node-1.2.6}/topos/pipeline/stages.py +0 -0
  380. {topos_node-1.2.4 → topos_node-1.2.6}/topos/pipeline/stub_enqueue.py +0 -0
  381. {topos_node-1.2.4 → topos_node-1.2.6}/topos/projections/__init__.py +0 -0
  382. {topos_node-1.2.4 → topos_node-1.2.6}/topos/projections/vector_index/__init__.py +0 -0
  383. {topos_node-1.2.4 → topos_node-1.2.6}/topos/projections/vector_index/base.py +0 -0
  384. {topos_node-1.2.4 → topos_node-1.2.6}/topos/projections/vector_index/builders.py +0 -0
  385. {topos_node-1.2.4 → topos_node-1.2.6}/topos/projections/vector_index/health_checks.py +0 -0
  386. {topos_node-1.2.4 → topos_node-1.2.6}/topos/protocol/__init__.py +0 -0
  387. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/__init__.py +0 -0
  388. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/audit.py +0 -0
  389. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/ddr.py +0 -0
  390. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/disclosure.py +0 -0
  391. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/fingerprint.py +0 -0
  392. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/game_layer.py +0 -0
  393. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/grant_cache.py +0 -0
  394. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/inference.py +0 -0
  395. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/intent.py +0 -0
  396. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/manifest.py +0 -0
  397. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/manifest_validation.py +0 -0
  398. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/minimizer.py +0 -0
  399. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/negotiation.py +0 -0
  400. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/pipeline.py +0 -0
  401. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/planner.py +0 -0
  402. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/runtime.py +0 -0
  403. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/scope_registry.json +0 -0
  404. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/scope_registry_loader.py +0 -0
  405. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/session.py +0 -0
  406. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/session_utils.py +0 -0
  407. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/source_generation.py +0 -0
  408. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/turn_classifier.py +0 -0
  409. {topos_node-1.2.4 → topos_node-1.2.6}/topos/query/types.py +0 -0
  410. {topos_node-1.2.4 → topos_node-1.2.6}/topos/rate_limit.py +0 -0
  411. {topos_node-1.2.4 → topos_node-1.2.6}/topos/routines/__init__.py +0 -0
  412. {topos_node-1.2.4 → topos_node-1.2.6}/topos/routines/schema.py +0 -0
  413. {topos_node-1.2.4 → topos_node-1.2.6}/topos/routines/store.py +0 -0
  414. {topos_node-1.2.4 → topos_node-1.2.6}/topos/runtime_update.py +0 -0
  415. {topos_node-1.2.4 → topos_node-1.2.6}/topos/sanitization/__init__.py +0 -0
  416. {topos_node-1.2.4 → topos_node-1.2.6}/topos/sanitization/ollama_transforms.py +0 -0
  417. {topos_node-1.2.4 → topos_node-1.2.6}/topos/services/__init__.py +0 -0
  418. {topos_node-1.2.4 → topos_node-1.2.6}/topos/services/container.py +0 -0
  419. {topos_node-1.2.4 → topos_node-1.2.6}/topos/services/embeddings/__init__.py +0 -0
  420. {topos_node-1.2.4 → topos_node-1.2.6}/topos/services/embeddings/base.py +0 -0
  421. {topos_node-1.2.4 → topos_node-1.2.6}/topos/services/embeddings/local.py +0 -0
  422. {topos_node-1.2.4 → topos_node-1.2.6}/topos/services/embeddings/remote.py +0 -0
  423. {topos_node-1.2.4 → topos_node-1.2.6}/topos/services/interfaces.py +0 -0
  424. {topos_node-1.2.4 → topos_node-1.2.6}/topos/services/llm/__init__.py +0 -0
  425. {topos_node-1.2.4 → topos_node-1.2.6}/topos/services/llm/base.py +0 -0
  426. {topos_node-1.2.4 → topos_node-1.2.6}/topos/services/llm/openai.py +0 -0
  427. {topos_node-1.2.4 → topos_node-1.2.6}/topos/services/local.py +0 -0
  428. {topos_node-1.2.4 → topos_node-1.2.6}/topos/services/postgres.py +0 -0
  429. {topos_node-1.2.4 → topos_node-1.2.6}/topos/sources/__init__.py +0 -0
  430. {topos_node-1.2.4 → topos_node-1.2.6}/topos/sources/canonical_signal_defaults.py +0 -0
  431. {topos_node-1.2.4 → topos_node-1.2.6}/topos/sources/definitions.py +0 -0
  432. {topos_node-1.2.4 → topos_node-1.2.6}/topos/sources/install_service.py +0 -0
  433. {topos_node-1.2.4 → topos_node-1.2.6}/topos/sources/runtime_install.py +0 -0
  434. {topos_node-1.2.4 → topos_node-1.2.6}/topos/sources/scrub_attribution.py +0 -0
  435. {topos_node-1.2.4 → topos_node-1.2.6}/topos/sources/scrub_service.py +0 -0
  436. {topos_node-1.2.4 → topos_node-1.2.6}/topos/startup_banner.py +0 -0
  437. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/__init__.py +0 -0
  438. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/adapters/__init__.py +0 -0
  439. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/adapters/fakes.py +0 -0
  440. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/adapters/postgres/stores.py +0 -0
  441. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/adapters/protocols.py +0 -0
  442. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/adapters/sqlite/__init__.py +0 -0
  443. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/adapters/sqlite/vector_search.py +0 -0
  444. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/canonical/__init__.py +0 -0
  445. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/canonical/activity_tables.py +0 -0
  446. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/canonical/ai_chat/__init__.py +0 -0
  447. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/canonical/ai_chat/canonicalizer.py +0 -0
  448. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/canonical/ai_chat/mapper.py +0 -0
  449. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/canonical/ai_chat/model.py +0 -0
  450. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/canonical/ai_chat/tables.py +0 -0
  451. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/canonical/calendar_contacts_tables.py +0 -0
  452. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/canonical/conversations_tables.py +0 -0
  453. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/canonical/mapping_store.py +0 -0
  454. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/canonical/postgres.py +0 -0
  455. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/__init__.py +0 -0
  456. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/client.py +0 -0
  457. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/activity_events_content_v1.py +0 -0
  458. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/actor_role_v1.py +0 -0
  459. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/canonical_address_book_v1.py +0 -0
  460. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/canonical_disclosure_v1.py +0 -0
  461. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/canonical_nsfw_v1.py +0 -0
  462. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/derivation_ledger_v1.py +0 -0
  463. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/entity_edges_validity_v1.py +0 -0
  464. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/episodes_v1.py +0 -0
  465. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/extraction_artifacts.py +0 -0
  466. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/journal_entries_duration_v1.py +0 -0
  467. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/journal_entries_ends_at_v1.py +0 -0
  468. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/journal_entries_people_v1.py +0 -0
  469. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/journal_entries_place_name_v1.py +0 -0
  470. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/journal_entries_starts_at_v1.py +0 -0
  471. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/pipeline_jobs_v1.py +0 -0
  472. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/remediation_person_model.py +0 -0
  473. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/scope_source_generation.py +0 -0
  474. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/signal_dimension_backfill_v1.py +0 -0
  475. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/signal_dimension_harness.py +0 -0
  476. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/signal_objects.py +0 -0
  477. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/signal_objects_period_v1.py +0 -0
  478. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/signal_objects_updated_by_v1.py +0 -0
  479. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/stage9_column_renames.py +0 -0
  480. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/vector_storage_v1.py +0 -0
  481. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/vector_storage_v2.py +0 -0
  482. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/vector_storage_v3.py +0 -0
  483. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/vector_storage_v4.py +0 -0
  484. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/wiki_clusters_v2.py +0 -0
  485. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/wiki_entities_v1.py +0 -0
  486. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/wiki_entity_review_v2.py +0 -0
  487. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/wiki_facts_v1.py +0 -0
  488. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/wiki_lifecycle_v1.py +0 -0
  489. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/wiki_mvp_phase0.py +0 -0
  490. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/wiki_mvp_phase1.py +0 -0
  491. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/wiki_mvp_phase4_messages_cutover.py +0 -0
  492. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/wiki_mvp_phase5_topic_clusters.py +0 -0
  493. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/wiki_mvp_phase6_dimension_briefs.py +0 -0
  494. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/wiki_mvp_query_quality.py +0 -0
  495. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/wiki_mvp_topic_clusters_coordination.py +0 -0
  496. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/wiki_stats_v1.py +0 -0
  497. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/migrations/wiki_timeline_v1.py +0 -0
  498. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/paths.py +0 -0
  499. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/postgres.py +0 -0
  500. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/schema.py +0 -0
  501. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/db/storage_breakdown.py +0 -0
  502. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/enrichment/__init__.py +0 -0
  503. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/enrichment/canonical_enrichment_store.py +0 -0
  504. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/enrichment/raw_enrichment_store.py +0 -0
  505. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/normalized/__init__.py +0 -0
  506. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/normalized/normalized_store.py +0 -0
  507. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/oplog/__init__.py +0 -0
  508. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/oplog/decision.py +0 -0
  509. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/oplog/oplog_store.py +0 -0
  510. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/oplog/postgres.py +0 -0
  511. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/person/identity_resolver.py +0 -0
  512. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/projections/__init__.py +0 -0
  513. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/projections/index_ops_store.py +0 -0
  514. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/projections/vector_index_store.py +0 -0
  515. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/raw/__init__.py +0 -0
  516. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/raw/browser_flat_tables.py +0 -0
  517. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/raw/file_store.py +0 -0
  518. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/raw/raw_store.py +0 -0
  519. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/raw/raw_tables_manager.py +0 -0
  520. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/raw/sqlite_raw_store.py +0 -0
  521. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/security/encryption.py +0 -0
  522. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/signal_identity.py +0 -0
  523. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/source_settings.py +0 -0
  524. {topos_node-1.2.4 → topos_node-1.2.6}/topos/storage/user_identity.py +0 -0
  525. {topos_node-1.2.4 → topos_node-1.2.6}/topos/sync/__init__.py +0 -0
  526. {topos_node-1.2.4 → topos_node-1.2.6}/topos/sync/client.py +0 -0
  527. {topos_node-1.2.4 → topos_node-1.2.6}/topos/sync_handlers.py +0 -0
  528. {topos_node-1.2.4 → topos_node-1.2.6}/topos/testing/__init__.py +0 -0
  529. {topos_node-1.2.4 → topos_node-1.2.6}/topos/testing/lifespan.py +0 -0
  530. {topos_node-1.2.4 → topos_node-1.2.6}/topos/uma_contact_enrichment.py +0 -0
  531. {topos_node-1.2.4 → topos_node-1.2.6}/topos/uma_filters.py +0 -0
  532. {topos_node-1.2.4 → topos_node-1.2.6}/topos/uma_resource_id.py +0 -0
  533. {topos_node-1.2.4 → topos_node-1.2.6}/topos/uma_rpt.py +0 -0
  534. {topos_node-1.2.4 → topos_node-1.2.6}/topos/upgrades/__init__.py +0 -0
  535. {topos_node-1.2.4 → topos_node-1.2.6}/topos/upgrades/manifests.json +0 -0
  536. {topos_node-1.2.4 → topos_node-1.2.6}/topos/upgrades/runner.py +0 -0
  537. {topos_node-1.2.4 → topos_node-1.2.6}/topos/utils/base_object.py +0 -0
  538. {topos_node-1.2.4 → topos_node-1.2.6}/topos/websocket_client.py +0 -0
  539. {topos_node-1.2.4 → topos_node-1.2.6}/topos_node.egg-info/dependency_links.txt +0 -0
  540. {topos_node-1.2.4 → topos_node-1.2.6}/topos_node.egg-info/entry_points.txt +0 -0
  541. {topos_node-1.2.4 → topos_node-1.2.6}/topos_node.egg-info/requires.txt +0 -0
  542. {topos_node-1.2.4 → topos_node-1.2.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.2.4
3
+ Version: 1.2.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
@@ -213,6 +213,76 @@ pip install -e ".[dev,engine]"
213
213
  pytest tests -m "public and not e2e" -q
214
214
  ```
215
215
 
216
+ ## Plugins
217
+
218
+ Topos Node supports **optional plugins**: separate Python packages installed alongside
219
+ `topos-node` that register handlers, connectors, or other runtime hooks. The core node
220
+ does not hardcode plugin names — discovery is entirely via setuptools entry points.
221
+
222
+ ### Contract: `topos.extensions`
223
+
224
+ | Rule | Detail |
225
+ | --- | --- |
226
+ | **Entry-point group** | `topos.extensions` |
227
+ | **Entry-point target** | A callable, e.g. `my_plugin:register` |
228
+ | **When it runs** | At process startup, before the server accepts traffic (`topos/extensions.py`) |
229
+ | **Failure mode** | A broken plugin is logged and skipped; the node keeps running |
230
+ | **Dependencies** | Your plugin declares `topos-node` (or `topos-node[local]`) in its own `pyproject.toml` |
231
+
232
+ **Minimal plugin**
233
+
234
+ `pyproject.toml`:
235
+
236
+ ```toml
237
+ [project]
238
+ name = "my-topos-plugin"
239
+ dependencies = ["topos-node[local]"]
240
+
241
+ [project.entry-points."topos.extensions"]
242
+ my_plugin = "my_topos_plugin:register"
243
+ ```
244
+
245
+ `my_topos_plugin/__init__.py`:
246
+
247
+ ```python
248
+ def register() -> None:
249
+ from my_topos_plugin.handlers import example # noqa: F401 — registers @handles
250
+ ```
251
+
252
+ `my_topos_plugin/handlers/example.py`:
253
+
254
+ ```python
255
+ from typing import Any, Dict, Optional
256
+ from topos.core.handlers.registry import handles
257
+
258
+ @handles("my_message_type")
259
+ async def handle_my_message(message: Dict[str, Any]) -> Optional[Dict[str, Any]]:
260
+ return {"status": "ok", "payload": {"received": message.get("type")}}
261
+ ```
262
+
263
+ **Install and run**
264
+
265
+ ```bash
266
+ pip install topos-node my-topos-plugin
267
+ topos-node
268
+ ```
269
+
270
+ Handlers registered in `register()` are available to the control-plane WebSocket
271
+ and local API paths that dispatch through `topos.core.handlers`.
272
+
273
+ ### Starter template
274
+
275
+ Fork **[dialoguesai/topos-plugin-template](https://github.com/dialoguesai/topos-plugin-template)**
276
+ for a working package with tests and CI. It registers a sample `plugin_template_ping`
277
+ handler you can copy and rename.
278
+
279
+ ### Guidelines
280
+
281
+ - Use **unique message type names** (prefix with your project) to avoid colliding with core handlers.
282
+ - Keep plugins in **separate repositories** — do not add proprietary logic to this repo.
283
+ - Message types your plugin handles do not need to appear in the public engine protocol
284
+ snapshot unless the hosted control plane will send them to all nodes.
285
+
216
286
  ## Contributing
217
287
 
218
288
  See `CONTRIBUTING.md` for:
@@ -156,6 +156,76 @@ pip install -e ".[dev,engine]"
156
156
  pytest tests -m "public and not e2e" -q
157
157
  ```
158
158
 
159
+ ## Plugins
160
+
161
+ Topos Node supports **optional plugins**: separate Python packages installed alongside
162
+ `topos-node` that register handlers, connectors, or other runtime hooks. The core node
163
+ does not hardcode plugin names — discovery is entirely via setuptools entry points.
164
+
165
+ ### Contract: `topos.extensions`
166
+
167
+ | Rule | Detail |
168
+ | --- | --- |
169
+ | **Entry-point group** | `topos.extensions` |
170
+ | **Entry-point target** | A callable, e.g. `my_plugin:register` |
171
+ | **When it runs** | At process startup, before the server accepts traffic (`topos/extensions.py`) |
172
+ | **Failure mode** | A broken plugin is logged and skipped; the node keeps running |
173
+ | **Dependencies** | Your plugin declares `topos-node` (or `topos-node[local]`) in its own `pyproject.toml` |
174
+
175
+ **Minimal plugin**
176
+
177
+ `pyproject.toml`:
178
+
179
+ ```toml
180
+ [project]
181
+ name = "my-topos-plugin"
182
+ dependencies = ["topos-node[local]"]
183
+
184
+ [project.entry-points."topos.extensions"]
185
+ my_plugin = "my_topos_plugin:register"
186
+ ```
187
+
188
+ `my_topos_plugin/__init__.py`:
189
+
190
+ ```python
191
+ def register() -> None:
192
+ from my_topos_plugin.handlers import example # noqa: F401 — registers @handles
193
+ ```
194
+
195
+ `my_topos_plugin/handlers/example.py`:
196
+
197
+ ```python
198
+ from typing import Any, Dict, Optional
199
+ from topos.core.handlers.registry import handles
200
+
201
+ @handles("my_message_type")
202
+ async def handle_my_message(message: Dict[str, Any]) -> Optional[Dict[str, Any]]:
203
+ return {"status": "ok", "payload": {"received": message.get("type")}}
204
+ ```
205
+
206
+ **Install and run**
207
+
208
+ ```bash
209
+ pip install topos-node my-topos-plugin
210
+ topos-node
211
+ ```
212
+
213
+ Handlers registered in `register()` are available to the control-plane WebSocket
214
+ and local API paths that dispatch through `topos.core.handlers`.
215
+
216
+ ### Starter template
217
+
218
+ Fork **[dialoguesai/topos-plugin-template](https://github.com/dialoguesai/topos-plugin-template)**
219
+ for a working package with tests and CI. It registers a sample `plugin_template_ping`
220
+ handler you can copy and rename.
221
+
222
+ ### Guidelines
223
+
224
+ - Use **unique message type names** (prefix with your project) to avoid colliding with core handlers.
225
+ - Keep plugins in **separate repositories** — do not add proprietary logic to this repo.
226
+ - Message types your plugin handles do not need to appear in the public engine protocol
227
+ snapshot unless the hosted control plane will send them to all nodes.
228
+
159
229
  ## Contributing
160
230
 
161
231
  See `CONTRIBUTING.md` for:
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "topos-node"
7
- version = "1.2.4"
7
+ version = "1.2.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"
@@ -0,0 +1,32 @@
1
+ from __future__ import annotations
2
+
3
+ import pytest
4
+
5
+ from topos.core.handlers.registry import handles
6
+ from topos.extensions import load_extensions
7
+
8
+
9
+ @pytest.mark.public
10
+ def test_load_extensions_does_not_raise_when_no_plugins_installed() -> None:
11
+ load_extensions()
12
+
13
+
14
+ @pytest.mark.public
15
+ def test_load_extensions_invokes_entry_point_callables(monkeypatch: pytest.MonkeyPatch) -> None:
16
+ seen: list[str] = []
17
+
18
+ def _init() -> None:
19
+ seen.append("ran")
20
+
21
+ class _FakeEntryPoint:
22
+ name = "test"
23
+
24
+ def load(self) -> object:
25
+ return _init
26
+
27
+ monkeypatch.setattr(
28
+ "topos.extensions._iter_extension_entry_points",
29
+ lambda: [_FakeEntryPoint()],
30
+ )
31
+ load_extensions()
32
+ assert seen == ["ran"]
@@ -1,6 +1,6 @@
1
1
  """Topos Control Plane Version Information."""
2
2
 
3
- __version__ = "1.2.4"
4
- __version_info__ = (1, 2, 4)
3
+ __version__ = "1.2.6"
4
+ __version_info__ = (1, 2, 6)
5
5
 
6
6
  __all__ = ["__version__", "__version_info__"]
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import hashlib
4
+ import logging
4
5
 
5
6
  from fastapi import APIRouter, Depends
6
7
 
@@ -10,6 +11,8 @@ from ..engine.usage_observation import emit_usage_observation
10
11
  from ..rate_limit import rate_limit
11
12
  from ..services.container import Services, get_services
12
13
 
14
+ logger = logging.getLogger("topos.api.llm")
15
+
13
16
  router = APIRouter()
14
17
 
15
18
 
@@ -19,6 +22,12 @@ router = APIRouter()
19
22
  dependencies=[Depends(require_api_key), Depends(rate_limit)],
20
23
  )
21
24
  async def llm_generation(body: GenerationRequest):
25
+ logger.info(
26
+ "llm_generation request: provider=%r model=%r prompt_chars=%d",
27
+ body.provider,
28
+ body.model,
29
+ len(body.prompt or ""),
30
+ )
22
31
  services: Services = get_services()
23
32
  result = await services.llm.generate(body.model_dump())
24
33
  usage = result.get("usage") if isinstance(result, dict) else {}
@@ -45,6 +54,12 @@ async def llm_generation(body: GenerationRequest):
45
54
  dependencies=[Depends(require_api_key), Depends(rate_limit)],
46
55
  )
47
56
  async def llm_generation_alias(body: GenerationRequest):
57
+ logger.info(
58
+ "llm_generation request (alias): provider=%r model=%r prompt_chars=%d",
59
+ body.provider,
60
+ body.model,
61
+ len(body.prompt or ""),
62
+ )
48
63
  services: Services = get_services()
49
64
  result = await services.llm.generate(body.model_dump())
50
65
  usage = result.get("usage") if isinstance(result, dict) else {}
@@ -232,11 +232,13 @@ async def list_entities(
232
232
  # as an entity id.
233
233
  @router.get("/entities/graph")
234
234
  async def get_entity_graph(
235
- limit_nodes: int = Query(default=100, ge=1, le=500),
236
- limit_edges: int = Query(default=300, ge=1, le=1500),
235
+ limit_nodes: int = Query(default=100, ge=1, le=5000),
236
+ limit_edges: int = Query(default=300, ge=1, le=20000),
237
237
  min_weight: float = Query(default=0.0, ge=0.0),
238
238
  include_closed: bool = Query(default=False),
239
239
  as_of: Optional[str] = Query(default=None),
240
+ selection: str = Query(default="weight"),
241
+ offset: int = Query(default=0, ge=0),
240
242
  _api_key: str = Depends(require_api_key),
241
243
  ):
242
244
  """Entity-spine graph (decayed typed edges) in list_graph node/edge shape.
@@ -244,16 +246,25 @@ async def get_entity_graph(
244
246
  Each edge carries valid_from/valid_to/last_event_at. ``as_of`` (ISO date)
245
247
  returns the graph as it stood at that instant (temporal scrubber);
246
248
  ``include_closed`` adds ended edges to the present view.
249
+
250
+ ``selection=weight`` (default) ranks by weight for MCP/minimal slices;
251
+ ``selection=all`` ranks by recency for the owner knowledge-graph UI.
247
252
  """
253
+ import asyncio
254
+
248
255
  from ..features.entities.reads import entity_graph
249
256
 
250
- return entity_graph(
251
- _entities_conn(),
257
+ conn = _entities_conn()
258
+ return await asyncio.to_thread(
259
+ entity_graph,
260
+ conn,
252
261
  limit_nodes=limit_nodes,
253
262
  limit_edges=limit_edges,
254
263
  min_weight=min_weight,
255
264
  include_closed=include_closed,
256
265
  as_of=as_of,
266
+ selection=selection,
267
+ offset=offset,
257
268
  )
258
269
 
259
270
 
@@ -0,0 +1,91 @@
1
+ """Tool-RAG endpoints: sync the tool index, retrieve top-K tools for a query.
2
+
3
+ PLAN_AGENT_QUALITY WS-3 (M2). The chat orchestration (topos-react-app) pushes
4
+ the gateway's tool list here after ``tools/list`` (hash-deduped upsert → cheap
5
+ no-op when unchanged) and calls ``/v1/tools/retrieve`` per turn to build a
6
+ focused tool doc sized to the model instead of a flat 52-tool dump.
7
+
8
+ Handlers are sync ``def`` on purpose: the embedding path is blocking HF
9
+ inference, and FastAPI runs sync handlers in its threadpool.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from typing import List, Optional
15
+
16
+ from fastapi import APIRouter, Depends, HTTPException
17
+ from pydantic import BaseModel, Field
18
+
19
+ from ..auth import require_api_key
20
+ from ..core.state import get_db_connection
21
+ from ..features.signal.tool_index import index_status, index_tools, retrieve_tools
22
+ from ..rate_limit import rate_limit
23
+
24
+ router = APIRouter()
25
+
26
+
27
+ class ToolSpecIn(BaseModel):
28
+ name: str
29
+ description: str = ""
30
+ connector_id: Optional[str] = None
31
+
32
+
33
+ class IndexToolsRequest(BaseModel):
34
+ tools: List[ToolSpecIn] = Field(default_factory=list, max_length=2000)
35
+ # Prune index rows absent from this payload (full-list syncs only).
36
+ prune_missing: bool = False
37
+
38
+
39
+ class RetrieveToolsRequest(BaseModel):
40
+ query: str
41
+ connector_scope: Optional[str] = None
42
+ k: int = 8
43
+ # Per-connector identity-tool override (PLAN_HELP_NUDGE A2): bare names to
44
+ # ride along beyond IDENTITY_TOOL_NAMES, for connectors whose identity tool
45
+ # has a nonstandard name (e.g. GraphQL ``viewer``).
46
+ identity_tools: Optional[List[str]] = None
47
+
48
+
49
+ def _require_conn():
50
+ conn = get_db_connection()
51
+ if conn is None:
52
+ raise HTTPException(status_code=503, detail="Database unavailable")
53
+ return conn
54
+
55
+
56
+ @router.post(
57
+ "/v1/tools/index",
58
+ dependencies=[Depends(require_api_key), Depends(rate_limit)],
59
+ )
60
+ def tools_index(body: IndexToolsRequest):
61
+ conn = _require_conn()
62
+ specs = [spec.model_dump() for spec in body.tools if str(spec.name or "").strip()]
63
+ if not specs and not body.prune_missing:
64
+ raise HTTPException(status_code=422, detail="tools must be a non-empty list")
65
+ return index_tools(conn, specs, prune_missing=body.prune_missing)
66
+
67
+
68
+ @router.post(
69
+ "/v1/tools/retrieve",
70
+ dependencies=[Depends(require_api_key), Depends(rate_limit)],
71
+ )
72
+ def tools_retrieve(body: RetrieveToolsRequest):
73
+ if not str(body.query or "").strip():
74
+ raise HTTPException(status_code=422, detail="query is required")
75
+ conn = _require_conn()
76
+ return retrieve_tools(
77
+ conn,
78
+ body.query,
79
+ connector_scope=body.connector_scope,
80
+ k=body.k,
81
+ extra_identity_names=body.identity_tools or (),
82
+ )
83
+
84
+
85
+ @router.get(
86
+ "/v1/tools/index/status",
87
+ dependencies=[Depends(require_api_key), Depends(rate_limit)],
88
+ )
89
+ def tools_index_status():
90
+ conn = _require_conn()
91
+ return index_status(conn)
@@ -45,10 +45,12 @@ from .api import (
45
45
  home_chat as home_chat_routes,
46
46
  privacy_disclose as privacy_disclose_routes,
47
47
  signal as signal_routes,
48
+ tool_index as tool_index_routes,
48
49
  upgrades as upgrades_routes,
49
50
  )
50
51
  from .config.settings import settings
51
52
  from .core.logging import align_uvicorn_loggers, configure_logging
53
+ from .extensions import load_extensions
52
54
  from .core import state
53
55
  from .core.handlers import handle_control_plane_request
54
56
  from .control_plane_client import ControlPlaneClient
@@ -65,6 +67,7 @@ from .sync import SyncClient
65
67
  from .sync_handlers import handle_sync_op
66
68
 
67
69
  configure_logging()
70
+ load_extensions()
68
71
  logger = logging.getLogger("topos.app")
69
72
 
70
73
  app = FastAPI(
@@ -128,10 +131,15 @@ app.include_router(privacy_disclose_routes.router)
128
131
  app.include_router(compute_remote_routes.router)
129
132
  app.include_router(engine_run_routes.router)
130
133
  app.include_router(data_commit_routes.router)
134
+ app.include_router(tool_index_routes.router)
131
135
 
132
136
 
133
137
  @app.on_event("startup")
134
138
  async def startup_event() -> None:
139
+ from .runtime_shutdown import clear_shutdown, install_shutdown_signal_hooks
140
+
141
+ clear_shutdown()
142
+ install_shutdown_signal_hooks()
135
143
  align_uvicorn_loggers()
136
144
  _log_runtime_banner()
137
145
  logger.info("CORS allowed origins: %s", settings.allowed_origins)
@@ -199,6 +207,16 @@ async def startup_event() -> None:
199
207
  )
200
208
  except Exception as e:
201
209
  logger.warning("Active source install rehydration at startup failed (non-fatal): %s", e)
210
+ if getattr(settings, "sanitization_prewarm_on_startup", True):
211
+ async def _prewarm_sanitization() -> None:
212
+ try:
213
+ from .sanitization.prewarm import prewarm_sanitization_models
214
+
215
+ await asyncio.to_thread(prewarm_sanitization_models)
216
+ except Exception as prewarm_exc: # noqa: BLE001
217
+ logger.warning("Sanitization prewarm at startup failed (non-fatal): %s", prewarm_exc)
218
+
219
+ asyncio.create_task(_prewarm_sanitization())
202
220
  if settings.topos_control_plane_url:
203
221
  if settings.hosted_pool_lease_enabled:
204
222
  try:
@@ -296,6 +314,11 @@ async def startup_event() -> None:
296
314
 
297
315
  @app.on_event("shutdown")
298
316
  async def shutdown_event() -> None:
317
+ from .runtime_shutdown import request_shutdown
318
+
319
+ # Wake cooperative workers (fact_llm / Ollama threads) before awaiting
320
+ # network teardown so Ctrl+C does not wait out a full enrichment batch.
321
+ request_shutdown("app_shutdown")
299
322
  await stop_runtime_update_monitor()
300
323
  if state.engine_presence_task:
301
324
  state.engine_presence_task.cancel()
@@ -13,7 +13,9 @@ from .demo_mappers import (
13
13
  DemoPlacesMapper,
14
14
  DemoProfileMapper,
15
15
  )
16
+ from .documents_mapper import DocumentsCanonicalMapper
16
17
  from .github_activity_mapper import GithubActivityCanonicalMapper
18
+ from .google_calendar_mapper import GoogleCalendarMapper
17
19
  from .grok_mapper import GrokCanonicalMapper
18
20
  from .messenger_mapper import ImessageCanonicalMapper, SignalCanonicalMapper, VoxtermTranscriptCanonicalMapper
19
21
 
@@ -33,13 +35,17 @@ MAPPER_REGISTRY = {
33
35
  "demo_places": DemoPlacesMapper,
34
36
  "demo_contacts": DemoContactsMapper,
35
37
  "journal_time_log": JournalTimeLogMapper,
38
+ "documents": DocumentsCanonicalMapper,
39
+ "google_calendar": GoogleCalendarMapper,
36
40
  }
37
41
 
38
42
  __all__ = [
39
43
  "BrowserActivityCanonicalMapper",
40
44
  "CanonicalMapper",
41
45
  "ChatGPTCanonicalMapper",
46
+ "DocumentsCanonicalMapper",
42
47
  "GithubActivityCanonicalMapper",
48
+ "GoogleCalendarMapper",
43
49
  "GrokCanonicalMapper",
44
50
  "ImessageCanonicalMapper",
45
51
  "SignalCanonicalMapper",
@@ -0,0 +1,43 @@
1
+ """Documents canonical mapper (PLAN_CANONICAL_CALENDAR_DOCUMENTS Part A).
2
+
3
+ Notion pages and Google Drive files both normalize to the same pinned
4
+ documents shape before reaching this mapper: doc_id, title, content, url,
5
+ mime_type, author, created_at, modified_at. Producing that shape from each
6
+ connector's native tool output (Notion's structured JSON, Drive's file
7
+ metadata) is a client/CP-side shaping concern (PLAN §A7, save-to-Topos
8
+ capability) — a separate, follow-up change. ``map()`` here is deliberately a
9
+ thin, near-identity read of the already-normalized keys (with a fallback to
10
+ the ingest record_id for doc_id), the same shape for both sources, which is
11
+ why one mapper class serves both ``notion_pages`` and ``gdrive_files``.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ from dataclasses import dataclass
17
+
18
+ from ...ingestion.parsers.base import NormalizedRecord
19
+ from .base import CanonicalMapper, CanonicalRecord, MappingMetadata
20
+
21
+
22
+ @dataclass
23
+ class DocumentsCanonicalMapper(CanonicalMapper):
24
+ version: str = "v1"
25
+
26
+ def map(self, normalized: NormalizedRecord) -> CanonicalRecord:
27
+ p = normalized.payload
28
+ doc_id = str(p.get("doc_id") or normalized.record_id)
29
+ canonical = {
30
+ "doc_id": doc_id,
31
+ "title": p.get("title"),
32
+ "content": p.get("content"),
33
+ "url": p.get("url"),
34
+ "mime_type": p.get("mime_type"),
35
+ "author": p.get("author"),
36
+ "created_at": p.get("created_at"),
37
+ "modified_at": p.get("modified_at"),
38
+ "source_record_id": doc_id,
39
+ }
40
+ return CanonicalRecord(record_id=doc_id, payload=canonical)
41
+
42
+ def mapping_metadata(self, normalized: NormalizedRecord) -> MappingMetadata:
43
+ return MappingMetadata(source_id="documents", mapping_version=self.version)
@@ -5,6 +5,15 @@ Additionally, each commit inside a PushEvent ``payload.commits[]`` maps to one
5
5
  ``journal_entries`` row — a commit reads like a work-journal entry (category
6
6
  'code', content = commit message). Only PushEvent commits fan out; PRs/issues
7
7
  stay activity-only.
8
+
9
+ Journal-lane policy (strict): when a commit carries an ``authorship`` field
10
+ (authored | ai_assisted | participated | bot — stamped by callers that know the
11
+ owner's login and can detect AI co-author trailers / bot authors), only
12
+ ``authored`` commits become journal entries; the rest stay activity-only.
13
+ External contributions and AI-generated commits are how the owner's time was
14
+ spent (activity), not the owner's personal words (journal). Commits without the
15
+ field (legacy webhook/UI-stream payloads) keep the historical all-commits
16
+ behavior.
8
17
  """
9
18
 
10
19
  from __future__ import annotations
@@ -160,6 +169,17 @@ class GithubActivityCanonicalMapper(CanonicalMapper):
160
169
  sha = str(commit.get("sha") or "").strip()
161
170
  if not sha:
162
171
  continue # no deterministic identity without a sha
172
+ # Journal-lane policy (strict): only commits the owner personally
173
+ # authored read as journal entries. Callers that can classify (they
174
+ # know the owner's login + can detect AI co-author trailers / bots)
175
+ # stamp `authorship` on each commit: authored | ai_assisted |
176
+ # participated | bot. Anything non-authored stays activity-only —
177
+ # external contributions and AI-generated commits are how time was
178
+ # spent, not the owner's personal journal. Absent field (legacy
179
+ # webhook/UI-stream payloads) keeps the historical behavior.
180
+ authorship = str(commit.get("authorship") or "").strip().lower() or None
181
+ if authorship is not None and authorship != "authored":
182
+ continue
163
183
  entry_id = f"github:{repo_name}:{sha}" if repo_name else f"github:{sha}"
164
184
  entry_at = _commit_timestamp(commit) or created_at
165
185
  metadata: Dict[str, Any] = {
@@ -168,6 +188,7 @@ class GithubActivityCanonicalMapper(CanonicalMapper):
168
188
  "ref": ref,
169
189
  "branch": branch,
170
190
  "event_id": f"github:{event_record_id}",
191
+ "authorship": authorship,
171
192
  }
172
193
  journal = {
173
194
  "entry_id": entry_id,