bob-dev 0.2.2__tar.gz → 0.2.3__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 (31) hide show
  1. {bob_dev-0.2.2/src/bob_dev.egg-info → bob_dev-0.2.3}/PKG-INFO +1 -1
  2. {bob_dev-0.2.2 → bob_dev-0.2.3}/pyproject.toml +1 -1
  3. {bob_dev-0.2.2 → bob_dev-0.2.3}/src/bob_dev/cli.py +11 -15
  4. bob_dev-0.2.3/src/bob_dev/services/claude.py +54 -0
  5. {bob_dev-0.2.2 → bob_dev-0.2.3}/src/bob_dev/services/terminal.py +1 -0
  6. {bob_dev-0.2.2 → bob_dev-0.2.3/src/bob_dev.egg-info}/PKG-INFO +1 -1
  7. bob_dev-0.2.2/src/bob_dev/services/claude.py +0 -27
  8. {bob_dev-0.2.2 → bob_dev-0.2.3}/LICENSE +0 -0
  9. {bob_dev-0.2.2 → bob_dev-0.2.3}/README.md +0 -0
  10. {bob_dev-0.2.2 → bob_dev-0.2.3}/setup.cfg +0 -0
  11. {bob_dev-0.2.2 → bob_dev-0.2.3}/src/__init__.py +0 -0
  12. {bob_dev-0.2.2 → bob_dev-0.2.3}/src/bob_dev/__init__.py +0 -0
  13. {bob_dev-0.2.2 → bob_dev-0.2.3}/src/bob_dev/constants/__init__.py +0 -0
  14. {bob_dev-0.2.2 → bob_dev-0.2.3}/src/bob_dev/constants/frameworks.py +0 -0
  15. {bob_dev-0.2.2 → bob_dev-0.2.3}/src/bob_dev/services/__init__.py +0 -0
  16. {bob_dev-0.2.2 → bob_dev-0.2.3}/src/bob_dev/services/config.py +0 -0
  17. {bob_dev-0.2.2 → bob_dev-0.2.3}/src/bob_dev/services/gitlab.py +0 -0
  18. {bob_dev-0.2.2 → bob_dev-0.2.3}/src/bob_dev/services/jira.py +0 -0
  19. {bob_dev-0.2.2 → bob_dev-0.2.3}/src/bob_dev/services/llm.py +0 -0
  20. {bob_dev-0.2.2 → bob_dev-0.2.3}/src/bob_dev/services/project.py +0 -0
  21. {bob_dev-0.2.2 → bob_dev-0.2.3}/src/bob_dev.egg-info/SOURCES.txt +0 -0
  22. {bob_dev-0.2.2 → bob_dev-0.2.3}/src/bob_dev.egg-info/dependency_links.txt +0 -0
  23. {bob_dev-0.2.2 → bob_dev-0.2.3}/src/bob_dev.egg-info/entry_points.txt +0 -0
  24. {bob_dev-0.2.2 → bob_dev-0.2.3}/src/bob_dev.egg-info/requires.txt +0 -0
  25. {bob_dev-0.2.2 → bob_dev-0.2.3}/src/bob_dev.egg-info/top_level.txt +0 -0
  26. {bob_dev-0.2.2 → bob_dev-0.2.3}/tests/test_cli.py +0 -0
  27. {bob_dev-0.2.2 → bob_dev-0.2.3}/tests/test_config.py +0 -0
  28. {bob_dev-0.2.2 → bob_dev-0.2.3}/tests/test_jira.py +0 -0
  29. {bob_dev-0.2.2 → bob_dev-0.2.3}/tests/test_llm.py +0 -0
  30. {bob_dev-0.2.2 → bob_dev-0.2.3}/tests/test_project.py +0 -0
  31. {bob_dev-0.2.2 → bob_dev-0.2.3}/tests/test_terminal.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bob-dev
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: An AI developer to write code for you
5
5
  Author-email: Samuel Pereira dos Santos <samuelsantosdev@gmail.com>
6
6
  Requires-Python: >=3.14
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "bob-dev"
7
- version = "0.2.2"
7
+ version = "0.2.3"
8
8
  description = "An AI developer to write code for you"
9
9
  readme = "README.md"
10
10
  authors = [{ name="Samuel Pereira dos Santos", email="samuelsantosdev@gmail.com" }]
@@ -33,6 +33,7 @@ import sys
33
33
  import argparse
34
34
  import asyncio
35
35
  from pathlib import Path
36
+ from time import sleep, time
36
37
 
37
38
  from InquirerPy import inquirer
38
39
  from dotenv import load_dotenv
@@ -60,8 +61,8 @@ from .services.config import check_configuration, update_env_file
60
61
  # ---------------------------------------------------------------------------
61
62
 
62
63
  SCRIPT_DIR = Path(__file__).resolve().parent
63
- load_dotenv(SCRIPT_DIR / ".env")
64
64
  ENV_PATH = Path.home() / ".bob_dev" / ".env"
65
+ load_dotenv(ENV_PATH) # Load .env if it exists, but don't require it
65
66
 
66
67
  OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY", "")
67
68
  GROK_API_KEY = os.environ.get("GROK_API_KEY", "")
@@ -221,39 +222,34 @@ def main() -> None:
221
222
  ))
222
223
 
223
224
  print(f"\n{BOLD}── Prompt Analysis {'─' * 50}{RESET}")
224
- print(analysis)
225
+ for line in analysis.splitlines():
226
+ print(line)
227
+ sleep(0.02) # Simulate a "typing" effect for better readability
225
228
  print("─" * 68 + "\n")
226
229
 
227
230
  # ── Confirm before handing off to Claude Code ────────────────────────────
228
- answer = input("Proceed and send prompt to Claude Code? [y/N] ").strip().lower()
231
+ answer = input("Proceed to prompt preview? [y/N] ").strip().lower()
229
232
  if answer != "y":
230
233
  prompt_file = SCRIPT_DIR / f"claude_prompt-{task_id}.md"
231
234
  prompt_file.write_text(prompt_md, encoding="utf-8")
232
235
  print_info(f"Aborted. Prompt saved to {prompt_file}")
233
236
  sys.exit(0)
234
237
 
235
- print_info("Prompt preview:")
238
+ print_info("\n\n\nPrompt preview:")
236
239
  print("-" * 68)
237
- print(prompt_md)
240
+ for line in prompt_md.splitlines():
241
+ print(line)
242
+ sleep(0.02) # Simulate a "typing" effect for better readability
238
243
  print("-" * 68)
239
244
  answer = input("\nAre you sure? This will run the Claude Code CLI with the generated prompt. [y/N] ").strip().lower()
240
245
  if answer != "y":
241
246
  print_info("Aborted by user.")
242
247
  sys.exit(0)
243
-
244
- answer = input("Do you want select a agent to do this development? [y/N] ").strip().upper()
245
- agent_claude = ""
246
- if answer == "Y":
247
- agents_of_claude = read_agents_from_claude(CLAUDE_CODE_CMD)
248
- agent_claude = inquirer.select(
249
- message="Select the agent to do the development:",
250
- choices=agents_of_claude,
251
- ).execute()
252
248
 
253
249
  # ── Step 4 – Pass prompt to Claude Code ──────────────────────────────────
254
250
  print_step("[4/4]", "Passing prompt to Claude Code …")
255
251
  print()
256
- asyncio.run(_pass_to_claude_code(prompt_md, task_id, agent_claude))
252
+ asyncio.run(_pass_to_claude_code(prompt_md, task_id, None))
257
253
 
258
254
 
259
255
  # ---------------------------------------------------------------------------
@@ -0,0 +1,54 @@
1
+ """claude.py
2
+
3
+ Claude Code utilities for bob_dev:
4
+ - List available agents from the Claude Code CLI.
5
+ - Run Claude Code commands and handle errors.
6
+ """
7
+
8
+ import subprocess
9
+ import json
10
+
11
+ from ..services.terminal import print_error
12
+
13
+
14
+ def read_agents_from_claude(claude_cmd: str) -> list[str]:
15
+ """Run *claude_cmd* with --list-agents and parse the output into a list."""
16
+ try:
17
+ # list the installed agents by running the CLI command. This is more reliable than
18
+ # trying to read the plugin directory directly, which may have different permissions or structure.
19
+ # The expected output is a list of agent names, one per line. We strip whitespace and ignore empty lines.
20
+
21
+ result_marketplace = subprocess.run(
22
+ ["ls", "~/.claude/plugins/marketplaces/claude-plugins-official/plugins"],
23
+ stdout=subprocess.PIPE,
24
+ stderr=subprocess.PIPE,
25
+ text=True,
26
+ check=True,
27
+ )
28
+ result_agents = subprocess.run(
29
+ [claude_cmd, "agents", "--json"],
30
+ stdout=subprocess.PIPE,
31
+ stderr=subprocess.PIPE,
32
+ text=True,
33
+ check=True,
34
+ )
35
+
36
+ agents_data = json.loads(result_agents.stdout)
37
+ # We want to extract the "name" field from each agent,
38
+ # but only if it has one (background agents may not have a name).
39
+ # We also want to include the marketplace plugins as agents,
40
+ # since they can be invoked by name as well.
41
+ # The marketplace plugins are just the filenames in the marketplace directory.
42
+ result_agents = [str(agent.get("name")).strip() for agent in agents_data if agent.get("name")]
43
+ agents_marketplace = [line.strip() for line in result_marketplace.stdout.splitlines() if line.strip()]
44
+ # Combine agents from both sources, ensuring uniqueness while preserving order.
45
+ seen = set()
46
+ combined_agents = []
47
+ for agent in result_agents + agents_marketplace:
48
+ if agent not in seen:
49
+ seen.add(agent)
50
+ combined_agents.append(agent)
51
+ return combined_agents
52
+ except Exception as exc:
53
+ print_error(f"Failed to list agents from Claude Code CLI: {exc}")
54
+ return []
@@ -11,6 +11,7 @@ from __future__ import annotations
11
11
 
12
12
  import asyncio
13
13
  import time
14
+ import sys
14
15
  from pathlib import Path
15
16
 
16
17
  # ---------------------------------------------------------------------------
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bob-dev
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: An AI developer to write code for you
5
5
  Author-email: Samuel Pereira dos Santos <samuelsantosdev@gmail.com>
6
6
  Requires-Python: >=3.14
@@ -1,27 +0,0 @@
1
- """claude.py
2
-
3
- Claude Code utilities for bob_dev:
4
- - List available agents from the Claude Code CLI.
5
- - Run Claude Code commands and handle errors.
6
- """
7
-
8
- import subprocess
9
-
10
- from ..services.terminal import print_error
11
-
12
-
13
- def read_agents_from_claude(claude_cmd: str) -> list[str]:
14
- """Run *claude_cmd* with --list-agents and parse the output into a list."""
15
- try:
16
- result = subprocess.run(
17
- [claude_cmd, "--list-agents"],
18
- stdout=subprocess.PIPE,
19
- stderr=subprocess.PIPE,
20
- text=True,
21
- check=True,
22
- )
23
- agents = [line.strip() for line in result.stdout.splitlines() if line.strip()]
24
- return agents
25
- except Exception as exc:
26
- print_error(f"Failed to list agents from Claude Code CLI: {exc}")
27
- return []
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes