Commit Graph
399 Commits
Author SHA1 Message Date
吉鑫升andClaude Opus 4.7 e0c1cb6581 feat: 定时任务管理 + 会话只读分享
定时任务:
- 管理员可查看/编辑/删除/触发全部用户的定时任务(新增 /api/scheduled-tasks/admin/* 接口与管理页)
- 卡死任务恢复:单次执行超 30 分钟超时重试(最多 3 次),耗尽后标记 failed;看门狗回收服务重启遗留的「执行中」任务

会话分享:
- 新增「只读链接」分享模式,生成公开免登录的只读对话快照页(/share/:code)
- 公开接口 /api/public/shares/* 提供对话快照与图片附件

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 15:39:40 +08:00
xuhd 8f88427d4e Merge branch 'master' of http://192.168.0.200/knowledge-base-bj/deerflow-server into xuhd 2026-05-18 10:25:51 +08:00
吉鑫升 4761677676 Merge remote-tracking branch 'origin/master' into ji 2026-05-18 10:03:49 +08:00
吉鑫升andClaude Opus 4.7 f61d053010 feat(skills): 新增技能详情字段并统一发布图标
- 技能新增 detail 字段(skills 表新增列 + Alembic 迁移),
  由管理员或技能发布者编辑,内置/公开技能仅管理员可编辑
- 新增 PUT /api/skills/{name}/detail 接口,GET/列表接口返回 detail
- 新增可复用的技能详情弹窗组件,支持 Markdown 渲染与内联编辑
- 智能体创建/编辑选技能、智能体卡片技能徽章均可查看技能详情
- 将定时任务/智能体/技能的发布图标统一为 Globe/Lock

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 10:03:37 +08:00
董宏凯 0af8ca5f78 历史记录回显 2026-05-17 22:55:01 +08:00
董宏凯 c19417a706 暂停继续 2026-05-17 21:19:12 +08:00
董宏凯 05ff10df1b ai改写调用 2026-05-17 20:18:11 +08:00
董宏凯 a0a6227368 文章类型添加 2026-05-17 19:50:52 +08:00
董宏凯 918e65d8d3 ai写作 2026-05-17 19:29:10 +08:00
董宏凯 10d7190ea4 ai写作 2026-05-17 14:22:25 +08:00
董宏凯 cc8703577d ai写作 2026-05-17 13:08:45 +08:00
董宏凯 4533755704 Merge branch 'master' of http://192.168.0.200/knowledge-base-bj/deerflow-server into dhk-1 2026-05-16 22:03:41 +08:00
董宏凯 da4a08dfe1 智能选中文字 2026-05-16 22:00:34 +08:00
xuhd 48ddbf0412 Merge branch 'master' of http://192.168.0.200/knowledge-base-bj/deerflow-server into xuhd 2026-05-16 15:51:49 +08:00
xuhdandClaude Opus 4.7 39def1c20b feat(skills): curator 健壮性加固 + 评审模型可配置 + 手动触发体验
调度健壮性:
- 技能进化总开关 skill_evolution.enabled 真正生效;CuratorConfig
  与 CuratorSubConfig 默认 enabled 改为 false(显式 opt-in)
- 新增 per-user 运行锁(.curator_state 的 running/started_at),
  防定时器与手动触发并发重复运行;6h stale 检测防进程残留死锁
- maybe_run_curator 改用 ThreadPoolExecutor 限并发(上限 5),
  防首次部署所有用户同时到期的惊群
- 首次运行持续失败时按 6h 退避重试,不再每个 tick 烧 LLM 配额
- should_run_now 时间解析容忍 naive 时间串;损坏的 last_run_at
  触发重跑而非永久死锁
- SkillStore 新增 list_published_names 批量接口,curator 一轮
  只查一次 published,取代逐技能查库

LLM 评审超时:
- _run_llm_review 给 agent.invoke 套整体超时
  (curator.review_timeout_seconds,默认 600s),超时中止本次评审
  并在 curator 日志输出,curator 正常收尾、释放运行锁
- copy_context 把 user 上下文传入工作线程

模型可配置:
- 新增 curator.model_name;curator 评审与技能安全审核共用该模型,
  未配置则回退主模型
- 移除独立的 moderation_model_name 配置
- 前端进化面板新增模型下拉选择器

手动触发体验:
- /api/curator/run 派发后台线程前先预检,返回 {triggered, reason},
  不再无论开关状态都提示"已开始"
- 前端:总开关/curator 开关未开时禁用"立即执行"按钮,
  被预检拦下时按原因(开关未开 / 已有任务在跑)给出准确提示

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 15:50:15 +08:00
董宏凯 e8a31b5d37 代码修改 2026-05-16 14:24:44 +08:00
董宏凯 e08e7be24c Merge branch 'master' of http://192.168.0.200/knowledge-base-bj/deerflow-server into dhk-1 2026-05-15 23:27:48 +08:00
董宏凯 1be600155b openCanvas 2026-05-15 23:27:34 +08:00
xuhdandClaude Opus 4.7 d592e1e535 fix(skills): curator 自我进化周期调度 + 并发/配置/安全修复
调度:
- app.py 新增常驻 curator 调度器,每小时检查一次"需不需要进化",
  替代原来"仅启动跑一次";多 worker 下用跨平台文件锁做 leader 选举,
  只有一个进程跑调度;启动延迟 5 分钟避开启动高峰

curator 逻辑修复:
- C1: should_run_now / apply_automatic_transitions / get_curator_status
  调用 _get_curator_config 时传 user_id,使 per-user 配置在运行时生效
- C3: usage.py 的 .usage.json 读-改-写加进程内锁,bump_* 改回调式,
  避免 curator 多线程并发丢状态更新
- C4a: curator 受限版 skill_manage 在工具层屏蔽 delete,
  堵住绕过 skill_archive 安全网删技能的口子
- C4b: 进化记录同时保存 LLM 自述(suggestions)与真实工具调用(actual_actions)
- 无候选技能时跳过 LLM 评审,省掉无意义的模型调用

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 19:31:05 +08:00
吉鑫升 33161c5bad Merge remote-tracking branch 'origin/likun' into ji
# Conflicts:
#	frontend-web/src/components/workspace/artifacts/artifact-file-detail.tsx
#	frontend-web/src/components/workspace/code-editor.tsx
#	frontend-web/src/components/workspace/input-box.tsx
#	frontend-web/src/pages/ChatPage.tsx
#	offline-backend-20260512/backend/app/gateway/routers/artifacts.py
2026-05-15 16:54:10 +08:00
吉鑫升 afc517b3a7 Merge remote-tracking branch 'origin/master' into ji
# Conflicts:
#	frontend-web/src/components/workspace/agents/agent-gallery.tsx
#	frontend-web/src/components/workspace/settings/skill-settings-page.tsx
2026-05-15 16:27:56 +08:00
likun de9f6b6711 feat: 新增写作画布系统 2026-05-15 16:22:04 +08:00
吉鑫升andClaude Opus 4.7 646cb8caeb feat: 标签管理功能 + 问答前缀对用户隐藏
标签管理:
- 新增 tags/tag_assignments 持久化层、迁移、/api/tags 路由
- 标签分智能体/技能/定时任务三类, 仅同类型可互打, 仅 admin 可增删改与打标签
- 三类资源列表支持按名称模糊检索与按标签筛选(走后端查询参数)
- 前端新增标签管理页、TagPickerDialog(点击即时绑定)、彩色标签 chip

问答前缀:
- 前缀不再拼入消息 content, 改存 additional_kwargs 由 PromptPrefixMiddleware
  在调模型前临时注入, 用户界面看不到前缀但模型仍收到
- 修正 thread_existed 闸门导致首轮前缀被跳过的问题

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 16:19:08 +08:00
xuhd 1574d44cc3 Merge branch 'master' of http://192.168.0.200/knowledge-base-bj/deerflow-server into xuhd 2026-05-15 15:26:16 +08:00
xuhdandClaude Opus 4.7 6981fc06ca feat(skills): 点击技能展示 SKILL.md 详情弹窗
- 后端新增 GET /api/skills/{name}/content 接口,返回公共/自定义技能的 SKILL.md 原文
- 前端技能行内容区可点击,弹窗以等宽原文展示 SKILL.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 15:23:34 +08:00
xuhdandClaude Opus 4.7 21a76f5e7c refactor(memory): Memory V2 P3 - 舍弃后台抽取 + Gateway 端点收口
P3 在 P1/P2 基础上完成 Memory V2 收尾:

舍弃后台抽取:
- 删除 updater/queue/storage/prompt/summarization_hook 五个模块
- 移除 background_extraction 配置段、扁平字段兼容、storage 字段
- 理由:Hindsight auto_retain 已自动留存每轮对话,后台抽取冗余

Hindsight 召回注入改用 wrap_model_call:
- 由 before_model 改为 wrap_model_call —— 召回只注入单次模型请求、
  不落持久 state,从根上消除 <memory-context> 泄漏给前端的风险
- builtin frozen snapshot 仍走系统提示词

Gateway 端点收口为 /api/memory/v2*:
- 删除旧 facts/history 端点 (/api/memory、/memory/facts 等)
- 新增 entries 增删改 (POST/PUT/DELETE /memory/v2/entries)
- 新增 POST /memory/v2/search —— Hindsight recall/reflect 检索代理
- client.py memory 方法重写为 V2 等价方法

文档同步更新 CLAUDE.md 与 MEMORY_V2_DESIGN_ZH.md。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 13:08:18 +08:00
xuhdandClaude Opus 4.7 f9d7610679 feat(memory): Memory V2 重写 - 可插拔 provider + Hindsight 集成
以 Hermes 的可插拔记忆架构为骨架重写 deerflow 记忆模块,兼容原有
结构化数据,并新增 Hindsight 作为外部记忆后端。

P1 - 抽象层 + builtin 本地记忆:
- MemoryProvider 抽象基类 + MemoryManager 编排层(builtin + ≤1 外部)
- BuiltinFileProvider:USER.md/MEMORY.md 二元存储、字符配额、文件锁、
  原子写、frozen snapshot
- memory 工具(LangChain @tool):LLM 主动写入用户画像/工作笔记
- 记忆内容安全扫描(注入/外渗模式 + 不可见 unicode)
- memory_config 改为嵌套结构 + 旧扁平字段兼容 + per-user 三层覆盖
- 迁移脚本 migrate_memory_to_v2.py:旧 memory.json -> USER.md/MEMORY.md
- Gateway 新增 /api/memory/v2 与 v2/config 端点(用户可配置白名单字段)

P2 - Hindsight 外部 provider:
- HindsightProvider:双 bank 隔离(user bank 跨 agent 共享 + work bank
  agent 私有)、并发召回合并、auto-retain、on_memory_write 镜像
- hindsight_recall/reflect/retain 三个 LangChain 工具
- MemoryMiddleware.before_model 注入 Hindsight 动态召回
- context/tools/hybrid 三种 memory_mode
- hindsight-client 作为可选依赖,未装时自动退回纯 builtin

注入走系统提示词(builtin frozen snapshot)+ before_model(Hindsight
动态召回)。后台抽取保留但默认关闭,P3 期重接入。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 12:15:55 +08:00
吉鑫升 aeba15eb16 Merge branch 'master' of http://192.168.0.200/knowledge-base-bj/deerflow-server into ji
# Conflicts:
#	frontend-web/src/pages/WorkspaceRoutes.tsx
#	offline-backend-20260512/backend/packages/harness/deerflow/persistence/models/__init__.py
2026-05-15 11:21:48 +08:00
xuhdandClaude Opus 4.7 62d525dae7 feat(skills): 自我进化 - 软归档/恢复 + Agent 归属 + 状态分层 UI
后端:
- 新增 PUT /api/skills/custom/{name}/state 与 /pinned 软归档/恢复 + 钉选 API
- skill_manage 工具: agent 创建写 DB 归属; 删除清理 .usage.json + DB row + cascade 引用; 加 ownership 预校验
- curator 全部软归档(文件保留在 custom/), 加 reason 必填(中文), 修 user_context 跨线程传播 / 协程泄漏 / archive 文件不再移动
- LLM 评审接 ToolErrorHandlingMiddleware, 工具异常自动重试不中止本轮; 替换 create_react_agent 为 create_agent
- skill_list 按当前 agent config.yaml 的 skills 字段过滤(custom agent), lead agent 仍可见全部
- 自我进化提示词对齐 Hermes 风格: 主动询问保存, reason 强制中文且面向用户
- 控制台日志增强: 自动归档/标过时/LLM 合并/删减建议 都按条目输出原因

前端:
- 技能管理页 Tab 改「全部 / 我的」, 正确包含他人发布的 custom 技能(修复 isCustom 互斥 bug)
- 新增「过时 N / 归档 N」右侧抽屉(恢复/查看/立即归档 ⋯ 菜单)
- 新增徽章: 钉选 / 来源(Agent 创建 / 用户上传) / 使用次数展示
- 内置技能徽章修复(原 isBuiltin && isCustom 永远 false)
- 自我进化日志 run_started sentinel 在前端展示为中文分隔条
- 移除冗余 enabled 开关(归档已覆盖此能力, 减少术语)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 00:00:52 +08:00
xuhd f8bc74b27f Merge branch 'master' of http://192.168.0.200/knowledge-base-bj/deerflow-server into xuhd 2026-05-14 23:45:10 +08:00
董宏凯 044370f13c 沙箱内容可保存 2026-05-14 22:12:20 +08:00
xuhd 9a67ca7c03 Merge branch 'master' of http://192.168.0.200/knowledge-base-bj/deerflow-server into xuhd 2026-05-14 20:45:02 +08:00
xuhdandClaude Sonnet 4.6 40cd8a24af feat: admin skill public upload + user management page
- Admin users can choose to install skills to public (built-in) or custom category via UI radio selector in InstallSkillDialog
- Backend: SkillStorage.ainstall_skill_from_archive accepts target_category param; non-admin 403 on public install
- Backend: AgentStore/SkillStore add count_owned(user_id); UserRepository/LocalAuthProvider add list_users()
- Backend: GET /api/v1/auth/users endpoint (admin-only) returns all users with skill_count and agent_count
- Frontend: admin-only "用户管理" nav item in sidebar; /page/workspace/admin/users route with user table
- i18n: added sidebar.users and adminUsers section in zh-CN/en-US

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 20:40:23 +08:00
吉鑫升 3ea33e1dee 大模型速度增加提示 2026-05-14 19:12:14 +08:00
xuhdandClaude Opus 4.7 4ef96c7930 feat(skills): 多租户阶段 3 — Curator + 配置 per-user
curator_log.py
- ring buffer 从单一 deque 改为 dict[user_id -> deque],每个用户
  自己的运行日志互不可见
- start_new_run / record / get_recent / clear 全部接 user_id
  关键字参数;未传时落入 __default__ 桶兼容旧调用
- 新增 clear_all() 用于跨用户清理(仅测试用)

curator.py
- 状态文件路径从 skills/.curator_state 改为
  .deer-flow/users/{user_id}/.curator_state(per-user 隔离)
- 所有公开 API 接受 user_id 参数:should_run_now /
  apply_automatic_transitions / _render_candidate_list /
  run_curator_review / _curator_thread_target /
  get_curator_status / _make_skill_archive_tool / _run_llm_review
- 新增 _list_user_owned_skill_names(user_id):通过 SkillStore
  查询当前用户拥有的 skill 名集合,用于过滤 transitions / LLM
  candidates,保证 user A 跑 curator 不会动 user B 的 skill;
  SkillStore 不可达时退化为"全部 agent-created skill"(兼容旧部署)
- _get_curator_config(user_id) 通过 load_skill_evolution_config_for_user
  叠加 per-user override,让阈值/间隔/moderation_model 也是 per-user
- maybe_run_curator 启动时枚举 UserRow,按用户检查 should_run_now
  并各起一个 daemon 线程跑

skill_evolution_runtime.py
- 全局 backend/skill_evolution.json 语义保留作为 fallback
- 新增 per-user API:resolve_user_path / load_user_overrides /
  save_user_overrides / get_user_overrides_mtime,文件落到
  .deer-flow/users/{user_id}/skill_evolution.json
- 新增 load_skill_evolution_config_for_user(user_id):读全局
  SkillEvolutionConfig 作为 baseline,浅合并 per-user JSON,
  返回 Pydantic 实例。验证失败时回落到 baseline

routers/skills.py
- /api/curator/status / run / config GET+PUT / logs 全部接
  _current_user_id 注入运行上下文
- update_curator_config 改为 per-user:保存到
  users/{user_id}/skill_evolution.json,不再 reset_app_config
- _build_curator_config_response 接受 SkillEvolutionConfig 实例
  (而不是 AppConfig)以适配 per-user 合并结果

旧 19 个测试继续通过;未引入新依赖。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 17:09:05 +08:00
xuhdandClaude Opus 4.7 cf191ef874 feat(skills/notifications): 多租户阶段 2 — 路由 + 级联 + 启动迁移
后端工作:

deps.py
- 挂载 skill_store / notification_store 到 app.state
- 启动时 set_notification_store(...) 注入到 harness sender;
  关闭时清空,保证测试和 embedded 模式不留状态
- 加 get_skill_store / get_notification_store FastAPI 依赖

routers/skills.py
- 加 _current_user_id / _is_admin_user / _get_owned_skill_or_raise /
  _get_editable_skill_or_raise(对齐 routers/agents.py)
- SkillResponse 加 owner_user_id / published / builtin 字段,
  _skill_to_response 接受 SkillStore 记录映射
- GET /api/skills 与 GET /api/skills/custom 改 per-user 可见性过滤
- POST /api/skills/install + /install-upload 预解析 archive 名校验
  全局 name 不被他人持有;安装后 ensure_legacy 注册 owner=current
- DELETE /api/skills/custom/{name} 走 _get_editable_skill_or_raise,
  调 cascade(owner 自删 = delete,admin 跨用户 = admin_takedown),
  SkillStore.delete / delete_admin 同步清除 DB 记录
- 新增 PUT /api/skills/custom/{name}/published 切换发布状态;
  从 published → unpublished 时触发 cascade(unpublish / admin_takedown)

skills/cascade.py(新)
- 扫所有 .deer-flow/agents/{id}/config.yaml,把指定 skill 从其 skills
  数组移除,并通过 deerflow.persistence.notifications.notify 给受
  影响 agent 的 owner 发站内信;admin 强制下架时另给 skill owner 发
  一条
- 操作类型:unpublish / delete / admin_takedown,对应不同文案

routers/notifications.py(新)+ app.include_router
- GET /api/notifications(unread_only / limit)
- GET /api/notifications/unread_count(红点用)
- POST /api/notifications/{id}/read
- POST /api/notifications/read_all
- DELETE /api/notifications/{id}

app.py lifespan
- _sync_legacy_skills(app):每次启动扫 skills/custom/ 把没在 DB
  的 skill 落库为 admin owner + published=True,幂等、非阻塞失败
- 调用顺序:_ensure_admin_user → _sync_legacy_skills → 启动 curator

测试:19 个旧用例继续通过;阶段 4 会写 test_skills_multitenancy.py

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 16:24:42 +08:00
xuhdandClaude Opus 4.7 f5bc02d598 fix: skills 路由两个小修复
skills.py:
- update_curator_config 直接 await get_curator_config() 报错
  ('Depends' object has no attribute 'skill_evolution')。FastAPI 路由
  默认参数 Depends(...) 只在请求时被框架解析,直接调用拿到的是依赖标记。
  抽出 _build_curator_config_response(config) 让 GET 和 PUT 共用。

skill_manage_tool.py:
- 模型把 action='list' 当成可用动作误调 skill_manage 报
  Unsupported action。补两个 read-only 别名 list/view,分别委派到
  skill_list_tool 和 skill_view_tool,docstring 同步更新。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 15:43:26 +08:00
xuhdandClaude Opus 4.7 9b6b94d919 feat(skills): 自我进化后端 — curator 配置可编辑 + 运行日志可读
后端骨架:
- curator.py / usage.py / skill_tools.py:基于使用计数的生命周期管理
  + LLM 合并/归档建议(同事已有原型,集中提交)
- skill_evolution_config.py:CuratorConfig 嵌套模型
- app.py:启动时按间隔触发 curator 后台线程
- tools.py:开启自我进化时一并注册 skill_list / skill_view 工具
- skill_manage_tool.py:agent 创建技能时标记 source=agent

本次新增:
- skill_evolution_runtime.py:skill_evolution.json 读写,原子写入
- app_config.py:把 overrides 深合并到 AppConfig.skill_evolution,
  并把 overrides 的 mtime 纳入缓存失效条件,前端 PUT 后热生效
- curator_log.py:进程内 ring buffer (maxlen=200),所有 record/get
  操作内部兜异常,保证 logging 永远不会让 curator 跑挂
- curator.py 关键节点插桩:run_started / 自动转换计数 / 候选数 /
  LLM agent invoke / 解析结果 / archive 动作 / run complete
- routers/skills.py:GET/PUT /api/curator/config(写到
  skill_evolution.json + reset_app_config)+ GET /api/curator/logs

测试:
- tests/test_skill_evolution_runtime.py:overrides 往返、损坏 JSON
  容错、AppConfig 合并、ring buffer 线程安全、record 异常吞咽

杂项:
- .gitignore:忽略 .deer-flow/* 与 skills/* 等运行时目录
- uv.lock:跟随依赖锁更新
- 清理已废弃的 agent runtime 数据 SOUL.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:00:21 +08:00
fengxiangdebaozi 2f2ba44c7c 添加推荐问题修改接口 2026-05-14 11:07:28 +08:00
xuhdandClaude Opus 4.7 434cf40b36 fix: /login/admin 自动把历史 admin 账户升级为 admin 角色
历史上以 username=admin 自动注册的账户曾被建成 system_role=user,
登录时按 username 修正一次,避免老库需要手工改表。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 10:25:24 +08:00
xuhdandClaude Opus 4.7 43044232bb feat: admin可删除内置专家
复用 _get_editable_or_raise 分支,给 AgentStore 增加 delete_builtin,
路由按 edit_mode 决定走 delete 还是 delete_builtin;前端 agent-card
为 admin 显示内置 agent 的删除按钮。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 09:53:13 +08:00
xuhdandClaude Sonnet 4.6 2abdf28eba feat: admin可编辑内置专家 + agent列表Tab分组
- /login/admin 登录时自动赋予 admin 角色,允许编辑内置专家
- agent列表页新增「全部」(内置+已发布) 和「自己的」两个Tab

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 23:16:18 +08:00
吉鑫升 31abad86d5 智能体配置 2026-05-13 20:04:06 +08:00
吉鑫升 a27206c543 Update local frontend and backend changes 2026-05-13 17:17:42 +08:00
吉鑫升 faca2c9a2d Merge branch 'likun' into master 2026-05-13 17:02:22 +08:00
吉鑫升 aa034f8669 定时任务订阅模式 2026-05-13 14:59:27 +08:00
likun b8926f00d7 新增用户意图确认功能 2026-05-13 14:36:44 +08:00
吉鑫升 cf2e4bdd9c 智能体分权 2026-05-13 11:36:17 +08:00
吉鑫升 e7a455f22e Initial commit: deerflow-server (frontend-web + offline-backend-20260512) 2026-05-13 09:36:15 +08:00