diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..f148b4d11261d2145993363f9dfc4867d91c1613 --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# Credentials and Secrets +.env + +# Python Compiled Files +__pycache__/ +*.py[cod] + +# Virtual Environments +venv/ +.venv/ + +# System Files +.DS_Store +Thumbs.db + +# Logs +*.log + +# Editor Directories +.vscode/ +.idea/ + +*.jpg + +stitch_merchflow_ai_dashboard.zip +screen.jpg +test_image.jpg +*.zip +*.jpeg +*.png \ No newline at end of file diff --git a/.vite/deps/_metadata.json b/.vite/deps/_metadata.json new file mode 100644 index 0000000000000000000000000000000000000000..53b40cc8acdeb1529f877875a6c89b7630f5e272 --- /dev/null +++ b/.vite/deps/_metadata.json @@ -0,0 +1,8 @@ +{ + "hash": "7678463b", + "configHash": "aaeefbd1", + "lockfileHash": "e3b0c442", + "browserHash": "7b5c57bd", + "optimized": {}, + "chunks": {} +} \ No newline at end of file diff --git a/.vite/deps/package.json b/.vite/deps/package.json new file mode 100644 index 0000000000000000000000000000000000000000..3dbc1ca591c0557e35b6004aeba250e6a70b56e3 --- /dev/null +++ b/.vite/deps/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..9c667ec66f8a68287dfd6489180bb02d06040bfc --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +FROM python:3.11-slim +WORKDIR /code +COPY ./requirements.txt /code/requirements.txt +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt +COPY . /code +# Fix permissions for libraries that write to home +RUN mkdir -p /tmp/home +ENV HOME=/tmp/home +# Start the FastAPI server on port 7860 (required by Hugging Face) +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"] diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b3617fca72fc57dca8df072e450f5415eae79360 --- /dev/null +++ b/README.md @@ -0,0 +1,151 @@ +--- +title: StyleSync AI +emoji: šŸ‘Ÿ +colorFrom: blue +colorTo: purple +sdk: docker +pinned: false +--- + +
+ +# šŸš€ StyleSync AI + +### Autonomous E-Commerce Catalog Intelligence + +![Python](https://img.shields.io/badge/Python-3.10+-3776AB?style=for-the-badge&logo=python&logoColor=white) +![FastAPI](https://img.shields.io/badge/FastAPI-005571?style=for-the-badge&logo=fastapi&logoColor=white) +![Google Gemini](https://img.shields.io/badge/Gemini_2.5_Flash-4285F4?style=for-the-badge&logo=google&logoColor=white) +![Pinecone](https://img.shields.io/badge/Pinecone-000000?style=for-the-badge&logo=pinecone&logoColor=white) +![Docker](https://img.shields.io/badge/Docker-2496ED?style=for-the-badge&logo=docker&logoColor=white) + +--- + +*A multi-agent AI pipeline that converts raw product imagery into enterprise-grade, SEO-optimized e-commerce catalogs in seconds.* + +
+ +--- + +## šŸŽÆ Core Value Proposition + +StyleSync AI eliminates the manual bottleneck of product catalog creation. By orchestrating **Computer Vision**, **Retrieval-Augmented Generation (RAG)**, and **Large Language Models** in a seamless autonomous pipeline, it delivers production-ready product listings — from a single image upload — with zero human intervention. + +--- + +## šŸ—ļø System Architecture + +The system employs a high-performance, event-driven architecture orchestrated by **FastAPI**: + +### šŸ‘ļø Visual Analyst Agent +- **Function**: Zero-shot product image analysis +- **Process**: Extracts granular visual attributes — dominant colors, material composition, design style, branding elements, and product classification +- **Engine**: `Gemini 2.5 Flash` via the unified **Google GenAI SDK** (`google-genai`) + +### 🧠 Semantic Memory Agent +- **Function**: RAG-based keyword retrieval with intelligent fallback +- **Process**: Vectorizes visual attributes to query a high-dimensional index, retrieving historically high-converting SEO keywords and market trends. When the database has no match for a niche, the **Intelligence Fallback** system autonomously generates keywords via Gemini — ensuring **0% empty results** +- **Engine**: `Pinecone Vector DB` with `gemini-embedding-001` embeddings (768 dimensions) + +### āœļø Writer Agent +- **Function**: High-conversion copy synthesis +- **Process**: Fuses visual intelligence with retrieved market data to generate persuasive, conversion-optimized titles, descriptions, and feature bullet points +- **Engine**: `Meta Llama 3.3 70B` (via Groq Cloud) + +### āš™ļø Pipeline Orchestrator +- **Function**: Async pipeline management & delivery +- **Process**: Handles non-blocking agent execution, error propagation, and API lifecycle management. Results are delivered instantly through the **Premium Glassmorphism UI** +- **Engine**: `FastAPI` with async/await architecture + +--- + +## šŸ–„ļø Production Interface + +StyleSync AI ships with a **Premium Glassmorphism UI** built for instant catalog generation: + +- šŸŽØ Frosted-glass aesthetic with dynamic gradient backgrounds +- šŸ“¤ Drag-and-drop image upload with real-time processing feedback +- šŸ“Š Structured JSON output display for visual data, SEO keywords, and generated listings +- šŸ“± Fully responsive design across desktop, tablet, and mobile + +--- + +## šŸ› ļø Technology Stack + +| Layer | Technology | Purpose | +|-------|-----------|---------| +| **Runtime** | Python 3.10+ | Core language | +| **Framework** | FastAPI | Async API orchestration | +| **AI SDK** | `google-genai` (Unified) | Vision & embedding inference | +| **Vision Model** | Gemini 2.5 Flash | Product image analysis | +| **Embeddings** | `gemini-embedding-001` | 768-dim vector generation | +| **Vector DB** | Pinecone (Serverless) | Semantic keyword retrieval | +| **LLM** | Llama 3.3 70B (Groq) | Copywriting synthesis | +| **UI** | Glassmorphism / Tailwind CSS | Production dashboard | +| **Deployment** | Docker / Hugging Face Spaces | Containerized hosting | + +--- + +## šŸ“‹ System Updates & Technical Milestones + +| Date | Milestone | +|------|-----------| +| **Feb 2026** | āœ… Full migration from deprecated `google-generativeai` to unified `google-genai` SDK | +| **Feb 2026** | āœ… Vision model upgraded to `Gemini 2.5 Flash` for industry-leading latency | +| **Feb 2026** | āœ… Pinecone vector alignment to `768 dimensions` with `gemini-embedding-001` for mathematical precision | +| **Feb 2026** | āœ… **Intelligence Fallback** system deployed — guarantees 0% empty SEO keyword results | +| **Feb 2026** | āœ… n8n webhook decoupled — pipeline relies strictly on the Glassmorphism UI for delivery | +| **Feb 2026** | āœ… Production Glassmorphism dashboard launched | + +--- + +## šŸš€ Quick Start + +### 1. Environment Configuration + +Create a `.env` file in the project root with the following keys: + +```env +GEMINI_API_KEY=your_google_genai_api_key +GROQ_API_KEY=your_groq_cloud_api_key +PINECONE_API_KEY=your_pinecone_api_key +``` + +### 2. Installation + +```bash +pip install -r requirements.txt +``` + +### 3. Launch + +```bash +python main.py +``` + +The production dashboard will be available at `http://localhost:7860`. + +--- + +## šŸ“ Project Structure + +``` +StyleSync-AI/ +ā”œā”€ā”€ main.py # FastAPI orchestrator & pipeline logic +ā”œā”€ā”€ dashboard.html # Glassmorphism production UI +ā”œā”€ā”€ Dockerfile # Container deployment config +ā”œā”€ā”€ requirements.txt # Python dependencies +ā”œā”€ā”€ agents/ +│ ā”œā”€ā”€ visual_analyst.py # Gemini 2.5 Flash vision agent +│ ā”œā”€ā”€ memory_agent.py # Pinecone RAG + embedding agent +│ └── writer_agent.py # Llama 3.3 copywriting agent +└── .env # Environment variables (not tracked) +``` + +--- + +
+ +**StyleSync AI** — Autonomous catalog intelligence for modern e-commerce. + +
diff --git a/agents/__init__.py b/agents/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/agents/manager.py b/agents/manager.py new file mode 100644 index 0000000000000000000000000000000000000000..a246213c4fc762489896742ea0a63a09225c006c --- /dev/null +++ b/agents/manager.py @@ -0,0 +1,46 @@ +import csv +import time +import os +import datetime +from agents.trend_spotter import TrendSpotter +from agents.visionary import Visionary + +class MerchManager: + def __init__(self): + self.trend_spotter = TrendSpotter() + self.visionary = Visionary() + self.results_dir = "results" + if not os.path.exists(self.results_dir): + os.makedirs(self.results_dir) + + def generate_batch(self, niche: str) -> str: + # Step 1: Get slogans + print(f"šŸ” Analyzing trends for niche: {niche}...") + slogans = self.trend_spotter.get_trends(niche) + + results = [] + + # Step 2: Generate art prompts + print(f"šŸŽØ Generating designs for {len(slogans)} slogans...") + for i, slogan in enumerate(slogans): + print(f"Generating design {i+1}/{len(slogans)}...") + prompt = self.visionary.generate_art_prompt(slogan, niche) + results.append({ + "Niche": niche, + "Slogan": slogan, + "Art Prompt": prompt + }) + time.sleep(10) + + # Step 3 & 4: Save to CSV + timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") + filename = f"merch_batch_{niche}_{timestamp}.csv" + filepath = os.path.join(self.results_dir, filename) + + with open(filepath, mode='w', newline='', encoding='utf-8') as file: + writer = csv.DictWriter(file, fieldnames=["Niche", "Slogan", "Art Prompt"]) + writer.writeheader() + writer.writerows(results) + + print(f"āœ… Batch complete! Saved to {filepath}") + return filename diff --git a/agents/memory_agent.py b/agents/memory_agent.py new file mode 100644 index 0000000000000000000000000000000000000000..ff9272bc8b503e5d745511c528963ac4186c987b --- /dev/null +++ b/agents/memory_agent.py @@ -0,0 +1,104 @@ +import os +import time +from dotenv import load_dotenv +from pinecone import Pinecone, ServerlessSpec +from google import genai + +load_dotenv() + +class MemoryAgent: + def __init__(self): + # Configure Gemini + self.gemini_api_key = os.getenv("GEMINI_API_KEY") + if not self.gemini_api_key: + raise ValueError("GEMINI_API_KEY not found") + self.client = genai.Client(api_key=self.gemini_api_key) + + # Configure Pinecone + self.pinecone_api_key = os.getenv("PINECONE_API_KEY") + if not self.pinecone_api_key: + raise ValueError("PINECONE_API_KEY not found") + + self.pc = Pinecone(api_key=self.pinecone_api_key) + self.index_name = "stylesync-index" + + # Check and create index + existing_indexes = [i.name for i in self.pc.list_indexes()] + if self.index_name not in existing_indexes: + print(f"Creating index {self.index_name}...") + self.pc.create_index( + name=self.index_name, + dimension=768, # gemini-embedding-001 output dimension + metric='cosine', + spec=ServerlessSpec( + cloud='aws', + region='us-east-1' + ) + ) + # Wait for index to be ready + while not self.pc.describe_index(self.index_name).status['ready']: + time.sleep(1) + print("Index created.") + + self.index = self.pc.Index(self.index_name) + + def _get_embedding(self, text): + # Using gemini-embedding-001 + result = self.client.models.embed_content( + model="gemini-embedding-001", + contents=text, + config=genai.types.EmbedContentConfig(output_dimensionality=768) + ) + return result.embeddings[0].values + + def seed_database(self): + # Check if empty + stats = self.index.describe_index_stats() + if stats.total_vector_count > 0: + print("Database already seeded.") + return + + print("Seeding database...") + items = [ + { + "id": "item1", + "text": "Running Shoe", + "keywords": "breathable, shock absorption, marathon training, lightweight" + }, + { + "id": "item2", + "text": "Graphic T-Shirt", + "keywords": "100% cotton, vintage wash, pre-shrunk, soft feel" + }, + { + "id": "item3", + "text": "Leather Wallet", + "keywords": "genuine leather, RFID blocking, minimalist, bifold" + } + ] + + vectors = [] + for item in items: + embedding = self._get_embedding(item['text']) + vectors.append({ + "id": item['id'], + "values": embedding, + "metadata": {"keywords": item['keywords'], "text": item['text']} + }) + + self.index.upsert(vectors=vectors) + print(f"Seeded {len(vectors)} items.") + + def retrieve_keywords(self, query_text: str): + try: + query_embedding = self._get_embedding(query_text) + + results = self.index.query( + vector=query_embedding, + top_k=5, + include_metadata=True + ) + return [m.metadata['keywords'] for m in results.matches if m.metadata and 'keywords' in m.metadata] + except Exception as e: + print(f"āŒ Keyword Retrieval Failed: {e}") + return [] diff --git a/agents/visual_analyst.py b/agents/visual_analyst.py new file mode 100644 index 0000000000000000000000000000000000000000..597c4800c42aecd29d4f08568a2ec3e7d20aa4e2 --- /dev/null +++ b/agents/visual_analyst.py @@ -0,0 +1,61 @@ +import os +import json +import re +from google import genai +from dotenv import load_dotenv + +load_dotenv() + +class VisualAnalyst: + def __init__(self): + self.api_key = os.getenv("GEMINI_API_KEY") + if not self.api_key: + raise ValueError("GEMINI_API_KEY not found") + + self.client = genai.Client(api_key=self.api_key) + self.model_name = "gemini-2.5-flash" + print(f"āœ… VisualAnalyst stored Gemini model: {self.model_name}") + + async def analyze_image(self, image_path: str): + try: + # Upload the file to Gemini + # Note: For efficiency in production, files should be managed (uploads/deletes) + # but for this agentic flow, we'll upload per request or assume local path usage helper if needed. + # However, the standard `model.generate_content` can take PIL images or file objects directly for some sdk versions, + # but using the File API is cleaner for 1.5 Flash multi-modal. + # Let's use the simpler PIL integration if available, or just path if the SDK supports it. + # actually, standard genai usage for images usually involves PIL or uploading. + # Let's try the PIL approach first as it's often more direct for local scripts. + import PIL.Image + img = PIL.Image.open(image_path) + + user_prompt = ( + "Analyze this product image. " + "Return ONLY valid JSON with keys: main_color, product_type, design_style, visual_features." + ) + + # We'll stick to prompt engineering for now to match the "Return ONLY valid JSON" instruction. + response = self.client.models.generate_content( + model=self.model_name, + contents=[user_prompt, img] + ) + + response_text = response.text + + # Use regex to find the JSON block robustly + match = re.search(r'\{.*\}', response_text, re.DOTALL) + if match: + cleaned_content = match.group(0) + else: + cleaned_content = response_text + + return json.loads(cleaned_content.strip()) + + except Exception as e: + print(f"āŒ Analysis Failed: {e}") + return { + "main_color": "Unknown", + "product_type": "Unknown", + "design_style": "Unknown", + "visual_features": [f"Error: {str(e)}"] + } diff --git a/agents/writer_agent.py b/agents/writer_agent.py new file mode 100644 index 0000000000000000000000000000000000000000..826bf305076b9d9167062be77a0d20f1c508b8c2 --- /dev/null +++ b/agents/writer_agent.py @@ -0,0 +1,48 @@ +import os +import json +from groq import Groq +from dotenv import load_dotenv + +load_dotenv() + +class WriterAgent: + def __init__(self): + self.api_key = os.getenv("GROQ_API_KEY") + if not self.api_key: + raise ValueError("GROQ_API_KEY not found in environment variables") + self.client = Groq(api_key=self.api_key) + self.model = "llama-3.3-70b-versatile" + + def write_listing(self, visual_data: dict, seo_keywords: list) -> dict: + system_prompt = ( + "You are an expert e-commerce copywriter. " + "Write a persuasive product listing based on these visual attributes and SEO keywords. " + "Return JSON with keys: title, description, bullet_points." + ) + + user_content = f""" + Visual Attributes: {json.dumps(visual_data, indent=2)} + + SEO Keywords: {', '.join(seo_keywords)} + + Please generate the listing in JSON format. + """ + + try: + completion = self.client.chat.completions.create( + model=self.model, + messages=[ + {"role": "system", "content": system_prompt}, + {"role": "user", "content": user_content} + ], + temperature=0.7, + response_format={"type": "json_object"}, + timeout=15.0 + ) + + response_text = completion.choices[0].message.content + return json.loads(response_text) + + except Exception as e: + print(f"Error generating listing: {e}") + return {"error": str(e)} diff --git a/apply_qa_fixes.py b/apply_qa_fixes.py new file mode 100644 index 0000000000000000000000000000000000000000..7b21cfd70eb26dc6a4a596510f242b56a1ea3f44 --- /dev/null +++ b/apply_qa_fixes.py @@ -0,0 +1,111 @@ +import os +import re + +def patch_main(): + with open("main.py", "r", encoding="utf-8") as f: + content = f.read() + + old_pattern = r'return JSONResponse\(\s*content=\{\s*"error": str\(e\),\s*"type": type\(e\)\.__name__,\s*"details": error_details\s*\},\s*status_code=500\s*\)' + new_text = '''return JSONResponse( + content={ + "error": "An internal server error occurred.", + "type": type(e).__name__ + }, + status_code=500 + )''' + content = re.sub(old_pattern, new_text, content[1:] if content.startswith('\ufeff') else content) + + with open("main.py", "w", encoding="utf-8") as f: + f.write(content) + print("Patched main.py") + + +def patch_memory_agent(): + path = "agents/memory_agent.py" + with open(path, "r", encoding="utf-8") as f: + content = f.read() + + old_func = r'def retrieve_keywords\(.*?: str\):.*?return \[m\.metadata\[\'keywords\'\] for m in results\.matches if m\.metadata and \'keywords\' in m\.metadata\]' + new_func = '''def retrieve_keywords(self, query_text: str): + try: + query_embedding = self._get_embedding(query_text) + + results = self.index.query( + vector=query_embedding, + top_k=5, + include_metadata=True + ) + return [m.metadata['keywords'] for m in results.matches if m.metadata and 'keywords' in m.metadata] + except Exception as e: + print(f"āŒ Keyword Retrieval Failed: {e}") + return []''' + + content = re.sub(old_func, new_func, content, flags=re.DOTALL) + + with open(path, "w", encoding="utf-8") as f: + f.write(content) + print("Patched agents/memory_agent.py") + + +def patch_visual_analyst(): + path = "agents/visual_analyst.py" + with open(path, "r", encoding="utf-8") as f: + content = f.read() + + # Add timeout + content = content.replace( + "response = self.model.generate_content([user_prompt, img])", + "response = self.model.generate_content([user_prompt, img], request_options={'timeout': 15.0})" + ) + + if "import re" not in content: + content = content.replace("import json", "import json\nimport re") + + # Rewrite JSON parsing + old_parsing = r'# Clean up potential markdown code fences.*?return json\.loads\(cleaned_content\.strip\(\)\)' + new_parsing = '''# Use regex to find the JSON block robustly + match = re.search(r'\\{.*\\}', response_text, re.DOTALL) + if match: + cleaned_content = match.group(0) + else: + cleaned_content = response_text + + return json.loads(cleaned_content.strip())''' + + content = re.sub(old_parsing, new_parsing, content, flags=re.DOTALL) + + with open(path, "w", encoding="utf-8") as f: + f.write(content) + print("Patched agents/visual_analyst.py") + + +def patch_writer_agent(): + path = "agents/writer_agent.py" + with open(path, "r", encoding="utf-8") as f: + content = f.read() + + old_completion = r'completion = self\.client\.chat\.completions\.create\(\s*model=self\.model,\s*messages=\[\s*\{"role": "system", "content": system_prompt\},\s*\{"role": "user", "content": user_content\}\s*\],\s*temperature=0\.7,\s*response_format=\{"type": "json_object"\}\s*\)' + + new_completion = '''completion = self.client.chat.completions.create( + model=self.model, + messages=[ + {"role": "system", "content": system_prompt}, + {"role": "user", "content": user_content} + ], + temperature=0.7, + response_format={"type": "json_object"}, + timeout=15.0 + )''' + + content = re.sub(old_completion, new_completion, content) + + with open(path, "w", encoding="utf-8") as f: + f.write(content) + print("Patched agents/writer_agent.py") + +if __name__ == "__main__": + patch_main() + patch_memory_agent() + patch_visual_analyst() + patch_writer_agent() + print("All file patching completed successfully.") diff --git a/args.json b/args.json new file mode 100644 index 0000000000000000000000000000000000000000..932aab106c59eb00118aaa29363078216419750f --- /dev/null +++ b/args.json @@ -0,0 +1,4 @@ +{ + "projectId": "13453765122851154258", + "screenId": "cf3af7f8a9e74daf85096241ed88c75c" +} diff --git a/check_basic.py b/check_basic.py new file mode 100644 index 0000000000000000000000000000000000000000..62ed83a48e0a428b6347cdd23e262080cb85ed5d --- /dev/null +++ b/check_basic.py @@ -0,0 +1,20 @@ +import os +from huggingface_hub import InferenceClient +from dotenv import load_dotenv + +load_dotenv() + +api_key = os.getenv("HF_TOKEN") +client = InferenceClient(api_key=api_key) + +print(f"Testing token with microsoft/resnet-50") + +try: + # Pass the URL directly as the input (InferenceClient handles URLs for image tasks) + result = client.image_classification( + model="microsoft/resnet-50", + image="https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/car.jpg?download=true" + ) + print("Success:", result) +except Exception as e: + print("Failed:", e) diff --git a/check_gemini.py b/check_gemini.py new file mode 100644 index 0000000000000000000000000000000000000000..cfca9358a8a65cf29acb003b394c594983f845f0 --- /dev/null +++ b/check_gemini.py @@ -0,0 +1,26 @@ +import os +import google.generativeai as genai +from dotenv import load_dotenv + +load_dotenv() + +api_key = os.getenv("GEMINI_API_KEY") or os.getenv("GOOGLE_API_KEY") +genai.configure(api_key=api_key) + +print("Listing available Gemini models...") +try: + for m in genai.list_models(): + if 'generateContent' in m.supported_generation_methods: + print(m.name) +except Exception as e: + print(f"List models failed: {e}") + +model_name = "gemini-1.5-flash" +print(f"\nTesting model: {model_name}") + +try: + model = genai.GenerativeModel(model_name) + response = model.generate_content("Hello, can you see this?") + print("Response:", response.text) +except Exception as e: + print(f"Test failed: {e}") diff --git a/check_gemini_clean.py b/check_gemini_clean.py new file mode 100644 index 0000000000000000000000000000000000000000..751fe58712a396513b8f40bd9b9773b8407f90ad --- /dev/null +++ b/check_gemini_clean.py @@ -0,0 +1,24 @@ +import os +import google.generativeai as genai +from dotenv import load_dotenv + +load_dotenv() + +api_key = os.getenv("GEMINI_API_KEY") or os.getenv("GOOGLE_API_KEY") +genai.configure(api_key=api_key) + +candidates = [ + "gemini-2.0-flash", + "gemini-2.0-flash-exp", + "models/gemini-2.0-flash" +] + +for model_name in candidates: + print(f"\nTesting model: {model_name}") + try: + model = genai.GenerativeModel(model_name) + response = model.generate_content("Hello") + print(f"āœ… Success with {model_name}: {response.text}") + break + except Exception as e: + print(f"āŒ Failed with {model_name}: {e}") diff --git a/check_groq.py b/check_groq.py new file mode 100644 index 0000000000000000000000000000000000000000..1f1cfc8daf0a05db639ec0c8a57894f8937e5d93 --- /dev/null +++ b/check_groq.py @@ -0,0 +1,11 @@ +import os +from groq import Groq +from dotenv import load_dotenv + +load_dotenv() +client = Groq(api_key=os.getenv("GROQ_API_KEY")) + +print("Listing Groq models...") +models = client.models.list() +for m in models.data: + print(m.id) diff --git a/check_groq_models.py b/check_groq_models.py new file mode 100644 index 0000000000000000000000000000000000000000..95ef4f8e708e6ef50024201903a48ad7c058663c --- /dev/null +++ b/check_groq_models.py @@ -0,0 +1,14 @@ +import os +from groq import Groq +from dotenv import load_dotenv + +load_dotenv() + +try: + client = Groq(api_key=os.getenv("GROQ_API_KEY")) + models = client.models.list() + print("Available Models:") + for model in models.data: + print(f"- {model.id}") +except Exception as e: + print(f"Error listing models: {e}") diff --git a/check_groq_vision.py b/check_groq_vision.py new file mode 100644 index 0000000000000000000000000000000000000000..2fef204aa21a954072c0646b9fd04ea68d80a0d2 --- /dev/null +++ b/check_groq_vision.py @@ -0,0 +1,36 @@ +import os +from groq import Groq +from dotenv import load_dotenv +import base64 + +load_dotenv() + +client = Groq(api_key=os.getenv("GROQ_API_KEY")) +model = "llama-3.2-11b-vision-preview" + +print(f"Testing Groq Vision model: {model}") + +# Test 1: Image URL +print("\n--- Test 1: Image URL ---") +try: + image_url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/car.jpg?download=true" + completion = client.chat.completions.create( + model=model, + messages=[ + { + "role": "user", + "content": [ + {"type": "text", "text": "What's in this image?"}, + {"type": "image_url", "image_url": {"url": image_url}}, + ], + } + ], + temperature=1, + max_tokens=1024, + top_p=1, + stream=False, + stop=None, + ) + print("Response:", completion.choices[0].message.content) +except Exception as e: + print("Groq Vision failed:", e) diff --git a/check_idefics.py b/check_idefics.py new file mode 100644 index 0000000000000000000000000000000000000000..9a147a19999a3e66c6c125232153a5e26f9112f8 --- /dev/null +++ b/check_idefics.py @@ -0,0 +1,33 @@ +import os +from huggingface_hub import InferenceClient +from dotenv import load_dotenv + +load_dotenv() + +api_key = os.getenv("HF_TOKEN") +client = InferenceClient(api_key=api_key) +model = "HuggingFaceM4/idefics2-8b" + +print(f"Testing model: {model}") + +# Test 1: Image URL +print("\n--- Test 1: Image URL ---") +try: + image_url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/car.jpg?download=true" + messages = [ + { + "role": "user", + "content": [ + {"type": "image_url", "image_url": {"url": image_url}}, + {"type": "text", "text": "What is in this image?"} + ] + } + ] + completion = client.chat.completions.create( + model=model, + messages=messages, + max_tokens=100 + ) + print("Response:", completion.choices[0].message.content) +except Exception as e: + print("Image URL failed:", e) diff --git a/check_idefics_raw.py b/check_idefics_raw.py new file mode 100644 index 0000000000000000000000000000000000000000..63e5737d1812d52a2843276bbd54f98858b8b93c --- /dev/null +++ b/check_idefics_raw.py @@ -0,0 +1,29 @@ +import os +import requests +import json +from dotenv import load_dotenv + +load_dotenv() + +api_key = os.getenv("HF_TOKEN") +model = "HuggingFaceM4/idefics2-8b" +url = f"https://router.huggingface.co/models/{model}" + +headers = {"Authorization": f"Bearer {api_key}"} + +print(f"Testing URL: {url}") + +# Test A: Simple text inputs +print("\n--- Test A: Simple Text ---") +response = requests.post(url, headers=headers, json={"inputs": "Hello"}) +print(f"Status: {response.status_code}") +print("Response:", response.text) + +# Test B: Formatted inputs (Standard for some VLM APIs) +# Often they accept { "inputs": "User: ...", "parameters": ... } +print("\n--- Test B: Formatted Prompt ---") +image_url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/car.jpg?download=true" +prompt = f"User: ![]({image_url}) Describe this image.\nAssistant:" +response = requests.post(url, headers=headers, json={"inputs": prompt, "parameters": {"max_new_tokens": 50}}) +print(f"Status: {response.status_code}") +print("Response:", response.text) diff --git a/check_idefics_v2.py b/check_idefics_v2.py new file mode 100644 index 0000000000000000000000000000000000000000..cff412d492377c765df36dfdf508f92fbc4211a4 --- /dev/null +++ b/check_idefics_v2.py @@ -0,0 +1,31 @@ +import os +from huggingface_hub import InferenceClient +from dotenv import load_dotenv + +load_dotenv() + +api_key = os.getenv("HF_TOKEN") +client = InferenceClient(api_key=api_key) +model = "HuggingFaceM4/idefics2-8b" + +print(f"Testing model: {model}") + +image_url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/car.jpg?download=true" + +# Format for Idefics2: +# User: ![]() \nAssistant: +prompt = f"User: ![]({image_url}) Describe this image.\nAssistant:" + +print(f"\n--- Testing with text_generation and specific prompt ---") +print(f"Prompt: {prompt}") + +try: + # Use text_generation for models that don't support chat + response = client.text_generation( + prompt=prompt, + model=model, + max_new_tokens=100 + ) + print("Response:", response) +except Exception as e: + print("Failed:", e) diff --git a/check_idefics_v3.py b/check_idefics_v3.py new file mode 100644 index 0000000000000000000000000000000000000000..c141fb6a5ab3ec0ccdc7486cf9f14be26624dc16 --- /dev/null +++ b/check_idefics_v3.py @@ -0,0 +1,30 @@ +import os +import traceback +from huggingface_hub import InferenceClient +from dotenv import load_dotenv + +load_dotenv() + +api_key = os.getenv("HF_TOKEN") +client = InferenceClient(api_key=api_key) +model = "HuggingFaceM4/idefics2-8b" + +print(f"Testing model: {model}") + +print("\n--- Test 1: Image to Text (Captioning) ---") +try: + # This might work if the API treats it as captioning + res = client.image_to_text( + "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/car.jpg?download=true", + model=model + ) + print("Response:", res) +except Exception: + traceback.print_exc() + +print("\n--- Test 2: Text Generation (Simple) ---") +try: + res = client.text_generation("describe a car", model=model, max_new_tokens=50) + print("Response:", res) +except Exception: + traceback.print_exc() diff --git a/check_llama.py b/check_llama.py new file mode 100644 index 0000000000000000000000000000000000000000..ce89a93096544562a342f56a6ac8eb2f0074892a --- /dev/null +++ b/check_llama.py @@ -0,0 +1,33 @@ +import os +from huggingface_hub import InferenceClient +from dotenv import load_dotenv + +load_dotenv() + +api_key = os.getenv("HF_TOKEN") +client = InferenceClient(api_key=api_key) +model = "meta-llama/Llama-3.2-11B-Vision-Instruct" + +print(f"Testing model: {model}") + +# Test 1: Image URL (Llama Vision) +print("\n--- Test 1: Image URL ---") +try: + image_url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/car.jpg?download=true" + messages = [ + { + "role": "user", + "content": [ + {"type": "image_url", "image_url": {"url": image_url}}, + {"type": "text", "text": "What is in this image?"} + ] + } + ] + completion = client.chat.completions.create( + model=model, + messages=messages, + max_tokens=100 + ) + print("Response:", completion.choices[0].message.content) +except Exception as e: + print("Image URL failed:", e) diff --git a/check_llava.py b/check_llava.py new file mode 100644 index 0000000000000000000000000000000000000000..45f8838ebf1283406699c569e89065ea0ce4f8de --- /dev/null +++ b/check_llava.py @@ -0,0 +1,33 @@ +import os +from huggingface_hub import InferenceClient +from dotenv import load_dotenv + +load_dotenv() + +api_key = os.getenv("HF_TOKEN") +client = InferenceClient(api_key=api_key) +model = "llava-hf/llava-1.5-7b-hf" + +print(f"Testing model: {model}") + +# Test 1: Image URL +print("\n--- Test 1: Image URL ---") +try: + image_url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/car.jpg?download=true" + messages = [ + { + "role": "user", + "content": [ + {"type": "image_url", "image_url": {"url": image_url}}, + {"type": "text", "text": "What is in this image?"} + ] + } + ] + completion = client.chat.completions.create( + model=model, + messages=messages, + max_tokens=100 + ) + print("Response:", completion.choices[0].message.content) +except Exception as e: + print("Image URL failed:", e) diff --git a/check_models.py b/check_models.py new file mode 100644 index 0000000000000000000000000000000000000000..959f25472fa8d8095ea27d730091b39b1be92b95 --- /dev/null +++ b/check_models.py @@ -0,0 +1,15 @@ +import google.generativeai as genai +import os +from dotenv import load_dotenv + +load_dotenv() + +api_key = os.getenv("GEMINI_API_KEY") +if not api_key: + print("No API key found") +else: + genai.configure(api_key=api_key) + print("Listing models...") + for m in genai.list_models(): + if 'generateContent' in m.supported_generation_methods: + print(m.name) diff --git a/check_models_list.py b/check_models_list.py new file mode 100644 index 0000000000000000000000000000000000000000..2f7dd960dc1329afe118c05f897888e57353f001 --- /dev/null +++ b/check_models_list.py @@ -0,0 +1,15 @@ +import google.generativeai as genai +import os +from dotenv import load_dotenv + +load_dotenv() + +api_key = os.getenv("GEMINI_API_KEY") +if not api_key: + print("āŒ API Key not found") +else: + genai.configure(api_key=api_key) + print("Listing available models...") + for m in genai.list_models(): + if 'generateContent' in m.supported_generation_methods: + print(m.name) diff --git a/check_qwen.py b/check_qwen.py new file mode 100644 index 0000000000000000000000000000000000000000..f91c5ec6dd133195b91d402ff082a927939b516f --- /dev/null +++ b/check_qwen.py @@ -0,0 +1,48 @@ +import os +from huggingface_hub import InferenceClient +from dotenv import load_dotenv + +load_dotenv() + +api_key = os.getenv("HF_TOKEN") +client = InferenceClient(api_key=api_key) +model = "Qwen/Qwen2-VL-7B-Instruct" + +print(f"Testing model: {model}") + +# Test 1: Text only +print("\n--- Test 1: Text Only ---") +try: + messages = [ + {"role": "user", "content": "Hello, are you working?"} + ] + completion = client.chat.completions.create( + model=model, + messages=messages, + max_tokens=100 + ) + print("Response:", completion.choices[0].message.content) +except Exception as e: + print("Text only failed:", e) + +# Test 2: Image (using a public URL to avoid base64 issues first) +print("\n--- Test 2: Image URL ---") +try: + image_url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/car.jpg?download=true" + messages = [ + { + "role": "user", + "content": [ + {"type": "image_url", "image_url": {"url": image_url}}, + {"type": "text", "text": "What is in this image?"} + ] + } + ] + completion = client.chat.completions.create( + model=model, + messages=messages, + max_tokens=100 + ) + print("Response:", completion.choices[0].message.content) +except Exception as e: + print("Image URL failed:", e) diff --git a/check_qwen_raw.py b/check_qwen_raw.py new file mode 100644 index 0000000000000000000000000000000000000000..45c10fd2848b66ec8c269e8a3fef31daabf88dbc --- /dev/null +++ b/check_qwen_raw.py @@ -0,0 +1,52 @@ +import os +import requests +import json +from dotenv import load_dotenv + +load_dotenv() + +api_key = os.getenv("HF_TOKEN") +model = "Qwen/Qwen2-VL-7B-Instruct" +# Update URL to router +url = f"https://router.huggingface.co/models/{model}" + +headers = {"Authorization": f"Bearer {api_key}"} + +print(f"Testing URL: {url}") + +# Test 1: Simple text generation payload (inputs string) +data_text = { + "inputs": "Hello", + "parameters": {"max_new_tokens": 50} +} +print("\n--- Test 1: Text Generation (inputs string) ---") +response = requests.post(url, headers=headers, json=data_text) +print(f"Status: {response.status_code}") +print("Response:", response.text) + +# Test 2: VQA format +data_vqa = { + "inputs": { + "image": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/car.jpg?download=true", + "question": "What is in this image?" + } +} +print("\n--- Test 2: VQA Format ---") +response = requests.post(url, headers=headers, json=data_vqa) +print(f"Status: {response.status_code}") +print("Response:", response.text) + +# Test 3: Chat Completions API (OpenAI style) +url_chat = f"https://router.huggingface.co/models/{model}/v1/chat/completions" +print(f"\nTesting URL: {url_chat}") +data_chat = { + "model": model, # Sometimes required in body + "messages": [ + {"role": "user", "content": "Hello"} + ], + "max_tokens": 50 +} +print("\n--- Test 3: Chat Completion ---") +response = requests.post(url_chat, headers=headers, json=data_chat) +print(f"Status: {response.status_code}") +print("Response:", response.text) diff --git a/clean_binary_deploy.py b/clean_binary_deploy.py new file mode 100644 index 0000000000000000000000000000000000000000..16df127fc6595fc521d36c9cd037911462ac9220 --- /dev/null +++ b/clean_binary_deploy.py @@ -0,0 +1,80 @@ +import os +import subprocess + +def main(): + files_to_delete = [ + "stitch_stylesync_ai_dashboard.zip", + "screen.jpg", + "test_image.jpg" + ] + + # Delete Local Binaries + print("Deleting local binaries...") + for filename in files_to_delete: + try: + os.remove(filename) + print(f"Deleted: {filename}") + except FileNotFoundError: + print(f"File not found (already deleted): {filename}") + except Exception as e: + print(f"Error deleting {filename}: {e}") + + # Update .gitignore + print("Updating .gitignore...") + gitignore_path = ".gitignore" + + # Read existing content to avoid duplicate entries + existing_ignores = [] + try: + if os.path.exists(gitignore_path): + with open(gitignore_path, "r", encoding="utf-8") as f: + existing_ignores = f.read().splitlines() + except Exception as e: + print(f"Warning: Could not read .gitignore: {e}") + + ignores_to_add = ["*.zip", "*.jpg"] + + try: + with open(gitignore_path, "a", encoding="utf-8") as f: + for ignore in ignores_to_add: + if ignore not in existing_ignores: + # add a newline if files doesn't end with one, but simplier to just write + f.write(f"\n{ignore}\n") + print(f"Added '{ignore}' to .gitignore") + else: + print(f"'{ignore}' already in .gitignore") + except Exception as e: + print(f"Error updating .gitignore: {e}") + + # The Orphan Branch Strategy + print("\nExecuting Git Orphan Branch Strategy...") + + commands = [ + "git checkout --orphan hf_clean_deploy_v2", + "git add .", + 'git commit -m "UI Update: Glassmorphism Design & Binary Cleanup"' + ] + + for cmd in commands: + print(f"Running: {cmd}") + subprocess.run(cmd, shell=True, check=False) + + push_cmd = "git push --force space hf_clean_deploy_v2:main" + print(f"\nRunning final push command: {push_cmd}") + + result = subprocess.run(push_cmd, shell=True, capture_output=True, text=True) + + # Expected Output + print("\n--- Push Command STDOUT ---") + print(result.stdout) + print("--- Push Command STDERR ---") + print(result.stderr) + print("---------------------------\n") + + if result.returncode == 0: + print("āœ… Force push successful!") + else: + print("āŒ Force push failed (see STDERR above).") + +if __name__ == "__main__": + main() diff --git a/code.html b/code.html new file mode 100644 index 0000000000000000000000000000000000000000..9104e6fde64fe5508e21d6326bd61d06bbd01df4 --- /dev/null +++ b/code.html @@ -0,0 +1,203 @@ + + + + +StyleSync AI Dashboard + + + + + + + + + +
+
+
+all_inclusive +
+
+

StyleSync AI

+Enterprise Edition +
+
+ +
+
+
+
+
+

Input Data

+Step 1 of 2 +
+
+
+
+cloud_upload +
+
+

Drop Product Image Here

+

Supports JPG, PNG, WEBP

+
+ +
+
+
+
+ +
+ +
+
+
+ +
+
+
+
+
+
+
+

Generated Output

+
+ + +
+
+
+
+
+ + +
+
+Vision Agent +Gemini Pro 1.5 +
+visibility +
+
+
+ +
+
+Reasoning Agent +Llama 3 70B +
+psychology +
+
+
+ +
+
+SEO Context +Pinecone DB +
+database +
+
+
+
+output.json +
+
+
+
+
+
+
+
1  {
+2    "product_analysis": {
+3      "title": "Apex Terrain All-Weather Performance Jacket",
+4      "category": "Outerwear / Men's / Technical Shells",
+5      "features": [
+6        "Gore-Tex Pro Membrane",
+7        "Articulated Sleeves",
+8        "Helmet-Compatible Hood"
+9      ],
+10     "seo_tags": [
+11       "#hikinggear", "#waterproof", "#adventure"
+12     ],
+13     "sentiment_score": 0.98,
+14     "market_fit": "High Demand"
+15   },
+16   "deployment_status": "Ready"
+17 }
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/connect_n8n.py b/connect_n8n.py new file mode 100644 index 0000000000000000000000000000000000000000..229041fe72e0225969167ddb119129031166cb5a --- /dev/null +++ b/connect_n8n.py @@ -0,0 +1,126 @@ +import os +import subprocess + +def update_requirements(): + req_file = "requirements.txt" + if not os.path.exists(req_file): + with open(req_file, "w") as f: + f.write("httpx\n") + print(f"Created {req_file} with httpx.") + return + + with open(req_file, "r") as f: + content = f.read() + + if "httpx" not in content: + with open(req_file, "a") as f: + f.write("\nhttpx\n") + print("Appended httpx to requirements.txt.") + else: + print("httpx already in requirements.txt.") + +def update_main(): + main_content = r'''import os +import httpx +import asyncio +from fastapi import FastAPI, UploadFile, File +from fastapi.responses import HTMLResponse, JSONResponse +from dotenv import load_dotenv +# Import Agents +from agents.visual_analyst import VisualAnalyst +from agents.memory_agent import MemoryAgent +from agents.writer_agent import WriterAgent +load_dotenv() +app = FastAPI() +# Initialize Agents +try: + visual_agent = VisualAnalyst() + memory_agent = MemoryAgent() + writer_agent = WriterAgent() + memory_agent.seed_database() + print("āœ… All Agents Online") +except Exception as e: + print(f"āš ļø Agent Startup Warning: {e}") +@app.get("/", response_class=HTMLResponse) +async def read_root(): + try: + with open("dashboard.html", "r") as f: + return f.read() + except FileNotFoundError: + return "

Error: dashboard.html not found

" +@app.post("/generate-catalog") +async def generate_catalog(file: UploadFile = File(...)): + try: + # 1. Save Temp File + os.makedirs("uploads", exist_ok=True) + file_path = f"uploads/{file.filename}" + with open(file_path, "wb") as f: + f.write(await file.read()) + # 2. Run AI Pipeline + visual_data = await visual_agent.analyze_image(file_path) + + query = f"{visual_data.get('main_color', '')} {visual_data.get('product_type', 'product')}" + seo_keywords = memory_agent.retrieve_keywords(query) + + listing = writer_agent.write_listing(visual_data, seo_keywords) + + # 3. Construct Final Payload + final_data = { + "visual_data": visual_data, + "seo_keywords": seo_keywords, + "listing": listing + } + # 4. ⚔ N8N AUTOMATION TRIGGER ⚔ + n8n_url = os.getenv("N8N_WEBHOOK_URL") + if n8n_url: + print(f"šŸš€ Sending data to N8N: {n8n_url}") + # Fire and forget (don't make the user wait for n8n) + asyncio.create_task(send_to_n8n(n8n_url, final_data)) + + # Cleanup + if os.path.exists(file_path): + os.remove(file_path) + + return JSONResponse(content=final_data) + except Exception as e: + return JSONResponse(content={"error": str(e)}, status_code=500) +# Async Helper to send data without blocking +async def send_to_n8n(url, data): + try: + async with httpx.AsyncClient() as client: + await client.post(url, json=data, timeout=5.0) + print("āœ… N8N Webhook Sent Successfully") + except Exception as e: + print(f"āŒ N8N Webhook Failed: {e}") +if __name__ == "__main__": + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=7860) +''' + with open("main.py", "w", encoding="utf-8") as f: + f.write(main_content) + print("Updated main.py with N8N integration logic.") + +def deploy(): + try: + subprocess.run(["git", "add", "."], check=True) + # Check if there are changes to commit + status = subprocess.run(["git", "status", "--porcelain"], capture_output=True, text=True) + if status.stdout.strip(): + subprocess.run(["git", "commit", "-m", "Add N8N Integration"], check=True) + print("Git commit successful.") + else: + print("No changes to commit.") + + print("Pushing to space...") + subprocess.run(["git", "push", "space", "clean_deploy:main"], check=True) + print("āœ… Successfully deployed to Hugging Face Space.") + + except subprocess.CalledProcessError as e: + print(f"āŒ Deployment failed: {e}") + +if __name__ == "__main__": + print("Starting N8N Integration Setup...") + update_requirements() + update_main() + deploy() + print("āœ… connect_n8n.py completed.") diff --git a/create_dockerfile.py b/create_dockerfile.py new file mode 100644 index 0000000000000000000000000000000000000000..03ef0f80ff9e027e30a57aef41a8c93db4f1a38d --- /dev/null +++ b/create_dockerfile.py @@ -0,0 +1,50 @@ +import subprocess +import sys + +def run_command(command): + print(f"Running: {command}") + try: + # shell=True allows us to run the command string exactly as provided + subprocess.run(command, shell=True, check=True) + except subprocess.CalledProcessError as e: + print(f"Error executing command '{command}': {e}") + sys.exit(1) + +def main(): + # 1. Create Dockerfile + dockerfile_content = """FROM python:3.9 +WORKDIR /code +COPY ./requirements.txt /code/requirements.txt +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt +COPY . /code +# Fix permissions for libraries that write to home +RUN mkdir -p /tmp/home +ENV HOME=/tmp/home +# Start the FastAPI server on port 7860 (required by Hugging Face) +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"] +""" + + print("Creating Dockerfile...") + try: + with open("Dockerfile", "w", newline='\n') as f: + f.write(dockerfile_content) + print("Dockerfile created successfully.") + except Exception as e: + print(f"Failed to create Dockerfile: {e}") + sys.exit(1) + + # 2. Push to Space + print("Executing Git commands...") + commands = [ + 'git add Dockerfile', + 'git commit -m "Add Dockerfile for Hugging Face deployment"', + 'git push -f space clean_deploy:main' + ] + + for cmd in commands: + run_command(cmd) + + print("\ncreate_dockerfile.py execution completed.") + +if __name__ == "__main__": + main() diff --git a/dashboard.html b/dashboard.html new file mode 100644 index 0000000000000000000000000000000000000000..55ec7781ef3b2ebe6493927756e5a8400c36ae24 --- /dev/null +++ b/dashboard.html @@ -0,0 +1,397 @@ + + + + +StyleSync AI Dashboard + + + + + + + + + + +
+
+
+
+all_inclusive +
+
+

StyleSync AI

+
+ +Enterprise Edition +
+
+
+ + +
+
+
+
+
+
+
+
+

Input Data

+Step 1 of 2 +
+
+ +
+
+
+cloud_upload +
+
+

Drop Product Image Here

+

Supports JPG, PNG, WEBP

+
+ +
+
+
+ +
+ +
+
+
+ +
+
+
+
+
+
+
+

Generated Output

+
+ + + + +
+
+
+
+
+ + +
+
+Vision Agent +Gemini Pro 1.5 +
+
+
+
+ +
+
+Reasoning Agent +Llama 3 70B +
+
+
+
+ +
+
+SEO Context +Pinecone DB +
+
+
+
+
+
+ +code + output.json + +
+
+
+
+
+
+
+
01{
+02  "product_analysis": {
+03    "title": "Noir Elite Series Artisan Timepiece",
+04    "category": "Luxury / Accessories",
+05    "features": [
+06      "Obsidian Finish",
+07      "Golden Accents",
+08      "Smart Haptic Interface"
+09    ],
+10    "seo_tags": [
+11      "#luxurywear", "#amberstyle", "#premiumtech"
+12    ],
+13    "sentiment_score": 0.99,
+14    "market_fit": "Exceptional"
+15  },
+16  "deployment_status": "Authorized"
+17}
+
+
+
+
+
+
+Ā© 2026 StyleSync AI — All Rights Reserved +
+ + + + diff --git a/deploy_new_ui.py b/deploy_new_ui.py new file mode 100644 index 0000000000000000000000000000000000000000..ac072140ef156dce97d09228046f6d5ffdd5c4a3 --- /dev/null +++ b/deploy_new_ui.py @@ -0,0 +1,60 @@ +import re +import subprocess +import sys + +def main(): + glassui_path = "glassui.html" + dashboard_path = "dashboard.html" + + # Read the New Design + try: + with open(glassui_path, 'r', encoding='utf-8') as f: + glassui_content = f.read() + except FileNotFoundError: + print(f"Error: Could not find '{glassui_path}'.") + sys.exit(1) + + # The Safety Scan (Crucial) + required_ids = [ + "dropZone", + "fileInput", + "browseBtn", + "startBtn", + "deployBtn", + "jsonOutput", + "copyBtn", + "downloadBtn" + ] + + for element_id in required_ids: + # Check if id="element_id" or id='element_id' exists + pattern = rf'id\s*=\s*[\'"]{element_id}[\'"]' + if not re.search(pattern, glassui_content): + print(f"āš ļø WARNING: Missing ID {element_id}") + + # Overwrite + try: + with open(dashboard_path, 'w', encoding='utf-8') as f: + f.write(glassui_content) + print(f"Successfully copied '{glassui_path}' to '{dashboard_path}'.") + except Exception as e: + print(f"Error overwriting '{dashboard_path}': {e}") + sys.exit(1) + + # Deploy + print("Deploying to Hugging Face...") + git_commands = [ + ["git", "add", "dashboard.html"], + ["git", "commit", "-m", "UI Update: Apply responsive Glassmorphism design from Stitch"], + ["git", "push", "space", "clean_deploy:main"] + ] + + for cmd in git_commands: + print(f"Running: {' '.join(cmd)}") + # Use encoding='utf-8' as strictly requested + result = subprocess.run(cmd, text=True, encoding='utf-8') + if result.returncode != 0: + print(f"Command failed: {' '.join(cmd)}") + +if __name__ == "__main__": + main() diff --git a/final_deploy_push.py b/final_deploy_push.py new file mode 100644 index 0000000000000000000000000000000000000000..e7a346790c855f278cd154fd99622f4818eef4a2 --- /dev/null +++ b/final_deploy_push.py @@ -0,0 +1,20 @@ +import subprocess +import sys + +# Force UTF-8 output for Windows terminals +sys.stdout.reconfigure(encoding='utf-8') + +def deploy(): + print("āš ļø Ensure you are inside the D:\\Projects\\StyleSync AI directory before running this!") + + command = "git push --force space clean_deploy:main" + print(f"\nRunning: {command} ...") + + try: + subprocess.run(command, check=True, shell=True) + print("\nāœ… Successfully pushed to Space!") + except subprocess.CalledProcessError as e: + print(f"\nāŒ Push failed: {e}") + +if __name__ == "__main__": + deploy() diff --git a/final_upload.py b/final_upload.py new file mode 100644 index 0000000000000000000000000000000000000000..eae0ea28ec668c44afef4f19a75744e01fa7179f --- /dev/null +++ b/final_upload.py @@ -0,0 +1,61 @@ +import subprocess +import sys + +def run_command(command, check=True): + try: + subprocess.run(command, check=check, shell=True, text=True) + except subprocess.CalledProcessError as e: + print(f"Error executing currently: {command}") + # We don't exit here because some commands like 'remote remove' might fail meaningfully but we want to continue, + # or we handle them specifically in the main flow. + if check: + # Re-raise if we strictly wanted this to succeed + raise e + +def main(): + # Input: Ask the user for the GitHub URL + if len(sys.argv) > 1: + github_url = sys.argv[1].strip() + else: + github_url = input('Please paste your GitHub URL here: ').strip() + + if not github_url: + print("Error: No URL provided.") + return + + try: + # Git Commands sequence + print("Initializing git...") + run_command("git init") + + print("Adding files...") + run_command("git add .") + + print("Committing files...") + try: + # Use check=True so it raises exception on failure, which we catch + run_command('git commit -m "Initial commit - StyleSync AI"', check=True) + except subprocess.CalledProcessError: + print("Commit failed (likely nothing to commit). Continuing...") + + print("Renaming branch to main...") + run_command("git branch -M main") + + print("Removing existing origin (if any)...") + # Don't check=True here because it fails if origin doesn't exist + run_command("git remote remove origin", check=False) + + print(f"Adding remote origin: {github_url}") + run_command(f"git remote add origin {github_url}") + + print("Pushing to GitHub...") + run_command("git push -u origin main") + + # Success message + print('āœ… Code is live on GitHub!') + + except Exception as e: + print(f"\nāŒ An error occurred: {e}") + +if __name__ == "__main__": + main() diff --git a/fix_browse_button.py b/fix_browse_button.py new file mode 100644 index 0000000000000000000000000000000000000000..8c6d43e8d99bfed44c4863798a0219b956b9cc67 --- /dev/null +++ b/fix_browse_button.py @@ -0,0 +1,57 @@ +import sys +import subprocess +import re + +def fix_html(): + with open('dashboard.html', 'r', encoding='utf-8') as f: + content = f.read() + + js_snippet = """ + const browseBtn = document.getElementById('browseBtn'); + browseBtn.addEventListener('click', (e) => { + e.preventDefault(); + fileInput.click(); + }); + fileInput.addEventListener('change', () => { + if (fileInput.files.length > 0) { + // Provide a visual cue that a file was selected + const fileName = fileInput.files[0].name; + browseBtn.innerHTML = `check_circle ${fileName}`; + } + }); +""" + + if "browseBtn.addEventListener('click', (e) => {" in content and "Provide a visual cue that a file was selected" in content: + print("Snippet already exists. Skipping injection.") + else: + # Find where the DOM elements are defined + target = "const downloadBtn = document.getElementById('downloadBtn');" + if target in content: + new_content = content.replace(target, target + "\n" + js_snippet) + with open('dashboard.html', 'w', encoding='utf-8') as f: + f.write(new_content) + print("Injected JS successfully.") + else: + print("Could not find insertion point!") + return False + + # Run git commands + subprocess.run(['git', 'add', 'dashboard.html'], check=True) + try: + subprocess.run(['git', 'commit', '-m', 'Bugfix: Wire up Browse Files button to hidden input'], check=True) + except subprocess.CalledProcessError: + print("Nothing to commit") + + subprocess.run(['git', 'push', '--force', 'space', 'HEAD:main'], check=True) + + # Push to origin main as well + try: + subprocess.run(['git', 'push', 'origin', 'HEAD:main'], check=True) + except subprocess.CalledProcessError: + print("Push to origin failed or not needed") + + print("Deployment triggered successfully.") + return True + +if __name__ == '__main__': + fix_html() diff --git a/fix_dashboard_api.py b/fix_dashboard_api.py new file mode 100644 index 0000000000000000000000000000000000000000..274ad87e08285a9ffd3b8bc6a496d0b91b51adb5 --- /dev/null +++ b/fix_dashboard_api.py @@ -0,0 +1,66 @@ +import sys +import subprocess +import re + +def patch_dashboard(): + with open('dashboard.html', 'r', encoding='utf-8') as f: + content = f.read() + + # Locate the setTimeout block inside startBtn.addEventListener and replace it with fetch logic + pattern = re.compile(r"setTimeout\(\(\) => \{[\s\S]*?\}, 1500\);", re.DOTALL) + + new_block = """try { + const formData = new FormData(); + formData.append('file', fileInput.files[0]); + + const response = await fetch('/generate-catalog', { + method: 'POST', + body: formData + }); + + const data = await response.json(); + jsonOutput.textContent = JSON.stringify(data, null, 2); + isCatalogGenerated = true; + } catch (error) { + console.error("Error generating catalog:", error); + } finally { + startBtn.innerHTML = '
Start Agent Workflowarrow_forward
'; + startBtn.disabled = false; + startBtn.classList.add('animate-pulse-slow', 'animate-glow-pulse'); + }""" + + if not pattern.search(content): + print("Error: Could not find the target setTimeout block in dashboard.html.") + return False + + new_content = pattern.sub(new_block, content) + + with open('dashboard.html', 'w', encoding='utf-8') as f: + f.write(new_content) + + print("Successfully patched dashboard.html") + return True + +def run_git_commands(): + commands = [ + ['git', 'add', 'dashboard.html'], + ['git', 'commit', '-m', 'Bugfix: Restore real API connection to Glassmorphism UI'], + ['git', 'push', '--force', 'space', 'HEAD:main'] + ] + + for cmd in commands: + print(f"Running: {' '.join(cmd)}") + result = subprocess.run(cmd, capture_output=True, text=True) + if result.returncode != 0: + print(f"Command failed with {result.returncode}: \\n{result.stderr}") + # Don't break here, let it try the other commands just in case, though push might fail if commit fails. + if cmd[1] == 'commit' and "nothing to commit" in result.stdout + result.stderr: + continue + if cmd[1] == 'push': + pass + else: + print(f"Success!\\n{result.stdout}") + +if __name__ == '__main__': + if patch_dashboard(): + run_git_commands() diff --git a/fix_dashboard_routing.py b/fix_dashboard_routing.py new file mode 100644 index 0000000000000000000000000000000000000000..d1451fc81ac97f14e06a5387ada14e2d88cfef77 --- /dev/null +++ b/fix_dashboard_routing.py @@ -0,0 +1,87 @@ +import os +import subprocess + +def main(): + # Define the content for main.py + main_py_content = """import os +from fastapi import FastAPI, UploadFile, File, HTTPException +from fastapi.responses import HTMLResponse, JSONResponse +from fastapi.staticfiles import StaticFiles +from agents.visual_analyst import VisualAnalyst +from dotenv import load_dotenv +# Load environment variables +load_dotenv() +app = FastAPI() +# Initialize Agent +visual_agent = VisualAnalyst() +# 1. READ THE DASHBOARD HTML FILE INTO MEMORY +try: + with open("dashboard.html", "r") as f: + dashboard_html = f.read() +except FileNotFoundError: + dashboard_html = "

Error: dashboard.html not found. Please ensure the file exists.

" +# 2. SERVE DASHBOARD AT ROOT (Home Page) +@app.get("/", response_class=HTMLResponse) +async def read_root(): + return dashboard_html +# 3. KEEP /dashboard ROUTE AS BACKUP +@app.get("/dashboard", response_class=HTMLResponse) +async def read_dashboard(): + return dashboard_html +@app.post("/analyze") +async def analyze_merch(file: UploadFile = File(...)): + try: + os.makedirs("uploads", exist_ok=True) + file_path = f"uploads/{file.filename}" + with open(file_path, "wb") as f: + f.write(await file.read()) + result = await visual_agent.analyze_image(file_path) + + if os.path.exists(file_path): + os.remove(file_path) + + return JSONResponse(content=result) + except Exception as e: + return JSONResponse(content={"error": str(e)}, status_code=500) +if __name__ == "__main__": + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=7860) +""" + + # Overwrite main.py + print("Overwriting main.py...") + try: + with open("main.py", "w", encoding="utf-8") as f: + f.write(main_py_content) + print("Successfully updated main.py") + except Exception as e: + print(f"Error writing main.py: {e}") + return + + # Define git commands + git_commands = [ + ["git", "add", "main.py"], + ["git", "commit", "-m", "Fix dashboard 404 by serving HTML at root"], + ["git", "push", "space", "clean_deploy:main"] + ] + + # Run git commands + print("\nRunning git commands...") + for cmd in git_commands: + print(f"Executing: {' '.join(cmd)}") + try: + subprocess.run(cmd, check=True) + except subprocess.CalledProcessError as e: + print(f"Command failed: {e}") + # If commit fails (e.g. nothing to commit), we might want to continue or stop. + # But push should definitely happen if commit works. + # If commit fails because "nothing to commit, working tree clean", push might still be relevant if previous commit wasn't pushed? + # But the user logic implies we just made a change to main.py, so commit should succeed unless main.py was ALREADY this content. + # We will continue to try push even if commit fails, just in case. + # But wait, if commit fails, push might proceed. + pass + + print("\nfix_dashboard_routing.py completed.") + +if __name__ == "__main__": + main() diff --git a/fix_google_key.py b/fix_google_key.py new file mode 100644 index 0000000000000000000000000000000000000000..cdabb024b499d627225436f7f41e66ecc88d51e3 --- /dev/null +++ b/fix_google_key.py @@ -0,0 +1,48 @@ +import os +import sys + +# Force UTF-8 output for Windows terminals +sys.stdout.reconfigure(encoding='utf-8') + +# 1. Update .env +env_path = ".env" +key = "GOOGLE_API_KEY" +value = "AIzaSyDgIkagGBciWNZDTn07OlfY9tVPvo6KJ1on" + +print(f"Updating {key} in .env...") + +lines = [] +if os.path.exists(env_path): + with open(env_path, "r", encoding="utf-8") as f: + lines = f.readlines() + +found = False +new_lines = [] +for line in lines: + if line.startswith(f"{key}="): + new_lines.append(f"{key}={value}\n") + found = True + else: + new_lines.append(line) + +if not found: + if new_lines and not new_lines[-1].endswith('\n'): + new_lines.append('\n') + new_lines.append(f"{key}={value}\n") + +with open(env_path, "w", encoding="utf-8") as f: + f.writelines(new_lines) + +print(f"āœ… Updated {key} in .env") + +# 2. Upload to Cloud +print("Syncing secrets to Hugging Face Space...") +try: + # Build path to ensure we can import upload_secrets + sys.path.append(os.getcwd()) + from upload_secrets import upload_secrets + + upload_secrets() + print("āœ… Google Key saved locally and uploaded to Hugging Face!") +except Exception as e: + print(f"āŒ Failed to sync: {e}") diff --git a/fix_js_syntax.py b/fix_js_syntax.py new file mode 100644 index 0000000000000000000000000000000000000000..95d0f2eaa378687ade1abf854eea651a17deef13 --- /dev/null +++ b/fix_js_syntax.py @@ -0,0 +1,147 @@ +import sys +import subprocess + +def fix_html(): + with open('dashboard.html', 'r', encoding='utf-8') as f: + content = f.read() + + parts = content.split('') + if len(parts) < 2: + print("Could not find in dashboard.html") + return False + + top_part = parts[0] + '\n' + + new_script = """ + + +""" + + with open('dashboard.html', 'w', encoding='utf-8') as f: + f.write(top_part + new_script) + + print("Replaced script successfully.") + + # Run git commands + subprocess.run(['git', 'add', 'dashboard.html'], check=True) + try: + subprocess.run(['git', 'commit', '-m', 'Critical Bugfix: Resolve corrupted JS syntax and restore core agent loop'], check=True) + except subprocess.CalledProcessError: + print("Nothing to commit") + + subprocess.run(['git', 'push', '--force', 'space', 'HEAD:main'], check=True) + + # Push to origin main as well + try: + subprocess.run(['git', 'push', 'origin', 'HEAD:main'], check=True) + except subprocess.CalledProcessError: + print("Push to origin failed or not needed") + + print("Deployment triggered successfully.") + +if __name__ == '__main__': + fix_html() diff --git a/fix_readme.py b/fix_readme.py new file mode 100644 index 0000000000000000000000000000000000000000..319e396c5679c2a074ce55473dd959f7c15c63d1 --- /dev/null +++ b/fix_readme.py @@ -0,0 +1,42 @@ +import os +import sys +import subprocess + +# Force UTF-8 output for Windows terminals +sys.stdout.reconfigure(encoding='utf-8') + +readme_content = """--- +title: StyleSync AI +emoji: šŸš€ +colorFrom: blue +colorTo: indigo +sdk: docker +pinned: false +--- +# StyleSync AI +An AI-powered catalog intelligence agent. +""" + +def run_command(command): + print(f"Running: {command}") + try: + subprocess.run(command, check=True, shell=True) + print("āœ… Success") + except subprocess.CalledProcessError as e: + print(f"āŒ Error: {e}") + # Don't exit, try to continue or let user see error + +def fix_readme(): + print("Writing README.md...") + with open("README.md", "w", encoding="utf-8") as f: + f.write(readme_content) + print("āœ… Created README.md") + + print("Deploying changes...") + run_command("git add README.md") + run_command('git commit -m "Add Hugging Face configuration"') + run_command("git push space clean_deploy:main") + print("āœ… Configuration fixed and pushed!") + +if __name__ == "__main__": + fix_readme() diff --git a/fix_vision_core.py b/fix_vision_core.py new file mode 100644 index 0000000000000000000000000000000000000000..5ab5455ebe5f3da50e3432d33ad0ce0366af50e7 --- /dev/null +++ b/fix_vision_core.py @@ -0,0 +1,90 @@ +import os +import subprocess + +def fix_vision_core(): + # Content for agents/visual_analyst.py + content = """import os +import json +import asyncio +import google.generativeai as genai +from PIL import Image +from dotenv import load_dotenv + +load_dotenv() + +class VisualAnalyst: + def __init__(self): + api_key = os.getenv("GEMINI_API_KEY") + if not api_key: + print("āš ļø GEMINI_API_KEY missing") + + genai.configure(api_key=api_key) + # Use the modern, faster Flash model + self.model = genai.GenerativeModel('gemini-1.5-flash') + + async def analyze_image(self, image_path: str): + print(f"šŸ‘ļø Analyzing image: {image_path}") + + try: + # 1. Load image properly with Pillow (Fixes format issues) + img = Image.open(image_path) + + # 2. Define the prompt + prompt = \"\"\" + Analyze this product image for an e-commerce listing. + Return ONLY a raw JSON object (no markdown formatting) with this structure: + { + "main_color": "string", + "product_type": "string", + "design_style": "string (minimalist, streetwear, vintage, etc)", + "visual_features": ["list", "of", "visible", "features"], + "suggested_title": "creative product title", + "condition_guess": "new/used" + } + \"\"\" + + # 3. Run in a thread to prevent blocking (Sync to Async wrapper) + response = await asyncio.to_thread( + self.model.generate_content, + [prompt, img] + ) + + # 4. Clean and Parse JSON + text_response = response.text.replace('```json', '').replace('```', '').strip() + return json.loads(text_response) + except Exception as e: + print(f"āŒ Vision Error: {e}") + # Return a Safe Fallback (Simulation) + return { + "main_color": "Unknown", + "product_type": "Unidentified Item", + "design_style": "Standard", + "visual_features": ["Error analyzing image"], + "suggested_title": "Manual Review Needed", + "condition_guess": "New" + } +""" + # Write the file + os.makedirs("agents", exist_ok=True) + with open("agents/visual_analyst.py", "w", encoding="utf-8") as f: + f.write(content) + print("āœ… agents/visual_analyst.py updated.") + + # Git operations + print("šŸš€ Pushing to HuggingFace...") + commands = [ + ["git", "add", "agents/visual_analyst.py"], + ["git", "commit", "-m", "Fix vision core and error handling"], + ["git", "push", "space", "clean_deploy:main"] + ] + + for cmd in commands: + try: + print(f"Running: {' '.join(cmd)}") + subprocess.run(cmd, check=True) + except subprocess.CalledProcessError as e: + print(f"āš ļø Command failed: {e}") + # Continue even if commit fails (e.g. prompt already applied) + +if __name__ == "__main__": + fix_vision_core() diff --git a/force_deploy.py b/force_deploy.py new file mode 100644 index 0000000000000000000000000000000000000000..e35f341d3ca757975428ceca5281e289ee84324b --- /dev/null +++ b/force_deploy.py @@ -0,0 +1,62 @@ +""" +force_deploy.py +Force-deploys the current codebase to the Hugging Face Space. +Handles HF binary file restrictions by untracking offending files first. +""" +import subprocess +import sys + +def run(cmd, allow_fail=False): + print(f"\n>>> {cmd}") + result = subprocess.run(cmd, shell=True, capture_output=True, text=True) + if result.stdout: + print(result.stdout.strip()) + if result.stderr: + print(result.stderr.strip()) + if result.returncode != 0 and not allow_fail: + print(f"Command failed with exit code {result.returncode}") + sys.exit(1) + return result + +if __name__ == "__main__": + print("=" * 60) + print(" StyleSync AI — Force Deploy to Hugging Face Space") + print("=" * 60) + + # 0. Remove binary files from Git tracking (keep local copies) + binaries = [ + "stitch_stylesync_ai_dashboard.zip", + "screen.jpg", + "test_image.jpg", + ] + for b in binaries: + run(f"git rm --cached {b}", allow_fail=True) + + # Ensure .gitignore blocks them from being re-added + ignore_entries = binaries + ["*.zip", "*.jpg", "*.jpeg", "*.png"] + try: + existing = open(".gitignore", "r").read() + except FileNotFoundError: + existing = "" + with open(".gitignore", "a") as f: + for entry in ignore_entries: + if entry not in existing: + f.write(f"\n{entry}") + print("\nUpdated .gitignore with binary exclusions.") + + # 1. Stage everything + run("git add .") + + # 2. Commit (allow fail in case nothing changed) + run('git commit -m "Critical Deployment: Force update of License, Security Fixes, and Branding"', allow_fail=True) + + # 3. Force push HEAD to space remote's main branch + run("git push --force space HEAD:main") + + # 4. Print the latest commit for verification + print("\n" + "=" * 60) + print(" Deployed Commit:") + print("=" * 60) + run("git log -1") + + print("\nāœ… Force deploy complete.") diff --git a/force_push.py b/force_push.py new file mode 100644 index 0000000000000000000000000000000000000000..2bd720807e49693d7bf0c9a1a56595b32b234274 --- /dev/null +++ b/force_push.py @@ -0,0 +1,14 @@ +import subprocess + +def main(): + print("Executing force push...") + command = "git push --force space HEAD:main" + result = subprocess.run(command, shell=True, capture_output=True, text=True) + + print("STDOUT:") + print(result.stdout) + print("STDERR:") + print(result.stderr) + +if __name__ == "__main__": + main() diff --git a/glassui.html b/glassui.html new file mode 100644 index 0000000000000000000000000000000000000000..61508c704e0997d3dffaa651600b27f7bd3af961 --- /dev/null +++ b/glassui.html @@ -0,0 +1,455 @@ + + + + +StyleSync AI Dashboard + + + + + + + + + + +
+
+
+
+all_inclusive +
+
+

StyleSync AI

+
+ +Enterprise Edition +
+
+
+ +
+
+
+
+
+
+
+
+

Input Data

+Step 1 of 2 +
+
+ +
+
+
+cloud_upload +
+
+

Drop Product Image Here

+

Supports JPG, PNG, WEBP

+
+ +
+
+
+ +
+ +
+
+
+ +
+
+
+
+
+
+
+

Generated Output

+
+ + + + +
+
+
+
+
+ + +
+
+Vision Agent +Gemini Pro 1.5 +
+
+
+
+ +
+
+Reasoning Agent +Llama 3 70B +
+
+
+
+ +
+
+SEO Context +Pinecone DB +
+
+
+
+
+
+ +code + output.json + +
+
+
+
+
+
+
+
01{
+02  "product_analysis": {
+03    "title": "Noir Elite Series Artisan Timepiece",
+04    "category": "Luxury / Accessories",
+05    "features": [
+06      "Obsidian Finish",
+07      "Golden Accents",
+08      "Smart Haptic Interface"
+09    ],
+10    "seo_tags": [
+11      "#luxurywear", "#amberstyle", "#premiumtech"
+12    ],
+13    "sentiment_score": 0.99,
+14    "market_fit": "Exceptional"
+15  },
+16  "deployment_status": "Authorized"
+17}
+
+
+
+
+
+
+Ā© 2026 StyleSync AI — All Rights Reserved +
+ + + \ No newline at end of file diff --git a/install_gh.py b/install_gh.py new file mode 100644 index 0000000000000000000000000000000000000000..e421ce8ccbd0c7a42306acfcb2b2e142a6d9317d --- /dev/null +++ b/install_gh.py @@ -0,0 +1,33 @@ +import shutil +import subprocess +import sys + +def main(): + # Check Status + gh_path = shutil.which('gh') + + if not gh_path: + # Install + print("GitHub CLI not found. Installing via winget...") + try: + subprocess.run(['winget', 'install', '--id', 'GitHub.cli', '-e'], check=True) + except subprocess.CalledProcessError as e: + print(f"Error installing GitHub CLI: {e}") + return + except FileNotFoundError: + print("Error: 'winget' command not found. Please ensure App Installer is installed.") + return + + # Post-Install Instructions (Runs if installed or if installation succeeded) + print("\n" + "="*40) + try: + # Attempt to use ANSI codes for bold, may not work in all Windows terminals but works in VS Code / modern Windows Terminal + print("āœ… \033[1mGitHub CLI is ready!\033[0m") + except: + print("āœ… GitHub CLI is ready!") + print("="*40) + print("āš ļø IMPORTANT: You must now restart your terminal to reload your PATH.") + print("šŸ‘‰ After restarting, run this command to log in: gh auth login") + +if __name__ == "__main__": + main() diff --git a/landingpage.html b/landingpage.html new file mode 100644 index 0000000000000000000000000000000000000000..0219ab85bf3a9db054adc7269e2ba3b24422139f --- /dev/null +++ b/landingpage.html @@ -0,0 +1,426 @@ + + + + + +StyleSync AI | Autonomous E-Commerce Catalog Intelligence + + + + + + + + + + + + + + + + +
+
+
+all_inclusive +
+
+

StyleSync AI

+

Enterprise Edition

+
+
+ +
+ +
+
+ +
+ +
+
+
+ + + + + + Now in Private Beta + +

+ Autonomous
+E-Commerce
+ Intelligence +

+

+ A multi-agent AI pipeline that converts raw product imagery into enterprise-grade, SEO-optimized e-commerce catalogs in seconds. +

+ +
+ +
+
+
+ +
+
+image +
+
+
+
+
+
+
+
+
+
+ +
+
+
+output.json +
+
{
+  "sku": "MF-9902",
+  "name": "AeroShell X",
+  "tags": ["SEO", "Hiker"]
+}
+
+
+
+
+
+
+ + +
+
+

Zero Manual Bottlenecks

+

Shift from human-in-the-loop to autonomous excellence. Our pipeline ensures your inventory is ready for global distribution instantly.

+
+
+
+
+bolt +
+

Instant Delivery

+

Go from product photo to live Shopify entry in under 15 seconds with zero latency agents.

+
+
+
+verified +
+

0% Human Error

+

Automated cross-referencing against technical specs ensures 100% attribute accuracy.

+
+
+
+trending_up +
+

SEO Native

+

Every description is engineered for search algorithms using real-time market sentiment data.

+
+
+
+ + +
+
+
+

Multi-Agent
Pipeline

+

A sophisticated orchestration of specialized AI agents working in harmony to deliver high-fidelity catalog data.

+
+
+memory + Orchestration Layer: FastAPI + LangGraph +
+
+
+
+ +
+
+visibility +
+
+
+

Visual Analyst

+GEMINI 2.5 FLASH +
+

Performs deep pixel analysis to extract material textures, silhouettes, and hardware details directly from raw imagery.

+
+
+ +
+
+database +
+
+
+

Semantic Memory

+PINECONE RAG +
+

Queries vector databases for historical product context, brand voice guidelines, and competitive SEO keywords.

+
+
+ +
+
+edit_note +
+
+
+

Writer Agent

+LLAMA 3.3 70B (GROQ) +
+

Synthesizes visual and semantic data into high-converting product descriptions, bullet points, and metadata.

+
+
+
+
+
+ + +
+
+
+

Technical Infrastructure

+SYSTEM_MANIFEST.V2 +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ComponentTechnologyPurposeStatus
Core BackendPython 3.10+ / FastAPIAsynchronous high-throughput processingSTABLE
Agent FrameworkGoogle GenAI / Groq SDKMulti-LLM orchestration & executionSTABLE
Knowledge BasePinecone Vector DBRetrieval Augmented Generation (RAG)STABLE
DeploymentDocker / KubernetesContainerized auto-scaling architectureSTABLE
+
+
+
+ + +
+
+
+

Scale Your Catalog To
Infinite.

+

Join enterprise retail leaders who are automating their supply chain intelligence with StyleSync AI.

+
+ + +
+
+
+ +
+ + + + + + + \ No newline at end of file diff --git a/launcher.py b/launcher.py new file mode 100644 index 0000000000000000000000000000000000000000..a9338e59ad7cd3e1476345e38a7159ccebb104e4 --- /dev/null +++ b/launcher.py @@ -0,0 +1,47 @@ +import subprocess +import time +import webbrowser +import os +import urllib.request +import sys + +def is_server_ready(url): + try: + with urllib.request.urlopen(url) as response: + return response.getcode() == 200 + except Exception: + return False + +def main(): + print("šŸš€ Starting Engine...") + + # Definition of the server command + # Using sys.executable to ensure we use the same python interpreter + server_command = [sys.executable, "-m", "uvicorn", "main:app", "--reload"] + + # Start the server as a subprocess + process = subprocess.Popen(server_command, cwd=os.getcwd()) + + server_url = "http://localhost:8000" + + # Poll for server availability + try: + while not is_server_ready(server_url): + time.sleep(1) + + print("āœ… Dashboard Launched") + + # Open the dashboard in the default web browser + dashboard_path = os.path.abspath("dashboard.html") + webbrowser.open(f"file:///{dashboard_path}") + + # Keep the script running to maintain the server process + process.wait() + + except KeyboardInterrupt: + print("\nšŸ›‘ Shutting down...") + process.terminate() + process.wait() + +if __name__ == "__main__": + main() diff --git a/legacy/trend_spotter.py b/legacy/trend_spotter.py new file mode 100644 index 0000000000000000000000000000000000000000..c0d5fbd14e22e5bebe3bc511e61c9a75a8166c69 --- /dev/null +++ b/legacy/trend_spotter.py @@ -0,0 +1,46 @@ +import os +import json +import google.generativeai as genai +from dotenv import load_dotenv + +load_dotenv() + +class TrendSpotter: + def __init__(self): + self.api_key = os.getenv("GEMINI_API_KEY") + if self.api_key: + genai.configure(api_key=self.api_key) + self.model = genai.GenerativeModel('gemini-flash-latest') + self.has_key = True + else: + self.model = None + self.has_key = False + + def get_trends(self, niche: str): + if not self.has_key: + print("āš ļø No API Key found, using mock data") + return ['Retro Cat Mom', 'Pixel Art Kitty', 'Cattitude'] + + try: + prompt = f"Generate 5 short, witty, and viral t-shirt text concepts for the niche: {niche}. Return strictly a JSON list of strings." + response = self.model.generate_content(prompt) + + content = response.text + # Clean up markdown formatting if present + if "```json" in content: + content = content.replace("```json", "").replace("```", "") + elif "```" in content: + content = content.replace("```", "") + + try: + trends = json.loads(content) + if isinstance(trends, list): + return trends + else: + return [content] + except json.JSONDecodeError: + return [content] + + except Exception as e: + print(f"āŒ Error calling Gemini: {e}") + return ['Retro Cat Mom', 'Pixel Art Kitty', 'Cattitude'] diff --git a/legacy/visionary.py b/legacy/visionary.py new file mode 100644 index 0000000000000000000000000000000000000000..0fc57e93709ec55c24ba07cb70c28bcf7738bfaf --- /dev/null +++ b/legacy/visionary.py @@ -0,0 +1,33 @@ +import os +import google.generativeai as genai +from dotenv import load_dotenv + +load_dotenv() + +class Visionary: + def __init__(self): + self.api_key = os.getenv("GEMINI_API_KEY") + if self.api_key: + genai.configure(api_key=self.api_key) + self.model = genai.GenerativeModel('gemini-flash-latest') + self.has_key = True + else: + self.model = None + self.has_key = False + + def generate_art_prompt(self, slogan: str, niche: str) -> str: + if not self.has_key: + return "Mock visualization: A cute retro cat wearing sunglasses, vector art, pastel colors" + + try: + system_prompt = ( + f'You are an expert T-shirt Designer. Create a high-quality AI art generation prompt ' + f'for the slogan: "{slogan}" in the niche: "{niche}". ' + f'Specify style (e.g., vector, retro, kawaii), colors, and composition. ' + f'Keep it under 40 words.' + ) + response = self.model.generate_content(system_prompt) + return response.text.strip() + except Exception as e: + print(f"āŒ Error calling Gemini: {e}") + return "Error generating prompt" diff --git a/legal/MSA_TEMPLATE.md b/legal/MSA_TEMPLATE.md new file mode 100644 index 0000000000000000000000000000000000000000..99ac65d670eecd984cf53286d5f79cdb32948dd3 --- /dev/null +++ b/legal/MSA_TEMPLATE.md @@ -0,0 +1,15 @@ +# Master Service Agreement + +**Parties:** "The Consultant" AND "[Client Name]" (The Client). + +## Clause 1: Payment & MSME Protection +Strict adherence to the Micro, Small and Medium Enterprises Development (MSMED) Act, 2006. Pursuant to Section 15, all payments must be settled within forty-five (45) days of invoice date. Delayed payments shall attract compound interest at three times (3x) the bank rate notified by the Reserve Bank of India, as mandated by Section 16 of the Act. + +## Clause 2: Intellectual Property Rights +Background IP (including pre-existing code, libraries, and agents) remains the sole property of the Consultant. Custom deliverables become Client property only upon full and final settlement of all dues. + +## Clause 3: Future Transfer (Successor Entity) +Assignment of Rights: The Consultant reserves the right to assign or transfer all rights, duties, and intellectual property created under this agreement to a successor corporate entity or affiliate upon formal incorporation, without requiring further consent from the Client. + +## Clause 4: Confidentiality +Both parties agree to hold in strict confidence any proprietary or confidential information, including trade secrets, disclosed during the course of this agreement. Such information shall not be used for any purpose other than the performance of obligations under this agreement, nor disclosed to any third party without prior written consent. diff --git a/main.py b/main.py new file mode 100644 index 0000000000000000000000000000000000000000..b7fb7a495fd657ec1623fe9f6be710124144de3b --- /dev/null +++ b/main.py @@ -0,0 +1,129 @@ +import os +import asyncio +import json +import traceback +from pathlib import Path +from fastapi import FastAPI, UploadFile, File, HTTPException +from fastapi.responses import FileResponse, JSONResponse +from dotenv import load_dotenv + +# Import Agents +from agents.visual_analyst import VisualAnalyst +from agents.memory_agent import MemoryAgent +from agents.writer_agent import WriterAgent + +load_dotenv() + +app = FastAPI() +BASE_DIR = Path(__file__).resolve().parent + +# Initialize Agents +try: + visual_agent = VisualAnalyst() + memory_agent = MemoryAgent() + writer_agent = WriterAgent() + + # Try seeding database, but don't crash if it fails (optional robustness) + try: + memory_agent.seed_database() + except Exception as e: + print(f"āš ļø Memory Agent Seed Warning: {e}") + + print("āœ… All Agents Online") +except Exception as e: + print(f"āŒ Agent Startup Failed: {e}") + # We continue, but endpoints might fail if agents aren't ready. + +@app.get("/") +async def read_root(): + landing_page = BASE_DIR / "landingpage.html" + if not landing_page.exists(): + raise HTTPException(status_code=404, detail="landingpage.html not found") + return FileResponse(landing_page) + + +@app.get("/dashboard") +async def read_dashboard(): + dashboard_page = BASE_DIR / "dashboard.html" + if not dashboard_page.exists(): + raise HTTPException(status_code=404, detail="dashboard.html not found") + return FileResponse(dashboard_page) + +@app.post("/generate-catalog") +async def generate_catalog(file: UploadFile = File(...)): + file_path = None + try: + # 1. Save Temp File + os.makedirs("uploads", exist_ok=True) + file_path = f"uploads/{file.filename}" + with open(file_path, "wb") as f: + f.write(await file.read()) + + # 2. Run AI Pipeline (Sequential) + print("ā–¶ļø Starting Visual Analysis...") + visual_data = await visual_agent.analyze_image(file_path) + + print("ā–¶ļø Retrieving Keywords...") + query = f"{visual_data.get('main_color', '')} {visual_data.get('product_type', 'product')}" + seo_keywords = memory_agent.retrieve_keywords(query) + + # 2b. AI Fallback: Generate keywords if Pinecone returns empty + if not seo_keywords: + print("šŸ¤– Database empty. Using AI Fallback for SEO keywords.") + try: + fallback_prompt = ( + f"The internal keyword database is empty for this product. " + f"Based on these visual features: {json.dumps(visual_data)}, " + f"generate a list of 10 high-converting e-commerce SEO tags " + f"and return them as a JSON array of strings. Return ONLY the JSON array." + ) + fallback_response = visual_agent.client.models.generate_content( + model="gemini-2.5-flash", + contents=fallback_prompt + ) + import re + match = re.search(r'\[.*\]', fallback_response.text, re.DOTALL) + if match: + seo_keywords = json.loads(match.group(0)) + else: + seo_keywords = [tag.strip() for tag in fallback_response.text.split(",") if tag.strip()] + print(f"āœ… AI Fallback generated {len(seo_keywords)} keywords.") + except Exception as fallback_err: + print(f"āš ļø AI Fallback also failed: {fallback_err}") + seo_keywords = [] + + print("ā–¶ļø Writing Listing...") + listing = writer_agent.write_listing(visual_data, seo_keywords) + + # 3. Construct Final Payload + final_data = { + "visual_data": visual_data, + "seo_keywords": seo_keywords, + "listing": listing + } + + return JSONResponse(content=final_data) + + except Exception as e: + error_details = traceback.format_exc() + print(f"āŒ Error in generate-catalog: {e}") + print(error_details) + return JSONResponse( + content={ + "error": "An internal server error occurred.", + "type": type(e).__name__ + }, + status_code=500 + ) + + finally: + # Cleanup + if file_path and os.path.exists(file_path): + try: + os.remove(file_path) + except Exception as cleanup_error: + print(f"āš ļø Cleanup Warning: {cleanup_error}") + +if __name__ == "__main__": + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=7860) diff --git a/projects.json b/projects.json new file mode 100644 index 0000000000000000000000000000000000000000..303b1cb7eaba2c8109e8c51cfabf7e00850e7e3a --- /dev/null +++ b/projects.json @@ -0,0 +1,757 @@ +{ + "projects": [ + { + "createTime": "2026-02-25T18:25:28.653824Z", + "designTheme": { + "colorMode": "DARK", + "customColor": "#7f0df2", + "font": "INTER", + "roundness": "ROUND_EIGHT", + "saturation": 2 + }, + "deviceType": "DESKTOP", + "metadata": { + "userRole": "OWNER" + }, + "name": "projects/13453765122851154258", + "origin": "STITCH", + "projectType": "TEXT_TO_UI_PRO", + "screenInstances": [ + { + "height": 600, + "id": "3a95b353-57ca-4c29-a0e0-ad8398fe3db3", + "sourceScreen": "projects/13453765122851154258/screens/15822672384834121564", + "type": "SCREEN_INSTANCE", + "width": 600 + }, + { + "height": 1024, + "hidden": true, + "id": "8bc0a17301cb44cf9a3905542e09db2b", + "sourceScreen": "projects/13453765122851154258/screens/8bc0a17301cb44cf9a3905542e09db2b", + "width": 1280, + "x": 753, + "y": -163 + }, + { + "height": 1024, + "hidden": true, + "id": "90bae99f55b046049c55926a7da7d787", + "sourceScreen": "projects/13453765122851154258/screens/90bae99f55b046049c55926a7da7d787", + "width": 1280, + "x": 804, + "y": -332 + }, + { + "height": 1024, + "hidden": true, + "id": "bf36d828ed3846cbb6b81f2b44d7e42d", + "sourceScreen": "projects/13453765122851154258/screens/bf36d828ed3846cbb6b81f2b44d7e42d", + "width": 1280, + "x": 664 + }, + { + "height": 1024, + "id": "cf3af7f8a9e74daf85096241ed88c75c", + "isFavourite": true, + "sourceScreen": "projects/13453765122851154258/screens/cf3af7f8a9e74daf85096241ed88c75c", + "width": 1280, + "x": 970, + "y": -179 + } + ], + "thumbnailScreenshot": { + "downloadUrl": "https://lh3.googleusercontent.com/aida/AOfcidVwihSF-Kd8W6zf1x913xCGZ7Wc7ZizpmwOg0SARD0a-Q43pMiPyRmB1fnygdmusXnFA8x_YHU_Y9zfRsj8Lp-Unj12g94PnahnjQufHEuMvdhS3JlJZc8dka2Qi3aty3PLeRGvzTgCL9BlN6Nmip5XZrLP6leo9ZKq-hg5iKfKLr7TaKmnN2WSum1VR9MOrqvuWkI2qMMakkvS2NZHKivzUTXVpmCkGNOMZ-2inEisr2GusRBbBrtyChqO", + "name": "projects/13453765122851154258/files/a19c43fc67b0469fbc1174a000338555" + }, + "title": "StyleSync AI", + "updateTime": "2026-02-25T18:44:08.130497Z", + "visibility": "PRIVATE" + }, + { + "createTime": "2026-02-12T18:28:57.583433Z", + "designTheme": { + "colorMode": "DARK", + "customColor": "#c8f906", + "font": "INTER", + "roundness": "ROUND_FULL", + "saturation": 2 + }, + "deviceType": "MOBILE", + "metadata": { + "userRole": "OWNER" + }, + "name": "projects/14416597482131741463", + "origin": "STITCH", + "projectType": "TEXT_TO_UI_PRO", + "screenInstances": [ + { + "height": 884, + "id": "91dd95e95696415196414912a882c7e7", + "sourceScreen": "projects/14416597482131741463/screens/91dd95e95696415196414912a882c7e7", + "width": 390, + "x": 1344 + }, + { + "height": 884, + "id": "b1053b8349ee4e4992f6cfbc92dab3fc", + "sourceScreen": "projects/14416597482131741463/screens/b1053b8349ee4e4992f6cfbc92dab3fc", + "width": 390 + }, + { + "height": 1324, + "id": "c7aff944733e486d983a63392b7aa65f", + "sourceScreen": "projects/14416597482131741463/screens/c7aff944733e486d983a63392b7aa65f", + "width": 390, + "x": 2252 + }, + { + "height": 2060, + "id": "d2e32096f621489fb0d0a4195928f9f4", + "sourceScreen": "projects/14416597482131741463/screens/d2e32096f621489fb0d0a4195928f9f4", + "width": 390, + "x": 1798 + }, + { + "height": 2035, + "hidden": true, + "id": "ec37f6f67858486198bf9eae665c2825", + "sourceScreen": "projects/14416597482131741463/screens/ec37f6f67858486198bf9eae665c2825", + "width": 390, + "y": 1942 + } + ], + "thumbnailScreenshot": { + "downloadUrl": "https://lh3.googleusercontent.com/aida/AOfcidVZhkC2L9hEo0egk8Y_EN0jF1M1U_xsJU_XBzPtnGnWIxWpCq0qqZvyYEh8cnRo8KB3IQpPkjX2vqxsBWcBm4TOzSaPJgGjK5LFat9ngLGaoMcZLSiUOc3TdC9Rbovm408BEpUWbIl3RASEla-WXi40EJv-ELimBTkuluXvPUwhL99y4Rub1UkfFpxudinWZedCzJ44QJD8VfUKzC-OW_zruNv7L4wxLhzfysunADtKIvfKkJ7-5uEceBY", + "name": "projects/14416597482131741463/files/1dcb6251d53346438730e8fe145924d2" + }, + "title": "House of Nutrition Landing Page", + "updateTime": "2026-02-12T18:40:45.529842Z", + "visibility": "PRIVATE" + }, + { + "createTime": "2026-02-09T17:36:41.806831Z", + "designTheme": { + "colorMode": "DARK", + "customColor": "#2b2bee", + "font": "BE_VIETNAM_PRO", + "roundness": "ROUND_EIGHT", + "saturation": 3 + }, + "deviceType": "MOBILE", + "metadata": { + "userRole": "OWNER" + }, + "name": "projects/14876616641695088904", + "origin": "STITCH", + "projectType": "TEXT_TO_UI_PRO", + "screenInstances": [ + { + "height": 884, + "id": "0403e315651948b28aafcfa4b3b0032c", + "sourceScreen": "projects/14876616641695088904/screens/0403e315651948b28aafcfa4b3b0032c", + "width": 390, + "y": 13089 + }, + { + "height": 884, + "id": "04cd0b2f4ce442d5affc2f5b75b26de3", + "sourceScreen": "projects/14876616641695088904/screens/04cd0b2f4ce442d5affc2f5b75b26de3", + "width": 390, + "x": 454, + "y": 13089 + }, + { + "height": 884, + "id": "0e70c9d66ddf489d8365c61004cca425", + "sourceScreen": "projects/14876616641695088904/screens/0e70c9d66ddf489d8365c61004cca425", + "width": 390, + "y": 19717 + }, + { + "height": 1099, + "id": "1336736c68fd4de09836d79018745afd", + "sourceScreen": "projects/14876616641695088904/screens/1336736c68fd4de09836d79018745afd", + "width": 390, + "y": 15417 + }, + { + "height": 1103, + "id": "1f8518adcc3542efa40b9d7d78681cc4", + "sourceScreen": "projects/14876616641695088904/screens/1f8518adcc3542efa40b9d7d78681cc4", + "width": 390, + "y": 9443 + }, + { + "height": 884, + "id": "24b25983e21f4042a6f42c0eab391114", + "sourceScreen": "projects/14876616641695088904/screens/24b25983e21f4042a6f42c0eab391114", + "width": 390, + "y": 24500 + }, + { + "height": 884, + "id": "2c61cd9c59ed44ceb646fc27e1d6348d", + "sourceScreen": "projects/14876616641695088904/screens/2c61cd9c59ed44ceb646fc27e1d6348d", + "width": 390, + "y": 5189 + }, + { + "height": 1048, + "id": "2d60fa1bc18a4ce7abb89d22a5afc3e6", + "sourceScreen": "projects/14876616641695088904/screens/2d60fa1bc18a4ce7abb89d22a5afc3e6", + "width": 390, + "y": 8139 + }, + { + "height": 1554, + "id": "30d3b1682ceb48aab8c017a887aa33d2", + "sourceScreen": "projects/14876616641695088904/screens/30d3b1682ceb48aab8c017a887aa33d2", + "width": 390, + "y": 6329 + }, + { + "height": 884, + "id": "5524c3f2f11b4e19974c68de88ff0501", + "sourceScreen": "projects/14876616641695088904/screens/5524c3f2f11b4e19974c68de88ff0501", + "width": 390, + "y": 4049 + }, + { + "height": 803, + "id": "5fff4884df894eb599d07ee74e8413e7", + "sourceScreen": "projects/14876616641695088904/screens/5fff4884df894eb599d07ee74e8413e7", + "width": 390, + "x": 908, + "y": 14229 + }, + { + "height": 1266, + "id": "6ae63c719a77450b83d1bd87b642ecfb", + "sourceScreen": "projects/14876616641695088904/screens/6ae63c719a77450b83d1bd87b642ecfb", + "width": 390, + "y": 16772 + }, + { + "height": 799, + "id": "866e1584496f45dc905ea6a347de4da4", + "sourceScreen": "projects/14876616641695088904/screens/866e1584496f45dc905ea6a347de4da4", + "width": 390, + "x": 454, + "y": 28270 + }, + { + "height": 891, + "id": "a664c737e8f546e182c07489ea60edf3", + "sourceScreen": "projects/14876616641695088904/screens/a664c737e8f546e182c07489ea60edf3", + "width": 390, + "y": 11942 + }, + { + "height": 1144, + "id": "aa56e4e88beb4f63b9d9a6634788ede6", + "sourceScreen": "projects/14876616641695088904/screens/aa56e4e88beb4f63b9d9a6634788ede6", + "width": 390, + "y": 2649 + }, + { + "height": 723, + "id": "ae015ad1ae8445da9293c6ca546ed92d", + "sourceScreen": "projects/14876616641695088904/screens/ae015ad1ae8445da9293c6ca546ed92d", + "width": 390, + "x": 454, + "y": 24500 + }, + { + "height": 1133, + "id": "b0132faa7cfb474193b3a035e4143d0d", + "sourceScreen": "projects/14876616641695088904/screens/b0132faa7cfb474193b3a035e4143d0d", + "width": 390, + "y": 23111 + }, + { + "height": 884, + "id": "b358d7f040d04d6180133f56b6914adc", + "sourceScreen": "projects/14876616641695088904/screens/b358d7f040d04d6180133f56b6914adc", + "width": 390, + "y": 25640 + }, + { + "height": 1998, + "id": "b66bbd8e89c043bd9d2c107c3e2c4ce8", + "sourceScreen": "projects/14876616641695088904/screens/b66bbd8e89c043bd9d2c107c3e2c4ce8", + "width": 390, + "y": 20857 + }, + { + "height": 1167, + "id": "bb10a997745c466585024c58ca800275", + "sourceScreen": "projects/14876616641695088904/screens/bb10a997745c466585024c58ca800275", + "width": 390, + "y": 18294 + }, + { + "height": 1234, + "id": "c14aacd0bd5e4d1c86ddf6af3c12a96e", + "sourceScreen": "projects/14876616641695088904/screens/c14aacd0bd5e4d1c86ddf6af3c12a96e", + "width": 390, + "y": 26780 + }, + { + "height": 1129, + "id": "c519daadb8054fed99550cf3e0fde652", + "sourceScreen": "projects/14876616641695088904/screens/c519daadb8054fed99550cf3e0fde652", + "width": 390, + "x": 454, + "y": 16772 + }, + { + "height": 884, + "id": "c6f4b4494ffa49b68d34a27b9e864eaf", + "sourceScreen": "projects/14876616641695088904/screens/c6f4b4494ffa49b68d34a27b9e864eaf", + "width": 390, + "y": 10802 + }, + { + "height": 932, + "id": "cb586b03a673475e9b0dfceef53f8ca6", + "sourceScreen": "projects/14876616641695088904/screens/cb586b03a673475e9b0dfceef53f8ca6", + "width": 390, + "x": 454, + "y": 14229 + }, + { + "height": 1253, + "id": "cfa8fc268bb54eee9f3daa823a2a335d", + "sourceScreen": "projects/14876616641695088904/screens/cfa8fc268bb54eee9f3daa823a2a335d", + "width": 390 + }, + { + "height": 884, + "id": "eee54a4b5b1a4380af6efcd7b12e0bd3", + "sourceScreen": "projects/14876616641695088904/screens/eee54a4b5b1a4380af6efcd7b12e0bd3", + "width": 390, + "y": 28270 + }, + { + "height": 884, + "id": "fa2c9f9ac77d4822b3b601c47e9de473", + "sourceScreen": "projects/14876616641695088904/screens/fa2c9f9ac77d4822b3b601c47e9de473", + "width": 390, + "y": 1509 + }, + { + "height": 884, + "id": "fbf09e340a01431bbdcaca34b039e56d", + "sourceScreen": "projects/14876616641695088904/screens/fbf09e340a01431bbdcaca34b039e56d", + "width": 390, + "y": 14229 + }, + { + "height": 884, + "id": "ffe3420c4dd748c8a130dca9d59979b3", + "sourceScreen": "projects/14876616641695088904/screens/ffe3420c4dd748c8a130dca9d59979b3", + "width": 390, + "x": 454, + "y": 23111 + } + ], + "thumbnailScreenshot": { + "downloadUrl": "https://lh3.googleusercontent.com/aida/AOfcidXd4EgEAE0cVviIP02RhFf-S0B_XyA1Hopm5w2-JY9vGBd17mifrmBlHT1oXWwOflFjPXn8DV8KZBqxMaFTTHniHs8RFBdb2ueceRnYGgeVVO3-0G6K40pelUeStYIBxEEf73oukJjvmPHaciY9-Dg40ysYFwgl7O9eQa5PrCWoub7X1hOGeLQ5yIJe2AhjWIeUwcDmW5CCFVA_QfCwpHwk78eOBPhfllfYXo18cOacHpBlj0BsB7pStfQ4", + "name": "projects/14876616641695088904/files/b1c6390f8db3459e8bd1a5ceaa570f86" + }, + "title": "Aura TV", + "updateTime": "2026-02-09T18:54:15.490610Z", + "visibility": "PRIVATE" + }, + { + "createTime": "2026-02-09T15:29:23.414547Z", + "designTheme": {}, + "metadata": { + "userRole": "OWNER" + }, + "name": "projects/10352760979295925874", + "origin": "STITCH", + "projectType": "PROJECT_DESIGN", + "title": "Draft README.md", + "updateTime": "2026-02-09T15:29:23.414547Z", + "visibility": "PRIVATE" + }, + { + "createTime": "2026-02-07T20:10:39.013135Z", + "designTheme": {}, + "metadata": { + "userRole": "OWNER" + }, + "name": "projects/11474351006747027536", + "origin": "STITCH", + "projectType": "PROJECT_DESIGN", + "title": "Continuity Redis Queue Verification", + "updateTime": "2026-02-07T20:10:39.013135Z", + "visibility": "PRIVATE" + }, + { + "createTime": "2026-01-02T21:37:47.732401Z", + "designTheme": { + "colorMode": "DARK", + "customColor": "#3713ec", + "font": "PLUS_JAKARTA_SANS", + "roundness": "ROUND_FULL", + "saturation": 2 + }, + "deviceType": "DESKTOP", + "metadata": { + "userRole": "OWNER" + }, + "name": "projects/2433657010932190317", + "origin": "STITCH", + "projectType": "TEXT_TO_UI_PRO", + "screenInstances": [ + { + "height": 714, + "id": "511f5d39a22641d49e65bf0c79823f82", + "sourceScreen": "projects/2433657010932190317/screens/511f5d39a22641d49e65bf0c79823f82", + "width": 1280, + "x": 7744 + }, + { + "height": 1024, + "id": "546a9408cf774fddb9e46be1b46465e5", + "sourceScreen": "projects/2433657010932190317/screens/546a9408cf774fddb9e46be1b46465e5", + "width": 1280, + "x": 5056 + }, + { + "height": 731, + "id": "a6d97010b7564a6f8051f63cf898316f", + "sourceScreen": "projects/2433657010932190317/screens/a6d97010b7564a6f8051f63cf898316f", + "width": 1280, + "x": 9088 + }, + { + "height": 714, + "id": "b644533eb2084dea937356b40582bd92", + "sourceScreen": "projects/2433657010932190317/screens/b644533eb2084dea937356b40582bd92", + "width": 1280, + "x": 6400 + }, + { + "height": 714, + "id": "c24b6584df4b4fb18457c47b74010a67", + "sourceScreen": "projects/2433657010932190317/screens/c24b6584df4b4fb18457c47b74010a67", + "width": 1280, + "x": 2368 + }, + { + "height": 714, + "id": "c50847373ed345fbbc29795455754fc5", + "sourceScreen": "projects/2433657010932190317/screens/c50847373ed345fbbc29795455754fc5", + "width": 1280, + "x": 3712 + }, + { + "height": 510, + "id": "d368a2a8-b872-478e-9027-950e819788da", + "sourceScreen": "projects/2433657010932190317/screens/5596238648239871334", + "width": 960 + }, + { + "height": 714, + "id": "fb95def010c2414bb055363bbe15e284", + "sourceScreen": "projects/2433657010932190317/screens/fb95def010c2414bb055363bbe15e284", + "width": 1280, + "x": 1024 + } + ], + "thumbnailScreenshot": { + "downloadUrl": "https://lh3.googleusercontent.com/aida/AOfcidVylXDx3fy-lDIZCKxu93nj5ccLLXs96fgT-kzQ6e3UaIim6EqtjIbaUB4XZKM3PoNA6qUrYpWMJxvQIwjKVBM-qz3UR3FQJwC9Tl76t2iA4vnyhe9ISV3pCAeNhgjrTaC69PpanG_R6aLFBrpujothPlrBRlv2Hg4yeVcJKJXOBMnTdAtLoADQs_XN6iWmf6nL-aK-ZmvGygXBVAWvZcmwRthfEWidd2-AAtX7VcbOo8neHlGbqJJGcb8", + "name": "projects/2433657010932190317/files/f647e84464644998a58c66bd6e5ebcb8" + }, + "title": "Spotify VisionOS Landing Page", + "updateTime": "2026-01-02T21:50:58.053355Z", + "visibility": "PRIVATE" + }, + { + "createTime": "2025-12-26T13:23:42.313267Z", + "designTheme": { + "colorMode": "DARK", + "customColor": "#7f0df2", + "font": "SPACE_GROTESK", + "roundness": "ROUND_EIGHT", + "saturation": 3 + }, + "deviceType": "DESKTOP", + "metadata": { + "userRole": "OWNER" + }, + "name": "projects/1557963788365082774", + "origin": "STITCH", + "projectType": "TEXT_TO_UI_PRO", + "screenInstances": [ + { + "height": 1024, + "id": "8091fb58aba6426d9e2b71ba9a55c2b5", + "sourceScreen": "projects/1557963788365082774/screens/8091fb58aba6426d9e2b71ba9a55c2b5", + "width": 1280 + } + ], + "thumbnailScreenshot": { + "downloadUrl": "https://lh3.googleusercontent.com/aida/AOfcidU6UBSHU6hzJW87gG7gN4j1xOrxZCn7CE6IAT5kIlkT-vEirE-4Tz8ZQRxshEMFYZhuOdDKWTO9Mh5ahuEv-hZbeHdr_QIN-R4TN3uUJu-hdEYUoaazVhGzlE61gSKcX0N2cYh6vMh3N5ZRqhbD3XV3Y9M7aVwYXN9mBxF69C6knKlmG7_c4qWlpMTwYAHPTblffkHs9CEGWJz3sW6VrkIxiSiq5Y_4X8ip8ZPkaa_DgwexB5vnd4Vv2g", + "name": "projects/1557963788365082774/files/6296130a1fe1424286a708b8fc4f8836" + }, + "title": "Continuity Dashboard", + "updateTime": "2025-12-26T13:25:55.556755Z", + "visibility": "PRIVATE" + }, + { + "createTime": "2025-12-13T21:24:48.432473Z", + "designTheme": { + "colorMode": "DARK", + "customColor": "#2bee79", + "font": "SPLINE_SANS", + "roundness": "ROUND_FULL", + "saturation": 3 + }, + "deviceType": "DESKTOP", + "metadata": { + "userRole": "OWNER" + }, + "name": "projects/15558297327625973075", + "origin": "STITCH", + "projectType": "TEXT_TO_UI_PRO", + "screenInstances": [ + { + "height": 1024, + "id": "bca4b7407c584037a859d6c46fe65e5f", + "sourceScreen": "projects/15558297327625973075/screens/bca4b7407c584037a859d6c46fe65e5f", + "width": 1280, + "y": 1280 + }, + { + "height": 1024, + "id": "dbca4b45d36c4ef2a026817001ad8956", + "sourceScreen": "projects/15558297327625973075/screens/dbca4b45d36c4ef2a026817001ad8956", + "width": 1280 + } + ], + "thumbnailScreenshot": { + "downloadUrl": "https://lh3.googleusercontent.com/aida/AOfcidW8yfO5Sx9it1kpgHKj53Z7KlwcijvHU8ZB6yBXvp0GZthaVZG_0kRrvpVtXeFbQDH5vuw6eXaSEDYMrAIETHa2buKF6qXwSGIF6-6fantnZFQqsHrqge07zrapQmalOMukZNtyyoiJfihsr0NzZc0XUkDo5Ez_UyheSzPkJA5_G78cfvDD_telmYCe0iLmm-sSD_eklDtSGnag23a1_k6Eoc7l8F-10W6G5aEV8aojJUQiwg0NDkV0g2Fc", + "name": "projects/15558297327625973075/files/d90f04b5d3ba49ff80dce85cbc68fe13" + }, + "title": "StyleSync AI Dashboard", + "updateTime": "2025-12-13T21:30:52.096705Z", + "visibility": "PRIVATE" + }, + { + "createTime": "2025-12-11T21:10:34.814568Z", + "designTheme": { + "colorMode": "LIGHT", + "customColor": "#f9f506", + "font": "SPLINE_SANS", + "roundness": "ROUND_FULL", + "saturation": 2 + }, + "deviceType": "DESKTOP", + "metadata": { + "userRole": "OWNER" + }, + "name": "projects/9539484857893441782", + "origin": "STITCH", + "projectType": "TEXT_TO_UI_PRO", + "screenInstances": [ + { + "height": 2887, + "id": "0107bc28f352430483e118170bb1fdbb", + "sourceScreen": "projects/9539484857893441782/screens/0107bc28f352430483e118170bb1fdbb", + "width": 1280, + "y": 3331 + }, + { + "height": 2887, + "id": "039d814e16994b74b269ec56cd4e571f", + "sourceScreen": "projects/9539484857893441782/screens/039d814e16994b74b269ec56cd4e571f", + "width": 1280, + "y": 6474 + }, + { + "height": 3075, + "id": "1b5d204b0c6d408fb59acbfa745782dd", + "sourceScreen": "projects/9539484857893441782/screens/1b5d204b0c6d408fb59acbfa745782dd", + "width": 1280, + "x": 2688 + }, + { + "height": 2434, + "id": "30bfd58fb84749c7aa2e643b3b32013c", + "sourceScreen": "projects/9539484857893441782/screens/30bfd58fb84749c7aa2e643b3b32013c", + "width": 1280, + "y": 9617 + }, + { + "height": 3034, + "id": "32031fbc83ec4f13a144b780ccfd4374", + "sourceScreen": "projects/9539484857893441782/screens/32031fbc83ec4f13a144b780ccfd4374", + "width": 1280, + "x": 1344 + }, + { + "height": 2772, + "id": "888eeb71e56745959b7f7d95e411f175", + "sourceScreen": "projects/9539484857893441782/screens/888eeb71e56745959b7f7d95e411f175", + "width": 1280, + "x": 4353, + "y": 151 + }, + { + "height": 1024, + "id": "f1b415128c2e451cabfa94246817abb3", + "sourceScreen": "projects/9539484857893441782/screens/f1b415128c2e451cabfa94246817abb3", + "width": 1280 + }, + { + "height": 1292, + "id": "f8e7509c68df4006b3350d7a1d0b3899", + "sourceScreen": "projects/9539484857893441782/screens/f8e7509c68df4006b3350d7a1d0b3899", + "width": 1280, + "x": 1344, + "y": 9617 + } + ], + "thumbnailScreenshot": { + "downloadUrl": "https://lh3.googleusercontent.com/aida/AOfcidV5UaPSUaP8unPgPTcp447dfmaH3IDeirvDPCWBgzsEVODUniUTEwJu6xRDRRK1dN_FM_6LzQamfaM3nnkrHv4zMnOVMZgRZjKYX_u1IfQNSX0NuAor5dMK-SYTYDI9eDV5PJYqcAg5Qav4mVGtubHGCistED_aWALdKDJxzWyrSn3pfRU2T6l-fbOllVyZ2wVkhm-4dgB9rku44eUo0JsPO5jsbDhTS8_hOScMHHv0gHa4SVvS-pmZ05A", + "name": "projects/9539484857893441782/files/8f860557e03749bc978f10c7a4f9259d" + }, + "title": "Gaurav Vashistha Portfolio", + "updateTime": "2025-12-13T21:23:57.879282Z", + "visibility": "PRIVATE" + }, + { + "createTime": "2025-12-11T21:02:53.053473Z", + "designTheme": { + "colorMode": "LIGHT", + "customColor": "#ea2a33", + "font": "SPLINE_SANS", + "roundness": "ROUND_EIGHT", + "saturation": 3 + }, + "deviceType": "DESKTOP", + "metadata": { + "userRole": "OWNER" + }, + "name": "projects/11685221869984408512", + "origin": "STITCH", + "projectType": "TEXT_TO_UI_PRO", + "screenInstances": [ + { + "height": 1632, + "id": "bbeb9fa35d4e48d8aa7b3f375fbbeac1", + "sourceScreen": "projects/11685221869984408512/screens/bbeb9fa35d4e48d8aa7b3f375fbbeac1", + "width": 1280 + } + ], + "thumbnailScreenshot": { + "downloadUrl": "https://lh3.googleusercontent.com/aida/AOfcidWh5K15vHTueYgyOGbjNg3hLdJA180DqU9UwOGfsbj7HU7Pe_8dVHf_-_5bK_e7IzTp0bOi-d8H6X6Cq4vDbcRWhszLAK5WbvX5KeFBo4oTGAXxx3em2soPB2DehFsComBwxxsi75qtPvLSsROcWW8f_MUe2sxmd57JQnuDCeEHmsZbTtg0o79TdZIXwh_Xb2aVj2a4rGq4dfJj7fRVWESIZz_8w5Js5rEjGrHo88UmcVD1PLfmWCzGiAMQ", + "name": "projects/11685221869984408512/files/2720c714dc0e4a589495246211537a13" + }, + "title": "Developer Portfolio Homepage", + "updateTime": "2025-12-11T21:10:30.140593Z", + "visibility": "PRIVATE" + }, + { + "createTime": "2025-12-11T21:02:07.188345Z", + "designTheme": {}, + "metadata": { + "userRole": "OWNER" + }, + "name": "projects/17495328282521709620", + "origin": "STITCH", + "projectType": "TEXT_TO_UI_PRO", + "updateTime": "2025-12-11T21:02:45.517477Z", + "visibility": "PRIVATE" + }, + { + "createTime": "2025-12-11T14:29:03.451868Z", + "designTheme": { + "colorMode": "DARK", + "customColor": "#13a4ec", + "font": "INTER", + "roundness": "ROUND_EIGHT", + "saturation": 3 + }, + "deviceType": "MOBILE", + "metadata": { + "userRole": "OWNER" + }, + "name": "projects/9585049832339031288", + "origin": "STITCH", + "projectType": "TEXT_TO_UI_PRO", + "screenInstances": [ + { + "height": 698, + "id": "06e18302346d42df87a21e05ea98c96f", + "sourceScreen": "projects/9585049832339031288/screens/06e18302346d42df87a21e05ea98c96f", + "width": 390, + "x": 924, + "y": 961 + }, + { + "height": 698, + "id": "230d6b07a86d4f56bed3de950577a359", + "sourceScreen": "projects/9585049832339031288/screens/230d6b07a86d4f56bed3de950577a359", + "width": 390, + "x": -271, + "y": 947 + }, + { + "height": 698, + "id": "51a0a19b55774b96be22a3c8ecb22a40", + "sourceScreen": "projects/9585049832339031288/screens/51a0a19b55774b96be22a3c8ecb22a40", + "width": 390, + "x": 355, + "y": 947 + }, + { + "height": 698, + "id": "bdb86d1013724984bbcdd822b74d3943", + "sourceScreen": "projects/9585049832339031288/screens/bdb86d1013724984bbcdd822b74d3943", + "width": 390, + "x": -844, + "y": 947 + }, + { + "height": 698, + "id": "bfefda73ab734db889fb3cfe9d455630", + "sourceScreen": "projects/9585049832339031288/screens/bfefda73ab734db889fb3cfe9d455630", + "width": 390, + "y": 1915 + }, + { + "height": 698, + "id": "f239458ea0d64d6d80b331000f1bac19", + "sourceScreen": "projects/9585049832339031288/screens/f239458ea0d64d6d80b331000f1bac19", + "width": 390, + "y": 2869 + } + ], + "thumbnailScreenshot": { + "downloadUrl": "https://lh3.googleusercontent.com/aida/AOfcidUbDNfVurrrfK5SFAKM_HpbQ5N5xodP1S6ZRCUTsgGcspBgrCa6u1R1dDLtInnQdGoVEbM7VYcNwlzmgUHrgNIfl_6kjp3WDJeUmDEJuXmeHyOiIPKJhZQT5Tag-cSlBRAxff8eEGB-nspuG-tGBksYNhV1B_rEDYHWwa9xGAxFS1ITEf3K7bqBoLanqV4h85Len4LRl_k9vWFynfE59-ieQ39nC2uZ5yhsz9Zktxjtvp234ZDjP7NB9H0", + "name": "projects/9585049832339031288/files/c4d1e82e07624ccea55021a120af9cd4" + }, + "title": "Send Files Screen", + "updateTime": "2025-12-11T14:39:48.965873Z", + "visibility": "PRIVATE" + }, + { + "createTime": "2025-12-11T14:28:27.026859Z", + "designTheme": {}, + "metadata": { + "userRole": "OWNER" + }, + "name": "projects/15763750653304082652", + "origin": "STITCH", + "projectType": "TEXT_TO_UI_PRO", + "updateTime": "2025-12-11T14:28:55.770282Z", + "visibility": "PRIVATE" + } + ] +} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..407f8b35a71aa06be5842f666deb5960b1052340 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,14 @@ +fastapi +uvicorn +python-multipart +langchain +langchain-community +langchain-google-genai +langchain-groq +pinecone>=3.0.0 +pydantic +python-dotenv +google-genai +groq +Pillow +huggingface_hub diff --git a/restore_full_brain.py b/restore_full_brain.py new file mode 100644 index 0000000000000000000000000000000000000000..d6d1b2b729d26ad5152deef536fca2cdd66c525c --- /dev/null +++ b/restore_full_brain.py @@ -0,0 +1,122 @@ +import os +import subprocess + +def restore_main(): + content = """import os +from fastapi import FastAPI, UploadFile, File +from fastapi.responses import HTMLResponse, JSONResponse +from dotenv import load_dotenv + +# Import Agents +from agents.visual_analyst import VisualAnalyst +from agents.memory_agent import MemoryAgent +from agents.writer_agent import WriterAgent + +load_dotenv() +app = FastAPI() + +# Initialize All Agents +try: + visual_agent = VisualAnalyst() + memory_agent = MemoryAgent() + writer_agent = WriterAgent() + + # Seed memory on startup + memory_agent.seed_database() + print("āœ… All Agents Online") +except Exception as e: + print(f"āš ļø Warning: Some agents failed to load: {e}") + +# 1. SERVE DASHBOARD AT ROOT +@app.get("/", response_class=HTMLResponse) +async def read_root(): + try: + with open("dashboard.html", "r") as f: + return f.read() + except FileNotFoundError: + return "Error: dashboard.html not found" + +# 2. THE MAIN ORCHESTRATOR ENDPOINT +@app.post("/generate-catalog") +async def generate_catalog(file: UploadFile = File(...)): + try: + # A. Save Temp File + os.makedirs("uploads", exist_ok=True) + file_path = f"uploads/{file.filename}" + with open(file_path, "wb") as f: + f.write(await file.read()) + + # B. Visual Analysis (The Eyes) + visual_data = await visual_agent.analyze_image(file_path) + + # C. Memory Search (The Context) + # Create a search query from visual data + query = f"{visual_data.get('main_color', '')} {visual_data.get('product_type', 'product')}" + seo_keywords = memory_agent.retrieve_keywords(query) + + # D. Write Copy (The Brain) + listing = writer_agent.write_listing(visual_data, seo_keywords) + + # Cleanup + if os.path.exists(file_path): + os.remove(file_path) + + # Return Full Data Structure + return JSONResponse(content={ + "visual_data": visual_data, + "seo_keywords": seo_keywords, + "listing": listing + }) + except Exception as e: + print(f"Error: {e}") + return JSONResponse(content={"error": str(e)}, status_code=500) + +if __name__ == "__main__": + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=7860) +""" + with open("main.py", "w", encoding="utf-8") as f: + f.write(content) + print("āœ… main.py restored with full agent logic.") + +def update_dashboard(): + try: + with open("dashboard.html", "r", encoding="utf-8") as f: + content = f.read() + + # Replace localhost URL with relative path + new_content = content.replace("http://localhost:8000/generate-catalog", "/generate-catalog") + + with open("dashboard.html", "w", encoding="utf-8") as f: + f.write(new_content) + print("āœ… dashboard.html updated for cloud deployment.") + except Exception as e: + print(f"āŒ Error updating dashboard.html: {e}") + +def deploy(): + print("šŸš€ Starting Deployment...") + commands = [ + ["git", "add", "main.py", "dashboard.html"], + ["git", "commit", "-m", "Restore full brain logic and fix dashboard URL"], + ["git", "push", "space", "clean_deploy:main"] + ] + + for cmd in commands: + try: + print(f"Running: {' '.join(cmd)}") + result = subprocess.run(cmd, check=True, capture_output=True, text=True) + print(result.stdout) + except subprocess.CalledProcessError as e: + print(f"āŒ Error running command: {' '.join(cmd)}") + print(e.stderr) + # Don't break on commit error as it might be empty + if "nothing to commit" in e.stderr: + continue + # For other errors we might want to continue or stop, but let's try to proceed + print("āœ… Deployment script finished.") + +if __name__ == "__main__": + print("šŸ”§ Restoring Full Brain...") + restore_main() + update_dashboard() + deploy() diff --git a/results/merch_batch_Coffee_20251214_052033.csv b/results/merch_batch_Coffee_20251214_052033.csv new file mode 100644 index 0000000000000000000000000000000000000000..c1f0a80e0566c43a7d8cb00773880893eb903857 --- /dev/null +++ b/results/merch_batch_Coffee_20251214_052033.csv @@ -0,0 +1,6 @@ +Niche,Slogan,Art Prompt +Coffee,Espresso Patronum.,"Neo-traditional digital illustration: Coffee portafilter emitting a glowing blue steam Patronus. Rich brown, teal, and gold colors. Centered, detailed T-shirt graphic. (23 words)" +Coffee,This Is My Resting Coffee Face.,"**Retro 1970s cartoon T-shirt design, centered.** Grumpy, steaming mug face integrated with bold text. Colors: Espresso, Cream, Burnt Orange. **Vector.**" +Coffee,My Blood Type Is Dark Roast.,"Retro screen print vector. Dripping anatomical heart as a coffee bean. Deep espresso, charcoal, and cream colors. Bold, centered T-shirt design." +Coffee,Humaning Is Hard.,Error generating prompt +Coffee,Powered By Anxiety & Arabica.,Error generating prompt diff --git a/results/merch_batch_Coffee_20251214_052441.csv b/results/merch_batch_Coffee_20251214_052441.csv new file mode 100644 index 0000000000000000000000000000000000000000..7f8381c28fd2d2bda077ce79ead91b3ca8e5f631 --- /dev/null +++ b/results/merch_batch_Coffee_20251214_052441.csv @@ -0,0 +1,6 @@ +Niche,Slogan,Art Prompt +Coffee,Thou Shalt Not Decaf.,"High-contrast woodcut engraving of sacred coffee tablets. Espresso, cream, gold palette. Centered, dramatic lighting. Vector-ready." +Coffee,Pre-Coffee: Danger Zone.,"Mid-Century modern warning sign, centered. Bold text on distressed yellow. Black/crimson palette. Vector, high contrast, coffee bomb symbol." +Coffee,My Blood Type Is Coffee.,"Vintage distressed screen print. IV blood bag filled with coffee, centered. Espresso, cream, and black palette. Typography reads: ""My Blood Type Is Coffee.""" +Coffee,"I'm Not Addicted, I'm Committed.","Retro-vector graphic: Coffee cup with stylized steam waves. Burnt orange, espresso, and cream palette. Centered, bold T-shirt design." +Coffee,Warning: May Talk About Coffee Too Much.,Error generating prompt diff --git a/results/merch_batch_Coffee_20251214_052609.csv b/results/merch_batch_Coffee_20251214_052609.csv new file mode 100644 index 0000000000000000000000000000000000000000..8fcc4073e7a26390e633aa14dadabb47b3061f78 --- /dev/null +++ b/results/merch_batch_Coffee_20251214_052609.csv @@ -0,0 +1,6 @@ +Niche,Slogan,Art Prompt +Coffee,Must Caffeinate to Human.,"Vintage tattoo flash style. Skull morphing into steaming coffee cup, centered. Warm brown, cream, black palette. T-shirt ready graphic." +Coffee,My Blood Type Is Arabica.,Error generating prompt +Coffee,Decaf Is A Conspiracy.,Error generating prompt +Coffee,Powered by Espresso and Anxiety.,Error generating prompt +Coffee,I'll Sleep When The Coffee Runs Out.,Error generating prompt diff --git a/results/merch_batch_Coffee_20251214_052808.csv b/results/merch_batch_Coffee_20251214_052808.csv new file mode 100644 index 0000000000000000000000000000000000000000..4d2451d6353381da86a9c628f569dd0c13971e1b --- /dev/null +++ b/results/merch_batch_Coffee_20251214_052808.csv @@ -0,0 +1,4 @@ +Niche,Slogan,Art Prompt +Coffee,Retro Cat Mom,Error generating prompt +Coffee,Pixel Art Kitty,Error generating prompt +Coffee,Cattitude,Error generating prompt diff --git a/scan_vision_models.py b/scan_vision_models.py new file mode 100644 index 0000000000000000000000000000000000000000..790809b19de08f78ff5c11be4e162a36aa33c9d9 --- /dev/null +++ b/scan_vision_models.py @@ -0,0 +1,44 @@ +import os +import requests +import json +from dotenv import load_dotenv + +load_dotenv() + +api_key = os.getenv("HF_TOKEN") +headers = {"Authorization": f"Bearer {api_key}"} + +candidates = [ + "HuggingFaceM4/idefics2-8b", + "HuggingFaceM4/idefics2-8b-chatty", + "llava-hf/llava-1.5-7b-hf", + "llava-hf/llava-v1.6-mistral-7b-hf", + "microsoft/Phi-3-vision-128k-instruct", + "NousResearch/Nous-Hermes-2-Vision-Alpha", + "OpenGVLab/InternVL-Chat-V1-5", + "Qwen/Qwen2.5-VL-7B-Instruct", + "google/paligemma-3b-mix-224" +] + +print("Scanning for working Serverless Vision Models...\n") + +for model in candidates: + url = f"https://router.huggingface.co/models/{model}" + print(f"Testing: {model}") + try: + # Simple probe payload + response = requests.post(url, headers=headers, json={"inputs": "Hello"}) + if response.status_code == 200: + print(f"āœ… WORKS! {model} (Status: 200)") + print(f"Response: {response.text[:100]}...") + elif response.status_code == 400: + # 400 might mean it Exists but input format is wrong (which is good!) + print(f"āš ļø EXISTS but 400 (Bad Request): {model}") + print(f"Response: {response.text[:100]}...") + elif response.status_code == 404: + print(f"āŒ 404 Not Found: {model}") + else: + print(f"āŒ Error {response.status_code}: {model}") + except Exception as e: + print(f"āŒ Exception: {e}") + print("-" * 30) diff --git a/screen_code.json b/screen_code.json new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/setup_dashboard.py b/setup_dashboard.py new file mode 100644 index 0000000000000000000000000000000000000000..ed1ad7cee2c9fa213197c85aa6569713be718fff --- /dev/null +++ b/setup_dashboard.py @@ -0,0 +1,140 @@ +import re +import os + +def automate_dashboard_setup(): + input_filename = "code.html" + output_filename = "dashboard.html" + + # 1. Check if the source file exists + if not os.path.exists(input_filename): + print(f"āŒ Error: '{input_filename}' not found. Please save your Stitch UI code as '{input_filename}' first.") + return + + print(f"Reading {input_filename}...") + with open(input_filename, "r", encoding="utf-8") as f: + html = f.read() + + # --- Step 1: Inject IDs into the HTML elements --- + + print("Injecting IDs for interactivity...") + + # Inject ID for the Drop Zone & Hidden Input + # We look for the dashed border div that acts as the drop zone + if 'border-dashed' in html: + html = re.sub( + r'(]*border-dashed[^>]*>)', + r'\1\n', + html, count=1 + ) + html = html.replace('border-dashed', 'id="dropZone" border-dashed') + + # Inject ID for the "Browse Files" button + if 'Browse Files' in html: + html = re.sub(r'(]*>)(\s*Browse Files)', r'