UNPKG

@guyycodes/plugin-sdk

Version:

AI-powered plugin scaffolding tool - Create full-stack applications with 7+ AI models, 50+ business integrations, and production-ready infrastructure

289 lines (235 loc) • 9.45 kB
// inside the /server/chat folder there exist 1 file: // 1. chat.py const fs = require('fs-extra'); const path = require('path'); const chalk = require('chalk'); async function createEnvConfigFiles(serverPath) { console.log(chalk.blue('šŸ¤– Creating config files...')); // Create agent directory const configPath = path.join(serverPath, 'config'); fs.ensureDirSync(configPath); // Create __init__.py await createEnvInit(configPath); // Create env.py await createEnv(configPath); // Create auth.py await createAuth(configPath); // Create routing.py await createRouting(configPath); // Create utils.py await createUtils(configPath); console.log(chalk.green('āœ… Config files created successfully')); } async function createEnvInit(envPath) { const initPy = `""" Env package for LangGraph chatbot Provides state management and graph execution for the chatbot env """`; fs.writeFileSync(path.join(envPath, '__init__.py'), initPy); } async function createEnv(envPath) { const envPy = `""" Environment Configuration for LangGraph Chatbot Ensures all required environment variables are loaded and available """ import os import sys from typing import Dict, Optional from dotenv import load_dotenv # Load environment variables from .env file load_dotenv() def validate_environment() -> None: """ Validate that all required environment variables are set """ required_vars = [ "OPENAI_API_KEY", "TAVILY_API_KEY", "LANGCHAIN_API_KEY" ] missing_vars = [var for var in required_vars if not os.getenv(var)] if missing_vars: print("āŒ Missing required environment variables:") for var in missing_vars: print(f" - {var}") print("""Please set these environment variables and try again. OpenAi: https://platform.openai.com/docs/api-reference/introduction, Tavily: https://tavily.ai/api, LangChain: https://smith.langchain.com/ to get the API keys.""") sys.stdout.flush() sys.exit(1) # Check optional B2 variables and log their status b2_vars = ["B2_MODEL_BUCKET_ID_API_KEY", "B2_MODEL_BUCKET_API_KEY"] print("šŸ“¦ Checking optional B2 storage variables:") for var in b2_vars: if os.getenv(var): print(f" āœ… {var}: Available") else: print(f" āŒ {var}: Not available") sys.stdout.flush() # Set defaults for optional variables os.environ["LANGCHAIN_TRACING_V2"] = os.getenv("LANGCHAIN_TRACING_V2", "true") os.environ["LANGCHAIN_PROJECT"] = os.getenv("LANGCHAIN_PROJECT", "chatbot-agent") os.environ["LANGCHAIN_ENDPOINT"] = os.getenv("LANGCHAIN_ENDPOINT", "https://api.smith.langchain.com") os.environ["NODE_ENV"] = os.getenv("NODE_ENV", "development") os.environ["PORT"] = os.getenv("PORT", "3000") def get_environment_info() -> Dict[str, Optional[str]]: """ Get environment configuration for display """ return { "NODE_ENV": os.getenv("NODE_ENV"), "PORT": os.getenv("PORT"), "LANGCHAIN_TRACING_V2": os.getenv("LANGCHAIN_TRACING_V2"), "LANGCHAIN_PROJECT": os.getenv("LANGCHAIN_PROJECT"), "LANGCHAIN_ENDPOINT": os.getenv("LANGCHAIN_ENDPOINT"), "REDIS_URI": os.getenv("REDIS_URI"), "POSTGRES_URI": os.getenv("POSTGRES_URI"), # Don't expose API keys for security "OPENAI_API_KEY": "āœ… Set" if os.getenv("OPENAI_API_KEY") else "āŒ Missing", "TAVILY_API_KEY": "āœ… Set" if os.getenv("TAVILY_API_KEY") else "āŒ Missing", "LANGCHAIN_API_KEY": "āœ… Set" if os.getenv("LANGCHAIN_API_KEY") else "āŒ Missing", # Optional B2 storage variables "B2_MODEL_BUCKET_ID_API_KEY": "āœ… Set" if os.getenv("B2_MODEL_BUCKET_ID_API_KEY") else "āŒ Not available", "B2_MODEL_BUCKET_API_KEY": "āœ… Set" if os.getenv("B2_MODEL_BUCKET_API_KEY") else "āŒ Not available", } `; fs.writeFileSync(path.join(envPath, 'env.py'), envPy); } async function createAuth(configPath) { const authPy = ` \# Simple API key authentication for development from typing import Optional \# Development API keys - in production, these should be stored securely VALID_API_KEYS = [ "pk_dev_7f8a9b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a", "pk_test_3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f", "pk_demo_9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b" ] def validate_api_key(api_key: Optional[str]) -> bool: """ Validate if the provided API key is valid Args: api_key: The API key to validate Returns: bool: True if valid, False otherwise """ if not api_key: return False return api_key in VALID_API_KEYS def get_api_key_from_headers(headers) -> Optional[str]: """ Extract API key from request headers Args: headers: Request headers Returns: Optional[str]: API key if found, None otherwise """ return headers.get("X-API-Key") or headers.get("x-api-key") `; fs.writeFileSync(path.join(configPath, 'auth.py'), authPy); } async function createRouting(configPath) { const routingPy = ` from fastapi import HTTPException, Request from typing import Tuple from .auth import validate_api_key, get_api_key_from_headers def parse_and_validate_request(request: Request) -> Tuple[str, str]: """ Parse X-Method-Endpoint header and validate API key authentication Args: request: FastAPI Request object Returns: Tuple[str, str]: (method, endpoint) parsed from header Raises: HTTPException: If header is missing, invalid, or API key is invalid """ \# Get method endpoint from header method_endpoint = request.headers.get("X-Method-Endpoint", "") actual_method = request.method \# Log incoming request for debugging print(f"\\nšŸ” Incoming request:") print(f" Actual Method: {actual_method}") print(f" URL: {request.url}") print(f" X-Method-Endpoint: {method_endpoint}") print(f" X-Backend-Service: {request.headers.get('X-Backend-Service', 'Not provided')}") print(f" X-Support-GPU: {request.headers.get('X-Support-GPU', 'Not provided')}") print(f" X-API-Key: {'[PROVIDED]' if request.headers.get('X-API-Key') else 'Not provided'}") print(f" Content-Type: {request.headers.get('Content-Type', 'Not provided')}") \# Validate method endpoint header exists if not method_endpoint: print(f"āŒ Missing X-Method-Endpoint header") raise HTTPException(status_code=400, detail="Missing X-Method-Endpoint header") \# Parse the header try: method, endpoint = method_endpoint.split(":", 1) print(f" Parsed: Method={method}, Endpoint={endpoint}") except ValueError: print(f"āŒ Invalid X-Method-Endpoint format: {method_endpoint}") raise HTTPException(status_code=400, detail="Invalid X-Method-Endpoint format. Expected 'METHOD:endpoint'") \# API Key validation (skip for health check) if endpoint != "/health": api_key = get_api_key_from_headers(request.headers) if not validate_api_key(api_key): print(f"āŒ Invalid or missing API key") raise HTTPException( status_code=401, detail="Invalid or missing API key. Please provide a valid API Key." ) print(f"āœ… API key validated successfully") return method, endpoint `; fs.writeFileSync(path.join(configPath, 'routing.py'), routingPy); } async function createUtils(configPath) { const utilsPy = ` """ Config utilities for reading app.config.json """ import json from pathlib import Path from typing import Optional def get_environment() -> str: """Get environment setting from app.config.json Returns: str: The environment value from config, defaults to 'localhost' """ try: # Find app.config.json by going up the directory tree current_dir = Path(__file__).parent while current_dir != current_dir.parent: config_file = current_dir / "app.config.json" if config_file.exists(): with open(config_file, 'r') as f: config = json.load(f) return config.get("environment", "localhost") current_dir = current_dir.parent # If not found, default to localhost return "localhost" except Exception as e: print(f"Warning: Could not read app.config.json: {e}") return "localhost" def get_app_config() -> Optional[dict]: """Get the full app.config.json configuration Returns: dict: The full config object, or None if not found """ try: current_dir = Path(__file__).parent while current_dir != current_dir.parent: config_file = current_dir / "app.config.json" if config_file.exists(): with open(config_file, 'r') as f: return json.load(f) current_dir = current_dir.parent return None except Exception: return None `; fs.writeFileSync(path.join(configPath, 'utils.py'), utilsPy); } module.exports = { createEnvConfigFiles, createEnvInit, createEnv }