contextual-engine 0.8.6__tar.gz → 0.8.9__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.8.6 → contextual_engine-0.8.9}/.github/workflows/ci.yml +1 -15
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/.gitignore +1 -0
- contextual_engine-0.8.9/.mcp.json +11 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/PKG-INFO +1 -1
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/__init__.py +2 -1
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/cli/__init__.py +2 -3
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/cli/commands/client.py +52 -13
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/cli/commands/config.py +3 -3
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/cli/commands/doctor.py +8 -10
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/cli/commands/index.py +0 -1
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/cli/commands/install.py +1 -2
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/cli/commands/mcp.py +9 -6
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/cli/commands/stats.py +11 -10
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/cli/commands/workspace.py +2 -1
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/cli/core/output.py +11 -10
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/git/incremental_git.py +15 -5
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/graph/integrator.py +1 -3
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/graph/resolver.py +2 -2
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/graph/staleness.py +3 -4
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/graph/traversal.py +0 -3
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/incremental/daemon_embed.py +0 -4
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/incremental/incremental_indexer.py +3 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/indexing/chunker.py +1 -4
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/indexing/pipeline.py +1 -1
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/integrations/client_content.py +0 -1
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/__main__.py +0 -2
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/_platform.py +1 -2
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/config.py +1 -1
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/middleware/audit.py +6 -5
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/middleware/ratelimit.py +2 -3
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/middleware/warmup.py +6 -3
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/server.py +18 -3
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/shim.py +79 -14
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/tools/graph.py +50 -18
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/tools/nexus.py +18 -6
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/tools/semantic.py +36 -10
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/tools/system.py +6 -3
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/tools/temporal.py +39 -13
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/temporal/blame_pipeline.py +2 -2
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/temporal/context.py +3 -6
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/pyproject.toml +1 -1
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/conftest.py +1 -5
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_accuracy.py +0 -7
- contextual_engine-0.8.9/tests/test_architecture.py +23 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_async.py +0 -6
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_behaviour.py +0 -6
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_flow.py +0 -6
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_git.py +0 -9
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_latency.py +0 -9
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_mcp.py +0 -10
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_mcp_hardening.py +0 -1
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_observability.py +0 -9
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_performance.py +0 -10
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_retrieval.py +0 -4
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_retry.py +0 -6
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_security.py +0 -6
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_storage.py +7 -6
- contextual_engine-0.8.6/.mcp.json +0 -8
- contextual_engine-0.8.6/tests/test_architecture.py +0 -43
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/.contextualignore +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/.github/workflows/release.yml +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/LICENSE +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/README.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/__main__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/cli/commands/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/cli/commands/auth.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/cli/commands/fetch.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/cli/commands/initialisation.py +1 -1
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/cli/core/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/cli/core/context.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/cli/core/decorators.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/cli/core/editor.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/config/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/config/base.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/config/global_/__init__.py +2 -2
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/config/global_/mcp_config.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/config/global_/security_config.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/config/global_/storage_config.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/config/indexing.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/config/paths.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/config/workspace/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/config/workspace/cache_config.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/config/workspace/indexing_config.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/config/workspace/observability_config.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/config/workspace/retrieval_config.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/config/workspace/workspace_config.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/core/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/core/errors.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/core/models.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/git/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/git/blame.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/git/hooks.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/graph/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/graph/dedup.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/graph/extractor.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/graph/store.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/incremental/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/incremental/file_watcher.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/indexing/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/indexing/_config.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/indexing/docs_pipeline.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/indexing/index_writer.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/indexing/merkle_tree.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/indexing/processor.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/indexing/symbol_extractor.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/integrations/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/integrations/client_writer.py +1 -1
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/access.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/daemon.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/middleware/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/middleware/auth.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/middleware/identity.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/middleware/workspace.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/router.py +2 -2
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/session_manager.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/mcp/tools/__init__.py +1 -1
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/models/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/models/_inference.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/models/allowlist.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/models/base_embedder.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/models/reranker_model.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/models/unified_embedder.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/observability/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/observability/config.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/observability/exporters.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/observability/logging.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/observability/retention.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/observability/tracer.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/retrieval/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/retrieval/context_assembler.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/retrieval/mmr.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/retrieval/pipeline.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/retrieval/ranker.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/retrieval/tokenizer.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/security/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/security/paths.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/security/sanitize.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/security/workspace.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/cache.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/connection.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/fts.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/lancedb_provider.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/enterprise/me001_orgs.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/enterprise/me002_org_members.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/enterprise/me003_teams.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/enterprise/me004_team_members.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/enterprise/me005_org_workspaces.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/enterprise/me006_workspace_permissions.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/enterprise/me007_idp_sync_log.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/enterprise/me008_org_policies.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/enterprise/me009_api_keys.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/enterprise/me010_org_audit_log.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/enterprise/me011_workspace_traceability.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/m001_global.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/m002_embeddings.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/m003_temporal.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/m004_graph.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/m005_cache.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/m006_logs.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/m007_terminal_sessions.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/m008_queue.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/m009_swarm.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/m010_task_force.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/m011_reminders.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/m013_temporal_l2.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/m014_nexus_foundation.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/runner.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/solo/m001_global.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/solo/m002_embeddings.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/solo/m003_temporal.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/solo/m004_graph.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/solo/m005_cache.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/solo/m006_logs.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/solo/m007_terminal_sessions.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/solo/m008_queue.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/solo/m009_swarm.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/solo/m010_task_force.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/solo/m011_reminders.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/solo/m012_workspace_metadata.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/solo/m013_temporal_l2.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/solo/m014_nexus_foundation.py +1 -1
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/teams/mt001_orgs.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/teams/mt002_org_members.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/teams/mt003_teams.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/teams/mt004_team_members.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/teams/mt005_team_workspaces.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/teams/mt006_workspace_permissions.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/teams/mt007_team_audit_log.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/migrations/teams/mt008_workspace_traceability.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/schema.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/schema_base.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/schema_ent.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/storage/schema_team.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/temporal/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/temporal/adr.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/temporal/query.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/contextual/temporal/velocity.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/ADRs/ADR-001-lancedb-over-vec0.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/ADRs/ADR-002-retry-exponential-backoff.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/ADRs/ADR-003-blake3-deduplication.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/ADRs/ADR-004-async-first-architecture.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/ADRs/ADR-005-model-lineup.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/ARCHITECTURE.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/CHANGELOG.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DATABASE.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DEPLOYMENT.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DISTRIBUTIONS.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/CHATGPT-DR-mcp-cli-security-testing-distribution.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/CHATGPT-DR-web-ui-experience.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/CLAUDE-DR-ai-agents-teams.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/CLAUDE-DR-competitive-landscape-market-analysis.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/CLAUDE-DR-core-architecture.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/CLAUDE-DR-mvp-phase0-technical-plan.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/CLAUDE-DR-strategic-briefing.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/GEMINI-DR-graph-implementation.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/GEMINI-DR-hybrid-retrieval-local-optimization.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/GEMINI-DR-infrastructure-security.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/GEMINI-DR-lance-specs.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/GEMINI-DR-nexus-graph-architecture.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/GEMINI-DR-nexus-graph-engineering.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/GEMINI-DR-vec0-vs-lancedb.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/GRAPH_LAYER_OPEN_QUESTIONS_RESOLVED.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/KIMI-DR-tech-stack-optimization.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/PERPLEXITY-DR-L2-temporal.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/PERPLEXITY-DR-client-integration.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/PERPLEXITY-DR-indexing-optimisation.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/PERPLEXITY-DR-lancedb-implementation.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/PERPLEXITY-DR-local-data-infrastructure.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/PERPLEXITY-DR-mcp-config.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/PERPLEXITY-DR-mcp-security-hardening.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/PERPLEXITY-DR-models-pipelines.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/PERPLEXITY-DR-python-async-ai-pipelines.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/DRs/PERPLEXITY-DR-semantic-indexing.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/FRONTEND.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/GITHUB.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/INTEGRATIONS.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/MCP_TOOLS.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/MEMORY.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/PROJECT_MANAGEMENT.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/PROJECT_PHASES.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/RESOURCES.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/ROADMAP.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/SECURITY.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/TEAMS.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/TECHNICAL_SPEC.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/TESTING.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/docs/VERSION.MD +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/pytest.ini +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/README.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/fixtures/__init__.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/fixtures/sample_code.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/fixtures/sample_docs.md +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_cache_stats.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_cli.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_graph.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_graph_resolution_order.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_incremental.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_indexing.py +0 -0
- {contextual_engine-0.8.6 → contextual_engine-0.8.9}/tests/test_query_cache_roundtrip.py +0 -0
|
@@ -32,18 +32,4 @@ jobs:
|
|
|
32
32
|
cache-dependency-glob: uv.lock
|
|
33
33
|
|
|
34
34
|
- name: Install dependencies
|
|
35
|
-
run: uv sync
|
|
36
|
-
|
|
37
|
-
- name: Ruff check
|
|
38
|
-
run: uv run ruff check .
|
|
39
|
-
|
|
40
|
-
- name: Ruff format check
|
|
41
|
-
run: uv run ruff format --check .
|
|
42
|
-
|
|
43
|
-
- name: Mypy
|
|
44
|
-
run: uv run mypy contextual/ --strict
|
|
45
|
-
|
|
46
|
-
- name: Pytest
|
|
47
|
-
env:
|
|
48
|
-
NUMBA_DISABLE_JIT: "1"
|
|
49
|
-
run: uv run pytest tests/
|
|
35
|
+
run: uv sync --extra dev --extra test
|
|
@@ -6,7 +6,8 @@ through bi-temporal fact tracking and deterministic retrieval.
|
|
|
6
6
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
|
-
from importlib.metadata import PackageNotFoundError
|
|
9
|
+
from importlib.metadata import PackageNotFoundError
|
|
10
|
+
from importlib.metadata import version as _pkg_version
|
|
10
11
|
|
|
11
12
|
try:
|
|
12
13
|
__version__ = _pkg_version("contextual-engine")
|
|
@@ -15,6 +15,7 @@ from typing import Any
|
|
|
15
15
|
|
|
16
16
|
import typer
|
|
17
17
|
|
|
18
|
+
from contextual import __version__ # single source: pyproject.toml via importlib.metadata
|
|
18
19
|
from contextual.cli import commands
|
|
19
20
|
from contextual.cli.core.decorators import _COMMAND_REGISTRY
|
|
20
21
|
from contextual.cli.core.output import (
|
|
@@ -24,8 +25,6 @@ from contextual.cli.core.output import (
|
|
|
24
25
|
print_version,
|
|
25
26
|
)
|
|
26
27
|
|
|
27
|
-
from contextual import __version__ # single source: pyproject.toml via importlib.metadata
|
|
28
|
-
|
|
29
28
|
# ── Brand theme: override Typer's default Rich help colors ────────────
|
|
30
29
|
# Must run before typer.Typer() is instantiated.
|
|
31
30
|
try:
|
|
@@ -54,7 +53,7 @@ try:
|
|
|
54
53
|
_ru.STYLE_ERRORS_SUGGESTION = "#6b6b6b"
|
|
55
54
|
_ru.STYLE_ERRORS_SUGGESTION_COMMAND = "white bold"
|
|
56
55
|
_ru.STYLE_ABORTED = "#6b6b6b"
|
|
57
|
-
|
|
56
|
+
|
|
58
57
|
# Custom additions to ensure no yellow/cyan is shown
|
|
59
58
|
_ru.STYLE_COMMANDS_TABLE_FIRST_COLUMN = "white"
|
|
60
59
|
_ru.STYLE_DEPRECATED = "#6b6b6b"
|
|
@@ -14,29 +14,29 @@ from typing import Annotated
|
|
|
14
14
|
|
|
15
15
|
import typer
|
|
16
16
|
|
|
17
|
-
from contextual.cli.core import register_command, require_config
|
|
17
|
+
from contextual.cli.core import open_in_editor, register_command, require_config
|
|
18
18
|
from contextual.cli.core.output import (
|
|
19
19
|
console,
|
|
20
|
+
print_agents_md_hint,
|
|
20
21
|
print_client_configured,
|
|
22
|
+
print_client_list,
|
|
21
23
|
print_client_removed,
|
|
22
24
|
print_error,
|
|
23
25
|
print_info,
|
|
24
26
|
print_md_injected,
|
|
25
27
|
print_md_removed,
|
|
26
|
-
print_agents_md_hint,
|
|
27
|
-
print_client_list,
|
|
28
28
|
print_rm_not_configured,
|
|
29
29
|
)
|
|
30
30
|
from contextual.integrations.client_content import (
|
|
31
|
-
cursor_file_content,
|
|
32
31
|
antigravity_file_content,
|
|
32
|
+
cursor_file_content,
|
|
33
33
|
marker_block,
|
|
34
34
|
)
|
|
35
35
|
from contextual.integrations.client_writer import (
|
|
36
|
-
write_type_a,
|
|
37
|
-
write_type_b,
|
|
38
36
|
remove_type_a,
|
|
39
37
|
remove_type_b,
|
|
38
|
+
write_type_a,
|
|
39
|
+
write_type_b,
|
|
40
40
|
)
|
|
41
41
|
|
|
42
42
|
|
|
@@ -223,8 +223,30 @@ def _write_client_config(
|
|
|
223
223
|
return target, ("written" if found_key is None else "updated")
|
|
224
224
|
|
|
225
225
|
|
|
226
|
+
def _find_contextual_mcp() -> str | None:
|
|
227
|
+
"""Locate the pip-installed contextual-mcp binary.
|
|
228
|
+
|
|
229
|
+
Looks next to sys.executable first — this is the binary that was installed
|
|
230
|
+
alongside the package in the user's active Python environment (pyenv, conda,
|
|
231
|
+
virtualenv, plain pip). That lookup is independent of PATH, so it works
|
|
232
|
+
even in AI clients that inherit a minimal environment. Falls back to a
|
|
233
|
+
PATH search for edge cases. Returns None when neither finds it, in which
|
|
234
|
+
case callers should fall back to uvx.
|
|
235
|
+
"""
|
|
236
|
+
sibling = Path(sys.executable).resolve().parent / "contextual-mcp"
|
|
237
|
+
if sibling.exists():
|
|
238
|
+
return str(sibling)
|
|
239
|
+
return shutil.which("contextual-mcp")
|
|
240
|
+
|
|
241
|
+
|
|
226
242
|
def _build_mcp_entry(uvx_path: str, workspace_root: Path) -> dict:
|
|
227
243
|
"""Build the default MCP launcher entry for Contextual."""
|
|
244
|
+
local = _find_contextual_mcp()
|
|
245
|
+
if local:
|
|
246
|
+
return {
|
|
247
|
+
"command": local,
|
|
248
|
+
"args": ["--workspace", str(workspace_root)],
|
|
249
|
+
}
|
|
228
250
|
return {
|
|
229
251
|
"command": uvx_path,
|
|
230
252
|
"args": ["--from", "contextual-engine", "contextual-mcp", "--workspace", str(workspace_root)],
|
|
@@ -232,7 +254,15 @@ def _build_mcp_entry(uvx_path: str, workspace_root: Path) -> dict:
|
|
|
232
254
|
|
|
233
255
|
|
|
234
256
|
def _build_claude_mcp_entry(uvx_path: str, workspace_root: Path) -> dict:
|
|
235
|
-
"""Build the Claude Desktop MCP entry
|
|
257
|
+
"""Build the Claude Desktop MCP entry."""
|
|
258
|
+
local = _find_contextual_mcp()
|
|
259
|
+
if local:
|
|
260
|
+
return {
|
|
261
|
+
"command": local,
|
|
262
|
+
"args": ["--workspace", str(workspace_root)],
|
|
263
|
+
}
|
|
264
|
+
# uvx fallback: Claude Desktop has a minimal PATH so wrap in zsh -lc to
|
|
265
|
+
# ensure uvx is findable before exec-ing.
|
|
236
266
|
return {
|
|
237
267
|
"command": "/bin/zsh",
|
|
238
268
|
"args": [
|
|
@@ -252,6 +282,13 @@ def _build_vscode_mcp_entry(uvx_path: str, workspace_root: Path) -> dict:
|
|
|
252
282
|
VS Code requires an explicit ``"type": "stdio"`` field — other clients
|
|
253
283
|
accept entries without it.
|
|
254
284
|
"""
|
|
285
|
+
local = _find_contextual_mcp()
|
|
286
|
+
if local:
|
|
287
|
+
return {
|
|
288
|
+
"type": "stdio",
|
|
289
|
+
"command": local,
|
|
290
|
+
"args": ["--workspace", str(workspace_root)],
|
|
291
|
+
}
|
|
255
292
|
return {
|
|
256
293
|
"type": "stdio",
|
|
257
294
|
"command": uvx_path,
|
|
@@ -371,10 +408,12 @@ def _write_codex_toml_config(
|
|
|
371
408
|
original = copy.deepcopy(existing)
|
|
372
409
|
mcp_servers = existing.setdefault("mcp_servers", {})
|
|
373
410
|
ws_str = str(workspace_root.resolve())
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
"
|
|
377
|
-
|
|
411
|
+
local = _find_contextual_mcp()
|
|
412
|
+
entry = (
|
|
413
|
+
{"command": local, "args": ["--workspace", str(workspace_root)]}
|
|
414
|
+
if local
|
|
415
|
+
else {"command": uvx_path, "args": ["--from", "contextual-engine", "contextual-mcp", "--workspace", str(workspace_root)]}
|
|
416
|
+
)
|
|
378
417
|
|
|
379
418
|
# TOML entries embed the workspace in args (no shell wrapper), so resolve
|
|
380
419
|
# the bound workspace from the --workspace arg rather than via the shared
|
|
@@ -535,8 +574,8 @@ def _display_manual_config(
|
|
|
535
574
|
ui_steps: list[str],
|
|
536
575
|
) -> None:
|
|
537
576
|
"""Print manual setup instructions for UI-based MCP clients."""
|
|
538
|
-
from rich.syntax import Syntax
|
|
539
577
|
from rich.panel import Panel
|
|
578
|
+
from rich.syntax import Syntax
|
|
540
579
|
from rich.text import Text
|
|
541
580
|
|
|
542
581
|
cmd = (
|
|
@@ -594,7 +633,7 @@ def _config_paths() -> dict[str, Path]:
|
|
|
594
633
|
"copilot": home / ".vscode" / "mcp.json",
|
|
595
634
|
"windsurf": home / ".codeium" / "windsurf" / "mcp_config.json",
|
|
596
635
|
"codex": home / ".codex" / "config.toml",
|
|
597
|
-
"antigravity": home / ".
|
|
636
|
+
"antigravity": home / ".antigravity" / "mcp.json",
|
|
598
637
|
}
|
|
599
638
|
|
|
600
639
|
|
|
@@ -4,13 +4,13 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import tomllib
|
|
6
6
|
import uuid
|
|
7
|
-
from datetime import
|
|
7
|
+
from datetime import UTC, datetime
|
|
8
8
|
from pathlib import Path
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
import tomli_w
|
|
11
11
|
import typer
|
|
12
12
|
|
|
13
|
-
from contextual.cli.core import get_context, register_command, require_config
|
|
13
|
+
from contextual.cli.core import get_context, open_in_editor, register_command, require_config
|
|
14
14
|
from contextual.cli.core.output import print_error, print_info, print_success, print_warning
|
|
15
15
|
from contextual.config.paths import GLOBAL_CONFIG, workspace_config
|
|
16
16
|
from contextual.config.workspace.workspace_config import WorkspaceConfig
|
|
@@ -3,25 +3,23 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
|
-
|
|
7
|
-
import sys
|
|
8
|
-
from pathlib import Path
|
|
6
|
+
|
|
9
7
|
import typer
|
|
10
8
|
|
|
11
9
|
from contextual.cli.core import get_context, register_command
|
|
12
|
-
from contextual.cli.core.output import HealthCheck, print_doctor
|
|
13
|
-
from contextual.config.paths import MCP_CONFIG_FILE as MCP_JSON_PATH
|
|
10
|
+
from contextual.cli.core.output import HealthCheck, print_doctor
|
|
14
11
|
from contextual.config.paths import (
|
|
15
12
|
GLOBAL_CONFIG,
|
|
16
13
|
GLOBAL_DB_DIR,
|
|
17
|
-
MODELS_DIR,
|
|
18
14
|
LOG_DIR,
|
|
15
|
+
MODELS_DIR,
|
|
19
16
|
embed_model_present,
|
|
20
17
|
rerank_model_present,
|
|
21
18
|
workspace_config,
|
|
22
19
|
workspace_db,
|
|
23
20
|
workspace_logs,
|
|
24
21
|
)
|
|
22
|
+
from contextual.config.paths import MCP_CONFIG_FILE as MCP_JSON_PATH
|
|
25
23
|
|
|
26
24
|
|
|
27
25
|
@register_command()
|
|
@@ -37,7 +35,7 @@ async def doctor(
|
|
|
37
35
|
global_cfg_ok = GLOBAL_CONFIG.exists()
|
|
38
36
|
ws_cfg_path = workspace_config(workspace_path)
|
|
39
37
|
ws_cfg_ok = ws_cfg_path.exists()
|
|
40
|
-
|
|
38
|
+
|
|
41
39
|
if not global_cfg_ok:
|
|
42
40
|
config_status = False
|
|
43
41
|
config_detail = "Missing global config. Run 'contextual setup'."
|
|
@@ -64,7 +62,7 @@ async def doctor(
|
|
|
64
62
|
dirs_ok = True
|
|
65
63
|
missing_dirs = []
|
|
66
64
|
unwritable_dirs = []
|
|
67
|
-
|
|
65
|
+
|
|
68
66
|
for name, path in dirs_to_check:
|
|
69
67
|
if not path.exists():
|
|
70
68
|
dirs_ok = False
|
|
@@ -101,7 +99,7 @@ async def doctor(
|
|
|
101
99
|
daemon_running = False
|
|
102
100
|
lock_detail = "Daemon not running."
|
|
103
101
|
try:
|
|
104
|
-
from contextual.mcp.daemon import
|
|
102
|
+
from contextual.mcp.daemon import is_running, read_lock
|
|
105
103
|
lock = read_lock()
|
|
106
104
|
if lock and is_running(lock):
|
|
107
105
|
daemon_running = True
|
|
@@ -114,7 +112,7 @@ async def doctor(
|
|
|
114
112
|
db_ok = GLOBAL_DB_DIR.exists()
|
|
115
113
|
ws_db_path = workspace_db(workspace_path)
|
|
116
114
|
ws_db_ok = ws_db_path.exists()
|
|
117
|
-
|
|
115
|
+
|
|
118
116
|
if db_ok:
|
|
119
117
|
db_detail = "Global DB OK."
|
|
120
118
|
if ws_db_ok:
|
|
@@ -10,7 +10,6 @@ from datetime import UTC, datetime
|
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
|
|
12
12
|
import structlog
|
|
13
|
-
|
|
14
13
|
import typer
|
|
15
14
|
|
|
16
15
|
from contextual import __version__ as current_version
|
|
@@ -394,7 +393,7 @@ def hooks_install(path: str = "") -> None:
|
|
|
394
393
|
print_info(f"{icon} {hook_name} {status}")
|
|
395
394
|
|
|
396
395
|
print_success(
|
|
397
|
-
|
|
396
|
+
"Hooks installed",
|
|
398
397
|
detail=f"{repo_root / '.git' / 'hooks'} · auto-indexes on commit, checkout, merge",
|
|
399
398
|
)
|
|
400
399
|
|
|
@@ -3,16 +3,19 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import time
|
|
6
|
+
|
|
6
7
|
import typer
|
|
7
|
-
|
|
8
|
+
|
|
9
|
+
from contextual.cli.core import open_in_editor, register_command
|
|
8
10
|
from contextual.cli.core.output import (
|
|
11
|
+
console,
|
|
9
12
|
print_error,
|
|
10
13
|
print_info,
|
|
11
14
|
print_success,
|
|
12
15
|
print_warning,
|
|
13
|
-
console,
|
|
14
16
|
)
|
|
15
|
-
from contextual.config.paths import
|
|
17
|
+
from contextual.config.paths import DAEMON_LOG
|
|
18
|
+
from contextual.config.paths import MCP_CONFIG_FILE as MCP_JSON_PATH
|
|
16
19
|
|
|
17
20
|
|
|
18
21
|
@register_command(group="mcp")
|
|
@@ -81,7 +84,7 @@ def mcp_start() -> None:
|
|
|
81
84
|
@register_command(group="mcp")
|
|
82
85
|
def mcp_stop() -> None:
|
|
83
86
|
"""Stop the running MCP daemon."""
|
|
84
|
-
from contextual.mcp.daemon import
|
|
87
|
+
from contextual.mcp.daemon import read_lock, stop_daemon
|
|
85
88
|
|
|
86
89
|
lock = read_lock()
|
|
87
90
|
if not lock:
|
|
@@ -135,7 +138,7 @@ def mcp_logs(
|
|
|
135
138
|
return
|
|
136
139
|
|
|
137
140
|
try:
|
|
138
|
-
with open(DAEMON_LOG,
|
|
141
|
+
with open(DAEMON_LOG, encoding="utf-8") as f:
|
|
139
142
|
all_lines = f.readlines()
|
|
140
143
|
for line in all_lines[-lines:]:
|
|
141
144
|
console.print(line, highlight=False, end="")
|
|
@@ -145,7 +148,7 @@ def mcp_logs(
|
|
|
145
148
|
|
|
146
149
|
if follow:
|
|
147
150
|
try:
|
|
148
|
-
with open(DAEMON_LOG,
|
|
151
|
+
with open(DAEMON_LOG, encoding="utf-8") as f:
|
|
149
152
|
f.seek(0, 2)
|
|
150
153
|
while True:
|
|
151
154
|
line = f.readline()
|
|
@@ -4,15 +4,16 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from datetime import UTC
|
|
6
6
|
from typing import Any
|
|
7
|
+
|
|
7
8
|
import typer
|
|
8
9
|
|
|
9
10
|
from contextual.cli.core import get_context, register_command, require_config, require_index
|
|
10
11
|
from contextual.cli.core.output import (
|
|
11
12
|
print_error,
|
|
12
13
|
print_stats,
|
|
13
|
-
print_version,
|
|
14
|
-
print_stats_temporal,
|
|
15
14
|
print_stats_graph,
|
|
15
|
+
print_stats_temporal,
|
|
16
|
+
print_version,
|
|
16
17
|
)
|
|
17
18
|
from contextual.security.sanitize import sql_str_literal
|
|
18
19
|
|
|
@@ -96,7 +97,7 @@ async def stats(
|
|
|
96
97
|
.where(f"workspace_id = {sql_str_literal(cli_ctx.workspace_id)}")
|
|
97
98
|
.to_list()
|
|
98
99
|
)
|
|
99
|
-
|
|
100
|
+
|
|
100
101
|
def format_dt(val: Any) -> str:
|
|
101
102
|
if not val:
|
|
102
103
|
return "never"
|
|
@@ -111,13 +112,13 @@ async def stats(
|
|
|
111
112
|
total = len(records)
|
|
112
113
|
accepted = sum(1 for r in records if r.get("status") == "accepted")
|
|
113
114
|
proposed = sum(1 for r in records if r.get("status") == "proposed")
|
|
114
|
-
|
|
115
|
+
|
|
115
116
|
valid_ats = [r.get("valid_at") for r in records if r.get("valid_at")]
|
|
116
117
|
last_created = format_dt(max(valid_ats)) if valid_ats else "never"
|
|
117
|
-
|
|
118
|
+
|
|
118
119
|
accepted_valid_ats = [r.get("valid_at") for r in records if r.get("valid_at") and r.get("status") == "accepted"]
|
|
119
120
|
last_accepted = format_dt(max(accepted_valid_ats)) if accepted_valid_ats else "never"
|
|
120
|
-
|
|
121
|
+
|
|
121
122
|
temporal_stats.update({
|
|
122
123
|
"total": total,
|
|
123
124
|
"accepted": accepted,
|
|
@@ -133,7 +134,7 @@ async def stats(
|
|
|
133
134
|
if show_graph:
|
|
134
135
|
try:
|
|
135
136
|
graph_stats = {"entity_count": 0, "edge_count": 0, "predicates": {}, "languages": []}
|
|
136
|
-
|
|
137
|
+
|
|
137
138
|
langs = []
|
|
138
139
|
if await provider._connection.table_exists("code_chunks"):
|
|
139
140
|
code_table = await provider._connection.get_table("code_chunks")
|
|
@@ -145,7 +146,7 @@ async def stats(
|
|
|
145
146
|
.to_list()
|
|
146
147
|
)
|
|
147
148
|
langs = sorted(list({r["language"] for r in records if r.get("language")}))
|
|
148
|
-
|
|
149
|
+
|
|
149
150
|
entity_count = 0
|
|
150
151
|
if await provider._connection.table_exists("entities"):
|
|
151
152
|
table = await provider._connection.get_table("entities")
|
|
@@ -155,7 +156,7 @@ async def stats(
|
|
|
155
156
|
.to_list()
|
|
156
157
|
)
|
|
157
158
|
entity_count = len(records)
|
|
158
|
-
|
|
159
|
+
|
|
159
160
|
edge_count = 0
|
|
160
161
|
predicates = {}
|
|
161
162
|
if await provider._connection.table_exists("triples"):
|
|
@@ -170,7 +171,7 @@ async def stats(
|
|
|
170
171
|
p = r.get("predicate")
|
|
171
172
|
if p:
|
|
172
173
|
predicates[p] = predicates.get(p, 0) + 1
|
|
173
|
-
|
|
174
|
+
|
|
174
175
|
graph_stats.update({
|
|
175
176
|
"entity_count": entity_count,
|
|
176
177
|
"edge_count": edge_count,
|
|
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
6
|
from pathlib import Path
|
|
7
|
+
|
|
7
8
|
import typer
|
|
8
9
|
|
|
9
10
|
from contextual.cli.core import register_command
|
|
@@ -31,7 +32,7 @@ async def workspace_list() -> None:
|
|
|
31
32
|
for r in records:
|
|
32
33
|
path_str = r.get("path") or ""
|
|
33
34
|
ws_id = r.get("id") or ""
|
|
34
|
-
|
|
35
|
+
|
|
35
36
|
# Attempt to load last_indexed_at from state.json on disk if the path exists
|
|
36
37
|
last_indexed_at = "never"
|
|
37
38
|
if path_str:
|
|
@@ -18,8 +18,8 @@ Design system:
|
|
|
18
18
|
|
|
19
19
|
from __future__ import annotations
|
|
20
20
|
|
|
21
|
-
from collections.abc import Generator
|
|
22
21
|
import contextlib
|
|
22
|
+
from collections.abc import Generator
|
|
23
23
|
from dataclasses import dataclass
|
|
24
24
|
from typing import Any
|
|
25
25
|
|
|
@@ -100,6 +100,7 @@ def print_index_start(path: str) -> None:
|
|
|
100
100
|
|
|
101
101
|
import sys as _sys
|
|
102
102
|
|
|
103
|
+
|
|
103
104
|
class IndexProgressHandle:
|
|
104
105
|
"""Lightweight stdout-based stage printer. No threads, no Rich.Progress.
|
|
105
106
|
|
|
@@ -134,7 +135,7 @@ class IndexProgressHandle:
|
|
|
134
135
|
pass # no-op — Ollama style, no per-file updates
|
|
135
136
|
|
|
136
137
|
def finish_chunking(self, chunk_count: int = 0) -> None:
|
|
137
|
-
self._write(
|
|
138
|
+
self._write("done\n")
|
|
138
139
|
|
|
139
140
|
def start_embedding(self, total_chunks: int = 0) -> None:
|
|
140
141
|
self._write(f" Embedding + writing {self._DOTS} ")
|
|
@@ -370,7 +371,7 @@ def print_global_setup_complete(
|
|
|
370
371
|
padding=(0, 1),
|
|
371
372
|
)
|
|
372
373
|
)
|
|
373
|
-
console.print(
|
|
374
|
+
console.print(" [#6b6b6b]Next →[/#6b6b6b] [white]contextual fetch[/white]")
|
|
374
375
|
console.print()
|
|
375
376
|
|
|
376
377
|
|
|
@@ -628,7 +629,7 @@ def print_fetch_complete(downloaded: list[str], already_present: list[str]) -> N
|
|
|
628
629
|
padding=(0, 1),
|
|
629
630
|
)
|
|
630
631
|
)
|
|
631
|
-
console.print(
|
|
632
|
+
console.print(" [#6b6b6b]Next →[/#6b6b6b] [white]contextual init .[/white]")
|
|
632
633
|
console.print()
|
|
633
634
|
|
|
634
635
|
|
|
@@ -660,8 +661,8 @@ def print_purge_complete(workspace_name: str) -> None:
|
|
|
660
661
|
f"[white]{workspace_name}[/white] [#6b6b6b]fully deregistered[/#6b6b6b]"
|
|
661
662
|
)
|
|
662
663
|
console.print(
|
|
663
|
-
|
|
664
|
-
|
|
664
|
+
" [#6b6b6b]Run[/#6b6b6b] [white]contextual init .[/white] "
|
|
665
|
+
"[#6b6b6b]to reinitialise this workspace.[/#6b6b6b]"
|
|
665
666
|
)
|
|
666
667
|
console.print()
|
|
667
668
|
|
|
@@ -702,7 +703,7 @@ def print_init_already_done(workspace_id: str, path: str) -> None:
|
|
|
702
703
|
padding=(0, 2),
|
|
703
704
|
)
|
|
704
705
|
)
|
|
705
|
-
console.print(
|
|
706
|
+
console.print(" [#6b6b6b]Next →[/#6b6b6b] [white]contextual index .[/white]")
|
|
706
707
|
console.print()
|
|
707
708
|
|
|
708
709
|
|
|
@@ -733,7 +734,7 @@ def print_init_complete(
|
|
|
733
734
|
padding=(0, 1),
|
|
734
735
|
)
|
|
735
736
|
)
|
|
736
|
-
console.print(
|
|
737
|
+
console.print(" [#6b6b6b]Next →[/#6b6b6b] [white]contextual index .[/white]")
|
|
737
738
|
console.print()
|
|
738
739
|
|
|
739
740
|
|
|
@@ -843,7 +844,7 @@ def print_auth_stub(command: str) -> None:
|
|
|
843
844
|
f"[#6b6b6b]— coming in auth hardening session[/#6b6b6b]"
|
|
844
845
|
)
|
|
845
846
|
console.print(
|
|
846
|
-
|
|
847
|
-
|
|
847
|
+
" [#6b6b6b]Authentication via Clerk + Cryptolens will be "
|
|
848
|
+
"implemented pre-launch.[/#6b6b6b]"
|
|
848
849
|
)
|
|
849
850
|
console.print()
|
|
@@ -145,13 +145,22 @@ class GitIntegration:
|
|
|
145
145
|
unstaged = [item.decode("utf-8", errors="replace") for item in status.unstaged]
|
|
146
146
|
untracked = [item.decode("utf-8", errors="replace") for item in status.untracked]
|
|
147
147
|
|
|
148
|
+
seen: set[str] = set(added + modified + deleted)
|
|
148
149
|
for relative_path in unstaged + untracked:
|
|
149
|
-
if
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
150
|
+
if relative_path in seen:
|
|
151
|
+
continue
|
|
152
|
+
full = Path(self.repo_path) / relative_path
|
|
153
|
+
if full.is_dir():
|
|
154
|
+
# dulwich reports untracked dirs as a single entry; expand to files.
|
|
155
|
+
for child in full.rglob("*"):
|
|
156
|
+
if child.is_file():
|
|
157
|
+
child_rel = str(child.relative_to(self.repo_path))
|
|
158
|
+
if child_rel not in seen:
|
|
159
|
+
modified.append(child_rel)
|
|
160
|
+
seen.add(child_rel)
|
|
161
|
+
else:
|
|
154
162
|
modified.append(relative_path)
|
|
163
|
+
seen.add(relative_path)
|
|
155
164
|
|
|
156
165
|
return ChangedFiles(added=added, modified=modified, deleted=deleted)
|
|
157
166
|
|
|
@@ -274,6 +283,7 @@ def get_git_integration(repo_path: Path | str) -> GitIntegration:
|
|
|
274
283
|
|
|
275
284
|
import atexit
|
|
276
285
|
|
|
286
|
+
|
|
277
287
|
def _cleanup_git_repos() -> None:
|
|
278
288
|
for integration in list(_git_integration_cache.values()):
|
|
279
289
|
integration.close()
|
|
@@ -17,9 +17,8 @@ process pool can be reintroduced behind the same interface if ever needed.
|
|
|
17
17
|
from __future__ import annotations
|
|
18
18
|
|
|
19
19
|
import asyncio
|
|
20
|
-
from datetime import datetime, timezone
|
|
21
|
-
import math
|
|
22
20
|
from dataclasses import dataclass, field
|
|
21
|
+
from datetime import datetime
|
|
23
22
|
from typing import Any
|
|
24
23
|
|
|
25
24
|
import structlog
|
|
@@ -510,7 +509,6 @@ def _make_graph_result(content: str, query: str) -> Any:
|
|
|
510
509
|
|
|
511
510
|
|
|
512
511
|
def _compute_staleness(node: dict | None = None, *, change_velocity: float | None = None, valid_at: datetime | None = None) -> float:
|
|
513
|
-
from contextual.graph.staleness import compute_staleness
|
|
514
512
|
if node is not None:
|
|
515
513
|
change_velocity = node.get("change_velocity")
|
|
516
514
|
valid_at = node.get("valid_at")
|
|
@@ -40,11 +40,11 @@ CONFIDENCE_FLOOR = 0.55
|
|
|
40
40
|
# Avoids a 500 K-row LanceDB scan per incremental-indexing file event.
|
|
41
41
|
# Entries are invalidated by invalidate_registry_cache() after a full re-index
|
|
42
42
|
# and expire naturally after _REGISTRY_TTL_SECONDS of inactivity.
|
|
43
|
-
_registry_cache: dict[str, tuple[
|
|
43
|
+
_registry_cache: dict[str, tuple[FunctionRegistry, float]] = {}
|
|
44
44
|
_REGISTRY_TTL_SECONDS: float = 120.0 # 2 minutes
|
|
45
45
|
|
|
46
46
|
|
|
47
|
-
async def get_or_build_registry(connector: Any, workspace_id: str) ->
|
|
47
|
+
async def get_or_build_registry(connector: Any, workspace_id: str) -> FunctionRegistry:
|
|
48
48
|
"""Return a cached FunctionRegistry for workspace_id, rebuilding if stale.
|
|
49
49
|
|
|
50
50
|
Thread-safe for a single async event loop (no lock needed — coroutines
|
|
@@ -16,8 +16,7 @@ Used in two places:
|
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
|
|
18
18
|
import math
|
|
19
|
-
from datetime import
|
|
20
|
-
|
|
19
|
+
from datetime import UTC, datetime
|
|
21
20
|
|
|
22
21
|
# Staleness thresholds
|
|
23
22
|
STALENESS_FRESH = 0.0 # definitely stable / recently updated
|
|
@@ -70,9 +69,9 @@ def compute_staleness(
|
|
|
70
69
|
return 0.0
|
|
71
70
|
|
|
72
71
|
# Ensure timezone-aware comparison
|
|
73
|
-
now = datetime.now(
|
|
72
|
+
now = datetime.now(UTC)
|
|
74
73
|
if valid_at.tzinfo is None:
|
|
75
|
-
valid_at = valid_at.replace(tzinfo=
|
|
74
|
+
valid_at = valid_at.replace(tzinfo=UTC)
|
|
76
75
|
|
|
77
76
|
days_since = max(0.0, (now - valid_at).total_seconds() / 86400.0)
|
|
78
77
|
recency_decay = math.exp(-days_since / decay_constant)
|
|
@@ -15,13 +15,10 @@ Performance targets (Python BFS @ ~1M edges): depth-1 < 50ms, depth-5 < 200ms.
|
|
|
15
15
|
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
|
|
18
|
-
import math
|
|
19
18
|
from typing import Any
|
|
20
19
|
|
|
21
20
|
import structlog
|
|
22
21
|
|
|
23
|
-
from contextual.graph.staleness import compute_staleness
|
|
24
|
-
|
|
25
22
|
logger = structlog.get_logger(__name__)
|
|
26
23
|
|
|
27
24
|
# Only follow edges at/above this confidence by default (drops fuzzy edges).
|