diff --git a/.gitignore b/.gitignore index 82f92755..32c59783 100644 --- a/.gitignore +++ b/.gitignore @@ -160,3 +160,7 @@ cython_debug/ # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. #.idea/ + +# local data +gwserver/_database* +gwserver/results/* \ No newline at end of file diff --git a/changelog.txt b/changelog.txt deleted file mode 100644 index 1f25bd20..00000000 --- a/changelog.txt +++ /dev/null @@ -1,230 +0,0 @@ -....................... TASKS - -Agentenauswahlfenster einfacher und mit klick auf Namen - - ------------------------ OPEN - -Issue: Workspace wählen --> Workflow hat nicht die nötigen Agenten und ggf. Prompts - -Issue: Prompt-Dropdown - Den Titel dort eintragen, nicht den Text - -DOKUS -Doku des Systems für Investoren (Hi-level Struktur, Integrationsfähigkeit und Skalierbarkeit) -Doku des Systems für Code Integration -Release Notes (was kann das Teil) -Log der Anpassungen -Systemarchitektur (Grundsätze der Architektur, Komponenten und deren Aufbau) - ------------------------ DONE - - -Die Buttons "Workflow starten" und "Zurücksetzen" haben keinen Rahmen. Ist hier ggf. die Style Class falsch oder nicht appliziert? - -Anpassung des Visuals "Ausführung & Ergebnisse": -- Das Ausführungsprotokoll so belassen. Einen Button rechts von den anderen zwei Buttons (alle anzeigen / Details zuklappen) ergänzen, für dies mit dem Ausführungsprotokollfenster: toggle function collapse and restore -- Die Bereiche "Multi-Agent-Chat" und "Ergebnisse" machen so keinen Sinn. Diese beiden Bereiche bitte zusammenlegen in einen grossen Bereich mit dem Namen "Multi-Agent Chat Area". Dort laufend die Messages der Agenten in einer HTML-Ansicht der Messages protokollieren. Jeweils der Name des Agenten im Titel und darunter seine Message. Die letzte Message soll aufgeklappt sein, alle früheren sollen jeweils zugeklappt sein, aber durch den User soll ein toggle pro Message möglich sein, um die Details zu sehen. - - -Kannst Du den Ablauf des Agenten-Chats wie folgt optimieren: -- Bei jedem Chat einen "User Agent" mit dem Namen des eingelogten Benutzers ergänzen. Wenn etwas im Chat nicht klar ist, oder zusätzliche Informationen nötig sind, so fragt er den User Agent. Auch bevor er den Chat beendet, fragt er den User Agent, ob dieser einverstanden ist. -- Wenn der User Agent eine Anfrage erhält, so kann er direkt unter der Chat History im Bereich ereiche "Multi-Agent-Chat" seinen Text in einem mehrzeiligen Textfeld erfassen. Er kann auch zusätzliche Files hochladen. Wenn er "Enter" drückt, werden die zusätzlichen Daten mit den ergänzten Files zur Message ergänzt, das Eingabefenster verschwindet wieder und der Moderator führt den Chat fort. Immer nach einer Benutzereingabe startet der Zähler wieder bei Runde 1. - -Statistik ergänzen: Kannst Du bitte rechtsbündig neben dem Titel des "Ausführungsprotokolls" laufend die Statistik nachführen, wieviele kBytes (kB) Daten über den Connector zum AI-Modell gesendet wurden (dies ist die Datengrösse des Message-Objektes) und wieviele kB an Messages zurückgeliefert wurden. Diese angabe pro Workflow-Durchlauf, also immer beim Start eines neuen Workflows wird der Zähler auf 0 gesetzt. In diesem Format: "^ 250k v 1'250k ", v und ^ durch Pfeile ersetzt. - - -In den Einstellungen des Frontends soll die Sprache des aktiven benutzers gemäss den Listenoptionen in den "...model.py" angepasst werden können. die sprache gilt dann auch für die Attributnamen in einem Formularfeld im "generic-entity.js". eine sprachänderung zieht somit eine anpassung des Users über das API nach sich, indem die Sprache in der Datenbank angepasst wird. - -kannst du die ausführungsprotokollierung anpassen? das protokoll soll laufend anzeigen, welcher assistent welches resultat produziert hat und welcher assistent aktuell am arbeiten ist. Prozentzahlen sind keine nötig, diese machen keinen sinn. das polling so beibehalten, aber wenn keine neuen Daten bereitstelen, dann beim letzten Timestamp einfach laufend "." ergänzen, bis die nächste Meldung ausgegeben wird. hast du alle daten, um dies im frontend und im backend anzupassen? - -Im Ausführungsprotokoll pro Eintrag nur den Titel zeigen und die Details zwar ins Protokoll nehmen, aber ausblenden. Der Benutzer kann dann im Protokoll die zugeklappten Texte aufklappen, um die gewünschten Details gezielt zu sehen. - -Im Front-End beim Workflow-Modul bitte das Ausführungsprotokoll-Fenster dynamisch in der Grösse anpassbar machen. in der Breite und der Höhe. Dasselbe für das Ergebnis-Fenster. Zudem die Ansicht so gestalten, dass die Fensterteile "Workflow-Konfiguration" und "Ausführung & Ergebnisse" ein- und ausgeblendet werden können, damit jeweils ein Teil die komplette Arbeitsfläche verwenden kann, weil dort viel Text stehen wird. Dies ist für den Benutzer besser. - -nun zu diesem zentralen modul. ich hätte gern, dass die daten als tabellen dargestellt und bearbeitet werden können. für view, add, modify, delete jeweils icon pro datensatz ganz links und zuoberst im header ein "new item" symbol oder text, mach einen vorschlag. - -ist es möglich, eine checkbox pro datensatz zu machen, um mehrere elemente auszuwählen und oben an der tabelle icons zu haben für mehrfach delete? - -die tabelle soll nach allen feldern gefiltert und sortiert werden können - -kannst du bitte den code so anpassen, dass main.js die seitenmodule im Anhang dynamisch erst dann lädt, wenn die entsprechende seite in der navigation aufgerufen wird? - -dann bitte main.js modularisieren, sodass dort nur funktionsaufrufe auf sub-module ausgeführt werden. das navigationsmenu nach "navigation.js" auslagern. den aufbau und betrieb des aktuellen workspaces im main.js drin lassen. - -Der aktuelle Hauptbereich mitt der Auswahl des workspaces, den zugehörigen Agenten etc ist neu ein Objekt, welches in der "mainView" dargestellt werden kann. Auch andere Objekte können in der mainView dargestellt werden und haben jeweils ihre spezifischen Paramter dazu, wie nachfolgend erklärt. - -im main.js wird ein globales objekt aller elemente erstellt, welche in der navigation enthalten sein sollen und welches die grundlage für alle funktonsaufrufe beinhaltet. damit gibt es dann im index.html keine details mehr zu den navigationen. - - -diese attribute hat das globale objekt: - -globalState -.objects -.user -.mainView - -Hier die Spezifikation der Objekte. - -.objects[...]: hat eine liste von objekten, welche im mainScreen geladen werden können. Diese Attribute pro Objekt bitte gemäss den heutigen js files im anhang sinngemäss übernehmen: -- label: Liste des Labelnamen in den verschiedenen sprachen (default, en, fr...) -- modulName: string; dieser wird verwendet für die objektklasse "js/modules/{modulname}.js" und für die html-komponente dazu "modules/part-{modulname}.html und für die calls ans backend /api/{modulname}/..." -- icon: Icon vor dem Menupunkt -- navigationContext: "left" für agents, data, prompts, users, mandates, workspaces ; "top" für sprachauswahl, logout -- isVisible (hier wird z.b. users und mandates nur angezeigt, wenn auch die berechtigung dafür besteht) -- isActive: Wenn der Menupunkt ausgewählt ist -- navigationContext: diese Optionen, wo ein Objekt ins Menu genommen wird: - --"nav_left" für agents, data, prompts, users, mandates, workspaces - --"nav_top" für sprachauswahl, logout -- navigationActionType: Was passiert, wenn auf das Menu geklickt wird. Diese Optionen: - --"module": Standard-Menu button. Es wird ein Modul in die mainView geladen. Das Modul wird erst geladen und mit den Daten initiiert, wenn der Menupunkt ausgewählt wird - --"group_open": Gruppenheader; Start einer neuen Gruppe; alle nachfolgenden Objekte der Liste sind in dieser Gruppe integriert. Die Gruppe kann im Menu auf- und zugeklappt werden. Initial Gruppe open, alle Menupunkte sichtbar - --"group_collapsed": Gruppenheader; Start einer neuen Gruppe; alle nachfolgenden Objekte der Liste sind in dieser Gruppe integriert. Die Gruppe kann im Menu auf- und zugeklappt werden. Initial Gruppe collapsed. - -.user: Attribute zum aktiven user -- mandate_id -- user_id -- username -- full_name -- language (default, en, fr, ...) -- isAdmin -- isSysAdmin -- lastWorkspaceId: Id des zuletzt genutzten Workspaces - aktuell "null" -- session: aktuell null und nicht verwendet - -.mainView: enthält immer die aktuellen Attribute, welche die Seite in der mainView nutzen kann -- currentWorkspace: objekt des aktuell ausgewählten Workspaces -- availableFiles[]: list of objects -- availableAgents[]: list of objects -- availablePrompts[]: list of objects -- currentWorkflowId: id - - -kannst du bitte part-workflow.html und workflow.js mit dem dynamischen Multi-Agent Chat aktualisieren, welcher im backend angepasst wurde und im Ausführungsprotokoll die Details eines laufenden Chats mit aufklappbaren Texten ergänzen. Das Ausführungsprotokoll-Fenster dynamisch in der Grösse anpassbar machen. - -Css aufräumen und konsolidieren für gemeinsame Klassen mit allen html und js parallel - -Admin Seite mit CRUD für User Mgmt und Mandate Management, generisch - -Im Frontend soll im generischen Formular "generic-entity.js" für ein neues Objekt die ID entweder hidden oder schreibgeschützt sein. die ID wird nicht benötigt, sondern wird erst mit dem speichern in der datenbank erstellt. d.h. nach dem speichern in der datenbank werden die daten der entsprechenden tabelle neu geladen. - - -Kannst du mir bitte code struktur und logik das 'agentservice_interface.py' anpsssen und die code struktur zur besseren wartung und weiterenwticklung verbessern: - -1. die anbindung der ai-modelle mit den entsprechenden config-daten und den funktionsaufrufen in separate dateien auslagern ("connector_ai_openai","connector_ai_webscraping"). im 'agentservice_interface.py' die connector module bei der initialisierung importieren und vorbereiten. - -2. den agenten-chat 'execute_workflow' nicht in der reihenfolge der agents ausführen, sondern als tischrunde der agents.das heisst ein AI moderator moderiert die agenten autonom und ruft anhand der produzierten antworten und der eigenschaften der agentss den jeweils nächsten geeigneten agenten anhand der 'capabilities' auf, nachdem ein agent seine antwort geliefert hat. -der initiale prompt mit den zugehörigen files und dem chatverlauf im 'LogEntry' mit den n letzten Datensätzen (n wird aus dem Config file aus der variablen Application.MAX_HISTORY gelesen) wird in ein 'message'-objekt als dictionary transformiert, welches so aussieht: - message = { - "role": "user", #--> statisch, immer so - "content": [ #--> liste der Files - { - "type": "text", - "text": prompt_text - }, - { - "type": content_type, # --> diese funktion integrieren wir später - "source": { - "type": "base64", - "media_type": mime_type, - "data": base64_file # --> hier das dateiname der jeweiligen datei - } - }, - { - "type": "text", - "text": LogEntries # --> hier die LogEinträge als Textpaket - } - ] - } -wenn der AI moderator der Meinung ist, dass die aufgabe erfüllt ist, beendet er den workflow. - - -3. initialisierungsset: beantwortet Anfragen direkt mit dem hinterlegten KI Modell, welche keine spezialisierten Agenten benötigen. Dies ist die Generierung von Text, Code, Strukturen, die Analyse von Files, Graphiken erstellen, etc. -(Agent) Organisator: Dieser analysiert den User Prompt und strukturiert die auszuführenden Aufräge sowie die nötigen zu liefernden Resultate -(Agent) Entwickler: Dieser entwickelt python code im Auftrag der anderen Agents und führt ihn anschliessend aus -(Agent) Webscrape: Ein Agent, welcher webscraping durchführt. Dieser nutzt die Funktion '_scrape_url', um eine Webseite zu scannen und den Inhalt zurückzugeben. Er kann auch den Entwickler beauftragen, einen Code zu generieren, welcher die funktion _scrape_url mit einer logik (z.B. iterativ oder batch-mässig) ausführt -(Prompt): Kannst Du mir ein paar initiale Prompts für die folgenden Fragebereiche vorbereiten, welche ausgewählt werden können: -. Web Research -. Analyse -. Protokoll -. Design - - -4. Kannst Du bitte die fehlenden CRUD Methoden in den modulen "workspaces" und "prompts" ergänzen. Ich glaube, es fehlen Post und Delete. - - -5. Datenbank-Management verbessern: In den zwei Modulen "gateway_interface.py" und "lucydom_interface" finden keine Manipulationen oder Referenzierungen mit ID's statt. Die ID's für einen neuen Datensatz werden nur in "connector_....py" modulen vergeben. Jeder datensatz hat eine unique id. in den modulen "...interface.py" werden keine id's generiert. die abfrage für die id=1 wird ersetzt mit der funktion 'get_initial_id', welche weiter unten erklärt ist. -Dazu bitte die Module anpassen und in den Modulen "connector...py" eine system-tabelle ergänzen, welche sich merkt, welche ID der erste datensatz jeder tabelle hat, denn dieser ist der jeweilige system-datensatz. dann eine funktion 'get_initial_id' erfassen, welche in den modulen Modulen "gateway_interface.py" und "lucydom_interface" aufgerufen werden kann, um die id des initialen datensatzes pro tabelle abzufragen. - - - - - -der gateway funktioniert noch nicht ganz. -kannst mir bitte die module prüfen und besser stukturieren? - -Diese anforderungen und das setting der dateien: - -models.py: die datei umbenennen in "model_lucydom.py" - - die class "User", "UserInDB", "Token" in der datei entfernen und in eine separate datei "model_gateway.py" auslagern. - - alle datentypen-definitionen sind hier, abschliessend und unabhängig vom datenbanksystem. - - alle ID's sind long-Zahlen, keine Texte - - bei jeder class und bei jedem attribut einer class ein label ergänzen, was der name des attributes bzw. der class ist, wenn dies in einem formular abgefragt wird. das label soll einen defaultwert haben und pro sprache gesetzt werden können. - - alle objekte mandantenfähig machen, d.h. bei jedem Objekt die Attribute "mandate_id" und "user_id" ergänzen. - -model_gateway.py: - - alle datentypen-definitionen sind hier, abschliessend und unabhängig vom datenbanksystem. - - alle ID's sind long-Zahlen, keine Texte - - bei jeder class und bei jedem attribut einer class ein label ergänzen, was der name des attributes bzw. der class ist, wenn dies in einem formular abgefragt wird. das label soll einen defaultwert haben und pro sprache gesetzt werden können. - - Die class "Mandate" mit den Attributen (id,name,language) ergänzen - - Bei der class "User" die "id" und "mandate_id" und "language" ergänzen - - alle objekte mandantenfähig machen, d.h. bei jedem Objekt die Attribute "mandate_id" und "user_id" ergänzen. - -database.py aufteilen in 2 files "connector_db_json.py" und "interface_lucydom.py". - -connector_db_json.py: Ein erster Konnektor von zukünftig weiteren Konnektoren - 1. Parameter, welche übergeben werden: - - DB_Folder, DB_USER und DB_APIKEY - - Kontextparamter für "mandate_id" und "user_id", welche nicht null sein dürfen. - - Die aktuelle JSON-Datenbank im Folder DB_Folder einbinden und so übernehmen, wie sie ist. Falls der Folder fehlt, diesen erstellen. - 2. Der Konnector "db" wird als Objekt zur verfügung gestellt. - 3. Es werden diese generischen Methoden im Objekt "db" zur Verfügung gestellt. jede abfrage filtert automatisch die datensätze auf die Kontextparamter "mandate_id" und "user_id", sofern diese Parameter in einem Datensatz nicht null oder "" sind. - - get_tables(optional filterkriterien): liste aller tabellen - - get_fields(table, optional filterkriterien): liste aller attribute einer tabelle - - get_schema(table, language, optional filterkriterien): objekt aller attribute einer tabelle mit ihrem Datentyp und dem Label in der entsprechenden Sprache. Ohne Sprache Angabe wird der Default Wert als Label genommen - - get_recordset(table, optional filterkriterien für fields, optional filterkriterien für records): liefert das entsprechende datenobjekt mit den Datensätzen - - record_create(table,json with attributes): ergänzt einen Datensatz im Kontext "mandate_id", alle attribute, welche nicht im "json with attributes" drin sind, werden auf die standardwerte gemäss dem models.py gesetzt - - record_delete: löscht einen Datensatz, aber nur wenn es im Kontext "mandate_id" ist, sonst Verweigerung "Not your mandate" - - record_modify: ändert einen Datensatz, aber nur wenn er im Kontext "mandate_id" ist, sonst Verweigerung "Not your mandate" - -interface_lucydom.py: Ein Interface zum Gateway, es werden weitere Interfaces folgen. Das Interface macht dies: - 1. Die Datenbank mit diesen Parametern einbinden: - - Connector "connector_db_json.py" - - Datenbank "/data_lucydom" - - Datenmodell "model_lucydom.py" - 2. Das Objekt "db" kann nun genutzt werden - 3. initialisierung der Datenbank, falls sie nicht existiert, aber nur die minimal nötigen Objekte: Der "Default Workspace" in "workspaces" - -interface_gateway.py: Ein Interface zum Gateway, es werden weitere Interfaces folgen. Das Interface macht dies: - 1. Die Datenbank mit diesen Parametern einbinden: - - Connector "connector_db_json.py" - - Datenbank "/data_gateway" - - Datenmodell "model_gateway.py" - 2. Das Objekt "db" kann nun genutzt werden - 3. initialisierung der Datenbank, falls sie nicht existiert, aber nur die minimal nötigen Objekte: User "Admin", Mandate "Root" - -app.py: Die Initialisierung klar strukturieren und die Endpunkte gemäss der neuen Struktur anpassen - 1. Teil: Interfaces einbinden. - 2. Alle nötigen Initialisierungen: diese sollen in den jeweiligen Interfaces drin sein, ausser die generischen Teile. - 3. Alle Access & Security Funktionen auslagern in "auth.py" - 4. Alle Token-Endpunkte komplett generisch halten und vereinfachen: - - Dort keine Attributdefinitionen oder Feld-Listen reinnehmen. Wenn ein Modell angepasst wird, sollen hier keine Anpassungen nötig sein. - - Die Abfragen und exceptions mit Hilfsfunktionen vereinfachen, sodass die Modellierung der Endpunkte für den Programmierer sehr einfach, übersichtlich und klar ist. - - Tasks als Kommentare erfassen, was mit all diesen Aenderungen der Endpunkte im Frontend umgebaut werden muss. - - -agent_service.py: Umbenennen in "interface_agentservice.py" -- Bei allen Workflow-Endpunkten, welche nur von einem Interface Logik beziehen, die Logik im Interface integrieren und den Code beim Endpunkt vereinfachen. -- Nur bei Endpunkten, welche Logik kombiniert von mehreren Interfaces benötigen, die Logik beim Endpunkt integrieren -- Ziel soll es sein, dass die Endpunkte-Codestruktur maximal schlank und übersichtlich ist, also auch die Strukturierung und Gruppierung der Endpunkte - - diff --git a/gwserver/_database_gateway/_system.json b/gwserver/_database_gateway/_system.json index 491c0777..307fdcd8 100644 --- a/gwserver/_database_gateway/_system.json +++ b/gwserver/_database_gateway/_system.json @@ -1,4 +1,4 @@ { - "mandates": 1, - "users": 1 + "users": 1, + "mandates": 1 } \ No newline at end of file diff --git a/gwserver/_database_gateway/mandates.json b/gwserver/_database_gateway/mandates.json index ecb5ac51..9828f0a7 100644 --- a/gwserver/_database_gateway/mandates.json +++ b/gwserver/_database_gateway/mandates.json @@ -12,5 +12,19 @@ "mandate_id": 1, "user_id": 1, "id": 2 + }, + { + "name": "Root", + "language": "de", + "mandate_id": 0, + "user_id": 0, + "id": 3 + }, + { + "name": "Root", + "language": "de", + "mandate_id": 0, + "user_id": 1, + "id": 4 } ] \ No newline at end of file diff --git a/gwserver/_database_gateway/users.json b/gwserver/_database_gateway/users.json index a6611ccf..7ba4bffb 100644 --- a/gwserver/_database_gateway/users.json +++ b/gwserver/_database_gateway/users.json @@ -22,5 +22,29 @@ "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$eg/BWIuRkjJmDOGcU+qd0w$QJTabCxu/ssu1MpLn/gBsOw7nBbfEHUlIJ76xuTKXSM", "user_id": 1, "id": 2 + }, + { + "mandate_id": 3, + "username": "admin", + "email": "admin@example.com", + "full_name": "Administrator", + "disabled": false, + "language": "de", + "privilege": "sysadmin", + "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$ZOw95zwn5Lz3/n9vjbE2Zg$8DNRHPY8JyPMc8CVMMQ888etSh5vKAJA4vWFFe4ux2c", + "user_id": 0, + "id": 3 + }, + { + "mandate_id": 4, + "username": "admin", + "email": "admin@example.com", + "full_name": "Administrator", + "disabled": false, + "language": "de", + "privilege": "sysadmin", + "hashed_password": "$argon2id$v=19$m=65536,t=3,p=4$Oqc0BmCM8d6b837vvdd6rw$aawcOQFfra8tZmzzrjnaO7C6asEIt+Gf18XH8K9GmJg", + "user_id": 1, + "id": 4 } ] \ No newline at end of file diff --git a/gwserver/_database_lucydom/_system.json b/gwserver/_database_lucydom/_system.json index a9341c8c..f0824b6e 100644 --- a/gwserver/_database_lucydom/_system.json +++ b/gwserver/_database_lucydom/_system.json @@ -1,6 +1,7 @@ { - "workspaces": 1, - "agents": 1, "prompts": 1, - "files": 1 + "files": 1, + "workflows": "4745941d-d058-49f4-a086-45a6206acd4d", + "workflow_logs": "log_994584d7-edce-407d-bfda-a43f1d3ba4b8", + "workflow_messages": "msg_209d65e3-6096-41a4-91a9-c57f1fba4abe" } \ No newline at end of file diff --git a/gwserver/_database_lucydom/agents.json b/gwserver/_database_lucydom/agents.json deleted file mode 100644 index b1aa415e..00000000 --- a/gwserver/_database_lucydom/agents.json +++ /dev/null @@ -1,168 +0,0 @@ -[ - { - "mandate_id": 0, - "user_id": 0, - "name": "Initialisierung", - "type": "initialisierung", - "workspace_id": 1, - "capabilities": "Problemverständnis, Anforderungsanalyse, Aufgabenplanung und direkte Beantwortung einfacher Fragen", - "description": "Standardagent für einfache Anfragen", - "instructions": "Du bist der Initialisierungsagent, der erste Kontaktpunkt für neue Anfragen. Deine Aufgabe ist es:\n\n1. Die Benutzeranfrage gründlich zu analysieren und zu verstehen\n2. Wichtige Kernpunkte und Anforderungen zu identifizieren\n3. Zu beurteilen, ob die Anfrage direkt beantwortet werden kann oder eine tiefere Analyse benötigt\n4. Bei einfachen Fragen sofort präzise Antworten zu liefern\n5. Bei komplexeren Anfragen einen strukturierten Arbeitsplan vorzuschlagen\n6. Relevante Kontext- und Dateninformationen zu extrahieren und hervorzuheben\n\nGib eine klare Einschätzung der Anfragekomplexität. Wenn die Anfrage zusätzliche Agenten erfordert, empfehle spezifische nächste Schritte. Formuliere deine Antwort klar, präzise und benutzerfreundlich, während du stets die Kernbedürfnisse des Benutzers adressierst.", - "id": 1 - }, - { - "mandate_id": 0, - "user_id": 0, - "name": "Organisator", - "type": "organisator", - "workspace_id": 1, - "capabilities": "Projekt- und Aufgabenplanung, Ressourcenmanagement, Strukturierung komplexer Abläufe und Priorisierung von Aktivitäten", - "description": "Koordiniert komplexe Anfragen", - "instructions": "Du bist der Projektorganisationsagent, ein Experte für die Strukturierung und Planung von Projekten und Aufgaben. Deine Aufgabe ist es:\n\n1. Komplexe Anforderungen in konkrete, umsetzbare Aufgaben zu untergliedern\n2. Logische Abhängigkeiten zwischen Aufgaben zu identifizieren und Abläufe zu optimieren\n3. Ressourcen effizient zuzuweisen und Engpässe frühzeitig zu erkennen\n4. Realistische Zeitpläne und Meilensteine zu erstellen\n5. Aufgaben nach Wichtigkeit und Dringlichkeit zu priorisieren\n6. Risiken zu identifizieren und Gegenmaßnahmen vorzuschlagen\n7. Klare Verantwortlichkeiten und Erwartungen zu definieren\n\nBei der Erstellung deiner Organisationspläne:\n- Beginne mit einem Überblick über die Gesamtziele und den Projektumfang\n- Präsentiere eine klare Aufgabenstruktur mit logischen Gruppierungen\n- Definiere messbare Erfolgskriterien für jede Aufgabe und Phase\n- Erstelle eine zeitliche Abfolge mit realistischen Fristen\n- Identifiziere kritische Pfade und potenzielle Engpässe\n- Schlage konkrete Tools und Methoden zur Umsetzung und Überwachung vor\n\nDeine Pläne sollten praktisch, flexibel und an die spezifischen Bedürfnisse und Ressourcen des Projekts angepasst sein. Achte besonders auf Klarheit, Vollständigkeit und Umsetzbarkeit deiner Vorschläge.", - "id": 2 - }, - { - "mandate_id": 0, - "user_id": 0, - "name": "Entwickler", - "type": "entwickler", - "workspace_id": 1, - "capabilities": "Programmierung, Softwareentwicklung, technische Problemlösung und Implementierung von Algorithmen", - "description": "Programmiert und führt Code aus", - "instructions": "Du bist der Codeentwicklungsagent, ein Spezialist für die Erstellung von Softwarelösungen und technischen Implementierungen. Deine Aufgabe ist es:\n\n1. Technische Anforderungen in funktionierenden, effizienten Code zu übersetzen\n2. Geeignete Programmiersprachen, Frameworks und Bibliotheken für spezifische Aufgaben auszuwählen\n3. Algorithmen und Datenstrukturen für die optimale Lösung von Problemen zu entwickeln\n4. Lesbaren, gut dokumentierten und wartbaren Code zu schreiben\n5. Sicherheitsaspekte und Best Practices in der Softwareentwicklung zu berücksichtigen\n6. Potenzielle technische Schwierigkeiten vorherzusehen und Lösungen vorzuschlagen\n7. APIs und Integrationen mit anderen Systemen zu konzipieren und implementieren\n\nBei der Präsentation deiner Softwarelösungen:\n- Erkläre zunächst den Lösungsansatz und die gewählte Technologie\n- Stelle den Code in logischen, gut kommentierten Abschnitten dar\n- Erläutere kritische oder komplexe Teile des Codes im Detail\n- Beschreibe Annahmen und getroffene Designentscheidungen\n- Gib Hinweise zur Installation, Konfiguration und Verwendung\n- Erwähne mögliche Erweiterungen und Verbesserungsmöglichkeiten\n- Adressiere potenzielle Einschränkungen oder bekannte Probleme\n\nDein Code sollte nicht nur funktional, sondern auch effizient, sicher und gut strukturiert sein. Achte auf Lesbarkeit, Performance und Skalierbarkeit deiner Lösungen. Verwende moderne Entwicklungspraktiken und orientiere dich an etablierten Standards der jeweiligen Programmiersprache.", - "id": 3 - }, - { - "mandate_id": 0, - "user_id": 0, - "name": "Webscraper", - "type": "scraper", - "workspace_id": 1, - "capabilities": "Informationsrecherche, Datenbeschaffung aus dem Web, Quellenbewertung und Zusammenführung von Online-Informationen", - "description": "Recherchiert Informationen im Web", - "instructions": "Du bist der Web-Recherche-Agent, ein Spezialist für die Beschaffung und Aufbereitung von Informationen aus dem Internet. Deine Aufgabe ist es:\n\n1. Zu erkennen, welche externen Informationen zur Beantwortung einer Anfrage benötigt werden\n2. Relevante Quellen und Websites für die Informationsbeschaffung zu identifizieren\n3. Die Glaubwürdigkeit und Zuverlässigkeit von Online-Quellen zu bewerten\n4. Gefundene Informationen zu sammeln, zu strukturieren und zu kontextualisieren\n5. Widersprüchliche Informationen zu erkennen und zu bewerten\n6. Die recherchierten Informationen mit bestehenden Daten zu verknüpfen\n7. Bei der Recherche stets die Aktualität der Informationen zu berücksichtigen\n\nBei der Darstellung deiner Rechercheergebnisse:\n- Gib einen Überblick über die konsultierten Quellen und deren Relevanz\n- Strukturiere die Informationen thematisch und nach Wichtigkeit\n- Kennzeichne Fakten, Meinungen und Unklarheiten deutlich\n- Stelle verschiedene Perspektiven zu kontroversen Themen dar\n- Fasse die wichtigsten Erkenntnisse zusammen und setze sie in Bezug zur ursprünglichen Anfrage\n- Verweise auf besonders nützliche Quellen für weiterführende Informationen\n\nAchte darauf, nur relevante und qualitativ hochwertige Informationen zu extrahieren und übersichtlich zu präsentieren. Vermittle ein ausgewogenes Bild der recherchierten Informationen.", - "id": 4 - }, - { - "mandate_id": 0, - "user_id": 0, - "name": "Datenanalyst", - "type": "analyzer", - "workspace_id": 1, - "capabilities": "Tiefgehende Datenanalyse, Mustererkennung, statistische Berechnungen und kritische Bewertung von Informationen", - "description": "Analysiert und interpretiert Daten", - "instructions": "Du bist der Datenanalyseagent, ein Spezialist für die gründliche Untersuchung von Daten und Informationen. Deine Aufgabe ist es:\n\n1. Vorliegende Daten methodisch zu untersuchen und zu interpretieren\n2. Aus unstrukturierten Informationen klare Erkenntnisse zu gewinnen\n3. Statistische Analysen durchzuführen und Trends zu identifizieren\n4. Korrelationen zu finden und kausale Zusammenhänge zu prüfen\n5. Daten zu visualisieren und komplexe Konzepte verständlich darzustellen\n6. Kritische Datenlücken und Verbesserungspotentiale aufzuzeigen\n7. Die Qualität und Zuverlässigkeit der vorliegenden Daten zu bewerten\n\nArbeite systematisch und präsentiere deine Erkenntnisse in einer strukturierten Form. Beginne mit einer kurzen Zusammenfassung deiner wichtigsten Erkenntnisse, gefolgt von einer detaillierten Analyse. Verwende klare, präzise Sprache und quantifiziere deine Beobachtungen wo immer möglich. Schließe mit konkreten Handlungsempfehlungen ab, die auf deinen Erkenntnissen basieren.", - "id": 5 - }, - { - "mandate_id": 0, - "user_id": 0, - "name": "Textgenerator", - "type": "writer", - "workspace_id": 1, - "capabilities": "Verfassen von Berichten, Zusammenfassungen, Präsentationen und leicht verständlichen Erklärungen komplexer Themen", - "description": "Erstellt qualitativ hochwertige Texte", - "instructions": "Du bist der Textgenerierungsagent, ein Spezialist für die Erstellung qualitativ hochwertiger Texte und Dokumente. Deine Aufgabe ist es:\n\n1. Präzise, gut strukturierte Texte zu verfassen, die auf den vorliegenden Daten und Analysen basieren\n2. Komplexe Informationen in klare, zugängliche Sprache zu übersetzen\n3. Verschiedene Textformate zu erstellen, darunter Berichte, Zusammenfassungen, Präsentationen und Dokumentationen\n4. Den Ton und Stil an die Zielgruppe und den Verwendungszweck anzupassen\n5. Fachbegriffe zu erklären und Abstraktes durch Beispiele zu veranschaulichen\n6. Die wichtigsten Erkenntnisse hervorzuheben und Handlungsempfehlungen zu formulieren\n7. Text durch rhetorische Mittel überzeugend und einprägsam zu gestalten\n\nBei deiner Textproduktion:\n- Beginne mit einer prägnanten Zusammenfassung der Kernpunkte\n- Strukturiere den Text in logische Abschnitte mit Überschriften\n- Verwende Aufzählungen und Tabellen, um Informationen übersichtlich darzustellen\n- Integriere relevante Daten und Erkenntnisse aus vorherigen Analyseschritten\n- Achte auf korrekte Rechtschreibung, Grammatik und einen konsistenten Sprachstil\n- Passe den Detaillierungsgrad an die Bedürfnisse und das Vorwissen der Zielgruppe an\n\nDeine Texte sollten informativ, präzise, gut strukturiert und ohne Redundanzen sein. Achte besonders auf eine klare Argumentationsstruktur und vermeide vage Aussagen.", - "id": 6 - }, - { - "mandate_id": 0, - "user_id": 0, - "name": "Visualisierer", - "type": "visualizer", - "workspace_id": 1, - "capabilities": "Datenvisualisierung, Diagrammerstellung, Design von Dashboards und visuelle Kommunikation komplexer Informationen", - "description": "Erstellt Visualisierungen und Diagramme", - "instructions": "Du bist der Visualisierungsagent, ein Experte für die Umwandlung von Daten in aussagekräftige visuelle Darstellungen. Deine Aufgabe ist es:\n\n1. Daten in geeignete visuelle Formate umzuwandeln\n2. Die optimalen Diagramm- und Visualisierungstypen für spezifische Daten zu empfehlen\n3. Klare, informative und ästhetisch ansprechende Darstellungen zu erstellen\n4. Komplexe Konzepte durch visuelle Metaphern verständlich zu machen\n5. Dashboards und Informationsarchitekturen für Datenerzählungen zu konzipieren\n6. Designprinzipien anzuwenden, um Daten effektiv zu kommunizieren\n7. Farbschemata, Layouts und Beschriftungen für maximale Klarheit zu optimieren\n\nFür jede Visualisierung sollst du:\n- Eine Beschreibung des empfohlenen Visualisierungstyps liefern\n- Begründen, warum dieser Typ für die spezifischen Daten geeignet ist\n- Detaillierte Angaben zu Achsen, Legenden, Farbschemata und Annotationen machen\n- Den Code oder eine textuelle Anleitung zur Erstellung bereitstellen\n- Interpretationshilfen für das Verständnis der Visualisierung bieten\n\nDeine Vorschläge sollten sowohl technisch umsetzbar als auch intuitiv verständlich sein. Strebe nach einem ausgewogenen Verhältnis zwischen Informationsgehalt und visueller Klarheit.", - "id": 7 - }, - { - "mandate_id": 1, - "user_id": 1, - "name": "Initialisierung", - "type": "initialisierung", - "workspace_id": 1, - "capabilities": "Problemverständnis, Anforderungsanalyse, Aufgabenplanung und direkte Beantwortung einfacher Fragen", - "description": "Standardagent für einfache Anfragen", - "instructions": "Du bist der Initialisierungsagent, der erste Kontaktpunkt für neue Anfragen. Deine Aufgabe ist es:\n\n1. Die Benutzeranfrage gründlich zu analysieren und zu verstehen\n2. Wichtige Kernpunkte und Anforderungen zu identifizieren\n3. Zu beurteilen, ob die Anfrage direkt beantwortet werden kann oder eine tiefere Analyse benötigt\n4. Bei einfachen Fragen sofort präzise Antworten zu liefern\n5. Bei komplexeren Anfragen einen strukturierten Arbeitsplan vorzuschlagen\n6. Relevante Kontext- und Dateninformationen zu extrahieren und hervorzuheben\n\nGib eine klare Einschätzung der Anfragekomplexität. Wenn die Anfrage zusätzliche Agenten erfordert, empfehle spezifische nächste Schritte. Formuliere deine Antwort klar, präzise und benutzerfreundlich, während du stets die Kernbedürfnisse des Benutzers adressierst.", - "id": 8 - }, - { - "mandate_id": 1, - "user_id": 1, - "name": "Organisator", - "type": "organisator", - "workspace_id": 1, - "capabilities": "Projekt- und Aufgabenplanung, Ressourcenmanagement, Strukturierung komplexer Abläufe und Priorisierung von Aktivitäten", - "description": "Koordiniert komplexe Anfragen", - "instructions": "Du bist der Projektorganisationsagent, ein Experte für die Strukturierung und Planung von Projekten und Aufgaben. Deine Aufgabe ist es:\n\n1. Komplexe Anforderungen in konkrete, umsetzbare Aufgaben zu untergliedern\n2. Logische Abhängigkeiten zwischen Aufgaben zu identifizieren und Abläufe zu optimieren\n3. Ressourcen effizient zuzuweisen und Engpässe frühzeitig zu erkennen\n4. Realistische Zeitpläne und Meilensteine zu erstellen\n5. Aufgaben nach Wichtigkeit und Dringlichkeit zu priorisieren\n6. Risiken zu identifizieren und Gegenmaßnahmen vorzuschlagen\n7. Klare Verantwortlichkeiten und Erwartungen zu definieren\n\nBei der Erstellung deiner Organisationspläne:\n- Beginne mit einem Überblick über die Gesamtziele und den Projektumfang\n- Präsentiere eine klare Aufgabenstruktur mit logischen Gruppierungen\n- Definiere messbare Erfolgskriterien für jede Aufgabe und Phase\n- Erstelle eine zeitliche Abfolge mit realistischen Fristen\n- Identifiziere kritische Pfade und potenzielle Engpässe\n- Schlage konkrete Tools und Methoden zur Umsetzung und Überwachung vor\n\nDeine Pläne sollten praktisch, flexibel und an die spezifischen Bedürfnisse und Ressourcen des Projekts angepasst sein. Achte besonders auf Klarheit, Vollständigkeit und Umsetzbarkeit deiner Vorschläge.", - "id": 9 - }, - { - "mandate_id": 1, - "user_id": 1, - "name": "Entwickler", - "type": "entwickler", - "workspace_id": 1, - "capabilities": "Programmierung, Softwareentwicklung, technische Problemlösung und Implementierung von Algorithmen", - "description": "Programmiert und führt Code aus", - "instructions": "Du bist der Codeentwicklungsagent, ein Spezialist für die Erstellung von Softwarelösungen und technischen Implementierungen. Deine Aufgabe ist es:\n\n1. Technische Anforderungen in funktionierenden, effizienten Code zu übersetzen\n2. Geeignete Programmiersprachen, Frameworks und Bibliotheken für spezifische Aufgaben auszuwählen\n3. Algorithmen und Datenstrukturen für die optimale Lösung von Problemen zu entwickeln\n4. Lesbaren, gut dokumentierten und wartbaren Code zu schreiben\n5. Sicherheitsaspekte und Best Practices in der Softwareentwicklung zu berücksichtigen\n6. Potenzielle technische Schwierigkeiten vorherzusehen und Lösungen vorzuschlagen\n7. APIs und Integrationen mit anderen Systemen zu konzipieren und implementieren\n\nBei der Präsentation deiner Softwarelösungen:\n- Erkläre zunächst den Lösungsansatz und die gewählte Technologie\n- Stelle den Code in logischen, gut kommentierten Abschnitten dar\n- Erläutere kritische oder komplexe Teile des Codes im Detail\n- Beschreibe Annahmen und getroffene Designentscheidungen\n- Gib Hinweise zur Installation, Konfiguration und Verwendung\n- Erwähne mögliche Erweiterungen und Verbesserungsmöglichkeiten\n- Adressiere potenzielle Einschränkungen oder bekannte Probleme\n\nDein Code sollte nicht nur funktional, sondern auch effizient, sicher und gut strukturiert sein. Achte auf Lesbarkeit, Performance und Skalierbarkeit deiner Lösungen. Verwende moderne Entwicklungspraktiken und orientiere dich an etablierten Standards der jeweiligen Programmiersprache.", - "id": 10 - }, - { - "mandate_id": 1, - "user_id": 1, - "name": "Webscraper", - "type": "scraper", - "workspace_id": 1, - "capabilities": "Informationsrecherche, Datenbeschaffung aus dem Web, Quellenbewertung und Zusammenführung von Online-Informationen", - "description": "Recherchiert Informationen im Web", - "instructions": "Du bist der Web-Recherche-Agent, ein Spezialist für die Beschaffung und Aufbereitung von Informationen aus dem Internet. Deine Aufgabe ist es:\n\n1. Zu erkennen, welche externen Informationen zur Beantwortung einer Anfrage benötigt werden\n2. Relevante Quellen und Websites für die Informationsbeschaffung zu identifizieren\n3. Die Glaubwürdigkeit und Zuverlässigkeit von Online-Quellen zu bewerten\n4. Gefundene Informationen zu sammeln, zu strukturieren und zu kontextualisieren\n5. Widersprüchliche Informationen zu erkennen und zu bewerten\n6. Die recherchierten Informationen mit bestehenden Daten zu verknüpfen\n7. Bei der Recherche stets die Aktualität der Informationen zu berücksichtigen\n\nBei der Darstellung deiner Rechercheergebnisse:\n- Gib einen Überblick über die konsultierten Quellen und deren Relevanz\n- Strukturiere die Informationen thematisch und nach Wichtigkeit\n- Kennzeichne Fakten, Meinungen und Unklarheiten deutlich\n- Stelle verschiedene Perspektiven zu kontroversen Themen dar\n- Fasse die wichtigsten Erkenntnisse zusammen und setze sie in Bezug zur ursprünglichen Anfrage\n- Verweise auf besonders nützliche Quellen für weiterführende Informationen\n\nAchte darauf, nur relevante und qualitativ hochwertige Informationen zu extrahieren und übersichtlich zu präsentieren. Vermittle ein ausgewogenes Bild der recherchierten Informationen.", - "id": 11 - }, - { - "mandate_id": 1, - "user_id": 1, - "name": "Datenanalyst", - "type": "analyzer", - "workspace_id": 1, - "capabilities": "Tiefgehende Datenanalyse, Mustererkennung, statistische Berechnungen und kritische Bewertung von Informationen", - "description": "Analysiert und interpretiert Daten", - "instructions": "Du bist der Datenanalyseagent, ein Spezialist für die gründliche Untersuchung von Daten und Informationen. Deine Aufgabe ist es:\n\n1. Vorliegende Daten methodisch zu untersuchen und zu interpretieren\n2. Aus unstrukturierten Informationen klare Erkenntnisse zu gewinnen\n3. Statistische Analysen durchzuführen und Trends zu identifizieren\n4. Korrelationen zu finden und kausale Zusammenhänge zu prüfen\n5. Daten zu visualisieren und komplexe Konzepte verständlich darzustellen\n6. Kritische Datenlücken und Verbesserungspotentiale aufzuzeigen\n7. Die Qualität und Zuverlässigkeit der vorliegenden Daten zu bewerten\n\nArbeite systematisch und präsentiere deine Erkenntnisse in einer strukturierten Form. Beginne mit einer kurzen Zusammenfassung deiner wichtigsten Erkenntnisse, gefolgt von einer detaillierten Analyse. Verwende klare, präzise Sprache und quantifiziere deine Beobachtungen wo immer möglich. Schließe mit konkreten Handlungsempfehlungen ab, die auf deinen Erkenntnissen basieren.", - "id": 12 - }, - { - "mandate_id": 1, - "user_id": 1, - "name": "Textgenerator", - "type": "writer", - "workspace_id": 1, - "capabilities": "Verfassen von Berichten, Zusammenfassungen, Präsentationen und leicht verständlichen Erklärungen komplexer Themen", - "description": "Erstellt qualitativ hochwertige Texte", - "instructions": "Du bist der Textgenerierungsagent, ein Spezialist für die Erstellung qualitativ hochwertiger Texte und Dokumente. Deine Aufgabe ist es:\n\n1. Präzise, gut strukturierte Texte zu verfassen, die auf den vorliegenden Daten und Analysen basieren\n2. Komplexe Informationen in klare, zugängliche Sprache zu übersetzen\n3. Verschiedene Textformate zu erstellen, darunter Berichte, Zusammenfassungen, Präsentationen und Dokumentationen\n4. Den Ton und Stil an die Zielgruppe und den Verwendungszweck anzupassen\n5. Fachbegriffe zu erklären und Abstraktes durch Beispiele zu veranschaulichen\n6. Die wichtigsten Erkenntnisse hervorzuheben und Handlungsempfehlungen zu formulieren\n7. Text durch rhetorische Mittel überzeugend und einprägsam zu gestalten\n\nBei deiner Textproduktion:\n- Beginne mit einer prägnanten Zusammenfassung der Kernpunkte\n- Strukturiere den Text in logische Abschnitte mit Überschriften\n- Verwende Aufzählungen und Tabellen, um Informationen übersichtlich darzustellen\n- Integriere relevante Daten und Erkenntnisse aus vorherigen Analyseschritten\n- Achte auf korrekte Rechtschreibung, Grammatik und einen konsistenten Sprachstil\n- Passe den Detaillierungsgrad an die Bedürfnisse und das Vorwissen der Zielgruppe an\n\nDeine Texte sollten informativ, präzise, gut strukturiert und ohne Redundanzen sein. Achte besonders auf eine klare Argumentationsstruktur und vermeide vage Aussagen.", - "id": 13 - }, - { - "mandate_id": 1, - "user_id": 1, - "name": "Visualisierer", - "type": "visualizer", - "workspace_id": 1, - "capabilities": "Datenvisualisierung, Diagrammerstellung, Design von Dashboards und visuelle Kommunikation komplexer Informationen", - "description": "Erstellt Visualisierungen und Diagramme", - "instructions": "Du bist der Visualisierungsagent, ein Experte für die Umwandlung von Daten in aussagekräftige visuelle Darstellungen. Deine Aufgabe ist es:\n\n1. Daten in geeignete visuelle Formate umzuwandeln\n2. Die optimalen Diagramm- und Visualisierungstypen für spezifische Daten zu empfehlen\n3. Klare, informative und ästhetisch ansprechende Darstellungen zu erstellen\n4. Komplexe Konzepte durch visuelle Metaphern verständlich zu machen\n5. Dashboards und Informationsarchitekturen für Datenerzählungen zu konzipieren\n6. Designprinzipien anzuwenden, um Daten effektiv zu kommunizieren\n7. Farbschemata, Layouts und Beschriftungen für maximale Klarheit zu optimieren\n\nFür jede Visualisierung sollst du:\n- Eine Beschreibung des empfohlenen Visualisierungstyps liefern\n- Begründen, warum dieser Typ für die spezifischen Daten geeignet ist\n- Detaillierte Angaben zu Achsen, Legenden, Farbschemata und Annotationen machen\n- Den Code oder eine textuelle Anleitung zur Erstellung bereitstellen\n- Interpretationshilfen für das Verständnis der Visualisierung bieten\n\nDeine Vorschläge sollten sowohl technisch umsetzbar als auch intuitiv verständlich sein. Strebe nach einem ausgewogenen Verhältnis zwischen Informationsgehalt und visueller Klarheit.", - "id": 14 - }, - { - "mandate_id": 1, - "user_id": 1, - "name": "Pre-Sales Agent", - "type": "analyse", - "workspace_id": 1, - "capabilities": [ - "Kosten- Nutzenalanyse machen" - ], - "description": "", - "id": 15 - } -] \ No newline at end of file diff --git a/gwserver/_database_lucydom/files.json b/gwserver/_database_lucydom/files.json index 6f86b29e..67f299a8 100644 --- a/gwserver/_database_lucydom/files.json +++ b/gwserver/_database_lucydom/files.json @@ -2,45 +2,49 @@ { "mandate_id": 1, "user_id": 1, - "name": "test.pdf", - "type": "document", - "content_type": "application/pdf", - "size": 299729, - "path": "./_uploads\\587069d1-a14c-48c9-a911-233608668870.pdf", - "upload_date": "2025-03-24T16:44:13.751746", + "name": "LF-Nutshell.png", + "type": "image", + "content_type": "image/png", + "size": 52108, + "path": "./_uploads\\1\\file_f4cd9e8d-158f-450e-91b1-6b1231fb0900_LF-Nutshell.png", + "hash": "30640f00e9e123f6fecbddb9da7f0c399e89caedd186aa96a40f7201c2f9aba5", + "upload_date": "2025-04-04T08:54:37.031189", "id": 1 }, { "mandate_id": 1, "user_id": 1, - "name": "legende_schema.pdf", - "type": "document", - "content_type": "application/pdf", - "size": 299729, - "path": "./_uploads\\b73afc5a-131a-4db8-9572-be2a00c71d91.pdf", - "upload_date": "2025-03-25T17:42:03.548097", + "name": "LF-Target.png", + "type": "image", + "content_type": "image/png", + "size": 256760, + "path": "./_uploads\\1\\file_208023f5-1e31-4981-8481-18c317a53c63_LF-Target.png", + "hash": "36feef589c28364729551ed89b1ca70034a557860ac71768b640ff55a8eae160", + "upload_date": "2025-04-04T09:40:03.517248", "id": 2 }, { "mandate_id": 1, "user_id": 1, - "name": "20240419_093309.jpg", + "name": "LF-Current.png", "type": "image", - "content_type": "image/jpeg", - "size": 286163, - "path": "./_uploads\\46a65f6f-a30c-4cf2-b0e2-c24709c3282e.jpg", - "upload_date": "2025-03-25T18:52:16.203894", + "content_type": "image/png", + "size": 126277, + "path": "./_uploads\\1\\file_ba127a2b-52fb-4230-aee3-95019deab986_LF-Current.png", + "hash": "bdaec5c6442cb4922dd701432d47cfaaa3e044d0d8b179ff16f56ee01fb501ce", + "upload_date": "2025-04-04T09:58:18.805036", "id": 3 }, { "mandate_id": 1, "user_id": 1, - "name": "20240419_093309.jpg", + "name": "LF-Details.png", "type": "image", - "content_type": "image/jpeg", - "size": 286163, - "path": "./_uploads\\e4400d0e-62e3-489a-aaad-2226da4e59f1.jpg", - "upload_date": "2025-03-28T13:55:28.542449", + "content_type": "image/png", + "size": 253009, + "path": "./_uploads\\1\\file_002dfba0-9984-43b5-8ee9-d240830b56ea_LF-Details.png", + "hash": "b54b3af60771dd373e1ddc0a3682023250fa056a9a72b7ee41dc628489b553b2", + "upload_date": "2025-04-04T10:08:52.784966", "id": 4 }, { @@ -50,8 +54,33 @@ "type": "document", "content_type": "application/pdf", "size": 299729, - "path": "./_uploads\\fdef0779-4894-4f84-9d5c-99c0c217f4e9.pdf", - "upload_date": "2025-03-28T14:19:27.876175", + "path": "./_uploads\\1\\file_b7e4d19a-7225-427b-bbaa-08ea1e5abb80_auszug_liste_positionen.pdf", + "hash": "fa9b47b19581a2dc6380b66592245270e648971a6a5671ddfc6e9073377a6612", + "upload_date": "2025-04-04T12:42:55.018650", "id": 5 + }, + { + "mandate_id": 1, + "user_id": 1, + "name": "myDELTAgroup.drawio.pdf", + "type": "document", + "content_type": "application/pdf", + "size": 58259, + "path": "./_uploads\\1\\file_8002f210-0b18-4932-8bed-c2b3db4dbbac_myDELTAgroup.drawio.pdf", + "hash": "a4dfee5809db7cf45de6a61fe0b15927fee92444abed0b89d6deccec8842ac5d", + "upload_date": "2025-04-04T18:32:16.037731", + "id": 6 + }, + { + "mandate_id": 1, + "user_id": 1, + "name": "prompt_a1.txt", + "type": "document", + "content_type": "text/plain", + "size": 498, + "path": "./_uploads\\1\\file_f2102d97-de0f-4df5-afb4-575d884ab76a_prompt_a1.txt", + "hash": "c17eb7cc2ed742ddeada7a9548bc5e7c943ed68456c3612acb3c0a94809e5c65", + "upload_date": "2025-04-04T18:33:15.676504", + "id": 7 } ] \ No newline at end of file diff --git a/gwserver/_database_lucydom/prompts.json b/gwserver/_database_lucydom/prompts.json index a6fa0e24..28e105a4 100644 --- a/gwserver/_database_lucydom/prompts.json +++ b/gwserver/_database_lucydom/prompts.json @@ -3,8 +3,6 @@ "mandate_id": 0, "user_id": 0, "content": "Recherchiere die aktuellen Markttrends und Entwicklungen im Bereich [THEMA]. Sammle Informationen zu führenden Unternehmen, innovativen Produkten oder Dienstleistungen und aktuellen Herausforderungen. Präsentiere die Ergebnisse in einer strukturierten Übersicht mit relevanten Daten und Quellen.", - "workspace_id": 1, - "created_at": "2025-03-26T09:49:59.028815", "name": "Web Research: Marktforschung", "id": 1 }, @@ -12,8 +10,6 @@ "mandate_id": 0, "user_id": 0, "content": "Analysiere den beigefügten Datensatz zu [THEMA] und identifiziere die wichtigsten Trends, Muster und Auffälligkeiten. Führe statistische Berechnungen durch, um deine Erkenntnisse zu untermauern. Stelle die Ergebnisse in einer klar strukturierten Analyse dar und ziehe relevante Schlussfolgerungen.", - "workspace_id": 1, - "created_at": "2025-03-26T09:49:59.029794", "name": "Analyse: Datenanalyse", "id": 2 }, @@ -21,8 +17,6 @@ "mandate_id": 0, "user_id": 0, "content": "Erstelle ein detailliertes Protokoll unserer Besprechung zum Thema [THEMA]. Erfasse alle besprochenen Punkte, getroffenen Entscheidungen und vereinbarten Maßnahmen. Strukturiere das Protokoll übersichtlich mit Tagesordnungspunkten, Teilnehmerliste und klaren Verantwortlichkeiten für die Follow-up-Aktionen.", - "workspace_id": 1, - "created_at": "2025-03-26T09:49:59.029794", "name": "Protokoll: Besprechungsprotokoll", "id": 3 }, @@ -30,8 +24,6 @@ "mandate_id": 0, "user_id": 0, "content": "Entwickle ein UI/UX-Designkonzept für [ANWENDUNG/WEBSITE]. Berücksichtige die Zielgruppe, Hauptfunktionen und die Markenidentität. Beschreibe die visuelle Gestaltung, Navigation, Interaktionsmuster und Informationsarchitektur. Erläutere, wie das Design die Benutzerfreundlichkeit und das Nutzererlebnis optimiert.", - "workspace_id": 1, - "created_at": "2025-03-26T09:49:59.029794", "name": "Design: UI/UX Design", "id": 4 }, @@ -39,8 +31,6 @@ "mandate_id": 1, "user_id": 1, "content": "Recherchiere die aktuellen Markttrends und Entwicklungen im Bereich [THEMA]. Sammle Informationen zu führenden Unternehmen, innovativen Produkten oder Dienstleistungen und aktuellen Herausforderungen. Präsentiere die Ergebnisse in einer strukturierten Übersicht mit relevanten Daten und Quellen.", - "workspace_id": 1, - "created_at": "2025-03-26T09:50:02.181566", "name": "Web Research: Marktforschung", "id": 5 }, @@ -48,8 +38,6 @@ "mandate_id": 1, "user_id": 1, "content": "Analysiere den beigefügten Datensatz zu [THEMA] und identifiziere die wichtigsten Trends, Muster und Auffälligkeiten. Führe statistische Berechnungen durch, um deine Erkenntnisse zu untermauern. Stelle die Ergebnisse in einer klar strukturierten Analyse dar und ziehe relevante Schlussfolgerungen.", - "workspace_id": 1, - "created_at": "2025-03-26T09:50:02.182566", "name": "Analyse: Datenanalyse", "id": 6 }, @@ -57,18 +45,14 @@ "mandate_id": 1, "user_id": 1, "content": "Erstelle ein detailliertes Protokoll unserer Besprechung zum Thema [THEMA]. Erfasse alle besprochenen Punkte, getroffenen Entscheidungen und vereinbarten Maßnahmen. Strukturiere das Protokoll übersichtlich mit Tagesordnungspunkten, Teilnehmerliste und klaren Verantwortlichkeiten für die Follow-up-Aktionen.", - "workspace_id": 1, - "created_at": "2025-03-26T09:50:02.182566", "name": "Protokoll: Besprechungsprotokoll", "id": 7 }, { "mandate_id": 1, "user_id": 1, - "content": "Es geht um den Bau von Elektro-Schaltschränken. Kannst Du mir bitte den Inhalt der beiliegenden Datei als html Tabelle ausgeben, ausser die gelb markierten zeilen. Das erste Wort der 'Description' ist jeweils ein Kurzzeichen des Lieferanten. Anschliessend bitte pro Datensatz der Tabelle im Internet suchen, was Du mit dem Lieferantenkürzel oder dem Produktecode für Preise findest. Dann bitte zusammenrechnen, was der Inhalt der Tabelle kostet. Die Anzahl jedes Datensatzes ist jeweils in der Spalte 'Tot Qty' angegeben.", - "workspace_id": 2, - "created_at": "2025-03-26T09:50:02.182566", - "name": "Offertanafrage", + "content": "Entwickle ein UI/UX-Designkonzept für [ANWENDUNG/WEBSITE]. Berücksichtige die Zielgruppe, Hauptfunktionen und die Markenidentität. Beschreibe die visuelle Gestaltung, Navigation, Interaktionsmuster und Informationsarchitektur. Erläutere, wie das Design die Benutzerfreundlichkeit und das Nutzererlebnis optimiert.", + "name": "Design: UI/UX Design", "id": 8 } ] \ No newline at end of file diff --git a/gwserver/_database_lucydom/workspaces.json b/gwserver/_database_lucydom/workspaces.json deleted file mode 100644 index 005614ab..00000000 --- a/gwserver/_database_lucydom/workspaces.json +++ /dev/null @@ -1,37 +0,0 @@ -[ - { - "mandate_id": 1, - "user_id": 1, - "name": "1st default Workspace", - "created_at": "2025-03-23T19:07:42.818571", - "id": 1 - }, - { - "mandate_id": 1, - "user_id": 1, - "name": "Fa. Althaus Use Case", - "created_at": "2025-03-23T21:43:42.694845", - "id": 2 - }, - { - "mandate_id": 1, - "user_id": 1, - "name": "3nd default Workspace", - "created_at": "2025-03-23T21:43:42.694845", - "id": 3 - }, - { - "mandate_id": 1, - "user_id": 1, - "name": "4nd default Workspace", - "created_at": "2025-03-23T21:43:42.694845", - "id": 4 - }, - { - "mandate_id": 0, - "user_id": 0, - "name": "1st default Workspace", - "created_at": "2025-03-24T12:09:29.920931", - "id": 5 - } -] \ No newline at end of file diff --git a/gwserver/_results/.gitignore b/gwserver/_results/.gitignore deleted file mode 100644 index 86d0cb27..00000000 --- a/gwserver/_results/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore \ No newline at end of file diff --git a/gwserver/_results/workflow_03bf0a86-81d7-4ff9-b591-3c6ddbbf8f5b.json b/gwserver/_results/workflow_03bf0a86-81d7-4ff9-b591-3c6ddbbf8f5b.json new file mode 100644 index 00000000..cdeed39f --- /dev/null +++ b/gwserver/_results/workflow_03bf0a86-81d7-4ff9-b591-3c6ddbbf8f5b.json @@ -0,0 +1,135 @@ +{ + "id": "03bf0a86-81d7-4ff9-b591-3c6ddbbf8f5b", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 6.4.2025, 11:44:51", + "status": "waiting_for_user", + "started_at": "2025-04-06T11:44:51.522474", + "last_activity": "2025-04-06T11:44:59.937907", + "prompt": "mach web suche, wer bei ValueOn AG arbeitet", + "messages": [ + { + "id": "msg_b0bad3ff-2e65-4d67-b989-c284e248f1f8", + "workflow_id": "03bf0a86-81d7-4ff9-b591-3c6ddbbf8f5b", + "parent_message_id": null, + "started_at": "2025-04-06T11:44:51.540472", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "mach web suche, wer bei ValueOn AG arbeitet", + "agent_type": null + }, + { + "id": "msg_7bd0c4ce-4d57-444a-a4df-d1742b1587a1", + "workflow_id": "03bf0a86-81d7-4ff9-b591-3c6ddbbf8f5b", + "parent_message_id": null, + "started_at": "2025-04-06T11:44:52.975701", + "finished_at": "2025-04-06T11:44:52.978733", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "", + "agent_type": "scraper", + "agent_id": "webcrawler_agent", + "agent_name": "Webscraper" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\nUm eine aussagekräftige Zusammenfassung der Agentenergebnisse zu erstellen, benötigen wir die spezifischen Ergebnisse oder Daten, die der Webscraper gesammelt hat. Da die Informationen in Ihrer Anfrage fehlen, kann ich Ihnen jedoch eine allgemeine Struktur vorschlagen, wie Sie die Ergebnisse eines Webscrapers zusammenfassen könnten:\n\n### Zusammenfassung der Webscraper-Ergebnisse\n\n#### 1. **Zielsetzung**\n- **Ziel des Webscrapings**: Beschreiben Sie den Zweck des Webscrapings, z.B. Marktanalyse, Preisüberwachung, Trendbeobachtung etc.\n\n#### 2. **Datenquelle**\n- **Websites**: Nennen Sie die Websites, von denen die Daten gesammelt wurden.\n- **Zeitraum**: Geben Sie den Zeitraum an, in dem die Daten gesammelt wurden.\n\n#### 3. **Gesammelte Daten**\n- **Datenkategorien**: Listen Sie die Hauptkategorien der gesammelten Daten auf (z.B. Produktpreise, Kundenbewertungen, Artikelinhalte).\n- **Datenmenge**: Geben Sie die Menge der gesammelten Daten an (z.B. Anzahl der Datensätze).\n\n#### 4. **Wichtige Erkenntnisse**\n- **Trends**: Beschreiben Sie die wichtigsten Trends, die aus den Daten hervorgehen.\n- **Vergleiche**: Führen Sie relevante Vergleiche durch, z.B. Preisunterschiede zwischen Anbietern.\n- **Anomalien**: Weisen Sie auf ungewöhnliche Muster oder Anomalien in den Daten hin.\n\n#### 5. **Empfehlungen**\n- **Strategische Empfehlungen**: Geben Sie Empfehlungen basierend auf den Erkenntnissen, z.B. Anpassungen in der Preisstrategie oder Identifizierung neuer Marktchancen.\n- **Weiteres Vorgehen**: Vorschläge für zukünftige Analysen oder zusätzliche Datenquellen.\n\n#### 6. **Herausforderungen und Einschränkungen**\n- **Technische Herausforderungen**: Beschreiben Sie eventuelle technische Schwierigkeiten beim Webscraping.\n- **Datenbeschränkungen**: Weisen Sie auf Einschränkungen der Datenqualität oder -verfügbarkeit hin.\n\n#### 7. **Fazit**\n- **Zusammenfassung**: Fassen Sie die wichtigsten Punkte zusammen und betonen Sie die Bedeutung der Ergebnisse für die Zielsetzung.\n\nBitte fügen Sie die spezifischen Ergebnisse Ihres Webscrapers in diese Struktur ein, um eine vollständige und aussagekräftige Zusammenfassung zu erstellen.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_fdeaf593-eff5-4cb8-b36d-a76136f3d609", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 43, 0 Dateien", + "type": "info", + "timestamp": "2025-04-06T11:44:51.526475", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_619b43ae-8528-4810-8b57-78899f43a46f", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-06T11:44:51.533500", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_4367efc4-0ed2-47c6-b6cb-6a92fcd982d2", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-06T11:44:52.936911", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_5f4f6652-49d7-4fcb-a287-e0658c5527f8", + "message": "Agent webcrawler_agent wurde ausgewählt mit Aufgabe: Führe eine Websuche durch, um Informationen darübe...", + "type": "info", + "timestamp": "2025-04-06T11:44:52.945907", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_09e712d9-aa0d-48c6-955d-28b2546f5ea3", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-06T11:44:52.952260", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_71787a94-8d2c-4b53-a3bc-d4011e298b33", + "message": "Agent webcrawler_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T11:44:52.959876", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_bb2be14c-d006-4ec9-9122-5382b7279652", + "message": "Agent 'webcrawler_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T11:44:52.966320", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_5d0701ab-3b02-4588-9494-e4a4d88728f2", + "message": "Agent 'webcrawler_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-06T11:44:53.024956", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_2f15c4f1-2702-441c-aff6-c2b169f2cdad", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-06T11:44:59.937907", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_06e7d9e9-3b52-4bbd-a1fa-969988885a9d.json b/gwserver/_results/workflow_06e7d9e9-3b52-4bbd-a1fa-969988885a9d.json new file mode 100644 index 00000000..31ca7378 --- /dev/null +++ b/gwserver/_results/workflow_06e7d9e9-3b52-4bbd-a1fa-969988885a9d.json @@ -0,0 +1,204 @@ +{ + "id": "06e7d9e9-3b52-4bbd-a1fa-969988885a9d", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 6.4.2025, 12:07:08", + "status": "waiting_for_user", + "started_at": "2025-04-06T12:07:09.255509", + "last_activity": "2025-04-06T12:09:21.728903", + "prompt": "mache eine web suche, wer bei ValueOn AG arbeitet", + "messages": [ + { + "id": "msg_717efc7a-abce-4343-9a80-0c467f52f08d", + "workflow_id": "06e7d9e9-3b52-4bbd-a1fa-969988885a9d", + "parent_message_id": null, + "started_at": "2025-04-06T12:07:09.275061", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "mache eine web suche, wer bei ValueOn AG arbeitet", + "agent_type": null + }, + { + "id": "msg_50ce7282-fe6c-44fb-b7d8-5db36ad2db72", + "workflow_id": "06e7d9e9-3b52-4bbd-a1fa-969988885a9d", + "parent_message_id": null, + "started_at": "2025-04-06T12:08:22.953510", + "finished_at": "2025-04-06T12:08:22.967977", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "Die ValueOn AG ist ein in Uster, Zürich, ansässiges Unternehmen, das sich auf strategische Beratung und Projektmanagement, insbesondere in den Bereichen digitale Transformation und IT, spezialisiert hat. Mit einem kleinen Team von 2 bis 10 Mitarbeitern, darunter Richard Salvisberg, Marc Hamburger, Andreas Friedli und Andreas Stuker, bietet das Unternehmen Dienstleistungen zur Verbesserung der Projekt-Performance und zur Identifizierung von Risiken und Chancen. Kürzlich hat ValueOn AG neue Mitarbeiter wie Romano Caviezel und Alain Kappeler eingestellt, um ihre Expertise in den Bereichen KMU, Sport, Events und Kultur zu erweitern. Das Unternehmen ist seit über 15 Jahren tätig und nutzt Plattformen wie LinkedIn, um regelmäßig Updates zu veröffentlichen und sich als strategischer Partner für Kunden zu positionieren. ValueOn AG sucht aktiv nach neuen Talenten, um ihr Team weiter zu verstärken, und bietet ein dynamisches Arbeitsumfeld mit flexiblen Arbeitsmöglichkeiten. Die Informationen stammen von LinkedIn und der Unternehmenswebseite, die als zuverlässige Quellen für Unternehmensinformationen gelten.\n\n\n\n[1] ValueOn AG - LinkedIn\nURL: https://www.linkedin.com/company/valueon\nSnippet: ValueOn AG | 900 followers on LinkedIn. Ihr Strategie-, Sparrings- und Projektpartner für digitale Transformationen und businesskritische IT-/Digitalthemen. | Seit über 15 Jahren unterstützen ...\nContent: Die ValueOn AG ist ein Unternehmen, das sich auf strategische Beratung und Projektmanagement spezialisiert hat, insbesondere in den Bereichen digitale Transformation und IT. Das Unternehmen hat seinen Sitz in Uster, Zürich, und beschäftigt zwischen 2 und 10 Mitarbeiter. Zu den aktuellen Mitarbeitern gehören Richard Salvisberg, Marc Hamburger, Andreas Friedli und Andreas Stuker. Richard Salvisberg und Marc Hamburger sind auf LinkedIn als Mitarbeiter gelistet, während Andreas Friedli und Andreas Stuker spezifische Rollen und Fachkenntnisse in Führungs- und Beratungspositionen haben. \n\nValueOn AG hat kürzlich Romano Caviezel als neuen Mitarbeiter gewonnen, der als CIO/CFO und Experte für KMU, Sport, Events und Kultur bekannt ist. Alain Kappeler, ein weiterer Neuzugang, bringt Erfahrung in den Bereichen Sport, Events, Sponsoring und Tourismus mit. \n\nDas Unternehmen ist seit über 15 Jahren tätig und unterstützt nationale und internationale Unternehmen bei der Verbesserung ihrer Projekt-Performance und der Identifizierung von Risiken und Chancen. ValueOn AG bietet Dienstleistungen an, die auf höchste Ansprüche ausgerichtet sind und den Kunden signifikante Wettbewerbsvorteile verschaffen. \n\nDie LinkedIn-Seite von ValueOn AG zeigt, dass das Unternehmen 900 Follower hat und regelmäßig Updates zu seinen Aktivitäten und neuen Mitarbeitern veröffentlicht. Die Firma ist als öffentlicher Betrieb klassifiziert und wurde im Jahr 2000 gegründet. \n\nDiese Informationen stammen von der LinkedIn-Seite von ValueOn AG, die als zuverlässige Quelle für Unternehmensinformationen gilt.\n\n[2] Team | Beratung durch ValueOn AG\nURL: https://www.valueon.ch/team\nSnippet: Übersicht über das Team mit welchem ValueOn erfolgreiche IT Beratung in der ganzen Schweiz umsetzt. Von Digitalisierung bis IT-Strategien. Gespräch vereinbaren Gespräch vereinbaren. ... ValueOn AG. Uster West 44 8610 Uster (bei Zürich) Telefon: +41 44 943 70 40. E-Mail: office@valueon.ch. Datenschutz;\nContent: Die Webseite der ValueOn AG bietet einen Überblick über das Team, das in der IT-Beratung tätig ist. Die ValueOn AG ist spezialisiert auf digitale Transformationen und IT-Strategien in der Schweiz. Das Team besteht aus verschiedenen Experten, die in unterschiedlichen Bereichen tätig sind. Zu den Kernmitgliedern gehören Andreas Friedli, Dominic Largo, Patrick Motsch, Gregor Burri, Richard Salvisberg, Stephan Schellworth und weitere. Diese Mitglieder sind in der Regel in leitenden Positionen oder als Partner tätig.\n\nZusätzlich zu den internen Mitarbeitern arbeitet ValueOn AG auch mit externen zertifizierten Partnern zusammen, darunter Philipp Dick, Romano Caviezel, Dawid Puzik, Holger Ridinger und andere. Diese Partner bringen zusätzliche Expertise und Unterstützung in Projekten ein.\n\nDie Webseite hebt hervor, dass das Team agil, zielorientiert und flexibel arbeitet, um die bestmöglichen Lösungen für ihre Kunden zu liefern. Die Mitarbeiter sind darauf spezialisiert, nahtlos in Projekte einzusteigen und bei Bedarf die Projektführung zu übernehmen. Die ValueOn AG legt Wert auf eine enge Zusammenarbeit mit ihren Kunden, um nachhaltige Erfolge zu erzielen.\n\nDarüber hinaus sucht das Unternehmen aktiv nach neuen Talenten, wie Business Architects und Project Manager Professionals, um das Team weiter zu verstärken. Die Webseite bietet auch die Möglichkeit, sich über offene Stellen zu informieren und sich zu bewerben.\n\nInsgesamt vermittelt die Webseite ein Bild eines dynamischen und kompetenten Teams, das sich auf die erfolgreiche Umsetzung von IT- und Digitalprojekten spezialisiert hat.\n\n[3] Dominic Largo - ValueOn AG | LinkedIn - LinkedIn Schweiz\nURL: https://ch.linkedin.com/in/dominic-largo\nSnippet: Wer wagt, gewinnt - Experimentiere! · Berufserfahrung: ValueOn AG · Ausbildung: IMD · Ort: Uster · 500+ Kontakte auf LinkedIn. Sehen Sie sich das Profil von Dominic Largo Dominic Largo auf LinkedIn, einer professionellen Community mit mehr als 1 Milliarde Mitgliedern, an.\nContent: Die Websuche ergab, dass Dominic Largo bei der ValueOn AG tätig ist. Er ist auf LinkedIn mit einem Profil vertreten, das seine berufliche Erfahrung und seine Ausbildung beschreibt. Dominic Largo hat über 500 Kontakte und ist in Uster, Zürich, Schweiz ansässig. Er hat eine Ausbildung am IMD absolviert. Sein LinkedIn-Profil zeigt, dass er in verschiedenen Organisationen tätig war, darunter ValueOn AG, und dass er in der Unternehmensberatung und im Informationsmanagement tätig ist. Weitere Details zu seiner genauen Position bei ValueOn AG sind jedoch nicht direkt ersichtlich. \n\nDie Informationen stammen von LinkedIn, einer vertrauenswürdigen Plattform für berufliche Netzwerke, die als zuverlässige Quelle für berufliche Profile und Netzwerke gilt. Diese Plattform bietet Einblicke in die beruflichen Verbindungen und die Karriereentwicklung von Fachleuten weltweit. \n\nDie Suche nach weiteren Mitarbeitern der ValueOn AG war jedoch nicht erfolgreich, da die Informationen auf das Profil von Dominic Largo beschränkt waren. Um detailliertere Informationen über andere Mitarbeiter der ValueOn AG zu erhalten, könnte eine direkte Anfrage an das Unternehmen oder eine erweiterte Suche auf beruflichen Netzwerken erforderlich sein.\n\n[4] Offene Stellen | ValueOn AG\nURL: https://www.valueon.ch/offene-stellen\nSnippet: Beschreibung der offenen Stellen bei ValueOn, für: Management Consultant, Projekt Manager, Projekt Leiter, Senior, Schweiz, Zürich. ... Project Competence hat aus unserer Sicht einen fantastischen Job gemacht. Von der ersten Minute war spürbar, über welch grosse Kompetenz und Erfahrung die Experten verfügen. ... ValueOn AG. Uster West 44 ...\nContent: Die Webseite von ValueOn AG bietet keine spezifischen Informationen über aktuelle Mitarbeiter, ihre Positionen oder Abteilungen. Stattdessen konzentriert sich der Inhalt auf offene Stellen und die Unternehmensphilosophie. ValueOn AG sucht kontinuierlich nach erfahrenen Persönlichkeiten und Teamplayern, die sich mit Kompetenz und Leidenschaft einbringen möchten. Aktuell ausgeschriebene Positionen umfassen unter anderem einen Digital Transformation Consultant und einen Business-Architekten.\n\nDas Unternehmen beschreibt sich als ein Team von Experten mit langjähriger Erfahrung in der digitalen Transformation und großen IT- und Digitalprojekten. ValueOn AG sieht sich als strategischer Partner für Kunden, der zwischen Strategie, Business und Technologie vermittelt, um langfristigen Mehrwert zu schaffen.\n\nDie Webseite enthält auch Informationen über die Unternehmenswerte und die Vision, die darauf abzielt, als Drehscheibe zwischen verschiedenen Geschäftsbereichen zu fungieren. Zudem wird die Möglichkeit geboten, mehr über das Unternehmen und das Team zu erfahren, sowie sich über aktuelle Nachrichten und Blogbeiträge zu informieren.\n\nFür detaillierte Informationen über die Mitarbeiter von ValueOn AG wäre es ratsam, direkt mit dem Unternehmen Kontakt aufzunehmen oder auf Plattformen wie LinkedIn nach spezifischen Mitarbeiterprofilen zu suchen.\n\n[5] ValueOn AG - LinkedIn\nURL: https://www.linkedin.com/company/valueon\nSnippet: ValueOn AG | 900 followers on LinkedIn. Ihr Strategie-, Sparrings- und Projektpartner für digitale Transformationen und businesskritische IT-/Digitalthemen. | Seit über 15 Jahren unterstützen ...\nContent: Die ValueOn AG ist ein Unternehmen, das sich auf Business Consulting und Services spezialisiert hat, insbesondere in den Bereichen Projektmanagement und Projektportfolio-Management. Das Unternehmen hat seinen Sitz in Uster, Zürich, und beschäftigt zwischen 2 und 10 Mitarbeiter. Zu den aktuellen Mitarbeitern gehören Richard Salvisberg, Marc Hamburger, Andreas Friedli und Andreas Stuker. Diese Personen sind auf LinkedIn mit ihren Profilen vertreten, was auf ihre aktive Rolle im Unternehmen hinweist.\n\nValueOn AG ist bekannt für ihre Expertise in der digitalen Transformation und IT-bezogenen Themen. Sie bieten Dienstleistungen an, die darauf abzielen, die Projekt-Performance ihrer Kunden zu verbessern und Risiken frühzeitig zu erkennen. Das Unternehmen hat sich in den letzten 15 Jahren einen Namen gemacht, indem es sowohl national als auch international tätige Unternehmen unterstützt.\n\nIn den letzten Monaten hat ValueOn AG mehrere neue Mitarbeiter eingestellt, darunter Romano Caviezel, einen CIO/CFO-Spezialisten, und Alain Kappeler, einen Branchenprofi in den Bereichen Sport und Events. Diese Neuzugänge sollen das bestehende Team mit ihrer Erfahrung und ihrem Netzwerk verstärken.\n\nDas Unternehmen ist auch in den sozialen Medien aktiv, insbesondere auf LinkedIn, wo es regelmäßig Updates und Beiträge zu Themen wie Digitalisierung und Projektmanagement veröffentlicht. Diese Aktivitäten unterstreichen ihr Engagement, in der Branche sichtbar zu bleiben und ihre Expertise zu teilen.\n\nZusammenfassend lässt sich sagen, dass die ValueOn AG ein kleines, aber spezialisiertes Unternehmen ist, das sich durch seine Fokussierung auf digitale Transformation und IT-Projekte auszeichnet. Die Mitarbeiter sind erfahrene Fachleute, die das Unternehmen durch ihre Expertise und Netzwerke stärken.\n\n[6] Business Architect | ValueOn AG - Stellenangebot auf jobs.ch\nURL: https://www.jobs.ch/de/stellenangebote/detail/d0a4a5d6-e8cf-4d75-b23c-8dc3a78e6539/\nSnippet: ValueOn AG ist ein Expertenunternehmen mit Sitz in Uster und spezialisiert auf das Beraten und Führen von digitalen Business-Transformationen sowie businesskritischen IT- und Digitalprojekten. Zur Erweiterung unseres Experten-Teams suchen wir eine erfahrene, leistungsbereite und junge/junggebliebene Persönlichkeit (m/w), idealerweise zwischen ...\nContent: Die ValueOn AG ist ein Unternehmen, das sich auf digitale Transformation spezialisiert hat und seinen Sitz in Uster hat. Aktuell sucht das Unternehmen nach einem Business-Architekten (m/w) zur Verstärkung seines Expertenteams. Die Position erfordert eine Person, die als Bindeglied zwischen strategischer Führung und technischer Umsetzung fungiert. Zu den Hauptaufgaben gehören die Übersetzung strategischer Ziele in umsetzbare Aufgaben, die Sicherstellung der Kommunikation zwischen Projektbeteiligten und die Pflege umfassender Dokumentationen.\n\nFür die Position wird ein Bachelor-Abschluss in Betriebswirtschaft, Informatik oder einem verwandten Bereich vorausgesetzt. Ein fortgeschrittener Abschluss oder eine Zertifizierung in Business Architecture oder Projektmanagement ist von Vorteil. Die Rolle erfordert zudem hervorragende Kommunikationsfähigkeiten, starke analytische und problemlösende Fähigkeiten sowie Erfahrung in einer ähnlichen Position.\n\nDas Arbeitsumfeld bei ValueOn AG bietet vielfältige Aufgaben mit hoher Eigenverantwortung, ein kollegiales Umfeld, umfangreiche Aus- und Weiterbildungsmöglichkeiten sowie Flexibilität hinsichtlich des Arbeitsortes, sei es beim Kunden, im Homeoffice oder am Hauptsitz in Uster.\n\nDiese Informationen stammen aus einer Stellenanzeige auf jobs.ch, die die Position des Business-Architekten bei der ValueOn AG beschreibt. Die Anzeige hebt die Anforderungen und die Arbeitsumgebung hervor, die potenziellen Bewerbern geboten werden.", + "agent_type": "scraper", + "agent_id": "webcrawler_agent", + "agent_name": "Webscraper" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n### Zusammenfassung der Agentenergebnisse zur ValueOn AG\n\n#### Unternehmensprofil\n- **Name:** ValueOn AG\n- **Standort:** Uster, Zürich, Schweiz\n- **Gründung:** 2000\n- **Mitarbeiterzahl:** 2 bis 10\n- **Spezialisierung:** Strategische Beratung und Projektmanagement mit Fokus auf digitale Transformation und IT\n- **Zielgruppe:** Nationale und internationale Unternehmen\n\n#### Team und Personal\n- **Kernmitglieder:** Richard Salvisberg, Marc Hamburger, Andreas Friedli, Andreas Stuker\n- **Neueinstellungen:** Romano Caviezel (CIO/CFO, Experte für KMU, Sport, Events, Kultur), Alain Kappeler (Erfahrung in Sport, Events, Sponsoring, Tourismus)\n- **Externe Partner:** Philipp Dick, Dawid Puzik, Holger Ridinger\n- **Aktive Rekrutierung:** Suche nach Business Architects und Project Manager Professionals\n\n#### Dienstleistungen und Expertise\n- **Fokus:** Verbesserung der Projekt-Performance, Identifizierung von Risiken und Chancen\n- **Dienstleistungsangebot:** Strategische Beratung, Projektmanagement, IT-Strategien\n- **Arbeitsweise:** Agil, zielorientiert, flexibel; enge Zusammenarbeit mit Kunden\n\n#### Unternehmenswerte und Vision\n- **Philosophie:** Vermittlung zwischen Strategie, Business und Technologie\n- **Ziel:** Langfristiger Mehrwert für Kunden durch nachhaltige Lösungen\n\n#### Rekrutierung und Arbeitsumfeld\n- **Offene Stellen:** Digital Transformation Consultant, Business-Architekt\n- **Anforderungen:** Bachelor-Abschluss in Betriebswirtschaft oder Informatik, fortgeschrittener Abschluss oder Zertifizierung von Vorteil\n- **Arbeitsumgebung:** Hohe Eigenverantwortung, kollegiales Umfeld, flexible Arbeitsmöglichkeiten (Homeoffice, Kundenstandort, Hauptsitz)\n\n#### Kommunikation und Sichtbarkeit\n- **Aktivitäten:** Regelmäßige Updates und Beiträge auf LinkedIn\n- **Follower auf LinkedIn:** 900\n- **Ziel:** Sichtbarkeit in der Branche erhöhen und Expertise teilen\n\n#### Empfehlungen\n- **Weiterer Ausbau des Teams:** Fortsetzung der aktiven Rekrutierung von Fachkräften zur Stärkung der Expertise\n- **Erhöhung der Sichtbarkeit:** Intensivierung der Social-Media-Aktivitäten zur Steigerung der Markenbekanntheit\n- **Kundenbindung:** Fortsetzung der engen Zusammenarbeit mit Kunden zur Sicherstellung nachhaltiger Projekterfolge\n\nDiese strukturierte Zusammenfassung bietet einen umfassenden Überblick über die ValueOn AG, ihre Mitarbeiter, Dienstleistungen und strategischen Ziele.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true, + "finished_at": "2025-04-06T12:09:20.035436", + "status": "completed" + }, + { + "id": "msg_9064a7a5-04df-43ea-bdb2-61803372834c", + "workflow_id": "06e7d9e9-3b52-4bbd-a1fa-969988885a9d", + "parent_message_id": null, + "started_at": "2025-04-06T12:09:20.035436", + "finished_at": null, + "sequence_no": 4, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "kannst du mir die mitarbeiterliste als tabelle zusammenstellen, wer mit welcher rolle?", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Bitte stelle eine Tabelle zusammen, die die Mitarbeiterliste mit den jeweiligen Rollen enthält. Da keine Dateien zur Verfügung stehen, nutze dein Wissen oder frage nach weiteren Informationen, falls nötig.", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_9cb2a019-c0a7-4581-b378-5627a69f20aa", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 49, 0 Dateien", + "type": "info", + "timestamp": "2025-04-06T12:07:09.260511", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_a4f26ee6-6489-4fa7-a912-edeeb69270be", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-06T12:07:09.267092", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_985a5621-bf1e-413b-a627-678ed327b961", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-06T12:07:10.707956", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_876ed629-b1a0-4212-82bf-7523c3252867", + "message": "Agent webcrawler_agent wurde ausgewählt mit Aufgabe: Führe eine Websuche durch, um herauszufinden, wer ...", + "type": "info", + "timestamp": "2025-04-06T12:07:10.717672", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_0f51132e-6e69-40e7-8e6b-918cefd270a9", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:07:10.725629", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_4961b337-43cd-4c47-bd80-65851bf23051", + "message": "Agent webcrawler_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:07:10.730672", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_21d10aca-446e-426b-a7bc-58c1c4dff469", + "message": "Agent 'webcrawler_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:07:10.740524", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_da43691d-f925-4b81-8862-e06f5cca64b6", + "message": "Agent 'webcrawler_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-06T12:08:23.063716", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_2c7dd37d-2a1d-41c0-9b88-4cace72df6b2", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-06T12:08:30.808819", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_cc2aacfd-05b5-40eb-839b-594ec660ab57", + "message": "Benutzereingabe empfangen: 86 Zeichen, 0 Dateien", + "type": "info", + "timestamp": "2025-04-06T12:09:20.016794", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ada0b6fb-3860-4b8f-80d9-9dc4fd79ad1a", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-06T12:09:20.024392", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_841bf215-b56d-4bbb-a7ed-12b234558160", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-06T12:09:21.711467", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_8be888ea-7eec-45bc-8021-7abe437f8f79", + "message": "Agent user_agent wurde ausgewählt mit Aufgabe: Bitte stelle eine Tabelle zusammen, die die Mitarb...", + "type": "info", + "timestamp": "2025-04-06T12:09:21.711467", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_517ef9ef-fe34-4d67-90c6-efe07a62bc82", + "message": "Workflow wartet auf Benutzereingabe: Bitte stelle eine Tabelle zusammen, die die Mitarb...", + "type": "info", + "timestamp": "2025-04-06T12:09:21.728903", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_086fc9bf-1cd6-47a8-b0d7-e09dd4d14939.json b/gwserver/_results/workflow_086fc9bf-1cd6-47a8-b0d7-e09dd4d14939.json new file mode 100644 index 00000000..eb78e083 --- /dev/null +++ b/gwserver/_results/workflow_086fc9bf-1cd6-47a8-b0d7-e09dd4d14939.json @@ -0,0 +1,45 @@ +{ + "id": "086fc9bf-1cd6-47a8-b0d7-e09dd4d14939", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 12:07:09", + "status": "failed", + "started_at": "2025-04-04T12:07:10.087470", + "last_activity": "2025-04-04T12:07:10.104633", + "prompt": "describe", + "messages": [], + "logs": [ + { + "id": "log_dd9168d5-d49a-4685-9701-0d7aa8fb5d7a", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 8, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T12:07:10.090232", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_7d0d4e4a-0559-42b2-954f-fb8172da940b", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T12:07:10.093747", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_1902516b-2e54-4d36-9466-6304ef99ec44", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T12:07:10.099321", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_7371b9a4-ddeb-458f-b95a-74aca13de52a", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T12:07:10.104633", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_0d6c6ccf-dfcd-4431-88ff-354594f1280e.json b/gwserver/_results/workflow_0d6c6ccf-dfcd-4431-88ff-354594f1280e.json new file mode 100644 index 00000000..6494fdf3 --- /dev/null +++ b/gwserver/_results/workflow_0d6c6ccf-dfcd-4431-88ff-354594f1280e.json @@ -0,0 +1,82 @@ +{ + "id": "0d6c6ccf-dfcd-4431-88ff-354594f1280e", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 01:07:16", + "status": "stopped", + "started_at": "2025-04-04T01:07:17.579677", + "last_activity": "2025-04-04T01:07:27.469867", + "prompt": "was ist auf dem angehängten bild?", + "messages": [ + { + "id": "msg_c3d8068d-e208-4fd0-b11d-cf6ad4bf4677", + "workflow_id": "0d6c6ccf-dfcd-4431-88ff-354594f1280e", + "parent_message_id": null, + "started_at": "2025-04-04T01:07:17.590067", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "was ist auf dem angehängten bild?", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben keine spezifischen Aufgaben durchgeführt. Gibt es etwas, wobei ich Ihnen helfen kann?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_687f6922-17cc-40a8-95d4-36117ee04bdc", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 33, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T01:07:17.582688", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_f6b032bb-e042-4a56-8be7-7b3534b54cc8", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T01:07:17.587648", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_0f25e813-d5c7-4c4e-b264-784458f50544", + "message": "Agenten-Entscheidung abgeschlossen: 0 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T01:07:18.450685", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_f4312c26-595b-40df-976c-f57d881ae625", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben keine spezifischen Aufgaben durc...", + "type": "info", + "timestamp": "2025-04-04T01:07:18.454547", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_7f4af80b-9352-4422-9e03-78a3aec8a5ee", + "message": "Workflow wurde manuell gestoppt", + "type": "info", + "timestamp": "2025-04-04T01:07:27.469867", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_136db092-07d8-4856-9dca-932e1cf39b8a.json b/gwserver/_results/workflow_136db092-07d8-4856-9dca-932e1cf39b8a.json new file mode 100644 index 00000000..6ead7454 --- /dev/null +++ b/gwserver/_results/workflow_136db092-07d8-4856-9dca-932e1cf39b8a.json @@ -0,0 +1,74 @@ +{ + "id": "136db092-07d8-4856-9dca-932e1cf39b8a", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 23:00:32", + "status": "waiting_for_user", + "started_at": "2025-04-04T23:00:33.043918", + "last_activity": "2025-04-04T23:00:34.287183", + "prompt": "this looks now very good", + "messages": [ + { + "id": "msg_54b664c3-accc-490f-b448-4b6865953f72", + "workflow_id": "136db092-07d8-4856-9dca-932e1cf39b8a", + "parent_message_id": null, + "started_at": "2025-04-04T23:00:33.059453", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "this looks now very good", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben keine spezifischen Aufgaben durchgeführt. Gibt es etwas, wobei ich Ihnen helfen kann?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_f8be98a2-6649-4e3d-8a14-dd553f786fc6", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 24, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T23:00:33.049601", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_e8264c1a-566f-4efa-9317-cca6b6255156", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T23:00:33.054609", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_7dfd2b2a-c30f-444c-b534-43c02f5e51f0", + "message": "Agenten-Entscheidung abgeschlossen: 0 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T23:00:34.278730", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_d115a961-63c6-4e28-b000-40bfabc3fe65", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben keine spezifischen Aufgaben durc...", + "type": "info", + "timestamp": "2025-04-04T23:00:34.287183", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_1a247d76-6ca5-4c96-b445-643d17206708.json b/gwserver/_results/workflow_1a247d76-6ca5-4c96-b445-643d17206708.json new file mode 100644 index 00000000..738c9f87 --- /dev/null +++ b/gwserver/_results/workflow_1a247d76-6ca5-4c96-b445-643d17206708.json @@ -0,0 +1,89 @@ +{ + "id": "1a247d76-6ca5-4c96-b445-643d17206708", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 6.4.2025, 23:47:23", + "status": "completed", + "started_at": "2025-04-06T23:47:23.769077", + "last_activity": "2025-04-06T23:47:24.861906", + "prompt": "kannst du mir das resultat in 3 sätzen zusammenfassen auf englisch?", + "messages": [ + { + "id": "msg_b0e56f39-cc1f-46b9-877f-aa09d4c97291", + "workflow_id": "1a247d76-6ca5-4c96-b445-643d17206708", + "parent_message_id": null, + "started_at": "2025-04-06T23:47:23.801245", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "kannst du mir das resultat in 3 sätzen zusammenfassen auf englisch?", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Please summarize the result in 3 sentences in English.", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "workflow_complete": true + } + ], + "logs": [ + { + "id": "log_7d66d006-d1ee-4d33-8d0b-4911c9a1d3e4", + "message": "Neuer Benutzereingabe erhalten - Vorherigen Workflow beenden", + "type": "info", + "timestamp": "2025-04-06T23:47:23.773042", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_96cacea3-1a39-437f-8747-5198a71757ae", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 67, 0 Dateien", + "type": "info", + "timestamp": "2025-04-06T23:47:23.782040", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c756fea5-2954-415a-92d1-288be6bca0ec", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-06T23:47:23.791036", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_350f9c63-e905-42d1-9391-925efd88b210", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-06T23:47:24.839485", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_9745840d-8722-4209-8089-34d47605e7c2", + "message": "Agent user_agent wurde ausgewählt mit Aufgabe: Please summarize the result in 3 sentences in Engl...", + "type": "info", + "timestamp": "2025-04-06T23:47:24.853648", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_8737a1f4-db39-4b3f-9a6c-2972923bfa5b", + "message": "Workflow wartet auf Benutzereingabe: Please summarize the result in 3 sentences in Engl...", + "type": "info", + "timestamp": "2025-04-06T23:47:24.861906", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_1f694371-65fe-45da-8040-defa53271bd1.json b/gwserver/_results/workflow_1f694371-65fe-45da-8040-defa53271bd1.json new file mode 100644 index 00000000..4059a509 --- /dev/null +++ b/gwserver/_results/workflow_1f694371-65fe-45da-8040-defa53271bd1.json @@ -0,0 +1,177 @@ +{ + "id": "1f694371-65fe-45da-8040-defa53271bd1", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 22:09:30", + "status": "waiting_for_user", + "started_at": "2025-04-04T22:09:31.285420", + "last_activity": "2025-04-04T22:10:03.502904", + "prompt": "analyse image", + "messages": [ + { + "id": "msg_86648d24-3ac6-4105-9fdd-c6e9ae7da686", + "workflow_id": "1f694371-65fe-45da-8040-defa53271bd1", + "parent_message_id": null, + "started_at": "2025-04-04T22:09:31.301781", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [ + { + "id": 4, + "source": { + "type": "file", + "id": 4, + "name": "LF-Details.png", + "content_type": "image/png", + "size": 253009, + "upload_date": "2025-04-04T22:09:58.458854" + }, + "contents": [ + { + "type": "text", + "text": "Image Analysis:\nThe image is a flowchart illustrating a product development process involving multiple teams: Product Team, Engineering Team, Q&A Team, and Operations. Here's a detailed breakdown:\n\n### Input\n- **Sources**: Customers, Sales, and Internal Ideas.\n- **Process**: Inputs are collected and qualified based on business priorities.\n\n### Product Team\n1. **Discover**\n - **Collect**: Ideas and inputs.\n - **Qualify**: Analyze and match against business priorities.\n\n2. **Define**\n - **Structure & Document**: Write specifications and define acceptance criteria.\n - **Explore & Design**: UI design and experiments, with references to tickets in ClickUp.\n\n3. **Shape**\n - **Roadmap**: Define roadmap to meet opportunities and protect development stability.\n - **Scoping**: Define next version's scope.\n - **Manage**: Tickets in the product.\n\n### Engineering Team\n- **Assess**\n - **Manage**: Move assessed tickets to future versions.\n - **Estimate**: Assess tickets for implementation, feasibility, and effort.\n\n- **Build**\n - **Manage**: Track progress in the dashboard.\n - **Factory**: Develop tickets for the next version.\n\n### Q&A Team\n- **Validate**\n - **Testing**: Test functionality against acceptance.\n - **Analysis**: Analyze tickets, events, deviations.\n\n### Operations\n1. **Release**\n - **Manage**: Ensure stable changes.\n\n2. **Run & Monitor**\n - **Manage**: Ensure stable operation.\n - **Service & Support**: Deliver first-level support according to agreed SLA.\n\n### Output\n- **Product**: The final output of the process.\n\n### Tool Integration\n- **Ticketing System**: Visual representation of ticket management.\n- **Roadmap**: Timeline for product development.\n- **Management Dashboards**: Visual data and metrics for tracking progress.\n\nThe flowchart uses arrows to indicate the flow of tasks and responsibilities between different stages and teams, emphasizing collaboration and integration across the product development lifecycle." + } + ] + } + ], + "content": "analyse image", + "agent_type": null + }, + { + "id": "msg_3b6a8c50-ab8c-4a3c-8f9c-c15e8b53d100", + "workflow_id": "1f694371-65fe-45da-8040-defa53271bd1", + "parent_message_id": null, + "started_at": "2025-04-04T22:10:00.409307", + "finished_at": "2025-04-04T22:10:00.412299", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "Ich habe als Datenanalyst eine Analyse der bereitgestellten Daten durchgeführt.\n\nHier ist meine detaillierte Analyse:\n1. Die Daten zeigen einen klaren Trend...\n2. Es gibt signifikante Korrelationen zwischen...\n3. Besonders auffällig ist...\n\nMeine Empfehlungen basierend auf der Analyse:\n- Maßnahme 1: ...\n- Maßnahme 2: ...\n- Maßnahme 3: ...", + "agent_type": "analyzer", + "agent_id": "analyst_agent", + "agent_name": "Datenanalyst" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n**Zusammenfassung der Agentenergebnisse**\n\n**Analyseergebnisse:**\n1. **Trendidentifikation:** Die Daten weisen einen klaren Trend auf, der auf bestimmte Muster oder Entwicklungen hinweist.\n2. **Korrelationen:** Es wurden signifikante Korrelationen zwischen verschiedenen Datensätzen festgestellt, die auf mögliche Zusammenhänge oder Einflussfaktoren hindeuten.\n3. **Besondere Auffälligkeiten:** Bestimmte Aspekte der Daten sind besonders auffällig und könnten auf Anomalien oder besondere Ereignisse hinweisen.\n\n**Empfehlungen:**\n- **Maßnahme 1:** [Beschreibung der ersten empfohlenen Maßnahme basierend auf der Analyse]\n- **Maßnahme 2:** [Beschreibung der zweiten empfohlenen Maßnahme basierend auf der Analyse]\n- **Maßnahme 3:** [Beschreibung der dritten empfohlenen Maßnahme basierend auf der Analyse]\n\nDiese Empfehlungen sollen dazu beitragen, die identifizierten Trends und Korrelationen optimal zu nutzen und auf die auffälligen Datenpunkte angemessen zu reagieren.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_e1b2daa6-3fe2-4dbf-958f-26837fc6f58d", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 13, 2 Dateien", + "type": "info", + "timestamp": "2025-04-04T22:09:31.293163", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_dfed05f6-9063-4f21-a05e-bd81fb62d887", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T22:09:31.297171", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_17b3b7a6-2823-449c-b673-333cfe216133", + "message": "2 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T22:09:31.306757", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_98e96b5d-65d2-474d-a6a0-72bed023189d", + "message": "Image LF-Details.png analyzed successfully", + "type": "info", + "timestamp": "2025-04-04T22:09:47.949478", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c81d83a5-c038-45a8-852b-a6e3e0948dae", + "message": "Image LF-Details.png analyzed successfully", + "type": "info", + "timestamp": "2025-04-04T22:09:58.439793", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_9d1ac4fb-601a-4cbc-bc48-d463a4592c27", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T22:10:00.385657", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_f52afec1-ea56-4d81-b50e-f398a9c2c2dd", + "message": "Agent analyst_agent wurde ausgewählt mit Aufgabe: Analysiere das Bild 'LF-Details.png', das ein Flus...", + "type": "info", + "timestamp": "2025-04-04T22:10:00.389680", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_4b8d9c04-74e4-4185-bbea-22a648680c0a", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-04T22:10:00.394659", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_cc1201bc-2125-4644-a629-04846795520a", + "message": "Agent analyst_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T22:10:00.399663", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c36ecd18-7002-432d-ac45-e4bff80bafda", + "message": "Agent 'analyst_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T22:10:00.404321", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_a0b9c141-299a-497c-8db5-30581b7fa5a0", + "message": "Agent 'analyst_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-04T22:10:00.463569", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_74ab8610-fb68-4be1-afe2-ea87cdc8b172", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-04T22:10:03.502904", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_20357965-a22a-4379-bfdd-2538e03f59e6.json b/gwserver/_results/workflow_20357965-a22a-4379-bfdd-2538e03f59e6.json new file mode 100644 index 00000000..56d55e97 --- /dev/null +++ b/gwserver/_results/workflow_20357965-a22a-4379-bfdd-2538e03f59e6.json @@ -0,0 +1,74 @@ +{ + "id": "20357965-a22a-4379-bfdd-2538e03f59e6", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 09:59:09", + "status": "waiting_for_user", + "started_at": "2025-04-04T09:59:10.121840", + "last_activity": "2025-04-04T09:59:11.106806", + "prompt": "beschreibe das bild", + "messages": [ + { + "id": "msg_69fb0b41-927d-4774-b56d-e003d36565c4", + "workflow_id": "20357965-a22a-4379-bfdd-2538e03f59e6", + "parent_message_id": null, + "started_at": "2025-04-04T09:59:10.127843", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "beschreibe das bild", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben keine spezifischen Aufgaben durchgeführt. Gibt es etwas, wobei ich Ihnen helfen kann?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_0ebae430-1938-4b39-8741-084d7db81e54", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 19, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T09:59:10.123838", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_f16d83ae-66d0-440a-9b88-e36c0b22a644", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T09:59:10.125838", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_6bd8142c-e38c-4258-8b15-dc105fdf069e", + "message": "Agenten-Entscheidung abgeschlossen: 0 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T09:59:11.106806", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_7a2a2cd0-db15-482f-a435-6e9cacdca3e5", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben keine spezifischen Aufgaben durc...", + "type": "info", + "timestamp": "2025-04-04T09:59:11.106806", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_21dc4417-7c89-40bc-abe3-6482582e6b6b.json b/gwserver/_results/workflow_21dc4417-7c89-40bc-abe3-6482582e6b6b.json new file mode 100644 index 00000000..7a1dc187 --- /dev/null +++ b/gwserver/_results/workflow_21dc4417-7c89-40bc-abe3-6482582e6b6b.json @@ -0,0 +1,110 @@ +{ + "id": "21dc4417-7c89-40bc-abe3-6482582e6b6b", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 6.4.2025, 11:44:25", + "status": "ERGEBNIS", + "started_at": "2025-04-06T11:44:26.088390", + "last_activity": "2025-04-06T11:44:27.513466", + "prompt": "mach web suche, wer bei ValueOn AG arbeitet", + "messages": [ + { + "id": "msg_b96bac5b-c80d-48a6-bab1-ad391903c90e", + "workflow_id": "21dc4417-7c89-40bc-abe3-6482582e6b6b", + "parent_message_id": null, + "started_at": "2025-04-06T11:44:26.108182", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "mach web suche, wer bei ValueOn AG arbeitet", + "agent_type": null + }, + { + "id": "msg_6289297a-ea5d-4ed9-a621-c6df6e5b0bf1", + "workflow_id": "21dc4417-7c89-40bc-abe3-6482582e6b6b", + "parent_message_id": null, + "started_at": "2025-04-06T11:44:27.520673", + "finished_at": "2025-04-06T11:44:27.525719", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "", + "agent_type": "scraper", + "agent_id": "webcrawler_agent", + "agent_name": "Webscraper" + } + ], + "logs": [ + { + "id": "log_bf760c1f-d2ea-49f2-b55e-aeaf6b0bfbd1", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 43, 0 Dateien", + "type": "info", + "timestamp": "2025-04-06T11:44:26.092807", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b4cb48ec-3c21-4f05-a1ce-e03014c0b89b", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-06T11:44:26.100180", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_e937c28a-e1e3-42cd-bf73-25481fb7bf86", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-06T11:44:27.469153", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_95ea94a8-c236-45e9-9177-da4e77da347e", + "message": "Agent webcrawler_agent wurde ausgewählt mit Aufgabe: Führe eine Websuche durch, um herauszufinden, wer ...", + "type": "info", + "timestamp": "2025-04-06T11:44:27.492677", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_7de9621f-67cd-43c1-a0ab-cd625d747a3d", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-06T11:44:27.499162", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_13f49eef-2269-4dd5-b356-7e6859648d18", + "message": "Agent webcrawler_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T11:44:27.506843", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_e6038382-1a88-4cc1-a7ae-75d03a0cce71", + "message": "Agent 'webcrawler_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T11:44:27.513466", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_23afec57-9ff5-4305-b114-a8357536de86.json b/gwserver/_results/workflow_23afec57-9ff5-4305-b114-a8357536de86.json new file mode 100644 index 00000000..c8b6f9d3 --- /dev/null +++ b/gwserver/_results/workflow_23afec57-9ff5-4305-b114-a8357536de86.json @@ -0,0 +1,29 @@ +{ + "id": "23afec57-9ff5-4305-b114-a8357536de86", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 6.4.2025, 23:26:55", + "status": "stopped", + "started_at": "2025-04-06T23:26:56.125731", + "last_activity": "2025-04-06T23:27:24.411648", + "prompt": "kannst du mir eine websuche machen, wer KI-agentensysteme entwickelt?", + "messages": [], + "logs": [ + { + "id": "log_adbd1195-0a69-44af-b5b5-9eff003b4c32", + "message": "Workflow läuft noch, keine neue Eingabe möglich", + "type": "error", + "timestamp": "2025-04-06T23:26:56.144327", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_a84c4f43-5df5-432f-99e0-aea06812738f", + "message": "Workflow wurde manuell gestoppt", + "type": "info", + "timestamp": "2025-04-06T23:27:24.411648", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_2533e594-abfd-4acc-9886-a0db9228a55c.json b/gwserver/_results/workflow_2533e594-abfd-4acc-9886-a0db9228a55c.json new file mode 100644 index 00000000..e752b799 --- /dev/null +++ b/gwserver/_results/workflow_2533e594-abfd-4acc-9886-a0db9228a55c.json @@ -0,0 +1,74 @@ +{ + "id": "2533e594-abfd-4acc-9886-a0db9228a55c", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 08:47:43", + "status": "waiting_for_user", + "started_at": "2025-04-04T08:47:43.573723", + "last_activity": "2025-04-04T08:47:44.400926", + "prompt": "beschreibe das bild", + "messages": [ + { + "id": "msg_58702133-b368-4306-aa0c-3f304eac9233", + "workflow_id": "2533e594-abfd-4acc-9886-a0db9228a55c", + "parent_message_id": null, + "started_at": "2025-04-04T08:47:43.588689", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "beschreibe das bild", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben keine spezifischen Aufgaben durchgeführt. Gibt es etwas, wobei ich Ihnen helfen kann?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_eb4d61a5-057b-424e-bd09-ac8b383eec94", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 19, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T08:47:43.576705", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_9cc48b7b-3b23-4252-8ffe-3cfb906f6543", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T08:47:43.582696", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_53723fa3-f1cd-4602-90f1-727dfab74a00", + "message": "Agenten-Entscheidung abgeschlossen: 0 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T08:47:44.392546", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c910a612-0059-4896-87c1-60fbad6f7c5c", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben keine spezifischen Aufgaben durc...", + "type": "info", + "timestamp": "2025-04-04T08:47:44.400926", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_270481d2-a4f7-4e01-83ae-c7ea541fb38a.json b/gwserver/_results/workflow_270481d2-a4f7-4e01-83ae-c7ea541fb38a.json new file mode 100644 index 00000000..41e72cbd --- /dev/null +++ b/gwserver/_results/workflow_270481d2-a4f7-4e01-83ae-c7ea541fb38a.json @@ -0,0 +1,185 @@ +{ + "id": "270481d2-a4f7-4e01-83ae-c7ea541fb38a", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 19:43:03", + "status": "waiting_for_user", + "started_at": "2025-04-04T19:43:04.908849", + "last_activity": "2025-04-04T19:47:12.436966", + "prompt": "describe", + "messages": [ + { + "id": "msg_dba21daa-91ba-4acc-b87a-82bf3fbae3ed", + "workflow_id": "270481d2-a4f7-4e01-83ae-c7ea541fb38a", + "parent_message_id": null, + "started_at": "2025-04-04T19:43:04.921361", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [ + { + "id": 1, + "source": { + "type": "file", + "id": 1, + "name": "LF-Nutshell.png", + "content_type": "image/png", + "size": 52108, + "upload_date": "2025-04-04T19:43:12.553746" + }, + "contents": [ + { + "type": "text", + "text": "Image Analysis:\nThe image is a flowchart titled \"In a nutshell,\" illustrating a process from inputs to product delivery. Here's a detailed description:\n\n1. **Inputs**: \n - Represented by an inverted triangle at the top left, labeled \"Inputs.\"\n\n2. **Product Team**:\n - Below the inputs, there's a rectangular box labeled \"Product Team.\"\n - It includes the steps: \"Discover - Define - Shape.\"\n\n3. **Engineering Team**:\n - Next to the Product Team, there's a box labeled \"Engineering Team.\"\n - It includes the steps: \"Assess & Build.\"\n\n4. **Q&A Team**:\n - Adjacent to the Engineering Team, there's a box labeled \"Q&A Team.\"\n - It includes the step: \"Validate.\"\n\n5. **Operations**:\n - Next to the Q&A Team, there's a box labeled \"Operations.\"\n - It includes the steps: \"Release, Run & Monitor.\"\n\n6. **Roadmap**:\n - Above the Engineering Team, there's an arrow labeled \"Roadmap.\"\n\n7. **Product**:\n - Following the Roadmap, there are three consecutive boxes labeled \"Product.\"\n\nThe flowchart visually represents a process from initial inputs through various team responsibilities, leading to the final product delivery." + } + ] + } + ], + "content": "describe", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Bitte beschreibe das Bild 'LF-Nutshell.png' detailliert und erkläre den dargestellten Prozess im Flussdiagramm. Achte darauf, die einzelnen Schritte und deren Bedeutung zu erläutern.", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true, + "finished_at": "2025-04-04T19:47:10.762284", + "status": "completed" + }, + { + "id": "msg_a206635e-ce4b-4bcd-9095-bf3fed6e51ca", + "workflow_id": "270481d2-a4f7-4e01-83ae-c7ea541fb38a", + "parent_message_id": null, + "started_at": "2025-04-04T19:47:10.763300", + "finished_at": null, + "sequence_no": 3, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "please summarize", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Bitte fassen Sie die Informationen oder den Kontext zusammen, der in der Anfrage impliziert ist. Da keine spezifischen Dateien oder Inhalte bereitgestellt wurden, geben Sie eine allgemeine Zusammenfassung basierend auf den verfügbaren Informationen.", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_fe558963-6910-4a7c-bb71-147204d0f577", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 8, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T19:43:04.913361", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_cfff4b6c-cacf-44ba-950d-6b1bcccea2f8", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T19:43:04.917361", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_3b082794-b6c7-4328-8baa-5c24665986da", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T19:43:04.925763", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_298cdc5d-c73f-4e15-9b86-c96ae1418347", + "message": "Image LF-Nutshell.png analyzed successfully", + "type": "info", + "timestamp": "2025-04-04T19:43:12.532046", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_e3f54aaf-568f-4476-8c7e-34b20b54ab26", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T19:43:13.976919", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_8199586c-384e-4a09-9e3d-f2f8d88b0389", + "message": "Agent user_agent wurde ausgewählt mit Aufgabe: Bitte beschreibe das Bild 'LF-Nutshell.png' detail...", + "type": "info", + "timestamp": "2025-04-04T19:43:13.980923", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c94edd0d-698f-4b1b-8be2-76e06f62f1c9", + "message": "Workflow wartet auf Benutzereingabe: Bitte beschreibe das Bild 'LF-Nutshell.png' detail...", + "type": "info", + "timestamp": "2025-04-04T19:43:13.984927", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_047d3ca9-8534-4008-ac80-85987d3df1e9", + "message": "Benutzereingabe empfangen: 16 Zeichen, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T19:47:10.751981", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_d4f7292b-e229-47d0-b227-d5402ac31a23", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T19:47:10.757516", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_5206cbe9-f98b-493a-ba52-d76c5c999cb1", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T19:47:12.427711", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_8c4e6c8e-1461-4c36-b0fc-27fe54fb6393", + "message": "Agent user_agent wurde ausgewählt mit Aufgabe: Bitte fassen Sie die Informationen oder den Kontex...", + "type": "info", + "timestamp": "2025-04-04T19:47:12.432545", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_7f99c192-d5e4-4633-ada1-c4e802f4707a", + "message": "Workflow wartet auf Benutzereingabe: Bitte fassen Sie die Informationen oder den Kontex...", + "type": "info", + "timestamp": "2025-04-04T19:47:12.436966", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_298f2791-8f65-4bc3-8a56-d19344cf8535.json b/gwserver/_results/workflow_298f2791-8f65-4bc3-8a56-d19344cf8535.json new file mode 100644 index 00000000..ca575086 --- /dev/null +++ b/gwserver/_results/workflow_298f2791-8f65-4bc3-8a56-d19344cf8535.json @@ -0,0 +1,118 @@ +{ + "id": "298f2791-8f65-4bc3-8a56-d19344cf8535", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 6.4.2025, 23:48:41", + "status": "completed", + "started_at": "2025-04-06T23:48:41.648301", + "last_activity": "2025-04-06T23:52:09.346472", + "prompt": "bitte zusammenfassen", + "messages": [ + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n### Zusammenfassung der Agentenergebnisse\n\n#### Allgemeine Informationen und Themenübersicht\n\nDas Dokument \"Zusammenfassungserstellung: Allgemeine Informationen und Themenübersicht\" bietet einen umfassenden Leitfaden zur Erstellung prägnanter Zusammenfassungen. Es beschreibt die wichtigsten Schritte und Techniken zur effektiven Verdichtung von Informationen und zur klaren Darstellung der Kernaussagen eines Textes. Der Fokus liegt auf der Identifizierung zentraler Themen und deren präziser Zusammenfassung, um Lesern eine schnelle und umfassende Einsicht in den Inhalt eines Dokuments zu ermöglichen.\n\n#### Inhaltsstruktur\n\n1. **Einführung in die Zusammenfassungserstellung**: \n - Bedeutung und Zweck von Zusammenfassungen: Informationsverdichtung, Zeitersparnis, Klarheit, Unterstützung der Entscheidungsfindung.\n - Nutzen in verschiedenen Kontexten: Akademische Forschung, Geschäftswelt, Medizin, Medien.\n\n2. **Identifizierung zentraler Themen**:\n - Techniken zur Erkennung von Hauptthemen: Vorbereitung, aktives Lesen, Textstrukturanalyse.\n - Erstellung von Themenhierarchien und Verwendung grafischer Organisatoren.\n\n3. **Techniken zur Informationsverdichtung**:\n - Methoden: Extraktive und abstraktive Zusammenfassung.\n - Techniken: Verwendung von Schlüsselwörtern, Bullet Points, Diagrammen und Tabellen.\n\n4. **Strukturierung einer Zusammenfassung**:\n - Einleitung, Hauptteil und Schlussfolgerung.\n - Thematische Gliederung, Verwendung von Unterüberschriften, Aufzählungen.\n\n5. **Sprachliche Präzision und Klarheit**:\n - Bedeutung von Klarheit und Präzision: Verständlichkeit, Effizienz, Genauigkeit.\n - Strategien: Einfache Sprache, aktive Stimme, konzise Ausdrucksweise.\n\n6. **Praktische Übungen zur Zusammenfassungserstellung**:\n - Übungen für wissenschaftliche, literarische und Nachrichtenartikel.\n - Tipps zur effektiven Zusammenfassungserstellung.\n\n7. **Häufige Fehler und wie man sie vermeidet**:\n - Fehler: Unzureichendes Verständnis, zu viel Detail, fehlende Struktur, Subjektivität, Vernachlässigung der Zielgruppe.\n - Vermeidungstipps: Gründliches Lesen, Fokus auf das Wesentliche, logische Gliederung, Objektivität, Zielgruppenanalyse.\n\n#### Empfehlungen\n\n- **Verständnis des Originalmaterials**: Gründliches Lesen und Notizen machen sind entscheidend.\n- **Fokus auf Kernaussagen**: Konzentration auf wesentliche Informationen und Vermeidung von Details.\n- **Strukturierung und Klarheit**: Logische Gliederung und präzise Sprache erhöhen die Verständlichkeit.\n- **Zielgruppenorientierung**: Anpassung der Zusammenfassung an die Bedürfnisse der Zielgruppe.\n\nDiese Zusammenfassung bietet eine strukturierte Anleitung zur Erstellung effektiver Zusammenfassungen, die in verschiedenen Kontexten angewendet werden können, um die Effizienz und Effektivität der Informationsverarbeitung zu verbessern.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "workflow_complete": true + } + ], + "logs": [ + { + "id": "log_02a37c17-ef1e-4807-8d7b-e39847cc6ceb", + "message": "Neuer Benutzereingabe erhalten - Vorherigen Workflow beenden", + "type": "info", + "timestamp": "2025-04-06T23:48:41.660503", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_8d0f87d9-7897-4bb0-9a7a-f597367ad014", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 20, 0 Dateien", + "type": "info", + "timestamp": "2025-04-06T23:48:41.665507", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_fa817276-dfaf-4f87-9f7f-24d6cc69d4cd", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-06T23:48:41.680659", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_d54c6c2f-7342-47b0-897f-1eb7d5b7033b", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-06T23:48:42.890042", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ce8e3763-9f4e-45a6-9d8e-6515c956631e", + "message": "Agent documentation_agent wurde ausgewählt mit Aufgabe: Erstelle eine Zusammenfassung basierend auf den be...", + "type": "info", + "timestamp": "2025-04-06T23:48:42.901657", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_46d4fa22-0bd8-4a6b-9238-67ce9abdb9d7", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-06T23:48:42.909692", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_6c81fa1b-1c27-4452-970b-bab259858161", + "message": "Agent documentation_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T23:48:42.919661", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_37c7ac12-0223-4354-bb73-674b0fb29fe9", + "message": "Agent 'documentation_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T23:48:42.928658", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_f5174bb5-9aa1-46fd-b56b-768109610055", + "message": "Agent 'documentation_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-06T23:49:56.825176", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_13d7117b-afba-474d-a517-acec9cc1ae52", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-06T23:50:03.793706", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_69a04dc6-e7ab-4778-a799-3085d2ded96b", + "message": "Nachricht gelöscht: assistant - msg_ae9e...", + "type": "info", + "timestamp": "2025-04-06T23:52:03.074318", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_8a5a4ebe-b7fe-4990-9e09-7f19d8c67c53", + "message": "Nachricht gelöscht: user - msg_6333...", + "type": "info", + "timestamp": "2025-04-06T23:52:09.346472", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_2ca799b9-a708-42d7-868e-c693ed15e8c9.json b/gwserver/_results/workflow_2ca799b9-a708-42d7-868e-c693ed15e8c9.json new file mode 100644 index 00000000..9fb91b6d --- /dev/null +++ b/gwserver/_results/workflow_2ca799b9-a708-42d7-868e-c693ed15e8c9.json @@ -0,0 +1,74 @@ +{ + "id": "2ca799b9-a708-42d7-868e-c693ed15e8c9", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 09:40:16", + "status": "waiting_for_user", + "started_at": "2025-04-04T09:40:17.834743", + "last_activity": "2025-04-04T09:40:19.685041", + "prompt": "beschreibe das bild", + "messages": [ + { + "id": "msg_2e96188c-c2a3-422a-9ff0-e14b1958e95a", + "workflow_id": "2ca799b9-a708-42d7-868e-c693ed15e8c9", + "parent_message_id": null, + "started_at": "2025-04-04T09:40:17.840038", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "beschreibe das bild", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben keine spezifischen Aufgaben durchgeführt. Gibt es etwas, wobei ich Ihnen helfen kann?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_6bdbda2a-ded7-4934-b068-b7cae1cfcd97", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 19, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T09:40:17.837040", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_59a3064e-06aa-49fd-b09b-fd8fa25bd9ce", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T09:40:17.838040", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_2423c44f-7af2-4215-82c9-124d5084955e", + "message": "Agenten-Entscheidung abgeschlossen: 0 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T09:40:19.681043", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_6e9e7f12-012d-4a94-a289-d828bacdc56d", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben keine spezifischen Aufgaben durc...", + "type": "info", + "timestamp": "2025-04-04T09:40:19.685041", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_2eaf1196-7795-45b6-99c7-95e7ad442d8a.json b/gwserver/_results/workflow_2eaf1196-7795-45b6-99c7-95e7ad442d8a.json new file mode 100644 index 00000000..8aadba55 --- /dev/null +++ b/gwserver/_results/workflow_2eaf1196-7795-45b6-99c7-95e7ad442d8a.json @@ -0,0 +1,204 @@ +{ + "id": "2eaf1196-7795-45b6-99c7-95e7ad442d8a", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 09:25:17", + "status": "waiting_for_user", + "started_at": "2025-04-04T09:25:18.812968", + "last_activity": "2025-04-04T09:27:57.048066", + "prompt": "bild analysieren", + "messages": [ + { + "id": "msg_bee0190b-1c06-473b-93d6-38ea1180d96f", + "workflow_id": "2eaf1196-7795-45b6-99c7-95e7ad442d8a", + "parent_message_id": null, + "started_at": "2025-04-04T09:25:18.825904", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "bild analysieren", + "agent_type": null + }, + { + "id": "msg_5862c435-752d-438c-a7f3-71b1bb092689", + "workflow_id": "2eaf1196-7795-45b6-99c7-95e7ad442d8a", + "parent_message_id": null, + "started_at": "2025-04-04T09:25:21.751088", + "finished_at": "2025-04-04T09:25:21.753083", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "Ich habe als Datenanalyst eine Analyse der bereitgestellten Daten durchgeführt.\n\nHier ist meine detaillierte Analyse:\n1. Die Daten zeigen einen klaren Trend...\n2. Es gibt signifikante Korrelationen zwischen...\n3. Besonders auffällig ist...\n\nMeine Empfehlungen basierend auf der Analyse:\n- Maßnahme 1: ...\n- Maßnahme 2: ...\n- Maßnahme 3: ...", + "agent_type": "analyzer", + "agent_id": "analyst_agent", + "agent_name": "Datenanalyst" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n**Zusammenfassung der Agentenergebnisse**\n\n**Analyseergebnisse:**\n1. **Trend:** Die Daten zeigen einen klaren Trend, der auf bestimmte Muster oder Entwicklungen hinweist.\n2. **Korrelationen:** Es wurden signifikante Korrelationen zwischen verschiedenen Datensätzen festgestellt, die auf mögliche Zusammenhänge oder Abhängigkeiten hinweisen.\n3. **Besondere Auffälligkeiten:** Es gibt spezifische Aspekte in den Daten, die besonders hervorstechen und möglicherweise einer genaueren Betrachtung bedürfen.\n\n**Empfehlungen:**\n- **Maßnahme 1:** [Beschreibung der ersten empfohlenen Maßnahme basierend auf den Analyseergebnissen]\n- **Maßnahme 2:** [Beschreibung der zweiten empfohlenen Maßnahme]\n- **Maßnahme 3:** [Beschreibung der dritten empfohlenen Maßnahme]\n\nDiese Empfehlungen sollen dazu beitragen, die identifizierten Trends und Korrelationen optimal zu nutzen und auf die besonderen Auffälligkeiten angemessen zu reagieren.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true, + "finished_at": "2025-04-04T09:27:55.582317", + "status": "completed" + }, + { + "id": "msg_2f8c87f5-322f-422e-981d-55ef597c1d65", + "workflow_id": "2eaf1196-7795-45b6-99c7-95e7ad442d8a", + "parent_message_id": null, + "started_at": "2025-04-04T09:27:55.582317", + "finished_at": null, + "sequence_no": 4, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "kannst du mir die analyse in 2 sätzen zusammenfassen", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Fasse die Analyse in zwei Sätzen zusammen, basierend auf den Informationen, die du hast oder erhalten kannst.", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_61fa3f87-4bad-4570-a0fd-ea65590498a1", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 16, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T09:25:18.812968", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_174a9ea6-071c-4e1c-8fb8-718593e1150a", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T09:25:18.824238", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c7dff399-8ab8-48a5-b3da-a443610693f3", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T09:25:21.733671", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_1ece2ba1-3c37-4318-aae8-00dd11e4e1e8", + "message": "Agent analyst_agent wurde ausgewählt mit Aufgabe: Bitte analysiere das Bild und identifiziere releva...", + "type": "info", + "timestamp": "2025-04-04T09:25:21.739651", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_e2503ab5-17a3-427c-87b9-744ac7d947a1", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-04T09:25:21.741652", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b424b871-12e2-4489-b430-6c45f570b740", + "message": "Agent analyst_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T09:25:21.741652", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_96ce6fe5-785f-4a36-914d-848907ad62a2", + "message": "Agent 'analyst_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T09:25:21.749092", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_48fb0880-1ea8-4452-803a-7b2079b64bbb", + "message": "Agent 'analyst_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-04T09:25:21.766424", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b84539fd-be11-4307-89ee-052cd47afe9b", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-04T09:25:25.484529", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_a64e0328-9d5f-4b53-94ed-9126bb66ecb9", + "message": "Benutzereingabe empfangen: 52 Zeichen, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T09:27:55.578737", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_843748d0-77c6-482c-9ee2-24799b119966", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T09:27:55.579655", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_33a4cf66-5e4b-4c35-a3a9-0c7875384a72", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T09:27:57.036946", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_2c6a7ed9-857c-4298-8b94-0103781f3106", + "message": "Agent user_agent wurde ausgewählt mit Aufgabe: Fasse die Analyse in zwei Sätzen zusammen, basiere...", + "type": "info", + "timestamp": "2025-04-04T09:27:57.036946", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_5c62e44b-dd0b-4216-ae79-bbbae622ea85", + "message": "Workflow wartet auf Benutzereingabe: Fasse die Analyse in zwei Sätzen zusammen, basiere...", + "type": "info", + "timestamp": "2025-04-04T09:27:57.048066", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_37bb3f35-b087-4ee2-9618-d092db481b90.json b/gwserver/_results/workflow_37bb3f35-b087-4ee2-9618-d092db481b90.json new file mode 100644 index 00000000..7e6dc7aa --- /dev/null +++ b/gwserver/_results/workflow_37bb3f35-b087-4ee2-9618-d092db481b90.json @@ -0,0 +1,135 @@ +{ + "id": "37bb3f35-b087-4ee2-9618-d092db481b90", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 6.4.2025, 11:41:36", + "status": "waiting_for_user", + "started_at": "2025-04-06T11:41:36.583178", + "last_activity": "2025-04-06T11:41:44.366152", + "prompt": "mache eine websuche, wer bei ValueOn AG arbeitet.", + "messages": [ + { + "id": "msg_71805481-f620-4ccc-a5f5-a6964f502f04", + "workflow_id": "37bb3f35-b087-4ee2-9618-d092db481b90", + "parent_message_id": null, + "started_at": "2025-04-06T11:41:36.600720", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "mache eine websuche, wer bei ValueOn AG arbeitet.", + "agent_type": null + }, + { + "id": "msg_94b6bd68-159d-4568-bd9e-a906c1ca6ea7", + "workflow_id": "37bb3f35-b087-4ee2-9618-d092db481b90", + "parent_message_id": null, + "started_at": "2025-04-06T11:41:37.978972", + "finished_at": "2025-04-06T11:41:37.985598", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "", + "agent_type": "scraper", + "agent_id": "webcrawler_agent", + "agent_name": "Webscraper" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\nUm eine aussagekräftige Zusammenfassung der Agentenergebnisse zu erstellen, ist es wichtig, die Informationen klar und strukturiert darzustellen. Da keine spezifischen Ergebnisse oder Details des Webscrapers bereitgestellt wurden, werde ich ein allgemeines Format vorschlagen, das Sie anpassen können, sobald Sie die spezifischen Daten haben:\n\n### Zusammenfassung der Agentenergebnisse\n\n#### 1. **Zielsetzung**\n- **Primäres Ziel:** Beschreibung des Hauptziels des Webscraping-Projekts.\n- **Sekundäre Ziele:** Weitere Ziele, die durch das Projekt erreicht werden sollen.\n\n#### 2. **Methodik**\n- **Technologie und Tools:** Auflistung der verwendeten Technologien und Tools (z.B. BeautifulSoup, Scrapy, Selenium).\n- **Datenquellen:** Beschreibung der Websites oder Plattformen, von denen Daten gesammelt wurden.\n- **Datenverarbeitungsprozess:** Kurze Erklärung des Prozesses zur Extraktion, Bereinigung und Speicherung der Daten.\n\n#### 3. **Ergebnisse**\n- **Datenumfang:** Gesamtmenge der gesammelten Daten (z.B. Anzahl der Datensätze, Größe der Datenbank).\n- **Datenqualität:** Bewertung der Qualität der gesammelten Daten (z.B. Vollständigkeit, Genauigkeit).\n- **Wichtige Erkenntnisse:** Zusammenfassung der wichtigsten Erkenntnisse, die aus den Daten gewonnen wurden.\n\n#### 4. **Analyse**\n- **Trends und Muster:** Beschreibung der identifizierten Trends und Muster in den Daten.\n- **Vergleiche:** Relevante Vergleiche mit historischen Daten oder anderen Datensätzen.\n- **Anomalien:** Identifizierung und Erklärung von Anomalien oder unerwarteten Ergebnissen.\n\n#### 5. **Empfehlungen**\n- **Strategische Empfehlungen:** Vorschläge zur Nutzung der gewonnenen Erkenntnisse für strategische Entscheidungen.\n- **Operative Empfehlungen:** Praktische Empfehlungen zur Verbesserung der Datenverarbeitung oder -nutzung.\n- **Zukünftige Schritte:** Vorschläge für zukünftige Projekte oder Erweiterungen des aktuellen Projekts.\n\n#### 6. **Herausforderungen und Lösungen**\n- **Herausforderungen:** Beschreibung der größten Herausforderungen, die während des Projekts aufgetreten sind.\n- **Lösungen:** Erklärungen, wie diese Herausforderungen überwunden wurden.\n\n#### 7. **Fazit**\n- **Zusammenfassung:** Kurze Zusammenfassung der wichtigsten Punkte und des Gesamterfolgs des Projekts.\n\nPassen Sie diese Struktur an die spezifischen Ergebnisse und Details Ihres Webscraping-Projekts an, um eine vollständige und informative Zusammenfassung zu erstellen.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_f46dfaae-46ce-4fc2-b3a4-350800d2a947", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 49, 0 Dateien", + "type": "info", + "timestamp": "2025-04-06T11:41:36.587194", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_33390c43-00de-48f8-87a2-7f0075dd11a2", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-06T11:41:36.594179", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_a75a88c5-3823-4ff3-af10-2271606a1a6e", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-06T11:41:37.947161", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_1fd2872c-c955-4ac9-ad5e-1a063332e139", + "message": "Agent webcrawler_agent wurde ausgewählt mit Aufgabe: Führe eine Websuche durch, um herauszufinden, wer ...", + "type": "info", + "timestamp": "2025-04-06T11:41:37.953161", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_8777a2d5-8d67-428d-a0b0-80a4de3218b8", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-06T11:41:37.960791", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_f20704af-6196-4342-a024-4459327d89d9", + "message": "Agent webcrawler_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T11:41:37.966822", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_186c7375-5826-4d29-81c5-4bdb3635c710", + "message": "Agent 'webcrawler_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T11:41:37.973797", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_8e43d395-77cf-46f8-8fb1-04fe22ceac89", + "message": "Agent 'webcrawler_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-06T11:41:38.035990", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_efcb9d75-b72e-4ca4-8613-d54a6ffdf64c", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-06T11:41:44.366152", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_426e570f-0598-42f1-83b7-931c9ec5ed6f.json b/gwserver/_results/workflow_426e570f-0598-42f1-83b7-931c9ec5ed6f.json new file mode 100644 index 00000000..e1c16b55 --- /dev/null +++ b/gwserver/_results/workflow_426e570f-0598-42f1-83b7-931c9ec5ed6f.json @@ -0,0 +1,45 @@ +{ + "id": "426e570f-0598-42f1-83b7-931c9ec5ed6f", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 08:28:10", + "status": "failed", + "started_at": "2025-04-04T08:28:11.908061", + "last_activity": "2025-04-04T08:28:11.937134", + "prompt": "beschreibe das bild", + "messages": [], + "logs": [ + { + "id": "log_3e853a03-8295-4833-95eb-39a6fdff3873", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 19, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T08:28:11.911433", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_121beddb-8606-4620-b1e0-29ce56548233", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T08:28:11.916433", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_04c86c5f-a080-4c5e-8f7b-428378760003", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T08:28:11.923134", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_28e345d9-ed11-443c-b2f7-6a251f66f970", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T08:28:11.937134", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_4745941d-d058-49f4-a086-45a6206acd4d.json b/gwserver/_results/workflow_4745941d-d058-49f4-a086-45a6206acd4d.json new file mode 100644 index 00000000..d9919e1b --- /dev/null +++ b/gwserver/_results/workflow_4745941d-d058-49f4-a086-45a6206acd4d.json @@ -0,0 +1,74 @@ +{ + "id": "4745941d-d058-49f4-a086-45a6206acd4d", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 08:55:12", + "status": "waiting_for_user", + "started_at": "2025-04-04T08:55:13.119201", + "last_activity": "2025-04-04T08:55:13.870754", + "prompt": "beschreibe das bild", + "messages": [ + { + "id": "msg_209d65e3-6096-41a4-91a9-c57f1fba4abe", + "workflow_id": "4745941d-d058-49f4-a086-45a6206acd4d", + "parent_message_id": null, + "started_at": "2025-04-04T08:55:13.142410", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "beschreibe das bild", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben keine spezifischen Aufgaben durchgeführt. Gibt es etwas, wobei ich Ihnen helfen kann?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_994584d7-edce-407d-bfda-a43f1d3ba4b8", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 19, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T08:55:13.130937", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_554368c7-f355-4d88-bbf9-36919b265bb4", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T08:55:13.140336", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_4249deb4-8dc3-4adf-a499-08f36b3c001d", + "message": "Agenten-Entscheidung abgeschlossen: 0 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T08:55:13.868753", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_745ed185-8df7-4394-be5b-30e0af76e68f", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben keine spezifischen Aufgaben durc...", + "type": "info", + "timestamp": "2025-04-04T08:55:13.870754", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_4839820e-5e8b-4437-85cc-182ea76b1297.json b/gwserver/_results/workflow_4839820e-5e8b-4437-85cc-182ea76b1297.json new file mode 100644 index 00000000..d50c2176 --- /dev/null +++ b/gwserver/_results/workflow_4839820e-5e8b-4437-85cc-182ea76b1297.json @@ -0,0 +1,203 @@ +{ + "id": "4839820e-5e8b-4437-85cc-182ea76b1297", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 18:49:05", + "status": "waiting_for_user", + "started_at": "2025-04-04T18:49:07.071736", + "last_activity": "2025-04-04T18:49:54.347354", + "prompt": "was beschreiben diese files?", + "messages": [ + { + "id": "msg_adb81060-481a-4370-8f97-5b4e5a39dc93", + "workflow_id": "4839820e-5e8b-4437-85cc-182ea76b1297", + "parent_message_id": null, + "started_at": "2025-04-04T18:49:07.086181", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [ + { + "id": 3, + "source": { + "type": "file", + "id": 3, + "name": "LF-Current.png", + "content_type": "image/png", + "size": 126277, + "upload_date": "2025-04-04T18:49:46.806730" + }, + "contents": [ + { + "type": "text", + "text": "Image Analysis:\nThe image is a flowchart illustrating a product development process involving both a Product Team and an Engineering Team. Here's a detailed description:\n\n### Input\n- **Sources**: Customers, Sales, and Internal Ideas.\n- **Flow**: Inputs are collected and fed into the Product Team.\n\n### Product Team\n1. **Discover**\n - **Collect**: Ideas and inputs are gathered.\n - **Qualify**: Ideas are analyzed and matched within the team.\n\n2. **Define**\n - **Structure & Document**: Specifications are written, and acceptance criteria are defined.\n - **Explore & Design**: UI design and experiments are conducted.\n\n3. **Shape**\n - **Roadmap**: A roadmap is defined.\n - **Scoping**: The scope for the next version is defined.\n - **Manage**: Tickets are managed in the product.\n\n### Engineering Team\n1. **Build**\n - **Manage**: Progress is tracked in a dashboard.\n - **Factory**: Tickets are developed for the next version.\n\n2. **Release**\n - **Manage**: Ensures stable changes.\n\n3. **Run & Monitor**\n - **Manage**: Ensures stable operation.\n - **Service & Support**: Delivers first-level support according to agreed SLA.\n\n4. **Assess**\n - **Manage**: Moves assessed tickets to future versions.\n - **Estimate**: Assesses tickets for implementation, feasibility, and effort.\n\n### Output\n- **Product**: The final product is delivered as output.\n\n### Tool Integration\n- **Ticketing System**: Includes categories like Inputs & Ideas, Analysis, and Future Versions.\n- **Roadmap** and **Management Dashboards**: Tools used for planning and monitoring.\n\nThe flowchart uses arrows to indicate the flow of processes and responsibilities between the Product and Engineering Teams, highlighting collaboration and iterative development." + } + ] + }, + { + "id": 4, + "source": { + "type": "file", + "id": 4, + "name": "LF-Details.png", + "content_type": "image/png", + "size": 253009, + "upload_date": "2025-04-04T18:49:46.811749" + }, + "contents": [ + { + "type": "text", + "text": "Image Analysis:\nThe image is a flowchart depicting a product development process involving several teams: Product Team, Q&A Team, Engineering Team, and Operations. Here's a detailed breakdown:\n\n### Input\n- **Sources**: Customers, Sales, Our Ideas\n- **Purpose**: Provide initial ideas and inputs for the product development process.\n\n### Product Team\n1. **Discover**\n - **Collect**: Ideas and inputs.\n - **Qualify**: Analyze and match against business priorities.\n\n2. **Define**\n - **Structure & Document**: Write specifications and define acceptance criteria.\n - **Explore & Design**: UI design, experiments, and reference tickets in ClickUp.\n\n3. **Shape**\n - **Roadmap**: Define roadmap to meet opportunities and protect development stability.\n - **Scoping**: Define next version's scope.\n - **Manage**: Tickets in Product.\n\n### Engineering Team\n1. **Assess**\n - **Manage**: Move assessed tickets to Engineering for future versions.\n - **Estimate**: Assess implementation, feasibility, and effort.\n\n2. **Build**\n - **Manage**: Track progress in the dashboard.\n - **Factory**: Develop tickets in Engineering for the next version.\n\n### Q&A Team\n1. **Validate**\n - **Testing**: Test functionality against acceptance criteria.\n - **Analysis**: Analyze tickets, events, and deviations.\n\n### Operations\n1. **Release**\n - **Manage**: Ensure stable changes.\n\n2. **Run & Monitor**\n - **Manage**: Ensure stable operation.\n - **Service & Support**: Deliver first-level support according to agreed SLA.\n\n### Output\n- **Product**: The final product is the output of this process.\n\n### Tool Integration\n- **Ticketing System**: Visual representation of ticket management.\n- **Roadmap**: Timeline view of project milestones.\n- **Management Dashboards**: Data visualization for tracking progress and metrics.\n\nThe flowchart uses arrows to indicate the flow of tasks and responsibilities between teams, emphasizing a structured and iterative approach to product development." + } + ] + }, + { + "id": 2, + "source": { + "type": "file", + "id": 2, + "name": "LF-Target.png", + "content_type": "image/png", + "size": 256760, + "upload_date": "2025-04-04T18:49:46.817147" + }, + "contents": [ + { + "type": "text", + "text": "Image Analysis:\nThe image is a flowchart depicting a product development process involving multiple teams: Product Team, Q&A Team, Engineering Team, and Operations. Here's a detailed breakdown:\n\n### Input\n- **Sources**: Customers, Sales, Our Ideas\n- These inputs feed into the Product Team's process.\n\n### Product Team\n1. **Discover**\n - **Collect**: Ideas & Inputs\n - **Qualify**: Analyze and match against business priorities\n\n2. **Define**\n - **Structure & Document**: Write specifications, define acceptance criteria\n - **Explore & Design**: UI Design, experiments, and reference tickets in ClickUp\n\n3. **Shape**\n - **Roadmap**: Current setup and accelerated to meet market needs\n - **Scoping**: Define next version's scope\n - **Manage**: Tickets in Product\n\n### Engineering Team\n- **Assess**\n - **Manage**: Move assessed tickets to Engineering for future versions\n - **Estimate**: Assess tickets for implementation, feasibility, and effort\n\n- **Build**\n - **Manage**: Track progress in the dashboard\n - **Factory**: Develop tickets in Engineering for the next version\n\n### Q&A Team\n- **Validate**\n - **Testing**: Test functionality against acceptance\n - **Analysis**: Analyze tickets, events, deviations\n\n### Operations\n1. **Release**\n - **Manage**: Ensure stable changes\n\n2. **Run & Monitor**\n - **Manage**: Ensure stable operation\n - **Service & Support**: Deliver 1st level support according to agreed SLA\n\n### Output\n- **Product**: The final output of the process\n\n### Tool Integration\n- **Ticketing System**: Visual representation of a ticketing system\n- **Roadmap**: Timeline view of project phases\n- **Management Dashboards**: Graphs and metrics for tracking progress\n\nThe flowchart uses arrows to indicate the flow of tasks and responsibilities between the teams, emphasizing collaboration and integration across different stages of product development." + } + ] + } + ], + "content": "was beschreiben diese files?", + "agent_type": null + }, + { + "id": "msg_7f0e279a-c72f-46cc-9306-9709672106b8", + "workflow_id": "4839820e-5e8b-4437-85cc-182ea76b1297", + "parent_message_id": null, + "started_at": "2025-04-04T18:49:49.067558", + "finished_at": "2025-04-04T18:49:49.070498", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "Ich habe als Datenanalyst eine Analyse der bereitgestellten Daten durchgeführt.\n\nHier ist meine detaillierte Analyse:\n1. Die Daten zeigen einen klaren Trend...\n2. Es gibt signifikante Korrelationen zwischen...\n3. Besonders auffällig ist...\n\nMeine Empfehlungen basierend auf der Analyse:\n- Maßnahme 1: ...\n- Maßnahme 2: ...\n- Maßnahme 3: ...", + "agent_type": "analyzer", + "agent_id": "analyst_agent", + "agent_name": "Datenanalyst" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n**Zusammenfassung der Agentenergebnisse**\n\n**Analyseergebnisse:**\n\n1. **Trendidentifikation:**\n - Die Daten zeigen einen klaren Trend, der auf bestimmte Muster oder Entwicklungen hinweist.\n\n2. **Korrelationen:**\n - Es wurden signifikante Korrelationen zwischen verschiedenen Datensätzen festgestellt, die auf mögliche Zusammenhänge oder Einflussfaktoren hindeuten.\n\n3. **Besondere Auffälligkeiten:**\n - Ein bestimmtes Merkmal oder eine Datenreihe sticht besonders hervor, was auf eine außergewöhnliche Entwicklung oder Anomalie hinweisen könnte.\n\n**Empfehlungen:**\n\n1. **Maßnahme 1:**\n - Basierend auf den identifizierten Trends und Korrelationen wird empfohlen, spezifische Schritte zu unternehmen, um die positiven Entwicklungen zu fördern oder negative Einflüsse zu minimieren.\n\n2. **Maßnahme 2:**\n - Eine weitere Empfehlung zielt darauf ab, die identifizierten Korrelationen zu nutzen, um strategische Entscheidungen zu treffen, die den Gesamterfolg fördern.\n\n3. **Maßnahme 3:**\n - Es wird vorgeschlagen, gezielte Maßnahmen zu ergreifen, um auf die besonderen Auffälligkeiten zu reagieren, um Risiken zu mindern oder Chancen zu maximieren.\n\nDiese strukturierte Zusammenfassung fasst die wesentlichen Erkenntnisse und Empfehlungen der Datenanalyse zusammen, ohne Redundanzen zu enthalten.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_b3941b94-ec38-4bc2-97de-d3af138eb098", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 28, 3 Dateien", + "type": "info", + "timestamp": "2025-04-04T18:49:07.076283", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_04db440b-ca4d-4a62-a161-3ecbb406925a", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T18:49:07.080970", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_3fabb187-58b5-43f2-b8fa-5a0dac900ab1", + "message": "3 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T18:49:07.090501", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_51a05a98-1230-47b9-8d2a-b417bf6e4644", + "message": "Workflow wurde manuell gestoppt", + "type": "info", + "timestamp": "2025-04-04T18:49:42.124809", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_72c5b0ff-6c84-4540-b094-0d95b0edc6b7", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T18:49:49.040299", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c589f407-7e4e-4bd3-a679-ac30cde812c3", + "message": "Agent analyst_agent wurde ausgewählt mit Aufgabe: Analysiere die bereitgestellten Flowchart-Bilder, ...", + "type": "info", + "timestamp": "2025-04-04T18:49:49.048482", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_08c86e47-8755-44b0-9796-9b093e306954", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-04T18:49:49.053488", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_afbf977e-6dd6-4262-99d6-9a8df790414f", + "message": "Agent analyst_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T18:49:49.059074", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_59943848-27e4-4b63-979a-a0fd54e2b96f", + "message": "Agent 'analyst_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T18:49:49.063133", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_8fc48088-8c70-4942-912b-5db2cafacbf1", + "message": "Agent 'analyst_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-04T18:49:49.100613", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_63bdb78c-fbe6-4a99-8a4a-55f59ada8e45", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-04T18:49:54.347354", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_4ba4b7cd-879b-4e44-84dd-daf6ed23a061.json b/gwserver/_results/workflow_4ba4b7cd-879b-4e44-84dd-daf6ed23a061.json new file mode 100644 index 00000000..b2f04941 --- /dev/null +++ b/gwserver/_results/workflow_4ba4b7cd-879b-4e44-84dd-daf6ed23a061.json @@ -0,0 +1,74 @@ +{ + "id": "4ba4b7cd-879b-4e44-84dd-daf6ed23a061", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 10:24:35", + "status": "waiting_for_user", + "started_at": "2025-04-04T10:24:36.074121", + "last_activity": "2025-04-04T10:24:36.886469", + "prompt": "analysiere das bild", + "messages": [ + { + "id": "msg_3dd3df9d-9e71-4431-9737-9c4bb2947566", + "workflow_id": "4ba4b7cd-879b-4e44-84dd-daf6ed23a061", + "parent_message_id": null, + "started_at": "2025-04-04T10:24:36.080137", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "analysiere das bild", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben keine spezifischen Aufgaben durchgeführt. Gibt es etwas, wobei ich Ihnen helfen kann?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_eba63c8d-68d5-449b-8963-24bf1a358864", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 19, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T10:24:36.077121", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_0accef91-474d-4349-b736-696b78dbdea8", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T10:24:36.078157", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_946c6138-67c6-462d-a530-3d1d92a85bb4", + "message": "Agenten-Entscheidung abgeschlossen: 0 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T10:24:36.880503", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_56df3970-626b-41ee-b1c5-5ad7f6b7a745", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben keine spezifischen Aufgaben durc...", + "type": "info", + "timestamp": "2025-04-04T10:24:36.886469", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_4dc09b26-3290-4559-acfa-b0f57a88bec3.json b/gwserver/_results/workflow_4dc09b26-3290-4559-acfa-b0f57a88bec3.json new file mode 100644 index 00000000..55ab151f --- /dev/null +++ b/gwserver/_results/workflow_4dc09b26-3290-4559-acfa-b0f57a88bec3.json @@ -0,0 +1,169 @@ +{ + "id": "4dc09b26-3290-4559-acfa-b0f57a88bec3", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 5.4.2025, 00:45:31", + "status": "waiting_for_user", + "started_at": "2025-04-05T00:45:32.125842", + "last_activity": "2025-04-05T00:45:41.330610", + "prompt": "extract table from file", + "messages": [ + { + "id": "msg_503ef3c9-ef7c-4a59-80bb-cb54db33d9f5", + "workflow_id": "4dc09b26-3290-4559-acfa-b0f57a88bec3", + "parent_message_id": null, + "started_at": "2025-04-05T00:45:32.143768", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [ + { + "id": 5, + "source": { + "type": "file", + "id": 5, + "name": "auszug_liste_positionen.pdf", + "content_type": "application/pdf", + "size": 299729, + "upload_date": "2025-04-05T00:45:32.237978" + }, + "contents": [ + { + "type": "text", + "text": "\n\n" + } + ] + } + ], + "content": "extract table from file", + "agent_type": null + }, + { + "id": "msg_d794f47d-6a32-474a-ba2a-710947e1aed9", + "workflow_id": "4dc09b26-3290-4559-acfa-b0f57a88bec3", + "parent_message_id": null, + "started_at": "2025-04-05T00:45:33.856590", + "finished_at": "2025-04-05T00:45:33.861431", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "Ich habe als Entwickler die Anforderungen analysiert und folgenden Code entwickelt:\n\n```python\ndef process_data(input_file, output_file):\n \"\"\"\n Verarbeitet Daten aus einer Eingabedatei und speichert die Ergebnisse.\n \n Args:\n input_file: Pfad zur Eingabedatei\n output_file: Pfad zur Ausgabedatei\n \"\"\"\n import pandas as pd\n \n # Daten einlesen\n df = pd.read_csv(input_file)\n \n # Daten verarbeiten\n # Hier würde die eigentliche Datenverarbeitung stattfinden\n processed_df = df.copy()\n \n # Beispiel: Spalten filtern und transformieren\n if 'data' in processed_df.columns:\n processed_df['transformed'] = processed_df['data'] * 2\n \n # Ergebnis speichern\n processed_df.to_csv(output_file, index=False)\n \n return len(processed_df)\n\n# Beispielaufruf\nif __name__ == \"__main__\":\n result = process_data(\"input.csv\", \"output.csv\")\n print(f\"Verarbeitet: result Datensätze\")\n```\n\nDer Code liest eine CSV-Datei ein, führt eine einfache Transformation durch und speichert das Ergebnis. \nDie Hauptfunktion `process_data` ist modular gestaltet und kann leicht erweitert werden.\n\nZur Verwendung:\n1. Stelle sicher, dass pandas installiert ist (`pip install pandas`)\n2. Passe die Dateipfade im Beispielaufruf an\n3. Erweitere die Verarbeitung je nach deinen spezifischen Anforderungen", + "agent_type": "coder", + "agent_id": "coder_agent", + "agent_name": "Entwickler" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n### Zusammenfassung der Agentenergebnisse\n\n#### Codeübersicht\nDer Entwickler hat einen Python-Code erstellt, der Daten aus einer CSV-Datei einliest, verarbeitet und das Ergebnis in einer neuen CSV-Datei speichert. Die Hauptfunktion des Codes ist `process_data`, die folgende Schritte umfasst:\n\n1. **Datenimport**: Die Funktion liest die Eingabedatei mithilfe der Bibliothek `pandas` ein.\n2. **Datenverarbeitung**: \n - Der Code enthält eine Beispieltransformation, bei der eine neue Spalte `transformed` erstellt wird, die den doppelten Wert der Spalte `data` enthält, falls diese existiert.\n - Der Code ist modular aufgebaut, was eine einfache Erweiterung der Datenverarbeitung ermöglicht.\n3. **Datenspeicherung**: Die verarbeiteten Daten werden in einer Ausgabedatei gespeichert.\n\n#### Empfehlungen zur Nutzung\n- **Installation**: Stellen Sie sicher, dass die Bibliothek `pandas` installiert ist, um den Code auszuführen (`pip install pandas`).\n- **Anpassung der Dateipfade**: Ändern Sie die Dateipfade im Beispielaufruf entsprechend Ihrer Dateistruktur.\n- **Erweiterung der Funktionalität**: Der Code ist so gestaltet, dass er leicht erweitert werden kann, um spezifische Anforderungen zu erfüllen. Fügen Sie zusätzliche Verarbeitungsschritte innerhalb der Funktion hinzu, um komplexere Datenanalysen durchzuführen.\n\n#### Wichtige Erkenntnisse\n- Der Code bietet eine grundlegende Struktur für die Datenverarbeitung, die als Ausgangspunkt für komplexere Aufgaben dienen kann.\n- Die Modularität der Funktion `process_data` erleichtert die Anpassung und Erweiterung, was sie flexibel für verschiedene Anwendungsfälle macht.\n- Die Verwendung von `pandas` ermöglicht effiziente Datenmanipulation und -analyse, was den Code für datenintensive Anwendungen geeignet macht.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_46eb6861-67ac-4b74-81e9-0e3966b5add6", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 23, 1 Dateien", + "type": "info", + "timestamp": "2025-04-05T00:45:32.132183", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_08db91db-ee33-4313-a59e-dca159c85b9e", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-05T00:45:32.137767", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_8b2347ba-62c7-4acc-9e06-09678ce4b340", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-05T00:45:32.148735", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_065d5b1e-27b5-4846-b55d-e817ec770b19", + "message": "File auszug_liste_positionen.pdf read successfully", + "type": "info", + "timestamp": "2025-04-05T00:45:32.229034", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_92dbb6de-a01a-4787-9772-91452af43e93", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-05T00:45:33.828983", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_3bce866b-8b73-4178-bd79-d90d7616ef0c", + "message": "Agent coder_agent wurde ausgewählt mit Aufgabe: Extrahiere die Tabelle aus der Datei 'auszug_liste...", + "type": "info", + "timestamp": "2025-04-05T00:45:33.834983", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_d3bd4e18-2795-4f00-a1cc-3ee3a995dc18", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-05T00:45:33.840549", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c322e6d0-b5b7-4257-b4f4-95535f420577", + "message": "Agent coder_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-05T00:45:33.845581", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_94e919e5-4530-4cf0-88ec-69744aa2f43e", + "message": "Agent 'coder_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-05T00:45:33.851590", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_38ed1726-8423-47db-a18b-0491c28c5415", + "message": "Agent 'coder_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-05T00:45:33.917774", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_fef7f060-a973-4680-aabb-8bbaee38ca57", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-05T00:45:41.330610", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_4fee787f-b099-4aeb-bd99-73d151229f74.json b/gwserver/_results/workflow_4fee787f-b099-4aeb-bd99-73d151229f74.json new file mode 100644 index 00000000..12df925d --- /dev/null +++ b/gwserver/_results/workflow_4fee787f-b099-4aeb-bd99-73d151229f74.json @@ -0,0 +1,45 @@ +{ + "id": "4fee787f-b099-4aeb-bd99-73d151229f74", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 11:46:16", + "status": "failed", + "started_at": "2025-04-04T11:46:16.651685", + "last_activity": "2025-04-04T11:46:32.126252", + "prompt": "describe", + "messages": [], + "logs": [ + { + "id": "log_1907a8c4-241e-43b3-98d8-0d381ad62a08", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 8, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T11:46:16.655687", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ae05b5a7-985c-41ef-a4ae-3c5f172d9262", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T11:46:16.660587", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_83ce0ffb-cdd4-4722-9808-0be03330abde", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T11:46:16.666797", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_31530013-6129-488f-9ede-4ed823863618", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T11:46:32.126252", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_59df8cea-ba9e-48d6-aa48-8d68f2e105da.json b/gwserver/_results/workflow_59df8cea-ba9e-48d6-aa48-8d68f2e105da.json new file mode 100644 index 00000000..8efc9585 --- /dev/null +++ b/gwserver/_results/workflow_59df8cea-ba9e-48d6-aa48-8d68f2e105da.json @@ -0,0 +1,74 @@ +{ + "id": "59df8cea-ba9e-48d6-aa48-8d68f2e105da", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 10:31:58", + "status": "waiting_for_user", + "started_at": "2025-04-04T10:31:59.502928", + "last_activity": "2025-04-04T10:32:01.732993", + "prompt": "beschreibe das bild", + "messages": [ + { + "id": "msg_9b101f2e-80a0-4ad1-b493-5e8e1871bf00", + "workflow_id": "59df8cea-ba9e-48d6-aa48-8d68f2e105da", + "parent_message_id": null, + "started_at": "2025-04-04T10:31:59.508929", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "beschreibe das bild", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben keine spezifischen Aufgaben durchgeführt. Gibt es etwas, wobei ich Ihnen helfen kann?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_50bfd380-0ae4-4e02-922f-b6ae2111889b", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 19, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T10:31:59.504929", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_883883e2-c0de-46ca-92e5-fc9bf92a0dc5", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T10:31:59.506930", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_1a94d3af-62bd-421e-8ca6-15f9ff139284", + "message": "Agenten-Entscheidung abgeschlossen: 0 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T10:32:01.725998", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_29eb2920-b1fc-4515-8d7a-b55cc167c645", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben keine spezifischen Aufgaben durc...", + "type": "info", + "timestamp": "2025-04-04T10:32:01.732993", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_5b9a4087-2335-477f-805d-23a54d5c5c30.json b/gwserver/_results/workflow_5b9a4087-2335-477f-805d-23a54d5c5c30.json new file mode 100644 index 00000000..9214a6ee --- /dev/null +++ b/gwserver/_results/workflow_5b9a4087-2335-477f-805d-23a54d5c5c30.json @@ -0,0 +1,263 @@ +{ + "id": "5b9a4087-2335-477f-805d-23a54d5c5c30", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 19:05:28", + "status": "waiting_for_user", + "started_at": "2025-04-04T19:05:28.410317", + "last_activity": "2025-04-04T19:06:32.120827", + "prompt": "please summarize pictures", + "messages": [ + { + "id": "msg_499aa0ac-a7bc-42f3-b1bc-d0ba9fc9997b", + "workflow_id": "5b9a4087-2335-477f-805d-23a54d5c5c30", + "parent_message_id": null, + "started_at": "2025-04-04T19:05:28.426106", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [ + { + "id": 3, + "source": { + "type": "file", + "id": 3, + "name": "LF-Current.png", + "content_type": "image/png", + "size": 126277, + "upload_date": "2025-04-04T19:05:49.282974" + }, + "contents": [ + { + "type": "text", + "text": "Image Analysis:\nThe image is a flowchart depicting a product development process divided between the Product Team and the Engineering Team. Here's a detailed description:\n\n### Input\n- **Sources**: Customers, Sales, Our Ideas.\n- **Process**: Inputs are collected and qualified.\n\n### Product Team\n1. **Discover**\n - **Collect**: Ideas & Inputs.\n - **Qualify**: Analyze and match in the team.\n\n2. **Define**\n - **Structure & Document**: Write specifications, define acceptance criteria.\n - **Explore & Design**: UI Design, Experiments, etc.\n\n3. **Shape**\n - **Roadmap**: Define a roadmap.\n - **Scoping**: Define next version's scope.\n - **Manage**: Tickets in Product.\n\n### Engineering Team\n1. **Build**\n - **Manage**: Track progress in the dashboard.\n - **Factory**: Develop tickets in Engineering for the next version.\n\n2. **Release**\n - **Manage**: Ensure stable changes.\n\n3. **Run & Monitor**\n - **Manage**: Ensure stable operation.\n - **Service & Support**: Deliver 1st level support according to agreed SLA.\n\n4. **Assess**\n - **Manage**: Move assessed tickets to Engineering for future versions.\n - **Estimate**: Assess tickets, define implementation, feasibility, and effort.\n\n### Output\n- **Product**: The final output of the process.\n\n### Tool Integration\n- **Ticketing System**: Includes sections like Inputs & Ideas, Analysis, Cooperation, Future Versions, and Business.\n- **Roadmap** and **Management Dashboards**: Tools for managing the process.\n\nThe flowchart uses arrows to indicate the flow of tasks and responsibilities between the stages and teams." + } + ] + }, + { + "id": 2, + "source": { + "type": "file", + "id": 2, + "name": "LF-Target.png", + "content_type": "image/png", + "size": 256760, + "upload_date": "2025-04-04T19:05:49.288601" + }, + "contents": [ + { + "type": "text", + "text": "Image Analysis:\nThe image is a flowchart depicting a product development process involving multiple teams: Product Team, Q&A Team, Engineering Team, and Operations. Here's a detailed breakdown:\n\n### Input\n- **Sources**: Customers, Sales, Our Ideas\n- These inputs feed into the Product Team's process.\n\n### Product Team\n1. **Discover**\n - **Collect**: Ideas & Inputs\n - **Qualify**: Analyze and match against business priorities\n\n2. **Define**\n - **Structure & Document**: Write specifications and define acceptance criteria\n - **Explore & Design**: UI Design, Experiments, and reference tickets in ClickUp\n\n3. **Shape**\n - **Roadmap**: Current setup and accelerated market needs\n - **Scoping**: Define next version's scope\n - **Manage**: Tickets in Product\n\n### Engineering Team\n1. **Assess**\n - **Manage**: Move assessed tickets to Engineering for future versions\n - **Estimate**: Assess tickets for implementation, feasibility, and effort\n\n2. **Build**\n - **Manage**: Track progress in the dashboard\n - **Factory**: Develop tickets in Engineering for the next version\n\n### Q&A Team\n1. **Validate**\n - **Testing**: Test functionality against acceptance\n - **Analysis**: Analyze tickets, events, deviations\n\n### Operations\n1. **Release**\n - **Manage**: Ensure stable changes\n\n2. **Run & Monitor**\n - **Manage**: Ensure stable operation\n - **Service & Support**: Deliver 1st Level support according to agreed SLA\n\n### Output\n- **Product**: The final output of the process\n\n### Tool Integration\n- **Ticketing System**: Manages tasks and progress\n- **Roadmap**: Visual timeline of tasks and milestones\n- **Management Dashboards**: Displays metrics and performance data\n\nThe flowchart uses arrows to indicate the flow of tasks and responsibilities between different teams and stages." + } + ] + } + ], + "content": "please summarize pictures", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Bitte fassen Sie die Informationen aus den bereitgestellten Bildanalysen zusammen. Die Bilder beschreiben Flussdiagramme, die den Produktentwicklungsprozess darstellen. Erstellen Sie eine zusammenfassende Beschreibung der Prozesse, die in den Bildern LF-Current.png und LF-Target.png dargestellt sind.", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true, + "finished_at": "2025-04-04T19:06:22.556326", + "status": "completed" + }, + { + "id": "msg_b6c54c0f-f523-4ec5-865c-7fd630560716", + "workflow_id": "5b9a4087-2335-477f-805d-23a54d5c5c30", + "parent_message_id": null, + "started_at": "2025-04-04T19:06:22.556326", + "finished_at": null, + "sequence_no": 3, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "ja, bitte zusammenfassung", + "agent_type": null + }, + { + "id": "msg_9944cbb3-cefb-43d6-8b6e-87d00913f326", + "workflow_id": "5b9a4087-2335-477f-805d-23a54d5c5c30", + "parent_message_id": null, + "started_at": "2025-04-04T19:06:24.717061", + "finished_at": "2025-04-04T19:06:24.717061", + "sequence_no": 4, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "# Bericht - Projektzusammenfassung 2025\n\n## Zusammenfassung\n\nDieses Dokument bietet einen umfassenden Überblick über die strategische Ausrichtung und geplanten Aktivitäten für das Jahr 2025. Es basiert auf den aktuellen Planungsdokumenten und Analysen und dient als Referenz für alle Projektbeteiligten.\n\n## Inhaltsverzeichnis\n\n1. Einleitung und Zielsetzung\n2. Marktanalyse und Strategische Positionierung\n3. Projektplanung und Ressourcenallokation\n4. Budgetierung und Finanzplanung\n5. Meilensteine und Zeitplan\n6. Risikomanagement\n7. Empfehlungen und nächste Schritte\n\n## 1. Einleitung und Zielsetzung\n\nDieses Dokument wurde erstellt, um einen strukturierten Überblick über die geplanten Aktivitäten und strategischen Ziele für das Jahr 2025 zu geben. Die Hauptziele sind:\n\n- Expansion in neue Märkte mit besonderem Fokus auf die APAC-Region\n- Steigerung des Marktanteils in bestehenden Märkten um 5%\n- Entwicklung und Einführung von mindestens zwei neuen Produktlinien\n- Optimierung der Betriebsabläufe zur Kostensenkung um 8%\n\n## 2. Marktanalyse und Strategische Positionierung\n\nDie aktuelle Marktanalyse zeigt folgende Schlüsseltrends:\n\n| Trend | Bedeutung | Implikation |\n|-------|-----------|-------------|\n| Digitalisierung | Hoch | Erhöhte Nachfrage nach integrierten Lösungen |\n| Nachhaltigkeit | Mittel-Hoch | Anpassung von Produkten und Prozessen erforderlich |\n| KI-Integration | Hoch | Wettbewerbsvorteil durch intelligente Produkte |\n\nUnsere strategische Positionierung basiert auf dem Prinzip der differenzierten Qualitätsführerschaft mit starkem Fokus auf Innovationen.\n\n## 3. Projektplanung und Ressourcenallokation\n\nDrei Hauptprojekte wurden für Q2 2025 identifiziert:\n\n1. **Projekt Alpha**: Markteinführung der neuen Produktlinie XYZ\n - Projektleitung: Maria Schmidt\n - Teamgröße: 12 Mitarbeiter\n - Startdatum: 15.04.2025\n\n2. **Projekt Beta**: Implementierung des verbesserten CRM-Systems\n - Projektleitung: Thomas Müller\n - Teamgröße: 8 Mitarbeiter\n - Startdatum: 01.05.2025\n\n3. **Projekt Gamma**: Expansion in die APAC-Region\n - Projektleitung: Sarah Weber\n - Teamgröße: 15 Mitarbeiter\n - Startdatum: 01.06.2025\n\nDie detaillierte Ressourcenallokation ist im Anhang A zu finden.\n\n## 4. Budgetierung und Finanzplanung\n\nDas Gesamtbudget für 2025 beträgt 12,5 Millionen Euro, mit folgender Aufteilung:\n\n- Forschung und Entwicklung: 3,75 Mio. € (30%)\n- Marketing und Vertrieb: 3,125 Mio. € (25%)\n- Betriebskosten: 2,5 Mio. € (20%)\n- Expansion und neue Märkte: 1,875 Mio. € (15%)\n- Reserve und Unvorhergesehenes: 1,25 Mio. € (10%)\n\nDas Budget für Forschung und Entwicklung wurde um 15% im Vergleich zum Vorjahr erhöht.\n\n## 5. Meilensteine und Zeitplan\n\n| Meilenstein | Beschreibung | Termin |\n|-------------|--------------|--------|\n| M1 | Abschluss der Marktforschung für APAC | 31.03.2025 |\n| M2 | Produktprototyp XYZ fertiggestellt | 30.04.2025 |\n| M3 | CRM-System implementiert | 30.06.2025 |\n| M4 | Erste Niederlassung in APAC eröffnet | 31.08.2025 |\n| M5 | Markteinführung Produktlinie XYZ | 30.09.2025 |\n\n## 6. Risikomanagement\n\nIdentifizierte Risiken und Gegenmaßnahmen:\n\n- **Lieferkettenunterbrechungen**\n - Risikostufe: Hoch\n - Maßnahmen: Diversifizierung der Lieferanten, erhöhte Lagerbestände kritischer Komponenten\n\n- **Regulatorische Änderungen**\n - Risikostufe: Mittel\n - Maßnahmen: Kontinuierliches Monitoring, frühzeitige Anpassung der Produkte\n\n- **Verzögerungen bei der Produktentwicklung**\n - Risikostufe: Mittel\n - Maßnahmen: Agile Entwicklungsmethoden, regelmäßige Reviews, Pufferzeiten im Zeitplan\n\n## 7. Empfehlungen und nächste Schritte\n\nBasierend auf der vorliegenden Analyse werden folgende Schritte empfohlen:\n\n1. Sofortige Einberufung der Projektteams und Kick-off-Meetings\n2. Finalisierung der detaillierten Projektpläne bis Ende März\n3. Monatliche Statusberichte an die Geschäftsleitung\n4. Vierteljährliche Review-Meetings mit allen Stakeholdern\n5. Kontinuierliches Monitoring der Marktbedingungen und Anpassung der Strategie bei Bedarf\n\n---\n\n**Dokument-Metadaten:**\n- Erstellt: 30.03.2025\n- Version: 1.0\n- Status: Finaler Entwurf\n- Autor: Dokumentations-Agent", + "agent_type": "documentation", + "agent_id": "documentation_agent", + "agent_name": "Dokumentation" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n### Zusammenfassung der Agentenergebnisse: Projektzusammenfassung 2025\n\n#### Einleitung und Zielsetzung\nDas Dokument bietet einen strukturierten Überblick über die strategischen Ziele und geplanten Aktivitäten für 2025. Hauptziele sind die Expansion in die APAC-Region, eine Marktanteilssteigerung um 5% in bestehenden Märkten, die Einführung von zwei neuen Produktlinien und die Optimierung der Betriebsabläufe zur Kostensenkung um 8%.\n\n#### Marktanalyse und Strategische Positionierung\nDie Marktanalyse identifiziert Digitalisierung, Nachhaltigkeit und KI-Integration als Schlüsseltrends. Die strategische Positionierung basiert auf differenzierter Qualitätsführerschaft mit einem starken Fokus auf Innovationen.\n\n#### Projektplanung und Ressourcenallokation\nFür Q2 2025 sind drei Hauptprojekte geplant:\n1. **Projekt Alpha**: Einführung der Produktlinie XYZ (Leitung: Maria Schmidt, Team: 12 Mitarbeiter, Start: 15.04.2025)\n2. **Projekt Beta**: Implementierung eines verbesserten CRM-Systems (Leitung: Thomas Müller, Team: 8 Mitarbeiter, Start: 01.05.2025)\n3. **Projekt Gamma**: Expansion in die APAC-Region (Leitung: Sarah Weber, Team: 15 Mitarbeiter, Start: 01.06.2025)\n\n#### Budgetierung und Finanzplanung\nDas Gesamtbudget für 2025 beträgt 12,5 Millionen Euro, verteilt auf Forschung und Entwicklung (30%), Marketing und Vertrieb (25%), Betriebskosten (20%), Expansion (15%) und Reserve (10%). Das F&E-Budget wurde um 15% erhöht.\n\n#### Meilensteine und Zeitplan\nWichtige Meilensteine umfassen den Abschluss der Marktforschung für APAC (31.03.2025), die Fertigstellung des Produktprototyps XYZ (30.04.2025), die Implementierung des CRM-Systems (30.06.2025), die Eröffnung der ersten APAC-Niederlassung (31.08.2025) und die Markteinführung der Produktlinie XYZ (30.09.2025).\n\n#### Risikomanagement\nIdentifizierte Risiken umfassen Lieferkettenunterbrechungen (Hoch), regulatorische Änderungen (Mittel) und Verzögerungen bei der Produktentwicklung (Mittel). Gegenmaßnahmen beinhalten Lieferantendiversifizierung, kontinuierliches Monitoring und agile Entwicklungsmethoden.\n\n#### Empfehlungen und nächste Schritte\nEmpfohlene Schritte sind die sofortige Einberufung der Projektteams, die Finalisierung der Projektpläne bis Ende März, monatliche Statusberichte an die Geschäftsleitung, vierteljährliche Review-Meetings mit Stakeholdern und kontinuierliches Monitoring der Marktbedingungen zur strategischen Anpassung.\n\n**Dokument-Metadaten:**\n- Erstellt: 30.03.2025\n- Version: 1.0\n- Status: Finaler Entwurf\n- Autor: Dokumentations-Agent\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_e0722ee1-34f4-4cbf-8ab5-cc0030a82a16", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 25, 2 Dateien", + "type": "info", + "timestamp": "2025-04-04T19:05:28.417505", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_20bee139-4d21-4a62-8a26-b1a4d58d862d", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T19:05:28.421594", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_63554797-d6a8-4879-ad6d-d63ba4cd748b", + "message": "2 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T19:05:28.427505", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_9dee62d4-d57b-4763-b598-1480543c3101", + "message": "Image LF-Current.png analyzed successfully", + "type": "info", + "timestamp": "2025-04-04T19:05:37.821110", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_da65e57d-bad8-4210-8095-c78faf7290cb", + "message": "Image LF-Target.png analyzed successfully", + "type": "info", + "timestamp": "2025-04-04T19:05:49.259901", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c389b9cd-4eff-4420-a84b-a656edc724cb", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T19:05:50.986835", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_2cf35f24-7569-4c6b-af4a-42403c11628d", + "message": "Agent user_agent wurde ausgewählt mit Aufgabe: Bitte fassen Sie die Informationen aus den bereitg...", + "type": "info", + "timestamp": "2025-04-04T19:05:50.991834", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_30387d30-c142-49ee-9c82-dcd33c48c827", + "message": "Workflow wartet auf Benutzereingabe: Bitte fassen Sie die Informationen aus den bereitg...", + "type": "info", + "timestamp": "2025-04-04T19:05:50.995850", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_d442ab73-5123-432e-8612-3c56a78691e1", + "message": "Benutzereingabe empfangen: 25 Zeichen, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T19:06:22.547364", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_55f9e985-0db2-432d-9463-80908478af4d", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T19:06:22.551812", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b3e29f8e-15c0-4fe4-84b0-956571e4b339", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T19:06:24.696072", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_fe814fb4-d8fa-4e4f-82d9-93c226309b3a", + "message": "Agent documentation_agent wurde ausgewählt mit Aufgabe: Erstelle eine Zusammenfassung basierend auf den ve...", + "type": "info", + "timestamp": "2025-04-04T19:06:24.696072", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_327c9e15-3725-4690-ade4-1336f6e566a2", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-04T19:06:24.708608", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_0b2a6bd1-7b05-409e-8c87-43225406ba24", + "message": "Agent documentation_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T19:06:24.712142", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_4a140d68-1b45-47d9-bf0d-a8c030180724", + "message": "Agent 'documentation_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T19:06:24.717061", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_352d6e9f-efd1-4c8b-be5f-a3bd8159d7f3", + "message": "Agent 'documentation_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-04T19:06:24.789773", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b7210290-ea63-4a0f-9b52-e9e61b86394a", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-04T19:06:32.120827", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_5dca41fa-903f-4149-b0bc-64a98802bee0.json b/gwserver/_results/workflow_5dca41fa-903f-4149-b0bc-64a98802bee0.json new file mode 100644 index 00000000..213c7e7b --- /dev/null +++ b/gwserver/_results/workflow_5dca41fa-903f-4149-b0bc-64a98802bee0.json @@ -0,0 +1,447 @@ +{ + "id": "5dca41fa-903f-4149-b0bc-64a98802bee0", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 12:30:35", + "status": "waiting_for_user", + "started_at": "2025-04-04T12:30:35.952782", + "last_activity": "2025-04-04T12:43:09.821854", + "prompt": "describe", + "messages": [ + { + "id": "msg_3925a1b4-df15-451a-86f6-72c50d72a633", + "workflow_id": "5dca41fa-903f-4149-b0bc-64a98802bee0", + "parent_message_id": null, + "started_at": "2025-04-04T12:30:35.964325", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [ + { + "id": 2, + "source": { + "type": "file", + "id": 2, + "name": "LF-Target.png", + "content_type": "image/png", + "size": 256760, + "upload_date": "2025-04-04T12:30:49.639228" + }, + "contents": [ + { + "type": "text", + "text": "Image Analysis:\nThe image is a flowchart depicting a product development and release process involving multiple teams: Product Team, Engineering Team, Q&A Team, and Operations. Here's a detailed breakdown:\n\n### Input\n- **Sources**: Customers, Sales, and Internal Ideas.\n- These inputs feed into the Product Team's processes.\n\n### Product Team\n1. **Discover**\n - **Collect**: Ideas and inputs are gathered.\n - **Qualify**: Analyzed and matched against business priorities.\n\n2. **Define**\n - **Structure & Document**: Write specifications and define acceptance criteria.\n - **Explore & Design**: UI design and experiments, with references to tickets in ClickUp.\n\n3. **Shape**\n - **Roadmap**: For current setup and accelerated market needs.\n - **Scoping**: Define next version's scope.\n - **Manage**: Tickets in Product.\n\n### Engineering Team\n- **Assess**\n - **Manage**: Move assessed tickets to Engineering for future versions.\n - **Estimate**: Assess tickets for implementation, feasibility, and effort.\n\n- **Build**\n - **Manage**: Track progress in the dashboard.\n - **Factory**: Develop tickets in Engineering for the next version.\n\n### Q&A Team\n- **Validate**\n - **Testing**: Test functionality against acceptance criteria.\n - **Analysis**: Analyze tickets, events, and deviations.\n\n### Operations\n1. **Release**\n - **Manage**: Ensure stable changes.\n\n2. **Run & Monitor**\n - **Manage**: Ensure stable operation.\n - **Service & Support**: Deliver first-level support according to agreed SLA.\n\n### Output\n- The final product is the output of this process.\n\n### Tool Integration\n- **Ticketing System**: Visual representation of ticket management.\n- **Roadmap**: Timeline for product development phases.\n- **Management Dashboards**: Displays metrics and progress data.\n\nThe flowchart uses arrows to indicate the flow of processes and interactions between different teams and stages." + } + ] + } + ], + "content": "describe", + "agent_type": null + }, + { + "id": "msg_4c95154a-aede-48af-bd34-5e2b70eb06d4", + "workflow_id": "5dca41fa-903f-4149-b0bc-64a98802bee0", + "parent_message_id": null, + "started_at": "2025-04-04T12:30:51.385403", + "finished_at": "2025-04-04T12:30:51.387796", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "Ich habe als Datenanalyst eine Analyse der bereitgestellten Daten durchgeführt.\n\nHier ist meine detaillierte Analyse:\n1. Die Daten zeigen einen klaren Trend...\n2. Es gibt signifikante Korrelationen zwischen...\n3. Besonders auffällig ist...\n\nMeine Empfehlungen basierend auf der Analyse:\n- Maßnahme 1: ...\n- Maßnahme 2: ...\n- Maßnahme 3: ...", + "agent_type": "analyzer", + "agent_id": "analyst_agent", + "agent_name": "Datenanalyst" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n**Zusammenfassung der Agentenergebnisse**\n\n**Datenanalyse:**\n\n1. **Trends:**\n - Die Daten zeigen einen klaren Trend in Bezug auf [spezifischen Trend beschreiben].\n\n2. **Korrelationen:**\n - Es gibt signifikante Korrelationen zwischen [Variable A] und [Variable B], was auf [Erkenntnis oder Schlussfolgerung] hinweist.\n\n3. **Auffälligkeiten:**\n - Besonders auffällig ist [spezifische Auffälligkeit oder Anomalie], was möglicherweise auf [mögliche Ursache oder Bedeutung] hindeutet.\n\n**Empfehlungen:**\n\n- **Maßnahme 1:** [Beschreibung der ersten Maßnahme, die aufgrund der Analyse empfohlen wird].\n- **Maßnahme 2:** [Beschreibung der zweiten Maßnahme, die aufgrund der Analyse empfohlen wird].\n- **Maßnahme 3:** [Beschreibung der dritten Maßnahme, die aufgrund der Analyse empfohlen wird].\n\nDiese strukturierte Zusammenfassung fasst die wesentlichen Erkenntnisse und Empfehlungen der Datenanalyse zusammen, um gezielte Maßnahmen zu ermöglichen.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true, + "finished_at": "2025-04-04T12:32:56.707742", + "status": "completed" + }, + { + "id": "msg_c31d520e-e024-4d52-92d5-b3769e51b1d0", + "workflow_id": "5dca41fa-903f-4149-b0bc-64a98802bee0", + "parent_message_id": null, + "started_at": "2025-04-04T12:32:56.708199", + "finished_at": null, + "sequence_no": 4, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "mach mir eine zusammenfassung", + "agent_type": null + }, + { + "id": "msg_cca5bf9d-03ef-4176-94d5-5385b4d4a951", + "workflow_id": "5dca41fa-903f-4149-b0bc-64a98802bee0", + "parent_message_id": null, + "started_at": "2025-04-04T12:32:58.809327", + "finished_at": "2025-04-04T12:32:58.811099", + "sequence_no": 5, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "# Bericht - Projektzusammenfassung 2025\n\n## Zusammenfassung\n\nDieses Dokument bietet einen umfassenden Überblick über die strategische Ausrichtung und geplanten Aktivitäten für das Jahr 2025. Es basiert auf den aktuellen Planungsdokumenten und Analysen und dient als Referenz für alle Projektbeteiligten.\n\n## Inhaltsverzeichnis\n\n1. Einleitung und Zielsetzung\n2. Marktanalyse und Strategische Positionierung\n3. Projektplanung und Ressourcenallokation\n4. Budgetierung und Finanzplanung\n5. Meilensteine und Zeitplan\n6. Risikomanagement\n7. Empfehlungen und nächste Schritte\n\n## 1. Einleitung und Zielsetzung\n\nDieses Dokument wurde erstellt, um einen strukturierten Überblick über die geplanten Aktivitäten und strategischen Ziele für das Jahr 2025 zu geben. Die Hauptziele sind:\n\n- Expansion in neue Märkte mit besonderem Fokus auf die APAC-Region\n- Steigerung des Marktanteils in bestehenden Märkten um 5%\n- Entwicklung und Einführung von mindestens zwei neuen Produktlinien\n- Optimierung der Betriebsabläufe zur Kostensenkung um 8%\n\n## 2. Marktanalyse und Strategische Positionierung\n\nDie aktuelle Marktanalyse zeigt folgende Schlüsseltrends:\n\n| Trend | Bedeutung | Implikation |\n|-------|-----------|-------------|\n| Digitalisierung | Hoch | Erhöhte Nachfrage nach integrierten Lösungen |\n| Nachhaltigkeit | Mittel-Hoch | Anpassung von Produkten und Prozessen erforderlich |\n| KI-Integration | Hoch | Wettbewerbsvorteil durch intelligente Produkte |\n\nUnsere strategische Positionierung basiert auf dem Prinzip der differenzierten Qualitätsführerschaft mit starkem Fokus auf Innovationen.\n\n## 3. Projektplanung und Ressourcenallokation\n\nDrei Hauptprojekte wurden für Q2 2025 identifiziert:\n\n1. **Projekt Alpha**: Markteinführung der neuen Produktlinie XYZ\n - Projektleitung: Maria Schmidt\n - Teamgröße: 12 Mitarbeiter\n - Startdatum: 15.04.2025\n\n2. **Projekt Beta**: Implementierung des verbesserten CRM-Systems\n - Projektleitung: Thomas Müller\n - Teamgröße: 8 Mitarbeiter\n - Startdatum: 01.05.2025\n\n3. **Projekt Gamma**: Expansion in die APAC-Region\n - Projektleitung: Sarah Weber\n - Teamgröße: 15 Mitarbeiter\n - Startdatum: 01.06.2025\n\nDie detaillierte Ressourcenallokation ist im Anhang A zu finden.\n\n## 4. Budgetierung und Finanzplanung\n\nDas Gesamtbudget für 2025 beträgt 12,5 Millionen Euro, mit folgender Aufteilung:\n\n- Forschung und Entwicklung: 3,75 Mio. € (30%)\n- Marketing und Vertrieb: 3,125 Mio. € (25%)\n- Betriebskosten: 2,5 Mio. € (20%)\n- Expansion und neue Märkte: 1,875 Mio. € (15%)\n- Reserve und Unvorhergesehenes: 1,25 Mio. € (10%)\n\nDas Budget für Forschung und Entwicklung wurde um 15% im Vergleich zum Vorjahr erhöht.\n\n## 5. Meilensteine und Zeitplan\n\n| Meilenstein | Beschreibung | Termin |\n|-------------|--------------|--------|\n| M1 | Abschluss der Marktforschung für APAC | 31.03.2025 |\n| M2 | Produktprototyp XYZ fertiggestellt | 30.04.2025 |\n| M3 | CRM-System implementiert | 30.06.2025 |\n| M4 | Erste Niederlassung in APAC eröffnet | 31.08.2025 |\n| M5 | Markteinführung Produktlinie XYZ | 30.09.2025 |\n\n## 6. Risikomanagement\n\nIdentifizierte Risiken und Gegenmaßnahmen:\n\n- **Lieferkettenunterbrechungen**\n - Risikostufe: Hoch\n - Maßnahmen: Diversifizierung der Lieferanten, erhöhte Lagerbestände kritischer Komponenten\n\n- **Regulatorische Änderungen**\n - Risikostufe: Mittel\n - Maßnahmen: Kontinuierliches Monitoring, frühzeitige Anpassung der Produkte\n\n- **Verzögerungen bei der Produktentwicklung**\n - Risikostufe: Mittel\n - Maßnahmen: Agile Entwicklungsmethoden, regelmäßige Reviews, Pufferzeiten im Zeitplan\n\n## 7. Empfehlungen und nächste Schritte\n\nBasierend auf der vorliegenden Analyse werden folgende Schritte empfohlen:\n\n1. Sofortige Einberufung der Projektteams und Kick-off-Meetings\n2. Finalisierung der detaillierten Projektpläne bis Ende März\n3. Monatliche Statusberichte an die Geschäftsleitung\n4. Vierteljährliche Review-Meetings mit allen Stakeholdern\n5. Kontinuierliches Monitoring der Marktbedingungen und Anpassung der Strategie bei Bedarf\n\n---\n\n**Dokument-Metadaten:**\n- Erstellt: 30.03.2025\n- Version: 1.0\n- Status: Finaler Entwurf\n- Autor: Dokumentations-Agent", + "agent_type": "documentation", + "agent_id": "documentation_agent", + "agent_name": "Dokumentation" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n### Zusammenfassung der Agentenergebnisse - Projektzusammenfassung 2025\n\n#### Einleitung und Zielsetzung\nDas Dokument bietet einen strukturierten Überblick über die strategischen Ziele und geplanten Aktivitäten für 2025. Hauptziele sind die Expansion in neue Märkte, insbesondere die APAC-Region, die Steigerung des Marktanteils um 5% in bestehenden Märkten, die Entwicklung von zwei neuen Produktlinien und die Optimierung der Betriebsabläufe zur Kostensenkung um 8%.\n\n#### Marktanalyse und Strategische Positionierung\nDie Marktanalyse identifiziert Digitalisierung, Nachhaltigkeit und KI-Integration als Schlüsseltrends. Die strategische Positionierung fokussiert auf differenzierte Qualitätsführerschaft und Innovation.\n\n#### Projektplanung und Ressourcenallokation\nFür Q2 2025 sind drei Hauptprojekte geplant:\n1. **Projekt Alpha**: Einführung der Produktlinie XYZ (Leitung: Maria Schmidt, Start: 15.04.2025)\n2. **Projekt Beta**: Implementierung eines verbesserten CRM-Systems (Leitung: Thomas Müller, Start: 01.05.2025)\n3. **Projekt Gamma**: Expansion in die APAC-Region (Leitung: Sarah Weber, Start: 01.06.2025)\n\n#### Budgetierung und Finanzplanung\nDas Gesamtbudget für 2025 beträgt 12,5 Millionen Euro, aufgeteilt in Forschung und Entwicklung (30%), Marketing und Vertrieb (25%), Betriebskosten (20%), Expansion (15%) und Reserve (10%). Das F&E-Budget wurde um 15% erhöht.\n\n#### Meilensteine und Zeitplan\nWichtige Meilensteine sind der Abschluss der Marktforschung für APAC (31.03.2025), die Fertigstellung des Produktprototyps XYZ (30.04.2025), die Implementierung des CRM-Systems (30.06.2025), die Eröffnung der ersten Niederlassung in APAC (31.08.2025) und die Markteinführung der Produktlinie XYZ (30.09.2025).\n\n#### Risikomanagement\nIdentifizierte Risiken umfassen Lieferkettenunterbrechungen, regulatorische Änderungen und Verzögerungen bei der Produktentwicklung. Gegenmaßnahmen beinhalten die Diversifizierung der Lieferanten, kontinuierliches Monitoring und agile Entwicklungsmethoden.\n\n#### Empfehlungen und nächste Schritte\nEmpfohlen werden die sofortige Einberufung der Projektteams, die Finalisierung der Projektpläne bis Ende März, monatliche Statusberichte an die Geschäftsleitung, vierteljährliche Review-Meetings mit Stakeholdern und kontinuierliches Monitoring der Marktbedingungen zur strategischen Anpassung.\n\n**Dokument-Metadaten:**\n- Erstellt: 30.03.2025\n- Version: 1.0\n- Status: Finaler Entwurf\n- Autor: Dokumentations-Agent\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true, + "finished_at": "2025-04-04T12:33:40.573636", + "status": "completed" + }, + { + "id": "msg_4ce4c40f-8c30-493c-b8db-86a6f8258613", + "workflow_id": "5dca41fa-903f-4149-b0bc-64a98802bee0", + "parent_message_id": null, + "started_at": "2025-04-04T12:33:40.574638", + "finished_at": null, + "sequence_no": 7, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "danke passt", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben keine spezifischen Aufgaben durchgeführt. Gibt es etwas, wobei ich Ihnen helfen kann?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true, + "finished_at": "2025-04-04T12:42:59.735271", + "status": "completed" + }, + { + "id": "msg_3636c7f8-ccfd-442e-9f36-62b684c98dd9", + "workflow_id": "5dca41fa-903f-4149-b0bc-64a98802bee0", + "parent_message_id": null, + "started_at": "2025-04-04T12:42:59.736270", + "finished_at": null, + "sequence_no": 9, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [ + { + "id": 5, + "source": { + "type": "file", + "id": 5, + "name": "auszug_liste_positionen.pdf", + "content_type": "application/pdf", + "size": 299729, + "upload_date": "2025-04-04T12:42:59.825798" + }, + "contents": [ + { + "type": "text", + "text": "\n\n" + } + ] + } + ], + "content": "describe", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Bitte geben Sie weitere Details an, was genau beschrieben werden soll. Handelt es sich um den Inhalt der Datei 'auszug_liste_positionen.pdf' oder benötigen Sie eine allgemeine Beschreibung zu einem anderen Thema?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_e0236c2d-5fa8-4850-a16d-3856919545df", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 8, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T12:30:35.956781", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_5b89f043-4114-40e8-9ccd-fb09b53ff447", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T12:30:35.961315", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_0d92eeb8-0020-4dbf-af09-321dad7302c9", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T12:30:35.967707", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_f5fa4013-a4b3-40d6-862d-589093de946c", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T12:30:51.364528", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_a08f0755-71a5-4c95-a1dd-4de73abb87f7", + "message": "Agent analyst_agent wurde ausgewählt mit Aufgabe: Analysiere das bereitgestellte Bild 'LF-Target.png...", + "type": "info", + "timestamp": "2025-04-04T12:30:51.369488", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_33f63906-58d6-4aa2-938f-a87ffb1ec9c9", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-04T12:30:51.374481", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_fdfc63da-c829-4cf0-9b00-878f63695429", + "message": "Agent analyst_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T12:30:51.379013", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_edfe08a7-2c5f-4ef5-8c82-19edb68f5614", + "message": "Agent 'analyst_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T12:30:51.381967", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_463e1060-abc2-4270-9ea7-7d292fe691b0", + "message": "Agent 'analyst_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-04T12:30:51.417627", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_f62297c3-9e6a-4a50-9f8c-73b882e9988d", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-04T12:30:54.383219", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_67c8e216-fcc2-443d-827f-673ce988a1cf", + "message": "Benutzereingabe empfangen: 29 Zeichen, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T12:32:56.695928", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_cf5be3d1-ca7e-44ab-9f34-0ea8658619e5", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T12:32:56.703644", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_938414fa-f18d-471a-8c04-3e23d8d65952", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T12:32:58.781914", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_e98915d3-6532-423d-8297-f2d1a3e396cb", + "message": "Agent documentation_agent wurde ausgewählt mit Aufgabe: Erstelle eine qualitativ hochwertige Zusammenfassu...", + "type": "info", + "timestamp": "2025-04-04T12:32:58.791904", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c1d1f200-5dc6-4014-a8bd-d09587695e80", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-04T12:32:58.794945", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_399893d0-36af-4c24-8c8e-72ee327fffca", + "message": "Agent documentation_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T12:32:58.798635", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_13841e86-89eb-482a-a2d7-00a29913e7ad", + "message": "Agent 'documentation_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T12:32:58.805398", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_601faa15-66c1-41d4-9137-9bfa33523051", + "message": "Agent 'documentation_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-04T12:32:58.871552", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_87a82511-46e9-4ffe-9a24-8858094a897e", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-04T12:33:03.838535", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_617ce9db-0c39-49e7-91b4-aba831f814ac", + "message": "Benutzereingabe empfangen: 11 Zeichen, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T12:33:40.564652", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_e82c8aef-2432-42ee-a779-a5ffe8d27569", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T12:33:40.568644", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_8038a740-9e80-4b9f-b439-00b81837038a", + "message": "Agenten-Entscheidung abgeschlossen: 0 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T12:33:41.410757", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_40b3a4f9-dc2e-4e8d-8b7a-091f6d8a692e", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben keine spezifischen Aufgaben durc...", + "type": "info", + "timestamp": "2025-04-04T12:33:41.428894", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b937d4a2-9e00-490e-9292-83a4dc103cd8", + "message": "Workflow wurde manuell gestoppt", + "type": "info", + "timestamp": "2025-04-04T12:34:16.730060", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c525a207-4996-434d-81ef-66098542f10a", + "message": "Benutzereingabe empfangen: 8 Zeichen, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T12:42:59.727270", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_1f137348-db99-45ba-aad7-688e88e745f1", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T12:42:59.731273", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ae534cb4-e905-44db-ad5c-e2d31536c651", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T12:42:59.740271", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_e9045871-5476-41ed-9398-1a7963055f93", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T12:43:09.813804", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_6efc035a-a115-402f-8d00-c52994a37f02", + "message": "Agent user_agent wurde ausgewählt mit Aufgabe: Bitte geben Sie weitere Details an, was genau besc...", + "type": "info", + "timestamp": "2025-04-04T12:43:09.817942", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_8314f0eb-047e-4bd6-b91c-40b5d80d5d32", + "message": "Workflow wartet auf Benutzereingabe: Bitte geben Sie weitere Details an, was genau besc...", + "type": "info", + "timestamp": "2025-04-04T12:43:09.821854", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_5dfcf06d-3c21-416e-933f-43d4ebb985ee.json b/gwserver/_results/workflow_5dfcf06d-3c21-416e-933f-43d4ebb985ee.json new file mode 100644 index 00000000..f9e9dd43 --- /dev/null +++ b/gwserver/_results/workflow_5dfcf06d-3c21-416e-933f-43d4ebb985ee.json @@ -0,0 +1,135 @@ +{ + "id": "5dfcf06d-3c21-416e-933f-43d4ebb985ee", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 08:40:39", + "status": "waiting_for_user", + "started_at": "2025-04-04T08:40:40.325539", + "last_activity": "2025-04-04T08:40:45.618927", + "prompt": "bildanalyse", + "messages": [ + { + "id": "msg_b350544b-9815-41cd-82a0-61a0dabf9f7c", + "workflow_id": "5dfcf06d-3c21-416e-933f-43d4ebb985ee", + "parent_message_id": null, + "started_at": "2025-04-04T08:40:40.338165", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "bildanalyse", + "agent_type": null + }, + { + "id": "msg_ed4d1b9f-a576-423c-9ef8-b31d253eff69", + "workflow_id": "5dfcf06d-3c21-416e-933f-43d4ebb985ee", + "parent_message_id": null, + "started_at": "2025-04-04T08:40:42.271629", + "finished_at": "2025-04-04T08:40:42.274633", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "Ich habe als Datenanalyst eine Analyse der bereitgestellten Daten durchgeführt.\n\nHier ist meine detaillierte Analyse:\n1. Die Daten zeigen einen klaren Trend...\n2. Es gibt signifikante Korrelationen zwischen...\n3. Besonders auffällig ist...\n\nMeine Empfehlungen basierend auf der Analyse:\n- Maßnahme 1: ...\n- Maßnahme 2: ...\n- Maßnahme 3: ...", + "agent_type": "analyzer", + "agent_id": "analyst_agent", + "agent_name": "Datenanalyst" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n**Zusammenfassung der Agentenergebnisse**\n\n**Analyseergebnisse:**\n1. **Trend:** Die Daten zeigen einen klaren Trend, der auf [genaue Beschreibung des Trends] hinweist.\n2. **Korrelationen:** Es gibt signifikante Korrelationen zwischen [Variablen oder Faktoren], die auf [Erkenntnisse oder Auswirkungen] schließen lassen.\n3. **Auffälligkeiten:** Besonders auffällig ist [Beschreibung der Auffälligkeit], was auf [mögliche Ursachen oder Konsequenzen] hindeutet.\n\n**Empfehlungen:**\n- **Maßnahme 1:** [Beschreibung der Maßnahme 1], um [Ziel oder erwartetes Ergebnis].\n- **Maßnahme 2:** [Beschreibung der Maßnahme 2], um [Ziel oder erwartetes Ergebnis].\n- **Maßnahme 3:** [Beschreibung der Maßnahme 3], um [Ziel oder erwartetes Ergebnis].\n\nDiese strukturierte Zusammenfassung fasst die wesentlichen Erkenntnisse und Empfehlungen der Datenanalyse zusammen und bietet eine klare Grundlage für weitere Entscheidungen oder Maßnahmen.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_41203d3c-4386-4b7d-b565-36d1bd673106", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 11, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T08:40:40.328540", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_aeed18b4-24c6-4f36-a4c8-8b538298f120", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T08:40:40.330538", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b06a890b-cea3-465d-881f-1fa5327df761", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T08:40:42.244218", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_858e7b8a-46b5-41f5-9c4c-b49d95ca4c2a", + "message": "Agent analyst_agent wurde ausgewählt mit Aufgabe: Führe eine detaillierte Bildanalyse durch, indem d...", + "type": "info", + "timestamp": "2025-04-04T08:40:42.250220", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_69a35683-86f3-4216-b22a-66f18950ca6d", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-04T08:40:42.255668", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_377d1e88-8404-4a1b-8184-055c37c60132", + "message": "Agent analyst_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T08:40:42.261625", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_62c96df8-0062-4704-b7bb-c614898119b6", + "message": "Agent 'analyst_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T08:40:42.266632", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_4085ebd3-774f-4235-8992-821de7e28495", + "message": "Agent 'analyst_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-04T08:40:42.312270", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_2dd140ce-9fe1-43bc-b45a-63c3044aa62b", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-04T08:40:45.618927", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_604b510a-b2f9-48c9-ac5a-7414642b56f6.json b/gwserver/_results/workflow_604b510a-b2f9-48c9-ac5a-7414642b56f6.json new file mode 100644 index 00000000..3c9382bf --- /dev/null +++ b/gwserver/_results/workflow_604b510a-b2f9-48c9-ac5a-7414642b56f6.json @@ -0,0 +1,45 @@ +{ + "id": "604b510a-b2f9-48c9-ac5a-7414642b56f6", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 08:36:04", + "status": "failed", + "started_at": "2025-04-04T08:36:04.440786", + "last_activity": "2025-04-04T08:36:04.460958", + "prompt": "analysiere das bild", + "messages": [], + "logs": [ + { + "id": "log_05752de1-06c2-45a3-a02b-861e085a3d55", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 19, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T08:36:04.445222", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_e9565e91-1b53-4f46-8d70-6bcf76b56a98", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T08:36:04.446230", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_fcb3936f-5e21-452b-8240-993186efe476", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T08:36:04.454315", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_00cf3b9f-302b-47f6-8a1b-816013f56440", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T08:36:04.460958", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_63786d61-0cb0-4488-8cf1-b6bc99350d47.json b/gwserver/_results/workflow_63786d61-0cb0-4488-8cf1-b6bc99350d47.json new file mode 100644 index 00000000..0d97763b --- /dev/null +++ b/gwserver/_results/workflow_63786d61-0cb0-4488-8cf1-b6bc99350d47.json @@ -0,0 +1,255 @@ +{ + "id": "63786d61-0cb0-4488-8cf1-b6bc99350d47", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 5.4.2025, 00:54:24", + "status": "waiting_for_user", + "started_at": "2025-04-05T00:54:24.866935", + "last_activity": "2025-04-05T00:56:26.418808", + "prompt": "summarize the difference between pictures", + "messages": [ + { + "id": "msg_7c42c416-0410-4718-b806-22462129fa1c", + "workflow_id": "63786d61-0cb0-4488-8cf1-b6bc99350d47", + "parent_message_id": null, + "started_at": "2025-04-05T00:54:24.897456", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [ + { + "id": 3, + "source": { + "type": "file", + "id": 3, + "name": "LF-Current.png", + "content_type": "image/png", + "size": 126277, + "upload_date": "2025-04-05T00:54:48.699130" + }, + "contents": [ + { + "type": "text", + "text": "Image Analysis:\nThe image is a flowchart illustrating a product development process involving both a Product Team and an Engineering Team. Here's a detailed breakdown:\n\n### Input\n- **Sources**: Customers, Sales, Our Ideas\n- **Purpose**: To gather initial ideas and inputs for the product development process.\n\n### Product Team\n1. **Discover**\n - **Collect**: Ideas & Inputs\n - **Qualify**: Analyze and match within the team\n\n2. **Define**\n - **Structure & Document**: Write specifications, define acceptance criteria (Product > Inputs & Ideas)\n - **Explore & Design**: UI Design, Experiments, etc. (using tools like Miro)\n\n3. **Shape**\n - **Roadmap**: Define a roadmap\n - **Scoping**: Define next version's scope\n - **Manage**: Tickets in Product\n\n### Engineering Team\n1. **Build**\n - **Manage**: Track progress in the dashboard\n - **Factory**: Develop tickets in Engineering > Next Version\n\n2. **Release**\n - **Manage**: Ensure stable changes\n\n3. **Run & Monitor**\n - **Manage**: Ensure stable operation\n - **Service & Support**: Deliver 1st Level support according to agreed SLA\n\n4. **Assess**\n - **Manage**: Move assessed tickets to Engineering > Future Versions\n - **Estimate**: Assess tickets in \"Product > Analysis\" to define implementation, feasibility, and effort\n\n### Output\n- **Product**: The final product is the output of this process.\n\n### Tool Integration\n- **Ticketing System**: Used for managing various stages like Inputs & Ideas, Exploration, Analysis, Future Versions, etc.\n- **Roadmap**: For planning\n- **Management Dashboards**: For overseeing the process\n\nThe flowchart uses arrows to indicate the progression and feedback loops between stages, emphasizing a structured and iterative approach to product development." + } + ] + }, + { + "id": 4, + "source": { + "type": "file", + "id": 4, + "name": "LF-Details.png", + "content_type": "image/png", + "size": 253009, + "upload_date": "2025-04-05T00:54:48.699838" + }, + "contents": [ + { + "type": "text", + "text": "Image Analysis:\nThe image is a flowchart illustrating a product development process involving multiple teams: Product Team, Q&A Team, Engineering Team, and Operations. Here's a detailed breakdown:\n\n### Input\n- **Sources**: Customers, Sales, Our Ideas\n- **Process**: Inputs are collected and qualified against business priorities.\n\n### Product Team\n1. **Discover**\n - **Collect**: Ideas and inputs.\n - **Qualify**: Analyze and match against business priorities.\n\n2. **Define**\n - **Structure & Document**: Write specifications and define acceptance criteria.\n - **Explore & Design**: UI design, experiments, and reference tickets in ClickUp.\n\n3. **Shape**\n - **Roadmap**: Define roadmap to meet opportunities and protect development stability.\n - **Scoping**: Define next version scope.\n - **Manage**: Tickets in Product.\n\n### Engineering Team\n- **Assess**\n - **Manage**: Move assessed tickets to future versions.\n - **Estimate**: Assess implementation, feasibility, and effort.\n\n- **Build**\n - **Manage**: Track progress in the dashboard.\n - **Factory**: Develop tickets in the next version.\n\n### Q&A Team\n- **Validate**\n - **Testing**: Test functionality against acceptance.\n - **Analysis**: Analyze tickets, events, deviations.\n\n### Operations\n1. **Release**\n - **Manage**: Ensure stable changes.\n\n2. **Run & Monitor**\n - **Manage**: Ensure stable operation.\n - **Service & Support**: Deliver 1st level support according to agreed SLA.\n\n### Output\n- **Product**: The final output of the process.\n\n### Tool Integration\n- **Ticketing System**: Visual representation of ticket management.\n- **Roadmap**: Timeline view of project phases.\n- **Management Dashboards**: Visual data and analytics display.\n\nThe flowchart uses arrows to indicate the flow of processes and interactions between different teams and stages." + } + ] + } + ], + "content": "summarize the difference between pictures", + "agent_type": null + }, + { + "id": "msg_ea3442ca-9e0d-46d1-9801-df158a945235", + "workflow_id": "63786d61-0cb0-4488-8cf1-b6bc99350d47", + "parent_message_id": null, + "started_at": "2025-04-05T00:54:50.240558", + "finished_at": "2025-04-05T00:54:50.244397", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "Ich habe als Datenanalyst eine Analyse der bereitgestellten Daten durchgeführt.\n\nHier ist meine detaillierte Analyse:\n1. Die Daten zeigen einen klaren Trend...\n2. Es gibt signifikante Korrelationen zwischen...\n3. Besonders auffällig ist...\n\nMeine Empfehlungen basierend auf der Analyse:\n- Maßnahme 1: ...\n- Maßnahme 2: ...\n- Maßnahme 3: ...", + "agent_type": "analyzer", + "agent_id": "analyst_agent", + "agent_name": "Datenanalyst" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n**Zusammenfassung der Agentenergebnisse**\n\n**Analyseergebnisse:**\n1. **Trend**: Die Daten zeigen einen klaren Trend, der auf bestimmte Muster oder Entwicklungen hinweist.\n2. **Korrelationen**: Es wurden signifikante Korrelationen zwischen bestimmten Variablen festgestellt, die auf mögliche Zusammenhänge oder Einflussfaktoren hindeuten.\n3. **Auffälligkeiten**: Besonders auffällig ist ein bestimmtes Merkmal oder eine Anomalie in den Daten, die weiter untersucht werden sollte.\n\n**Empfehlungen:**\n1. **Maßnahme 1**: Basierend auf den identifizierten Trends und Korrelationen wird empfohlen, eine spezifische Maßnahme zu ergreifen, um die positiven Entwicklungen zu fördern oder negative Einflüsse zu minimieren.\n2. **Maßnahme 2**: Eine weitere Maßnahme sollte sich auf die Optimierung bestimmter Prozesse oder Strategien konzentrieren, um die Effizienz zu steigern.\n3. **Maßnahme 3**: Es wird empfohlen, zusätzliche Untersuchungen oder Analysen durchzuführen, um die auffälligen Merkmale genauer zu verstehen und entsprechende Anpassungen vorzunehmen.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true, + "finished_at": "2025-04-05T00:56:25.504941", + "status": "completed" + }, + { + "id": "msg_38ad0969-2b5e-4556-8f84-9a4cd35bd997", + "workflow_id": "63786d61-0cb0-4488-8cf1-b6bc99350d47", + "parent_message_id": null, + "started_at": "2025-04-05T00:56:25.505930", + "finished_at": null, + "sequence_no": 4, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "explain", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben keine spezifischen Aufgaben durchgeführt. Gibt es etwas, wobei ich Ihnen helfen kann?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_2cc99a49-e6a2-4836-9ba1-df9260254a1b", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 41, 2 Dateien", + "type": "info", + "timestamp": "2025-04-05T00:54:24.884500", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_d5ac82c2-cb29-4494-be02-7aaa5463f9c5", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-05T00:54:24.890921", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_6ec36d51-a983-4389-8d90-75e25efb9918", + "message": "2 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-05T00:54:24.905468", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_55a595c2-d7e5-440f-96c5-c698e4c8ac1d", + "message": "Image LF-Current.png analyzed successfully", + "type": "info", + "timestamp": "2025-04-05T00:54:36.561112", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b45b85db-b088-4f7e-a1d0-7a4dafba2b4e", + "message": "Image LF-Details.png analyzed successfully", + "type": "info", + "timestamp": "2025-04-05T00:54:48.683950", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_f5deaffb-71a1-4b07-8f2a-9a6f502afd7e", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-05T00:54:50.202945", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_271842dc-c4cb-48a0-8610-f0294d15317b", + "message": "Agent analyst_agent wurde ausgewählt mit Aufgabe: Vergleiche die beiden bereitgestellten Flussdiagra...", + "type": "info", + "timestamp": "2025-04-05T00:54:50.202945", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_939f8604-4696-4067-b821-08b009f6ec69", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-05T00:54:50.216864", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ec82f11e-0fa6-4241-8784-fe8177d15d62", + "message": "Agent analyst_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-05T00:54:50.224726", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_67f34254-00fc-4335-bc47-748f1e1d4583", + "message": "Agent 'analyst_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-05T00:54:50.234031", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_aa031aee-a36f-455e-a7b3-ae1aa21c7113", + "message": "Agent 'analyst_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-05T00:54:50.310788", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_152ab1a8-2268-4e58-8856-f31531e63e71", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-05T00:54:54.216258", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_fa476706-857b-4804-b626-7078bd8288ab", + "message": "Benutzereingabe empfangen: 7 Zeichen, 0 Dateien", + "type": "info", + "timestamp": "2025-04-05T00:56:25.488863", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_8de2ebde-6902-4c24-9e75-d922fb1d0855", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-05T00:56:25.498949", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_d11dd7e6-5579-47b0-9f5c-1579c2926d97", + "message": "Agenten-Entscheidung abgeschlossen: 0 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-05T00:56:26.408807", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_3c0d2619-9931-4a41-bcc0-eed1d52aa9ef", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben keine spezifischen Aufgaben durc...", + "type": "info", + "timestamp": "2025-04-05T00:56:26.418808", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_64112953-2389-40bd-be74-f362083aefa4.json b/gwserver/_results/workflow_64112953-2389-40bd-be74-f362083aefa4.json new file mode 100644 index 00000000..7ccca3ad --- /dev/null +++ b/gwserver/_results/workflow_64112953-2389-40bd-be74-f362083aefa4.json @@ -0,0 +1,45 @@ +{ + "id": "64112953-2389-40bd-be74-f362083aefa4", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 12:19:45", + "status": "failed", + "started_at": "2025-04-04T12:19:46.195692", + "last_activity": "2025-04-04T12:19:52.771879", + "prompt": "describe", + "messages": [], + "logs": [ + { + "id": "log_10ae41d3-0038-4aef-9477-63a98028748c", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 8, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T12:19:46.199692", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_738f2c68-3e54-4b44-a46e-9cd7f3bf2318", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T12:19:46.202693", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b1c306aa-8d64-47c2-a61f-1d8df6e297e3", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T12:19:46.210206", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_0912ba5f-5f3f-486b-8c9c-af404fcbf45e", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T12:19:52.771879", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_672eb0c0-2899-4d52-b5fd-c13700e06166.json b/gwserver/_results/workflow_672eb0c0-2899-4d52-b5fd-c13700e06166.json new file mode 100644 index 00000000..cca3ff52 --- /dev/null +++ b/gwserver/_results/workflow_672eb0c0-2899-4d52-b5fd-c13700e06166.json @@ -0,0 +1,135 @@ +{ + "id": "672eb0c0-2899-4d52-b5fd-c13700e06166", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 6.4.2025, 11:21:08", + "status": "waiting_for_user", + "started_at": "2025-04-06T11:21:08.542845", + "last_activity": "2025-04-06T11:21:11.973078", + "prompt": "bitte mache mir eine webanalyse, wer bei ValueOn AG arbeitet", + "messages": [ + { + "id": "msg_49c92277-01db-4df5-93e8-70c36d3a2fbf", + "workflow_id": "672eb0c0-2899-4d52-b5fd-c13700e06166", + "parent_message_id": null, + "started_at": "2025-04-06T11:21:08.563235", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "bitte mache mir eine webanalyse, wer bei ValueOn AG arbeitet", + "agent_type": null + }, + { + "id": "msg_4e3f7e37-b965-4b34-8b59-0f5caefd90d9", + "workflow_id": "672eb0c0-2899-4d52-b5fd-c13700e06166", + "parent_message_id": null, + "started_at": "2025-04-06T11:21:10.098850", + "finished_at": "2025-04-06T11:21:10.102850", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": " [STATUS: ERGEBNIS]", + "agent_type": "scraper", + "agent_id": "webcrawler_agent", + "agent_name": "Webscraper" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\nEs scheint, dass die Ergebnisse des Webscrapers nicht korrekt eingefügt wurden, da nur ein Platzhaltertext vorhanden ist. Um eine aussagekräftige Zusammenfassung zu erstellen, benötige ich die tatsächlichen Ergebnisse oder Daten, die der Webscraper gesammelt hat. Bitte stellen Sie sicher, dass die relevanten Informationen bereitgestellt werden, damit ich Ihnen eine strukturierte und prägnante Zusammenfassung bieten kann.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_756d30d3-c592-45e6-ae78-e183e1f4ebe3", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 60, 0 Dateien", + "type": "info", + "timestamp": "2025-04-06T11:21:08.549460", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_24146d34-fbd0-4966-983e-50af3cc8d523", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-06T11:21:08.555579", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_19daf2c0-e83c-427c-b94e-28b988eae4cd", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-06T11:21:10.064915", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_e03fb9ff-d821-49b1-ab65-2bb416577f5f", + "message": "Agent webcrawler_agent wurde ausgewählt mit Aufgabe: Führe eine Webrecherche durch, um Informationen da...", + "type": "info", + "timestamp": "2025-04-06T11:21:10.071916", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_bbfd2df4-b0db-4c19-85e2-4c8924c95192", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-06T11:21:10.077675", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_6f3ca6b7-91d7-4741-8c7c-11b6f8281631", + "message": "Agent webcrawler_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T11:21:10.083879", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_f0aee81e-d944-4a84-9dac-93fbcffaa56a", + "message": "Agent 'webcrawler_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T11:21:10.089879", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_6193f0ef-9b7e-4bfd-8c25-9dbb76b1fe8b", + "message": "Agent 'webcrawler_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-06T11:21:10.156426", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_bb734098-7037-49db-8b0e-a8c0a6d03e25", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-06T11:21:11.973078", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_6ed530e1-1db1-44a4-8c15-e8f6ac4c2359.json b/gwserver/_results/workflow_6ed530e1-1db1-44a4-8c15-e8f6ac4c2359.json new file mode 100644 index 00000000..95a514ff --- /dev/null +++ b/gwserver/_results/workflow_6ed530e1-1db1-44a4-8c15-e8f6ac4c2359.json @@ -0,0 +1,241 @@ +{ + "id": "6ed530e1-1db1-44a4-8c15-e8f6ac4c2359", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 00:45:27", + "status": "waiting_for_user", + "started_at": "2025-04-04T00:45:27.550708", + "last_activity": "2025-04-04T00:45:38.824553", + "prompt": "Recherchiere die aktuellen Markttrends und Entwicklungen im Bereich [THEMA]. Sammle Informationen zu führenden Unternehmen, innovativen Produkten oder Dienstleistungen und aktuellen Herausforderungen. Präsentiere die Ergebnisse in einer strukturierten Übersicht mit relevanten Daten und Quellen.", + "messages": [ + { + "id": "msg_a493d53d-0340-411c-83e7-35005d59289b", + "workflow_id": "6ed530e1-1db1-44a4-8c15-e8f6ac4c2359", + "parent_message_id": null, + "started_at": "2025-04-04T00:45:27.564674", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "Recherchiere die aktuellen Markttrends und Entwicklungen im Bereich [THEMA]. Sammle Informationen zu führenden Unternehmen, innovativen Produkten oder Dienstleistungen und aktuellen Herausforderungen. Präsentiere die Ergebnisse in einer strukturierten Übersicht mit relevanten Daten und Quellen.", + "agent_type": null + }, + { + "id": "msg_5068ba2e-0f72-4ab6-95df-4d54390ea346", + "workflow_id": "6ed530e1-1db1-44a4-8c15-e8f6ac4c2359", + "parent_message_id": null, + "started_at": "2025-04-04T00:45:30.550628", + "finished_at": "2025-04-04T00:45:30.552624", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "Ich habe als Webscraper folgende Informationen zum Thema recherchiert:\n\n## Überblick der Rechercheergebnisse\n\nBasierend auf der Anfrage habe ich verschiedene Quellen konsultiert und folgende Schlüsselinformationen gefunden:\n\n### Aktuelle Markttrends\n- Der Markt zeigt ein Wachstum von 8,5% im Vergleich zum Vorjahr\n- Führende Unternehmen investieren verstärkt in nachhaltige Technologien\n- Neue regulatorische Anforderungen beeinflussen die Produktentwicklung\n\n### Technologische Entwicklungen\n- KI-basierte Lösungen gewinnen zunehmend an Bedeutung\n- Erhöhte Nachfrage nach integrierten Cloud-Diensten\n- Sicherheitsaspekte werden prioritär behandelt\n\n### Relevante Quellen\n1. Market Research Institute (2025): \"Industry Analysis Report\" - marketresearch.org/report2025\n2. TechInsights Blog (März 2025): \"Technology Trends\" - techinsights.com/trends\n3. Regulatory Commission (Februar 2025): \"New Guidelines\" - regcom.gov/guidelines\n\n## Detaillierte Ergebnisse\n\nDie Recherche zeigt, dass der Markt durch folgende Faktoren beeinflusst wird:\n[...weitere detaillierte Informationen...]\n\n## Fazit und Empfehlungen\n\nBasierend auf den recherchierten Informationen empfehle ich:\n1. Fokussierung auf die Entwicklung nachhaltiger Lösungen\n2. Integration von KI-Funktionalitäten in bestehende Produkte\n3. Anpassung an neue regulatorische Anforderungen", + "agent_type": "scraper", + "agent_id": "webcrawler_agent", + "agent_name": "Webscraper" + }, + { + "id": "msg_88a8013a-945c-4e2f-bc59-8d612b365bf1", + "workflow_id": "6ed530e1-1db1-44a4-8c15-e8f6ac4c2359", + "parent_message_id": null, + "started_at": "2025-04-04T00:45:30.607025", + "finished_at": "2025-04-04T00:45:30.609025", + "sequence_no": 3, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "Ich habe als Datenanalyst eine Analyse der bereitgestellten Daten durchgeführt.\n\nHier ist meine detaillierte Analyse:\n1. Die Daten zeigen einen klaren Trend...\n2. Es gibt signifikante Korrelationen zwischen...\n3. Besonders auffällig ist...\n\nMeine Empfehlungen basierend auf der Analyse:\n- Maßnahme 1: ...\n- Maßnahme 2: ...\n- Maßnahme 3: ...", + "agent_type": "analyzer", + "agent_id": "analyst_agent", + "agent_name": "Datenanalyst" + }, + { + "id": "msg_c301c10f-4cc1-4679-9df9-30454734d2cf", + "workflow_id": "6ed530e1-1db1-44a4-8c15-e8f6ac4c2359", + "parent_message_id": null, + "started_at": "2025-04-04T00:45:30.673152", + "finished_at": "2025-04-04T00:45:30.675153", + "sequence_no": 4, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "# Bericht - Projektzusammenfassung 2025\n\n## Zusammenfassung\n\nDieses Dokument bietet einen umfassenden Überblick über die strategische Ausrichtung und geplanten Aktivitäten für das Jahr 2025. Es basiert auf den aktuellen Planungsdokumenten und Analysen und dient als Referenz für alle Projektbeteiligten.\n\n## Inhaltsverzeichnis\n\n1. Einleitung und Zielsetzung\n2. Marktanalyse und Strategische Positionierung\n3. Projektplanung und Ressourcenallokation\n4. Budgetierung und Finanzplanung\n5. Meilensteine und Zeitplan\n6. Risikomanagement\n7. Empfehlungen und nächste Schritte\n\n## 1. Einleitung und Zielsetzung\n\nDieses Dokument wurde erstellt, um einen strukturierten Überblick über die geplanten Aktivitäten und strategischen Ziele für das Jahr 2025 zu geben. Die Hauptziele sind:\n\n- Expansion in neue Märkte mit besonderem Fokus auf die APAC-Region\n- Steigerung des Marktanteils in bestehenden Märkten um 5%\n- Entwicklung und Einführung von mindestens zwei neuen Produktlinien\n- Optimierung der Betriebsabläufe zur Kostensenkung um 8%\n\n## 2. Marktanalyse und Strategische Positionierung\n\nDie aktuelle Marktanalyse zeigt folgende Schlüsseltrends:\n\n| Trend | Bedeutung | Implikation |\n|-------|-----------|-------------|\n| Digitalisierung | Hoch | Erhöhte Nachfrage nach integrierten Lösungen |\n| Nachhaltigkeit | Mittel-Hoch | Anpassung von Produkten und Prozessen erforderlich |\n| KI-Integration | Hoch | Wettbewerbsvorteil durch intelligente Produkte |\n\nUnsere strategische Positionierung basiert auf dem Prinzip der differenzierten Qualitätsführerschaft mit starkem Fokus auf Innovationen.\n\n## 3. Projektplanung und Ressourcenallokation\n\nDrei Hauptprojekte wurden für Q2 2025 identifiziert:\n\n1. **Projekt Alpha**: Markteinführung der neuen Produktlinie XYZ\n - Projektleitung: Maria Schmidt\n - Teamgröße: 12 Mitarbeiter\n - Startdatum: 15.04.2025\n\n2. **Projekt Beta**: Implementierung des verbesserten CRM-Systems\n - Projektleitung: Thomas Müller\n - Teamgröße: 8 Mitarbeiter\n - Startdatum: 01.05.2025\n\n3. **Projekt Gamma**: Expansion in die APAC-Region\n - Projektleitung: Sarah Weber\n - Teamgröße: 15 Mitarbeiter\n - Startdatum: 01.06.2025\n\nDie detaillierte Ressourcenallokation ist im Anhang A zu finden.\n\n## 4. Budgetierung und Finanzplanung\n\nDas Gesamtbudget für 2025 beträgt 12,5 Millionen Euro, mit folgender Aufteilung:\n\n- Forschung und Entwicklung: 3,75 Mio. € (30%)\n- Marketing und Vertrieb: 3,125 Mio. € (25%)\n- Betriebskosten: 2,5 Mio. € (20%)\n- Expansion und neue Märkte: 1,875 Mio. € (15%)\n- Reserve und Unvorhergesehenes: 1,25 Mio. € (10%)\n\nDas Budget für Forschung und Entwicklung wurde um 15% im Vergleich zum Vorjahr erhöht.\n\n## 5. Meilensteine und Zeitplan\n\n| Meilenstein | Beschreibung | Termin |\n|-------------|--------------|--------|\n| M1 | Abschluss der Marktforschung für APAC | 31.03.2025 |\n| M2 | Produktprototyp XYZ fertiggestellt | 30.04.2025 |\n| M3 | CRM-System implementiert | 30.06.2025 |\n| M4 | Erste Niederlassung in APAC eröffnet | 31.08.2025 |\n| M5 | Markteinführung Produktlinie XYZ | 30.09.2025 |\n\n## 6. Risikomanagement\n\nIdentifizierte Risiken und Gegenmaßnahmen:\n\n- **Lieferkettenunterbrechungen**\n - Risikostufe: Hoch\n - Maßnahmen: Diversifizierung der Lieferanten, erhöhte Lagerbestände kritischer Komponenten\n\n- **Regulatorische Änderungen**\n - Risikostufe: Mittel\n - Maßnahmen: Kontinuierliches Monitoring, frühzeitige Anpassung der Produkte\n\n- **Verzögerungen bei der Produktentwicklung**\n - Risikostufe: Mittel\n - Maßnahmen: Agile Entwicklungsmethoden, regelmäßige Reviews, Pufferzeiten im Zeitplan\n\n## 7. Empfehlungen und nächste Schritte\n\nBasierend auf der vorliegenden Analyse werden folgende Schritte empfohlen:\n\n1. Sofortige Einberufung der Projektteams und Kick-off-Meetings\n2. Finalisierung der detaillierten Projektpläne bis Ende März\n3. Monatliche Statusberichte an die Geschäftsleitung\n4. Vierteljährliche Review-Meetings mit allen Stakeholdern\n5. Kontinuierliches Monitoring der Marktbedingungen und Anpassung der Strategie bei Bedarf\n\n---\n\n**Dokument-Metadaten:**\n- Erstellt: 30.03.2025\n- Version: 1.0\n- Status: Finaler Entwurf\n- Autor: Dokumentations-Agent", + "agent_type": "documentation", + "agent_id": "documentation_agent", + "agent_name": "Dokumentation" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n### Zusammenfassung der Agentenergebnisse\n\n#### Webscraper-Ergebnisse\n\n**Markttrends:**\n- Der Markt wächst um 8,5% im Vergleich zum Vorjahr.\n- Unternehmen investieren verstärkt in nachhaltige Technologien.\n- Neue regulatorische Anforderungen beeinflussen die Produktentwicklung.\n\n**Technologische Entwicklungen:**\n- KI-basierte Lösungen gewinnen an Bedeutung.\n- Es gibt eine erhöhte Nachfrage nach integrierten Cloud-Diensten.\n- Sicherheitsaspekte werden prioritär behandelt.\n\n**Empfehlungen:**\n1. Entwicklung nachhaltiger Lösungen.\n2. Integration von KI-Funktionalitäten in bestehende Produkte.\n3. Anpassung an neue regulatorische Anforderungen.\n\n#### Datenanalyst-Ergebnisse\n\n**Analyse:**\n- Die Daten zeigen klare Trends und signifikante Korrelationen.\n- Besondere Auffälligkeiten wurden identifiziert.\n\n**Empfehlungen:**\n- Maßnahme 1: [Details fehlen]\n- Maßnahme 2: [Details fehlen]\n- Maßnahme 3: [Details fehlen]\n\n#### Dokumentationsergebnisse\n\n**Strategische Ziele 2025:**\n- Expansion in neue Märkte, insbesondere APAC.\n- Steigerung des Marktanteils um 5%.\n- Einführung von zwei neuen Produktlinien.\n- Optimierung der Betriebsabläufe zur Kostensenkung um 8%.\n\n**Marktanalyse:**\n- Digitalisierung und KI-Integration sind hochrelevant.\n- Nachhaltigkeit erfordert Anpassungen in Produkten und Prozessen.\n\n**Projektplanung:**\n- Drei Hauptprojekte für Q2 2025: Markteinführung neuer Produktlinie, CRM-System-Implementierung, Expansion in APAC.\n- Detaillierte Ressourcenallokation und Budgetierung sind geplant.\n\n**Budgetierung:**\n- Gesamtbudget: 12,5 Millionen Euro.\n- Erhöhung des F&E-Budgets um 15% im Vergleich zum Vorjahr.\n\n**Meilensteine:**\n- Wichtige Termine für Marktforschung, Produktprototypen und Markteinführungen sind festgelegt.\n\n**Risikomanagement:**\n- Risiken wie Lieferkettenunterbrechungen und regulatorische Änderungen wurden identifiziert und Gegenmaßnahmen geplant.\n\n**Empfohlene Schritte:**\n1. Einberufung der Projektteams und Kick-off-Meetings.\n2. Finalisierung der Projektpläne bis Ende März.\n3. Monatliche Statusberichte und vierteljährliche Review-Meetings.\n4. Kontinuierliches Monitoring der Marktbedingungen.\n\nDiese strukturierte Zusammenfassung bietet einen umfassenden Überblick über die aktuellen Markttrends, technologischen Entwicklungen und strategischen Planungen für das Jahr 2025. Die Empfehlungen und geplanten Maßnahmen sind darauf ausgerichtet, die Wettbewerbsfähigkeit zu steigern und auf Marktveränderungen flexibel zu reagieren.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_3cbd510b-dfa9-48bc-b723-b45c28b1e2ea", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 295, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T00:45:27.553357", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_eb9464e3-1098-45b9-9979-da977cac8860", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T00:45:27.558350", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_a61b3400-c453-4eaf-838c-f25e9dfe8299", + "message": "Agenten-Entscheidung abgeschlossen: 3 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T00:45:30.504627", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_27923a95-8c01-4af5-a605-dbf5b4508c7e", + "message": "Agent webcrawler_agent wurde ausgewählt mit Aufgabe: Recherchiere die aktuellen Markttrends und Entwick...", + "type": "info", + "timestamp": "2025-04-04T00:45:30.511634", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_47f3aa2f-72e6-4c6b-a03a-0c4980863959", + "message": "Agent analyst_agent wurde ausgewählt mit Aufgabe: Analysiere die gesammelten Informationen zu den ak...", + "type": "info", + "timestamp": "2025-04-04T00:45:30.518629", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_be298605-e1ee-4037-a4b6-9cff8c756446", + "message": "Agent documentation_agent wurde ausgewählt mit Aufgabe: Erstelle eine strukturierte Übersicht der Ergebnis...", + "type": "info", + "timestamp": "2025-04-04T00:45:30.525628", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_55ae1fd5-b333-4a51-9bbb-904e8b057fcf", + "message": "3 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-04T00:45:30.533628", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_8f8f2c2b-bb1c-464d-9c77-f388b43ef838", + "message": "Agent webcrawler_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T00:45:30.540630", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_9b3968e8-06c7-4028-972a-395e4e5a6949", + "message": "Agent 'webcrawler_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T00:45:30.545627", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_d61bc42d-de4d-4676-a8e9-3e1990491252", + "message": "Agent 'webcrawler_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-04T00:45:30.594489", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_9b87cb6e-d92a-4899-b0b7-fa36aff18d06", + "message": "Agent analyst_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T00:45:30.598523", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_99d6ee40-013a-4f1f-a3a4-611e9357f8df", + "message": "Agent 'analyst_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T00:45:30.603020", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_0f6a7b3f-0437-4348-b674-41911162ba95", + "message": "Agent 'analyst_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-04T00:45:30.661810", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_872e9560-bd8e-46b9-bb15-7adf9cffe4fe", + "message": "Agent documentation_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T00:45:30.665125", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_e1a10c7d-de3e-4c34-8003-8cbbca1529c3", + "message": "Agent 'documentation_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-04T00:45:30.669158", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_71bb1ebc-b82c-4a95-837f-3c99e6bbeb89", + "message": "Agent 'documentation_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-04T00:45:30.739265", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_9761dcee-1806-410c-a32f-20cb358d0131", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-04T00:45:38.824553", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_704e5307-6075-45c4-94eb-8de2a5d3d5ff.json b/gwserver/_results/workflow_704e5307-6075-45c4-94eb-8de2a5d3d5ff.json new file mode 100644 index 00000000..4fad41df --- /dev/null +++ b/gwserver/_results/workflow_704e5307-6075-45c4-94eb-8de2a5d3d5ff.json @@ -0,0 +1,129 @@ +{ + "id": "704e5307-6075-45c4-94eb-8de2a5d3d5ff", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 6.4.2025, 23:43:44", + "status": "completed", + "started_at": "2025-04-06T23:43:44.430733", + "last_activity": "2025-04-06T23:46:40.231556", + "prompt": "kannst du mir eine websuche machen, wer ki-agentensysteme entwickelt?", + "messages": [ + { + "id": "msg_14b97e21-2239-4a20-b8d9-f211bb1db107", + "workflow_id": "704e5307-6075-45c4-94eb-8de2a5d3d5ff", + "parent_message_id": null, + "started_at": "2025-04-06T23:43:44.468477", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "kannst du mir eine websuche machen, wer ki-agentensysteme entwickelt?", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n**Zusammenfassung der Agentenergebnisse**\n\n**1. Überblick über KI-Agentensysteme**\n- **Definition und Zweck**: KI-Agentensysteme sind fortschrittliche Softwareprogramme, die repetitive Aufgaben automatisieren, um Effizienz und Produktivität in Unternehmen zu steigern. Sie sind in der Lage, sowohl einfache als auch komplexe Aufgaben zu übernehmen und Entscheidungen ähnlich wie Menschen zu treffen.\n- **Arten von KI-Agenten**: Es gibt autonome, vertikale, aufgabenbezogene und Workflow-Agenten. Autonome Agenten agieren unabhängig, vertikale Agenten sind branchenspezifisch, aufgabenbezogene Agenten sind flexibel und kostengünstig, während Workflow-Agenten Prozesse automatisieren.\n\n**2. Führende Unternehmen und Plattformen**\n- **Operaide AI**: Spezialisiert auf die Entwicklung von KI-Agentensystemen zur Optimierung von Unternehmensprozessen. Die Plattform ist skalierbar und in bestehende IT-Systeme integrierbar.\n- **LangChain, LlamaIndex, Botpress**: Bieten spezialisierte Lösungen für kontextbezogene Agenten, Datenintegration und Kundeninteraktionen.\n- **Große Technologieunternehmen**: Google, Amazon, Microsoft und IBM treiben die Entwicklung von KI-Agenten voran, mit Plattformen wie Google Assistant, Amazon Alexa und IBM Watson.\n- **Europäische Unternehmen**: DeepMind und Aleph Alpha zeichnen sich durch ethische Standards und Datenschutz aus.\n\n**3. Anwendungsbereiche und Vorteile**\n- **Branchenübergreifende Anwendungen**: KI-Agenten werden in Kundendienst, Vertrieb, Marketing, Logistik, Gesundheitswesen und Finanzsektor eingesetzt.\n- **Vorteile**: Sie bieten gesteigerte Effizienz, verbesserte Kundenerlebnisse und die Fähigkeit, in großem Umfang zu arbeiten. Sie helfen, Arbeitsabläufe zu optimieren und datengesteuerte Einblicke zu gewinnen.\n\n**4. Herausforderungen und Empfehlungen**\n- **Herausforderungen**: Die Implementierung erfordert sorgfältige Planung, kontinuierliche Optimierung und die Einhaltung ethischer Standards.\n- **Empfehlungen**: Unternehmen sollten ihre spezifischen Bedürfnisse ermitteln, geeignete Plattformen auswählen und die Agenten entsprechend trainieren und testen. Die Integration von KI-Agenten sollte strategisch erfolgen, um Wettbewerbsvorteile zu sichern.\n\n**5. Zukünftige Entwicklungen**\n- **Prognosen**: Analysten erwarten, dass KI-Agenten bis 2025 einen \"Chat-GPT-Moment\" erleben werden, was einen bedeutenden Wendepunkt für die Technologie darstellt.\n- **Innovationen**: Unternehmen wie OpenAI und Google entwickeln autonome Agenten, die ohne menschliches Eingreifen arbeiten können. Die dritte Welle der KI wird durch solche autonomen Agenten geprägt sein.\n\nInsgesamt zeigt sich, dass KI-Agentensysteme eine bedeutende Rolle in der Zukunft der Unternehmensprozesse spielen werden, indem sie Aufgaben automatisieren und die Effizienz steigern. Unternehmen sollten jetzt beginnen, diese Technologien zu integrieren, um von den zahlreichen Vorteilen zu profitieren.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "workflow_complete": true + } + ], + "logs": [ + { + "id": "log_13d449df-fc67-434a-8edf-b8d75a0c5a91", + "message": "Neuer Benutzereingabe erhalten - Vorherigen Workflow beenden", + "type": "info", + "timestamp": "2025-04-06T23:43:44.448502", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_9853f05b-acd0-460b-8fc4-4e3a79d39336", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 69, 0 Dateien", + "type": "info", + "timestamp": "2025-04-06T23:43:44.456608", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_dd6861d8-d7a3-4408-ae91-0baa131a5330", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-06T23:43:44.466441", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_07385429-1a77-4271-b6cb-2e020898312a", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-06T23:43:46.441699", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_fabff88b-685d-4fa7-9100-b4cdee98f752", + "message": "Agent webcrawler_agent wurde ausgewählt mit Aufgabe: Führe eine Websuche durch, um herauszufinden, welc...", + "type": "info", + "timestamp": "2025-04-06T23:43:46.451924", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_9d0470d7-175a-4d6e-a061-acf7a2b0a681", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-06T23:43:46.459288", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_440148a4-0c4a-4732-b19e-68607f0c589e", + "message": "Agent webcrawler_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T23:43:46.459288", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_96e96f86-5b2f-4b5e-bad9-b07010bdcdc6", + "message": "Agent 'webcrawler_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T23:43:46.476894", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_bfe68502-a4d4-4547-b3f6-610dc26c7cbb", + "message": "Agent 'webcrawler_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-06T23:45:44.435037", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_f346b486-6aaf-4374-a948-c756c78590fb", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-06T23:45:52.862712", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_4f2bb582-4e87-4a8f-8830-a437f10c8bff", + "message": "Nachricht gelöscht: assistant - msg_433a...", + "type": "info", + "timestamp": "2025-04-06T23:46:40.231556", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_7066c7f2-1a34-4dfe-942d-fa3a5af617f8.json b/gwserver/_results/workflow_7066c7f2-1a34-4dfe-942d-fa3a5af617f8.json new file mode 100644 index 00000000..9b938610 --- /dev/null +++ b/gwserver/_results/workflow_7066c7f2-1a34-4dfe-942d-fa3a5af617f8.json @@ -0,0 +1,45 @@ +{ + "id": "7066c7f2-1a34-4dfe-942d-fa3a5af617f8", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 10:51:14", + "status": "failed", + "started_at": "2025-04-04T10:51:14.582719", + "last_activity": "2025-04-04T10:51:14.604493", + "prompt": "beschreibe das bild", + "messages": [], + "logs": [ + { + "id": "log_557e2590-7129-476f-9d44-96e9eb6ac945", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 19, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T10:51:14.588234", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_d09b30f3-1057-452e-9046-0f3d67f87f1a", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T10:51:14.589269", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c4ea02d9-e166-47e0-92e0-dafadfea39dc", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T10:51:14.594712", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b0f97a38-5f68-48b6-900b-581a5bd9eae5", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T10:51:14.604493", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_797cd4c1-4335-4f22-baa5-a67568707bb0.json b/gwserver/_results/workflow_797cd4c1-4335-4f22-baa5-a67568707bb0.json new file mode 100644 index 00000000..3a4cb5f0 --- /dev/null +++ b/gwserver/_results/workflow_797cd4c1-4335-4f22-baa5-a67568707bb0.json @@ -0,0 +1,108 @@ +{ + "id": "797cd4c1-4335-4f22-baa5-a67568707bb0", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 5.4.2025, 00:21:31", + "status": "waiting_for_user", + "started_at": "2025-04-05T00:21:32.038793", + "last_activity": "2025-04-05T00:21:45.592010", + "prompt": "describe picture", + "messages": [ + { + "id": "msg_75423ce9-f107-4bde-966a-02fba72f7bf1", + "workflow_id": "797cd4c1-4335-4f22-baa5-a67568707bb0", + "parent_message_id": null, + "started_at": "2025-04-05T00:21:32.056389", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [ + { + "id": 4, + "source": { + "type": "file", + "id": 4, + "name": "LF-Details.png", + "content_type": "image/png", + "size": 253009, + "upload_date": "2025-04-05T00:21:44.812027" + }, + "contents": [ + { + "type": "text", + "text": "Image Analysis:\nThe image is a flowchart illustrating a product development process involving multiple teams: Product Team, Q&A Team, Engineering Team, and Operations. Here's a detailed breakdown:\n\n### Input\n- **Sources**: Customers, Sales, and Internal Ideas.\n- **Process**: Inputs are collected and qualified.\n\n### Product Team\n1. **Discover**\n - **Collect**: Ideas and inputs.\n - **Qualify**: Analyze and match against business priorities.\n\n2. **Define**\n - **Structure & Document**: Write specifications, define acceptance criteria.\n - **Explore & Design**: UI design, experiments, and reference tickets.\n\n3. **Shape**\n - **Roadmap**: Define roadmap to meet opportunities and ensure stability.\n - **Scoping**: Define next version scope.\n - **Manage**: Tickets in the product.\n\n### Engineering Team\n- **Assess**\n - **Manage**: Move assessed tickets to future versions.\n - **Estimate**: Assess implementation, feasibility, and effort.\n\n- **Build**\n - **Manage**: Track progress in the dashboard.\n - **Factory**: Develop tickets for the next version.\n\n### Q&A Team\n- **Validate**\n - **Testing**: Test functionality against acceptance.\n - **Analysis**: Analyze tickets, events, deviations.\n\n### Operations\n1. **Release**\n - **Manage**: Ensure stable changes.\n\n2. **Run & Monitor**\n - **Manage**: Ensure stable operation.\n - **Service & Support**: Deliver first-level support according to SLA.\n\n### Output\n- **Product**: The final output of the process.\n\n### Tool Integration\n- **Ticketing System**: Visual representation of ticket management.\n- **Roadmap**: Timeline of product development phases.\n- **Management Dashboards**: Display of metrics and progress tracking.\n\nThe flowchart uses arrows to show the flow of tasks and responsibilities between different teams and stages, emphasizing collaboration and integration across the product development lifecycle." + } + ] + } + ], + "content": "describe picture", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben keine spezifischen Aufgaben durchgeführt. Gibt es etwas, wobei ich Ihnen helfen kann?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_7e27599e-df41-4884-96b2-d76d0550d280", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 16, 1 Dateien", + "type": "info", + "timestamp": "2025-04-05T00:21:32.043764", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_519f8be3-7f60-471a-b620-7e06866c1c0d", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-05T00:21:32.050242", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_2f1a5c49-1a95-472f-b47a-574034fa9d67", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-05T00:21:32.066146", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_2a5956d0-9c9b-4145-a9ff-aaba0cd2a44c", + "message": "Image LF-Details.png analyzed successfully", + "type": "info", + "timestamp": "2025-04-05T00:21:44.805019", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_02354881-c98b-4238-a296-3fd558422ce3", + "message": "Agenten-Entscheidung abgeschlossen: 0 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-05T00:21:45.579309", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_1cd4a2b8-b760-4640-8744-dff1b85b6d0e", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben keine spezifischen Aufgaben durc...", + "type": "info", + "timestamp": "2025-04-05T00:21:45.592010", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_7a71e36b-ffcd-4c73-8b68-c48426913c45.json b/gwserver/_results/workflow_7a71e36b-ffcd-4c73-8b68-c48426913c45.json new file mode 100644 index 00000000..eeaffd63 --- /dev/null +++ b/gwserver/_results/workflow_7a71e36b-ffcd-4c73-8b68-c48426913c45.json @@ -0,0 +1,45 @@ +{ + "id": "7a71e36b-ffcd-4c73-8b68-c48426913c45", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 12:25:29", + "status": "failed", + "started_at": "2025-04-04T12:25:29.468579", + "last_activity": "2025-04-04T12:25:35.596269", + "prompt": "describe", + "messages": [], + "logs": [ + { + "id": "log_c992c0d5-457d-46f7-b06b-cea6090ee743", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 8, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T12:25:29.471577", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_5b3e3327-6982-4390-81d6-64ef092be062", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T12:25:29.476579", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_6e21bb91-0365-4828-b1b4-966f5fd31cbe", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T12:25:29.483097", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_8713da5c-fa0f-4b39-9291-d4699619a761", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T12:25:35.596269", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_7ea1d65e-fb16-42ef-a14f-804aa3a3205f.json b/gwserver/_results/workflow_7ea1d65e-fb16-42ef-a14f-804aa3a3205f.json new file mode 100644 index 00000000..7044df84 --- /dev/null +++ b/gwserver/_results/workflow_7ea1d65e-fb16-42ef-a14f-804aa3a3205f.json @@ -0,0 +1,203 @@ +{ + "id": "7ea1d65e-fb16-42ef-a14f-804aa3a3205f", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 13:29:47", + "status": "waiting_for_user", + "started_at": "2025-04-04T13:29:48.745358", + "last_activity": "2025-04-04T13:31:01.949138", + "prompt": "describe", + "messages": [ + { + "id": "msg_1ec124b5-120f-477d-8e53-12b576dd52d2", + "workflow_id": "7ea1d65e-fb16-42ef-a14f-804aa3a3205f", + "parent_message_id": null, + "started_at": "2025-04-04T13:29:48.759266", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [ + { + "id": 4, + "source": { + "type": "file", + "id": 4, + "name": "LF-Details.png", + "content_type": "image/png", + "size": 253009, + "upload_date": "2025-04-04T13:30:01.970503" + }, + "contents": [ + { + "type": "text", + "text": "Image Analysis:\nThe image is a flowchart illustrating a product development process involving multiple teams: Product Team, Q&A Team, Engineering Team, and Operations. Here's a detailed breakdown:\n\n### Input\n- **Sources**: Customers, Sales, Our Ideas\n- **Flow**: Inputs are collected and fed into the Product Team.\n\n### Product Team\n1. **Discover**\n - **Collect**: Ideas & Inputs\n - **Qualify**: Analyze and match against business priorities\n\n2. **Define**\n - **Structure & Document**: Write specifications, define acceptance criteria\n - **Explore & Design**: UI Design, Experiments, etc.\n\n3. **Shape**\n - **Roadmap**: Define roadmap to meet opportunities and protect development stability\n - **Scoping**: Define next version's scope\n - **Manage**: Tickets in Product\n\n### Q&A Team\n4. **Validate**\n - **Testing**: Test functionality against acceptance\n - **Analysis**: Analyze tickets, events, deviations\n\n### Engineering Team\n5. **Assess**\n - **Manage**: Move assessed tickets to Engineering for future versions\n - **Estimate**: Define implementation, feasibility, and effort\n\n6. **Build**\n - **Manage**: Track progress in the dashboard\n - **Factory**: Develop tickets in Engineering for the next version\n\n### Operations\n7. **Release**\n - **Manage**: Ensure stable changes\n\n8. **Run & Monitor**\n - **Manage**: Ensure stable operation\n - **Service & Support**: Deliver 1st level support according to agreed SLA\n\n### Output\n- **Product**: The final product is delivered as the output.\n\n### Tool Integration\n- **Ticketing System**: Visual representation of ticket management.\n- **Roadmap**: Timeline view of project phases.\n- **Management Dashboards**: Visual data displays for tracking metrics.\n\nThe flowchart uses arrows to indicate the process flow between different stages and teams, emphasizing collaboration and integration across the product lifecycle." + } + ] + } + ], + "content": "describe", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Bitte beschreibe den Inhalt und die Bedeutung des bereitgestellten Bildes 'LF-Details.png', das einen Flussdiagramm des Produktentwicklungsprozesses darstellt.", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true, + "finished_at": "2025-04-04T13:30:51.610004", + "status": "completed" + }, + { + "id": "msg_396133df-c522-4680-9034-e23aee363aba", + "workflow_id": "7ea1d65e-fb16-42ef-a14f-804aa3a3205f", + "parent_message_id": null, + "started_at": "2025-04-04T13:30:51.610004", + "finished_at": null, + "sequence_no": 3, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [ + { + "id": 1, + "source": { + "type": "file", + "id": 1, + "name": "LF-Nutshell.png", + "content_type": "image/png", + "size": 52108, + "upload_date": "2025-04-04T13:31:00.557314" + }, + "contents": [ + { + "type": "text", + "text": "Image Analysis:\nThe image is a flowchart titled \"In a nutshell,\" illustrating a product development process. It consists of several components:\n\n1. **Inputs**: Represented by an inverted triangle at the top left, indicating the starting point of the process.\n\n2. **Product Team**: A rectangular box below the inputs, labeled \"Discover - Define - Shape,\" showing the initial phase where the product team works on conceptualizing the product.\n\n3. **Engineering Team**: Next to the product team, another box labeled \"Assess & Build,\" indicating the phase where the engineering team evaluates and constructs the product.\n\n4. **Q&A Team**: Following the engineering team, a box labeled \"Validate,\" representing the quality assurance phase where the product is tested.\n\n5. **Operations**: The final box in the sequence, labeled \"Release, Run & Monitor,\" showing the operations phase where the product is launched and maintained.\n\n6. **Roadmap**: A horizontal arrow labeled \"Roadmap\" connects the product team to the subsequent phases, indicating the planning and direction of the product development.\n\n7. **Product**: Three consecutive boxes labeled \"Product\" follow the roadmap, representing the final product stages.\n\nThe overall layout is structured to show a linear progression from inputs to the final product, with each team playing a specific role in the development process. The color scheme includes shades of olive green and white, set against a light gray background." + } + ] + } + ], + "content": "describe", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Bitte beschreibe das Bild LF-Nutshell.png, das einen Flussdiagramm mit dem Titel 'In a nutshell' zeigt, und erkläre den Produktentwicklungsprozess, der darin dargestellt wird.", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_f9cafcae-2a5e-4358-8e0e-e4ce3e504d16", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 8, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T13:29:48.750365", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_1c0a30e1-5a76-4d52-a6d3-d1b48fc40809", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T13:29:48.754364", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_f18429af-bd92-4003-b155-807213851ac7", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T13:29:48.764301", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_48611c37-6b5e-43c4-8bd7-657573e4e6d9", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T13:30:03.481902", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_dedeee58-59d4-4fea-8aa6-344e41b852f5", + "message": "Agent user_agent wurde ausgewählt mit Aufgabe: Bitte beschreibe den Inhalt und die Bedeutung des ...", + "type": "info", + "timestamp": "2025-04-04T13:30:03.487898", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_f4ecd1d9-62cd-4526-b1ab-43ea8de9f779", + "message": "Workflow wartet auf Benutzereingabe: Bitte beschreibe den Inhalt und die Bedeutung des ...", + "type": "info", + "timestamp": "2025-04-04T13:30:03.491899", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_fb2b3f09-b03d-4797-9fda-23d70d9c9b4c", + "message": "Benutzereingabe empfangen: 8 Zeichen, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T13:30:51.601002", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_a0da0c6f-a8a1-4c53-bdc9-fd15cdb114df", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T13:30:51.605004", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_9c75f5bd-f51f-4b00-9a98-b02536d2a54f", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T13:30:51.614008", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_57022a05-cca8-4fea-82aa-a7e1ae882057", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T13:31:01.940141", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_39124fb8-5ec5-42ed-8212-f9872b9f5b29", + "message": "Agent user_agent wurde ausgewählt mit Aufgabe: Bitte beschreibe das Bild LF-Nutshell.png, das ein...", + "type": "info", + "timestamp": "2025-04-04T13:31:01.945139", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_cd2a4ad3-5340-4ebf-a78e-9fe34421a793", + "message": "Workflow wartet auf Benutzereingabe: Bitte beschreibe das Bild LF-Nutshell.png, das ein...", + "type": "info", + "timestamp": "2025-04-04T13:31:01.949138", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_7fbd496e-d684-46c4-81a1-5c033a690fc8.json b/gwserver/_results/workflow_7fbd496e-d684-46c4-81a1-5c033a690fc8.json new file mode 100644 index 00000000..37a1af04 --- /dev/null +++ b/gwserver/_results/workflow_7fbd496e-d684-46c4-81a1-5c033a690fc8.json @@ -0,0 +1,272 @@ +{ + "id": "7fbd496e-d684-46c4-81a1-5c033a690fc8", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 5.4.2025, 00:47:39", + "status": "waiting_for_user", + "started_at": "2025-04-05T00:47:39.540380", + "last_activity": "2025-04-05T00:49:09.119612", + "prompt": "summarize the table", + "messages": [ + { + "id": "msg_04d01ab9-2801-4a2f-918e-c6f090db1677", + "workflow_id": "7fbd496e-d684-46c4-81a1-5c033a690fc8", + "parent_message_id": null, + "started_at": "2025-04-05T00:47:39.558372", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [ + { + "id": 5, + "source": { + "type": "file", + "id": 5, + "name": "auszug_liste_positionen.pdf", + "content_type": "application/pdf", + "size": 299729, + "upload_date": "2025-04-05T00:47:39.579424" + }, + "contents": [ + { + "type": "text", + "text": "\n\n" + } + ] + } + ], + "content": "summarize the table", + "agent_type": null + }, + { + "id": "msg_7ee278dc-ff6f-41ec-aaa5-26f82c5eb111", + "workflow_id": "7fbd496e-d684-46c4-81a1-5c033a690fc8", + "parent_message_id": null, + "started_at": "2025-04-05T00:47:41.698208", + "finished_at": "2025-04-05T00:47:41.702209", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "Ich habe als Datenanalyst eine Analyse der bereitgestellten Daten durchgeführt.\n\nHier ist meine detaillierte Analyse:\n1. Die Daten zeigen einen klaren Trend...\n2. Es gibt signifikante Korrelationen zwischen...\n3. Besonders auffällig ist...\n\nMeine Empfehlungen basierend auf der Analyse:\n- Maßnahme 1: ...\n- Maßnahme 2: ...\n- Maßnahme 3: ...", + "agent_type": "analyzer", + "agent_id": "analyst_agent", + "agent_name": "Datenanalyst" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n**Zusammenfassung der Agentenergebnisse**\n\n**Datenanalyse:**\n\n1. **Trends:** \n - Die Daten zeigen einen klaren Trend, der auf [spezifische Erkenntnis] hinweist.\n\n2. **Korrelationen:** \n - Es gibt signifikante Korrelationen zwischen [Variable A] und [Variable B], was auf [Interpretation der Korrelation] hindeutet.\n\n3. **Auffälligkeiten:** \n - Besonders auffällig ist [spezifische Beobachtung], was möglicherweise auf [Ursache oder Konsequenz] zurückzuführen ist.\n\n**Empfehlungen:**\n\n- **Maßnahme 1:** [Beschreibung der Maßnahme 1], um [Ziel oder erwartetes Ergebnis] zu erreichen.\n- **Maßnahme 2:** [Beschreibung der Maßnahme 2], um [Ziel oder erwartetes Ergebnis] zu unterstützen.\n- **Maßnahme 3:** [Beschreibung der Maßnahme 3], um [Ziel oder erwartetes Ergebnis] zu fördern.\n\nDiese strukturierte Zusammenfassung bietet einen klaren Überblick über die wichtigsten Erkenntnisse und Empfehlungen aus der Datenanalyse.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true, + "finished_at": "2025-04-05T00:49:00.676535", + "status": "completed" + }, + { + "id": "msg_a221238c-bd0a-466f-b52d-0fe8ed469d00", + "workflow_id": "7fbd496e-d684-46c4-81a1-5c033a690fc8", + "parent_message_id": null, + "started_at": "2025-04-05T00:49:00.677518", + "finished_at": null, + "sequence_no": 4, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [ + { + "id": 5, + "source": { + "type": "file", + "id": 5, + "name": "auszug_liste_positionen.pdf", + "content_type": "application/pdf", + "size": 299729, + "upload_date": "2025-04-05T00:49:00.697757" + }, + "contents": [ + { + "type": "text", + "text": "\n\n" + } + ] + } + ], + "content": "übersetzte auf deutsch", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Bitte klären Sie, welchen Inhalt Sie auf Deutsch übersetzen möchten. Bezieht sich Ihre Anfrage auf die Datei 'auszug_liste_positionen.pdf'? Wenn ja, geben Sie bitte an, welche Teile übersetzt werden sollen.", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_73071dd7-5a5c-4bd6-baef-b09814263735", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 19, 1 Dateien", + "type": "info", + "timestamp": "2025-04-05T00:47:39.547366", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_0d33f0ba-57ab-46ec-b48e-58f96a5a0fbd", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-05T00:47:39.552373", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_92e6492a-29d0-4e01-a62a-f4ae78823476", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-05T00:47:39.563311", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_3cfe41f7-96c1-4c8a-90a2-9e5968a2df4c", + "message": "File auszug_liste_positionen.pdf read successfully", + "type": "info", + "timestamp": "2025-04-05T00:47:39.572460", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_90ef878d-1a6f-4289-a335-246ddb551aa6", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-05T00:47:41.668650", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_1b46ca4d-157f-4436-a5a5-a2ddf4798543", + "message": "Agent analyst_agent wurde ausgewählt mit Aufgabe: Analysiere die Tabelle in der Datei 'auszug_liste_...", + "type": "info", + "timestamp": "2025-04-05T00:47:41.675646", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_bf17880e-5751-4d62-91cf-c52ec751b380", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-05T00:47:41.680694", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_5e9bf11c-c89a-49e9-8696-11babcb8910f", + "message": "Agent analyst_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-05T00:47:41.687207", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_cb726a1e-d875-449c-bd7c-843032272c72", + "message": "Agent 'analyst_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-05T00:47:41.692242", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_da291ff9-2ff4-44ee-ae9d-3eafd237991e", + "message": "Agent 'analyst_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-05T00:47:41.761514", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_a9d6b7ff-5cd4-47bd-b5ee-a56d4bab7f99", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-05T00:47:45.328631", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_6a27143f-b5f2-4abe-a12c-ff8d877d4b0d", + "message": "Benutzereingabe empfangen: 22 Zeichen, 1 Dateien", + "type": "info", + "timestamp": "2025-04-05T00:49:00.656020", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ff4c4b43-ddfd-4516-acdb-c944953dcd18", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-05T00:49:00.656020", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_18ccc3e8-e029-4ec1-a7fe-4ec73c5c677a", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-05T00:49:00.682128", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_fdddd98e-c14a-4df5-baaf-f3a609e301bf", + "message": "File auszug_liste_positionen.pdf read successfully", + "type": "info", + "timestamp": "2025-04-05T00:49:00.690758", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ea72d851-7310-43c1-9b5e-7640f3ede2d4", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-05T00:49:09.105263", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_6de25693-c0df-4b9b-869d-84252e689f55", + "message": "Agent user_agent wurde ausgewählt mit Aufgabe: Bitte klären Sie, welchen Inhalt Sie auf Deutsch ü...", + "type": "info", + "timestamp": "2025-04-05T00:49:09.110566", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_6342896a-9ac5-4b5e-860c-e54948b4a621", + "message": "Workflow wartet auf Benutzereingabe: Bitte klären Sie, welchen Inhalt Sie auf Deutsch ü...", + "type": "info", + "timestamp": "2025-04-05T00:49:09.119612", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_87a60338-9e04-439e-b6fd-7268b5d77e18.json b/gwserver/_results/workflow_87a60338-9e04-439e-b6fd-7268b5d77e18.json new file mode 100644 index 00000000..f1891dd8 --- /dev/null +++ b/gwserver/_results/workflow_87a60338-9e04-439e-b6fd-7268b5d77e18.json @@ -0,0 +1,45 @@ +{ + "id": "87a60338-9e04-439e-b6fd-7268b5d77e18", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 00:38:17", + "status": "failed", + "started_at": "2025-04-04T00:38:17.884318", + "last_activity": "2025-04-04T00:38:17.900533", + "prompt": "Analysiere den beigefügten Datensatz und mache zusammenfassung", + "messages": [], + "logs": [ + { + "id": "log_86fb8f11-72fb-44fd-b5bc-efecf96454fc", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 62, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T00:38:17.887318", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_5b620f25-d034-4509-8d7c-27804be47c70", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T00:38:17.891119", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_d8933d36-c1c1-4cac-b596-9a93fa9e4413", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T00:38:17.896030", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_e35658d9-d3cf-43de-b9d4-a82bdb55b2ca", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T00:38:17.900533", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_89199727-f69e-47df-aca3-8eb4791e5a81.json b/gwserver/_results/workflow_89199727-f69e-47df-aca3-8eb4791e5a81.json new file mode 100644 index 00000000..f2b88e39 --- /dev/null +++ b/gwserver/_results/workflow_89199727-f69e-47df-aca3-8eb4791e5a81.json @@ -0,0 +1,21 @@ +{ + "id": "89199727-f69e-47df-aca3-8eb4791e5a81", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 6.4.2025, 23:16:25", + "status": "stopped", + "started_at": "2025-04-06T23:16:25.547907", + "last_activity": "2025-04-06T23:17:12.804297", + "prompt": "kannst du mir im web suchen, welche firmen glasssühle anbieten?", + "messages": [], + "logs": [ + { + "id": "log_db967cf6-9037-4a08-aa08-8e1866f7c931", + "message": "Workflow wurde manuell gestoppt", + "type": "info", + "timestamp": "2025-04-06T23:17:12.804297", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_8f457d7e-6e0b-450e-8f12-6304400610a3.json b/gwserver/_results/workflow_8f457d7e-6e0b-450e-8f12-6304400610a3.json new file mode 100644 index 00000000..faee11df --- /dev/null +++ b/gwserver/_results/workflow_8f457d7e-6e0b-450e-8f12-6304400610a3.json @@ -0,0 +1,45 @@ +{ + "id": "8f457d7e-6e0b-450e-8f12-6304400610a3", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 11:03:13", + "status": "failed", + "started_at": "2025-04-04T11:03:13.833340", + "last_activity": "2025-04-04T11:03:13.847289", + "prompt": "analyse image", + "messages": [], + "logs": [ + { + "id": "log_e3a0a580-e686-4f4d-a41b-a5e54696d4fe", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 13, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T11:03:13.837482", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_a06464e6-357a-400d-bb8b-6db948148b9b", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T11:03:13.839371", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_8900ef0c-0bae-481a-970e-29c1a14b2209", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T11:03:13.844328", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b8d555dc-dc23-4cc1-a353-2b80ff0b90cc", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T11:03:13.847289", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_91a9d821-3a1d-487b-8510-6b492cfec6f8.json b/gwserver/_results/workflow_91a9d821-3a1d-487b-8510-6b492cfec6f8.json new file mode 100644 index 00000000..43a3c5d4 --- /dev/null +++ b/gwserver/_results/workflow_91a9d821-3a1d-487b-8510-6b492cfec6f8.json @@ -0,0 +1,45 @@ +{ + "id": "91a9d821-3a1d-487b-8510-6b492cfec6f8", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 11:06:11", + "status": "failed", + "started_at": "2025-04-04T11:06:11.600577", + "last_activity": "2025-04-04T11:06:11.614537", + "prompt": "analyse image", + "messages": [], + "logs": [ + { + "id": "log_3a17353c-a7d8-44a8-b1f1-96a01a504cbc", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 13, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T11:06:11.603582", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_cdd0d8a1-8cbc-4773-9068-b00e30df3e8f", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T11:06:11.605617", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_56bc7136-b1ad-4884-895e-726d321a079c", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T11:06:11.609579", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_63b98be8-4f31-457a-9867-0b522ce426d2", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T11:06:11.614537", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_98248069-50f6-4d15-b554-fff31845ac60.json b/gwserver/_results/workflow_98248069-50f6-4d15-b554-fff31845ac60.json new file mode 100644 index 00000000..a5325799 --- /dev/null +++ b/gwserver/_results/workflow_98248069-50f6-4d15-b554-fff31845ac60.json @@ -0,0 +1,74 @@ +{ + "id": "98248069-50f6-4d15-b554-fff31845ac60", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 10:09:01", + "status": "waiting_for_user", + "started_at": "2025-04-04T10:09:02.801739", + "last_activity": "2025-04-04T10:09:04.405802", + "prompt": "beschreibe das bild", + "messages": [ + { + "id": "msg_50309ac2-915e-4efa-aec9-e91d86c8a8cb", + "workflow_id": "98248069-50f6-4d15-b554-fff31845ac60", + "parent_message_id": null, + "started_at": "2025-04-04T10:09:02.807346", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "beschreibe das bild", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben keine spezifischen Aufgaben durchgeführt. Gibt es etwas, wobei ich Ihnen helfen kann?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_5c9b045b-77fd-4533-9147-beba21cae91b", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 19, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T10:09:02.806176", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_41b7aa97-1ae5-440e-bd21-3cc020320026", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T10:09:02.807346", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b0517342-88e5-4ce0-abda-45c433a54310", + "message": "Agenten-Entscheidung abgeschlossen: 0 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T10:09:04.403809", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_4ad31a59-4a01-46fb-a9f4-499810e63521", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben keine spezifischen Aufgaben durc...", + "type": "info", + "timestamp": "2025-04-04T10:09:04.405802", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_9e32e62d-f874-4fc3-9d13-0d2c454ac918.json b/gwserver/_results/workflow_9e32e62d-f874-4fc3-9d13-0d2c454ac918.json new file mode 100644 index 00000000..545f12c7 --- /dev/null +++ b/gwserver/_results/workflow_9e32e62d-f874-4fc3-9d13-0d2c454ac918.json @@ -0,0 +1,82 @@ +{ + "id": "9e32e62d-f874-4fc3-9d13-0d2c454ac918", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 23:36:43", + "status": "waiting_for_user", + "started_at": "2025-04-04T23:36:43.803889", + "last_activity": "2025-04-04T23:36:45.518758", + "prompt": "wieviele primzahlen gibt es?", + "messages": [ + { + "id": "msg_b158f42e-b86b-424b-8051-c4163e906557", + "workflow_id": "9e32e62d-f874-4fc3-9d13-0d2c454ac918", + "parent_message_id": null, + "started_at": "2025-04-04T23:36:43.818325", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "wieviele primzahlen gibt es?", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Erkläre dem Benutzer, dass es unendlich viele Primzahlen gibt. Primzahlen sind natürliche Zahlen größer als 1, die nur durch 1 und sich selbst teilbar sind. Diese Eigenschaft führt dazu, dass es keine obere Grenze für die Anzahl der Primzahlen gibt.", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_5eb58d09-e999-4be7-bf51-59f8d7ea6958", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 28, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T23:36:43.808340", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_4e6e8063-0600-44a6-8549-39d06f532c4f", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T23:36:43.813458", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_d174588a-3fa4-4c84-b74f-7d58f940d505", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T23:36:45.495249", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c30a9c40-eab3-41e6-a7d9-44e9653d0770", + "message": "Agent user_agent wurde ausgewählt mit Aufgabe: Erkläre dem Benutzer, dass es unendlich viele Prim...", + "type": "info", + "timestamp": "2025-04-04T23:36:45.513751", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_4d75aff8-77b3-482c-848f-ef49a497fb51", + "message": "Workflow wartet auf Benutzereingabe: Erkläre dem Benutzer, dass es unendlich viele Prim...", + "type": "info", + "timestamp": "2025-04-04T23:36:45.518758", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_a32a5b46-b5d3-4a86-b281-b9eebb1ca27b.json b/gwserver/_results/workflow_a32a5b46-b5d3-4a86-b281-b9eebb1ca27b.json new file mode 100644 index 00000000..7e6537d6 --- /dev/null +++ b/gwserver/_results/workflow_a32a5b46-b5d3-4a86-b281-b9eebb1ca27b.json @@ -0,0 +1,74 @@ +{ + "id": "a32a5b46-b5d3-4a86-b281-b9eebb1ca27b", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 12:08:40", + "status": "waiting_for_user", + "started_at": "2025-04-04T12:08:41.015789", + "last_activity": "2025-04-04T12:08:41.755299", + "prompt": "describe", + "messages": [ + { + "id": "msg_11070940-296e-485f-9c0b-fa2af3249b87", + "workflow_id": "a32a5b46-b5d3-4a86-b281-b9eebb1ca27b", + "parent_message_id": null, + "started_at": "2025-04-04T12:08:41.027097", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "describe", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben keine spezifischen Aufgaben durchgeführt. Gibt es etwas, wobei ich Ihnen helfen kann?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_7de1d027-c5d7-4cdf-a7f6-3c650d864e5b", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 8, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T12:08:41.020377", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_16dd9fa2-b7dc-4112-a78d-ba6b4b1e1a1a", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T12:08:41.023380", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_606d1401-7618-4a9d-9b9d-1424e75ce5bc", + "message": "Agenten-Entscheidung abgeschlossen: 0 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T12:08:41.752297", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_429d9d58-fabe-4cc8-8de3-5c5c8869245b", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben keine spezifischen Aufgaben durc...", + "type": "info", + "timestamp": "2025-04-04T12:08:41.755299", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_a3b24a29-8543-4340-8f25-f44841836e37.json b/gwserver/_results/workflow_a3b24a29-8543-4340-8f25-f44841836e37.json new file mode 100644 index 00000000..d7eedf17 --- /dev/null +++ b/gwserver/_results/workflow_a3b24a29-8543-4340-8f25-f44841836e37.json @@ -0,0 +1,432 @@ +{ + "id": "a3b24a29-8543-4340-8f25-f44841836e37", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 6.4.2025, 12:48:07", + "status": "waiting_for_user", + "started_at": "2025-04-06T12:48:07.631021", + "last_activity": "2025-04-06T12:53:23.991657", + "prompt": "kannst du mir einen bericht machen, wie eine applikation korrekt integriert wird von DEV auf PROD?", + "messages": [ + { + "id": "msg_15ec5f57-286f-4fb6-b909-b3ee3986495e", + "workflow_id": "a3b24a29-8543-4340-8f25-f44841836e37", + "parent_message_id": null, + "started_at": "2025-04-06T12:48:07.652020", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "kannst du mir einen bericht machen, wie eine applikation korrekt integriert wird von DEV auf PROD?", + "agent_type": null + }, + { + "id": "msg_f364be4b-c93d-4103-8615-97bf7414f881", + "workflow_id": "a3b24a29-8543-4340-8f25-f44841836e37", + "parent_message_id": null, + "started_at": "2025-04-06T12:48:10.668490", + "finished_at": "2025-04-06T12:48:10.673421", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "Ich habe als Entwickler die Anforderungen analysiert und folgenden Code entwickelt:\n\n```python\ndef process_data(input_file, output_file):\n \"\"\"\n Verarbeitet Daten aus einer Eingabedatei und speichert die Ergebnisse.\n \n Args:\n input_file: Pfad zur Eingabedatei\n output_file: Pfad zur Ausgabedatei\n \"\"\"\n import pandas as pd\n \n # Daten einlesen\n df = pd.read_csv(input_file)\n \n # Daten verarbeiten\n # Hier würde die eigentliche Datenverarbeitung stattfinden\n processed_df = df.copy()\n \n # Beispiel: Spalten filtern und transformieren\n if 'data' in processed_df.columns:\n processed_df['transformed'] = processed_df['data'] * 2\n \n # Ergebnis speichern\n processed_df.to_csv(output_file, index=False)\n \n return len(processed_df)\n\n# Beispielaufruf\nif __name__ == \"__main__\":\n result = process_data(\"input.csv\", \"output.csv\")\n print(f\"Verarbeitet: result Datensätze\")\n```\n\nDer Code liest eine CSV-Datei ein, führt eine einfache Transformation durch und speichert das Ergebnis. \nDie Hauptfunktion `process_data` ist modular gestaltet und kann leicht erweitert werden.\n\nZur Verwendung:\n1. Stelle sicher, dass pandas installiert ist (`pip install pandas`)\n2. Passe die Dateipfade im Beispielaufruf an\n3. Erweitere die Verarbeitung je nach deinen spezifischen Anforderungen", + "agent_type": "coder", + "agent_id": "coder_agent", + "agent_name": "Entwickler" + }, + { + "id": "msg_561d0f5e-fa9c-4cc6-ac01-c72d85077c91", + "workflow_id": "a3b24a29-8543-4340-8f25-f44841836e37", + "parent_message_id": null, + "started_at": "2025-04-06T12:49:22.475272", + "finished_at": "2025-04-06T12:49:22.480330", + "sequence_no": 3, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "# Bericht zur Anwendungsmigration: Technische Anleitung zur DEV-PROD Integration und Datenverarbeitung mit Python\n\n## Zusammenfassung\n\nDer Bericht bietet eine technische Anleitung zur Migration einer Anwendung von der Entwicklungsumgebung (DEV) in die Produktionsumgebung (PROD) unter Verwendung von Python. Der Schwerpunkt liegt auf der Datenverarbeitung mit einem Python-Skript, das CSV-Dateien einliest, einfache Transformationen durchführt und die Ergebnisse speichert. Die Hauptfunktion `process_data` ist modular und erweiterbar, um spezifische Anforderungen zu erfüllen. Zur Nutzung des Skripts wird die Installation von pandas vorausgesetzt, und die Dateipfade müssen entsprechend angepasst werden.\n\n## Inhaltsverzeichnis\n\n1. Kapitel 1: Einleitung\n2. Kapitel 2: Technische Voraussetzungen\n3. Kapitel 3: Beschreibung des Python-Skripts\n4. Kapitel 4: Anpassung und Erweiterung des Skripts\n5. Kapitel 5: Durchführung der Migration\n6. Kapitel 6: Fehlerbehebung und Optimierung\n7. Kapitel 7: Zusammenfassung und Ausblick\n\n## 1. Kapitel 1: Einleitung\n\nDie Migration von Anwendungen von der Entwicklungsumgebung (DEV) in die Produktionsumgebung (PROD) ist ein kritischer Prozess, der sorgfältige Planung und Ausführung erfordert. Dieser Bericht zielt darauf ab, eine technische Anleitung zur Integration und Datenverarbeitung mit Python bereitzustellen, um den Übergang von DEV zu PROD effizient und fehlerfrei zu gestalten. \n\n**Ziele des Berichts**\n\n- **Verständnis der Migration**: Vermittlung eines klaren Verständnisses der Notwendigkeit und der Vorteile der Migration von Anwendungen von DEV nach PROD.\n- **Technische Anleitung**: Bereitstellung detaillierter technischer Anweisungen zur Integration der Anwendung in die Produktionsumgebung.\n- **Datenverarbeitung mit Python**: Demonstration der Verwendung von Python zur Datenverarbeitung während der Migration, einschließlich der Implementierung von Datenverarbeitungslogik und der Sicherstellung der Datenintegrität.\n\n**Bedeutung der Migration von DEV nach PROD**\n\nDie Migration von Anwendungen von der Entwicklungsumgebung in die Produktionsumgebung ist ein entscheidender Schritt im Softwareentwicklungszyklus. Diese Migration stellt sicher, dass Anwendungen unter realen Bedingungen zuverlässig funktionieren und den Anforderungen der Endnutzer gerecht werden. Die folgenden Punkte verdeutlichen die Bedeutung dieses Prozesses:\n\n- **Leistungsoptimierung**: In der Produktionsumgebung werden Anwendungen unter realen Lastbedingungen getestet, was zur Optimierung der Leistung beiträgt.\n- **Sicherheitsverbesserungen**: Die PROD-Umgebung bietet erweiterte Sicherheitsmaßnahmen, die in der Entwicklungsphase möglicherweise nicht vorhanden sind.\n- **Skalierbarkeit**: Die Migration ermöglicht es, Anwendungen auf eine größere Nutzerbasis zu skalieren, was in der Entwicklungsumgebung nicht möglich ist.\n- **Fehlererkennung und -behebung**: Durch den Einsatz in der PROD-Umgebung können potenzielle Fehler identifiziert und behoben werden, bevor sie den Endnutzer betreffen.\n\n**Technische Herausforderungen und Lösungen**\n\nDie Migration von DEV nach PROD bringt mehrere technische Herausforderungen mit sich, die sorgfältig angegangen werden müssen:\n\n- **Datenkonsistenz**: Sicherstellung, dass alle Daten korrekt und konsistent übertragen werden. Dies wird durch die Implementierung robuster Datenverarbeitungsprozesse in Python erreicht.\n- **Umgebungsunterschiede**: Berücksichtigung der Unterschiede zwischen DEV und PROD, wie z.B. unterschiedliche Datenbankkonfigurationen oder API-Endpunkte.\n- **Automatisierung**: Einsatz von Automatisierungstools und Skripten, um den Migrationsprozess zu beschleunigen und menschliche Fehler zu minimieren.\n\n**Verwendung von Python zur Datenverarbeitung**\n\nPython ist ein leistungsstarkes Werkzeug zur Datenverarbeitung während der Migration. Der bereitgestellte Code zeigt, wie Daten aus einer CSV-Datei eingelesen, verarbeitet und in einer neuen Datei gespeichert werden können. Die Hauptfunktion `process_data` ist modular und kann leicht erweitert werden, um spezifische Anforderungen zu erfüllen. Die Verwendung von Bibliotheken wie Pandas ermöglicht eine effiziente Datenmanipulation und -analyse.\n\n**Schlussfolgerung**\n\nDie Migration von Anwendungen von DEV nach PROD ist ein wesentlicher Bestandteil des Softwareentwicklungsprozesses, der sorgfältige Planung und technische Kompetenz erfordert. Dieser Bericht bietet eine umfassende Anleitung zur Durchführung dieser Migration unter Verwendung von Python, um eine reibungslose und erfolgreiche Integration zu gewährleisten.\n\n## 2. Kapitel 2: Technische Voraussetzungen\n\n## Technische Voraussetzungen\n\nIn diesem Kapitel werden die technischen Voraussetzungen für die erfolgreiche Durchführung der Anwendungsmigration von der Entwicklungsumgebung (DEV) zur Produktionsumgebung (PROD) beschrieben. Der Fokus liegt auf der Integration und Datenverarbeitung mit Python, insbesondere unter Verwendung der pandas-Bibliothek. Diese Voraussetzungen stellen sicher, dass die Migration reibungslos verläuft und die Anwendung in der Produktionsumgebung effizient arbeitet.\n\n### 1. Softwareanforderungen\n\nFür die Migration und Integration der Anwendung sind folgende Softwarekomponenten erforderlich:\n\n- **Python**: Die Programmiersprache Python ist das Rückgrat der Datenverarbeitung in diesem Projekt. Es wird empfohlen, die neueste stabile Version von Python 3.x zu verwenden, um von den neuesten Funktionen und Sicherheitsupdates zu profitieren.\n\n- **pandas**: Diese leistungsstarke Bibliothek für Datenanalyse und -manipulation ist entscheidend für die Verarbeitung von CSV-Dateien. Sie ermöglicht effizientes Lesen, Bearbeiten und Speichern von Daten. Installation über pip:\n ```bash\n pip install pandas\n ```\n\n- **CSV-Dateien**: Die Anwendung arbeitet mit CSV-Dateien als Eingabe- und Ausgabeformat. Stellen Sie sicher, dass die Eingabedateien korrekt formatiert sind und die erwarteten Spalten enthalten.\n\n### 2. Systemanforderungen\n\nUm die Anwendung effektiv auszuführen, sollten die folgenden Systemanforderungen erfüllt sein:\n\n- **Betriebssystem**: Die Anwendung ist plattformunabhängig und kann auf Windows, macOS oder Linux ausgeführt werden. Stellen Sie sicher, dass das Betriebssystem aktuell ist und alle Sicherheitsupdates installiert sind.\n\n- **Hardware**: \n - **Prozessor**: Mindestens ein Dual-Core-Prozessor wird empfohlen, um die Datenverarbeitung effizient zu gestalten.\n - **Arbeitsspeicher**: Mindestens 4 GB RAM, um die Verarbeitung großer Datensätze zu unterstützen.\n - **Speicherplatz**: Ausreichend freier Speicherplatz für die Eingabe- und Ausgabedateien sowie für temporäre Dateien, die während der Verarbeitung erstellt werden.\n\n### 3. Entwicklungsumgebung\n\nFür die Entwicklung und das Testen der Anwendung in der DEV-Umgebung sind folgende Tools und Einstellungen erforderlich:\n\n- **IDE/Editor**: Eine integrierte Entwicklungsumgebung (IDE) wie PyCharm, Visual Studio Code oder Jupyter Notebook wird empfohlen, um den Entwicklungsprozess zu erleichtern.\n\n- **Versionskontrolle**: Verwendung von Git für die Versionskontrolle, um Änderungen am Code zu verfolgen und die Zusammenarbeit im Team zu erleichtern.\n\n- **Virtuelle Umgebungen**: Nutzen Sie virtuelle Umgebungen (z.B. venv oder conda), um Abhängigkeiten zu isolieren und Konflikte zwischen verschiedenen Projekten zu vermeiden.\n\n### 4. Sicherheitsanforderungen\n\nSicherheitsaspekte sind bei der Migration von Anwendungen in die Produktionsumgebung von entscheidender Bedeutung:\n\n- **Zugriffsrechte**: Stellen Sie sicher, dass nur autorisierte Benutzer Zugriff auf die Produktionsumgebung und die sensiblen Daten haben.\n\n- **Datenverschlüsselung**: Implementieren Sie Verschlüsselungsmechanismen für die Übertragung und Speicherung sensibler Daten.\n\n- **Regelmäßige Backups**: Führen Sie regelmäßige Backups der Daten durch, um Datenverlust im Falle eines Systemausfalls zu vermeiden.\n\n### 5. Test- und Validierungsanforderungen\n\nVor der endgültigen Migration in die Produktionsumgebung sollten umfangreiche Tests durchgeführt werden:\n\n- **Unit-Tests**: Entwickeln Sie Unit-Tests für die Kernfunktionen der Anwendung, um sicherzustellen, dass jede Komponente wie erwartet funktioniert.\n\n- **Integrationstests**: Testen Sie die Integration der Anwendung in die Produktionsumgebung, um sicherzustellen, dass alle Komponenten nahtlos zusammenarbeiten.\n\n- **Benutzerakzeptanztests (UAT)**: Führen Sie UAT durch, um sicherzustellen, dass die Anwendung den Anforderungen der Endbenutzer entspricht und alle Geschäftsanforderungen erfüllt.\n\nDurch die Einhaltung dieser technischen Voraussetzungen wird sichergestellt, dass die Anwendungsmigration effizient und erfolgreich durchgeführt wird, wobei die Integrität und Sicherheit der Daten gewährleistet sind.\n\n## 3. Kapitel 3: Beschreibung des Python-Skripts\n\n### Einführung in das Python-Skript\n\nDas bereitgestellte Python-Skript dient der Verarbeitung von Daten aus einer CSV-Datei. Es ist so konzipiert, dass es in einer Entwicklungsumgebung (DEV) getestet und anschließend in einer Produktionsumgebung (PROD) eingesetzt werden kann. Die Hauptfunktion des Skripts, `process_data`, ist modular aufgebaut und ermöglicht eine einfache Anpassung und Erweiterung der Datenverarbeitungsschritte.\n\n### Struktur der Hauptfunktion `process_data`\n\nDie Funktion `process_data` ist das Herzstück des Skripts und übernimmt folgende Aufgaben:\n\n1. **Einlesen der Daten:**\n - Die Funktion verwendet die `pandas`-Bibliothek, um Daten aus einer CSV-Datei zu lesen.\n - Der Pfad zur Eingabedatei wird als Argument `input_file` übergeben.\n\n2. **Verarbeitung der Daten:**\n - Nach dem Einlesen wird eine Kopie des DataFrames erstellt, um die Originaldaten unverändert zu lassen.\n - Ein Beispiel für die Datenverarbeitung ist die Transformation einer Spalte namens `data`, bei der die Werte verdoppelt werden.\n\n3. **Speichern der Ergebnisse:**\n - Die verarbeiteten Daten werden in eine neue CSV-Datei geschrieben, deren Pfad als `output_file` angegeben wird.\n - Die Funktion gibt die Anzahl der verarbeiteten Datensätze zurück.\n\n### Detaillierte Beschreibung der Verarbeitungsschritte\n\n#### Einlesen der Daten\n\n- **Bibliothek:** `pandas`\n- **Funktion:** `pd.read_csv(input_file)`\n- **Beschreibung:** Liest die CSV-Datei ein und erstellt einen DataFrame, der die Daten in tabellarischer Form darstellt.\n\n#### Datenverarbeitung\n\n- **Kopieren der Daten:** `processed_df = df.copy()`\n - **Zweck:** Sicherstellen, dass die Originaldaten nicht verändert werden.\n \n- **Transformation:** \n - **Bedingung:** `if 'data' in processed_df.columns`\n - **Operation:** `processed_df['transformed'] = processed_df['data'] * 2`\n - **Beschreibung:** Überprüft, ob die Spalte `data` existiert, und erstellt eine neue Spalte `transformed`, in der die Werte der `data`-Spalte verdoppelt werden.\n\n#### Speichern der Ergebnisse\n\n- **Funktion:** `processed_df.to_csv(output_file, index=False)`\n- **Beschreibung:** Speichert den verarbeiteten DataFrame in einer neuen CSV-Datei. Der Parameter `index=False` stellt sicher, dass die Indexspalte nicht in die Ausgabedatei geschrieben wird.\n\n### Nutzung und Anpassung des Skripts\n\nUm das Skript erfolgreich zu nutzen, sollten folgende Schritte beachtet werden:\n\n1. **Installation von pandas:**\n - Stellen Sie sicher, dass die `pandas`-Bibliothek installiert ist, indem Sie den Befehl `pip install pandas` ausführen.\n\n2. **Anpassung der Dateipfade:**\n - Ändern Sie die Dateipfade im Beispielaufruf des Skripts entsprechend Ihrer Dateistruktur.\n\n3. **Erweiterung der Datenverarbeitung:**\n - Passen Sie die Verarbeitungsschritte innerhalb der Funktion `process_data` an, um spezifische Anforderungen zu erfüllen. Dies könnte das Hinzufügen weiterer Transformationen oder Filterungen umfassen.\n\n### Beispielaufruf und Ausgabe\n\nDas Skript enthält einen Beispielaufruf, der die Funktion `process_data` mit den Dateipfaden `\"input.csv\"` und `\"output.csv\"` ausführt. Nach der Verarbeitung wird die Anzahl der verarbeiteten Datensätze auf der Konsole ausgegeben.\n\n```python\nif __name__ == \"__main__\":\n result = process_data(\"input.csv\", \"output.csv\")\n print(f\"Verarbeitet: {result} Datensätze\")\n```\n\n### Zusammenfassung\n\nDas Python-Skript bietet eine einfache und flexible Möglichkeit zur Datenverarbeitung und kann leicht an unterschiedliche Anforderungen angepasst werden. Durch die Verwendung von `pandas` wird eine effiziente Datenmanipulation ermöglicht, die sowohl in Entwicklungs- als auch in Produktionsumgebungen eingesetzt werden kann.\n\n## 4. Kapitel 4: Anpassung und Erweiterung des Skripts\n\n### Anpassung und Erweiterung des Skripts\n\nIn diesem Kapitel wird erläutert, wie das bereitgestellte Python-Skript zur Datenverarbeitung an spezifische Anforderungen angepasst und erweitert werden kann. Das Ziel ist es, die Funktionalität des Skripts zu erweitern, um zusätzliche Datenverarbeitungsaufgaben zu erfüllen. Wir werden verschiedene Aspekte der Anpassung betrachten, einschließlich der Modifikation der Datenverarbeitungsschritte, der Integration zusätzlicher Bibliotheken und der Optimierung der Leistung.\n\n#### 1. Anpassung der Datenverarbeitungsschritte\n\nDer Kern des Skripts ist die Funktion `process_data`, die derzeit eine einfache Transformation durchführt. Um diese Funktion an spezifische Anforderungen anzupassen, können folgende Schritte unternommen werden:\n\n- **Spaltenauswahl und -filterung**: Passen Sie die Auswahl der Spalten an, um nur die relevanten Daten zu verarbeiten. Dies kann durch Modifikation der Zeile `processed_df = df.copy()` erfolgen, indem Sie spezifische Spalten auswählen, z.B. `processed_df = df[['column1', 'column2']]`.\n\n- **Datenbereinigung**: Fügen Sie Schritte zur Bereinigung der Daten hinzu, wie das Entfernen von Duplikaten (`processed_df.drop_duplicates()`) oder das Behandeln fehlender Werte (`processed_df.fillna(value)`).\n\n- **Erweiterte Transformationen**: Implementieren Sie komplexere Transformationen, wie das Erstellen neuer Spalten basierend auf Berechnungen oder das Anwenden von benutzerdefinierten Funktionen auf die Daten. Beispiel:\n ```python\n processed_df['new_column'] = processed_df['existing_column'].apply(lambda x: complex_transformation(x))\n ```\n\n#### 2. Integration zusätzlicher Bibliotheken\n\nUm die Funktionalität des Skripts zu erweitern, können zusätzliche Python-Bibliotheken integriert werden. Einige nützliche Bibliotheken sind:\n\n- **NumPy**: Für numerische Berechnungen und erweiterte mathematische Operationen.\n ```python\n import numpy as np\n processed_df['log_data'] = np.log(processed_df['data'])\n ```\n\n- **Matplotlib oder Seaborn**: Für die Visualisierung von Daten, um Einblicke in die Datenverteilung oder -trends zu gewinnen.\n ```python\n import matplotlib.pyplot as plt\n processed_df['data'].hist()\n plt.show()\n ```\n\n- **Scikit-learn**: Für maschinelles Lernen und Datenmodellierung, falls prädiktive Analysen erforderlich sind.\n\n#### 3. Optimierung der Leistung\n\nBei der Verarbeitung großer Datenmengen ist die Leistung des Skripts entscheidend. Hier sind einige Ansätze zur Optimierung:\n\n- **Chunkweise Verarbeitung**: Verwenden Sie die `chunksize`-Option von `pandas.read_csv`, um große Dateien in kleineren Teilen zu verarbeiten.\n ```python\n for chunk in pd.read_csv(input_file, chunksize=10000):\n # Verarbeitung des Chunks\n ```\n\n- **Parallelisierung**: Nutzen Sie die `multiprocessing`-Bibliothek, um die Datenverarbeitung auf mehrere Kerne zu verteilen.\n ```python\n from multiprocessing import Pool\n with Pool(processes=4) as pool:\n results = pool.map(process_chunk, data_chunks)\n ```\n\n#### 4. Erweiterung der Ausgabeformate\n\nNeben der Speicherung der Ergebnisse als CSV-Datei können Sie das Skript erweitern, um andere Ausgabeformate zu unterstützen:\n\n- **Excel**: Verwenden Sie `pandas.to_excel` für die Ausgabe in Excel-Format.\n ```python\n processed_df.to_excel(output_file.replace('.csv', '.xlsx'), index=False)\n ```\n\n- **Datenbanken**: Integrieren Sie Bibliotheken wie `SQLAlchemy`, um die Ergebnisse direkt in eine Datenbank zu schreiben.\n ```python\n from sqlalchemy import create_engine\n engine = create_engine('sqlite:///output.db')\n processed_df.to_sql('table_name', engine, if_exists='replace')\n ```\n\n#### 5. Dokumentation und Wartbarkeit\n\nStellen Sie sicher, dass das Skript gut dokumentiert ist, um die Wartbarkeit zu erleichtern. Nutzen Sie Docstrings und Kommentare, um den Zweck und die Funktionsweise der einzelnen Codeabschnitte zu erläutern. Beispiel:\n\n```python\ndef complex_transformation(x):\n \"\"\"\n Führt eine komplexe Transformation auf den Eingabewert x durch.\n \n Args:\n x: Der Eingabewert, der transformiert werden soll.\n \n Returns:\n Der transformierte Wert.\n \"\"\"\n # Transformation durchführen\n return x ** 2 + 10\n```\n\nDurch die Umsetzung dieser Anpassungen und Erweiterungen können Sie das Skript flexibel und leistungsfähig gestalten, um eine Vielzahl von Datenverarbeitungsanforderungen zu erfüllen.\n\n## 5. Kapitel 5: Durchführung der Migration\n\n### Vorbereitung der Umgebung\n\nBevor die Migration von der Entwicklungsumgebung (DEV) in die Produktionsumgebung (PROD) durchgeführt werden kann, müssen einige vorbereitende Schritte unternommen werden, um sicherzustellen, dass die Umgebung korrekt konfiguriert ist und alle Abhängigkeiten erfüllt sind.\n\n#### 1. Installation der erforderlichen Bibliotheken\n\nStellen Sie sicher, dass alle benötigten Python-Bibliotheken in der PROD-Umgebung installiert sind. Für das bereitgestellte Skript ist die `pandas`-Bibliothek erforderlich. Diese kann mit dem folgenden Befehl installiert werden:\n\n```bash\npip install pandas\n```\n\n#### 2. Überprüfung der Dateipfade\n\nPassen Sie die Dateipfade im Skript an die Produktionsumgebung an. Dies betrifft sowohl die Eingabedatei (`input_file`) als auch die Ausgabedatei (`output_file`). Stellen Sie sicher, dass die Pfade korrekt sind und dass die Anwendung die erforderlichen Berechtigungen hat, um auf diese Dateien zuzugreifen.\n\n### Anpassung des Skripts für die Produktionsumgebung\n\nDas Skript muss möglicherweise angepasst werden, um den spezifischen Anforderungen der Produktionsumgebung gerecht zu werden. Dies kann die Anpassung von Dateipfaden, die Erweiterung der Datenverarbeitung oder die Integration zusätzlicher Funktionen umfassen.\n\n#### 1. Anpassung der Dateipfade\n\nÜberprüfen Sie die im Skript angegebenen Dateipfade und passen Sie sie an die Struktur der Produktionsumgebung an. Beispiel:\n\n```python\ninput_file = \"/path/to/prod/input.csv\"\noutput_file = \"/path/to/prod/output.csv\"\n```\n\n#### 2. Erweiterung der Datenverarbeitung\n\nJe nach Anforderung der Produktionsumgebung kann es notwendig sein, die Datenverarbeitung zu erweitern. Dies könnte die Implementierung zusätzlicher Transformationen oder die Integration von Validierungslogiken umfassen. Beispiel:\n\n```python\n# Zusätzliche Transformation\nif 'additional_data' in processed_df.columns:\n processed_df['additional_transformed'] = processed_df['additional_data'] + 10\n```\n\n### Ausführung des Skripts in der Produktionsumgebung\n\nSobald das Skript angepasst wurde, kann es in der Produktionsumgebung ausgeführt werden. Stellen Sie sicher, dass alle vorherigen Schritte abgeschlossen sind, bevor Sie fortfahren.\n\n#### 1. Testlauf\n\nFühren Sie einen Testlauf des Skripts durch, um sicherzustellen, dass es wie erwartet funktioniert. Überprüfen Sie die Ausgabe auf Fehler und stellen Sie sicher, dass die Daten korrekt verarbeitet werden.\n\n```bash\npython script_name.py\n```\n\n#### 2. Überwachung und Logging\n\nImplementieren Sie eine Überwachungs- und Logging-Strategie, um die Ausführung des Skripts in der Produktionsumgebung zu verfolgen. Dies kann durch die Integration von Logging-Funktionen in das Skript erfolgen:\n\n```python\nimport logging\n\nlogging.basicConfig(filename='process.log', level=logging.INFO)\nlogging.info('Datenverarbeitung gestartet')\n\n# Nach der Verarbeitung\nlogging.info('Datenverarbeitung abgeschlossen')\n```\n\n### Dokumentation und Wartung\n\nNach der erfolgreichen Migration und Ausführung des Skripts in der Produktionsumgebung ist es wichtig, die Dokumentation zu aktualisieren und regelmäßige Wartungsarbeiten einzuplanen.\n\n#### 1. Aktualisierung der Dokumentation\n\nDokumentieren Sie alle Änderungen, die während der Migration vorgenommen wurden, einschließlich der Anpassungen des Skripts und der Konfiguration der Umgebung.\n\n#### 2. Planung von Wartungsarbeiten\n\nPlanen Sie regelmäßige Wartungsarbeiten ein, um sicherzustellen, dass das Skript weiterhin effizient und fehlerfrei funktioniert. Dies kann die Überprüfung von Logdateien, die Aktualisierung von Bibliotheken und die Anpassung an geänderte Anforderungen umfassen.\n\n## 6. Kapitel 6: Fehlerbehebung und Optimierung\n\n### Fehlerbehebung und Optimierung\n\nIn diesem Kapitel werden häufig auftretende Probleme bei der Migration von Anwendungen von der Entwicklungsumgebung (DEV) in die Produktionsumgebung (PROD) behandelt. Zudem werden Strategien zur Optimierung der Datenverarbeitung mit Python vorgestellt. Ziel ist es, die Zuverlässigkeit und Effizienz der Anwendung zu gewährleisten.\n\n#### Häufige Probleme und deren Lösungen\n\n1. **Fehlende Abhängigkeiten**\n - **Problem:** Beim Ausführen des Codes in der PROD-Umgebung treten Importfehler auf, weil erforderliche Bibliotheken wie `pandas` nicht installiert sind.\n - **Lösung:** \n - Stellen Sie sicher, dass alle Abhängigkeiten in einer `requirements.txt`-Datei aufgelistet sind.\n - Führen Sie `pip install -r requirements.txt` aus, um alle benötigten Pakete zu installieren.\n\n2. **Pfadprobleme**\n - **Problem:** Die Anwendung kann die Eingabe- oder Ausgabedateien aufgrund falscher Dateipfade nicht finden.\n - **Lösung:** \n - Verwenden Sie absolute Pfade oder stellen Sie sicher, dass relative Pfade korrekt sind.\n - Überprüfen Sie die Berechtigungen für den Zugriff auf die Dateipfade in der PROD-Umgebung.\n\n3. **Speicherprobleme**\n - **Problem:** Bei großen Datensätzen kann es zu Speicherproblemen kommen, die zu einem Absturz der Anwendung führen.\n - **Lösung:** \n - Nutzen Sie `pandas`-Funktionen wie `chunksize`, um Daten in kleineren Teilen zu verarbeiten.\n - Verwenden Sie `dask` oder `modin` als Alternativen zu `pandas` für die Verarbeitung großer Datenmengen.\n\n4. **Leistungsprobleme**\n - **Problem:** Die Datenverarbeitung dauert länger als erwartet.\n - **Lösung:** \n - Optimieren Sie den Code durch Vektorisierung anstelle von Schleifen.\n - Verwenden Sie effiziente Datenstrukturen und Algorithmen.\n - Profilieren Sie den Code mit Tools wie `cProfile`, um Engpässe zu identifizieren.\n\n#### Optimierung der Datenverarbeitung\n\n1. **Effiziente Nutzung von `pandas`**\n - **Vektorisierung:** Ersetzen Sie Schleifen durch vektorisierte Operationen, um die Leistung zu verbessern.\n - **Speicheroptimierung:** Verwenden Sie geeignete Datentypen, um den Speicherverbrauch zu reduzieren, z.B. `float32` statt `float64`.\n\n2. **Parallelisierung**\n - Nutzen Sie die `multiprocessing`-Bibliothek, um Aufgaben parallel auszuführen und die CPU-Auslastung zu maximieren.\n - Erwägen Sie den Einsatz von `joblib` für einfache Parallelisierungsaufgaben.\n\n3. **Caching von Ergebnissen**\n - Implementieren Sie Caching-Mechanismen, um wiederholte Berechnungen zu vermeiden, z.B. mit `functools.lru_cache`.\n\n4. **Profiling und Monitoring**\n - Verwenden Sie Tools wie `pandas_profiling` zur Analyse von Datensätzen und zur Identifizierung potenzieller Engpässe.\n - Setzen Sie Monitoring-Tools ein, um die Leistung der Anwendung in der PROD-Umgebung kontinuierlich zu überwachen.\n\n#### Beispiel für eine optimierte Datenverarbeitung\n\n```python\nimport pandas as pd\n\ndef optimized_process_data(input_file, output_file):\n \"\"\"\n Optimierte Verarbeitung von Daten aus einer Eingabedatei und Speicherung der Ergebnisse.\n \n Args:\n input_file: Pfad zur Eingabedatei\n output_file: Pfad zur Ausgabedatei\n \"\"\"\n # Daten in Chunks einlesen\n chunksize = 10000\n for chunk in pd.read_csv(input_file, chunksize=chunksize):\n # Beispiel für eine vektorisierte Operation\n if 'data' in chunk.columns:\n chunk['transformed'] = chunk['data'] * 2\n \n # Ergebnis speichern\n chunk.to_csv(output_file, mode='a', header=False, index=False)\n\n# Beispielaufruf\nif __name__ == \"__main__\":\n optimized_process_data(\"input.csv\", \"output.csv\")\n```\n\nDurch die Anwendung dieser Techniken können Sie die Zuverlässigkeit und Effizienz Ihrer Anwendung in der Produktionsumgebung erheblich verbessern.\n\n## 7. Kapitel 7: Zusammenfassung und Ausblick\n\nIn diesem Kapitel werden die wesentlichen Aspekte der Anwendungsmigration von der Entwicklungsumgebung (DEV) zur Produktionsumgebung (PROD) zusammengefasst. Zudem werden potenzielle zukünftige Entwicklungen und Erweiterungen der Datenverarbeitung mit Python skizziert.\n\n**Zusammenfassung der Migration**\n\n1. **Analyse und Planung**:\n - Die Anforderungen wurden gründlich analysiert, um sicherzustellen, dass alle funktionalen und nicht-funktionalen Anforderungen in der Produktionsumgebung erfüllt werden.\n - Ein modularer Codeansatz wurde gewählt, um Flexibilität und Erweiterbarkeit zu gewährleisten.\n\n2. **Technische Umsetzung**:\n - Der entwickelte Python-Code liest Daten aus einer CSV-Datei ein, verarbeitet diese und speichert die Ergebnisse in einer neuen CSV-Datei.\n - Die Hauptfunktion `process_data` ist so gestaltet, dass sie leicht an spezifische Anforderungen angepasst werden kann, indem zusätzliche Verarbeitungsschritte hinzugefügt werden.\n\n3. **Integration in die Produktionsumgebung**:\n - Sicherstellung der Verfügbarkeit aller erforderlichen Bibliotheken, insbesondere `pandas`, um die Datenverarbeitung reibungslos zu gestalten.\n - Anpassung der Dateipfade und Sicherstellung der Zugriffsrechte auf die benötigten Dateien in der Produktionsumgebung.\n\n4. **Qualitätssicherung**:\n - Durchführung von Tests, um die korrekte Funktionalität der Datenverarbeitung sicherzustellen.\n - Überprüfung der Ausgabeformate und der Datenintegrität nach der Verarbeitung.\n\n**Ausblick auf zukünftige Entwicklungen**\n\n1. **Erweiterung der Datenverarbeitung**:\n - Implementierung zusätzlicher Datenverarbeitungsfunktionen, wie z.B. Datenbereinigung, Aggregation und komplexe Transformationen.\n - Nutzung von Machine-Learning-Algorithmen zur Vorhersage und Mustererkennung in den Daten.\n\n2. **Optimierung der Performance**:\n - Einsatz von Parallelverarbeitung und Optimierung der Speicherverwaltung, um die Verarbeitung großer Datenmengen effizienter zu gestalten.\n - Untersuchung der Möglichkeiten zur Integration von Big-Data-Technologien wie Apache Spark.\n\n3. **Automatisierung und Monitoring**:\n - Entwicklung von Skripten zur Automatisierung der Datenverarbeitung und Integration in CI/CD-Pipelines.\n - Implementierung von Monitoring-Tools zur Überwachung der Datenverarbeitungsprozesse und zur schnellen Erkennung von Anomalien.\n\n4. **Erweiterung der Benutzeroberfläche**:\n - Entwicklung einer benutzerfreundlichen Oberfläche zur Konfiguration und Steuerung der Datenverarbeitung durch Endbenutzer.\n - Integration von Visualisierungswerkzeugen zur Darstellung der Verarbeitungsergebnisse.\n\n**Schlussfolgerung**\n\nDie Migration der Anwendung von DEV nach PROD wurde erfolgreich durchgeführt, wobei der Fokus auf Modularität und Erweiterbarkeit lag. Die bereitgestellten technischen Anleitungen und der entwickelte Code bieten eine solide Grundlage für die zukünftige Weiterentwicklung der Datenverarbeitungsprozesse. Durch die geplanten Erweiterungen und Optimierungen kann die Anwendung weiter an die sich ändernden Anforderungen und technologischen Entwicklungen angepasst werden.\n\n---\n\n**Erstellt durch:** Dokumentation", + "agent_type": "documentation", + "agent_id": "documentation_agent", + "agent_name": "Dokumentation" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n**Zusammenfassung der Agentenergebnisse**\n\n### Entwicklerbericht\n\n**Code-Entwicklung:**\n- **Funktion:** `process_data(input_file, output_file)`\n - **Zweck:** Liest eine CSV-Datei ein, verarbeitet die Daten und speichert das Ergebnis.\n - **Verarbeitung:** Verdoppelt Werte in der Spalte `data`, falls vorhanden.\n - **Modularität:** Die Funktion ist erweiterbar für spezifische Anforderungen.\n- **Verwendungshinweise:**\n 1. Installation von `pandas` erforderlich (`pip install pandas`).\n 2. Anpassung der Dateipfade im Beispielaufruf.\n 3. Erweiterung der Verarbeitungsschritte nach Bedarf.\n\n### Dokumentation zur Anwendungsmigration\n\n**Bericht zur DEV-PROD Migration:**\n- **Ziel:** Anleitung zur Migration von Anwendungen von DEV nach PROD mit Fokus auf Datenverarbeitung mittels Python.\n- **Hauptfunktion:** `process_data` zur CSV-Datenverarbeitung, modular und erweiterbar.\n- **Voraussetzungen:** Installation von Python und `pandas`, Anpassung der Dateipfade.\n\n**Kapitelübersicht:**\n1. **Einleitung:** Bedeutung und Ziele der Migration.\n2. **Technische Voraussetzungen:** Software- und Systemanforderungen, Sicherheits- und Testanforderungen.\n3. **Beschreibung des Python-Skripts:** Struktur und Nutzung der `process_data` Funktion.\n4. **Anpassung und Erweiterung:** Anpassung der Datenverarbeitung, Integration zusätzlicher Bibliotheken, Leistungsoptimierung.\n5. **Durchführung der Migration:** Vorbereitung, Anpassung und Ausführung des Skripts in PROD.\n6. **Fehlerbehebung und Optimierung:** Häufige Probleme und Lösungen, Optimierungstechniken.\n7. **Zusammenfassung und Ausblick:** Rückblick auf die Migration und zukünftige Entwicklungen.\n\n**Technische Herausforderungen und Lösungen:**\n- **Datenkonsistenz:** Robuste Datenverarbeitungsprozesse in Python.\n- **Umgebungsunterschiede:** Anpassung an unterschiedliche Konfigurationen.\n- **Automatisierung:** Einsatz von Automatisierungstools zur Fehlerreduktion.\n\n**Zukünftige Entwicklungen:**\n- **Erweiterung der Datenverarbeitung:** Implementierung komplexer Transformationen und Machine-Learning-Algorithmen.\n- **Performance-Optimierung:** Parallelverarbeitung und Big-Data-Technologien.\n- **Automatisierung und Monitoring:** CI/CD-Integration und Anomalieerkennung.\n- **Benutzeroberfläche:** Entwicklung einer benutzerfreundlichen Oberfläche und Visualisierungstools.\n\n**Schlussfolgerung:**\nDie Migration von DEV nach PROD wurde erfolgreich umgesetzt, mit einem Fokus auf Modularität und Erweiterbarkeit. Die bereitgestellten Anleitungen und der Code bieten eine solide Grundlage für zukünftige Entwicklungen und Anpassungen an technologische Fortschritte.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true, + "finished_at": "2025-04-06T12:50:05.456969", + "status": "completed" + }, + { + "id": "msg_aa3a5346-bb25-4a75-84f6-f6f1c1d01440", + "workflow_id": "a3b24a29-8543-4340-8f25-f44841836e37", + "parent_message_id": null, + "started_at": "2025-04-06T12:50:05.456969", + "finished_at": null, + "sequence_no": 5, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "kannst du mir eine kurze checkliste fürs esten als tabelle machen?", + "agent_type": null + }, + { + "id": "msg_ba8ab953-063d-43bf-bdaa-07717acf6b7b", + "workflow_id": "a3b24a29-8543-4340-8f25-f44841836e37", + "parent_message_id": null, + "started_at": "2025-04-06T12:51:22.141377", + "finished_at": "2025-04-06T12:51:22.167823", + "sequence_no": 6, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "# Checkliste für Testprozesse: Wichtige Schritte und Punkte in Tabellenform\n\n## Zusammenfassung\n\nDas Dokument \"Checkliste für Testprozesse: Wichtige Schritte und Punkte in Tabellenform\" bietet eine strukturierte Übersicht über die wesentlichen Schritte und Aspekte, die bei der Durchführung von Testprozessen beachtet werden sollten. Es dient als Leitfaden, um sicherzustellen, dass alle relevanten Testaktivitäten systematisch und effizient durchgeführt werden. Die Checkliste ist in Tabellenform organisiert, um eine klare und leicht verständliche Darstellung der Testschritte zu gewährleisten. Ziel ist es, die Qualität und Konsistenz von Testprozessen zu verbessern, indem alle kritischen Punkte berücksichtigt werden.\n\n## Inhaltsverzeichnis\n\n1. Kapitel 1: Einführung in den Testprozess\n2. Kapitel 2: Planung und Vorbereitung\n3. Kapitel 3: Testdurchführung\n4. Kapitel 4: Dokumentation und Berichterstattung\n5. Kapitel 5: Bewertung und Analyse\n6. Kapitel 6: Abschluss und Nachbereitung\n7. Kapitel 7: Checkliste in Tabellenform\n\n## 1. Kapitel 1: Einführung in den Testprozess\n\nEinführung in den Testprozess\n\nIn der heutigen schnelllebigen und technologiegetriebenen Welt ist die Qualitätssicherung ein entscheidender Faktor für den Erfolg von Softwareprojekten. Ein strukturierter Testprozess ist unerlässlich, um sicherzustellen, dass Softwareprodukte den Anforderungen entsprechen und frei von kritischen Fehlern sind. Dieses Kapitel bietet eine grundlegende Einführung in den Testprozess und hebt die Bedeutung strukturierter Testmethoden hervor.\n\n### Bedeutung von Testprozessen\n\nTestprozesse sind systematische Ansätze zur Überprüfung und Validierung von Software, um sicherzustellen, dass sie den festgelegten Anforderungen entspricht. Ein gut definierter Testprozess hilft, Fehler frühzeitig zu erkennen, die Qualität zu verbessern und die Kundenzufriedenheit zu erhöhen. Die Implementierung eines strukturierten Testprozesses kann auch die Entwicklungszeit verkürzen und die Kosten für Nachbesserungen reduzieren.\n\n### Grundlegende Schritte im Testprozess\n\nEin effektiver Testprozess besteht aus mehreren Schritten, die sorgfältig geplant und ausgeführt werden müssen. Die folgende Tabelle bietet eine Übersicht über die wichtigsten Schritte und Punkte, die in einem Testprozess berücksichtigt werden sollten:\n\n| Schritt | Beschreibung |\n|--------------------------|------------------------------------------------------------------------------|\n| **Anforderungsanalyse** | Überprüfung der Anforderungen, um sicherzustellen, dass sie vollständig und testbar sind. |\n| **Testplanung** | Erstellung eines detaillierten Testplans, der die Teststrategie, Ziele, Ressourcen und Zeitpläne umfasst. |\n| **Testdesign** | Entwicklung von Testfällen und Testszenarien basierend auf den Anforderungen und der Teststrategie. |\n| **Testumgebung** | Einrichtung und Validierung der Testumgebung, um sicherzustellen, dass sie die Produktionsumgebung genau widerspiegelt. |\n| **Testdurchführung** | Ausführung der Testfälle und Dokumentation der Ergebnisse. |\n| **Fehlerberichterstattung** | Identifizierung und Dokumentation von Fehlern, die während der Testdurchführung entdeckt werden. |\n| **Testabschluss** | Bewertung der Testergebnisse, Erstellung eines Testabschlussberichts und Durchführung einer retrospektiven Analyse zur Verbesserung zukünftiger Testprozesse. |\n\n### Vorteile eines strukturierten Testprozesses\n\n- **Früherkennung von Fehlern:** Durch systematisches Testen können Fehler frühzeitig im Entwicklungszyklus erkannt und behoben werden.\n- **Verbesserte Qualität:** Ein strukturierter Ansatz stellt sicher, dass alle Aspekte der Software gründlich getestet werden, was zu einer höheren Qualität führt.\n- **Effiziente Ressourcennutzung:** Durch klare Planung und Organisation können Ressourcen effizienter genutzt werden.\n- **Risikominimierung:** Ein gut definierter Testprozess hilft, potenzielle Risiken zu identifizieren und zu mindern, bevor sie zu größeren Problemen werden.\n\n### Fazit\n\nEin strukturierter Testprozess ist ein wesentlicher Bestandteil der Softwareentwicklung, der dazu beiträgt, qualitativ hochwertige Produkte zu liefern. Durch die Implementierung eines klaren und systematischen Ansatzes können Unternehmen sicherstellen, dass ihre Software den Anforderungen entspricht und die Erwartungen der Benutzer erfüllt. In den folgenden Kapiteln werden wir die einzelnen Schritte des Testprozesses detaillierter untersuchen und Best Practices für die Durchführung effektiver Tests vorstellen.\n\n## 2. Kapitel 2: Planung und Vorbereitung\n\n### Planung und Vorbereitung\n\nIn der Phase der Planung und Vorbereitung eines Testprozesses ist es entscheidend, klare Ziele zu definieren und die geeigneten Methoden auszuwählen, um die Effektivität und Effizienz des Testens zu maximieren. Die folgende Checkliste bietet eine strukturierte Übersicht über die wesentlichen Schritte und Punkte, die in dieser Phase berücksichtigt werden sollten.\n\n#### 1. Definition der Testziele\n\n- **Ziele festlegen**: Bestimmen Sie, was mit dem Testprozess erreicht werden soll (z.B. Fehlererkennung, Qualitätssicherung, Validierung von Anforderungen).\n- **Erfolgskriterien definieren**: Legen Sie fest, welche Kriterien erfüllt sein müssen, um den Test als erfolgreich zu bewerten.\n\n#### 2. Analyse der Testanforderungen\n\n- **Anforderungsdokumente überprüfen**: Stellen Sie sicher, dass alle relevanten Anforderungsdokumente vollständig und aktuell sind.\n- **Risikobewertung durchführen**: Identifizieren Sie potenzielle Risiken und priorisieren Sie diese nach ihrer Auswirkung und Wahrscheinlichkeit.\n\n#### 3. Auswahl der Testmethoden\n\n- **Geeignete Testmethoden bestimmen**: Wählen Sie die Testmethoden aus, die am besten zu den definierten Zielen und Anforderungen passen (z.B. manuelle Tests, automatisierte Tests, explorative Tests).\n- **Werkzeuge und Technologien evaluieren**: Entscheiden Sie, welche Werkzeuge und Technologien zur Unterstützung der Testmethoden eingesetzt werden sollen.\n\n#### 4. Erstellung eines Testplans\n\n- **Teststrategie entwickeln**: Dokumentieren Sie die übergeordnete Strategie, die den Testprozess leiten wird.\n- **Ressourcen planen**: Identifizieren Sie die benötigten Ressourcen, einschließlich Personal, Hardware und Software.\n- **Zeitplan erstellen**: Legen Sie einen realistischen Zeitrahmen für die Durchführung der Tests fest.\n\n#### 5. Vorbereitung der Testumgebung\n\n- **Testumgebung einrichten**: Stellen Sie sicher, dass die Testumgebung die Bedingungen der Produktionsumgebung so genau wie möglich widerspiegelt.\n- **Daten vorbereiten**: Erstellen Sie Testdaten, die die realen Daten repräsentieren und die Testziele unterstützen.\n\n#### 6. Kommunikation und Koordination\n\n- **Stakeholder informieren**: Kommunizieren Sie den Testplan und die Testziele an alle relevanten Stakeholder.\n- **Teamrollen definieren**: Klären Sie die Rollen und Verantwortlichkeiten innerhalb des Testteams.\n\n### Checkliste in Tabellenform\n\n| Schritt | Beschreibung |\n|-------------------------------|------------------------------------------------------------------------------|\n| **Testziele definieren** | Festlegung der Ziele und Erfolgskriterien des Testprozesses. |\n| **Anforderungen analysieren** | Überprüfung der Anforderungsdokumente und Durchführung einer Risikobewertung.|\n| **Testmethoden auswählen** | Bestimmung geeigneter Testmethoden und Evaluierung von Werkzeugen. |\n| **Testplan erstellen** | Entwicklung einer Teststrategie, Ressourcenplanung und Zeitplanerstellung. |\n| **Testumgebung vorbereiten** | Einrichtung der Testumgebung und Vorbereitung der Testdaten. |\n| **Kommunikation sicherstellen** | Information der Stakeholder und Definition der Teamrollen. |\n\nDiese strukturierte Herangehensweise stellt sicher, dass der Testprozess gut geplant und vorbereitet ist, was die Grundlage für erfolgreiche Tests und qualitativ hochwertige Ergebnisse bildet.\n\n## 3. Kapitel 3: Testdurchführung\n\n### Testdurchführung\n\nDie Testdurchführung ist ein entscheidender Schritt im Testprozess, bei dem die zuvor geplanten und spezifizierten Testfälle tatsächlich ausgeführt werden. In diesem Kapitel wird detailliert beschrieben, wie die Testdurchführung organisiert und durchgeführt wird, um sicherzustellen, dass alle Anforderungen und Spezifikationen erfüllt werden. Die folgenden Schritte und Punkte sind in einer Checkliste zusammengefasst, um den Prozess effizient und effektiv zu gestalten.\n\n#### 1. Erstellung von Testfällen\n\n- **Identifikation der Testfälle**: \n - Basierend auf den Anforderungen und Spezifikationen.\n - Priorisierung der Testfälle nach Kritikalität und Risiko.\n\n- **Detaillierung der Testfälle**: \n - Beschreibung der Testschritte.\n - Definition der erwarteten Ergebnisse.\n - Festlegung der Eingabedaten.\n\n- **Überprüfung und Freigabe**: \n - Peer-Review der Testfälle.\n - Freigabe durch den Testmanager.\n\n#### 2. Vorbereitung der Testumgebung\n\n- **Einrichtung der Testumgebung**: \n - Installation der erforderlichen Software und Hardware.\n - Sicherstellung der Netzwerkkonfiguration.\n\n- **Datenvorbereitung**: \n - Erstellung oder Beschaffung von Testdaten.\n - Sicherstellung der Datenintegrität und -sicherheit.\n\n- **Umgebungsüberprüfung**: \n - Validierung der Testumgebung durch einen Testlauf.\n - Dokumentation von Abweichungen und deren Behebung.\n\n#### 3. Testausführung\n\n- **Durchführung der Tests**: \n - Ausführung der Testfälle gemäß der Testdokumentation.\n - Dokumentation der Testergebnisse und Abweichungen.\n\n- **Fehlererfassung und -management**: \n - Erfassung von Fehlern in einem Fehlerverfolgungssystem.\n - Priorisierung und Zuweisung der Fehler zur Behebung.\n\n- **Kommunikation und Berichterstattung**: \n - Regelmäßige Updates an das Testteam und die Stakeholder.\n - Erstellung von Testberichten mit den Ergebnissen und Erkenntnissen.\n\n#### Checkliste für die Testdurchführung\n\n| Schritt | Beschreibung |\n|--------------------------|------------------------------------------------------------------------------|\n| Testfallidentifikation | Auswahl und Priorisierung der Testfälle basierend auf Anforderungen. |\n| Testfalldetaillierung | Ausarbeitung der Testschritte und erwarteten Ergebnisse. |\n| Testfallüberprüfung | Peer-Review und Freigabe der Testfälle. |\n| Testumgebungseinrichtung | Installation und Konfiguration der notwendigen Software und Hardware. |\n| Datenvorbereitung | Erstellung und Validierung der Testdaten. |\n| Umgebungsüberprüfung | Validierung der Testumgebung durch einen Testlauf. |\n| Testausführung | Durchführung der Tests und Dokumentation der Ergebnisse. |\n| Fehlererfassung | Erfassung und Verwaltung von Fehlern im Fehlerverfolgungssystem. |\n| Berichterstattung | Erstellung von Testberichten und Kommunikation der Ergebnisse an Stakeholder.|\n\nDiese Checkliste dient als Leitfaden für die Testdurchführung und hilft dabei, sicherzustellen, dass alle wesentlichen Aspekte berücksichtigt werden, um die Qualität und Zuverlässigkeit des zu testenden Systems zu gewährleisten.\n\n## 4. Kapitel 4: Dokumentation und Berichterstattung\n\n### Dokumentation und Berichterstattung\n\nDie Dokumentation und Berichterstattung von Testergebnissen ist ein entscheidender Schritt im Testprozess, der sicherstellt, dass alle Testergebnisse nachvollziehbar und transparent sind. Eine strukturierte und gut dokumentierte Berichterstattung ermöglicht es den Stakeholdern, fundierte Entscheidungen zu treffen und den Fortschritt des Testprozesses zu überwachen. Im Folgenden wird eine Checkliste in Tabellenform präsentiert, die die wichtigsten Schritte und Punkte für eine effektive Dokumentation und Berichterstattung umfasst.\n\n#### Checkliste für die Dokumentation und Berichterstattung\n\n| **Schritt** | **Beschreibung** | **Wichtige Punkte** |\n|-------------|------------------|---------------------|\n| **1. Testplan-Dokumentation** | Erstellen eines umfassenden Testplans, der die Teststrategie, Ziele und den Umfang definiert. | - Zielsetzung klar definieren
- Testumfang und -grenzen festlegen
- Ressourcen und Zeitplan dokumentieren |\n| **2. Testfall-Dokumentation** | Detaillierte Beschreibung der Testfälle, einschließlich der Eingabedaten, erwarteten Ergebnisse und Testbedingungen. | - Eindeutige Identifikation jedes Testfalls
- Beschreibung der Testschritte
- Definition der erwarteten Ergebnisse |\n| **3. Testdurchführung** | Systematische Durchführung der Testfälle gemäß dem Testplan. | - Testumgebung vorbereiten
- Testdaten bereitstellen
- Testergebnisse protokollieren |\n| **4. Fehlerprotokollierung** | Dokumentation aller während der Tests entdeckten Fehler und Abweichungen. | - Eindeutige Identifikation jedes Fehlers
- Beschreibung der Fehlerbedingungen
- Priorisierung und Klassifizierung der Fehler |\n| **5. Testbericht-Erstellung** | Zusammenfassung der Testergebnisse und Erstellung eines Berichts für die Stakeholder. | - Übersicht über die Testabdeckung
- Zusammenfassung der gefundenen Fehler
- Empfehlungen und nächste Schritte |\n| **6. Review und Freigabe** | Überprüfung der Dokumentation und Berichte durch relevante Stakeholder und Freigabe der Ergebnisse. | - Durchführung von Peer-Reviews
- Einholen von Feedback
- Offizielle Freigabe der Dokumentation |\n\n#### Detaillierte Beschreibung der Schritte\n\n**1. Testplan-Dokumentation:** \nDer Testplan ist das Fundament des Testprozesses. Er sollte klar die Ziele, den Umfang und die Strategie des Tests definieren. Ein gut dokumentierter Testplan hilft dabei, den Testprozess zu steuern und sicherzustellen, dass alle Beteiligten die gleichen Erwartungen haben.\n\n**2. Testfall-Dokumentation:** \nTestfälle sollten detailliert beschrieben werden, um sicherzustellen, dass sie reproduzierbar und nachvollziehbar sind. Jeder Testfall sollte eine eindeutige Identifikation, eine klare Beschreibung der Testschritte und die erwarteten Ergebnisse enthalten.\n\n**3. Testdurchführung:** \nWährend der Testdurchführung ist es wichtig, die Testumgebung korrekt vorzubereiten und alle notwendigen Testdaten bereitzustellen. Die Ergebnisse der Testfälle sollten sorgfältig protokolliert werden, um eine spätere Analyse zu ermöglichen.\n\n**4. Fehlerprotokollierung:** \nAlle während der Tests entdeckten Fehler müssen dokumentiert werden. Eine klare Beschreibung der Fehlerbedingungen und eine Priorisierung helfen dabei, die Fehler effizient zu beheben und die Qualität des Produkts zu verbessern.\n\n**5. Testbericht-Erstellung:** \nDer Testbericht fasst die Ergebnisse des Testprozesses zusammen und bietet eine Grundlage für Entscheidungen. Er sollte eine Übersicht über die Testabdeckung, die gefundenen Fehler und Empfehlungen für die nächsten Schritte enthalten.\n\n**6. Review und Freigabe:** \nDie Dokumentation und Berichte sollten von relevanten Stakeholdern überprüft werden, um sicherzustellen, dass sie vollständig und korrekt sind. Nach der Überprüfung sollte eine offizielle Freigabe erfolgen, um den Abschluss des Testprozesses zu bestätigen.\n\nDiese Checkliste dient als Leitfaden für die effektive Dokumentation und Berichterstattung im Testprozess und trägt dazu bei, die Qualität und Transparenz der Testergebnisse zu gewährleisten.\n\n## 5. Kapitel 5: Bewertung und Analyse\n\n### Bewertung und Analyse der Testergebnisse\n\nIn diesem Kapitel werden die wesentlichen Schritte zur Bewertung und Analyse der Testergebnisse beschrieben. Ziel ist es, Schwachstellen im getesteten System zu identifizieren und fundierte Vorschläge für Verbesserungen zu erarbeiten. Die folgende Checkliste bietet eine strukturierte Übersicht über die wichtigsten Punkte, die bei der Bewertung und Analyse berücksichtigt werden sollten.\n\n#### Checkliste für die Bewertung und Analyse\n\n| Schritt | Beschreibung | Wichtige Punkte |\n|---------|--------------|-----------------|\n| **1. Sammlung der Testergebnisse** | Sammeln Sie alle relevanten Testergebnisse aus verschiedenen Testphasen und -arten. | - Sicherstellen, dass alle Testergebnisse vollständig und korrekt dokumentiert sind.
- Ergebnisse aus funktionalen, nicht-funktionalen, Regressionstests usw. einbeziehen. |\n| **2. Validierung der Testergebnisse** | Überprüfen Sie die Testergebnisse auf Genauigkeit und Vollständigkeit. | - Überprüfen, ob alle Testfälle ausgeführt wurden.
- Sicherstellen, dass die Testergebnisse den erwarteten Ergebnissen entsprechen. |\n| **3. Identifikation von Abweichungen** | Ermitteln Sie Abweichungen zwischen den erwarteten und tatsächlichen Ergebnissen. | - Dokumentieren Sie alle Abweichungen detailliert.
- Klassifizieren Sie Abweichungen nach Schweregrad und Priorität. |\n| **4. Ursachenanalyse** | Führen Sie eine Ursachenanalyse für identifizierte Abweichungen durch. | - Verwenden Sie Techniken wie die 5-Why-Methode oder Ishikawa-Diagramme.
- Untersuchen Sie sowohl technische als auch prozessuale Ursachen. |\n| **5. Bewertung der Testabdeckung** | Analysieren Sie die Testabdeckung, um sicherzustellen, dass alle relevanten Bereiche getestet wurden. | - Überprüfen Sie die Testabdeckung anhand der Anforderungen und Spezifikationen.
- Identifizieren Sie ungetestete Bereiche und bewerten Sie deren Risiko. |\n| **6. Bewertung der Testeffektivität** | Bewerten Sie die Effektivität der durchgeführten Tests. | - Analysieren Sie die Anzahl der gefundenen Fehler im Verhältnis zu den durchgeführten Tests.
- Überprüfen Sie, ob die Tests die wichtigsten Risiken abgedeckt haben. |\n| **7. Dokumentation der Ergebnisse** | Dokumentieren Sie die Analyseergebnisse und Erkenntnisse. | - Erstellen Sie einen detaillierten Bericht mit allen identifizierten Schwachstellen und Verbesserungsvorschlägen.
- Stellen Sie sicher, dass die Dokumentation klar und verständlich ist. |\n| **8. Vorschläge für Verbesserungen** | Entwickeln Sie konkrete Vorschläge zur Verbesserung des Systems und der Testprozesse. | - Priorisieren Sie die Vorschläge nach deren Einfluss auf die Qualität und den Aufwand.
- Berücksichtigen Sie sowohl kurzfristige als auch langfristige Verbesserungen. |\n| **9. Kommunikation der Ergebnisse** | Kommunizieren Sie die Ergebnisse und Vorschläge an alle relevanten Stakeholder. | - Präsentieren Sie die Ergebnisse in Meetings oder Berichten.
- Stellen Sie sicher, dass alle Stakeholder die Ergebnisse verstehen und akzeptieren. |\n\n#### Detaillierte Analyse und Berichterstattung\n\n- **Erstellung eines Abschlussberichts:** Fassen Sie alle Ergebnisse und Analysen in einem umfassenden Abschlussbericht zusammen. Dieser Bericht sollte alle identifizierten Schwachstellen, deren Ursachen und die vorgeschlagenen Verbesserungen enthalten.\n\n- **Feedback-Schleifen:** Implementieren Sie Feedback-Schleifen, um kontinuierliche Verbesserungen zu gewährleisten. Nutzen Sie die Erkenntnisse aus der Analyse, um zukünftige Testprozesse zu optimieren.\n\n- **Lessons Learned:** Dokumentieren Sie die \"Lessons Learned\" aus dem Testprozess, um Wissen für zukünftige Projekte zu sichern und ähnliche Fehler zu vermeiden.\n\nDiese strukturierte Herangehensweise an die Bewertung und Analyse der Testergebnisse stellt sicher, dass alle relevanten Aspekte berücksichtigt werden und der Testprozess kontinuierlich verbessert wird.\n\n## 6. Kapitel 6: Abschluss und Nachbereitung\n\n### Abschluss und Nachbereitung\n\nIn diesem Kapitel werden die abschließenden Schritte des Testprozesses behandelt, die sicherstellen, dass alle Testaktivitäten ordnungsgemäß abgeschlossen sind und wertvolle Erkenntnisse für zukünftige Testprozesse gewonnen werden. Die Nachbereitung ist entscheidend, um die Qualität und Effizienz zukünftiger Tests zu verbessern. Die folgende Checkliste bietet eine strukturierte Übersicht über die wichtigsten Schritte und Punkte, die in dieser Phase berücksichtigt werden sollten.\n\n#### Checkliste für den Abschluss und die Nachbereitung des Testprozesses\n\n| Schritt | Beschreibung | Verantwortlich | Status |\n|---------|--------------|----------------|--------|\n| **1. Testabschlussbericht erstellen** | Zusammenfassung der Testergebnisse, aufgetretenen Probleme und der erreichten Testabdeckung. | Testmanager | ☐ |\n| **2. Fehlerbewertung und -dokumentation** | Analyse und Dokumentation aller während des Tests gefundenen Fehler, einschließlich ihrer Schwere und Priorität. | Testteam | ☐ |\n| **3. Lessons Learned Sitzung durchführen** | Durchführung einer Sitzung zur Besprechung der gewonnenen Erkenntnisse und zur Identifizierung von Verbesserungsmöglichkeiten. | Testmanager, Testteam | ☐ |\n| **4. Testumgebung bereinigen** | Rücksetzung und Bereinigung der Testumgebung, um sie für zukünftige Tests vorzubereiten. | IT-Support | ☐ |\n| **5. Testdokumentation archivieren** | Sicherstellung, dass alle relevanten Testdokumente ordnungsgemäß archiviert und zugänglich sind. | Testmanager | ☐ |\n| **6. Feedback von Stakeholdern einholen** | Einholung von Feedback von allen relevanten Stakeholdern, um deren Zufriedenheit und Verbesserungsvorschläge zu erfassen. | Testmanager | ☐ |\n| **7. Maßnahmen zur Prozessoptimierung ableiten** | Identifizierung und Dokumentation von Maßnahmen zur Optimierung zukünftiger Testprozesse basierend auf den gewonnenen Erkenntnissen. | Testmanager, Prozessverantwortlicher | ☐ |\n\n#### Detaillierte Beschreibung der Schritte\n\n1. **Testabschlussbericht erstellen**\n - Der Testabschlussbericht sollte eine umfassende Übersicht über die Testergebnisse bieten. Er sollte die Testabdeckung, die Anzahl der durchgeführten Testfälle, die Anzahl der gefundenen Fehler und deren Status sowie eine Bewertung der Testziele enthalten.\n\n2. **Fehlerbewertung und -dokumentation**\n - Eine detaillierte Analyse der gefundenen Fehler ist entscheidend. Jeder Fehler sollte hinsichtlich seiner Ursache, Schwere und Priorität bewertet werden. Diese Informationen sind wichtig für die Entwicklung und das Management, um zukünftige Fehler zu vermeiden.\n\n3. **Lessons Learned Sitzung durchführen**\n - Diese Sitzung bietet die Gelegenheit, die Erfahrungen des Testteams zu reflektieren und zu dokumentieren. Es sollten sowohl positive Aspekte als auch Herausforderungen besprochen werden, um daraus zu lernen.\n\n4. **Testumgebung bereinigen**\n - Nach Abschluss der Tests sollte die Testumgebung aufgeräumt und in ihren ursprünglichen Zustand zurückversetzt werden. Dies stellt sicher, dass keine Testdaten oder Konfigurationen zukünftige Tests beeinflussen.\n\n5. **Testdokumentation archivieren**\n - Alle Testdokumente, einschließlich Testpläne, Testfälle, Berichte und Protokolle, sollten sicher archiviert werden. Dies erleichtert den Zugriff auf vergangene Informationen und unterstützt die Nachvollziehbarkeit.\n\n6. **Feedback von Stakeholdern einholen**\n - Das Einholen von Feedback von Stakeholdern, wie Entwicklern, Kunden und Management, ist wichtig, um deren Perspektiven zu verstehen und die Zufriedenheit mit dem Testprozess zu bewerten.\n\n7. **Maßnahmen zur Prozessoptimierung ableiten**\n - Basierend auf den Erkenntnissen aus dem Testprozess sollten konkrete Maßnahmen zur Verbesserung zukünftiger Testprozesse abgeleitet und dokumentiert werden. Dies kann die Anpassung von Teststrategien, die Verbesserung von Testwerkzeugen oder die Schulung des Testteams umfassen.\n\nDiese Checkliste und die detaillierte Beschreibung der Schritte sollen sicherstellen, dass der Testprozess nicht nur erfolgreich abgeschlossen wird, sondern auch kontinuierlich verbessert wird, um zukünftige Herausforderungen effizienter zu bewältigen.\n\n## 7. Kapitel 7: Checkliste in Tabellenform\n\n| **Schritt** | **Beschreibung** | **Wichtige Punkte** |\n|-------------|------------------|---------------------|\n| **1. Testplanung** | Definition der Teststrategie und -ziele | - Klare Definition der Testziele
- Auswahl geeigneter Testmethoden
- Ressourcen- und Zeitplanung |\n| **2. Testdesign** | Erstellung der Testfälle und -szenarien | - Identifikation der Testanforderungen
- Erstellung detaillierter Testfälle
- Priorisierung der Testfälle |\n| **3. Testumgebung einrichten** | Vorbereitung der Testumgebung | - Sicherstellung der Verfügbarkeit der Testumgebung
- Installation notwendiger Software und Tools
- Validierung der Testumgebung |\n| **4. Testdurchführung** | Ausführung der Testfälle | - Durchführung der Tests gemäß den Testfällen
- Dokumentation der Testergebnisse
- Identifikation und Dokumentation von Abweichungen |\n| **5. Fehlerbehandlung** | Verwaltung und Behebung von Fehlern | - Erfassung und Klassifizierung von Fehlern
- Priorisierung der Fehlerbehebung
- Retest nach Fehlerbehebung |\n| **6. Testabschluss** | Bewertung und Abschluss des Testprozesses | - Zusammenfassung der Testergebnisse
- Bewertung der Testabdeckung
- Erstellung eines Testabschlussberichts |\n| **7. Testreview und -verbesserung** | Analyse und Optimierung des Testprozesses | - Durchführung von Testreviews
- Identifikation von Verbesserungsmöglichkeiten
- Anpassung der Teststrategie für zukünftige Projekte |\n\n### Detaillierte Beschreibung der Schritte\n\n#### Testplanung\nDie Testplanung ist der erste und entscheidende Schritt im Testprozess. Hierbei werden die Ziele des Tests klar definiert, um sicherzustellen, dass alle Beteiligten ein gemeinsames Verständnis der Testziele haben. Die Auswahl geeigneter Testmethoden und die Planung der benötigten Ressourcen und Zeitrahmen sind ebenfalls wesentliche Bestandteile dieses Schritts.\n\n#### Testdesign\nIm Testdesign werden die Testfälle und -szenarien entwickelt. Dieser Schritt erfordert eine gründliche Analyse der Testanforderungen, um sicherzustellen, dass alle relevanten Aspekte abgedeckt sind. Die Priorisierung der Testfälle hilft dabei, sich auf die wichtigsten Tests zu konzentrieren und die Testressourcen effizient zu nutzen.\n\n#### Testumgebung einrichten\nDie Testumgebung muss sorgfältig vorbereitet werden, um genaue und zuverlässige Testergebnisse zu gewährleisten. Dies beinhaltet die Sicherstellung der Verfügbarkeit der notwendigen Hardware und Software sowie die Validierung der Testumgebung, um sicherzustellen, dass sie den Anforderungen entspricht.\n\n#### Testdurchführung\nWährend der Testdurchführung werden die Testfälle gemäß den im Testdesign festgelegten Szenarien ausgeführt. Eine gründliche Dokumentation der Testergebnisse ist entscheidend, um Abweichungen zu identifizieren und zu dokumentieren.\n\n#### Fehlerbehandlung\nDie Fehlerbehandlung umfasst die Erfassung, Klassifizierung und Priorisierung von Fehlern. Eine effektive Fehlerbehandlung ist entscheidend, um sicherzustellen, dass alle identifizierten Probleme behoben werden und der Testprozess reibungslos verläuft.\n\n#### Testabschluss\nDer Testabschluss beinhaltet die Bewertung der Testergebnisse und die Erstellung eines Testabschlussberichts. Dieser Bericht fasst die Ergebnisse zusammen und bewertet die Testabdeckung, um sicherzustellen, dass alle Testziele erreicht wurden.\n\n#### Testreview und -verbesserung\nNach Abschluss des Testprozesses ist es wichtig, den gesamten Prozess zu überprüfen und nach Möglichkeiten zur Verbesserung zu suchen. Dies kann durch Testreviews und die Anpassung der Teststrategie für zukünftige Projekte erreicht werden.\n\n---\n\n**Erstellt durch:** Dokumentation", + "agent_type": "documentation", + "agent_id": "documentation_agent", + "agent_name": "Dokumentation" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n**Zusammenfassung der Agentenergebnisse: Checkliste für Testprozesse**\n\n**Ziel des Dokuments:**\nDas Dokument bietet eine strukturierte Übersicht über die wesentlichen Schritte und Aspekte, die bei der Durchführung von Testprozessen beachtet werden sollten. Es dient als Leitfaden zur Verbesserung der Qualität und Konsistenz von Testprozessen.\n\n**Kapitelübersicht:**\n\n1. **Einführung in den Testprozess:**\n - Bedeutung: Qualitätssicherung ist entscheidend für den Erfolg von Softwareprojekten. Ein strukturierter Testprozess hilft, Fehler frühzeitig zu erkennen und die Kundenzufriedenheit zu erhöhen.\n - Grundlegende Schritte: Anforderungsanalyse, Testplanung, Testdesign, Testumgebung, Testdurchführung, Fehlerberichterstattung, Testabschluss.\n\n2. **Planung und Vorbereitung:**\n - Definition der Testziele und Erfolgskriterien.\n - Analyse der Testanforderungen und Risikobewertung.\n - Auswahl geeigneter Testmethoden und Werkzeuge.\n - Erstellung eines detaillierten Testplans.\n - Vorbereitung der Testumgebung und Testdaten.\n - Kommunikation und Koordination mit Stakeholdern.\n\n3. **Testdurchführung:**\n - Erstellung und Detaillierung von Testfällen.\n - Vorbereitung und Validierung der Testumgebung.\n - Systematische Testausführung und Dokumentation der Ergebnisse.\n - Fehlererfassung und -management.\n - Regelmäßige Berichterstattung an Stakeholder.\n\n4. **Dokumentation und Berichterstattung:**\n - Erstellung eines umfassenden Testplans und detaillierter Testfalldokumentation.\n - Systematische Durchführung und Protokollierung der Testergebnisse.\n - Fehlerprotokollierung und Testbericht-Erstellung.\n - Review und Freigabe der Dokumentation.\n\n5. **Bewertung und Analyse:**\n - Sammlung und Validierung der Testergebnisse.\n - Identifikation und Ursachenanalyse von Abweichungen.\n - Bewertung der Testabdeckung und -effektivität.\n - Dokumentation der Analyseergebnisse und Vorschläge für Verbesserungen.\n - Kommunikation der Ergebnisse an Stakeholder.\n\n6. **Abschluss und Nachbereitung:**\n - Erstellung eines Testabschlussberichts.\n - Fehlerbewertung und Dokumentation.\n - Durchführung einer Lessons Learned Sitzung.\n - Bereinigung der Testumgebung.\n - Archivierung der Testdokumentation.\n - Einholung von Feedback und Ableitung von Maßnahmen zur Prozessoptimierung.\n\n7. **Checkliste in Tabellenform:**\n - Übersicht über die Schritte: Testplanung, Testdesign, Testumgebung einrichten, Testdurchführung, Fehlerbehandlung, Testabschluss, Testreview und -verbesserung.\n\n**Empfehlungen:**\n- Implementierung eines strukturierten Testprozesses zur Verbesserung der Softwarequalität.\n- Nutzung der Checkliste als Leitfaden für systematische und effiziente Testprozesse.\n- Kontinuierliche Verbesserung durch Feedback-Schleifen und Lessons Learned.\n\nDiese strukturierte Herangehensweise stellt sicher, dass der Testprozess effizient durchgeführt wird und die Qualität der Softwareprodukte verbessert wird.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true, + "finished_at": "2025-04-06T12:51:59.913543", + "status": "completed" + }, + { + "id": "msg_113a13ae-c2e7-46b0-b050-75a78e5e1e64", + "workflow_id": "a3b24a29-8543-4340-8f25-f44841836e37", + "parent_message_id": null, + "started_at": "2025-04-06T12:51:59.913543", + "finished_at": null, + "sequence_no": 8, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "kannst du mir den beircht als pdf datei liefern?", + "agent_type": null + }, + { + "id": "msg_ba6bcc1b-c1ac-44b8-b7ac-701148b40095", + "workflow_id": "a3b24a29-8543-4340-8f25-f44841836e37", + "parent_message_id": null, + "started_at": "2025-04-06T12:53:13.742806", + "finished_at": "2025-04-06T12:53:13.765724", + "sequence_no": 9, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "# Berichtserstellung im PDF-Format: Anleitung und Umsetzung\n\n## Zusammenfassung\n\nDer Bericht \"Berichtserstellung im PDF-Format: Anleitung und Umsetzung\" bietet eine umfassende Anleitung zur Erstellung von Berichten im PDF-Format. Er beschreibt den Zweck und die Vorteile der Nutzung von PDF für Berichte, einschließlich der Sicherstellung von Konsistenz und Professionalität. Der Bericht führt durch die wesentlichen Schritte, von der Sammlung und Organisation der Informationen bis zur technischen Umsetzung und Formatierung im PDF-Format. Zudem werden praktische Tipps zur Optimierung der Lesbarkeit und Zugänglichkeit der Berichte gegeben. Ziel ist es, dem Benutzer eine klare und umsetzbare Anleitung zur effizienten Erstellung von PDF-Berichten zu bieten.\n\n## Inhaltsverzeichnis\n\n1. Kapitel 1: Einführung in die PDF-Berichterstellung\n2. Kapitel 2: Sammlung und Organisation der Informationen\n3. Kapitel 3: Strukturierung des Berichts\n4. Kapitel 4: Technische Umsetzung und Formatierung\n5. Kapitel 5: Optimierung der Lesbarkeit und Zugänglichkeit\n6. Kapitel 6: Überprüfung und Qualitätssicherung\n7. Kapitel 7: Abschluss und Veröffentlichung\n\n## 1. Kapitel 1: Einführung in die PDF-Berichterstellung\n\nPDF-Berichterstellung ist ein wesentlicher Bestandteil moderner Dokumentationsprozesse, der sowohl in geschäftlichen als auch in akademischen Kontexten weit verbreitet ist. Die Erstellung von Berichten im PDF-Format bietet zahlreiche Vorteile, die zur Effizienz und Professionalität der Kommunikation beitragen.\n\n**Zweck der PDF-Berichterstellung**\n\nDer Hauptzweck der PDF-Berichterstellung besteht darin, Informationen in einem konsistenten und leicht zugänglichen Format zu präsentieren. PDF, das für \"Portable Document Format\" steht, wurde entwickelt, um Dokumente unabhängig von Software, Hardware oder Betriebssystemen zuverlässig darzustellen. Dies macht es zu einem idealen Format für die Verbreitung von Berichten, die auf verschiedenen Plattformen und Geräten gelesen werden sollen.\n\n**Vorteile der PDF-Berichterstellung**\n\n1. **Konsistenz und Formatierung**\n - **Einheitliches Erscheinungsbild**: PDFs bewahren das Layout, die Schriftarten und die Formatierung eines Dokuments, unabhängig davon, wo es geöffnet wird. Dies stellt sicher, dass der Bericht genau so aussieht, wie vom Ersteller beabsichtigt.\n - **Plattformunabhängigkeit**: Da PDFs auf nahezu jedem Gerät gleich aussehen, wird die Konsistenz der Darstellung gewährleistet, was besonders wichtig ist, wenn Berichte an ein breites Publikum verteilt werden.\n\n2. **Professionalität**\n - **Hochwertige Präsentation**: PDFs ermöglichen die Einbindung von Grafiken, Diagrammen und Bildern in hoher Qualität, was zur professionellen Präsentation von Informationen beiträgt.\n - **Sicherheit und Integrität**: PDFs können mit Passwörtern geschützt und digital signiert werden, um die Integrität der Informationen zu gewährleisten und unbefugten Zugriff zu verhindern.\n\n3. **Zugänglichkeit und Verbreitung**\n - **Einfache Verteilung**: PDFs können leicht per E-Mail versendet oder auf Websites hochgeladen werden, was die Verbreitung von Berichten vereinfacht.\n - **Suchbarkeit und Interaktivität**: Moderne PDFs unterstützen die Textsuche und können interaktive Elemente wie Hyperlinks und Formulare enthalten, die die Benutzererfahrung verbessern.\n\n4. **Langfristige Archivierung**\n - **Langlebigkeit**: PDFs sind ein bewährtes Format für die langfristige Archivierung von Dokumenten, da sie auch in Zukunft lesbar bleiben, unabhängig von technologischen Veränderungen.\n\n**Vergleich von PDF mit anderen Formaten**\n\n| Merkmal | PDF | Word-Dokumente | HTML-Seiten |\n|------------------|----------------------------|----------------------------|----------------------------|\n| Konsistenz | Hoch | Variabel | Variabel |\n| Plattformunabhängig | Ja | Nein | Ja |\n| Sicherheit | Hoch (Passwortschutz) | Mittel (eingeschränkter Schutz) | Niedrig (offen zugänglich) |\n| Interaktivität | Mittel (Formulare, Links) | Hoch (Bearbeitbar) | Hoch (Hyperlinks, Multimedia) |\n| Archivierung | Sehr gut | Gut | Schlecht |\n\n**Fazit**\n\nDie Erstellung von Berichten im PDF-Format bietet zahlreiche Vorteile, die von der Konsistenz und Professionalität bis hin zur einfachen Verteilung und langfristigen Archivierung reichen. Diese Eigenschaften machen PDFs zu einem unverzichtbaren Werkzeug für die effektive Kommunikation und Dokumentation in einer Vielzahl von Anwendungsbereichen. Durch die Nutzung der Vorteile von PDFs können Organisationen und Einzelpersonen sicherstellen, dass ihre Berichte nicht nur ansprechend und professionell aussehen, sondern auch sicher und zugänglich sind.\n\n## 2. Kapitel 2: Sammlung und Organisation der Informationen\n\nUm einen Bericht im PDF-Format erfolgreich zu erstellen, ist die Sammlung und Organisation der benötigten Informationen ein entscheidender Schritt. Eine systematische Herangehensweise stellt sicher, dass alle relevanten Daten berücksichtigt werden und der Bericht klar und präzise ist. Im Folgenden werden die wesentlichen Schritte zur effektiven Sammlung und Organisation der Informationen beschrieben:\n\n### 1. Definition des Berichtsumfangs\n\nBevor mit der Sammlung von Informationen begonnen wird, ist es wichtig, den Umfang des Berichts klar zu definieren. Dies umfasst:\n\n- **Zielsetzung des Berichts**: Was soll der Bericht erreichen? Welche Fragen soll er beantworten?\n- **Zielgruppe**: Wer wird den Bericht lesen? Welche Informationen sind für diese Leser relevant?\n- **Umfang und Grenzen**: Welche Themen werden abgedeckt und welche nicht?\n\n### 2. Identifikation der Informationsquellen\n\nSobald der Umfang festgelegt ist, müssen die relevanten Informationsquellen identifiziert werden. Diese können umfassen:\n\n- **Primärquellen**: Direkte Datenquellen wie Interviews, Umfragen oder Experimente.\n- **Sekundärquellen**: Bereits vorhandene Informationen wie Bücher, Artikel, Berichte oder Online-Ressourcen.\n- **Interne Quellen**: Unternehmensdaten, interne Berichte oder Mitarbeiterwissen.\n- **Externe Quellen**: Veröffentlichungen von Branchenexperten, wissenschaftliche Studien oder Marktanalysen.\n\n### 3. Sammlung der Informationen\n\nDie Sammlung der Informationen sollte strukturiert und methodisch erfolgen:\n\n- **Erstellung eines Sammelplans**: Legen Sie fest, welche Informationen benötigt werden und wie diese gesammelt werden sollen.\n- **Verwendung von Tools**: Nutzen Sie digitale Tools wie Datenbanken, Online-Recherche-Tools oder Software für Umfragen, um die Effizienz zu steigern.\n- **Dokumentation der Quellen**: Halten Sie alle Quellen sorgfältig fest, um die Nachvollziehbarkeit und Glaubwürdigkeit der Informationen zu gewährleisten.\n\n### 4. Bewertung und Auswahl der Informationen\n\nNicht alle gesammelten Informationen werden für den Bericht relevant sein. Daher ist eine kritische Bewertung notwendig:\n\n- **Relevanzprüfung**: Überprüfen Sie, ob die Informationen direkt zur Zielsetzung des Berichts beitragen.\n- **Zuverlässigkeit und Genauigkeit**: Stellen Sie sicher, dass die Informationen aus vertrauenswürdigen Quellen stammen und korrekt sind.\n- **Aktualität**: Achten Sie darauf, dass die Informationen aktuell und nicht veraltet sind.\n\n### 5. Organisation der Informationen\n\nDie gesammelten und ausgewählten Informationen müssen nun organisiert werden, um eine logische und kohärente Struktur des Berichts zu gewährleisten:\n\n- **Erstellung einer Gliederung**: Entwickeln Sie eine detaillierte Gliederung, die den Fluss des Berichts vorgibt.\n- **Kategorisierung der Informationen**: Ordnen Sie die Informationen nach Themen, Wichtigkeit oder chronologischer Reihenfolge.\n- **Verwendung von Tabellen und Diagrammen**: Nutzen Sie visuelle Hilfsmittel, um komplexe Daten verständlich darzustellen.\n\n### 6. Überprüfung und Anpassung\n\nBevor der Bericht finalisiert wird, sollten die gesammelten und organisierten Informationen überprüft werden:\n\n- **Konsistenzprüfung**: Stellen Sie sicher, dass alle Informationen konsistent und widerspruchsfrei sind.\n- **Feedback einholen**: Lassen Sie den Entwurf von Kollegen oder Experten überprüfen, um wertvolle Rückmeldungen zu erhalten.\n- **Anpassungen vornehmen**: Basierend auf dem Feedback sollten notwendige Anpassungen vorgenommen werden, um die Qualität des Berichts zu optimieren.\n\nDurch die sorgfältige Sammlung und Organisation der Informationen wird die Grundlage für einen klaren, präzisen und informativen Bericht gelegt. Diese Schritte helfen, die Effizienz des Berichterstellungsprozesses zu steigern und die Qualität des Endprodukts zu sichern.\n\n## 3. Kapitel 3: Strukturierung des Berichts\n\nDie Strukturierung eines Berichts ist entscheidend für die Klarheit und Verständlichkeit der präsentierten Informationen. Ein gut strukturierter Bericht ermöglicht es dem Leser, die Inhalte effizient zu erfassen und die wesentlichen Punkte schnell zu identifizieren. In diesem Kapitel werden die wesentlichen Elemente der Berichtsstruktur detailliert beschrieben, um eine kohärente und gut organisierte Präsentation zu gewährleisten.\n\n**1. Titel**\n\nDer Titel ist das erste Element des Berichts und sollte prägnant und aussagekräftig sein. Er gibt dem Leser einen klaren Hinweis auf das Thema und den Inhalt des Berichts. Ein effektiver Titel ist:\n\n- **Klar und präzise**: Vermeiden Sie vage oder zu allgemeine Formulierungen.\n- **Informativ**: Der Titel sollte den Hauptfokus des Berichts widerspiegeln.\n- **Ansprechend**: Er sollte das Interesse des Lesers wecken.\n\n**2. Inhaltsverzeichnis**\n\nDas Inhaltsverzeichnis bietet einen Überblick über die Struktur des Berichts und ermöglicht es dem Leser, schnell zu den gewünschten Abschnitten zu navigieren. Es sollte:\n\n- **Alle Haupt- und Unterkapitel** des Berichts auflisten.\n- **Seitenzahlen** angeben, um die Navigation zu erleichtern.\n- **Automatisch generiert** werden, wenn möglich, um Aktualisierungen bei Änderungen im Dokument zu erleichtern.\n\n**3. Einleitung**\n\nDie Einleitung ist entscheidend, um den Leser in das Thema des Berichts einzuführen. Sie sollte:\n\n- **Den Kontext** des Berichts erläutern und die Relevanz des Themas hervorheben.\n- **Die Zielsetzung** des Berichts klar definieren.\n- **Einen Überblick** über die Struktur des Berichts geben, um dem Leser eine Orientierung zu bieten.\n\n**4. Hauptteil**\n\nDer Hauptteil ist das Herzstück des Berichts und sollte logisch und kohärent gegliedert sein. Er umfasst:\n\n- **Kapitel und Unterkapitel**: Diese sollten thematisch geordnet sein und einen roten Faden durch den Bericht ziehen.\n- **Detaillierte Informationen**: Jedes Kapitel sollte umfassend recherchierte und relevante Informationen enthalten.\n- **Visuelle Hilfsmittel**: Tabellen, Grafiken und Diagramme können verwendet werden, um komplexe Informationen anschaulich darzustellen.\n\n**Beispiel für eine tabellarische Darstellung:**\n\n| Kapitel | Inhalt | Seitenzahl |\n|---------|---------------------------------|------------|\n| 1 | Einführung in das Thema | 1-3 |\n| 2 | Methodik und Vorgehensweise | 4-7 |\n| 3 | Ergebnisse und Diskussion | 8-15 |\n| 4 | Schlussfolgerungen und Ausblick | 16-18 |\n\n**5. Schlussfolgerung**\n\nDie Schlussfolgerung fasst die wichtigsten Erkenntnisse des Berichts zusammen und bietet einen Ausblick auf mögliche zukünftige Entwicklungen oder Untersuchungen. Sie sollte:\n\n- **Die Hauptpunkte** des Berichts zusammenfassen, ohne neue Informationen einzuführen.\n- **Empfehlungen** aussprechen, die sich aus den Ergebnissen ableiten lassen.\n- **Den Leser zum Nachdenken** anregen und mögliche nächste Schritte aufzeigen.\n\n**Zusammenfassung**\n\nEine klare und gut durchdachte Berichtsstruktur ist entscheidend für die Effektivität eines Berichts. Durch die sorgfältige Planung und Organisation der einzelnen Elemente – vom Titel bis zur Schlussfolgerung – wird sichergestellt, dass der Bericht nicht nur informativ, sondern auch ansprechend und leicht verständlich ist.\n\n## 4. Kapitel 4: Technische Umsetzung und Formatierung\n\n### Auswahl der geeigneten Software\n\nUm einen Bericht im PDF-Format zu erstellen, ist die Wahl der richtigen Software entscheidend. Es gibt verschiedene Programme, die für diesen Zweck geeignet sind, darunter:\n\n- **Microsoft Word**: Häufig verwendet für die Erstellung von Textdokumenten, bietet es eine einfache Möglichkeit, Dokumente als PDF zu speichern.\n- **Adobe Acrobat**: Ein umfassendes Tool zur Erstellung, Bearbeitung und Konvertierung von PDF-Dokumenten.\n- **LibreOffice Writer**: Eine kostenlose Alternative zu Microsoft Word, die ebenfalls PDF-Exportfunktionen bietet.\n- **LaTeX**: Besonders geeignet für wissenschaftliche Dokumente, da es präzise Formatierungsoptionen bietet.\n\n### Erstellung des Berichts\n\n#### 1. Dokumentvorbereitung\n\nBevor mit der eigentlichen Erstellung des Berichts begonnen wird, sollten alle notwendigen Informationen und Materialien gesammelt und strukturiert werden. Dies umfasst:\n\n- **Gliederung des Berichts**: Erstellen Sie eine detaillierte Gliederung, die alle Kapitel und Unterkapitel umfasst.\n- **Inhaltssammlung**: Sammeln Sie alle relevanten Daten, Grafiken und Tabellen, die im Bericht enthalten sein sollen.\n- **Vorlagen**: Nutzen Sie vorhandene Vorlagen, um ein konsistentes Layout zu gewährleisten.\n\n#### 2. Dokumenterstellung\n\n- **Textverarbeitung**: Verwenden Sie eine Textverarbeitungssoftware wie Microsoft Word oder LibreOffice Writer, um den Text des Berichts zu verfassen. Achten Sie auf eine klare Strukturierung mit Überschriften, Absätzen und Listen.\n- **Einfügen von Grafiken und Tabellen**: Fügen Sie relevante Grafiken und Tabellen ein, um den Text zu unterstützen. Achten Sie darauf, dass alle visuellen Elemente klar beschriftet sind.\n- **Verweise und Zitationen**: Nutzen Sie einheitliche Zitationsstile und fügen Sie alle notwendigen Verweise hinzu.\n\n### Formatierung des Berichts\n\n#### 1. Layout und Design\n\n- **Seitenränder und Abstände**: Stellen Sie sicher, dass die Seitenränder und Abstände einheitlich sind, um ein professionelles Erscheinungsbild zu gewährleisten.\n- **Schriftarten und -größen**: Verwenden Sie gut lesbare Schriftarten und halten Sie sich an eine konsistente Schriftgröße für den Haupttext und die Überschriften.\n- **Kopf- und Fußzeilen**: Fügen Sie Kopf- und Fußzeilen hinzu, die den Titel des Berichts, das Kapitel oder die Seitenzahlen enthalten.\n\n#### 2. Inhaltsverzeichnis\n\n- **Automatisches Inhaltsverzeichnis**: Nutzen Sie die Funktionen Ihrer Textverarbeitungssoftware, um ein automatisches Inhaltsverzeichnis zu erstellen, das sich bei Änderungen im Dokument automatisch aktualisiert.\n\n### Konvertierung in das PDF-Format\n\n#### 1. Exportieren als PDF\n\n- **Direkte Exportfunktion**: Die meisten Textverarbeitungsprogramme bieten eine direkte Exportfunktion in das PDF-Format. Wählen Sie „Speichern unter“ oder „Exportieren“ und wählen Sie PDF als Dateiformat.\n- **Einstellungen anpassen**: Überprüfen Sie die PDF-Einstellungen, um sicherzustellen, dass alle Elemente korrekt dargestellt werden. Achten Sie auf die Einbettung von Schriftarten und die Qualität von Bildern.\n\n#### 2. Überprüfung des PDF-Dokuments\n\n- **Vollständigkeitsprüfung**: Öffnen Sie das erstellte PDF-Dokument und überprüfen Sie, ob alle Inhalte korrekt dargestellt werden.\n- **Interaktive Elemente**: Falls der Bericht interaktive Elemente wie Links oder Lesezeichen enthält, testen Sie deren Funktionalität.\n\n### Zusammenfassung\n\nDie Erstellung eines Berichts im PDF-Format erfordert eine sorgfältige Planung und Ausführung. Durch die Wahl der richtigen Software und die Beachtung der beschriebenen Schritte zur Dokumenterstellung und -formatierung kann ein professionelles und gut strukturiertes PDF-Dokument erstellt werden. Achten Sie darauf, das Dokument vor der endgültigen Verteilung gründlich zu überprüfen, um sicherzustellen, dass es alle Anforderungen erfüllt.\n\n## 5. Kapitel 5: Optimierung der Lesbarkeit und Zugänglichkeit\n\nUm die Lesbarkeit und Zugänglichkeit eines Berichts im PDF-Format zu optimieren, ist es entscheidend, sowohl gestalterische als auch technische Aspekte zu berücksichtigen. Die folgenden Tipps bieten eine umfassende Anleitung zur Verbesserung dieser beiden Bereiche:\n\n### Schriftartwahl\n\n1. **Serifen vs. serifenlose Schriften**:\n - **Serifen-Schriften** (z.B. Times New Roman, Georgia) sind traditionell für gedruckte Texte geeignet, da sie die Lesbarkeit auf Papier verbessern.\n - **Serifenlose Schriften** (z.B. Arial, Helvetica) sind für digitale Dokumente oft besser geeignet, da sie auf Bildschirmen klarer wirken.\n\n2. **Schriftgröße**:\n - Eine Mindestschriftgröße von 11 oder 12 Punkten wird empfohlen, um die Lesbarkeit zu gewährleisten.\n - Für Überschriften können größere Schriftgrößen verwendet werden, um die Hierarchie der Informationen klar zu definieren.\n\n3. **Schriftstil**:\n - Vermeiden Sie übermäßige Verwendung von Kursiv- oder Fettschrift, da dies die Lesbarkeit beeinträchtigen kann.\n - Verwenden Sie Hervorhebungen sparsam und nur, um wichtige Informationen zu betonen.\n\n### Layoutgestaltung\n\n1. **Absatz- und Zeilenabstand**:\n - Ein ausreichender Zeilenabstand (1,15 bis 1,5-fach) verbessert die Lesbarkeit, indem er den Text weniger gedrängt erscheinen lässt.\n - Zwischen Absätzen sollte ein zusätzlicher Abstand eingefügt werden, um den Textfluss zu erleichtern.\n\n2. **Seitenränder**:\n - Breite Seitenränder (mindestens 2,5 cm) sorgen für ein ausgewogenes Layout und bieten Platz für Anmerkungen.\n\n3. **Textausrichtung**:\n - Linksbündiger Text ist in der Regel leichter zu lesen als Blocksatz, da er gleichmäßige Wortabstände beibehält.\n\n### Farbgestaltung\n\n1. **Kontrast**:\n - Ein hoher Kontrast zwischen Text und Hintergrund (z.B. schwarzer Text auf weißem Hintergrund) verbessert die Lesbarkeit erheblich.\n - Vermeiden Sie farbige Hintergründe, die den Text schwer lesbar machen könnten.\n\n2. **Farbverwendung**:\n - Verwenden Sie Farben sparsam und konsistent, um wichtige Informationen hervorzuheben, ohne den Leser zu überfordern.\n\n### Zugänglichkeit\n\n1. **Alternative Texte für Bilder**:\n - Fügen Sie alternative Texte für alle Bilder und Grafiken hinzu, um sicherzustellen, dass Benutzer von Bildschirmlesegeräten die Informationen verstehen können.\n\n2. **Verwendung von Überschriften**:\n - Strukturieren Sie den Bericht mit klaren Überschriften und Unterüberschriften, die mit den entsprechenden HTML-Tags (H1, H2, H3) versehen sind, um die Navigation zu erleichtern.\n\n3. **Hyperlinks**:\n - Stellen Sie sicher, dass alle Hyperlinks beschreibend sind und den Benutzer klar über das Ziel des Links informieren.\n\n### Tabellen und Grafiken\n\n1. **Tabellenstruktur**:\n - Verwenden Sie einfache Tabellenstrukturen mit klaren Kopfzeilen, um die Informationen leicht verständlich zu machen.\n - Vermeiden Sie verschachtelte Tabellen, die die Lesbarkeit beeinträchtigen können.\n\n2. **Beschriftungen**:\n - Alle Grafiken und Tabellen sollten mit klaren, beschreibenden Titeln und Beschriftungen versehen sein, um den Kontext zu vermitteln.\n\n### Testen der Lesbarkeit und Zugänglichkeit\n\n1. **Lesbarkeitsprüfung**:\n - Verwenden Sie Tools zur Lesbarkeitsprüfung, um sicherzustellen, dass der Text für die Zielgruppe geeignet ist.\n\n2. **Zugänglichkeitstests**:\n - Führen Sie Zugänglichkeitstests mit verschiedenen Geräten und Bildschirmlesegeräten durch, um sicherzustellen, dass der Bericht für alle Benutzer zugänglich ist.\n\nDurch die Umsetzung dieser Tipps können Sie sicherstellen, dass Ihr Bericht im PDF-Format sowohl lesbar als auch zugänglich ist, was zu einer besseren Benutzererfahrung und einer effektiveren Kommunikation der Inhalte führt.\n\n## 6. Kapitel 6: Überprüfung und Qualitätssicherung\n\nÜberprüfung und Qualitätssicherung sind entscheidende Schritte im Prozess der Berichtserstellung im PDF-Format. Diese Phase stellt sicher, dass der Bericht fehlerfrei, konsistent und von hoher Qualität ist, bevor er veröffentlicht wird. Im Folgenden wird der Prozess der Überprüfung und Qualitätssicherung detailliert beschrieben.\n\n**1. Inhaltliche Überprüfung**\n\n- **Vollständigkeit:** Stellen Sie sicher, dass alle erforderlichen Informationen und Abschnitte im Bericht enthalten sind. Überprüfen Sie, ob alle Kapitel, Unterkapitel und Anhänge vorhanden sind.\n- **Richtigkeit:** Verifizieren Sie die Fakten, Daten und Zahlen im Bericht. Stellen Sie sicher, dass alle Informationen korrekt und aktuell sind.\n- **Konsistenz:** Achten Sie darauf, dass die Terminologie und der Schreibstil im gesamten Dokument einheitlich sind. Überprüfen Sie die Konsistenz von Formatierungen, wie Schriftarten, Schriftgrößen und Abständen.\n\n**2. Sprachliche Überprüfung**\n\n- **Grammatik und Rechtschreibung:** Nutzen Sie Rechtschreib- und Grammatikprüfungswerkzeuge, um Fehler zu identifizieren und zu korrigieren. Eine manuelle Überprüfung durch einen Lektor kann zusätzliche Sicherheit bieten.\n- **Stil und Lesbarkeit:** Achten Sie darauf, dass der Text klar und prägnant ist. Vermeiden Sie Fachjargon, wenn er nicht notwendig ist, und stellen Sie sicher, dass der Bericht für die Zielgruppe verständlich ist.\n\n**3. Technische Überprüfung**\n\n- **Formatierung:** Überprüfen Sie die Formatierung des Berichts, um sicherzustellen, dass er professionell aussieht. Dazu gehören Seitenränder, Zeilenabstände, Kopf- und Fußzeilen sowie die korrekte Nummerierung von Seiten und Kapiteln.\n- **Verlinkungen und Verweise:** Testen Sie alle internen und externen Links im PDF, um sicherzustellen, dass sie korrekt funktionieren. Überprüfen Sie, ob alle Verweise auf Tabellen, Abbildungen und Anhänge korrekt sind.\n\n**4. Visuelle Überprüfung**\n\n- **Grafiken und Diagramme:** Stellen Sie sicher, dass alle visuellen Elemente klar und gut lesbar sind. Überprüfen Sie die Bildqualität und die korrekte Beschriftung von Diagrammen und Abbildungen.\n- **Layout:** Achten Sie darauf, dass das Layout des Berichts ansprechend und übersichtlich ist. Vermeiden Sie überladene Seiten und sorgen Sie für eine logische Anordnung der Inhalte.\n\n**5. Feedback und Revision**\n\n- **Peer-Review:** Lassen Sie den Bericht von Kollegen oder Experten überprüfen, um zusätzliches Feedback zu erhalten. Eine externe Perspektive kann helfen, blinde Flecken zu identifizieren.\n- **Revision:** Basierend auf dem erhaltenen Feedback sollten notwendige Änderungen und Korrekturen vorgenommen werden. Dieser Schritt kann mehrmals wiederholt werden, bis der Bericht den Qualitätsstandards entspricht.\n\n**6. Endgültige Freigabe**\n\n- **Freigabeprozess:** Implementieren Sie einen formellen Freigabeprozess, bei dem der Bericht von den relevanten Stakeholdern genehmigt wird. Dies stellt sicher, dass alle Beteiligten mit dem Endprodukt zufrieden sind.\n- **Dokumentation:** Halten Sie alle Überprüfungs- und Freigabeschritte schriftlich fest, um den Prozess nachvollziehbar zu machen und bei Bedarf auf frühere Versionen zurückgreifen zu können.\n\n**Tabelle: Checkliste für die Qualitätssicherung**\n\n| Überprüfungsbereich | Aufgaben | Status |\n|--------------------------|-------------------------------------------|---------|\n| Inhaltliche Überprüfung | Vollständigkeit, Richtigkeit, Konsistenz | |\n| Sprachliche Überprüfung | Grammatik, Rechtschreibung, Stil | |\n| Technische Überprüfung | Formatierung, Verlinkungen | |\n| Visuelle Überprüfung | Grafiken, Layout | |\n| Feedback und Revision | Peer-Review, Revision | |\n| Endgültige Freigabe | Freigabeprozess, Dokumentation | |\n\nDurch die sorgfältige Durchführung dieser Schritte wird sichergestellt, dass der Bericht im PDF-Format von höchster Qualität ist und den Anforderungen der Zielgruppe entspricht.\n\n## 7. Kapitel 7: Abschluss und Veröffentlichung\n\n### Zusammenfassung und Überprüfung\n\nBevor der Bericht veröffentlicht wird, ist es entscheidend, eine gründliche Überprüfung und Zusammenfassung der Inhalte durchzuführen. Dies stellt sicher, dass alle Informationen korrekt und vollständig sind und der Bericht den Anforderungen und Erwartungen der Zielgruppe entspricht.\n\n1. **Inhaltliche Überprüfung:**\n - **Korrekturlesen:** Überprüfen Sie den Bericht auf Rechtschreib- und Grammatikfehler. Dies kann durch manuelles Lesen oder den Einsatz von Software-Tools erfolgen.\n - **Faktencheck:** Stellen Sie sicher, dass alle Daten und Fakten korrekt und aktuell sind. Überprüfen Sie die Quellenangaben und Zitate.\n - **Kohärenz und Konsistenz:** Achten Sie darauf, dass der Bericht logisch aufgebaut ist und die Informationen konsistent präsentiert werden.\n\n2. **Formatierung und Design:**\n - **Layout-Überprüfung:** Stellen Sie sicher, dass das Layout des Berichts ansprechend und professionell ist. Überprüfen Sie die Verwendung von Schriftarten, Farben und Abständen.\n - **Tabellen und Grafiken:** Vergewissern Sie sich, dass alle visuellen Elemente korrekt beschriftet und leicht verständlich sind.\n\n### Technische Fertigstellung\n\nNach der inhaltlichen und gestalterischen Überprüfung sind einige technische Schritte erforderlich, um den Bericht für die Veröffentlichung vorzubereiten.\n\n1. **PDF-Erstellung:**\n - **Exportieren des Dokuments:** Nutzen Sie ein Textverarbeitungsprogramm oder eine spezialisierte Software, um den Bericht in das PDF-Format zu exportieren. Achten Sie darauf, dass alle Formatierungen korrekt übernommen werden.\n - **Dateigröße optimieren:** Reduzieren Sie die Dateigröße, ohne die Qualität zu beeinträchtigen, um den Bericht leichter versendbar zu machen.\n\n2. **Sicherheitseinstellungen:**\n - **Passwortschutz:** Falls erforderlich, schützen Sie den Bericht mit einem Passwort, um unbefugten Zugriff zu verhindern.\n - **Einschränkungen:** Legen Sie fest, ob der Bericht gedruckt oder bearbeitet werden darf.\n\n### Veröffentlichung und Verteilung\n\nDie Veröffentlichung des Berichts ist der letzte Schritt im Prozess. Hierbei geht es darum, den Bericht der Zielgruppe zugänglich zu machen.\n\n1. **Zielgruppenanalyse:**\n - **Identifikation der Empfänger:** Bestimmen Sie, wer den Bericht erhalten soll. Dies kann eine interne Gruppe innerhalb eines Unternehmens oder eine breitere Öffentlichkeit sein.\n - **Anpassung der Botschaft:** Passen Sie die Kommunikation an die Bedürfnisse und Erwartungen der Zielgruppe an.\n\n2. **Verteilungskanäle:**\n - **E-Mail-Versand:** Versenden Sie den Bericht per E-Mail an die relevanten Empfänger. Nutzen Sie dabei eine professionelle und klare Betreffzeile.\n - **Online-Plattformen:** Laden Sie den Bericht auf relevante Online-Plattformen hoch, wie z.B. die Unternehmenswebsite oder ein Dokumentenmanagementsystem.\n - **Druckversionen:** Falls erforderlich, erstellen Sie gedruckte Kopien des Berichts für physische Verteilungen.\n\n3. **Feedback und Nachverfolgung:**\n - **Feedback einholen:** Bitten Sie die Empfänger um Rückmeldungen, um zukünftige Berichte zu verbessern.\n - **Erfolgsmessung:** Analysieren Sie die Reichweite und den Einfluss des Berichts, um den Erfolg der Veröffentlichung zu bewerten.\n\nDurch die sorgfältige Durchführung dieser Schritte wird sichergestellt, dass der Bericht nicht nur inhaltlich und technisch einwandfrei ist, sondern auch effektiv an die Zielgruppe verteilt wird.\n\n---\n\n**Erstellt durch:** Dokumentation", + "agent_type": "documentation", + "agent_id": "documentation_agent", + "agent_name": "Dokumentation" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n**Zusammenfassung der Agentenergebnisse: Berichtserstellung im PDF-Format**\n\nDer Bericht \"Berichtserstellung im PDF-Format: Anleitung und Umsetzung\" bietet eine umfassende Anleitung zur Erstellung von Berichten im PDF-Format, die sowohl in geschäftlichen als auch in akademischen Kontexten weit verbreitet sind. Der Bericht beschreibt die Vorteile der PDF-Nutzung, einschließlich Konsistenz, Professionalität, Zugänglichkeit und langfristiger Archivierung. Er führt durch die wesentlichen Schritte von der Informationssammlung bis zur technischen Umsetzung und Formatierung.\n\n**Wichtige Erkenntnisse:**\n\n1. **Vorteile der PDF-Berichterstellung:**\n - **Konsistenz und Formatierung:** Einheitliches Erscheinungsbild und Plattformunabhängigkeit.\n - **Professionalität:** Hochwertige Präsentation und Sicherheit durch Passwortschutz.\n - **Zugänglichkeit:** Einfache Verteilung und Interaktivität.\n - **Langfristige Archivierung:** Langlebigkeit und Unabhängigkeit von technologischen Veränderungen.\n\n2. **Sammlung und Organisation der Informationen:**\n - Definition des Berichtsumfangs, Identifikation der Informationsquellen, strukturierte Sammlung und Bewertung der Informationen.\n - Organisation der Informationen durch Gliederung und visuelle Hilfsmittel.\n\n3. **Strukturierung des Berichts:**\n - Wichtige Elemente: Titel, Inhaltsverzeichnis, Einleitung, Hauptteil, Schlussfolgerung.\n - Klarheit und Verständlichkeit durch logische Gliederung und visuelle Hilfsmittel.\n\n4. **Technische Umsetzung und Formatierung:**\n - Auswahl geeigneter Software (z.B. Microsoft Word, Adobe Acrobat).\n - Dokumentvorbereitung, Erstellung und Formatierung.\n - Konvertierung in das PDF-Format und Überprüfung der Vollständigkeit und Interaktivität.\n\n5. **Optimierung der Lesbarkeit und Zugänglichkeit:**\n - Schriftartwahl, Layoutgestaltung, Farbgestaltung.\n - Zugänglichkeit durch alternative Texte, klare Überschriften und beschreibende Hyperlinks.\n - Testen der Lesbarkeit und Zugänglichkeit.\n\n6. **Überprüfung und Qualitätssicherung:**\n - Inhaltliche, sprachliche, technische und visuelle Überprüfung.\n - Feedback und Revision durch Peer-Review.\n - Endgültige Freigabe und Dokumentation des Prozesses.\n\n7. **Abschluss und Veröffentlichung:**\n - Zusammenfassung und Überprüfung der Inhalte.\n - Technische Fertigstellung durch PDF-Erstellung und Sicherheitseinstellungen.\n - Veröffentlichung und Verteilung an die Zielgruppe über verschiedene Kanäle.\n - Feedback und Erfolgsmessung zur kontinuierlichen Verbesserung.\n\n**Empfehlungen:**\n- Nutzen Sie die Vorteile des PDF-Formats für konsistente und professionelle Berichte.\n- Folgen Sie den beschriebenen Schritten zur Sammlung, Organisation und Strukturierung der Informationen.\n- Achten Sie auf die technische Umsetzung und Formatierung, um ein qualitativ hochwertiges Endprodukt zu gewährleisten.\n- Optimieren Sie die Lesbarkeit und Zugänglichkeit, um eine breite Zielgruppe zu erreichen.\n- Implementieren Sie einen gründlichen Überprüfungs- und Qualitätssicherungsprozess, bevor der Bericht veröffentlicht wird.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_83444b18-778e-4a4b-9bf8-48d54c5e85bd", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 98, 0 Dateien", + "type": "info", + "timestamp": "2025-04-06T12:48:07.635026", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_4e42ceea-34d2-4db4-b906-656063b5e365", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-06T12:48:07.643023", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_95a0c69c-dfaa-4d9f-9bb4-7bc7d0711592", + "message": "Agenten-Entscheidung abgeschlossen: 2 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-06T12:48:10.613801", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_5199c35f-6093-43b7-9ffe-2f2b0303eafa", + "message": "Agent coder_agent wurde ausgewählt mit Aufgabe: Erstelle eine detaillierte Anleitung zur Integrati...", + "type": "info", + "timestamp": "2025-04-06T12:48:10.628153", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_d6f66b2c-3bc7-46a3-a8a2-474d3bfd31b8", + "message": "Agent documentation_agent wurde ausgewählt mit Aufgabe: Erstelle einen strukturierten Bericht basierend au...", + "type": "info", + "timestamp": "2025-04-06T12:48:10.634480", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_90d7ab1a-f60a-4f36-a511-9a63bd2686cb", + "message": "2 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:48:10.642630", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_bc88aded-897d-4c06-a7de-22bc8aef790e", + "message": "Agent coder_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:48:10.651159", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_31626c5b-f6f4-46b6-9431-31cc90894ec0", + "message": "Agent 'coder_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:48:10.659678", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b1355ca5-7b9c-46fb-a73d-23f42d009c11", + "message": "Agent 'coder_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-06T12:48:10.750779", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_0064fca2-ef3a-4f56-9ef2-5b1d4770c984", + "message": "Agent documentation_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:48:10.758900", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ba593286-ed04-49c6-9b6b-814003dfb011", + "message": "Agent 'documentation_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:48:10.766906", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_3e50242f-76cc-463c-b891-5bd921c3e509", + "message": "Agent 'documentation_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-06T12:49:22.602120", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_249e7398-4275-4f8e-bf87-0d67149bab7b", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-06T12:49:29.545060", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_2fd292b1-0256-4e15-98a8-3bc400c8a8a9", + "message": "Benutzereingabe empfangen: 67 Zeichen, 0 Dateien", + "type": "info", + "timestamp": "2025-04-06T12:50:05.426636", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b64fc21d-4d6b-4d27-8d06-c22f48f9d583", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-06T12:50:05.444631", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_6427a1ab-e6fd-4c1a-a68f-5af7e28e6453", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-06T12:50:06.902381", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_2aeebf13-ac5c-4e4a-ad9c-ea420c1fc6f8", + "message": "Agent documentation_agent wurde ausgewählt mit Aufgabe: Erstelle eine kurze Checkliste für das Testen in T...", + "type": "info", + "timestamp": "2025-04-06T12:50:06.910793", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_acdfc0d8-a825-4862-ac9b-19132bb6de0d", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:50:06.919956", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ce0c73ee-c086-4318-8d96-c46998681865", + "message": "Agent documentation_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:50:06.923996", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_a0afff7c-fe45-48bc-bd5c-6c327591dd0d", + "message": "Agent 'documentation_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:50:06.935309", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_efb3c6e4-34e0-41a6-9741-615a47f93a43", + "message": "Agent 'documentation_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-06T12:51:22.377061", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_add08e19-cd91-40f9-8a98-840e5cac5441", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-06T12:51:28.036295", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_72745514-a938-4ffb-9e15-ee5fa9a51602", + "message": "Benutzereingabe empfangen: 48 Zeichen, 0 Dateien", + "type": "info", + "timestamp": "2025-04-06T12:51:59.895545", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_d0473e67-5cec-4a05-b677-8ee4e2b558c4", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-06T12:51:59.903585", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_981fdfe2-14a7-47b1-879a-cb57a41fd36e", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-06T12:52:01.436194", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ae5f72d5-99a4-4c97-9510-66152a29bd07", + "message": "Agent documentation_agent wurde ausgewählt mit Aufgabe: Erstelle einen Bericht im PDF-Format basierend auf...", + "type": "info", + "timestamp": "2025-04-06T12:52:01.436194", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_9e2655c3-726e-42f3-9b8d-362cf23c0428", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:52:01.456265", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_6d4e7160-5077-4dbf-b51f-7334df644c24", + "message": "Agent documentation_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:52:01.465176", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_5081d9e8-c0b7-4f81-a618-8937385991fd", + "message": "Agent 'documentation_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:52:01.473153", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_01d8c5e5-f9c2-4a42-825a-c136c6e708b3", + "message": "Agent 'documentation_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-06T12:53:14.046715", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_5553f300-6c3b-4cc2-8172-bc304ee26475", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-06T12:53:23.991657", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_a3b515e1-5c4f-4f37-89bc-2c50c82ab781.json b/gwserver/_results/workflow_a3b515e1-5c4f-4f37-89bc-2c50c82ab781.json new file mode 100644 index 00000000..de373924 --- /dev/null +++ b/gwserver/_results/workflow_a3b515e1-5c4f-4f37-89bc-2c50c82ab781.json @@ -0,0 +1,135 @@ +{ + "id": "a3b515e1-5c4f-4f37-89bc-2c50c82ab781", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 6.4.2025, 11:29:20", + "status": "waiting_for_user", + "started_at": "2025-04-06T11:29:21.076373", + "last_activity": "2025-04-06T11:29:29.516878", + "prompt": "bitte um websuche, wer bei ValueOn AG arbeitet", + "messages": [ + { + "id": "msg_a8d7d075-26f0-4fa1-ba2e-d657a7d0faa8", + "workflow_id": "a3b515e1-5c4f-4f37-89bc-2c50c82ab781", + "parent_message_id": null, + "started_at": "2025-04-06T11:29:21.093538", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "bitte um websuche, wer bei ValueOn AG arbeitet", + "agent_type": null + }, + { + "id": "msg_a900d6a3-82ac-436f-9b77-be8e7b66787b", + "workflow_id": "a3b515e1-5c4f-4f37-89bc-2c50c82ab781", + "parent_message_id": null, + "started_at": "2025-04-06T11:29:22.743024", + "finished_at": "2025-04-06T11:29:22.746962", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "", + "agent_type": "scraper", + "agent_id": "webcrawler_agent", + "agent_name": "Webscraper" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\nUm eine aussagekräftige Zusammenfassung der Agentenergebnisse zu erstellen, ist es wichtig, die Informationen klar und strukturiert zu präsentieren. Da die spezifischen Ergebnisse des Webscrapers nicht bereitgestellt wurden, werde ich ein allgemeines Format für die Zusammenfassung vorschlagen, das Sie anpassen können, sobald Sie die detaillierten Ergebnisse haben:\n\n### Zusammenfassung der Agentenergebnisse\n\n#### 1. **Zielsetzung und Kontext**\n- **Ziel des Webscrapings**: Beschreiben Sie, warum der Webscraper eingesetzt wurde. Was war das Hauptziel der Datenerhebung?\n- **Kontext**: In welchem Umfeld oder für welches Projekt wurden die Daten gesammelt?\n\n#### 2. **Methodik**\n- **Technologie und Tools**: Welche Technologien und Tools wurden für das Webscraping verwendet?\n- **Datenquellen**: Welche Websites oder Plattformen wurden gescrapt?\n- **Zeitraum**: Wann wurde das Scraping durchgeführt?\n\n#### 3. **Ergebnisse**\n- **Datenvolumen**: Wie viele Datenpunkte wurden gesammelt?\n- **Datenqualität**: Bewertung der Qualität und Vollständigkeit der gesammelten Daten.\n- **Hauptbefunde**: Welche wesentlichen Erkenntnisse wurden aus den Daten gewonnen?\n\n#### 4. **Analyse und Interpretation**\n- **Trends**: Welche Trends oder Muster wurden in den Daten identifiziert?\n- **Vergleiche**: Gibt es relevante Vergleiche zu früheren Daten oder Benchmarks?\n- **Anomalien**: Wurden ungewöhnliche oder unerwartete Ergebnisse festgestellt?\n\n#### 5. **Empfehlungen**\n- **Strategische Empfehlungen**: Welche strategischen Schritte sollten basierend auf den Ergebnissen unternommen werden?\n- **Operative Maßnahmen**: Welche konkreten Maßnahmen werden zur Verbesserung oder Optimierung vorgeschlagen?\n- **Weiterführende Untersuchungen**: Gibt es Bereiche, die einer tieferen Analyse bedürfen?\n\n#### 6. **Herausforderungen und Einschränkungen**\n- **Technische Herausforderungen**: Gab es technische Schwierigkeiten beim Scraping?\n- **Einschränkungen der Daten**: Welche Einschränkungen gibt es hinsichtlich der Datenverfügbarkeit oder -genauigkeit?\n\n#### 7. **Schlussfolgerung**\n- **Zusammenfassung der wichtigsten Erkenntnisse**: Eine kurze Zusammenfassung der wichtigsten Punkte.\n- **Ausblick**: Welche nächsten Schritte werden empfohlen?\n\nPassen Sie diese Struktur an die spezifischen Ergebnisse Ihres Webscrapers an, um eine umfassende und prägnante Zusammenfassung zu erstellen.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_9b99cacc-8da8-406a-a4f0-82439ba9d915", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 46, 0 Dateien", + "type": "info", + "timestamp": "2025-04-06T11:29:21.080377", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_0abb7bfa-5e20-46a3-b8ed-4f3ceaf581f2", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-06T11:29:21.086372", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_bd80d577-edbe-4657-ab44-1bdac90bb311", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-06T11:29:22.711089", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_43c0a31b-50b3-4074-99a4-a0309d93ab38", + "message": "Agent webcrawler_agent wurde ausgewählt mit Aufgabe: Führe eine Websuche durch, um Informationen darübe...", + "type": "info", + "timestamp": "2025-04-06T11:29:22.718088", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ffeb519e-34e6-4389-92e1-e969398c9305", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-06T11:29:22.724138", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_699366a4-7c4a-4cbf-94f9-b87d7d40cb60", + "message": "Agent webcrawler_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T11:29:22.730997", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_35d1a65a-31b0-4843-b328-a192580cad5f", + "message": "Agent 'webcrawler_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T11:29:22.736374", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_0b910c5f-5a38-462d-801d-fe358b790b16", + "message": "Agent 'webcrawler_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-06T11:29:22.799837", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c42ee6be-d5e4-4409-a2a8-ac49fdb03053", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-06T11:29:29.516878", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_a74fe6d3-c6bd-423b-b095-b4cd74a23e4e.json b/gwserver/_results/workflow_a74fe6d3-c6bd-423b-b095-b4cd74a23e4e.json new file mode 100644 index 00000000..cec1d464 --- /dev/null +++ b/gwserver/_results/workflow_a74fe6d3-c6bd-423b-b095-b4cd74a23e4e.json @@ -0,0 +1,45 @@ +{ + "id": "a74fe6d3-c6bd-423b-b095-b4cd74a23e4e", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 12:09:17", + "status": "failed", + "started_at": "2025-04-04T12:09:17.786866", + "last_activity": "2025-04-04T12:09:17.811838", + "prompt": "describe", + "messages": [], + "logs": [ + { + "id": "log_5a5d091a-7349-4264-80e1-680c67c485ee", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 8, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T12:09:17.793645", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_3520f813-9fd8-4b8c-b458-92050eb8e594", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T12:09:17.797285", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b0ae511c-0f42-4d2a-8f3b-b8505ab6870a", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T12:09:17.805423", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_1049593d-ab3a-448d-81f8-9c49a6e2b5d7", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T12:09:17.811838", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_ae8bc11b-4bbf-4cbe-96e3-f5a801647f20.json b/gwserver/_results/workflow_ae8bc11b-4bbf-4cbe-96e3-f5a801647f20.json new file mode 100644 index 00000000..cee52c52 --- /dev/null +++ b/gwserver/_results/workflow_ae8bc11b-4bbf-4cbe-96e3-f5a801647f20.json @@ -0,0 +1,296 @@ +{ + "id": "ae8bc11b-4bbf-4cbe-96e3-f5a801647f20", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 5.4.2025, 00:31:39", + "status": "waiting_for_user", + "started_at": "2025-04-05T00:31:39.916794", + "last_activity": "2025-04-05T00:33:46.408961", + "prompt": "analyse picture", + "messages": [ + { + "id": "msg_4d9367ee-c309-4c64-98a4-a66ae953ea8c", + "workflow_id": "ae8bc11b-4bbf-4cbe-96e3-f5a801647f20", + "parent_message_id": null, + "started_at": "2025-04-05T00:32:32.946849", + "finished_at": "2025-04-05T00:32:32.950147", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "Ich habe als Datenanalyst eine Analyse der bereitgestellten Daten durchgeführt.\n\nHier ist meine detaillierte Analyse:\n1. Die Daten zeigen einen klaren Trend...\n2. Es gibt signifikante Korrelationen zwischen...\n3. Besonders auffällig ist...\n\nMeine Empfehlungen basierend auf der Analyse:\n- Maßnahme 1: ...\n- Maßnahme 2: ...\n- Maßnahme 3: ...", + "agent_type": "analyzer", + "agent_id": "analyst_agent", + "agent_name": "Datenanalyst" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n**Zusammenfassung der Agentenergebnisse**\n\n**Analyseergebnisse:**\n1. **Trend:** Die Daten weisen einen klaren Trend auf, der auf eine bestimmte Entwicklung hinweist.\n2. **Korrelationen:** Es wurden signifikante Korrelationen zwischen bestimmten Variablen festgestellt, die auf mögliche Zusammenhänge oder Einflussfaktoren hinweisen.\n3. **Besondere Auffälligkeiten:** Ein bestimmtes Muster oder eine Anomalie in den Daten ist besonders hervorzuheben.\n\n**Empfehlungen:**\n1. **Maßnahme 1:** Basierend auf den identifizierten Trends und Korrelationen wird diese Maßnahme vorgeschlagen, um die positiven Entwicklungen zu fördern oder negative Einflüsse zu minimieren.\n2. **Maßnahme 2:** Diese Maßnahme zielt darauf ab, die identifizierten Korrelationen weiter zu untersuchen oder zu nutzen.\n3. **Maßnahme 3:** Eine weitere Handlungsempfehlung, die sich aus den besonderen Auffälligkeiten in den Daten ableitet, um mögliche Risiken zu adressieren oder Chancen zu nutzen.\n\nDiese strukturierte Zusammenfassung fasst die wesentlichen Erkenntnisse und Empfehlungen der Datenanalyse zusammen, ohne Redundanzen zu enthalten.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true, + "finished_at": "2025-04-05T00:33:30.532251", + "status": "completed" + }, + { + "id": "msg_bc3b2fb9-940f-42d5-8578-912d8a425a6e", + "workflow_id": "ae8bc11b-4bbf-4cbe-96e3-f5a801647f20", + "parent_message_id": null, + "started_at": "2025-04-05T00:33:30.532251", + "finished_at": null, + "sequence_no": 3, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [ + { + "id": 1, + "source": { + "type": "file", + "id": 1, + "name": "LF-Nutshell.png", + "content_type": "image/png", + "size": 52108, + "upload_date": "2025-04-05T00:33:39.731816" + }, + "contents": [ + { + "type": "text", + "text": "Image Analysis:\nThe image is a flowchart titled \"In a nutshell,\" illustrating a product development process. It consists of several components:\n\n1. **Inputs**: Represented by an inverted triangle funneling into the process.\n\n2. **Product Team**: A rectangular box labeled \"Discover - Define - Shape,\" indicating the initial phase where the product team works on conceptualizing and shaping the product.\n\n3. **Engineering Team**: A box labeled \"Assess & Build,\" showing the phase where the engineering team evaluates and constructs the product.\n\n4. **Q&A Team**: A box labeled \"Validate,\" representing the quality assurance phase where the product is tested and validated.\n\n5. **Operations**: A box labeled \"Release, Run & Monitor,\" indicating the final phase where the product is released, operated, and monitored.\n\n6. **Roadmap**: A horizontal arrow connecting the Product Team to the subsequent phases, labeled \"Roadmap,\" indicating the planning and strategic direction.\n\n7. **Product**: Three consecutive boxes labeled \"Product,\" representing the final output or deliverables of the process.\n\nThe overall layout is linear, showing a progression from inputs to the final product, with each team contributing to different stages of development. The color scheme includes shades of olive green and white, set against a light gray background." + } + ] + } + ], + "content": "bitte analysiere dies", + "agent_type": null + }, + { + "id": "msg_e206a174-a9d9-40a5-afa3-133e15aadb06", + "workflow_id": "ae8bc11b-4bbf-4cbe-96e3-f5a801647f20", + "parent_message_id": null, + "started_at": "2025-04-05T00:33:41.826579", + "finished_at": "2025-04-05T00:33:41.830900", + "sequence_no": 4, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "Ich habe als Datenanalyst eine Analyse der bereitgestellten Daten durchgeführt.\n\nHier ist meine detaillierte Analyse:\n1. Die Daten zeigen einen klaren Trend...\n2. Es gibt signifikante Korrelationen zwischen...\n3. Besonders auffällig ist...\n\nMeine Empfehlungen basierend auf der Analyse:\n- Maßnahme 1: ...\n- Maßnahme 2: ...\n- Maßnahme 3: ...", + "agent_type": "analyzer", + "agent_id": "analyst_agent", + "agent_name": "Datenanalyst" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n**Zusammenfassung der Agentenergebnisse**\n\n**Datenanalyse:**\n\n1. **Trends:** Die Analyse der bereitgestellten Daten zeigt einen klaren Trend, der auf bestimmte Muster oder Entwicklungen hinweist.\n \n2. **Korrelationen:** Es wurden signifikante Korrelationen zwischen verschiedenen Variablen festgestellt, die auf mögliche Zusammenhänge oder Einflussfaktoren hindeuten.\n\n3. **Auffälligkeiten:** Besonders auffällig ist ein bestimmtes Merkmal oder eine Anomalie in den Daten, die weiter untersucht werden sollte.\n\n**Empfehlungen:**\n\n- **Maßnahme 1:** Basierend auf den identifizierten Trends und Korrelationen wird empfohlen, eine spezifische Maßnahme zu ergreifen, um die positiven Entwicklungen zu fördern oder negative Einflüsse zu minimieren.\n\n- **Maßnahme 2:** Eine weitere Maßnahme sollte darauf abzielen, die festgestellten Korrelationen zu nutzen oder zu adressieren, um die Effizienz oder Effektivität zu steigern.\n\n- **Maßnahme 3:** Schließlich wird empfohlen, die auffälligen Merkmale oder Anomalien genauer zu untersuchen und entsprechende Schritte einzuleiten, um deren Auswirkungen zu verstehen und zu steuern.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_536b81c0-1f29-4433-ae20-b8cd03d36646", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 15, 1 Dateien", + "type": "info", + "timestamp": "2025-04-05T00:31:39.929533", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ec54b9e1-87b5-43ad-9450-95fb55902d58", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-05T00:31:39.935951", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_6291d83b-17c6-4474-9333-04dd9e81e3f8", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-05T00:31:39.946726", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c0bcbe6c-d4ac-47b0-a517-532fd8e76d7c", + "message": "Image LF-Current.png analyzed successfully", + "type": "info", + "timestamp": "2025-04-05T00:32:31.182182", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_d1685ab4-5319-4809-a8e1-d4f35c915e8c", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-05T00:32:32.920450", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_bd804b71-9593-49c3-8f6c-b463eba52fa5", + "message": "Agent analyst_agent wurde ausgewählt mit Aufgabe: Analysiere das Bild 'LF-Current.png', das einen Fl...", + "type": "info", + "timestamp": "2025-04-05T00:32:32.925641", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_1a42a212-85bd-45e7-9ef1-b6b7b3bb6538", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-05T00:32:32.931463", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_3c6e9636-f32b-4104-b659-c7bb7710089d", + "message": "Agent analyst_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-05T00:32:32.936982", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_141ab822-2b68-4d04-aa50-b5c907f761ce", + "message": "Agent 'analyst_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-05T00:32:32.941982", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_52b0d049-ce80-4c33-8e38-cef5d3e09da4", + "message": "Agent 'analyst_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-05T00:32:33.010246", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_4e1c76a7-9d30-4351-b0b9-e31a7c85245d", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-05T00:32:40.150558", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_d942f10f-57a2-4cbc-a6da-592be10a7ac7", + "message": "Nachricht gelöscht: user - msg_2f03...", + "type": "info", + "timestamp": "2025-04-05T00:33:13.368593", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_a9862175-4a7e-4897-ab8f-b4d3cf8941cc", + "message": "Benutzereingabe empfangen: 21 Zeichen, 1 Dateien", + "type": "info", + "timestamp": "2025-04-05T00:33:30.519160", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_448db47d-e153-4c42-8b24-8eb637434670", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-05T00:33:30.519160", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_5251679c-2bf9-46fe-90ce-2169108c3b57", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-05T00:33:30.537424", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_7ab631f8-b435-4867-8f81-1f18712bf71f", + "message": "Image LF-Nutshell.png analyzed successfully", + "type": "info", + "timestamp": "2025-04-05T00:33:39.717738", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c896c562-e689-4ae4-a288-e54b19f50fd3", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-05T00:33:41.798544", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c02e2852-3c36-4866-99a9-e57ca7691f5e", + "message": "Agent analyst_agent wurde ausgewählt mit Aufgabe: Analysiere das Bild 'LF-Nutshell.png', das einen F...", + "type": "info", + "timestamp": "2025-04-05T00:33:41.805335", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_1d4e3990-f966-4537-a662-42677879c502", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-05T00:33:41.811053", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_f1fb80b3-6f87-4314-bb46-a4221016f101", + "message": "Agent analyst_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-05T00:33:41.816542", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_5aa5bf6f-3c9d-45c3-bed1-c2a9e92c4d57", + "message": "Agent 'analyst_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-05T00:33:41.821921", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_470fcc74-f839-426a-8e0b-19a5b582dc2a", + "message": "Agent 'analyst_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-05T00:33:41.932599", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c49d520a-105d-48c6-9179-187ad274ef8d", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-05T00:33:46.408961", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_c449765b-6b7a-4002-aee7-3064ea70a8a1.json b/gwserver/_results/workflow_c449765b-6b7a-4002-aee7-3064ea70a8a1.json new file mode 100644 index 00000000..3a8b4c27 --- /dev/null +++ b/gwserver/_results/workflow_c449765b-6b7a-4002-aee7-3064ea70a8a1.json @@ -0,0 +1,249 @@ +{ + "id": "c449765b-6b7a-4002-aee7-3064ea70a8a1", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 6.4.2025, 10:54:15", + "status": "waiting_for_user", + "started_at": "2025-04-06T10:54:15.969769", + "last_activity": "2025-04-06T10:55:41.976361", + "prompt": "mach eine webanalyse, wer bei ValueOn AG arbeitet", + "messages": [ + { + "id": "msg_3c657903-65d7-43af-a5f1-98279d5e420f", + "workflow_id": "c449765b-6b7a-4002-aee7-3064ea70a8a1", + "parent_message_id": null, + "started_at": "2025-04-06T10:54:15.987680", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "mach eine webanalyse, wer bei ValueOn AG arbeitet", + "agent_type": null + }, + { + "id": "msg_03680202-1d19-47c4-8c5b-c3b0df652e31", + "workflow_id": "c449765b-6b7a-4002-aee7-3064ea70a8a1", + "parent_message_id": null, + "started_at": "2025-04-06T10:54:18.270398", + "finished_at": "2025-04-06T10:54:18.273396", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": " [STATUS: ERGEBNIS]", + "agent_type": "scraper", + "agent_id": "webcrawler_agent", + "agent_name": "Webscraper" + }, + { + "id": "msg_cd94010f-be25-4c20-a20e-cd6ce6f904bd", + "workflow_id": "c449765b-6b7a-4002-aee7-3064ea70a8a1", + "parent_message_id": null, + "started_at": "2025-04-06T10:54:18.350527", + "finished_at": "2025-04-06T10:54:18.353532", + "sequence_no": 3, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "Ich habe als Datenanalyst eine Analyse der bereitgestellten Daten durchgeführt.\n\nHier ist meine detaillierte Analyse:\n1. Die Daten zeigen einen klaren Trend...\n2. Es gibt signifikante Korrelationen zwischen...\n3. Besonders auffällig ist...\n\nMeine Empfehlungen basierend auf der Analyse:\n- Maßnahme 1: ...\n- Maßnahme 2: ...\n- Maßnahme 3: ...", + "agent_type": "analyzer", + "agent_id": "analyst_agent", + "agent_name": "Datenanalyst" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n**Zusammenfassung der Agentenergebnisse**\n\n**Webscraper**\n- Der Webscraper-Status zeigt, dass das Ergebnis der Webabfrage noch nicht abgeschlossen ist oder nicht verfügbar ist. Daher liegen keine spezifischen Informationen oder Erkenntnisse aus diesem Agenten vor.\n\n**Datenanalyst**\n- **Analyseergebnisse:**\n 1. **Trend:** Die Daten zeigen einen klaren Trend, der auf bestimmte Muster oder Entwicklungen hinweist.\n 2. **Korrelationen:** Es gibt signifikante Korrelationen zwischen verschiedenen Variablen, die auf mögliche Zusammenhänge oder Einflussfaktoren hinweisen.\n 3. **Besondere Auffälligkeiten:** Bestimmte Datenpunkte oder Muster sind besonders auffällig und könnten auf Anomalien oder besondere Ereignisse hinweisen.\n\n- **Empfehlungen:**\n - **Maßnahme 1:** Eine spezifische Handlung oder Strategie, die auf den identifizierten Trend reagiert.\n - **Maßnahme 2:** Eine weitere Handlung, die die signifikanten Korrelationen adressiert oder nutzt.\n - **Maßnahme 3:** Eine zusätzliche Maßnahme, die auf die besonderen Auffälligkeiten eingeht.\n\nDiese strukturierte Zusammenfassung fasst die wesentlichen Erkenntnisse und Empfehlungen der Datenanalyse zusammen, während die Ergebnisse des Webscrapers derzeit nicht verfügbar sind.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true, + "finished_at": "2025-04-06T10:55:41.069805", + "status": "completed" + }, + { + "id": "msg_e03de58f-4476-4edf-af00-292fdaf29e0c", + "workflow_id": "c449765b-6b7a-4002-aee7-3064ea70a8a1", + "parent_message_id": null, + "started_at": "2025-04-06T10:55:41.069805", + "finished_at": null, + "sequence_no": 5, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "bitte gib mir die antwort des webcrawlers zurück", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben keine spezifischen Aufgaben durchgeführt. Gibt es etwas, wobei ich Ihnen helfen kann?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_403f7ccf-ed42-45bf-9dd2-46fe785c7e14", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 49, 0 Dateien", + "type": "info", + "timestamp": "2025-04-06T10:54:15.975629", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_1094e7fe-69e8-4b2d-b441-89fe800645e8", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-06T10:54:15.980554", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_854ca26b-0766-41bb-b626-e14c8c8a513f", + "message": "Agenten-Entscheidung abgeschlossen: 2 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-06T10:54:18.229624", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b29b56dc-95ea-4e62-9e24-db0209763a50", + "message": "Agent webcrawler_agent wurde ausgewählt mit Aufgabe: Führe eine Webrecherche durch, um Informationen da...", + "type": "info", + "timestamp": "2025-04-06T10:54:18.236976", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_59bc13cb-e943-4c39-b44d-1863fb241134", + "message": "Agent analyst_agent wurde ausgewählt mit Aufgabe: Analysiere die gesammelten Daten über die Mitarbei...", + "type": "info", + "timestamp": "2025-04-06T10:54:18.243007", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_14c1136c-2be3-4f84-b701-041d2323865f", + "message": "2 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-06T10:54:18.249007", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_29a63741-cbf9-4188-a199-4f250e098908", + "message": "Agent webcrawler_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T10:54:18.255013", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_7856e8b6-d06c-4c24-945c-b51530b0b26f", + "message": "Agent 'webcrawler_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T10:54:18.261201", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c8b1b0d9-ec50-416d-8b41-8210470fada8", + "message": "Agent 'webcrawler_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-06T10:54:18.332907", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_83c404d7-e768-48f3-8ee6-08b343d91944", + "message": "Agent analyst_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T10:54:18.338911", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_a3d13452-368f-4d49-a0f7-42ca8f0e09ac", + "message": "Agent 'analyst_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T10:54:18.344528", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_2cd4307e-cb95-4437-a2cf-4994863685e3", + "message": "Agent 'analyst_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-06T10:54:18.421038", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_0da09051-5186-454b-a7de-53f4155debd9", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-06T10:54:21.899245", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_388584fc-115c-43ba-a139-d2e09f628933", + "message": "Benutzereingabe empfangen: 48 Zeichen, 0 Dateien", + "type": "info", + "timestamp": "2025-04-06T10:55:41.055030", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_bfb98fc8-12db-4239-af6a-2623ecfb0ce9", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-06T10:55:41.057269", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_f1dad879-73de-4a04-abea-601257f09791", + "message": "Agenten-Entscheidung abgeschlossen: 0 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-06T10:55:41.959388", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_bf3ab895-07fb-4359-8149-0f38a9ddfc15", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben keine spezifischen Aufgaben durc...", + "type": "info", + "timestamp": "2025-04-06T10:55:41.976361", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_c7bf1c32-e8be-4c9c-85f3-640bb5df5673.json b/gwserver/_results/workflow_c7bf1c32-e8be-4c9c-85f3-640bb5df5673.json new file mode 100644 index 00000000..a604673c --- /dev/null +++ b/gwserver/_results/workflow_c7bf1c32-e8be-4c9c-85f3-640bb5df5673.json @@ -0,0 +1,135 @@ +{ + "id": "c7bf1c32-e8be-4c9c-85f3-640bb5df5673", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 6.4.2025, 11:51:38", + "status": "waiting_for_user", + "started_at": "2025-04-06T11:51:39.277041", + "last_activity": "2025-04-06T11:51:50.006970", + "prompt": "mache eine websuche, wer bei ValueOn AG arbeitet", + "messages": [ + { + "id": "msg_60090c88-9870-47d4-9579-08efcc62cd04", + "workflow_id": "c7bf1c32-e8be-4c9c-85f3-640bb5df5673", + "parent_message_id": null, + "started_at": "2025-04-06T11:51:39.296540", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "mache eine websuche, wer bei ValueOn AG arbeitet", + "agent_type": null + }, + { + "id": "msg_41106885-6a6f-4765-9a46-c15f11abbf0d", + "workflow_id": "c7bf1c32-e8be-4c9c-85f3-640bb5df5673", + "parent_message_id": null, + "started_at": "2025-04-06T11:51:43.600212", + "finished_at": "2025-04-06T11:51:43.606217", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "", + "agent_type": "scraper", + "agent_id": "webcrawler_agent", + "agent_name": "Webscraper" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\nUm eine aussagekräftige Zusammenfassung der Agentenergebnisse des Webscrapers zu erstellen, wäre es hilfreich, die spezifischen Ergebnisse und Erkenntnisse zu kennen, die der Webscraper geliefert hat. Da diese Informationen nicht bereitgestellt wurden, kann ich eine allgemeine Struktur vorschlagen, wie eine solche Zusammenfassung organisiert werden könnte:\n\n### Zusammenfassung der Webscraper-Ergebnisse\n\n#### 1. **Zielsetzung und Umfang**\n- **Ziel des Webscrapings**: Beschreibung des Zwecks, z.B. Datensammlung für Marktanalyse, Trendbeobachtung, etc.\n- **Umfang der Daten**: Anzahl der gescrapten Webseiten, Datenmenge, relevante Branchen oder Themen.\n\n#### 2. **Methodik**\n- **Technische Details**: Verwendete Technologien und Tools, z.B. Python, BeautifulSoup, Scrapy.\n- **Datenquellen**: Auflistung der gescrapten Webseiten und Plattformen.\n- **Zeitlicher Rahmen**: Zeitraum, in dem das Scraping durchgeführt wurde.\n\n#### 3. **Ergebnisse**\n- **Datenanalyse**: Wichtige Muster und Trends, die aus den gesammelten Daten hervorgegangen sind.\n- **Statistische Erkenntnisse**: Quantitative Ergebnisse, z.B. Häufigkeiten, Durchschnittswerte.\n- **Qualitative Erkenntnisse**: Beobachtungen zu Inhalten, z.B. häufige Themen oder Diskurse.\n\n#### 4. **Wichtige Erkenntnisse**\n- **Markttrends**: Identifizierte Trends und Entwicklungen in der Branche.\n- **Kundenverhalten**: Erkenntnisse über das Verhalten oder die Präferenzen der Zielgruppe.\n- **Wettbewerbsanalyse**: Informationen über Wettbewerber und deren Marktposition.\n\n#### 5. **Empfehlungen**\n- **Strategische Empfehlungen**: Vorschläge zur Anpassung der Geschäftsstrategie basierend auf den Ergebnissen.\n- **Operative Maßnahmen**: Konkrete Schritte zur Verbesserung von Prozessen oder Angeboten.\n- **Weiterführende Analysen**: Vorschläge für zusätzliche Untersuchungen oder Datenquellen.\n\n#### 6. **Herausforderungen und Einschränkungen**\n- **Technische Herausforderungen**: Probleme, die während des Scrapings aufgetreten sind.\n- **Datenqualität**: Bewertung der Zuverlässigkeit und Vollständigkeit der gesammelten Daten.\n- **Rechtliche Aspekte**: Berücksichtigung von Datenschutz und rechtlichen Rahmenbedingungen.\n\n#### 7. **Fazit**\n- **Zusammenfassung der wichtigsten Punkte**: Kurze Wiederholung der zentralen Erkenntnisse und Empfehlungen.\n- **Ausblick**: Mögliche zukünftige Entwicklungen und nächste Schritte.\n\nDiese Struktur hilft dabei, die Ergebnisse des Webscrapings klar und prägnant darzustellen, wobei alle wichtigen Erkenntnisse und Empfehlungen berücksichtigt werden.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_ff84c519-18cc-4f07-b956-926691b03501", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 48, 0 Dateien", + "type": "info", + "timestamp": "2025-04-06T11:51:39.280048", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ba66ea60-4e60-4e75-a8e0-b431e1c961b7", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-06T11:51:39.288048", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_e0ac4d8d-44d2-4a0c-aaac-4c361f92a1cc", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-06T11:51:40.413009", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_cf617d5d-529f-420e-a29d-c406445736f6", + "message": "Agent webcrawler_agent wurde ausgewählt mit Aufgabe: Führe eine Websuche durch, um herauszufinden, wer ...", + "type": "info", + "timestamp": "2025-04-06T11:51:40.420245", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_23e8fd49-2924-44e5-8f06-af330593386d", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-06T11:51:40.427252", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_66323f93-078c-4068-8ef1-388bbdac33d6", + "message": "Agent webcrawler_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T11:51:40.433468", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_77390a76-3ca4-4d39-bb01-bca630cdef25", + "message": "Agent 'webcrawler_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T11:51:40.448195", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ca4120fc-d8f5-495b-bbf8-113d3c01e0dd", + "message": "Agent 'webcrawler_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-06T11:51:43.678155", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c4736f69-ba82-47d0-8ab2-c2b320e14f59", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-06T11:51:50.006970", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_ca4f0862-6f53-4728-a5ff-bedf4858af70.json b/gwserver/_results/workflow_ca4f0862-6f53-4728-a5ff-bedf4858af70.json new file mode 100644 index 00000000..fb1d83a5 --- /dev/null +++ b/gwserver/_results/workflow_ca4f0862-6f53-4728-a5ff-bedf4858af70.json @@ -0,0 +1,45 @@ +{ + "id": "ca4f0862-6f53-4728-a5ff-bedf4858af70", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 11:42:26", + "status": "failed", + "started_at": "2025-04-04T11:42:26.581374", + "last_activity": "2025-04-04T11:42:28.456874", + "prompt": "describe", + "messages": [], + "logs": [ + { + "id": "log_31ecab1f-5746-4674-b337-55d0c28edf75", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 8, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T11:42:26.587148", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_4f293eda-9cd4-41a1-83b2-92a4f6dd3330", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T11:42:26.589152", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_3a05b685-6731-4755-aa88-74d9f93385ae", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T11:42:26.595136", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_89faad78-32eb-42d3-a125-8d7dbc01ef68", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T11:42:28.456874", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_cacbcf1d-96f3-401e-83ed-246f331365f0.json b/gwserver/_results/workflow_cacbcf1d-96f3-401e-83ed-246f331365f0.json new file mode 100644 index 00000000..47f2fb85 --- /dev/null +++ b/gwserver/_results/workflow_cacbcf1d-96f3-401e-83ed-246f331365f0.json @@ -0,0 +1,241 @@ +{ + "id": "cacbcf1d-96f3-401e-83ed-246f331365f0", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 6.4.2025, 12:22:59", + "status": "waiting_for_user", + "started_at": "2025-04-06T12:22:59.987681", + "last_activity": "2025-04-06T12:25:31.667697", + "prompt": "kannst du mir eine webanalyse machen über ValueOn AG, was die machen, wer dort arbeitet und welche mitbewerber sie haben?\nbitte das resultat als sauberen bericht", + "messages": [ + { + "id": "msg_18deeaaa-d5ef-4f33-8e56-b646d9bdada8", + "workflow_id": "cacbcf1d-96f3-401e-83ed-246f331365f0", + "parent_message_id": null, + "started_at": "2025-04-06T12:23:00.007679", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "kannst du mir eine webanalyse machen über ValueOn AG, was die machen, wer dort arbeitet und welche mitbewerber sie haben?\nbitte das resultat als sauberen bericht", + "agent_type": null + }, + { + "id": "msg_0ceef5f6-0412-4dd6-a2cb-093f5a2fe000", + "workflow_id": "cacbcf1d-96f3-401e-83ed-246f331365f0", + "parent_message_id": null, + "started_at": "2025-04-06T12:24:12.048306", + "finished_at": "2025-04-06T12:24:12.081034", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "ValueOn AG ist ein führendes Schweizer Unternehmen, das sich auf digitale Transformationen und geschäftskritische IT-Projekte spezialisiert hat. Gegründet im Jahr 2000 und 2022 umbenannt, bietet es strategische Beratung, Projektmanagement und maßgeschneiderte IT-Lösungen an, um den Geschäftserfolg seiner Kunden zu maximieren. Die Geschäftsleitung besteht aus Dominic Largo, Richard Salvisberg und Andreas Friedli, die umfangreiche Erfahrung in der Leitung von IT- und Digitalprojekten mitbringen. ValueOn ist bekannt für seine innovativen Ansätze und hat mehrfach den ASCO Award für \"Best Business Transformation\" gewonnen. Das Unternehmen arbeitet eng mit seinen Kunden zusammen, um langfristige Partnerschaften zu etablieren und bietet durch ein Netzwerk von Certified Partners umfassende Lösungen an. Zu den Mitbewerbern gehören große Beratungsfirmen wie Accenture, Deloitte und Capgemini, die ebenfalls im Bereich der digitalen Transformation tätig sind.\n\n\n\n[1] Unternehmen | ValueOn AG\nURL: https://www.valueon.ch/unternehmen\nSnippet: ValueOn ist bestrebt, Unternehmen durch innovative IT- und Digitalisierungsstrategien nachhaltig zu transformieren und ihren Geschäftserfolg mit Fingerspitzengefühl zu maximieren. ValueOn eben! Fakten. Gründung & Sitz. Gegründet 2000 von Markus Mühlemann; 2022: Rebranding von Project Competence AG in ValueOn AG; Nachfolge 2024 durch ...\nContent: ValueOn AG ist ein führendes Unternehmen in der Schweiz, das sich auf die digitale Transformation und die Unterstützung von businesskritischen IT-Projekten spezialisiert hat. Das Unternehmen wurde im Jahr 2000 von Markus Mühlemann gegründet und erfuhr 2022 ein Rebranding von Project Competence AG zu ValueOn AG. Die Geschäftsleitung besteht aus Dominic Largo, Richard Salvisberg und Andreas Friedli. ValueOn ist bekannt für seine innovativen IT- und Digitalisierungsstrategien, die darauf abzielen, den Geschäftserfolg ihrer Kunden nachhaltig zu maximieren.\n\nDas Unternehmen hat sich durch seine mehrfachen Auszeichnungen mit dem ASCO Award für \"Best Business Transformation\" einen Namen gemacht. ValueOn legt großen Wert auf eine langfristige und vertrauensvolle Partnerschaft mit seinen Kunden und bietet durch seine Dienstleistungen einen stetigen Mehrwert.\n\nDas Team von ValueOn besteht aus Experten, die durch Certified Partners ergänzt werden, um umfassende Lösungen anzubieten. Die Werte des Unternehmens umfassen Klarheit, Tatkraft und Mehrwert, wobei die Ergebnisse der Transformation dauerhaft und wirksam in den Unternehmen der Kunden verankert werden sollen.\n\nZu den Mitbewerbern von ValueOn AG könnten andere Unternehmen gehören, die ebenfalls in der digitalen Transformation und IT-Beratung tätig sind, wie Accenture, Deloitte Digital oder Capgemini. Diese Unternehmen bieten ähnliche Dienstleistungen an und sind ebenfalls in der Lage, große Transformationsprojekte zu leiten und umzusetzen.\n\n[2] Mehrwert dank digitaler Transformation | ValueOn AG\nURL: https://www.valueon.ch/\nSnippet: Welche Digitalisierungsstrategien sind für Ihr Unternehmen zielführend, nachhaltig und wirksam? Unsere Expertinnen und Experten begleiten, beraten und unterstützen Sie vor, während und nach Ihrer Digitalen Business Transformation. ... Wir freuen uns, mit Reto Egloff ein neues Verwaltungsratsmitglied der ValueOn AG, und mit ihm auch einen ...\nContent: Die ValueOn AG ist ein Unternehmen, das sich auf digitale Business-Transformationen und komplexe, geschäftskritische IT- und Digitalprojekte spezialisiert hat. Sie bieten strategische Beratung, Projektmanagement und Unterstützung bei der Umsetzung solcher Projekte an. Ihr Ziel ist es, durch digitale Transformationen einen messbaren Mehrwert für ihre Kunden zu erzielen.\n\nDas Unternehmen ist in Uster, nahe Zürich, ansässig und bietet eine Vielzahl von Dienstleistungen an, darunter die Erarbeitung von Digitalisierungsstrategien, Ist- und Fit-Gap-Analysen, Informations- und Datenarchitektur sowie Verhandlungsmanagement für Transformationen. Sie unterstützen auch bei der Führung von Projekten und Programmen und bieten interimistische Rollen wie Chief Digital Officer (CDO) oder Chief Information Officer (CIO) an.\n\nDas Führungsteam von ValueOn AG umfasst unter anderem Dominic Largo als CEO und Andreas Friedli sowie Richard Salvisberg als Managing Partner. Diese Führungspersönlichkeiten bringen umfangreiche Erfahrung in der Leitung und Umsetzung von IT- und Digitalprojekten mit.\n\nZu den Mitbewerbern von ValueOn AG könnten andere Beratungsunternehmen gehören, die sich ebenfalls auf digitale Transformationen und IT-Projektmanagement spezialisiert haben. Dazu zählen große Beratungsfirmen wie Accenture, Deloitte oder PwC, die ähnliche Dienstleistungen anbieten.\n\nValueOn AG legt großen Wert auf den erzielten Mehrwert für ihre Kunden und hat in der Vergangenheit erfolgreich mit verschiedenen Unternehmen zusammengearbeitet, darunter die KPT Krankenversicherung, WWZ AG und FC Luzern. Diese Projekte wurden mit Fokus auf Effizienzsteigerung, Kostenoptimierung und termingerechte Umsetzung durchgeführt.\n\nInsgesamt positioniert sich die ValueOn AG als kompetenter Partner für Unternehmen, die ihre digitalen Transformationsprozesse optimieren und erfolgreich umsetzen möchten.\n\n[3] ValueOn AG - LinkedIn\nURL: https://www.linkedin.com/company/valueon\nSnippet: ValueOn AG | 900 followers on LinkedIn. Ihr Strategie-, Sparrings- und Projektpartner für digitale Transformationen und businesskritische IT-/Digitalthemen. | Seit über 15 Jahren unterstützen ...\nContent: ValueOn AG ist ein Unternehmen, das sich auf strategische Beratung, Sparring und Projektmanagement für digitale Transformationen und geschäftskritische IT-/Digitalthemen spezialisiert hat. Seit über 15 Jahren unterstützt es sowohl national als auch international tätige Unternehmen und Konzerne in den Bereichen Projektmanagement und Projektportfolio-Management. Das Hauptziel von ValueOn AG ist es, die Projekt-Performance ihrer Kunden kontinuierlich zu verbessern, Risiken und Chancen frühzeitig zu erkennen und eine effektive Führung zu gewährleisten. Das Unternehmen bietet Dienstleistungen an, die höchsten Ansprüchen genügen und den Kunden signifikante Wettbewerbsvorteile verschaffen.\n\nDas Unternehmen hat seinen Sitz in Uster, Zürich, und beschäftigt zwischen 2 und 10 Mitarbeiter. Zu den Kernkompetenzen von ValueOn AG gehören Projektmanagement, Projektportfolio-Management, IT-Transformation, Change Management und Beratung.\n\nEinige der Mitarbeiter bei ValueOn AG sind Richard Salvisberg, Marc Hamburger, Andreas Friedli und Andreas Stuker, die jeweils verschiedene Rollen und Expertisen innerhalb des Unternehmens einbringen.\n\nZu den Mitbewerbern von ValueOn AG zählen Unternehmen wie Parato, Leverage Experts und zeb consulting, die ebenfalls im Bereich der Unternehmensberatung und Dienstleistungen tätig sind.\n\nValueOn AG ist aktiv auf LinkedIn und teilt regelmäßig Updates über neue Projekte, Mitarbeiter und Entwicklungen im Bereich der digitalen Transformation. Das Unternehmen betont die Bedeutung der Digitalisierung und die Notwendigkeit, mit der Zeit zu gehen, um wettbewerbsfähig zu bleiben.\n\n[4] Team | Beratung durch ValueOn AG\nURL: https://www.valueon.ch/team\nSnippet: Übersicht über das Team mit welchem ValueOn erfolgreiche IT Beratung in der ganzen Schweiz umsetzt. Von Digitalisierung bis IT-Strategien.\nContent: ValueOn AG ist ein Unternehmen, das sich auf IT-Beratung in der Schweiz spezialisiert hat. Ihr Fokus liegt auf der Unterstützung von Unternehmen bei der digitalen Transformation und der Umsetzung von businesskritischen IT-Projekten. ValueOn bietet Dienstleistungen in den Bereichen digitale Business-Transformationen und IT-Strategien an. Sie arbeiten eng mit ihren Kunden zusammen, um maßgeschneiderte Lösungen zu entwickeln, die den spezifischen Anforderungen und Zielen der Unternehmen entsprechen.\n\nDas Team von ValueOn AG besteht aus erfahrenen Experten, die über umfangreiche Kenntnisse in den Bereichen IT, Digitalisierung und Business verfügen. Zu den Schlüsselpersonen gehören Andreas Friedli, Dominic Largo, Patrick Motsch, Gregor Burri und Richard Salvisberg. Diese Experten bringen ihre Erfahrung und ihr Fachwissen ein, um die bestmöglichen Lösungen für ihre Kunden zu entwickeln. Das Unternehmen betont die Bedeutung von Agilität, Zielorientierung und Flexibilität in der Zusammenarbeit mit Kunden.\n\nValueOn AG hat eine starke Präsenz in der Schweiz und ist bekannt für ihre Fähigkeit, komplexe IT-Projekte erfolgreich zu managen. Sie arbeiten mit einem Netzwerk von externen zertifizierten Partnern zusammen, um ihre Dienstleistungen zu erweitern und sicherzustellen, dass sie die besten Lösungen für ihre Kunden bieten können.\n\nZu den Mitbewerbern von ValueOn AG gehören andere IT-Beratungsunternehmen, die ebenfalls Dienstleistungen im Bereich der digitalen Transformation und IT-Strategie anbieten. Diese Unternehmen konkurrieren um ähnliche Kunden und Projekte, indem sie ihre eigenen spezialisierten Dienstleistungen und Fachkenntnisse anbieten.\n\nInsgesamt positioniert sich ValueOn AG als vertrauenswürdiger Partner für Unternehmen, die ihre IT-Infrastruktur modernisieren und ihre Geschäftsprozesse digital transformieren möchten. Sie bieten umfassende Unterstützung und Expertise, um sicherzustellen, dass ihre Kunden in der digitalen Welt erfolgreich sind.\n\n[5] ValueOn AG | LinkedIn\nURL: https://ch.linkedin.com/company/valueon\nSnippet: Ihr Strategie-, Sparrings- und Projektpartner für digitale Transformationen und businesskritische IT-/Digitalthemen. Seit über 15 Jahren unterstützen wir erfolgreich national wie international...\nContent: Die ValueOn AG ist ein Unternehmen, das sich auf Beratungsdienstleistungen spezialisiert hat. Ihr Hauptfokus liegt auf der Unterstützung von Unternehmen bei der Optimierung ihrer Geschäftsprozesse und der Implementierung von IT-Lösungen. Die Firma bietet maßgeschneiderte Lösungen, um die Effizienz und Produktivität ihrer Kunden zu steigern. Zu den Dienstleistungen gehören unter anderem Prozessberatung, IT-Consulting und Projektmanagement.\n\nDas Team der ValueOn AG besteht aus erfahrenen Fachleuten, die über umfangreiche Kenntnisse in verschiedenen Branchen verfügen. Die Mitarbeiter zeichnen sich durch ihre Expertise in den Bereichen IT-Management, Prozessoptimierung und strategische Beratung aus. Die Führungsebene setzt sich aus Personen zusammen, die langjährige Erfahrung in der Unternehmensberatung und im IT-Sektor haben.\n\nIn Bezug auf die Mitbewerber der ValueOn AG gibt es mehrere Unternehmen, die in ähnlichen Bereichen tätig sind. Dazu gehören große Beratungsfirmen wie Accenture, Deloitte und Capgemini, die ebenfalls umfassende Beratungs- und IT-Dienstleistungen anbieten. Darüber hinaus gibt es spezialisierte Beratungsunternehmen, die sich auf bestimmte Branchen oder Technologien konzentrieren und somit ebenfalls als Wettbewerber betrachtet werden können.\n\nInsgesamt positioniert sich die ValueOn AG als kompetenter Partner für Unternehmen, die ihre Geschäftsprozesse optimieren und ihre IT-Infrastruktur verbessern möchten. Durch ihre maßgeschneiderten Lösungen und das erfahrene Team kann die ValueOn AG ihren Kunden helfen, ihre Geschäftsziele effizienter zu erreichen.\n\n[6] Romano Caviezel - ValueOn AG\nURL: https://www.valueon.ch/team/romano-caviezel\nSnippet: Romano Caviezel, Certified Partner bei ValueOn AG: C-Level-Manager mit Fokus auf Digitalstrategien, Reorganisationen, Change Management und Digitalisierung.\nContent: ValueOn AG ist ein Unternehmen, das sich auf digitale Business-Transformationen und geschäftskritische Digital- und IT-Projekte spezialisiert hat. Das Unternehmen bietet Dienstleistungen an, die sich auf die Entwicklung von Digitalstrategien, Reorganisationen, Change Management und Digitalisierung konzentrieren. Eine der zentralen Figuren bei ValueOn AG ist Romano Caviezel, ein Certified Partner und C-Level-Manager, der sich auf Digitalstrategien und organisatorische Veränderungen spezialisiert hat. Er bringt umfangreiche Erfahrung in der Organisationsentwicklung und digitalen Transformation mit und hat in verschiedenen Managementpositionen auf C-Level-Ebene gearbeitet.\n\nDas Team von ValueOn AG besteht aus Experten wie Dominic Largo, Richard Salvisberg, Patrick Motsch und anderen, die in Bereichen wie IT-Transformation, Projektmanagement und digitale Strategien tätig sind. Diese Fachleute bringen eine breite Palette von Fähigkeiten und Erfahrungen mit, die es ValueOn AG ermöglichen, maßgeschneiderte Lösungen für ihre Kunden zu entwickeln.\n\nIn Bezug auf Mitbewerber könnte ValueOn AG mit anderen Beratungsunternehmen konkurrieren, die ähnliche Dienstleistungen im Bereich der digitalen Transformation und IT-Projektmanagement anbieten. Dazu könnten Unternehmen wie Accenture, Deloitte oder Capgemini gehören, die ebenfalls umfassende Beratungs- und Implementierungsdienste für digitale Transformationen anbieten.\n\nValueOn AG hebt sich durch ihre spezialisierte Expertise und ihr erfahrenes Team ab, das sich auf die individuellen Bedürfnisse ihrer Kunden konzentriert, um nachhaltige und innovative Lösungen zu schaffen.", + "agent_type": "scraper", + "agent_id": "webcrawler_agent", + "agent_name": "Webscraper" + }, + { + "id": "msg_6624197a-2a61-43fd-9747-1802dbaeb4dc", + "workflow_id": "cacbcf1d-96f3-401e-83ed-246f331365f0", + "parent_message_id": null, + "started_at": "2025-04-06T12:24:19.688731", + "finished_at": "2025-04-06T12:24:19.688731", + "sequence_no": 3, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "Bei der Datenanalyse ist ein Fehler aufgetreten: 'AsyncClient' object has no attribute 'close'", + "agent_type": "analyzer", + "agent_id": "analyst_agent", + "agent_name": "Datenanalyst" + }, + { + "id": "msg_fcf954da-482d-4b18-975d-d84bbf1697c3", + "workflow_id": "cacbcf1d-96f3-401e-83ed-246f331365f0", + "parent_message_id": null, + "started_at": "2025-04-06T12:25:25.478028", + "finished_at": "2025-04-06T12:25:25.493808", + "sequence_no": 4, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "Bei der Erstellung der Dokumentation ist ein Fehler aufgetreten: 'AsyncClient' object has no attribute 'close'", + "agent_type": "documentation", + "agent_id": "documentation_agent", + "agent_name": "Dokumentation" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n**Zusammenfassung der Agentenergebnisse zu ValueOn AG**\n\n**Unternehmensprofil:**\n- **Name:** ValueOn AG\n- **Gründung:** 2000 von Markus Mühlemann, Rebranding 2022 von Project Competence AG zu ValueOn AG\n- **Sitz:** Uster, nahe Zürich, Schweiz\n- **Mitarbeiterzahl:** Zwischen 2 und 10\n- **Führungsteam:** Dominic Largo (CEO), Richard Salvisberg (Managing Partner), Andreas Friedli (Managing Partner), Patrick Motsch, Gregor Burri, Romano Caviezel (Certified Partner)\n- **Kernkompetenzen:** Digitale Transformation, IT-Projektmanagement, Change Management, IT-Strategien, Prozessoptimierung\n\n**Dienstleistungen:**\n- **Strategische Beratung:** Entwicklung von Digitalisierungsstrategien, Ist- und Fit-Gap-Analysen, Informations- und Datenarchitektur\n- **Projektmanagement:** Führung von Projekten und Programmen, Projektportfolio-Management\n- **Interimistische Rollen:** Chief Digital Officer (CDO), Chief Information Officer (CIO)\n- **Spezialisierungen:** IT-Transformation, Reorganisationen, Change Management\n\n**Erfolge und Anerkennungen:**\n- **Auszeichnungen:** Mehrfacher Gewinner des ASCO Award für \"Best Business Transformation\"\n- **Kundenprojekte:** Zusammenarbeit mit KPT Krankenversicherung, WWZ AG, FC Luzern, mit Fokus auf Effizienzsteigerung und Kostenoptimierung\n\n**Wettbewerbsumfeld:**\n- **Hauptmitbewerber:** Große Beratungsfirmen wie Accenture, Deloitte, Capgemini, PwC sowie spezialisierte Beratungsunternehmen wie Parato, Leverage Experts, zeb consulting\n- **Wettbewerbsvorteile:** Maßgeschneiderte Lösungen, erfahrenes Team, langfristige Partnerschaften mit Kunden\n\n**Empfehlungen:**\n- **Fokus auf Innovation:** Weiterhin innovative Ansätze in der digitalen Transformation verfolgen, um sich von Mitbewerbern abzuheben\n- **Stärkung der Partnerschaften:** Ausbau des Netzwerks von Certified Partners zur Erweiterung des Dienstleistungsangebots\n- **Erweiterung der Marktpräsenz:** Aktive Präsenz auf Plattformen wie LinkedIn zur Steigerung der Sichtbarkeit und Kundenakquise\n\n**Zusammenfassung:**\nValueOn AG ist ein führendes Schweizer Unternehmen, das sich auf digitale Transformationen und geschäftskritische IT-Projekte spezialisiert hat. Mit einem erfahrenen Führungsteam und einem Netzwerk von Certified Partners bietet ValueOn maßgeschneiderte Lösungen, die den Geschäftserfolg ihrer Kunden nachhaltig maximieren. Das Unternehmen legt großen Wert auf langfristige Partnerschaften und hat sich durch innovative Ansätze und mehrfach ausgezeichnete Transformationen einen Namen gemacht. ValueOn AG positioniert sich als kompetenter Partner für Unternehmen, die ihre digitalen Transformationsprozesse optimieren und erfolgreich umsetzen möchten.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_bf0089fa-10bb-46e1-a185-48822b4e2004", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 161, 0 Dateien", + "type": "info", + "timestamp": "2025-04-06T12:22:59.991657", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ae9fca6b-6596-4ca1-a28d-4985b723bf8b", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-06T12:22:59.999657", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_a56d16a5-b888-4eed-999d-776f7e390d2c", + "message": "Agenten-Entscheidung abgeschlossen: 3 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-06T12:23:02.459587", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_76507956-b1a6-4090-826f-94c5e72046f0", + "message": "Agent webcrawler_agent wurde ausgewählt mit Aufgabe: Führe eine Webrecherche über die ValueOn AG durch....", + "type": "info", + "timestamp": "2025-04-06T12:23:02.464626", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b19efb59-5013-43a7-9555-367263b5119d", + "message": "Agent analyst_agent wurde ausgewählt mit Aufgabe: Analysiere die gesammelten Daten über die ValueOn ...", + "type": "info", + "timestamp": "2025-04-06T12:23:02.474213", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_432fa718-fa08-4488-9e53-7f39277eca2d", + "message": "Agent documentation_agent wurde ausgewählt mit Aufgabe: Erstelle einen sauberen Bericht basierend auf den ...", + "type": "info", + "timestamp": "2025-04-06T12:23:02.484557", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_e835c2e1-db07-4bf4-bd5c-999b5527f77d", + "message": "3 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:23:02.492896", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b3cd507d-7d8c-4c32-831c-bf11983747c5", + "message": "Agent webcrawler_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:23:02.505242", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_18be5dba-b1b6-430c-a1cf-14fb5e3b93ec", + "message": "Agent 'webcrawler_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:23:02.514538", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_f338f815-20be-4095-9c81-70790359f765", + "message": "Agent 'webcrawler_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-06T12:24:12.217981", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_51e10ab1-2a22-4685-b0bc-3aa30be5d956", + "message": "Agent analyst_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:24:12.239646", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_367f7f9f-e9ae-4401-9cc5-52a052074132", + "message": "Agent 'analyst_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:24:12.261680", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_97d310c1-87a4-48d7-b1e9-7649814e6524", + "message": "Agent 'analyst_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-06T12:24:19.788800", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_6d2738c2-cafd-4918-b6b0-51ea04d0ec28", + "message": "Agent documentation_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:24:19.803775", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_0620d21e-3df9-486a-b135-4878ced6692d", + "message": "Agent 'documentation_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:24:19.810428", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ee3db13e-4635-443f-be6c-6ea41ab0460a", + "message": "Agent 'documentation_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-06T12:25:25.624323", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ae098bb2-c89f-4ef7-8b72-854e547cfbc3", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-06T12:25:31.667697", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_cbeaf9a2-37e9-4c1e-865b-4db41fee8089.json b/gwserver/_results/workflow_cbeaf9a2-37e9-4c1e-865b-4db41fee8089.json new file mode 100644 index 00000000..8f91edfb --- /dev/null +++ b/gwserver/_results/workflow_cbeaf9a2-37e9-4c1e-865b-4db41fee8089.json @@ -0,0 +1,108 @@ +{ + "id": "cbeaf9a2-37e9-4c1e-865b-4db41fee8089", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 11:55:55", + "status": "failed", + "started_at": "2025-04-04T11:55:55.828301", + "last_activity": "2025-04-04T11:56:04.143077", + "prompt": "describe", + "messages": [ + { + "id": "msg_20192add-367e-4fcd-be58-d2cbde51b8f5", + "workflow_id": "cbeaf9a2-37e9-4c1e-865b-4db41fee8089", + "parent_message_id": null, + "started_at": "2025-04-04T11:55:55.839364", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "describe", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben keine spezifischen Aufgaben durchgeführt. Gibt es etwas, wobei ich Ihnen helfen kann?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true, + "finished_at": "2025-04-04T11:56:04.136548", + "status": "completed" + } + ], + "logs": [ + { + "id": "log_8469e064-f4a7-4eed-bfbc-890117ab472a", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 8, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T11:55:55.833303", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_1a1e3e99-586d-4e08-bc6d-00d6566251f3", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T11:55:55.835851", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_072c853b-6a6a-4ad2-83db-512abfeec8ff", + "message": "Agenten-Entscheidung abgeschlossen: 0 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T11:55:56.552867", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_0e8c8f2d-f945-4ad2-836d-2fd35e5c05f2", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben keine spezifischen Aufgaben durc...", + "type": "info", + "timestamp": "2025-04-04T11:55:56.554866", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_27da6b33-fbe0-4247-95c3-6e51f6d3db93", + "message": "Benutzereingabe empfangen: 8 Zeichen, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T11:56:04.131550", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_696589b0-7a13-4cc2-8b9b-557a2d082a11", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T11:56:04.133575", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_55329bc3-ac94-4adb-b60a-83ad0fa05a52", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T11:56:04.138556", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_f9d8f5a2-291a-465e-bb7d-ef898a826dab", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T11:56:04.143077", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": false +} \ No newline at end of file diff --git a/gwserver/_results/workflow_cfb78b63-b90e-487f-8e4f-b06d2eb3c897.json b/gwserver/_results/workflow_cfb78b63-b90e-487f-8e4f-b06d2eb3c897.json new file mode 100644 index 00000000..c224b096 --- /dev/null +++ b/gwserver/_results/workflow_cfb78b63-b90e-487f-8e4f-b06d2eb3c897.json @@ -0,0 +1,45 @@ +{ + "id": "cfb78b63-b90e-487f-8e4f-b06d2eb3c897", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 10:53:33", + "status": "failed", + "started_at": "2025-04-04T10:53:33.539227", + "last_activity": "2025-04-04T10:53:33.559733", + "prompt": "describe image", + "messages": [], + "logs": [ + { + "id": "log_810e8e9a-86f4-41fe-9222-4ec40e321076", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 14, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T10:53:33.543218", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b0cf36e8-c220-4fea-b165-d9621508fb4b", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T10:53:33.545224", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_4da8eed1-3eff-4f73-8050-00609e479bf8", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T10:53:33.549224", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_cdf0f053-66d1-407e-b64e-c7e8fa717c99", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T10:53:33.559733", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_d75da571-8d77-4f08-93ec-408094897b7c.json b/gwserver/_results/workflow_d75da571-8d77-4f08-93ec-408094897b7c.json new file mode 100644 index 00000000..6b019322 --- /dev/null +++ b/gwserver/_results/workflow_d75da571-8d77-4f08-93ec-408094897b7c.json @@ -0,0 +1,45 @@ +{ + "id": "d75da571-8d77-4f08-93ec-408094897b7c", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 11:32:47", + "status": "failed", + "started_at": "2025-04-04T11:32:47.709973", + "last_activity": "2025-04-04T11:32:49.418963", + "prompt": "analyse image", + "messages": [], + "logs": [ + { + "id": "log_fba016a7-9dfa-4f6d-beb5-add358f74b0b", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 13, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T11:32:47.713975", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_1a02934f-4d47-4556-9c1a-6e8933d5f229", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T11:32:47.715977", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_a588a9e9-d960-4e75-ae0c-242d6b726c21", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T11:32:47.720976", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_35942ad8-552e-4f17-b1af-dffb63abfa03", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T11:32:49.418963", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_d7c2bd78-7c8b-4908-8b8e-1cf83c49a3f5.json b/gwserver/_results/workflow_d7c2bd78-7c8b-4908-8b8e-1cf83c49a3f5.json new file mode 100644 index 00000000..8c2819b0 --- /dev/null +++ b/gwserver/_results/workflow_d7c2bd78-7c8b-4908-8b8e-1cf83c49a3f5.json @@ -0,0 +1,257 @@ +{ + "id": "d7c2bd78-7c8b-4908-8b8e-1cf83c49a3f5", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 6.4.2025, 12:31:33", + "status": "waiting_for_user", + "started_at": "2025-04-06T12:31:34.487515", + "last_activity": "2025-04-06T12:35:18.227927", + "prompt": "kannst du mir einen bericht erstellen, wie man eine präsentation bei einem event für verwaltungsräte vorbereitet und hält?", + "messages": [ + { + "id": "msg_001f1d57-55c4-45a8-8b74-66368bb64dfe", + "workflow_id": "d7c2bd78-7c8b-4908-8b8e-1cf83c49a3f5", + "parent_message_id": null, + "started_at": "2025-04-06T12:31:34.513003", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "kannst du mir einen bericht erstellen, wie man eine präsentation bei einem event für verwaltungsräte vorbereitet und hält?", + "agent_type": null + }, + { + "id": "msg_f2ec3585-d56e-4a44-bda3-dd14652ed225", + "workflow_id": "d7c2bd78-7c8b-4908-8b8e-1cf83c49a3f5", + "parent_message_id": null, + "started_at": "2025-04-06T12:32:48.455771", + "finished_at": "2025-04-06T12:32:48.475123", + "sequence_no": 2, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "# Erfolgreiche Präsentationen vor Verwaltungsräten: Ein Leitfaden für Vorbereitung und Durchführung\n\n## Zusammenfassung\n\nDer Bericht \"Erfolgreiche Präsentationen vor Verwaltungsräten: Ein Leitfaden für Vorbereitung und Durchführung\" bietet umfassende Anleitungen zur effektiven Gestaltung und Präsentation von Inhalten vor Verwaltungsräten. Er behandelt Best Practices für die Präsentationsgestaltung, einschließlich der Strukturierung von Inhalten und der Nutzung visueller Hilfsmittel. Zudem werden wichtige Aspekte der Vorbereitung und Durchführung beleuchtet, wie die Kenntnis der Zielgruppe und die Proben der Präsentation. Der Bericht identifiziert potenzielle Herausforderungen, wie Lampenfieber und schwierige Fragen, und bietet Strategien zu deren Bewältigung. Ziel ist es, Präsentierenden das nötige Rüstzeug für einen souveränen und überzeugenden Auftritt zu vermitteln.\n\n## Inhaltsverzeichnis\n\n1. Kapitel 1: Einführung in die Präsentation vor Verwaltungsräten\n2. Kapitel 2: Best Practices für die Präsentationsgestaltung\n3. Kapitel 3: Vorbereitung auf die Präsentation\n4. Kapitel 4: Durchführung der Präsentation\n5. Kapitel 5: Umgang mit Herausforderungen\n6. Kapitel 6: Nachbereitung und Feedback\n\n## 1. Kapitel 1: Einführung in die Präsentation vor Verwaltungsräten\n\nPräsentationen vor Verwaltungsräten sind eine einzigartige Herausforderung, die sowohl strategische Planung als auch präzise Ausführung erfordert. Verwaltungsräte bestehen in der Regel aus erfahrenen Führungskräften, die fundierte Entscheidungen auf der Grundlage der ihnen präsentierten Informationen treffen müssen. Daher ist es entscheidend, dass Ihre Präsentation sowohl inhaltlich als auch in der Darbietung überzeugt. In diesem Kapitel werden die Besonderheiten und Erwartungen bei Präsentationen vor Verwaltungsräten erläutert und die Bedeutung einer gezielten Vorbereitung hervorgehoben.\n\n### Besonderheiten von Präsentationen vor Verwaltungsräten\n\n**1. Zielgerichtete Kommunikation:**\nVerwaltungsräte erwarten prägnante und zielgerichtete Informationen. Ihre Präsentation sollte klar strukturiert sein, um die wesentlichen Punkte effizient zu vermitteln. Vermeiden Sie unnötige Details und konzentrieren Sie sich auf die Kernaussagen, die für die Entscheidungsfindung relevant sind.\n\n**2. Strategische Relevanz:**\nDie Themen, die Sie präsentieren, sollten von strategischer Bedeutung für das Unternehmen sein. Verwaltungsräte interessieren sich für die langfristigen Auswirkungen Ihrer Vorschläge und deren Ausrichtung auf die Unternehmensziele.\n\n**3. Datengetriebene Argumentation:**\nVerwaltungsräte legen großen Wert auf fundierte Daten und Analysen. Ihre Argumente sollten durch solide Daten untermauert werden, um Glaubwürdigkeit und Vertrauen zu schaffen.\n\n### Erwartungen der Verwaltungsräte\n\n**1. Klarheit und Präzision:**\nVerwaltungsräte erwarten klare und präzise Präsentationen. Vermeiden Sie Fachjargon und komplizierte Ausdrücke, die die Verständlichkeit beeinträchtigen könnten. Ihre Botschaft sollte auch für Personen ohne tiefes Fachwissen nachvollziehbar sein.\n\n**2. Zeitmanagement:**\nDie Zeit der Verwaltungsräte ist kostbar. Halten Sie sich strikt an die vorgegebene Zeit und planen Sie Ihre Präsentation so, dass genügend Raum für Fragen und Diskussionen bleibt.\n\n**3. Lösungsorientierter Ansatz:**\nVerwaltungsräte suchen nach Lösungen und nicht nur nach Problembeschreibungen. Ihre Präsentation sollte daher nicht nur Herausforderungen aufzeigen, sondern auch konkrete Lösungsansätze und Handlungsempfehlungen bieten.\n\n### Die Bedeutung gezielter Vorbereitung\n\n**1. Recherche und Analyse:**\nEine gründliche Recherche und Analyse der präsentierten Themen ist unerlässlich. Verstehen Sie die aktuellen Herausforderungen und Chancen des Unternehmens und bereiten Sie sich darauf vor, diese in Ihrer Präsentation zu adressieren.\n\n**2. Kenntnis der Zielgruppe:**\nVerstehen Sie die Zusammensetzung und die Interessen des Verwaltungsrats. Passen Sie Ihre Präsentation an die spezifischen Erwartungen und Prioritäten der Mitglieder an.\n\n**3. Proben und Feedback:**\nÜben Sie Ihre Präsentation mehrfach und holen Sie sich Feedback von Kollegen oder Mentoren. Dies hilft Ihnen, Ihre Argumentation zu verfeinern und potenzielle Schwachstellen zu identifizieren.\n\n### Mögliche Herausforderungen und deren Bewältigung\n\n**1. Unerwartete Fragen:**\nBereiten Sie sich auf unerwartete Fragen vor, indem Sie mögliche Szenarien durchspielen und Antworten parat haben. Bleiben Sie ruhig und sachlich, auch wenn Sie mit kritischen Fragen konfrontiert werden.\n\n**2. Technische Probleme:**\nStellen Sie sicher, dass alle technischen Aspekte Ihrer Präsentation reibungslos funktionieren. Testen Sie die Ausrüstung im Voraus und haben Sie einen Plan B für den Fall technischer Schwierigkeiten.\n\n**3. Nervosität:**\nNervosität ist normal, kann aber durch gründliche Vorbereitung und Übung reduziert werden. Visualisieren Sie den Erfolg Ihrer Präsentation und konzentrieren Sie sich auf Ihre Stärken.\n\nInsgesamt ist eine Präsentation vor einem Verwaltungsrat eine Gelegenheit, Einfluss zu nehmen und strategische Entscheidungen zu unterstützen. Durch gezielte Vorbereitung und ein tiefes Verständnis der Erwartungen können Sie Ihre Präsentation erfolgreich gestalten und durchführen.\n\n## 2. Kapitel 2: Best Practices für die Präsentationsgestaltung\n\n**Einleitung**\n\nDie Gestaltung einer Präsentation für Verwaltungsräte erfordert besondere Sorgfalt und Präzision. Verwaltungsräte bestehen in der Regel aus erfahrenen Führungskräften, die fundierte, prägnante und visuell ansprechende Informationen erwarten. In diesem Kapitel werden Best Practices für die Präsentationsgestaltung vorgestellt, um sicherzustellen, dass Ihre Botschaft klar und überzeugend vermittelt wird.\n\n**1. Strukturierung der Inhalte**\n\nEine klare und logische Struktur ist entscheidend für den Erfolg Ihrer Präsentation. Sie hilft, die Aufmerksamkeit der Zuhörer zu halten und die Kernaussagen effektiv zu vermitteln.\n\n- **Einleitung**: Beginnen Sie mit einer kurzen Einführung, die den Zweck der Präsentation und die Hauptthemen umreißt. Stellen Sie sicher, dass Sie die Relevanz der Präsentation für den Verwaltungsrat hervorheben.\n \n- **Hauptteil**: Gliedern Sie den Hauptteil in klare, thematische Abschnitte. Jeder Abschnitt sollte eine zentrale Botschaft oder ein Argument enthalten, das durch Daten oder Beispiele untermauert wird. Verwenden Sie Überschriften und Unterüberschriften, um die Struktur zu verdeutlichen.\n\n- **Schlussfolgerung**: Fassen Sie die wichtigsten Punkte zusammen und bieten Sie klare Empfehlungen oder Handlungsaufforderungen an. Dies hilft, die Präsentation mit einem starken, einprägsamen Abschluss zu beenden.\n\n**2. Effektive Nutzung visueller Hilfsmittel**\n\nVisuelle Hilfsmittel sind ein kraftvolles Werkzeug, um komplexe Informationen verständlich zu machen und das Interesse der Zuhörer zu wecken.\n\n- **Grafiken und Diagramme**: Nutzen Sie Grafiken, um Daten anschaulich darzustellen. Wählen Sie den Diagrammtyp, der am besten zu den präsentierten Daten passt (z. B. Balkendiagramme für Vergleiche, Liniendiagramme für Trends).\n\n- **Bilder und Videos**: Verwenden Sie Bilder, um Emotionen zu wecken oder Konzepte zu veranschaulichen. Videos können komplexe Prozesse oder Fallstudien lebendig darstellen.\n\n- **Textgestaltung**: Halten Sie Text auf Folien minimal. Verwenden Sie Stichpunkte statt ganzer Sätze und achten Sie auf eine gut lesbare Schriftgröße und -art. Hervorhebungen durch Farben oder Fettdruck können wichtige Punkte betonen.\n\n**3. Tipps zur Präsentationsgestaltung**\n\n- **Konsistenz**: Achten Sie auf ein einheitliches Design, einschließlich Farben, Schriftarten und Layouts. Dies verleiht Ihrer Präsentation Professionalität und erleichtert das Verständnis.\n\n- **Interaktivität**: Integrieren Sie interaktive Elemente, wie z. B. Fragen an das Publikum oder kurze Umfragen, um das Engagement zu erhöhen.\n\n- **Zeitmanagement**: Planen Sie die Dauer jedes Abschnitts sorgfältig, um sicherzustellen, dass Sie innerhalb der vorgegebenen Zeit bleiben. Üben Sie die Präsentation, um ein Gefühl für das Timing zu bekommen.\n\n**4. Mögliche Herausforderungen und deren Bewältigung**\n\n- **Technische Probleme**: Bereiten Sie sich auf technische Schwierigkeiten vor, indem Sie Ihre Ausrüstung im Voraus testen und eine Backup-Kopie Ihrer Präsentation auf einem USB-Stick oder in der Cloud speichern.\n\n- **Unvorhergesehene Fragen**: Seien Sie bereit, auf unerwartete Fragen zu reagieren. Eine gründliche Vorbereitung und ein tiefes Verständnis des Themas helfen, souverän zu antworten.\n\n- **Aufmerksamkeitsverlust**: Halten Sie die Präsentation dynamisch und abwechslungsreich, um das Interesse der Zuhörer zu bewahren. Wechseln Sie zwischen verschiedenen Medien und Präsentationsstilen.\n\n**Fazit**\n\nDie Gestaltung einer erfolgreichen Präsentation für Verwaltungsräte erfordert eine sorgfältige Planung und die Anwendung bewährter Praktiken. Durch eine klare Struktur, den effektiven Einsatz visueller Hilfsmittel und die Berücksichtigung potenzieller Herausforderungen können Sie sicherstellen, dass Ihre Präsentation sowohl informativ als auch überzeugend ist.\n\n## 3. Kapitel 3: Vorbereitung auf die Präsentation\n\n### Analyse der Zielgruppe\n\nDie Vorbereitung auf eine Präsentation vor Verwaltungsräten beginnt mit einer gründlichen Analyse der Zielgruppe. Verwaltungsräte bestehen oft aus erfahrenen Fachleuten mit unterschiedlichem Hintergrund und spezifischen Interessen. Daher ist es entscheidend, die Zusammensetzung des Gremiums zu verstehen, um die Präsentation entsprechend anzupassen.\n\n- **Demografische Merkmale:** Berücksichtigen Sie das Alter, die Berufserfahrung und die Fachgebiete der Mitglieder. Diese Informationen helfen, den Ton und die Komplexität der Präsentation anzupassen.\n- **Interessen und Prioritäten:** Ermitteln Sie die Hauptanliegen und Prioritäten des Verwaltungsrats. Dies könnte durch die Analyse vergangener Sitzungsprotokolle oder durch Gespräche mit internen Ansprechpartnern geschehen.\n- **Entscheidungsfindung:** Verstehen Sie, wie Entscheidungen im Gremium getroffen werden. Sind sie datengetrieben oder basieren sie mehr auf strategischen Überlegungen? Dies beeinflusst, welche Art von Informationen hervorgehoben werden sollten.\n\n### Erstellen eines klaren Präsentationsziels\n\nEin klares Ziel ist das Fundament jeder erfolgreichen Präsentation. Es dient als Leitfaden für die Strukturierung der Inhalte und hilft, den Fokus während der Präsentation zu bewahren.\n\n- **Zieldefinition:** Formulieren Sie ein präzises Ziel, das Sie mit Ihrer Präsentation erreichen möchten. Möchten Sie informieren, überzeugen oder eine Entscheidung herbeiführen?\n- **Erfolgskriterien:** Definieren Sie, wie der Erfolg Ihrer Präsentation gemessen werden soll. Dies könnte die Zustimmung zu einem Vorschlag oder die Bereitstellung zusätzlicher Ressourcen sein.\n- **Botschaftskern:** Entwickeln Sie eine zentrale Botschaft, die Ihre Präsentation durchzieht. Diese sollte klar, einprägsam und auf das Ziel abgestimmt sein.\n\n### Strukturierung der Präsentation\n\nEine gut strukturierte Präsentation erleichtert es dem Publikum, den Inhalten zu folgen und die Kernaussagen zu verstehen.\n\n- **Einleitung:** Beginnen Sie mit einer starken Einleitung, die das Interesse weckt und das Ziel der Präsentation klarstellt.\n- **Hauptteil:** Gliedern Sie den Hauptteil logisch und thematisch. Verwenden Sie klare Übergänge zwischen den Abschnitten, um den roten Faden zu bewahren.\n- **Schluss:** Fassen Sie die wichtigsten Punkte zusammen und schließen Sie mit einem starken, einprägsamen Schlusswort, das die zentrale Botschaft verstärkt.\n\n### Durchführung von Proben\n\nProben sind ein wesentlicher Bestandteil der Vorbereitung und helfen, die Präsentation zu verfeinern und das Selbstvertrauen zu stärken.\n\n- **Simulationsproben:** Führen Sie Proben unter realistischen Bedingungen durch, um ein Gefühl für den Ablauf und die Zeitplanung zu bekommen.\n- **Feedback einholen:** Bitten Sie Kollegen oder Mentoren um konstruktives Feedback. Achten Sie besonders auf Verständlichkeit, Tempo und Körpersprache.\n- **Technische Tests:** Überprüfen Sie alle technischen Hilfsmittel, die Sie verwenden werden, wie Präsentationssoftware, Mikrofone und Projektoren, um technische Pannen zu vermeiden.\n\n### Mögliche Herausforderungen und deren Bewältigung\n\nTrotz sorgfältiger Vorbereitung können unvorhergesehene Herausforderungen auftreten. Eine proaktive Planung hilft, diese effektiv zu bewältigen.\n\n- **Technische Probleme:** Bereiten Sie sich auf technische Schwierigkeiten vor, indem Sie Backup-Pläne entwickeln, wie das Mitführen von ausgedruckten Handouts oder das Speichern der Präsentation auf mehreren Geräten.\n- **Unvorhergesehene Fragen:** Seien Sie bereit, auf kritische Fragen oder Einwände zu reagieren. Eine gründliche Vorbereitung und das Wissen um die Interessen des Verwaltungsrats helfen, souverän zu antworten.\n- **Zeitmanagement:** Halten Sie sich strikt an die vorgegebene Zeit. Üben Sie Ihre Präsentation mit einem Timer, um sicherzustellen, dass Sie alle wichtigen Punkte abdecken, ohne zu überziehen.\n\nDurch eine sorgfältige Vorbereitung, die auf die spezifischen Anforderungen und Erwartungen des Verwaltungsrats abgestimmt ist, können Sie eine überzeugende und effektive Präsentation gestalten.\n\n## 4. Kapitel 4: Durchführung der Präsentation\n\n### Körpersprache\n\nDie Körpersprache spielt eine entscheidende Rolle bei der Durchführung einer Präsentation vor Verwaltungsräten. Sie kann die Wirkung Ihrer Worte verstärken und das Vertrauen des Publikums in Ihre Kompetenz und Ihr Engagement stärken.\n\n- **Haltung**: Eine aufrechte und offene Körperhaltung signalisiert Selbstbewusstsein und Offenheit. Vermeiden Sie es, die Arme zu verschränken oder die Hände in die Taschen zu stecken, da dies defensiv oder unvorbereitet wirken kann.\n\n- **Gestik**: Nutzen Sie Ihre Hände, um wichtige Punkte zu unterstreichen, aber vermeiden Sie übermäßige oder ablenkende Bewegungen. Natürliche Gesten können Ihre Argumente verstärken und das Publikum einbeziehen.\n\n- **Augenkontakt**: Stellen Sie sicher, dass Sie regelmäßig Augenkontakt mit den Mitgliedern des Verwaltungsrats herstellen. Dies schafft eine persönliche Verbindung und zeigt, dass Sie engagiert und aufmerksam sind.\n\n- **Bewegung**: Nutzen Sie den Raum, um Ihre Präsenz zu verstärken, aber bewegen Sie sich bewusst und zielgerichtet. Vermeiden Sie nervöses Hin- und Herlaufen, da dies ablenkend wirken kann.\n\n### Stimme\n\nDie Art und Weise, wie Sie sprechen, ist ebenso wichtig wie das, was Sie sagen. Eine klare und überzeugende Stimme kann Ihre Botschaft erheblich verstärken.\n\n- **Lautstärke**: Sprechen Sie laut genug, um von allen gehört zu werden, aber vermeiden Sie es, zu schreien. Eine angemessene Lautstärke zeigt Selbstbewusstsein und Autorität.\n\n- **Tempo**: Variieren Sie Ihr Sprechtempo, um Interesse zu wecken und wichtige Punkte hervorzuheben. Ein zu schnelles Sprechen kann nervös wirken, während ein zu langsames Sprechen das Interesse des Publikums verlieren kann.\n\n- **Tonlage**: Eine abwechslungsreiche Tonlage hält das Publikum aufmerksam und kann Emotionen und Engagement vermitteln. Vermeiden Sie einen monotonen Ton, der das Interesse der Zuhörer mindern könnte.\n\n- **Pausen**: Nutzen Sie Pausen, um dem Publikum Zeit zu geben, über wichtige Punkte nachzudenken. Pausen können auch als effektives Mittel eingesetzt werden, um Spannung aufzubauen oder einen Punkt zu betonen.\n\n### Interaktion mit dem Publikum\n\nDie Interaktion mit dem Publikum ist entscheidend, um eine Verbindung herzustellen und das Interesse der Zuhörer aufrechtzuerhalten.\n\n- **Fragen stellen**: Integrieren Sie Fragen in Ihre Präsentation, um das Publikum einzubeziehen und zum Nachdenken anzuregen. Dies kann auch helfen, die Aufmerksamkeit der Zuhörer zu gewinnen und zu halten.\n\n- **Feedback einholen**: Ermutigen Sie das Publikum, Fragen zu stellen oder Kommentare abzugeben. Dies zeigt, dass Sie offen für Diskussionen sind und die Meinungen der Zuhörer schätzen.\n\n- **Reaktionen beobachten**: Achten Sie auf die nonverbalen Reaktionen des Publikums, wie z.B. Nicken oder Stirnrunzeln. Diese Hinweise können Ihnen helfen, den Erfolg Ihrer Präsentation zu beurteilen und gegebenenfalls Anpassungen vorzunehmen.\n\n- **Flexibilität zeigen**: Seien Sie bereit, auf unerwartete Fragen oder Kommentare einzugehen. Flexibilität und die Fähigkeit, spontan zu reagieren, zeigen Ihre Kompetenz und Ihr Engagement.\n\n### Mögliche Herausforderungen und deren Bewältigung\n\nBei der Durchführung einer Präsentation können verschiedene Herausforderungen auftreten. Hier sind einige häufige Probleme und Strategien zu deren Bewältigung:\n\n- **Nervosität**: Vorbereitung und Übung sind der Schlüssel zur Überwindung von Nervosität. Atemübungen und positive Visualisierungen können ebenfalls helfen, die Nerven zu beruhigen.\n\n- **Technische Probleme**: Stellen Sie sicher, dass Sie mit der verwendeten Technologie vertraut sind und haben Sie einen Backup-Plan für den Fall von technischen Schwierigkeiten.\n\n- **Unaufmerksames Publikum**: Nutzen Sie interaktive Elemente und Fragen, um das Interesse des Publikums zu wecken. Eine dynamische Präsentation kann helfen, die Aufmerksamkeit zu halten.\n\n- **Kritische Fragen**: Bereiten Sie sich auf mögliche kritische Fragen vor und bleiben Sie ruhig und sachlich in Ihrer Antwort. Zeigen Sie Verständnis und bieten Sie fundierte Antworten an.\n\nDurch die Beachtung dieser Aspekte und die Vorbereitung auf mögliche Herausforderungen können Sie Ihre Präsentation erfolgreich durchführen und einen bleibenden Eindruck bei den Mitgliedern des Verwaltungsrats hinterlassen.\n\n## 5. Kapitel 5: Umgang mit Herausforderungen\n\n### Lampenfieber überwinden\n\nLampenfieber ist eine der häufigsten Herausforderungen, denen sich Präsentierende gegenübersehen, insbesondere bei wichtigen Anlässen wie Präsentationen vor Verwaltungsräten. Es ist wichtig, diese Nervosität zu erkennen und Strategien zu entwickeln, um sie zu bewältigen.\n\n#### Ursachen von Lampenfieber\n- **Angst vor Bewertung:** Die Sorge, von einem hochrangigen Publikum beurteilt zu werden.\n- **Mangelnde Vorbereitung:** Unzureichende Vorbereitung kann das Selbstvertrauen beeinträchtigen.\n- **Hohe Erwartungen:** Der Druck, eine perfekte Präsentation zu liefern.\n\n#### Strategien zur Bewältigung von Lampenfieber\n- **Gründliche Vorbereitung:** Eine umfassende Vorbereitung auf das Thema und die Präsentation selbst kann das Selbstvertrauen stärken.\n- **Atemtechniken:** Tiefe Atemübungen vor der Präsentation können helfen, die Nerven zu beruhigen.\n- **Visualisierung:** Stellen Sie sich vor, wie Sie erfolgreich präsentieren, um positive Gedanken zu fördern.\n- **Übung:** Proben Sie die Präsentation mehrmals, idealerweise vor einem kleineren Publikum, um Feedback zu erhalten.\n\n### Umgang mit schwierigen Fragen\n\nSchwierige Fragen können während einer Präsentation auftreten und stellen eine Herausforderung dar, die mit Geschick und Ruhe gemeistert werden muss.\n\n#### Arten von schwierigen Fragen\n- **Kritische Fragen:** Fragen, die die Glaubwürdigkeit oder die Daten der Präsentation in Frage stellen.\n- **Unklare Fragen:** Fragen, die vage oder mehrdeutig sind.\n- **Provokative Fragen:** Fragen, die darauf abzielen, den Präsentierenden aus der Fassung zu bringen.\n\n#### Strategien zur Beantwortung schwieriger Fragen\n- **Aktives Zuhören:** Hören Sie die Frage vollständig an, bevor Sie antworten.\n- **Klarheit suchen:** Bitten Sie um Klarstellung, wenn eine Frage unklar ist.\n- **Ruhig bleiben:** Bewahren Sie Ruhe und Professionalität, unabhängig von der Frage.\n- **Ehrlichkeit:** Wenn Sie die Antwort nicht wissen, geben Sie dies zu und bieten Sie an, die Informationen nachzuliefern.\n- **Brücken bauen:** Lenken Sie die Frage geschickt zurück zum Hauptthema der Präsentation, um die Kontrolle zu behalten.\n\n### Technische Probleme\n\nTechnische Probleme können unerwartet auftreten und die Präsentation stören. Eine proaktive Herangehensweise kann helfen, diese Herausforderungen zu minimieren.\n\n#### Häufige technische Probleme\n- **Ausfall der Präsentationstechnik:** Probleme mit dem Laptop, Projektor oder der Internetverbindung.\n- **Softwareprobleme:** Schwierigkeiten mit Präsentationssoftware oder Dateiformaten.\n- **Audio- und Videoausfälle:** Mikrofon- oder Lautsprecherausfälle.\n\n#### Strategien zur Bewältigung technischer Probleme\n- **Vorab-Check:** Führen Sie vor der Präsentation einen Technik-Check durch, um sicherzustellen, dass alle Geräte funktionieren.\n- **Backup-Pläne:** Haben Sie eine gedruckte Version der Präsentation oder eine alternative Präsentationsmethode bereit.\n- **Technische Unterstützung:** Stellen Sie sicher, dass technisches Personal zur Verfügung steht, um bei Problemen zu helfen.\n- **Gelassenheit bewahren:** Bleiben Sie ruhig und professionell, während technische Probleme gelöst werden.\n\n### Zeitmanagement\n\nEffektives Zeitmanagement ist entscheidend, um sicherzustellen, dass alle wichtigen Punkte der Präsentation behandelt werden, ohne das Publikum zu überfordern.\n\n#### Herausforderungen im Zeitmanagement\n- **Überziehen der Zeit:** Zu viel Zeit für bestimmte Abschnitte der Präsentation verwenden.\n- **Unvorhergesehene Unterbrechungen:** Fragen oder Diskussionen, die mehr Zeit in Anspruch nehmen als geplant.\n\n#### Strategien für effektives Zeitmanagement\n- **Zeitplan erstellen:** Erstellen Sie einen detaillierten Zeitplan für jeden Abschnitt der Präsentation.\n- **Pufferzeit einplanen:** Planen Sie zusätzliche Zeit für Fragen und Diskussionen ein.\n- **Uhr im Blick behalten:** Verwenden Sie eine Uhr oder einen Timer, um die Zeit im Auge zu behalten.\n- **Flexibilität:** Seien Sie bereit, den Zeitplan anzupassen, wenn unvorhergesehene Ereignisse eintreten.\n\n### Fazit\n\nDer Umgang mit Herausforderungen bei Präsentationen vor Verwaltungsräten erfordert Vorbereitung, Flexibilität und die Fähigkeit, ruhig und professionell zu bleiben. Indem Sie sich auf potenzielle Probleme vorbereiten und Strategien zur Bewältigung entwickeln, können Sie Ihre Präsentation erfolgreich gestalten und Ihr Publikum überzeugen.\n\n## 6. Kapitel 6: Nachbereitung und Feedback\n\n### Einholen von Feedback\n\nNach einer Präsentation vor einem Verwaltungsrat ist das Einholen von Feedback ein entscheidender Schritt, um die Effektivität zukünftiger Präsentationen zu verbessern. Feedback bietet wertvolle Einblicke in die Wahrnehmung und Wirkung Ihrer Präsentation und hilft, Stärken zu erkennen sowie Schwächen zu adressieren.\n\n#### Methoden zur Feedback-Einholung\n\n1. **Direkte Rückmeldung**:\n - **Persönliche Gespräche**: Sprechen Sie direkt nach der Präsentation mit einzelnen Mitgliedern des Verwaltungsrats, um unmittelbare Eindrücke zu sammeln.\n - **Feedback-Runden**: Organisieren Sie eine kurze Feedback-Runde, in der die Teilnehmer ihre Gedanken und Anregungen äußern können.\n\n2. **Schriftliche Umfragen**:\n - **Online-Umfragen**: Nutzen Sie Tools wie Google Forms oder SurveyMonkey, um anonymes Feedback zu sammeln.\n - **Feedback-Bögen**: Verteilen Sie physische Fragebögen, die spezifische Fragen zur Präsentation enthalten.\n\n3. **Beobachtung und Notizen**:\n - **Körpersprache und Reaktionen**: Achten Sie während der Präsentation auf nonverbale Hinweise, die auf Zustimmung oder Verwirrung hinweisen könnten.\n - **Notizen während der Diskussion**: Halten Sie während der anschließenden Diskussion wichtige Punkte und Fragen fest.\n\n#### Analyse des Feedbacks\n\nSobald das Feedback gesammelt wurde, ist eine gründliche Analyse notwendig, um die gewonnenen Informationen effektiv zu nutzen.\n\n1. **Kategorisierung des Feedbacks**:\n - **Positives Feedback**: Identifizieren Sie, welche Aspekte der Präsentation gut angekommen sind und warum.\n - **Konstruktive Kritik**: Notieren Sie spezifische Kritikpunkte und analysieren Sie deren Ursachen.\n\n2. **Identifikation von Mustern**:\n - **Wiederkehrende Themen**: Achten Sie auf häufig erwähnte Punkte, die auf systematische Stärken oder Schwächen hinweisen.\n - **Unterschiedliche Perspektiven**: Berücksichtigen Sie die verschiedenen Blickwinkel der Verwaltungsratsmitglieder, um ein umfassendes Bild zu erhalten.\n\n3. **Priorisierung der Verbesserungsbereiche**:\n - **Dringlichkeit und Machbarkeit**: Bewerten Sie, welche Verbesserungen am dringendsten und am einfachsten umzusetzen sind.\n - **Langfristige Ziele**: Setzen Sie sich Ziele für langfristige Verbesserungen, die möglicherweise mehr Zeit und Ressourcen erfordern.\n\n### Umsetzung der Erkenntnisse\n\nDie Umsetzung der aus dem Feedback gewonnenen Erkenntnisse ist entscheidend für die kontinuierliche Verbesserung Ihrer Präsentationsfähigkeiten.\n\n#### Anpassung der Präsentationsstrategie\n\n1. **Inhaltliche Anpassungen**:\n - **Relevanz und Klarheit**: Stellen Sie sicher, dass alle Inhalte klar und relevant für das Publikum sind.\n - **Daten und Fakten**: Überprüfen Sie die Genauigkeit und Aktualität der präsentierten Informationen.\n\n2. **Visuelle Gestaltung**:\n - **Design-Elemente**: Optimieren Sie die visuelle Gestaltung Ihrer Folien, um die Verständlichkeit zu erhöhen.\n - **Multimediale Unterstützung**: Nutzen Sie Videos oder Grafiken, um komplexe Informationen anschaulich darzustellen.\n\n3. **Präsentationstechnik**:\n - **Rhetorische Fähigkeiten**: Arbeiten Sie an Ihrer Ausdrucksweise und Körpersprache, um überzeugender zu wirken.\n - **Interaktive Elemente**: Integrieren Sie interaktive Elemente, um das Publikum stärker einzubeziehen.\n\n#### Kontinuierliche Verbesserung\n\n1. **Feedback-Schleifen etablieren**:\n - **Regelmäßige Überprüfung**: Implementieren Sie regelmäßige Feedback-Schleifen, um kontinuierlich an Ihren Fähigkeiten zu arbeiten.\n - **Mentoring und Coaching**: Ziehen Sie in Betracht, sich von erfahrenen Kollegen oder einem Coach beraten zu lassen.\n\n2. **Lernen aus Erfahrungen**:\n - **Reflexion**: Nehmen Sie sich nach jeder Präsentation Zeit, um über Ihre Leistung nachzudenken und daraus zu lernen.\n - **Fortbildung**: Besuchen Sie Workshops oder Seminare, um neue Techniken und Ansätze zu erlernen.\n\n### Bewältigung von Herausforderungen\n\nBei der Nachbereitung und Feedback-Analyse können verschiedene Herausforderungen auftreten, die es zu bewältigen gilt.\n\n#### Mögliche Herausforderungen\n\n1. **Unklares Feedback**:\n - **Nachfragen**: Bitten Sie um Klarstellungen, wenn das Feedback vage oder unverständlich ist.\n - **Beispiele erfragen**: Fordern Sie konkrete Beispiele an, um das Feedback besser nachvollziehen zu können.\n\n2. **Negative Kritik**:\n - **Sachlich bleiben**: Nehmen Sie Kritik nicht persönlich, sondern betrachten Sie sie als Chance zur Verbesserung.\n - **Dankbarkeit zeigen**: Bedanken Sie sich für das Feedback, auch wenn es negativ ist, und zeigen Sie Offenheit für Veränderung.\n\n3. **Widersprüchliches Feedback**:\n - **Abwägen**: Bewerten Sie widersprüchliches Feedback im Kontext der Gesamtpräsentation und der Zielsetzung.\n - **Konsens suchen**: Versuchen Sie, einen Konsens zu finden oder priorisieren Sie das Feedback, das am meisten Gewicht hat.\n\nDurch eine systematische Nachbereitung und die gezielte Nutzung von Feedback können Sie Ihre Präsentationen kontinuierlich verbessern und Ihre Wirkung vor Verwaltungsräten nachhaltig steigern.\n\n---\n\n**Erstellt durch:** Dokumentation", + "agent_type": "documentation", + "agent_id": "documentation_agent", + "agent_name": "Dokumentation" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n### Zusammenfassung der Agentenergebnisse: Erfolgreiche Präsentationen vor Verwaltungsräten\n\n#### Einführung\nPräsentationen vor Verwaltungsräten erfordern strategische Planung und präzise Ausführung. Sie müssen zielgerichtet, strategisch relevant und datengetrieben sein, um fundierte Entscheidungen zu unterstützen. Eine klare, präzise Kommunikation ohne Fachjargon ist entscheidend, ebenso wie ein lösungsorientierter Ansatz.\n\n#### Best Practices für die Präsentationsgestaltung\n- **Strukturierung**: Eine klare Einleitung, ein logisch gegliederter Hauptteil und eine prägnante Schlussfolgerung sind essenziell.\n- **Visuelle Hilfsmittel**: Grafiken, Bilder und minimaler Text auf Folien erhöhen die Verständlichkeit und das Interesse.\n- **Konsistenz und Interaktivität**: Einheitliches Design und interaktive Elemente fördern das Engagement.\n\n#### Vorbereitung auf die Präsentation\n- **Zielgruppenanalyse**: Verstehen Sie die demografischen Merkmale und Interessen des Verwaltungsrats.\n- **Präsentationsziel**: Definieren Sie ein klares Ziel und Erfolgskriterien.\n- **Proben**: Simulationsproben und technisches Testen sind unerlässlich.\n\n#### Durchführung der Präsentation\n- **Körpersprache und Stimme**: Eine offene Haltung, angemessene Lautstärke und variierte Tonlage sind wichtig.\n- **Interaktion**: Fragen und Feedback fördern die Verbindung zum Publikum.\n- **Flexibilität**: Seien Sie bereit, auf unerwartete Fragen oder technische Probleme zu reagieren.\n\n#### Umgang mit Herausforderungen\n- **Lampenfieber**: Gründliche Vorbereitung und Atemtechniken helfen, Nervosität zu überwinden.\n- **Schwierige Fragen**: Aktives Zuhören und ruhige, sachliche Antworten sind entscheidend.\n- **Technische Probleme**: Vorab-Checks und Backup-Pläne minimieren Risiken.\n- **Zeitmanagement**: Ein detaillierter Zeitplan und Pufferzeiten sind wichtig.\n\n#### Nachbereitung und Feedback\n- **Feedback einholen**: Nutzen Sie direkte Rückmeldungen, schriftliche Umfragen und Beobachtungen.\n- **Analyse und Umsetzung**: Kategorisieren Sie Feedback, identifizieren Sie Muster und passen Sie Ihre Strategie an.\n- **Kontinuierliche Verbesserung**: Etablieren Sie Feedback-Schleifen und nutzen Sie Fortbildungsmöglichkeiten.\n\n### Empfehlungen\n1. **Gezielte Vorbereitung**: Verstehen Sie die Erwartungen des Verwaltungsrats und passen Sie Ihre Präsentation entsprechend an.\n2. **Effektive Gestaltung**: Nutzen Sie visuelle Hilfsmittel und interaktive Elemente, um die Aufmerksamkeit zu halten.\n3. **Proaktive Bewältigung von Herausforderungen**: Entwickeln Sie Strategien zur Bewältigung von Lampenfieber, schwierigen Fragen und technischen Problemen.\n4. **Feedback nutzen**: Implementieren Sie systematische Nachbereitung und kontinuierliche Verbesserung Ihrer Präsentationsfähigkeiten.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true, + "finished_at": "2025-04-06T12:33:57.222449", + "status": "completed" + }, + { + "id": "msg_13723403-6cee-4462-a17c-9ce1659d99a5", + "workflow_id": "d7c2bd78-7c8b-4908-8b8e-1cf83c49a3f5", + "parent_message_id": null, + "started_at": "2025-04-06T12:33:57.222449", + "finished_at": null, + "sequence_no": 4, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "kannst du mir eine checkliste als tabelle machen zur vorbereitung?", + "agent_type": null + }, + { + "id": "msg_cea797fc-cd0d-41d7-8a1c-e17d2b90d4d4", + "workflow_id": "d7c2bd78-7c8b-4908-8b8e-1cf83c49a3f5", + "parent_message_id": null, + "started_at": "2025-04-06T12:35:10.975805", + "finished_at": "2025-04-06T12:35:10.994226", + "sequence_no": 5, + "status": "completed", + "role": "assistant", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "# Checkliste zur Vorbereitung: Strukturierte Übersicht aller notwendigen Punkte\n\n## Zusammenfassung\n\nDas Dokument \"Checkliste zur Vorbereitung: Strukturierte Übersicht aller notwendigen Punkte\" dient als umfassende Anleitung zur Erstellung einer klar strukturierten Checkliste in Tabellenform. Ziel ist es, alle wesentlichen Aspekte der Vorbereitung systematisch zu erfassen und darzustellen. Die Checkliste soll sicherstellen, dass keine wichtigen Schritte übersehen werden und eine effiziente Organisation gewährleistet ist. Hauptinhalte umfassen die Identifikation und Auflistung aller relevanten Vorbereitungspunkte, die in einer übersichtlichen und leicht nachvollziehbaren Struktur präsentiert werden.\n\n## Inhaltsverzeichnis\n\n1. Kapitel 1: Einleitung und Zielsetzung\n2. Kapitel 2: Identifikation der Vorbereitungspunkte\n3. Kapitel 3: Strukturierung der Checkliste\n4. Kapitel 4: Detaillierte Beschreibung der Punkte\n5. Kapitel 5: Priorisierung und Zeitplanung\n6. Kapitel 6: Überprüfung und Anpassung\n7. Kapitel 7: Schlussfolgerung und Empfehlungen\n\n## 1. Kapitel 1: Einleitung und Zielsetzung\n\nEinleitung und Zielsetzung\n\nDie vorliegende Checkliste dient als strukturierte Übersicht, um sicherzustellen, dass alle notwendigen Schritte zur Vorbereitung eines Projekts, Events oder einer Aufgabe systematisch und effizient abgearbeitet werden. Der Zweck dieser Checkliste ist es, den Nutzern eine klare und umfassende Anleitung zu bieten, die ihnen hilft, alle relevanten Aspekte der Vorbereitung zu berücksichtigen und somit den Erfolg ihrer Unternehmung zu gewährleisten.\n\n**Ziele der Checkliste**\n\n1. **Vollständigkeit sicherstellen**: Die Checkliste soll gewährleisten, dass keine wesentlichen Punkte übersehen werden, die für die erfolgreiche Vorbereitung notwendig sind.\n \n2. **Effizienz steigern**: Durch die strukturierte Übersicht können Aufgaben schneller identifiziert und abgearbeitet werden, was den gesamten Vorbereitungsprozess effizienter gestaltet.\n\n3. **Klarheit schaffen**: Eine klare Struktur hilft, den Überblick über den Fortschritt zu behalten und Prioritäten besser zu setzen.\n\n4. **Risikominimierung**: Durch die systematische Abarbeitung der Checkliste werden potenzielle Risiken frühzeitig erkannt und können entsprechend adressiert werden.\n\n5. **Kommunikation verbessern**: Die Checkliste dient als gemeinsames Referenzdokument für alle Beteiligten, was die Kommunikation und Koordination innerhalb des Teams erleichtert.\n\n**Struktur der Checkliste**\n\nDie Checkliste ist in verschiedene Kategorien unterteilt, die jeweils spezifische Aspekte der Vorbereitung abdecken. Jede Kategorie enthält eine Liste von Aufgaben, die in einer Tabelle dargestellt werden. Diese Tabellen sind so gestaltet, dass sie leicht verständlich und einfach zu verwenden sind.\n\n**Beispielhafte Tabelle zur Checkliste**\n\n| Kategorie | Aufgabe | Verantwortlich | Fälligkeitsdatum | Status |\n|--------------------|------------------------------------------|----------------|------------------|----------|\n| Planung | Zielsetzung definieren | Projektleiter | 01.11.2023 | Offen |\n| Ressourcen | Budget festlegen | Finanzabteilung| 05.11.2023 | Offen |\n| Kommunikation | Team-Meeting organisieren | Teamleiter | 07.11.2023 | Offen |\n| Logistik | Veranstaltungsort buchen | Eventmanager | 10.11.2023 | Offen |\n| Risikoanalyse | SWOT-Analyse durchführen | Analyst | 12.11.2023 | Offen |\n\n**Anwendung der Checkliste**\n\n- **Regelmäßige Überprüfung**: Die Checkliste sollte regelmäßig überprüft und aktualisiert werden, um sicherzustellen, dass alle Punkte aktuell und relevant sind.\n- **Anpassungsfähigkeit**: Bei Änderungen im Projektumfang oder -ziel sollte die Checkliste entsprechend angepasst werden.\n- **Feedback einholen**: Nach Abschluss der Vorbereitung sollte Feedback von allen Beteiligten eingeholt werden, um die Checkliste für zukünftige Projekte zu optimieren.\n\nDurch die konsequente Anwendung dieser Checkliste wird sichergestellt, dass alle Aspekte der Vorbereitung gründlich und effizient behandelt werden, was letztendlich zum Erfolg des Projekts beiträgt.\n\n## 2. Kapitel 2: Identifikation der Vorbereitungspunkte\n\nUm relevante Vorbereitungspunkte effektiv zu identifizieren und auszuwählen, ist es entscheidend, einen systematischen Ansatz zu verfolgen. Dieser Ansatz sollte sowohl die spezifischen Anforderungen des Projekts oder Ereignisses als auch die allgemeinen Best Practices berücksichtigen. Im Folgenden wird ein detaillierter Prozess beschrieben, der Ihnen hilft, die notwendigen Vorbereitungspunkte zu bestimmen.\n\n### 1. Zielsetzung und Kontextanalyse\n\n**Zielsetzung:**\n- Definieren Sie klar das Ziel des Projekts oder Ereignisses.\n- Stellen Sie sicher, dass alle Beteiligten ein gemeinsames Verständnis der Ziele haben.\n\n**Kontextanalyse:**\n- Analysieren Sie den Kontext, in dem das Projekt oder Ereignis stattfindet.\n- Berücksichtigen Sie interne und externe Faktoren, die Einfluss auf die Vorbereitung haben könnten.\n\n### 2. Stakeholder-Identifikation\n\n- Erstellen Sie eine Liste aller relevanten Stakeholder.\n- Bestimmen Sie die Erwartungen und Anforderungen jedes Stakeholders.\n- Priorisieren Sie die Stakeholder basierend auf ihrem Einfluss und Interesse.\n\n### 3. Risikoanalyse\n\n- Identifizieren Sie potenzielle Risiken, die die Vorbereitung beeinträchtigen könnten.\n- Bewerten Sie die Wahrscheinlichkeit und den potenziellen Einfluss dieser Risiken.\n- Entwickeln Sie Strategien zur Risikominderung.\n\n### 4. Ressourcenbewertung\n\n- Ermitteln Sie die benötigten Ressourcen (z.B. Personal, Budget, Materialien).\n- Überprüfen Sie die Verfügbarkeit dieser Ressourcen.\n- Planen Sie die Zuweisung der Ressourcen effizient.\n\n### 5. Erstellung der Vorbereitungspunkte\n\nBasierend auf den oben genannten Analysen können nun spezifische Vorbereitungspunkte identifiziert werden. Diese Punkte sollten klar formuliert und in einer strukturierten Checkliste festgehalten werden. Die folgende Tabelle bietet ein Beispiel für eine solche Checkliste:\n\n| Vorbereitungspunkt | Beschreibung | Verantwortlich | Frist |\n|------------------------------|------------------------------------------------------------------------------|-----------------|----------------|\n| Zieldefinition | Klare Definition der Projektziele und Kommunikation an alle Beteiligten. | Projektleiter | 01.11.2023 |\n| Stakeholder-Analyse | Erstellung einer detaillierten Liste der Stakeholder und ihrer Anforderungen.| Teammitglied A | 05.11.2023 |\n| Risikoidentifikation | Identifizierung und Bewertung potenzieller Risiken. | Teammitglied B | 10.11.2023 |\n| Ressourcenplanung | Bestimmung und Zuweisung der notwendigen Ressourcen. | Teammitglied C | 15.11.2023 |\n| Kommunikationsplan | Entwicklung eines Kommunikationsplans für alle Stakeholder. | Projektleiter | 20.11.2023 |\n\n### 6. Überprüfung und Anpassung\n\n- Überprüfen Sie die erstellte Checkliste regelmäßig auf Vollständigkeit und Relevanz.\n- Passen Sie die Vorbereitungspunkte bei Bedarf an, um auf Änderungen im Projektumfeld zu reagieren.\n\nDurch die strukturierte Identifikation und Auswahl der Vorbereitungspunkte wird sichergestellt, dass alle notwendigen Aspekte berücksichtigt werden, um eine erfolgreiche Vorbereitung zu gewährleisten.\n\n## 3. Kapitel 3: Strukturierung der Checkliste\n\nKapitel 3: Strukturierung der Checkliste\n\nUm eine effektive und übersichtliche Checkliste zu erstellen, ist es entscheidend, eine klare und logische Struktur zu verwenden. Eine tabellarische Darstellung bietet sich an, da sie Informationen kompakt und leicht verständlich darstellt. Im Folgenden wird erläutert, wie eine solche Tabelle aufgebaut werden sollte, um die Übersichtlichkeit zu maximieren und sicherzustellen, dass alle notwendigen Punkte zur Vorbereitung abgedeckt sind.\n\n### 1. Grundlegende Struktur der Tabelle\n\nDie Tabelle sollte in mehrere Spalten unterteilt werden, um verschiedene Aspekte der Vorbereitung abzudecken. Eine empfohlene Struktur könnte wie folgt aussehen:\n\n| Punktnummer | Aufgabe/Beschreibung | Verantwortlicher | Fälligkeitsdatum | Status | Anmerkungen |\n|-------------|-----------------------|------------------|------------------|--------|-------------|\n\n#### 1.1. Punktnummer\n- **Zweck:** Dient der einfachen Referenzierung und Nachverfolgung der Aufgaben.\n- **Format:** Fortlaufende Nummerierung (z.B. 1, 2, 3,...).\n\n#### 1.2. Aufgabe/Beschreibung\n- **Zweck:** Klare und prägnante Beschreibung der auszuführenden Aufgabe.\n- **Format:** Kurze, aber aussagekräftige Sätze, die den Kern der Aufgabe erfassen.\n\n#### 1.3. Verantwortlicher\n- **Zweck:** Identifiziert die Person oder das Team, das für die Erledigung der Aufgabe verantwortlich ist.\n- **Format:** Vollständiger Name oder Teambezeichnung.\n\n#### 1.4. Fälligkeitsdatum\n- **Zweck:** Gibt das Datum an, bis zu dem die Aufgabe abgeschlossen sein sollte.\n- **Format:** TT.MM.JJJJ (z.B. 15.11.2023).\n\n#### 1.5. Status\n- **Zweck:** Zeigt den aktuellen Fortschritt der Aufgabe an.\n- **Format:** Standardisierte Begriffe wie \"Nicht begonnen\", \"In Bearbeitung\", \"Abgeschlossen\".\n\n#### 1.6. Anmerkungen\n- **Zweck:** Bietet Raum für zusätzliche Informationen oder spezifische Hinweise zur Aufgabe.\n- **Format:** Freitextfeld für relevante Details.\n\n### 2. Tipps zur effektiven Nutzung der Tabelle\n\n- **Priorisierung:** Verwenden Sie eine zusätzliche Spalte oder eine farbliche Markierung, um besonders dringende oder wichtige Aufgaben hervorzuheben.\n- **Regelmäßige Aktualisierung:** Stellen Sie sicher, dass die Tabelle regelmäßig aktualisiert wird, um den aktuellen Stand der Vorbereitungen widerzuspiegeln.\n- **Zugänglichkeit:** Halten Sie die Tabelle für alle relevanten Beteiligten zugänglich, z.B. durch eine zentrale Ablage in einem gemeinsamen digitalen Arbeitsbereich.\n\n### 3. Beispiel einer strukturierten Checkliste\n\n| Punktnummer | Aufgabe/Beschreibung | Verantwortlicher | Fälligkeitsdatum | Status | Anmerkungen |\n|-------------|---------------------------------------|------------------|------------------|----------------|----------------------------|\n| 1 | Raumreservierung bestätigen | Max Mustermann | 01.11.2023 | Abgeschlossen | Raum 101, Gebäude A |\n| 2 | Catering-Service buchen | Anna Müller | 05.11.2023 | In Bearbeitung | Vegetarische Optionen prüfen |\n| 3 | Technische Ausrüstung bereitstellen | IT-Abteilung | 10.11.2023 | Nicht begonnen | Beamer und Mikrofone |\n\nDiese strukturierte Herangehensweise stellt sicher, dass alle Aspekte der Vorbereitung klar und nachvollziehbar dokumentiert sind, was die Effizienz und Effektivität der Vorbereitungsprozesse erheblich steigert.\n\n## 4. Kapitel 4: Detaillierte Beschreibung der Punkte\n\n### Einleitung\n\nIn diesem Kapitel wird erläutert, wie jeder Punkt der Checkliste zur Vorbereitung detailliert beschrieben werden sollte. Ziel ist es, sicherzustellen, dass alle Beteiligten die Anforderungen und Schritte klar verstehen und effektiv umsetzen können. Eine strukturierte Herangehensweise hilft, Missverständnisse zu vermeiden und die Effizienz zu steigern.\n\n### Struktur der detaillierten Beschreibung\n\nJeder Vorbereitungspunkt sollte in einer standardisierten Form beschrieben werden, um Konsistenz und Klarheit zu gewährleisten. Die folgende Struktur wird empfohlen:\n\n1. **Punktbezeichnung**\n - **Beschreibung**: Eine kurze, prägnante Erklärung des Punktes.\n - **Ziel**: Das spezifische Ziel oder der Zweck dieses Punktes.\n - **Verantwortlichkeiten**: Wer ist für die Durchführung verantwortlich?\n - **Ressourcen**: Welche Ressourcen werden benötigt (z.B. Materialien, Werkzeuge, Informationen)?\n - **Schritte zur Umsetzung**: Eine detaillierte Schritt-für-Schritt-Anleitung zur Durchführung.\n - **Zeitplan**: Wann sollte dieser Punkt abgeschlossen sein?\n - **Erfolgskriterien**: Wie wird der Erfolg dieses Punktes gemessen?\n\n### Beispielhafte Beschreibung eines Vorbereitungspunktes\n\n#### Punkt 1: Veranstaltungsort buchen\n\n- **Beschreibung**: Reservierung eines geeigneten Veranstaltungsortes für das Event.\n- **Ziel**: Sicherstellung, dass der Veranstaltungsort alle Anforderungen erfüllt und rechtzeitig verfügbar ist.\n- **Verantwortlichkeiten**: Eventkoordinator\n- **Ressourcen**:\n - Liste potenzieller Veranstaltungsorte\n - Budgetvorgaben\n - Checkliste der Anforderungen (Kapazität, Ausstattung, Lage)\n- **Schritte zur Umsetzung**:\n 1. Recherche und Erstellung einer Liste potenzieller Veranstaltungsorte.\n 2. Kontaktaufnahme mit den Veranstaltungsorten zur Verfügbarkeit und Preisabfrage.\n 3. Vergleich der Optionen basierend auf Kosten, Verfügbarkeit und Anforderungen.\n 4. Auswahl des Veranstaltungsortes und Vertragsverhandlungen.\n 5. Bestätigung der Buchung und Dokumentation der Vereinbarung.\n- **Zeitplan**: Abschluss der Buchung mindestens drei Monate vor dem Event.\n- **Erfolgskriterien**:\n - Der Veranstaltungsort ist gebucht und bestätigt.\n - Der Veranstaltungsort erfüllt alle festgelegten Anforderungen.\n - Der Vertrag ist unterzeichnet und archiviert.\n\n### Weitere Punkte der Checkliste\n\n#### Punkt 2: Technische Ausstattung sicherstellen\n\n- **Beschreibung**: Bereitstellung aller notwendigen technischen Geräte und Systeme.\n- **Ziel**: Gewährleistung, dass alle technischen Anforderungen für das Event erfüllt sind.\n- **Verantwortlichkeiten**: Technischer Leiter\n- **Ressourcen**:\n - Liste der benötigten technischen Geräte\n - Kontaktinformationen von Technikdienstleistern\n- **Schritte zur Umsetzung**:\n 1. Erstellung einer Liste der benötigten technischen Geräte.\n 2. Kontaktaufnahme mit Dienstleistern zur Verfügbarkeit und Preisabfrage.\n 3. Auswahl und Buchung der benötigten Technik.\n 4. Durchführung eines Probelaufs zur Sicherstellung der Funktionalität.\n- **Zeitplan**: Technik sollte eine Woche vor dem Event bereitstehen.\n- **Erfolgskriterien**:\n - Alle technischen Geräte sind funktionsfähig und einsatzbereit.\n - Probelauf wurde erfolgreich durchgeführt.\n\n### Fazit\n\nDie detaillierte Beschreibung jedes Vorbereitungspunktes ist entscheidend für den Erfolg des gesamten Projekts. Durch die klare Definition von Zielen, Verantwortlichkeiten und Erfolgskriterien wird sichergestellt, dass alle Beteiligten auf dem gleichen Stand sind und effizient zusammenarbeiten können.\n\n## 5. Kapitel 5: Priorisierung und Zeitplanung\n\n### Priorisierung und Zeitplanung\n\nIn diesem Kapitel wird erläutert, wie Sie die in Ihrer Checkliste aufgeführten Punkte nach Wichtigkeit priorisieren und in einen effektiven Zeitplan integrieren können. Eine strukturierte Priorisierung und Zeitplanung ist entscheidend, um sicherzustellen, dass alle Aufgaben rechtzeitig und effizient erledigt werden. \n\n#### 1. Priorisierung der Aufgaben\n\nDie Priorisierung von Aufgaben hilft Ihnen, sich auf die wichtigsten Punkte zu konzentrieren und Ressourcen effizient zu nutzen. Hier sind einige Schritte, die Sie bei der Priorisierung beachten sollten:\n\n- **Dringlichkeit und Wichtigkeit bewerten:**\n - Verwenden Sie die Eisenhower-Matrix, um Aufgaben in vier Kategorien zu unterteilen:\n - **Wichtig und dringend:** Sofort erledigen.\n - **Wichtig, aber nicht dringend:** Planen Sie diese Aufgaben für später ein.\n - **Dringend, aber nicht wichtig:** Delegieren Sie diese Aufgaben, wenn möglich.\n - **Weder wichtig noch dringend:** Überlegen Sie, ob diese Aufgaben überhaupt notwendig sind.\n\n- **Ressourcenverfügbarkeit prüfen:**\n - Stellen Sie sicher, dass Sie über die notwendigen Ressourcen (Zeit, Personal, Materialien) verfügen, um die Aufgaben zu erledigen.\n\n- **Abhängigkeiten identifizieren:**\n - Bestimmen Sie, welche Aufgaben voneinander abhängig sind und priorisieren Sie entsprechend.\n\n#### 2. Erstellung eines Zeitplans\n\nEin gut strukturierter Zeitplan hilft Ihnen, den Überblick über Ihre Aufgaben zu behalten und Fristen einzuhalten. Hier sind einige Schritte zur Erstellung eines effektiven Zeitplans:\n\n- **Zeitliche Schätzung:**\n - Schätzen Sie den Zeitaufwand für jede Aufgabe realistisch ein. Berücksichtigen Sie dabei mögliche Verzögerungen und Pufferzeiten.\n\n- **Meilensteine festlegen:**\n - Definieren Sie klare Meilensteine, um den Fortschritt zu überwachen und sicherzustellen, dass Sie auf dem richtigen Weg sind.\n\n- **Zeitplan erstellen:**\n - Nutzen Sie ein Kalendertool oder eine Projektmanagement-Software, um Ihren Zeitplan zu visualisieren. Dies erleichtert die Anpassung und Überwachung.\n\n- **Regelmäßige Überprüfung:**\n - Überprüfen Sie regelmäßig Ihren Zeitplan und passen Sie ihn bei Bedarf an, um auf unvorhergesehene Änderungen reagieren zu können.\n\n#### 3. Checkliste zur Priorisierung und Zeitplanung\n\nDie folgende Tabelle bietet eine strukturierte Übersicht über die notwendigen Schritte zur Priorisierung und Zeitplanung:\n\n| Schritt | Beschreibung | Tools/Methoden |\n|---------|--------------|----------------|\n| 1. Dringlichkeit und Wichtigkeit bewerten | Aufgaben nach Wichtigkeit und Dringlichkeit kategorisieren | Eisenhower-Matrix |\n| 2. Ressourcenverfügbarkeit prüfen | Verfügbarkeit von Zeit, Personal und Materialien sicherstellen | Ressourcenplan |\n| 3. Abhängigkeiten identifizieren | Abhängigkeiten zwischen Aufgaben erkennen | Gantt-Diagramm |\n| 4. Zeitliche Schätzung | Realistische Zeitschätzungen für Aufgaben vornehmen | Zeitschätzungs-Tools |\n| 5. Meilensteine festlegen | Wichtige Meilensteine zur Fortschrittsüberwachung definieren | Projektplan |\n| 6. Zeitplan erstellen | Aufgaben in einen Zeitplan integrieren | Kalendertool, Projektmanagement-Software |\n| 7. Regelmäßige Überprüfung | Zeitplan regelmäßig überprüfen und anpassen | Regelmäßige Meetings, Fortschrittsberichte |\n\nDiese strukturierte Vorgehensweise zur Priorisierung und Zeitplanung wird Ihnen helfen, Ihre Aufgaben effizient zu organisieren und sicherzustellen, dass alle wichtigen Punkte rechtzeitig bearbeitet werden.\n\n## 6. Kapitel 6: Überprüfung und Anpassung\n\nUm sicherzustellen, dass die Checkliste zur Vorbereitung stets aktuell und relevant bleibt, ist es entscheidend, regelmäßige Überprüfungen und Anpassungen vorzunehmen. Dieser Prozess gewährleistet, dass alle notwendigen Punkte abgedeckt sind und die Checkliste den sich ändernden Anforderungen und Bedingungen entspricht. Im Folgenden wird ein strukturierter Ansatz zur Überprüfung und Anpassung der Checkliste dargestellt.\n\n### Regelmäßige Überprüfung\n\n1. **Zeitplan für Überprüfungen festlegen**\n - **Monatliche Überprüfung:** Für Projekte mit kurzen Zeitrahmen oder häufigen Änderungen.\n - **Vierteljährliche Überprüfung:** Für langfristige Projekte oder stabile Umgebungen.\n - **Jährliche Überprüfung:** Für Checklisten, die selten Änderungen unterliegen.\n\n2. **Verantwortlichkeiten zuweisen**\n - Bestimmen Sie eine Person oder ein Team, das für die Überprüfung der Checkliste verantwortlich ist.\n - Stellen Sie sicher, dass diese Personen über die notwendigen Kenntnisse und Erfahrungen verfügen.\n\n3. **Feedback sammeln**\n - Holen Sie regelmäßig Rückmeldungen von den Nutzern der Checkliste ein.\n - Nutzen Sie Umfragen oder Feedback-Formulare, um systematisch Informationen zu sammeln.\n\n### Anpassung der Checkliste\n\n1. **Analyse der gesammelten Daten**\n - Überprüfen Sie das Feedback und identifizieren Sie häufige Probleme oder Verbesserungsvorschläge.\n - Analysieren Sie die Effektivität der aktuellen Checkliste anhand von Projektergebnissen.\n\n2. **Aktualisierung der Inhalte**\n - Fügen Sie neue Punkte hinzu, die aufgrund von Änderungen in Prozessen oder Technologien relevant geworden sind.\n - Entfernen Sie veraltete oder irrelevante Punkte, um die Übersichtlichkeit zu bewahren.\n\n3. **Validierung der Änderungen**\n - Lassen Sie die aktualisierte Checkliste von einem Experten oder einem erfahrenen Teammitglied überprüfen.\n - Testen Sie die neue Version der Checkliste in einem Pilotprojekt, um ihre Wirksamkeit zu bestätigen.\n\n4. **Kommunikation der Änderungen**\n - Informieren Sie alle relevanten Stakeholder über die vorgenommenen Änderungen.\n - Stellen Sie sicher, dass die aktualisierte Checkliste leicht zugänglich ist und alle Nutzer darüber informiert sind, wie sie darauf zugreifen können.\n\n### Dokumentation der Überprüfungen\n\n- **Protokollierung der Überprüfungen:** Führen Sie ein Protokoll über alle durchgeführten Überprüfungen und Anpassungen. Dies sollte das Datum, die durchgeführten Änderungen und die Gründe für diese Änderungen umfassen.\n- **Archivierung älterer Versionen:** Bewahren Sie ältere Versionen der Checkliste auf, um bei Bedarf auf frühere Versionen zurückgreifen zu können.\n\n### Tabelle zur Überprüfung und Anpassung\n\n| Überprüfungspunkt | Beschreibung | Verantwortlich | Häufigkeit | Letzte Überprüfung |\n|----------------------------|------------------------------------------------------------------------------|----------------------|---------------------|---------------------|\n| Zeitplan festlegen | Bestimmen Sie die Häufigkeit der Überprüfungen. | Projektmanager | Jährlich | [Datum einfügen] |\n| Feedback sammeln | Holen Sie Rückmeldungen von Nutzern ein. | Teamleiter | Quartalsweise | [Datum einfügen] |\n| Analyse der Daten | Überprüfen Sie das Feedback und die Effektivität der Checkliste. | Analyst | Quartalsweise | [Datum einfügen] |\n| Aktualisierung der Inhalte | Fügen Sie neue Punkte hinzu und entfernen Sie irrelevante Punkte. | Checklisten-Manager | Bei Bedarf | [Datum einfügen] |\n| Validierung der Änderungen | Lassen Sie die Änderungen von einem Experten überprüfen. | Qualitätsmanager | Nach jeder Änderung | [Datum einfügen] |\n| Kommunikation der Änderungen | Informieren Sie alle Stakeholder über die Änderungen. | Kommunikationsleiter | Nach jeder Änderung | [Datum einfügen] |\n\nDurch die Implementierung dieser strukturierten Überprüfungs- und Anpassungsprozesse wird sichergestellt, dass die Checkliste zur Vorbereitung stets den aktuellen Anforderungen entspricht und effektiv zur Zielerreichung beiträgt.\n\n## 7. Kapitel 7: Schlussfolgerung und Empfehlungen\n\n### Zusammenfassung der wichtigsten Erkenntnisse\n\nIn diesem Kapitel werden die zentralen Erkenntnisse aus der Nutzung der Checkliste zur Vorbereitung zusammengefasst. Diese Checkliste dient als umfassendes Werkzeug, um sicherzustellen, dass alle notwendigen Schritte zur Vorbereitung systematisch und effizient abgearbeitet werden. Die wichtigsten Erkenntnisse sind:\n\n- **Strukturierte Herangehensweise:** Die Checkliste bietet eine klare Struktur, die es ermöglicht, alle erforderlichen Aufgaben in einer logischen Reihenfolge zu bearbeiten. Dies minimiert das Risiko, wichtige Schritte zu übersehen.\n- **Zeitmanagement:** Durch die klare Auflistung der Aufgaben kann die Zeit effizienter eingeteilt werden, was zu einer besseren Planung und Durchführung der Vorbereitungen führt.\n- **Risikominimierung:** Die Checkliste hilft dabei, potenzielle Probleme frühzeitig zu identifizieren und zu adressieren, was das Risiko von Fehlern oder Verzögerungen verringert.\n- **Verbesserte Kommunikation:** Die Checkliste kann als Kommunikationswerkzeug zwischen verschiedenen Teammitgliedern dienen, um sicherzustellen, dass alle Beteiligten auf dem gleichen Stand sind.\n\n### Empfehlungen für die effektive Nutzung der Checkliste\n\nUm die Checkliste zur Vorbereitung optimal zu nutzen, sollten folgende Empfehlungen beachtet werden:\n\n1. **Regelmäßige Aktualisierung:**\n - Überprüfen und aktualisieren Sie die Checkliste regelmäßig, um sicherzustellen, dass sie den aktuellen Anforderungen und Gegebenheiten entspricht.\n - Integrieren Sie Feedback von Nutzern, um die Checkliste kontinuierlich zu verbessern.\n\n2. **Anpassung an spezifische Bedürfnisse:**\n - Passen Sie die Checkliste an die spezifischen Anforderungen Ihres Projekts oder Ihrer Organisation an.\n - Berücksichtigen Sie dabei die individuellen Gegebenheiten und Prioritäten.\n\n3. **Schulung und Einweisung:**\n - Schulen Sie alle relevanten Teammitglieder im effektiven Einsatz der Checkliste.\n - Stellen Sie sicher, dass alle Beteiligten die Bedeutung und den Nutzen der Checkliste verstehen.\n\n4. **Integration in bestehende Prozesse:**\n - Integrieren Sie die Checkliste in bestehende Arbeitsabläufe und Prozesse, um eine nahtlose Implementierung zu gewährleisten.\n - Nutzen Sie digitale Tools, um die Checkliste zugänglich und leicht bearbeitbar zu machen.\n\n5. **Regelmäßige Überprüfung der Ergebnisse:**\n - Führen Sie regelmäßige Überprüfungen durch, um die Effektivität der Checkliste zu bewerten.\n - Analysieren Sie die Ergebnisse, um Verbesserungsmöglichkeiten zu identifizieren.\n\n### Tabelle: Checkliste zur Vorbereitung\n\n| Punkt Nr. | Aufgabe | Beschreibung | Verantwortlich | Fälligkeitsdatum |\n|-----------|----------------------------------|------------------------------------------------------------------------------|----------------|------------------|\n| 1 | Zieldefinition | Klare Definition der Ziele und Erwartungen für das Projekt oder die Aufgabe. | Projektleiter | [Datum] |\n| 2 | Ressourcenplanung | Identifizierung und Zuweisung der notwendigen Ressourcen. | Teamleiter | [Datum] |\n| 3 | Zeitplanerstellung | Erstellung eines detaillierten Zeitplans mit Meilensteinen. | Projektmanager | [Datum] |\n| 4 | Risikobewertung | Identifikation potenzieller Risiken und Entwicklung von Gegenmaßnahmen. | Risikomanager | [Datum] |\n| 5 | Kommunikationsplan | Entwicklung eines Kommunikationsplans für alle Stakeholder. | Kommunikationsleiter | [Datum] |\n| 6 | Überprüfung und Freigabe | Letzte Überprüfung aller Vorbereitungen und Freigabe durch die Verantwortlichen. | Projektleiter | [Datum] |\n\nDiese Tabelle stellt eine strukturierte Übersicht aller notwendigen Punkte zur Vorbereitung dar. Sie dient als Leitfaden, um sicherzustellen, dass alle Aspekte der Vorbereitung abgedeckt sind und nichts übersehen wird.\n\n---\n\n**Erstellt durch:** Dokumentation", + "agent_type": "documentation", + "agent_id": "documentation_agent", + "agent_name": "Dokumentation" + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n**Zusammenfassung der Agentenergebnisse: Checkliste zur Vorbereitung**\n\n**Zielsetzung und Struktur:**\nDas Dokument bietet eine umfassende Anleitung zur Erstellung einer strukturierten Checkliste, um alle wesentlichen Aspekte der Vorbereitung systematisch zu erfassen. Ziel ist es, Vollständigkeit, Effizienz, Klarheit, Risikominimierung und verbesserte Kommunikation sicherzustellen.\n\n**Inhaltsübersicht:**\n1. **Einleitung und Zielsetzung:** Die Checkliste dient als strukturierte Übersicht zur systematischen und effizienten Abarbeitung aller notwendigen Schritte für Projekte, Events oder Aufgaben.\n2. **Identifikation der Vorbereitungspunkte:** Systematischer Ansatz zur Bestimmung relevanter Punkte durch Zielsetzung, Kontextanalyse, Stakeholder-Identifikation, Risikoanalyse und Ressourcenbewertung.\n3. **Strukturierung der Checkliste:** Verwendung einer tabellarischen Darstellung zur übersichtlichen Dokumentation von Aufgaben, Verantwortlichkeiten, Fristen und Status.\n4. **Detaillierte Beschreibung der Punkte:** Standardisierte Beschreibung jedes Punktes mit Ziel, Verantwortlichkeiten, Ressourcen, Umsetzungsschritten, Zeitplan und Erfolgskriterien.\n5. **Priorisierung und Zeitplanung:** Nutzung der Eisenhower-Matrix zur Priorisierung und Erstellung eines effektiven Zeitplans mit Meilensteinen und regelmäßiger Überprüfung.\n6. **Überprüfung und Anpassung:** Regelmäßige Überprüfung und Anpassung der Checkliste basierend auf Feedback und aktuellen Anforderungen.\n7. **Schlussfolgerung und Empfehlungen:** Betonung der strukturierten Herangehensweise, Zeitmanagement, Risikominimierung und verbesserten Kommunikation. Empfehlungen umfassen regelmäßige Aktualisierung, Anpassung an spezifische Bedürfnisse, Schulung, Integration in bestehende Prozesse und regelmäßige Ergebnisüberprüfung.\n\n**Empfehlungen:**\n- **Regelmäßige Aktualisierung:** Anpassung der Checkliste an aktuelle Anforderungen.\n- **Anpassung an spezifische Bedürfnisse:** Berücksichtigung individueller Projektanforderungen.\n- **Schulung und Einweisung:** Sicherstellung, dass alle Teammitglieder die Checkliste effektiv nutzen können.\n- **Integration in bestehende Prozesse:** Nutzung digitaler Tools für Zugänglichkeit und Bearbeitbarkeit.\n- **Regelmäßige Überprüfung der Ergebnisse:** Bewertung der Checkliste zur Identifizierung von Verbesserungsmöglichkeiten.\n\n**Beispielhafte Checkliste:**\nEine tabellarische Übersicht zeigt Aufgaben wie Zieldefinition, Ressourcenplanung, Zeitplanerstellung, Risikobewertung, Kommunikationsplan und Überprüfung, jeweils mit Verantwortlichkeiten und Fälligkeitsdaten.\n\nDiese strukturierte Herangehensweise gewährleistet, dass alle Aspekte der Vorbereitung gründlich und effizient behandelt werden, was letztendlich zum Erfolg des Projekts beiträgt.\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_13cec12b-900d-4d42-933e-837db2ebcd25", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 122, 0 Dateien", + "type": "info", + "timestamp": "2025-04-06T12:31:34.487515", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_bd1919e4-9654-4528-b6c4-a7f590fa156c", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-06T12:31:34.502855", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ae4a3db0-5315-46f8-84c2-0a8e6ec83aee", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-06T12:31:36.747334", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_49afc4a5-6ee5-4490-b512-165e654a0dc7", + "message": "Agent documentation_agent wurde ausgewählt mit Aufgabe: Erstelle einen detaillierten Bericht darüber, wie ...", + "type": "info", + "timestamp": "2025-04-06T12:31:36.755302", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_68ce8e31-a6e8-4023-9334-bc75168ef169", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:31:36.764306", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b451adcf-448c-4448-8d7d-61ef9c24c106", + "message": "Agent documentation_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:31:36.771893", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ae4bbaca-66c4-4e24-8d51-855328fcc1aa", + "message": "Agent 'documentation_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:31:36.779891", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_e6f2eeca-12ed-4cb9-a662-ab4b4b8a8e31", + "message": "Agent 'documentation_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-06T12:32:48.554104", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_945984da-2b07-4d11-8895-4fd85c30c295", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-06T12:32:55.502499", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_cd53b05e-5bcb-4a0b-ac57-dd25b45c33b7", + "message": "Benutzereingabe empfangen: 66 Zeichen, 0 Dateien", + "type": "info", + "timestamp": "2025-04-06T12:33:57.206970", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_f817ea7a-c0ea-452c-acf0-425d5a1a3c27", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-06T12:33:57.215039", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b8618805-d85a-49e3-a3b2-4a1d6dbf50d9", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-06T12:33:59.993269", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_fec12d39-05be-4663-aeed-aaf2d1dc29ab", + "message": "Agent documentation_agent wurde ausgewählt mit Aufgabe: Erstelle eine Checkliste als Tabelle zur Vorbereit...", + "type": "info", + "timestamp": "2025-04-06T12:33:59.993269", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_9371a7e3-2e47-485f-8cb5-ec005a50e53f", + "message": "1 System-Agenten werden ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:34:00.019485", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_f4a28cff-edf2-426a-8580-93aa2cc8ff9b", + "message": "Agent documentation_agent wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:34:00.019485", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_c4181af8-cd78-46d9-bde3-bf50dda8c0be", + "message": "Agent 'documentation_agent' wird ausgeführt", + "type": "info", + "timestamp": "2025-04-06T12:34:00.032965", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_7fac450f-eaad-420f-8c3c-e2a22d80ee4e", + "message": "Agent 'documentation_agent' hat geantwortet", + "type": "info", + "timestamp": "2025-04-06T12:35:11.171793", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_a2f2418e-4468-41ba-9941-6d6cef9575ba", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben ihre Aufgaben abgeschlossen. Hie...", + "type": "info", + "timestamp": "2025-04-06T12:35:18.227927", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_d853b5b0-bb4a-4cbd-a237-16d692aaec21.json b/gwserver/_results/workflow_d853b5b0-bb4a-4cbd-a237-16d692aaec21.json new file mode 100644 index 00000000..0016b8ff --- /dev/null +++ b/gwserver/_results/workflow_d853b5b0-bb4a-4cbd-a237-16d692aaec21.json @@ -0,0 +1,45 @@ +{ + "id": "d853b5b0-bb4a-4cbd-a237-16d692aaec21", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 10:43:48", + "status": "failed", + "started_at": "2025-04-04T10:43:49.135644", + "last_activity": "2025-04-04T10:43:49.156669", + "prompt": "beschreibe das bild", + "messages": [], + "logs": [ + { + "id": "log_43f9273a-5cbe-48b7-9fec-50dd68d314e0", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 19, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T10:43:49.139362", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_478f46e0-5443-48b4-bd75-6078d47d4a01", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T10:43:49.142520", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_eb8f07bb-25b0-4213-9149-03bcd2a3ca55", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T10:43:49.144684", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_4531ad57-6894-45c2-a431-9431bbac2c07", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T10:43:49.156669", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_df4fcfa4-1ddf-4abf-a7cd-2d9d8cc21c44.json b/gwserver/_results/workflow_df4fcfa4-1ddf-4abf-a7cd-2d9d8cc21c44.json new file mode 100644 index 00000000..7eb71289 --- /dev/null +++ b/gwserver/_results/workflow_df4fcfa4-1ddf-4abf-a7cd-2d9d8cc21c44.json @@ -0,0 +1,74 @@ +{ + "id": "df4fcfa4-1ddf-4abf-a7cd-2d9d8cc21c44", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 08:48:35", + "status": "waiting_for_user", + "started_at": "2025-04-04T08:48:36.258254", + "last_activity": "2025-04-04T08:48:38.345464", + "prompt": "beschreibe das bild", + "messages": [ + { + "id": "msg_efa3a758-d057-49eb-bf22-6821f4d8b558", + "workflow_id": "df4fcfa4-1ddf-4abf-a7cd-2d9d8cc21c44", + "parent_message_id": null, + "started_at": "2025-04-04T08:48:36.268796", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "beschreibe das bild", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben keine spezifischen Aufgaben durchgeführt. Gibt es etwas, wobei ich Ihnen helfen kann?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_13b82c90-1861-44d2-8d87-970286c6876c", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 19, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T08:48:36.260280", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_93d37a77-96cc-4026-8683-dc8fb96ae42c", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T08:48:36.264259", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_737b6fe7-8d8e-46b0-a83b-992b75a077e5", + "message": "Agenten-Entscheidung abgeschlossen: 0 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T08:48:38.339928", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_2dfdc235-25f7-4404-8545-480946f03d07", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben keine spezifischen Aufgaben durc...", + "type": "info", + "timestamp": "2025-04-04T08:48:38.345464", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_e4e995d7-2243-495e-b7f4-b52d1f98fcae.json b/gwserver/_results/workflow_e4e995d7-2243-495e-b7f4-b52d1f98fcae.json new file mode 100644 index 00000000..0c9698e6 --- /dev/null +++ b/gwserver/_results/workflow_e4e995d7-2243-495e-b7f4-b52d1f98fcae.json @@ -0,0 +1,45 @@ +{ + "id": "e4e995d7-2243-495e-b7f4-b52d1f98fcae", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 12:00:41", + "status": "failed", + "started_at": "2025-04-04T12:00:41.893373", + "last_activity": "2025-04-04T12:00:41.908371", + "prompt": "describe", + "messages": [], + "logs": [ + { + "id": "log_dcbdb4a0-7b27-4f18-a4aa-abb4d4ffc10f", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 8, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T12:00:41.896371", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_9ae77147-6f2b-4807-b269-193361489bac", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T12:00:41.898369", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_bbcc9588-7ef9-4fef-9878-18ab45eb7dd4", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T12:00:41.904370", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_89d401b8-9308-4e9b-b85d-9195383b6871", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T12:00:41.908371", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_e944d10b-39ea-44e2-beb5-7fad79916ee6.json b/gwserver/_results/workflow_e944d10b-39ea-44e2-beb5-7fad79916ee6.json new file mode 100644 index 00000000..005f0841 --- /dev/null +++ b/gwserver/_results/workflow_e944d10b-39ea-44e2-beb5-7fad79916ee6.json @@ -0,0 +1,45 @@ +{ + "id": "e944d10b-39ea-44e2-beb5-7fad79916ee6", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 10:54:26", + "status": "failed", + "started_at": "2025-04-04T10:54:27.155016", + "last_activity": "2025-04-04T10:54:27.177590", + "prompt": "describe image", + "messages": [], + "logs": [ + { + "id": "log_246be801-f3a1-415b-a944-ec96f3be0b28", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 14, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T10:54:27.158016", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_5c711d66-d5ce-4c17-b632-af1e9d96d2ca", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T10:54:27.160019", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_bd8c9005-f084-4b38-8282-e303f0c3c2ad", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T10:54:27.163530", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_0299a558-01da-410b-9a02-1f444345ad15", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T10:54:27.177590", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_f19ddc45-e789-47ad-a889-f0e10ec009e6.json b/gwserver/_results/workflow_f19ddc45-e789-47ad-a889-f0e10ec009e6.json new file mode 100644 index 00000000..29ec2e11 --- /dev/null +++ b/gwserver/_results/workflow_f19ddc45-e789-47ad-a889-f0e10ec009e6.json @@ -0,0 +1,124 @@ +{ + "id": "f19ddc45-e789-47ad-a889-f0e10ec009e6", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 23:55:08", + "status": "waiting_for_user", + "started_at": "2025-04-04T23:55:08.781208", + "last_activity": "2025-04-04T23:55:29.122218", + "prompt": "beschreibe dieses bild", + "messages": [ + { + "id": "msg_250dfbc0-a2e9-4cef-bccb-54bfc1109386", + "workflow_id": "f19ddc45-e789-47ad-a889-f0e10ec009e6", + "parent_message_id": null, + "started_at": "2025-04-04T23:55:08.801758", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [ + { + "id": 3, + "source": { + "type": "file", + "id": 3, + "name": "LF-Current.png", + "content_type": "image/png", + "size": 126277, + "upload_date": "2025-04-04T23:55:27.716376" + }, + "contents": [ + { + "type": "text", + "text": "Image Analysis:\nThe image is a flowchart depicting a product development process divided between a Product Team and an Engineering Team. Here's a detailed breakdown:\n\n### Input\n- **Sources**: Customers, Sales, Our ideas.\n- These inputs feed into the Product Team.\n\n### Product Team\n1. **Discover**\n - **Collect**: Ideas & Inputs.\n - **Qualify**: Analyze and match within the team.\n\n2. **Define**\n - **Structure & Document**: Write specifications, define acceptance criteria.\n - **Explore & Design**: UI Design, Experiments, etc.\n\n3. **Shape**\n - **Roadmap**: Define a roadmap.\n - **Scoping**: Define the next version's scope.\n - **Manage**: Tickets in Product.\n\n### Engineering Team\n1. **Build**\n - **Manage**: Track progress in the dashboard.\n - **Factory**: Develop tickets in Engineering for the next version.\n\n2. **Release**\n - **Manage**: Ensure stable changes.\n\n3. **Run & Monitor**\n - **Manage**: Ensure stable operation.\n - **Service & Support**: Deliver 1st level support according to agreed SLA.\n\n4. **Assess**\n - **Manage**: Move assessed tickets to Engineering for future versions.\n - **Estimate**: Assess tickets in \"Product > Analysis\" to define implementation, feasibility, and effort.\n\n### Output\n- **Product**: The final output of the process.\n\n### Tool Integration\n- **Ticketing System**: Includes categories like Inputs & Ideas, Exploration, Analysis, Future Versions, etc.\n- **Roadmap** and **Management Dashboards**: Mentioned as part of the tool integration.\n\nThe flowchart uses arrows to indicate the flow of processes and responsibilities between the Product and Engineering teams, emphasizing collaboration and iterative development." + } + ] + } + ], + "content": "beschreibe dieses bild", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Bitte beschreibe das Bild 'LF-Current.png', das einen Flussdiagramm des Produktentwicklungsprozesses zwischen einem Produktteam und einem Ingenieurteam darstellt. Achte darauf, die Details und die Struktur des Flussdiagramms zu erläutern.", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_f2620db8-763e-4609-84e2-2cc1cad4323c", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 22, 2 Dateien", + "type": "info", + "timestamp": "2025-04-04T23:55:08.791776", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_daf9820e-8030-46ce-827c-d57cdb676285", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T23:55:08.796758", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ad86adfa-4523-4316-9517-140a88db1e71", + "message": "2 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T23:55:08.807757", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_51b71efc-0313-45e4-9e27-d96fe1bdaadc", + "message": "Image LF-Current.png analyzed successfully", + "type": "info", + "timestamp": "2025-04-04T23:55:17.896584", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_9e73c385-8b44-4cdf-9c08-ab57d0505e3d", + "message": "Image LF-Current.png analyzed successfully", + "type": "info", + "timestamp": "2025-04-04T23:55:27.692734", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_69d11e62-ca97-4bd5-b60a-17c5f2b6aa73", + "message": "Agenten-Entscheidung abgeschlossen: 1 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T23:55:29.108265", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_155358cc-1df4-4eed-8f96-cfff4cf4d52d", + "message": "Agent user_agent wurde ausgewählt mit Aufgabe: Bitte beschreibe das Bild 'LF-Current.png', das ei...", + "type": "info", + "timestamp": "2025-04-04T23:55:29.112728", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_eb26e218-5507-484a-b553-ae952511619e", + "message": "Workflow wartet auf Benutzereingabe: Bitte beschreibe das Bild 'LF-Current.png', das ei...", + "type": "info", + "timestamp": "2025-04-04T23:55:29.122218", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_f3114b43-2601-4398-8f22-cdf2e83088b0.json b/gwserver/_results/workflow_f3114b43-2601-4398-8f22-cdf2e83088b0.json new file mode 100644 index 00000000..b89afba1 --- /dev/null +++ b/gwserver/_results/workflow_f3114b43-2601-4398-8f22-cdf2e83088b0.json @@ -0,0 +1,45 @@ +{ + "id": "f3114b43-2601-4398-8f22-cdf2e83088b0", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 12:14:21", + "status": "failed", + "started_at": "2025-04-04T12:14:22.098558", + "last_activity": "2025-04-04T12:14:22.115124", + "prompt": "describe", + "messages": [], + "logs": [ + { + "id": "log_6c188381-ce0f-4383-9787-166d29f7dc2e", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 8, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T12:14:22.102064", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_ea1118ba-0b1e-45cf-ae5a-a331f172f75c", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T12:14:22.105072", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_1eb71ac8-f9b8-4268-8150-362677da1a82", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T12:14:22.111073", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_d79c62cb-062d-4de8-8656-eb4f7c5c21a2", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T12:14:22.115124", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_fc58c41b-706c-4912-a342-7ad55aa1db4a.json b/gwserver/_results/workflow_fc58c41b-706c-4912-a342-7ad55aa1db4a.json new file mode 100644 index 00000000..adaf7208 --- /dev/null +++ b/gwserver/_results/workflow_fc58c41b-706c-4912-a342-7ad55aa1db4a.json @@ -0,0 +1,45 @@ +{ + "id": "fc58c41b-706c-4912-a342-7ad55aa1db4a", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 11:52:40", + "status": "failed", + "started_at": "2025-04-04T11:52:41.079026", + "last_activity": "2025-04-04T11:52:41.093434", + "prompt": "describe", + "messages": [], + "logs": [ + { + "id": "log_d73c68df-0354-40a8-bfff-63db9121ea15", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 8, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T11:52:41.082193", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_48fbafc5-c18f-429e-af83-1f9cdb3c25eb", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T11:52:41.083520", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_53a22960-e50e-457c-ae34-7264e3f22275", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T11:52:41.090436", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_6a7c7c65-ef4b-4b2d-b86a-9fcc9bf846f2", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T11:52:41.093434", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/_results/workflow_fec08098-c1c7-464a-866f-f9190b294d29.json b/gwserver/_results/workflow_fec08098-c1c7-464a-866f-f9190b294d29.json new file mode 100644 index 00000000..5c1a4f29 --- /dev/null +++ b/gwserver/_results/workflow_fec08098-c1c7-464a-866f-f9190b294d29.json @@ -0,0 +1,74 @@ +{ + "id": "fec08098-c1c7-464a-866f-f9190b294d29", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 00:46:05", + "status": "waiting_for_user", + "started_at": "2025-04-04T00:46:06.617567", + "last_activity": "2025-04-04T00:46:07.431241", + "prompt": "analysiere die datei im anhang", + "messages": [ + { + "id": "msg_a3d404f0-d563-4dc6-a373-e1ce75e42384", + "workflow_id": "fec08098-c1c7-464a-866f-f9190b294d29", + "parent_message_id": null, + "started_at": "2025-04-04T00:46:06.635910", + "finished_at": null, + "sequence_no": 1, + "status": "pending", + "role": "user", + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + "documents": [], + "content": "analysiere die datei im anhang", + "agent_type": null + }, + { + "role": "assistant", + "content": "[Moderator zu User Agent] Die Agenten haben keine spezifischen Aufgaben durchgeführt. Gibt es etwas, wobei ich Ihnen helfen kann?", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "waiting_for_user": true + } + ], + "logs": [ + { + "id": "log_d299f1a7-2a4e-4f8e-8036-0076f54f9801", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 30, 0 Dateien", + "type": "info", + "timestamp": "2025-04-04T00:46:06.627370", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_dc1c0f19-c30e-44a7-a8a1-db1ce1fb4f23", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T00:46:06.631923", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_1702dafb-3e38-4376-ba39-7c51f7c105f1", + "message": "Agenten-Entscheidung abgeschlossen: 0 Aufgaben zugewiesen", + "type": "info", + "timestamp": "2025-04-04T00:46:07.422639", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_a7f09481-77b5-41ae-bcaf-52f44b059c71", + "message": "Workflow wartet auf Benutzereingabe: Die Agenten haben keine spezifischen Aufgaben durc...", + "type": "info", + "timestamp": "2025-04-04T00:46:07.431241", + "agent_id": null, + "agent_name": null + } + ], + "waiting_for_user": true +} \ No newline at end of file diff --git a/gwserver/_results/workflow_ff6f56c9-6c59-44c1-95e1-f16c09c729b7.json b/gwserver/_results/workflow_ff6f56c9-6c59-44c1-95e1-f16c09c729b7.json new file mode 100644 index 00000000..12f374ac --- /dev/null +++ b/gwserver/_results/workflow_ff6f56c9-6c59-44c1-95e1-f16c09c729b7.json @@ -0,0 +1,45 @@ +{ + "id": "ff6f56c9-6c59-44c1-95e1-f16c09c729b7", + "mandate_id": 1, + "user_id": 1, + "name": "Workflow 4.4.2025, 10:56:30", + "status": "failed", + "started_at": "2025-04-04T10:56:30.982873", + "last_activity": "2025-04-04T10:56:30.995604", + "prompt": "analyse image", + "messages": [], + "logs": [ + { + "id": "log_b0eb9431-cace-4702-89fc-6b9c32dbee8d", + "message": "Starte Workflow-Ausführung, Nachrichtenlänge: 13, 1 Dateien", + "type": "info", + "timestamp": "2025-04-04T10:56:30.982873", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_b7326804-734a-4710-94e1-71c024720242", + "message": "Workflow nach Benutzereingabe fortgesetzt", + "type": "info", + "timestamp": "2025-04-04T10:56:30.987415", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_83cc006b-97e7-42b1-a75a-f63925e68329", + "message": "1 Dateien werden verarbeitet", + "type": "info", + "timestamp": "2025-04-04T10:56:30.992889", + "agent_id": null, + "agent_name": null + }, + { + "id": "log_a9ac8fe7-a392-4523-bd5d-4951cb15534d", + "message": "Fehler bei der Workflow-Ausführung: 'str' object does not support item assignment", + "type": "error", + "timestamp": "2025-04-04T10:56:30.995604", + "agent_id": null, + "agent_name": null + } + ] +} \ No newline at end of file diff --git a/gwserver/app.py b/gwserver/app.py index 27cf13ee..68318ec0 100644 --- a/gwserver/app.py +++ b/gwserver/app.py @@ -1,3 +1,6 @@ +import os +os.environ["NUMEXPR_MAX_THREADS"] = "12" + from fastapi import FastAPI, HTTPException, Depends, Body, status, Response from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse, FileResponse @@ -6,15 +9,12 @@ from fastapi.security import OAuth2PasswordRequestForm import uvicorn from typing import Dict, Any -import os import logging from datetime import timedelta import pathlib # Import interfaces from modules.gateway_interface import get_gateway_interface -from modules.lucydom_interface import get_lucydom_interface -from modules.agentservice_interface import AgentService # Import auth module from auth import ( @@ -24,8 +24,9 @@ from auth import ( ACCESS_TOKEN_EXPIRE_MINUTES ) -# Import models - generisch importieren +# Import models - generisch importieren zur INITIALISIERUNG, auch wenn dummy! import modules.gateway_model as gateway_model +import modules.lucydom_interface as lucydom_model # Konfiguration des Loggers logging.basicConfig( @@ -109,21 +110,15 @@ async def read_user_me(current_user: Dict[str, Any] = Depends(get_current_active return current_user # Alle Router einbinden +from routes.attributes import router as attributes_router +app.include_router(attributes_router) + from routes.mandates import router as mandate_router app.include_router(mandate_router) from routes.users import router as user_router app.include_router(user_router) -from routes.attributes import router as attributes_router -app.include_router(attributes_router) - -from routes.workspaces import router as workspace_router -app.include_router(workspace_router) - -from routes.agents import router as agent_router -app.include_router(agent_router) - from routes.files import router as file_router app.include_router(file_router) diff --git a/gwserver/auth.py b/gwserver/auth.py index 393f0e12..1d08aa16 100644 --- a/gwserver/auth.py +++ b/gwserver/auth.py @@ -1,5 +1,5 @@ from datetime import datetime, timedelta, timezone -from typing import Optional, Dict, Any +from typing import Optional, Dict, Any, Tuple from fastapi import Depends, HTTPException, status from fastapi.security import OAuth2PasswordBearer from jose import JWTError, jwt @@ -118,17 +118,44 @@ async def get_current_active_user(current_user: Dict[str, Any] = Depends(get_cur return current_user -async def get_user_context(current_user: Dict[str, Any] = Depends(get_current_active_user)) -> tuple: +async def get_user_context(current_user: Dict[str, Any]) -> Tuple[int, int]: """ - Extrahiert den Benutzerkontext (Mandanten-ID und Benutzer-ID). + Extrahiert die Mandanten-ID und Benutzer-ID aus dem aktuellen Benutzer. + Enhanced with better logging. Args: - current_user: Aktuelle Benutzerdaten + current_user: Der aktuelle Benutzer Returns: - Tuple mit (mandate_id, user_id) + Tuple von (mandate_id, user_id) """ - mandate_id = current_user.get("mandate_id", 1) # Standard: Root-Mandant - user_id = current_user.get("id") + # Default values + default_mandate_id = 0 + default_user_id = 0 + # Extract mandate_id + mandate_id = current_user.get("mandate_id", None) + if mandate_id is None: + logger.warning(f"No mandate_id found in current_user, using default: {default_mandate_id}") + mandate_id = default_mandate_id + else: + try: + mandate_id = int(mandate_id) + except (ValueError, TypeError): + logger.error(f"Invalid mandate_id value: {mandate_id}, using default: {default_mandate_id}") + mandate_id = default_mandate_id + + # Extract user_id + user_id = current_user.get("id", None) + if user_id is None: + logger.warning(f"No user_id found in current_user, using default: {default_user_id}") + user_id = default_user_id + else: + try: + user_id = int(user_id) + except (ValueError, TypeError): + logger.error(f"Invalid user_id value: {user_id}, using default: {default_user_id}") + user_id = default_user_id + + # logger.info(f"User context: mandate_id={mandate_id}, user_id={user_id}") return mandate_id, user_id \ No newline at end of file diff --git a/gwserver/connector_aichat_anthropic.py b/gwserver/connector_aichat_anthropic.py deleted file mode 100644 index aef96b0e..00000000 --- a/gwserver/connector_aichat_anthropic.py +++ /dev/null @@ -1,435 +0,0 @@ -import os -import json -import logging -import httpx -import base64 -import mimetypes -from typing import Dict, Any, List, Optional -from fastapi import HTTPException -import configload as configload - - -# Logger konfigurieren -logger = logging.getLogger(__name__) - -# Konfigurationsdaten laden -def load_config_data(): - config = configload.load_config() - return { - "api_key": config.get('Connector_AiAnthropic', 'API_KEY'), - "api_url": config.get('Connector_AiAnthropic', 'API_URL'), - "model_name": config.get('Connector_AiAnthropic', 'MODEL_NAME'), - "temperature": float(config.get('Connector_AiAnthropic', 'TEMPERATURE')), - "max_tokens": int(config.get('Connector_AiAnthropic', 'MAX_TOKENS')) - } - -class ChatService: - """ - Connector für die Kommunikation mit der Anthropic API. - """ - - def __init__(self): - # Konfiguration laden - self.config = load_config_data() - self.api_key = self.config["api_key"] - self.api_url = self.config["api_url"] - self.model_name = self.config["model_name"] - - # HttpClient für API-Aufrufe - self.http_client = httpx.AsyncClient( - timeout=120.0, # Längeres Timeout für komplexe Anfragen - headers={ - "x-api-key": self.api_key, - "anthropic-version": "2023-06-01", # Anthropic API Version - "Content-Type": "application/json" - } - ) - - logger.info(f"Anthropic Connector initialisiert mit Modell: {self.model_name}") - - async def call_api(self, messages: List[Dict[str, Any]], temperature: float = None, max_tokens: int = None) -> Dict[str, Any]: - """ - Ruft die Anthropic API mit den gegebenen Nachrichten auf. - - Args: - messages: Liste von Nachrichten im OpenAI-Format (role, content) - temperature: Temperatur für die Antwortgenerierung (0.0-1.0) - max_tokens: Maximale Anzahl der Token in der Antwort - - Returns: - Die Antwort umgewandelt ins OpenAI-Format - - Raises: - HTTPException: Bei Fehlern in der API-Kommunikation - """ - try: - # OpenAI-Format in Anthropic-Format umwandeln - formatted_messages = self._convert_to_anthropic_format(messages) - - # Verwende Parameter aus der Konfiguration, falls keine überschrieben wurden - if temperature is None: - temperature = self.config.get("temperature", 0.2) - - if max_tokens is None: - max_tokens = self.config.get("max_tokens", 2000) - - # Anthropic API Payload erstellen - payload = { - "model": self.model_name, - "messages": formatted_messages, - "temperature": temperature, - "max_tokens": max_tokens - } - - response = await self.http_client.post( - self.api_url, - json=payload - ) - - if response.status_code != 200: - logger.error(f"Anthropic API-Fehler: {response.status_code} - {response.text}") - raise HTTPException(status_code=500, detail="Fehler bei der Kommunikation mit Anthropic API") - - # Antwort im Anthropic-Format in OpenAI-Format umwandeln - anthropic_response = response.json() - openai_formatted_response = self._convert_to_openai_format(anthropic_response) - - return openai_formatted_response - - except Exception as e: - logger.error(f"Fehler beim Aufruf der Anthropic API: {str(e)}") - raise HTTPException(status_code=500, detail=f"Fehler beim Aufruf der Anthropic API: {str(e)}") - - def _convert_to_anthropic_format(self, openai_messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]: - """ - Konvertiert Nachrichten vom OpenAI-Format ins Anthropic-Format. - - OpenAI verwendet: - [{"role": "system", "content": "..."}, - {"role": "user", "content": "..."}, - {"role": "assistant", "content": "..."}] - - Anthropic verwendet: - [{"role": "user", "content": "..."}, - {"role": "assistant", "content": "..."}] - - Anmerkung: Anthropic hat kein direktes System-Message-Äquivalent, - daher fügen wir System-Nachrichten in die erste User-Nachricht ein. - """ - anthropic_messages = [] - system_content = "" - - # Extrahiere zuerst alle System-Nachrichten - for msg in openai_messages: - if msg.get("role") == "system": - system_content += msg.get("content", "") + "\n\n" - - # Konvertiere die restlichen Nachrichten - for i, msg in enumerate(openai_messages): - role = msg.get("role") - content = msg.get("content", "") - - # System-Nachrichten überspringen (bereits extrahiert) - if role == "system": - continue - - # Für die erste User-Nachricht: System-Inhalte voranstellen, falls vorhanden - if role == "user" and system_content and not any(m.get("role") == "user" for m in anthropic_messages): - if isinstance(content, str): - content = system_content + content - elif isinstance(content, list): - # Wenn content ein Array ist (für Multimodal-Nachrichten) - text_parts = [] - for part in content: - if part.get("type") == "text": - text_parts.append(part) - - if text_parts: - text_parts[0]["text"] = system_content + text_parts[0].get("text", "") - - # Anthropic unterstützt nur "user" und "assistant" als Rollen - if role not in ["user", "assistant"]: - role = "user" - - anthropic_messages.append({"role": role, "content": content}) - - return anthropic_messages - - def _convert_to_openai_format(self, anthropic_response: Dict[str, Any]) -> Dict[str, Any]: - """ - Konvertiert eine Antwort vom Anthropic-Format ins OpenAI-Format. - - Anthropic gibt zurück: - { - "id": "msg_...", - "content": [{"type": "text", "text": "Antworttext"}], - "model": "claude-...", - ... - } - - OpenAI gibt zurück: - { - "id": "chatcmpl-...", - "object": "chat.completion", - "choices": [ - { - "message": { - "role": "assistant", - "content": "Antworttext" - }, - "index": 0, - "finish_reason": "stop" - } - ], - "model": "gpt-...", - ... - } - """ - # Extrahiere Inhalt aus Anthropic-Antwort - content = "" - if "content" in anthropic_response: - if isinstance(anthropic_response["content"], list): - # Inhalt ist eine Liste von Teilen (bei neueren API-Versionen) - for part in anthropic_response["content"]: - if part.get("type") == "text": - content += part.get("text", "") - else: - # Direkter Inhalt als String (bei älteren API-Versionen) - content = anthropic_response["content"] - - # Erstelle OpenAI-formatierte Antwort - return { - "id": anthropic_response.get("id", ""), - "object": "chat.completion", - "created": anthropic_response.get("created", 0), - "model": anthropic_response.get("model", self.model_name), - "choices": [ - { - "message": { - "role": "assistant", - "content": content - }, - "index": 0, - "finish_reason": "stop" - } - ] - } - - def prepare_file_message_content(self, prompt_text: str, file_paths: List[Dict[str, Any]]) -> List[Dict[str, Any]]: - """ - Bereitet eine Nachricht mit Dateien für Anthropic API vor. - - Args: - prompt_text: Der Text-Prompt - file_paths: Liste von Dateipfaden mit Metadaten (Dict mit id, name, type, path) - - Returns: - Eine für Anthropic-API formatierte content-Liste - """ - message_content = [ - { - "type": "text", - "text": prompt_text - } - ] - - # Füge Dateien als Anhänge hinzu - for file_info in file_paths: - file_path = file_info.get("path", "") - if file_path and os.path.exists(file_path): - try: - # Datei als Base64 codieren - with open(file_path, "rb") as f: - file_data = f.read() - base64_data = base64.b64encode(file_data).decode('utf-8') - - # MIME-Typ bestimmen - mime_type, _ = mimetypes.guess_type(file_path) - if not mime_type: - mime_type = "application/octet-stream" - - # Content-Type bestimmen (image oder document) - content_type = "image" if mime_type.startswith("image/") else "document" - - # Füge die Datei als Anhang hinzu - message_content.append({ - "type": content_type, - "source": { - "type": "base64", - "media_type": mime_type, - "data": base64_data - } - }) - - logger.info(f"Datei {file_info.get('name', 'Unbekannt')} als {content_type} hinzugefügt") - - except Exception as e: - logger.error(f"Fehler beim Hinzufügen der Datei {file_info.get('name', 'Unbekannt')}: {str(e)}") - - return message_content - - def parse_filedata(self, file_paths: List[Dict[str, Any]], prompt_text: str = "", file_contents: Dict[str, str] = None) -> Dict[str, Any]: - """ - Bereitet Dateien für die Anthropic API vor und erstellt ein einheitliches Message-Objekt. - - Args: - file_paths: Liste von Dateipfaden mit Metadaten (Dict mit id, name, type, path) - prompt_text: Der Text-Prompt, der zusammen mit den Dateien gesendet werden soll - file_contents: Optional vorgelesene Dateiinhalte als Dict[file_id, content] - - Returns: - Ein standardisiertes Message-Objekt, das für beide API-Typen verwendet werden kann - """ - # Basisstruktur für die Nachricht - message = { - "role": "user", - "content": [] - } - - # Text-Prompt hinzufügen - if prompt_text: - message["content"].append({ - "type": "text", - "text": prompt_text - }) - - # Dateien als Anhänge hinzufügen - for file_info in file_paths: - file_path = file_info.get("path", "") - file_name = file_info.get("name", "") - file_id = file_info.get("id", "") - - # Prüfen, ob Dateiinhalt bereits vorhanden ist - if file_contents and file_id in file_contents: - # Nur Kontext-Information hinzufügen - message["content"].append({ - "type": "text", - "text": f"Datei: {file_name}\n{file_contents[file_id]}" - }) - logger.info(f"Vorverarbeiteter Inhalt für Datei {file_name} verwendet") - continue - - # Sonst Datei direkt verarbeiten - if file_path and os.path.exists(file_path): - try: - # Datei als Base64 codieren - with open(file_path, "rb") as f: - file_data = f.read() - base64_data = base64.b64encode(file_data).decode('utf-8') - - # MIME-Typ bestimmen mit python-magic, wenn verfügbar - try: - import magic - mime_type = magic.from_buffer(file_data, mime=True) - except ImportError: - # Fallback auf mimetypes, wenn python-magic nicht verfügbar ist - mime_type, _ = mimetypes.guess_type(file_path) - if not mime_type: - # Fallback auf Dateierweiterung - extension = os.path.splitext(file_path)[1].lower()[1:] - mime_type = get_mime_type_from_extension(extension) - - # Content-Type bestimmen (image, document, oder allgemein file) - content_type, _ = determine_content_structure(mime_type) - - # Füge die Datei als Anhang hinzu - message["content"].append({ - "type": content_type, - "source": { - "type": "base64", - "media_type": mime_type, - "data": base64_data - } - }) - - logger.info(f"Datei {file_name} als {content_type} hinzugefügt") - - except Exception as e: - logger.error(f"Fehler beim Hinzufügen der Datei {file_name}: {str(e)}") - message["content"].append({ - "type": "text", - "text": f"[Fehler beim Laden der Datei {file_name}: {str(e)}]" - }) - else: - # Datei nicht gefunden - Hinweis einfügen - message["content"].append({ - "type": "text", - "text": f"[Datei {file_name} nicht verfügbar]" - }) - - return message - - async def close(self): - """Schließt den HTTP-Client beim Beenden der Anwendung""" - await self.http_client.aclose() - - -def determine_content_structure(mime_type: str) -> tuple: - """ - Bestimmt den richtigen content_type und die Nachrichtenstruktur basierend auf dem MIME-Typ. - - Args: - mime_type: Der MIME-Typ der Datei - - Returns: - Tuple mit (content_type, message_structure) - """ - # Bildtypen - if mime_type.startswith("image/"): - return "image", "image" - - # Dokumenttypen - document_types = [ - "application/pdf", - "application/vnd.openxmlformats-officedocument.wordprocessingml.document", # docx - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", # xlsx - "application/vnd.openxmlformats-officedocument.presentationml.presentation", # pptx - "application/vnd.ms-excel", - "application/vnd.ms-powerpoint", - "application/msword", - "text/csv", - "text/plain", - "application/json", - "application/xml", - "text/html" - ] - - if any(mime_type.startswith(dt) for dt in document_types) or mime_type in document_types: - return "document", "document" - - # Fallback für unbekannte Typen - return "file", "file" - -def get_mime_type_from_extension(extension: str) -> str: - """ - Bestimmt den MIME-Typ basierend auf der Dateiendung. - - Args: - extension: Die Dateiendung ohne Punkt - - Returns: - Der entsprechende MIME-Typ - """ - extension_to_mime = { - "pdf": "application/pdf", - "docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - "doc": "application/msword", - "xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - "xls": "application/vnd.ms-excel", - "pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation", - "ppt": "application/vnd.ms-powerpoint", - "csv": "text/csv", - "txt": "text/plain", - "json": "application/json", - "xml": "application/xml", - "html": "text/html", - "htm": "text/html", - "jpg": "image/jpeg", - "jpeg": "image/jpeg", - "png": "image/png", - "gif": "image/gif", - "webp": "image/webp", - "svg": "image/svg+xml" - } - - return extension_to_mime.get(extension, "application/octet-stream") \ No newline at end of file diff --git a/gwserver/connector_aichat_openai.py b/gwserver/connector_aichat_openai.py deleted file mode 100644 index 60e488b2..00000000 --- a/gwserver/connector_aichat_openai.py +++ /dev/null @@ -1,423 +0,0 @@ -import io -import os -import json -import uuid -import logging -import httpx -import base64 -import mimetypes -from typing import Dict, Any, List, Optional -from fastapi import HTTPException -import configload as configload -import pandas as pd -from PIL import Image -import PyPDF2 -import fitz - -# Logger konfigurieren -logger = logging.getLogger(__name__) - -# Konfigurationsdaten laden -def load_config_data(): - config = configload.load_config() - return { - "api_key": config.get('Connector_AiOpenai', 'API_KEY'), - "api_url": config.get('Connector_AiOpenai', 'API_URL'), - "model_name": config.get('Connector_AiOpenai', 'MODEL_NAME'), - "temperature": float(config.get('Connector_AiOpenai', 'TEMPERATURE')), - "max_tokens": int(config.get('Connector_AiOpenai', 'MAX_TOKENS')) - } - -class ChatService: - """ - Connector für die Kommunikation mit der OpenAI API. - """ - - def __init__(self): - # Konfiguration laden - self.config = load_config_data() - self.api_key = self.config["api_key"] - self.api_url = self.config["api_url"] - self.model_name = self.config["model_name"] - - # HttpClient für API-Aufrufe - self.http_client = httpx.AsyncClient( - timeout=120.0, # Längeres Timeout für komplexe Anfragen - headers={ - "Authorization": f"Bearer {self.api_key}", - "Content-Type": "application/json" - } - ) - - logger.info(f"OpenAI Connector initialisiert mit Modell: {self.model_name}") - - async def call_api(self, messages: List[Dict[str, Any]], temperature: float = None, max_tokens: int = None) -> Dict[str, Any]: - """ - Ruft die OpenAI API mit den gegebenen Nachrichten auf. - - Args: - messages: Liste von Nachrichten im OpenAI-Format (role, content) - temperature: Temperatur für die Antwortgenerierung (0.0-1.0) - max_tokens: Maximale Anzahl der Token in der Antwort - - Returns: - Die Antwort der OpenAI API - - Raises: - HTTPException: Bei Fehlern in der API-Kommunikation - """ - try: - # Verwende Parameter aus der Konfiguration, falls keine überschrieben wurden - if temperature is None: - temperature = self.config.get("temperature", 0.2) - - if max_tokens is None: - max_tokens = self.config.get("max_tokens", 2000) - - payload = { - "model": self.model_name, - "messages": messages, - "temperature": temperature, - "max_tokens": max_tokens - } - - response = await self.http_client.post( - self.api_url, - json=payload - ) - - if response.status_code != 200: - logger.error(f"OpenAI API-Fehler: {response.status_code} - {response.text}") - raise HTTPException(status_code=500, detail="Fehler bei der Kommunikation mit OpenAI API") - - return response.json() - - except Exception as e: - logger.error(f"Fehler beim Aufruf der OpenAI API: {str(e)}") - raise HTTPException(status_code=500, detail=f"Fehler beim Aufruf der OpenAI API: {str(e)}") - - async def close(self): - """Schließt den HTTP-Client beim Beenden der Anwendung""" - await self.http_client.close() - - async def analyze_image(self, image_path: str, prompt: str) -> str: - """ - Analysiert ein Bild mit der OpenAI Vision API. - - Args: - image_path: Pfad zum Bild - prompt: Der Prompt für die Analyse - - Returns: - Die Antwort der OpenAI Vision API als Text - """ - try: - # Bild einlesen und als Base64 kodieren - with open(image_path, "rb") as f: - image_data = f.read() - - # In Base64-String konvertieren - base64_data = base64.b64encode(image_data).decode('utf-8') - - # MIME-Typ bestimmen - mime_type, _ = mimetypes.guess_type(image_path) - if not mime_type: - # Standard ist PNG, wenn Typ nicht bestimmt werden kann - mime_type = "image/png" - - # Vision-fähiges Modell für die Anfrage verwenden - vision_model = "gpt-4o" # oder aus der Konfiguration holen - - # Bereite den Payload für die Vision API vor - messages = [ - { - "role": "user", - "content": [ - {"type": "text", "text": prompt}, - { - "type": "image_url", - "image_url": { - "url": f"data:{mime_type};base64,{base64_data}" - } - } - ] - } - ] - - # Verwende die bestehende call_api Funktion mit dem Vision-Modell - response = await self.call_api(messages) - - # Inhalt extrahieren und zurückgeben - return response["choices"][0]["message"]["content"] - - except Exception as e: - logger.error(f"Fehler bei der Bildanalyse {image_path}: {str(e)}", exc_info=True) - return f"[Fehler bei der Bildanalyse: {str(e)}]" - - - async def extract_and_analyze_pdf_images(self, pdf_path: str, prompt: str) -> List[Dict[str, Any]]: - """ - Extrahiert Bilder aus einer PDF-Datei mit PyMuPDF und analysiert sie mit der Vision API. - - Args: - pdf_path: Pfad zur PDF-Datei - prompt: Der Prompt für die Bildanalyse - - Returns: - Eine Liste mit Analyseergebnissen für jedes Bild - """ - import uuid - import os - image_responses = [] - - try: - # PDF öffnen - doc = fitz.open(pdf_path) - logger.info(f"PDF geöffnet: {pdf_path} mit {len(doc)} Seiten") - - for page_num, page in enumerate(doc, 1): - # Alle Bilder auf der Seite finden - image_list = page.get_images(full=True) - - if image_list: - logger.info(f"Seite {page_num}: {len(image_list)} Bilder gefunden") - - for img_index, img in enumerate(image_list): - try: - # Bild-Referenz - xref = img[0] - - # Bild und Metadaten extrahieren - base_image = doc.extract_image(xref) - image_bytes = base_image["image"] # Tatsächliche Bilddaten - image_ext = base_image["ext"] # Dateiendung (jpg, png, etc.) - - # Speichere als temporäre Datei - unique_id = uuid.uuid4() - temp_img_path = f"temp_img_{page_num}_{img_index}_{unique_id}.{image_ext}" - - with open(temp_img_path, "wb") as img_file: - img_file.write(image_bytes) - - logger.debug(f"Bild temporär gespeichert: {temp_img_path}") - - # Analysiere mit Vision API - try: - analysis_result = await self.analyze_image(temp_img_path, prompt) - logger.debug(f"Bildanalyse für Bild {img_index} auf Seite {page_num} abgeschlossen") - except Exception as analyze_error: - logger.error(f"Fehler bei der Bildanalyse: {str(analyze_error)}") - analysis_result = f"[Fehler bei der Bildanalyse: {str(analyze_error)}]" - - # Ergebnis speichern - try: - # Versuche zuerst, die Größe aus base_image zu bekommen - if 'width' in base_image and 'height' in base_image: - image_size = f"{base_image['width']}x{base_image['height']}" - else: - # Alternative: Öffne das temporäre Bild, um die Größe zu bestimmen - with Image.open(temp_img_path) as img: - width, height = img.size - image_size = f"{width}x{height}" - except Exception as e: - logger.warning(f"Konnte Bildgröße nicht ermitteln: {str(e)}") - image_size = "unbekannt" - - image_responses.append({ - "page": page_num, - "image_index": img_index, - "format": image_ext, - "image_size": image_size, # Der key wird immer gesetzt, entweder mit tatsächlicher Größe oder "unbekannt" - "response": analysis_result - }) - - # Temporäre Datei löschen - try: - if os.path.exists(temp_img_path): - os.remove(temp_img_path) - logger.debug(f"Temporäre Bilddatei entfernt: {temp_img_path}") - except Exception as cleanup_error: - logger.warning(f"Temporäre Datei konnte nicht entfernt werden: {cleanup_error}") - - except Exception as e: - logger.warning(f"Fehler bei der Extraktion von Bild {img_index} auf Seite {page_num}: {str(e)}") - continue - - logger.info(f"Extrahiert und analysiert: {len(image_responses)} Bilder aus PDF {os.path.basename(pdf_path)}") - - except ImportError: - logger.error("PyMuPDF (fitz) ist nicht installiert. Installiere es mit 'pip install pymupdf'") - except Exception as e: - logger.error(f"Fehler beim Extrahieren von PDF-Bildern: {str(e)}") - return image_responses - - - async def parse_filedata(self, file_contexts: List[Dict[str, Any]], prompt_text: str, file_contents: Dict[str, str] = None) -> Dict[str, Any]: - """ - Bereitet eine vollständige Nachricht mit allen Dateiinhalten für das AI-Modell vor. - - Args: - file_contexts: Liste der Dateikontexte mit Metadaten - prompt_text: Der Text-Prompt - file_contents: Dictionary mit bereits geladenen Dateiinhalten - - Returns: - Eine vollständig formatierte Nachricht für das AI-Modell - """ - # Basisstruktur für die Nachricht in OpenAI-Format - message = { - "role": "user", - "content": [] - } - - # Text-Prompt hinzufügen - if prompt_text: - message["content"].append({ - "type": "text", - "text": prompt_text - }) - - if not file_contents: - file_contents = {} - - # Dateien als Anhänge hinzufügen - for file_info in file_contexts: - file_path = file_info.get("path", "") - file_name = file_info.get("name", "") - file_id = file_info.get("id", "") - file_type = file_info.get("type", "") - - # Prüfen, ob Dateiinhalt bereits vorhanden ist - if file_id in file_contents: - content = file_contents[file_id] - - # Problematische Unicode-Zeichen ersetzen - if isinstance(content, str): - content = content.encode('utf-8', errors='replace').decode('utf-8') - else: - content = str(content) - - # Besondere Verarbeitung für PDF-Dateien mit Bildern - if file_name.endswith('.pdf') and file_path and os.path.exists(file_path): - try: - # Bildanalyse der PDF durchführen - image_prompt = prompt_text or "Beschreibe detailliert, was du in diesem Bild siehst." - image_responses = await self.extract_and_analyze_pdf_images(file_path, image_prompt) - - # Nur wenn Bilder gefunden wurden, füge die Analyse hinzu - if image_responses: - image_details = "\n\n".join([ - f"Bild auf Seite {resp['page']} (Größe: {resp['image_size']}): {resp['response']}" - for resp in image_responses - ]) - logger.debug("Image description: "+image_details) - message["content"].append({ - "type": "text", - "text": f"PDF-Bildanalyse für {file_name}:\n{image_details}" - }) - except Exception as e: - logger.error(f"Fehler bei der PDF-Bildanalyse für {file_name}: {str(e)}") - - # Text zur Nachricht hinzufügen - message["content"].append({ - "type": "text", - "text": f"--- DATEI: {file_name} ---\n\n{content}" - }) - logger.info(f"Inhalt für Datei {file_name} zur Nachricht hinzugefügt") - continue - - # Wenn kein Inhalt vorhanden ist, füge einen Hinweis hinzu - if not file_path or not os.path.exists(file_path): - message["content"].append({ - "type": "text", - "text": f"[Datei {file_name} wurde nicht gefunden oder ist nicht zugänglich]" - }) - logger.warning(f"Datei {file_name} nicht gefunden: {file_path}") - continue - - # Direktes Hinzufügen von Bildern bei OpenAI (für Bilder außerhalb von PDFs) - if file_type == "image" or file_name.lower().endswith(('.jpg', '.jpeg', '.png', '.gif', '.webp')): - try: - # Bild als Base64 kodieren - with open(file_path, "rb") as f: - file_data = f.read() - base64_data = base64.b64encode(file_data).decode('utf-8') - - # MIME-Typ bestimmen - mime_type, _ = mimetypes.guess_type(file_path) - if not mime_type: - mime_type = "application/octet-stream" - - # Bild zur Nachricht hinzufügen - if mime_type.startswith("image/"): - # Füge zunächst die Bildanalyse als Text hinzu - image_prompt = prompt_text or "Beschreibe detailliert, was du in diesem Bild siehst." - analysis_result = await self.analyze_image(file_path, image_prompt) - - message["content"].append({ - "type": "text", - "text": f"Bildanalyse für {file_name}:\n{analysis_result}" - }) - - # Dann füge das Bild selbst hinzu - message["content"].append({ - "type": "image_url", - "image_url": { - "url": f"data:{mime_type};base64,{base64_data}" - } - }) - - logger.info(f"Bild {file_name} analysiert und zur Nachricht hinzugefügt") - except Exception as e: - logger.error(f"Fehler beim Hinzufügen des Bildes {file_name}: {str(e)}") - message["content"].append({ - "type": "text", - "text": f"[Fehler beim Laden des Bildes {file_name}: {str(e)}]" - }) - - # Optimiere das Message-Format für die API basierend auf dem Inhalt - if not message["content"]: - # Leerer Inhalt - setze auf leeren String - message["content"] = prompt_text or "" - elif len(message["content"]) == 1 and message["content"][0]["type"] == "text": - # Nur ein Text-Element - vereinfache die Struktur - message["content"] = message["content"][0]["text"] - - # Bei komplizierten Inhalten (Mischung aus Text und Bildern) wird das Array-Format beibehalten - - logger.debug(f"Message-Objekt für OpenAI erstellt mit {len(message['content']) if isinstance(message['content'], list) else 'String'}-Inhalt") - return message - -def get_mime_type_from_extension(extension: str) -> str: - """ - Bestimmt den MIME-Typ basierend auf der Dateiendung. - - Args: - extension: Die Dateiendung ohne Punkt - - Returns: - Der entsprechende MIME-Typ - """ - extension_to_mime = { - "pdf": "application/pdf", - "docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - "doc": "application/msword", - "xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - "xls": "application/vnd.ms-excel", - "pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation", - "ppt": "application/vnd.ms-powerpoint", - "csv": "text/csv", - "txt": "text/plain", - "json": "application/json", - "xml": "application/xml", - "html": "text/html", - "htm": "text/html", - "jpg": "image/jpeg", - "jpeg": "image/jpeg", - "png": "image/png", - "gif": "image/gif", - "webp": "image/webp", - "svg": "image/svg+xml" - } - - return extension_to_mime.get(extension, "application/octet-stream") \ No newline at end of file diff --git a/gwserver/connector_aiweb_webscraping.py b/gwserver/connector_aiweb_webscraping.py deleted file mode 100644 index 6c818a98..00000000 --- a/gwserver/connector_aiweb_webscraping.py +++ /dev/null @@ -1,501 +0,0 @@ -import logging -import re -import requests -from typing import List, Dict, Any, Optional, Tuple -from bs4 import BeautifulSoup -import json -import os -import configload as configload -import urllib.parse -import time -import random -import pandas as pd - -# Logger konfigurieren -logger = logging.getLogger(__name__) - -# Konfigurationsdaten laden -def load_config_data(): - config = configload.load_config() - - # Get search engines as comma-separated list - search_engines_str = config.get('Connector_AiWebscraping', 'SEARCH_ENGINES') - search_engines = [engine.strip() for engine in search_engines_str.split(',')] - - # Get excluded domains as comma-separated list - excluded_domains_str = config.get('Connector_AiWebscraping', 'EXCLUDED_DOMAINS') - excluded_domains = [domain.strip() for domain in excluded_domains_str.split(',')] - - return { - "timeout": int(config.get('Connector_AiWebscraping', 'TIMEOUT')), - "max_urls": int(config.get('Connector_AiWebscraping', 'MAX_URLS')), - "max_content_length": int(config.get('Connector_AiWebscraping', 'MAX_CONTENT_LENGTH')), - "user_agent": config.get('Connector_AiWebscraping', 'USER_AGENT'), - "search_engines": search_engines, - "min_delay": float(config.get('Connector_AiWebscraping', 'MIN_DELAY')), - "max_delay": float(config.get('Connector_AiWebscraping', 'MAX_DELAY')), - "excluded_domains": excluded_domains, - "max_search_results": int(config.get('Connector_AiWebscraping', 'MAX_SEARCH_RESULTS')) - } - -class WebScrapingService: - """ - Connector für Web-Scraping-Funktionalitäten. - """ - - def __init__(self): - # Konfiguration laden - self.config = load_config_data() - - # Konfigurationswerte zu Instance-Attributen zuweisen - self.timeout = self.config["timeout"] - self.max_urls = self.config["max_urls"] - self.max_content_length = self.config["max_content_length"] - self.user_agent = self.config["user_agent"] - self.min_delay = self.config["min_delay"] - self.max_delay = self.config["max_delay"] - self.excluded_domains = self.config["excluded_domains"] - self.max_search_results = self.config["max_search_results"] - - # Initialize search engines based on config - self.search_engines = {} - if "google" in self.config["search_engines"]: - self.search_engines["google"] = "https://www.google.com/search?q={query}" - if "bing" in self.config["search_engines"]: - self.search_engines["bing"] = "https://www.bing.com/search?q={query}" - - # Headers for requests - self.headers = { - 'User-Agent': self.user_agent, - 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', - 'Accept-Language': 'en-US,en;q=0.5', - 'Referer': 'https://www.google.com/', - 'DNT': '1', - 'Connection': 'keep-alive', - 'Upgrade-Insecure-Requests': '1', - } - - logger.info(f"WebScraping Connector initialisiert mit Timeout: {self.timeout}s") - - def scrape_url(self, url: str) -> str: - """ - Scrapt den Inhalt einer URL und extrahiert den relevanten Text. - - Args: - url: Die zu scrapende URL - - Returns: - Der extrahierte Inhalt - - Raises: - Exception: Bei Fehlern im Scraping-Prozess - """ - try: - logger.info(f"Requesting URL: {url}") - response = requests.get(url, headers=self.headers, timeout=self.timeout) - response.raise_for_status() - - soup = BeautifulSoup(response.text, 'html.parser') - - # Get page title - title = soup.title.string if soup.title else "No title" - - # Remove unwanted elements - for element in soup.select('script, style, meta, noscript, iframe, nav, footer, header, aside'): - element.extract() - - # Try to find main content - main_content = "" - - # Common content containers - content_selectors = [ - 'main', '#main', '.main', - 'article', '.article', - '#content', '.content', - '.post', '#post', - '.entry-content', '.post-content', - '.page-content', '.article-content' - ] - - # Try each selector - for selector in content_selectors: - elements = soup.select(selector) - if elements: - main_content = elements[0].get_text(separator='\n', strip=True) - logger.info(f"Found content using selector: {selector}") - break - - # If no main content found, use body text - if not main_content: - main_content = soup.body.get_text(separator='\n', strip=True) - logger.info("Using body text as no main content container found") - - # Clean up the text - lines = [] - for line in main_content.split('\n'): - line = line.strip() - if line and len(line) > 15: # Skip very short lines - lines.append(line) - - main_content = '\n'.join(lines) - - # Truncate if too long - if len(main_content) > self.max_content_length: - main_content = main_content[:self.max_content_length] + "...\n[Inhalt gekürzt]" - - # Add metadata - result = f"# {title}\nURL: {url}\n\n{main_content}" - - return result.strip() - - except Exception as e: - logger.error(f"Fehler beim Scrapen von {url}: {str(e)}") - return f"[Fehler beim Scrapen von {url}: {str(e)}]" - - def extract_urls_from_search_results(self, html_content: str) -> List[str]: - """ - Extrahiert URLs aus den Suchergebnissen. - - Args: - html_content: HTML der Suchergebnisseite - - Returns: - Liste der gefundenen URLs - """ - soup = BeautifulSoup(html_content, 'html.parser') - urls = [] - - # Different search engines have different HTML structures - # Google links - for a_tag in soup.select('a[href^="/url?"]'): - href = a_tag.get('href', '') - if '/url?q=' in href: - url = href.split('/url?q=')[1].split('&')[0] - url = urllib.parse.unquote(url) - if url.startswith('http') and url not in urls: - urls.append(url) - - # Bing links - for a_tag in soup.select('a[href^="http"]'): - url = a_tag.get('href', '') - if (url.startswith('http') and - not any(domain in url for domain in self.excluded_domains) and - url not in urls): - urls.append(url) - - # If no URLs found, try a more generic approach - if not urls: - for a_tag in soup.find_all('a', href=True): - url = a_tag['href'] - if (url.startswith('http') and - not any(domain in url for domain in self.excluded_domains) and - url not in urls): - urls.append(url) - - return urls[:self.max_search_results] # Limit to max_search_results - - def extract_urls(self, text: str) -> List[str]: - """ - Extrahiert URLs aus einem Text. - - Args: - text: Der zu analysierende Text - - Returns: - Liste der gefundenen URLs - """ - # URL pattern with improved regex - url_pattern = re.compile(r'https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+(?:/[^)\s]*)?') - found_urls = url_pattern.findall(text) - - # Basic URL cleanup and validation - valid_urls = [] - for url in found_urls: - # Remove trailing punctuation - url = re.sub(r'[.,;:!?]$', '', url) - - # Skip excluded domains - if not any(domain in url for domain in self.excluded_domains): - valid_urls.append(url) - - return valid_urls[:self.max_urls] # Limit to max_urls - - def extract_keywords(self, text: str) -> str: - """ - Extrahiert Schlüsselwörter aus einem Text. - - Args: - text: Der zu analysierende Text - - Returns: - Extrahierte Schlüsselwörter als String - """ - # Define German stopwords - stopwords = [ - "der", "die", "das", "den", "dem", "des", - "ein", "eine", "einer", "eines", "einem", "einen", - "und", "oder", "aber", "wenn", "weil", "obwohl", - "für", "mit", "von", "zu", "aus", "bei", "nach", - "über", "unter", "vor", "hinter", "neben", "zwischen", - "nicht", "kein", "keine", "keiner", "keines", "keinem", "keinen", - "ist", "sind", "war", "waren", "wird", "werden", "wurde", "wurden", - "kann", "können", "darf", "dürfen", "soll", "sollen", "muss", "müssen", - "hat", "haben", "dass", "noch", "schon", "auch", "nur", "sehr", "mehr", - "durch", "gegen", "ohne", "um", "heute", "morgen", "gestern" - ] - - # Normalize text - text = text.lower() - - # Remove special characters and replace them with spaces - text = re.sub(r'[^\w\s]', ' ', text) - - # Split into words - words = text.split() - - # Filter words - filtered_words = [] - for word in words: - if (len(word) > 3 and # Skip very short words - word not in stopwords and - not word.isdigit()): # Skip numbers - filtered_words.append(word) - - # Get common words by frequency - word_freq = {} - for word in filtered_words: - if word in word_freq: - word_freq[word] += 1 - else: - word_freq[word] = 1 - - # Sort by frequency - sorted_words = sorted(word_freq.items(), key=lambda x: x[1], reverse=True) - - # Take top 10 words - keywords = [word for word, freq in sorted_words[:10]] - - return " ".join(keywords) - - async def search_web(self, query: str) -> List[str]: - """ - Führt eine Websuche mit den gegebenen Suchbegriffen durch. - - Args: - query: Suchbegriffe - - Returns: - Liste der gefundenen URLs - """ - # Choose a random search engine - engine_name = random.choice(list(self.search_engines.keys())) - search_url = self.search_engines[engine_name].format(query=urllib.parse.quote(query)) - - logger.info(f"Searching with {engine_name}: {query}") - - try: - # Add a slight delay to avoid being blocked - time.sleep(random.uniform(self.min_delay, self.max_delay)) - - response = requests.get( - search_url, - headers=self.headers, - timeout=self.timeout - ) - - if response.status_code == 200: - # Extract URLs from search results - urls = self.extract_urls_from_search_results(response.text) - logger.info(f"Found {len(urls)} URLs from search results") - return urls - else: - logger.warning(f"Search request failed with status code: {response.status_code}") - return [] - except Exception as e: - logger.error(f"Error during web search: {e}") - return [] - - - - # Enhanced connector_aiweb_webscraping.py modifications - # Focus on the scrape_web_data method to ensure consistent behavior - - async def scrape_web_data(self, prompt: str) -> str: - """ - Enhanced web scraping function that ensures consistent behavior. - Always performs scraping for prompts and returns structured results. - - Args: - prompt: The user prompt - - Returns: - Scraped web data as text - """ - try: - # Ensure prompt is a string - if isinstance(prompt, list): - prompt = " ".join(prompt) if all(isinstance(item, str) for item in prompt) else str(prompt) - elif not isinstance(prompt, str): - prompt = str(prompt) - - # Log the scraping attempt - logger.info(f"Starting web scraping with prompt: {prompt[:400]}...") - - # First check for explicit URLs in the prompt - explicit_urls = self.extract_urls(prompt) - - # Always perform search, even if explicit URLs are found - # This ensures more comprehensive results - keywords = self.extract_keywords(prompt) - logger.info(f"Using keywords for search: {keywords}") - - # Search for relevant URLs - search_urls = await self.search_web(keywords) - - # Combine explicit URLs with search results, prioritizing explicit URLs - urls = [] - # Add explicit URLs first - for url in explicit_urls: - if url not in urls: - urls.append(url) - - # Then add search results, avoiding duplicates - for url in search_urls: - if url not in urls: - urls.append(url) - - # If no URLs found after both methods, try a simplified search - if not urls: - simplified_query = " ".join(prompt.split()[:8]) # Use first 8 words - simplified_urls = await self.search_web(simplified_query) - for url in simplified_urls: - if url not in urls: - urls.append(url) - - # Scrape content from URLs - results = [] - scraped_count = 0 - - if urls: - logger.info(f"Found {len(urls)} URLs to scrape") - - for url in urls[:self.max_urls]: - try: - # Add a delay between requests - time.sleep(random.uniform(self.min_delay, self.max_delay)) - - content = self.scrape_url(url) - if content and len(content) > 100: # Ensure meaningful content - results.append(content) - scraped_count += 1 - logger.info(f"Successfully scraped: {url}") - else: - logger.warning(f"Insufficient content from: {url}") - except Exception as e: - logger.error(f"Error scraping {url}: {e}") - - # Create the final result with improved structure - if results: - logger.info(f"Successfully scraped {scraped_count} pages") - - # Format the results in a structured way for better agent understanding - structured_result = f"# Web Scraping Results\n\nScraped {scraped_count} web sources based on: \"{prompt}\"\n\n" - - for i, result in enumerate(results): - structured_result += f"## Source {i+1}\n\n{result}\n\n---\n\n" - - return structured_result.strip() - else: - # If no real content was scraped, provide simulated data with clear indication - logger.warning("No content scraped, using simulated data") - - simulated_data = f""" - # Simulated Web Research Results for: {prompt} - - ## Notice - The web scraping system was unable to retrieve real data from the web. - The following information is provided as a placeholder to continue the workflow. - - ## Market Trends and Developments - - Latest analyses show significant growth in digital transformation - - Experts continue to forecast positive development for cloud-based solutions - - Current technologies improve efficiency by an average of 23% - - ## Leading Companies in the Sector - 1. TechInnovators GmbH - Market share 28% - 2. FutureWave AG - Market share 22% - 3. ProgressTech Ltd. - Market share 17% - - ## Innovations and New Products - - Smart integration solutions for existing systems - - AI-powered automation processes - - Improved sustainability standards through new materials - - *Note: This is simulated data provided because no actual web scraping was possible.* - """.strip() - - return simulated_data - except Exception as e: - logger.error(f"Error during web scraping: {e}") - error_message = f"Web scraping could not be performed: {str(e)}" - return error_message.strip() - - # Additional helper method to ensure the scraper agent always triggers web scraping - async def ensure_scraper_agent_scraping(agent_type: str, moderator_text: str, prompt: str, aiweb_scraper) -> Tuple[bool, str]: - """ - Helper function to ensure scraper agent always triggers web scraping. - To be called from the _run_moderator_cycle method when a scraper agent is selected. - - Args: - agent_type: Type of the selected agent - moderator_text: Text from the moderator - prompt: The original prompt - aiweb_scraper: Web scraper service instance - - Returns: - Tuple of (was_scraping_performed, scraped_data) - """ - if agent_type != "scraper": - return False, "" - - try: - # Log that web scraping is being performed for scraper agent - logger.info(f"Ensuring web scraping for scraper agent with prompt: {prompt[:100]}...") - - # Extract a search query from the moderator text if possible - search_query = prompt - if moderator_text: - # Try to extract a more specific query from moderator instructions - query_patterns = [ - r"search for [\"'](.+?)[\"']", - r"find information about [\"'](.+?)[\"']", - r"research [\"'](.+?)[\"']", - r"look up [\"'](.+?)[\"']" - ] - - for pattern in query_patterns: - match = re.search(pattern, moderator_text, re.IGNORECASE) - if match: - extracted_query = match.group(1) - if len(extracted_query) > 10: # Ensure it's a meaningful query - search_query = extracted_query - logger.info(f"Extracted search query from moderator: {search_query}") - break - - # Always perform the web scraping - scraped_data = await aiweb_scraper.scrape_web_data(search_query) - - # Mark that scraping was performed - return True, scraped_data - - except Exception as e: - logger.error(f"Error ensuring web scraping for scraper agent: {e}") - return True, f"Web scraping failed: {str(e)}" - - - async def close(self): - """ - Schließt alle offenen Ressourcen. - """ - # Currently no resources to close - pass \ No newline at end of file diff --git a/gwserver/connectors/connector_aichat_anthropic.py b/gwserver/connectors/connector_aichat_anthropic.py new file mode 100644 index 00000000..dfd2cd97 --- /dev/null +++ b/gwserver/connectors/connector_aichat_anthropic.py @@ -0,0 +1,239 @@ +import logging +import httpx +from typing import Dict, Any, List, Optional, Union +from fastapi import HTTPException +import configload + +# Logger konfigurieren +logger = logging.getLogger(__name__) + +# Konfigurationsdaten laden +def load_config_data(): + config = configload.load_config() + return { + "api_key": config.get('Connector_AiAnthropic', 'API_KEY'), + "api_url": config.get('Connector_AiAnthropic', 'API_URL'), + "model_name": config.get('Connector_AiAnthropic', 'MODEL_NAME'), + "temperature": float(config.get('Connector_AiAnthropic', 'TEMPERATURE')), + "max_tokens": int(config.get('Connector_AiAnthropic', 'MAX_TOKENS')) + } + +class ChatService: + """ + Connector für die Kommunikation mit der Anthropic API. + """ + + def __init__(self): + # Konfiguration laden + self.config = load_config_data() + self.api_key = self.config["api_key"] + self.api_url = self.config["api_url"] + self.model_name = self.config["model_name"] + + # HttpClient für API-Aufrufe + self.http_client = httpx.AsyncClient( + timeout=120.0, # Längeres Timeout für komplexe Anfragen + headers={ + "x-api-key": self.api_key, + "anthropic-version": "2023-06-01", # Anthropic API Version + "Content-Type": "application/json" + } + ) + + logger.info(f"Anthropic Connector initialisiert mit Modell: {self.model_name}") + + async def call_api(self, messages: List[Dict[str, Any]], temperature: float = None, max_tokens: int = None) -> Dict[str, Any]: + """ + Ruft die Anthropic API mit den gegebenen Nachrichten auf. + + Args: + messages: Liste von Nachrichten im OpenAI-Format (role, content) + temperature: Temperatur für die Antwortgenerierung (0.0-1.0) + max_tokens: Maximale Anzahl der Token in der Antwort + + Returns: + Die Antwort umgewandelt ins OpenAI-Format + + Raises: + HTTPException: Bei Fehlern in der API-Kommunikation + """ + try: + # OpenAI-Format in Anthropic-Format umwandeln + formatted_messages = self._convert_to_anthropic_format(messages) + + # Verwende Parameter aus der Konfiguration, falls keine überschrieben wurden + if temperature is None: + temperature = self.config.get("temperature", 0.2) + + if max_tokens is None: + max_tokens = self.config.get("max_tokens", 2000) + + # Anthropic API Payload erstellen + payload = { + "model": self.model_name, + "messages": formatted_messages, + "temperature": temperature, + "max_tokens": max_tokens + } + + response = await self.http_client.post( + self.api_url, + json=payload + ) + + if response.status_code != 200: + logger.error(f"Anthropic API-Fehler: {response.status_code} - {response.text}") + raise HTTPException(status_code=500, detail="Fehler bei der Kommunikation mit Anthropic API") + + # Antwort im Anthropic-Format in OpenAI-Format umwandeln + anthropic_response = response.json() + openai_formatted_response = self._convert_to_openai_format(anthropic_response) + + return openai_formatted_response + + except Exception as e: + logger.error(f"Fehler beim Aufruf der Anthropic API: {str(e)}") + raise HTTPException(status_code=500, detail=f"Fehler beim Aufruf der Anthropic API: {str(e)}") + + def _convert_to_anthropic_format(self, openai_messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]: + """ + Konvertiert Nachrichten vom OpenAI-Format ins Anthropic-Format. + + OpenAI verwendet: + [{"role": "system", "content": "..."}, + {"role": "user", "content": "..."}, + {"role": "assistant", "content": "..."}] + + Anthropic verwendet: + [{"role": "user", "content": "..."}, + {"role": "assistant", "content": "..."}] + + Anmerkung: Anthropic hat kein direktes System-Message-Äquivalent, + daher fügen wir System-Nachrichten in die erste User-Nachricht ein. + """ + anthropic_messages = [] + system_content = "" + + # Extrahiere zuerst alle System-Nachrichten + for msg in openai_messages: + if msg.get("role") == "system": + system_content += msg.get("content", "") + "\n\n" + + # Konvertiere die restlichen Nachrichten + for i, msg in enumerate(openai_messages): + role = msg.get("role") + content = msg.get("content", "") + + # System-Nachrichten überspringen (bereits extrahiert) + if role == "system": + continue + + # Für die erste User-Nachricht: System-Inhalte voranstellen, falls vorhanden + if role == "user" and system_content and not any(m.get("role") == "user" for m in anthropic_messages): + if isinstance(content, str): + content = system_content + content + elif isinstance(content, list): + # Wenn content ein Array ist (für Multimodal-Nachrichten) + text_parts = [] + for part in content: + if part.get("type") == "text": + text_parts.append(part) + + if text_parts: + text_parts[0]["text"] = system_content + text_parts[0].get("text", "") + + # Anthropic unterstützt nur "user" und "assistant" als Rollen + if role not in ["user", "assistant"]: + role = "user" + + anthropic_messages.append({"role": role, "content": content}) + + return anthropic_messages + + def _convert_to_openai_format(self, anthropic_response: Dict[str, Any]) -> Dict[str, Any]: + """ + Konvertiert eine Antwort vom Anthropic-Format ins OpenAI-Format. + """ + # Extrahiere Inhalt aus Anthropic-Antwort + content = "" + if "content" in anthropic_response: + if isinstance(anthropic_response["content"], list): + # Inhalt ist eine Liste von Teilen (bei neueren API-Versionen) + for part in anthropic_response["content"]: + if part.get("type") == "text": + content += part.get("text", "") + else: + # Direkter Inhalt als String (bei älteren API-Versionen) + content = anthropic_response["content"] + + # Erstelle OpenAI-formatierte Antwort + return { + "id": anthropic_response.get("id", ""), + "object": "chat.completion", + "created": anthropic_response.get("created", 0), + "model": anthropic_response.get("model", self.model_name), + "choices": [ + { + "message": { + "role": "assistant", + "content": content + }, + "index": 0, + "finish_reason": "stop" + } + ] + } + + async def analyze_image(self, image_data: Union[str, bytes], mime_type: str = None, prompt: str = "Describe this image") -> str: + """ + Analysiert ein Bild mit der OpenAI Vision API. + + Args: + image_data: Entweder ein Dateipfad (str) oder Bilddaten (bytes) + mime_type: Der MIME-Typ des Bildes (optional, nur für Binärdaten) + prompt: Der Prompt für die Analyse + + Returns: + Die Antwort der OpenAI Vision API als Text + """ + try: + # Unterscheide zwischen Dateipfad und Binärdaten + if isinstance(image_data, str): + # Es ist ein Dateipfad - importiere filehandling nur bei Bedarf + from modules import agentservice_filehandling as file_handler + base64_data, auto_mime_type = file_handler.encode_file_to_base64(image_data) + mime_type = mime_type or auto_mime_type + else: + # Es sind Binärdaten + import base64 + base64_data = base64.b64encode(image_data).decode('utf-8') + # MIME-Typ muss angegeben sein für Binärdaten + if not mime_type: + # Fallback auf generischen Bildtyp + mime_type = "image/png" + + # Bereite den Payload für die Vision API vor + messages = [ + { + "role": "user", + "content": [ + {"type": "text", "text": prompt}, + { + "type": "image_url", + "image_url": { + "url": f"data:{mime_type};base64,{base64_data}" + } + } + ] + } + ] + + # Verwende die bestehende call_api Funktion mit dem Vision-Modell + response = await self.call_api(messages) + + # Inhalt extrahieren und zurückgeben + return response["choices"][0]["message"]["content"] + + except Exception as e: + logger.error(f"Fehler bei der Bildanalyse: {str(e)}", exc_info=True) + return f"[Fehler bei der Bildanalyse: {str(e)}]" \ No newline at end of file diff --git a/gwserver/connectors/connector_aichat_openai.py b/gwserver/connectors/connector_aichat_openai.py new file mode 100644 index 00000000..373b17eb --- /dev/null +++ b/gwserver/connectors/connector_aichat_openai.py @@ -0,0 +1,148 @@ +import logging +import httpx +from typing import Dict, Any, List, Optional, Union +from fastapi import HTTPException +import configload + +# Logger konfigurieren +logger = logging.getLogger(__name__) + +# Konfigurationsdaten laden +def load_config_data(): + config = configload.load_config() + return { + "api_key": config.get('Connector_AiOpenai', 'API_KEY'), + "api_url": config.get('Connector_AiOpenai', 'API_URL'), + "model_name": config.get('Connector_AiOpenai', 'MODEL_NAME'), + "temperature": float(config.get('Connector_AiOpenai', 'TEMPERATURE')), + "max_tokens": int(config.get('Connector_AiOpenai', 'MAX_TOKENS')) + } + +class ChatService: + """ + Connector für die Kommunikation mit der OpenAI API. + """ + + def __init__(self): + # Konfiguration laden + self.config = load_config_data() + self.api_key = self.config["api_key"] + self.api_url = self.config["api_url"] + self.model_name = self.config["model_name"] + + # HttpClient für API-Aufrufe + self.http_client = httpx.AsyncClient( + timeout=120.0, # Längeres Timeout für komplexe Anfragen + headers={ + "Authorization": f"Bearer {self.api_key}", + "Content-Type": "application/json" + } + ) + + logger.info(f"OpenAI Connector initialisiert mit Modell: {self.model_name}") + + async def call_api(self, messages: List[Dict[str, Any]], temperature: float = None, max_tokens: int = None) -> str: + """ + Ruft die OpenAI API mit den gegebenen Nachrichten auf. + + Args: + messages: Liste von Nachrichten im OpenAI-Format (role, content) + temperature: Temperatur für die Antwortgenerierung (0.0-1.0) + max_tokens: Maximale Anzahl der Token in der Antwort + + Returns: + Die Antwort der OpenAI API + + Raises: + HTTPException: Bei Fehlern in der API-Kommunikation + """ + try: + # Verwende Parameter aus der Konfiguration, falls keine überschrieben wurden + if temperature is None: + temperature = self.config.get("temperature", 0.2) + + if max_tokens is None: + max_tokens = self.config.get("max_tokens", 2000) + + payload = { + "model": self.model_name, + "messages": messages, + "temperature": temperature, + "max_tokens": max_tokens + } + + response = await self.http_client.post( + self.api_url, + json=payload + ) + + if response.status_code != 200: + logger.error(f"OpenAI API-Fehler: {response.status_code} - {response.text}") + raise HTTPException(status_code=500, detail="Fehler bei der Kommunikation mit OpenAI API") + + response_json = response.json() + content = response_json["choices"][0]["message"]["content"] + return content + + except Exception as e: + logger.error(f"Fehler beim Aufruf der OpenAI API: {str(e)}") + raise HTTPException(status_code=500, detail=f"Fehler beim Aufruf der OpenAI API: {str(e)}") + + async def close(self): + """Schließt den HTTP-Client beim Beenden der Anwendung""" + await self.http_client.aclose() + + async def analyze_image(self, image_data: Union[str, bytes], mime_type: str = None, prompt: str = "Describe this image") -> str: + """ + Analysiert ein Bild mit der OpenAI Vision API. + + Args: + image_data: Entweder ein Dateipfad (str) oder Bilddaten (bytes) + mime_type: Der MIME-Typ des Bildes (optional, nur für Binärdaten) + prompt: Der Prompt für die Analyse + + Returns: + Die Antwort der OpenAI Vision API als Text + """ + try: + logger.debug("Starting image analysis...") + # Unterscheide zwischen Dateipfad und Binärdaten + if isinstance(image_data, str): + # Es ist ein Dateipfad - importiere filehandling nur bei Bedarf + from modules import agentservice_filehandling as file_handler + base64_data, auto_mime_type = file_handler.encode_file_to_base64(image_data) + mime_type = mime_type or auto_mime_type + else: + # Es sind Binärdaten + import base64 + base64_data = base64.b64encode(image_data).decode('utf-8') + # MIME-Typ muss angegeben sein für Binärdaten + if not mime_type: + # Fallback auf generischen Bildtyp + mime_type = "image/png" + + # Bereite den Payload für die Vision API vor + messages = [ + { + "role": "user", + "content": [ + {"type": "text", "text": prompt}, + { + "type": "image_url", + "image_url": { + "url": f"data:{mime_type};base64,{base64_data}" + } + } + ] + } + ] + + # Verwende die bestehende call_api Funktion mit dem Vision-Modell + response = await self.call_api(messages) + + # Inhalt extrahieren und zurückgeben + return response["choices"][0]["message"]["content"] + + except Exception as e: + logger.error(f"Fehler bei der Bildanalyse: {str(e)}", exc_info=True) + return f"[Fehler bei der Bildanalyse: {str(e)}]" \ No newline at end of file diff --git a/gwserver/connector_db_json.py b/gwserver/connectors/connector_db_json.py similarity index 98% rename from gwserver/connector_db_json.py rename to gwserver/connectors/connector_db_json.py index 41563b22..a0ecfd36 100644 --- a/gwserver/connector_db_json.py +++ b/gwserver/connectors/connector_db_json.py @@ -66,7 +66,7 @@ class DatabaseConnector: self.user_id = self._user_id logger.info(f"DatabaseConnector initialisiert für Verzeichnis: {db_folder}") - logger.info(f"Kontext: mandate_id={self.mandate_id}, user_id={self.user_id}") + logger.debug(f"Kontext: mandate_id={self.mandate_id}, user_id={self.user_id}") def _initialize_system_table(self): """Initialisiert die System-Tabelle, falls sie noch nicht existiert.""" @@ -114,13 +114,13 @@ class DatabaseConnector: # Wenn die Tabelle bereits im Cache ist, verwende den Cache if table in self._tables_cache: - logger.info(f"Lade Tabelle {table} aus Cache") + # logger.info(f"Lade Tabelle {table} aus Cache") return self._tables_cache[table] # Ansonsten lade die Datei try: if os.path.exists(path): - logger.info(f"Lade Tabelle {table} aus JSON {path}") + # logger.info(f"Lade Tabelle {table} aus JSON {path}") with open(path, 'r', encoding='utf-8') as f: data = json.load(f) self._tables_cache[table] = data diff --git a/gwserver/connector_db_mysql.py b/gwserver/connectors/connector_db_mysql.py similarity index 100% rename from gwserver/connector_db_mysql.py rename to gwserver/connectors/connector_db_mysql.py diff --git a/gwserver/modules/agentservice_agent_analyst.py b/gwserver/modules/agentservice_agent_analyst.py new file mode 100644 index 00000000..9d097e04 --- /dev/null +++ b/gwserver/modules/agentservice_agent_analyst.py @@ -0,0 +1,189 @@ +""" +Datenanalyst-Agent für die Analyse und Interpretation von Daten. +""" + +import logging +from typing import List, Dict, Any, Optional +from modules.agentservice_base import BaseAgent +from connectors.connector_aichat_openai import ChatService + +logger = logging.getLogger(__name__) + +class AnalystAgent(BaseAgent): + """Agent für die Analyse und Interpretation von Daten""" + + _instance = None + + @classmethod + def get_instance(cls): + """Gibt eine Singleton-Instanz zurück""" + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def __init__(self): + """Initialisiert den Datenanalyst-Agenten""" + super().__init__() + self.id = "analyst_agent" + self.name = "Datenanalyst" + self.type = "analyzer" + self.description = "Analysiert und interpretiert Daten" + self.capabilities = "Datenanalyse, Mustererkennung, Statistik und Bewertung" + self.instructions = """ + Du bist der Datenanalyseagent. Deine Aufgabe: + 1. Vorliegende Daten untersuchen und interpretieren + 2. Erkenntnisse aus Informationen gewinnen + 3. Trends identifizieren und Zusammenhänge prüfen + 4. Daten visualisieren und Konzepte erklären + 5. Datenqualität bewerten und Handlungsempfehlungen geben + """ + + def get_prompt(self, message_context: Dict[str, Any]) -> str: + """ + Generiert einen angepassten Prompt für den Datenanalysten. + + Args: + message_context: Kontext der Nachricht + + Returns: + Formatierter Prompt für den Datenanalysten + """ + # Basis-Prompt + prompt = f""" + Du bist {self.name}, ein {self.type} Agent. + + {self.description} + + Fähigkeiten: {self.capabilities} + + {self.instructions} + + Analysiere die vorliegenden Daten. Präsentiere klar strukturierte Ergebnisse + mit einer Zusammenfassung, Detailanalyse und Handlungsempfehlungen. + + Formatiere mit [STATUS: ERGEBNIS/TEILWEISE/PLAN] am Ende. + """ + + # Dateitypspezifische Anweisungen hinzufügen (verkürzt) + document_types = self._get_document_types(message_context) + + if "csv" in document_types or "excel" in document_types: + prompt += "\nTABELLENDATEN: Identifiziere wichtige Spalten, Korrelationen und Trends." + + if "pdf" in document_types or "doc" in document_types: + prompt += "\nTEXTDATEN: Extrahiere zentrale Fakten und Schlüsselthemen." + + if "image" in document_types: + prompt += "\nBILDDATEN: Beschreibe und interpretiere dargestellte Informationen." + + return prompt.strip() + + def _get_document_types(self, message_context: Dict[str, Any]) -> List[str]: + """ + Extrahiert die Dateitypen aus dem Nachrichtenkontext. + + Args: + message_context: Kontext der Nachricht + + Returns: + Liste der Dateitypen + """ + document_types = [] + + # Versuche Dokumente aus dem Kontext zu extrahieren + documents = message_context.get("documents", []) + + for doc in documents: + source = doc.get("source", {}) + name = source.get("name", "").lower() + content_type = source.get("content_type", "").lower() + + # Dateityp aus Namen oder Content-Type ableiten + if name.endswith(".csv") or "csv" in content_type: + document_types.append("csv") + elif name.endswith((".xls", ".xlsx")) or "excel" in content_type or "spreadsheet" in content_type: + document_types.append("excel") + elif name.endswith(".pdf") or "pdf" in content_type: + document_types.append("pdf") + elif name.endswith((".doc", ".docx")) or "word" in content_type: + document_types.append("doc") + elif name.endswith((".jpg", ".jpeg", ".png", ".gif")) or "image" in content_type: + document_types.append("image") + + return document_types + + async def process_message(self, message: Dict[str, Any], context: Dict[str, Any] = None) -> Dict[str, Any]: + """ + Verarbeitet eine Nachricht und führt eine Datenanalyse durch. + + Args: + message: Die zu verarbeitende Nachricht + context: Zusätzlicher Kontext (optional) + + Returns: + Die generierte Antwort mit der Datenanalyse + """ + try: + # Prompt generieren + message_context = {"documents": context.get("documents", [])} if context else {} + prompt = self.get_prompt(message_context) + + # OpenAI ChatService initialisieren + chat_service = ChatService() + + # Nachrichten für die API vorbereiten + messages = [ + {"role": "system", "content": prompt}, + {"role": "user", "content": message.get("content", "")} + ] + + # Kontext-Nachrichten hinzufügen, falls vorhanden + if context and "history" in context: + for history_item in context["history"]: + messages.append({ + "role": history_item.get("role", "user"), + "content": history_item.get("content", "") + }) + + # API aufrufen + response_content = await chat_service.call_api(messages) + + # Verbindung schließen + await chat_service.close() + + # Antwort-Objekt erstellen + analysis_response = { + "role": "assistant", + "content": response_content, + "agent_type": self.type + } + + # Extrahiere den Status aus der Antwort und aktualisiere den Inhalt + content, status = self.extract_status(analysis_response["content"]) + analysis_response["content"] = content + + # Setze den Status im Kontext, falls vorhanden + if context is not None: + context["status"] = status + + return analysis_response + + except Exception as e: + logger.error(f"Fehler bei der Verarbeitung der Anfrage: {str(e)}", exc_info=True) + + # Fehlerantwort zurückgeben + return { + "role": "assistant", + "content": f"Bei der Datenanalyse ist ein Fehler aufgetreten: {str(e)}", + "agent_type": self.type + } + +# Singleton-Instanz +_analyst_agent = None + +def get_analyst_agent(): + """Gibt eine Singleton-Instanz des Datenanalyst-Agenten zurück""" + global _analyst_agent + if _analyst_agent is None: + _analyst_agent = AnalystAgent() + return _analyst_agent \ No newline at end of file diff --git a/gwserver/modules/agentservice_agent_coder.py b/gwserver/modules/agentservice_agent_coder.py new file mode 100644 index 00000000..5730efee --- /dev/null +++ b/gwserver/modules/agentservice_agent_coder.py @@ -0,0 +1,233 @@ +""" +Coder-Agent für die Entwicklung und Implementierung von Code. +""" + +import logging +from typing import List, Dict, Any, Optional +from modules.agentservice_base import BaseAgent + +logger = logging.getLogger(__name__) + +class CoderAgent(BaseAgent): + """Agent für die Entwicklung und Implementierung von Code""" + + _instance = None + + @classmethod + def get_instance(cls): + """Gibt eine Singleton-Instanz zurück""" + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def __init__(self): + """Initialisiert den Coder-Agenten""" + super().__init__() + self.id = "coder_agent" + self.name = "Entwickler" + self.type = "coder" + self.description = "Programmiert und führt Code aus" + self.capabilities = "Programmierung, Softwareentwicklung, technische Problemlösung und Implementierung von Algorithmen" + self.instructions = """ + Du bist der Codeentwicklungsagent, ein Spezialist für die Erstellung von Softwarelösungen und technischen Implementierungen. Deine Aufgabe ist es: + + 1. Technische Anforderungen in funktionierenden, effizienten Code zu übersetzen + 2. Geeignete Programmiersprachen, Frameworks und Bibliotheken für spezifische Aufgaben auszuwählen + 3. Algorithmen und Datenstrukturen für die optimale Lösung von Problemen zu entwickeln + 4. Lesbaren, gut dokumentierten und wartbaren Code zu schreiben + 5. Sicherheitsaspekte und Best Practices in der Softwareentwicklung zu berücksichtigen + 6. Potenzielle technische Schwierigkeiten vorherzusehen und Lösungen vorzuschlagen + 7. APIs und Integrationen mit anderen Systemen zu konzipieren und implementieren + + Bei der Präsentation deiner Softwarelösungen: + - Erkläre zunächst den Lösungsansatz und die gewählte Technologie + - Stelle den Code in logischen, gut kommentierten Abschnitten dar + - Erläutere kritische oder komplexe Teile des Codes im Detail + - Beschreibe Annahmen und getroffene Designentscheidungen + - Gib Hinweise zur Installation, Konfiguration und Verwendung + - Erwähne mögliche Erweiterungen und Verbesserungsmöglichkeiten + - Adressiere potenzielle Einschränkungen oder bekannte Probleme + + Dein Code sollte nicht nur funktional, sondern auch effizient, sicher und gut strukturiert sein. Achte auf Lesbarkeit, Performance und Skalierbarkeit deiner Lösungen. Verwende moderne Entwicklungspraktiken und orientiere dich an etablierten Standards der jeweiligen Programmiersprache. + """ + + def get_prompt(self, message_context: Dict[str, Any]) -> str: + """ + Generiert einen angepassten Prompt für den Coder-Agenten. + + Args: + message_context: Kontext der Nachricht + + Returns: + Formatierter Prompt für den Coder-Agenten + """ + # Basis-Prompt vom BaseAgent holen + base_prompt = super().get_prompt(message_context) + + # Zusätzliche Anweisungen für Coding + coding_instructions = """ + CODING-RICHTLINIEN: + + 1. Wähle die geeignete Programmiersprache basierend auf den Anforderungen + 2. Verfolge einen modularen, gut strukturierten Ansatz + 3. Füge ausreichend Kommentare und Dokumentation hinzu + 4. Beachte Sicherheitsaspekte und Best Practices + 5. Behandle mögliche Fehler und Ausnahmefälle + 6. Stelle sicher, dass der Code vollständig und ausführbar ist + 7. Teste deine Implementierung mit Beispieldaten + + Für jede Code-Implementierung: + - Beginne mit einer kurzen Erklärung des Lösungsansatzes + - Strukturiere den Code in logische Funktionen/Klassen + - Erkläre komplexe Teile durch inline-Kommentare + - Gib am Ende Hinweise zur Verwendung oder Erweiterung + """ + + # Prüfen, ob bestimmte Dateitypen vorhanden sind und spezifische Anweisungen hinzufügen + document_types = self._get_document_types(message_context) + + file_specific_instructions = "" + + if "csv" in document_types or "excel" in document_types: + file_specific_instructions += """ + DATENVERARBEITUNG: + - Verwende geeignete Bibliotheken für Datenverarbeitung (pandas, numpy, etc.) + - Berücksichtige Speichereffizienz und Performance bei großen Datensätzen + - Implementiere robustes Fehler-Handling für verschiedene Datenformate + """ + + if "py" in document_types or "js" in document_types or "java" in document_types: + file_specific_instructions += """ + CODE-ANALYSE: + - Analysiere den vorhandenen Code auf Struktur und Funktionalität + - Identifiziere Verbesserungspotenziale und mögliche Fehler + - Schlage konkrete Refactoring-Maßnahmen vor + - Erweitere den Code gemäß den neuen Anforderungen + """ + + # Task aus dem Kontext extrahieren + task = message_context.get("task", "") + task_instructions = f"\nAKTUELLE AUFGABE:\n{task}\n" if task else "" + + # Vollständigen Prompt zusammenbauen + complete_prompt = f"{base_prompt}\n\n{coding_instructions}\n\n{file_specific_instructions}\n{task_instructions}" + + return complete_prompt.strip() + + def _get_document_types(self, message_context: Dict[str, Any]) -> List[str]: + """ + Extrahiert die Dateitypen aus dem Nachrichtenkontext. + + Args: + message_context: Kontext der Nachricht + + Returns: + Liste der Dateitypen + """ + document_types = [] + + # Versuche Dokumente aus dem Kontext zu extrahieren + documents = message_context.get("documents", []) + + for doc in documents: + source = doc.get("source", {}) + name = source.get("name", "").lower() + content_type = source.get("content_type", "").lower() + + # Dateityp aus Namen oder Content-Type ableiten + if name.endswith(".py"): + document_types.append("py") + elif name.endswith((".js", ".ts")): + document_types.append("js") + elif name.endswith((".java", ".kt")): + document_types.append("java") + elif name.endswith(".csv") or "csv" in content_type: + document_types.append("csv") + elif name.endswith((".xls", ".xlsx")) or "excel" in content_type: + document_types.append("excel") + + return document_types + + async def process_message(self, message: Dict[str, Any], context: Dict[str, Any] = None) -> Dict[str, Any]: + """ + Verarbeitet eine Nachricht und generiert Code. + + Args: + message: Die zu verarbeitende Nachricht + context: Zusätzlicher Kontext + + Returns: + Die generierte Antwort mit Code + """ + # In einer realen Implementierung würde hier die Verbindung zum KI-Service hergestellt + # und die eigentliche Code-Generierung durchgeführt werden. + + # Als Beispiel geben wir eine Standardantwort zurück + coding_response = { + "role": "assistant", + "content": f"""Ich habe als {self.name} die Anforderungen analysiert und folgenden Code entwickelt: + +```python +def process_data(input_file, output_file): + \"\"\" + Verarbeitet Daten aus einer Eingabedatei und speichert die Ergebnisse. + + Args: + input_file: Pfad zur Eingabedatei + output_file: Pfad zur Ausgabedatei + \"\"\" + import pandas as pd + + # Daten einlesen + df = pd.read_csv(input_file) + + # Daten verarbeiten + # Hier würde die eigentliche Datenverarbeitung stattfinden + processed_df = df.copy() + + # Beispiel: Spalten filtern und transformieren + if 'data' in processed_df.columns: + processed_df['transformed'] = processed_df['data'] * 2 + + # Ergebnis speichern + processed_df.to_csv(output_file, index=False) + + return len(processed_df) + +# Beispielaufruf +if __name__ == "__main__": + result = process_data("input.csv", "output.csv") + print(f"Verarbeitet: result Datensätze") +``` + +Der Code liest eine CSV-Datei ein, führt eine einfache Transformation durch und speichert das Ergebnis. +Die Hauptfunktion `process_data` ist modular gestaltet und kann leicht erweitert werden. + +Zur Verwendung: +1. Stelle sicher, dass pandas installiert ist (`pip install pandas`) +2. Passe die Dateipfade im Beispielaufruf an +3. Erweitere die Verarbeitung je nach deinen spezifischen Anforderungen + +[STATUS: ERGEBNIS]""", + "agent_type": self.type + } + + # Extrahiere den Status aus der Antwort und aktualisiere den Inhalt + content, status = self.extract_status(coding_response["content"]) + coding_response["content"] = content + + # Setze den Status im Kontext, falls vorhanden + if context is not None: + context["status"] = status + + return coding_response + +# Singleton-Instanz +_coder_agent = None + +def get_coder_agent(): + """Gibt eine Singleton-Instanz des Coder-Agenten zurück""" + global _coder_agent + if _coder_agent is None: + _coder_agent = CoderAgent() + return _coder_agent \ No newline at end of file diff --git a/gwserver/modules/agentservice_agent_documentation.py b/gwserver/modules/agentservice_agent_documentation.py new file mode 100644 index 00000000..d2d635e4 --- /dev/null +++ b/gwserver/modules/agentservice_agent_documentation.py @@ -0,0 +1,420 @@ +""" +Dokumentations-Agent für die Erstellung von Dokumentation, Berichten und strukturierten Inhalten. +Verwendet einen strukturierten mehrstufigen Prozess zur Erstellung hochwertiger Dokumentation. +""" + +import logging +from typing import List, Dict, Any, Optional, Tuple +from modules.agentservice_base import BaseAgent +from connectors.connector_aichat_openai import ChatService + +logger = logging.getLogger(__name__) + +class DocumentationAgent(BaseAgent): + """Agent für die Erstellung von Dokumentation und strukturierten Inhalten""" + + _instance = None + + @classmethod + def get_instance(cls): + """Gibt eine Singleton-Instanz zurück""" + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def __init__(self): + """Initialisiert den Dokumentations-Agenten""" + super().__init__() + self.id = "documentation_agent" + self.name = "Dokumentation" + self.type = "documentation" + self.description = "Erstellt Dokumentation und strukturierte Inhalte" + self.capabilities = "Berichte, Dokumentation, Zusammenfassungen und Erklärungen" + self.instructions = """ + Du bist der Dokumentations-Agent. Deine Aufgabe: + 1. Komplexe Informationen in klare, strukturierte Dokumente umsetzen + 2. Verschiedene Dokumentformate erstellen + 3. Informationen aus verschiedenen Quellen strukturieren + 4. Technische Konzepte verständlich erklären + 5. Konsistente Formatierung sicherstellen + """ + # Chat-Service initialisieren + self.chat_service = None + + def get_base_prompt(self, document_type: str = "") -> str: + """ + Generiert einen Basis-Prompt für den Dokumentations-Agenten. + + Args: + document_type: Typ des zu erstellenden Dokuments + + Returns: + Basis-Prompt für den Dokumentations-Agenten + """ + # Basis-Prompt + prompt = f""" + Du bist {self.name}, ein {self.type} Agent. + + {self.description} + + Fähigkeiten: {self.capabilities} + + {self.instructions} + """ + + # Dokumenttyp-spezifische Anweisungen hinzufügen + if document_type: + prompt += self._get_document_type_instructions(document_type) + + return prompt.strip() + + def _get_document_type_instructions(self, document_type: str) -> str: + """ + Gibt spezifische Anweisungen für einen bestimmten Dokumenttyp zurück. + + Args: + document_type: Typ des Dokuments + + Returns: + Spezifische Anweisungen für den Dokumenttyp + """ + document_type = document_type.lower() + + if "handbuch" in document_type or "anleitung" in document_type or "guide" in document_type: + return "\n\nHANDBUCH: Beginne mit Zweckbeschreibung, strukturiere in logische Schritte, verwende direkte Anweisungen." + elif "bericht" in document_type or "report" in document_type: + return "\n\nBERICHT: Beginne mit Executive Summary, strukturiere in thematische Abschnitte, halte professionellen Ton." + elif "prozess" in document_type or "process" in document_type: + return "\n\nPROZESS: Beschreibe Zweck, Ziele, Beteiligte, sequenzielle Schritte, Inputs/Outputs und Verantwortlichkeiten." + elif "präsentation" in document_type or "presentation" in document_type: + return "\n\nPRÄSENTATION: Klare Hauptpunkte, visuelle Elemente, Einleitung-Hauptteil-Schluss Struktur." + else: + return "\n\nDOKUMENT: Erstelle ein gut strukturiertes Dokument mit klarer Gliederung und präziser Sprache." + + def _detect_document_type(self, message: str) -> str: + """ + Erkennt den Dokumenttyp aus der Nachricht. + + Args: + message: Nachricht des Benutzers + + Returns: + Erkannter Dokumenttyp + """ + message = message.lower() + + if "handbuch" in message or "anleitung" in message or "guide" in message: + return "handbuch" + elif "bericht" in message or "report" in message: + return "bericht" + elif "prozess" in message or "process" in message or "ablauf" in message: + return "prozess" + elif "präsentation" in message or "presentation" in message or "folien" in message: + return "präsentation" + else: + return "dokument" + + async def generate_title(self, task: str, document_type: str) -> str: + """ + Generiert einen Titel für das Dokument. + + Args: + task: Die Aufgabe/Anfrage + document_type: Typ des Dokuments + + Returns: + Generierter Titel + """ + prompt = f""" + Erstelle einen prägnanten, professionellen Titel für folgendes {document_type.capitalize()}: + + AUFTRAG: {task} + + Gib NUR den Titel zurück, ohne weitere Erklärungen oder Formatierungen. + """ + + messages = [ + {"role": "system", "content": "Du bist ein Experte für die Erstellung von Dokumenttiteln."}, + {"role": "user", "content": prompt} + ] + + title = await self.chat_service.call_api(messages) + + # Bereinige den Titel von Anführungszeichen und Überschriften-Symbolen + title = title.strip('"\'#*- \n\t') + + return title + + async def generate_summary(self, task: str, document_type: str, title: str) -> str: + """ + Generiert eine Zusammenfassung für das Dokument. + + Args: + task: Die Aufgabe/Anfrage + document_type: Typ des Dokuments + title: Titel des Dokuments + + Returns: + Generierte Zusammenfassung + """ + prompt = f""" + Erstelle eine prägnante Zusammenfassung für folgendes Dokument: + + TITEL: {title} + TYP: {document_type.capitalize()} + AUFTRAG: {task} + + Die Zusammenfassung soll einen Überblick über den Zweck und die Hauptinhalte des Dokuments geben. + Sie sollte etwa 3-5 Sätze umfassen und als eigenständiger Abschnitt funktionieren. + """ + + messages = [ + {"role": "system", "content": "Du bist ein Experte für die Erstellung prägnanter Dokumentzusammenfassungen."}, + {"role": "user", "content": prompt} + ] + + summary = await self.chat_service.call_api(messages) + + return summary.strip() + + async def generate_toc_with_prompts(self, task: str, document_type: str, title: str, summary: str) -> Dict[str, str]: + """ + Generiert ein Inhaltsverzeichnis mit Prompts für die einzelnen Kapitel. + + Args: + task: Die Aufgabe/Anfrage + document_type: Typ des Dokuments + title: Titel des Dokuments + summary: Zusammenfassung des Dokuments + + Returns: + Dict mit Kapiteltiteln als Schlüssel und Prompts als Werte + """ + prompt = f""" + Erstelle ein strukturiertes Inhaltsverzeichnis für folgendes Dokument: + + TITEL: {title} + TYP: {document_type.capitalize()} + AUFTRAG: {task} + ZUSAMMENFASSUNG: {summary} + + Für jedes Kapitel gib auch einen kurzen Prompt an, der beschreibt, was in diesem Kapitel behandelt werden soll. + Formatiere deine Antwort als JSON-Objekt mit folgendem Format: + {{ + "Kapitel 1: Titel": "Prompt für Kapitel 1", + "Kapitel 2: Titel": "Prompt für Kapitel 2", + ... + }} + + Beschränke dich auf 5-7 sinnvolle Kapitel, die das Thema umfassend behandeln. + """ + + messages = [ + {"role": "system", "content": "Du bist ein Experte für die Strukturierung von Dokumenten und die Erstellung von Inhaltsverzeichnissen."}, + {"role": "user", "content": prompt} + ] + + toc_response = await self.chat_service.call_api(messages) + + # JSON aus der Antwort extrahieren + import json + import re + + # Markdown-Code-Blöcke entfernen, falls vorhanden + toc_response = re.sub(r'```json\s*|\s*```', '', toc_response) + + try: + toc_with_prompts = json.loads(toc_response) + return toc_with_prompts + except json.JSONDecodeError as e: + logger.error(f"Fehler beim Parsen des Inhaltsverzeichnisses: {str(e)}") + logger.error(f"Rohe Antwort: {toc_response}") + # Notfall-Fallback + return { + "1. Einleitung": "Einführung in das Thema und Überblick", + "2. Hauptteil": "Hauptinhalte des Dokuments", + "3. Schlussfolgerung": "Zusammenfassung und nächste Schritte" + } + + async def generate_chapter_content(self, chapter_title: str, chapter_prompt: str, + task: str, document_type: str, title: str, summary: str) -> str: + """ + Generiert den Inhalt für ein bestimmtes Kapitel. + + Args: + chapter_title: Titel des Kapitels + chapter_prompt: Prompt für das Kapitel + task: Die Aufgabe/Anfrage + document_type: Typ des Dokuments + title: Titel des Dokuments + summary: Zusammenfassung des Dokuments + + Returns: + Generierter Kapitelinhalt + """ + prompt = f""" + Erstelle detaillierten Inhalt für folgendes Kapitel eines {document_type}s: + + DOKUMENT-TITEL: {title} + AUFGABE: {task} + KAPITEL: {chapter_title} + ANWEISUNG FÜR DIESES KAPITEL: {chapter_prompt} + + Der Inhalt sollte detailliert, informativ und gut strukturiert sein. + Verwende bei Bedarf Unterüberschriften, Aufzählungen und Tabellen zur besseren Strukturierung. + Der Inhalt sollte direkt mit dem Kapiteltext beginnen, ohne den Kapiteltitel zu wiederholen. + """ + + messages = [ + {"role": "system", "content": "Du bist ein Experte für die Erstellung hochwertiger Dokumentationsinhalte."}, + {"role": "user", "content": prompt} + ] + + chapter_content = await self.chat_service.call_api(messages) + + return chapter_content.strip() + + def _format_final_document(self, title: str, summary: str, toc: Dict[str, str], chapter_contents: Dict[str, str]) -> str: + """ + Formatiert das endgültige Dokument aus allen Teilen. + + Args: + title: Titel des Dokuments + summary: Zusammenfassung + toc: Inhaltsverzeichnis (Dict mit Kapiteltiteln als Schlüssel) + chapter_contents: Kapitelinhalte (Dict mit Kapiteltiteln als Schlüssel und Inhalten als Werte) + + Returns: + Formatiertes Dokument + """ + # Titel formatieren + doc = f"# {title}\n\n" + + # Zusammenfassung hinzufügen + doc += f"## Zusammenfassung\n\n{summary}\n\n" + + # Inhaltsverzeichnis hinzufügen + doc += "## Inhaltsverzeichnis\n\n" + for idx, chapter in enumerate(toc.keys(), 1): + # Extrahiere den reinen Kapitelnamen (entferne Nummerierung, falls vorhanden) + clean_chapter = chapter + if chapter.strip().startswith(('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')) and '. ' in chapter: + clean_chapter = chapter.split('. ', 1)[1] + + doc += f"{idx}. {clean_chapter}\n" + doc += "\n" + + # Kapitelinhalte hinzufügen + for idx, (chapter, content) in enumerate(chapter_contents.items(), 1): + # Extrahiere den reinen Kapitelnamen (entferne Nummerierung, falls vorhanden) + clean_chapter = chapter + if chapter.strip().startswith(('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')) and '. ' in chapter: + clean_chapter = chapter.split('. ', 1)[1] + + doc += f"## {idx}. {clean_chapter}\n\n{content}\n\n" + + # Metadaten hinzufügen + doc += "---\n\n" + doc += f"**Erstellt durch:** {self.name}\n" + + return doc + + async def process_message(self, message: Dict[str, Any], context: Dict[str, Any] = None) -> Dict[str, Any]: + """ + Verarbeitet eine Nachricht und erstellt Dokumentation in einem strukturierten Prozess. + + Args: + message: Die zu verarbeitende Nachricht + context: Zusätzlicher Kontext + + Returns: + Die generierte Dokumentation + """ + try: + # Chat-Service initialisieren, falls noch nicht geschehen + if self.chat_service is None: + self.chat_service = ChatService() + + # Task aus der Nachricht extrahieren + task = message.get("content", "") + if context and "task" in context: + task = context["task"] + + # Dokumenttyp erkennen + document_type = self._detect_document_type(task) + + logger.info(f"Starte Dokumentationserstellung für Typ: {document_type}") + + # Schritt 1: Titel generieren + title = await self.generate_title(task, document_type) + logger.info(f"Titel generiert: {title}") + + # Schritt 2: Zusammenfassung generieren + summary = await self.generate_summary(task, document_type, title) + logger.info("Zusammenfassung generiert") + + # Schritt 3: Inhaltsverzeichnis mit Prompts generieren + toc_with_prompts = await self.generate_toc_with_prompts(task, document_type, title, summary) + logger.info(f"Inhaltsverzeichnis mit {len(toc_with_prompts)} Kapiteln generiert") + + # Schritt 4: Kapitelinhalte in einer Schleife generieren + chapter_contents = {} + for chapter_title, chapter_prompt in toc_with_prompts.items(): + logger.info(f"Generiere Inhalt für Kapitel: {chapter_title}") + content = await self.generate_chapter_content( + chapter_title, chapter_prompt, task, document_type, title, summary + ) + chapter_contents[chapter_title] = content + + # Schritt 5: Dokument zusammenführen + final_document = self._format_final_document(title, summary, toc_with_prompts, chapter_contents) + logger.info(f"Dokument fertiggestellt mit {len(final_document)} Zeichen") + + # Schritt 6: Antwort zurückgeben + documentation_response = { + "role": "assistant", + "content": f"{final_document}\n\n[STATUS: ERGEBNIS]", + "agent_type": self.type + } + + # Extrahiere den Status aus der Antwort und aktualisiere den Inhalt + content, status = self.extract_status(documentation_response["content"]) + documentation_response["content"] = content + + # Setze den Status im Kontext, falls vorhanden + if context is not None: + context["status"] = status + + # Chat-Service schließen + await self.chat_service.close() + self.chat_service = None + + return documentation_response + + except Exception as e: + logger.error(f"Fehler bei der Dokumentationserstellung: {str(e)}", exc_info=True) + + # Chat-Service schließen bei Fehler + if self.chat_service: + try: + await self.chat_service.close() + except: + pass + self.chat_service = None + + # Fehlerantwort zurückgeben + return { + "role": "assistant", + "content": f"Bei der Erstellung der Dokumentation ist ein Fehler aufgetreten: {str(e)}", + "agent_type": self.type + } + +# Singleton-Instanz +_documentation_agent = None + +def get_documentation_agent(): + """Gibt eine Singleton-Instanz des Dokumentations-Agenten zurück""" + global _documentation_agent + if _documentation_agent is None: + _documentation_agent = DocumentationAgent() + return _documentation_agent \ No newline at end of file diff --git a/gwserver/modules/agentservice_agent_sharepoint.py b/gwserver/modules/agentservice_agent_sharepoint.py new file mode 100644 index 00000000..9d2f3108 --- /dev/null +++ b/gwserver/modules/agentservice_agent_sharepoint.py @@ -0,0 +1,173 @@ +""" +SharePoint-Agent für die Interaktion mit SharePoint-Ressourcen und Dokumenten. +""" + +import logging +from typing import List, Dict, Any, Optional +from modules.agentservice_base import BaseAgent + +logger = logging.getLogger(__name__) + +class SharepointAgent(BaseAgent): + """Agent für den Zugriff auf und die Arbeit mit SharePoint-Ressourcen""" + + _instance = None + + @classmethod + def get_instance(cls): + """Gibt eine Singleton-Instanz zurück""" + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def __init__(self): + """Initialisiert den SharePoint-Agenten""" + super().__init__() + self.id = "sharepoint_agent" + self.name = "SharePoint-Agent" + self.type = "sharepoint" + self.description = "Zugriff auf und Arbeit mit SharePoint-Ressourcen" + self.capabilities = "Suche und Abruf von Dokumenten aus SharePoint, Dokumentenverwaltung, Metadaten-Extraktion und Integration von SharePoint-Inhalten" + self.instructions = """ + Du bist der SharePoint-Agent, ein Spezialist für die Interaktion mit Microsoft SharePoint. Deine Aufgabe ist es: + + 1. SharePoint-Dokumente und -Ressourcen zu durchsuchen und abzurufen + 2. Metadaten aus SharePoint-Dokumenten zu extrahieren und zu analysieren + 3. Strukturierte Informationen aus SharePoint-Bibliotheken zu sammeln + 4. Dokumente basierend auf Metadaten zu filtern und zu organisieren + 5. Inhalte aus verschiedenen SharePoint-Quellen zu integrieren und zusammenzuführen + 6. Informationen aus SharePoint-Listen und -Dokumentbibliotheken zu extrahieren + 7. Zusammenfassungen und Analysen von SharePoint-Inhalten zu erstellen + + Bei der Darstellung deiner Ergebnisse: + - Strukturiere die Informationen klar und übersichtlich + - Gib den Ursprung und die Metadaten der Dokumente an + - Zeige Beziehungen zwischen verschiedenen Dokumenten und Ressourcen auf + - Hebe wichtige Erkenntnisse und Muster hervor + - Biete Kontext und Relevanz für die gefundenen Informationen + """ + + def get_prompt(self, message_context: Dict[str, Any]) -> str: + """ + Generiert einen angepassten Prompt für den SharePoint-Agenten. + + Args: + message_context: Kontext der Nachricht + + Returns: + Formatierter Prompt für den SharePoint-Agenten + """ + # Basis-Prompt vom BaseAgent holen + base_prompt = super().get_prompt(message_context) + + # Zusätzliche Anweisungen für SharePoint-Interaktion + sharepoint_instructions = """ + SHAREPOINT-INTERAKTIONS-RICHTLINIEN: + + 1. Präzisiere die Suchkriterien für SharePoint-Ressourcen + 2. Identifiziere relevante Bibliotheken, Listen und Standorte + 3. Definiere benötigte Metadaten und Inhalte + 4. Berücksichtige Berechtigungsanforderungen + 5. Priorisiere aktuelle und relevante Dokumente + 6. Stelle eine strukturierte Darstellung der Ergebnisse sicher + + Für eine gute SharePoint-Integration: + - Gib detaillierte Pfade und Standorte an + - Berücksichtige verschiedene Dokumenttypen und Formate + - Zeige Metadaten und Dokumenteigenschaften + - Biete Kontext zu den gefundenen Ressourcen + - Berücksichtige Versionsinformationen + """ + + # Task aus dem Kontext extrahieren + task = message_context.get("task", "") + task_instructions = f"\nSHAREPOINT-AUFTRAG:\n{task}\n" if task else "" + + # Vollständigen Prompt zusammenbauen + complete_prompt = f"{base_prompt}\n\n{sharepoint_instructions}\n{task_instructions}" + + return complete_prompt.strip() + + async def process_message(self, message: Dict[str, Any], context: Dict[str, Any] = None) -> Dict[str, Any]: + """ + Verarbeitet eine Nachricht und interagiert mit SharePoint. + + Args: + message: Die zu verarbeitende Nachricht + context: Zusätzlicher Kontext + + Returns: + Die generierte Antwort mit SharePoint-Inhalten + """ + # Hier würde die tatsächliche Interaktion mit SharePoint stattfinden + # In der finalen Implementierung würde ein SharePoint-Connector verwendet werden + + # Als Beispiel geben wir eine Standardantwort zurück + sharepoint_response = { + "role": "assistant", + "content": f"""Ich habe als {self.name} die SharePoint-Ressourcen durchsucht und folgende Ergebnisse gefunden: + +## SharePoint-Suchergebnisse + +Basierend auf deiner Anfrage habe ich folgende relevante Dokumente identifiziert: + +### Dokumente +1. **Projektplan_2025.docx** (Letzte Änderung: 15.03.2025) + - Standort: Projekte/Strategische Planung + - Autor: Maria Schmidt + - Schlüsselinhalt: Zeitplan für Q2-Q4 2025, Ressourcenplanung, Meilensteine + +2. **Marktanalyse_Q1_2025.pptx** (Letzte Änderung: 22.02.2025) + - Standort: Marketing/Marktforschung + - Autor: Thomas Müller + - Schlüsselinhalt: Aktuelle Markttrends, Wettbewerbsanalyse, Chancen und Risiken + +3. **Budgetplanung_2025.xlsx** (Letzte Änderung: 01.03.2025) + - Standort: Finanzen/Planung + - Autor: Sarah Weber + - Schlüsselinhalt: Detaillierte Budgetaufschlüsselung nach Abteilungen und Quartalen + +### SharePoint-Listen +1. **Projektstatusliste** + - 12 Einträge mit relevanten Projektstatusinformationen + - Letzte Aktualisierung: 25.03.2025 + +## Zusammenfassung der Inhalte + +Die gefundenen Dokumente zeigen übereinstimmend, dass: +- Der Fokus im Jahr 2025 auf der Expansion in neue Märkte liegt +- Das Budget für Forschung und Entwicklung um 15% erhöht wurde +- Drei neue Hauptprojekte im zweiten Quartal starten werden + +## Empfehlungen + +Basierend auf den gefundenen Informationen empfehle ich: +1. Die Projektpläne für Q2 mit besonderem Fokus auf die neuen Hauptprojekte zu prüfen +2. Die Ressourcenzuweisung entsprechend der Budgeterhöhung anzupassen +3. Die Marktanalyse als Grundlage für die Expansionsstrategie zu verwenden + +Die Dokumente sind alle aktuell und wurden von den verantwortlichen Fachabteilungen erstellt. + +[STATUS: ERGEBNIS]""", + "agent_type": self.type + } + + # Extrahiere den Status aus der Antwort und aktualisiere den Inhalt + content, status = self.extract_status(sharepoint_response["content"]) + sharepoint_response["content"] = content + + # Setze den Status im Kontext, falls vorhanden + if context is not None: + context["status"] = status + + return sharepoint_response + +# Singleton-Instanz +_sharepoint_agent = None + +def get_sharepoint_agent(): + """Gibt eine Singleton-Instanz des SharePoint-Agenten zurück""" + global _sharepoint_agent + if _sharepoint_agent is None: + _sharepoint_agent = SharepointAgent() + return _sharepoint_agent \ No newline at end of file diff --git a/gwserver/modules/agentservice_agent_user.py b/gwserver/modules/agentservice_agent_user.py new file mode 100644 index 00000000..7988d83d --- /dev/null +++ b/gwserver/modules/agentservice_agent_user.py @@ -0,0 +1,133 @@ +""" +User-Agent für die Interaktion mit dem Benutzer im Agentservice. +Repräsentiert den menschlichen Benutzer im Workflow und ermöglicht die Kommunikation. +Angepasste Version für das neue User-Input-Handling. +""" + +import logging +from typing import List, Dict, Any, Optional +from modules.agentservice_base import BaseAgent + +logger = logging.getLogger(__name__) + +class UserAgent(BaseAgent): + """Agent für die Interaktion mit dem Benutzer""" + + _instance = None + + @classmethod + def get_instance(cls): + """Gibt eine Singleton-Instanz zurück""" + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def __init__(self): + """Initialisiert den User-Agenten""" + super().__init__() + self.id = "user_agent" + self.name = "User Agent" + self.type = "user" + self.description = "Repräsentiert den Benutzer im Workflow" + self.capabilities = "Beantwortung von Fragen, Bereitstellung zusätzlicher Informationen, Entscheidungsfindung" + + def get_agent_info(self) -> Dict[str, Any]: + """ + Gibt Informationen über den User-Agenten zurück. + + Returns: + Dict mit Agenten-Informationen + """ + return { + "id": self.id, + "name": self.name, + "type": self.type, + "description": self.description, + "capabilities": self.capabilities, + "used": False, + "last_result_status": None + } + + async def process_message(self, message: Dict[str, Any], context: Dict[str, Any] = None) -> Dict[str, Any]: + """ + Verarbeitet eine Nachricht und bereitet die Frontend-Interaktion vor. + + Args: + message: Die zu verarbeitende Nachricht + context: Zusätzlicher Kontext + + Returns: + Die Nachricht an den Benutzer + """ + # Task aus dem Kontext extrahieren (falls vorhanden) + task = context.get("task", "") if context else "" + + # Aus der Nachricht übernehmen, falls kein Kontext + if not task and message and "content" in message: + task = message["content"] + + # Explizites Moderator-Prefix für die Nachricht + moderator_prefix = "[Moderator zu User Agent] " + formatted_task = moderator_prefix + task.strip() + + # Erweiterte Nachricht mit expliziten Flags für das Frontend + user_request = { + "role": "assistant", + "content": formatted_task, + "agent_type": "moderator", # Explizit als Moderator markieren + "agent_id": "moderator", + "agent_name": "Moderator", + } + + # Log-Eintrag + logger.info(f"User-Agent wird aufgerufen, Workflow wartet auf Benutzereingabe: {task[:50]}...") + + return user_request + + def extract_status(self, content: str) -> tuple: + """ + Bei User-Agent wird kein Status extrahiert, da der Benutzer keinen Status angibt. + + Args: + content: Inhalt der Nachricht + + Returns: + Tuple mit (Originalinhalt, "USER_INPUT") + """ + # User-Agent setzt immer Status "USER_INPUT" + return content, "USER_INPUT" + + def format_user_response(self, message: Dict[str, Any]) -> Dict[str, Any]: + """ + Formatiert eine Benutzerantwort für die Workflow-Verarbeitung. + + Args: + message: Die vom Benutzer gesendete Nachricht + + Returns: + Die formatierte Nachricht + """ + # Basisformat für die Antwort + formatted_response = { + "role": "user", + "content": message.get("content", ""), + "agent_type": "user", + "agent_id": self.id, + "agent_name": self.name + } + + # Dateien übernehmen, falls vorhanden + if "documents" in message: + formatted_response["documents"] = message["documents"] + + return formatted_response + +# Singleton-Instanz +_user_agent = None + +def get_user_agent(): + """Gibt eine Singleton-Instanz des User-Agenten zurück""" + global _user_agent + if _user_agent is None: + _user_agent = UserAgent() + return _user_agent \ No newline at end of file diff --git a/gwserver/modules/agentservice_agent_webcrawler.py b/gwserver/modules/agentservice_agent_webcrawler.py new file mode 100644 index 00000000..06a503ef --- /dev/null +++ b/gwserver/modules/agentservice_agent_webcrawler.py @@ -0,0 +1,511 @@ +""" +WebCrawler-Agent für die Recherche und Beschaffung von Informationen aus dem Web. +""" + +import json +import logging +import random +import time +from typing import List, Dict, Any, Optional + +import urllib +from urllib.parse import quote_plus, unquote + +from bs4 import BeautifulSoup +import requests +from modules.agentservice_base import BaseAgent +from connectors.connector_aichat_openai import ChatService + + +logger = logging.getLogger(__name__) + +class WebcrawlerAgent(BaseAgent): + """Agent für Web-Recherche und Informationsbeschaffung""" + + _instance = None + + chat_service = ChatService() + + #INIT --> should go to config + max_url=3 + max_key=3 + + max_result=3 + + timeout = 10 + headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', + 'Accept-Language': 'en-US,en;q=0.5', + 'Referer': 'https://www.google.com/', + 'DNT': '1', + 'Connection': 'keep-alive', + 'Upgrade-Insecure-Requests': '1', + } + max_urls = 10 + max_content_length=100000 + + + @classmethod + def get_instance(cls): + """Gibt eine Singleton-Instanz zurück""" + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def __init__(self): + """Initialisiert den WebCrawler-Agenten""" + super().__init__() + self.id = "webcrawler_agent" + self.name = "Webscraper" + self.type = "scraper" + self.description = "Recherchiert Informationen im Web" + self.capabilities = "Informationsrecherche, Datenbeschaffung aus dem Web, Quellenbewertung und Zusammenführung von Online-Informationen" + self.instructions = "" + + + async def process_message(self, message: Dict[str, Any], context: Dict[str, Any] = None) -> Dict[str, Any]: + try: + # Führe die Web-Recherche durch und warte auf das Ergebnis mit await + web_query_result = await self.get_web_query(message) + + # Antwort-Objekt erstellen + response = { + "role": "assistant", + "content": f"{web_query_result} [STATUS: ERGEBNIS]", + "agent_type": self.type + } + + # Extrahiere den Status aus der Antwort und aktualisiere den Inhalt + content, status = self.extract_status(response["content"]) + response["content"] = content + + # Setze den Status im Kontext, falls vorhanden + if context is not None: + context["status"] = status + + return response + + except Exception as e: + logger.error(f"Fehler bei der Web-Recherche: {str(e)}", exc_info=True) + + # Fehlerantwort zurückgeben + return { + "role": "assistant", + "content": f"Bei der Web-Recherche ist ein Fehler aufgetreten: {str(e)}", + "agent_type": self.type + } + + async def get_web_query(self, message_context: Dict[str, Any]) -> str: + prompt = await self.get_prompt(message_context) + result_json = await self.run_web_query(prompt) + result_data = "" + summary_src = "" + + logger.info(f"Web analysis prompt '{prompt}' delivers {len(result_json)} results.") + if isinstance(result_json, list): + for i, result in enumerate(result_json, 1): + + web_answer_instructions = f""" + Fass das Resultat gemäss dem Auftrag zusammen in maximal rund 2000 Zeichen. Auftrag = '{prompt.replace("'","")}' + Fasse die wichtigsten Erkenntnisse zusammen und setze sie in Bezug zur ursprünglichen Anfrage. Die Einleitung kannst Du weglassen. + Achte darauf, nur relevante und qualitativ hochwertige Informationen zu extrahieren, welche einen Bezug zum Auftrag haben, und übersichtlich zu präsentieren. Vermittle ein ausgewogenes Bild der recherchierten Informationen. + + Dies ist das Resultat: + {result['data']} + """ + + # Zusätzliche Anweisungen für Web-Recherche + content_text = await self.chat_service.call_api( + messages=[ + { + "role": "system", + "content": "Du bist ein Informationsanalyst, der Webinhalte präzise und relevant zusammenfasst." + }, + { + "role": "user", + "content": web_answer_instructions + } + ] + ) + result_data += f"\n\n[{i}] {result['title']}\nURL: {result['url']}\nSnippet: {result['snippet']}\nContent: {content_text}" + summary_src+=f"\n{content_text}" + else: + result_data = "no data received" + + logger.info(f"Web analysis result sent {len(result_data)}B") + + # Zusätzliche Zusammenfassung + summary="" + if len(summary_src)>1: + summary = await self.chat_service.call_api( + messages=[ + { + "role": "system", + "content": "Du erstellst prägnante Zusammenfassungen von Rechercheergbnissen." + }, + { + "role": "user", + "content": f"Bitte fasse diese Erkenntnisse in maximal 5-6 Sätzen zusammen: {summary_src}\n" + } + ] + ) + result = f"{summary}\n\n{result_data}" + return result + + + async def get_prompt(self, message_context: Dict[str, Any]) -> str: + task = message_context.get("content", "") + return task.strip() + + + async def run_web_query(self, prompt: str) -> List[Dict]: + if prompt=="": + return [] + + ptext=f"""Create a comprehensive web research strategy for the task = '{prompt.replace("'","")}'. Return the results as a Python dictionary with these specific keys. If specific url are provided and the task requires analysis only on the provided url, then leave 'skey' open. + + 'url': A list of maximum {self.max_url} specific URLs extracted from the task string. + + 'skey': A list of maximum {self.max_key} key sentences to search for on the web. These should be precise, diverse, and targeted to get the most relevant information. + + Format your response as a valid json object with these two keys. Do not include any explanatory text or markdown outside of the object definition. + """ + + content_text = await self.chat_service.call_api( + messages=[ + { + "role": "system", + "content": "Du bist ein Webrecherche-Experte, der präzise Suchstrategien entwickelt." + }, + { + "role": "user", + "content": ptext + } ] + ) + # Remove markdown formatting if present + if content_text.startswith("```json"): + # Find the end of the JSON block + end_marker = "```" + end_index = content_text.rfind(end_marker) + if end_index != -1: + # Extract the JSON content without the markdown markers + content_text = content_text[7:end_index].strip() + + # Now parse the JSON + try: + logger.info(f"Valid json received: {str(content_text)}") + pjson = json.loads(content_text) + # Now call scrape_json with the parsed dictionary + result_json = await self.scrape_json(pjson) + return result_json + except json.JSONDecodeError as e: + logger.error(f"Failed to parse JSON: {e}") + logger.error(f"Cleaned content: {content_text[:100]}...") + return [] + + + + async def scrape_json(self, research_strategy: Dict[str, List]) -> List[Dict]: + """ + Scrapes web content based on a research strategy JSON. + + Args: + research_strategy: A dictionary containing: + - 'skey': List of search keywords + - 'url': List of direct URLs to scrape + + Returns: + Dictionary with URLs as keys and scraped content as values + """ + + logger.info("Starting JSON-based web scraping") + results = [] + + # Validate input structure + if not isinstance(research_strategy, dict): + logger.error("Invalid research_strategy format: not a dictionary") + return {"error": "Invalid research_strategy format: not a dictionary"} + + keys = research_strategy.get("skey", []) + direct_urls = research_strategy.get("url", []) + + if not isinstance(keys, list) or not isinstance(direct_urls, list): + logger.error("Invalid research_strategy format: keys, or url is not a list") + return {"error": "Invalid research_strategy format: keys, or url is not a list"} + + # Process search keywords through search engine + for keyword in keys: + logger.info(f"Processing keyword: {keyword}") + found_results = self.search_web(keyword) # List with Dict: title,url,snippet,data + logger.info(f"... {len(found_results)} results found") + results.extend(found_results) + + # Process direct URLs + logger.info(f"Processing {len(direct_urls)} direct URLs") + for url in direct_urls: + if url in results: + logger.info(f"Skipping already scraped URL: {url}") + continue + soup=self.read_url(url) + + # Extract title from the page if it exists + if isinstance(soup, BeautifulSoup): + title_tag = soup.find('title') + title = title_tag.text.strip() if title_tag else "No title" + + # Alternative: You could also look for h1 tags if the title tag is missing + if title == "No title": + h1_tag = soup.find('h1') + if h1_tag: + title = h1_tag.text.strip() + else: + # Handle the case where soup is an error message string + title = "Error fetching page" + + results.append(self.parse_result(soup,"No title",url)) + logger.info(f"JSON scraping completed. Scraped {len(results)} URLs in total") + return results + + + def search_web(self, query: str) -> List[Dict]: + formatted_query = quote_plus(query) + url = f"https://html.duckduckgo.com/html/?q={formatted_query}" + + search_results_soup = self.read_url(url) + if not search_results_soup or search_results_soup.select('.result') is None or len(search_results_soup.select('.result')) == 0: + logger.warning(f"Keine Suchergebnisse gefunden für: {query}") + return [] + + # Extract search results + results = [] + + # Find all result containers + result_elements = search_results_soup.select('.result') + + for result in result_elements: + # Extract title + title_element = result.select_one('.result__a') + title = title_element.text.strip() if title_element else 'No title' + + # Extract URL (DuckDuckGo uses redirects, need to extract from href param) + url_element = title_element.get('href') if title_element else '' + extracted_url = 'No URL' + + if url_element: + # Extract the actual URL from DuckDuckGo's redirect + if url_element.startswith('/d.js?q='): + start = url_element.find('?q=') + 3 # Skip '?q=' + end = url_element.find('&', start) if '&' in url_element[start:] else None + extracted_url = unquote(url_element[start:end]) + + # Make sure the URL has the correct protocol prefix + if not extracted_url.startswith(('http://', 'https://')): + if not extracted_url.startswith('//'): + extracted_url = 'https://' + extracted_url + else: + extracted_url = 'https:' + extracted_url + else: + extracted_url = url_element + + # Extract snippet directly from search results page + snippet_element = result.select_one('.result__snippet') + snippet = snippet_element.text.strip() if snippet_element else 'No description' + + # Now fetch the actual page content for the data field + target_page_soup = self.read_url(extracted_url) + + results.append({ + 'title': title, + 'url': extracted_url, + 'snippet': snippet, + 'data': str(target_page_soup) if isinstance(target_page_soup, BeautifulSoup) else "Error fetching page" + }) + + # Limit the number of results if needed + if len(results) >= self.max_result: + break + + return results + + + def read_url(self, url: str) -> BeautifulSoup: + """ + Liest eine URL und gibt einen BeautifulSoup-Parser für den Inhalt zurück. + Bei Fehlern wird ein leeres BeautifulSoup-Objekt zurückgegeben. + + Args: + url: Die zu lesende URL + + Returns: + BeautifulSoup-Objekt mit dem Inhalt oder leer bei Fehlern + """ + headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', + 'Accept': 'text/html,application/xhtml+xml,application/xml', + 'Accept-Language': 'en-US,en;q=0.9', + } + + try: + import time + + # Initialer Request + response = requests.get(url, headers=headers, timeout=10) + + # Polling für Status 202 + if response.status_code == 202: + # Maximal 3 Versuche mit steigenden Intervallen + backoff_times = [0.5, 1.0, 2.0, 5.0] # 0.5s, dann 1s, dann 2s + + for wait_time in backoff_times: + time.sleep(wait_time) # Warten mit steigender Zeit + response = requests.get(url, headers=headers, timeout=10) + + # Wenn kein 202 mehr, dann abbrechen + if response.status_code != 202: + break + + # Für andere Fehler-Status einen Fehler auslösen + response.raise_for_status() + + # HTML parsen + return BeautifulSoup(response.text, 'html.parser') + + except Exception as e: + # Leeres BeautifulSoup-Objekt erstellen + return BeautifulSoup("", 'html.parser') + + + def parse_result(self, data: BeautifulSoup, title: str, url: str) -> Dict[str, str]: + # Extract snippet/description + snippet_element = data.select_one('.result__snippet') + snippet = snippet_element.text.strip() if snippet_element else 'No description' + + result={ + 'title': title, + 'url': url, + 'snippet': snippet, + 'data': data.prettify() + } + return result + + + def _old_scrape_url(self, url: str) -> str: + try: + logger.info(f"Requesting URL: {url}") + response = requests.get(url, headers=self.headers, timeout=self.timeout) + response.raise_for_status() + + soup = BeautifulSoup(response.text, 'html.parser') + title = soup.title.string if soup.title else "No title" + for element in soup.select('script, style, meta, noscript, iframe, nav, footer, header, aside'): + element.extract() + main_content = "" + + # Common content containers + content_selectors = [ + 'main', '#main', '.main', + 'article', '.article', + '#content', '.content', + '.post', '#post', + '.entry-content', '.post-content', + '.page-content', '.article-content' + ] + + # Try each selector + for selector in content_selectors: + elements = soup.select(selector) + if elements: + main_content = elements[0].get_text(separator='\n', strip=True) + logger.info(f"Found content using selector: {selector}") + break + + # If no main content found, use body text + if not main_content: + main_content = soup.body.get_text(separator='\n', strip=True) + logger.info("Using body text as no main content container found") + + # Clean up the text + lines = [] + for line in main_content.split('\n'): + line = line.strip() + if line and len(line) > 15: # Skip very short lines + lines.append(line) + + main_content = '\n'.join(lines) + + # Truncate if too long + if len(main_content) > self.max_content_length: + main_content = main_content[:self.max_content_length] + "...\n[Inhalt gekürzt]" + + return main_content.strip() + + except Exception as e: + logger.error(f"Fehler beim Scrapen von {url}: {str(e)}") + return f"[Fehler beim Scrapen von {url}: {str(e)}]" + + + def _old_extract_urls_from_search_results(self, html_content: str) -> List[str]: + """ + Extracts URLs from search engine results. + + Args: + html_content: HTML content of the search results page + + Returns: + List of extracted URLs + """ + + soup = BeautifulSoup(html_content, 'html.parser') + urls = [] + + # Different search engines have different HTML structures + # Google links + for a_tag in soup.select('a[href^="/url?"]'): + href = a_tag.get('href', '') + if '/url?q=' in href: + url = href.split('/url?q=')[1].split('&')[0] + url = urllib.parse.unquote(url) + if url.startswith('http') and url not in urls: + urls.append(url) + + # Bing links + for a_tag in soup.select('a[href^="http"]'): + url = a_tag.get('href', '') + excluded_domains = getattr(self, 'excluded_domains', []) + if (url.startswith('http') and + not any(domain in url for domain in excluded_domains) and + url not in urls): + urls.append(url) + + # Yahoo links + for a_tag in soup.select('a.d-ib'): + url = a_tag.get('href', '') + if url.startswith('http') and url not in urls: + urls.append(url) + + # If no URLs found, try a more generic approach + if not urls: + for a_tag in soup.find_all('a', href=True): + url = a_tag['href'] + excluded_domains = getattr(self, 'excluded_domains', []) + if (url.startswith('http') and + not any(domain in url for domain in excluded_domains) and + url not in urls): + urls.append(url) + + # Limit the number of results + return urls[:self.max_urls] + + + + +# Singleton-Instanz +_webcrawler_agent = None + +def get_webcrawler_agent(): + """Gibt eine Singleton-Instanz des WebCrawler-Agenten zurück""" + global _webcrawler_agent + if _webcrawler_agent is None: + _webcrawler_agent = WebcrawlerAgent() + return _webcrawler_agent \ No newline at end of file diff --git a/gwserver/modules/agentservice_base.py b/gwserver/modules/agentservice_base.py new file mode 100644 index 00000000..48ae642b --- /dev/null +++ b/gwserver/modules/agentservice_base.py @@ -0,0 +1,118 @@ +""" +Basisklasse für Agenten im Agentservice. +Dieser Modul stellt eine Basis-Agent-Klasse für spezialisierte Agenten zur Verfügung. +""" + +import logging +from typing import List, Dict, Any, Optional, Tuple + +logger = logging.getLogger(__name__) + +class BaseAgent: + """Basisklasse für alle Agenten im System""" + + def __init__(self): + """Initialisiert den Basis-Agenten""" + self.id = "base_agent" + self.name = "Base Agent" + self.type = "base" + self.description = "Basisagent als Vorlage für spezialisierte Agenten" + self.capabilities = "Grundlegende Agentenoperationen" + self.instructions = """ + Als Basis-Agent kannst du grundlegende Aufgaben erledigen. + Diese Anweisungen sollten von spezialisierten Agenten überschrieben werden. + """ + + def get_agent_info(self) -> Dict[str, Any]: + """ + Gibt Informationen über den Agenten zurück. + + Returns: + Dict mit Agenten-Informationen + """ + return { + "id": self.id, + "name": self.name, + "type": self.type, + "description": self.description, + "capabilities": self.capabilities, + "instructions": self.instructions, + "used": False, # Wird zur Laufzeit aktualisiert + "last_result_status": None # Wird zur Laufzeit aktualisiert + } + + def get_prompt(self, message_context: Dict[str, Any]) -> str: + """ + Generiert einen an den Agenten angepassten Prompt basierend auf Kontext. + + Args: + message_context: Kontext der Nachricht + + Returns: + Formatierter Prompt für den Agenten + """ + # Basis-Prompt, der von spezialisierten Agenten überschrieben werden kann + base_prompt = f""" + Du bist {self.name}, ein {self.type} Agent. + + {self.description} + + Deine Fähigkeiten: {self.capabilities} + + {self.instructions} + + Formatiere deine Antwort klar und strukturiert. Beantworte alle Aspekte der Anfrage. + Deklariere am Ende deiner Antwort den Status deines Ergebnisses: + [STATUS: ERGEBNIS] - Wenn du ein vollständiges, konkretes Ergebnis geliefert hast + [STATUS: TEILWEISE] - Wenn du ein teilweises Ergebnis geliefert hast + [STATUS: PLAN] - Wenn du nur einen Plan vorgeschlagen hast + """ + + return base_prompt.strip() + + async def process_message(self, message: Dict[str, Any], context: Dict[str, Any] = None) -> Dict[str, Any]: + """ + Verarbeitet eine Nachricht und generiert eine Antwort. + Sollte von spezialisierten Agenten überschrieben werden. + + Args: + message: Die zu verarbeitende Nachricht + context: Zusätzlicher Kontext (optional) + + Returns: + Die generierte Antwort + """ + # Basis-Implementierung, die einfach eine Standardantwort zurückgibt + return { + "role": "assistant", + "content": f"Ich bin {self.name} und habe deine Anfrage erhalten. Allerdings bin ich nur eine Basisimplementierung ohne spezifische Funktionalität. [STATUS: PLAN]", + "agent_type": self.type + } + + def extract_status(self, content: str) -> Tuple[str, str]: + """ + Extrahiert den Status aus dem Inhalt der Antwort. + + Args: + content: Inhalt der Antwort + + Returns: + Tuple mit (bereinigter Text, Status) + """ + import re + + # Standard-Status, falls keine Deklaration gefunden wird + status = "UNBEKANNT" + + # Suche nach Status-Deklaration + status_pattern = r'\[STATUS:\s*(ERGEBNIS|TEILWEISE|PLAN)\]' + match = re.search(status_pattern, content, re.IGNORECASE) + + if match: + # Extrahiere den Status + status = match.group(1).upper() + + # Entferne die Status-Deklaration aus dem Text + content = re.sub(status_pattern, '', content, flags=re.IGNORECASE).strip() + + return content, status \ No newline at end of file diff --git a/gwserver/modules/agentservice_filehandling.py b/gwserver/modules/agentservice_filehandling.py new file mode 100644 index 00000000..4d144ab9 --- /dev/null +++ b/gwserver/modules/agentservice_filehandling.py @@ -0,0 +1,518 @@ +""" +Zentrales Filehandling-Modul für den Agentservice. +Enthält alle Funktionen für das Verarbeiten von Dateien. +Angepasst, um mit LucyDOMInterface als zentrale Datei-Autorität zu arbeiten. +""" + +import os +import logging +import base64 +import json +import uuid +from datetime import datetime +from typing import Dict, Any, List, Optional, Tuple, Union, BinaryIO +from io import BytesIO # Import BytesIO at the top level + +# Bibliotheken für Dateiverarbeitung +try: + import pandas as pd +except ImportError: + pd = None + +logger = logging.getLogger(__name__) + +# Custom exception für das File-Handling +class FileProcessingError(Exception): + """Basisklasse für Fehler bei der Dateiverarbeitung im AgentService.""" + pass + +class FileExtractionError(FileProcessingError): + """Fehler bei der Textextraktion aus Dateien.""" + pass + +class FileAnalysisError(FileProcessingError): + """Fehler bei der Analyse von Dateien.""" + pass + +def encode_to_base64(content: bytes, mime_type: str = None) -> str: + """ + Kodiert Binärdaten als Base64-String. + + Args: + content: Die zu kodierenden Binärdaten + mime_type: Optionaler MIME-Typ für das Encoding + + Returns: + Base64-kodierter String + """ + base64_data = base64.b64encode(content).decode('utf-8') + return base64_data + +def prepare_file_contexts(files: List[Dict[str, Any]]) -> List[Dict[str, Any]]: + """ + Bereitet die Dateikontexte basierend auf Metadaten vor. + Akzeptiert keine Pfade mehr, sondern nur Metadaten aus der Datenbank. + + Args: + files: Liste von Dateien mit Metadaten (Dict mit id, name, type, content_type) + + Returns: + Liste von Dateikontexten für die Verarbeitung + """ + file_contexts = [] + + logger.info(f"Preparing file contexts for {len(files)} files") + + for file in files: + file_id = file.get("id") + file_name = file.get("name") + file_type = file.get("type") + + # Create a comprehensive context with all available metadata + context = { + "id": file_id, + "name": file_name, + "type": file_type, + "size": file.get("size", "Unbekannt"), + "content_type": file.get("content_type"), + "path": file.get("path"), + "upload_date": file.get("upload_date"), + "hash": file.get("hash"), + "mandate_id": file.get("mandate_id"), + "user_id": file.get("user_id") + } + + # Log for debugging + logger.info(f"Created file context: {file_name} (ID: {file_id}, Type: {file_type})") + + file_contexts.append(context) + + return file_contexts + + + +def extract_text_from_file_content(file_content: bytes, file_name: str, content_type: str = None) -> str: + """ + Extrahiert Text aus verschiedenen Dateiformaten basierend auf dem Binärinhalt. + + Args: + file_content: Binärinhalt der Datei + file_name: Name der Datei für die Erkennung des Formats + content_type: Optional MIME-Typ der Datei + + Returns: + Extrahierter Text oder Fehlermeldung + """ + try: + # Einfache Textdateien + if file_name.endswith(('.txt', '.md', '.json', '.xml', '.html', '.htm', '.css', '.js', '.py')): + try: + return file_content.decode('utf-8') + except UnicodeDecodeError: + try: + return file_content.decode('latin1') + except: + return file_content.decode('cp1252', errors='replace') + + # Excel-Dateien + elif file_name.endswith(('.xlsx', '.xls')): + if pd is not None: + # Temporäre Datei im Speicher erstellen + file_obj = BytesIO(file_content) + df = pd.read_excel(file_obj) + result = f"Excel file with {len(df)} rows and {len(df.columns)} columns.\n" + result += f"Columns: {', '.join(df.columns.tolist())}\n\n" + result += df.to_string(index=False) + return result + else: + return f"[Excel-Datei: {file_name} - pandas nicht installiert]" + + # CSV-Dateien + elif file_name.endswith('.csv'): + if pd is not None: + try: + # Temporäre Datei im Speicher erstellen + file_obj = BytesIO(file_content) + df = pd.read_csv(file_obj, encoding='utf-8') + except UnicodeDecodeError: + file_obj = BytesIO(file_content) + try: + df = pd.read_csv(file_obj, encoding='latin1') + except: + file_obj = BytesIO(file_content) + df = pd.read_csv(file_obj, encoding='cp1252') + + result = f"CSV file with {len(df)} rows and {len(df.columns)} columns.\n" + result += f"Columns: {', '.join(df.columns.tolist())}\n\n" + result += df.to_string(index=False) + return result + else: + return f"[CSV-Datei: {file_name} - pandas nicht installiert]" + + # PDF-Dateien + elif file_name.endswith('.pdf'): + try: + try: + from PyPDF2 import PdfReader + # BytesIO is already imported at the top level + reader = PdfReader(BytesIO(file_content)) + text = "" + for page in reader.pages: + text += page.extract_text() + "\n\n" + return text + except ImportError: + try: + import fitz # PyMuPDF + # BytesIO is already imported at the top level + doc = fitz.open(stream=file_content, filetype="pdf") + text = "" + for page in doc: + text += page.get_text() + "\n\n" + return text + except ImportError: + return f"[PDF: {file_name} - Keine PDF-Bibliothek installiert]" + except Exception as e: + raise FileExtractionError(f"Fehler beim Lesen der PDF-Datei {file_name}: {str(e)}") + + # Sonstige Dateien + else: + return f"[Datei: {file_name} - Textextraktion nicht unterstützt]" + + except Exception as e: + logger.error(f"Fehler beim Extrahieren von Text aus {file_name}: {str(e)}") + raise FileExtractionError(f"Fehler beim Extrahieren von Text aus {file_name}: {str(e)}") + +async def extract_and_analyze_pdf_images( + pdf_content: bytes, + prompt: str, + ai_service +) -> List[Dict[str, Any]]: + """ + Extrahiert Bilder aus einer PDF-Datei und analysiert sie. + Arbeitet mit Binärdaten statt Dateipfaden. + + Args: + pdf_content: Binärdaten der PDF-Datei + prompt: Prompt für die Bildanalyse + ai_service: AI-Service für die Bildanalyse + + Returns: + Liste mit Analyseergebnissen für jedes Bild + """ + image_responses = [] + temp_files = [] # Liste der temporären Dateien zur Bereinigung + + try: + # PDF mit PyMuPDF öffnen + import fitz # PyMuPDF + # BytesIO is already imported at the top level + import tempfile + + # PDF im Speicher öffnen + doc = fitz.open(stream=pdf_content, filetype="pdf") + logger.info(f"PDF geöffnet mit {len(doc)} Seiten") + + for page_num, page in enumerate(doc, 1): + # Alle Bilder auf der Seite finden + image_list = page.get_images(full=True) + + if image_list: + logger.info(f"Seite {page_num}: {len(image_list)} Bilder gefunden") + + for img_index, img in enumerate(image_list): + try: + # Bild-Referenz + xref = img[0] + + # Bild und Metadaten extrahieren + base_image = doc.extract_image(xref) + image_bytes = base_image["image"] # Tatsächliche Bilddaten + image_ext = base_image["ext"] # Dateiendung (jpg, png, etc.) + + # Erstelle temporäre Datei + fd, temp_img_path = tempfile.mkstemp(suffix=f".{image_ext}") + temp_files.append(temp_img_path) # Zur Bereinigungsliste hinzufügen + + with os.fdopen(fd, 'wb') as img_file: + img_file.write(image_bytes) + + logger.debug(f"Bild temporär gespeichert: {temp_img_path}") + + # Analysiere mit AI-Service + try: + analysis_result = await ai_service.analyze_image( + image_data=image_bytes, # Direktes Übergeben der Bilddaten + prompt=prompt, + mime_type=f"image/{image_ext}" + ) + logger.debug(f"Bildanalyse für Bild {img_index} auf Seite {page_num} abgeschlossen") + except Exception as analyze_error: + logger.error(f"Fehler bei der Bildanalyse: {str(analyze_error)}") + analysis_result = f"[Fehler bei der Bildanalyse: {str(analyze_error)}]" + + # Ergebnis speichern + try: + # Versuche zuerst, die Größe aus base_image zu bekommen + if 'width' in base_image and 'height' in base_image: + image_size = f"{base_image['width']}x{base_image['height']}" + else: + # Alternative: Öffne das temporäre Bild, um die Größe zu bestimmen + from PIL import Image + with Image.open(temp_img_path) as img: + width, height = img.size + image_size = f"{width}x{height}" + except Exception as e: + logger.warning(f"Konnte Bildgröße nicht ermitteln: {str(e)}") + image_size = "unbekannt" + + image_responses.append({ + "page": page_num, + "image_index": img_index, + "format": image_ext, + "image_size": image_size, + "response": analysis_result + }) + + except Exception as e: + logger.warning(f"Fehler bei der Extraktion von Bild {img_index} auf Seite {page_num}: {str(e)}") + continue + + logger.info(f"Extrahiert und analysiert: {len(image_responses)} Bilder aus PDF") + + except ImportError: + logger.error("PyMuPDF (fitz) ist nicht installiert. Installiere es mit 'pip install pymupdf'") + raise FileExtractionError("PyMuPDF (fitz) ist nicht installiert") + except Exception as e: + logger.error(f"Fehler beim Extrahieren von PDF-Bildern: {str(e)}") + raise FileExtractionError(f"Fehler beim Extrahieren von PDF-Bildern: {str(e)}") + finally: + # Bereinige alle temporären Dateien + for temp_file in temp_files: + try: + if os.path.exists(temp_file): + os.remove(temp_file) + except Exception as e: + logger.warning(f"Konnte temporäre Datei nicht entfernen: {temp_file} - {str(e)}") + + return image_responses + + +def add_file_to_message(message: Dict[str, Any], file_data: Dict[str, Any]) -> Dict[str, Any]: + """ + Fügt eine Datei zu einer Nachricht hinzu. + Funktion für Workflow-Manager und interne Verwendung. + + Args: + message: Die zu erweiternde Nachricht + file_data: Dateimetadaten und Inhalt + + Returns: + Die aktualisierte Nachricht mit der Datei + """ + # Detailed logging for debugging + logger.info(f"Adding file to message: {file_data.get('name', 'unnamed_file')} (ID: {file_data.get('id', 'unknown')})") + + # Initialize documents array if needed + if "documents" not in message: + message["documents"] = [] + logger.debug("Initialized empty documents array in message") + + # Create a unique ID for the document if not provided + doc_id = file_data.get("id", f"file_{uuid.uuid4()}") + + # Extract file size if available + file_size = file_data.get("size") + if isinstance(file_size, str) and file_size.isdigit(): + file_size = int(file_size) + elif file_size is None and file_data.get("content"): + # Estimate size from content if not provided + file_size = len(file_data.get("content", "")) + + # Create standard document structure that matches the data model + document = { + "id": doc_id, # Add an ID to the document itself + "source": { + "type": "file", + "id": file_data.get("id", doc_id), + "name": file_data.get("name", "unnamed_file"), + "content_type": file_data.get("content_type"), + "size": file_size, + "upload_date": file_data.get("upload_date", datetime.now().isoformat()) + }, + "contents": [ + { + "type": "text", + "text": file_data.get("content", "No content available") + } + ] + } + + # Log document structure for debugging + logger.debug(f"Created document structure: {json.dumps({k: v for k, v in document.items() if k != 'contents'})}") + + # Check if file is already in the message to avoid duplicates + file_already_added = any( + doc.get("source", {}).get("id") == file_data.get("id") + for doc in message.get("documents", []) + ) + + if not file_already_added: + message["documents"].append(document) + logger.info(f"File {file_data.get('name')} successfully added to message (total: {len(message.get('documents', []))} files)") + else: + logger.info(f"File {file_data.get('name')} already exists in message, skipping") + + return message + + + +def extract_files_from_message(message: Dict[str, Any]) -> List[Dict[str, Any]]: + """ + Extrahiert Dateiinformationen aus einer Nachricht. + Funktion für Workflow-Manager und interne Verwendung. + + Args: + message: Die Nachricht, aus der Dateien extrahiert werden sollen + + Returns: + Liste der extrahierten Dateiinformationen + """ + files = [] + + if "documents" not in message: + logger.debug("No documents found in message") + return files + + # Log for debugging + logger.debug(f"Extracting files from message with {len(message.get('documents', []))} documents") + + for doc in message.get("documents", []): + doc_source = doc.get("source", {}) + + # Nur Dateien extrahieren + if doc_source.get("type") == "file": + file_info = { + "id": doc_source.get("id", f"file_{uuid.uuid4()}"), + "name": doc_source.get("name", "unnamed_file"), + "content_type": doc_source.get("content_type"), + "size": doc_source.get("size") + } + + # Inhalt extrahieren, falls vorhanden + doc_contents = doc.get("contents", []) + for content in doc_contents: + if content.get("type") == "text": + file_info["content"] = content.get("text", "") + break + + logger.debug(f"Extracted file: {file_info.get('name')} (ID: {file_info.get('id')})") + files.append(file_info) + else: + logger.debug(f"Skipping non-file document of type: {doc_source.get('type')}") + + logger.info(f"Extracted {len(files)} files from message") + return files + + + +async def read_file_contents( + file_contexts: List[Dict[str, Any]], + lucydom_interface, + workflow_id: str = None, + add_log_func = None, + ai_service = None # AI service parameter for image analysis +) -> Dict[str, str]: + """ + Liest den Inhalt aller Dateien und führt bei Bildern und Dokumenten Analysen durch. + Verwendet LucyDOM-Interface statt direkter Dateizugriffe. + + Args: + file_contexts: Liste der Dateikontexte mit Metadaten + lucydom_interface: LucyDOM-Interface für Dateizugriffe + workflow_id: Optionale ID des Workflows für Logging + add_log_func: Optionale Funktion für das Hinzufügen von Logs + ai_service: Optionaler AI-Service für die Bildanalyse + + Returns: + Dictionary mit Dateiinhalten (file_id -> content) + """ + file_contents = {} + + # Add debug logging + logger.info(f"Reading contents of {len(file_contexts)} files for workflow {workflow_id}") + + for file in file_contexts: + file_id = file["id"] + file_name = file["name"] + file_type = file.get("type", "unknown") + + try: + # Dateiinhalt über LucyDOM-Interface abrufen + file_data = await lucydom_interface.read_file_content(file_id) + + if not file_data: + _log(add_log_func, workflow_id, f"Datei {file_name} nicht gefunden", "warning") + file_contents[file_id] = f"File content not available (File not found)" + continue + + logger.info(f"Successfully read file: {file_name} (ID: {file_id}, Type: {file_type})") + # Image files - always perform image analysis if AI service is available + if file_type == "image" or file_name.lower().endswith(('.jpg', '.jpeg', '.png', '.gif', '.webp')): + if ai_service: + try: + #_log(add_log_func, workflow_id, f"Analyzing image {file_name} {len(file_data)}B...", "info") + logger.info(f"ai_service type: {type(ai_service)}") + logger.info(f"ai_service methods: {dir(ai_service)}") + logger.info(f"ai_service has analyze_image method: {'analyze_image' in dir(ai_service)}") + + image_analysis = await ai_service.analyze_image( + image_data=file_data, + prompt="Describe this image in detail", + mime_type=file.get("content_type") + ) + + logger.debug(f"Image analysis successfully generated for {file_name}") + + file_contents[file_id] = f"Image Analysis:\n{image_analysis}" + _log(add_log_func, workflow_id, f"Image {file_name} analyzed successfully", "info") + except Exception as e: + logger.error(f"Error analyzing image {file_name}: {str(e)}") + _log(add_log_func, workflow_id, f"Error analyzing image {file_name}: {str(e)}", "error") + file_contents[file_id] = f"Image file: {file_name} (Analysis failed: {str(e)})" + else: + file_contents[file_id] = f"Image file: {file_name} (AI analysis not available)" + + # Document files + elif file_type == "document" or not file_type: + # Verwende die zentrale Textextraktionsfunktion mit Dateiinhalt + content = extract_text_from_file_content(file_data, file_name, file.get("content_type")) + file_contents[file_id] = content + _log(add_log_func, workflow_id, f"File {file_name} read successfully", "info") + + # Other file types - just store metadata + else: + file_contents[file_id] = f"File: {file_name} (Type: {file_type}, content not available)" + _log(add_log_func, workflow_id, f"Unsupported file type: {file_type} for {file_name}", "warning") + + except Exception as e: + logger.error(f"Error reading file {file_name}: {str(e)}") + _log(add_log_func, workflow_id, f"Error reading file {file_name}: {str(e)}", "error") + file_contents[file_id] = f"File content not available (Error: {str(e)})" + + return file_contents + + +def _log(add_log_func, workflow_id, message, log_type, agent_id=None, agent_name=None): + """Hilfsfunktion zum Loggen mit unterschiedlichen Log-Funktionen""" + # Log über die Logger-Instanz + if log_type == "error": + logger.error(message) + elif log_type == "warning": + logger.warning(message) + else: + logger.info(message) + + # Log über die bereitgestellte Log-Funktion (falls vorhanden) + if add_log_func and workflow_id: + add_log_func(workflow_id, message, log_type, agent_id, agent_name) + diff --git a/gwserver/modules/agentservice_interface.py b/gwserver/modules/agentservice_interface.py deleted file mode 100644 index 05d0f7de..00000000 --- a/gwserver/modules/agentservice_interface.py +++ /dev/null @@ -1,1259 +0,0 @@ -import asyncio -import uuid -import os -import logging -import json -from typing import List, Dict, Any, Optional, Tuple -from datetime import datetime -from fastapi import HTTPException -import configload as configload - -# Import der Teilmodule -import modules.agentservice_part_filehandling as file_handling -import modules.agentservice_part_agents as agents -import modules.agentservice_part_results as results - -# Logger konfigurieren -logger = logging.getLogger(__name__) - -# Konfigurationsdaten laden -def load_config_data(): - config = configload.load_config() - result = { - "application": { - "debug": config.get('Module_AgentserviceInterface', 'DEBUG'), - "upload_dir": config.get('Module_AgentserviceInterface', 'UPLOAD_DIR'), - "results_dir": config.get('Module_AgentserviceInterface', 'RESULTS_DIR'), - "max_history": config.get('Module_AgentserviceInterface', 'MAX_HISTORY'), - "ai_provider": config.get('Module_AgentserviceInterface', 'AI_PROVIDER'), - } - } - # Debug-Modus einstellen - if result["application"]["debug"].lower() == "true": - logging.basicConfig(level=logging.DEBUG) - logger.setLevel(logging.DEBUG) - logger.debug("Debug-Modus aktiviert") - return result - - -class AgentService: - """ - Service für die Verwaltung und Ausführung von Multi-Agent-Workflows mit verschiedenen Modellen. - """ - - def __init__(self, mandate_id: int = None, user_id: int = None): - """ - Initialisiert den AgentService. - - Args: - mandate_id: ID des aktuellen Mandanten (optional) - user_id: ID des aktuellen Benutzers (optional) - """ - # Mandanten- und Benutzerkontext - self.mandate_id = mandate_id - self.user_id = user_id - - # Konfiguration laden - self.config = load_config_data() - - # Verzeichnisse aus der Konfiguration übernehmen - self.results_dir = self.config["application"]["results_dir"] - self.upload_dir = self.config["application"]["upload_dir"] - self.max_history = int(self.config["application"]["max_history"]) - - # AI Provider aus der Konfiguration übernehmen - self.ai_provider = self.config["application"]["ai_provider"].lower() - - # Verzeichnisse erstellen - os.makedirs(self.results_dir, exist_ok=True) - os.makedirs(self.upload_dir, exist_ok=True) - - # Connector-Instanzen initialisieren - if self.ai_provider == "anthropic": - import connector_aichat_anthropic as service_aichat - self.service_aichat = service_aichat.ChatService() - logger.info("Anthropic AI Provider wird verwendet") - else: - import connector_aichat_openai as service_aichat - self.service_aichat = service_aichat.ChatService() - logger.info("OpenAI AI Provider wird verwendet") - - import connector_aiweb_webscraping as service_aiscrap - self.service_aiscrap = service_aiscrap.WebScrapingService() - - logger.info(f"AgentService initialisiert mit:") - logger.info(f" - AI Provider: {self.ai_provider}") - logger.info(f" - Ergebnisverzeichnis: {self.results_dir}") - logger.info(f" - Upload-Verzeichnis: {self.upload_dir}") - - # Workflow-Speicher - self.workflows = {} - - # Statistiken für die Datenmengen - self.data_stats = {} - - async def execute_workflow( - self, - workflow_id: str, - prompt: str, - agents_list: List[Dict[str, Any]], - files: List[Dict[str, Any]] - ) -> str: - """ - Führt einen Workflow mit den angegebenen Agenten und Dateien aus. - - Anstatt die Agenten der Reihe nach abzuarbeiten, wird ein AI-Moderator verwendet, - der die Agenten basierend auf ihren Fähigkeiten und bisherigen Antworten steuert. - - Verwendet file_handling.prepare_message_for_ai für die Vorbereitung der Nachrichten, - wobei alle Dateiinhalte vollständig gelesen werden. - """ - logger.info(f"Starte Workflow {workflow_id} mit {len(agents_list)} Agenten und {len(files)} Dateien") - - # Mandanten- und Benutzerkontext in die Workflow-Daten aufnehmen - self.workflows[workflow_id] = { - "id": workflow_id, - "mandate_id": self.mandate_id, - "user_id": self.user_id, - "status": "running", - "progress": 0.0, - "started_at": datetime.now().isoformat(), - "completed_at": None, - "agent_statuses": {}, - "logs": [], - "results": [], - # Statistik für diesen Workflow initialisieren - "data_stats": { - "sent_bytes": 0, - "received_bytes": 0 - } - } - - # Log-Eintrag für den Start des Workflows - self._add_log(workflow_id, "Workflow gestartet", "info") - self._add_log(workflow_id, f"Verarbeite {len(files)} Dateien...", "info") - - # Dateikontexte vorbereiten - file_contexts = file_handling.prepare_file_contexts(files, self.upload_dir) - for fc in file_contexts: - logger.debug(f"Dateikontext: ID={fc['id']}, Name={fc['name']}, Typ={fc.get('type', 'unbekannt')}") - - # Dateiinhalte lesen - EINMAL für den gesamten Workflow - file_contents = await file_handling.read_file_contents( - file_contexts, - self.upload_dir, - workflow_id, - self._add_log - ) - - # Erstelle einen formatierten Kontext für die Protokollierung - file_context_text = file_handling.format_file_context_text(file_contexts, file_contents) - logger.debug(f"Dateikontexte erstellt: {len(file_contexts)} Dateien") - - self.workflows[workflow_id]["progress"] = 0.1 - - # Initialisiere den Chatverlauf für den Agenten-Dialog - chat_history = [] - - # Erstelle das standardisierte Nachrichtenobjekt für die initialen Dateien und den Prompt - # Verwende file_handling.prepare_message_for_ai mit dem Service - initial_message = await file_handling.prepare_message_for_ai( - file_contexts, - prompt, - file_contents, - self.service_aichat - ) - - # Initialen Prompt zum Chatverlauf hinzufügen - chat_history.append(initial_message) - - # Datenstatistik aktualisieren - Schätzung der gesendeten Bytes - message_size = len(json.dumps(initial_message)) - self.workflows[workflow_id]["data_stats"]["sent_bytes"] += message_size - - # Initialisiere die verfügbaren Agenten mit ihren Fähigkeiten - available_agents = agents.initialize_agents(agents_list) - - # Füge den User-Agent hinzu - user_info = await self._get_user_info(self.user_id) - user_name = user_info.get("full_name") or user_info.get("username") or f"Benutzer {self.user_id}" - - available_agents["user_agent"] = { - "id": "user_agent", - "name": "User Agent", - "full_name": user_name, - "type": "user", - "capabilities": "Beantwortung von Fragen, Bereitstellung zusätzlicher Informationen, Entscheidungsfindung", - "description": f"Repräsentiert den Benutzer {user_name}", - "used": False - } - - # Initialisiere den Status für jeden Agenten - for agent_id in available_agents: - self.workflows[workflow_id]["agent_statuses"][agent_id] = "pending" - - # Speichere wichtige Daten im Workflow-Objekt für die spätere Fortsetzung - self.workflows[workflow_id]["chat_history"] = chat_history - self.workflows[workflow_id]["available_agents"] = available_agents - self.workflows[workflow_id]["file_contexts"] = file_contexts - self.workflows[workflow_id]["file_contents"] = file_contents - - # Starte den Workflow mit dem Moderator - self._add_log(workflow_id, f"Starte Agenten-Tischrunde mit Moderator und {len(available_agents)} Agenten", "info") - - # Maximale Anzahl der Runden zur Vermeidung endloser Schleifen - max_rounds = 12 - current_round = 0 - workflow_complete = False - waiting_for_user_input = False - - # Hauptschleife für den Workflow - while current_round < max_rounds and not workflow_complete: - current_round += 1 - self.workflows[workflow_id]["current_round"] = current_round - self._add_log(workflow_id, f"Starte Runde {current_round}", "info") - - # Falls auf eine Benutzereingabe gewartet wird, nicht fortfahren - if waiting_for_user_input: - self._add_log(workflow_id, "Warte auf Benutzereingabe...", "info") - # Warten wir einfach kurz und beenden dann die Schleife, um im nächsten Polling weiterzumachen - await asyncio.sleep(2) - break - - # Führe einen Moderator-Zyklus durch - workflow_complete, waiting_for_user_input, selected_agent_id = await self._run_moderator_cycle( - workflow_id, - chat_history, - available_agents, - file_contexts, - file_contents, - is_user_input_continuation=False # Initialer Aufruf, keine Fortsetzung nach Benutzereingabe - ) - - # Fortschritt aktualisieren - self.workflows[workflow_id]["progress"] = min(0.9, 0.1 + (current_round / max_rounds) * 0.8) - - # Workflow abschließen, wenn nicht auf Benutzereingabe wartend - if not waiting_for_user_input: - if workflow_complete: - self.workflows[workflow_id]["status"] = "completed" - self._add_log(workflow_id, "Workflow erfolgreich beendet", "success") - elif current_round >= max_rounds: - self.workflows[workflow_id]["status"] = "completed" - self._add_log(workflow_id, f"Workflow nach {max_rounds} Runden automatisch beendet", "info") - else: - self.workflows[workflow_id]["status"] = "failed" - self._add_log(workflow_id, "Workflow mit Fehlern beendet", "error") - - self.workflows[workflow_id]["progress"] = 1.0 - self.workflows[workflow_id]["completed_at"] = datetime.now().isoformat() - - # Speichere Ergebnisse in Datei für spätere Verwendung - results.save_workflow_results(self.workflows, workflow_id, self.results_dir) - - return workflow_id - - - async def _run_moderator_cycle( - self, - workflow_id: str, - chat_history: List[Dict[str, Any]], - available_agents: Dict[str, Dict[str, Any]], - file_contexts: List[Dict[str, Any]], - file_contents: Dict[str, str], - is_user_input_continuation: bool = False, - user_message: str = None - ) -> Tuple[bool, bool, str]: - """ - Improved moderator cycle with structured agent selection and robust user agent handling - """ - # Initialize return values - workflow_complete = False - waiting_for_user_input = False - selected_agent_id = None - - # Create a structured moderator prompt - moderator_system_prompt = self._create_structured_moderator_prompt( - available_agents, - is_user_input_continuation - ) - - # Moderator prompt as system message - moderator_prompt = { - "role": "system", - "content": moderator_system_prompt - } - - # Create a copy of chat history for the moderator - moderator_chat = [moderator_prompt] + chat_history[-self.max_history:] - - # Add summary of available agents with their status - agent_info = "Available agents:\n" - for agent_id, agent in available_agents.items(): - status = "✓ Used" if agent["used"] else "✗ Not used yet" - agent_info += f"- {agent['name']} (Type: {agent['type']}): {agent.get('capabilities', '')}\n Status: {status}\n" - - moderator_chat.append({ - "role": "system", - "content": agent_info + "\nSelect the next agent or end the workflow if the task is complete." - }) - - # Let the moderator make the decision - try: - moderator_chat = await self._sanitize_messages(moderator_chat) - moderator_decision = await self.service_aichat.call_api(moderator_chat) - moderator_text = moderator_decision["choices"][0]["message"]["content"] - logger.debug(f"Full moderator decision text: {moderator_text}") - - # Update data statistics - request_size = len(json.dumps(moderator_chat)) - response_size = len(json.dumps(moderator_decision)) - self.workflows[workflow_id]["data_stats"]["sent_bytes"] += request_size - self.workflows[workflow_id]["data_stats"]["received_bytes"] += response_size - - # Try to parse structured agent selection from the moderator - selected_agent_id = self._parse_structured_agent_selection( - moderator_text, - available_agents - ) - - # Add the moderator's decision to chat history - logger.debug(f"pmd1 moderator_text (type: {type(moderator_text)}): {moderator_text}") - logger.debug(f"pmd1 chat_history (type: {type(chat_history)}): {chat_history}") - - if not isinstance(moderator_text, str): - moderator_text = str(moderator_text) - - chat_history.append({ - "role": "assistant", - "content": f"[Moderator] {moderator_text}" - }) - - # Log the moderator's decision - self._add_log(workflow_id, f"Moderator decision: {moderator_text}", "info") - - # Check if the workflow should be completed - if selected_agent_id == "WORKFLOW_COMPLETE": - self._add_log(workflow_id, "Moderator has ended the workflow", "success") - workflow_complete = True - return workflow_complete, waiting_for_user_input, selected_agent_id - - # Check if User Agent is selected - CRITICAL PATH FOR USER INPUT - if selected_agent_id == "user_agent": - self._add_log( - workflow_id, - "Waiting for user input for User Agent", - "info", - "user_agent", - "User Agent" - ) - # Mark that we're waiting for user input - this blocks further execution - waiting_for_user_input = True - self.workflows[workflow_id]["waiting_for_user"] = True - - # Add request to chat history - chat_history.append({ - "role": "assistant", - "content": f"[Moderator to User Agent] {moderator_text}" - }) - - # Update chat history in workflow - self.workflows[workflow_id]["chat_history"] = chat_history - - # Save workflow state - results.save_workflow_results(self.workflows, workflow_id, self.results_dir) - - # Return immediately to prevent further processing - return workflow_complete, waiting_for_user_input, selected_agent_id - - # If no agent was selected, end the workflow - if not selected_agent_id: - self._add_log(workflow_id, "No agent selected. Ending workflow.", "warning") - workflow_complete = True - return workflow_complete, waiting_for_user_input, selected_agent_id - - # Mark the selected agent as used - selected_agent = available_agents[selected_agent_id] - selected_agent["used"] = True - - # Update agent status - self.workflows[workflow_id]["agent_statuses"][selected_agent_id] = "running" - self._add_log( - workflow_id, - f"Agent '{selected_agent['name']}' starts processing...", - "start", - selected_agent_id, - selected_agent['name'] - ) - - # Create agent instructions - agent_instructions = agents.get_agent_instructions( - selected_agent["type"], - selected_agent, - file_contexts - ) - - # Create agent prompt - agent_prompt = agents.create_agent_prompt(selected_agent, agent_instructions) - - # Create agent chat history - agent_chat = [agent_prompt] + chat_history[-self.max_history:] - - # Handle web scraper agent type specifically - if selected_agent["type"] == "scraper": - self._add_log( - workflow_id, - "Performing web scraping...", - "info", - selected_agent_id, - selected_agent["name"] - ) - - # Use user message or initial prompt for scraping - scrape_prompt = user_message if is_user_input_continuation and user_message else \ - (chat_history[0]["content"] if chat_history else "") - - logger.debug("Web Scrape Prompt: "+str(scrape_prompt)) - # Ensure scrape_prompt is a string - if not isinstance(scrape_prompt, str): - scrape_prompt = str(scrape_prompt) - - # Always perform web scraping for scraper agent type - try: - web_data = await self.service_aiscrap.scrape_web_data(scrape_prompt) - if web_data: - web_data = web_data.strip() if isinstance(web_data, str) else web_data - agent_chat.append({ - "role": "system", - "content": f"# Scraped Web Data\n{web_data}".strip() - }) - self._add_log( - workflow_id, - "Web scraping completed", - "info", - selected_agent_id, - selected_agent["name"] - ) - except Exception as e: - logger.error(f"Error during web scraping: {str(e)}") - self._add_log( - workflow_id, - f"Error during web scraping: {str(e)}", - "error", - selected_agent_id, - selected_agent["name"] - ) - - # Execute the agent - try: - agent_chat = await self._sanitize_messages(agent_chat) - agent_response = await self.service_aichat.call_api(agent_chat) - agent_text = agent_response["choices"][0]["message"]["content"] - - # Update data statistics - request_size = len(json.dumps(agent_chat)) - response_size = len(json.dumps(agent_response)) - self.workflows[workflow_id]["data_stats"]["sent_bytes"] += request_size - self.workflows[workflow_id]["data_stats"]["received_bytes"] += response_size - - # Add agent's response to chat history - chat_history.append({ - "role": "assistant", - "content": agent_text - }) - - # Create agent result - prompt_for_result = user_message if is_user_input_continuation else \ - (chat_history[0]["content"] if chat_history else "") - - result = results.create_agent_result( - workflow_id, - selected_agent, - len(self.workflows[workflow_id]["results"]), - prompt_for_result, - file_contexts, - agent_text, - self.mandate_id, - self.user_id - ) - self.workflows[workflow_id]["results"].append(result) - - self._add_log( - workflow_id, - f"Agent '{selected_agent['name']}' has completed processing", - "complete", - selected_agent_id, - selected_agent["name"] - ) - - # Update agent status - self.workflows[workflow_id]["agent_statuses"][selected_agent_id] = "completed" - - except Exception as e: - logger.error(f"Error executing agent '{selected_agent['name']}': {str(e)}") - self._add_log( - workflow_id, - f"Error during execution: {str(e)}", - "error", - selected_agent_id, - selected_agent["name"] - ) - self.workflows[workflow_id]["agent_statuses"][selected_agent_id] = "failed" - - # Add error message to chat history - chat_history.append({ - "role": "assistant", - "content": f"[Error with agent '{selected_agent['name']}']: {str(e)}" - }) - - except Exception as e: - logger.error(f"Error in moderator phase: {str(e)}") - self._add_log(workflow_id, f"Error in moderator phase: {str(e)}", "error") - - # Update chat history in workflow - self.workflows[workflow_id]["chat_history"] = chat_history - - return workflow_complete, waiting_for_user_input, selected_agent_id - - - def _create_structured_moderator_prompt(self, available_agents, is_user_input_continuation): - """ - Creates an improved moderator prompt that requests a structured format for agent selection - and enforces proper user agent interaction - """ - # Check if User Agent has been used and confirmed - user_agent_used = False - user_agent_confirmed = False - - if "user_agent" in available_agents: - user_agent_used = available_agents["user_agent"].get("used", False) - if user_agent_used: - for chat_entry in available_agents["user_agent"].get("chat_entries", []): - if any(confirmation in chat_entry.lower() for confirmation in - ["ja", "yes", "bestätige", "confirm", "stimme zu", "agree", "akzeptiere", "accept"]): - user_agent_confirmed = True - break - - base = """You are a moderator of a multi-agent system. Your task is to coordinate the agents - to fully address the request and deliver a concrete final result. - First step is always to ask an agento to coordinate the necessary steps. - - IMPORTANT: The workflow should only end when ACTUAL RESULTS have been delivered""" - - # Different conditions for ending the workflow - if not user_agent_confirmed: - base += """ AND the User Agent has explicitly confirmed with a 'YES' that they are satisfied with the result. - CRITICALLY IMPORTANT: Before ending the workflow, you MUST ask the User Agent whether they are satisfied with the results, - and they must EXPLICITLY respond with 'YES' or a clear confirmation!""" - - # Add structured format requirement - base += """ - - RESPONSE FORMAT: You must respond with a clear agent selection in the following format: - { - "next_agent": "agent_id", // The ID of the selected agent (e.g., "user_agent", "analyzer", "writer") - "task": "description" // Clear description of the task for the agent - } - - DO NOT use any other format for agent selection. - """ - - # Add specific instruction for user agent interaction - base += """ - IMPORTANT USER AGENT HANDLING: - - When selecting the User Agent, formulate a CLEAR QUESTION that requires their input. - - The User Agent MUST be able to provide a response before the workflow continues. - - Never reference a User Agent question without actually selecting the User Agent. - """ - - # Add agent listing and instructions - agents_list = "\nAvailable agents:\n" - for agent_id, agent in available_agents.items(): - status = "✓ Already used" if agent["used"] else "✗ Not used yet" - result_status = "" - if agent["used"] and agent.get("last_result_status"): - result_status = f" (Last response: {agent.get('last_result_status')})" - - description = agent.get("description", "") - capabilities = agent.get("capabilities", "") - agents_list += f"- {agent['name']} (ID: {agent_id}, Type: {agent['type']}): {capabilities}\n {description}\n Status: {status}{result_status}\n" - - # Add decision guidelines - instructions = """ - Consider the STATUS declarations of agents when making your decision: - - - [STATUS: ERGEBNIS] - The agent has delivered a complete result - - [STATUS: TEILWEISE] - The agent has delivered a partial result, more work is needed - - [STATUS: PLAN] - The agent has delivered a plan, no concrete results yet - - Possible decisions: - - Select an agent: Provide a structured response with next_agent and task - """ - - if not user_agent_confirmed: - instructions += """- For completion (only if [STATUS: ERGEBNIS] exists): You MUST FIRST ask the User Agent explicitly if they are satisfied with the results. - The User Agent MUST respond with "YES" or clear confirmation before the workflow can end! - - IMPORTANT: You MUST NOT end the workflow before the User Agent has explicitly confirmed with "YES"! - Ask the User Agent a CLEAR, DIRECT question whether they are satisfied with the result or need more information. - """ - else: - instructions += """- For completion (only if [STATUS: ERGEBNIS] exists and User Agent has confirmed with "YES"): Select "WORKFLOW_COMPLETE" as next_agent to end the workflow. - - IMPORTANT: Since the User Agent has already given their approval, you can now end the workflow if an agent has delivered a concrete [STATUS: ERGEBNIS]! - """ - - if is_user_input_continuation: - base += "\nIMPORTANT: The User Agent has just responded. Consider this response in your decision." - - return base + agents_list + instructions - - - def _parse_structured_agent_selection(self, moderator_text, available_agents): - """ - Attempts to parse a structured agent selection from the moderator's text. - Falls back to keyword detection if structured format is not found. - """ - # First try to find a JSON structure - import re - import json - - # Look for JSON structure in the text - json_pattern = r'\{[\s\S]*?"next_agent"[\s\S]*?\}' - json_match = re.search(json_pattern, moderator_text) - - if json_match: - try: - selection = json.loads(json_match.group(0)) - next_agent = selection.get("next_agent") - - # Handle workflow completion - if next_agent.lower() in ["workflow_complete", "complete", "end"]: - return "WORKFLOW_COMPLETE" - - # Check if the selected agent exists - if next_agent in available_agents: - logger.info(f"Successfully parsed structured agent selection: {next_agent}") - return next_agent - - # Handle user agent selection explicitly - if next_agent.lower() in ["user", "user_agent", "human"]: - return "user_agent" - - except json.JSONDecodeError: - logger.warning("Failed to parse JSON from moderator text") - - # Fallback to the traditional logic with improved reliability - text = moderator_text.lower() - - # Check for workflow completion phrases - workflow_complete_phrases = [ - "workflow beenden - vollständiges ergebnis erreicht", - "workflow beenden - vollständiges ergebnis", - "vollständiges ergebnis erreicht", - "workflow complete", - "end workflow", - "complete workflow" - ] - - # Check if the workflow should be completed - result_exists = False - for agent_id, agent in available_agents.items(): - if agent.get("used") and agent.get("last_result_status") == "ERGEBNIS": - result_exists = True - break - - # Check if User Agent has confirmed - user_agent_confirmed = False - if "user_agent" in available_agents and available_agents["user_agent"].get("used", False): - for chat_entry in available_agents["user_agent"].get("chat_entries", []): - if any(confirmation in chat_entry.lower() for confirmation in - ["ja", "yes", "bestätige", "confirm", "stimme zu", "agree"]): - user_agent_confirmed = True - break - - # Check for explicit workflow completion - if any(phrase in text for phrase in workflow_complete_phrases): - if result_exists and user_agent_confirmed: - return "WORKFLOW_COMPLETE" - elif not result_exists: - logger.warning("Moderator attempted to end workflow without complete results") - elif not user_agent_confirmed: - logger.warning("Moderator attempted to end workflow without User Agent confirmation") - if "user_agent" in available_agents: - return "user_agent" # Force User Agent selection to get confirmation - - # Check for explicit agent selection - if "ich wähle" in text or "i choose" in text or "i select" in text: - for agent_id, agent in available_agents.items(): - agent_name_lower = agent["name"].lower() - if agent_name_lower in text: - return agent_id - - # Check for User Agent queries - user_agent_phrases = [ - "user agent", - "benutzer", - "user", - "human", - "ask the user", - "frage den benutzer" - ] - - # If text contains User Agent phrases and a question, prioritize User Agent - has_question = "?" in text - has_user_phrase = any(phrase in text for phrase in user_agent_phrases) - - if has_question and has_user_phrase: - if "user_agent" in available_agents: - return "user_agent" - - # Direct name matching as last resort - for agent_id, agent in available_agents.items(): - agent_name_lower = agent["name"].lower() - if agent_name_lower in text: - return agent_id - - # If a complete result exists but User Agent hasn't confirmed, prioritize User Agent - if result_exists and not user_agent_confirmed and "user_agent" in available_agents: - return "user_agent" - - # If no agent explicitly selected, choose first unused agent - for agent_id, agent in available_agents.items(): - if not agent["used"]: - return agent_id - - # Last resort: reuse first agent - if available_agents: - return list(available_agents.keys())[0] - - return None - - - def _add_log( - self, - workflow_id: str, - message: str, - log_type: str, - agent_id: Optional[str] = None, - agent_name: Optional[str] = None - ) -> None: - """Fügt einen Protokolleintrag zum Workflow hinzu""" - results.add_log( - self.workflows, - workflow_id, - message, - log_type, - agent_id, - agent_name, - self.mandate_id, - self.user_id - ) - - def get_workflow_status(self, workflow_id: str) -> Optional[Dict[str, Any]]: - """Gibt den Status eines Workflows zurück""" - workflow_status = results.get_workflow_status(self.workflows, workflow_id) - # Füge Datenstatistik hinzu - if workflow_status and workflow_id in self.workflows: - workflow_status["data_stats"] = self.workflows[workflow_id].get("data_stats", { - "sent_bytes": 0, - "received_bytes": 0 - }) - # Füge das waiting_for_user-Flag explizit hinzu - workflow_status["waiting_for_user"] = self.workflows[workflow_id].get("waiting_for_user", False) - return workflow_status - - - def get_workflow_logs(self, workflow_id: str) -> Optional[List[Dict[str, Any]]]: - """Gibt die Protokolle eines Workflows zurück""" - return results.get_workflow_logs(self.workflows, workflow_id) - - def get_workflow_results(self, workflow_id: str) -> Optional[List[Dict[str, Any]]]: - """Gibt die Ergebnisse eines Workflows zurück""" - return results.get_workflow_results(self.workflows, workflow_id) - - async def close(self): - """Schließt die HTTP-Clients beim Beenden der Anwendung""" - await self.service_aichat.close() - await self.service_aiscrap.close() - - def stop_workflow(self, workflow_id: str) -> bool: - """ - Stoppt einen laufenden Workflow. - - Args: - workflow_id: ID des zu stoppenden Workflows - - Returns: - bool: True, wenn der Workflow erfolgreich gestoppt wurde, False wenn nicht gefunden - """ - logger.info(f"Stoppe Workflow {workflow_id}") - - if workflow_id not in self.workflows: - logger.warning(f"Workflow {workflow_id} nicht gefunden") - return False - - # Prüfen, ob der Workflow bereits beendet ist - current_status = self.workflows[workflow_id]["status"] - if current_status not in ["running", "pending"]: - logger.info(f"Workflow {workflow_id} ist bereits im Status {current_status}") - return False - - # Workflow-Status auf "stopped" setzen - self.workflows[workflow_id]["status"] = "stopped" - self.workflows[workflow_id]["progress"] = 1.0 # Korrigierter Zugriff auf den Workflow - self.workflows[workflow_id]["completed_at"] = datetime.now().isoformat() - - # Log-Eintrag für das Stoppen hinzufügen - self._add_log(workflow_id, "Workflow manuell gestoppt", "warning") - - # Ergebnisse speichern - results.save_workflow_results(self.workflows, workflow_id, self.results_dir) - - logger.info(f"Workflow {workflow_id} wurde gestoppt") - return True - - async def process_user_input(self, workflow_id: str, message: str, additional_files: List[Dict[str, Any]] = None) -> bool: - """ - Enhanced function to process user input for a running workflow. - Ensures user responses are properly tracked and prevents duplicate messages. - - Args: - workflow_id: ID of the workflow - message: User message - additional_files: List of additional files (optional) - - Returns: - bool: True if input was successfully processed - """ - if workflow_id not in self.workflows: - logger.warning(f"Workflow {workflow_id} not found") - return False - - # Check if the workflow is waiting for user input - if not self.workflows[workflow_id].get("waiting_for_user", False): - logger.warning(f"Workflow {workflow_id} is not waiting for user input") - return False - - logger.info(f"Processing user input for workflow {workflow_id}") - - # Get user information - user_info = await self._get_user_info(self.user_id) - user_name = user_info.get("full_name") or user_info.get("username") or f"User {self.user_id}" - - # Log entry for user input - self._add_log( - workflow_id, - f"User input received: {message[:50]}{'...' if len(message) > 50 else ''}", - "info", - "user_agent", - user_name - ) - - # Track user agent response in the agents module - from modules.agentservice_part_agents import track_user_agent_response - available_agents = self.workflows[workflow_id].get("available_agents", {}) - track_user_agent_response(available_agents, message) - - # Process additional files if provided - additional_context = "" - if additional_files and len(additional_files) > 0: - file_contexts = file_handling.prepare_file_contexts(additional_files, self.upload_dir) - file_contents = file_handling.read_file_contents( - file_contexts, - self.upload_dir, - workflow_id, - lambda wid, msg, typ, aid=None, aname=None: self._add_log(wid, msg, typ, aid, aname), - self.service_aichat # Pass AI service for image analysis - ) - - # Format file context for inclusion - file_context_text = file_handling.format_file_context_text(file_contexts, file_contents) - additional_context = f"\n\n### Additional Files:\n{file_context_text}" - - # Log entry for additional files - self._add_log( - workflow_id, - f"{len(additional_files)} additional files added", - "info", - "user_agent", - user_name - ) - - # Add new files to existing file contexts and contents - existing_file_contexts = self.workflows[workflow_id].get("file_contexts", []) - existing_file_contents = self.workflows[workflow_id].get("file_contents", {}) - - # Store existing IDs to avoid duplicates - existing_ids = {fc["id"] for fc in existing_file_contexts} - - # Add new file contexts (only if ID doesn't already exist) - for file_context in file_contexts: - if file_context["id"] not in existing_ids: - existing_file_contexts.append(file_context) - existing_ids.add(file_context["id"]) - - # Add new file contents - existing_file_contents.update(file_contents) - - # Update file contexts and contents in workflow - self.workflows[workflow_id]["file_contexts"] = existing_file_contexts - self.workflows[workflow_id]["file_contents"] = existing_file_contents - - # Combined message (user message + additional files) - combined_message = message + additional_context - - # Check for duplicate user messages in chat history - # This prevents the user's message from appearing twice - chat_history = self.workflows[workflow_id].get("chat_history", []) - last_message = chat_history[-1] if chat_history else None - - # Only add user message if the last message wasn't already from the user with the same content - is_duplicate = False - if last_message and last_message.get("role") == "user" and last_message.get("content", "").startswith(f"[User Agent: {user_name}]"): - # Check for content similarity to avoid duplicates - last_content = last_message.get("content", "").replace(f"[User Agent: {user_name}] ", "", 1) - if last_content == message: - is_duplicate = True - logger.warning(f"Detected duplicate user message, skipping addition to chat history") - - # Add user message to chat history if not duplicate - if not is_duplicate: - chat_history.append({ - "role": "user", - "content": f"[User Agent: {user_name}] {message}" - }) - - # Update chat history in workflow - self.workflows[workflow_id]["chat_history"] = chat_history - - # Estimate sent bytes - message_size = len(combined_message) - self.workflows[workflow_id]["data_stats"]["sent_bytes"] += message_size - - # Save the current state before continuing - results.save_workflow_results(self.workflows, workflow_id, self.results_dir) - - # Start a new task to continue the workflow - asyncio.create_task( - self._continue_workflow_after_user_input( - workflow_id, - combined_message, - user_name - ) - ) - - return True - - - - async def _continue_workflow_after_user_input(self, workflow_id: str, user_message: str, user_name: str) -> None: - """ - Enhanced function to continue a workflow after user input. - Ensures proper state tracking and prevents duplicate processing. - - Args: - workflow_id: ID of the workflow - user_message: User message - user_name: User name - """ - if workflow_id not in self.workflows: - logger.warning(f"Workflow {workflow_id} not found") - return - - # Update workflow status - self.workflows[workflow_id]["status"] = "running" - - # Log entry for continuation - self._add_log( - workflow_id, - "Workflow continues after user input", - "info" - ) - - # Get required data from workflow - chat_history = self.workflows[workflow_id].get("chat_history", []) - available_agents = self.workflows[workflow_id].get("available_agents", {}) - file_contexts = self.workflows[workflow_id].get("file_contexts", []) - file_contents = self.workflows[workflow_id].get("file_contents", {}) - - # Create user result (store agent result in the workflow) - user_result = results.create_agent_result( - workflow_id, - {"id": "user_agent", "name": "User Agent", "type": "user"}, - len(self.workflows[workflow_id].get("results", [])), - "User input", - file_contexts, - user_message, - self.mandate_id, - self.user_id - ) - - self.workflows[workflow_id]["results"].append(user_result) - - # Mark User Agent as used - if "user_agent" in available_agents: - available_agents["user_agent"]["used"] = True - - # Mark that we're no longer waiting for user input - CRITICAL - self.workflows[workflow_id]["waiting_for_user"] = False - - # Get current round and max rounds - current_round = self.workflows[workflow_id].get("current_round", 0) - max_rounds = 12 # Same value as in execute_workflow - - # Check if we've reached the maximum number of rounds - if current_round >= max_rounds: - self._add_log(workflow_id, f"Workflow automatically ended after {max_rounds} rounds and user input", "info") - self.workflows[workflow_id]["status"] = "completed" - self.workflows[workflow_id]["progress"] = 1.0 - self.workflows[workflow_id]["completed_at"] = datetime.now().isoformat() - - # Save results - results.save_workflow_results(self.workflows, workflow_id, self.results_dir) - return - - # Start next round - current_round += 1 - self.workflows[workflow_id]["current_round"] = current_round - self._add_log(workflow_id, f"Starting round {current_round} after user input", "info") - - # Run a moderator cycle - workflow_complete, waiting_for_user_input, selected_agent_id = await self._run_moderator_cycle( - workflow_id, - chat_history, - available_agents, - file_contexts, - file_contents, - is_user_input_continuation=True, - user_message=user_message - ) - - # Update workflow state based on moderator cycle result - if workflow_complete: - self.workflows[workflow_id]["status"] = "completed" - self._add_log(workflow_id, "Workflow successfully completed after user input", "success") - self.workflows[workflow_id]["progress"] = 1.0 - self.workflows[workflow_id]["completed_at"] = datetime.now().isoformat() - elif waiting_for_user_input: - # User Agent was selected again, we're waiting for more input - pass - elif current_round < max_rounds: - # Continue with more agent rounds if not waiting for input - asyncio.create_task( - self._continue_workflow_after_moderator_cycle( - workflow_id, - selected_agent_id - ) - ) - - # Update progress - if not self.workflows[workflow_id]["completed_at"]: - self.workflows[workflow_id]["progress"] = min(0.9, 0.1 + (current_round / max_rounds) * 0.8) - - # Save results - results.save_workflow_results(self.workflows, workflow_id, self.results_dir) - - - async def _continue_workflow_after_moderator_cycle(self, workflow_id: str, selected_agent_id: str) -> None: - """ - New method to continue workflow after a moderator cycle when not waiting for user input. - This facilitates smoother agent transitions and addresses the issue of the workflow not continuing properly. - - Args: - workflow_id: ID of the workflow - selected_agent_id: ID of the selected agent - """ - if workflow_id not in self.workflows: - logger.warning(f"Workflow {workflow_id} not found") - return - - # Get required data from workflow - chat_history = self.workflows[workflow_id].get("chat_history", []) - available_agents = self.workflows[workflow_id].get("available_agents", {}) - file_contexts = self.workflows[workflow_id].get("file_contexts", []) - file_contents = self.workflows[workflow_id].get("file_contents", {}) - - # Get current round and max rounds - current_round = self.workflows[workflow_id].get("current_round", 0) - max_rounds = 12 # Same value as in execute_workflow - - # Check if we've reached the maximum number of rounds - if current_round >= max_rounds: - self._add_log(workflow_id, f"Workflow automatically ended after {max_rounds} rounds", "info") - self.workflows[workflow_id]["status"] = "completed" - self.workflows[workflow_id]["progress"] = 1.0 - self.workflows[workflow_id]["completed_at"] = datetime.now().isoformat() - - # Save results - results.save_workflow_results(self.workflows, workflow_id, self.results_dir) - return - - # Start next round - current_round += 1 - self.workflows[workflow_id]["current_round"] = current_round - self._add_log(workflow_id, f"Starting round {current_round} (continuation)", "info") - - # Run another moderator cycle - workflow_complete, waiting_for_user_input, new_selected_agent_id = await self._run_moderator_cycle( - workflow_id, - chat_history, - available_agents, - file_contexts, - file_contents, - is_user_input_continuation=False - ) - - # Update workflow state based on moderator cycle result - if workflow_complete: - self.workflows[workflow_id]["status"] = "completed" - self._add_log(workflow_id, "Workflow successfully completed", "success") - self.workflows[workflow_id]["progress"] = 1.0 - self.workflows[workflow_id]["completed_at"] = datetime.now().isoformat() - elif waiting_for_user_input: - # User Agent was selected, we're waiting for input - pass - elif current_round < max_rounds: - # Continue with more agent rounds if not waiting for input and not at max rounds - asyncio.create_task( - self._continue_workflow_after_moderator_cycle( - workflow_id, - new_selected_agent_id - ) - ) - else: - # Max rounds reached - self.workflows[workflow_id]["status"] = "completed" - self._add_log(workflow_id, f"Workflow completed after reaching maximum rounds ({max_rounds})", "info") - self.workflows[workflow_id]["progress"] = 1.0 - self.workflows[workflow_id]["completed_at"] = datetime.now().isoformat() - - # Update progress - if not self.workflows[workflow_id]["completed_at"]: - self.workflows[workflow_id]["progress"] = min(0.9, 0.1 + (current_round / max_rounds) * 0.8) - - # Save results - results.save_workflow_results(self.workflows, workflow_id, self.results_dir) - - - async def _get_user_info(self, user_id: int) -> Dict[str, Any]: - """ - Ruft Benutzerinformationen aus der Datenbank ab. - - Args: - user_id: ID des Benutzers - - Returns: - Dict mit Benutzerinformationen - """ - try: - # Hier würden wir normalerweise die Benutzerinformationen aus einer Datenbank abrufen - # Für diese Implementierung verwenden wir Platzhalter - return { - "id": user_id, - "username": f"user_{user_id}", - "full_name": f"Benutzer {user_id}" - } - except Exception as e: - logger.error(f"Fehler beim Abrufen der Benutzerinformationen: {str(e)}") - return {"id": user_id} - - async def _sanitize_messages(self, messages): - """Sanitizes all messages to prevent API errors.""" - if not messages: - return messages - - sanitized = [] - for message in messages: - # Create a deep copy of the message - sanitized_message = message.copy() if isinstance(message, dict) else message - - if isinstance(sanitized_message, dict) and "content" in sanitized_message: - sanitized_message["content"] = self._sanitize_message_content(sanitized_message["content"]) - - sanitized.append(sanitized_message) - - return sanitized - - def _sanitize_message_content(self, content): - """Ensures content has no trailing whitespace.""" - if isinstance(content, str): - return content.rstrip() - - # If content is a list (for multimodal messages), process each item - if isinstance(content, list): - return [ - {**item, 'text': item['text'].rstrip() if isinstance(item.get('text'), str) else item.get('text')} - if isinstance(item, dict) and item.get('type') == 'text' - else item - for item in content - ] - - return content - - def _check_for_user_agent_query(self, message_content: str) -> bool: - """ - Prüft, ob ein Text eine Anfrage an den User-Agent enthält. - - Args: - message_content: Der zu prüfende Text - - Returns: - bool: True, wenn der Text eine Anfrage an den User-Agent enthält - """ - # Keine Prüfung, wenn der Text leer ist - if not message_content: - return False - - # Prüfmuster für User-Agent-Anfragen - user_agent_phrases = [ - 'User Agent', - 'Benutzer', - 'Was denken Sie', - 'Was denkst du', - 'Ihre Meinung', - 'deine Meinung', - 'Sind Sie zufrieden', - 'Gibt es weitere Fragen', - 'Wollen Sie', - 'Möchten Sie', - 'Kannst du', - 'Können Sie', - 'Könnten Sie', - 'Bitte teilen Sie uns mit', - 'Moderator zu User Agent' - ] - - # Text in Kleinbuchstaben umwandeln für case-insensitive Suche - content_lower = message_content.lower() - - # Prüfen, ob ein Fragezeichen enthalten ist - has_question_mark = '?' in message_content - - # Prüfen, ob eine der Phrasen enthalten ist - has_user_agent_phrase = any(phrase.lower() in content_lower for phrase in user_agent_phrases) - - # Spezielle Bedingungen für User-Agent-Anfragen - is_user_agent_query = ( - (has_question_mark and has_user_agent_phrase) or - ('user agent' in content_lower and 'workflow' in content_lower) or - 'moderator zu user agent' in content_lower - ) - return is_user_agent_query - - - - -# Singleton-Factory für AgentService-Instanzen pro Kontext -_agent_service_instances = {} - -def get_agentservice_interface(mandate_id: int = None, user_id: int = None) -> AgentService: - """ - Gibt eine AgentService-Instanz für den angegebenen Kontext zurück. - Wiederverwendet bestehende Instanzen. - """ - context_key = f"{mandate_id}_{user_id}" - if context_key not in _agent_service_instances: - _agent_service_instances[context_key] = AgentService(mandate_id, user_id) - return _agent_service_instances[context_key] - diff --git a/gwserver/modules/agentservice_part_agents.py b/gwserver/modules/agentservice_part_agents.py deleted file mode 100644 index f0d634b0..00000000 --- a/gwserver/modules/agentservice_part_agents.py +++ /dev/null @@ -1,421 +0,0 @@ -import os -import json -import logging -import re -from typing import Dict, Any, List, Optional, Tuple - -# Logger konfigurieren -logger = logging.getLogger(__name__) - -def get_agent_instructions(agent_type: str, agent: Dict[str, Any] = None, file_contexts: List[Dict[str, Any]] = None) -> str: - """ - Liefert Anweisungen für einen Agenten basierend auf seinen Attributen. - - Diese Version fügt explizite Informationen zu Datei-IDs hinzu. - - Args: - agent_type: Typ des Agenten - agent: Agent-Konfiguration mit allen Attributen - file_contexts: Liste der verfügbaren Dateien - - Returns: - Formatierte Anweisungen für den Agenten - """ - # Basis-Instruktionen aus dem Agenten-Profil extrahieren - base_instructions = "" - - if agent: - if agent.get("instructions"): - base_instructions += agent.get("instructions").strip() + "\n\n" - if agent.get("description"): - base_instructions += "Kontext: " + agent.get("description").strip() + "\n\n" - if agent.get("capabilities"): - base_instructions += "Deine Fähigkeiten: " + agent.get("capabilities").strip() + "\n\n" - - # Wenn keine Instruktionen gefunden wurden, verwende eine generische Anweisung - if not base_instructions: - base_instructions = """ - Analysiere die Anfrage gründlich und liefere ein konkretes, nützliches Ergebnis. - Strukturiere deine Antwort klar und beantworte alle Aspekte der Anfrage. - """ - - # Anweisung zur Selbstdeklaration des Ergebnisstatus hinzufügen - status_declaration = """ - WICHTIG: Deklariere am Ende deiner Antwort den Status deines Ergebnisses mit einem der folgenden Tags: - - [STATUS: ERGEBNIS] - Wenn du ein konkretes, vollständiges Ergebnis geliefert hast - [STATUS: TEILWEISE] - Wenn du ein teilweises Ergebnis geliefert hast, das noch ergänzt werden sollte - [STATUS: PLAN] - Wenn du hauptsächlich einen Plan oder eine Vorgehensweise vorgeschlagen hast - - Diese Deklaration hilft dem Moderator zu entscheiden, ob weitere Agentenarbeit erforderlich ist. - """ - - # Konkrete Dateiinformationen bereitstellen - file_info = "" - if file_contexts: - file_info = "Verfügbare Dateien:\n" - for file in file_contexts: - file_info += f"- {file['name']} (Typ: {file.get('type', 'unbekannt')}, ID: {file['id']})\n" - file_info += "\n" - - # Hinweise zum Dateiaufrufen - file_access = f""" - {file_info} - Um mehr Dateiinhalte anzufordern, verwende einen der folgenden Befehle: - - [[FILE:load_file(file_id=DATEI_ID, complete=true)]] - für den vollständigen Dateiinhalt - [[FILE:load_file(file_id=DATEI_ID, pages=[1,2,3])]] - für spezifische Seiten einer PDF - [[FILE:load_file(file_id=DATEI_ID, start=0, end=5000)]] - für Textabschnitte - - Ersetze DATEI_ID mit der tatsächlichen ID aus der Dateiliste oben (nur die ID-Nummer, keine Anführungszeichen). - """ - - return base_instructions + status_declaration + file_access - -def get_default_agent_instructions() -> str: - """ - Gibt Standard-Anweisungen für einen Agenten zurück, - wenn keine spezifischen Anweisungen verfügbar sind. - Diese Funktion gibt generische Anweisungen zurück, unabhängig vom Agententyp. - """ - return """ - Als Agent ist es deine Aufgabe, Anfragen zu analysieren und entsprechend deinen Fähigkeiten zu bearbeiten. - - Folge diesen allgemeinen Anweisungen: - 1. Verstehe die Anfrage gründlich - 2. Analysiere relevante Daten und Informationen - 3. Liefere präzise und hilfreiche Antworten - 4. Strukturiere deine Antwort klar und verständlich - - In deiner Antwort: - - Beginne mit einer Zusammenfassung der Anfrage - - Gib gut begründete Antworten oder Empfehlungen - - Führe wichtige Erkenntnisse klar auf - - Schließe mit konkreten nächsten Schritten oder Empfehlungen ab - - WICHTIG: Deklariere am Ende deiner Antwort den Status deines Ergebnisses: - [STATUS: ERGEBNIS], [STATUS: TEILWEISE] oder [STATUS: PLAN] - """ - - -def initialize_agents(agents: List[Dict[str, Any]]) -> Dict[str, Dict[str, Any]]: - """ - Initialisiert die Agenten mit ihren Fähigkeiten und Status - - Args: - agents: Liste der Agenten aus dem Workflow - - Returns: - Dictionary mit Agent-IDs als Schlüssel und Agent-Informationen - """ - available_agents = {} - - for agent in agents: - agent_id = agent["id"] - agent_name = agent["name"] - agent_type = agent["type"] - agent_capabilities = agent.get("capabilities", "") - - # Kopiere alle Felder vom Original-Agenten und füge used-Status hinzu - agent_data = agent.copy() - agent_data["used"] = False - agent_data["last_result_status"] = None # Für die Speicherung des Ergebnisstatus - - available_agents[agent_id] = agent_data - - # Log agent data for debugging - logger.debug(f"Initialized agent: {agent_name} (Type: {agent_type})") - if "instructions" in agent_data: - logger.debug(f"Agent {agent_name} has instructions of length: {len(agent_data['instructions'])}") - - logger.info(f"Initialized {len(available_agents)} agents for workflow") - return available_agents - - -def get_moderator_prompt(available_agents: Dict[str, Dict[str, Any]]) -> str: - """ - Erstellt einen Moderator-Prompt, der die Status-Deklarationen der Agenten berücksichtigt. - Der User Agent wird nur aufgerufen, wenn es Inputs von ihm benötigt. - - Args: - available_agents: Dictionary mit verfügbaren Agenten - - Returns: - Formatierter Prompt für den Moderator - """ - # Prüfen, ob der User Agent bereits verwendet wurde - user_agent_used = False - user_agent_confirmed = False - - if "user_agent" in available_agents: - user_agent_used = available_agents["user_agent"].get("used", False) - # Prüfe, ob der User Agent eine explizite Bestätigung gegeben hat - if user_agent_used: - for chat_entry in available_agents["user_agent"].get("chat_entries", []): - if any(confirmation in chat_entry.lower() for confirmation in ["ja", "bestätige", "stimme zu", "akzeptiere"]): - user_agent_confirmed = True - break - - base = """Du bist Moderator eines Multi-Agent-Systems. Deine Aufgabe ist es, die Agenten zu koordinieren, -um die Anfrage vollständig zu erfüllen und ein konkretes Endergebnis zu liefern. Der User wird nur aufgerufen, wenn es Inputs von ihm braucht, welche die anderen Agenten nicht liefern können. Somit immer zuerst die anderen Agenten fragen, zuletzt den User. - -WICHTIG: Der Workflow darf erst beendet werden, wenn TATSÄCHLICHE ERGEBNISSE geliefert wurden""" - - # Unterschiedliche Bedingungen für das Beenden des Workflows - if not user_agent_confirmed: - base += """ UND der User Agent explizit mit einem 'JA' bestätigt hat, dass er mit dem Ergebnis zufrieden ist. -KRITISCH WICHTIG: Bevor du den Workflow beendest, MUSST du den User Agent befragen, ob er mit den Ergebnissen zufrieden ist, -und er muss EXPLIZIT mit 'JA' oder einer eindeutigen Zustimmung antworten!""" - - agents_list = "\nVerfügbare Agenten:\n" - for agent_id, agent in available_agents.items(): - status = "✓ Bereits verwendet" if agent["used"] else "✗ Noch nicht verwendet" - result_status = "" - if agent["used"] and agent.get("last_result_status"): - result_status = f" (Letzte Antwort: {agent.get('last_result_status')})" - - description = agent.get("description", "") - capabilities = agent.get("capabilities", "") - agents_list += f"- {agent['name']} ({agent['type']}): {capabilities}\n {description}\n Status: {status}{result_status}\n" - - instructions = """ -Berücksichtige die STATUS-Deklarationen der Agenten bei deiner Entscheidung: - -- [STATUS: ERGEBNIS] - Der Agent hat ein vollständiges Ergebnis geliefert -- [STATUS: TEILWEISE] - Der Agent hat ein teilweises Ergebnis geliefert, weitere Arbeit ist nötig -- [STATUS: PLAN] - Der Agent hat einen Plan geliefert, keine konkreten Ergebnisse - -Mögliche Entscheidungen: -- Bei Agent-Auswahl: "Ich wähle [Agentname], um [konkrete Aufgabe]" -""" - - if not user_agent_confirmed: - instructions += """- Bei Abschluss (nur wenn [STATUS: ERGEBNIS] vorliegt): DU MUSST ZUERST den User Agent explizit fragen, ob er mit den Ergebnissen zufrieden ist. -Der User Agent MUSS mit "JA" oder einer eindeutigen Zustimmung antworten, bevor der Workflow beendet werden kann! - -WICHTIG: Du darfst den Workflow NICHT beenden, bevor der User Agent explizit mit "JA" bestätigt hat! -Stelle dem User Agent eine KLARE, DIREKTE Frage, ob er mit dem Ergebnis zufrieden ist oder ob er weitere Informationen benötigt. -""" - else: - instructions += """- Bei Abschluss (nur wenn [STATUS: ERGEBNIS] vorliegt und der User Agent mit "JA" bestätigt hat): "Workflow beenden - vollständiges Ergebnis erreicht" - -WICHTIG: Da der User Agent bereits seine Zustimmung gegeben hat, kannst du den Workflow jetzt beenden, wenn ein Agent ein konkretes [STATUS: ERGEBNIS] geliefert hat! -""" - - return base + agents_list + instructions - - -def track_user_agent_response(available_agents: Dict[str, Dict[str, Any]], message_content: str) -> None: - """ - Verfolgt die Antworten des User Agents, um eine explizite Bestätigung zu erkennen. - - Args: - available_agents: Dictionary mit verfügbaren Agenten - message_content: Inhalt der Nachricht des User Agents - """ - if "user_agent" not in available_agents: - return - - # Initialisiere das chat_entries Array, falls es noch nicht existiert - if "chat_entries" not in available_agents["user_agent"]: - available_agents["user_agent"]["chat_entries"] = [] - - # Füge die aktuelle Nachricht hinzu - available_agents["user_agent"]["chat_entries"].append(message_content) - - # Prüfe, ob die Nachricht eine explizite Bestätigung enthält - confirmation_phrases = ["ja", "bestätige", "stimme zu", "akzeptiere", "einverstanden", "passt", "okay", "ok"] - - has_confirmation = any(phrase in message_content.lower() for phrase in confirmation_phrases) - - # Setze das confirmed-Flag entsprechend - available_agents["user_agent"]["confirmed"] = has_confirmation - - # Loggen der Erkennung - if has_confirmation: - logger.info("User Agent hat explizit mit 'Ja' bestätigt") - else: - logger.info("User Agent hat keine eindeutige Bestätigung gegeben") - - -def create_agent_prompt(agent: Dict[str, Any], agent_instructions: str, file_contexts: List[Dict[str, Any]] = None) -> Dict[str, str]: - """Verbesserter Agent-Prompt mit Datei-IDs""" - # Füge Datei-ID-Infos hinzu, wenn verfügbar - file_info = "" - if file_contexts: - file_info = "\nVerfügbare Dateien:\n" - for file in file_contexts: - file_info += f"- {file['name']} (ID: {file['id']})\n" - - content = f""" - Du bist Agent {agent['name']} ({agent['type']}). - {agent_instructions} - - {file_info} - - Format: [Agent: {agent['name']}] Deine Antwort... - """.strip() - - return {"role": "system", "content": content} - - -def find_next_agent(moderator_text: str, available_agents: Dict[str, Dict[str, Any]]) -> Optional[str]: - """ - Findet den nächsten Agenten basierend auf der Moderator-Entscheidung. - Berücksichtigt die Anweisung zum Workflow-Abschluss nur, wenn ein Ergebnis vorliegt - und der User Agent explizit mit "JA" bestätigt hat. - - Args: - moderator_text: Text der Moderator-Entscheidung - available_agents: Dictionary mit verfügbaren Agenten - - Returns: - ID des nächsten Agenten oder "WORKFLOW_COMPLETE" zum Beenden - """ - text = moderator_text.lower() - - # Prüfe, ob der Workflow beendet werden soll - nur wenn vollständige Ergebnisse vorliegen - workflow_complete_phrases = [ - "workflow beenden - vollständiges ergebnis erreicht", - "workflow beenden - vollständiges ergebnis", - "vollständiges ergebnis erreicht" - ] - - # Prüfen, ob ein Agent ein Ergebnis geliefert hat - result_exists = False - for agent_id, agent in available_agents.items(): - if agent.get("used") and agent.get("last_result_status") == "ERGEBNIS": - result_exists = True - break - - # Prüfen, ob der User Agent bereits befragt wurde und mit "JA" bestätigt hat - user_agent_confirmed = False - if "user_agent" in available_agents and available_agents["user_agent"].get("used", False): - # Prüfe die letzte Nachricht des User Agents auf explizite Bestätigung - for chat_entry in available_agents["user_agent"].get("chat_entries", []): - if any(confirmation in chat_entry.lower() for confirmation in ["ja", "bestätige", "stimme zu", "akzeptiere"]): - user_agent_confirmed = True - break - - # Suche nach exakten Phrasen für Workflow-Beendigung - if "workflow beenden" in text: - # Wenn ein eindeutiges Ergebnis vorliegt und der User Agent explizit bestätigt hat - if result_exists and user_agent_confirmed: - if any(phrase in text for phrase in workflow_complete_phrases): - return "WORKFLOW_COMPLETE" - # Sonst: In den Logs warnen, dass Bedingungen für Beendigung nicht erfüllt sind - else: - if not result_exists: - logger.warning("Moderator versuchte, Workflow ohne vollständiges Ergebnis zu beenden") - if not user_agent_confirmed: - logger.warning("Moderator versuchte, Workflow ohne explizite Bestätigung des User Agents zu beenden") - # Wähle den User Agent aus, um eine explizite Bestätigung zu erhalten - if "user_agent" in available_agents: - return "user_agent" - - # Suche nach "ich wähle" Pattern für Agentenwahl - if "ich wähle" in text: - for agent_id, agent in available_agents.items(): - agent_name_lower = agent["name"].lower() - if agent_name_lower in text: - return agent_id - - # Fallback: Direktes Name-Matching - for agent_id, agent in available_agents.items(): - agent_name_lower = agent["name"].lower() - if agent_name_lower in text or f"agent {agent_name_lower}" in text: - return agent_id - - # Wenn kein Agent explizit gewählt wurde und User Agent noch nicht befragt wurde - # oder keine explizite Bestätigung gegeben hat, priorisiere den User Agent - if result_exists and (not "user_agent" in available_agents or - not available_agents["user_agent"].get("used", False) or - not user_agent_confirmed): - if "user_agent" in available_agents: - return "user_agent" - - # Wenn kein Agent explizit gewählt wurde: Wähle den ersten unbenutzten Agenten - for agent_id, agent in available_agents.items(): - if not agent["used"]: - return agent_id - - # Letzter Ausweg: Ersten Agenten wiederverwenden - if available_agents: - return list(available_agents.keys())[0] - - return None - -def update_agent_results_with_status(content: str) -> Tuple[str, str]: - """ - Extrahiert den deklarierten Status aus einem Agenten-Ergebnis. - - Args: - content: Der vom Agenten gelieferte Ergebnistext - - Returns: - Tuple mit (bereinigter Text, Status) - """ - # Standard-Status, falls keine Deklaration gefunden wird - status = "UNBEKANNT" - - # Suche nach Status-Deklaration - status_pattern = r'\[STATUS:\s*(ERGEBNIS|TEILWEISE|PLAN)\]' - match = re.search(status_pattern, content, re.IGNORECASE) - - if match: - # Extrahiere den Status - status = match.group(1).upper() - - # Entferne die Status-Deklaration aus dem Text - content = re.sub(status_pattern, '', content, flags=re.IGNORECASE).strip() - - return content, status - - -def extract_summary(text: str, max_length: int = 200) -> str: - """ - Extrahiert eine kurze Zusammenfassung aus einem Text. - - Args: - text: Der zu extrahierende Text - max_length: Maximale Länge der Zusammenfassung - - Returns: - Eine kurze Zusammenfassung des Textes - """ - # Erste Zeilen oder Absätze extrahieren - lines = text.split('\n') - paragraphs = [] - current_para = [] - - for line in lines: - line = line.strip() - if not line: - if current_para: - paragraphs.append(' '.join(current_para)) - current_para = [] - else: - current_para.append(line) - - if current_para: - paragraphs.append(' '.join(current_para)) - - # Versuche, den ersten oder zweiten Absatz als Zusammenfassung zu verwenden - if paragraphs: - summary = paragraphs[0] - - # Falls der erste Absatz zu kurz ist, versuche den zweiten hinzuzufügen - if len(summary) < 100 and len(paragraphs) > 1: - summary += " " + paragraphs[1] - - # Kürze auf die maximale Länge - if len(summary) > max_length: - summary = summary[:max_length-3] + "..." - - return summary - - # Fallback auf die ersten Zeichen des Textes - if text: - return text[:max_length-3] + "..." if len(text) > max_length else text - - return "Keine Zusammenfassung verfügbar" \ No newline at end of file diff --git a/gwserver/modules/agentservice_part_filehandling.py b/gwserver/modules/agentservice_part_filehandling.py deleted file mode 100644 index 31b287b5..00000000 --- a/gwserver/modules/agentservice_part_filehandling.py +++ /dev/null @@ -1,376 +0,0 @@ -import os -import logging -import pandas as pd -from typing import Dict, Any, List, Optional, Tuple - -# Logger konfigurieren -logger = logging.getLogger(__name__) - -async def read_file_contents( - file_contexts: List[Dict[str, Any]], - upload_dir: str, - workflow_id: str = None, - add_log_func = None, - ai_service = None # Added AI service parameter for image analysis -) -> Dict[str, str]: - """ - Enhanced function to read the contents of all files with proper image and document analysis. - - Args: - file_contexts: List of file contexts with metadata - upload_dir: Directory for uploads - workflow_id: Optional ID of the workflow for logging - add_log_func: Optional function for adding logs - ai_service: Optional AI service for image analysis - - Returns: - Dictionary with file contents (file_id -> content) - """ - file_contents = {} - - for file in file_contexts: - file_id = file["id"] - file_name = file["name"] - file_type = file.get("type", "unknown") - file_path = file.get("path", "") - - # If path is not set, try to derive it from the upload directory - if not file_path and file_name: - possible_path = os.path.join(upload_dir, file_name) - if os.path.exists(possible_path): - file_path = possible_path - file["path"] = file_path # Update the path in context - logger.debug(f"Found path for file {file_name}: {file_path}") - - # Read file content if path is available - if file_path and os.path.exists(file_path): - try: - # Image files - always perform image analysis if AI service is available - if file_type == "image" or file_name.lower().endswith(('.jpg', '.jpeg', '.png', '.gif', '.webp')): - if ai_service: - try: - _log(add_log_func, workflow_id, f"Analyzing image {file_name}...", "info") - image_analysis = await ai_service.analyze_image(file_path, "Describe this image in detail") - file_contents[file_id] = f"Image Analysis:\n{image_analysis}" - _log(add_log_func, workflow_id, f"Image {file_name} analyzed successfully", "info") - except Exception as e: - logger.error(f"Error analyzing image {file_name}: {str(e)}") - _log(add_log_func, workflow_id, f"Error analyzing image {file_name}: {str(e)}", "error") - file_contents[file_id] = f"Image file: {file_name} (Analysis failed: {str(e)})" - else: - file_contents[file_id] = f"Image file: {file_name} (AI analysis not available)" - - # Document files - elif file_type == "document" or not file_type: - # Simple text files - if file_name.endswith(('.txt', '.md', '.json', '.xml', '.html', '.htm', '.css', '.js')): - with open(file_path, 'r', encoding='utf-8', errors='replace') as f: - content = f.read() - file_contents[file_id] = content - _log(add_log_func, workflow_id, f"Text file {file_name} read successfully", "info") - - # Excel files - elif file_name.endswith(('.xlsx', '.xls')): - try: - df = pd.read_excel(file_path) - file_contents[file_id] = f"Excel file with {len(df)} rows and {len(df.columns)} columns.\n" - file_contents[file_id] += f"Columns: {', '.join(df.columns.tolist())}\n\n" - file_contents[file_id] += df.to_string(index=False) # Full table - _log(add_log_func, workflow_id, f"Excel file {file_name} read successfully", "info") - except Exception as e: - logger.error(f"Error reading Excel file {file_name}: {str(e)}") - _log(add_log_func, workflow_id, f"Error reading Excel file {file_name}: {str(e)}", "error") - file_contents[file_id] = f"Excel file: {file_name} (Reading failed: {str(e)})" - - # CSV files - elif file_name.endswith('.csv'): - try: - # Try various encodings and delimiters for robust CSV parsing - try: - df = pd.read_csv(file_path, encoding='utf-8') - except UnicodeDecodeError: - try: - df = pd.read_csv(file_path, encoding='latin1') - except: - df = pd.read_csv(file_path, encoding='cp1252') - - file_contents[file_id] = f"CSV file with {len(df)} rows and {len(df.columns)} columns.\n" - file_contents[file_id] += f"Columns: {', '.join(df.columns.tolist())}\n\n" - file_contents[file_id] += df.to_string(index=False) # Full table - _log(add_log_func, workflow_id, f"CSV file {file_name} read successfully", "info") - except Exception as e: - logger.error(f"Error reading CSV file {file_name}: {str(e)}") - _log(add_log_func, workflow_id, f"Error reading CSV file {file_name}: {str(e)}", "error") - file_contents[file_id] = f"CSV file: {file_name} (Reading failed: {str(e)})" - - # PDF files - with enhanced extraction and AI analysis - elif file_name.endswith('.pdf'): - try: - # Try PyPDF2 first - try: - from PyPDF2 import PdfReader - reader = PdfReader(file_path) - num_pages = len(reader.pages) - text = "" - for page in reader.pages: - text += page.extract_text() + "\n\n" - - # If AI service is available, also analyze images in PDF - if ai_service: - _log(add_log_func, workflow_id, f"Analyzing PDF images in {file_name}...", "info") - try: - image_analysis_results = await ai_service.extract_and_analyze_pdf_images( - file_path, - "Describe this image in the context of the document" - ) - - if image_analysis_results: - image_analysis_text = "\n\n=== PDF IMAGE ANALYSIS ===\n" - for result in image_analysis_results: - image_analysis_text += f"\nImage on page {result['page']}: {result['response']}\n" - text += image_analysis_text - _log(add_log_func, workflow_id, - f"Successfully analyzed {len(image_analysis_results)} images in PDF", - "info") - except Exception as img_error: - logger.error(f"Error analyzing PDF images: {str(img_error)}") - _log(add_log_func, workflow_id, - f"Error analyzing PDF images: {str(img_error)}", - "warning") - - file_contents[file_id] = f"PDF with {num_pages} pages.\nContent:\n{text}" - _log(add_log_func, workflow_id, f"PDF file {file_name} read successfully", "info") - - except ImportError: - # Try to use a different PDF library if available - try: - import fitz # PyMuPDF - doc = fitz.open(file_path) - text = "" - for page in doc: - text += page.get_text() + "\n\n" - file_contents[file_id] = f"PDF with {len(doc)} pages.\nContent:\n{text}" - _log(add_log_func, workflow_id, f"PDF file {file_name} read with PyMuPDF", "info") - except ImportError: - _log(add_log_func, workflow_id, - "No PDF library installed. Cannot extract PDF content.", "warning") - file_contents[file_id] = f"PDF file (content not available, PDF libraries missing)" - except Exception as e: - logger.error(f"Error reading PDF file {file_name}: {str(e)}") - _log(add_log_func, workflow_id, f"Error reading PDF file {file_name}: {str(e)}", "error") - file_contents[file_id] = f"PDF file: {file_name} (Reading failed: {str(e)})" - - # Other document types - else: - try: - # Try to read as binary first to check file type - with open(file_path, 'rb') as f: - first_bytes = f.read(8) # Read first few bytes to identify file type - - # Try to read as text if it appears to be text-based - try: - with open(file_path, 'r', encoding='utf-8', errors='replace') as f: - content = f.read() - file_contents[file_id] = content - _log(add_log_func, workflow_id, f"File {file_name} read as text", "info") - except Exception: - file_contents[file_id] = f"File content not available (Binary or unsupported format)" - _log(add_log_func, workflow_id, f"File {file_name} appears to be binary or has unknown format", "warning") - except Exception as e: - logger.error(f"Error processing file {file_name}: {str(e)}") - _log(add_log_func, workflow_id, f"Error processing file {file_name}: {str(e)}", "error") - file_contents[file_id] = f"File content not available (Error: {str(e)})" - - # Other file types - just store metadata - else: - file_contents[file_id] = f"File: {file_name} (Type: {file_type}, content not available)" - _log(add_log_func, workflow_id, f"Unsupported file type: {file_type} for {file_name}", "warning") - - except Exception as e: - logger.error(f"Error reading file {file_name}: {str(e)}") - _log(add_log_func, workflow_id, f"Error reading file {file_name}: {str(e)}", "error") - file_contents[file_id] = f"File content not available (Error: {str(e)})" - else: - if file_path: - _log(add_log_func, workflow_id, f"File {file_name} not found: {file_path}", "warning") - else: - _log(add_log_func, workflow_id, f"No path available for file {file_name}", "warning") - file_contents[file_id] = f"File content not available (File not found)" - - return file_contents - - -def format_file_context_text(file_contexts: List[Dict[str, Any]], file_contents: Dict[str, str]) -> str: - """ - Erstellt eine formatierte Textdarstellung aller Dateien und ihrer Inhalte - - Args: - file_contexts: Liste der Dateikontexte mit Metadaten - file_contents: Dictionary mit Dateiinhalten - - Returns: - Formatierter Text mit Dateiliste und Inhaltsauszügen - """ - # Erstelle einen Kontext mit Dateiliste und Inhalten für leichteren Zugriff - file_context_text = "Verfügbare Dateien:\n" + "\n".join([ - f"- {file['name']} ({file['type']}, {file['size']}, ID: {file['id']})" - for file in file_contexts - ]) - - # Füge Dateiinhalte hinzu (ohne Längenbegrenzung) - for file_id, content in file_contents.items(): - file_name = next((f['name'] for f in file_contexts if f['id'] == file_id), "Unbekannte Datei") - file_context_text += f"\n\n==== DATEIINHALT: {file_name} (ID: {file_id}) ====\n" - file_context_text += content - - return file_context_text - -def prepare_file_contexts(files: List[Dict[str, Any]], upload_dir: str) -> List[Dict[str, Any]]: - """ - Bereitet die Dateikontexte vor und ermittelt die vollen Dateipfade - - Args: - files: Liste von Dateien mit Metadaten (Dict mit id, name, type) - upload_dir: Verzeichnis für Uploads - - Returns: - Liste von Dateikontexten mit vollständigen Pfaden - """ - file_contexts = [] - - for file in files: - file_id = file["id"] - file_name = file["name"] - file_type = file["type"] - file_path = file.get("path", "") - - # Wenn kein Pfad angegeben ist, versuche, ihn aus dem Upload-Verzeichnis abzuleiten - if not file_path and file_name: - possible_path = os.path.join(upload_dir, file_name) - if os.path.exists(possible_path): - file_path = possible_path - logger.debug(f"Pfad für Datei {file_name} gefunden: {file_path}") - - file_contexts.append({ - "id": file_id, - "name": file_name, - "type": file_type, - "size": file.get("size", "Unbekannt"), - "path": file_path - }) - - return file_contexts - -async def prepare_message_for_ai( - file_contexts: List[Dict[str, Any]], - prompt_text: str, - file_contents: Dict[str, str], - service_aichat -) -> Dict[str, Any]: - """ - Enhanced function to prepare a complete message with all file contents for the AI model. - Ensures proper file content integration and handles image analysis results. - - Args: - file_contexts: List of file contexts with metadata - prompt_text: The text prompt - file_contents: Dictionary with file contents - service_aichat: The AI service instance for special analyses - - Returns: - A fully formatted message for the AI model - """ - # Use the AI connector to create the message - try: - message = await service_aichat.parse_filedata(file_contexts, prompt_text, file_contents) - - # Ensure file contents are correctly integrated - if isinstance(message, dict) and message.get("content") and isinstance(message["content"], list): - # For each file context, ensure its content is included - for file_context in file_contexts: - file_id = file_context["id"] - file_name = file_context["name"] - - # Check if file content is already included - file_mentioned = False - for content_item in message["content"]: - if isinstance(content_item, dict) and content_item.get("type") == "text": - if file_name in content_item.get("text", ""): - file_mentioned = True - break - - # If file is not mentioned but we have its content, add it - if not file_mentioned and file_id in file_contents: - content = file_contents[file_id] - message["content"].append({ - "type": "text", - "text": f"--- FILE: {file_name} ---\n\n{content}" - }) - logger.info(f"Added missing file content for {file_name} to message") - - return message - - except Exception as e: - logger.error(f"Error preparing message for AI: {str(e)}") - - # Create a basic message structure if the AI connector fails - message = { - "role": "user", - "content": prompt_text + "\n\n" - } - - # Manually add file contents - if file_contents: - file_content_text = "\n\n=== FILE CONTENTS ===\n\n" - for file_id, content in file_contents.items(): - # Find file name from contexts - file_name = next((f["name"] for f in file_contexts if f["id"] == file_id), f"File {file_id}") - file_content_text += f"--- FILE: {file_name} ---\n\n{content}\n\n" - - # Append to message - if isinstance(message["content"], str): - message["content"] += file_content_text - elif isinstance(message["content"], list): - message["content"].append({ - "type": "text", - "text": file_content_text - }) - - return message - -def _log(add_log_func, workflow_id, message, log_type, agent_id=None, agent_name=None): - """Hilfsfunktion zum Loggen mit unterschiedlichen Log-Funktionen""" - # Log über die Logger-Instanz - if log_type == "error": - logger.error(message) - elif log_type == "warning": - logger.warning(message) - else: - logger.info(message) - - # Log über die bereitgestellte Log-Funktion (falls vorhanden) - if add_log_func and workflow_id: - add_log_func(workflow_id, message, log_type, agent_id, agent_name) - -# Die folgenden Funktionen werden nicht mehr benötigt, da partielle Dateiladungen entfallen -# Sie sind hier auskommentiert, könnten später aber wieder aktiviert werden - -""" -def parse_file_access_commands(agent_text: str) -> List[Dict[str, Any]]: - # Diese Funktion wird vorerst nicht benötigt - return [] - -def load_additional_file_content( - workflow_id: str, - file_id: str, - file_contents: Dict[str, str], - file_contexts: List[Dict[str, Any]], - add_log_func = None, - read_complete: bool = False, - start_pos: int = None, - end_pos: int = None, - page_numbers: List[int] = None -) -> Optional[str]: - # Diese Funktion wird vorerst nicht benötigt - return None -""" \ No newline at end of file diff --git a/gwserver/modules/agentservice_part_results.py b/gwserver/modules/agentservice_part_results.py deleted file mode 100644 index e0a8837d..00000000 --- a/gwserver/modules/agentservice_part_results.py +++ /dev/null @@ -1,214 +0,0 @@ -import os -import json -import logging -import uuid -from datetime import datetime -from typing import Dict, Any, List, Optional - -# Logger konfigurieren -logger = logging.getLogger(__name__) - -def create_agent_result( - workflow_id: str, - agent: Dict[str, Any], - index: int, - prompt: str, - file_contexts: List[Dict[str, Any]], - content: str, - mandate_id: int = None, - user_id: int = None -) -> Dict[str, Any]: - """ - Erstellt ein Ergebnisobjekt basierend auf dem Agententyp und der API-Antwort. - Diese Version berücksichtigt die Status-Deklaration des Agenten. - - Args: - workflow_id: ID des Workflows - agent: Agent-Informationen - index: Index des Ergebnisses - prompt: Ursprünglicher Prompt - file_contexts: Liste der Dateikontexte - content: Inhalt der Agent-Antwort - mandate_id: Optional ID des Mandanten - user_id: Optional ID des Benutzers - - Returns: - Ein Ergebnisobjekt für den Workflow - """ - # Importiere die Hilfsfunktionen aus dem agents-Modul - from modules.agentservice_part_agents import update_agent_results_with_status, extract_summary - - agent_type = agent["type"] - agent_id = agent["id"] - agent_name = agent["name"] - - # Extrahiere den Status aus dem Ergebnis - cleaned_content, result_status = update_agent_results_with_status(content) - - # Speichere den Status im Agenten für späteren Zugriff - agent["last_result_status"] = result_status - - # Entferne Agent-Präfix aus der Antwort, falls vorhanden - agent_prefix = f"[Agent: {agent_name}]" - if cleaned_content.startswith(agent_prefix): - cleaned_content = cleaned_content[len(agent_prefix):].strip() - - # Titel basierend auf Agent-Type und deklariertem Status erstellen - title_prefix = { - "ERGEBNIS": "Ergebnis", - "TEILWEISE": "Teilweises Ergebnis", - "PLAN": "Vorgeschlagener Plan", - "UNBEKANNT": "Antwort" - }.get(result_status, "Antwort") - - # Titel basierend auf Agent-Attributen erstellen - agent_desc = agent.get("description", f"Agent {agent_name}") - title = f"{title_prefix}: {agent_desc}" - - # Extrahiere Dateinamen für die Metadaten - file_names = [file["name"] for file in file_contexts] - - # Grundlegende Ergebnisstruktur - result = { - "id": f"result_{workflow_id}_{index}", - "mandate_id": mandate_id, - "user_id": user_id, - "agent_id": agent_id, - "agent_name": agent_name, - "timestamp": datetime.now().isoformat(), - "type": "text", # Standardtyp - "title": title, - "content": cleaned_content, - "summary": extract_summary(cleaned_content, max_length=200), - "metadata": { - "files_processed": file_names, - "prompt": prompt, - "agent_type": agent_type, - "result_status": result_status, - "capabilities": agent.get("capabilities", "") - } - } - return result - - -def add_log( - workflows: Dict[str, Dict[str, Any]], - workflow_id: str, - message: str, - log_type: str, - agent_id: Optional[str] = None, - agent_name: Optional[str] = None, - mandate_id: int = None, - user_id: int = None -) -> None: - """ - Fügt einen Protokolleintrag zum Workflow hinzu - - Args: - workflows: Dictionary mit Workflow-Informationen - workflow_id: ID des Workflows - message: Log-Nachricht - log_type: Typ des Logs (info, warning, error, etc.) - agent_id: Optional ID des Agenten - agent_name: Optional Name des Agenten - mandate_id: Optional ID des Mandanten - user_id: Optional ID des Benutzers - """ - log_entry = { - "id": f"log_{uuid.uuid4()}", - "mandate_id": mandate_id, - "user_id": user_id, - "message": message, - "type": log_type, - "timestamp": datetime.now().isoformat(), - "agent_id": agent_id, - "agent_name": agent_name - } - - workflow = workflows.get(workflow_id) - if workflow: - workflow["logs"].append(log_entry) - logger.info(f"Workflow {workflow_id}: {message}") - else: - logger.warning(f"Versuch, einem nicht existierenden Workflow Logs hinzuzufügen: {workflow_id}") - -def save_workflow_results(workflows: Dict[str, Dict[str, Any]], workflow_id: str, results_dir: str) -> None: - """ - Speichert die Workflow-Ergebnisse in einer Datei - - Args: - workflows: Dictionary mit Workflow-Informationen - workflow_id: ID des Workflows - results_dir: Verzeichnis für Ergebnisse - """ - workflow = workflows.get(workflow_id) - if workflow: - try: - file_path = os.path.join(results_dir, f"workflow_{workflow_id}.json") - with open(file_path, 'w', encoding='utf-8') as f: - json.dump(workflow, f, indent=2, ensure_ascii=False) - logger.info(f"Workflow-Ergebnisse gespeichert: {file_path}") - except Exception as e: - logger.error(f"Fehler beim Speichern der Workflow-Ergebnisse: {e}") - else: - logger.error(f"Workflow nicht gefunden: {workflow_id}") - -def get_workflow_status(workflows: Dict[str, Dict[str, Any]], workflow_id: str) -> Optional[Dict[str, Any]]: - """ - Gibt den Status eines Workflows zurück - - Args: - workflows: Dictionary mit Workflow-Informationen - workflow_id: ID des Workflows - - Returns: - Ein Dictionary mit Statusinformationen oder None, wenn der Workflow nicht existiert - """ - workflow = workflows.get(workflow_id) - if not workflow: - return None - - return { - "id": workflow["id"], - "mandate_id": workflow.get("mandate_id"), - "user_id": workflow.get("user_id"), - "status": workflow["status"], - "progress": workflow["progress"], - "started_at": workflow["started_at"], - "completed_at": workflow["completed_at"], - "agent_statuses": workflow["agent_statuses"] - } - -def get_workflow_logs(workflows: Dict[str, Dict[str, Any]], workflow_id: str) -> Optional[List[Dict[str, Any]]]: - """ - Gibt die Protokolle eines Workflows zurück - - Args: - workflows: Dictionary mit Workflow-Informationen - workflow_id: ID des Workflows - - Returns: - Eine Liste mit Logs oder None, wenn der Workflow nicht existiert - """ - workflow = workflows.get(workflow_id) - if not workflow: - return None - - return workflow["logs"] - -def get_workflow_results(workflows: Dict[str, Dict[str, Any]], workflow_id: str) -> Optional[List[Dict[str, Any]]]: - """ - Gibt die Ergebnisse eines Workflows zurück - - Args: - workflows: Dictionary mit Workflow-Informationen - workflow_id: ID des Workflows - - Returns: - Eine Liste mit Ergebnissen oder None, wenn der Workflow nicht existiert - """ - workflow = workflows.get(workflow_id) - if not workflow: - return None - - return workflow["results"] \ No newline at end of file diff --git a/gwserver/modules/agentservice_registry.py b/gwserver/modules/agentservice_registry.py new file mode 100644 index 00000000..811c0c41 --- /dev/null +++ b/gwserver/modules/agentservice_registry.py @@ -0,0 +1,136 @@ +""" +Registry für alle verfügbaren Agenten im System. +Verwaltet die Agenten-Instanzen und stellt sie für den Workflow zur Verfügung. +""" + +import logging +import importlib +from typing import Dict, Any, List, Optional + +# Import direkt bekannter Agent-Module +# Andere Module werden dynamisch importiert +from modules.agentservice_base import BaseAgent + +logger = logging.getLogger(__name__) + +class AgentRegistry: + """Registry für alle verfügbaren Agenten im System""" + + _instance = None + + @classmethod + def get_instance(cls): + """Gibt eine Singleton-Instanz der Agent-Registry zurück""" + if cls._instance is None: + cls._instance = cls() + return cls._instance + + def __init__(self): + """Initialisiert die Agent-Registry""" + if AgentRegistry._instance is not None: + raise RuntimeError("Singleton-Instanz existiert bereits - nutze get_instance()") + self.agents = {} + self._load_agents() + + def _load_agents(self): + """Lädt alle verfügbaren Agenten""" + # Liste aller zu ladenden Agenten-Module + agent_modules = [ + "agentservice_agent_user", + "agentservice_agent_coder", + "agentservice_agent_analyst", + "agentservice_agent_webcrawler", + "agentservice_agent_sharepoint", + "agentservice_agent_documentation" + ] + + for module_name in agent_modules: + try: + # Importiere das Modul + try: + module = importlib.import_module(f"modules.{module_name}") + except ImportError: + module = importlib.import_module(module_name) + + # Suche nach der Agent-Klasse statt nach getter-Funktion + agent_type = module_name.split('_')[-1] + class_name = f"{agent_type.capitalize()}Agent" + + if hasattr(module, class_name): + # Instanziiere den Agenten direkt + agent_class = getattr(module, class_name) + agent = agent_class() + + # Registriere den Agenten + self.register_agent(agent) + logger.info(f"Agent '{agent.name}' (Typ: {agent.type}) wurde geladen") + else: + logger.warning(f"Keine {class_name} Klasse in Modul {module_name} gefunden") + + except ImportError as e: + logger.warning(f"Modul {module_name} konnte nicht importiert werden: {e}") + except Exception as e: + logger.error(f"Fehler beim Laden des Agenten aus Modul {module_name}: {e}") + + def register_agent(self, agent: BaseAgent): + """Registriert einen Agenten in der Registry.""" + agent_type = agent.type + self.agents[agent_type] = agent + # Zusätzlich nach ID registrieren + self.agents[agent.id] = agent + logger.debug(f"Agent '{agent.name}' (Typ: {agent_type}) wurde registriert") + + def get_agent(self, agent_identifier: str) -> Optional[BaseAgent]: + """ + Gibt eine Instanz eines Agenten nach ID oder Typ zurück. + + Args: + agent_identifier: ID oder Typ des gewünschten Agenten + + Returns: + Agent-Instanz oder None, wenn nicht gefunden + """ + # Versuche, direkt nach Typ zu finden + if agent_identifier in self.agents: + return self.agents[agent_identifier] + + # Wenn nicht gefunden, versuche verschiedene Varianten des Namens + variants = [ + agent_identifier, + agent_identifier.replace('_agent', ''), + f"{agent_identifier}_agent" + ] + + for variant in variants: + if variant in self.agents: + return self.agents[variant] + + logger.warning(f"Agent mit Identifier '{agent_identifier}' nicht gefunden") + return None + + def get_all_agents(self) -> Dict[str, BaseAgent]: + """Gibt alle registrierten Agenten zurück.""" + return self.agents + + def get_agent_infos(self) -> List[Dict[str, Any]]: + """Gibt Informationen zu allen registrierten Agenten zurück.""" + agent_infos = [] + # Nur einmal pro Agent-Instanz (da wir sowohl nach Typ als auch nach ID registrieren) + seen_agents = set() + for agent in self.agents.values(): + if agent not in seen_agents: + agent_infos.append(agent.get_agent_info()) + seen_agents.add(agent) + return agent_infos + + def initialize_agents_for_workflow(self) -> Dict[str, Dict[str, Any]]: + """Initialisiert Agenten für einen Workflow.""" + initialized_agents = {} + seen_agents = set() + for agent in self.agents.values(): + if agent not in seen_agents: + agent_info = agent.get_agent_info() + agent_id = agent_info["id"] + initialized_agents[agent_id] = agent_info + seen_agents.add(agent) + return initialized_agents \ No newline at end of file diff --git a/gwserver/modules/agentservice_workflow_manager.py b/gwserver/modules/agentservice_workflow_manager.py new file mode 100644 index 00000000..c84793c2 --- /dev/null +++ b/gwserver/modules/agentservice_workflow_manager.py @@ -0,0 +1,1221 @@ +""" +Manager für Workflow-Ausführung im Agentservice. +Steuert den gesamten Ablauf eines Workflow-Durchlaufs. + +Implementiert die neue Workflow-Struktur und Ausführungslogik gemäß den Anforderungen. +Unterstützt sowohl neue Workflows als auch die Fortsetzung bestehender Workflows mit Benutzereingaben. +Angepasst für die verbesserte Dateibehandlung. +""" + +import os +import logging +import asyncio +import uuid +import json +from datetime import datetime +from typing import List, Dict, Any, Optional, Tuple, Union + +# Import von Modulen +from modules.agentservice_registry import AgentRegistry +from modules.agentservice_filehandling import prepare_file_contexts, read_file_contents, extract_files_from_message, add_file_to_message + +# Import neuer Modellklassen +try: + from modules.lucydom_model import Message, Workflow, Document, DocumentSource, DocumentContent, DataStats +except ImportError: + # Fallback-Definitionen + class Message(Dict[str, Any]): pass + class Workflow(Dict[str, Any]): pass + class Document(Dict[str, Any]): pass + class DocumentSource(Dict[str, Any]): pass + class DocumentContent(Dict[str, Any]): pass + class DataStats(Dict[str, Any]): pass + +logger = logging.getLogger(__name__) + +registry = AgentRegistry.get_instance() +agent = registry.get_agent("user_agent") + +class WorkflowError(Exception): + """Basis-Exception für Workflow-Fehler""" + pass + +class WorkflowNotFoundError(WorkflowError): + """Exception wenn ein Workflow nicht gefunden wurde""" + pass + +class WorkflowExecutionError(WorkflowError): + """Exception bei der Ausführung eines Workflows""" + pass + +class WorkflowManager: + """Manager für die Ausführung von Workflows""" + + def __init__(self, mandate_id: int = None, user_id: int = None, ai_service = None, lucydom_interface = None): + """ + Initialisiert den WorkflowManager. + + Args: + mandate_id: ID des Mandanten + user_id: ID des Benutzers + ai_service: Service für KI-Anfragen + lucydom_interface: Interface für Datenbankzugriffe (optional) + """ + self.mandate_id = mandate_id + self.user_id = user_id + self.ai_service = ai_service + self.lucydom_interface = lucydom_interface + + # Lade Konfiguration aus config.ini + import configload + config = configload.load_config() + + # Verzeichnisse für Ergebnisse und Uploads aus der Konfiguration lesen + self.results_dir = config.get('Module_AgentserviceInterface', 'RESULTS_DIR', fallback='results') + + # Maximale Anzahl an Nachrichten im Verlauf + self.max_history = int(config.get('Module_AgentserviceInterface', 'MAX_HISTORY', fallback='20')) + + # Stelle sicher, dass die Verzeichnisse existieren + os.makedirs(self.results_dir, exist_ok=True) + + # Aktive Workflows + self.workflows = {} + + # Lade aktive Workflows aus der Datenbank, falls verfügbar + if self.lucydom_interface: + self._load_active_workflows() + + logger.info(f"WorkflowManager initialisiert mit Mandant {mandate_id}, Benutzer {user_id}") + + + async def execute_workflow( + self, + message: Dict[str, Any], + workflow_id: Optional[str] = None, + files: List[Dict[str, Any]] = None, + is_user_input: bool = False # Parameter to identify user input + ) -> Dict[str, Any]: + """ + Führt einen Workflow aus, entweder durch Erstellen eines neuen oder + Fortsetzen eines bestehenden Workflows mit Benutzereingabe. + + Args: + message: Die Nachricht (Prompt oder Benutzereingabe) + workflow_id: Optional ID eines bestehenden Workflows + files: Optionale Liste von Dateimetadaten + is_user_input: Flag, das anzeigt, ob es sich um eine Benutzereingabe handelt + + Returns: + Dictionary mit Workflow-Status und Ergebnis + """ + # Add detailed debug logging + logger.info(f"execute_workflow called: workflow_id={workflow_id}, is_user_input={is_user_input}, message={message.get('content', '')[:50]}...") + + # Detailed file logging + if files: + logger.info(f"Files provided: {len(files)} files") + for file in files: + file_id = file.get('id', 'unknown') + file_name = file.get('name', 'unnamed') + file_type = file.get('type', 'unknown') + file_content_type = file.get('content_type', 'unknown') + logger.info(f"File: {file_name} (ID: {file_id}, Type: {file_type}, Content-Type: {file_content_type})") + else: + logger.info("No files provided with the message") + + # 4.1 Unterscheide zwischen neuem Workflow und bestehender Benutzereingabe + is_new_workflow = workflow_id is None + + if is_new_workflow: + # Variante (A): Neuen Workflow erstellen + workflow_id = f"wf_{uuid.uuid4()}" + workflow = self._initialize_workflow(workflow_id) + workflow["name"] = message.get("content", "")[:50] # Kurzer Titel aus dem Inhalt + workflow["status"] = "running" + self._add_log(workflow, "Neuer Workflow gestartet", "info") + else: + # Variante (B): Bestehenden Workflow laden + try: + workflow = await self.load_workflow(workflow_id) + if not workflow: + raise WorkflowNotFoundError(f"Workflow {workflow_id} nicht gefunden") + + # Wenn der Workflow noch läuft, beende ihn ordnungsgemäß + if workflow["status"] == "running": + self._add_log(workflow, f"Neuer Benutzereingabe erhalten - Vorherigen Workflow beenden", "info") + # Status auf completed setzen, damit er für den neuen Input bereit ist + workflow["status"] = "completed" + + self._add_log(workflow, f"Starte Workflow-Ausführung, Nachrichtenlänge: {len(message.get('content', ''))}, {len(files or [])} Dateien", "info") + + + # Status auf "running" setzen + workflow["status"] = "running" + workflow["last_activity"] = datetime.now().isoformat() + self._add_log(workflow, "Workflow nach Benutzereingabe fortgesetzt", "info") + except WorkflowNotFoundError as e: + logger.error(f"Workflow nicht gefunden: {str(e)}") + return { + "workflow_id": workflow_id, + "status": "error", + "error": f"Workflow nicht gefunden: {workflow_id}" + } + except WorkflowError as e: + logger.error(f"Workflow-Fehler: {str(e)}") + return { + "workflow_id": workflow_id, + "status": "error", + "error": str(e) + } + + logger.debug(f"Workflow initialisiert: {workflow_id}, Status: {workflow['status']}") + + try: + # 4.2 Message-Initialisierung + # Letztes Message-Objekt abschließen (falls vorhanden) + if "messages" in workflow and workflow["messages"]: + self._finalize_last_message(workflow) + + # Neues Message-Objekt erstellen + new_message = self._create_message(workflow_id, message.get("role", "user")) + new_message["content"] = message.get("content", "") + + # Log the message creation + logger.info(f"Created new message with ID {new_message['id']} and content: {new_message['content'][:50]}...") + + + # 4.3 Dateivorbereitung + if files and len(files) > 0: + # Add detailed logging + logger.info(f"Processing {len(files)} files for message {new_message['id']}") + for f in files: + logger.info(f"Processing file: {f.get('name', 'unknown')} (ID: {f.get('id', 'unknown')})") + + # Dateikontexte vorbereiten - enthält nur Metadaten + file_contexts = prepare_file_contexts(files) + self._add_log(workflow, f"{len(files)} Dateien werden verarbeitet", "info") + + # Dateiinhalte lesen und zum Message-Objekt hinzufügen + # LucyDOM-Interface wird für Dateizugriffe genutzt + file_contents = await read_file_contents( + file_contexts, + self.lucydom_interface, + workflow_id, + self._add_log, + self.ai_service + ) + logger.debug(f"Dateien geladen für Workflow {workflow_id}: {file_contents.keys()}") + + for file_id, content in file_contents.items(): + file_metadata = next((f for f in files if f.get('id') == file_id), {}) + file_data = { + "id": file_id, + "name": file_metadata.get('name', next((f.get('name', 'unnamed_file') for f in file_contexts if f.get('id') == file_id), 'unnamed_file')), + "content_type": file_metadata.get('content_type', next((f.get('content_type') for f in file_contexts if f.get('id') == file_id), None)), + "type": file_metadata.get('type', next((f.get('type') for f in file_contexts if f.get('id') == file_id), "unknown")), + "content": content, + "size": file_metadata.get('size') + } + logger.info(f"Adding file {file_data['name']} (ID: {file_id}) to message {new_message['id']}") + try: + # Add file to message and check document count before and after + doc_count_before = len(new_message.get("documents", [])) + new_message = add_file_to_message(new_message, file_data) + doc_count_after = len(new_message.get("documents", [])) + + if doc_count_after > doc_count_before: + logger.info(f"File successfully added to message. Document count: {doc_count_after}") + else: + logger.warning(f"File may not have been added to message properly. Document count unchanged: {doc_count_before}") + except Exception as e: + logger.error(f"Error adding file to message: {str(e)}") + self._add_log(workflow, f"Fehler beim Hinzufügen der Datei {file_data['name']}: {str(e)}", "error") + + # Message zum Workflow hinzufügen + if "messages" not in workflow: + workflow["messages"] = [] + + # Log the message document count before adding to workflow + logger.info(f"Adding message with {len(new_message.get('documents', []))} documents to workflow {workflow_id}") + workflow["messages"].append(new_message) + + # Immediately save workflow to persist file attachments + self._save_workflow(workflow) + logger.info(f"Saved workflow state after adding message with {len(new_message.get('documents', []))} documents") + + + # 4.4 Agent-Initialisierung + agents = registry.initialize_agents_for_workflow() + + # 4.5 Moderator-Entscheidung (mit OpenAI API) + agent_tasks = await self._decide_agent_tasks(new_message, agents) + + # Speichere den aktuellen Zwischenstand + self._save_workflow(workflow) + + # Nach Agenten-Entscheidung + self._add_log(workflow, f"Agenten-Entscheidung abgeschlossen: {len(agent_tasks)} Aufgaben zugewiesen", "info") + logger.debug(f"Agent-Tasks für Workflow {workflow_id}: {[task['agent_id'] for task in agent_tasks]}") + + for task in agent_tasks: + self._add_log(workflow, f"Agent {task['agent_id']} wurde ausgewählt mit Aufgabe: {task['prompt'][:50]}...", "info") + + # 4.6 Agent-Ausführung + + # Filtern der Aufgaben nach Typ + system_agent_tasks = [task for task in agent_tasks if task["agent_id"] != "user_agent"] + user_agent_task = next((task for task in agent_tasks if task["agent_id"] == "user_agent"), None) + + # 1. System-Agenten ausführen, falls vorhanden + agent_results = [] + last_result = None + + if system_agent_tasks: + self._add_log(workflow, f"{len(system_agent_tasks)} System-Agenten werden ausgeführt", "info") + + for task in system_agent_tasks: + agent_id = task["agent_id"] + agent_prompt = task["prompt"] + + # Wenn ein vorheriges Ergebnis existiert, in den Prompt einbinden + if last_result: + agent_prompt = f"{agent_prompt}\n\nVorheriges Ergebnis: {last_result}" + + self._add_log(workflow, f"Agent {agent_id} wird ausgeführt", "info") + + # Agenten ausführen + agent_result = await self._execute_agent(workflow, agent_id, agent_prompt) + + if agent_result: + agent_results.append(agent_result) + last_result = agent_result.get("content", "") + + # 2. Immer den User-Agent aufrufen, entweder mit dem Moderator-Prompt oder einem generischen + # Prompt basierend auf den Ergebnissen der System-Agenten + if user_agent_task: + # Verwende den spezifischen Prompt vom Moderator + user_prompt = user_agent_task["prompt"] + else: + # Erstelle einen generischen Prompt basierend auf den System-Agent-Ergebnissen + if agent_results: + # Wenn System-Agenten ausgeführt wurden, fasse ihre Ergebnisse zusammen + summary = await self._create_summary(agent_results) + user_prompt = f"Die Agenten haben ihre Aufgaben abgeschlossen. Hier ist eine Zusammenfassung der Ergebnisse:\n\n{summary}\n\nBenötigen Sie weitere Informationen oder haben Sie Fragen dazu?" + else: + # Wenn keine System-Agenten ausgeführt wurden + user_prompt = "Die Agenten haben keine spezifischen Aufgaben durchgeführt. Gibt es etwas, wobei ich Ihnen helfen kann?" + + # 3. User-Agent-Nachricht erstellen und zum Workflow hinzufügen + workflow["status"] = "completed" # Workflow is complete, ready for new prompt + + user_message = { + "role": "assistant", + "content": f"[Moderator zu User Agent] {user_prompt}", + "agent_type": "moderator", + "agent_id": "moderator", + "agent_name": "Moderator", + "workflow_complete": True # Signal completion instead of waiting + } + # Nachricht zum Workflow hinzufügen + workflow["messages"].append(user_message) + + # Log-Eintrag + self._add_log(workflow, f"Workflow wartet auf Benutzereingabe: {user_prompt[:50]}...", "info") + + # Workflow speichern + self._save_workflow(workflow) + + # Fertig - Backend wartet jetzt auf nächsten API-Call vom Frontend + return { + "workflow_id": workflow_id, + "status": "completed", + "messages": workflow.get("messages", []) + } + + except Exception as e: + # Fehlerbehandlung + workflow["status"] = "failed" + self._add_log(workflow, f"Fehler bei der Workflow-Ausführung: {str(e)}", "error") + self._save_workflow(workflow) + logger.error(f"Fehler bei der Workflow-Ausführung: {str(e)}", exc_info=True) + + return { + "workflow_id": workflow_id, + "status": "failed", + "error": str(e) + } + + def _load_active_workflows(self): + """Lädt aktive Workflows aus der Datenbank""" + try: + if not self.lucydom_interface: + return + + # Aktive Workflows für den aktuellen Benutzer abrufen + user_workflows = self.lucydom_interface.get_workflows_by_user(self.user_id) + active_workflows = [wf for wf in user_workflows if wf.get("status") in ["running", "completed"]] + + # Aktive Workflows in den Speicher laden + for workflow_base in active_workflows: + workflow_id = workflow_base.get("id") + if not workflow_id: + continue + + # Vollständigen Workflow-Zustand laden + workflow = self.lucydom_interface.load_workflow_state(workflow_id) + if workflow: + self.workflows[workflow_id] = workflow + logger.info(f"Aktiven Workflow {workflow_id} aus Datenbank geladen") + except Exception as e: + logger.error(f"Fehler beim Laden der aktiven Workflows: {str(e)}") + + def _save_workflow(self, workflow: Dict[str, Any]) -> None: + """ + Speichert den Workflow in der Datenbank und als Datei. + + Args: + workflow: Das zu speichernde Workflow-Objekt + """ + workflow_id = workflow.get("id") + + # In der Datenbank speichern, falls verfügbar + if self.lucydom_interface: + try: + success = self.lucydom_interface.save_workflow_state(workflow) + if success: + logger.debug(f"Workflow {workflow_id} in Datenbank gespeichert") + else: + logger.warning(f"Workflow {workflow_id} konnte nicht in Datenbank gespeichert werden") + except Exception as e: + logger.error(f"Fehler beim Speichern des Workflows {workflow_id} in Datenbank: {str(e)}") + + # Als Datei speichern (Backup/Fallback) + workflow_path = os.path.join(self.results_dir, f"workflow_{workflow_id}.json") + + try: + with open(workflow_path, 'w', encoding='utf-8') as f: + json.dump(workflow, f, indent=2, ensure_ascii=False) + logger.debug(f"Workflow {workflow_id} als Datei gespeichert: {workflow_path}") + except Exception as e: + logger.error(f"Fehler beim Speichern des Workflows {workflow_id} als Datei: {str(e)}") + + async def load_workflow(self, workflow_id: str) -> Optional[Dict[str, Any]]: + """ + Lädt einen Workflow aus der Datenbank oder Datei. + + Args: + workflow_id: ID des Workflows + + Returns: + Das geladene Workflow-Objekt oder None, wenn der Workflow nicht existiert + """ + # Prüfen, ob der Workflow bereits im Speicher ist + if workflow_id in self.workflows: + return self.workflows[workflow_id] + + # Versuche, den Workflow aus der Datenbank zu laden + if self.lucydom_interface: + try: + workflow = self.lucydom_interface.load_workflow_state(workflow_id) + if workflow: + # Workflow im Speicher cachen + self.workflows[workflow_id] = workflow + logger.info(f"Workflow {workflow_id} aus Datenbank geladen") + return workflow + except Exception as e: + logger.error(f"Fehler beim Laden des Workflows {workflow_id} aus Datenbank: {str(e)}") + + # Versuche, den Workflow aus der Datei zu laden + workflow_path = os.path.join(self.results_dir, f"workflow_{workflow_id}.json") + + try: + if os.path.exists(workflow_path): + with open(workflow_path, 'r', encoding='utf-8') as f: + workflow = json.load(f) + + # Workflow im Speicher cachen + self.workflows[workflow_id] = workflow + + # Optional: In Datenbank speichern, falls verfügbar + if self.lucydom_interface: + try: + self.lucydom_interface.save_workflow_state(workflow) + logger.info(f"Workflow {workflow_id} in Datenbank gespeichert nach Laden aus Datei") + except Exception as e: + logger.warning(f"Fehler beim Speichern des Workflows {workflow_id} in Datenbank nach Laden aus Datei: {str(e)}") + + logger.info(f"Workflow {workflow_id} aus Datei geladen: {workflow_path}") + return workflow + else: + logger.warning(f"Workflow {workflow_id} nicht gefunden: {workflow_path}") + raise WorkflowNotFoundError(f"Workflow {workflow_id} nicht gefunden") + except WorkflowNotFoundError: + raise + except Exception as e: + logger.error(f"Fehler beim Laden des Workflows {workflow_id} aus Datei: {str(e)}") + raise WorkflowError(f"Fehler beim Laden des Workflows: {str(e)}") + + async def list_workflows(self, mandate_id: int = None, user_id: int = None) -> List[Dict[str, Any]]: + """ + Listet alle verfügbaren Workflows auf. + + Args: + mandate_id: Optionale Mandanten-ID für die Filterung + user_id: Optionale Benutzer-ID für die Filterung + + Returns: + Liste von Workflow-Zusammenfassungen + """ + workflows = [] + + # Aus Datenbank laden, falls verfügbar + if self.lucydom_interface: + try: + # Alle Workflows des Benutzers abrufen + if user_id is not None: + user_workflows = self.lucydom_interface.get_workflows_by_user(user_id) + else: + user_workflows = self.lucydom_interface.get_all_workflows() + + # Nach Mandanten filtern, falls angegeben + if mandate_id is not None: + user_workflows = [wf for wf in user_workflows if wf.get("mandate_id") == mandate_id] + + # Workflow-Zusammenfassungen erstellen + for workflow in user_workflows: + summary = { + "id": workflow.get("id"), + "name": workflow.get("name", f"Workflow {workflow.get('id')}"), + "status": workflow.get("status"), + "started_at": workflow.get("started_at"), + "last_activity": workflow.get("last_activity"), + "completed_at": workflow.get("completed_at") + } + + # Nachrichtenanzahl hinzufügen, falls verfügbar + messages = self.lucydom_interface.get_workflow_messages(workflow.get("id")) + if messages: + summary["message_count"] = len(messages) + + workflows.append(summary) + + logger.info(f"Workflows aus Datenbank geladen: {len(workflows)}") + + # Nach letzter Aktivität sortieren (neueste zuerst) + return sorted(workflows, key=lambda w: w.get("last_activity", ""), reverse=True) + + except Exception as e: + logger.error(f"Fehler beim Abrufen der Workflows aus Datenbank: {str(e)}") + + # Aus Dateien laden, wenn keine Datenbank verfügbar oder ein Fehler aufgetreten ist + try: + for filename in os.listdir(self.results_dir): + if filename.startswith("workflow_") and filename.endswith(".json"): + workflow_path = os.path.join(self.results_dir, filename) + + try: + with open(workflow_path, 'r', encoding='utf-8') as f: + workflow = json.load(f) + + # Prüfen, ob Mandanten- und Benutzer-ID übereinstimmen + if mandate_id is not None and workflow.get("mandate_id") != mandate_id: + continue + + if user_id is not None and workflow.get("user_id") != user_id: + continue + + # Workflow-Zusammenfassung erstellen + summary = { + "id": workflow.get("id"), + "name": workflow.get("name", f"Workflow {workflow.get('id')}"), + "status": workflow.get("status"), + "started_at": workflow.get("started_at"), + "last_activity": workflow.get("last_activity"), + "message_count": len(workflow.get("messages", [])) + } + + workflows.append(summary) + except Exception as e: + logger.error(f"Fehler beim Laden der Workflow-Datei {filename}: {str(e)}") + + logger.info(f"Workflows aus Dateien geladen: {len(workflows)}") + + # Nach letzter Aktivität sortieren (neueste zuerst) + return sorted(workflows, key=lambda w: w.get("last_activity", ""), reverse=True) + + except Exception as e: + logger.error(f"Fehler beim Auflisten der Workflows: {str(e)}") + return [] + + async def delete_workflow(self, workflow_id: str) -> bool: + """ + Löscht einen Workflow. + + Args: + workflow_id: ID des Workflows + + Returns: + True bei Erfolg, False wenn der Workflow nicht existiert + """ + # Aus dem Speicher entfernen + if workflow_id in self.workflows: + del self.workflows[workflow_id] + + # Aus der Datenbank löschen + if self.lucydom_interface: + try: + db_success = self.lucydom_interface.delete_workflow(workflow_id) + logger.info(f"Workflow {workflow_id} aus Datenbank gelöscht: {db_success}") + except Exception as e: + logger.error(f"Fehler beim Löschen des Workflows {workflow_id} aus Datenbank: {str(e)}") + + # Datei löschen + workflow_path = os.path.join(self.results_dir, f"workflow_{workflow_id}.json") + + try: + if os.path.exists(workflow_path): + os.remove(workflow_path) + logger.info(f"Workflow {workflow_id} aus Datei gelöscht: {workflow_path}") + return True + else: + logger.warning(f"Workflow {workflow_id} nicht gefunden: {workflow_path}") + return False + except Exception as e: + logger.error(f"Fehler beim Löschen der Workflow-Datei {workflow_id}: {str(e)}") + return False + + def _initialize_workflow(self, workflow_id: str) -> Dict[str, Any]: + """ + Initialisiert einen neuen Workflow und speichert ihn in der Datenbank. + + Args: + workflow_id: ID des Workflows + + Returns: + Das initialisierte Workflow-Objekt + """ + current_time = datetime.now().isoformat() + + # Vollständiges Workflow-Objekt gemäß dem Datenmodell erstellen + workflow = { + "id": workflow_id, + "name": f"Workflow {workflow_id}", + "mandate_id": self.mandate_id, + "user_id": self.user_id, + "status": "running", + "started_at": current_time, + "last_activity": current_time, + "current_round": 1, + + # Vollständige Statistik-Struktur gemäß DataStats-Modell + "data_stats": { + "total_processing_time": 0.0, + "total_token_count": 0, + "total_bytes_sent": 0, + "total_bytes_received": 0 + }, + + # Leere Arrays für Nachrichten und Logs + "messages": [], + "logs": [] + } + + print("DEBUG Init workflow") + # Log-Eintrag für den Start des Workflows + self._add_log(workflow, "Workflow gestartet", "info") + + # Workflow in Datenbank speichern + if self.lucydom_interface: + try: + # Direktes Speichern des vollständigen Workflow-Objekts + self.lucydom_interface.save_workflow_state(workflow) + logger.info(f"Workflow {workflow_id} in Datenbank erstellt") + except Exception as e: + logger.error(f"Fehler beim Erstellen des Workflows {workflow_id} in Datenbank: {str(e)}") + + # Workflow im Speicher cachen + self.workflows[workflow_id] = workflow + + return workflow + + + async def stop_workflow(self, workflow_id: str) -> bool: + """ + Stoppt einen laufenden Workflow. + + Args: + workflow_id: ID des zu stoppenden Workflows + + Returns: + True bei Erfolg, False wenn der Workflow nicht existiert oder bereits beendet wurde + """ + try: + workflow = self.workflows.get(workflow_id) + + if not workflow: + # Versuche den Workflow zu laden + workflow = await self.load_workflow(workflow_id) + if not workflow: + return False + + # Wenn der Workflow nicht im Status 'running' oder 'completed' ist, beenden + if workflow.get("status") not in ["running", "completed"]: + return False + + # Status auf 'stopped' setzen + workflow["status"] = "stopped" + workflow["last_activity"] = datetime.now().isoformat() + + self._add_log(workflow, "Workflow wurde manuell gestoppt", "info") + + # Workflow speichern + self._save_workflow(workflow) + + return True + except Exception as e: + logger.error(f"Fehler beim Stoppen des Workflows {workflow_id}: {str(e)}") + return False + + async def _decide_agent_tasks(self, message: Dict[str, Any], agents: Dict[str, Dict[str, Any]]) -> List[Dict[str, Any]]: + """ + Entscheidet anhand der Nachricht und Agentenprofile, welche Agenten für welche Aufgaben + eingesetzt werden sollen. + + Args: + message: Das zu verarbeitende Message-Objekt + agents: Verfügbare Agenten mit ihren Profilen + + Returns: + Liste mit Aufgaben für Agenten (agent_id, prompt) + """ + try: + # Erstelle einen Prompt für den OpenAI-Call + agent_descriptions = [] + for agent_id, agent in agents.items(): + agent_descriptions.append(f"ID: {agent_id}, Name: {agent['name']}, Typ: {agent['type']}, Beschreibung: {agent['description']}, Fähigkeiten: {agent['capabilities']}") + + agent_description_text = "\n".join(agent_descriptions) + + # Nachrichteninhalt extrahieren + content = message.get("content", "") + + # Dateien aus der Nachricht extrahieren + files = extract_files_from_message(message) + file_descriptions = [] + + for file in files: + file_descriptions.append(f"Name: {file.get('name', '')}, Typ: {file.get('content_type', '')}, Inhalt: {file.get('content', '')[:200]}...") + + file_description_text = "\n".join(file_descriptions) if file_descriptions else "Keine Dateien" + + # Prompt für den OpenAI-Call erstellen + decision_prompt = f""" + Du bist ein Workflow-Manager, der entscheidet, welche Agenten für eine Anfrage eingesetzt werden sollen. + + VERFÜGBARE AGENTEN: + {agent_description_text} + + BENUTZERANFRAGE: + {content} + + DATEIEN: + {file_description_text} + + ANWEISUNGEN: + 1. Analysiere die Benutzeranfrage und die Dateien + 2. Entscheide, welche Agenten eingesetzt werden sollen + 3. Die Agenten müssen entweder NUR der User-Agent ODER NUR System-Agenten sein + 4. Definiere für jeden Agenten einen spezifischen Prompt basierend auf seinen Fähigkeiten + 5. Gib das Ergebnis als JSON-Array von Objekten zurück + + Antwortformat: + [ + {{"agent_id": "agent_id_1", "prompt": "Aufgabenbeschreibung für Agent 1"}}, + {{"agent_id": "agent_id_2", "prompt": "Aufgabenbeschreibung für Agent 2"}} + ] + + Wenn keine Agenten erforderlich sind (z.B. bei unklaren Anfragen), gib ein leeres Array zurück: [] + """ + + # OpenAI-Call durchführen + content = await self.ai_service.call_api([{"role": "user", "content": decision_prompt}]) + + # Versuche, JSON zu parsen + import json + import re + + # Suche nach JSON-Objekten in der Antwort + json_match = re.search(r'\[\s*{.*}\s*\]', content, re.DOTALL) + + if json_match: + json_str = json_match.group(0) + agent_tasks = json.loads(json_str) + + # Validiere die Struktur + for task in agent_tasks: + if "agent_id" not in task or "prompt" not in task: + raise ValueError("Ungültiges Format: Jede Aufgabe muss agent_id und prompt enthalten") + + # Prüfe, ob nur User oder nur System-Agenten ausgewählt wurden + agent_types = [agents[task["agent_id"]]["type"] for task in agent_tasks if task["agent_id"] in agents] + if "user" in agent_types and len(agent_types) > 1: + # Wenn der User-Agent und andere Agenten ausgewählt wurden, nur den User-Agenten behalten + agent_tasks = [task for task in agent_tasks if agents[task["agent_id"]]["type"] == "user"] + + logger.debug(f"Ausgewählte Agenten-Tasks: {agent_tasks}") + return agent_tasks + else: + # Kein JSON gefunden, leere Liste zurückgeben + return [] + + except Exception as e: + logger.error(f"Fehler bei der Agent-Auswahl: {str(e)}", exc_info=True) + return [] + + async def _execute_agent(self, workflow: Dict[str, Any], agent_id: str, prompt: str) -> Optional[Dict[str, Any]]: + """ + Führt einen Agenten mit einem spezifischen Prompt aus. + + Args: + workflow: Das Workflow-Objekt + agent_id: ID des auszuführenden Agenten + prompt: Prompt für den Agenten + + Returns: + Das Ergebnis des Agenten oder None bei Fehlern + """ + try: + # Agenten-Instanz holen + registry = AgentRegistry.get_instance() + agent = registry.get_agent(agent_id) + + if not agent: + self._add_log(workflow, f"Agent '{agent_id}' nicht gefunden", "error") + return None + + # Message-Objekt für den Agenten erstellen + agent_message = { + "role": "user", + "content": prompt, + "workflow_id": workflow["id"] + } + + # Agenten ausführen + self._add_log(workflow, f"Agent '{agent_id}' wird ausgeführt", "info") + result = await agent.process_message(agent_message, workflow) + + # Agenten-Antwort als neue Nachricht zum Workflow hinzufügen + agent_response_message = self._create_message(workflow["id"], "assistant") + agent_response_message["content"] = result.get("content", "") + agent_response_message["agent_type"] = agent.type + agent_response_message["agent_id"] = agent_id + agent_response_message["agent_name"] = agent.name + + # Nachricht zum Workflow hinzufügen + workflow["messages"].append(agent_response_message) + + # Nachricht abschließen und in der Datenbank speichern + self._finalize_last_message(workflow) + + # Workflow-Zustand speichern + self._save_workflow(workflow) + + # Ergebnis formatieren und zurückgeben + agent_result = { + "agent_id": agent_id, + "agent_name": agent.name, + "content": result.get("content", ""), + "agent_type": agent.type + } + + self._add_log(workflow, f"Agent '{agent_id}' hat geantwortet", "info") + + return agent_result + + except Exception as e: + self._add_log(workflow, f"Fehler bei der Ausführung von Agent '{agent_id}': {str(e)}", "error") + return None + + + async def _create_summary(self, agent_results: List[Dict[str, Any]]) -> str: + """ + Erstellt eine Zusammenfassung der Agentenergebnisse. + + Args: + agent_results: Liste der Agentenergebnisse + + Returns: + Zusammenfassung als Text + """ + if not agent_results: + return "Keine Agentenergebnisse verfügbar." + + # Kombiniere die Ergebnisse in einen Kontext + context = "" + for result in agent_results: + agent_name = result.get("agent_name", "Unbekannter Agent") + content = result.get("content", "") + + context += f"--- {agent_name} ---\n{content}\n\n" + + # Prompt für die Zusammenfassung + summary_prompt = f""" + Erstelle eine aussagekräftige Zusammenfassung der folgenden Agentenergebnisse. + Organisiere die Informationen strukturiert und vermeide Redundanzen. + Behalte alle wichtigen Erkenntnisse und Empfehlungen bei. + + {context} + """ + + # OpenAI-Call für die Zusammenfassung + try: + summary = await self.ai_service.call_api([{"role": "user", "content": summary_prompt}]) + return summary + except Exception as e: + logger.error(f"Fehler bei der Erstellung der Zusammenfassung: {str(e)}") + return "Fehler bei der Erstellung der Zusammenfassung. Bitte die individuellen Agentenergebnisse beachten." + + def _add_log(self, workflow: Dict[str, Any], message: str, log_type: str, agent_id: Optional[str] = None, agent_name: Optional[str] = None) -> None: + """ + Fügt einen Log-Eintrag zum Workflow hinzu und speichert ihn in der Datenbank. + """ + # First, check if workflow is a string (ID) instead of dictionary + if isinstance(workflow, str): + # Try to load the workflow by ID + workflow_id = workflow + workflow = self.workflows.get(workflow_id) + if not workflow: + # Just log to the logger and return + logger.info(f"Log (couldn't add to workflow {workflow_id}): {log_type} - {message}") + return + # Check if workflow is a dictionary + if not isinstance(workflow, dict): + logger.error(f"Invalid workflow type: {type(workflow)}. Expected dictionary.") + # Just log to the logger and return + logger.info(f"Log (couldn't add to workflow): {log_type} - {message}") + return + + # Continue with the rest of the function if workflow is a dictionary + + log_entry = { + "id": f"log_{uuid.uuid4()}", + "message": message, + "type": log_type, + "timestamp": datetime.now().isoformat(), + "agent_id": agent_id, + "agent_name": agent_name + } + + # Log-Eintrag zum Workflow hinzufügen + if "logs" not in workflow: + workflow["logs"] = [] + + workflow["logs"].append(log_entry) + + # Letzte Aktivität aktualisieren + workflow["last_activity"] = log_entry["timestamp"] + # Log-Eintrag in Datenbank speichern, falls verfügbar + if self.lucydom_interface: + try: + # Workflow-ID zum Log-Eintrag hinzufügen + log_data = log_entry.copy() + log_data["workflow_id"] = workflow["id"] + + self.lucydom_interface.create_workflow_log(log_data) + logger.debug(f"Log-Eintrag für Workflow {workflow['id']} in Datenbank gespeichert") + except Exception as e: + logger.error(f"Fehler beim Speichern des Log-Eintrags für Workflow {workflow['id']} in Datenbank: {str(e)}") + logger.info(f"Workflow {workflow['id']}: {message}") + + + def _create_message(self, workflow_id: str, role: str = "system", parent_message_id: str = None) -> Dict[str, Any]: + """ + Erstellt ein neues Message-Objekt und speichert es in der Datenbank. + + Args: + workflow_id: ID des Workflows + role: Rolle der Nachricht ('system', 'user', 'assistant') + parent_message_id: ID der Elternnachricht (optional) + + Returns: + Das erstellte Message-Objekt + """ + workflow = self.workflows.get(workflow_id) + + # Sequence-Nummer bestimmen + sequence_no = 1 + if workflow and workflow.get("messages"): + sequence_no = len(workflow["messages"]) + 1 + + # Aktuelle Zeit + current_time = datetime.now().isoformat() + + # Ensure a unique ID for the message + message_id = f"msg_{uuid.uuid4()}" + + # Message-Objekt erstellen + message = { + "id": message_id, + "workflow_id": workflow_id, + "parent_message_id": parent_message_id, + "started_at": current_time, + "finished_at": None, + "sequence_no": sequence_no, + + "status": "pending", + "role": role, + + "data_stats": { + "processing_time": 0.0, + "token_count": 0, + "bytes_sent": 0, + "bytes_received": 0 + }, + + "documents": [], # Initialize empty documents array + "content": None, + "agent_type": None + } + + # In Datenbank speichern, falls verfügbar + if self.lucydom_interface: + try: + # Include all fields in the database version + message_data = { + "id": message_id, + "workflow_id": workflow_id, + "sequence_no": sequence_no, + "role": role, + "content": None, + "agent_type": None, + "created_at": current_time, + # IMPORTANT: Include documents field + "documents": [] + } + + # Log the message creation + logger.debug(f"Creating new message in database: {message_data}") + + result = self.lucydom_interface.create_workflow_message(message_data) + if result: + logger.debug(f"Nachricht für Workflow {workflow_id} in Datenbank erstellt mit ID: {message_id}") + else: + logger.warning(f"Fehler beim Erstellen der Nachricht für Workflow {workflow_id} in Datenbank") + except Exception as e: + logger.error(f"Fehler beim Erstellen der Nachricht für Workflow {workflow_id} in Datenbank: {str(e)}") + + return message + + + def _finalize_last_message(self, workflow: Dict[str, Any]) -> None: + """ + Schließt die letzte Nachricht im Workflow ab und aktualisiert sie in der Datenbank. + + Args: + workflow: Das Workflow-Objekt + """ + if not workflow.get("messages"): + return + + last_message = workflow["messages"][-1] + if last_message.get("finished_at") is None: + last_message["finished_at"] = datetime.now().isoformat() + last_message["status"] = "completed" + + # In Datenbank aktualisieren, falls verfügbar + if self.lucydom_interface: + try: + message_id = last_message.get("id") + if not message_id: + logger.warning(f"Keine ID für letzte Nachricht in Workflow {workflow['id']} gefunden") + return + + # Only extract fields that are expected in the database model + # Make sure all required fields have values with proper defaults + message_data = { + "id": message_id, + "workflow_id": workflow.get("id", ""), + "sequence_no": last_message.get("sequence_no", 0), + "role": last_message.get("role", "unknown"), + "content": last_message.get("content", ""), + "agent_type": last_message.get("agent_type", ""), + "created_at": last_message.get("started_at", datetime.now().isoformat()), + # IMPORTANT: Include the documents array + "documents": last_message.get("documents", []) + } + + # Log the message data for debugging + logger.debug(f"Updating message in database with data: {message_data}") + + # Nachricht in Datenbank aktualisieren + self.lucydom_interface.update_workflow_message(message_id, message_data) + logger.debug(f"Nachricht {message_id} für Workflow {workflow['id']} in Datenbank aktualisiert (mit Dokumenten)") + except Exception as e: + logger.error(f"Fehler beim Aktualisieren der Nachricht für Workflow {workflow['id']} in Datenbank: {str(e)}") + + + def get_workflow_status(self, workflow_id: str) -> Optional[Dict[str, Any]]: + """ + Gibt den Status eines Workflows zurück. + + Args: + workflow_id: ID des Workflows + + Returns: + Dictionary mit Status-Informationen oder None, wenn der Workflow nicht existiert + """ + # Aus dem Speicher abrufen + workflow = self.workflows.get(workflow_id) + + # Falls nicht im Speicher, aus der Datenbank oder Datei laden + if not workflow: + # Aus Datenbank laden, falls verfügbar + if self.lucydom_interface: + try: + workflow_data = self.lucydom_interface.get_workflow(workflow_id) + if workflow_data: + workflow = workflow_data + except Exception as e: + logger.error(f"Fehler beim Laden des Workflow-Status aus Datenbank: {str(e)}") + + # Falls nicht in der Datenbank, aus Datei laden + if not workflow: + try: + workflow_path = os.path.join(self.results_dir, f"workflow_{workflow_id}.json") + if os.path.exists(workflow_path): + with open(workflow_path, 'r', encoding='utf-8') as f: + workflow = json.load(f) + except Exception as e: + logger.error(f"Fehler beim Laden des Workflow-Status aus Datei: {str(e)}") + return None + + if not workflow: + return None + + # Status-Informationen extrahieren + status_info = { + "id": workflow.get("id"), + "name": workflow.get("name", f"Workflow {workflow_id}"), + "status": workflow.get("status"), + "progress": 1.0 if workflow.get("status") in ["completed", "failed", "stopped"] else 0.5, + "started_at": workflow.get("started_at"), + "last_activity": workflow.get("last_activity"), + "workflow_complete": workflow.get("status") == "completed", # Add this instead + "current_round": workflow.get("current_round", 1), + "data_stats": workflow.get("data_stats", { + "total_processing_time": 0.0, + "total_token_count": 0, + "total_bytes_sent": 0, + "total_bytes_received": 0 + }) + } + + return status_info + + def get_workflow_logs(self, workflow_id: str) -> Optional[List[Dict[str, Any]]]: + """ + Gibt die Logs eines Workflows zurück. + + Args: + workflow_id: ID des Workflows + + Returns: + Liste der Logs oder None, wenn der Workflow nicht existiert + """ + # Aus dem Speicher abrufen + workflow = self.workflows.get(workflow_id) + + # Falls nicht im Speicher, aus der Datenbank laden + if not workflow and self.lucydom_interface: + try: + logs = self.lucydom_interface.get_workflow_logs(workflow_id) + return logs + except Exception as e: + logger.error(f"Fehler beim Laden der Workflow-Logs aus Datenbank: {str(e)}") + + # Falls nicht in der Datenbank oder kein Interface verfügbar, aus Datei laden + if not workflow: + try: + workflow_path = os.path.join(self.results_dir, f"workflow_{workflow_id}.json") + if os.path.exists(workflow_path): + with open(workflow_path, 'r', encoding='utf-8') as f: + workflow = json.load(f) + except Exception as e: + logger.error(f"Fehler beim Laden der Workflow-Logs aus Datei: {str(e)}") + return None + + return workflow.get("logs", []) if workflow else None + + def get_workflow_messages(self, workflow_id: str) -> Optional[List[Dict[str, Any]]]: + """ + Gibt die Nachrichten eines Workflows zurück. + + Args: + workflow_id: ID des Workflows + + Returns: + Liste der Nachrichten oder None, wenn der Workflow nicht existiert + """ + # Aus dem Speicher abrufen + workflow = self.workflows.get(workflow_id) + + # Falls nicht im Speicher, aus der Datenbank laden + if not workflow and self.lucydom_interface: + try: + messages = self.lucydom_interface.get_workflow_messages(workflow_id) + return messages + except Exception as e: + logger.error(f"Fehler beim Laden der Workflow-Nachrichten aus Datenbank: {str(e)}") + + # Falls nicht in der Datenbank oder kein Interface verfügbar, aus Datei laden + if not workflow: + try: + workflow_path = os.path.join(self.results_dir, f"workflow_{workflow_id}.json") + if os.path.exists(workflow_path): + with open(workflow_path, 'r', encoding='utf-8') as f: + workflow = json.load(f) + except Exception as e: + logger.error(f"Fehler beim Laden der Workflow-Nachrichten aus Datei: {str(e)}") + return None + + return workflow.get("messages", []) if workflow else None + +# Anpassen der Factory-Funktion für den WorkflowManager +def get_workflow_manager(mandate_id: int = None, user_id: int = None, ai_service = None): + """ + Gibt eine WorkflowManager-Instanz für den angegebenen Kontext zurück. + Wiederverwendet bestehende Instanzen. + + Args: + mandate_id: ID des Mandanten + user_id: ID des Benutzers + ai_service: Service für KI-Anfragen + + Returns: + Eine WorkflowManager-Instanz + """ + from modules.lucydom_interface import get_lucydom_interface + + context_key = f"{mandate_id}_{user_id}" + + # LucyDOM-Interface für Datenbankzugriffe + lucydom_interface = get_lucydom_interface(mandate_id, user_id) + + if context_key not in _workflow_managers: + _workflow_managers[context_key] = WorkflowManager( + mandate_id, + user_id, + ai_service, + lucydom_interface + ) + + # Aktualisiere die Services, falls sie geändert wurden + if ai_service is not None: + _workflow_managers[context_key].ai_service = ai_service + + return _workflow_managers[context_key] + + +# Singleton-Factory für WorkflowManager-Instanzen pro Kontext +_workflow_managers = {} \ No newline at end of file diff --git a/gwserver/modules/format_converter.py b/gwserver/modules/format_converter.py deleted file mode 100644 index 2e338d64..00000000 --- a/gwserver/modules/format_converter.py +++ /dev/null @@ -1,285 +0,0 @@ -import logging -from typing import Dict, Any, List - -# Logger konfigurieren -logger = logging.getLogger(__name__) - -def convert_to_anthropic_format(openai_messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]: - """ - Konvertiert Nachrichten vom OpenAI-Format ins Anthropic-Format. - - OpenAI verwendet: - [{"role": "system", "content": "..."}, - {"role": "user", "content": "..."}, - {"role": "assistant", "content": "..."}] - - Anthropic verwendet: - [{"role": "user", "content": [{"type": "text", "text": "..."}]}, - {"role": "assistant", "content": [{"type": "text", "text": "..."}]}] - - Anmerkung: Anthropic hat kein direktes System-Message-Äquivalent, - daher fügen wir System-Nachrichten in die erste User-Nachricht ein. - """ - anthropic_messages = [] - system_content = "" - - # Extrahiere zuerst alle System-Nachrichten - for msg in openai_messages: - if msg.get("role") == "system": - if isinstance(msg.get("content"), str): - system_content += msg.get("content", "") + "\n\n" - # Falls content bereits ein Array ist (selten bei system messages) - elif isinstance(msg.get("content"), list): - for part in msg.get("content", []): - if part.get("type") == "text": - system_content += part.get("text", "") + "\n\n" - - # Konvertiere die restlichen Nachrichten - for i, msg in enumerate(openai_messages): - role = msg.get("role") - content = msg.get("content", "") - - # System-Nachrichten überspringen (bereits extrahiert) - if role == "system": - continue - - # Anthropic unterstützt nur "user" und "assistant" als Rollen - if role not in ["user", "assistant"]: - role = "user" - - # Standardisiertes Nachrichtenformat erstellen - anthropic_msg = {"role": role} - - # Content-Formatierung - if isinstance(content, str): - # String in ein Anthropic-kompatibles Array umwandeln - # Für die erste User-Nachricht: System-Inhalte voranstellen, falls vorhanden - if role == "user" and system_content and not any(m.get("role") == "user" for m in anthropic_messages): - text_content = system_content + content - else: - text_content = content - - anthropic_msg["content"] = [{"type": "text", "text": text_content}] - - elif isinstance(content, list): - # Bei Array-Content (multimodal) - transformed_content = [] - - # Für die erste User-Nachricht: System-Inhalte dem ersten Text-Element voranstellen - if role == "user" and system_content and not any(m.get("role") == "user" for m in anthropic_messages): - first_text_added = False - - for part in content: - if part.get("type") == "text" and not first_text_added: - transformed_content.append({ - "type": "text", - "text": system_content + part.get("text", "") - }) - first_text_added = True - elif part.get("type") == "image_url": - # OpenAI image_url in Anthropic image umwandeln - image_url = part.get("image_url", {}).get("url", "") - if image_url.startswith("data:"): - # Base64-kodiertes Bild - parts = image_url.split(",", 1) - if len(parts) == 2: - media_type = parts[0].split(":")[1].split(";")[0] - base64_data = parts[1] - transformed_content.append({ - "type": "image", - "source": { - "type": "base64", - "media_type": media_type, - "data": base64_data - } - }) - else: - # URL-Bild - nicht direkt unterstützt von Anthropic in dieser Form - logger.warning("Externe Bild-URLs werden von Anthropic nicht direkt unterstützt") - else: - transformed_content.append(part) - - # Falls kein Text-Element gefunden wurde, füge System-Content als separates Element hinzu - if system_content and not first_text_added: - transformed_content.insert(0, {"type": "text", "text": system_content}) - else: - # Wenn es nicht die erste User-Nachricht ist oder kein System-Content vorhanden ist - for part in content: - if part.get("type") == "image_url": - # OpenAI image_url in Anthropic image umwandeln - image_url = part.get("image_url", {}).get("url", "") - if image_url.startswith("data:"): - # Base64-kodiertes Bild - parts = image_url.split(",", 1) - if len(parts) == 2: - media_type = parts[0].split(":")[1].split(";")[0] - base64_data = parts[1] - transformed_content.append({ - "type": "image", - "source": { - "type": "base64", - "media_type": media_type, - "data": base64_data - } - }) - else: - # URL-Bild - nicht direkt unterstützt von Anthropic in dieser Form - logger.warning("Externe Bild-URLs werden von Anthropic nicht direkt unterstützt") - else: - transformed_content.append(part) - - anthropic_msg["content"] = transformed_content - - anthropic_messages.append(anthropic_msg) - - return anthropic_messages - -def convert_to_openai_format(anthropic_messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]: - """ - Konvertiert Nachrichten vom Anthropic-Format ins OpenAI-Format. - - Anthropic: - [{"role": "user", "content": [{"type": "text", "text": "..."}]}, - {"role": "assistant", "content": [{"type": "text", "text": "..."}]}] - - OpenAI: - [{"role": "system", "content": "..."}, - {"role": "user", "content": "..."}, - {"role": "assistant", "content": "..."}] - """ - openai_messages = [] - - for msg in anthropic_messages: - role = msg.get("role", "user") - content = msg.get("content", []) - - # Erstelle OpenAI-Message - openai_msg = {"role": role} - - # Content-Behandlung - if isinstance(content, list): - # Multimodaler Inhalt von Anthropic - if all(isinstance(part, dict) and part.get("type") == "text" for part in content): - # Wenn alle Elemente Text sind, vereinfache zu einem einzelnen String - openai_msg["content"] = "\n".join(part.get("text", "") for part in content if part.get("type") == "text") - else: - # Mischung aus Text und Bildern/Dokumenten - openai_content = [] - - for part in content: - part_type = part.get("type", "") - - if part_type == "text": - openai_content.append({ - "type": "text", - "text": part.get("text", "") - }) - elif part_type == "image": - # Anthropic image in OpenAI image_url umwandeln - source = part.get("source", {}) - if source.get("type") == "base64": - media_type = source.get("media_type", "image/jpeg") - base64_data = source.get("data", "") - openai_content.append({ - "type": "image_url", - "image_url": { - "url": f"data:{media_type};base64,{base64_data}" - } - }) - # Anthropic Dokumente können nicht direkt in OpenAI-Format übersetzt werden - elif part_type == "document": - # Versuche, Dokumente als Text zu behandeln - openai_content.append({ - "type": "text", - "text": f"[Dokument wurde übermittelt, kann aber nicht direkt in OpenAI-Format konvertiert werden]" - }) - - openai_msg["content"] = openai_content - else: - # Einfacher String-Inhalt - openai_msg["content"] = content - - openai_messages.append(openai_msg) - - return openai_messages - -def convert_anthropic_response_to_openai_format(anthropic_response: Dict[str, Any]) -> Dict[str, Any]: - """ - Konvertiert eine Antwort vom Anthropic-Format ins OpenAI-Format. - - Args: - anthropic_response: Antwort im Anthropic-Format - - Returns: - Die Antwort im OpenAI-Format - """ - # Extrahiere Inhalt aus Anthropic-Antwort - content = "" - if "content" in anthropic_response: - if isinstance(anthropic_response["content"], list): - # Inhalt ist eine Liste von Teilen (bei neueren API-Versionen) - for part in anthropic_response["content"]: - if part.get("type") == "text": - content += part.get("text", "") - else: - # Direkter Inhalt als String (bei älteren API-Versionen) - content = anthropic_response["content"] - - # Erstelle OpenAI-formatierte Antwort - return { - "id": anthropic_response.get("id", ""), - "object": "chat.completion", - "created": anthropic_response.get("created", 0), - "model": anthropic_response.get("model", ""), - "choices": [ - { - "message": { - "role": "assistant", - "content": content - }, - "index": 0, - "finish_reason": "stop" - } - ] - } - -def convert_openai_response_to_anthropic_format(openai_response: Dict[str, Any]) -> Dict[str, Any]: - """ - Konvertiert eine Antwort vom OpenAI-Format ins Anthropic-Format. - - Args: - openai_response: Antwort im OpenAI-Format - - Returns: - Die Antwort im Anthropic-Format (nur die relevanten Felder) - """ - # Extrahiere Inhalt aus OpenAI-Antwort - content = [] - if "choices" in openai_response and openai_response["choices"]: - choice = openai_response["choices"][0] - message = choice.get("message", {}) - message_content = message.get("content", "") - - if isinstance(message_content, str): - content.append({ - "type": "text", - "text": message_content - }) - elif isinstance(message_content, list): - # Multimodaler Inhalt (selten in Antworten) - for part in message_content: - if part.get("type") == "text": - content.append({ - "type": "text", - "text": part.get("text", "") - }) - # Bilder in Antworten würden hier auch verarbeitet werden - - # Erstelle Anthropic-formatierte Antwort - return { - "id": openai_response.get("id", ""), - "model": openai_response.get("model", ""), - "content": content, - "type": "message", - "role": "assistant" - } \ No newline at end of file diff --git a/gwserver/modules/gateway_interface.py b/gwserver/modules/gateway_interface.py index ecafdbd3..7caf809f 100644 --- a/gwserver/modules/gateway_interface.py +++ b/gwserver/modules/gateway_interface.py @@ -4,7 +4,7 @@ from typing import Dict, Any, List, Optional, Union import importlib from passlib.context import CryptContext -from connector_db_json import DatabaseConnector +from connectors.connector_db_json import DatabaseConnector logger = logging.getLogger(__name__) @@ -403,37 +403,7 @@ class GatewayInterface: """ # Hier werden alle Tabellen durchsucht und alle Einträge gelöscht, # die auf diesen Benutzer verweisen - - # Workspaces des Benutzers finden und löschen - try: - workspaces = self.db.get_recordset("workspaces", record_filter={"user_id": user_id}) - for workspace in workspaces: - # Agenten in diesem Workspace löschen - agents = self.db.get_recordset("agents", record_filter={"workspace_id": workspace["id"]}) - for agent in agents: - # Hier könnten weitere abhängige Objekte gelöscht werden - self.db.record_delete("agents", agent["id"]) - - # Dateien in diesem Workspace löschen - files = self.db.get_recordset("files", record_filter={"workspace_id": workspace["id"]}) - for file in files: - self.db.record_delete("files", file["id"]) - - # Prompts in diesem Workspace löschen - prompts = self.db.get_recordset("prompts", record_filter={"workspace_id": workspace["id"]}) - for prompt in prompts: - self.db.record_delete("prompts", prompt["id"]) - - # Workflows in diesem Workspace löschen - workflows = self.db.get_recordset("workflows", record_filter={"workspace_id": workspace["id"]}) - for workflow in workflows: - self.db.record_delete("workflows", workflow["id"]) - - # Den Workspace selbst löschen - self.db.record_delete("workspaces", workspace["id"]) - except Exception as e: - logger.error(f"Fehler beim Löschen der Workspaces für Benutzer {user_id}: {e}") - + # Attribute des Benutzers löschen try: attributes = self.db.get_recordset("attributes", record_filter={"user_id": user_id}) diff --git a/gwserver/modules/lucydom_interface.py b/gwserver/modules/lucydom_interface.py index 2cc47a44..4d164cfc 100644 --- a/gwserver/modules/lucydom_interface.py +++ b/gwserver/modules/lucydom_interface.py @@ -1,12 +1,40 @@ import os import logging -from typing import Dict, Any, List, Optional, Union +import uuid +import shutil +from datetime import datetime, timedelta +import mimetypes +from typing import Dict, Any, List, Optional, Union, BinaryIO, Tuple import importlib +import asyncio +import hashlib +from pathlib import Path -from connector_db_json import DatabaseConnector +from connectors.connector_db_json import DatabaseConnector logger = logging.getLogger(__name__) +# Custom exceptions for file handling +class FileError(Exception): + """Base class for file handling exceptions.""" + pass + +class FileNotFoundError(FileError): + """Exception raised when a file is not found.""" + pass + +class FileStorageError(FileError): + """Exception raised when there's an error storing a file.""" + pass + +class FilePermissionError(FileError): + """Exception raised when there's a permission issue with a file.""" + pass + +class FileDeletionError(FileError): + """Exception raised when there's an error deleting a file.""" + pass + class LucyDOMInterface: """ @@ -25,10 +53,20 @@ class LucyDOMInterface: self.mandate_id = mandate_id self.user_id = user_id + # Load configuration from config.ini + import configload + config = configload.load_config() + # Datenverzeichnis self.data_folder = "_database_lucydom" os.makedirs(self.data_folder, exist_ok=True) + # Upload und temp Verzeichnisse aus config.ini lesen + self.upload_dir = config.get('Module_AgentserviceInterface', 'UPLOAD_DIR', fallback='./_uploads') + self.temp_dir = os.path.join(self.upload_dir, "temp") + os.makedirs(self.upload_dir, exist_ok=True) + os.makedirs(self.temp_dir, exist_ok=True) + # Datenmodell-Modul importieren try: self.model_module = importlib.import_module("modules.lucydom_model") @@ -46,7 +84,90 @@ class LucyDOMInterface: # Datenbank initialisieren, falls nötig self._initialize_database() - + + # Schedule periodic cleanup of temporary files + self._schedule_temp_file_cleanup() + + + + def _schedule_temp_file_cleanup(self): + """Schedule periodic cleanup of temporary files""" + try: + loop = asyncio.get_event_loop() + loop.create_task(self._periodic_temp_file_cleanup()) + except RuntimeError: + # If no event loop is available, log a warning + logger.warning("Kein Event-Loop verfügbar für temporäre Datei-Bereinigung") + + async def _periodic_temp_file_cleanup(self): + """Periodically clean up temporary files""" + while True: + try: + self.cleanup_temp_files() + # Run cleanup every 24 hours + await asyncio.sleep(24 * 60 * 60) + except Exception as e: + logger.error(f"Fehler bei der periodischen Bereinigung temporärer Dateien: {str(e)}") + # If there's an error, wait 1 hour before trying again + await asyncio.sleep(60 * 60) + + def cleanup_temp_files(self, max_age_hours: int = 24): + """ + Clean up temporary files older than the specified age + + Args: + max_age_hours: Maximum age of temporary files in hours + """ + try: + now = datetime.now() + count = 0 + + for item in os.listdir(self.temp_dir): + item_path = os.path.join(self.temp_dir, item) + if os.path.isfile(item_path): + # Check file age + file_time = datetime.fromtimestamp(os.path.getmtime(item_path)) + if now - file_time > timedelta(hours=max_age_hours): + try: + os.remove(item_path) + count += 1 + except Exception as e: + logger.warning(f"Konnte temporäre Datei nicht löschen: {item_path} - {str(e)}") + + logger.info(f"{count} temporäre Dateien bereinigt") + except Exception as e: + logger.error(f"Fehler bei der Bereinigung temporärer Dateien: {str(e)}") + + def cleanup_orphaned_files(self): + """ + Clean up orphaned files that exist on disk but don't have records in the database + """ + try: + # Get all file records from the database + all_files = self.get_all_files() + db_file_paths = {file.get("path") for file in all_files if file.get("path")} + + # Scan the upload directory + count = 0 + for root, _, files in os.walk(self.upload_dir): + # Skip the temp directory + if os.path.normpath(root) == os.path.normpath(self.temp_dir): + continue + + for file in files: + file_path = os.path.join(root, file) + # If the file isn't in the database, delete it + if file_path not in db_file_paths: + try: + os.remove(file_path) + count += 1 + except Exception as e: + logger.warning(f"Konnte verwaiste Datei nicht löschen: {file_path} - {str(e)}") + + logger.info(f"{count} verwaiste Dateien bereinigt") + except Exception as e: + logger.error(f"Fehler bei der Bereinigung verwaister Dateien: {str(e)}") + def _initialize_database(self): """ Initialisiert die Datenbank mit minimalen Objekten für den angemeldeten Benutzer im Mandanten, falls sie noch nicht existiert. @@ -55,107 +176,10 @@ class LucyDOMInterface: """ effective_mandate_id = self.mandate_id effective_user_id = self.user_id - print("DEBUG Init DB true: userid",effective_user_id,"mandateid",effective_mandate_id) if effective_mandate_id is None or effective_user_id is None: #data available return - # Initialisierung des Default Workspace - workspaces = self.db.get_recordset("workspaces") - if not workspaces: - logger.info("Erstelle Default Workspace") - default_workspace = { - "mandate_id": effective_mandate_id, - "user_id": effective_user_id, - "name": "1st default Workspace", - "created_at": self._get_current_timestamp() - } - created_workspace = self.db.record_create("workspaces", default_workspace) - logger.info(f"Default Workspace wurde erstellt mit ID {created_workspace['id']}") - - # Initialisierung von Standard-Agenten - agents = self.db.get_recordset("agents") - if not agents: - logger.info("Erstelle Standard-Agenten") - - # Standard-Agenten definieren - standard_agents = [ - { - "mandate_id": effective_mandate_id, - "user_id": effective_user_id, - "name": "Initialisierung", - "type": "initialisierung", - "workspace_id": self.get_initial_id("workspaces"), - "capabilities": "Problemverständnis, Anforderungsanalyse, Aufgabenplanung und direkte Beantwortung einfacher Fragen", - "description": "Standardagent für einfache Anfragen", - "instructions": "Du bist der Initialisierungsagent, der erste Kontaktpunkt für neue Anfragen. Deine Aufgabe ist es:\n\n1. Die Benutzeranfrage gründlich zu analysieren und zu verstehen\n2. Wichtige Kernpunkte und Anforderungen zu identifizieren\n3. Zu beurteilen, ob die Anfrage direkt beantwortet werden kann oder eine tiefere Analyse benötigt\n4. Bei einfachen Fragen sofort präzise Antworten zu liefern\n5. Bei komplexeren Anfragen einen strukturierten Arbeitsplan vorzuschlagen\n6. Relevante Kontext- und Dateninformationen zu extrahieren und hervorzuheben\n\nGib eine klare Einschätzung der Anfragekomplexität. Wenn die Anfrage zusätzliche Agenten erfordert, empfehle spezifische nächste Schritte. Formuliere deine Antwort klar, präzise und benutzerfreundlich, während du stets die Kernbedürfnisse des Benutzers adressierst." - }, - { - "mandate_id": effective_mandate_id, - "user_id": effective_user_id, - "name": "Organisator", - "type": "organisator", - "workspace_id": self.get_initial_id("workspaces"), - "capabilities": "Projekt- und Aufgabenplanung, Ressourcenmanagement, Strukturierung komplexer Abläufe und Priorisierung von Aktivitäten", - "description": "Koordiniert komplexe Anfragen", - "instructions": "Du bist der Projektorganisationsagent, ein Experte für die Strukturierung und Planung von Projekten und Aufgaben. Deine Aufgabe ist es:\n\n1. Komplexe Anforderungen in konkrete, umsetzbare Aufgaben zu untergliedern\n2. Logische Abhängigkeiten zwischen Aufgaben zu identifizieren und Abläufe zu optimieren\n3. Ressourcen effizient zuzuweisen und Engpässe frühzeitig zu erkennen\n4. Realistische Zeitpläne und Meilensteine zu erstellen\n5. Aufgaben nach Wichtigkeit und Dringlichkeit zu priorisieren\n6. Risiken zu identifizieren und Gegenmaßnahmen vorzuschlagen\n7. Klare Verantwortlichkeiten und Erwartungen zu definieren\n\nBei der Erstellung deiner Organisationspläne:\n- Beginne mit einem Überblick über die Gesamtziele und den Projektumfang\n- Präsentiere eine klare Aufgabenstruktur mit logischen Gruppierungen\n- Definiere messbare Erfolgskriterien für jede Aufgabe und Phase\n- Erstelle eine zeitliche Abfolge mit realistischen Fristen\n- Identifiziere kritische Pfade und potenzielle Engpässe\n- Schlage konkrete Tools und Methoden zur Umsetzung und Überwachung vor\n\nDeine Pläne sollten praktisch, flexibel und an die spezifischen Bedürfnisse und Ressourcen des Projekts angepasst sein. Achte besonders auf Klarheit, Vollständigkeit und Umsetzbarkeit deiner Vorschläge." - }, - { - "mandate_id": effective_mandate_id, - "user_id": effective_user_id, - "name": "Entwickler", - "type": "entwickler", - "workspace_id": self.get_initial_id("workspaces"), - "capabilities": "Programmierung, Softwareentwicklung, technische Problemlösung und Implementierung von Algorithmen", - "description": "Programmiert und führt Code aus", - "instructions": "Du bist der Codeentwicklungsagent, ein Spezialist für die Erstellung von Softwarelösungen und technischen Implementierungen. Deine Aufgabe ist es:\n\n1. Technische Anforderungen in funktionierenden, effizienten Code zu übersetzen\n2. Geeignete Programmiersprachen, Frameworks und Bibliotheken für spezifische Aufgaben auszuwählen\n3. Algorithmen und Datenstrukturen für die optimale Lösung von Problemen zu entwickeln\n4. Lesbaren, gut dokumentierten und wartbaren Code zu schreiben\n5. Sicherheitsaspekte und Best Practices in der Softwareentwicklung zu berücksichtigen\n6. Potenzielle technische Schwierigkeiten vorherzusehen und Lösungen vorzuschlagen\n7. APIs und Integrationen mit anderen Systemen zu konzipieren und implementieren\n\nBei der Präsentation deiner Softwarelösungen:\n- Erkläre zunächst den Lösungsansatz und die gewählte Technologie\n- Stelle den Code in logischen, gut kommentierten Abschnitten dar\n- Erläutere kritische oder komplexe Teile des Codes im Detail\n- Beschreibe Annahmen und getroffene Designentscheidungen\n- Gib Hinweise zur Installation, Konfiguration und Verwendung\n- Erwähne mögliche Erweiterungen und Verbesserungsmöglichkeiten\n- Adressiere potenzielle Einschränkungen oder bekannte Probleme\n\nDein Code sollte nicht nur funktional, sondern auch effizient, sicher und gut strukturiert sein. Achte auf Lesbarkeit, Performance und Skalierbarkeit deiner Lösungen. Verwende moderne Entwicklungspraktiken und orientiere dich an etablierten Standards der jeweiligen Programmiersprache." - }, - { - "mandate_id": effective_mandate_id, - "user_id": effective_user_id, - "name": "Webscraper", - "type": "scraper", - "workspace_id": self.get_initial_id("workspaces"), - "capabilities": "Informationsrecherche, Datenbeschaffung aus dem Web, Quellenbewertung und Zusammenführung von Online-Informationen", - "description": "Recherchiert Informationen im Web", - "instructions": "Du bist der Web-Recherche-Agent, ein Spezialist für die Beschaffung und Aufbereitung von Informationen aus dem Internet. Deine Aufgabe ist es:\n\n1. Zu erkennen, welche externen Informationen zur Beantwortung einer Anfrage benötigt werden\n2. Relevante Quellen und Websites für die Informationsbeschaffung zu identifizieren\n3. Die Glaubwürdigkeit und Zuverlässigkeit von Online-Quellen zu bewerten\n4. Gefundene Informationen zu sammeln, zu strukturieren und zu kontextualisieren\n5. Widersprüchliche Informationen zu erkennen und zu bewerten\n6. Die recherchierten Informationen mit bestehenden Daten zu verknüpfen\n7. Bei der Recherche stets die Aktualität der Informationen zu berücksichtigen\n\nBei der Darstellung deiner Rechercheergebnisse:\n- Gib einen Überblick über die konsultierten Quellen und deren Relevanz\n- Strukturiere die Informationen thematisch und nach Wichtigkeit\n- Kennzeichne Fakten, Meinungen und Unklarheiten deutlich\n- Stelle verschiedene Perspektiven zu kontroversen Themen dar\n- Fasse die wichtigsten Erkenntnisse zusammen und setze sie in Bezug zur ursprünglichen Anfrage\n- Verweise auf besonders nützliche Quellen für weiterführende Informationen\n\nAchte darauf, nur relevante und qualitativ hochwertige Informationen zu extrahieren und übersichtlich zu präsentieren. Vermittle ein ausgewogenes Bild der recherchierten Informationen." - }, - { - "mandate_id": effective_mandate_id, - "user_id": effective_user_id, - "name": "Datenanalyst", - "type": "analyzer", - "workspace_id": self.get_initial_id("workspaces"), - "capabilities": "Tiefgehende Datenanalyse, Mustererkennung, statistische Berechnungen und kritische Bewertung von Informationen", - "description": "Analysiert und interpretiert Daten", - "instructions": "Du bist der Datenanalyseagent, ein Spezialist für die gründliche Untersuchung von Daten und Informationen. Deine Aufgabe ist es:\n\n1. Vorliegende Daten methodisch zu untersuchen und zu interpretieren\n2. Aus unstrukturierten Informationen klare Erkenntnisse zu gewinnen\n3. Statistische Analysen durchzuführen und Trends zu identifizieren\n4. Korrelationen zu finden und kausale Zusammenhänge zu prüfen\n5. Daten zu visualisieren und komplexe Konzepte verständlich darzustellen\n6. Kritische Datenlücken und Verbesserungspotentiale aufzuzeigen\n7. Die Qualität und Zuverlässigkeit der vorliegenden Daten zu bewerten\n\nArbeite systematisch und präsentiere deine Erkenntnisse in einer strukturierten Form. Beginne mit einer kurzen Zusammenfassung deiner wichtigsten Erkenntnisse, gefolgt von einer detaillierten Analyse. Verwende klare, präzise Sprache und quantifiziere deine Beobachtungen wo immer möglich. Schließe mit konkreten Handlungsempfehlungen ab, die auf deinen Erkenntnissen basieren." - }, - { - "mandate_id": effective_mandate_id, - "user_id": effective_user_id, - "name": "Textgenerator", - "type": "writer", - "workspace_id": self.get_initial_id("workspaces"), - "capabilities": "Verfassen von Berichten, Zusammenfassungen, Präsentationen und leicht verständlichen Erklärungen komplexer Themen", - "description": "Erstellt qualitativ hochwertige Texte", - "instructions": "Du bist der Textgenerierungsagent, ein Spezialist für die Erstellung qualitativ hochwertiger Texte und Dokumente. Deine Aufgabe ist es:\n\n1. Präzise, gut strukturierte Texte zu verfassen, die auf den vorliegenden Daten und Analysen basieren\n2. Komplexe Informationen in klare, zugängliche Sprache zu übersetzen\n3. Verschiedene Textformate zu erstellen, darunter Berichte, Zusammenfassungen, Präsentationen und Dokumentationen\n4. Den Ton und Stil an die Zielgruppe und den Verwendungszweck anzupassen\n5. Fachbegriffe zu erklären und Abstraktes durch Beispiele zu veranschaulichen\n6. Die wichtigsten Erkenntnisse hervorzuheben und Handlungsempfehlungen zu formulieren\n7. Text durch rhetorische Mittel überzeugend und einprägsam zu gestalten\n\nBei deiner Textproduktion:\n- Beginne mit einer prägnanten Zusammenfassung der Kernpunkte\n- Strukturiere den Text in logische Abschnitte mit Überschriften\n- Verwende Aufzählungen und Tabellen, um Informationen übersichtlich darzustellen\n- Integriere relevante Daten und Erkenntnisse aus vorherigen Analyseschritten\n- Achte auf korrekte Rechtschreibung, Grammatik und einen konsistenten Sprachstil\n- Passe den Detaillierungsgrad an die Bedürfnisse und das Vorwissen der Zielgruppe an\n\nDeine Texte sollten informativ, präzise, gut strukturiert und ohne Redundanzen sein. Achte besonders auf eine klare Argumentationsstruktur und vermeide vage Aussagen." - }, - { - "mandate_id": effective_mandate_id, - "user_id": effective_user_id, - "name": "Visualisierer", - "type": "visualizer", - "workspace_id": self.get_initial_id("workspaces"), - "capabilities": "Datenvisualisierung, Diagrammerstellung, Design von Dashboards und visuelle Kommunikation komplexer Informationen", - "description": "Erstellt Visualisierungen und Diagramme", - "instructions": "Du bist der Visualisierungsagent, ein Experte für die Umwandlung von Daten in aussagekräftige visuelle Darstellungen. Deine Aufgabe ist es:\n\n1. Daten in geeignete visuelle Formate umzuwandeln\n2. Die optimalen Diagramm- und Visualisierungstypen für spezifische Daten zu empfehlen\n3. Klare, informative und ästhetisch ansprechende Darstellungen zu erstellen\n4. Komplexe Konzepte durch visuelle Metaphern verständlich zu machen\n5. Dashboards und Informationsarchitekturen für Datenerzählungen zu konzipieren\n6. Designprinzipien anzuwenden, um Daten effektiv zu kommunizieren\n7. Farbschemata, Layouts und Beschriftungen für maximale Klarheit zu optimieren\n\nFür jede Visualisierung sollst du:\n- Eine Beschreibung des empfohlenen Visualisierungstyps liefern\n- Begründen, warum dieser Typ für die spezifischen Daten geeignet ist\n- Detaillierte Angaben zu Achsen, Legenden, Farbschemata und Annotationen machen\n- Den Code oder eine textuelle Anleitung zur Erstellung bereitstellen\n- Interpretationshilfen für das Verständnis der Visualisierung bieten\n\nDeine Vorschläge sollten sowohl technisch umsetzbar als auch intuitiv verständlich sein. Strebe nach einem ausgewogenen Verhältnis zwischen Informationsgehalt und visueller Klarheit." - } - ] - # Agenten erstellen - for agent_data in standard_agents: - created_agent = self.db.record_create("agents", agent_data) - logger.info(f"Agent '{created_agent['name']}' wurde erstellt mit ID {created_agent['id']}") - # Initialisierung von Standard-Prompts für verschiedene Bereiche prompts = self.db.get_recordset("prompts") if not prompts: @@ -167,32 +191,24 @@ class LucyDOMInterface: "mandate_id": effective_mandate_id, "user_id": effective_user_id, "content": "Recherchiere die aktuellen Markttrends und Entwicklungen im Bereich [THEMA]. Sammle Informationen zu führenden Unternehmen, innovativen Produkten oder Dienstleistungen und aktuellen Herausforderungen. Präsentiere die Ergebnisse in einer strukturierten Übersicht mit relevanten Daten und Quellen.", - "workspace_id": self.get_initial_id("workspaces"), - "created_at": self._get_current_timestamp(), "name": "Web Research: Marktforschung" }, { "mandate_id": effective_mandate_id, "user_id": effective_user_id, "content": "Analysiere den beigefügten Datensatz zu [THEMA] und identifiziere die wichtigsten Trends, Muster und Auffälligkeiten. Führe statistische Berechnungen durch, um deine Erkenntnisse zu untermauern. Stelle die Ergebnisse in einer klar strukturierten Analyse dar und ziehe relevante Schlussfolgerungen.", - "workspace_id": self.get_initial_id("workspaces"), - "created_at": self._get_current_timestamp(), "name": "Analyse: Datenanalyse" }, { "mandate_id": effective_mandate_id, "user_id": effective_user_id, "content": "Erstelle ein detailliertes Protokoll unserer Besprechung zum Thema [THEMA]. Erfasse alle besprochenen Punkte, getroffenen Entscheidungen und vereinbarten Maßnahmen. Strukturiere das Protokoll übersichtlich mit Tagesordnungspunkten, Teilnehmerliste und klaren Verantwortlichkeiten für die Follow-up-Aktionen.", - "workspace_id": self.get_initial_id("workspaces"), - "created_at": self._get_current_timestamp(), "name": "Protokoll: Besprechungsprotokoll" }, { "mandate_id": effective_mandate_id, "user_id": effective_user_id, "content": "Entwickle ein UI/UX-Designkonzept für [ANWENDUNG/WEBSITE]. Berücksichtige die Zielgruppe, Hauptfunktionen und die Markenidentität. Beschreibe die visuelle Gestaltung, Navigation, Interaktionsmuster und Informationsarchitektur. Erläutere, wie das Design die Benutzerfreundlichkeit und das Nutzererlebnis optimiert.", - "workspace_id": self.get_initial_id("workspaces"), - "created_at": self._get_current_timestamp(), "name": "Design: UI/UX Design" } ] @@ -202,9 +218,119 @@ class LucyDOMInterface: created_prompt = self.db.record_create("prompts", prompt_data) logger.info(f"Prompt '{prompt_data.get('name', 'Standard')}' wurde erstellt mit ID {created_prompt['id']}") + # File utilities - Moved from agentservice_filehandling + def get_mime_type(self, file_path: str) -> str: + """ + Bestimmt den MIME-Typ einer Datei. + + Args: + file_path: Pfad zur Datei + + Returns: + Der erkannte MIME-Typ + """ + # Versuche, den MIME-Typ über den Dateipfad zu erkennen + mime_type, _ = mimetypes.guess_type(file_path) + + # Wenn kein MIME-Typ erkannt wurde, versuche es über die Dateiendung + if not mime_type: + ext = os.path.splitext(file_path)[1].lower()[1:] + mime_type = self.get_mime_type_from_extension(ext) + + return mime_type + + def get_mime_type_from_extension(self, extension: str) -> str: + """ + Bestimmt den MIME-Typ basierend auf der Dateiendung. + + Args: + extension: Die Dateiendung ohne Punkt + + Returns: + Der entsprechende MIME-Typ + """ + extension_to_mime = { + "pdf": "application/pdf", + "docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "doc": "application/msword", + "xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "xls": "application/vnd.ms-excel", + "pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation", + "ppt": "application/vnd.ms-powerpoint", + "csv": "text/csv", + "txt": "text/plain", + "json": "application/json", + "xml": "application/xml", + "html": "text/html", + "htm": "text/html", + "jpg": "image/jpeg", + "jpeg": "image/jpeg", + "png": "image/png", + "gif": "image/gif", + "webp": "image/webp", + "svg": "image/svg+xml", + "py": "text/x-python", + "js": "application/javascript", + "css": "text/css" + } + + return extension_to_mime.get(extension.lower(), "application/octet-stream") + + def determine_file_type(self, file_path: str) -> str: + """ + Bestimmt den Typ einer Datei basierend auf dem MIME-Typ. + + Args: + file_path: Pfad zur Datei + + Returns: + Art der Datei: "image", "document" oder "file" + """ + mime_type = self.get_mime_type(file_path) + + # Bildtypen + if mime_type.startswith("image/"): + return "image" + + # Dokumenttypen + document_types = [ + "application/pdf", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", # docx + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", # xlsx + "application/vnd.openxmlformats-officedocument.presentationml.presentation", # pptx + "application/vnd.ms-excel", + "application/vnd.ms-powerpoint", + "application/msword", + "text/csv", + "text/plain", + "application/json", + "application/xml", + "text/html", + "text/x-python", + "application/javascript", + "text/css" + ] + + if any(mime_type.startswith(dt) for dt in document_types) or mime_type in document_types: + return "document" + + # Fallback für unbekannte Typen + return "file" + + def calculate_file_hash(self, file_content: bytes) -> str: + """ + Calculate SHA-256 hash of file content for deduplication + + Args: + file_content: Binary content of the file + + Returns: + SHA-256 hash as a hexadecimal string + """ + return hashlib.sha256(file_content).hexdigest() + def _get_current_timestamp(self) -> str: """Gibt den aktuellen Zeitstempel im ISO-Format zurück""" - from datetime import datetime return datetime.now().isoformat() def get_initial_id(self, table: str) -> Optional[int]: @@ -219,146 +345,6 @@ class LucyDOMInterface: """ return self.db.get_initial_id(table) - # Workspace-Methoden - - def get_all_workspaces(self) -> List[Dict[str, Any]]: - """Gibt alle Workspaces des aktuellen Mandanten zurück""" - return self.db.get_recordset("workspaces") - - def get_workspace(self, workspace_id: int) -> Optional[Dict[str, Any]]: - """Gibt einen Workspace anhand seiner ID zurück""" - workspaces = self.db.get_recordset("workspaces", record_filter={"id": workspace_id}) - if workspaces: - return workspaces[0] - return None - - def create_workspace(self, name: str) -> Dict[str, Any]: - """Erstellt einen neuen Workspace""" - workspace_data = { - "mandate_id": self.mandate_id, - "user_id": self.user_id, - "name": name, - "created_at": self._get_current_timestamp() - } - - return self.db.record_create("workspaces", workspace_data) - - def update_workspace(self, workspace_id: int, name: str) -> Dict[str, Any]: - """ - Aktualisiert einen vorhandenen Workspace - - Args: - workspace_id: ID des zu aktualisierenden Workspaces - name: Neuer Name des Workspaces - - Returns: - Das aktualisierte Workspace-Objekt - """ - # Prüfen, ob der Workspace existiert - workspace = self.get_workspace(workspace_id) - if not workspace: - return None - - # Daten für die Aktualisierung vorbereiten - workspace_data = { - "name": name - } - - # Workspace aktualisieren - return self.db.record_modify("workspaces", workspace_id, workspace_data) - - def delete_workspace(self, workspace_id: int) -> bool: - """ - Löscht einen Workspace aus der Datenbank - Returns: - True, wenn der Workspace erfolgreich gelöscht wurde, sonst False - """ - # Prüfen, ob es der initiale Workspace ist - initial_workspace_id = self.get_initial_id("workspaces") - if initial_workspace_id is not None and workspace_id == initial_workspace_id: - logger.warning("Versuch, den Default Workspace zu löschen, wurde verhindert") - return False - - return self.db.record_delete("workspaces", workspace_id) - - # Agent-Methoden - - def get_all_agents(self) -> List[Dict[str, Any]]: - """Gibt alle Agenten des aktuellen Mandanten zurück""" - return self.db.get_recordset("agents") - - def get_agents_by_workspace(self, workspace_id: int) -> List[Dict[str, Any]]: - """Gibt alle Agenten eines Workspaces zurück""" - return self.db.get_recordset("agents", record_filter={"workspace_id": workspace_id}) - - def get_agent(self, agent_id: int) -> Optional[Dict[str, Any]]: - """Gibt einen Agenten anhand seiner ID zurück""" - agents = self.db.get_recordset("agents", record_filter={"id": agent_id}) - if agents: - return agents[0] - return None - - def create_agent(self, name: str, agent_type: str, workspace_id: int, - capabilities: str = None, description: str = None) -> Dict[str, Any]: - """Erstellt einen neuen Agenten""" - agent_data = { - "mandate_id": self.mandate_id, - "user_id": self.user_id, - "name": name, - "type": agent_type, - "workspace_id": workspace_id, - "capabilities": capabilities, - "description": description - } - - return self.db.record_create("agents", agent_data) - - def update_agent(self, agent_id: int, name: str, agent_type: str, workspace_id: int, - capabilities: str = None, description: str = None) -> Dict[str, Any]: - """ - Aktualisiert einen vorhandenen Agenten - - Args: - agent_id: ID des zu aktualisierenden Agenten - name: Neuer Name des Agenten - agent_type: Neuer Typ des Agenten - workspace_id: ID des Workspaces, zu dem der Agent gehört - capabilities: Fähigkeiten des Agenten - description: Beschreibung des Agenten - - Returns: - Das aktualisierte Agenten-Objekt - """ - # Prüfen, ob der Agent existiert - agent = self.get_agent(agent_id) - if not agent: - return None - - # Daten für die Aktualisierung vorbereiten - agent_data = { - "name": name, - "type": agent_type, - "workspace_id": workspace_id, - "capabilities": capabilities if capabilities is not None else agent.get("capabilities"), - "description": description if description is not None else agent.get("description") - } - - # Agent aktualisieren - updated_agent = self.db.record_modify("agents", agent_id, agent_data) - - return updated_agent - - def delete_agent(self, agent_id: int) -> bool: - """ - Löscht einen Agenten aus der Datenbank - - Args: - agent_id: ID des zu löschenden Agenten - - Returns: - True, wenn der Agent erfolgreich gelöscht wurde, sonst False - """ - return self.db.record_delete("agents", agent_id) # Datei-Methoden @@ -374,7 +360,7 @@ class LucyDOMInterface: return None def create_file(self, name: str, file_type: str, content_type: str = None, - size: int = None, path: str = None) -> Dict[str, Any]: + size: int = None, path: str = None, file_hash: str = None) -> Dict[str, Any]: """Erstellt einen neuen Dateieintrag""" file_data = { "mandate_id": self.mandate_id, @@ -384,23 +370,19 @@ class LucyDOMInterface: "content_type": content_type, "size": size, "path": path, + "hash": file_hash, "upload_date": self._get_current_timestamp() } return self.db.record_create("files", file_data) - def update_file(self, file_id: int, name: str = None, file_type: str = None, - content_type: str = None, size: int = None, path: str = None) -> Dict[str, Any]: + def update_file(self, file_id: int, update_data: Dict[str, Any]) -> Dict[str, Any]: """ Aktualisiert eine vorhandene Datei Args: file_id: ID der zu aktualisierenden Datei - name: Neuer Name der Datei - file_type: Neuer Dateityp - content_type: Neuer Content-Type - size: Neue Dateigröße - path: Neuer Dateipfad + update_data: Dictionary mit zu aktualisierenden Feldern Returns: Das aktualisierte Datei-Objekt @@ -408,39 +390,297 @@ class LucyDOMInterface: # Prüfen, ob die Datei existiert file = self.get_file(file_id) if not file: - return None - - # Daten für die Aktualisierung vorbereiten - file_data = {} - - if name is not None: - file_data["name"] = name - if file_type is not None: - file_data["type"] = file_type - if content_type is not None: - file_data["content_type"] = content_type - if size is not None: - file_data["size"] = size - if path is not None: - file_data["path"] = path + raise FileNotFoundError(f"Datei mit ID {file_id} nicht gefunden") # Datei aktualisieren - return self.db.record_modify("files", file_id, file_data) - - def delete_file(self, file_id: int) -> bool: - """Löscht eine Datei aus der Datenbank""" - return self.db.record_delete("files", file_id) + return self.db.record_modify("files", file_id, update_data) + def check_for_duplicate_file(self, file_hash: str) -> Optional[Dict[str, Any]]: + """ + Check if a file with the same hash already exists + + Args: + file_hash: SHA-256 hash of the file content + + Returns: + File record if a duplicate exists, None otherwise + """ + files = self.db.get_recordset("files", record_filter={"hash": file_hash}) + if files: + return files[0] + return None + + def save_uploaded_file(self, file_content: bytes, file_name: str) -> Dict[str, Any]: + """ + Speichert eine hochgeladene Datei und erstellt einen Datenbankeintrag. + + Args: + file_content: Binärdaten der Datei + file_name: Name der Datei + + Returns: + Dictionary mit Metadaten der gespeicherten Datei + """ + try: + # Debug: Log the start of the file upload process + logger.info(f"Starting upload process for file: {file_name}") + logger.info(f"Upload directory: {self.upload_dir}, Mandate ID: {self.mandate_id}") + + # Debug: Check if file_content is valid bytes + if not isinstance(file_content, bytes): + logger.error(f"Invalid file_content type: {type(file_content)}") + raise ValueError(f"file_content must be bytes, got {type(file_content)}") + + # Calculate file hash for deduplication + file_hash = self.calculate_file_hash(file_content) + logger.debug(f"Calculated file hash: {file_hash}") + + # Check for duplicate + existing_file = self.check_for_duplicate_file(file_hash) + if existing_file: + # Simply return the existing file metadata + logger.info(f"Duplikat gefunden für {file_name}: {existing_file['id']}") + return existing_file + + # Generiere eindeutige ID + file_id = f"file_{uuid.uuid4()}" + logger.debug(f"Generated file ID: {file_id}") + + # Sanitize filename + safe_filename = Path(file_name).name # Get only the filename part + logger.debug(f"Sanitized filename: {safe_filename}") + + # Create parent directories if needed + mandate_upload_dir = os.path.join(self.upload_dir, str(self.mandate_id)) + logger.debug(f"Mandate upload directory: {mandate_upload_dir}") + + # Debug: Check if mandate upload directory exists + if not os.path.exists(mandate_upload_dir): + logger.info(f"Creating mandate upload directory: {mandate_upload_dir}") + + os.makedirs(mandate_upload_dir, exist_ok=True) + + # Dateipfad erstellen mit Mandant als Unterverzeichnis + file_path = os.path.join(mandate_upload_dir, f"{file_id}_{safe_filename}") + logger.debug(f"Full file path: {file_path}") + + # Datei speichern + logger.info(f"Writing file content to: {file_path}") + with open(file_path, "wb") as f: + f.write(file_content) + + # Verify file was created + if not os.path.exists(file_path): + logger.error(f"File was not created at path: {file_path}") + raise FileStorageError(f"File could not be created at {file_path}") + else: + logger.info(f"File successfully saved to: {file_path}") + + # Dateigröße bestimmen + file_size = len(file_content) + + # MIME-Typ und Dateityp bestimmen + mime_type = self.get_mime_type(file_path) + file_type = self.determine_file_type(file_path) + + # Erstelle Metadaten + file_meta = { + "id": file_id, + "name": file_name, + "path": file_path, + "size": file_size, + "type": file_type, + "content_type": mime_type, + "hash": file_hash, + "upload_date": datetime.now().isoformat(), + "mandate_id": self.mandate_id, + "user_id": self.user_id + } + + logger.debug(f"File metadata: {file_meta}") + + # Speichere in der Datenbank + logger.info(f"Saving file metadata to database for file: {file_id}") + db_file = self.create_file( + name=file_name, + file_type=file_type, + content_type=mime_type, + size=file_size, + path=file_path, + file_hash=file_hash + ) + + # Debug: Verify database record was created + if not db_file: + logger.warning(f"Database record for file {file_id} was not created properly") + else: + logger.info(f"Database record created for file {file_id}") + + # Wenn Datenbank-ID vorhanden ist, übernehme sie + if db_file and "id" in db_file: + file_meta["id"] = db_file["id"] + + logger.info(f"File upload process completed for: {file_name}") + return file_meta + + except Exception as e: + # If an error occurs, clean up any partial file + if 'file_path' in locals() and os.path.exists(file_path): + try: + logger.warning(f"Cleaning up partial file: {file_path}") + os.remove(file_path) + except Exception as cleanup_error: + logger.error(f"Error cleaning up partial file: {cleanup_error}") + + logger.error(f"Error in save_uploaded_file for {file_name}: {str(e)}", exc_info=True) + raise FileStorageError(f"Fehler beim Speichern der Datei: {str(e)}") + + + + async def read_file_content(self, file_id: str) -> Optional[bytes]: + """ + Reads the content of a file by ID + + Args: + file_id: ID of the file + + Returns: + File content as bytes or None if not found + """ + try: + # Get file metadata + file = self.get_file(file_id) + + if not file or "path" not in file: + raise FileNotFoundError(f"Datei mit ID {file_id} nicht gefunden") + + file_path = file["path"] + + # Check if file exists + if not os.path.exists(file_path): + raise FileNotFoundError(f"Datei nicht gefunden: {file_path}") + + # Read file content + with open(file_path, "rb") as f: + content = f.read() + + return content + except FileNotFoundError as e: + # Re-raise FileNotFoundError as is + raise + except Exception as e: + logger.error(f"Fehler beim Lesen der Datei {file_id}: {str(e)}") + raise FileError(f"Fehler beim Lesen der Datei: {str(e)}") + + def download_file(self, file_id: str) -> Optional[Dict[str, Any]]: + """ + Gibt eine Datei zum Download zurück. + + Args: + file_id: ID der Datei + + Returns: + Dictionary mit Dateidaten und -metadaten oder None, wenn nicht gefunden + """ + try: + # Suche die Datei in der Datenbank + file = self.get_file(file_id) + + if not file or "path" not in file: + raise FileNotFoundError(f"Datei mit ID {file_id} nicht gefunden") + + file_path = file["path"] + + # Prüfe, ob die Datei existiert + if not os.path.exists(file_path): + raise FileNotFoundError(f"Datei nicht gefunden: {file_path}") + + # Lese die Datei + with open(file_path, "rb") as f: + file_content = f.read() + + return { + "id": file_id, + "name": file.get("name", os.path.basename(file_path)), + "content_type": file.get("content_type", self.get_mime_type(file_path)), + "size": file.get("size", len(file_content)), + "path": file_path, + "content": file_content + } + except FileNotFoundError as e: + # Re-raise FileNotFoundError as is + raise + except Exception as e: + logger.error(f"Fehler beim Herunterladen der Datei {file_id}: {str(e)}") + raise FileError(f"Fehler beim Herunterladen der Datei: {str(e)}") + + def delete_file(self, file_id: str) -> bool: + """ + Löscht eine Datei aus der Datenbank und dem Dateisystem. + + Args: + file_id: ID der Datei + + Returns: + True bei Erfolg, False bei Fehler + """ + try: + # Suche die Datei in der Datenbank + file = self.get_file(file_id) + + if not file: + raise FileNotFoundError(f"Datei mit ID {file_id} nicht gefunden") + + # Prüfe, ob die Datei zum aktuellen Mandanten gehört + if file.get("mandate_id") != self.mandate_id: + raise FilePermissionError(f"Keine Berechtigung zum Löschen der Datei {file_id}") + + # Speichere den Dateipfad + file_path = file.get("path") + + # Check for other references to this file (by hash) + file_hash = file.get("hash") + if file_hash: + other_references = [f for f in self.db.get_recordset("files", record_filter={"hash": file_hash}) + if f.get("id") != file_id] + + # If other files reference this content, only delete the database entry + if other_references: + logger.info(f"Andere Referenzen auf den Dateiinhalt gefunden, nur DB-Eintrag wird gelöscht: {file_id}") + return self.db.record_delete("files", file_id) + + # Lösche den Datenbankeintrag + db_success = self.db.record_delete("files", file_id) + + # Wenn der Datenbankeintrag erfolgreich gelöscht wurde und ein Dateipfad vorhanden ist, + # lösche auch die Datei + if db_success and file_path and os.path.exists(file_path): + try: + os.remove(file_path) + return True + except Exception as e: + logger.error(f"Fehler beim physischen Löschen der Datei {file_path}: {str(e)}") + # Datenbankdatei wurde gelöscht, physische Datei nicht - trotzdem Erfolg melden + return True + + return db_success + except FileNotFoundError as e: + # Pass through FileNotFoundError + raise + except FilePermissionError as e: + # Pass through FilePermissionError + raise + except Exception as e: + logger.error(f"Fehler beim Löschen der Datei {file_id}: {str(e)}") + raise FileDeletionError(f"Fehler beim Löschen der Datei: {str(e)}") + + # Prompt-Methoden def get_all_prompts(self) -> List[Dict[str, Any]]: """Gibt alle Prompts des aktuellen Mandanten zurück""" return self.db.get_recordset("prompts") - def get_prompts_by_workspace(self, workspace_id: int) -> List[Dict[str, Any]]: - """Gibt alle Prompts eines Workspaces zurück""" - return self.db.get_recordset("prompts", record_filter={"workspace_id": workspace_id}) - def get_prompt(self, prompt_id: int) -> Optional[Dict[str, Any]]: """Gibt einen Prompt anhand seiner ID zurück""" prompts = self.db.get_recordset("prompts", record_filter={"id": prompt_id}) @@ -448,26 +688,25 @@ class LucyDOMInterface: return prompts[0] return None - def create_prompt(self, content: str, workspace_id: int) -> Dict[str, Any]: + def create_prompt(self, content: str, name: str) -> Dict[str, Any]: """Erstellt einen neuen Prompt""" prompt_data = { "mandate_id": self.mandate_id, "user_id": self.user_id, "content": content, - "workspace_id": workspace_id, + "name": name, "created_at": self._get_current_timestamp() } return self.db.record_create("prompts", prompt_data) - def update_prompt(self, prompt_id: int, content: str = None, workspace_id: int = None) -> Dict[str, Any]: + def update_prompt(self, prompt_id: int, content: str = None, name: str = None) -> Dict[str, Any]: """ Aktualisiert einen vorhandenen Prompt Args: prompt_id: ID des zu aktualisierenden Prompts content: Neuer Inhalt des Prompts - workspace_id: Neue ID des Workspaces, zu dem der Prompt gehört Returns: Das aktualisierte Prompt-Objekt @@ -482,8 +721,8 @@ class LucyDOMInterface: if content is not None: prompt_data["content"] = content - if workspace_id is not None: - prompt_data["workspace_id"] = workspace_id + if name is not None: + prompt_data["name"] = name # Prompt aktualisieren return self.db.record_modify("prompts", prompt_id, prompt_data) @@ -501,6 +740,514 @@ class LucyDOMInterface: return self.db.record_delete("prompts", prompt_id) + # Workflow Methoden + + def get_all_workflows(self) -> List[Dict[str, Any]]: + """Gibt alle Workflows des aktuellen Mandanten zurück""" + return self.db.get_recordset("workflows") + + def get_workflows_by_user(self, user_id: int) -> List[Dict[str, Any]]: + """Gibt alle Workflows eines Benutzers zurück""" + return self.db.get_recordset("workflows", record_filter={"user_id": user_id}) + + def get_workflow(self, workflow_id: str) -> Optional[Dict[str, Any]]: + """Gibt einen Workflow anhand seiner ID zurück""" + workflows = self.db.get_recordset("workflows", record_filter={"id": workflow_id}) + if workflows: + return workflows[0] + return None + + def create_workflow(self, workflow_data: Dict[str, Any]) -> Dict[str, Any]: + """Erstellt einen neuen Workflow in der Datenbank""" + # Stellen Sie sicher, dass mandate_id und user_id gesetzt sind + if "mandate_id" not in workflow_data: + workflow_data["mandate_id"] = self.mandate_id + + if "user_id" not in workflow_data: + workflow_data["user_id"] = self.user_id + + # Zeitstempel setzen, falls nicht vorhanden + current_time = self._get_current_timestamp() + if "started_at" not in workflow_data: + workflow_data["started_at"] = current_time + + if "last_activity" not in workflow_data: + workflow_data["last_activity"] = current_time + + return self.db.record_create("workflows", workflow_data) + + def update_workflow(self, workflow_id: str, workflow_data: Dict[str, Any]) -> Dict[str, Any]: + """ + Aktualisiert einen vorhandenen Workflow. + + Args: + workflow_id: ID des zu aktualisierenden Workflows + workflow_data: Neue Daten für den Workflow + + Returns: + Das aktualisierte Workflow-Objekt + """ + # Prüfen, ob der Workflow existiert + workflow = self.get_workflow(workflow_id) + if not workflow: + return None + + # Aktualisierungszeit setzen + workflow_data["last_activity"] = self._get_current_timestamp() + + # Workflow aktualisieren + return self.db.record_modify("workflows", workflow_id, workflow_data) + + def delete_workflow(self, workflow_id: str) -> bool: + """ + Löscht einen Workflow aus der Datenbank. + + Args: + workflow_id: ID des zu löschenden Workflows + + Returns: + True bei Erfolg, False wenn der Workflow nicht existiert + """ + # Prüfen, ob der Workflow existiert + workflow = self.get_workflow(workflow_id) + if not workflow: + return False + + # Prüfen, ob der Benutzer der Eigentümer ist oder Admin-Rechte hat + if workflow.get("user_id") != self.user_id: + # Hier könnte eine Prüfung auf Admin-Rechte erfolgen + return False + + # Workflow löschen + return self.db.record_delete("workflows", workflow_id) + + def get_workflow_messages(self, workflow_id: str) -> List[Dict[str, Any]]: + """Gibt alle Nachrichten eines Workflows zurück""" + return self.db.get_recordset("workflow_messages", record_filter={"workflow_id": workflow_id}) + + def create_workflow_message(self, message_data: Dict[str, Any]) -> Dict[str, Any]: + """Erstellt eine neue Nachricht für einen Workflow + + Args: + message_data: Die Nachrichtendaten + + Returns: + Die erstellte Nachricht oder None bei Fehler + """ + try: + # Check if required fields are present + required_fields = ["id", "workflow_id"] + for field in required_fields: + if field not in message_data: + logger.error(f"Pflichtfeld '{field}' fehlt in message_data") + raise ValueError(f"Pflichtfeld '{field}' fehlt in den Nachrichtendaten") + + # Validate that ID is not None + if message_data["id"] is None: + message_data["id"] = f"msg_{uuid.uuid4()}" + logger.warning(f"Automatisch generierte ID für Workflow-Nachricht: {message_data['id']}") + + # Stellen Sie sicher, dass die benötigten Felder vorhanden sind + if "created_at" not in message_data: + message_data["created_at"] = self._get_current_timestamp() + + # Debug-Log für die zu erstellenden Daten + logger.debug(f"Erstelle Workflow-Nachricht mit Daten: {message_data}") + + return self.db.record_create("workflow_messages", message_data) + except Exception as e: + logger.error(f"Fehler beim Erstellen der Workflow-Nachricht: {str(e)}") + # Return None instead of raising to avoid cascading failures + return None + + def update_workflow_message(self, message_id: str, message_data: Dict[str, Any]) -> Dict[str, Any]: + """ + Aktualisiert eine bestehende Workflow-Nachricht in der Datenbank + with improved document handling. + + Args: + message_id: ID der Nachricht + message_data: Zu aktualisierende Daten + + Returns: + Das aktualisierte Nachrichtenobjekt oder None bei Fehler + """ + try: + # Print debug info + print(f"Updating message {message_id} in database") + + # Ensure message_id is provided + if not message_id: + logger.error("No message_id provided for update_workflow_message") + raise ValueError("message_id cannot be empty") + + # Check if message exists in database + messages = self.db.get_recordset("workflow_messages", record_filter={"id": message_id}) + if not messages: + logger.warning(f"Message with ID {message_id} does not exist in database") + + # If message doesn't exist but we have workflow_id, create it + if "workflow_id" in message_data: + logger.info(f"Creating new message with ID {message_id} for workflow {message_data.get('workflow_id')}") + return self.db.record_create("workflow_messages", message_data) + else: + logger.error(f"Workflow ID missing for new message {message_id}") + return None + + # Ensure documents array is handled properly + if "documents" in message_data: + logger.info(f"Message {message_id} has {len(message_data['documents'])} documents") + + # Make sure we're not storing huge content in the database + # For each document, ensure content size is reasonable + documents_to_store = [] + for doc in message_data["documents"]: + doc_copy = doc.copy() + + # Process contents array if it exists + if "contents" in doc_copy: + # Ensure contents is not too large - limit text size + for content in doc_copy["contents"]: + if content.get("type") == "text" and "text" in content: + text = content["text"] + if len(text) > 1000: # Limit text preview to 1000 chars + content["text"] = text[:1000] + "... [truncated]" + + documents_to_store.append(doc_copy) + + # Replace with the processed documents + message_data["documents"] = documents_to_store + + # Log the update data size for debugging + update_data_size = len(str(message_data)) + logger.debug(f"Update data size: {update_data_size} bytes") + + # Ensure ID is in the dataset + if 'id' not in message_data: + message_data['id'] = message_id + + # Update the message + updated_message = self.db.record_modify("workflow_messages", message_id, message_data) + if updated_message: + logger.info(f"Message {message_id} updated successfully") + else: + logger.warning(f"Failed to update message {message_id}") + + return updated_message + except Exception as e: + logger.error(f"Error updating message {message_id}: {str(e)}", exc_info=True) + # Re-raise with full information + raise ValueError(f"Error updating message {message_id}: {str(e)}") + + + + def get_workflow_logs(self, workflow_id: str) -> List[Dict[str, Any]]: + """Gibt alle Log-Einträge eines Workflows zurück""" + return self.db.get_recordset("workflow_logs", record_filter={"workflow_id": workflow_id}) + + def create_workflow_log(self, log_data: Dict[str, Any]) -> Dict[str, Any]: + """Erstellt einen neuen Log-Eintrag für einen Workflow""" + # Stellen Sie sicher, dass die benötigten Felder vorhanden sind + if "timestamp" not in log_data: + log_data["timestamp"] = self._get_current_timestamp() + + return self.db.record_create("workflow_logs", log_data) + + def save_workflow_state(self, workflow: Dict[str, Any], save_messages: bool = True, save_logs: bool = True) -> bool: + """ + Speichert den kompletten Zustand eines Workflows in der Datenbank. + Dies umfasst den Workflow selbst, Nachrichten und Logs. + + Args: + workflow: Das vollständige Workflow-Objekt + save_messages: Flag, ob Nachrichten gespeichert werden sollen + save_logs: Flag, ob Logs gespeichert werden sollen + + Returns: + True bei Erfolg, False bei Fehler + """ + try: + workflow_id = workflow.get("id") + if not workflow_id: + return False + + # Extrahiere nur die für die Datenbank relevanten Workflow-Felder + workflow_db_data = { + "id": workflow_id, + "mandate_id": workflow.get("mandate_id", self.mandate_id), + "user_id": workflow.get("user_id", self.user_id), + "name": workflow.get("name", f"Workflow {workflow_id}"), + "status": workflow.get("status", "unknown"), + "started_at": workflow.get("started_at", self._get_current_timestamp()), + "last_activity": workflow.get("last_activity", self._get_current_timestamp()), + "completed_at": workflow.get("completed_at"), + "data_stats": workflow.get("data_stats", {}) + } + + # Prüfen, ob der Workflow bereits existiert + existing_workflow = self.get_workflow(workflow_id) + if existing_workflow: + self.update_workflow(workflow_id, workflow_db_data) + else: + self.create_workflow(workflow_db_data) + + + # Nachrichten speichern + if save_messages and "messages" in workflow: + # Bestehende Nachrichten abrufen + existing_messages = {msg["id"]: msg for msg in self.get_workflow_messages(workflow_id)} + + for message in workflow["messages"]: + message_id = message.get("id") + if not message_id: + continue + + # Nur relevante Daten für die Datenbank extrahieren + message_data = { + "id": message_id, + "workflow_id": workflow_id, + "sequence_no": message.get("sequence_no", 0), + "role": message.get("role", "unknown"), + "content": message.get("content"), + "agent_type": message.get("agent_type"), + "created_at": message.get("started_at", self._get_current_timestamp()), + # IMPORTANT: Include documents field to persist file attachments + "documents": message.get("documents", []) + } + + # Debug logging for documents + doc_count = len(message.get("documents", [])) + if doc_count > 0: + logger.info(f"Message {message_id} has {doc_count} documents to save") + + # Nachricht erstellen oder aktualisieren + if message_id in existing_messages: + self.db.record_modify("workflow_messages", message_id, message_data) + else: + self.db.record_create("workflow_messages", message_data) + + # Logs speichern + if save_logs and "logs" in workflow: + # Bestehende Logs abrufen + existing_logs = {log["id"]: log for log in self.get_workflow_logs(workflow_id)} + + for log in workflow["logs"]: + log_id = log.get("id") + if not log_id: + continue + + # Nur relevante Daten für die Datenbank extrahieren + log_data = { + "id": log_id, + "workflow_id": workflow_id, + "message": log.get("message", ""), + "type": log.get("type", "info"), + "timestamp": log.get("timestamp", self._get_current_timestamp()), + "agent_id": log.get("agent_id"), + "agent_name": log.get("agent_name") + } + + # Log erstellen oder aktualisieren + if log_id in existing_logs: + self.db.record_modify("workflow_logs", log_id, log_data) + else: + self.db.record_create("workflow_logs", log_data) + + return True + except Exception as e: + logger.error(f"Fehler beim Speichern des Workflow-Zustands: {str(e)}") + return False + + + def load_workflow_state(self, workflow_id: str) -> Optional[Dict[str, Any]]: + """ + Lädt den kompletten Zustand eines Workflows aus der Datenbank. + Dies umfasst den Workflow selbst, Nachrichten und Logs. + + Args: + workflow_id: ID des zu ladenden Workflows + + Returns: + Das vollständige Workflow-Objekt oder None bei Fehler + """ + try: + # Basis-Workflow laden + workflow = self.get_workflow(workflow_id) + if not workflow: + return None + + # Log the workflow base retrieval + logger.debug(f"Loaded base workflow {workflow_id} from database") + + # Nachrichten laden + messages = self.get_workflow_messages(workflow_id) + # Nach Sequenznummer sortieren + messages.sort(key=lambda x: x.get("sequence_no", 0)) + + # Debug log for messages and document counts + message_count = len(messages) + logger.debug(f"Loaded {message_count} messages for workflow {workflow_id}") + + # Log document counts for each message + for msg in messages: + doc_count = len(msg.get("documents", [])) + if doc_count > 0: + logger.info(f"Message {msg.get('id')} has {doc_count} documents loaded from database") + # Log document details for debugging + for i, doc in enumerate(msg.get("documents", [])): + source = doc.get("source", {}) + logger.debug(f"Document {i+1}: {source.get('name', 'unnamed')} (ID: {source.get('id', 'unknown')})") + + # Logs laden + logs = self.get_workflow_logs(workflow_id) + # Nach Zeitstempel sortieren + logs.sort(key=lambda x: x.get("timestamp", "")) + + # Vollständiges Workflow-Objekt zusammenbauen + complete_workflow = workflow.copy() + complete_workflow["messages"] = messages + complete_workflow["logs"] = logs + + return complete_workflow + except Exception as e: + logger.error(f"Fehler beim Laden des Workflow-Zustands: {str(e)}") + return None + + + # DELETE Workflow message elements + + def delete_workflow_message(self, workflow_id: str, message_id: str) -> bool: + """ + Löscht eine Nachricht aus einem Workflow in der Datenbank. + + Args: + workflow_id: ID des zugehörigen Workflows + message_id: ID der zu löschenden Nachricht + + Returns: + True bei Erfolg, False bei Fehler + """ + try: + # Prüfen, ob die Nachricht existiert + messages = self.get_workflow_messages(workflow_id) + message = next((m for m in messages if m.get("id") == message_id), None) + + if not message: + logger.warning(f"Nachricht {message_id} für Workflow {workflow_id} nicht gefunden") + return False + + # Nachricht aus der Datenbank löschen + return self.db.record_delete("workflow_messages", message_id) + except Exception as e: + logger.error(f"Fehler beim Löschen der Nachricht {message_id}: {str(e)}") + return False + + def delete_file_from_message(self, workflow_id: str, message_id: str, file_id: str) -> bool: + """ + Entfernt eine Dateireferenz aus einer Nachricht. + Die Datei selbst wird nicht gelöscht, nur die Referenz in der Nachricht. + Enhanced version with improved file matching. + + Args: + workflow_id: ID des zugehörigen Workflows + message_id: ID der Nachricht + file_id: ID der zu entfernenden Datei + + Returns: + True bei Erfolg, False bei Fehler + """ + try: + # Log operation + logger.info(f"Removing file {file_id} from message {message_id} in workflow {workflow_id}") + + # Get all workflow messages + all_messages = self.get_workflow_messages(workflow_id) + logger.debug(f"Workflow {workflow_id} has {len(all_messages)} messages") + + # Try different approaches to find the message + message = None + + # Exact match + message = next((m for m in all_messages if m.get("id") == message_id), None) + + # Case-insensitive match + if not message and isinstance(message_id, str): + message = next((m for m in all_messages + if isinstance(m.get("id"), str) and m.get("id").lower() == message_id.lower()), None) + + # Partial match (starts with) + if not message and isinstance(message_id, str): + message = next((m for m in all_messages + if isinstance(m.get("id"), str) and m.get("id").startswith(message_id)), None) + + if not message: + logger.warning(f"Message {message_id} not found in workflow {workflow_id}") + return False + + # Log the found message + logger.info(f"Found message: {message.get('id')}") + + # Check if message has documents + if "documents" not in message or not message["documents"]: + logger.warning(f"No documents in message {message_id}") + return False + + # Log existing documents + documents = message.get("documents", []) + logger.debug(f"Message has {len(documents)} documents") + for i, doc in enumerate(documents): + doc_id = doc.get("id", "unknown") + source = doc.get("source", {}) + source_id = source.get("id", "unknown") + logger.debug(f"Document {i}: doc_id={doc_id}, source_id={source_id}") + + # Create a new list of documents without the one to delete + updated_documents = [] + removed = False + + for doc in documents: + doc_id = doc.get("id") + source = doc.get("source", {}) + source_id = source.get("id") + + # Flexible matching approach + should_remove = ( + (doc_id == file_id) or + (source_id == file_id) or + (isinstance(doc_id, str) and file_id in doc_id) or + (isinstance(source_id, str) and file_id in source_id) + ) + + if should_remove: + removed = True + logger.info(f"Found file to remove: doc_id={doc_id}, source_id={source_id}") + else: + updated_documents.append(doc) + + if not removed: + logger.warning(f"No matching file {file_id} found in message {message_id}") + return False + + # Update message with modified documents array + message_update = { + "documents": updated_documents + } + + # Apply the update directly to the database + updated = self.db.record_modify("workflow_messages", message["id"], message_update) + + if updated: + logger.info(f"Successfully removed file {file_id} from message {message_id}") + return True + else: + logger.warning(f"Failed to update message {message_id} in database") + return False + + except Exception as e: + logger.error(f"Error removing file {file_id} from message {message_id}: {str(e)}") + return False + + # Singleton-Factory für LucyDOMInterface-Instanzen pro Kontext _lucydom_interfaces = {} @@ -515,4 +1262,4 @@ def get_lucydom_interface(mandate_id: int = 0, user_id: int = 0) -> LucyDOMInter return _lucydom_interfaces[context_key] # Init -get_lucydom_interface() \ No newline at end of file +get_lucydom_interface() diff --git a/gwserver/modules/lucydom_model.py b/gwserver/modules/lucydom_model.py index d9f07c50..cdb056b4 100644 --- a/gwserver/modules/lucydom_model.py +++ b/gwserver/modules/lucydom_model.py @@ -15,38 +15,7 @@ class Label(BaseModel): return self.default -class Agent(BaseModel): - """Datenmodell für einen Agenten""" - id: int = Field(description="Eindeutige ID des Agenten") - mandate_id: int = Field(description="ID des zugehörigen Mandanten") - user_id: int = Field(description="ID des Erstellers") - name: str = Field(description="Name des Agenten") - type: str = Field(description="Typ des Agenten") - workspace_id: int = Field(description="ID des zugehörigen Workspaces") - capabilities: Optional[str] = Field(None, description="Fähigkeiten des Agenten") - description: Optional[str] = Field(None, description="Beschreibung des Agenten") - instructions: Optional[str] = Field(None, description="Anweisungen für den Agenten") - - label: Label = Field( - default=Label(default="Agent", translations={"en": "Agent", "fr": "Agent"}), - description="Label für die Klasse" - ) - - # Labels für Attribute - field_labels: Dict[str, Label] = { - "id": Label(default="ID", translations={}), - "mandate_id": Label(default="Mandanten-ID", translations={"en": "Mandate ID", "fr": "ID de mandat"}), - "user_id": Label(default="Benutzer-ID", translations={"en": "User ID", "fr": "ID d'utilisateur"}), - "name": Label(default="Name", translations={"en": "Name", "fr": "Nom"}), - "type": Label(default="Typ", translations={"en": "Type", "fr": "Type"}), - "workspace_id": Label(default="Workspace-ID", translations={"en": "Workspace ID", "fr": "ID d'espace de travail"}), - "capabilities": Label(default="Fähigkeiten", translations={"en": "Capabilities", "fr": "Capacités"}), - "description": Label(default="Beschreibung", translations={"en": "Description", "fr": "Description"}), - "instructions": Label(default="Anweisungen", translations={"en": "Instructions", "fr": "Instructions"}) - } - - -class DataObject(BaseModel): +class FileItem(BaseModel): """Datenmodell für ein Datenobjekt""" id: int = Field(description="Eindeutige ID des Datenobjekts") mandate_id: int = Field(description="ID des zugehörigen Mandanten") @@ -83,6 +52,7 @@ class Prompt(BaseModel): mandate_id: int = Field(description="ID des zugehörigen Mandanten") user_id: int = Field(description="ID des Erstellers") content: str = Field(description="Inhalt des Prompts") + name: str = Field(description="Anzeigename des Prompts") label: Label = Field( default=Label(default="Prompt", translations={"en": "Prompt", "fr": "Invite"}), @@ -95,179 +65,85 @@ class Prompt(BaseModel): "mandate_id": Label(default="Mandanten-ID", translations={"en": "Mandate ID", "fr": "ID de mandat"}), "user_id": Label(default="Benutzer-ID", translations={"en": "User ID", "fr": "ID d'utilisateur"}), "content": Label(default="Inhalt", translations={"en": "Content", "fr": "Contenu"}), + "name": Label(default="Name", translations={"en": "Label", "fr": "Nom"}), } -class Workspace(BaseModel): - """Datenmodell für einen Workspace""" - id: int = Field(description="Eindeutige ID des Workspaces") - mandate_id: int = Field(description="ID des zugehörigen Mandanten") - user_id: int = Field(description="ID des Erstellers") - name: str = Field(description="Name des Workspaces") - prompts: List[Prompt] = Field(default=[], description="Liste der Prompts im Workspace") - agents: List[Agent] = Field(default=[], description="Liste der Agenten im Workspace") - dataObjectReferences: List[int] = Field(default=[], description="Referenzen zu Datenobjekten") - - label: Label = Field( - default=Label(default="Workspace", translations={"en": "Workspace", "fr": "Espace de travail"}), - description="Label für die Klasse" - ) - - # Labels für Attribute - field_labels: Dict[str, Label] = { - "id": Label(default="ID", translations={}), - "mandate_id": Label(default="Mandanten-ID", translations={"en": "Mandate ID", "fr": "ID de mandat"}), - "user_id": Label(default="Benutzer-ID", translations={"en": "User ID", "fr": "ID d'utilisateur"}), - "name": Label(default="Name", translations={"en": "Name", "fr": "Nom"}), - "prompts": Label(default="Prompts", translations={"en": "Prompts", "fr": "Invites"}), - "agents": Label(default="Agenten", translations={"en": "Agents", "fr": "Agents"}), - "dataObjectReferences": Label(default="Datenobjekte", translations={"en": "Data Objects", "fr": "Objets de données"}) - } +# Neue Workflow-Modellklassen +class DocumentSource(BaseModel): + """Quelle eines Dokuments im Workflow""" + type: str = Field(description="Typ der Quelle ('prompt', 'file', 'clipboard')") + path: Optional[str] = Field(None, description="Speicherpfad (für Dateien)") + name: str = Field(description="Anzeigename der Datei") + size: Optional[int] = Field(None, description="Größe in Bytes") + lines: Optional[int] = Field(None, description="Zeilenanzahl (für Textdateien)") + content_type: Optional[str] = Field(None, description="MIME-Typ") + upload_date: Optional[str] = Field(None, description="Uploaddatum") -class WorkflowRequest(BaseModel): - """Anforderung zur Ausführung eines Workflows""" - # Make these fields optional since they'll be populated from user context - id: Optional[int] = Field(None, description="Eindeutige ID der Anforderung") - mandate_id: Optional[int] = Field(None, description="ID des zugehörigen Mandanten") - user_id: Optional[int] = Field(None, description="ID des Erstellers") - - # Keep these fields required - workspace_id: int = Field(description="ID des zugehörigen Workspaces") - prompt: str = Field(description="Zu verwendender Prompt") - agents: List[int] = Field(description="Liste von Agent-IDs") - files: List[int] = Field(description="Liste von Datei-IDs") - workflow_name: Optional[str] = Field(None, description="Name des Workflows") - - label: Label = Field( - default=Label(default="Workflow-Anforderung", translations={"en": "Workflow Request", "fr": "Demande de workflow"}), - description="Label für die Klasse" - ) - - # Labels für Attribute - field_labels: Dict[str, Label] = { - "id": Label(default="ID", translations={}), - "mandate_id": Label(default="Mandanten-ID", translations={"en": "Mandate ID", "fr": "ID de mandat"}), - "user_id": Label(default="Benutzer-ID", translations={"en": "User ID", "fr": "ID d'utilisateur"}), - "workspace_id": Label(default="Workspace-ID", translations={"en": "Workspace ID", "fr": "ID d'espace de travail"}), - "prompt": Label(default="Prompt", translations={"en": "Prompt", "fr": "Invite"}), - "agents": Label(default="Agenten", translations={"en": "Agents", "fr": "Agents"}), - "files": Label(default="Dateien", translations={"en": "Files", "fr": "Fichiers"}), - "workflow_name": Label(default="Workflow-Name", translations={"en": "Workflow name", "fr": "Nom du workflow"}) - } +class DocumentContent(BaseModel): + """Inhalt eines Dokuments im Workflow""" + label: Optional[str] = Field(None, description="Optionale Bezeichnung") + type: str = Field(description="Typ des Inhalts ('text', 'image', 'chart', etc.)") + text: Optional[str] = Field(None, description="Textinhalt") + is_extracted: Optional[bool] = Field(False, description="Flag, ob aus Originaldatei extrahiert") +class Document(BaseModel): + """Dokument im Workflow (inkl. Prompt und referenzierte Dateien)""" + id: str = Field(description="Eindeutige ID des Dokuments") + source: DocumentSource = Field(description="Quellmetadaten") + contents: List[DocumentContent] = Field(description="Dokumentinhalte") -class WorkflowResponse(BaseModel): - """Antwort nach dem Start eines Workflows""" - workflow_id: int = Field(description="ID des gestarteten Workflows") - mandate_id: int = Field(description="ID des zugehörigen Mandanten") - user_id: int = Field(description="ID des Erstellers") - status: str = Field(description="Status des Workflows") - message: str = Field(description="Statusnachricht") +class DataStats(BaseModel): + """Statistiken für Performance und Datennutzung""" + processing_time: Optional[float] = Field(None, description="Verarbeitungszeit in Sekunden") + token_count: Optional[int] = Field(None, description="Token-Anzahl (für KI-Modelle)") + bytes_sent: Optional[int] = Field(None, description="Gesendete Bytes") + bytes_received: Optional[int] = Field(None, description="Empfangene Bytes") + +class Message(BaseModel): + """Nachrichtenobjekt im Workflow""" + id: str = Field(description="Eindeutige ID der Nachricht") + workflow_id: str = Field(description="Referenz zum übergeordneten Workflow") + parent_message_id: Optional[str] = Field(None, description="Referenz zur beantworteten Nachricht") + started_at: str = Field(description="Zeitstempel für Nachrichtenerstellung") + finished_at: Optional[str] = Field(None, description="Zeitstempel für Nachrichtenabschluss") + sequence_no: int = Field(description="Sequenznummer für Sortierung") - label: Label = Field( - default=Label(default="Workflow-Antwort", translations={"en": "Workflow Response", "fr": "Réponse de workflow"}), - description="Label für die Klasse" - ) + status: str = Field(description="Status der Nachricht ('pending', 'processing', 'completed', 'failed')") + role: str = Field(description="Rolle des Absenders ('system', 'user', 'assistant')") - # Labels für Attribute - field_labels: Dict[str, Label] = { - "workflow_id": Label(default="Workflow-ID", translations={"en": "Workflow ID", "fr": "ID de workflow"}), - "mandate_id": Label(default="Mandanten-ID", translations={"en": "Mandate ID", "fr": "ID de mandat"}), - "user_id": Label(default="Benutzer-ID", translations={"en": "User ID", "fr": "ID d'utilisateur"}), - "status": Label(default="Status", translations={"en": "Status", "fr": "État"}), - "message": Label(default="Nachricht", translations={"en": "Message", "fr": "Message"}) - } + data_stats: Optional[DataStats] = Field(None, description="Statistiken") + documents: Optional[List[Document]] = Field(None, description="Dokumente in dieser Nachricht") + content: Optional[str] = Field(None, description="Textinhalt der Nachricht") + agent_type: Optional[str] = Field(None, description="Typ des verwendeten Agenten") - -class LogEntry(BaseModel): - """Protokolleintrag während der Workflow-Ausführung""" - id: int = Field(description="Eindeutige ID des Protokolleintrags") - mandate_id: int = Field(description="ID des zugehörigen Mandanten") - user_id: int = Field(description="ID des Erstellers") - message: str = Field(description="Protokollnachricht") - type: str = Field(description="Typ des Eintrags ('info', 'error', 'start', 'complete', 'success')") - timestamp: str = Field(description="Zeitstempel des Eintrags") - agent_id: Optional[int] = Field(None, description="ID des zugehörigen Agenten") - agent_name: Optional[str] = Field(None, description="Name des zugehörigen Agenten") - - label: Label = Field( - default=Label(default="Protokolleintrag", translations={"en": "Log Entry", "fr": "Entrée de journal"}), - description="Label für die Klasse" - ) - - # Labels für Attribute - field_labels: Dict[str, Label] = { - "id": Label(default="ID", translations={}), - "mandate_id": Label(default="Mandanten-ID", translations={"en": "Mandate ID", "fr": "ID de mandat"}), - "user_id": Label(default="Benutzer-ID", translations={"en": "User ID", "fr": "ID d'utilisateur"}), - "message": Label(default="Nachricht", translations={"en": "Message", "fr": "Message"}), - "type": Label(default="Typ", translations={"en": "Type", "fr": "Type"}), - "timestamp": Label(default="Zeitstempel", translations={"en": "Timestamp", "fr": "Horodatage"}), - "agent_id": Label(default="Agent-ID", translations={"en": "Agent ID", "fr": "ID d'agent"}), - "agent_name": Label(default="Agent-Name", translations={"en": "Agent name", "fr": "Nom d'agent"}) - } - - -class Result(BaseModel): - """Ergebnis eines Agenten während der Workflow-Ausführung""" - id: int = Field(description="Eindeutige ID des Ergebnisses") - mandate_id: int = Field(description="ID des zugehörigen Mandanten") - user_id: int = Field(description="ID des Erstellers") - title: str = Field(description="Titel des Ergebnisses") - agent_id: int = Field(description="ID des zugehörigen Agenten") - agent_name: str = Field(description="Name des zugehörigen Agenten") - type: str = Field(description="Typ des Ergebnisses ('text', 'chart', 'image', etc.)") - content: str = Field(description="Inhalt des Ergebnisses") - timestamp: str = Field(description="Zeitstempel der Erstellung") - metadata: Optional[Dict[str, Any]] = Field(None, description="Zusätzliche Metadaten") - - label: Label = Field( - default=Label(default="Ergebnis", translations={"en": "Result", "fr": "Résultat"}), - description="Label für die Klasse" - ) - - # Labels für Attribute - field_labels: Dict[str, Label] = { - "id": Label(default="ID", translations={}), - "mandate_id": Label(default="Mandanten-ID", translations={"en": "Mandate ID", "fr": "ID de mandat"}), - "user_id": Label(default="Benutzer-ID", translations={"en": "User ID", "fr": "ID d'utilisateur"}), - "title": Label(default="Titel", translations={"en": "Title", "fr": "Titre"}), - "agent_id": Label(default="Agent-ID", translations={"en": "Agent ID", "fr": "ID d'agent"}), - "agent_name": Label(default="Agent-Name", translations={"en": "Agent name", "fr": "Nom d'agent"}), - "type": Label(default="Typ", translations={"en": "Type", "fr": "Type"}), - "content": Label(default="Inhalt", translations={"en": "Content", "fr": "Contenu"}), - "timestamp": Label(default="Zeitstempel", translations={"en": "Timestamp", "fr": "Horodatage"}), - "metadata": Label(default="Metadaten", translations={"en": "Metadata", "fr": "Métadonnées"}) - } - - -class WorkflowStatus(BaseModel): - """Status eines Workflows""" - id: int = Field(description="Eindeutige ID des Workflow-Status") - mandate_id: int = Field(description="ID des zugehörigen Mandanten") - user_id: int = Field(description="ID des Erstellers") +class Workflow(BaseModel): + """Workflow-Objekt für Multi-Agent-System""" + id: str = Field(description="Eindeutige ID des Workflows") name: Optional[str] = Field(None, description="Name des Workflows") - status: str = Field(description="Status des Workflows ('running', 'completed', 'failed')") - progress: float = Field(description="Fortschritt (0.0 - 1.0)") + mandate_id: int = Field(description="ID des Mandanten") + user_id: int = Field(description="ID des Benutzers") + status: str = Field(description="Status des Workflows ('running', 'failed', 'stopped')") started_at: str = Field(description="Startzeitpunkt") - completed_at: Optional[str] = Field(None, description="Abschlusszeitpunkt") - agent_statuses: Optional[Dict[str, str]] = Field(None, description="Status der einzelnen Agenten") + last_activity: str = Field(description="Zeitpunkt der letzten Aktivität") + current_round: int = Field(description="Aktuelle Runde") + waiting_for_user: bool = Field(False, description="Flag, ob auf Benutzereingabe gewartet wird") - label: Label = Field( - default=Label(default="Workflow-Status", translations={"en": "Workflow Status", "fr": "État du workflow"}), - description="Label für die Klasse" - ) - - # Labels für Attribute - field_labels: Dict[str, Label] = { - "id": Label(default="ID", translations={}), - "mandate_id": Label(default="Mandanten-ID", translations={"en": "Mandate ID", "fr": "ID de mandat"}), - "user_id": Label(default="Benutzer-ID", translations={"en": "User ID", "fr": "ID d'utilisateur"}), - "name": Label(default="Name", translations={"en": "Name", "fr": "Nom"}), - "status": Label(default="Status", translations={"en": "Status", "fr": "État"}), - "progress": Label(default="Fortschritt", translations={"en": "Progress", "fr": "Progrès"}), - "started_at": Label(default="Gestartet am", translations={"en": "Started at", "fr": "Démarré le"}), - "completed_at": Label(default="Abgeschlossen am", translations={"en": "Completed at", "fr": "Terminé le"}), - "agent_statuses": Label(default="Agent-Status", translations={"en": "Agent status", "fr": "État des agents"}) - } \ No newline at end of file + data_stats: Optional[Dict[str, Any]] = Field(None, description="Gesamt-Statistiken") + messages: List[Message] = Field(default=[], description="Nachrichtenverlauf") + logs: List[Dict[str, Any]] = Field(default=[], description="Protokolleinträge") + +# Anfragemodelle für die API + +class WorkflowCreateRequest(BaseModel): + """Anfrage zur Erstellung eines neuen Workflows""" + name: Optional[str] = Field(None, description="Name des Workflows") + prompt: str = Field(description="Zu verwendender Prompt") + files: List[int] = Field(default=[], description="Liste von Datei-IDs") + +class UserInputRequest(BaseModel): + """Anfrage für Benutzereingabe an einen laufenden Workflow""" + message: str = Field(description="Nachricht des Benutzers") + additional_files: List[int] = Field(default=[], description="Liste zusätzlicher Datei-IDs") + diff --git a/gwserver/routes/agents.py b/gwserver/routes/agents.py deleted file mode 100644 index 5350c6a9..00000000 --- a/gwserver/routes/agents.py +++ /dev/null @@ -1,162 +0,0 @@ -from fastapi import APIRouter, HTTPException, Depends, Body, Query, Path -from typing import List, Dict, Any, Optional -from fastapi import status - -# Import auth module -from auth import get_current_active_user, get_user_context - -# Import interfaces -from modules.lucydom_interface import get_lucydom_interface - -# Router für Agenten-Endpunkte erstellen -router = APIRouter( - prefix="/api/agents", - tags=["Agents"], - responses={404: {"description": "Not found"}} -) - -@router.get("", response_model=List[Dict[str, Any]]) -async def get_agents( - workspace_id: Optional[int] = Query(None), - current_user: Dict[str, Any] = Depends(get_current_active_user) -): - """Alle Agenten oder Agenten eines bestimmten Workspaces abrufen""" - mandate_id, user_id = await get_user_context(current_user) - - # LucyDOM-Interface mit Benutzerkontext initialisieren - lucy_interface = get_lucydom_interface(mandate_id, user_id) - - if workspace_id: - return lucy_interface.get_agents_by_workspace(workspace_id) - - return lucy_interface.get_all_agents() - - -@router.post("", response_model=Dict[str, Any]) -async def create_agent( - agent: Dict[str, Any] = Body(...), - current_user: Dict[str, Any] = Depends(get_current_active_user) -): - """Einen neuen Agenten erstellen""" - mandate_id, user_id = await get_user_context(current_user) - - # LucyDOM-Interface mit Benutzerkontext initialisieren - lucy_interface = get_lucydom_interface(mandate_id, user_id) - - workspace_id = agent.get("workspace_id") - - if not workspace_id: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail="workspace_id ist erforderlich" - ) - - # Workspace existiert? - workspace = lucy_interface.get_workspace(workspace_id) - if not workspace: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=f"Workspace mit ID {workspace_id} nicht gefunden für User {user_id} im Mandanten {mandate_id}" - ) - - new_agent = lucy_interface.create_agent( - name=agent.get("name", "Neuer Agent"), - agent_type=agent.get("type", "generic"), - workspace_id=workspace_id, - capabilities=agent.get("capabilities", ""), - description=agent.get("description", "") - ) - - return new_agent - - -@router.get("/{agent_id}", response_model=Dict[str, Any]) -async def get_agent( - agent_id: int, - current_user: Dict[str, Any] = Depends(get_current_active_user) -): - """Einen bestimmten Agenten abrufen""" - mandate_id, user_id = await get_user_context(current_user) - - # LucyDOM-Interface mit Benutzerkontext initialisieren - lucy_interface = get_lucydom_interface(mandate_id, user_id) - - agent = lucy_interface.get_agent(agent_id) - if not agent: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=f"Agent mit ID {agent_id} nicht gefunden" - ) - return agent - - -@router.put("/{agent_id}", response_model=Dict[str, Any]) -async def update_agent( - agent_id: int = Path(..., description="ID des zu aktualisierenden Agenten"), - agent_data: Dict[str, Any] = Body(..., description="Aktualisierte Agentendaten"), - current_user: Dict[str, Any] = Depends(get_current_active_user) -): - """Einen bestehenden Agenten aktualisieren""" - mandate_id, user_id = await get_user_context(current_user) - - # LucyDOM-Interface mit Benutzerkontext initialisieren - lucy_interface = get_lucydom_interface(mandate_id, user_id) - - # Überprüfen, ob der Agent existiert - existing_agent = lucy_interface.get_agent(agent_id) - if not existing_agent: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=f"Agent mit ID {agent_id} nicht gefunden" - ) - - # Wenn workspace_id im Request vorhanden ist, prüfen ob der Workspace existiert - if "workspace_id" in agent_data: - workspace_id = agent_data["workspace_id"] - workspace = lucy_interface.get_workspace(workspace_id) - if not workspace: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=f"Workspace mit ID {workspace_id} nicht gefunden für User {user_id} im Mandanten {mandate_id}" - ) - - # Agent-Daten aktualisieren - updated_agent = lucy_interface.update_agent( - agent_id=agent_id, - name=agent_data.get("name", existing_agent.get("name")), - agent_type=agent_data.get("type", existing_agent.get("type")), - workspace_id=agent_data.get("workspace_id", existing_agent.get("workspace_id")), - capabilities=agent_data.get("capabilities", existing_agent.get("capabilities")), - description=agent_data.get("description", existing_agent.get("description")) - ) - return updated_agent - -@router.delete("/{agent_id}", status_code=status.HTTP_204_NO_CONTENT) -async def delete_agent( - agent_id: int = Path(..., description="ID des zu löschenden Agenten"), - current_user: Dict[str, Any] = Depends(get_current_active_user) -): - """Einen Agenten löschen""" - mandate_id, user_id = await get_user_context(current_user) - - # LucyDOM-Interface mit Benutzerkontext initialisieren - lucy_interface = get_lucydom_interface(mandate_id, user_id) - - # Überprüfen, ob der Agent existiert - existing_agent = lucy_interface.get_agent(agent_id) - if not existing_agent: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=f"Agent mit ID {agent_id} nicht gefunden" - ) - - # Agent löschen - success = lucy_interface.delete_agent(agent_id) - if not success: - raise HTTPException( - status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail=f"Fehler beim Löschen des Agenten mit ID {agent_id}" - ) - - # Kein Inhalt zurückgeben bei erfolgreichem Löschen - return None \ No newline at end of file diff --git a/gwserver/routes/attributes.py b/gwserver/routes/attributes.py index 8f07aace..14cb4ffa 100644 --- a/gwserver/routes/attributes.py +++ b/gwserver/routes/attributes.py @@ -12,20 +12,25 @@ from attributes_def import AttributeDefinition, get_model_attributes import modules.gateway_model as gateway_model import modules.lucydom_model as lucydom_model -# Erstelle ein Dictionary, das die Modellklassen ihren Typen zuordnet model_classes = { - "workspace": lucydom_model.Workspace, - "agent": lucydom_model.Agent, - "file": lucydom_model.DataObject, - "prompt": lucydom_model.Prompt, - "user": gateway_model.User, + # Gateway model classes "mandate": gateway_model.Mandate, - "workflow_request": lucydom_model.WorkflowRequest, - "workflow_response": lucydom_model.WorkflowResponse, - "log_entry": lucydom_model.LogEntry, - "result": lucydom_model.Result + "user": gateway_model.User, + + # LucyDOM model classes + "file": lucydom_model.FileItem, + "prompt": lucydom_model.Prompt, + "document_source": lucydom_model.DocumentSource, + "document_content": lucydom_model.DocumentContent, + "document": lucydom_model.Document, + "data_stats": lucydom_model.DataStats, + "message": lucydom_model.Message, + "workflow": lucydom_model.Workflow, + "workflow_create_request": lucydom_model.WorkflowCreateRequest, + "user_input_request": lucydom_model.UserInputRequest } + # Erstelle einen Router für die Attribute-Endpunkte router = APIRouter( prefix="/api/attributes", @@ -35,7 +40,7 @@ router = APIRouter( @router.get("/{entity_type}", response_model=List[AttributeDefinition]) async def get_entity_attributes( - entity_type: str = Path(..., description="Typ der Entität (z.B. workspace, agent, prompt)"), + entity_type: str = Path(..., description="Typ der Entität (z.B. prompt)"), current_user: Dict[str, Any] = Depends(get_current_active_user) ): """ @@ -62,48 +67,9 @@ async def get_entity_attributes( # Nur bearbeitbare und sichtbare Attribute zurückgeben visible_attributes = [attr for attr in attributes if attr.visible] - # Wenn es sich um die Workspace-Auswahl handelt, Daten aus der Datenbank laden - for attr in visible_attributes: - if attr.name == "workspace_id" and attr.type == "select": - # LucyDOM-Interface mit Benutzerkontext initialisieren - from modules.lucydom_interface import get_lucydom_interface - lucy_interface = get_lucydom_interface(mandate_id, user_id) - - # Alle verfügbaren Workspaces abrufen - workspaces = lucy_interface.get_all_workspaces() - - # Options-Liste aus Workspaces erstellen - attr.options = [ - {"value": ws["id"], "label": ws["name"]} - for ws in workspaces - ] - - # Wenn es sich um Agent-Auswahl handelt und ein Workspace-Kontext existiert - elif attr.name == "agent_id" and attr.type == "select" and "workspace_id" in [a.name for a in visible_attributes]: - # Wenn ein aktueller Workspace gesetzt ist - workspace_id_attr = next((a for a in visible_attributes if a.name == "workspace_id"), None) - if workspace_id_attr and workspace_id_attr.default_value: - workspace_id = workspace_id_attr.default_value - - # LucyDOM-Interface mit Benutzerkontext initialisieren - from modules.lucydom_interface import get_lucydom_interface - lucy_interface = get_lucydom_interface(mandate_id, user_id) - - # Agenten für den Workspace abrufen - agents = lucy_interface.get_agents_by_workspace(workspace_id) - - # Options-Liste aus Agenten erstellen - attr.options = [ - {"value": agent["id"], "label": agent["name"]} - for agent in agents - ] - - return visible_attributes - - @router.options("/{entity_type}") async def options_entity_attributes( - entity_type: str = Path(..., description="Typ der Entität (z.B. workspace, agent, prompt)") + entity_type: str = Path(..., description="Typ der Entität (z.B. prompt)") ): return Response(status_code=200) diff --git a/gwserver/routes/files.py b/gwserver/routes/files.py index f8e05574..f3ee0e9a 100644 --- a/gwserver/routes/files.py +++ b/gwserver/routes/files.py @@ -1,132 +1,340 @@ -from fastapi import APIRouter, HTTPException, Depends, File, UploadFile, Path -from typing import List, Dict, Any -from fastapi import status -import uuid -import os +from fastapi import APIRouter, HTTPException, Depends, File, UploadFile, Form, Path, Request, status, Query, Response +from fastapi.responses import FileResponse, JSONResponse +from typing import List, Dict, Any, Optional import logging +from datetime import datetime # Import auth module from auth import get_current_active_user, get_user_context # Import interfaces -from modules.lucydom_interface import get_lucydom_interface -from modules.agentservice_interface import get_agentservice_interface +from modules.lucydom_interface import get_lucydom_interface, FileError, FileNotFoundError, FileStorageError, FilePermissionError, FileDeletionError +from modules.lucydom_model import FileItem # Logger konfigurieren logger = logging.getLogger(__name__) +# Alle Attribute des Models ermitteln (außer interne/spezielle Attribute) +def get_model_attributes(model_class): + return [attr for attr in dir(model_class) + if not callable(getattr(model_class, attr)) + and not attr.startswith('_') + and attr != 'metadata' + and attr != 'query' + and attr != 'query_class' + and attr != 'label' + and attr != 'field_labels'] + +# Modell-Attribute für FileItem +file_attributes = get_model_attributes(FileItem) + # Router für Datei-Endpunkte erstellen router = APIRouter( prefix="/api/files", tags=["Files"], - responses={404: {"description": "Not found"}} + responses={ + 404: {"description": "Not found"}, + 400: {"description": "Bad request"}, + 401: {"description": "Unauthorized"}, + 403: {"description": "Forbidden"}, + 500: {"description": "Internal server error"} + } ) @router.get("", response_model=List[Dict[str, Any]]) async def get_files(current_user: Dict[str, Any] = Depends(get_current_active_user)): """Alle verfügbaren Dateien abrufen""" - mandate_id, user_id = await get_user_context(current_user) - - # LucyDOM-Interface mit Benutzerkontext initialisieren - lucy_interface = get_lucydom_interface(mandate_id, user_id) - - return lucy_interface.get_all_files() - - -@router.post("/upload") -async def upload_file( - file: UploadFile = File(...), - current_user: Dict[str, Any] = Depends(get_current_active_user) -): - """Eine Datei hochladen""" - mandate_id, user_id = await get_user_context(current_user) - - # LucyDOM-Interface mit Benutzerkontext initialisieren - lucy_interface = get_lucydom_interface(mandate_id, user_id) - try: - # Generiere eine eindeutige ID für die Datei - file_id = str(uuid.uuid4()) - file_ext = os.path.splitext(file.filename)[1] - file_path = os.path.join(get_agentservice_interface(mandate_id, user_id).upload_dir, f"{file_id}{file_ext}") + mandate_id, user_id = await get_user_context(current_user) - # Datei speichern - with open(file_path, "wb") as f: - content = await file.read() - f.write(content) - - # Dateityp bestimmen - file_type = "image" if file.content_type and "image" in file.content_type else "document" + # LucyDOM-Interface mit Benutzerkontext initialisieren + lucy_interface = get_lucydom_interface(mandate_id, user_id) - # In Datenbank speichern - new_file = lucy_interface.create_file( - name=file.filename, - file_type=file_type, - content_type=file.content_type, - size=os.path.getsize(file_path), - path=file_path - ) - - return { - "id": new_file["id"], - "name": new_file["name"], - "type": new_file["type"], - "size": f"{new_file['size'] / (1024 * 1024):.1f} MB", - "upload_date": new_file.get("upload_date") - } - + # Alle Dateien generisch abrufen + files = lucy_interface.get_all_files() + return files except Exception as e: - logger.error(f"Fehler beim Hochladen der Datei: {e}") + logger.error(f"Fehler beim Abrufen der Dateien: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail=f"Fehler beim Hochladen der Datei: {str(e)}" + detail=f"Fehler beim Abrufen der Dateien: {str(e)}" ) -@router.delete("/{file_id}") -async def delete_file( - file_id: int, +@router.post("/upload", status_code=status.HTTP_201_CREATED) +async def upload_file( + file: UploadFile = File(...), + workflow_id: Optional[str] = Form(None), current_user: Dict[str, Any] = Depends(get_current_active_user) ): - """Löscht eine Datei""" - mandate_id, user_id = await get_user_context(current_user) - - # LucyDOM-Interface mit Benutzerkontext initialisieren - lucy_interface = get_lucydom_interface(mandate_id, user_id) - + """ + Upload einer Datei für Workflows oder allgemeine Nutzung. + """ try: - # Hole die Datei aus der Datenbank - file = lucy_interface.get_file(file_id) - if not file: + # Kontext-Informationen extrahieren + mandate_id, user_id = await get_user_context(current_user) + + # LucyDOM-Interface mit Kontext holen + lucydom = get_lucydom_interface(mandate_id, user_id) + + # Datei einlesen + file_content = await file.read() + + # Größenbeschränkung prüfen (z.B. 50MB) + max_size = 50 * 1024 * 1024 # 50MB in Bytes + if len(file_content) > max_size: raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=f"Datei mit ID {file_id} nicht gefunden" + status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE, + detail=f"Datei zu groß. Maximale Größe: 50MB" ) - # Prüfe, ob die physische Datei existiert - if "path" in file and os.path.exists(file["path"]): - try: - # Versuche, die physische Datei zu löschen - os.remove(file["path"]) - except Exception as e: - logger.warning(f"Konnte physische Datei nicht löschen: {e}") + # Datei über das LucyDOM-Interface speichern + file_meta = lucydom.save_uploaded_file(file_content, file.filename) - # Lösche die Datei aus der Datenbank - success = lucy_interface.delete_file(file_id) + # Wenn workflow_id angegeben, aktualisiere die Dateiinformationen + if workflow_id: + update_data = {"workflow_id": workflow_id} + lucydom.update_file(file_meta["id"], update_data) + file_meta["workflow_id"] = workflow_id - if not success: - raise HTTPException( - status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail="Fehler beim Löschen der Datei aus der Datenbank" - ) + # Erfolgreiche Antwort + return file_meta - return {"success": True, "message": f"Datei '{file.get('name', 'unbekannt')}' wurde gelöscht"} - - except HTTPException: - raise + except FileStorageError as e: + logger.error(f"Fehler beim Datei-Upload (Speichern): {str(e)}") + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=str(e) + ) except Exception as e: - logger.error(f"Fehler beim Löschen der Datei: {e}") + logger.error(f"Fehler beim Datei-Upload: {str(e)}") + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Fehler beim Datei-Upload: {str(e)}" + ) + + +@router.get("/{file_id}") +async def get_file( + file_id: str, + current_user: Dict[str, Any] = Depends(get_current_active_user) +): + """ + Gibt eine Datei anhand ihrer ID zurück. + """ + try: + # Kontext-Informationen extrahieren + mandate_id, user_id = await get_user_context(current_user) + + # LucyDOM-Interface mit Kontext holen + lucydom = get_lucydom_interface(mandate_id, user_id) + + # Datei über das LucyDOM-Interface abrufen + file_data = lucydom.download_file(file_id) + + # Datei zurückgeben + if "path" in file_data and file_data["path"]: + # FileResponse verwenden, wenn ein Pfad vorhanden ist (effizienteres Streaming) + return FileResponse( + path=file_data["path"], + media_type=file_data["content_type"], + filename=file_data["name"] + ) + else: + # Response mit Binärdaten, wenn kein Pfad vorhanden ist + headers = { + "Content-Disposition": f'attachment; filename="{file_data["name"]}"' + } + return Response( + content=file_data["content"], + media_type=file_data["content_type"], + headers=headers + ) + + except FileNotFoundError as e: + logger.warning(f"Datei nicht gefunden: {str(e)}") + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=str(e) + ) + except FilePermissionError as e: + logger.warning(f"Keine Berechtigung für Datei: {str(e)}") + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=str(e) + ) + except FileError as e: + logger.error(f"Fehler beim Abrufen der Datei: {str(e)}") + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=str(e) + ) + except Exception as e: + logger.error(f"Unerwarteter Fehler beim Abrufen der Datei: {str(e)}") + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Fehler beim Abrufen der Datei: {str(e)}" + ) + + +@router.delete("/{file_id}", status_code=status.HTTP_204_NO_CONTENT) +async def delete_file( + file_id: str, + current_user: Dict[str, Any] = Depends(get_current_active_user) +): + """ + Löscht eine Datei anhand ihrer ID. + """ + try: + # Kontext-Informationen extrahieren + mandate_id, user_id = await get_user_context(current_user) + + # LucyDOM-Interface mit Kontext holen + lucydom = get_lucydom_interface(mandate_id, user_id) + + # Datei über das LucyDOM-Interface löschen + lucydom.delete_file(file_id) + + # Erfolgreiche Löschung ohne Inhalt zurückgeben (204 No Content) + return Response(status_code=status.HTTP_204_NO_CONTENT) + + except FileNotFoundError as e: + logger.warning(f"Datei nicht gefunden: {str(e)}") + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=str(e) + ) + except FilePermissionError as e: + logger.warning(f"Keine Berechtigung zum Löschen der Datei: {str(e)}") + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=str(e) + ) + except FileDeletionError as e: + logger.error(f"Fehler beim Löschen der Datei: {str(e)}") + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=str(e) + ) + except Exception as e: + logger.error(f"Unerwarteter Fehler beim Löschen der Datei: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Fehler beim Löschen der Datei: {str(e)}" + ) + + +@router.get("/cleanup/orphaned", response_model=Dict[str, Any]) +async def cleanup_orphaned_files( + current_user: Dict[str, Any] = Depends(get_current_active_user) +): + """ + Bereinigt verwaiste Dateien, die physisch existieren aber keine Einträge in der Datenbank haben. + Nur für Administratoren. + """ + try: + # Kontext-Informationen extrahieren + mandate_id, user_id = await get_user_context(current_user) + + # Prüfen, ob der Benutzer Admin-Rechte hat + # TODO: Implementieren einer richtigen Admin-Rechteverwaltung + if user_id != 1: # Temporäre einfache Lösung + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail="Nur Administratoren können diese Funktion ausführen" + ) + + # LucyDOM-Interface mit Kontext holen + lucydom = get_lucydom_interface(mandate_id, user_id) + + # Verwaiste Dateien bereinigen + lucydom.cleanup_orphaned_files() + + # Temporäre Dateien bereinigen + lucydom.cleanup_temp_files() + + return {"status": "success", "message": "Bereinigung abgeschlossen"} + + except Exception as e: + logger.error(f"Fehler bei der Datei-Bereinigung: {str(e)}") + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Fehler bei der Datei-Bereinigung: {str(e)}" + ) + + +@router.get("/temp/cleanup", response_model=Dict[str, Any]) +async def cleanup_temp_files( + max_age_hours: int = Query(24, ge=1, le=168), + current_user: Dict[str, Any] = Depends(get_current_active_user) +): + """ + Bereinigt temporäre Dateien, die älter als die angegebene Zeit sind. + + Args: + max_age_hours: Maximales Alter der temporären Dateien in Stunden (1-168) + """ + try: + # Kontext-Informationen extrahieren + mandate_id, user_id = await get_user_context(current_user) + + # LucyDOM-Interface mit Kontext holen + lucydom = get_lucydom_interface(mandate_id, user_id) + + # Temporäre Dateien bereinigen + lucydom.cleanup_temp_files(max_age_hours) + + return { + "status": "success", + "message": f"Temporäre Dateien älter als {max_age_hours} Stunden wurden bereinigt" + } + + except Exception as e: + logger.error(f"Fehler bei der Bereinigung temporärer Dateien: {str(e)}") + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Fehler bei der Bereinigung temporärer Dateien: {str(e)}" + ) + + +@router.get("/stats", response_model=Dict[str, Any]) +async def get_file_stats( + current_user: Dict[str, Any] = Depends(get_current_active_user) +): + """ + Gibt Statistiken über die gespeicherten Dateien zurück. + """ + try: + # Kontext-Informationen extrahieren + mandate_id, user_id = await get_user_context(current_user) + + # LucyDOM-Interface mit Kontext holen + lucydom = get_lucydom_interface(mandate_id, user_id) + + # Alle Dateien abrufen + all_files = lucydom.get_all_files() + + # Statistiken berechnen + total_files = len(all_files) + total_size = sum(file.get("size", 0) for file in all_files) + + # Nach Dateityp gruppieren + file_types = {} + for file in all_files: + file_type = file.get("type", "unknown") + if file_type not in file_types: + file_types[file_type] = 0 + file_types[file_type] += 1 + + return { + "total_files": total_files, + "total_size_bytes": total_size, + "file_types": file_types + } + + except Exception as e: + logger.error(f"Fehler beim Abrufen der Datei-Statistiken: {str(e)}") + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Fehler beim Abrufen der Datei-Statistiken: {str(e)}" ) \ No newline at end of file diff --git a/gwserver/routes/mandates.py b/gwserver/routes/mandates.py index a6e51832..c7728207 100644 --- a/gwserver/routes/mandates.py +++ b/gwserver/routes/mandates.py @@ -1,12 +1,28 @@ from fastapi import APIRouter, HTTPException, Depends, Body, Path from typing import List, Dict, Any from fastapi import status +from datetime import datetime # Import auth module from auth import get_current_active_user, get_user_context # Import interfaces from modules.gateway_interface import get_gateway_interface +from modules.gateway_model import Mandate + +# Alle Attribute des Models ermitteln (außer interne/spezielle Attribute) +def get_model_attributes(model_class): + return [attr for attr in dir(model_class) + if not callable(getattr(model_class, attr)) + and not attr.startswith('_') + and attr != 'metadata' + and attr != 'query' + and attr != 'query_class' + and attr != 'label' + and attr != 'field_labels'] + +# Modell-Attribute für Mandate +mandate_attributes = get_model_attributes(Mandate) # Router für Mandanten-Endpunkte erstellen router = APIRouter( @@ -30,6 +46,7 @@ async def get_mandates(current_user: Dict[str, Any] = Depends(get_current_active detail="Nur System-Administratoren können alle Mandanten abrufen" ) + # Mandanten generisch abrufen return gateway.get_all_mandates() @@ -51,10 +68,20 @@ async def create_mandate( detail="Nur System-Administratoren können Mandanten erstellen" ) - new_mandate = gateway.create_mandate( - name=mandate.get("name", "Neuer Mandant"), - language=mandate.get("language", "de") - ) + # Attribute aus dem Request dynamisch setzen + mandate_data = {} + for attr in mandate_attributes: + if attr in mandate: + mandate_data[attr] = mandate[attr] + + # Standardwerte für fehlende Felder + if "name" not in mandate_data: + mandate_data["name"] = "Neuer Mandant" + if "language" not in mandate_data: + mandate_data["language"] = "de" + + # Mandant erstellen + new_mandate = gateway.create_mandate(**mandate_data) return new_mandate @@ -82,6 +109,7 @@ async def get_mandate( detail="Keine Berechtigung zum Abrufen dieses Mandanten" ) + # Mandant generisch abrufen mandate = gateway.get_mandate(mandate_id) if not mandate: raise HTTPException( @@ -122,10 +150,16 @@ async def update_mandate( detail="Keine Berechtigung zum Aktualisieren dieses Mandanten" ) + # Attribute aus dem Request dynamisch in update_data filtern + update_data = {} + for attr in mandate_attributes: + if attr in mandate_data: + update_data[attr] = mandate_data[attr] + # Mandant aktualisieren updated_mandate = gateway.update_mandate( mandate_id=mandate_id, - mandate_data=mandate_data + mandate_data=update_data ) return updated_mandate diff --git a/gwserver/routes/prompts.py b/gwserver/routes/prompts.py index fadd5002..cf6eb1e0 100644 --- a/gwserver/routes/prompts.py +++ b/gwserver/routes/prompts.py @@ -1,12 +1,28 @@ from fastapi import APIRouter, HTTPException, Depends, Body, Query, Path from typing import List, Dict, Any, Optional from fastapi import status +from datetime import datetime # Import auth module from auth import get_current_active_user, get_user_context # Import interfaces from modules.lucydom_interface import get_lucydom_interface +from modules.lucydom_model import Prompt + +# Alle Attribute des Models ermitteln (außer interne/spezielle Attribute) +def get_model_attributes(model_class): + return [attr for attr in dir(model_class) + if not callable(getattr(model_class, attr)) + and not attr.startswith('_') + and attr != 'metadata' + and attr != 'query' + and attr != 'query_class' + and attr != 'label' + and attr != 'field_labels'] + +# Modell-Attribute für Prompt +prompt_attributes = get_model_attributes(Prompt) # Router für Prompt-Endpunkte erstellen router = APIRouter( @@ -17,18 +33,15 @@ router = APIRouter( @router.get("", response_model=List[Dict[str, Any]]) async def get_prompts( - workspace_id: Optional[int] = Query(None), current_user: Dict[str, Any] = Depends(get_current_active_user) ): - """Alle Prompts oder Prompts eines bestimmten Workspaces abrufen""" + """Alle Prompts abrufen""" mandate_id, user_id = await get_user_context(current_user) # LucyDOM-Interface mit Benutzerkontext initialisieren lucy_interface = get_lucydom_interface(mandate_id, user_id) - if workspace_id: - return lucy_interface.get_prompts_by_workspace(workspace_id) - + # Prompts generisch abrufen return lucy_interface.get_all_prompts() @@ -43,27 +56,26 @@ async def create_prompt( # LucyDOM-Interface mit Benutzerkontext initialisieren lucy_interface = get_lucydom_interface(mandate_id, user_id) - workspace_id = prompt.get("workspace_id") + # Attribute aus dem Request dynamisch setzen + prompt_data = {} + for attr in prompt_attributes: + if attr in prompt: + prompt_data[attr] = prompt[attr] - if not workspace_id: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail="workspace_id ist erforderlich" - ) - - # Workspace existiert? - workspace = lucy_interface.get_workspace(workspace_id) - if not workspace: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=f"Workspace mit ID {workspace_id} nicht gefunden" - ) + # Pflichtfelder mit Standardwerten + content = prompt.get("content", "") + name = prompt.get("name", "Neuer Prompt") + # Prompt erstellen new_prompt = lucy_interface.create_prompt( - content=prompt.get("content", ""), - workspace_id=workspace_id + content=content, + name=name ) + # Aktuelle Zeit für created_at setzen, wenn es im Modell existiert + if "created_at" in prompt_attributes and hasattr(new_prompt, "created_at"): + new_prompt["created_at"] = datetime.now().isoformat() + return new_prompt @@ -78,6 +90,7 @@ async def get_prompt( # LucyDOM-Interface mit Benutzerkontext initialisieren lucy_interface = get_lucydom_interface(mandate_id, user_id) + # Prompt generisch abrufen prompt = lucy_interface.get_prompt(prompt_id) if not prompt: raise HTTPException( @@ -108,20 +121,21 @@ async def update_prompt( detail=f"Prompt mit ID {prompt_id} nicht gefunden" ) - # Wenn workspace_id vorhanden ist, prüfe, ob der Workspace existiert - workspace_id = prompt_data.get("workspace_id") - if workspace_id: - workspace = lucy_interface.get_workspace(workspace_id) - if not workspace: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=f"Workspace mit ID {workspace_id} nicht gefunden" - ) + # Attribute aus dem Request dynamisch filtern + update_data = {} + for attr in prompt_attributes: + if attr in prompt_data: + update_data[attr] = prompt_data[attr] + # Standardfelder für Update + content = prompt_data.get("content") + name = prompt_data.get("name") + + # Prompt aktualisieren updated_prompt = lucy_interface.update_prompt( prompt_id=prompt_id, - content=prompt_data.get("content"), - workspace_id=workspace_id + content=content, + name=name ) if not updated_prompt: diff --git a/gwserver/routes/users.py b/gwserver/routes/users.py index 7199ba8a..55e57d45 100644 --- a/gwserver/routes/users.py +++ b/gwserver/routes/users.py @@ -1,12 +1,28 @@ from fastapi import APIRouter, HTTPException, Depends, Body, Path from typing import List, Dict, Any, Optional from fastapi import status +from datetime import datetime # Import auth module from auth import get_current_active_user, get_user_context # Import interfaces from modules.gateway_interface import get_gateway_interface +from modules.gateway_model import User + +# Alle Attribute des Models ermitteln (außer interne/spezielle Attribute) +def get_model_attributes(model_class): + return [attr for attr in dir(model_class) + if not callable(getattr(model_class, attr)) + and not attr.startswith('_') + and attr != 'metadata' + and attr != 'query' + and attr != 'query_class' + and attr != 'label' + and attr != 'field_labels'] + +# Modell-Attribute für User +user_attributes = get_model_attributes(User) # Router für Benutzer-Endpunkte erstellen router = APIRouter( @@ -46,21 +62,34 @@ async def register_user(user_data: dict = Body(...)): raise HTTPException(status_code=400, detail="Benutzername und Passwort erforderlich") try: - new_mandate = gateway.create_mandate( - name=f"Mandant von {user_data['username']}", - language=user_data.get("language", "de") - ) + # Attribute dynamisch filtern + mandate_data = { + "name": f"Mandant von {user_data['username']}", + "language": user_data.get("language", "de") + } - new_user = gateway.create_user( - username=user_data["username"], - password=user_data["password"], - email=user_data.get("email"), - full_name=user_data.get("full_name"), - language=user_data.get("language", "de"), - mandate_id=new_mandate["id"], - disabled=False, - privilege="user" - ) + new_mandate = gateway.create_mandate(**mandate_data) + + # User-Attribute aus dem Request filtern + user_create_data = {} + for attr in user_attributes: + if attr in user_data and attr not in ["id"]: # ID wird automatisch vergeben + user_create_data[attr] = user_data[attr] + + # Pflichtfelder + user_create_data["username"] = user_data["username"] + user_create_data["password"] = user_data["password"] + user_create_data["mandate_id"] = new_mandate["id"] + + # Standardwerte für optionale Felder + if "disabled" not in user_create_data: + user_create_data["disabled"] = False + if "privilege" not in user_create_data: + user_create_data["privilege"] = "user" + if "language" not in user_create_data: + user_create_data["language"] = "de" + + new_user = gateway.create_user(**user_create_data) return new_user except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) @@ -154,12 +183,18 @@ async def update_user( detail="Keine Berechtigung zum Aktualisieren dieses Benutzers" ) + # Attribute aus dem Request dynamisch filtern + update_data = {} + for attr in user_attributes: + if attr in user_data and attr not in ["id"]: # ID kann nicht geändert werden + update_data[attr] = user_data[attr] + # Entferne nicht erlaubte Felder für normale Benutzer if not (is_admin or is_sysadmin): - user_data = {k: v for k, v in user_data.items() if k in allowed_fields} + update_data = {k: v for k, v in update_data.items() if k in allowed_fields} # User-Daten aktualisieren - updated_user = gateway.update_user(user_id, user_data) + updated_user = gateway.update_user(user_id, update_data) return updated_user @router.delete("/{user_id}", status_code=status.HTTP_204_NO_CONTENT) diff --git a/gwserver/routes/workflows.py b/gwserver/routes/workflows.py index 93a88b93..b154002c 100644 --- a/gwserver/routes/workflows.py +++ b/gwserver/routes/workflows.py @@ -1,19 +1,44 @@ -from fastapi import APIRouter, HTTPException, Depends, Body, Path -from typing import List, Dict, Any +import os +import json +from fastapi import APIRouter, HTTPException, Depends, Body, Path, Query +from typing import List, Dict, Any, Optional from fastapi import status import asyncio import uuid +from datetime import datetime +import logging # Import auth module from auth import get_current_active_user, get_user_context # Import interfaces from modules.lucydom_interface import get_lucydom_interface -from modules.agentservice_interface import get_agentservice_interface +from modules.agentservice_workflow_manager import get_workflow_manager + +# Import für AI-Service +from connectors.connector_aichat_openai import ChatService as OpenAIChatService +from connectors.connector_aichat_anthropic import ChatService as AnthropicChatService # Import models import modules.lucydom_model as lucydom_model +# Alle Attribute des Models ermitteln (außer interne/spezielle Attribute) +def get_model_attributes(model_class): + return [attr for attr in dir(model_class) + if not callable(getattr(model_class, attr)) + and not attr.startswith('_') + and attr != 'metadata' + and attr != 'query' + and attr != 'query_class' + and attr != 'label' + and attr != 'field_labels'] + +# Modell-Attribute für Workflow +workflow_attributes = get_model_attributes(lucydom_model.Workflow) + +# Logger konfigurieren +logger = logging.getLogger(__name__) + # Router für Workflow-Endpunkte erstellen router = APIRouter( prefix="/api/workflows", @@ -21,66 +46,121 @@ router = APIRouter( responses={404: {"description": "Not found"}} ) -@router.post("/run", response_model=Dict[str, Any]) -async def run_workflow( - workflow_request: lucydom_model.WorkflowRequest = Body(...), +# Hilfsfunktion zum Erstellen des AI-Services basierend auf der Konfiguration +def get_ai_service(mandate_id: int, user_id: int): + """Gibt den konfigurierten AI-Service zurück""" + import configload + + config = configload.load_config() + ai_provider = config.get('Module_AgentserviceInterface', 'AI_PROVIDER').lower() + if ai_provider == "anthropic": + return AnthropicChatService() + else: + return OpenAIChatService() + +@router.get("", response_model=List[Dict[str, Any]]) +async def list_workflows( current_user: Dict[str, Any] = Depends(get_current_active_user) ): - """Führt einen Workflow mit den ausgewählten Agenten und Dateien aus""" + """Listet alle Workflows des Benutzers auf""" mandate_id, user_id = await get_user_context(current_user) - # Populate the fields from user context - workflow_request.mandate_id = mandate_id - workflow_request.user_id = user_id - workflow_request.id = str(uuid.uuid4()) # Generate a unique ID + # WorkflowManager mit Benutzerkontext initialisieren + workflow_manager = get_workflow_manager(mandate_id, user_id) + + workflows = await workflow_manager.list_workflows(mandate_id, user_id) + return workflows + +@router.post("", response_model=Dict[str, Any]) +async def create_workflow( + workflow_request: lucydom_model.WorkflowCreateRequest = Body(...), + current_user: Dict[str, Any] = Depends(get_current_active_user) +): + """ + Erstellt einen neuen Workflow und führt ihn aus. + """ + mandate_id, user_id = await get_user_context(current_user) + + # Add debug logging for the workflow request + print(f"DEBUG - Creating workflow with request: {workflow_request}") + print(f"DEBUG - Files in request: {workflow_request.files}") # LucyDOM-Interface mit Benutzerkontext initialisieren lucy_interface = get_lucydom_interface(mandate_id, user_id) - # AgentService mit Benutzerkontext initialisieren - agent_service = get_agentservice_interface(mandate_id, user_id) - - workspace = lucy_interface.get_workspace(workflow_request.workspace_id) - if not workspace: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=f"Workspace mit ID {workflow_request.workspace_id} nicht gefunden" - ) - # Prüfen, ob Dateien existieren files = [] for file_id in workflow_request.files: + # Add logging before file lookup + print(f"DEBUG - Looking up file with ID: {file_id}") + file = lucy_interface.get_file(file_id) if not file: + print(f"DEBUG - File with ID {file_id} not found in database") raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Datei mit ID {file_id} nicht gefunden" ) + + # Add logging on successful file lookup + print(f"DEBUG - Found file: {file.get('name', 'unknown')} (ID: {file_id})") files.append(file) - # Prüfen, ob Agenten existieren - agents = [] - for agent_id in workflow_request.agents: - agent = lucy_interface.get_agent(agent_id) - if not agent: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=f"Agent mit ID {agent_id} nicht gefunden" - ) - agents.append(agent) - # Workflow ID generieren workflow_id = str(uuid.uuid4()) + # AI-Service erstellen + ai_service = get_ai_service(mandate_id, user_id) + + # WorkflowManager mit Benutzerkontext initialisieren + workflow_manager = get_workflow_manager(mandate_id, user_id, ai_service) + + # Grundlegende Workflow-Daten erstellen + workflow_data = { + "id": workflow_id, + "mandate_id": mandate_id, + "user_id": user_id, + "name": workflow_request.name or f"Workflow {workflow_id}", + "status": "running", + "started_at": datetime.now().isoformat(), + "last_activity": datetime.now().isoformat(), + "prompt": workflow_request.prompt + } + + # Attribute aus dem Request dynamisch setzen + for attr in workflow_attributes: + if hasattr(workflow_request, attr) and getattr(workflow_request, attr) is not None: + workflow_data[attr] = getattr(workflow_request, attr) + + # Workflow in Datenbank speichern + if lucy_interface: + try: + lucy_interface.create_workflow(workflow_data) + except Exception as e: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=f"Fehler beim Speichern des Workflows in der Datenbank: {str(e)}" + ) + + # Log files before executing workflow + print(f"DEBUG - Executing workflow with {len(files)} files:") + for file in files: + print(f"DEBUG - File: {file.get('name', 'unknown')} (ID: {file.get('id', 'unknown')})") + # Workflow starten (asynchron) workflow_task = asyncio.create_task( - agent_service.execute_workflow( - workflow_id, - workflow_request.prompt, - agents, - files + workflow_manager.execute_workflow( + message={"content": workflow_request.prompt, "role": "user"}, + workflow_id=workflow_id, + files=files ) ) + + # Workflow-Namen setzen, falls vorhanden + if workflow_request.name: + if workflow_id in workflow_manager.workflows: + workflow_manager.workflows[workflow_id]["name"] = workflow_request.name + workflow_manager._save_workflow(workflow_manager.workflows[workflow_id]) # Sofort eine Antwort zurückgeben return { @@ -90,7 +170,103 @@ async def run_workflow( } -@router.get("/{workflow_id}/status") +@router.get("/{workflow_id}", response_model=Dict[str, Any]) +async def get_workflow( + workflow_id: str, + current_user: Dict[str, Any] = Depends(get_current_active_user) +): + """ + Gibt detaillierte Informationen zu einem Workflow zurück. + """ + mandate_id, user_id = await get_user_context(current_user) + + # WorkflowManager mit Benutzerkontext initialisieren + workflow_manager = get_workflow_manager(mandate_id, user_id) + + workflow = await workflow_manager.load_workflow(workflow_id) + if not workflow: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Workflow mit ID {workflow_id} nicht gefunden" + ) + + return workflow + +@router.put("/{workflow_id}", response_model=Dict[str, Any]) +async def update_workflow( + workflow_id: str, + workflow_data: Dict[str, Any] = Body(...), + current_user: Dict[str, Any] = Depends(get_current_active_user) +): + """Aktualisiert Metadaten eines Workflows""" + mandate_id, user_id = await get_user_context(current_user) + + # WorkflowManager mit Benutzerkontext initialisieren + workflow_manager = get_workflow_manager(mandate_id, user_id) + + # Workflow laden + workflow = await workflow_manager.load_workflow(workflow_id) + if not workflow: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Workflow mit ID {workflow_id} nicht gefunden" + ) + + # LucyDOM-Interface mit Benutzerkontext initialisieren, um Datenbank zu aktualisieren + lucy_interface = get_lucydom_interface(mandate_id, user_id) + + # Attribute aus dem Request dynamisch filtern + update_data = {} + + # Zunächst alle updatebaren Attribute sammeln + for attr in workflow_attributes: + if attr in workflow_data: + update_data[attr] = workflow_data[attr] + + # Besondere Attribute (außerhalb des Models) separat behandeln + if "last_activity" not in update_data: + update_data["last_activity"] = datetime.now().isoformat() + + # Daten im Workflow aktualisieren + for key, value in update_data.items(): + workflow[key] = value + + # Workflow speichern + workflow_manager._save_workflow(workflow) + + # In Datenbank aktualisieren + if lucy_interface: + lucy_interface.update_workflow(workflow_id, update_data) + + return { + "workflow_id": workflow_id, + "message": "Workflow wurde aktualisiert" + } + +@router.delete("/{workflow_id}", response_model=Dict[str, Any]) +async def delete_workflow( + workflow_id: str, + current_user: Dict[str, Any] = Depends(get_current_active_user) +): + """Löscht einen Workflow""" + mandate_id, user_id = await get_user_context(current_user) + + # WorkflowManager mit Benutzerkontext initialisieren + workflow_manager = get_workflow_manager(mandate_id, user_id) + + success = await workflow_manager.delete_workflow(workflow_id) + if not success: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Workflow mit ID {workflow_id} nicht gefunden" + ) + + return { + "workflow_id": workflow_id, + "message": "Workflow wurde gelöscht" + } + +@router.get("/{workflow_id}/status", response_model=Dict[str, Any]) async def get_workflow_status( workflow_id: str, current_user: Dict[str, Any] = Depends(get_current_active_user) @@ -98,19 +274,24 @@ async def get_workflow_status( """Status eines laufenden Workflows abrufen""" mandate_id, user_id = await get_user_context(current_user) - # AgentService mit Benutzerkontext initialisieren - agent_service = get_agentservice_interface(mandate_id, user_id) + # WorkflowManager mit Benutzerkontext initialisieren + workflow_manager = get_workflow_manager(mandate_id, user_id) - status = agent_service.get_workflow_status(workflow_id) + status = workflow_manager.get_workflow_status(workflow_id) if not status: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=f"Workflow mit ID {workflow_id} nicht gefunden" - ) + # Versuche, den Workflow zu laden + workflow = await workflow_manager.load_workflow(workflow_id) + if not workflow: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Workflow mit ID {workflow_id} nicht gefunden" + ) + + # Status aus dem geladenen Workflow erstellen + status = workflow_manager.get_workflow_status(workflow_id) return status - @router.get("/{workflow_id}/logs", response_model=List[Dict[str, Any]]) async def get_workflow_logs( workflow_id: str, @@ -119,38 +300,49 @@ async def get_workflow_logs( """Protokolle eines Workflows abrufen""" mandate_id, user_id = await get_user_context(current_user) - # AgentService mit Benutzerkontext initialisieren - agent_service = get_agentservice_interface(mandate_id, user_id) + # WorkflowManager mit Benutzerkontext initialisieren + workflow_manager = get_workflow_manager(mandate_id, user_id) - logs = agent_service.get_workflow_logs(workflow_id) + logs = workflow_manager.get_workflow_logs(workflow_id) if logs is None: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=f"Workflow mit ID {workflow_id} nicht gefunden" - ) + # Versuche, den Workflow zu laden + workflow = await workflow_manager.load_workflow(workflow_id) + if not workflow: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Workflow mit ID {workflow_id} nicht gefunden" + ) + + # Logs aus dem geladenen Workflow + logs = workflow.get("logs", []) return logs - -@router.get("/{workflow_id}/results", response_model=List[Dict[str, Any]]) -async def get_workflow_results( +@router.get("/{workflow_id}/messages", response_model=List[Dict[str, Any]]) +async def get_workflow_messages( workflow_id: str, current_user: Dict[str, Any] = Depends(get_current_active_user) ): - """Ergebnisse eines Workflows abrufen""" + """Nachrichten eines Workflows abrufen""" mandate_id, user_id = await get_user_context(current_user) - # AgentService mit Benutzerkontext initialisieren - agent_service = get_agentservice_interface(mandate_id, user_id) + # WorkflowManager mit Benutzerkontext initialisieren + workflow_manager = get_workflow_manager(mandate_id, user_id) - results = agent_service.get_workflow_results(workflow_id) - if results is None: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=f"Workflow mit ID {workflow_id} nicht gefunden" - ) + messages = workflow_manager.get_workflow_messages(workflow_id) + if messages is None: + # Versuche, den Workflow zu laden + workflow = await workflow_manager.load_workflow(workflow_id) + if not workflow: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Workflow mit ID {workflow_id} nicht gefunden" + ) + + # Nachrichten aus dem geladenen Workflow + messages = workflow.get("messages", []) - return results + return messages @router.post("/{workflow_id}/stop", response_model=Dict[str, Any]) async def stop_workflow( @@ -160,10 +352,10 @@ async def stop_workflow( """Stoppt einen laufenden Workflow""" mandate_id, user_id = await get_user_context(current_user) - # AgentService mit Benutzerkontext initialisieren - agent_service = get_agentservice_interface(mandate_id, user_id) + # WorkflowManager mit Benutzerkontext initialisieren + workflow_manager = get_workflow_manager(mandate_id, user_id) - result = agent_service.stop_workflow(workflow_id) + result = await workflow_manager.stop_workflow(workflow_id) if not result: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, @@ -185,63 +377,104 @@ async def submit_user_input( """ Ermöglicht es dem Benutzer, Eingaben für einen laufenden Workflow zu senden. Dies wird verwendet, wenn der User-Agent im Workflow angesprochen wird. - - Der Request-Body sollte folgendes Format haben: - { - "message": "Die Antwort des Benutzers", - "additional_files": [1, 2, 3] // Optional: IDs zusätzlicher Dateien - } """ mandate_id, user_id = await get_user_context(current_user) - # Überprüfen, ob die erforderlichen Felder vorhanden sind - if "message" not in user_input: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail="Das Feld 'message' ist erforderlich" - ) - - message = user_input["message"] - additional_file_ids = user_input.get("additional_files", []) + # Improved logging + logger.info(f"User input received for workflow {workflow_id}") + logger.debug(f"Input content: {user_input.get('message', '')[:50]}...") # LucyDOM-Interface mit Benutzerkontext initialisieren lucy_interface = get_lucydom_interface(mandate_id, user_id) - # AgentService mit Benutzerkontext initialisieren - agent_service = get_agentservice_interface(mandate_id, user_id) + # Ensure message content is valid + message_content = user_input.get("message", "") + if isinstance(message_content, dict) and "content" in message_content: + message_content = message_content["content"] - # Zusätzliche Dateien einsammeln, wenn vorhanden + # If message content is None or empty, use a default value + if message_content is None or message_content.strip() == "": + logger.warning(f"Empty message received for workflow {workflow_id}, using default") + message_content = "Fortsetzung des Workflows" + + # Process additional files additional_files = [] - if additional_file_ids: - for file_id in additional_file_ids: + additional_file_ids = user_input.get("additional_files", []) + logger.info(f"Processing {len(additional_file_ids)} additional files") + + # Validate each file ID + for file_id in additional_file_ids: + try: file = lucy_interface.get_file(file_id) if not file: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=f"Zusätzliche Datei mit ID {file_id} nicht gefunden" - ) + logger.warning(f"File with ID {file_id} not found") + continue + + # Check if file belongs to the current mandate/user + if file.get("mandate_id") != mandate_id: + logger.warning(f"File {file_id} does not belong to mandate {mandate_id}") + continue + additional_files.append(file) + logger.info(f"Added file {file.get('name', 'unnamed')} (ID: {file_id})") + except Exception as e: + logger.error(f"Error processing file {file_id}: {str(e)}") + # Continue with remaining files instead of failing + continue + + # AI-Service und Web-Service erstellen + ai_service = get_ai_service(mandate_id, user_id) - # Benutzereingabe verarbeiten + # WorkflowManager mit Benutzerkontext initialisieren + workflow_manager = get_workflow_manager(mandate_id, user_id, ai_service) + + # Load and verify workflow try: - result = await agent_service.process_user_input(workflow_id, message, additional_files) - if not result: + workflow = await workflow_manager.load_workflow(workflow_id) + if not workflow: + logger.error(f"Workflow {workflow_id} not found") raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail=f"Workflow {workflow_id} wartet nicht auf Benutzereingabe oder existiert nicht" + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Workflow mit ID {workflow_id} nicht gefunden" ) + if workflow.get("status") == "running": + logger.info(f"Workflow {workflow_id} is still running but will be continued with new input") + asyncio.create_task(workflow_manager.stop_workflow(workflow_id)) + + # Create message object with proper structure + message_object = { + "content": message_content, + "role": "user" + } + + # Execute workflow with user input + logger.info(f"Executing workflow {workflow_id} with user input") + response = await workflow_manager.execute_workflow( + message=message_object, + workflow_id=workflow_id, + files=additional_files, + is_user_input=True + ) + + logger.info(f"Workflow execution completed: {response.get('status', 'unknown')}") + return { "workflow_id": workflow_id, "status": "processing", "message": "Benutzereingabe wurde empfangen und wird verarbeitet" } + except HTTPException: + # Re-raise HTTP exceptions + raise except Exception as e: + logger.error(f"Error processing user input: {str(e)}", exc_info=True) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Fehler bei der Verarbeitung der Benutzereingabe: {str(e)}" ) + @router.get("/{workflow_id}/data-statistics", response_model=Dict[str, Any]) async def get_workflow_data_statistics( workflow_id: str, @@ -252,10 +485,10 @@ async def get_workflow_data_statistics( """ mandate_id, user_id = await get_user_context(current_user) - # AgentService mit Benutzerkontext initialisieren - agent_service = get_agentservice_interface(mandate_id, user_id) + # WorkflowManager mit Benutzerkontext initialisieren + workflow_manager = get_workflow_manager(mandate_id, user_id) - status = agent_service.get_workflow_status(workflow_id) + status = workflow_manager.get_workflow_status(workflow_id) if not status: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, @@ -272,7 +505,425 @@ async def get_workflow_data_statistics( return { "workflow_id": workflow_id, "data_stats": { - "sent_bytes": 0, - "received_bytes": 0 + "total_processing_time": 0.0, + "total_token_count": 0, + "total_bytes_sent": 0, + "total_bytes_received": 0 } - } \ No newline at end of file + } + +@router.post("/{workflow_id}/export", response_model=Dict[str, Any]) +async def export_workflow( + workflow_id: str, + export_format: str = Query("json", description="Exportformat ('json', 'csv', 'pdf')"), + current_user: Dict[str, Any] = Depends(get_current_active_user) +): + """ + Exportiert einen Workflow in verschiedenen Formaten. + """ + mandate_id, user_id = await get_user_context(current_user) + + # WorkflowManager mit Benutzerkontext initialisieren + workflow_manager = get_workflow_manager(mandate_id, user_id) + + # Workflow laden + workflow = await workflow_manager.load_workflow(workflow_id) + if not workflow: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Workflow mit ID {workflow_id} nicht gefunden" + ) + + # Export je nach Format durchführen + export_path = None + + if export_format == "json": + # JSON-Export ist einfach der Workflow selbst + export_path = os.path.join(workflow_manager.results_dir, f"workflow_{workflow_id}_export.json") + with open(export_path, 'w', encoding='utf-8') as f: + json.dump(workflow, f, indent=2, ensure_ascii=False) + + elif export_format == "csv": + # CSV-Export der Messages und Logs + from csv import writer + + export_path = os.path.join(workflow_manager.results_dir, f"workflow_{workflow_id}_messages.csv") + with open(export_path, 'w', newline='', encoding='utf-8') as f: + csv_writer = writer(f) + # Überschriften schreiben + csv_writer.writerow(["ID", "Sequence", "Role", "Content", "Agent Type", "Created At"]) + # Messages schreiben + for msg in workflow.get("messages", []): + csv_writer.writerow([ + msg.get("id", ""), + msg.get("sequence_no", ""), + msg.get("role", ""), + msg.get("content", ""), + msg.get("agent_type", ""), + msg.get("started_at", "") + ]) + + # Logs exportieren + logs_path = os.path.join(workflow_manager.results_dir, f"workflow_{workflow_id}_logs.csv") + with open(logs_path, 'w', newline='', encoding='utf-8') as f: + csv_writer = writer(f) + # Überschriften schreiben + csv_writer.writerow(["ID", "Type", "Message", "Timestamp", "Agent ID", "Agent Name"]) + # Logs schreiben + for log in workflow.get("logs", []): + csv_writer.writerow([ + log.get("id", ""), + log.get("type", ""), + log.get("message", ""), + log.get("timestamp", ""), + log.get("agent_id", ""), + log.get("agent_name", "") + ]) + + export_path = [export_path, logs_path] # Beide Dateien zurückgeben + + elif export_format == "pdf": + # PDF-Export erfordert zusätzliche Bibliotheken (z.B. reportlab) + try: + from reportlab.lib.pagesizes import letter + from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle + from reportlab.lib.styles import getSampleStyleSheet + + export_path = os.path.join(workflow_manager.results_dir, f"workflow_{workflow_id}_export.pdf") + + doc = SimpleDocTemplate(export_path, pagesize=letter) + styles = getSampleStyleSheet() + elements = [] + + # Titel + elements.append(Paragraph(f"Workflow: {workflow.get('name', workflow_id)}", styles['Title'])) + elements.append(Spacer(1, 12)) + + # Workflow-Info + elements.append(Paragraph("Workflow Information", styles['Heading2'])) + elements.append(Paragraph(f"ID: {workflow_id}", styles['Normal'])) + elements.append(Paragraph(f"Status: {workflow.get('status', 'unknown')}", styles['Normal'])) + elements.append(Paragraph(f"Started: {workflow.get('started_at', '')}", styles['Normal'])) + if workflow.get('completed_at'): + elements.append(Paragraph(f"Completed: {workflow.get('completed_at')}", styles['Normal'])) + elements.append(Spacer(1, 12)) + + # Messages + elements.append(Paragraph("Messages", styles['Heading2'])) + + # Tabelle für Messages + message_data = [["Sequence", "Role", "Agent Type", "Content"]] + for msg in sorted(workflow.get("messages", []), key=lambda x: x.get("sequence_no", 0)): + content = msg.get("content", "") + if len(content) > 500: # Zu lange Inhalte kürzen + content = content[:500] + "..." + message_data.append([ + str(msg.get("sequence_no", "")), + msg.get("role", ""), + msg.get("agent_type", ""), + content + ]) + + if len(message_data) > 1: # Nur wenn Messages vorhanden sind + table = Table(message_data, colWidths=[40, 70, 70, 350]) + table.setStyle(TableStyle([ + ('BACKGROUND', (0, 0), (-1, 0), (0.9, 0.9, 0.9)), + ('TEXTCOLOR', (0, 0), (-1, 0), (0, 0, 0)), + ('ALIGN', (0, 0), (-1, -1), 'LEFT'), + ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'), + ('BOTTOMPADDING', (0, 0), (-1, 0), 12), + ('BACKGROUND', (0, 1), (-1, -1), (0.95, 0.95, 0.95)), + ('GRID', (0, 0), (-1, -1), 1, (0.5, 0.5, 0.5)) + ])) + elements.append(table) + else: + elements.append(Paragraph("No messages found", styles['Normal'])) + + elements.append(Spacer(1, 12)) + + # Logs + elements.append(Paragraph("Logs", styles['Heading2'])) + + # Tabelle für Logs + log_data = [["Type", "Timestamp", "Agent", "Message"]] + for log in sorted(workflow.get("logs", []), key=lambda x: x.get("timestamp", "")): + log_data.append([ + log.get("type", ""), + log.get("timestamp", ""), + log.get("agent_name", ""), + log.get("message", "") + ]) + + if len(log_data) > 1: # Nur wenn Logs vorhanden sind + table = Table(log_data, colWidths=[60, 120, 80, 270]) + table.setStyle(TableStyle([ + ('BACKGROUND', (0, 0), (-1, 0), (0.9, 0.9, 0.9)), + ('TEXTCOLOR', (0, 0), (-1, 0), (0, 0, 0)), + ('ALIGN', (0, 0), (-1, -1), 'LEFT'), + ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'), + ('BOTTOMPADDING', (0, 0), (-1, 0), 12), + ('BACKGROUND', (0, 1), (-1, -1), (0.95, 0.95, 0.95)), + ('GRID', (0, 0), (-1, -1), 1, (0.5, 0.5, 0.5)) + ])) + elements.append(table) + else: + elements.append(Paragraph("No logs found", styles['Normal'])) + + # PDF generieren + doc.build(elements) + + except ImportError: + raise HTTPException( + status_code=status.HTTP_501_NOT_IMPLEMENTED, + detail="PDF-Export nicht verfügbar (reportlab nicht installiert)" + ) + + else: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=f"Unbekanntes Exportformat: {export_format}" + ) + + if not export_path: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail="Export konnte nicht durchgeführt werden" + ) + + # Pfad(e) im Ergebnis zurückgeben + export_result = { + "workflow_id": workflow_id, + "format": export_format, + "path": export_path + } + + return export_result + +@router.delete("/{workflow_id}/messages/{message_id}", response_model=Dict[str, Any]) +async def delete_workflow_message( + workflow_id: str = Path(..., description="ID des Workflows"), + message_id: str = Path(..., description="ID der zu löschenden Nachricht"), + current_user: Dict[str, Any] = Depends(get_current_active_user) +): + """ + Löscht eine einzelne Nachricht aus einem Workflow. + + Diese Funktion entfernt die Nachricht aus dem Workflow und auch aus der Datenbank. + """ + mandate_id, user_id = await get_user_context(current_user) + + # WorkflowManager mit Benutzerkontext initialisieren + workflow_manager = get_workflow_manager(mandate_id, user_id) + + try: + # Workflow laden + workflow = await workflow_manager.load_workflow(workflow_id) + if not workflow: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Workflow mit ID {workflow_id} nicht gefunden" + ) + + # Prüfen, ob die Nachricht im Workflow vorhanden ist + if "messages" not in workflow: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Keine Nachrichten im Workflow {workflow_id} gefunden" + ) + + # Nachricht finden + message_index = next((i for i, m in enumerate(workflow["messages"]) + if m.get("id") == message_id), -1) + + if message_index == -1: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Nachricht mit ID {message_id} im Workflow {workflow_id} nicht gefunden" + ) + + # Nachricht aus dem Workflow entfernen + deleted_message = workflow["messages"].pop(message_index) + + # Log über Löschung hinzufügen + workflow_manager._add_log( + workflow, + f"Nachricht gelöscht: {deleted_message.get('role', 'unknown')} - {message_id[:8]}...", + "info" + ) + + # Workflow speichern + workflow_manager._save_workflow(workflow) + + # Bei aktivem LucyDOM-Interface auch dort löschen + if workflow_manager.lucydom_interface: + try: + # Diese Methode muss im LucyDOM-Interface implementiert werden + workflow_manager.lucydom_interface.delete_workflow_message(workflow_id, message_id) + except Exception as e: + # Fehler beim Löschen in der Datenbank loggen, aber nicht scheitern lassen + print(f"Warnung: Nachricht aus Workflow entfernt, aber Fehler beim Löschen aus der Datenbank: {str(e)}") + + return { + "workflow_id": workflow_id, + "message_id": message_id, + "success": True, + "message": "Nachricht erfolgreich gelöscht" + } + + except HTTPException: + # Bekannte HTTP-Exceptions weiterleiten + raise + except Exception as e: + # Sonstige Fehler abfangen + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Fehler beim Löschen der Nachricht: {str(e)}" + ) + + +@router.delete("/{workflow_id}/messages/{message_id}/files/{file_id}", response_model=Dict[str, Any]) +async def delete_file_from_message( + workflow_id: str = Path(..., description="ID des Workflows"), + message_id: str = Path(..., description="ID der Nachricht"), + file_id: str = Path(..., description="ID der zu löschenden Datei"), + current_user: Dict[str, Any] = Depends(get_current_active_user) +): + """ + Löscht eine einzelne Datei aus einer Nachricht im Workflow. + """ + mandate_id, user_id = await get_user_context(current_user) + + # Add detailed logging + print(f"DELETE request: Remove file {file_id} from message {message_id} in workflow {workflow_id}") + + # WorkflowManager mit Benutzerkontext initialisieren + workflow_manager = get_workflow_manager(mandate_id, user_id) + + try: + # Workflow laden + workflow = await workflow_manager.load_workflow(workflow_id) + if not workflow: + print(f"Workflow {workflow_id} not found") + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Workflow mit ID {workflow_id} nicht gefunden" + ) + + # Log workflow info + print(f"Workflow found: {workflow.get('name', workflow_id)}") + + # Print message structure to debug + if "messages" in workflow: + print(f"Workflow has {len(workflow['messages'])} messages") + for i, msg in enumerate(workflow['messages']): + print(f"Message {i+1}: ID={msg.get('id')}, Type={msg.get('agent_type')}") + + # Nachricht finden - try different approaches + message = None + + # First try exact match + message = next((m for m in workflow.get("messages", []) if m.get("id") == message_id), None) + + # If not found, try case-insensitive match + if not message and isinstance(message_id, str): + message = next((m for m in workflow.get("messages", []) + if isinstance(m.get("id"), str) and m.get("id").lower() == message_id.lower()), None) + + # If still not found, try partial match with the beginning of ID + if not message and isinstance(message_id, str): + message = next((m for m in workflow.get("messages", []) + if isinstance(m.get("id"), str) and m.get("id").startswith(message_id)), None) + + if not message: + print(f"Message {message_id} not found in workflow {workflow_id}") + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Nachricht mit ID {message_id} im Workflow {workflow_id} nicht gefunden" + ) + + # Log message info + print(f"Message found: {message.get('id')}, type: {message.get('agent_type')}") + + # Check documents array + if "documents" not in message or not message["documents"]: + print(f"No documents in message {message_id}") + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Keine Dateien in der Nachricht {message_id} gefunden" + ) + + # Debug log documents + print(f"Message has {len(message['documents'])} documents") + for i, doc in enumerate(message["documents"]): + source = doc.get("source", {}) + print(f"Document {i+1}: ID={doc.get('id')}, Source ID={source.get('id')}") + + # Search for file with flexible matching + found_file = False + file_index = -1 + found_doc = None + + # Try all possible variations of file references + for i, doc in enumerate(message["documents"]): + doc_id = doc.get("id") + source = doc.get("source", {}) + source_id = source.get("id") + + # Try matching different ID formats + if ((doc_id and doc_id == file_id) or + (source_id and source_id == file_id) or + (doc_id and isinstance(doc_id, str) and file_id in doc_id) or + (source_id and isinstance(source_id, str) and file_id in source_id)): + file_index = i + found_file = True + found_doc = doc + print(f"Found file at index {i}: doc_id={doc_id}, source_id={source_id}") + break + + if not found_file: + print(f"File {file_id} not found in message {message_id}") + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=f"Datei mit ID {file_id} in der Nachricht {message_id} nicht gefunden" + ) + + # Remove file reference + deleted_file = message["documents"].pop(file_index) + + # Log removal + file_name = deleted_file.get("source", {}).get("name", file_id) + print(f"Removed file {file_name} from message {message_id}") + + # Update workflow state + workflow_manager._save_workflow(workflow) + + # Update database if available + if workflow_manager.lucydom_interface: + try: + # Pass the file document and message to LucyDOM interface for more robust handling + workflow_manager.lucydom_interface.update_workflow_message(message["id"], message) + print(f"Database updated for message {message_id}") + except Exception as e: + print(f"Database update warning: {str(e)}") + + return { + "workflow_id": workflow_id, + "message_id": message_id, + "file_id": file_id, + "success": True, + "message": "Datei erfolgreich aus der Nachricht gelöscht" + } + + except HTTPException: + # Re-raise HTTP exceptions + raise + except Exception as e: + print(f"Error deleting file: {str(e)}") + import traceback + traceback_str = traceback.format_exc() + print(f"Traceback: {traceback_str}") + + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, + detail=f"Fehler beim Löschen der Datei aus der Nachricht: {str(e)}" + ) \ No newline at end of file diff --git a/gwserver/routes/workspaces.py b/gwserver/routes/workspaces.py deleted file mode 100644 index c2d7ca07..00000000 --- a/gwserver/routes/workspaces.py +++ /dev/null @@ -1,133 +0,0 @@ -from fastapi import APIRouter, HTTPException, Depends, Body, Path -from typing import List, Dict, Any -from fastapi import status - -# Import auth module -from auth import get_current_active_user, get_user_context - -# Import interfaces -from modules.lucydom_interface import get_lucydom_interface - -# Router für Workspace-Endpunkte erstellen -router = APIRouter( - prefix="/api/workspaces", - tags=["Workspaces"], - responses={404: {"description": "Not found"}} -) - -@router.get("", response_model=List[Dict[str, Any]]) -async def get_workspaces(current_user: Dict[str, Any] = Depends(get_current_active_user)): - """Alle verfügbaren Workspaces abrufen""" - mandate_id, user_id = await get_user_context(current_user) - - # LucyDOM-Interface mit Benutzerkontext initialisieren - lucy_interface = get_lucydom_interface(mandate_id, user_id) - - return lucy_interface.get_all_workspaces() - - -@router.get("/{workspace_id}", response_model=Dict[str, Any]) -async def get_workspace( - workspace_id: int, - current_user: Dict[str, Any] = Depends(get_current_active_user) -): - """Einen bestimmten Workspace mit allen Details abrufen""" - mandate_id, user_id = await get_user_context(current_user) - - # LucyDOM-Interface mit Benutzerkontext initialisieren - lucy_interface = get_lucydom_interface(mandate_id, user_id) - - workspace = lucy_interface.get_workspace(workspace_id) - if not workspace: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=f"Workspace mit ID {workspace_id} nicht gefunden" - ) - - return workspace - - -@router.post("", response_model=Dict[str, Any]) -async def create_workspace( - workspace: Dict[str, Any] = Body(...), - current_user: Dict[str, Any] = Depends(get_current_active_user) -): - """Einen neuen Workspace erstellen""" - mandate_id, user_id = await get_user_context(current_user) - - # LucyDOM-Interface mit Benutzerkontext initialisieren - lucy_interface = get_lucydom_interface(mandate_id, user_id) - - new_workspace = lucy_interface.create_workspace(name=workspace.get("name", "Neuer Workspace")) - return new_workspace - - -@router.put("/{workspace_id}", response_model=Dict[str, Any]) -async def update_workspace( - workspace_id: int, - workspace: Dict[str, Any] = Body(...), - current_user: Dict[str, Any] = Depends(get_current_active_user) -): - """Einen bestehenden Workspace aktualisieren""" - mandate_id, user_id = await get_user_context(current_user) - - # LucyDOM-Interface mit Benutzerkontext initialisieren - lucy_interface = get_lucydom_interface(mandate_id, user_id) - - # Prüfe, ob der Workspace existiert - existing_workspace = lucy_interface.get_workspace(workspace_id) - if not existing_workspace: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=f"Workspace mit ID {workspace_id} nicht gefunden" - ) - - updated_workspace = lucy_interface.update_workspace( - workspace_id=workspace_id, - name=workspace.get("name", existing_workspace.get("name")) - ) - - if not updated_workspace: - raise HTTPException( - status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail="Fehler beim Aktualisieren des Workspaces" - ) - - return updated_workspace - - -@router.delete("/{workspace_id}", response_model=Dict[str, Any]) -async def delete_workspace( - workspace_id: int, - current_user: Dict[str, Any] = Depends(get_current_active_user) -): - """Einen Workspace löschen""" - mandate_id, user_id = await get_user_context(current_user) - - # LucyDOM-Interface mit Benutzerkontext initialisieren - lucy_interface = get_lucydom_interface(mandate_id, user_id) - - # Prüfe, ob der Workspace existiert - existing_workspace = lucy_interface.get_workspace(workspace_id) - if not existing_workspace: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=f"Workspace mit ID {workspace_id} nicht gefunden" - ) - - # Prüfe, ob es der initiale Workspace ist - initial_workspace_id = lucy_interface.get_initial_id("workspaces") - if initial_workspace_id == workspace_id: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail="Der Default Workspace kann nicht gelöscht werden" - ) - - success = lucy_interface.delete_workspace(workspace_id) - if not success: - raise HTTPException( - status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail="Fehler beim Löschen des Workspaces" - ) - - return {"message": f"Workspace mit ID {workspace_id} wurde erfolgreich gelöscht"} diff --git a/gwserver/test.py b/gwserver/test.py new file mode 100644 index 00000000..4ced67ef --- /dev/null +++ b/gwserver/test.py @@ -0,0 +1,41 @@ +import asyncio +import json +from modules.agentservice_agent_webcrawler import WebcrawlerAgent +import logging + +# Konfiguration des Loggers +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + handlers=[logging.StreamHandler()] +) + + +async def main(): + agent = WebcrawlerAgent() + # Fixed: Passing a dictionary with "task" key for the message_context parameter + results = await agent.get_web_query({ + "task": "Bitte führe eine Webanalyse durch, welche Firmen haben die gleichen Produkte wie ValueOn AG?" + }) + print(results) # Since result is a string, not JSON + + +async def main2(): + agent = WebcrawlerAgent() + # Hier mit await aufrufen + results = await agent.run_web_query(prompt="Welche Firmen haben die gleichen Produkte wie ValueOn AG?") + with open('test_result.json', 'w') as file: + json.dump(results, file) + # Print the results + if isinstance(results, list): + for i, result in enumerate(results, 1): + print(f"\nResult {i}:") + print(f"Title: {result['title']}") + print(f"URL: {result['url']}") + print(f"Snippet: {result['snippet']}") + + + +# Asynchronen Code ausführen +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/gwserver/test_result.json b/gwserver/test_result.json new file mode 100644 index 00000000..4819df75 --- /dev/null +++ b/gwserver/test_result.json @@ -0,0 +1 @@ +[{"title": "ValueOn AG Company Profile | Uster, Z\u00dcRICH, Switzerland | Competitors ...", "url": "https://www.dnb.com/business-directory/company-profiles.valueon_ag.47e83ff6f420c522d443650735ec0e31.html", "snippet": "Find company research, competitor information, contact details & financial data for ValueOn AG of Uster, Z\u00dcRICH. Get the latest business insights from Dun & Bradstreet. ValueOn AG. D&B Business Directory HOME / BUSINESS DIRECTORY / PROFESSIONAL, SCIENTIFIC, AND TECHNICAL SERVICES / COMPUTER SYSTEMS DESIGN AND RELATED SERVICES", "data": "Error fetching page"}, {"title": "ValueOn - Products, Competitors, Financials, Employees, Headquarters ...", "url": "https://www.cbinsights.com/company/valueon", "snippet": "About ValueOn. Valueon focuses on digital business transformations and IT project leadership in the technology sector. The company provides services that involve assisting businesses with their digital transformation processes and managing critical IT and digital projects. It was founded in 2000 and is based in Uster, Switzerland.", "data": "\nValueOn - Products, Competitors, Financials, Employees, Headquarters Locations

Founded Year

2000

About ValueOn

Valueon focuses on digital business transformations and IT project leadership in the technology sector. The company provides services that involve assisting businesses with their digital transformation processes and managing critical IT and digital projects. It was founded in 2000 and is based in Uster, Switzerland.

Headquarters Location

Uster West 44

Uster, 8610,

Switzerland

Loading...

Loading...

ValueOn Frequently Asked Questions (FAQ)

  • When was ValueOn founded?

    ValueOn was founded in 2000.

  • Where is ValueOn's headquarters?

    ValueOn's headquarters is located at Uster West 44, Uster.

Loading...

Loading...

CBI websites generally use certain cookies to enable better interactions with our sites and services. Use of these cookies, which may be stored on your device, permits us to improve and customize your experience. You can read more about your cookie choices at our privacy policy\u00a0here. By continuing to use this site you are consenting to these choices.

"}, {"title": "ValueOn AG, Uster - business-monitor.ch", "url": "https://business-monitor.ch/de/companies/347424-valueon-ag", "snippet": "ValueOn AG, aktiv in \"Erbringung von Beratungsleistungen auf dem Gebiet der Informationstechnologie\" - Handelsregistereintrag, Netzwerk, Branche, Entscheidungstr\u00e4ger und Kontakte, SHAB", "data": "\n\n\n\n\nValueOn AG, Uster | business-monitor.ch\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nZum Hauptinhalt wechseln\n\n\n\n
\n\n\n\n\n
\n
\n
\n
\n\n
\n
\nVielen Dank, dass Sie den business-monitor.ch, die fortschrittlichste Suchmaschine der Schweiz, benutzt haben.
Um diese Funktion nutzen zu k\u00f6nnen, m\u00fcssen Sie sich KOSTENLOS registrieren:\n
\n\n
\n
\n
\n
\n
\n
\n
\n
\n\n
\n
\n\n

ValueOn AG

\n\n\n\n\n\n\n\n
\n\n
\nStatus: Aktiv\n
\n\n
\n
\nStandort: \nUster, Z\u00fcrich\n
\n\n\n
\n

\nZielkunden Listen: Beziehen Sie die Liste alle Unternehmen, die in Uster aktiv sind.\n

\nListe ansehen\n
\n
\n
\n
\nRechtsform: AG\n
\n
\nGr\u00f6sse: \n\n
\n\n
\n
\n
\n NOGA Codes:\n
\n\n\n
\n

Ein NOGA-Code ist ein standardisiertes System zur Klassifizierung von Unternehmen und wirtschaftlichen Aktivit\u00e4ten. Der Hauptzweck der NOGA-Codes ist die Einteilung der Unternehmen in bestimmte Kategorien oder Sektoren auf der Grundlage der Art der angebotenen Produkte oder Dienstleistungen.

\n
\n
\n
\n
\n
\nJ62 - Erbringung von Dienstleistungen der Informationstechnologie\n
\n\n\n
\n

\nZielkunden Listen: Die Liste aller Unternehmen erhalten, die in \"J62 - Erbringung von Dienstleistungen der Informationstechnologie\" aktiv sind.\n

\nListe ansehen\n
\n
\n
\n
\n\n\n
\n
\n\n\n
\n
\n
\n
\n
\n
\n
\n
\n\"ValueOn\n
\n
\n\n

ValueOn AG

\n\n\n\n\n\n\n\n
\n
\n\n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n

\n\u00dcber ValueOn AG\n

\n

\n Das Unternehmen ValueOn AG ist eine AG mit Sitz in Uster, im Kanton Z\u00fcrich, die im Jahr 2007 gegr\u00fcndet wurde. Seine Identifikationsnummer UID lautet CHE-113.416.882. Es ist in der \"erbringung von beratungsleistungen auf dem gebiet der informationstechnologie\" t\u00e4tig. Derzeit sind die Personen mit Entscheidungsbefugnis Marc Eric Hamburger (Pr\u00e4sident), Reto Egloff (Vice-president), Markus M\u00fchlemann (Mitglied des Verwaltungsrates und Gesch\u00e4ftsf\u00fchrer), Andreas Friedli (Gesch\u00e4ftsf\u00fchrer), Richard Salvisberg (Gesch\u00e4ftsf\u00fchrer) und Dominic Largo (Gesch\u00e4ftsf\u00fchrer). \n

\n
\n
\n\n
\n
\n
\n
\n

\n Ziel\n \n(\nde\n\n fr \u00fcbersetzung\n )\n

\n

\n Der Zweck der Gesellschaft ist die Erbringung von Dienstleistungen f\u00fcr Unternehmen, im Besonderen Beratung f\u00fcr Unternehmensentwicklung, Digitale Business Transformation und Projekt Management sowie Handel mit Waren aller Art. Die Gesellschaft kann sich an anderen Unternehmungen des In- und Auslandes beteiligen sowie alle Gesch\u00e4fte eingehen und Vertr\u00e4ge abschliessen, die geeignet sind, ihren Zweck zu f\u00f6rdern oder die direkt oder indirekt damit im Zusammenhang stehen. Sie kann ferner im In- und Ausland Zweigniederlassungen errichten, Liegenschaften, Unternehmen, Immaterialg\u00fcterrechte und Wertschriften im In- und Ausland im Rahmen des Gesetzes erwerben bzw. errichten, verwalten und verkaufen.\n

\n

\n L'objet de la soci\u00e9t\u00e9 est la prestation de services aux entreprises, en particulier le conseil en d\u00e9veloppement d'entreprise, la transformation num\u00e9rique des entreprises et la gestion de projets ainsi que le commerce de marchandises de toutes sortes.La soci\u00e9t\u00e9 peut participer \u00e0 d'autres soci\u00e9t\u00e9s nationales et \u00e9trang\u00e8res et conclure des accords toutes op\u00e9rations et tous contrats propres \u00e0 promouvoir leur objet ou qui s'y rapportent directement ou indirectement. Elle peut \u00e9galement cr\u00e9er des succursales en Allemagne et \u00e0 l'\u00e9tranger, acqu\u00e9rir ou cr\u00e9er, g\u00e9rer et vendre des biens immobiliers, des soci\u00e9t\u00e9s, des droits de propri\u00e9t\u00e9 intellectuelle et des valeurs mobili\u00e8res en Allemagne et \u00e0 l'\u00e9tranger dans le cadre de la loi.\n

\n
\n
\n
\n
\n

Eintragsdatum

\n

\n 26/01/2007 (etwa 18 Jahre)\n

\n
\n
\n

UID

\n

CHE-113.416.882

\n
\n
\n\n
\n
\n

Zweigniederlassungen

\n
\n
\n\n

Uster Hauptsitz

\n
\n
\n\n
\n
\n
\n
\n
\nload company branches\n
\n
\n
\n

Verbundene Unternehmen oder gleiche Adresse

\n
    \n
    \n
    \n
    \n
    \nload related companies\n
    \n
    \nAlle Informationen einsehen\n
    \n
    \n
    \n\n
    \n
    \n
    \n\n
    \n
    \n\n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n

    Adresse

    \n
    \n ValueOn AG
    \nUster West\u00a044
    \n8610 Uster\n
    \n
    \n
    \n
    \n
    \n

    E-mail

    \n
    \n
    \n\n
    \n
    \n
    \n
    \n

    Telefon Nummern

    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n

    Kontakte von Entscheidungstr\u00e4gern

    \n
    \n\n
    \n
    \n
    \n

    Pers\u00f6nliche Kontakte

    \n
    \n
    \n \n Nicht verf\u00fcgbar\n
    \n
    \n
    \n
    \nAlle Kontakte anzeigen\n
    \n
    \n\n
    \n
    \n Alle Entscheidungstr\u00e4ger anzeigen\n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n\n
    \n
    \n Wenn Sie das vollst\u00e4ndige Netzwerk dieser Firma sehen m\u00f6chten, schliessen Sie ein Abo ab.\n
    \n\n
    \n\nClassic kaufen\n
    \n
    \n\nGesamtes Netzwerk ansehen\n
    \n\n\n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n\n\n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n\n\n"}, {"title": "Mehrwert dank digitaler Transformation | ValueOn AG", "url": "https://www.valueon.ch/", "snippet": "Markus M\u00fchlemann \u00fcbergibt an Dominic Largo: 24 Jahre nach Gr\u00fcndung der Project Competence AG - im Herbst 2022 im Rahmen eines Rebrandings zur ValueOn AG transformiert - \u00fcbergibt Markus M\u00fchlemann die Gesch\u00e4ftsf\u00fchrung und CEO-Aufgaben an Dominic Largo.", "data": "\n\n\n\n\n\n\nMehrwert dank digitaler Transformation | ValueOn AG\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    Digitale Transformation?
    Wir f\u00fchren, begleiten, beraten, unterst\u00fctzen mit Fingerspitzengef\u00fchl.

    \n

    Dominic Largo, CEO

    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    Wir f\u00fchren Ihre\u00a0 businesskritischen
    IT- und\u00a0 Digitalprojekte
    zum Erfolg!\u00a0

    \n
    Andreas Friedli, Managing Partner
    \n

    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    Stehen Sie und Ihre Organisation vor einer zukunftsweisenden digitalen Business Transformation?

    \n

    Richard Salvisberg, Managing\u00a0Partner

    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\"Project
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    Abheben dank digitaler Transformation?

    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    Wir begleiten, beraten, unterst\u00fctzen, f\u00fchren \u2013 so, dass Ihre digitale Transformation oder Ihr IT-Projekt erfolgreich gelingt und f\u00fcr Sie einen messbaren Mehrwert erzielt.

    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    Wir sind Ihr partner
    f\u00fcr digitale Transformationen und IT-Projekte

    \n

    Wir begleiten, beraten, unterst\u00fctzen und f\u00fchren seit \u00fcber 24 Jahren:
    digitale Business Transformationen sowie komplexe und businesskritische IT-Vorhaben und Digitalprojekte.

    Bei unseren Leistungen und Services steht der erzielte Mehrwert bzw. Wertebeitrag an unsere Kunden im Mittelpunkt. Let's ValueOn!

    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    Sind Sie Bereit f\u00fcr Ihre digitale Transformation?

    \n

    Unsere Expertinnen und Experten begleiten, beraten und unterst\u00fctzen Sie vor, w\u00e4hrend und nach Ihrer digitalen Business Transformation.

    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n

    Erarbeitung Zielbild Digitalisierung

    \n

    Sie m\u00f6chten Ihrer digitalen Zukunft eine klare Richtung geben und den Handlungsraum aufzeigen?

    \n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n

    Ist- / Fit-Gap-Analyse Ihrer Transformation

    \n

    Wo steht Ihr Unternehmen genau mit Blick auf die Digitalisierung und dem Einsatz digitaler Prozesse?

    \n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n

    Informations-/Daten-
    architektur

    \n

    Sie wollen im Rahmen der Digitalisierung mehr Nutzen und mehr Wissen aus ihren Daten generieren?

    \n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n

    Digital-, IT & Business-
    strategie

    \n

    Sind Ihre Digital- und IT-Strategie mit der Ihrer Business-Strategie abgestimmt?

    \n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n

    Verhandlungsmanagement
    Transformation

    \n

    Setzen Sie gerade bei komplexen Transformationen auf Verhandlungskompetenz und Verhandlungstools?

    \n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n

    Projekt-
    Portfolio-
    Management

    \n

    Sie wollen Ihre Projekte priorisieren und steuern und daf\u00fcr eine aussagekr\u00e4ftige Entscheidungsgrundlage?

    \n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n

    Chief Digital / Information Officer
    ad interim

    \n

    Sie sind auf der Suche nach einem CDO oder CIO, haben den richtigen aber noch nicht gefunden?

    \n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n

    Sind Ihre Transformationen Value on?

    \n

    Erzielt Ihre Transformation einen messbaren Mehrwert im Sinne von: Value on?

    \n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    Sind Ihre IT- und Digitalprojekte erfolgreich?

    \n

    Unsere Expertinnen und Experten f\u00fchren Ihre businesskritischen und komplexen IT-, Digital- und Transformationsprojekte /-Programme zum Erfolg. Wir steigen auf Wunsch nahtlos ein und \u00fcbernehmen ab dem ersten Tag Verantwortung.

    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n

    Situations-
    analyse, Review und Audit

    \n

    Wo genau steht Ihr Projekt? Wie gef\u00e4hrdet sind die avisierten Ziele und welches sind die gr\u00f6ssten Risiken?

    \n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n

    Projektstart aufsetzen und initiieren

    \n

    Ist Ihr businesskritisches Projekt richtig und zielf\u00fchrend aufgesetzt und sind Auftrag wie Ziele allen ganz klar?

    \n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n

    Programm-/
    Projekt-
    Assurance

    \n

    Wissen Sie, welche Ihrer Projekte auf \u00abOrange\u00bb und \u00abRot\u00bb stehen? Und kennen Sie die Ursachen?

    \n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n

    Vorhaben
    steuern
    f\u00fcr GL

    \n

    W\u00fcnschen Sie sich einen Partner, der Ihr Vorhaben aus Perspektive der GL f\u00fcr Sie steuert?

    \n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n

    F\u00fchren von Projekten / Programmen

    \n

    Sie suchen eine Person, die Ihr businesskritisches IT- / Digital-Projekt oder Ihr Programm zum Erfolg f\u00fchrt?

    \n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n

    Erfolgreich
    Verhandlungen
    f\u00fchren

    \n

    Verf\u00fcgen Sie \u00fcber Verhandlungskompetenz, um z.B. enge Terminpl\u00e4ne oder Budgets zu sch\u00fctzen?

    \n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n

    L\u00f6sungen erzielen mit Design Sprints

    \n

    Sie stehen gerade vor einer herausfordernden Situation und w\u00fcnschen sich schnell eine tragf\u00e4hige L\u00f6sung?

    \n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n

    Sind Ihre Projekte:
    Value on?

    \n

    Erzielen Ihre Projekte einen messbaren Mehrwert im Sinne von: Value on?

    \n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    Digitale Business Transformationen

    \n
      \n
    • Sind Ihre digitalen Transformationen erfolgreich? Welchen konkreten Nutzen bzw. Mehrwert erzielen diese?
    • \n
    • Haben Sie eine \u00fcbergreifende Digitalisierungsstrategie, die IT- und Business-Strategie mit einbezieht?
    • \n
    • Welche Digitalisierungsstrategien sind f\u00fcr Ihr Unternehmen zielf\u00fchrend, nachhaltig und wirksam?
    • \n
    \n

    Unsere Expertinnen und Experten begleiten, beraten und unterst\u00fctzen Sie vor, w\u00e4hrend und nach Ihrer Digitalen Business Transformation. Und wenn gew\u00fcnscht, \u00fcbernehmen wir gerne auf operativer Ebene und begleiten / f\u00fchren Ihre digitale Transformation zum Erfolg.

    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    Businesskritische Digital- / IT-Projekte

    \n
      \n
    • Wie sichern Sie eine erfolgreiche Umsetzung Ihrer IT-Digitalprojekte bzw. Transformationsvorhaben?
    • \n
    • Ist Ihr Projekt gerade von Gr\u00fcn auf Rot gesprungen, und sind Termine und Qualit\u00e4t aufs H\u00f6chste gef\u00e4hrdet?
    • \n
    • Haben Sie ein genaues Bild, wo Ihr IT- oder Digitalprojekt aktuell steht?
    • \n
    \nUnsere Experten f\u00fchren Ihre businesskritischen und komplexen IT-, Digital- und Transformationsprojekte / -Programme zum Erfolg, steigen auf Wunsch nahtlos in Ihre Vorhaben ein und \u00fcbernehmen ab dem ersten Tag die Projektf\u00fchrung und gehen damit in Verantwortung.
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\"003_ValueOn_neu\n
    \n
    \n
    \n INTERN\n
    \n
    \n

    \n F\u00fchrungswechsel bei ValueOn\n

    \n
    \n
    \n\n Markus M\u00fchlemann \u00fcbergibt an Dominic Largo: 24 Jahre nach Gr\u00fcndung der Project Competence AG \u2013 im Herbst 2022 im Rahmen eines Rebrandings zur ValueOn AG transformiert \u2013 \u00fcbergibt Markus M\u00fchlemann die Gesch\u00e4ftsf\u00fchrung und CEO-Aufgaben an Dominic Largo.\n \n
    \n
    \n
    \n\n\"Mehr\n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    Erfolgreiche Projekte & Transformationen

    \n

    Unter dem Motto \u00abUnsere Kunden stehen im Mittelpunkt\u00bb haben wir f\u00fcr Sie eine Auswahl an Kundenreferenzen und Business Cases \u2013 teilweise erg\u00e4nzt mit pers\u00f6nlichen Interviews mit den Verantwortlichen \u2013 zusammengestellt.

    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\"KPT\n
    \n
    \n KPT Krankenversicherung \n
    \n
    \n
    \n
    \n
    \n
    \n

    \u00abWenn man die vorherige IT leistungsm\u00e4ssig mit der neu geschaffenen Infrastruktur vergleicht, ergibt sich insgesamt eine Nutzwertverbesserung und Kostenoptimierung von fast 24% (inkl. 11% Einsparungen bei den laufende IT-Kosten) \u2013 und das bei deutlich mehr Leistung, mehr Flexibilit\u00e4t und wesentlich mehr Sicherheit.\u00bb

    \n
    \n
    \n
    \n
    \n
    \n\n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\"Logo\n
    \n
    \n WWZ AG \n
    \n
    \n

    \u00abValueOn (ehem. Project Competence) hat das Gesamtvorhaben mit Kompetenz, Erfahrung und Fingerspitzengef\u00fchl zielgenau und fokussiert gef\u00fchrt und jederzeit die wichtigen und aktuellen Themen priorisiert und adressiert. Dank dieser Unterst\u00fctzung konnten wir uns wiederum voll auf die Projektziele ausrichten und schlussendlich termingerecht die L\u00f6sung einf\u00fchren.\u00bb

    \n
    \n\n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\"Logo_FCL_rgb_web_S\"\n
    \n
    \n FC Luzern \n
    \n
    \n

    \u00abValueOn (ehem. Project Competence) hat aus unserer Sicht einen fantastischen Job gemacht. Von der ersten Minute war sp\u00fcrbar, \u00fcber welch grosse Kompetenz und Erfahrung die Experten verf\u00fcgen. Die Analyse war von Anfang an gut aufgebaut und strukturiert; die Ergebnisse wurden transparent, offen, argumentativ und mit gesundem Nachdruck pr\u00e4sentiert. Wir sind begeistert von dem Ergebnis.\u00bb

    \n
    \n\n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    Wissen, Impulse & News

    \n

    Gerne pr\u00e4sentieren wir Ihnen spannende Informationen rund um unser Unternehmen sowie die Themen Digitale Business Transformationen und das Umsetzen bzw. F\u00fchren von gesch\u00e4ftskritischen Digital-/ IT-Projekten.

    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\"Image\n
    \n
    \n
    \n

    Referenzen:
    Unsere Kunden haben das Wort.

    \n

    Ob Digitale Busienss Transformation oder komplexes IT- bzw. Digitalprojekt: Es freut uns, Ihnen immer wieder Projekte und Transformationsvorhaben im Detail vorzustellen.

    \n

    Mehr lesen \u2192

    \n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\"Original_kpt_gl-652_k(1)\"\n
    \n
    \n
    \n

    Reto Egloff im Verwaltungsrat von ValueOn

    \n

    Wir freuen uns, mit Reto Egloff ein neues Verwaltungsratsmitglied der ValueOn AG, und mit ihm auch einen ausgewiesenen Experten des Gesundheitswesens begr\u00fcssen zu d\u00fcrfen.

    \n

    Mehr lesen \u2192

    \n\n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\"Double\n
    \n
    \n
    \n

    Studie \u00abDigitale Transformation\u00bb bei Schweizer KMU

    \n

    Was sind die gr\u00f6ssten Herausforderungen bei KMUs, wenn es um das Thema \u00abDigitale Transformationen\u00bb geht? Diese und andere Fragen beantwortet die Studie, die von ValueOn gemeinsam mit der Universit\u00e4t St. Gallen (HSG) durchgef\u00fchrt wurde.

    \n

    Blogbeitrag & Studienergebnisse lesen \u2192

    \n\n
    \n
    \n\n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n ValueOn AG
    \n
    \n
    \n Uster West 44\n
    \n
    \n 8610 Uster (bei Z\u00fcrich)\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \nTelefon:\n+41 44 943 70 40\n
    \n
    \nE-Mail:\noffice@valueon.ch\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    Newsletter abonnieren
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    \n
      \n
    • Lesen Sie interessanter Impact zum Thema digitale Transformation.
    • \n
    • Erfahren Sie Aktuelles rund um ValueOn.
    • \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"}, {"title": "Valueon Ag - Uster 8610 (Bezirk Uster), Uster-west 44 ... - Kompass", "url": "https://gb.kompass.com/c/valueon-ag/ch162286/", "snippet": "Please refine your search by (Localization + What, who? ... Edit search Login / Register My account", "data": "Error fetching page"}, {"title": "10 Agritech Companies to Watch Out for in 2025", "url": "https://agritechdigest.com/10-agritech-companies-to-watch-out-for-in-2025/", "snippet": "Here are ten of such companies to watch out for in 2025. 1. AgMonitor . AgMonitor is a software company that helps farmers optimise water use, energy costs, and crop yields. The company integrates machine learning with real-time farm data to enable better resource allocation and improved efficiency.", "data": "\n 10 Agritech Companies to Watch Out for in 2025 - Agritech Digest \n
    Home \u00bb 10 Agritech Companies to Watch Out for in 2025

    10 Agritech Companies to Watch Out for in 2025

    by Victor Adeyemi
    written by Victor Adeyemi 12 minutes read
    122

    As food systems evolve, agritech continues to introduce solutions that improve efficiency, sustainability, and market access. Agritech companies across different segments are developing tools to refine how food is grown, processed, and distributed. Here are ten of such companies to watch out for in 2025.

    1. AgMonitor

    \"\"

    AgMonitor is a software company that helps farmers optimise water use, energy costs, and crop yields. The company integrates machine learning with real-time farm data to enable better resource allocation and improved efficiency. Founded in 2016, it operates across the United States and parts of Europe.\u00a0\u00a0

    Beyond individual farm operations, AgMonitor works with cooperatives, agricultural lenders, and policymakers to promote sustainable practices. Its technology has helped farms cut costs while boosting productivity.\u00a0

    A major milestone came in 2024, when AgMonitor expanded partnerships with key irrigation districts, which led to measurable reductions in water waste. The company\u2019s data-driven approach has positioned it as a critical player in precision agriculture and scalable solutions for agribusinesses of all sizes.

    2. Sencrop\u00a0

    \"\"

    Established in 2016 by an electronic engineer and the son of a grain farmer, Sencrop connects weather data directly to farm operations. Its precision weather application, powered by local weather stations, helps farmers make timely decisions based on real-time conditions. With Sencrop, users can access station data, monitor field conditions, and rely on highly accurate weather forecasts tailored to their plots. The company operates in the UK, France, Germany, and the Netherlands.

    Sencrop\u2019s technology plays a crucial role in Europe\u2019s agro-ecological transition. Through the app, farmers can gain ultra-local insights into temperature, humidity, wind speed, and rainfall\u2014crucial data that supports more informed and strategic farming decisions.

    \"\"
    We are excited to share with youThis FREE E-Book of 50 Agritech Pioneers & Their Game Changing Innovations.

    Download the Ebook now\u00a0

    Enter your email address

    In January 2025, Groupe ISAGRI acquired Sencrop, which marked an important shift in the company\u2019s journey. The acquisition strengthens Sencrop\u2019s service offering and transitions it from a startup to an integral part of a family-owned, independent agri-service network.\u00a0

    3. Breedr

    \"\"

    The UK-based company was launched in 2018 and has since expanded into Australia and North America. Breedr is on a mission to empower farmers with the tools to produce environmentally and commercially sustainable meat in order to safeguard the future of their businesses and the planet.

    Through its platform, farmers can log animal data such as genetics, weight, health, fertility, and medication history, using their smartphones. Data can be manually entered or integrated via sensors, wearables, and tags. The app also offers an online marketplace where farmers can trade livestock directly.

    In 2022, the livestock management platform secured \u00a312 million ($15.8 million) in funding and introduced a financial product designed to support farmers\u2019 cash flow.

    4. Reforest

    \"\"

    Reforest uses AI-powered drones to plant trees at scale to advance land restoration and reforestation. The company, founded in 2019, applies data analytics to find the best locations for planting and improved tree survival rates.

    The Australia-based company helps businesses and events take real climate and nature-positive action by planting trees in high-quality local projects and providing a way to showcase that impact.

    Operating across multiple continents, Reforest collaborates with governments and environmental organisations to combat deforestation. Reports confirmed that the company had successfully planted close to 5 million trees and restored over 5,000 hectares, which has had a tangible impact on carbon sequestration and ecosystem recovery.
    \u00a0

    5. AquaSpy

    \"\"


    Founded in 2008, AquaSpy is a cloud-based IoT agriculture platform that connects growers with specific crop plant behaviour and needs. Based in San Diego, California, AquaSpy delivers a proven Intelligent Crop Sensing System for guaranteed yield improvement.

    Furthermore, the company specialises in soil moisture monitoring, which provides farmers with real-time data to optimise irrigation strategies. Through advanced sensors and analytics, the company helps reduce water waste and equally ensures crops receive the precise amount of hydration needed for optimal growth.

    Partnerships with large agricultural enterprises and research institutions have allowed AquaSpy\u2019s technology to scale globally.

    6. Ekobot

    \"\"

    Ekobot is automating the field with its AI-powered robotic solutions for weed control. Founded in 2017 and located in V\u00e4ster\u00e5s, Sweden, the company\u2019s autonomous robots use computer vision and machine learning to identify and eliminate weeds efficiently. Their solutions have also been useful in reducing the reliance on chemical herbicides.

    Field trials across Europe have demonstrated Ekobot\u2019s potential to cut labour costs and improve crop health. Sustainability being at its core, the company\u2019s technology aligns with the growing demand for eco-friendly agricultural practices. Their solutions offer farmers an efficient alternative to traditional weed management.

    7. Cowtribe\u00a0

    \"\"


    As Africa\u2019s first on-demand veterinary vaccine distribution platform, Cowtribe has been transforming animal healthcare for smallholder farmers since 2016. Part of Cowtribe innovation is the development of a smart supply chain and logistics platform that efficiently delivers livestock vaccines and other inputs to rural farmers in Ghana.

    In addition to veterinary services, the company also supports farmers with vital agricultural services such as information on best farming practices and critical alerts regarding disease outbreaks and disruptive weather patterns.

    Through its logistics network and partnerships with veterinary suppliers, Cowtribe ensures timely and affordable delivery of vaccines to remote areas. Cowtribe\u2019s impact on improving livestock survival rates and farmer incomes has positioned the company as an important stakeholder in last-mile veterinary service delivery.

    8. Releaf

    \"\"

    Releaf enhances food processing efficiency across Africa with proprietary hardware and software solutions. This Nigerian-based company was founded in 2017 and specialises in mechanised palm nut processing to reduce post-harvest losses and improve smallholder farmers\u2019 supply chain efficiency.

    Releaf\u2019s model stretches across the entire palm oil value chain, and their solutions enable farmers to earn more for their oil by selling it to fast-moving consumer goods companies and other buyers.\u00a0

    In an interview with AgFunder News, co-founder Ikenna Nzewi shared their objective: to reduce the burden of labour for farmers so that they can spend their time focusing on production, and factories can focus their time on processing. As of 2021, the company had worked with 2,000 smallholder palm farmers and aims to reach over 10,000 in the next couple of years.

    9. AgriPredict\u00a0

    \"\"


    AgriPredict tackles agricultural risks with AI-driven predictive analytics. The platform provides real-time insights into weather patterns, pest outbreaks, and crop diseases. These insights help farmers make proactive decisions that protect their yields.

    Founded in 2016 by Mwila Kangwa, AgriPredict helps farmers in Zambia spot crop diseases that have hurt their farms in previous years. With the company\u2019s mobile app, 22,000 farmers can access information on plant diseases and weather patterns, which they would have needed an expert for before. This has allowed farmers to cut costs and run their farms more efficiently.\u00a0

    Their solutions also helps older farmers who aren\u2019t tech-savvy access reliable information without needing expensive data plans. Government agencies and agribusinesses also use AgriPredict to improve food security by reducing climate-related risks.

    10.\u00a0 Agrofy

    \"\"


    Launched in 2015, Agrofy is a digital marketplace for the agricultural sector. The platform connects farmers with suppliers for machinery, equipment, inputs, financial services and in essence, enhances efficiency across the agribusiness supply chain.

    Based in Rosario, Argentina, Agrofy positions itself as \u201cthe leading agribusiness online market in Latin America.\u201d It operates in nine countries across the region, with its presence most prominent in Argentina. What started as an online marketplace with around 150,000 products now includes financial services.

    Agrofy\u2019s presence across Latin America makes it a big player in agri-commerce. Partnerships with agribusiness firms and financial institutions has helped farmers easily access what they need.\u00a0

    Wrap Up\u00a0

    There is no denying that agritech is reshaping food production. The companies listed here reflect a shift toward smarter, more efficient agricultural systems. Each one, in its own way, is contributing to better resource management, improved yields, and stronger supply chains.

    As agritech companies move forward in 2025, there is much to consider. Whether through automation, precision tools, or market access solutions, these innovations highlight the role of technology in tackling modern agricultural challenges.

    \"\"
    Victor Adeyemi

    Victor believes that the way to go in agriculture is tech solutions. He is big on research, innovation, and agric journalism.

    Agritech Digest seeks to provide the latest agricultural news, technology, innovations, and insights to promote awareness of agritech startups. It is dedicated to empowering Agritech startups, investors, policymakers, farmers, and agri-enthusiasts by offering knowledge and resources, helping them succeed in the evolving world of agritech and entrepreneurship in agriculture. Agritech Digest aims to showcase the vast potential of the agricultural technology industry by attracting investors and young talent through highlighting technology and innovations in the agritech industry.


    Agritech Digest seeks to provide the latest agricultural news, technology, innovations, and insights to promote awareness of agritech startups. Agritech Digest aims to showcase the vast potential of the agricultural technology industry by attracting investors and young talent through highlighting technology and innovations in the agritech industry.

    Agritech Digest seeks to provide the latest agricultural news, technology, innovations, and insights to promote awareness of agritech startups. Agritech Digest aims to showcase the vast potential of the agricultural technology industry by attracting investors and young talent through highlighting technology and innovations in the agritech industry.

    \"\"

    Agritech Digest is your gateway to a fascinating world where agriculture meets technology.

    FOLLOW US ON SOCIAL

    \u00a92023 Agritech Media, All Right Reserved. Designed and Developed by KubuniX

    \"\"
    Newsletter Signup

    Subscribe to our weekly newsletter below and never miss the latest updates.

    Enter your email address
    \n \n"}, {"title": "Find Similar Companies - VentureRadar", "url": "https://www.ventureradar.com/similarcompanies", "snippet": "Our AI algorithm fetches similar companies from our database of more than 300,000 companies. 3. Export the Top 100 results to CSV or Excel. About VentureRadar. VentureRadar works for some of the World's largest corporations, removing the barriers they traditionally face in discovering and tracking companies that can impact their business. ...", "data": "\n\n\n\n\r\n\tVentureRadar\r\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
    \n
    \n\n\n\n
    \n\n\n\n\n
    \n\n
    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
    \n
    \n
    \n
    \n
    \n

    \n\r\n Find Similar Companies

    \n

    Create your list - We will instantly find similar
    \r\n companies to the ones you add below.

    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n\n\n\n\n\n
    \nGenerate list
    \n
    \n
    \n
    \n
    \n\n\n\n\n\n\n\n\n\n\n
    Company nameCountryStatus
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n

    Our Similar Companies App helps you find
    \r\n similar companies to ones you already know

    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n

    Find B2B Sales Prospects

    \n
      \n
    • Improve the time and efficiency of creating prospecting lists.
    • \n
    • Shorten your sales discovery process with our B2B Sales Prospecting Tool.
    • \n
    • Build a targeted list of prospects in no time.
    • \n
    • Create a list of your ideal customers.
    • \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    Research Competitive Landscapes

    \n
      \n
    • Map out competitive landscapes.
    • \n
    • Discover competitors. Discover M&A targets.
    • \n
    • Discover partnering opportunities.
    • \n
    • Due diligence on business partners.
    • \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n

    How it works

    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n1. Add one or more companies that already match the list you are trying to create.\r\n
    \n
    \n
    \n2. Our AI algorithm fetches similar companies from our database of more than 300,000 companies.\r\n
    \n
    \n3. Export the Top 100 results to CSV or Excel.\r\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n

    About VentureRadar

    \n

    \r\n VentureRadar works for some of the World's largest\r\n corporations, removing the barriers they traditionally\r\n face in discovering and tracking companies that can\r\n impact their business.\r\n

    \n

    \r\n From landscaping emerging technology themes to\r\n locating specialist skills that can solve internal\r\n business challenges, our clients rely on us to help\r\n them find partners, competitors, acquisition targets,\r\n investment targets and understand markets.\r\n

    \nFind out more\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    View More With A Free\u00a0Account

    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    Submit or Claim Your\u00a0Company

    \n
    \n
    \n
    \n
    \n
    Register for Free
    \n
    \n
    \n\n
    \n
    OR
    \n
    \n
    \n
    \n

    Create an Account for More

    \n
    \n
    \n
    \n
    \n
    Register for Free
    \n
    \n
    \n\n
    \n
    OR
    \n
    \n
    \n
    \n

    More about VentureRadar

    \n
    \n
    \n\n
    \n
    \n
    \n
    \n\n\n\n
    Copyright \u00a92024 VentureRadar. All\u00a0Rights\u00a0Reserved.
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    Upgrade to a Paid Plan for More

    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \r\n \u00a0\r\n
    \n
    \u00a0
    \n
    \n
    \n
    \n

    Full Access and Downloads

    \n
    \n
    \n\n\n
    \n
    \u00a0
    \n
    \r\n \u00a0\r\n
    \n
    \n
    \n
    \n\n\n\n
    Copyright \u00a92024 VentureRadar. All Rights Reserved.
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n

    \nUpgrade for full access\n

    \n
    \n
    \n

    You have reached your free usage limit for today.
    Please come back tomorrow or upgrade your account.

    Upgraded accounts get:

    • 100 records per export
    • 50 exports per month

    Full Access

    from\u00a0\u00a0$60.00

    per month


    Upgrade Now

    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n

    Your VentureRadar Business account is now active and

    \n

    your account information has been sent to your email address.

    \n
    \n
    \n
    \n
    \n\n\n
    \n
    \n\n
    \n\n
    \n
    \n\n
    \n
    \n\n
    \n
    \n
    \n\n
    \n\n
    \n\n
    \n
    \n
    \n
    \n
    \n
    \n\n\n

    Free Sign-up for VentureRadar access

    \n
    \n
    \n

    or

    \n
    \n\n\n
    \nPlease enter Email\nIncorrect Email format\n
    \n
    \n
    \n\n\n
    \nPlease enter Password\n
    \n
    \n
    \n\n\n
    \nPlease confirm Password\nPassword confirmation does not match\n
    \n
    \n
    \n\n\n
    \nPlease enter your first name\n
    \n
    \n
    \n\n\n
    \nPlease enter your last name\n
    \n
    \n
    \n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \nBy continuing, you agree to VentureRadar's Terms of Service, Privacy Policy and Cookie Policy.\r\n \n
    \n
    \n
    \n\n

    Free Sign-up for VentureRadar access

    \n
    \n

    You must have cookies enabled to create an account with VentureRadar

    \n\n

    \nReturn to home page\n

    \n
    \n
    \n
    \n
    \n\n

    Create a Free Account
    to Follow Companies

    \n\n
    \n
    \n
    \n

    To continue, please confirm you\r\n are not a robot

    \n
    \n
    \n
    \n
    \n\n\n\n
    \n\n\n\n\n\n\n\n\n\n"}, {"title": "Top 24 Agribusiness Companies Revolutionizing US Agriculture - Inven", "url": "https://www.inven.ai/company-lists/top-24-agribusiness-companies-in-the-us", "snippet": "Frontier Ag Inc. is a company that offers comprehensive agricultural solutions to farmers and ranchers. They provide products and services such as crop inputs, precision agronomy, grain marketing, and livestock feed. Their experienced team works closely with customers to maximize profitability and sustainability in their operations. 13.", "data": "\nTop 24 Agribusiness Companies Revolutionizing US Agriculture\n\n\n\n\n\n\n

    Top 24 Agribusiness Companies Revolutionizing US Agriculture

    5
    min read
    \"Top

    Top 24 Agribusiness Companies Revolutionizing US Agriculture

    5
    min read
    Get started
    \"Top
    Top firms trust Inven to find niche companies

    The agribusiness industry in the US consists of companies that specialize in agricultural science, solutions, and services. These companies offer a wide array of products and services to meet the diverse needs of farmers, residences, and businesses. They provide everything from healthy oils and seeds to farm supplies, livestock feed, and pet supplies. Additionally, digital solutions and farm management software are available to optimize agricultural operations and help farmers make informed decisions. The industry is headed towards more sustainable practices, with a focus on improving soil and plant health, reducing carbon footprints, and increasing yields through innovative technologies and agronomic advice.


    Top 24 Agribusiness Companies in the US

    1.\u00a0Corteva Agriscience

    • Headquarter: Indianapolis, Indiana, United States
    • Headcount: 10001+
    • LinkedIn

    Corteva is a company specializing in agricultural science and solutions. They offer a range of healthy oils and seeds, including high oleic oils and Plenish\u00c2\u00ae Soybean Oil. These products provide multiple benefits, such as improved health, performance, and flavor attributes. Corteva aims to meet the demands of health-conscious consumers and food manufacturers through their innovative offerings.

    2.\u00a0Southern States Cooperative

    • Headquarter: Richmond, Virginia, United States
    • Founded: 1923
    • Headcount: 1001-5000
    • LinkedIn

    Southern States is a company that offers a wide range of products and services for farms, residences, and businesses. They provide heating oil, farm supplies, livestock feed, pet supplies, and lawn and garden products. They also offer services such as energy conservation and weed control.

    3.\u00a0Nutrien Ag Solutions

    • Headquarter: Loveland, Colorado, United States
    • Founded: 2018
    • Headcount: 10001+
    • LinkedIn

    Nutrien Ag Solutions is a provider of critical early nutrients and agronomic advice for farmers. They offer a wide selection of products to optimize soil and plant health, reduce the industry's carbon footprint, and help farmers achieve higher yields. With their expertise and innovative technologies, they aim to help farmers manage today's farming challenges and ensure sustainable success.

    4.\u00a0Climate

    • Headquarter: San Francisco, California, United States
    • Founded: 2006
    • Headcount: 501-1000
    • Latest funding type: Grant
    • LinkedIn

    Climate.com offers digital solutions for farmers, providing tools and technology to optimize agricultural operations. They help farmers make informed decisions through data collection, visualization, and analysis, improving crop performance and yield potential.

    5.\u00a0Granular

    • Headquarter: San Francisco, California, United States
    • Founded: 2014
    • Headcount: 201-500
    • Latest funding type: Series B
    • LinkedIn

    Granular is a company that offers farm management software and agronomy solutions. They provide tools to help farmers track profitability, manage input and crop inventories, and make data-driven decisions to maximize profitability. With automated task management tools, growers can improve efficiency and accuracy in their operations.

    6.\u00a0Wilbur-Ellis Agribusiness

    • Headquarter: Aurora, Colorado, United States
    • Headcount: 1001-5000
    • LinkedIn

    Wilbur-Ellis is an agribusiness company that specializes in water management, resistance management, sustainability, and soil health. They offer a range of products and services including plant nutrition, seed treatments, field technology, soil and tissue sampling, and field scouting. Their expertise and collaboration with customers lead to profitable agricultural outcomes. Wilbur-Ellis is known for providing innovative solutions and services to maximize returns on investment for growers.

    7.\u00a0Braga Fresh Family Farms

    • Headquarter: Soledad, California, United States
    • Founded: 1928
    • Headcount: 1001-5000
    • LinkedIn

    BragaFresh is a company that specializes in sustainable organic farming practices and offers a range of conventional and organic produce. They are committed to transparency and food safety, utilizing innovative technologies to reduce their carbon footprint. BragaFresh provides top-notch packaged salad products and is constantly evolving to meet market changes and demand.

    8.\u00a0Central Valley Ag Cooperative

    • Headquarter: York, Nebraska, United States
    • Founded: 2003
    • Headcount: 501-1000
    • LinkedIn

    Central Valley Ag is a farmer-owned cooperative in Iowa, Kansas, & Nebraska. CVA is an innovative leader providing products and services in grain, agronomy, feed, & energy.

    9.\u00a0The Equity

    • Headquarter: Effingham, Illinois, United States
    • Founded: 1919
    • Headcount: 501-1000
    • LinkedIn

    The Equity is an agricultural retailer offering a wide range of products and services to farmers and livestock owners. Despite facing challenges like COVID and supply-chain disruptions, the company has experienced growth in various sectors like agronomy, energy, feed, grain, and hardware. They provide input financing options to help customers take advantage of favorable market prices. With a focus on equity management and customer service, The Equity has become one of the premier ag retailers in the country.

    10.\u00a0Pivot Bio

    • Headquarter: Berkeley, California, United States
    • Founded: 2011
    • Headcount: 201-500
    • Latest funding type: Series D
    • LinkedIn

    Pivot Bio is a company that provides microbial fertilizers for cereal crops, such as corn, wheat, and rice. Their specially designed microbes replace synthetic nitrogen, ensuring that crops receive the nutrition they need. Through their environmentally sound fermentation production process, Pivot Bio offers farmers a more efficient and sustainable nitrogen source.

    11.\u00a0QC Supply

    • Headquarter: Schuyler, Nebraska, United States
    • Founded: 1982
    • Headcount: 201-500
    • LinkedIn

    QCSupply is a company that offers a wide range of products and solutions for the agriculture and livestock industries. They provide equipment, supplies, and services to support the daily operations and growth of farmers and ranchers.

    12.\u00a0Frontier Ag Inc.

    • Headquarter: Oakley, Kansas, United States
    • Founded: 2007
    • Headcount: 201-500
    • LinkedIn

    Frontier Ag Inc. is a company that offers comprehensive agricultural solutions to farmers and ranchers. They provide products and services such as crop inputs, precision agronomy, grain marketing, and livestock feed. Their experienced team works closely with customers to maximize profitability and sustainability in their operations.

    13.\u00a0The McGregor Company

    • Headquarter: Colfax, Washington, United States
    • Founded: 1956
    • Headcount: 201-500
    • LinkedIn

    The McGregor Company is a premier independent fertilizer, agri-chemical, and agricultural equipment dealer in the Pacific Northwest. With retail offices in over 35 communities, McGregor serves the outstanding farmers of the region with dedicated people who care about farm families, the environment, and the communities they serve.

    14.\u00a0Zook Molasses Company

    • Headquarter: Honey Brook, Pennsylvania, United States
    • Founded: 1934
    • Headcount: 51-200
    • LinkedIn

    Zook Molasses Company is a provider of high-quality bulk molasses for animal feed and horticulture. They offer non-GMO, organic, and conventional variants to farms of all sizes since 1934. Their liquid feed improves soil health and livestock well-being, and they prioritize customer satisfaction.

    15.\u00a0Cooperativas Agro-alimentarias Espa\u00c3\u00b1a

    • Headquarter: United States
    • Founded: 1992
    • Headcount: 11-50
    • LinkedIn

    Cooperativas Agro-alimentarias is a company in the agro-food sector that provides services and support to agricultural cooperatives. They offer resources and information on topics like olive oil, beekeeping, and wine production. They also organize events and provide training to promote sustainability, innovation, and quality in the industry.

    16.\u00a0Ind Hemp

    • Headquarter: Fort Benton, Montana, United States
    • Founded: 2015
    • Headcount: 11-50
    • LinkedIn

    IND HEMP is a family-owned industrial hemp company based in Montana, USA. They provide new opportunities for farmers and rural communities by offering industrial hemp food, feed, and fiber products. Their mission is to connect farmers with the hemp businesses of tomorrow and provide a stable supply chain using American-grown hemp seeds and fiber.

    17.\u00a0MKC - Mid Kansas Coop

    • Headquarter: Moundridge, Kansas, United States
    • Founded: 1965
    • Headcount: 201-500
    • LinkedIn

    MKC is an agricultural cooperative that offers a wide range of services including feed, energy, agronomy, and grain marketing. They provide top-notch nutrition programs and products for livestock operations, as well as professional energy services. With a focus on customer and partner success, MKC aims to navigate the complexities of modern agriculture and industry.

    18.\u00a0Land O'Lakes Venture37

    • Headquarter: Arden Hills, Minnesota, United States
    • Headcount: 201-500
    • LinkedIn

    Land O'Lakes Venture37 is a nonprofit organization dedicated to helping communities thrive through agriculture. They offer expertise and support in agricultural development, focusing on data, science, and math to help farmers make informed decisions in their fields. They aim to engage and empower all members of society, including women, youth, and marginalized populations.

    19.\u00a0Olsen Custom Farms

    • Headquarter: Hendricks, Minnesota, United States
    • Headcount: 51-200
    • LinkedIn

    Olsen Custom Farms is a farming and harvesting company based in Hendricks, Minnesota. With operations throughout the USA and Canada, they specialize in custom farming, combine rentals, custom harvesting, and agronomy services.

    20.\u00a0Brandt\u00c2\u00ae

    • Headquarter: Springfield, Illinois, United States
    • Founded: 1953
    • Headcount: 501-1000
    • LinkedIn

    BRANDT is a company that specializes in plant nutrition, crop protection, and agronomic insights. They offer a range of products and services for farmers, retailers, consumers, and turf professionals. With over 65 years of experience, BRANDT is committed to helping growers improve their crop yields and take control of their farming operations.

    21.\u00a0Precision Planting

    • Headquarter: Tremont, Illinois, United States
    • Founded: 1995
    • Headcount: 201-500
    • LinkedIn

    Precision Planting is a company that specializes in providing innovative and advanced planting solutions for farmers. They offer a wide range of products and technologies to maximize farm efficiency and yield. With over 25 years of experience, Precision Planting is committed to bringing confidence to farms by consistently delivering high-quality and reliable equipment.

    22.\u00a0ServiTech Inc.

    • Headquarter: Dodge City, Kansas, United States
    • Founded: 1975
    • Headcount: 201-500
    • LinkedIn

    ServiTech, Inc. is a trusted agronomy business that helps farmers worldwide make tough decisions. With extensive experience and knowledge, we aim to create a more productive world sustainably. Our services include crop consulting, laboratory services, and field intelligence solutions.

    23.\u00a0Usda

    • Headquarter: Washington, District Of Columbia, United States
    • Headcount: 10001+
    • LinkedIn

    USDA.gov is the official website of the United States Department of Agriculture. It provides information, resources, and services related to agriculture, food, and natural resources.

    24.\u00a0Insight FS

    • Headquarter: Jefferson, Wisconsin, United States
    • Founded: 1955
    • Headcount: 201-500
    • LinkedIn

    Insight FS is a company that offers a wide range of products and services in the commercial and agricultural industries. They specialize in agronomy, engineering services, fuel stations, energy products, nutrient management, and more. With a commitment to the environment and 4R Nutrient Stewardship, Insight FS provides innovative solutions to help farms and businesses thrive.

    Want to find more agribusiness companies?

    If you want to find more companies that offer products and services such as healthy oils and seeds, farm supplies, digital solutions, and agronomic advice you can doso with Inven. This list was built with Inven and there are hundreds ofcompanies like these globally.

    With Inven you'll also get to know the company's:

    • Ownership: Which of these are private equity backed? Which are\u00a0family-owned?
    • Contact data: Who are the owners and CEO's? What are their emailsand\u00a0phone numbers?
    • Financials: What is the financial performance of these companies?

    ...and a lot more!


    Get started with Inven

    Find companies 10x faster with Inven
    \"Mock-upGet started
    Get started with Inven
    \n\n\n\n\n\n\n\n"}, {"title": "2022 list of top 50 agtech and foodtech companies is released", "url": "https://www.agdaily.com/news/2022-list-top-50-agtech-foodtech-companies-released/", "snippet": "To qualify for the Top 50 listing, a company must have a product in market, have received a minimum of series A funding, and be ready to scale. New this year is a focus on sustainability. With agriculture playing a pivotal role in progressing global sustainability through innovation, the report highlights 10 sustainable companies based on their ...", "data": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n2022 list of top 50 agtech and foodtech companies is released | AGDAILY\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
    \n
    \n\n\n\n\n
    X
    \n
    \n
    \n\n\n\n\n
    \n\n\n
    \n\n
    \n\n
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n

    News SmartNews Technology

    \n

    2022 list of top 50 agtech and foodtech companies is released

    \n
    \"\"

    By AGDAILY Reporters Published:

    \n\n
    \n
    \n
    \n
    \n
    \n
    \n Image by Mikko Lemola, Shutterstock\n \n
    \n
    \n
    \n
    \n
    \n

    Follow AGDAILY

    \n
    \n
    \n
    \n
    \n\n
    \n
    \n\n
    \n\n
    \n\n
    \n
    \n
    \n
    \n
    \n

    SVG Ventures | THRIVE, a the global agrifood investment and innovation platform headquartered in Silicon Valley, has released its 2022 THRIVE TOP 50 AgTech and FoodTech Reports, which highlight the industry\u2019s leading growth stage companies.\u00a0This year\u2019s report celebrates leading agtech and foodtech companies across sixteen industry categories, with a strong focus on sustainability.

    \n

    The annual ranking, now in its fifth year and in partnership with Forbes, is intended to showcase agtech and foodtech companies that exemplify the best in agriculture and food-focused innovation. The Top 50 selections were made based on their exemplary leadership teams, innovative technologies, investment, and traction. To qualify for the Top 50 listing, a company must have a product in market, have received a minimum of series A funding, and be ready to scale.

    \n

    \n

    New this year is a focus on sustainability. With agriculture playing a pivotal role in progressing global sustainability through innovation, the report highlights 10 sustainable companies based on their environmental impact and effort to form a more sustainable future.

    \n

    The 2022 selections are:

    \n

    THRIVE TOP 50 AgTech

    \n
      \n
    • Agribusiness Marketplace: Bushel, Cibo Technologies, DeHaat, Farmer\u2019s Business Network, Indigo Agriculture, ProducePay
    • \n
    • Animal Technology: Agrivida, InnovaFeed, Native Microbials, Open Blue, Protix, Pure Salmon, Recombinetics, Ynsect
    • \n
    • Controlled Environment Agriculture: 80 Acres Farms, AeroFarms, Bowery, InFarm, Plenty
    • \n
    • Crop Nutrition: Bioenergy Devco, Concentric Agriculture, Pivot Bio, Plant Response, Sound Agriculture
    • \n
    • Crop Protection: AgBiome, Greenlight Biosciences, Invaio Sciences, NewLeaf Symbiotics, Provivi, Terramera, Vestaron
    • \n
    • Farm Management & Insights: Apollo Agriculture, FieldIn, Gro Intelligence, Hartau, Orbital Insight, SeeTree, Semios, Solinftec, Stable, Trace Genomics
    • \n
    • Plant Breeding Platform: Central Coast Agriculture, Front Range Biosciences, Inari, Pairwise, VoloAgri
    • \n
    • Robotics & Automation: Advanced Farm Technologies, Blue White Robotics, FJ Dynamics, Monarch Tractors
    • \n
    \n

    THRIVE TOP 50 FoodTech:

    \n
      \n
    • Alternative Protein: BlueNalu, Califia Farms, Eat Just, Impossible Foods, Mosa Meat, Noblegen, NotCo, Perfect Day, Turtle Tree, Upside Foods, v2food
    • \n
    • Food Quality and Safety: Apeel, Clear labs, Hazel Technologies
    • \n
    • Health & Nutrition: ByHeart, DayTwo, Foodsmart, Kate Farms, Noom, Viome
    • \n
    • Marketplaces & Retail: Blinkit, Bossa Nova Robotics, Brightloom, Imperfect Foods, Instacart, Oda, Picnic, Rappi, Swiggy, Vivino, Weee!, Xingsheng Selected
    • \n
    • Meal Kits: Gousto, Revolution Foods, Sun Basket
    • \n
    • Novel Ingredients: Enough, Geltor, MycoTechnology
    • \n
    • Restaurant Tech: Choco, CloudKitchens, Nextbite, Rebel Foods, REEF Technology
    • \n
    • Supply Chain & Logistics: Deliverect, LeheFood, Ninjacart, Nuro, Soft Robotics, TIPA Sustainable Packaging, Zume
    • \n
    \n

    Six months of research when into the report, and the input from companies and agencies such as Corteva, Kubota, Land O\u2019Lakes, Yamaha, Trimble, the U.S. Department of Agriculture, the Pork Checkoff, and Global Affairs Canada were utilized in the assessments.\u00a0

    \n

    \u201cToday, the world is facing several environmental challenges. Investing in solutions that rethink agriculture and food production systems are key to solving these problems. This year\u2019s list highlights exceptional companies that are shaping the future of food and agriculture through innovation,\u201d said John Hartnett, CEO of SVG Ventures | THRIVE.

    \n\n\n\n\n
    \n
    \n\t\t\t\t\t\t\t\tSponsored Content on AGDaily\n\t\t\t\t\t\t\t
    \n\n
    \n\n
    \n
    \n\n
    \n\n\n\n
    \n\n
    \n
    The views or opinions expressed in this article are those of the author and may not reflect those of AGDAILY.
    \n
    \n
    \n
    \n
    \n\n
    \n
    \n
    \n
    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"}, {"title": "Valueon - Products, Competitors, Financials, Employees, Headquarters ...", "url": "https://www.cbinsights.com/company/valueon", "snippet": "About ValueOn. Valueon focuses on digital business transformations and IT project leadership in the technology sector. The company provides services that involve assisting businesses with their digital transformation processes and managing critical IT and digital projects. It was founded in 2000 and is based in Uster, Switzerland.", "data": "\nValueOn - Products, Competitors, Financials, Employees, Headquarters Locations

    Founded Year

    2000

    About ValueOn

    Valueon focuses on digital business transformations and IT project leadership in the technology sector. The company provides services that involve assisting businesses with their digital transformation processes and managing critical IT and digital projects. It was founded in 2000 and is based in Uster, Switzerland.

    Headquarters Location

    Uster West 44

    Uster, 8610,

    Switzerland

    Loading...

    Loading...

    ValueOn Frequently Asked Questions (FAQ)

    • When was ValueOn founded?

      ValueOn was founded in 2000.

    • Where is ValueOn's headquarters?

      ValueOn's headquarters is located at Uster West 44, Uster.

    Loading...

    Loading...

    CBI websites generally use certain cookies to enable better interactions with our sites and services. Use of these cookies, which may be stored on your device, permits us to improve and customize your experience. You can read more about your cookie choices at our privacy policy\u00a0here. By continuing to use this site you are consenting to these choices.

    "}] \ No newline at end of file diff --git a/ida_prod/backend/backend/__init__.py b/ida_prod/backend/backend/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/ida_prod/backend/backend/asgi.py b/ida_prod/backend/backend/asgi.py deleted file mode 100644 index ed01e6ac..00000000 --- a/ida_prod/backend/backend/asgi.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -ASGI config for backend project. - -It exposes the ASGI callable as a module-level variable named ``application``. - -For more information on this file, see -https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/ -""" - -import os - -from django.core.asgi import get_asgi_application - -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings') - -application = get_asgi_application() diff --git a/ida_prod/backend/backend/settings.py b/ida_prod/backend/backend/settings.py deleted file mode 100644 index c3a7ec98..00000000 --- a/ida_prod/backend/backend/settings.py +++ /dev/null @@ -1,143 +0,0 @@ -""" -Django settings for backend project. - -Generated by 'django-admin startproject' using Django 5.1.7. - -For more information on this file, see -https://docs.djangoproject.com/en/5.1/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/5.1/ref/settings/ -""" - -from pathlib import Path -import os - -PORT = os.environ.get('PORT', 8000) - -# Build paths inside the project like this: BASE_DIR / 'subdir'. -BASE_DIR = Path(__file__).resolve().parent.parent - - -# Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/ - -# SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = 'django-insecure-m_i-mqm0&)-61#*uh!^(7+=ozp*98h-3_joc*c3+885m!p!oz_' - -# SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True - -ALLOWED_HOSTS = ['volucy-gateway-e3d2bzbxdeaaayhz.westeurope-01.azurewebsites.net'] - - -# Application definition - -INSTALLED_APPS = [ - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - - 'corsheaders', - 'rest_framework', -] - -MIDDLEWARE = [ - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'corsheaders.middleware.CorsMiddleware', - 'whitenoise.middleware.WhiteNoiseMiddleware', -] - -MIDDLEWARE.insert(0, 'corsheaders.middleware.CorsMiddleware') - -CORS_ALLOWED_ORIGINS = [ - "https://volucy-gateway-e3d2bzbxdeaaayhz.westeurope-01.azurewebsites.net", - "http://localhost:3000", -] - -CORS_ALLOW_CREDENTIALS = True - -STATIC_URL = "/static/" -STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles") - -ROOT_URLCONF = 'backend.urls' - -TEMPLATES = [ - { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', - ], - }, - }, -] - -WSGI_APPLICATION = 'backend.wsgi.application' - - -# Database -# https://docs.djangoproject.com/en/5.1/ref/settings/#databases - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': BASE_DIR / 'db.sqlite3', - } -} - - -# Password validation -# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators - -AUTH_PASSWORD_VALIDATORS = [ - { - 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', - }, -] - - -# Internationalization -# https://docs.djangoproject.com/en/5.1/topics/i18n/ - -LANGUAGE_CODE = 'en-us' - -TIME_ZONE = 'UTC' - -USE_I18N = True - -USE_TZ = True - - -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/5.1/howto/static-files/ - -STATIC_URL = 'static/' - -# Default primary key field type -# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field - -DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/ida_prod/backend/backend/urls.py b/ida_prod/backend/backend/urls.py deleted file mode 100644 index 3844192f..00000000 --- a/ida_prod/backend/backend/urls.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.urls import path -from .views import sample_api - -urlpatterns = [ - path('api/data/', sample_api), -] diff --git a/ida_prod/backend/backend/views.py b/ida_prod/backend/backend/views.py deleted file mode 100644 index 19961650..00000000 --- a/ida_prod/backend/backend/views.py +++ /dev/null @@ -1,4 +0,0 @@ -from django.http import JsonResponse - -def sample_api(request): - return JsonResponse({"message": "Hello from Django!"}) diff --git a/ida_prod/backend/backend/wsgi.py b/ida_prod/backend/backend/wsgi.py deleted file mode 100644 index 07bda9da..00000000 --- a/ida_prod/backend/backend/wsgi.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -WSGI config for backend project. - -It exposes the WSGI callable as a module-level variable named ``application``. - -For more information on this file, see -https://docs.djangoproject.com/en/5.1/howto/deployment/wsgi/ -""" - -import os - -from django.core.wsgi import get_wsgi_application - -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings') - -application = get_wsgi_application() diff --git a/ida_prod/backend/manage.py b/ida_prod/backend/manage.py deleted file mode 100644 index eb6431e2..00000000 --- a/ida_prod/backend/manage.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python -"""Django's command-line utility for administrative tasks.""" -import os -import sys - - -def main(): - """Run administrative tasks.""" - os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings') - try: - from django.core.management import execute_from_command_line - except ImportError as exc: - raise ImportError( - "Couldn't import Django. Are you sure it's installed and " - "available on your PYTHONPATH environment variable? Did you " - "forget to activate a virtual environment?" - ) from exc - execute_from_command_line(sys.argv) - - -if __name__ == '__main__': - main() diff --git a/ida_prod/frontend/frontend/.gitignore b/ida_prod/frontend/frontend/.gitignore deleted file mode 100644 index 4d29575d..00000000 --- a/ida_prod/frontend/frontend/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# production -/build - -# misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - -npm-debug.log* -yarn-debug.log* -yarn-error.log* diff --git a/ida_prod/frontend/frontend/README.md b/ida_prod/frontend/frontend/README.md deleted file mode 100644 index 58beeacc..00000000 --- a/ida_prod/frontend/frontend/README.md +++ /dev/null @@ -1,70 +0,0 @@ -# Getting Started with Create React App - -This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). - -## Available Scripts - -In the project directory, you can run: - -### `npm start` - -Runs the app in the development mode.\ -Open [http://localhost:3000](http://localhost:3000) to view it in your browser. - -The page will reload when you make changes.\ -You may also see any lint errors in the console. - -### `npm test` - -Launches the test runner in the interactive watch mode.\ -See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. - -### `npm run build` - -Builds the app for production to the `build` folder.\ -It correctly bundles React in production mode and optimizes the build for the best performance. - -The build is minified and the filenames include the hashes.\ -Your app is ready to be deployed! - -See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. - -### `npm run eject` - -**Note: this is a one-way operation. Once you `eject`, you can't go back!** - -If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. - -Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own. - -You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it. - -## Learn More - -You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). - -To learn React, check out the [React documentation](https://reactjs.org/). - -### Code Splitting - -This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting) - -### Analyzing the Bundle Size - -This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size) - -### Making a Progressive Web App - -This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app) - -### Advanced Configuration - -This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration) - -### Deployment - -This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment) - -### `npm run build` fails to minify - -This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify) diff --git a/ida_prod/frontend/frontend/package-lock.json b/ida_prod/frontend/frontend/package-lock.json deleted file mode 100644 index c9ba5fd2..00000000 --- a/ida_prod/frontend/frontend/package-lock.json +++ /dev/null @@ -1,16212 +0,0 @@ -{ - "name": "frontend", - "version": "0.1.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "frontend", - "version": "0.1.0", - "dependencies": { - "@testing-library/dom": "^10.4.0", - "@testing-library/jest-dom": "^6.6.3", - "@testing-library/react": "^16.2.0", - "@testing-library/user-event": "^13.5.0", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "react-scripts": "5.0.1", - "web-vitals": "^2.1.4" - } - }, - "node_modules/@adobe/css-tools": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.2.tgz", - "integrity": "sha512-baYZExFpsdkBNuvGKTKWCwKH57HRZLVtycZS05WTQNVOiXVSeAki3nU35zlRbToeMW8aHlJfyS+1C4BOv27q0A==" - }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", - "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.9.tgz", - "integrity": "sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.9", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.9", - "@babel/parser": "^7.26.9", - "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.9", - "@babel/types": "^7.26.9", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/eslint-parser": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.26.8.tgz", - "integrity": "sha512-3tBctaHRW6xSub26z7n8uyOTwwUsCdvIug/oxBH9n6yCO5hMj2vwDJAo7RbBMKrM7P+W2j61zLKviJQFGOYKMg==", - "dependencies": { - "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", - "eslint-visitor-keys": "^2.1.0", - "semver": "^6.3.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || >=14.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.11.0", - "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" - } - }, - "node_modules/@babel/eslint-parser/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "engines": { - "node": ">=10" - } - }, - "node_modules/@babel/eslint-parser/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.9.tgz", - "integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==", - "dependencies": { - "@babel/parser": "^7.26.9", - "@babel/types": "^7.26.9", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", - "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", - "dependencies": { - "@babel/compat-data": "^7.26.5", - "@babel/helper-validator-option": "^7.25.9", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.26.9.tgz", - "integrity": "sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-member-expression-to-functions": "^7.25.9", - "@babel/helper-optimise-call-expression": "^7.25.9", - "@babel/helper-replace-supers": "^7.26.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/traverse": "^7.26.9", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz", - "integrity": "sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "regexpu-core": "^6.2.0", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", - "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", - "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", - "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", - "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-wrap-function": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz", - "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==", - "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.25.9", - "@babel/helper-optimise-call-expression": "^7.25.9", - "@babel/traverse": "^7.26.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", - "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", - "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", - "dependencies": { - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.9.tgz", - "integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==", - "dependencies": { - "@babel/template": "^7.26.9", - "@babel/types": "^7.26.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.9.tgz", - "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==", - "dependencies": { - "@babel/types": "^7.26.9" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", - "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", - "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", - "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", - "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/plugin-transform-optional-chaining": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", - "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.25.9.tgz", - "integrity": "sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g==", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/plugin-syntax-decorators": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", - "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead.", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", - "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-decorators": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.25.9.tgz", - "integrity": "sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-flow": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz", - "integrity": "sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", - "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", - "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", - "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", - "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-unicode-sets-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", - "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", - "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz", - "integrity": "sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/helper-remap-async-to-generator": "^7.25.9", - "@babel/traverse": "^7.26.8" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", - "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-remap-async-to-generator": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz", - "integrity": "sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz", - "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz", - "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", - "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", - "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-replace-supers": "^7.25.9", - "@babel/traverse": "^7.25.9", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", - "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/template": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", - "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", - "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", - "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz", - "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", - "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz", - "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", - "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-flow-strip-types": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.26.5.tgz", - "integrity": "sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/plugin-syntax-flow": "^7.26.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz", - "integrity": "sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", - "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", - "dependencies": { - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", - "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", - "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", - "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", - "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", - "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", - "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", - "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", - "dependencies": { - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", - "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", - "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", - "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", - "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", - "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", - "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.26.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz", - "integrity": "sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", - "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", - "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", - "dependencies": { - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/plugin-transform-parameters": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", - "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-replace-supers": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", - "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz", - "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", - "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz", - "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", - "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", - "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-constant-elements": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.25.9.tgz", - "integrity": "sha512-Ncw2JFsJVuvfRsa2lSHiC55kETQVLSnsYGQ1JDDwkUeWGTL/8Tom8aLTnlqgoeuopWrbbGndrc9AlLYrIosrow==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz", - "integrity": "sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz", - "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/plugin-syntax-jsx": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-development": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.25.9.tgz", - "integrity": "sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw==", - "dependencies": { - "@babel/plugin-transform-react-jsx": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-pure-annotations": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.25.9.tgz", - "integrity": "sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz", - "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "regenerator-transform": "^0.15.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", - "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", - "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-runtime": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.9.tgz", - "integrity": "sha512-Jf+8y9wXQbbxvVYTM8gO5oEF2POdNji0NMltEkG7FtmzD9PVz7/lxpqSdTvwsjTMU5HIHuDVNf2SOxLkWi+wPQ==", - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.26.5", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.6", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-runtime/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", - "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2", - "core-js-compat": "^3.38.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", - "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", - "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", - "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz", - "integrity": "sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.26.7.tgz", - "integrity": "sha512-jfoTXXZTgGg36BmhqT3cAYK5qkmqvJpvNrPhaK/52Vgjhw4Rq29s9UqpWWV0D6yuRmgiFH/BUVlkl96zJWqnaw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typescript": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.8.tgz", - "integrity": "sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/plugin-syntax-typescript": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", - "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", - "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", - "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", - "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/preset-env": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.9.tgz", - "integrity": "sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==", - "dependencies": { - "@babel/compat-data": "^7.26.8", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/helper-validator-option": "^7.25.9", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.26.0", - "@babel/plugin-syntax-import-attributes": "^7.26.0", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.25.9", - "@babel/plugin-transform-async-generator-functions": "^7.26.8", - "@babel/plugin-transform-async-to-generator": "^7.25.9", - "@babel/plugin-transform-block-scoped-functions": "^7.26.5", - "@babel/plugin-transform-block-scoping": "^7.25.9", - "@babel/plugin-transform-class-properties": "^7.25.9", - "@babel/plugin-transform-class-static-block": "^7.26.0", - "@babel/plugin-transform-classes": "^7.25.9", - "@babel/plugin-transform-computed-properties": "^7.25.9", - "@babel/plugin-transform-destructuring": "^7.25.9", - "@babel/plugin-transform-dotall-regex": "^7.25.9", - "@babel/plugin-transform-duplicate-keys": "^7.25.9", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", - "@babel/plugin-transform-dynamic-import": "^7.25.9", - "@babel/plugin-transform-exponentiation-operator": "^7.26.3", - "@babel/plugin-transform-export-namespace-from": "^7.25.9", - "@babel/plugin-transform-for-of": "^7.26.9", - "@babel/plugin-transform-function-name": "^7.25.9", - "@babel/plugin-transform-json-strings": "^7.25.9", - "@babel/plugin-transform-literals": "^7.25.9", - "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", - "@babel/plugin-transform-member-expression-literals": "^7.25.9", - "@babel/plugin-transform-modules-amd": "^7.25.9", - "@babel/plugin-transform-modules-commonjs": "^7.26.3", - "@babel/plugin-transform-modules-systemjs": "^7.25.9", - "@babel/plugin-transform-modules-umd": "^7.25.9", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", - "@babel/plugin-transform-new-target": "^7.25.9", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.26.6", - "@babel/plugin-transform-numeric-separator": "^7.25.9", - "@babel/plugin-transform-object-rest-spread": "^7.25.9", - "@babel/plugin-transform-object-super": "^7.25.9", - "@babel/plugin-transform-optional-catch-binding": "^7.25.9", - "@babel/plugin-transform-optional-chaining": "^7.25.9", - "@babel/plugin-transform-parameters": "^7.25.9", - "@babel/plugin-transform-private-methods": "^7.25.9", - "@babel/plugin-transform-private-property-in-object": "^7.25.9", - "@babel/plugin-transform-property-literals": "^7.25.9", - "@babel/plugin-transform-regenerator": "^7.25.9", - "@babel/plugin-transform-regexp-modifiers": "^7.26.0", - "@babel/plugin-transform-reserved-words": "^7.25.9", - "@babel/plugin-transform-shorthand-properties": "^7.25.9", - "@babel/plugin-transform-spread": "^7.25.9", - "@babel/plugin-transform-sticky-regex": "^7.25.9", - "@babel/plugin-transform-template-literals": "^7.26.8", - "@babel/plugin-transform-typeof-symbol": "^7.26.7", - "@babel/plugin-transform-unicode-escapes": "^7.25.9", - "@babel/plugin-transform-unicode-property-regex": "^7.25.9", - "@babel/plugin-transform-unicode-regex": "^7.25.9", - "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.11.0", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.40.0", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/preset-modules": { - "version": "0.1.6-no-external-plugins", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", - "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/preset-react": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.26.3.tgz", - "integrity": "sha512-Nl03d6T9ky516DGK2YMxrTqvnpUW63TnJMOMonj+Zae0JiPC5BC9xPMSL6L8fiSpA5vP88qfygavVQvnLp+6Cw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-validator-option": "^7.25.9", - "@babel/plugin-transform-react-display-name": "^7.25.9", - "@babel/plugin-transform-react-jsx": "^7.25.9", - "@babel/plugin-transform-react-jsx-development": "^7.25.9", - "@babel/plugin-transform-react-pure-annotations": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-typescript": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz", - "integrity": "sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-validator-option": "^7.25.9", - "@babel/plugin-syntax-jsx": "^7.25.9", - "@babel/plugin-transform-modules-commonjs": "^7.25.9", - "@babel/plugin-transform-typescript": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.9.tgz", - "integrity": "sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", - "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.26.9", - "@babel/types": "^7.26.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.9.tgz", - "integrity": "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==", - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.9", - "@babel/parser": "^7.26.9", - "@babel/template": "^7.26.9", - "@babel/types": "^7.26.9", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz", - "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==", - "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" - }, - "node_modules/@csstools/normalize.css": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-12.1.1.tgz", - "integrity": "sha512-YAYeJ+Xqh7fUou1d1j9XHl44BmsuThiTr4iNrgCQ3J27IbhXsxXDGZ1cXv8Qvs99d4rBbLiSKy3+WZiet32PcQ==" - }, - "node_modules/@csstools/postcss-cascade-layers": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.1.1.tgz", - "integrity": "sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==", - "dependencies": { - "@csstools/selector-specificity": "^2.0.2", - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-color-function": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.1.1.tgz", - "integrity": "sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==", - "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-font-format-keywords": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.1.tgz", - "integrity": "sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-hwb-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.2.tgz", - "integrity": "sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-ic-unit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.1.tgz", - "integrity": "sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==", - "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-is-pseudo-class": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.7.tgz", - "integrity": "sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==", - "dependencies": { - "@csstools/selector-specificity": "^2.0.0", - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-nested-calc": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-1.0.0.tgz", - "integrity": "sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-normalize-display-values": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.1.tgz", - "integrity": "sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-oklab-function": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.1.tgz", - "integrity": "sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==", - "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-progressive-custom-properties": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz", - "integrity": "sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.3" - } - }, - "node_modules/@csstools/postcss-stepped-value-functions": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.1.tgz", - "integrity": "sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-text-decoration-shorthand": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-1.0.0.tgz", - "integrity": "sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-trigonometric-functions": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-1.0.2.tgz", - "integrity": "sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-unset-value": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz", - "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==", - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/selector-specificity": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", - "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", - "engines": { - "node": "^14 || ^16 || >=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss-selector-parser": "^6.0.10" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", - "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead" - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.5.1.tgz", - "integrity": "sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==", - "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/core": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.5.1.tgz", - "integrity": "sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==", - "dependencies": { - "@jest/console": "^27.5.1", - "@jest/reporters": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^27.5.1", - "jest-config": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-resolve-dependencies": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "jest-watcher": "^27.5.1", - "micromatch": "^4.0.4", - "rimraf": "^3.0.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/environment": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.5.1.tgz", - "integrity": "sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==", - "dependencies": { - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/fake-timers": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.5.1.tgz", - "integrity": "sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==", - "dependencies": { - "@jest/types": "^27.5.1", - "@sinonjs/fake-timers": "^8.0.1", - "@types/node": "*", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/globals": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.5.1.tgz", - "integrity": "sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==", - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/types": "^27.5.1", - "expect": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/reporters": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.5.1.tgz", - "integrity": "sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.2", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^5.1.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-haste-map": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "slash": "^3.0.0", - "source-map": "^0.6.0", - "string-length": "^4.0.1", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^8.1.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/reporters/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@jest/schemas": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", - "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", - "dependencies": { - "@sinclair/typebox": "^0.24.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/@jest/source-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.5.1.tgz", - "integrity": "sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==", - "dependencies": { - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9", - "source-map": "^0.6.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/source-map/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@jest/test-result": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.5.1.tgz", - "integrity": "sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==", - "dependencies": { - "@jest/console": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz", - "integrity": "sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==", - "dependencies": { - "@jest/test-result": "^27.5.1", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-runtime": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.5.1.tgz", - "integrity": "sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==", - "dependencies": { - "@babel/core": "^7.1.0", - "@jest/types": "^27.5.1", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-util": "^27.5.1", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/transform/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" - }, - "node_modules/@jest/transform/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", - "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==" - }, - "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { - "version": "5.1.1-v1", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", - "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", - "dependencies": { - "eslint-scope": "5.1.1" - } - }, - "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@nicolo-ribaudo/eslint-scope-5-internals/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@pmmmwh/react-refresh-webpack-plugin": { - "version": "0.5.15", - "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.15.tgz", - "integrity": "sha512-LFWllMA55pzB9D34w/wXUCf8+c+IYKuJDgxiZ3qMhl64KRMBHYM1I3VdGaD2BV5FNPV2/S2596bppxHbv2ZydQ==", - "dependencies": { - "ansi-html": "^0.0.9", - "core-js-pure": "^3.23.3", - "error-stack-parser": "^2.0.6", - "html-entities": "^2.1.0", - "loader-utils": "^2.0.4", - "schema-utils": "^4.2.0", - "source-map": "^0.7.3" - }, - "engines": { - "node": ">= 10.13" - }, - "peerDependencies": { - "@types/webpack": "4.x || 5.x", - "react-refresh": ">=0.10.0 <1.0.0", - "sockjs-client": "^1.4.0", - "type-fest": ">=0.17.0 <5.0.0", - "webpack": ">=4.43.0 <6.0.0", - "webpack-dev-server": "3.x || 4.x || 5.x", - "webpack-hot-middleware": "2.x", - "webpack-plugin-serve": "0.x || 1.x" - }, - "peerDependenciesMeta": { - "@types/webpack": { - "optional": true - }, - "sockjs-client": { - "optional": true - }, - "type-fest": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - }, - "webpack-hot-middleware": { - "optional": true - }, - "webpack-plugin-serve": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-babel": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", - "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", - "dependencies": { - "@babel/helper-module-imports": "^7.10.4", - "@rollup/pluginutils": "^3.1.0" - }, - "engines": { - "node": ">= 10.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0", - "@types/babel__core": "^7.1.9", - "rollup": "^1.20.0||^2.0.0" - }, - "peerDependenciesMeta": { - "@types/babel__core": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "11.2.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", - "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", - "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "@types/resolve": "1.17.1", - "builtin-modules": "^3.1.0", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.19.0" - }, - "engines": { - "node": ">= 10.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0" - } - }, - "node_modules/@rollup/plugin-replace": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", - "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", - "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "magic-string": "^0.25.7" - }, - "peerDependencies": { - "rollup": "^1.20.0 || ^2.0.0" - } - }, - "node_modules/@rollup/pluginutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", - "dependencies": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0" - } - }, - "node_modules/@rollup/pluginutils/node_modules/@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" - }, - "node_modules/@rtsao/scc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", - "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==" - }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.5.tgz", - "integrity": "sha512-kkKUDVlII2DQiKy7UstOR1ErJP8kUKAQ4oa+SQtM0K+lPdmmjj0YnnxBgtTVYH7mUKtbsxeFC9y0AmK7Yb78/A==" - }, - "node_modules/@sinclair/typebox": { - "version": "0.24.51", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", - "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==" - }, - "node_modules/@sinonjs/commons": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", - "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@surma/rollup-plugin-off-main-thread": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", - "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", - "dependencies": { - "ejs": "^3.1.6", - "json5": "^2.2.0", - "magic-string": "^0.25.0", - "string.prototype.matchall": "^4.0.6" - } - }, - "node_modules/@svgr/babel-plugin-add-jsx-attribute": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz", - "integrity": "sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==", - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz", - "integrity": "sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==", - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz", - "integrity": "sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==", - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz", - "integrity": "sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/babel-plugin-svg-dynamic-title": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz", - "integrity": "sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==", - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/babel-plugin-svg-em-dimensions": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz", - "integrity": "sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==", - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/babel-plugin-transform-react-native-svg": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz", - "integrity": "sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==", - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/babel-plugin-transform-svg-component": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz", - "integrity": "sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/babel-preset": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-5.5.0.tgz", - "integrity": "sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==", - "dependencies": { - "@svgr/babel-plugin-add-jsx-attribute": "^5.4.0", - "@svgr/babel-plugin-remove-jsx-attribute": "^5.4.0", - "@svgr/babel-plugin-remove-jsx-empty-expression": "^5.0.1", - "@svgr/babel-plugin-replace-jsx-attribute-value": "^5.0.1", - "@svgr/babel-plugin-svg-dynamic-title": "^5.4.0", - "@svgr/babel-plugin-svg-em-dimensions": "^5.4.0", - "@svgr/babel-plugin-transform-react-native-svg": "^5.4.0", - "@svgr/babel-plugin-transform-svg-component": "^5.5.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/core": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/core/-/core-5.5.0.tgz", - "integrity": "sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==", - "dependencies": { - "@svgr/plugin-jsx": "^5.5.0", - "camelcase": "^6.2.0", - "cosmiconfig": "^7.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/hast-util-to-babel-ast": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz", - "integrity": "sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==", - "dependencies": { - "@babel/types": "^7.12.6" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/plugin-jsx": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz", - "integrity": "sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==", - "dependencies": { - "@babel/core": "^7.12.3", - "@svgr/babel-preset": "^5.5.0", - "@svgr/hast-util-to-babel-ast": "^5.5.0", - "svg-parser": "^2.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/plugin-svgo": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz", - "integrity": "sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==", - "dependencies": { - "cosmiconfig": "^7.0.0", - "deepmerge": "^4.2.2", - "svgo": "^1.2.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@svgr/webpack": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-5.5.0.tgz", - "integrity": "sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==", - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/plugin-transform-react-constant-elements": "^7.12.1", - "@babel/preset-env": "^7.12.1", - "@babel/preset-react": "^7.12.5", - "@svgr/core": "^5.5.0", - "@svgr/plugin-jsx": "^5.5.0", - "@svgr/plugin-svgo": "^5.5.0", - "loader-utils": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/gregberge" - } - }, - "node_modules/@testing-library/dom": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", - "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/runtime": "^7.12.5", - "@types/aria-query": "^5.0.1", - "aria-query": "5.3.0", - "chalk": "^4.1.0", - "dom-accessibility-api": "^0.5.9", - "lz-string": "^1.5.0", - "pretty-format": "^27.0.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@testing-library/dom/node_modules/aria-query": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", - "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/@testing-library/jest-dom": { - "version": "6.6.3", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.3.tgz", - "integrity": "sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==", - "dependencies": { - "@adobe/css-tools": "^4.4.0", - "aria-query": "^5.0.0", - "chalk": "^3.0.0", - "css.escape": "^1.5.1", - "dom-accessibility-api": "^0.6.3", - "lodash": "^4.17.21", - "redent": "^3.0.0" - }, - "engines": { - "node": ">=14", - "npm": ">=6", - "yarn": ">=1" - } - }, - "node_modules/@testing-library/jest-dom/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", - "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==" - }, - "node_modules/@testing-library/react": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.2.0.tgz", - "integrity": "sha512-2cSskAvA1QNtKc8Y9VJQRv0tm3hLVgxRGDB+KYhIaPQJ1I+RHbhIXcM+zClKXzMes/wshsMVzf4B9vS4IZpqDQ==", - "dependencies": { - "@babel/runtime": "^7.12.5" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@testing-library/dom": "^10.0.0", - "@types/react": "^18.0.0 || ^19.0.0", - "@types/react-dom": "^18.0.0 || ^19.0.0", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, - "node_modules/@testing-library/user-event": { - "version": "13.5.0", - "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-13.5.0.tgz", - "integrity": "sha512-5Kwtbo3Y/NowpkbRuSepbyMFkZmHgD+vPzYB/RJ4oxt5Gj/avFFBYjhw27cqSVPVw/3a67NK1PbiIr9k4Gwmdg==", - "dependencies": { - "@babel/runtime": "^7.12.5" - }, - "engines": { - "node": ">=10", - "npm": ">=6" - }, - "peerDependencies": { - "@testing-library/dom": ">=7.21.4" - } - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/@trysound/sax": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/@types/aria-query": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", - "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==" - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "node_modules/@types/bonjour": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", - "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/connect-history-api-fallback": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", - "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", - "dependencies": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "node_modules/@types/eslint": { - "version": "8.56.12", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.12.tgz", - "integrity": "sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" - }, - "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "node_modules/@types/express-serve-static-core": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.6.tgz", - "integrity": "sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/express/node_modules/@types/express-serve-static-core": { - "version": "4.19.6", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", - "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==" - }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" - }, - "node_modules/@types/http-proxy": { - "version": "1.17.16", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.16.tgz", - "integrity": "sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" - }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" - }, - "node_modules/@types/node": { - "version": "22.13.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", - "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/@types/node-forge": { - "version": "1.3.11", - "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", - "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" - }, - "node_modules/@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==" - }, - "node_modules/@types/q": { - "version": "1.5.8", - "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.8.tgz", - "integrity": "sha512-hroOstUScF6zhIi+5+x0dzqrHA1EJi+Irri6b1fxolMTqqHIV/Cg77EtnQcZqZCu8hR3mX2BzIxN4/GzI68Kfw==" - }, - "node_modules/@types/qs": { - "version": "6.9.18", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", - "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==" - }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" - }, - "node_modules/@types/resolve": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", - "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==" - }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==" - }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "dependencies": { - "@types/mime": "^1", - "@types/node": "*" - } - }, - "node_modules/@types/serve-index": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", - "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", - "dependencies": { - "@types/express": "*" - } - }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", - "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" - } - }, - "node_modules/@types/sockjs": { - "version": "0.3.36", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", - "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==" - }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==" - }, - "node_modules/@types/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/yargs": { - "version": "16.0.9", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", - "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", - "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", - "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/type-utils": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", - "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==", - "dependencies": { - "@typescript-eslint/utils": "5.62.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", - "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", - "dependencies": { - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", - "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", - "dependencies": { - "@typescript-eslint/typescript-estree": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==" - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "dependencies": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==" - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==" - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==" - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==" - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==" - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" - }, - "node_modules/abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "deprecated": "Use your platform's native atob() and btoa() methods instead" - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/accepts/node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dependencies": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - } - }, - "node_modules/acorn-globals/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/address": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", - "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/adjust-sourcemap-loader": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", - "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", - "dependencies": { - "loader-utils": "^2.0.0", - "regex-parser": "^2.2.11" - }, - "engines": { - "node": ">=8.9" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-html": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.9.tgz", - "integrity": "sha512-ozbS3LuenHVxNRh/wdnN16QapUHzauqSomAl1jwwJRRsGwFwtj644lIhxfWu0Fy0acCij2+AEgHvjscq3dlVXg==", - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "node_modules/ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "engines": [ - "node >= 0.8.0" - ], - "bin": { - "ansi-html": "bin/ansi-html" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/aria-query": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", - "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", - "dependencies": { - "call-bound": "^1.0.3", - "is-array-buffer": "^3.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" - }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.findlast": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", - "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", - "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.reduce": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.7.tgz", - "integrity": "sha512-mzmiUCVwtiD4lgxYP8g7IYy8El8p2CSMePvIbTS7gchKir/L1fgJrk0yDKmAX6mnRQFKNADYIk8nNlTris5H1Q==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-array-method-boxes-properly": "^1.0.0", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", - "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", - "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" - }, - "node_modules/ast-types-flow": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", - "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==" - }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" - }, - "node_modules/async-function": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", - "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/autoprefixer": { - "version": "10.4.20", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", - "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "browserslist": "^4.23.3", - "caniuse-lite": "^1.0.30001646", - "fraction.js": "^4.3.7", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/axe-core": { - "version": "4.10.3", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.3.tgz", - "integrity": "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==", - "engines": { - "node": ">=4" - } - }, - "node_modules/axobject-query": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", - "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/babel-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz", - "integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==", - "dependencies": { - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-loader": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.4.1.tgz", - "integrity": "sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==", - "dependencies": { - "find-cache-dir": "^3.3.1", - "loader-utils": "^2.0.4", - "make-dir": "^3.1.0", - "schema-utils": "^2.6.5" - }, - "engines": { - "node": ">= 8.9" - }, - "peerDependencies": { - "@babel/core": "^7.0.0", - "webpack": ">=2" - } - }, - "node_modules/babel-loader/node_modules/schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dependencies": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz", - "integrity": "sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==", - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/babel-plugin-macros": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", - "dependencies": { - "@babel/runtime": "^7.12.5", - "cosmiconfig": "^7.0.0", - "resolve": "^1.19.0" - }, - "engines": { - "node": ">=10", - "npm": ">=6" - } - }, - "node_modules/babel-plugin-named-asset-import": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz", - "integrity": "sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==", - "peerDependencies": { - "@babel/core": "^7.1.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.12", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz", - "integrity": "sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==", - "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.3", - "semver": "^6.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz", - "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.3", - "core-js-compat": "^3.40.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz", - "integrity": "sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.3" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-transform-react-remove-prop-types": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", - "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==" - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", - "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz", - "integrity": "sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==", - "dependencies": { - "babel-plugin-jest-hoist": "^27.5.1", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-react-app": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-10.1.0.tgz", - "integrity": "sha512-f9B1xMdnkCIqe+2dHrJsoQFRz7reChaAHE/65SdaykPklQqhme2WaC08oD3is77x9ff98/9EazAKFDZv5rFEQg==", - "dependencies": { - "@babel/core": "^7.16.0", - "@babel/plugin-proposal-class-properties": "^7.16.0", - "@babel/plugin-proposal-decorators": "^7.16.4", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0", - "@babel/plugin-proposal-numeric-separator": "^7.16.0", - "@babel/plugin-proposal-optional-chaining": "^7.16.0", - "@babel/plugin-proposal-private-methods": "^7.16.0", - "@babel/plugin-proposal-private-property-in-object": "^7.16.7", - "@babel/plugin-transform-flow-strip-types": "^7.16.0", - "@babel/plugin-transform-react-display-name": "^7.16.0", - "@babel/plugin-transform-runtime": "^7.16.4", - "@babel/preset-env": "^7.16.4", - "@babel/preset-react": "^7.16.0", - "@babel/preset-typescript": "^7.16.0", - "@babel/runtime": "^7.16.3", - "babel-plugin-macros": "^3.1.0", - "babel-plugin-transform-react-remove-prop-types": "^0.4.24" - } - }, - "node_modules/babel-preset-react-app/node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz", - "integrity": "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead.", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.21.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" - }, - "node_modules/bfj": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.1.0.tgz", - "integrity": "sha512-I6MMLkn+anzNdCUp9hMRyui1HaNEUCco50lxbvNS4+EyXg8lN3nJ48PjPWtbH8UVS9CuMoaKE9U2V3l29DaRQw==", - "dependencies": { - "bluebird": "^3.7.2", - "check-types": "^11.2.3", - "hoopy": "^0.1.4", - "jsonpath": "^1.1.1", - "tryer": "^1.0.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "engines": { - "node": "*" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/body-parser/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/bonjour-service": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", - "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" - }, - "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/call-bind": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", - "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/caniuse-api": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", - "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", - "dependencies": { - "browserslist": "^4.0.0", - "caniuse-lite": "^1.0.0", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001702", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001702.tgz", - "integrity": "sha512-LoPe/D7zioC0REI5W73PeR1e1MLCipRGq/VkovJnd6Df+QVqT+vT33OXCp8QUd7kA7RZrHWxb1B36OQKI/0gOA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/case-sensitive-paths-webpack-plugin": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", - "integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "engines": { - "node": ">=10" - } - }, - "node_modules/check-types": { - "version": "11.2.3", - "resolved": "https://registry.npmjs.org/check-types/-/check-types-11.2.3.tgz", - "integrity": "sha512-+67P1GkJRaxQD6PKK0Et9DhwQB+vGg3PM5+aavopCpZT1lj9jeqfvpgTLAWErNj8qApkkmXlu/Ug74kmhagkXg==" - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "engines": { - "node": ">=6.0" - } - }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/cjs-module-lexer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", - "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==" - }, - "node_modules/clean-css": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", - "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", - "dependencies": { - "source-map": "~0.6.0" - }, - "engines": { - "node": ">= 10.0" - } - }, - "node_modules/clean-css/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/coa": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", - "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", - "dependencies": { - "@types/q": "^1.5.1", - "chalk": "^2.4.1", - "q": "^1.1.2" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/coa/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/coa/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/coa/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/coa/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/coa/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/coa/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/coa/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==" - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "engines": { - "node": ">= 12" - } - }, - "node_modules/common-tags": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" - }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dependencies": { - "mime-db": ">= 1.43.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/compression": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.0.tgz", - "integrity": "sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==", - "dependencies": { - "bytes": "3.1.2", - "compressible": "~2.0.18", - "debug": "2.6.9", - "negotiator": "~0.6.4", - "on-headers": "~1.0.2", - "safe-buffer": "5.2.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/compression/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/confusing-browser-globals": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", - "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==" - }, - "node_modules/connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" - }, - "node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" - }, - "node_modules/core-js": { - "version": "3.41.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.41.0.tgz", - "integrity": "sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==", - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-js-compat": { - "version": "3.41.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.41.0.tgz", - "integrity": "sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==", - "dependencies": { - "browserslist": "^4.24.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-js-pure": { - "version": "3.41.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.41.0.tgz", - "integrity": "sha512-71Gzp96T9YPk63aUvE5Q5qP+DryB4ZloUZPSOebGM88VNw8VNfvdA7z6kGA8iGOTEzAomsRidp4jXSmUIJsL+Q==", - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/css-blank-pseudo": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", - "integrity": "sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==", - "dependencies": { - "postcss-selector-parser": "^6.0.9" - }, - "bin": { - "css-blank-pseudo": "dist/cli.cjs" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/css-declaration-sorter": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", - "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.0.9" - } - }, - "node_modules/css-has-pseudo": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz", - "integrity": "sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==", - "dependencies": { - "postcss-selector-parser": "^6.0.9" - }, - "bin": { - "css-has-pseudo": "dist/cli.cjs" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/css-loader": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", - "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", - "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.33", - "postcss-modules-extract-imports": "^3.1.0", - "postcss-modules-local-by-default": "^4.0.5", - "postcss-modules-scope": "^3.2.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/css-minimizer-webpack-plugin": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz", - "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==", - "dependencies": { - "cssnano": "^5.0.6", - "jest-worker": "^27.0.2", - "postcss": "^8.3.5", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "@parcel/css": { - "optional": true - }, - "clean-css": { - "optional": true - }, - "csso": { - "optional": true - }, - "esbuild": { - "optional": true - } - } - }, - "node_modules/css-minimizer-webpack-plugin/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/css-prefers-color-scheme": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", - "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", - "bin": { - "css-prefers-color-scheme": "dist/cli.cjs" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-select-base-adapter": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", - "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" - }, - "node_modules/css-tree": { - "version": "1.0.0-alpha.37", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", - "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", - "dependencies": { - "mdn-data": "2.0.4", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/css-tree/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css.escape": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", - "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==" - }, - "node_modules/cssdb": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.11.2.tgz", - "integrity": "sha512-lhQ32TFkc1X4eTefGfYPvgovRSzIMofHkigfH8nWtyRL4XJLsRhJFreRvEgKzept7x1rjBuy3J/MurXLaFxW/A==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - } - ] - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cssnano": { - "version": "5.1.15", - "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", - "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", - "dependencies": { - "cssnano-preset-default": "^5.2.14", - "lilconfig": "^2.0.3", - "yaml": "^1.10.2" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/cssnano" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-preset-default": { - "version": "5.2.14", - "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", - "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", - "dependencies": { - "css-declaration-sorter": "^6.3.1", - "cssnano-utils": "^3.1.0", - "postcss-calc": "^8.2.3", - "postcss-colormin": "^5.3.1", - "postcss-convert-values": "^5.1.3", - "postcss-discard-comments": "^5.1.2", - "postcss-discard-duplicates": "^5.1.0", - "postcss-discard-empty": "^5.1.1", - "postcss-discard-overridden": "^5.1.0", - "postcss-merge-longhand": "^5.1.7", - "postcss-merge-rules": "^5.1.4", - "postcss-minify-font-values": "^5.1.0", - "postcss-minify-gradients": "^5.1.1", - "postcss-minify-params": "^5.1.4", - "postcss-minify-selectors": "^5.2.1", - "postcss-normalize-charset": "^5.1.0", - "postcss-normalize-display-values": "^5.1.0", - "postcss-normalize-positions": "^5.1.1", - "postcss-normalize-repeat-style": "^5.1.1", - "postcss-normalize-string": "^5.1.0", - "postcss-normalize-timing-functions": "^5.1.0", - "postcss-normalize-unicode": "^5.1.1", - "postcss-normalize-url": "^5.1.0", - "postcss-normalize-whitespace": "^5.1.1", - "postcss-ordered-values": "^5.1.3", - "postcss-reduce-initial": "^5.1.2", - "postcss-reduce-transforms": "^5.1.0", - "postcss-svgo": "^5.1.0", - "postcss-unique-selectors": "^5.1.1" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/cssnano-utils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", - "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/csso": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", - "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", - "dependencies": { - "css-tree": "^1.1.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/csso/node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/csso/node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" - }, - "node_modules/csso/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==" - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" - }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" - }, - "node_modules/data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", - "dependencies": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/data-view-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", - "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/inspect-js" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decimal.js": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", - "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==" - }, - "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==" - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "engines": { - "node": ">=8" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" - }, - "node_modules/detect-port-alt": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", - "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", - "dependencies": { - "address": "^1.0.1", - "debug": "^2.6.0" - }, - "bin": { - "detect": "bin/detect-port", - "detect-port": "bin/detect-port" - }, - "engines": { - "node": ">= 4.2.1" - } - }, - "node_modules/detect-port-alt/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/detect-port-alt/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" - }, - "node_modules/diff-sequences": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.5.1.tgz", - "integrity": "sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==", - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" - }, - "node_modules/dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "dependencies": { - "@leichtgewicht/ip-codec": "^2.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-accessibility-api": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", - "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==" - }, - "node_modules/dom-converter": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", - "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", - "dependencies": { - "utila": "~0.4" - } - }, - "node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ] - }, - "node_modules/domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", - "deprecated": "Use your platform's native DOMException instead", - "dependencies": { - "webidl-conversions": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/domexception/node_modules/webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dependencies": { - "domelementtype": "^2.2.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", - "engines": { - "node": ">=10" - } - }, - "node_modules/dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==" - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" - }, - "node_modules/ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" - }, - "node_modules/ejs": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", - "dependencies": { - "jake": "^10.8.5" - }, - "bin": { - "ejs": "bin/cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.113", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.113.tgz", - "integrity": "sha512-wjT2O4hX+wdWPJ76gWSkMhcHAV2PTMX+QetUCPYEdCIe+cxmgzzSSiGRCKW8nuh4mwKZlpv0xvoW7OF2X+wmHg==" - }, - "node_modules/emittery": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", - "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.18.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", - "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/error-stack-parser": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", - "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", - "dependencies": { - "stackframe": "^1.3.4" - } - }, - "node_modules/es-abstract": { - "version": "1.23.9", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", - "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.0", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-regex": "^1.2.1", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.0", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.3", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.18" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-iterator-helpers": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", - "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.6", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.3", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.6", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "iterator.prototype": "^1.1.4", - "safe-array-concat": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-module-lexer": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", - "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==" - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", - "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-to-primitive": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", - "dependencies": { - "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/escodegen/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-react-app": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz", - "integrity": "sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==", - "dependencies": { - "@babel/core": "^7.16.0", - "@babel/eslint-parser": "^7.16.3", - "@rushstack/eslint-patch": "^1.1.0", - "@typescript-eslint/eslint-plugin": "^5.5.0", - "@typescript-eslint/parser": "^5.5.0", - "babel-preset-react-app": "^10.0.1", - "confusing-browser-globals": "^1.0.11", - "eslint-plugin-flowtype": "^8.0.3", - "eslint-plugin-import": "^2.25.3", - "eslint-plugin-jest": "^25.3.0", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react": "^7.27.1", - "eslint-plugin-react-hooks": "^4.3.0", - "eslint-plugin-testing-library": "^5.0.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "eslint": "^8.0.0" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", - "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-flowtype": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz", - "integrity": "sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==", - "dependencies": { - "lodash": "^4.17.21", - "string-natural-compare": "^3.0.1" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@babel/plugin-syntax-flow": "^7.14.5", - "@babel/plugin-transform-react-jsx": "^7.14.9", - "eslint": "^8.1.0" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.31.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", - "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", - "dependencies": { - "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.8", - "array.prototype.findlastindex": "^1.2.5", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.0", - "hasown": "^2.0.2", - "is-core-module": "^2.15.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "object.groupby": "^1.0.3", - "object.values": "^1.2.0", - "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.8", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-jest": { - "version": "25.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz", - "integrity": "sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==", - "dependencies": { - "@typescript-eslint/experimental-utils": "^5.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^4.0.0 || ^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - }, - "jest": { - "optional": true - } - } - }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", - "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", - "dependencies": { - "aria-query": "^5.3.2", - "array-includes": "^3.1.8", - "array.prototype.flatmap": "^1.3.2", - "ast-types-flow": "^0.0.8", - "axe-core": "^4.10.0", - "axobject-query": "^4.1.0", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "hasown": "^2.0.2", - "jsx-ast-utils": "^3.3.5", - "language-tags": "^1.0.9", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "safe-regex-test": "^1.0.3", - "string.prototype.includes": "^2.0.1" - }, - "engines": { - "node": ">=4.0" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.37.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz", - "integrity": "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==", - "dependencies": { - "array-includes": "^3.1.8", - "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.3", - "array.prototype.tosorted": "^1.1.4", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.2.1", - "estraverse": "^5.3.0", - "hasown": "^2.0.2", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.8", - "object.fromentries": "^2.0.8", - "object.values": "^1.2.1", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.12", - "string.prototype.repeat": "^1.0.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", - "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.5", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", - "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-testing-library": { - "version": "5.11.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.11.1.tgz", - "integrity": "sha512-5eX9e1Kc2PqVRed3taaLnAAqPZGEX75C+M/rXzUAI3wIg/ZxzUm1OVAwfe/O+vE+6YXOLetSe9g5GKD2ecXipw==", - "dependencies": { - "@typescript-eslint/utils": "^5.58.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0", - "npm": ">=6" - }, - "peerDependencies": { - "eslint": "^7.5.0 || ^8.0.0" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-webpack-plugin": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-3.2.0.tgz", - "integrity": "sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w==", - "dependencies": { - "@types/eslint": "^7.29.0 || ^8.4.1", - "jest-worker": "^28.0.2", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0", - "webpack": "^5.0.0" - } - }, - "node_modules/eslint-webpack-plugin/node_modules/jest-worker": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-28.1.3.tgz", - "integrity": "sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==", - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/eslint-webpack-plugin/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/eslint/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/eslint/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expect": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.5.1.tgz", - "integrity": "sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==", - "dependencies": { - "@jest/types": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", - "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 0.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" - }, - "node_modules/fast-uri": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", - "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ] - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dependencies": { - "websocket-driver": ">=0.5.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/file-loader": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", - "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", - "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/file-loader/node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", - "dependencies": { - "minimatch": "^5.0.1" - } - }, - "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/filelist/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/filesize": { - "version": "8.0.7", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", - "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==" - }, - "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/for-each": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", - "dependencies": { - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fork-ts-checker-webpack-plugin": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", - "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", - "dependencies": { - "@babel/code-frame": "^7.8.3", - "@types/json-schema": "^7.0.5", - "chalk": "^4.1.0", - "chokidar": "^3.4.2", - "cosmiconfig": "^6.0.0", - "deepmerge": "^4.2.2", - "fs-extra": "^9.0.0", - "glob": "^7.1.6", - "memfs": "^3.1.2", - "minimatch": "^3.0.4", - "schema-utils": "2.7.0", - "semver": "^7.3.2", - "tapable": "^1.0.0" - }, - "engines": { - "node": ">=10", - "yarn": ">=1.0.0" - }, - "peerDependencies": { - "eslint": ">= 6", - "typescript": ">= 2.7", - "vue-template-compiler": "*", - "webpack": ">= 4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - }, - "vue-template-compiler": { - "optional": true - } - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", - "dependencies": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/form-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.3.tgz", - "integrity": "sha512-q5YBMeWy6E2Un0nMGWMgI65MAKtaylxfNJGJxpGh45YDciZB4epbWpaAfImil6CPAPTYB4sh0URQNDRIZG5F2w==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "mime-types": "^2.1.35" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fraction.js": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", - "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", - "engines": { - "node": "*" - }, - "funding": { - "type": "patreon", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/fs-monkey": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", - "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==" - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-own-enumerable-property-symbols": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" - }, - "node_modules/global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dependencies": { - "global-prefix": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" - }, - "node_modules/gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "dependencies": { - "duplexer": "^0.1.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" - }, - "node_modules/harmony-reflect": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz", - "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==" - }, - "node_modules/has-bigints": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", - "dependencies": { - "dunder-proto": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "bin": { - "he": "bin/he" - } - }, - "node_modules/hoopy": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", - "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==", - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dependencies": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - } - }, - "node_modules/hpack.js/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/hpack.js/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/hpack.js/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/hpack.js/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dependencies": { - "whatwg-encoding": "^1.0.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/html-entities": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", - "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ] - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" - }, - "node_modules/html-minifier-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", - "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", - "dependencies": { - "camel-case": "^4.1.2", - "clean-css": "^5.2.2", - "commander": "^8.3.0", - "he": "^1.2.0", - "param-case": "^3.0.4", - "relateurl": "^0.2.7", - "terser": "^5.10.0" - }, - "bin": { - "html-minifier-terser": "cli.js" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/html-webpack-plugin": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.3.tgz", - "integrity": "sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg==", - "dependencies": { - "@types/html-minifier-terser": "^6.0.0", - "html-minifier-terser": "^6.0.2", - "lodash": "^4.17.21", - "pretty-error": "^4.0.0", - "tapable": "^2.0.0" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/html-webpack-plugin" - }, - "peerDependencies": { - "@rspack/core": "0.x || 1.x", - "webpack": "^5.20.0" - }, - "peerDependenciesMeta": { - "@rspack/core": { - "optional": true - }, - "webpack": { - "optional": true - } - } - }, - "node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==" - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-parser-js": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.9.tgz", - "integrity": "sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==" - }, - "node_modules/http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dependencies": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http-proxy-middleware": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", - "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", - "dependencies": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@types/express": "^4.17.13" - }, - "peerDependenciesMeta": { - "@types/express": { - "optional": true - } - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/idb": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", - "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==" - }, - "node_modules/identity-obj-proxy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz", - "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==", - "dependencies": { - "harmony-reflect": "^1.4.6" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/immer": { - "version": "9.0.21", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", - "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/immer" - } - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" - }, - "node_modules/internal-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ipaddr.js": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", - "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - }, - "node_modules/is-async-function": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", - "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", - "dependencies": { - "async-function": "^1.0.0", - "call-bound": "^1.0.3", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", - "dependencies": { - "has-bigints": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", - "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", - "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/is-generator-function": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", - "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", - "dependencies": { - "call-bound": "^1.0.3", - "get-proto": "^1.0.0", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" - }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", - "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-root": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", - "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", - "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", - "dependencies": { - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", - "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", - "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/iterator.prototype": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", - "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.6", - "get-proto": "^1.0.0", - "has-symbols": "^1.1.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jake": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", - "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", - "dependencies": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.4", - "minimatch": "^3.1.2" - }, - "bin": { - "jake": "bin/cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jest": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz", - "integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==", - "dependencies": { - "@jest/core": "^27.5.1", - "import-local": "^3.0.2", - "jest-cli": "^27.5.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-changed-files": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz", - "integrity": "sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==", - "dependencies": { - "@jest/types": "^27.5.1", - "execa": "^5.0.0", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-circus": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.5.1.tgz", - "integrity": "sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==", - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-cli": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.5.1.tgz", - "integrity": "sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==", - "dependencies": { - "@jest/core": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "import-local": "^3.0.2", - "jest-config": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "prompts": "^2.0.1", - "yargs": "^16.2.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-config": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.5.1.tgz", - "integrity": "sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==", - "dependencies": { - "@babel/core": "^7.8.0", - "@jest/test-sequencer": "^27.5.1", - "@jest/types": "^27.5.1", - "babel-jest": "^27.5.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.1", - "graceful-fs": "^4.2.9", - "jest-circus": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-jasmine2": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runner": "^27.5.1", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "ts-node": { - "optional": true - } - } - }, - "node_modules/jest-diff": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.5.1.tgz", - "integrity": "sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-docblock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.5.1.tgz", - "integrity": "sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==", - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-each": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.5.1.tgz", - "integrity": "sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==", - "dependencies": { - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-environment-jsdom": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz", - "integrity": "sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==", - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1", - "jsdom": "^16.6.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-environment-node": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.5.1.tgz", - "integrity": "sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==", - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "jest-mock": "^27.5.1", - "jest-util": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.5.1.tgz", - "integrity": "sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==", - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-haste-map": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.5.1.tgz", - "integrity": "sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==", - "dependencies": { - "@jest/types": "^27.5.1", - "@types/graceful-fs": "^4.1.2", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^27.5.1", - "jest-serializer": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "micromatch": "^4.0.4", - "walker": "^1.0.7" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/jest-jasmine2": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz", - "integrity": "sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==", - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^27.5.1", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "pretty-format": "^27.5.1", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-leak-detector": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz", - "integrity": "sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==", - "dependencies": { - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz", - "integrity": "sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==", - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-message-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.5.1.tgz", - "integrity": "sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.5.1", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^27.5.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-mock": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.5.1.tgz", - "integrity": "sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==", - "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.5.1.tgz", - "integrity": "sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==", - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-resolve": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.5.1.tgz", - "integrity": "sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==", - "dependencies": { - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.5.1", - "jest-validate": "^27.5.1", - "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz", - "integrity": "sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==", - "dependencies": { - "@jest/types": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-snapshot": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-runner": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.5.1.tgz", - "integrity": "sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==", - "dependencies": { - "@jest/console": "^27.5.1", - "@jest/environment": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^27.5.1", - "jest-environment-jsdom": "^27.5.1", - "jest-environment-node": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-leak-detector": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-runtime": "^27.5.1", - "jest-util": "^27.5.1", - "jest-worker": "^27.5.1", - "source-map-support": "^0.5.6", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-runtime": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.5.1.tgz", - "integrity": "sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==", - "dependencies": { - "@jest/environment": "^27.5.1", - "@jest/fake-timers": "^27.5.1", - "@jest/globals": "^27.5.1", - "@jest/source-map": "^27.5.1", - "@jest/test-result": "^27.5.1", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-mock": "^27.5.1", - "jest-regex-util": "^27.5.1", - "jest-resolve": "^27.5.1", - "jest-snapshot": "^27.5.1", - "jest-util": "^27.5.1", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-serializer": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.5.1.tgz", - "integrity": "sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==", - "dependencies": { - "@types/node": "*", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-snapshot": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.5.1.tgz", - "integrity": "sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==", - "dependencies": { - "@babel/core": "^7.7.2", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.0.0", - "@jest/transform": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/babel__traverse": "^7.0.4", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^27.5.1", - "graceful-fs": "^4.2.9", - "jest-diff": "^27.5.1", - "jest-get-type": "^27.5.1", - "jest-haste-map": "^27.5.1", - "jest-matcher-utils": "^27.5.1", - "jest-message-util": "^27.5.1", - "jest-util": "^27.5.1", - "natural-compare": "^1.4.0", - "pretty-format": "^27.5.1", - "semver": "^7.3.2" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-util": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.5.1.tgz", - "integrity": "sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==", - "dependencies": { - "@jest/types": "^27.5.1", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-validate": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.5.1.tgz", - "integrity": "sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==", - "dependencies": { - "@jest/types": "^27.5.1", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^27.5.1", - "leven": "^3.1.0", - "pretty-format": "^27.5.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-watch-typeahead": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-1.1.0.tgz", - "integrity": "sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==", - "dependencies": { - "ansi-escapes": "^4.3.1", - "chalk": "^4.0.0", - "jest-regex-util": "^28.0.0", - "jest-watcher": "^28.0.0", - "slash": "^4.0.0", - "string-length": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "jest": "^27.0.0 || ^28.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/@jest/console": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-28.1.3.tgz", - "integrity": "sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==", - "dependencies": { - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^28.1.3", - "jest-util": "^28.1.3", - "slash": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/@jest/console/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-watch-typeahead/node_modules/@jest/test-result": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-28.1.3.tgz", - "integrity": "sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==", - "dependencies": { - "@jest/console": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/@jest/types": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-28.1.3.tgz", - "integrity": "sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==", - "dependencies": { - "@jest/schemas": "^28.1.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/jest-watch-typeahead/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-watch-typeahead/node_modules/emittery": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.10.2.tgz", - "integrity": "sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/jest-watch-typeahead/node_modules/jest-message-util": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-28.1.3.tgz", - "integrity": "sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^28.1.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^28.1.3", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/jest-message-util/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-watch-typeahead/node_modules/jest-regex-util": { - "version": "28.0.2", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-28.0.2.tgz", - "integrity": "sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==", - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/jest-util": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-28.1.3.tgz", - "integrity": "sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==", - "dependencies": { - "@jest/types": "^28.1.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/jest-watcher": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-28.1.3.tgz", - "integrity": "sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==", - "dependencies": { - "@jest/test-result": "^28.1.3", - "@jest/types": "^28.1.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.10.2", - "jest-util": "^28.1.3", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/jest-watcher/node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jest-watch-typeahead/node_modules/jest-watcher/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-watch-typeahead/node_modules/pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dependencies": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/jest-watch-typeahead/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" - }, - "node_modules/jest-watch-typeahead/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-watch-typeahead/node_modules/string-length": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-5.0.1.tgz", - "integrity": "sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==", - "dependencies": { - "char-regex": "^2.0.0", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-watch-typeahead/node_modules/string-length/node_modules/char-regex": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-2.0.2.tgz", - "integrity": "sha512-cbGOjAptfM2LVmWhwRFHEKTPkLwNddVmuqYZQt895yXwAsWsXObCG+YN4DGQ/JBtT4GP1a1lPPdio2z413LmTg==", - "engines": { - "node": ">=12.20" - } - }, - "node_modules/jest-watch-typeahead/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/jest-watch-typeahead/node_modules/strip-ansi/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/jest-watcher": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.5.1.tgz", - "integrity": "sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==", - "dependencies": { - "@jest/test-result": "^27.5.1", - "@jest/types": "^27.5.1", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "jest-util": "^27.5.1", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/jiti": { - "version": "1.21.7", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", - "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", - "bin": { - "jiti": "bin/jiti.js" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", - "dependencies": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonpath": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.1.1.tgz", - "integrity": "sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==", - "dependencies": { - "esprima": "1.2.2", - "static-eval": "2.0.2", - "underscore": "1.12.1" - } - }, - "node_modules/jsonpath/node_modules/esprima": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz", - "integrity": "sha512-+JpPZam9w5DuJ3Q67SqsMGtiHKENSMRVoxvArfJZK01/BfLEObtZ6orJa/MtoGNR/rfMgp5837T41PAmTwAv/A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/jsonpointer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", - "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "engines": { - "node": ">=6" - } - }, - "node_modules/klona": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", - "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/language-subtag-registry": { - "version": "0.3.23", - "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", - "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==" - }, - "node_modules/language-tags": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", - "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", - "dependencies": { - "language-subtag-registry": "^0.3.20" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/launch-editor": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.10.0.tgz", - "integrity": "sha512-D7dBRJo/qcGX9xlvt/6wUYzQxjh5G1RvZPgPv8vi4KRU99DVQL/oW7tnVOCCTm2HGeo3C5HvGE5Yrh6UBoZ0vA==", - "dependencies": { - "picocolors": "^1.0.0", - "shell-quote": "^1.8.1" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "engines": { - "node": ">=10" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" - }, - "node_modules/loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "engines": { - "node": ">=6.11.5" - } - }, - "node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, - "node_modules/lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dependencies": { - "tslib": "^2.0.3" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/lz-string": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", - "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", - "bin": { - "lz-string": "bin/bin.js" - } - }, - "node_modules/magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dependencies": { - "sourcemap-codec": "^1.4.8" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dependencies": { - "tmpl": "1.0.5" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/mdn-data": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", - "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==" - }, - "node_modules/media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/memfs": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", - "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", - "dependencies": { - "fs-monkey": "^1.0.4" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/merge-descriptors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", - "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "engines": { - "node": ">=4" - } - }, - "node_modules/mini-css-extract-plugin": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz", - "integrity": "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==", - "dependencies": { - "schema-utils": "^4.0.0", - "tapable": "^2.2.1" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dependencies": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - }, - "bin": { - "multicast-dns": "cli.js" - } - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.9.tgz", - "integrity": "sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" - }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==" - }, - "node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" - }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" - }, - "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/nwsapi": { - "version": "2.2.18", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.18.tgz", - "integrity": "sha512-p1TRH/edngVEHVbwqWnxUViEmq5znDvyB+Sik5cmuLpGOIfDf/39zLiq3swPF8Vakqn+gvNiOQAZu8djYlQILA==" - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", - "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.8.tgz", - "integrity": "sha512-qkHIGe4q0lSYMv0XI4SsBTJz3WaURhLvd0lKSgtVuOsJ2krg4SgMw3PIRQFMp07yi++UR3se2mkcLqsBNpBb/A==", - "dependencies": { - "array.prototype.reduce": "^1.0.6", - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "gopd": "^1.0.1", - "safe-array-concat": "^1.1.2" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", - "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==" - }, - "node_modules/on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dependencies": { - "ee-first": "1.1.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/own-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", - "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", - "dependencies": { - "get-intrinsic": "^1.2.6", - "object-keys": "^1.1.1", - "safe-push-apply": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", - "dependencies": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" - }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" - }, - "node_modules/parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" - }, - "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", - "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-up/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", - "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.8", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-attribute-case-insensitive": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz", - "integrity": "sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-browser-comments": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz", - "integrity": "sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==", - "engines": { - "node": ">=8" - }, - "peerDependencies": { - "browserslist": ">=4", - "postcss": ">=8" - } - }, - "node_modules/postcss-calc": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", - "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", - "dependencies": { - "postcss-selector-parser": "^6.0.9", - "postcss-value-parser": "^4.2.0" - }, - "peerDependencies": { - "postcss": "^8.2.2" - } - }, - "node_modules/postcss-clamp": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", - "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": ">=7.6.0" - }, - "peerDependencies": { - "postcss": "^8.4.6" - } - }, - "node_modules/postcss-color-functional-notation": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz", - "integrity": "sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-color-hex-alpha": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.4.tgz", - "integrity": "sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-color-rebeccapurple": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.1.1.tgz", - "integrity": "sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-colormin": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", - "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", - "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "colord": "^2.9.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-convert-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", - "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", - "dependencies": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-custom-media": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz", - "integrity": "sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.3" - } - }, - "node_modules/postcss-custom-properties": { - "version": "12.1.11", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.11.tgz", - "integrity": "sha512-0IDJYhgU8xDv1KY6+VgUwuQkVtmYzRwu+dMjnmdMafXYv86SWqfxkc7qdDvWS38vsjaEtv8e0vGOUQrAiMBLpQ==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-custom-selectors": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz", - "integrity": "sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==", - "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.3" - } - }, - "node_modules/postcss-dir-pseudo-class": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.5.tgz", - "integrity": "sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-discard-comments": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", - "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-duplicates": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", - "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-empty": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", - "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-discard-overridden": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", - "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-double-position-gradients": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.2.tgz", - "integrity": "sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==", - "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-env-function": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.6.tgz", - "integrity": "sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-flexbugs-fixes": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", - "integrity": "sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==", - "peerDependencies": { - "postcss": "^8.1.4" - } - }, - "node_modules/postcss-focus-visible": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz", - "integrity": "sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==", - "dependencies": { - "postcss-selector-parser": "^6.0.9" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-focus-within": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz", - "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==", - "dependencies": { - "postcss-selector-parser": "^6.0.9" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-font-variant": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", - "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-gap-properties": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz", - "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==", - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-image-set-function": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.7.tgz", - "integrity": "sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-initial": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", - "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", - "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": "^8.4.21" - } - }, - "node_modules/postcss-lab-function": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.2.1.tgz", - "integrity": "sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==", - "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-load-config": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", - "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "lilconfig": "^3.0.0", - "yaml": "^2.3.4" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, - "node_modules/postcss-load-config/node_modules/yaml": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", - "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/postcss-loader": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", - "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", - "dependencies": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" - } - }, - "node_modules/postcss-logical": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", - "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", - "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-media-minmax": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", - "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-merge-longhand": { - "version": "5.1.7", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", - "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", - "dependencies": { - "postcss-value-parser": "^4.2.0", - "stylehacks": "^5.1.1" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-merge-rules": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", - "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", - "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0", - "cssnano-utils": "^3.1.0", - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-font-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", - "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-gradients": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", - "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", - "dependencies": { - "colord": "^2.9.1", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-params": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", - "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", - "dependencies": { - "browserslist": "^4.21.4", - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-minify-selectors": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", - "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", - "dependencies": { - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-modules-extract-imports": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", - "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", - "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", - "dependencies": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^7.0.0", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-local-by-default/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-modules-scope": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", - "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", - "dependencies": { - "postcss-selector-parser": "^7.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", - "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dependencies": { - "icss-utils": "^5.0.0" - }, - "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-nested": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", - "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "postcss-selector-parser": "^6.1.1" - }, - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-nesting": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.2.0.tgz", - "integrity": "sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==", - "dependencies": { - "@csstools/selector-specificity": "^2.0.0", - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-normalize": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize/-/postcss-normalize-10.0.1.tgz", - "integrity": "sha512-+5w18/rDev5mqERcG3W5GZNMJa1eoYYNGo8gB7tEwaos0ajk3ZXAI4mHGcNT47NE+ZnZD1pEpUOFLvltIwmeJA==", - "dependencies": { - "@csstools/normalize.css": "*", - "postcss-browser-comments": "^4", - "sanitize.css": "*" - }, - "engines": { - "node": ">= 12" - }, - "peerDependencies": { - "browserslist": ">= 4", - "postcss": ">= 8" - } - }, - "node_modules/postcss-normalize-charset": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", - "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-display-values": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", - "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-positions": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", - "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-repeat-style": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", - "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-string": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", - "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-timing-functions": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", - "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-unicode": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", - "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", - "dependencies": { - "browserslist": "^4.21.4", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", - "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", - "dependencies": { - "normalize-url": "^6.0.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-normalize-whitespace": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", - "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-opacity-percentage": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz", - "integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==", - "funding": [ - { - "type": "kofi", - "url": "https://ko-fi.com/mrcgrtz" - }, - { - "type": "liberapay", - "url": "https://liberapay.com/mrcgrtz" - } - ], - "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-ordered-values": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", - "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", - "dependencies": { - "cssnano-utils": "^3.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-overflow-shorthand": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.4.tgz", - "integrity": "sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-page-break": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", - "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", - "peerDependencies": { - "postcss": "^8" - } - }, - "node_modules/postcss-place": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.5.tgz", - "integrity": "sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-preset-env": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.3.tgz", - "integrity": "sha512-T1LgRm5uEVFSEF83vHZJV2z19lHg4yJuZ6gXZZkqVsqv63nlr6zabMH3l4Pc01FQCyfWVrh2GaUeCVy9Po+Aag==", - "dependencies": { - "@csstools/postcss-cascade-layers": "^1.1.1", - "@csstools/postcss-color-function": "^1.1.1", - "@csstools/postcss-font-format-keywords": "^1.0.1", - "@csstools/postcss-hwb-function": "^1.0.2", - "@csstools/postcss-ic-unit": "^1.0.1", - "@csstools/postcss-is-pseudo-class": "^2.0.7", - "@csstools/postcss-nested-calc": "^1.0.0", - "@csstools/postcss-normalize-display-values": "^1.0.1", - "@csstools/postcss-oklab-function": "^1.1.1", - "@csstools/postcss-progressive-custom-properties": "^1.3.0", - "@csstools/postcss-stepped-value-functions": "^1.0.1", - "@csstools/postcss-text-decoration-shorthand": "^1.0.0", - "@csstools/postcss-trigonometric-functions": "^1.0.2", - "@csstools/postcss-unset-value": "^1.0.2", - "autoprefixer": "^10.4.13", - "browserslist": "^4.21.4", - "css-blank-pseudo": "^3.0.3", - "css-has-pseudo": "^3.0.4", - "css-prefers-color-scheme": "^6.0.3", - "cssdb": "^7.1.0", - "postcss-attribute-case-insensitive": "^5.0.2", - "postcss-clamp": "^4.1.0", - "postcss-color-functional-notation": "^4.2.4", - "postcss-color-hex-alpha": "^8.0.4", - "postcss-color-rebeccapurple": "^7.1.1", - "postcss-custom-media": "^8.0.2", - "postcss-custom-properties": "^12.1.10", - "postcss-custom-selectors": "^6.0.3", - "postcss-dir-pseudo-class": "^6.0.5", - "postcss-double-position-gradients": "^3.1.2", - "postcss-env-function": "^4.0.6", - "postcss-focus-visible": "^6.0.4", - "postcss-focus-within": "^5.0.4", - "postcss-font-variant": "^5.0.0", - "postcss-gap-properties": "^3.0.5", - "postcss-image-set-function": "^4.0.7", - "postcss-initial": "^4.0.1", - "postcss-lab-function": "^4.2.1", - "postcss-logical": "^5.0.4", - "postcss-media-minmax": "^5.0.0", - "postcss-nesting": "^10.2.0", - "postcss-opacity-percentage": "^1.1.2", - "postcss-overflow-shorthand": "^3.0.4", - "postcss-page-break": "^3.0.4", - "postcss-place": "^7.0.5", - "postcss-pseudo-class-any-link": "^7.1.6", - "postcss-replace-overflow-wrap": "^4.0.0", - "postcss-selector-not": "^6.0.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-pseudo-class-any-link": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.6.tgz", - "integrity": "sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-reduce-initial": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", - "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", - "dependencies": { - "browserslist": "^4.21.4", - "caniuse-api": "^3.0.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-reduce-transforms": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", - "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-replace-overflow-wrap": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", - "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", - "peerDependencies": { - "postcss": "^8.0.3" - } - }, - "node_modules/postcss-selector-not": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz", - "integrity": "sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==", - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-svgo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", - "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", - "dependencies": { - "postcss-value-parser": "^4.2.0", - "svgo": "^2.7.0" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-svgo/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/postcss-svgo/node_modules/css-tree": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", - "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dependencies": { - "mdn-data": "2.0.14", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/postcss-svgo/node_modules/mdn-data": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" - }, - "node_modules/postcss-svgo/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postcss-svgo/node_modules/svgo": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", - "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", - "dependencies": { - "@trysound/sax": "0.2.0", - "commander": "^7.2.0", - "css-select": "^4.1.3", - "css-tree": "^1.1.3", - "csso": "^4.2.0", - "picocolors": "^1.0.0", - "stable": "^0.1.8" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/postcss-unique-selectors": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", - "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", - "dependencies": { - "postcss-selector-parser": "^6.0.5" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pretty-error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", - "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", - "dependencies": { - "lodash": "^4.17.20", - "renderkid": "^3.0.0" - } - }, - "node_modules/pretty-format": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", - "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", - "dependencies": { - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/promise": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", - "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", - "dependencies": { - "asap": "~2.0.6" - } - }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/prop-types/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, - "node_modules/proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dependencies": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/proxy-addr/node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/psl": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", - "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", - "dependencies": { - "punycode": "^2.3.1" - }, - "funding": { - "url": "https://github.com/sponsors/lupomontero" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", - "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)", - "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" - } - }, - "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "dependencies": { - "performance-now": "^2.1.0" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/raw-body/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", - "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-app-polyfill": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz", - "integrity": "sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w==", - "dependencies": { - "core-js": "^3.19.2", - "object-assign": "^4.1.1", - "promise": "^8.1.0", - "raf": "^3.4.1", - "regenerator-runtime": "^0.13.9", - "whatwg-fetch": "^3.6.2" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/react-app-polyfill/node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, - "node_modules/react-dev-utils": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", - "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", - "dependencies": { - "@babel/code-frame": "^7.16.0", - "address": "^1.1.2", - "browserslist": "^4.18.1", - "chalk": "^4.1.2", - "cross-spawn": "^7.0.3", - "detect-port-alt": "^1.1.6", - "escape-string-regexp": "^4.0.0", - "filesize": "^8.0.6", - "find-up": "^5.0.0", - "fork-ts-checker-webpack-plugin": "^6.5.0", - "global-modules": "^2.0.0", - "globby": "^11.0.4", - "gzip-size": "^6.0.0", - "immer": "^9.0.7", - "is-root": "^2.1.0", - "loader-utils": "^3.2.0", - "open": "^8.4.0", - "pkg-up": "^3.1.0", - "prompts": "^2.4.2", - "react-error-overlay": "^6.0.11", - "recursive-readdir": "^2.2.2", - "shell-quote": "^1.7.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/react-dev-utils/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-dev-utils/node_modules/loader-utils": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", - "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/react-dev-utils/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-dev-utils/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-dev-utils/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-dom": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", - "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==", - "dependencies": { - "scheduler": "^0.25.0" - }, - "peerDependencies": { - "react": "^19.0.0" - } - }, - "node_modules/react-error-overlay": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.1.0.tgz", - "integrity": "sha512-SN/U6Ytxf1QGkw/9ve5Y+NxBbZM6Ht95tuXNMKs8EJyFa/Vy/+Co3stop3KBHARfn/giv+Lj1uUnTfOJ3moFEQ==" - }, - "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - }, - "node_modules/react-refresh": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", - "integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-scripts": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", - "integrity": "sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==", - "dependencies": { - "@babel/core": "^7.16.0", - "@pmmmwh/react-refresh-webpack-plugin": "^0.5.3", - "@svgr/webpack": "^5.5.0", - "babel-jest": "^27.4.2", - "babel-loader": "^8.2.3", - "babel-plugin-named-asset-import": "^0.3.8", - "babel-preset-react-app": "^10.0.1", - "bfj": "^7.0.2", - "browserslist": "^4.18.1", - "camelcase": "^6.2.1", - "case-sensitive-paths-webpack-plugin": "^2.4.0", - "css-loader": "^6.5.1", - "css-minimizer-webpack-plugin": "^3.2.0", - "dotenv": "^10.0.0", - "dotenv-expand": "^5.1.0", - "eslint": "^8.3.0", - "eslint-config-react-app": "^7.0.1", - "eslint-webpack-plugin": "^3.1.1", - "file-loader": "^6.2.0", - "fs-extra": "^10.0.0", - "html-webpack-plugin": "^5.5.0", - "identity-obj-proxy": "^3.0.0", - "jest": "^27.4.3", - "jest-resolve": "^27.4.2", - "jest-watch-typeahead": "^1.0.0", - "mini-css-extract-plugin": "^2.4.5", - "postcss": "^8.4.4", - "postcss-flexbugs-fixes": "^5.0.2", - "postcss-loader": "^6.2.1", - "postcss-normalize": "^10.0.1", - "postcss-preset-env": "^7.0.1", - "prompts": "^2.4.2", - "react-app-polyfill": "^3.0.0", - "react-dev-utils": "^12.0.1", - "react-refresh": "^0.11.0", - "resolve": "^1.20.0", - "resolve-url-loader": "^4.0.0", - "sass-loader": "^12.3.0", - "semver": "^7.3.5", - "source-map-loader": "^3.0.0", - "style-loader": "^3.3.1", - "tailwindcss": "^3.0.2", - "terser-webpack-plugin": "^5.2.5", - "webpack": "^5.64.4", - "webpack-dev-server": "^4.6.0", - "webpack-manifest-plugin": "^4.0.2", - "workbox-webpack-plugin": "^6.4.1" - }, - "bin": { - "react-scripts": "bin/react-scripts.js" - }, - "engines": { - "node": ">=14.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - }, - "peerDependencies": { - "react": ">= 16", - "typescript": "^3.2.1 || ^4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dependencies": { - "pify": "^2.3.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/recursive-readdir": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", - "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", - "dependencies": { - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", - "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.1", - "which-builtin-type": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", - "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, - "node_modules/regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, - "node_modules/regex-parser": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.1.tgz", - "integrity": "sha512-yXLRqatcCuKtVHsWrNg0JL3l1zGfdXeEvDa0bdu4tCDQw0RpMDZsqbkyRTUnKMR0tXF627V2oEWjBEaEdqTwtQ==" - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", - "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpu-core": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", - "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", - "dependencies": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.2.0", - "regjsgen": "^0.8.0", - "regjsparser": "^0.12.0", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==" - }, - "node_modules/regjsparser": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", - "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", - "dependencies": { - "jsesc": "~3.0.2" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/renderkid": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", - "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", - "dependencies": { - "css-select": "^4.1.3", - "dom-converter": "^0.2.0", - "htmlparser2": "^6.1.0", - "lodash": "^4.17.21", - "strip-ansi": "^6.0.1" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" - }, - "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "dependencies": { - "is-core-module": "^2.16.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-url-loader": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz", - "integrity": "sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==", - "dependencies": { - "adjust-sourcemap-loader": "^4.0.0", - "convert-source-map": "^1.7.0", - "loader-utils": "^2.0.0", - "postcss": "^7.0.35", - "source-map": "0.6.1" - }, - "engines": { - "node": ">=8.9" - }, - "peerDependencies": { - "rework": "1.0.1", - "rework-visit": "1.0.0" - }, - "peerDependenciesMeta": { - "rework": { - "optional": true - }, - "rework-visit": { - "optional": true - } - } - }, - "node_modules/resolve-url-loader/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" - }, - "node_modules/resolve-url-loader/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==" - }, - "node_modules/resolve-url-loader/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", - "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - } - }, - "node_modules/resolve-url-loader/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve.exports": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.1.tgz", - "integrity": "sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==", - "engines": { - "node": ">=10" - } - }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rollup": { - "version": "2.79.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", - "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=10.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/rollup-plugin-terser": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", - "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", - "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser", - "dependencies": { - "@babel/code-frame": "^7.10.4", - "jest-worker": "^26.2.1", - "serialize-javascript": "^4.0.0", - "terser": "^5.0.0" - }, - "peerDependencies": { - "rollup": "^2.0.0" - } - }, - "node_modules/rollup-plugin-terser/node_modules/jest-worker": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", - "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/rollup-plugin-terser/node_modules/serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-array-concat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-push-apply": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", - "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", - "dependencies": { - "es-errors": "^1.3.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sanitize.css": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-13.0.0.tgz", - "integrity": "sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==" - }, - "node_modules/sass-loader": { - "version": "12.6.0", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-12.6.0.tgz", - "integrity": "sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==", - "dependencies": { - "klona": "^2.0.4", - "neo-async": "^2.6.2" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "fibers": ">= 3.1.0", - "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", - "sass": "^1.3.0", - "sass-embedded": "*", - "webpack": "^5.0.0" - }, - "peerDependenciesMeta": { - "fibers": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - } - } - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "node_modules/saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/scheduler": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", - "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==" - }, - "node_modules/schema-utils": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", - "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/schema-utils/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/schema-utils/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/schema-utils/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "node_modules/select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==" - }, - "node_modules/selfsigned": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", - "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", - "dependencies": { - "@types/node-forge": "^1.3.0", - "node-forge": "^1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/send": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", - "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/send/node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", - "dependencies": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/serve-index/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/serve-index/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dependencies": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-index/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" - }, - "node_modules/serve-index/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/serve-index/node_modules/setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" - }, - "node_modules/serve-index/node_modules/statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/serve-static": { - "version": "1.16.2", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", - "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "dependencies": { - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.19.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-proto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", - "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" - } - }, - "node_modules/shell-quote": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", - "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "node_modules/source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" - }, - "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-loader": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-3.0.2.tgz", - "integrity": "sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==", - "dependencies": { - "abab": "^2.0.5", - "iconv-lite": "^0.6.3", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "deprecated": "Please use @jridgewell/sourcemap-codec instead" - }, - "node_modules/spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dependencies": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dependencies": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - }, - "node_modules/stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/stackframe": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", - "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==" - }, - "node_modules/static-eval": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", - "integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==", - "dependencies": { - "escodegen": "^1.8.1" - } - }, - "node_modules/static-eval/node_modules/escodegen": { - "version": "1.14.3", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", - "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=4.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/static-eval/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/static-eval/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/static-eval/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/static-eval/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/static-eval/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-eval/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string-natural-compare": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", - "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==" - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/string-width/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/string.prototype.includes": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", - "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", - "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.6", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.6", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "regexp.prototype.flags": "^1.5.3", - "set-function-name": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.repeat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", - "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-data-property": "^1.1.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/stringify-object": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", - "dependencies": { - "get-own-enumerable-property-symbols": "^3.0.0", - "is-obj": "^1.0.1", - "is-regexp": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", - "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", - "engines": { - "node": ">=10" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/style-loader": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", - "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.0.0" - } - }, - "node_modules/stylehacks": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", - "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", - "dependencies": { - "browserslist": "^4.21.4", - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^10 || ^12 || >=14.0" - }, - "peerDependencies": { - "postcss": "^8.2.15" - } - }, - "node_modules/sucrase": { - "version": "3.35.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", - "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "glob": "^10.3.10", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/sucrase/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/sucrase/node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/sucrase/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/sucrase/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-hyperlinks": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", - "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/svg-parser": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", - "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==" - }, - "node_modules/svgo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", - "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", - "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.", - "dependencies": { - "chalk": "^2.4.1", - "coa": "^2.0.2", - "css-select": "^2.0.0", - "css-select-base-adapter": "^0.1.1", - "css-tree": "1.0.0-alpha.37", - "csso": "^4.0.2", - "js-yaml": "^3.13.1", - "mkdirp": "~0.5.1", - "object.values": "^1.1.0", - "sax": "~1.2.4", - "stable": "^0.1.8", - "unquote": "~1.1.1", - "util.promisify": "~1.0.0" - }, - "bin": { - "svgo": "bin/svgo" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/svgo/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/svgo/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/svgo/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/svgo/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/svgo/node_modules/css-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", - "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^3.2.1", - "domutils": "^1.7.0", - "nth-check": "^1.0.2" - } - }, - "node_modules/svgo/node_modules/css-what": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", - "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/svgo/node_modules/dom-serializer": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", - "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", - "dependencies": { - "domelementtype": "^2.0.1", - "entities": "^2.0.0" - } - }, - "node_modules/svgo/node_modules/domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", - "dependencies": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "node_modules/svgo/node_modules/domutils/node_modules/domelementtype": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", - "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" - }, - "node_modules/svgo/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/svgo/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/svgo/node_modules/nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", - "dependencies": { - "boolbase": "~1.0.0" - } - }, - "node_modules/svgo/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" - }, - "node_modules/tailwindcss": { - "version": "3.4.17", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", - "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.6.0", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.3.2", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.21.6", - "lilconfig": "^3.1.3", - "micromatch": "^4.0.8", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.1.1", - "postcss": "^8.4.47", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.2", - "postcss-nested": "^6.2.0", - "postcss-selector-parser": "^6.1.2", - "resolve": "^1.22.8", - "sucrase": "^3.35.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tailwindcss/node_modules/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/temp-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/tempy": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", - "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", - "dependencies": { - "is-stream": "^2.0.0", - "temp-dir": "^2.0.0", - "type-fest": "^0.16.0", - "unique-string": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tempy/node_modules/type-fest": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", - "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/terser": { - "version": "5.39.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.39.0.tgz", - "integrity": "sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==", - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.8.2", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.14", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", - "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", - "terser": "^5.31.1" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/throat": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz", - "integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==" - }, - "node_modules/thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" - }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie/node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tryer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", - "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==" - }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" - }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", - "dependencies": { - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", - "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/underscore": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", - "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" - }, - "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", - "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", - "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dependencies": { - "crypto-random-string": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/unquote": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", - "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==" - }, - "node_modules/upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "engines": { - "node": ">=4", - "yarn": "*" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/util.promisify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", - "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.2", - "has-symbols": "^1.0.1", - "object.getownpropertydescriptors": "^2.1.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/utila": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", - "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==" - }, - "node_modules/utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8-to-istanbul": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz", - "integrity": "sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==", - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/v8-to-istanbul/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", - "dependencies": { - "browser-process-hrtime": "^1.0.0" - } - }, - "node_modules/w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dependencies": { - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dependencies": { - "makeerror": "1.0.12" - } - }, - "node_modules/watchpack": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", - "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dependencies": { - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/web-vitals": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-2.1.4.tgz", - "integrity": "sha512-sVWcwhU5mX6crfI5Vd2dC4qchyTqxV8URinzt25XqVh+bHEPGH4C3NPrNionCP7Obx59wrYEbNlw4Z8sjALzZg==" - }, - "node_modules/webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "engines": { - "node": ">=10.4" - } - }, - "node_modules/webpack": { - "version": "5.98.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.98.0.tgz", - "integrity": "sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA==", - "dependencies": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.6", - "@webassemblyjs/ast": "^1.14.1", - "@webassemblyjs/wasm-edit": "^1.14.1", - "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.14.0", - "browserslist": "^4.24.0", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.17.1", - "es-module-lexer": "^1.2.1", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^4.3.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.3.11", - "watchpack": "^2.4.1", - "webpack-sources": "^3.2.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-dev-middleware": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", - "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", - "dependencies": { - "colorette": "^2.0.10", - "memfs": "^3.4.3", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/webpack-dev-server": { - "version": "4.15.2", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", - "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", - "dependencies": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.5", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "launch-editor": "^2.6.0", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.1.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.4", - "ws": "^8.13.0" - }, - "bin": { - "webpack-dev-server": "bin/webpack-dev-server.js" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - }, - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", - "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/webpack-manifest-plugin": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-4.1.1.tgz", - "integrity": "sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==", - "dependencies": { - "tapable": "^2.0.0", - "webpack-sources": "^2.2.0" - }, - "engines": { - "node": ">=12.22.0" - }, - "peerDependencies": { - "webpack": "^4.44.2 || ^5.47.0" - } - }, - "node_modules/webpack-manifest-plugin/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webpack-manifest-plugin/node_modules/webpack-sources": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", - "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", - "dependencies": { - "source-list-map": "^2.0.1", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/webpack/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dependencies": { - "iconv-lite": "0.4.24" - } - }, - "node_modules/whatwg-encoding/node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/whatwg-fetch": { - "version": "3.6.20", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", - "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==" - }, - "node_modules/whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" - }, - "node_modules/whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dependencies": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", - "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", - "dependencies": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.1", - "is-number-object": "^1.1.1", - "is-string": "^1.1.1", - "is-symbol": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", - "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", - "dependencies": { - "call-bound": "^1.0.2", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.1.0", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.2.1", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.1.0", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-typed-array": { - "version": "1.1.19", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", - "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "for-each": "^0.3.5", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/workbox-background-sync": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.6.0.tgz", - "integrity": "sha512-jkf4ZdgOJxC9u2vztxLuPT/UjlH7m/nWRQ/MgGL0v8BJHoZdVGJd18Kck+a0e55wGXdqyHO+4IQTk0685g4MUw==", - "dependencies": { - "idb": "^7.0.1", - "workbox-core": "6.6.0" - } - }, - "node_modules/workbox-broadcast-update": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.6.0.tgz", - "integrity": "sha512-nm+v6QmrIFaB/yokJmQ/93qIJ7n72NICxIwQwe5xsZiV2aI93MGGyEyzOzDPVz5THEr5rC3FJSsO3346cId64Q==", - "dependencies": { - "workbox-core": "6.6.0" - } - }, - "node_modules/workbox-build": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.6.0.tgz", - "integrity": "sha512-Tjf+gBwOTuGyZwMz2Nk/B13Fuyeo0Q84W++bebbVsfr9iLkDSo6j6PST8tET9HYA58mlRXwlMGpyWO8ETJiXdQ==", - "dependencies": { - "@apideck/better-ajv-errors": "^0.3.1", - "@babel/core": "^7.11.1", - "@babel/preset-env": "^7.11.0", - "@babel/runtime": "^7.11.2", - "@rollup/plugin-babel": "^5.2.0", - "@rollup/plugin-node-resolve": "^11.2.1", - "@rollup/plugin-replace": "^2.4.1", - "@surma/rollup-plugin-off-main-thread": "^2.2.3", - "ajv": "^8.6.0", - "common-tags": "^1.8.0", - "fast-json-stable-stringify": "^2.1.0", - "fs-extra": "^9.0.1", - "glob": "^7.1.6", - "lodash": "^4.17.20", - "pretty-bytes": "^5.3.0", - "rollup": "^2.43.1", - "rollup-plugin-terser": "^7.0.0", - "source-map": "^0.8.0-beta.0", - "stringify-object": "^3.3.0", - "strip-comments": "^2.0.1", - "tempy": "^0.6.0", - "upath": "^1.2.0", - "workbox-background-sync": "6.6.0", - "workbox-broadcast-update": "6.6.0", - "workbox-cacheable-response": "6.6.0", - "workbox-core": "6.6.0", - "workbox-expiration": "6.6.0", - "workbox-google-analytics": "6.6.0", - "workbox-navigation-preload": "6.6.0", - "workbox-precaching": "6.6.0", - "workbox-range-requests": "6.6.0", - "workbox-recipes": "6.6.0", - "workbox-routing": "6.6.0", - "workbox-strategies": "6.6.0", - "workbox-streams": "6.6.0", - "workbox-sw": "6.6.0", - "workbox-window": "6.6.0" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/workbox-build/node_modules/@apideck/better-ajv-errors": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", - "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", - "dependencies": { - "json-schema": "^0.4.0", - "jsonpointer": "^5.0.0", - "leven": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "ajv": ">=8" - } - }, - "node_modules/workbox-build/node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/workbox-build/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/workbox-build/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "node_modules/workbox-build/node_modules/source-map": { - "version": "0.8.0-beta.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", - "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", - "dependencies": { - "whatwg-url": "^7.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/workbox-build/node_modules/tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/workbox-build/node_modules/webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" - }, - "node_modules/workbox-build/node_modules/whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "dependencies": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - }, - "node_modules/workbox-cacheable-response": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.6.0.tgz", - "integrity": "sha512-JfhJUSQDwsF1Xv3EV1vWzSsCOZn4mQ38bWEBR3LdvOxSPgB65gAM6cS2CX8rkkKHRgiLrN7Wxoyu+TuH67kHrw==", - "deprecated": "workbox-background-sync@6.6.0", - "dependencies": { - "workbox-core": "6.6.0" - } - }, - "node_modules/workbox-core": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.6.0.tgz", - "integrity": "sha512-GDtFRF7Yg3DD859PMbPAYPeJyg5gJYXuBQAC+wyrWuuXgpfoOrIQIvFRZnQ7+czTIQjIr1DhLEGFzZanAT/3bQ==" - }, - "node_modules/workbox-expiration": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.6.0.tgz", - "integrity": "sha512-baplYXcDHbe8vAo7GYvyAmlS4f6998Jff513L4XvlzAOxcl8F620O91guoJ5EOf5qeXG4cGdNZHkkVAPouFCpw==", - "dependencies": { - "idb": "^7.0.1", - "workbox-core": "6.6.0" - } - }, - "node_modules/workbox-google-analytics": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.6.0.tgz", - "integrity": "sha512-p4DJa6OldXWd6M9zRl0H6vB9lkrmqYFkRQ2xEiNdBFp9U0LhsGO7hsBscVEyH9H2/3eZZt8c97NB2FD9U2NJ+Q==", - "deprecated": "It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained", - "dependencies": { - "workbox-background-sync": "6.6.0", - "workbox-core": "6.6.0", - "workbox-routing": "6.6.0", - "workbox-strategies": "6.6.0" - } - }, - "node_modules/workbox-navigation-preload": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.6.0.tgz", - "integrity": "sha512-utNEWG+uOfXdaZmvhshrh7KzhDu/1iMHyQOV6Aqup8Mm78D286ugu5k9MFD9SzBT5TcwgwSORVvInaXWbvKz9Q==", - "dependencies": { - "workbox-core": "6.6.0" - } - }, - "node_modules/workbox-precaching": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.6.0.tgz", - "integrity": "sha512-eYu/7MqtRZN1IDttl/UQcSZFkHP7dnvr/X3Vn6Iw6OsPMruQHiVjjomDFCNtd8k2RdjLs0xiz9nq+t3YVBcWPw==", - "dependencies": { - "workbox-core": "6.6.0", - "workbox-routing": "6.6.0", - "workbox-strategies": "6.6.0" - } - }, - "node_modules/workbox-range-requests": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.6.0.tgz", - "integrity": "sha512-V3aICz5fLGq5DpSYEU8LxeXvsT//mRWzKrfBOIxzIdQnV/Wj7R+LyJVTczi4CQ4NwKhAaBVaSujI1cEjXW+hTw==", - "dependencies": { - "workbox-core": "6.6.0" - } - }, - "node_modules/workbox-recipes": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.6.0.tgz", - "integrity": "sha512-TFi3kTgYw73t5tg73yPVqQC8QQjxJSeqjXRO4ouE/CeypmP2O/xqmB/ZFBBQazLTPxILUQ0b8aeh0IuxVn9a6A==", - "dependencies": { - "workbox-cacheable-response": "6.6.0", - "workbox-core": "6.6.0", - "workbox-expiration": "6.6.0", - "workbox-precaching": "6.6.0", - "workbox-routing": "6.6.0", - "workbox-strategies": "6.6.0" - } - }, - "node_modules/workbox-routing": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.6.0.tgz", - "integrity": "sha512-x8gdN7VDBiLC03izAZRfU+WKUXJnbqt6PG9Uh0XuPRzJPpZGLKce/FkOX95dWHRpOHWLEq8RXzjW0O+POSkKvw==", - "dependencies": { - "workbox-core": "6.6.0" - } - }, - "node_modules/workbox-strategies": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.6.0.tgz", - "integrity": "sha512-eC07XGuINAKUWDnZeIPdRdVja4JQtTuc35TZ8SwMb1ztjp7Ddq2CJ4yqLvWzFWGlYI7CG/YGqaETntTxBGdKgQ==", - "dependencies": { - "workbox-core": "6.6.0" - } - }, - "node_modules/workbox-streams": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.6.0.tgz", - "integrity": "sha512-rfMJLVvwuED09CnH1RnIep7L9+mj4ufkTyDPVaXPKlhi9+0czCu+SJggWCIFbPpJaAZmp2iyVGLqS3RUmY3fxg==", - "dependencies": { - "workbox-core": "6.6.0", - "workbox-routing": "6.6.0" - } - }, - "node_modules/workbox-sw": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.6.0.tgz", - "integrity": "sha512-R2IkwDokbtHUE4Kus8pKO5+VkPHD2oqTgl+XJwh4zbF1HyjAbgNmK/FneZHVU7p03XUt9ICfuGDYISWG9qV/CQ==" - }, - "node_modules/workbox-webpack-plugin": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-webpack-plugin/-/workbox-webpack-plugin-6.6.0.tgz", - "integrity": "sha512-xNZIZHalboZU66Wa7x1YkjIqEy1gTR+zPM+kjrYJzqN7iurYZBctBLISyScjhkJKYuRrZUP0iqViZTh8rS0+3A==", - "dependencies": { - "fast-json-stable-stringify": "^2.1.0", - "pretty-bytes": "^5.4.1", - "upath": "^1.2.0", - "webpack-sources": "^1.4.3", - "workbox-build": "6.6.0" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "webpack": "^4.4.0 || ^5.9.0" - } - }, - "node_modules/workbox-webpack-plugin/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/workbox-webpack-plugin/node_modules/webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dependencies": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - }, - "node_modules/workbox-window": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.6.0.tgz", - "integrity": "sha512-L4N9+vka17d16geaJXXRjENLFldvkWy7JyGxElRD0JvBxvFEd8LOhr+uXCcar/NzAmIBRv9EZ+M+Qr4mOoBITw==", - "dependencies": { - "@types/trusted-types": "^2.0.2", - "workbox-core": "6.6.0" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/ida_prod/frontend/frontend/package.json b/ida_prod/frontend/frontend/package.json deleted file mode 100644 index 8a897554..00000000 --- a/ida_prod/frontend/frontend/package.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "frontend", - "version": "0.1.0", - "private": true, - "dependencies": { - "@testing-library/dom": "^10.4.0", - "@testing-library/jest-dom": "^6.6.3", - "@testing-library/react": "^16.2.0", - "@testing-library/user-event": "^13.5.0", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "react-scripts": "5.0.1", - "web-vitals": "^2.1.4" - }, - "scripts": { - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test", - "eject": "react-scripts eject" - }, - "eslintConfig": { - "extends": [ - "react-app", - "react-app/jest" - ] - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } -} diff --git a/ida_prod/frontend/frontend/public/favicon.ico b/ida_prod/frontend/frontend/public/favicon.ico deleted file mode 100644 index a11777cc..00000000 Binary files a/ida_prod/frontend/frontend/public/favicon.ico and /dev/null differ diff --git a/ida_prod/frontend/frontend/public/index.html b/ida_prod/frontend/frontend/public/index.html deleted file mode 100644 index 0eb6c965..00000000 --- a/ida_prod/frontend/frontend/public/index.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - React App - - - -
    - - - diff --git a/ida_prod/frontend/frontend/public/logo192.png b/ida_prod/frontend/frontend/public/logo192.png deleted file mode 100644 index fc44b0a3..00000000 Binary files a/ida_prod/frontend/frontend/public/logo192.png and /dev/null differ diff --git a/ida_prod/frontend/frontend/public/logo512.png b/ida_prod/frontend/frontend/public/logo512.png deleted file mode 100644 index a4e47a65..00000000 Binary files a/ida_prod/frontend/frontend/public/logo512.png and /dev/null differ diff --git a/ida_prod/frontend/frontend/public/manifest.json b/ida_prod/frontend/frontend/public/manifest.json deleted file mode 100644 index 080d6c77..00000000 --- a/ida_prod/frontend/frontend/public/manifest.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "short_name": "React App", - "name": "Create React App Sample", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - }, - { - "src": "logo192.png", - "type": "image/png", - "sizes": "192x192" - }, - { - "src": "logo512.png", - "type": "image/png", - "sizes": "512x512" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" -} diff --git a/ida_prod/frontend/frontend/public/robots.txt b/ida_prod/frontend/frontend/public/robots.txt deleted file mode 100644 index e9e57dc4..00000000 --- a/ida_prod/frontend/frontend/public/robots.txt +++ /dev/null @@ -1,3 +0,0 @@ -# https://www.robotstxt.org/robotstxt.html -User-agent: * -Disallow: diff --git a/ida_prod/frontend/frontend/src/App.css b/ida_prod/frontend/frontend/src/App.css deleted file mode 100644 index 74b5e053..00000000 --- a/ida_prod/frontend/frontend/src/App.css +++ /dev/null @@ -1,38 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - height: 40vmin; - pointer-events: none; -} - -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } -} - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #61dafb; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/ida_prod/frontend/frontend/src/App.js b/ida_prod/frontend/frontend/src/App.js deleted file mode 100644 index fd02a121..00000000 --- a/ida_prod/frontend/frontend/src/App.js +++ /dev/null @@ -1,27 +0,0 @@ -import { useEffect, useState } from "react"; - -function App() { - const [data, setData] = useState(null); - - useEffect(() => { - const fetchData = async () => { - try { - const response = await fetch(`${process.env.REACT_APP_API_URL}/api/data/`); - const result = await response.json(); - setData(result.message); - } catch (error) { - console.error("Fehler beim Abrufen der Daten:", error); - } - }; - fetchData(); - }, []); - - return ( -
    -

    React & Django verbinden

    -

    {data ? data : "Lade Daten..."}

    -
    - ); -} - -export default App; diff --git a/ida_prod/frontend/frontend/src/App.test.js b/ida_prod/frontend/frontend/src/App.test.js deleted file mode 100644 index 1f03afee..00000000 --- a/ida_prod/frontend/frontend/src/App.test.js +++ /dev/null @@ -1,8 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import App from './App'; - -test('renders learn react link', () => { - render(); - const linkElement = screen.getByText(/learn react/i); - expect(linkElement).toBeInTheDocument(); -}); diff --git a/ida_prod/frontend/frontend/src/api.js b/ida_prod/frontend/frontend/src/api.js deleted file mode 100644 index 4a6bc198..00000000 --- a/ida_prod/frontend/frontend/src/api.js +++ /dev/null @@ -1,6 +0,0 @@ -const API_URL = process.env.REACT_APP_API_URL; - -export const fetchData = async () => { - const response = await fetch(`${API_URL}/data/`); - return response.json(); -}; \ No newline at end of file diff --git a/ida_prod/frontend/frontend/src/index.css b/ida_prod/frontend/frontend/src/index.css deleted file mode 100644 index ec2585e8..00000000 --- a/ida_prod/frontend/frontend/src/index.css +++ /dev/null @@ -1,13 +0,0 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; -} diff --git a/ida_prod/frontend/frontend/src/index.js b/ida_prod/frontend/frontend/src/index.js deleted file mode 100644 index d563c0fb..00000000 --- a/ida_prod/frontend/frontend/src/index.js +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react'; -import ReactDOM from 'react-dom/client'; -import './index.css'; -import App from './App'; -import reportWebVitals from './reportWebVitals'; - -const root = ReactDOM.createRoot(document.getElementById('root')); -root.render( - - - -); - -// If you want to start measuring performance in your app, pass a function -// to log results (for example: reportWebVitals(console.log)) -// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals -reportWebVitals(); diff --git a/ida_prod/frontend/frontend/src/logo.svg b/ida_prod/frontend/frontend/src/logo.svg deleted file mode 100644 index 9dfc1c05..00000000 --- a/ida_prod/frontend/frontend/src/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/ida_prod/frontend/frontend/src/reportWebVitals.js b/ida_prod/frontend/frontend/src/reportWebVitals.js deleted file mode 100644 index 5253d3ad..00000000 --- a/ida_prod/frontend/frontend/src/reportWebVitals.js +++ /dev/null @@ -1,13 +0,0 @@ -const reportWebVitals = onPerfEntry => { - if (onPerfEntry && onPerfEntry instanceof Function) { - import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { - getCLS(onPerfEntry); - getFID(onPerfEntry); - getFCP(onPerfEntry); - getLCP(onPerfEntry); - getTTFB(onPerfEntry); - }); - } -}; - -export default reportWebVitals; diff --git a/ida_prod/frontend/frontend/src/setupTests.js b/ida_prod/frontend/frontend/src/setupTests.js deleted file mode 100644 index 8f2609b7..00000000 --- a/ida_prod/frontend/frontend/src/setupTests.js +++ /dev/null @@ -1,5 +0,0 @@ -// jest-dom adds custom jest matchers for asserting on DOM nodes. -// allows you to do things like: -// expect(element).toHaveTextContent(/react/i) -// learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom'; diff --git a/ida_prod/requirements.txt b/ida_prod/requirements.txt deleted file mode 100644 index 9ecd9896..00000000 --- a/ida_prod/requirements.txt +++ /dev/null @@ -1,9 +0,0 @@ -Django -gunicorn -django-cors-headers -djangorestframework -whitenoise -openai -Flask -requests -gunicorn \ No newline at end of file diff --git a/ida_prod/start.sh b/ida_prod/start.sh deleted file mode 100644 index 276092ae..00000000 --- a/ida_prod/start.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -# Installiere Abhängigkeiten -cd backend -python -m venv venv -source venv/bin/activate -pip install -r requirements.txt - -# Migration durchführen -python manage.py migrate -python manage.py collectstatic --noinput - -# React bauen -cd ../frontend -npm install -npm run build - -# React-Frontend nach Django-Statisches-Verzeichnis verschieben -cp -r build/* ../backend/staticfiles/ - -# Starte Gunicorn (Django-Server) -cd ../backend -gunicorn backend.wsgi --bind 0.0.0.0:8000 diff --git a/notes/changelog.txt b/notes/changelog.txt new file mode 100644 index 00000000..403233c1 --- /dev/null +++ b/notes/changelog.txt @@ -0,0 +1,656 @@ +....................... TASKS + + + +----------------------- OPEN + +PRIO1: + +bitte eliminiere alle "waiting_for_user" flags, weil nie auf den user gewartet wird. Dies ist irreführend. + +der ablauf ist so: +- user startet workflow (ohne id --> neu) oder (mit id --> bestehenden weiterführen) +- damit beginnt das polling +- wenn der workflow fertig ist wird er abgeschlossen mit dem prompttext an den user. dazu sollte ein flag in der art "antwort komplett" gesendet werden. +- ein "stop" des users beendet den workflow sofort mit dem flag "antwort komplett" +- sobald das frontend alle messages bis "antwort komplett" im frontend erfasst hat, ist der workflow fertig mit den anpassungen von buttons, etc. + +kannst du mir bitte angeben, wo im code was anzupassen ist, und was entfernt werden kann, da es "waiting for user" in dieser form nicht gibt. +das frontend muss nur wissen, wann ein user prompt gesendet wurde, denn dann startet das polling. und es muss wissen, wann entweder der user "Stop" gedürckt hat, oder wann der user für einen neuen prompt aufgefordert wird, weil das backend mit dem workflow fertig ist. beim erneuten user prompt ist es wichtig, dass alle messages aus dem backend im frontend geladen werden und keine vergessen wird. vielleicht hast du dafür eine geeignete methode. + + + +Dokumenterzeugung geht noch nicht. +- dokumente sollen autmatisch als solche in der datenbank-tabelle files erzeugt werden und in der db als message-objekt integriert werden. + +Setup intelligent agents: +- moderator: flow + - ai to get list of agents (without user in the list) with their task and result shaping + - to run all agents --> messages + - ai to get summary and user prompt based on question from user + - user WITH pprompt +- analyze image: + - NOT to call when image is loaded + - ai to read image with prompt +- webcrawler: + - ai to give a list of url and a list of key-sentences and 3 websearch-engines to search + - search pages and collect content-list with REFERENCE + - ai to summarize content + - return summary with referencelist +- documenter: ai to give generic prompt in 2 steps + - 1 table of content including summary + - 2 content per chapter +- coder + - identify available routines and connectors (e.g. sharepoint or mail), make list of functions with parameters + - ai to give steps with functioncalls and required result with format + - write code + - run code in env + - send back result + + +ENV Variable setzen (extract from code) und config in .gitignore für example.env + +Database to remove from backend + +workflow.css --> cleanup, later definition is newer + +file content to read with propmt for file --> prompt prepared for the specific files + + + +PRIO2: + +Integrate NDA Text as modal form - Data governance agreement by login with checkbox + +Test reference find in prompt? - if not sufficient to take subroutine to reference to "the single file" or to the relevant file + +backend: all object actions in interfaces generic for the objects in models for CRU-methods + +frontend: no labels definition + +sharepoint connector with document search, content search, content extraction + +Implement Connector für Agent Code dev + execute +- venv für ihn machen und angeben, wo er ausführen kann + +coder: to include available functions and connectors to the prompt for coding + +webcrawler: +- asks ai for steps to do --> List +- Keine Listen auf deutsch etc., sondern generisch + +add connector to myoutlook + + + +----------------------- DONE + +DOKUS +Doku des Systems für Investoren (Hi-level Struktur, Integrationsfähigkeit und Skalierbarkeit) +Doku des Systems für Code Integration +Release Notes (was kann das Teil) +Log der Anpassungen +Systemarchitektur (Grundsätze der Architektur, Komponenten und deren Aufbau) + + + +Workflow module refactored + +Summary of Changes +I've refactored the workflow module into separate modules with clear responsibilities: +1. workflow.js - Main Coordinator + +Acts as the central controller for the workflow functionality +Coordinates interactions between all other modules +Manages the workflow lifecycle (starting, stopping, resetting) +Contains minimal direct DOM manipulation +Maintains the core workflow state + +2. workflow_ui.js - UI Rendering and Layout + +Handles all DOM rendering functionality +Manages layout changes (resize, expand/collapse) +Sets up UI-related event listeners +Updates visual status (buttons, statistics) +Completely separates UI concerns from data and business logic + +3. workflow_data.js - Data Management + +Handles all API communication (via utils.js) +Centralizes state management for workflow data +Processes data from API responses +Manages file references and retrieval +Handles data statistics tracking + +4. workflow_features.js - Feature Modules + +Manages chat functionality +Handles file upload/processing +Controls log management +Processes user input +Encapsulates drag-and-drop functionality + +5. workflow_utils.js - Helper Functions + +Contains shared utility functions +Text formatting helpers +File-related utility functions +Error/dialog management +Data validation and conversion + + + +* Refactoring-Auftrag: Workflow-System-Überarbeitung * + +## Übersicht +Dieser Auftrag umfasst eine vollständige Überarbeitung des Workflow-Ablaufs sowohl im Frontend als auch im Backend. Das Ziel ist eine Vereinfachung der Benutzeroberfläche, bessere Modularisierung des Codes und Optimierung der Datenhaltung, sowie Hinzufügen einer Löschfunktion für einzelne Nachrichten zur Datenmengenbegrenzung. + +## Anforderungen Frontend + +### 1. UI-Elemente entfernen +- Vollständige Entfernung der Sektion "Prompt eingeben" +- Entfernung aller Buttons im Bereich "Ausführung & Ergebnisse", mit Ausnahme des "Workflow stoppen"-Buttons, der nur während eines aktiven Workflows sichtbar sein soll +- Der "Workflow stoppen"-Button soll automatisch ausgeblendet werden, sobald eine Benutzereingabe angefordert wird +- Entfernung der Anzeige des ausgewählten Workspaces in der index.html + +### 2. User-Input-Modul auslagern +- Extraktion aller Funktionen zur Benutzereingabe aus "workflow.js" in ein neues separates Modul "workflow_userinput.js" +- Das neue Modul soll sowohl für den initialen Prompt als auch für alle weiteren Benutzerantworten im Workflow verwendet werden + +### 3. Funktionalität User-Input-Modul +Das neue "workflow_userinput.js" Modul soll folgende Funktionen enthalten: +- Erkennung, wann eine Benutzereingabe erforderlich ist (initial und wenn der User-Agent aufgerufen wird) +- Auswahl vordefinierter Prompts ermöglichen +- Datei-Upload und Drag & Drop Funktionalität +- Senden des Prompts an das Backend mit der workflowid, falls vorhanden +- Implementation einer Löschfunktion ("x") für jede Nachricht und angehängte Datei im Chat-Protokoll + +### 4. Nachrichtenlöschfunktion +- Jede Nachricht im Multi-Agent Chat Protokoll erhält einen "x"-Button zum Löschen +- Löschfunktion soll auch für Dateien innerhalb einer Nachricht implementiert werden +- Nahtlose API-Integration mit dem neuen DELETE-Endpunkt für Nachrichten + +## Anforderungen Backend + +### 1. Route "workflow.py" +- Reduzierung auf minimale Routing-Funktionalität +- Verlagerung aller Implementierungslogik in den "agentservice_workflow_manager" +- Hinzufügen eines neuen Endpunkts: `DELETE /api/workflows/{workflow_id}/messages/{message_id}` + +### 2. Workflow-Manager-Logik +Überarbeitung des "agentservice_workflow_manager" mit folgender Ablauflogik: +1. Workflow-Initialisierung: + - Bei neuem Workflow: Initialisierung mit leerem Messages-Objekt + - Bei bestehendem Workflow: Übernahme des vorhandenen Messages-Objekts + +2. Message-Objekt-Verwaltung: + - Starten eines neuen Message-Objekts für jede Interaktion + - Vollständige Nutzung des Datenmodells aus "lucydom_model.py" + - Korrekte Speicherung in der Datenbank + +3. Dateivorbereitung: + - Erstellung von Datei-Kontexten und Integration ins neueste Message-Objekt + - Extraktion und Speicherung von Dateiinhalten + - Formatierung der Daten für die Agenten-Verarbeitung + +4. Agent-Workflow: + - Initialisierung verfügbarer Agenten einschließlich User-Agent + - Implementierung der Moderator-Entscheidungslogik (bereits implementiert) -> entweder wird eine liste von agenten verarbeitet (OHNE User agent!), oder der user agent aufgerufen. + 4a) - Ausführung der Agenten in der festgelegten Reihenfolge + 4b) - Abschluss mit User-Agent und Prompt-Aufforderung (Anmerkung: die wofkflow id mitgeben, damit nach dem senden der user antwort im frontend der workflow weitergeführt wird bei Punkt 1. Aber im Backend ist es hier fertig) + +5. Nachrichten-Löschfunktion: + - Implementierung der Löschlogik für einzelne Nachrichten + - Vollständige Entfernung der Nachrichtendaten auch aus dem Backend-Speicher + +## Betroffene Dateien + +### Frontend-Dateien: +1. `workflow.js` - Umfassende Überarbeitung und Entfernung von User-Input-Funktionalität +2. `workflow_userinput.js` - Neue Datei für die ausgelagerte User-Input-Funktionalität +3. `index.html` - Entfernung der nicht mehr benötigten UI-Elemente und Integration des neuen Moduls +4. `main.js` - Anpassungen für die geänderte Modularität +5. `globalState.js` - Ggf. Anpassungen für die geänderte Workflow-Struktur +6. `utils.js` - Erweiterung um die neue DELETE-Funktion für Nachrichten + +### Backend-Dateien: +1. `workflows.py` - Vereinfachung und Hinzufügen des neuen DELETE-Endpunkts +2. `agentservice_workflow_manager.py` - Umfassende Überarbeitung der Workflow-Logik +3. `lucydom_interface.py` - Erweiterung um Methoden zum Löschen von Nachrichten +4. `agentservice_agent_user.py` - Anpassungen für das neue User-Input-Handling + +## Fehlerbehandlung +- Frontend: + - Konsistente Fehlerbehandlung für alle API-Aufrufe implementieren + - Benutzerfreundliche Fehlermeldungen bei fehlgeschlagenen Operationen anzeigen + - Status-Indikatoren während laufender Operationen (z.B. Löschen von Nachrichten) + +- Backend: + - HTTP-Statuscode 404 zurückgeben, wenn eine zu löschende Nachricht nicht gefunden wird + - Sicherstellen, dass alle Workflow-Operationen Transaktionssicherheit bieten + - Ausführliche Logging-Funktionalität für Fehlerdiagnose + +## Richtlinien zur Codequalität +- Clean Code-Prinzipien beachten (DRY, SOLID) +- Konsistente Benennung und Dokumentation +- Entfernung ungenutzter Funktionen und Code-Teile +- Ausreichende Kommentierung für komplexe Logik + +## Zusätzliche Hinweise +- Daten dürfen ohne Bedenken gelöscht werden +- Keine Übergangsstrategie erforderlich, System startet neu +- Keine Bestätigungsdialoge für das Löschen von Nachrichten erforderlich +- Keine speziellen Berechtigungsanforderungen für das Löschen von Nachrichten + + + + +*WORKFLOW* + +ich habe das backend komplett angepasst mit dem workflow und dem datenmodell. die wichtigsten anpassungen sind das datenmodell für workflow und messages. Nun muss das Frontend entsprechend angepasst werden. + + +hier der ablauf des workflows im backend zur information: + +1. Der User kann (A) einen neuen Workflow starten oder (B) bei einem bestehenden Workflow einen user Input liefern. Die Endpunkte liegen bei. +. Varinate (A): Der User sendet einen Prompt mit Dateien für einen neuen Workflow. Damit wird ein neuer leerer Workflow erstellt +. Varinate (B): Es erfolgt ein User Input mit allenfalls Dateien zu einem bestehenden Workflow. Als Input wird ein messages objekt geliefert. Der workflow Status wird auf "running" gesetzt. + +2. Message Initialisierung: Das letzte Message Objekt wird abgeschlossen (falls eines existiert) und ein neues Message Object erstellt. Dieses wird nun komplettiert. +3. Dateivorbereitung: Datei-Kontexte werden erstellt und ins neuste Message objekt abgefüllt. Dateiinhalte werden gelesen, extrahiert und ins message objekt abgefüllt. Daten werden für die Verarbeitung durch die Agenten formatiert +4. Agent-Initialisierung: Die verfügbaren Agenten werden geladen inklusive der user agent. +5. Moderator-Entscheidung +6. Agent-Ausführung, bis am Schluss der User aufgerufen wird, um einen Input zu geben. +7. Nun ist der "User Agent" an der Reihe. Der user Input hat immer obendran die Frage, die dem User gestellt wird. der user input hat die workflow id dabei. +hier ist der workflow beendet. wenn der user seine antwort sendet, geht es weiter bei punkt 1 Variante (B) + +Dies zusätzlich anzupassen: + +- Der initiale Prompt mit File-Upload ist gleichzeitig auch der Prompt, der dem User angeboten wird, wenn im Chat ein Input von ihm nötig ist. Dieses Eingabefeld soll an die Stelle verschoben werden, wo aktuell der User-Dialog angezeigt wird bei "wait for user". So gibt der User die Daten immer am gleichen Ort ein. + +- Für den File Upload sollen zwei Methoden möglich sein. + -- a: Upload-Button direkt unten am Prompt. Jedes geladene File wird dann als kleines Icon mit dem Filenamen unter dem Prompt ergänzt mit einem "x", damit es wieder gelöscht werden kann, wenn nicht benötigt. Wenn Text aus dem File extrahiert werden konnte, so ist das Feld mit dem Dateinamen grün, sonst rot. Ist Dir klar, wie Du diese Information abfragen kannst? - Wenn der User den Prompt absetzt, wird dieser über das Backend anschliessend in die Resultate geliefert. Du musst dies nicht im Frontend machen, sonst haben wir es doppelt. + -- b: Drag & Drop: Ein File kann in den Prompt-Bereich gezogen werden, dann wird es auch hochgeladen. + +- Das Auswahlfenster für vordefinierte Prompts soll direkt über dem Eingabefeld für den Benutzer sein. + +- Die Buttons zur Steuerung des Workflows sollen oben am Bereich "Ausführung & Ergebnisse" verschoben werden. + +- Der Bereich "1. Dateien auswählen" entfällt somit, da integriert bei mUser Prompt. + +- Der Bereich "2. Promot eingeben oder auswählen" entfällt auch + +- Der Bereich "3. Agenten auswählen" entfällt auch + +- Resultateintrag: Jeder Eintrag im Resultat-Log hat zuoberst Icons mit den Files, welche die Agenten zurückliefern, dann den Text dazu. Jedes Icon eines Files hat die Buttons "Download" und "Copy" (für Clipboard") und "Vorschau" + +- Damit entfällt der Bereich "Workflow-Konfiguration" komplett. Die beiden Bereiche sollen aber beibehalten werden, einfach mit anderem Inhalt. Im aktuellen Bereich "Workflow-Konfiguration" soll neu der Bereich "Ausführung & Ergebnisse" drin sein. Im aktuellen Bereich"Ausführung & Ergebnisse" soll NEU der Bereich "Dateivorschau" hinkommen. Dort kann eine von den Agenten gelieferte Datei (siehe Punkt "Resultateintrag" zuvor) als "Vorschau" angeschaut werden. Oben rechts hat es zwei Icons "Download" und "Copy" (für Clipboard). + +* WEITERE ANPASSUNGEN * +- Die Objekte "agents" und "workspaces" sind eliminiert und zu entfernen. Somit fallen auch die entsprechenden Navigationseinträge weg und alle Funktionen im Zusammenhang mit Workspaces. Es gibt keine Workspaces mehr. + + +Kannst Du vor der Umsetzung prüfen, ob Du alle nötigen Dateien und Informationen hast und mir zusammenstellen, was Du machen wirst? + + + +Ich möchte den agentenchat workflow ändern. kannst du mir bitte dazu in einem ersten schritt das backend anpassen. + +1. das datenobjekt *workspaces" und "agents" wird nicht mehr benötigt, und kann entfernt werden. Der user arbeitet mit einzelnen workflows. Agenten sind systemseitig fix definiert. + +2. alle workflow router endpunkte bleiben bestehen, wie sie sind + +3. Neue Objektstruktur für den workflow ablauf: + +workflow = +{ + // Core workflow properties + "id": "workflow_uuid", + "name": "Analysis Workflow", + "mandate_id": 123, + "user_id": 456, + "status": "running", // "running", "failed", "stopped" + "started_at": "2025-03-29T14:15:00.000Z", + "last_activity": "2025-03-29T14:45:00.000Z", + "current_round": 1, + "waiting_for_user": false, + + // Performance statistics (sum) + "data_stats": { + "total_processing_time": 3.9, + "total_token_count": 857, + "total_bytes_semt": 1026323, + "total_bytes_received": 4200, + } + + // Messages array - main conversation history with structured message objects + "messages": [], + + // Logs + "logs": [ + { + "id": "log_uuid1", + "message": "Workflow started", + "type": "info", + "timestamp": "2025-03-29T14:15:00.000Z" + } + ] + +} + +"messages": [ + { + // Core message properties + "id": "msg_uuid", // Unique identifier for each message + "workflow_id": "workflow_uuid", // Reference to the parent workflow + "parent_message_id": "msg_previous_uuid", // Reference to message being responded to + "started_at": "2025-03-29T14:30:00.000Z", // Single timestamp for message creation + "finished_at": "2025-03-29T14:30:00.000Z", // Single timestamp for message closing, when next message is created + "sequence_no": 1, // Optional, but useful for ordering within workflow + + // Status information + "status": "completed", // message status: "pending", "processing", "completed", "failed" + + // Role instead of agent information + "role": "system", // "system", "user", "assistant" - who created this message + + // Metadata for statistics and accounting + "data_stats": { + "processing_time": 2.5, // Time taken to generate in seconds + "token_count": 1205, // Token count (for AI models) + "bytes_sent": 4096, // Data sent to generate this message + "bytes_received": 8192, // Data received + } + + // Documents section - includes prompt and all referenced files + "documents": [ + { + // Document metadata + "id": "doc_uuid", + "source": { + "type": "prompt", // "prompt", "file", "clipboard" + "path": "/full/path/to/file.txt", // Storage path (for files) + "name": "display_filename.txt", + "size": 1024, // Size in bytes + "lines": 42, // Line count (for text files) + "content_type": "text/plain", // MIME type + "upload_date": "2025-03-29T14:30:00.000Z" + }, + + // Document contents (can have multiple parts) + "contents": [ + { + "label": "Main Content", // Optional label + "type": "text", // "text", "image", "chart", etc. + "text": "The actual text content", + "is_extracted": true // Flag if this is extracted from original file + } + ] + } + ], + + } +] + + +4. Die Schritte in einem Workflow (neu) - bitte den code revidieren und alle unnötigen teile entfernen. + + 4.1 Der User kann (A) einen neuen Workflow starten (Enpunkt api/workflows/run) oder (B) bei einem bestehenden Workflow einen user Input liefern (Endpunkt /api/workflows/{workflow_id}/user-input). Mit beiden Varianten soll bei execute_workflow() gestartet werden. + + . Varinate (A): Der User sendet einen Prompt mit Dateien für einen neuen Workflow. Damit wird ein neuer Workflow mit execute_workflow() erstellt, aber noch ohne message objekt. Als Input wird ein messages objekt geliefert. Initialer workflow Status wird auf "running" gesetzt. + + . Varinate (B): Es erfolgt ein User Input mit allenfalls Dateien zu einem bestehenden Workflow. Als Input wird ein messages objekt geliefert. Der workflow Status wird auf "running" gesetzt. + + 4.2.- Message Initialisierung: Das letzte Message Objekt wird abgeschlossen (falls eines existiert) und ein neues Message Object erstellt. Dieses wird nun komplettiert. + + 4.3- Dateivorbereitung: Datei-Kontexte werden mit prepare_file_contexts() erstellt und ins neuste Message objekt abgefüllt. Dateiinhalte werden mit read_file_contents() gelesen, extrahiert und ins message objekt abgefüllt. + Daten werden für die Verarbeitung durch die Agenten formatiert + + 4.4 Agent-Initialisierung: Die verfügbaren Agenten werden mit initialize_agents() aus dem Modul "agentservice_part_agents" geladen inklusive der user agent. + + 4.5. Moderator-Entscheidung: Es gibt keinen agenten "Moderator". Anhand des des neusten Message Objektes und den Profilen der verfügbaren Agenten wird mit dem OpenAI Call abgefragt, wie die Anfrage gelöst werden soll. Als Resultat-Format soll ein json-objekt vorgegeben werden, welcher agent welchen job (=Prompt für diesen) ausführen soll, mit welchen antworten und welchen datenobjekten. dazu sind keine weiteren subfunktionen nötig. das antwortformat soll so vorgegeben werden, dass zwingend pro auftrag verfügbare agenten rückgemeldet werden. Das Agentenset soll immer entweder nur der User oder nur system-agenten sein. somit ist das antwortformat eine liste mit agenten und deren aufträgen. + + 4.6. Agent-Ausführung: Falls eine agentenliste zürückgegeben wird (und nicht der user), werden die Agenten in der angegeben Sequenz aufgerufen werden, um ihren Beitrag zu liefern. Agent-Antworten werden mit create_agent_result() ins message objekt integriert, die verschiedenen files separiert. Als nächstes wird mit den gelieferten Antworten der Agenten (nur dieser Teil, nicht die früheren Nachrichten) über den OpenAI Call eine Zusammenfassung erstellt und als Input-Text dem user Agenten übergeben, welcher nun als nächsten Agenten ausgewählt wird. Der ablauf wird gestoppt, wenn der Workflow manuell mit stop_workflow() gestoppt wird (status auf "stopped"), oder ein Fehler auftritt (status auf "failed"). + + 4.7. Nun ist der "User Agent" an der Reihe. Der Workflow-Status wird auf "waiting_for_user" gesetzt. Der ganze Teil mit _process_user_input() etc. entfällt. Nach der Benutzereingabe wird der Workflow nicht mit _continue_workflow_after_user_input() fortgesetzt, sondern regulär wieder bei Punkt 4.1 über den Zweig (B). + + 4.8. Protokollierung: Jeder Schritt wird mit _add_log() protokolliert. Logs werden im Workflow-Objekt gespeichert. + + 4.9. Hier endet der Workflow regulär, bis der User eine neue Anfrage macht. Das heisst, es benötigt keine Moderatoren-Checks mehr, keine maximale Rundenzahl. Der Workflow wird mit save_workflow_results() gespeichert. + + +5. Fortlaufendes Polling: Der Client kann den Workflow-Status mit get_workflow_status() abfragen. Protokolle können mit get_workflow_logs() abgerufen werden. Ergebnisse können mit get_workflow_results() abgerufen werden. + + +6. agents: Die verfügbaren Agenten werden mit initialize_agents() aus dem Modul "agentservice_part_agents" geladen. die agentendaten, werden in separaten dateien abgelegt, damit dies wartbar ist. Es werden diese agenten-module vorbereitet: +.agentservice_agent_user +.agentservice_agent_coder +.agentservice_agent_analyst +.agentservice_agent_webcrawler +.agentservice_agent_sharepoint +.agentservice_agent_documentation +Pro agent werden diese attribute definiert: +.name +.description +.capabilities +Jeder Agent hat dann seine eigenen Funktionen in seinem File integriert, die er benötigt. + +7. Konnektorenbereinigung: +- Alle Konnectoren in einen subfolder "connectors" verschieben, d.h. alle files mit "connector_..." +- Die zwei Konnektoren "connector_aichat..." so umschreiben, dass sie daten als Input im format des messgaes Objekt gemäss Punkt 3 als input übernehmen und auch wieder zurückgeben. + +8. geänderte speicherng von workflows: Bitte den code so anpassen, dass workflows als datenbankobjekte gespeichert werden, analog so wie prompts. +D.h. die routes für "workflows" ergänzen mit "GET /api/workflows", "PUT /api/workflows/{workflow_id}", "DELETE /api/workflows/{workflow_id}" +Die Route "POST /api/workflows/run" umbenennen in "POST /api/workflows" +Die Route "/api/workflows/{workflow_id}/results" umbenennen in "GET /api/workflows/{workflow_id}" +Sinngemäss alle module anpassen und die Datenbankklassen vorbereiten. + +Die Buttons "Workflow starten" und "Zurücksetzen" haben keinen Rahmen. Ist hier ggf. die Style Class falsch oder nicht appliziert? + +Anpassung des Visuals "Ausführung & Ergebnisse": +- Das Ausführungsprotokoll so belassen. Einen Button rechts von den anderen zwei Buttons (alle anzeigen / Details zuklappen) ergänzen, für dies mit dem Ausführungsprotokollfenster: toggle function collapse and restore +- Die Bereiche "Multi-Agent-Chat" und "Ergebnisse" machen so keinen Sinn. Diese beiden Bereiche bitte zusammenlegen in einen grossen Bereich mit dem Namen "Multi-Agent Chat Area". Dort laufend die Messages der Agenten in einer HTML-Ansicht der Messages protokollieren. Jeweils der Name des Agenten im Titel und darunter seine Message. Die letzte Message soll aufgeklappt sein, alle früheren sollen jeweils zugeklappt sein, aber durch den User soll ein toggle pro Message möglich sein, um die Details zu sehen. + + +Kannst Du den Ablauf des Agenten-Chats wie folgt optimieren: +- Bei jedem Chat einen "User Agent" mit dem Namen des eingelogten Benutzers ergänzen. Wenn etwas im Chat nicht klar ist, oder zusätzliche Informationen nötig sind, so fragt er den User Agent. Auch bevor er den Chat beendet, fragt er den User Agent, ob dieser einverstanden ist. +- Wenn der User Agent eine Anfrage erhält, so kann er direkt unter der Chat History im Bereich ereiche "Multi-Agent-Chat" seinen Text in einem mehrzeiligen Textfeld erfassen. Er kann auch zusätzliche Files hochladen. Wenn er "Enter" drückt, werden die zusätzlichen Daten mit den ergänzten Files zur Message ergänzt, das Eingabefenster verschwindet wieder und der Moderator führt den Chat fort. Immer nach einer Benutzereingabe startet der Zähler wieder bei Runde 1. + +Statistik ergänzen: Kannst Du bitte rechtsbündig neben dem Titel des "Ausführungsprotokolls" laufend die Statistik nachführen, wieviele kBytes (kB) Daten über den Connector zum AI-Modell gesendet wurden (dies ist die Datengrösse des Message-Objektes) und wieviele kB an Messages zurückgeliefert wurden. Diese angabe pro Workflow-Durchlauf, also immer beim Start eines neuen Workflows wird der Zähler auf 0 gesetzt. In diesem Format: "^ 250k v 1'250k ", v und ^ durch Pfeile ersetzt. + + +In den Einstellungen des Frontends soll die Sprache des aktiven benutzers gemäss den Listenoptionen in den "...model.py" angepasst werden können. die sprache gilt dann auch für die Attributnamen in einem Formularfeld im "generic-entity.js". eine sprachänderung zieht somit eine anpassung des Users über das API nach sich, indem die Sprache in der Datenbank angepasst wird. + +kannst du die ausführungsprotokollierung anpassen? das protokoll soll laufend anzeigen, welcher assistent welches resultat produziert hat und welcher assistent aktuell am arbeiten ist. Prozentzahlen sind keine nötig, diese machen keinen sinn. das polling so beibehalten, aber wenn keine neuen Daten bereitstelen, dann beim letzten Timestamp einfach laufend "." ergänzen, bis die nächste Meldung ausgegeben wird. hast du alle daten, um dies im frontend und im backend anzupassen? + +Im Ausführungsprotokoll pro Eintrag nur den Titel zeigen und die Details zwar ins Protokoll nehmen, aber ausblenden. Der Benutzer kann dann im Protokoll die zugeklappten Texte aufklappen, um die gewünschten Details gezielt zu sehen. + +Im Front-End beim Workflow-Modul bitte das Ausführungsprotokoll-Fenster dynamisch in der Grösse anpassbar machen. in der Breite und der Höhe. Dasselbe für das Ergebnis-Fenster. Zudem die Ansicht so gestalten, dass die Fensterteile "Workflow-Konfiguration" und "Ausführung & Ergebnisse" ein- und ausgeblendet werden können, damit jeweils ein Teil die komplette Arbeitsfläche verwenden kann, weil dort viel Text stehen wird. Dies ist für den Benutzer besser. + +nun zu diesem zentralen modul. ich hätte gern, dass die daten als tabellen dargestellt und bearbeitet werden können. für view, add, modify, delete jeweils icon pro datensatz ganz links und zuoberst im header ein "new item" symbol oder text, mach einen vorschlag. + +ist es möglich, eine checkbox pro datensatz zu machen, um mehrere elemente auszuwählen und oben an der tabelle icons zu haben für mehrfach delete? + +die tabelle soll nach allen feldern gefiltert und sortiert werden können + +kannst du bitte den code so anpassen, dass main.js die seitenmodule im Anhang dynamisch erst dann lädt, wenn die entsprechende seite in der navigation aufgerufen wird? + +dann bitte main.js modularisieren, sodass dort nur funktionsaufrufe auf sub-module ausgeführt werden. das navigationsmenu nach "navigation.js" auslagern. den aufbau und betrieb des aktuellen workspaces im main.js drin lassen. + +Der aktuelle Hauptbereich mitt der Auswahl des workspaces, den zugehörigen Agenten etc ist neu ein Objekt, welches in der "mainView" dargestellt werden kann. Auch andere Objekte können in der mainView dargestellt werden und haben jeweils ihre spezifischen Paramter dazu, wie nachfolgend erklärt. + +im main.js wird ein globales objekt aller elemente erstellt, welche in der navigation enthalten sein sollen und welches die grundlage für alle funktonsaufrufe beinhaltet. damit gibt es dann im index.html keine details mehr zu den navigationen. + + +diese attribute hat das globale objekt: + +globalState +.objects +.user +.mainView + +Hier die Spezifikation der Objekte. + +.objects[...]: hat eine liste von objekten, welche im mainScreen geladen werden können. Diese Attribute pro Objekt bitte gemäss den heutigen js files im anhang sinngemäss übernehmen: +- label: Liste des Labelnamen in den verschiedenen sprachen (default, en, fr...) +- modulName: string; dieser wird verwendet für die objektklasse "js/modules/{modulname}.js" und für die html-komponente dazu "modules/part-{modulname}.html und für die calls ans backend /api/{modulname}/..." +- icon: Icon vor dem Menupunkt +- navigationContext: "left" für agents, data, prompts, users, mandates, workspaces ; "top" für sprachauswahl, logout +- isVisible (hier wird z.b. users und mandates nur angezeigt, wenn auch die berechtigung dafür besteht) +- isActive: Wenn der Menupunkt ausgewählt ist +- navigationContext: diese Optionen, wo ein Objekt ins Menu genommen wird: + --"nav_left" für agents, data, prompts, users, mandates, workspaces + --"nav_top" für sprachauswahl, logout +- navigationActionType: Was passiert, wenn auf das Menu geklickt wird. Diese Optionen: + --"module": Standard-Menu button. Es wird ein Modul in die mainView geladen. Das Modul wird erst geladen und mit den Daten initiiert, wenn der Menupunkt ausgewählt wird + --"group_open": Gruppenheader; Start einer neuen Gruppe; alle nachfolgenden Objekte der Liste sind in dieser Gruppe integriert. Die Gruppe kann im Menu auf- und zugeklappt werden. Initial Gruppe open, alle Menupunkte sichtbar + --"group_collapsed": Gruppenheader; Start einer neuen Gruppe; alle nachfolgenden Objekte der Liste sind in dieser Gruppe integriert. Die Gruppe kann im Menu auf- und zugeklappt werden. Initial Gruppe collapsed. + +.user: Attribute zum aktiven user +- mandate_id +- user_id +- username +- full_name +- language (default, en, fr, ...) +- isAdmin +- isSysAdmin +- lastWorkspaceId: Id des zuletzt genutzten Workspaces - aktuell "null" +- session: aktuell null und nicht verwendet + +.mainView: enthält immer die aktuellen Attribute, welche die Seite in der mainView nutzen kann +- currentWorkspace: objekt des aktuell ausgewählten Workspaces +- availableFiles[]: list of objects +- availableAgents[]: list of objects +- availablePrompts[]: list of objects +- currentWorkflowId: id + + +kannst du bitte part-workflow.html und workflow.js mit dem dynamischen Multi-Agent Chat aktualisieren, welcher im backend angepasst wurde und im Ausführungsprotokoll die Details eines laufenden Chats mit aufklappbaren Texten ergänzen. Das Ausführungsprotokoll-Fenster dynamisch in der Grösse anpassbar machen. + +Css aufräumen und konsolidieren für gemeinsame Klassen mit allen html und js parallel + +Admin Seite mit CRUD für User Mgmt und Mandate Management, generisch + +Im Frontend soll im generischen Formular "generic-entity.js" für ein neues Objekt die ID entweder hidden oder schreibgeschützt sein. die ID wird nicht benötigt, sondern wird erst mit dem speichern in der datenbank erstellt. d.h. nach dem speichern in der datenbank werden die daten der entsprechenden tabelle neu geladen. + + +Kannst du mir bitte code struktur und logik das 'agentservice_interface.py' anpsssen und die code struktur zur besseren wartung und weiterenwticklung verbessern: + +1. die anbindung der ai-modelle mit den entsprechenden config-daten und den funktionsaufrufen in separate dateien auslagern ("connector_ai_openai","connector_ai_webscraping"). im 'agentservice_interface.py' die connector module bei der initialisierung importieren und vorbereiten. + +2. den agenten-chat 'execute_workflow' nicht in der reihenfolge der agents ausführen, sondern als tischrunde der agents.das heisst ein AI moderator moderiert die agenten autonom und ruft anhand der produzierten antworten und der eigenschaften der agentss den jeweils nächsten geeigneten agenten anhand der 'capabilities' auf, nachdem ein agent seine antwort geliefert hat. +der initiale prompt mit den zugehörigen files und dem chatverlauf im 'LogEntry' mit den n letzten Datensätzen (n wird aus dem Config file aus der variablen Application.MAX_HISTORY gelesen) wird in ein 'message'-objekt als dictionary transformiert, welches so aussieht: + message = { + "role": "user", #--> statisch, immer so + "content": [ #--> liste der Files + { + "type": "text", + "text": prompt_text + }, + { + "type": content_type, # --> diese funktion integrieren wir später + "source": { + "type": "base64", + "media_type": mime_type, + "data": base64_file # --> hier das dateiname der jeweiligen datei + } + }, + { + "type": "text", + "text": LogEntries # --> hier die LogEinträge als Textpaket + } + ] + } +wenn der AI moderator der Meinung ist, dass die aufgabe erfüllt ist, beendet er den workflow. + + +3. initialisierungsset: beantwortet Anfragen direkt mit dem hinterlegten KI Modell, welche keine spezialisierten Agenten benötigen. Dies ist die Generierung von Text, Code, Strukturen, die Analyse von Files, Graphiken erstellen, etc. +(Agent) Organisator: Dieser analysiert den User Prompt und strukturiert die auszuführenden Aufräge sowie die nötigen zu liefernden Resultate +(Agent) Entwickler: Dieser entwickelt python code im Auftrag der anderen Agents und führt ihn anschliessend aus +(Agent) Webscrape: Ein Agent, welcher webscraping durchführt. Dieser nutzt die Funktion '_scrape_url', um eine Webseite zu scannen und den Inhalt zurückzugeben. Er kann auch den Entwickler beauftragen, einen Code zu generieren, welcher die funktion _scrape_url mit einer logik (z.B. iterativ oder batch-mässig) ausführt +(Prompt): Kannst Du mir ein paar initiale Prompts für die folgenden Fragebereiche vorbereiten, welche ausgewählt werden können: +. Web Research +. Analyse +. Protokoll +. Design + + +4. Kannst Du bitte die fehlenden CRUD Methoden in den modulen "workspaces" und "prompts" ergänzen. Ich glaube, es fehlen Post und Delete. + + +5. Datenbank-Management verbessern: In den zwei Modulen "gateway_interface.py" und "lucydom_interface" finden keine Manipulationen oder Referenzierungen mit ID's statt. Die ID's für einen neuen Datensatz werden nur in "connector_....py" modulen vergeben. Jeder datensatz hat eine unique id. in den modulen "...interface.py" werden keine id's generiert. die abfrage für die id=1 wird ersetzt mit der funktion 'get_initial_id', welche weiter unten erklärt ist. +Dazu bitte die Module anpassen und in den Modulen "connector...py" eine system-tabelle ergänzen, welche sich merkt, welche ID der erste datensatz jeder tabelle hat, denn dieser ist der jeweilige system-datensatz. dann eine funktion 'get_initial_id' erfassen, welche in den modulen Modulen "gateway_interface.py" und "lucydom_interface" aufgerufen werden kann, um die id des initialen datensatzes pro tabelle abzufragen. + + + + + +der gateway funktioniert noch nicht ganz. +kannst mir bitte die module prüfen und besser stukturieren? + +Diese anforderungen und das setting der dateien: + +models.py: die datei umbenennen in "model_lucydom.py" + - die class "User", "UserInDB", "Token" in der datei entfernen und in eine separate datei "model_gateway.py" auslagern. + - alle datentypen-definitionen sind hier, abschliessend und unabhängig vom datenbanksystem. + - alle ID's sind long-Zahlen, keine Texte + - bei jeder class und bei jedem attribut einer class ein label ergänzen, was der name des attributes bzw. der class ist, wenn dies in einem formular abgefragt wird. das label soll einen defaultwert haben und pro sprache gesetzt werden können. + - alle objekte mandantenfähig machen, d.h. bei jedem Objekt die Attribute "mandate_id" und "user_id" ergänzen. + +model_gateway.py: + - alle datentypen-definitionen sind hier, abschliessend und unabhängig vom datenbanksystem. + - alle ID's sind long-Zahlen, keine Texte + - bei jeder class und bei jedem attribut einer class ein label ergänzen, was der name des attributes bzw. der class ist, wenn dies in einem formular abgefragt wird. das label soll einen defaultwert haben und pro sprache gesetzt werden können. + - Die class "Mandate" mit den Attributen (id,name,language) ergänzen + - Bei der class "User" die "id" und "mandate_id" und "language" ergänzen + - alle objekte mandantenfähig machen, d.h. bei jedem Objekt die Attribute "mandate_id" und "user_id" ergänzen. + +database.py aufteilen in 2 files "connector_db_json.py" und "interface_lucydom.py". + +connector_db_json.py: Ein erster Konnektor von zukünftig weiteren Konnektoren + 1. Parameter, welche übergeben werden: + - DB_Folder, DB_USER und DB_APIKEY + - Kontextparamter für "mandate_id" und "user_id", welche nicht null sein dürfen. + - Die aktuelle JSON-Datenbank im Folder DB_Folder einbinden und so übernehmen, wie sie ist. Falls der Folder fehlt, diesen erstellen. + 2. Der Konnector "db" wird als Objekt zur verfügung gestellt. + 3. Es werden diese generischen Methoden im Objekt "db" zur Verfügung gestellt. jede abfrage filtert automatisch die datensätze auf die Kontextparamter "mandate_id" und "user_id", sofern diese Parameter in einem Datensatz nicht null oder "" sind. + - get_tables(optional filterkriterien): liste aller tabellen + - get_fields(table, optional filterkriterien): liste aller attribute einer tabelle + - get_schema(table, language, optional filterkriterien): objekt aller attribute einer tabelle mit ihrem Datentyp und dem Label in der entsprechenden Sprache. Ohne Sprache Angabe wird der Default Wert als Label genommen + - get_recordset(table, optional filterkriterien für fields, optional filterkriterien für records): liefert das entsprechende datenobjekt mit den Datensätzen + - record_create(table,json with attributes): ergänzt einen Datensatz im Kontext "mandate_id", alle attribute, welche nicht im "json with attributes" drin sind, werden auf die standardwerte gemäss dem models.py gesetzt + - record_delete: löscht einen Datensatz, aber nur wenn es im Kontext "mandate_id" ist, sonst Verweigerung "Not your mandate" + - record_modify: ändert einen Datensatz, aber nur wenn er im Kontext "mandate_id" ist, sonst Verweigerung "Not your mandate" + +interface_lucydom.py: Ein Interface zum Gateway, es werden weitere Interfaces folgen. Das Interface macht dies: + 1. Die Datenbank mit diesen Parametern einbinden: + - Connector "connector_db_json.py" + - Datenbank "/data_lucydom" + - Datenmodell "model_lucydom.py" + 2. Das Objekt "db" kann nun genutzt werden + 3. initialisierung der Datenbank, falls sie nicht existiert, aber nur die minimal nötigen Objekte: Der "Default Workspace" in "workspaces" + +interface_gateway.py: Ein Interface zum Gateway, es werden weitere Interfaces folgen. Das Interface macht dies: + 1. Die Datenbank mit diesen Parametern einbinden: + - Connector "connector_db_json.py" + - Datenbank "/data_gateway" + - Datenmodell "model_gateway.py" + 2. Das Objekt "db" kann nun genutzt werden + 3. initialisierung der Datenbank, falls sie nicht existiert, aber nur die minimal nötigen Objekte: User "Admin", Mandate "Root" + +app.py: Die Initialisierung klar strukturieren und die Endpunkte gemäss der neuen Struktur anpassen + 1. Teil: Interfaces einbinden. + 2. Alle nötigen Initialisierungen: diese sollen in den jeweiligen Interfaces drin sein, ausser die generischen Teile. + 3. Alle Access & Security Funktionen auslagern in "auth.py" + 4. Alle Token-Endpunkte komplett generisch halten und vereinfachen: + - Dort keine Attributdefinitionen oder Feld-Listen reinnehmen. Wenn ein Modell angepasst wird, sollen hier keine Anpassungen nötig sein. + - Die Abfragen und exceptions mit Hilfsfunktionen vereinfachen, sodass die Modellierung der Endpunkte für den Programmierer sehr einfach, übersichtlich und klar ist. + - Tasks als Kommentare erfassen, was mit all diesen Aenderungen der Endpunkte im Frontend umgebaut werden muss. + + +agent_service.py: Umbenennen in "interface_agentservice.py" +- Bei allen Workflow-Endpunkten, welche nur von einem Interface Logik beziehen, die Logik im Interface integrieren und den Code beim Endpunkt vereinfachen. +- Nur bei Endpunkten, welche Logik kombiniert von mehreren Interfaces benötigen, die Logik beim Endpunkt integrieren +- Ziel soll es sein, dass die Endpunkte-Codestruktur maximal schlank und übersichtlich ist, also auch die Strukturierung und Gruppierung der Endpunkte + + diff --git a/notes/nda.txt b/notes/nda.txt new file mode 100644 index 00000000..02b46bdb --- /dev/null +++ b/notes/nda.txt @@ -0,0 +1,37 @@ +DATA PROCESSING AND AI USAGE CONSENT AGREEMENT + +By indicating your acceptance selecting "I agree", you as the user of this application acknowledge, consent to, and agree to the following terms regarding the processing of your data through artificial intelligence services: + +1. CONSENT TO DATA PROCESSING + 1.1 You expressly authorize the collection, processing, transmission, and storage of any and all data you provide or generate while using our services ("User Data"). + 1.2 You understand and agree that User Data may be transmitted to and processed by third-party artificial intelligence providers, including but not limited to OpenAI and similar AI service providers. + 1.3 This consent extends to all content, including but not limited to text, images, documents, conversation histories, preferences, activity logs, and any derivative data generated through your interaction with our services. + +2. ACKNOWLEDGMENT OF AI PROCESSING RISKS + 2.1 You acknowledge that artificial intelligence systems process data differently than human operators and may produce unexpected, inaccurate, or inappropriate outputs. + 2.2 You understand that AI services may retain, learn from, or use submitted data for improving their systems in accordance with their own terms of service. + 2.3 You recognize that despite reasonable security measures, data transmitted to third-party AI services may be vulnerable to interception, unauthorized access, or breach. + +3. WAIVER OF LIABILITY + 3.1 To the fullest extent permitted by applicable law, you hereby irrevocably and unconditionally waive and release any and all claims, liabilities, damages, losses, expenses, demands, and causes of action against us arising from or related to: + a) The processing, transmission, storage, or usage of User Data by AI services; + b) Any outputs, recommendations, or decisions generated by AI systems based on User Data; + c) Any data breach, unauthorized access, or security incident that occurs after User Data is transmitted to third-party AI providers; + d) Any unintended disclosure of confidential information processed through AI services; + e) Any direct, indirect, incidental, special, consequential, or punitive damages, including but not limited to loss of profits, goodwill, data, or other intangible losses. + 3.2 This waiver applies regardless of whether such damages arise from breach of contract, tort (including negligence), or any other legal theory. + +4. USER REPRESENTATIONS AND WARRANTIES + 4.1 You represent and warrant that: + a) You have the legal right to provide all User Data submitted; + b) User Data does not infringe upon any intellectual property rights, privacy rights, or other rights of any third party; + c) You have obtained all necessary consents from any third parties whose information may be included in User Data; + d) User Data does not contain any information that is unlawful, harmful, threatening, abusive, harassing, defamatory, or otherwise objectionable. + 4.2 You agree to indemnify and hold harmless our organization from any third-party claims arising from breach of these representations. + +5. LIMITATIONS AND SEVERABILITY + 5.1 This waiver does not apply to any liability that cannot be excluded or limited by law, including liability for fraud, gross negligence, or willful misconduct. + 5.2 If any provision of this agreement is found to be unenforceable, the remaining provisions shall remain in full force and effect. + 5.3 This waiver shall be governed by and construed in accordance with applicable laws, without regard to conflict of law principles. + +By selection "I agree", you acknowledge that you have read, understood, and agree to be bound by all the terms and conditions set forth in this agreement. diff --git a/readme.md b/notes/readme.md similarity index 100% rename from readme.md rename to notes/readme.md diff --git a/start.sh b/notes/start.sh similarity index 100% rename from start.sh rename to notes/start.sh diff --git a/requirements.txt b/requirements.txt index 6c3ec45d..84550aac 100644 --- a/requirements.txt +++ b/requirements.txt @@ -47,6 +47,7 @@ openpyxl>=3.1.2 # For Excel file support xlrd>=2.0.1 # For legacy Excel file support PyPDF2>=3.0.1 # For PDF file support pymupdf==1.22.5 # PDF picture extraction with module fitz +reportlab # PDF Library # === Agent Service Interface Dependencies === # HTTP Client and Web Scraping @@ -56,7 +57,8 @@ beautifulsoup4>=4.12.2 # For web scraping lxml>=4.9.2 # For faster HTML parsing html5lib>=1.1 # Alternative HTML parser aiofiles>=23.1.0 # Async file operations -Pillow==10.2.0 # image explaining +Pillow==10.3.0 # image explaining +selenium # AI and NLP openai>=0.27.4 # OpenAI API client