mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:00:42 +00:00
fix: harden Google Live tool responses (#72426) (thanks @BsnizND)
This commit is contained in:
@@ -67,6 +67,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Google Meet: clear queued Gemini Live playback when realtime interruptions arrive, restart Chrome command-pair audio output after clears, and expose Google Live interruption/VAD config knobs for Meet and Voice Call realtime bridges. Fixes #72523. (#72524) Thanks @BsnizND.
|
||||
- Google Meet: add `realtime.agentId` so live meeting consults can target a named OpenClaw agent instead of always using `main`. (#72381) Thanks @BsnizND.
|
||||
- Google Meet: route stateful `google_meet` tool actions through the gateway-owned runtime so created or joined realtime sessions remain visible to status, speak, and leave after the agent turn ends. Fixes #72440. (#72441) Thanks @BsnizND.
|
||||
- Google Meet: preserve Gemini Live function names when replying to realtime tool calls so Google SDK validation accepts the `FunctionResponse` payload. Fixes #72425. (#72426) Thanks @BsnizND.
|
||||
- Matrix/E2EE: stabilize recovery and broken-device QA flows while avoiding Matrix device-cleanup sync races that could leave shutdown-time crypto work running. Thanks @gumadeiras.
|
||||
- Cron: apply `cron.maxConcurrentRuns` to a dedicated `cron-nested` isolated agent-turn lane as well as cron dispatch, so parallel cron jobs no longer serialize on inner LLM execution while non-cron nested flows keep their existing lane behavior. Fixes #72707. Thanks @kagura-agent.
|
||||
- Cron: treat isolated run-level agent failures as job errors even when no reply payload is produced, synthesizing a safe error payload so model/provider failures increment error counters and trigger failure notifications instead of clearing as successful. Fixes #43604; carries forward #43631. Thanks @SPFAdvisors.
|
||||
|
||||
@@ -414,4 +414,44 @@ describe("buildGoogleRealtimeVoiceProvider", () => {
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("reports Google Live tool response send failures without losing the call name", async () => {
|
||||
const provider = buildGoogleRealtimeVoiceProvider();
|
||||
const onError = vi.fn();
|
||||
const bridge = provider.createBridge({
|
||||
providerConfig: { apiKey: "gemini-key" },
|
||||
onAudio: vi.fn(),
|
||||
onClearAudio: vi.fn(),
|
||||
onError,
|
||||
});
|
||||
|
||||
await bridge.connect();
|
||||
lastConnectParams().callbacks.onmessage({
|
||||
setupComplete: { sessionId: "session-1" },
|
||||
toolCall: {
|
||||
functionCalls: [{ id: "call-1", name: "lookup", args: { query: "hi" } }],
|
||||
},
|
||||
});
|
||||
|
||||
const sendError = new Error("SDK send failed");
|
||||
session.sendToolResponse.mockImplementationOnce(() => {
|
||||
throw sendError;
|
||||
});
|
||||
|
||||
bridge.submitToolResult("call-1", ["retryable"]);
|
||||
|
||||
expect(onError).toHaveBeenCalledWith(sendError);
|
||||
|
||||
bridge.submitToolResult("call-1", { result: "ok" });
|
||||
|
||||
expect(session.sendToolResponse).toHaveBeenLastCalledWith({
|
||||
functionResponses: [
|
||||
{
|
||||
id: "call-1",
|
||||
name: "lookup",
|
||||
response: { result: "ok" },
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -461,19 +461,25 @@ class GoogleRealtimeVoiceBridge implements RealtimeVoiceBridge {
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.pendingFunctionNames.delete(callId);
|
||||
this.session.sendToolResponse({
|
||||
functionResponses: [
|
||||
{
|
||||
id: callId,
|
||||
name,
|
||||
response:
|
||||
result && typeof result === "object"
|
||||
? (result as Record<string, unknown>)
|
||||
: { output: result },
|
||||
},
|
||||
],
|
||||
});
|
||||
try {
|
||||
this.session.sendToolResponse({
|
||||
functionResponses: [
|
||||
{
|
||||
id: callId,
|
||||
name,
|
||||
response:
|
||||
result && typeof result === "object" && !Array.isArray(result)
|
||||
? (result as Record<string, unknown>)
|
||||
: { output: result },
|
||||
},
|
||||
],
|
||||
});
|
||||
this.pendingFunctionNames.delete(callId);
|
||||
} catch (error) {
|
||||
this.config.onError?.(
|
||||
error instanceof Error ? error : new Error("Failed to send Google Live function response"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
acknowledgeMark(): void {}
|
||||
|
||||
Reference in New Issue
Block a user