ara-cli 0.1.10.5__py3-none-any.whl → 0.1.13.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. ara_cli/__init__.py +51 -6
  2. ara_cli/__main__.py +87 -75
  3. ara_cli/ara_command_action.py +95 -57
  4. ara_cli/ara_config.py +187 -128
  5. ara_cli/ara_subcommands/common.py +2 -2
  6. ara_cli/ara_subcommands/config.py +221 -0
  7. ara_cli/ara_subcommands/convert.py +43 -0
  8. ara_cli/ara_subcommands/fetch.py +41 -0
  9. ara_cli/ara_subcommands/fetch_agents.py +22 -0
  10. ara_cli/ara_subcommands/fetch_scripts.py +19 -0
  11. ara_cli/ara_subcommands/fetch_templates.py +15 -10
  12. ara_cli/ara_subcommands/list.py +97 -23
  13. ara_cli/artefact_autofix.py +115 -62
  14. ara_cli/artefact_converter.py +256 -0
  15. ara_cli/chat.py +283 -62
  16. ara_cli/chat_agent/__init__.py +0 -0
  17. ara_cli/chat_agent/agent_process_manager.py +155 -0
  18. ara_cli/chat_script_runner/__init__.py +0 -0
  19. ara_cli/chat_script_runner/script_completer.py +23 -0
  20. ara_cli/chat_script_runner/script_finder.py +41 -0
  21. ara_cli/chat_script_runner/script_lister.py +36 -0
  22. ara_cli/chat_script_runner/script_runner.py +36 -0
  23. ara_cli/chat_web_search/__init__.py +0 -0
  24. ara_cli/chat_web_search/web_search.py +263 -0
  25. ara_cli/commands/agent_run_command.py +98 -0
  26. ara_cli/commands/fetch_agents_command.py +106 -0
  27. ara_cli/commands/fetch_scripts_command.py +43 -0
  28. ara_cli/commands/fetch_templates_command.py +39 -0
  29. ara_cli/commands/fetch_templates_commands.py +39 -0
  30. ara_cli/commands/list_agents_command.py +39 -0
  31. ara_cli/completers.py +71 -35
  32. ara_cli/constants.py +2 -0
  33. ara_cli/directory_navigator.py +37 -4
  34. ara_cli/llm_utils.py +58 -0
  35. ara_cli/prompt_chat.py +20 -4
  36. ara_cli/prompt_extractor.py +47 -32
  37. ara_cli/template_loader.py +2 -1
  38. ara_cli/template_manager.py +52 -21
  39. ara_cli/templates/global-scripts/hello_global.py +1 -0
  40. ara_cli/templates/prompt-modules/commands/add_scenarios_for_new_behaviour.feature_creation_agent.commands.md +1 -0
  41. ara_cli/templates/prompt-modules/commands/align_feature_with_implementation_changes.interview_agent.commands.md +1 -0
  42. ara_cli/templates/prompt-modules/commands/analyze_codebase_and_plan_tasks.interview_agent.commands.md +1 -0
  43. ara_cli/templates/prompt-modules/commands/choose_best_parent_artefact.interview_agent.commands.md +1 -0
  44. ara_cli/templates/prompt-modules/commands/create_tasks_from_artefact_content.interview_agent.commands.md +1 -0
  45. ara_cli/templates/prompt-modules/commands/create_tests_for_uncovered_modules.test_generation_agent.commands.md +1 -0
  46. ara_cli/templates/prompt-modules/commands/derive_features_from_video_description.feature_creation_agent.commands.md +1 -0
  47. ara_cli/templates/prompt-modules/commands/describe_agent_capabilities.agent.commands.md +1 -0
  48. ara_cli/templates/prompt-modules/commands/empty.commands.md +2 -12
  49. ara_cli/templates/prompt-modules/commands/execute_scoped_todos_in_task.interview_agent.commands.md +1 -0
  50. ara_cli/templates/prompt-modules/commands/explain_single_file_purpose.interview_agent.commands.md +1 -0
  51. ara_cli/templates/prompt-modules/commands/extract_file_information_bullets.interview_agent.commands.md +1 -0
  52. ara_cli/templates/prompt-modules/commands/extract_general.commands.md +12 -0
  53. ara_cli/templates/prompt-modules/commands/extract_markdown.commands.md +11 -0
  54. ara_cli/templates/prompt-modules/commands/extract_python.commands.md +13 -0
  55. ara_cli/templates/prompt-modules/commands/feature_add_or_modifiy_specified_behavior.commands.md +36 -0
  56. ara_cli/templates/prompt-modules/commands/feature_generate_initial_specified_bevahior.commands.md +53 -0
  57. ara_cli/templates/prompt-modules/commands/fix_failing_behave_step_definitions.interview_agent.commands.md +1 -0
  58. ara_cli/templates/prompt-modules/commands/fix_failing_pytest_tests.interview_agent.commands.md +1 -0
  59. ara_cli/templates/prompt-modules/commands/general_instruction_policy.commands.md +47 -0
  60. ara_cli/templates/prompt-modules/commands/generate_and_fix_pytest_tests.test_generation_agent.commands.md +1 -0
  61. ara_cli/templates/prompt-modules/commands/prompt_template_tech_stack_transformer.commands.md +95 -0
  62. ara_cli/templates/prompt-modules/commands/python_bug_fixing_code.commands.md +34 -0
  63. ara_cli/templates/prompt-modules/commands/python_generate_code.commands.md +27 -0
  64. ara_cli/templates/prompt-modules/commands/python_refactoring_code.commands.md +39 -0
  65. ara_cli/templates/prompt-modules/commands/python_step_definitions_generation_and_fixing.commands.md +40 -0
  66. ara_cli/templates/prompt-modules/commands/python_unittest_generation_and_fixing.commands.md +48 -0
  67. ara_cli/templates/prompt-modules/commands/suggest_next_story_child_tasks.interview_agent.commands.md +1 -0
  68. ara_cli/templates/prompt-modules/commands/summarize_or_transcribe_media.interview_agent.commands.md +1 -0
  69. ara_cli/templates/prompt-modules/commands/update_feature_to_match_implementation.feature_creation_agent.commands.md +1 -0
  70. ara_cli/templates/prompt-modules/commands/update_user_story_with_requirements.interview_agent.commands.md +1 -0
  71. ara_cli/version.py +1 -1
  72. {ara_cli-0.1.10.5.dist-info → ara_cli-0.1.13.3.dist-info}/METADATA +33 -1
  73. {ara_cli-0.1.10.5.dist-info → ara_cli-0.1.13.3.dist-info}/RECORD +89 -43
  74. tests/test_ara_command_action.py +31 -19
  75. tests/test_ara_config.py +177 -90
  76. tests/test_artefact_autofix.py +170 -97
  77. tests/test_artefact_autofix_integration.py +495 -0
  78. tests/test_artefact_converter.py +357 -0
  79. tests/test_artefact_extraction.py +564 -0
  80. tests/test_chat.py +162 -126
  81. tests/test_chat_givens_images.py +603 -0
  82. tests/test_chat_script_runner.py +454 -0
  83. tests/test_llm_utils.py +164 -0
  84. tests/test_prompt_chat.py +343 -0
  85. tests/test_prompt_extractor.py +683 -0
  86. tests/test_web_search.py +467 -0
  87. ara_cli/templates/prompt-modules/blueprints/complete_pytest_unittest.blueprint.md +0 -27
  88. ara_cli/templates/prompt-modules/blueprints/pytest_unittest_prompt.blueprint.md +0 -32
  89. ara_cli/templates/prompt-modules/blueprints/task_todo_list_implement_feature_BDD_way.blueprint.md +0 -30
  90. ara_cli/templates/prompt-modules/commands/artefact_classification.commands.md +0 -9
  91. ara_cli/templates/prompt-modules/commands/artefact_extension.commands.md +0 -17
  92. ara_cli/templates/prompt-modules/commands/artefact_formulation.commands.md +0 -14
  93. ara_cli/templates/prompt-modules/commands/behave_step_generation.commands.md +0 -102
  94. ara_cli/templates/prompt-modules/commands/code_generation_complex.commands.md +0 -20
  95. ara_cli/templates/prompt-modules/commands/code_generation_simple.commands.md +0 -13
  96. ara_cli/templates/prompt-modules/commands/error_fixing.commands.md +0 -20
  97. ara_cli/templates/prompt-modules/commands/feature_file_update.commands.md +0 -18
  98. ara_cli/templates/prompt-modules/commands/feature_formulation.commands.md +0 -43
  99. ara_cli/templates/prompt-modules/commands/js_code_generation_simple.commands.md +0 -13
  100. ara_cli/templates/prompt-modules/commands/refactoring.commands.md +0 -15
  101. ara_cli/templates/prompt-modules/commands/refactoring_analysis.commands.md +0 -9
  102. ara_cli/templates/prompt-modules/commands/reverse_engineer_feature_file.commands.md +0 -15
  103. ara_cli/templates/prompt-modules/commands/reverse_engineer_program_flow.commands.md +0 -19
  104. {ara_cli-0.1.10.5.dist-info → ara_cli-0.1.13.3.dist-info}/WHEEL +0 -0
  105. {ara_cli-0.1.10.5.dist-info → ara_cli-0.1.13.3.dist-info}/entry_points.txt +0 -0
  106. {ara_cli-0.1.10.5.dist-info → ara_cli-0.1.13.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,343 @@
1
+ """
2
+ Unit tests for prompt chat mode functionality
3
+
4
+ These tests cover the functionality previously tested by:
5
+ - Setup_Combined_Chat_Prompt_Mode_with_Chat_Name.feature
6
+ """
7
+
8
+ import pytest
9
+ import os
10
+ import tempfile
11
+ from unittest.mock import patch, MagicMock, mock_open
12
+
13
+
14
+ # =============================================================================
15
+ # Tests for chat file handling with custom names
16
+ # =============================================================================
17
+
18
+
19
+ class TestChatFileNaming:
20
+ """Tests for chat file naming conventions."""
21
+
22
+ def test_chat_name_without_extension_gets_suffix(self):
23
+ """Chat name without extension gets _chat.md suffix."""
24
+ with tempfile.TemporaryDirectory() as tmpdir:
25
+ from ara_cli.chat import Chat
26
+
27
+ mock_config = MagicMock()
28
+ mock_config.llm_config = [
29
+ {"provider": "openai", "model": "gpt-4", "temperature": 1.0}
30
+ ]
31
+
32
+ with patch(
33
+ "ara_cli.prompt_handler.ConfigManager.get_config",
34
+ return_value=mock_config,
35
+ ):
36
+ temp_file = os.path.join(tmpdir, "test_chat.md")
37
+ with open(temp_file, "w") as f:
38
+ f.write("# ara prompt:\n")
39
+
40
+ chat = Chat(temp_file, reset=False)
41
+
42
+ # Initialize with a name without extension
43
+ new_chat = chat.initialize_new_chat(os.path.join(tmpdir, "new_chat"))
44
+
45
+ assert new_chat.endswith("_chat.md")
46
+
47
+ def test_chat_name_with_extension_keeps_extension(self):
48
+ """Chat name with .md extension keeps it."""
49
+ with tempfile.TemporaryDirectory() as tmpdir:
50
+ from ara_cli.chat import Chat
51
+
52
+ mock_config = MagicMock()
53
+ mock_config.llm_config = [
54
+ {"provider": "openai", "model": "gpt-4", "temperature": 1.0}
55
+ ]
56
+
57
+ with patch(
58
+ "ara_cli.prompt_handler.ConfigManager.get_config",
59
+ return_value=mock_config,
60
+ ):
61
+ temp_file = os.path.join(tmpdir, "test_chat.md")
62
+ with open(temp_file, "w") as f:
63
+ f.write("# ara prompt:\n")
64
+
65
+ chat = Chat(temp_file, reset=False)
66
+ new_chat = chat.initialize_new_chat(os.path.join(tmpdir, "custom.md"))
67
+
68
+ assert new_chat.endswith("custom.md")
69
+
70
+
71
+ # =============================================================================
72
+ # Tests for existing chat handling
73
+ # =============================================================================
74
+
75
+
76
+ class TestExistingChatHandling:
77
+ """Tests for handling existing chat files."""
78
+
79
+ def test_reset_true_clears_chat_content(self):
80
+ """reset=True clears existing chat content."""
81
+ with tempfile.TemporaryDirectory() as tmpdir:
82
+ from ara_cli.chat import Chat
83
+
84
+ chat_file = os.path.join(tmpdir, "existing_chat.md")
85
+ with open(chat_file, "w") as f:
86
+ f.write("Previous chat content\n# ara prompt:\nOld prompt")
87
+
88
+ mock_config = MagicMock()
89
+ mock_config.llm_config = [
90
+ {"provider": "openai", "model": "gpt-4", "temperature": 1.0}
91
+ ]
92
+
93
+ with patch(
94
+ "ara_cli.prompt_handler.ConfigManager.get_config",
95
+ return_value=mock_config,
96
+ ):
97
+ Chat(chat_file, reset=True)
98
+
99
+ with open(chat_file, "r") as f:
100
+ content = f.read()
101
+
102
+ assert "Previous chat content" not in content
103
+ assert "# ara prompt:" in content
104
+
105
+ def test_reset_false_keeps_chat_content(self):
106
+ """reset=False keeps existing chat content."""
107
+ with tempfile.TemporaryDirectory() as tmpdir:
108
+ from ara_cli.chat import Chat
109
+
110
+ chat_file = os.path.join(tmpdir, "existing_chat.md")
111
+ original_content = "Previous chat content\n# ara prompt:\nKeep me"
112
+ with open(chat_file, "w") as f:
113
+ f.write(original_content)
114
+
115
+ mock_config = MagicMock()
116
+ mock_config.llm_config = [
117
+ {"provider": "openai", "model": "gpt-4", "temperature": 1.0}
118
+ ]
119
+
120
+ with patch(
121
+ "ara_cli.prompt_handler.ConfigManager.get_config",
122
+ return_value=mock_config,
123
+ ):
124
+ Chat(chat_file, reset=False)
125
+
126
+ with open(chat_file, "r") as f:
127
+ content = f.read()
128
+
129
+ assert "Keep me" in content
130
+
131
+ @patch("sys.stdin.readline", return_value="y\n")
132
+ def test_user_prompted_to_reset_when_reset_none(self, mock_input):
133
+ """User is prompted when reset=None and file exists."""
134
+ with tempfile.TemporaryDirectory() as tmpdir:
135
+ from ara_cli.chat import Chat
136
+
137
+ chat_file = os.path.join(tmpdir, "existing_chat.md")
138
+ with open(chat_file, "w") as f:
139
+ f.write("# ara prompt:\nOld content")
140
+
141
+ mock_config = MagicMock()
142
+ mock_config.llm_config = [
143
+ {"provider": "openai", "model": "gpt-4", "temperature": 1.0}
144
+ ]
145
+
146
+ with patch(
147
+ "ara_cli.prompt_handler.ConfigManager.get_config",
148
+ return_value=mock_config,
149
+ ):
150
+ Chat(chat_file, reset=None)
151
+
152
+ # User chose 'y' to reset, so content should be cleared
153
+ with open(chat_file, "r") as f:
154
+ content = f.read().strip()
155
+
156
+ assert content == "# ara prompt:"
157
+
158
+
159
+ # =============================================================================
160
+ # Tests for incomplete chat name resolution
161
+ # =============================================================================
162
+
163
+
164
+ class TestIncompleteChatName:
165
+ """Tests for resolving incomplete chat names."""
166
+
167
+ @patch("sys.stdin.readline", return_value="n\n")
168
+ def test_finds_existing_file_with_suffix(self, mock_input):
169
+ """Finds existing file when incomplete name provided."""
170
+ with tempfile.TemporaryDirectory() as tmpdir:
171
+ from ara_cli.chat import Chat
172
+
173
+ # Create a file with the full name
174
+ existing_file = os.path.join(tmpdir, "new_test_chat.md")
175
+ with open(existing_file, "w") as f:
176
+ f.write("# ara prompt:\n")
177
+
178
+ mock_config = MagicMock()
179
+ mock_config.llm_config = [
180
+ {"provider": "openai", "model": "gpt-4", "temperature": 1.0}
181
+ ]
182
+
183
+ with patch(
184
+ "ara_cli.prompt_handler.ConfigManager.get_config",
185
+ return_value=mock_config,
186
+ ):
187
+ chat = Chat(existing_file, reset=False)
188
+
189
+ # The setup_chat method should find the existing file
190
+ result = chat.setup_chat(os.path.join(tmpdir, "new_test"))
191
+
192
+ assert os.path.exists(result)
193
+
194
+
195
+ # =============================================================================
196
+ # Tests for default chat content
197
+ # =============================================================================
198
+
199
+
200
+ class TestDefaultChatContent:
201
+ """Tests for default chat content creation."""
202
+
203
+ def test_new_chat_has_default_prompt_header(self):
204
+ """New chat file contains default prompt header."""
205
+ with tempfile.TemporaryDirectory() as tmpdir:
206
+ from ara_cli.chat import Chat
207
+
208
+ chat_file = os.path.join(tmpdir, "new_chat.md")
209
+
210
+ mock_config = MagicMock()
211
+ mock_config.llm_config = [
212
+ {"provider": "openai", "model": "gpt-4", "temperature": 1.0}
213
+ ]
214
+
215
+ with patch(
216
+ "ara_cli.prompt_handler.ConfigManager.get_config",
217
+ return_value=mock_config,
218
+ ):
219
+ Chat(chat_file, reset=False)
220
+
221
+ with open(chat_file, "r") as f:
222
+ content = f.read()
223
+
224
+ assert "# ara prompt:" in content
225
+
226
+
227
+ # =============================================================================
228
+ # Tests for prompt config file handling
229
+ # =============================================================================
230
+
231
+
232
+ class TestPromptConfigFiles:
233
+ """Tests for prompt config file creation and handling."""
234
+
235
+ @patch("ara_cli.update_config_prompt.update_config_prompt_files")
236
+ def test_config_files_created_when_missing(self, mock_update):
237
+ """Prompt config files are created when missing."""
238
+ # This test verifies the behavior is available
239
+ # The actual creation happens in update_config_prompt module
240
+ assert callable(mock_update)
241
+
242
+
243
+ # =============================================================================
244
+ # Tests for chat session lifecycle
245
+ # =============================================================================
246
+
247
+
248
+ class TestChatSessionLifecycle:
249
+ """Tests for chat session start and stop."""
250
+
251
+ def test_chat_has_quit_alias(self):
252
+ """Chat instance has 'q' alias for quit."""
253
+ with tempfile.TemporaryDirectory() as tmpdir:
254
+ from ara_cli.chat import Chat
255
+
256
+ chat_file = os.path.join(tmpdir, "test_chat.md")
257
+
258
+ mock_config = MagicMock()
259
+ mock_config.llm_config = [
260
+ {"provider": "openai", "model": "gpt-4", "temperature": 1.0}
261
+ ]
262
+
263
+ with patch(
264
+ "ara_cli.prompt_handler.ConfigManager.get_config",
265
+ return_value=mock_config,
266
+ ):
267
+ chat = Chat(chat_file, reset=False)
268
+
269
+ # Check for 'q' alias which maps to QUIT
270
+ assert "q" in chat.aliases
271
+
272
+ def test_chat_has_help_alias(self):
273
+ """Chat instance has 'h' alias for help."""
274
+ with tempfile.TemporaryDirectory() as tmpdir:
275
+ from ara_cli.chat import Chat
276
+
277
+ chat_file = os.path.join(tmpdir, "test_chat.md")
278
+
279
+ mock_config = MagicMock()
280
+ mock_config.llm_config = [
281
+ {"provider": "openai", "model": "gpt-4", "temperature": 1.0}
282
+ ]
283
+
284
+ with patch(
285
+ "ara_cli.prompt_handler.ConfigManager.get_config",
286
+ return_value=mock_config,
287
+ ):
288
+ chat = Chat(chat_file, reset=False)
289
+
290
+ # Check for 'h' alias which maps to HELP
291
+ assert "h" in chat.aliases
292
+
293
+ def test_quit_alias_works(self):
294
+ """'q' alias works for QUIT command."""
295
+ with tempfile.TemporaryDirectory() as tmpdir:
296
+ from ara_cli.chat import Chat
297
+
298
+ chat_file = os.path.join(tmpdir, "test_chat.md")
299
+
300
+ mock_config = MagicMock()
301
+ mock_config.llm_config = [
302
+ {"provider": "openai", "model": "gpt-4", "temperature": 1.0}
303
+ ]
304
+
305
+ with patch(
306
+ "ara_cli.prompt_handler.ConfigManager.get_config",
307
+ return_value=mock_config,
308
+ ):
309
+ chat = Chat(chat_file, reset=False)
310
+
311
+ assert "q" in chat.aliases
312
+
313
+
314
+ # =============================================================================
315
+ # Tests for artefact-based prompt chat
316
+ # =============================================================================
317
+
318
+
319
+ class TestArtefactPromptChat:
320
+ """Tests for prompt chat mode with artefacts."""
321
+
322
+ @patch("ara_cli.prompt_handler.ConfigManager.get_config")
323
+ def test_chat_can_be_initialized_for_artefact(self, mock_config):
324
+ """Chat can be initialized for an artefact."""
325
+ with tempfile.TemporaryDirectory() as tmpdir:
326
+ from ara_cli.chat import Chat
327
+
328
+ mock_config.return_value = MagicMock(
329
+ llm_config=[
330
+ {"provider": "openai", "model": "gpt-4", "temperature": 1.0}
331
+ ]
332
+ )
333
+
334
+ # Simulate artefact data directory structure
335
+ artefact_data_dir = os.path.join(tmpdir, "123_test_task.data")
336
+ os.makedirs(artefact_data_dir, exist_ok=True)
337
+
338
+ chat_file = os.path.join(artefact_data_dir, "task_chat.md")
339
+
340
+ chat = Chat(chat_file, reset=False)
341
+
342
+ assert os.path.exists(chat_file)
343
+ assert chat.chat_name == chat_file