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

NovelAI 绘坊 siriustl/dsh-novelai-atelier

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

在会话侧栏调用 NovelAI 生成与编辑插画

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

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

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add siriustl/dsh-novelai-atelier
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · tool
装得上吗
本站已在 dsh 0.2.1-rc.5 下真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 21 天前
档位由哪些信号合成

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

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

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

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 92 处,展示前 83 条)
  • 发起网络请求
    client/api.ts:25
    try { return await fetch(url, { credentials: 'same-origin', ...init }) }
  • 发起网络请求
    src/core/client.ts:185
    dispatcher = this.proxy ? new ProxyAgent(this.proxy) : undefined
  • 发起网络请求
    src/core/client.ts:188
    response = await fetch(target, opts)
  • 发起网络请求
    src/core/client.ts:276
    return await this.request('GET', url, init, signal)
  • 发起网络请求
    src/core/client.ts:330
    const response = await this.request('POST', this.imageUrl + endpoint, { json: payload }, signal)
  • 读取本地文件
    src/core/imageInputs.ts:51
    if (!existsSync(target) || !statSync(target).isFile()) throw new Error(`Image file does not exist: ${target}`)
  • 读取本地文件
    src/core/imageInputs.ts:51
    if (!existsSync(target) || !statSync(target).isFile()) throw new Error(`Image file does not exist: ${target}`)
  • 读取本地文件
    src/core/imageInputs.ts:52
    if (statSync(target).size > MAX_INPUT_BYTES) throw new Error('Input image exceeds the 48 MiB file limit')
  • 读取本地文件
    src/core/metadata.ts:37
    if (!existsSync(target) || !statSync(target).isFile() || statSync(target).size > 64 * 1024 * 1024)
  • 读取本地文件
    src/core/metadata.ts:37
    if (!existsSync(target) || !statSync(target).isFile() || statSync(target).size > 64 * 1024 * 1024)
  • 读取本地文件
    src/core/metadata.ts:39
    const data = readFileSync(target)
  • 读取本地文件
    src/core/operations.ts:138
    if (!existsSync(path) || !statSync(path).isFile()) throw new Error(`Vibe encoding file does not exist: ${path}`)
  • 读取本地文件
    src/core/operations.ts:138
    if (!existsSync(path) || !statSync(path).isFile()) throw new Error(`Vibe encoding file does not exist: ${path}`)
  • 读取本地文件
    src/core/operations.ts:139
    const data = readFileSync(path)
  • 读取本地文件
    src/core/operations.ts:177
    if (existsSync(receiptPath)) {
  • 读取本地文件
    src/core/operations.ts:178
    if (statSync(receiptPath).size > 1024 * 1024) throw new Error('Vibe receipt exceeds the size limit')
  • 读取本地文件
    src/core/operations.ts:180
    try { receipt = JSON.parse(readFileSync(receiptPath, 'utf8')) } catch { throw new Error('Invalid vibe JSON receipt') }
  • 写入本地文件
    src/core/preparation.ts:128
    mkdirSync(directory, { recursive: true })
  • 写入本地文件
    src/core/preparation.ts:132
    writeFileSync(imagePath, result.toPng())
  • 写入本地文件
    src/core/preparation.ts:140
    writeFileSync(maskPath, mask.toPng())
  • 写入本地文件
    src/core/preparation.ts:149
    writeFileSync(receipt, JSON.stringify({ request, result: response }, null, 2) + '\n', 'utf8')
  • 读取本地文件
    src/core/recovery.ts:53
    if (!existsSync(path) || !statSync(path).isFile() || !path.toLowerCase().endsWith('.json')) throw new Error('Receipt must be a local .json file')
  • 读取本地文件
    src/core/recovery.ts:53
    if (!existsSync(path) || !statSync(path).isFile() || !path.toLowerCase().endsWith('.json')) throw new Error('Receipt must be a local .json file')
  • 读取本地文件
    src/core/recovery.ts:54
    const raw = readFileSync(path)
  • 读取本地文件
    src/core/recovery.ts:72
    return { path, exists: existsSync(path) && statSync(path).isFile() }
  • 读取本地文件
    src/core/recovery.ts:72
    return { path, exists: existsSync(path) && statSync(path).isFile() }
  • 写入本地文件
    src/core/service.ts:38
    writeFileSync(tmp, content)
  • 写入本地文件
    src/core/service.ts:43
    renameSync(tmp, path)
  • 删除本地文件
    src/core/service.ts:55
    try { unlinkSync(tmp) } catch { }
  • 写入本地文件
    src/core/service.ts:158
    mkdirSync(directory, { recursive: true })
  • 写入本地文件
    src/core/service.ts:195
    writeFileSync(responsePath, response)
  • 写入本地文件
    src/core/service.ts:206
    writeFileSync(path, response)
  • 写入本地文件
    src/core/service.ts:222
    writeFileSync(rawPath, imageBytes)
  • 删除本地文件
    src/core/service.ts:254
    unlinkSync(responsePath)
  • 读取本地文件
    src/core/service.ts:326
    return JSON.parse(readFileSync(path, 'utf8')) as Record<string, unknown>
  • 读取本地文件
    src/core/specs.ts:24
    cached = JSON.parse(readFileSync(base, 'utf8')) as SpecCatalog
  • 读取本地文件
    src/workbench/app.ts:41
    if (existsSync(path)) return readFileSync(path, 'utf8')
  • 读取本地文件
    src/workbench/app.ts:41
    if (existsSync(path)) return readFileSync(path, 'utf8')
  • 写入本地文件
    src/workbench/assets.ts:20
    mkdirSync(this.directory, { recursive: true })
  • 读取本地文件
    src/workbench/assets.ts:66
    const [root, source] = await Promise.all([realpath(this.directory), realpath(frozenPath)])
  • 读取本地文件
    src/workbench/assets.ts:69
    const info = await stat(source)
  • 读取本地文件
    src/workbench/assets.ts:70
    if (!info.isFile() || info.size > MAX_ASSET || createHash('sha256').update(readFileSync(source)).digest('hex') !== digest)
  • 读取本地文件
    src/workbench/assets.ts:75
    if (!existsSync(path)) writeFileSync(path, data)
  • 写入本地文件
    src/workbench/assets.ts:75
    if (!existsSync(path)) writeFileSync(path, data)
  • 读取本地文件
    src/workbench/assets.ts:81
    if (!existsSync(source) || !statSync(source).isFile() || statSync(source).size > MAX_ASSET)
  • 读取本地文件
    src/workbench/assets.ts:81
    if (!existsSync(source) || !statSync(source).isFile() || statSync(source).size > MAX_ASSET)
  • 写入本地文件
    src/workbench/assets.ts:107
    if (!existsSync(target)) writeFileSync(target, data)
  • 发起网络请求
    src/workbench/assistant.ts:341
    response = await fetch(endpoint, {
  • 发起网络请求
    src/workbench/assistant.ts:578
    const result = await this.request(endpoint, apiKey, String(config['model']), messages, {
  • 读取本地文件
    src/workbench/backup.ts:73
    if (!existsSync(raw)) throw new Error('备份所需文件缺失:' + raw)
  • 读取本地文件
    src/workbench/backup.ts:74
    const data = readFileSync(raw)
  • 读取本地文件
    src/workbench/backup.ts:99
    if (!existsSync(value)) return
  • 写入本地文件
    src/workbench/backup.ts:176
    mkdirSync(directory, { recursive: true })
  • 写入本地文件
    src/workbench/backup.ts:179
    writeFileSync(target, zipped)
  • 读取本地文件
    src/workbench/backup.ts:187
    const raw = readFileSync(path)
  • 写入本地文件
    src/workbench/backup.ts:274
    mkdirSync(assetsDirectory, { recursive: true })
  • 写入本地文件
    src/workbench/backup.ts:276
    mkdirSync(output, { recursive: true })
  • 读取本地文件
    src/workbench/backup.ts:295
    if (!existsSync(target)) writeFileSync(target, bytes)
  • 写入本地文件
    src/workbench/backup.ts:295
    if (!existsSync(target)) writeFileSync(target, bytes)
  • 执行外部命令来自配置/变量
    src/workbench/reveal.ts:19
    const child = spawn(command, [path], { shell: false, stdio: 'ignore', windowsHide: false })
  • 读取本地文件
    src/workbench/reveal.ts:62
    const info = await stat(path)
  • 读取本地文件
    src/workbench/reveal.ts:64
    const bytes = await readFile(path)
  • 读取本地文件
    src/workbench/reveal.ts:74
    try { canonical = await realpath(candidate); if (!(await stat(canonical)).isFile()) continue }
  • 读取本地文件
    src/workbench/reveal.ts:74
    try { canonical = await realpath(candidate); if (!(await stat(canonical)).isFile()) continue }
  • 写入本地文件
    src/workbench/settings.ts:23
    mkdirSync(this.secretsDir, { recursive: true, mode: 0o700 })
  • 写入本地文件
    src/workbench/settings.ts:24
    chmodSync(this.secretsDir, 0o700)
  • 读取本地文件
    src/workbench/settings.ts:29
    if (create && !existsSync(path)) {
  • 读取本地文件
    src/workbench/settings.ts:30
    const encrypted = readdirSync(this.secretsDir).some((name) => name.endsWith('.secret')
  • 读取本地文件
    src/workbench/settings.ts:31
    && readFileSync(join(this.secretsDir, name), 'utf8').startsWith('NAI-SECRET-V1\n'))
  • 写入本地文件
    src/workbench/settings.ts:33
    try { writeFileSync(path, randomBytes(32), { flag: 'wx', mode: 0o600 }) } catch (error) {
  • 读取本地文件
    src/workbench/settings.ts:37
    const key = readFileSync(path)
  • 写入本地文件
    src/workbench/settings.ts:39
    chmodSync(path, 0o600)
  • 写入本地文件
    src/workbench/settings.ts:53
    writeFileSync(tmp, envelope, { flag: 'wx', mode: 0o600 })
  • 写入本地文件
    src/workbench/settings.ts:54
    try { renameSync(tmp, path) } catch (error) { try { unlinkSync(tmp) } catch { } throw error }
  • 删除本地文件
    src/workbench/settings.ts:54
    try { renameSync(tmp, path) } catch (error) { try { unlinkSync(tmp) } catch { } throw error }
  • 读取本地文件
    src/workbench/settings.ts:60
    if (!replaceExisting && existsSync(join(this.secretsDir, reference + '.secret'))) this.secret(reference)
  • 读取本地文件
    src/workbench/settings.ts:68
    const stored = readFileSync(join(this.secretsDir, reference + '.secret'), 'utf8')
  • 读取本地文件
    src/workbench/util.ts:81
    return JSON.parse(readFileSync(this.path, 'utf8')) as T
  • 写入本地文件
    src/workbench/util.ts:89
    mkdirSync(dirname(this.path), { recursive: true })
  • 写入本地文件
    src/workbench/util.ts:91
    writeFileSync(tmp, JSON.stringify(value))
  • 写入本地文件
    src/workbench/util.ts:93
    renameSync(tmp, this.path)
  • 删除本地文件
    src/workbench/util.ts:95
    try { unlinkSync(tmp) } catch { }
  • 读取本地文件
    src/workbench/util.ts:100
    exists(): boolean { return existsSync(this.path) }
扫描于 2026/11/4(0 天前) · 范围 全包扫描(包内未声明入口) · 来源 GitHub 仓库

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

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-scope@deepseek-ai/dsh-tools@deepseek-ai/schemastery
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

面向 DeepSeek Harness 的 NovelAI V5/V4.5 生图插件:内置 15 项 Agent 工具与嵌入式生图工作台

README

由 DeepSeek 最新模型翻译生成
DSH NovelAI Atelier 面向 DeepSeek Harness 智能体生态的 NovelAI V5 / V4.5 图像生成工具集与嵌入式工作台插件。 🌟 核心特性 - 🤖 15 项 Agent 原生工具:文生图(nai_generate_image)、全能图像编辑(nai_edit_image:含局部重绘、全图重绘、增强、2倍放大、导演线稿、Vibe编码)、参数回执恢复与检查(nai_image_info)、资料库与草稿管理等,专为大语言模型 Tool Calling 精心设计与压缩。 - 🎨 无缝嵌入式右侧工作台:深度注入 DSH 右侧栏抽屉(sidebarRightTabs),无需额外开启独立 Web 端口或后台服务,与当前 AI 会话实时共享内存草稿与上下文。 - 📚 模块化资料库(Library):支持角色本体定义、形态分支(服装/外形差异化继承)、画师风格混合、负面提示词解耦与例图可视化管理。 - ⏱️ 自动化生图计划(Schedules):支持单次、每日、定时间隔以及固定请求/AI 智能构思的自动化任务队列,内置额度与运行次数安全预算保护。 - 🔒 本地优先与隐私安全:NovelAI Token(pst-...)本机安全加密隔离存储;所有生成图片、元数据与工作台数据严格保存在本地用户目录。
展开完整文档(README 剩余 1 节)
DSH NovelAI Atelier

面向 DeepSeek Harness 智能体生态的 NovelAI V5 / V4.5 图像生成工具集与嵌入式工作台插件。

🌟 核心特性

- 🤖 15 项 Agent 原生工具:文生图(nai_generate_image)、全能图像编辑(nai_edit_image:含局部重绘、全图重绘、增强、2倍放大、导演线稿、Vibe编码)、参数回执恢复与检查(nai_image_info)、资料库与草稿管理等,专为大语言模型 Tool Calling 精心设计与压缩。
- 🎨 无缝嵌入式右侧工作台:深度注入 DSH 右侧栏抽屉(sidebarRightTabs),无需额外开启独立 Web 端口或后台服务,与当前 AI 会话实时共享内存草稿与上下文。
- 📚 模块化资料库(Library):支持角色本体定义、形态分支(服装/外形差异化继承)、画师风格混合、负面提示词解耦与例图可视化管理。
- ⏱️ 自动化生图计划(Schedules):支持单次、每日、定时间隔以及固定请求/AI 智能构思的自动化任务队列,内置额度与运行次数安全预算保护。
- 🔒 本地优先与隐私安全:NovelAI Token(pst-...)本机安全加密隔离存储;所有生成图片、元数据与工作台数据严格保存在本地用户目录。

📦 安装与配置

推荐:桌面客户端 GUI 一键安装

1. 从 Releases 页面 下载最新安装包 dsh-novelai-atelier-0.15.3.tgz 并保存到本地稳定路径。
2. 打开 DeepSeek Harness 左侧「插件」页面,点击「添加插件」。
3. 在「包名或地址」输入安装包的绝对路径(例如 D:\Downloads\dsh-novelai-atelier-0.15.3.tgz),点击安装。
4. 安装完成后点击「立即启用」。
5. 建议完整退出并重新打开 DSH,以保证宿主进程、原生图片依赖与前端模块完全加载生效。
6. 打开右侧抽屉栏的「NovelAI 生图工作台」,在设置中配置你的 NovelAI pst-… 令牌。

命令行(CLI)安装

在桌面客户端自带的 CLI 环境中执行(PowerShell 示例):

& 'D:\Program Files\DeepSeek Harness\resources\runtime\cli\bin\dsh.cmd' plugin --profile desktop add 'D:\Downloads\dsh-novelai-atelier-0.15.3.tgz'

详细的配置与版本迁移说明请参阅 安装指南 (INSTALL.md)。

🚀 常用生成与协作流程

1. 智能体按需启用

- 普通模式下默认仅加载轻量入口 nai_use_tools,不会占用额外 Context Token;
- 当需要生图或编辑时,AI 自动或手动调用 nai_use_tools({enabled:true}) 挂载完整能力;
- 也可以直接新建「NovelAI Atelier」专属预设模式会话。

2. 文生图与编辑

- 单张文生图:调用 nai_generate_image,默认采用 V5 Full、23 步、Euler Ancestral、Karras 调度、CFG 7,生成完毕直接返回图片路径。
- 图像编辑与重绘:通过 nai_edit_image 完成全图重绘(img2img)、局部重绘(inpaint,白色涂抹重绘)、细节增强(enhance)、2倍无损放大(upscale)或风格提取(encode_vibe)。
- 参数与回执回溯:使用 nai_image_info 的 recover 操作可直接从已生成的 PNG 或回执 JSON 中完美还原所有提示词、Seed、模型参数及参考图哈希。

3. 数据与隐私安全规范

- 默认工作台数据目录:~/.novelai-workbench
- 默认图片保存目录:~/Pictures/NovelAI
- 分发与共享提示:对外分发插件时只需提供官方打出的 .tgz 发布包。请勿将本机的私有工作台目录、凭据目录(secrets/)或整库备份对外共享。从画廊导出的作品原图可能包含提示词、Seed 及 EXIF 元数据,对外公开发布前请注意核对。

🛠️ 本地开发与质量验证

本项目采用严格的工程规范与测试驱动验证:

类型检查
pnpm run typecheck

运行自动化测试(52 文件 / 596 测试用例)
pnpm test

构建客户端与服务端 bundle
pnpm run build

验证包导出与安装包完整性
pnpm run verify:package

📄 开源许可证

本项目基于 MIT License 开源。
预览分享卡片长什么样 ↓siriustl/dsh-novelai-atelier
分享 · DeepSeek Harness Hub
siriustl/dsh-novelai-atelier

在会话侧栏调用 NovelAI 生成与编辑插画

这是你的仓库?认领条目

回到顶部