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 editId = $state<string | null>(null)
|
||||||
let editContent = $state('')
|
let editContent = $state('')
|
||||||
let editCategory = $state('stable')
|
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(
|
const filtered = $derived(
|
||||||
filter === 'all' ? memories : memories.filter(m => m.category === filter)
|
filter === 'all' ? memories : memories.filter(m => m.category === filter)
|
||||||
@@ -94,6 +103,26 @@
|
|||||||
editId = m.id; editContent = m.content; editCategory = m.category
|
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() })
|
$effect(() => { load() })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -102,11 +131,63 @@
|
|||||||
<h1>Gedächtnis</h1>
|
<h1>Gedächtnis</h1>
|
||||||
<div class="sub">Fakten, Entscheidungen und Kontext — geteilt von allen KI-Tools via MCP.</div>
|
<div class="sub">Fakten, Entscheidungen und Kontext — geteilt von allen KI-Tools via MCP.</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="primary" style="flex-shrink:0;margin-top:4px"
|
<div class="flex gap-2" style="flex-shrink:0;margin-top:4px">
|
||||||
onclick={() => { adding = !adding; newContent = '' }}>
|
<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'}
|
{adding ? 'Abbrechen' : '+ Eintrag'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</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 -->
|
<!-- Add form -->
|
||||||
{#if adding}
|
{#if adding}
|
||||||
|
|||||||
Vendored
+41
-37
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user