Repository navigation
fix(core): streamsOutput 工具不受屏障,越过屏障照常按顺序执行 - #374
Merged
Merged
Conversation
输出接收器在函数调用开头就对外执行说话这类工具,屏障却在响应结束后才把同一条回复里排在 屏障工具后面的调用记成未执行;模型看到未执行回执重说一遍,观众听到两遍。 - ToolDef 加 streamsOutput:标了的调用在屏障工具执行完之后照常按顺序执行,回执是真实结果。 没标的照旧跳过;被跳过的回执末尾用 streamedPastBarrier 列出越过屏障执行过的流式工具名。 - 只按这个标记认:带 speak 标签的确认发送工具正是屏障要拦的,接收器 externalizes 的运行时 报告也不作数。EagerDispatch 仍在屏障处停下,interrupt 照旧跳过本轮尚未开始的调用;fork 没有输出接收器,屏障不变。 - 没采用「屏障后的调用不交给接收器」:说话不是要先看前面结果才能做的动作,规则放在工具上。 - 新用例在去掉 loop.ts 的改动后失败;原屏障用例里被跳过的工具加上 speak 标签。 Co-authored-by: Lantichr <333946430+Lantichr@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| if (barrierHit) { | ||
| const def = this.toolDefs.find((t) => t.name === call.name); | ||
| const pastBarrier = barrierHit; | ||
| if (pastBarrier && !def?.streamsOutput) { |
There was a problem hiding this comment.
docs/sessions.md 把 src/core/loop.ts 列为 owner,本 PR 改了这支文件里何时跳过后续调用,但没有改这一页。
AGENTS.md §8:「Every page under docs/ and every README of a code unit names, in its first line, the file or interface it shadows: its owner. The commit that changes the owner changes the page.」
此处把跳过条件改成 pastBarrier && !def?.streamsOutput。barrierHit 也会在同一轮前一个调用 status !== 'completed' 时置位。docs/sessions.md 写的是非 completed 的调用之后「同一轮排在它后面的调用也不执行」。这一句对 streamsOutput 不再成立。
请把 docs/sessions.md 改到与现行规则一致,或在 PR 说明里写明为什么这一页可以不改。
— Cortico PR Gate via Cursor Cloud Agent
This was referenced Nov 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #367
中文
ToolDef加一个可选标记streamsOutput,表示输出接收器(outputTap)在模型还在输出时就对外执行这个工具。主循环的屏障不跳过它:同一条回复里排在barrierAfter工具后面、标了streamsOutput的调用,在屏障工具执行完之后照常按顺序执行,回执是它自己的真实结果。没标的调用照旧跳过,回执仍是[not executed: review the preceding tool result first];只要同一条回复里有流式工具越过屏障执行过,这些回执末尾再加一行[streaming tools in this response ran as usual: <工具名>]。EagerDispatch仍在屏障处停下,interrupt 照旧跳过本轮尚未开始的调用;fork 没有输出接收器,屏障不变。为什么:接收器在函数调用开头就开演说话类工具,屏障却在响应结束后才把它记成未执行,模型看到回执重说一遍,观众听两遍。标记只按工具声明认:不按
speak标签认,因为确认发送的工具也是speak,屏障本来就是为拦它设的;也不按接收器externalizes的运行时报告认。感谢 @Lantichr 报告并给出复现用例和补丁。新测试沿用他的用例(屏障工具
stage加普通工具after,带outputTap),加一个流式工具后改了断言。没有照补丁的做法(屏障后的调用不交给接收器):说话不是要先看前面结果才能做的动作,规则应当是流式工具不归屏障管,不该把这句台词拦下不播。怎么验的:新用例在去掉
src/core/loop.ts的改动后失败,改动后通过;原有的屏障用例里被跳过的工具加上speak标签,确认没标的照旧跳过。没验的:没在真实直播上跑。扩展要在vtuber_act上标streamsOutput才生效,在 Pal-AI-Lab/cortico-world-vtuber#14,要等这个 PR 合并发版后再合。English
ToolDefgains an optionalstreamsOutputflag: the output tap executes this tool externally while the model is still producing output. The main loop's barrier does not skip such calls. AstreamsOutputcall placed after abarrierAftertool in the same response runs in order once the barrier tool has finished, and its receipt is its own result. Unflagged calls are still skipped with[not executed: review the preceding tool result first]; when any streaming tool ran past the barrier, those receipts get one more line,[streaming tools in this response ran as usual: <names>].EagerDispatchstill stops at the barrier, an interrupt still skips calls that have not started, and forks keep their barrier because they have no output tap.Why: the tap starts performing a speech tool when the call opens, but the barrier marked that call as not executed after the response ended, so the model repeated itself and the audience heard the line twice. The flag is the only signal. The
speaktag is not used, because the send-confirm tool is alsospeakand is what the barrier exists for; the tap's runtimeexternalizesreport is not used either.Thanks to @Lantichr for the report, the reproduction and the patch. The new test is built on his fixture (barrier tool
stage, plain toolafter, anoutputTap), with a streaming tool added and the assertions changed. The patch's approach, withholding calls after the barrier from the tap, was not taken: speaking does not depend on the preceding result, so the rule is that streaming tools are outside the barrier, and the line should not be held back.Verified: the new test fails with the
src/core/loop.tschange removed and passes with it; the existing barrier test now tags its skipped toolspeakto show that unflagged calls are still skipped. Not verified: no live stream run. The extension needsstreamsOutputonvtuber_act; that is Pal-AI-Lab/cortico-world-vtuber#14, to be merged after this one is merged and released.Checks
pnpm test(289 files, 5227 passed, 3 skipped)pnpm run typecheckpnpm typecheck:web🤖 Generated with Claude Code