ara-cli 0.1.10.5__py3-none-any.whl → 0.1.13.3__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.
Files changed (106) hide show
  1. ara_cli/__init__.py +51 -6
  2. ara_cli/__main__.py +87 -75
  3. ara_cli/ara_command_action.py +95 -57
  4. ara_cli/ara_config.py +187 -128
  5. ara_cli/ara_subcommands/common.py +2 -2
  6. ara_cli/ara_subcommands/config.py +221 -0
  7. ara_cli/ara_subcommands/convert.py +43 -0
  8. ara_cli/ara_subcommands/fetch.py +41 -0
  9. ara_cli/ara_subcommands/fetch_agents.py +22 -0
  10. ara_cli/ara_subcommands/fetch_scripts.py +19 -0
  11. ara_cli/ara_subcommands/fetch_templates.py +15 -10
  12. ara_cli/ara_subcommands/list.py +97 -23
  13. ara_cli/artefact_autofix.py +115 -62
  14. ara_cli/artefact_converter.py +256 -0
  15. ara_cli/chat.py +283 -62
  16. ara_cli/chat_agent/__init__.py +0 -0
  17. ara_cli/chat_agent/agent_process_manager.py +155 -0
  18. ara_cli/chat_script_runner/__init__.py +0 -0
  19. ara_cli/chat_script_runner/script_completer.py +23 -0
  20. ara_cli/chat_script_runner/script_finder.py +41 -0
  21. ara_cli/chat_script_runner/script_lister.py +36 -0
  22. ara_cli/chat_script_runner/script_runner.py +36 -0
  23. ara_cli/chat_web_search/__init__.py +0 -0
  24. ara_cli/chat_web_search/web_search.py +263 -0
  25. ara_cli/commands/agent_run_command.py +98 -0
  26. ara_cli/commands/fetch_agents_command.py +106 -0
  27. ara_cli/commands/fetch_scripts_command.py +43 -0
  28. ara_cli/commands/fetch_templates_command.py +39 -0
  29. ara_cli/commands/fetch_templates_commands.py +39 -0
  30. ara_cli/commands/list_agents_command.py +39 -0
  31. ara_cli/completers.py +71 -35
  32. ara_cli/constants.py +2 -0
  33. ara_cli/directory_navigator.py +37 -4
  34. ara_cli/llm_utils.py +58 -0
  35. ara_cli/prompt_chat.py +20 -4
  36. ara_cli/prompt_extractor.py +47 -32
  37. ara_cli/template_loader.py +2 -1
  38. ara_cli/template_manager.py +52 -21
  39. ara_cli/templates/global-scripts/hello_global.py +1 -0
  40. ara_cli/templates/prompt-modules/commands/add_scenarios_for_new_behaviour.feature_creation_agent.commands.md +1 -0
  41. ara_cli/templates/prompt-modules/commands/align_feature_with_implementation_changes.interview_agent.commands.md +1 -0
  42. ara_cli/templates/prompt-modules/commands/analyze_codebase_and_plan_tasks.interview_agent.commands.md +1 -0
  43. ara_cli/templates/prompt-modules/commands/choose_best_parent_artefact.interview_agent.commands.md +1 -0
  44. ara_cli/templates/prompt-modules/commands/create_tasks_from_artefact_content.interview_agent.commands.md +1 -0
  45. ara_cli/templates/prompt-modules/commands/create_tests_for_uncovered_modules.test_generation_agent.commands.md +1 -0
  46. ara_cli/templates/prompt-modules/commands/derive_features_from_video_description.feature_creation_agent.commands.md +1 -0
  47. ara_cli/templates/prompt-modules/commands/describe_agent_capabilities.agent.commands.md +1 -0
  48. ara_cli/templates/prompt-modules/commands/empty.commands.md +2 -12
  49. ara_cli/templates/prompt-modules/commands/execute_scoped_todos_in_task.interview_agent.commands.md +1 -0
  50. ara_cli/templates/prompt-modules/commands/explain_single_file_purpose.interview_agent.commands.md +1 -0
  51. ara_cli/templates/prompt-modules/commands/extract_file_information_bullets.interview_agent.commands.md +1 -0
  52. ara_cli/templates/prompt-modules/commands/extract_general.commands.md +12 -0
  53. ara_cli/templates/prompt-modules/commands/extract_markdown.commands.md +11 -0
  54. ara_cli/templates/prompt-modules/commands/extract_python.commands.md +13 -0
  55. ara_cli/templates/prompt-modules/commands/feature_add_or_modifiy_specified_behavior.commands.md +36 -0
  56. ara_cli/templates/prompt-modules/commands/feature_generate_initial_specified_bevahior.commands.md +53 -0
  57. ara_cli/templates/prompt-modules/commands/fix_failing_behave_step_definitions.interview_agent.commands.md +1 -0
  58. ara_cli/templates/prompt-modules/commands/fix_failing_pytest_tests.interview_agent.commands.md +1 -0
  59. ara_cli/templates/prompt-modules/commands/general_instruction_policy.commands.md +47 -0
  60. ara_cli/templates/prompt-modules/commands/generate_and_fix_pytest_tests.test_generation_agent.commands.md +1 -0
  61. ara_cli/templates/prompt-modules/commands/prompt_template_tech_stack_transformer.commands.md +95 -0
  62. ara_cli/templates/prompt-modules/commands/python_bug_fixing_code.commands.md +34 -0
  63. ara_cli/templates/prompt-modules/commands/python_generate_code.commands.md +27 -0
  64. ara_cli/templates/prompt-modules/commands/python_refactoring_code.commands.md +39 -0
  65. ara_cli/templates/prompt-modules/commands/python_step_definitions_generation_and_fixing.commands.md +40 -0
  66. ara_cli/templates/prompt-modules/commands/python_unittest_generation_and_fixing.commands.md +48 -0
  67. ara_cli/templates/prompt-modules/commands/suggest_next_story_child_tasks.interview_agent.commands.md +1 -0
  68. ara_cli/templates/prompt-modules/commands/summarize_or_transcribe_media.interview_agent.commands.md +1 -0
  69. ara_cli/templates/prompt-modules/commands/update_feature_to_match_implementation.feature_creation_agent.commands.md +1 -0
  70. ara_cli/templates/prompt-modules/commands/update_user_story_with_requirements.interview_agent.commands.md +1 -0
  71. ara_cli/version.py +1 -1
  72. {ara_cli-0.1.10.5.dist-info → ara_cli-0.1.13.3.dist-info}/METADATA +33 -1
  73. {ara_cli-0.1.10.5.dist-info → ara_cli-0.1.13.3.dist-info}/RECORD +89 -43
  74. tests/test_ara_command_action.py +31 -19
  75. tests/test_ara_config.py +177 -90
  76. tests/test_artefact_autofix.py +170 -97
  77. tests/test_artefact_autofix_integration.py +495 -0
  78. tests/test_artefact_converter.py +357 -0
  79. tests/test_artefact_extraction.py +564 -0
  80. tests/test_chat.py +162 -126
  81. tests/test_chat_givens_images.py +603 -0
  82. tests/test_chat_script_runner.py +454 -0
  83. tests/test_llm_utils.py +164 -0
  84. tests/test_prompt_chat.py +343 -0
  85. tests/test_prompt_extractor.py +683 -0
  86. tests/test_web_search.py +467 -0
  87. ara_cli/templates/prompt-modules/blueprints/complete_pytest_unittest.blueprint.md +0 -27
  88. ara_cli/templates/prompt-modules/blueprints/pytest_unittest_prompt.blueprint.md +0 -32
  89. ara_cli/templates/prompt-modules/blueprints/task_todo_list_implement_feature_BDD_way.blueprint.md +0 -30
  90. ara_cli/templates/prompt-modules/commands/artefact_classification.commands.md +0 -9
  91. ara_cli/templates/prompt-modules/commands/artefact_extension.commands.md +0 -17
  92. ara_cli/templates/prompt-modules/commands/artefact_formulation.commands.md +0 -14
  93. ara_cli/templates/prompt-modules/commands/behave_step_generation.commands.md +0 -102
  94. ara_cli/templates/prompt-modules/commands/code_generation_complex.commands.md +0 -20
  95. ara_cli/templates/prompt-modules/commands/code_generation_simple.commands.md +0 -13
  96. ara_cli/templates/prompt-modules/commands/error_fixing.commands.md +0 -20
  97. ara_cli/templates/prompt-modules/commands/feature_file_update.commands.md +0 -18
  98. ara_cli/templates/prompt-modules/commands/feature_formulation.commands.md +0 -43
  99. ara_cli/templates/prompt-modules/commands/js_code_generation_simple.commands.md +0 -13
  100. ara_cli/templates/prompt-modules/commands/refactoring.commands.md +0 -15
  101. ara_cli/templates/prompt-modules/commands/refactoring_analysis.commands.md +0 -9
  102. ara_cli/templates/prompt-modules/commands/reverse_engineer_feature_file.commands.md +0 -15
  103. ara_cli/templates/prompt-modules/commands/reverse_engineer_program_flow.commands.md +0 -19
  104. {ara_cli-0.1.10.5.dist-info → ara_cli-0.1.13.3.dist-info}/WHEEL +0 -0
  105. {ara_cli-0.1.10.5.dist-info → ara_cli-0.1.13.3.dist-info}/entry_points.txt +0 -0
  106. {ara_cli-0.1.10.5.dist-info → ara_cli-0.1.13.3.dist-info}/top_level.txt +0 -0
ara_cli/__init__.py CHANGED
@@ -1,20 +1,65 @@
1
1
  import warnings
2
2
  from .error_handler import ErrorHandler
3
3
 
4
-
5
- whitelisted_commands = ["RERUN", "SEND", "EXTRACT", "LOAD_IMAGE", "CHOOSE_MODEL", "CHOOSE_EXTRACTION_MODEL", "CURRENT_MODEL", "CURRENT_EXTRACTION_MODEL", "LIST_MODELS"]
6
-
4
+ whitelisted_commands = [
5
+ "RERUN",
6
+ "SEND",
7
+ "EXTRACT",
8
+ "LOAD_IMAGE",
9
+ "CHOOSE_MODEL",
10
+ "CHOOSE_EXTRACTION_MODEL",
11
+ "CURRENT_MODEL",
12
+ "CURRENT_EXTRACTION_MODEL",
13
+ "LIST_MODELS",
14
+ ]
7
15
 
8
16
  error_handler = ErrorHandler()
9
17
 
10
18
 
11
19
  # ANSI escape codes for coloring
12
- YELLOW = '\033[93m'
13
- RESET = '\033[0m'
20
+ YELLOW = "\033[93m"
21
+ RESET = "\033[0m"
14
22
 
15
23
 
16
24
  def format_warning(message, category, *args, **kwargs):
17
- return f'{YELLOW}[WARNING] {category.__name__}: {message}{RESET}\n'
25
+ return f"{YELLOW}[WARNING] {category.__name__}: {message}{RESET}\n"
18
26
 
19
27
 
20
28
  warnings.formatwarning = format_warning
29
+
30
+ ### CHAT VALUES ###
31
+
32
+ CATEGORY_CHAT_CONTROL = "Chat control commands"
33
+ CATEGORY_LLM_CONTROL = "Language model controls"
34
+ CATEGORY_SCRIPT_CONTROL = "Script control commands"
35
+ CATEGORY_AGENT_CONTROL = "Agent control commands"
36
+
37
+ ROLE_PROMPT = "ara prompt"
38
+ ROLE_RESPONSE = "ara response"
39
+
40
+ INTRO = """/***************************************/
41
+ araarar
42
+ aa ara
43
+ aa aa aara
44
+ a araarar
45
+ a ar ar
46
+ aa ara
47
+ a a
48
+ a aa
49
+ a a
50
+ ar aa aa
51
+ (c) ara chat by talsen team
52
+ aa aa
53
+ aa a
54
+ a aa
55
+ aa
56
+ /***************************************/
57
+ Start chatting (type 'HELP'/'h' for available commands, 'QUIT'/'q' to exit chat mode):"""
58
+
59
+ BINARY_TYPE_MAPPING = {
60
+ ".png": "image/png",
61
+ ".jpg": "image/jpeg",
62
+ ".jpeg": "image/jpeg",
63
+ }
64
+
65
+ DOCUMENT_TYPE_EXTENSIONS = [".docx", ".doc", ".odt", ".pdf"]
ara_cli/__main__.py CHANGED
@@ -1,9 +1,7 @@
1
1
  import typer
2
- import sys
3
2
  import os
4
3
  from typing import Optional
5
4
  from os import getenv
6
- from ara_cli.error_handler import AraError
7
5
  from ara_cli.version import __version__
8
6
  from ara_cli import error_handler
9
7
  from ara_cli.ara_subcommands.create import register as register_create_cli
@@ -14,18 +12,29 @@ from ara_cli.ara_subcommands.list_tags import register as register_list_tags_cli
14
12
  from ara_cli.ara_subcommands.prompt import register as register_prompt_cli
15
13
  from ara_cli.ara_subcommands.chat import register as register_chat_cli
16
14
  from ara_cli.ara_subcommands.template import register as register_template_cli
17
- from ara_cli.ara_subcommands.fetch_templates import register as register_fetch_templates_cli
15
+ from ara_cli.ara_subcommands.fetch_templates import (
16
+ register as register_fetch_templates_cli,
17
+ )
18
+ from ara_cli.ara_subcommands.fetch_scripts import register as register_fetch_scripts_cli
19
+ from ara_cli.ara_subcommands.fetch_agents import register as register_fetch_agents_cli
20
+ from ara_cli.ara_subcommands.fetch import register as register_fetch_cli
18
21
  from ara_cli.ara_subcommands.read import register as register_read_cli
19
22
  from ara_cli.ara_subcommands.reconnect import register as register_reconnect_cli
20
23
  from ara_cli.ara_subcommands.read_status import register as register_read_status_cli
21
24
  from ara_cli.ara_subcommands.read_user import register as register_read_user_cli
22
25
  from ara_cli.ara_subcommands.set_status import register as register_set_status_cli
23
26
  from ara_cli.ara_subcommands.set_user import register as register_set_user_cli
24
- from ara_cli.ara_subcommands.classifier_directory import register as register_classifier_directory_cli
27
+ from ara_cli.ara_subcommands.classifier_directory import (
28
+ register as register_classifier_directory_cli,
29
+ )
25
30
  from ara_cli.ara_subcommands.scan import register as register_scan_cli
26
31
  from ara_cli.ara_subcommands.autofix import register as register_autofix_cli
27
32
  from ara_cli.ara_subcommands.extract import register as register_extract_cli
28
33
  from ara_cli.ara_subcommands.load import register as register_load_cli
34
+ from ara_cli.ara_subcommands.config import register as register_config_cli
35
+ from ara_cli.ara_subcommands.convert import register as register_convert_cli
36
+
37
+ from ara_cli.directory_navigator import DirectoryNavigator
29
38
 
30
39
 
31
40
  def version_callback(value: bool):
@@ -36,7 +45,7 @@ def version_callback(value: bool):
36
45
 
37
46
  def is_debug_mode_enabled():
38
47
  """Check if debug mode is enabled via environment variable."""
39
- return getenv('ARA_DEBUG', '').lower() in ('1', 'true', 'yes')
48
+ return getenv("ARA_DEBUG", "").lower() in ("1", "true", "yes")
40
49
 
41
50
 
42
51
  def configure_debug_mode(debug: bool, env_debug_mode: bool):
@@ -45,95 +54,74 @@ def configure_debug_mode(debug: bool, env_debug_mode: bool):
45
54
  error_handler.debug_mode = True
46
55
 
47
56
 
48
- def find_ara_directory_root():
49
- """Find the root ara directory by traversing up the directory tree."""
50
- current_dir = os.getcwd()
51
-
52
- # Check if we're already inside an ara directory structure
53
- path_parts = current_dir.split(os.sep)
54
-
55
- # Look for 'ara' in the path parts
56
- if 'ara' in path_parts:
57
- ara_index = path_parts.index('ara')
58
- # Reconstruct path up to and including 'ara'
59
- ara_root_parts = path_parts[:ara_index + 1]
60
- potential_ara_root = os.sep.join(ara_root_parts)
61
- if os.path.exists(potential_ara_root) and os.path.isdir(potential_ara_root):
62
- return potential_ara_root
63
-
64
- # If not inside ara directory, check current directory and parents
65
- check_dir = current_dir
66
- while check_dir != os.path.dirname(check_dir): # Stop at filesystem root
67
- ara_path = os.path.join(check_dir, 'ara')
68
- if os.path.exists(ara_path) and os.path.isdir(ara_path):
69
- return ara_path
70
- check_dir = os.path.dirname(check_dir)
71
-
72
- return None
73
-
74
-
75
57
  def check_ara_directory_exists():
76
58
  """Check if ara directory exists or if we're inside ara directory tree."""
77
- return find_ara_directory_root() is not None
59
+ return DirectoryNavigator.find_ara_directory_root() is not None
78
60
 
79
61
 
80
62
  def prompt_create_ara_directory():
81
63
  """Prompt user to create ara directory and create it if confirmed."""
82
64
  # Print the prompt message
83
- print("No 'ara' directory found. Create one in the current directory? (Y/n)", end=" ", flush=True)
84
-
65
+ print(
66
+ "No 'ara' directory found. Create one in the current directory? (Y/n)",
67
+ end=" ",
68
+ flush=True,
69
+ )
70
+
85
71
  # Read user input
86
72
  try:
87
73
  response = input().strip()
88
74
  except (EOFError, KeyboardInterrupt):
89
75
  typer.echo("\nOperation cancelled.")
90
76
  raise typer.Exit(1)
91
-
92
- if response.lower() in ('y', 'yes', ''):
77
+
78
+ if response.lower() in ("y", "yes", ""):
93
79
  current_dir = os.getcwd()
94
- ara_path = os.path.join(current_dir, 'ara')
95
-
80
+ ara_path = os.path.join(current_dir, "ara")
81
+
96
82
  # Create ara directory structure
97
83
  subdirectories = [
98
- 'businessgoals',
99
- 'capabilities',
100
- 'epics',
101
- 'examples',
102
- 'features',
103
- 'keyfeatures',
104
- 'tasks',
105
- 'userstories',
106
- 'vision'
84
+ "businessgoals",
85
+ "capabilities",
86
+ "epics",
87
+ "examples",
88
+ "features",
89
+ "keyfeatures",
90
+ "tasks",
91
+ "userstories",
92
+ "vision",
107
93
  ]
108
-
94
+
109
95
  try:
110
96
  # Create main ara directory
111
97
  os.makedirs(ara_path, exist_ok=True)
112
-
98
+
113
99
  # Create subdirectories for artefact types
114
100
  for subdir in subdirectories:
115
101
  os.makedirs(os.path.join(ara_path, subdir), exist_ok=True)
116
-
102
+
117
103
  # Create .araconfig directory
118
- araconfig_path = os.path.join(ara_path, '.araconfig')
104
+ araconfig_path = os.path.join(ara_path, ".araconfig")
119
105
  os.makedirs(araconfig_path, exist_ok=True)
120
-
106
+
121
107
  # Create default ara_config.json using ConfigManager
122
108
  from ara_cli.ara_config import ConfigManager, ARAconfig
123
- config_file_path = os.path.join(araconfig_path, 'ara_config.json')
124
-
109
+
110
+ config_file_path = os.path.join(araconfig_path, "ara_config.json")
111
+
125
112
  # Reset ConfigManager to ensure clean state
126
113
  ConfigManager.reset()
127
-
114
+
128
115
  # Create default config and save it
129
116
  default_config = ARAconfig()
130
117
  from ara_cli.ara_config import save_data
118
+
131
119
  save_data(config_file_path, default_config)
132
-
120
+
133
121
  typer.echo(f"Created ara directory structure at {ara_path}")
134
122
  typer.echo(f"Created default configuration at {config_file_path}")
135
123
  return True
136
-
124
+
137
125
  except OSError as e:
138
126
  typer.echo(f"Error creating ara directory: {e}", err=True)
139
127
  raise typer.Exit(1)
@@ -181,15 +169,16 @@ ara artefact handling examples:
181
169
  > rename artefact and artefact data directory for e.g. a feature: ara rename feature {initial_feature_name} {new_feature_name}
182
170
  > create additional templates for a specific aspect (valid aspects are: customer,
183
171
  persona, concept, technology) related to an existing artefact like a feature: ara create feature {feature_name} aspect {aspect_name}
184
- > list artefact data with .md file extension ara list --data {classifier} {artefact_name} --include-extension .md
185
- > list artefact data with .md and .json file extensions ara list --data {classifier} {artefact_name} --include-extension .md .json
172
+ > list artefact data with .md file extension ara list {classifier} {artefact_name} --data --include-extension .md
173
+ > list artefact data with .md and .json file extensions ara list {classifier} {artefact_name} --data --include-extension .md .json
186
174
  > list everything but userstories ara list --exclude-extension .userstory
187
175
  > list all existing features: ara list --include-extension .feature
176
+ > list all artefacts of a specific classifier: ara list {classifier}
188
177
  > list all child artefacts contributing value to a parent artefact: ara list --include-content "Contributes to {name_of_parent_artefact} {ara classifier_of_parent_artefact}"
189
178
  > list tasks which contain 'example content' ara list --include-extension .task --include-content "example content"
190
- > list children artefacts of a userstory ara list --children userstory {name_of_userstory}
191
- > list parent artefacts of a userstory ara list --branch userstory {name_of_userstory}
192
- > list parent businessgoal artefact of a userstory ara list --branch userstory {name_of_userstory} --include-extension .businessgoal
179
+ > list children artefacts of a userstory ara list userstory {name_of_userstory} --children
180
+ > list parent artefacts of a userstory ara list userstory {name_of_userstory} --branch
181
+ > list parent businessgoal artefact of a userstory ara list userstory {name_of_userstory} --branch --include-extension .businessgoal
193
182
  > print any artefact template for e.g. a feature file template in the terminal: ara template feature
194
183
 
195
184
  ara prompt templates examples:
@@ -204,25 +193,32 @@ ara chat examples:
204
193
  > load selected templates in config_prompt_templates.md for the task {task_name}: ara prompt load task {task_name}
205
194
  > create and send configured prompt of the task {task_name} to the configured LLM: ara prompt send task {task_name}
206
195
  > extract the selected LLM response in task.exploration.md and save to disk: ara prompt extract task {task_name}
196
+
197
+ ara config examples:
198
+ > show current configuration status: ara config show
199
+ > show only LLM configurations: ara config show --llm
200
+ > reset LLM configurations to defaults: ara config reset --llm-config -y
201
+ > preview reset without making changes: ara config reset --all --dry-run
207
202
  """,
208
203
  no_args_is_help=True,
209
204
  add_completion=True,
210
- rich_markup_mode="rich"
205
+ rich_markup_mode="rich",
211
206
  )
212
207
 
213
208
  @app.callback(invoke_without_command=True)
214
209
  def main(
215
210
  ctx: typer.Context,
216
211
  version: Optional[bool] = typer.Option(
217
- None, "--version", "-v",
212
+ None,
213
+ "--version",
214
+ "-v",
218
215
  callback=version_callback,
219
216
  is_eager=True,
220
- help="Show version and exit"
217
+ help="Show version and exit",
221
218
  ),
222
219
  debug: bool = typer.Option(
223
- False, "--debug",
224
- help="Enable debug mode for detailed error output"
225
- )
220
+ False, "--debug", help="Enable debug mode for detailed error output"
221
+ ),
226
222
  ):
227
223
  """The ara cli terminal tool is a management tool for classified ara artefacts."""
228
224
  debug_mode = is_debug_mode_enabled()
@@ -232,15 +228,26 @@ ara chat examples:
232
228
  if ctx.invoked_subcommand is None:
233
229
  ctx.get_help()
234
230
  ctx.exit()
235
-
231
+
236
232
  # Check for ara directory before executing any command
237
233
  # Skip check for commands that don't require ara directory
238
234
  commands_requiring_ara = {
239
- 'create', 'delete', 'rename', 'list', 'list-tags', 'prompt',
240
- 'read', 'reconnect', 'read-status', 'read-user', 'set-status',
241
- 'set-user', 'classifier-directory', 'scan', 'autofix'
235
+ "create",
236
+ "delete",
237
+ "rename",
238
+ "list",
239
+ "list-tags",
240
+ "prompt",
241
+ "read",
242
+ "reconnect",
243
+ "read-status",
244
+ "read-user",
245
+ "set-status",
246
+ "set-user",
247
+ "scan",
248
+ "autofix",
242
249
  }
243
-
250
+
244
251
  if ctx.invoked_subcommand in commands_requiring_ara:
245
252
  requires_ara_directory()
246
253
 
@@ -254,6 +261,9 @@ ara chat examples:
254
261
  register_chat_cli(app)
255
262
  register_template_cli(app)
256
263
  register_fetch_templates_cli(app)
264
+ register_fetch_scripts_cli(app)
265
+ register_fetch_agents_cli(app)
266
+ register_fetch_cli(app)
257
267
  register_read_cli(app)
258
268
  register_reconnect_cli(app)
259
269
  register_read_status_cli(app)
@@ -265,6 +275,8 @@ ara chat examples:
265
275
  register_autofix_cli(app)
266
276
  register_extract_cli(app)
267
277
  register_load_cli(app)
278
+ register_config_cli(app)
279
+ register_convert_cli(app)
268
280
 
269
281
  return app
270
282
 
@@ -281,4 +293,4 @@ def cli():
281
293
 
282
294
 
283
295
  if __name__ == "__main__":
284
- cli()
296
+ cli()
@@ -23,24 +23,33 @@ def create_action(args):
23
23
  from ara_cli.artefact_reader import ArtefactReader
24
24
  from ara_cli.artefact_fuzzy_search import find_closest_rule
25
25
 
26
- check_validity(Classifier.is_valid_classifier(args.classifier), "Invalid classifier provided. Please provide a valid classifier.")
27
- check_validity(is_valid_filename(args.parameter), "Invalid filename provided. Please provide a valid filename.")
26
+ check_validity(Classifier.is_valid_classifier(args.classifier),
27
+ "Invalid classifier provided. Please provide a valid classifier.")
28
+ check_validity(is_valid_filename(args.parameter),
29
+ "Invalid filename provided. Please provide a valid filename.")
28
30
 
29
31
  def handle_parent_arguments(args):
30
- parent_classifier = args.parent_classifier if hasattr(args, "parent_classifier") else None
31
- parent_name = args.parent_name if hasattr(args, "parent_name") else None
32
+ parent_classifier = args.parent_classifier if hasattr(
33
+ args, "parent_classifier") else None
34
+ parent_name = args.parent_name if hasattr(
35
+ args, "parent_name") else None
32
36
  rule = args.rule if hasattr(args, 'rule') else None
33
37
  invalid_classifier_message = "Invalid parent classifier provided. Please provide a valid classifier"
34
38
  invalid_name_message = "Invalid filename provided for parent. Please provide a valid filename."
35
39
  if parent_classifier and parent_name and rule:
36
- check_validity(Classifier.is_valid_classifier(parent_classifier), invalid_classifier_message)
37
- check_validity(is_valid_filename(parent_name), invalid_name_message)
38
- parent_artefact = ArtefactReader.read_artefact(artefact_name=parent_name, classifier=parent_classifier)
40
+ check_validity(Classifier.is_valid_classifier(
41
+ parent_classifier), invalid_classifier_message)
42
+ check_validity(is_valid_filename(
43
+ parent_name), invalid_name_message)
44
+ parent_artefact = ArtefactReader.read_artefact(
45
+ artefact_name=parent_name, classifier=parent_classifier)
39
46
  rule = find_closest_rule(parent_artefact, rule)
40
47
  return parent_classifier, parent_name, rule
41
48
  if parent_classifier and parent_name:
42
- check_validity(Classifier.is_valid_classifier(parent_classifier), invalid_classifier_message)
43
- check_validity(is_valid_filename(parent_name), invalid_name_message)
49
+ check_validity(Classifier.is_valid_classifier(
50
+ parent_classifier), invalid_classifier_message)
51
+ check_validity(is_valid_filename(
52
+ parent_name), invalid_name_message)
44
53
  return parent_classifier, parent_name, rule
45
54
  return None, None, None
46
55
 
@@ -61,7 +70,8 @@ def create_action(args):
61
70
  return
62
71
 
63
72
  artefact_creator = ArtefactCreator()
64
- artefact_creator.run(args.parameter, args.classifier, parent_classifier, parent_name, rule)
73
+ artefact_creator.run(args.parameter, args.classifier,
74
+ parent_classifier, parent_name, rule)
65
75
 
66
76
 
67
77
  @handle_errors(context="delete action", error_handler=error_handler)
@@ -78,22 +88,33 @@ def rename_action(args):
78
88
  from ara_cli.classifier import Classifier
79
89
  from ara_cli.filename_validator import is_valid_filename
80
90
 
81
- check_validity(is_valid_filename(args.parameter), "Invalid filename provided. Please provide a valid filename.")
82
- check_validity(Classifier.is_valid_classifier(args.classifier), "Invalid classifier provided. Please provide a valid classifier.")
83
- check_validity(is_valid_filename(args.aspect), "Invalid new filename provided. Please provide a valid filename.")
91
+ check_validity(is_valid_filename(args.parameter),
92
+ "Invalid filename provided. Please provide a valid filename.")
93
+ check_validity(Classifier.is_valid_classifier(args.classifier),
94
+ "Invalid classifier provided. Please provide a valid classifier.")
95
+ check_validity(is_valid_filename(
96
+ args.aspect), "Invalid new filename provided. Please provide a valid filename.")
84
97
 
85
98
  artefact_renamer = ArtefactRenamer()
86
99
  artefact_renamer.rename(args.parameter, args.aspect, args.classifier)
87
100
 
88
101
 
102
+ def _execute_list_method(method, classifier, artefact_name, list_filter, flag_name):
103
+ """Helper function to validate and execute list methods."""
104
+ if not classifier or not artefact_name:
105
+ raise AraError(
106
+ f"Both classifier and artefact_name are required for --{flag_name}"
107
+ )
108
+ method(classifier=classifier, artefact_name=artefact_name, list_filter=list_filter)
109
+
110
+
89
111
  @handle_errors(context="rename action", error_handler=error_handler)
90
112
  def list_action(args):
91
113
  from ara_cli.artefact_lister import ArtefactLister
92
114
  from ara_cli.list_filter import ListFilter
93
115
 
94
- branch_classifier, branch_artefact_name = args.branch_args
95
- children_classifier, children_artefact_name = args.children_args
96
- data_classifier, data_artefact_name = args.data_args
116
+ classifier = args.classifier
117
+ artefact_name = args.artefact_name
97
118
 
98
119
  artefact_lister = ArtefactLister()
99
120
 
@@ -106,29 +127,27 @@ def list_action(args):
106
127
  exclude_tags=args.exclude_tags
107
128
  )
108
129
 
109
- if branch_classifier and branch_artefact_name:
110
- artefact_lister.list_branch(
111
- classifier=branch_classifier,
112
- artefact_name=branch_artefact_name,
113
- list_filter=list_filter
114
- )
115
- return
116
-
117
- if children_classifier and children_artefact_name:
118
- artefact_lister.list_children(
119
- classifier=children_classifier,
120
- artefact_name=children_artefact_name,
121
- list_filter=list_filter
122
- )
123
- return
130
+ # Map flags to their corresponding methods
131
+ flag_method_map = {
132
+ "branch": (args.branch, artefact_lister.list_branch),
133
+ "children": (args.children, artefact_lister.list_children),
134
+ "data": (args.data, artefact_lister.list_data),
135
+ }
124
136
 
125
- if data_classifier and data_artefact_name:
126
- artefact_lister.list_data(
127
- classifier=data_classifier,
128
- artefact_name=data_artefact_name,
129
- list_filter=list_filter
137
+ for flag_name, (flag_value, method) in flag_method_map.items():
138
+ if flag_value:
139
+ _execute_list_method(
140
+ method, classifier, artefact_name, list_filter, flag_name
141
+ )
142
+ return
143
+
144
+ # If both classifier and artefact_name are present, but no specific action flag (branch, children, data)
145
+ # was provided, raise an error as per requirements.
146
+ if classifier and artefact_name:
147
+ raise AraError(
148
+ f"To list specific info for '{classifier} {artefact_name}', "
149
+ "you must provide one of: --children, --branch, or --data."
130
150
  )
131
- return
132
151
 
133
152
  artefact_lister.list_files(list_filter=list_filter)
134
153
 
@@ -171,8 +190,10 @@ def prompt_action(args):
171
190
  from ara_cli.classifier import Classifier
172
191
  from ara_cli.filename_validator import is_valid_filename
173
192
 
174
- check_validity(Classifier.is_valid_classifier(args.classifier), "Invalid classifier provided. Please provide a valid classifier.")
175
- check_validity(is_valid_filename(args.parameter), "Invalid filename provided. Please provide a valid filename.")
193
+ check_validity(Classifier.is_valid_classifier(args.classifier),
194
+ "Invalid classifier provided. Please provide a valid classifier.")
195
+ check_validity(is_valid_filename(args.parameter),
196
+ "Invalid filename provided. Please provide a valid filename.")
176
197
 
177
198
  classifier = args.classifier
178
199
  param = args.parameter
@@ -207,7 +228,8 @@ def prompt_action(args):
207
228
  from ara_cli.update_config_prompt import update_artefact_config_prompt_files
208
229
  extract_and_save_prompt_results(classifier, param, write=write)
209
230
  print(f"automatic update after extract")
210
- update_artefact_config_prompt_files(classifier, param, automatic_update=True)
231
+ update_artefact_config_prompt_files(
232
+ classifier, param, automatic_update=True)
211
233
 
212
234
  def handle_chat():
213
235
  from ara_cli.prompt_chat import initialize_prompt_chat_mode
@@ -216,11 +238,13 @@ def prompt_action(args):
216
238
  output_mode = args.output_mode
217
239
  append_strings = args.append
218
240
  restricted = args.restricted
219
- initialize_prompt_chat_mode(classifier, param, chat_name, reset=reset, output_mode=output_mode, append_strings=append_strings, restricted=restricted)
241
+ initialize_prompt_chat_mode(classifier, param, chat_name, reset=reset,
242
+ output_mode=output_mode, append_strings=append_strings, restricted=restricted)
220
243
 
221
244
  def handle_update():
222
245
  from ara_cli.update_config_prompt import update_artefact_config_prompt_files
223
- update_artefact_config_prompt_files(classifier, param, automatic_update=True)
246
+ update_artefact_config_prompt_files(
247
+ classifier, param, automatic_update=True)
224
248
 
225
249
  command_dispatcher = {
226
250
  'init': handle_init,
@@ -255,7 +279,8 @@ def chat_action(args):
255
279
  chat_file_path = join(cwd, chat_name)
256
280
 
257
281
  with suppress_stdout(output_mode):
258
- chat = Chat(chat_file_path, reset=reset) if not restricted else Chat(chat_file_path, reset=reset, enable_commands=whitelisted_commands)
282
+ chat = Chat(chat_file_path, reset=reset) if not restricted else Chat(
283
+ chat_file_path, reset=reset, enable_commands=whitelisted_commands)
259
284
 
260
285
  if append_strings:
261
286
  chat.append_strings(append_strings)
@@ -305,7 +330,8 @@ def load_action(args):
305
330
  default_pattern = default_patterns.get(template_type)
306
331
 
307
332
  if not template_name and not default_pattern:
308
- raise AraError(f"A template name is required for template type '{template_type}'.")
333
+ raise AraError(
334
+ f"A template name is required for template type '{template_type}'.")
309
335
 
310
336
  loader = TemplateLoader() # No chat instance for CLI context
311
337
  success = loader.load_template(
@@ -324,7 +350,8 @@ def template_action(args):
324
350
  from ara_cli.classifier import Classifier
325
351
  from ara_cli.template_manager import TemplatePathManager
326
352
 
327
- check_validity(Classifier.is_valid_classifier(args.classifier), "Invalid classifier provided. Please provide a valid classifier.")
353
+ check_validity(Classifier.is_valid_classifier(args.classifier),
354
+ "Invalid classifier provided. Please provide a valid classifier.")
328
355
 
329
356
  template_manager = TemplatePathManager()
330
357
  content = template_manager.get_template_content(args.classifier)
@@ -345,9 +372,11 @@ def fetch_templates_action(args):
345
372
 
346
373
  subdirs = ["commands", "rules", "intentions", "blueprints"]
347
374
 
348
- os.makedirs(join(prompt_templates_dir, "global-prompt-modules"), exist_ok=True)
375
+ os.makedirs(join(prompt_templates_dir,
376
+ "global-prompt-modules"), exist_ok=True)
349
377
  for subdir in subdirs:
350
- target_dir = join(prompt_templates_dir, "global-prompt-modules", subdir)
378
+ target_dir = join(prompt_templates_dir,
379
+ "global-prompt-modules", subdir)
351
380
  source_dir = join(global_prompt_templates_path, subdir)
352
381
  os.makedirs(target_dir, exist_ok=True)
353
382
  for item in os.listdir(source_dir):
@@ -356,7 +385,8 @@ def fetch_templates_action(args):
356
385
  shutil.copy2(source, target)
357
386
 
358
387
  custom_prompt_templates_subdir = config.custom_prompt_templates_subdir
359
- local_prompt_modules_dir = join(prompt_templates_dir, custom_prompt_templates_subdir)
388
+ local_prompt_modules_dir = join(
389
+ prompt_templates_dir, custom_prompt_templates_subdir)
360
390
  os.makedirs(local_prompt_modules_dir, exist_ok=True)
361
391
  for subdir in subdirs:
362
392
  os.makedirs(join(local_prompt_modules_dir, subdir), exist_ok=True)
@@ -459,9 +489,11 @@ def read_status_action(args):
459
489
  artefact_info = file_classifier.classify_files()
460
490
  artefact_info_dicts = artefact_info.get(classifier, [])
461
491
 
462
- all_artefact_names = [artefact_info["title"] for artefact_info in artefact_info_dicts]
492
+ all_artefact_names = [artefact_info["title"]
493
+ for artefact_info in artefact_info_dicts]
463
494
  if artefact_name not in all_artefact_names:
464
- suggest_close_name_matches(artefact_name, all_artefact_names, report_as_error=True)
495
+ suggest_close_name_matches(
496
+ artefact_name, all_artefact_names, report_as_error=True)
465
497
  return
466
498
 
467
499
  artefact_info = next(filter(
@@ -492,9 +524,11 @@ def read_user_action(args):
492
524
  artefact_info = file_classifier.classify_files()
493
525
  artefact_info_dicts = artefact_info.get(classifier, [])
494
526
 
495
- all_artefact_names = [artefact_info["title"] for artefact_info in artefact_info_dicts]
527
+ all_artefact_names = [artefact_info["title"]
528
+ for artefact_info in artefact_info_dicts]
496
529
  if artefact_name not in all_artefact_names:
497
- suggest_close_name_matches(artefact_name, all_artefact_names, report_as_error=True)
530
+ suggest_close_name_matches(
531
+ artefact_name, all_artefact_names, report_as_error=True)
498
532
  return
499
533
 
500
534
  artefact_info = next(filter(
@@ -529,12 +563,14 @@ def set_status_action(args):
529
563
  if new_status.startswith('@'):
530
564
  new_status = new_status.lstrip('@')
531
565
 
532
- check_validity(new_status in status_tags, "Invalid status provided. Please provide a valid status.")
566
+ check_validity(new_status in status_tags,
567
+ "Invalid status provided. Please provide a valid status.")
533
568
 
534
569
  file_classifier = FileClassifier(os)
535
570
  classified_artefacts_info = file_classifier.classify_files()
536
571
  classified_artefact_dict = classified_artefacts_info.get(classifier, [])
537
- all_artefact_names = [artefact_info["title"] for artefact_info in classified_artefact_dict]
572
+ all_artefact_names = [artefact_info["title"]
573
+ for artefact_info in classified_artefact_dict]
538
574
 
539
575
  if artefact_name not in all_artefact_names:
540
576
  suggest_close_name_matches(artefact_name, all_artefact_names)
@@ -554,7 +590,8 @@ def set_status_action(args):
554
590
  with open(f"{artefact_info['file_path']}", 'w', encoding='utf-8') as file:
555
591
  file.write(serialized_content)
556
592
 
557
- print(f"Status of task '{artefact_name}' has been updated to '{new_status}'.")
593
+ print(
594
+ f"Status of task '{artefact_name}' has been updated to '{new_status}'.")
558
595
 
559
596
 
560
597
  @handle_errors(context="set-user action", error_handler=error_handler)
@@ -572,7 +609,8 @@ def set_user_action(args):
572
609
  file_classifier = FileClassifier(os)
573
610
  classified_artefacts_info = file_classifier.classify_files()
574
611
  classified_artefact_dict = classified_artefacts_info.get(classifier, [])
575
- all_artefact_names = [artefact_info["title"] for artefact_info in classified_artefact_dict]
612
+ all_artefact_names = [artefact_info["title"]
613
+ for artefact_info in classified_artefact_dict]
576
614
 
577
615
  if artefact_name not in all_artefact_names:
578
616
  suggest_close_name_matches(artefact_name, all_artefact_names)
@@ -673,4 +711,4 @@ def extract_action(args):
673
711
  write=write,
674
712
  output=lambda msg: print(msg, file=sys.stdout)
675
713
  )
676
- command.execute()
714
+ command.execute()