ara-cli 0.1.9.81__tar.gz → 0.1.9.84__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 (160) hide show
  1. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/PKG-INFO +1 -1
  2. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/chat.py +116 -90
  3. ara_cli-0.1.9.84/ara_cli/commands/load_command.py +65 -0
  4. ara_cli-0.1.9.84/ara_cli/commands/load_image_command.py +34 -0
  5. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/prompt_handler.py +55 -0
  6. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/version.py +1 -1
  7. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli.egg-info/PKG-INFO +1 -1
  8. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli.egg-info/SOURCES.txt +2 -0
  9. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/test_chat.py +221 -151
  10. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/MANIFEST.in +0 -0
  11. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/README.md +0 -0
  12. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/__init__.py +0 -0
  13. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/__main__.py +0 -0
  14. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/ara_command_action.py +0 -0
  15. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/ara_command_parser.py +0 -0
  16. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/ara_config.py +0 -0
  17. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_autofix.py +0 -0
  18. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_creator.py +0 -0
  19. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_deleter.py +0 -0
  20. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_fuzzy_search.py +0 -0
  21. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_link_updater.py +0 -0
  22. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_lister.py +0 -0
  23. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_models/__init__.py +0 -0
  24. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_models/artefact_load.py +0 -0
  25. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_models/artefact_mapping.py +0 -0
  26. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_models/artefact_model.py +0 -0
  27. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_models/artefact_templates.py +0 -0
  28. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_models/businessgoal_artefact_model.py +0 -0
  29. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_models/capability_artefact_model.py +0 -0
  30. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_models/epic_artefact_model.py +0 -0
  31. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_models/example_artefact_model.py +0 -0
  32. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_models/feature_artefact_model.py +0 -0
  33. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_models/issue_artefact_model.py +0 -0
  34. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_models/keyfeature_artefact_model.py +0 -0
  35. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_models/serialize_helper.py +0 -0
  36. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_models/task_artefact_model.py +0 -0
  37. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_models/userstory_artefact_model.py +0 -0
  38. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_models/vision_artefact_model.py +0 -0
  39. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_reader.py +0 -0
  40. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_renamer.py +0 -0
  41. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/artefact_scan.py +0 -0
  42. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/classifier.py +0 -0
  43. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/codefusionretriever.py +0 -0
  44. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/codehierachieretriever.py +0 -0
  45. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/commandline_completer.py +0 -0
  46. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/commands/__init__.py +0 -0
  47. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/commands/command.py +0 -0
  48. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/commands/extract_command.py +0 -0
  49. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/directory_navigator.py +0 -0
  50. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/file_classifier.py +0 -0
  51. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/file_lister.py +0 -0
  52. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/filename_validator.py +0 -0
  53. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/list_filter.py +0 -0
  54. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/output_suppressor.py +0 -0
  55. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/prompt_chat.py +0 -0
  56. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/prompt_extractor.py +0 -0
  57. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/prompt_rag.py +0 -0
  58. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/run_file_lister.py +0 -0
  59. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/tag_extractor.py +0 -0
  60. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/template_manager.py +0 -0
  61. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/agile.artefacts +0 -0
  62. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/blueprints/complete_pytest_unittest.blueprint.md +0 -0
  63. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/blueprints/empty.blueprint.md +0 -0
  64. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/blueprints/task_todo_list_C4_architecture_analysis.blueprint.md +0 -0
  65. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/blueprints/task_todo_list_implement_feature_BDD_way.blueprint.md +0 -0
  66. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/commands/architecture_C4_analysis.commands.md +0 -0
  67. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/commands/architecture_radon_cc_score.commands.md +0 -0
  68. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/commands/architecture_radon_halstead_v.commands.md +0 -0
  69. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/commands/architecture_radon_maintainability_score.commands.md +0 -0
  70. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/commands/artefact_classification.commands.md +0 -0
  71. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/commands/artefact_extension.commands.md +0 -0
  72. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/commands/artefact_formulation.commands.md +0 -0
  73. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/commands/behave_step_generation.commands.md +0 -0
  74. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/commands/code_generation_complex.commands.md +0 -0
  75. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/commands/code_generation_simple.commands.md +0 -0
  76. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/commands/empty.commands.md +0 -0
  77. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/commands/error_fixing.commands.md +0 -0
  78. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/commands/feature_file_update.commands.md +0 -0
  79. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/commands/feature_formulation.commands.md +0 -0
  80. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/commands/js_code_generation_simple.commands.md +0 -0
  81. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/commands/refactoring.commands.md +0 -0
  82. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/commands/refactoring_analysis.commands.md +0 -0
  83. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/commands/reverse_engineer_feature_file.commands.md +0 -0
  84. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/commands/reverse_engineer_program_flow.commands.md +0 -0
  85. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/intentions/classify_task.intention.md +0 -0
  86. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/intentions/empty.intention.md +0 -0
  87. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/intentions/error_fixing.intention.md +0 -0
  88. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/intentions/feature_fix_steps_for_scenario.intention.md +0 -0
  89. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/intentions/feature_formulation.intention.md +0 -0
  90. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/intentions/feature_reverse_formulation_from_code.intention.md +0 -0
  91. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/intentions/feature_scenario_implementation.intention.md +0 -0
  92. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/intentions/feature_scenario_implementation_update.intention.md +0 -0
  93. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/intentions/feature_scenario_outline_extension.intention.md +0 -0
  94. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/intentions/feature_update_formulation.intention.md +0 -0
  95. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/intentions/fibonacci_example_implementation.intention.md +0 -0
  96. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/intentions/js_implementation_from_task_description.intention.md +0 -0
  97. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/intentions/js_steps_implementation.intention.md +0 -0
  98. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/intentions/python_cli_implementation_with_test.intention.md +0 -0
  99. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/intentions/python_code_understanding.intention.md +0 -0
  100. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/intentions/task_implementation.intention.md +0 -0
  101. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/intentions/task_prompt_control_by_status.intention.md +0 -0
  102. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/intentions/task_stepwise_implementation_by_number.intention.md +0 -0
  103. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/intentions/task_stepwise_implementation_by_status.intention.md +0 -0
  104. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/rules/architecture_analyst.rules.md +0 -0
  105. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/rules/code_analyst.rules.md +0 -0
  106. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/rules/empty.rules.md +0 -0
  107. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/rules/error_analyst.rules.md +0 -0
  108. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/rules/gherkin_expert.rules.md +0 -0
  109. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/rules/js_expert_developer.rules.md +0 -0
  110. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/rules/product_owner.rules.md +0 -0
  111. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/rules/python_behave.rules.md +0 -0
  112. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/prompt-modules/rules/python_developer.rules.md +0 -0
  113. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/specification_breakdown_files/template.concept.exploration.md +0 -0
  114. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/specification_breakdown_files/template.concept.md +0 -0
  115. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/specification_breakdown_files/template.customer.exploration.md +0 -0
  116. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/specification_breakdown_files/template.customer.md +0 -0
  117. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/specification_breakdown_files/template.persona.exploration.md +0 -0
  118. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/specification_breakdown_files/template.persona.md +0 -0
  119. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/specification_breakdown_files/template.step.exploration.md +0 -0
  120. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/specification_breakdown_files/template.step.md +0 -0
  121. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/specification_breakdown_files/template.technology.exploration.md +0 -0
  122. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/specification_breakdown_files/template.technology.md +0 -0
  123. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/template.businessgoal.prompt_log.md +0 -0
  124. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/template.capability.prompt_log.md +0 -0
  125. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/template.epic.prompt_log.md +0 -0
  126. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/template.example.prompt_log.md +0 -0
  127. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/template.feature.prompt_log.md +0 -0
  128. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/template.issue.prompt_log.md +0 -0
  129. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/template.keyfeature.prompt_log.md +0 -0
  130. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/template.steps.prompt_log.md +0 -0
  131. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/template.task.prompt_log.md +0 -0
  132. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/template.userstory.prompt_log.md +0 -0
  133. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/templates/template.vision.prompt_log.md +0 -0
  134. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli/update_config_prompt.py +0 -0
  135. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli.egg-info/dependency_links.txt +0 -0
  136. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli.egg-info/entry_points.txt +0 -0
  137. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli.egg-info/requires.txt +0 -0
  138. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/ara_cli.egg-info/top_level.txt +0 -0
  139. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/docker/base/requirements.txt +0 -0
  140. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/setup.cfg +0 -0
  141. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/setup.py +0 -0
  142. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/__init__.py +0 -0
  143. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/test_ara_command_action.py +0 -0
  144. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/test_ara_config.py +0 -0
  145. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/test_artefact_autofix.py +0 -0
  146. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/test_artefact_fuzzy_search.py +0 -0
  147. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/test_artefact_link_updater.py +0 -0
  148. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/test_artefact_lister.py +0 -0
  149. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/test_artefact_reader.py +0 -0
  150. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/test_artefact_renamer.py +0 -0
  151. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/test_artefact_scan.py +0 -0
  152. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/test_classifier.py +0 -0
  153. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/test_directory_navigator.py +0 -0
  154. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/test_file_classifier.py +0 -0
  155. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/test_file_creator.py +0 -0
  156. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/test_file_lister.py +0 -0
  157. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/test_list_filter.py +0 -0
  158. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/test_tag_extractor.py +0 -0
  159. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/test_template_manager.py +0 -0
  160. {ara_cli-0.1.9.81 → ara_cli-0.1.9.84}/tests/test_update_config_prompt.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ara_cli
3
- Version: 0.1.9.81
3
+ Version: 0.1.9.84
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
@@ -1,12 +1,20 @@
1
1
  import os
2
- import cmd2
3
2
  import argparse
3
+ import cmd2
4
4
  from ara_cli.prompt_handler import send_prompt
5
5
 
6
+ from ara_cli.file_loaders.document_file_loader import DocumentFileLoader
7
+ from ara_cli.file_loaders.binary_file_loader import BinaryFileLoader
8
+ from ara_cli.file_loaders.text_file_loader import TextFileLoader
9
+
6
10
 
7
11
  extract_parser = argparse.ArgumentParser()
8
12
  extract_parser.add_argument('-s', '--skip-queries', action='store_true', help='Force extraction')
9
13
 
14
+ load_parser = argparse.ArgumentParser()
15
+ load_parser.add_argument('file_name', nargs='?', default='', help='File to load')
16
+ load_parser.add_argument('--load-images', action='store_true', help='Extract and describe images from documents')
17
+
10
18
 
11
19
  class Chat(cmd2.Cmd):
12
20
  CATEGORY_CHAT_CONTROL = "Chat control commands"
@@ -353,75 +361,67 @@ Start chatting (type 'HELP'/'h' for available commands, 'QUIT'/'q' to exit chat
353
361
  return None
354
362
  return file_path
355
363
 
356
- @file_exists_check
357
- def load_text_file(self, file_path, prefix: str = "", suffix: str = "", block_delimiter: str = ""):
358
- with open(file_path, 'r', encoding='utf-8', errors="replace") as file:
359
- file_content = file.read()
360
- if block_delimiter:
361
- file_content = f"{block_delimiter}\n{file_content}\n{block_delimiter}"
362
- write_content = f"{prefix}{file_content}{suffix}\n"
363
-
364
- with open(self.chat_name, 'a', encoding='utf-8') as chat_file:
365
- chat_file.write(write_content)
366
- return True
364
+ # @file_exists_check
365
+ def load_text_file(
366
+ self,
367
+ file_path,
368
+ prefix: str = "",
369
+ suffix: str = "",
370
+ block_delimiter: str = "",
371
+ extract_images: bool = False
372
+ ):
373
+ loader = TextFileLoader(self)
374
+ return loader.load(
375
+ file_path,
376
+ prefix=prefix,
377
+ suffix=suffix,
378
+ block_delimiter=block_delimiter,
379
+ extract_images=extract_images
380
+ )
367
381
 
368
- @file_exists_check
382
+ # @file_exists_check
369
383
  def load_binary_file(self, file_path, mime_type: str, prefix: str = "", suffix: str = ""):
370
- import base64
371
-
372
- with open(file_path, 'rb') as file:
373
- file_content = file.read()
374
- base64_image = base64.b64encode(file_content).decode("utf-8")
375
-
376
- write_content = f"{prefix}![{os.path.basename(file_path)}](data:{mime_type};base64,{base64_image}){suffix}\n"
377
-
378
- with open(self.chat_name, 'a', encoding='utf-8') as chat_file:
379
- chat_file.write(write_content)
380
- return True
381
-
382
- def read_docx(self, file_path):
383
- import docx
384
- doc = docx.Document(file_path)
385
- return '\n'.join(para.text for para in doc.paragraphs)
386
-
387
- def read_pdf(self, file_path):
388
- import pymupdf4llm
389
- return pymupdf4llm.to_markdown(file_path, write_images=False)
390
-
391
- def read_odt(self, file_path):
392
- import pymupdf4llm
393
- return pymupdf4llm.to_markdown(file_path, write_images=False)
394
-
395
- @file_exists_check
396
- def load_document_file(self, file_path: str, prefix: str = "", suffix: str = "", block_delimiter: str = "```"):
397
- import os
398
-
399
- _, ext = os.path.splitext(file_path)
400
- ext = ext.lower()
401
-
402
- text_content = ""
403
- match ext:
404
- case ".docx":
405
- text_content = self.read_docx(file_path)
406
- case ".pdf":
407
- text_content = self.read_pdf(file_path)
408
- case ".odt":
409
- text_content = self.read_odt(file_path)
410
- # Add more cases if needed.
411
- case _:
412
- print("Unsupported document type.")
413
- return False
384
+ loader = BinaryFileLoader(self)
385
+ return loader.load(
386
+ file_path,
387
+ mime_type=mime_type,
388
+ prefix=prefix,
389
+ suffix=suffix
390
+ )
414
391
 
415
- if block_delimiter:
416
- text_content = f"{block_delimiter}\n{text_content}\n{block_delimiter}"
392
+ def read_markdown(self, file_path: str, extract_images: bool = False) -> str:
393
+ """Read markdown file and optionally extract/describe images"""
394
+ from ara_cli.file_loaders.text_file_loader import MarkdownReader
417
395
 
418
- write_content = f"{prefix}{text_content}{suffix}\n"
396
+ reader = MarkdownReader(file_path)
397
+ return reader.read(extract_images=extract_images)
419
398
 
420
- with open(self.chat_name, 'a', encoding='utf-8') as chat_file:
421
- chat_file.write(write_content)
422
- return True
399
+ # @file_exists_check
400
+ def load_document_file(
401
+ self,
402
+ file_path: str,
403
+ prefix: str = "",
404
+ suffix: str = "",
405
+ block_delimiter: str = "```",
406
+ extract_images: bool = False
407
+ ):
408
+ loader = DocumentFileLoader(self)
409
+ return loader.load(
410
+ file_path,
411
+ prefix=prefix,
412
+ suffix=suffix,
413
+ block_delimiter=block_delimiter,
414
+ extract_images=extract_images
415
+ )
423
416
 
424
- def load_file(self, file_name: str, prefix: str = "", suffix: str = "", block_delimiter: str = ""):
417
+ def load_file(
418
+ self,
419
+ file_name: str,
420
+ prefix: str = "",
421
+ suffix: str = "",
422
+ block_delimiter: str = "",
423
+ extract_images: bool = False
424
+ ):
425
425
  binary_type_mapping = Chat.BINARY_TYPE_MAPPING
426
426
  document_type_extensions = Chat.DOCUMENT_TYPE_EXTENSIONS
427
427
 
@@ -432,28 +432,31 @@ Start chatting (type 'HELP'/'h' for available commands, 'QUIT'/'q' to exit chat
432
432
  file_type = mime_type
433
433
  break
434
434
 
435
- is_file_document = any(file_name_lower.endswith(ext) for ext in document_type_extensions)
435
+ is_file_document = any(file_name_lower.endswith(ext)
436
+ for ext in document_type_extensions)
436
437
 
437
438
  if is_file_document:
438
439
  return self.load_document_file(
439
- file_name=file_name,
440
+ file_path=file_name,
440
441
  prefix=prefix,
441
442
  suffix=suffix,
442
- block_delimiter=block_delimiter
443
+ block_delimiter=block_delimiter,
444
+ extract_images=extract_images
443
445
  )
444
446
  elif file_type:
445
447
  return self.load_binary_file(
446
- file_name=file_name,
448
+ file_path=file_name,
447
449
  mime_type=file_type,
448
450
  prefix=prefix,
449
451
  suffix=suffix
450
452
  )
451
453
  else:
452
454
  return self.load_text_file(
453
- file_name=file_name,
455
+ file_path=file_name,
454
456
  prefix=prefix,
455
457
  suffix=suffix,
456
- block_delimiter=block_delimiter
458
+ block_delimiter=block_delimiter,
459
+ extract_images=extract_images
457
460
  )
458
461
 
459
462
  def choose_file_to_load(self, files: list[str], pattern: str):
@@ -496,8 +499,14 @@ Start chatting (type 'HELP'/'h' for available commands, 'QUIT'/'q' to exit chat
496
499
  self.message_buffer.append(self.full_input)
497
500
 
498
501
  @cmd2.with_category(CATEGORY_CHAT_CONTROL)
499
- def do_LOAD(self, file_name):
500
- """Load a file and append its contents to chat file. Can be given the file name in-line. Will attempt to find the file relative to chat file first, then treat the given path as absolute"""
502
+ @cmd2.with_argparser(load_parser)
503
+ def do_LOAD(self, args):
504
+ """Load a file and append its contents to chat file. Can be given the file name in-line. Will attempt to find the file relative to chat file first, then treat the given path as absolute. Use --load-images flag to extract and describe images from documents."""
505
+ from ara_cli.commands.load_command import LoadCommand
506
+
507
+ file_name = args.file_name
508
+ load_images = args.load_images
509
+
501
510
  matching_files = self.find_matching_files_to_load(file_name)
502
511
  if not matching_files:
503
512
  return
@@ -506,12 +515,20 @@ Start chatting (type 'HELP'/'h' for available commands, 'QUIT'/'q' to exit chat
506
515
  block_delimiter = "```"
507
516
  prefix = f"\nFile: {file_path}\n"
508
517
  self.add_prompt_tag_if_needed(self.chat_name)
509
- if not os.path.isdir(file_path) and self.load_file(file_path, prefix=prefix, block_delimiter=block_delimiter):
510
- print(f"Loaded contents of file {file_path}")
518
+
519
+ if not os.path.isdir(file_path):
520
+ command = LoadCommand(
521
+ chat_instance=self,
522
+ file_path=file_path,
523
+ prefix=prefix,
524
+ block_delimiter=block_delimiter,
525
+ extract_images=load_images,
526
+ output=self.poutput
527
+ )
528
+ command.execute()
511
529
 
512
530
  def complete_LOAD(self, text, line, begidx, endidx):
513
531
  import glob
514
-
515
532
  return [x for x in glob.glob(text + '*')]
516
533
 
517
534
  def _retrieve_ara_config(self):
@@ -547,7 +564,7 @@ Start chatting (type 'HELP'/'h' for available commands, 'QUIT'/'q' to exit chat
547
564
 
548
565
  if file_type:
549
566
  return self.load_binary_file(
550
- file_name=file_name,
567
+ file_path=file_name,
551
568
  mime_type=file_type,
552
569
  prefix=prefix,
553
570
  suffix=suffix
@@ -562,22 +579,12 @@ Start chatting (type 'HELP'/'h' for available commands, 'QUIT'/'q' to exit chat
562
579
  return False
563
580
  return True
564
581
 
565
- @cmd2.with_category(CATEGORY_CHAT_CONTROL)
566
- def do_LOAD_DOCUMENT(self, file_name):
567
- """Load a document file (PDF, DOCX, DOC, ODT) and append its text content to chat file. Can be given the file name in-line. Will attempt to find the file relative to chat file first, then treat the given path as absolute"""
568
- matching_files = self.find_matching_files_to_load(file_name)
569
- if not matching_files:
570
- return
571
-
572
- for file_path in matching_files:
573
- prefix = f"\nFile: {file_path}\n"
574
- self.add_prompt_tag_if_needed(self.chat_name)
575
- if not os.path.isdir(file_path) and self.load_document_file(file_path, prefix=prefix):
576
- print(f"Loaded document file {file_path}")
577
582
 
578
583
  @cmd2.with_category(CATEGORY_CHAT_CONTROL)
579
584
  def do_LOAD_IMAGE(self, file_name):
580
585
  """Load an image file and append it to chat file. Can be given the file name in-line. Will attempt to find the file relative to chat file first, then treat the given path as absolute"""
586
+ from ara_cli.commands.load_image_command import LoadImageCommand
587
+
581
588
  matching_files = self.find_matching_files_to_load(file_name)
582
589
  if not matching_files:
583
590
  return
@@ -585,8 +592,27 @@ Start chatting (type 'HELP'/'h' for available commands, 'QUIT'/'q' to exit chat
585
592
  for file_path in matching_files:
586
593
  prefix = f"\nFile: {file_path}\n"
587
594
  self.add_prompt_tag_if_needed(self.chat_name)
588
- if not os.path.isdir(file_path) and self.load_image(file_path, prefix=prefix):
589
- print(f"Loaded image file {file_path}")
595
+
596
+ if not os.path.isdir(file_path):
597
+ # Determine mime type
598
+ file_type = None
599
+ file_path_lower = file_path.lower()
600
+ for extension, mime_type in Chat.BINARY_TYPE_MAPPING.items():
601
+ if file_path_lower.endswith(extension):
602
+ file_type = mime_type
603
+ break
604
+
605
+ if file_type:
606
+ command = LoadImageCommand(
607
+ chat_instance=self,
608
+ file_path=file_path,
609
+ mime_type=file_type,
610
+ prefix=prefix,
611
+ output=self.poutput
612
+ )
613
+ command.execute()
614
+ else:
615
+ self.perror(f"File {file_path} not recognized as image, could not load")
590
616
 
591
617
  @cmd2.with_category(CATEGORY_LLM_CONTROL)
592
618
  def do_LIST_MODELS(self, _):
@@ -0,0 +1,65 @@
1
+ from ara_cli.commands.command import Command
2
+ from ara_cli.file_loaders.file_loader import FileLoaderFactory
3
+ from ara_cli.file_loaders.binary_file_loader import BinaryFileLoader
4
+
5
+
6
+ class LoadCommand(Command):
7
+ def __init__(
8
+ self,
9
+ chat_instance,
10
+ file_path: str,
11
+ prefix: str = "",
12
+ suffix: str = "",
13
+ block_delimiter: str = "",
14
+ extract_images: bool = False,
15
+ output=None
16
+ ):
17
+ self.chat = chat_instance
18
+ self.file_path = file_path
19
+ self.prefix = prefix
20
+ self.suffix = suffix
21
+ self.block_delimiter = block_delimiter
22
+ self.extract_images = extract_images
23
+ self.output = output or print
24
+
25
+ def execute(self) -> bool:
26
+ loader = FileLoaderFactory.create_loader(self.file_path, self.chat)
27
+
28
+ if isinstance(loader, BinaryFileLoader):
29
+ # Determine mime type for binary files
30
+ file_name_lower = self.file_path.lower()
31
+ mime_type = None
32
+ for extension, mt in FileLoaderFactory.BINARY_TYPE_MAPPING.items():
33
+ if file_name_lower.endswith(extension):
34
+ mime_type = mt
35
+ break
36
+
37
+ if not mime_type:
38
+ self.output(
39
+ f"Could not determine mime type for {self.file_path}")
40
+ return False
41
+
42
+ success = loader.load(
43
+ self.file_path,
44
+ mime_type=mime_type,
45
+ prefix=self.prefix,
46
+ suffix=self.suffix
47
+ )
48
+ elif hasattr(loader, 'load'):
49
+ success = loader.load(
50
+ self.file_path,
51
+ prefix=self.prefix,
52
+ suffix=self.suffix,
53
+ block_delimiter=self.block_delimiter,
54
+ extract_images=self.extract_images
55
+ )
56
+ else:
57
+ return False
58
+
59
+ if success:
60
+ if self.extract_images and not isinstance(loader, BinaryFileLoader):
61
+ self.output(
62
+ f"Loaded contents of file {self.file_path} with images extracted")
63
+ else:
64
+ self.output(f"Loaded contents of file {self.file_path}")
65
+ return success
@@ -0,0 +1,34 @@
1
+ from ara_cli.commands.command import Command
2
+ from ara_cli.file_loaders.binary_file_loader import BinaryFileLoader
3
+
4
+
5
+ class LoadImageCommand(Command):
6
+ def __init__(
7
+ self,
8
+ chat_instance,
9
+ file_path: str,
10
+ mime_type: str,
11
+ prefix: str = "",
12
+ suffix: str = "",
13
+ output=None
14
+ ):
15
+ self.chat = chat_instance
16
+ self.file_path = file_path
17
+ self.mime_type = mime_type
18
+ self.prefix = prefix
19
+ self.suffix = suffix
20
+ self.output = output or print
21
+
22
+ def execute(self) -> bool:
23
+ loader = BinaryFileLoader(self.chat)
24
+ success = loader.load(
25
+ self.file_path,
26
+ mime_type=self.mime_type,
27
+ prefix=self.prefix,
28
+ suffix=self.suffix
29
+ )
30
+
31
+ if success:
32
+ self.output(f"Loaded image file {self.file_path}")
33
+
34
+ return success
@@ -15,6 +15,8 @@ import glob
15
15
  import logging
16
16
 
17
17
 
18
+
19
+
18
20
  class LLMSingleton:
19
21
  _instance = None
20
22
  _model = None
@@ -105,6 +107,59 @@ def send_prompt(prompt):
105
107
  yield chunk
106
108
 
107
109
 
110
+ def describe_image(image_path: str) -> str:
111
+ """
112
+ Send an image to the LLM and get a text description.
113
+
114
+ Args:
115
+ image_path: Path to the image file
116
+
117
+ Returns:
118
+ Text description of the image
119
+ """
120
+ import base64
121
+
122
+ # Read and encode the image
123
+ with open(image_path, 'rb') as image_file:
124
+ base64_image = base64.b64encode(image_file.read()).decode('utf-8')
125
+
126
+ # Determine image type
127
+ image_extension = os.path.splitext(image_path)[1].lower()
128
+ mime_type = {
129
+ '.png': 'image/png',
130
+ '.jpg': 'image/jpeg',
131
+ '.jpeg': 'image/jpeg',
132
+ '.gif': 'image/gif',
133
+ '.bmp': 'image/bmp'
134
+ }.get(image_extension, 'image/png')
135
+
136
+ # Create message with image
137
+ message = {
138
+ "role": "user",
139
+ "content": [
140
+ {
141
+ "type": "text",
142
+ "text": "Please describe this image in detail. If it contains text, transcribe it exactly. If it's a diagram or chart, explain its structure and content. If it's a photo or illustration, describe what you see."
143
+ },
144
+ {
145
+ "type": "image_url",
146
+ "image_url": {
147
+ "url": f"data:{mime_type};base64,{base64_image}"
148
+ }
149
+ }
150
+ ]
151
+ }
152
+
153
+ # Get response from LLM
154
+ response_text = ""
155
+ for chunk in send_prompt([message]):
156
+ chunk_content = chunk.choices[0].delta.content
157
+ if chunk_content:
158
+ response_text += chunk_content
159
+
160
+ return response_text.strip()
161
+
162
+
108
163
  def append_headings(classifier, param, heading_name):
109
164
  sub_directory = Classifier.get_sub_directory(classifier)
110
165
 
@@ -1,2 +1,2 @@
1
1
  # version.py
2
- __version__ = "0.1.9.81" # fith parameter like .0 for local install test purposes only. official numbers should be 4 digit numbers
2
+ __version__ = "0.1.9.84" # 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.81
3
+ Version: 0.1.9.84
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
@@ -60,6 +60,8 @@ ara_cli/artefact_models/vision_artefact_model.py
60
60
  ara_cli/commands/__init__.py
61
61
  ara_cli/commands/command.py
62
62
  ara_cli/commands/extract_command.py
63
+ ara_cli/commands/load_command.py
64
+ ara_cli/commands/load_image_command.py
63
65
  ara_cli/templates/agile.artefacts
64
66
  ara_cli/templates/template.businessgoal.prompt_log.md
65
67
  ara_cli/templates/template.capability.prompt_log.md