devcrew 0.1.0__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.
devcrew/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ """DevCrew — an AI software team in a pipeline: plan -> code -> test -> review."""
2
+
3
+ __version__ = "0.1.0"
devcrew/agents.py ADDED
@@ -0,0 +1,80 @@
1
+ """The four specialised agents.
2
+
3
+ Each agent gets a narrow role, goal and backstory ("role-scoped context").
4
+ This is deliberate: a focused prompt hallucinates less than one giant
5
+ prompt asking a single LLM to plan, code, test and review all at once.
6
+ """
7
+
8
+ import os
9
+
10
+ from crewai import LLM, Agent
11
+
12
+ DEFAULT_MODEL = "gpt-4o-mini"
13
+
14
+
15
+ def get_llm(model: str | None = None) -> LLM:
16
+ """One shared LLM config. Model comes from the argument, then the MODEL env var."""
17
+ return LLM(
18
+ model=model or os.getenv("MODEL", DEFAULT_MODEL),
19
+ temperature=0.3, # low temp = more deterministic, parseable output
20
+ )
21
+
22
+
23
+ def project_manager(llm: LLM) -> Agent:
24
+ return Agent(
25
+ role="Project Manager",
26
+ goal="Break the user's idea into a small, concrete development plan.",
27
+ backstory=(
28
+ "You are a pragmatic software project manager. You take vague "
29
+ "one-line ideas and turn them into 3-6 unambiguous tasks a "
30
+ "developer can implement in a single Python file. You never "
31
+ "invent features the user did not ask for."
32
+ ),
33
+ llm=llm,
34
+ verbose=True,
35
+ )
36
+
37
+
38
+ def developer(llm: LLM) -> Agent:
39
+ return Agent(
40
+ role="Python Developer",
41
+ goal="Implement the project plan as clean, working Python code.",
42
+ backstory=(
43
+ "You are a senior Python developer. You write a single, "
44
+ "self-contained, runnable Python file with functions, docstrings "
45
+ "and a __main__ demo block. You implement exactly the tasks in "
46
+ "the plan — nothing more. You only use the standard library."
47
+ ),
48
+ llm=llm,
49
+ verbose=True,
50
+ )
51
+
52
+
53
+ def qa_tester(llm: LLM) -> Agent:
54
+ return Agent(
55
+ role="QA Tester",
56
+ goal="Find bugs and untested edge cases in the developer's code.",
57
+ backstory=(
58
+ "You are a sceptical QA engineer. You read code line by line "
59
+ "looking for edge cases: empty inputs, wrong types, negative "
60
+ "numbers, duplicates. You design test cases and honestly mark "
61
+ "which ones the current code would fail."
62
+ ),
63
+ llm=llm,
64
+ verbose=True,
65
+ )
66
+
67
+
68
+ def code_reviewer(llm: LLM) -> Agent:
69
+ return Agent(
70
+ role="Code Reviewer",
71
+ goal="Judge the code on readability and correctness, using the QA report.",
72
+ backstory=(
73
+ "You are a strict but fair code reviewer. You consider both the "
74
+ "code and the QA report, score readability and correctness out "
75
+ "of 10, and give a final verdict: approved or changes_requested. "
76
+ "You point at specific functions, never vague advice."
77
+ ),
78
+ llm=llm,
79
+ verbose=True,
80
+ )
devcrew/cli.py ADDED
@@ -0,0 +1,71 @@
1
+ """Command-line entry point: `devcrew "your project idea"`."""
2
+
3
+ import argparse
4
+ import os
5
+ import sys
6
+
7
+ from dotenv import load_dotenv
8
+
9
+ from . import __version__
10
+ from .agents import DEFAULT_MODEL
11
+
12
+ OUTPUT_FILES = (
13
+ ("01_plan.json", "Project Manager's plan"),
14
+ ("02_code.py", "Developer's code"),
15
+ ("03_test_report.json", "QA Tester's report"),
16
+ ("04_review.json", "Code Reviewer's verdict"),
17
+ )
18
+
19
+
20
+ def build_parser() -> argparse.ArgumentParser:
21
+ parser = argparse.ArgumentParser(
22
+ prog="devcrew",
23
+ description="Run an AI software team (plan -> code -> test -> review) on a one-line idea.",
24
+ )
25
+ parser.add_argument("idea", help='what to build, e.g. "a CLI expense tracker"')
26
+ parser.add_argument(
27
+ "-o",
28
+ "--output-dir",
29
+ default="output",
30
+ help="folder for results, relative to the current directory (default: output)",
31
+ )
32
+ parser.add_argument(
33
+ "-m", "--model", default=None, help=f"LLM to use (default: $MODEL or {DEFAULT_MODEL})"
34
+ )
35
+ parser.add_argument("--version", action="version", version=f"%(prog)s {__version__}")
36
+ return parser
37
+
38
+
39
+ def main(argv: list[str] | None = None) -> int:
40
+ parser = build_parser()
41
+ args = parser.parse_args(argv)
42
+
43
+ # CrewAI only writes task output to relative paths: it rejects ".." and "~",
44
+ # and silently drops the leading "/" of an absolute path.
45
+ if (
46
+ os.path.isabs(args.output_dir)
47
+ or ".." in args.output_dir.split(os.sep)
48
+ or (args.output_dir.startswith(("~", "$")))
49
+ ):
50
+ parser.error("--output-dir must be a relative path inside the current directory")
51
+
52
+ load_dotenv()
53
+
54
+ if not os.getenv("OPENAI_API_KEY"):
55
+ sys.exit("Missing OPENAI_API_KEY. Copy .env.example to .env and add your key.")
56
+
57
+ os.makedirs(args.output_dir, exist_ok=True)
58
+
59
+ # Imported here so `--help` and `--version` stay fast.
60
+ from .crew import run
61
+
62
+ print(f"\n🚀 DevCrew starting on: {args.idea}\n")
63
+ run(args.idea, output_dir=args.output_dir, model=args.model)
64
+ print(f"\n✅ Done. Check the {args.output_dir}/ folder:")
65
+ for name, what in OUTPUT_FILES:
66
+ print(f" {name:<20}— {what}")
67
+ return 0
68
+
69
+
70
+ if __name__ == "__main__":
71
+ sys.exit(main())
devcrew/crew.py ADDED
@@ -0,0 +1,33 @@
1
+ """Assemble the crew and run the pipeline end-to-end."""
2
+
3
+ from crewai import Crew, Process
4
+
5
+ from . import agents, tasks
6
+
7
+
8
+ def build_crew(output_dir: str = "output", model: str | None = None) -> Crew:
9
+ llm = agents.get_llm(model)
10
+
11
+ pm = agents.project_manager(llm)
12
+ dev = agents.developer(llm)
13
+ qa = agents.qa_tester(llm)
14
+ reviewer = agents.code_reviewer(llm)
15
+
16
+ t_plan = tasks.plan_task(pm, output_dir=output_dir)
17
+ t_code = tasks.code_task(dev, plan=t_plan, output_dir=output_dir)
18
+ t_test = tasks.test_task(qa, code=t_code, output_dir=output_dir)
19
+ t_review = tasks.review_task(reviewer, code=t_code, tests=t_test, output_dir=output_dir)
20
+
21
+ return Crew(
22
+ agents=[pm, dev, qa, reviewer],
23
+ tasks=[t_plan, t_code, t_test, t_review],
24
+ process=Process.sequential, # strict order: plan -> code -> test -> review
25
+ verbose=True,
26
+ )
27
+
28
+
29
+ def run(idea: str, output_dir: str = "output", model: str | None = None) -> str:
30
+ """Run the full pipeline for a one-line project idea."""
31
+ crew = build_crew(output_dir=output_dir, model=model)
32
+ result = crew.kickoff(inputs={"idea": idea})
33
+ return str(result)
devcrew/schemas.py ADDED
@@ -0,0 +1,66 @@
1
+ """Pydantic schemas that force each agent to return structured JSON.
2
+
3
+ Why this matters: LLM agents tend to ramble. By binding each task to a
4
+ schema, the output of one agent becomes machine-parseable input for the
5
+ next agent in the pipeline — no regex, no guessing.
6
+ """
7
+
8
+ from typing import Literal
9
+
10
+ from pydantic import BaseModel, Field
11
+
12
+ # ---------- Project Manager output ----------
13
+
14
+
15
+ class PlanItem(BaseModel):
16
+ id: int = Field(description="Sequential task id, starting at 1")
17
+ title: str = Field(description="Short task title")
18
+ description: str = Field(description="What exactly needs to be built")
19
+
20
+
21
+ class ProjectPlan(BaseModel):
22
+ project_name: str
23
+ summary: str = Field(description="One-paragraph summary of the project")
24
+ tasks: list[PlanItem] = Field(description="3-6 concrete development tasks")
25
+
26
+
27
+ # ---------- QA Tester output ----------
28
+
29
+
30
+ class TestCase(BaseModel):
31
+ name: str
32
+ scenario: str = Field(description="What is being tested")
33
+ expected: str = Field(description="Expected behaviour")
34
+ verdict: Literal["pass", "fail"] = Field(
35
+ description="'pass' or 'fail' based on reading the code"
36
+ )
37
+ notes: str = Field(default="", description="Why it passes/fails")
38
+
39
+
40
+ class TestReport(BaseModel):
41
+ total_cases: int
42
+ passed: int
43
+ failed: int
44
+ test_cases: list[TestCase]
45
+ bugs_found: list[str] = Field(description="Concrete bugs or edge cases the code misses")
46
+
47
+
48
+ # ---------- Code Reviewer output ----------
49
+
50
+
51
+ class ReviewComment(BaseModel):
52
+ severity: Literal["critical", "major", "minor"] = Field(
53
+ description="'critical', 'major' or 'minor'"
54
+ )
55
+ location: str = Field(description="Function or section of code")
56
+ comment: str
57
+
58
+
59
+ class ReviewReport(BaseModel):
60
+ verdict: Literal["approved", "changes_requested"] = Field(
61
+ description="'approved' or 'changes_requested'"
62
+ )
63
+ readability_score: int = Field(ge=1, le=10, description="1-10")
64
+ correctness_score: int = Field(ge=1, le=10, description="1-10")
65
+ comments: list[ReviewComment]
66
+ summary: str = Field(description="Final review summary in 2-3 sentences")
devcrew/tasks.py ADDED
@@ -0,0 +1,74 @@
1
+ """The pipeline: Plan -> Code -> Test -> Review.
2
+
3
+ The hand-off between agents happens through CrewAI's `context` parameter:
4
+ each task receives the *output* of the previous task(s) as input. That is
5
+ the "orchestrated hand-off" — no agent sees the whole conversation, only
6
+ what it needs.
7
+ """
8
+
9
+ import os
10
+
11
+ from crewai import Agent, Task
12
+
13
+ from .schemas import ProjectPlan, ReviewReport, TestReport
14
+
15
+
16
+ def plan_task(agent: Agent, output_dir: str = "output") -> Task:
17
+ return Task(
18
+ description=(
19
+ "The user wants to build: '{idea}'.\n"
20
+ "Create a development plan with 3-6 concrete tasks. The whole "
21
+ "project must fit in ONE Python file using only the standard "
22
+ "library."
23
+ ),
24
+ expected_output="A structured project plan as JSON.",
25
+ agent=agent,
26
+ output_json=ProjectPlan,
27
+ output_file=os.path.join(output_dir, "01_plan.json"),
28
+ )
29
+
30
+
31
+ def code_task(agent: Agent, plan: Task, output_dir: str = "output") -> Task:
32
+ return Task(
33
+ description=(
34
+ "Implement the project plan you received as ONE self-contained "
35
+ "Python file. Include docstrings and a small demo under "
36
+ "`if __name__ == '__main__':`. Output ONLY the raw Python code, "
37
+ "no markdown fences, no explanations."
38
+ ),
39
+ expected_output="A single runnable Python file.",
40
+ agent=agent,
41
+ context=[plan], # hand-off: developer only sees the plan
42
+ output_file=os.path.join(output_dir, "02_code.py"),
43
+ )
44
+
45
+
46
+ def test_task(agent: Agent, code: Task, output_dir: str = "output") -> Task:
47
+ return Task(
48
+ description=(
49
+ "Read the Python code you received and design 5-8 test cases "
50
+ "covering normal use and edge cases (empty input, invalid input, "
51
+ "duplicates, boundaries). For each, decide honestly whether the "
52
+ "CURRENT code would pass or fail, and list concrete bugs."
53
+ ),
54
+ expected_output="A structured QA test report as JSON.",
55
+ agent=agent,
56
+ context=[code], # hand-off: tester only sees the code
57
+ output_json=TestReport,
58
+ output_file=os.path.join(output_dir, "03_test_report.json"),
59
+ )
60
+
61
+
62
+ def review_task(agent: Agent, code: Task, tests: Task, output_dir: str = "output") -> Task:
63
+ return Task(
64
+ description=(
65
+ "Review the code, taking the QA report into account. Score "
66
+ "readability and correctness out of 10, leave specific comments "
67
+ "with severity levels, and give a final verdict."
68
+ ),
69
+ expected_output="A structured code review as JSON.",
70
+ agent=agent,
71
+ context=[code, tests], # hand-off: reviewer sees code + QA report
72
+ output_json=ReviewReport,
73
+ output_file=os.path.join(output_dir, "04_review.json"),
74
+ )
@@ -0,0 +1,143 @@
1
+ Metadata-Version: 2.5
2
+ Name: devcrew
3
+ Version: 0.1.0
4
+ Summary: An AI software team in a pipeline: four agents plan, code, test and review a project from a one-line idea.
5
+ Project-URL: Homepage, https://github.com/agrvasu05/DevCrew
6
+ Project-URL: Issues, https://github.com/agrvasu05/DevCrew/issues
7
+ Project-URL: Changelog, https://github.com/agrvasu05/DevCrew/blob/main/CHANGELOG.md
8
+ Author: Vasu Agrawal
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: agents,ai,code-generation,code-review,crewai,llm,multi-agent
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
21
+ Classifier: Topic :: Software Development :: Code Generators
22
+ Requires-Python: <3.14,>=3.10
23
+ Requires-Dist: crewai>=1.0.0
24
+ Requires-Dist: python-dotenv>=1.0.0
25
+ Provides-Extra: dev
26
+ Requires-Dist: pytest>=8; extra == 'dev'
27
+ Requires-Dist: ruff>=0.6; extra == 'dev'
28
+ Description-Content-Type: text/markdown
29
+
30
+ # DevCrew — Multi-Agent AI Orchestration System
31
+
32
+ [![CI](https://github.com/agrvasu05/DevCrew/actions/workflows/ci.yml/badge.svg)](https://github.com/agrvasu05/DevCrew/actions/workflows/ci.yml)
33
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
34
+ ![Python 3.10–3.13](https://img.shields.io/badge/python-3.10%E2%80%933.13-blue.svg)
35
+
36
+ An AI software team in a pipeline. You give it a one-line project idea; four specialised LLM agents plan it, code it, test it, and review it — each handing structured output to the next.
37
+
38
+ Built with **CrewAI** on the OpenAI API.
39
+
40
+ ## How it works
41
+
42
+ ```
43
+ idea ─→ ┌─────────────────┐ ┌─────────────────┐
44
+ │ Project Manager │ ───→ │ Developer │
45
+ │ plan.json │ │ code.py │
46
+ └─────────────────┘ └───────┬─────────┘
47
+ │
48
+ ▼
49
+ ┌─────────────────┐ ┌─────────────────┐
50
+ │ Code Reviewer │ ←─── │ QA Tester │
51
+ │ review.json │ │ test_report.json│
52
+ └─────────────────┘ └─────────────────┘
53
+ (sees code + QA report)
54
+ ```
55
+
56
+ 1. **Project Manager** turns the idea into a 3–6 task plan (JSON).
57
+ 2. **Developer** implements the plan as one runnable Python file.
58
+ 3. **QA Tester** designs edge-case tests against the code and honestly marks which would fail (JSON).
59
+ 4. **Code Reviewer** reads the code *and* the QA report, scores it, and gives a verdict (JSON).
60
+
61
+ ## Design decisions
62
+
63
+ - **Role-scoped context, not one giant prompt.** Each agent only receives what it needs (the developer sees the plan, not the user's raw message). Narrow prompts hallucinate less and stay on task.
64
+ - **Structured JSON outputs via Pydantic.** Every non-code output is bound to a schema (`devcrew/schemas.py`), so one agent's output is machine-parseable input for the next — no regex, no parsing failures.
65
+ - **Sequential process.** A software pipeline has a natural order; sequential orchestration keeps the run deterministic and debuggable. Every stage is written to `output/` so you can inspect exactly where a run went wrong.
66
+ - **Adversarial QA.** The tester is prompted to be sceptical and mark failures honestly, and the reviewer sees the QA report — so the review verdict is grounded in found bugs, not vibes.
67
+
68
+ ## Run it
69
+
70
+ ```bash
71
+ git clone https://github.com/agrvasu05/DevCrew && cd DevCrew
72
+ pip install -e .
73
+ cp .env.example .env # add your OPENAI_API_KEY
74
+
75
+ devcrew "Build a CLI expense tracker with categories and monthly totals"
76
+ ```
77
+
78
+ `python main.py "..."` still works if you'd rather not install the package.
79
+
80
+ | Option | Default | What it does |
81
+ |---|---|---|
82
+ | `-o`, `--output-dir` | `output` | Where results go (a path relative to the current directory) |
83
+ | `-m`, `--model` | `$MODEL` or `gpt-4o-mini` | Which LLM the agents use |
84
+ | `--version` | | Print the version |
85
+
86
+ Outputs land in the output directory:
87
+
88
+ | File | Agent | Contents |
89
+ |---|---|---|
90
+ | `01_plan.json` | Project Manager | Task breakdown |
91
+ | `02_code.py` | Developer | Runnable Python file |
92
+ | `03_test_report.json` | QA Tester | Test cases + bugs found |
93
+ | `04_review.json` | Code Reviewer | Scores, comments, verdict |
94
+
95
+ A full example run is committed in [`sample_output/`](sample_output/).
96
+
97
+ > DevCrew never runs the code it generates. Read `02_code.py` before you execute it.
98
+
99
+ ## Development
100
+
101
+ ```bash
102
+ pip install -e ".[dev]"
103
+ pytest # no API key or network needed
104
+ ruff check .
105
+ ```
106
+
107
+ The tests check how the pipeline is wired (which agent sees which output) and validate
108
+ `sample_output/` against the schemas, without calling an LLM. CI runs them on Python 3.10–3.13.
109
+
110
+ ## Roadmap
111
+
112
+ - Feed the reviewer's verdict back to the Developer for a fix-up round when changes are requested
113
+ - Actually run the generated code against the QA test cases in a sandbox
114
+ - Support projects that span more than one file
115
+ - A small eval set of project ideas to catch prompt regressions in CI
116
+
117
+ Ideas and PRs are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md).
118
+
119
+ ## Stack
120
+
121
+ Python · CrewAI · OpenAI API · Pydantic
122
+
123
+ ## Project structure
124
+
125
+ ```
126
+ devcrew/
127
+ ├── main.py # thin wrapper around devcrew.cli
128
+ ├── devcrew/
129
+ │ ├── cli.py # `devcrew` command-line entry point
130
+ │ ├── agents.py # 4 agents with role-scoped prompts
131
+ │ ├── tasks.py # pipeline tasks + context hand-offs
132
+ │ ├── schemas.py # Pydantic schemas for structured JSON
133
+ │ └── crew.py # crew assembly (sequential process)
134
+ ├── sample_output/ # committed example run
135
+ ├── tests/ # offline unit tests
136
+ ├── pyproject.toml
137
+ ├── requirements.txt
138
+ └── .env.example
139
+ ```
140
+
141
+ ## License
142
+
143
+ [MIT](LICENSE) © Vasu Agrawal
@@ -0,0 +1,11 @@
1
+ devcrew/__init__.py,sha256=b5HYA_4lnPE-WrarBBTVBvw-VRH8lQ3U36JyUA87zM4,108
2
+ devcrew/agents.py,sha256=EHXo2Lxdnv9DgLZrUpnE1-DerJeiRqrcUhuTnm16_3o,2743
3
+ devcrew/cli.py,sha256=AuMCy-UEkMxu80XM5WD06hM3clpZovnOw5GH-ubRPDY,2234
4
+ devcrew/crew.py,sha256=jb3mGyne-7yC0ZWeNRwTtt_741tND4QRAl-IjV_P5DY,1157
5
+ devcrew/schemas.py,sha256=_XvI_wEi0vO6CJoeD24Lg9s8kxO1nLu-AiRAtSrQ8b4,2121
6
+ devcrew/tasks.py,sha256=dJQh1C-P9ZtDdEGM3dnDEsfqEaBLiVMgcqe7yl0BcGE,2842
7
+ devcrew-0.1.0.dist-info/METADATA,sha256=xbjFeofvbbxYeOh906hggmbDofhGZqOKDdTx2GDpMys,6429
8
+ devcrew-0.1.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
9
+ devcrew-0.1.0.dist-info/entry_points.txt,sha256=ViCXHUuWsN5mGfaDO7sRvYnD_nOH3faEAHNlg-k8-ko,45
10
+ devcrew-0.1.0.dist-info/licenses/LICENSE,sha256=fc3Um9yZj96IwCbnwNCmkWs6ZvlGDqz3YUfacpaxios,1069
11
+ devcrew-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.32.4
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ devcrew = devcrew.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Vasu Agrawal
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.