nodes-ui-flow / src /nodes /KnowledgeAnswerFlowNode.jsx
markitzeroo
Deploy updated nodes UI flow
1dd9186
import { memo, useState } from 'react';
import NodeShell from '../components/NodeShell.jsx';
import { useWorkflow } from '../context/WorkflowContext.jsx';
import { uploadContextFile } from '../lib/api.js';
import { getNodeAccent } from '../lib/nodeRegistry.js';
function arrayBufferToBase64(buffer) {
const bytes = new Uint8Array(buffer);
let binary = '';
bytes.forEach((byte) => {
binary += String.fromCharCode(byte);
});
return window.btoa(binary);
}
function KnowledgeAnswerFlowNode({ id, data, selected, type }) {
const { backendUrl, getNodeHandles, patchNodeData } = useWorkflow();
const handles = getNodeHandles(type, data);
const runtime = data.runtime || {};
const [isUploading, setIsUploading] = useState(false);
const [uploadError, setUploadError] = useState('');
const handleUpload = async (event) => {
const file = event.target.files?.[0];
event.target.value = '';
if (!file) {
return;
}
setIsUploading(true);
setUploadError('');
try {
const contentBase64 = arrayBufferToBase64(await file.arrayBuffer());
const context = await uploadContextFile(backendUrl, file.name, contentBase64);
patchNodeData(id, {
source: 'uploaded',
contextPath: context.context_path || '',
originalPath: context.original_path || '',
contextFilename: context.filename || file.name,
contextCharacters: context.characters || 0,
});
} catch (error) {
console.error('Failed to upload knowledge context:', error);
setUploadError(error instanceof Error ? error.message : 'Не удалось загрузить knowledge-файл');
} finally {
setIsUploading(false);
}
};
return (
<NodeShell
nodeId={id}
title={data.title}
accent={getNodeAccent(type)}
selected={selected}
status={runtime.status}
inputs={handles.inputs}
outputs={handles.outputs}
>
<div className="field-stack">
<label className="field-stack">
<span className="field-label">Источник знаний</span>
<select
className="nodrag node-input"
value={data.source || 'uploaded'}
onChange={(event) => patchNodeData(id, { source: event.target.value })}
>
<option value="uploaded">Загруженный файл</option>
<option value="rag">RAG-заглушка</option>
</select>
</label>
{data.source !== 'rag' ? (
<label className="field-stack">
<span className="field-label">Knowledge-файл для этой ноды</span>
<input
className="nodrag node-input"
type="file"
accept=".doc,.docx,.md,.txt"
disabled={isUploading}
onChange={handleUpload}
/>
<small>
{data.contextPath
? `${data.contextFilename || 'Загруженный файл'} -> ${data.contextPath}`
: 'Файл к этой ноде не привязан'}
</small>
</label>
) : null}
<div className="node-note">
{runtime.answer
? `Ответ: ${runtime.answer}`
: 'Отвечает на последний вопрос пользователя по knowledge-файлу этой ноды или RAG-заглушке.'}
</div>
{isUploading ? <div className="node-note">Загружаю и извлекаю текст...</div> : null}
{uploadError ? <div className="node-error">{uploadError}</div> : null}
{runtime.error ? <div className="node-error">{runtime.error}</div> : null}
</div>
</NodeShell>
);
}
export default memo(KnowledgeAnswerFlowNode);