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;