{
  "product": "vimox-hub",
  "version": "0.5.0",
  "limit": 50,
  "history": [
    {
      "id": "v0.5.0",
      "date": "2026-11-01",
      "title": "v0.5.0 · 平台能力升级与 TikTok 支持",
      "body": "- TikTok 使用独立账号 Profile 登录，支持关键词视频搜索、作品信息、评论与二级回复读取；签名在本地计算，请求复用登录态和账号代理。\n- TikTok 支持创作者作品监控、作品/近期作品评论监控、本账号作品和可见数据同步；主页读取采用登录账号浏览器并记录可诊断的协议状态。\n- TikTok 新增用户搜索、关注/取关、私信、评论和评论回复任务，写操作进入统一任务队列、风控检查和“结果待确认”状态，避免网络中断时重复发送。\n- TikTok 媒体下载携带账号 Cookie、UA、Referer 和代理，并保留本地媒体索引与来源信息。\n- 快手采集补齐新版搜索、可滚动容器分页、评论响应兼容和历史边界；小红书增加收藏夹读取；统一事件中心、群成员快照、操作记录和浏览器上下文回收。\n- 修复合并后的 `fallback_error` 未定义异常、评论弹窗 AbortController 缺失、Node 22 小红书签名器无法启动和取消浏览器启动时的上下文清理。\n- 保留四个平台既有作品下载路由：`app/engine/share_downloader.py`、抖音原生详情、快手/小红书账号下载与视频号 `xlf` 路由未被 TikTok 代码覆盖。"
    },
    {
      "id": "v0.4.1",
      "date": "2026-10-29",
      "title": "v0.4.1 · Chrome 下载协议缺失兼容修复",
      "body": "- 精确识别下载行为指令缺失，对版本探测和持久化账号 Context 采用浏览器默认下载策略；保留同一内核、Profile、代理与身份配置，兼容重试有明确上限。\n- 在临时版本探测阶段记录下载能力，避免后续账号反复初始化失败；驱动断连后继续使用已确认的兼容策略。\n- 只调整当前驱动实例和当前异步任务的下载参数，不修改第三方依赖文件；正常浏览器和小红书原生 CDP 路径保持原行为。\n- 将协议错误转为简短的版本、驱动和依赖排查提示，不再把 Chrome 版本过旧当作唯一原因；保留版本查看及升级入口。\n- 自动恢复后仍需手动处理的协议错误弹出修复指引，提供升级 Hub、依赖检测、浏览器环境及修复后重试步骤；可关闭、去重、主动重新打开，等待当前编辑弹窗关闭后展示，保留未保存输入。\n- 在 AGENTS.md 明确用户报错必须有恢复机制，至少提供可操作的修复弹窗；禁止无界重试、仅展示原始错误或误删账号数据。\n- 在 `docs/bug/2026-10-29-Chrome升级后下载协议缺失仍无法启动.md` 记录证据、平台路径差异、根因边界、修复和复现步骤；同步 README 和指南。"
    },
    {
      "id": "v0.4.0",
      "date": "2026-10-29",
      "title": "v0.4.0 · Chrome 版本查看、升级入口与兼容性提示",
      "body": "- 欢迎页显示 Vimox Hub 应用版本；环境检测详情显示系统 Chrome 完整版本和安装位置，覆盖用户目录与系统目录安装。\n- 欢迎页与平台账号「浏览器内核」均提供「检查更新 / 升级 Chrome」及重新检测。直接打开 Chrome 自带更新页，不依赖失败的自动化连接；未安装时打开官网指南。\n- 识别 `Browser.setDownloadBehavior` 等协议指令缺失，将完整启动日志转为明确的升级提示和操作入口；指纹 Chromium 与内置 Chromium 提示处理对应内核。\n- 浏览器探测完成上下文与页面验证后才记录可用渠道；协议不兼容时不静默将账号 Profile 切换到其他内核。\n- 同步 README、官网指南、更新日志及应用内记录。"
    },
    {
      "id": "v0.3.6",
      "date": "2026-10-25",
      "title": "v0.3.6 · 版本与发布日志维护规则",
      "body": "- `AGENTS.md` 要求代码、配置和文档更新均递增语义化版本，同步 `package.json` 与 `package-lock.json`，每个新版本新增 `docs/release/v<版本号>.md`。\n- 明确发布日志内容、历史保留、日志生成校验及同一提交内交付源码、版本与日志的要求。\n- 应用内日志生成支持按语义化版本倒序读取新版日志，继续兼容旧日期日志与既有历史起点配置；缺少当前版本日志、当前版本被排除或版本日志缺少日期时报错。\n- 本次版本从 0.3.5 升至 0.3.6，同步根目录更新日志与应用内日志。"
    },
    {
      "id": "2026-10-25-普通抖音链接原生下载",
      "date": "2026-10-25",
      "title": "普通抖音链接原生下载",
      "body": "## 变化\n\n- 恢复账号模式下普通抖音分享链接的浏览器原生详情与 CDN 下载，修复最近路由改动导致的 yt-dlp 回归。\n- 新增普通链接原生路由测试和回归原因记录。"
    },
    {
      "id": "2026-10-25-抖音详情读取临时标签修复",
      "date": "2026-10-25",
      "title": "抖音详情读取临时标签修复",
      "body": "## 变化\n\n- 当前页作品下载在账号浏览器已有 CDP context 中创建临时详情 tab，监听导航期间的详情接口响应，避免仅依赖已打开页面里可能缺失的 hydration 状态。\n- 详情读取结束后关闭临时 tab；原作品 tab 不导航、不关闭，继续承载下载进度显示。"
    },
    {
      "id": "2026-10-25-抖音详情等待延长至120秒",
      "date": "2026-10-25",
      "title": "抖音详情等待延长至 120 秒",
      "body": "## 变化\n\n- 抖音分享短链读取上限提高到 120 秒。\n- 抖音浏览器作品详情读取最低等待 120 秒，适配网络卡顿和页面延迟加载。\n- 当前页下载桥接确认等待提高到 20 秒，总请求等待提高到 20 分钟。"
    },
    {
      "id": "2026-10-25-抖音短链提取不依赖分享容器",
      "date": "2026-10-25",
      "title": "抖音短链提取不依赖分享容器",
      "body": "- 截图确认原生点击已执行，但后端因等待 `[data-e2e=\"video-share-container\"]` 可见而超时；用户验证可用的页面脚本实际等待二维码 `img[alt*=\"https://v.douyin.com/\"]`。\n- 改为直接等待并读取带抖音短链的二维码 `alt` 图片。`video-share-container` 只在存在时负责清理，不再作为分享面板打开成功的判断条件。\n- 无论接口还是二维码 `alt` 都未得到短链时，错误消息附带分享入口、容器和二维码图片数量，便于区分 DOM 变化。"
    },
    {
      "id": "2026-10-25-抖音点击提取修复与诊断日志",
      "date": "2026-10-25",
      "title": "抖音点击提取修复与诊断日志",
      "body": "- 将抖音分享入口触发改为在当前作品 tab 执行 DOM 原生 `element.click()`，与页面控制台验证成功的 `btn.click()` 保持一致；不再使用未能触发页面逻辑的 Patchright `locator.click()`。\n- 下载按钮在页面 DevTools Console 输出开始、桥接接收、结果和失败日志；服务端记录分享入口点击、短链来源及面板读取失败原因，不记录 Cookie。\n- 失败提示保留具体的点击/展开异常，方便区分页面入口定位、面板展开和后续下载问题。"
    },
    {
      "id": "2026-10-25-抖音推荐页当前作品下载",
      "date": "2026-10-25",
      "title": "抖音推荐页当前作品下载",
      "body": "## 变化\n\n- 抖音账号浏览器停留在 `/?recommend=1` 等推荐流页面时，不再因为 URL 不是具体作品地址而直接拒绝下载。\n- 只要当前页面存在分享入口，系统会点击入口读取二维码或接口短链，再复用原生详情与 CDN 下载链路。\n- 下载失败时保留浮层和错误信息，避免用户误以为客户端消失。"
    },
    {
      "id": "2026-10-25-抖音当前作品详情失败回退",
      "date": "2026-10-25",
      "title": "抖音当前作品详情失败回退",
      "body": "## 变化\n\n- 当前作品详情接口无响应或原生读取失败时，自动回退到 yt-dlp 通用分享链接下载。\n- 回退前同步当前 CDP 浏览器 Cookie，并沿用当前 tab User-Agent 与账号代理。\n- 记录 `yt_dlp_fallback` 路由及原生错误；普通分享链接保持原有下载路由。"
    },
    {
      "id": "2026-10-25-抖音当前作品直接使用分享链接下载",
      "date": "2026-10-25",
      "title": "抖音当前作品直接使用分享链接下载",
      "body": "## 变化\n\n- 账号浏览器“下载当前作品”已经在当前 tab 取得 `v.douyin.com` 短链后，直接将短链交给 yt-dlp，不再进入易超时的作品详情页解析。\n- 首轮按公开链接下载，不附加 CDP Cookie；首轮失败时再用最新 CDP Cookie 重试，兼容免登录和需登录作品。\n- 控制台分别记录 `yt_dlp_public_first` 与 `yt_dlp_cookie_retry`，准确标注 Cookie 是否实际挂载。"
    },
    {
      "id": "2026-10-25-抖音当前作品使用原生下载",
      "date": "2026-10-25",
      "title": "抖音当前作品使用原生下载",
      "body": "账号浏览器的“下载当前作品”取得分享短链后，统一下载入口现在优先调用抖音原生详情读取与 CDN 媒体下载，并继续写入链接下载历史。普通视频和图文不再强制送入 yt-dlp 的 TikTok Cookie 校验；音频转换等原生路线未覆盖的请求仍保留 yt-dlp 回退。原始 Cookie 诊断日志继续用于确实进入 yt-dlp 的情况。\n\n验证：\n\n- `.venv/Scripts/python.exe -m pytest tests/test_douyin_share_download.py::DouyinShareDownloadTests::test_account_browser_share_short_link_uses_native_douyin_route tests/test_douyin_share_download.py::DouyinShareDownloadTests::test_current_page_download_reuses_owned_browser_lock tests/test_douyin_share_download.py::DouyinShareDownloadTests::test_current_page_prefers_its_browser_session_over_api_mode -q --tb=short`：3 passed。\n- `.venv/Scripts/python.exe -m pytest tests/test_account_browser_download.py tests/test_douyin_share_download.py tests/test_share_downloader.py -q --tb=short`：69 passed、3 skipped。\n- `.venv/Scripts/python.exe -m compileall -q app/main.py tests/test_douyin_share_download.py` 与 `git diff --check`：通过。"
    },
    {
      "id": "2026-10-25-抖音原生下载与CDP浮层",
      "date": "2026-10-25",
      "title": "抖音原生下载与 CDP 浮层",
      "body": "## 变化\n\n- 抖音账号浏览器“下载当前作品”改用账号浏览器详情读取、`parse_aweme` 和项目原生 CDN 下载器，不再把当前页短链作为 yt-dlp 的正常路径。\n- 小红书和抖音下载历史的“打开原链接”统一通过绑定账号的 CDP 浏览器当前标签打开。\n- 当前页下载浮层增加可手动隐藏的关闭按钮；隐藏不会取消后台下载，下载成功或失败后自动收起并保留历史记录与重试入口。\n- 增加原生路线、XHS CDP 打开按钮和浮层行为的回归断言。"
    },
    {
      "id": "2026-10-25-抖音分享链接点击提取",
      "date": "2026-10-25",
      "title": "抖音分享链接点击提取",
      "body": "- 将分享入口从 hover 改为当前作品 tab 内点击，读取 `/aweme/v1/web/web_shorten/` 成功响应中的 `data.short_url`；接口没有可用短链时，从分享面板二维码图片 `alt` 兜底提取。\n- 短链读取完成或失败后移除 `[data-e2e=\"video-share-container\"]`，并解除 CDP response 监听，避免面板残留和监听器累积。\n- 短码正则只接受 `v.douyin.com` 的单段 `[A-Za-z0-9_-]+` 路径，支持可选尾斜杠；原 `[/\\w-]+` 写法允许多段斜杠且可能从非法后缀中截取部分链接，现加边界校验拒绝该情况。"
    },
    {
      "id": "2026-10-25-抖音分享短链延迟等待",
      "date": "2026-10-25",
      "title": "抖音分享短链延迟等待",
      "body": "抖音分享面板和二维码在卡顿设备上可能晚于原有 3 秒超时才加载。当前页点击分享后会持续轮询短链接口响应和二维码图片 `alt`，最长等待 60 秒；二维码出现时仍给接口响应 1.5 秒优先机会，超时错误会注明等待时长和页面诊断状态。\n\n验证：\n\n- `.venv/Scripts/python.exe -m pytest tests/test_account_browser_download.py tests/test_douyin_share_download.py tests/test_share_downloader.py -q --tb=short`：67 passed、3 skipped。\n- `$env:VIMOX_HUB_RUN_LOCAL_CDP='1'; .venv/Scripts/python.exe -m pytest tests/test_account_browser_download.py::AccountBrowserDownloadTests::test_douyin_jingxuan_modal_converts_to_share_link_in_same_tab -q --tb=short`：1 passed；Chromium fixture 延迟 3.5 秒插入二维码，验证超过旧 3 秒窗口仍可提取短链。\n- `.venv/Scripts/python.exe -m compileall -q app/main.py tests/test_account_browser_download.py` 与 `git diff --check`：通过。"
    },
    {
      "id": "2026-10-25-抖音临时标签二次重试",
      "date": "2026-10-25",
      "title": "抖音临时标签二次重试",
      "body": "## 变化\n\n- 修复详情读取内部仍限制 60 秒的问题，现在支持外层配置的 120 秒等待。\n- CDP 下载临时详情 tab 没有任何媒体响应时，自动关闭并新建第二个 tab 重试一次。\n- 日志明确记录 `retrying with a fresh tab`，用于区分链接错误和页面初始化竞态。"
    },
    {
      "id": "2026-10-25-抖音下载进度与历史占位",
      "date": "2026-10-25",
      "title": "抖音下载进度与历史占位",
      "body": "## 变化\n\n- 抖音当前作品下载提交后立即创建下载历史占位记录，解析作品信息后更新标题，下载结束后原位转成成功或失败记录。\n- 原生媒体下载每约半秒报告一次字节数、总大小和传输速度；账号浏览器浮层显示等待时间、百分比、MB/s，下载历史显示占位状态与进度摘要。\n- 下载历史“打开原链接”增加左右间距和点击热区，hover 改为柔和底色，不再用遮挡内容的提示气泡。"
    },
    {
      "id": "2026-10-25-抖音Cookie传递诊断日志",
      "date": "2026-10-25",
      "title": "抖音 Cookie 传递诊断日志",
      "body": "当前作品分享短链现在同时输出到 Python 服务控制台和当前 tab 的 DevTools。yt-dlp 启动前会记录临时 Netscape Cookie 文件实际写入数、是否包含登录类 Cookie 与 `s_v_web_id`、Cookie 文件是否传入 yt-dlp，以及 User-Agent 来源；日志不包含 Cookie 值。下载优先复用当前浏览器标签的 User-Agent。yt-dlp 的 `Fresh cookies (not necessarily logged in)` 提示调整为 Cookie 新鲜度/接口风控诊断，避免错误提示账号登录失效。\n\n验证：\n\n- `.venv/Scripts/python.exe -m pytest tests/test_account_browser_download.py tests/test_douyin_share_download.py tests/test_share_downloader.py -q --tb=short`：69 passed、3 skipped。\n- `$env:VIMOX_HUB_RUN_LOCAL_CDP='1'; .venv/Scripts/python.exe -m pytest tests/test_account_browser_download.py::AccountBrowserDownloadTests::test_douyin_jingxuan_modal_converts_to_share_link_in_same_tab -q --tb=short`：1 passed。\n- `.venv/Scripts/python.exe -m compileall -q app/main.py tests/test_account_browser_download.py tests/test_douyin_share_download.py tests/test_share_downloader.py` 与 `git diff --check`：通过。"
    },
    {
      "id": "2026-10-25-抖音CDP详情失败自动回退",
      "date": "2026-10-25",
      "title": "抖音 CDP 详情失败自动回退",
      "body": "## 变化\n\n- CDP 页面成功提取抖音短链后，如果临时详情标签没有返回作品 JSON，不再直接失败。\n- 自动复用通用链接下载器完成下载，行为与关闭 CDP 后手动粘贴链接一致。\n- 日志新增 `douyin_browser_link_fallback`，并保留 `native_error` 说明详情读取失败原因。"
    },
    {
      "id": "2026-10-25-抖音CDP会话关闭与详情诊断",
      "date": "2026-10-25",
      "title": "抖音 CDP 会话关闭与详情诊断",
      "body": "## 变化\n\n- 修复账号浏览器关闭竞态导致的 Patchright `Network.setCacheDisabled: session closed` 未捕获异常。\n- 增强抖音详情读取日志，区分当前标签与临时标签，并在无详情响应时自动刷新一次。"
    },
    {
      "id": "2026-10-25-快手详情新标签回退",
      "date": "2026-10-25",
      "title": "快手详情新标签回退",
      "body": "## 变化\n\n- 修复快手原生详情流程遗漏 `suppress` 导入导致的运行时错误。\n- 快手分享短链继续在当前 tab 提取，作品详情在账号浏览器 context 新开 tab 读取，完成后关闭。\n- GraphQL 详情读取失败时自动回退通用下载器，日志记录 `kuaishou_browser_link_fallback` 和原生失败原因。"
    },
    {
      "id": "2026-10-25-快手推荐页跳转作品",
      "date": "2026-10-25",
      "title": "快手推荐页跳转作品",
      "body": "## 变化\n\n- 快手推荐页点击转发时允许先发生页面路由跳转，不再在 `new-reco` 首页 URL 阶段提前误报。\n- 等待页面跳转到 `/short-video/{photoId}` 后继续读取分享面板二维码中的 `/f/` 短链。\n- 快手详情页链接继续直接解析作品 ID，推荐页没有有效作品分享短链时才报错。"
    },
    {
      "id": "2026-10-25-快手推荐页提交分享短链",
      "date": "2026-10-25",
      "title": "快手推荐页提交分享短链",
      "body": "## 变化\n\n- 快手推荐页点击下载时，前端先点击 `.forward` 并解析二维码中的 `/f/` 分享短链。\n- 后端不再收到 `https://www.kuaishou.com/new-reco` 作为下载 URL。\n- 控制台新增“本次下载请求链接”日志，便于确认实际提交的地址。"
    },
    {
      "id": "2026-10-25-快手分享链接与提示框",
      "date": "2026-10-25",
      "title": "快手分享链接与提示框",
      "body": "## 变化\n\n- 账号浏览器当前页下载浮层的状态提示支持手动关闭，并在成功后 10 秒自动关闭，下载按钮保持常驻。\n- 快手页面点击 `.forward` 转发入口后，从隐藏分享面板二维码 `src` 的 `content` 参数提取 `https://www.kuaishou.com/f/...` 分享短链。\n- 快手账号链接优先使用浏览器 GraphQL 详情和项目原生 CDN 下载，兼容 `short-video`、`/f/` 分享链接；普通无账号路径保持通用下载器。"
    },
    {
      "id": "2026-10-25-快手分享详情与浏览器driver恢复",
      "date": "2026-10-25",
      "title": "快手分享详情与浏览器 driver 恢复",
      "body": "## 变化\n\n- 快手 SSR 详情请求保留原始分享短链或完整落地 URL，跟随分享重定向并保留 `shareToken` 等查询参数。部分快手作品仅在该分享上下文中返回 Apollo 媒体信息；裸作品 ID 页面可能返回无详情的 HTTP 200。\n- 账号浏览器遇到 Patchright driver 管道断连时，清理失效连接并自动重新启动 driver，对原启动请求重试一次。\n- 增加快手分享上下文和 Patchright driver 断连识别的回归测试。"
    },
    {
      "id": "2026-10-25-修复抖音下载后页面跳转",
      "date": "2026-10-25",
      "title": "修复抖音下载后页面跳转",
      "body": "## 变化\n\n- 当前页下载先读取 `jingxuan?modal_id` 当前页面已加载的详情，尽量不触发导航。\n- 必须临时导航读取详情时，在下载读取结束后恢复用户原页面。"
    },
    {
      "id": "2026-10-25-修复快手推荐页短链流程",
      "date": "2026-10-25",
      "title": "修复快手推荐页短链流程",
      "body": "## 变化\n\n- 修复快手推荐页点击转发后已取得 `/f/` 短链，却因后处理调用错误函数名而失败的问题。\n- 统一使用 `ks_looks_like_photo` 判断快手作品页，并记录最终快手下载 URL。"
    },
    {
      "id": "2026-10-25-修复CDP下抖音通用链接下载",
      "date": "2026-10-25",
      "title": "修复 CDP 下抖音通用链接下载",
      "body": "## 变化\n\n- 普通抖音分享链接恢复通用 yt-dlp 下载；仅“当前页下载”入口使用原生详情读取，且不再因账号浏览器打开而强制切换下载路径或同步实时 Cookie。\n- 抖音当前页作品详情读取复用账号浏览器当前 tab，并保持该 tab 打开。\n- 当前页下载按钮在页面控制台输出当前作品 URL；下载浮层避开播放器控制区，历史“打开原链接”提示缩短。"
    },
    {
      "id": "2026-10-25-下载浮层自动收起",
      "date": "2026-10-25",
      "title": "下载浮层自动收起",
      "body": "## 变化\n\n- 移除下载浮层关闭叉号，避免误关闭后找不到“下载当前作品”入口。\n- 下载成功后显示 10 秒倒计时，倒计时结束自动隐藏浮层。\n- 下载失败时保留浮层和重试按钮，方便继续操作。"
    },
    {
      "id": "2026-10-25-下载提示独立关闭",
      "date": "2026-10-25",
      "title": "下载提示独立关闭",
      "body": "## 变化\n\n- 下载状态文字框新增右上角关闭按钮，仅关闭提示文字，不影响“下载当前作品”按钮。\n- 下载成功后 10 秒自动关闭状态文字框，下载按钮继续常驻。\n- 下载失败时状态文字框保留，支持查看错误并重试。"
    },
    {
      "id": "2026-10-25-下载按钮常驻",
      "date": "2026-10-25",
      "title": "下载按钮常驻",
      "body": "## 变化\n\n- 下载成功后不再自动隐藏当前页下载浮层。\n- “下载当前作品”按钮始终保留，完成提示改为“可继续下载其他作品”。\n- 失败时仍保留错误信息和重试能力。"
    },
    {
      "id": "2026-10-25-xlf视频解析与支持平台说明",
      "date": "2026-10-25",
      "title": "xlf 视频解析与支持平台说明",
      "body": "- 视频号分享链接直接使用 Router 的 `xlf` 视频解析模型，复用统一「模型设置」的认证，不再依赖通用平台提取器与视频号 Cookie。\n- 其他平台保留现有成功路径，常规解析失败后最多补充调用一次 xlf；本地存储、文件大小限制与媒体工具问题不触发模型请求。单次解析上限 120 秒，不增加模型重试。\n- xlf 返回直链通过现有媒体传输和后处理能力下载，不重新运行平台提取器。保留源平台、原始来源链接、本地归档及统一下载历史。\n- 日志记录主路由/回退路由、调用次数、是否提交、解析/下载阶段和原始失败原因，不输出密钥与 Cookie。失败提示给出统一设置入口及后续操作。\n- 链接下载界面与 README 补充抖音、快手、小红书、视频号、B站、YouTube、TikTok、头条/西瓜、微视、皮皮虾、好看视频、微博、京东及视频直链的解析尝试说明，提示费用和可用性边界。\n- 问题方案见 `docs/bug/2026-10-25-视频号与其他平台xlf解析补充.md`。"
    },
    {
      "id": "2026-10-25-kuaishou-share-url-decode",
      "date": "2026-10-25",
      "title": "快手分享二维码链接解码修复",
      "body": "快手推荐页已从二维码参数中取得分享短链，但后端未导入 `unquote`，因此请求会以 `name 'unquote' is not defined` 失败。现在补齐 URL 解码导入，并添加回归测试，覆盖二维码 `content` 参数中编码的 `/f/` 分享链接。\n\n验证：\n\n- `python -m pytest tests/test_account_browser_download.py -q`\n- `python -m compileall -q app/main.py tests/test_account_browser_download.py`\n- `git diff --check`"
    },
    {
      "id": "2026-10-25-kuaishou-profile-lock-recovery",
      "date": "2026-10-25",
      "title": "快手账号浏览器 Profile 锁恢复",
      "body": "## 变化\n\n- 修复 Windows 首字节锁导致应用读取不到旧 Hub 所有者 PID、快手浏览器持续启动失败的问题。\n- 锁元数据移至首字节之后，并兼容旧版本锁文件；保留账号 Profile、Cookie 和外部未知进程保护。\n- 恢复日志记录 PID 与 Profile 目录；旧 context 延迟关闭事件不再释放新 context 的锁。\n- 补齐浏览器生命周期测试桩的 `close_context` 接口。"
    },
    {
      "id": "2026-10-25-kuaishou-link-support",
      "date": "2026-10-25",
      "title": "快手链接解析兼容",
      "body": "分析了用户提供的 [KS-Downloader](https://github.com/JoeanAmier/KS-Downloader) 1.7 源码。它使用 GPL-3.0，支持通过 HTTP 跟随 `/f/`、`v.kuaishou.com` 分享短链的跳转并从落地页提取作品详情。本次没有把 GPL 项目代码或其额外依赖直接并入 Vimox Hub，而是在现有快手解析和浏览器 GraphQL 下载链路中补齐相同的链接入口：`www.kuaishou.com/f/...` 与 `v.kuaishou.com/...` 会跟随跳转，`kuaishou.cn/short-video/...` 可识别为快手作品直链。\n\n上游项目与许可：\n\n- 源码：<https://github.com/JoeanAmier/KS-Downloader>\n- 许可证：GPL-3.0，随上游仓库的 `LICENSE` 文件提供。\n\n验证：\n\n- `python -m pytest tests/test_kuaishou_current.py tests/test_share_downloader.py -q`\n- `python -m compileall -q app/platforms/kuaishou/resolve.py app/engine/share_downloader.py`\n- `git diff --check`"
    },
    {
      "id": "2026-10-25-kuaishou-direct-ssr-download",
      "date": "2026-10-25",
      "title": "快手下载优先使用 SSR 媒体解析",
      "body": "快手当前页下载此前优先打开账号 CDP 新标签监听 GraphQL；当 CDP 没有暴露该响应时，虽然作品页 HTML 已包含 Apollo SSR 媒体数据，流程仍会等超时后交给不支持该快手 URL 的通用 yt-dlp 路由。本次将下载顺序改为先使用 Chrome TLS 指纹 HTTP 会话请求精确作品页，直接从 Apollo SSR 状态解析视频或图集媒体并沿用 Hub 原生媒体下载器；只有 SSR 请求/提取失败时才打开 CDP 标签尝试 GraphQL。\n\n已使用用户提供的分享短链验证：跳转至 `/short-video/3xmiah94sm27xqq`，页面 SSR 状态成功解析出作者、作品标题、封面及 MP4 媒体地址。\n\n验证：\n\n- `python -m pytest tests/test_account_browser_download.py tests/test_kuaishou_current.py tests/test_share_downloader.py -q`\n- `python -m compileall -q app/main.py tests/test_account_browser_download.py`\n- `git diff --check`"
    },
    {
      "id": "2026-10-25-kuaishou-apollo-fallback",
      "date": "2026-10-25",
      "title": "快手 SSR 作品详情回退",
      "body": "修复快手详情页没有捕获到 CDP GraphQL 响应时引用未初始化作品对象的异常。快手分享短链落地页会将 `window.__APOLLO_STATE__` 嵌在 HTML 中；现在优先从 SSR Apollo 状态读取作品视频或图集媒体、标题及作者信息，GraphQL 响应仍作为兜底来源。\n\n验证：\n\n- 使用分享短链请求验证其重定向到 `/short-video/{作品ID}`，并确认详情 HTML 含 Apollo 状态和媒体地址。\n- `python -m pytest tests/test_account_browser_download.py tests/test_kuaishou_current.py tests/test_share_downloader.py -q`\n- `python -m compileall -q app/main.py tests/test_account_browser_download.py`\n- `git diff --check`"
    },
    {
      "id": "2026-10-24-账号浏览器Profile冲突修复",
      "date": "2026-10-24",
      "title": "账号浏览器 Profile 冲突修复",
      "body": "- 修复打开非小红书账号的可见浏览器后，下载当前作品再次启动同一 Profile 并报 `BrowserProfileConflictError` 的问题。\n- 可见 context 现在登记在 `BrowserManager` 生命周期内，后续详情读取复用该会话；关闭 context 时统一释放 Profile 锁。\n- 更新 Profile 冲突提示，说明开发版与安装版共用同一账号 Profile 时需先关闭另一版本的浏览器窗口。\n- 账号浏览器关闭回调统一通过 `BrowserManager` 清理，避免已关闭 context 留在缓存中。\n- 在 [bug 记录](../bug/2026-10-24-账号浏览器下载Profile冲突.md) 记录现象、根因、修复与兼容边界。"
    },
    {
      "id": "2026-10-24-账号Profile冲突自动恢复",
      "date": "2026-10-24",
      "title": "账号 Profile 冲突自动恢复",
      "body": "- 启动账号浏览器遇到 Chrome 原生锁或应用 `.browser.lock` 时，先等待短暂的 Chromium 退出写回窗口。\n- 若锁仍存在，读取旧 Vimox 锁的进程信息，并终止确认属于 Vimox 的旧服务进程树；同时只处理可执行文件为 Chrome/Chromium 且 `--user-data-dir` 完整匹配当前 Profile 的浏览器进程，再等待锁释放并重试。\n- 通用 `uvicorn`、其他应用及无法确认归属的进程不会被终止，仍返回 Profile 冲突提示；不会删除、复制或迁移 Profile。\n- 验证：浏览器、CDP、安全及下载相关测试合计 128 passed、3 skipped；`compileall` 与 `git diff --check` 通过。"
    },
    {
      "id": "2026-10-24-抖音精选页链接下载回退修复",
      "date": "2026-10-24",
      "title": "抖音精选页链接下载回退修复",
      "body": "- 修复抖音 `jingxuan?modal_id=...` 与其他页面的 `modal_id` 作品链接交给 yt-dlp 后报 `Unsupported URL`：提取/下载前转换为该作品的标准 `/video/{id}` 地址，保留图文和已有作品路由。\n- 账号浏览器链接下载使用标准作品地址打开详情，并监听精选页的 feed/related 响应；解析结果仍严格校验目标作品 ID。\n- 链接下载结果、失败历史及服务日志附带请求编号、入口、下载通道、阶段、目标作品、媒体文件数量和耗时；服务日志不输出账号 Cookie。\n- 本地 yt-dlp 2026.08.19 实测不接受精选页 modal 路由但接受标准 video 路由；新回归测试同时验证截图中两个作品 ID。"
    },
    {
      "id": "2026-10-24-抖音精选页下载与模型输出上限",
      "date": "2026-10-24",
      "title": "抖音精选页下载与模型输出上限",
      "body": "- 抖音精选页“下载当前作品”直接提交当前 `jingxuan?modal_id=...` URL，由后端现有 `modal_id` 解析和下载流程处理，不再等待分享按钮或读取混淆 CSS 类名。\n- 多模态图片、视频、Router 理解和账号诊断报告请求统一固定为 32000 tokens；更新上游脚本的本地 SHA-256 记录。\n- 验证：已完成的全量相关回归为 208 passed、3 skipped；本次直链调整后的下载器、抖音和分享链接测试为 56 passed、3 skipped。Router 测试验证即使客户端请求较小值，服务端仍发送 32000。\n- 真实账号页面：现有服务 `127.0.0.1:18639` 成功复用账号 3 的登录浏览器并导航到 `https://www.douyin.com/jingxuan?modal_id=7698360942177815850`，返回 `current_page_download_enabled=true`。另一实例 `127.0.0.1:18787` 因该账号 Profile 已被 18639 持有而报 Profile 冲突；本机 Chrome 未开放 CDP，`browser-harness` Python 模块缺失，故无法自动点击真实窗口并确认文件落盘。"
    },
    {
      "id": "2026-10-24-抖音当前页直链下载调整",
      "date": "2026-10-24",
      "title": "抖音当前页直链下载调整",
      "body": "- “下载当前作品”直接提交当前浏览器 URL，支持精选页 `jingxuan?modal_id=...`，不再触发分享弹窗或解析短链。\n- 验证：`.venv/Scripts/python.exe -m pytest tests/test_account_browser_download.py tests/test_douyin_share_download.py tests/test_share_downloader.py -q --tb=short`：56 passed、3 skipped。"
    },
    {
      "id": "2026-10-24-抖音当前页直达链接下载",
      "date": "2026-10-24",
      "title": "抖音当前页直达链接下载",
      "body": "- 发布版本：Vimox Hub 0.3.5。\n- 浏览器“下载当前作品”按钮在点击时直接获取 `location.href` 并交给 Vimox Hub。\n- 账号浏览器的抖音请求跳过作品详情读取，直接使用通用链接下载器及所选账号 Cookie、代理和下载历史，避免长时间读取详情后失败。\n- 验证：`.venv/Scripts/python.exe -m pytest tests/test_douyin_share_download.py tests/test_account_browser_download.py tests/test_share_downloader.py -q --tb=short`：57 passed、3 skipped。\n- 验证：启用 `VIMOX_HUB_RUN_LOCAL_CDP=1` 运行精选页 Chromium 桥接验收：1 passed，确认只提交当前 `location.href`、tab 数量和 URL 不变。\n- 验证：`npm run build:ui`、Python `py_compile` 通过。真实登录 Chrome 未开放 CDP，无法自动确认账号 Cookie 下实际媒体落盘。"
    },
    {
      "id": "2026-10-24-抖音当前页分享链接与CDP下载",
      "date": "2026-10-24",
      "title": "抖音当前页分享链接与 CDP 下载",
      "body": "- 恢复并接入历史版本的分享短链提取脚本：从当前抖音 `jingxuan?modal_id=...` 页面分享面板的二维码/复制链接区域提取 `v.douyin.com`，再经当前 tab 的下载桥接调用 yt-dlp 链接下载。\n- 下载桥接同时传递分享短链和原始作品页 URL；下载历史仍可打开原始 modal 链接。\n- 历史记录的「打开原链接」使用该账号 CDP 浏览器；「重试」会导航同一账号浏览器标签并触发页面内下载按钮。账号浏览器尚未打开时自动启动对应账号浏览器。\n- 当前 tab 下载不再调用会创建作品读取页的抖音 native 解析器；临时 Cookie 仍从该 CDP context 同步给 yt-dlp。"
    },
    {
      "id": "2026-10-24-抖音当前页下载复用原标签",
      "date": "2026-10-24",
      "title": "抖音当前页下载复用原标签",
      "body": "- 该版本曾把“下载当前作品”交给 Hub 后再读取抖音详情，造成等待过久或失败；此行为已由 `2026-10-24-抖音当前页直达链接下载.md` 修正。\n- 下载完成提示在 Vimox Hub「链接下载」查看已下载内容。\n- 此记录说明上一版的问题；请以直达链接下载记录中的实现和验证为准。"
    },
    {
      "id": "2026-10-24-抖音分享面板真实悬停",
      "date": "2026-10-24",
      "title": "抖音分享面板真实悬停",
      "body": "- 将分享入口操作移至账号 CDP 后端，在当前作品 tab 对 `[data-e2e=\"video-player-share\"]` 使用浏览器真实鼠标 hover；不再依赖 `dispatchEvent` 合成鼠标事件。\n- 等待 `[data-e2e=\"video-share-container\"]` 出现后读取容器内二维码 `alt` 的分享短链，再交给 yt-dlp。原作品 URL 仍单独保留到下载历史。\n- 本地 Chromium 验收从没有分享面板的页面开始；只有真实 hover 事件触发页面监听器后才创建分享面板，确认短链提取成功且 tab 数仍为 1。"
    },
    {
      "id": "2026-10-24-抖音下载与社交素材本地化",
      "date": "2026-10-24",
      "title": "抖音下载与社交素材本地化",
      "body": "- 抖音链接下载新增账号浏览器读取通道，复用已登录账号的浏览器环境、代理和统一读取模式；直连接口返回 403 或空详情时，混合模式会回退浏览器读取。\n- 短链会先解析到准确作品页，严格校验作品 ID，避免把推荐作品误当成目标下载。\n- 下载历史封面优先读取本地封面、图集或本地视频生成的缓存缩略图，只有本地素材不存在时才保留远端地址。\n- AGENTS.md 补充社交媒体原始图片、视频和封面有效期与本地素材索引约定。"
    },
    {
      "id": "2026-10-24-抖音Cookie自动同步与失败重试",
      "date": "2026-10-24",
      "title": "抖音 Cookie 自动同步与失败重试",
      "body": "- 从账号浏览器当前标签下载抖音作品时，强制使用当前 Chrome/CDP 浏览器登录态读取作品，不再绕开账号浏览器改用旧 Cookie 快照。\n- 仅在回退到 yt-dlp 时，从当前账号浏览器上下文读取最新抖音 Cookie，过滤为抖音域名并写入本次下载临时文件；下载完成或失败后删除临时文件，不将 Cookie 值写入日志或长期存储。\n- 下载历史显示可打开的原始链接；失败记录新增「重试」按钮，自动复用原账号和当前选择的画质。\n- 对照本地成功/失败历史：作品 `7698360942177815850` 的成功记录来自抖音短链账号浏览器通道；失败记录的错误为 yt-dlp `Unsupported URL`。截图中的新失败来自绕过浏览器通道后使用旧 Cookie 文件。"
    },
    {
      "id": "2026-10-24-修复抖音分享面板短链读取",
      "date": "2026-10-24",
      "title": "修复抖音分享面板短链读取",
      "body": "- 根据真实抖音页面 DOM，分享弹层由 `[data-e2e=\"video-share-container\"]` 标记，复制操作是文字为「复制链接」的按钮；分享短链出现在容器内二维码图片的 `alt` 文案中。\n- 页面已打开分享弹层时，先从该容器图片 `alt` 提取 `v.douyin.com` 短链，不再先等待弹层中不存在的「分享」按钮。\n- 每个作品的短链码是动态数据，只用于匹配和提取，不用于选择器或页面分支判断。自动化测试使用独立 fixture 短码。"
    }
  ],
  "releaseDate": "2026-10-31T19:12:51.574Z",
  "downloadUrl": "https://vimox.cn/downloads/vimox-hub/VimoxHub-Setup.exe",
  "size": 87470597,
  "sha256": "88de819dd9341ba9c99b6c0ef2adad448e308fe8724d229bec07c2e06225884b",
  "blockmapUrl": "https://vimox.cn/downloads/vimox-hub/VimoxHub-Setup.exe.blockmap",
  "releaseUrl": "https://vimox.cn/downloads/vimox-hub/guide/#install"
}
