feat(desktop): merge desktop_sessions.json on memory import

Import now also merges the source's temp/desktop_sessions.json into the
current session list (dedup by id), updating both memory and the on-disk
file so past desktop chats reappear in the sidebar immediately.

- manager.import_sessions(): id-dedup merge, in-memory + persist
- import handler returns sessionsAdded/sessionsSkipped
- frontend shows session count in toast and reloads the sidebar
This commit is contained in:
yiqi-017 committed 2026-07-06 00:48:15 +08:00
1 parent ec44d69bfe
commit aff6560440
3 files changed
+51 -1

No files matched your search

+6
View File
@@ -461,6 +461,7 @@ const I18N = {
'sys.memoryImported': '记忆已导入',
'err.memoryImport': '导入记忆失败',
'sys.memoryImportBackup': '原记忆已备份至',
'sys.memorySessions': '会话',
'sys.memoryPickTitle': '选择 GenericAgent 根目录(包含 memory 与 temp 的目录)',
'sys.memoryImportPrompt': '请输入 GenericAgent 根目录的完整路径(包含 memory 与 temp 的目录,而非 memory 文件夹本身):',
'sys.mykeyExported': '模型配置已导出',
@@ -639,6 +640,7 @@ const I18N = {
'sys.memoryImported': 'Memory imported',
'err.memoryImport': 'Failed to import memory',
'sys.memoryImportBackup': 'Previous memory backed up to',
'sys.memorySessions': 'sessions',
'sys.memoryPickTitle': 'Select the GenericAgent root directory (the folder containing memory and temp)',
'sys.memoryImportPrompt': 'Enter the full path of the GenericAgent root directory (the folder containing memory and temp, not the memory folder itself):',
'sys.mykeyExported': 'Model config exported',
@@ -1030,7 +1032,11 @@ async function importMemoryFromDir() {
if (!res || res.ok === false) throw new Error((res && res.error) || 'import failed');
const detail = `memory: ${res.memoryCopied}, model_responses: ${res.responsesCopied}`
+ (res.responsesSkipped ? ` (skip ${res.responsesSkipped})` : '')
+ `, ${t('sys.memorySessions')}: ${res.sessionsAdded || 0}`
+ (res.backupDir ? `\n${t('sys.memoryImportBackup')}: ${res.backupDir}` : '');
if (res.sessionsAdded) {
try { await loadSessions(); } catch (_) {}
}
showChanToast(t('sys.memoryImported'), detail, 'ok');
}
bindClick('import-memory-btn', async (e) => {
+1 -1
View File
@@ -678,6 +678,6 @@
<!-- highlight.js -->
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/highlight.min.js" crossorigin="anonymous"></script>
<script src="phosphor-icons.js?v=2"></script>
<script src="app.js?v=210"></script>
<script src="app.js?v=211"></script>
</body>
</html>
+44
View File
@@ -188,6 +188,49 @@ class AgentManager:
except Exception as e:
print(f"[bridge] load sessions failed: {e}", file=sys.stderr)
def import_sessions(self, source_dir: str) -> dict:
"""把 source_dir/temp/desktop_sessions.json 合并进当前会话列表(按 id 去重)。
既更新内存(立即在侧边栏可见)又落盘。返回新增/跳过计数。
"""
src = Path(source_dir).expanduser().resolve()
src_file = src / "temp" / "desktop_sessions.json"
if not src_file.is_file():
return {"sessionsAdded": 0, "sessionsSkipped": 0, "sessionsFileFound": False}
try:
arr = json.loads(src_file.read_text(encoding="utf-8"))
if not isinstance(arr, list):
raise ValueError("desktop_sessions.json is not a list")
except Exception as e:
raise ValueError(f"cannot read desktop_sessions.json: {e}")
added = 0
skipped = 0
with self.lock:
for item in arr:
sid = item.get("id")
if not sid or sid in self.sessions:
skipped += 1
continue
msgs = item.get("messages", [])
sess = Session(id=sid, title=item.get("title", "New chat"),
cwd=item.get("cwd", self.ga_root),
created_at=item.get("created_at", time.time()),
updated_at=item.get("updated_at", time.time()),
messages=msgs,
msg_seq=item.get("msg_seq", 0),
pinned=item.get("pinned", False),
untitled=item.get("untitled", True),
plan_scan_baseline=_load_plan_baseline(item, msgs),
plan_path=_sanitize_desktop_plan_path(sid, item.get("plan_path") or ""),
status="idle", agent=None,
llm_history=item.get("llm_history"),
llm_no=item.get("llm_no"))
self.sessions[sid] = sess
added += 1
if added:
self._persist()
return {"sessionsAdded": added, "sessionsSkipped": skipped, "sessionsFileFound": True}
def _mykey_file(self) -> Path:
p = Path(self.ga_root) / "mykey.py"
if not p.exists():
@@ -1812,6 +1855,7 @@ async def memory_import_handler(request):
return json_ok({"ok": False, "error": "missing_sourceDir"}, status=400)
try:
result = _import_memory_from(source_dir, manager.ga_root)
result.update(manager.import_sessions(source_dir))
except Exception as e:
return json_ok({"ok": False, "error": str(e)}, status=400)
return json_ok(result)