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.
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/.github/workflows/release.yml +0 -2
- contextual_engine-0.8.1/.mcp.json +8 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/PKG-INFO +32 -17
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/README.md +4 -3
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/__init__.py +8 -2
- contextual_engine-0.8.1/contextual/__main__.py +8 -0
- contextual_engine-0.8.1/contextual/cli/__init__.py +271 -0
- contextual_engine-0.8.1/contextual/cli/commands/__init__.py +35 -0
- contextual_engine-0.8.1/contextual/cli/commands/auth.py +24 -0
- contextual_engine-0.8.1/contextual/cli/commands/client.py +316 -0
- contextual_engine-0.8.1/contextual/cli/commands/config.py +161 -0
- contextual_engine-0.8.1/contextual/cli/commands/doctor.py +154 -0
- contextual_engine-0.8.1/contextual/cli/commands/fetch.py +221 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/cli/commands/index.py +60 -125
- contextual_engine-0.8.1/contextual/cli/commands/initialisation.py +609 -0
- contextual_engine-0.8.1/contextual/cli/commands/install.py +431 -0
- contextual_engine-0.8.1/contextual/cli/commands/mcp.py +163 -0
- contextual_engine-0.8.1/contextual/cli/commands/stats.py +192 -0
- contextual_engine-0.8.1/contextual/cli/commands/workspace.py +52 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/cli/core/__init__.py +2 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/cli/core/context.py +36 -9
- contextual_engine-0.8.1/contextual/cli/core/decorators.py +157 -0
- contextual_engine-0.8.1/contextual/cli/core/editor.py +25 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/cli/core/output.py +400 -405
- contextual_engine-0.8.1/contextual/config/__init__.py +120 -0
- contextual_engine-0.8.1/contextual/config/base.py +92 -0
- contextual_engine-0.8.1/contextual/config/global_/__init__.py +21 -0
- contextual_engine-0.8.1/contextual/config/global_/mcp_config.py +289 -0
- contextual_engine-0.8.1/contextual/config/global_/security_config.py +12 -0
- contextual_engine-0.8.1/contextual/config/global_/storage_config.py +32 -0
- contextual_engine-0.8.1/contextual/config/indexing.py +481 -0
- contextual_engine-0.8.1/contextual/config/paths.py +135 -0
- contextual_engine-0.8.1/contextual/config/workspace/__init__.py +26 -0
- contextual_engine-0.8.1/contextual/config/workspace/cache_config.py +12 -0
- contextual_engine-0.8.1/contextual/config/workspace/indexing_config.py +26 -0
- contextual_engine-0.8.1/contextual/config/workspace/observability_config.py +28 -0
- contextual_engine-0.8.1/contextual/config/workspace/retrieval_config.py +54 -0
- contextual_engine-0.8.1/contextual/config/workspace/workspace_config.py +22 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/core/__init__.py +2 -2
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/core/errors.py +7 -80
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/core/models.py +24 -179
- contextual_engine-0.8.1/contextual/git/hooks.py +285 -0
- contextual_engine-0.8.1/contextual/git/incremental_git.py +281 -0
- contextual_engine-0.8.1/contextual/graph/__init__.py +32 -0
- contextual_engine-0.8.1/contextual/graph/dedup.py +171 -0
- contextual_engine-0.8.1/contextual/graph/extractor.py +571 -0
- contextual_engine-0.8.1/contextual/graph/integrator.py +520 -0
- contextual_engine-0.8.1/contextual/graph/resolver.py +344 -0
- contextual_engine-0.8.1/contextual/graph/staleness.py +143 -0
- contextual_engine-0.8.1/contextual/graph/store.py +453 -0
- contextual_engine-0.8.1/contextual/graph/traversal.py +335 -0
- contextual_engine-0.8.1/contextual/incremental/__init__.py +42 -0
- contextual_engine-0.8.1/contextual/incremental/daemon_embed.py +91 -0
- contextual_engine-0.8.1/contextual/incremental/file_watcher.py +515 -0
- contextual_engine-0.8.1/contextual/incremental/incremental_indexer.py +324 -0
- contextual_engine-0.8.1/contextual/indexing/__init__.py +264 -0
- contextual_engine-0.8.1/contextual/indexing/_config.py +89 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/indexing/chunker.py +59 -417
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/indexing/docs_pipeline.py +209 -46
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/indexing/index_writer.py +31 -21
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/indexing/merkle_tree.py +64 -11
- contextual_engine-0.8.1/contextual/indexing/pipeline.py +2196 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/indexing/processor.py +139 -129
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/indexing/symbol_extractor.py +30 -23
- contextual_engine-0.8.1/contextual/mcp/__init__.py +22 -0
- contextual_engine-0.8.1/contextual/mcp/__main__.py +69 -0
- contextual_engine-0.8.1/contextual/mcp/_platform.py +81 -0
- contextual_engine-0.8.1/contextual/mcp/access.py +346 -0
- contextual_engine-0.8.1/contextual/mcp/config.py +16 -0
- contextual_engine-0.8.1/contextual/mcp/daemon.py +359 -0
- contextual_engine-0.8.1/contextual/mcp/middleware/__init__.py +5 -0
- contextual_engine-0.8.1/contextual/mcp/middleware/audit.py +165 -0
- contextual_engine-0.8.1/contextual/mcp/middleware/auth.py +78 -0
- contextual_engine-0.8.1/contextual/mcp/middleware/ratelimit.py +121 -0
- contextual_engine-0.8.1/contextual/mcp/middleware/warmup.py +102 -0
- contextual_engine-0.8.1/contextual/mcp/middleware/workspace.py +129 -0
- contextual_engine-0.8.1/contextual/mcp/router.py +217 -0
- contextual_engine-0.8.1/contextual/mcp/server.py +890 -0
- contextual_engine-0.8.1/contextual/mcp/session_manager.py +315 -0
- contextual_engine-0.8.1/contextual/mcp/shim.py +345 -0
- contextual_engine-0.8.1/contextual/mcp/tools/__init__.py +388 -0
- contextual_engine-0.8.1/contextual/mcp/tools/graph.py +1010 -0
- contextual_engine-0.8.1/contextual/mcp/tools/nexus.py +719 -0
- contextual_engine-0.8.1/contextual/mcp/tools/semantic.py +982 -0
- contextual_engine-0.8.1/contextual/mcp/tools/system.py +415 -0
- contextual_engine-0.8.1/contextual/mcp/tools/temporal.py +445 -0
- contextual_engine-0.8.1/contextual/models/__init__.py +541 -0
- contextual_engine-0.8.1/contextual/models/_inference.py +21 -0
- contextual_engine-0.8.1/contextual/models/allowlist.py +122 -0
- contextual_engine-0.8.1/contextual/models/base_embedder.py +72 -0
- contextual_engine-0.8.1/contextual/models/reranker_model.py +322 -0
- contextual_engine-0.8.1/contextual/models/unified_embedder.py +371 -0
- contextual_engine-0.8.1/contextual/observability/__init__.py +53 -0
- contextual_engine-0.8.1/contextual/observability/config.py +35 -0
- contextual_engine-0.8.1/contextual/observability/exporters.py +146 -0
- contextual_engine-0.8.1/contextual/observability/logging.py +113 -0
- contextual_engine-0.8.1/contextual/observability/retention.py +49 -0
- contextual_engine-0.8.1/contextual/observability/tracer.py +103 -0
- contextual_engine-0.8.1/contextual/retrieval/__init__.py +219 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/retrieval/context_assembler.py +28 -38
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/retrieval/mmr.py +7 -2
- contextual_engine-0.8.1/contextual/retrieval/pipeline.py +848 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/retrieval/ranker.py +24 -14
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/retrieval/tokenizer.py +5 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/security/__init__.py +4 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/security/sanitize.py +58 -1
- contextual_engine-0.8.1/contextual/storage/__init__.py +205 -0
- contextual_engine-0.8.1/contextual/storage/cache.py +338 -0
- contextual_engine-0.8.1/contextual/storage/connection.py +472 -0
- contextual_engine-0.8.1/contextual/storage/fts.py +81 -0
- contextual_engine-0.8.1/contextual/storage/lancedb_provider.py +2120 -0
- contextual_engine-0.8.1/contextual/storage/migrations/__init__.py +17 -0
- contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me001_orgs.py +51 -0
- contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me002_org_members.py +52 -0
- contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me003_teams.py +49 -0
- contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me004_team_members.py +48 -0
- contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me005_org_workspaces.py +48 -0
- contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me006_workspace_permissions.py +51 -0
- contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me007_idp_sync_log.py +48 -0
- contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me008_org_policies.py +47 -0
- contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me009_api_keys.py +50 -0
- contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me010_org_audit_log.py +54 -0
- contextual_engine-0.8.1/contextual/storage/migrations/enterprise/me011_workspace_traceability.py +97 -0
- contextual_engine-0.8.1/contextual/storage/migrations/m001_global.py +1 -0
- contextual_engine-0.8.1/contextual/storage/migrations/m002_embeddings.py +1 -0
- contextual_engine-0.8.1/contextual/storage/migrations/m003_temporal.py +1 -0
- contextual_engine-0.8.1/contextual/storage/migrations/m004_graph.py +1 -0
- contextual_engine-0.8.1/contextual/storage/migrations/m005_cache.py +1 -0
- contextual_engine-0.8.1/contextual/storage/migrations/m006_logs.py +1 -0
- contextual_engine-0.8.1/contextual/storage/migrations/m007_terminal_sessions.py +1 -0
- contextual_engine-0.8.1/contextual/storage/migrations/m008_queue.py +1 -0
- contextual_engine-0.8.1/contextual/storage/migrations/m009_swarm.py +1 -0
- contextual_engine-0.8.1/contextual/storage/migrations/m010_task_force.py +1 -0
- contextual_engine-0.8.1/contextual/storage/migrations/m011_reminders.py +1 -0
- contextual_engine-0.8.1/contextual/storage/migrations/m013_temporal_l2.py +1 -0
- contextual_engine-0.8.1/contextual/storage/migrations/m014_nexus_foundation.py +1 -0
- contextual_engine-0.8.1/contextual/storage/migrations/runner.py +791 -0
- contextual_engine-0.8.1/contextual/storage/migrations/solo/m001_global.py +45 -0
- contextual_engine-0.8.1/contextual/storage/migrations/solo/m002_embeddings.py +45 -0
- contextual_engine-0.8.1/contextual/storage/migrations/solo/m003_temporal.py +45 -0
- contextual_engine-0.8.1/contextual/storage/migrations/solo/m004_graph.py +45 -0
- contextual_engine-0.8.1/contextual/storage/migrations/solo/m005_cache.py +45 -0
- contextual_engine-0.8.1/contextual/storage/migrations/solo/m006_logs.py +45 -0
- contextual_engine-0.8.1/contextual/storage/migrations/solo/m007_terminal_sessions.py +59 -0
- contextual_engine-0.8.1/contextual/storage/migrations/solo/m008_queue.py +59 -0
- contextual_engine-0.8.1/contextual/storage/migrations/solo/m009_swarm.py +59 -0
- contextual_engine-0.8.1/contextual/storage/migrations/solo/m010_task_force.py +59 -0
- contextual_engine-0.8.1/contextual/storage/migrations/solo/m011_reminders.py +59 -0
- contextual_engine-0.8.1/contextual/storage/migrations/solo/m012_workspace_metadata.py +148 -0
- contextual_engine-0.8.1/contextual/storage/migrations/solo/m013_temporal_l2.py +55 -0
- contextual_engine-0.8.1/contextual/storage/migrations/solo/m014_nexus_foundation.py +311 -0
- contextual_engine-0.8.1/contextual/storage/migrations/teams/mt001_orgs.py +47 -0
- contextual_engine-0.8.1/contextual/storage/migrations/teams/mt002_org_members.py +48 -0
- contextual_engine-0.8.1/contextual/storage/migrations/teams/mt003_teams.py +48 -0
- contextual_engine-0.8.1/contextual/storage/migrations/teams/mt004_team_members.py +47 -0
- contextual_engine-0.8.1/contextual/storage/migrations/teams/mt005_team_workspaces.py +50 -0
- contextual_engine-0.8.1/contextual/storage/migrations/teams/mt006_workspace_permissions.py +48 -0
- contextual_engine-0.8.1/contextual/storage/migrations/teams/mt007_team_audit_log.py +49 -0
- contextual_engine-0.8.1/contextual/storage/migrations/teams/mt008_workspace_traceability.py +93 -0
- contextual_engine-0.8.1/contextual/storage/schema.py +1335 -0
- contextual_engine-0.8.1/contextual/storage/schema_base.py +399 -0
- contextual_engine-0.8.1/contextual/storage/schema_ent.py +512 -0
- contextual_engine-0.8.1/contextual/storage/schema_team.py +372 -0
- contextual_engine-0.8.1/contextual/temporal/__init__.py +27 -0
- contextual_engine-0.8.1/contextual/temporal/adr.py +855 -0
- contextual_engine-0.8.1/contextual/temporal/blame_pipeline.py +432 -0
- contextual_engine-0.8.1/contextual/temporal/context.py +294 -0
- contextual_engine-0.8.1/contextual/temporal/query.py +207 -0
- contextual_engine-0.8.1/contextual/temporal/velocity.py +135 -0
- contextual_engine-0.8.1/docs/DATABASE.md +152 -0
- contextual_engine-0.8.1/docs/DRs/GEMINI-DR-graph-implementation.md +298 -0
- contextual_engine-0.8.1/docs/DRs/GEMINI-DR-nexus-graph-architecture.md +232 -0
- contextual_engine-0.8.1/docs/DRs/GEMINI-DR-nexus-graph-engineering.md +257 -0
- contextual_engine-0.8.1/docs/DRs/GRAPH_LAYER_OPEN_QUESTIONS_RESOLVED.md +163 -0
- contextual_engine-0.8.1/docs/DRs/PERPLEXITY-DR-L2-temporal.md +1856 -0
- contextual_engine-0.8.1/docs/DRs/PERPLEXITY-DR-client-integration.md +364 -0
- contextual_engine-0.8.1/docs/DRs/PERPLEXITY-DR-mcp-config.md +806 -0
- contextual_engine-0.8.1/docs/INTEGRATIONS.md +79 -0
- contextual_engine-0.8.1/docs/MCP_TOOLS.md +102 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/MEMORY.md +30 -7
- contextual_engine-0.8.1/pyproject.toml +227 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/pytest.ini +26 -12
- contextual_engine-0.8.1/tests/README.md +215 -0
- contextual_engine-0.8.1/tests/conftest.py +146 -0
- contextual_engine-0.8.1/tests/fixtures/sample_code.py +9 -0
- contextual_engine-0.8.1/tests/fixtures/sample_docs.md +9 -0
- contextual_engine-0.8.1/tests/test_accuracy.py +30 -0
- contextual_engine-0.8.1/tests/test_architecture.py +43 -0
- contextual_engine-0.8.1/tests/test_async.py +29 -0
- contextual_engine-0.8.1/tests/test_behaviour.py +29 -0
- contextual_engine-0.8.1/tests/test_cache_stats.py +38 -0
- contextual_engine-0.8.1/tests/test_cli.py +74 -0
- contextual_engine-0.8.1/tests/test_flow.py +29 -0
- contextual_engine-0.8.1/tests/test_git.py +37 -0
- contextual_engine-0.8.1/tests/test_graph.py +322 -0
- contextual_engine-0.8.1/tests/test_graph_resolution_order.py +66 -0
- contextual_engine-0.8.1/tests/test_incremental.py +658 -0
- contextual_engine-0.8.1/tests/test_indexing.py +317 -0
- contextual_engine-0.8.1/tests/test_latency.py +32 -0
- contextual_engine-0.8.1/tests/test_mcp.py +43 -0
- contextual_engine-0.8.1/tests/test_mcp_hardening.py +184 -0
- contextual_engine-0.8.1/tests/test_observability.py +32 -0
- contextual_engine-0.8.1/tests/test_performance.py +33 -0
- contextual_engine-0.8.1/tests/test_query_cache_roundtrip.py +39 -0
- contextual_engine-0.8.1/tests/test_retrieval.py +413 -0
- contextual_engine-0.8.1/tests/test_retry.py +29 -0
- contextual_engine-0.8.1/tests/test_security.py +29 -0
- contextual_engine-0.8.1/tests/test_storage.py +996 -0
- contextual_engine-0.2.0/AUDIT_LOG.md +0 -1114
- contextual_engine-0.2.0/FINAL_AUDIT.md +0 -706
- contextual_engine-0.2.0/RECOVERY_AUDIT.md +0 -348
- contextual_engine-0.2.0/contextual/cli/__init__.py +0 -144
- contextual_engine-0.2.0/contextual/cli/commands/__init__.py +0 -11
- contextual_engine-0.2.0/contextual/cli/commands/account.py +0 -18
- contextual_engine-0.2.0/contextual/cli/commands/client.py +0 -235
- contextual_engine-0.2.0/contextual/cli/commands/fetch.py +0 -99
- contextual_engine-0.2.0/contextual/cli/commands/serve.py +0 -11
- contextual_engine-0.2.0/contextual/cli/commands/stats.py +0 -61
- contextual_engine-0.2.0/contextual/cli/commands/temporal.py +0 -15
- contextual_engine-0.2.0/contextual/cli/core/decorators.py +0 -104
- contextual_engine-0.2.0/contextual/config/__init__.py +0 -103
- contextual_engine-0.2.0/contextual/config/indexing.py +0 -170
- contextual_engine-0.2.0/contextual/indexing/__init__.py +0 -139
- contextual_engine-0.2.0/contextual/indexing/file_watcher.py +0 -365
- contextual_engine-0.2.0/contextual/indexing/incremental.py +0 -391
- contextual_engine-0.2.0/contextual/indexing/pipeline.py +0 -825
- contextual_engine-0.2.0/contextual/integrations/__init__.py +0 -10
- contextual_engine-0.2.0/contextual/integrations/git_integration.py +0 -547
- contextual_engine-0.2.0/contextual/mcp/__init__.py +0 -15
- contextual_engine-0.2.0/contextual/mcp/__main__.py +0 -25
- contextual_engine-0.2.0/contextual/mcp/docs_tools.py +0 -325
- contextual_engine-0.2.0/contextual/mcp/server.py +0 -159
- contextual_engine-0.2.0/contextual/mcp/tools.py +0 -589
- contextual_engine-0.2.0/contextual/models/__init__.py +0 -439
- contextual_engine-0.2.0/contextual/models/base_embedder.py +0 -140
- contextual_engine-0.2.0/contextual/models/reranker_model.py +0 -195
- contextual_engine-0.2.0/contextual/models/unified_embedder.py +0 -205
- contextual_engine-0.2.0/contextual/observability/__init__.py +0 -21
- contextual_engine-0.2.0/contextual/observability/logging.py +0 -144
- contextual_engine-0.2.0/contextual/retrieval/__init__.py +0 -224
- contextual_engine-0.2.0/contextual/retrieval/pipeline.py +0 -543
- contextual_engine-0.2.0/contextual/retrieval/search.py +0 -636
- contextual_engine-0.2.0/contextual/storage/__init__.py +0 -134
- contextual_engine-0.2.0/contextual/storage/cache.py +0 -232
- contextual_engine-0.2.0/contextual/storage/connection.py +0 -453
- contextual_engine-0.2.0/contextual/storage/lancedb_provider.py +0 -1311
- contextual_engine-0.2.0/contextual/storage/schema.py +0 -510
- contextual_engine-0.2.0/docs/Architecture_Diagram.png +0 -0
- contextual_engine-0.2.0/docs/INTEGRATIONS.md +0 -530
- contextual_engine-0.2.0/pyproject.toml +0 -160
- contextual_engine-0.2.0/test_incremental.py +0 -165
- contextual_engine-0.2.0/test_mcp.py +0 -580
- contextual_engine-0.2.0/tests/conftest.py +0 -440
- contextual_engine-0.2.0/tests/test_accuracy_speed_async_integrity.py +0 -411
- contextual_engine-0.2.0/tests/test_architecture_security_flow.py +0 -523
- contextual_engine-0.2.0/tests/test_architecture_wiring.py +0 -730
- contextual_engine-0.2.0/tests/test_cross_file_chunk_batching.py +0 -142
- contextual_engine-0.2.0/tests/test_deduplication.py +0 -397
- contextual_engine-0.2.0/tests/test_expected_behavior.py +0 -890
- contextual_engine-0.2.0/tests/test_performance.py +0 -911
- contextual_engine-0.2.0/tests/test_purge_command.py +0 -43
- contextual_engine-0.2.0/tests/test_retry_logic.py +0 -79
- contextual_engine-0.2.0/tests/test_speed_accuracy.py +0 -813
- contextual_engine-0.2.0/tests/test_thread_safety.py +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/.contextualignore +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/.github/workflows/ci.yml +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/.gitignore +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/LICENSE +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/git/__init__.py +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/git/blame.py +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/security/paths.py +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/contextual/security/workspace.py +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/ADRs/ADR-001-lancedb-over-vec0.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/ADRs/ADR-002-retry-exponential-backoff.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/ADRs/ADR-003-blake3-deduplication.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/ADRs/ADR-004-async-first-architecture.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/ADRs/ADR-005-model-lineup.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/ARCHITECTURE.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/CHANGELOG.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DEPLOYMENT.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DISTRIBUTIONS.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/CHATGPT-DR-mcp-cli-security-testing-distribution.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/CHATGPT-DR-web-ui-experience.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/CLAUDE-DR-ai-agents-teams.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/CLAUDE-DR-competitive-landscape-market-analysis.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/CLAUDE-DR-core-architecture.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/CLAUDE-DR-mvp-phase0-technical-plan.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/CLAUDE-DR-strategic-briefing.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/GEMINI-DR-hybrid-retrieval-local-optimization.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/GEMINI-DR-infrastructure-security.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/GEMINI-DR-lance-specs.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/GEMINI-DR-vec0-vs-lancedb.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/KIMI-DR-tech-stack-optimization.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/PERPLEXITY-DR-indexing-optimisation.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/PERPLEXITY-DR-lancedb-implementation.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/PERPLEXITY-DR-local-data-infrastructure.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/PERPLEXITY-DR-mcp-security-hardening.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/PERPLEXITY-DR-models-pipelines.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/PERPLEXITY-DR-python-async-ai-pipelines.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/DRs/PERPLEXITY-DR-semantic-indexing.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/FRONTEND.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/GITHUB.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/PROJECT_MANAGEMENT.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/PROJECT_PHASES.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/RESOURCES.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/ROADMAP.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/SECURITY.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/TEAMS.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/TECHNICAL_SPEC.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/TESTING.md +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/docs/VERSION.MD +0 -0
- {contextual_engine-0.2.0 → contextual_engine-0.8.1}/tests/__init__.py +0 -0
- /contextual_engine-0.2.0/docs/MCP_TOOLS.md → /contextual_engine-0.8.1/tests/fixtures/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: contextual-engine
|
|
3
|
-
Version: 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 ::
|
|
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.
|
|
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:
|
|
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
|
[](https://pypi.org/project/contextual-engine/)
|
|
187
|
-
[](LICENSE)
|
|
202
|
+
[](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
|
-
|
|
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
|
[](https://pypi.org/project/contextual-engine/)
|
|
6
|
-
[](LICENSE)
|
|
7
|
+
[](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
|
-
|
|
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
|
-
|
|
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__ = "
|
|
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,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")
|