mirror of https://github.com/openclaw/openclaw.git
113 lines
3.5 KiB
TypeScript
113 lines
3.5 KiB
TypeScript
import type { SessionEntry } from "../config/sessions.js";
|
|
|
|
export type ModelOverrideSelection = {
|
|
provider: string;
|
|
model: string;
|
|
isDefault?: boolean;
|
|
};
|
|
|
|
export function applyModelOverrideToSessionEntry(params: {
|
|
entry: SessionEntry;
|
|
selection: ModelOverrideSelection;
|
|
profileOverride?: string;
|
|
profileOverrideSource?: "auto" | "user";
|
|
}): { updated: boolean } {
|
|
const { entry, selection, profileOverride } = params;
|
|
const profileOverrideSource = params.profileOverrideSource ?? "user";
|
|
let updated = false;
|
|
let selectionUpdated = false;
|
|
|
|
if (selection.isDefault) {
|
|
if (entry.providerOverride) {
|
|
delete entry.providerOverride;
|
|
updated = true;
|
|
selectionUpdated = true;
|
|
}
|
|
if (entry.modelOverride) {
|
|
delete entry.modelOverride;
|
|
updated = true;
|
|
selectionUpdated = true;
|
|
}
|
|
} else {
|
|
if (entry.providerOverride !== selection.provider) {
|
|
entry.providerOverride = selection.provider;
|
|
updated = true;
|
|
selectionUpdated = true;
|
|
}
|
|
if (entry.modelOverride !== selection.model) {
|
|
entry.modelOverride = selection.model;
|
|
updated = true;
|
|
selectionUpdated = true;
|
|
}
|
|
}
|
|
|
|
// Model overrides supersede previously recorded runtime model identity.
|
|
// If runtime fields are stale (or the override changed), clear them so status
|
|
// surfaces reflect the selected model immediately.
|
|
const runtimeModel = typeof entry.model === "string" ? entry.model.trim() : "";
|
|
const runtimeProvider = typeof entry.modelProvider === "string" ? entry.modelProvider.trim() : "";
|
|
const runtimePresent = runtimeModel.length > 0 || runtimeProvider.length > 0;
|
|
const runtimeAligned =
|
|
runtimeModel === selection.model &&
|
|
(runtimeProvider.length === 0 || runtimeProvider === selection.provider);
|
|
if (runtimePresent && (selectionUpdated || !runtimeAligned)) {
|
|
if (entry.model !== undefined) {
|
|
delete entry.model;
|
|
updated = true;
|
|
}
|
|
if (entry.modelProvider !== undefined) {
|
|
delete entry.modelProvider;
|
|
updated = true;
|
|
}
|
|
}
|
|
|
|
// contextTokens are derived from the active session model. When the selected
|
|
// model changes (or runtime model is already stale), the cached window can
|
|
// pin the session to an older/smaller limit until another run refreshes it.
|
|
if (
|
|
entry.contextTokens !== undefined &&
|
|
(selectionUpdated || (runtimePresent && !runtimeAligned))
|
|
) {
|
|
delete entry.contextTokens;
|
|
updated = true;
|
|
}
|
|
|
|
if (profileOverride) {
|
|
if (entry.authProfileOverride !== profileOverride) {
|
|
entry.authProfileOverride = profileOverride;
|
|
updated = true;
|
|
}
|
|
if (entry.authProfileOverrideSource !== profileOverrideSource) {
|
|
entry.authProfileOverrideSource = profileOverrideSource;
|
|
updated = true;
|
|
}
|
|
if (entry.authProfileOverrideCompactionCount !== undefined) {
|
|
delete entry.authProfileOverrideCompactionCount;
|
|
updated = true;
|
|
}
|
|
} else {
|
|
if (entry.authProfileOverride) {
|
|
delete entry.authProfileOverride;
|
|
updated = true;
|
|
}
|
|
if (entry.authProfileOverrideSource) {
|
|
delete entry.authProfileOverrideSource;
|
|
updated = true;
|
|
}
|
|
if (entry.authProfileOverrideCompactionCount !== undefined) {
|
|
delete entry.authProfileOverrideCompactionCount;
|
|
updated = true;
|
|
}
|
|
}
|
|
|
|
// Clear stale fallback notice when the user explicitly switches models.
|
|
if (updated) {
|
|
delete entry.fallbackNoticeSelectedModel;
|
|
delete entry.fallbackNoticeActiveModel;
|
|
delete entry.fallbackNoticeReason;
|
|
entry.updatedAt = Date.now();
|
|
}
|
|
|
|
return { updated };
|
|
}
|