mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:20:43 +00:00
Add Google Meet realtime consult agentId (#72381)
Remote proof:
- CI run 24982271745 passed on 6122e13c9f.
- Blacksmith Testbox tbx_01kq6vwehcszjfpp52f0pb3v1q passed focused Google Meet formatting, docs/link checks, realtime consult runtime tests, Google Meet tests, extension test typecheck, the core-unit-fast-support shard, and the core support boundary shard.
Thanks @BsnizND.
Co-authored-by: BSnizND <199837910+BsnizND@users.noreply.github.com>
This commit is contained in:
@@ -33,6 +33,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Voice Call: allow SecretRef-backed Twilio auth tokens and call-specific OpenAI/ElevenLabs TTS API keys through the plugin config surface. Fixes #68690. Thanks @joshavant.
|
||||
- Google Meet: clean stale chrome-node realtime audio bridges by URL before rejoining, expose active node bridge inspection, and tolerate transient node input pull failures instead of dropping the Meet session. Fixes #72371. (#72372) Thanks @BsnizND.
|
||||
- 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.
|
||||
- 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: 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.
|
||||
- Cron: preserve exact `NO_REPLY` tool results from isolated jobs with empty final assistant turns as quiet successes instead of surfacing incomplete-turn errors. Fixes #68452; carries forward #68453. Thanks @anyech.
|
||||
|
||||
@@ -897,6 +897,8 @@ Defaults:
|
||||
`openclaw_agent_consult` for deeper answers
|
||||
- `realtime.introMessage`: short spoken readiness check when the realtime bridge
|
||||
connects; set it to `""` to join silently
|
||||
- `realtime.agentId`: optional OpenClaw agent id for
|
||||
`openclaw_agent_consult`; defaults to `main`
|
||||
|
||||
Optional overrides:
|
||||
|
||||
@@ -915,6 +917,7 @@ Optional overrides:
|
||||
},
|
||||
realtime: {
|
||||
provider: "google",
|
||||
agentId: "jay",
|
||||
toolPolicy: "owner",
|
||||
introMessage: "Say exactly: I'm here.",
|
||||
providers: {
|
||||
@@ -1001,6 +1004,10 @@ meeting transcript context and returns a concise spoken answer to the realtime
|
||||
voice session. The voice model can then speak that answer back into the meeting.
|
||||
It uses the same shared realtime consult tool as Voice Call.
|
||||
|
||||
By default, consults run against the `main` agent. Set `realtime.agentId` when a
|
||||
Meet lane should consult a dedicated OpenClaw agent workspace, model defaults,
|
||||
tool policy, memory, and session history.
|
||||
|
||||
`realtime.toolPolicy` controls the consult run:
|
||||
|
||||
- `safe-read-only`: expose the consult tool and limit the regular agent to
|
||||
|
||||
@@ -287,6 +287,16 @@ describe("google-meet plugin", () => {
|
||||
expect(resolveGoogleMeetConfig({}).realtime.instructions).toContain("openclaw_agent_consult");
|
||||
});
|
||||
|
||||
it("resolves the realtime consult agent id", () => {
|
||||
expect(
|
||||
resolveGoogleMeetConfig({
|
||||
realtime: {
|
||||
agentId: " jay ",
|
||||
},
|
||||
}).realtime.agentId,
|
||||
).toBe("jay");
|
||||
});
|
||||
|
||||
it("uses env fallbacks for OAuth, preview, and default meeting values", () => {
|
||||
expect(
|
||||
resolveGoogleMeetConfigWithEnv(
|
||||
@@ -1976,7 +1986,7 @@ describe("google-meet plugin", () => {
|
||||
|
||||
const handle = await startCommandRealtimeAudioBridge({
|
||||
config: resolveGoogleMeetConfig({
|
||||
realtime: { provider: "openai", model: "gpt-realtime" },
|
||||
realtime: { provider: "openai", model: "gpt-realtime", agentId: "jay" },
|
||||
}),
|
||||
fullConfig: {} as never,
|
||||
runtime: runtime as never,
|
||||
@@ -2041,10 +2051,14 @@ describe("google-meet plugin", () => {
|
||||
expect(runtime.agent.runEmbeddedPiAgent).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
messageProvider: "google-meet",
|
||||
agentId: "jay",
|
||||
sessionKey: "agent:jay:google-meet:meet-1",
|
||||
sandboxSessionKey: "agent:jay:google-meet:meet-1",
|
||||
thinkLevel: "high",
|
||||
toolsAllow: ["read", "web_search", "web_fetch", "x_search", "memory_search", "memory_get"],
|
||||
}),
|
||||
);
|
||||
expect(sessionStore).toHaveProperty("agent:jay:google-meet:meet-1");
|
||||
|
||||
await handle.stop();
|
||||
expect(bridge.close).toHaveBeenCalled();
|
||||
|
||||
@@ -120,6 +120,11 @@ const googleMeetConfigSchema = {
|
||||
label: "Realtime Intro Message",
|
||||
help: "Spoken once when the realtime bridge is ready. Set to an empty string to join silently.",
|
||||
},
|
||||
"realtime.agentId": {
|
||||
label: "Realtime Consult Agent",
|
||||
help: 'OpenClaw agent id used by openclaw_agent_consult. Defaults to "main".',
|
||||
advanced: true,
|
||||
},
|
||||
"realtime.toolPolicy": {
|
||||
label: "Realtime Tool Policy",
|
||||
help: "Safe read-only tools are available by default; owner requests can unlock broader tools.",
|
||||
|
||||
@@ -129,6 +129,11 @@
|
||||
"label": "Realtime Intro Message",
|
||||
"help": "Spoken once when the realtime bridge is ready. Set to an empty string to join silently."
|
||||
},
|
||||
"realtime.agentId": {
|
||||
"label": "Realtime Consult Agent",
|
||||
"help": "OpenClaw agent id used by openclaw_agent_consult. Defaults to \"main\".",
|
||||
"advanced": true
|
||||
},
|
||||
"realtime.toolPolicy": {
|
||||
"label": "Realtime Tool Policy",
|
||||
"help": "Safe read-only tools are available by default; owner requests can unlock broader tools.",
|
||||
@@ -353,6 +358,10 @@
|
||||
"type": "string",
|
||||
"default": "Say exactly: I'm here and listening."
|
||||
},
|
||||
"agentId": {
|
||||
"type": "string",
|
||||
"description": "OpenClaw agent id used by openclaw_agent_consult. Defaults to \"main\"."
|
||||
},
|
||||
"toolPolicy": {
|
||||
"type": "string",
|
||||
"enum": ["safe-read-only", "owner", "none"],
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
resolveRealtimeVoiceAgentConsultToolsAllow,
|
||||
type RealtimeVoiceTool,
|
||||
} from "openclaw/plugin-sdk/realtime-voice";
|
||||
import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
|
||||
import type { GoogleMeetConfig, GoogleMeetToolPolicy } from "./config.js";
|
||||
|
||||
export const GOOGLE_MEET_AGENT_CONSULT_TOOL_NAME = REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME;
|
||||
@@ -26,11 +27,14 @@ export async function consultOpenClawAgentForGoogleMeet(params: {
|
||||
args: unknown;
|
||||
transcript: Array<{ role: "user" | "assistant"; text: string }>;
|
||||
}): Promise<{ text: string }> {
|
||||
const agentId = normalizeAgentId(params.config.realtime.agentId);
|
||||
const sessionKey = `agent:${agentId}:google-meet:${params.meetingSessionId}`;
|
||||
return await consultRealtimeVoiceAgent({
|
||||
cfg: params.fullConfig,
|
||||
agentRuntime: params.runtime.agent,
|
||||
logger: params.logger,
|
||||
sessionKey: `google-meet:${params.meetingSessionId}`,
|
||||
agentId,
|
||||
sessionKey,
|
||||
messageProvider: "google-meet",
|
||||
lane: "google-meet",
|
||||
runIdPrefix: `google-meet:${params.meetingSessionId}`,
|
||||
|
||||
@@ -57,6 +57,7 @@ export type GoogleMeetConfig = {
|
||||
model?: string;
|
||||
instructions?: string;
|
||||
introMessage?: string;
|
||||
agentId?: string;
|
||||
toolPolicy: GoogleMeetToolPolicy;
|
||||
providers: Record<string, Record<string, unknown>>;
|
||||
};
|
||||
@@ -361,6 +362,7 @@ export function resolveGoogleMeetConfigWithEnv(
|
||||
introMessage:
|
||||
normalizeOptionalString(realtime.introMessage) ??
|
||||
DEFAULT_GOOGLE_MEET_CONFIG.realtime.introMessage,
|
||||
agentId: normalizeOptionalString(realtime.agentId),
|
||||
toolPolicy: resolveRealtimeVoiceAgentConsultToolPolicy(
|
||||
realtime.toolPolicy,
|
||||
DEFAULT_GOOGLE_MEET_CONFIG.realtime.toolPolicy,
|
||||
|
||||
Reference in New Issue
Block a user