@voria/cli 0.0.2

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 (67) hide show
  1. package/README.md +439 -0
  2. package/bin/voria +730 -0
  3. package/docs/ARCHITECTURE.md +419 -0
  4. package/docs/CHANGELOG.md +189 -0
  5. package/docs/CONTRIBUTING.md +447 -0
  6. package/docs/DESIGN_DECISIONS.md +380 -0
  7. package/docs/DEVELOPMENT.md +535 -0
  8. package/docs/EXAMPLES.md +434 -0
  9. package/docs/INSTALL.md +335 -0
  10. package/docs/IPC_PROTOCOL.md +310 -0
  11. package/docs/LLM_INTEGRATION.md +416 -0
  12. package/docs/MODULES.md +470 -0
  13. package/docs/PERFORMANCE.md +346 -0
  14. package/docs/PLUGINS.md +432 -0
  15. package/docs/QUICKSTART.md +184 -0
  16. package/docs/README.md +133 -0
  17. package/docs/ROADMAP.md +346 -0
  18. package/docs/SECURITY.md +334 -0
  19. package/docs/TROUBLESHOOTING.md +565 -0
  20. package/docs/USER_GUIDE.md +700 -0
  21. package/package.json +63 -0
  22. package/python/voria/__init__.py +8 -0
  23. package/python/voria/__pycache__/__init__.cpython-312.pyc +0 -0
  24. package/python/voria/__pycache__/engine.cpython-312.pyc +0 -0
  25. package/python/voria/core/__init__.py +1 -0
  26. package/python/voria/core/__pycache__/__init__.cpython-312.pyc +0 -0
  27. package/python/voria/core/__pycache__/setup.cpython-312.pyc +0 -0
  28. package/python/voria/core/agent/__init__.py +9 -0
  29. package/python/voria/core/agent/__pycache__/__init__.cpython-312.pyc +0 -0
  30. package/python/voria/core/agent/__pycache__/loop.cpython-312.pyc +0 -0
  31. package/python/voria/core/agent/loop.py +343 -0
  32. package/python/voria/core/executor/__init__.py +19 -0
  33. package/python/voria/core/executor/__pycache__/__init__.cpython-312.pyc +0 -0
  34. package/python/voria/core/executor/__pycache__/executor.cpython-312.pyc +0 -0
  35. package/python/voria/core/executor/executor.py +431 -0
  36. package/python/voria/core/github/__init__.py +33 -0
  37. package/python/voria/core/github/__pycache__/__init__.cpython-312.pyc +0 -0
  38. package/python/voria/core/github/__pycache__/client.cpython-312.pyc +0 -0
  39. package/python/voria/core/github/client.py +438 -0
  40. package/python/voria/core/llm/__init__.py +55 -0
  41. package/python/voria/core/llm/__pycache__/__init__.cpython-312.pyc +0 -0
  42. package/python/voria/core/llm/__pycache__/base.cpython-312.pyc +0 -0
  43. package/python/voria/core/llm/__pycache__/claude_provider.cpython-312.pyc +0 -0
  44. package/python/voria/core/llm/__pycache__/gemini_provider.cpython-312.pyc +0 -0
  45. package/python/voria/core/llm/__pycache__/modal_provider.cpython-312.pyc +0 -0
  46. package/python/voria/core/llm/__pycache__/model_discovery.cpython-312.pyc +0 -0
  47. package/python/voria/core/llm/__pycache__/openai_provider.cpython-312.pyc +0 -0
  48. package/python/voria/core/llm/base.py +152 -0
  49. package/python/voria/core/llm/claude_provider.py +188 -0
  50. package/python/voria/core/llm/gemini_provider.py +148 -0
  51. package/python/voria/core/llm/modal_provider.py +228 -0
  52. package/python/voria/core/llm/model_discovery.py +289 -0
  53. package/python/voria/core/llm/openai_provider.py +146 -0
  54. package/python/voria/core/patcher/__init__.py +9 -0
  55. package/python/voria/core/patcher/__pycache__/__init__.cpython-312.pyc +0 -0
  56. package/python/voria/core/patcher/__pycache__/patcher.cpython-312.pyc +0 -0
  57. package/python/voria/core/patcher/patcher.py +375 -0
  58. package/python/voria/core/planner/__init__.py +1 -0
  59. package/python/voria/core/setup.py +201 -0
  60. package/python/voria/core/token_manager/__init__.py +29 -0
  61. package/python/voria/core/token_manager/__pycache__/__init__.cpython-312.pyc +0 -0
  62. package/python/voria/core/token_manager/__pycache__/manager.cpython-312.pyc +0 -0
  63. package/python/voria/core/token_manager/manager.py +241 -0
  64. package/python/voria/engine.py +1185 -0
  65. package/python/voria/plugins/__init__.py +1 -0
  66. package/python/voria/plugins/python/__init__.py +1 -0
  67. package/python/voria/plugins/typescript/__init__.py +1 -0
@@ -0,0 +1,432 @@
1
+ # Plugin Development Guide
2
+
3
+ How to create and integrate plugins for voria.
4
+
5
+ ## What Are Plugins?
6
+
7
+ Plugins extend voria to support additional:
8
+ - **Programming languages** (test frameworks, code parsers)
9
+ - **VCS systems** (GitHub, GitLab, Gitea)
10
+ - **CI/CD platforms** (Jenkins, CircleCI, GitHub Actions)
11
+ - **LLM providers** (via the core llm module)
12
+
13
+ ## Plugin Types
14
+
15
+ ### 1. Language Plugins
16
+
17
+ Add support for new programming languages.
18
+
19
+ **Location**: `python/voria/plugins/<language>/`
20
+
21
+ **Structure**:
22
+ ```python
23
+ # __init__.py
24
+ from .executor import TestExecutor
25
+ from .parser import CodeParser
26
+ from .formatter import CodeFormatter
27
+
28
+ __all__ = ["TestExecutor", "CodeParser", "CodeFormatter"]
29
+ ```
30
+
31
+ **Implementation**:
32
+ ```python
33
+ # executor.py
34
+ from voria.core.executor import TestExecutor, TestResult
35
+
36
+ class GoTestExecutor(TestExecutor):
37
+ """Execute Go tests with 'go test ./...'"""
38
+
39
+ async def detect(self) -> bool:
40
+ """Return True if Go repo detected"""
41
+ return Path("go.mod").exists()
42
+
43
+ async def run(self, path: str) -> TestSuiteResult:
44
+ """Execute tests and return results"""
45
+ result = await subprocess.run(
46
+ ["go", "test", "-v", "./..."],
47
+ cwd=path,
48
+ capture_output=True
49
+ )
50
+ return self.parse_output(result.stdout)
51
+
52
+ def parse_output(self, output: str) -> TestSuiteResult:
53
+ """Parse 'go test' output"""
54
+ # Parse and return TestSuiteResult
55
+ pass
56
+ ```
57
+
58
+ **Registration** (`python/voria/core/executor/executor.py`):
59
+ ```python
60
+ from voria.plugins.go import GoTestExecutor
61
+
62
+ class TestExecutor:
63
+ EXECUTORS = {
64
+ "python": PytestExecutor,
65
+ "javascript": JestExecutor,
66
+ "go": GoTestExecutor, # ← Add here
67
+ }
68
+
69
+ async def detect_framework(self) -> Optional[str]:
70
+ for name, executor_class in self.EXECUTORS.items():
71
+ if await executor_class().detect():
72
+ return name
73
+ return None
74
+ ```
75
+
76
+ ### 2. VCS Plugins
77
+
78
+ Support new version control systems.
79
+
80
+ **Example: GitLab Support**
81
+
82
+ ```python
83
+ # python/voria/plugins/vcs/gitlab.py
84
+ from voria.core.github import GitHubClient # Base class
85
+
86
+ class GitLabClient(GitHubClient):
87
+ """GitLab API client"""
88
+
89
+ def __init__(self, token: str, base_url: str = "https://gitlab.com"):
90
+ self.token = token
91
+ self.base_url = base_url
92
+
93
+ async def fetch_issue(self, issue_id: int) -> Issue:
94
+ """Fetch GitLab issue"""
95
+ url = f"{self.base_url}/api/v4/projects/.../issues/{issue_id}"
96
+ return await self.client.get(url)
97
+
98
+ async def create_pr(self, **kwargs) -> PR:
99
+ """Create merge request (GitLab's PR equivalent)"""
100
+ pass
101
+ ```
102
+
103
+ **Registration**:
104
+ ```python
105
+ # python/voria/core/github/__init__.py
106
+ from voria.plugins.vcs.gitlab import GitLabClient
107
+
108
+ VCS_PROVIDERS = {
109
+ "github": GitHubClient,
110
+ "gitlab": GitLabClient, # ← Add
111
+ }
112
+
113
+ def create_vcs_client(vcs_type: str, **kwargs):
114
+ return VCS_PROVIDERS[vcs_type](**kwargs)
115
+ ```
116
+
117
+ ### 3. CI/CD Plugins
118
+
119
+ Integrate with CI/CD platforms.
120
+
121
+ **Example: Jenkins Integration**
122
+
123
+ ```python
124
+ # python/voria/plugins/ci/jenkins.py
125
+ import httpx
126
+
127
+ class JenkinsCI:
128
+ """Jenkins CI client"""
129
+
130
+ def __init__(self, url: str, token: str):
131
+ self.url = url
132
+ self.client = httpx.AsyncClient(
133
+ auth=httpx.BasicAuth("voria", token)
134
+ )
135
+
136
+ async def trigger_build(self, job_name: str) -> str:
137
+ """Trigger Jenkins job"""
138
+ url = f"{self.url}/job/{job_name}/build"
139
+ resp = await self.client.post(url)
140
+ return resp.headers["Location"] # Build URL
141
+
142
+ async def get_build_status(self, build_url: str) -> str:
143
+ """Get build status (SUCCESS, FAILURE, etc.)"""
144
+ api_url = f"{build_url}/api/json"
145
+ resp = await self.client.get(api_url)
146
+ return resp.json()["result"]
147
+
148
+ async def wait_for_build(self, build_url: str, timeout: int = 3600):
149
+ """Wait for build to complete"""
150
+ start = time.time()
151
+ while time.time() - start < timeout:
152
+ status = await self.get_build_status(build_url)
153
+ if status in ["SUCCESS", "FAILURE", "ABORTED"]:
154
+ return status
155
+ await asyncio.sleep(10) # Poll every 10s
156
+ raise TimeoutError("Build took too long")
157
+ ```
158
+
159
+ **Usage**:
160
+ ```python
161
+ # In agent loop
162
+ jenkins = JenkinsCI("https://jenkins.example.com", token)
163
+ build_url = await jenkins.trigger_build("voria-tests")
164
+ status = await jenkins.wait_for_build(build_url)
165
+ if status == "SUCCESS":
166
+ print("CI passed!")
167
+ ```
168
+
169
+ ## Creating a Custom Plugin
170
+
171
+ ### Step 1: Define Plugin Interface
172
+
173
+ ```python
174
+ # python/voria/plugins/my_lang/executor.py
175
+ from abc import ABC, abstractmethod
176
+ from voria.core.executor import TestSuiteResult
177
+
178
+ class MyLangExecutor(ABC):
179
+ """Base class for my language test executor"""
180
+
181
+ @abstractmethod
182
+ async def detect(self) -> bool:
183
+ """Check if this language is present"""
184
+ pass
185
+
186
+ @abstractmethod
187
+ async def run(self, path: str) -> TestSuiteResult:
188
+ """Run tests and return results"""
189
+ pass
190
+
191
+ @abstractmethod
192
+ def parse_output(self, output: str) -> TestSuiteResult:
193
+ """Parse test output"""
194
+ pass
195
+ ```
196
+
197
+ ### Step 2: Implement Plugin
198
+
199
+ ```python
200
+ # python/voria/plugins/python_rust/executor.py
201
+ import subprocess
202
+ from pathlib import Path
203
+ from voria.plugins.my_lang.executor import MyLangExecutor
204
+
205
+ class PythonRustExecutor(MyLangExecutor):
206
+ """Pytest + cargo test executor"""
207
+
208
+ async def detect(self) -> bool:
209
+ """Detect if Python+Rust project"""
210
+ return (
211
+ Path("Cargo.toml").exists() and
212
+ (Path("tests") / "test_*.py").glob("*")
213
+ )
214
+
215
+ async def run(self, path: str) -> TestSuiteResult:
216
+ """Run both pytest and cargo test"""
217
+ # Run pytest
218
+ py_result = await self._run_pytest(path)
219
+
220
+ # Run cargo test
221
+ rs_result = await self._run_cargo(path)
222
+
223
+ # Combine results
224
+ return TestSuiteResult(
225
+ framework="python+rust",
226
+ total=py_result.total + rs_result.total,
227
+ passed=py_result.passed + rs_result.passed,
228
+ failed=py_result.failed + rs_result.failed,
229
+ )
230
+
231
+ async def _run_pytest(self, path: str):
232
+ # Implementation
233
+ pass
234
+
235
+ async def _run_cargo(self, path: str):
236
+ # Implementation
237
+ pass
238
+
239
+ def parse_output(self, output: str):
240
+ # Implementation
241
+ pass
242
+ ```
243
+
244
+ ### Step 3: Register Plugin
245
+
246
+ ```python
247
+ # python/voria/core/executor/executor.py
248
+ from voria.plugins.python_rust.executor import PythonRustExecutor
249
+
250
+ class TestExecutor:
251
+ EXECUTORS = {
252
+ "python": PytestExecutor,
253
+ "javascript": JestExecutor,
254
+ "go": GoTestExecutor,
255
+ "python+rust": PythonRustExecutor, # ← Add
256
+ }
257
+ ```
258
+
259
+ ### Step 4: Test Plugin
260
+
261
+ ```python
262
+ # tests/test_python_rust_plugin.py
263
+ import pytest
264
+ from voria.plugins.python_rust.executor import PythonRustExecutor
265
+
266
+ @pytest.mark.asyncio
267
+ async def test_detect_python_rust():
268
+ executor = PythonRustExecutor()
269
+ # Create test directory with Cargo.toml and tests/
270
+ result = await executor.detect()
271
+ assert result is True
272
+
273
+ @pytest.mark.asyncio
274
+ async def test_run_tests():
275
+ executor = PythonRustExecutor()
276
+ result = await executor.run("/path/to/repo")
277
+ assert result.total > 0
278
+ ```
279
+
280
+ ## Packaging Plugins
281
+
282
+ ### As Separate Package
283
+
284
+ ```python
285
+ # setup.py (for plugin package)
286
+ from setuptools import setup
287
+
288
+ setup(
289
+ name="voria-plugin-kotlin",
290
+ version="0.1.0",
291
+ py_modules=["voria_kotlin"],
292
+ install_requires=[
293
+ "voria>=0.2.0",
294
+ ],
295
+ entry_points={
296
+ "voria.plugins": [
297
+ "kotlin = voria_kotlin:KotlinExecutor",
298
+ ]
299
+ }
300
+ )
301
+ ```
302
+
303
+ ### Load External Plugins
304
+
305
+ ```python
306
+ # python/voria/core/executor/executor.py
307
+ import importlib
308
+
309
+ class TestExecutor:
310
+ def __init__(self):
311
+ self.executors = self._load_plugins()
312
+
313
+ def _load_plugins(self):
314
+ """Load plugins from entry points"""
315
+ plugins = {}
316
+ try:
317
+ import pkg_resources
318
+ for entry_point in pkg_resources.iter_entry_points("voria.plugins"):
319
+ plugins[entry_point.name] = entry_point.load()
320
+ except:
321
+ pass
322
+ return plugins
323
+ ```
324
+
325
+ ## Plugin Examples
326
+
327
+ ### Complete Python Plugin
328
+
329
+ ```python
330
+ #python/voria/plugins/django/executor.py
331
+ class DjangoTestExecutor:
332
+ """Django test executor"""
333
+
334
+ async def detect(self) -> bool:
335
+ return (
336
+ Path("manage.py").exists() and
337
+ Path("settings.py").exists()
338
+ )
339
+
340
+ async def run(self, path: str) -> TestSuiteResult:
341
+ result = await subprocess.run(
342
+ ["python", "manage.py", "test", "-v", "2"],
343
+ cwd=path,
344
+ capture_output=True
345
+ )
346
+
347
+ from voria.core.executor import TestSuiteResult, TestStatus
348
+
349
+ # Parse Django test output
350
+ output = result.stdout.decode()
351
+ lines = output.split('\n')
352
+
353
+ # Look for summary line: "Ran 42 tests..."
354
+ passed = 0
355
+ failed = 0
356
+ for line in lines:
357
+ if "OK" in line:
358
+ passed += 42 # Simplified
359
+ elif "FAILED" in line:
360
+ # Parse failures
361
+ pass
362
+
363
+ return TestSuiteResult(
364
+ framework="django",
365
+ total=42,
366
+ passed=passed,
367
+ failed=failed,
368
+ )
369
+
370
+ def parse_output(self, output: str):
371
+ pass
372
+ ```
373
+
374
+ ### Custom Code Parser Plugin
375
+
376
+ ```python
377
+ # python/voria/plugins/kotlin/parser.py
378
+ import re
379
+ from dataclasses import dataclass
380
+
381
+ @dataclass
382
+ class KotlinFunction:
383
+ name: str
384
+ args: List[str]
385
+ return_type: str
386
+
387
+ class KotlinParser:
388
+ """Parse Kotlin code for analysis"""
389
+
390
+ def parse_functions(self, source: str) -> List[KotlinFunction]:
391
+ """Extract functions from Kotlin source"""
392
+ pattern = r'fun\s+(\w+)\s*\((.*?)\)\s*:\s*(\w+)'
393
+ matches = re.finditer(pattern, source)
394
+
395
+ functions = []
396
+ for match in matches:
397
+ func = KotlinFunction(
398
+ name=match.group(1),
399
+ args=[a.strip() for a in match.group(2).split(',')],
400
+ return_type=match.group(3)
401
+ )
402
+ functions.append(func)
403
+
404
+ return functions
405
+ ```
406
+
407
+ ## Plugin Development Checklist
408
+
409
+ - [ ] Inherit from appropriate base class
410
+ - [ ] Implement all abstract methods
411
+ - [ ] Add comprehensive docstrings
412
+ - [ ] Write unit tests
413
+ - [ ] Test with real projects
414
+ - [ ] Handle errors gracefully
415
+ - [ ] Document setup requirements
416
+ - [ ] Register in appropriate manager
417
+ - [ ] Add to plugin registry
418
+ - [ ] Submit PR or publish package
419
+
420
+ ## Useful Resources
421
+
422
+ - Base classes: See `python/voria/core/*/` modules
423
+ - Examples: Check ExistingPlugins in `python/voria/plugins/`
424
+ - Testing: Use pytest with async support
425
+ - Async/await: Python 3.7+ syntax
426
+
427
+ ---
428
+
429
+ **See Also:**
430
+ - [DEVELOPMENT.md](DEVELOPMENT.md) - Dev environment setup
431
+ - [MODULES.md](MODULES.md) - Module documentation
432
+ - [LLM_INTEGRATION.md](LLM_INTEGRATION.md) - Add new LLM providers
@@ -0,0 +1,184 @@
1
+ # Quick Start Guide
2
+
3
+ Get voria running in 5 minutes or less!
4
+
5
+ ## 5-Minute Setup
6
+
7
+ ### 1. Install (2 minutes)
8
+
9
+ ```bash
10
+ # Install globally from npm
11
+ npm install -g @srizdebnath/voria
12
+
13
+ # Verify
14
+ voria --version
15
+ ```
16
+
17
+ ### 2. Configure LLM Provider (1 minute)
18
+
19
+ ```bash
20
+ # Setup Modal (FREE and easy!)
21
+ voria setup-modal your_modal_api_key
22
+
23
+ # Or get prompted for token
24
+ voria setup-modal
25
+ ```
26
+
27
+ ### 3. Setup GitHub Access (1 minute)
28
+
29
+ ```bash
30
+ voria set-github-token
31
+ # Paste your GitHub Personal Access Token
32
+ ```
33
+
34
+ ### 4. List Issues (1 minute)
35
+
36
+ ```bash
37
+ # List issues from any repository
38
+ voria list-issues owner/repo
39
+
40
+ # Or with full GitHub URL
41
+ voria list-issues https://github.com/owner/repo
42
+ ```
43
+
44
+ **✅ That's it! voria is ready.**
45
+
46
+ ## Common Commands
47
+
48
+ ### List Issues in a Repository
49
+
50
+ ```bash
51
+ # Using owner/repo format
52
+ voria list-issues ansh/voria
53
+
54
+ # Using GitHub URL
55
+ voria list-issues https://github.com/ansh/voria
56
+
57
+ # Interactive mode
58
+ voria list-issues # Will prompt for repo
59
+ ```
60
+
61
+ ### Fix a GitHub Issue
62
+
63
+ ```bash
64
+ # Fix issue with repo specified
65
+ voria fix 42 ansh/voria
66
+
67
+ # Fix with GitHub URL
68
+ voria fix 42 https://github.com/ansh/voria
69
+
70
+ # Interactive mode
71
+ voria fix 42 # Will prompt for repo
72
+ ```
73
+
74
+ ### Plan out a Fix
75
+
76
+ ```bash
77
+ # Plan how to fix an issue by ID
78
+ voria plan 123
79
+
80
+ # Apply a patch after planning
81
+ voria apply /path/to/patch.diff
82
+ ```
83
+
84
+ ### Show Help
85
+
86
+ ```bash
87
+ voria --help # General help
88
+ voria fix --help # Command-specific help
89
+ voria list-issues --help # List issues help
90
+ ```
91
+
92
+ ## LLM Providers
93
+
94
+ voria supports multiple providers. Set one up during setup:
95
+
96
+ ### 1. Modal (Easiest - Free tier)
97
+
98
+ ```bash
99
+ # Get key from https://platform.openai.com/
100
+ export OPENAI_API_KEY="sk-..."
101
+ ```
102
+
103
+ ### 3. Google Gemini (Fast & Affordable)
104
+
105
+ ```bash
106
+ # Get key from https://makersuite.google.com/app/apikey
107
+ export GOOGLE_API_KEY="..."
108
+ ```
109
+
110
+ ### 4. Anthropic Claude (Highest Quality)
111
+
112
+ ```bash
113
+ # Get key from https://console.anthropic.com/
114
+ export ANTHROPIC_API_KEY="..."
115
+ ```
116
+
117
+ ## Project Structure (What You Got)
118
+
119
+ ```
120
+ voria/
121
+ ├── rust/ # CLI (Rust)
122
+ ├── python/ # Engine (Python)
123
+ ├── docs/ # Documentation (You are here!)
124
+ └── target/ # Build output
125
+ ```
126
+
127
+ ## Verify Everything Works
128
+
129
+ ```bash
130
+ # Test CLI
131
+ ./target/release/voria --version
132
+ ./target/release/voria --help
133
+
134
+ # Test Python engine
135
+ python3 -m voria.engine
136
+
137
+ # Test end-to-end
138
+ ./target/release/voria plan 1
139
+ ```
140
+
141
+ ## Next Steps
142
+
143
+ 1. **Learn usage** → Read [USER_GUIDE.md](USER_GUIDE.md)
144
+ 2. **See examples** → Check [EXAMPLES.md](EXAMPLES.md)
145
+ 3. **Understand it** → Study [ARCHITECTURE.md](ARCHITECTURE.md)
146
+ 4. **Contribute** → Follow [CONTRIBUTING.md](CONTRIBUTING.md)
147
+
148
+ ## Quick Links
149
+
150
+ - [Full Installation](INSTALL.md)
151
+ - [User Guide](USER_GUIDE.md)
152
+ - [Examples](EXAMPLES.md)
153
+ - [Troubleshooting](TROUBLESHOOTING.md)
154
+ - [GitHub](https://github.com/Srizdebnath/voria)
155
+
156
+ ## ❓ Common Issues
157
+
158
+ ### Command not found
159
+ ```bash
160
+ # Make sure you're in the right directory
161
+ cd voria
162
+ ./target/release/voria --version
163
+ ```
164
+
165
+ ### LLM not working
166
+ ```bash
167
+ # Verify configuration
168
+ python3 -m voria.core.setup
169
+
170
+ # Or set environment variable
171
+ export OPENAI_API_KEY="your-key-here"
172
+ ```
173
+
174
+ ### Python import error
175
+ ```bash
176
+ # Reinstall Python package
177
+ cd python
178
+ pip install -e .
179
+ cd ..
180
+ ```
181
+
182
+ ---
183
+
184
+ **Ready to go deeper?** → [USER_GUIDE.md](USER_GUIDE.md) 🚀