feat: allow memory import without session (#493)
This commit is contained in:
@@ -28,6 +28,7 @@ from core.database import SessionLocal
|
||||
from src.llm_core import llm_call_async
|
||||
from services.memory.memory_extractor import audit_memories
|
||||
from src.auth_helpers import get_current_user
|
||||
from src.endpoint_resolver import resolve_endpoint
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -313,16 +314,30 @@ def setup_memory_routes(memory_manager: MemoryManager, session_manager: SessionM
|
||||
@router.post("/import")
|
||||
async def import_memories_from_file(
|
||||
request: Request,
|
||||
session: str = Form(...),
|
||||
session: str | None = Form(None),
|
||||
file: UploadFile = File(...)
|
||||
):
|
||||
"""Extract memory suggestions from an uploaded file (PDF, TXT, MD, etc.)."""
|
||||
from src.auth_helpers import require_privilege
|
||||
require_privilege(request, "can_manage_memory")
|
||||
try:
|
||||
sess = session_manager.get_session(session)
|
||||
except KeyError:
|
||||
raise HTTPException(404, "Session not found — needed for LLM config")
|
||||
|
||||
endpoint_url = None
|
||||
model = None
|
||||
headers = {}
|
||||
|
||||
if session:
|
||||
try:
|
||||
sess = session_manager.get_session(session)
|
||||
endpoint_url = sess.endpoint_url
|
||||
model = sess.model
|
||||
headers = sess.headers
|
||||
except KeyError:
|
||||
raise HTTPException(404, "Session not found — needed for LLM config")
|
||||
else:
|
||||
endpoint_url, model, headers = resolve_endpoint("utility", owner=_owner(request))
|
||||
|
||||
if not endpoint_url or not model:
|
||||
raise HTTPException(400, "No LLM model configured. Set a default model in Settings.")
|
||||
|
||||
# Read file content
|
||||
content = await file.read()
|
||||
@@ -404,15 +419,15 @@ def setup_memory_routes(memory_manager: MemoryManager, session_manager: SessionM
|
||||
|
||||
try:
|
||||
raw = await llm_call_async(
|
||||
sess.endpoint_url,
|
||||
sess.model,
|
||||
endpoint_url,
|
||||
model,
|
||||
[
|
||||
{"role": "system", "content": import_prompt},
|
||||
{"role": "user", "content": f"Document: {filename}\n\n{text}"},
|
||||
],
|
||||
temperature=0.2,
|
||||
max_tokens=2000,
|
||||
headers=sess.headers,
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
# Parse JSON
|
||||
|
||||
@@ -300,7 +300,7 @@
|
||||
<input type="file" id="memory-import-file" accept=".txt,.md,.pdf,.csv,.log,.json,.py,.js,.html" hidden />
|
||||
</div>
|
||||
<p class="memory-desc doclib-desc" style="margin:4px 0 6px;">
|
||||
Import a <code>.txt</code>, <code>.md</code>, <code>.pdf</code>, <code>.csv</code>, <code>.log</code>, <code>.json</code>, <code>.py</code>, <code>.js</code>, or <code>.html</code> file — the AI reads it and suggests candidate memories you can approve. Needs an open chat session (it uses that session's model).
|
||||
Import a <code>.txt</code>, <code>.md</code>, <code>.pdf</code>, <code>.csv</code>, <code>.log</code>, <code>.json</code>, <code>.py</code>, <code>.js</code>, or <code>.html</code> file — the AI reads it and suggests candidate memories you can approve.
|
||||
</p>
|
||||
<div class="memory-add-row" style="margin-top:8px;">
|
||||
<div class="skill-ph-wrap" style="flex:1;min-width:0;">
|
||||
@@ -1390,7 +1390,7 @@
|
||||
</div>
|
||||
<div class="admin-card">
|
||||
<h2 style="display:flex;align-items:center;gap:6px;"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:1px;opacity:0.6;flex-shrink:0"><path d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z"/></svg>Utility Model <span style="font-size:0.72em;opacity:0.55;font-weight:normal;">(Recommended: Local Endpoint)</span></h2>
|
||||
<div class="admin-toggle-sub" style="margin-bottom:8px">Runs background tasks (compaction, cleanup, auto-naming) on a small/local model instead of your chat model. Leave blank to use the chat model.</div>
|
||||
<div class="admin-toggle-sub" style="margin-bottom:8px">Runs background tasks (compaction, cleanup, auto-naming, retrieving memories from files) on a small/local model instead of your chat model. Leave blank to use the chat model.</div>
|
||||
<div class="settings-col">
|
||||
<div class="settings-row">
|
||||
<label class="settings-label">Endpoint</label>
|
||||
|
||||
@@ -1160,10 +1160,6 @@ async function handleImportFile(file) {
|
||||
if (!file) return;
|
||||
|
||||
const sessionId = sessionModule?.getCurrentSessionId?.();
|
||||
if (!sessionId) {
|
||||
showError('Open a session first — import needs an AI model');
|
||||
return;
|
||||
}
|
||||
|
||||
const importBtn = document.getElementById('memory-import-btn');
|
||||
const _origImportHtml = importBtn ? importBtn.innerHTML : '';
|
||||
@@ -1180,7 +1176,9 @@ async function handleImportFile(file) {
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
formData.append('session', sessionId);
|
||||
if (sessionId) {
|
||||
formData.append('session', sessionId);
|
||||
}
|
||||
|
||||
const res = await fetch(`${window.location.origin}/api/memory/import`, {
|
||||
method: 'POST',
|
||||
|
||||
Reference in New Issue
Block a user