ara-cli 0.1.9.77__py3-none-any.whl → 0.1.10.8__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.

Potentially problematic release.


This version of ara-cli might be problematic. Click here for more details.

Files changed (122) hide show
  1. ara_cli/__init__.py +18 -2
  2. ara_cli/__main__.py +245 -66
  3. ara_cli/ara_command_action.py +128 -63
  4. ara_cli/ara_config.py +201 -177
  5. ara_cli/ara_subcommands/__init__.py +0 -0
  6. ara_cli/ara_subcommands/autofix.py +26 -0
  7. ara_cli/ara_subcommands/chat.py +27 -0
  8. ara_cli/ara_subcommands/classifier_directory.py +16 -0
  9. ara_cli/ara_subcommands/common.py +100 -0
  10. ara_cli/ara_subcommands/create.py +75 -0
  11. ara_cli/ara_subcommands/delete.py +22 -0
  12. ara_cli/ara_subcommands/extract.py +22 -0
  13. ara_cli/ara_subcommands/fetch_templates.py +14 -0
  14. ara_cli/ara_subcommands/list.py +65 -0
  15. ara_cli/ara_subcommands/list_tags.py +25 -0
  16. ara_cli/ara_subcommands/load.py +48 -0
  17. ara_cli/ara_subcommands/prompt.py +136 -0
  18. ara_cli/ara_subcommands/read.py +47 -0
  19. ara_cli/ara_subcommands/read_status.py +20 -0
  20. ara_cli/ara_subcommands/read_user.py +20 -0
  21. ara_cli/ara_subcommands/reconnect.py +27 -0
  22. ara_cli/ara_subcommands/rename.py +22 -0
  23. ara_cli/ara_subcommands/scan.py +14 -0
  24. ara_cli/ara_subcommands/set_status.py +22 -0
  25. ara_cli/ara_subcommands/set_user.py +22 -0
  26. ara_cli/ara_subcommands/template.py +16 -0
  27. ara_cli/artefact_autofix.py +214 -28
  28. ara_cli/artefact_creator.py +5 -8
  29. ara_cli/artefact_deleter.py +2 -4
  30. ara_cli/artefact_fuzzy_search.py +13 -6
  31. ara_cli/artefact_lister.py +29 -55
  32. ara_cli/artefact_models/artefact_data_retrieval.py +23 -0
  33. ara_cli/artefact_models/artefact_model.py +106 -25
  34. ara_cli/artefact_models/artefact_templates.py +23 -13
  35. ara_cli/artefact_models/epic_artefact_model.py +11 -2
  36. ara_cli/artefact_models/feature_artefact_model.py +56 -1
  37. ara_cli/artefact_models/userstory_artefact_model.py +15 -3
  38. ara_cli/artefact_reader.py +4 -5
  39. ara_cli/artefact_renamer.py +6 -2
  40. ara_cli/artefact_scan.py +2 -2
  41. ara_cli/chat.py +594 -219
  42. ara_cli/chat_agent/__init__.py +0 -0
  43. ara_cli/chat_agent/agent_communicator.py +62 -0
  44. ara_cli/chat_agent/agent_process_manager.py +211 -0
  45. ara_cli/chat_agent/agent_status_manager.py +73 -0
  46. ara_cli/chat_agent/agent_workspace_manager.py +76 -0
  47. ara_cli/commands/__init__.py +0 -0
  48. ara_cli/commands/command.py +7 -0
  49. ara_cli/commands/extract_command.py +15 -0
  50. ara_cli/commands/load_command.py +65 -0
  51. ara_cli/commands/load_image_command.py +34 -0
  52. ara_cli/commands/read_command.py +117 -0
  53. ara_cli/completers.py +144 -0
  54. ara_cli/directory_navigator.py +37 -4
  55. ara_cli/error_handler.py +134 -0
  56. ara_cli/file_classifier.py +3 -2
  57. ara_cli/file_loaders/__init__.py +0 -0
  58. ara_cli/file_loaders/binary_file_loader.py +33 -0
  59. ara_cli/file_loaders/document_file_loader.py +34 -0
  60. ara_cli/file_loaders/document_reader.py +245 -0
  61. ara_cli/file_loaders/document_readers.py +233 -0
  62. ara_cli/file_loaders/file_loader.py +50 -0
  63. ara_cli/file_loaders/file_loaders.py +123 -0
  64. ara_cli/file_loaders/image_processor.py +89 -0
  65. ara_cli/file_loaders/markdown_reader.py +75 -0
  66. ara_cli/file_loaders/text_file_loader.py +187 -0
  67. ara_cli/global_file_lister.py +51 -0
  68. ara_cli/prompt_extractor.py +214 -87
  69. ara_cli/prompt_handler.py +508 -146
  70. ara_cli/tag_extractor.py +54 -24
  71. ara_cli/template_loader.py +245 -0
  72. ara_cli/template_manager.py +14 -4
  73. ara_cli/templates/prompt-modules/commands/empty.commands.md +2 -12
  74. ara_cli/templates/prompt-modules/commands/extract_general.commands.md +12 -0
  75. ara_cli/templates/prompt-modules/commands/extract_markdown.commands.md +11 -0
  76. ara_cli/templates/prompt-modules/commands/extract_python.commands.md +13 -0
  77. ara_cli/templates/prompt-modules/commands/feature_add_or_modifiy_specified_behavior.commands.md +36 -0
  78. ara_cli/templates/prompt-modules/commands/feature_generate_initial_specified_bevahior.commands.md +53 -0
  79. ara_cli/templates/prompt-modules/commands/prompt_template_tech_stack_transformer.commands.md +95 -0
  80. ara_cli/templates/prompt-modules/commands/python_bug_fixing_code.commands.md +34 -0
  81. ara_cli/templates/prompt-modules/commands/python_generate_code.commands.md +27 -0
  82. ara_cli/templates/prompt-modules/commands/python_refactoring_code.commands.md +39 -0
  83. ara_cli/templates/prompt-modules/commands/python_step_definitions_generation_and_fixing.commands.md +40 -0
  84. ara_cli/templates/prompt-modules/commands/python_unittest_generation_and_fixing.commands.md +48 -0
  85. ara_cli/update_config_prompt.py +7 -1
  86. ara_cli/version.py +1 -1
  87. ara_cli-0.1.10.8.dist-info/METADATA +241 -0
  88. {ara_cli-0.1.9.77.dist-info → ara_cli-0.1.10.8.dist-info}/RECORD +104 -59
  89. tests/test_ara_command_action.py +66 -52
  90. tests/test_ara_config.py +200 -279
  91. tests/test_artefact_autofix.py +361 -5
  92. tests/test_artefact_lister.py +52 -132
  93. tests/test_artefact_scan.py +1 -1
  94. tests/test_chat.py +2009 -603
  95. tests/test_file_classifier.py +23 -0
  96. tests/test_file_creator.py +3 -5
  97. tests/test_global_file_lister.py +131 -0
  98. tests/test_prompt_handler.py +746 -0
  99. tests/test_tag_extractor.py +19 -13
  100. tests/test_template_loader.py +192 -0
  101. tests/test_template_manager.py +5 -4
  102. ara_cli/ara_command_parser.py +0 -536
  103. ara_cli/templates/prompt-modules/blueprints/complete_pytest_unittest.blueprint.md +0 -27
  104. ara_cli/templates/prompt-modules/blueprints/task_todo_list_implement_feature_BDD_way.blueprint.md +0 -30
  105. ara_cli/templates/prompt-modules/commands/artefact_classification.commands.md +0 -9
  106. ara_cli/templates/prompt-modules/commands/artefact_extension.commands.md +0 -17
  107. ara_cli/templates/prompt-modules/commands/artefact_formulation.commands.md +0 -14
  108. ara_cli/templates/prompt-modules/commands/behave_step_generation.commands.md +0 -102
  109. ara_cli/templates/prompt-modules/commands/code_generation_complex.commands.md +0 -20
  110. ara_cli/templates/prompt-modules/commands/code_generation_simple.commands.md +0 -13
  111. ara_cli/templates/prompt-modules/commands/error_fixing.commands.md +0 -20
  112. ara_cli/templates/prompt-modules/commands/feature_file_update.commands.md +0 -18
  113. ara_cli/templates/prompt-modules/commands/feature_formulation.commands.md +0 -43
  114. ara_cli/templates/prompt-modules/commands/js_code_generation_simple.commands.md +0 -13
  115. ara_cli/templates/prompt-modules/commands/refactoring.commands.md +0 -15
  116. ara_cli/templates/prompt-modules/commands/refactoring_analysis.commands.md +0 -9
  117. ara_cli/templates/prompt-modules/commands/reverse_engineer_feature_file.commands.md +0 -15
  118. ara_cli/templates/prompt-modules/commands/reverse_engineer_program_flow.commands.md +0 -19
  119. ara_cli-0.1.9.77.dist-info/METADATA +0 -18
  120. {ara_cli-0.1.9.77.dist-info → ara_cli-0.1.10.8.dist-info}/WHEEL +0 -0
  121. {ara_cli-0.1.9.77.dist-info → ara_cli-0.1.10.8.dist-info}/entry_points.txt +0 -0
  122. {ara_cli-0.1.9.77.dist-info → ara_cli-0.1.10.8.dist-info}/top_level.txt +0 -0
@@ -2,17 +2,19 @@ from os.path import join
2
2
  import os
3
3
  import sys
4
4
  import json
5
+ from ara_cli.error_handler import AraError
6
+ from ara_cli.error_handler import handle_errors, AraValidationError
5
7
  from ara_cli.output_suppressor import suppress_stdout
6
8
  from ara_cli.artefact_fuzzy_search import suggest_close_name_matches
7
- from . import whitelisted_commands
9
+ from . import whitelisted_commands, error_handler
8
10
 
9
11
 
10
12
  def check_validity(condition, error_message):
11
13
  if not condition:
12
- print(error_message)
13
- sys.exit(1)
14
+ raise AraValidationError(error_message)
14
15
 
15
16
 
17
+ @handle_errors(context="create action", error_handler=error_handler)
16
18
  def create_action(args):
17
19
  from ara_cli.artefact_creator import ArtefactCreator
18
20
  from ara_cli.classifier import Classifier
@@ -62,6 +64,7 @@ def create_action(args):
62
64
  artefact_creator.run(args.parameter, args.classifier, parent_classifier, parent_name, rule)
63
65
 
64
66
 
67
+ @handle_errors(context="delete action", error_handler=error_handler)
65
68
  def delete_action(args):
66
69
  from ara_cli.artefact_deleter import ArtefactDeleter
67
70
 
@@ -69,6 +72,7 @@ def delete_action(args):
69
72
  artefact_deleter.delete(args.parameter, args.classifier, args.force)
70
73
 
71
74
 
75
+ @handle_errors(context="rename action", error_handler=error_handler)
72
76
  def rename_action(args):
73
77
  from ara_cli.artefact_renamer import ArtefactRenamer
74
78
  from ara_cli.classifier import Classifier
@@ -82,6 +86,7 @@ def rename_action(args):
82
86
  artefact_renamer.rename(args.parameter, args.aspect, args.classifier)
83
87
 
84
88
 
89
+ @handle_errors(context="rename action", error_handler=error_handler)
85
90
  def list_action(args):
86
91
  from ara_cli.artefact_lister import ArtefactLister
87
92
  from ara_cli.list_filter import ListFilter
@@ -125,12 +130,10 @@ def list_action(args):
125
130
  )
126
131
  return
127
132
 
128
- if (args.tags):
129
- artefact_lister.list_files(tags=args.tags, list_filter=list_filter)
130
- return
131
133
  artefact_lister.list_files(list_filter=list_filter)
132
134
 
133
135
 
136
+ @handle_errors(context="list-tags action", error_handler=error_handler)
134
137
  def list_tags_action(args):
135
138
  from ara_cli.tag_extractor import TagExtractor
136
139
  from ara_cli.list_filter import ListFilter
@@ -141,20 +144,29 @@ def list_tags_action(args):
141
144
  )
142
145
 
143
146
  tag_extractor = TagExtractor()
144
- tags = tag_extractor.extract_tags(
147
+ tag_groups = tag_extractor.extract_tags(
145
148
  filtered_extra_column=getattr(args, "filtered_extra_column", False),
146
149
  list_filter=list_filter
147
150
  )
148
151
 
149
152
  if args.json:
150
- output = json.dumps({"tags": tags})
153
+ all_tags = []
154
+ for group in tag_groups.values():
155
+ all_tags.extend(group)
156
+ output = json.dumps({"tags": sorted(all_tags)})
151
157
  print(output)
152
158
  return
153
159
 
154
- output = "\n".join(f"- {tag}" for tag in tags)
160
+ output_lines = []
161
+ for key in sorted(tag_groups.keys()):
162
+ line = " ".join(sorted(list(tag_groups[key])))
163
+ output_lines.append(line)
164
+
165
+ output = "\n".join(f"- {tag}" for tag in output_lines)
155
166
  print(output)
156
167
 
157
168
 
169
+ @handle_errors(context="prompt action", error_handler=error_handler)
158
170
  def prompt_action(args):
159
171
  from ara_cli.classifier import Classifier
160
172
  from ara_cli.filename_validator import is_valid_filename
@@ -165,6 +177,7 @@ def prompt_action(args):
165
177
  classifier = args.classifier
166
178
  param = args.parameter
167
179
  init = args.steps
180
+ write = getattr(args, 'write', False)
168
181
 
169
182
  def handle_init():
170
183
  from ara_cli.prompt_handler import initialize_prompt_templates
@@ -192,7 +205,7 @@ def prompt_action(args):
192
205
  def handle_extract():
193
206
  from ara_cli.prompt_extractor import extract_and_save_prompt_results
194
207
  from ara_cli.update_config_prompt import update_artefact_config_prompt_files
195
- extract_and_save_prompt_results(classifier, param)
208
+ extract_and_save_prompt_results(classifier, param, write=write)
196
209
  print(f"automatic update after extract")
197
210
  update_artefact_config_prompt_files(classifier, param, automatic_update=True)
198
211
 
@@ -226,6 +239,7 @@ def prompt_action(args):
226
239
  raise ValueError(f"Unknown command '{init}' provided.")
227
240
 
228
241
 
242
+ @handle_errors(context="chat action", error_handler=error_handler)
229
243
  def chat_action(args):
230
244
  from ara_cli.chat import Chat
231
245
 
@@ -252,6 +266,60 @@ def chat_action(args):
252
266
  chat.start()
253
267
 
254
268
 
269
+ def _find_chat_file(chat_name: str) -> str | None:
270
+ """Resolves the chat file path based on common naming conventions."""
271
+ # Logic from setup_chat for finding existing files.
272
+ if os.path.exists(chat_name) and os.path.isfile(chat_name):
273
+ return chat_name
274
+
275
+ chat_name_md = f"{chat_name}.md"
276
+ if os.path.exists(chat_name_md) and os.path.isfile(chat_name_md):
277
+ return chat_name_md
278
+
279
+ chat_name_chat_md = f"{chat_name}_chat.md"
280
+ if os.path.exists(chat_name_chat_md) and os.path.isfile(chat_name_chat_md):
281
+ return chat_name_chat_md
282
+
283
+ return None
284
+
285
+
286
+ @handle_errors(context="load action", error_handler=error_handler)
287
+ def load_action(args):
288
+ from ara_cli.template_loader import TemplateLoader
289
+
290
+ chat_name = args.chat_name
291
+ template_type = args.template_type
292
+ template_name = args.template_name
293
+
294
+ chat_file_path = _find_chat_file(chat_name)
295
+
296
+ if not chat_file_path:
297
+ raise AraError(f"Chat file for '{chat_name}' not found.")
298
+
299
+ default_patterns = {
300
+ "rules": "*.rules.md",
301
+ "intention": "*.intention.md",
302
+ "commands": "*.commands.md"
303
+ }
304
+
305
+ default_pattern = default_patterns.get(template_type)
306
+
307
+ if not template_name and not default_pattern:
308
+ raise AraError(f"A template name is required for template type '{template_type}'.")
309
+
310
+ loader = TemplateLoader() # No chat instance for CLI context
311
+ success = loader.load_template(
312
+ template_name=template_name,
313
+ template_type=template_type,
314
+ chat_file_path=chat_file_path,
315
+ default_pattern=default_pattern
316
+ )
317
+
318
+ if not success:
319
+ sys.exit(1)
320
+
321
+
322
+ @handle_errors(context="template action", error_handler=error_handler)
255
323
  def template_action(args):
256
324
  from ara_cli.classifier import Classifier
257
325
  from ara_cli.template_manager import TemplatePathManager
@@ -264,6 +332,7 @@ def template_action(args):
264
332
  print(content)
265
333
 
266
334
 
335
+ @handle_errors(context="fetch-templates action", error_handler=error_handler)
267
336
  def fetch_templates_action(args):
268
337
  import shutil
269
338
  from ara_cli.ara_config import ConfigManager
@@ -293,56 +362,35 @@ def fetch_templates_action(args):
293
362
  os.makedirs(join(local_prompt_modules_dir, subdir), exist_ok=True)
294
363
 
295
364
 
365
+ @handle_errors(context="read action", error_handler=error_handler)
296
366
  def read_action(args):
297
- from ara_cli.artefact_reader import ArtefactReader
298
- from ara_cli.file_classifier import FileClassifier
367
+ from ara_cli.commands.read_command import ReadCommand
368
+ from ara_cli.list_filter import ListFilter
299
369
 
300
370
  classifier = args.classifier
301
371
  artefact_name = args.parameter
302
372
  read_mode = args.read_mode
303
373
 
304
- file_classifier = FileClassifier(os)
305
- classified_artefacts = ArtefactReader.read_artefacts()
306
- artefacts = classified_artefacts.get(classifier, [])
307
- all_artefact_names = [a.title for a in artefacts]
308
-
309
- if artefact_name not in all_artefact_names:
310
- suggest_close_name_matches(
311
- artefact_name,
312
- all_artefact_names
313
- )
314
- return
315
-
316
- target_artefact = next(filter(
317
- lambda x: x.title == artefact_name, artefacts
318
- ))
374
+ list_filter = ListFilter(
375
+ include_content=args.include_content,
376
+ exclude_content=args.exclude_content,
377
+ include_extension=args.include_extension,
378
+ exclude_extension=args.exclude_extension,
379
+ include_tags=args.include_tags,
380
+ exclude_tags=args.exclude_tags
381
+ )
319
382
 
320
- artefacts_by_classifier = {classifier: []}
383
+ command = ReadCommand(
384
+ classifier=classifier,
385
+ artefact_name=artefact_name,
386
+ read_mode=read_mode,
387
+ list_filter=list_filter
388
+ )
321
389
 
322
- match read_mode:
323
- case "branch":
324
- ArtefactReader.step_through_value_chain(
325
- artefact_name=artefact_name,
326
- classifier=classifier,
327
- artefacts_by_classifier=artefacts_by_classifier,
328
- classified_artefacts=classified_artefacts
329
- )
330
- file_classifier.print_classified_files(artefacts_by_classifier, print_content=True)
331
- case "children":
332
- artefacts = ArtefactReader.find_children(
333
- artefact_name=artefact_name,
334
- classifier=classifier,
335
- classified_artefacts=classified_artefacts
336
- )
337
- file_classifier.print_classified_files(
338
- files_by_classifier=artefacts,
339
- print_content=True
340
- )
341
- case _:
342
- artefacts_by_classifier[classifier].append(target_artefact)
343
- file_classifier.print_classified_files(artefacts_by_classifier, print_content=True)
390
+ command.execute()
344
391
 
345
392
 
393
+ @handle_errors(context="reconnect action", error_handler=error_handler)
346
394
  def reconnect_action(args):
347
395
  from ara_cli.artefact_models.artefact_load import artefact_from_content
348
396
  from ara_cli.artefact_models.artefact_model import Contribution
@@ -370,8 +418,7 @@ def reconnect_action(args):
370
418
  )
371
419
 
372
420
  if not artefact:
373
- print(read_error_message)
374
- return
421
+ raise AraError(read_error_message)
375
422
 
376
423
  parent = ArtefactReader.read_artefact(
377
424
  artefact_name=parent_name,
@@ -380,8 +427,7 @@ def reconnect_action(args):
380
427
  )
381
428
 
382
429
  if not parent:
383
- print(read_error_message)
384
- return
430
+ raise AraError(read_error_message)
385
431
 
386
432
  contribution = Contribution(
387
433
  artefact_name=parent.title,
@@ -389,13 +435,9 @@ def reconnect_action(args):
389
435
  )
390
436
 
391
437
  if rule:
392
- try:
393
- closest_rule = find_closest_rule(parent, rule)
394
- contribution.rule = closest_rule
395
- feedback_message += f" using rule '{closest_rule}'"
396
- except TypeError as e:
397
- print(f"{type(e).__name__}:", e)
398
- exit(1)
438
+ closest_rule = find_closest_rule(parent, rule)
439
+ contribution.rule = closest_rule
440
+ feedback_message += f" using rule '{closest_rule}'"
399
441
 
400
442
  artefact.contribution = contribution
401
443
  with open(artefact.file_path, 'w', encoding='utf-8') as file:
@@ -405,6 +447,7 @@ def reconnect_action(args):
405
447
  print(feedback_message + ".")
406
448
 
407
449
 
450
+ @handle_errors(context="read-status action", error_handler=error_handler)
408
451
  def read_status_action(args):
409
452
  from ara_cli.file_classifier import FileClassifier
410
453
  from ara_cli.artefact_models.artefact_load import artefact_from_content
@@ -418,7 +461,7 @@ def read_status_action(args):
418
461
 
419
462
  all_artefact_names = [artefact_info["title"] for artefact_info in artefact_info_dicts]
420
463
  if artefact_name not in all_artefact_names:
421
- suggest_close_name_matches(artefact_name, all_artefact_names)
464
+ suggest_close_name_matches(artefact_name, all_artefact_names, report_as_error=True)
422
465
  return
423
466
 
424
467
  artefact_info = next(filter(
@@ -437,6 +480,7 @@ def read_status_action(args):
437
480
  print(status)
438
481
 
439
482
 
483
+ @handle_errors(context="read-user action", error_handler=error_handler)
440
484
  def read_user_action(args):
441
485
  from ara_cli.artefact_models.artefact_load import artefact_from_content
442
486
  from ara_cli.file_classifier import FileClassifier
@@ -450,7 +494,7 @@ def read_user_action(args):
450
494
 
451
495
  all_artefact_names = [artefact_info["title"] for artefact_info in artefact_info_dicts]
452
496
  if artefact_name not in all_artefact_names:
453
- suggest_close_name_matches(artefact_name, all_artefact_names)
497
+ suggest_close_name_matches(artefact_name, all_artefact_names, report_as_error=True)
454
498
  return
455
499
 
456
500
  artefact_info = next(filter(
@@ -470,6 +514,7 @@ def read_user_action(args):
470
514
  print(f" - {tag}")
471
515
 
472
516
 
517
+ @handle_errors(context="set-status action", error_handler=error_handler)
473
518
  def set_status_action(args):
474
519
  from ara_cli.artefact_models.artefact_model import ALLOWED_STATUS_VALUES
475
520
  from ara_cli.artefact_models.artefact_load import artefact_from_content
@@ -512,6 +557,7 @@ def set_status_action(args):
512
557
  print(f"Status of task '{artefact_name}' has been updated to '{new_status}'.")
513
558
 
514
559
 
560
+ @handle_errors(context="set-user action", error_handler=error_handler)
515
561
  def set_user_action(args):
516
562
  from ara_cli.file_classifier import FileClassifier
517
563
  from ara_cli.artefact_models.artefact_load import artefact_from_content
@@ -550,6 +596,7 @@ def set_user_action(args):
550
596
  print(f"User of task '{artefact_name}' has been updated to '{new_user}'.")
551
597
 
552
598
 
599
+ @handle_errors(context="classifier-directory action", error_handler=error_handler)
553
600
  def classifier_directory_action(args):
554
601
  from ara_cli.classifier import Classifier
555
602
 
@@ -558,6 +605,7 @@ def classifier_directory_action(args):
558
605
  print(subdirectory)
559
606
 
560
607
 
608
+ @handle_errors(context="scan action", error_handler=error_handler)
561
609
  def scan_action(args):
562
610
  from ara_cli.file_classifier import FileClassifier
563
611
  from ara_cli.artefact_scan import find_invalid_files, show_results
@@ -572,6 +620,7 @@ def scan_action(args):
572
620
  show_results(invalid_artefacts)
573
621
 
574
622
 
623
+ @handle_errors(context="autofix_action", error_handler=error_handler)
575
624
  def autofix_action(args):
576
625
  from ara_cli.artefact_autofix import parse_report, apply_autofix, read_report_file
577
626
  from ara_cli.file_classifier import FileClassifier
@@ -609,3 +658,19 @@ def autofix_action(args):
609
658
  )
610
659
 
611
660
  print("\nAutofix process completed. Please review the changes.")
661
+
662
+
663
+ @handle_errors(context="extract action", error_handler=error_handler)
664
+ def extract_action(args):
665
+ from ara_cli.commands.extract_command import ExtractCommand
666
+
667
+ filename = args.filename
668
+ force = args.force
669
+ write = getattr(args, 'write', False)
670
+ command = ExtractCommand(
671
+ file_name=filename,
672
+ force=force,
673
+ write=write,
674
+ output=lambda msg: print(msg, file=sys.stdout)
675
+ )
676
+ command.execute()