From 2a79f747019c2b64888e4cfce477ff5790fc5b41 Mon Sep 17 00:00:00 2001
From: Alix-007
Date: Thu, 20 Aug 2026 15:22:30 +0800
Subject: [PATCH] fix(ui): prioritize active session quota provider (#120557)
(#122053)
---
.../pages/chat/chat-composer-context.test.ts | 48 +++++++++++--------
.../chat/components/chat-composer-context.ts | 4 +-
2 files changed, 28 insertions(+), 24 deletions(-)
diff --git a/ui/src/pages/chat/chat-composer-context.test.ts b/ui/src/pages/chat/chat-composer-context.test.ts
index cacd3787c174..ca4627976845 100644
--- a/ui/src/pages/chat/chat-composer-context.test.ts
+++ b/ui/src/pages/chat/chat-composer-context.test.ts
@@ -178,8 +178,17 @@ describe("renderChatComposer context usage", () => {
expect(container.textContent).not.toContain("Est. cost");
});
- it("falls back from an unmatched session provider to the response quota group", () => {
- const container = renderComposer({
+ it("uses response provenance only when the session provider is absent", () => {
+ const session = {
+ key: "main",
+ kind: "direct",
+ updatedAt: null,
+ totalTokens: 1_000,
+ contextTokens: 200_000,
+ model: "gateway-injected",
+ modelProvider: "openclaw" as string | undefined,
+ };
+ const composerProps = {
messages: [
{ role: "user", content: "hi" },
{
@@ -191,19 +200,9 @@ describe("renderChatComposer context usage", () => {
},
],
sessions: {
- sessions: [
- {
- key: "main",
- kind: "direct",
- updatedAt: null,
- totalTokens: 1_000,
- contextTokens: 200_000,
- model: "gateway-injected",
- modelProvider: "openclaw",
- },
- ],
+ sessions: [session],
defaults: { contextTokens: 200_000 },
- } as never,
+ },
providerUsage: {
modelAuthStatusResult: {
ts: Date.now(),
@@ -231,16 +230,23 @@ describe("renderChatComposer context usage", () => {
],
},
},
- });
-
- expect(
+ };
+ const providerNames = (container: HTMLElement) =>
[...container.querySelectorAll("[data-chat-usage-provider='true']")].map((row) =>
row.textContent?.replace(/\s+/g, " ").trim(),
- ),
- ).toEqual(["Provider: OpenAI", "Provider: Claude"]);
- expect(container.textContent).not.toContain("Est. cost");
- expect(container.textContent).not.toContain("Cost by Type");
+ );
+
+ const container = renderComposer(composerProps as never);
+
+ expect(providerNames(container)).toEqual(["Provider: Claude", "Provider: OpenAI"]);
+ expect(container.textContent).toContain("Cost by Type");
expect(container.textContent).not.toContain("Model:");
+
+ session.modelProvider = undefined;
+ expect(providerNames(renderComposer(composerProps as never))).toEqual([
+ "Provider: OpenAI",
+ "Provider: Claude",
+ ]);
});
it("omits the cost-by-type section when every recorded cost is zero", () => {
diff --git a/ui/src/pages/chat/components/chat-composer-context.ts b/ui/src/pages/chat/components/chat-composer-context.ts
index 4cc8685bd931..b5fe879d559d 100644
--- a/ui/src/pages/chat/components/chat-composer-context.ts
+++ b/ui/src/pages/chat/components/chat-composer-context.ts
@@ -120,7 +120,6 @@ function getContextNoticeViewModel(
input: number | null;
output: number | null;
cost: number | null;
- provider: string | null;
detail: string;
color: string;
bg: string;
@@ -154,7 +153,6 @@ function getContextNoticeViewModel(
input,
output,
cost,
- provider: session?.modelProvider?.trim() || null,
};
if (!warning) {
return {
@@ -350,7 +348,7 @@ export function renderContextNotice(
)
: undefined;
};
- const currentGroup = findQuotaGroup(model?.provider) ?? findQuotaGroup(providerCosts?.provider);
+ const currentGroup = findQuotaGroup(session?.modelProvider?.trim() || providerCosts?.provider);
const planGroups = currentGroup
? [currentGroup, ...quotaGroups.filter((group) => group !== currentGroup)]
: quotaGroups;