devloop 0.6.4__tar.gz → 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. {devloop-0.6.4 → devloop-0.7.0}/PKG-INFO +41 -1
  2. {devloop-0.6.4 → devloop-0.7.0}/README.md +40 -0
  3. {devloop-0.6.4 → devloop-0.7.0}/pyproject.toml +35 -7
  4. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/agents/code_rabbit.py +8 -10
  5. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/agents/test_runner.py +4 -0
  6. devloop-0.7.0/src/devloop/cli/coderabbit_installer.py +189 -0
  7. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/main.py +273 -202
  8. devloop-0.7.0/src/devloop/cli/snyk_installer.py +189 -0
  9. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/agent.py +11 -2
  10. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/auto_fix.py +46 -0
  11. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/context_store.py +2 -0
  12. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/daemon_health.py +2 -0
  13. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/pattern_detector.py +2 -0
  14. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/telemetry.py +10 -10
  15. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/security/factory.py +2 -2
  16. {devloop-0.6.4 → devloop-0.7.0}/LICENSE +0 -0
  17. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/__init__.py +0 -0
  18. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/agents/__init__.py +0 -0
  19. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/agents/agent_health_monitor.py +0 -0
  20. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/agents/ci_monitor.py +0 -0
  21. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/agents/doc_lifecycle.py +0 -0
  22. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/agents/echo.py +0 -0
  23. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/agents/file_logger.py +0 -0
  24. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/agents/formatter.py +0 -0
  25. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/agents/git_commit_assistant.py +0 -0
  26. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/agents/linter.py +0 -0
  27. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/agents/performance_profiler.py +0 -0
  28. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/agents/sandbox_helper.py +0 -0
  29. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/agents/security_scanner.py +0 -0
  30. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/agents/snyk.py +0 -0
  31. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/agents/type_checker.py +0 -0
  32. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/__init__.py +0 -0
  33. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/agent_rules.py +0 -0
  34. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/commands/__init__.py +0 -0
  35. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/commands/agent_publish.py +0 -0
  36. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/commands/audit.py +0 -0
  37. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/commands/custom_agents.py +0 -0
  38. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/commands/feedback.py +0 -0
  39. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/commands/marketplace.py +0 -0
  40. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/commands/marketplace_server.py +0 -0
  41. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/commands/metrics.py +0 -0
  42. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/commands/release.py +0 -0
  43. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/commands/summary.py +0 -0
  44. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/commands/telemetry.py +0 -0
  45. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/commands/tools.py +0 -0
  46. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/main_v1.py +0 -0
  47. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/pre_push_check.py +0 -0
  48. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/prerequisites.py +0 -0
  49. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/pyodide_installer.py +0 -0
  50. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/templates/.devloop/tools-registry.json +0 -0
  51. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/templates/claude_commands/README.md +0 -0
  52. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/templates/claude_commands/agent-summary.md +0 -0
  53. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/templates/claude_commands/devloop-findings.md +0 -0
  54. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/templates/claude_commands/devloop-status.md +0 -0
  55. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/templates/claude_commands/extract-findings.md +0 -0
  56. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/templates/claude_commands/verify-work.md +0 -0
  57. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/templates/devloop_agents_template.md +0 -0
  58. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/templates/git_hooks/post-commit +0 -0
  59. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/templates/git_hooks/pre-commit +0 -0
  60. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/templates/git_hooks/pre-commit-checks +0 -0
  61. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/templates/git_hooks/pre-push +0 -0
  62. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/templates/supervisor/devloop.conf +0 -0
  63. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/cli/templates/systemd/devloop.service +0 -0
  64. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/collectors/__init__.py +0 -0
  65. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/collectors/base.py +0 -0
  66. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/collectors/filesystem.py +0 -0
  67. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/collectors/git.py +0 -0
  68. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/collectors/manager.py +0 -0
  69. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/collectors/process.py +0 -0
  70. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/collectors/system.py +0 -0
  71. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/__init__.py +0 -0
  72. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/action_logger.py +0 -0
  73. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/agent_audit_logger.py +0 -0
  74. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/agent_template.py +0 -0
  75. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/amp_integration.py +0 -0
  76. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/amp_thread_mapper.py +0 -0
  77. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/backup_manager.py +0 -0
  78. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/claude_adapter.py +0 -0
  79. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/config.py +0 -0
  80. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/config_schema.py +0 -0
  81. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/context.py +0 -0
  82. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/contextual_feedback.py +0 -0
  83. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/custom_agent.py +0 -0
  84. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/debug_trace.py +0 -0
  85. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/error_handler.py +0 -0
  86. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/error_notifier.py +0 -0
  87. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/event.py +0 -0
  88. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/event_replayer.py +0 -0
  89. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/event_store.py +0 -0
  90. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/feedback.py +0 -0
  91. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/file_lock_manager.py +0 -0
  92. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/learning.py +0 -0
  93. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/manager.py +0 -0
  94. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/operational_health.py +0 -0
  95. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/pattern_analyzer.py +0 -0
  96. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/performance.py +0 -0
  97. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/proactive_feedback.py +0 -0
  98. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/project_context.py +0 -0
  99. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/summary_formatter.py +0 -0
  100. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/summary_generator.py +0 -0
  101. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/tool_dependencies.py +0 -0
  102. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/tool_registry.py +0 -0
  103. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/tool_runner.py +0 -0
  104. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/core/transactional_io.py +0 -0
  105. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/integrations/__init__.py +0 -0
  106. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/integrations/beads_integration.py +0 -0
  107. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/lsp/__init__.py +0 -0
  108. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/lsp/__main__.py +0 -0
  109. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/lsp/mapper.py +0 -0
  110. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/lsp/server.py +0 -0
  111. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/marketplace/__init__.py +0 -0
  112. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/marketplace/api.py +0 -0
  113. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/marketplace/cache.py +0 -0
  114. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/marketplace/http_server.py +0 -0
  115. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/marketplace/installer.py +0 -0
  116. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/marketplace/metadata.py +0 -0
  117. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/marketplace/publisher.py +0 -0
  118. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/marketplace/registry.py +0 -0
  119. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/marketplace/registry_client.py +0 -0
  120. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/marketplace/reviews.py +0 -0
  121. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/marketplace/search.py +0 -0
  122. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/marketplace/signing.py +0 -0
  123. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/metrics/__init__.py +0 -0
  124. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/metrics/dora.py +0 -0
  125. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/metrics/value_metrics.py +0 -0
  126. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/providers/__init__.py +0 -0
  127. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/providers/artifactory_registry.py +0 -0
  128. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/providers/ci_provider.py +0 -0
  129. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/providers/circleci_provider.py +0 -0
  130. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/providers/github_actions_provider.py +0 -0
  131. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/providers/gitlab_ci_provider.py +0 -0
  132. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/providers/jenkins_provider.py +0 -0
  133. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/providers/provider_manager.py +0 -0
  134. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/providers/pypi_registry.py +0 -0
  135. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/providers/registry_provider.py +0 -0
  136. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/release/__init__.py +0 -0
  137. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/release/release_manager.py +0 -0
  138. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/security/__init__.py +0 -0
  139. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/security/audit_logger.py +0 -0
  140. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/security/bubblewrap_sandbox.py +0 -0
  141. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/security/cgroups_helper.py +0 -0
  142. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/security/no_sandbox.py +0 -0
  143. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/security/package.json +0 -0
  144. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/security/path_validator.py +0 -0
  145. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/security/pyodide_runner.js +0 -0
  146. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/security/pyodide_sandbox.py +0 -0
  147. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/security/sandbox.py +0 -0
  148. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/security/token_manager.py +0 -0
  149. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/telemetry/__init__.py +0 -0
  150. {devloop-0.6.4 → devloop-0.7.0}/src/devloop/telemetry/telemetry_manager.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devloop
3
- Version: 0.6.4
3
+ Version: 0.7.0
4
4
  Summary: Intelligent background agents for development workflow automation
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -1405,6 +1405,46 @@ devloop custom-list
1405
1405
  ls -la .devloop/custom_agents/
1406
1406
  ```
1407
1407
 
1408
+ ### Snyk or CodeRabbit not working
1409
+
1410
+ **Snyk Agent Issues:**
1411
+
1412
+ ```bash
1413
+ # Verify Snyk CLI is installed
1414
+ snyk --version
1415
+
1416
+ # Check authentication
1417
+ snyk auth status
1418
+
1419
+ # Re-authenticate if needed
1420
+ snyk auth
1421
+
1422
+ # Verify token is set
1423
+ echo $SNYK_TOKEN
1424
+
1425
+ # Test manually
1426
+ snyk test --json
1427
+ ```
1428
+
1429
+ **CodeRabbit Agent Issues:**
1430
+
1431
+ ```bash
1432
+ # Verify CodeRabbit CLI is installed
1433
+ coderabbit --version
1434
+
1435
+ # Check API key is set
1436
+ echo $CODE_RABBIT_API_KEY
1437
+
1438
+ # Test manually
1439
+ coderabbit review --format json <file>
1440
+ ```
1441
+
1442
+ **Common Issues:**
1443
+ - **"CLI not installed"** — Install via `npm install -g snyk` or `npm install -g @code-rabbit/cli`
1444
+ - **"Authentication failed"** — Re-run `snyk auth` or verify `CODE_RABBIT_API_KEY`
1445
+ - **"No vulnerabilities found but expected some"** — Ensure dependency files exist (package.json, requirements.txt, etc.)
1446
+ - **Agent not triggering** — Check file patterns in `.devloop/agents.json` match your dependency files
1447
+
1408
1448
  ### Agent modified my files unexpectedly
1409
1449
 
1410
1450
  1. Check git diff: `git diff`
@@ -1364,6 +1364,46 @@ devloop custom-list
1364
1364
  ls -la .devloop/custom_agents/
1365
1365
  ```
1366
1366
 
1367
+ ### Snyk or CodeRabbit not working
1368
+
1369
+ **Snyk Agent Issues:**
1370
+
1371
+ ```bash
1372
+ # Verify Snyk CLI is installed
1373
+ snyk --version
1374
+
1375
+ # Check authentication
1376
+ snyk auth status
1377
+
1378
+ # Re-authenticate if needed
1379
+ snyk auth
1380
+
1381
+ # Verify token is set
1382
+ echo $SNYK_TOKEN
1383
+
1384
+ # Test manually
1385
+ snyk test --json
1386
+ ```
1387
+
1388
+ **CodeRabbit Agent Issues:**
1389
+
1390
+ ```bash
1391
+ # Verify CodeRabbit CLI is installed
1392
+ coderabbit --version
1393
+
1394
+ # Check API key is set
1395
+ echo $CODE_RABBIT_API_KEY
1396
+
1397
+ # Test manually
1398
+ coderabbit review --format json <file>
1399
+ ```
1400
+
1401
+ **Common Issues:**
1402
+ - **"CLI not installed"** — Install via `npm install -g snyk` or `npm install -g @code-rabbit/cli`
1403
+ - **"Authentication failed"** — Re-run `snyk auth` or verify `CODE_RABBIT_API_KEY`
1404
+ - **"No vulnerabilities found but expected some"** — Ensure dependency files exist (package.json, requirements.txt, etc.)
1405
+ - **Agent not triggering** — Check file patterns in `.devloop/agents.json` match your dependency files
1406
+
1367
1407
  ### Agent modified my files unexpectedly
1368
1408
 
1369
1409
  1. Check git diff: `git diff`
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "devloop"
3
- version = "0.6.4"
3
+ version = "0.7.0"
4
4
  description = "Intelligent background agents for development workflow automation"
5
5
  authors = ["DevLoop Contributors <devloop@example.com>"]
6
6
  license = "MIT"
@@ -53,12 +53,16 @@ lsprotocol = "^2023.0.0"
53
53
  [tool.poetry.group.dev.dependencies]
54
54
  pytest = "^7.4"
55
55
  pytest-asyncio = "^0.21"
56
+ pytest-cov = "^4.1"
56
57
  black = "^23.12"
57
58
  ruff = "^0.1"
58
59
  mypy = "^1.8"
59
60
  bandit = "^1.7"
60
61
  radon = "^6.0"
61
62
  types-aiofiles = "^23.2"
63
+ pytest-rerunfailures = "^16.1"
64
+ types-pyyaml = "^6.0.12.20250915"
65
+ types-psutil = "^7.2.1.20251231"
62
66
 
63
67
  [tool.poetry.extras]
64
68
  snyk = []
@@ -92,19 +96,43 @@ markers = [
92
96
  "security: marks tests as security tests",
93
97
  "benchmark: marks tests as benchmarks",
94
98
  ]
99
+ addopts = "--cov=src/devloop --cov-report=term-missing --cov-report=html --cov-report=xml"
100
+
101
+ [tool.coverage.run]
102
+ source = ["src/devloop"]
103
+ omit = [
104
+ "*/tests/*",
105
+ "*/test_*.py",
106
+ "*/__pycache__/*",
107
+ "*/site-packages/*",
108
+ ]
109
+
110
+ [tool.coverage.report]
111
+ precision = 2
112
+ show_missing = true
113
+ skip_covered = false
114
+ exclude_lines = [
115
+ "pragma: no cover",
116
+ "def __repr__",
117
+ "raise AssertionError",
118
+ "raise NotImplementedError",
119
+ "if __name__ == .__main__.:",
120
+ "if TYPE_CHECKING:",
121
+ "if typing.TYPE_CHECKING:",
122
+ ]
95
123
 
96
124
  [tool.mypy]
97
- python_version = "0.4.1"
125
+ python_version = "3.11"
98
126
  warn_return_any = false
99
- warn_unused_configs = false
127
+ warn_unused_configs = true
100
128
  disallow_untyped_defs = false
101
129
  disallow_incomplete_defs = false
102
130
  check_untyped_defs = false
103
131
  disallow_untyped_decorators = false
104
132
  no_implicit_optional = false
105
- warn_redundant_casts = false
106
- warn_unused_ignores = false
107
- warn_no_return = false
133
+ warn_redundant_casts = true
134
+ warn_unused_ignores = true
135
+ warn_no_return = true
108
136
  follow_imports = "normal"
109
- ignore_missing_imports = true
137
+ ignore_missing_imports = false
110
138
  show_error_codes = true
@@ -144,9 +144,9 @@ class CodeRabbitAgent(Agent):
144
144
  async def _run_code_rabbit(self, path: Path) -> CodeRabbitResult:
145
145
  """Run Code Rabbit analysis on a file."""
146
146
  try:
147
- # Check if code-rabbit CLI is installed
147
+ # Check if coderabbit CLI is installed
148
148
  check = await asyncio.create_subprocess_exec(
149
- "code-rabbit",
149
+ "coderabbit",
150
150
  "--version",
151
151
  stdout=asyncio.subprocess.PIPE,
152
152
  stderr=asyncio.subprocess.PIPE,
@@ -155,13 +155,13 @@ class CodeRabbitAgent(Agent):
155
155
 
156
156
  if check.returncode != 0:
157
157
  return CodeRabbitResult(
158
- success=False, error="code-rabbit CLI not installed"
158
+ success=False, error="coderabbit CLI not installed"
159
159
  )
160
160
 
161
- # Run Code Rabbit with JSON output
161
+ # Run CodeRabbit with JSON output (review command)
162
162
  proc = await asyncio.create_subprocess_exec(
163
- "code-rabbit",
164
- "analyze",
163
+ "coderabbit",
164
+ "review",
165
165
  "--format",
166
166
  "json",
167
167
  str(path),
@@ -174,7 +174,7 @@ class CodeRabbitAgent(Agent):
174
174
  if proc.returncode != 0 and not stdout:
175
175
  return CodeRabbitResult(
176
176
  success=False,
177
- error=f"code-rabbit failed: {stderr.decode() if stderr else 'unknown error'}",
177
+ error=f"coderabbit failed: {stderr.decode() if stderr else 'unknown error'}",
178
178
  )
179
179
 
180
180
  if stdout:
@@ -190,9 +190,7 @@ class CodeRabbitAgent(Agent):
190
190
  return CodeRabbitResult(success=True, issues=[])
191
191
 
192
192
  except FileNotFoundError:
193
- return CodeRabbitResult(
194
- success=False, error="code-rabbit command not found"
195
- )
193
+ return CodeRabbitResult(success=False, error="coderabbit command not found")
196
194
  except Exception as e:
197
195
  self.logger.error(f"Error running Code Rabbit: {e}")
198
196
  return CodeRabbitResult(success=False, error=str(e))
@@ -17,6 +17,8 @@ from devloop.core.project_context import ProjectContext
17
17
  class TestRunnerConfig:
18
18
  """Configuration for TestRunnerAgent."""
19
19
 
20
+ __test__ = False # Not a pytest test class
21
+
20
22
  def __init__(self, config: Dict[str, Any]):
21
23
  self.enabled = config.get("enabled", True)
22
24
  self.run_on_save = config.get("runOnSave", True)
@@ -154,6 +156,8 @@ class TestResult:
154
156
  class TestRunnerAgent(Agent):
155
157
  """Agent that runs tests when files change."""
156
158
 
159
+ __test__ = False # Not a pytest test class
160
+
157
161
  def __init__(
158
162
  self,
159
163
  name: str,
@@ -0,0 +1,189 @@
1
+ """CodeRabbit CLI installation helper for devloop init command."""
2
+
3
+ import os
4
+ import shutil
5
+ import subprocess
6
+ from typing import Tuple
7
+
8
+ import typer
9
+ from rich.console import Console
10
+
11
+ console = Console()
12
+
13
+
14
+ def check_coderabbit_available() -> Tuple[bool, str]:
15
+ """Check if CodeRabbit CLI is available.
16
+
17
+ Returns:
18
+ Tuple of (is_available, version_or_error)
19
+ """
20
+ coderabbit_path = shutil.which("coderabbit")
21
+ if not coderabbit_path:
22
+ return False, "CodeRabbit CLI not found in PATH"
23
+
24
+ try:
25
+ result = subprocess.run(
26
+ ["coderabbit", "--version"],
27
+ capture_output=True,
28
+ text=True,
29
+ timeout=5,
30
+ )
31
+ if result.returncode == 0:
32
+ version = result.stdout.strip()
33
+ return True, version
34
+ else:
35
+ return False, "Failed to get CodeRabbit version"
36
+ except Exception as e:
37
+ return False, str(e)
38
+
39
+
40
+ def check_coderabbit_api_key() -> bool:
41
+ """Check if CODE_RABBIT_API_KEY environment variable is set.
42
+
43
+ Returns:
44
+ True if CODE_RABBIT_API_KEY is set and non-empty
45
+ """
46
+ api_key = os.environ.get("CODE_RABBIT_API_KEY", "").strip()
47
+ return bool(api_key)
48
+
49
+
50
+ def install_coderabbit_cli() -> bool:
51
+ """Install CodeRabbit CLI using the official installer script.
52
+
53
+ Returns:
54
+ True if installation succeeded, False otherwise
55
+ """
56
+ try:
57
+ # Check if curl is available
58
+ curl_path = shutil.which("curl")
59
+ if not curl_path:
60
+ console.print("[red]✗[/red] curl not found. Please install curl first.")
61
+ return False
62
+
63
+ # Check if sh is available
64
+ sh_path = shutil.which("sh")
65
+ if not sh_path:
66
+ console.print("[red]✗[/red] sh shell not found.")
67
+ return False
68
+
69
+ # Run the CodeRabbit installer
70
+ console.print(" Installing CodeRabbit CLI...")
71
+ console.print(" Running: curl -fsSL https://cli.coderabbit.ai/install.sh | sh")
72
+
73
+ # Download and run installer
74
+ result = subprocess.run(
75
+ ["sh", "-c", "curl -fsSL https://cli.coderabbit.ai/install.sh | sh"],
76
+ capture_output=True,
77
+ text=True,
78
+ timeout=180, # 3 minutes timeout
79
+ )
80
+
81
+ if result.returncode == 0:
82
+ console.print(" [green]✓[/green] CodeRabbit CLI installed successfully")
83
+ return True
84
+ else:
85
+ console.print("[red]✗[/red] Installation failed:")
86
+ if result.stderr:
87
+ console.print(f" {result.stderr}")
88
+ return False
89
+
90
+ except subprocess.TimeoutExpired:
91
+ console.print("[red]✗[/red] Installation timed out (>3 minutes)")
92
+ return False
93
+ except Exception as e:
94
+ console.print(f"[red]✗[/red] Installation failed: {e}")
95
+ return False
96
+
97
+
98
+ def authenticate_coderabbit() -> bool:
99
+ """Authenticate CodeRabbit CLI.
100
+
101
+ CodeRabbit CLI uses CODE_RABBIT_API_KEY environment variable for authentication.
102
+ The 'coderabbit auth' command may be used for interactive authentication.
103
+
104
+ Returns:
105
+ True if authentication is configured, False otherwise
106
+ """
107
+ try:
108
+ api_key = os.environ.get("CODE_RABBIT_API_KEY", "").strip()
109
+ if not api_key:
110
+ console.print(
111
+ "[yellow]⚠[/yellow] CODE_RABBIT_API_KEY environment variable not set"
112
+ )
113
+ console.print(" Set CODE_RABBIT_API_KEY before running CodeRabbit scans")
114
+ console.print(" Or run 'coderabbit auth' for interactive authentication")
115
+ return False
116
+
117
+ console.print(" [green]✓[/green] CODE_RABBIT_API_KEY is configured")
118
+ return True
119
+
120
+ except Exception as e:
121
+ console.print(f"[yellow]⚠[/yellow] Authentication check failed: {e}")
122
+ return False
123
+
124
+
125
+ def prompt_coderabbit_installation(non_interactive: bool = False) -> bool:
126
+ """Prompt user to install CodeRabbit CLI and perform installation.
127
+
128
+ Args:
129
+ non_interactive: If True, skip prompts and return success
130
+
131
+ Returns:
132
+ True if CodeRabbit was installed/configured (or user declined), False on critical error
133
+ """
134
+ if non_interactive:
135
+ return True # Skip in non-interactive mode
136
+
137
+ # Check if CodeRabbit CLI is already installed
138
+ coderabbit_available, coderabbit_info = check_coderabbit_available()
139
+
140
+ if coderabbit_available:
141
+ console.print(
142
+ f"\n[green]✓[/green] CodeRabbit CLI already installed: {coderabbit_info}"
143
+ )
144
+
145
+ # Check authentication
146
+ if not check_coderabbit_api_key():
147
+ console.print(
148
+ " [yellow]Note:[/yellow] Set CODE_RABBIT_API_KEY environment variable to authenticate"
149
+ )
150
+ console.print(" Or run 'coderabbit auth' manually later")
151
+ else:
152
+ authenticate_coderabbit()
153
+
154
+ return True
155
+
156
+ # CodeRabbit not installed - offer to install
157
+ console.print("\n[yellow]CodeRabbit CLI Installation[/yellow]")
158
+ console.print(
159
+ "CodeRabbit CLI is not installed. It's required for AI-powered code analysis."
160
+ )
161
+
162
+ if typer.confirm(
163
+ " Install CodeRabbit CLI now using the official installer?", default=True
164
+ ):
165
+ if install_coderabbit_cli():
166
+ # Check authentication
167
+ if not check_coderabbit_api_key():
168
+ console.print(
169
+ "\n [yellow]Next steps:[/yellow] Set CODE_RABBIT_API_KEY environment variable"
170
+ )
171
+ console.print(
172
+ " Or run 'coderabbit auth' for interactive authentication"
173
+ )
174
+ else:
175
+ authenticate_coderabbit()
176
+ return True
177
+ else:
178
+ console.print(
179
+ "\n [yellow]You can install CodeRabbit manually later:[/yellow]"
180
+ )
181
+ console.print(" curl -fsSL https://cli.coderabbit.ai/install.sh | sh")
182
+ console.print(" coderabbit auth")
183
+ return False
184
+ else:
185
+ console.print(" Skipped CodeRabbit CLI installation")
186
+ console.print(
187
+ " [yellow]Install later with:[/yellow] curl -fsSL https://cli.coderabbit.ai/install.sh | sh"
188
+ )
189
+ return True