openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
313 lines (312 loc) • 15.2 kB
JavaScript
import { l as normalizeOptionalString } from "./string-coerce-1VuiLaaR.mjs";
import { t as formatErrorMessage } from "./errors-O33D01XW.mjs";
import { n as normalizeAgentId } from "./agent-id-D1-Q6vR4.mjs";
import { n as buildAgentMainSessionKey } from "./session-key-CmZ4o9-l.mjs";
import "./session-key-C09ow4h0.mjs";
import { r as normalizeOptionalAccountId } from "./account-id-DbRsdayc.mjs";
import { t as normalizeRouteBindingChannelId } from "./binding-scope-uGqaW78p.mjs";
import { t as INTERNAL_MESSAGE_CHANNEL } from "./message-channel-constants-B3vfipkP.mjs";
import { n as normalizeMessageChannel } from "./message-channel-core-CqBAHB04.mjs";
import { n as isGatewayMessageChannel, t as isDeliverableMessageChannel } from "./message-channel-normalize-DeTO1ikE.mjs";
import "./message-channel-j-k-Nup3.mjs";
import { n as assertAgentDatabaseAdmitted } from "./agent-database-admission-dWNS6Rcs.mjs";
import { c as getReplyPayloadMetadata } from "./reply-payload-NzglYOOT.mjs";
import { r as listConfiguredBindings, t as isRouteBinding } from "./bindings-Cw_QSeBA.mjs";
import { t as resolveSessionDeliveryTarget } from "./targets-session-BP-SgkrG.mjs";
import { i as resolveChannelTarget } from "./target-resolver-zetQFKNJ.mjs";
import { i as serializeDurableMessagePayloadOutcomes } from "./send-CqAjSzNt.mjs";
import { r as resolveOutboundChannelPlugin } from "./channel-resolution-D9vhAPIJ.mjs";
import "./runtime-BZREclVS.mjs";
import { i as resolveChannelDefaultAccountId } from "./helpers-Bm4RKejp.mjs";
import { a as resolveOutboundSessionRoute } from "./outbound-session-CZWaNgO2.mjs";
import { a as resolveOutboundTarget } from "./targets-BUerMF9S.mjs";
import { t as hasAnyNonEmptyString } from "./delivery-evidence-values-jHsxUGXm.mjs";
//#region src/infra/outbound/agent-delivery.ts
function resolveAgentDeliveryPlan(params) {
const requestedRaw = normalizeOptionalString(params.requestedChannel) ?? "";
const requestedChannel = (requestedRaw ? normalizeMessageChannel(requestedRaw) : void 0) || "last";
const explicitTo = normalizeOptionalString(params.explicitTo);
const normalizedTurnSource = params.turnSourceChannel ? normalizeMessageChannel(params.turnSourceChannel) : void 0;
const turnSourceChannel = normalizedTurnSource && isDeliverableMessageChannel(normalizedTurnSource) ? normalizedTurnSource : void 0;
const turnSourceTo = normalizeOptionalString(params.turnSourceTo);
const turnSourceAccountId = normalizeOptionalAccountId(params.turnSourceAccountId);
const turnSourceThreadId = params.turnSourceThreadId != null && params.turnSourceThreadId !== "" ? params.turnSourceThreadId : void 0;
const baseDelivery = resolveSessionDeliveryTarget({
entry: params.sessionEntry,
requestedChannel: requestedChannel === "webchat" ? "last" : requestedChannel,
explicitTo,
explicitThreadId: params.explicitThreadId,
turnSourceChannel,
turnSourceTo,
turnSourceAccountId,
turnSourceThreadId
});
const resolvedChannel = (() => {
if (requestedChannel === "webchat") return INTERNAL_MESSAGE_CHANNEL;
if (requestedChannel !== "last" && isGatewayMessageChannel(requestedChannel)) return requestedChannel;
if (baseDelivery.channel && baseDelivery.channel !== "webchat") return baseDelivery.channel;
return INTERNAL_MESSAGE_CHANNEL;
})();
const deliveryTargetMode = explicitTo ? "explicit" : isDeliverableMessageChannel(resolvedChannel) ? "implicit" : void 0;
const resolvedAccountId = normalizeOptionalAccountId(params.accountId) ?? (deliveryTargetMode === "implicit" ? baseDelivery.accountId : void 0);
let resolvedTo = explicitTo;
if (!resolvedTo && isDeliverableMessageChannel(resolvedChannel) && resolvedChannel === baseDelivery.lastChannel) resolvedTo = baseDelivery.lastTo;
return {
baseDelivery,
resolvedChannel,
resolvedTo,
resolvedAccountId,
resolvedThreadId: baseDelivery.threadId,
deliveryTargetMode
};
}
async function resolveAgentDeliveryPlanWithSessionRoute(params) {
assertAgentDatabaseAdmitted(params.agentId);
const plan = resolveAgentDeliveryPlan(params);
const { resolvedChannel } = plan;
if (!params.wantsDelivery || !isDeliverableMessageChannel(resolvedChannel)) return plan;
const plugin = params.preparedPlugin ?? resolveOutboundChannelPlugin({
channel: resolvedChannel,
cfg: params.cfg,
agentId: params.agentId,
allowBootstrap: true
});
if (!plugin) return plan;
const pluginPlan = {
...plan,
plugin
};
const hasPluginSessionRoute = Boolean(plugin.messaging?.resolveOutboundSessionRoute);
const hasPluginTargetResolver = Boolean(plugin.messaging?.targetResolver);
const hasPluginConcreteTargetResolver = Boolean(plugin.messaging?.targetResolver?.resolveTarget);
if (!hasPluginSessionRoute && !hasPluginTargetResolver && params.sessionRouteMode !== "allow-fallback") return pluginPlan;
const resolvedAccountId = pluginPlan.resolvedAccountId ?? (params.sessionRouteMode === "allow-fallback" ? resolveChannelDefaultAccountId({
plugin,
cfg: params.cfg
}) : void 0);
const routedPlan = resolvedAccountId === pluginPlan.resolvedAccountId ? pluginPlan : {
...pluginPlan,
resolvedAccountId
};
const normalizedTarget = resolveOutboundTarget({
channel: resolvedChannel,
plugin,
to: routedPlan.resolvedTo,
cfg: params.cfg,
accountId: routedPlan.resolvedAccountId,
mode: routedPlan.deliveryTargetMode ?? "explicit"
});
const targetInput = normalizedTarget.ok ? normalizedTarget.to : routedPlan.resolvedTo;
if (!targetInput) return normalizedTarget.ok ? routedPlan : {
...routedPlan,
targetResolutionError: normalizedTarget.error
};
const resolvedTarget = await resolveChannelTarget({
cfg: params.cfg,
channel: resolvedChannel,
input: targetInput,
accountId: routedPlan.resolvedAccountId,
unknownTargetMode: hasPluginConcreteTargetResolver ? "error" : "normalized",
plugin
});
if (!resolvedTarget.ok) return {
...routedPlan,
targetResolutionError: resolvedTarget.error
};
if (!normalizedTarget.ok && resolvedTarget.target.resolutionSource === "normalized") return {
...routedPlan,
targetResolutionError: normalizedTarget.error
};
const sessionRouteTarget = resolvedTarget.target.to;
const resolvedSessionRouteTarget = !normalizedTarget.ok || normalizedTarget.to !== resolvedTarget.target.to || resolvedTarget.target.resolutionSource === "directory" ? resolvedTarget.target : void 0;
const resolvedPlan = {
...routedPlan,
resolvedTo: sessionRouteTarget
};
if (!hasPluginSessionRoute && params.sessionRouteMode !== "allow-fallback") return resolvedPlan;
const explicitThreadId = params.explicitThreadId != null && params.explicitThreadId !== "" ? params.explicitThreadId : void 0;
const requestedThreadId = resolvedPlan.deliveryTargetMode === "explicit" ? explicitThreadId : resolvedPlan.resolvedThreadId;
const route = await resolveOutboundSessionRoute({
cfg: params.cfg,
channel: resolvedChannel,
plugin,
agentId: params.agentId,
accountId: routedPlan.resolvedAccountId,
target: sessionRouteTarget,
...resolvedSessionRouteTarget ? { resolvedTarget: resolvedSessionRouteTarget } : {},
currentSessionKey: params.currentSessionKey,
threadId: requestedThreadId
}).catch(() => null);
const globalDmScope = params.cfg.session?.dmScope ?? "main";
const knownNonExactRoute = params.sessionRouteMode === "allow-fallback" && (route?.recipientSessionExact === false || route?.recipientSessionExact === "direct-alias");
const canonicalMainSessionKey = buildAgentMainSessionKey({
agentId: params.agentId,
mainKey: params.cfg.session?.mainKey
});
const usesCanonicalMainSession = route?.recipientSessionExact === "direct-alias" && route.chatType === "direct" && route.sessionKey === route.baseSessionKey && route.sessionKey === canonicalMainSessionKey && globalDmScope === "main" && !listConfiguredBindings(params.cfg).some((binding) => isRouteBinding(binding) && binding.session?.dmScope !== void 0 && binding.session.dmScope !== "main" && normalizeRouteBindingChannelId(binding.match.channel) === resolvedChannel);
const usesIsolatedDeliveryIdentity = route?.recipientSessionExact === "delivery-identity" && route.baseSessionKey !== canonicalMainSessionKey && route.baseSessionKey.startsWith(`agent:${normalizeAgentId(params.agentId)}:${resolvedChannel}:`) && (route.sessionKey === route.baseSessionKey || route.sessionKey.startsWith(`${route.baseSessionKey}:`));
const selectedRoute = route && (route.recipientSessionExact === "delivery-identity" ? usesIsolatedDeliveryIdentity : !knownNonExactRoute || usesCanonicalMainSession) ? route : null;
if (!selectedRoute) {
if (resolvedSessionRouteTarget) return {
...resolvedPlan,
resolvedTo: resolvedSessionRouteTarget.to,
resolvedThreadId: requestedThreadId
};
return resolvedPlan;
}
return {
...resolvedPlan,
resolvedSessionKey: selectedRoute.sessionKey,
resolvedTo: hasPluginSessionRoute ? selectedRoute.to : resolvedSessionRouteTarget?.to ?? sessionRouteTarget,
resolvedThreadId: selectedRoute.threadId ?? requestedThreadId
};
}
/** Resolves an explicit recipient into its canonical or stable provider-owned session. */
async function resolveAgentExplicitRecipientSession(params) {
const plan = await resolveAgentDeliveryPlanWithSessionRoute({
cfg: params.cfg,
agentId: params.agentId,
requestedChannel: params.channel,
explicitTo: params.to,
explicitThreadId: params.threadId,
accountId: params.accountId,
wantsDelivery: true,
sessionRouteMode: "allow-fallback"
});
if (!plan.resolvedSessionKey && !plan.targetResolutionError) return { error: /* @__PURE__ */ new Error(`Unable to resolve a session route for channel "${params.channel}"`) };
return {
sessionKey: plan.resolvedSessionKey,
channel: plan.resolvedChannel,
to: plan.resolvedTo,
accountId: plan.resolvedAccountId,
threadId: plan.resolvedThreadId,
error: plan.targetResolutionError
};
}
function resolveAgentOutboundTarget(params) {
const targetMode = params.targetMode ?? params.plan.deliveryTargetMode ?? (params.plan.resolvedTo ? "explicit" : "implicit");
if (params.plan.targetResolutionError) return {
resolvedTarget: {
ok: false,
error: params.plan.targetResolutionError
},
resolvedTo: void 0,
targetMode
};
if (!isDeliverableMessageChannel(params.plan.resolvedChannel) || params.validateExplicitTarget !== true && params.plan.resolvedTo) return {
resolvedTarget: null,
resolvedTo: params.plan.resolvedTo,
targetMode
};
const resolvedTarget = resolveOutboundTarget({
channel: params.plan.resolvedChannel,
...params.plan.plugin ? { plugin: params.plan.plugin } : {},
to: params.plan.resolvedTo,
cfg: params.cfg,
accountId: params.plan.resolvedAccountId,
mode: targetMode
});
return {
resolvedTarget,
resolvedTo: resolvedTarget.ok ? resolvedTarget.to : params.plan.resolvedTo,
targetMode
};
}
//#endregion
//#region src/agents/command/delivery-result.ts
function hasNonEmptyArray(value) {
return Array.isArray(value) && value.length > 0;
}
function buildDeliveryResult(params) {
const successfulCronAdds = params.result.successfulCronAdds;
const hasSuccessfulCronAdds = typeof successfulCronAdds === "number" && Number.isFinite(successfulCronAdds) && successfulCronAdds > 0;
return {
payloads: params.payloads,
meta: params.meta,
...params.result.didSendViaMessagingTool === true ? { didSendViaMessagingTool: true } : {},
...params.result.didDeliverSourceReplyViaMessageTool === true ? { didDeliverSourceReplyViaMessageTool: true } : {},
...params.result.sourceReplyDelivered ? { sourceReplyDelivered: true } : {},
...params.result.sourceReplyDeliveryState !== void 0 ? { sourceReplyDeliveryState: params.result.sourceReplyDeliveryState } : {},
...hasNonEmptyArray(params.result.messagingToolSourceReplyPayloads) ? { messagingToolSourceReplyPayloads: params.result.messagingToolSourceReplyPayloads } : {},
...hasAnyNonEmptyString(params.result.messagingToolSentTexts) ? { messagingToolSentTexts: params.result.messagingToolSentTexts } : {},
...hasAnyNonEmptyString(params.result.messagingToolSentMediaUrls) ? { messagingToolSentMediaUrls: params.result.messagingToolSentMediaUrls } : {},
...hasNonEmptyArray(params.result.messagingToolSentTargets) ? { messagingToolSentTargets: params.result.messagingToolSentTargets } : {},
...params.result.didSendDeterministicApprovalPrompt === true ? { didSendDeterministicApprovalPrompt: true } : {},
...hasNonEmptyArray(params.result.acceptedSessionSpawns) ? { acceptedSessionSpawns: params.result.acceptedSessionSpawns } : {},
...params.result.requesterContinuationSettled === true ? { requesterContinuationSettled: true } : {},
...hasSuccessfulCronAdds ? { successfulCronAdds } : {},
...params.deliverySucceeded !== void 0 ? { deliverySucceeded: params.deliverySucceeded } : {},
...params.deliveryStatus ? { deliveryStatus: params.deliveryStatus } : {}
};
}
function deliveryStatusFromDurableSend(send) {
const payloadOutcomes = serializeDurableMessagePayloadOutcomes(send.payloadOutcomes, { includeHookEffect: true });
const status = {
requested: true,
attempted: true,
status: send.status
};
switch (send.status) {
case "sent": return {
...status,
succeeded: true,
resultCount: send.results.length,
...payloadOutcomes ? { payloadOutcomes } : {}
};
case "suppressed": return {
...status,
succeeded: true,
reason: send.reason,
resultCount: 0,
...payloadOutcomes ? { payloadOutcomes } : {}
};
case "partial_failed": return {
...status,
succeeded: "partial",
error: true,
errorMessage: formatErrorMessage(send.error),
resultCount: send.results.length,
sentBeforeError: true,
...payloadOutcomes ? { payloadOutcomes } : {}
};
case "failed": return {
...status,
succeeded: false,
error: true,
errorMessage: formatErrorMessage(send.error),
...send.stage ? { reason: send.stage } : {},
...payloadOutcomes ? { payloadOutcomes } : {}
};
}
return send;
}
function preDeliveryFailureStatus(reason) {
return {
requested: true,
attempted: false,
status: "failed",
succeeded: false,
error: true,
reason
};
}
function noVisiblePayloadStatus(reason) {
return {
requested: true,
attempted: false,
status: "suppressed",
succeeded: true,
reason: reason === "channel_transform" ? reason : "no_visible_payload",
resultCount: 0
};
}
/**
* Payloads the source may receive. A tool-only source gets only host-granted ones
* (diagnostics, media); a host-owned turn may also keep runtime error payloads out of it.
*/
function selectSourceDeliverablePayloads(payloads, opts) {
const deliverable = opts.internalDeliverySuppressErrors ? payloads.filter((payload) => payload.isError !== true) : payloads;
return opts.sourceReplyDeliveryMode === "message_tool_only" ? deliverable.filter((payload) => getReplyPayloadMetadata(payload)?.deliverDespiteSourceReplySuppression === true) : deliverable;
}
//#endregion
export { selectSourceDeliverablePayloads as a, resolveAgentOutboundTarget as c, preDeliveryFailureStatus as i, deliveryStatusFromDurableSend as n, resolveAgentDeliveryPlanWithSessionRoute as o, noVisiblePayloadStatus as r, resolveAgentExplicitRecipientSession as s, buildDeliveryResult as t };