openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
162 lines (161 loc) • 7.5 kB
JavaScript
import { a as normalizeLowercaseStringOrEmpty } from "./string-coerce-mnp54Vah.js";
import { d as requiresFoldedSessionKeyAliasProof } from "./session-key-utils-Bx3apsJ3.js";
import { i as getRuntimeConfig } from "./io-Gi7-pyU-.js";
import { i as resolveSessionStoreKey, r as resolveSessionStoreAgentId } from "./session-store-key-BsydjA1h.js";
import { n as deliveryContextFromSession } from "./delivery-context.shared-CpAdEETO.js";
import { u as resolveStorePath } from "./paths-NEwU8m3X.js";
import { A as parseSessionThreadInfo, B as normalizeStoreSessionKey, L as foldedSessionKeyAliasCandidates, R as hasMismatchedCaseSensitiveDeliveryProof, a as readSessionStoreSnapshot, z as isConfirmedLowercasedLegacyAlias } from "./store-load-C4uq6Lrq.js";
import "./store-Qsgtu-0y.js";
import { r as resolveAllAgentSessionStoreTargetsSync } from "./targets-BrMDn2yj.js";
//#region src/config/sessions/delivery-info.ts
function hasRoutableDeliveryContext(context) {
return Boolean(context?.channel && context?.to);
}
/**
* Extracts the routable delivery context and thread id for a persisted session key.
*
* Thread/topic keys first try their exact store entry, then fall back to the base session when
* the thread entry has no delivery route of its own.
*/
function extractDeliveryInfo(sessionKey, options) {
const { baseSessionKey, threadId } = parseSessionThreadInfo(sessionKey);
if (!sessionKey || !baseSessionKey) return {
deliveryContext: void 0,
threadId
};
let deliveryContext;
try {
const lookup = loadDeliverySessionEntry({
cfg: options?.cfg ?? getRuntimeConfig(),
sessionKey,
baseSessionKey
});
let entry = lookup.entry;
let storedDeliveryContext = deliveryContextFromSession(entry);
if (!hasRoutableDeliveryContext(storedDeliveryContext) && baseSessionKey !== sessionKey) {
entry = lookup.baseEntry;
storedDeliveryContext = deliveryContextFromSession(entry);
}
if (hasRoutableDeliveryContext(storedDeliveryContext)) deliveryContext = {
channel: storedDeliveryContext.channel,
to: storedDeliveryContext.to,
accountId: storedDeliveryContext.accountId,
threadId: storedDeliveryContext.threadId
};
} catch {}
return {
deliveryContext,
threadId
};
}
function resolveDeliveryStorePaths(cfg, agentId) {
const paths = /* @__PURE__ */ new Set();
paths.add(resolveStorePath(cfg.session?.store, { agentId }));
for (const target of resolveAllAgentSessionStoreTargetsSync(cfg)) if (target.agentId === agentId) paths.add(target.storePath);
return [...paths];
}
function asSessionEntry(entry) {
return entry;
}
function findSessionEntryInStore(store, keys) {
let normalizedIndex;
let bestEntry;
let bestUpdatedAt = 0;
let bestRoutable = false;
let bestExact = false;
const acceptCandidate = (candidate, isExact = false) => {
if (!candidate) return;
const entry = candidate;
const candidateRoutable = hasRoutableDeliveryContext(deliveryContextFromSession(entry));
const candidateUpdatedAt = entry.updatedAt ?? 0;
if (!bestEntry || candidateRoutable && !bestRoutable || candidateRoutable === bestRoutable && isExact && !bestExact || candidateRoutable === bestRoutable && isExact === bestExact && candidateUpdatedAt > bestUpdatedAt) {
bestEntry = entry;
bestUpdatedAt = candidateUpdatedAt;
bestRoutable = candidateRoutable;
bestExact = isExact;
}
};
for (const key of keys) {
const trimmed = key.trim();
const normalized = normalizeStoreSessionKey(key);
const foldedLegacyKeys = foldedSessionKeyAliasCandidates(normalized);
const exactKeyWins = requiresFoldedSessionKeyAliasProof(normalized);
let foundRoutableCandidate = false;
if (Object.hasOwn(store, normalized) && !hasMismatchedCaseSensitiveDeliveryProof(asSessionEntry(store[normalized]), normalized)) {
foundRoutableCandidate ||= hasRoutableDeliveryContext(deliveryContextFromSession(asSessionEntry(store[normalized])));
acceptCandidate(store[normalized], exactKeyWins);
}
for (const foldedLegacyKey of foldedLegacyKeys) {
if (!Object.hasOwn(store, foldedLegacyKey) || !isConfirmedLowercasedLegacyAlias(asSessionEntry(store[foldedLegacyKey]), normalized)) continue;
const foldedLegacyEntry = asSessionEntry(store[foldedLegacyKey]);
foundRoutableCandidate ||= hasRoutableDeliveryContext(deliveryContextFromSession(foldedLegacyEntry));
acceptCandidate(foldedLegacyEntry);
}
if (trimmed !== normalized && Object.hasOwn(store, trimmed) && !hasMismatchedCaseSensitiveDeliveryProof(asSessionEntry(store[trimmed]), normalized)) {
foundRoutableCandidate ||= hasRoutableDeliveryContext(deliveryContextFromSession(asSessionEntry(store[trimmed])));
acceptCandidate(store[trimmed]);
}
if (trimmed !== normalized || !foundRoutableCandidate) {
normalizedIndex ??= buildFreshestSessionEntryIndex(store);
const freshest = normalizedIndex.get(normalized);
if (!hasMismatchedCaseSensitiveDeliveryProof(freshest, normalized)) acceptCandidate(freshest);
for (const foldedLegacyKey of foldedLegacyKeys) {
const foldedFreshest = normalizedIndex.get(foldedLegacyKey);
if (isConfirmedLowercasedLegacyAlias(foldedFreshest, normalized)) acceptCandidate(foldedFreshest);
}
}
}
return bestEntry;
}
function buildFreshestSessionEntryIndex(store) {
const index = /* @__PURE__ */ new Map();
for (const [key, candidate] of Object.entries(store)) {
const entry = asSessionEntry(candidate);
if (!entry) continue;
const normalized = normalizeStoreSessionKey(key);
const existing = index.get(normalized);
const entryRoutable = hasRoutableDeliveryContext(deliveryContextFromSession(entry));
const existingRoutable = hasRoutableDeliveryContext(deliveryContextFromSession(existing));
if (!existing || entryRoutable && !existingRoutable || entryRoutable === existingRoutable && (entry.updatedAt ?? 0) > (existing.updatedAt ?? 0)) index.set(normalized, entry);
const foldedLegacyKey = normalizeLowercaseStringOrEmpty(normalized);
if (foldedLegacyKey === normalized || requiresFoldedSessionKeyAliasProof(normalized)) continue;
const foldedExisting = index.get(foldedLegacyKey);
const foldedExistingRoutable = hasRoutableDeliveryContext(deliveryContextFromSession(foldedExisting));
if (!foldedExisting || entryRoutable && !foldedExistingRoutable || entryRoutable === foldedExistingRoutable && (entry.updatedAt ?? 0) > (foldedExisting.updatedAt ?? 0)) index.set(foldedLegacyKey, entry);
}
return index;
}
function loadDeliverySessionEntry(params) {
const canonicalKey = resolveSessionStoreKey({
cfg: params.cfg,
sessionKey: params.sessionKey
});
const canonicalBaseKey = resolveSessionStoreKey({
cfg: params.cfg,
sessionKey: params.baseSessionKey
});
const agentId = resolveSessionStoreAgentId(params.cfg, canonicalKey);
const sessionKeys = [params.sessionKey, canonicalKey];
const baseKeys = [params.baseSessionKey, canonicalBaseKey];
let fallback;
for (const storePath of resolveDeliveryStorePaths(params.cfg, agentId)) {
const store = readSessionStoreSnapshot(storePath);
const entry = findSessionEntryInStore(store, sessionKeys);
const baseEntry = findSessionEntryInStore(store, baseKeys);
if (!entry && !baseEntry) continue;
fallback ??= {
entry,
baseEntry
};
if (hasRoutableDeliveryContext(deliveryContextFromSession(entry)) || hasRoutableDeliveryContext(deliveryContextFromSession(baseEntry))) return {
entry,
baseEntry
};
}
return fallback ?? {
entry: void 0,
baseEntry: void 0
};
}
//#endregion
export { extractDeliveryInfo as t };