🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

游戏王研究工具 mellfy-puppy/ygo-tools-for-dsh

DeepSeek Harness
mellfy-puppy8 天前有提交已提供中文文档扫描:含敏感能力

面向 DeepSeek Harness 的游戏王卡片研究、卡组分析与决斗验证工具

38.7/100
综合分
11
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/24 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

该插件未发布到 npm,按作者文档从 GitHub 源安装即可(静态检查只覆盖 npm 路径,不代表插件不可用)。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add mellfy-puppy/ygo-tools-for-dsh
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · skill
装得上吗
实装验证未通过(unknown),装前请到仓库确认最近更新与 issue
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 8 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
⚠︎ 实装验证未通过(unknown · 2026/9/27) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装

仓库 package.json 标记 private,未发布到 npm,需从源码安装

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✗npm 包ygo-tools-for-dsh(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=22.0.0 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/25 19:32:46

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 110 处,展示前 60 条)
  • 读取本地文件
    lib/index.js:304
    const raw = readFileSync(SKILL_BODY_FILE, 'utf8');
  • 读取本地文件
    skill/backend/index.mjs:145
    const content = await readFile(path, 'utf8');
  • 执行外部命令来自配置/变量
    skill/backend/persistent-engine-client.mjs:92
    const child = spawn(process.execPath, [SERVER_ENTRY, '--host', options.hostname, '--port', String(options.port)], {
  • 发起网络请求
    skill/backend/persistent-engine-client.mjs:118
    const response = await fetch(url, {
  • 读取本地文件
    skill/backend/source-adapter.mjs:696
    const deckText = await readFile(resolve(deckFile), 'utf8');
  • 读取本地文件
    skill/backend/source-adapter.mjs:825
    const payload = await readFile(resolve(String(input.file)));
  • 写入本地文件
    skill/backend/source-adapter.mjs:1090
    await mkdir(dirname(savedPath), { recursive: true });
  • 写入本地文件
    skill/backend/source-adapter.mjs:1091
    await writeFile(savedPath, ydk, 'utf8');
  • 写入本地文件
    skill/backend/source-adapter.mjs:1409
    await mkdir(outputDir, { recursive: true });
  • 写入本地文件
    skill/backend/source-adapter.mjs:1413
    await writeFile(stagingPath, replayBytes);
  • 删除本地文件
    skill/backend/source-adapter.mjs:1439
    await rm(outputPath, { force: true });
  • 写入本地文件
    skill/backend/source-adapter.mjs:1440
    await rename(stagingPath, outputPath);
  • 删除本地文件
    skill/backend/source-adapter.mjs:1442
    await rm(stagingPath, { force: true });
  • 写入本地文件
    skill/backend/source-adapter.mjs:1500
    await mkdir(outputDir, { recursive: true });
  • 读取本地文件
    skill/backend/source-adapter.mjs:1839
    const replay = new ygoproYrp.YGOProYrp().fromYrp(await readFile(replayPath));
  • 读取本地文件
    skill/backend/ygopro2-discovery.mjs:153
    entries = await readdir(current.directory, { withFileTypes: true });
  • 读取本地文件
    skill/backend/ygopro2-discovery.mjs:247
    payload = await readFile(executable);
  • 读取本地文件
    skill/backend/ygopro2-discovery.mjs:275
    entries = await readdir(decksDirectory, { withFileTypes: true });
  • 读取本地文件
    skill/backend/ygopro2-discovery.mjs:307
    try { return (await stat(path)).isFile(); } catch { return false; }
  • 读取本地文件
    skill/backend/ygopro2-discovery.mjs:311
    try { return (await stat(path)).isDirectory(); } catch { return false; }
  • 读取本地文件
    skill/backend/combo-artifact.mjs:80
    return { ok: true, kind: 'file', path, value: await readFile(path, 'utf8') };
  • 读取本地文件
    skill/backend/deck-migration.mjs:9
    const payload = JSON.parse(await readFile(path, 'utf8'));
  • 写入本地文件
    skill/backend/deck-learning.mjs:145
    await mkdir(skillDirectory(options), { recursive: true });
  • 写入本地文件
    skill/backend/deck-learning.mjs:153
    try { await writeFile(path, content, { encoding: 'utf8', flag: 'wx' }); }
  • 写入本地文件
    skill/backend/deck-learning.mjs:158
    await writeFile(temporary, content, { encoding: 'utf8', flag: 'wx' });
  • 写入本地文件
    skill/backend/deck-learning.mjs:160
    await rename(temporary, path);
  • 删除本地文件
    skill/backend/deck-learning.mjs:161
    } finally { await rm(temporary, { force: true }); }
  • 读取本地文件
    skill/backend/deck-learning.mjs:174
    try { entries = await readdir(directory, { withFileTypes: true }); }
  • 删除本地文件
    skill/backend/deck-learning.mjs:204
    await rm(loaded.data.path);
  • 读取本地文件
    skill/backend/deck-learning.mjs:240
    const stat = await lstat(path);
  • 读取本地文件
    skill/backend/deck-learning.mjs:243
    return await readFile(path, 'utf8');
  • 写入本地文件
    skill/backend/ygopro2-duel.mjs:226
    await writeFile(playerDeckFile, serializeYdkText(this.playerDeck), 'utf8');
  • 写入本地文件
    skill/backend/ygopro2-duel.mjs:230
    await writeFile(opponentDeckFile, serializeYdkText(this.opponentDeck), 'utf8');
  • 写入本地文件
    skill/backend/ygopro2-duel.mjs:288
    await writeFile(playerDeckFile, serializeYdkText(this.playerDeck), 'utf8');
  • 执行外部命令来自配置/变量
    skill/backend/ygopro2-duel.mjs:686
    const child = spawn(executable, args, {
  • 删除本地文件递归
    skill/backend/ygopro2-duel.mjs:807
    if (this.tempDirectory) await rm(this.tempDirectory, { recursive: true, force: true });
  • 读取本地文件
    skill/backend/ygopro2-duel.mjs:927
    archive = await JSZip.loadAsync(await readFile(sourceArchive));
  • 读取本地文件
    skill/backend/ygopro2-duel.mjs:940
    const installedConstantText = await readFile(join(sourceScripts, 'constant.lua'), 'utf8').catch(() => '');
  • 写入本地文件
    skill/backend/ygopro2-duel.mjs:948
    await mkdir(runtimeRoot, { recursive: true });
  • 写入本地文件
    skill/backend/ygopro2-duel.mjs:950
    await copyFile(installation.paths.serverExecutable, serverExecutable);
  • 读取本地文件
    skill/backend/ygopro2-duel.mjs:959
    const installedBytes = await readFile(target).catch(() => null);
  • 写入本地文件
    skill/backend/ygopro2-duel.mjs:961
    await writeFile(target, archiveBytes);
  • 读取本地文件
    skill/backend/ygopro2-duel.mjs:1049
    for (const entry of await readdir(root, { withFileTypes: true })) {
  • 读取本地文件
    skill/backend/ygopro2-duel.mjs:1056
    const source = await readFile(path, 'utf8');
  • 读取本地文件
    skill/backend/ygopro2-duel.mjs:1071
    return (await stat(BUNDLED_CLIENT_EXECUTABLE)).isFile() ? BUNDLED_CLIENT_EXECUTABLE : null;
  • 执行外部命令来自配置/变量
    skill/backend/ygopro2-duel.mjs:1115
    const child = spawn(clientExecutable, ['-n', name, '-h', host, '-p', String(runner.hostPort), '-j'], {
  • 执行外部命令固定命令
    skill/backend/ygopro2-duel.mjs:1142
    execFile('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', script], { windowsHide: true, timeout: 10000 }, (error, stdout) => {
  • 读取本地文件
    skill/runtime/combo-simulator.cjs:197
    return candidatePaths.find((candidate) => fs.existsSync(candidate)) ?? candidatePaths[0];
  • 写入本地文件
    skill/runtime/combo-simulator.cjs:1201
    fs.mkdirSync(path.dirname(outPath), { recursive: true });
  • 写入本地文件
    skill/runtime/combo-simulator.cjs:1202
    fs.writeFileSync(outPath, Buffer.from(bytes));
  • 读取本地文件
    skill/runtime/combo-simulator.cjs:1212
    if (!filePath || !fs.existsSync(filePath) || !fs.statSync(filePath).isFile()) {
  • 读取本地文件
    skill/runtime/combo-simulator.cjs:1229
    return uniq(candidates.filter((p) => fs.existsSync(p) && fs.statSync(p).isDirectory()));
  • 读取本地文件
    skill/runtime/combo-simulator.cjs:1263
    const text = fs.readFileSync(filePath, 'utf8');
  • 读取本地文件
    skill/runtime/combo-simulator.cjs:1343
    if (fs.existsSync(fullPath)) return fullPath;
  • 读取本地文件
    skill/runtime/combo-simulator.cjs:2440
    if (fs.existsSync(metaPath) && fs.existsSync(binaryPath)) {
  • 写入本地文件
    skill/runtime/combo-simulator.cjs:2487
    fs.mkdirSync(ROOT_SNAPSHOT_CACHE_DIR, { recursive: true });
  • 写入本地文件
    skill/runtime/combo-simulator.cjs:5565
    fs.mkdirSync(path.dirname(filePath), { recursive: true });
  • 写入本地文件
    skill/runtime/combo-simulator.cjs:5566
    fs.appendFileSync(
  • 执行外部命令来自配置/变量
    skill/runtime/combo-simulator.cjs:7005
    const child = fork(__filename, ['--child-worker'], {
  • 写入本地文件
    skill/runtime/combo-simulator.cjs:7820
    fs.mkdirSync(WEB_ARCHIVE_DIR, { recursive: true });
扫描于 2026/10/31(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-app-boot@deepseek-ai/dsh-system-prompt@deepseek-ai/dsh-tools@deepseek-ai/dsh-skill@deepseek-ai/dsh-llm@deepseek-ai/dsh-agent-preset@deepseek-ai/cordis
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 卡片研究
  • 卡组分析
  • 决斗验证

README

由 DeepSeek 最新模型翻译生成
YGO Tools for DSH DeepSeek Harness 的游戏王插件:查卡、卡组分析、Combo 推演、录像复盘,以及在 YGOPro2 里和模型对局。 插件把卡片数据、禁限表、卡组管理和 OCG 规则引擎接入模型。模型给出的操作都会在规则引擎里检查是否合法。 安装 Release 提供两个安装包,插件代码相同: | 安装包 | 内容 | | integrated | 插件 + YGOPro2 客户端(不含卡图),不需要另装 YGOPro2 | | external | 只有插件,对局时使用本机已安装的 YGOPro2 | v1.5.x 适配 DSH 0.2.x(桌面版默认 profile 为 desktop,命令行启动的 Web 版一般为 web)。DSH 0.1.x 请安装 v1.4.0。
展开完整文档(README 剩余 1 节)
YGO Tools for DSH

DeepSeek Harness 的游戏王插件:查卡、卡组分析、Combo 推演、录像复盘,以及在 YGOPro2 里和模型对局。

插件把卡片数据、禁限表、卡组管理和 OCG 规则引擎接入模型。模型给出的操作都会在规则引擎里检查是否合法。

安装

Release 提供两个安装包,插件代码相同:

| 安装包 | 内容 |
| integrated | 插件 + YGOPro2 客户端(不含卡图),不需要另装 YGOPro2 |
| external | 只有插件,对局时使用本机已安装的 YGOPro2 |

v1.5.x 适配 DSH 0.2.x(桌面版默认 profile 为 desktop,命令行启动的 Web 版一般为 web)。DSH 0.1.x 请安装 v1.4.0。

附带客户端
dsh plugin --profile desktop add "https://github.com/mellfy-puppy/ygo-tools-for-dsh/releases/download/v1.5.1/ygo-tools-for-dsh-1.5.1-integrated.tgz"

不带客户端
dsh plugin --profile desktop add "https://github.com/mellfy-puppy/ygo-tools-for-dsh/releases/download/v1.5.1/ygo-tools-for-dsh-1.5.1-external.tgz"

也可以在 DSH 设置的插件页面填入上面的地址安装。安装后新建会话,选择“游戏王模式”;如果没有出现,重启 DSH 后再新建会话。

与 AI 对局

在 DSH 里让模型载入卡组并开房,YGOPro2 会自动打开并进入房间,点准备即可开始。

flowchart LR
A[DSH 对话] -->|开房| B[AI.Server]
B --- C[模型的 WindBot] B --- D[你的 YGOPro2]

- 对局开始后 DSH 会话自动继续,不需要再回 DSH 输入“开始”。
- 模型的每一步操作都显示在 DSH 对话里;游戏内聊天会转给模型,模型也能回复。
- 只有一个选项的决策(例如只能选“不连锁”)由插件直接处理,不再询问模型。
- 服务端和模型使用的 WindBot 随插件附带,使用插件内的卡库。更新卡库后,下次开房即生效。
- integrated 包只使用自带的客户端;external 包会查找本机安装的 YGOPro2,找不到时模型会给出房间地址,手动加入即可。

[!IMPORTANT]
房间默认只监听 127.0.0.1。设置 bindAddress:"0.0.0.0" 可让局域网内的电脑加入,房间没有密码。

其他功能

- 卡片:查询卡文、属性、数值,读取禁限表;正式卡和先行卡可联网增量更新。
- 卡组:载入、检查、编辑、导出 YDK。
- 推演:创建局面、固定起手、查看合法动作并执行,支持检查点回滚和分支比较。
- 复盘:解析 YRP 录像;learnDeck 可把复盘结论保存为与卡组绑定的 Skill,下次载入同一卡组时自动使用。

工具

| 类别 | 工具 |
| 卡片 | queryCards manageCardDataSources getBanlistContext |
| 卡组 | manageSessionDeck learnDeck |
| 决斗 | resetGame observeDuel executeAction simulateActions |
| 状态 | manageCheckpoint manageEngineSession |
| 分析 | analyzeCombo analyzeReplay saveArtifact |
| 对局 | manageYgoPro2(discover status host wait chat close) |

运行方式

规则引擎在独立进程中运行(127.0.0.1:19981),第一次调用 YGO 工具时启动,DSH 重启后不受影响。决斗状态默认只保存在内存里,只有明确要求时才导出文件。

从源码打包

node scripts/build-release.mjs external
node scripts/build-release.mjs integrated --client <YGOPro2 安装目录>

integrated 会去掉卡图、录像、卡组、客户端自带的 AI 和个人配置,再写入插件卡库。输出在 dist/。

项目结构

lib/ 插件入口、DSH 技能说明 skill/backend/ 工具、会话、引擎服务与 YGOPro2 桥接 skill/resources/lib/ 卡库、禁限表与卡片脚本 skill/resources/ygopro2-bridge/ AI.Server 与模型用的 WindBot skill/vendor/ 随包附带的运行依赖 scripts/build-release.mjs 打包脚本 tests/ 自动化测试

许可

插件代码使用 0BSD。AI.Server 和集成包内的 YGOPro2 客户端(YGOProUnity_V2)为 GPLv3,许可证随包附带。卡片数据库、禁限表和卡片脚本遵循各自上游项目的许可。卡图不随包分发。
预览分享卡片长什么样 ↓mellfy-puppy/ygo-tools-for-dsh
分享 · DeepSeek Harness Hub
mellfy-puppy/ygo-tools-for-dsh

面向 DeepSeek Harness 的游戏王卡片研究、卡组分析与决斗验证工具

回到顶部