@openclaw/googlechat 2026.5.2-beta.2 → 2026.5.3-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.
Files changed (75) hide show
  1. package/dist/api-C67jv0ow.js +627 -0
  2. package/dist/api.js +3 -0
  3. package/dist/channel-DE2hroMn.js +682 -0
  4. package/dist/channel-config-api.js +5 -0
  5. package/dist/channel-plugin-api.js +2 -0
  6. package/dist/channel.runtime-CoSLc-4R.js +920 -0
  7. package/dist/contract-api.js +3 -0
  8. package/dist/doctor-contract-CG1sLToP.js +151 -0
  9. package/dist/doctor-contract-api.js +2 -0
  10. package/dist/index.js +22 -0
  11. package/dist/runtime-api-wkIdfwqY.js +30 -0
  12. package/dist/runtime-api.js +2 -0
  13. package/dist/secret-contract-DtQ_IO7J.js +99 -0
  14. package/dist/secret-contract-api.js +2 -0
  15. package/dist/setup-entry.js +15 -0
  16. package/dist/setup-plugin-api.js +75 -0
  17. package/dist/setup-surface-CofP-Gg9.js +309 -0
  18. package/dist/test-api.js +3 -0
  19. package/package.json +14 -6
  20. package/api.ts +0 -3
  21. package/channel-config-api.ts +0 -1
  22. package/channel-plugin-api.ts +0 -1
  23. package/contract-api.ts +0 -5
  24. package/doctor-contract-api.ts +0 -1
  25. package/index.ts +0 -20
  26. package/runtime-api.ts +0 -60
  27. package/secret-contract-api.ts +0 -5
  28. package/setup-entry.ts +0 -13
  29. package/setup-plugin-api.ts +0 -3
  30. package/src/accounts.ts +0 -169
  31. package/src/actions.test.ts +0 -265
  32. package/src/actions.ts +0 -227
  33. package/src/api.ts +0 -322
  34. package/src/approval-auth.test.ts +0 -24
  35. package/src/approval-auth.ts +0 -32
  36. package/src/auth.ts +0 -209
  37. package/src/channel-config.test.ts +0 -39
  38. package/src/channel.adapters.ts +0 -293
  39. package/src/channel.deps.runtime.ts +0 -28
  40. package/src/channel.runtime.ts +0 -17
  41. package/src/channel.setup.ts +0 -98
  42. package/src/channel.test.ts +0 -695
  43. package/src/channel.ts +0 -256
  44. package/src/config-schema.test.ts +0 -16
  45. package/src/config-schema.ts +0 -3
  46. package/src/doctor-contract.test.ts +0 -75
  47. package/src/doctor-contract.ts +0 -182
  48. package/src/doctor.ts +0 -57
  49. package/src/gateway.ts +0 -63
  50. package/src/google-auth.runtime.test.ts +0 -462
  51. package/src/google-auth.runtime.ts +0 -539
  52. package/src/group-policy.ts +0 -17
  53. package/src/monitor-access.test.ts +0 -443
  54. package/src/monitor-access.ts +0 -405
  55. package/src/monitor-reply-delivery.ts +0 -156
  56. package/src/monitor-routing.ts +0 -55
  57. package/src/monitor-types.ts +0 -33
  58. package/src/monitor-webhook.test.ts +0 -446
  59. package/src/monitor-webhook.ts +0 -285
  60. package/src/monitor.reply-delivery.test.ts +0 -139
  61. package/src/monitor.ts +0 -428
  62. package/src/monitor.webhook-routing.test.ts +0 -252
  63. package/src/runtime.ts +0 -9
  64. package/src/secret-contract.test.ts +0 -60
  65. package/src/secret-contract.ts +0 -161
  66. package/src/sender-allow.ts +0 -46
  67. package/src/setup-core.ts +0 -40
  68. package/src/setup-surface.ts +0 -236
  69. package/src/setup.test.ts +0 -560
  70. package/src/targets.test.ts +0 -421
  71. package/src/targets.ts +0 -66
  72. package/src/types.config.ts +0 -3
  73. package/src/types.ts +0 -73
  74. package/test-api.ts +0 -2
  75. package/tsconfig.json +0 -16
@@ -0,0 +1,309 @@
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";
4
+ import { normalizeOptionalString, normalizeStringifiedOptionalString } from "openclaw/plugin-sdk/text-runtime";
5
+ import { z } from "zod";
6
+ 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
+ }
97
+ const googlechatSetupAdapter = createPatchedAccountSetupAdapter({
98
+ channelKey: "googlechat",
99
+ validateInput: createSetupInputPresenceValidator({
100
+ defaultAccountOnlyEnvError: "GOOGLE_CHAT_SERVICE_ACCOUNT env vars can only be used for the default account.",
101
+ whenNotUseEnv: [{
102
+ someOf: ["token", "tokenFile"],
103
+ message: "Google Chat requires --token (service account JSON) or --token-file."
104
+ }]
105
+ }),
106
+ buildPatch: (input) => {
107
+ const patch = input.useEnv ? {} : input.tokenFile ? { serviceAccountFile: input.tokenFile } : input.token ? { serviceAccount: input.token } : {};
108
+ const audienceType = input.audienceType?.trim();
109
+ const audience = input.audience?.trim();
110
+ const webhookPath = input.webhookPath?.trim();
111
+ const webhookUrl = input.webhookUrl?.trim();
112
+ return {
113
+ ...patch,
114
+ ...audienceType ? { audienceType } : {},
115
+ ...audience ? { audience } : {},
116
+ ...webhookPath ? { webhookPath } : {},
117
+ ...webhookUrl ? { webhookUrl } : {}
118
+ };
119
+ }
120
+ });
121
+ //#endregion
122
+ //#region extensions/googlechat/src/setup-surface.ts
123
+ const channel = "googlechat";
124
+ const ENV_SERVICE_ACCOUNT = "GOOGLE_CHAT_SERVICE_ACCOUNT";
125
+ const ENV_SERVICE_ACCOUNT_FILE = "GOOGLE_CHAT_SERVICE_ACCOUNT_FILE";
126
+ const USE_ENV_FLAG = "__googlechatUseEnv";
127
+ const AUTH_METHOD_FLAG = "__googlechatAuthMethod";
128
+ const googlechatDmPolicy = {
129
+ label: "Google Chat",
130
+ channel,
131
+ policyKey: "channels.googlechat.dm.policy",
132
+ allowFromKey: "channels.googlechat.dm.allowFrom",
133
+ resolveConfigKeys: (cfg, accountId) => (accountId ?? resolveDefaultGoogleChatAccountId(cfg)) !== DEFAULT_ACCOUNT_ID$1 ? {
134
+ policyKey: `channels.googlechat.accounts.${accountId ?? resolveDefaultGoogleChatAccountId(cfg)}.dm.policy`,
135
+ allowFromKey: `channels.googlechat.accounts.${accountId ?? resolveDefaultGoogleChatAccountId(cfg)}.dm.allowFrom`
136
+ } : {
137
+ policyKey: "channels.googlechat.dm.policy",
138
+ allowFromKey: "channels.googlechat.dm.allowFrom"
139
+ },
140
+ getCurrent: (cfg, accountId) => resolveGoogleChatAccount({
141
+ cfg,
142
+ accountId: accountId ?? resolveDefaultGoogleChatAccountId(cfg)
143
+ }).config.dm?.policy ?? "pairing",
144
+ setPolicy: (cfg, policy, accountId) => {
145
+ const resolvedAccountId = accountId ?? resolveDefaultGoogleChatAccountId(cfg);
146
+ const currentDm = resolveGoogleChatAccount({
147
+ cfg,
148
+ accountId: resolvedAccountId
149
+ }).config.dm;
150
+ return applySetupAccountConfigPatch({
151
+ cfg,
152
+ channelKey: channel,
153
+ accountId: resolvedAccountId,
154
+ patch: { dm: {
155
+ ...currentDm,
156
+ policy,
157
+ ...policy === "open" ? { allowFrom: addWildcardAllowFrom(currentDm?.allowFrom) } : {}
158
+ } }
159
+ });
160
+ },
161
+ promptAllowFrom: createPromptParsedAllowFromForAccount({
162
+ defaultAccountId: resolveDefaultGoogleChatAccountId,
163
+ message: "Google Chat allowFrom (users/<id> or raw email; avoid users/<email>)",
164
+ placeholder: "users/123456789, name@example.com",
165
+ parseEntries: (raw) => ({ entries: mergeAllowFromEntries(void 0, splitSetupEntries(raw)) }),
166
+ getExistingAllowFrom: ({ cfg, accountId }) => resolveGoogleChatAccount({
167
+ cfg,
168
+ accountId
169
+ }).config.dm?.allowFrom ?? [],
170
+ applyAllowFrom: ({ cfg, accountId, allowFrom }) => applySetupAccountConfigPatch({
171
+ cfg,
172
+ channelKey: channel,
173
+ accountId,
174
+ patch: { dm: {
175
+ ...resolveGoogleChatAccount({
176
+ cfg,
177
+ accountId
178
+ }).config.dm,
179
+ allowFrom
180
+ } }
181
+ })
182
+ })
183
+ };
184
+ function createServiceAccountTextInput(params) {
185
+ return {
186
+ inputKey: params.inputKey,
187
+ message: params.message,
188
+ placeholder: params.placeholder,
189
+ shouldPrompt: ({ credentialValues }) => credentialValues[USE_ENV_FLAG] !== "1" && credentialValues[AUTH_METHOD_FLAG] === params.authMethod,
190
+ validate: ({ value }) => normalizeStringifiedOptionalString(value) ? void 0 : "Required",
191
+ normalizeValue: ({ value }) => normalizeStringifiedOptionalString(value) ?? "",
192
+ applySet: async ({ cfg, accountId, value }) => applySetupAccountConfigPatch({
193
+ cfg,
194
+ channelKey: channel,
195
+ accountId,
196
+ patch: { [params.patchKey]: value }
197
+ })
198
+ };
199
+ }
200
+ const googlechatSetupWizard = {
201
+ channel,
202
+ status: createStandardChannelSetupStatus({
203
+ channelLabel: "Google Chat",
204
+ configuredLabel: "configured",
205
+ unconfiguredLabel: "needs service account",
206
+ configuredHint: "configured",
207
+ unconfiguredHint: "needs auth",
208
+ includeStatusLine: true,
209
+ resolveConfigured: ({ cfg, accountId }) => resolveGoogleChatAccount({
210
+ cfg,
211
+ accountId
212
+ }).credentialSource !== "none"
213
+ }),
214
+ introNote: {
215
+ title: "Google Chat setup",
216
+ lines: [
217
+ "Google Chat apps use service-account auth and an HTTPS webhook.",
218
+ "Set the Chat API scopes in your service account and configure the Chat app URL.",
219
+ "Webhook verification requires audience type + audience value.",
220
+ `Docs: ${formatDocsLink("/channels/googlechat", "googlechat")}`
221
+ ]
222
+ },
223
+ 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]))) {
225
+ if (await prompter.confirm({
226
+ message: "Use GOOGLE_CHAT_SERVICE_ACCOUNT env vars?",
227
+ initialValue: true
228
+ })) return {
229
+ cfg: applySetupAccountConfigPatch({
230
+ cfg,
231
+ channelKey: channel,
232
+ accountId,
233
+ patch: {}
234
+ }),
235
+ credentialValues: {
236
+ ...credentialValues,
237
+ [USE_ENV_FLAG]: "1"
238
+ }
239
+ };
240
+ }
241
+ const method = await prompter.select({
242
+ message: "Google Chat auth method",
243
+ options: [{
244
+ value: "file",
245
+ label: "Service account JSON file"
246
+ }, {
247
+ value: "inline",
248
+ label: "Paste service account JSON"
249
+ }],
250
+ initialValue: "file"
251
+ });
252
+ return { credentialValues: {
253
+ ...credentialValues,
254
+ [USE_ENV_FLAG]: "0",
255
+ [AUTH_METHOD_FLAG]: method
256
+ } };
257
+ },
258
+ credentials: [],
259
+ textInputs: [createServiceAccountTextInput({
260
+ inputKey: "tokenFile",
261
+ message: "Service account JSON path",
262
+ placeholder: "/path/to/service-account.json",
263
+ authMethod: "file",
264
+ patchKey: "serviceAccountFile"
265
+ }), createServiceAccountTextInput({
266
+ inputKey: "token",
267
+ message: "Service account JSON (single line)",
268
+ placeholder: "{\"type\":\"service_account\", ... }",
269
+ authMethod: "inline",
270
+ patchKey: "serviceAccount"
271
+ })],
272
+ finalize: async ({ cfg, accountId, prompter }) => {
273
+ const account = resolveGoogleChatAccount({
274
+ cfg,
275
+ accountId
276
+ });
277
+ const audienceType = await prompter.select({
278
+ message: "Webhook audience type",
279
+ options: [{
280
+ value: "app-url",
281
+ label: "App URL (recommended)"
282
+ }, {
283
+ value: "project-number",
284
+ label: "Project number"
285
+ }],
286
+ initialValue: account.config.audienceType === "project-number" ? "project-number" : "app-url"
287
+ });
288
+ return { cfg: migrateBaseNameToDefaultAccount({
289
+ cfg: applySetupAccountConfigPatch({
290
+ cfg,
291
+ channelKey: channel,
292
+ accountId,
293
+ patch: {
294
+ audienceType,
295
+ audience: normalizeOptionalString(await prompter.text({
296
+ message: audienceType === "project-number" ? "Project number" : "App URL",
297
+ placeholder: audienceType === "project-number" ? "1234567890" : "https://your.host/googlechat",
298
+ initialValue: account.config.audience || void 0,
299
+ validate: (value) => normalizeStringifiedOptionalString(value) ? void 0 : "Required"
300
+ })) ?? ""
301
+ }
302
+ }),
303
+ channelKey: channel
304
+ }) };
305
+ },
306
+ dmPolicy: googlechatDmPolicy
307
+ };
308
+ //#endregion
309
+ export { resolveDefaultGoogleChatAccountId as a, listGoogleChatAccountIds as i, googlechatSetupAdapter as n, resolveGoogleChatAccount as o, listEnabledGoogleChatAccounts as r, resolveGoogleChatConfigAccessorAccount as s, googlechatSetupWizard as t };
@@ -0,0 +1,3 @@
1
+ import { R as setGoogleChatRuntime } from "./runtime-api-wkIdfwqY.js";
2
+ import { t as googlechatPlugin } from "./channel-DE2hroMn.js";
3
+ export { googlechatPlugin, setGoogleChatRuntime };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/googlechat",
3
- "version": "2026.5.2-beta.2",
3
+ "version": "2026.5.3-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.2-beta.2"
20
+ "openclaw": ">=2026.5.3-beta.2"
21
21
  },
22
22
  "peerDependenciesMeta": {
23
23
  "openclaw": {
@@ -75,14 +75,22 @@
75
75
  "minHostVersion": ">=2026.4.10"
76
76
  },
77
77
  "compat": {
78
- "pluginApi": ">=2026.5.2-beta.2"
78
+ "pluginApi": ">=2026.5.3-beta.2"
79
79
  },
80
80
  "build": {
81
- "openclawVersion": "2026.5.2-beta.2"
81
+ "openclawVersion": "2026.5.3-beta.2"
82
82
  },
83
83
  "release": {
84
84
  "publishToClawHub": true,
85
85
  "publishToNpm": true
86
- }
87
- }
86
+ },
87
+ "runtimeExtensions": [
88
+ "./dist/index.js"
89
+ ],
90
+ "runtimeSetupEntry": "./dist/setup-entry.js"
91
+ },
92
+ "files": [
93
+ "dist/**",
94
+ "openclaw.plugin.json"
95
+ ]
88
96
  }
package/api.ts DELETED
@@ -1,3 +0,0 @@
1
- export { googlechatPlugin } from "./src/channel.js";
2
- export { googlechatSetupAdapter } from "./src/setup-core.js";
3
- export { googlechatSetupWizard } from "./src/setup-surface.js";
@@ -1 +0,0 @@
1
- export { GoogleChatChannelConfigSchema } from "./src/config-schema.js";
@@ -1 +0,0 @@
1
- export { googlechatPlugin } from "./src/channel.js";
package/contract-api.ts DELETED
@@ -1,5 +0,0 @@
1
- export {
2
- collectRuntimeConfigAssignments,
3
- secretTargetRegistryEntries,
4
- } from "./src/secret-contract.js";
5
- export { normalizeCompatibilityConfig, legacyConfigRules } from "./src/doctor-contract.js";
@@ -1 +0,0 @@
1
- export { normalizeCompatibilityConfig, legacyConfigRules } from "./src/doctor-contract.js";
package/index.ts DELETED
@@ -1,20 +0,0 @@
1
- import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
2
-
3
- export default defineBundledChannelEntry({
4
- id: "googlechat",
5
- name: "Google Chat",
6
- description: "OpenClaw Google Chat channel plugin",
7
- importMetaUrl: import.meta.url,
8
- plugin: {
9
- specifier: "./channel-plugin-api.js",
10
- exportName: "googlechatPlugin",
11
- },
12
- secrets: {
13
- specifier: "./secret-contract-api.js",
14
- exportName: "channelSecrets",
15
- },
16
- runtime: {
17
- specifier: "./runtime-api.js",
18
- exportName: "setGoogleChatRuntime",
19
- },
20
- });
package/runtime-api.ts DELETED
@@ -1,60 +0,0 @@
1
- // Private runtime barrel for the bundled Google Chat extension.
2
- // Keep this barrel thin and avoid broad plugin-sdk surfaces during bootstrap.
3
-
4
- export { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
5
- export {
6
- createActionGate,
7
- jsonResult,
8
- readNumberParam,
9
- readReactionParams,
10
- readStringParam,
11
- } from "openclaw/plugin-sdk/channel-actions";
12
- export { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-primitives";
13
- export type {
14
- ChannelMessageActionAdapter,
15
- ChannelMessageActionName,
16
- ChannelStatusIssue,
17
- } from "openclaw/plugin-sdk/channel-contract";
18
- export { missingTargetError } from "openclaw/plugin-sdk/channel-feedback";
19
- export {
20
- createAccountStatusSink,
21
- runPassiveAccountLifecycle,
22
- } from "openclaw/plugin-sdk/channel-lifecycle";
23
- export { createChannelPairingController } from "openclaw/plugin-sdk/channel-pairing";
24
- export { createChannelReplyPipeline } from "openclaw/plugin-sdk/channel-reply-pipeline";
25
- export {
26
- evaluateGroupRouteAccessForPolicy,
27
- resolveDmGroupAccessWithLists,
28
- resolveSenderScopedGroupPolicy,
29
- } from "openclaw/plugin-sdk/channel-policy";
30
- export { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
31
- export { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
32
- export type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
33
- export { GoogleChatConfigSchema } from "openclaw/plugin-sdk/bundled-channel-config-schema";
34
- export {
35
- GROUP_POLICY_BLOCKED_LABEL,
36
- resolveAllowlistProviderRuntimeGroupPolicy,
37
- resolveDefaultGroupPolicy,
38
- warnMissingProviderGroupPolicyFallbackOnce,
39
- } from "openclaw/plugin-sdk/runtime-group-policy";
40
- export { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-name-runtime";
41
- export { fetchRemoteMedia, resolveChannelMediaMaxBytes } from "openclaw/plugin-sdk/media-runtime";
42
- export { loadOutboundMediaFromUrl } from "openclaw/plugin-sdk/outbound-media";
43
- export type { PluginRuntime } from "openclaw/plugin-sdk/runtime-store";
44
- export { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
45
- export type { GoogleChatAccountConfig, GoogleChatConfig } from "openclaw/plugin-sdk/config-types";
46
- export { extractToolSend } from "openclaw/plugin-sdk/tool-send";
47
- export { resolveInboundMentionDecision } from "openclaw/plugin-sdk/channel-inbound";
48
- export { resolveInboundRouteEnvelopeBuilderWithRuntime } from "openclaw/plugin-sdk/inbound-envelope";
49
- export { resolveWebhookPath } from "openclaw/plugin-sdk/webhook-path";
50
- export {
51
- registerWebhookTargetWithPluginRoute,
52
- resolveWebhookTargetWithAuthOrReject,
53
- withResolvedWebhookRequestPipeline,
54
- } from "openclaw/plugin-sdk/webhook-targets";
55
- export {
56
- createWebhookInFlightLimiter,
57
- readJsonWebhookBodyOrReject,
58
- type WebhookInFlightLimiter,
59
- } from "openclaw/plugin-sdk/webhook-request-guards";
60
- export { setGoogleChatRuntime } from "./src/runtime.js";
@@ -1,5 +0,0 @@
1
- export {
2
- channelSecrets,
3
- collectRuntimeConfigAssignments,
4
- secretTargetRegistryEntries,
5
- } from "./src/secret-contract.js";
package/setup-entry.ts DELETED
@@ -1,13 +0,0 @@
1
- import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
2
-
3
- export default defineBundledChannelSetupEntry({
4
- importMetaUrl: import.meta.url,
5
- plugin: {
6
- specifier: "./setup-plugin-api.js",
7
- exportName: "googlechatSetupPlugin",
8
- },
9
- secrets: {
10
- specifier: "./secret-contract-api.js",
11
- exportName: "channelSecrets",
12
- },
13
- });
@@ -1,3 +0,0 @@
1
- // Keep bundled setup entry imports narrow so setup loads do not pull the
2
- // broader Google Chat runtime plugin surface.
3
- export { googlechatSetupPlugin } from "./src/channel.setup.js";
package/src/accounts.ts DELETED
@@ -1,169 +0,0 @@
1
- import {
2
- createAccountListHelpers,
3
- DEFAULT_ACCOUNT_ID,
4
- normalizeAccountId,
5
- type OpenClawConfig,
6
- resolveAccountEntry,
7
- resolveMergedAccountConfig,
8
- } from "openclaw/plugin-sdk/account-resolution";
9
- import { safeParseJsonWithSchema, safeParseWithSchema } from "openclaw/plugin-sdk/extension-shared";
10
- import { isSecretRef } from "openclaw/plugin-sdk/secret-input";
11
- import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
12
- import { z } from "zod";
13
- import type { GoogleChatAccountConfig } from "./types.config.js";
14
-
15
- type GoogleChatCredentialSource = "file" | "inline" | "env" | "none";
16
-
17
- export type ResolvedGoogleChatAccount = {
18
- accountId: string;
19
- name?: string;
20
- enabled: boolean;
21
- config: GoogleChatAccountConfig;
22
- credentialSource: GoogleChatCredentialSource;
23
- credentials?: Record<string, unknown>;
24
- credentialsFile?: string;
25
- };
26
-
27
- export type GoogleChatConfigAccessorAccount = {
28
- config: GoogleChatAccountConfig;
29
- };
30
-
31
- const ENV_SERVICE_ACCOUNT = "GOOGLE_CHAT_SERVICE_ACCOUNT";
32
- const ENV_SERVICE_ACCOUNT_FILE = "GOOGLE_CHAT_SERVICE_ACCOUNT_FILE";
33
- const JsonRecordSchema = z.record(z.string(), z.unknown());
34
-
35
- const {
36
- listAccountIds: listGoogleChatAccountIds,
37
- resolveDefaultAccountId: resolveDefaultGoogleChatAccountId,
38
- } = createAccountListHelpers("googlechat");
39
- export { listGoogleChatAccountIds, resolveDefaultGoogleChatAccountId };
40
-
41
- function mergeGoogleChatAccountConfig(
42
- cfg: OpenClawConfig,
43
- accountId: string,
44
- ): GoogleChatAccountConfig {
45
- const raw = cfg.channels?.["googlechat"] ?? {};
46
- const base = resolveMergedAccountConfig<GoogleChatAccountConfig>({
47
- channelConfig: raw as GoogleChatAccountConfig,
48
- accounts: raw.accounts as Record<string, Partial<GoogleChatAccountConfig>> | undefined,
49
- accountId,
50
- omitKeys: ["defaultAccount"],
51
- });
52
- const defaultAccountConfig = resolveAccountEntry(raw.accounts, DEFAULT_ACCOUNT_ID) ?? {};
53
- if (accountId === DEFAULT_ACCOUNT_ID) {
54
- return base;
55
- }
56
- const {
57
- enabled: _ignoredEnabled,
58
- dangerouslyAllowNameMatching: _ignoredDangerouslyAllowNameMatching,
59
- serviceAccount: _ignoredServiceAccount,
60
- serviceAccountRef: _ignoredServiceAccountRef,
61
- serviceAccountFile: _ignoredServiceAccountFile,
62
- ...defaultAccountShared
63
- } = defaultAccountConfig;
64
- // In multi-account setups, allow accounts.default to provide shared defaults
65
- // (for example webhook/audience fields) while preserving top-level and account overrides.
66
- return { ...defaultAccountShared, ...base } as GoogleChatAccountConfig;
67
- }
68
-
69
- export function resolveGoogleChatConfigAccessorAccount(params: {
70
- cfg: OpenClawConfig;
71
- accountId?: string | null;
72
- }): GoogleChatConfigAccessorAccount {
73
- const accountId = normalizeAccountId(
74
- params.accountId ?? params.cfg.channels?.googlechat?.defaultAccount,
75
- );
76
- return { config: mergeGoogleChatAccountConfig(params.cfg, accountId) };
77
- }
78
-
79
- function parseServiceAccount(value: unknown): Record<string, unknown> | null {
80
- if (isSecretRef(value)) {
81
- return null;
82
- }
83
-
84
- if (typeof value === "string") {
85
- const trimmed = value.trim();
86
- if (!trimmed) {
87
- return null;
88
- }
89
- return safeParseJsonWithSchema(JsonRecordSchema, trimmed);
90
- }
91
-
92
- return safeParseWithSchema(JsonRecordSchema, value);
93
- }
94
-
95
- function resolveCredentialsFromConfig(params: {
96
- accountId: string;
97
- account: GoogleChatAccountConfig;
98
- }): {
99
- credentials?: Record<string, unknown>;
100
- credentialsFile?: string;
101
- source: GoogleChatCredentialSource;
102
- } {
103
- const { account, accountId } = params;
104
- const inline = parseServiceAccount(account.serviceAccount);
105
- if (inline) {
106
- return { credentials: inline, source: "inline" };
107
- }
108
-
109
- if (isSecretRef(account.serviceAccount)) {
110
- throw new Error(
111
- `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.`,
112
- );
113
- }
114
-
115
- if (isSecretRef(account.serviceAccountRef)) {
116
- throw new Error(
117
- `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.`,
118
- );
119
- }
120
-
121
- const file = normalizeOptionalString(account.serviceAccountFile);
122
- if (file) {
123
- return { credentialsFile: file, source: "file" };
124
- }
125
-
126
- if (accountId === DEFAULT_ACCOUNT_ID) {
127
- const envJson = process.env[ENV_SERVICE_ACCOUNT];
128
- const envInline = parseServiceAccount(envJson);
129
- if (envInline) {
130
- return { credentials: envInline, source: "env" };
131
- }
132
- const envFile = normalizeOptionalString(process.env[ENV_SERVICE_ACCOUNT_FILE]);
133
- if (envFile) {
134
- return { credentialsFile: envFile, source: "env" };
135
- }
136
- }
137
-
138
- return { source: "none" };
139
- }
140
-
141
- export function resolveGoogleChatAccount(params: {
142
- cfg: OpenClawConfig;
143
- accountId?: string | null;
144
- }): ResolvedGoogleChatAccount {
145
- const accountId = normalizeAccountId(
146
- params.accountId ?? params.cfg.channels?.["googlechat"]?.defaultAccount,
147
- );
148
- const baseEnabled = params.cfg.channels?.["googlechat"]?.enabled !== false;
149
- const merged = mergeGoogleChatAccountConfig(params.cfg, accountId);
150
- const accountEnabled = merged.enabled !== false;
151
- const enabled = baseEnabled && accountEnabled;
152
- const credentials = resolveCredentialsFromConfig({ accountId, account: merged });
153
-
154
- return {
155
- accountId,
156
- name: normalizeOptionalString(merged.name),
157
- enabled,
158
- config: merged,
159
- credentialSource: credentials.source,
160
- credentials: credentials.credentials,
161
- credentialsFile: credentials.credentialsFile,
162
- };
163
- }
164
-
165
- export function listEnabledGoogleChatAccounts(cfg: OpenClawConfig): ResolvedGoogleChatAccount[] {
166
- return listGoogleChatAccountIds(cfg)
167
- .map((accountId) => resolveGoogleChatAccount({ cfg, accountId }))
168
- .filter((account) => account.enabled);
169
- }