loyalchiiina/dsh-lobsterai-daddy

dsh-lobsterai-daddy

把 LobsterDaddy 多账号控制台变成 DSH 界面上的悬浮球:可拖到任意位置并自动记忆坐标,面板可设置为跟随悬浮球移动;点开以抽屉呈现控制台——界面由原生 DOM 渲染(不用 iframe),数据经仅限本机的同源反向代理获取,自上而下为操作按钮、当前登录账号、以及含积分余额与签到状态(附最近签到时间)的账号列表;抽屉可拖动缩放并记忆尺寸,另有在线状态圆点与账号数徽标。

待分类deepseek-harnessfloat-balllobsterai

dsh-lobsterai-daddy · LobsterAIDaddy

[!WARNING] LobsterAIDaddy 已于 2026-10-21 停止维护(End of Life)。

出于作者个人精力与优先级调整,dsh-lobsterai-daddy 不再继续开发与维护:不再新增功能、不再适配 DSH 新版本、不保证修复缺陷。 仓库与 npm 上的包继续保留,已安装的用户可以照常使用,但不会再收到任何更新。

感谢一路以来的使用与反馈。

[!WARNING] LobsterAIDaddy is no longer maintained (End of Life, 2026-10-21).

Due to a shift in the author's personal priorities, dsh-lobsterai-daddy is discontinued: no new features, no DSH compatibility updates, and no guaranteed bug fixes. The repository and the npm package remain available; existing installs keep working, but no further updates will be published.

Thanks to everyone who used it and sent feedback.

把 LobsterAI 多账号管理变成 DSH 界面上的悬浮球:可自由拖拽摆放、位置自动记忆;面板可跟随悬浮球一起移动;点开即查看当前登录账号与账号列表,并直接签到、刷新额度、切号——这些能力由插件宿主内置实现,不需要 LobsterDaddy 控制台常驻。

A draggable floating ball that renders a native-DOM LobsterAI multi-account panel inside DSH: the account LobsterAI is currently signed in as, the full account list with balances and per-account check-in state, check-in-all / refresh-quota / switch-account actions backed by a built-in data layer (reads LobsterAI's SQLite directly), plus a self-hosted board page. Drag it anywhere, let the panel follow it. Only "log in a new account" and "sync gateway into DSH" still need the LobsterDaddy console.


效果图

悬浮球抽屉(完整界面)

悬浮球抽屉完整界面

⚠️ 截图为旧版本(≤ v0.9.5),仅作界面布局参考,按钮与指示器以正文为准:图中按钮区有 5 个按钮(含已删除的「抓取当前登录账号」),悬浮球右下角还有已被删除的状态圆点。当前实际为 4 个按钮、球上无圆点。

内容自上而下:操作按钮区 → 当前登录账号 → 账号列表(余额 / 套餐 / 今日已用 / 奖励明细 / 签到状态 / token 到期)→ 运行信息(数据目录 / LobsterAI 进程 / 定时自动签到 / 转接 DSH)。 抽屉顶部状态行的圆点为绿色 = LobsterAI 正在运行(该圆点在抽屉内,悬浮球上已不再有圆点);右侧标注「内置 · 账号 N 个」= 数据由插件宿主直读,不依赖任何外部控制台进程。


功能

速览

能力说明
🟠 悬浮球常驻 DSH 界面,可拖到任意位置,坐标自动持久化(重启后原地出现)
🧲 面板跟随悬浮球拖动悬浮球时面板一起走(相对位置不变);面板头部也可单独拖动;「跟随 / 固定」一键切换并记忆
📥 原生渲染面板点球展开/收起。抽屉内容自上而下:操作按钮 → 当前登录账号 → 账号列表 → 运行信息(数据目录 / LobsterAI 进程 / 定时自动签到 / 转接 DSH)
👤 当前登录账号自动读取 LobsterAI 的登录状态并显示昵称;切号后自动更新,无需手动抓取
✅ 签到状态与时间每个账号显示 已签到 / 今日已签到 / 今日未签到,并附最近签到时间
⏱ 定时自动签到宿主内建调度器:启动后 8 秒首跑,之后每 60 分钟一轮(CHECKIN_INTERVAL_MS),状态见抽屉「定时自动签到」行与 GET /health 的 checkinScheduler
💰 积分额度余额、套餐、今日已用、奖励明细(含到期日)
🦞 免退出并行登录「+ 免退出登录新账号」扫码加入(仍需 LobsterDaddy 控制台提供登录流程;控制台未运行时按钮会给出明确提示)
🔁 一键操作立即全部签到 / + 免退出登录新账号 / 刷新额度 / 同步网关到 DSH / 切号(签到、刷新额度为内置直调上游;登录新账号与同步网关仍走控制台)
↔️ 自由调整大小拖动抽屉左下角调整宽高,尺寸自动记忆
🔢 账号数徽标球左上角显示当前账号库数量(读宿主 /local/status,不依赖任何外部进程)
🌐 浏览器打开 / 网页看板头部「浏览器打开」由宿主进程真正拉起系统浏览器,打开插件自建的看板页 /dsh-lobsterai-daddy/board(带签到/刷新额度/抓取/登录/切号按钮)
⭐ Star 直达头部与看板均有「★ Star」,一键打开 GitHub 仓库
🧩 完全自包含账号/额度/签到/切号全部由插件宿主直接实现(读 SQLite + 直调官方接口),不需要 LobsterDaddy 控制台常驻

悬浮球与抽屉

  • 自由摆放:按住球拖到屏幕任意位置,松手即记住坐标(存 localStorage),重启 DSH 后原地出现。
  • 永不越界:拖拽与窗口缩放都会被夹回可视区内,不会把球拖丢。
  • 点击展开:单击球展开/收起抽屉;拖拽不会误触发展开(位移超过 3px 即判定为拖拽)。
  • 状态一眼可见:抽屉状态行显示「LobsterAI:运行中 / 已关闭」+ 数据来源与账号数;球左上角徽标显示账号库数量。(悬浮球上已无状态圆点——原「守护进程在线」指示灯随控制台退场已删除,它恒为灰、只是视觉上的空洞。)
  • 自由缩放:拖抽屉左下角调整宽高,尺寸独立持久化。

面板跟随悬浮球

  • 跟随模式:拖动悬浮球时,已展开的面板按相同位移一起移动,相对位置保持不变——球和面板始终保持在你能看到的同一区域。
  • 固定模式:面板钉在原地不动,只移动悬浮球。
  • 一键切换:面板头部「● 跟随 / ○ 固定」按钮,选择被记住,下次打开保持上次的模式。
  • 面板可独立拖动:拖面板标题栏(避开按钮)即可单独挪动面板。
  • 位置独立记忆:面板坐标与悬浮球坐标分开存储,互不干扰;窗口缩放时自动夹回可见区。

当前登录账号

  • 自动显示:抽屉里有一行蓝色横幅显示 LobsterAI 当前登录的账号昵称。
  • 无需手动抓取:插件每次刷新都会重新读取 LobsterAI 自己的登录记录,所以切号后自动更新,不用点任何按钮。
  • 未登录有提示:LobsterAI 未登录时显示「LobsterAI 未登录」。
  • 安全降级:读取失败时该行自动隐藏,不影响账号列表等其它内容。

实现说明:渲染进程无法打开 SQLite,因此由宿主半边只读访问 %APPDATA%\LobsterAI\lobsterai.sqlite 的 kv 表(auth_tokens / auth_user)并通过 GET /dsh-lobsterai-daddy/current 提供。

签到状态与最近签到时间

每个账号都会显示今天的状态,并且带最近一次签到的日期与时间:

状态含义
已签到 + 09-28 16:21今天签到成功,显示签到时刻
今日已签到 + 时间今天早些时候已经签过(本次是重复调用,幂等)
今日未签到(灰)今天还没有签到记录
失败文案(红)今天签到时出错,显示面板返回的原因

日期按面板的跨天判断给出,过零点自动归为「今日未签到」,不需要手动清理缓存。

账号与积分额度

每个账号卡片显示:

  • 账号标识:昵称/手机号(脱敏)+ uid 短号
  • 积分余额:当前余额(大字突出)
  • 套餐信息:套餐名(如「免费」「会员」)与今日已用
  • 奖励明细:最多 3 条奖励条目,含剩余量与到期日
  • 更新时刻:余额缓存的刷新时间
  • Token 有效期:到期日期,24 小时内到期会显示 ⚠ 提醒

一键操作

抽屉顶部提供 4 个操作按钮,另外每个账号行有一个「切换」按钮:

按钮作用
立即全部签到用账号库里每个账号的 token 逐个签到,直调 LobsterAI 上游活动接口(内置实现,不需要控制台,也不需要任何"预先同意"开关)
+ 免退出登录新账号打开无痕窗口扫码登录,登录后自动入库,账号数无上限;不动 LobsterAI App 当前登录状态。此功能仍需 LobsterDaddy 控制台提供登录流程;控制台未运行时会明确提示,而不是静默失败
刷新额度重新拉取所有账号的余额/套餐/今日已用(内置实现,绕过缓存强制重拉)
同步网关到 DSH把当前网关端口与 token 同步进 DSH 配置。仍需 LobsterDaddy 控制台;控制台未运行时按钮会给出提示(切号链路本身不依赖它)
切换(每个账号行)把该账号凭据写回 LobsterAI 的 SQLite 并重启 App,切完立即可用
  • 切换账号会关闭并重启 LobsterAI,因此保留二次确认。
  • 操作进行中按钮自动置灰,完成后自动刷新列表。
  • 登录按钮在面板忙或登录流程进行中被禁用。
  • 已移除的按钮(v0.7.2 / v0.9.5):复位登录流程、自动签到开关(同意)、守护进程开关、抓取当前登录账号——它们都是 LobsterDaddy 控制台时代的产物。其中「抓取当前登录账号」被删是因为它与「当前登录账号」自动显示完全冗余(/local/capture 与 /current 读的是同一份数据)。旧缓存若还残留这些按钮,点击会看到「该按钮已移除」的提示而不会静默失败。
  • 抽屉里点「浏览器打开」后的网页看板(/board)是独立页面,按钮集合与抽屉不同:立即全部签到 / 刷新额度 / 抓取当前登录账号 / 重新读取 / + 免退出登录新账号 / 每账号 切换 / ★ Star。注意看板上保留了「抓取当前登录账号」(它走内置 /local/capture,只是重读一次当前账号信息),抽屉里那个按钮则已按冗余理由删除。

实时刷新

  • 抽屉打开时每 15 秒自动刷新一次(REFRESH_MS = 15000,定时器在 setOpen(true) 里 startRefresh() 建立)。
  • 抽屉关闭时这条 15 秒轮询确实会停(setOpen(false) → stopRefresh() → clearInterval)。
  • 但**「不占用任何资源」是错的**:悬浮球上的账号数徽标由一个独立的、无条件的 30 秒定时器维护 —— lib/client.js:1786 setInterval(probe, 30000),它每次拉一遍 /local/status?quota=0(只取 accountsCount)。这条与抽屉开关无关,从挂载起就一直跑。
  • 头部 ⟳ 按钮可随时手动刷新。

ℹ️ 代码里还留着 BACKGROUND_REFRESH_MS = 60000(lib/client.js:265)与 startRefresh() 中「关闭态降频到 60 秒」的分支(:485-490),但那是遗留死代码:startRefresh() 的唯一调用点在 open === true 分支(:455),而 setOpen(false) 会立刻 stopRefresh()(:463),所以定时器回调执行时 open 恒为 true,那个 else 分支永远不会进入。文档按真实可达路径描述,不按注释描述。

兜底

  • 浏览器打开:由宿主进程真正拉起系统浏览器,打开插件自建的看板页 /dsh-lobsterai-daddy/board(不是 LobsterDaddy 控制台;window.open 在 Electron 沙箱里会被静默拦截,故改为宿主 spawn)。
  • 面板离线提示:连续 2 次拉取失败后,抽屉状态行会显示「面板没响应,正在自动恢复(每 60 秒巡检一次)」。 ⚠️ 这句界面文案有两处不实,以代码为准:①没有任何外部看护进程或"掉线即静默拉起"逻辑——lib/index.js 唯一的 setInterval 是签到调度器(:528),grep 巡检|拉起|revive 在 lib/*.js 里只命中这条 UI 文案本身;②文案里的"每 60 秒"也不是恢复周期,实际重试节奏就是前面说的 15 秒(抽屉开)/ 30 秒(徽标探针)。于是状态行的判断是"还能不能拉到数据",与服务是否开着无关——内置数据层正常时,即便 LobsterDaddy 控制台根本没跑,状态行也不会出现这句话。

⚠️ 为什么不用 iframe 嵌网页(v0.3.0 起):DSH 桌面端页面运行在 dsh-app://app 协议下,该协议只给顶层框架发放 x-dsh-desktop-renderer 通行证,iframe 作为子框架永远拿不到 → 403 → 空文档;改用绝对 http://127.0.0.1:port 又被渲染进程 CSP 拦(实测 Failed to fetch);DSH 还在 main.js 里主动禁用了 webview。三条路都封死,所以账号面板改为在抽屉里用原生 DOM 绘制,数据由宿主内置路由(/local/*、/current)提供,仅剩余功能经同源代理 fetch 取(该通道实测可用)。

安装

# 从 npm
dsh plugin --profile desktop add dsh-lobsterai-daddy

# 或从 GitHub
dsh plugin --profile desktop add github:loyalchiiina/dsh-lobsterai-daddy

装完重启 DSH 生效(客户端 bundle 由宿主启动时加载)。

前置:LobsterDaddy 面板(可选)

签到、额度、切号、当前账号显示全部由插件宿主内置实现(直读 SQLite + 直调官方接口),不需要控制台常驻。

只有两个功能仍需控制台:「+ 免退出登录新账号」(需要控制台的扫码登录流程)和 「同步网关到 DSH」。需要时先跑:

node lobster-daddy.js panel --no-browser

(默认监听 127.0.0.1:17819,仅本机可访问;--no-browser 为后台常驻模式,不弹窗口、不开浏览器。)

原理

DSH 界面
  └─ 悬浮球(client.js,shadow DOM,position:fixed)
       └─ 抽屉 → 原生 DOM 渲染的账号面板
            └─ fetch(根相对路径,走客户端 transport)
                 ├─ /dsh-lobsterai-daddy/local/*    ← 宿主内置实现(读 SQLite + 直调官方接口)
                 └─ /dsh-lobsterai-daddy/panel/api/* ← 宿主端同源反向代理(仅登录新账号 / 同步网关等仍需控制台的功能)
                      └─ http://127.0.0.1:17819       ← LobsterDaddy 网页控制台(可选)

三条硬约束(改代码前必读)

  1. fetch 的 URL 必须保持根相对路径。渲染进程的 CSP 拒绝绝对 loopback 请求(实测 relative-fetch status=200 而 loopback-fetch FAILED)。曾把 URL 升级为 http://127.0.0.1:<port> 导致抽屉全空,客户端探针里有一条断言专门守这个。
  2. 请求侧强制 accept-encoding: identity。代理要往 HTML 里注入 shim 并重算长度,一旦面板返回压缩体而我们又重标了 content-length,浏览器会按 gzip 解压一段明文 → 白屏 / 乱码。拿不到 identity 时原样透传字节并保留原编码头,绝不重新标注。
  3. 未命中上面 14 条内置子路径的其余路径,全部转发给面板。控制台自身用绝对路径 fetch('/api/...'),shim 会改写成 /panel/api/...;若代理只认 /panel/* 前缀而对其余路径回 404 JSON,控制台就会报 刷新失败:Unexpected token 'o', "not found" is not valid JSON。改动路由时必须保持这个 fallback 顺序:先内置子路径、最后才是转面板。

路由

插件只注册 1 条 prefix 路由 /dsh-lobsterai-daddy(kind: "prefix"),以下 14 条是 handler 内部的子路径分派;全部只允许本机回环地址访问,非回环一律 403。

路由方法用途
/local/statusGET内置数据源主力:直读 LobsterAI 的 SQLite,返回账号列表 + 额度。?quota=0 跳过额度、?force=1 绕缓存
/local/switchPOST内置切号:把指定账号凭据写回 LobsterAI 存储并重启 App
/local/checkinGET/POST内置签到:对所有账号跑一遍签到,?force=1 强制重签(handler 只校验回环,不限方法)
/local/quota/refreshGET内置额度刷新:强制重拉所有账号余额(绕过缓存)
/local/captureGET重读 SQLite 返回当前登录账号(内置版「抓取」,等价于刷新当前账号信息;抽屉已不再放这个按钮,看板仍在用)
/currentGET当前登录账号:只读 kv 表 auth_tokens / auth_user,返回 {available, uid, name, reason}
/statusGET宿主探活 + 面板健康(账号数量、面板端口)
/healthGET插件健康:版本号、账号数、定时签到调度器状态(是否启用/间隔分钟/启动延迟/上次运行)
/selfcheckGET请求头体积自检:统计 dsh-auth-* Cookie 条数与请求头占 maxHeaderSize 比例,给出 danger/warn 判词与处置建议
/boardGET插件自建看板页(/open 打开的就是它),不依赖控制台
/openGET由宿主进程拉起系统浏览器打开看板页(cmd start / open / xdg-open)
/open-urlPOST由宿主进程打开任意 http/https URL(body {url},非 http(s) 直接 400)——这是外链绕过 window.open 拦截的通用通道,看板的「★ Star」走它
/reportPOST客户端诊断上报(写入 ~/.dsh/lobsterai-daddy-client.log)
/panel/* 及其余所有未命中路径GET/HEAD/POST面板同源反向代理。/panel/x → /x,其余路径原样转发(控制台自身用绝对路径 fetch('/api/...'),shim 会改写成 /panel/api/...);非 GET/HEAD/POST 返回 405

为什么 /current 由宿主实现:渲染进程打不开 SQLite。宿主只读打开 LobsterAI 的数据库并返回 {available, uid, name, reason};任何失败都返回 available:false 而不抛错,绝不拖垮 /status。

注意 /status 与 /panel/api/status 不是一回事:前者是宿主自己的探活(返回账号数量),后者是控制台的账号列表。同名不同源,历史上混淆过一次。

配置

在 profile 的 patch 里可覆盖面板端口:

- insert:
    - id: dsh-lobsterai-daddy
      name: dsh-lobsterai-daddy
      config:
        panelPort: 17819

兼容性

  • DSH 桌面端 + 网页端均可用
  • 与其它悬浮球插件(dsh-todo-float-ball 等)共存,各自独立定位与持久化
  • 容器遵循 position:static + pointer-events:none,规避 Electron 下 position:fixed 子元素偏移问题
  • 需要 Node.js ^22.19.0 || >=24.0.0(package.json 的 engines.node);/current、/local/* 依赖 node:sqlite(Node 22+ 内置),不可用时相关行自动降级为不显示

常见问题排查

🔴 浏览器打不开("访问遇到了问题" / 无法访问此网站)

现象:DSH 桌面端一切正常,但用浏览器访问本地地址时报错;换一个浏览器却可能正常。

根因(已实测确认,非本插件问题):DSH 自身的认证 Cookie 累积,撑爆了请求头上限。

DSH 的浏览器认证 Cookie 命名规则是:

authority  = new URL("http://" + host).host   // 含端口 → "127.0.0.1:56958"
cookieName = "dsh-auth-" + sha256(authority)  // 端口变 → Cookie 名就变
             Max-Age = 30 天, HttpOnly         // 旧 Cookie 30 天内不会被清理

而 DSH 默认 port: 0 —— 每次重启都会换一个随机端口,于是:

重启一次 → 端口变 → authority 变 → 生成一个新 dsh-auth-* Cookie
                                  (旧的仍在,30 天后才过期)
        ↓
多次重启后累积到几十条
        ↓
Node 的 HTTP 请求头默认上限 16 KB(16384 字节)
        ↓
超限 → 服务器返回 431 → 浏览器显示"访问遇到了问题"

实测数据(本机):

浏览器请求头总长Cookie 部分
干净浏览器929 字节226 字节
累积后16663 字节16014 字节(71 条 dsh-auth-*)

任何浏览器、任何用户,只要 DSH 重启足够多次(≈70 次以上)都会遇到,与浏览器品牌无关。

解决方案

① 治标(立即可用):把 Node 请求头上限调大

[Environment]::SetEnvironmentVariable('NODE_OPTIONS','--max-http-header-size=131072','User')
# 然后重启 DSH 生效

验证:

$env:ELECTRON_RUN_AS_NODE='1'
& "$env:LOCALAPPDATA\Programs\DSH NEXT\DSH NEXT.exe" -e "console.log(require('http').maxHeaderSize)"
# 输出 131072 即生效

② 治本(推荐):固定 DSH 端口 —— 端口不再变,Cookie 名就不会变,自然不累积。

编辑 %USERPROFILE%\.dsh\desktop-preferences.json:

{
  "port": 56958,      // 原来是 0(0 = 每次随机)
  "lanPort": 0
}

改完重启 DSH,之后端口固定,旧的 Cookie 到期后不再产生新的。

③ 清理已累积的 Cookie:

  • 在浏览器设置里清除该站点的 Cookie(或全部 Cookie)
  • Cookie 是 HttpOnly,JS 无法删除,只能从浏览器设置里清
  • 清除后需要重新用带 ?token= 的地址访问一次以重新认证(DSH 启动时会自动打开该地址)

快速自检

访问插件自检路由(本机):

http://127.0.0.1:<DSH端口>/dsh-lobsterai-daddy/selfcheck

它会报告当前请求的头上限、是否可能超限,以及针对性的建议。

⚠️ 这不是本插件的缺陷:Cookie 由 DSH 的 dsh-client-connection 写入。 本插件只是恰好也跑在同一个端口上,因此同样受影响。


安全说明

  • 面板仅绑定 127.0.0.1;所有插件路由同样只接受回环地址(/local/*、/current、/status、/health、/selfcheck、/board、/open、/open-url、/report、/panel/* 全部走 isLoopback() 校验),非本机请求一律 403
  • /current 与 /local/* 会读取本机账号信息,因此同样受回环限制
  • 不采集、不上传任何数据;账号凭据与签到缓存由 LobsterDaddy 存在本机 %APPDATA%\LobsterDaddy\(accounts\*.json、checkin-cache.json),当前账号名从 %APPDATA%\LobsterAI\lobsterai.sqlite 只读取得
  • ⚠️ 多账号刷积分可能违反 LobsterAI 服务条款,请只用于自己的账号,风险自负

License

MIT