@openclaw/googlechat 2026.5.14-beta.1 → 2026.5.16-beta.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/{actions-C__ryYKJ.js → actions-CpWMO4Q6.js} +3 -3
- package/dist/{api-CBWAN9YL.js → api-BJ9DOsBR.js} +17 -3
- package/dist/api.js +2 -2
- package/dist/{channel-BpW0Eiw7.js → channel-Bf5PtC25.js} +49 -10
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-CKDAMPpq.js → channel.runtime-DFdC1y3n.js} +1 -1
- package/dist/contract-api.js +2 -2
- package/dist/doctor-contract-api.js +1 -1
- package/dist/secret-contract-api.js +1 -1
- package/dist/setup-plugin-api.js +1 -2
- package/dist/setup-surface-Q6Vgbsv2.js +314 -0
- package/dist/test-api.js +1 -1
- package/package.json +4 -4
- package/dist/accounts-BlfWEj_G.js +0 -100
- package/dist/setup-surface-Cr3BORD4.js +0 -217
- package/dist/targets-AuEcZdcJ.js +0 -43
- /package/dist/{doctor-contract-BsERSjSe.js → doctor-contract-CG1sLToP.js} +0 -0
- /package/dist/{secret-contract-DLAG2_NI.js → secret-contract-DtQ_IO7J.js} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { o as resolveGoogleChatAccount, r as listEnabledGoogleChatAccounts } from "./setup-surface-Q6Vgbsv2.js";
|
|
2
2
|
import { P as getGoogleChatRuntime } from "./runtime-api-DuEfWHnr.js";
|
|
3
|
-
import { c as sendGoogleChatMessage, o as listGoogleChatReactions, r as deleteGoogleChatReaction, t as createGoogleChatReaction, u as uploadGoogleChatAttachment } from "./api-
|
|
4
|
-
import {
|
|
3
|
+
import { c as sendGoogleChatMessage, o as listGoogleChatReactions, r as deleteGoogleChatReaction, t as createGoogleChatReaction, u as uploadGoogleChatAttachment } from "./api-BJ9DOsBR.js";
|
|
4
|
+
import { n as resolveGoogleChatOutboundSpace } from "./channel-Bf5PtC25.js";
|
|
5
5
|
import { extractToolSend } from "openclaw/plugin-sdk/tool-send";
|
|
6
6
|
import { createActionGate, jsonResult, readNumberParam, readReactionParams, readStringParam } from "openclaw/plugin-sdk/channel-actions";
|
|
7
7
|
import { loadOutboundMediaFromUrl } from "openclaw/plugin-sdk/outbound-media";
|
|
@@ -314,6 +314,13 @@ const CHAT_SCOPE = "https://www.googleapis.com/auth/chat.bot";
|
|
|
314
314
|
const CHAT_ISSUER = "chat@system.gserviceaccount.com";
|
|
315
315
|
const ADDON_ISSUER_PATTERN = /^service-\d+@gcp-sa-gsuiteaddons\.iam\.gserviceaccount\.com$/;
|
|
316
316
|
const CHAT_CERTS_URL = "https://www.googleapis.com/service_accounts/v1/metadata/x509/chat@system.gserviceaccount.com";
|
|
317
|
+
async function readGoogleChatCertsResponse(response) {
|
|
318
|
+
try {
|
|
319
|
+
return await response.json();
|
|
320
|
+
} catch (cause) {
|
|
321
|
+
throw new Error("Google Chat cert fetch failed: malformed JSON response", { cause });
|
|
322
|
+
}
|
|
323
|
+
}
|
|
317
324
|
const MAX_AUTH_CACHE_SIZE = 32;
|
|
318
325
|
const authCache = /* @__PURE__ */ new Map();
|
|
319
326
|
let cachedCerts = null;
|
|
@@ -378,7 +385,7 @@ async function fetchChatCerts() {
|
|
|
378
385
|
});
|
|
379
386
|
try {
|
|
380
387
|
if (!response.ok) throw new Error(`Failed to fetch Chat certs (${response.status})`);
|
|
381
|
-
const certs = await response
|
|
388
|
+
const certs = await readGoogleChatCertsResponse(response);
|
|
382
389
|
cachedCerts = {
|
|
383
390
|
fetchedAt: now,
|
|
384
391
|
certs
|
|
@@ -452,6 +459,13 @@ async function verifyGoogleChatRequest(params) {
|
|
|
452
459
|
//#region extensions/googlechat/src/api.ts
|
|
453
460
|
const CHAT_API_BASE = "https://chat.googleapis.com/v1";
|
|
454
461
|
const CHAT_UPLOAD_BASE = "https://chat.googleapis.com/upload/v1";
|
|
462
|
+
async function readGoogleChatJsonResponse(response, label) {
|
|
463
|
+
try {
|
|
464
|
+
return await response.json();
|
|
465
|
+
} catch (cause) {
|
|
466
|
+
throw new Error(`${label}: malformed JSON response`, { cause });
|
|
467
|
+
}
|
|
468
|
+
}
|
|
455
469
|
const headersToObject = (headers) => headers instanceof Headers ? Object.fromEntries(headers.entries()) : Array.isArray(headers) ? Object.fromEntries(headers) : headers || {};
|
|
456
470
|
async function withGoogleChatResponse(params) {
|
|
457
471
|
const { account, url, init, auditContext, errorPrefix = "Google Chat API", handleResponse } = params;
|
|
@@ -489,7 +503,7 @@ async function fetchJson(account, url, init) {
|
|
|
489
503
|
}
|
|
490
504
|
},
|
|
491
505
|
auditContext: "googlechat.api.json",
|
|
492
|
-
handleResponse: async (response) => await response
|
|
506
|
+
handleResponse: async (response) => await readGoogleChatJsonResponse(response, "Google Chat API request failed")
|
|
493
507
|
});
|
|
494
508
|
}
|
|
495
509
|
async function fetchOk(account, url, init) {
|
|
@@ -572,7 +586,7 @@ async function uploadGoogleChatAttachment(params) {
|
|
|
572
586
|
},
|
|
573
587
|
auditContext: "googlechat.upload",
|
|
574
588
|
errorPrefix: "Google Chat upload",
|
|
575
|
-
handleResponse: async (response) => await response
|
|
589
|
+
handleResponse: async (response) => await readGoogleChatJsonResponse(response, "Google Chat upload failed")
|
|
576
590
|
})).attachmentDataRef?.attachmentUploadToken };
|
|
577
591
|
}
|
|
578
592
|
async function downloadGoogleChatMedia(params) {
|
package/dist/api.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
import {
|
|
1
|
+
import { n as googlechatSetupAdapter, t as googlechatSetupWizard } from "./setup-surface-Q6Vgbsv2.js";
|
|
2
|
+
import { t as googlechatPlugin } from "./channel-Bf5PtC25.js";
|
|
3
3
|
export { googlechatPlugin, googlechatSetupAdapter, googlechatSetupWizard };
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as resolveDefaultGoogleChatAccountId, i as listGoogleChatAccountIds, n as googlechatSetupAdapter, o as resolveGoogleChatAccount, s as resolveGoogleChatConfigAccessorAccount, t as googlechatSetupWizard } from "./setup-surface-Q6Vgbsv2.js";
|
|
2
2
|
import { T as resolveChannelMediaMaxBytes, _ as missingTargetError, a as buildChannelConfigSchema, g as loadOutboundMediaFromUrl, i as PAIRING_APPROVED_MESSAGE, o as chunkTextForOutbound, r as GoogleChatConfigSchema, t as DEFAULT_ACCOUNT_ID, x as readRemoteMediaBuffer } from "./runtime-api-DuEfWHnr.js";
|
|
3
|
-
import {
|
|
4
|
-
import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-
|
|
5
|
-
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-
|
|
6
|
-
import { n as googlechatSetupAdapter, t as googlechatSetupWizard } from "./setup-surface-Cr3BORD4.js";
|
|
3
|
+
import { a as findGoogleChatDirectMessage } from "./api-BJ9DOsBR.js";
|
|
4
|
+
import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-CG1sLToP.js";
|
|
5
|
+
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-DtQ_IO7J.js";
|
|
7
6
|
import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
|
|
8
7
|
import { formatNormalizedAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
|
|
9
8
|
import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
@@ -19,6 +18,46 @@ import { createMessageReceiptFromOutboundResults, defineChannelMessageAdapter }
|
|
|
19
18
|
import { composeAccountWarningCollectors, createAllowlistProviderOpenWarningCollector, createDangerousNameMatchingMutableAllowlistWarningCollector, resolveChannelGroupRequireMention } from "openclaw/plugin-sdk/channel-policy";
|
|
20
19
|
import { createChannelDirectoryAdapter, listResolvedDirectoryGroupEntriesFromMapKeys, listResolvedDirectoryUserEntriesFromAllowFrom } from "openclaw/plugin-sdk/directory-runtime";
|
|
21
20
|
import { sanitizeForPlainText } from "openclaw/plugin-sdk/outbound-runtime";
|
|
21
|
+
//#region extensions/googlechat/src/targets.ts
|
|
22
|
+
function normalizeGoogleChatTarget(raw) {
|
|
23
|
+
const trimmed = raw?.trim();
|
|
24
|
+
if (!trimmed) return;
|
|
25
|
+
const normalized = trimmed.replace(/^(googlechat|google-chat|gchat):/i, "").replace(/^user:(users\/)?/i, "users/").replace(/^space:(spaces\/)?/i, "spaces/");
|
|
26
|
+
if (isGoogleChatUserTarget(normalized)) {
|
|
27
|
+
const suffix = normalized.slice(6);
|
|
28
|
+
return suffix.includes("@") ? `users/${normalizeLowercaseStringOrEmpty(suffix)}` : normalized;
|
|
29
|
+
}
|
|
30
|
+
if (isGoogleChatSpaceTarget(normalized)) return normalized;
|
|
31
|
+
if (normalized.includes("@")) return `users/${normalizeLowercaseStringOrEmpty(normalized)}`;
|
|
32
|
+
return normalized;
|
|
33
|
+
}
|
|
34
|
+
function isGoogleChatUserTarget(value) {
|
|
35
|
+
return normalizeLowercaseStringOrEmpty(value).startsWith("users/");
|
|
36
|
+
}
|
|
37
|
+
function isGoogleChatSpaceTarget(value) {
|
|
38
|
+
return normalizeLowercaseStringOrEmpty(value).startsWith("spaces/");
|
|
39
|
+
}
|
|
40
|
+
function stripMessageSuffix(target) {
|
|
41
|
+
const index = target.indexOf("/messages/");
|
|
42
|
+
if (index === -1) return target;
|
|
43
|
+
return target.slice(0, index);
|
|
44
|
+
}
|
|
45
|
+
async function resolveGoogleChatOutboundSpace(params) {
|
|
46
|
+
const normalized = normalizeGoogleChatTarget(params.target);
|
|
47
|
+
if (!normalized) throw new Error("Missing Google Chat target.");
|
|
48
|
+
const base = stripMessageSuffix(normalized);
|
|
49
|
+
if (isGoogleChatSpaceTarget(base)) return base;
|
|
50
|
+
if (isGoogleChatUserTarget(base)) {
|
|
51
|
+
const dm = await findGoogleChatDirectMessage({
|
|
52
|
+
account: params.account,
|
|
53
|
+
userName: base
|
|
54
|
+
});
|
|
55
|
+
if (!dm?.name) throw new Error(`No Google Chat DM found for ${base}`);
|
|
56
|
+
return dm.name;
|
|
57
|
+
}
|
|
58
|
+
return base;
|
|
59
|
+
}
|
|
60
|
+
//#endregion
|
|
22
61
|
//#region extensions/googlechat/src/approval-auth.ts
|
|
23
62
|
function normalizeGoogleChatApproverId(value) {
|
|
24
63
|
const normalized = normalizeGoogleChatTarget(String(value));
|
|
@@ -54,7 +93,7 @@ function resolveGoogleChatGroupRequireMention(params) {
|
|
|
54
93
|
}
|
|
55
94
|
//#endregion
|
|
56
95
|
//#region extensions/googlechat/src/channel.adapters.ts
|
|
57
|
-
const loadGoogleChatChannelRuntime$2 = createLazyRuntimeNamedExport(() => import("./channel.runtime-
|
|
96
|
+
const loadGoogleChatChannelRuntime$2 = createLazyRuntimeNamedExport(() => import("./channel.runtime-DFdC1y3n.js"), "googleChatChannelRuntime");
|
|
58
97
|
function createGoogleChatSendReceipt(params) {
|
|
59
98
|
const messageId = params.messageId?.trim();
|
|
60
99
|
return createMessageReceiptFromOutboundResults({
|
|
@@ -295,7 +334,7 @@ const collectGoogleChatMutableAllowlistWarnings = createDangerousNameMatchingMut
|
|
|
295
334
|
});
|
|
296
335
|
//#endregion
|
|
297
336
|
//#region extensions/googlechat/src/gateway.ts
|
|
298
|
-
const loadGoogleChatChannelRuntime$1 = createLazyRuntimeNamedExport(() => import("./channel.runtime-
|
|
337
|
+
const loadGoogleChatChannelRuntime$1 = createLazyRuntimeNamedExport(() => import("./channel.runtime-DFdC1y3n.js"), "googleChatChannelRuntime");
|
|
299
338
|
async function startGoogleChatGatewayAccount(ctx) {
|
|
300
339
|
const account = ctx.account;
|
|
301
340
|
const statusSink = createAccountStatusSink({
|
|
@@ -335,7 +374,7 @@ async function startGoogleChatGatewayAccount(ctx) {
|
|
|
335
374
|
}
|
|
336
375
|
//#endregion
|
|
337
376
|
//#region extensions/googlechat/src/channel.ts
|
|
338
|
-
const loadGoogleChatChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-
|
|
377
|
+
const loadGoogleChatChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-DFdC1y3n.js"), "googleChatChannelRuntime");
|
|
339
378
|
const meta = {
|
|
340
379
|
id: "googlechat",
|
|
341
380
|
label: "Google Chat",
|
|
@@ -391,7 +430,7 @@ const googlechatActions = {
|
|
|
391
430
|
},
|
|
392
431
|
extractToolSend: ({ args }) => extractToolSend(args, "sendMessage"),
|
|
393
432
|
handleAction: async (ctx) => {
|
|
394
|
-
const { googlechatMessageActions } = await import("./actions-
|
|
433
|
+
const { googlechatMessageActions } = await import("./actions-CpWMO4Q6.js");
|
|
395
434
|
if (!googlechatMessageActions.handleAction) throw new Error("Google Chat actions are not available.");
|
|
396
435
|
return await googlechatMessageActions.handleAction(ctx);
|
|
397
436
|
}
|
|
@@ -542,4 +581,4 @@ const googlechatPlugin = createChatChannelPlugin({
|
|
|
542
581
|
outbound: googlechatOutboundAdapter
|
|
543
582
|
});
|
|
544
583
|
//#endregion
|
|
545
|
-
export { googlechatPlugin as t };
|
|
584
|
+
export { resolveGoogleChatOutboundSpace as n, googlechatPlugin as t };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as googlechatPlugin } from "./channel-
|
|
1
|
+
import { t as googlechatPlugin } from "./channel-Bf5PtC25.js";
|
|
2
2
|
export { googlechatPlugin };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { E as resolveDefaultGroupPolicy, M as warnMissingProviderGroupPolicyFallbackOnce, O as resolveInboundRouteEnvelopeBuilderWithRuntime, P as getGoogleChatRuntime, k as resolveWebhookPath, m as isDangerousNameMatchingEnabled, n as GROUP_POLICY_BLOCKED_LABEL, u as createChannelPairingController, w as resolveAllowlistProviderRuntimeGroupPolicy } from "./runtime-api-DuEfWHnr.js";
|
|
2
|
-
import { c as sendGoogleChatMessage, d as verifyGoogleChatRequest, i as downloadGoogleChatMedia, l as updateGoogleChatMessage, n as deleteGoogleChatMessage, s as probeGoogleChat, u as uploadGoogleChatAttachment } from "./api-
|
|
2
|
+
import { c as sendGoogleChatMessage, d as verifyGoogleChatRequest, i as downloadGoogleChatMedia, l as updateGoogleChatMessage, n as deleteGoogleChatMessage, s as probeGoogleChat, u as uploadGoogleChatAttachment } from "./api-BJ9DOsBR.js";
|
|
3
3
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
4
|
import { mergePairLoopGuardConfig } from "openclaw/plugin-sdk/pair-loop-guard-runtime";
|
|
5
5
|
import { WEBHOOK_RATE_LIMIT_DEFAULTS, createFixedWindowRateLimiter, normalizeWebhookPath, resolveRequestClientIp } from "openclaw/plugin-sdk/webhook-ingress";
|
package/dist/contract-api.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-
|
|
2
|
-
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-
|
|
1
|
+
import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-CG1sLToP.js";
|
|
2
|
+
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-DtQ_IO7J.js";
|
|
3
3
|
export { collectRuntimeConfigAssignments, legacyConfigRules, normalizeCompatibilityConfig, secretTargetRegistryEntries };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-
|
|
1
|
+
import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-CG1sLToP.js";
|
|
2
2
|
export { legacyConfigRules, normalizeCompatibilityConfig };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-
|
|
1
|
+
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-DtQ_IO7J.js";
|
|
2
2
|
export { channelSecrets, collectRuntimeConfigAssignments, secretTargetRegistryEntries };
|
package/dist/setup-plugin-api.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import { n as googlechatSetupAdapter, t as googlechatSetupWizard } from "./setup-surface-Cr3BORD4.js";
|
|
1
|
+
import { a as resolveDefaultGoogleChatAccountId, i as listGoogleChatAccountIds, n as googlechatSetupAdapter, o as resolveGoogleChatAccount, s as resolveGoogleChatConfigAccessorAccount, t as googlechatSetupWizard } from "./setup-surface-Q6Vgbsv2.js";
|
|
3
2
|
import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
|
|
4
3
|
import { formatNormalizedAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
|
|
5
4
|
import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import { safeParseJsonWithSchema, safeParseWithSchema } from "openclaw/plugin-sdk/extension-shared";
|
|
2
|
+
import { normalizeOptionalString, normalizeStringifiedOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
|
+
import { DEFAULT_ACCOUNT_ID, createAccountListHelpers, normalizeAccountId, resolveAccountEntry, resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-resolution";
|
|
4
|
+
import { mergePairLoopGuardConfig } from "openclaw/plugin-sdk/pair-loop-guard-runtime";
|
|
5
|
+
import { isSecretRef } from "openclaw/plugin-sdk/secret-input";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { createPatchedAccountSetupAdapter, createSetupInputPresenceValidator } from "openclaw/plugin-sdk/setup-runtime";
|
|
8
|
+
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, addWildcardAllowFrom, applySetupAccountConfigPatch, createPromptParsedAllowFromForAccount, createSetupTranslator, createStandardChannelSetupStatus, formatDocsLink, mergeAllowFromEntries, migrateBaseNameToDefaultAccount, splitSetupEntries } from "openclaw/plugin-sdk/setup";
|
|
9
|
+
//#region extensions/googlechat/src/accounts.ts
|
|
10
|
+
const ENV_SERVICE_ACCOUNT$1 = "GOOGLE_CHAT_SERVICE_ACCOUNT";
|
|
11
|
+
const ENV_SERVICE_ACCOUNT_FILE$1 = "GOOGLE_CHAT_SERVICE_ACCOUNT_FILE";
|
|
12
|
+
const JsonRecordSchema = z.record(z.string(), z.unknown());
|
|
13
|
+
const { listAccountIds: listGoogleChatAccountIds, resolveDefaultAccountId: resolveDefaultGoogleChatAccountId } = createAccountListHelpers("googlechat");
|
|
14
|
+
function mergeGoogleChatAccountConfig(cfg, accountId) {
|
|
15
|
+
const raw = cfg.channels?.["googlechat"] ?? {};
|
|
16
|
+
const base = resolveMergedAccountConfig({
|
|
17
|
+
channelConfig: raw,
|
|
18
|
+
accounts: raw.accounts,
|
|
19
|
+
accountId,
|
|
20
|
+
omitKeys: ["defaultAccount"],
|
|
21
|
+
nestedObjectKeys: ["botLoopProtection"]
|
|
22
|
+
});
|
|
23
|
+
const defaultAccountConfig = resolveAccountEntry(raw.accounts, DEFAULT_ACCOUNT_ID) ?? {};
|
|
24
|
+
if (accountId === DEFAULT_ACCOUNT_ID) return base;
|
|
25
|
+
const { enabled: _ignoredEnabled, dangerouslyAllowNameMatching: _ignoredDangerouslyAllowNameMatching, serviceAccount: _ignoredServiceAccount, serviceAccountRef: _ignoredServiceAccountRef, serviceAccountFile: _ignoredServiceAccountFile, ...defaultAccountShared } = defaultAccountConfig;
|
|
26
|
+
const botLoopProtection = mergePairLoopGuardConfig(defaultAccountShared.botLoopProtection, base.botLoopProtection);
|
|
27
|
+
return {
|
|
28
|
+
...defaultAccountShared,
|
|
29
|
+
...base,
|
|
30
|
+
...botLoopProtection ? { botLoopProtection } : {}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function resolveGoogleChatConfigAccessorAccount(params) {
|
|
34
|
+
const accountId = normalizeAccountId(params.accountId ?? params.cfg.channels?.googlechat?.defaultAccount);
|
|
35
|
+
return { config: mergeGoogleChatAccountConfig(params.cfg, accountId) };
|
|
36
|
+
}
|
|
37
|
+
function parseServiceAccount(value) {
|
|
38
|
+
if (isSecretRef(value)) return null;
|
|
39
|
+
if (typeof value === "string") {
|
|
40
|
+
const trimmed = value.trim();
|
|
41
|
+
if (!trimmed) return null;
|
|
42
|
+
return safeParseJsonWithSchema(JsonRecordSchema, trimmed);
|
|
43
|
+
}
|
|
44
|
+
return safeParseWithSchema(JsonRecordSchema, value);
|
|
45
|
+
}
|
|
46
|
+
function resolveCredentialsFromConfig(params) {
|
|
47
|
+
const { account, accountId } = params;
|
|
48
|
+
const inline = parseServiceAccount(account.serviceAccount);
|
|
49
|
+
if (inline) return {
|
|
50
|
+
credentials: inline,
|
|
51
|
+
source: "inline"
|
|
52
|
+
};
|
|
53
|
+
if (isSecretRef(account.serviceAccount)) throw new Error(`channels.googlechat.accounts.${accountId}.serviceAccount: unresolved SecretRef "${account.serviceAccount.source}:${account.serviceAccount.provider}:${account.serviceAccount.id}". Resolve this command against an active gateway runtime snapshot before reading it.`);
|
|
54
|
+
if (isSecretRef(account.serviceAccountRef)) throw new Error(`channels.googlechat.accounts.${accountId}.serviceAccount: unresolved SecretRef "${account.serviceAccountRef.source}:${account.serviceAccountRef.provider}:${account.serviceAccountRef.id}". Resolve this command against an active gateway runtime snapshot before reading it.`);
|
|
55
|
+
const file = normalizeOptionalString(account.serviceAccountFile);
|
|
56
|
+
if (file) return {
|
|
57
|
+
credentialsFile: file,
|
|
58
|
+
source: "file"
|
|
59
|
+
};
|
|
60
|
+
if (accountId === DEFAULT_ACCOUNT_ID) {
|
|
61
|
+
const envJson = process.env[ENV_SERVICE_ACCOUNT$1];
|
|
62
|
+
const envInline = parseServiceAccount(envJson);
|
|
63
|
+
if (envInline) return {
|
|
64
|
+
credentials: envInline,
|
|
65
|
+
source: "env"
|
|
66
|
+
};
|
|
67
|
+
const envFile = normalizeOptionalString(process.env[ENV_SERVICE_ACCOUNT_FILE$1]);
|
|
68
|
+
if (envFile) return {
|
|
69
|
+
credentialsFile: envFile,
|
|
70
|
+
source: "env"
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return { source: "none" };
|
|
74
|
+
}
|
|
75
|
+
function resolveGoogleChatAccount(params) {
|
|
76
|
+
const accountId = normalizeAccountId(params.accountId ?? params.cfg.channels?.["googlechat"]?.defaultAccount);
|
|
77
|
+
const baseEnabled = params.cfg.channels?.["googlechat"]?.enabled !== false;
|
|
78
|
+
const merged = mergeGoogleChatAccountConfig(params.cfg, accountId);
|
|
79
|
+
const accountEnabled = merged.enabled !== false;
|
|
80
|
+
const enabled = baseEnabled && accountEnabled;
|
|
81
|
+
const credentials = resolveCredentialsFromConfig({
|
|
82
|
+
accountId,
|
|
83
|
+
account: merged
|
|
84
|
+
});
|
|
85
|
+
return {
|
|
86
|
+
accountId,
|
|
87
|
+
name: normalizeOptionalString(merged.name),
|
|
88
|
+
enabled,
|
|
89
|
+
config: merged,
|
|
90
|
+
credentialSource: credentials.source,
|
|
91
|
+
credentials: credentials.credentials,
|
|
92
|
+
credentialsFile: credentials.credentialsFile
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function listEnabledGoogleChatAccounts(cfg) {
|
|
96
|
+
return listGoogleChatAccountIds(cfg).map((accountId) => resolveGoogleChatAccount({
|
|
97
|
+
cfg,
|
|
98
|
+
accountId
|
|
99
|
+
})).filter((account) => account.enabled);
|
|
100
|
+
}
|
|
101
|
+
const googlechatSetupAdapter = createPatchedAccountSetupAdapter({
|
|
102
|
+
channelKey: "googlechat",
|
|
103
|
+
validateInput: createSetupInputPresenceValidator({
|
|
104
|
+
defaultAccountOnlyEnvError: "GOOGLE_CHAT_SERVICE_ACCOUNT env vars can only be used for the default account.",
|
|
105
|
+
whenNotUseEnv: [{
|
|
106
|
+
someOf: ["token", "tokenFile"],
|
|
107
|
+
message: "Google Chat requires --token (service account JSON) or --token-file."
|
|
108
|
+
}]
|
|
109
|
+
}),
|
|
110
|
+
buildPatch: (input) => {
|
|
111
|
+
const patch = input.useEnv ? {} : input.tokenFile ? { serviceAccountFile: input.tokenFile } : input.token ? { serviceAccount: input.token } : {};
|
|
112
|
+
const audienceType = input.audienceType?.trim();
|
|
113
|
+
const audience = input.audience?.trim();
|
|
114
|
+
const webhookPath = input.webhookPath?.trim();
|
|
115
|
+
const webhookUrl = input.webhookUrl?.trim();
|
|
116
|
+
return {
|
|
117
|
+
...patch,
|
|
118
|
+
...audienceType ? { audienceType } : {},
|
|
119
|
+
...audience ? { audience } : {},
|
|
120
|
+
...webhookPath ? { webhookPath } : {},
|
|
121
|
+
...webhookUrl ? { webhookUrl } : {}
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region extensions/googlechat/src/setup-surface.ts
|
|
127
|
+
const t = createSetupTranslator();
|
|
128
|
+
const channel = "googlechat";
|
|
129
|
+
const ENV_SERVICE_ACCOUNT = "GOOGLE_CHAT_SERVICE_ACCOUNT";
|
|
130
|
+
const ENV_SERVICE_ACCOUNT_FILE = "GOOGLE_CHAT_SERVICE_ACCOUNT_FILE";
|
|
131
|
+
const USE_ENV_FLAG = "__googlechatUseEnv";
|
|
132
|
+
const AUTH_METHOD_FLAG = "__googlechatAuthMethod";
|
|
133
|
+
const googlechatDmPolicy = {
|
|
134
|
+
label: "Google Chat",
|
|
135
|
+
channel,
|
|
136
|
+
policyKey: "channels.googlechat.dm.policy",
|
|
137
|
+
allowFromKey: "channels.googlechat.dm.allowFrom",
|
|
138
|
+
resolveConfigKeys: (cfg, accountId) => (accountId ?? resolveDefaultGoogleChatAccountId(cfg)) !== DEFAULT_ACCOUNT_ID$1 ? {
|
|
139
|
+
policyKey: `channels.googlechat.accounts.${accountId ?? resolveDefaultGoogleChatAccountId(cfg)}.dm.policy`,
|
|
140
|
+
allowFromKey: `channels.googlechat.accounts.${accountId ?? resolveDefaultGoogleChatAccountId(cfg)}.dm.allowFrom`
|
|
141
|
+
} : {
|
|
142
|
+
policyKey: "channels.googlechat.dm.policy",
|
|
143
|
+
allowFromKey: "channels.googlechat.dm.allowFrom"
|
|
144
|
+
},
|
|
145
|
+
getCurrent: (cfg, accountId) => resolveGoogleChatAccount({
|
|
146
|
+
cfg,
|
|
147
|
+
accountId: accountId ?? resolveDefaultGoogleChatAccountId(cfg)
|
|
148
|
+
}).config.dm?.policy ?? "pairing",
|
|
149
|
+
setPolicy: (cfg, policy, accountId) => {
|
|
150
|
+
const resolvedAccountId = accountId ?? resolveDefaultGoogleChatAccountId(cfg);
|
|
151
|
+
const currentDm = resolveGoogleChatAccount({
|
|
152
|
+
cfg,
|
|
153
|
+
accountId: resolvedAccountId
|
|
154
|
+
}).config.dm;
|
|
155
|
+
return applySetupAccountConfigPatch({
|
|
156
|
+
cfg,
|
|
157
|
+
channelKey: channel,
|
|
158
|
+
accountId: resolvedAccountId,
|
|
159
|
+
patch: { dm: {
|
|
160
|
+
...currentDm,
|
|
161
|
+
policy,
|
|
162
|
+
...policy === "open" ? { allowFrom: addWildcardAllowFrom(currentDm?.allowFrom) } : {}
|
|
163
|
+
} }
|
|
164
|
+
});
|
|
165
|
+
},
|
|
166
|
+
promptAllowFrom: createPromptParsedAllowFromForAccount({
|
|
167
|
+
defaultAccountId: resolveDefaultGoogleChatAccountId,
|
|
168
|
+
message: t("wizard.googlechat.allowFromPrompt"),
|
|
169
|
+
placeholder: "users/123456789, name@example.com",
|
|
170
|
+
parseEntries: (raw) => ({ entries: mergeAllowFromEntries(void 0, splitSetupEntries(raw)) }),
|
|
171
|
+
getExistingAllowFrom: ({ cfg, accountId }) => resolveGoogleChatAccount({
|
|
172
|
+
cfg,
|
|
173
|
+
accountId
|
|
174
|
+
}).config.dm?.allowFrom ?? [],
|
|
175
|
+
applyAllowFrom: ({ cfg, accountId, allowFrom }) => applySetupAccountConfigPatch({
|
|
176
|
+
cfg,
|
|
177
|
+
channelKey: channel,
|
|
178
|
+
accountId,
|
|
179
|
+
patch: { dm: {
|
|
180
|
+
...resolveGoogleChatAccount({
|
|
181
|
+
cfg,
|
|
182
|
+
accountId
|
|
183
|
+
}).config.dm,
|
|
184
|
+
allowFrom
|
|
185
|
+
} }
|
|
186
|
+
})
|
|
187
|
+
})
|
|
188
|
+
};
|
|
189
|
+
function createServiceAccountTextInput(params) {
|
|
190
|
+
return {
|
|
191
|
+
inputKey: params.inputKey,
|
|
192
|
+
message: params.message,
|
|
193
|
+
placeholder: params.placeholder,
|
|
194
|
+
shouldPrompt: ({ credentialValues }) => credentialValues[USE_ENV_FLAG] !== "1" && credentialValues[AUTH_METHOD_FLAG] === params.authMethod,
|
|
195
|
+
validate: ({ value }) => normalizeStringifiedOptionalString(value) ? void 0 : "Required",
|
|
196
|
+
normalizeValue: ({ value }) => normalizeStringifiedOptionalString(value) ?? "",
|
|
197
|
+
applySet: async ({ cfg, accountId, value }) => applySetupAccountConfigPatch({
|
|
198
|
+
cfg,
|
|
199
|
+
channelKey: channel,
|
|
200
|
+
accountId,
|
|
201
|
+
patch: { [params.patchKey]: value }
|
|
202
|
+
})
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
const googlechatSetupWizard = {
|
|
206
|
+
channel,
|
|
207
|
+
status: createStandardChannelSetupStatus({
|
|
208
|
+
channelLabel: "Google Chat",
|
|
209
|
+
configuredLabel: t("wizard.channels.statusConfigured"),
|
|
210
|
+
unconfiguredLabel: t("wizard.channels.statusNeedsServiceAccount"),
|
|
211
|
+
configuredHint: t("wizard.channels.statusConfigured"),
|
|
212
|
+
unconfiguredHint: t("wizard.channels.statusNeedsAuth"),
|
|
213
|
+
includeStatusLine: true,
|
|
214
|
+
resolveConfigured: ({ cfg, accountId }) => resolveGoogleChatAccount({
|
|
215
|
+
cfg,
|
|
216
|
+
accountId
|
|
217
|
+
}).credentialSource !== "none"
|
|
218
|
+
}),
|
|
219
|
+
introNote: {
|
|
220
|
+
title: t("wizard.googlechat.setupTitle"),
|
|
221
|
+
lines: [
|
|
222
|
+
t("wizard.googlechat.setupServiceAccount"),
|
|
223
|
+
t("wizard.googlechat.setupScopes"),
|
|
224
|
+
t("wizard.googlechat.setupAudience"),
|
|
225
|
+
t("wizard.channels.docs", { link: formatDocsLink("/channels/googlechat", "googlechat") })
|
|
226
|
+
]
|
|
227
|
+
},
|
|
228
|
+
prepare: async ({ cfg, accountId, credentialValues, prompter }) => {
|
|
229
|
+
if (accountId === DEFAULT_ACCOUNT_ID$1 && (Boolean(process.env[ENV_SERVICE_ACCOUNT]) || Boolean(process.env[ENV_SERVICE_ACCOUNT_FILE]))) {
|
|
230
|
+
if (await prompter.confirm({
|
|
231
|
+
message: t("wizard.googlechat.useEnvPrompt"),
|
|
232
|
+
initialValue: true
|
|
233
|
+
})) return {
|
|
234
|
+
cfg: applySetupAccountConfigPatch({
|
|
235
|
+
cfg,
|
|
236
|
+
channelKey: channel,
|
|
237
|
+
accountId,
|
|
238
|
+
patch: {}
|
|
239
|
+
}),
|
|
240
|
+
credentialValues: {
|
|
241
|
+
...credentialValues,
|
|
242
|
+
[USE_ENV_FLAG]: "1"
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
const method = await prompter.select({
|
|
247
|
+
message: t("wizard.googlechat.authMethod"),
|
|
248
|
+
options: [{
|
|
249
|
+
value: "file",
|
|
250
|
+
label: t("wizard.googlechat.serviceAccountFile")
|
|
251
|
+
}, {
|
|
252
|
+
value: "inline",
|
|
253
|
+
label: t("wizard.googlechat.serviceAccountInline")
|
|
254
|
+
}],
|
|
255
|
+
initialValue: "file"
|
|
256
|
+
});
|
|
257
|
+
return { credentialValues: {
|
|
258
|
+
...credentialValues,
|
|
259
|
+
[USE_ENV_FLAG]: "0",
|
|
260
|
+
[AUTH_METHOD_FLAG]: method
|
|
261
|
+
} };
|
|
262
|
+
},
|
|
263
|
+
credentials: [],
|
|
264
|
+
textInputs: [createServiceAccountTextInput({
|
|
265
|
+
inputKey: "tokenFile",
|
|
266
|
+
message: t("wizard.googlechat.serviceAccountPath"),
|
|
267
|
+
placeholder: "/path/to/service-account.json",
|
|
268
|
+
authMethod: "file",
|
|
269
|
+
patchKey: "serviceAccountFile"
|
|
270
|
+
}), createServiceAccountTextInput({
|
|
271
|
+
inputKey: "token",
|
|
272
|
+
message: t("wizard.googlechat.serviceAccountJson"),
|
|
273
|
+
placeholder: "{\"type\":\"service_account\", ... }",
|
|
274
|
+
authMethod: "inline",
|
|
275
|
+
patchKey: "serviceAccount"
|
|
276
|
+
})],
|
|
277
|
+
finalize: async ({ cfg, accountId, prompter }) => {
|
|
278
|
+
const account = resolveGoogleChatAccount({
|
|
279
|
+
cfg,
|
|
280
|
+
accountId
|
|
281
|
+
});
|
|
282
|
+
const audienceType = await prompter.select({
|
|
283
|
+
message: t("wizard.googlechat.webhookAudienceType"),
|
|
284
|
+
options: [{
|
|
285
|
+
value: "app-url",
|
|
286
|
+
label: t("wizard.googlechat.appUrlRecommended")
|
|
287
|
+
}, {
|
|
288
|
+
value: "project-number",
|
|
289
|
+
label: t("wizard.googlechat.projectNumber")
|
|
290
|
+
}],
|
|
291
|
+
initialValue: account.config.audienceType === "project-number" ? "project-number" : "app-url"
|
|
292
|
+
});
|
|
293
|
+
return { cfg: migrateBaseNameToDefaultAccount({
|
|
294
|
+
cfg: applySetupAccountConfigPatch({
|
|
295
|
+
cfg,
|
|
296
|
+
channelKey: channel,
|
|
297
|
+
accountId,
|
|
298
|
+
patch: {
|
|
299
|
+
audienceType,
|
|
300
|
+
audience: normalizeOptionalString(await prompter.text({
|
|
301
|
+
message: audienceType === "project-number" ? t("wizard.googlechat.projectNumber") : t("wizard.googlechat.appUrl"),
|
|
302
|
+
placeholder: audienceType === "project-number" ? "1234567890" : "https://your.host/googlechat",
|
|
303
|
+
initialValue: account.config.audience || void 0,
|
|
304
|
+
validate: (value) => normalizeStringifiedOptionalString(value) ? void 0 : t("common.required")
|
|
305
|
+
})) ?? ""
|
|
306
|
+
}
|
|
307
|
+
}),
|
|
308
|
+
channelKey: channel
|
|
309
|
+
}) };
|
|
310
|
+
},
|
|
311
|
+
dmPolicy: googlechatDmPolicy
|
|
312
|
+
};
|
|
313
|
+
//#endregion
|
|
314
|
+
export { resolveDefaultGoogleChatAccountId as a, listGoogleChatAccountIds as i, googlechatSetupAdapter as n, resolveGoogleChatAccount as o, listEnabledGoogleChatAccounts as r, resolveGoogleChatConfigAccessorAccount as s, googlechatSetupWizard as t };
|
package/dist/test-api.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/googlechat",
|
|
3
|
-
"version": "2026.5.
|
|
3
|
+
"version": "2026.5.16-beta.1",
|
|
4
4
|
"description": "OpenClaw Google Chat channel plugin",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"openclaw": "workspace:*"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
|
-
"openclaw": ">=2026.5.
|
|
20
|
+
"openclaw": ">=2026.5.16-beta.1"
|
|
21
21
|
},
|
|
22
22
|
"peerDependenciesMeta": {
|
|
23
23
|
"openclaw": {
|
|
@@ -75,10 +75,10 @@
|
|
|
75
75
|
"minHostVersion": ">=2026.4.10"
|
|
76
76
|
},
|
|
77
77
|
"compat": {
|
|
78
|
-
"pluginApi": ">=2026.5.
|
|
78
|
+
"pluginApi": ">=2026.5.16-beta.1"
|
|
79
79
|
},
|
|
80
80
|
"build": {
|
|
81
|
-
"openclawVersion": "2026.5.
|
|
81
|
+
"openclawVersion": "2026.5.16-beta.1"
|
|
82
82
|
},
|
|
83
83
|
"release": {
|
|
84
84
|
"publishToClawHub": true,
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { safeParseJsonWithSchema, safeParseWithSchema } from "openclaw/plugin-sdk/extension-shared";
|
|
2
|
-
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
|
-
import { DEFAULT_ACCOUNT_ID, createAccountListHelpers, normalizeAccountId, resolveAccountEntry, resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-resolution";
|
|
4
|
-
import { mergePairLoopGuardConfig } from "openclaw/plugin-sdk/pair-loop-guard-runtime";
|
|
5
|
-
import { isSecretRef } from "openclaw/plugin-sdk/secret-input";
|
|
6
|
-
import { z } from "zod";
|
|
7
|
-
//#region extensions/googlechat/src/accounts.ts
|
|
8
|
-
const ENV_SERVICE_ACCOUNT = "GOOGLE_CHAT_SERVICE_ACCOUNT";
|
|
9
|
-
const ENV_SERVICE_ACCOUNT_FILE = "GOOGLE_CHAT_SERVICE_ACCOUNT_FILE";
|
|
10
|
-
const JsonRecordSchema = z.record(z.string(), z.unknown());
|
|
11
|
-
const { listAccountIds: listGoogleChatAccountIds, resolveDefaultAccountId: resolveDefaultGoogleChatAccountId } = createAccountListHelpers("googlechat");
|
|
12
|
-
function mergeGoogleChatAccountConfig(cfg, accountId) {
|
|
13
|
-
const raw = cfg.channels?.["googlechat"] ?? {};
|
|
14
|
-
const base = resolveMergedAccountConfig({
|
|
15
|
-
channelConfig: raw,
|
|
16
|
-
accounts: raw.accounts,
|
|
17
|
-
accountId,
|
|
18
|
-
omitKeys: ["defaultAccount"],
|
|
19
|
-
nestedObjectKeys: ["botLoopProtection"]
|
|
20
|
-
});
|
|
21
|
-
const defaultAccountConfig = resolveAccountEntry(raw.accounts, DEFAULT_ACCOUNT_ID) ?? {};
|
|
22
|
-
if (accountId === DEFAULT_ACCOUNT_ID) return base;
|
|
23
|
-
const { enabled: _ignoredEnabled, dangerouslyAllowNameMatching: _ignoredDangerouslyAllowNameMatching, serviceAccount: _ignoredServiceAccount, serviceAccountRef: _ignoredServiceAccountRef, serviceAccountFile: _ignoredServiceAccountFile, ...defaultAccountShared } = defaultAccountConfig;
|
|
24
|
-
const botLoopProtection = mergePairLoopGuardConfig(defaultAccountShared.botLoopProtection, base.botLoopProtection);
|
|
25
|
-
return {
|
|
26
|
-
...defaultAccountShared,
|
|
27
|
-
...base,
|
|
28
|
-
...botLoopProtection ? { botLoopProtection } : {}
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
function resolveGoogleChatConfigAccessorAccount(params) {
|
|
32
|
-
const accountId = normalizeAccountId(params.accountId ?? params.cfg.channels?.googlechat?.defaultAccount);
|
|
33
|
-
return { config: mergeGoogleChatAccountConfig(params.cfg, accountId) };
|
|
34
|
-
}
|
|
35
|
-
function parseServiceAccount(value) {
|
|
36
|
-
if (isSecretRef(value)) return null;
|
|
37
|
-
if (typeof value === "string") {
|
|
38
|
-
const trimmed = value.trim();
|
|
39
|
-
if (!trimmed) return null;
|
|
40
|
-
return safeParseJsonWithSchema(JsonRecordSchema, trimmed);
|
|
41
|
-
}
|
|
42
|
-
return safeParseWithSchema(JsonRecordSchema, value);
|
|
43
|
-
}
|
|
44
|
-
function resolveCredentialsFromConfig(params) {
|
|
45
|
-
const { account, accountId } = params;
|
|
46
|
-
const inline = parseServiceAccount(account.serviceAccount);
|
|
47
|
-
if (inline) return {
|
|
48
|
-
credentials: inline,
|
|
49
|
-
source: "inline"
|
|
50
|
-
};
|
|
51
|
-
if (isSecretRef(account.serviceAccount)) throw new Error(`channels.googlechat.accounts.${accountId}.serviceAccount: unresolved SecretRef "${account.serviceAccount.source}:${account.serviceAccount.provider}:${account.serviceAccount.id}". Resolve this command against an active gateway runtime snapshot before reading it.`);
|
|
52
|
-
if (isSecretRef(account.serviceAccountRef)) throw new Error(`channels.googlechat.accounts.${accountId}.serviceAccount: unresolved SecretRef "${account.serviceAccountRef.source}:${account.serviceAccountRef.provider}:${account.serviceAccountRef.id}". Resolve this command against an active gateway runtime snapshot before reading it.`);
|
|
53
|
-
const file = normalizeOptionalString(account.serviceAccountFile);
|
|
54
|
-
if (file) return {
|
|
55
|
-
credentialsFile: file,
|
|
56
|
-
source: "file"
|
|
57
|
-
};
|
|
58
|
-
if (accountId === DEFAULT_ACCOUNT_ID) {
|
|
59
|
-
const envJson = process.env[ENV_SERVICE_ACCOUNT];
|
|
60
|
-
const envInline = parseServiceAccount(envJson);
|
|
61
|
-
if (envInline) return {
|
|
62
|
-
credentials: envInline,
|
|
63
|
-
source: "env"
|
|
64
|
-
};
|
|
65
|
-
const envFile = normalizeOptionalString(process.env[ENV_SERVICE_ACCOUNT_FILE]);
|
|
66
|
-
if (envFile) return {
|
|
67
|
-
credentialsFile: envFile,
|
|
68
|
-
source: "env"
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
return { source: "none" };
|
|
72
|
-
}
|
|
73
|
-
function resolveGoogleChatAccount(params) {
|
|
74
|
-
const accountId = normalizeAccountId(params.accountId ?? params.cfg.channels?.["googlechat"]?.defaultAccount);
|
|
75
|
-
const baseEnabled = params.cfg.channels?.["googlechat"]?.enabled !== false;
|
|
76
|
-
const merged = mergeGoogleChatAccountConfig(params.cfg, accountId);
|
|
77
|
-
const accountEnabled = merged.enabled !== false;
|
|
78
|
-
const enabled = baseEnabled && accountEnabled;
|
|
79
|
-
const credentials = resolveCredentialsFromConfig({
|
|
80
|
-
accountId,
|
|
81
|
-
account: merged
|
|
82
|
-
});
|
|
83
|
-
return {
|
|
84
|
-
accountId,
|
|
85
|
-
name: normalizeOptionalString(merged.name),
|
|
86
|
-
enabled,
|
|
87
|
-
config: merged,
|
|
88
|
-
credentialSource: credentials.source,
|
|
89
|
-
credentials: credentials.credentials,
|
|
90
|
-
credentialsFile: credentials.credentialsFile
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
function listEnabledGoogleChatAccounts(cfg) {
|
|
94
|
-
return listGoogleChatAccountIds(cfg).map((accountId) => resolveGoogleChatAccount({
|
|
95
|
-
cfg,
|
|
96
|
-
accountId
|
|
97
|
-
})).filter((account) => account.enabled);
|
|
98
|
-
}
|
|
99
|
-
//#endregion
|
|
100
|
-
export { resolveGoogleChatConfigAccessorAccount as a, resolveGoogleChatAccount as i, listGoogleChatAccountIds as n, resolveDefaultGoogleChatAccountId as r, listEnabledGoogleChatAccounts as t };
|
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
import { i as resolveGoogleChatAccount, r as resolveDefaultGoogleChatAccountId } from "./accounts-BlfWEj_G.js";
|
|
2
|
-
import { normalizeOptionalString, normalizeStringifiedOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
|
-
import { createPatchedAccountSetupAdapter, createSetupInputPresenceValidator } from "openclaw/plugin-sdk/setup-runtime";
|
|
4
|
-
import { DEFAULT_ACCOUNT_ID, addWildcardAllowFrom, applySetupAccountConfigPatch, createPromptParsedAllowFromForAccount, createStandardChannelSetupStatus, formatDocsLink, mergeAllowFromEntries, migrateBaseNameToDefaultAccount, splitSetupEntries } from "openclaw/plugin-sdk/setup";
|
|
5
|
-
const googlechatSetupAdapter = createPatchedAccountSetupAdapter({
|
|
6
|
-
channelKey: "googlechat",
|
|
7
|
-
validateInput: createSetupInputPresenceValidator({
|
|
8
|
-
defaultAccountOnlyEnvError: "GOOGLE_CHAT_SERVICE_ACCOUNT env vars can only be used for the default account.",
|
|
9
|
-
whenNotUseEnv: [{
|
|
10
|
-
someOf: ["token", "tokenFile"],
|
|
11
|
-
message: "Google Chat requires --token (service account JSON) or --token-file."
|
|
12
|
-
}]
|
|
13
|
-
}),
|
|
14
|
-
buildPatch: (input) => {
|
|
15
|
-
const patch = input.useEnv ? {} : input.tokenFile ? { serviceAccountFile: input.tokenFile } : input.token ? { serviceAccount: input.token } : {};
|
|
16
|
-
const audienceType = input.audienceType?.trim();
|
|
17
|
-
const audience = input.audience?.trim();
|
|
18
|
-
const webhookPath = input.webhookPath?.trim();
|
|
19
|
-
const webhookUrl = input.webhookUrl?.trim();
|
|
20
|
-
return {
|
|
21
|
-
...patch,
|
|
22
|
-
...audienceType ? { audienceType } : {},
|
|
23
|
-
...audience ? { audience } : {},
|
|
24
|
-
...webhookPath ? { webhookPath } : {},
|
|
25
|
-
...webhookUrl ? { webhookUrl } : {}
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
//#endregion
|
|
30
|
-
//#region extensions/googlechat/src/setup-surface.ts
|
|
31
|
-
const channel = "googlechat";
|
|
32
|
-
const ENV_SERVICE_ACCOUNT = "GOOGLE_CHAT_SERVICE_ACCOUNT";
|
|
33
|
-
const ENV_SERVICE_ACCOUNT_FILE = "GOOGLE_CHAT_SERVICE_ACCOUNT_FILE";
|
|
34
|
-
const USE_ENV_FLAG = "__googlechatUseEnv";
|
|
35
|
-
const AUTH_METHOD_FLAG = "__googlechatAuthMethod";
|
|
36
|
-
const googlechatDmPolicy = {
|
|
37
|
-
label: "Google Chat",
|
|
38
|
-
channel,
|
|
39
|
-
policyKey: "channels.googlechat.dm.policy",
|
|
40
|
-
allowFromKey: "channels.googlechat.dm.allowFrom",
|
|
41
|
-
resolveConfigKeys: (cfg, accountId) => (accountId ?? resolveDefaultGoogleChatAccountId(cfg)) !== DEFAULT_ACCOUNT_ID ? {
|
|
42
|
-
policyKey: `channels.googlechat.accounts.${accountId ?? resolveDefaultGoogleChatAccountId(cfg)}.dm.policy`,
|
|
43
|
-
allowFromKey: `channels.googlechat.accounts.${accountId ?? resolveDefaultGoogleChatAccountId(cfg)}.dm.allowFrom`
|
|
44
|
-
} : {
|
|
45
|
-
policyKey: "channels.googlechat.dm.policy",
|
|
46
|
-
allowFromKey: "channels.googlechat.dm.allowFrom"
|
|
47
|
-
},
|
|
48
|
-
getCurrent: (cfg, accountId) => resolveGoogleChatAccount({
|
|
49
|
-
cfg,
|
|
50
|
-
accountId: accountId ?? resolveDefaultGoogleChatAccountId(cfg)
|
|
51
|
-
}).config.dm?.policy ?? "pairing",
|
|
52
|
-
setPolicy: (cfg, policy, accountId) => {
|
|
53
|
-
const resolvedAccountId = accountId ?? resolveDefaultGoogleChatAccountId(cfg);
|
|
54
|
-
const currentDm = resolveGoogleChatAccount({
|
|
55
|
-
cfg,
|
|
56
|
-
accountId: resolvedAccountId
|
|
57
|
-
}).config.dm;
|
|
58
|
-
return applySetupAccountConfigPatch({
|
|
59
|
-
cfg,
|
|
60
|
-
channelKey: channel,
|
|
61
|
-
accountId: resolvedAccountId,
|
|
62
|
-
patch: { dm: {
|
|
63
|
-
...currentDm,
|
|
64
|
-
policy,
|
|
65
|
-
...policy === "open" ? { allowFrom: addWildcardAllowFrom(currentDm?.allowFrom) } : {}
|
|
66
|
-
} }
|
|
67
|
-
});
|
|
68
|
-
},
|
|
69
|
-
promptAllowFrom: createPromptParsedAllowFromForAccount({
|
|
70
|
-
defaultAccountId: resolveDefaultGoogleChatAccountId,
|
|
71
|
-
message: "Google Chat allowFrom (users/<id> or raw email; avoid users/<email>)",
|
|
72
|
-
placeholder: "users/123456789, name@example.com",
|
|
73
|
-
parseEntries: (raw) => ({ entries: mergeAllowFromEntries(void 0, splitSetupEntries(raw)) }),
|
|
74
|
-
getExistingAllowFrom: ({ cfg, accountId }) => resolveGoogleChatAccount({
|
|
75
|
-
cfg,
|
|
76
|
-
accountId
|
|
77
|
-
}).config.dm?.allowFrom ?? [],
|
|
78
|
-
applyAllowFrom: ({ cfg, accountId, allowFrom }) => applySetupAccountConfigPatch({
|
|
79
|
-
cfg,
|
|
80
|
-
channelKey: channel,
|
|
81
|
-
accountId,
|
|
82
|
-
patch: { dm: {
|
|
83
|
-
...resolveGoogleChatAccount({
|
|
84
|
-
cfg,
|
|
85
|
-
accountId
|
|
86
|
-
}).config.dm,
|
|
87
|
-
allowFrom
|
|
88
|
-
} }
|
|
89
|
-
})
|
|
90
|
-
})
|
|
91
|
-
};
|
|
92
|
-
function createServiceAccountTextInput(params) {
|
|
93
|
-
return {
|
|
94
|
-
inputKey: params.inputKey,
|
|
95
|
-
message: params.message,
|
|
96
|
-
placeholder: params.placeholder,
|
|
97
|
-
shouldPrompt: ({ credentialValues }) => credentialValues[USE_ENV_FLAG] !== "1" && credentialValues[AUTH_METHOD_FLAG] === params.authMethod,
|
|
98
|
-
validate: ({ value }) => normalizeStringifiedOptionalString(value) ? void 0 : "Required",
|
|
99
|
-
normalizeValue: ({ value }) => normalizeStringifiedOptionalString(value) ?? "",
|
|
100
|
-
applySet: async ({ cfg, accountId, value }) => applySetupAccountConfigPatch({
|
|
101
|
-
cfg,
|
|
102
|
-
channelKey: channel,
|
|
103
|
-
accountId,
|
|
104
|
-
patch: { [params.patchKey]: value }
|
|
105
|
-
})
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
const googlechatSetupWizard = {
|
|
109
|
-
channel,
|
|
110
|
-
status: createStandardChannelSetupStatus({
|
|
111
|
-
channelLabel: "Google Chat",
|
|
112
|
-
configuredLabel: "configured",
|
|
113
|
-
unconfiguredLabel: "needs service account",
|
|
114
|
-
configuredHint: "configured",
|
|
115
|
-
unconfiguredHint: "needs auth",
|
|
116
|
-
includeStatusLine: true,
|
|
117
|
-
resolveConfigured: ({ cfg, accountId }) => resolveGoogleChatAccount({
|
|
118
|
-
cfg,
|
|
119
|
-
accountId
|
|
120
|
-
}).credentialSource !== "none"
|
|
121
|
-
}),
|
|
122
|
-
introNote: {
|
|
123
|
-
title: "Google Chat setup",
|
|
124
|
-
lines: [
|
|
125
|
-
"Google Chat apps use service-account auth and an HTTPS webhook.",
|
|
126
|
-
"Set the Chat API scopes in your service account and configure the Chat app URL.",
|
|
127
|
-
"Webhook verification requires audience type + audience value.",
|
|
128
|
-
`Docs: ${formatDocsLink("/channels/googlechat", "googlechat")}`
|
|
129
|
-
]
|
|
130
|
-
},
|
|
131
|
-
prepare: async ({ cfg, accountId, credentialValues, prompter }) => {
|
|
132
|
-
if (accountId === DEFAULT_ACCOUNT_ID && (Boolean(process.env[ENV_SERVICE_ACCOUNT]) || Boolean(process.env[ENV_SERVICE_ACCOUNT_FILE]))) {
|
|
133
|
-
if (await prompter.confirm({
|
|
134
|
-
message: "Use GOOGLE_CHAT_SERVICE_ACCOUNT env vars?",
|
|
135
|
-
initialValue: true
|
|
136
|
-
})) return {
|
|
137
|
-
cfg: applySetupAccountConfigPatch({
|
|
138
|
-
cfg,
|
|
139
|
-
channelKey: channel,
|
|
140
|
-
accountId,
|
|
141
|
-
patch: {}
|
|
142
|
-
}),
|
|
143
|
-
credentialValues: {
|
|
144
|
-
...credentialValues,
|
|
145
|
-
[USE_ENV_FLAG]: "1"
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
const method = await prompter.select({
|
|
150
|
-
message: "Google Chat auth method",
|
|
151
|
-
options: [{
|
|
152
|
-
value: "file",
|
|
153
|
-
label: "Service account JSON file"
|
|
154
|
-
}, {
|
|
155
|
-
value: "inline",
|
|
156
|
-
label: "Paste service account JSON"
|
|
157
|
-
}],
|
|
158
|
-
initialValue: "file"
|
|
159
|
-
});
|
|
160
|
-
return { credentialValues: {
|
|
161
|
-
...credentialValues,
|
|
162
|
-
[USE_ENV_FLAG]: "0",
|
|
163
|
-
[AUTH_METHOD_FLAG]: method
|
|
164
|
-
} };
|
|
165
|
-
},
|
|
166
|
-
credentials: [],
|
|
167
|
-
textInputs: [createServiceAccountTextInput({
|
|
168
|
-
inputKey: "tokenFile",
|
|
169
|
-
message: "Service account JSON path",
|
|
170
|
-
placeholder: "/path/to/service-account.json",
|
|
171
|
-
authMethod: "file",
|
|
172
|
-
patchKey: "serviceAccountFile"
|
|
173
|
-
}), createServiceAccountTextInput({
|
|
174
|
-
inputKey: "token",
|
|
175
|
-
message: "Service account JSON (single line)",
|
|
176
|
-
placeholder: "{\"type\":\"service_account\", ... }",
|
|
177
|
-
authMethod: "inline",
|
|
178
|
-
patchKey: "serviceAccount"
|
|
179
|
-
})],
|
|
180
|
-
finalize: async ({ cfg, accountId, prompter }) => {
|
|
181
|
-
const account = resolveGoogleChatAccount({
|
|
182
|
-
cfg,
|
|
183
|
-
accountId
|
|
184
|
-
});
|
|
185
|
-
const audienceType = await prompter.select({
|
|
186
|
-
message: "Webhook audience type",
|
|
187
|
-
options: [{
|
|
188
|
-
value: "app-url",
|
|
189
|
-
label: "App URL (recommended)"
|
|
190
|
-
}, {
|
|
191
|
-
value: "project-number",
|
|
192
|
-
label: "Project number"
|
|
193
|
-
}],
|
|
194
|
-
initialValue: account.config.audienceType === "project-number" ? "project-number" : "app-url"
|
|
195
|
-
});
|
|
196
|
-
return { cfg: migrateBaseNameToDefaultAccount({
|
|
197
|
-
cfg: applySetupAccountConfigPatch({
|
|
198
|
-
cfg,
|
|
199
|
-
channelKey: channel,
|
|
200
|
-
accountId,
|
|
201
|
-
patch: {
|
|
202
|
-
audienceType,
|
|
203
|
-
audience: normalizeOptionalString(await prompter.text({
|
|
204
|
-
message: audienceType === "project-number" ? "Project number" : "App URL",
|
|
205
|
-
placeholder: audienceType === "project-number" ? "1234567890" : "https://your.host/googlechat",
|
|
206
|
-
initialValue: account.config.audience || void 0,
|
|
207
|
-
validate: (value) => normalizeStringifiedOptionalString(value) ? void 0 : "Required"
|
|
208
|
-
})) ?? ""
|
|
209
|
-
}
|
|
210
|
-
}),
|
|
211
|
-
channelKey: channel
|
|
212
|
-
}) };
|
|
213
|
-
},
|
|
214
|
-
dmPolicy: googlechatDmPolicy
|
|
215
|
-
};
|
|
216
|
-
//#endregion
|
|
217
|
-
export { googlechatSetupAdapter as n, googlechatSetupWizard as t };
|
package/dist/targets-AuEcZdcJ.js
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { a as findGoogleChatDirectMessage } from "./api-CBWAN9YL.js";
|
|
2
|
-
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
|
-
//#region extensions/googlechat/src/targets.ts
|
|
4
|
-
function normalizeGoogleChatTarget(raw) {
|
|
5
|
-
const trimmed = raw?.trim();
|
|
6
|
-
if (!trimmed) return;
|
|
7
|
-
const normalized = trimmed.replace(/^(googlechat|google-chat|gchat):/i, "").replace(/^user:(users\/)?/i, "users/").replace(/^space:(spaces\/)?/i, "spaces/");
|
|
8
|
-
if (isGoogleChatUserTarget(normalized)) {
|
|
9
|
-
const suffix = normalized.slice(6);
|
|
10
|
-
return suffix.includes("@") ? `users/${normalizeLowercaseStringOrEmpty(suffix)}` : normalized;
|
|
11
|
-
}
|
|
12
|
-
if (isGoogleChatSpaceTarget(normalized)) return normalized;
|
|
13
|
-
if (normalized.includes("@")) return `users/${normalizeLowercaseStringOrEmpty(normalized)}`;
|
|
14
|
-
return normalized;
|
|
15
|
-
}
|
|
16
|
-
function isGoogleChatUserTarget(value) {
|
|
17
|
-
return normalizeLowercaseStringOrEmpty(value).startsWith("users/");
|
|
18
|
-
}
|
|
19
|
-
function isGoogleChatSpaceTarget(value) {
|
|
20
|
-
return normalizeLowercaseStringOrEmpty(value).startsWith("spaces/");
|
|
21
|
-
}
|
|
22
|
-
function stripMessageSuffix(target) {
|
|
23
|
-
const index = target.indexOf("/messages/");
|
|
24
|
-
if (index === -1) return target;
|
|
25
|
-
return target.slice(0, index);
|
|
26
|
-
}
|
|
27
|
-
async function resolveGoogleChatOutboundSpace(params) {
|
|
28
|
-
const normalized = normalizeGoogleChatTarget(params.target);
|
|
29
|
-
if (!normalized) throw new Error("Missing Google Chat target.");
|
|
30
|
-
const base = stripMessageSuffix(normalized);
|
|
31
|
-
if (isGoogleChatSpaceTarget(base)) return base;
|
|
32
|
-
if (isGoogleChatUserTarget(base)) {
|
|
33
|
-
const dm = await findGoogleChatDirectMessage({
|
|
34
|
-
account: params.account,
|
|
35
|
-
userName: base
|
|
36
|
-
});
|
|
37
|
-
if (!dm?.name) throw new Error(`No Google Chat DM found for ${base}`);
|
|
38
|
-
return dm.name;
|
|
39
|
-
}
|
|
40
|
-
return base;
|
|
41
|
-
}
|
|
42
|
-
//#endregion
|
|
43
|
-
export { resolveGoogleChatOutboundSpace as i, isGoogleChatUserTarget as n, normalizeGoogleChatTarget as r, isGoogleChatSpaceTarget as t };
|
|
File without changes
|
|
File without changes
|