@openclaw/googlechat 2026.5.7 → 2026.5.10-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.
@@ -1,40 +1,44 @@
1
- import { A as resolveInboundRouteEnvelopeBuilderWithRuntime, D as resolveDefaultGroupPolicy, F as warnMissingProviderGroupPolicyFallbackOnce, L as getGoogleChatRuntime, M as resolveWebhookPath, O as resolveDmGroupAccessWithLists, T as resolveAllowlistProviderRuntimeGroupPolicy, f as evaluateGroupRouteAccessForPolicy, g as isDangerousNameMatchingEnabled, j as resolveSenderScopedGroupPolicy, l as createChannelPairingController, n as GROUP_POLICY_BLOCKED_LABEL, u as createChannelReplyPipeline } from "./runtime-api-wkIdfwqY.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-C8OqyWsW.js";
3
- import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
4
- import { resolveInboundMentionDecision } from "openclaw/plugin-sdk/channel-inbound";
1
+ import { E as resolveDefaultGroupPolicy, M as warnMissingProviderGroupPolicyFallbackOnce, O as resolveInboundRouteEnvelopeBuilderWithRuntime, P as getGoogleChatRuntime, h as isDangerousNameMatchingEnabled, k as resolveWebhookPath, n as GROUP_POLICY_BLOCKED_LABEL, u as createChannelPairingController, w as resolveAllowlistProviderRuntimeGroupPolicy } from "./runtime-api-DMEzhesS.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-AErsImS_.js";
3
+ import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/text-runtime";
5
4
  import { registerWebhookTargetWithPluginRoute, resolveWebhookTargetWithAuthOrReject, withResolvedWebhookRequestPipeline } from "openclaw/plugin-sdk/webhook-targets";
6
5
  import { createWebhookInFlightLimiter, readJsonWebhookBodyOrReject } from "openclaw/plugin-sdk/webhook-request-guards";
7
- import { expandAllowFromWithAccessGroups } from "openclaw/plugin-sdk/security-runtime";
6
+ import { channelIngressRoutes, createChannelIngressResolver, defineStableChannelIngressIdentity } from "openclaw/plugin-sdk/channel-ingress-runtime";
8
7
  import { deliverTextOrMediaReply, resolveSendableOutboundReplyParts } from "openclaw/plugin-sdk/reply-payload";
9
- //#region extensions/googlechat/src/sender-allow.ts
10
- function normalizeUserId$1(raw) {
11
- const trimmed = typeof raw === "string" ? raw.trim() : "";
12
- if (!trimmed) return "";
13
- return normalizeLowercaseStringOrEmpty(trimmed.replace(/^users\//i, ""));
14
- }
15
- function isEmailLike(value) {
16
- return value.includes("@");
17
- }
18
- function isSenderAllowed(senderId, senderEmail, allowFrom, allowNameMatching = false) {
19
- if (allowFrom.includes("*")) return true;
20
- const normalizedSenderId = normalizeUserId$1(senderId);
21
- const normalizedEmail = normalizeLowercaseStringOrEmpty(senderEmail ?? "");
22
- return allowFrom.some((entry) => {
23
- const normalized = normalizeLowercaseStringOrEmpty(entry);
24
- if (!normalized) return false;
25
- const withoutPrefix = normalized.replace(/^(googlechat|google-chat|gchat):/i, "");
26
- if (withoutPrefix.startsWith("users/")) return normalizeUserId$1(withoutPrefix) === normalizedSenderId;
27
- if (allowNameMatching && normalizedEmail && isEmailLike(withoutPrefix)) return withoutPrefix === normalizedEmail;
28
- return withoutPrefix.replace(/^users\//i, "") === normalizedSenderId;
29
- });
30
- }
31
- //#endregion
32
8
  //#region extensions/googlechat/src/monitor-access.ts
33
9
  function normalizeUserId(raw) {
34
10
  const trimmed = normalizeOptionalString(raw) ?? "";
35
11
  if (!trimmed) return "";
36
12
  return normalizeLowercaseStringOrEmpty(trimmed.replace(/^users\//i, ""));
37
13
  }
14
+ const GOOGLECHAT_EMAIL_KIND = "plugin:googlechat-email";
15
+ function normalizeEntryValue(raw) {
16
+ return normalizeLowercaseStringOrEmpty(raw ?? "");
17
+ }
18
+ function normalizeGoogleChatStableEntry(entry) {
19
+ const withoutProvider = normalizeEntryValue(entry).replace(/^(googlechat|google-chat|gchat):/i, "");
20
+ if (!withoutProvider) return null;
21
+ return withoutProvider.startsWith("users/") ? normalizeUserId(withoutProvider) : withoutProvider;
22
+ }
23
+ function normalizeGoogleChatEmailEntry(entry) {
24
+ if (normalizeEntryValue(entry).replace(/^(googlechat|google-chat|gchat):/i, "").startsWith("users/")) return null;
25
+ const stable = normalizeGoogleChatStableEntry(entry);
26
+ return stable?.includes("@") ? stable : null;
27
+ }
28
+ const googleChatIngressIdentity = defineStableChannelIngressIdentity({
29
+ key: "sender-id",
30
+ normalizeEntry: normalizeGoogleChatStableEntry,
31
+ normalizeSubject: normalizeUserId,
32
+ aliases: [{
33
+ key: "email",
34
+ kind: GOOGLECHAT_EMAIL_KIND,
35
+ normalizeEntry: normalizeGoogleChatEmailEntry,
36
+ normalizeSubject: normalizeEntryValue,
37
+ dangerous: true
38
+ }],
39
+ isWildcardEntry: (entry) => normalizeEntryValue(entry) === "*",
40
+ resolveEntryId: ({ entryIndex, fieldKey }) => fieldKey === "stableId" ? `entry-${entryIndex + 1}:user` : `entry-${entryIndex + 1}:${fieldKey}`
41
+ });
38
42
  function resolveGroupConfig(params) {
39
43
  const { groupId, groupName, groups } = params;
40
44
  const entries = groups ?? {};
@@ -121,120 +125,116 @@ async function applyGoogleChatInboundAccessPolicy(params) {
121
125
  });
122
126
  const groupEntry = groupConfigResolved.entry;
123
127
  const groupUsers = groupEntry?.users ?? account.config.groupAllowFrom ?? [];
124
- const isGoogleChatSenderAllowed = (_senderId, allowFrom) => isSenderAllowed(senderId, senderEmail, allowFrom, allowNameMatching);
125
- const expandedGroupUsers = await expandAllowFromWithAccessGroups({
126
- cfg: config,
127
- allowFrom: groupUsers,
128
- channel: "googlechat",
128
+ let effectiveWasMentioned;
129
+ const dmPolicy = account.config.dm?.policy ?? "pairing";
130
+ const rawConfigAllowFrom = normalizeStringEntries(account.config.dm?.allowFrom);
131
+ const shouldComputeAuth = core.channel.commands.shouldComputeCommandAuthorized(rawBody, config);
132
+ const groupActivation = (() => {
133
+ if (!isGroup) return;
134
+ const requireMention = groupEntry?.requireMention ?? account.config.requireMention ?? true;
135
+ const mentionInfo = extractMentionInfo(message.annotations ?? [], account.config.botUser);
136
+ return {
137
+ requireMention,
138
+ allowTextCommands: core.channel.commands.shouldHandleTextCommands({
139
+ cfg: config,
140
+ surface: "googlechat"
141
+ }),
142
+ hasControlCommand: core.channel.text.hasControlCommand(rawBody, config),
143
+ wasMentioned: mentionInfo.wasMentioned,
144
+ hasAnyMention: mentionInfo.hasAnyMention
145
+ };
146
+ })();
147
+ const command = {
148
+ hasControlCommand: groupActivation?.hasControlCommand ?? shouldComputeAuth,
149
+ groupOwnerAllowFrom: "none"
150
+ };
151
+ const groupAllowFrom = normalizeStringEntries(groupUsers);
152
+ const senderGroupPolicy = groupConfigResolved.allowlistConfigured && groupAllowFrom.length === 0 ? groupPolicy : groupPolicy === "disabled" ? "disabled" : groupAllowFrom.length > 0 ? "allowlist" : "open";
153
+ const route = channelIngressRoutes(isGroup && groupPolicy !== "disabled" && groupEntry?.enabled === false && {
154
+ id: "googlechat:space",
155
+ enabled: false,
156
+ matched: true,
157
+ matchId: "googlechat-space",
158
+ blockReason: "route_disabled"
159
+ }, isGroup && groupPolicy === "allowlist" && groupEntry?.enabled !== false && !groupConfigResolved.allowlistConfigured && {
160
+ id: "googlechat:space",
161
+ allowed: false,
162
+ blockReason: "empty_allowlist"
163
+ }, isGroup && groupPolicy === "allowlist" && groupEntry?.enabled !== false && groupConfigResolved.allowlistConfigured && {
164
+ id: "googlechat:space",
165
+ senderPolicy: "deny-when-empty",
166
+ ...groupEntry ? { senderAllowFromSource: "effective-group" } : {},
167
+ allowed: Boolean(groupEntry),
168
+ matchId: "googlechat-space",
169
+ blockReason: groupEntry ? "sender_empty_allowlist" : "route_not_allowlisted"
170
+ });
171
+ const resolvedAccess = await createChannelIngressResolver({
172
+ channelId: "googlechat",
129
173
  accountId: account.accountId,
130
- senderId,
131
- isSenderAllowed: isGoogleChatSenderAllowed
174
+ identity: googleChatIngressIdentity,
175
+ cfg: config,
176
+ readStoreAllowFrom: pairing.readAllowFromStore
177
+ }).message({
178
+ subject: {
179
+ stableId: senderId,
180
+ aliases: { email: senderEmail }
181
+ },
182
+ conversation: {
183
+ kind: isGroup ? "group" : "direct",
184
+ id: spaceId
185
+ },
186
+ route,
187
+ allowFrom: rawConfigAllowFrom,
188
+ groupAllowFrom,
189
+ dmPolicy,
190
+ groupPolicy: senderGroupPolicy,
191
+ policy: {
192
+ groupAllowFromFallbackToAllowFrom: false,
193
+ mutableIdentifierMatching: allowNameMatching ? "enabled" : "disabled",
194
+ ...groupActivation ? { activation: {
195
+ requireMention: groupActivation.requireMention,
196
+ allowTextCommands: groupActivation.allowTextCommands
197
+ } } : {}
198
+ },
199
+ ...groupActivation == null ? {} : { mentionFacts: {
200
+ canDetectMention: true,
201
+ wasMentioned: groupActivation.wasMentioned,
202
+ hasAnyMention: groupActivation.hasAnyMention,
203
+ implicitMentionKinds: []
204
+ } },
205
+ command
132
206
  });
133
- let effectiveWasMentioned;
207
+ const senderAccess = resolvedAccess.senderAccess;
208
+ const commandAuthorized = resolvedAccess.commandAccess.requested ? resolvedAccess.commandAccess.authorized : void 0;
134
209
  if (isGroup) {
135
210
  if (groupConfigResolved.deprecatedNameMatch) {
136
211
  logVerbose(`drop group message (deprecated mutable group key matched, space=${spaceId})`);
137
212
  return { ok: false };
138
213
  }
139
- const groupAllowlistConfigured = groupConfigResolved.allowlistConfigured;
140
- const routeAccess = evaluateGroupRouteAccessForPolicy({
141
- groupPolicy,
142
- routeAllowlistConfigured: groupAllowlistConfigured,
143
- routeMatched: Boolean(groupEntry),
144
- routeEnabled: groupEntry?.enabled !== false
145
- });
146
- if (!routeAccess.allowed) {
147
- if (routeAccess.reason === "disabled") logVerbose(`drop group message (groupPolicy=disabled, space=${spaceId})`);
148
- else if (routeAccess.reason === "empty_allowlist") logVerbose(`drop group message (groupPolicy=allowlist, no allowlist, space=${spaceId})`);
149
- else if (routeAccess.reason === "route_not_allowlisted") logVerbose(`drop group message (not allowlisted, space=${spaceId})`);
150
- else if (routeAccess.reason === "route_disabled") logVerbose(`drop group message (space disabled, space=${spaceId})`);
214
+ const routeBlockReason = resolvedAccess.routeAccess.reason;
215
+ if (routeBlockReason && routeBlockReason !== "sender_empty_allowlist") {
216
+ if (routeBlockReason === "empty_allowlist") logVerbose(`drop group message (groupPolicy=allowlist, no allowlist, space=${spaceId})`);
217
+ else if (routeBlockReason === "route_not_allowlisted") logVerbose(`drop group message (not allowlisted, space=${spaceId})`);
218
+ else if (routeBlockReason === "route_disabled") logVerbose(`drop group message (space disabled, space=${spaceId})`);
151
219
  return { ok: false };
152
220
  }
153
- if (expandedGroupUsers.length > 0) {
154
- warnDeprecatedUsersEmailEntries(logVerbose, expandedGroupUsers);
155
- if (!isSenderAllowed(senderId, senderEmail, expandedGroupUsers, allowNameMatching)) {
156
- logVerbose(`drop group message (sender not allowed, ${senderId})`);
157
- return { ok: false };
158
- }
221
+ if (senderAccess.effectiveGroupAllowFrom.length > 0 && senderAccess.decision !== "allow") {
222
+ warnDeprecatedUsersEmailEntries(logVerbose, senderAccess.effectiveGroupAllowFrom);
223
+ logVerbose(`drop group message (sender not allowed, ${senderId})`);
224
+ return { ok: false };
159
225
  }
160
226
  }
161
- const dmPolicy = account.config.dm?.policy ?? "pairing";
162
- const rawConfigAllowFrom = (account.config.dm?.allowFrom ?? []).map((v) => String(v));
163
- const normalizedGroupUsers = expandedGroupUsers;
164
- const senderGroupPolicy = groupConfigResolved.allowlistConfigured && normalizedGroupUsers.length === 0 ? groupPolicy : resolveSenderScopedGroupPolicy({
165
- groupPolicy,
166
- groupAllowFrom: normalizedGroupUsers
167
- });
168
- const shouldComputeAuth = core.channel.commands.shouldComputeCommandAuthorized(rawBody, config);
169
- const storeAllowFrom = !isGroup && dmPolicy !== "allowlist" && dmPolicy !== "open" ? await pairing.readAllowFromStore().catch(() => []) : [];
170
- const [configAllowFrom, effectiveStoreAllowFrom] = await Promise.all([expandAllowFromWithAccessGroups({
171
- cfg: config,
172
- allowFrom: rawConfigAllowFrom,
173
- channel: "googlechat",
174
- accountId: account.accountId,
175
- senderId,
176
- isSenderAllowed: isGoogleChatSenderAllowed
177
- }), expandAllowFromWithAccessGroups({
178
- cfg: config,
179
- allowFrom: storeAllowFrom,
180
- channel: "googlechat",
181
- accountId: account.accountId,
182
- senderId,
183
- isSenderAllowed: isGoogleChatSenderAllowed
184
- })]);
185
- const access = resolveDmGroupAccessWithLists({
186
- isGroup,
187
- dmPolicy,
188
- groupPolicy: senderGroupPolicy,
189
- allowFrom: configAllowFrom,
190
- groupAllowFrom: normalizedGroupUsers,
191
- storeAllowFrom: effectiveStoreAllowFrom,
192
- groupAllowFromFallbackToAllowFrom: false,
193
- isSenderAllowed: (allowFrom) => isSenderAllowed(senderId, senderEmail, allowFrom, allowNameMatching)
194
- });
195
- const effectiveAllowFrom = access.effectiveAllowFrom;
196
- const effectiveGroupAllowFrom = access.effectiveGroupAllowFrom;
227
+ const effectiveAllowFrom = senderAccess.effectiveAllowFrom;
197
228
  warnDeprecatedUsersEmailEntries(logVerbose, effectiveAllowFrom);
198
- const commandAllowFrom = isGroup ? effectiveGroupAllowFrom : effectiveAllowFrom;
199
- const useAccessGroups = config.commands?.useAccessGroups !== false;
200
- const senderAllowedForCommands = isSenderAllowed(senderId, senderEmail, commandAllowFrom, allowNameMatching);
201
- const commandAuthorized = shouldComputeAuth ? core.channel.commands.resolveCommandAuthorizedFromAuthorizers({
202
- useAccessGroups,
203
- authorizers: [{
204
- configured: commandAllowFrom.length > 0,
205
- allowed: senderAllowedForCommands
206
- }]
207
- }) : void 0;
208
- if (isGroup) {
209
- const requireMention = groupEntry?.requireMention ?? account.config.requireMention ?? true;
210
- const mentionInfo = extractMentionInfo(message.annotations ?? [], account.config.botUser);
211
- const allowTextCommands = core.channel.commands.shouldHandleTextCommands({
212
- cfg: config,
213
- surface: "googlechat"
214
- });
215
- const mentionDecision = resolveInboundMentionDecision({
216
- facts: {
217
- canDetectMention: true,
218
- wasMentioned: mentionInfo.wasMentioned,
219
- hasAnyMention: mentionInfo.hasAnyMention,
220
- implicitMentionKinds: []
221
- },
222
- policy: {
223
- isGroup: true,
224
- requireMention,
225
- allowTextCommands,
226
- hasControlCommand: core.channel.text.hasControlCommand(rawBody, config),
227
- commandAuthorized: commandAuthorized === true
228
- }
229
- });
230
- effectiveWasMentioned = mentionDecision.effectiveWasMentioned;
231
- if (mentionDecision.shouldSkip) {
229
+ if (isGroup && resolvedAccess.activationAccess.ran) {
230
+ effectiveWasMentioned = resolvedAccess.activationAccess.effectiveWasMentioned;
231
+ if (resolvedAccess.activationAccess.shouldSkip) {
232
232
  logVerbose(`drop group message (mention required, space=${spaceId})`);
233
233
  return { ok: false };
234
234
  }
235
235
  }
236
- if (isGroup && access.decision !== "allow") {
237
- logVerbose(`drop group message (sender policy blocked, reason=${access.reason}, space=${spaceId})`);
236
+ if (isGroup && senderAccess.decision !== "allow") {
237
+ logVerbose(`drop group message (sender policy blocked, reason=${resolvedAccess.ingress.reasonCode === "route_sender_empty" ? "groupPolicy=allowlist (empty allowlist)" : senderAccess.reasonCode}, space=${spaceId})`);
238
238
  return { ok: false };
239
239
  }
240
240
  if (!isGroup) {
@@ -242,8 +242,8 @@ async function applyGoogleChatInboundAccessPolicy(params) {
242
242
  logVerbose(`Blocked Google Chat DM from ${senderId} (dmPolicy=disabled)`);
243
243
  return { ok: false };
244
244
  }
245
- if (access.decision !== "allow") {
246
- if (access.decision === "pairing") await pairing.issueChallenge({
245
+ if (senderAccess.decision !== "allow") {
246
+ if (senderAccess.decision === "pairing") await pairing.issueChallenge({
247
247
  senderId,
248
248
  senderIdLine: `Your Google Chat user id: ${senderId}`,
249
249
  meta: {
@@ -281,6 +281,19 @@ async function applyGoogleChatInboundAccessPolicy(params) {
281
281
  };
282
282
  }
283
283
  //#endregion
284
+ //#region extensions/googlechat/src/monitor-durable.ts
285
+ function resolveGoogleChatDurableReplyOptions(params) {
286
+ if (params.infoKind !== "final" || params.typingMessageName) return false;
287
+ const threadId = params.payload.replyToId?.trim() || void 0;
288
+ return {
289
+ to: params.spaceId,
290
+ ...threadId ? {
291
+ replyToId: threadId,
292
+ threadId
293
+ } : {}
294
+ };
295
+ }
296
+ //#endregion
284
297
  //#region extensions/googlechat/src/monitor-reply-delivery.ts
285
298
  async function deliverGoogleChatReply(params) {
286
299
  const { payload, account, spaceId, runtime, core, config, statusSink } = params;
@@ -791,12 +804,6 @@ async function processMessageWithPipeline(params) {
791
804
  } catch (err) {
792
805
  runtime.error?.(`Failed sending typing message: ${String(err)}`);
793
806
  }
794
- const { onModelSelected, ...replyPipeline } = createChannelReplyPipeline({
795
- cfg: config,
796
- agentId: route.agentId,
797
- channel: "googlechat",
798
- accountId: route.accountId
799
- });
800
807
  await core.channel.turn.run({
801
808
  channel: "googlechat",
802
809
  accountId: route.accountId,
@@ -821,6 +828,12 @@ async function processMessageWithPipeline(params) {
821
828
  recordInboundSession: core.channel.session.recordInboundSession,
822
829
  dispatchReplyWithBufferedBlockDispatcher: core.channel.reply.dispatchReplyWithBufferedBlockDispatcher,
823
830
  delivery: {
831
+ durable: (payload, info) => resolveGoogleChatDurableReplyOptions({
832
+ payload,
833
+ infoKind: info.kind,
834
+ spaceId,
835
+ typingMessageName
836
+ }),
824
837
  deliver: async (payload) => {
825
838
  await deliverGoogleChatReply({
826
839
  payload,
@@ -834,12 +847,14 @@ async function processMessageWithPipeline(params) {
834
847
  });
835
848
  typingMessageName = void 0;
836
849
  },
850
+ onDelivered: () => {
851
+ statusSink?.({ lastOutboundAt: Date.now() });
852
+ },
837
853
  onError: (err, info) => {
838
854
  runtime.error?.(`[${account.accountId}] Google Chat ${info.kind} reply failed: ${String(err)}`);
839
855
  }
840
856
  },
841
- dispatcherOptions: replyPipeline,
842
- replyOptions: { onModelSelected },
857
+ replyPipeline: {},
843
858
  record: { onRecordError: (err) => {
844
859
  runtime.error?.(`googlechat: failed updating session meta: ${String(err)}`);
845
860
  } }
@@ -1,3 +1,3 @@
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";
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";
3
3
  export { collectRuntimeConfigAssignments, legacyConfigRules, normalizeCompatibilityConfig, secretTargetRegistryEntries };
@@ -1,2 +1,2 @@
1
- import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-CG1sLToP.js";
1
+ import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-BsERSjSe.js";
2
2
  export { legacyConfigRules, normalizeCompatibilityConfig };
@@ -1,21 +1,20 @@
1
- import { createActionGate as createActionGate$1, jsonResult as jsonResult$1, readNumberParam as readNumberParam$1, readReactionParams as readReactionParams$1, readStringParam as readStringParam$1 } from "openclaw/plugin-sdk/channel-actions";
2
- import { loadOutboundMediaFromUrl as loadOutboundMediaFromUrl$1 } from "openclaw/plugin-sdk/outbound-media";
3
1
  import { extractToolSend as extractToolSend$1 } from "openclaw/plugin-sdk/tool-send";
4
2
  import { fetchWithSsrFGuard as fetchWithSsrFGuard$1 } from "openclaw/plugin-sdk/ssrf-runtime";
5
3
  import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
4
+ import { createActionGate as createActionGate$1, jsonResult as jsonResult$1, readNumberParam as readNumberParam$1, readReactionParams as readReactionParams$1, readStringParam as readStringParam$1 } from "openclaw/plugin-sdk/channel-actions";
6
5
  import { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-primitives";
7
6
  import { missingTargetError } from "openclaw/plugin-sdk/channel-feedback";
8
7
  import { createAccountStatusSink as createAccountStatusSink$1, runPassiveAccountLifecycle as runPassiveAccountLifecycle$1 } from "openclaw/plugin-sdk/channel-lifecycle";
9
8
  import { createChannelPairingController } from "openclaw/plugin-sdk/channel-pairing";
10
- import { createChannelReplyPipeline } from "openclaw/plugin-sdk/channel-reply-pipeline";
11
- import { evaluateGroupRouteAccessForPolicy, resolveDmGroupAccessWithLists, resolveSenderScopedGroupPolicy } from "openclaw/plugin-sdk/channel-policy";
9
+ import { createChannelMessageReplyPipeline } from "openclaw/plugin-sdk/channel-message";
12
10
  import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
13
11
  import { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
14
12
  import { GoogleChatConfigSchema } from "openclaw/plugin-sdk/bundled-channel-config-schema";
15
13
  import { GROUP_POLICY_BLOCKED_LABEL, resolveAllowlistProviderRuntimeGroupPolicy, resolveDefaultGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce } from "openclaw/plugin-sdk/runtime-group-policy";
16
14
  import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-name-runtime";
17
15
  import { fetchRemoteMedia, resolveChannelMediaMaxBytes } from "openclaw/plugin-sdk/media-runtime";
18
- import { resolveInboundMentionDecision as resolveInboundMentionDecision$1 } from "openclaw/plugin-sdk/channel-inbound";
16
+ import { loadOutboundMediaFromUrl as loadOutboundMediaFromUrl$1 } from "openclaw/plugin-sdk/outbound-media";
17
+ import { resolveInboundMentionDecision } from "openclaw/plugin-sdk/channel-inbound";
19
18
  import { resolveInboundRouteEnvelopeBuilderWithRuntime } from "openclaw/plugin-sdk/inbound-envelope";
20
19
  import { resolveWebhookPath } from "openclaw/plugin-sdk/webhook-path";
21
20
  import { registerWebhookTargetWithPluginRoute as registerWebhookTargetWithPluginRoute$1, resolveWebhookTargetWithAuthOrReject as resolveWebhookTargetWithAuthOrReject$1, withResolvedWebhookRequestPipeline as withResolvedWebhookRequestPipeline$1 } from "openclaw/plugin-sdk/webhook-targets";
@@ -27,4 +26,4 @@ const { setRuntime: setGoogleChatRuntime, getRuntime: getGoogleChatRuntime } = c
27
26
  errorMessage: "Google Chat runtime not initialized"
28
27
  });
29
28
  //#endregion
30
- export { resolveInboundRouteEnvelopeBuilderWithRuntime as A, readStringParam$1 as C, resolveDefaultGroupPolicy as D, resolveChannelMediaMaxBytes as E, warnMissingProviderGroupPolicyFallbackOnce as F, withResolvedWebhookRequestPipeline$1 as I, getGoogleChatRuntime as L, resolveWebhookPath as M, resolveWebhookTargetWithAuthOrReject$1 as N, resolveDmGroupAccessWithLists as O, runPassiveAccountLifecycle$1 as P, setGoogleChatRuntime as R, readReactionParams$1 as S, resolveAllowlistProviderRuntimeGroupPolicy as T, jsonResult$1 as _, buildChannelConfigSchema as a, readJsonWebhookBodyOrReject$1 as b, createActionGate$1 as c, createWebhookInFlightLimiter$1 as d, evaluateGroupRouteAccessForPolicy as f, isDangerousNameMatchingEnabled as g, fetchWithSsrFGuard$1 as h, PAIRING_APPROVED_MESSAGE as i, resolveSenderScopedGroupPolicy as j, resolveInboundMentionDecision$1 as k, createChannelPairingController as l, fetchRemoteMedia as m, GROUP_POLICY_BLOCKED_LABEL as n, chunkTextForOutbound as o, extractToolSend$1 as p, GoogleChatConfigSchema as r, createAccountStatusSink$1 as s, DEFAULT_ACCOUNT_ID as t, createChannelReplyPipeline as u, loadOutboundMediaFromUrl$1 as v, registerWebhookTargetWithPluginRoute$1 as w, readNumberParam$1 as x, missingTargetError as y };
29
+ export { resolveWebhookTargetWithAuthOrReject$1 as A, registerWebhookTargetWithPluginRoute$1 as C, resolveInboundMentionDecision as D, resolveDefaultGroupPolicy as E, setGoogleChatRuntime as F, warnMissingProviderGroupPolicyFallbackOnce as M, withResolvedWebhookRequestPipeline$1 as N, resolveInboundRouteEnvelopeBuilderWithRuntime as O, getGoogleChatRuntime as P, readStringParam$1 as S, resolveChannelMediaMaxBytes as T, loadOutboundMediaFromUrl$1 as _, buildChannelConfigSchema as a, readNumberParam$1 as b, createActionGate$1 as c, createWebhookInFlightLimiter$1 as d, extractToolSend$1 as f, jsonResult$1 as g, isDangerousNameMatchingEnabled as h, PAIRING_APPROVED_MESSAGE as i, runPassiveAccountLifecycle$1 as j, resolveWebhookPath as k, createChannelMessageReplyPipeline as l, fetchWithSsrFGuard$1 as m, GROUP_POLICY_BLOCKED_LABEL as n, chunkTextForOutbound as o, fetchRemoteMedia as p, GoogleChatConfigSchema as r, createAccountStatusSink$1 as s, DEFAULT_ACCOUNT_ID as t, createChannelPairingController as u, missingTargetError as v, resolveAllowlistProviderRuntimeGroupPolicy as w, readReactionParams$1 as x, readJsonWebhookBodyOrReject$1 as y };
@@ -1,2 +1,2 @@
1
- import { A as resolveInboundRouteEnvelopeBuilderWithRuntime, C as readStringParam, D as resolveDefaultGroupPolicy, E as resolveChannelMediaMaxBytes, F as warnMissingProviderGroupPolicyFallbackOnce, I as withResolvedWebhookRequestPipeline, M as resolveWebhookPath, N as resolveWebhookTargetWithAuthOrReject, O as resolveDmGroupAccessWithLists, P as runPassiveAccountLifecycle, R as setGoogleChatRuntime, S as readReactionParams, T as resolveAllowlistProviderRuntimeGroupPolicy, _ as jsonResult, a as buildChannelConfigSchema, b as readJsonWebhookBodyOrReject, c as createActionGate, d as createWebhookInFlightLimiter, f as evaluateGroupRouteAccessForPolicy, g as isDangerousNameMatchingEnabled, h as fetchWithSsrFGuard, i as PAIRING_APPROVED_MESSAGE, j as resolveSenderScopedGroupPolicy, k as resolveInboundMentionDecision, l as createChannelPairingController, m as fetchRemoteMedia, n as GROUP_POLICY_BLOCKED_LABEL, o as chunkTextForOutbound, p as extractToolSend, r as GoogleChatConfigSchema, s as createAccountStatusSink, t as DEFAULT_ACCOUNT_ID, u as createChannelReplyPipeline, v as loadOutboundMediaFromUrl, w as registerWebhookTargetWithPluginRoute, x as readNumberParam, y as missingTargetError } from "./runtime-api-wkIdfwqY.js";
2
- export { DEFAULT_ACCOUNT_ID, GROUP_POLICY_BLOCKED_LABEL, GoogleChatConfigSchema, PAIRING_APPROVED_MESSAGE, buildChannelConfigSchema, chunkTextForOutbound, createAccountStatusSink, createActionGate, createChannelPairingController, createChannelReplyPipeline, createWebhookInFlightLimiter, evaluateGroupRouteAccessForPolicy, extractToolSend, fetchRemoteMedia, fetchWithSsrFGuard, isDangerousNameMatchingEnabled, jsonResult, loadOutboundMediaFromUrl, missingTargetError, readJsonWebhookBodyOrReject, readNumberParam, readReactionParams, readStringParam, registerWebhookTargetWithPluginRoute, resolveAllowlistProviderRuntimeGroupPolicy, resolveChannelMediaMaxBytes, resolveDefaultGroupPolicy, resolveDmGroupAccessWithLists, resolveInboundMentionDecision, resolveInboundRouteEnvelopeBuilderWithRuntime, resolveSenderScopedGroupPolicy, resolveWebhookPath, resolveWebhookTargetWithAuthOrReject, runPassiveAccountLifecycle, setGoogleChatRuntime, warnMissingProviderGroupPolicyFallbackOnce, withResolvedWebhookRequestPipeline };
1
+ import { A as resolveWebhookTargetWithAuthOrReject, C as registerWebhookTargetWithPluginRoute, D as resolveInboundMentionDecision, E as resolveDefaultGroupPolicy, F as setGoogleChatRuntime, M as warnMissingProviderGroupPolicyFallbackOnce, N as withResolvedWebhookRequestPipeline, O as resolveInboundRouteEnvelopeBuilderWithRuntime, S as readStringParam, T as resolveChannelMediaMaxBytes, _ as loadOutboundMediaFromUrl, a as buildChannelConfigSchema, b as readNumberParam, c as createActionGate, d as createWebhookInFlightLimiter, f as extractToolSend, g as jsonResult, h as isDangerousNameMatchingEnabled, i as PAIRING_APPROVED_MESSAGE, j as runPassiveAccountLifecycle, k as resolveWebhookPath, l as createChannelMessageReplyPipeline, m as fetchWithSsrFGuard, n as GROUP_POLICY_BLOCKED_LABEL, o as chunkTextForOutbound, p as fetchRemoteMedia, r as GoogleChatConfigSchema, s as createAccountStatusSink, t as DEFAULT_ACCOUNT_ID, u as createChannelPairingController, v as missingTargetError, w as resolveAllowlistProviderRuntimeGroupPolicy, x as readReactionParams, y as readJsonWebhookBodyOrReject } from "./runtime-api-DMEzhesS.js";
2
+ export { DEFAULT_ACCOUNT_ID, GROUP_POLICY_BLOCKED_LABEL, GoogleChatConfigSchema, PAIRING_APPROVED_MESSAGE, buildChannelConfigSchema, chunkTextForOutbound, createAccountStatusSink, createActionGate, createChannelMessageReplyPipeline, createChannelPairingController, createWebhookInFlightLimiter, extractToolSend, fetchRemoteMedia, fetchWithSsrFGuard, isDangerousNameMatchingEnabled, jsonResult, loadOutboundMediaFromUrl, missingTargetError, readJsonWebhookBodyOrReject, readNumberParam, readReactionParams, readStringParam, registerWebhookTargetWithPluginRoute, resolveAllowlistProviderRuntimeGroupPolicy, resolveChannelMediaMaxBytes, resolveDefaultGroupPolicy, resolveInboundMentionDecision, resolveInboundRouteEnvelopeBuilderWithRuntime, resolveWebhookPath, resolveWebhookTargetWithAuthOrReject, runPassiveAccountLifecycle, setGoogleChatRuntime, warnMissingProviderGroupPolicyFallbackOnce, withResolvedWebhookRequestPipeline };
@@ -1,2 +1,2 @@
1
- import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-DtQ_IO7J.js";
1
+ import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-DLAG2_NI.js";
2
2
  export { channelSecrets, collectRuntimeConfigAssignments, secretTargetRegistryEntries };
@@ -1,4 +1,5 @@
1
- import { a as resolveDefaultGoogleChatAccountId, i as listGoogleChatAccountIds, n as googlechatSetupAdapter, o as resolveGoogleChatAccount, s as resolveGoogleChatConfigAccessorAccount, t as googlechatSetupWizard } from "./setup-surface-CofP-Gg9.js";
1
+ import { a as resolveGoogleChatConfigAccessorAccount, i as resolveGoogleChatAccount, n as listGoogleChatAccountIds, r as resolveDefaultGoogleChatAccountId } from "./accounts-BbM9zX1S.js";
2
+ import { n as googlechatSetupAdapter, t as googlechatSetupWizard } from "./setup-surface-S4ArLnR8.js";
2
3
  import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
3
4
  import { formatNormalizedAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
4
5
  import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
@@ -1,99 +1,7 @@
1
- import { safeParseJsonWithSchema, safeParseWithSchema } from "openclaw/plugin-sdk/extension-shared";
2
- import { DEFAULT_ACCOUNT_ID, createAccountListHelpers, normalizeAccountId, resolveAccountEntry, resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-resolution";
3
- import { isSecretRef } from "openclaw/plugin-sdk/secret-input";
1
+ import { i as resolveGoogleChatAccount, r as resolveDefaultGoogleChatAccountId } from "./accounts-BbM9zX1S.js";
4
2
  import { normalizeOptionalString, normalizeStringifiedOptionalString } from "openclaw/plugin-sdk/text-runtime";
5
- import { z } from "zod";
6
3
  import { createPatchedAccountSetupAdapter, createSetupInputPresenceValidator } from "openclaw/plugin-sdk/setup-runtime";
7
- import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, addWildcardAllowFrom, applySetupAccountConfigPatch, createPromptParsedAllowFromForAccount, createStandardChannelSetupStatus, formatDocsLink, mergeAllowFromEntries, migrateBaseNameToDefaultAccount, splitSetupEntries } from "openclaw/plugin-sdk/setup";
8
- //#region extensions/googlechat/src/accounts.ts
9
- const ENV_SERVICE_ACCOUNT$1 = "GOOGLE_CHAT_SERVICE_ACCOUNT";
10
- const ENV_SERVICE_ACCOUNT_FILE$1 = "GOOGLE_CHAT_SERVICE_ACCOUNT_FILE";
11
- const JsonRecordSchema = z.record(z.string(), z.unknown());
12
- const { listAccountIds: listGoogleChatAccountIds, resolveDefaultAccountId: resolveDefaultGoogleChatAccountId } = createAccountListHelpers("googlechat");
13
- function mergeGoogleChatAccountConfig(cfg, accountId) {
14
- const raw = cfg.channels?.["googlechat"] ?? {};
15
- const base = resolveMergedAccountConfig({
16
- channelConfig: raw,
17
- accounts: raw.accounts,
18
- accountId,
19
- omitKeys: ["defaultAccount"]
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
- return {
25
- ...defaultAccountShared,
26
- ...base
27
- };
28
- }
29
- function resolveGoogleChatConfigAccessorAccount(params) {
30
- const accountId = normalizeAccountId(params.accountId ?? params.cfg.channels?.googlechat?.defaultAccount);
31
- return { config: mergeGoogleChatAccountConfig(params.cfg, accountId) };
32
- }
33
- function parseServiceAccount(value) {
34
- if (isSecretRef(value)) return null;
35
- if (typeof value === "string") {
36
- const trimmed = value.trim();
37
- if (!trimmed) return null;
38
- return safeParseJsonWithSchema(JsonRecordSchema, trimmed);
39
- }
40
- return safeParseWithSchema(JsonRecordSchema, value);
41
- }
42
- function resolveCredentialsFromConfig(params) {
43
- const { account, accountId } = params;
44
- const inline = parseServiceAccount(account.serviceAccount);
45
- if (inline) return {
46
- credentials: inline,
47
- source: "inline"
48
- };
49
- 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.`);
50
- 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.`);
51
- const file = normalizeOptionalString(account.serviceAccountFile);
52
- if (file) return {
53
- credentialsFile: file,
54
- source: "file"
55
- };
56
- if (accountId === DEFAULT_ACCOUNT_ID) {
57
- const envJson = process.env[ENV_SERVICE_ACCOUNT$1];
58
- const envInline = parseServiceAccount(envJson);
59
- if (envInline) return {
60
- credentials: envInline,
61
- source: "env"
62
- };
63
- const envFile = normalizeOptionalString(process.env[ENV_SERVICE_ACCOUNT_FILE$1]);
64
- if (envFile) return {
65
- credentialsFile: envFile,
66
- source: "env"
67
- };
68
- }
69
- return { source: "none" };
70
- }
71
- function resolveGoogleChatAccount(params) {
72
- const accountId = normalizeAccountId(params.accountId ?? params.cfg.channels?.["googlechat"]?.defaultAccount);
73
- const baseEnabled = params.cfg.channels?.["googlechat"]?.enabled !== false;
74
- const merged = mergeGoogleChatAccountConfig(params.cfg, accountId);
75
- const accountEnabled = merged.enabled !== false;
76
- const enabled = baseEnabled && accountEnabled;
77
- const credentials = resolveCredentialsFromConfig({
78
- accountId,
79
- account: merged
80
- });
81
- return {
82
- accountId,
83
- name: normalizeOptionalString(merged.name),
84
- enabled,
85
- config: merged,
86
- credentialSource: credentials.source,
87
- credentials: credentials.credentials,
88
- credentialsFile: credentials.credentialsFile
89
- };
90
- }
91
- function listEnabledGoogleChatAccounts(cfg) {
92
- return listGoogleChatAccountIds(cfg).map((accountId) => resolveGoogleChatAccount({
93
- cfg,
94
- accountId
95
- })).filter((account) => account.enabled);
96
- }
4
+ import { DEFAULT_ACCOUNT_ID, addWildcardAllowFrom, applySetupAccountConfigPatch, createPromptParsedAllowFromForAccount, createStandardChannelSetupStatus, formatDocsLink, mergeAllowFromEntries, migrateBaseNameToDefaultAccount, splitSetupEntries } from "openclaw/plugin-sdk/setup";
97
5
  const googlechatSetupAdapter = createPatchedAccountSetupAdapter({
98
6
  channelKey: "googlechat",
99
7
  validateInput: createSetupInputPresenceValidator({
@@ -130,7 +38,7 @@ const googlechatDmPolicy = {
130
38
  channel,
131
39
  policyKey: "channels.googlechat.dm.policy",
132
40
  allowFromKey: "channels.googlechat.dm.allowFrom",
133
- resolveConfigKeys: (cfg, accountId) => (accountId ?? resolveDefaultGoogleChatAccountId(cfg)) !== DEFAULT_ACCOUNT_ID$1 ? {
41
+ resolveConfigKeys: (cfg, accountId) => (accountId ?? resolveDefaultGoogleChatAccountId(cfg)) !== DEFAULT_ACCOUNT_ID ? {
134
42
  policyKey: `channels.googlechat.accounts.${accountId ?? resolveDefaultGoogleChatAccountId(cfg)}.dm.policy`,
135
43
  allowFromKey: `channels.googlechat.accounts.${accountId ?? resolveDefaultGoogleChatAccountId(cfg)}.dm.allowFrom`
136
44
  } : {
@@ -221,7 +129,7 @@ const googlechatSetupWizard = {
221
129
  ]
222
130
  },
223
131
  prepare: async ({ cfg, accountId, credentialValues, prompter }) => {
224
- if (accountId === DEFAULT_ACCOUNT_ID$1 && (Boolean(process.env[ENV_SERVICE_ACCOUNT]) || Boolean(process.env[ENV_SERVICE_ACCOUNT_FILE]))) {
132
+ if (accountId === DEFAULT_ACCOUNT_ID && (Boolean(process.env[ENV_SERVICE_ACCOUNT]) || Boolean(process.env[ENV_SERVICE_ACCOUNT_FILE]))) {
225
133
  if (await prompter.confirm({
226
134
  message: "Use GOOGLE_CHAT_SERVICE_ACCOUNT env vars?",
227
135
  initialValue: true
@@ -306,4 +214,4 @@ const googlechatSetupWizard = {
306
214
  dmPolicy: googlechatDmPolicy
307
215
  };
308
216
  //#endregion
309
- export { resolveDefaultGoogleChatAccountId as a, listGoogleChatAccountIds as i, googlechatSetupAdapter as n, resolveGoogleChatAccount as o, listEnabledGoogleChatAccounts as r, resolveGoogleChatConfigAccessorAccount as s, googlechatSetupWizard as t };
217
+ export { googlechatSetupAdapter as n, googlechatSetupWizard as t };
@@ -0,0 +1,43 @@
1
+ import { a as findGoogleChatDirectMessage } from "./api-AErsImS_.js";
2
+ import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-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 };
package/dist/test-api.js CHANGED
@@ -1,3 +1,3 @@
1
- import { R as setGoogleChatRuntime } from "./runtime-api-wkIdfwqY.js";
2
- import { t as googlechatPlugin } from "./channel-CHniJUSZ.js";
1
+ import { F as setGoogleChatRuntime } from "./runtime-api-DMEzhesS.js";
2
+ import { t as googlechatPlugin } from "./channel-9lvRWX6T.js";
3
3
  export { googlechatPlugin, setGoogleChatRuntime };