按模型名补齐自定义网关模型的上下文与推理能力
29.9/100
综合分
0
GitHub 星标
579
npm 周下载
—/5
用户评分
数据截至 2026/9/17 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dsh-model-metadatanpm 源 · dsh-model-metadata 的发布者账号已校验与本仓库一致
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · vision
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 48 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包dsh-model-metadata @ 0.3.0
✓Node 引擎要求 >=22 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/9/21 23:43:22
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 88 处,展示前 48 条)
- 读取本地文件lib/index.mjs:312
if (existsSync(nvm)) { - 读取本地文件lib/index.mjs:313
for (const version of readdirSync(nvm)) add(join(nvm, version, "lib", "node_modules", "@deepseek-ai", "dsh", "node_modules")); - 读取本地文件lib/index.mjs:394
if (!existsSync(file)) continue; - 读取本地文件lib/index.mjs:506
stats = statSync(path); - 读取本地文件lib/index.mjs:516
const parsed = JSON.parse(readFileSync(path, "utf8")); - 写入本地文件lib/index.mjs:796
utimesSync(path, now, now); - 写入本地文件lib/index.mjs:804
mkdirSync(dirname(path), { recursive: true }); - 写入本地文件lib/index.mjs:805
writeFileSync(temporary, JSON.stringify(snapshot)); - 写入本地文件lib/index.mjs:806
renameSync(temporary, path); - 删除本地文件lib/index.mjs:814
rmSync(temporary, { force: true }); - 读取本地文件lib/index.mjs:1296
const stats = statSync(settingsStampPath); - 发起网络请求lib/client.js:719
response = await fetch(url, { headers: { accept: "application/json" }, cache: "no-store" }); - 发起网络请求lib/snapshot.mjs:181
const response = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) }); - 发起网络请求lib/snapshot.mjs:205
const response = await fetch(url, { headers, signal: AbortSignal.timeout(timeoutMs) }); - 读取本地文件dev-paths.mjs:31
candidates.push(existsSync(join(configured, "package.json")) ? dirname(configured) : configured); - 读取本地文件dev-paths.mjs:42
if (existsSync(nvm)) { - 读取本地文件dev-paths.mjs:43
for (const version of readdirSync(nvm)) candidates.push(join(nvm, version, "lib")); - 读取本地文件dev-paths.mjs:74
if (existsSync(join(installed, "package.json"))) add(installed); - 读取本地文件dev-paths.mjs:86
if (existsSync(join(root, "node_modules", specifier, "package.json"))) return root; - 读取本地文件dev-paths.mjs:137
if (existsSync(cache)) { - 执行外部命令固定命令dev-paths.mjs:152
const found = execFileSync("which", [command], { encoding: "utf8" }).trim(); - 读取本地文件install-plugin.mjs:81
const ROW_ID = JSON.parse(readFileSync(join(HERE, "package.json"), "utf8")).name; - 读取本地文件install-plugin.mjs:233
if (!existsSync(patchFile)) return undefined; - 读取本地文件install-plugin.mjs:234
return readFileSync(patchFile, "utf8"); - 读取本地文件install-plugin.mjs:386
if (!existsSync(entry)) return { skipped: `no dsh-app-boot at ${entry}` }; - 读取本地文件install-plugin.mjs:391
const rows = yaml.load(readFileSync(patchFile, "utf8")) ?? []; - 读取本地文件install-plugin.mjs:400
return existsSync(file) - 删除本地文件install-plugin.mjs:462
rmSync(file, { force: true }); - 删除本地文件install-plugin.mjs:465
rmdirSync(dropInDir()); - 删除本地文件install-plugin.mjs:489
rmdirSync(directory); - 写入本地文件install-plugin.mjs:548
mkdirSync(dropInDir(), { recursive: true }); - 写入本地文件install-plugin.mjs:549
writeFileSync(dropInFile(), `[Service]\nEnvironment=DSH_PI_AI_CATALOG_FALLBACK_INPUT=${mode}\n`); - 执行外部命令固定命令install-plugin.mjs:556
const reload = spawnSync("systemctl", ["--user", "daemon-reload"], { encoding: "utf8" }); - 删除本地文件install-plugin.mjs:593
for (const name of stale) rmSync(join(pluginDst, name), { force: true }); - 写入本地文件install-plugin.mjs:693
writeFileSync(patchFile, `${kept.length === 0 ? "[]" : kept}\n`); - 删除本地文件递归install-plugin.mjs:715
rmSync(pluginDst, { recursive: true, force: true }); - 删除本地文件install-plugin.mjs:718
rmSync(snapshotDst, { force: true }); - 写入本地文件install-plugin.mjs:757
mkdirSync(join(dshHome, "plugins"), { recursive: true }); - 写入本地文件install-plugin.mjs:758
mkdirSync(pluginDst, { recursive: true }); - 写入本地文件install-plugin.mjs:759
mkdirSync(dirname(patchFile), { recursive: true }); - 写入本地文件lib/refresh-snapshot.mjs:87
mkdirSync(dirname(out), { recursive: true }); - 写入本地文件lib/refresh-snapshot.mjs:92
writeFileSync(temporary, JSON.stringify(snapshot)); - 写入本地文件lib/refresh-snapshot.mjs:93
renameSync(temporary, out); - 删除本地文件lib/refresh-snapshot.mjs:95
rmSync(temporary, { force: true }); - 读取本地文件lib/refresh-snapshot.mjs:115
if (typeof readdirSync === "function" && existsSync(nvm)) { - 读取本地文件lib/refresh-snapshot.mjs:116
for (const version of readdirSync(nvm)) roots.push(join(nvm, version, "lib", "node_modules", "@deepseek-ai", "dsh", "node_modules")); - 读取本地文件lib/refresh-snapshot.mjs:121
if (!existsSync(file)) continue; - 读取本地文件lib/refresh-snapshot.mjs:140
const document = yaml.load(readFileSync(file, "utf8"));
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-llm-pi-ai给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 按模型名匹配元数据
- 补齐上下文与输出上限
- 标注推理档位与视觉
DSH 插件:按裸模型名把 custom-gateway 的模型匹配到应有的模型元数据(上下文窗口、输出上限、推理档位、视觉),不往你的设置里写任何东西
README
由 DeepSeek 最新模型翻译生成dsh-model-metadata
npm
license
node
Listed on dsh-plugin.org
已发布到 npm(dsh-model-metadata),源码在 github.com/pgjh/dsh-model-metadata。
English — Fills in the missing capability metadata of models you declared yourself on a custom gateway (context window, output cap, reasoning levels, can it see images). Every model is looked up by name at runtime; no DSH file is touched, and your settings document changes only when you press 写入 yourself. The fused controls follow the Settings page's language (Simplified Chinese, English).
一句话:你在 DSH 里接自己的网关时,模型往往只写了个名字。这个插件按模型名去目录里查一次,把上下文长度、输出上限、推理等级、能不能看图补上。
展开完整文档(README 剩余 1 节)
dsh-model-metadata npm license node Listed on dsh-plugin.org 已发布到 npm(dsh-model-metadata),源码在 github.com/pgjh/dsh-model-metadata。 English — Fills in the missing capability metadata of models you declared yourself on a custom gateway (context window, output cap, reasoning levels, can it see images). Every model is looked up by name at runtime; no DSH file is touched, and your settings document changes only when you press 写入 yourself. The fused controls follow the Settings page's language (Simplified Chinese, English). 一句话:你在 DSH 里接自己的网关时,模型往往只写了个名字。这个插件按模型名去目录里查一次,把上下文长度、输出上限、推理等级、能不能看图补上。 这是怎么回事 接自定义网关时,settings.yaml 里一般只写 id: llm-pi-ai: providers: my-gateway: # 你给这个网关起的名字 api: openai-responses baseURL: https://gateway.example/v1 models: - id: my-gateway/gpt-4o name: gpt-4o - id: my-gateway/claude-sonnet-4-5 name: claude-sonnet-4-5 问题是 DSH 查元数据的方式:它拿网关名 + 模型 id 原样去内置目录里对,而 my-gateway 当然不在目录里。于是这两个模型被当成“什么都不支持”: - 上下文按 256K 算 → 长对话被提前压缩,或者反过来爆掉; - 没有推理等级 → 模型选择器写着「当前模型未提供推理等级。」; - 只能收文字 → 发图片直接被拒。 但 gpt-4o、claude-sonnet-4-5 这些名字,目录里其实都有。差的只是按名字查一次。 插件做的事 1. 按模型名查:取 id 里最后一个 / 后面的名字(my-gateway/gpt-4o → gpt-4o),按“官方路由 → 内置目录 → opencode → models.dev”的顺序查(详见下面「哪些名字认得出」),查到之后,就把这个模型该有的上下文长度、输出上限、推理等级、图片支持补上去。名字的写法差一点也没关系:deepseek-v41-flash、deepseek-v4.1-flash、"DeepSeek-V41-Flash" 算同一个名字,显示名和 -exp 之类的后缀也能对上。 2. 只补缺的:你在 settings.yaml 里亲手写过的字段,它不动。反过来,它读不到这份文档时也绝不猜——文件不在它找的位置、机器上没有 YAML 解析器、或者你正编辑到一半 YAML 语法坏了,它都会完全不补,并在日志里说明原因(enrichment off (…)):这时候“你有没有声明”是它看不见的事实,而“借用”会把你亲手钉住的 64K 覆盖成目录里的 272K。 3. 界面上给你两个开关:推理等级、视觉。DSH 官方界面没有这两个控件,这里是唯一的图形入口;改完点「写入」固定下来,不点就一直跟着目录走。写入是按行的:双击只写一次,也不会把别的行还没写入的改动丢掉;只读的部署会直接说明写不了。这两个控件和结论行跟随设置页的语言(简体中文 / English)。 4. 目录数据自己更新:启动、打开界面、以及按天(每小时检查一次是否过期)各更新一次 models.dev,所以新模型不用你手动管;数据没变时只确认一次,不重新下载。 安装 装插件用的是 pnpm(和 npm 一个意思),先确认有: corepack enable pnpm # Node 自带;或者 npm i -g pnpm 然后三种方式选一种(web 是 profile 名,一般不用改): | 方式 | 命令 | | npm 包(推荐) | dsh plugin --profile web add dsh-model-metadata | | GitHub 仓库 | dsh plugin --profile web add github:pgjh/dsh-model-metadata | | 本地源码 | dsh plugin --profile web add /path/to/checkout | 命令会把包装好,并自动挂进 DSH 的插件列表,不用你手改配置文件。装完重启一次(用你启动 dsh 的方式:直接跑 dsh web 的就重跑一遍;交给 systemd 的就 systemctl --user restart ;Docker 里就重启容器)。 之后记住这条界线:界面上的改动刷新页面就行,逻辑上的改动要重启。 还有一种不用 pnpm 的“复制文件”装法:node install-plugin.mjs --apply。这个文件也在 npm 包里(装好之后在包的目录里一样能跑),它不经过 dsh plugin。它写在 DSH home 的 cordis.patch.yml 里,对所有 profile 生效,所以别和上面三种混用,否则插件会被装两遍。 用法 界面:设置 → 模型 → 你的网关卡片 → 编辑 → 自定义设置 → 模型目录 每个模型行里(名称下面、“容量”上面)会多出两行: - 推理等级:菜单里挑一个(跟随自动匹配 / 关闭推理 / 低·中·高 / 自定义…)。选「自定义…」可以填 low, high, max,写法和 settings.yaml 里一样。 - 视觉:跟随自动匹配 / 开启(能看图)/ 关闭(只收文字)。 - 下面那行是结论,告诉你查到了什么: 自动匹配:anthropic · 200K / 输出 64K · 有推理等级 · 视觉 写「无匹配」就是这个名字哪里的目录都没有,需要你自己填。 - 新加的行自己会出结论:卡片开着时点「添加模型」、输入完 id、或保存后重新打开这张卡,插件都会重新问一次目录,不用关掉设置再进来(更不用重启 dsh)。 - 改动之后才会出现「写入」按钮:只写这一行的两个字段,其它内容原样保留。写入是按行做的——双击只写一次,写完那一行仍留着写入结果,别的行还没写入的改动也不会跟着消失。 - 只读的部署(设置页自己就不让改)点「写入」会得到「这张卡片是只读的,无法写入」,而不是一个看不出原因的失败。 - 控件和结论行的文字跟随设置页的语言:设置页是简体中文就用中文,是 English 就用英文。 容量为什么不在这个界面里改 官方那一行的「容量」折叠已经管上下文和输出上限了,再开两个框只会让你纠结哪个算数。插件只告诉你这两个值的真实来源(你自己声明的 → 目录里查到的 → 网关默认);而官方输入框里的灰字永远只是网关默认值(比如 256K),认不出 gpt-4o 其实是 128K。要改就用同一行的「容量」。 目录数据什么时候更新 | 时机 | 说明 | | 启动 dsh | 默认检查一次;本地数据不到 15 分钟就跳过(DSH_PI_AI_CATALOG_REFRESH_ON_START=stale 改成按天判断,off 则不在启动时检查) | | 打开 dsh 界面 | 数据超过 6 小时就后台更新(DSH_PI_AI_CATALOG_REFRESH_OPEN_HOURS,0 = 不按这个时机更新)。这个时机是界面数据路由被请求时触发的,所以 DSH_PI_AI_CATALOG_PANEL=off 会让它一起消失(见下表) | | 按天(进程常驻时的那条路) | 插件每小时看一次本地数据的年龄,超过 24 小时(DSH_PI_AI_CATALOG_REFRESH)就后台更新;0 = 关掉所有自动更新(总开关)。这条是给“一直不重启、也不打开设置页”的部署准备的:以前没有它,这种进程会一直用最初那份数据 | | 手动 | node lib/refresh-snapshot.mjs,立刻生效、不用重启(--help 列出 --out / --url / --timeout-ms / --settings;--settings 会顺带打印“你配的模型里这份数据覆盖到了哪些”) | 一次检查不一定等于一次下载:请求会带上本地数据里存的 ETag,models.dev 回一个没有内容的 304 就说明数据没变——这时只把本地文件的时间戳重新盖一次,不重新下载。下载失败也不会被反复重试:自动触发的两次尝试之间至少隔 5 分钟,所以网络不通时反复打开界面不会变成一连串下载请求(手动跑 refresh-snapshot.mjs 不受这条限制)。 数据存在 $DSH_HOME/models-dev-snapshot.json(当前约 0.6 MB,随 models.dev 数据量增长;机器上只此一份,所有 profile 共用)。放这里是有意的:更新插件会替换整个插件目录,数据若跟着插件走就会被一起丢掉、下次启动还得重下一遍;放在 DSH home 里,更新插件完全不会碰它,也不用等下载。装好第一次启动时如果还没有数据,它会自己下载一份(约 5 MB,几秒钟)。想换位置就用 DSH_PI_AI_CATALOG_SNAPSHOT 指到别处。 开关(环境变量,按需) | 变量 | 默认 | 取值 / 作用 | | DSH_PI_AI_CATALOG_FALLBACK | full | full = 容量 + 推理等级 + 图片都补;context = 容量和图片照补,推理那一半关掉(等价于把 DSH_PI_AI_CATALOG_FALLBACK_LEVELS 设成 off;图片要一起关就用 DSH_PI_AI_CATALOG_FALLBACK_INPUT=off);off = 插件完全不干活 | | DSH_PI_AI_CATALOG_FALLBACK_LEVELS | on | on = 任何匹配到的来源都能声明推理等级;bundled = 只有 DSH 自带目录(pi-ai 目录、官方 DeepSeek 路由自己的目录)能,models.dev 只补容量;off = 完全不碰推理等级 | | DSH_PI_AI_CATALOG_FALLBACK_INPUT | on | on = 图片也走同一套匹配;bundled = 只信 DSH 自带目录(含官方 DeepSeek 路由自己的目录),不信 models.dev;off = 不判断图片 | | DSH_PI_AI_CATALOG_REFRESH | 24 | 过期小时数,超过就认为数据旧了;0 = 关掉所有自动更新 | | DSH_PI_AI_CATALOG_REFRESH_ON_START | always | always = 启动就检查(受下面的下限保护);stale = 只在超过 DSH_PI_AI_CATALOG_REFRESH 小时时才检查;off = 启动不检查 | | DSH_PI_AI_CATALOG_REFRESH_START_FLOOR_MINUTES | 15 | 启动检查的下限:本地数据比它新就跳过,避免重启循环反复下载 | | DSH_PI_AI_CATALOG_REFRESH_OPEN_HOURS | 6 | 打开界面时,数据超过这个小时数才后台更新;0 = 不按这个时机更新 | | DSH_PI_AI_CATALOG_SNAPSHOT | $DSH_HOME/models-dev-snapshot.json | 数据文件换位置(插件在磁盘上只写这一个文件) | | DSH_PI_AI_CATALOG_SNAPSHOT_URL | models.dev 的公开地址(默认数据源) | 换数据来源(自建镜像 / 代理用) | | DSH_PI_AI_CATALOG_PANEL | on | off = 根本不注册界面数据路由(补全本身不受影响,只是编辑器里不会出现那两行控件,也不会显示任何报错)。注意它同时会关掉「数据超过 6 小时、打开界面时更新」这个时机——那个时机就是这条路由被请求时触发的 | | DSH_PI_AI_CATALOG_PANEL_HOSTS | 不设 = 任何 Host | 逗号分隔的 Host 白名单:只回应列出来的 Host,不在其中的一律拒绝;反代后面用 | | DSH_CATALOG_FALLBACK_NODE_MODULES | 不设 | 额外的一个 node_modules 根目录:找不到 DSH 的包时从这里找 | | DSH_PI_AI_SETTINGS_FILE | $DSH_HOME/settings.yaml | 读哪个设置文档(判断哪些字段是你自己声明的) | DSH_PI_AI_CATALOG_FALLBACK_LEVELS 是为什么存在的:镜像站对某些模型只给一个"会推理"的裸标记、没有等级细节,把它当作"低/中/高都行"可能给端点送去它当场就拒绝的等级——和图片那个开关防的是同一类过度声明。设成 bundled 时,自带目录(它们本来就带等级映射)说了算,models.dev 只用来补容量。 每个开关都做校验:不设就是上面的默认值;写了但不认识会在日志里报一次,然后落回一个写明的取值——大多数开关落到保守的那一端:DSH_PI_AI_CATALOG_FALLBACK_INPUT 认不出算 off、DSH_PI_AI_CATALOG_FALLBACK_LEVELS 认不出算 bundled、DSH_PI_AI_CATALOG_REFRESH_ON_START 认不出算 off;两个例外是故意落到宽松端(那正是它们的默认值,认不出时宁可维持原行为):DSH_PI_AI_CATALOG_FALLBACK 认不出算 full、DSH_PI_AI_CATALOG_PANEL 认不出算 on。小时数只认普通的非负十进制数:0x10 这种写法会被拒绝并按默认值处理,不会悄悄读成 0(那等于关掉自动更新)。 更新插件 | 装法 | 命令 | | npm / GitHub | dsh plugin --profile web update dsh-model-metadata | | 本地复制 | node install-plugin.mjs --update(等同 --apply:重新拷一份文件、把插件行补上;跑完会告诉你只需刷新页面还是必须重启 dsh) | 两种更新都只替换插件目录:目录数据($DSH_HOME/models-dev-snapshot.json)在 DSH home 里,更新插件不会碰它,也不用重新下载。想连数据一起删掉是另一条命令(见「卸载」里的 --purge)。 哪些名字认得出 - 只看最后一个 / 后面的名字:my-gateway/gpt-4o 和 other-gateway/gpt-4o 一样好使,网关叫什么不影响。 - 名字怎么算一样,按顺序试: 1. 完全一样,或只有大小写不同; 2. 忽略 .、-、_ 和空格再比一次——deepseek-v41-flash、deepseek-v4.1-flash、"DeepSeek V41 Flash" 都读作同一个名字(网关别名差的基本就是这点写法); 3. 显示名也算数——官方 DeepSeek 路由把 V41 flash 叫 deepseek-flash、显示成 "DeepSeek-V41-Flash",按显示名就能对上; 4. 目录里的名字多带一个 -exp、-experimental、-latest、-preview、-free 后缀也算——DeepSeek-V4-Flash-Vision 对上 deepseek-v4-flash-vision-exp。这个宽松只朝一个方向:目录里的名字可以多一个装饰后缀,你自己写的名字多带则不算同一个(gpt-4o-free 不是 gpt-4o——同名的 -free 端点经常是另一套部署、另一个窗口)。 - 查的顺序(先查到的赢):模型自家厂商的官方路由(glm→智谱、kimi→月之暗面、deepseek→官方 deepseek-official 路由自己的目录、gpt→openai、claude→anthropic…)→ DSH 内置目录(pi-ai)的其余部分 → opencode 聚合器 → models.dev 快照。官方目录在 @deepseek-ai/dsh-llm-deepseek 里,不翻 pi-ai 目录就查不到它——所以这一路是单独去问的(你在 llm-deepseek 设置段里改过的目录也会被用上);聚合器是转抄别人目录的,所以永远排在正经目录后面,只用来补缺。 - models.dev 那一层里,同一个名字往往有好几家 provider 都发布,数字并不一致,所以里面的顺序是:这个模型自家厂商发布的行 → id 正好等于裸名的行 → 别人转抄或起别名的行 → 看起来不像聊天模型的行(图片、embedding、语音这类端点只是排在最后,不会让本来能匹配的名字变成「无匹配」)。 - 新加的网关不用注册任何东西,加完就能认;官方路由新出的型号在 models.dev 跟上之前,也能靠官方目录先对上。 - 名字是自己编的(比如 my-gateway/internal-model-v3),哪里都没有 → 界面写「无匹配」,自己填即可。若目录里有同家族的其它型号(比如你写了 doubao-seedream-5-lite,目录里有一堆 doubao-seed-*),「无匹配」那行会把它们列出来供参考——但不会自动拿来当元数据,写法对不上就是没把握,宁缺毋滥。 常见问题 会不会改我的配置? 不会。你不点「写入」,它一个字节都不写 settings.yaml;点了也只写那一行的推理等级和视觉:写之前会重读一次当前配置,别的行的内容、以及别的行你还没写入的改动都不会被顺手带走。 界面文字是中文还是英文? 跟随设置页:设置页切到 English,这两个控件和结论行就是英文,其它语言回落到简体中文。 会不会改 DSH 自己的文件? 不会。它只在运行时包一层,官方文件一字未动。 和“把元数据写进配置”的插件有什么不同? 那种是查一次就把值复制进你的配置,写进去就固定了;这里是每次按名字现查,目录更新了值也跟着变。想固定就点「写入」。 来源写着第三方(models.dev:xxx、openrouter)可信吗? 一般没问题,结论行会写出来源;不对就在那一行改写,你自己的声明永远优先。 手机上能用吗? 能。两个选择器用的是 DSH 自己的菜单,不会弹系统那套全屏单选。 卸载 dsh plugin --profile web remove dsh-model-metadata # npm / GitHub / 本地源码装法 node install-plugin.mjs --uninstall # 复制文件装法:只删插件行,拷进去的文件留着 node install-plugin.mjs --purge # 卸载,并把拷进去的文件和目录数据一起删掉 用 --vision 写过的 systemd drop-in,--uninstall 和 --purge 会一起删掉。 复制安装器还有几个选项(node install-plugin.mjs --help 是完整列表):--check 只报告当前状态并跑一次挂载自检(不写任何文件,--vision 也一样),--apply / --update 都是“重新拷一份并补上插件行”,--profile 只改某个 profile 的补丁文件,--home / --install 指定 DSH home 与 DSH 安装位置,--unit + --unit-dir 指出 systemd 的 drop-in 目录,--vision on|bundled|off 就是给这个单元写 DSH_PI_AI_CATALOG_FALLBACK_INPUT 的 override(on 是删掉 override、回到插件默认)。另外 --purge 删的是插件真正读的那个快照文件:你设过 DSH_PI_AI_CATALOG_SNAPSHOT 就删那个路径,而不是默认名字那个。 注意 - 插件挂在 DSH 内部一个没有公开文档的位置(PiAiAdapter)。DSH 升级若改动它,插件会自动停用并打一行日志,不会让 DSH 起不来。 - 界面读数据用的 GET /model-metadata/matrix 不走应用的登录校验(DSH 目前没给插件路由留校验钩子)。它只回答模型名和目录结论,不含地址、也不含任何密钥——但另一面要说清楚:端口对别人可达的部署,别人也能读到“你配置了哪些模型”。 - 不想要这条路由就用开关关掉:DSH_PI_AI_CATALOG_PANEL=off。补全本身完全不受影响,编辑器里只是不会出现那两行控件(也不会显示任何报错——客户端分不清“开关关了”还是“路由没注册过”,所以它什么都不说)。只想在特定的名字上回应(比如在反代后面)就用 DSH_PI_AI_CATALOG_PANEL_HOSTS 给出允许的 Host 列表,不在列表里的 Host 一律拒绝;来自别的站点的浏览器跨站请求也一律拒绝。真要连注册这段代码都去掉,最后的手段才是删掉 lib/index.mjs 里的 registerPanel(ctx, logger) 一行——那是改源码、插件更新后会回来,能不改就不改;而且它不只去掉那条路由,还会一起失去“打开界面时更新数据”这个时机(registerPanel 是那个时机的唯一入口,另一个入口是每小时检查一次的按天规则,不受影响)。 开发 这一节的东西要源码检出;除 npm run test:unit 之外,都还要一份真的 DSH 安装——它们要驱动真实的 PiAiAdapter,缺了这份安装会直接失败(verify.mjs 和 test-fallback.mjs 会明确提示用 DSH_INSTALL 指路),不会假装跑过。 npm test # = node verify.mjs:主回归。verify.mjs 自己会拉起下面带 ✔ 的套件 npm run verify # 同上,名字更直白 npm run test:unit # 不需要 DSH 安装:unit + install-plugin + refresh-policy 三个套件 node verify.mjs 里包含:官方文件没被改动、补全真的生效、你自己声明的字段优先、mode/input 开关生效、打包不变量(该发布的文件都发了、客户端注册名和包名一致、安装器标记不带包名),以及「lib/ 读的每个环境变量都写进了 README」这类防漂移断言,再加上这几个套件(✔): | 套件 | 需要什么 | 测什么 | | ✔ tests/unit.mjs | 无(不联网、不装 DSH) | 三个纯模块:名字规则、快照整理、面板数据与写入 | | ✔ tests/install-plugin.mjs | 无(在临时目录里合成 DSH 布局) | 复制安装器:写行、卸载、--purge、退出码 | | ✔ tests/refresh-policy.mjs | 无(fetch 打桩,不联网) | 更新时机:启动、打开界面、按天、各个开关、去重 | | ✔ tests/panel.mjs | DSH 的包,不需要起服务器 | 面板数据;浏览器半边能否按 DSH 的模块形状加载、和宿主半边是否一致 | | ✔ tests/hot-snapshot.mjs | 同上 | 目录数据换了以后,同一个进程里下次解析就用新数据 | | ✔ tests/hot-add-model.mjs | 同上 | 运行中新增的模型也会被补全 | | tests/browser-check.mjs | 跑着的 dsh + Chromium | 真浏览器里验收界面 | | tests/fusion-write.mjs | 跑着的 dsh + Chromium | 真点一次「写入」,跑完把 settings.yaml 还原 | | tests/new-route.mjs | 跑着的 dsh + Chromium | 临时加一个网关,验证“新网关自动匹配”,跑完还原 | | tests/live-refresh.mjs | 联网(约 5 MB) | 真去 models.dev 拉一次,验证自动更新 | | tests/harness.mjs | — | 不是套件:上面各套件共用的脚手架(断言、临时目录、Cordis 上下文替身) | 每个套件跑完都会打印一行 N/M assertions passed;verify.mjs 连这一行也检查,套件“一个断言都没做就退出 0”会被判失败。 单跑诊断工具: node test-fallback.mjs --source \ --plugin ./lib/index.mjs --settings --source 不写会去自动找已安装的适配器(找不到就让它报错,用下面的 DSH_INSTALL 指路);--plugin 加上就会带上本插件,用来对比“有插件 / 没插件”同一个模型的两行结果。不写 --settings 时它会自带一份空文档(既不读、也不会被机器上的 settings.yaml 影响);--plugin-settings 让适配器和插件读不同的文档,用来复现“声明存在、插件读不到”这一类情况(这时代码会拒绝补任何字段,见「插件做的事」第 2 条)。真浏览器工具同理,需要时用环境变量指路(不写死任何绝对路径): DSH_INSTALL= # 找不到 DSH 时 CHROME= # 找不到浏览器时(默认扫 Playwright 缓存与 PATH) PLAYWRIGHT_CHROME= # 同上,兼容 Playwright 自己的变量名 DSH_UNIT= # 浏览器工具要从 journal 里取应用 URL 时(或用 --url 直接给) LIVE_REFRESH_DEADLINE_MS= # tests/live-refresh.mjs 等真下载完成的上限(默认 300000) lib/index.mjs 宿主端:按名字查目录、补元数据、提供界面数据、更新时机 lib/names.mjs 模型名怎么读(裸名、宽松比较、后缀)的唯一实现 lib/client.js 浏览器端:把两个开关放进模型行(用 DSH 自己的菜单组件) lib/panel.mjs 界面数据与写入内容的纯函数 lib/snapshot.mjs models.dev 目录的下载与整理 lib/refresh-snapshot.mjs 手动更新目录的 CLI cordis.patch.yml 安装时自动挂载插件的那一行 install-plugin.mjs 不用 pnpm 的本地安装 / 更新 / 卸载 packaging.mjs 包布局与本地布局的约定(安装器和测试共用) dev-paths.mjs 开发工具找 DSH 与浏览器的唯一出处(不含机器相关的绝对路径;浏览器那部分要真的 DSH 安装和 Chromium) tests/harness.mjs 各套件共用的脚手架 tests/unit.mjs 三个纯模块的套件 tests/install-plugin.mjs 复制安装器的套件 tests/cdp.mjs 三个浏览器工具共用的 CDP 驱动 tests/snapshot-fixture.json 回归测试用的两条目录数据(让结果与当天数据无关) CHANGELOG.md 每个版本改了什么 npm 包里发的是 lib/index.mjs、lib/names.mjs、lib/panel.mjs、lib/snapshot.mjs、lib/refresh-snapshot.mjs、lib/client.js、cordis.patch.yml、install-plugin.mjs、packaging.mjs、dev-paths.mjs、README.md、CHANGELOG.md、LICENSE 和 package.json——所以“复制文件”装法在 npm 装好的副本里也能用。verify.mjs、test-fallback.mjs 和 tests/ 是开发工具,不在包里,只有源码检出里有。 问题与贡献 遇到问题、想让某个名字被认出来、或想改点别的,直接开 issue:——带上 DSH 版本和插件启动那行日志,形如: dsh-model-metadata: installed (mode full+levels:on+input:on, refresh 24h + on start always (floor 15m) + on open 6h + daily check 1h, panel on, adapter /dsh-llm-pi-ai/lib/index.js, catalog /pi-ai/dist/providers/all.js, model names indexed 2604, official deepseek catalog 4 models, snapshot entries 3698) (这行里有用的就是括号里那几段开关状态和三个数字;它不含地址也不含密钥。)另外别贴 baseURL、API key 或任何 credentials:真正需要的是模型名和目录来源,够定位了。 许可 MIT(见 LICENSE)。
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
pgjh/dsh-model-metadata
按模型名补齐自定义网关模型的上下文与推理能力
相关插件 · 视觉能力
智能体工作台Devin-AXIS/iPolloWork
企业级、本地优先的智能体工作台,面向个人和智能体团队——一个工作区,容纳多个智能体引擎;一套统一体系,管理插件和技能;支…
★ 7,364已汉化DSH
72
开源设计工作台nexu-io/open-design
OpenDesign:首个协作式 AI 设计智能体工作区
★ 105,709已汉化DSH
71.8
GPT 图像提示词库freestylefly/awesome-gpt-image-2
Prompt as Code | GPT Image 2 / 2.5 提示词与案例库,530+ 个案例、20+…
★ 34,534已汉化DSH
71.5
多智能体编码工作区spacering-net/codeg
多智能体协作的 AI 编程工作区:汇总 Claude Code、Codex、OpenCode、Pi、Grok Build 等来源的会话。支持桌面应用、自托管服务器或 Docker。
★ 4,319已汉化DSH
71.5
AI 用量桌面小部件Javis603/token-monitor
EN | 简 | 繁 | KO | JA | PT
★ 3,533已汉化DSH
71.1
架构图生成器tt-a1i/archify
把你想理解、规划或分享的事,变成可以互动的可视化作品。
★ 93,105已汉化DSH
71.1
这是你的仓库?认领条目