Skip to content

Commit 70bab53

Browse files
committed
fix(status): show effective channel model override
1 parent 432a597 commit 70bab53

2 files changed

Lines changed: 63 additions & 22 deletions

File tree

src/auto-reply/status.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,37 @@ describe("buildStatusMessage", () => {
824824
expect(normalized).toContain("channel override");
825825
});
826826

827+
it("shows the effective channel override model when it differs from the default", () => {
828+
const text = buildStatusMessage({
829+
config: {
830+
channels: {
831+
modelByChannel: {
832+
telegram: {
833+
"group-123": "xai/grok-4.3",
834+
},
835+
},
836+
},
837+
} as unknown as OpenClawConfig,
838+
agent: {
839+
model: "openai/gpt-5.5",
840+
},
841+
sessionEntry: {
842+
sessionId: "abc",
843+
updatedAt: 0,
844+
channel: "telegram",
845+
groupId: "group-123",
846+
},
847+
sessionKey: "agent:main:main",
848+
sessionScope: "per-sender",
849+
queue: { mode: "collect", depth: 0 },
850+
});
851+
const normalized = normalizeTestText(text);
852+
853+
expect(normalized).toContain("Model: xai/grok-4.3");
854+
expect(normalized).toContain("channel override");
855+
expect(normalized).toContain("Session/default model: openai/gpt-5.5");
856+
});
857+
827858
it("uses the channel override model context window instead of stale persisted context", () => {
828859
const text = buildStatusMessage({
829860
config: {

src/status/status-message.ts

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -481,13 +481,11 @@ const formatVoiceModeLine = (
481481
return parts.join(" · ");
482482
};
483483

484-
function resolveChannelModelNote(params: {
484+
function resolveChannelModelRef(params: {
485485
config?: OpenClawConfig;
486486
entry?: SessionEntry;
487-
selectedProvider: string;
488-
selectedModel: string;
489487
parentSessionKey?: string;
490-
}): string | undefined {
488+
}): { provider: string; model: string; label: string } | undefined {
491489
if (!params.config || !params.entry) {
492490
return undefined;
493491
}
@@ -523,13 +521,13 @@ function resolveChannelModelNote(params: {
523521
if (!resolvedOverride) {
524522
return undefined;
525523
}
526-
if (
527-
resolvedOverride.ref.provider !== params.selectedProvider ||
528-
resolvedOverride.ref.model !== params.selectedModel
529-
) {
530-
return undefined;
531-
}
532-
return "channel override";
524+
return {
525+
provider: resolvedOverride.ref.provider,
526+
model: resolvedOverride.ref.model,
527+
label:
528+
formatProviderModelRef(resolvedOverride.ref.provider, resolvedOverride.ref.model) ||
529+
channelOverride.model,
530+
};
533531
}
534532

535533
function hasUserPinnedModelSelection(entry: SessionEntry | undefined): boolean {
@@ -582,14 +580,20 @@ export function buildStatusMessage(args: StatusArgs): string {
582580
selectedModel,
583581
sessionEntry: entry,
584582
});
583+
const channelModelRef = resolveChannelModelRef({
584+
config: args.config,
585+
entry,
586+
parentSessionKey: args.parentSessionKey,
587+
});
588+
const initialActiveModelLabel = channelModelRef?.label ?? modelRefs.active.label ?? "unknown";
585589
const initialFallbackState = resolveActiveFallbackState({
586590
selectedModelRef: modelRefs.selected.label || "unknown",
587-
activeModelRef: modelRefs.active.label || "unknown",
591+
activeModelRef: initialActiveModelLabel,
588592
config: args.config,
589593
state: entry,
590594
});
591-
let activeProvider = modelRefs.active.provider;
592-
let activeModel = modelRefs.active.model;
595+
let activeProvider = channelModelRef?.provider ?? modelRefs.active.provider;
596+
let activeModel = channelModelRef?.model ?? modelRefs.active.model;
593597
let contextLookupProvider: string | undefined = activeProvider;
594598
let contextLookupModel = activeModel;
595599
const runtimeModelRaw = normalizeOptionalString(entry?.model) ?? "";
@@ -716,13 +720,7 @@ export function buildStatusMessage(args: StatusArgs): string {
716720
typeof resolvedActiveContextTokens === "number"
717721
? Math.min(explicitRuntimeContextTokens, resolvedActiveContextTokens)
718722
: (explicitRuntimeContextTokens ?? resolvedActiveContextTokens);
719-
const channelModelNote = resolveChannelModelNote({
720-
config: args.config,
721-
entry,
722-
selectedProvider,
723-
selectedModel,
724-
parentSessionKey: args.parentSessionKey,
725-
});
723+
const channelModelNote = channelModelRef ? "channel override" : undefined;
726724
const persistedContextTokens =
727725
typeof entry?.contextTokens === "number" && entry.contextTokens > 0
728726
? entry.contextTokens
@@ -972,9 +970,16 @@ export function buildStatusMessage(args: StatusArgs): string {
972970
const costLabel = hasUsage ? formatUsd(cost) : undefined;
973971

974972
const selectedAuthLabel = selectedAuthLabelValue ? ` · 🔑 ${selectedAuthLabelValue}` : "";
973+
const activeAuthLabel = activeAuthLabelValue ? ` · 🔑 ${activeAuthLabelValue}` : "";
975974
const modelNote = channelModelNote ? ` · ${channelModelNote}` : "";
976975
const configuredDefaultModelLabel = normalizeOptionalString(args.configuredDefaultModelLabel);
977976
const sessionHasPersistedModelSelection = hasUserPinnedModelSelection(entry);
977+
const channelOverrideDiffersFromSelected =
978+
channelModelRef !== undefined &&
979+
channelModelRef.label !== selectedModelLabel &&
980+
!areRuntimeModelRefsEquivalent(channelModelRef.label, selectedModelLabel, {
981+
config: args.config,
982+
});
978983
const configDefaultDiffersFromSession =
979984
sessionHasPersistedModelSelection &&
980985
configuredDefaultModelLabel &&
@@ -991,7 +996,12 @@ export function buildStatusMessage(args: StatusArgs): string {
991996
`↩️ Clear with: /model ${configuredDefaultModelLabel} or /reset`,
992997
"📖 Docs: https://docs.openclaw.ai/concepts/models#selection-source-and-fallback-behavior",
993998
]
994-
: [`🧠 Model: ${selectedModelLabel}${selectedAuthLabel}${modelNote}`];
999+
: channelOverrideDiffersFromSelected && channelModelRef
1000+
? [
1001+
`🧠 Model: ${channelModelRef.label}${activeAuthLabel}${modelNote}`,
1002+
`📌 Session/default model: ${selectedModelLabel}${selectedAuthLabel}`,
1003+
]
1004+
: [`🧠 Model: ${selectedModelLabel}${selectedAuthLabel}${modelNote}`];
9951005

9961006
// Show configured fallback models (from agent model config)
9971007
const configuredFallbacks = (() => {

0 commit comments

Comments
 (0)