ara-cli 0.1.9.63__tar.gz → 0.1.9.65__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.
Files changed (164) hide show
  1. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/PKG-INFO +1 -1
  2. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/README.md +11 -9
  3. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/ara_command_action.py +42 -12
  4. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/ara_command_parser.py +7 -0
  5. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_autofix.py +2 -3
  6. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_creator.py +3 -2
  7. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_fuzzy_search.py +21 -2
  8. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_models/artefact_model.py +3 -2
  9. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_models/feature_artefact_model.py +64 -1
  10. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_reader.py +23 -1
  11. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/prompt_extractor.py +7 -3
  12. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/prompt_handler.py +20 -7
  13. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tag_extractor.py +20 -9
  14. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tests/test_ara_command_action.py +6 -2
  15. ara_cli-0.1.9.65/ara_cli/tests/test_tag_extractor.py +83 -0
  16. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/version.py +1 -1
  17. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli.egg-info/PKG-INFO +1 -1
  18. ara_cli-0.1.9.63/ara_cli/tests/test_tag_extractor.py +0 -54
  19. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/MANIFEST.in +0 -0
  20. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/__init__.py +0 -0
  21. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/__main__.py +0 -0
  22. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/ara_config.py +0 -0
  23. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_deleter.py +0 -0
  24. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_link_updater.py +0 -0
  25. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_lister.py +0 -0
  26. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_models/artefact_load.py +0 -0
  27. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_models/artefact_mapping.py +0 -0
  28. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_models/artefact_templates.py +0 -0
  29. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_models/businessgoal_artefact_model.py +0 -0
  30. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_models/capability_artefact_model.py +0 -0
  31. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_models/epic_artefact_model.py +0 -0
  32. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_models/example_artefact_model.py +0 -0
  33. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_models/issue_artefact_model.py +0 -0
  34. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_models/keyfeature_artefact_model.py +0 -0
  35. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_models/serialize_helper.py +0 -0
  36. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_models/task_artefact_model.py +0 -0
  37. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_models/userstory_artefact_model.py +0 -0
  38. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_models/vision_artefact_model.py +0 -0
  39. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_renamer.py +0 -0
  40. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/artefact_scan.py +0 -0
  41. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/chat.py +0 -0
  42. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/classifier.py +0 -0
  43. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/codefusionretriever.py +0 -0
  44. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/codehierachieretriever.py +0 -0
  45. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/commandline_completer.py +0 -0
  46. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/directory_navigator.py +0 -0
  47. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/file_classifier.py +0 -0
  48. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/file_lister.py +0 -0
  49. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/filename_validator.py +0 -0
  50. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/list_filter.py +0 -0
  51. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/output_suppressor.py +0 -0
  52. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/prompt_chat.py +0 -0
  53. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/prompt_rag.py +0 -0
  54. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/run_file_lister.py +0 -0
  55. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/template_manager.py +0 -0
  56. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/agile.artefacts +0 -0
  57. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/blueprints/complete_pytest_unittest.blueprint.md +0 -0
  58. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/blueprints/empty.blueprint.md +0 -0
  59. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/blueprints/task_todo_list_C4_architecture_analysis.blueprint.md +0 -0
  60. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/blueprints/task_todo_list_implement_feature_BDD_way.blueprint.md +0 -0
  61. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/commands/architecture_C4_analysis.commands.md +0 -0
  62. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/commands/architecture_radon_cc_score.commands.md +0 -0
  63. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/commands/architecture_radon_halstead_v.commands.md +0 -0
  64. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/commands/architecture_radon_maintainability_score.commands.md +0 -0
  65. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/commands/artefact_classification.commands.md +0 -0
  66. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/commands/artefact_extension.commands.md +0 -0
  67. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/commands/artefact_formulation.commands.md +0 -0
  68. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/commands/behave_step_generation.commands.md +0 -0
  69. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/commands/code_generation_complex.commands.md +0 -0
  70. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/commands/code_generation_simple.commands.md +0 -0
  71. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/commands/empty.commands.md +0 -0
  72. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/commands/error_fixing.commands.md +0 -0
  73. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/commands/feature_file_update.commands.md +0 -0
  74. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/commands/feature_formulation.commands.md +0 -0
  75. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/commands/js_code_generation_simple.commands.md +0 -0
  76. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/commands/refactoring.commands.md +0 -0
  77. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/commands/refactoring_analysis.commands.md +0 -0
  78. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/commands/reverse_engineer_feature_file.commands.md +0 -0
  79. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/commands/reverse_engineer_program_flow.commands.md +0 -0
  80. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/intentions/classify_task.intention.md +0 -0
  81. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/intentions/empty.intention.md +0 -0
  82. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/intentions/error_fixing.intention.md +0 -0
  83. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/intentions/feature_fix_steps_for_scenario.intention.md +0 -0
  84. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/intentions/feature_formulation.intention.md +0 -0
  85. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/intentions/feature_reverse_formulation_from_code.intention.md +0 -0
  86. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/intentions/feature_scenario_implementation.intention.md +0 -0
  87. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/intentions/feature_scenario_implementation_update.intention.md +0 -0
  88. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/intentions/feature_scenario_outline_extension.intention.md +0 -0
  89. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/intentions/feature_update_formulation.intention.md +0 -0
  90. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/intentions/fibonacci_example_implementation.intention.md +0 -0
  91. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/intentions/js_implementation_from_task_description.intention.md +0 -0
  92. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/intentions/js_steps_implementation.intention.md +0 -0
  93. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/intentions/python_cli_implementation_with_test.intention.md +0 -0
  94. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/intentions/python_code_understanding.intention.md +0 -0
  95. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/intentions/task_implementation.intention.md +0 -0
  96. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/intentions/task_prompt_control_by_status.intention.md +0 -0
  97. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/intentions/task_stepwise_implementation_by_number.intention.md +0 -0
  98. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/intentions/task_stepwise_implementation_by_status.intention.md +0 -0
  99. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/rules/architecture_analyst.rules.md +0 -0
  100. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/rules/code_analyst.rules.md +0 -0
  101. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/rules/empty.rules.md +0 -0
  102. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/rules/error_analyst.rules.md +0 -0
  103. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/rules/gherkin_expert.rules.md +0 -0
  104. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/rules/js_expert_developer.rules.md +0 -0
  105. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/rules/product_owner.rules.md +0 -0
  106. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/rules/python_behave.rules.md +0 -0
  107. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/prompt-modules/rules/python_developer.rules.md +0 -0
  108. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/specification_breakdown_files/template.concept.exploration.md +0 -0
  109. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/specification_breakdown_files/template.concept.md +0 -0
  110. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/specification_breakdown_files/template.customer.exploration.md +0 -0
  111. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/specification_breakdown_files/template.customer.md +0 -0
  112. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/specification_breakdown_files/template.persona.exploration.md +0 -0
  113. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/specification_breakdown_files/template.persona.md +0 -0
  114. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/specification_breakdown_files/template.step.exploration.md +0 -0
  115. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/specification_breakdown_files/template.step.md +0 -0
  116. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/specification_breakdown_files/template.technology.exploration.md +0 -0
  117. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/specification_breakdown_files/template.technology.md +0 -0
  118. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.businessgoal +0 -0
  119. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.businessgoal.prompt_log.md +0 -0
  120. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.capability +0 -0
  121. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.capability.prompt_log.md +0 -0
  122. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.epic +0 -0
  123. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.epic.prompt_log.md +0 -0
  124. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.example +0 -0
  125. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.example.prompt_log.md +0 -0
  126. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.feature +0 -0
  127. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.feature.prompt_log.md +0 -0
  128. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.issue +0 -0
  129. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.issue.prompt_log.md +0 -0
  130. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.keyfeature +0 -0
  131. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.keyfeature.prompt_log.md +0 -0
  132. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.steps.prompt_log.md +0 -0
  133. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.task +0 -0
  134. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.task.prompt_log.md +0 -0
  135. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.userstory +0 -0
  136. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.userstory.prompt_log.md +0 -0
  137. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.vision +0 -0
  138. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/templates/template.vision.prompt_log.md +0 -0
  139. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tests/__init__.py +0 -0
  140. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tests/test_ara_autofix.py +0 -0
  141. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tests/test_ara_config.py +0 -0
  142. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tests/test_artefact_fuzzy_search.py +0 -0
  143. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tests/test_artefact_link_updater.py +0 -0
  144. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tests/test_artefact_lister.py +0 -0
  145. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tests/test_artefact_reader.py +0 -0
  146. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tests/test_artefact_renamer.py +0 -0
  147. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tests/test_artefact_scan.py +0 -0
  148. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tests/test_chat.py +0 -0
  149. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tests/test_classifier.py +0 -0
  150. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tests/test_directory_navigator.py +0 -0
  151. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tests/test_file_classifier.py +0 -0
  152. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tests/test_file_creator.py +0 -0
  153. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tests/test_file_lister.py +0 -0
  154. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tests/test_list_filter.py +0 -0
  155. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tests/test_template_manager.py +0 -0
  156. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/tests/test_update_config_prompt.py +0 -0
  157. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli/update_config_prompt.py +0 -0
  158. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli.egg-info/SOURCES.txt +0 -0
  159. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli.egg-info/dependency_links.txt +0 -0
  160. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli.egg-info/entry_points.txt +0 -0
  161. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli.egg-info/requires.txt +0 -0
  162. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/ara_cli.egg-info/top_level.txt +0 -0
  163. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/setup.cfg +0 -0
  164. {ara_cli-0.1.9.63 → ara_cli-0.1.9.65}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ara_cli
3
- Version: 0.1.9.63
3
+ Version: 0.1.9.65
4
4
  Requires-Dist: litellm
5
5
  Requires-Dist: llama-index
6
6
  Requires-Dist: llama-index-llms-openai
@@ -6,7 +6,6 @@
6
6
  - [update dependencies](#update-dependencies)
7
7
  - [test and run during development](#test-and-run-during-development)
8
8
  - [set version and build and install locally for testing outside of container](#set-version-and-build-and-install-locally-for-testing-outside-of-container)
9
- - [upload to test pypi with test pypi API key](#upload-to-test-pypi-with-test-pypi-api-key)
10
9
  - [upload to live pypi with talsen team production API key (from main branch)](#upload-to-live-pypi-with-talsen-team-production-api-key-from-main-branch)
11
10
 
12
11
  # ara usage
@@ -59,6 +58,8 @@ To update dependencies, add package names in `setup.py`. The packages will ONLY
59
58
  4. Test the functionality
60
59
 
61
60
 
61
+ <!--
62
+ #### DEPRECATED
62
63
  ## upload to test pypi with test pypi API key
63
64
  1. run `bash deploy.sh`
64
65
  2. run `login.sh`
@@ -73,19 +74,20 @@ twine upload --repository testpypi dist/* --verbose -u __token__ -p pypi-AgENdGV
73
74
 
74
75
  this will upload to a test pypi account.
75
76
 
76
-
77
- 6. run `python3 -m pip install --index-url https://test.pypi.org/simple/ ara_cli==<VERSION>`
78
- 7. run `ara -h`
79
- 8. if everything has worked (upload, installation and usage) you can now continue to upload the package to pypi (live)
77
+ 1. run `python3 -m pip install --index-url https://test.pypi.org/simple/ ara_cli==<VERSION>`
78
+ 2. run `ara -h`
79
+ 3. if everything has worked (upload, installation and usage) you can now continue to upload the package to pypi (live)
80
+ -->
80
81
 
81
82
 
82
83
  ## upload to live pypi with talsen team production API key (from main branch)
83
84
  1. run `bash deploy.sh`
84
85
  2. run `login.sh`
85
- 3. `dist` folder should still be there from the testupload (otherwise do `python setup.py sdist bdist_wheel` inside the container again), do NOT upload to live without previously testing in test pypi!
86
- 4. Get the API-Key from [nextcloud](https://cloud.talsen.team/apps/keeweb/?open=%2Finfrastructure%2Fpublic-services%2Fapi-keys.kdbx)
87
- 5. Get the Password from Hans or DevOps
88
- 6. run the following command:
86
+ 3. from inside container run `python setup.py sdist bdist_wheel`
87
+ 4. `dist` folder should now contain the built wheel ready to upload
88
+ 5. Get the API-Key from [nextcloud](https://cloud.talsen.team/apps/keeweb/?open=%2Finfrastructure%2Fpublic-services%2Fapi-keys.kdbx)
89
+ 6. Get the Password from Hans or DevOps
90
+ 7. run the following command:
89
91
  ```bash
90
92
  twine upload dist/* --verbose -u __token__ -p <API-Key>
91
93
  ```
@@ -18,6 +18,8 @@ def create_action(args):
18
18
  from ara_cli.classifier import Classifier
19
19
  from ara_cli.filename_validator import is_valid_filename
20
20
  from ara_cli.template_manager import SpecificationBreakdownAspects
21
+ from ara_cli.artefact_reader import ArtefactReader
22
+ from ara_cli.artefact_fuzzy_search import find_closest_rule
21
23
 
22
24
  check_validity(Classifier.is_valid_classifier(args.classifier), "Invalid classifier provided. Please provide a valid classifier.")
23
25
  check_validity(is_valid_filename(args.parameter), "Invalid filename provided. Please provide a valid filename.")
@@ -25,11 +27,20 @@ def create_action(args):
25
27
  def handle_parent_arguments(args):
26
28
  parent_classifier = args.parent_classifier if hasattr(args, "parent_classifier") else None
27
29
  parent_name = args.parent_name if hasattr(args, "parent_name") else None
30
+ rule = args.rule if hasattr(args, 'rule') else None
31
+ invalid_classifier_message = "Invalid parent classifier provided. Please provide a valid classifier"
32
+ invalid_name_message = "Invalid filename provided for parent. Please provide a valid filename."
33
+ if parent_classifier and parent_name and rule:
34
+ check_validity(Classifier.is_valid_classifier(parent_classifier), invalid_classifier_message)
35
+ check_validity(is_valid_filename(parent_name), invalid_name_message)
36
+ parent_artefact = ArtefactReader.read_single_artefact(artefact_name=parent_name, classifier=parent_classifier)
37
+ rule = find_closest_rule(parent_artefact, rule)
38
+ return parent_classifier, parent_name, rule
28
39
  if parent_classifier and parent_name:
29
- check_validity(Classifier.is_valid_classifier(parent_classifier), "Invalid parent classifier provided. Please provide a valid classifier")
30
- check_validity(is_valid_filename(parent_name), "Invalid filename provided for parent. Please provide a valid filename.")
31
- return parent_classifier, parent_name
32
- return None, None
40
+ check_validity(Classifier.is_valid_classifier(parent_classifier), invalid_classifier_message)
41
+ check_validity(is_valid_filename(parent_name), invalid_name_message)
42
+ return parent_classifier, parent_name, rule
43
+ return None, None, None
33
44
 
34
45
  def handle_aspect_creation(args):
35
46
  aspect = args.aspect if hasattr(args, "aspect") else None
@@ -43,12 +54,12 @@ def create_action(args):
43
54
  sys.exit(1)
44
55
  return False
45
56
 
46
- parent_classifier, parent_name = handle_parent_arguments(args)
57
+ parent_classifier, parent_name, rule = handle_parent_arguments(args)
47
58
  if handle_aspect_creation(args):
48
59
  return
49
60
 
50
61
  artefact_creator = ArtefactCreator()
51
- artefact_creator.run(args.parameter, args.classifier, parent_classifier, parent_name)
62
+ artefact_creator.run(args.parameter, args.classifier, parent_classifier, parent_name, rule)
52
63
 
53
64
 
54
65
  def delete_action(args):
@@ -122,15 +133,17 @@ def list_action(args):
122
133
 
123
134
  def list_tags_action(args):
124
135
  from ara_cli.tag_extractor import TagExtractor
136
+ from ara_cli.list_filter import ListFilter
125
137
 
126
- tag_classifier = None
127
- if args.include_classifier:
128
- tag_classifier = args.include_classifier
138
+ list_filter = ListFilter(
139
+ include_extension=args.include_classifier,
140
+ exclude_extension=args.exclude_classifier,
141
+ )
129
142
 
130
143
  tag_extractor = TagExtractor()
131
144
  tags = tag_extractor.extract_tags(
132
- include_classifier=tag_classifier,
133
- filtered_extra_column=getattr(args, "filtered_extra_column", False)
145
+ filtered_extra_column=getattr(args, "filtered_extra_column", False),
146
+ list_filter=list_filter
134
147
  )
135
148
 
136
149
  if args.json:
@@ -334,14 +347,18 @@ def reconnect_action(args):
334
347
  from ara_cli.artefact_models.artefact_load import artefact_from_content
335
348
  from ara_cli.artefact_models.artefact_model import Contribution
336
349
  from ara_cli.artefact_reader import ArtefactReader
350
+ from ara_cli.artefact_fuzzy_search import find_closest_rule
337
351
 
338
352
  classifier = args.classifier
339
353
  artefact_name = args.parameter
340
354
  parent_classifier = args.parent_classifier
341
355
  parent_name = args.parent_name
356
+ rule = args.rule if hasattr(args, 'rule') else None
342
357
 
343
358
  read_error_message = f"Could not connect {classifier} '{artefact_name}' to {parent_classifier} '{parent_name}'"
344
359
 
360
+ feedback_message = f"Updated contribution of {classifier} '{artefact_name}' to {parent_classifier} '{parent_name}'"
361
+
345
362
  content, artefact_info = ArtefactReader.read_artefact(
346
363
  artefact_name=artefact_name,
347
364
  classifier=classifier
@@ -367,14 +384,27 @@ def reconnect_action(args):
367
384
  content=parent_content
368
385
  )
369
386
 
370
- artefact.contribution = Contribution(
387
+ contribution = Contribution(
371
388
  artefact_name=parent.title,
372
389
  classifier=parent.artefact_type
373
390
  )
391
+
392
+ if rule:
393
+ try:
394
+ closest_rule = find_closest_rule(parent, rule)
395
+ contribution.rule = closest_rule
396
+ feedback_message += f" using rule '{closest_rule}'"
397
+ except TypeError as e:
398
+ print(f"{type(e).__name__}:", e)
399
+ exit(1)
400
+
401
+ artefact.contribution = contribution
374
402
  with open(artefact.file_path, 'w') as file:
375
403
  artefact_content = artefact.serialize()
376
404
  file.write(artefact_content)
377
405
 
406
+ print(feedback_message + ".")
407
+
378
408
 
379
409
  def read_status_action(args):
380
410
  from ara_cli.file_classifier import FileClassifier
@@ -18,6 +18,7 @@ def create_parser(subparsers):
18
18
  contribution_parser = option_parser.add_parser("contributes-to")
19
19
  contribution_parser.add_argument("parent_classifier", choices=classifiers, help="Classifier of the parent")
20
20
  contribution_parser.add_argument("parent_name", help="Name of a parent artefact").completer = ParentNameCompleter()
21
+ contribution_parser.add_argument("-r", "--rule", dest="rule", action="store")
21
22
 
22
23
  aspect_parser = option_parser.add_parser("aspect")
23
24
  aspect_parser.add_argument("aspect", choices=aspects, help="Adds additional specification breakdown aspects in data directory.")
@@ -70,12 +71,16 @@ def add_filter_flags(parser):
70
71
  extension_group.add_argument(
71
72
  "-i",
72
73
  "--include-extension",
74
+ "--include-classifier",
75
+ dest="include_extension",
73
76
  nargs='+',
74
77
  help='list of extensions to include in listing'
75
78
  )
76
79
  extension_group.add_argument(
77
80
  "-e",
78
81
  "--exclude-extension",
82
+ "--exclude-classifier",
83
+ dest="exclude_extension",
79
84
  nargs='+',
80
85
  help='list of extensions to exclude from listing'
81
86
  )
@@ -121,6 +126,7 @@ def list_tags_parser(subparsers):
121
126
  tags_parser = subparsers.add_parser("list-tags", help="Show tags")
122
127
  tags_parser.add_argument("--json", "-j", help="Output tags as JSON", action=argparse.BooleanOptionalAction)
123
128
  tags_parser.add_argument("--include-classifier", choices=classifiers, help="Show tags for an artefact type")
129
+ tags_parser.add_argument("--exclude_classifier", choices=classifiers, help="Show tags for an artefact type")
124
130
  tags_parser.add_argument("--filtered-extra-column", action="store_true", help="Filter tags for extra column")
125
131
 
126
132
 
@@ -184,6 +190,7 @@ def reconnect_parser(subparsers):
184
190
  reconnect_parser.add_argument("parameter", help="Filename of artefact").completer = ArtefactCompleter()
185
191
  reconnect_parser.add_argument("parent_classifier", choices=classifiers, help="Classifier of the parent artefact type")
186
192
  reconnect_parser.add_argument("parent_name", help="Filename of parent artefact").completer = ParentNameCompleter()
193
+ reconnect_parser.add_argument("-r", "--rule", dest="rule", action="store")
187
194
 
188
195
 
189
196
  def read_status_parser(subparsers):
@@ -83,9 +83,8 @@ def construct_prompt(artefact_type, reason, file_path, artefact_text):
83
83
 
84
84
  prompt = (
85
85
  f"Correct the following {artefact_type} artefact to fix the issue: {reason}. "
86
- "Provide the complete, corrected artefact. Do not reformulate the artefact, "
86
+ "Provide the corrected artefact. Do not reformulate the artefact, "
87
87
  "just fix the pydantic model errors, use correct grammar. "
88
- "Do not remove comments. "
89
88
  "You should follow the name of the file "
90
89
  f"from its path {file_path} for naming the arteafact's title. "
91
90
  "You are not allowed to use file extention in the artefact title. "
@@ -114,7 +113,7 @@ def run_agent(prompt, artefact_class):
114
113
  from pydantic_ai import Agent
115
114
  # gpt-4o
116
115
  # anthropic:claude-3-7-sonnet-20250219
117
- agent = Agent(model="gpt-4o",
116
+ agent = Agent(model="anthropic:claude-3-7-sonnet-20250219",
118
117
  result_type=artefact_class, instrument=True)
119
118
  result = agent.run_sync(prompt)
120
119
  return result.data
@@ -87,7 +87,7 @@ class ArtefactCreator:
87
87
  artefact._parent = matching_artefacts[0]
88
88
  return artefact
89
89
 
90
- def run(self, filename, classifier, parent_classifier=None, parent_name=None):
90
+ def run(self, filename, classifier, parent_classifier=None, parent_name=None, rule=None):
91
91
  # make sure this function is always called from the ara top level directory
92
92
  original_directory = os.getcwd()
93
93
  navigator = DirectoryNavigator()
@@ -111,7 +111,8 @@ class ArtefactCreator:
111
111
  if parent_classifier and parent_name:
112
112
  artefact.set_contribution(
113
113
  artefact_name=parent_name,
114
- classifier=parent_classifier
114
+ classifier=parent_classifier,
115
+ rule=rule
115
116
  )
116
117
 
117
118
  artefact_content = artefact.serialize()
@@ -1,9 +1,10 @@
1
1
  import difflib
2
+ from textwrap import indent
2
3
  from typing import Optional
3
4
 
4
5
 
5
- def suggest_close_names(artefact_name: str, all_artefact_names: list[str], message: str):
6
- closest_matches = difflib.get_close_matches(artefact_name, all_artefact_names, cutoff=0.5)
6
+ def suggest_close_names(artefact_name: str, all_artefact_names: list[str], message: str, cutoff=0.5):
7
+ closest_matches = difflib.get_close_matches(artefact_name, all_artefact_names, cutoff=cutoff)
7
8
  print(message)
8
9
  if not closest_matches:
9
10
  return
@@ -38,3 +39,21 @@ def find_closest_name_match(artefact_name: str, all_artefact_names: list[str]) -
38
39
  return None
39
40
  closest_match = closest_matches[0]
40
41
  return closest_match
42
+
43
+
44
+ def find_closest_rule(parent_artefact: 'Artefact', rule: str):
45
+ parent_classifier = parent_artefact.artefact_type.value
46
+ parent_title = parent_artefact.title
47
+ if not hasattr(parent_artefact, 'rules'):
48
+ raise TypeError(f"{parent_classifier.capitalize()} artefact '{parent_title}' can not possess rules. Only userstories and epics have rules.")
49
+ rules = parent_artefact.rules
50
+ if rule in rules:
51
+ return rule
52
+ print(f"Rule '{rule}' does not match existing rules in {parent_classifier} artefact '{parent_title}'. Attempting to find closest match among existing rules.")
53
+ closest_matches = difflib.get_close_matches(rule, rules, cutoff=0.5)
54
+ rules_list_string = indent('\n'.join(rules), prefix='\t- ')
55
+ if not closest_matches:
56
+ raise ValueError(f"Can not determine a match for rule '{rule}' in {parent_classifier} artefact '{parent_title}'. Found rules:\n{rules_list_string}")
57
+ closest_match = closest_matches[0]
58
+ print(f"Found closest matching rule of '{closest_match}'")
59
+ return closest_match
@@ -401,9 +401,10 @@ class Artefact(BaseModel, ABC):
401
401
  return description
402
402
  return f"{description}{self.description}"
403
403
 
404
- def set_contribution(self, artefact_name, classifier):
404
+ def set_contribution(self, artefact_name, classifier, rule=None):
405
405
  contribution = Contribution(
406
406
  artefact_name=artefact_name,
407
- classifier=classifier
407
+ classifier=classifier,
408
+ rule=rule
408
409
  )
409
410
  self.contribution = contribution
@@ -1,5 +1,5 @@
1
1
  from pydantic import BaseModel, field_validator, model_validator, Field
2
- from typing import List, Dict, Tuple, Union
2
+ from typing import List, Dict, Tuple, Union, Optional
3
3
  from ara_cli.artefact_models.artefact_model import Artefact, ArtefactType, Intent
4
4
  import re
5
5
 
@@ -98,6 +98,35 @@ class Example(BaseModel):
98
98
  return cls(values=values)
99
99
 
100
100
 
101
+ class Background(BaseModel):
102
+ steps: List[str] = Field(
103
+ description="A list of Gherkin 'Given' type steps that describe what the background does."
104
+ )
105
+
106
+ @field_validator('steps', mode='before')
107
+ def validate_steps(cls, v: List[str]) -> List[str]:
108
+ """Ensure steps are non-empty and stripped."""
109
+ steps = [step.strip() for step in v if step.strip()]
110
+ if not steps:
111
+ raise ValueError("steps list must not be empty")
112
+ return steps
113
+
114
+ @classmethod
115
+ def from_lines(cls, lines: List[str], start_idx: int) -> Tuple['Background', int]:
116
+ """Parse a Background from a list of lines starting at start_idx."""
117
+ if not lines[start_idx].startswith('Background:'):
118
+ raise ValueError("Expected 'Background:' at start index")
119
+
120
+ steps = []
121
+ idx = start_idx + 1
122
+ while idx < len(lines) and not lines[idx].startswith('Background:'):
123
+ step = lines[idx].strip()
124
+ if step:
125
+ steps.append(step)
126
+ idx += 1
127
+ return cls(steps=steps), idx
128
+
129
+
101
130
  class Scenario(BaseModel):
102
131
  title: str = Field(
103
132
  description="The name of the scenario, giving a short summary of the test case. It comes from the 'Scenario:' line in the feature file."
@@ -213,6 +242,8 @@ class FeatureArtefact(Artefact):
213
242
  artefact_type: ArtefactType = ArtefactType.feature
214
243
  intent: FeatureIntent
215
244
  scenarios: List[Union[Scenario, ScenarioOutline]] = Field(default=None)
245
+ background: Optional[Background] = Field(
246
+ default=None, description="Highly optional background Gherkin steps for Feature Artefacts. This steps apply for all scenarios and scenario outlines in this feature file.")
216
247
 
217
248
  @field_validator('artefact_type')
218
249
  def validate_artefact_type(cls, v):
@@ -229,6 +260,16 @@ class FeatureArtefact(Artefact):
229
260
  def _artefact_type(cls) -> ArtefactType:
230
261
  return ArtefactType.feature
231
262
 
263
+ def _serialize_background(self) -> str:
264
+ """Helper method to dispatch background serialization."""
265
+ if not self.background:
266
+ return ""
267
+ lines = []
268
+ lines.append(" Background:")
269
+ for step in self.background.steps:
270
+ lines.append(f" {step}")
271
+ return "\n".join(lines)
272
+
232
273
  def _serialize_scenario(self, scenario: Union[Scenario, ScenarioOutline]) -> str:
233
274
  """Helper method to dispatch scenario serialization."""
234
275
  if isinstance(scenario, Scenario):
@@ -309,6 +350,10 @@ class FeatureArtefact(Artefact):
309
350
  lines.append(description)
310
351
  lines.append("")
311
352
 
353
+ if self.background:
354
+ lines.append(self._serialize_background())
355
+ lines.append("")
356
+
312
357
  if self.scenarios:
313
358
  for scenario in self.scenarios:
314
359
  lines.append(self._serialize_scenario(scenario))
@@ -321,9 +366,11 @@ class FeatureArtefact(Artefact):
321
366
  fields = super()._parse_common_fields(text)
322
367
 
323
368
  intent = FeatureIntent.deserialize(text)
369
+ background = cls.deserialize_background(text)
324
370
  scenarios = cls.deserialize_scenarios(text)
325
371
 
326
372
  fields['scenarios'] = scenarios
373
+ fields['background'] = background
327
374
  fields['intent'] = intent
328
375
 
329
376
  return cls(**fields)
@@ -348,3 +395,19 @@ class FeatureArtefact(Artefact):
348
395
  else:
349
396
  idx += 1
350
397
  return scenarios
398
+
399
+ @classmethod
400
+ def deserialize_background(cls, text):
401
+ lines = [line.strip()
402
+ for line in text.strip().splitlines() if line.strip()]
403
+
404
+ background = None
405
+ idx = 0
406
+ while idx < len(lines):
407
+ line = lines[idx].strip()
408
+ if line.startswith('Background:'):
409
+ background, next_idx = Background.from_lines(lines, idx)
410
+ break
411
+ else:
412
+ idx += 1
413
+ return background
@@ -1,6 +1,7 @@
1
1
  from ara_cli.classifier import Classifier
2
2
  from ara_cli.file_classifier import FileClassifier
3
3
  from ara_cli.artefact_models.artefact_model import Artefact
4
+ from ara_cli.artefact_models.artefact_load import artefact_from_content
4
5
  from ara_cli.artefact_fuzzy_search import suggest_close_name_matches_for_parent, suggest_close_name_matches
5
6
  from typing import Dict, List
6
7
  import os
@@ -9,7 +10,7 @@ import re
9
10
 
10
11
  class ArtefactReader:
11
12
  @staticmethod
12
- def read_artefact(artefact_name, classifier):
13
+ def read_artefact(artefact_name, classifier) -> tuple[str, dict[str, str]]:
13
14
  if not Classifier.is_valid_classifier(classifier):
14
15
  print("Invalid classifier provided. Please provide a valid classifier.")
15
16
  return None, None
@@ -34,6 +35,27 @@ class ArtefactReader:
34
35
 
35
36
  return None, None
36
37
 
38
+ @staticmethod
39
+ def read_single_artefact(artefact_name, classifier, classified_file_info=None) -> Artefact:
40
+ if not Classifier.is_valid_classifier(classifier):
41
+ print("Invalid classifier provided. Please provide a valid classifier.")
42
+ return None
43
+ if not classified_file_info:
44
+ file_classifier = FileClassifier(os)
45
+ classified_file_info = file_classifier.classify_files()
46
+ artefact_info_of_classifier = classified_file_info.get(classifier, [])
47
+
48
+ for artefact_info in artefact_info_of_classifier:
49
+ file_path = artefact_info["file_path"]
50
+ artefact_title = artefact_info["title"]
51
+ if artefact_title == artefact_name:
52
+ with open(file_path, 'r') as file:
53
+ content = file.read()
54
+ artefact = artefact_from_content(content)
55
+ artefact._file_path = file_path
56
+ return artefact
57
+ return None
58
+
37
59
  @staticmethod
38
60
  def extract_parent_tree(artefact_content):
39
61
  artefact_titles = Classifier.artefact_titles()
@@ -184,10 +184,14 @@ def handle_existing_file(filename, block_content):
184
184
  create_file_if_not_exist(filename, block_content)
185
185
  else:
186
186
  print(f"File {filename} exists, creating modification prompt")
187
- prompt = create_prompt_for_file_modification(block_content, filename)
187
+ prompt_text = create_prompt_for_file_modification(block_content, filename)
188
+ messages = [{"role": "user", "content": prompt_text}]
188
189
  response = ""
189
- for chunk in send_prompt(prompt):
190
- response += chunk.content
190
+
191
+ for chunk in send_prompt(messages):
192
+ content = chunk.choices[0].delta.content
193
+ if content:
194
+ response += content
191
195
  modify_and_save_file(response, filename)
192
196
 
193
197
 
@@ -355,8 +355,12 @@ def prepend_system_prompt(message_list):
355
355
 
356
356
 
357
357
  def append_images_to_message(message, image_data_list):
358
- message_content = message["content"]
359
- message["content"] = message_content + image_data_list
358
+ if not image_data_list:
359
+ return message
360
+ new_content_list = [{"type": "text", "text": message}]
361
+ new_content_list.extend(image_data_list)
362
+
363
+ message["content"] = new_content_list
360
364
 
361
365
  return message
362
366
 
@@ -376,14 +380,23 @@ def create_and_send_custom_prompt(classifier, parameter):
376
380
  append_headings(classifier, parameter, "prompt")
377
381
  write_prompt_result(classifier, parameter, prompt)
378
382
 
379
- message_list = append_images_to_message(combined_content_markdown, image_data_list)
380
- append_headings(classifier, parameter, "result")
383
+ base_message = {
384
+ "role": "user",
385
+ "content": combined_content_markdown
386
+ }
387
+
388
+ final_message = append_images_to_message(base_message, image_data_list)
381
389
 
390
+ message_list_to_send = [final_message]
391
+
392
+ append_headings(classifier, parameter, "result")
382
393
  artefact_data_path = f"ara/{sub_directory}/{parameter}.data/{classifier}.prompt_log.md"
383
394
  with open(artefact_data_path, 'a') as file:
384
- for chunk in send_prompt(message_list):
385
- file.write(chunk.content)
386
- file.flush()
395
+ for chunk in send_prompt(message_list_to_send):
396
+ content = chunk.choices[0].delta.content
397
+ if content:
398
+ file.write(content)
399
+ file.flush()
387
400
  # write_prompt_result(classifier, parameter, response)
388
401
 
389
402
 
@@ -1,12 +1,18 @@
1
1
  import os
2
- from ara_cli.artefact_models.artefact_load import artefact_from_content
2
+ from ara_cli.list_filter import ListFilter, filter_list
3
+ from ara_cli.artefact_lister import ArtefactLister
3
4
 
4
5
 
5
6
  class TagExtractor:
6
7
  def __init__(self, file_system=None):
7
8
  self.file_system = file_system or os
8
9
 
9
- def extract_tags(self, navigate_to_target=False, include_classifier=None, filtered_extra_column=False):
10
+ def extract_tags(
11
+ self,
12
+ navigate_to_target=False,
13
+ filtered_extra_column=False,
14
+ list_filter: ListFilter | None = None
15
+ ):
10
16
  from ara_cli.template_manager import DirectoryNavigator
11
17
  from ara_cli.artefact_reader import ArtefactReader
12
18
 
@@ -16,24 +22,29 @@ class TagExtractor:
16
22
 
17
23
  artefacts = ArtefactReader.read_artefacts()
18
24
 
19
- if include_classifier:
20
- artefacts = {include_classifier: artefacts[include_classifier]}
25
+ filtered_artefacts = filter_list(
26
+ list_to_filter=artefacts,
27
+ list_filter=list_filter,
28
+ content_retrieval_strategy=ArtefactLister.artefact_content_retrieval,
29
+ file_path_retrieval=ArtefactLister.artefact_path_retrieval,
30
+ tag_retrieval=ArtefactLister.artefact_tags_retrieval
31
+ )
21
32
 
22
33
  unique_tags = set()
23
34
 
24
35
  if filtered_extra_column:
25
36
  status_tags = {"to-do", "in-progress", "review", "done", "closed"}
26
- filtered_artefacts = []
37
+ artefacts_to_process = []
27
38
 
28
- for artefact_list in artefacts.values():
39
+ for artefact_list in filtered_artefacts.values():
29
40
  for artefact in artefact_list:
30
41
  tags = artefact.tags + \
31
42
  [artefact.status] if artefact.status else artefact.tags
32
43
  tag_set = set(tag for tag in tags if tag is not None)
33
44
  if not tag_set & status_tags:
34
- filtered_artefacts.append(artefact)
45
+ artefacts_to_process.append(artefact)
35
46
 
36
- for artefact in filtered_artefacts:
47
+ for artefact in artefacts_to_process:
37
48
  tags = [tag for tag in (
38
49
  artefact.tags + [artefact.status]) if tag is not None]
39
50
  for tag in tags:
@@ -46,7 +57,7 @@ class TagExtractor:
46
57
  unique_tags.add(tag)
47
58
 
48
59
  else:
49
- for artefact_list in artefacts.values():
60
+ for artefact_list in filtered_artefacts.values():
50
61
  for artefact in artefact_list:
51
62
  user_tags = [f"user_{tag}" for tag in artefact.users]
52
63
  tags = [tag for tag in (artefact.tags + [artefact.status] + user_tags) if tag is not None]
@@ -26,8 +26,10 @@ def mock_dependencies():
26
26
  "ara_cli.filename_validator.is_valid_filename"
27
27
  ) as mock_is_valid_filename, patch(
28
28
  "ara_cli.template_manager.SpecificationBreakdownAspects"
29
- ) as MockSpecificationBreakdownAspects:
30
- yield MockArtefactCreator, MockClassifier, mock_is_valid_filename, MockSpecificationBreakdownAspects
29
+ ) as MockSpecificationBreakdownAspects, patch(
30
+ "ara_cli.artefact_fuzzy_search.find_closest_rule"
31
+ ) as mock_find_closest_rule:
32
+ yield MockArtefactCreator, MockClassifier, mock_is_valid_filename, MockSpecificationBreakdownAspects, mock_find_closest_rule
31
33
 
32
34
 
33
35
  @pytest.fixture
@@ -129,9 +131,11 @@ def test_create_action_validity_checks(
129
131
  MockClassifier,
130
132
  mock_is_valid_filename,
131
133
  MockSpecificationBreakdownAspects,
134
+ mock_find_closest_rule,
132
135
  ) = mock_dependencies
133
136
  MockClassifier.is_valid_classifier.return_value = classifier_valid
134
137
  mock_is_valid_filename.return_value = filename_valid
138
+ mock_find_closest_rule.return_value = None
135
139
 
136
140
  args = MagicMock()
137
141
  args.classifier = "test_classifier"