dsh-closet-tracker:把本地衣物愿望清单挂进 Harness 侧边栏

前言

DSH 的理念是「一切皆插件」。当你要给自己的 Harness 加一个自己用得上的能力时,常见做法是写一个面板,字段自己定义、接口自己拼、样式自己抄。这个插件走的是另一条路:它先有一个独立的本地 Web 应用管着真实数据,再让 Harness 面板只做「读同一份数据 + 同一份操作」。下面介绍的是 ramanasai 维护的 dsh-closet-tracker。

这是什么

一个仓库出两种形态:app/ 是一个零依赖的 Bun Web 应用,负责抓取商品链接、存数据、出统计;仓库根目录本身是一个 DSH 插件包,在 Harness 左侧边栏放一个衣架图标,在主列渲染完整的愿望清单面板,读的是同一个 app/data/items.json。

它解决的问题是:两边的数据保持同一份,你在 Web 应用里加的条目会立刻出现在 Harness 面板里,反之亦然。插件在 SkillHub 社区目录中归在「客户端」分类。

核心功能

下面这些能力都来自 README:

  • 读同一个数据源,两边共用 app/data/items.json
  • 粘贴链接即可加单品:应用抓取名称、图片、价格、店铺、品牌、分类,条目立刻进网格
  • 统计:愿望清单总值、仍需购买件数、已购数量、上次检查以来的降价
  • 筛选、搜索、排序:状态页签(All / Wishlist / Bought)、分类筛选、自由文本搜索、按最新 / 价格 / 名称 / 降价幅度排序
  • 单品操作:立即查价、愿望清单与已购互切、两步确认删除
  • Sync all:重新抓取所有在跟踪的链接并报告降价
  • 原生外观:只用主题 token,明暗跟随 Harness;空状态和离线状态会说明该怎么办;本地应用挂掉时每 12 秒静默重试

安装与启用

安装分两步:先把 Web 应用跑起来,再装插件包。Web 应用不需要 bun install:

cd app
bun run start          # http://localhost:3003
open http://localhost:3003

插件包需要 DeepSeek Harness(面向 0.2.1-rc.5 构建)且已有 profile。官方给出的安装方式是先把仓库 clone 下来,再把 clone 的绝对路径作为 target 传给 plugin_manager install_bundle——仓库根目录就是插件包本身:

git clone https://github.com/ramanasai/dsh-closet-tracker.git
plugin_manager install_bundle target=/absolute/path/to/dsh-closet-tracker

也可以在 Harness 的 Plugin Manager UI 里选「从本地目录安装 bundle」,填同一个路径。

另一个不 clone 的方式:从 Releases 下载 dsh-closet-tracker-1.0.0.tgz,直接把 tarball 路径当 target:

plugin_manager install_bundle target=/absolute/path/to/dsh-closet-tracker-1.0.0.tgz

装完后边栏出现标着 Closet Tracker 的衣架图标。插件只负责界面,数据要应用跑着才显示;如果安装前 Harness 页面已经开着,装完重新加载一次。

配置

上游地址写在 cordis.patch.yml,随 bundle 的 patch 插入 profile:

- insert:
    - id: closet-tracker
      name: dsh-closet-tracker
      config:
        # The local app. localhost reaches IPv4 or IPv6 loopback listeners.
        baseUrl: http://localhost:3003

端口换了的话,应用侧用 PORT=4000 bun run start 启动,再让 baseUrl 对上。默认的 3003 来自应用自身(process.env.PORT || 3003)。

内部结构

插件分两半,中间隔着一条代理。index.js 是 Host 端,client.js 是 Client 端。

应用是一个不发 CORS 头的本地进程,Harness 的插件指引又不允许用 iframe 包页面,所以 Host 端注册了一个同源代理路由,Client 端以 /closet-api/api/... 调用。代理的行为比较克制:

  • 只转发 /closet-api/api/*,其余路径不代理
  • 保留方法、请求体、上游状态码和 content-type
  • 上游只收到 host、content-type、accept;Harness 会话 cookie 和 Authorization 都不转发
  • 走 Harness Connection 的浏览器认证,Connection 服务不可用时 fail closed,返回 401
  • 上游地址由 config.baseUrl 固定,请求路径改不动它;上游超时 45 秒;应用不可达时回结构化的 502 JSON

Client 端用 Harness module table 里的 React 渲染,只用 --dsw-alias-* 主题 token,可见文案都走 Harness locale 服务注册。注册点一共三个:sidebar.panellist(id: closet-tracker,order: 30,衣架图标)、main(key: closet-tracker → 愿望清单面板)、Host 路由前缀 /closet-api。

典型用法

装好之后,日常就是三条路。

1、看到喜欢的商品,把链接粘进 Web 应用,应用抓取后把条目写入 items.json;Harness 面板刷新即可看到新条目。

2、在面板里用状态页签切换 All / Wishlist / Bought,用分类筛选和搜索定位,按价格或降价幅度排序。单品操作里可以现在查价(立即请求应用抓一次)、互切愿望清单与已购、两步确认删除。

3、想整体看看降了多少,点 Sync all,应用重新抓取每个在跟踪的链接并回报降价。

测试部分用 Node 自带的 test runner,不需要 Bun 也不需要真实应用——测试会自己起一个桩上游:

npm test                          # node --test: proxy forwarding, allowlist, gate, header hygiene
node --check index.js client.js   # syntax
cd app && bun run start           # run the app itself

适用场景与注意

适合两类人:一是想要 Harness 里一个隐私可控的购物清单面板、且愿意自己跑一个本地应用的开发者;二是想研究 DSH 插件里 Host / Client 两半怎么配合、代理还要守哪些边界的人——test/proxy.test.mjs 覆盖了转发白名单、认证门、请求头卫生,可以当参考。

几点要注意。插件以当前 DSH 进程的权限运行,所以安装前先读一遍 index.js、client.js 和 cordis.patch.yml,以及它的许可证;许可证是 MIT,仓库里另有一份打包在 app/public/vendor/ 的 jsPDF,同样由其作者以 MIT 授权。应用的 app/data/ 是个人数据目录,已被 gitignore。Web 应用不依赖任何框架,跑在任意浏览器里也能用,不装插件不影响它本身。README 明确说 Amazon 和 Ajio 的链接抓取效果差(两者都挡爬虫),条目仍会加入,需要用应用的编辑对话框手动补全。

常见故障和处理:

  • 面板提示 “Closet Tracker is not reachable at http://localhost:3003”:先跑 cd app && bun run start;面板自身每 12 秒会重试,也可以点 Try again
  • 装完边栏图标不显示:重新加载一次 Harness 页面,让新的 client 模块生成生效
  • 面板显示的是别的应用的数据:确认 cordis.patch.yml 里的 baseUrl 与应用端口一致
  • 端口占用:cd app && make stop 会清掉占用该 PORT(默认 3003)的监听进程;用别的端口启动时要同步改 baseUrl。注意 make stop 是按端口杀的,确认是你要杀的东西,可以用 lsof -nP -iTCP:3003 -sTCP:LISTEN 查一下

结尾

这个插件的价值在于分工清楚:应用管数据和抓取,插件管 Harness 里的呈现,中间用一条带认证和白名单的同源代理打通。两边数据是同一份,改一处就行。目录页与源码在下面。

  • SkillHub 目录页:https://www.skillhub.cn/plugins/ramanasai/dsh-closet-tracker
  • GitHub:https://github.com/ramanasai/dsh-closet-tracker
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜