separated gateway from frontend

This commit is contained in:
valueon 2025-03-15 21:27:59 +01:00
parent fce4c721c6
commit 5a0c7e0ae8
30 changed files with 27 additions and 2504 deletions

View file

@ -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>

View file

@ -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;
})();

View file

@ -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>

View file

@ -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;
})();

View file

@ -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>

View file

@ -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;
})();

View file

@ -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>

View file

@ -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.

View file

@ -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>

View file

@ -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>

View file

@ -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
};
}
);

View file

@ -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;
}

View file

@ -31,47 +31,6 @@ Das Projekt besteht aus zwei Hauptkomponenten:
- `agent_service.py` - Multi-Agent-Orchestrierung - `agent_service.py` - Multi-Agent-Orchestrierung
- `requirements.txt` - Python-Abhängigkeiten - `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 ### Backend-Installation
1. Virtuelle Umgebung erstellen und aktivieren: 1. Virtuelle Umgebung erstellen und aktivieren:
```bash ```bash
@ -95,54 +54,6 @@ Das Projekt besteht aus zwei Hauptkomponenten:
- Backend API: `http://localhost:8000` - Backend API: `http://localhost:8000`
- API-Dokumentation: `http://localhost:8000/docs` - 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 ### Datenbank-Migration
Für größere Installationen die JSON-basierte Datenbank ersetzen durch: Für größere Installationen die JSON-basierte Datenbank ersetzen durch:
- PostgreSQL für relationale Daten - PostgreSQL für relationale Daten

View file

@ -1,13 +1,13 @@
@echo off @echo off
echo Data Platform - Multi-Agent Service echo Data Platform - Multi-Agent Service
echo Startskript fuer Frontend und Backend echo Startskript fuer gwserver
echo ---------------------------------------- echo ----------------------------------------
:: Verzeichnisstruktur erstellen, falls sie nicht existiert :: Verzeichnisstruktur erstellen, falls sie nicht existiert
if not exist backend\data mkdir backend\data if not exist gwserver\data mkdir gwserver\data
if not exist backend\uploads mkdir backend\uploads if not exist gwserver\uploads mkdir gwserver\uploads
if not exist backend\results mkdir backend\results if not exist gwserver\results mkdir gwserver\results
if not exist backend\webparts mkdir backend\webparts if not exist gwserver\webparts mkdir gwserver\webparts
:: Prüfen, ob Python installiert ist :: Prüfen, ob Python installiert ist
python --version >nul 2>&1 python --version >nul 2>&1
@ -17,37 +17,27 @@ if %errorlevel% neq 0 (
) )
:: Virtuelle Umgebung erstellen, falls sie nicht existiert :: Virtuelle Umgebung erstellen, falls sie nicht existiert
if not exist backend\venv ( if not exist gwserver\venv (
echo Erstelle virtuelle Python-Umgebung... echo Erstelle virtuelle Python-Umgebung...
cd backend cd gwserver
python -m venv venv python -m venv venv
cd .. cd ..
) )
:: Virtuelle Umgebung aktivieren :: Virtuelle Umgebung aktivieren
echo Aktiviere virtuelle Umgebung... echo Aktiviere virtuelle Umgebung...
call backend\venv\Scripts\activate call gwserver\venv\Scripts\activate
:: Abhängigkeiten installieren :: Abhängigkeiten installieren
echo Installiere Abhaengigkeiten... echo Installiere Abhaengigkeiten...
pip install -r requirements.txt pip install -r requirements.txt
:: Starte Backend in neuem Fenster :: Starte gwserver in neuem Fenster
echo Starte Backend-Server... echo Starte gwserver-Server...
start cmd /k "cd backend && call venv\Scripts\activate && uvicorn app:app --reload --host 0.0.0.0 --port 8000" start cmd /k "cd gwserver && 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"
echo ---------------------------------------- echo ----------------------------------------
echo Server wurden gestartet! echo Server wurden gestartet!
echo Frontend laeuft auf: http://localhost:8080 echo Gateway laeuft auf: http://localhost:8000
echo Backend API laeuft auf: http://localhost:8000
echo API-Dokumentation: http://localhost:8000/docs echo API-Dokumentation: http://localhost:8000/docs
echo Schliesse die Kommandozeilenfenster, um die Server zu beenden.
pause pause

View file

@ -6,14 +6,14 @@ BLUE='\033[0;34m'
NC='\033[0m' # No Color NC='\033[0m' # No Color
echo -e "${GREEN}Data Platform - Multi-Agent Service${NC}" 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 "----------------------------------------" echo "----------------------------------------"
# Verzeichnisstruktur erstellen, falls sie nicht existiert # Verzeichnisstruktur erstellen, falls sie nicht existiert
mkdir -p backend/data mkdir -p gwserver/data
mkdir -p backend/uploads mkdir -p gwserver/uploads
mkdir -p backend/results mkdir -p gwserver/results
mkdir -p backend/webparts mkdir -p gwserver/webparts
# Prüfen, ob Python installiert ist # Prüfen, ob Python installiert ist
if command -v python3 &>/dev/null; then if command -v python3 &>/dev/null; then
@ -26,50 +26,37 @@ else
fi fi
# Virtuelle Umgebung erstellen, falls sie nicht existiert # Virtuelle Umgebung erstellen, falls sie nicht existiert
if [ ! -d "backend/venv" ]; then if [ ! -d "gwserver/venv" ]; then
echo "Erstelle virtuelle Python-Umgebung..." echo "Erstelle virtuelle Python-Umgebung..."
cd backend cd gwserver
$PYTHON_CMD -m venv venv $PYTHON_CMD -m venv venv
cd .. cd ..
fi fi
# Virtuelle Umgebung aktivieren # Virtuelle Umgebung aktivieren
echo "Aktiviere virtuelle Umgebung..." 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 # Abhängigkeiten installieren
echo "Installiere Abhängigkeiten..." echo "Installiere Abhängigkeiten..."
pip install -r requirements.txt pip install -r requirements.txt
# Backend als Hintergrundprozess starten # gwserver als Hintergrundprozess starten
echo "Starte Backend-Server..." echo "Starte gwserver-Server..."
cd backend cd gwserver
uvicorn app:app --reload --host 0.0.0.0 --port 8000 & uvicorn app:app --reload --host 0.0.0.0 --port 8000 &
BACKEND_PID=$! GWSERVER_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=$!
cd .. cd ..
echo "----------------------------------------" echo "----------------------------------------"
echo -e "${GREEN}Server wurden gestartet!${NC}" echo "gwserver API läuft auf: http://localhost:8000"
echo "Frontend läuft auf: http://localhost:8080"
echo "Backend API läuft auf: http://localhost:8000"
echo "API-Dokumentation: http://localhost:8000/docs" 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 # Funktion zum Beenden der Server bei STRG+C
cleanup() { cleanup() {
echo -e "\n${GREEN}Beende Server...${NC}" echo -e "\n${GREEN}Beende Server...${NC}"
kill $BACKEND_PID kill $GWSERVER_PID
kill $FRONTEND_PID
echo "Server wurden beendet" echo "Server wurden beendet"
exit 0 exit 0
} }

View file

@ -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": {}
}
]
}
]
}
}

View file

@ -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

View file

@ -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")