Automatisierungen
diff --git a/src/pages/views/automation/AutomationTemplatesView.tsx b/src/pages/views/automation/AutomationTemplatesView.tsx
index 5aa4cf4..43a2cdc 100644
--- a/src/pages/views/automation/AutomationTemplatesView.tsx
+++ b/src/pages/views/automation/AutomationTemplatesView.tsx
@@ -123,7 +123,7 @@ export const AutomationTemplatesView: React.FC = () => {
}
return (
-
+
Automation-Vorlagen
diff --git a/src/pages/views/workspace/ChatStream.tsx b/src/pages/views/workspace/ChatStream.tsx
index 7bb68d7..0b5c330 100644
--- a/src/pages/views/workspace/ChatStream.tsx
+++ b/src/pages/views/workspace/ChatStream.tsx
@@ -74,6 +74,18 @@ export const ChatStream: React.FC
= ({
{msg.message}
) : (
+ {msg.documentsLabel && (
+
+ {msg.documentsLabel}
+
+ )}
{msg.message && (
{
- const msgs = (res.data.messages || []).map((m: any) => ({
- id: m.id || `loaded-${Math.random()}`,
- workflowId: wfId,
- role: m.role || 'assistant',
- message: m.content || m.message || '',
- publishedAt: m.createdAt || Date.now() / 1000,
- }));
+ const msgs = (res.data.messages || [])
+ .map((m: any) => _mapLoadedWorkspaceMessage(m, wfId))
+ .sort(_compareWorkspaceMessages);
setMessages(msgs);
})
.catch(() => {});
@@ -210,6 +206,13 @@ export function useWorkspace(instanceId: string): UseWorkspaceReturn {
role: 'user',
message: prompt,
publishedAt: Date.now() / 1000,
+ documents: _documentsFromFileIds(files, fileIds),
+ documentsLabel: _attachmentLabelFromContext(
+ dataSourceIds,
+ featureDataSourceIds,
+ dataSources,
+ featureDataSources,
+ ),
},
]);
@@ -393,7 +396,15 @@ export function useWorkspace(instanceId: string): UseWorkspaceReturn {
onStreamEnd: () => setIsProcessing(false),
});
},
- [instanceId, isProcessing, workflowId, refreshFiles],
+ [
+ instanceId,
+ isProcessing,
+ workflowId,
+ refreshFiles,
+ files,
+ dataSources,
+ featureDataSources,
+ ],
);
const stopProcessing = useCallback(() => {
@@ -468,6 +479,94 @@ export function useWorkspace(instanceId: string): UseWorkspaceReturn {
};
}
+// ---------------------------------------------------------------------------
+// Internal: loaded message mapping & attachment display
+// ---------------------------------------------------------------------------
+
+function _mapLoadedWorkspaceMessage(m: Record, wfId: string): Message {
+ const publishedAt =
+ (typeof m.publishedAt === 'number' ? m.publishedAt : undefined) ??
+ (typeof m.createdAt === 'number' ? m.createdAt : undefined) ??
+ Date.now() / 1000;
+ const docsRaw = Array.isArray(m.documents) ? m.documents : [];
+ const documents: MessageDocument[] = docsRaw.map((d: any) => ({
+ id: String(d.id || `doc-${d.fileId}`),
+ messageId: String(d.messageId || ''),
+ fileId: String(d.fileId || ''),
+ fileName: String(d.fileName || ''),
+ mimeType: String(d.mimeType || 'application/octet-stream'),
+ fileSize: Number(d.fileSize || 0),
+ roundNumber: Number(d.roundNumber ?? 0),
+ taskNumber: Number(d.taskNumber ?? 0),
+ actionNumber: Number(d.actionNumber ?? 0),
+ actionId: String(d.actionId || ''),
+ }));
+ return {
+ id: String(m.id || `loaded-${Math.random()}`),
+ workflowId: wfId,
+ role: String(m.role || 'assistant'),
+ message: String(m.content ?? m.message ?? ''),
+ publishedAt,
+ sequenceNr: typeof m.sequenceNr === 'number' ? m.sequenceNr : undefined,
+ documents: documents.length ? documents : undefined,
+ documentsLabel: typeof m.documentsLabel === 'string' ? m.documentsLabel : undefined,
+ };
+}
+
+function _compareWorkspaceMessages(a: Message, b: Message): number {
+ const ta = (a.publishedAt || 0) - (b.publishedAt || 0);
+ if (ta !== 0) return ta;
+ const sa = (a.sequenceNr ?? 0) - (b.sequenceNr ?? 0);
+ if (sa !== 0) return sa;
+ return String(a.id).localeCompare(String(b.id));
+}
+
+function _documentsFromFileIds(files: WorkspaceFile[], fileIds: string[]): MessageDocument[] | undefined {
+ const out: MessageDocument[] = [];
+ for (const fid of fileIds) {
+ const f = files.find(x => x.id === fid);
+ if (f) {
+ out.push({
+ id: `local-${fid}-${Date.now()}`,
+ messageId: '',
+ fileId: f.id,
+ fileName: f.fileName,
+ mimeType: f.mimeType,
+ fileSize: f.fileSize,
+ roundNumber: 0,
+ taskNumber: 0,
+ actionNumber: 0,
+ actionId: '',
+ });
+ }
+ }
+ return out.length ? out : undefined;
+}
+
+function _attachmentLabelFromContext(
+ dataSourceIds: string[],
+ featureDataSourceIds: string[],
+ dataSources: DataSource[],
+ featureDataSources: FeatureDataSource[],
+): string | undefined {
+ const parts: string[] = [];
+ const dsLabels = dataSourceIds
+ .map(id => {
+ const ds = dataSources.find(d => d.id === id);
+ return ds?.label || ds?.path;
+ })
+ .filter((x): x is string => Boolean(x));
+ if (dsLabels.length) parts.push(`Datenquellen: ${dsLabels.join(', ')}`);
+ const fdsLabels = featureDataSourceIds
+ .map(id => {
+ const fds = featureDataSources.find(x => x.id === id);
+ return fds ? `${fds.tableName} (${fds.label})` : '';
+ })
+ .filter(Boolean);
+ if (fdsLabels.length) parts.push(`Feature-Daten: ${fdsLabels.join(', ')}`);
+ return parts.length ? parts.join(' | ') : undefined;
+}
+
// ---------------------------------------------------------------------------
// Internal event handlers
// ---------------------------------------------------------------------------