mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 07:40:44 +00:00
fix(ui): retry errored talk sessions
This commit is contained in:
@@ -62,6 +62,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
- Control UI/Talk: make failed Talk startup errors dismissable and clear the stale Talk error state when dismissed, so missing realtime voice provider configuration does not leave a permanent chat banner. Fixes #77071. Thanks @ijoshdavis.
|
||||
- Control UI/Talk: stop and clear failed realtime Talk sessions when dismissing runtime error banners, so the next Talk click starts a fresh session instead of only stopping the stale one. Thanks @vincentkoc.
|
||||
- Control UI/Talk: retry from a failed realtime Talk session on the next Talk click instead of requiring a separate stale-session stop click first. Thanks @vincentkoc.
|
||||
- Google Chat: create an isolated Google auth transport per auth client, so google-auth-library interceptor mutations do not accumulate across webhook verification and access-token clients. Thanks @vincentkoc.
|
||||
- Control UI/performance: cap long-task and long-animation-frame diagnostics in the shared event log, so slow-render telemetry does not evict gateway/plugin events from the Debug and Overview views. Thanks @vincentkoc.
|
||||
- Web fetch: late-bind `web_fetch` config and provider fallback metadata from the active runtime snapshot, matching `web_search` so long-lived tools do not use stale fetch provider settings. Thanks @vincentkoc.
|
||||
|
||||
57
ui/src/ui/app.talk.test.ts
Normal file
57
ui/src/ui/app.talk.test.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
/* @vitest-environment jsdom */
|
||||
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
const { realtimeTalkCtor, startMock, stopMock } = vi.hoisted(() => ({
|
||||
realtimeTalkCtor: vi.fn(),
|
||||
startMock: vi.fn(),
|
||||
stopMock: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("./chat/realtime-talk.ts", () => ({
|
||||
RealtimeTalkSession: realtimeTalkCtor,
|
||||
}));
|
||||
|
||||
describe("OpenClawApp Talk controls", () => {
|
||||
beforeEach(() => {
|
||||
realtimeTalkCtor.mockReset();
|
||||
startMock.mockReset();
|
||||
stopMock.mockReset();
|
||||
realtimeTalkCtor.mockImplementation(
|
||||
function MockRealtimeTalkSession(this: { start: typeof startMock; stop: typeof stopMock }) {
|
||||
this.start = startMock;
|
||||
this.stop = stopMock;
|
||||
},
|
||||
);
|
||||
startMock.mockResolvedValue(undefined);
|
||||
});
|
||||
|
||||
it("retries Talk immediately when the previous session is already in error state", async () => {
|
||||
const { OpenClawApp } = await import("./app.ts");
|
||||
const app = new OpenClawApp() as unknown as {
|
||||
client: unknown;
|
||||
connected: boolean;
|
||||
realtimeTalkActive: boolean;
|
||||
realtimeTalkStatus: string;
|
||||
realtimeTalkSession: { stop(): void } | null;
|
||||
sessionKey: string;
|
||||
toggleRealtimeTalk(): Promise<void>;
|
||||
};
|
||||
const staleStop = vi.fn();
|
||||
app.client = { request: vi.fn() } as never;
|
||||
app.connected = true;
|
||||
app.sessionKey = "main";
|
||||
app.realtimeTalkActive = true;
|
||||
app.realtimeTalkStatus = "error";
|
||||
app.realtimeTalkSession = { stop: staleStop };
|
||||
|
||||
await app.toggleRealtimeTalk();
|
||||
|
||||
expect(staleStop).toHaveBeenCalledOnce();
|
||||
expect(realtimeTalkCtor).toHaveBeenCalledOnce();
|
||||
expect(startMock).toHaveBeenCalledOnce();
|
||||
expect(stopMock).not.toHaveBeenCalled();
|
||||
expect(app.realtimeTalkStatus).toBe("connecting");
|
||||
expect(app.realtimeTalkSession).not.toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -908,13 +908,18 @@ export class OpenClawApp extends LitElement {
|
||||
|
||||
async toggleRealtimeTalk() {
|
||||
if (this.realtimeTalkSession) {
|
||||
this.realtimeTalkSession.stop();
|
||||
this.realtimeTalkSession = null;
|
||||
this.realtimeTalkActive = false;
|
||||
this.realtimeTalkStatus = "idle";
|
||||
this.realtimeTalkDetail = null;
|
||||
this.realtimeTalkTranscript = null;
|
||||
return;
|
||||
if (this.realtimeTalkStatus === "error") {
|
||||
this.realtimeTalkSession.stop();
|
||||
this.realtimeTalkSession = null;
|
||||
} else {
|
||||
this.realtimeTalkSession.stop();
|
||||
this.realtimeTalkSession = null;
|
||||
this.realtimeTalkActive = false;
|
||||
this.realtimeTalkStatus = "idle";
|
||||
this.realtimeTalkDetail = null;
|
||||
this.realtimeTalkTranscript = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!this.client || !this.connected) {
|
||||
this.lastError = "Gateway not connected";
|
||||
|
||||
Reference in New Issue
Block a user