@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.
- package/dist/accounts-BbM9zX1S.js +96 -0
- package/dist/actions-D-PNwmYx.js +160 -0
- package/dist/{api-C8OqyWsW.js → api-AErsImS_.js} +1 -1
- package/dist/api.js +2 -2
- package/dist/{channel-CHniJUSZ.js → channel-9lvRWX6T.js} +87 -224
- package/dist/channel-config-api.js +1 -1
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-Bu7xf0wo.js → channel.runtime-CK4QbJkn.js} +151 -136
- package/dist/contract-api.js +2 -2
- package/dist/doctor-contract-api.js +1 -1
- package/dist/{runtime-api-wkIdfwqY.js → runtime-api-DMEzhesS.js} +5 -6
- package/dist/runtime-api.js +2 -2
- package/dist/secret-contract-api.js +1 -1
- package/dist/setup-plugin-api.js +2 -1
- package/dist/{setup-surface-CofP-Gg9.js → setup-surface-S4ArLnR8.js} +5 -97
- package/dist/targets-qggOq6n-.js +43 -0
- package/dist/test-api.js +2 -2
- package/package.json +5 -6
- /package/dist/{doctor-contract-CG1sLToP.js → doctor-contract-BsERSjSe.js} +0 -0
- /package/dist/{secret-contract-DtQ_IO7J.js → secret-contract-DLAG2_NI.js} +0 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { safeParseJsonWithSchema, safeParseWithSchema } from "openclaw/plugin-sdk/extension-shared";
|
|
2
|
+
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
|
3
|
+
import { DEFAULT_ACCOUNT_ID, createAccountListHelpers, normalizeAccountId, resolveAccountEntry, resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-resolution";
|
|
4
|
+
import { isSecretRef } from "openclaw/plugin-sdk/secret-input";
|
|
5
|
+
import { z } from "openclaw/plugin-sdk/zod";
|
|
6
|
+
//#region extensions/googlechat/src/accounts.ts
|
|
7
|
+
const ENV_SERVICE_ACCOUNT = "GOOGLE_CHAT_SERVICE_ACCOUNT";
|
|
8
|
+
const ENV_SERVICE_ACCOUNT_FILE = "GOOGLE_CHAT_SERVICE_ACCOUNT_FILE";
|
|
9
|
+
const JsonRecordSchema = z.record(z.string(), z.unknown());
|
|
10
|
+
const { listAccountIds: listGoogleChatAccountIds, resolveDefaultAccountId: resolveDefaultGoogleChatAccountId } = createAccountListHelpers("googlechat");
|
|
11
|
+
function mergeGoogleChatAccountConfig(cfg, accountId) {
|
|
12
|
+
const raw = cfg.channels?.["googlechat"] ?? {};
|
|
13
|
+
const base = resolveMergedAccountConfig({
|
|
14
|
+
channelConfig: raw,
|
|
15
|
+
accounts: raw.accounts,
|
|
16
|
+
accountId,
|
|
17
|
+
omitKeys: ["defaultAccount"]
|
|
18
|
+
});
|
|
19
|
+
const defaultAccountConfig = resolveAccountEntry(raw.accounts, DEFAULT_ACCOUNT_ID) ?? {};
|
|
20
|
+
if (accountId === DEFAULT_ACCOUNT_ID) return base;
|
|
21
|
+
const { enabled: _ignoredEnabled, dangerouslyAllowNameMatching: _ignoredDangerouslyAllowNameMatching, serviceAccount: _ignoredServiceAccount, serviceAccountRef: _ignoredServiceAccountRef, serviceAccountFile: _ignoredServiceAccountFile, ...defaultAccountShared } = defaultAccountConfig;
|
|
22
|
+
return {
|
|
23
|
+
...defaultAccountShared,
|
|
24
|
+
...base
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function resolveGoogleChatConfigAccessorAccount(params) {
|
|
28
|
+
const accountId = normalizeAccountId(params.accountId ?? params.cfg.channels?.googlechat?.defaultAccount);
|
|
29
|
+
return { config: mergeGoogleChatAccountConfig(params.cfg, accountId) };
|
|
30
|
+
}
|
|
31
|
+
function parseServiceAccount(value) {
|
|
32
|
+
if (isSecretRef(value)) return null;
|
|
33
|
+
if (typeof value === "string") {
|
|
34
|
+
const trimmed = value.trim();
|
|
35
|
+
if (!trimmed) return null;
|
|
36
|
+
return safeParseJsonWithSchema(JsonRecordSchema, trimmed);
|
|
37
|
+
}
|
|
38
|
+
return safeParseWithSchema(JsonRecordSchema, value);
|
|
39
|
+
}
|
|
40
|
+
function resolveCredentialsFromConfig(params) {
|
|
41
|
+
const { account, accountId } = params;
|
|
42
|
+
const inline = parseServiceAccount(account.serviceAccount);
|
|
43
|
+
if (inline) return {
|
|
44
|
+
credentials: inline,
|
|
45
|
+
source: "inline"
|
|
46
|
+
};
|
|
47
|
+
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.`);
|
|
48
|
+
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.`);
|
|
49
|
+
const file = normalizeOptionalString(account.serviceAccountFile);
|
|
50
|
+
if (file) return {
|
|
51
|
+
credentialsFile: file,
|
|
52
|
+
source: "file"
|
|
53
|
+
};
|
|
54
|
+
if (accountId === DEFAULT_ACCOUNT_ID) {
|
|
55
|
+
const envJson = process.env[ENV_SERVICE_ACCOUNT];
|
|
56
|
+
const envInline = parseServiceAccount(envJson);
|
|
57
|
+
if (envInline) return {
|
|
58
|
+
credentials: envInline,
|
|
59
|
+
source: "env"
|
|
60
|
+
};
|
|
61
|
+
const envFile = normalizeOptionalString(process.env[ENV_SERVICE_ACCOUNT_FILE]);
|
|
62
|
+
if (envFile) return {
|
|
63
|
+
credentialsFile: envFile,
|
|
64
|
+
source: "env"
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return { source: "none" };
|
|
68
|
+
}
|
|
69
|
+
function resolveGoogleChatAccount(params) {
|
|
70
|
+
const accountId = normalizeAccountId(params.accountId ?? params.cfg.channels?.["googlechat"]?.defaultAccount);
|
|
71
|
+
const baseEnabled = params.cfg.channels?.["googlechat"]?.enabled !== false;
|
|
72
|
+
const merged = mergeGoogleChatAccountConfig(params.cfg, accountId);
|
|
73
|
+
const accountEnabled = merged.enabled !== false;
|
|
74
|
+
const enabled = baseEnabled && accountEnabled;
|
|
75
|
+
const credentials = resolveCredentialsFromConfig({
|
|
76
|
+
accountId,
|
|
77
|
+
account: merged
|
|
78
|
+
});
|
|
79
|
+
return {
|
|
80
|
+
accountId,
|
|
81
|
+
name: normalizeOptionalString(merged.name),
|
|
82
|
+
enabled,
|
|
83
|
+
config: merged,
|
|
84
|
+
credentialSource: credentials.source,
|
|
85
|
+
credentials: credentials.credentials,
|
|
86
|
+
credentialsFile: credentials.credentialsFile
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function listEnabledGoogleChatAccounts(cfg) {
|
|
90
|
+
return listGoogleChatAccountIds(cfg).map((accountId) => resolveGoogleChatAccount({
|
|
91
|
+
cfg,
|
|
92
|
+
accountId
|
|
93
|
+
})).filter((account) => account.enabled);
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
export { resolveGoogleChatConfigAccessorAccount as a, resolveGoogleChatAccount as i, listGoogleChatAccountIds as n, resolveDefaultGoogleChatAccountId as r, listEnabledGoogleChatAccounts as t };
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { i as resolveGoogleChatAccount, t as listEnabledGoogleChatAccounts } from "./accounts-BbM9zX1S.js";
|
|
2
|
+
import { P as getGoogleChatRuntime } from "./runtime-api-DMEzhesS.js";
|
|
3
|
+
import { c as sendGoogleChatMessage, o as listGoogleChatReactions, r as deleteGoogleChatReaction, t as createGoogleChatReaction, u as uploadGoogleChatAttachment } from "./api-AErsImS_.js";
|
|
4
|
+
import { i as resolveGoogleChatOutboundSpace } from "./targets-qggOq6n-.js";
|
|
5
|
+
import { extractToolSend } from "openclaw/plugin-sdk/tool-send";
|
|
6
|
+
import { createActionGate, jsonResult, readNumberParam, readReactionParams, readStringParam } from "openclaw/plugin-sdk/channel-actions";
|
|
7
|
+
import { loadOutboundMediaFromUrl } from "openclaw/plugin-sdk/outbound-media";
|
|
8
|
+
//#region extensions/googlechat/src/actions.ts
|
|
9
|
+
const providerId = "googlechat";
|
|
10
|
+
function listEnabledAccounts(cfg) {
|
|
11
|
+
return listEnabledGoogleChatAccounts(cfg).filter((account) => account.enabled && account.credentialSource !== "none");
|
|
12
|
+
}
|
|
13
|
+
function isReactionsEnabled(accounts) {
|
|
14
|
+
for (const account of accounts) if (createActionGate(account.config.actions)("reactions")) return true;
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
function resolveAppUserNames(account) {
|
|
18
|
+
return new Set(["users/app", account.config.botUser?.trim()].filter(Boolean));
|
|
19
|
+
}
|
|
20
|
+
async function loadGoogleChatActionMedia(params) {
|
|
21
|
+
const runtime = getGoogleChatRuntime();
|
|
22
|
+
return /^https?:\/\//i.test(params.mediaUrl) ? await runtime.channel.media.fetchRemoteMedia({
|
|
23
|
+
url: params.mediaUrl,
|
|
24
|
+
maxBytes: params.maxBytes
|
|
25
|
+
}) : await loadOutboundMediaFromUrl(params.mediaUrl, {
|
|
26
|
+
maxBytes: params.maxBytes,
|
|
27
|
+
mediaAccess: params.mediaAccess,
|
|
28
|
+
mediaLocalRoots: params.mediaLocalRoots,
|
|
29
|
+
mediaReadFile: params.mediaReadFile
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
const googlechatMessageActions = {
|
|
33
|
+
describeMessageTool: ({ cfg, accountId }) => {
|
|
34
|
+
const accounts = accountId ? [resolveGoogleChatAccount({
|
|
35
|
+
cfg,
|
|
36
|
+
accountId
|
|
37
|
+
})].filter((account) => account.enabled && account.credentialSource !== "none") : listEnabledAccounts(cfg);
|
|
38
|
+
if (accounts.length === 0) return null;
|
|
39
|
+
const actions = /* @__PURE__ */ new Set([]);
|
|
40
|
+
actions.add("send");
|
|
41
|
+
actions.add("upload-file");
|
|
42
|
+
if (isReactionsEnabled(accounts)) {
|
|
43
|
+
actions.add("react");
|
|
44
|
+
actions.add("reactions");
|
|
45
|
+
}
|
|
46
|
+
return { actions: Array.from(actions) };
|
|
47
|
+
},
|
|
48
|
+
extractToolSend: ({ args }) => {
|
|
49
|
+
return extractToolSend(args, "sendMessage");
|
|
50
|
+
},
|
|
51
|
+
handleAction: async ({ action, params, cfg, accountId, mediaAccess, mediaLocalRoots, mediaReadFile }) => {
|
|
52
|
+
const account = resolveGoogleChatAccount({
|
|
53
|
+
cfg,
|
|
54
|
+
accountId
|
|
55
|
+
});
|
|
56
|
+
if (account.credentialSource === "none") throw new Error("Google Chat credentials are missing.");
|
|
57
|
+
if (action === "send" || action === "upload-file") {
|
|
58
|
+
const to = readStringParam(params, "to", { required: true });
|
|
59
|
+
const content = readStringParam(params, "message", {
|
|
60
|
+
required: action === "send",
|
|
61
|
+
allowEmpty: true
|
|
62
|
+
}) ?? readStringParam(params, "initialComment", { allowEmpty: true }) ?? "";
|
|
63
|
+
const mediaUrl = readStringParam(params, "media", { trim: false }) ?? readStringParam(params, "filePath", { trim: false }) ?? readStringParam(params, "path", { trim: false });
|
|
64
|
+
const threadId = readStringParam(params, "threadId") ?? readStringParam(params, "replyTo");
|
|
65
|
+
const space = await resolveGoogleChatOutboundSpace({
|
|
66
|
+
account,
|
|
67
|
+
target: to
|
|
68
|
+
});
|
|
69
|
+
if (mediaUrl) {
|
|
70
|
+
const loaded = await loadGoogleChatActionMedia({
|
|
71
|
+
mediaUrl,
|
|
72
|
+
maxBytes: (account.config.mediaMaxMb ?? 20) * 1024 * 1024,
|
|
73
|
+
mediaAccess,
|
|
74
|
+
mediaLocalRoots,
|
|
75
|
+
mediaReadFile
|
|
76
|
+
});
|
|
77
|
+
const uploadFileName = readStringParam(params, "filename") ?? readStringParam(params, "title") ?? loaded.fileName ?? "attachment";
|
|
78
|
+
const upload = await uploadGoogleChatAttachment({
|
|
79
|
+
account,
|
|
80
|
+
space,
|
|
81
|
+
filename: uploadFileName,
|
|
82
|
+
buffer: loaded.buffer,
|
|
83
|
+
contentType: loaded.contentType
|
|
84
|
+
});
|
|
85
|
+
await sendGoogleChatMessage({
|
|
86
|
+
account,
|
|
87
|
+
space,
|
|
88
|
+
text: content,
|
|
89
|
+
thread: threadId ?? void 0,
|
|
90
|
+
attachments: upload.attachmentUploadToken ? [{
|
|
91
|
+
attachmentUploadToken: upload.attachmentUploadToken,
|
|
92
|
+
contentName: uploadFileName
|
|
93
|
+
}] : void 0
|
|
94
|
+
});
|
|
95
|
+
return jsonResult({
|
|
96
|
+
ok: true,
|
|
97
|
+
to: space
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
if (action === "upload-file") throw new Error("upload-file requires media, filePath, or path");
|
|
101
|
+
await sendGoogleChatMessage({
|
|
102
|
+
account,
|
|
103
|
+
space,
|
|
104
|
+
text: content,
|
|
105
|
+
thread: threadId ?? void 0
|
|
106
|
+
});
|
|
107
|
+
return jsonResult({
|
|
108
|
+
ok: true,
|
|
109
|
+
to: space
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
if (action === "react") {
|
|
113
|
+
const messageName = readStringParam(params, "messageId", { required: true });
|
|
114
|
+
const { emoji, remove, isEmpty } = readReactionParams(params, { removeErrorMessage: "Emoji is required to remove a Google Chat reaction." });
|
|
115
|
+
if (remove || isEmpty) {
|
|
116
|
+
const reactions = await listGoogleChatReactions({
|
|
117
|
+
account,
|
|
118
|
+
messageName
|
|
119
|
+
});
|
|
120
|
+
const appUsers = resolveAppUserNames(account);
|
|
121
|
+
const toRemove = reactions.filter((reaction) => {
|
|
122
|
+
const userName = reaction.user?.name?.trim();
|
|
123
|
+
if (appUsers.size > 0 && !appUsers.has(userName ?? "")) return false;
|
|
124
|
+
if (emoji) return reaction.emoji?.unicode === emoji;
|
|
125
|
+
return true;
|
|
126
|
+
});
|
|
127
|
+
for (const reaction of toRemove) {
|
|
128
|
+
if (!reaction.name) continue;
|
|
129
|
+
await deleteGoogleChatReaction({
|
|
130
|
+
account,
|
|
131
|
+
reactionName: reaction.name
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return jsonResult({
|
|
135
|
+
ok: true,
|
|
136
|
+
removed: toRemove.length
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return jsonResult({
|
|
140
|
+
ok: true,
|
|
141
|
+
reaction: await createGoogleChatReaction({
|
|
142
|
+
account,
|
|
143
|
+
messageName,
|
|
144
|
+
emoji
|
|
145
|
+
})
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
if (action === "reactions") return jsonResult({
|
|
149
|
+
ok: true,
|
|
150
|
+
reactions: await listGoogleChatReactions({
|
|
151
|
+
account,
|
|
152
|
+
messageName: readStringParam(params, "messageId", { required: true }),
|
|
153
|
+
limit: readNumberParam(params, "limit", { integer: true }) ?? void 0
|
|
154
|
+
})
|
|
155
|
+
});
|
|
156
|
+
throw new Error(`Action ${action} is not supported for provider ${providerId}.`);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
//#endregion
|
|
160
|
+
export { googlechatMessageActions };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { m as fetchWithSsrFGuard$1 } from "./runtime-api-DMEzhesS.js";
|
|
2
2
|
import { normalizeLowercaseStringOrEmpty, resolveUserPath } from "openclaw/plugin-sdk/text-runtime";
|
|
3
3
|
import crypto from "node:crypto";
|
|
4
4
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
package/dist/api.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as
|
|
1
|
+
import { t as googlechatPlugin } from "./channel-9lvRWX6T.js";
|
|
2
|
+
import { n as googlechatSetupAdapter, t as googlechatSetupWizard } from "./setup-surface-S4ArLnR8.js";
|
|
3
3
|
export { googlechatPlugin, googlechatSetupAdapter, googlechatSetupWizard };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-
|
|
5
|
-
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-
|
|
1
|
+
import { a as resolveGoogleChatConfigAccessorAccount, i as resolveGoogleChatAccount, n as listGoogleChatAccountIds, r as resolveDefaultGoogleChatAccountId } from "./accounts-BbM9zX1S.js";
|
|
2
|
+
import { T as resolveChannelMediaMaxBytes, _ as loadOutboundMediaFromUrl, a as buildChannelConfigSchema, i as PAIRING_APPROVED_MESSAGE, o as chunkTextForOutbound, p as fetchRemoteMedia, r as GoogleChatConfigSchema, t as DEFAULT_ACCOUNT_ID, v as missingTargetError } from "./runtime-api-DMEzhesS.js";
|
|
3
|
+
import { i as resolveGoogleChatOutboundSpace, n as isGoogleChatUserTarget, r as normalizeGoogleChatTarget, t as isGoogleChatSpaceTarget } from "./targets-qggOq6n-.js";
|
|
4
|
+
import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-BsERSjSe.js";
|
|
5
|
+
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-DLAG2_NI.js";
|
|
6
|
+
import { n as googlechatSetupAdapter, t as googlechatSetupWizard } from "./setup-surface-S4ArLnR8.js";
|
|
6
7
|
import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
|
|
7
8
|
import { formatNormalizedAllowFromEntries } from "openclaw/plugin-sdk/allow-from";
|
|
8
9
|
import { adaptScopedAccountAccessor, createScopedChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
@@ -10,207 +11,14 @@ import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
|
|
|
10
11
|
import { buildPassiveProbedChannelStatusSummary } from "openclaw/plugin-sdk/extension-shared";
|
|
11
12
|
import { createLazyRuntimeNamedExport } from "openclaw/plugin-sdk/lazy-runtime";
|
|
12
13
|
import { createComputedAccountStatusAdapter, createDefaultChannelRuntimeState } from "openclaw/plugin-sdk/status-helpers";
|
|
13
|
-
import { createActionGate, jsonResult, readNumberParam, readReactionParams, readStringParam } from "openclaw/plugin-sdk/channel-actions";
|
|
14
|
-
import { loadOutboundMediaFromUrl } from "openclaw/plugin-sdk/outbound-media";
|
|
15
14
|
import { extractToolSend } from "openclaw/plugin-sdk/tool-send";
|
|
15
|
+
import { createResolvedApproverActionAuthAdapter, resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
|
|
16
16
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
|
17
17
|
import { createAccountStatusSink, runPassiveAccountLifecycle } from "openclaw/plugin-sdk/channel-lifecycle";
|
|
18
|
+
import { createMessageReceiptFromOutboundResults, defineChannelMessageAdapter } from "openclaw/plugin-sdk/channel-message";
|
|
18
19
|
import { composeAccountWarningCollectors, createAllowlistProviderOpenWarningCollector, createDangerousNameMatchingMutableAllowlistWarningCollector, resolveChannelGroupRequireMention } from "openclaw/plugin-sdk/channel-policy";
|
|
19
|
-
import { createResolvedApproverActionAuthAdapter, resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
|
|
20
20
|
import { createChannelDirectoryAdapter, listResolvedDirectoryGroupEntriesFromMapKeys, listResolvedDirectoryUserEntriesFromAllowFrom } from "openclaw/plugin-sdk/directory-runtime";
|
|
21
21
|
import { sanitizeForPlainText } from "openclaw/plugin-sdk/outbound-runtime";
|
|
22
|
-
//#region extensions/googlechat/src/targets.ts
|
|
23
|
-
function normalizeGoogleChatTarget(raw) {
|
|
24
|
-
const trimmed = raw?.trim();
|
|
25
|
-
if (!trimmed) return;
|
|
26
|
-
const normalized = trimmed.replace(/^(googlechat|google-chat|gchat):/i, "").replace(/^user:(users\/)?/i, "users/").replace(/^space:(spaces\/)?/i, "spaces/");
|
|
27
|
-
if (isGoogleChatUserTarget(normalized)) {
|
|
28
|
-
const suffix = normalized.slice(6);
|
|
29
|
-
return suffix.includes("@") ? `users/${normalizeLowercaseStringOrEmpty(suffix)}` : normalized;
|
|
30
|
-
}
|
|
31
|
-
if (isGoogleChatSpaceTarget(normalized)) return normalized;
|
|
32
|
-
if (normalized.includes("@")) return `users/${normalizeLowercaseStringOrEmpty(normalized)}`;
|
|
33
|
-
return normalized;
|
|
34
|
-
}
|
|
35
|
-
function isGoogleChatUserTarget(value) {
|
|
36
|
-
return normalizeLowercaseStringOrEmpty(value).startsWith("users/");
|
|
37
|
-
}
|
|
38
|
-
function isGoogleChatSpaceTarget(value) {
|
|
39
|
-
return normalizeLowercaseStringOrEmpty(value).startsWith("spaces/");
|
|
40
|
-
}
|
|
41
|
-
function stripMessageSuffix(target) {
|
|
42
|
-
const index = target.indexOf("/messages/");
|
|
43
|
-
if (index === -1) return target;
|
|
44
|
-
return target.slice(0, index);
|
|
45
|
-
}
|
|
46
|
-
async function resolveGoogleChatOutboundSpace(params) {
|
|
47
|
-
const normalized = normalizeGoogleChatTarget(params.target);
|
|
48
|
-
if (!normalized) throw new Error("Missing Google Chat target.");
|
|
49
|
-
const base = stripMessageSuffix(normalized);
|
|
50
|
-
if (isGoogleChatSpaceTarget(base)) return base;
|
|
51
|
-
if (isGoogleChatUserTarget(base)) {
|
|
52
|
-
const dm = await findGoogleChatDirectMessage({
|
|
53
|
-
account: params.account,
|
|
54
|
-
userName: base
|
|
55
|
-
});
|
|
56
|
-
if (!dm?.name) throw new Error(`No Google Chat DM found for ${base}`);
|
|
57
|
-
return dm.name;
|
|
58
|
-
}
|
|
59
|
-
return base;
|
|
60
|
-
}
|
|
61
|
-
//#endregion
|
|
62
|
-
//#region extensions/googlechat/src/actions.ts
|
|
63
|
-
const providerId = "googlechat";
|
|
64
|
-
function listEnabledAccounts(cfg) {
|
|
65
|
-
return listEnabledGoogleChatAccounts(cfg).filter((account) => account.enabled && account.credentialSource !== "none");
|
|
66
|
-
}
|
|
67
|
-
function isReactionsEnabled(accounts) {
|
|
68
|
-
for (const account of accounts) if (createActionGate(account.config.actions)("reactions")) return true;
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
71
|
-
function resolveAppUserNames(account) {
|
|
72
|
-
return new Set(["users/app", account.config.botUser?.trim()].filter(Boolean));
|
|
73
|
-
}
|
|
74
|
-
async function loadGoogleChatActionMedia(params) {
|
|
75
|
-
const runtime = getGoogleChatRuntime();
|
|
76
|
-
return /^https?:\/\//i.test(params.mediaUrl) ? await runtime.channel.media.fetchRemoteMedia({
|
|
77
|
-
url: params.mediaUrl,
|
|
78
|
-
maxBytes: params.maxBytes
|
|
79
|
-
}) : await loadOutboundMediaFromUrl(params.mediaUrl, {
|
|
80
|
-
maxBytes: params.maxBytes,
|
|
81
|
-
mediaAccess: params.mediaAccess,
|
|
82
|
-
mediaLocalRoots: params.mediaLocalRoots,
|
|
83
|
-
mediaReadFile: params.mediaReadFile
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
const googlechatMessageActions = {
|
|
87
|
-
describeMessageTool: ({ cfg, accountId }) => {
|
|
88
|
-
const accounts = accountId ? [resolveGoogleChatAccount({
|
|
89
|
-
cfg,
|
|
90
|
-
accountId
|
|
91
|
-
})].filter((account) => account.enabled && account.credentialSource !== "none") : listEnabledAccounts(cfg);
|
|
92
|
-
if (accounts.length === 0) return null;
|
|
93
|
-
const actions = /* @__PURE__ */ new Set([]);
|
|
94
|
-
actions.add("send");
|
|
95
|
-
actions.add("upload-file");
|
|
96
|
-
if (isReactionsEnabled(accounts)) {
|
|
97
|
-
actions.add("react");
|
|
98
|
-
actions.add("reactions");
|
|
99
|
-
}
|
|
100
|
-
return { actions: Array.from(actions) };
|
|
101
|
-
},
|
|
102
|
-
extractToolSend: ({ args }) => {
|
|
103
|
-
return extractToolSend(args, "sendMessage");
|
|
104
|
-
},
|
|
105
|
-
handleAction: async ({ action, params, cfg, accountId, mediaAccess, mediaLocalRoots, mediaReadFile }) => {
|
|
106
|
-
const account = resolveGoogleChatAccount({
|
|
107
|
-
cfg,
|
|
108
|
-
accountId
|
|
109
|
-
});
|
|
110
|
-
if (account.credentialSource === "none") throw new Error("Google Chat credentials are missing.");
|
|
111
|
-
if (action === "send" || action === "upload-file") {
|
|
112
|
-
const to = readStringParam(params, "to", { required: true });
|
|
113
|
-
const content = readStringParam(params, "message", {
|
|
114
|
-
required: action === "send",
|
|
115
|
-
allowEmpty: true
|
|
116
|
-
}) ?? readStringParam(params, "initialComment", { allowEmpty: true }) ?? "";
|
|
117
|
-
const mediaUrl = readStringParam(params, "media", { trim: false }) ?? readStringParam(params, "filePath", { trim: false }) ?? readStringParam(params, "path", { trim: false });
|
|
118
|
-
const threadId = readStringParam(params, "threadId") ?? readStringParam(params, "replyTo");
|
|
119
|
-
const space = await resolveGoogleChatOutboundSpace({
|
|
120
|
-
account,
|
|
121
|
-
target: to
|
|
122
|
-
});
|
|
123
|
-
if (mediaUrl) {
|
|
124
|
-
const loaded = await loadGoogleChatActionMedia({
|
|
125
|
-
mediaUrl,
|
|
126
|
-
maxBytes: (account.config.mediaMaxMb ?? 20) * 1024 * 1024,
|
|
127
|
-
mediaAccess,
|
|
128
|
-
mediaLocalRoots,
|
|
129
|
-
mediaReadFile
|
|
130
|
-
});
|
|
131
|
-
const uploadFileName = readStringParam(params, "filename") ?? readStringParam(params, "title") ?? loaded.fileName ?? "attachment";
|
|
132
|
-
const upload = await uploadGoogleChatAttachment({
|
|
133
|
-
account,
|
|
134
|
-
space,
|
|
135
|
-
filename: uploadFileName,
|
|
136
|
-
buffer: loaded.buffer,
|
|
137
|
-
contentType: loaded.contentType
|
|
138
|
-
});
|
|
139
|
-
await sendGoogleChatMessage({
|
|
140
|
-
account,
|
|
141
|
-
space,
|
|
142
|
-
text: content,
|
|
143
|
-
thread: threadId ?? void 0,
|
|
144
|
-
attachments: upload.attachmentUploadToken ? [{
|
|
145
|
-
attachmentUploadToken: upload.attachmentUploadToken,
|
|
146
|
-
contentName: uploadFileName
|
|
147
|
-
}] : void 0
|
|
148
|
-
});
|
|
149
|
-
return jsonResult({
|
|
150
|
-
ok: true,
|
|
151
|
-
to: space
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
if (action === "upload-file") throw new Error("upload-file requires media, filePath, or path");
|
|
155
|
-
await sendGoogleChatMessage({
|
|
156
|
-
account,
|
|
157
|
-
space,
|
|
158
|
-
text: content,
|
|
159
|
-
thread: threadId ?? void 0
|
|
160
|
-
});
|
|
161
|
-
return jsonResult({
|
|
162
|
-
ok: true,
|
|
163
|
-
to: space
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
if (action === "react") {
|
|
167
|
-
const messageName = readStringParam(params, "messageId", { required: true });
|
|
168
|
-
const { emoji, remove, isEmpty } = readReactionParams(params, { removeErrorMessage: "Emoji is required to remove a Google Chat reaction." });
|
|
169
|
-
if (remove || isEmpty) {
|
|
170
|
-
const reactions = await listGoogleChatReactions({
|
|
171
|
-
account,
|
|
172
|
-
messageName
|
|
173
|
-
});
|
|
174
|
-
const appUsers = resolveAppUserNames(account);
|
|
175
|
-
const toRemove = reactions.filter((reaction) => {
|
|
176
|
-
const userName = reaction.user?.name?.trim();
|
|
177
|
-
if (appUsers.size > 0 && !appUsers.has(userName ?? "")) return false;
|
|
178
|
-
if (emoji) return reaction.emoji?.unicode === emoji;
|
|
179
|
-
return true;
|
|
180
|
-
});
|
|
181
|
-
for (const reaction of toRemove) {
|
|
182
|
-
if (!reaction.name) continue;
|
|
183
|
-
await deleteGoogleChatReaction({
|
|
184
|
-
account,
|
|
185
|
-
reactionName: reaction.name
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
return jsonResult({
|
|
189
|
-
ok: true,
|
|
190
|
-
removed: toRemove.length
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
return jsonResult({
|
|
194
|
-
ok: true,
|
|
195
|
-
reaction: await createGoogleChatReaction({
|
|
196
|
-
account,
|
|
197
|
-
messageName,
|
|
198
|
-
emoji
|
|
199
|
-
})
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
if (action === "reactions") return jsonResult({
|
|
203
|
-
ok: true,
|
|
204
|
-
reactions: await listGoogleChatReactions({
|
|
205
|
-
account,
|
|
206
|
-
messageName: readStringParam(params, "messageId", { required: true }),
|
|
207
|
-
limit: readNumberParam(params, "limit", { integer: true }) ?? void 0
|
|
208
|
-
})
|
|
209
|
-
});
|
|
210
|
-
throw new Error(`Action ${action} is not supported for provider ${providerId}.`);
|
|
211
|
-
}
|
|
212
|
-
};
|
|
213
|
-
//#endregion
|
|
214
22
|
//#region extensions/googlechat/src/approval-auth.ts
|
|
215
23
|
function normalizeGoogleChatApproverId(value) {
|
|
216
24
|
const normalized = normalizeGoogleChatTarget(String(value));
|
|
@@ -246,7 +54,20 @@ function resolveGoogleChatGroupRequireMention(params) {
|
|
|
246
54
|
}
|
|
247
55
|
//#endregion
|
|
248
56
|
//#region extensions/googlechat/src/channel.adapters.ts
|
|
249
|
-
const loadGoogleChatChannelRuntime$2 = createLazyRuntimeNamedExport(() => import("./channel.runtime-
|
|
57
|
+
const loadGoogleChatChannelRuntime$2 = createLazyRuntimeNamedExport(() => import("./channel.runtime-CK4QbJkn.js"), "googleChatChannelRuntime");
|
|
58
|
+
function createGoogleChatSendReceipt(params) {
|
|
59
|
+
const messageId = params.messageId?.trim();
|
|
60
|
+
return createMessageReceiptFromOutboundResults({
|
|
61
|
+
results: messageId ? [{
|
|
62
|
+
channel: "googlechat",
|
|
63
|
+
messageId,
|
|
64
|
+
chatId: params.chatId,
|
|
65
|
+
conversationId: params.chatId
|
|
66
|
+
}] : [],
|
|
67
|
+
threadId: params.chatId,
|
|
68
|
+
kind: params.kind
|
|
69
|
+
});
|
|
70
|
+
}
|
|
250
71
|
const formatAllowFromEntry = (entry) => normalizeLowercaseStringOrEmpty(entry.trim().replace(/^(googlechat|google-chat|gchat):/i, "").replace(/^user:/i, "").replace(/^users\//i, ""));
|
|
251
72
|
const collectGoogleChatSecurityWarnings = composeAccountWarningCollectors(createAllowlistProviderOpenWarningCollector({
|
|
252
73
|
providerConfigPresent: (cfg) => cfg.channels?.googlechat !== void 0,
|
|
@@ -351,14 +172,20 @@ const googlechatOutboundAdapter = {
|
|
|
351
172
|
});
|
|
352
173
|
const thread = typeof threadId === "number" ? String(threadId) : threadId ?? replyToId ?? void 0;
|
|
353
174
|
const { sendGoogleChatMessage } = await loadGoogleChatChannelRuntime$2();
|
|
175
|
+
const messageId = (await sendGoogleChatMessage({
|
|
176
|
+
account,
|
|
177
|
+
space,
|
|
178
|
+
text,
|
|
179
|
+
thread
|
|
180
|
+
}))?.messageName ?? "";
|
|
354
181
|
return {
|
|
355
|
-
messageId
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
182
|
+
messageId,
|
|
183
|
+
chatId: space,
|
|
184
|
+
receipt: createGoogleChatSendReceipt({
|
|
185
|
+
messageId,
|
|
186
|
+
chatId: space,
|
|
187
|
+
kind: "text"
|
|
188
|
+
})
|
|
362
189
|
};
|
|
363
190
|
},
|
|
364
191
|
sendMedia: async ({ cfg, to, text, mediaUrl, mediaAccess, mediaLocalRoots, mediaReadFile, accountId, replyToId, threadId }) => {
|
|
@@ -380,7 +207,7 @@ const googlechatOutboundAdapter = {
|
|
|
380
207
|
const loaded = /^https?:\/\//i.test(mediaUrl) ? await fetchRemoteMedia({
|
|
381
208
|
url: mediaUrl,
|
|
382
209
|
maxBytes: effectiveMaxBytes
|
|
383
|
-
}) : await loadOutboundMediaFromUrl
|
|
210
|
+
}) : await loadOutboundMediaFromUrl(mediaUrl, {
|
|
384
211
|
maxBytes: effectiveMaxBytes,
|
|
385
212
|
mediaAccess,
|
|
386
213
|
mediaLocalRoots,
|
|
@@ -394,22 +221,41 @@ const googlechatOutboundAdapter = {
|
|
|
394
221
|
buffer: loaded.buffer,
|
|
395
222
|
contentType: loaded.contentType
|
|
396
223
|
});
|
|
224
|
+
const messageId = (await sendGoogleChatMessage({
|
|
225
|
+
account,
|
|
226
|
+
space,
|
|
227
|
+
text,
|
|
228
|
+
thread,
|
|
229
|
+
attachments: upload.attachmentUploadToken ? [{
|
|
230
|
+
attachmentUploadToken: upload.attachmentUploadToken,
|
|
231
|
+
contentName: loaded.fileName
|
|
232
|
+
}] : void 0
|
|
233
|
+
}))?.messageName ?? "";
|
|
397
234
|
return {
|
|
398
|
-
messageId
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
contentName: loaded.fileName
|
|
406
|
-
}] : void 0
|
|
407
|
-
}))?.messageName ?? "",
|
|
408
|
-
chatId: space
|
|
235
|
+
messageId,
|
|
236
|
+
chatId: space,
|
|
237
|
+
receipt: createGoogleChatSendReceipt({
|
|
238
|
+
messageId,
|
|
239
|
+
chatId: space,
|
|
240
|
+
kind: "media"
|
|
241
|
+
})
|
|
409
242
|
};
|
|
410
243
|
}
|
|
411
244
|
}
|
|
412
245
|
};
|
|
246
|
+
const googlechatMessageAdapter = defineChannelMessageAdapter({
|
|
247
|
+
id: "googlechat",
|
|
248
|
+
durableFinal: { capabilities: {
|
|
249
|
+
text: true,
|
|
250
|
+
media: true,
|
|
251
|
+
thread: true,
|
|
252
|
+
messageSendingHooks: true
|
|
253
|
+
} },
|
|
254
|
+
send: {
|
|
255
|
+
text: googlechatOutboundAdapter.attachedResults.sendText,
|
|
256
|
+
media: googlechatOutboundAdapter.attachedResults.sendMedia
|
|
257
|
+
}
|
|
258
|
+
});
|
|
413
259
|
//#endregion
|
|
414
260
|
//#region extensions/googlechat/src/doctor.ts
|
|
415
261
|
function asObjectRecord(value) {
|
|
@@ -449,7 +295,7 @@ const collectGoogleChatMutableAllowlistWarnings = createDangerousNameMatchingMut
|
|
|
449
295
|
});
|
|
450
296
|
//#endregion
|
|
451
297
|
//#region extensions/googlechat/src/gateway.ts
|
|
452
|
-
const loadGoogleChatChannelRuntime$1 = createLazyRuntimeNamedExport(() => import("./channel.runtime-
|
|
298
|
+
const loadGoogleChatChannelRuntime$1 = createLazyRuntimeNamedExport(() => import("./channel.runtime-CK4QbJkn.js"), "googleChatChannelRuntime");
|
|
453
299
|
async function startGoogleChatGatewayAccount(ctx) {
|
|
454
300
|
const account = ctx.account;
|
|
455
301
|
const statusSink = createAccountStatusSink({
|
|
@@ -489,7 +335,7 @@ async function startGoogleChatGatewayAccount(ctx) {
|
|
|
489
335
|
}
|
|
490
336
|
//#endregion
|
|
491
337
|
//#region extensions/googlechat/src/channel.ts
|
|
492
|
-
const loadGoogleChatChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-
|
|
338
|
+
const loadGoogleChatChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-CK4QbJkn.js"), "googleChatChannelRuntime");
|
|
493
339
|
const meta = {
|
|
494
340
|
id: "googlechat",
|
|
495
341
|
label: "Google Chat",
|
|
@@ -527,9 +373,25 @@ const googleChatConfigAdapter = createScopedChannelConfigAdapter({
|
|
|
527
373
|
resolveDefaultTo: (account) => account.config.defaultTo
|
|
528
374
|
});
|
|
529
375
|
const googlechatActions = {
|
|
530
|
-
describeMessageTool: (
|
|
531
|
-
|
|
376
|
+
describeMessageTool: ({ cfg, accountId }) => {
|
|
377
|
+
const accounts = accountId ? [resolveGoogleChatAccount({
|
|
378
|
+
cfg,
|
|
379
|
+
accountId
|
|
380
|
+
})].filter((account) => account.enabled && account.credentialSource !== "none") : listGoogleChatAccountIds(cfg).map((id) => resolveGoogleChatAccount({
|
|
381
|
+
cfg,
|
|
382
|
+
accountId: id
|
|
383
|
+
})).filter((account) => account.enabled && account.credentialSource !== "none");
|
|
384
|
+
if (accounts.length === 0) return null;
|
|
385
|
+
const actions = new Set(["send", "upload-file"]);
|
|
386
|
+
if (accounts.some((account) => account.config.actions?.reactions !== false)) {
|
|
387
|
+
actions.add("react");
|
|
388
|
+
actions.add("reactions");
|
|
389
|
+
}
|
|
390
|
+
return { actions: Array.from(actions) };
|
|
391
|
+
},
|
|
392
|
+
extractToolSend: ({ args }) => extractToolSend(args, "sendMessage"),
|
|
532
393
|
handleAction: async (ctx) => {
|
|
394
|
+
const { googlechatMessageActions } = await import("./actions-D-PNwmYx.js");
|
|
533
395
|
if (!googlechatMessageActions.handleAction) throw new Error("Google Chat actions are not available.");
|
|
534
396
|
return await googlechatMessageActions.handleAction(ctx);
|
|
535
397
|
}
|
|
@@ -589,6 +451,7 @@ const googlechatPlugin = createChatChannelPlugin({
|
|
|
589
451
|
}
|
|
590
452
|
},
|
|
591
453
|
directory: googlechatDirectoryAdapter,
|
|
454
|
+
message: googlechatMessageAdapter,
|
|
592
455
|
resolver: { resolveTargets: async ({ inputs, kind }) => {
|
|
593
456
|
return inputs.map((input) => {
|
|
594
457
|
const normalized = normalizeGoogleChatTarget(input);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as buildChannelConfigSchema, r as GoogleChatConfigSchema } from "./runtime-api-
|
|
1
|
+
import { a as buildChannelConfigSchema, r as GoogleChatConfigSchema } from "./runtime-api-DMEzhesS.js";
|
|
2
2
|
//#region extensions/googlechat/src/config-schema.ts
|
|
3
3
|
const GoogleChatChannelConfigSchema = buildChannelConfigSchema(GoogleChatConfigSchema);
|
|
4
4
|
//#endregion
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as googlechatPlugin } from "./channel-
|
|
1
|
+
import { t as googlechatPlugin } from "./channel-9lvRWX6T.js";
|
|
2
2
|
export { googlechatPlugin };
|