织墨 InkWeaver — 以本地化为核心的长篇小说创作空间,章节连贯性持续保持,审阅有据可查,带运行日志,还有经过审阅的 DSH 插件
31.4/100
综合分
2
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/9 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
该插件未发布到 npm,按作者文档从 GitHub 源安装即可(静态检查只覆盖 npm 路径,不代表插件不可用)。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add shuishuipingan/InkWeaver该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · browser
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 26 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装仓库 package.json 标记 private,未发布到 npm,需从源码安装
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包inkweaver(未发布到 npm,仅可源码安装)
✓Node 引擎要求 >=20 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明
源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/12 21:21:31
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 104 处,展示前 88 条)
- 读取本地文件electron/controllers/import-controller.ts:92
const stats = statSync(canonicalLocation, { bigint: true }) - 读取本地文件electron/controllers/import-controller.ts:504
const selectedSize = statSync(identity.canonicalLocation).size - 读取密钥环境变量electron/embedding.ts:196
const token = process.env.AI_NOVEL_RELEASE_SMOKE_TOKEN - 发起网络请求electron/embedding.ts:287
const res = await fetch(url, { - 发起网络请求electron/embedding.ts:323
const res = await fetch(url, { - 发起网络请求electron/llm/gemini-provider.ts:116
const res = await fetch(url, { - 发起网络请求electron/llm/gemini-provider.ts:214
const res = await fetch(url, { - 发起网络请求electron/llm/openai-provider.ts:84
const res = await fetch(url, { - 发起网络请求electron/llm/openai-provider.ts:155
const res = await fetch(url, { - 读取本地文件electron/mcp/mcp-manager.ts:126
const raw = await readFile(path, 'utf-8') - 执行外部命令来自配置/变量electron/mcp/mcp-manager.ts:205
const proc = spawn(command, args, { - 读取本地文件electron/security/windows-safe-file-system.ts:146
const information = statSync(canonicalRoot, { bigint: true }) - 读取本地文件electron/security/windows-safe-file-system.ts:262
if (packagedPath && existsSync(packagedPath)) return packagedPath - 读取本地文件electron/security/windows-safe-file-system.ts:267
if (existsSync(sourcePath)) return sourcePath - 执行外部命令来自配置/变量electron/security/windows-safe-file-system.ts:302
return spawn(command, args, { - 读取本地文件electron/security/windows-safe-file-system.ts:518
|| !existsSync(packagedPath) - 读取本地文件electron/security/windows-safe-file-system.ts:524
if (!existsSync(helperPath)) throw secureError('SECURE_FS_HELPER_UNAVAILABLE') - 读取本地文件electron/services/project-snapshot-service.ts:60
const info = await lstat(destinationPath) - 读取本地文件electron/services/project-snapshot-service.ts:62
const entries = await readdir(destinationPath) - 读取本地文件electron/services/project-snapshot-service.ts:72
const entries = await readdir(current, { withFileTypes: true }) - 读取本地文件electron/services/project-snapshot-service.ts:78
const bytes = await readFile(path.join(root, child)) - 写入本地文件electron/services/project-snapshot-service.ts:92
await mkdir(root, { recursive: true }) - 读取本地文件electron/services/project-snapshot-service.ts:102
if ((await stat(source)).isDirectory()) await cp(source, path.join(root, relative), { recursive: true, force: true }) - 写入本地文件electron/services/project-snapshot-service.ts:116
await writeFile(path.join(root, 'manifest.json'), JSON.stringify(manifest, null, 2), 'utf8') - 读取本地文件electron/services/project-snapshot-service.ts:125
try { entries = await readdir(root, { withFileTypes: true }) } catch { return [] } - 删除本地文件递归electron/services/project-snapshot-service.ts:162
await rm(target, { recursive: true, force: true }) - 写入本地文件electron/services/project-snapshot-service.ts:229
await mkdir(destination, { recursive: true }) - 写入本地文件electron/services/project-snapshot-service.ts:234
await mkdir(path.dirname(target), { recursive: true }) - 写入本地文件electron/services/project-snapshot-service.ts:235
await copyFile(source, target) - 写入本地文件electron/services/project-snapshot-service.ts:237
await writeFile(path.join(destination, 'manifest.json'), JSON.stringify(manifest, null, 2), 'utf8') - 写入本地文件electron/services/runtime-log-writer.ts:9
appendFile(filePath: string, data: string, encoding?: BufferEncoding): void | Promise<void> - 写入本地文件electron/services/runtime-log-writer.ts:10
mkdir(directory: string, options?: { recursive?: boolean }): void | Promise<void> - 读取本地文件electron/services/runtime-log-writer.ts:12
readdir(directory: string): string[] | Promise<string[]> - 读取本地文件electron/services/runtime-log-writer.ts:13
stat(filePath: string): { size: number } | Promise<{ size: number }> - 写入本地文件electron/services/runtime-log-writer.ts:14
rename(from: string, to: string): void | Promise<void> - 写入本地文件electron/services/runtime-log-writer.ts:16
writeFile(filePath: string, data: string, encoding?: BufferEncoding): void | Promise<void> - 写入本地文件electron/services/runtime-log-writer.ts:21
appendFile: async (filePath, data, encoding = 'utf8') => { await appendFile(filePath, data, encoding) }, - 写入本地文件electron/services/runtime-log-writer.ts:22
mkdir: async (directory, options) => { await mkdir(directory, options) }, - 读取本地文件electron/services/runtime-log-writer.ts:25
await stat(filePath) - 读取本地文件electron/services/runtime-log-writer.ts:31
readdir: directory => readdir(directory), - 读取本地文件electron/services/runtime-log-writer.ts:32
stat: filePath => stat(filePath), - 删除本地文件electron/services/runtime-log-writer.ts:34
unlink: filePath => unlink(filePath), - 读取本地文件electron/services/runtime-log-writer.ts:36
readFile: (filePath, encoding = 'utf8') => readFile(filePath, encoding), - 读取本地文件plugins/inkweaver-dsh/src/novel-migration.ts:321
const configured = await lstat(root) - 读取本地文件plugins/inkweaver-dsh/src/novel-migration.ts:331
canonical = await realpath(root) - 读取本地文件plugins/inkweaver-dsh/src/novel-migration.ts:344
const value = await lstat(path) - 读取本地文件plugins/inkweaver-dsh/src/novel-migration.ts:358
const value = await lstat(path) - 读取本地文件plugins/inkweaver-dsh/src/novel-migration.ts:362
return await readFile(path) - 读取本地文件plugins/inkweaver-dsh/src/novel-migration.ts:380
const entries = await readdir(directory, { withFileTypes: true }) - 写入本地文件plugins/inkweaver-dsh/src/novel-migration.ts:561
await mkdir(archivePath, { recursive: true, mode: 0o700 }) - 写入本地文件plugins/inkweaver-dsh/src/novel-migration.ts:566
await mkdir(join(destination, '..'), { recursive: true, mode: 0o700 }) - 删除本地文件plugins/inkweaver-dsh/src/novel-migration.ts:575
await rm(temporary, { force: true }) - 写入本地文件plugins/inkweaver-dsh/src/novel-migration.ts:577
await writeFile(temporary, record.bytes, { flag: 'wx', mode: 0o600 }) - 删除本地文件plugins/inkweaver-dsh/src/novel-migration.ts:592
await rm(temporary, { force: true }) - 删除本地文件plugins/inkweaver-dsh/src/novel-migration.ts:614
rm(path, { force: true }), - 删除本地文件plugins/inkweaver-dsh/src/novel-migration.ts:615
rm(`${path}-journal`, { force: true }), - 删除本地文件plugins/inkweaver-dsh/src/novel-migration.ts:616
rm(`${path}-wal`, { force: true }), - 删除本地文件plugins/inkweaver-dsh/src/novel-migration.ts:617
rm(`${path}-shm`, { force: true }), - 写入本地文件plugins/inkweaver-dsh/src/novel-project.ts:429
await mkdir(projectDir, { recursive: true, mode: 0o700 }) - 写入本地文件plugins/inkweaver-dsh/src/novel-project.ts:477
await mkdir(parent, { recursive: true, mode: 0o700 }) - 读取本地文件plugins/inkweaver-dsh/src/novel-project.ts:514
text = normalizeText(await readFile(filename, { encoding: 'utf8', signal })) - 读取本地文件plugins/inkweaver-dsh/src/novel-project.ts:621
const entries = await readdir(directory, { withFileTypes: true }) - 读取本地文件plugins/inkweaver-dsh/src/novel-project.ts:640
canonical = await realpath(this.#root) - 读取本地文件plugins/inkweaver-dsh/src/novel-project.ts:653
if ((await lstat(path)).isSymbolicLink()) { - 读取本地文件plugins/inkweaver-dsh/src/novel-project.ts:687
await lstat(path) - 读取本地文件plugins/inkweaver-dsh/src/novel-store.ts:1967
const existing = await lstat(projectDirectory) - 写入本地文件plugins/inkweaver-dsh/src/novel-store.ts:1978
await mkdir(projectDirectory, { recursive: true, mode: 0o700 }) - 读取本地文件plugins/inkweaver-dsh/src/novel-store.ts:1979
const created = await lstat(projectDirectory) - 读取本地文件plugins/inkweaver-dsh/src/novel-store.ts:1986
const existingIgnore = await lstat(gitignore) - 读取本地文件plugins/inkweaver-dsh/src/novel-store.ts:1990
const existing = await readFile(gitignore, 'utf8') - 删除本地文件plugins/inkweaver-dsh/src/novel-store.ts:2069
rm(path, { force: true }), - 删除本地文件plugins/inkweaver-dsh/src/novel-store.ts:2070
rm(`${path}-journal`, { force: true }), - 删除本地文件plugins/inkweaver-dsh/src/novel-store.ts:2071
rm(`${path}-wal`, { force: true }), - 删除本地文件plugins/inkweaver-dsh/src/novel-store.ts:2072
rm(`${path}-shm`, { force: true }), - 读取本地文件plugins/inkweaver-dsh/src/novel-store.ts:3227
canonicalRoot = await realpath(root) - 读取本地文件plugins/inkweaver-dsh/src/novel-store.ts:3234
const databaseFile = await lstat(databasePath) - 删除本地文件plugins/inkweaver-dsh/src/novel-store.ts:3379
rm(databasePath, { force: true }), - 删除本地文件plugins/inkweaver-dsh/src/novel-store.ts:3380
rm(`${databasePath}-journal`, { force: true }), - 写入本地文件plugins/inkweaver-dsh/src/preset-installer.ts:58
await mkdir(presetRoot, { recursive: true, mode: 0o700 }) - 读取本地文件plugins/inkweaver-dsh/src/preset-installer.ts:64
const contents = await readFile(join(templateRoot, filename), 'utf8') - 写入本地文件plugins/inkweaver-dsh/src/preset-installer.ts:69
await rename(stagingRoot, targetRoot) - 删除本地文件递归plugins/inkweaver-dsh/src/preset-installer.ts:78
if (!published) await rm(stagingRoot, { recursive: true, force: true }) - 读取本地文件plugins/inkweaver-dsh/src/preset-installer.ts:137
targetStat = await lstat(targetRoot) - 读取本地文件plugins/inkweaver-dsh/src/preset-installer.ts:144
const entries = (await readdir(targetRoot)).sort() - 读取本地文件plugins/inkweaver-dsh/src/preset-installer.ts:150
const entry = await lstat(join(targetRoot, filename)) - 读取本地文件plugins/inkweaver-dsh/src/preset-installer.ts:153
readFile(join(templateRoot, filename)), - 读取本地文件plugins/inkweaver-dsh/src/preset-installer.ts:154
readFile(join(targetRoot, filename)), - 发起网络请求src/services/blueprint-title-batch.ts:292
const result = await input.request(targets, maxTokens, repairHint)
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 长篇小说创作工作台
- 章节连续性维护
- 证据支撑审阅
README
由 DeepSeek 最新模型翻译生成织墨 / InkWeaver
织墨 InkWeaver 是一款本地优先的桌面工作台,面向长篇小说创作。它把项目设定、角色、世界观、章节蓝图、正文、审稿、修订与定稿组织成可追溯的创作链,让你在保留最终决定权的前提下使用自己选择的 AI 模型。
当前版本:v1.4.8
长篇写作的资料选择与预算说明
把一本长篇小说写成会持续发展的整体。 InkWeaver 是本地优先的 AI 小说创作工作台:它把故事设定、角色状态、章节蓝图、候选草稿、证据化审稿和作者定稿串成一条可追溯的连续写作链。
v1.4.8 修复写稿前的「缺少当前状态证据」提示对首次登场的角色也报出的纯噪音。此前只写到第 1 章、批量创作第 2-5 章时,第 3、4 章会各弹出一条「[信息不足] 缺少当前状态证据 · 蓝图安排‘赵阔’出场…」——这条检查的文案自己就写着“需要补充状态或说明这是首次出场”,已经承认首次出场是合法情况,却仍要求作者逐条手动确认,于是任何新角色第一次登场都必然产生一条只要求“确认它是新的”的提示。现在该提示只在“本应有记录、却没有”时才报:角色必须在更早的已定稿章节里出场过,而本章没有适用的状态记录。首次登场不再报;已经出场过、状态缺失的情况仍然报。判据只认已经写下的章节(同一批次里还没写的下一章不算),因此赵阔在第 3、4 章的两条提示都不会再出现。
展开完整文档(README 剩余 1 节)
织墨 / InkWeaver 织墨 InkWeaver 是一款本地优先的桌面工作台,面向长篇小说创作。它把项目设定、角色、世界观、章节蓝图、正文、审稿、修订与定稿组织成可追溯的创作链,让你在保留最终决定权的前提下使用自己选择的 AI 模型。 当前版本:v1.4.8 长篇写作的资料选择与预算说明 把一本长篇小说写成会持续发展的整体。 InkWeaver 是本地优先的 AI 小说创作工作台:它把故事设定、角色状态、章节蓝图、候选草稿、证据化审稿和作者定稿串成一条可追溯的连续写作链。 v1.4.8 修复写稿前的「缺少当前状态证据」提示对首次登场的角色也报出的纯噪音。此前只写到第 1 章、批量创作第 2-5 章时,第 3、4 章会各弹出一条「[信息不足] 缺少当前状态证据 · 蓝图安排‘赵阔’出场…」——这条检查的文案自己就写着“需要补充状态或说明这是首次出场”,已经承认首次出场是合法情况,却仍要求作者逐条手动确认,于是任何新角色第一次登场都必然产生一条只要求“确认它是新的”的提示。现在该提示只在“本应有记录、却没有”时才报:角色必须在更早的已定稿章节里出场过,而本章没有适用的状态记录。首次登场不再报;已经出场过、状态缺失的情况仍然报。判据只认已经写下的章节(同一批次里还没写的下一章不算),因此赵阔在第 3、4 章的两条提示都不会再出现。保留此前的长篇写作资料选择说明、工作流审计修复与安全审计收据。同一 Release 提供 Windows、macOS 和 Linux x64;DSH 插件沿用 v1.2.0,不发布 npm。 下载 v1.4.8 · 三分钟开始第一章 · 全书方向调整指南 · 安装 DSH 插件 · 提交问题或建议 · 参与讨论 InkWeaver 欢迎页 InkWeaver continuous writing loop 适合谁 - 想写中长篇、连载或多卷小说,希望角色、伏笔和世界规则不会在章节之间丢失的作者; - 需要把 AI 当作可审核的创作助手,而不是一键替自己定稿的作者; - 希望项目资料留在本机,并且能在每次模型调用、审稿、恢复和导出后追溯依据的人。 不适合谁 - 只想在线聊天、临时生成一段文字,不需要项目结构或章节连续性的人; - 期待软件自带模型额度、在线阅读社区或自动保证文学质量的人。 三分钟理解工作流 1. 新建作品并填写题材、写作语言、目标章节数和创作策略; 2. 维护角色、世界观、故事线和章节蓝图; 3. 生成候选草稿,查看上下文和来源收据; 4. 让 AI 提交结构化审稿意见,由作者确认需要处理的项目; 5. 对比修订并定稿,下一章只读取已经确认的连续性事实。 接手开发或深入维护时,再阅读项目文件指南、1.2.0 完整功能与验收图、全局日志验收收据和GitHub/分发核验收据。逐项用户可见更新见更新日志;参与开发请看贡献指南,规划请看Roadmap。 如果这个工作流正好解决你的长篇创作问题,欢迎先用样例项目走完一章,再通过 Issue 或 Discussions 分享可复现的体验;觉得方向有价值也可以在 GitHub 上点 Star,帮助更多作者找到它。 织墨解决什么问题 普通聊天工具擅长生成一段文字,却很难长期维护小说中的角色状态、世界规则、章节计划和前后因果。织墨提供的是创作编排层:项目资料有明确归属,生成任务有上下文和状态,审稿意见由作者确认,定稿结果会继续成为后续章节的事实来源。 它不是模型服务,也不是在线小说平台。软件不附带模型额度;你可以连接本地模型或自己拥有权限的云端模型。项目数据默认保存在本机。 创作流程 1. 建立故事前提、题材、写作语言和创作策略。 2. 生成或编辑角色、人物关系、世界观和故事架构。 3. 规划全书目录与逐章蓝图。 4. 按章节选择模型和目标字数生成草稿。 5. 让 AI 提交结构化审稿意见,由作者编辑、忽略、补充并确认。 6. 根据人工确认的清单修稿,通过差异对比决定是否合并。 7. 定稿章节,更新连续性事实、人物状态和伏笔进度,再进入下一章。 核心能力 - 长篇一致性上下文继承:故事前提、角色、世界观、蓝图与已定稿事实会进入后续创作,减少设定遗失和前后矛盾。 - 伏笔与叙事线索系统:记录计划、埋设、推进、回收与超期线索,让长线悬念可以检查和兑现。 - 章节模型与字数控制:单章和连续写作都使用本次选择的模型与目标字数;相同目标的重复任务会被阻止。 - 人工审稿闭环:AI 审稿不是自动改稿。作者先确认问题清单,再修稿、检查差异并决定最终文本。 - 参考资料与知识库:支持导入 TXT、Markdown 和 EPUB;可下载内置本地向量模型离线检索(首次运行可选,无需 API Key,GPU → 核显 → CPU 自动选择),也可使用自己的 API 向量模型,或在没有向量来源时使用全文检索。 - 角色卡与关系图:维护结构化人物事实,关系图支持缩放、平移和一键清空。 - 可恢复任务:长时间生成、批量章节、导入、单章写稿、人物提取、审稿、审稿驱动修稿、只读修稿、定稿、定稿后处理修复、架构生成、配置生成和章节蓝图生成都有不含正文的恢复收据;恢复时重新读取权威来源或安全启动参数,并校验项目 lease,避免旧任务写入错误项目。 - 中英文界面:界面语言与小说写作语言相互独立。 - 更准确的失败提示:内容限制、模型调用失败、上下文预算不足和资源冲突不会被伪装成成功结果。 1.2.0 创作与日志体验 1.2.0 的验收目标,是让一部长篇小说保持「持续发展」的阅读感,同时让每一次模型调用、作者决定和失败恢复都留下可追溯证据。新能力按作者实际工作顺序组织: - 阶段化 Writing Skill:Skill 可以作为独立 SKILL.md 安装、卸载和重新加载,并标明 planning、drafting、review、polish 阶段;Agent 面板按当前阶段筛选,用户 Skill 与项目 Skill 仍受路径和项目会话隔离。 - 主线/支线故事线视图:每条叙事线显示 planned、planted、progressing、resolved 或 dormant/overdue 的投影进度、下一目标章节和事件数;事件行保留定稿草稿 ID、正文指纹和证据,点击「打开证据」前会重新验证当前项目会话。 - 规划资料导入:大纲、世界观、人物表、时间线和风格说明可导入当前项目。导入先形成带 SHA-256 的 candidate,只有作者显式确认后才进入蓝图和后续写作上下文;重复内容幂等,冲突和拒绝均可回读。 - 角色权威边界:蓝图明确列出的角色和作者确认的候选才可进入角色表;模型在定稿后发现的新角色只进入候选队列,不会自动写入 roster。每次状态变化追加 author/model/legacy-unknown 来源、定稿 ID、正文 hash 和证据区间。 - 完整中文长篇链:项目会话、写作语言、界面语言、模型 lease 和来源指纹从蓝图、草稿、审稿、修订到定稿保持一致;草稿待审、作者确认和自动定稿是可见的不同阶段,不会把候选稿伪装成定稿。 - 四层章节材料:写前上下文把作者任务、未来计划、定稿历史、未定稿候选稿和相邻正文片段分开显示;每层有 source span、纳入/省略原因和覆盖状态,预算不足或来源缺失不会静默吞掉作者硬性要求。 - 证据化审稿:蓝图关键事件逐项标记 completed、prepared、deferred、not-found 或 needs-verification,并附来源章节/正文证据;证据不足不会自动触发修稿,修订目标必须由作者明确勾选。 - 连续草稿血缘:批量续写优先读取实际保存的候选稿 ID、版本和完整正文,下一章不读取或污染 finalized history;关闭、重启或切换标签页后仍按保存版本继续。 - 全局结构化日志:主进程、Renderer、IPC handle、工作流 UI、模型调用、更新器、MCP 子进程、文件/数据库边界、窗口生命周期、未捕获异常和 Promise 拒绝统一写入 append-only JSONL。日志包含事件 ID、进程/PID、序号、时间、run/project session/correlation ID、操作结果、耗时和错误链。 - 日志完整性与诊断:日志按日期/大小轮转并生成 SHA-256 manifest,重试队列和 emergency spool 防止磁盘/IPC 短暂失败静默丢失;重启回放去重,页查询显示 pending/degraded 状态,主进程可导出包含段、manifest、bundle 清单和缺口状态的完整诊断包。默认只存元数据,长字符串、路径和凭据会限长/脱敏。 - 并发、恢复与导出护栏:多标签保存、旧请求、过期恢复、非定稿导出、拆分目录残留、标题截断、更新队列覆盖和 Windows 辅助进程退出均有来源指纹、CAS、唯一临时目录或精确进程分类保护。 - Windows/macOS 更新:已打包 Windows x64、macOS arm64 和 macOS x64 使用同一 UpdateService 状态机;应用内检查、下载、安装、单飞排队和已下载版本单调性均有日志和失败分类。 1.1.0 创作体验 1.1.0 的目标,是让长篇小说读起来像一个持续发展的整体,而不是一章章互不相干的生成结果。当前已经落地的开发能力包括: - 章节连续性工作单:为每章记录场景进入状态、目标、阻碍、选择、后果和离开状态,并区分作者计划、AI 候选、作者确认和正文实际;同一工作单还可以记录卷级主线/支线贡献、人物情绪余波、读者期待和多视角落点。 - 证据化章节交接:前章定稿的地点、视角、未完成动作、即时目标、情绪和待回应问题带有来源正文证据;来源定稿变化后,旧交接不会继续冒充最新事实。 - 连读与重复提示:连续阅读器按定稿权威顺序合并章节,显示章节边界、搜索、阅读位置和回到编辑器入口;重复开头、重复结尾或连续天气开场只作为建议,作者可以明确保留刻意复沓。 - 分层写前上下文:上下文按完整条目裁剪,不会把证据或否定词从中间截断;AI 输出面板会显示哪些条目纳入、哪些因不相关或预算省略,且收据不复制私人正文。 - 知情范围与误信:角色知道的事实、信念、传闻和误信分开保存,附获知方式、来源章节、有效范围和证据;只有作者确认且在当前章节生效的知识才会注入写稿。 - 安全历史修订:历史正文变化会列出受影响的连续性投影、章节交接和叙事线;修稿 Proposal 绑定基准正文指纹,正文变化后拒绝合并旧修稿。 - 人物候选字段审核:全文提取的角色候选保留字段证据、别名、关系和当前状态;作者可以逐字段勾选,未勾选内容不会写入权威角色卡。角色改名通过稳定 characterId 保留旧名和关系引用。 - 关系图工作台:支持姓名/别名搜索、一跳和二跳聚焦、关系类型过滤、键盘列表、节点固定/取消固定、项目级布局保存和重置;有向关系可以显示箭头、来源章节和正文证据。 - 一致性快照与无蓝图导出:SQLite 使用 backup API 创建一致性快照并记录文件哈希;即使没有章节蓝图,也能按 finalized authority 顺序导出定稿正文。 这些能力已通过内部工程验收;真实模型文学质量不在本轮发布声明内,作者仍应对事实、风格、版权和最终定稿负责。 模型连接 织墨支持两类请求协议: - OpenAI-compatible:用于 OpenAI、DeepSeek、Ollama、NovelAI 预设及其他兼容 Chat Completions 的服务。 - Gemini 原生协议:用于 Google Gemini 兼容端点。 模型高级设置会根据已知能力提供推理强度、温度、结构化输出和最大输出长度等选项。填写 API Key 与 Base URL 后可以获取模型列表。自定义地址仍需符合以上协议之一,不能把任意 HTTP 接口直接当作模型服务。 Ollama 推荐使用 Ollama 的 OpenAI-compatible 地址: Provider: Ollama(本地)或自定义 Protocol: OpenAI-compatible Base URL: http://127.0.0.1:11434/v1 Model: 你的 Ollama 模型名,例如 qwen3:14b NovelAI NovelAI 目前属于最小兼容支持。请使用自己的 Persistent API Token 和账户实际可用的模型标识。项目不会向该端点发送标准 response_format;由于维护者无法使用用户账户完成资格验证,模型权限和接口差异请以 NovelAI 官方资料为准。 数据与隐私 | 数据 | 默认位置或去向 | | 小说设定、角色、蓝图、草稿、审稿和定稿 | 项目目录内的本地 SQLite 数据库与定稿文本 | | 知识库索引 | 项目目录内的本地 LanceDB 数据 | | 模型和 API Key 配置 | 本机用户目录 ~/.vela/models.json | | 应用偏好 | 本机用户目录 ~/.vela/config.json | | 本地模型请求 | 你配置的本机或局域网推理服务 | | 云端模型请求 | 你主动选择的模型供应商 | 渲染界面不能直接读取 API Key。文件、数据库和模型请求由 Electron 主进程执行;访问项目外文件必须由用户通过系统选择器授权。 安装与更新 Windows x64 从 GitHub Releases 下载: inkweaver-setup-<版本号>.exe Windows 版本支持应用内检查、下载和安装更新。当前安装包未代码签名,系统可能显示发布者或信誉提示;继续前请确认下载来自项目官方 Release。 macOS Apple Silicon 与 Intel 分别使用: inkweaver-mac-arm64-<版本号>-installer.dmg inkweaver-mac-x64-<版本号>-installer.dmg 当前 macOS 安装包未代码签名(未使用 Developer ID 签名)且未公证。请只从正式 v1.4.8 Release下载,并按系统安全提示确认首次打开。桌面 Release 共 13 项资产,覆盖 Windows x64、macOS Apple Silicon、macOS Intel 和 Linux x64;DSH 插件 tarball 保留在 v1.2.0 Release。 Linux x64 v1.4.8 Linux 资产仅以 x64 构建。本次资格验证使用 Ubuntu 22.04、Debian 13 和 Fedora 44;不据此声明其他发行版或 Linux ARM64 已验证。包以 Ubuntu 22.04 的 glibc 2.35 环境构建,资格记录会检查打包文件所需的最高 glibc 符号版本不高于 2.35。 从正式 v1.4.8 Release下载对应文件及各自的 SHA-256 校验文件: inkweaver-linux-x64-1.4.8.AppImage inkweaver-linux-x64-1.4.8.deb inkweaver-linux-x64-1.4.8.rpm AppImage 在 FUSE 可用时可直接启动。若系统没有 FUSE,可用内置提取运行模式: chmod +x inkweaver-linux-x64-1.4.8.AppImage ./inkweaver-linux-x64-1.4.8.AppImage --appimage-extract-and-run AppImage 使用用户命名空间 sandbox,系统需允许普通用户创建用户命名空间。若系统策略禁用了此能力,请使用对应的 deb/rpm 安装包。 Ubuntu/Debian 可安装 deb,Fedora 可安装 rpm: sudo apt install ./inkweaver-linux-x64-1.4.8.deb sudo dnf install ./inkweaver-linux-x64-1.4.8.rpm Linux 安装包未签名。下载后先在同一目录核对对应校验文件,例如: sha256sum -c inkweaver-linux-x64-1.4.8.deb.sha256 DeepSeek Harness 插件 仓库中的 @shuishuipingan/inkweaver-dsh@1.2.0 是独立的 DSH 插件,不是桌面版的替代品。它提供精简的项目设置、故事架构、人物、全书纲要、章节蓝图和章节正文流程;模型修改先进入 Proposal,由用户审核应用后才改变权威项目状态。本轮 1.2.0 不发布 npm,插件通过 GitHub Release tarball 和本地安装说明交付。 迁移提示:@ethanyoq/dsh-ai-novel-writer 是仓库迁移前的历史包名,不是 1.2.0 开发线的交付包;新安装请只使用 @shuishuipingan/inkweaver-dsh。DSH 宿主本身与 Web UI companion 由 DeepSeek Harness 生态维护,不属于本仓库的 npm 包。 dsh plugin --profile web add '<path-to-inkweaver-dsh-tarball.tgz>' dsh --profile web 插件使用独立的 .ai-novel 项目格式,不读取桌面版项目。完整说明见 插件文档。 正式 tarball:shuishuipingan-inkweaver-dsh-1.2.0.tgz,当前资格构建为 241,776 bytes、SHA-256 0b67def78e2660ad2e29840efa158132ec00d6ec51bc81f0ed36b4067515ad66;GitHub Release 资产必须逐字节复现该 digest。它兼容目前官方默认发布渠道的 @deepseek-ai/dsh@0.1.5-rc.1;外部 @linxin666/dsh-web-all@0.3.20 只是宿主 companion,不属于本项目交付物。 本地开发 需要 Node.js 20+ 和 pnpm 11: pnpm install pnpm dev 常用验证命令: pnpm typecheck pnpm test pnpm test:browser pnpm build 当前边界 - 不提供模型账号、云端额度、在线发布或阅读社区。 - 不保证所有第三方接口只修改 URL 和 Key 就能接入。 - AI 输出仍需作者进行事实、质量和版权判断。 - 重要作品在升级和迁移前应自行备份。 许可证 桌面应用使用 GPL-3.0。内嵌 DeepSeek Harness 插件使用独立 MIT 许可。
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
shuishuipingan/InkWeaver
织墨 InkWeaver — 以本地化为核心的长篇小说创作空间,章节连贯性持续保持,审阅有据可查,带运行日志,还有经过审阅的 DSH 插件
相关插件 · 浏览器
智能体插件框架deepseek-ai/deepseek-harness
DeepSeek Harnessdsh是由 DeepSeek AI 开发的开源 agent harness智能体框架。
★ 270,422已汉化DSH
71.9
多设备 Agent 看板YaoApp/yao
✨ 所有 Agent 和工作区集中管理,覆盖你的每一台设备。任务看板追踪进度,桌面端、移动端、浏览器、API…
★ 8,147已汉化DSH
71.2
可扩展侧边栏工作台omdsh-dev/DSH-better-sidebar
DSH 的双工作台:原生右侧栏 + 自绘底部面板,并把 ctx.betterSidebar 服务开放给所有插件
★ 4,761已汉化DSH
71.1
浏览器自动化桥Tencent/BrowserSkill
你的 Agent。你的浏览器。连接,就能协作。
★ 9,967已汉化DSH
71
AI 小说创作工作台EthanYoQ/AI-Novel-Writer
AI 小说作家 / AI Novel Writer
★ 1,591已汉化DSH
70.7
智能体浏览器引擎platonai/Browser4
DeepSeek Harness 集成
★ 1,175已汉化DSH
70.4
这是你的仓库?认领条目