diff --git a/extensions/google-meet/src/cli.test.ts b/extensions/google-meet/src/cli.test.ts index 5a638aecce07..d8097255b081 100644 --- a/extensions/google-meet/src/cli.test.ts +++ b/extensions/google-meet/src/cli.test.ts @@ -832,6 +832,50 @@ describe("google-meet CLI", () => { } }); + it.each([ + ["0", 0], + ["3", 3], + ["+3", 3], + [" 3 ", 3], + [String(Number.MAX_SAFE_INTEGER), Number.MAX_SAFE_INTEGER], + ] as const)("accepts base-10 safe transcript cursors: %s", async (since, expected) => { + const callGatewayFromCli = vi.fn(async () => ({ + found: true, + sessionId: "meet_gateway", + startIndex: expected, + nextIndex: expected, + lines: [], + })); + + await setupCli({ callGatewayFromCli }).parseAsync( + ["googlemeet", "transcript", "meet_gateway", "--since", since], + { from: "user" }, + ); + + expect(callGatewayFromCli).toHaveBeenCalledWith( + "googlemeet.transcript", + { json: true, timeout: "5000" }, + { sessionId: "meet_gateway", sinceIndex: expected }, + { progress: false }, + ); + }); + + it.each(["", " ", "-1", "0x10", "0o10", "0b10", "1e0", "1.5", "9007199254740992"])( + "rejects non-decimal transcript cursors before gateway delegation: %s", + async (since) => { + const callGatewayFromCli = vi.fn(); + + await expect( + setupCli({ callGatewayFromCli }).parseAsync( + ["googlemeet", "transcript", "meet_gateway", "--since", since], + { from: "user" }, + ), + ).rejects.toThrow("--since must be a non-negative safe integer"); + + expect(callGatewayFromCli).not.toHaveBeenCalled(); + }, + ); + it("delegates join to the gateway-owned runtime when available", async () => { const callGatewayFromCli = vi.fn(async () => ({ session: { diff --git a/extensions/google-meet/src/cli.ts b/extensions/google-meet/src/cli.ts index efac5d9499e0..1f5a091aceee 100644 --- a/extensions/google-meet/src/cli.ts +++ b/extensions/google-meet/src/cli.ts @@ -1,4 +1,3 @@ -// Google Meet plugin module implements cli behavior. import { mkdir, writeFile } from "node:fs/promises"; import path from "node:path"; import { createInterface } from "node:readline/promises"; @@ -9,6 +8,7 @@ import { expectDefined } from "openclaw/plugin-sdk/expect-runtime"; import { callGatewayFromCli } from "openclaw/plugin-sdk/gateway-runtime"; import { clampTimerTimeoutMs, + parseStrictNonNegativeInteger, parseStrictPositiveInteger, } from "openclaw/plugin-sdk/number-runtime"; import prettyMilliseconds from "pretty-ms"; @@ -2263,8 +2263,8 @@ export function registerGoogleMeetCli(params: { .option("--since ", "Resume from the previous response's nextIndex") .option("--json", "Print JSON output", false) .action(async (sessionId: string, options: { since?: string; json?: boolean }) => { - const sinceIndex = options.since === undefined ? undefined : Number(options.since); - if (sinceIndex !== undefined && (!Number.isSafeInteger(sinceIndex) || sinceIndex < 0)) { + const sinceIndex = parseStrictNonNegativeInteger(options.since); + if (options.since !== undefined && sinceIndex === undefined) { throw new Error("--since must be a non-negative safe integer"); } const delegated = await callGoogleMeetGateway({