contextual-engine 0.2.0__tar.gz → 0.8.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (313) hide show
  1. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/.github/workflows/release.yml +0 -2
  2. contextual_engine-0.8.1/.mcp.json +8 -0
  3. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/PKG-INFO +32 -17
  4. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/README.md +4 -3
  5. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/__init__.py +8 -2
  6. contextual_engine-0.8.1/contextual/__main__.py +8 -0
  7. contextual_engine-0.8.1/contextual/cli/__init__.py +271 -0
  8. contextual_engine-0.8.1/contextual/cli/commands/__init__.py +35 -0
  9. contextual_engine-0.8.1/contextual/cli/commands/auth.py +24 -0
  10. contextual_engine-0.8.1/contextual/cli/commands/client.py +316 -0
  11. contextual_engine-0.8.1/contextual/cli/commands/config.py +161 -0
  12. contextual_engine-0.8.1/contextual/cli/commands/doctor.py +154 -0
  13. contextual_engine-0.8.1/contextual/cli/commands/fetch.py +221 -0
  14. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/cli/commands/index.py +60 -125
  15. contextual_engine-0.8.1/contextual/cli/commands/initialisation.py +609 -0
  16. contextual_engine-0.8.1/contextual/cli/commands/install.py +431 -0
  17. contextual_engine-0.8.1/contextual/cli/commands/mcp.py +163 -0
  18. contextual_engine-0.8.1/contextual/cli/commands/stats.py +192 -0
  19. contextual_engine-0.8.1/contextual/cli/commands/workspace.py +52 -0
  20. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/cli/core/__init__.py +2 -0
  21. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/cli/core/context.py +36 -9
  22. contextual_engine-0.8.1/contextual/cli/core/decorators.py +157 -0
  23. contextual_engine-0.8.1/contextual/cli/core/editor.py +25 -0
  24. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/cli/core/output.py +400 -405
  25. contextual_engine-0.8.1/contextual/config/__init__.py +120 -0
  26. contextual_engine-0.8.1/contextual/config/base.py +92 -0
  27. contextual_engine-0.8.1/contextual/config/global_/__init__.py +21 -0
  28. contextual_engine-0.8.1/contextual/config/global_/mcp_config.py +289 -0
  29. contextual_engine-0.8.1/contextual/config/global_/security_config.py +12 -0
  30. contextual_engine-0.8.1/contextual/config/global_/storage_config.py +32 -0
  31. contextual_engine-0.8.1/contextual/config/indexing.py +481 -0
  32. contextual_engine-0.8.1/contextual/config/paths.py +135 -0
  33. contextual_engine-0.8.1/contextual/config/workspace/__init__.py +26 -0
  34. contextual_engine-0.8.1/contextual/config/workspace/cache_config.py +12 -0
  35. contextual_engine-0.8.1/contextual/config/workspace/indexing_config.py +26 -0
  36. contextual_engine-0.8.1/contextual/config/workspace/observability_config.py +28 -0
  37. contextual_engine-0.8.1/contextual/config/workspace/retrieval_config.py +54 -0
  38. contextual_engine-0.8.1/contextual/config/workspace/workspace_config.py +22 -0
  39. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/core/__init__.py +2 -2
  40. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/core/errors.py +7 -80
  41. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/core/models.py +24 -179
  42. contextual_engine-0.8.1/contextual/git/hooks.py +285 -0
  43. contextual_engine-0.8.1/contextual/git/incremental_git.py +281 -0
  44. contextual_engine-0.8.1/contextual/graph/__init__.py +32 -0
  45. contextual_engine-0.8.1/contextual/graph/dedup.py +171 -0
  46. contextual_engine-0.8.1/contextual/graph/extractor.py +571 -0
  47. contextual_engine-0.8.1/contextual/graph/integrator.py +520 -0
  48. contextual_engine-0.8.1/contextual/graph/resolver.py +344 -0
  49. contextual_engine-0.8.1/contextual/graph/staleness.py +143 -0
  50. contextual_engine-0.8.1/contextual/graph/store.py +453 -0
  51. contextual_engine-0.8.1/contextual/graph/traversal.py +335 -0
  52. contextual_engine-0.8.1/contextual/incremental/__init__.py +42 -0
  53. contextual_engine-0.8.1/contextual/incremental/daemon_embed.py +91 -0
  54. contextual_engine-0.8.1/contextual/incremental/file_watcher.py +515 -0
  55. contextual_engine-0.8.1/contextual/incremental/incremental_indexer.py +324 -0
  56. contextual_engine-0.8.1/contextual/indexing/__init__.py +264 -0
  57. contextual_engine-0.8.1/contextual/indexing/_config.py +89 -0
  58. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/indexing/chunker.py +59 -417
  59. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/indexing/docs_pipeline.py +209 -46
  60. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/indexing/index_writer.py +31 -21
  61. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/indexing/merkle_tree.py +64 -11
  62. contextual_engine-0.8.1/contextual/indexing/pipeline.py +2196 -0
  63. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/indexing/processor.py +139 -129
  64. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/indexing/symbol_extractor.py +30 -23
  65. contextual_engine-0.8.1/contextual/mcp/__init__.py +22 -0
  66. contextual_engine-0.8.1/contextual/mcp/__main__.py +69 -0
  67. contextual_engine-0.8.1/contextual/mcp/_platform.py +81 -0
  68. contextual_engine-0.8.1/contextual/mcp/access.py +346 -0
  69. contextual_engine-0.8.1/contextual/mcp/config.py +16 -0
  70. contextual_engine-0.8.1/contextual/mcp/daemon.py +359 -0
  71. contextual_engine-0.8.1/contextual/mcp/middleware/__init__.py +5 -0
  72. contextual_engine-0.8.1/contextual/mcp/middleware/audit.py +165 -0
  73. contextual_engine-0.8.1/contextual/mcp/middleware/auth.py +78 -0
  74. contextual_engine-0.8.1/contextual/mcp/middleware/ratelimit.py +121 -0
  75. contextual_engine-0.8.1/contextual/mcp/middleware/warmup.py +102 -0
  76. contextual_engine-0.8.1/contextual/mcp/middleware/workspace.py +129 -0
  77. contextual_engine-0.8.1/contextual/mcp/router.py +217 -0
  78. contextual_engine-0.8.1/contextual/mcp/server.py +890 -0
  79. contextual_engine-0.8.1/contextual/mcp/session_manager.py +315 -0
  80. contextual_engine-0.8.1/contextual/mcp/shim.py +345 -0
  81. contextual_engine-0.8.1/contextual/mcp/tools/__init__.py +388 -0
  82. contextual_engine-0.8.1/contextual/mcp/tools/graph.py +1010 -0
  83. contextual_engine-0.8.1/contextual/mcp/tools/nexus.py +719 -0
  84. contextual_engine-0.8.1/contextual/mcp/tools/semantic.py +982 -0
  85. contextual_engine-0.8.1/contextual/mcp/tools/system.py +415 -0
  86. contextual_engine-0.8.1/contextual/mcp/tools/temporal.py +445 -0
  87. contextual_engine-0.8.1/contextual/models/__init__.py +541 -0
  88. contextual_engine-0.8.1/contextual/models/_inference.py +21 -0
  89. contextual_engine-0.8.1/contextual/models/allowlist.py +122 -0
  90. contextual_engine-0.8.1/contextual/models/base_embedder.py +72 -0
  91. contextual_engine-0.8.1/contextual/models/reranker_model.py +322 -0
  92. contextual_engine-0.8.1/contextual/models/unified_embedder.py +371 -0
  93. contextual_engine-0.8.1/contextual/observability/__init__.py +53 -0
  94. contextual_engine-0.8.1/contextual/observability/config.py +35 -0
  95. contextual_engine-0.8.1/contextual/observability/exporters.py +146 -0
  96. contextual_engine-0.8.1/contextual/observability/logging.py +113 -0
  97. contextual_engine-0.8.1/contextual/observability/retention.py +49 -0
  98. contextual_engine-0.8.1/contextual/observability/tracer.py +103 -0
  99. contextual_engine-0.8.1/contextual/retrieval/__init__.py +219 -0
  100. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/retrieval/context_assembler.py +28 -38
  101. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/retrieval/mmr.py +7 -2
  102. contextual_engine-0.8.1/contextual/retrieval/pipeline.py +848 -0
  103. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/retrieval/ranker.py +24 -14
  104. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/retrieval/tokenizer.py +5 -0
  105. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/security/__init__.py +4 -0
  106. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/security/sanitize.py +58 -1
  107. contextual_engine-0.8.1/contextual/storage/__init__.py +205 -0
  108. contextual_engine-0.8.1/contextual/storage/cache.py +338 -0
  109. contextual_engine-0.8.1/contextual/storage/connection.py +472 -0
  110. contextual_engine-0.8.1/contextual/storage/fts.py +81 -0
  111. contextual_engine-0.8.1/contextual/storage/lancedb_provider.py +2120 -0
  112. contextual_engine-0.8.1/contextual/storage/migrations/__init__.py +17 -0
  113. contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me001_orgs.py +51 -0
  114. contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me002_org_members.py +52 -0
  115. contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me003_teams.py +49 -0
  116. contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me004_team_members.py +48 -0
  117. contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me005_org_workspaces.py +48 -0
  118. contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me006_workspace_permissions.py +51 -0
  119. contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me007_idp_sync_log.py +48 -0
  120. contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me008_org_policies.py +47 -0
  121. contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me009_api_keys.py +50 -0
  122. contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me010_org_audit_log.py +54 -0
  123. contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me011_workspace_traceability.py +97 -0
  124. contextual_engine-0.8.1/contextual/storage/migrations/m001_global.py +1 -0
  125. contextual_engine-0.8.1/contextual/storage/migrations/m002_embeddings.py +1 -0
  126. contextual_engine-0.8.1/contextual/storage/migrations/m003_temporal.py +1 -0
  127. contextual_engine-0.8.1/contextual/storage/migrations/m004_graph.py +1 -0
  128. contextual_engine-0.8.1/contextual/storage/migrations/m005_cache.py +1 -0
  129. contextual_engine-0.8.1/contextual/storage/migrations/m006_logs.py +1 -0
  130. contextual_engine-0.8.1/contextual/storage/migrations/m007_terminal_sessions.py +1 -0
  131. contextual_engine-0.8.1/contextual/storage/migrations/m008_queue.py +1 -0
  132. contextual_engine-0.8.1/contextual/storage/migrations/m009_swarm.py +1 -0
  133. contextual_engine-0.8.1/contextual/storage/migrations/m010_task_force.py +1 -0
  134. contextual_engine-0.8.1/contextual/storage/migrations/m011_reminders.py +1 -0
  135. contextual_engine-0.8.1/contextual/storage/migrations/m013_temporal_l2.py +1 -0
  136. contextual_engine-0.8.1/contextual/storage/migrations/m014_nexus_foundation.py +1 -0
  137. contextual_engine-0.8.1/contextual/storage/migrations/runner.py +791 -0
  138. contextual_engine-0.8.1/contextual/storage/migrations/solo/m001_global.py +45 -0
  139. contextual_engine-0.8.1/contextual/storage/migrations/solo/m002_embeddings.py +45 -0
  140. contextual_engine-0.8.1/contextual/storage/migrations/solo/m003_temporal.py +45 -0
  141. contextual_engine-0.8.1/contextual/storage/migrations/solo/m004_graph.py +45 -0
  142. contextual_engine-0.8.1/contextual/storage/migrations/solo/m005_cache.py +45 -0
  143. contextual_engine-0.8.1/contextual/storage/migrations/solo/m006_logs.py +45 -0
  144. contextual_engine-0.8.1/contextual/storage/migrations/solo/m007_terminal_sessions.py +59 -0
  145. contextual_engine-0.8.1/contextual/storage/migrations/solo/m008_queue.py +59 -0
  146. contextual_engine-0.8.1/contextual/storage/migrations/solo/m009_swarm.py +59 -0
  147. contextual_engine-0.8.1/contextual/storage/migrations/solo/m010_task_force.py +59 -0
  148. contextual_engine-0.8.1/contextual/storage/migrations/solo/m011_reminders.py +59 -0
  149. contextual_engine-0.8.1/contextual/storage/migrations/solo/m012_workspace_metadata.py +148 -0
  150. contextual_engine-0.8.1/contextual/storage/migrations/solo/m013_temporal_l2.py +55 -0
  151. contextual_engine-0.8.1/contextual/storage/migrations/solo/m014_nexus_foundation.py +311 -0
  152. contextual_engine-0.8.1/contextual/storage/migrations/teams/mt001_orgs.py +47 -0
  153. contextual_engine-0.8.1/contextual/storage/migrations/teams/mt002_org_members.py +48 -0
  154. contextual_engine-0.8.1/contextual/storage/migrations/teams/mt003_teams.py +48 -0
  155. contextual_engine-0.8.1/contextual/storage/migrations/teams/mt004_team_members.py +47 -0
  156. contextual_engine-0.8.1/contextual/storage/migrations/teams/mt005_team_workspaces.py +50 -0
  157. contextual_engine-0.8.1/contextual/storage/migrations/teams/mt006_workspace_permissions.py +48 -0
  158. contextual_engine-0.8.1/contextual/storage/migrations/teams/mt007_team_audit_log.py +49 -0
  159. contextual_engine-0.8.1/contextual/storage/migrations/teams/mt008_workspace_traceability.py +93 -0
  160. contextual_engine-0.8.1/contextual/storage/schema.py +1335 -0
  161. contextual_engine-0.8.1/contextual/storage/schema_base.py +399 -0
  162. contextual_engine-0.8.1/contextual/storage/schema_ent.py +512 -0
  163. contextual_engine-0.8.1/contextual/storage/schema_team.py +372 -0
  164. contextual_engine-0.8.1/contextual/temporal/__init__.py +27 -0
  165. contextual_engine-0.8.1/contextual/temporal/adr.py +855 -0
  166. contextual_engine-0.8.1/contextual/temporal/blame_pipeline.py +432 -0
  167. contextual_engine-0.8.1/contextual/temporal/context.py +294 -0
  168. contextual_engine-0.8.1/contextual/temporal/query.py +207 -0
  169. contextual_engine-0.8.1/contextual/temporal/velocity.py +135 -0
  170. contextual_engine-0.8.1/docs/DATABASE.md +152 -0
  171. contextual_engine-0.8.1/docs/DRs/GEMINI-DR-graph-implementation.md +298 -0
  172. contextual_engine-0.8.1/docs/DRs/GEMINI-DR-nexus-graph-architecture.md +232 -0
  173. contextual_engine-0.8.1/docs/DRs/GEMINI-DR-nexus-graph-engineering.md +257 -0
  174. contextual_engine-0.8.1/docs/DRs/GRAPH_LAYER_OPEN_QUESTIONS_RESOLVED.md +163 -0
  175. contextual_engine-0.8.1/docs/DRs/PERPLEXITY-DR-L2-temporal.md +1856 -0
  176. contextual_engine-0.8.1/docs/DRs/PERPLEXITY-DR-client-integration.md +364 -0
  177. contextual_engine-0.8.1/docs/DRs/PERPLEXITY-DR-mcp-config.md +806 -0
  178. contextual_engine-0.8.1/docs/INTEGRATIONS.md +79 -0
  179. contextual_engine-0.8.1/docs/MCP_TOOLS.md +102 -0
  180. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/MEMORY.md +30 -7
  181. contextual_engine-0.8.1/pyproject.toml +227 -0
  182. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/pytest.ini +26 -12
  183. contextual_engine-0.8.1/tests/README.md +215 -0
  184. contextual_engine-0.8.1/tests/conftest.py +146 -0
  185. contextual_engine-0.8.1/tests/fixtures/sample_code.py +9 -0
  186. contextual_engine-0.8.1/tests/fixtures/sample_docs.md +9 -0
  187. contextual_engine-0.8.1/tests/test_accuracy.py +30 -0
  188. contextual_engine-0.8.1/tests/test_architecture.py +43 -0
  189. contextual_engine-0.8.1/tests/test_async.py +29 -0
  190. contextual_engine-0.8.1/tests/test_behaviour.py +29 -0
  191. contextual_engine-0.8.1/tests/test_cache_stats.py +38 -0
  192. contextual_engine-0.8.1/tests/test_cli.py +74 -0
  193. contextual_engine-0.8.1/tests/test_flow.py +29 -0
  194. contextual_engine-0.8.1/tests/test_git.py +37 -0
  195. contextual_engine-0.8.1/tests/test_graph.py +322 -0
  196. contextual_engine-0.8.1/tests/test_graph_resolution_order.py +66 -0
  197. contextual_engine-0.8.1/tests/test_incremental.py +658 -0
  198. contextual_engine-0.8.1/tests/test_indexing.py +317 -0
  199. contextual_engine-0.8.1/tests/test_latency.py +32 -0
  200. contextual_engine-0.8.1/tests/test_mcp.py +43 -0
  201. contextual_engine-0.8.1/tests/test_mcp_hardening.py +184 -0
  202. contextual_engine-0.8.1/tests/test_observability.py +32 -0
  203. contextual_engine-0.8.1/tests/test_performance.py +33 -0
  204. contextual_engine-0.8.1/tests/test_query_cache_roundtrip.py +39 -0
  205. contextual_engine-0.8.1/tests/test_retrieval.py +413 -0
  206. contextual_engine-0.8.1/tests/test_retry.py +29 -0
  207. contextual_engine-0.8.1/tests/test_security.py +29 -0
  208. contextual_engine-0.8.1/tests/test_storage.py +996 -0
  209. contextual_engine-0.2.0/AUDIT_LOG.md +0 -1114
  210. contextual_engine-0.2.0/FINAL_AUDIT.md +0 -706
  211. contextual_engine-0.2.0/RECOVERY_AUDIT.md +0 -348
  212. contextual_engine-0.2.0/contextual/cli/__init__.py +0 -144
  213. contextual_engine-0.2.0/contextual/cli/commands/__init__.py +0 -11
  214. contextual_engine-0.2.0/contextual/cli/commands/account.py +0 -18
  215. contextual_engine-0.2.0/contextual/cli/commands/client.py +0 -235
  216. contextual_engine-0.2.0/contextual/cli/commands/fetch.py +0 -99
  217. contextual_engine-0.2.0/contextual/cli/commands/serve.py +0 -11
  218. contextual_engine-0.2.0/contextual/cli/commands/stats.py +0 -61
  219. contextual_engine-0.2.0/contextual/cli/commands/temporal.py +0 -15
  220. contextual_engine-0.2.0/contextual/cli/core/decorators.py +0 -104
  221. contextual_engine-0.2.0/contextual/config/__init__.py +0 -103
  222. contextual_engine-0.2.0/contextual/config/indexing.py +0 -170
  223. contextual_engine-0.2.0/contextual/indexing/__init__.py +0 -139
  224. contextual_engine-0.2.0/contextual/indexing/file_watcher.py +0 -365
  225. contextual_engine-0.2.0/contextual/indexing/incremental.py +0 -391
  226. contextual_engine-0.2.0/contextual/indexing/pipeline.py +0 -825
  227. contextual_engine-0.2.0/contextual/integrations/__init__.py +0 -10
  228. contextual_engine-0.2.0/contextual/integrations/git_integration.py +0 -547
  229. contextual_engine-0.2.0/contextual/mcp/__init__.py +0 -15
  230. contextual_engine-0.2.0/contextual/mcp/__main__.py +0 -25
  231. contextual_engine-0.2.0/contextual/mcp/docs_tools.py +0 -325
  232. contextual_engine-0.2.0/contextual/mcp/server.py +0 -159
  233. contextual_engine-0.2.0/contextual/mcp/tools.py +0 -589
  234. contextual_engine-0.2.0/contextual/models/__init__.py +0 -439
  235. contextual_engine-0.2.0/contextual/models/base_embedder.py +0 -140
  236. contextual_engine-0.2.0/contextual/models/reranker_model.py +0 -195
  237. contextual_engine-0.2.0/contextual/models/unified_embedder.py +0 -205
  238. contextual_engine-0.2.0/contextual/observability/__init__.py +0 -21
  239. contextual_engine-0.2.0/contextual/observability/logging.py +0 -144
  240. contextual_engine-0.2.0/contextual/retrieval/__init__.py +0 -224
  241. contextual_engine-0.2.0/contextual/retrieval/pipeline.py +0 -543
  242. contextual_engine-0.2.0/contextual/retrieval/search.py +0 -636
  243. contextual_engine-0.2.0/contextual/storage/__init__.py +0 -134
  244. contextual_engine-0.2.0/contextual/storage/cache.py +0 -232
  245. contextual_engine-0.2.0/contextual/storage/connection.py +0 -453
  246. contextual_engine-0.2.0/contextual/storage/lancedb_provider.py +0 -1311
  247. contextual_engine-0.2.0/contextual/storage/schema.py +0 -510
  248. contextual_engine-0.2.0/docs/Architecture_Diagram.png +0 -0
  249. contextual_engine-0.2.0/docs/INTEGRATIONS.md +0 -530
  250. contextual_engine-0.2.0/pyproject.toml +0 -160
  251. contextual_engine-0.2.0/test_incremental.py +0 -165
  252. contextual_engine-0.2.0/test_mcp.py +0 -580
  253. contextual_engine-0.2.0/tests/conftest.py +0 -440
  254. contextual_engine-0.2.0/tests/test_accuracy_speed_async_integrity.py +0 -411
  255. contextual_engine-0.2.0/tests/test_architecture_security_flow.py +0 -523
  256. contextual_engine-0.2.0/tests/test_architecture_wiring.py +0 -730
  257. contextual_engine-0.2.0/tests/test_cross_file_chunk_batching.py +0 -142
  258. contextual_engine-0.2.0/tests/test_deduplication.py +0 -397
  259. contextual_engine-0.2.0/tests/test_expected_behavior.py +0 -890
  260. contextual_engine-0.2.0/tests/test_performance.py +0 -911
  261. contextual_engine-0.2.0/tests/test_purge_command.py +0 -43
  262. contextual_engine-0.2.0/tests/test_retry_logic.py +0 -79
  263. contextual_engine-0.2.0/tests/test_speed_accuracy.py +0 -813
  264. contextual_engine-0.2.0/tests/test_thread_safety.py +0 -0
  265. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/.contextualignore +0 -0
  266. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/.github/workflows/ci.yml +0 -0
  267. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/.gitignore +0 -0
  268. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/LICENSE +0 -0
  269. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/git/__init__.py +0 -0
  270. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/git/blame.py +0 -0
  271. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/security/paths.py +0 -0
  272. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/security/workspace.py +0 -0
  273. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/ADRs/ADR-001-lancedb-over-vec0.md +0 -0
  274. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/ADRs/ADR-002-retry-exponential-backoff.md +0 -0
  275. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/ADRs/ADR-003-blake3-deduplication.md +0 -0
  276. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/ADRs/ADR-004-async-first-architecture.md +0 -0
  277. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/ADRs/ADR-005-model-lineup.md +0 -0
  278. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/ARCHITECTURE.md +0 -0
  279. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/CHANGELOG.md +0 -0
  280. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DEPLOYMENT.md +0 -0
  281. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DISTRIBUTIONS.md +0 -0
  282. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/CHATGPT-DR-mcp-cli-security-testing-distribution.md +0 -0
  283. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/CHATGPT-DR-web-ui-experience.md +0 -0
  284. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/CLAUDE-DR-ai-agents-teams.md +0 -0
  285. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/CLAUDE-DR-competitive-landscape-market-analysis.md +0 -0
  286. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/CLAUDE-DR-core-architecture.md +0 -0
  287. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/CLAUDE-DR-mvp-phase0-technical-plan.md +0 -0
  288. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/CLAUDE-DR-strategic-briefing.md +0 -0
  289. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/GEMINI-DR-hybrid-retrieval-local-optimization.md +0 -0
  290. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/GEMINI-DR-infrastructure-security.md +0 -0
  291. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/GEMINI-DR-lance-specs.md +0 -0
  292. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/GEMINI-DR-vec0-vs-lancedb.md +0 -0
  293. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/KIMI-DR-tech-stack-optimization.md +0 -0
  294. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/PERPLEXITY-DR-indexing-optimisation.md +0 -0
  295. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/PERPLEXITY-DR-lancedb-implementation.md +0 -0
  296. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/PERPLEXITY-DR-local-data-infrastructure.md +0 -0
  297. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/PERPLEXITY-DR-mcp-security-hardening.md +0 -0
  298. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/PERPLEXITY-DR-models-pipelines.md +0 -0
  299. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/PERPLEXITY-DR-python-async-ai-pipelines.md +0 -0
  300. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/PERPLEXITY-DR-semantic-indexing.md +0 -0
  301. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/FRONTEND.md +0 -0
  302. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/GITHUB.md +0 -0
  303. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/PROJECT_MANAGEMENT.md +0 -0
  304. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/PROJECT_PHASES.md +0 -0
  305. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/RESOURCES.md +0 -0
  306. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/ROADMAP.md +0 -0
  307. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/SECURITY.md +0 -0
  308. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/TEAMS.md +0 -0
  309. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/TECHNICAL_SPEC.md +0 -0
  310. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/TESTING.md +0 -0
  311. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/VERSION.MD +0 -0
  312. {contextual_engine-0.2.0 → contextual_engine-0.8.1}/tests/__init__.py +0 -0
  313. /contextual_engine-0.2.0/docs/MCP_TOOLS.md → /contextual_engine-0.8.1/tests/fixtures/__init__.py +0 -0
@@ -32,8 +32,6 @@ jobs:
32
32
 
33
33
  - name: Publish to PyPI
34
34
  uses: pypa/gh-action-pypi-publish@release/v1
35
- with:
36
- password: ${{ secrets.PYPI_API_TOKEN }}
37
35
 
38
36
  - name: Extract version from tag
39
37
  id: version
@@ -0,0 +1,8 @@
1
+ {
2
+ "mcpServers": {
3
+ "contextual": {
4
+ "command": "/Users/apple/TechStack/Projects/Contextual/.venv/bin/contextual-mcp",
5
+ "args": ["--workspace", "/Users/apple/TechStack/Projects/Contextual"]
6
+ }
7
+ }
8
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: contextual-engine
3
- Version: 0.2.0
3
+ Version: 0.8.1
4
4
  Summary: Temporal-first local code memory for AI tools via MCP
5
5
  Project-URL: Homepage, https://contextuallabs.dev
6
6
  Project-URL: Documentation, https://contextuallabs.dev/docs
@@ -120,63 +120,77 @@ License: BUSINESS SOURCE LICENSE 1.1
120
120
  ---
121
121
  License-File: LICENSE
122
122
  Keywords: ai,code-search,developer-tools,embeddings,local-first,mcp,temporal
123
- Classifier: Development Status :: 3 - Alpha
123
+ Classifier: Development Status :: 4 - Beta
124
124
  Classifier: Environment :: Console
125
125
  Classifier: Intended Audience :: Developers
126
+ Classifier: License :: Other/Proprietary License
127
+ Classifier: Operating System :: OS Independent
126
128
  Classifier: Programming Language :: Python :: 3.12
127
129
  Classifier: Programming Language :: Python :: 3.13
128
130
  Classifier: Topic :: Software Development :: Libraries
129
131
  Classifier: Topic :: Text Processing :: Indexing
130
132
  Classifier: Typing :: Typed
131
- Requires-Python: <3.15,>=3.12
133
+ Requires-Python: <3.14,>=3.12
132
134
  Requires-Dist: blake3>=0.4.1
135
+ Requires-Dist: docutils>=0.21
136
+ Requires-Dist: dulwich>=0.21
133
137
  Requires-Dist: einops>=0.7
134
138
  Requires-Dist: fastmcp<4,>=3.2
139
+ Requires-Dist: httpx[http2]>=0.27.0
135
140
  Requires-Dist: huggingface-hub>=0.23
136
141
  Requires-Dist: lancedb<0.31,>=0.26
142
+ Requires-Dist: markdown-it-py>=4.0
143
+ Requires-Dist: mdit-py-plugins
137
144
  Requires-Dist: numpy>=1.26
145
+ Requires-Dist: opentelemetry-api>=1.24.0
146
+ Requires-Dist: opentelemetry-sdk>=1.24.0
138
147
  Requires-Dist: pathspec>=0.10
139
148
  Requires-Dist: platformdirs>=3.3
140
149
  Requires-Dist: psutil>=5.9.0
141
150
  Requires-Dist: pyarrow>=14.0
142
151
  Requires-Dist: pydantic>=2.0
143
152
  Requires-Dist: pygit2>=1.15
153
+ Requires-Dist: python-frontmatter
154
+ Requires-Dist: rapidfuzz>=3
144
155
  Requires-Dist: rich>=13.0
145
156
  Requires-Dist: safetensors>=0.4.3
146
157
  Requires-Dist: sentence-transformers>=3.0
147
158
  Requires-Dist: simsimd<6,>=3.9
148
- Requires-Dist: sqlite-vec>=0.1.1
159
+ Requires-Dist: starlette>=0.37
149
160
  Requires-Dist: structlog>=25.4
150
161
  Requires-Dist: tantivy>=0.20.1
151
162
  Requires-Dist: tenacity>=8.0
152
163
  Requires-Dist: tiktoken>=0.5
153
164
  Requires-Dist: tokenizers<=0.23.0,>=0.19
165
+ Requires-Dist: tomli-w>=1.0.0
154
166
  Requires-Dist: torch>=2.2
155
167
  Requires-Dist: transformers<4.60,>=4.40
156
168
  Requires-Dist: tree-sitter-language-pack>=0.7.2
157
169
  Requires-Dist: typer<1.0,>=0.9
170
+ Requires-Dist: uvicorn>=0.27
158
171
  Requires-Dist: watchdog>=4.0
159
172
  Provides-Extra: benchmark
160
173
  Requires-Dist: coir-eval; extra == 'benchmark'
161
174
  Requires-Dist: ranx>=0.3; extra == 'benchmark'
162
175
  Provides-Extra: dev
163
176
  Requires-Dist: build>=1.0; extra == 'dev'
164
- Requires-Dist: docutils>=0.21; extra == 'dev'
165
- Requires-Dist: markdown-it-py>=4.0; extra == 'dev'
166
- Requires-Dist: mdit-py-plugins; extra == 'dev'
167
177
  Requires-Dist: mypy>=1.10; extra == 'dev'
168
- Requires-Dist: pytest-asyncio>=1.0; extra == 'dev'
169
- Requires-Dist: pytest-cov>=4.0; extra == 'dev'
170
- Requires-Dist: pytest-xdist>=3.0; extra == 'dev'
171
- Requires-Dist: pytest>=7.0; extra == 'dev'
172
- Requires-Dist: python-frontmatter; extra == 'dev'
173
- Requires-Dist: ranx>=0.3; extra == 'dev'
174
- Requires-Dist: rapidfuzz>=3; extra == 'dev'
175
178
  Requires-Dist: ruff>=0.4; extra == 'dev'
176
179
  Requires-Dist: twine>=5.0; extra == 'dev'
177
180
  Provides-Extra: mps
178
181
  Requires-Dist: torch>=2.4.0; extra == 'mps'
179
182
  Requires-Dist: torchvision>=0.19.0; extra == 'mps'
183
+ Provides-Extra: test
184
+ Requires-Dist: anyio[trio]>=4.3.0; extra == 'test'
185
+ Requires-Dist: freezegun>=1.5.0; extra == 'test'
186
+ Requires-Dist: hypothesis>=6.100.0; extra == 'test'
187
+ Requires-Dist: polyfactory>=2.16.0; extra == 'test'
188
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'test'
189
+ Requires-Dist: pytest-benchmark>=4.0.0; extra == 'test'
190
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'test'
191
+ Requires-Dist: pytest-xdist>=3.5.0; extra == 'test'
192
+ Requires-Dist: pytest>=8.3.0; extra == 'test'
193
+ Requires-Dist: respx>=0.21.0; extra == 'test'
180
194
  Description-Content-Type: text/markdown
181
195
 
182
196
  # Contextual
@@ -184,8 +198,8 @@ Description-Content-Type: text/markdown
184
198
  **Local-first temporal semantic code memory engine for AI tools**
185
199
 
186
200
  [![PyPI](https://img.shields.io/pypi/v/contextual-engine)](https://pypi.org/project/contextual-engine/)
187
- [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
188
- [![Python](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/downloads/)
201
+ [![License](https://img.shields.io/badge/license-BUSL%201.1-blue.svg)](LICENSE)
202
+ [![Python](https://img.shields.io/badge/python-3.12%2B-blue)](https://www.python.org/downloads/)
189
203
 
190
204
  ## What is Contextual?
191
205
 
@@ -252,4 +266,5 @@ Add to your AI tool's MCP config:
252
266
 
253
267
  ## License
254
268
 
255
- Apache 2.0
269
+ Business Source License 1.1 (BUSL-1.1) — see [LICENSE](LICENSE) for the full
270
+ terms, including the Additional Use Grant and the Change Date / Change License.
@@ -3,8 +3,8 @@
3
3
  **Local-first temporal semantic code memory engine for AI tools**
4
4
 
5
5
  [![PyPI](https://img.shields.io/pypi/v/contextual-engine)](https://pypi.org/project/contextual-engine/)
6
- [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
7
- [![Python](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/downloads/)
6
+ [![License](https://img.shields.io/badge/license-BUSL%201.1-blue.svg)](LICENSE)
7
+ [![Python](https://img.shields.io/badge/python-3.12%2B-blue)](https://www.python.org/downloads/)
8
8
 
9
9
  ## What is Contextual?
10
10
 
@@ -71,4 +71,5 @@ Add to your AI tool's MCP config:
71
71
 
72
72
  ## License
73
73
 
74
- Apache 2.0
74
+ Business Source License 1.1 (BUSL-1.1) — see [LICENSE](LICENSE) for the full
75
+ terms, including the Additional Use Grant and the Change Date / Change License.
@@ -6,9 +6,15 @@ through bi-temporal fact tracking and deterministic retrieval.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
- __version__ = "0.2.0"
9
+ from importlib.metadata import PackageNotFoundError, version as _pkg_version
10
+
11
+ try:
12
+ __version__ = _pkg_version("contextual-engine")
13
+ except PackageNotFoundError:
14
+ __version__ = "0.0.0+dev"
15
+
10
16
  __author__ = "Contextual Team"
11
- __license__ = "BSL-1.1"
17
+ __license__ = "BUSL-1.1"
12
18
 
13
19
  # Public API exports will be added as modules are built
14
20
  __all__ = [
@@ -0,0 +1,8 @@
1
+ """Package entrypoint for `python -m contextual`."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from contextual.cli import main
6
+
7
+ if __name__ == "__main__":
8
+ main()
@@ -0,0 +1,271 @@
1
+ """
2
+ Contextual CLI - Auto-discovering command-line interface.
3
+
4
+ Commands are registered via @register_command decorator and automatically
5
+ discovered at import time. No manual wiring required.
6
+ """
7
+
8
+ import asyncio
9
+ import inspect
10
+ import shutil
11
+ import sys
12
+ from functools import wraps
13
+ from pathlib import Path
14
+ from typing import Any
15
+
16
+ import typer
17
+
18
+ from contextual.cli import commands
19
+ from contextual.cli.core.decorators import _COMMAND_REGISTRY
20
+ from contextual.cli.core.output import (
21
+ print_error,
22
+ print_reset_start,
23
+ print_reset_success,
24
+ print_version,
25
+ )
26
+
27
+ from contextual import __version__ # single source: pyproject.toml via importlib.metadata
28
+
29
+ # ── Brand theme: override Typer's default Rich help colors ────────────
30
+ # Must run before typer.Typer() is instantiated.
31
+ try:
32
+ try:
33
+ import typer.rich_utils as _ru
34
+ except ImportError:
35
+ import typer._rich_utils as _ru
36
+
37
+ _ru.STYLE_OPTION = "white"
38
+ _ru.STYLE_SWITCH = "white"
39
+ _ru.STYLE_NEGATIVE_OPTION = "white"
40
+ _ru.STYLE_NEGATIVE_SWITCH = "white"
41
+ _ru.STYLE_METAVAR = "#6b6b6b"
42
+ _ru.STYLE_METAVAR_SEPARATOR = "#6b6b6b"
43
+ _ru.STYLE_USAGE = "white bold"
44
+ _ru.STYLE_USAGE_COMMAND = "white"
45
+ _ru.STYLE_HELPTEXT_FIRST_LINE = "white"
46
+ _ru.STYLE_HELPTEXT = "#6b6b6b"
47
+ _ru.STYLE_OPTION_HELP = "#6b6b6b"
48
+ _ru.STYLE_OPTION_DEFAULT = "#6b6b6b"
49
+ _ru.STYLE_OPTION_ENVVAR = "#6b6b6b"
50
+ _ru.STYLE_REQUIRED_SHORT = "white bold"
51
+ _ru.STYLE_REQUIRED_LONG = "white bold"
52
+ _ru.STYLE_DEPRECATED_COMMAND = "#6b6b6b"
53
+ _ru.STYLE_ERRORS_PANEL_BORDER = "white"
54
+ _ru.STYLE_ERRORS_SUGGESTION = "#6b6b6b"
55
+ _ru.STYLE_ERRORS_SUGGESTION_COMMAND = "white bold"
56
+ _ru.STYLE_ABORTED = "#6b6b6b"
57
+
58
+ # Custom additions to ensure no yellow/cyan is shown
59
+ _ru.STYLE_COMMANDS_TABLE_FIRST_COLUMN = "white"
60
+ _ru.STYLE_DEPRECATED = "#6b6b6b"
61
+ except (ImportError, AttributeError):
62
+ pass # Graceful — if Typer internals change, don't crash
63
+ # ─────────────────────────────────────────────────────────────────────
64
+
65
+ # Create main Typer app
66
+ app = typer.Typer(
67
+ name="contextual",
68
+ help="Local-first temporal semantic code memory engine",
69
+ add_completion=False,
70
+ no_args_is_help=True,
71
+ )
72
+
73
+
74
+ @app.callback(invoke_without_command=True)
75
+ def _root_callback(
76
+ ctx: typer.Context,
77
+ version: bool = typer.Option(
78
+ False,
79
+ "--version",
80
+ "-V",
81
+ help="Show version and exit.",
82
+ is_eager=True,
83
+ ),
84
+ reset: bool = typer.Option(
85
+ False,
86
+ "--reset",
87
+ help="Reset the current workspace .contextual directory and reinitialise.",
88
+ is_eager=True,
89
+ ),
90
+ purge: bool = typer.Option(
91
+ False,
92
+ "--purge",
93
+ help="Nuclear: delete workspace, deregister globally, remove from MCP configs.",
94
+ is_eager=True,
95
+ ),
96
+ ) -> None:
97
+ """Local-first temporal semantic code memory engine."""
98
+ if version:
99
+ print_version(__version__)
100
+ raise typer.Exit()
101
+
102
+ if reset:
103
+ workspace_dir = Path.cwd()
104
+ contextual_dir = workspace_dir / ".contextual"
105
+
106
+ print_reset_start(str(workspace_dir))
107
+
108
+ try:
109
+ shutil.rmtree(contextual_dir, ignore_errors=False)
110
+ except FileNotFoundError:
111
+ pass
112
+ except Exception as e:
113
+ print_error(f"Failed to purge workspace: {e}")
114
+ raise typer.Exit(1) from e
115
+
116
+ from contextual.cli.commands.initialisation import init as init_workspace
117
+
118
+ try:
119
+ loop = get_shared_loop()
120
+ loop.run_until_complete(init_workspace("."))
121
+ # Fresh state — nothing indexed yet. Write valid JSON ("{}"), not an
122
+ # empty file, so stats/workspace readers parse it as "never indexed"
123
+ # instead of hitting a JSONDecodeError.
124
+ (contextual_dir / "state.json").write_text("{}\n", encoding="utf-8")
125
+ except Exception as e:
126
+ print_error(f"Failed to reinitialise workspace: {e}")
127
+ raise typer.Exit(1) from e
128
+
129
+ print_reset_success(str(workspace_dir))
130
+ raise typer.Exit()
131
+
132
+ if purge:
133
+ from contextual.cli.core.output import (
134
+ print_error,
135
+ print_purge_complete,
136
+ print_purge_warning,
137
+ print_warning,
138
+ )
139
+
140
+ workspace_dir = Path.cwd()
141
+ workspace_name = workspace_dir.name
142
+ contextual_dir = workspace_dir / ".contextual"
143
+
144
+ print_purge_warning(workspace_name)
145
+
146
+ confirm = typer.prompt("Type workspace name to confirm")
147
+ if confirm.strip() != workspace_name:
148
+ print_error("Name mismatch. Aborted. Nothing was deleted.")
149
+ raise typer.Exit(1)
150
+
151
+ # 1. Stop daemon if running for this workspace
152
+ try:
153
+ from contextual.mcp.daemon import read_lock, stop_daemon
154
+ if read_lock():
155
+ stop_daemon()
156
+ except Exception:
157
+ pass
158
+
159
+ # 2. Read workspace_id before deleting (needed for deregistration)
160
+ workspace_id: str | None = None
161
+ try:
162
+ import tomllib
163
+ ws_config = contextual_dir / "config.toml"
164
+ if ws_config.exists():
165
+ with open(ws_config, "rb") as f:
166
+ ws_cfg = tomllib.load(f)
167
+ workspace_id = ws_cfg.get("workspace", {}).get("workspace_id")
168
+ except Exception:
169
+ pass
170
+
171
+ # 3. Delete .contextual/ directory
172
+ try:
173
+ shutil.rmtree(contextual_dir, ignore_errors=False)
174
+ except FileNotFoundError:
175
+ pass
176
+ except Exception as e:
177
+ print_error(f"Failed to delete workspace directory: {e}")
178
+ raise typer.Exit(1) from e
179
+
180
+ # 4. Deregister from global registry
181
+ if workspace_id:
182
+ try:
183
+ from contextual.storage import deregister_workspace
184
+ loop = get_shared_loop()
185
+ loop.run_until_complete(deregister_workspace(workspace_id))
186
+ except Exception:
187
+ print_warning(
188
+ "Could not remove the workspace from the global registry. "
189
+ "Run 'contextual workspace list' to verify."
190
+ )
191
+
192
+ print_purge_complete(workspace_name)
193
+ raise typer.Exit()
194
+
195
+
196
+ _SHARED_LOOP: asyncio.AbstractEventLoop | None = None
197
+
198
+
199
+ def get_shared_loop() -> asyncio.AbstractEventLoop:
200
+ global _SHARED_LOOP
201
+ if _SHARED_LOOP is None or _SHARED_LOOP.is_closed():
202
+ _SHARED_LOOP = asyncio.new_event_loop()
203
+ asyncio.set_event_loop(_SHARED_LOOP)
204
+ return _SHARED_LOOP
205
+
206
+
207
+ def make_sync(func: Any) -> Any:
208
+ """Wrap async function in a synchronous runner sharing one loop."""
209
+ if not inspect.iscoroutinefunction(func):
210
+ return func
211
+
212
+ @wraps(func)
213
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
214
+ loop = get_shared_loop()
215
+ return loop.run_until_complete(func(*args, **kwargs))
216
+
217
+ return wrapper
218
+
219
+
220
+ # Build command structure
221
+ _groups: dict[str, typer.Typer] = {}
222
+
223
+ for group_name, cmd_name, cmd_help, command_func in _COMMAND_REGISTRY:
224
+ # Derive CLI name: explicit name wins, else function name
225
+ fn_name = getattr(command_func, "__name__", str(command_func))
226
+ cli_name = cmd_name or fn_name.replace("_", "-")
227
+
228
+ # Strip group prefix from function name if no explicit name given
229
+ # e.g. mcp_status under group="mcp" → "status" not "mcp-status"
230
+ if cmd_name is None and group_name and fn_name.startswith(group_name + "_"):
231
+ cli_name = fn_name[len(group_name) + 1:].replace("_", "-")
232
+
233
+ sync_func = make_sync(command_func)
234
+
235
+ kwargs: dict[str, Any] = {}
236
+ if cmd_help:
237
+ kwargs["help"] = cmd_help
238
+
239
+ if group_name is None:
240
+ app.command(name=cli_name, **kwargs)(sync_func)
241
+ else:
242
+ if group_name not in _groups:
243
+ _groups[group_name] = typer.Typer(
244
+ help=f"{group_name.title()} commands",
245
+ no_args_is_help=True,
246
+ )
247
+ app.add_typer(_groups[group_name], name=group_name)
248
+ if cli_name == group_name:
249
+ _groups[group_name].callback(invoke_without_command=True, **kwargs)(sync_func)
250
+ else:
251
+ _groups[group_name].command(name=cli_name, **kwargs)(sync_func)
252
+
253
+
254
+ # CLI entry point (called from __main__.py)
255
+ def main() -> None:
256
+ """Main CLI entry point."""
257
+ from contextual.observability import ObservabilityConfig
258
+ from contextual.observability.logging import configure_logging
259
+
260
+ configure_logging(ObservabilityConfig(log_level="WARNING"))
261
+ try:
262
+ app()
263
+ except KeyboardInterrupt:
264
+ sys.exit(130)
265
+ except Exception as e:
266
+ print_error(str(e))
267
+ sys.exit(1)
268
+
269
+
270
+ if __name__ == "__main__":
271
+ main()
@@ -0,0 +1,35 @@
1
+ """
2
+ Auto-import all command modules.
3
+
4
+ This file is imported by cli/__init__.py, which triggers all
5
+ @register_command decorators in command files.
6
+ """
7
+
8
+ # Import all command modules (order doesn't matter)
9
+ from contextual.cli.commands import (
10
+ auth,
11
+ client,
12
+ config,
13
+ doctor,
14
+ fetch,
15
+ index,
16
+ initialisation,
17
+ install,
18
+ mcp,
19
+ stats,
20
+ workspace,
21
+ )
22
+
23
+ __all__ = [
24
+ "auth",
25
+ "client",
26
+ "config",
27
+ "doctor",
28
+ "fetch",
29
+ "index",
30
+ "initialisation",
31
+ "install",
32
+ "mcp",
33
+ "stats",
34
+ "workspace",
35
+ ]
@@ -0,0 +1,24 @@
1
+ """Authentication stub commands."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from contextual.cli.core import register_command
6
+ from contextual.cli.core.output import print_auth_stub
7
+
8
+
9
+ @register_command()
10
+ def login() -> None:
11
+ """Authenticate the CLI with user credentials."""
12
+ print_auth_stub("login")
13
+
14
+
15
+ @register_command()
16
+ def logout() -> None:
17
+ """Sign out and remove credentials."""
18
+ print_auth_stub("logout")
19
+
20
+
21
+ @register_command()
22
+ def account() -> None:
23
+ """Show authentication and account status."""
24
+ print_auth_stub("account")