Repository navigation
【插件开发问题】latestAssistantTurn 会返回过期值(同一视图里 settlementTurn = 4 而它是 1) #189
Closed
lidochka77
started this conversation in
General
Replies: 1 comment 1 reply
|
感谢详细的报告,证据链很清楚,问题确认并已修复,已推送,在应用里更新到最新即可生效。 实际原因和推测的稍有不同:不是数组顺序问题,而是每轮结束后界面视图只重算有变化的部分, 修复后每次都会按最新消息计算。 |
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
纯外行手搓小插件,今天调试的时候大肥鱼说这个是源码有点问题,最好提报给原作者看看,所以就让大肥鱼写了一份报告,请作者审阅!
标题
latestAssistantTurn会返回过期值(同一视图里settlementTurn= 4 而它是 1),按文档用registerComposerAction的context.turn挂媒体项的插件会把卡片挂到开场白那一轮,用户正看的那一轮里永远不显示正文
环境
tavernapiVersion 2(getTurn/getCardContext/backgroundModel/attach/update/list/remove/getHistory)+tavernUiapiVersion 2(registerComposerAction/registerMediaRenderer/registerPanel)。没有改酒馆源码,也没有读写酒馆的数据目录。
现象
在新开的一局里(开场白之后又正常玩了几轮),点插件按钮挂一个自定义
kind的媒体项:status: "ready",内容是完整的),但它落在 turn 1(开场白)下面;证据链(全部通过酒馆自己的接口读到,没有猜)
即:卡片和
currentKey(1)完全一致,酒馆愿意把这两项交给页面。问题不在存储、也不在绑定。getSession视图自相矛盾:用户侧确认:往上翻到最上面,那两张卡就挂在开场白下面 ——
说明渲染本身没问题,只是挂错了轮次。
反过来看历史:这位用户以前在第 5 轮 / 第 37 轮挂的卡片都正常显示 ——
只有这次"新开的对话"错位,所以它是状态相关的、不是每次必现。
根因(源码级)
tavern-plugin/lib/index.js:1832-1840(安装版 2.5.0):而
latestAssistantTurn直接取它(:1904latestAssistantTurn: latestStoryTurn)。也就是说
latestAssistantTurn并不是"最新的故事轮次",而是「
chat.messages里最后一条 assistant 消息的turn」,而开场白那条的turn兜底值是 1。我们这份对话里数组最后一条 assistant 消息正是开场白
(
latestAssistantMessageId也报tavern-opening:…),于是算出 1 —— 可settlementTurn/rollbackTargetTurn已经都是 4 了。该数组的顺序/窗口在新对话与老对话里不同,这正好解释了"老对话正常、新对话错位"。
影响面(这条最要紧)
接口文档里
registerComposerAction写的是「针对当前最新一轮」,context = { gameId, turn, busy }。于是任何按文档用
context.turn去attach({ turn })的插件,在这种状态下都会把媒体项挂到第 1 轮;而渲染只看「你正看的那条消息的那一轮」,结果就是卡片静默消失:
host 端一切正常、
pluginMediaForTurn也返回了数据,日志里没有任何报错,用户只会觉得"点了没反应"。这不是某一个插件的问题。
我们目前的临时绕法(供参考)
不直接用
context.turn,而用拿不到
getHistory(老版本酒馆、或这一轮还没结算)就沿用原值。但这只是防守:插件多了一次本地调用,而且一旦酒馆的编号语义再变,绕法也会跟着错。
可能的方向(供你判断,不一定按这个做)
latestStoryTurn取「真正最新的一轮」:例如取chat.messages里turn的最大值,或直接复用
settlementTurn/ 投影里的最新轮次,而不是"数组最后一个元素";registerComposerAction的context.turn与渲染器用同一套编号(消息节点那个
tavernStoryTurnForDshTurn(...)的结果),两边就不会打架;tavern.getCurrentTurn({gameId})),并在文档里点名「不要拿
context.turn直接 attach」;latestStoryTurn时排除message.greeting === true的那条。最短复现路径
新建一局 → 只说一两轮 → 用一个按文档实现的小插件(
registerComposerAction取context.turn)attach一个自定义kind的媒体项 → 到getSession里看:latestAssistantTurn会明显小于settlementTurn,而媒体项落在 turn 1、页面里看不到。顺带一条正面反馈:
pluginMediaForTurn/pluginMediaTurns这套接口很好用 ——我们正是靠它把"卡片到底存到哪一轮去了"一次问清楚的,否则这个问题会更难查。
All reactions