openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
201 lines (200 loc) • 9.46 kB
JavaScript
import { l as normalizeOptionalString } from "./string-coerce-1VuiLaaR.mjs";
import { y as uniqueStrings } from "./string-normalization-D6DKCpwE.mjs";
import { r as defaultRuntime } from "./runtime-BRg2NubB.mjs";
import { t as formatErrorMessage } from "./errors-BvOkmQM5.mjs";
import { t as normalizeAnyChannelId } from "./registry-normalize-DKVgg-js.mjs";
import { D as getPreparedMessageToolCatalog } from "./runtime-U4i1bMh7.mjs";
import "./registry-DvTPWA3B.mjs";
import { n as getLoadedChannelPlugin, r as listChannelPlugins, t as getChannelPlugin } from "./registry-Bcrk1FVy.mjs";
import "./plugins-BXkKReMp.mjs";
import { t as loadOptionalBundledChannelPublicArtifact } from "./optional-public-artifact-C1gsSm0z.mjs";
import { Type } from "typebox";
//#region src/channels/plugins/message-tool-api.ts
/**
* Resolves a bundled channel's message-tool discovery adapter without loading the full plugin.
*/
function resolveBundledChannelMessageToolDiscoveryAdapter(channelId) {
const describeMessageTool = loadOptionalBundledChannelPublicArtifact({
channelId,
artifactBasename: "message-tool-api.js"
})?.describeMessageTool;
if (typeof describeMessageTool !== "function") return;
return { describeMessageTool };
}
//#endregion
//#region src/channels/plugins/message-action-discovery.ts
/** Lists message-action adapters from the caller's exact prepared registry. */
const listMessageActionDiscoveryChannels = (preparedMessageToolCatalog) => (preparedMessageToolCatalog ?? getPreparedMessageToolCatalog())?.channels ?? listChannelPlugins();
const loggedMessageActionErrors = /* @__PURE__ */ new Set();
function resolveMessageActionDiscoveryChannelId(raw) {
return normalizeAnyChannelId(raw) ?? normalizeOptionalString(raw);
}
function createMessageActionDiscoveryContext(params) {
const currentChannelProvider = resolveMessageActionDiscoveryChannelId(params.channel ?? params.currentChannelProvider);
return {
cfg: params.cfg ?? {},
...params.chatType ? { chatType: params.chatType } : {},
currentChannelId: params.currentChannelId,
currentChannelProvider,
currentThreadTs: params.currentThreadTs,
currentMessageId: params.currentMessageId,
accountId: params.accountId,
sessionKey: params.sessionKey,
sessionId: params.sessionId,
agentId: params.agentId,
requesterSenderId: params.requesterSenderId,
senderIsOwner: params.senderIsOwner
};
}
function describeMessageToolSafely(params) {
try {
return params.describeMessageTool(params.context) ?? null;
} catch (error) {
const message = formatErrorMessage(error);
const key = `${params.pluginId}:describeMessageTool:${message}`;
if (!loggedMessageActionErrors.has(key)) {
loggedMessageActionErrors.add(key);
const stack = error instanceof Error && error.stack ? error.stack : null;
defaultRuntime.error?.(`[message-action-discovery] ${params.pluginId}.actions.describeMessageTool failed: ${stack ?? message}`);
}
return null;
}
}
function normalizeMessageToolMediaSourceParams(mediaSourceParams, action) {
if (Array.isArray(mediaSourceParams)) return mediaSourceParams;
if (!mediaSourceParams || typeof mediaSourceParams !== "object") return [];
const scopedMediaSourceParams = mediaSourceParams;
if (action) {
const scoped = scopedMediaSourceParams[action];
return Array.isArray(scoped) ? scoped : [];
}
return Object.values(scopedMediaSourceParams).flatMap((scoped) => Array.isArray(scoped) ? scoped : []);
}
function resolveCurrentChannelMessageToolDiscoveryAdapter(channel, preparedMessageToolCatalog) {
const channelId = resolveMessageActionDiscoveryChannelId(channel);
if (!channelId) return null;
const catalog = preparedMessageToolCatalog ?? getPreparedMessageToolCatalog();
const prepared = catalog?.getChannel(channelId);
if (prepared?.actions) return {
pluginId: prepared.id,
actions: prepared.actions
};
if (!catalog) {
const loadedPlugin = getLoadedChannelPlugin(channelId);
if (loadedPlugin?.actions) return {
pluginId: loadedPlugin.id,
actions: loadedPlugin.actions
};
}
const bundledActions = resolveBundledChannelMessageToolDiscoveryAdapter(channelId);
if (bundledActions) return {
pluginId: channelId,
actions: bundledActions
};
const plugin = catalog ? void 0 : getChannelPlugin(channelId);
return plugin?.actions ? {
pluginId: plugin.id,
actions: plugin.actions
} : null;
}
function resolveMessageActionDiscoveryForPlugin(params) {
const adapter = params.actions;
const described = adapter ? describeMessageToolSafely({
pluginId: params.pluginId,
context: params.context,
describeMessageTool: adapter.describeMessageTool
}) : null;
const schema = params.includeSchema ? described?.schema : void 0;
return {
actions: params.includeActions && Array.isArray(described?.actions) ? [...described.actions] : [],
capabilities: params.includeCapabilities && Array.isArray(described?.capabilities) ? described.capabilities : [],
schemaContributions: schema ? Array.isArray(schema) ? schema : [schema] : [],
mediaSourceParams: normalizeMessageToolMediaSourceParams(described?.mediaSourceParams, params.action)
};
}
function listCrossChannelSchemaSupportedMessageActions(params) {
const resolved = resolveCurrentMessageActionDiscovery(params, {
includeActions: true,
includeSchema: true
});
if (!resolved) return [];
const schemaBlockedActions = /* @__PURE__ */ new Set();
for (const contribution of resolved.schemaContributions) {
if ((contribution.visibility ?? "current-channel") !== "current-channel") continue;
if (!Object.hasOwn(contribution, "actions")) return [];
const actions = contribution.actions;
if (!Array.isArray(actions)) return [];
for (const action of actions) schemaBlockedActions.add(action);
}
return resolved.actions.filter((action) => !schemaBlockedActions.has(action));
}
/**
* Merges schema properties while preserving the first plugin to define a key.
*/
function mergeToolSchemaProperties(target, source) {
if (!source) return;
for (const [name, schema] of Object.entries(source)) {
if (name in target) continue;
target[name] = Type.IsOptional(schema) ? schema : Type.Optional(schema);
}
}
function resolveChannelMessageToolSchemaProperties(params) {
const properties = {};
const currentChannel = resolveMessageActionDiscoveryChannelId(params.channel);
const discoveryBase = createMessageActionDiscoveryContext(params);
const contextForPlugin = (pluginId) => {
const contextualAccountId = !currentChannel || resolveMessageActionDiscoveryChannelId(pluginId) === currentChannel ? params.accountId : void 0;
return {
...discoveryBase,
accountId: params.resolveAccountIdForChannel ? params.resolveAccountIdForChannel(pluginId, contextualAccountId) : contextualAccountId
};
};
const seenPluginIds = /* @__PURE__ */ new Set();
const mergePluginSchema = (pluginId, actions) => {
for (const contribution of resolveMessageActionDiscoveryForPlugin({
pluginId,
actions,
context: contextForPlugin(pluginId),
includeSchema: true
}).schemaContributions) {
const visibility = contribution.visibility ?? "current-channel";
if (!currentChannel || visibility === "all-configured" || pluginId === currentChannel) mergeToolSchemaProperties(properties, contribution.properties);
}
};
const channels = listMessageActionDiscoveryChannels(params.preparedMessageToolCatalog);
for (const plugin of channels) {
if (!plugin.actions) continue;
seenPluginIds.add(plugin.id);
mergePluginSchema(plugin.id, plugin.actions);
}
if (currentChannel && !seenPluginIds.has(currentChannel)) {
const currentActions = resolveCurrentChannelMessageToolDiscoveryAdapter(currentChannel, params.preparedMessageToolCatalog);
if (currentActions?.actions) mergePluginSchema(currentActions.pluginId, currentActions.actions);
}
return properties;
}
function resolveCurrentMessageActionDiscovery(params, selection = {}) {
const pluginActions = resolveCurrentChannelMessageToolDiscoveryAdapter(params.channel, params.preparedMessageToolCatalog);
return pluginActions ? resolveMessageActionDiscoveryForPlugin({
...pluginActions,
context: createMessageActionDiscoveryContext(params),
action: params.action,
...selection
}) : null;
}
function resolveChannelMessageToolMediaSourceParamKeys(params) {
return uniqueStrings(resolveCurrentMessageActionDiscovery(params)?.mediaSourceParams ?? []);
}
function channelSupportsMessageCapability(cfg, capability, preparedMessageToolCatalog) {
return listMessageActionDiscoveryChannels(preparedMessageToolCatalog).map((plugin) => resolveMessageActionDiscoveryForPlugin({
pluginId: plugin.id,
actions: plugin.actions,
context: { cfg },
includeCapabilities: true
}).capabilities).some((pluginCapabilities) => pluginCapabilities.includes(capability));
}
function channelSupportsMessageCapabilityForChannel(params, capability) {
return resolveCurrentMessageActionDiscovery(params, { includeCapabilities: true })?.capabilities.includes(capability) ?? false;
}
//#endregion
export { listMessageActionDiscoveryChannels as a, resolveCurrentChannelMessageToolDiscoveryAdapter as c, listCrossChannelSchemaSupportedMessageActions as i, resolveMessageActionDiscoveryChannelId as l, channelSupportsMessageCapabilityForChannel as n, resolveChannelMessageToolMediaSourceParamKeys as o, createMessageActionDiscoveryContext as r, resolveChannelMessageToolSchemaProperties as s, channelSupportsMessageCapability as t, resolveMessageActionDiscoveryForPlugin as u };