openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
266 lines (265 loc) • 10.6 kB
JavaScript
import { u as resolveAgentDir } from "./agent-scope-config-DcbEhP0R.js";
import { t as modelKey } from "./model-key-CMdQNkZf.js";
import { A as resolveCollapsedSessionAuthPinSource } from "./agent-scope-DbtJyKUL.js";
import { c as resolveContextConfigProviderForRuntime } from "./openai-routing-Ex_3E9TF.js";
import { a as enqueueSystemEvent } from "./system-events-C03jsM0j.js";
import { f as emitSessionLifecycleEvent } from "./session-history-eviction-C4srftLJ.js";
import { s as isModelSelectionLocked, t as MODEL_SELECTION_LOCKED_MESSAGE } from "./model-overrides-Bm7jo7Di.js";
import { o as resolveSupportedThinkingLevel } from "./thinking-DterdXhr.js";
import { o as resolveEffectiveAgentRuntime } from "./thinking-runtime-BiFbTVdI.js";
import "./model-selection-di2kjKCB.js";
import { c as refreshQueuedFollowupSession } from "./settings-jmDsm5RI.js";
import "./queue-BpaiO3X2.js";
import { t as triggerSessionPatchHook } from "./session-patch-hooks-Bav35gWY.js";
import { t as applyModelOverrideWithAuthProfileCompatibility } from "./auth-profile-preservation-DCNwoc5M.js";
import { n as createModelVisibilityPolicy } from "./model-visibility-policy-mYoB7nkk.js";
import { t as persistStickyModelSelectionBestEffort } from "./sticky-model-selection-BlEz_Ddb.js";
import { a as prepareModelSelectionRuntime, s as applyModelRuntimeDirective, t as findSelectedCatalogEntry } from "./model-runtime-normalization-CVjCcJkR.js";
import { a as sessionModelOverrideChangesApplied, n as adoptPersistedSessionSnapshot, t as SESSION_MODEL_OVERRIDE_TRANSACTION_FIELDS } from "./session-snapshot-merge-Cf1TdJBp.js";
import { t as resolveContextTokens } from "./model-selection-context-BUKuYlr-.js";
import { t as persistReplySessionEntry } from "./session-entry-persistence-Cdz5cLuU.js";
//#region src/model-picker/apply-session-model-selection.ts
/** Applies the model transaction field family to one caller-owned snapshot. */
function applySessionModelSelectionToEntry(params) {
const modelChange = applyModelOverrideWithAuthProfileCompatibility({
cfg: params.cfg,
agentDir: params.agentDir,
entry: params.entry,
currentProvider: params.currentProvider,
selection: params.request,
profileOverride: params.request.profileOverride,
markLiveSwitchPending: params.markLiveSwitchPending
});
const runtimeChange = applyModelRuntimeDirective(params.entry, params.runtime);
return {
changed: modelChange.updated || runtimeChange.updated,
...params.runtime.kind === "clear" || params.runtime.kind === "set" ? { runtimeChange: params.runtime } : {}
};
}
function formatModelSwitchEvent(provider, model, alias) {
const label = `${provider}/${model}`;
return alias ? `Model switched to ${alias} (${label}).` : `Model switched to ${label}.`;
}
function rejectNotAllowed(provider, model) {
return {
status: "rejected",
reason: "not-allowed",
message: `Model ${provider}/${model} is not available for this agent.`
};
}
/** Applies one validated picker selection to the authoritative live session. */
async function applySessionModelSelection(params) {
const startingStoreEntry = params.sessionStore[params.sessionKey];
const startingEntry = params.storePath ? params.sessionEntry : startingStoreEntry ?? params.sessionEntry;
const initialEntry = { ...startingEntry };
if (isModelSelectionLocked(startingEntry)) return {
status: "rejected",
reason: "locked",
message: MODEL_SELECTION_LOCKED_MESSAGE
};
const normalizedModelKey = modelKey(params.request.provider, params.request.model);
if (!(params.modelPolicy ?? createModelVisibilityPolicy({
cfg: params.cfg,
catalog: [...params.modelCatalog],
defaultProvider: params.defaultProvider,
defaultModel: params.defaultModel,
agentId: params.agentId
})).allows(params.request)) return rejectNotAllowed(params.request.provider, params.request.model);
const request = {
...params.request,
isDefault: normalizedModelKey === modelKey(params.defaultProvider, params.defaultModel)
};
const prepared = await prepareModelSelectionRuntime({
cfg: params.cfg,
agentId: params.agentId,
sessionEntry: startingEntry,
provider: request.provider,
model: request.model,
catalog: params.thinkingCatalog ?? params.modelCatalog,
rawRuntime: request.runtime.kind === "set" ? request.runtime.runtime : request.runtime.kind === "clear" ? "default" : void 0
});
if (prepared.status === "rejected") return prepared;
const authProfileError = params.validateAuthProfileSelection?.();
if (authProfileError) return {
status: "rejected",
reason: "not-allowed",
message: authProfileError
};
const currentEntry = params.storePath ? startingEntry : params.sessionStore[params.sessionKey] ?? params.sessionEntry;
if (isModelSelectionLocked(currentEntry)) return {
status: "rejected",
reason: "locked",
message: MODEL_SELECTION_LOCKED_MESSAGE
};
if (!params.storePath && (params.sessionStore[params.sessionKey] !== startingStoreEntry || currentEntry.sessionId !== initialEntry.sessionId)) return {
status: "conflict",
message: "Model change was not applied because the session changed. Retry."
};
const runtime = prepared.runtime;
const thinkingCatalog = prepared.catalog;
const selectedCatalogEntry = findSelectedCatalogEntry({
catalog: thinkingCatalog,
...request
});
const nextEntry = { ...startingEntry };
const applied = applySessionModelSelectionToEntry({
cfg: params.cfg,
agentDir: resolveAgentDir(params.cfg, params.agentId),
entry: nextEntry,
currentProvider: params.currentProvider,
request,
runtime,
markLiveSwitchPending: params.markLiveSwitchPending
});
const thinkingRuntime = resolveEffectiveAgentRuntime({
cfg: params.cfg,
provider: request.provider,
modelId: request.model,
modelApi: selectedCatalogEntry?.api,
modelBaseUrl: selectedCatalogEntry?.baseUrl,
agentId: params.agentId,
sessionKey: params.sessionKey,
sessionEntry: nextEntry
});
const currentThinkingLevel = nextEntry.thinkingLevel;
let thinkingRemap;
if (currentThinkingLevel) {
const remapped = resolveSupportedThinkingLevel({
provider: request.provider,
model: request.model,
level: currentThinkingLevel,
catalog: [...thinkingCatalog],
agentRuntime: thinkingRuntime
});
if (remapped !== currentThinkingLevel) {
nextEntry.thinkingLevel = remapped;
thinkingRemap = {
from: currentThinkingLevel,
to: remapped,
provider: request.provider,
model: request.model
};
}
}
nextEntry.updatedAt = Date.now();
let persistedEntry;
if (params.storePath) {
const persistence = await persistReplySessionEntry({
storePath: params.storePath,
sessionKey: params.sessionKey,
initialEntry,
entry: nextEntry,
allowCreate: params.allowCreate,
reassertLiveModelSwitchPending: applied.changed && nextEntry.liveModelSwitchPending === true,
requireModelSelectionUnlocked: true,
touchedFields: SESSION_MODEL_OVERRIDE_TRANSACTION_FIELDS,
validateCommit: params.validateAuthProfileSelection
});
if (persistence.entry) {
params.sessionStore[params.sessionKey] = persistence.entry;
adoptPersistedSessionSnapshot(params.sessionEntry, persistence.entry);
}
if (persistence.status === "model-selection-locked") return {
status: "rejected",
reason: "locked",
message: MODEL_SELECTION_LOCKED_MESSAGE
};
if (persistence.status === "commit-rejected") return {
status: "rejected",
reason: "not-allowed",
message: persistence.error
};
if (persistence.status !== "current" || !sessionModelOverrideChangesApplied({
initial: initialEntry,
next: nextEntry,
current: persistence.entry,
reassertLiveModelSwitchPending: applied.changed && nextEntry.liveModelSwitchPending === true
})) return {
status: "conflict",
message: "Model change was not applied because the session changed. Retry."
};
persistedEntry = persistence.entry;
} else {
adoptPersistedSessionSnapshot(params.sessionEntry, nextEntry);
params.sessionStore[params.sessionKey] = params.sessionEntry;
persistedEntry = params.sessionEntry;
}
const agentRuntime = resolveEffectiveAgentRuntime({
cfg: params.cfg,
provider: request.provider,
modelId: request.model,
modelApi: selectedCatalogEntry?.api,
modelBaseUrl: selectedCatalogEntry?.baseUrl,
agentId: params.agentId,
sessionKey: params.sessionKey,
sessionEntry: persistedEntry
});
const provider = request.provider;
const model = request.model;
const effectiveModelRef = `${provider}/${model}`;
const changed = applied.changed || thinkingRemap !== void 0;
const configuredDefaultUpdate = params.canPersistStickyModelSelection === true && (!request.isDefault || params.stickyModelSelectionTarget) ? persistStickyModelSelectionBestEffort({
agentId: params.agentId,
model: effectiveModelRef,
...params.stickyModelSelectionTarget ? { target: params.stickyModelSelectionTarget } : {}
}) : void 0;
if (changed) {
emitSessionLifecycleEvent({
sessionKey: params.sessionKey,
agentId: params.agentId,
reason: "patch"
});
triggerSessionPatchHook({
cfg: params.cfg,
sessionEntry: persistedEntry,
sessionKey: params.sessionKey,
patch: {
key: params.sessionKey,
model: params.patchModel ?? effectiveModelRef
}
});
refreshQueuedFollowupSession({
key: params.sessionKey,
nextProvider: provider,
nextModel: model,
nextRouteResolution: "resolved",
nextModelOverrideSource: request.isDefault ? void 0 : "user",
nextAuthProfileId: persistedEntry.authProfileOverride,
nextAuthProfileIdSource: resolveCollapsedSessionAuthPinSource(persistedEntry),
nextThinking: {
level: persistedEntry.thinkingLevel,
catalog: [...thinkingCatalog],
agentRuntime
}
});
}
if (`${params.currentProvider}/${params.currentModel}` !== effectiveModelRef) enqueueSystemEvent(formatModelSwitchEvent(provider, model, request.alias), {
sessionKey: params.sessionKey,
contextKey: `model:${effectiveModelRef}`
});
const contextProvider = resolveContextConfigProviderForRuntime({
provider,
runtimeId: agentRuntime,
config: params.cfg
});
return {
status: "applied",
provider,
model,
effectiveModelRef,
agentRuntime,
changed,
contextTokens: resolveContextTokens({
cfg: params.cfg,
provider: contextProvider,
model,
modelContextWindow: selectedCatalogEntry?.contextWindow,
modelContextTokens: selectedCatalogEntry?.contextTokens
}),
...configuredDefaultUpdate ? { configuredDefaultUpdate } : {},
...applied.runtimeChange ? { runtimeChange: applied.runtimeChange } : {},
...thinkingRemap ? { thinkingRemap } : {}
};
}
//#endregion
export { applySessionModelSelection as t };