@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
package/src/channel.ts DELETED
@@ -1,256 +0,0 @@
1
- import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
2
- import { formatNormalizedAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
3
- import {
4
- adaptScopedAccountAccessor,
5
- createScopedChannelConfigAdapter,
6
- } from "openclaw/plugin-sdk/channel-config-helpers";
7
- import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
8
- import { buildPassiveProbedChannelStatusSummary } from "openclaw/plugin-sdk/extension-shared";
9
- import { createLazyRuntimeNamedExport } from "openclaw/plugin-sdk/lazy-runtime";
10
- import {
11
- createComputedAccountStatusAdapter,
12
- createDefaultChannelRuntimeState,
13
- } from "openclaw/plugin-sdk/status-helpers";
14
- import { googlechatMessageActions } from "./actions.js";
15
- import { googleChatApprovalAuth } from "./approval-auth.js";
16
- import {
17
- formatAllowFromEntry,
18
- googlechatDirectoryAdapter,
19
- googlechatGroupsAdapter,
20
- googlechatOutboundAdapter,
21
- googlechatPairingTextAdapter,
22
- googlechatSecurityAdapter,
23
- googlechatThreadingAdapter,
24
- } from "./channel.adapters.js";
25
- import {
26
- buildChannelConfigSchema,
27
- DEFAULT_ACCOUNT_ID,
28
- GoogleChatConfigSchema,
29
- isGoogleChatSpaceTarget,
30
- isGoogleChatUserTarget,
31
- listGoogleChatAccountIds,
32
- normalizeGoogleChatTarget,
33
- type GoogleChatConfigAccessorAccount,
34
- resolveGoogleChatConfigAccessorAccount,
35
- resolveDefaultGoogleChatAccountId,
36
- resolveGoogleChatAccount,
37
- type ChannelMessageActionAdapter,
38
- type ChannelStatusIssue,
39
- type ResolvedGoogleChatAccount,
40
- } from "./channel.deps.runtime.js";
41
- import {
42
- legacyConfigRules as GOOGLECHAT_LEGACY_CONFIG_RULES,
43
- normalizeCompatibilityConfig as normalizeGoogleChatCompatibilityConfig,
44
- } from "./doctor-contract.js";
45
- import { collectGoogleChatMutableAllowlistWarnings } from "./doctor.js";
46
- import { startGoogleChatGatewayAccount } from "./gateway.js";
47
- import { collectRuntimeConfigAssignments, secretTargetRegistryEntries } from "./secret-contract.js";
48
- import { googlechatSetupAdapter } from "./setup-core.js";
49
- import { googlechatSetupWizard } from "./setup-surface.js";
50
-
51
- const loadGoogleChatChannelRuntime = createLazyRuntimeNamedExport(
52
- () => import("./channel.runtime.js"),
53
- "googleChatChannelRuntime",
54
- );
55
-
56
- const meta = {
57
- id: "googlechat",
58
- label: "Google Chat",
59
- selectionLabel: "Google Chat (Chat API)",
60
- docsPath: "/channels/googlechat",
61
- docsLabel: "googlechat",
62
- blurb: "Google Workspace Chat app with HTTP webhook.",
63
- aliases: ["gchat", "google-chat"],
64
- order: 55,
65
- detailLabel: "Google Chat",
66
- systemImage: "message.badge",
67
- markdownCapable: true,
68
- };
69
-
70
- const googleChatConfigAdapter = createScopedChannelConfigAdapter<
71
- ResolvedGoogleChatAccount,
72
- GoogleChatConfigAccessorAccount
73
- >({
74
- sectionKey: "googlechat",
75
- listAccountIds: listGoogleChatAccountIds,
76
- resolveAccount: adaptScopedAccountAccessor(resolveGoogleChatAccount),
77
- resolveAccessorAccount: resolveGoogleChatConfigAccessorAccount,
78
- defaultAccountId: resolveDefaultGoogleChatAccountId,
79
- clearBaseFields: [
80
- "serviceAccount",
81
- "serviceAccountFile",
82
- "audienceType",
83
- "audience",
84
- "webhookPath",
85
- "webhookUrl",
86
- "botUser",
87
- "name",
88
- ],
89
- resolveAllowFrom: (account) => account.config.dm?.allowFrom,
90
- formatAllowFrom: (allowFrom) =>
91
- formatNormalizedAllowFromEntries({
92
- allowFrom,
93
- normalizeEntry: formatAllowFromEntry,
94
- }),
95
- resolveDefaultTo: (account) => account.config.defaultTo,
96
- });
97
-
98
- const googlechatActions: ChannelMessageActionAdapter = {
99
- describeMessageTool: (ctx) => googlechatMessageActions.describeMessageTool?.(ctx) ?? null,
100
- extractToolSend: (ctx) => googlechatMessageActions.extractToolSend?.(ctx) ?? null,
101
- handleAction: async (ctx) => {
102
- if (!googlechatMessageActions.handleAction) {
103
- throw new Error("Google Chat actions are not available.");
104
- }
105
- return await googlechatMessageActions.handleAction(ctx);
106
- },
107
- };
108
-
109
- export const googlechatPlugin = createChatChannelPlugin({
110
- base: {
111
- id: "googlechat",
112
- meta: { ...meta },
113
- setup: googlechatSetupAdapter,
114
- setupWizard: googlechatSetupWizard,
115
- capabilities: {
116
- chatTypes: ["direct", "group", "thread"],
117
- reactions: true,
118
- threads: true,
119
- media: true,
120
- nativeCommands: false,
121
- blockStreaming: true,
122
- },
123
- streaming: {
124
- blockStreamingCoalesceDefaults: { minChars: 1500, idleMs: 1000 },
125
- },
126
- reload: { configPrefixes: ["channels.googlechat"] },
127
- configSchema: buildChannelConfigSchema(GoogleChatConfigSchema),
128
- config: {
129
- ...googleChatConfigAdapter,
130
- isConfigured: (account) => account.credentialSource !== "none",
131
- describeAccount: (account) =>
132
- describeAccountSnapshot({
133
- account,
134
- configured: account.credentialSource !== "none",
135
- extra: {
136
- credentialSource: account.credentialSource,
137
- },
138
- }),
139
- },
140
- approvalCapability: googleChatApprovalAuth,
141
- secrets: {
142
- secretTargetRegistryEntries,
143
- collectRuntimeConfigAssignments,
144
- },
145
- groups: googlechatGroupsAdapter,
146
- messaging: {
147
- targetPrefixes: ["googlechat", "google-chat", "gchat"],
148
- normalizeTarget: normalizeGoogleChatTarget,
149
- targetResolver: {
150
- looksLikeId: (raw, normalized) => {
151
- const value = normalized ?? raw.trim();
152
- return isGoogleChatSpaceTarget(value) || isGoogleChatUserTarget(value);
153
- },
154
- hint: "<spaces/{space}|users/{user}>",
155
- },
156
- },
157
- directory: googlechatDirectoryAdapter,
158
- resolver: {
159
- resolveTargets: async ({ inputs, kind }) => {
160
- const resolved = inputs.map((input) => {
161
- const normalized = normalizeGoogleChatTarget(input);
162
- if (!normalized) {
163
- return { input, resolved: false, note: "empty target" };
164
- }
165
- if (kind === "user" && isGoogleChatUserTarget(normalized)) {
166
- return { input, resolved: true, id: normalized };
167
- }
168
- if (kind === "group" && isGoogleChatSpaceTarget(normalized)) {
169
- return { input, resolved: true, id: normalized };
170
- }
171
- return {
172
- input,
173
- resolved: false,
174
- note: "use spaces/{space} or users/{user}",
175
- };
176
- });
177
- return resolved;
178
- },
179
- },
180
- actions: googlechatActions,
181
- doctor: {
182
- dmAllowFromMode: "nestedOnly",
183
- groupModel: "route",
184
- groupAllowFromFallbackToAllowFrom: false,
185
- warnOnEmptyGroupSenderAllowlist: false,
186
- legacyConfigRules: GOOGLECHAT_LEGACY_CONFIG_RULES,
187
- normalizeCompatibilityConfig: normalizeGoogleChatCompatibilityConfig,
188
- collectMutableAllowlistWarnings: collectGoogleChatMutableAllowlistWarnings,
189
- },
190
- status: createComputedAccountStatusAdapter<ResolvedGoogleChatAccount>({
191
- defaultRuntime: createDefaultChannelRuntimeState(DEFAULT_ACCOUNT_ID),
192
- collectStatusIssues: (accounts): ChannelStatusIssue[] =>
193
- accounts.flatMap((entry) => {
194
- const accountId = entry.accountId ?? DEFAULT_ACCOUNT_ID;
195
- const enabled = entry.enabled !== false;
196
- const configured = entry.configured === true;
197
- if (!enabled || !configured) {
198
- return [];
199
- }
200
- const issues: ChannelStatusIssue[] = [];
201
- if (!entry.audience) {
202
- issues.push({
203
- channel: "googlechat",
204
- accountId,
205
- kind: "config",
206
- message: "Google Chat audience is missing (set channels.googlechat.audience).",
207
- fix: "Set channels.googlechat.audienceType and channels.googlechat.audience.",
208
- });
209
- }
210
- if (!entry.audienceType) {
211
- issues.push({
212
- channel: "googlechat",
213
- accountId,
214
- kind: "config",
215
- message: "Google Chat audienceType is missing (app-url or project-number).",
216
- fix: "Set channels.googlechat.audienceType and channels.googlechat.audience.",
217
- });
218
- }
219
- return issues;
220
- }),
221
- buildChannelSummary: ({ snapshot }) =>
222
- buildPassiveProbedChannelStatusSummary(snapshot, {
223
- credentialSource: snapshot.credentialSource ?? "none",
224
- audienceType: snapshot.audienceType ?? null,
225
- audience: snapshot.audience ?? null,
226
- webhookPath: snapshot.webhookPath ?? null,
227
- webhookUrl: snapshot.webhookUrl ?? null,
228
- }),
229
- probeAccount: async ({ account }) =>
230
- (await loadGoogleChatChannelRuntime()).probeGoogleChat(account),
231
- resolveAccountSnapshot: ({ account }) => ({
232
- accountId: account.accountId,
233
- name: account.name,
234
- enabled: account.enabled,
235
- configured: account.credentialSource !== "none",
236
- extra: {
237
- credentialSource: account.credentialSource,
238
- audienceType: account.config.audienceType,
239
- audience: account.config.audience,
240
- webhookPath: account.config.webhookPath,
241
- webhookUrl: account.config.webhookUrl,
242
- dmPolicy: account.config.dm?.policy ?? "pairing",
243
- },
244
- }),
245
- }),
246
- gateway: {
247
- startAccount: startGoogleChatGatewayAccount,
248
- },
249
- },
250
- pairing: {
251
- text: googlechatPairingTextAdapter,
252
- },
253
- security: googlechatSecurityAdapter,
254
- threading: googlechatThreadingAdapter,
255
- outbound: googlechatOutboundAdapter,
256
- });
@@ -1,16 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { GoogleChatConfigSchema } from "../runtime-api.js";
3
-
4
- describe("googlechat config schema", () => {
5
- it("accepts serviceAccount refs", () => {
6
- const result = GoogleChatConfigSchema.safeParse({
7
- serviceAccountRef: {
8
- source: "file",
9
- provider: "filemain",
10
- id: "/channels/googlechat/serviceAccount",
11
- },
12
- });
13
-
14
- expect(result.success).toBe(true);
15
- });
16
- });
@@ -1,3 +0,0 @@
1
- import { buildChannelConfigSchema, GoogleChatConfigSchema } from "../runtime-api.js";
2
-
3
- export const GoogleChatChannelConfigSchema = buildChannelConfigSchema(GoogleChatConfigSchema);
@@ -1,75 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { normalizeCompatibilityConfig } from "./doctor-contract.js";
3
-
4
- describe("googlechat doctor contract", () => {
5
- it("removes legacy streamMode keys", () => {
6
- const result = normalizeCompatibilityConfig({
7
- cfg: {
8
- channels: {
9
- googlechat: {
10
- streamMode: "append",
11
- accounts: {
12
- work: {
13
- streamMode: "replace",
14
- },
15
- },
16
- },
17
- },
18
- } as never,
19
- });
20
-
21
- expect(result.changes).toEqual([
22
- "Removed channels.googlechat.streamMode (legacy key no longer used).",
23
- "Removed channels.googlechat.accounts.work.streamMode (legacy key no longer used).",
24
- ]);
25
- expect(result.config.channels?.googlechat).toEqual({
26
- accounts: {
27
- work: {},
28
- },
29
- });
30
- });
31
-
32
- it("moves legacy group allow toggles into enabled", () => {
33
- const result = normalizeCompatibilityConfig({
34
- cfg: {
35
- channels: {
36
- googlechat: {
37
- groups: {
38
- "spaces/aaa": {
39
- allow: false,
40
- },
41
- "spaces/bbb": {
42
- allow: true,
43
- enabled: false,
44
- },
45
- },
46
- accounts: {
47
- work: {
48
- groups: {
49
- "spaces/ccc": {
50
- allow: true,
51
- },
52
- },
53
- },
54
- },
55
- },
56
- },
57
- } as never,
58
- });
59
-
60
- expect(result.changes).toEqual([
61
- "Moved channels.googlechat.groups.spaces/aaa.allow → channels.googlechat.groups.spaces/aaa.enabled.",
62
- "Removed channels.googlechat.groups.spaces/bbb.allow (channels.googlechat.groups.spaces/bbb.enabled already set).",
63
- "Moved channels.googlechat.accounts.work.groups.spaces/ccc.allow → channels.googlechat.accounts.work.groups.spaces/ccc.enabled.",
64
- ]);
65
- expect(result.config.channels?.googlechat?.groups?.["spaces/aaa"]).toEqual({
66
- enabled: false,
67
- });
68
- expect(result.config.channels?.googlechat?.groups?.["spaces/bbb"]).toEqual({
69
- enabled: false,
70
- });
71
- expect(result.config.channels?.googlechat?.accounts?.work?.groups?.["spaces/ccc"]).toEqual({
72
- enabled: true,
73
- });
74
- });
75
- });
@@ -1,182 +0,0 @@
1
- import type {
2
- ChannelDoctorConfigMutation,
3
- ChannelDoctorLegacyConfigRule,
4
- } from "openclaw/plugin-sdk/channel-contract";
5
- import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
6
- import { asObjectRecord } from "openclaw/plugin-sdk/runtime-doctor";
7
-
8
- type GoogleChatChannelsConfig = NonNullable<OpenClawConfig["channels"]>;
9
-
10
- function hasLegacyGoogleChatStreamMode(value: unknown): boolean {
11
- return asObjectRecord(value)?.streamMode !== undefined;
12
- }
13
-
14
- function hasLegacyGoogleChatGroupAllowAlias(value: unknown): boolean {
15
- const groups = asObjectRecord(asObjectRecord(value)?.groups);
16
- if (!groups) {
17
- return false;
18
- }
19
- return Object.values(groups).some((group) =>
20
- Object.prototype.hasOwnProperty.call(asObjectRecord(group) ?? {}, "allow"),
21
- );
22
- }
23
-
24
- function hasLegacyAccountAliases(value: unknown, match: (entry: unknown) => boolean): boolean {
25
- const accounts = asObjectRecord(value);
26
- if (!accounts) {
27
- return false;
28
- }
29
- return Object.values(accounts).some((account) => match(account));
30
- }
31
-
32
- function normalizeGoogleChatGroups(params: {
33
- groups: Record<string, unknown>;
34
- pathPrefix: string;
35
- changes: string[];
36
- }): { groups: Record<string, unknown>; changed: boolean } {
37
- let changed = false;
38
- const nextGroups = { ...params.groups };
39
- for (const [groupId, groupValue] of Object.entries(params.groups)) {
40
- const group = asObjectRecord(groupValue);
41
- if (!group || !Object.prototype.hasOwnProperty.call(group, "allow")) {
42
- continue;
43
- }
44
- const nextGroup = { ...group };
45
- if (nextGroup.enabled === undefined) {
46
- nextGroup.enabled = group.allow;
47
- params.changes.push(
48
- `Moved ${params.pathPrefix}.${groupId}.allow → ${params.pathPrefix}.${groupId}.enabled.`,
49
- );
50
- } else {
51
- params.changes.push(
52
- `Removed ${params.pathPrefix}.${groupId}.allow (${params.pathPrefix}.${groupId}.enabled already set).`,
53
- );
54
- }
55
- delete nextGroup.allow;
56
- nextGroups[groupId] = nextGroup;
57
- changed = true;
58
- }
59
- return { groups: nextGroups, changed };
60
- }
61
-
62
- function normalizeGoogleChatEntry(params: {
63
- entry: Record<string, unknown>;
64
- pathPrefix: string;
65
- changes: string[];
66
- }): { entry: Record<string, unknown>; changed: boolean } {
67
- let updated = params.entry;
68
- let changed = false;
69
-
70
- if (updated.streamMode !== undefined) {
71
- updated = { ...updated };
72
- delete updated.streamMode;
73
- params.changes.push(`Removed ${params.pathPrefix}.streamMode (legacy key no longer used).`);
74
- changed = true;
75
- }
76
-
77
- const groups = asObjectRecord(updated.groups);
78
- if (groups) {
79
- const normalized = normalizeGoogleChatGroups({
80
- groups,
81
- pathPrefix: `${params.pathPrefix}.groups`,
82
- changes: params.changes,
83
- });
84
- if (normalized.changed) {
85
- updated = { ...updated, groups: normalized.groups };
86
- changed = true;
87
- }
88
- }
89
-
90
- return { entry: updated, changed };
91
- }
92
-
93
- export const legacyConfigRules: ChannelDoctorLegacyConfigRule[] = [
94
- {
95
- path: ["channels", "googlechat"],
96
- message: "channels.googlechat.streamMode is legacy and no longer used; it is removed on load.",
97
- match: hasLegacyGoogleChatStreamMode,
98
- },
99
- {
100
- path: ["channels", "googlechat", "accounts"],
101
- message:
102
- "channels.googlechat.accounts.<id>.streamMode is legacy and no longer used; it is removed on load.",
103
- match: (value) => hasLegacyAccountAliases(value, hasLegacyGoogleChatStreamMode),
104
- },
105
- {
106
- path: ["channels", "googlechat"],
107
- message:
108
- 'channels.googlechat.groups.<id>.allow is legacy; use channels.googlechat.groups.<id>.enabled instead. Run "openclaw doctor --fix".',
109
- match: hasLegacyGoogleChatGroupAllowAlias,
110
- },
111
- {
112
- path: ["channels", "googlechat", "accounts"],
113
- message:
114
- 'channels.googlechat.accounts.<id>.groups.<id>.allow is legacy; use channels.googlechat.accounts.<id>.groups.<id>.enabled instead. Run "openclaw doctor --fix".',
115
- match: (value) => hasLegacyAccountAliases(value, hasLegacyGoogleChatGroupAllowAlias),
116
- },
117
- ];
118
-
119
- export function normalizeCompatibilityConfig({
120
- cfg,
121
- }: {
122
- cfg: OpenClawConfig;
123
- }): ChannelDoctorConfigMutation {
124
- const rawEntry = asObjectRecord(
125
- (cfg.channels as Record<string, unknown> | undefined)?.googlechat,
126
- );
127
- if (!rawEntry) {
128
- return { config: cfg, changes: [] };
129
- }
130
-
131
- const changes: string[] = [];
132
- let updated = rawEntry;
133
- let changed = false;
134
-
135
- const root = normalizeGoogleChatEntry({
136
- entry: updated,
137
- pathPrefix: "channels.googlechat",
138
- changes,
139
- });
140
- updated = root.entry;
141
- changed = root.changed;
142
-
143
- const accounts = asObjectRecord(updated.accounts);
144
- if (accounts) {
145
- let accountsChanged = false;
146
- const nextAccounts = { ...accounts };
147
- for (const [accountId, accountValue] of Object.entries(accounts)) {
148
- const account = asObjectRecord(accountValue);
149
- if (!account) {
150
- continue;
151
- }
152
- const normalized = normalizeGoogleChatEntry({
153
- entry: account,
154
- pathPrefix: `channels.googlechat.accounts.${accountId}`,
155
- changes,
156
- });
157
- if (!normalized.changed) {
158
- continue;
159
- }
160
- nextAccounts[accountId] = normalized.entry;
161
- accountsChanged = true;
162
- }
163
- if (accountsChanged) {
164
- updated = { ...updated, accounts: nextAccounts };
165
- changed = true;
166
- }
167
- }
168
-
169
- if (!changed) {
170
- return { config: cfg, changes: [] };
171
- }
172
- return {
173
- config: {
174
- ...cfg,
175
- channels: {
176
- ...cfg.channels,
177
- googlechat: updated as GoogleChatChannelsConfig["googlechat"],
178
- },
179
- },
180
- changes,
181
- };
182
- }
package/src/doctor.ts DELETED
@@ -1,57 +0,0 @@
1
- import { createDangerousNameMatchingMutableAllowlistWarningCollector } from "openclaw/plugin-sdk/channel-policy";
2
-
3
- function asObjectRecord(value: unknown): Record<string, unknown> | null {
4
- return value && typeof value === "object" && !Array.isArray(value)
5
- ? (value as Record<string, unknown>)
6
- : null;
7
- }
8
-
9
- function isGoogleChatMutableAllowEntry(raw: string): boolean {
10
- const text = raw.trim();
11
- if (!text || text === "*") {
12
- return false;
13
- }
14
-
15
- const withoutPrefix = text.replace(/^(googlechat|google-chat|gchat):/i, "").trim();
16
- if (!withoutPrefix) {
17
- return false;
18
- }
19
-
20
- const withoutUsers = withoutPrefix.replace(/^users\//i, "");
21
- return withoutUsers.includes("@");
22
- }
23
-
24
- export const collectGoogleChatMutableAllowlistWarnings =
25
- createDangerousNameMatchingMutableAllowlistWarningCollector({
26
- channel: "googlechat",
27
- detector: isGoogleChatMutableAllowEntry,
28
- collectLists: (scope) => {
29
- const lists = [
30
- {
31
- pathLabel: `${scope.prefix}.groupAllowFrom`,
32
- list: scope.account.groupAllowFrom,
33
- },
34
- ];
35
- const dm = asObjectRecord(scope.account.dm);
36
- if (dm) {
37
- lists.push({
38
- pathLabel: `${scope.prefix}.dm.allowFrom`,
39
- list: dm.allowFrom,
40
- });
41
- }
42
- const groups = asObjectRecord(scope.account.groups);
43
- if (groups) {
44
- for (const [groupKey, groupRaw] of Object.entries(groups)) {
45
- const group = asObjectRecord(groupRaw);
46
- if (!group) {
47
- continue;
48
- }
49
- lists.push({
50
- pathLabel: `${scope.prefix}.groups.${groupKey}.users`,
51
- list: group.users,
52
- });
53
- }
54
- }
55
- return lists;
56
- },
57
- });
package/src/gateway.ts DELETED
@@ -1,63 +0,0 @@
1
- import {
2
- createAccountStatusSink,
3
- runPassiveAccountLifecycle,
4
- } from "openclaw/plugin-sdk/channel-lifecycle";
5
- import type { OpenClawConfig } from "openclaw/plugin-sdk/config-types";
6
- import { createLazyRuntimeNamedExport } from "openclaw/plugin-sdk/lazy-runtime";
7
- import type { ChannelAccountSnapshot } from "openclaw/plugin-sdk/status-helpers";
8
- import type { ResolvedGoogleChatAccount } from "./accounts.js";
9
- import type { GoogleChatRuntimeEnv } from "./monitor-types.js";
10
-
11
- const loadGoogleChatChannelRuntime = createLazyRuntimeNamedExport(
12
- () => import("./channel.runtime.js"),
13
- "googleChatChannelRuntime",
14
- );
15
-
16
- export async function startGoogleChatGatewayAccount(ctx: {
17
- account: ResolvedGoogleChatAccount;
18
- cfg: OpenClawConfig;
19
- runtime: GoogleChatRuntimeEnv;
20
- abortSignal: AbortSignal;
21
- setStatus: (next: ChannelAccountSnapshot) => void;
22
- log?: {
23
- info?: (message: string) => void;
24
- };
25
- }): Promise<void> {
26
- const account = ctx.account;
27
- const statusSink = createAccountStatusSink({
28
- accountId: account.accountId,
29
- setStatus: ctx.setStatus,
30
- });
31
- ctx.log?.info?.(`[${account.accountId}] starting Google Chat webhook`);
32
- const { resolveGoogleChatWebhookPath, startGoogleChatMonitor } =
33
- await loadGoogleChatChannelRuntime();
34
- statusSink({
35
- running: true,
36
- lastStartAt: Date.now(),
37
- webhookPath: resolveGoogleChatWebhookPath({ account }),
38
- audienceType: account.config.audienceType,
39
- audience: account.config.audience,
40
- });
41
- await runPassiveAccountLifecycle({
42
- abortSignal: ctx.abortSignal,
43
- start: async () =>
44
- await startGoogleChatMonitor({
45
- account,
46
- config: ctx.cfg,
47
- runtime: ctx.runtime,
48
- abortSignal: ctx.abortSignal,
49
- webhookPath: account.config.webhookPath,
50
- webhookUrl: account.config.webhookUrl,
51
- statusSink,
52
- }),
53
- stop: async (unregister) => {
54
- unregister?.();
55
- },
56
- onStop: async () => {
57
- statusSink({
58
- running: false,
59
- lastStopAt: Date.now(),
60
- });
61
- },
62
- });
63
- }