Commit Graph

791 Commits

Author SHA1 Message Date
0aa8af8618 fix(chat): 显式新建对话路由隔离后端残留上下文
/new 与 /multiagent/new 上不再被 terminal 状态快照、对话广播事件
拽回上一个对话;个性化默认值在显式新建路由下保持权威。
2026-07-28 18:43:19 +08:00
3c66c6b05f refactor(naming): 移除代码中的第三方产品名
- DeepSeekClient → APIClient(含 7 个 mixin,38 个文件)
- --claude-* CSS 变量全部替换为新语义 token,删除 _tokens.scss 兼容别名
- build_openai_tools → build_llm_tools
- login/register.html 主题 key claude → classic;terminal.html 变量改 --app- 前缀
- 注释中的 Claude 归因描述中性化
- 顺带删除误跟踪的 __pycache__ .pyc 缓存
2026-07-28 18:43:03 +08:00
0eaa8ba450 feat(quickdock): 新增快捷窗口自动展开设置,修复展开按钮与动画
- 个人空间·外观与显示新增「快捷窗口自动展开」开关(默认开);
  关闭后新内容到达不再自动展开,只能通过右侧悬浮按钮手动展开;
  设置切换立即生效
- 展开/收起悬浮按钮无内容时也常显;线条色对齐左侧对话记录侧边栏
  (--claude-text),移除 hover 与展开态变色
- 修复展开动画方向:empty 态保留上下 padding,消除 padding-top
  过渡带来的垂直分量,展开恢复为纯横向从右到左
2026-07-28 12:49:24 +08:00
ce3979d9c7 fix(frontend): 自定义工具指南 md 移入前端源码树,修复构建失败
doc/ 目录在公开发布清洗中已取消追踪,但 CustomToolsGuideApp.vue
仍以 ?raw 方式 import 其中的 custom_tools_guide.md,导致克隆/
同步 main 后 vite 构建无法解析该文件。将指南移入 static/src/admin/
与使用方同目录,import 改为相对路径。
2026-07-28 01:00:36 +08:00
f1fcba1da0 perf(chat): 折叠块跳过子树渲染,根治窗口拖拽卡顿
- 极简模式(0fr)与堆叠/思维链(max-height:0)折叠只裁视觉,DOM 仍全量
  参与布局,几千节点的步骤组在窗口拖拽时逐帧重排导致卡顿;
  折叠态改为 content-visibility:hidden + contain-intrinsic-size:0
  跳过整个子树渲染
- 过渡列表加入 content-visibility + transition-behavior:allow-discrete,
  隐藏翻转延迟到收起动画结束后生效,展开立即恢复;不支持的引擎
  退化为立即跳过,动画本体不受影响
- 删除 .stacked-block .collapsible-content 冗余 transition 规则:
  特异性更高且漏写 content-visibility,曾致收起时内容瞬间消失、
  块高瞬间坍塌而外壳慢一拍
- 堆叠块收放改为纯容器裁切、不淡出,与极简模式一致
2026-07-27 23:58:55 +08:00
8741edec18 feat(chat): 快捷导航三态自适应布局与快捷窗口手动收起
- 左侧输入跳转导航支持钉死/居中/隐藏三态:随轨宽空白自适应,
  波浪宽度按可用空白比例压缩避免遮挡消息;滚动位置同步高亮当前阅读轮次
- QuickDock 新增悬浮展开/收起按钮,userCollapsed 与无内容自动收起相互独立
- 轨宽/空白经 ResizeObserver 实测校准,兼容 macOS 经典滚动条宽度差异
2026-07-27 20:07:03 +08:00
eaa312acd4 fix(quickdock): 移除后台指令详情首行命令高亮 2026-07-26 00:56:26 +08:00
7ed54456d6 feat(chat): 对话区左侧用户输入快捷跳转导航 2026-07-26 00:56:08 +08:00
87a6a03943 feat(settings): 新建对话按钮行为可选,移除根目录创建文件与诊断日志入口 2026-07-26 00:55:46 +08:00
57352b28fb feat(compression): 深度压缩提示词支持轮次/最新输入占位与运行时状态注入 2026-07-26 00:55:24 +08:00
64902b124a feat(admin): 二级密码未配置时显示设置引导页,登录 Docker 报错改为原地弹窗 2026-07-25 16:52:42 +08:00
b78504c31e fix(admin): 修复管理面板创建旧式命名孤儿容器,切除 app_legacy 旧架构死代码 2026-07-25 12:27:06 +08:00
cf51ab0555 refactor(cleanup): 移除余额查询功能、清理前端调试日志、规整终端输出 2026-07-25 12:07:04 +08:00
bb420b0d04 chore(repo): 公开发布准备——取消追踪非源码文件并重写配置文档
- 取消追踪 552 个文件(运行态数据、密钥历史、实验/归档目录、
  agentskills/easyagent/demo/android-webview-app 等不公开内容)
- .gitignore 追加公开发布排除项与 cache/ 忽略
- 重写 README.md:mac 为主/开发中声明、web/host 双模式、Docker 镜像、
  数据存储、settings.json/custom_models.json 配置说明
- .env.example 删除失效项(AGENT_API_* 等),标注推荐 settings.json
- 新增 config/custom_models.json.example(Kimi-K3 蓝本 + DeepSeek 示例)
- 修复 utils/perf_log.py 硬编码本机路径(改走 config.paths.LOGS_DIR)
2026-07-25 00:44:15 +08:00
a900d6cc61 fix(sidebar): 修复删除工作区不生效与控制台 TDZ 报错
- ConversationSidebar: immediate watcher 在 setup 阶段同步执行,却引用了
  之后才声明的 isGroupByWorkspaceActive,触发 TDZ ReferenceError;
  调整声明顺序并加注释防回退
- WorkspaceSwitcher: onDocClick 为捕获阶段监听,未排除 teleport 到 body
  的二级菜单,点击菜单项(删除/重命名)会先关闭整个浮层,导致内联
  确认框永远不可见、删除流程无法走完;补充 .ws-menu-floating 排除
- WorkspaceSwitcher: 删除确认按钮区靠右对齐
2026-07-23 21:55:14 +08:00
c6151e86fe chore(prompts): 调整沙箱权限提示、ask_user 适用边界与 git 提交授权语义 2026-07-23 19:41:16 +08:00
f25523e441 fix(sidebar): 侧边栏样式与动画修复,对话搜索重构为后端跨工作区聚合
- 对话条目:修复「…」按钮因 action-wrap 宽度未随 32px 列同步而溢出条目圆角外(并移除无效的分组列宽覆盖)
- 工作区入口按钮:移除右侧当前工作区名称
- 切换工作区:重排期间禁用子对话 FLIP 位移与展开折叠过渡,全部瞬间移动(不影响新建/复制/删除动画)
- 删除动画:before-leave 用 offsetTop 锁定离场元素原位,修复 flex 容器 absolute 静态位置跳到顶部导致非首条删除无左滑
- 个人空间:修复「按项目分组对话」勾选框 SVG path 多重复一段导致描边错位
- 搜索:改为后端 /api/conversations/search(标题+首条用户消息首句匹配,带实例级缓存),分组模式 all_workspaces=1 跨工作区搜索并按工作区分类展示;移除前端 N+1 预览请求与 project_path 噪音匹配
2026-07-23 19:26:55 +08:00
b593d63856 feat(frontend): 侧边栏紧凑化与挤压式重设计,移除工作区面板功能拆分
- 对话侧边栏:行高/字号/圆角紧凑化,fixed 覆盖式改为文档流挤压式展开,移除工作区/虚拟显示器按钮
- 新增 WorkspaceSwitcher 浮层组件:列表即切换器,内联重命名/删除确认/新建表单动画,「…」菜单 fixed 逃逸裁切,刚好 7 行内部滚动
- 移除 LeftPanel 及两个旧工作区对话框:管理工作区迁入侧边栏,文件管理迁入输入栏 + 菜单(最多 4 项滚动)
- 个人空间移除默认隐藏工作区/隐藏快捷窗口设置项;删除 panelMode 门控轮询(QuickDock 常驻轮询 + socket 推送替代)
- 修复 flex 压缩导致菜单行高失效、分组对话 viewport 裁切最后一行、action-wrap 撑高对话项、/new 残留最近对话待办(无对话 id 不再请求 todo-list)
- 工作区入口按钮改内联 layers 图标并统一 18px,host/docker 模式 localStorage 缓存避免按钮首屏延迟出现
2026-07-23 16:47:49 +08:00
15779be939 fix(quickdock): 修复待办窗口在移动端↔桌面端切换后被吞不恢复
TodoWindow 的 visible/rows 由 watch(todoList) 驱动但缺少 immediate: true,
视口切换导致 QuickDock 整体 v-if 卸载重挂时,store 中 todoList 未变化
watch 不触发,visible 永远停留在初始 false。与 RunnerWindow/FileWindow
对齐补上 immediate: true,重挂载时按现有数据立即初始化。
2026-07-23 00:51:08 +08:00
2b84a7adf8 perf(chat): 对话区 virtua 窗口化渲染,解决挤压卡顿与全量渲染
- v-for 全量渲染改为 virtua Virtualizer 窗口化,只挂载可视区+buffer 消息块
- 追底引擎 resize 弹簧动画改 instant:拖拽挤压时逐帧瞬时吸底,内容向上生长
- 消息按对象身份(WeakMap)分配稳定 key,支撑 virtua 逐项高度缓存
- 用户气泡随滚动重挂载时补测量/补观察,保证折叠状态正确恢复
- 滚动追踪日志默认关闭(逐scroll事件日志本身是每帧开销),排障可显式开启
- 修复 2 处依赖 DOM 层级的 CSS 结构选择器
- 新增依赖 virtua(~3kB)
2026-07-23 00:21:49 +08:00
d891ccf08f docs: 代码修改约定改为根治优先原则 2026-07-22 22:38:15 +08:00
f953127613 fix(frontend): 修复引导/压缩等运行期注入消息场景下刷新导致运行记录重复显示
刷新恢复运行中任务时,重建判据只看最后一条消息:当运行区间中夹着
运行期注入的 user 消息(运行中引导/通知、多智能体内联消息、压缩续接
引导语)时,引导前的静态 assistant 段未被清空,而事件重放从 0 重建
整个任务内容,导致同一段运行记录显示两遍。

修复:重建前先界定本次运行区间(越过 assistant 与运行期注入 user 消
息,直到任务发起消息),复用区间内第一条 assistant 作为重放容器并
移除区间其余部分(注入消息与后续分段由事件流按原序重建),同时绑定
currentMessageIndex 使容器复用真正生效。
2026-07-22 22:20:25 +08:00
eb037ccb7c fix(quickdock): 修复快捷窗口 live 链路、raw 对象响应式与刷新误播动画 2026-07-22 19:33:34 +08:00
165bcdb264 feat(quickdock): 文件预览接入 Prism 语法高亮,修复深色模式运算符底色与 show_file 高亮失效 2026-07-22 19:33:21 +08:00
26f31a09ec fix(versioning): 修复 shallow 快照日志重复行导致的 diff 配对错误
根因:state.jsonl 采用只追加日志,track_edit 的中间半成品快照与
make_snapshot 的完整快照各自成行;加载时每行都被回放为独立快照,
_find_snapshot_pair 简单取下标-1 作为上一快照,导致 diff 基准落在
同一条消息自己的半成品行上——半成品中缺失的已跟踪文件被全部判为
added 并按全文件计新增(如 +1928 -0)。

彻底修复(非补丁):
- 持久化改为原子全量重写(temp + os.replace),结构性保证磁盘上
  一条 message_id 永远只有一行
- _load_state 幂等重载并在加载时折叠历史重复行(保留每消息最后一行),
  旧脏数据无需迁移即可透明愈合
- track_edit / make_snapshot 在按 state 文件加锁的临界区内执行
  重载->变更->保存,避免短生命周期实例间丢行
- _find_snapshot_pair 防御性跳过同 message_id 行
- 新增 6 个回归测试(test/test_shallow_versioning.py)

验证:新测试 6/6 通过;test_server_refactor_smoke 6/6 通过;
用 conv_20260721_175016_796 真实数据只读复算,seq8 由 +1295/-0
修正为 +796/-7(3 文件),seq10 由 +1928/-0 修正为 +592/-3(4 文件),
seq31 与历史正确记录 +482/-1 完全一致。
2026-07-22 15:48:11 +08:00
5cb18ab987 feat(quickdock): 计数器只显示总数、输出内容加浅底色块、修复点击展开详情误选文字 2026-07-22 15:03:19 +08:00
b0fdd47ad9 chore: 取消追踪 .astrion/memory 本地记忆文件 2026-07-22 14:10:31 +08:00
3ea8d9ad00 fix(frontend): 修复推理滑块动画卡顿、快捷窗口待办跨对话串数据、输入框高度回退
- EffortSlider: 圆钮/填充改走 transform + clip-path 合成器属性,rAF 直写 DOM 绕过 Vue 响应式,消除每帧重渲染与 reflow
- useLegacySocket: todo_updated 全局广播按 conversation_id 过滤,不再串入子智能体待办;移除用事件 conv id 覆盖当前对话 id 的危险逻辑
- watchers: 修复 currentConversationId 重复键互相覆盖导致清空逻辑从未注册的问题,合并为单个 watcher(/new 页面不再残留待办)
- InputComposer: 输入框最大高度 6 行 -> 10 行
2026-07-22 11:19:09 +08:00
77a271fa23 fix(multi-agent): MultiAgentState 全局单例,根治 terminate 后状态分裂复活
- MultiAgentState 从 manager 实例属性改为进程级全局注册表 GLOBAL_MULTI_AGENT_STATES
  (多 manager 并存时各 from_snapshot 出独立副本,terminate 只标记一份,轮询落到陈旧副本显示空闲)
- _load_state 恢复后用任务记录校准实例终态(磁盘快照可能被陈旧副本洗回 idle)
- 显示名后缀固定用角色内编号(role_seq 每次创建必递增),与内部 agent_id 命名空间分离;
  存量 _None 后缀按对话×角色×创建时间自愈迁移
- tools_execution 同步含 edited_files 工具埋点(write/edit/delete/rename)
2026-07-22 00:53:05 +08:00
171833e4d1 feat(quickdock): 新增对话区右侧快捷窗口(待办/子智能体/后台指令/文件记录)
- 四窗口固定顺序占位布局,空时收起到 0 宽;动画区分「运行中新出现」与「切换/加载」
- 文件记录:edit/write 埋点写入对话 metadata.edited_files,预览走既有 /api/file/content
- 详情面板:lastDetail/lastStatus 快照、首次填充静态+瞬间到底、终态四色分类
- 数据通道全部走 REST 轮询(带 conversation_id 对话级隔离),含 demo 与设计文档
2026-07-22 00:52:36 +08:00
1901aeb82f feat(personalization): 新增隐藏工具审核面板选项
- 个人空间「工具」页新增开关,默认开启
- 自动审核模式下开启时,后台审核工具不再自动展开审核面板
  (实时审批事件与待审批轮询两处自动展开均拦截,含移动端 overlay)
- 手动批准模式不受影响,面板照常弹出等待人工操作
2026-07-21 17:13:19 +08:00
9618148ed3 refactor(execution): 移除执行环境 TTL 自动回退机制
- 后端:移除 host_execution_direct_until、_refresh_execution_mode_by_ttl
  及 HOST_EXECUTION_DIRECT_TTL_SECONDS 配置,切换执行环境后一直生效
- 前端:移除到期定时同步、回退检测、自动回退 toast 及权限自动降级逻辑
- 文档:AGENTS.md 与 host_sandbox_and_permission_model.md 同步更新
2026-07-21 17:12:57 +08:00
5969d04c99 feat(input): 精简输入栏版本控制与权限显示
- 版本控制按钮只显示「版本控制」,不再显示开/关状态
- 权限按钮去掉「权限:」前缀,右侧新增执行环境标签
  (沙箱=次要色 / 完全访问=警示黄),仅在宿主机模式显示
2026-07-21 17:11:58 +08:00
794742e981 fix(static): 子智能体停止请求携带 conversation_id,修复误报无权限
terminateSubAgent/stopAllAgents 此前不带 conversation_id,with_terminal
落到工作区级服务 terminal,其 current_conversation_id 是最近加载的对话,
与目标任务所属对话不一致时后端返回 403「无权限停止该子智能体任务」。
补上后会请求命中对话级 terminal,权限校验通过,且终结操作直接作用于
持有活实例的 manager(优先直接 cancel,不再依赖 control.json 兜底)。
2026-07-21 16:16:41 +08:00
a1a9a47446 fix(multi-agent): 终结子智能体改为吸收态,修复终结后复活/停止无效
terminate_sub_agent 彻底化:
- 通过 _sub_agent_instances 找到活实例直接 cancel 其 _task(原实现只查
  _running_tasks,多 manager 并存时拿不到句柄导致 cancel 未送达)
- 实例置 _cancelled 并从注册表移除,防止 inject 找到活实例直接复活
- MultiAgentState 同步标记 terminated(原实现不写,侧边栏一直显示 idle)
- output.json 改写为 terminated 终态快照(原实现保留陈旧 idle 快照,
  会被 _check_task_status 读回复活任务记录)
- 新增 control.json 跨 manager 击杀/软停止信号通道,子智能体运行循环
  每个 idle tick / 每轮开始自行消费

注入/复活路径拒绝终结者:
- inject_message_to_sub_agent 检查最新任务记录,terminated 拒绝注入并
  清理孤儿实例;_revive_sub_agent 排除 terminated 记录
- send_message_to_sub_agent 工具返回明确的'已被终结'错误
- stop_sub_agent / soft_stop_all_agents 跳过 terminated,本地无实例时
  经 control.json 让对端 manager 上的实例自行软停止

terminated 吸收态防护:
- _check_task_status/_handle_running_snapshot 不再用陈旧快照覆盖终结记录
- output.json 为 terminated 时同步本地记录(跨 manager 终结广播)
- reconcile_task_states 的 idle/running 修正跳过终态任务
- MultiAgentState.mark_status 禁止 terminated 被覆盖回 idle/running
- 硬取消路径 output.json 写 terminated 而非 failed,避免 failed 被复活
2026-07-21 15:46:24 +08:00
265f71e297 fix(static): 修复运行期加载对话进度块周期性重复显示
对账循环把 pending/cancel_requested 的活任务误判为「缺轮询」(服务端活跃
集合含 pending/cancel_requested,而 hasActiveTask 只认 running),每 2.5s
触发一次「清去重 + 偏移归零」的全量事件重放;思考/文本/tool_preparing 块
创建无幂等,每轮重放整份追加,十几份后页面卡死。

A: 对账 resume 增加 alreadyTrackingMain 判定(同任务且轮询在跑则不介入,
   仅幂等对齐 taskInProgress 标志位)
B: resumeTask 收编 resetOffset——同任务且轮询在跑时拒绝归零事件偏移,
   仅冷启动恢复(不同任务或轮询已停)允许归零
D: startThinkingAction/startTextAction/handleToolPreparing 幂等创建,
   已有流式块/同 id 块时复用而非新建,作为去重集合被清后的最后防线
2026-07-21 14:39:42 +08:00
c9c3eedd82 feat: 移除实验性间隔思考模式,推理强度前置到前端
- 彻底移除「每 N 次请求强制思考」的间隔调度机制(思考/非思考交替导致缓存命中率极低)
- 运行模式收敛为 fast/thinking:原 deep 改名 thinking,历史数据读取时映射
- 新增推理强度五档滑块(low/medium/high/xhigh/max + 默认不传参),置于模型/模式弹窗
- 模型配置新增 reasoning_effort 开关;档位会话级持久化到对话 meta,随对话保存/恢复
- 个人空间新增「默认推理强度」;新用户默认运行模式改为 thinking
- 滑块交互:JS 插值驱动(点击/拖动/吸附全程平滑),首帧档位语义定位无闪烁
- 保存链路:前端防抖 600ms + conversation_id 兜底,修复 /new 发消息丢档位、切对话恢复错误
2026-07-21 13:47:53 +08:00
496bbe4f97 docs: 计划文档加注方向C后语义演进与bootstrap只读边界 2026-07-20 23:50:20 +08:00
01a1658a99 feat(server): 对话保存改为按 message_id 合并写(方向C merge-on-save)
save_conversation 全量覆写改为合并写:快路径前缀追加与现状一致;
慢路径以磁盘为基、同 id 取内存版、内存独有追加在后——旧实例任何
时机的写回都不再丢消息,回退从根免疫。豁免路径(allow_shrink,
仅检查点恢复)保持覆写语义。A 守卫降级为 merged 断言,缩减写回
从拒绝进化为矫正(旧实例独有消息也能救回)。慢路径矫正时打印
🔀 [ConvSaveMerge] 观察日志。详见计划文档 §7。
2026-07-20 23:16:04 +08:00
858ff45187 feat(static): 进入对话统一走 bootstrap 协议(方案B)
新增 enterConversation 单一入口:一次 GET bootstrap 拿全量数据,
restoreTaskState 增加快速路径(注入 task/events 跳过三次串行请求与
4s 死等,消除运行中刷新的两段式体验);needsRebuild 仍前端重算保证
恢复行为与现状等价。PUT load 保留后端兼容、前端不再调用。
2026-07-20 22:31:01 +08:00
21f3acdf16 feat(server): 新增对话 bootstrap 聚合接口(方案B)
GET /api/conversations/<id>/bootstrap 一次性返回进入对话所需的
meta/messages/running/task_replay(needs_rebuild/replay_from 判定移植自
前端 compression.ts),只读语义不写对话文件,规避 safe_nav 双轨与旧内存
回写面。设计文档:docs/conversation_load_unification_plan.md
2026-07-20 22:30:43 +08:00
17c48474d9 docs: 对话加载统一化计划(A防回写+B统一加载协议),屏蔽子智能体交付目录 2026-07-20 21:24:00 +08:00
a9fe6ae622 fix(server): 对话保存防回退守卫与load同对话跳过切换前保存
crud_mixin.save_conversation 新增 allow_shrink 参数与守卫:消息数缩减且未
豁免时拒绝写入,堵住工作区级/对话级双实例旧内存回写(当日三次实锤:
load切换前保存542→506、新建前保存104→77、__del__析构103→77)。
检查点恢复作为唯一合法缩减路径显式豁免。load_conversation_by_id 加载
目标==当前对话时跳过切换前保存(接下来以磁盘为准重载)。debug trace
增加 shrink_suspect 字段覆盖旧非空回写场景。
2026-07-20 21:23:29 +08:00
ccdc101192 chore(terminal): 删除无调用的 _derive_pip_from_python 死代码 2026-07-20 15:53:16 +08:00
cb877b4b67 fix(static): 对话级并行后调整输入栏锁定与发送守卫
- displayLockEngaged 不再因当前对话有运行中任务而硬锁输入栏,仅压缩期间锁定;
- 同对话运行守卫后移到 composerBusy 分支之后,避免刷新后对账未恢复时误发新任务。
2026-07-20 15:51:21 +08:00
bfc039a9a9 fix(terminal): 移除命令执行前的 python/pip 路径重写,按用户原始命令执行
run_command 与后台 run_command 此前会把命令中的 python/python3/pip/pip3 正则替换为解析出的容器或本地解释器路径,删除该重写逻辑后命令按原样执行。
2026-07-20 15:51:21 +08:00
0dd51c7b48 chore(debug): 新增对话保存写入追踪日志,捕获空覆盖调用栈
临时调试代码:每次保存对话时记录 old/new 消息数与项目内调用栈到
logs/conversation_save_debug.log(JSONL),wipe_suspect 时额外打印告警。
用于排查对话消息被清空问题,确认修复后应移除。
2026-07-20 15:16:45 +08:00
766080c05c chore(gitignore): 屏蔽 .playwright-mcp 调试快照目录 2026-07-20 15:15:58 +08:00
bd06f96d07 fix(server,static): 修复执行环境/权限模式切换对当前对话不生效
对话级 terminal 隔离后,模式切换请求未携带 conversation_id,
落在工作区级服务 terminal 上;而任务实际运行在对话级 terminal,
且 load_conversation 每次都会从对话 metadata 恢复创建时冻结的模式,
导致旧对话模式永远无法改变、新对话继承服务 terminal 的瞬时模式。

- 前端 permission.ts:权限/执行环境/网络权限的 POST 与 GET
  均携带当前 conversation_id,路由到对话级 terminal 并持久化到正确对话
- 后端 permission.py:切换时同步工作区级服务 terminal 的内存态
  (persist=False),保证新建对话继承最新模式而非过期模式
- 附带修复:运行期间切换的 pending 队列此前排在错误的 terminal 上,
  任务工具循环永远消费不到
2026-07-20 14:25:49 +08:00
8628954f30 fix(server): 修复对话消息被空历史覆盖——WebTerminal.__del__与回收器保存增加非空守卫
对话级 terminal 隔离后,被丢弃的实例(竞态重复、回收重建、TTL回收)
常处于 current_conversation_id 已设但 conversation_history 为空的状态,
GC 触发 __del__ 时无条件 save_current_conversation 把磁盘非空对话覆盖为空。
两处保存路径均增加 conversation_history 非空守卫。
2026-07-20 13:26:18 +08:00