diff --git a/fabricate/cli.py b/fabricate/cli.py index 939cc41..4391383 100644 --- a/fabricate/cli.py +++ b/fabricate/cli.py @@ -34,12 +34,12 @@ def cli(): @cli.command() @click.option( - "--anthropic-key", "-a", - envvar="FABRICATE_ANTHROPIC_API_KEY", - help="Anthropic API key (or set FABRICATE_ANTHROPIC_API_KEY)" + "--gemini-key", "-g", + envvar="FABRICATE_GEMINI_API_KEY", + help="Google Gemini API key (or set FABRICATE_GEMINI_API_KEY)" ) @click.option( - "--github-token", "-g", + "--github-token", "-t", envvar="FABRICATE_GITHUB_TOKEN", help="GitHub personal access token (or set FABRICATE_GITHUB_TOKEN)" ) @@ -99,7 +99,7 @@ def cli(): help="Show what would be created without actually creating" ) @click.option( - "--tech", "-t", + "--tech", multiple=True, help="Technologies to include (e.g., tailwind, prisma, redis, docker)" ) @@ -109,7 +109,7 @@ def cli(): help="Project categories to build (e.g., cli_tool, web_app, saas, dashboard, api)" ) def generate( - anthropic_key: Optional[str], + gemini_key: Optional[str], github_token: Optional[str], languages: tuple, repos: Optional[int], @@ -139,16 +139,16 @@ def generate( fabricate generate -l python -l javascript -l go -r 10 -d 730 # Specify technologies and project types - fabricate generate -l nextjs -t tailwind -t prisma -c saas -c dashboard + fabricate generate -l nextjs --tech tailwind --tech prisma -c saas -c dashboard # Local only (no GitHub push) fabricate generate --no-push -r 2 """ # Validate required credentials - if not anthropic_key: - console.print("[red]Error: Anthropic API key required[/red]") - console.print("Set FABRICATE_ANTHROPIC_API_KEY or use --anthropic-key") + if not gemini_key: + console.print("[red]Error: Google Gemini API key required[/red]") + console.print("Set FABRICATE_GEMINI_API_KEY or use --gemini-key") sys.exit(1) if not github_token and not no_push: @@ -196,7 +196,7 @@ def generate( # Run the fabrication try: generated = run_fabrication( - anthropic_api_key=anthropic_key, + gemini_api_key=gemini_key, github_token=github_token or "", languages=languages_list, num_repos=repos, @@ -342,4 +342,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/fabricate/config.py b/fabricate/config.py index ff65e0c..5eb0138 100644 --- a/fabricate/config.py +++ b/fabricate/config.py @@ -87,7 +87,7 @@ def generate_commit_date(self, repo_start_date: datetime, commit_index: int, tot class FabricateSettings(BaseSettings): """Environment-based settings for Fabricate.""" - anthropic_api_key: str = Field(description="Anthropic API key for code generation") + gemini_api_key: str = Field(description="Google Gemini API key for code generation") github_token: str = Field(description="GitHub personal access token") github_username: Optional[str] = Field(default=None, description="GitHub username (auto-detected if not set)") work_dir: str = Field(default="./fabricated_repos", description="Directory for temporary repo work") @@ -207,4 +207,3 @@ class Config: "dashboard", "saas", ] - diff --git a/fabricate/generator.py b/fabricate/generator.py index 3038a22..a59bc00 100644 --- a/fabricate/generator.py +++ b/fabricate/generator.py @@ -1,5 +1,5 @@ """ -Code generation using Anthropic's Claude API. +Code generation using Google's Gemini 3.1 Pro API. """ import json @@ -7,7 +7,7 @@ from typing import Optional from dataclasses import dataclass -import anthropic +import google.generativeai as genai from rich.console import Console from .config import LANGUAGE_CONFIGS, COMPLEXITY_PROFILES, PROJECT_CATEGORIES @@ -42,24 +42,27 @@ class GeneratedRepo: class CodeGenerator: - """Generates code and repository content using Claude.""" + """Generates code and repository content using Gemini 3.1 Pro.""" - def __init__(self, api_key: str, model: str = "claude-opus-4-5-20251101"): - self.client = anthropic.Anthropic(api_key=api_key) + def __init__(self, api_key: str, model: str = "gemini-3.1-pro-preview"): + genai.configure(api_key=api_key) + self.client = genai.GenerativeModel(model) self.model = model - def _call_claude(self, system: str, user: str, max_tokens: int = 4096) -> str: - """Make a call to Claude API.""" - response = self.client.messages.create( - model=self.model, - max_tokens=max_tokens, - system=system, - messages=[{"role": "user", "content": user}] + def _call_gemini(self, system: str, user: str, max_tokens: int = 4096) -> str: + """Make a call to Gemini API.""" + combined_prompt = f"{system}\n\n{user}" + response = self.client.generate_content( + combined_prompt, + generation_config=genai.types.GenerationConfig( + max_output_tokens=max_tokens, + temperature=0.7, + ) ) - return response.content[0].text + return response.text def _extract_json(self, response: str) -> dict: - """Extract JSON from Claude's response, handling various formats.""" + """Extract JSON from Gemini's response, handling various formats.""" if not response or not response.strip(): raise ValueError("Empty response") @@ -148,7 +151,7 @@ def generate_repo_concept( "main_features": ["feature1", "feature2", "feature3"] }}""" - response = self._call_claude(system, user, max_tokens=500) + response = self._call_gemini(system, user, max_tokens=500) try: return self._extract_json(response) @@ -215,7 +218,7 @@ def generate_initial_commit( - Make the code realistic and functional - Use proper formatting and indentation (use \\n for newlines, \\t for tabs)""" - response = self._call_claude(system, user, max_tokens=8000) + response = self._call_gemini(system, user, max_tokens=8000) try: data = self._extract_json(response) @@ -368,7 +371,7 @@ def generate_subsequent_commit( - Use conventional commit message format - Content should be complete and valid {language} code""" - response = self._call_claude(system, user, max_tokens=6000) + response = self._call_gemini(system, user, max_tokens=6000) try: data = self._extract_json(response) @@ -455,4 +458,3 @@ def generate_full_repo( commits=commits, topics=concept.get("topics", [language]) ) - diff --git a/fabricate/persona.py b/fabricate/persona.py index a744aa3..8a4e636 100644 --- a/fabricate/persona.py +++ b/fabricate/persona.py @@ -30,14 +30,14 @@ class PersonaFabricator: def __init__( self, - anthropic_api_key: str, + gemini_api_key: str, github_token: str, github_username: Optional[str] = None, work_dir: str = "./fabricated_repos", author_name: Optional[str] = None, author_email: Optional[str] = None ): - self.generator = CodeGenerator(anthropic_api_key) + self.generator = CodeGenerator(gemini_api_key) self.github = GitHubClient(github_token, github_username) # Get user info for author details @@ -224,7 +224,7 @@ def _print_summary(self, repos: list[GeneratedRepo], config: PersonaConfig) -> N def run_fabrication( - anthropic_api_key: str, + gemini_api_key: str, github_token: str, languages: list[str], num_repos: int, @@ -242,7 +242,7 @@ def run_fabrication( Convenience function to run a complete fabrication. Args: - anthropic_api_key: Anthropic API key for code generation + gemini_api_key: Google Gemini API key for code generation github_token: GitHub personal access token languages: List of programming languages to use num_repos: Number of repositories to create @@ -271,7 +271,7 @@ def run_fabrication( ) fabricator = PersonaFabricator( - anthropic_api_key=anthropic_api_key, + gemini_api_key=gemini_api_key, github_token=github_token, github_username=github_username, work_dir=work_dir @@ -282,4 +282,3 @@ def run_fabrication( push_to_github=push_to_github, cleanup_local=cleanup_local ) - diff --git a/requirements.txt b/requirements.txt index 0c2c5ce..a2ce427 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -anthropic>=0.39.0 +google-generativeai>=0.8.0 PyGithub>=2.1.1 gitpython>=3.1.40 click>=8.1.7 @@ -6,4 +6,3 @@ pydantic>=2.5.0 pydantic-settings>=2.1.0 rich>=13.7.0 python-dotenv>=1.0.0 -