@openclaw/googlechat 2026.5.14-beta.1 → 2026.5.14-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.
@@ -1,7 +1,7 @@
1
- import { i as resolveGoogleChatAccount, t as listEnabledGoogleChatAccounts } from "./accounts-BlfWEj_G.js";
1
+ import { o as resolveGoogleChatAccount, r as listEnabledGoogleChatAccounts } from "./setup-surface-BlDqtKML.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-CBWAN9YL.js";
4
- import { i as resolveGoogleChatOutboundSpace } from "./targets-AuEcZdcJ.js";
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-DzmqN0DY.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.json();
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.json()
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.json()
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 googlechatPlugin } from "./channel-BpW0Eiw7.js";
2
- import { n as googlechatSetupAdapter, t as googlechatSetupWizard } from "./setup-surface-Cr3BORD4.js";
1
+ import { n as googlechatSetupAdapter, t as googlechatSetupWizard } from "./setup-surface-BlDqtKML.js";
2
+ import { t as googlechatPlugin } from "./channel-DzmqN0DY.js";
3
3
  export { googlechatPlugin, googlechatSetupAdapter, googlechatSetupWizard };
@@ -1,9 +1,8 @@
1
- import { a as resolveGoogleChatConfigAccessorAccount, i as resolveGoogleChatAccount, n as listGoogleChatAccountIds, r as resolveDefaultGoogleChatAccountId } from "./accounts-BlfWEj_G.js";
1
+ import { a as resolveDefaultGoogleChatAccountId, i as listGoogleChatAccountIds, n as googlechatSetupAdapter, o as resolveGoogleChatAccount, s as resolveGoogleChatConfigAccessorAccount, t as googlechatSetupWizard } from "./setup-surface-BlDqtKML.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 { i as resolveGoogleChatOutboundSpace, n as isGoogleChatUserTarget, r as normalizeGoogleChatTarget, t as isGoogleChatSpaceTarget } from "./targets-AuEcZdcJ.js";
4
- import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-BsERSjSe.js";
5
- import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-DLAG2_NI.js";
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-CKDAMPpq.js"), "googleChatChannelRuntime");
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-CKDAMPpq.js"), "googleChatChannelRuntime");
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-CKDAMPpq.js"), "googleChatChannelRuntime");
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-C__ryYKJ.js");
433
+ const { googlechatMessageActions } = await import("./actions-Cp9JuEzB.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-BpW0Eiw7.js";
1
+ import { t as googlechatPlugin } from "./channel-DzmqN0DY.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-CBWAN9YL.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-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";
@@ -1,3 +1,3 @@
1
- import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-BsERSjSe.js";
2
- import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-DLAG2_NI.js";
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-BsERSjSe.js";
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-DLAG2_NI.js";
1
+ import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-DtQ_IO7J.js";
2
2
  export { channelSecrets, collectRuntimeConfigAssignments, secretTargetRegistryEntries };
@@ -1,5 +1,4 @@
1
- import { a as resolveGoogleChatConfigAccessorAccount, i as resolveGoogleChatAccount, n as listGoogleChatAccountIds, r as resolveDefaultGoogleChatAccountId } from "./accounts-BlfWEj_G.js";
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-BlDqtKML.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";
@@ -1,7 +1,103 @@
1
- import { i as resolveGoogleChatAccount, r as resolveDefaultGoogleChatAccountId } from "./accounts-BlfWEj_G.js";
1
+ import { safeParseJsonWithSchema, safeParseWithSchema } from "openclaw/plugin-sdk/extension-shared";
2
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";
3
7
  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";
8
+ import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, addWildcardAllowFrom, applySetupAccountConfigPatch, createPromptParsedAllowFromForAccount, 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
+ }
5
101
  const googlechatSetupAdapter = createPatchedAccountSetupAdapter({
6
102
  channelKey: "googlechat",
7
103
  validateInput: createSetupInputPresenceValidator({
@@ -38,7 +134,7 @@ const googlechatDmPolicy = {
38
134
  channel,
39
135
  policyKey: "channels.googlechat.dm.policy",
40
136
  allowFromKey: "channels.googlechat.dm.allowFrom",
41
- resolveConfigKeys: (cfg, accountId) => (accountId ?? resolveDefaultGoogleChatAccountId(cfg)) !== DEFAULT_ACCOUNT_ID ? {
137
+ resolveConfigKeys: (cfg, accountId) => (accountId ?? resolveDefaultGoogleChatAccountId(cfg)) !== DEFAULT_ACCOUNT_ID$1 ? {
42
138
  policyKey: `channels.googlechat.accounts.${accountId ?? resolveDefaultGoogleChatAccountId(cfg)}.dm.policy`,
43
139
  allowFromKey: `channels.googlechat.accounts.${accountId ?? resolveDefaultGoogleChatAccountId(cfg)}.dm.allowFrom`
44
140
  } : {
@@ -129,7 +225,7 @@ const googlechatSetupWizard = {
129
225
  ]
130
226
  },
131
227
  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]))) {
228
+ if (accountId === DEFAULT_ACCOUNT_ID$1 && (Boolean(process.env[ENV_SERVICE_ACCOUNT]) || Boolean(process.env[ENV_SERVICE_ACCOUNT_FILE]))) {
133
229
  if (await prompter.confirm({
134
230
  message: "Use GOOGLE_CHAT_SERVICE_ACCOUNT env vars?",
135
231
  initialValue: true
@@ -214,4 +310,4 @@ const googlechatSetupWizard = {
214
310
  dmPolicy: googlechatDmPolicy
215
311
  };
216
312
  //#endregion
217
- export { googlechatSetupAdapter as n, googlechatSetupWizard as t };
313
+ 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
@@ -1,3 +1,3 @@
1
1
  import { F as setGoogleChatRuntime } from "./runtime-api-DuEfWHnr.js";
2
- import { t as googlechatPlugin } from "./channel-BpW0Eiw7.js";
2
+ import { t as googlechatPlugin } from "./channel-DzmqN0DY.js";
3
3
  export { googlechatPlugin, setGoogleChatRuntime };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/googlechat",
3
- "version": "2026.5.14-beta.1",
3
+ "version": "2026.5.14-beta.2",
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.14-beta.1"
20
+ "openclaw": ">=2026.5.14-beta.2"
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.14-beta.1"
78
+ "pluginApi": ">=2026.5.14-beta.2"
79
79
  },
80
80
  "build": {
81
- "openclawVersion": "2026.5.14-beta.1"
81
+ "openclawVersion": "2026.5.14-beta.2"
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,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 };