fix: unify context limit resolution behind provider API (#11213)
Signed-off-by: Jack Amadeo <jackamadeo@squareup.com>
This commit is contained in:
@@ -160,6 +160,7 @@ describe('applyGooseSessionNotification', () => {
|
||||
type: 'tokenState',
|
||||
tokenState: {
|
||||
totalTokens: 42,
|
||||
contextLimit: 200,
|
||||
accumulatedInputTokens: 10,
|
||||
accumulatedOutputTokens: 15,
|
||||
accumulatedTotalTokens: 25,
|
||||
|
||||
@@ -219,7 +219,7 @@ describe('ACP providers', () => {
|
||||
|
||||
expect(result.connectionChecked).toBe(true);
|
||||
expect(result.provider.metadata.known_models).toEqual([
|
||||
{ name: 'claude-sonnet', context_limit: 0, reasoning: undefined },
|
||||
{ name: 'claude-sonnet', context_limit: undefined, reasoning: undefined },
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -268,7 +268,7 @@ describe('ACP providers', () => {
|
||||
});
|
||||
expect(enabled.is_configured).toBe(true);
|
||||
expect(enabled.metadata.known_models).toEqual([
|
||||
{ name: 'claude-sonnet', context_limit: 0, reasoning: undefined },
|
||||
{ name: 'claude-sonnet', context_limit: undefined, reasoning: undefined },
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@@ -872,6 +872,7 @@ describe('createAcpSessionNotificationAdapter', () => {
|
||||
type: 'tokenState',
|
||||
tokenState: {
|
||||
totalTokens: 42,
|
||||
contextLimit: 200,
|
||||
accumulatedInputTokens: 10,
|
||||
accumulatedOutputTokens: 15,
|
||||
accumulatedTotalTokens: 25,
|
||||
|
||||
@@ -15,6 +15,7 @@ export function applyGooseSessionNotification(
|
||||
type: 'tokenState',
|
||||
tokenState: {
|
||||
totalTokens: update.used,
|
||||
contextLimit: update.contextLimit,
|
||||
accumulatedInputTokens: update.accumulatedInputTokens,
|
||||
accumulatedOutputTokens: update.accumulatedOutputTokens,
|
||||
accumulatedTotalTokens: update.accumulatedInputTokens + update.accumulatedOutputTokens,
|
||||
|
||||
@@ -71,7 +71,7 @@ function providerEntryToDetails(entry: ProviderInventoryEntryDto): ProviderDetai
|
||||
})),
|
||||
known_models: entry.models.map((model) => ({
|
||||
name: model.id,
|
||||
context_limit: model.contextLimit ?? 0,
|
||||
context_limit: model.contextLimit ?? undefined,
|
||||
reasoning: model.reasoning ?? undefined,
|
||||
})),
|
||||
setup_steps: entry.setupSteps,
|
||||
|
||||
@@ -522,6 +522,7 @@ export default function BaseChat({
|
||||
initialValue={initialPrompt}
|
||||
setView={setView}
|
||||
totalTokens={tokenState?.totalTokens ?? session?.usage?.total_tokens ?? undefined}
|
||||
contextLimit={tokenState?.contextLimit}
|
||||
accumulatedInputTokens={
|
||||
tokenState?.accumulatedInputTokens ??
|
||||
session?.accumulated_usage?.input_tokens ??
|
||||
|
||||
@@ -82,7 +82,7 @@ const removeQueuedMessage = (messages: QueuedMessage[], messageId: string): Queu
|
||||
|
||||
const MAX_IMAGES_PER_MESSAGE = 10;
|
||||
|
||||
const TOKEN_LIMIT_DEFAULT = 128000; // fallback for custom models that the backend doesn't know about
|
||||
const TOKEN_LIMIT_DEFAULT = 128000; // used before a session has a backend-resolved limit
|
||||
|
||||
const getContextAlertType = (totalTokens: number, tokenLimit: number): AlertType => {
|
||||
const percentage = tokenLimit ? (totalTokens / tokenLimit) * 100 : 0;
|
||||
@@ -172,6 +172,7 @@ interface ChatInputProps {
|
||||
onFilesProcessed?: () => void;
|
||||
setView: (view: View) => void;
|
||||
totalTokens?: number;
|
||||
contextLimit?: number;
|
||||
accumulatedInputTokens?: number;
|
||||
accumulatedOutputTokens?: number;
|
||||
accumulatedCost?: number | null;
|
||||
@@ -207,6 +208,7 @@ export default function ChatInput({
|
||||
onFilesProcessed,
|
||||
setView,
|
||||
totalTokens,
|
||||
contextLimit,
|
||||
accumulatedInputTokens,
|
||||
accumulatedOutputTokens,
|
||||
accumulatedCost,
|
||||
@@ -581,7 +583,11 @@ export default function ChatInput({
|
||||
// Load providers and get current model's token limit
|
||||
const loadProviderDetails = async () => {
|
||||
try {
|
||||
// Reset token limit loaded state
|
||||
if (sessionId) {
|
||||
setTokenLimit(0);
|
||||
setIsTokenLimitLoaded(false);
|
||||
return;
|
||||
}
|
||||
setIsTokenLimitLoaded(false);
|
||||
|
||||
// Use effective model/provider (includes overrides from in-session model changes),
|
||||
@@ -642,7 +648,20 @@ export default function ChatInput({
|
||||
useEffect(() => {
|
||||
loadProviderDetails();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [effectiveModel, effectiveProvider, configModel, configProvider]);
|
||||
}, [effectiveModel, effectiveProvider, configModel, configProvider, sessionId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (contextLimit === undefined) {
|
||||
if (sessionId) {
|
||||
setTokenLimit(0);
|
||||
setIsTokenLimitLoaded(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
setTokenLimit(contextLimit);
|
||||
setIsTokenLimitLoaded(true);
|
||||
}, [contextLimit, sessionId]);
|
||||
|
||||
// Handle token usage alerts
|
||||
useEffect(() => {
|
||||
|
||||
+2
-2
@@ -459,8 +459,8 @@ export default function CustomProviderForm({
|
||||
|
||||
const modelList = models
|
||||
.split(',')
|
||||
.map((m) => m.trim())
|
||||
.filter((m) => m);
|
||||
.map((name) => name.trim())
|
||||
.filter(Boolean);
|
||||
|
||||
let allHeaders = [...headers];
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ export type TokenState = {
|
||||
inputTokens: number;
|
||||
outputTokens: number;
|
||||
totalTokens: number;
|
||||
contextLimit?: number;
|
||||
};
|
||||
|
||||
export interface ChatType {
|
||||
|
||||
@@ -13,7 +13,7 @@ export type ConfigKey = {
|
||||
};
|
||||
|
||||
export type ModelInfo = {
|
||||
context_limit: number;
|
||||
context_limit?: number | null;
|
||||
currency?: string | null;
|
||||
input_token_cost?: number | null;
|
||||
name: string;
|
||||
|
||||
Reference in New Issue
Block a user