


















@@ -197,6 +197,80 @@ describe("google-meet create flow", () => {
197197);
198198});
199199200+it("reports structured manual action when browser creation needs Google login", async () => {
201+const { methods } = setup(
202+{
203+defaultTransport: "chrome-node",
204+chromeNode: { node: "parallels-macos" },
205+},
206+{
207+nodesInvokeHandler: async (params) => {
208+const proxy = params.params as { path?: string; body?: { url?: string } };
209+if (proxy.path === "/tabs") {
210+return { payload: { result: { tabs: [] } } };
211+}
212+if (proxy.path === "/tabs/open") {
213+return {
214+payload: {
215+result: {
216+targetId: "login-tab",
217+title: "New Tab",
218+url: proxy.body?.url,
219+},
220+},
221+};
222+}
223+if (proxy.path === "/act") {
224+return {
225+payload: {
226+result: {
227+ok: true,
228+targetId: "login-tab",
229+result: {
230+manualActionReason: "google-login-required",
231+manualAction:
232+"Sign in to Google in the OpenClaw browser profile, then retry meeting creation.",
233+browserUrl: "https://accounts.google.com/signin",
234+browserTitle: "Sign in - Google Accounts",
235+notes: ["Sign-in page detected."],
236+},
237+},
238+},
239+};
240+}
241+throw new Error(`unexpected browser proxy path ${proxy.path}`);
242+},
243+},
244+);
245+const handler = methods.get("googlemeet.create") as
246+| ((ctx: {
247+params: Record<string, unknown>;
248+respond: ReturnType<typeof vi.fn>;
249+}) => Promise<void>)
250+| undefined;
251+const respond = vi.fn();
252+253+await handler?.({ params: {}, respond });
254+255+expect(respond.mock.calls[0]?.[0]).toBe(false);
256+expect(respond.mock.calls[0]?.[1]).toMatchObject({
257+source: "browser",
258+error:
259+"google-login-required: Sign in to Google in the OpenClaw browser profile, then retry meeting creation.",
260+manualActionRequired: true,
261+manualActionReason: "google-login-required",
262+manualActionMessage:
263+"Sign in to Google in the OpenClaw browser profile, then retry meeting creation.",
264+browser: {
265+nodeId: "node-1",
266+targetId: "login-tab",
267+browserUrl: "https://accounts.google.com/signin",
268+browserTitle: "Sign in - Google Accounts",
269+notes: ["Sign-in page detected."],
270+},
271+});
272+});
273+200274it("creates and joins a Meet through the create tool action by default", async () => {
201275const { tools, nodesInvoke } = setup(
202276{
@@ -292,6 +366,71 @@ describe("google-meet create flow", () => {
292366);
293367});
294368369+it("returns structured manual action from the create tool action", async () => {
370+const { tools } = setup(
371+{
372+defaultTransport: "chrome-node",
373+chromeNode: { node: "parallels-macos" },
374+},
375+{
376+nodesInvokeHandler: async (params) => {
377+const proxy = params.params as { path?: string; body?: { url?: string } };
378+if (proxy.path === "/tabs") {
379+return { payload: { result: { tabs: [] } } };
380+}
381+if (proxy.path === "/tabs/open") {
382+return {
383+payload: {
384+result: {
385+targetId: "permission-tab",
386+title: "Meet",
387+url: proxy.body?.url,
388+},
389+},
390+};
391+}
392+if (proxy.path === "/act") {
393+return {
394+payload: {
395+result: {
396+ok: true,
397+targetId: "permission-tab",
398+result: {
399+manualActionReason: "meet-permission-required",
400+manualAction:
401+"Allow microphone/camera permissions for Meet in the OpenClaw browser profile, then retry meeting creation.",
402+browserUrl: "https://meet.google.com/new",
403+browserTitle: "Meet",
404+},
405+},
406+},
407+};
408+}
409+throw new Error(`unexpected browser proxy path ${proxy.path}`);
410+},
411+},
412+);
413+const tool = tools[0] as {
414+execute: (id: string, params: unknown) => Promise<{ details: Record<string, unknown> }>;
415+};
416+417+const result = await tool.execute("id", { action: "create" });
418+419+expect(result.details).toMatchObject({
420+source: "browser",
421+manualActionRequired: true,
422+manualActionReason: "meet-permission-required",
423+manualActionMessage:
424+"Allow microphone/camera permissions for Meet in the OpenClaw browser profile, then retry meeting creation.",
425+browser: {
426+nodeId: "node-1",
427+targetId: "permission-tab",
428+browserUrl: "https://meet.google.com/new",
429+browserTitle: "Meet",
430+},
431+});
432+});
433+295434it("reuses an existing browser create tab instead of opening duplicates", async () => {
296435const { methods, nodesInvoke } = setup(
297436{
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。