fix(tts): gated playback clearing to user messages
Moved vocalizer interruption from agent_start to user message_start so agentLoopContinue preserves queued speech. Expanded regression coverage for continuation starts and user prompt boundaries. Fixes #6375
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed Assistant-mode TTS playback aborting when an agent continued after a tool call in the same run; internal turn boundaries now preserve queued speech, while a new agent run still interrupts prior playback. ([#6375](https://github.com/can1357/oh-my-pi/issues/6375))
|
||||
- Fixed Assistant-mode TTS playback aborting when an agent continued after a tool call or automatic follow-up in the same run; internal continuation boundaries now preserve queued speech, while a new user message still interrupts prior playback. ([#6375](https://github.com/can1357/oh-my-pi/issues/6375))
|
||||
- Fixed credential-shaped tokens (GitHub/GitLab/OpenAI/Anthropic key patterns) being redacted from outbound provider requests even with `secrets.enabled` off; the pattern redaction now follows the `secrets.enabled` ("Hide Secrets") setting like the secret obfuscator.
|
||||
- Fixed Ctrl-clicking a wrapped OAuth authorization URL opening only the clicked row's truncated fragment by preserving the complete hyperlink target on every rendered row.
|
||||
- Fixed used-only absolute usage amounts across output surfaces: CLI now renders `$123.45 used`; the TUI shows a neutral, width-bounded amount instead of a pending/dotted/account-count placeholder; and ACP preserves `123.45 usd used` while suppressing duplicate window suffixes such as `— extra`. ([#5575](https://github.com/can1357/oh-my-pi/issues/5575))
|
||||
|
||||
@@ -405,7 +405,6 @@ export class EventController {
|
||||
}
|
||||
|
||||
async #handleAgentStart(_event: Extract<AgentSessionEvent, { type: "agent_start" }>): Promise<void> {
|
||||
vocalizer.clear();
|
||||
this.#toolTimelineComponents.clear();
|
||||
this.#postToolAssistantComponents.clear();
|
||||
this.#lastIntent = undefined;
|
||||
@@ -450,6 +449,7 @@ export class EventController {
|
||||
}
|
||||
this.ctx.ui.requestRender();
|
||||
} else if (event.message.role === "user") {
|
||||
vocalizer.clear();
|
||||
const textContent = this.ctx.getUserMessageText(event.message);
|
||||
const imageBlocks =
|
||||
typeof event.message.content === "string"
|
||||
|
||||
@@ -22,6 +22,11 @@ function createContext() {
|
||||
transcriptMessageComponents: new WeakMap(),
|
||||
pendingTools,
|
||||
hideThinkingBlock: false,
|
||||
getUserMessageText: () => "new prompt",
|
||||
locallySubmittedUserSignatures: new Set<string>(),
|
||||
addMessageToChat: vi.fn(),
|
||||
editor: { setText: vi.fn() },
|
||||
updatePendingMessagesDisplay: vi.fn(),
|
||||
setWorkingMessage,
|
||||
clearPinnedError: vi.fn(),
|
||||
ensureLoadingAnimation,
|
||||
@@ -62,15 +67,24 @@ describe("EventController aborted-turn working messages", () => {
|
||||
resetSettingsForTest();
|
||||
});
|
||||
|
||||
it("preserves playback across internal turns and clears it for a new agent run", async () => {
|
||||
it("preserves playback across internal continuations and clears it for a user message", async () => {
|
||||
const clear = vi.spyOn(vocalizer, "clear").mockImplementation(() => {});
|
||||
const { ctx } = createContext();
|
||||
const controller = new EventController(ctx);
|
||||
|
||||
await controller.handleEvent(AGENT_START);
|
||||
await controller.handleEvent({ type: "turn_start" });
|
||||
expect(clear).not.toHaveBeenCalled();
|
||||
|
||||
await controller.handleEvent(AGENT_START);
|
||||
await controller.handleEvent({
|
||||
type: "message_start",
|
||||
message: {
|
||||
role: "user",
|
||||
content: [{ type: "text", text: "new prompt" }],
|
||||
attribution: "user",
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
});
|
||||
expect(clear).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user