dsh-aivn
AIVN's stage engine inside DeepSeek Harness: a workspace is a play, the playwright preset writes Stage DSL, and a Stage tab in the conversation renders it live (backgrounds, sprites, dialog, stop-point choices, line-by-line TTS). dsh-aivn:把 AIVN 的舞台引擎装进 DSH——工作区就是一部剧目,剧作家预设写 Stage DSL,对话页的「舞台」tab 实时演出(背景、立绘、台词条、停止点选项、逐句语音)。 适合需要将DSL文本实时渲染为包含背景、立绘和台词的舞台剧的用户。
インストール
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:john-walks-slow/dsh-aivnドキュメント
README 全文を読む ↗dsh-aivn
把 AIVN 的舞台引擎装进 DSH。
一个工作区就是一部剧目:在里面开会话、选「剧作家」预设,对话页就多一个「AIVN」tab (只给剧作家会话——搭台助手的会话里没有这个 tab), 剧作家写的 Stage DSL 被实时演出来——背景、立绘、台词条、停止点选项都在这里;玩家点一条选项, 这句话回到剧作家手上,它接着往下写。

装
包是 DSH 的 bundle(package.json 里声明了 dsh.bundle.patch):
dsh plugin --profile web add dsh-aivn
从 GitHub 直装也行——lib/ 是跟踪的构建产物,所以不需要构建脚本、也不会触发
pnpm 的 allowBuilds 拦截:
dsh plugin --profile web add github:john-walks-slow/dsh-aivn
- 手工挂:在 profile 的
cordis.patch.yml里加一行:
- insert:
- id: dsh-aivn
name: dsh-aivn
config: {}
- 客户端半边(「AIVN」tab)挂在
conversation.view槽上,需要dsh-web-app。它在package.json的dsh.client{platform:"web"}里声明,不走 Loader。
可配的有六处——语音、联网检索、生图、配乐、命令行、按预设禁用工具;前五项都不配也能照常跑(只是那几项能力没有,对应工具不注册、提示词不提),禁用项默认空。
两种改法,改完都就地生效(不用重启 dsh):
- 界面(推荐):侧边栏 Plugins → dsh-aivn 里的配置卡。分两段——P0 决定能力开不开(Key 与后端),P1 是默认就能用的口味项;顶部一行状态灯显示当前哪几项能力是开的。密钥只写不回显,卡片上另有「清除已存 Key」。
- 配置文件:profile 的
cordis.patch.yml。界面保存的也是这里边——两种改法落在同一份配置上。
- id: dsh-aivn
name: dsh-aivn
config:
ttsKeys: [""] # 多把可轮询,摊免费额度(界面上逗号分隔)
ttsBaseUrl: https://api.fish.audio # 默认值,一般不用写
ttsModel: s2.1-pro-free # 默认值
ttsConcurrency: 2 # 同时合成的上限
searchKeys: [""] # 给了它搭台助手才有 web_search
searchBaseUrl: https://api.exa.ai # 默认值
shell: false # true = 给搭台助手放开 bash
imageFormat: gemini # gemini | openai | modelslab(接口格式,不是产品名)
imageBaseUrl: http://127.0.0.1:38000 # 本机 flow2api;官方 API 或别的网关填它自己的地址
imageModel: gemini-3.0-pro-image
imageSize: 1K # 1K / 2K / 4K(K 大写),或字面像素 1536x1024
imageApiKey: "" # 本机网关不校验就留空(留空 = 不带鉴权头)
imageTimeoutMs: 180000
musicBaseUrl: http://127.0.0.1:38000
musicModel: flow-music-lyria-3.5
musicApiKey: ""
musicTimeoutMs: 240000
playwriterDisabledTools: "" # 按预设禁用工具(逗号分隔的工具名),默认空 = 两预设一致
stagehandDisabledTools: ""
配置面是扁平的 19 个字段(DSH 设置界面的控件只认顶层字段,嵌套写法它寻址不到):
| 配置项 | 默认 | 给了会怎样 | 环境变量兜底 |
|---|---|---|---|
ttsKeys | 空 | 舞台有语音开关,两个预设多一个 list_voices(音色库与合成共用这池 key) | DSH_AIVN_TTS_KEYS |
ttsBaseUrl / ttsModel / ttsConcurrency | Fish 官方 / s2.1-pro-free / 2 | — | — |
searchKeys | 空 | 两个预设多一个 web_search(一次调用同时拿回结果与正文) | DSH_AIVN_EXA_KEYS |
searchBaseUrl | https://api.exa.ai | 换代理 / 镜像时改 | — |
shell | false | 两个预设的 tool-bash 行真装上(默认关,与 AIVN 的 defaultOff 同口径)。bash 是预设的「一行」,只对新建会话生效 | — |
imageFormat / imageBaseUrl / imageModel | — | 地址与模型都给齐才有 generate_image / generate_asset(两个预设都有);cut / import_asset 不依赖它。格式是接口协议形状,不是产品名 | — |
imageSize | 1K | 档位 1K/2K/4K(K 大写)或字面像素 1536x1024;gemini 格式只认档位,openai/modelslab 两种都收(modelslab 封顶 1024) | — |
imageApiKey / imageTimeoutMs | 空 / 180000 | 本机网关不校验就把 key 留空(不带鉴权头);出图慢就把超时调大 | — |
musicBaseUrl / musicModel | — | 都给齐才有 generate_bgm(只有 Gemini 形状,没有 format) | — |
musicApiKey / musicTimeoutMs | 空 / 240000 | 同上;一首曲子实测约 84 秒 | — |
playwriterDisabledTools / stagehandDisabledTools | 空 | 按预设禁用工具(逗号分隔的工具名,取值为「Agent 工具」清单里的工具名)。默认空 = 两预设工具面完全一致 | — |
| 抠底调参 | 见「素材生成」 | DSH_AIVN_CUTOUT_TOLERANCE / _KEY_SMOOTH / _EDGE_BAND / _SPILL / _SOLID_RESIDUAL 五个环境变量 | 同名环境变量 |
key 两处都没有 = 那项能力停用:工具不注册、提示词里也不提。两个预设、一条 /new-play 命令、
/aivn 路由都是固定的,不可配。
改完的配置由 loader 原位提交进运行中的引用,插件据此重建能力面:那一轮的工具装/卸、搭台助手
提示词里门控的那几章、语音后端,开着的会话下一轮就用新的;唯一例外是 shell——它翻的是预设行集,
已开着的会话保持原样,新建一个才吃到。
开发期
@aivn/core与@aivn/stage走file:依赖(指向 stage-ai 仓库)。发布版换成版本号。
用
- 新建会话,在座位 chip 上选 剧作家(备料的那位是 搭台助手)。 预设是在会话开始时定下的,中途换不了——想换就新建一个会话。
- 会话的工作目录根要有
play.json。没有的话舞台会明说「这个会话的工作目录里没有 play.json, 还不是一座剧目」——那就先把它立起来,见下。 - 说一句话开演。之后的一切都在舞台上发生——那句话会把剧目的开局指令(
opening)一并带给剧作家, 所以不必照着剧本念开场白,随便说句什么(「开始吧」)就行。
「AIVN」tab 是会话头部的第三个 tab(Chat / Trajectory / AIVN),只在这个会话是剧作家预设时出现。
导演工具栏(提示 / 改写 / 重写)
舞台右上角那排键是给导演用的,三轮动作都走宿主侧的同一条路:
| 动作 | 它会做什么 | 什么时候能点 |
|---|---|---|
| 提示 · 引导 | 把这句话排进剧作家的下一轮。正在演的这一拍不受影响,停止点还在,玩家照选不误 | 随时 |
| 提示 · 打断 | 先停下正在写的这一轮,再用这句话接着写 | 随时 |
| 改写 | 把最后一步写出来的内容作废,让剧作家按你交代的那句重写一遍(弹窗里预填的是当前这一句,改完提交) | 不在写的时候 |
| 重写 | 把这一拍整段作废,让剧作家重新写(指令可留空 = 纯重写) | 不在写的时候 |
两件要紧的事:
- 改写 / 重写和 AIVN 那边的同名功能不是一回事。AIVN 有一份自己的脚本模型,「改写」是直接改
那一行脚本、不经过模型;DSH 这边的剧本就是剧作家的输出、会话日志才是权威,所以「改这一句」
只能是让剧作家重写这一拍:插件往会话里追加一条替换标记(
surfaceOp.replace,与dsh-rewind同一个手法),被作废的那一段从上下文里真的消失,模型看不到旧内容。 代价是一次重写要花一轮 LLM(AIVN 的原地改写不花),换来的是上下文不会和画面对不上。 - 生图不在这一排:出图在搭台助手那条会话里做(
generate_asset/generate_image),舞台这排键点了也没有落点, 所以不摆。
导演说的话带自己一支来源(dsh-aivn-director),不会变成一行玩家台词:舞台的时间线上
只有玩家真正说过的话。剧作家那边由系统提示词的《演出契约》第 7 条交代「(导演…」是片场喊话。
回退与分支:舞台跟着会话走
- 回退(
dsh-rewind的「回退到这里」):它往会话里追加一条替换标记,插件收到就把舞台 整段重投影一遍——回退之后刷新或重新打开,「AIVN」tab 演到的就是你回退到的那个点。 - 在新对话中分支(DSH 原生的分支):新会话带着父会话的前缀,插件这边不做任何事—— 第一次打开它的舞台时,帧流里一帧都没有,插件就从会话面重铺一遍,于是新会话停在分叉那一刻 (连同那一刻的停止点)。
- 插件不做自己那一套谱系分支(AIVN 的路线图 / 旧枝那套):要分岔就用 DSH 原生的两样。
进行中浮层
右上角那枚「进行中」徽标(有东西时才出现)里是两样:排队中的提示(还没进会话的那些) 与正在合成的语音。出图与配乐不在里面——插件里它们是同步的工具调用,没有回合之外的作业可报。 玩家按了 HIDE 时它跟着舞台一起收起来。
起一座新剧目
工作区里没有 play.json 就是「这还不是一座剧目」:写一份出来就是立起一座剧目,没有生成器。
字段与布局写在两个预设的提示词里(《剧目文件》那一章,同一段文本),模型用文件工具直接写。
- 人:输入框敲
/new-play 雨中的旧校舍。不给剧目名就取工作目录名——这一步替你写play.json与骨架文件,不花一次 LLM 往返。 - Agent:照《剧目文件》写。搭台助手备料时就顺手立起来了。
/new-play 只写不存在的文件:play.json 已经在那儿就直接报错(这里已经是一座剧目,
要起新的就换一个空目录开会话),memory/always/premise.md 与角色卡已经写好就跳过、
在回执里列成「保留」。落下的骨架就是下面那张目录表里的前几行——之后缺什么补什么。
写完想知道对不对,让搭台助手调 validate_play。
一部剧目长什么样
工作目录根就是剧目根:
play.json 剧目配置(唯一的必填文件)
memory/always/premise.md 世界观前提
memory/always/craft.md 文风与禁忌(散文,只能拿话说)
memory/always/state/scene.md 当下场景(剧作家自己写)
memory/always/state/threads.md 未了线索(剧作家自己写)
memory/always/state/state.json 好感度与旗标(同上:好感度是 0~100 的整数,键是角色 id)
characters/.md 角色卡
assets/backgrounds/… 背景
assets/cg/… 插图
assets/sprites//… 立绘:每个主体一个目录
assets/sfx/… assets/bgm/… 音效与音乐
assets/manifest.json 素材描述表:素材 id → 一句话画面
endings.json 结局账本(引擎维护、跨周目累加;不要手改)
play.json
必需字段只有两个:
{ "id": "my-play", "title": "我的剧目" }
其余字段(全部可选):
| 字段 | 作用 |
|---|---|
opening | 开局那条 user 消息的正文。玩家在这条会话里说第一句话时,它与那句话一起发给剧作家;空舞台上的「开演」按钮发的也是它。缺省 (游戏开始,请演出第一轮) |
characters | [{ id, name }]。只用来给台词条配名字:立绘绑定在角色卡的 frontmatter 上 |
craft | 写作参数,见下 |
initialState / initialScene | 剧目的起始状态与起始场景 |
newGamePlus | 多周目开关(缺省 false)。开启后,同工作区新开的会话(新周目)会在提示词里注入此前已达成的结局,见「结局与多周目」 |
scriptLanguage | 剧本语言(ISO 639-1)。缺省跟随玩家说什么话 |
voiceLanguage / defaultVoiceId / cover | 语音与封面:属于 AIVN app,本插件当前不读 |
image | {"model": "…", "size": "2K"}:这座剧目自己的出图模型与档位,覆盖部署级设置(两个字段各覆盖各的,留空即跟随部署配置)。比如一部剧的立绘要 2K 抠底、另一部的小剧场插图 1K 就够 |
agents | agent 运行设置:属于 AIVN app,本插件当前不读 |
结局与多周目
故事走到真正的终点时,剧作家把那一轮的最后一行写成结局标签(它取代那一轮的 ``):
到达结局后舞台进入终局态:不给任何按钮、不能继续,想再玩只能走 DSH 的「在新对话中分支」
(回到结局之前)或新建一条会话。结局之后引擎会单开一轮请剧作家写一段收束散文
(…),流式填进结局卡。
结局由引擎自动记到工作区根的 endings.json:跨周目累加、按 id 去重、reachedIn 记它在第几周目
达成。这份账本引擎独占,不要手改。
play.json 打开 newGamePlus 后,同工作区新开的会话(新周目)开头会把此前已达成的结局注入
剧作家的提示词,让它安排多周目要素(角色隐约记得、某些路线 / 选项不同)。引擎只保证账本可见,
不强制解锁任何内容——怎么用完全由剧作家决定。新周目开始时引擎会把 memory/always/state/
三个状态文件重置回起点(premise.md / craft.md / 记忆索引 / 角色卡都不动)。
characters/<id>.md
一张角色卡就是一份 Markdown,可选 frontmatter:
---
name: 林
sprite: lin
voice: 短句,少用形容词
---
十七岁,话少,习惯先看窗外再看人。
name—— 台词条上的名字。sprite—— 绑到哪个立绘目录(assets/sprites//)。不写就是角色自己的 id。 立绘是立绘自己的事:characters/可以没有立绘,sprites/也可以没有卡。body—— 人设正文。
assets/manifest.json
剧作家认 id 认不出画面,靠这份描述:
{
"veranda": { "description": "黄昏时分的走廊,木地板反着暖光" },
"lin/normal": { "description": "林,常服,平静的神色" }
}
键是素材 id,不是路径——不带目录前缀,也不带扩展名。写成 backgrounds/veranda.png
不会报错,只是永远匹配不上,剧作家会以为这件素材没有描述。三种键形:
| 素材 | 键 |
|---|---|
| 背景 / 插图 / 音效 / 音乐 | 文件名去掉扩展名(veranda) |
| 立绘(整主体) | 立绘目录名(lin) |
| 立绘(单个差分) | /(lin/normal) |
值里除了 description 还能写 tags、title、framing、stature、anchor
(立绘摆位),音乐还能写 mood、scene、durationSec、loop、volume。
背景、插图、音效、音乐按扩展名白名单收(png/jpg/jpeg/webp/mp3/ogg/wav/m4a);立绘按
sprites// 分目录,每个目录里的第一个文件是找不到指定差分时的兜底。
craft:写作参数
play.json 的 craft 段,三个字段都可不写(不写 = 引擎默认):
| 字段 | 取值 | 默认 |
|---|---|---|
beatLength | short / medium / long | medium |
stopOptions | two / three / four / free | three |
assets.background | library-first / library / generate | library-first |
assets.cg | library / generate / off | generate |
assets.sprite | generate / off | generate |
assets.audio | library / off | library |
free = 固定停在自由输入框,不给选项面板。
素材来源四类是给剧作家的意向指令:引擎按这四项把「缺素材时怎么办」写进剧作家的《写作参数》——例如 cg: off 让它别写 ``、background: generate 让它自己出图。注意两点:
- 没有跨剧目素材库(应用级
library/永久不做):library/library-first里「用库」那一支永远走不到,会退化成「用本剧目已有的 / 出图」; - 生图那几支还要看有没有配生图后端:没配时会自动改成「用已有素材或旁白交代」,不会教剧作家去调一个不存在的工具。
文风、禁忌、称呼习惯这类只能拿话说的口径写在 memory/always/craft.md,不在 play.json 里。
这一段用 edit 定点改(只动 craft 这一个键,文件里其余部分一个字节都不碰)。工具里没有
set_craft:写文件就是写文件。写错的值引擎静默当没写——改完让搭台助手调 validate_play,
它会把不认的取值报出来。
theme.json:舞台皮肤
剧目根可以放一份 theme.json,改这座剧目的舞台外观:键就是 @aivn/stage/stage.css 里
.stage-root 上的 CSS 变量名,值过白名单校验。不放这份文件就是默认皮——一个变量都不注,
画面与从前逐像素一致。
{
"--dialog-bg": "linear-gradient(178deg, rgb(16 14 20 / 0.94), rgb(8 7 10 / 0.96))",
"--dialog-ink": "#f4eee0",
"--stage-bg": "#0b0a12",
"--stage-radius": "6px",
"--accent": "#8a5cf6",
"--accent-ink": "#f7fbff",
"--font-ui": "\"Noto Serif CJK SC\", serif"
}
十七个可设置的键,分五组:
| 组 | 键 | 取值 |
|---|---|---|
| 台词条 | --dialog-bg | 颜色,或 linear-gradient(deg, , ) |
--dialog-line、--dialog-ink、--dialog-ink-soft、--dialog-ink-thought、--dialog-ink-faint | 颜色 | |
--dialog-shadow | none,或 0 10px 30px rgb(0 0 0 / 0.45) 这样的「x y 模糊 颜色」 | |
| 衬底与圆角 | --stage-bg | 颜色(图片未到或加载中露出的底) |
--stage-radius | 0px–24px | |
--sprite-dim | 0.2–1(1 = 非发言人立绘完全不压暗) | |
| 选肢卡 | --choice-bg、--choice-line、--choice-ink | 颜色 |
| 字体 | --font-ui | 逗号分隔的字体名,整串 ≤ 200 字符 |
| 主色 | --accent、--accent-ink、--accent-soft | 颜色 |
颜色写法:#rgb / #rrggbb / #rrggbbaa / rgb() / rgba() / hsl() / hsla()(空格与逗号两种
参数语法都认)。不认颜色名、var()、calc()、url()——这条通道收的是值,不是 CSS 文本。
两个入口:
- 让搭台助手改:把想要的基调说清楚,它调
set_stage_style写文件,写完立刻把新皮肤推给 同一座剧目已经打开的舞台(不用刷新)。不给参数调用一次 = 看当前生效值与默认值对照。 - 自己手改:改完刷新页面或切一次会话生效(手改不广播)。
白名单外的键与非法值,手改时只丢那一项,工具调用时整次拒绝(一个字节都不写);文件整个坏掉时 舞台回默认皮、剧目照常开演。
两个预设
| id | 名字 | 干什么 |
|---|---|---|
aivn-playwriter | 剧作家 | 实时写 Stage DSL 的那位;它的输出被接进舞台 |
aivn-stagehand | 搭台助手 | 备料:写设定、角色卡、创作口径、挑音色、出图与入库、配乐、查资料 |
两个预设的行集同构:指令文件发现(AGENTS.md)+ persona(就是那份提示词)+ 文件工具 +
文件检索 + 技能库(自带的 skills/,见下)+ 一行默认关的 tool-bash(shell: true 才真装上)。
工具面也完全一致(见「Agent 工具」),角色差别只剩 persona、注入内容与舞台管线。
预设里不会再列一行 dsh-aivn——宿主已经装了本插件,再来一行会把路由与事件订阅重复装一遍。
只有剧作家预设的会话会进舞台管线。搭台助手说什么都不上台。
技能库(两个预设)
插件自带三份做法速查,随包发布(skills/),装进两个预设的会话:
| 技能 | 讲什么 |
|---|---|
aivn-play-setup | 起新剧目 / 改设定的四步做法与各文件写法(premise / craft.md / craft 段 / 角色卡 / 记忆卡 / 素材表)、craft 取值、备料顺序 |
aivn-visual-craft | 画风锚点写在哪、角色外形怎么锁(头身比 / 五官 / 服装)、差分布局与命名、图单怎么写、可直接粘贴的生图提示词写法 |
aivn-audio | 免费 BGM / 音效去哪里找、哪档授权能商用、六大场景与常见音效类别的选源、再分发与 AI 训练红线 |
清单进 system prompt(只列名字与一句话),模型觉得对上了才加载全文——三份都是长篇,不该每轮全读。
includeDefaultRoots: false 是刻意的:宿主上那几十个本机运维技能不该挤进这两个预设的清单。
上下文注入
剧作家的系统提示词由两部分拼成,中间夹着每轮注入的剧目上下文——剧作家不需要自己去
ls + read 一圈就知道这部戏的设定、有谁、有什么素材、现在演到哪儿:
| 段 | 内容 | 来源 |
|---|---|---|
| 静态前半 | 身份、怎么工作、剧目在哪 | persona 的 prefix |
| 《剧本语言》 | 正文用哪种语言写 | play.json 的 scriptLanguage |
| 《剧目设定》 | 世界观前提 | memory/always/premise.md |
| 《角色表》 | 每张卡的正文 + 音色 + 立绘差分;只有立绘没有卡的主体单列一节 | characters/*.md |
| 《素材清单》 | 背景 / 音乐 / 音效 / 插图的 id + 描述;有音乐音效时附编排规则 | assets/ + assets/manifest.json |
| 《写作参数》 | 每轮多长、给几条选项、素材来源,外加创作口径散文 | play.json 的 craft + memory/always/craft.md |
| 《记忆索引》 | 每张设定卡一行(分类 / 标题 / 路径 / 摘要) | memory/index/** |
| 静态后半 | 剧本格式、记忆卡怎么写、引入新角色、演出契约 | 插件注册的尾段 |
| 【状态】 | 场景、好感度、旗标、活跃剧情线(每轮变化的 user 角色快照) | memory/always/state/* |
这些段只挂给剧作家的会话(注册在 Agent scope 上),搭台助手看不到舞台契约。 快照按秒级 TTL 缓存:一个 turn 里的多个 step 读到同一份,跨轮自然重读。 改完文件不用做别的,下一轮就生效。
搭台助手的注入是另一套(同样注册在它自己的 scope 上):
| 段 | 内容 | 来源 |
|---|---|---|
| 《剧本语言》 | 给演出看的内容用哪种语言写(与用户对话仍是中文) | play.json 的 scriptLanguage |
| 《当前状态》 | 剧目文件清单(路径 + 大小,三层深)+ 开演条件报告 | 工作目录 + readiness |
它不需要舞台契约(不写剧本),也不需要角色表那种逐条展开——它要的是「现在盘上有什么、 还缺什么」,刚写完文件下一轮就看得见。
Agent 工具
工具跟着预设装、跟着预设卸。validate_play 两个预设都有;其余按角色分。
剧作家的停止点不是工具:它是剧本正文最后一行的一个标签——(选项面板)、 (自由输入框)、(这一段自然演完)。轮尾因此是一条助手消息, DSH 的「在新对话中分支」与舞台重建(只重放助手文本)都认得上。**故事真正的终点改用 **
(同为末行标签、取代那一轮的 ``,见「结局与多周目」)。
模型用文件工具就能做的事一律没有:play.json、craft 段、memory/always/state/ 都是文件工具
写出来的,写成什么样由提示词说清(见上「起一座新剧目」);「这座剧目有什么素材」也一样——
剧作家的 A 区每轮注入《素材清单》与《角色表》(id + 描述),搭台助手看《当前状态》的文件清单、
要描述就 read assets/manifest.json。
两个预设装同一套 AIVN 工具(工具清单见 src/tool-catalog.ts);「门控」列只有配了对应后端 / key 才注册的项。
按预设禁用某几个工具,用插件配置 playwriterDisabledTools / stagehandDisabledTools(逗号分隔的工具名,默认空 = 两预设完全一致)。
| 工具 | 门控 | 作用 |
|---|---|---|
validate_play | — | 剧目自查:play.json 读不读得出来(缺字段、坏 JSON 会给原因)、craft 里有没有引擎不认的取值、状态文件好不好、故事前提、角色卡张数、立绘、背景、素材条数、出图台账里有没有指向不存在文件的登记。刚写过剧目文件之后调它。没有硬门槛,缺什么都能开演 |
set_stage_style | — | 写剧目根的 theme.json(舞台皮肤:台词条、选项卡、衬底、圆角、字体、主色),写完把全量皮肤推给同剧目已打开的舞台。三态:省略 = 不动、给值 = 改、null = 回默认;不带参数调用 = 看当前值。值格式与可设置的键见上 |
generate_image | 生图后端 | 纯生成:一段画面描述 → 一张候选图(回执给文件路径与预览),返回时不绑定任何剧目目标、不抠底、不登记。画幅用 aspectRatio(默认 16:9);references 可垫主体 id / 剧目内路径 / http(s) 网址。落成素材另走 cut / import_asset(或直接 generate_asset) |
cut | — | 抠底:纯色底的图 → 透明 PNG(只写输出,不改源图)。source 给剧目内相对路径,output 不给就写到候选区。五档调参见下(tolerance / spill / edgeBand / keySmooth / solidResidual)。立绘登记前先跑它;抠脏了就对着同一张源图重调再跑。不依赖生图后端 |
import_asset | — | 把一张图登记成剧目素材:写 assets/、补素材表(呈现声明 + 描述)、记台账,不抠底。source 给剧目内相对路径或 http(s) 网址;落位显式给——kind(background / cg / sprite)必填,立绘再给 spriteId / variant / framing / stature / title。立绘要传已抠好的透明 PNG(外部来源先 cut);original 可留抠底前原片以便重抠。不依赖生图后端 |
generate_asset | 生图后端 | 一键:出图 +(立绘)自动抠底 + 登记,一次完成,回执给最终素材路径。参数与 import_asset 的落位一致(kind + name / spriteId / variant / framing / stature)。只有这条路由引擎自动做色键底、身份锁、差分垫 neutral;同名素材已有则直接跳过 |
generate_bgm | 音乐后端 | 生成一首 BGM 落 assets/bgm/;同步等待(约 84 秒),name 就是剧本里 `` 引用的 id |
list_voices | tts.keys | 查 Fish 音色库挑音色:按语言 / 标签 / 标题关键词取窗口,本地按 gender 筛,按热度排序出前 25 条。挑好的 id 填进角色卡的 voice |
web_search | search.keys | 联网检索:一次调用同时拿回结果与正文。只查剧目之外的事实——设定、角色、剧情都在工作区文件里 |
list_voices / web_search / generate_image / generate_asset / generate_bgm 在没配对应 key / 后端时
不注册,提示词里也不提它们。validate_play / set_stage_style / cut / import_asset 不门控:
它们只读写剧目文件、跑抠底,不碰生图后端——所以没配生图也能用外部工具出图、cut 抠底、import_asset 登记。
文件工具(read / write / edit / glob / grep / read_image)由预设的行集提供,两个预设都有。
素材生成
「像素从哪来」和「像素怎么变成剧目素材」是两步,工具也是分开的:
- 一键(
generate_asset):出图 +(立绘)自动抠底 + 登记,一步到位——「就想要一张能用的图」走这条。 - **原子三件套(
generate_image/cut