UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

303 lines (302 loc) 11.2 kB
import { a as normalizeLowercaseStringOrEmpty, c as normalizeOptionalString, f as normalizeStringifiedOptionalString } from "./string-coerce-mnp54Vah.js"; import { t as formatDocsLink } from "./links-CsLBrRff.js"; import "./account-id-Df9e41E6.js"; import { s as createScopedChannelConfigAdapter, t as adaptScopedAccountAccessor } from "./channel-config-helpers-lj5quus3.js"; import "./string-coerce-runtime-CEGJWkQ_.js"; import { n as describeAccountSnapshot } from "./account-helpers-pcH3lGFY.js"; import { a as createSetupInputPresenceValidator, i as createPatchedAccountSetupAdapter, n as applySetupAccountConfigPatch, s as migrateBaseNameToDefaultAccount } from "./setup-helpers-DO5nSeNy.js"; import { n as formatNormalizedAllowFromEntries } from "./allow-from-DCaV3hzI.js"; import { t as createSetupTranslator } from "./i18n-7g_f4oaD.js"; import { Q as splitSetupEntries, d as createPromptParsedAllowFromForAccount, f as createStandardChannelSetupStatus, t as addWildcardAllowFrom, v as mergeAllowFromEntries } from "./setup-wizard-helpers-Dv-t1nb8.js"; import "./setup-DHfdBmUU.js"; import "./setup-runtime-BvLK-H0G.js"; import { a as resolveGoogleChatConfigAccessorAccount, i as resolveGoogleChatAccount, n as listGoogleChatAccountIds, r as resolveDefaultGoogleChatAccountId } from "./accounts-BedKEwKe.js"; const googlechatSetupAdapter = createPatchedAccountSetupAdapter({ channelKey: "googlechat", validateInput: createSetupInputPresenceValidator({ defaultAccountOnlyEnvError: "GOOGLE_CHAT_SERVICE_ACCOUNT env vars can only be used for the default account.", whenNotUseEnv: [{ someOf: ["token", "tokenFile"], message: "Google Chat requires --token (service account JSON) or --token-file." }] }), buildPatch: (input) => { const patch = input.useEnv ? {} : input.tokenFile ? { serviceAccountFile: input.tokenFile } : input.token ? { serviceAccount: input.token } : {}; const audienceType = input.audienceType?.trim(); const audience = input.audience?.trim(); const webhookPath = input.webhookPath?.trim(); const webhookUrl = input.webhookUrl?.trim(); return { ...patch, ...audienceType ? { audienceType } : {}, ...audience ? { audience } : {}, ...webhookPath ? { webhookPath } : {}, ...webhookUrl ? { webhookUrl } : {} }; } }); //#endregion //#region extensions/googlechat/src/setup-surface.ts const t = createSetupTranslator(); const channel = "googlechat"; const ENV_SERVICE_ACCOUNT = "GOOGLE_CHAT_SERVICE_ACCOUNT"; const ENV_SERVICE_ACCOUNT_FILE = "GOOGLE_CHAT_SERVICE_ACCOUNT_FILE"; const USE_ENV_FLAG = "__googlechatUseEnv"; const AUTH_METHOD_FLAG = "__googlechatAuthMethod"; const googlechatDmPolicy = { label: "Google Chat", channel, policyKey: "channels.googlechat.dm.policy", allowFromKey: "channels.googlechat.dm.allowFrom", resolveConfigKeys: (cfg, accountId) => (accountId ?? resolveDefaultGoogleChatAccountId(cfg)) !== "default" ? { policyKey: `channels.googlechat.accounts.${accountId ?? resolveDefaultGoogleChatAccountId(cfg)}.dm.policy`, allowFromKey: `channels.googlechat.accounts.${accountId ?? resolveDefaultGoogleChatAccountId(cfg)}.dm.allowFrom` } : { policyKey: "channels.googlechat.dm.policy", allowFromKey: "channels.googlechat.dm.allowFrom" }, getCurrent: (cfg, accountId) => resolveGoogleChatAccount({ cfg, accountId: accountId ?? resolveDefaultGoogleChatAccountId(cfg) }).config.dm?.policy ?? "pairing", setPolicy: (cfg, policy, accountId) => { const resolvedAccountId = accountId ?? resolveDefaultGoogleChatAccountId(cfg); const currentDm = resolveGoogleChatAccount({ cfg, accountId: resolvedAccountId }).config.dm; return applySetupAccountConfigPatch({ cfg, channelKey: channel, accountId: resolvedAccountId, patch: { dm: { ...currentDm, policy, ...policy === "open" ? { allowFrom: addWildcardAllowFrom(currentDm?.allowFrom) } : {} } } }); }, promptAllowFrom: createPromptParsedAllowFromForAccount({ defaultAccountId: resolveDefaultGoogleChatAccountId, message: t("wizard.googlechat.allowFromPrompt"), placeholder: "users/123456789, name@example.com", parseEntries: (raw) => ({ entries: mergeAllowFromEntries(void 0, splitSetupEntries(raw)) }), getExistingAllowFrom: ({ cfg, accountId }) => resolveGoogleChatAccount({ cfg, accountId }).config.dm?.allowFrom ?? [], applyAllowFrom: ({ cfg, accountId, allowFrom }) => applySetupAccountConfigPatch({ cfg, channelKey: channel, accountId, patch: { dm: { ...resolveGoogleChatAccount({ cfg, accountId }).config.dm, allowFrom } } }) }) }; function createServiceAccountTextInput(params) { return { inputKey: params.inputKey, message: params.message, placeholder: params.placeholder, shouldPrompt: ({ credentialValues }) => credentialValues[USE_ENV_FLAG] !== "1" && credentialValues[AUTH_METHOD_FLAG] === params.authMethod, validate: ({ value }) => normalizeStringifiedOptionalString(value) ? void 0 : "Required", normalizeValue: ({ value }) => normalizeStringifiedOptionalString(value) ?? "", applySet: async ({ cfg, accountId, value }) => applySetupAccountConfigPatch({ cfg, channelKey: channel, accountId, patch: { [params.patchKey]: value } }) }; } const googlechatSetupWizard = { channel, status: createStandardChannelSetupStatus({ channelLabel: "Google Chat", configuredLabel: t("wizard.channels.statusConfigured"), unconfiguredLabel: t("wizard.channels.statusNeedsServiceAccount"), configuredHint: t("wizard.channels.statusConfigured"), unconfiguredHint: t("wizard.channels.statusNeedsAuth"), includeStatusLine: true, resolveConfigured: ({ cfg, accountId }) => resolveGoogleChatAccount({ cfg, accountId }).credentialSource !== "none" }), introNote: { title: t("wizard.googlechat.setupTitle"), lines: [ t("wizard.googlechat.setupServiceAccount"), t("wizard.googlechat.setupScopes"), t("wizard.googlechat.setupAudience"), t("wizard.channels.docs", { link: formatDocsLink("/channels/googlechat", "googlechat") }) ] }, prepare: async ({ cfg, accountId, credentialValues, prompter }) => { if (accountId === "default" && (Boolean(process.env[ENV_SERVICE_ACCOUNT]) || Boolean(process.env[ENV_SERVICE_ACCOUNT_FILE]))) { if (await prompter.confirm({ message: t("wizard.googlechat.useEnvPrompt"), initialValue: true })) return { cfg: applySetupAccountConfigPatch({ cfg, channelKey: channel, accountId, patch: {} }), credentialValues: { ...credentialValues, [USE_ENV_FLAG]: "1" } }; } const method = await prompter.select({ message: t("wizard.googlechat.authMethod"), options: [{ value: "file", label: t("wizard.googlechat.serviceAccountFile") }, { value: "inline", label: t("wizard.googlechat.serviceAccountInline") }], initialValue: "file" }); return { credentialValues: { ...credentialValues, [USE_ENV_FLAG]: "0", [AUTH_METHOD_FLAG]: method } }; }, credentials: [], textInputs: [createServiceAccountTextInput({ inputKey: "tokenFile", message: t("wizard.googlechat.serviceAccountPath"), placeholder: "/path/to/service-account.json", authMethod: "file", patchKey: "serviceAccountFile" }), createServiceAccountTextInput({ inputKey: "token", message: t("wizard.googlechat.serviceAccountJson"), placeholder: "{\"type\":\"service_account\", ... }", authMethod: "inline", patchKey: "serviceAccount" })], finalize: async ({ cfg, accountId, prompter }) => { const account = resolveGoogleChatAccount({ cfg, accountId }); const audienceType = await prompter.select({ message: t("wizard.googlechat.webhookAudienceType"), options: [{ value: "app-url", label: t("wizard.googlechat.appUrlRecommended") }, { value: "project-number", label: t("wizard.googlechat.projectNumber") }], initialValue: account.config.audienceType === "project-number" ? "project-number" : "app-url" }); return { cfg: migrateBaseNameToDefaultAccount({ cfg: applySetupAccountConfigPatch({ cfg, channelKey: channel, accountId, patch: { audienceType, audience: normalizeOptionalString(await prompter.text({ message: audienceType === "project-number" ? t("wizard.googlechat.projectNumber") : t("wizard.googlechat.appUrl"), placeholder: audienceType === "project-number" ? "1234567890" : "https://your.host/googlechat", initialValue: account.config.audience || void 0, validate: (value) => normalizeStringifiedOptionalString(value) ? void 0 : t("common.required") })) ?? "" } }), channelKey: channel }) }; }, dmPolicy: googlechatDmPolicy }; //#endregion //#region extensions/googlechat/src/channel-base.ts const GOOGLECHAT_CHANNEL_ID = "googlechat"; const googlechatMeta = { id: GOOGLECHAT_CHANNEL_ID, label: "Google Chat", selectionLabel: "Google Chat (Chat API)", docsPath: "/channels/googlechat", docsLabel: "googlechat", blurb: "Google Workspace Chat app with HTTP webhook.", aliases: ["gchat", "google-chat"], order: 55, detailLabel: "Google Chat", systemImage: "message.badge", markdownCapable: true }; const formatGoogleChatAllowFromEntry = (entry) => normalizeLowercaseStringOrEmpty(entry.trim().replace(/^(googlechat|google-chat|gchat):/i, "").replace(/^user:/i, "").replace(/^users\//i, "")); const googleChatConfigAdapter = createScopedChannelConfigAdapter({ sectionKey: GOOGLECHAT_CHANNEL_ID, listAccountIds: listGoogleChatAccountIds, resolveAccount: adaptScopedAccountAccessor(resolveGoogleChatAccount), resolveAccessorAccount: resolveGoogleChatConfigAccessorAccount, defaultAccountId: resolveDefaultGoogleChatAccountId, clearBaseFields: [ "serviceAccount", "serviceAccountFile", "audienceType", "audience", "webhookPath", "webhookUrl", "botUser", "name" ], resolveAllowFrom: (account) => account.config.dm?.allowFrom, formatAllowFrom: (allowFrom) => formatNormalizedAllowFromEntries({ allowFrom, normalizeEntry: formatGoogleChatAllowFromEntry }), resolveDefaultTo: (account) => account.config.defaultTo }); function createGoogleChatPluginBase(params = {}) { return { id: GOOGLECHAT_CHANNEL_ID, meta: { ...googlechatMeta }, setup: googlechatSetupAdapter, setupWizard: googlechatSetupWizard, capabilities: { chatTypes: [ "direct", "group", "thread" ], reactions: true, threads: true, media: true, nativeCommands: false, blockStreaming: true }, streaming: { blockStreamingCoalesceDefaults: { minChars: 1500, idleMs: 1e3 } }, reload: { configPrefixes: ["channels.googlechat"] }, ...params.configSchema ? { configSchema: params.configSchema } : {}, config: { ...googleChatConfigAdapter, isConfigured: (account) => account.credentialSource !== "none", describeAccount: (account) => describeAccountSnapshot({ account, configured: account.credentialSource !== "none", extra: { credentialSource: account.credentialSource } }) } }; } //#endregion export { googlechatSetupAdapter as a, googlechatSetupWizard as i, createGoogleChatPluginBase as n, formatGoogleChatAllowFromEntry as r, GOOGLECHAT_CHANNEL_ID as t };