diff --git a/CHANGELOG.md b/CHANGELOG.md index b1967d0e..dc2240e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,8 @@ ### Fixed +- MCP Tools in Settings → System now uses a bounded scroll region with 5-item default pages, a per-page selector up to 40 tools, and a visible result summary, so large MCP tool inventories no longer make the settings panel balloon indefinitely. + - **PR #2201** by @MrFant — Multi-turn conversations with thinking-mode providers (MiMo/Xiaomi, DeepSeek, Kimi/Moonshot) no longer 400 with `Param Incorrect: reasoning_content must be passed back`. WebUI's `_sanitize_messages_for_api()` strips fields not in `_API_SAFE_MSG_KEYS` before sending conversation history to the LLM; `reasoning_content` was missing from the whitelist, so when history was replayed on the second turn, the assistant message with `tool_calls` arrived without `reasoning_content` and providers enforcing thinking-mode echo-back rejected it. One-line fix: adds `'reasoning_content'` to `_API_SAFE_MSG_KEYS`. CLI was unaffected because `run_agent.py` has its own `_copy_reasoning_content_for_api()` that doesn't go through this filter. - **PR #2198** by @Michaelyklam — Fork-from-here keep-count was off-by-one (or larger) for truncated sessions where the visible-message index didn't match the absolute transcript index. JS now sends `_oldestIdx + msgIdx` (the absolute message index in the full transcript) as `keep_count` instead of the visible-window-relative index — captured *before* `_ensureAllMessagesLoaded()` resets `_oldestIdx`, so the index remains stable. Backend `source_messages[:keep_count]` then forks from the correct point even when the user has only loaded a tail window. When the full transcript is loaded (`_oldestIdx==0`), behavior is unchanged. 186-line regression suite in `tests/test_issue2184_fork_from_here_absolute_index.py` explicitly pins `keep_count: absoluteKeepCount` (and forbids the old `keep_count: msgIdx` form). diff --git a/docs/pr-media/2210/after-mcp-tools-paginated.png b/docs/pr-media/2210/after-mcp-tools-paginated.png new file mode 100644 index 00000000..e2793510 Binary files /dev/null and b/docs/pr-media/2210/after-mcp-tools-paginated.png differ diff --git a/docs/pr-media/2210/before-mcp-tools-unbounded.png b/docs/pr-media/2210/before-mcp-tools-unbounded.png new file mode 100644 index 00000000..9123a563 Binary files /dev/null and b/docs/pr-media/2210/before-mcp-tools-unbounded.png differ diff --git a/static/i18n.js b/static/i18n.js index b0a28ade..4e9fe34d 100644 --- a/static/i18n.js +++ b/static/i18n.js @@ -92,6 +92,20 @@ const LOCALES = { mcp_tools_load_failed: 'Failed to load MCP tools.', mcp_tools_schema_empty: 'No schema parameters.', mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe servers.', + mcp_tools_summary_no_matches: (query,total) => `No MCP tools matching “${query}” (${total} total MCP tools).`, + mcp_tools_summary_none: 'No MCP tools to show.', + mcp_tools_summary_matching: (query) => ` matching “${query}”`, + mcp_tools_summary_total_note: (total) => ` (${total} total MCP tools)`, + mcp_tools_summary_showing: (start,end,filtered,searchNote,totalNote,page,pages) => `Showing ${start}-${end} of ${filtered} MCP tools${searchNote}${totalNote}. Page ${page} of ${pages}.`, + mcp_tools_page_size_prefix: 'Show', + mcp_tools_page_size_suffix: 'per page', + mcp_tools_per_page_aria: 'MCP tools per page', + mcp_tools_inactive_configured_servers: (servers) => `Configured but inactive in this WebUI runtime: ${servers}.`, + mcp_tools_pagination_label: 'MCP tools pagination', + mcp_tools_previous_page: '‹ Prev', + mcp_tools_previous_page_aria: 'Previous MCP tools page', + mcp_tools_next_page: 'Next ›', + mcp_tools_next_page_aria: 'Next MCP tools page', // PDF preview (#480) pdf_loading: 'Loading PDF {0}…', pdf_too_large: 'PDF too large for inline preview', @@ -1217,6 +1231,20 @@ const LOCALES = { mcp_tools_load_failed: 'Caricamento strumenti MCP fallito.', mcp_tools_schema_empty: 'Nessun parametro schema.', mcp_tools_runtime_note: "L'inventario strumenti usa solo dati runtime MCP già noti; la WebUI non avvia né interroga i server.", + mcp_tools_summary_no_matches: (query,total) => `No MCP tools matching “${query}” (${total} total MCP tools).`, + mcp_tools_summary_none: 'No MCP tools to show.', + mcp_tools_summary_matching: (query) => ` matching “${query}”`, + mcp_tools_summary_total_note: (total) => ` (${total} total MCP tools)`, + mcp_tools_summary_showing: (start,end,filtered,searchNote,totalNote,page,pages) => `Showing ${start}-${end} of ${filtered} MCP tools${searchNote}${totalNote}. Page ${page} of ${pages}.`, + mcp_tools_page_size_prefix: 'Show', + mcp_tools_page_size_suffix: 'per page', + mcp_tools_per_page_aria: 'MCP tools per page', + mcp_tools_inactive_configured_servers: (servers) => `Configured but inactive in this WebUI runtime: ${servers}.`, + mcp_tools_pagination_label: 'MCP tools pagination', + mcp_tools_previous_page: '‹ Prev', + mcp_tools_previous_page_aria: 'Previous MCP tools page', + mcp_tools_next_page: 'Next ›', + mcp_tools_next_page_aria: 'Next MCP tools page', // PDF preview (#480) pdf_loading: 'Caricamento PDF {0}…', pdf_too_large: "PDF troppo grande per l'anteprima inline", @@ -2334,6 +2362,20 @@ const LOCALES = { mcp_tools_load_failed: 'MCP ツールの読み込みに失敗しました。', mcp_tools_schema_empty: 'スキーマパラメータはありません。', mcp_tools_runtime_note: 'ツール一覧は既知の MCP ランタイム情報のみを使用します。WebUI はサーバーの起動や探索を行いません。', + mcp_tools_summary_no_matches: (query,total) => `No MCP tools matching “${query}” (${total} total MCP tools).`, + mcp_tools_summary_none: 'No MCP tools to show.', + mcp_tools_summary_matching: (query) => ` matching “${query}”`, + mcp_tools_summary_total_note: (total) => ` (${total} total MCP tools)`, + mcp_tools_summary_showing: (start,end,filtered,searchNote,totalNote,page,pages) => `Showing ${start}-${end} of ${filtered} MCP tools${searchNote}${totalNote}. Page ${page} of ${pages}.`, + mcp_tools_page_size_prefix: 'Show', + mcp_tools_page_size_suffix: 'per page', + mcp_tools_per_page_aria: 'MCP tools per page', + mcp_tools_inactive_configured_servers: (servers) => `Configured but inactive in this WebUI runtime: ${servers}.`, + mcp_tools_pagination_label: 'MCP tools pagination', + mcp_tools_previous_page: '‹ Prev', + mcp_tools_previous_page_aria: 'Previous MCP tools page', + mcp_tools_next_page: 'Next ›', + mcp_tools_next_page_aria: 'Next MCP tools page', // PDF preview (#480) pdf_loading: 'PDF {0} を読み込み中…', pdf_too_large: 'PDF が大きすぎてインラインプレビューできません', @@ -3453,6 +3495,20 @@ const LOCALES = { mcp_tools_load_failed: 'Failed to load MCP tools.', mcp_tools_schema_empty: 'No schema parameters.', mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe servers.', + mcp_tools_summary_no_matches: (query,total) => `No MCP tools matching “${query}” (${total} total MCP tools).`, + mcp_tools_summary_none: 'No MCP tools to show.', + mcp_tools_summary_matching: (query) => ` matching “${query}”`, + mcp_tools_summary_total_note: (total) => ` (${total} total MCP tools)`, + mcp_tools_summary_showing: (start,end,filtered,searchNote,totalNote,page,pages) => `Showing ${start}-${end} of ${filtered} MCP tools${searchNote}${totalNote}. Page ${page} of ${pages}.`, + mcp_tools_page_size_prefix: 'Show', + mcp_tools_page_size_suffix: 'per page', + mcp_tools_per_page_aria: 'MCP tools per page', + mcp_tools_inactive_configured_servers: (servers) => `Configured but inactive in this WebUI runtime: ${servers}.`, + mcp_tools_pagination_label: 'MCP tools pagination', + mcp_tools_previous_page: '‹ Prev', + mcp_tools_previous_page_aria: 'Previous MCP tools page', + mcp_tools_next_page: 'Next ›', + mcp_tools_next_page_aria: 'Next MCP tools page', thinking: 'Думаю', expand_all: 'Развернуть всё', collapse_all: 'Свернуть всё', @@ -4504,6 +4560,20 @@ const LOCALES = { mcp_tools_load_failed: 'Failed to load MCP tools.', mcp_tools_schema_empty: 'No schema parameters.', mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe servers.', + mcp_tools_summary_no_matches: (query,total) => `No MCP tools matching “${query}” (${total} total MCP tools).`, + mcp_tools_summary_none: 'No MCP tools to show.', + mcp_tools_summary_matching: (query) => ` matching “${query}”`, + mcp_tools_summary_total_note: (total) => ` (${total} total MCP tools)`, + mcp_tools_summary_showing: (start,end,filtered,searchNote,totalNote,page,pages) => `Showing ${start}-${end} of ${filtered} MCP tools${searchNote}${totalNote}. Page ${page} of ${pages}.`, + mcp_tools_page_size_prefix: 'Show', + mcp_tools_page_size_suffix: 'per page', + mcp_tools_per_page_aria: 'MCP tools per page', + mcp_tools_inactive_configured_servers: (servers) => `Configured but inactive in this WebUI runtime: ${servers}.`, + mcp_tools_pagination_label: 'MCP tools pagination', + mcp_tools_previous_page: '‹ Prev', + mcp_tools_previous_page_aria: 'Previous MCP tools page', + mcp_tools_next_page: 'Next ›', + mcp_tools_next_page_aria: 'Next MCP tools page', thinking: 'Pensando', expand_all: 'Expandir todo', collapse_all: 'Contraer todo', @@ -5558,6 +5628,20 @@ const LOCALES = { mcp_tools_load_failed: 'Failed to load MCP tools.', mcp_tools_schema_empty: 'No schema parameters.', mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe servers.', + mcp_tools_summary_no_matches: (query,total) => `No MCP tools matching “${query}” (${total} total MCP tools).`, + mcp_tools_summary_none: 'No MCP tools to show.', + mcp_tools_summary_matching: (query) => ` matching “${query}”`, + mcp_tools_summary_total_note: (total) => ` (${total} total MCP tools)`, + mcp_tools_summary_showing: (start,end,filtered,searchNote,totalNote,page,pages) => `Showing ${start}-${end} of ${filtered} MCP tools${searchNote}${totalNote}. Page ${page} of ${pages}.`, + mcp_tools_page_size_prefix: 'Show', + mcp_tools_page_size_suffix: 'per page', + mcp_tools_per_page_aria: 'MCP tools per page', + mcp_tools_inactive_configured_servers: (servers) => `Configured but inactive in this WebUI runtime: ${servers}.`, + mcp_tools_pagination_label: 'MCP tools pagination', + mcp_tools_previous_page: '‹ Prev', + mcp_tools_previous_page_aria: 'Previous MCP tools page', + mcp_tools_next_page: 'Next ›', + mcp_tools_next_page_aria: 'Next MCP tools page', thinking: 'Nachdenken', expand_all: 'Alle ausklappen', collapse_all: 'Alle einklappen', @@ -6616,6 +6700,20 @@ const LOCALES = { mcp_tools_load_failed: '加载 MCP 工具失败。', mcp_tools_schema_empty: '无参数。', mcp_tools_runtime_note: '工具清单仅使用已知的活跃 MCP 运行时数据;WebUI 不会启动或探测服务器。', + mcp_tools_summary_no_matches: (query,total) => `No MCP tools matching “${query}” (${total} total MCP tools).`, + mcp_tools_summary_none: 'No MCP tools to show.', + mcp_tools_summary_matching: (query) => ` matching “${query}”`, + mcp_tools_summary_total_note: (total) => ` (${total} total MCP tools)`, + mcp_tools_summary_showing: (start,end,filtered,searchNote,totalNote,page,pages) => `Showing ${start}-${end} of ${filtered} MCP tools${searchNote}${totalNote}. Page ${page} of ${pages}.`, + mcp_tools_page_size_prefix: 'Show', + mcp_tools_page_size_suffix: 'per page', + mcp_tools_per_page_aria: 'MCP tools per page', + mcp_tools_inactive_configured_servers: (servers) => `Configured but inactive in this WebUI runtime: ${servers}.`, + mcp_tools_pagination_label: 'MCP tools pagination', + mcp_tools_previous_page: '‹ Prev', + mcp_tools_previous_page_aria: 'Previous MCP tools page', + mcp_tools_next_page: 'Next ›', + mcp_tools_next_page_aria: 'Next MCP tools page', thinking: '思考过程', expand_all: '全部展开', collapse_all: '全部折叠', @@ -7662,6 +7760,20 @@ const LOCALES = { mcp_tools_load_failed: 'Failed to load MCP tools.', mcp_tools_schema_empty: 'No schema parameters.', mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe servers.', + mcp_tools_summary_no_matches: (query,total) => `No MCP tools matching “${query}” (${total} total MCP tools).`, + mcp_tools_summary_none: 'No MCP tools to show.', + mcp_tools_summary_matching: (query) => ` matching “${query}”`, + mcp_tools_summary_total_note: (total) => ` (${total} total MCP tools)`, + mcp_tools_summary_showing: (start,end,filtered,searchNote,totalNote,page,pages) => `Showing ${start}-${end} of ${filtered} MCP tools${searchNote}${totalNote}. Page ${page} of ${pages}.`, + mcp_tools_page_size_prefix: 'Show', + mcp_tools_page_size_suffix: 'per page', + mcp_tools_per_page_aria: 'MCP tools per page', + mcp_tools_inactive_configured_servers: (servers) => `Configured but inactive in this WebUI runtime: ${servers}.`, + mcp_tools_pagination_label: 'MCP tools pagination', + mcp_tools_previous_page: '‹ Prev', + mcp_tools_previous_page_aria: 'Previous MCP tools page', + mcp_tools_next_page: 'Next ›', + mcp_tools_next_page_aria: 'Next MCP tools page', thinking: '\u601d\u8003\u904e\u7a0b', expand_all: '\u5168\u90e8\u5c55\u958b', collapse_all: '\u5168\u90e8\u6298\u758a', @@ -9764,6 +9876,20 @@ const LOCALES = { mcp_tools_load_failed: 'Failed to load MCP tools.', mcp_tools_schema_empty: 'No schema parameters.', mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe servers.', + mcp_tools_summary_no_matches: (query,total) => `No MCP tools matching “${query}” (${total} total MCP tools).`, + mcp_tools_summary_none: 'No MCP tools to show.', + mcp_tools_summary_matching: (query) => ` matching “${query}”`, + mcp_tools_summary_total_note: (total) => ` (${total} total MCP tools)`, + mcp_tools_summary_showing: (start,end,filtered,searchNote,totalNote,page,pages) => `Showing ${start}-${end} of ${filtered} MCP tools${searchNote}${totalNote}. Page ${page} of ${pages}.`, + mcp_tools_page_size_prefix: 'Show', + mcp_tools_page_size_suffix: 'per page', + mcp_tools_per_page_aria: 'MCP tools per page', + mcp_tools_inactive_configured_servers: (servers) => `Configured but inactive in this WebUI runtime: ${servers}.`, + mcp_tools_pagination_label: 'MCP tools pagination', + mcp_tools_previous_page: '‹ Prev', + mcp_tools_previous_page_aria: 'Previous MCP tools page', + mcp_tools_next_page: 'Next ›', + mcp_tools_next_page_aria: 'Next MCP tools page', thinking: '생각 중', expand_all: '모두 펼치기', collapse_all: '모두 접기', @@ -10878,6 +11004,20 @@ const LOCALES = { mcp_tools_load_failed: 'Échec du chargement des outils MCP.', mcp_tools_schema_empty: 'Aucun paramètre de schéma.', mcp_tools_runtime_note: 'L\'inventaire des outils utilise uniquement les données d\'exécution MCP actives déjà connues ; le WebUI ne démarre pas et ne sonde pas les serveurs.', + mcp_tools_summary_no_matches: (query,total) => `No MCP tools matching “${query}” (${total} total MCP tools).`, + mcp_tools_summary_none: 'No MCP tools to show.', + mcp_tools_summary_matching: (query) => ` matching “${query}”`, + mcp_tools_summary_total_note: (total) => ` (${total} total MCP tools)`, + mcp_tools_summary_showing: (start,end,filtered,searchNote,totalNote,page,pages) => `Showing ${start}-${end} of ${filtered} MCP tools${searchNote}${totalNote}. Page ${page} of ${pages}.`, + mcp_tools_page_size_prefix: 'Show', + mcp_tools_page_size_suffix: 'per page', + mcp_tools_per_page_aria: 'MCP tools per page', + mcp_tools_inactive_configured_servers: (servers) => `Configured but inactive in this WebUI runtime: ${servers}.`, + mcp_tools_pagination_label: 'MCP tools pagination', + mcp_tools_previous_page: '‹ Prev', + mcp_tools_previous_page_aria: 'Previous MCP tools page', + mcp_tools_next_page: 'Next ›', + mcp_tools_next_page_aria: 'Next MCP tools page', pdf_loading: 'Chargement du PDF {0}…', pdf_too_large: 'PDF trop volumineux pour un aperçu en ligne', pdf_no_pages: 'Le PDF n\'a pas de pages', diff --git a/static/index.html b/static/index.html index 8a530d16..f7c3f07d 100644 --- a/static/index.html +++ b/static/index.html @@ -1138,7 +1138,9 @@