ara-cli 0.1.9.95__py3-none-any.whl → 0.1.10.0__py3-none-any.whl
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.
- ara_cli/__init__.py +5 -2
- ara_cli/__main__.py +61 -13
- ara_cli/ara_command_action.py +85 -20
- ara_cli/ara_command_parser.py +42 -2
- ara_cli/ara_config.py +118 -94
- ara_cli/artefact_autofix.py +131 -2
- ara_cli/artefact_creator.py +2 -7
- ara_cli/artefact_deleter.py +2 -4
- ara_cli/artefact_fuzzy_search.py +13 -6
- ara_cli/artefact_models/artefact_templates.py +3 -3
- ara_cli/artefact_models/feature_artefact_model.py +25 -0
- ara_cli/artefact_reader.py +4 -5
- ara_cli/chat.py +210 -150
- ara_cli/commands/extract_command.py +4 -11
- ara_cli/error_handler.py +134 -0
- ara_cli/file_classifier.py +3 -2
- ara_cli/prompt_extractor.py +1 -1
- ara_cli/prompt_handler.py +268 -127
- ara_cli/template_loader.py +245 -0
- ara_cli/version.py +1 -1
- {ara_cli-0.1.9.95.dist-info → ara_cli-0.1.10.0.dist-info}/METADATA +2 -1
- {ara_cli-0.1.9.95.dist-info → ara_cli-0.1.10.0.dist-info}/RECORD +32 -29
- tests/test_ara_command_action.py +66 -52
- tests/test_artefact_autofix.py +361 -5
- tests/test_chat.py +1894 -546
- tests/test_file_classifier.py +23 -0
- tests/test_file_creator.py +3 -5
- tests/test_prompt_handler.py +40 -4
- tests/test_template_loader.py +192 -0
- {ara_cli-0.1.9.95.dist-info → ara_cli-0.1.10.0.dist-info}/WHEEL +0 -0
- {ara_cli-0.1.9.95.dist-info → ara_cli-0.1.10.0.dist-info}/entry_points.txt +0 -0
- {ara_cli-0.1.9.95.dist-info → ara_cli-0.1.10.0.dist-info}/top_level.txt +0 -0
|
@@ -3,20 +3,13 @@ from ara_cli.prompt_extractor import extract_responses
|
|
|
3
3
|
import os
|
|
4
4
|
|
|
5
5
|
class ExtractCommand(Command):
|
|
6
|
-
def __init__(self, file_name, force=False, write=False, output=None
|
|
6
|
+
def __init__(self, file_name, force=False, write=False, output=None):
|
|
7
7
|
self.file_name = file_name
|
|
8
8
|
self.force = force
|
|
9
9
|
self.write = write
|
|
10
10
|
self.output = output # Callable for standard output (optional)
|
|
11
|
-
self.error_output = error_output # Callable for errors (optional)
|
|
12
11
|
|
|
13
12
|
def execute(self, *args, **kwargs):
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
self.output("End of extraction")
|
|
18
|
-
except Exception as e:
|
|
19
|
-
if self.error_output:
|
|
20
|
-
self.error_output(f"Extraction failed: {e}")
|
|
21
|
-
else:
|
|
22
|
-
raise
|
|
13
|
+
extract_responses(self.file_name, True, force=self.force, write=self.write)
|
|
14
|
+
if self.output:
|
|
15
|
+
self.output("End of extraction")
|
ara_cli/error_handler.py
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import traceback
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from functools import wraps
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
RED = '\033[91m'
|
|
9
|
+
RESET = '\033[0m'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ErrorLevel(Enum):
|
|
13
|
+
INFO = "INFO"
|
|
14
|
+
WARNING = "WARNING"
|
|
15
|
+
ERROR = "ERROR"
|
|
16
|
+
CRITICAL = "CRITICAL"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class AraError(Exception):
|
|
20
|
+
"""Base exception class for ARA CLI errors"""
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self, message: str, error_code: int = 1, level: ErrorLevel = ErrorLevel.ERROR
|
|
24
|
+
):
|
|
25
|
+
self.message = message
|
|
26
|
+
self.error_code = error_code
|
|
27
|
+
self.level = level
|
|
28
|
+
super().__init__(self.message)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class AraValidationError(AraError):
|
|
32
|
+
"""Raised when validation fails"""
|
|
33
|
+
|
|
34
|
+
def __init__(self, message: str):
|
|
35
|
+
super().__init__(message, error_code=2, level=ErrorLevel.ERROR)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class AraConfigurationError(AraError):
|
|
39
|
+
"""Raised when configuration is invalid"""
|
|
40
|
+
|
|
41
|
+
def __init__(self, message: str):
|
|
42
|
+
super().__init__(message, error_code=4, level=ErrorLevel.ERROR)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ErrorHandler:
|
|
46
|
+
"""Centralized error handler for ARA CLI"""
|
|
47
|
+
|
|
48
|
+
def __init__(self, debug_mode: bool = False):
|
|
49
|
+
self.debug_mode = debug_mode
|
|
50
|
+
|
|
51
|
+
def handle_error(self, error: Exception, context: Optional[str] = None) -> None:
|
|
52
|
+
"""Handle any error with standardized output"""
|
|
53
|
+
if isinstance(error, AraError):
|
|
54
|
+
self._handle_ara_error(error, context)
|
|
55
|
+
else:
|
|
56
|
+
self._handle_generic_error(error, context)
|
|
57
|
+
|
|
58
|
+
def _handle_ara_error(self, error: AraError, context: Optional[str] = None) -> None:
|
|
59
|
+
"""Handle ARA-specific errors"""
|
|
60
|
+
self._report_ara_error(error, context)
|
|
61
|
+
|
|
62
|
+
sys.exit(error.error_code)
|
|
63
|
+
|
|
64
|
+
def _handle_generic_error(
|
|
65
|
+
self, error: Exception, context: Optional[str] = None
|
|
66
|
+
) -> None:
|
|
67
|
+
"""Handle generic Python errors"""
|
|
68
|
+
self._report_generic_error(error, context)
|
|
69
|
+
|
|
70
|
+
sys.exit(1)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def report_error(self, error: Exception, context: Optional[str] = None) -> None:
|
|
74
|
+
"""Report error with standardized formatting but don't exit"""
|
|
75
|
+
if isinstance(error, AraError):
|
|
76
|
+
self._report_ara_error(error, context)
|
|
77
|
+
else:
|
|
78
|
+
self._report_generic_error(error, context)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _report_ara_error(self, error: AraError, context: Optional[str] = None) -> None:
|
|
82
|
+
"""Report ARA-specific errors without exiting"""
|
|
83
|
+
error_prefix = f"[{error.level.value}]"
|
|
84
|
+
|
|
85
|
+
if context:
|
|
86
|
+
print(f"{RED}{error_prefix} {context}: {error.message}{RESET}", file=sys.stderr)
|
|
87
|
+
else:
|
|
88
|
+
print(f"{RED}{error_prefix} {error.message}{RESET}", file=sys.stderr)
|
|
89
|
+
|
|
90
|
+
if self.debug_mode:
|
|
91
|
+
traceback.print_exc()
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _report_generic_error(self, error: Exception, context: Optional[str] = None) -> None:
|
|
95
|
+
"""Report generic Python errors without exiting"""
|
|
96
|
+
error_type = type(error).__name__
|
|
97
|
+
|
|
98
|
+
if context:
|
|
99
|
+
print(f"{RED}[ERROR] {context}: {error_type}: {str(error)}{RESET}", file=sys.stderr)
|
|
100
|
+
else:
|
|
101
|
+
print(f"{RED}[ERROR] {error_type}: {str(error)}{RESET}", file=sys.stderr)
|
|
102
|
+
|
|
103
|
+
if self.debug_mode:
|
|
104
|
+
traceback.print_exc()
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def validate_and_exit(
|
|
108
|
+
self, condition: bool, message: str, error_code: int = 1
|
|
109
|
+
) -> None:
|
|
110
|
+
"""Validate condition and exit with error if false"""
|
|
111
|
+
if not condition:
|
|
112
|
+
raise AraValidationError(message)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def handle_errors(_func=None, context: Optional[str] = None, error_handler: Optional[ErrorHandler] = None):
|
|
116
|
+
"""Decorator to handle errors in action functions"""
|
|
117
|
+
|
|
118
|
+
def decorator(func):
|
|
119
|
+
@wraps(func)
|
|
120
|
+
def wrapper(*args, **kwargs):
|
|
121
|
+
nonlocal error_handler
|
|
122
|
+
if error_handler is None:
|
|
123
|
+
error_handler = ErrorHandler()
|
|
124
|
+
|
|
125
|
+
try:
|
|
126
|
+
return func(*args, **kwargs)
|
|
127
|
+
except Exception as e:
|
|
128
|
+
error_handler.handle_error(e, context or func.__name__)
|
|
129
|
+
|
|
130
|
+
return wrapper
|
|
131
|
+
|
|
132
|
+
if callable(_func):
|
|
133
|
+
return decorator(_func)
|
|
134
|
+
return decorator
|
ara_cli/file_classifier.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from . import error_handler
|
|
1
2
|
from ara_cli.classifier import Classifier
|
|
2
3
|
from ara_cli.artefact_models.artefact_model import Artefact
|
|
3
4
|
from ara_cli.artefact_fuzzy_search import find_closest_name_matches
|
|
@@ -33,8 +34,8 @@ class FileClassifier:
|
|
|
33
34
|
if byte > 127:
|
|
34
35
|
return True
|
|
35
36
|
except Exception as e:
|
|
36
|
-
|
|
37
|
-
print(f"Error while checking if file is binary: {e}")
|
|
37
|
+
error_handler.report_error(e, "checking if file is binary")
|
|
38
|
+
# print(f"Error while checking if file is binary: {e}")
|
|
38
39
|
return False
|
|
39
40
|
|
|
40
41
|
def read_file_with_fallback(self, file_path):
|
ara_cli/prompt_extractor.py
CHANGED
|
@@ -17,7 +17,7 @@ def extract_code_blocks_md(markdown_text):
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
def extract_responses(document_path, relative_to_ara_root=False, force=False, write=False):
|
|
20
|
-
print(f"
|
|
20
|
+
print(f"Starting extraction from '{document_path}'")
|
|
21
21
|
block_extraction_counter = 0
|
|
22
22
|
|
|
23
23
|
with open(document_path, 'r', encoding='utf-8', errors='replace') as file:
|