janito 0.3.0__tar.gz → 0.4.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.3.0 → janito-0.4.0}/PKG-INFO +34 -8
- {janito-0.3.0 → janito-0.4.0}/README.md +32 -7
- {janito-0.3.0 → janito-0.4.0}/janito/__main__.py +158 -59
- janito-0.4.0/janito/analysis.py +281 -0
- janito-0.4.0/janito/changeapplier.py +436 -0
- janito-0.4.0/janito/changeviewer.py +350 -0
- janito-0.4.0/janito/claude.py +59 -0
- janito-0.4.0/janito/common.py +23 -0
- {janito-0.3.0 → janito-0.4.0}/janito/config.py +8 -3
- janito-0.4.0/janito/console.py +330 -0
- janito-0.4.0/janito/contentchange.py +84 -0
- janito-0.4.0/janito/contextparser.py +113 -0
- janito-0.4.0/janito/fileparser.py +125 -0
- janito-0.4.0/janito/prompts.py +66 -0
- janito-0.4.0/janito/qa.py +63 -0
- {janito-0.3.0 → janito-0.4.0}/janito/scan.py +24 -9
- janito-0.4.0/janito/version.py +23 -0
- {janito-0.3.0 → janito-0.4.0}/pyproject.toml +2 -1
- janito-0.4.0/tests/conftest.py +45 -0
- janito-0.4.0/tests/test_contentchange.py +68 -0
- janito-0.4.0/tests/test_integration.py +64 -0
- janito-0.4.0/tests/test_prompts.py +59 -0
- janito-0.4.0/tests/test_scan.py +98 -0
- janito-0.3.0/CHANGELOG.md +0 -26
- janito-0.3.0/janito/changeviewer.py +0 -64
- janito-0.3.0/janito/claude.py +0 -74
- janito-0.3.0/janito/console.py +0 -60
- janito-0.3.0/janito/contentchange.py +0 -165
- janito-0.3.0/janito/prompts.py +0 -97
- janito-0.3.0/janito/qa.py +0 -32
- janito-0.3.0/tests/__init__.py +0 -2
- janito-0.3.0/tests/test_main.py +0 -51
- {janito-0.3.0 → janito-0.4.0}/.gitignore +0 -0
- {janito-0.3.0 → janito-0.4.0}/LICENSE +0 -0
- {janito-0.3.0 → janito-0.4.0}/janito/__init__.py +0 -0
- {janito-0.3.0 → janito-0.4.0}/setup.py +0 -0
- {janito-0.3.0 → janito-0.4.0}/tools/release.sh +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: janito
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.4.0
|
4
4
|
Summary: A CLI tool for software development tasks powered by AI
|
5
5
|
Project-URL: Homepage, https://github.com/joaompinto/janito
|
6
6
|
Project-URL: Repository, https://github.com/joaompinto/janito.git
|
@@ -18,6 +18,7 @@ Requires-Python: >=3.8
|
|
18
18
|
Requires-Dist: anthropic
|
19
19
|
Requires-Dist: pathspec
|
20
20
|
Requires-Dist: rich
|
21
|
+
Requires-Dist: tomli
|
21
22
|
Requires-Dist: typer
|
22
23
|
Description-Content-Type: text/markdown
|
23
24
|
|
@@ -25,7 +26,7 @@ Description-Content-Type: text/markdown
|
|
25
26
|
|
26
27
|
A CLI tool for software development tasks powered by AI.
|
27
28
|
|
28
|
-
Janito
|
29
|
+
Meet Janito, your friendly AI-powered software development buddy! Janito helps you with coding tasks like refactoring, documentation updates, and code optimization while being clear and concise in its responses.
|
29
30
|
|
30
31
|
## 📥 Installation
|
31
32
|
|
@@ -59,6 +60,15 @@ export ANTHROPIC_API_KEY='your-api-key-here'
|
|
59
60
|
|
60
61
|
You can also add this to your shell profile (~/.bashrc, ~/.zshrc, etc.) for persistence.
|
61
62
|
|
63
|
+
### ⚙️ Test Command Setup
|
64
|
+
You can configure a test command to run before applying changes:
|
65
|
+
|
66
|
+
```bash
|
67
|
+
export JANITO_TEST_CMD='your-test-command'
|
68
|
+
```
|
69
|
+
|
70
|
+
This command will be executed in the preview directory before applying changes to verify they don't break anything.
|
71
|
+
|
62
72
|
## 📖 Usage
|
63
73
|
|
64
74
|
Janito can be used in two modes: Command Line or Interactive Console.
|
@@ -70,17 +80,26 @@ janito REQUEST [OPTIONS]
|
|
70
80
|
```
|
71
81
|
|
72
82
|
#### Arguments
|
73
|
-
- `REQUEST`: The modification request
|
83
|
+
- `REQUEST`: The modification request to process (optional)
|
74
84
|
|
75
85
|
#### Options
|
86
|
+
##### General Options
|
87
|
+
- `--version`: Show version and exit
|
76
88
|
- `-w, --workdir PATH`: Working directory (defaults to current directory)
|
77
|
-
-
|
89
|
+
- `-i, --include PATH`: Additional paths to include in analysis (can be used multiple times)
|
90
|
+
|
91
|
+
##### Operation Modes
|
92
|
+
- `--ask TEXT`: Ask a question about the codebase instead of making changes
|
93
|
+
- `--scan`: Preview files that would be analyzed without making changes
|
78
94
|
- `--play PATH`: Replay a saved prompt file
|
79
|
-
|
80
|
-
|
95
|
+
|
96
|
+
##### Output Control
|
97
|
+
- `--raw`: Print raw response instead of markdown format
|
81
98
|
- `-v, --verbose`: Show verbose output
|
82
|
-
- `--
|
83
|
-
|
99
|
+
- `--debug`: Show debug information
|
100
|
+
|
101
|
+
##### Testing
|
102
|
+
- `-t, --test COMMAND`: Test command to run before applying changes (overrides JANITO_TEST_CMD)
|
84
103
|
|
85
104
|
### 🖥️ Interactive Console Mode
|
86
105
|
|
@@ -105,6 +124,12 @@ janito "update tests" -i ./tests -i ./lib
|
|
105
124
|
janito --ask "explain the authentication flow"
|
106
125
|
janito --scan # Preview files to be analyzed
|
107
126
|
|
127
|
+
# Test Command Examples
|
128
|
+
janito "update code" --test "pytest" # Run pytest before applying changes
|
129
|
+
janito "refactor module" -t "make test" # Run make test before applying
|
130
|
+
export JANITO_TEST_CMD="python -m unittest" # Set default test command
|
131
|
+
janito "optimize function" # Will use JANITO_TEST_CMD
|
132
|
+
|
108
133
|
# Console Mode
|
109
134
|
janito # Starts interactive session
|
110
135
|
```
|
@@ -120,6 +145,7 @@ janito # Starts interactive session
|
|
120
145
|
- 🐛 Debug and verbose output modes
|
121
146
|
- ❓ Question-answering about codebase
|
122
147
|
- 🔍 File scanning preview
|
148
|
+
- 🧪 Test command execution before applying changes
|
123
149
|
|
124
150
|
## 📚 History and Debugging
|
125
151
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
A CLI tool for software development tasks powered by AI.
|
4
4
|
|
5
|
-
Janito
|
5
|
+
Meet Janito, your friendly AI-powered software development buddy! Janito helps you with coding tasks like refactoring, documentation updates, and code optimization while being clear and concise in its responses.
|
6
6
|
|
7
7
|
## 📥 Installation
|
8
8
|
|
@@ -36,6 +36,15 @@ export ANTHROPIC_API_KEY='your-api-key-here'
|
|
36
36
|
|
37
37
|
You can also add this to your shell profile (~/.bashrc, ~/.zshrc, etc.) for persistence.
|
38
38
|
|
39
|
+
### ⚙️ Test Command Setup
|
40
|
+
You can configure a test command to run before applying changes:
|
41
|
+
|
42
|
+
```bash
|
43
|
+
export JANITO_TEST_CMD='your-test-command'
|
44
|
+
```
|
45
|
+
|
46
|
+
This command will be executed in the preview directory before applying changes to verify they don't break anything.
|
47
|
+
|
39
48
|
## 📖 Usage
|
40
49
|
|
41
50
|
Janito can be used in two modes: Command Line or Interactive Console.
|
@@ -47,17 +56,26 @@ janito REQUEST [OPTIONS]
|
|
47
56
|
```
|
48
57
|
|
49
58
|
#### Arguments
|
50
|
-
- `REQUEST`: The modification request
|
59
|
+
- `REQUEST`: The modification request to process (optional)
|
51
60
|
|
52
61
|
#### Options
|
62
|
+
##### General Options
|
63
|
+
- `--version`: Show version and exit
|
53
64
|
- `-w, --workdir PATH`: Working directory (defaults to current directory)
|
54
|
-
-
|
65
|
+
- `-i, --include PATH`: Additional paths to include in analysis (can be used multiple times)
|
66
|
+
|
67
|
+
##### Operation Modes
|
68
|
+
- `--ask TEXT`: Ask a question about the codebase instead of making changes
|
69
|
+
- `--scan`: Preview files that would be analyzed without making changes
|
55
70
|
- `--play PATH`: Replay a saved prompt file
|
56
|
-
|
57
|
-
|
71
|
+
|
72
|
+
##### Output Control
|
73
|
+
- `--raw`: Print raw response instead of markdown format
|
58
74
|
- `-v, --verbose`: Show verbose output
|
59
|
-
- `--
|
60
|
-
|
75
|
+
- `--debug`: Show debug information
|
76
|
+
|
77
|
+
##### Testing
|
78
|
+
- `-t, --test COMMAND`: Test command to run before applying changes (overrides JANITO_TEST_CMD)
|
61
79
|
|
62
80
|
### 🖥️ Interactive Console Mode
|
63
81
|
|
@@ -82,6 +100,12 @@ janito "update tests" -i ./tests -i ./lib
|
|
82
100
|
janito --ask "explain the authentication flow"
|
83
101
|
janito --scan # Preview files to be analyzed
|
84
102
|
|
103
|
+
# Test Command Examples
|
104
|
+
janito "update code" --test "pytest" # Run pytest before applying changes
|
105
|
+
janito "refactor module" -t "make test" # Run make test before applying
|
106
|
+
export JANITO_TEST_CMD="python -m unittest" # Set default test command
|
107
|
+
janito "optimize function" # Will use JANITO_TEST_CMD
|
108
|
+
|
85
109
|
# Console Mode
|
86
110
|
janito # Starts interactive session
|
87
111
|
```
|
@@ -97,6 +121,7 @@ janito # Starts interactive session
|
|
97
121
|
- 🐛 Debug and verbose output modes
|
98
122
|
- ❓ Question-answering about codebase
|
99
123
|
- 🔍 File scanning preview
|
124
|
+
- 🧪 Test command execution before applying changes
|
100
125
|
|
101
126
|
## 📚 History and Debugging
|
102
127
|
|
@@ -1,13 +1,12 @@
|
|
1
|
+
import sys
|
1
2
|
import typer
|
2
3
|
from typing import Optional, Dict, Any, List
|
3
4
|
from pathlib import Path
|
4
5
|
from janito.claude import ClaudeAPIAgent
|
5
6
|
import shutil
|
6
7
|
from janito.prompts import (
|
7
|
-
build_request_analisys_prompt,
|
8
8
|
build_selected_option_prompt,
|
9
|
-
SYSTEM_PROMPT,
|
10
|
-
parse_options
|
9
|
+
SYSTEM_PROMPT,
|
11
10
|
)
|
12
11
|
from rich.console import Console
|
13
12
|
from rich.markdown import Markdown
|
@@ -34,54 +33,51 @@ from janito.scan import collect_files_content, is_dir_empty, preview_scan
|
|
34
33
|
from janito.qa import ask_question, display_answer
|
35
34
|
from rich.prompt import Prompt, Confirm
|
36
35
|
from janito.config import config
|
37
|
-
from
|
36
|
+
from janito.version import get_version
|
37
|
+
from janito.common import progress_send_message
|
38
|
+
from janito.analysis import format_analysis, build_request_analysis_prompt, parse_analysis_options, get_history_file_type, AnalysisOption
|
38
39
|
|
39
|
-
def get_version() -> str:
|
40
|
-
try:
|
41
|
-
return version("janito")
|
42
|
-
except:
|
43
|
-
return "dev"
|
44
|
-
|
45
|
-
def format_analysis(analysis: str, raw: bool = False, claude: Optional[ClaudeAPIAgent] = None) -> None:
|
46
|
-
"""Format and display the analysis output"""
|
47
|
-
console = Console()
|
48
|
-
if raw and claude:
|
49
|
-
console.print("\n=== Message History ===")
|
50
|
-
for role, content in claude.messages_history:
|
51
|
-
console.print(f"\n[bold cyan]{role.upper()}:[/bold cyan]")
|
52
|
-
console.print(content)
|
53
|
-
console.print("\n=== End Message History ===\n")
|
54
|
-
else:
|
55
|
-
md = Markdown(analysis)
|
56
|
-
console.print(md)
|
57
40
|
|
58
41
|
def prompt_user(message: str, choices: List[str] = None) -> str:
|
59
|
-
"""Display a prominent user prompt with optional choices"""
|
42
|
+
"""Display a prominent user prompt with optional choices using consistent colors"""
|
60
43
|
console = Console()
|
44
|
+
|
45
|
+
# Define consistent colors
|
46
|
+
COLORS = {
|
47
|
+
'primary': '#729FCF', # Soft blue for primary elements
|
48
|
+
'secondary': '#8AE234', # Bright green for actions/success
|
49
|
+
'accent': '#AD7FA8', # Purple for accents
|
50
|
+
'muted': '#7F9F7F', # Muted green for less important text
|
51
|
+
}
|
52
|
+
|
61
53
|
console.print()
|
62
|
-
console.print(Rule(" User Input Required ", style="bold
|
54
|
+
console.print(Rule(" User Input Required ", style=f"bold {COLORS['primary']}"))
|
63
55
|
|
64
56
|
if choices:
|
65
|
-
choice_text = f"[
|
66
|
-
console.print(Panel(choice_text, box=box.ROUNDED))
|
57
|
+
choice_text = f"[{COLORS['accent']}]Options: {', '.join(choices)}[/{COLORS['accent']}]"
|
58
|
+
console.print(Panel(choice_text, box=box.ROUNDED, border_style=COLORS['primary']))
|
67
59
|
|
68
|
-
return Prompt.ask(f"[bold
|
60
|
+
return Prompt.ask(f"[bold {COLORS['secondary']}]> {message}[/bold {COLORS['secondary']}]")
|
69
61
|
|
70
|
-
def
|
71
|
-
"""
|
62
|
+
def validate_option_letter(letter: str, options: dict) -> bool:
|
63
|
+
"""Validate if the given letter is a valid option or 'M' for modify"""
|
64
|
+
return letter.upper() in options or letter.upper() == 'M'
|
65
|
+
|
66
|
+
def get_option_selection() -> str:
|
67
|
+
"""Get user input for option selection with modify option"""
|
68
|
+
console = Console()
|
69
|
+
console.print("\n[cyan]Enter option letter or 'M' to modify request[/cyan]")
|
72
70
|
while True:
|
73
|
-
|
74
|
-
|
75
|
-
return
|
76
|
-
|
77
|
-
console = Console()
|
78
|
-
console.print("[red]Please enter a valid number[/red]")
|
71
|
+
letter = prompt_user("Select option").strip().upper()
|
72
|
+
if letter == 'M' or (letter.isalpha() and len(letter) == 1):
|
73
|
+
return letter
|
74
|
+
console.print("[red]Please enter a valid letter or 'M'[/red]")
|
79
75
|
|
80
|
-
def
|
81
|
-
"""Create and return the history directory path"""
|
82
|
-
|
83
|
-
|
84
|
-
return
|
76
|
+
def get_changes_history_path(workdir: Path) -> Path:
|
77
|
+
"""Create and return the changes history directory path"""
|
78
|
+
changes_history_dir = workdir / '.janito' / 'changes_history'
|
79
|
+
changes_history_dir.mkdir(parents=True, exist_ok=True)
|
80
|
+
return changes_history_dir
|
85
81
|
|
86
82
|
def get_timestamp() -> str:
|
87
83
|
"""Get current UTC timestamp in YMD_HMS format with leading zeros"""
|
@@ -95,46 +91,148 @@ def save_prompt_to_file(prompt: str) -> Path:
|
|
95
91
|
return temp_path
|
96
92
|
|
97
93
|
def save_to_file(content: str, prefix: str, workdir: Path) -> Path:
|
98
|
-
"""Save content to a timestamped file in history directory"""
|
99
|
-
|
94
|
+
"""Save content to a timestamped file in changes history directory"""
|
95
|
+
changes_history_dir = get_changes_history_path(workdir)
|
100
96
|
timestamp = get_timestamp()
|
101
97
|
filename = f"{timestamp}_{prefix}.txt"
|
102
|
-
file_path =
|
98
|
+
file_path = changes_history_dir / filename
|
103
99
|
file_path.write_text(content)
|
104
100
|
return file_path
|
105
101
|
|
102
|
+
def modify_request(request: str) -> str:
|
103
|
+
"""Display current request and get modified version with improved formatting"""
|
104
|
+
console = Console()
|
105
|
+
|
106
|
+
# Display current request in a panel with clear formatting
|
107
|
+
console.print("\n[bold cyan]Current Request:[/bold cyan]")
|
108
|
+
console.print(Panel(
|
109
|
+
Text(request, style="white"),
|
110
|
+
border_style="blue",
|
111
|
+
title="Previous Request",
|
112
|
+
padding=(1, 2)
|
113
|
+
))
|
114
|
+
|
115
|
+
# Get modified request with clear prompt
|
116
|
+
console.print("\n[bold cyan]Enter modified request below:[/bold cyan]")
|
117
|
+
console.print("[dim](Press Enter to submit, Ctrl+C to cancel)[/dim]")
|
118
|
+
try:
|
119
|
+
new_request = prompt_user("Modified request")
|
120
|
+
if not new_request.strip():
|
121
|
+
console.print("[yellow]No changes made, keeping original request[/yellow]")
|
122
|
+
return request
|
123
|
+
return new_request
|
124
|
+
except KeyboardInterrupt:
|
125
|
+
console.print("\n[yellow]Modification cancelled, keeping original request[/yellow]")
|
126
|
+
return request
|
127
|
+
|
128
|
+
def format_option_text(option: AnalysisOption) -> str:
|
129
|
+
"""Format an AnalysisOption into a string representation"""
|
130
|
+
option_text = f"Option {option.letter}:\n"
|
131
|
+
option_text += f"Summary: {option.summary}\n\n"
|
132
|
+
option_text += "Description:\n"
|
133
|
+
for item in option.description_items:
|
134
|
+
option_text += f"- {item}\n"
|
135
|
+
option_text += "\nAffected files:\n"
|
136
|
+
for file in option.affected_files:
|
137
|
+
option_text += f"- {file}\n"
|
138
|
+
return option_text
|
139
|
+
|
106
140
|
def handle_option_selection(claude: ClaudeAPIAgent, initial_response: str, request: str, raw: bool = False, workdir: Optional[Path] = None, include: Optional[List[Path]] = None) -> None:
|
107
141
|
"""Handle option selection and implementation details"""
|
108
|
-
|
142
|
+
options = parse_analysis_options(initial_response)
|
143
|
+
if not options:
|
144
|
+
console = Console()
|
145
|
+
console.print("[red]No valid options found in the response[/red]")
|
146
|
+
return
|
147
|
+
|
148
|
+
while True:
|
149
|
+
option = get_option_selection()
|
150
|
+
|
151
|
+
if option == 'M':
|
152
|
+
# Use the new modify_request function for better UX
|
153
|
+
new_request = modify_request(request)
|
154
|
+
if new_request == request:
|
155
|
+
continue
|
156
|
+
|
157
|
+
# Rerun analysis with new request
|
158
|
+
paths_to_scan = [workdir] if workdir else []
|
159
|
+
if include:
|
160
|
+
paths_to_scan.extend(include)
|
161
|
+
files_content = collect_files_content(paths_to_scan, workdir) if paths_to_scan else ""
|
162
|
+
|
163
|
+
initial_prompt = build_request_analysis_prompt(files_content, new_request)
|
164
|
+
initial_response = progress_send_message(claude, initial_prompt)
|
165
|
+
save_to_file(initial_response, 'analysis', workdir)
|
166
|
+
|
167
|
+
format_analysis(initial_response, raw, claude)
|
168
|
+
options = parse_analysis_options(initial_response)
|
169
|
+
if not options:
|
170
|
+
console = Console()
|
171
|
+
console.print("[red]No valid options found in the response[/red]")
|
172
|
+
return
|
173
|
+
continue
|
174
|
+
|
175
|
+
if not validate_option_letter(option, options):
|
176
|
+
console = Console()
|
177
|
+
console.print(f"[red]Invalid option '{option}'. Valid options are: {', '.join(options.keys())} or 'M' to modify[/red]")
|
178
|
+
continue
|
179
|
+
|
180
|
+
break
|
181
|
+
|
109
182
|
paths_to_scan = [workdir] if workdir else []
|
110
183
|
if include:
|
111
184
|
paths_to_scan.extend(include)
|
112
185
|
files_content = collect_files_content(paths_to_scan, workdir) if paths_to_scan else ""
|
113
186
|
|
114
|
-
|
187
|
+
# Format the selected option before building prompt
|
188
|
+
selected_option = options[option]
|
189
|
+
option_text = format_option_text(selected_option)
|
190
|
+
|
191
|
+
# Remove initial_response from the arguments
|
192
|
+
selected_prompt = build_selected_option_prompt(option_text, request, files_content)
|
115
193
|
prompt_file = save_to_file(selected_prompt, 'selected', workdir)
|
116
194
|
if config.verbose:
|
117
195
|
print(f"\nSelected prompt saved to: {prompt_file}")
|
118
196
|
|
119
|
-
selected_response = claude
|
197
|
+
selected_response = progress_send_message(claude, selected_prompt)
|
120
198
|
changes_file = save_to_file(selected_response, 'changes', workdir)
|
199
|
+
|
121
200
|
if config.verbose:
|
122
|
-
|
201
|
+
try:
|
202
|
+
rel_path = changes_file.relative_to(workdir)
|
203
|
+
print(f"\nChanges saved to: ./{rel_path}")
|
204
|
+
except ValueError:
|
205
|
+
print(f"\nChanges saved to: {changes_file}")
|
123
206
|
|
124
207
|
changes = parse_block_changes(selected_response)
|
125
|
-
preview_and_apply_changes(changes, workdir)
|
208
|
+
preview_and_apply_changes(changes, workdir, config.test_cmd)
|
126
209
|
|
127
210
|
def replay_saved_file(filepath: Path, claude: ClaudeAPIAgent, workdir: Path, raw: bool = False) -> None:
|
128
211
|
"""Process a saved prompt file and display the response"""
|
129
212
|
if not filepath.exists():
|
130
213
|
raise FileNotFoundError(f"File {filepath} not found")
|
131
214
|
|
132
|
-
file_type = get_file_type(filepath)
|
133
215
|
content = filepath.read_text()
|
134
216
|
|
217
|
+
# Add debug output of file content
|
218
|
+
if config.debug:
|
219
|
+
console = Console()
|
220
|
+
console.print("\n[bold blue]Debug: File Content[/bold blue]")
|
221
|
+
console.print(Panel(
|
222
|
+
content,
|
223
|
+
title=f"Content of {filepath.name}",
|
224
|
+
border_style="blue",
|
225
|
+
padding=(1, 2)
|
226
|
+
))
|
227
|
+
console.print()
|
228
|
+
|
229
|
+
file_type = get_history_file_type(filepath)
|
230
|
+
|
135
231
|
if file_type == 'changes':
|
136
232
|
changes = parse_block_changes(content)
|
137
|
-
preview_and_apply_changes(changes, workdir)
|
233
|
+
success = preview_and_apply_changes(changes, workdir, config.test_cmd)
|
234
|
+
if not success:
|
235
|
+
raise typer.Exit(1)
|
138
236
|
elif file_type == 'analysis':
|
139
237
|
format_analysis(content, raw, claude)
|
140
238
|
handle_option_selection(claude, content, content, raw, workdir)
|
@@ -144,14 +242,15 @@ def replay_saved_file(filepath: Path, claude: ClaudeAPIAgent, workdir: Path, raw
|
|
144
242
|
console.print("\n=== Prompt Content ===")
|
145
243
|
console.print(content)
|
146
244
|
console.print("=== End Prompt Content ===\n")
|
147
|
-
|
245
|
+
|
246
|
+
response = progress_send_message(claude, content)
|
148
247
|
changes_file = save_to_file(response, 'changes_', workdir)
|
149
248
|
print(f"\nChanges saved to: {changes_file}")
|
150
249
|
|
151
250
|
changes = parse_block_changes(response)
|
152
|
-
preview_and_apply_changes(
|
251
|
+
preview_and_apply_changes(changes, workdir, config.test_cmd)
|
153
252
|
else:
|
154
|
-
response = claude
|
253
|
+
response = progress_send_message(claude, content)
|
155
254
|
format_analysis(response, raw)
|
156
255
|
|
157
256
|
def process_question(question: str, workdir: Path, include: List[Path], raw: bool, claude: ClaudeAPIAgent) -> None:
|
@@ -160,7 +259,6 @@ def process_question(question: str, workdir: Path, include: List[Path], raw: boo
|
|
160
259
|
if include:
|
161
260
|
paths_to_scan.extend(include)
|
162
261
|
files_content = collect_files_content(paths_to_scan, workdir)
|
163
|
-
|
164
262
|
answer = ask_question(question, files_content, claude)
|
165
263
|
display_answer(answer, raw)
|
166
264
|
|
@@ -187,14 +285,15 @@ def typer_main(
|
|
187
285
|
play: Optional[Path] = typer.Option(None, "--play", help="Replay a saved prompt file"),
|
188
286
|
include: Optional[List[Path]] = typer.Option(None, "-i", "--include", help="Additional paths to include in analysis", exists=True),
|
189
287
|
debug: bool = typer.Option(False, "--debug", help="Show debug information"),
|
190
|
-
debug_line: Optional[int] = typer.Option(None, "--debug-line", help="Show debug information only for specific line number"),
|
191
288
|
verbose: bool = typer.Option(False, "-v", "--verbose", help="Show verbose output"),
|
192
289
|
scan: bool = typer.Option(False, "--scan", help="Preview files that would be analyzed"),
|
193
290
|
version: bool = typer.Option(False, "--version", help="Show version and exit"),
|
291
|
+
test: Optional[str] = typer.Option(None, "-t", "--test", help="Test command to run before applying changes"),
|
194
292
|
) -> None:
|
195
293
|
"""
|
196
294
|
Analyze files and provide modification instructions.
|
197
295
|
"""
|
296
|
+
|
198
297
|
if version:
|
199
298
|
console = Console()
|
200
299
|
console.print(f"Janito v{get_version()}")
|
@@ -202,7 +301,7 @@ def typer_main(
|
|
202
301
|
|
203
302
|
config.set_debug(debug)
|
204
303
|
config.set_verbose(verbose)
|
205
|
-
config.
|
304
|
+
config.set_test_cmd(test)
|
206
305
|
|
207
306
|
claude = ClaudeAPIAgent(system_prompt=SYSTEM_PROMPT)
|
208
307
|
|
@@ -245,9 +344,9 @@ def typer_main(
|
|
245
344
|
else:
|
246
345
|
files_content = collect_files_content(paths_to_scan, workdir)
|
247
346
|
|
248
|
-
initial_prompt =
|
249
|
-
initial_response = claude
|
250
|
-
|
347
|
+
initial_prompt = build_request_analysis_prompt(files_content, request)
|
348
|
+
initial_response = progress_send_message(claude, initial_prompt)
|
349
|
+
save_to_file(initial_response, 'analysis', workdir)
|
251
350
|
|
252
351
|
format_analysis(initial_response, raw, claude)
|
253
352
|
|