janito 0.5.0__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.
- janito-0.7.0/PKG-INFO +167 -0
- janito-0.7.0/README.md +142 -0
- janito-0.7.0/janito/__init__.py +2 -0
- janito-0.7.0/janito/__main__.py +142 -0
- {janito-0.5.0 → janito-0.7.0}/janito/agents/__init__.py +9 -9
- {janito-0.5.0 → janito-0.7.0}/janito/agents/agent.py +10 -3
- janito-0.7.0/janito/agents/claudeai.py +45 -0
- {janito-0.5.0 → janito-0.7.0}/janito/agents/openai.py +5 -1
- janito-0.7.0/janito/change/__init__.py +32 -0
- janito-0.7.0/janito/change/__main__.py +0 -0
- {janito-0.5.0/janito → janito-0.7.0/janito/change}/analysis/__init__.py +5 -15
- janito-0.7.0/janito/change/analysis/__main__.py +7 -0
- janito-0.7.0/janito/change/analysis/analyze.py +62 -0
- janito-0.7.0/janito/change/analysis/formatting.py +78 -0
- janito-0.7.0/janito/change/analysis/options.py +81 -0
- {janito-0.5.0/janito → janito-0.7.0/janito/change}/analysis/prompts.py +33 -18
- janito-0.7.0/janito/change/analysis/view/__init__.py +9 -0
- janito-0.7.0/janito/change/analysis/view/terminal.py +181 -0
- janito-0.7.0/janito/change/applier/__init__.py +5 -0
- janito-0.7.0/janito/change/applier/file.py +58 -0
- janito-0.7.0/janito/change/applier/main.py +156 -0
- janito-0.7.0/janito/change/applier/text.py +247 -0
- janito-0.7.0/janito/change/applier/workspace_dir.py +58 -0
- janito-0.7.0/janito/change/core.py +124 -0
- janito-0.5.0/janito/changehistory.py → janito-0.7.0/janito/change/history.py +12 -14
- janito-0.7.0/janito/change/operations.py +7 -0
- janito-0.7.0/janito/change/parser.py +287 -0
- janito-0.7.0/janito/change/play.py +54 -0
- janito-0.7.0/janito/change/preview.py +82 -0
- janito-0.7.0/janito/change/prompts.py +121 -0
- janito-0.7.0/janito/change/test.py +0 -0
- janito-0.7.0/janito/change/validator.py +269 -0
- {janito-0.5.0/janito/changeviewer → janito-0.7.0/janito/change/viewer}/__init__.py +3 -4
- janito-0.7.0/janito/change/viewer/content.py +66 -0
- {janito-0.5.0/janito/changeviewer → janito-0.7.0/janito/change/viewer}/diff.py +19 -4
- janito-0.7.0/janito/change/viewer/panels.py +533 -0
- janito-0.7.0/janito/change/viewer/styling.py +114 -0
- {janito-0.5.0/janito/changeviewer → janito-0.7.0/janito/change/viewer}/themes.py +3 -5
- janito-0.7.0/janito/clear_statement_parser/clear_statement_format.txt +328 -0
- janito-0.7.0/janito/clear_statement_parser/examples.txt +326 -0
- janito-0.7.0/janito/clear_statement_parser/models.py +104 -0
- janito-0.7.0/janito/clear_statement_parser/parser.py +496 -0
- janito-0.7.0/janito/cli/base.py +30 -0
- janito-0.7.0/janito/cli/commands.py +88 -0
- janito-0.7.0/janito/cli/functions.py +111 -0
- janito-0.7.0/janito/cli/history.py +61 -0
- janito-0.7.0/janito/common.py +80 -0
- janito-0.7.0/janito/config.py +102 -0
- janito-0.7.0/janito/demo/__init__.py +4 -0
- janito-0.7.0/janito/demo/data.py +13 -0
- janito-0.7.0/janito/demo/mock_data.py +20 -0
- janito-0.7.0/janito/demo/operations.py +45 -0
- janito-0.7.0/janito/demo/runner.py +59 -0
- janito-0.7.0/janito/demo/scenarios.py +32 -0
- janito-0.7.0/janito/prompt.py +36 -0
- {janito-0.5.0 → janito-0.7.0}/janito/qa.py +6 -14
- janito-0.7.0/janito/search_replace/README.md +192 -0
- janito-0.7.0/janito/search_replace/__init__.py +7 -0
- janito-0.7.0/janito/search_replace/__main__.py +21 -0
- janito-0.7.0/janito/search_replace/core.py +120 -0
- janito-0.7.0/janito/search_replace/logger.py +35 -0
- janito-0.7.0/janito/search_replace/parser.py +52 -0
- janito-0.7.0/janito/search_replace/play.py +61 -0
- janito-0.7.0/janito/search_replace/replacer.py +36 -0
- janito-0.7.0/janito/search_replace/searcher.py +411 -0
- janito-0.7.0/janito/search_replace/strategy_result.py +10 -0
- janito-0.7.0/janito/shell/__init__.py +38 -0
- janito-0.7.0/janito/shell/bus.py +31 -0
- janito-0.7.0/janito/shell/commands.py +136 -0
- janito-0.7.0/janito/shell/history.py +20 -0
- janito-0.7.0/janito/shell/processor.py +32 -0
- janito-0.7.0/janito/shell/prompt.py +48 -0
- janito-0.7.0/janito/shell/registry.py +60 -0
- janito-0.7.0/janito/tui/__init__.py +21 -0
- janito-0.7.0/janito/tui/base.py +22 -0
- janito-0.7.0/janito/tui/flows/__init__.py +5 -0
- janito-0.7.0/janito/tui/flows/changes.py +65 -0
- janito-0.7.0/janito/tui/flows/content.py +128 -0
- janito-0.7.0/janito/tui/flows/selection.py +117 -0
- janito-0.7.0/janito/tui/screens/__init__.py +3 -0
- janito-0.7.0/janito/tui/screens/app.py +1 -0
- janito-0.7.0/janito/workspace/__init__.py +6 -0
- janito-0.7.0/janito/workspace/analysis.py +121 -0
- janito-0.7.0/janito/workspace/show.py +141 -0
- janito-0.7.0/janito/workspace/stats.py +43 -0
- janito-0.7.0/janito/workspace/types.py +98 -0
- janito-0.7.0/janito/workspace/workset.py +108 -0
- janito-0.7.0/janito/workspace/workspace.py +114 -0
- {janito-0.5.0 → janito-0.7.0}/pyproject.toml +2 -2
- janito-0.7.0/tests/test_python_adjustments.py +271 -0
- {janito-0.5.0 → janito-0.7.0}/tools/release.sh +12 -2
- janito-0.5.0/PKG-INFO +0 -146
- janito-0.5.0/README.md +0 -122
- janito-0.5.0/janito/__init__.py +0 -49
- janito-0.5.0/janito/__main__.py +0 -54
- janito-0.5.0/janito/_contextparser.py +0 -113
- janito-0.5.0/janito/agents/claudeai.py +0 -64
- janito-0.5.0/janito/analysis/display.py +0 -149
- janito-0.5.0/janito/analysis/options.py +0 -112
- janito-0.5.0/janito/change/__init__.py +0 -19
- janito-0.5.0/janito/change/applier.py +0 -269
- janito-0.5.0/janito/change/content.py +0 -62
- janito-0.5.0/janito/change/indentation.py +0 -33
- janito-0.5.0/janito/change/position.py +0 -169
- janito-0.5.0/janito/changeviewer/panels.py +0 -268
- janito-0.5.0/janito/changeviewer/styling.py +0 -59
- janito-0.5.0/janito/cli/commands.py +0 -53
- janito-0.5.0/janito/cli/functions.py +0 -286
- janito-0.5.0/janito/common.py +0 -23
- janito-0.5.0/janito/config.py +0 -37
- janito-0.5.0/janito/console/__init__.py +0 -3
- janito-0.5.0/janito/console/commands.py +0 -112
- janito-0.5.0/janito/console/core.py +0 -62
- janito-0.5.0/janito/console/display.py +0 -157
- janito-0.5.0/janito/fileparser.py +0 -334
- janito-0.5.0/janito/prompts.py +0 -81
- janito-0.5.0/janito/scan.py +0 -176
- janito-0.5.0/janito/tests/test_fileparser.py +0 -26
- janito-0.5.0/tests/conftest.py +0 -45
- janito-0.5.0/tests/test_contentchange.py +0 -68
- janito-0.5.0/tests/test_integration.py +0 -64
- janito-0.5.0/tests/test_prompts.py +0 -59
- janito-0.5.0/tests/test_scan.py +0 -98
- {janito-0.5.0 → janito-0.7.0}/.gitignore +0 -0
- {janito-0.5.0 → janito-0.7.0}/LICENSE +0 -0
- {janito-0.5.0 → janito-0.7.0}/janito/agents/test.py +0 -0
- {janito-0.5.0 → janito-0.7.0}/janito/cli/__init__.py +0 -0
- {janito-0.5.0 → janito-0.7.0}/janito/cli/registry.py +0 -0
- {janito-0.5.0 → janito-0.7.0}/janito/review.py +0 -0
- {janito-0.5.0 → janito-0.7.0}/janito/version.py +0 -0
- {janito-0.5.0 → janito-0.7.0}/setup.py +0 -0
janito-0.7.0/PKG-INFO
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: janito
|
3
|
+
Version: 0.7.0
|
4
|
+
Summary: A CLI tool for software development tasks powered by AI
|
5
|
+
Project-URL: Homepage, https://github.com/joaompinto/janito
|
6
|
+
Project-URL: Repository, https://github.com/joaompinto/janito.git
|
7
|
+
Author-email: João Pinto <lamego.pinto@gmail.com>
|
8
|
+
License: MIT
|
9
|
+
License-File: LICENSE
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
11
|
+
Classifier: Environment :: Console
|
12
|
+
Classifier: Intended Audience :: Developers
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
14
|
+
Classifier: Programming Language :: Python :: 3.8
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
17
|
+
Classifier: Topic :: Software Development
|
18
|
+
Requires-Python: >=3.8
|
19
|
+
Requires-Dist: anthropic
|
20
|
+
Requires-Dist: pathspec
|
21
|
+
Requires-Dist: rich
|
22
|
+
Requires-Dist: tomli
|
23
|
+
Requires-Dist: typer
|
24
|
+
Description-Content-Type: text/markdown
|
25
|
+
|
26
|
+
# Janito
|
27
|
+
|
28
|
+
[](https://badge.fury.io/py/janito)
|
29
|
+
[](https://opensource.org/licenses/MIT)
|
30
|
+
|
31
|
+
AI-powered CLI tool for code modifications and analysis. Janito helps you modify, analyze, and understand your codebase using natural language commands.
|
32
|
+
|
33
|
+
## Table of Contents
|
34
|
+
|
35
|
+
- [Features](#features)
|
36
|
+
- [Installation](#installation)
|
37
|
+
- [Usage](#usage)
|
38
|
+
- [Basic Commands](#basic-commands)
|
39
|
+
- [Examples](#examples)
|
40
|
+
- [Configuration](#configuration)
|
41
|
+
- [Development](#development)
|
42
|
+
- [License](#license)
|
43
|
+
|
44
|
+
## Features
|
45
|
+
|
46
|
+
- 🤖 AI-powered code analysis and modifications
|
47
|
+
- 🔄 Incremental code changes with search/replace operations
|
48
|
+
- 🎯 Precise text modifications with context matching
|
49
|
+
- 💬 Natural language interface for code operations
|
50
|
+
- 🔍 Interactive code exploration
|
51
|
+
- 📝 Automatic documentation generation
|
52
|
+
- ⚡ Fast and efficient codebase navigation
|
53
|
+
- 💾 Smart Claude AI prompt caching for faster responses
|
54
|
+
|
55
|
+
## Installation
|
56
|
+
|
57
|
+
### Prerequisites
|
58
|
+
|
59
|
+
- Python 3.8 or higher
|
60
|
+
- Anthropic API key (with smart caching to reduce API costs)
|
61
|
+
|
62
|
+
### Install via pip
|
63
|
+
|
64
|
+
```bash
|
65
|
+
pip install janito
|
66
|
+
```
|
67
|
+
|
68
|
+
### Set up API key
|
69
|
+
|
70
|
+
```bash
|
71
|
+
export ANTHROPIC_API_KEY=your_api_key_here
|
72
|
+
```
|
73
|
+
|
74
|
+
## Usage
|
75
|
+
|
76
|
+
### Basic Commands
|
77
|
+
|
78
|
+
Janito supports incremental code changes through precise text operations:
|
79
|
+
- Search and replace with context matching
|
80
|
+
- Delete specific code blocks
|
81
|
+
- File operations (create, replace, rename, move, remove)
|
82
|
+
|
83
|
+
```bash
|
84
|
+
# Start interactive shell
|
85
|
+
janito
|
86
|
+
|
87
|
+
# Modify code with natural language
|
88
|
+
janito "add docstrings to this file"
|
89
|
+
|
90
|
+
# Ask questions about the codebase
|
91
|
+
janito --ask "explain the main function in this file"
|
92
|
+
|
93
|
+
# Preview files that would be analyzed
|
94
|
+
janito --scan
|
95
|
+
```
|
96
|
+
|
97
|
+
### Examples
|
98
|
+
|
99
|
+
1. Add documentation to a file:
|
100
|
+
```bash
|
101
|
+
janito "add docstrings to all functions in src/main.py"
|
102
|
+
```
|
103
|
+
|
104
|
+
2. Analyze code structure:
|
105
|
+
```bash
|
106
|
+
janito --ask "what are the main classes in this project?"
|
107
|
+
```
|
108
|
+
|
109
|
+
3. Refactor code:
|
110
|
+
```bash
|
111
|
+
janito "convert this function to use async/await"
|
112
|
+
```
|
113
|
+
|
114
|
+
4. Generate tests:
|
115
|
+
```bash
|
116
|
+
janito "create unit tests for the User class"
|
117
|
+
```
|
118
|
+
|
119
|
+
## Configuration
|
120
|
+
|
121
|
+
### Environment Variables
|
122
|
+
|
123
|
+
- `ANTHROPIC_API_KEY`: Anthropic API key for Claude AI
|
124
|
+
- `JANITO_TEST_CMD`: Default test command to run after changes
|
125
|
+
|
126
|
+
### Command Line Options
|
127
|
+
|
128
|
+
- `-w, --workspace_dir`: Set working directory
|
129
|
+
- `-i, --include`: Additional paths to include
|
130
|
+
- `--debug`: Show debug information
|
131
|
+
- `--verbose`: Show verbose output
|
132
|
+
- `--auto-apply`: Apply changes without confirmation
|
133
|
+
|
134
|
+
## Development
|
135
|
+
|
136
|
+
### Setting up Development Environment
|
137
|
+
|
138
|
+
```bash
|
139
|
+
# Clone the repository
|
140
|
+
git clone https://github.com/joaompinto/janito.git
|
141
|
+
cd janito
|
142
|
+
|
143
|
+
# Create and activate virtual environment
|
144
|
+
python -m venv venv
|
145
|
+
source venv/bin/activate # On Windows: venv\Scripts\activate
|
146
|
+
|
147
|
+
# Install development dependencies
|
148
|
+
pip install -e ".[dev]"
|
149
|
+
```
|
150
|
+
|
151
|
+
### Running Tests
|
152
|
+
|
153
|
+
```bash
|
154
|
+
pytest
|
155
|
+
```
|
156
|
+
|
157
|
+
### Contributing
|
158
|
+
|
159
|
+
1. Fork the repository
|
160
|
+
2. Create a feature branch
|
161
|
+
3. Commit your changes
|
162
|
+
4. Push to the branch
|
163
|
+
5. Create a Pull Request
|
164
|
+
|
165
|
+
## License
|
166
|
+
|
167
|
+
MIT License - see [LICENSE](LICENSE)
|
janito-0.7.0/README.md
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
# Janito
|
2
|
+
|
3
|
+
[](https://badge.fury.io/py/janito)
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
5
|
+
|
6
|
+
AI-powered CLI tool for code modifications and analysis. Janito helps you modify, analyze, and understand your codebase using natural language commands.
|
7
|
+
|
8
|
+
## Table of Contents
|
9
|
+
|
10
|
+
- [Features](#features)
|
11
|
+
- [Installation](#installation)
|
12
|
+
- [Usage](#usage)
|
13
|
+
- [Basic Commands](#basic-commands)
|
14
|
+
- [Examples](#examples)
|
15
|
+
- [Configuration](#configuration)
|
16
|
+
- [Development](#development)
|
17
|
+
- [License](#license)
|
18
|
+
|
19
|
+
## Features
|
20
|
+
|
21
|
+
- 🤖 AI-powered code analysis and modifications
|
22
|
+
- 🔄 Incremental code changes with search/replace operations
|
23
|
+
- 🎯 Precise text modifications with context matching
|
24
|
+
- 💬 Natural language interface for code operations
|
25
|
+
- 🔍 Interactive code exploration
|
26
|
+
- 📝 Automatic documentation generation
|
27
|
+
- ⚡ Fast and efficient codebase navigation
|
28
|
+
- 💾 Smart Claude AI prompt caching for faster responses
|
29
|
+
|
30
|
+
## Installation
|
31
|
+
|
32
|
+
### Prerequisites
|
33
|
+
|
34
|
+
- Python 3.8 or higher
|
35
|
+
- Anthropic API key (with smart caching to reduce API costs)
|
36
|
+
|
37
|
+
### Install via pip
|
38
|
+
|
39
|
+
```bash
|
40
|
+
pip install janito
|
41
|
+
```
|
42
|
+
|
43
|
+
### Set up API key
|
44
|
+
|
45
|
+
```bash
|
46
|
+
export ANTHROPIC_API_KEY=your_api_key_here
|
47
|
+
```
|
48
|
+
|
49
|
+
## Usage
|
50
|
+
|
51
|
+
### Basic Commands
|
52
|
+
|
53
|
+
Janito supports incremental code changes through precise text operations:
|
54
|
+
- Search and replace with context matching
|
55
|
+
- Delete specific code blocks
|
56
|
+
- File operations (create, replace, rename, move, remove)
|
57
|
+
|
58
|
+
```bash
|
59
|
+
# Start interactive shell
|
60
|
+
janito
|
61
|
+
|
62
|
+
# Modify code with natural language
|
63
|
+
janito "add docstrings to this file"
|
64
|
+
|
65
|
+
# Ask questions about the codebase
|
66
|
+
janito --ask "explain the main function in this file"
|
67
|
+
|
68
|
+
# Preview files that would be analyzed
|
69
|
+
janito --scan
|
70
|
+
```
|
71
|
+
|
72
|
+
### Examples
|
73
|
+
|
74
|
+
1. Add documentation to a file:
|
75
|
+
```bash
|
76
|
+
janito "add docstrings to all functions in src/main.py"
|
77
|
+
```
|
78
|
+
|
79
|
+
2. Analyze code structure:
|
80
|
+
```bash
|
81
|
+
janito --ask "what are the main classes in this project?"
|
82
|
+
```
|
83
|
+
|
84
|
+
3. Refactor code:
|
85
|
+
```bash
|
86
|
+
janito "convert this function to use async/await"
|
87
|
+
```
|
88
|
+
|
89
|
+
4. Generate tests:
|
90
|
+
```bash
|
91
|
+
janito "create unit tests for the User class"
|
92
|
+
```
|
93
|
+
|
94
|
+
## Configuration
|
95
|
+
|
96
|
+
### Environment Variables
|
97
|
+
|
98
|
+
- `ANTHROPIC_API_KEY`: Anthropic API key for Claude AI
|
99
|
+
- `JANITO_TEST_CMD`: Default test command to run after changes
|
100
|
+
|
101
|
+
### Command Line Options
|
102
|
+
|
103
|
+
- `-w, --workspace_dir`: Set working directory
|
104
|
+
- `-i, --include`: Additional paths to include
|
105
|
+
- `--debug`: Show debug information
|
106
|
+
- `--verbose`: Show verbose output
|
107
|
+
- `--auto-apply`: Apply changes without confirmation
|
108
|
+
|
109
|
+
## Development
|
110
|
+
|
111
|
+
### Setting up Development Environment
|
112
|
+
|
113
|
+
```bash
|
114
|
+
# Clone the repository
|
115
|
+
git clone https://github.com/joaompinto/janito.git
|
116
|
+
cd janito
|
117
|
+
|
118
|
+
# Create and activate virtual environment
|
119
|
+
python -m venv venv
|
120
|
+
source venv/bin/activate # On Windows: venv\Scripts\activate
|
121
|
+
|
122
|
+
# Install development dependencies
|
123
|
+
pip install -e ".[dev]"
|
124
|
+
```
|
125
|
+
|
126
|
+
### Running Tests
|
127
|
+
|
128
|
+
```bash
|
129
|
+
pytest
|
130
|
+
```
|
131
|
+
|
132
|
+
### Contributing
|
133
|
+
|
134
|
+
1. Fork the repository
|
135
|
+
2. Create a feature branch
|
136
|
+
3. Commit your changes
|
137
|
+
4. Push to the branch
|
138
|
+
5. Create a Pull Request
|
139
|
+
|
140
|
+
## License
|
141
|
+
|
142
|
+
MIT License - see [LICENSE](LICENSE)
|
@@ -0,0 +1,142 @@
|
|
1
|
+
import typer
|
2
|
+
from typing import Optional, List, Set
|
3
|
+
from pathlib import Path
|
4
|
+
from rich.text import Text
|
5
|
+
from rich import print as rich_print
|
6
|
+
from rich.console import Console
|
7
|
+
from rich.text import Text
|
8
|
+
from .version import get_version
|
9
|
+
|
10
|
+
from janito.config import config
|
11
|
+
from janito.workspace import workset
|
12
|
+
from janito.workspace.types import ScanType # Add this import
|
13
|
+
from .cli.commands import (
|
14
|
+
handle_request, handle_ask, handle_play,
|
15
|
+
handle_scan, handle_demo
|
16
|
+
)
|
17
|
+
|
18
|
+
app = typer.Typer(pretty_exceptions_enable=False)
|
19
|
+
|
20
|
+
def validate_paths(paths: Optional[List[Path]]) -> Optional[List[Path]]:
|
21
|
+
"""Validate include paths for duplicates.
|
22
|
+
|
23
|
+
Args:
|
24
|
+
paths: List of paths to validate, or None if no paths provided
|
25
|
+
|
26
|
+
Returns:
|
27
|
+
Validated list of paths or None if no paths provided
|
28
|
+
"""
|
29
|
+
if not paths: # This handles both None and empty list cases
|
30
|
+
return None
|
31
|
+
|
32
|
+
# Convert paths to absolute and resolve symlinks
|
33
|
+
resolved_paths: Set[Path] = set()
|
34
|
+
unique_paths: List[Path] = []
|
35
|
+
|
36
|
+
for path in paths:
|
37
|
+
resolved = path.absolute().resolve()
|
38
|
+
if resolved in resolved_paths:
|
39
|
+
error_text = Text(f"\nError: Duplicate path provided: {path} ", style="red")
|
40
|
+
rich_print(error_text)
|
41
|
+
raise typer.Exit(1)
|
42
|
+
resolved_paths.add(resolved)
|
43
|
+
unique_paths.append(path)
|
44
|
+
|
45
|
+
return unique_paths if unique_paths else None
|
46
|
+
|
47
|
+
def typer_main(
|
48
|
+
change_request: str = typer.Argument(None, help="Change request or command"),
|
49
|
+
workspace_dir: Optional[Path] = typer.Option(None, "-w", "--workspace_dir", help="Working directory", file_okay=False, dir_okay=True),
|
50
|
+
debug: bool = typer.Option(False, "--debug", help="Show debug information"),
|
51
|
+
verbose: bool = typer.Option(False, "--verbose", help="Show verbose output"),
|
52
|
+
include: Optional[List[Path]] = typer.Option(None, "-i", "--include", help="Additional paths to include"),
|
53
|
+
ask: Optional[str] = typer.Option(None, "--ask", help="Ask a question about the codebase"),
|
54
|
+
play: Optional[Path] = typer.Option(None, "--play", help="Replay a saved prompt file"),
|
55
|
+
scan: bool = typer.Option(False, "--scan", help="Preview files that would be analyzed"),
|
56
|
+
version: bool = typer.Option(False, "--version", help="Show version information"),
|
57
|
+
test_cmd: Optional[str] = typer.Option(None, "--test", help="Command to run tests after changes"),
|
58
|
+
auto_apply: bool = typer.Option(False, "--auto-apply", help="Apply changes without confirmation"),
|
59
|
+
tui: bool = typer.Option(False, "--tui", help="Use terminal user interface"),
|
60
|
+
history: bool = typer.Option(False, "--history", help="Display history of requests"),
|
61
|
+
recursive: Optional[List[Path]] = typer.Option(None, "-r", "--recursive", help="Paths to scan recursively (directories only)"),
|
62
|
+
demo: bool = typer.Option(False, "--demo", help="Run demo scenarios"),
|
63
|
+
skip_work: bool = typer.Option(False, "--skip-work", help="Skip scanning workspace_dir when using include paths"),
|
64
|
+
):
|
65
|
+
"""Janito - AI-powered code modification assistant"""
|
66
|
+
if version:
|
67
|
+
console = Console()
|
68
|
+
console.print(f"Janito version {get_version()}")
|
69
|
+
return
|
70
|
+
|
71
|
+
if demo:
|
72
|
+
handle_demo()
|
73
|
+
return
|
74
|
+
|
75
|
+
if history:
|
76
|
+
from janito.cli.history import display_history
|
77
|
+
display_history()
|
78
|
+
return
|
79
|
+
|
80
|
+
# Configure workspace
|
81
|
+
config.set_workspace_dir(workspace_dir)
|
82
|
+
config.set_debug(debug)
|
83
|
+
config.set_verbose(verbose)
|
84
|
+
config.set_auto_apply(auto_apply)
|
85
|
+
config.set_tui(tui)
|
86
|
+
|
87
|
+
# Configure workset with scan paths
|
88
|
+
if include:
|
89
|
+
if config.debug:
|
90
|
+
Console(stderr=True).print("[cyan]Debug: Processing include paths...[/cyan]")
|
91
|
+
for path in include:
|
92
|
+
full_path = config.workspace_dir / path
|
93
|
+
if not full_path.resolve().is_relative_to(config.workspace_dir):
|
94
|
+
error_text = Text(f"\nError: Path must be within workspace: {path}", style="red")
|
95
|
+
rich_print(error_text)
|
96
|
+
raise typer.Exit(1)
|
97
|
+
workset.add_scan_path(path, ScanType.PLAIN)
|
98
|
+
|
99
|
+
if recursive:
|
100
|
+
if config.debug:
|
101
|
+
Console(stderr=True).print("[cyan]Debug: Processing recursive paths...[/cyan]")
|
102
|
+
for path in recursive:
|
103
|
+
full_path = config.workspace_dir / path
|
104
|
+
if not path.is_dir():
|
105
|
+
error_text = Text(f"\nError: Recursive path must be a directory: {path} ", style="red")
|
106
|
+
rich_print(error_text)
|
107
|
+
raise typer.Exit(1)
|
108
|
+
if not full_path.resolve().is_relative_to(config.workspace_dir):
|
109
|
+
error_text = Text(f"\nError: Path must be within workspace: {path}", style="red")
|
110
|
+
rich_print(error_text)
|
111
|
+
raise typer.Exit(1)
|
112
|
+
workset.add_scan_path(path, ScanType.RECURSIVE)
|
113
|
+
|
114
|
+
# Validate skip_work usage
|
115
|
+
if skip_work and not workset.paths:
|
116
|
+
error_text = Text("\nError: --skip-work requires at least one include path (-i or -r)", style="red")
|
117
|
+
rich_print(error_text)
|
118
|
+
raise typer.Exit(1)
|
119
|
+
|
120
|
+
if test_cmd:
|
121
|
+
config.set_test_cmd(test_cmd)
|
122
|
+
|
123
|
+
# Refresh workset content before handling commands
|
124
|
+
workset.refresh()
|
125
|
+
|
126
|
+
if ask:
|
127
|
+
handle_ask(ask)
|
128
|
+
elif play:
|
129
|
+
handle_play(play)
|
130
|
+
elif scan:
|
131
|
+
handle_scan()
|
132
|
+
elif change_request:
|
133
|
+
handle_request(change_request)
|
134
|
+
else:
|
135
|
+
from janito.shell import start_shell
|
136
|
+
start_shell()
|
137
|
+
|
138
|
+
def main():
|
139
|
+
typer.run(typer_main)
|
140
|
+
|
141
|
+
if __name__ == "__main__":
|
142
|
+
main()
|
@@ -5,18 +5,18 @@ SYSTEM_PROMPT = """I am Janito, your friendly software development buddy. I help
|
|
5
5
|
ai_backend = os.getenv('AI_BACKEND', 'claudeai').lower()
|
6
6
|
|
7
7
|
if ai_backend == 'openai':
|
8
|
+
import warnings
|
9
|
+
warnings.warn(
|
10
|
+
"Using deprecated OpenAI backend. Please switch to Claude AI backend by removing AI_BACKEND=openai "
|
11
|
+
"from your environment variables.",
|
12
|
+
DeprecationWarning,
|
13
|
+
stacklevel=2
|
14
|
+
)
|
8
15
|
from .openai import OpenAIAgent as AIAgent
|
9
16
|
elif ai_backend == 'claudeai':
|
10
17
|
from .claudeai import ClaudeAIAgent as AIAgent
|
11
18
|
else:
|
12
19
|
raise ValueError(f"Unsupported AI_BACKEND: {ai_backend}")
|
13
20
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
@classmethod
|
18
|
-
def get_agent(cls):
|
19
|
-
if cls._instance is None:
|
20
|
-
cls._instance = AIAgent(SYSTEM_PROMPT)
|
21
|
-
return cls._instance
|
22
|
-
|
21
|
+
# Create a singleton instance
|
22
|
+
agent = AIAgent(SYSTEM_PROMPT)
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
from abc import ABC, abstractmethod
|
3
2
|
from threading import Event
|
4
3
|
from typing import Optional, List, Tuple
|
@@ -16,6 +15,14 @@ class Agent(ABC):
|
|
16
15
|
self.messages_history.append(("system", system_prompt))
|
17
16
|
|
18
17
|
@abstractmethod
|
19
|
-
def send_message(self, message: str,
|
20
|
-
"""Send message to AI
|
18
|
+
def send_message(self, message: str, system: str) -> str:
|
19
|
+
"""Send message to the AI agent
|
20
|
+
|
21
|
+
Args:
|
22
|
+
message: The message to send
|
23
|
+
stop_event: Optional event to signal cancellation
|
24
|
+
|
25
|
+
Returns:
|
26
|
+
The response from the AI agent
|
27
|
+
"""
|
21
28
|
pass
|
@@ -0,0 +1,45 @@
|
|
1
|
+
import anthropic
|
2
|
+
import os
|
3
|
+
from typing import Optional
|
4
|
+
from threading import Event
|
5
|
+
from .agent import Agent
|
6
|
+
|
7
|
+
class ClaudeAIAgent(Agent):
|
8
|
+
"""Handles interaction with Claude API, including message handling"""
|
9
|
+
DEFAULT_MODEL = "claude-3-5-sonnet-20241022"
|
10
|
+
|
11
|
+
def __init__(self, system_prompt: str = None):
|
12
|
+
self.api_key = os.getenv('ANTHROPIC_API_KEY')
|
13
|
+
super().__init__(self.api_key, system_prompt)
|
14
|
+
if not system_prompt:
|
15
|
+
raise ValueError("system_prompt is required")
|
16
|
+
|
17
|
+
if not self.api_key:
|
18
|
+
raise ValueError("ANTHROPIC_API_KEY environment variable is required")
|
19
|
+
self.client = anthropic.Client(api_key=self.api_key)
|
20
|
+
self.model = os.getenv('CLAUDE_MODEL', self.DEFAULT_MODEL)
|
21
|
+
self.system_message = system_prompt
|
22
|
+
self.last_prompt = None
|
23
|
+
self.last_full_message = None
|
24
|
+
self.last_response = None
|
25
|
+
|
26
|
+
|
27
|
+
def send_message(self, message: str, system_message: str = None) -> str:
|
28
|
+
"""Send message to Claude API and return response"""
|
29
|
+
self.messages_history.append(("user", message))
|
30
|
+
# Store the full message
|
31
|
+
self.last_full_message = message
|
32
|
+
|
33
|
+
response = self.client.messages.create(
|
34
|
+
model=self.model, # Use discovered model
|
35
|
+
system=system_message or self.system_message,
|
36
|
+
max_tokens=8192,
|
37
|
+
messages=[
|
38
|
+
{"role": "user", "content": message}
|
39
|
+
],
|
40
|
+
temperature=0,
|
41
|
+
)
|
42
|
+
|
43
|
+
|
44
|
+
# Always return the response, let caller handle cancellation
|
45
|
+
return response
|
@@ -5,7 +5,11 @@ from threading import Event
|
|
5
5
|
from .agent import Agent
|
6
6
|
|
7
7
|
class OpenAIAgent(Agent):
|
8
|
-
"""Handles interaction with OpenAI API, including message handling
|
8
|
+
"""[DEPRECATED] Handles interaction with OpenAI API, including message handling.
|
9
|
+
|
10
|
+
This backend is no longer actively maintained. Please use the Claude AI backend instead.
|
11
|
+
The code is kept for backward compatibility but may be removed in future versions.
|
12
|
+
"""
|
9
13
|
DEFAULT_MODEL = "o1-mini-2024-09-12"
|
10
14
|
|
11
15
|
def __init__(self, api_key: Optional[str] = None, system_prompt: str = None):
|
@@ -0,0 +1,32 @@
|
|
1
|
+
"""
|
2
|
+
This package provides the following change flow steps:
|
3
|
+
|
4
|
+
- Create a preview directory
|
5
|
+
- Build change request prompt
|
6
|
+
- Send change request to AI agent
|
7
|
+
- Parse the response into changes
|
8
|
+
- Save response to history file
|
9
|
+
- Preview the changes (applying them to the preview directory)
|
10
|
+
- Validate the changes
|
11
|
+
- Run tests if specified
|
12
|
+
- Show the change view (using janito.changeviewer)
|
13
|
+
- Prompt the user to apply the changes to the working directory
|
14
|
+
- Apply the changes
|
15
|
+
"""
|
16
|
+
|
17
|
+
from typing import Tuple
|
18
|
+
from pathlib import Path
|
19
|
+
from ..agents import agent # Updated import to use singleton directly
|
20
|
+
from .parser import build_change_request_prompt, parse_response
|
21
|
+
from .preview import setup_workspace_dir_preview
|
22
|
+
from .applier.main import ChangeApplier
|
23
|
+
|
24
|
+
__all__ = [
|
25
|
+
'build_change_request_prompt',
|
26
|
+
'get_change_response',
|
27
|
+
'parse_response',
|
28
|
+
'setup_workspace_dir_preview',
|
29
|
+
'parse_change_response',
|
30
|
+
'save_change_response',
|
31
|
+
'ChangeApplier'
|
32
|
+
]
|
File without changes
|
@@ -4,30 +4,20 @@ This module provides functionality for analyzing and displaying code changes.
|
|
4
4
|
"""
|
5
5
|
|
6
6
|
from .options import AnalysisOption, parse_analysis_options
|
7
|
-
from .
|
8
|
-
format_analysis,
|
9
|
-
get_history_file_type,
|
10
|
-
get_history_path,
|
11
|
-
get_timestamp,
|
12
|
-
save_to_file
|
13
|
-
)
|
7
|
+
from .view import format_analysis, prompt_user, get_option_selection
|
14
8
|
from .prompts import (
|
15
9
|
build_request_analysis_prompt,
|
16
|
-
get_option_selection,
|
17
|
-
prompt_user,
|
18
10
|
validate_option_letter
|
19
11
|
)
|
12
|
+
from .analyze import analyze_request
|
20
13
|
|
21
14
|
__all__ = [
|
22
15
|
'AnalysisOption',
|
23
16
|
'parse_analysis_options',
|
24
17
|
'format_analysis',
|
25
|
-
'get_history_file_type',
|
26
|
-
'get_history_path',
|
27
|
-
'get_timestamp',
|
28
|
-
'save_to_file',
|
29
18
|
'build_request_analysis_prompt',
|
30
19
|
'get_option_selection',
|
31
20
|
'prompt_user',
|
32
|
-
'validate_option_letter'
|
33
|
-
|
21
|
+
'validate_option_letter',
|
22
|
+
'analyze_request'
|
23
|
+
]
|