@openclaw/googlechat 2026.7.1 → 2026.7.2-beta.2
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/actions-B4nbMjmi.js +76 -0
- package/dist/api.js +2 -2
- package/dist/approval-auth-B2m8ckdj.js +30 -0
- package/dist/{approval-handler.runtime-BnkufknT.js → approval-handler.runtime-DH6QCsS8.js} +5 -4
- package/dist/{channel-_o671C-U.js → channel-CST-JKw9.js} +34 -55
- package/dist/{channel-base-DJICAvKH.js → channel-base-fY2AAQj5.js} +1 -2
- package/dist/channel-config-api.js +1 -2
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.adapters-FEj7zUjh.js → channel.adapters-Dhy4lV4f.js} +85 -146
- package/dist/{channel.runtime-CYmt7Ybo.js → channel.runtime-CE5zWkzP.js} +156 -120
- package/dist/config-api-CsD0IFxF.js +3 -0
- package/dist/directory-contract-api.js +1 -1
- package/dist/{doctor-contract-BcEqUZ4j.js → doctor-contract-CvhD0eoX.js} +19 -3
- package/dist/doctor-contract-api.js +1 -1
- package/dist/{runtime-api-BbVoWRxq.js → runtime-api-1v-DgldF.js} +3 -6
- package/dist/runtime-api.js +3 -2
- package/dist/{secret-contract-lCMHqumt.js → secret-contract-D__4IIu_.js} +19 -26
- package/dist/secret-contract-api.js +1 -1
- package/dist/setup-plugin-api.js +1 -1
- package/npm-shrinkwrap.json +3 -4
- package/openclaw.plugin.json +72 -48
- package/package.json +4 -6
- package/dist/actions-BacnMHv0.js +0 -159
- package/dist/approval-auth-C_BVZZFA.js +0 -27
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
import { l as resolveGoogleChatAccount, r as formatGoogleChatAllowFromEntry } from "./channel-base-
|
|
2
|
-
import {
|
|
1
|
+
import { l as resolveGoogleChatAccount, r as formatGoogleChatAllowFromEntry } from "./channel-base-fY2AAQj5.js";
|
|
2
|
+
import { d as fetchWithSsrFGuard$1, i as chunkTextForOutbound, m as missingTargetError, r as PAIRING_APPROVED_MESSAGE } from "./runtime-api-1v-DgldF.js";
|
|
3
3
|
import { buildChannelOutboundSessionRoute } from "openclaw/plugin-sdk/channel-core";
|
|
4
4
|
import { createLazyRuntimeNamedExport } from "openclaw/plugin-sdk/lazy-runtime";
|
|
5
5
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
6
|
-
import crypto from "node:crypto";
|
|
7
6
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
8
|
-
import { parseMediaContentLength } from "openclaw/plugin-sdk/media-runtime";
|
|
9
|
-
import { readProviderJsonResponse, readResponseTextLimited } from "openclaw/plugin-sdk/provider-http";
|
|
7
|
+
import { parseMediaContentLength, readResponseTextSnippet } from "openclaw/plugin-sdk/media-runtime";
|
|
10
8
|
import { readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
|
|
11
9
|
import { buildHostnameAllowlistPolicyFromSuffixAllowlist, fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
10
|
+
import crypto from "node:crypto";
|
|
11
|
+
import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
|
|
12
|
+
import { readProviderJsonResponse } from "openclaw/plugin-sdk/provider-http";
|
|
12
13
|
import { createMessageReceiptFromOutboundResults, defineChannelMessageAdapter, sanitizeForPlainText } from "openclaw/plugin-sdk/channel-outbound";
|
|
13
14
|
import { sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking";
|
|
14
15
|
import fs from "node:fs/promises";
|
|
15
16
|
import { resolveUserPath } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
16
17
|
import { adaptScopedAccountAccessor } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
17
|
-
import { composeAccountWarningCollectors, createAllowlistProviderOpenWarningCollector,
|
|
18
|
+
import { buildChannelGroupsScopeTree, composeAccountWarningCollectors, createAllowlistProviderOpenWarningCollector, resolveScopeRequireMention } from "openclaw/plugin-sdk/channel-policy";
|
|
18
19
|
import { createChannelDirectoryAdapter, listResolvedDirectoryGroupEntriesFromMapKeys, listResolvedDirectoryUserEntriesFromAllowFrom } from "openclaw/plugin-sdk/directory-runtime";
|
|
19
20
|
//#region extensions/googlechat/src/approval-card-actions.ts
|
|
20
21
|
const GOOGLECHAT_APPROVAL_ACTION = "openclaw.approval";
|
|
@@ -24,6 +25,8 @@ const GOOGLECHAT_APPROVAL_ACTION_VALUE = "approval";
|
|
|
24
25
|
const MANUAL_EXEC_APPROVAL_COMMAND_RE = /(?:^|[\s`])\/approve[ \t]+([^ \t\r\n`|]+)[ \t]+(allow-once|allow-always|deny)(?=$|[\s`|.,;:!?])/giu;
|
|
25
26
|
const approvalCardBindings = /* @__PURE__ */ new Map();
|
|
26
27
|
const approvalCardResolvingTokens = /* @__PURE__ */ new Set();
|
|
28
|
+
const GOOGLECHAT_APPROVAL_CARD_BINDING_MAX_ENTRIES = 1024;
|
|
29
|
+
const GOOGLECHAT_MANUAL_APPROVAL_SUPPRESSION_MAX_ENTRIES = 1024;
|
|
27
30
|
const manualApprovalFollowupSuppressions = /* @__PURE__ */ new Map();
|
|
28
31
|
function createGoogleChatApprovalToken() {
|
|
29
32
|
return crypto.randomBytes(18).toString("base64url");
|
|
@@ -53,7 +56,9 @@ function readGoogleChatApprovalActionToken(event) {
|
|
|
53
56
|
}
|
|
54
57
|
function registerGoogleChatApprovalCardBinding(binding) {
|
|
55
58
|
if (binding.expiresAtMs <= Date.now()) return false;
|
|
59
|
+
if (approvalCardBindings.has(binding.token)) approvalCardBindings.delete(binding.token);
|
|
56
60
|
approvalCardBindings.set(binding.token, binding);
|
|
61
|
+
pruneMapToMaxSize(approvalCardBindings, GOOGLECHAT_APPROVAL_CARD_BINDING_MAX_ENTRIES);
|
|
57
62
|
registerGoogleChatManualApprovalFollowupSuppression({
|
|
58
63
|
approvalId: binding.approvalId,
|
|
59
64
|
approvalKind: binding.approvalKind,
|
|
@@ -82,7 +87,9 @@ function registerGoogleChatManualApprovalFollowupSuppression(suppression) {
|
|
|
82
87
|
if (suppression.expiresAtMs <= Date.now()) return false;
|
|
83
88
|
const key = manualApprovalFollowupSuppressionKey(suppression.approvalId);
|
|
84
89
|
if (!key) return false;
|
|
90
|
+
if (manualApprovalFollowupSuppressions.has(key)) manualApprovalFollowupSuppressions.delete(key);
|
|
85
91
|
manualApprovalFollowupSuppressions.set(key, suppression);
|
|
92
|
+
pruneMapToMaxSize(manualApprovalFollowupSuppressions, GOOGLECHAT_MANUAL_APPROVAL_SUPPRESSION_MAX_ENTRIES);
|
|
86
93
|
return true;
|
|
87
94
|
}
|
|
88
95
|
function unregisterGoogleChatManualApprovalFollowupSuppression(approvalId) {
|
|
@@ -161,7 +168,7 @@ function unregisterGoogleChatApprovalCardBindings(tokens) {
|
|
|
161
168
|
//#endregion
|
|
162
169
|
//#region extensions/googlechat/src/google-auth.runtime.ts
|
|
163
170
|
const GOOGLE_AUTH_POLICY = buildHostnameAllowlistPolicyFromSuffixAllowlist(["accounts.google.com", "googleapis.com"]);
|
|
164
|
-
const
|
|
171
|
+
const GOOGLE_AUTH_FETCH_TIMEOUT_MS = 3e4;
|
|
165
172
|
const GOOGLE_AUTH_URI = "https://accounts.google.com/o/oauth2/auth";
|
|
166
173
|
const GOOGLE_AUTH_PROVIDER_CERTS_URL = "https://www.googleapis.com/oauth2/v1/certs";
|
|
167
174
|
const GOOGLE_AUTH_TOKEN_URI = "https://oauth2.googleapis.com/token";
|
|
@@ -376,17 +383,18 @@ function resolveGoogleAuthDispatcherPolicy(input, init) {
|
|
|
376
383
|
};
|
|
377
384
|
return { init: nextInit };
|
|
378
385
|
}
|
|
379
|
-
function createGoogleAuthFetch(
|
|
386
|
+
function createGoogleAuthFetch() {
|
|
380
387
|
return async (input, init) => {
|
|
381
388
|
const url = input instanceof Request ? input.url : String(input);
|
|
382
389
|
const guardedOptions = resolveGoogleAuthDispatcherPolicy(input, init);
|
|
383
390
|
const { response, release } = await fetchWithSsrFGuard({
|
|
384
|
-
auditContext:
|
|
391
|
+
auditContext: "googlechat.auth.google-auth",
|
|
385
392
|
dispatcherPolicy: guardedOptions.dispatcherPolicy,
|
|
386
393
|
init: guardedOptions.init,
|
|
387
394
|
policy: GOOGLE_AUTH_POLICY,
|
|
388
|
-
|
|
389
|
-
|
|
395
|
+
signal: guardedOptions.init?.signal ?? void 0,
|
|
396
|
+
timeoutMs: GOOGLE_AUTH_FETCH_TIMEOUT_MS,
|
|
397
|
+
url
|
|
390
398
|
});
|
|
391
399
|
try {
|
|
392
400
|
const body = await readGoogleAuthResponseBytes(response);
|
|
@@ -437,24 +445,15 @@ async function readGoogleAuthResponseBytes(response) {
|
|
|
437
445
|
return bytes;
|
|
438
446
|
}
|
|
439
447
|
async function loadGoogleAuthRuntime() {
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
Gaxios: gaxiosModule.Gaxios,
|
|
445
|
-
GoogleAuth: googleAuthModule.GoogleAuth,
|
|
446
|
-
OAuth2Client: googleAuthModule.OAuth2Client
|
|
447
|
-
};
|
|
448
|
-
} catch (error) {
|
|
449
|
-
googleAuthRuntimePromise = null;
|
|
450
|
-
throw error;
|
|
451
|
-
}
|
|
452
|
-
})();
|
|
448
|
+
googleAuthRuntimePromise ??= import("google-auth-library").catch((error) => {
|
|
449
|
+
googleAuthRuntimePromise = null;
|
|
450
|
+
throw error;
|
|
451
|
+
});
|
|
453
452
|
return await googleAuthRuntimePromise;
|
|
454
453
|
}
|
|
455
454
|
async function getGoogleAuthTransport() {
|
|
456
|
-
const {
|
|
457
|
-
return installGoogleAuthHeaderCompatibilityInterceptor(new Gaxios({ fetchImplementation: createGoogleAuthFetch() }));
|
|
455
|
+
const { gaxios } = await loadGoogleAuthRuntime();
|
|
456
|
+
return installGoogleAuthHeaderCompatibilityInterceptor(new gaxios.Gaxios({ fetchImplementation: createGoogleAuthFetch() }));
|
|
458
457
|
}
|
|
459
458
|
async function resolveValidatedGoogleChatCredentials(account) {
|
|
460
459
|
if (account.credentials) return validateGoogleChatServiceAccountCredentials(account.credentials);
|
|
@@ -467,6 +466,7 @@ const CHAT_SCOPE = "https://www.googleapis.com/auth/chat.bot";
|
|
|
467
466
|
const CHAT_ISSUER = "chat@system.gserviceaccount.com";
|
|
468
467
|
const ADDON_ISSUER_PATTERN = /^service-\d+@gcp-sa-gsuiteaddons\.iam\.gserviceaccount\.com$/;
|
|
469
468
|
const CHAT_CERTS_URL = "https://www.googleapis.com/service_accounts/v1/metadata/x509/chat@system.gserviceaccount.com";
|
|
469
|
+
const GOOGLECHAT_CERT_FETCH_TIMEOUT_MS = 3e4;
|
|
470
470
|
async function readGoogleChatCertsResponse(response) {
|
|
471
471
|
return readProviderJsonResponse(response, "Google Chat cert fetch failed");
|
|
472
472
|
}
|
|
@@ -495,12 +495,11 @@ async function getAuthInstance(account) {
|
|
|
495
495
|
const key = buildAuthKey(account);
|
|
496
496
|
const cached = authCache.get(account.accountId);
|
|
497
497
|
if (cached && cached.key === key) return cached.auth;
|
|
498
|
-
const [{ GoogleAuth },
|
|
498
|
+
const [{ GoogleAuth }, transporter, credentials] = await Promise.all([
|
|
499
499
|
loadGoogleAuthRuntime(),
|
|
500
500
|
getGoogleAuthTransport(),
|
|
501
501
|
resolveValidatedGoogleChatCredentials(account)
|
|
502
502
|
]);
|
|
503
|
-
const transporter = rawTransporter;
|
|
504
503
|
const evictOldest = () => {
|
|
505
504
|
if (authCache.size > MAX_AUTH_CACHE_SIZE) {
|
|
506
505
|
const oldest = authCache.keys().next().value;
|
|
@@ -530,7 +529,8 @@ async function fetchChatCerts() {
|
|
|
530
529
|
if (cachedCerts && now - cachedCerts.fetchedAt < 600 * 1e3) return cachedCerts.certs;
|
|
531
530
|
const { response, release } = await fetchWithSsrFGuard$1({
|
|
532
531
|
url: CHAT_CERTS_URL,
|
|
533
|
-
auditContext: "googlechat.auth.certs"
|
|
532
|
+
auditContext: "googlechat.auth.certs",
|
|
533
|
+
timeoutMs: GOOGLECHAT_CERT_FETCH_TIMEOUT_MS
|
|
534
534
|
});
|
|
535
535
|
try {
|
|
536
536
|
if (!response.ok) throw new Error(`Failed to fetch Chat certs (${response.status})`);
|
|
@@ -607,13 +607,41 @@ async function verifyGoogleChatRequest(params) {
|
|
|
607
607
|
//#endregion
|
|
608
608
|
//#region extensions/googlechat/src/api.ts
|
|
609
609
|
const CHAT_API_BASE = "https://chat.googleapis.com/v1";
|
|
610
|
-
const
|
|
610
|
+
const GOOGLECHAT_API_TIMEOUT_MS = 3e4;
|
|
611
|
+
const GOOGLECHAT_MEDIA_TIMEOUT_GRACE_MS = 3e4;
|
|
612
|
+
const GOOGLECHAT_MEDIA_MIN_BYTES_PER_SECOND = 256 * 1024;
|
|
613
|
+
const GOOGLECHAT_MEDIA_MAX_TIMEOUT_MS = 15 * 6e4;
|
|
614
|
+
const GOOGLECHAT_RESPONSE_READ_IDLE_TIMEOUT_MS = 3e4;
|
|
615
|
+
const GOOGLECHAT_JSON_RESPONSE_MAX_BYTES = 16 * 1024 * 1024;
|
|
616
|
+
const GOOGLECHAT_ERROR_BODY_MAX_BYTES = 16 * 1024;
|
|
617
|
+
function resolveGoogleChatMediaTimeoutMs(maxBytes) {
|
|
618
|
+
if (!maxBytes) return GOOGLECHAT_MEDIA_MAX_TIMEOUT_MS;
|
|
619
|
+
const transferMs = Math.ceil(maxBytes / GOOGLECHAT_MEDIA_MIN_BYTES_PER_SECOND * 1e3);
|
|
620
|
+
return Math.min(GOOGLECHAT_MEDIA_TIMEOUT_GRACE_MS + transferMs, GOOGLECHAT_MEDIA_MAX_TIMEOUT_MS);
|
|
621
|
+
}
|
|
611
622
|
async function readGoogleChatJsonResponse(response, label) {
|
|
612
|
-
|
|
623
|
+
const bytes = await readResponseWithLimit(response, GOOGLECHAT_JSON_RESPONSE_MAX_BYTES, {
|
|
624
|
+
chunkTimeoutMs: GOOGLECHAT_RESPONSE_READ_IDLE_TIMEOUT_MS,
|
|
625
|
+
onIdleTimeout: ({ chunkTimeoutMs }) => /* @__PURE__ */ new Error(`${label}: response body stalled after ${chunkTimeoutMs}ms`),
|
|
626
|
+
onOverflow: ({ maxBytes }) => /* @__PURE__ */ new Error(`${label}: JSON response exceeds ${maxBytes} bytes`)
|
|
627
|
+
});
|
|
628
|
+
try {
|
|
629
|
+
return JSON.parse(new TextDecoder().decode(bytes));
|
|
630
|
+
} catch (cause) {
|
|
631
|
+
throw new Error(`${label}: malformed JSON response`, { cause });
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
async function readGoogleChatErrorResponse(response, label) {
|
|
635
|
+
return await readResponseTextSnippet(response, {
|
|
636
|
+
maxBytes: GOOGLECHAT_ERROR_BODY_MAX_BYTES,
|
|
637
|
+
maxChars: GOOGLECHAT_ERROR_BODY_MAX_BYTES,
|
|
638
|
+
chunkTimeoutMs: GOOGLECHAT_RESPONSE_READ_IDLE_TIMEOUT_MS,
|
|
639
|
+
onIdleTimeout: ({ chunkTimeoutMs }) => /* @__PURE__ */ new Error(`${label} error response stalled after ${chunkTimeoutMs}ms`)
|
|
640
|
+
}) ?? "";
|
|
613
641
|
}
|
|
614
642
|
const headersToObject = (headers) => headers instanceof Headers ? Object.fromEntries(headers.entries()) : Array.isArray(headers) ? Object.fromEntries(headers) : headers || {};
|
|
615
643
|
async function withGoogleChatResponse(params) {
|
|
616
|
-
const { account, url, init, auditContext, errorPrefix = "Google Chat API", handleResponse } = params;
|
|
644
|
+
const { account, url, init, auditContext, errorPrefix = "Google Chat API", timeoutMs = GOOGLECHAT_API_TIMEOUT_MS, handleResponse } = params;
|
|
617
645
|
const token = await getGoogleChatAccessToken(account);
|
|
618
646
|
const { response, release } = await fetchWithSsrFGuard({
|
|
619
647
|
url,
|
|
@@ -624,11 +652,12 @@ async function withGoogleChatResponse(params) {
|
|
|
624
652
|
Authorization: `Bearer ${token}`
|
|
625
653
|
}
|
|
626
654
|
},
|
|
627
|
-
auditContext
|
|
655
|
+
auditContext,
|
|
656
|
+
timeoutMs
|
|
628
657
|
});
|
|
629
658
|
try {
|
|
630
659
|
if (!response.ok) {
|
|
631
|
-
const text = await
|
|
660
|
+
const text = await readGoogleChatErrorResponse(response, errorPrefix);
|
|
632
661
|
throw new Error(`${errorPrefix} ${response.status}: ${text || response.statusText}`);
|
|
633
662
|
}
|
|
634
663
|
return await handleResponse(response);
|
|
@@ -666,6 +695,7 @@ async function fetchBuffer(account, url, init, options) {
|
|
|
666
695
|
url,
|
|
667
696
|
init,
|
|
668
697
|
auditContext: "googlechat.api.buffer",
|
|
698
|
+
timeoutMs: resolveGoogleChatMediaTimeoutMs(options?.maxBytes),
|
|
669
699
|
handleResponse: async (res) => {
|
|
670
700
|
const maxBytes = options?.maxBytes;
|
|
671
701
|
const lengthHeader = res.headers.get("content-length");
|
|
@@ -678,20 +708,22 @@ async function fetchBuffer(account, url, init, options) {
|
|
|
678
708
|
contentType: res.headers.get("content-type") ?? void 0
|
|
679
709
|
};
|
|
680
710
|
return {
|
|
681
|
-
buffer: await readResponseWithLimit(res, maxBytes, {
|
|
711
|
+
buffer: await readResponseWithLimit(res, maxBytes, {
|
|
712
|
+
chunkTimeoutMs: GOOGLECHAT_RESPONSE_READ_IDLE_TIMEOUT_MS,
|
|
713
|
+
onOverflow: () => /* @__PURE__ */ new Error(`Google Chat media exceeds max bytes (${maxBytes})`)
|
|
714
|
+
}),
|
|
682
715
|
contentType: res.headers.get("content-type") ?? void 0
|
|
683
716
|
};
|
|
684
717
|
}
|
|
685
718
|
});
|
|
686
719
|
}
|
|
687
720
|
async function sendGoogleChatMessage(params) {
|
|
688
|
-
const { account, space, text, thread, cardsV2
|
|
689
|
-
if (text && (!cardsV2 || cardsV2.length === 0) &&
|
|
721
|
+
const { account, space, text, thread, cardsV2 } = params;
|
|
722
|
+
if (text && (!cardsV2 || cardsV2.length === 0) && shouldSuppressGoogleChatManualExecApprovalFollowupText(text)) return null;
|
|
690
723
|
const body = {};
|
|
691
724
|
if (text) body.text = text;
|
|
692
725
|
if (cardsV2 && cardsV2.length > 0) body.cardsV2 = cardsV2;
|
|
693
726
|
if (thread) body.thread = { name: thread };
|
|
694
|
-
if (attachments && attachments.length > 0) body.attachment = attachments.map((item) => Object.assign({ attachmentDataRef: { attachmentUploadToken: item.attachmentUploadToken } }, item.contentName ? { contentName: item.contentName } : {}));
|
|
695
727
|
const urlObj = new URL(`${CHAT_API_BASE}/${space}/messages`);
|
|
696
728
|
if (thread) urlObj.searchParams.set("messageReplyOption", "REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD");
|
|
697
729
|
const result = await fetchJson(account, urlObj.toString(), {
|
|
@@ -720,52 +752,10 @@ async function deleteGoogleChatMessage(params) {
|
|
|
720
752
|
const { account, messageName } = params;
|
|
721
753
|
await fetchOk(account, `${CHAT_API_BASE}/${messageName}`, { method: "DELETE" });
|
|
722
754
|
}
|
|
723
|
-
async function uploadGoogleChatAttachment(params) {
|
|
724
|
-
const { account, space, filename, buffer, contentType } = params;
|
|
725
|
-
const boundary = `openclaw-${crypto.randomUUID()}`;
|
|
726
|
-
const header = `--${boundary}\r\nContent-Type: application/json; charset=UTF-8\r\n\r\n${JSON.stringify({ filename })}\r\n`;
|
|
727
|
-
const mediaHeader = `--${boundary}\r\nContent-Type: ${contentType ?? "application/octet-stream"}\r\n\r\n`;
|
|
728
|
-
const footer = `\r\n--${boundary}--\r\n`;
|
|
729
|
-
const body = Buffer.concat([
|
|
730
|
-
Buffer.from(header, "utf8"),
|
|
731
|
-
Buffer.from(mediaHeader, "utf8"),
|
|
732
|
-
buffer,
|
|
733
|
-
Buffer.from(footer, "utf8")
|
|
734
|
-
]);
|
|
735
|
-
return { attachmentUploadToken: (await withGoogleChatResponse({
|
|
736
|
-
account,
|
|
737
|
-
url: `${CHAT_UPLOAD_BASE}/${space}/attachments:upload?uploadType=multipart`,
|
|
738
|
-
init: {
|
|
739
|
-
method: "POST",
|
|
740
|
-
headers: { "Content-Type": `multipart/related; boundary=${boundary}` },
|
|
741
|
-
body
|
|
742
|
-
},
|
|
743
|
-
auditContext: "googlechat.upload",
|
|
744
|
-
errorPrefix: "Google Chat upload",
|
|
745
|
-
handleResponse: async (response) => await readGoogleChatJsonResponse(response, "Google Chat upload failed")
|
|
746
|
-
})).attachmentDataRef?.attachmentUploadToken };
|
|
747
|
-
}
|
|
748
755
|
async function downloadGoogleChatMedia(params) {
|
|
749
756
|
const { account, resourceName, maxBytes } = params;
|
|
750
757
|
return await fetchBuffer(account, `${CHAT_API_BASE}/media/${resourceName}?alt=media`, void 0, { maxBytes });
|
|
751
758
|
}
|
|
752
|
-
async function createGoogleChatReaction(params) {
|
|
753
|
-
const { account, messageName, emoji } = params;
|
|
754
|
-
return await fetchJson(account, `${CHAT_API_BASE}/${messageName}/reactions`, {
|
|
755
|
-
method: "POST",
|
|
756
|
-
body: JSON.stringify({ emoji: { unicode: emoji } })
|
|
757
|
-
});
|
|
758
|
-
}
|
|
759
|
-
async function listGoogleChatReactions(params) {
|
|
760
|
-
const { account, messageName, limit } = params;
|
|
761
|
-
const url = new URL(`${CHAT_API_BASE}/${messageName}/reactions`);
|
|
762
|
-
if (limit && limit > 0) url.searchParams.set("pageSize", String(limit));
|
|
763
|
-
return (await fetchJson(account, url.toString(), { method: "GET" })).reactions ?? [];
|
|
764
|
-
}
|
|
765
|
-
async function deleteGoogleChatReaction(params) {
|
|
766
|
-
const { account, reactionName } = params;
|
|
767
|
-
await fetchOk(account, `${CHAT_API_BASE}/${reactionName}`, { method: "DELETE" });
|
|
768
|
-
}
|
|
769
759
|
async function findGoogleChatDirectMessage(params) {
|
|
770
760
|
const { account, userName } = params;
|
|
771
761
|
const url = new URL(`${CHAT_API_BASE}/spaces:findDirectMessage`);
|
|
@@ -876,17 +866,23 @@ async function resolveGoogleChatOutboundSessionRoute(params) {
|
|
|
876
866
|
}
|
|
877
867
|
//#endregion
|
|
878
868
|
//#region extensions/googlechat/src/group-policy.ts
|
|
869
|
+
function buildGoogleChatGroupPolicyScope(params) {
|
|
870
|
+
const matchKey = params.groupId && Object.hasOwn(params.tree.scopes, params.groupId) ? params.groupId : void 0;
|
|
871
|
+
return {
|
|
872
|
+
tree: params.tree,
|
|
873
|
+
path: matchKey ? [matchKey] : [],
|
|
874
|
+
matchKey
|
|
875
|
+
};
|
|
876
|
+
}
|
|
879
877
|
function resolveGoogleChatGroupRequireMention(params) {
|
|
880
|
-
return
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
accountId: params.accountId
|
|
885
|
-
});
|
|
878
|
+
return resolveScopeRequireMention(buildGoogleChatGroupPolicyScope({
|
|
879
|
+
tree: buildChannelGroupsScopeTree(params.cfg, "googlechat", params.accountId),
|
|
880
|
+
groupId: params.groupId
|
|
881
|
+
}));
|
|
886
882
|
}
|
|
887
883
|
//#endregion
|
|
888
884
|
//#region extensions/googlechat/src/channel.adapters.ts
|
|
889
|
-
const loadGoogleChatChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-
|
|
885
|
+
const loadGoogleChatChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-CE5zWkzP.js"), "googleChatChannelRuntime");
|
|
890
886
|
function createGoogleChatSendReceipt(params) {
|
|
891
887
|
const messageId = params.messageId?.trim();
|
|
892
888
|
return createMessageReceiptFromOutboundResults({
|
|
@@ -1035,59 +1031,6 @@ const googlechatOutboundAdapter = {
|
|
|
1035
1031
|
kind: "text"
|
|
1036
1032
|
})
|
|
1037
1033
|
};
|
|
1038
|
-
},
|
|
1039
|
-
sendMedia: async ({ cfg, to, text, mediaUrl, mediaAccess, mediaLocalRoots, mediaReadFile, accountId, replyToId, threadId }) => {
|
|
1040
|
-
if (!mediaUrl) throw new Error("Google Chat mediaUrl is required.");
|
|
1041
|
-
const account = resolveGoogleChatAccount({
|
|
1042
|
-
cfg,
|
|
1043
|
-
accountId
|
|
1044
|
-
});
|
|
1045
|
-
const space = await resolveGoogleChatOutboundSpace({
|
|
1046
|
-
account,
|
|
1047
|
-
target: to
|
|
1048
|
-
});
|
|
1049
|
-
const thread = typeof threadId === "number" ? String(threadId) : threadId ?? replyToId ?? void 0;
|
|
1050
|
-
const effectiveMaxBytes = resolveChannelMediaMaxBytes({
|
|
1051
|
-
cfg,
|
|
1052
|
-
resolveChannelLimitMb: ({ cfg: cfgLocal, accountId: accountIdLocal }) => (cfgLocal.channels?.googlechat)?.accounts?.[accountIdLocal]?.mediaMaxMb ?? (cfgLocal.channels?.googlechat)?.mediaMaxMb,
|
|
1053
|
-
accountId
|
|
1054
|
-
}) ?? (account.config.mediaMaxMb ?? 20) * 1024 * 1024;
|
|
1055
|
-
const loaded = /^https?:\/\//i.test(mediaUrl) ? await readRemoteMediaBuffer({
|
|
1056
|
-
url: mediaUrl,
|
|
1057
|
-
maxBytes: effectiveMaxBytes
|
|
1058
|
-
}) : await loadOutboundMediaFromUrl(mediaUrl, {
|
|
1059
|
-
maxBytes: effectiveMaxBytes,
|
|
1060
|
-
mediaAccess,
|
|
1061
|
-
mediaLocalRoots,
|
|
1062
|
-
mediaReadFile
|
|
1063
|
-
});
|
|
1064
|
-
const { sendGoogleChatMessage, uploadGoogleChatAttachment } = await loadGoogleChatChannelRuntime();
|
|
1065
|
-
const upload = await uploadGoogleChatAttachment({
|
|
1066
|
-
account,
|
|
1067
|
-
space,
|
|
1068
|
-
filename: loaded.fileName ?? "attachment",
|
|
1069
|
-
buffer: loaded.buffer,
|
|
1070
|
-
contentType: loaded.contentType
|
|
1071
|
-
});
|
|
1072
|
-
const messageId = (await sendGoogleChatMessage({
|
|
1073
|
-
account,
|
|
1074
|
-
space,
|
|
1075
|
-
text,
|
|
1076
|
-
thread,
|
|
1077
|
-
attachments: upload.attachmentUploadToken ? [{
|
|
1078
|
-
attachmentUploadToken: upload.attachmentUploadToken,
|
|
1079
|
-
contentName: loaded.fileName
|
|
1080
|
-
}] : void 0
|
|
1081
|
-
}))?.messageName ?? "";
|
|
1082
|
-
return {
|
|
1083
|
-
messageId,
|
|
1084
|
-
chatId: space,
|
|
1085
|
-
receipt: createGoogleChatSendReceipt({
|
|
1086
|
-
messageId,
|
|
1087
|
-
chatId: space,
|
|
1088
|
-
kind: "media"
|
|
1089
|
-
})
|
|
1090
|
-
};
|
|
1091
1034
|
}
|
|
1092
1035
|
}
|
|
1093
1036
|
};
|
|
@@ -1095,14 +1038,10 @@ const googlechatMessageAdapter = defineChannelMessageAdapter({
|
|
|
1095
1038
|
id: "googlechat",
|
|
1096
1039
|
durableFinal: { capabilities: {
|
|
1097
1040
|
text: true,
|
|
1098
|
-
media: true,
|
|
1099
1041
|
thread: true,
|
|
1100
1042
|
messageSendingHooks: true
|
|
1101
1043
|
} },
|
|
1102
|
-
send: {
|
|
1103
|
-
text: googlechatOutboundAdapter.attachedResults.sendText,
|
|
1104
|
-
media: googlechatOutboundAdapter.attachedResults.sendMedia
|
|
1105
|
-
}
|
|
1044
|
+
send: { text: googlechatOutboundAdapter.attachedResults.sendText }
|
|
1106
1045
|
});
|
|
1107
1046
|
//#endregion
|
|
1108
|
-
export {
|
|
1047
|
+
export { releaseGoogleChatApprovalCardBinding as A, claimGoogleChatApprovalCardBinding as C, readGoogleChatApprovalActionToken as D, getGoogleChatApprovalCardBinding as E, unregisterGoogleChatManualApprovalFollowupSuppression as M, registerGoogleChatApprovalCardBinding as O, buildGoogleChatApprovalActionParameters as S, createGoogleChatApprovalToken as T, probeGoogleChat as _, googlechatPairingTextAdapter as a, verifyGoogleChatRequest as b, buildGoogleChatGroupPolicyScope as c, isGoogleChatUserTarget as d, normalizeGoogleChatTarget as f, downloadGoogleChatMedia as g, deleteGoogleChatMessage as h, googlechatOutboundAdapter as i, unregisterGoogleChatApprovalCardBindings as j, registerGoogleChatManualApprovalFollowupSuppression as k, isGoogleChatGroupSpace as l, resolveGoogleChatOutboundSpace as m, googlechatGroupsAdapter as n, googlechatSecurityAdapter as o, resolveGoogleChatOutboundSessionRoute as p, googlechatMessageAdapter as r, googlechatThreadingAdapter as s, googlechatDirectoryAdapter as t, isGoogleChatSpaceTarget as u, sendGoogleChatMessage as v, completeGoogleChatApprovalCardBinding as w, GOOGLECHAT_APPROVAL_ACTION as x, updateGoogleChatMessage as y };
|