diff --git a/src/games/storywriter/components/chat-sidebar.tsx b/src/games/storywriter/components/chat-sidebar.tsx index 79471d5..9ac820a 100644 --- a/src/games/storywriter/components/chat-sidebar.tsx +++ b/src/games/storywriter/components/chat-sidebar.tsx @@ -128,14 +128,14 @@ export const ChatPanel = ({ visible }: { visible: boolean }) => { model: model.id, input: chatRequest?.messages ?? [], tools: chatRequest?.tools, - enable_thinking: chatRequest?.enable_thinking, + reasoning: chatRequest?.reasoning, }; const response = await LLM.countTokens(connection, countRequest); setTokenCount({ taken: response.input_tokens, - total: model.max_context ?? response.input_tokens, + total: model.context_length ?? response.input_tokens, }); } catch { setTokenCount(null); diff --git a/src/games/storywriter/components/settings/connection.tsx b/src/games/storywriter/components/settings/connection.tsx index cc08e25..4eecefa 100644 --- a/src/games/storywriter/components/settings/connection.tsx +++ b/src/games/storywriter/components/settings/connection.tsx @@ -41,15 +41,13 @@ export const ConnectionSettings = () => { const groupedModels = useMemo(() => { const sorted = (modelsData ?? []).sort((a, b) => { - const aWeight = Number(a.support_tools) * 2 + Number(a.support_thinking); - const bWeight = Number(b.support_tools) * 2 + Number(b.support_thinking); + const aWeight = Number(a.supported_parameters.includes('tools')) * 2 + Number(a.supported_parameters.includes('reasoning')); + const bWeight = Number(b.supported_parameters.includes('tools')) * 2 + Number(b.supported_parameters.includes('reasoning')); if (aWeight !== bWeight) return bWeight - aWeight; - const aContext = a.max_context ?? 0; - const bContext = b.max_context ?? 0; - if (aContext !== bContext) return bContext - aContext; + if (a.context_length !== b.context_length) return b.context_length - a.context_length; return a.id.localeCompare(b.id); }); - const groups = Map.groupBy(sorted, m => m.max_context ?? 0); + const groups = Map.groupBy(sorted, m => m.context_length); return Array.from(groups.entries()) .sort((a, b) => b[0] - a[0]) .map(([context, models]) => ({ context, models })); @@ -161,7 +159,7 @@ export const ConnectionSettings = () => { {models.map(m => ( ))} diff --git a/src/games/storywriter/utils/llm.ts b/src/games/storywriter/utils/llm.ts index 342445e..c429876 100644 --- a/src/games/storywriter/utils/llm.ts +++ b/src/games/storywriter/utils/llm.ts @@ -54,14 +54,23 @@ namespace LLM { model: string; messages: ChatMessage[]; tools?: Tool[]; + tool_choice?: 'none' | 'auto' | 'required' | { type: 'function'; function: { name: string } }; + parallel_tool_calls?: boolean; temperature?: number; max_tokens?: number; + max_completion_tokens?: number; stop?: string | string[]; banned_tokens?: string[]; top_p?: number; + top_k?: number; + min_p?: number; frequency_penalty?: number; - presence_penalty?: number; - enable_thinking?: boolean; + repetition_penalty?: number; + reasoning?: { + effort?: 'xhigh' | 'high' | 'medium' | 'low' | 'minimal' | 'none'; + exclude?: boolean; + max_tokens?: number; + }; add_generation_prompt?: boolean; } @@ -109,11 +118,13 @@ namespace LLM { object: 'model'; created: number; owned_by: string; - support_tools: boolean; - support_infill: boolean; - support_thinking: boolean; - max_context?: number; - max_length?: number; + context_length: number; + supported_parameters: string[]; + top_provider: { + context_length: number; + max_completion_tokens: number; + is_moderated: boolean; + }; } export interface ModelsResponse { @@ -132,7 +143,11 @@ namespace LLM { input: LLM.ChatMessage[]; tools?: LLM.Tool[]; add_generation_prompt?: boolean; - enable_thinking?: boolean; + reasoning?: { + effort?: string; + exclude?: boolean; + max_tokens?: number; + }; } export type CountTokensRequest = CountTokensRequestString | CountTokensRequestMessages; @@ -190,7 +205,7 @@ namespace LLM { }); let closed = false; - const handleEnd = (e?: unknown) => { + const handleEnd = (_e?: unknown) => { if (closed) return; closed = true; controller.close(); diff --git a/src/games/storywriter/utils/prompt.ts b/src/games/storywriter/utils/prompt.ts index e323ba9..f458923 100644 --- a/src/games/storywriter/utils/prompt.ts +++ b/src/games/storywriter/utils/prompt.ts @@ -395,21 +395,19 @@ namespace Prompt { return { model: model.id, messages: applyVars(formattedMessages), - enable_thinking: false, - max_tokens: model.max_length ? model.max_length : 2048, - add_generation_prompt: true, + max_tokens: model.top_provider.max_completion_tokens || 2048, banned_tokens: state.bannedTokens, }; } // Estimate token budget for story text let storyTokenBudget = 0; - if (model.max_context) { + if (model.context_length) { const nonStorySystem = formatSystemPrompt(state, 0); const chatText = messages.map(m => m.content).join('\n'); - const maxOutput = model.max_length ?? 2048; + const maxOutput = model.top_provider.max_completion_tokens || 2048; const otherTokens = approxTokens(nonStorySystem) + approxTokens(chatText) + maxOutput; - storyTokenBudget = model.max_context - otherTokens; + storyTokenBudget = model.context_length - otherTokens; } messages.unshift({ @@ -423,8 +421,8 @@ namespace Prompt { messages: applyVars(messages), tools: Tools.getTools(), banned_tokens: state.bannedTokens, - enable_thinking: enableThinking, - max_tokens: model.max_length ? model.max_length : 2048, + reasoning: { effort: enableThinking ? 'high' : 'none' }, + max_tokens: model.top_provider.max_completion_tokens || 2048, }; } }