feat(v8.3): Memory Import aus Cloud-KIs + Batch-POST
- MemoryPanel: "Import"-Button öffnet Formular - Jede Zeile wird ein eigener Gedächtnis-Eintrag (Batch-POST) - Kategorie + Quelle (claude/gemini/chatgpt/import) wählbar - Zeilen-Vorschau zeigt erkannte Einträge vor dem Speichern Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,15 @@
|
||||
let editId = $state<string | null>(null)
|
||||
let editContent = $state('')
|
||||
let editCategory = $state('stable')
|
||||
let importing = $state(false)
|
||||
let importText = $state('')
|
||||
let importCategory = $state('stable')
|
||||
let importSource = $state('import')
|
||||
let importBusy = $state(false)
|
||||
|
||||
const importLines = $derived(
|
||||
importText.split('\n').map(l => l.trim()).filter(l => l.length > 0)
|
||||
)
|
||||
|
||||
const filtered = $derived(
|
||||
filter === 'all' ? memories : memories.filter(m => m.category === filter)
|
||||
@@ -94,6 +103,26 @@
|
||||
editId = m.id; editContent = m.content; editCategory = m.category
|
||||
}
|
||||
|
||||
async function runImport() {
|
||||
if (importLines.length === 0) return
|
||||
importBusy = true
|
||||
let ok = 0
|
||||
for (const line of importLines) {
|
||||
try {
|
||||
const m = await api('/api/memory', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ content: line, category: importCategory, source: importSource })
|
||||
})
|
||||
memories = [m, ...memories]
|
||||
ok++
|
||||
} catch {}
|
||||
}
|
||||
importBusy = false
|
||||
importing = false
|
||||
importText = ''
|
||||
toast(`${ok} von ${importLines.length} Einträgen importiert`)
|
||||
}
|
||||
|
||||
$effect(() => { load() })
|
||||
</script>
|
||||
|
||||
@@ -102,12 +131,64 @@
|
||||
<h1>Gedächtnis</h1>
|
||||
<div class="sub">Fakten, Entscheidungen und Kontext — geteilt von allen KI-Tools via MCP.</div>
|
||||
</div>
|
||||
<button class="primary" style="flex-shrink:0;margin-top:4px"
|
||||
onclick={() => { adding = !adding; newContent = '' }}>
|
||||
{adding ? 'Abbrechen' : '+ Eintrag'}
|
||||
</button>
|
||||
<div class="flex gap-2" style="flex-shrink:0;margin-top:4px">
|
||||
<button class="ghost" onclick={() => { importing = !importing; adding = false; importText = '' }}>
|
||||
{importing ? 'Abbrechen' : '⇩ Import'}
|
||||
</button>
|
||||
<button class="primary" onclick={() => { adding = !adding; importing = false; newContent = '' }}>
|
||||
{adding ? 'Abbrechen' : '+ Eintrag'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Import form -->
|
||||
{#if importing}
|
||||
<div class="card" style="border-color:rgba(45,212,191,.25)">
|
||||
<div class="card-h"><h3>Import aus Claude / Gemini / ChatGPT</h3></div>
|
||||
<div class="card-sub" style="margin-bottom:10px">
|
||||
Füge Erkenntnisse aus anderen KI-Sessions ein — jede Zeile wird ein eigener Eintrag.
|
||||
</div>
|
||||
<label>Einträge (eine Zeile = ein Eintrag)</label>
|
||||
<textarea
|
||||
rows="8"
|
||||
placeholder={"Tobi arbeitet am liebsten abends.\nProjektsprache: Deutsch.\nBosgame M5 läuft mit Ubuntu 26.04.\n..."}
|
||||
style="width:100%;box-sizing:border-box;resize:vertical;margin-bottom:10px;font-family:var(--mono);font-size:12.5px"
|
||||
bind:value={importText}
|
||||
></textarea>
|
||||
<div style="display:flex;gap:12px;flex-wrap:wrap;margin-bottom:14px">
|
||||
<div style="flex:1;min-width:160px">
|
||||
<label>Kategorie für alle Einträge</label>
|
||||
<select bind:value={importCategory} style="margin-bottom:0">
|
||||
<option value="user">Über mich — Wer du bist, Präferenzen</option>
|
||||
<option value="instruction">Verhalten — Regeln für alle KI-Tools</option>
|
||||
<option value="stable">Stabil — Projektfakten</option>
|
||||
<option value="versioned">Versioniert — Tech-Versionen</option>
|
||||
<option value="ephemeral">Temporär — 7 Tage, dann weg</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="flex:1;min-width:120px">
|
||||
<label>Quelle</label>
|
||||
<select bind:value={importSource} style="margin-bottom:0">
|
||||
<option value="import">import</option>
|
||||
<option value="claude">claude</option>
|
||||
<option value="gemini">gemini</option>
|
||||
<option value="chatgpt">chatgpt</option>
|
||||
<option value="manual">manual</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{#if importLines.length > 0}
|
||||
<div class="card-sub" style="margin-bottom:10px">{importLines.length} Eintrag/Einträge erkannt</div>
|
||||
{/if}
|
||||
<div class="btn-row">
|
||||
<button class="primary" onclick={runImport} disabled={importLines.length === 0 || importBusy}>
|
||||
{importBusy ? 'Importiere…' : `${importLines.length} Einträge speichern`}
|
||||
</button>
|
||||
<button class="ghost" onclick={() => { importing = false; importText = '' }}>Abbrechen</button>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Add form -->
|
||||
{#if adding}
|
||||
<div class="card">
|
||||
|
||||
Reference in New Issue
Block a user