separated gateway from frontend
This commit is contained in:
parent
fce4c721c6
commit
5a0c7e0ae8
30 changed files with 27 additions and 2504 deletions
|
|
@ -1,15 +0,0 @@
|
|||
<!-- Meine Agents Ansicht -->
|
||||
<div id="agents-view">
|
||||
<h2>Meine Agents</h2>
|
||||
<div class="card">
|
||||
<div class="section-header">
|
||||
<h3>Verfügbare Agents</h3>
|
||||
<button class="add-btn" id="add-agent-btn">
|
||||
<i class="fas fa-plus"></i> Neuen Agent hinzufügen
|
||||
</button>
|
||||
</div>
|
||||
<div id="agents-list-container">
|
||||
<!-- Wird dynamisch gefüllt -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,204 +0,0 @@
|
|||
(function() {
|
||||
// DOM-Elemente
|
||||
let addAgentBtn, agentsListContainer;
|
||||
|
||||
// Initialisierungsfunktion für das Agenten-Modul
|
||||
function initAgentsModule(globalState) {
|
||||
// DOM-Elemente referenzieren
|
||||
addAgentBtn = document.getElementById('add-agent-btn');
|
||||
agentsListContainer = document.getElementById('agents-list-container');
|
||||
|
||||
// Event-Listener hinzufügen
|
||||
setupEventListeners(globalState);
|
||||
|
||||
// Initialdaten rendern
|
||||
renderMyAgents(globalState);
|
||||
}
|
||||
|
||||
// Event-Listener einrichten
|
||||
function setupEventListeners(globalState) {
|
||||
// Neuen Agenten hinzufügen
|
||||
addAgentBtn.addEventListener('click', () => {
|
||||
openAgentCreationModal(globalState);
|
||||
});
|
||||
}
|
||||
|
||||
// Modal zum Erstellen eines neuen Agenten öffnen
|
||||
function openAgentCreationModal(globalState) {
|
||||
// Einfaches Prompt als Platzhalter - in einer realen Anwendung würde dies
|
||||
// durch ein ansprechendes Modal oder Formular ersetzt
|
||||
const agentName = prompt('Name des neuen Agenten:');
|
||||
const agentType = prompt('Typ des Agenten (z.B. Analyse, Transformation):');
|
||||
const agentDescription = prompt('Beschreibung des Agenten:');
|
||||
|
||||
if (agentName && agentType) {
|
||||
const newAgent = {
|
||||
id: `agent_${Date.now()}`,
|
||||
name: agentName,
|
||||
type: agentType,
|
||||
description: agentDescription || '',
|
||||
workspace_id: globalState.currentWorkspace?.id,
|
||||
capabilities: []
|
||||
};
|
||||
|
||||
// Agent zur globalen Liste hinzufügen
|
||||
globalState.availableAgents.push(newAgent);
|
||||
|
||||
// UI aktualisieren
|
||||
renderMyAgents(globalState);
|
||||
|
||||
// Optional: Agent speichern
|
||||
saveAgent(newAgent, globalState);
|
||||
}
|
||||
}
|
||||
|
||||
// Meine Agenten rendern
|
||||
function renderMyAgents(globalState) {
|
||||
console.info()
|
||||
if (!agentsListContainer) {
|
||||
console.error("No agents container")
|
||||
return;
|
||||
}
|
||||
|
||||
agentsListContainer.innerHTML = '';
|
||||
|
||||
// Agenten für den aktuellen Workspace filtern
|
||||
const workspaceAgents = globalState.availableAgents.filter(
|
||||
agent => agent.workspace_id === globalState.currentWorkspace.id
|
||||
);
|
||||
// console.info("debug: agentid-wsid: "+ (globalState.availableAgents[0].workspace_id) + " - " + globalState.currentWorkspace.id + ", wsAgents: " + workspaceAgents.length)
|
||||
|
||||
if (workspaceAgents.length === 0) {
|
||||
agentsListContainer.innerHTML = '<div class="empty-state">Keine Agenten vorhanden.</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
workspaceAgents.forEach(agent => {
|
||||
const agentItem = document.createElement('div');
|
||||
agentItem.className = 'agent-list-item';
|
||||
agentItem.innerHTML = `
|
||||
<div class="agent-header">
|
||||
<h4>${agent.name}</h4>
|
||||
<span class="agent-type">${agent.type}</span>
|
||||
</div>
|
||||
<div class="agent-description">${agent.description || ''}</div>
|
||||
<div class="agent-capabilities">
|
||||
${agent.capabilities ? agent.capabilities.map(cap =>
|
||||
`<span class="capability-tag">${cap}</span>`
|
||||
).join('') : ''}
|
||||
</div>
|
||||
<div class="agent-actions">
|
||||
<button class="edit-agent-btn" data-id="${agent.id}">
|
||||
<i class="fas fa-edit"></i> Bearbeiten
|
||||
</button>
|
||||
<button class="delete-agent-btn" data-id="${agent.id}">
|
||||
<i class="fas fa-trash"></i> Löschen
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
agentsListContainer.appendChild(agentItem);
|
||||
});
|
||||
|
||||
// Event-Listener für Agenten-Aktionen einrichten
|
||||
setupAgentActionListeners(globalState);
|
||||
}
|
||||
|
||||
// Event-Listener für Agenten-Aktionen
|
||||
function setupAgentActionListeners(globalState) {
|
||||
// Bearbeiten-Button
|
||||
document.querySelectorAll('.edit-agent-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const agentId = btn.getAttribute('data-id');
|
||||
const agent = globalState.availableAgents.find(a => a.id === agentId);
|
||||
|
||||
if (agent) {
|
||||
editAgent(agent, globalState);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Löschen-Button
|
||||
document.querySelectorAll('.delete-agent-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const agentId = btn.getAttribute('data-id');
|
||||
|
||||
if (confirm('Möchten Sie diesen Agenten wirklich löschen?')) {
|
||||
deleteAgent(agentId, globalState);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Agent bearbeiten
|
||||
function editAgent(agent, globalState) {
|
||||
// Einfaches Prompt als Platzhalter - in einer realen Anwendung würde dies
|
||||
// durch ein ansprechendes Modal oder Formular ersetzt
|
||||
const newName = prompt('Name des Agenten:', agent.name);
|
||||
const newType = prompt('Typ des Agenten:', agent.type);
|
||||
const newDescription = prompt('Beschreibung des Agenten:', agent.description);
|
||||
|
||||
if (newName) {
|
||||
// Agent aktualisieren
|
||||
agent.name = newName;
|
||||
agent.type = newType || agent.type;
|
||||
agent.description = newDescription || agent.description;
|
||||
|
||||
// UI aktualisieren
|
||||
renderMyAgents(globalState);
|
||||
|
||||
// Optional: Aktualisierung auf dem Server
|
||||
updateAgent(agent);
|
||||
}
|
||||
}
|
||||
|
||||
// Agent speichern
|
||||
async function saveAgent(agentData, globalState) {
|
||||
try {
|
||||
// Agent auf dem Server speichern
|
||||
const response = await window.globalUtils.postData('/api/agents/save', agentData);
|
||||
|
||||
// Rückmeldung vom Server verarbeiten
|
||||
if (response && response.id) {
|
||||
// Wenn der Server eine ID zurückgibt, diese aktualisieren
|
||||
const index = globalState.availableAgents.findIndex(a => a.id === agentData.id);
|
||||
if (index !== -1) {
|
||||
globalState.availableAgents[index].id = response.id;
|
||||
}
|
||||
|
||||
// UI aktualisieren
|
||||
renderMyAgents(globalState);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Speichern des Agenten:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Agent aktualisieren
|
||||
async function updateAgent(agent) {
|
||||
try {
|
||||
// Agent auf dem Server aktualisieren
|
||||
await window.globalUtils.postData('/api/agents/update', agent);
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Aktualisieren des Agenten:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Agent löschen
|
||||
async function deleteAgent(agentId, globalState) {
|
||||
try {
|
||||
// Aus dem globalen State entfernen
|
||||
globalState.availableAgents = globalState.availableAgents.filter(a => a.id !== agentId);
|
||||
|
||||
// UI aktualisieren
|
||||
renderMyAgents(globalState);
|
||||
|
||||
// Agent vom Server löschen
|
||||
await window.globalUtils.postData('/api/agents/delete', { id: agentId });
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Löschen des Agenten:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Modul-Initialisierung exportieren
|
||||
window.initAgentsModule = initAgentsModule;
|
||||
})();
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
<!-- Meine Daten Ansicht -->
|
||||
<div id="data-view">
|
||||
<h2>Meine Daten</h2>
|
||||
<div class="card">
|
||||
<div class="section-header">
|
||||
<h3>Verfügbare Dateien</h3>
|
||||
<button class="upload-btn" id="data-upload-btn">
|
||||
<i class="fas fa-upload"></i> Neue Dateien hochladen
|
||||
</button>
|
||||
<input type="file" id="data-file-input" multiple hidden>
|
||||
</div>
|
||||
<div class="files-container">
|
||||
<ul class="file-list" id="my-files-list">
|
||||
<!-- Wird dynamisch gefüllt -->
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
// data-module.js
|
||||
(function() {
|
||||
// DOM-Elemente
|
||||
let dataFileInput, uploadBtn, myFilesList;
|
||||
|
||||
// Initialisierungsfunktion für das Daten-Modul
|
||||
function initDataModule(globalState) {
|
||||
// DOM-Elemente referenzieren
|
||||
dataFileInput = document.getElementById('data-file-input');
|
||||
uploadBtn = document.getElementById('data-upload-btn');
|
||||
myFilesList = document.getElementById('my-files-list');
|
||||
|
||||
// Event-Listener hinzufügen
|
||||
setupEventListeners(globalState);
|
||||
|
||||
// Initialdaten rendern
|
||||
renderMyFiles(globalState);
|
||||
}
|
||||
|
||||
// Event-Listener einrichten
|
||||
function setupEventListeners(globalState) {
|
||||
// Datei-Upload
|
||||
uploadBtn.addEventListener('click', () => dataFileInput.click());
|
||||
dataFileInput.addEventListener('change',
|
||||
window.globalUtils.handleFileUpload(dataFileInput, (newFile) => {
|
||||
// Nach erfolgreichem Upload
|
||||
globalState.availableFiles.push(newFile);
|
||||
renderMyFiles(globalState);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Meine Dateien rendern
|
||||
function renderMyFiles(globalState) {
|
||||
if (!myFilesList) return;
|
||||
|
||||
myFilesList.innerHTML = '';
|
||||
|
||||
if (globalState.availableFiles.length === 0) {
|
||||
myFilesList.innerHTML = '<div class="empty-state">Keine Dateien vorhanden.</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
globalState.availableFiles.forEach(file => {
|
||||
const li = document.createElement('li');
|
||||
li.className = 'file-item';
|
||||
li.innerHTML = `
|
||||
<div class="file-item-name">
|
||||
<i class="fas ${file.type === 'document' ? 'fa-file-alt' : 'fa-file-image'}"></i>
|
||||
<span>${file.name}</span>
|
||||
</div>
|
||||
<div class="file-item-info">
|
||||
<span>${file.size || ''}</span>
|
||||
<span>${new Date(file.upload_date || Date.now()).toLocaleString()}</span>
|
||||
</div>
|
||||
<div class="file-actions">
|
||||
<button class="view-file-btn" data-id="${file.id}">
|
||||
<i class="fas fa-eye"></i>
|
||||
</button>
|
||||
<button class="delete-file-btn" data-id="${file.id}">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
myFilesList.appendChild(li);
|
||||
});
|
||||
|
||||
// Event-Listener für Datei-Aktionen
|
||||
setupFileActionListeners(globalState);
|
||||
}
|
||||
|
||||
// Event-Listener für Datei-Aktionen
|
||||
function setupFileActionListeners(globalState) {
|
||||
// Datei anzeigen
|
||||
document.querySelectorAll('.view-file-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const fileId = btn.getAttribute('data-id');
|
||||
const file = globalState.availableFiles.find(f => f.id === fileId);
|
||||
if (file && file.path) {
|
||||
window.open(file.path, '_blank');
|
||||
} else {
|
||||
alert('Datei nicht verfügbar');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Datei löschen
|
||||
document.querySelectorAll('.delete-file-btn').forEach(btn => {
|
||||
btn.addEventListener('click', async () => {
|
||||
const fileId = btn.getAttribute('data-id');
|
||||
if (confirm('Möchten Sie diese Datei wirklich löschen?')) {
|
||||
try {
|
||||
// TODO: API-Endpunkt zum Löschen implementieren
|
||||
// await fetch(`/files/${fileId}`, { method: 'DELETE' });
|
||||
|
||||
// Aus dem globalen State entfernen
|
||||
globalState.availableFiles = globalState.availableFiles.filter(f => f.id !== fileId);
|
||||
|
||||
// UI aktualisieren
|
||||
renderMyFiles(globalState);
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Löschen der Datei:", error);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Modul-Initialisierung exportieren
|
||||
window.initDataModule = initDataModule;
|
||||
})();
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
<!-- Meine Prompts Ansicht -->
|
||||
<div id="prompts-view">
|
||||
<h2>Meine Prompts</h2>
|
||||
<div class="card">
|
||||
<div class="section-header">
|
||||
<h3>Gespeicherte Prompts</h3>
|
||||
<button class="add-btn" id="add-prompt-btn">
|
||||
<i class="fas fa-plus"></i> Neuen Prompt erstellen
|
||||
</button>
|
||||
</div>
|
||||
<div id="prompts-list">
|
||||
<!-- Wird dynamisch gefüllt -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,168 +0,0 @@
|
|||
// prompts-module.js
|
||||
(function() {
|
||||
// DOM-Elemente
|
||||
let addPromptBtn, promptsList;
|
||||
|
||||
// Initialisierungsfunktion für das Prompts-Modul
|
||||
function initPromptsModule(globalState) {
|
||||
// DOM-Elemente referenzieren
|
||||
addPromptBtn = document.getElementById('add-prompt-btn');
|
||||
promptsList = document.getElementById('prompts-list');
|
||||
|
||||
// Event-Listener hinzufügen
|
||||
setupEventListeners(globalState);
|
||||
|
||||
// Initialdaten rendern
|
||||
renderMyPrompts(globalState);
|
||||
}
|
||||
|
||||
// Event-Listener einrichten
|
||||
function setupEventListeners(globalState) {
|
||||
// Neuen Prompt hinzufügen
|
||||
addPromptBtn.addEventListener('click', () => {
|
||||
const newPrompt = prompt('Geben Sie den neuen Prompt ein:');
|
||||
if (newPrompt && newPrompt.trim()) {
|
||||
const promptData = {
|
||||
id: `prompt_${Date.now()}`,
|
||||
content: newPrompt.trim(),
|
||||
created_at: new Date().toISOString()
|
||||
};
|
||||
|
||||
// Prompt zur globalen Liste hinzufügen
|
||||
globalState.availablePrompts.push(promptData);
|
||||
|
||||
// UI aktualisieren
|
||||
renderMyPrompts(globalState);
|
||||
|
||||
// Optional: Prompt speichern
|
||||
savePrompt(promptData, globalState);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Meine Prompts rendern
|
||||
function renderMyPrompts(globalState) {
|
||||
if (!promptsList) return;
|
||||
|
||||
promptsList.innerHTML = '';
|
||||
|
||||
if (globalState.availablePrompts.length === 0) {
|
||||
promptsList.innerHTML = '<div class="empty-state">Keine Prompts vorhanden.</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
globalState.availablePrompts.forEach(prompt => {
|
||||
const promptItem = document.createElement('div');
|
||||
promptItem.className = 'prompt-item';
|
||||
promptItem.innerHTML = `
|
||||
<div class="prompt-content">${prompt.content}</div>
|
||||
<div class="prompt-meta">Erstellt am: ${new Date(prompt.created_at).toLocaleString()}</div>
|
||||
<div class="prompt-actions">
|
||||
<button class="use-prompt-btn" data-id="${prompt.id}">
|
||||
<i class="fas fa-play"></i> Verwenden
|
||||
</button>
|
||||
<button class="delete-prompt-btn" data-id="${prompt.id}">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
promptsList.appendChild(promptItem);
|
||||
});
|
||||
|
||||
// Event-Listener für Prompt-Aktionen einrichten
|
||||
setupPromptActionListeners(globalState);
|
||||
}
|
||||
|
||||
// Event-Listener für Prompt-Aktionen
|
||||
function setupPromptActionListeners(globalState) {
|
||||
// "Verwenden"-Button
|
||||
document.querySelectorAll('.use-prompt-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const promptId = btn.getAttribute('data-id');
|
||||
const selectedPrompt = globalState.availablePrompts.find(p => p.id === promptId);
|
||||
|
||||
if (selectedPrompt) {
|
||||
// Workflow-Modul aktivieren und Prompt übernehmen
|
||||
document.querySelector('a[href="#workflow"]').click();
|
||||
|
||||
// Prompt in Workflow-Eingabefeld setzen
|
||||
const promptInput = document.getElementById('prompt-input');
|
||||
const promptSelect = document.getElementById('prompt-select');
|
||||
|
||||
if (promptInput) {
|
||||
promptInput.value = selectedPrompt.content;
|
||||
}
|
||||
|
||||
if (promptSelect) {
|
||||
// Wenn der Prompt bereits existiert, ihn in der Dropdown auswählen
|
||||
const existingOption = Array.from(promptSelect.options).find(
|
||||
option => option.textContent.includes(selectedPrompt.content.substring(0, 50))
|
||||
);
|
||||
|
||||
if (existingOption) {
|
||||
promptSelect.value = existingOption.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// "Löschen"-Button
|
||||
document.querySelectorAll('.delete-prompt-btn').forEach(btn => {
|
||||
btn.addEventListener('click', async () => {
|
||||
const promptId = btn.getAttribute('data-id');
|
||||
|
||||
if (confirm('Möchten Sie diesen Prompt wirklich löschen?')) {
|
||||
try {
|
||||
// Aus dem globalen State entfernen
|
||||
globalState.availablePrompts = globalState.availablePrompts.filter(p => p.id !== promptId);
|
||||
|
||||
// UI aktualisieren
|
||||
renderMyPrompts(globalState);
|
||||
|
||||
// Optional: Prompt vom Server löschen
|
||||
await deletePrompt(promptId);
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Löschen des Prompts:", error);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Prompt speichern
|
||||
async function savePrompt(promptData, globalState) {
|
||||
try {
|
||||
// Prompt auf dem Server speichern
|
||||
const response = await window.globalUtils.postData('/api/prompts/save', promptData);
|
||||
|
||||
// Rückmeldung vom Server verarbeiten
|
||||
if (response && response.id) {
|
||||
// Wenn der Server eine ID zurückgibt, diese aktualisieren
|
||||
const index = globalState.availablePrompts.findIndex(p => p.id === promptData.id);
|
||||
if (index !== -1) {
|
||||
globalState.availablePrompts[index].id = response.id;
|
||||
}
|
||||
|
||||
// UI aktualisieren
|
||||
renderMyPrompts(globalState);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Speichern des Prompts:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Prompt löschen
|
||||
async function deletePrompt(promptId) {
|
||||
try {
|
||||
// Prompt vom Server löschen
|
||||
await window.globalUtils.postData('/api/prompts/delete', { id: promptId });
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Löschen des Prompts:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Modul-Initialisierung exportieren
|
||||
window.initPromptsModule = initPromptsModule;
|
||||
})();
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
<!-- Workflow Module -->
|
||||
<div class="workflow-container">
|
||||
<!-- Linke Seite - Workflow-Konfiguration -->
|
||||
<div class="config-panel">
|
||||
<h2>Workflow-Konfiguration</h2>
|
||||
|
||||
<!-- 1. Dateien auswählen -->
|
||||
<div class="card">
|
||||
<h3>1. Dateien auswählen</h3>
|
||||
|
||||
<div class="files-container">
|
||||
<div class="file-selection">
|
||||
<div class="section-header">
|
||||
<span>Verfügbare Dateien</span>
|
||||
<button class="upload-btn" id="upload-btn">
|
||||
<i class="fas fa-upload"></i> Hochladen
|
||||
</button>
|
||||
<input type="file" id="file-input" multiple hidden>
|
||||
</div>
|
||||
<ul class="file-list" id="available-files">
|
||||
<!-- Wird dynamisch gefüllt -->
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="selected-files">
|
||||
<h4>Ausgewählte Dateien</h4>
|
||||
<div class="selected-files-container" id="selected-files-container">
|
||||
<div class="empty-state" id="empty-files-state">
|
||||
<i class="fas fa-upload"></i>
|
||||
<span>Keine Dateien ausgewählt</span>
|
||||
</div>
|
||||
<ul class="selected-file-list" id="selected-files">
|
||||
<!-- Wird dynamisch gefüllt -->
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Prompt eingeben oder auswählen -->
|
||||
<div class="card">
|
||||
<h3>2. Prompt eingeben oder auswählen</h3>
|
||||
|
||||
<!-- Prompt-Auswahl -->
|
||||
<div class="form-group">
|
||||
<label for="prompt-select" class="prompt-select-label">
|
||||
Gespeicherte Prompts:
|
||||
</label>
|
||||
<select id="prompt-select" class="prompt-select">
|
||||
<option value="">-- Prompt auswählen --</option>
|
||||
<!-- Wird dynamisch gefüllt -->
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Eingabefeld für eigenen Prompt -->
|
||||
<textarea
|
||||
id="prompt-input"
|
||||
placeholder="Beschreiben Sie die Aufgabe für die Agenten..."
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<!-- 3. Agenten auswählen -->
|
||||
<div class="card">
|
||||
<h3>3. Agenten auswählen</h3>
|
||||
<ul class="agent-list" id="agent-list">
|
||||
<!-- Wird dynamisch gefüllt -->
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Aktionsbuttons -->
|
||||
<div class="action-buttons">
|
||||
<button class="reset-btn" id="reset-btn">Zurücksetzen</button>
|
||||
<button class="start-btn" id="start-workflow-btn">Workflow starten</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Rechte Seite - Ausführung und Ergebnisse -->
|
||||
<div class="results-panel">
|
||||
<h2>Ausführung & Ergebnisse</h2>
|
||||
|
||||
<!-- Ausführungsprotokoll -->
|
||||
<div class="card">
|
||||
<h3>Ausführungsprotokoll</h3>
|
||||
<div class="log-container" id="execution-log">
|
||||
<div class="log-empty-state">Workflow noch nicht gestartet. Protokoll wird hier angezeigt.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Ergebnisse -->
|
||||
<div class="card">
|
||||
<h3>Ergebnisse</h3>
|
||||
<div class="results-container" id="results-container">
|
||||
<div class="results-empty-state" id="empty-results-state">
|
||||
<div>Keine Ergebnisse verfügbar</div>
|
||||
<div class="sub-text">Führen Sie einen Workflow aus, um Ergebnisse zu sehen</div>
|
||||
</div>
|
||||
<div class="results-list" id="results-list">
|
||||
<!-- Wird dynamisch gefüllt -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,408 +0,0 @@
|
|||
// workflow-module.js
|
||||
(function() {
|
||||
// Workflow-Modul-Zustand
|
||||
let workflowState = {
|
||||
selectedFiles: [],
|
||||
selectedAgents: [],
|
||||
prompt: "",
|
||||
logs: [],
|
||||
results: [],
|
||||
isRunning: false
|
||||
};
|
||||
|
||||
// DOM-Elemente
|
||||
let availableFiles, selectedFiles, emptyFilesState,
|
||||
fileInput, uploadBtn, promptInput, promptSelect,
|
||||
agentList, resetBtn, startWorkflowBtn,
|
||||
executionLog, resultsContainer,
|
||||
emptyResultsState, resultsList;
|
||||
|
||||
// Initialisierungsfunktion für das Workflow-Modul
|
||||
function initWorkflowModule(globalState) {
|
||||
// DOM-Elemente referenzieren
|
||||
availableFiles = document.getElementById('available-files');
|
||||
selectedFiles = document.getElementById('selected-files');
|
||||
emptyFilesState = document.getElementById('empty-files-state');
|
||||
fileInput = document.getElementById('file-input');
|
||||
uploadBtn = document.getElementById('upload-btn');
|
||||
promptInput = document.getElementById('prompt-input');
|
||||
promptSelect = document.getElementById('prompt-select');
|
||||
agentList = document.getElementById('agent-list');
|
||||
resetBtn = document.getElementById('reset-btn');
|
||||
startWorkflowBtn = document.getElementById('start-workflow-btn');
|
||||
executionLog = document.getElementById('execution-log');
|
||||
resultsContainer = document.getElementById('results-container');
|
||||
emptyResultsState = document.getElementById('empty-results-state');
|
||||
resultsList = document.getElementById('results-list');
|
||||
|
||||
// Event-Listener hinzufügen
|
||||
setupEventListeners(globalState);
|
||||
|
||||
// Initialdaten rendern
|
||||
renderFiles(globalState);
|
||||
renderPromptSelector(globalState);
|
||||
renderAgents(globalState);
|
||||
}
|
||||
|
||||
// Event-Listener einrichten
|
||||
function setupEventListeners(globalState) {
|
||||
// Datei-Upload
|
||||
uploadBtn.addEventListener('click', () => fileInput.click());
|
||||
fileInput.addEventListener('change',
|
||||
window.globalUtils.handleFileUpload(fileInput, (newFile) => {
|
||||
// Nach erfolgreichem Upload
|
||||
workflowState.selectedFiles.push(newFile);
|
||||
renderSelectedFiles();
|
||||
renderFiles(globalState);
|
||||
})
|
||||
);
|
||||
|
||||
// Prompt-Eingabe
|
||||
promptInput.addEventListener('input', (e) => {
|
||||
workflowState.prompt = e.target.value;
|
||||
});
|
||||
|
||||
// Prompt-Auswahl
|
||||
promptSelect.addEventListener('change', () => {
|
||||
const selectedPromptId = promptSelect.value;
|
||||
if (selectedPromptId) {
|
||||
const selectedPrompt = globalState.availablePrompts.find(p => p.id === selectedPromptId);
|
||||
if (selectedPrompt) {
|
||||
promptInput.value = selectedPrompt.content;
|
||||
workflowState.prompt = selectedPrompt.content;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Zurücksetzen
|
||||
resetBtn.addEventListener('click', resetWorkflow);
|
||||
|
||||
// Workflow starten
|
||||
startWorkflowBtn.addEventListener('click', () => runWorkflow(globalState));
|
||||
}
|
||||
|
||||
// Verfügbare Dateien rendern
|
||||
function renderFiles(globalState) {
|
||||
availableFiles.innerHTML = '';
|
||||
globalState.availableFiles.forEach(file => {
|
||||
const li = document.createElement('li');
|
||||
li.className = 'file-item';
|
||||
const isSelected = workflowState.selectedFiles.some(f => f.id === file.id);
|
||||
li.innerHTML = `
|
||||
<div class="file-item-name">
|
||||
<input type="checkbox" id="file-${file.id}" ${isSelected ? 'checked' : ''}>
|
||||
<label for="file-${file.id}">
|
||||
<i class="fas ${file.type === 'document' ? 'fa-file-alt' : 'fa-file-image'}"></i>
|
||||
${file.name}
|
||||
</label>
|
||||
</div>
|
||||
<span class="file-item-info">${file.size || ''}</span>
|
||||
`;
|
||||
const checkbox = li.querySelector(`#file-${file.id}`);
|
||||
checkbox.addEventListener('change', () => {
|
||||
if (checkbox.checked) {
|
||||
workflowState.selectedFiles.push(file);
|
||||
} else {
|
||||
workflowState.selectedFiles = workflowState.selectedFiles.filter(f => f.id !== file.id);
|
||||
}
|
||||
renderSelectedFiles();
|
||||
});
|
||||
availableFiles.appendChild(li);
|
||||
});
|
||||
}
|
||||
|
||||
// Ausgewählte Dateien rendern
|
||||
function renderSelectedFiles() {
|
||||
if (workflowState.selectedFiles.length === 0) {
|
||||
emptyFilesState.style.display = 'flex';
|
||||
selectedFiles.innerHTML = '';
|
||||
} else {
|
||||
emptyFilesState.style.display = 'none';
|
||||
selectedFiles.innerHTML = '';
|
||||
workflowState.selectedFiles.forEach(file => {
|
||||
const li = document.createElement('li');
|
||||
li.className = 'selected-file-item';
|
||||
li.innerHTML = `
|
||||
<div class="file-item-name">
|
||||
<i class="fas ${file.type === 'document' ? 'fa-file-alt' : 'fa-file-image'}"></i>
|
||||
${file.name}
|
||||
</div>
|
||||
<button class="remove-file-btn" data-id="${file.id}">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
`;
|
||||
selectedFiles.appendChild(li);
|
||||
});
|
||||
|
||||
// Event-Listener für Entfernen-Buttons
|
||||
document.querySelectorAll('.remove-file-btn').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const fileId = btn.getAttribute('data-id');
|
||||
workflowState.selectedFiles = workflowState.selectedFiles.filter(f => f.id !== fileId);
|
||||
renderSelectedFiles();
|
||||
renderFiles(window.globalState);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Prompt-Auswahlbox rendern
|
||||
function renderPromptSelector(globalState) {
|
||||
// Existierende Optionen entfernen (außer der ersten)
|
||||
while (promptSelect.options.length > 1) {
|
||||
promptSelect.remove(1);
|
||||
}
|
||||
|
||||
// Prompts aus dem globalen State hinzufügen
|
||||
globalState.availablePrompts.forEach(prompt => {
|
||||
const option = document.createElement('option');
|
||||
option.value = prompt.id;
|
||||
option.textContent = prompt.content.substring(0, 50) + (prompt.content.length > 50 ? '...' : '');
|
||||
promptSelect.appendChild(option);
|
||||
});
|
||||
}
|
||||
|
||||
// Agenten rendern
|
||||
function renderAgents(globalState) {
|
||||
agentList.innerHTML = '';
|
||||
|
||||
// Agenten für den aktuellen Workspace filtern
|
||||
const workspaceAgents = globalState.availableAgents.filter(
|
||||
agent => agent.workspace_id === globalState.currentWorkspace?.id
|
||||
);
|
||||
|
||||
if (workspaceAgents.length === 0) {
|
||||
agentList.innerHTML = '<div class="empty-state">Keine Agenten im ausgewählten Workspace verfügbar.</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
workspaceAgents.forEach(agent => {
|
||||
const li = document.createElement('li');
|
||||
li.className = 'agent-item';
|
||||
const isSelected = workflowState.selectedAgents.some(a => a.id === agent.id);
|
||||
li.innerHTML = `
|
||||
<div class="agent-header">
|
||||
<input type="checkbox" id="agent-${agent.id}" class="agent-checkbox" ${isSelected ? 'checked' : ''}>
|
||||
<label for="agent-${agent.id}" class="agent-name">${agent.name}</label>
|
||||
</div>
|
||||
<div class="agent-description">${agent.description || ''}</div>
|
||||
`;
|
||||
const checkbox = li.querySelector(`#agent-${agent.id}`);
|
||||
checkbox.addEventListener('change', () => {
|
||||
if (checkbox.checked) {
|
||||
workflowState.selectedAgents.push(agent);
|
||||
} else {
|
||||
workflowState.selectedAgents = workflowState.selectedAgents.filter(a => a.id !== agent.id);
|
||||
}
|
||||
});
|
||||
agentList.appendChild(li);
|
||||
});
|
||||
}
|
||||
|
||||
// Ausführungsprotokoll aktualisieren
|
||||
function addLogEntry(message, type = 'info') {
|
||||
const log = {
|
||||
id: `log_${Date.now()}`,
|
||||
message,
|
||||
type,
|
||||
timestamp: new Date().toISOString()
|
||||
};
|
||||
workflowState.logs.push(log);
|
||||
renderLogs();
|
||||
return log;
|
||||
}
|
||||
|
||||
// Protokoll rendern
|
||||
function renderLogs() {
|
||||
if (workflowState.logs.length === 0) {
|
||||
executionLog.innerHTML = '<div class="log-empty-state">Workflow noch nicht gestartet. Protokoll wird hier angezeigt.</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
executionLog.innerHTML = '';
|
||||
workflowState.logs.forEach(log => {
|
||||
const logEntry = document.createElement('div');
|
||||
logEntry.className = 'log-entry';
|
||||
logEntry.innerHTML = `
|
||||
<span class="log-time">[${new Date(log.timestamp).toLocaleTimeString()}]</span>
|
||||
<span class="log-message log-${log.type}">${log.message}</span>
|
||||
`;
|
||||
executionLog.appendChild(logEntry);
|
||||
});
|
||||
|
||||
// Zum Ende scrollen
|
||||
executionLog.scrollTop = executionLog.scrollHeight;
|
||||
}
|
||||
|
||||
// Ergebnis hinzufügen
|
||||
function addResult(result) {
|
||||
workflowState.results.push(result);
|
||||
renderResults();
|
||||
}
|
||||
|
||||
// Ergebnisse rendern
|
||||
function renderResults() {
|
||||
if (workflowState.results.length === 0) {
|
||||
emptyResultsState.style.display = 'flex';
|
||||
resultsList.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
emptyResultsState.style.display = 'none';
|
||||
resultsList.style.display = 'block';
|
||||
resultsList.innerHTML = '';
|
||||
|
||||
workflowState.results.forEach(result => {
|
||||
const resultItem = document.createElement('div');
|
||||
resultItem.className = 'result-item';
|
||||
|
||||
if (result.type === 'text') {
|
||||
resultItem.innerHTML = `
|
||||
<div class="result-header">
|
||||
<div>
|
||||
<div class="result-title">${result.title}</div>
|
||||
<div class="result-agent">Erstellt von: ${result.agent_name}</div>
|
||||
</div>
|
||||
<button class="save-btn">
|
||||
<i class="fas fa-save"></i> Speichern
|
||||
</button>
|
||||
</div>
|
||||
<div class="result-content">${result.content}</div>
|
||||
`;
|
||||
} else if (result.type === 'chart') {
|
||||
resultItem.innerHTML = `
|
||||
<div class="result-header">
|
||||
<div>
|
||||
<div class="result-title">${result.title}</div>
|
||||
<div class="result-agent">Erstellt von: ${result.agent_name}</div>
|
||||
</div>
|
||||
<button class="save-btn">
|
||||
<i class="fas fa-save"></i> Speichern
|
||||
</button>
|
||||
</div>
|
||||
<div class="chart-container">
|
||||
<div class="chart-title">Umsatzentwicklung nach Quartal</div>
|
||||
<div>${result.content}</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
resultsList.appendChild(resultItem);
|
||||
});
|
||||
}
|
||||
|
||||
// Workflow-Ausführung
|
||||
async function runWorkflow(globalState) {
|
||||
if (workflowState.selectedFiles.length === 0 ||
|
||||
workflowState.selectedAgents.length === 0 ||
|
||||
!workflowState.prompt.trim()) {
|
||||
alert("Bitte wählen Sie Dateien und Agenten aus und geben Sie einen Prompt ein.");
|
||||
return;
|
||||
}
|
||||
|
||||
workflowState.isRunning = true;
|
||||
workflowState.logs = [];
|
||||
workflowState.results = [];
|
||||
|
||||
startWorkflowBtn.textContent = 'Wird ausgeführt...';
|
||||
startWorkflowBtn.classList.add('running');
|
||||
startWorkflowBtn.disabled = true;
|
||||
|
||||
renderLogs();
|
||||
renderResults();
|
||||
|
||||
try {
|
||||
// API-Aufruf an das Backend für Workflow-Ausführung
|
||||
const workflowData = {
|
||||
workspace_id: globalState.currentWorkspace.id,
|
||||
files: workflowState.selectedFiles.map(file => file.id),
|
||||
agents: workflowState.selectedAgents.map(agent => agent.id),
|
||||
prompt: workflowState.prompt,
|
||||
workflow_name: "Workflow " + new Date().toLocaleString()
|
||||
};
|
||||
|
||||
const response = await window.globalUtils.postData('/api/workflow/run', workflowData);
|
||||
|
||||
if (response && response.workflow_id) {
|
||||
const workflowId = response.workflow_id;
|
||||
addLogEntry("Workflow gestartet", "info");
|
||||
addLogEntry(`Workflow-ID: ${workflowId}`, "info");
|
||||
|
||||
// Polling für Workflow-Status und -Ergebnisse starten
|
||||
pollWorkflowStatus(workflowId);
|
||||
} else {
|
||||
throw new Error("Workflow konnte nicht gestartet werden");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Starten des Workflows:", error);
|
||||
workflowState.isRunning = false;
|
||||
startWorkflowBtn.textContent = 'Workflow starten';
|
||||
startWorkflowBtn.classList.remove('running');
|
||||
startWorkflowBtn.disabled = false;
|
||||
|
||||
addLogEntry(`Fehler beim Starten des Workflows: ${error.message}`, "error");
|
||||
}
|
||||
}
|
||||
|
||||
// Workflow-Status abfragen
|
||||
async function pollWorkflowStatus(workflowId) {
|
||||
try {
|
||||
// Status abrufen
|
||||
const status = await window.globalUtils.fetchData(`/api/workflow/${workflowId}/status`);
|
||||
|
||||
// Logs abrufen und anzeigen
|
||||
const logs = await window.globalUtils.fetchData(`/api/workflow/${workflowId}/logs`);
|
||||
workflowState.logs = logs;
|
||||
renderLogs();
|
||||
|
||||
// Status aktualisieren
|
||||
if (status) {
|
||||
// Fortschritt anzeigen
|
||||
addLogEntry(`Fortschritt: ${Math.round(status.progress * 100)}%`, "info");
|
||||
|
||||
// Wenn der Workflow abgeschlossen ist, Ergebnisse abrufen
|
||||
if (status.status === 'completed' || status.status === 'failed') {
|
||||
const results = await window.globalUtils.fetchData(`/api/workflow/${workflowId}/results`);
|
||||
workflowState.results = results;
|
||||
renderResults();
|
||||
|
||||
addLogEntry(`Workflow ${status.status === 'completed' ? 'erfolgreich beendet' : 'fehlgeschlagen'}`,
|
||||
status.status === 'completed' ? "success" : "error");
|
||||
|
||||
workflowState.isRunning = false;
|
||||
startWorkflowBtn.textContent = 'Workflow starten';
|
||||
startWorkflowBtn.classList.remove('running');
|
||||
startWorkflowBtn.disabled = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Weiteres Polling nach einer kurzen Verzögerung
|
||||
setTimeout(() => pollWorkflowStatus(workflowId), 2000);
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Abrufen des Workflow-Status:", error);
|
||||
addLogEntry(`Fehler beim Abrufen des Workflow-Status: ${error.message}`, "error");
|
||||
|
||||
workflowState.isRunning = false;
|
||||
startWorkflowBtn.textContent = 'Workflow starten';
|
||||
startWorkflowBtn.classList.remove('running');
|
||||
startWorkflowBtn.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Workflow zurücksetzen
|
||||
function resetWorkflow() {
|
||||
workflowState.selectedFiles = [];
|
||||
workflowState.selectedAgents = [];
|
||||
promptInput.value = "";
|
||||
promptSelect.selectedIndex = 0;
|
||||
workflowState.prompt = "";
|
||||
|
||||
renderFiles(window.globalState);
|
||||
renderSelectedFiles();
|
||||
renderAgents(window.globalState);
|
||||
}
|
||||
|
||||
// Modul-Initialisierung exportieren
|
||||
window.initWorkflowModule = initWorkflowModule;
|
||||
})();
|
||||
Binary file not shown.
|
|
@ -1,15 +0,0 @@
|
|||
<!-- Meine Agents Ansicht -->
|
||||
<div id="agents-view" style="display:none;">
|
||||
<h2>Meine Agents</h2>
|
||||
<div class="card">
|
||||
<div class="section-header">
|
||||
<h3>Verfügbare Agents</h3>
|
||||
<button class="add-btn" id="add-agent-btn">
|
||||
<i class="fas fa-plus"></i> Neuen Agent hinzufügen
|
||||
</button>
|
||||
</div>
|
||||
<div id="agents-list-container">
|
||||
<!-- Wird dynamisch gefüllt -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>PowerOn | Multi-Agent Service</title>
|
||||
<link rel="stylesheet" href="./styles.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Navigation -->
|
||||
<nav class="navbar">
|
||||
<div class="navbar-container">
|
||||
<h1 class="navbar-logo">Data Platform</h1>
|
||||
<div class="navbar-user">
|
||||
<span>Shelly Miller</span>
|
||||
<button class="icon-button">
|
||||
<i class="fas fa-cog"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="app-container">
|
||||
<!-- Seitenleiste -->
|
||||
<aside class="sidebar">
|
||||
<div class="workspace-section">
|
||||
<h2>Workspaces</h2>
|
||||
<ul class="workspace-list" id="workspace-list">
|
||||
<!-- Workspace-Liste wird vom JavaScript gefüllt -->
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<ul class="sidebar-nav">
|
||||
<li class="sidebar-item active">
|
||||
<a href="#workflow">
|
||||
<i class="fas fa-play-circle"></i>
|
||||
<span>Workflow-Ausführung</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<a href="#data">
|
||||
<i class="fas fa-database"></i>
|
||||
<span>Meine Daten</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<a href="#prompts">
|
||||
<i class="fas fa-comment-alt"></i>
|
||||
<span>Meine Prompts</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<a href="#agents">
|
||||
<i class="fas fa-wrench"></i>
|
||||
<span>Meine Agents</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</aside>
|
||||
|
||||
<!-- Hauptinhalt -->
|
||||
<main class="main-content">
|
||||
<!-- Module werden dynamisch geladen -->
|
||||
<div id="part-workflow"></div>
|
||||
<div id="part-data"></div>
|
||||
<div id="part-prompts"></div>
|
||||
<div id="part-agents"></div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<!-- Module scripts -->
|
||||
<script src="main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
321
frontend/main.js
321
frontend/main.js
|
|
@ -1,321 +0,0 @@
|
|||
document.addEventListener('DOMContentLoaded',async function(){
|
||||
// Globale Hilfsfunktionen und Initialisierung
|
||||
|
||||
// State-Management
|
||||
const globalState = {
|
||||
workspaces: [],
|
||||
currentWorkspace: null,
|
||||
availableFiles: [],
|
||||
availableAgents: [],
|
||||
availablePrompts: [],
|
||||
};
|
||||
|
||||
async function loadModuleHtml(filename) {
|
||||
// Backend-URL für HTML Module verwenden
|
||||
try {
|
||||
const apiBaseUrl = `${window.location.protocol}//${window.location.hostname}:8000`;
|
||||
const modulePath = `${apiBaseUrl}/webparts/${filename}`;
|
||||
console.log(`Lade HTML-Modul von: ${modulePath}`);
|
||||
const response = await fetch(modulePath);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP-Fehler beim Laden des Moduls: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
const htmlContent = await response.text();
|
||||
return htmlContent;
|
||||
} catch (error) {
|
||||
console.error(`Fehler beim Laden des Moduls ${filename}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadModuleJs(filename) {
|
||||
try {
|
||||
const apiBaseUrl = `${window.location.protocol}//${window.location.hostname}:8000`;
|
||||
const response = await fetch(`${apiBaseUrl}/webparts/${filename}`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to load JS module: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
const jsContent = await response.text();
|
||||
// Create a script element and add it to the page
|
||||
const scriptElement = document.createElement('script');
|
||||
scriptElement.textContent = jsContent;
|
||||
document.head.appendChild(scriptElement);
|
||||
console.log(`JS module ${filename} loaded successfully`);
|
||||
} catch (error) {
|
||||
console.error(`Error loading JS module ${filename}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
function fetchFromApi(url) {
|
||||
// Basis-URL für die API mit korrektem Port
|
||||
const apiBaseUrl = `${window.location.protocol}//${window.location.hostname}:8000`;
|
||||
const fullUrl = url.startsWith('http') ? url : `${apiBaseUrl}${url}`;
|
||||
console.log(`Fetching data from: ${fullUrl}`);
|
||||
return fullUrl
|
||||
}
|
||||
|
||||
// Hilfsfunktion zum Abrufen von Daten vom Backend
|
||||
async function fetchData(url) {
|
||||
try {
|
||||
fullUrl=fetchFromApi(url)
|
||||
const response = await fetch(fullUrl);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Format-Fehler beim Abrufen von ${fullUrl}: ${response.statusText}`);
|
||||
}
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error(`Genereller Fehler beim Abrufen von ${fullUrl}:`, error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
// Hilfsfunktion zum Senden von Daten an das Backend
|
||||
async function postData(url, data) {
|
||||
try {
|
||||
fullUrl=fetchFromApi(url)
|
||||
const response = await fetch(fullUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Fehler beim Senden an ${fullUrl}: ${response.statusText}`);
|
||||
}
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error(`Fehler beim Senden an ${fullUrl}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Globale Initialisierungsfunktion
|
||||
async function initialize() {
|
||||
try {
|
||||
// Load Module Scripts
|
||||
loadModuleJs("part-workflow.js")
|
||||
loadModuleJs("part-data.js")
|
||||
loadModuleJs("part-prompts.js")
|
||||
loadModuleJs("part-agents.js")
|
||||
|
||||
// Daten vom Backend abrufen
|
||||
globalState.workspaces = await fetchData('/api/workspaces');
|
||||
globalState.availableFiles = await fetchData('/api/files');
|
||||
globalState.availablePrompts = await fetchData('/api/prompts');
|
||||
|
||||
// Wenn Workspaces vorhanden sind, den ersten auswählen
|
||||
if (globalState.workspaces.length > 0) {
|
||||
globalState.currentWorkspace = globalState.workspaces[0];
|
||||
|
||||
// Agenten für den aktuellen Workspace abrufen
|
||||
globalState.availableAgents = await fetchData(`/api/agents?workspace_id=${globalState.currentWorkspace.id}`);
|
||||
console.info("Debug agents set for: "+`/api/agents?workspace_id=${globalState.currentWorkspace.id}`+", result="+globalState.availableAgents)
|
||||
}
|
||||
|
||||
// Event-Listener für Menüpunkte
|
||||
setupMenuNavigation();
|
||||
|
||||
// Workspaces rendern, nachdem alle Daten geladen wurden
|
||||
renderWorkspaces();
|
||||
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Initialisieren der Daten:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Menünavigation einrichten
|
||||
function setupMenuNavigation() {
|
||||
const menuItems = {
|
||||
'workflow': document.querySelector('a[href="#workflow"]').parentElement,
|
||||
'data': document.querySelector('a[href="#data"]').parentElement,
|
||||
'prompts': document.querySelector('a[href="#prompts"]').parentElement,
|
||||
'agents': document.querySelector('a[href="#agents"]').parentElement
|
||||
};
|
||||
|
||||
const moduleContainers = {
|
||||
'workflow': document.getElementById('part-workflow'),
|
||||
'data': document.getElementById('part-data'),
|
||||
'prompts': document.getElementById('part-prompts'),
|
||||
'agents': document.getElementById('part-agents')
|
||||
};
|
||||
|
||||
// Menüpunkte initialisieren
|
||||
Object.keys(menuItems).forEach(key => {
|
||||
menuItems[key].addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Aktive Klasse von allen Menüpunkten entfernen
|
||||
Object.values(menuItems).forEach(item => item.classList.remove('active'));
|
||||
|
||||
// Alle Module ausblenden
|
||||
Object.values(moduleContainers).forEach(container => container.style.display = 'none')
|
||||
|
||||
// Aktuelle Ansicht aktivieren
|
||||
this.classList.add('active');
|
||||
moduleContainers[key].style.display = 'block';
|
||||
|
||||
// Laden und Aktualisieren der Moduldaten
|
||||
switch(key) {
|
||||
case 'workflow':
|
||||
loadWorkflowModule();
|
||||
break;
|
||||
case 'data':
|
||||
loadDataModule();
|
||||
break;
|
||||
case 'prompts':
|
||||
loadPromptsModule();
|
||||
break;
|
||||
case 'agents':
|
||||
loadAgentsModule();
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Initial das Workflow-Modul laden
|
||||
loadWorkflowModule();
|
||||
}
|
||||
|
||||
// Modul-Ladungsfunktionen
|
||||
async function loadWorkflowModule() {
|
||||
try {
|
||||
// Dynamisches Laden des Workflow-Moduls
|
||||
const moduleContent = await loadModuleHtml('part-workflow.html');
|
||||
const workflowModule = document.getElementById('part-workflow');
|
||||
workflowModule.innerHTML = moduleContent;
|
||||
|
||||
// Initialisiere Workflow-Modul-Funktionalität
|
||||
if (window.initWorkflowModule) {
|
||||
window.initWorkflowModule(globalState);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Laden des Workflow-Moduls:", error);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadDataModule() {
|
||||
try {
|
||||
// Dynamisches Laden des Daten-Moduls
|
||||
const moduleContent = await loadModuleHtml('part-data.html');
|
||||
const dataModule = document.getElementById('part-data');
|
||||
dataModule.innerHTML = moduleContent;
|
||||
|
||||
// Initialisiere Daten-Modul-Funktionalität
|
||||
if (window.initDataModule) {
|
||||
window.initDataModule(globalState);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Laden des Daten-Moduls:", error);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadPromptsModule() {
|
||||
try {
|
||||
// Dynamisches Laden des Prompts-Moduls
|
||||
const moduleContent = await loadModuleHtml('part-prompts.html');
|
||||
const promptsModule = document.getElementById('part-prompts');
|
||||
promptsModule.innerHTML = moduleContent;
|
||||
|
||||
// Initialisiere Prompts-Modul-Funktionalität
|
||||
if (window.initPromptsModule) {
|
||||
window.initPromptsModule(globalState);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Laden des Prompts-Moduls:", error);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadAgentsModule() {
|
||||
try {
|
||||
// Dynamisches Laden des Agenten-Moduls
|
||||
const moduleContent = await loadModuleHtml('part-agents.html');
|
||||
const agentsModule = document.getElementById('part-agents');
|
||||
agentsModule.innerHTML = moduleContent;
|
||||
|
||||
// Initialisiere Agenten-Modul-Funktionalität
|
||||
if (window.initAgentsModule) {
|
||||
window.initAgentsModule(globalState);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Laden des Agenten-Moduls:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Workspace-Funktionen
|
||||
function renderWorkspaces() {
|
||||
const workspaceList = document.getElementById('workspace-list');
|
||||
workspaceList.innerHTML = '';
|
||||
|
||||
globalState.workspaces.forEach(workspace => {
|
||||
const li = document.createElement('li');
|
||||
li.className = `workspace-item ${workspace.id === globalState.currentWorkspace?.id ? 'active' : ''}`;
|
||||
li.innerHTML = `
|
||||
<i class="fas fa-folder"></i>
|
||||
<span>${workspace.name}</span>
|
||||
`;
|
||||
li.addEventListener('click', async () => {
|
||||
globalState.currentWorkspace = workspace;
|
||||
|
||||
// Agenten für den neuen Workspace abrufen
|
||||
globalState.availableAgents = await fetchData(`/api/agents?workspace_id=${workspace.id}`);
|
||||
|
||||
renderWorkspaces();
|
||||
|
||||
// Aktualisiere aktive Module
|
||||
loadWorkflowModule();
|
||||
loadAgentsModule();
|
||||
});
|
||||
workspaceList.appendChild(li);
|
||||
});
|
||||
}
|
||||
|
||||
// Gemeinsame Utility-Funktionen
|
||||
function handleFileUpload(fileInput, onUploadSuccess) {
|
||||
return async () => {
|
||||
if (fileInput.files.length > 0) {
|
||||
for (const file of fileInput.files) {
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
|
||||
const response = await fetch('/files/upload', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Fehler beim Hochladen der Datei: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const newFile = await response.json();
|
||||
|
||||
if (onUploadSuccess) {
|
||||
onUploadSuccess(newFile);
|
||||
}
|
||||
|
||||
// Globale Dateiliste aktualisieren
|
||||
globalState.availableFiles.push(newFile);
|
||||
} catch (error) {
|
||||
console.error("Fehler beim Hochladen der Datei:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Eingabefeld zurücksetzen
|
||||
fileInput.value = "";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Initialisierung starten
|
||||
initialize();
|
||||
|
||||
// Globale Funktionen für Module exportieren
|
||||
window.globalUtils = {
|
||||
fetchData,
|
||||
postData,
|
||||
handleFileUpload,
|
||||
renderWorkspaces
|
||||
};
|
||||
}
|
||||
);
|
||||
|
|
@ -1,796 +0,0 @@
|
|||
/* Grundlegende Resets und Fonts */
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
background-color: #f0f2f5;
|
||||
color: #333;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
background: none;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
/* Navbar */
|
||||
.navbar {
|
||||
background-color: #2563eb;
|
||||
color: white;
|
||||
padding: 1rem;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.navbar-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
max-width: 1800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.navbar-logo {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.navbar-user {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.icon-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
border-radius: 50%;
|
||||
color: white;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.icon-button:hover {
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
|
||||
/* App Container Layout */
|
||||
.app-container {
|
||||
display: flex;
|
||||
max-width: 1800px;
|
||||
margin: 0 auto;
|
||||
min-height: calc(100vh - 4rem);
|
||||
}
|
||||
|
||||
/* Sidebar */
|
||||
.sidebar {
|
||||
width: 250px;
|
||||
background-color: white;
|
||||
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.05);
|
||||
padding: 1.5rem 1rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.workspace-section h2 {
|
||||
font-size: 1.2rem;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.workspace-list {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.workspace-item {
|
||||
padding: 0.5rem 0.75rem;
|
||||
border-radius: 0.375rem;
|
||||
margin-bottom: 0.25rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.workspace-item i {
|
||||
margin-right: 0.5rem;
|
||||
color: #4b5563;
|
||||
}
|
||||
|
||||
.workspace-item:hover {
|
||||
background-color: #f3f4f6;
|
||||
}
|
||||
|
||||
.workspace-item.active {
|
||||
background-color: #e0f2fe;
|
||||
color: #1d4ed8;
|
||||
}
|
||||
|
||||
.sidebar-nav {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.sidebar-item {
|
||||
padding: 0.75rem;
|
||||
border-radius: 0.375rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.sidebar-item a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.sidebar-item i {
|
||||
margin-right: 0.75rem;
|
||||
width: 1.25rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sidebar-item:hover {
|
||||
background-color: #f3f4f6;
|
||||
}
|
||||
|
||||
.sidebar-item.active {
|
||||
background-color: #e0f2fe;
|
||||
color: #1d4ed8;
|
||||
}
|
||||
|
||||
/* Main Content */
|
||||
.main-content {
|
||||
flex: 1;
|
||||
padding: 1.5rem;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.workflow-container {
|
||||
display: flex;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.config-panel, .results-panel {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* Cards */
|
||||
.card {
|
||||
background-color: white;
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||
padding: 1.25rem;
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 1rem;
|
||||
color: #4b5563;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.5rem;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
/* File Selection */
|
||||
.files-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.upload-btn {
|
||||
background-color: #fff;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 0.375rem;
|
||||
padding: 0.375rem 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
color: #4b5563;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.375rem;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.upload-btn:hover {
|
||||
background-color: #f9fafb;
|
||||
border-color: #9ca3af;
|
||||
}
|
||||
|
||||
.file-list {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 0.375rem;
|
||||
background-color: #f9fafb;
|
||||
}
|
||||
|
||||
.file-item {
|
||||
padding: 0.625rem;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.file-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.file-item-name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.file-item-info {
|
||||
font-size: 0.75rem;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.selected-files-container {
|
||||
border: 1px dashed #d1d5db;
|
||||
border-radius: 0.375rem;
|
||||
min-height: 100px;
|
||||
background-color: #f9fafb;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100px;
|
||||
color: #9ca3af;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.empty-state i {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.selected-file-list {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.selected-file-item {
|
||||
background-color: white;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 0.375rem;
|
||||
padding: 0.5rem 0.75rem;
|
||||
margin-bottom: 0.5rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.selected-file-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.remove-file-btn {
|
||||
color: #ef4444;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.remove-file-btn:hover {
|
||||
background-color: #fee2e2;
|
||||
}
|
||||
|
||||
/* Prompt input */
|
||||
#prompt-input {
|
||||
width: 100%;
|
||||
min-height: 150px;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 0.375rem;
|
||||
padding: 0.75rem;
|
||||
font-family: inherit;
|
||||
resize: vertical;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
#prompt-input:focus {
|
||||
outline: none;
|
||||
border-color: #2563eb;
|
||||
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
|
||||
}
|
||||
|
||||
/* Agent list */
|
||||
.agent-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.agent-item {
|
||||
background-color: #f9fafb;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 0.375rem;
|
||||
padding: 0.75rem;
|
||||
}
|
||||
|
||||
.agent-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.agent-checkbox {
|
||||
margin-right: 0.75rem;
|
||||
}
|
||||
|
||||
.agent-name {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.agent-description {
|
||||
margin-top: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
color: #6b7280;
|
||||
margin-left: 2rem;
|
||||
}
|
||||
|
||||
/* Action buttons */
|
||||
.action-buttons {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
|
||||
.reset-btn {
|
||||
background-color: #f3f4f6;
|
||||
color: #4b5563;
|
||||
border-radius: 0.375rem;
|
||||
padding: 0.625rem 1.25rem;
|
||||
font-weight: 500;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.reset-btn:hover {
|
||||
background-color: #e5e7eb;
|
||||
}
|
||||
|
||||
.start-btn {
|
||||
background-color: #10b981;
|
||||
color: white;
|
||||
border-radius: 0.375rem;
|
||||
padding: 0.625rem 1.25rem;
|
||||
font-weight: 500;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.start-btn:hover {
|
||||
background-color: #059669;
|
||||
}
|
||||
|
||||
.start-btn.running {
|
||||
background-color: #9ca3af;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
/* Log Container */
|
||||
.log-container {
|
||||
background-color: #111827;
|
||||
color: #34d399;
|
||||
border-radius: 0.375rem;
|
||||
padding: 0.75rem;
|
||||
font-family: 'Consolas', 'Monaco', monospace;
|
||||
font-size: 0.875rem;
|
||||
height: 300px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.log-empty-state {
|
||||
color: #6b7280;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.log-entry {
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.log-time {
|
||||
color: #9ca3af;
|
||||
}
|
||||
|
||||
.log-message {
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.log-info {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.log-success {
|
||||
color: #34d399;
|
||||
}
|
||||
|
||||
.log-error {
|
||||
color: #f87171;
|
||||
}
|
||||
|
||||
.log-start {
|
||||
color: #60a5fa;
|
||||
}
|
||||
|
||||
.log-complete {
|
||||
color: #c084fc;
|
||||
}
|
||||
|
||||
/* Results Container */
|
||||
.results-container {
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.results-empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #f9fafb;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 0.375rem;
|
||||
padding: 2.5rem 1rem;
|
||||
color: #6b7280;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sub-text {
|
||||
font-size: 0.875rem;
|
||||
color: #9ca3af;
|
||||
margin-top: 0.25rem;
|
||||
}
|
||||
|
||||
.results-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.result-item {
|
||||
background-color: #f9fafb;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 0.375rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.result-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.result-title {
|
||||
font-weight: 600;
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
.result-agent {
|
||||
font-size: 0.75rem;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.save-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
color: #2563eb;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 0.25rem;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.save-btn:hover {
|
||||
background-color: #e0f2fe;
|
||||
}
|
||||
|
||||
.result-content {
|
||||
background-color: white;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 0.375rem;
|
||||
padding: 0.75rem;
|
||||
font-size: 0.875rem;
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
background-color: white;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 0.375rem;
|
||||
padding: 0.75rem;
|
||||
text-align: center;
|
||||
height: 200px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.chart-title {
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
padding-bottom: 0.5rem;
|
||||
margin-bottom: 0.75rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Styles für die Prompt-Auswahl */
|
||||
.form-group {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.prompt-select-label {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
color: #4b5563;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.prompt-select {
|
||||
width: 100%;
|
||||
padding: 0.5rem;
|
||||
border: 1px solid #d1d5db;
|
||||
border-radius: 0.375rem;
|
||||
background-color: white;
|
||||
font-size: 0.875rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
/* Styles für die Prompt-Liste */
|
||||
.prompt-item {
|
||||
background-color: white;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 0.375rem;
|
||||
padding: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.prompt-content {
|
||||
font-size: 0.875rem;
|
||||
white-space: pre-line;
|
||||
margin-bottom: 0.5rem;
|
||||
padding: 0.75rem;
|
||||
background-color: #f9fafb;
|
||||
border-radius: 0.25rem;
|
||||
border: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.prompt-meta {
|
||||
font-size: 0.75rem;
|
||||
color: #6b7280;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.prompt-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.use-prompt-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
background-color: #10b981;
|
||||
color: white;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.use-prompt-btn:hover {
|
||||
background-color: #059669;
|
||||
}
|
||||
|
||||
.delete-prompt-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
background-color: #ef4444;
|
||||
color: white;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.delete-prompt-btn:hover {
|
||||
background-color: #dc2626;
|
||||
}
|
||||
|
||||
/* Styles für die Agenten-Liste */
|
||||
.agent-list-item {
|
||||
background-color: white;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 0.375rem;
|
||||
padding: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.agent-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.agent-header h4 {
|
||||
margin: 0;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.agent-type {
|
||||
font-size: 0.75rem;
|
||||
background-color: #e0f2fe;
|
||||
color: #0369a1;
|
||||
padding: 0.125rem 0.375rem;
|
||||
border-radius: 9999px;
|
||||
}
|
||||
|
||||
.agent-description {
|
||||
font-size: 0.875rem;
|
||||
margin-bottom: 0.75rem;
|
||||
color: #4b5563;
|
||||
}
|
||||
|
||||
.agent-capabilities {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.25rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
|
||||
.capability-tag {
|
||||
font-size: 0.75rem;
|
||||
background-color: #f3f4f6;
|
||||
color: #4b5563;
|
||||
padding: 0.125rem 0.375rem;
|
||||
border-radius: 9999px;
|
||||
}
|
||||
|
||||
.agent-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.edit-agent-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
background-color: #3b82f6;
|
||||
color: white;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.edit-agent-btn:hover {
|
||||
background-color: #2563eb;
|
||||
}
|
||||
|
||||
.delete-agent-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
background-color: #ef4444;
|
||||
color: white;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.delete-agent-btn:hover {
|
||||
background-color: #dc2626;
|
||||
}
|
||||
|
||||
/* Styles für die Dateien-Liste */
|
||||
.file-actions {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.view-file-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 1.75rem;
|
||||
height: 1.75rem;
|
||||
background-color: #3b82f6;
|
||||
color: white;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.view-file-btn:hover {
|
||||
background-color: #2563eb;
|
||||
}
|
||||
|
||||
.delete-file-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 1.75rem;
|
||||
height: 1.75rem;
|
||||
background-color: #ef4444;
|
||||
color: white;
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.delete-file-btn:hover {
|
||||
background-color: #dc2626;
|
||||
}
|
||||
|
||||
/* Styles für Abschnittsüberschriften */
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.section-header h3 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
padding: 0.375rem 0.75rem;
|
||||
background-color: #10b981;
|
||||
color: white;
|
||||
border-radius: 0.375rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.add-btn:hover {
|
||||
background-color: #059669;
|
||||
}
|
||||
89
readme.md
89
readme.md
|
|
@ -31,47 +31,6 @@ Das Projekt besteht aus zwei Hauptkomponenten:
|
|||
- `agent_service.py` - Multi-Agent-Orchestrierung
|
||||
- `requirements.txt` - Python-Abhängigkeiten
|
||||
|
||||
## Hauptfunktionen
|
||||
|
||||
### Workspace-Management
|
||||
- Mehrere Workspaces für verschiedene Projekte
|
||||
- Organisierte Gruppenarbeit mit geteilten Ressourcen
|
||||
|
||||
### Datei-Verarbeitung
|
||||
- Upload verschiedener Dateitypen (PDF, Excel, Bilder, etc.)
|
||||
- Automatische Erkennung und Kategorisierung
|
||||
|
||||
### Agent-Orchestrierung
|
||||
- Kombination verschiedener Agent-Typen:
|
||||
- **Datenanalyse-Agent**: Extrahiert Insights aus strukturierten Daten
|
||||
- **Visualisierungs-Agent**: Erstellt Diagramme und visuelle Darstellungen
|
||||
- **Text-Generator**: Verfasst Berichte und Zusammenfassungen
|
||||
- **Web-Scraper**: Sammelt externe Daten
|
||||
- **Marktanalyse-Agent**: Spezialisiert auf Wettbewerbsanalyse
|
||||
|
||||
### Workflow-Ausführung
|
||||
- Echtzeit-Protokollierung des Fortschritts
|
||||
- Vollständige Nachverfolgbarkeit aller Schritte
|
||||
|
||||
### Ergebnis-Management
|
||||
- Strukturierte Darstellung von Analysen, Diagrammen und Berichten
|
||||
- Export- und Sharing-Funktionen
|
||||
|
||||
## Installation und Einrichtung
|
||||
|
||||
### Voraussetzungen
|
||||
- Python 3.8+
|
||||
- Ein moderner Webbrowser
|
||||
- Optional: Node.js für Entwicklungswerkzeuge
|
||||
|
||||
### Frontend-Installation
|
||||
1. Klonen des Repositories
|
||||
2. Platzieren der Frontend-Dateien auf einem Webserver oder lokalen Entwicklungsserver:
|
||||
```bash
|
||||
# Mit Python einen einfachen HTTP-Server starten
|
||||
python -m http.server 8080
|
||||
```
|
||||
|
||||
### Backend-Installation
|
||||
1. Virtuelle Umgebung erstellen und aktivieren:
|
||||
```bash
|
||||
|
|
@ -95,54 +54,6 @@ Das Projekt besteht aus zwei Hauptkomponenten:
|
|||
- Backend API: `http://localhost:8000`
|
||||
- API-Dokumentation: `http://localhost:8000/docs`
|
||||
|
||||
## Verwendung: Der Customer Journey
|
||||
|
||||
### 1. Workspace auswählen oder erstellen
|
||||
- Wählen Sie einen vorhandenen Workspace oder erstellen Sie einen neuen für Ihr Projekt
|
||||
|
||||
### 2. Dateien hochladen
|
||||
- Laden Sie die zu analysierenden Dateien hoch
|
||||
- Das System erkennt automatisch Dateitypen und bereitet sie für die Verarbeitung vor
|
||||
|
||||
### 3. Prompt formulieren
|
||||
- Definieren Sie in natürlicher Sprache, was Sie analysieren möchten
|
||||
- Je präziser Ihre Anweisungen, desto zielgerichteter die Ergebnisse
|
||||
|
||||
### 4. Agenten konfigurieren
|
||||
- Wählen Sie die passenden Agenten für Ihre Aufgabe
|
||||
- Kombinieren Sie Agenten für umfassendere Analysen
|
||||
- Datenanalyse → Visualisierung → Textgenerierung
|
||||
|
||||
### 5. Workflow ausführen
|
||||
- Starten Sie den Workflow und verfolgen Sie die Ausführung in Echtzeit
|
||||
- Im linken Bereich sehen Sie die Konfiguration
|
||||
- Im rechten Bereich werden Protokoll und Ergebnisse angezeigt
|
||||
|
||||
### 6. Ergebnisse verwenden
|
||||
- Sehen Sie Analysen, Diagramme und Berichte ein
|
||||
- Exportieren oder teilen Sie die Ergebnisse
|
||||
- Iterieren Sie bei Bedarf mit angepassten Prompts oder Agent-Konfigurationen
|
||||
|
||||
## Anpassung und Erweiterung
|
||||
|
||||
### Integration mit echten KI-Diensten
|
||||
Die aktuelle Implementierung simuliert die Agent-Verarbeitung. Für eine produktive Nutzung:
|
||||
|
||||
1. Erweitern Sie `agent_service.py` mit Integrationen zu:
|
||||
- OpenAI GPT-Modellen (ChatGPT, GPT-4)
|
||||
- Claude von Anthropic
|
||||
- Eigenentwickelten Modellen mit spezieller Expertise
|
||||
|
||||
2. Implementieren Sie robuste Datei-Parser für:
|
||||
- PDF-Dokumente mit OCR
|
||||
- Excel- und CSV-Verarbeitung
|
||||
- Bild- und Medienanalyse
|
||||
|
||||
3. Ergänzen Sie Authentifizierung und Autorisierung:
|
||||
- Benutzer-Accounts mit Rollenkonzept
|
||||
- API-Schlüsselverwaltung für externe Dienste
|
||||
- Sichere Datenspeicherung
|
||||
|
||||
### Datenbank-Migration
|
||||
Für größere Installationen die JSON-basierte Datenbank ersetzen durch:
|
||||
- PostgreSQL für relationale Daten
|
||||
|
|
|
|||
34
start.bat
34
start.bat
|
|
@ -1,13 +1,13 @@
|
|||
@echo off
|
||||
echo Data Platform - Multi-Agent Service
|
||||
echo Startskript fuer Frontend und Backend
|
||||
echo Startskript fuer gwserver
|
||||
echo ----------------------------------------
|
||||
|
||||
:: Verzeichnisstruktur erstellen, falls sie nicht existiert
|
||||
if not exist backend\data mkdir backend\data
|
||||
if not exist backend\uploads mkdir backend\uploads
|
||||
if not exist backend\results mkdir backend\results
|
||||
if not exist backend\webparts mkdir backend\webparts
|
||||
if not exist gwserver\data mkdir gwserver\data
|
||||
if not exist gwserver\uploads mkdir gwserver\uploads
|
||||
if not exist gwserver\results mkdir gwserver\results
|
||||
if not exist gwserver\webparts mkdir gwserver\webparts
|
||||
|
||||
:: Prüfen, ob Python installiert ist
|
||||
python --version >nul 2>&1
|
||||
|
|
@ -17,37 +17,27 @@ if %errorlevel% neq 0 (
|
|||
)
|
||||
|
||||
:: Virtuelle Umgebung erstellen, falls sie nicht existiert
|
||||
if not exist backend\venv (
|
||||
if not exist gwserver\venv (
|
||||
echo Erstelle virtuelle Python-Umgebung...
|
||||
cd backend
|
||||
cd gwserver
|
||||
python -m venv venv
|
||||
cd ..
|
||||
)
|
||||
|
||||
:: Virtuelle Umgebung aktivieren
|
||||
echo Aktiviere virtuelle Umgebung...
|
||||
call backend\venv\Scripts\activate
|
||||
call gwserver\venv\Scripts\activate
|
||||
|
||||
:: Abhängigkeiten installieren
|
||||
echo Installiere Abhaengigkeiten...
|
||||
pip install -r requirements.txt
|
||||
|
||||
:: Starte Backend in neuem Fenster
|
||||
echo Starte Backend-Server...
|
||||
start cmd /k "cd backend && call venv\Scripts\activate && uvicorn app:app --reload --host 0.0.0.0 --port 8000"
|
||||
|
||||
:: Kurz warten, um sicherzustellen, dass das Backend startet
|
||||
timeout /t 2 >nul
|
||||
|
||||
:: Starte Frontend-Server in neuem Fenster
|
||||
echo Starte Frontend-Server...
|
||||
start cmd /k "cd frontend && python -m http.server 8080"
|
||||
:: Starte gwserver in neuem Fenster
|
||||
echo Starte gwserver-Server...
|
||||
start cmd /k "cd gwserver && call venv\Scripts\activate && uvicorn app:app --reload --host 0.0.0.0 --port 8000"
|
||||
|
||||
echo ----------------------------------------
|
||||
echo Server wurden gestartet!
|
||||
echo Frontend laeuft auf: http://localhost:8080
|
||||
echo Backend API laeuft auf: http://localhost:8000
|
||||
echo Gateway laeuft auf: http://localhost:8000
|
||||
echo API-Dokumentation: http://localhost:8000/docs
|
||||
echo Schliesse die Kommandozeilenfenster, um die Server zu beenden.
|
||||
|
||||
pause
|
||||
43
start.sh
43
start.sh
|
|
@ -6,14 +6,14 @@ BLUE='\033[0;34m'
|
|||
NC='\033[0m' # No Color
|
||||
|
||||
echo -e "${GREEN}Data Platform - Multi-Agent Service${NC}"
|
||||
echo -e "${BLUE}Startskript für Frontend und Backend${NC}"
|
||||
echo -e "${BLUE}Startskript für gwserver${NC}"
|
||||
echo "----------------------------------------"
|
||||
|
||||
# Verzeichnisstruktur erstellen, falls sie nicht existiert
|
||||
mkdir -p backend/data
|
||||
mkdir -p backend/uploads
|
||||
mkdir -p backend/results
|
||||
mkdir -p backend/webparts
|
||||
mkdir -p gwserver/data
|
||||
mkdir -p gwserver/uploads
|
||||
mkdir -p gwserver/results
|
||||
mkdir -p gwserver/webparts
|
||||
|
||||
# Prüfen, ob Python installiert ist
|
||||
if command -v python3 &>/dev/null; then
|
||||
|
|
@ -26,50 +26,37 @@ else
|
|||
fi
|
||||
|
||||
# Virtuelle Umgebung erstellen, falls sie nicht existiert
|
||||
if [ ! -d "backend/venv" ]; then
|
||||
if [ ! -d "gwserver/venv" ]; then
|
||||
echo "Erstelle virtuelle Python-Umgebung..."
|
||||
cd backend
|
||||
cd gwserver
|
||||
$PYTHON_CMD -m venv venv
|
||||
cd ..
|
||||
fi
|
||||
|
||||
# Virtuelle Umgebung aktivieren
|
||||
echo "Aktiviere virtuelle Umgebung..."
|
||||
source backend/venv/bin/activate 2>/dev/null || . backend/venv/bin/activate
|
||||
source gwserver/venv/bin/activate 2>/dev/null || . gwserver/venv/bin/activate
|
||||
|
||||
# Abhängigkeiten installieren
|
||||
echo "Installiere Abhängigkeiten..."
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Backend als Hintergrundprozess starten
|
||||
echo "Starte Backend-Server..."
|
||||
cd backend
|
||||
# gwserver als Hintergrundprozess starten
|
||||
echo "Starte gwserver-Server..."
|
||||
cd gwserver
|
||||
uvicorn app:app --reload --host 0.0.0.0 --port 8000 &
|
||||
BACKEND_PID=$!
|
||||
cd ..
|
||||
|
||||
# Kurz warten, um sicherzustellen, dass das Backend startet
|
||||
sleep 2
|
||||
|
||||
# Frontend-Server starten
|
||||
echo "Starte Frontend-Server..."
|
||||
cd frontend
|
||||
$PYTHON_CMD -m http.server 8080 &
|
||||
FRONTEND_PID=$!
|
||||
GWSERVER_PID=$!
|
||||
cd ..
|
||||
|
||||
echo "----------------------------------------"
|
||||
echo -e "${GREEN}Server wurden gestartet!${NC}"
|
||||
echo "Frontend läuft auf: http://localhost:8080"
|
||||
echo "Backend API läuft auf: http://localhost:8000"
|
||||
echo "gwserver API läuft auf: http://localhost:8000"
|
||||
echo "API-Dokumentation: http://localhost:8000/docs"
|
||||
echo -e "${BLUE}Drücke STRG+C, um beide Server zu beenden${NC}"
|
||||
echo -e "${BLUE}Drücke STRG+C, um Server zu beenden${NC}"
|
||||
|
||||
# Funktion zum Beenden der Server bei STRG+C
|
||||
cleanup() {
|
||||
echo -e "\n${GREEN}Beende Server...${NC}"
|
||||
kill $BACKEND_PID
|
||||
kill $FRONTEND_PID
|
||||
kill $GWSERVER_PID
|
||||
echo "Server wurden beendet"
|
||||
exit 0
|
||||
}
|
||||
|
|
|
|||
55
test/data.py
55
test/data.py
|
|
@ -1,55 +0,0 @@
|
|||
data_object_model = {
|
||||
"Mandate": {
|
||||
"id": "mandate_001",
|
||||
"users": [
|
||||
{
|
||||
"id": "user_001",
|
||||
"settings": {
|
||||
"id": "setting_001",
|
||||
"preferences": {}
|
||||
},
|
||||
"sessions": [
|
||||
{
|
||||
"id": "session_001",
|
||||
"timestamp": "2025-03-13T12:00:00Z",
|
||||
"active": True
|
||||
}
|
||||
],
|
||||
"workspaces": [
|
||||
{
|
||||
"id": "workspace_001",
|
||||
"prompts": [
|
||||
{
|
||||
"id": "prompt_001",
|
||||
"content": "",
|
||||
"created_at": "2025-03-13T10:30:00Z"
|
||||
}
|
||||
],
|
||||
"agents": [
|
||||
{
|
||||
"id": "agent_001",
|
||||
"type": "assistant",
|
||||
"capabilities": []
|
||||
}
|
||||
],
|
||||
"dataObjectReferences": ["dataobject_001", "dataobject_002"]
|
||||
}
|
||||
],
|
||||
"dataObjects": [
|
||||
{
|
||||
"id": "dataobject_001",
|
||||
"type": "document",
|
||||
"content": {},
|
||||
"metadata": {}
|
||||
},
|
||||
{
|
||||
"id": "dataobject_002",
|
||||
"type": "image",
|
||||
"content": {},
|
||||
"metadata": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
# pip install Flask requests gunicorn
|
||||
|
||||
from flask import Flask, request, jsonify
|
||||
import requests
|
||||
import openai
|
||||
|
||||
openai.api_key = "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"
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
# Define the routes for the gateway
|
||||
|
||||
@app.route('/service1/<path:path>', methods=['GET', 'POST', 'PUT', 'DELETE'])
|
||||
def service1_proxy(path):
|
||||
url = f'http://service1/{path}'
|
||||
response = requests.request(
|
||||
method=request.method,
|
||||
url=url,
|
||||
headers=request.headers,
|
||||
data=request.get_data(),
|
||||
cookies=request.cookies,
|
||||
allow_redirects=False
|
||||
)
|
||||
return (response.content, response.status_code, response.headers.items())
|
||||
|
||||
@app.route('/gpt', methods=['POST'])
|
||||
def gpt4_proxy():
|
||||
data = request.json
|
||||
prompt = data.get('prompt', '')
|
||||
model = 'gpt-4'
|
||||
response = openai.ChatCompletion.create(
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": prompt,
|
||||
}
|
||||
],
|
||||
model=model,
|
||||
)
|
||||
return jsonify({'response': response.choices[0].message.content.strip()})
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(host='0.0.0.0', port=8000)
|
||||
|
||||
# start with: gunicorn -w 4 -b 0.0.0.0:8000 app:app
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
import requests
|
||||
|
||||
def test_gateway(prompttext):
|
||||
url = 'https://volucy-gateway-e3d2bzbxdeaaayhz.westeurope-01.azurewebsites.net:8000/gpt'
|
||||
# url = 'http://localhost:8000/gpt'
|
||||
payload = {
|
||||
'prompt': prompttext,
|
||||
}
|
||||
response = requests.post(url, json=payload)
|
||||
if response.status_code == 200:
|
||||
print('Response from GPT:', response.json()['response'])
|
||||
else:
|
||||
print('Failed to get response:', response.status_code, response.text)
|
||||
|
||||
test_gateway("Please give me a python script to summarize all cells in an excel sheet")
|
||||
print("finished")
|
||||
Loading…
Reference in a new issue