Passer au contenu principal
1

dsh-plugin-crypto-ticker

18569663yz-web/dsh-plugin-crypto-ticker

A live crypto ticker card in the DeepSeek Harness sidebar footer, above the balance and Settings, showing BTC, ETH, SOL and JUP prices, 24-hour change and 24-point sparklines, with a pulse on each price tick, zero dependencies and no API key.

Installer

dsh plugin --profile web add github:18569663yz-web/dsh-plugin-crypto-ticker

README

dsh-plugin-crypto-ticker

给 DSH(DeepSeek Harness) Web GUI 用的加密货币行情卡片:侧边栏左下角、余额与设置上方,实时显示 BTC / ETH / SOL / JUP 等主流代币的价格、24 小时涨跌和迷你走势图。

零依赖、免密钥、开箱即用——不装任何其它插件也能正常显示(已在干净 profile 下用无头浏览器验证过)。

侧边栏左下角的行情卡片

上图为真实页面截图(无头浏览器渲染,2× 像素密度)。完整界面见 screenshot-full.png。

┌────────────────────────┐
│  …会话列表…             │
│                        │
│  行情             OKX ⟳   │
│  ● BTC   76,926  +1.72% ╱╲╱   │  ← 这张卡片
│  ● ETH    2,472  +3.72% ╱╲╱   │
│  ● SOL   102.00  +5.47% ╱╲╱   │
│  ● JUP     0.263 +13.4% ╱╲╱   │
│  ⚙ 设置                │
└────────────────────────┘

特性

  • 红涨绿跌(中文习惯),价格按量级自动选小数位,成交量按 K/M/B 缩写。
  • 真实的 24 小时小时线,不是装饰——首屏从交易所取 24 根 1H 收盘价,之后把实时读数续上去,线会一直动。
  • 价格上跳标红、下跳标绿并短暂脉冲,扫一眼就知道刚在动。
  • 点任意一行或表头 ⟳ 立即刷新;悬停看 24h 高/低、成交量、当前信源与更新时间。
  • 侧边栏收成 56px 窄栏时自动变成「字标 + 价格」。
  • 数据源自动降级:OKX → Binance → CoinGecko。全部不可用时保留最后已知价格并置灰、表头显示「已断开」,而不是清空界面。
  • 宿主侧缓存,多个标签页共享同一份数据,不会因为开了三个窗口就把上游请求翻三倍。
  • 自动适配系统代理(见下文),国内网络不用额外配置。

安装

方式一:dsh plugin(推荐)

dsh plugin --profile web add github:18569663yz-web/dsh-plugin-crypto-ticker

dsh plugin 会把包装进 $DSH_HOME/profiles/web,并自动把它加入 profile 的 bundle 层栈(因为本包的 package.json 声明了 dsh.bundle.patch):

"dsh": { "profile": { "bundles": [
  "@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-plugin-crypto-ticker"
]}}

装完重启 dsh web 即可(桌面端则完全退出后重开)。

国内网络:ERR_PNPM_GIT_RESOLVE_FAILED

pnpm 用 git ls-remote 解析 github: 依赖,它只走 HTTPS,不读浏览器/系统的代理设置。国内直连 github.com 经常超时,会报:

Error: ERR_PNPM_GIT_RESOLVE_FAILED
  ╰─▶ Failed to resolve git dependency "github:...": git ls-remote failed:
      fatal: unable to access 'https://github.com/...': Failed to connect to github.com port 443

优先改用 codeload 的 tar 包地址。 实测国内可以直连——被挡的是 github.com,codeload.github.com 是通的,而且这条路径完全不经过 git:

dsh plugin --profile web add https://codeload.github.com/18569663yz-web/dsh-plugin-crypto-ticker/tar.gz/refs/heads/main

Release 页面里的 .tgz 资产也能装,但它同样需要代理:下载会 302 跳到 objects.githubusercontent.com,国内直连不通。

dsh plugin --profile web add https://github.com/18569663yz-web/dsh-plugin-crypto-ticker/releases/download/v0.1.0/dsh-plugin-crypto-ticker-0.1.0.tgz

或者给这次安装配上代理(端口换成你自己的):

$env:HTTPS_PROXY = 'http://127.0.0.1:7890'
$env:HTTP_PROXY  = 'http://127.0.0.1:7890'
dsh plugin --profile web add github:18569663yz-web/dsh-plugin-crypto-ticker

插件运行时不需要这个。 行情请求走的是本插件自带的传输层,它会自己读 Windows 系统代理(见下面「系统代理」一节),不受 HTTPS_PROXY 是否设置影响。

方式二:脚本安装(不经过 pnpm)

适合离线或不想动 node_modules 的场景:

.\install-crypto-ticker-plugin.ps1 -Profile web          # 安装
.\install-crypto-ticker-plugin.ps1 -Profile web -Uninstall   # 卸载

它把文件复制到 $DSH_HOME/profiles/web/plugins/ 并往 cordis.patch.yml 写一行相对路径。

两种方式不要同时用:那样插件会被加载两次(重复 id 会让插件树启动失败)。已经在用脚本方式的话,先 -Uninstall 再走方式一。

⚠️ 改完客户端代码必须重启,不是刷新

client-modules 给每个外挂 bundle 分配的 rev 是启动时生成的不透明值,且 bundle 响应头是 cache-control: immutable:

// packages/client/modules/src/index.ts
// The opaque initial rev rides the row until HMR observes a file change;
const rev = this.allocateInitialRevision()

rev 不变 → 浏览器永远命中旧缓存,此时硬刷新也没用(URL 没变)。所以改过 client.js(哪怕只是改 CSS)都必须重启 dsh web。判断新代码是否真的进了浏览器,看界面:布局或文案变了就是新版;如果重启后毫无变化,多半是这个包没被装载,而不是缓存问题。

配置

全部可选。走方式一时写在 profile 的 cordis.patch.yml:

- id: crypto-ticker
  config:
    symbols: [BTC, ETH, SOL, JUP]   # 要显示的标的,默认 BTC, ETH, SOL, JUP
    schedule: 15                    # 刷新间隔(秒),默认 15
    cacheMs: 10000                  # 宿主缓存窗口,默认 10 秒
    sparklineCacheMs: 300000        # 走势序列重取间隔,默认 5 分钟
    upstreamTimeoutMs: 8000         # 单个信源超时,默认 8 秒
    proxy: false                    # 显式代理 / false 强制直连 / 不填自动探测

标的写币种代码即可(去空格、转大写、自动去重)。OKX 与 Binance 支持任意 XXXUSDT 现货对;CoinGecko 只认常见资产(见 index.js 的 COINGECKO_IDS),未知标的在兜底信源下没有价格。

想加别的币,直接把它填进 symbols 就行,不用改代码。内置的 CoinGecko id 映射覆盖:BTC、ETH、SOL、JUP、BNB、XRP、DOGE、ADA、AVAX、TON、LINK、SUI、LTC、DOT、TRX。

JUP 是 Solana 上的 Jupiter 代币,但在 OKX 与 Binance 都有 JUPUSDT 现货对,所以它和 BTC 一样只用现成的交易所接口,不需要任何 Solana 链上访问(不连 RPC、不读合约、不碰钱包)。

数据来源

顺序信源接口密钥
1OKXGET /api/v5/market/tickers?instType=SPOT、GET /api/v5/market/candles免
2BinanceGET /api/v3/ticker/24hr、GET /api/v3/klines免
3CoinGeckoGET /api/simple/price(仅行情,免费层无 K 线)免

四个默认标的(BTC / ETH / SOL / JUP)在三个信源上都取得到,包括走势图(CoinGecko 除外,它没有 K 线)。

系统代理(国内网络必读)

交易所接口在国内需要代理,而 Node 的 fetch 不读 Windows 系统代理(浏览器读,Node 不读)。如果什么都不做,插件会在每个信源上各超时 8 秒、界面显示「已断开」——而同一时刻用 PowerShell 测同一个 URL 却是通的,很容易误判成接口挂了。

所以宿主半侧自己解析代理,优先级从高到低:

  1. config.proxy;
  2. HTTPS_PROXY / https_proxy / HTTP_PROXY / http_proxy 环境变量;
  3. Windows 注册表 HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings(即系统代理);
  4. 都没有则直连——没有代理的机器上直连本来就是对的。

本地(127.0.0.1)访问不受代理影响。只支持 http:// 代理(CONNECT 隧道);https:// 代理会退回直连并在宿主日志告警。

没用 undici 的 ProxyAgent:它不是本插件的依赖,而 profile 的 plugins/ 目录没有自己的 node_modules,去猜 DSH 安装目录里的 undici 太脆。Node 自带的 http/tls 永远在,https.mjs 直接开 CONNECT 隧道。

实现要点(给维护者)

文件角色
index.js宿主半侧:在 Connection 的 /api 通道注册精确 Fetch 路由 /api/crypto.ticker,负责取数、缓存、多源降级、代理
https.mjs传输层:零依赖 HTTPS GET,支持 HTTP 代理 CONNECT 隧道、chunked 解码、超时与大响应体上限
client.js浏览器半侧:window.__ModuleLoader__.load({ id, factory }) 形式的客户端 bundle,注册进 sidebar.footer.action
cordis.patch.ymlbundle patch:dsh plugin 安装时由 dsh 自动应用

数据走 /api 而不是自建端口是有意的:桌面端不监听任何端口,渲染进程的 /api/* 经 dsh-app:// 由分帧管道转发给宿主,只有注册在 Connection 上的精确路由才能到达。同一路由在 dsh web 下由 HTTP 桥接承载,两种界面都能用。

宿主还把浏览器挂载心跳写进 $DSH_HOME/crypto-ticker.json 的 clientSeenAt——宿主看不见界面,这是「卡片真的渲染出来了」的唯一外部证据:

Get-Content "$env:USERPROFILE\.dsh\crypto-ticker.json" -Raw

左下角排版踩过的三个坑

全靠无头浏览器量 computed style 才看清,读源码推不出来:

  1. 槽位元素 display: contents,自己不生成盒子——真正排布占用者的是更外层的 .footerActions。
  2. .footerActions 默认 flex-wrap: nowrap,flex-basis:100% 只当初始尺寸、不换行,卡片会被压成半行。所以卡片挂载时向上找第一个真正的 flex 容器并给它加 wrap(只改运行时 inline style,幂等)。
  3. slot.register 的 order ≠ CSS 的 order:前者决定 ui-slots 生成的 DOM 顺序,后者才决定 flex 的排布位置。只改前者的话 flex 仍按默认 0,而 dsh-cost-meter 先加载、DOM 更靠前,余额就压在卡片上面。

当前取值:宽栏 .dct-root { flex: 1 0 100%; order: -990 }(独占整行、排在余额上方),窄栏 .dct-rail { order: 0 }。想换成「余额在上」,把两处 -990 改成 990 即可。

开发与自检

node tests/smoke.mjs   # 宿主路由 + 缓存 + 三源降级 + chunked 解码 + 代理优先级 + bundle 注册与渲染
node tests/live.mjs    # 真实网络:打印各标的当前价(需要能访问交易所)

smoke.mjs 把三个交易所重定向到进程内的本地 HTTP 服务器,不需要网络。仓库根目录的 verify-crypto-ticker.ps1 会逐层验证安装是否生效,measure-footer-layout.ps1 用无头浏览器量真实布局(排查「改了看不到」很有用)。

已知限制

  • 只在 web / desktop 的 Web GUI 显示;headless、sdk、acp 等没有侧边栏的 profile 装上也不可见。
  • 若只有 CoinGecko 可用(免费层无 K 线),走势图退化为「本次会话内的实时读数」曲线,冷启动时点数很少。
  • 界面文案是中文硬编码,未接入 DSH 的 locale 字典(树外插件不走 verify-client-ui-i18n)。
  • 只支持 http:// 代理。
  • 桌面端重建 profile(应用资源变化或「重置 Desktop」)会清掉 plugins 目录与 patch 行;用方式一安装则表现为依赖丢失,重装即可。

许可

MIT。行情数据版权归各交易所所有,仅供个人参考,不构成投资建议。

Plugins associés