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

ara_cli/__main__.py CHANGED
@@ -20,6 +20,7 @@ from ara_cli.ara_command_action import (
20
20
  classifier_directory_action,
21
21
  scan_action,
22
22
  autofix_action,
23
+ extract_action
23
24
  )
24
25
  import argcomplete
25
26
  import sys
@@ -45,6 +46,7 @@ def define_action_mapping():
45
46
  "classifier-directory": classifier_directory_action,
46
47
  "scan": scan_action,
47
48
  "autofix": autofix_action,
49
+ "extract": extract_action
48
50
  }
49
51
 
50
52
 
@@ -609,3 +609,18 @@ def autofix_action(args):
609
609
  )
610
610
 
611
611
  print("\nAutofix process completed. Please review the changes.")
612
+
613
+
614
+ def extract_action(args):
615
+ from ara_cli.commands.extract_command import ExtractCommand
616
+
617
+ filename = args.filename
618
+ skip_queries = args.skip_queries
619
+ print(file_name)
620
+ command = ExtractCommand(
621
+ file_name=filename,
622
+ skip_queries=skip_queries,
623
+ output=lambda msg: print(msg, file=sys.stdout),
624
+ error_output=lambda msg: print(msg, file=sys.stderr)
625
+ )
626
+ command.execute()
@@ -422,6 +422,19 @@ def autofix_parser(subparsers):
422
422
  )
423
423
 
424
424
 
425
+ def extract_parser(subparsers):
426
+ extract_parser = subparsers.add_parser("extract", help="Extract blocks of marked content from a given file.")
427
+ extract_parser.add_argument(
428
+ "filename",
429
+ help="Input file to extract from."
430
+ )
431
+ extract_parser.add_argument(
432
+ "--skip-queries", "-s",
433
+ action="store_true",
434
+ help="Answer queries with yes when extracting."
435
+ )
436
+
437
+
425
438
  class CustomHelpFormatter(argparse.HelpFormatter):
426
439
  def __init__(self, *args, **kwargs):
427
440
  self.add_examples = kwargs.pop("add_examples", False)
@@ -532,5 +545,6 @@ def action_parser():
532
545
  classifier_directory_parser(subparsers)
533
546
  scan_parser(subparsers)
534
547
  autofix_parser(subparsers)
548
+ extract_parser(subparsers)
535
549
 
536
550
  return parser
ara_cli/chat.py CHANGED
@@ -1,8 +1,13 @@
1
1
  import os
2
2
  import cmd2
3
+ import argparse
3
4
  from ara_cli.prompt_handler import send_prompt
4
5
 
5
6
 
7
+ extract_parser = argparse.ArgumentParser()
8
+ extract_parser.add_argument('-s', '--skip-queries', action='store_true', help='Force extraction')
9
+
10
+
6
11
  class Chat(cmd2.Cmd):
7
12
  CATEGORY_CHAT_CONTROL = "Chat control commands"
8
13
  CATEGORY_LLM_CONTROL = "Language model controls"
@@ -741,12 +746,18 @@ Start chatting (type 'HELP'/'h' for available commands, 'QUIT'/'q' to exit chat
741
746
  self._load_template_from_global_or_local(template_name=template_name, template_type=template_type)
742
747
 
743
748
  @cmd2.with_category(CATEGORY_CHAT_CONTROL)
744
- def do_EXTRACT(self, _):
745
- """Search for markdown code blocks containing \"# [x] extract\" as first line and \"# filename: <path/filename>\" as second line and copy the content of the code block to the specified file. The extracted code block is then marked with \"# [v] extract\""""
746
- from ara_cli.prompt_extractor import extract_responses
747
-
748
- extract_responses(self.chat_name, True)
749
- print("End of extraction")
749
+ @cmd2.with_argparser(extract_parser)
750
+ def do_EXTRACT(self, args):
751
+ """Search for markdown code blocks containing "# [x] extract" as first line and "# filename: <path/filename>" as second line and copy the content of the code block to the specified file. The extracted code block is then marked with "# [v] extract"."""
752
+ from ara_cli.commands.extract_command import ExtractCommand
753
+
754
+ command = ExtractCommand(
755
+ file_name=self.chat_name,
756
+ skip_queries=args.skip_queries,
757
+ output=self.poutput,
758
+ error_output=self.perror
759
+ )
760
+ command.execute()
750
761
 
751
762
  @cmd2.with_category(CATEGORY_CHAT_CONTROL)
752
763
  def do_LOAD_GIVENS(self, file_name):
File without changes
@@ -0,0 +1,7 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+
4
+ class Command(ABC):
5
+ @abstractmethod
6
+ def execute(self, *args, **kwargs): # pragma: no cover
7
+ pass
@@ -0,0 +1,21 @@
1
+ from ara_cli.commands.command import Command
2
+ from ara_cli.prompt_extractor import extract_responses
3
+ import os
4
+
5
+ class ExtractCommand(Command):
6
+ def __init__(self, file_name, skip_queries=False, output=None, error_output=None):
7
+ self.file_name = file_name
8
+ self.skip_queries = skip_queries
9
+ self.output = output # Callable for standard output (optional)
10
+ self.error_output = error_output # Callable for errors (optional)
11
+
12
+ def execute(self, *args, **kwargs):
13
+ try:
14
+ extract_responses(self.file_name, True, skip_queries=self.skip_queries)
15
+ if self.output:
16
+ self.output("End of extraction")
17
+ except Exception as e:
18
+ if self.error_output:
19
+ self.error_output(f"Extraction failed: {e}")
20
+ else:
21
+ raise
@@ -17,7 +17,7 @@ def extract_code_blocks_md(markdown_text):
17
17
  return code_blocks
18
18
 
19
19
 
20
- def extract_responses(document_path, relative_to_ara_root=False):
20
+ def extract_responses(document_path, relative_to_ara_root=False, skip_queries=False):
21
21
  print(f"Debug: Starting extraction from {document_path}")
22
22
  block_extraction_counter = 0
23
23
 
@@ -26,7 +26,6 @@ def extract_responses(document_path, relative_to_ara_root=False):
26
26
 
27
27
  cwd = os.getcwd()
28
28
  if relative_to_ara_root:
29
- from ara_cli.directory_navigator import DirectoryNavigator
30
29
  navigator = DirectoryNavigator()
31
30
  navigator.navigate_to_target()
32
31
  os.chdir('..')
@@ -52,7 +51,7 @@ def extract_responses(document_path, relative_to_ara_root=False):
52
51
  block_lines = block_lines[1:] # Remove first line again after removing filename line
53
52
  block = '\n'.join(block_lines)
54
53
 
55
- handle_existing_file(file_path, block)
54
+ handle_existing_file(file_path, block, skip_queries)
56
55
  block_extraction_counter += 1
57
56
 
58
57
  # Update the markdown content
@@ -81,8 +80,7 @@ def extract_responses(document_path, relative_to_ara_root=False):
81
80
  artefact_path = artefact.file_path
82
81
  directory = os.path.dirname(artefact_path)
83
82
  os.makedirs(directory, exist_ok=True)
84
- with open(artefact_path, 'w', encoding='utf-8') as file:
85
- file.write(serialized_artefact)
83
+ handle_existing_file(artefact_path, serialized_artefact, skip_queries)
86
84
 
87
85
  os.chdir(original_directory)
88
86
 
@@ -127,12 +125,19 @@ def prompt_user_decision(prompt):
127
125
  return input(prompt)
128
126
 
129
127
 
130
- def create_file_if_not_exist(filename, content):
128
+ def determine_should_create(skip_query=False):
129
+ if skip_query:
130
+ return True
131
+ user_decision = prompt_user_decision("File does not exist. Create? (y/n): ")
132
+ if user_decision.lower() in ['y', 'yes']:
133
+ return True
134
+ return False
135
+
136
+
137
+ def create_file_if_not_exist(filename, content, skip_query=False):
131
138
  try:
132
139
  if not os.path.exists(filename):
133
- user_decision = prompt_user_decision("File does not exist. Create? (y/n): ")
134
-
135
- if user_decision.lower() in ['y', 'yes']:
140
+ if determine_should_create(skip_query):
136
141
  # Ensure the directory exists
137
142
  os.makedirs(os.path.dirname(filename), exist_ok=True)
138
143
 
@@ -170,7 +175,7 @@ def create_prompt_for_file_modification(content_str, filename):
170
175
  {{
171
176
  "filename": "path/filename.filextension",
172
177
  "content": "full content of the modified file in valid json format"
173
- }}
178
+ }}
174
179
  """
175
180
 
176
181
  # print(f"Debug: modification prompt created: {prompt_text}")
@@ -178,10 +183,10 @@ def create_prompt_for_file_modification(content_str, filename):
178
183
  return prompt_text
179
184
 
180
185
 
181
- def handle_existing_file(filename, block_content):
186
+ def handle_existing_file(filename, block_content, skip_query=False):
182
187
  if not os.path.isfile(filename):
183
188
  print(f"File {filename} does not exist, attempting to create")
184
- create_file_if_not_exist(filename, block_content)
189
+ create_file_if_not_exist(filename, block_content, skip_query)
185
190
  else:
186
191
  print(f"File {filename} exists, creating modification prompt")
187
192
  prompt_text = create_prompt_for_file_modification(block_content, filename)
ara_cli/prompt_handler.py CHANGED
@@ -25,9 +25,10 @@ class LLMSingleton:
25
25
 
26
26
  if not selected_config:
27
27
  raise ValueError(f"No configuration found for the model: {model_id}")
28
-
28
+ if not isinstance(selected_config, LLMConfigItem):
29
+ selected_config = LLMConfigItem(**selected_config)
29
30
  LLMSingleton._model = model_id
30
-
31
+
31
32
  # Typesafe for None values inside the config.
32
33
  self.config_parameters = selected_config.model_dump(exclude_none=True)
33
34
 
ara_cli/version.py CHANGED
@@ -1,2 +1,2 @@
1
1
  # version.py
2
- __version__ = "0.1.9.78" # fith parameter like .0 for local install test purposes only. official numbers should be 4 digit numbers
2
+ __version__ = "0.1.9.80" # fith parameter like .0 for local install test purposes only. official numbers should be 4 digit numbers
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ara_cli
3
- Version: 0.1.9.78
3
+ Version: 0.1.9.80
4
4
  Summary: Powerful, open source command-line tool for managing, structuring and automating software development artifacts in line with Business-Driven Development (BDD) and AI-assisted processes
5
5
  Description-Content-Type: text/markdown
6
6
  Requires-Dist: litellm
@@ -24,7 +24,7 @@ Dynamic: summary
24
24
 
25
25
  # ara-cli
26
26
 
27
- **ara-cli** is a powerful, open source command-line tool for managing, structuring and automating software development artifacts in line with Business-Driven Development (BDD) and AI-assisted processes. With an intuitive interface and platform-independent implementation in Python, ara-cli enables teams to structure business goals, capabilities, features, user stories, and tasks, and to leverage integrated AI/chat capabilities for requirements engineering, documentation, and process automation.
27
+ **ara-cli** is a powerful, open source command-line tool for managing, structuring and automating software development artifacts in line with Behavior-Driven Development (BDD) and AI-assisted processes. With an intuitive interface and platform-independent implementation in Python, ara-cli enables teams to structure business goals, capabilities, features, user stories, and tasks, and to leverage integrated AI/chat capabilities for requirements engineering, documentation, and process automation.
28
28
 
29
29
  ---
30
30
 
@@ -1,7 +1,7 @@
1
1
  ara_cli/__init__.py,sha256=0zl7IegxTid26EBGLav_fXZ4CCIV3H5TfAoFQiOHjvg,148
2
- ara_cli/__main__.py,sha256=ppfq0FIi4x6ONRzP67784A4BPo2labh8Bd_EExuXo4U,2011
3
- ara_cli/ara_command_action.py,sha256=J613DUTjRxrPG8Jm-fJcIM0QlZTeULmq9Q7DKkDxJHg,22039
4
- ara_cli/ara_command_parser.py,sha256=vyxLELnyAZFC2C3v0hH4-r9QBmJ8oIs0hCZukkMFXfc,20136
2
+ ara_cli/__main__.py,sha256=J5DCDLRZ6UcpYwM1-NkjaLo4PTetcSj2dB4HrrftkUw,2064
3
+ ara_cli/ara_command_action.py,sha256=a6yqYg40QW8UXSq85J33bZqPNQkjhRkLcS2flt0Zacs,22457
4
+ ara_cli/ara_command_parser.py,sha256=I-e9W-QwTIMKMzlHycSlCWCyBFQfiFYvGre1XsDbrFI,20573
5
5
  ara_cli/ara_config.py,sha256=SgZfQVpqj5JJN4SB0n2IvAH0sKIdS3k1K1Zht2wDywA,8814
6
6
  ara_cli/artefact_autofix.py,sha256=WVTiIR-jo4YKmmz4eS3qTFvl45W1YKwAk1XSuz9QX10,20015
7
7
  ara_cli/artefact_creator.py,sha256=0Ory6cB-Ahkw-BDNb8QHnTbp_OHGABdkb9bhwcEdcIc,6063
@@ -12,7 +12,7 @@ ara_cli/artefact_lister.py,sha256=jhk4n4eqp7hDIq07q43QzS7-36BM3OfZ4EABxCeOGcw,47
12
12
  ara_cli/artefact_reader.py,sha256=Pho0_Eqm7kD9CNbVMhKb6mkNM0I3iJiCJXbXmVp1DJU,7827
13
13
  ara_cli/artefact_renamer.py,sha256=Hnz_3zD9xxnBa1FHyUE6mIktLk_9ttP2rFRvQIkmz-o,4061
14
14
  ara_cli/artefact_scan.py,sha256=msPCm-vPWOAZ_e_z5GylXxq1MtNlmJ4zvKrsdOFCWF4,4813
15
- ara_cli/chat.py,sha256=Plje33XcOedSx-nmLCkuFIXSqHPIvMcy5I71xYWuYmU,31956
15
+ ara_cli/chat.py,sha256=WguQDTgwJ8F1bnpxM7BtEkGH-jHhAzlC8aFDVig1Kks,32298
16
16
  ara_cli/classifier.py,sha256=zWskj7rBYdqYBGjksBm46iTgVU5IIf2PZsJr4qeiwVU,1878
17
17
  ara_cli/codefusionretriever.py,sha256=fCHgXdIBRzkVAnapX-KI2NQ44XbrrF4tEQmn5J6clUI,1980
18
18
  ara_cli/codehierachieretriever.py,sha256=Xd3EgEWWhkSf1TmTWtf8X5_YvyE_4B66nRrqarwSiTU,1182
@@ -24,14 +24,14 @@ ara_cli/filename_validator.py,sha256=Aw9PL8d5-Ymhp3EY6lDrUBk3cudaNqo1Uw5RzPpI1jA
24
24
  ara_cli/list_filter.py,sha256=qKGwwQsrWe7L5FbdxEbBYD1bbbi8c-RMypjXqXvLbgs,5291
25
25
  ara_cli/output_suppressor.py,sha256=nwiHaQLwabOjMoJOeUESBnZszGMxrQZfJ3N2OvahX7Y,389
26
26
  ara_cli/prompt_chat.py,sha256=kd_OINDQFit6jN04bb7mzgY259JBbRaTaNp9F-webkc,1346
27
- ara_cli/prompt_extractor.py,sha256=6l1Or7wuFNUDqbMg-NDXpFX-WMi2XV7YGH6hGDvow2o,7557
28
- ara_cli/prompt_handler.py,sha256=f1J-SAyFQjVgfi0k_Pk4JYotcU_UV4oSrLKoJH-25iM,18576
27
+ ara_cli/prompt_extractor.py,sha256=aY7k9JSfwwbhV3jiNmuijiLss1SlTJ1K_I3Q0sKK85U,7697
28
+ ara_cli/prompt_handler.py,sha256=RN409FCUC1VYvML33mcSIvfofEFrHh9iu3W-RY5ti2k,18689
29
29
  ara_cli/prompt_rag.py,sha256=ydlhe4CUqz0jdzlY7jBbpKaf_5fjMrAZKnriKea3ZAg,7485
30
30
  ara_cli/run_file_lister.py,sha256=XbrrDTJXp1LFGx9Lv91SNsEHZPP-PyEMBF_P4btjbDA,2360
31
31
  ara_cli/tag_extractor.py,sha256=TGdaQOVnjy25R0zDsAifB67C5oom0Fwo24s0_fr5A_I,3151
32
32
  ara_cli/template_manager.py,sha256=YwrN6AYPpl6ZrW8BVQpVXx8yTRf-oNpJUIKeg4NAggs,6606
33
33
  ara_cli/update_config_prompt.py,sha256=Oy9vNTw6UhDohyTEfSKkqE5ifEMPlmWNYkKHgUrK_pY,4607
34
- ara_cli/version.py,sha256=8uB-BYYtS-wDJMQLMNnX870pu9lmnUnQMT23kLhsfwE,146
34
+ ara_cli/version.py,sha256=JbVvnt8MB55-_4XtxrGGxjlyQogGwxaaodr4L4TXWmE,146
35
35
  ara_cli/artefact_models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
36
  ara_cli/artefact_models/artefact_load.py,sha256=IXzWxP-Q_j_oDGMno0m-OuXCQ7Vd5c_NctshGr4ROBw,621
37
37
  ara_cli/artefact_models/artefact_mapping.py,sha256=8aD0spBjkJ8toMAmFawc6UTUxB6-tEEViZXv2I-r88Q,1874
@@ -48,6 +48,9 @@ ara_cli/artefact_models/serialize_helper.py,sha256=Wks30wy-UrwJURetydKykLgJkdGRg
48
48
  ara_cli/artefact_models/task_artefact_model.py,sha256=1BSMbz9D-RXvdpdd0RlAr9hUx84Rcuysk2YfQC8Qy14,6046
49
49
  ara_cli/artefact_models/userstory_artefact_model.py,sha256=2awH31ROtm7j4T44Bv4cylQDYLQtnfgXZMhDu_pgw-k,6435
50
50
  ara_cli/artefact_models/vision_artefact_model.py,sha256=frjaUJj-mmIlVHEhzAQztCGs-CtvNu_odSborgztfzo,5251
51
+ ara_cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
+ ara_cli/commands/command.py,sha256=Y_2dNeuxRjbyI3ScXNv55lptSe8Hs_ya78L0nPYNZHA,154
53
+ ara_cli/commands/extract_command.py,sha256=TfKuOnKQzJ8JPpJyKDm7qhm5mvbZnHspCem8g6YgACo,835
51
54
  ara_cli/templates/agile.artefacts,sha256=nTA8dp98HWKAD-0qhmNpVYIfkVGoJshZqMJGnphiOsE,7932
52
55
  ara_cli/templates/template.businessgoal.prompt_log.md,sha256=xF6bkgj_GqAAqHxJWJiQNt11mEuSGemIqoZ2wOo6dI0,214
53
56
  ara_cli/templates/template.capability.prompt_log.md,sha256=eO8EzrHgb2vYJ-DP1jGzAfDlMo8nY75hZDfhh0s40uQ,208
@@ -131,7 +134,7 @@ tests/test_artefact_lister.py,sha256=VCEOCgDgnAOeUUgIoGAbWgz60hf9UT-tdHg18LGfB34
131
134
  tests/test_artefact_reader.py,sha256=660K-d8ed-j8hulsUB_7baPD2-hhbg9TffUR5yVc4Uo,927
132
135
  tests/test_artefact_renamer.py,sha256=lSnKCCfoFGgKhTdDZrEaeBq1xJAak1QoqH5aSeOe9Ro,3494
133
136
  tests/test_artefact_scan.py,sha256=uNWgrt7ieZ4ogKACsPqzAsh59JF2BhTKSag31hpVrTQ,16887
134
- tests/test_chat.py,sha256=fUGqpsyilLjwIFNlCAC69pYGEhwRuU6pplywwGJk-K8,54907
137
+ tests/test_chat.py,sha256=eOj3fQXRUfaRQEjS_tRFuqCgAUYSh0MUkLplYtaM1E8,54927
135
138
  tests/test_classifier.py,sha256=grYGPksydNdPsaEBQxYHZTuTdcJWz7VQtikCKA6BNaQ,1920
136
139
  tests/test_directory_navigator.py,sha256=7G0MVrBbtBvbrFUpL0zb_9EkEWi1dulWuHsrQxMJxDY,140
137
140
  tests/test_file_classifier.py,sha256=kLWPiePu3F5mkVuI_lK_2QlLh2kXD_Mt2K8KZZ1fAnA,10940
@@ -141,8 +144,8 @@ tests/test_list_filter.py,sha256=fJA3d_SdaOAUkE7jn68MOVS0THXGghy1fye_64Zvo1U,796
141
144
  tests/test_tag_extractor.py,sha256=nSiAYlTKZ7TLAOtcJpwK5zTWHhFYU0tI5xKnivLc1dU,2712
142
145
  tests/test_template_manager.py,sha256=q-LMHRG4rHkD6ON6YW4cpZxUx9hul6Or8wVVRC2kb-8,4099
143
146
  tests/test_update_config_prompt.py,sha256=xsqj1WTn4BsG5Q2t-sNPfu7EoMURFcS-hfb5VSXUnJc,6765
144
- ara_cli-0.1.9.78.dist-info/METADATA,sha256=j8cLr6oh3gVDON2FJE-pds7Psqspoxsgo008NV6btWw,6739
145
- ara_cli-0.1.9.78.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
146
- ara_cli-0.1.9.78.dist-info/entry_points.txt,sha256=v4h7MzysTgSIDYfEo3oj4Kz_8lzsRa3hq-KJHEcLVX8,45
147
- ara_cli-0.1.9.78.dist-info/top_level.txt,sha256=WM4cLHT5DYUaWzLtRj-gu3yVNFpGQ6lLRI3FMmC-38I,14
148
- ara_cli-0.1.9.78.dist-info/RECORD,,
147
+ ara_cli-0.1.9.80.dist-info/METADATA,sha256=boiCl52joIvK3TyGQ4Y3-La2zoBqC-YEDs1dPh9l43I,6739
148
+ ara_cli-0.1.9.80.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
149
+ ara_cli-0.1.9.80.dist-info/entry_points.txt,sha256=v4h7MzysTgSIDYfEo3oj4Kz_8lzsRa3hq-KJHEcLVX8,45
150
+ ara_cli-0.1.9.80.dist-info/top_level.txt,sha256=WM4cLHT5DYUaWzLtRj-gu3yVNFpGQ6lLRI3FMmC-38I,14
151
+ ara_cli-0.1.9.80.dist-info/RECORD,,
tests/test_chat.py CHANGED
@@ -1173,7 +1173,7 @@ def test_do_EXTRACT(temp_chat_file, capsys):
1173
1173
 
1174
1174
  with patch('ara_cli.prompt_extractor.extract_responses') as mock_extract_responses:
1175
1175
  chat.do_EXTRACT("")
1176
- mock_extract_responses.assert_called_once_with(temp_chat_file.name, True)
1176
+ mock_extract_responses.assert_called_once_with(temp_chat_file.name, True, skip_queries=False)
1177
1177
 
1178
1178
  captured = capsys.readouterr()
1179
1179
  assert "End of extraction" in captured.out