@kodelyth/google-meet 2026.5.39 → 2026.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/calendar-CEiBGUl2.js +136 -0
- package/dist/chrome-create-DMyPCiEd.js +965 -0
- package/dist/cli-BMVhSIb8.js +1390 -0
- package/dist/create-IbyMXB3V.js +108 -0
- package/dist/doctor-contract-api.js +56 -0
- package/dist/index.js +4979 -0
- package/dist/oauth-7_sWAae1.js +141 -0
- package/klaw.plugin.json +12 -46
- package/package.json +17 -6
- package/doctor-contract-api.js +0 -7
- package/index.js +0 -7
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { fetchWithSsrFGuard } from "klaw/plugin-sdk/ssrf-runtime";
|
|
2
|
+
import { generateHexPkceVerifierChallenge } from "klaw/plugin-sdk/provider-auth";
|
|
3
|
+
import { generateOAuthState, parseOAuthCallbackInput, waitForLocalOAuthCallback } from "klaw/plugin-sdk/provider-auth-runtime";
|
|
4
|
+
//#region extensions/google-meet/src/oauth.ts
|
|
5
|
+
const GOOGLE_MEET_REDIRECT_URI = "http://localhost:8085/oauth2callback";
|
|
6
|
+
const GOOGLE_MEET_AUTH_URL = "https://accounts.google.com/o/oauth2/v2/auth";
|
|
7
|
+
const GOOGLE_MEET_TOKEN_URL = "https://oauth2.googleapis.com/token";
|
|
8
|
+
const GOOGLE_MEET_TOKEN_HOST = "oauth2.googleapis.com";
|
|
9
|
+
const GOOGLE_MEET_SCOPES = [
|
|
10
|
+
"https://www.googleapis.com/auth/meetings.space.created",
|
|
11
|
+
"https://www.googleapis.com/auth/meetings.space.readonly",
|
|
12
|
+
"https://www.googleapis.com/auth/meetings.space.settings",
|
|
13
|
+
"https://www.googleapis.com/auth/meetings.conference.media.readonly",
|
|
14
|
+
"https://www.googleapis.com/auth/calendar.events.readonly",
|
|
15
|
+
"https://www.googleapis.com/auth/drive.meet.readonly"
|
|
16
|
+
];
|
|
17
|
+
function buildGoogleMeetAuthUrl(params) {
|
|
18
|
+
return `${GOOGLE_MEET_AUTH_URL}?${new URLSearchParams({
|
|
19
|
+
client_id: params.clientId,
|
|
20
|
+
response_type: "code",
|
|
21
|
+
redirect_uri: params.redirectUri ?? GOOGLE_MEET_REDIRECT_URI,
|
|
22
|
+
scope: (params.scopes ?? GOOGLE_MEET_SCOPES).join(" "),
|
|
23
|
+
code_challenge: params.challenge,
|
|
24
|
+
code_challenge_method: "S256",
|
|
25
|
+
access_type: "offline",
|
|
26
|
+
prompt: "consent",
|
|
27
|
+
state: params.state
|
|
28
|
+
}).toString()}`;
|
|
29
|
+
}
|
|
30
|
+
async function executeGoogleTokenRequest(body) {
|
|
31
|
+
const { response, release } = await fetchWithSsrFGuard({
|
|
32
|
+
url: GOOGLE_MEET_TOKEN_URL,
|
|
33
|
+
init: {
|
|
34
|
+
method: "POST",
|
|
35
|
+
headers: {
|
|
36
|
+
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
|
|
37
|
+
Accept: "application/json"
|
|
38
|
+
},
|
|
39
|
+
body
|
|
40
|
+
},
|
|
41
|
+
policy: { allowedHostnames: [GOOGLE_MEET_TOKEN_HOST] },
|
|
42
|
+
auditContext: "google-meet.oauth.token"
|
|
43
|
+
});
|
|
44
|
+
try {
|
|
45
|
+
if (!response.ok) {
|
|
46
|
+
const detail = await response.text();
|
|
47
|
+
throw new Error(`Google OAuth token request failed (${response.status}): ${detail}`);
|
|
48
|
+
}
|
|
49
|
+
const payload = await response.json();
|
|
50
|
+
const accessToken = payload.access_token?.trim();
|
|
51
|
+
if (!accessToken) throw new Error("Google OAuth token response was missing access_token");
|
|
52
|
+
const expiresInSeconds = typeof payload.expires_in === "number" && Number.isFinite(payload.expires_in) ? payload.expires_in : 3600;
|
|
53
|
+
return {
|
|
54
|
+
accessToken,
|
|
55
|
+
expiresAt: Date.now() + expiresInSeconds * 1e3,
|
|
56
|
+
refreshToken: payload.refresh_token?.trim() || void 0,
|
|
57
|
+
scope: payload.scope?.trim() || void 0,
|
|
58
|
+
tokenType: payload.token_type?.trim() || void 0
|
|
59
|
+
};
|
|
60
|
+
} finally {
|
|
61
|
+
await release();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function tokenRequestBody(values) {
|
|
65
|
+
const body = new URLSearchParams();
|
|
66
|
+
for (const [key, value] of Object.entries(values)) if (value?.trim()) body.set(key, value);
|
|
67
|
+
return body;
|
|
68
|
+
}
|
|
69
|
+
async function exchangeGoogleMeetAuthCode(params) {
|
|
70
|
+
return await executeGoogleTokenRequest(tokenRequestBody({
|
|
71
|
+
client_id: params.clientId,
|
|
72
|
+
client_secret: params.clientSecret,
|
|
73
|
+
code: params.code,
|
|
74
|
+
grant_type: "authorization_code",
|
|
75
|
+
redirect_uri: params.redirectUri ?? GOOGLE_MEET_REDIRECT_URI,
|
|
76
|
+
code_verifier: params.verifier
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
async function refreshGoogleMeetAccessToken(params) {
|
|
80
|
+
return await executeGoogleTokenRequest(tokenRequestBody({
|
|
81
|
+
client_id: params.clientId,
|
|
82
|
+
client_secret: params.clientSecret,
|
|
83
|
+
grant_type: "refresh_token",
|
|
84
|
+
refresh_token: params.refreshToken
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
function shouldUseCachedGoogleMeetAccessToken(params) {
|
|
88
|
+
const now = params.now ?? Date.now();
|
|
89
|
+
const safetyWindowMs = params.safetyWindowMs ?? 6e4;
|
|
90
|
+
return Boolean(params.accessToken?.trim() && typeof params.expiresAt === "number" && Number.isFinite(params.expiresAt) && params.expiresAt > now + safetyWindowMs);
|
|
91
|
+
}
|
|
92
|
+
async function resolveGoogleMeetAccessToken(params) {
|
|
93
|
+
if (shouldUseCachedGoogleMeetAccessToken(params)) return {
|
|
94
|
+
accessToken: params.accessToken.trim(),
|
|
95
|
+
expiresAt: params.expiresAt,
|
|
96
|
+
refreshed: false
|
|
97
|
+
};
|
|
98
|
+
if (!params.clientId?.trim() || !params.refreshToken?.trim()) throw new Error("Missing Google Meet OAuth credentials. Configure oauth.clientId and oauth.refreshToken, or pass --client-id and --refresh-token.");
|
|
99
|
+
const refreshed = await refreshGoogleMeetAccessToken({
|
|
100
|
+
clientId: params.clientId,
|
|
101
|
+
clientSecret: params.clientSecret,
|
|
102
|
+
refreshToken: params.refreshToken
|
|
103
|
+
});
|
|
104
|
+
return {
|
|
105
|
+
accessToken: refreshed.accessToken,
|
|
106
|
+
expiresAt: refreshed.expiresAt,
|
|
107
|
+
refreshed: true
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function createGoogleMeetPkce() {
|
|
111
|
+
const { verifier, challenge } = generateHexPkceVerifierChallenge();
|
|
112
|
+
return {
|
|
113
|
+
verifier,
|
|
114
|
+
challenge
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function createGoogleMeetOAuthState() {
|
|
118
|
+
return generateOAuthState();
|
|
119
|
+
}
|
|
120
|
+
async function waitForGoogleMeetAuthCode(params) {
|
|
121
|
+
params.writeLine(`Open this URL in your browser:\n\n${params.authUrl}\n`);
|
|
122
|
+
if (params.manual) {
|
|
123
|
+
const parsed = parseOAuthCallbackInput(await params.promptInput("Paste the full redirect URL here: "), {
|
|
124
|
+
missingState: "Missing 'state' parameter. Paste the full redirect URL.",
|
|
125
|
+
invalidInput: "Paste the full redirect URL, not just the code."
|
|
126
|
+
});
|
|
127
|
+
if ("error" in parsed) throw new Error(parsed.error);
|
|
128
|
+
if (parsed.state !== params.state) throw new Error("OAuth state mismatch - please try again");
|
|
129
|
+
return parsed.code;
|
|
130
|
+
}
|
|
131
|
+
return (await waitForLocalOAuthCallback({
|
|
132
|
+
expectedState: params.state,
|
|
133
|
+
timeoutMs: params.timeoutMs,
|
|
134
|
+
port: 8085,
|
|
135
|
+
callbackPath: "/oauth2callback",
|
|
136
|
+
redirectUri: GOOGLE_MEET_REDIRECT_URI,
|
|
137
|
+
successTitle: "Google Meet OAuth complete"
|
|
138
|
+
})).code;
|
|
139
|
+
}
|
|
140
|
+
//#endregion
|
|
141
|
+
export { buildGoogleMeetAuthUrl, createGoogleMeetOAuthState, createGoogleMeetPkce, exchangeGoogleMeetAuthCode, resolveGoogleMeetAccessToken, waitForGoogleMeetAuthCode };
|
package/klaw.plugin.json
CHANGED
|
@@ -3,24 +3,14 @@
|
|
|
3
3
|
"name": "Google Meet",
|
|
4
4
|
"description": "Join Google Meet calls through Chrome or Twilio transports.",
|
|
5
5
|
"enabledByDefault": false,
|
|
6
|
-
"commandAliases": [
|
|
7
|
-
{
|
|
8
|
-
"name": "googlemeet"
|
|
9
|
-
}
|
|
10
|
-
],
|
|
6
|
+
"commandAliases": [{ "name": "googlemeet" }],
|
|
11
7
|
"activation": {
|
|
12
8
|
"onStartup": true,
|
|
13
|
-
"onCommands": [
|
|
14
|
-
|
|
15
|
-
],
|
|
16
|
-
"onCapabilities": [
|
|
17
|
-
"tool"
|
|
18
|
-
]
|
|
9
|
+
"onCommands": ["googlemeet"],
|
|
10
|
+
"onCapabilities": ["tool"]
|
|
19
11
|
},
|
|
20
12
|
"contracts": {
|
|
21
|
-
"tools": [
|
|
22
|
-
"google_meet"
|
|
23
|
-
]
|
|
13
|
+
"tools": ["google_meet"]
|
|
24
14
|
},
|
|
25
15
|
"uiHints": {
|
|
26
16
|
"defaults.meeting": {
|
|
@@ -251,20 +241,12 @@
|
|
|
251
241
|
},
|
|
252
242
|
"defaultTransport": {
|
|
253
243
|
"type": "string",
|
|
254
|
-
"enum": [
|
|
255
|
-
"chrome",
|
|
256
|
-
"chrome-node",
|
|
257
|
-
"twilio"
|
|
258
|
-
],
|
|
244
|
+
"enum": ["chrome", "chrome-node", "twilio"],
|
|
259
245
|
"default": "chrome"
|
|
260
246
|
},
|
|
261
247
|
"defaultMode": {
|
|
262
248
|
"type": "string",
|
|
263
|
-
"enum": [
|
|
264
|
-
"agent",
|
|
265
|
-
"bidi",
|
|
266
|
-
"transcribe"
|
|
267
|
-
],
|
|
249
|
+
"enum": ["agent", "bidi", "transcribe"],
|
|
268
250
|
"default": "agent"
|
|
269
251
|
},
|
|
270
252
|
"chrome": {
|
|
@@ -273,9 +255,7 @@
|
|
|
273
255
|
"properties": {
|
|
274
256
|
"audioBackend": {
|
|
275
257
|
"type": "string",
|
|
276
|
-
"enum": [
|
|
277
|
-
"blackhole-2ch"
|
|
278
|
-
],
|
|
258
|
+
"enum": ["blackhole-2ch"],
|
|
279
259
|
"default": "blackhole-2ch"
|
|
280
260
|
},
|
|
281
261
|
"launch": {
|
|
@@ -307,10 +287,7 @@
|
|
|
307
287
|
},
|
|
308
288
|
"audioFormat": {
|
|
309
289
|
"type": "string",
|
|
310
|
-
"enum": [
|
|
311
|
-
"pcm16-24khz",
|
|
312
|
-
"g711-ulaw-8khz"
|
|
313
|
-
],
|
|
290
|
+
"enum": ["pcm16-24khz", "g711-ulaw-8khz"],
|
|
314
291
|
"default": "pcm16-24khz"
|
|
315
292
|
},
|
|
316
293
|
"audioBufferBytes": {
|
|
@@ -464,10 +441,7 @@
|
|
|
464
441
|
"properties": {
|
|
465
442
|
"strategy": {
|
|
466
443
|
"type": "string",
|
|
467
|
-
"enum": [
|
|
468
|
-
"agent",
|
|
469
|
-
"bidi"
|
|
470
|
-
],
|
|
444
|
+
"enum": ["agent", "bidi"],
|
|
471
445
|
"default": "agent"
|
|
472
446
|
},
|
|
473
447
|
"provider": {
|
|
@@ -498,11 +472,7 @@
|
|
|
498
472
|
},
|
|
499
473
|
"toolPolicy": {
|
|
500
474
|
"type": "string",
|
|
501
|
-
"enum": [
|
|
502
|
-
"safe-read-only",
|
|
503
|
-
"owner",
|
|
504
|
-
"none"
|
|
505
|
-
],
|
|
475
|
+
"enum": ["safe-read-only", "owner", "none"],
|
|
506
476
|
"default": "safe-read-only"
|
|
507
477
|
},
|
|
508
478
|
"providers": {
|
|
@@ -541,9 +511,7 @@
|
|
|
541
511
|
"properties": {
|
|
542
512
|
"provider": {
|
|
543
513
|
"type": "string",
|
|
544
|
-
"enum": [
|
|
545
|
-
"google-oauth"
|
|
546
|
-
]
|
|
514
|
+
"enum": ["google-oauth"]
|
|
547
515
|
},
|
|
548
516
|
"clientId": {
|
|
549
517
|
"type": "string"
|
|
@@ -559,8 +527,6 @@
|
|
|
559
527
|
}
|
|
560
528
|
},
|
|
561
529
|
"configContracts": {
|
|
562
|
-
"compatibilityMigrationPaths": [
|
|
563
|
-
"plugins.entries.google-meet.config.realtime.provider"
|
|
564
|
-
]
|
|
530
|
+
"compatibilityMigrationPaths": ["plugins.entries.google-meet.config.realtime.provider"]
|
|
565
531
|
}
|
|
566
532
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kodelyth/google-meet",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.6.1",
|
|
4
4
|
"description": "Klaw Google Meet participant plugin",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -13,19 +13,23 @@
|
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"@kodelyth/plugin-sdk": "1.0.1",
|
|
16
|
-
"@kodelyth/klaw": "2026.5.
|
|
16
|
+
"@kodelyth/klaw": "2026.5.42"
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
|
19
|
-
"@kodelyth/klaw": ">=2026.5.19"
|
|
19
|
+
"@kodelyth/klaw": ">=2026.5.19",
|
|
20
|
+
"klaw": ">=2026.5.39"
|
|
20
21
|
},
|
|
21
22
|
"peerDependenciesMeta": {
|
|
22
23
|
"@kodelyth/klaw": {
|
|
23
24
|
"optional": true
|
|
25
|
+
},
|
|
26
|
+
"klaw": {
|
|
27
|
+
"optional": true
|
|
24
28
|
}
|
|
25
29
|
},
|
|
26
30
|
"klaw": {
|
|
27
31
|
"extensions": [
|
|
28
|
-
"./index.
|
|
32
|
+
"./index.ts"
|
|
29
33
|
],
|
|
30
34
|
"install": {
|
|
31
35
|
"npmSpec": "@kodelyth/google-meet",
|
|
@@ -41,6 +45,13 @@
|
|
|
41
45
|
"release": {
|
|
42
46
|
"publishToClawHub": true,
|
|
43
47
|
"publishToNpm": true
|
|
44
|
-
}
|
|
45
|
-
|
|
48
|
+
},
|
|
49
|
+
"runtimeExtensions": [
|
|
50
|
+
"./dist/index.js"
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
"files": [
|
|
54
|
+
"dist/**",
|
|
55
|
+
"klaw.plugin.json"
|
|
56
|
+
]
|
|
46
57
|
}
|
package/doctor-contract-api.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export * from "../../../dist/extensions/google-meet/doctor-contract-api.js";
|
|
2
|
-
import * as module from "../../../dist/extensions/google-meet/doctor-contract-api.js";
|
|
3
|
-
let defaultExport = "default" in module ? module.default : module;
|
|
4
|
-
for (let index = 0; index < 4 && defaultExport && typeof defaultExport === "object" && "default" in defaultExport; index += 1) {
|
|
5
|
-
defaultExport = defaultExport.default;
|
|
6
|
-
}
|
|
7
|
-
export { defaultExport as default };
|
package/index.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export * from "../../../dist/extensions/google-meet/index.js";
|
|
2
|
-
import defaultModule from "../../../dist/extensions/google-meet/index.js";
|
|
3
|
-
let defaultExport = defaultModule;
|
|
4
|
-
for (let index = 0; index < 4 && defaultExport && typeof defaultExport === "object" && "default" in defaultExport; index += 1) {
|
|
5
|
-
defaultExport = defaultExport.default;
|
|
6
|
-
}
|
|
7
|
-
export { defaultExport as default };
|