openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
289 lines (288 loc) • 13.3 kB
JavaScript
import { a as asOptionalRecord, c as isRecord } from "./record-coerce-TIsquoVR.mjs";
import { i as getGatewayPluginMetadataSnapshot } from "./current-plugin-metadata-state-CfLPTM0e.mjs";
import "./model-ref-shared-KBg0y299.mjs";
import { t as modelKey } from "./model-key-5zORvMDY.mjs";
import { i as buildModelAliasIndex, v as resolveModelRefFromString, y as readUtilityModelSetting } from "./model-selection-shared-DcM6hdAC.mjs";
import { t as resolveDefaultModelForAgent } from "./model-selection-config-BdeHEviO.mjs";
import { a as hasGatewayClientCap, t as GATEWAY_CLIENT_CAPS } from "./client-info-C8RatpKO.mjs";
import { n as readOperatorModelPolicyMembership, r as resolveOperatorModelDefault, t as prepareOperatorModelPolicy } from "./operator-model-policy-7XqG83Qr.mjs";
import { d as resolveOperatorRolePolicy } from "./operator-role-policy-Bsa4SHqC.mjs";
import { c as isTranscriptOnlyOpenClawAssistantModel } from "./transcript-only-openclaw-assistant-CzjHCvH2.mjs";
import { n as isSyntheticGatewayCaller } from "./gateway-personal-caller-CPQUGI4q.mjs";
import { t as getSessionDefaults } from "./session-utils-model-BzF2akFQ.mjs";
import { n as createModelVisibilityPolicy } from "./model-visibility-policy-CJ73IRCN.mjs";
import { t as SerializedJsonArray } from "./serialized-json-B87207AB.mjs";
import { isDeepStrictEqual } from "node:util";
//#region src/gateway/session-fast-mode-presentation.ts
/** Released native decoders accept only booleans and "auto". Never rewrite stored selection. */
function prepareSessionFastModePresentation(client) {
const supportsUltrafast = !client || isSyntheticGatewayCaller(client) || hasGatewayClientCap(client.connect.caps, GATEWAY_CLIENT_CAPS.ULTRAFAST);
return (mode) => mode === "ultrafast" && !supportsUltrafast ? true : mode;
}
/** Creation replay retains the canonical result and presents its entry at delivery time. */
function projectSessionFastModeEntryResult(payload, client) {
if (prepareSessionFastModePresentation(client)("ultrafast") !== true || !isRecord(payload) || !isRecord(payload.entry) || payload.entry.fastMode !== "ultrafast") return payload;
return {
...payload,
entry: {
...payload.entry,
fastMode: true
}
};
}
/** Catalog caches stay canonical; each recipient decodes only its negotiated speed values. */
function projectModelFastModeCatalog(payload, client) {
if (prepareSessionFastModePresentation(client)("ultrafast") !== true) return payload;
const project = (models) => models.map((model) => ({
...model,
...model.effectiveFastMode === "ultrafast" ? { effectiveFastMode: true } : {},
...model.runtimeChoices ? { runtimeChoices: model.runtimeChoices.map((choice) => choice.effectiveFastMode === "ultrafast" ? {
...choice,
effectiveFastMode: true
} : choice) } : {}
}));
return {
...payload,
...payload.models ? { models: project(payload.models) } : {},
...payload.decisionModels ? { decisionModels: project(payload.decisionModels) } : {}
};
}
//#endregion
//#region src/gateway/operator-model-presentation.ts
/** Inventory/auth changes do not retire choices; changed selection authority does. */
function modelSelectionPoliciesMatch(previous, next) {
if ((previous.models?.mode ?? "merge") !== (next.models?.mode ?? "merge") || !isDeepStrictEqual(previous.gateway?.roles, next.gateway?.roles)) return false;
const manifestPlugins = getGatewayPluginMetadataSnapshot() ?? [];
for (const role of Object.values(next.gateway?.roles?.definitions ?? {})) {
const before = prepareOperatorModelPolicy({
cfg: previous,
policy: role.modelPolicy,
manifestPlugins
});
const after = prepareOperatorModelPolicy({
cfg: next,
policy: role.modelPolicy,
manifestPlugins
});
if (readOperatorModelPolicyMembership(before) !== readOperatorModelPolicyMembership(after)) return false;
}
const agentIds = /* @__PURE__ */ new Set([
void 0,
...Object.keys(previous.agents?.entries ?? {}),
...Object.keys(next.agents?.entries ?? {})
]);
for (const agentId of agentIds) {
const policy = (cfg) => {
const model = resolveDefaultModelForAgent({
cfg,
agentId
});
return createModelVisibilityPolicy({
cfg,
agentId,
catalog: [],
defaultProvider: model.provider,
defaultModel: model,
manifestPlugins
});
};
const before = policy(previous);
const after = policy(next);
if (before.allowAny !== after.allowAny || !before.allowAny && !isDeepStrictEqual(before.allowedKeys, after.allowedKeys)) return false;
}
return true;
}
/** History and startup share a final projection without changing any persisted session facts. */
function projectOperatorModelRead(scope, input) {
const result = input.metadata ? {
...input,
metadata: projectModelFastModeCatalog(input.metadata, scope.client)
} : input;
const cfg = scope.context.getRuntimeConfig();
const presentation = prepareOperatorModelPresentation({
cfg,
policyConfig: scope.context.getCommittedRuntimeConfig?.() ?? cfg,
client: scope.client
});
if (!presentation) return result;
const policy = result.defaults || result.metadata ? presentation.forAgent(scope.agentId, scope.catalog) : void 0;
return {
...result,
...result.defaults && policy ? { defaults: policy.defaults(result.defaults) } : {},
...result.metadata && policy ? { metadata: policy.metadata(result.metadata) } : {},
...result.sessionInfo ? { sessionInfo: presentation.session(result.sessionInfo) } : {},
...result.messages ? { messages: (result.messages instanceof SerializedJsonArray ? result.messages.materialize() : result.messages).map(result.kind === "delta" ? presentation.deltaMessage : presentation.message) } : {},
...Object.hasOwn(result, "message") ? { message: presentation.message(result.message) } : {}
};
}
/** Build after read preparation; responses consume current role and prepared metadata together. */
function prepareOperatorModelPresentation(params) {
const { cfg, policyConfig, client } = params;
const modelPolicy = resolveOperatorRolePolicy(client, policyConfig)?.modelPolicy;
if (!modelPolicy) return;
const metadataSnapshot = params.metadataSnapshot ?? getGatewayPluginMetadataSnapshot();
const manifestPlugins = metadataSnapshot ?? [];
const policy = prepareOperatorModelPolicy({
cfg: policyConfig,
policy: modelPolicy,
manifestPlugins
});
if (!policy) return;
const filterModels = (models) => models.filter((model) => policy.allows({
provider: model.provider,
model: model.id
}));
const hidden = (provider, model) => (provider != null || model != null) && (typeof provider !== "string" || typeof model !== "string" || !policy.allows({
provider,
model
}));
const projectSession = (row) => {
const hideModel = hidden(row.modelProvider, row.model);
const hideActiveModel = hidden(row.activeModelProvider, row.activeModel);
const budget = asOptionalRecord(row.contextBudgetStatus);
const hideBudget = budget && hidden(budget.provider, budget.model);
if (!hideModel && !hideActiveModel && !hideBudget) return row;
const projected = { ...row };
for (const field of ["modelProvider", "model"]) if (hideModel && projected[field] != null) delete projected[field];
for (const field of ["activeModelProvider", "activeModel"]) if (hideActiveModel && projected[field] != null) delete projected[field];
if (hideBudget) delete projected.contextBudgetStatus;
return projected;
};
const projectMessage = (value) => {
const message = asOptionalRecord(value);
if (!message || message.role !== "assistant" || isTranscriptOnlyOpenClawAssistantModel(message.provider, message.model) || !hidden(message.provider, message.model)) return value;
const projected = { ...message };
for (const field of ["provider", "model"]) if (projected[field] != null) delete projected[field];
return projected;
};
return {
session: projectSession,
message: projectMessage,
deltaMessage(value) {
const envelope = asOptionalRecord(value);
if (!envelope) return value;
const session = asOptionalRecord(envelope.session);
return {
...projectSession(envelope),
...session ? { session: projectSession(session) } : {},
...Object.hasOwn(envelope, "message") ? { message: projectMessage(envelope.message) } : {}
};
},
forAgent(agentId, catalog = []) {
const normalization = {
cfg,
agentId,
manifestPlugins,
allowManifestNormalization: true,
allowPluginNormalization: false
};
const configuredDefault = resolveDefaultModelForAgent(normalization);
const selection = {
...normalization,
defaultProvider: configuredDefault.provider
};
let aliasIndex;
const allowedReference = (raw) => {
const ref = resolveModelRefFromString({
...selection,
raw,
aliasIndex: aliasIndex ??= buildModelAliasIndex(selection)
})?.ref;
return ref && policy.allows(ref) ? ref : void 0;
};
let manualPolicy;
const defaultModel = resolveOperatorModelDefault({
...normalization,
policy,
model: configuredDefault,
allows: (ref) => (manualPolicy ??= createModelVisibilityPolicy({
...normalization,
catalog,
defaultProvider: configuredDefault.provider,
defaultModel: configuredDefault
})).allows(ref)
});
const modelSelectionPolicy = {
restricted: true,
defaultModel: defaultModel ? modelKey(defaultModel.provider, defaultModel.model) : null
};
const projectDefaults = (defaults) => {
if (!defaultModel) return {
model: null,
modelProvider: null,
contextTokens: null,
...defaults.modelSelectionTarget ? { modelSelectionTarget: defaults.modelSelectionTarget } : {}
};
if (defaultModel.provider === defaults.modelProvider && defaultModel.model === defaults.model) return defaults;
return {
...getSessionDefaults(cfg, catalog, {
agentId,
modelRef: defaultModel,
metadataSnapshot,
allowPluginNormalization: false,
providerPolicySource: "active"
}),
...defaults.modelSelectionTarget ? { modelSelectionTarget: defaults.modelSelectionTarget } : {}
};
};
return {
catalog(result) {
const models = filterModels(result.models);
const decisionModels = result.decisionModels && filterModels(result.decisionModels);
const utilityModel = result.defaultModels?.automaticUtilityModel ? allowedReference(result.defaultModels.automaticUtilityModel) : void 0;
const utilitySetting = result.defaultModels?.utilityRuntime ? readUtilityModelSetting(cfg) : void 0;
const utilityRuntimeVisible = utilitySetting?.kind === "auto" ? utilityModel !== void 0 : utilitySetting?.kind === "explicit" && allowedReference(utilitySetting.modelRef) !== void 0;
const visibleProviders = new Set(models.map(({ provider }) => provider));
for (const model of decisionModels ?? []) visibleProviders.add(model.provider);
if (defaultModel) visibleProviders.add(defaultModel.provider);
if (utilityModel) visibleProviders.add(utilityModel.provider);
const disclosedProfileId = result.accountSelection?.kind === "automatic" ? void 0 : result.accountSelection?.authProfileId;
const providerOutcomes = (result.providerOutcomes ?? []).filter(({ provider, profileId }) => visibleProviders.has(provider) && (!profileId || profileId === disclosedProfileId));
return {
...result,
models,
modelSelectionPolicy,
pendingProviders: (result.pendingProviders ?? []).filter((provider) => visibleProviders.has(provider)),
providerOutcomes,
refreshFailed: result.refreshFailed === true && providerOutcomes.some(({ status }) => status !== "ready"),
...decisionModels ? { decisionModels } : {},
...result.defaultModels ? { defaultModels: {
automaticUtilityModel: utilityModel ? result.defaultModels.automaticUtilityModel : null,
...utilityRuntimeVisible && result.defaultModels.utilityRuntime ? { utilityRuntime: result.defaultModels.utilityRuntime } : {}
} } : {}
};
},
metadata(result) {
return {
...result,
...result.models ? { models: filterModels(result.models) } : {},
modelSelectionPolicy
};
},
defaults: projectDefaults,
agent(row) {
const { model: _model, utilityModel, agentRuntime: _runtime, thinkingLevels: _levels, thinkingOptions: _options, thinkingDefault: _thinking, ...identity } = row;
const defaults = projectDefaults({
model: null,
modelProvider: null,
contextTokens: null
});
return {
...identity,
model: {
...modelSelectionPolicy.defaultModel ? { primary: modelSelectionPolicy.defaultModel } : {},
...row.model?.fallbacks ? { fallbacks: row.model.fallbacks.filter((ref) => allowedReference(ref)) } : {}
},
...utilityModel && allowedReference(utilityModel) ? { utilityModel } : {},
agentRuntime: defaults.agentRuntime,
thinkingLevels: defaults.thinkingLevels,
thinkingOptions: defaults.thinkingOptions,
thinkingDefault: defaults.thinkingDefault
};
}
};
}
};
}
//#endregion
export { projectModelFastModeCatalog as a, prepareSessionFastModePresentation as i, prepareOperatorModelPresentation as n, projectSessionFastModeEntryResult as o, projectOperatorModelRead as r, modelSelectionPoliciesMatch as t };