openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
130 lines (129 loc) • 6.33 kB
JavaScript
import { n as getRuntimeConfig } from "./io.runtime-B9iJRs3w.js";
import { n as normalizeAgentId } from "./agent-id-CeT3w4ap.js";
import { y as resolveDefaultAgentId } from "./agent-scope-config-DcbEhP0R.js";
import { O as parseAgentSessionKey } from "./session-key-BnWWjqNc.js";
import "./agent-scope-DbtJyKUL.js";
import "./io-bdCzpGWJ.js";
import "./session-accessor-YsytfDtG.js";
import { u as loadSessionEntryReadOnly } from "./session-accessor.sqlite-entry-CWk3jL7s.js";
import { i as resolveSessionStoreKey, n as resolveSessionStoreAgentId } from "./session-store-key-8xEjWSNi.js";
import { t as buildLatestSubagentRunReadIndex } from "./subagent-registry-read-DeFf_9Nz.js";
import "./operator-approval-store-BxnBnd-1.js";
//#region src/gateway/approval-session-audience.ts
const MAX_APPROVAL_AUDIENCE_SESSIONS = 64;
function canonicalizeAudienceSessionKey(sources, sessionKey, relativeToSessionKey) {
const raw = sessionKey?.trim();
if (!raw) return null;
return sources.canonicalizeSessionKey(raw, relativeToSessionKey)?.trim() || null;
}
/** Resolves the source session and its operator-visible ancestor audience. */
function resolveApprovalSessionAudienceFromSources(params) {
const sourceSessionKey = canonicalizeAudienceSessionKey(params.sources, params.sourceSessionKey);
if (!sourceSessionKey) return [];
const audience = [];
const queued = /* @__PURE__ */ new Set([sourceSessionKey]);
const pending = [sourceSessionKey];
const enqueue = (sessionKey) => {
if (!sessionKey || queued.has(sessionKey) || pending.length >= MAX_APPROVAL_AUDIENCE_SESSIONS) return;
queued.add(sessionKey);
pending.push(sessionKey);
};
for (const sessionKey of pending) {
audience.push(sessionKey);
const subagentLineage = params.sources.getLatestSubagentLineage(sessionKey);
const registryParents = [canonicalizeAudienceSessionKey(params.sources, subagentLineage?.controllerSessionKey, sessionKey), canonicalizeAudienceSessionKey(params.sources, subagentLineage?.requesterSessionKey, sessionKey)].filter((candidate) => Boolean(candidate));
if (registryParents.length > 0) {
for (const parentSessionKey of registryParents) enqueue(parentSessionKey);
continue;
}
const storedLineage = params.sources.getStoredSessionLineage(sessionKey);
const parentSessionKey = storedLineage?.parentSessionKey?.trim() ? storedLineage.parentSessionKey : storedLineage?.spawnedBy;
enqueue(canonicalizeAudienceSessionKey(params.sources, parentSessionKey, sessionKey));
}
return audience;
}
function createRuntimeApprovalSessionAudienceSources(cfg, sourceAgentId) {
const subagentRuns = buildLatestSubagentRunReadIndex();
const resolveStorageTarget = (sessionKey) => {
const parsed = parseAgentSessionKey(sessionKey);
if (parsed?.rest.toLowerCase() === "global") return {
agentId: normalizeAgentId(parsed.agentId),
sessionKey: "global"
};
return {
agentId: resolveSessionStoreAgentId(cfg, sessionKey),
sessionKey
};
};
return {
canonicalizeSessionKey: (sessionKey, relativeToSessionKey) => {
if (!relativeToSessionKey) return canonicalizeApprovalSourceStreamKey(cfg, sessionKey, sourceAgentId);
const relativeAgentId = resolveSessionStoreAgentId(cfg, relativeToSessionKey);
const canonical = resolveSessionStoreKey({
cfg,
sessionKey,
storeAgentId: relativeAgentId
});
return canonical ? resolveApprovalSourceStreamKey(canonical, relativeAgentId) : canonical;
},
getLatestSubagentLineage: (sessionKey) => subagentRuns.getLatestSubagentRun(sessionKey),
getStoredSessionLineage: (sessionKey) => {
const target = resolveStorageTarget(sessionKey);
return loadSessionEntryReadOnly({
agentId: target.agentId,
clone: false,
hydrateSkillPromptRefs: false,
sessionKey: target.sessionKey
});
}
};
}
/** Resolves an approval audience from the live registry and session stores. */
function resolveApprovalSessionAudience(sourceSessionKey, sourceAgentId) {
return resolveApprovalSessionAudienceFromSources({
sourceSessionKey,
sources: createRuntimeApprovalSessionAudienceSources(getRuntimeConfig(), sourceAgentId)
});
}
/** Canonicalize one source key against config: agent scoping, main-key aliases, global sentinel. */
function canonicalizeApprovalSourceStreamKey(cfg, sessionKey, sourceAgentId) {
const ownerAgentId = normalizeAgentId(sourceAgentId ?? resolveDefaultAgentId(cfg));
const lowered = sessionKey.trim().toLowerCase();
const scoped = parseAgentSessionKey(sessionKey) || lowered === "global" || lowered === "unknown" ? sessionKey : `agent:${ownerAgentId}:${sessionKey}`;
return resolveApprovalSourceStreamKey(resolveSessionStoreKey({
cfg,
sessionKey: scoped
}), ownerAgentId);
}
/**
* Fallback audience key when the lineage walk fails. Config-only
* canonicalization (agent scope, configured main-key aliases) still applies
* when the config loads; the pure-string form is the true last resort.
*/
/** Non-throwing audience resolver for injection into the approval manager.
* Lineage is routing metadata, not an approval safety prerequisite; when
* session stores are unavailable this preserves the agent-scoped source. */
function resolveApprovalSessionAudienceWithFallback(sourceSessionKey, sourceAgentId) {
try {
return resolveApprovalSessionAudience(sourceSessionKey, sourceAgentId);
} catch {
return [resolveApprovalFallbackAudienceSessionKey(sourceSessionKey, sourceAgentId)];
}
}
function resolveApprovalFallbackAudienceSessionKey(sourceSessionKey, sourceAgentId) {
try {
return canonicalizeApprovalSourceStreamKey(getRuntimeConfig(), sourceSessionKey, sourceAgentId);
} catch {
return resolveApprovalSourceStreamKey(sourceSessionKey, sourceAgentId);
}
}
/** Best-effort stream key used when lineage lookup is unavailable. */
function resolveApprovalSourceStreamKey(sourceSessionKey, sourceAgentId) {
const normalizedSessionKey = sourceSessionKey.trim();
const lowered = normalizedSessionKey.toLowerCase();
if (!sourceAgentId || lowered === "unknown" || parseAgentSessionKey(normalizedSessionKey)) return normalizedSessionKey;
const agentId = normalizeAgentId(sourceAgentId);
return lowered === "global" ? `agent:${agentId}:global` : `agent:${agentId}:${normalizedSessionKey}`;
}
//#endregion
export { resolveApprovalSourceStreamKey as n, resolveApprovalSessionAudienceWithFallback as t };