72832f4ef2259d5c0fb3513e6af528220387435e

#1
by sky-meilin - opened
This view is limited to 50 files because it contains too many changes. See the raw diff here.
Files changed (50) hide show
  1. Docker +0 -11
  2. README.md +6 -63
  3. SKYOS_BLUEPRINT_PHASE_1.md +18 -16
  4. agency_core.py +0 -176
  5. app.py +23 -80
  6. audio_core.py +0 -16
  7. code_runner.py +16 -36
  8. core/chunker.py +9 -8
  9. core/cleaner.py +8 -10
  10. core/deepseek.py +2 -2
  11. core/embeddings.py +2 -11
  12. core/hermes.py +2 -2
  13. core/joyai.py +2 -2
  14. core/loader.py +24 -22
  15. core/orchestrator.py +68 -31
  16. core/router.py +1 -15
  17. crm_core.py +7 -39
  18. extractor.py +14 -26
  19. fanvue_guide.py +3 -18
  20. mcp_server.py +10 -40
  21. modules/adapters/base_adapter.py +0 -33
  22. modules/adapters/huggingface_adapter.py +0 -154
  23. modules/adapters/init.py +0 -24
  24. modules/adapters/sheets_adapter.py +0 -175
  25. modules/avatar_streamer.py +24 -23
  26. modules/creator_os.py +4 -15
  27. modules/crypto_engine.py +29 -14
  28. modules/dashboard/__init__.py +0 -112
  29. modules/dashboard/chat_panel.py +0 -41
  30. modules/dashboard/config.py +0 -97
  31. modules/dashboard/dashboard.py +0 -74
  32. modules/dashboard/event_handler.py +0 -184
  33. modules/dashboard/header.py +0 -113
  34. modules/dashboard/icons.py +0 -114
  35. modules/dashboard/navigation_panel.py +0 -53
  36. modules/dashboard/status_panel.py +0 -78
  37. modules/dashboard/theme.py +0 -66
  38. modules/dashboard/utils.py +0 -91
  39. modules/fanvue_guide.py +4 -4
  40. modules/google/__init__.py +0 -42
  41. modules/google/auth.py +0 -126
  42. modules/google/calendar_gateway.py +0 -166
  43. modules/google/config.py +0 -121
  44. modules/google/discovery.py +0 -110
  45. modules/google/docs_gateway.py +0 -154
  46. modules/google/drive_gateway.py +0 -57
  47. modules/google/gmail_gateway.py +0 -162
  48. modules/google/oauth.py +0 -117
  49. modules/google/utils.py +0 -130
  50. modules/remote_control.py +30 -17
Docker DELETED
@@ -1,11 +0,0 @@
1
- docker run -it -p 7860:7860 --platform=linux/amd64 \
2
- -e HF_READ_TOKEN="YOUR_VALUE_HERE" \
3
- -e HF_TOKEN="YOUR_VALUE_HERE" \
4
- -e WP_APP_PASSWORD="YOUR_VALUE_HERE" \
5
- -e DIGITAL_PRODUCT_CSV_URL="https://docs.google.com/spreadsheets/d/1ARXP9Oh5dp0uS0N09ymGJMDsLaAbzcWihb-jaaUwIuI/export?format=csv&gid=2026061006" \
6
- -e DEEPSEEK_MEMORY_CSV_URL="https://docs.google.com/spreadsheets/d/14XwhyeMxZJbEKUcWfa4_D4fajnzMTgoblVz4lTXFRpE/export?format=csv&gid=419179114" \
7
- -e DEFAULT_LANGUAGE="de" \
8
- -e APP_ENV="production" \
9
- -e WORDPRESS_AUTH_MODE="mcp" \
10
- -e WORDPRESS_MCP_URL="https://public-api.wordpress.com/wpcom/v2/mcp/v1" \
11
- registry.hf.space/sky-meilin-skyosfullcore:cpu-0040161-9lwc09te python app.py
 
 
 
 
 
 
 
 
 
 
 
 
README.md CHANGED
@@ -1,70 +1,13 @@
1
  ---
2
  title: SkyOSFullCore
3
- emoji: 🌌
4
- colorFrom: blue
5
- colorTo: indigo
6
  sdk: gradio
7
- sdk_version: 6.19.0
 
8
  app_file: app.py
9
  pinned: false
10
  ---
11
 
12
- # SkyOS Universal Control Center & Creator OS
13
- **Version:** `skyos_v3_core_2026_06_28`
14
- **Plattform-Kompatibilität:** Optimiert für Android 15 (Redmi 13) & Hugging Face Spaces Runtime
15
-
16
- ---
17
-
18
- ## 🏢 System-Architektur
19
-
20
- SkyOS ist ein modular aufgebautes Betriebssystem zur Automatisierung von Agentur-Prozessen, Lead-Verarbeitung, Trend-Vorhersagen und Content-Infrastrukturen. Die Architektur trennt strikt die Benutzeroberfläche von der Verarbeitungslogik und den Daten-Gateways.
21
-
22
- ### 📁 Modul-Übersicht
23
-
24
- * **`app.py` (v3_audio):** Das zentrale Steuerpult. Eine schlanke Gradio-Oberfläche, die vollständig dynamisch geladen wird und sowohl Textbefehle als auch native Audio-Direktaufnahmen verarbeitet.
25
- * **`agency_core.py`:** Die Single Source of Truth für das Agentur-Grid. Verwaltet 15 Fachabteilungen, aufgeteilt in 5 strategische Cluster. Jede Abteilung entspricht einer isolierten Location (Tabellenplatz) im Google Sheets Backend.
26
- * **`audio_core.py`:** Das Sprachverarbeitungs-Modul. Verarbeitet `.wav`/`.mp3`-Streams aus dem UI-Mikrofon, transkribiert diese über Whisper und speist die Text-Intents direkt in den Core-Router ein.
27
- * **`router.py`:** Nimmt universale Befehle entgegen, validiert System-Status und verteilt die Aufgaben an die Sub-Module. Enthält eine abgesicherte Fehlerbehandlung (`safe_status_query`), um JSON-Parse-Fehler im Frontend zu verhindern.
28
- * **`extractor.py` / `crm_core.py`:** Analysiert eingehende Nachrichten auf Intents, extrahiert Kontakt- und Prioritätsdaten für die Lead-Pipeline.
29
- * **`trend_predictor.py`:** Mathematische Engine zur Berechnung des *Virality Index* basierend auf Share-Rate, Interaktionstiefe, Hook-Stärke und Marktsättigung.
30
- * **`worklog.py`:** Protokolliert jede System-Aktion im JSONL-Stream zur lückenlosen Diagnose.
31
- * **`sheets_gateway.py`:** Die Schnittstelle zur persistenten Live-Datenbank (`best_practice`), die Änderungen direkt in das korrespondierende Tabellenblatt einträgt.
32
-
33
- ---
34
-
35
- ## 🗂️ Multidimensionales Agentur-Grid
36
-
37
- Die Zuweisung und Speicherung erfolgt automatisiert über die in `agency_core.py` definierten Cluster und deren Tabellenplätze:
38
-
39
- ### 1. Management & Operations
40
- * **Executive Leadership (CEO, Managing Director):** `executive_leadership`
41
- * **Operations / Administration (HR, Finance, Legal):** `operations_admin`
42
- * **Project Management:** `project_management`
43
-
44
- ### 2. Client & Strategy
45
- * **Account Management / Client Services:** `account_management`
46
- * **Strategy & Planning:** `strategy_planning`
47
-
48
- ### 3. Creation & Content
49
- * **Creative Department (Design, Copywriting):** `creative_department`
50
- * **Content Marketing:** `content_marketing`
51
- * **Social Media Management:** `social_media`
52
- * **Community Management:** `community_management`
53
-
54
- ### 4. Technical & Performance Marketing
55
- * **SEO / Technical SEO:** `seo_technical`
56
- * **Paid Media / PPC:** `paid_media`
57
- * **Media Buying:** `media_buying`
58
- * **Email Marketing:** `email_marketing`
59
-
60
- ### 5. Tech & Data
61
- * **Development / Engineering / Web Development:** `development_engineering`
62
- * **Analytics & Data / Business Intelligence:** `analytics_bi`
63
-
64
- ---
65
-
66
- ## 🚀 Installation & Start
67
-
68
- ### Voraussetzungen
69
- ```bash
70
- pip install gradio openai-whisper
 
1
  ---
2
  title: SkyOSFullCore
3
+ emoji: 👁
4
+ colorFrom: gray
5
+ colorTo: blue
6
  sdk: gradio
7
+ sdk_version: 6.14.0
8
+ python_version: '3.13'
9
  app_file: app.py
10
  pinned: false
11
  ---
12
 
13
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
SKYOS_BLUEPRINT_PHASE_1.md CHANGED
@@ -1,22 +1,24 @@
1
- # Sky - Die Lösung: Phase 1 - Ökosystem-Setup Blueprint
2
 
3
  ## 1. Startpunkt für die Verbindungen festlegen (Der Gateway)
4
- * **Komponente:** Layer 1: Hugging Face Space (Gradio UI & Core Engine).
5
- * **Rolle:** Zentrale Steuereinheit und Schnittstelle.
6
- * **Funktion:** Verarbeitet alle eingehenden Anfragen (z. B. via Webhooks von Telegram, WordPress oder Zapier) direkt im Space.
7
- * **Aktion:** `app.py` als primären API-Endpoint und Interface definieren.
8
 
9
  ## 2. API bereitstellen (Die Proprietäre Schnittstelle)
10
- * **Public/Private Routing:**
11
- * Der `SkyOrchestrator` fängt Anfragen ab und routet sie intern an die spezifischen Module (`hermes`, `deepseek`, `joyai`).
12
- * Der `router_publish.py` übernimmt die direkte, gesicherte Kommunikation mit externen APIs (WordPress MCP, Telegram).
13
- * **IP-Schutz:** Die Logik und die Prompts werden innerhalb des privaten Hugging Face Spaces gekapselt. Die sensiblen Endpunkte und Keys werden ausschließlich über geschützte Umgebungsvariablen (Secrets) im Container geladen.
 
 
14
 
15
  ## 3. Daten einspeisen (Context Injection)
16
- * **Datenquelle:** 200 Assets des generischen KI-Influencer-Assets (gestreamt via Google Sheets CSV-URLs und Hugging Face Datasets).
17
- * **Format:** Strukturierte Metadaten und bereinigte Kontext-Vektoren (durchgeführt via `cleaner.py`, `chunker.py` und `embeddings.py`).
18
- * **Integration:** Die extrahierten Chunks bilden den **"Context Injection"**-Teil des internen Workflows:
19
- 1. **Base Prompt Template:** System-Anweisungen für die Persona.
20
- 2. **Context Injection:** Dynamisch geladene Chunks der 200 Assets (z. B. aus dem Contentplan, Fanvue-Guide oder den Produkt-Tabellen).
21
- 3. **Style Transfer Layer:** Anpassung des Outputs an das gewünschte Ziel-Format (z. B. WordPress-Post, Telegram-Nachricht).
22
- * **Ziel:** Maximale Relevanz ohne Kontext-Overhead zur Vorbereitung des Custom Model Fine-tunings für den unfairen Vorteil.
 
1
+ Kann meine Nummer# Sky - Die Lösung: Phase 1 - Ökosystem-Setup Blueprint
2
 
3
  ## 1. Startpunkt für die Verbindungen festlegen (Der Gateway)
4
+ - **Komponente:** Layer 2: Firebase Functions (Backend Logic).
5
+ - **Rolle:** Unüberwindbarer Gateway und zentrale Schleuse.
6
+ - **Funktion:** Alle Anfragen vom Hugging Face Space (Layer 1) werden an einen verschlüsselten Firebase Endpoint gesendet.
7
+ - **Aktion:** Firebase Function als Haupt-API-Endpoint definieren.
8
 
9
  ## 2. API bereitstellen (Die Proprietäre Schnittstelle)
10
+ - **Public API (Layer 1 zu Layer 2):**
11
+ - Gradio App konfiguriert, um Benutzeranfrage via **HTTP POST** an den Firebase Function Endpoint zu senden.
12
+ - **Private API (Layer 2 zu Layer 3):**
13
+ - Firebase führt **Validierungen** durch (Rate Limiting, Usage Tracking).
14
+ - Ruft die **Layer 3: Core Logic** auf (Proprietary Prompt Engineering).
15
+ - **IP-Schutz:** Sicherstellen, dass Layer 3 nur **intern** von Firebase aufgerufen werden kann und die eigentliche Logik niemals exponiert wird.
16
 
17
  ## 3. Daten einspeisen (Context Injection)
18
+ - **Datenquelle:** 200 Assets des generischen KI-Influencer-Assets.
19
+ - **Format:** Strukturierte Metadaten und Kontext-Vektoren.
20
+ - **Integration:** Die Vektoren bilden den **"Context Injection"**-Teil des internen Workflows:
21
+ 1. Base Prompt Template
22
+ 2. Context Injection (Deine 200 Assets)
23
+ 3. Style Transfer Layer
24
+ - **Ziel:** Optimales Informieren des Custom Model Fine-tunings für den unfairen Vorteil.
agency_core.py DELETED
@@ -1,176 +0,0 @@
1
- """
2
- agency_core.py
3
- SkyOS Agency Architecture Core
4
- Version: skyos_agency_core_v1_2026_06_28
5
- Verwaltet die Abteilungsstrukturen, Rollen-Mappings und Berechtigungen separat von app.py.
6
- """
7
-
8
- from __future__ import annotations
9
- from typing import Any, Dict, List, Optional
10
-
11
- AGENCY_CORE_VERSION = "skyos_agency_core_v1_2026_06_28"
12
-
13
- # Definition der exakten Abteilungsstruktur (Single Source of Truth)
14
- DEPARTMENTS: Dict[str, Dict[str, Any]] = {
15
- "executive_leadership": {
16
- "name": "Executive Leadership (CEO, Managing Director)",
17
- "cluster": "Management & Operations",
18
- "description": "Gesamtstrategie, Vision, Skalierung und finale Freigaben.",
19
- "allowed_routers": ["router.py", "router_publish.py"]
20
- },
21
- "account_management": {
22
- "name": "Account Management / Client Services",
23
- "cluster": "Client & Strategy",
24
- "description": "Kundenbetreuung, Onboarding, Upselling und primäre Schnittstelle für Leads.",
25
- "allowed_routers": ["router.py"]
26
- },
27
- "strategy_planning": {
28
- "name": "Strategy & Planning",
29
- "cluster": "Client & Strategy",
30
- "description": "Konzeption, Marktanalysen, Zielgruppendefinition und Kampagnenausrichtung.",
31
- "allowed_routers": ["router.py"]
32
- },
33
- "creative_department": {
34
- "name": "Creative Department (Design, Copywriting)",
35
- "cluster": "Creation & Content",
36
- "description": "Visuelle Assets, Werbetexte, Branding, Layouts und Skripte.",
37
- "allowed_routers": ["router.py"]
38
- },
39
- "content_marketing": {
40
- "name": "Content Marketing",
41
- "cluster": "Creation & Content",
42
- "description": "Langfristige Content-Strategien, Blog-Artikel, Whitepaper und SEO-Inhalte.",
43
- "allowed_routers": ["router.py"]
44
- },
45
- "seo_technical": {
46
- "name": "SEO / Technical SEO",
47
- "cluster": "Technical & Performance Marketing",
48
- "description": "Organische Reichweite, OnPage-/OffPage-Optimierung, Core Web Vitals.",
49
- "allowed_routers": ["router.py"]
50
- },
51
- "paid_media": {
52
- "name": "Paid Media / PPC",
53
- "cluster": "Technical & Performance Marketing",
54
- "description": "Bezahlte Werbekampagnen auf Google Ads, Meta Ads, TikTok Ads.",
55
- "allowed_routers": ["router.py"]
56
- },
57
- "social_media": {
58
- "name": "Social Media Management",
59
- "cluster": "Creation & Content",
60
- "description": "Kanalkuration, Redaktionspläne, Posting-Taktung (TikTok, Instagram).",
61
- "allowed_routers": ["router.py", "router_publish.py"]
62
- },
63
- "email_marketing": {
64
- "name": "Email Marketing",
65
- "cluster": "Technical & Performance Marketing",
66
- "description": "Newsletter, automatisierte E-Mail-Funnel, Lead-Nurturing.",
67
- "allowed_routers": ["router.py"]
68
- },
69
- "analytics_bi": {
70
- "name": "Analytics & Data / Business Intelligence",
71
- "cluster": "Tech & Data",
72
- "description": "Tracking-Infrastruktur, Live-Dashboards, ROI-Berechnung.",
73
- "allowed_routers": ["router.py"]
74
- },
75
- "development_engineering": {
76
- "name": "Development / Engineering / Web Development",
77
- "cluster": "Tech & Data",
78
- "description": "WordPress-Setups, API-Anbindungen, SkyOS Core-Entwicklung.",
79
- "allowed_routers": ["router.py", "router_publish.py"]
80
- },
81
- "operations_admin": {
82
- "name": "Operations / Administration (HR, Finance, Legal)",
83
- "cluster": "Management & Operations",
84
- "description": "Verträge, Rechnungsstellung, HR-Prozesse, interne Compliance.",
85
- "allowed_routers": ["router.py"]
86
- },
87
- "media_buying": {
88
- "name": "Media Buying",
89
- "cluster": "Technical & Performance Marketing",
90
- "description": "Einkauf von Werbeplätzen, Budget-Verwaltung, Verhandlungen.",
91
- "allowed_routers": ["router.py"]
92
- },
93
- "community_management": {
94
- "name": "Community Management",
95
- "cluster": "Creation & Content",
96
- "description": "Interaktion mit Followern, Kommentar-Moderation, DM-Automations.",
97
- "allowed_routers": ["router.py"]
98
- },
99
- "project_management": {
100
- "name": "Project Management",
101
- "cluster": "Management & Operations",
102
- "description": "Terminplanung, Ressourcenverteilung, Task-Monitoring.",
103
- "allowed_routers": ["router.py"]
104
- }
105
- }
106
-
107
-
108
- def get_agency_status() -> Dict[str, Any]:
109
- """Gibt den Status und die Version des Agency-Moduls zurück."""
110
- return {
111
- "module": "agency_core",
112
- "version": AGENCY_CORE_VERSION,
113
- "status": "active",
114
- "department_count": len(DEPARTMENTS)
115
- }
116
-
117
-
118
- def get_department_details(dept_key: str) -> Optional[Dict[str, Any]]:
119
- """Holt die Metadaten einer spezifischen Abteilung über ihren System-Key."""
120
- return DEPARTMENTS.get(str(dept_key or "").lower().strip(), None)
121
-
122
-
123
- def get_departments_by_cluster(cluster_name: str) -> List[Dict[str, Any]]:
124
- """Filtert alle Abteilungen, die zu einem bestimmten Cluster gehören."""
125
- target_cluster = str(cluster_name or "").lower().strip()
126
- result = []
127
- for _, data in DEPARTMENTS.items():
128
- if target_cluster in data["cluster"].lower():
129
- result.append(data)
130
- return result
131
-
132
-
133
- def route_task_to_department(task_description: str) -> Dict[str, Any]:
134
- """
135
- Heuristische Intent-Erkennung, um eine Aufgabe automatisch
136
- der passenden Abteilung zuzuweisen.
137
- """
138
- text = str(task_description or "").lower().strip()
139
-
140
- if any(w in text for w in ["code", "bug", "api", "server", "datenbank", "plugin", "wordpress"]):
141
- dept = "development_engineering"
142
- elif any(w in text for w in ["rechnung", "vertrag", "geld", "finance", "legal", "mitarbeiter"]):
143
- dept = "operations_admin"
144
- elif any(w in text for w in ["seo", "keywords", "ranking", "search", "vitals"]):
145
- dept = "seo_technical"
146
- elif any(w in text for w in ["ads", "ppc", "google ads", "meta ads", "kampagne"]):
147
- dept = "paid_media"
148
- elif any(w in text for w in ["newsletter", "mail", "funnel", "automation"]):
149
- dept = "email_marketing"
150
- elif any(w in text for w in ["tracking", "dashboard", "analytics", "daten", "report"]):
151
- dept = "analytics_bi"
152
- elif any(w in text for w in ["design", "logo", "copy", "texten", "werbetext", "grafik"]):
153
- dept = "creative_department"
154
- elif any(w in text for w in ["posting", "instagram", "tiktok", "reel", "shorts", "planen"]):
155
- dept = "social_media"
156
- elif any(w in text for w in ["kommentar", "dm", "nachricht", "interaktion", "community"]):
157
- dept = "community_management"
158
- elif any(w in text for w in ["termin", "deadline", "zeitplan", "board", "task"]):
159
- dept = "project_management"
160
- elif any(w in text for w in ["kunde", "onboarding", "absprache", "call"]):
161
- dept = "account_management"
162
- elif any(w in text for w in ["strategie", "analyse", "ausrichtung", "konzept"]):
163
- dept = "strategy_planning"
164
- else:
165
- dept = "project_management" # Default-Fallback
166
-
167
- return {
168
- "status": "assigned",
169
- "assigned_department_key": dept,
170
- "department_name": DEPARTMENTS[dept]["name"],
171
- "cluster": DEPARTMENTS[dept]["cluster"]
172
- }
173
-
174
-
175
- if __name__ == "__main__":
176
- print(get_agency_status())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app.py CHANGED
@@ -1,89 +1,32 @@
1
- """
2
- app.py
3
- SkyOS Dashboard Control Center – Simple Studio Edition
4
- Komplett fokussiert auf Streaming, Chat & Direktnavigation
5
- """
6
-
7
  import gradio as gr
8
- from datetime import datetime
9
- import zoneinfo
10
- from persona_sky_meilin import (
11
- AVATAR_PERSONA, AVATAR_JOBTITEL, COMPANY_NAME, SYSTEM_NAME,
12
- LIGHTING_PROFILES, MATERIAL_PROFILES, build_studio_manifest
13
- )
14
-
15
- try:
16
- from modules.avatar_streamer import AvatarStreamer
17
- streamer = AvatarStreamer()
18
- streamer.set_avatar(AVATAR_PERSONA)
19
- AVATAR_READY = True
20
- except Exception as e:
21
- AVATAR_READY = False
22
-
23
- tz_berlin = zoneinfo.ZoneInfo("Europe/Berlin")
24
 
25
- def handle_interaction(text, audio, lighting, material):
26
- if not AVATAR_READY:
27
- return "Eingabe registriert. Render-Pipeline wird vorbereitet.", None
28
-
29
- # Nutzt Text-Eingabe, fällt auf Audio-Verarbeitung zurück, falls Text leer ist
30
- input_source = text if text else "Sprachbefehl verarbeitet."
31
- manifest = build_studio_manifest(input_source, lighting, material)
32
-
33
- streamer.start_stream()
34
- streamer.send_message(f"Execute: {manifest}")
35
-
36
- response = "Ich starte das Live-Streaming mit den gewünschten visuellen Anpassungen."
37
- return [(input_source, response)], None
38
 
39
- with gr.Blocks(theme=gr.themes.Soft(), title=f"{SYSTEM_NAME} Dashboard") as demo:
40
-
41
- # ================= HEADER =================
42
- with gr.Row():
43
- gr.Markdown(f"# 🌌 {SYSTEM_NAME} – {AVATAR_PERSONA} Studio")
44
 
45
- # ================= CORE INTERFACE =================
46
- with gr.Row():
47
- # Linke Spalte: Streaming-Fenster (9:16)
48
- with gr.Column(scale=1):
49
- avatar_video_output = gr.Video(
50
- label="Studio Stream (9:16)",
51
- interactive=False
52
- )
53
-
54
- # Rechte Spalte: Chat & Steuerung
55
- with gr.Column(scale=2):
56
- chat_feed = gr.Chatbot(label="Chat-Interface (Aktiv wenn kein Stream)")
57
-
58
- with gr.Row():
59
- msg_input = gr.Textbox(placeholder="Nachricht oder Skript eingeben...", label="Texteingabe", scale=3)
60
- audio_input = gr.Audio(sources=["microphone"], type="filepath", label="Spracheingabe", scale=2)
61
-
62
- with gr.Row():
63
- lighting_profile = gr.Dropdown(choices=list(LIGHTING_PROFILES.keys()), value="Golden Hour", label="☀️ Licht")
64
- material_profile = gr.Dropdown(choices=list(MATERIAL_PROFILES.keys()), value="Lack & Leder (High-Gloss)", label="🧥 Outfit")
65
-
66
- submit_btn = gr.Button("Senden & Streamen", variant="primary")
67
 
68
- gr.HTML("<hr style='border: 1px solid #e5e7eb; margin: 20px 0;'>")
 
 
69
 
70
- # ================= NAVIGATION (Ziele) =================
71
- gr.Markdown("### 🏢 Bereiche öffnen")
72
- with gr.Row():
73
- # Die Buttons nutzen target="_blank" im HTML-Kontext, um isolierte Tabs zu öffnen
74
- gr.HTML(f'<a href="/management" target="_blank"><button style="width:100%; padding:15px; background-color:#f3f4f6; border:1px solid #d1d5db; border-radius:8px; cursor:pointer;">💼 1. Management & Operations</button></a>')
75
- gr.HTML(f'<a href="/client" target="_blank"><button style="width:100%; padding:15px; background-color:#f3f4f6; border:1px solid #d1d5db; border-radius:8px; cursor:pointer;">🤝 2. Client & Strategy</button></a>')
76
- gr.HTML(f'<a href="/creation" target="_blank"><button style="width:100%; padding:15px; background-color:#f3f4f6; border:1px solid #d1d5db; border-radius:8px; cursor:pointer;">🎨 3. Creation & Content</button></a>')
77
- with gr.Row():
78
- gr.HTML(f'<a href="/technical" target="_blank"><button style="width:100%; padding:15px; background-color:#f3f4f6; border:1px solid #d1d5db; border-radius:8px; cursor:pointer;">📊 4. Technical & Performance</button></a>')
79
- gr.HTML(f'<a href="/data" target="_blank"><button style="width:100%; padding:15px; background-color:#f3f4f6; border:1px solid #d1d5db; border-radius:8px; cursor:pointer;">⚡ 5. Tech & Data</button></a>')
80
 
81
- # Event-Verknüpfung
82
- submit_btn.click(
83
- fn=handle_interaction,
84
- inputs=[msg_input, audio_input, lighting_profile, material_profile],
85
- outputs=[chat_feed, avatar_video_output]
86
- )
87
 
88
  if __name__ == "__main__":
89
- demo.launch(server_name="0.0.0.0", server_port=7860)
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
+ from fastapi import FastAPI, Request
3
+ from pydantic import BaseModel
4
+ from router import route, status
5
+ from state_store import init_db
6
+ from sheets_gateway import get_sheet_answer
 
 
 
 
 
 
 
 
 
 
 
7
 
8
+ app = FastAPI()
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
+ class MessageRequest(BaseModel):
11
+ message: str
12
+ level: str = "fully_open"
 
 
13
 
14
+ @app.post("/process")
15
+ @app.post("/webhook/zapier")
16
+ async def handle_request(req: MessageRequest):
17
+ result = route(message=req.message, level=req.level)
18
+ return {"success": True, "response": str(result.get("response", result))}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
+ @app.get("/")
21
+ def root():
22
+ return {"status": "online", "router": status()}
23
 
24
+ init_db()
 
 
 
 
 
 
 
 
 
25
 
26
+ with gr.Blocks() as demo:
27
+ gr.Markdown("# SkyOS MCP Server v2")
28
+ gr.ChatInterface(fn=lambda m, h: str(route(m).get("response", "Error")))
 
 
 
29
 
30
  if __name__ == "__main__":
31
+ import uvicorn
32
+ uvicorn.run(app, host="0.0.0.0", port=7860)
audio_core.py DELETED
@@ -1,16 +0,0 @@
1
- import os
2
- import subprocess
3
- import sys
4
- from typing import Dict, Any
5
-
6
- # Erzwingt die Installation der Pakete direkt im laufenden Container
7
- try:
8
- import whisper
9
- except ImportError:
10
- subprocess.check_call([sys.executable, "-m", "pip", "install", "openai-whisper", "torch"])
11
- import whisper
12
-
13
- try:
14
- _model = whisper.load_model("base")
15
- except Exception:
16
- _model = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
code_runner.py CHANGED
@@ -4,44 +4,24 @@ from diffusers import AutoPipelineForText2Image, LCMScheduler
4
  model_id = "stabilityai/stable-diffusion-xl-base-1.0"
5
  lcm_lora_id = "latent-consistency/lcm-lora-sdxl"
6
 
7
- # Dynamische Geräte-Erkennung (CPU vs. CUDA)
8
- device = "cuda" if torch.cuda.is_available() else "cpu"
9
- torch_dtype = torch.float16 if device == "cuda" else torch.float32
 
 
10
 
11
- print(f"CodeRunner initialisiert. Nutze Gerät: {device} mit {torch_dtype}")
 
12
 
13
- try:
14
- pipe = AutoPipelineForText2Image.from_pretrained(
15
- model_id,
16
- torch_dtype=torch_dtype,
17
- variant="fp16" if device == "cuda" else None # fp16-Variante läuft auf reinem CPU-Torch oft instabil
18
- )
19
 
20
- pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)
21
-
22
- # Sicherer Transfer auf das verfügbare Gerät
23
- if device == "cuda":
24
- pipe.to("cuda")
25
- else:
26
- # Überlebenswichtig für CPU Spaces: Reduziert den RAM-Verbrauch drastisch
27
- print("Optimiere Speicher für CPU-Betrieb...")
28
- pipe.enable_attention_slicing()
29
 
30
- # LoRA Gewichte laden und fusionieren für maximalen Speedup
31
- pipe.load_lora_weights(lcm_lora_id)
32
- pipe.fuse_lora()
 
 
33
 
34
- prompt = "Sky Meilin, consistent AI persona, creator system, cinematic portrait"
35
-
36
- # Generierung starten
37
- image = pipe(
38
- prompt=prompt,
39
- num_inference_steps=4,
40
- guidance_scale=1.5
41
- ).images[0]
42
-
43
- image.save("sky_output.png")
44
- print("Bild erfolgreich generiert und als 'sky_output.png' gespeichert.")
45
-
46
- except Exception as e:
47
- print(f"Fehler bei der Bildgenerierung in code_runner: {str(e)}")
 
4
  model_id = "stabilityai/stable-diffusion-xl-base-1.0"
5
  lcm_lora_id = "latent-consistency/lcm-lora-sdxl"
6
 
7
+ pipe = AutoPipelineForText2Image.from_pretrained(
8
+ model_id,
9
+ torch_dtype=torch.float16,
10
+ variant="fp16"
11
+ )
12
 
13
+ pipe.scheduler = LCMScheduler.from_config(pipe.scheduler.config)
14
+ pipe.to("cuda")
15
 
16
+ pipe.load_lora_weights(lcm_lora_id)
17
+ pipe.fuse_lora()
 
 
 
 
18
 
19
+ prompt = "Sky Meilin, consistent AI persona, creator system, cinematic portrait"
 
 
 
 
 
 
 
 
20
 
21
+ image = pipe(
22
+ prompt=prompt,
23
+ num_inference_steps=4,
24
+ guidance_scale=1.5
25
+ ).images[0]
26
 
27
+ image.save("sky_output.png")
 
 
 
 
 
 
 
 
 
 
 
 
 
core/chunker.py CHANGED
@@ -1,5 +1,6 @@
1
  from typing import List, Dict, Any, Optional
2
 
 
3
  class Chunker:
4
  """
5
  Splits raw text into chunks for:
@@ -17,6 +18,7 @@ class Chunker:
17
  Simple character-based chunking with overlap.
18
  Stable baseline for RAG pipelines.
19
  """
 
20
  if not text:
21
  return []
22
 
@@ -24,18 +26,14 @@ class Chunker:
24
  start = 0
25
  text_length = len(text)
26
 
27
- # Absicherung: Schrittweite berechnen und Endlosschleife verhindern
28
- step = self.chunk_size - self.overlap
29
- if step <= 0:
30
- step = 1
31
-
32
  while start < text_length:
33
  end = start + self.chunk_size
34
  chunk = text[start:end]
 
35
  chunks.append(chunk)
36
 
37
- # Sicherer Vorwärtsschritt
38
- start += step
39
 
40
  return chunks
41
 
@@ -50,10 +48,12 @@ class Chunker:
50
  Returns:
51
  list of chunked documents with metadata
52
  """
 
53
  chunked_output = []
54
 
55
  for doc in documents:
56
  text = doc.get(field, "")
 
57
  chunks = self.chunk_text(text)
58
 
59
  for i, chunk in enumerate(chunks):
@@ -71,6 +71,7 @@ class Chunker:
71
  Optional smarter fallback:
72
  paragraph-aware chunking.
73
  """
 
74
  paragraphs = text.split("\n\n")
75
  chunks = []
76
  buffer = ""
@@ -86,4 +87,4 @@ class Chunker:
86
  if buffer:
87
  chunks.append(buffer.strip())
88
 
89
- return chunks
 
1
  from typing import List, Dict, Any, Optional
2
 
3
+
4
  class Chunker:
5
  """
6
  Splits raw text into chunks for:
 
18
  Simple character-based chunking with overlap.
19
  Stable baseline for RAG pipelines.
20
  """
21
+
22
  if not text:
23
  return []
24
 
 
26
  start = 0
27
  text_length = len(text)
28
 
 
 
 
 
 
29
  while start < text_length:
30
  end = start + self.chunk_size
31
  chunk = text[start:end]
32
+
33
  chunks.append(chunk)
34
 
35
+ # move forward with overlap
36
+ start += self.chunk_size - self.overlap
37
 
38
  return chunks
39
 
 
48
  Returns:
49
  list of chunked documents with metadata
50
  """
51
+
52
  chunked_output = []
53
 
54
  for doc in documents:
55
  text = doc.get(field, "")
56
+
57
  chunks = self.chunk_text(text)
58
 
59
  for i, chunk in enumerate(chunks):
 
71
  Optional smarter fallback:
72
  paragraph-aware chunking.
73
  """
74
+
75
  paragraphs = text.split("\n\n")
76
  chunks = []
77
  buffer = ""
 
87
  if buffer:
88
  chunks.append(buffer.strip())
89
 
90
+ return chunks
core/cleaner.py CHANGED
@@ -2,20 +2,18 @@
2
 
3
  import re
4
 
 
5
  class Cleaner:
6
  def clean_text(self, text: str) -> str:
7
- if not text:
8
- return ""
9
-
10
  text = text.lower()
11
 
12
- # URLs entfernen (korrigiert auf \S+)
13
- text = re.sub(r"http\S+", "", text)
14
 
15
- # Sonderzeichen reduzieren (korrigiert auf \s)
16
- text = re.sub(r"[^a-zA-Z0-9äöüÄÖÜß\s]", " ", text)
17
 
18
- # Mehrfachspaces entfernen (korrigiert auf \s+)
19
- text = re.sub(r"\s+", " ", text)
20
 
21
- return text.strip()
 
2
 
3
  import re
4
 
5
+
6
  class Cleaner:
7
  def clean_text(self, text: str) -> str:
 
 
 
8
  text = text.lower()
9
 
10
+ # URLs entfernen
11
+ text = re.sub(r"http\\S+", "", text)
12
 
13
+ # Sonderzeichen reduzieren
14
+ text = re.sub(r"[^a-zA-Z0-9äöüÄÖÜß\\s]", " ", text)
15
 
16
+ # Mehrfachspaces entfernen
17
+ text = re.sub(r"\\s+", " ", text)
18
 
19
+ return text.strip()
core/deepseek.py CHANGED
@@ -5,7 +5,7 @@ def process(message: str) -> str:
5
  Später kann hier eine echte API- oder Modell-Anbindung eingebaut werden.
6
  """
7
 
8
- if message is None or not str(message).strip():
9
  return "DeepSeek: Keine Eingabe erhalten."
10
 
11
  message = str(message).strip()
@@ -15,4 +15,4 @@ def process(message: str) -> str:
15
  f"Eingabe empfangen:\n{message}\n\n"
16
  "Analyse-Modus: aktiviert.\n"
17
  "Status: process() funktioniert."
18
- )
 
5
  Später kann hier eine echte API- oder Modell-Anbindung eingebaut werden.
6
  """
7
 
8
+ if not message or not str(message).strip():
9
  return "DeepSeek: Keine Eingabe erhalten."
10
 
11
  message = str(message).strip()
 
15
  f"Eingabe empfangen:\n{message}\n\n"
16
  "Analyse-Modus: aktiviert.\n"
17
  "Status: process() funktioniert."
18
+ )
core/embeddings.py CHANGED
@@ -1,13 +1,11 @@
1
  from sentence_transformers import SentenceTransformer
2
  from typing import List, Union
3
- import numpy as np
4
 
5
  class Embedder:
6
  def __init__(self, model_name: str = "all-MiniLM-L6-v2"):
7
- # Nutzt verfügbare Hardware (Cuda/CPU) automatisch
8
  self.model = SentenceTransformer(model_name)
9
 
10
- def encode(self, texts: Union[str, List[str]], normalize: bool = True) -> np.ndarray:
11
  """
12
  Encodes text(s) into embeddings.
13
 
@@ -18,16 +16,9 @@ class Embedder:
18
  Returns:
19
  numpy.ndarray embeddings
20
  """
21
- if not texts:
22
- return np.array([])
23
-
24
  if isinstance(texts, str):
25
- if not texts.strip():
26
- return np.array([])
27
  texts = [texts]
28
 
29
- # Konvertiert leere Strings in der Liste, um Crashs zu vermeiden
30
- texts = [t if t.strip() else " " for t in texts]
31
-
32
  embeddings = self.model.encode(texts, normalize_embeddings=normalize)
33
  return embeddings
 
 
1
  from sentence_transformers import SentenceTransformer
2
  from typing import List, Union
 
3
 
4
  class Embedder:
5
  def __init__(self, model_name: str = "all-MiniLM-L6-v2"):
 
6
  self.model = SentenceTransformer(model_name)
7
 
8
+ def encode(self, texts: Union[str, List[str]], normalize: bool = True):
9
  """
10
  Encodes text(s) into embeddings.
11
 
 
16
  Returns:
17
  numpy.ndarray embeddings
18
  """
 
 
 
19
  if isinstance(texts, str):
 
 
20
  texts = [texts]
21
 
 
 
 
22
  embeddings = self.model.encode(texts, normalize_embeddings=normalize)
23
  return embeddings
24
+
core/hermes.py CHANGED
@@ -4,7 +4,7 @@ def process(message: str) -> str:
4
  Verarbeitet eingehende Nachrichten für SkyOSFullCore.
5
  """
6
 
7
- if message is None or not str(message).strip():
8
  return "Hermes: Keine Eingabe erhalten."
9
 
10
  message = str(message).strip()
@@ -13,4 +13,4 @@ def process(message: str) -> str:
13
  "Hermes Core ist aktiv.\n\n"
14
  f"Eingabe empfangen:\n{message}\n\n"
15
  "Status: process() funktioniert."
16
- )
 
4
  Verarbeitet eingehende Nachrichten für SkyOSFullCore.
5
  """
6
 
7
+ if not message or not str(message).strip():
8
  return "Hermes: Keine Eingabe erhalten."
9
 
10
  message = str(message).strip()
 
13
  "Hermes Core ist aktiv.\n\n"
14
  f"Eingabe empfangen:\n{message}\n\n"
15
  "Status: process() funktioniert."
16
+ )
core/joyai.py CHANGED
@@ -4,7 +4,7 @@ def process(message: str) -> str:
4
  Kreativ-/Personality-Modul für SkyOSFullCore.
5
  """
6
 
7
- if message is None or not str(message).strip():
8
  return "JoyAI: Keine Eingabe erhalten."
9
 
10
  message = str(message).strip()
@@ -14,4 +14,4 @@ def process(message: str) -> str:
14
  f"Eingabe empfangen:\n{message}\n\n"
15
  "Kreativ-Modus: aktiviert.\n"
16
  "Status: process() funktioniert."
17
- )
 
4
  Kreativ-/Personality-Modul für SkyOSFullCore.
5
  """
6
 
7
+ if not message or not str(message).strip():
8
  return "JoyAI: Keine Eingabe erhalten."
9
 
10
  message = str(message).strip()
 
14
  f"Eingabe empfangen:\n{message}\n\n"
15
  "Kreativ-Modus: aktiviert.\n"
16
  "Status: process() funktioniert."
17
+ )
core/loader.py CHANGED
@@ -3,49 +3,51 @@
3
  from datasets import load_dataset
4
  import os
5
 
 
6
  class DatasetLoader:
 
7
  def __init__(self):
 
8
  print("DatasetLoader geladen")
 
9
  self.hf_token = os.getenv("HF_TOKEN", None)
 
10
  self.datasets = {
11
  "matrix_game": "Skywork/Matrix-Game-3.0",
12
  "framework_storage": "sky-meilin/SkyAiFramework-storage"
13
  }
14
 
15
  def list_datasets(self):
 
16
  return list(self.datasets.keys())
17
 
18
- def load(self, dataset_name: str, name: str = None):
 
19
  if dataset_name not in self.datasets:
 
20
  raise ValueError(
21
  f"Dataset '{dataset_name}' nicht registriert."
22
  )
23
 
24
  dataset_path = self.datasets[dataset_name]
25
- try:
26
- # name erlaubt das Laden von Unterordnern/Konfigurationen, falls nötig
27
- dataset = load_dataset(
28
- dataset_path,
29
- name=name,
30
- token=self.hf_token
31
- )
32
- return dataset
33
- except Exception as e:
34
- raise RuntimeError(f"Fehler beim Laden von {dataset_name}: {str(e)}")
35
 
36
- def load_split(self, dataset_name: str, split: str = None, name: str = None):
37
- dataset = self.load(dataset_name, name=name)
 
 
 
 
38
 
39
- # Falls das Dataset direkt ein einzelnes Dataset ist (kein Dict mit Splits)
40
- if not hasattr(dataset, "keys"):
41
- return dataset
 
 
 
 
42
 
43
  if split is None:
44
- split = list(dataset.keys())[0]
45
 
46
- if split not in dataset:
47
- raise ValueError(
48
- f"Split '{split}' existiert nicht. Verfügbar: {list(dataset.keys())}"
49
- )
50
 
51
- return dataset[split]
 
3
  from datasets import load_dataset
4
  import os
5
 
6
+
7
  class DatasetLoader:
8
+
9
  def __init__(self):
10
+
11
  print("DatasetLoader geladen")
12
+
13
  self.hf_token = os.getenv("HF_TOKEN", None)
14
+
15
  self.datasets = {
16
  "matrix_game": "Skywork/Matrix-Game-3.0",
17
  "framework_storage": "sky-meilin/SkyAiFramework-storage"
18
  }
19
 
20
  def list_datasets(self):
21
+
22
  return list(self.datasets.keys())
23
 
24
+ def load(self, dataset_name: str):
25
+
26
  if dataset_name not in self.datasets:
27
+
28
  raise ValueError(
29
  f"Dataset '{dataset_name}' nicht registriert."
30
  )
31
 
32
  dataset_path = self.datasets[dataset_name]
 
 
 
 
 
 
 
 
 
 
33
 
34
+ dataset = load_dataset(
35
+ dataset_path,
36
+ token=self.hf_token
37
+ )
38
+
39
+ return dataset
40
 
41
+ def load_split(
42
+ self,
43
+ dataset_name: str,
44
+ split: str = None
45
+ ):
46
+
47
+ dataset = self.load(dataset_name)
48
 
49
  if split is None:
 
50
 
51
+ split = list(dataset.keys())[0]
 
 
 
52
 
53
+ return dataset[split]
core/orchestrator.py CHANGED
@@ -1,8 +1,7 @@
1
- from . import hermes, deepseek, joyai
2
 
3
 
4
  class SkyOrchestrator:
5
-
6
  def __init__(self):
7
  self.modules = {
8
  "hermes": hermes,
@@ -21,25 +20,25 @@ class SkyOrchestrator:
21
 
22
  try:
23
  return str(module.process(message))
 
24
  except Exception as e:
25
  return f"{module_name}: Fehler in process(): {str(e)}"
26
 
27
  def detect_modules(self, message: str) -> list:
28
  text = str(message or "").lower()
 
29
  selected = []
30
 
31
- # Content / SEO / Business / Knowledge Sources
32
  content_keywords = [
33
  "blog",
34
  "seo",
35
  "artikel",
36
  "content",
37
- "contentplan",
38
- "backlog",
39
  "social",
40
  "post",
41
  "marketing",
42
- "fanvue",
43
  ]
44
 
45
  # Technik / System
@@ -52,7 +51,7 @@ class SkyOrchestrator:
52
  "python",
53
  "telegram",
54
  "wordpress",
55
- "gravatar",
56
  ]
57
 
58
  # Kreativ / Persona
@@ -62,77 +61,115 @@ class SkyOrchestrator:
62
  "persona",
63
  "sky",
64
  "charakter",
65
- "creator",
66
  ]
67
 
68
  # Direkte Modulaufrufe behalten
69
  if "hermes" in text:
70
  selected.append("hermes")
 
71
  if "deepseek" in text:
72
  selected.append("deepseek")
 
73
  if "joy" in text or "joyai" in text:
74
  selected.append("joyai")
75
 
76
  # Automatische Intent-Erkennung
77
  if any(word in text for word in content_keywords):
78
- selected.extend(["hermes", "deepseek"])
 
 
 
 
79
  elif any(word in text for word in system_keywords):
80
- selected.append("hermes")
 
 
 
81
  elif any(word in text for word in creative_keywords):
82
- selected.append("joyai")
 
 
83
 
84
  # Fallback
85
  if not selected:
86
- selected.append("hermes")
 
 
87
 
88
  return list(dict.fromkeys(selected))
89
 
90
  def process(self, message: str) -> str:
 
91
  if not message or not str(message).strip():
92
  return "SkyOrchestrator: Keine Eingabe erhalten."
93
 
94
- selected_modules = self.detect_modules(message)
 
 
 
95
  results = []
96
 
97
  for module_name in selected_modules:
98
- results.append(self.safe_process(module_name, message))
99
-
100
- # Hier wird vermerkt, falls nach Inhalten gesucht wurde, um das für den Router sichtbar zu machen
101
- knowledge_note = ""
102
- if any(
103
- k in str(message).lower()
104
- for k in ["contentplan", "backlog", "template", "storage"]
105
- ):
106
- knowledge_note = (
107
- "ℹ️ Info: Anfrage betrifft Knowledge Sources / Contentplan.\n\n"
108
  )
109
 
110
  return (
111
  "SkyOrchestrator aktiv\n\n"
 
112
  f"Ausgewählte Module:\n"
113
  f"{', '.join(selected_modules)}\n\n"
114
- f"{knowledge_note}"
115
  "Antworten:\n\n"
116
- + "\n\n-------------------\n\n".join(results)
 
 
 
117
  )
118
 
119
  def status(self) -> str:
 
120
  active_modules = []
 
121
  for name, module in self.modules.items():
122
- if module is not None and hasattr(module, "process"):
123
- active_modules.append(f"✅ {name}")
 
 
 
 
 
 
 
 
124
  else:
125
- active_modules.append(f"❌ {name}")
126
 
127
- return "SkyOSFullCore Orchestrator Status\n\n" + "\n".join(active_modules)
 
 
 
 
 
 
 
 
 
 
128
 
129
 
130
  orchestrator = SkyOrchestrator()
131
 
132
 
133
  def process(message: str) -> str:
134
- return orchestrator.process(message)
 
 
135
 
136
 
137
  def status() -> str:
138
- return orchestrator.status()
 
1
+ from core import hermes, deepseek, joyai
2
 
3
 
4
  class SkyOrchestrator:
 
5
  def __init__(self):
6
  self.modules = {
7
  "hermes": hermes,
 
20
 
21
  try:
22
  return str(module.process(message))
23
+
24
  except Exception as e:
25
  return f"{module_name}: Fehler in process(): {str(e)}"
26
 
27
  def detect_modules(self, message: str) -> list:
28
  text = str(message or "").lower()
29
+
30
  selected = []
31
 
32
+ # Content / SEO / Business
33
  content_keywords = [
34
  "blog",
35
  "seo",
36
  "artikel",
37
  "content",
 
 
38
  "social",
39
  "post",
40
  "marketing",
41
+ "fanvue"
42
  ]
43
 
44
  # Technik / System
 
51
  "python",
52
  "telegram",
53
  "wordpress",
54
+ "gravatar"
55
  ]
56
 
57
  # Kreativ / Persona
 
61
  "persona",
62
  "sky",
63
  "charakter",
64
+ "creator"
65
  ]
66
 
67
  # Direkte Modulaufrufe behalten
68
  if "hermes" in text:
69
  selected.append("hermes")
70
+
71
  if "deepseek" in text:
72
  selected.append("deepseek")
73
+
74
  if "joy" in text or "joyai" in text:
75
  selected.append("joyai")
76
 
77
  # Automatische Intent-Erkennung
78
  if any(word in text for word in content_keywords):
79
+ selected.extend([
80
+ "hermes",
81
+ "deepseek"
82
+ ])
83
+
84
  elif any(word in text for word in system_keywords):
85
+ selected.append(
86
+ "hermes"
87
+ )
88
+
89
  elif any(word in text for word in creative_keywords):
90
+ selected.append(
91
+ "joyai"
92
+ )
93
 
94
  # Fallback
95
  if not selected:
96
+ selected.append(
97
+ "hermes"
98
+ )
99
 
100
  return list(dict.fromkeys(selected))
101
 
102
  def process(self, message: str) -> str:
103
+
104
  if not message or not str(message).strip():
105
  return "SkyOrchestrator: Keine Eingabe erhalten."
106
 
107
+ selected_modules = self.detect_modules(
108
+ message
109
+ )
110
+
111
  results = []
112
 
113
  for module_name in selected_modules:
114
+
115
+ results.append(
116
+ self.safe_process(
117
+ module_name,
118
+ message
119
+ )
 
 
 
 
120
  )
121
 
122
  return (
123
  "SkyOrchestrator aktiv\n\n"
124
+
125
  f"Ausgewählte Module:\n"
126
  f"{', '.join(selected_modules)}\n\n"
127
+
128
  "Antworten:\n\n"
129
+
130
+ + "\n\n-------------------\n\n".join(
131
+ results
132
+ )
133
  )
134
 
135
  def status(self) -> str:
136
+
137
  active_modules = []
138
+
139
  for name, module in self.modules.items():
140
+
141
+ if (
142
+ module is not None
143
+ and hasattr(module, "process")
144
+ ):
145
+
146
+ active_modules.append(
147
+ f"✅ {name}"
148
+ )
149
+
150
  else:
 
151
 
152
+ active_modules.append(
153
+ f"❌ {name}"
154
+ )
155
+
156
+ return (
157
+ "SkyOSFullCore Orchestrator Status\n\n"
158
+
159
+ + "\n".join(
160
+ active_modules
161
+ )
162
+ )
163
 
164
 
165
  orchestrator = SkyOrchestrator()
166
 
167
 
168
  def process(message: str) -> str:
169
+ return orchestrator.process(
170
+ message
171
+ )
172
 
173
 
174
  def status() -> str:
175
+ return orchestrator.status()
core/router.py CHANGED
@@ -1,17 +1,4 @@
1
- import os
2
- import sys
3
-
4
- # Stellt sicher, dass das Hauptverzeichnis im Suchpfad ist, damit router_publish gefunden wird
5
- main_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
6
- if main_dir not in sys.path:
7
- sys.path.insert(0, main_dir)
8
-
9
- # Initialisierung der Fallback-Variablen
10
- can_handle_publish_route = lambda msg: False
11
- handle_publish_route = lambda msg: "Publish Router nicht verfügbar."
12
- get_publish_router_status = lambda: "inaktiv (Import-Fehler)"
13
- PUBLISH_ROUTER_IMPORT_ERROR = None
14
-
15
  try:
16
  from router_publish import (
17
  can_handle_publish_route as _can_handle_publish_route,
@@ -22,7 +9,6 @@ try:
22
  can_handle_publish_route = _can_handle_publish_route
23
  handle_publish_route = _handle_publish_route
24
  get_publish_router_status = _get_publish_router_status
25
-
26
  except ImportError as e:
27
  PUBLISH_ROUTER_IMPORT_ERROR = f"ImportError: {e}"
28
  except Exception as exc:
 
1
+ # /app/router.py - Dieser Block muss den alten Import ersetzen
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  try:
3
  from router_publish import (
4
  can_handle_publish_route as _can_handle_publish_route,
 
9
  can_handle_publish_route = _can_handle_publish_route
10
  handle_publish_route = _handle_publish_route
11
  get_publish_router_status = _get_publish_router_status
 
12
  except ImportError as e:
13
  PUBLISH_ROUTER_IMPORT_ERROR = f"ImportError: {e}"
14
  except Exception as exc:
crm_core.py CHANGED
@@ -1,22 +1,11 @@
1
- """
2
- crm_core.py
3
- SkyOS CRM Core
4
- Version: skyos_crm_core_v2_2026_06_04
5
- Verarbeitet Leads, Kontakte, Kundenstatus und bereitet Daten für den Sheets-Sync vor.
6
- """
7
 
8
  from datetime import datetime
9
- import json
10
 
11
- CRM_CORE_VERSION = "skyos_crm_core_v2_2026_06_04"
12
 
13
- # Sicheres Laden des State Stores zur persistenten Event-Verfolgung
14
- STATE_STORE_AVAILABLE = False
15
- try:
16
- from state_store import log_event
17
- STATE_STORE_AVAILABLE = True
18
- except Exception:
19
- pass
20
 
21
 
22
  def crm_status():
@@ -68,7 +57,6 @@ def parse_lead_from_text(message: str):
68
 
69
  lead = create_lead(notes=text)
70
 
71
- # Plattformen-Erkennung
72
  if "instagram" in lower:
73
  lead["Platform"] = "Instagram"
74
  elif "tiktok" in lower:
@@ -82,7 +70,6 @@ def parse_lead_from_text(message: str):
82
  elif "gmail" in lower or "email" in lower:
83
  lead["Platform"] = "Email"
84
 
85
- # Prioritäten-Erkennung
86
  if "priorität hoch" in lower or "prio hoch" in lower or "high" in lower:
87
  lead["Priority"] = "high"
88
  elif "priorität niedrig" in lower or "prio niedrig" in lower or "low" in lower:
@@ -90,7 +77,6 @@ def parse_lead_from_text(message: str):
90
  else:
91
  lead["Priority"] = "medium"
92
 
93
- # Status-Erkennung
94
  if "interessiert" in lower:
95
  lead["Status"] = "interested"
96
  elif "kontaktiert" in lower or "contacted" in lower:
@@ -100,7 +86,6 @@ def parse_lead_from_text(message: str):
100
  else:
101
  lead["Status"] = "new"
102
 
103
- # Angebots-Erkennung
104
  if "agency" in lower or "agentur" in lower:
105
  lead["Offer"] = "Agency Angebot"
106
  elif "crm" in lower:
@@ -110,16 +95,11 @@ def parse_lead_from_text(message: str):
110
  elif "fanvue" in lower:
111
  lead["Offer"] = "Fanvue / Creator Angebot"
112
 
113
- # Abgesicherte Namens-Extraktion (ignoriert URLs wie http:// oder https://)
114
- if ":" in text and "http:" not in lower and "https:" not in lower:
115
  after_colon = text.split(":", 1)[1].strip()
116
  possible_name = after_colon.split(",", 1)[0].strip()
117
  if possible_name:
118
  lead["Name"] = possible_name
119
- elif ":" in text and ("http:" in lower or "https:" in lower):
120
- parts = text.split()
121
- if len(parts) > 1 and not parts[1].startswith("http"):
122
- lead["Name"] = parts[1].replace(",", "")
123
 
124
  return lead
125
 
@@ -139,23 +119,11 @@ def process_crm_message(message: str):
139
  or "followup" in lower
140
  or "crm" in lower
141
  ):
142
- parsed_lead = parse_lead_from_text(text)
143
-
144
- # KORRIGIERT: Daten-Sicherung über den State Store, falls verfügbar
145
- if STATE_STORE_AVAILABLE:
146
- log_event(
147
- message=f"Lead-Generierung für {parsed_lead['Name']}",
148
- context=parsed_lead,
149
- route_target="crm_core -> sheets_pipeline",
150
- response="Lead erfolgreich erfasst und im State hinterlegt."
151
- )
152
-
153
  return {
154
  "success": True,
155
  "action": "create_lead",
156
  "crm_core": CRM_CORE_VERSION,
157
- "lead": parsed_lead,
158
- "sync_status": "state_logged" if STATE_STORE_AVAILABLE else "volatile_memory"
159
  }
160
 
161
  return {
@@ -167,4 +135,4 @@ def process_crm_message(message: str):
167
 
168
 
169
  if __name__ == "__main__":
170
- print(crm_status())
 
1
+ # crm_core.py
2
+ # SkyOS CRM Core
3
+ # Version: skyos_crm_core_v2_2026_06_04
 
 
 
4
 
5
  from datetime import datetime
 
6
 
 
7
 
8
+ CRM_CORE_VERSION = "skyos_crm_core_v2_2026_06_04"
 
 
 
 
 
 
9
 
10
 
11
  def crm_status():
 
57
 
58
  lead = create_lead(notes=text)
59
 
 
60
  if "instagram" in lower:
61
  lead["Platform"] = "Instagram"
62
  elif "tiktok" in lower:
 
70
  elif "gmail" in lower or "email" in lower:
71
  lead["Platform"] = "Email"
72
 
 
73
  if "priorität hoch" in lower or "prio hoch" in lower or "high" in lower:
74
  lead["Priority"] = "high"
75
  elif "priorität niedrig" in lower or "prio niedrig" in lower or "low" in lower:
 
77
  else:
78
  lead["Priority"] = "medium"
79
 
 
80
  if "interessiert" in lower:
81
  lead["Status"] = "interested"
82
  elif "kontaktiert" in lower or "contacted" in lower:
 
86
  else:
87
  lead["Status"] = "new"
88
 
 
89
  if "agency" in lower or "agentur" in lower:
90
  lead["Offer"] = "Agency Angebot"
91
  elif "crm" in lower:
 
95
  elif "fanvue" in lower:
96
  lead["Offer"] = "Fanvue / Creator Angebot"
97
 
98
+ if ":" in text:
 
99
  after_colon = text.split(":", 1)[1].strip()
100
  possible_name = after_colon.split(",", 1)[0].strip()
101
  if possible_name:
102
  lead["Name"] = possible_name
 
 
 
 
103
 
104
  return lead
105
 
 
119
  or "followup" in lower
120
  or "crm" in lower
121
  ):
 
 
 
 
 
 
 
 
 
 
 
122
  return {
123
  "success": True,
124
  "action": "create_lead",
125
  "crm_core": CRM_CORE_VERSION,
126
+ "lead": parse_lead_from_text(text)
 
127
  }
128
 
129
  return {
 
135
 
136
 
137
  if __name__ == "__main__":
138
+ print(crm_status())
extractor.py CHANGED
@@ -2,16 +2,7 @@ from typing import Dict, Any
2
 
3
 
4
  def analyze_context(message: str) -> Dict[str, Any]:
5
- # Text normalisieren und für Wort-Splitting vorbereiten
6
- text_raw = message.lower()
7
-
8
- # Satzzeichen entfernen für exaktes Word-Matching
9
- clean_text = text_raw
10
- for char in [".", ",", "!", "?", ";", ":", "-", "_", "(", ")", "[", "]", "\n", "\r"]:
11
- clean_text = clean_text.replace(char, " ")
12
-
13
- # In einzelne Wörter splitten, um Sub-String-Fehler (z.B. "ich" in "sicherlich") zu vermeiden
14
- words_set = set(clean_text.split())
15
 
16
  scores = {
17
  "Business": 0.0,
@@ -40,21 +31,20 @@ def analyze_context(message: str) -> Dict[str, Any]:
40
  "ziel", "entscheidung", "gedanke"
41
  ]
42
 
43
- # Abgleich auf echte Wort-Treffer oder exakte Phrasen
44
  for word in business_words:
45
- if word in words_set or (" " in word and word in text_raw):
46
  scores["Business"] += 1
47
 
48
  for word in tech_words:
49
- if word in words_set or (" " in word and word in text_raw):
50
  scores["Technik"] += 1
51
 
52
  for word in creative_words:
53
- if word in words_set or (" " in word and word in text_raw):
54
  scores["Kreativ"] += 1
55
 
56
  for word in personal_words:
57
- if word in words_set:
58
  scores["Persönlich"] += 0.5
59
 
60
  total = sum(scores.values()) or 1
@@ -64,28 +54,24 @@ def analyze_context(message: str) -> Dict[str, Any]:
64
  for key, value in scores.items()
65
  }
66
 
67
- raw_primary = max(distribution, key=distribution.get)
68
- actual_confidence = distribution.get(raw_primary, 0.5)
69
 
70
- # Wenn der stärkste Intent unter 40% liegt, deklarieren wir es als gemischten Kontext
71
- if distribution[raw_primary] < 0.4:
72
  primary = "Mixed"
73
- else:
74
- primary = raw_primary
75
 
76
- intent = detect_intent(text_raw)
77
- complexity = detect_complexity(text_raw)
78
 
79
  return {
80
  "primary_context": {
81
  "type": primary,
82
- "confidence": actual_confidence if primary != "Mixed" else round(actual_confidence, 2)
83
  },
84
  "context_distribution": distribution,
85
  "intent_layer": intent,
86
  "complexity_level": complexity,
87
  "routing_hint": build_routing_hint(primary, intent, complexity),
88
- "reasoning": "Kontext wurde anhand exakter Schlüsselwörter und Signalgruppen bestimmt."
89
  }
90
 
91
 
@@ -113,8 +99,10 @@ def detect_complexity(text: str) -> str:
113
 
114
  if length > 1500:
115
  return "high"
 
116
  if length > 500:
117
  return "medium"
 
118
  return "low"
119
 
120
 
@@ -136,4 +124,4 @@ def build_routing_hint(primary: str, intent: Dict[str, Any], complexity: str) ->
136
  "target_system": target,
137
  "priority": priority,
138
  "intent": intent["type"]
139
- }
 
2
 
3
 
4
  def analyze_context(message: str) -> Dict[str, Any]:
5
+ text = message.lower()
 
 
 
 
 
 
 
 
 
6
 
7
  scores = {
8
  "Business": 0.0,
 
31
  "ziel", "entscheidung", "gedanke"
32
  ]
33
 
 
34
  for word in business_words:
35
+ if word in text:
36
  scores["Business"] += 1
37
 
38
  for word in tech_words:
39
+ if word in text:
40
  scores["Technik"] += 1
41
 
42
  for word in creative_words:
43
+ if word in text:
44
  scores["Kreativ"] += 1
45
 
46
  for word in personal_words:
47
+ if word in text:
48
  scores["Persönlich"] += 0.5
49
 
50
  total = sum(scores.values()) or 1
 
54
  for key, value in scores.items()
55
  }
56
 
57
+ primary = max(distribution, key=distribution.get)
 
58
 
59
+ if distribution[primary] < 0.4:
 
60
  primary = "Mixed"
 
 
61
 
62
+ intent = detect_intent(text)
63
+ complexity = detect_complexity(text)
64
 
65
  return {
66
  "primary_context": {
67
  "type": primary,
68
+ "confidence": distribution.get(primary, 0.5) if primary != "Mixed" else 0.5
69
  },
70
  "context_distribution": distribution,
71
  "intent_layer": intent,
72
  "complexity_level": complexity,
73
  "routing_hint": build_routing_hint(primary, intent, complexity),
74
+ "reasoning": "Kontext wurde anhand erkannter Schlüsselwörter und Signalgruppen bestimmt."
75
  }
76
 
77
 
 
99
 
100
  if length > 1500:
101
  return "high"
102
+
103
  if length > 500:
104
  return "medium"
105
+
106
  return "low"
107
 
108
 
 
124
  "target_system": target,
125
  "priority": priority,
126
  "intent": intent["type"]
127
+ }
fanvue_guide.py CHANGED
@@ -13,21 +13,6 @@ FANVUE_VERIFICATION = "https://fanvue.com/settings/verification"
13
  FANVUE_PAYOUTS = "https://fanvue.com/settings/payouts"
14
 
15
 
16
- def clean_username(name: str) -> str:
17
- """Bereinigt den Namen für gültige Plattform-Usernames (keine Umlaute/Sonderzeichen)."""
18
- username = name.lower().strip()
19
- # Umlaute ersetzen
20
- replacements = {"ä": "ae", "ö": "oe", "ü": "ue", "ß": "ss"}
21
- for char, rep in replacements.items():
22
- username = username.replace(char, rep)
23
-
24
- # Leerzeichen und Bindestriche durch Unterstriche ersetzen
25
- username = username.replace(" ", "_").replace("-", "_")
26
-
27
- # Erlaubte Zeichen filtern (nur Alphanumerisch und Unterstriche)
28
- return "".join(c for c in username if c.isalnum() or c == "_")
29
-
30
-
31
  def get_fanvue_guide(creator_name: str = "Creator") -> str:
32
  """
33
  Gibt eine vollständige, personalisierte Fanvue Setup-Anleitung zurück.
@@ -39,7 +24,6 @@ def get_fanvue_guide(creator_name: str = "Creator") -> str:
39
  Vollständige Schritt-für-Schritt Anleitung als String.
40
  """
41
  name = creator_name.strip() if creator_name else "Creator"
42
- suggested_username = clean_username(name)
43
 
44
  guide = f"""Fanvue Setup Guide — {name}
45
  Version: {MODULE_VERSION}
@@ -60,7 +44,7 @@ SCHRITT 2 — Profil einrichten
60
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
61
 
62
  1. Oben rechts auf Avatar klicken → "Edit Profile"
63
- 2. Username eingeben: {suggested_username}
64
  3. Display Name: {name}
65
  4. Bio: Dein Hook-Text (2 Sätze — wer du bist + was Subscriber erwartet)
66
  5. Profilbild hochladen (empfohlen: quadratisch, min. 400×400px)
@@ -140,6 +124,7 @@ def process(message: str) -> str:
140
  Fanvue Guide als String.
141
  """
142
  name = "Creator"
 
143
  msg = message.lower() if message else ""
144
 
145
  if "molina" in msg:
@@ -151,4 +136,4 @@ def process(message: str) -> str:
151
 
152
 
153
  if __name__ == "__main__":
154
- print(get_fanvue_guide("Molina Hill"))
 
13
  FANVUE_PAYOUTS = "https://fanvue.com/settings/payouts"
14
 
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  def get_fanvue_guide(creator_name: str = "Creator") -> str:
17
  """
18
  Gibt eine vollständige, personalisierte Fanvue Setup-Anleitung zurück.
 
24
  Vollständige Schritt-für-Schritt Anleitung als String.
25
  """
26
  name = creator_name.strip() if creator_name else "Creator"
 
27
 
28
  guide = f"""Fanvue Setup Guide — {name}
29
  Version: {MODULE_VERSION}
 
44
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
45
 
46
  1. Oben rechts auf Avatar klicken → "Edit Profile"
47
+ 2. Username eingeben: {name.lower().replace(" ", "_")}
48
  3. Display Name: {name}
49
  4. Bio: Dein Hook-Text (2 Sätze — wer du bist + was Subscriber erwartet)
50
  5. Profilbild hochladen (empfohlen: quadratisch, min. 400×400px)
 
124
  Fanvue Guide als String.
125
  """
126
  name = "Creator"
127
+
128
  msg = message.lower() if message else ""
129
 
130
  if "molina" in msg:
 
136
 
137
 
138
  if __name__ == "__main__":
139
+ print(get_fanvue_guide("Molina Hill"))
mcp_server.py CHANGED
@@ -1,40 +1,19 @@
1
- """
2
- mcp_server.py
3
- SkyOS Model Context Protocol (MCP) Server
4
- Stellt LLM-Agenten (wie Claude oder DeepSeek) Werkzeuge für das Creator OS bereit.
5
- """
6
-
7
- import json
8
  from mcp.server.fastmcp import FastMCP
9
-
10
- # Core-System-Imports
11
- from router import route, status
12
- from trend_predictor import skyos_trend_score
13
- from crm_core import process_crm_message
14
 
15
  # Initialisierung des MCP-Servers
16
  mcp = FastMCP("SkyOS_MCP_Server")
17
 
18
-
19
  @mcp.tool()
20
  def route_request(message: str) -> str:
21
- """
22
- Leitet Anfragen durch den SkyOS Router.
23
- Verarbeitet Text-Intents und steuert die Sub-Module an.
24
- """
25
- result = route(message)
26
- # Falls das Ergebnis ein Dictionary/Objekt ist, sauber als JSON-String zurückgeben
27
- if isinstance(result, (dict, list)):
28
- return json.dumps(result, ensure_ascii=False)
29
- return str(result)
30
-
31
 
32
  @mcp.tool()
33
  def get_system_status() -> str:
34
  """Gibt den aktuellen Status des SkyOS-Systems zurück."""
35
  return status()
36
 
37
-
38
  @mcp.tool()
39
  def analyze_trend(
40
  name: str,
@@ -44,28 +23,19 @@ def analyze_trend(
44
  narrative: float,
45
  saturation: float
46
  ) -> dict:
47
- """
48
- Führt eine mathematische Trend-Analyse über den skyos_trend_score aus.
49
- Berechnet Virality Index und Aufstiegswahrscheinlichkeiten für Contentpläne.
50
- """
51
  return skyos_trend_score(name, share_rate, comment_depth, hook_score, narrative, saturation)
52
 
53
-
54
  @mcp.tool()
55
- def crm_core_access(command: str) -> dict:
56
- """
57
- Schnittstelle zum CRM Core Modul.
58
- Erstellt Leads, filtert Prioritäten und analysiert Plattformen aus dem Text.
59
- """
60
- return process_crm_message(command)
61
-
62
 
63
  @mcp.tool()
64
  def skyos_process_trigger(action: str) -> str:
65
- """Trigger für skyos_process zum Starten von automatisierten Workflows."""
66
- return f"SkyOS Process: Aktion '{action}' erfolgreich eingeleitet und im Hintergrund gestartet."
67
-
68
 
69
  if __name__ == "__main__":
70
- # Startet den MCP Server im Standard-Transportmodus (stdio)
71
  mcp.run()
 
 
 
 
 
 
 
 
1
  from mcp.server.fastmcp import FastMCP
2
+ from router import route, status, skyos_trend_score
 
 
 
 
3
 
4
  # Initialisierung des MCP-Servers
5
  mcp = FastMCP("SkyOS_MCP_Server")
6
 
 
7
  @mcp.tool()
8
  def route_request(message: str) -> str:
9
+ """Leitet Anfragen durch den SkyOS Router."""
10
+ return str(route(message))
 
 
 
 
 
 
 
 
11
 
12
  @mcp.tool()
13
  def get_system_status() -> str:
14
  """Gibt den aktuellen Status des SkyOS-Systems zurück."""
15
  return status()
16
 
 
17
  @mcp.tool()
18
  def analyze_trend(
19
  name: str,
 
23
  narrative: float,
24
  saturation: float
25
  ) -> dict:
26
+ """Führt eine Trend-Analyse über den skyos_trend_score aus."""
 
 
 
27
  return skyos_trend_score(name, share_rate, comment_depth, hook_score, narrative, saturation)
28
 
 
29
  @mcp.tool()
30
+ def crm_core_access(command: str) -> str:
31
+ """Schnittstelle zum CRM Core Modul."""
32
+ # Hier wird die direkte Anbindung an den CRM Core abgebildet
33
+ return f"CRM Core: Befehl '{command}' verarbeitet."
 
 
 
34
 
35
  @mcp.tool()
36
  def skyos_process_trigger(action: str) -> str:
37
+ """Trigger für skyos_process zum Starten von Workflows."""
38
+ return f"SkyOS Process: Aktion '{action}' eingeleitet."
 
39
 
40
  if __name__ == "__main__":
 
41
  mcp.run()
modules/adapters/base_adapter.py DELETED
@@ -1,33 +0,0 @@
1
- """
2
- base_adapter.py
3
-
4
- Basisklasse aller Sync-Adapter.
5
- """
6
-
7
- from __future__ import annotations
8
-
9
- from abc import ABC, abstractmethod
10
-
11
-
12
- class BaseAdapter(ABC):
13
-
14
- @property
15
- @abstractmethod
16
- def name(self) -> str:
17
- ...
18
-
19
- @abstractmethod
20
- def connect(self) -> bool:
21
- ...
22
-
23
- @abstractmethod
24
- def pull(self):
25
- ...
26
-
27
- @abstractmethod
28
- def push(self, data):
29
- ...
30
-
31
- @abstractmethod
32
- def sync(self):
33
- ...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/adapters/huggingface_adapter.py DELETED
@@ -1,154 +0,0 @@
1
- """
2
- huggingface_adapter.py
3
- SkyOS Hugging Face Adapter
4
-
5
- Adapter für die Integration von Hugging Face
6
- Modellen und APIs in den SkyOS Sync Manager / Core.
7
-
8
- Autor: Sky Meilin
9
- Projekt: SkyOS
10
- """
11
-
12
- from __future__ import annotations
13
-
14
- import os
15
- from ..logger import logger
16
- from .base_adapter import BaseAdapter
17
-
18
- # Offizielles Hugging Face SDK
19
- try:
20
- from huggingface_hub import InferenceClient
21
- except ImportError:
22
- InferenceClient = None
23
-
24
-
25
- class HuggingFaceAdapter(BaseAdapter):
26
- """
27
- Adapter zur Kommunikation mit Hugging Face APIs und Modellen.
28
- """
29
-
30
- def __init__(self, model_id: str = "meta-llama/Llama-3-8B-Instruct") -> None:
31
- self._connected = False
32
- self.model_id = model_id
33
- self.client: InferenceClient | None = None
34
-
35
- # ---------------------------------------------------------
36
- # Eigenschaften
37
- # ---------------------------------------------------------
38
-
39
- @property
40
- def name(self) -> str:
41
- return "Hugging Face"
42
-
43
- @property
44
- def connected(self) -> bool:
45
- return self._connected
46
-
47
- # ---------------------------------------------------------
48
- # Verbindung
49
- # ---------------------------------------------------------
50
-
51
- def connect(self) -> bool:
52
- """
53
- Initialisiert den Hugging Face Inference Client mit dem API-Token.
54
- """
55
- if InferenceClient is None:
56
- logger.error(
57
- "%s: 'huggingface_hub' Bibliothek ist nicht installiert. "
58
- "Bitte installiere sie mit 'pip install huggingface_hub'.",
59
- self.name
60
- )
61
- self._connected = False
62
- return False
63
-
64
- # Sucht das Token aus den Umgebungsvariablen (z.B. in deiner .env)
65
- hf_token = os.getenv("HF_TOKEN") or os.getenv("HUGGINGFACE_CO_API_TOKEN")
66
-
67
- try:
68
- # Verbindung wird mit dem Client-Objekt aufgebaut
69
- self.client = InferenceClient(model=self.model_id, token=hf_token)
70
- self._connected = True
71
-
72
- logger.info(
73
- "%s verbunden. Standard-Modell: %s (Token vorhanden: %s)",
74
- self.name,
75
- self.model_id,
76
- "Ja" if hf_token else "Nein (Öffentliche API)"
77
- )
78
- return True
79
-
80
- except Exception as error:
81
- logger.exception(
82
- "%s Verbindung fehlgeschlagen: %s",
83
- self.name,
84
- error
85
- )
86
- self._connected = False
87
- return False
88
-
89
- def disconnect(self) -> None:
90
- """
91
- Trennt die Verbindung zum Client.
92
- """
93
- self.client = None
94
- self._connected = False
95
- logger.info("%s getrennt.", self.name)
96
-
97
- def is_connected(self) -> bool:
98
- """
99
- Gibt den Verbindungsstatus zurück.
100
- """
101
- return self._connected
102
-
103
- # ---------------------------------------------------------
104
- # Inference Funktionalität (Schnittstelle für den Core)
105
- # ---------------------------------------------------------
106
-
107
- def generate_text(self, prompt: str, **kwargs) -> str | None:
108
- """
109
- Sendet einen Prompt an das geladene Hugging Face Modell.
110
- """
111
- if not self._connected or not self.client:
112
- logger.warning("%s: Textgenerierung nicht möglich – nicht verbunden.", self.name)
113
- return None
114
-
115
- try:
116
- # Nutzt die Standard-Textgenerierung des Inference Clients
117
- response = self.client.text_generation(prompt, **kwargs)
118
- return response
119
- except Exception as error:
120
- logger.error("%s Fehler bei der Textgenerierung: %s", self.name, error)
121
- return None
122
-
123
- # ---------------------------------------------------------
124
- # BaseAdapter (Synchronisation)
125
- # ---------------------------------------------------------
126
-
127
- def pull(self) -> dict | None:
128
- """
129
- Phase 2: Status-Check des Modells oder Abruf von Metadaten über das Repository.
130
- """
131
- if not self._connected or not self.client:
132
- return None
133
-
134
- try:
135
- # Beispielhafter Pull: Modell-Informationen abrufen
136
- model_info = {"model_id": self.model_id, "status": "aktiv/bereit"}
137
- return model_info
138
- except Exception as error:
139
- logger.error("%s Fehler beim Pull der Modell-Daten: %s", self.name, error)
140
- return None
141
-
142
- def push(self, data: dict) -> bool:
143
- """
144
- Phase 3: Falls nötig, Konfigurationen oder Logs an Hugging Face Repositories
145
- oder Spaces senden (Standardmäßig auf True gesetzt).
146
- """
147
- return True
148
-
149
- def sync(self) -> bool:
150
- """
151
- Prüft die Erreichbarkeit des Modells.
152
- """
153
- logger.info("Starte Sync für %s...", self.name)
154
- return self.connect()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/adapters/init.py DELETED
@@ -1,24 +0,0 @@
1
- """
2
- SkyOS Sync Adapters
3
- """
4
-
5
- from .sync_manager import SyncManager
6
- from .registry import SyncRegistry
7
- from .scheduler import SyncScheduler
8
- from .conflict_resolver import ConflictResolver
9
-
10
- from .adapters import (
11
- BaseAdapter,
12
- GoogleSheetsAdapter,
13
- HuggingFaceAdapter,
14
- )
15
-
16
- __all__ = [
17
- "SyncManager",
18
- "SyncRegistry",
19
- "SyncScheduler",
20
- "ConflictResolver",
21
- "BaseAdapter",
22
- "GoogleSheetsAdapter",
23
- "HuggingFaceAdapter",
24
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/adapters/sheets_adapter.py DELETED
@@ -1,175 +0,0 @@
1
- """
2
- sheets_adapter.py
3
- SkyOS Google Sheets Adapter
4
-
5
- Adapter für die Anbindung von Google Sheets
6
- an den SkyOS Sync Manager.
7
-
8
- Autor: Sky Meilin
9
- Projekt: SkyOS
10
- """
11
-
12
- from __future__ import annotations
13
-
14
- import logging
15
-
16
- from ..logger import logger
17
- from .base_adapter import BaseAdapter
18
-
19
- # Vorhandene Google-Module von SkyOS
20
- from ...Google.auth import GoogleAuth
21
- from ...Google.sheets_gateway import SheetsGateway
22
-
23
-
24
- class GoogleSheetsAdapter(BaseAdapter):
25
- """
26
- Adapter für Google Sheets.
27
- """
28
-
29
- def __init__(self, spreadsheet_id: str | None = None) -> None:
30
- self._connected = False
31
- self.auth = GoogleAuth()
32
- self.gateway = SheetsGateway(self.auth)
33
- # Die ID der Google Sheet-Datei, die synchronisiert werden soll
34
- self.spreadsheet_id = spreadsheet_id
35
-
36
- # ---------------------------------------------------------
37
- # Eigenschaften
38
- # ---------------------------------------------------------
39
-
40
- @property
41
- def name(self) -> str:
42
- return "Google Sheets"
43
-
44
- @property
45
- def connected(self) -> bool:
46
- return self._connected
47
-
48
- # ---------------------------------------------------------
49
- # Verbindung
50
- # ---------------------------------------------------------
51
-
52
- def connect(self) -> bool:
53
- """
54
- Baut die Verbindung zu Google auf.
55
- """
56
- try:
57
- self.auth.authenticate()
58
- self.gateway.connect()
59
- self._connected = True
60
-
61
- logger.info(
62
- "%s verbunden.",
63
- self.name,
64
- )
65
- return True
66
-
67
- except Exception as error:
68
- logger.exception(
69
- "%s Verbindung fehlgeschlagen: %s",
70
- self.name,
71
- error,
72
- )
73
- self._connected = False
74
- return False
75
-
76
- def disconnect(self) -> None:
77
- """
78
- Trennt die Verbindung.
79
- """
80
- self._connected = False
81
- logger.info(
82
- "%s getrennt.",
83
- self.name,
84
- )
85
-
86
- def is_connected(self) -> bool:
87
- """
88
- Verbindungsstatus.
89
- """
90
- return self._connected
91
-
92
- # ---------------------------------------------------------
93
- # Informationen
94
- # ---------------------------------------------------------
95
-
96
- def list_sheets(self) -> list[str]:
97
- """
98
- Gibt alle Tabellenblätter (Locations) zurück.
99
- """
100
- if not self._connected or not self.spreadsheet_id:
101
- return []
102
-
103
- try:
104
- # Holt alle Tabellenblatt-Namen der aktuellen Datei
105
- return self.gateway.get_sheet_names(self.spreadsheet_id)
106
- except Exception as error:
107
- logger.error("Fehler beim Abrufen der Tabellenblätter: %s", error)
108
- return []
109
-
110
- # ---------------------------------------------------------
111
- # BaseAdapter (Synchronisation)
112
- # ---------------------------------------------------------
113
-
114
- def pull(self) -> dict[str, list[list]] | None:
115
- """
116
- Phase 2: Daten aus den Google Sheets (nach Locations/Tabs aufgeteilt) abrufen.
117
- Gibt ein Dictionary zurück: { "Location_Name": [[Zeile1], [Zeile2], ...] }
118
- """
119
- if not self._connected or not self.spreadsheet_id:
120
- logger.warning("%s: Pull nicht möglich - keine Verbindung oder Spreadsheet-ID.", self.name)
121
- return None
122
-
123
- try:
124
- sheets = self.list_sheets()
125
- pulled_data = {}
126
-
127
- for sheet_name in sheets:
128
- # Liest alle Daten aus dem jeweiligen Tabellenblatt (der Location)
129
- data = self.gateway.read_values(self.spreadsheet_id, range_name=f"'{sheet_name}'!A:Z")
130
- pulled_data[sheet_name] = data
131
- logger.debug("Daten für Location '%s' erfolgreich gepullt.", sheet_name)
132
-
133
- return pulled_data
134
-
135
- except Exception as error:
136
- logger.exception("Fehler beim Pull der Google Sheets Daten: %s", error)
137
- return None
138
-
139
- def push(self, data: dict[str, list[list]]) -> bool:
140
- """
141
- Phase 3: Synchronisierte Daten zurück in die Google Sheets schreiben.
142
- Erwartet Daten im Format: { "Location_Name": [[Zeile1], [Zeile2], ...] }
143
- """
144
- if not self._connected or not self.spreadsheet_id:
145
- logger.warning("%s: Push nicht möglich - keine Verbindung oder Spreadsheet-ID.", self.name)
146
- return False
147
-
148
- try:
149
- for sheet_name, rows in data.items():
150
- # Überschreibt oder aktualisiert das Tabellenblatt für diese Location
151
- self.gateway.write_values(
152
- self.spreadsheet_id,
153
- range_name=f"'{sheet_name}'!A1",
154
- values=rows
155
- )
156
- logger.debug("Daten für Location '%s' erfolgreich gepusht.", sheet_name)
157
-
158
- return True
159
-
160
- except Exception as error:
161
- logger.exception("Fehler beim Push der Google Sheets Daten: %s", error)
162
- return False
163
-
164
- def sync(self) -> bool:
165
- """
166
- Führt einen lokalen Test- oder Direktsync durch (Pull -> Push).
167
- """
168
- logger.info("Starte Sync für %s...", self.name)
169
- data = self.pull()
170
- if data is None:
171
- return False
172
-
173
- # Hier könnte ein Verarbeitungs- oder Abgleichschritt stattfinden
174
-
175
- return self.push(data)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/avatar_streamer.py CHANGED
@@ -3,49 +3,45 @@
3
  import time
4
  from typing import Dict, Any
5
 
 
6
  class AvatarStreamer:
7
- # Klassen-Attribute verhindern den Zustandverlust bei Neu-Instanziierung
8
- _avatar_name = "Sky Meilin"
9
- _status = "idle"
10
 
11
  def __init__(self):
12
- print("AvatarStreamer geladen")
13
-
14
- @property
15
- def avatar_name(self) -> str:
16
- return AvatarStreamer._avatar_name
17
-
18
- @avatar_name.setter
19
- def avatar_name(self, name: str):
20
- AvatarStreamer._avatar_name = name
21
 
22
- @property
23
- def status(self) -> str:
24
- return AvatarStreamer._status
25
 
26
- @status.setter
27
- def status(self, value: str):
28
- AvatarStreamer._status = value
29
 
30
  def set_avatar(self, name: str):
 
31
  self.avatar_name = name
32
 
33
- def start_stream(self) -> Dict[str, Any]:
 
34
  self.status = "streaming"
 
35
  return {
36
  "status": self.status,
37
  "avatar": self.avatar_name
38
  }
39
 
40
- def stop_stream(self) -> Dict[str, Any]:
 
41
  self.status = "offline"
 
42
  return {
43
  "status": self.status,
44
  "avatar": self.avatar_name
45
  }
46
 
47
- def send_message(self, text: str) -> Dict[str, Any]:
 
 
 
 
48
  if self.status != "streaming":
 
49
  return {
50
  "error": "Avatar nicht aktiv"
51
  }
@@ -55,10 +51,15 @@ class AvatarStreamer:
55
  "message": text,
56
  "timestamp": time.time()
57
  }
 
58
  return payload
59
 
60
- def emotion(self, emotion_name: str) -> Dict[str, Any]:
 
 
 
 
61
  return {
62
  "avatar": self.avatar_name,
63
  "emotion": emotion_name
64
- }
 
3
  import time
4
  from typing import Dict, Any
5
 
6
+
7
  class AvatarStreamer:
 
 
 
8
 
9
  def __init__(self):
 
 
 
 
 
 
 
 
 
10
 
11
+ print("AvatarStreamer geladen")
 
 
12
 
13
+ self.avatar_name = "Sky Meilin"
14
+ self.status = "idle"
 
15
 
16
  def set_avatar(self, name: str):
17
+
18
  self.avatar_name = name
19
 
20
+ def start_stream(self):
21
+
22
  self.status = "streaming"
23
+
24
  return {
25
  "status": self.status,
26
  "avatar": self.avatar_name
27
  }
28
 
29
+ def stop_stream(self):
30
+
31
  self.status = "offline"
32
+
33
  return {
34
  "status": self.status,
35
  "avatar": self.avatar_name
36
  }
37
 
38
+ def send_message(
39
+ self,
40
+ text: str
41
+ ) -> Dict[str, Any]:
42
+
43
  if self.status != "streaming":
44
+
45
  return {
46
  "error": "Avatar nicht aktiv"
47
  }
 
51
  "message": text,
52
  "timestamp": time.time()
53
  }
54
+
55
  return payload
56
 
57
+ def emotion(
58
+ self,
59
+ emotion_name: str
60
+ ):
61
+
62
  return {
63
  "avatar": self.avatar_name,
64
  "emotion": emotion_name
65
+ }
modules/creator_os.py CHANGED
@@ -1,18 +1,7 @@
1
  """
2
- modules/creator_os.py
3
- Creator OS — Paket-Initialisierung & Core-Metadaten
4
- Zentrale Definition der System-Rolle und Markenarchitektur.
5
  """
6
 
7
- PACKAGE_VERSION = "modules_v1_3_2026_06_28"
8
-
9
- # Globale System-Eckpfeiler
10
- SYSTEM_AUTHORITY = {
11
- "role": "Head of Automation",
12
- "company": "Agency Level Up",
13
- "focus": [
14
- "KI-gestützte Creator-Workflows",
15
- "Automatisierte Content-Systeme",
16
- "Digitale Markenarchitekturen für skalierbare Projekte"
17
- ]
18
- }
 
1
  """
2
+ modules/__init__.py
3
+ Creator OS — Paket-Initialisierung
4
+ Macht den modules/ Ordner zu einem Python-Paket.
5
  """
6
 
7
+ PACKAGE_VERSION = "modules_v1_2026_06_02"
 
 
 
 
 
 
 
 
 
 
 
modules/crypto_engine.py CHANGED
@@ -1,7 +1,6 @@
1
  # modules/crypto_engine.py
2
 
3
  import hashlib
4
- import json
5
  import secrets
6
  from typing import Dict, Any
7
 
@@ -9,33 +8,49 @@ from typing import Dict, Any
9
  class CryptoEngine:
10
 
11
  def __init__(self):
 
12
  print("CryptoEngine geladen")
 
13
  self.algorithm = "sha256"
14
 
15
  def hash_text(self, text: str) -> str:
16
- if not text:
17
- return ""
18
- return hashlib.sha256(text.encode("utf-8")).hexdigest()
19
 
20
- def generate_token(self, length: int = 32) -> str:
 
 
 
 
 
 
 
 
21
  return secrets.token_hex(length)
22
 
23
- def verify_hash(self, text: str, hashed: str) -> bool:
24
- return self.hash_text(text) == hashed
 
 
 
25
 
26
- def secure_payload(self, payload: Dict[str, Any]) -> Dict[str, Any]:
27
- if not payload:
28
- payload = {}
 
 
 
 
 
 
 
29
 
30
- # Sort_keys=True sorgt für eine deterministische und stabile String-Form
31
- payload_string = json.dumps(payload, sort_keys=True)
32
  payload_hash = self.hash_text(payload_string)
33
 
34
  return {
35
  "payload": payload,
36
  "hash": payload_hash,
37
- "algorithm": self.algorithm,
38
  }
39
 
40
  def create_session_key(self) -> str:
41
- return secrets.token_urlsafe(64)
 
 
1
  # modules/crypto_engine.py
2
 
3
  import hashlib
 
4
  import secrets
5
  from typing import Dict, Any
6
 
 
8
  class CryptoEngine:
9
 
10
  def __init__(self):
11
+
12
  print("CryptoEngine geladen")
13
+
14
  self.algorithm = "sha256"
15
 
16
  def hash_text(self, text: str) -> str:
 
 
 
17
 
18
+ return hashlib.sha256(
19
+ text.encode("utf-8")
20
+ ).hexdigest()
21
+
22
+ def generate_token(
23
+ self,
24
+ length: int = 32
25
+ ) -> str:
26
+
27
  return secrets.token_hex(length)
28
 
29
+ def verify_hash(
30
+ self,
31
+ text: str,
32
+ hashed: str
33
+ ) -> bool:
34
 
35
+ new_hash = self.hash_text(text)
36
+
37
+ return new_hash == hashed
38
+
39
+ def secure_payload(
40
+ self,
41
+ payload: Dict[str, Any]
42
+ ) -> Dict[str, Any]:
43
+
44
+ payload_string = str(payload)
45
 
 
 
46
  payload_hash = self.hash_text(payload_string)
47
 
48
  return {
49
  "payload": payload,
50
  "hash": payload_hash,
51
+ "algorithm": self.algorithm
52
  }
53
 
54
  def create_session_key(self) -> str:
55
+
56
+ return secrets.token_urlsafe(64)
modules/dashboard/__init__.py DELETED
@@ -1,112 +0,0 @@
1
- """
2
- __init__.py
3
- SkyOS Dashboard Module
4
-
5
- Initialisiert das Armaturenbrett-Modul.
6
-
7
- Autor: Sky Meilin
8
- Projekt: SkyOS
9
- """
10
-
11
- from __future__ import annotations
12
-
13
-
14
- # ---------------------------------------------------------
15
- # Modul Informationen
16
- # ---------------------------------------------------------
17
-
18
- __title__ = "SkyOS Armaturenbrett"
19
- __version__ = "0.1.0"
20
- __author__ = "Sky Meilin"
21
-
22
-
23
- # ---------------------------------------------------------
24
- # Konfiguration
25
- # ---------------------------------------------------------
26
-
27
- from .config import (
28
- DASHBOARD,
29
- UI,
30
- BACKEND,
31
- get_config,
32
- )
33
-
34
-
35
- # ---------------------------------------------------------
36
- # Theme
37
- # ---------------------------------------------------------
38
-
39
- from .theme import (
40
- DashboardTheme,
41
- DEFAULT_THEME,
42
- get_theme,
43
- )
44
-
45
-
46
- # ---------------------------------------------------------
47
- # Icons
48
- # ---------------------------------------------------------
49
-
50
- from .icons import (
51
- ICONS,
52
- get_icon,
53
- )
54
-
55
-
56
- # ---------------------------------------------------------
57
- # Utilities
58
- # ---------------------------------------------------------
59
-
60
- from .utils import (
61
- current_time,
62
- current_timestamp,
63
- format_status,
64
- clean_text,
65
- )
66
-
67
-
68
- # ---------------------------------------------------------
69
- # Event Handler
70
- # ---------------------------------------------------------
71
-
72
- from .event_handler import (
73
- register_events,
74
- send_message,
75
- refresh_status,
76
- refresh_header,
77
- )
78
-
79
-
80
- # ---------------------------------------------------------
81
- # Public API
82
- # ---------------------------------------------------------
83
-
84
- __all__ = [
85
-
86
- # Config
87
- "DASHBOARD",
88
- "UI",
89
- "BACKEND",
90
- "get_config",
91
-
92
- # Theme
93
- "DashboardTheme",
94
- "DEFAULT_THEME",
95
- "get_theme",
96
-
97
- # Icons
98
- "ICONS",
99
- "get_icon",
100
-
101
- # Utils
102
- "current_time",
103
- "current_timestamp",
104
- "format_status",
105
- "clean_text",
106
-
107
- # Events
108
- "register_events",
109
- "send_message",
110
- "refresh_status",
111
- "refresh_header",
112
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/dashboard/chat_panel.py DELETED
@@ -1,41 +0,0 @@
1
- """
2
- chat_panel.py
3
- SkyOS Chat
4
- """
5
-
6
- from __future__ import annotations
7
-
8
- import gradio as gr
9
-
10
-
11
- def build_chat_panel() -> dict:
12
-
13
- with gr.Column(scale=2):
14
-
15
- chatbot = gr.Chatbot(
16
- label="SkyOS Chat",
17
- type="messages",
18
- )
19
-
20
- message = gr.Textbox(
21
- label="Nachricht",
22
- placeholder="Nachricht eingeben...",
23
- )
24
-
25
- audio = gr.Audio(
26
- sources=["microphone"],
27
- type="filepath",
28
- label="Sprache",
29
- )
30
-
31
- send = gr.Button(
32
- "Senden",
33
- variant="primary",
34
- )
35
-
36
- return {
37
- "chatbot": chatbot,
38
- "message": message,
39
- "audio": audio,
40
- "send": send,
41
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/dashboard/config.py DELETED
@@ -1,97 +0,0 @@
1
- """
2
- config.py
3
- SkyOS Dashboard Configuration
4
-
5
- Zentrale Konfiguration für UI, Events und Backend-Verbindungen.
6
-
7
- Autor: Sky Meilin
8
- Projekt: SkyOS
9
- """
10
-
11
- from __future__ import annotations
12
-
13
- from dataclasses import dataclass
14
-
15
-
16
- # ---------------------------------------------------------
17
- # Dashboard Settings
18
- # ---------------------------------------------------------
19
-
20
- @dataclass(frozen=True)
21
- class DashboardConfig:
22
- """
23
- Globale Dashboard-Konfiguration.
24
- """
25
-
26
- title: str = "SkyOS Dashboard"
27
- version: str = "0.1.0"
28
-
29
- refresh_interval: int = 5000 # Millisekunden
30
-
31
- enable_audio: bool = True
32
- enable_stream: bool = True
33
- enable_navigation: bool = True
34
-
35
- debug_mode: bool = False
36
-
37
-
38
- # ---------------------------------------------------------
39
- # UI Settings
40
- # ---------------------------------------------------------
41
-
42
- @dataclass(frozen=True)
43
- class UIConfig:
44
- """
45
- Layout-Konfiguration.
46
- """
47
-
48
- sidebar_width: int = 280
49
- panel_radius: int = 12
50
-
51
- max_chat_height: int = 600
52
-
53
- compact_mode: bool = False
54
-
55
-
56
- # ---------------------------------------------------------
57
- # Backend Settings
58
- # ---------------------------------------------------------
59
-
60
- @dataclass(frozen=True)
61
- class BackendConfig:
62
- """
63
- Verbindung zu SkyOS Backend-Modulen.
64
- """
65
-
66
- router_enabled: bool = False
67
- status_monitor_enabled: bool = False
68
-
69
- router_name: str = "SkyOS Router"
70
- creator_name: str = "CreatorOS"
71
-
72
-
73
- # ---------------------------------------------------------
74
- # Runtime Configuration
75
- # ---------------------------------------------------------
76
-
77
- DASHBOARD = DashboardConfig()
78
-
79
- UI = UIConfig()
80
-
81
- BACKEND = BackendConfig()
82
-
83
-
84
- # ---------------------------------------------------------
85
- # Helper
86
- # ---------------------------------------------------------
87
-
88
- def get_config():
89
- """
90
- Liefert komplette Dashboard-Konfiguration.
91
- """
92
-
93
- return {
94
- "dashboard": DASHBOARD,
95
- "ui": UI,
96
- "backend": BACKEND,
97
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/dashboard/dashboard.py DELETED
@@ -1,74 +0,0 @@
1
- """
2
- dashboard.py
3
- SkyOS Dashboard Builder
4
-
5
- Erstellt das komplette Gradio-Dashboard und verbindet
6
- alle Dashboard-Module.
7
-
8
- Autor: Sky Meilin
9
- Projekt: SkyOS
10
- """
11
-
12
- from __future__ import annotations
13
-
14
- import gradio as gr
15
-
16
- from .theme import THEME
17
- from .header import build_header
18
- from .status_panel import build_status_panel
19
- from .stream_panel import build_stream_panel
20
- from .chat_panel import build_chat_panel
21
- from .navigation_panel import build_navigation_panel
22
- from .event_handler import register_events
23
-
24
-
25
- def create_dashboard() -> gr.Blocks:
26
- """
27
- Erstellt das komplette Dashboard.
28
- """
29
-
30
- with gr.Blocks(
31
- title="SkyOS Dashboard"
32
- ) as demo:
33
-
34
- # -----------------------------------------
35
- # Header
36
- # -----------------------------------------
37
- build_header()
38
-
39
- gr.Markdown("---")
40
-
41
- # -----------------------------------------
42
- # Status
43
- # -----------------------------------------
44
- status_components = build_status_panel()
45
-
46
- gr.Markdown("---")
47
-
48
- # -----------------------------------------
49
- # Hauptbereich
50
- # -----------------------------------------
51
- with gr.Row():
52
-
53
- stream_components = build_stream_panel()
54
-
55
- chat_components = build_chat_panel()
56
-
57
- gr.Markdown("---")
58
-
59
- # -----------------------------------------
60
- # Navigation
61
- # -----------------------------------------
62
- navigation_components = build_navigation_panel()
63
-
64
- # -----------------------------------------
65
- # Events verbinden
66
- # -----------------------------------------
67
- register_events(
68
- status=status_components,
69
- stream=stream_components,
70
- chat=chat_components,
71
- navigation=navigation_components,
72
- )
73
-
74
- return demo
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/dashboard/event_handler.py DELETED
@@ -1,184 +0,0 @@
1
- """
2
- event_handler.py
3
- SkyOS Dashboard Event Handler
4
-
5
- Verbindet alle UI-Komponenten mit den Backend-Modulen.
6
-
7
- Autor: Sky Meilin
8
- Projekt: SkyOS
9
- """
10
-
11
- from __future__ import annotations
12
-
13
- import logging
14
-
15
- logger = logging.getLogger("SkyOS.Dashboard")
16
-
17
-
18
- # ---------------------------------------------------------
19
- # Backend Bridge
20
- # ---------------------------------------------------------
21
-
22
- def process_message(message: str) -> str:
23
- """
24
- Übergangspunkt zum SkyOS Router.
25
-
26
- Wird später ersetzt durch:
27
- Router.handle(message)
28
- """
29
-
30
- return (
31
- "Nachricht empfangen. "
32
- "Die Verarbeitung übernimmt später der SkyOS Router."
33
- )
34
-
35
-
36
- # ---------------------------------------------------------
37
- # Chat Events
38
- # ---------------------------------------------------------
39
-
40
- def send_message(text, audio):
41
- """
42
- Standard-Chatcallback.
43
- """
44
-
45
- try:
46
- if text:
47
- user_input = text
48
-
49
- elif audio:
50
- user_input = "🎤 Spracheingabe empfangen."
51
-
52
- else:
53
- return [], "", None
54
-
55
-
56
- response = process_message(user_input)
57
-
58
- history = [
59
- {
60
- "role": "user",
61
- "content": user_input,
62
- },
63
- {
64
- "role": "assistant",
65
- "content": response,
66
- },
67
- ]
68
-
69
- return history, "", None
70
-
71
- except Exception:
72
- logger.exception("Chat-Verarbeitung fehlgeschlagen.")
73
-
74
- return (
75
- [
76
- {
77
- "role": "assistant",
78
- "content": "⚠️ Fehler bei der Verarbeitung."
79
- }
80
- ],
81
- "",
82
- None,
83
- )
84
-
85
-
86
- # ---------------------------------------------------------
87
- # Status Events
88
- # ---------------------------------------------------------
89
-
90
- def refresh_status():
91
- """
92
- Status-Aktualisierung.
93
-
94
- Später:
95
- StatusMonitor.get_status()
96
- """
97
-
98
- logger.info("Status aktualisiert")
99
-
100
- return (
101
- "🟢 Online",
102
- "🟡 Nicht verbunden",
103
- "🟢 Aktiv",
104
- "🟢 Aktiv",
105
- "🟢 Aktiv",
106
- "🟢 Aktiv",
107
- "🟢 Online",
108
- "🟢 Online",
109
- )
110
-
111
-
112
- # ---------------------------------------------------------
113
- # Header Events
114
- # ---------------------------------------------------------
115
-
116
- def refresh_header():
117
- """
118
- Aktualisiert die Dashboard-Uhr.
119
- """
120
-
121
- from .header import current_time
122
-
123
- return (
124
- current_time(),
125
- )
126
-
127
-
128
- # ---------------------------------------------------------
129
- # Event Registrierung
130
- # ---------------------------------------------------------
131
-
132
- def register_events(
133
- *,
134
- status: dict,
135
- stream: dict,
136
- chat: dict,
137
- navigation: dict,
138
- ):
139
- """
140
- Registriert alle Dashboard-Events.
141
- """
142
-
143
- logger.info("Registriere Dashboard Events...")
144
-
145
-
146
- # Chat Button
147
-
148
- if "send" in chat:
149
-
150
- chat["send"].click(
151
- fn=send_message,
152
- inputs=[
153
- chat["message"],
154
- chat["audio"],
155
- ],
156
- outputs=[
157
- chat["chatbot"],
158
- chat["message"],
159
- chat["audio"],
160
- ],
161
- )
162
-
163
-
164
- # Enter Taste
165
-
166
- if "message" in chat:
167
-
168
- chat["message"].submit(
169
- fn=send_message,
170
- inputs=[
171
- chat["message"],
172
- chat["audio"],
173
- ],
174
- outputs=[
175
- chat["chatbot"],
176
- chat["message"],
177
- chat["audio"],
178
- ],
179
- )
180
-
181
-
182
- logger.info(
183
- "Dashboard Events registriert."
184
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/dashboard/header.py DELETED
@@ -1,113 +0,0 @@
1
- """
2
- header.py
3
- SkyOS Dashboard Header
4
-
5
- Erstellt den Kopfbereich des Dashboards mit
6
- Logo, Systeminformationen und Live-Uhr.
7
-
8
- Autor: Sky Meilin
9
- Projekt: SkyOS
10
- """
11
-
12
- from __future__ import annotations
13
-
14
- from datetime import datetime
15
- import zoneinfo
16
-
17
- import gradio as gr
18
-
19
- from persona_sky_meilin import (
20
- SYSTEM_NAME,
21
- AVATAR_PERSONA,
22
- AVATAR_JOBTITEL,
23
- COMPANY_NAME,
24
- )
25
-
26
- # ---------------------------------------------------------
27
- # Zeitzone
28
- # ---------------------------------------------------------
29
-
30
- BERLIN_TZ = zoneinfo.ZoneInfo("Europe/Berlin")
31
-
32
-
33
- # ---------------------------------------------------------
34
- # Hilfsfunktionen
35
- # ---------------------------------------------------------
36
-
37
- def current_time() -> str:
38
- """Aktuelle Uhrzeit in Deutschland."""
39
-
40
- return datetime.now(BERLIN_TZ).strftime("%d.%m.%Y • %H:%M:%S")
41
-
42
-
43
- # ---------------------------------------------------------
44
- # Header
45
- # ---------------------------------------------------------
46
-
47
- def build_header() -> dict:
48
- """
49
- Erstellt den Dashboard-Header.
50
-
51
- Returns
52
- -------
53
- dict
54
- Referenzen auf Komponenten.
55
- """
56
-
57
- with gr.Column():
58
-
59
- gr.Markdown(
60
- f"""
61
- # 🌌 {SYSTEM_NAME}
62
-
63
- ### 👤 {AVATAR_PERSONA}
64
- **{AVATAR_JOBTITEL}**
65
-
66
- 🏢 {COMPANY_NAME}
67
- """
68
- )
69
-
70
- with gr.Row():
71
-
72
- clock = gr.Textbox(
73
- value=current_time(),
74
- label="🕒 Uhrzeit",
75
- interactive=False,
76
- scale=1,
77
- )
78
-
79
- system = gr.Textbox(
80
- value=SYSTEM_NAME,
81
- label="💻 System",
82
- interactive=False,
83
- scale=1,
84
- )
85
-
86
- company = gr.Textbox(
87
- value=COMPANY_NAME,
88
- label="🏢 Unternehmen",
89
- interactive=False,
90
- scale=1,
91
- )
92
-
93
- return {
94
- "clock": clock,
95
- "system": system,
96
- "company": company,
97
- }
98
-
99
-
100
- # ---------------------------------------------------------
101
- # Live-Update
102
- # ---------------------------------------------------------
103
-
104
- def refresh_header():
105
- """
106
- Aktualisiert die dynamischen Header-Daten.
107
- """
108
-
109
- return {
110
- "clock": current_time(),
111
- "system": SYSTEM_NAME,
112
- "company": COMPANY_NAME,
113
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/dashboard/icons.py DELETED
@@ -1,114 +0,0 @@
1
- """
2
- icons.py
3
- SkyOS Dashboard Icons
4
-
5
- Zentrale Icon-Verwaltung für das Armaturenbrett.
6
-
7
- Autor: Sky Meilin
8
- Projekt: SkyOS
9
- """
10
-
11
- from __future__ import annotations
12
-
13
-
14
- # ---------------------------------------------------------
15
- # System Icons
16
- # ---------------------------------------------------------
17
-
18
- ONLINE = "🟢"
19
- OFFLINE = "⚫"
20
- WARNING = "🟡"
21
- ERROR = "🔴"
22
- ACTIVE = "⚡"
23
- INACTIVE = "○"
24
-
25
-
26
- # ---------------------------------------------------------
27
- # Navigation Icons
28
- # ---------------------------------------------------------
29
-
30
- HOME = "🏠"
31
- DASHBOARD = "📊"
32
- SYSTEM = "⚙️"
33
- SETTINGS = "🔧"
34
- LOGS = "📜"
35
-
36
-
37
- # ---------------------------------------------------------
38
- # Chat Icons
39
- # ---------------------------------------------------------
40
-
41
- CHAT = "💬"
42
- SEND = "📤"
43
- MICROPHONE = "🎤"
44
- USER = "👤"
45
- ASSISTANT = "🤖"
46
-
47
-
48
- # ---------------------------------------------------------
49
- # Stream Icons
50
- # ---------------------------------------------------------
51
-
52
- STREAM = "📡"
53
- VIDEO = "🎥"
54
- AUDIO = "🔊"
55
- LIVE = "🔴"
56
-
57
-
58
- # ---------------------------------------------------------
59
- # Status Icons
60
- # ---------------------------------------------------------
61
-
62
- CPU = "🖥️"
63
- MEMORY = "💾"
64
- NETWORK = "🌐"
65
- DATABASE = "🗄️"
66
- SECURITY = "🛡️"
67
-
68
-
69
- # ---------------------------------------------------------
70
- # Actions
71
- # ---------------------------------------------------------
72
-
73
- REFRESH = "🔄"
74
- SEARCH = "🔍"
75
- SAVE = "💾"
76
- CLOSE = "✖"
77
- CHECK = "✔"
78
-
79
-
80
- # ---------------------------------------------------------
81
- # Icon Sammlung
82
- # ---------------------------------------------------------
83
-
84
- ICONS = {
85
- "online": ONLINE,
86
- "offline": OFFLINE,
87
- "warning": WARNING,
88
- "error": ERROR,
89
-
90
- "home": HOME,
91
- "dashboard": DASHBOARD,
92
- "settings": SETTINGS,
93
-
94
- "chat": CHAT,
95
- "send": SEND,
96
- "microphone": MICROPHONE,
97
-
98
- "stream": STREAM,
99
- "live": LIVE,
100
-
101
- "refresh": REFRESH,
102
- "check": CHECK,
103
- }
104
-
105
-
106
- def get_icon(name: str) -> str:
107
- """
108
- Liefert ein Icon anhand des Namens.
109
- """
110
-
111
- return ICONS.get(
112
- name,
113
- "?"
114
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/dashboard/navigation_panel.py DELETED
@@ -1,53 +0,0 @@
1
- """
2
- navigation_panel.py
3
- Navigation
4
- """
5
-
6
- from __future__ import annotations
7
-
8
- import gradio as gr
9
-
10
-
11
- BUTTON_STYLE = """
12
- width:100%;
13
- padding:15px;
14
- background:#f3f4f6;
15
- border:1px solid #d1d5db;
16
- border-radius:8px;
17
- cursor:pointer;
18
- """
19
-
20
-
21
- def build_navigation_panel():
22
-
23
- gr.Markdown("## 🏢 Navigation")
24
-
25
- with gr.Row():
26
-
27
- gr.HTML(
28
- f'<a href="/management" target="_blank"><button style="{BUTTON_STYLE}">💼 Management</button></a>'
29
- )
30
-
31
- gr.HTML(
32
- f'<a href="/client" target="_blank"><button style="{BUTTON_STYLE}">🤝 Client</button></a>'
33
- )
34
-
35
- gr.HTML(
36
- f'<a href="/creation" target="_blank"><button style="{BUTTON_STYLE}">🎨 Creation</button></a>'
37
- )
38
-
39
- with gr.Row():
40
-
41
- gr.HTML(
42
- f'<a href="/technical" target="_blank"><button style="{BUTTON_STYLE}">📊 Technical</button></a>'
43
- )
44
-
45
- gr.HTML(
46
- f'<a href="/data" target="_blank"><button style="{BUTTON_STYLE}">⚡ Data</button></a>'
47
- )
48
-
49
- gr.HTML(
50
- f'<a href="/settings" target="_blank"><button style="{BUTTON_STYLE}">⚙️ Einstellungen</button></a>'
51
- )
52
-
53
- return {}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/dashboard/status_panel.py DELETED
@@ -1,78 +0,0 @@
1
- """
2
- status_panel.py
3
- SkyOS Dashboard
4
-
5
- Systemstatus-Panel.
6
- """
7
-
8
- from __future__ import annotations
9
-
10
- import gradio as gr
11
-
12
-
13
- def build_status_panel() -> dict:
14
-
15
- gr.Markdown("## 📊 Systemstatus")
16
-
17
- with gr.Row():
18
-
19
- avatar = gr.Textbox(
20
- value="🟢 Online",
21
- label="Avatar",
22
- interactive=False,
23
- )
24
-
25
- google = gr.Textbox(
26
- value="🟡 Nicht verbunden",
27
- label="Google",
28
- interactive=False,
29
- )
30
-
31
- router = gr.Textbox(
32
- value="🟢 Aktiv",
33
- label="Router",
34
- interactive=False,
35
- )
36
-
37
- crm = gr.Textbox(
38
- value="🟢 Aktiv",
39
- label="CRM",
40
- interactive=False,
41
- )
42
-
43
- with gr.Row():
44
-
45
- creator = gr.Textbox(
46
- value="🟢 Aktiv",
47
- label="Creator",
48
- interactive=False,
49
- )
50
-
51
- worklog = gr.Textbox(
52
- value="🟢 Aktiv",
53
- label="Worklog",
54
- interactive=False,
55
- )
56
-
57
- github = gr.Textbox(
58
- value="🟢 Online",
59
- label="GitHub",
60
- interactive=False,
61
- )
62
-
63
- huggingface = gr.Textbox(
64
- value="🟢 Online",
65
- label="Hugging Face",
66
- interactive=False,
67
- )
68
-
69
- return {
70
- "avatar": avatar,
71
- "google": google,
72
- "router": router,
73
- "crm": crm,
74
- "creator": creator,
75
- "worklog": worklog,
76
- "github": github,
77
- "huggingface": huggingface,
78
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/dashboard/theme.py DELETED
@@ -1,66 +0,0 @@
1
- """
2
- theme.py
3
- SkyOS Dashboard Theme
4
-
5
- Zentrale Darstellungskonfiguration für das Armaturenbrett.
6
-
7
- Autor: Sky Meilin
8
- Projekt: SkyOS
9
- """
10
-
11
- from __future__ import annotations
12
-
13
- from dataclasses import dataclass
14
-
15
-
16
- # ---------------------------------------------------------
17
- # Theme Definition
18
- # ---------------------------------------------------------
19
-
20
- @dataclass(frozen=True)
21
- class DashboardTheme:
22
- """
23
- Farb- und Style-Konfiguration des Dashboards.
24
- """
25
-
26
- # Hintergrund
27
- background: str = "#0b1120"
28
- surface: str = "#111827"
29
- panel: str = "#1f2937"
30
-
31
- # Text
32
- text: str = "#f8fafc"
33
- muted: str = "#94a3b8"
34
-
35
- # Statusfarben
36
- online: str = "#22c55e"
37
- warning: str = "#eab308"
38
- error: str = "#ef4444"
39
- offline: str = "#64748b"
40
-
41
- # Akzente
42
- primary: str = "#38bdf8"
43
- secondary: str = "#6366f1"
44
-
45
- # UI
46
- border_radius: str = "12px"
47
- panel_padding: str = "16px"
48
-
49
-
50
- # ---------------------------------------------------------
51
- # Standard Theme
52
- # ---------------------------------------------------------
53
-
54
- DEFAULT_THEME = DashboardTheme()
55
-
56
-
57
- # ---------------------------------------------------------
58
- # Theme Zugriff
59
- # ---------------------------------------------------------
60
-
61
- def get_theme() -> DashboardTheme:
62
- """
63
- Gibt das aktive Dashboard Theme zurück.
64
- """
65
-
66
- return DEFAULT_THEME
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/dashboard/utils.py DELETED
@@ -1,91 +0,0 @@
1
- """
2
- utils.py
3
- SkyOS Dashboard Utilities
4
-
5
- Gemeinsame Hilfsfunktionen für das Armaturenbrett.
6
-
7
- Autor: Sky Meilin
8
- Projekt: SkyOS
9
- """
10
-
11
- from __future__ import annotations
12
-
13
- from datetime import datetime
14
-
15
-
16
- # ---------------------------------------------------------
17
- # Zeitfunktionen
18
- # ---------------------------------------------------------
19
-
20
- def current_timestamp() -> str:
21
- """
22
- Erstellt einen formatierten Zeitstempel.
23
- """
24
-
25
- return datetime.now().strftime(
26
- "%d.%m.%Y %H:%M:%S"
27
- )
28
-
29
-
30
- def current_time() -> str:
31
- """
32
- Liefert aktuelle Uhrzeit.
33
- """
34
-
35
- return datetime.now().strftime(
36
- "%H:%M:%S"
37
- )
38
-
39
-
40
- # ---------------------------------------------------------
41
- # Status Helfer
42
- # ---------------------------------------------------------
43
-
44
- def status_icon(active: bool) -> str:
45
- """
46
- Gibt Statussymbol zurück.
47
- """
48
-
49
- return "🟢" if active else "🔴"
50
-
51
-
52
- def format_status(
53
- name: str,
54
- active: bool,
55
- ) -> str:
56
- """
57
- Erstellt eine Statusanzeige.
58
- """
59
-
60
- return (
61
- f"{status_icon(active)} {name}"
62
- )
63
-
64
-
65
- # ---------------------------------------------------------
66
- # Text Helfer
67
- # ---------------------------------------------------------
68
-
69
- def clean_text(text: str | None) -> str:
70
- """
71
- Bereinigt Benutzereingaben.
72
- """
73
-
74
- if not text:
75
- return ""
76
-
77
- return text.strip()
78
-
79
-
80
- def limit_text(
81
- text: str,
82
- length: int = 100,
83
- ) -> str:
84
- """
85
- Kürzt lange Texte für UI-Anzeigen.
86
- """
87
-
88
- if len(text) <= length:
89
- return text
90
-
91
- return text[:length] + "..."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/fanvue_guide.py CHANGED
@@ -1,7 +1,7 @@
1
  """
2
- modules/fanvue_guide.py
3
- Creator OS — Fanvue Guide Module
4
- Enthält Leitfäden und Strukturen für die Fanvue-Plattform.
5
  """
6
 
7
- PACKAGE_VERSION = "modules_fanvue_v1_2026_06_02"
 
1
  """
2
+ modules/__init__.py
3
+ Creator OS — Paket-Initialisierung
4
+ Macht den modules/ Ordner zu einem Python-Paket.
5
  """
6
 
7
+ PACKAGE_VERSION = "modules_v1_2026_06_02"
modules/google/__init__.py DELETED
@@ -1,42 +0,0 @@
1
- """
2
- SkyOS Google Integration Package
3
- ================================
4
- Zentrale Exporte aller Google-Module.
5
-
6
- Autor: Sky Meilin
7
- Projekt: SkyOS FullCore
8
- """
9
-
10
- from .config import GoogleConfig
11
- from .auth import GoogleAuth
12
- from .oauth import OAuthManager
13
-
14
- from .calendar_gateway import CalendarGateway
15
- from .sheets_gateway import SheetsGateway
16
- from .docs_gateway import DocsGateway
17
- from .drive_gateway import DriveGateway
18
- from .gmail_gateway import GmailGateway
19
-
20
- from .discovery import GoogleDiscovery
21
- from .utils import (
22
- logger,
23
- ensure_directory,
24
- timestamp,
25
- safe_execute
26
- )
27
-
28
- __all__ = [
29
- "GoogleConfig",
30
- "GoogleAuth",
31
- "OAuthManager",
32
- "CalendarGateway",
33
- "SheetsGateway",
34
- "DocsGateway",
35
- "DriveGateway",
36
- "GmailGateway",
37
- "GoogleDiscovery",
38
- "logger",
39
- "ensure_directory",
40
- "timestamp",
41
- "safe_execute",
42
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/google/auth.py DELETED
@@ -1,126 +0,0 @@
1
- """
2
- auth.py
3
- SkyOS Google Authentication
4
-
5
- Stellt authentifizierte Google Services für alle Module bereit.
6
-
7
- Autor: Sky Meilin
8
- Projekt: SkyOS Full Core
9
- """
10
-
11
- from __future__ import annotations
12
-
13
- import logging
14
-
15
- from googleapiclient.discovery import build
16
-
17
- from Module.google.oauth import oauth
18
-
19
- logger = logging.getLogger("SkyOS.GoogleAuth")
20
-
21
-
22
- class GoogleAuth:
23
- """Zentrale Google-Authentifizierung."""
24
-
25
- _credentials = None
26
- _services = {}
27
-
28
- @classmethod
29
- def credentials(cls):
30
- """Liefert gültige OAuth-Credentials."""
31
-
32
- if cls._credentials is None:
33
- cls._credentials = oauth.authenticate()
34
-
35
- return cls._credentials
36
-
37
- @classmethod
38
- def service(
39
- cls,
40
- api_name: str,
41
- api_version: str,
42
- ):
43
- """
44
- Erzeugt oder liefert einen zwischengespeicherten Google-Service.
45
-
46
- Beispiel:
47
- GoogleAuth.service("drive", "v3")
48
- """
49
-
50
- key = f"{api_name}:{api_version}"
51
-
52
- if key not in cls._services:
53
-
54
- logger.info(
55
- "Initialisiere Google Service %s (%s)",
56
- api_name,
57
- api_version,
58
- )
59
-
60
- cls._services[key] = build(
61
- api_name,
62
- api_version,
63
- credentials=cls.credentials(),
64
- cache_discovery=False,
65
- )
66
-
67
- return cls._services[key]
68
-
69
- @classmethod
70
- def reset(cls):
71
- """Setzt alle gecachten Services zurück."""
72
-
73
- cls._services.clear()
74
- cls._credentials = None
75
-
76
-
77
- # -------------------------------------------------
78
- # Komfortfunktionen
79
- # -------------------------------------------------
80
-
81
- def get_credentials():
82
- """Liefert gültige OAuth-Credentials."""
83
- return GoogleAuth.credentials()
84
-
85
-
86
- def get_service(
87
- api_name: str,
88
- api_version: str,
89
- ):
90
- """
91
- Liefert einen Google API Service.
92
-
93
- Beispiele:
94
- get_service("drive", "v3")
95
- get_service("calendar", "v3")
96
- get_service("gmail", "v1")
97
- """
98
-
99
- return GoogleAuth.service(
100
- api_name,
101
- api_version,
102
- )
103
-
104
-
105
- # -------------------------------------------------
106
- # Spezielle Kurzfunktionen
107
- # -------------------------------------------------
108
-
109
- def drive():
110
- return get_service("drive", "v3")
111
-
112
-
113
- def docs():
114
- return get_service("docs", "v1")
115
-
116
-
117
- def sheets():
118
- return get_service("sheets", "v4")
119
-
120
-
121
- def gmail():
122
- return get_service("gmail", "v1")
123
-
124
-
125
- def calendar():
126
- return get_service("calendar", "v3")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/google/calendar_gateway.py DELETED
@@ -1,166 +0,0 @@
1
- """
2
- calendar_gateway.py
3
- SkyOS Google Calendar Gateway
4
-
5
- Zentrale Schnittstelle zur Google Calendar API.
6
- Alle Kalenderfunktionen laufen über dieses Gateway.
7
-
8
- Autor: Sky Meilin
9
- Projekt: SkyOS Full Core
10
- """
11
-
12
- from __future__ import annotations
13
-
14
- import logging
15
- from datetime import datetime, timedelta
16
- from typing import Any
17
-
18
- from googleapiclient.discovery import build
19
-
20
- # Gemeinsame Authentifizierung
21
- from Module.google.auth import get_credentials
22
-
23
- logger = logging.getLogger("SkyOS.Calendar")
24
-
25
-
26
- class CalendarGateway:
27
- """Google Calendar Gateway"""
28
-
29
- def __init__(self):
30
- credentials = get_credentials()
31
- self.service = build(
32
- "calendar",
33
- "v3",
34
- credentials=credentials,
35
- cache_discovery=False,
36
- )
37
-
38
- # -------------------------------------------------
39
- # Kalender
40
- # -------------------------------------------------
41
-
42
- def list_calendars(self) -> list[dict]:
43
- """Alle verfügbaren Kalender"""
44
-
45
- response = self.service.calendarList().list().execute()
46
- return response.get("items", [])
47
-
48
- # -------------------------------------------------
49
- # Termine
50
- # -------------------------------------------------
51
-
52
- def list_events(
53
- self,
54
- calendar_id: str = "primary",
55
- max_results: int = 20,
56
- ) -> list[dict]:
57
-
58
- now = datetime.utcnow().isoformat() + "Z"
59
-
60
- response = (
61
- self.service.events()
62
- .list(
63
- calendarId=calendar_id,
64
- timeMin=now,
65
- maxResults=max_results,
66
- singleEvents=True,
67
- orderBy="startTime",
68
- )
69
- .execute()
70
- )
71
-
72
- return response.get("items", [])
73
-
74
- def create_event(
75
- self,
76
- summary: str,
77
- start: datetime,
78
- end: datetime,
79
- description: str = "",
80
- location: str = "",
81
- calendar_id: str = "primary",
82
- ) -> dict:
83
-
84
- event = {
85
- "summary": summary,
86
- "description": description,
87
- "location": location,
88
- "start": {
89
- "dateTime": start.isoformat(),
90
- "timeZone": "Europe/Berlin",
91
- },
92
- "end": {
93
- "dateTime": end.isoformat(),
94
- "timeZone": "Europe/Berlin",
95
- },
96
- }
97
-
98
- return (
99
- self.service.events()
100
- .insert(calendarId=calendar_id, body=event)
101
- .execute()
102
- )
103
-
104
- def delete_event(
105
- self,
106
- event_id: str,
107
- calendar_id: str = "primary",
108
- ):
109
-
110
- self.service.events().delete(
111
- calendarId=calendar_id,
112
- eventId=event_id,
113
- ).execute()
114
-
115
- def update_event(
116
- self,
117
- event_id: str,
118
- body: dict,
119
- calendar_id: str = "primary",
120
- ):
121
-
122
- return (
123
- self.service.events()
124
- .update(
125
- calendarId=calendar_id,
126
- eventId=event_id,
127
- body=body,
128
- )
129
- .execute()
130
- )
131
-
132
- def get_event(
133
- self,
134
- event_id: str,
135
- calendar_id: str = "primary",
136
- ):
137
-
138
- return (
139
- self.service.events()
140
- .get(
141
- calendarId=calendar_id,
142
- eventId=event_id,
143
- )
144
- .execute()
145
- )
146
-
147
-
148
- # -----------------------------------------------------
149
- # Test
150
- # -----------------------------------------------------
151
-
152
- if __name__ == "__main__":
153
-
154
- calendar = CalendarGateway()
155
-
156
- print("Kalender:")
157
- for cal in calendar.list_calendars():
158
- print("-", cal["summary"])
159
-
160
- print("\nNächste Termine:")
161
-
162
- for event in calendar.list_events():
163
- print(
164
- event.get("start", {}).get("dateTime"),
165
- event.get("summary"),
166
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/google/config.py DELETED
@@ -1,121 +0,0 @@
1
- """
2
- config.py
3
- SkyOS Google Configuration
4
-
5
- Zentrale Konfiguration für alle Google-Dienste.
6
-
7
- Autor: Sky Meilin
8
- Projekt: SkyOS Full Core
9
- """
10
-
11
- from __future__ import annotations
12
-
13
- import os
14
-
15
- try:
16
- from dotenv import load_dotenv
17
- load_dotenv()
18
- except ImportError:
19
- pass
20
-
21
-
22
- # -------------------------------------------------
23
- # Projekt
24
- # -------------------------------------------------
25
-
26
- PROJECT_NAME = "SkyOS Full Core"
27
-
28
- TIMEZONE = os.getenv("SKYOS_TIMEZONE", "Europe/Berlin")
29
-
30
-
31
- # -------------------------------------------------
32
- # Google OAuth
33
- # -------------------------------------------------
34
-
35
- GOOGLE_CLIENT_ID = os.getenv("GOOGLE_CLIENT_ID", "")
36
-
37
- GOOGLE_CLIENT_SECRET = os.getenv("GOOGLE_CLIENT_SECRET", "")
38
-
39
- GOOGLE_PROJECT_ID = os.getenv("GOOGLE_PROJECT_ID", "")
40
-
41
- GOOGLE_REDIRECT_URI = os.getenv(
42
- "GOOGLE_REDIRECT_URI",
43
- "http://localhost:8080/"
44
- )
45
-
46
-
47
- # -------------------------------------------------
48
- # Token
49
- # -------------------------------------------------
50
-
51
- TOKEN_FILE = os.getenv(
52
- "GOOGLE_TOKEN_FILE",
53
- "token.json"
54
- )
55
-
56
- CREDENTIALS_FILE = os.getenv(
57
- "GOOGLE_CREDENTIALS_FILE",
58
- "credentials.json"
59
- )
60
-
61
-
62
- # -------------------------------------------------
63
- # OAuth Scopes
64
- # -------------------------------------------------
65
-
66
- GOOGLE_SCOPES = [
67
-
68
- # Google Drive
69
- "https://www.googleapis.com/auth/drive",
70
-
71
- # Google Docs
72
- "https://www.googleapis.com/auth/documents",
73
-
74
- # Google Sheets
75
- "https://www.googleapis.com/auth/spreadsheets",
76
-
77
- # Gmail
78
- "https://www.googleapis.com/auth/gmail.modify",
79
-
80
- # Google Kalender
81
- "https://www.googleapis.com/auth/calendar",
82
-
83
- # Benutzerinformationen
84
- "openid",
85
- "https://www.googleapis.com/auth/userinfo.email",
86
- "https://www.googleapis.com/auth/userinfo.profile",
87
- ]
88
-
89
-
90
- # -------------------------------------------------
91
- # Logging
92
- # -------------------------------------------------
93
-
94
- LOG_LEVEL = os.getenv(
95
- "SKYOS_LOG_LEVEL",
96
- "INFO"
97
- )
98
-
99
-
100
- # -------------------------------------------------
101
- # Debug
102
- # -------------------------------------------------
103
-
104
- DEBUG = os.getenv(
105
- "SKYOS_DEBUG",
106
- "false"
107
- ).lower() == "true"
108
-
109
-
110
- # -------------------------------------------------
111
- # Status
112
- # -------------------------------------------------
113
-
114
- CONFIG = {
115
- "project": PROJECT_NAME,
116
- "timezone": TIMEZONE,
117
- "redirect_uri": GOOGLE_REDIRECT_URI,
118
- "credentials": CREDENTIALS_FILE,
119
- "token": TOKEN_FILE,
120
- "debug": DEBUG,
121
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/google/discovery.py DELETED
@@ -1,110 +0,0 @@
1
- """
2
- discovery.py
3
- SkyOS Google Discovery
4
-
5
- Prüft verfügbare Google-Dienste und den
6
- Authentifizierungsstatus.
7
-
8
- Autor: Sky Meilin
9
- Projekt: SkyOS Full Core
10
- """
11
-
12
- from __future__ import annotations
13
-
14
- import logging
15
-
16
- from Module.google.auth import (
17
- drive,
18
- docs,
19
- sheets,
20
- gmail,
21
- calendar,
22
- )
23
-
24
- logger = logging.getLogger("SkyOS.GoogleDiscovery")
25
-
26
-
27
- class GoogleDiscovery:
28
-
29
- def __init__(self):
30
- self.services = {
31
- "drive": drive,
32
- "docs": docs,
33
- "sheets": sheets,
34
- "gmail": gmail,
35
- "calendar": calendar,
36
- }
37
-
38
- # -------------------------------------------------
39
- # Einzelnen Dienst prüfen
40
- # -------------------------------------------------
41
-
42
- def check_service(self, name: str):
43
-
44
- if name not in self.services:
45
- return {
46
- "service": name,
47
- "available": False,
48
- "error": "Unknown service",
49
- }
50
-
51
- try:
52
- self.services[name]()
53
-
54
- return {
55
- "service": name,
56
- "available": True,
57
- }
58
-
59
- except Exception as e:
60
-
61
- logger.exception(e)
62
-
63
- return {
64
- "service": name,
65
- "available": False,
66
- "error": str(e),
67
- }
68
-
69
- # -------------------------------------------------
70
- # Alle Dienste prüfen
71
- # -------------------------------------------------
72
-
73
- def discover(self):
74
-
75
- result = {}
76
-
77
- for name in self.services:
78
-
79
- result[name] = self.check_service(name)
80
-
81
- return result
82
-
83
- # -------------------------------------------------
84
- # Statusübersicht
85
- # -------------------------------------------------
86
-
87
- def health(self):
88
-
89
- status = self.discover()
90
-
91
- ok = all(
92
- item["available"]
93
- for item in status.values()
94
- )
95
-
96
- return {
97
- "google_available": ok,
98
- "services": status,
99
- }
100
-
101
- # -------------------------------------------------
102
- # Unterstützte Dienste
103
- # -------------------------------------------------
104
-
105
- def supported_services(self):
106
-
107
- return list(self.services.keys())
108
-
109
-
110
- google_discovery = GoogleDiscovery()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/google/docs_gateway.py DELETED
@@ -1,154 +0,0 @@
1
- """
2
- docs_gateway.py
3
- SkyOS Google Docs Gateway
4
-
5
- Google Docs Schnittstelle für SkyOS.
6
-
7
- Autor: Sky Meilin
8
- Projekt: SkyOS Full Core
9
- """
10
-
11
- from __future__ import annotations
12
-
13
- import logging
14
-
15
- from Module.google.auth import docs
16
-
17
- logger = logging.getLogger("SkyOS.GoogleDocs")
18
-
19
-
20
- class DocsGateway:
21
-
22
- def __init__(self):
23
- self.service = docs()
24
-
25
- # --------------------------------------------------
26
- # Dokument erstellen
27
- # --------------------------------------------------
28
-
29
- def create_document(self, title: str):
30
- """Erstellt ein neues Google-Dokument."""
31
-
32
- document = (
33
- self.service.documents()
34
- .create(
35
- body={
36
- "title": title
37
- }
38
- )
39
- .execute()
40
- )
41
-
42
- logger.info("Dokument erstellt: %s", title)
43
-
44
- return document
45
-
46
- # --------------------------------------------------
47
- # Dokument abrufen
48
- # --------------------------------------------------
49
-
50
- def get_document(self, document_id: str):
51
- """Lädt ein Google-Dokument."""
52
-
53
- return (
54
- self.service.documents()
55
- .get(
56
- documentId=document_id
57
- )
58
- .execute()
59
- )
60
-
61
- # --------------------------------------------------
62
- # Text anhängen
63
- # --------------------------------------------------
64
-
65
- def append_text(
66
- self,
67
- document_id: str,
68
- text: str,
69
- index: int = 1,
70
- ):
71
- """
72
- Fügt Text in das Dokument ein.
73
- Standardmäßig am Dokumentanfang.
74
- """
75
-
76
- requests = [
77
- {
78
- "insertText": {
79
- "location": {
80
- "index": index
81
- },
82
- "text": text,
83
- }
84
- }
85
- ]
86
-
87
- return (
88
- self.service.documents()
89
- .batchUpdate(
90
- documentId=document_id,
91
- body={
92
- "requests": requests
93
- },
94
- )
95
- .execute()
96
- )
97
-
98
- # --------------------------------------------------
99
- # Dokument ersetzen
100
- # --------------------------------------------------
101
-
102
- def replace_text(
103
- self,
104
- document_id: str,
105
- search_text: str,
106
- replace_text: str,
107
- ):
108
- """Ersetzt Text im gesamten Dokument."""
109
-
110
- requests = [
111
- {
112
- "replaceAllText": {
113
- "containsText": {
114
- "text": search_text,
115
- "matchCase": True,
116
- },
117
- "replaceText": replace_text,
118
- }
119
- }
120
- ]
121
-
122
- return (
123
- self.service.documents()
124
- .batchUpdate(
125
- documentId=document_id,
126
- body={
127
- "requests": requests
128
- },
129
- )
130
- .execute()
131
- )
132
-
133
- # --------------------------------------------------
134
- # Titel ändern
135
- # --------------------------------------------------
136
-
137
- def rename_document(
138
- self,
139
- document_id: str,
140
- new_title: str,
141
- ):
142
- """
143
- Titel ändern.
144
-
145
- Benötigt zusätzlich drive_gateway.py,
146
- da der Dateiname über Google Drive verwaltet wird.
147
- """
148
-
149
- raise NotImplementedError(
150
- "rename_document erfolgt über drive_gateway.py"
151
- )
152
-
153
-
154
- docs_gateway = DocsGateway()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/google/drive_gateway.py DELETED
@@ -1,57 +0,0 @@
1
- """
2
- gateway.py
3
- SkyOS Google Gateway
4
-
5
- Zentraler Zugriff auf alle Google-Services.
6
-
7
- Autor: Sky Meilin
8
- Projekt: SkyOS Full Core
9
- """
10
-
11
- from Module.google.auth import (
12
- drive,
13
- docs,
14
- sheets,
15
- gmail,
16
- calendar,
17
- )
18
-
19
-
20
- class GoogleGateway:
21
- """Zentrale Schnittstelle für alle Google APIs."""
22
-
23
- @staticmethod
24
- def drive():
25
- return drive()
26
-
27
- @staticmethod
28
- def docs():
29
- return docs()
30
-
31
- @staticmethod
32
- def sheets():
33
- return sheets()
34
-
35
- @staticmethod
36
- def gmail():
37
- return gmail()
38
-
39
- @staticmethod
40
- def calendar():
41
- return calendar()
42
-
43
- @staticmethod
44
- def services():
45
- """Liefert alle initialisierten Services."""
46
-
47
- return {
48
- "drive": drive(),
49
- "docs": docs(),
50
- "sheets": sheets(),
51
- "gmail": gmail(),
52
- "calendar": calendar(),
53
- }
54
-
55
-
56
- # Singleton
57
- google = GoogleGateway()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/google/gmail_gateway.py DELETED
@@ -1,162 +0,0 @@
1
- """
2
- gmail_gateway.py
3
- SkyOS Google Gmail Gateway
4
-
5
- Gmail-Schnittstelle für private Google-Konten.
6
-
7
- Autor: Sky Meilin
8
- Projekt: SkyOS Full Core
9
- """
10
-
11
- from __future__ import annotations
12
-
13
- import base64
14
- import logging
15
- from email.mime.text import MIMEText
16
-
17
- from Module.google.auth import gmail
18
-
19
- logger = logging.getLogger("SkyOS.Gmail")
20
-
21
-
22
- class GmailGateway:
23
-
24
- def __init__(self):
25
- self.service = gmail()
26
-
27
- # --------------------------------------------------
28
- # Nachrichten
29
- # --------------------------------------------------
30
-
31
- def list_messages(
32
- self,
33
- query: str = "",
34
- max_results: int = 10,
35
- ):
36
- """Listet Nachrichten auf."""
37
-
38
- response = (
39
- self.service.users()
40
- .messages()
41
- .list(
42
- userId="me",
43
- q=query,
44
- maxResults=max_results,
45
- )
46
- .execute()
47
- )
48
-
49
- return response.get("messages", [])
50
-
51
- def get_message(self, message_id: str):
52
- """Liest eine Nachricht."""
53
-
54
- return (
55
- self.service.users()
56
- .messages()
57
- .get(
58
- userId="me",
59
- id=message_id,
60
- format="full",
61
- )
62
- .execute()
63
- )
64
-
65
- # --------------------------------------------------
66
- # Senden
67
- # --------------------------------------------------
68
-
69
- def send_email(
70
- self,
71
- to: str,
72
- subject: str,
73
- body: str,
74
- ):
75
- """Sendet eine E-Mail."""
76
-
77
- message = MIMEText(body)
78
-
79
- message["to"] = to
80
- message["subject"] = subject
81
-
82
- raw = base64.urlsafe_b64encode(
83
- message.as_bytes()
84
- ).decode()
85
-
86
- return (
87
- self.service.users()
88
- .messages()
89
- .send(
90
- userId="me",
91
- body={
92
- "raw": raw
93
- },
94
- )
95
- .execute()
96
- )
97
-
98
- # --------------------------------------------------
99
- # Labels
100
- # --------------------------------------------------
101
-
102
- def list_labels(self):
103
- """Listet alle Labels."""
104
-
105
- response = (
106
- self.service.users()
107
- .labels()
108
- .list(
109
- userId="me"
110
- )
111
- .execute()
112
- )
113
-
114
- return response.get("labels", [])
115
-
116
- # --------------------------------------------------
117
- # Löschen
118
- # --------------------------------------------------
119
-
120
- def delete_message(
121
- self,
122
- message_id: str,
123
- ):
124
- """Löscht eine Nachricht."""
125
-
126
- return (
127
- self.service.users()
128
- .messages()
129
- .delete(
130
- userId="me",
131
- id=message_id,
132
- )
133
- .execute()
134
- )
135
-
136
- # --------------------------------------------------
137
- # Archivieren
138
- # --------------------------------------------------
139
-
140
- def archive_message(
141
- self,
142
- message_id: str,
143
- ):
144
- """Archiviert eine Nachricht."""
145
-
146
- return (
147
- self.service.users()
148
- .messages()
149
- .modify(
150
- userId="me",
151
- id=message_id,
152
- body={
153
- "removeLabelIds": [
154
- "INBOX"
155
- ]
156
- },
157
- )
158
- .execute()
159
- )
160
-
161
-
162
- gmail_gateway = GmailGateway()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/google/oauth.py DELETED
@@ -1,117 +0,0 @@
1
- """
2
- oauth.py
3
- SkyOS Google OAuth
4
-
5
- OAuth-Authentifizierung für private Google-Konten.
6
-
7
- Autor: Sky Meilin
8
- Projekt: SkyOS Full Core
9
- """
10
-
11
- from __future__ import annotations
12
-
13
- import logging
14
- from pathlib import Path
15
-
16
- from google.auth.transport.requests import Request
17
- from google.oauth2.credentials import Credentials
18
- from google_auth_oauthlib.flow import InstalledAppFlow
19
-
20
- from Module.google.config import (
21
- GOOGLE_SCOPES,
22
- CREDENTIALS_FILE,
23
- TOKEN_FILE,
24
- )
25
-
26
- logger = logging.getLogger("SkyOS.GoogleOAuth")
27
-
28
-
29
- class GoogleOAuth:
30
-
31
- def __init__(self):
32
- self.credentials = None
33
-
34
- def load_credentials(self) -> Credentials | None:
35
- """Lädt vorhandene Zugangsdaten."""
36
-
37
- token_path = Path(TOKEN_FILE)
38
-
39
- if token_path.exists():
40
- self.credentials = Credentials.from_authorized_user_file(
41
- TOKEN_FILE,
42
- GOOGLE_SCOPES,
43
- )
44
-
45
- return self.credentials
46
-
47
- def refresh_credentials(self) -> Credentials | None:
48
- """Erneuert ein abgelaufenes Token."""
49
-
50
- if (
51
- self.credentials
52
- and self.credentials.expired
53
- and self.credentials.refresh_token
54
- ):
55
- logger.info("Google Token wird aktualisiert...")
56
- self.credentials.refresh(Request())
57
- self.save_credentials()
58
-
59
- return self.credentials
60
-
61
- def authenticate(self) -> Credentials:
62
- """Startet den OAuth-Login, falls erforderlich."""
63
-
64
- self.load_credentials()
65
-
66
- if (
67
- self.credentials
68
- and self.credentials.valid
69
- ):
70
- return self.credentials
71
-
72
- if (
73
- self.credentials
74
- and self.credentials.expired
75
- and self.credentials.refresh_token
76
- ):
77
- self.refresh_credentials()
78
- return self.credentials
79
-
80
- logger.info("Starte Google OAuth Login...")
81
-
82
- flow = InstalledAppFlow.from_client_secrets_file(
83
- CREDENTIALS_FILE,
84
- GOOGLE_SCOPES,
85
- )
86
-
87
- self.credentials = flow.run_local_server(
88
- port=0,
89
- prompt="consent",
90
- )
91
-
92
- self.save_credentials()
93
-
94
- return self.credentials
95
-
96
- def save_credentials(self):
97
- """Speichert das OAuth-Token."""
98
-
99
- if self.credentials is None:
100
- return
101
-
102
- with open(TOKEN_FILE, "w", encoding="utf-8") as token:
103
- token.write(self.credentials.to_json())
104
-
105
- logger.info("Google Token gespeichert.")
106
-
107
- def revoke(self):
108
- """Entfernt das lokale Token."""
109
-
110
- token_path = Path(TOKEN_FILE)
111
-
112
- if token_path.exists():
113
- token_path.unlink()
114
- logger.info("Google Token gelöscht.")
115
-
116
-
117
- oauth = GoogleOAuth()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/google/utils.py DELETED
@@ -1,130 +0,0 @@
1
- """
2
- utils.py
3
- SkyOS Google Utilities
4
-
5
- Gemeinsame Hilfsfunktionen für alle Google-Module.
6
-
7
- Autor: Sky Meilin
8
- Projekt: SkyOS Full Core
9
- """
10
-
11
- from __future__ import annotations
12
-
13
- import logging
14
- import re
15
- from datetime import datetime
16
- from pathlib import Path
17
- from typing import Any
18
-
19
- logger = logging.getLogger("SkyOS.GoogleUtils")
20
-
21
-
22
- # -------------------------------------------------
23
- # Datum & Zeit
24
- # -------------------------------------------------
25
-
26
- def iso_now() -> str:
27
- """Aktuelle UTC-Zeit im ISO-8601-Format."""
28
- return datetime.utcnow().replace(microsecond=0).isoformat() + "Z"
29
-
30
-
31
- def format_datetime(dt: datetime) -> str:
32
- """Konvertiert datetime in ISO-8601."""
33
- return dt.isoformat()
34
-
35
-
36
- # -------------------------------------------------
37
- # Dateinamen
38
- # -------------------------------------------------
39
-
40
- def sanitize_filename(filename: str) -> str:
41
- """Entfernt ungültige Zeichen aus Dateinamen."""
42
-
43
- filename = re.sub(r'[<>:"/\\|?*]', "_", filename)
44
- filename = filename.strip()
45
-
46
- return filename
47
-
48
-
49
- def file_extension(path: str) -> str:
50
- """Gibt die Dateiendung zurück."""
51
-
52
- return Path(path).suffix.lower()
53
-
54
-
55
- # -------------------------------------------------
56
- # Google IDs
57
- # -------------------------------------------------
58
-
59
- def is_google_id(value: str) -> bool:
60
- """
61
- Einfache Prüfung, ob ein String
62
- wie eine Google-ID aussieht.
63
- """
64
-
65
- return (
66
- isinstance(value, str)
67
- and len(value) > 20
68
- )
69
-
70
-
71
- # -------------------------------------------------
72
- # API Antworten
73
- # -------------------------------------------------
74
-
75
- def success(data: Any = None, message: str = "OK") -> dict:
76
- """Standardisierte Erfolgsausgabe."""
77
-
78
- return {
79
- "success": True,
80
- "message": message,
81
- "data": data,
82
- }
83
-
84
-
85
- def error(message: str, exception: Exception | None = None) -> dict:
86
- """Standardisierte Fehlerausgabe."""
87
-
88
- logger.error(message)
89
-
90
- return {
91
- "success": False,
92
- "message": message,
93
- "error": str(exception) if exception else None,
94
- }
95
-
96
-
97
- # -------------------------------------------------
98
- # Logging
99
- # -------------------------------------------------
100
-
101
- def log_api_call(service: str, action: str):
102
-
103
- logger.info(
104
- "[%s] %s",
105
- service.upper(),
106
- action,
107
- )
108
-
109
-
110
- # -------------------------------------------------
111
- # MIME Types
112
- # -------------------------------------------------
113
-
114
- GOOGLE_MIME_TYPES = {
115
-
116
- "document":
117
- "application/vnd.google-apps.document",
118
-
119
- "spreadsheet":
120
- "application/vnd.google-apps.spreadsheet",
121
-
122
- "folder":
123
- "application/vnd.google-apps.folder",
124
-
125
- "presentation":
126
- "application/vnd.google-apps.presentation",
127
-
128
- "drawing":
129
- "application/vnd.google-apps.drawing",
130
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
modules/remote_control.py CHANGED
@@ -4,47 +4,59 @@ from typing import Dict, Any
4
 
5
 
6
  class RemoteControl:
7
- # Klassen-Attribut verhindert den Verlust der Geräteliste bei Neu-Instanziierung
8
- _connected_devices: Dict[str, Dict[str, str]] = {}
9
 
10
  def __init__(self):
 
11
  print("RemoteControl geladen")
12
 
13
- @property
14
- def connected_devices(self) -> Dict[str, Dict[str, str]]:
15
- return RemoteControl._connected_devices
 
 
 
 
16
 
17
- def connect_device(self, device_id: str, device_type: str) -> Dict[str, str]:
18
  self.connected_devices[device_id] = {
19
  "type": device_type,
20
  "status": "connected"
21
  }
 
22
  return {
23
  "device_id": device_id,
24
  "status": "connected"
25
  }
26
 
27
- def disconnect_device(self, device_id: str) -> Dict[str, str]:
 
 
 
 
28
  if device_id in self.connected_devices:
29
- self.connected_devices[device_id]["status"] = "disconnected"
 
 
 
 
30
  return {
31
  "device_id": device_id,
32
  "status": "disconnected"
33
  }
 
34
  return {
35
  "error": "Gerät nicht gefunden"
36
  }
37
 
38
- def send_command(self, device_id: str, command: str) -> Dict[str, Any]:
 
 
 
 
 
39
  if device_id not in self.connected_devices:
40
- return {
41
- "error": "Gerät nicht verbunden"
42
- }
43
 
44
- # Falls ein Gerät den Status 'disconnected' hat, wird das Senden blockiert
45
- if self.connected_devices[device_id].get("status") != "connected":
46
  return {
47
- "error": "Gerät ist offline"
48
  }
49
 
50
  return {
@@ -53,5 +65,6 @@ class RemoteControl:
53
  "status": "sent"
54
  }
55
 
56
- def list_devices(self) -> Dict[str, Dict[str, str]]:
57
- return self.connected_devices
 
 
4
 
5
 
6
  class RemoteControl:
 
 
7
 
8
  def __init__(self):
9
+
10
  print("RemoteControl geladen")
11
 
12
+ self.connected_devices = {}
13
+
14
+ def connect_device(
15
+ self,
16
+ device_id: str,
17
+ device_type: str
18
+ ):
19
 
 
20
  self.connected_devices[device_id] = {
21
  "type": device_type,
22
  "status": "connected"
23
  }
24
+
25
  return {
26
  "device_id": device_id,
27
  "status": "connected"
28
  }
29
 
30
+ def disconnect_device(
31
+ self,
32
+ device_id: str
33
+ ):
34
+
35
  if device_id in self.connected_devices:
36
+
37
+ self.connected_devices[device_id][
38
+ "status"
39
+ ] = "disconnected"
40
+
41
  return {
42
  "device_id": device_id,
43
  "status": "disconnected"
44
  }
45
+
46
  return {
47
  "error": "Gerät nicht gefunden"
48
  }
49
 
50
+ def send_command(
51
+ self,
52
+ device_id: str,
53
+ command: str
54
+ ) -> Dict[str, Any]:
55
+
56
  if device_id not in self.connected_devices:
 
 
 
57
 
 
 
58
  return {
59
+ "error": "Gerät nicht verbunden"
60
  }
61
 
62
  return {
 
65
  "status": "sent"
66
  }
67
 
68
+ def list_devices(self):
69
+
70
+ return self.connected_devices