/* Inject, Status, Settings modes — real API */ // ── Inject ──────────────────────────────────────────────────── function InjectMode({ onHome }) { const [step, setStep] = React.useState('select'); const [project, setProject] = React.useState(null); const [type, setType] = React.useState(null); const [text, setText] = React.useState(''); const [saving, setSaving] = React.useState(false); const fileRef = React.useRef(null); const projectsQ = useApi(() => API.projects(), []); const projects = (projectsQ.data?.projects || []).filter(p => !p.archived); const saveText = async () => { if (!text.trim()) return; setSaving(true); try { await API.injectText(project, text); setText(''); setStep('done'); } catch (e) { alert('Ошибка: ' + e.message); } finally { setSaving(false); } }; const saveFile = async (file) => { if (!file) return; setSaving(true); try { const fd = new FormData(); fd.append('file', file); await API.injectFile(project, fd); setStep('done'); } catch (e) { alert('Ошибка: ' + e.message); } finally { setSaving(false); } }; if (step === 'done') { return (
saved} onHome={onHome} />
Сохранено в {project}
{type === 'file' ? `Файл → projects/${project}/injected/. Embedder проиндексирует при следующем цикле.` : `Инструкция → projects/${project}/memory.md. M1 учтёт в следующем запросе.`}
); } if (step === 'select') { return (
router · embedder} onHome={onHome} />
в какой проект
{projectsQ.loading ?
: projectsQ.error ? : projects.length === 0 ?
Нет проектов
: projects.map(p => (
{ setProject(p.name); setStep('type'); }}>
{p.name} {p.parent_id && [sub]}
{p.mode} · {p.status}
)) }
Inject — одноразовая сессия. M1/M2 не задействованы.
); } if (step === 'type') { return (
target: {project} {onHome && }
Тип инъекции
); } if (step === 'file') { return (
→ injected/ {onHome && }
Загрузка файла
e.target.files[0] && saveFile(e.target.files[0])} />
Выбери файл
любой формат · до 10 MB
); } // text instruction return (
→ memory.md {onHome && }
Инструкция