import os import re import json import gradio as gr from typing import Dict, List, Optional from openai import OpenAI # إعداد العميل - يمكنك استخدام أي نموذج متوافق مع OpenAI API API_KEY = os.getenv("API_KEY", "") BASE_URL = os.getenv("BASE_URL", "https://api.openai.com/v1") client = OpenAI(api_key=API_KEY, base_url=BASE_URL) if API_KEY else None CSS = """ :root { direction: rtl; } * { font-family: "Tajawal", system-ui, -apple-system, sans-serif; } .gradio-container { direction: rtl; } .app-header { text-align: center; margin: 20px 0; } .app-title { font-size: 24px; font-weight: bold; color: #2D3748; } .app-sub { color: #718096; margin-bottom: 30px; } .result-area { direction: ltr; } """ SYSTEM_PROMPT = """أنت مساعد متخصص في تحويل أوامر Docker إلى قوالب نشر Ghaymah. قم بتحليل أوامر Docker Run أو Docker Compose وأنشئ قالب Ghaymah المناسب. هيكل قالب Ghaymah: { "category": "development|automation|database|etc", "description": "وصف التطبيق", "icon": "IconName", "id": "app-id", "name": "App Name", "resources": [ { "type": "volume", "values": { "name": "data-volume", "size": "{{volumeSize}}", "userId": "{{userId}}" } }, { "type": "app", "values": { "container": { "image": "image:tag" }, "env": { "VARIABLE": "value" }, "name": "app-name", "ports": [{"expose": true, "number": 8080}], "projectId": "{{projectId}}", "publicAccess": { "baseDomain": "hosted.ghaymah.systems", "domain": "auto", "enabled": true }, "resourceTier": "{{resourceTier}}", "storage": { "volumes": [ { "mountPath": "/data", "name": "{{resources[0].uniqueName}}" } ] } } } ], "variables": { "resourceTier": { "default": "t3", "description": "Instance size", "options": ["t1", "t2", "t3", "t4", "t5", "t6", "t7"], "type": "dropdown" }, "volumeSize": { "default": "1Gi", "description": "Volume size", "options": ["512Mi", "1Gi", "2Gi", "5Gi", "10Gi"], "type": "dropdown" } } } Examples { "category": "automation", "description": "n8n workflow automation", "icon": "Zap", "id": "n8n", "name": "n8n", "resources": [ { "type": "volume", "values": { "name": "n8n-data", "size": "{{volumeSize}}", "userId": "{{userId}}" } }, { "type": "app", "values": { "container": { "image": "docker.n8n.io/n8nio/n8n" }, "env": { "EXECUTIONS_DATA_MAX_AGE": "336", "EXECUTIONS_DATA_PRUNE": "true", "N8N_EDITOR_BASE_URL": "https://{{resources[1].uniqueName}}.hosted.ghaymah.systems", "N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS": false, "N8N_HIRING_BANNER_ENABLED": false, "N8N_HOST": "{{resources[1].uniqueName}}.hosted.ghaymah.systems", "N8N_PORT": "5678", "N8N_PROTOCOL": "https", "N8N_PROXY_HOPS": 1, "N8N_TEMPLATES_ENABLED": true, "WEBHOOK_URL": "https://{{resources[1].uniqueName}}.hosted.ghaymah.systems" }, "fsGroup": 1000, "name": "n8n", "ports": [ { "expose": true, "number": 5678 } ], "projectId": "{{projectId}}", "publicAccess": { "baseDomain": "hosted.ghaymah.systems", "domain": "auto", "enabled": true }, "resourceTier": "{{resourceTier}}", "storage": { "volumes": [ { "mountPath": "/home/node", "name": "{{resources[0].uniqueName}}" } ] } } } ], "variables": { "resourceTier": { "default": "t4", "description": "Instance size", "options": [ "t1", "t2", "t3", "t4", "t5", "t6", "t7" ], "type": "dropdown" }, "volumeSize": { "default": "1Gi", "description": "Volume size", "options": [ "512Mi", "1Gi", "2Gi", "5Gi", "10Gi" ], "type": "dropdown" } } } Example 2 { "category": "development", "description": "DocuSeal is an open-source document signing platform", "icon": "Box", "id": "docuseal", "name": "DocuSeal", "resources": [ { "type": "volume", "values": { "name": "docuseal-data", "size": "{{volumeSize}}", "userId": "{{userId}}" } }, { "type": "volume", "values": { "name": "postgres-data", "size": "{{pgVolumeSize}}", "userId": "{{userId}}" } }, { "type": "app", "values": { "container": { "image": "docuseal/docuseal:latest" }, "env": { "DATABASE_URL": "postgresql://postgres:postgres@{{resources[1].uniqueName}}:5432/docuseal", "FORCE_SSL": "{{host}}" }, "name": "docuseal", "ports": [ { "expose": true, "number": 3000 } ], "projectId": "{{projectId}}", "publicAccess": { "baseDomain": "hosted.ghaymah.systems", "domain": "auto", "enabled": true }, "resourceTier": "{{resourceTier}}", "storage": { "volumes": [ { "mountPath": "/data/docuseal", "name": "{{resources[0].uniqueName}}" } ] } } }, { "type": "app", "values": { "container": { "image": "postgres:16" }, "env": { "PGDATA": "/var/lib/postgresql/data/pgdata", "POSTGRES_DB": "docuseal", "POSTGRES_PASSWORD": "postgres", "POSTGRES_USER": "postgres" }, "healthCheck": { "command": [ "CMD-SHELL", "pg_isready -U postgres" ], "interval": 5, "retries": 5, "timeout": 5 }, "name": "postgres", "ports": [ { "expose": false, "number": 5432 } ], "projectId": "{{projectId}}", "publicAccess": { "enabled": false }, "resourceTier": "{{resourceTier}}", "storage": { "volumes": [ { "mountPath": "/var/lib/postgresql/data", "name": "{{resources[1].uniqueName}}" } ] } } } ], "variables": { "host": { "default": "", "description": "Host domain for SSL (leave empty if not using SSL)", "type": "text" }, "pgVolumeSize": { "default": "1Gi", "description": "PostgreSQL data volume size", "options": [ "512Mi", "1Gi", "2Gi", "5Gi", "10Gi" ], "type": "dropdown" }, "resourceTier": { "default": "t3", "description": "Instance size", "options": [ "t1", "t2", "t3", "t4", "t5", "t6", "t7" ], "type": "dropdown" }, "volumeSize": { "default": "2Gi", "description": "DocuSeal data volume size", "options": [ "512Mi", "1Gi", "2Gi", "5Gi", "10Gi" ], "type": "dropdown" } } } Example 3 { "category": "database", "description": "PostgreSQL database server with Hasura GraphQL Engine", "icon": "Database", "id": "postgres-hasura", "name": "Hasura GraphQL", "resources": [ { "type": "volume", "values": { "name": "postgres-data", "size": "{{volumeSize}}", "userId": "{{userId}}" } }, { "type": "app", "values": { "container": { "image": "postgres:{{version}}" }, "env": { "PGDATA": "/var/lib/postgresql/data/pgdata", "POSTGRES_DB": "graphql", "POSTGRES_HOST_AUTH_METHOD": "scram-sha-256", "POSTGRES_INITDB_ARGS": "--auth-host=scram-sha-256 --auth-local=scram-sha-256", "POSTGRES_PASSWORD": "postgres", "POSTGRES_USER": "postgres" }, "fsGroup": 999, "name": "postgres", "ports": [ { "expose": false, "number": 5432 } ], "projectId": "{{projectId}}", "publicAccess": { "enabled": false }, "resourceTier": "{{resourceTier}}", "storage": { "volumes": [ { "mountPath": "/var/lib/postgresql/data", "name": "{{resources[0].uniqueName}}" } ] } } }, { "type": "app", "values": { "container": { "image": "hasura/graphql-engine:latest" }, "env": { "HASURA_GRAPHQL_ADMIN_SECRET": "{{adminSecret}}", "HASURA_GRAPHQL_DATABASE_URL": "postgres://postgres:postgres@{{resources[1].uniqueName}}:5432/graphql", "HASURA_GRAPHQL_DEV_MODE": "true", "HASURA_GRAPHQL_ENABLED_LOG_TYPES": "startup, http-log, webhook-log, websocket-log, query-log", "HASURA_GRAPHQL_ENABLE_CONSOLE": "true" }, "name": "hasura", "ports": [ { "expose": true, "number": 8080 } ], "projectId": "{{projectId}}", "publicAccess": { "baseDomain": "hosted.ghaymah.systems", "domain": "auto", "enabled": true }, "resourceTier": "{{hasuraResourceTier}}" } } ], "variables": { "adminSecret": { "default": "test-secret", "description": "Hasura admin secret", "type": "password" }, "hasuraResourceTier": { "default": "t3", "description": "Hasura instance size", "options": [ "t1", "t2", "t3", "t4", "t5", "t6", "t7" ], "type": "dropdown" }, "resourceTier": { "default": "t3", "description": "PostgreSQL instance size", "options": [ "t1", "t2", "t3", "t4", "t5", "t6", "t7" ], "type": "dropdown" }, "version": { "default": "15", "description": "PostgreSQL version (compatible with Hasura)", "options": [ "12", "13", "14", "15", "16" ], "type": "dropdown" }, "volumeSize": { "default": "200Mi", "description": "Volume size for database storage", "options": [ "200Mi", "500Mi", "1Gi", "2Gi", "5Gi", "10Gi" ], "type": "dropdown" } } } أرجع JSON صالح فقط بدون أي نص إضافي.""" def analyze_docker_command(command: str) -> str: """تحليل أمر Docker باستخدام النموذج اللغوي""" if not client: return json.dumps({ "error": "⚠️ لم يتم تكوين API_KEY. الرجاء إضافة المفتاح في متغيرات البيئة." }, indent=2, ensure_ascii=False) try: response = client.chat.completions.create( model="DeepSeek-Coder", messages=[ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": f"""حول أمر Docker التالي إلى قالب Ghaymah: {command} ملاحظات: - استخدم المنافذ المناسبة - أضف المتغيرات البيئية اللازمة - حدد الفئة المناسبة (development, automation, database, etc) - اختر أيقونة مناسبة من: Box, Database, Server, Code, Zap, Search - تأكد من أن القالب يعمل بشكل صحيح على منصة Ghaymah"""} ], temperature=0.1, max_tokens=2000 ) result = response.choices[0].message.content # محاولة استخراج JSON من الرد json_match = re.search(r'\{.*\}', result, re.DOTALL) if json_match: return json_match.group() else: return result except Exception as e: return json.dumps({ "error": f"فشل في التحليل: {str(e)}" }, indent=2, ensure_ascii=False) def validate_and_format_json(json_str: str) -> str: """التحقق من صحة JSON وتنسيقه""" try: parsed = json.loads(json_str) return json.dumps(parsed, indent=2, ensure_ascii=False) except json.JSONDecodeError: # إذا لم يكن JSON صالحاً، إرجاعه كما هو مع رسالة خطأ return f"⚠️ الناتج ليس JSON صالح:\n\n{json_str}" def process_docker_input(docker_input: str, input_type: str) -> dict: """معالجة إدخال Docker وإرجاع قالب Ghaymah""" if not docker_input.strip(): return {"error": "الرجاء إدخال أمر Docker أو تكوين Docker Compose"} try: if input_type == "docker_run": result = analyze_docker_command(docker_input) else: # docker_compose result = analyze_docker_command(f"docker-compose:\n{docker_input}") # محاولة تحويل الناتج إلى قاموس try: if isinstance(result, str): return json.loads(result) return result except: return {"raw_output": result} except Exception as e: return {"error": f"حدث خطأ: {str(e)}"} # أمثلة للاستخدام DOCKER_RUN_EXAMPLES = [ "docker run -d --name nginx -p 8080:80 nginx:latest", "docker run -it --rm -p 7700:7700 -v $(pwd)/meili_data:/meili_data getmeili/meilisearch:v1.16", "docker run -d --name postgres -p 5432:5432 -e POSTGRES_PASSWORD=mysecretpassword -v pg_data:/var/lib/postgresql/data postgres:15", "docker run -d --name redis -p 6379:6379 -v redis_data:/data redis:7-alpine" ] DOCKER_COMPOSE_EXAMPLES = [ """version: '3.8' services: web: image: nginx:latest ports: - "8080:80" volumes: - ./html:/usr/share/nginx/html db: image: postgres:15 environment: POSTGRES_PASSWORD: mysecretpassword volumes: - pg_data:/var/lib/postgresql/data volumes: pg_data:""", """version: '3' services: app: image: node:18 ports: - "3000:3000" environment: - NODE_ENV=production volumes: - app_data:/app/data volumes: app_data:""" ] # واجهة Gradio with gr.Blocks(title="محول Docker إلى Ghaymah", css=CSS, theme=gr.themes.Soft()) as demo: gr.HTML("""