dsh-aimy
Manages a relay station's many groups and rates for DSH, switching the station's billing group in place and refreshing the model list and rate on stations that expose /v1/token/group; stations without it fall back to read-only and keep serving models.
Install
dsh plugin --profile web add dsh-aimy
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✓ |
| 2 list | ✓ |
| 3 mount | ✓ |
| 4 boot | — |
Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
<img src="assets/icon-180.png" width="72" align="right" alt="dsh-Aimy">
dsh-Aimy
DSH(DeepSeek Harness)插件 dsh-Aimy:解决中转站多分组多倍率不方便管理的问题——把中转站作为模型来源接入 DSH,支持就地切换中转站分组,同步刷新模型列表与计费倍率。
配合的中转站接口:GET/PUT /v1/token/group(见 [../docs/dsh-aimy.md](../docs/dsh-aimy.md))。
入口
入口 · 插槽 · 说明
首页左侧栏图标 + 主区面板「Aimy-艾米」 · sidebar.panellist(order 30)+ main(key dsh-aimy) · 整页面板,撑满主区、自带滚动
- 面板 id、
main的 key、包名一致,都是dsh-aimy;sidebar 点图标时把activePanelId设成该 id,main据此命中。 - 两处注册都在
src/client/app.ts的apply()里,inject = ['slots']。 - client 侧必须用
react.createElement(可变 children);react/jsx-runtime的jsx(type, props, key)第三参是 key,会把h(type, props, ...children)的子节点全部丢掉。 - 面板头部与侧栏图标共用
src/shared/brand.ts里的品牌路径。
为什么不放设置页:宿主dsh-client-ui-settings-general的navIcon(id)按分区 id
硬编码图标,只认account/models/agent-presets/plugins/archived-sessions,
其余一律回落到齿轮;settings.section插槽也只消费id/order/label,从不读icon,
插件侧无法覆盖。借用已知 id 同样不可行——它们已被内置分区占用,重复 id 会让
renderSlot(only: active) 同时渲染两个分区。所以只保留侧栏入口,避免设置页出现一行齿轮。
截图(市场详情页)
市场(dsh-market)详情页会展示插件截图。在你自己的仓库里声明,改图无需再提 PR:
// screenshots.json(与 package.json 同级) ["assets/screenshots/01-panel.png", "assets/screenshots/02-group.png"]
- 放图目录:
assets/screenshots/(见该目录下的 README) - 1–8 张;dsh-market 只展示前 6 张
- 支持相对路径(不得以
/开头、不得含..),或 GitHub 托管的 https 绝对 URL
(raw.githubusercontent.com / user-images.githubusercontent.com /
camo.githubusercontent.com / github.com)。第三方图床会被拒——截图 URL 会带上访问者 IP
- 未声明时市场会从本 README 自动抽取图片(回退行为)
自检:npm run check:screenshots(校验格式、数量、主机白名单、文件是否存在)
当前未声明 screenshots.json:保留「从 README 自动抽取」的回退。
想显示真实面板截图时,把图放进 assets/screenshots/ 再声明即可。
状态
- ✅ P1:包骨架、host 路由、侧栏面板、分组读取与切换、旧版降级
- ✅ P2:复用
@deepseek-ai/dsh-llm-pi-ai挂载模型路由,切组后重挂载刷新模型目录 - ✅ P4-1:面板里直接填密钥(写 DSH 凭据库,write-only),保存后立即探测并挂载模型
- ✅ P4-2:「当前选中模型不在新分组」提示(只提示,不自动改选)
- ✅ 双档案:Aimy-艾米(地址隐藏的预设)+ 兼容模式(自填 URL/协议,适配 new-api / sub2api)
- ✅ 模型能力声明:逐模型解析真实容量(站点声明 → 官方目录 → 兜底 1M/128K),面板可开关图片
- ✅ 余额桥:装 dsh-pet 时,宠物的「查看余额」直接读本站额度
- ✅ 分组信息缓存(TTL 5 分钟 + stale-while-revalidate),面板热路径 1–8ms
- ✅ 已发布 npm:
dsh-aimy
安装
一条命令(npm,推荐)
dsh plugin --profile desktop add dsh-aimy
发到 npm 的是预构建包(lib/ 已在包内),安装时不跑构建脚本,不会停在
ERR_PNPM_IGNORED_BUILDS / allowBuilds 授权那一步。
一条命令(GitHub 源码)
dsh plugin --profile desktop add github:Sheep1x/dsh-aimy
--profile不能省:DSH 的plugin子命令要求显式指定 profile(省略会报--profile <name> is required)。- 这条命令把参数原样转发给 profile 目录下的 pnpm,装完仍需把
dsh-aimy加进dsh.profile.bundles(见下)。 - 仓库提交了
lib/,安装即得可加载的包。但 GitHub 来源仍可能触发 pnpm 的构建授权检查,
若停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED,把提示的键名加进该 profile 的
pnpm-workspace.yaml 的 allowBuilds 后重试;改用上面的 npm 命令可完全避开这一步。
方式一:pnpm 从 GitHub 安装(无需走 registry)
cd ~/.dsh/profiles/desktop pnpm add github:Sheep1x/dsh-aimy # 或 npm i github:Sheep1x/dsh-aimy
然后在 profile 的 package.json 里把 dsh-aimy 加进 dsh.profile.bundles。
前置条件:本机要有git(pnpm 的github:依赖靠它取包),且能访问 GitHub。
仓库提交了构建产物lib/,所以源码安装(dsh plugin add/pnpm add github:…/file:)拿到的就是可直接加载的包,
不依赖prepare在装机时构建(file:与dsh plugin add都不会跑prepare)。
改完源码请node build.mjs并一起提交lib/,否则用户装到的是旧代码。
想锁定版本可以用 github:Sheep1x/dsh-aimy#<commit-sha>。
方式二:本地路径
先把源码构建出 lib/,再装:
pnpm add file:D:/openwork/dsh-aimy
git clone https://github.com/Sheep1x/dsh-aimy.git cd dsh-aimy npm install # 装 esbuild 等构建依赖 npm run build # 产出 lib/index.js 与 lib/client.js npm test # 136 项测试(host + capacity + group-cache + client)
然后在 DSH profile 里装本地目录,并把 dsh-aimy 加进 dsh.profile.bundles(~/.dsh/profiles/<profile>/package.json)。
cd ~/.dsh/profiles/desktop pnpm add link:D:/openwork/dsh-aimy # 软链:build 完重启即生效 # 或 pnpm add file:D:/openwork/dsh-aimy # 快照:改完要 pnpm install --force
link:只在node_modules/dsh-aimy建一条软链;file:会按files字段打快照,源码变动 pnpm 未必自动刷新。
两种方式下 peer(@deepseek-ai/*)都由 DSH 的 profile 解析器按包名路由,不依赖本目录的node_modules。
安装(本地开发)
cd dsh-aimy "C:/Program Files/nodejs/node.exe" build.mjs # 构建 lib/index.js + lib/client.js
然后在 DSH profile(~/.dsh/profiles/<profile>/package.json)里加依赖并加入 bundles:
cd ~/.dsh/profiles/desktop pnpm add file:D:/openwork/one-hub/dsh-aimy
{
"dsh": { "profile": { "bundles": [ "...", "dsh-aimy" ] } }
}
重启 DSH 后,首页左侧栏出现「Aimy-艾米」图标,点开是整页面板。
两个 Tab / 两个档案
Tab · 地址 · 密钥引用 · 路由名 · 显示名 · 能力
Aimy-艾米(默认) · 内置 https://aimy.sheep1x.top,界面只读展示、不可编辑 · ONEHUB_API_KEY · onehub · Aimy-艾米 · 读模型 + 真实切分组
兼容模式 · 用户自填(写入 $DSH_HOME/dsh-aimy/profiles.json) · ONEHUB_COMPAT_API_KEY · onehub-compat · 兼容模式 · 读模型 + 调用;分组接口缺失时自动只读
- 两个档案互相独立:各自挂各自的 pi-ai 路由,模型选择器里按显示名区分,切 Tab 只是切配置页。
- 兼容模式适配 new-api / sub2api / 任意 OpenAI 兼容网关,可选
anthropic-messages协议。 - 分组接口是可选能力:
/v1/token/group返回 404 时只把supportsSwitch置 false,模型照常拉取与调用。
配置
插件配置在 profile 的 cordis.patch.yml(bundle 自带默认值,按需覆盖):
- id: dsh-aimy
name: dsh-aimy
config:
baseURL: https://aimy.sheep1x.top # 中转站根地址(不要带 /v1)
apiKeyRef: ONEHUB_API_KEY # 凭据引用名
group: '' # 期望分组(空 = 跟随令牌)
probeModels: false # 刷新目录后探测可达性(见下)
模型可达性探测(默认关闭)
中转站偶尔会「目录里有、调用报 model not found」。开启 probeModels 后,每次刷新目录会为
每个模型发一条最小生成请求(max_tokens: 1),把结果写进状态里的 reachability。
探测端点跟随该档案的线路协议,与真实调用同一套口径:openai-responses → POST /v1/responses
({ input, max_output_tokens })、openai-completions → POST /v1/chat/completions
({ messages, max_tokens })、anthropic-messages → `POST /v1/messa
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::9,最后更新 2026-10-29