openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
264 lines (263 loc) • 10.5 kB
JavaScript
import { t as DEFAULT_ACCOUNT_ID } from "./account-id-Df9e41E6.js";
import { r as buildChannelConfigSchema } from "./config-schema-CO2ikh7C.js";
import { i as createLazyRuntimeNamedExport } from "./lazy-runtime-D-7_JraP.js";
import { i as createChatChannelPlugin } from "./core-DSxVv-v1.js";
import "./channel-core-IukkNCd-.js";
import { i as runPassiveAccountLifecycle, t as createAccountStatusSink } from "./channel-lifecycle.core-Bfh0_sXw.js";
import { n as createDangerousNameMatchingMutableAllowlistWarningCollector } from "./channel-policy-CIW58SA5.js";
import { t as CHANNEL_APPROVAL_NATIVE_RUNTIME_CONTEXT_CAPABILITY } from "./approval-handler-adapter-runtime-DLWtIqHq.js";
import { r as registerChannelRuntimeContext } from "./channel-runtime-context-Bx08uB94.js";
import "./channel-outbound-B3_Zy-kG.js";
import { d as createDefaultChannelRuntimeState, u as createComputedAccountStatusAdapter } from "./status-helpers-BevxX6Pu.js";
import { n as GoogleChatConfigSchema } from "./bundled-channel-config-schema-DwZyvOaO.js";
import { n as buildPassiveProbedChannelStatusSummary } from "./extension-shared-B8fkO3TV.js";
import { t as extractToolSend } from "./tool-send-DzTXHBeR.js";
import { i as resolveGoogleChatAccount, n as listGoogleChatAccountIds } from "./accounts-BedKEwKe.js";
import { n as isGoogleChatUserTarget, r as normalizeGoogleChatTarget, t as isGoogleChatSpaceTarget } from "./targets-BIe3h2UJ.js";
import { i as shouldSuppressLocalGoogleChatExecApprovalPrompt, n as isGoogleChatNativeApprovalClientEnabled, t as googleChatApprovalCapability } from "./approval-native-ByN6UwCu.js";
import { n as createGoogleChatPluginBase, t as GOOGLECHAT_CHANNEL_ID } from "./channel-base-D9bH8n7T.js";
import { a as googlechatPairingTextAdapter, i as googlechatOutboundAdapter, n as googlechatGroupsAdapter, o as googlechatSecurityAdapter, r as googlechatMessageAdapter, s as googlechatThreadingAdapter, t as googlechatDirectoryAdapter } from "./channel.adapters-CZ1j4YOQ.js";
import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-B06pP0v1.js";
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-BmNerIOL.js";
//#region extensions/googlechat/src/doctor.ts
function asObjectRecord(value) {
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
}
function isGoogleChatMutableAllowEntry(raw) {
const text = raw.trim();
if (!text || text === "*") return false;
const withoutPrefix = text.replace(/^(googlechat|google-chat|gchat):/i, "").trim();
if (!withoutPrefix) return false;
return withoutPrefix.replace(/^users\//i, "").includes("@");
}
const collectGoogleChatMutableAllowlistWarnings = createDangerousNameMatchingMutableAllowlistWarningCollector({
channel: "googlechat",
detector: isGoogleChatMutableAllowEntry,
collectLists: (scope) => {
const lists = [{
pathLabel: `${scope.prefix}.groupAllowFrom`,
list: scope.account.groupAllowFrom
}];
const dm = asObjectRecord(scope.account.dm);
if (dm) lists.push({
pathLabel: `${scope.prefix}.dm.allowFrom`,
list: dm.allowFrom
});
const groups = asObjectRecord(scope.account.groups);
if (groups) for (const [groupKey, groupRaw] of Object.entries(groups)) {
const group = asObjectRecord(groupRaw);
if (!group) continue;
lists.push({
pathLabel: `${scope.prefix}.groups.${groupKey}.users`,
list: group.users
});
}
return lists;
}
});
//#endregion
//#region extensions/googlechat/src/gateway.ts
const loadGoogleChatChannelRuntime$1 = createLazyRuntimeNamedExport(() => import("./channel.runtime-DtxTFBoI.js"), "googleChatChannelRuntime");
async function startGoogleChatGatewayAccount(ctx) {
const account = ctx.account;
const statusSink = createAccountStatusSink({
accountId: account.accountId,
setStatus: ctx.setStatus
});
ctx.log?.info?.(`[${account.accountId}] starting Google Chat webhook`);
const { resolveGoogleChatWebhookPath, startGoogleChatMonitor } = await loadGoogleChatChannelRuntime$1();
statusSink({
running: true,
lastStartAt: Date.now(),
webhookPath: resolveGoogleChatWebhookPath({ account }),
audienceType: account.config.audienceType,
audience: account.config.audience
});
if (isGoogleChatNativeApprovalClientEnabled({
cfg: ctx.cfg,
accountId: account.accountId
})) registerChannelRuntimeContext({
channelRuntime: ctx.channelRuntime,
channelId: "googlechat",
accountId: account.accountId,
capability: CHANNEL_APPROVAL_NATIVE_RUNTIME_CONTEXT_CAPABILITY,
context: { account },
abortSignal: ctx.abortSignal
});
await runPassiveAccountLifecycle({
abortSignal: ctx.abortSignal,
start: async () => await startGoogleChatMonitor({
account,
config: ctx.cfg,
runtime: ctx.runtime,
abortSignal: ctx.abortSignal,
webhookPath: account.config.webhookPath,
webhookUrl: account.config.webhookUrl,
statusSink
}),
stop: async (unregister) => {
unregister?.();
},
onStop: async () => {
statusSink({
running: false,
lastStopAt: Date.now()
});
}
});
}
//#endregion
//#region extensions/googlechat/src/channel.ts
const loadGoogleChatChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-DtxTFBoI.js"), "googleChatChannelRuntime");
const googlechatActions = {
describeMessageTool: ({ cfg, accountId }) => {
const accounts = accountId ? [resolveGoogleChatAccount({
cfg,
accountId
})].filter((account) => account.enabled && account.credentialSource !== "none") : listGoogleChatAccountIds(cfg).map((id) => resolveGoogleChatAccount({
cfg,
accountId: id
})).filter((account) => account.enabled && account.credentialSource !== "none");
if (accounts.length === 0) return null;
const actions = new Set(["send", "upload-file"]);
if (accounts.some((account) => account.config.actions?.reactions !== false)) {
actions.add("react");
actions.add("reactions");
}
return { actions: Array.from(actions) };
},
extractToolSend: ({ args }) => extractToolSend(args, "sendMessage"),
handleAction: async (ctx) => {
const { googlechatMessageActions } = await import("./actions-DAjUsnbQ.js");
if (!googlechatMessageActions.handleAction) throw new Error("Google Chat actions are not available.");
return await googlechatMessageActions.handleAction(ctx);
}
};
const googlechatPlugin = createChatChannelPlugin({
base: {
...createGoogleChatPluginBase({ configSchema: buildChannelConfigSchema(GoogleChatConfigSchema) }),
approvalCapability: googleChatApprovalCapability,
secrets: {
secretTargetRegistryEntries,
collectRuntimeConfigAssignments
},
groups: googlechatGroupsAdapter,
messaging: {
targetPrefixes: [
"googlechat",
"google-chat",
"gchat"
],
normalizeTarget: normalizeGoogleChatTarget,
targetResolver: {
looksLikeId: (raw, normalized) => {
const value = normalized ?? raw.trim();
return isGoogleChatSpaceTarget(value) || isGoogleChatUserTarget(value);
},
hint: "<spaces/{space}|users/{user}>"
}
},
directory: googlechatDirectoryAdapter,
message: googlechatMessageAdapter,
resolver: { resolveTargets: async ({ inputs, kind }) => {
return inputs.map((input) => {
const normalized = normalizeGoogleChatTarget(input);
if (!normalized) return {
input,
resolved: false,
note: "empty target"
};
if (kind === "user" && isGoogleChatUserTarget(normalized)) return {
input,
resolved: true,
id: normalized
};
if (kind === "group" && isGoogleChatSpaceTarget(normalized)) return {
input,
resolved: true,
id: normalized
};
return {
input,
resolved: false,
note: "use spaces/{space} or users/{user}"
};
});
} },
actions: googlechatActions,
doctor: {
dmAllowFromMode: "nestedOnly",
groupModel: "route",
groupAllowFromFallbackToAllowFrom: false,
warnOnEmptyGroupSenderAllowlist: false,
legacyConfigRules,
normalizeCompatibilityConfig,
collectMutableAllowlistWarnings: collectGoogleChatMutableAllowlistWarnings
},
status: createComputedAccountStatusAdapter({
defaultRuntime: createDefaultChannelRuntimeState(DEFAULT_ACCOUNT_ID),
collectStatusIssues: (accounts) => accounts.flatMap((entry) => {
const accountId = entry.accountId ?? "default";
const enabled = entry.enabled !== false;
const configured = entry.configured === true;
if (!enabled || !configured) return [];
const issues = [];
if (!entry.audience) issues.push({
channel: GOOGLECHAT_CHANNEL_ID,
accountId,
kind: "config",
message: "Google Chat audience is missing (set channels.googlechat.audience).",
fix: "Set channels.googlechat.audienceType and channels.googlechat.audience."
});
if (!entry.audienceType) issues.push({
channel: GOOGLECHAT_CHANNEL_ID,
accountId,
kind: "config",
message: "Google Chat audienceType is missing (app-url or project-number).",
fix: "Set channels.googlechat.audienceType and channels.googlechat.audience."
});
return issues;
}),
buildChannelSummary: ({ snapshot }) => buildPassiveProbedChannelStatusSummary(snapshot, {
credentialSource: snapshot.credentialSource ?? "none",
audienceType: snapshot.audienceType ?? null,
audience: snapshot.audience ?? null,
webhookPath: snapshot.webhookPath ?? null,
webhookUrl: snapshot.webhookUrl ?? null
}),
probeAccount: async ({ account }) => (await loadGoogleChatChannelRuntime()).probeGoogleChat(account),
resolveAccountSnapshot: ({ account }) => ({
accountId: account.accountId,
name: account.name,
enabled: account.enabled,
configured: account.credentialSource !== "none",
extra: {
credentialSource: account.credentialSource,
audienceType: account.config.audienceType,
audience: account.config.audience,
webhookPath: account.config.webhookPath,
webhookUrl: account.config.webhookUrl,
dmPolicy: account.config.dm?.policy ?? "pairing"
}
})
}),
gateway: { startAccount: startGoogleChatGatewayAccount }
},
pairing: { text: googlechatPairingTextAdapter },
security: googlechatSecurityAdapter,
threading: googlechatThreadingAdapter,
outbound: {
...googlechatOutboundAdapter,
base: {
...googlechatOutboundAdapter.base,
shouldSuppressLocalPayloadPrompt: ({ cfg, accountId, payload, hint }) => shouldSuppressLocalGoogleChatExecApprovalPrompt({
cfg,
accountId,
payload,
hint
})
}
}
});
//#endregion
export { googlechatPlugin as t };