v0.16.18: 网络超时 30s→900s + 流式超时动态计算修复 + 预存编译错误修复

This commit is contained in:
2026-08-01 14:13:04 +08:00
parent 794f94ab89
commit e140e735de
10 changed files with 126 additions and 126 deletions
+1 -1
View File
@@ -101,7 +101,7 @@ export function createMenu(): void {
dialog.showMessageBox(mainWindow!, {
type: 'info',
title: '关于 Metona Ollama',
message: 'Metona Ollama Desktop v0.16.17',
message: 'Metona Ollama Desktop v0.16.18',
detail: 'TypeScript + Electron Ollama AI 聊天客户端\n\nhttps://gitee.com/thzxx/metona-ollama',
icon: getIconPath()
});
+3 -3
View File
@@ -124,8 +124,8 @@ export function killToolProcess(): boolean {
/** HTTP 请求超时(毫秒),默认 30s,可通过 IPC 设置 */
let HTTP_TIMEOUT = 30_000;
/** HTTP 请求超时(毫秒),默认 900s,可通过 IPC 设置 */
let HTTP_TIMEOUT = 900_000;
/** 设置 HTTP 请求超时(毫秒),0=禁用超时 */
export function setHTTPTimeout(ms: number): void {
@@ -576,7 +576,7 @@ export async function handleWebFetch(params: { url: string; max_chars?: number;
} catch (err) {
const errMsg = (err as Error).message;
if (errMsg.includes('abort') && attempt < maxAttempts - 1) {
lastError = `请求超时 (${HTTP_TIMEOUT > 0 ? HTTP_TIMEOUT / 1000 : '∞'}s)(将重试)`;
lastError = `请求超时 (${HTTP_TIMEOUT > 0 ? HTTP_TIMEOUT / 1000 : '∞'}s)(将重试)`; // 900s 默认,大页面/慢服务器需要更长时间
continue;
}
if (errMsg.includes('abort')) {
+1 -1
View File
@@ -129,7 +129,7 @@ function renderMetricsDashboard(): void {
suggestionsEl.innerHTML = suggestions.map(s => `
<div class="md-suggestion">
<span class="md-suggestion-severity md-severity-${s.severity}">${s.severity}</span>
<span class="md-suggestion-msg">${s.message}</span>
<span class="md-suggestion-msg">${s.suggestion}</span>
</div>
`).join('');
}
+4 -4
View File
@@ -106,22 +106,22 @@ export function initSettingsModal(): void {
const saveHttpTimeout = debounce(async () => {
const db = state.get<ChatDB | null>(KEYS.DB);
const sec = parseSec(inputHttpTimeout.value.trim());
const ms = sec >= 0 ? sec * 1000 : 30_000;
const ms = sec >= 0 ? sec * 1000 : 900_000;
if (db) await db.saveSetting('httpTimeout', sec);
const bridge = window.metonaDesktop;
if (bridge?.tool?.setTimeouts) {
await bridge.tool.setTimeouts({ http: ms });
}
logSetting('HTTP 超时', sec >= 0 ? (sec === 0 ? '已禁用' : `${sec}s`) : '默认(30s)');
logSetting('HTTP 超时', sec >= 0 ? (sec === 0 ? '已禁用' : `${sec}s`) : '默认(900s)');
}, 500);
const saveStreamTimeout = debounce(async () => {
const db = state.get<ChatDB | null>(KEYS.DB);
const sec = parseSec(inputStreamTimeout.value.trim());
const ms = sec >= 0 ? sec * 1000 : 300_000;
const ms = sec >= 0 ? sec * 1000 : -1;
state.set('streamTimeout', ms);
if (db) await db.saveSetting('streamTimeout', sec);
logSetting('流式超时', sec >= 0 ? (sec === 0 ? '已禁用' : `${sec}s`) : '默认(300s)');
logSetting('流式超时', sec >= 0 ? (sec === 0 ? '已禁用' : `${sec}s`) : '默认(动态)');
}, 500);
const saveMCPTimeout = debounce(async () => {
+2 -2
View File
@@ -28,7 +28,7 @@
<div class="header-left">
<img class="logo" src="./assets/icons/llama.png" alt="logo" />
<span class="app-title">Metona Ollama</span>
<span class="app-version">v0.16.17</span>
<span class="app-version">v0.16.18</span>
<button class="icon-btn help-btn" id="btnHelp" title="使用帮助">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/>
@@ -344,7 +344,7 @@
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;">
<div>
<label style="font-size:12px;color:var(--text-secondary);" for="inputHttpTimeout">🌐 HTTP 请求超时(秒)</label>
<input class="setting-input" id="inputHttpTimeout" type="number" min="0" step="5" placeholder="30" style="margin-bottom:0;">
<input class="setting-input" id="inputHttpTimeout" type="number" min="0" step="5" placeholder="900" style="margin-bottom:0;">
<p class="text-muted" style="font-size:10px;">web_search / web_fetch 等 HTTP 请求的超时</p>
</div>
<div>
+3 -3
View File
@@ -459,13 +459,13 @@ async function init(): Promise<void> {
}
// 应用流式超时到 stateagent-engine 读取,0=禁用)
state.set('streamTimeout', streamTimeout >= 0 ? streamTimeout * 1000 : 300_000);
state.set('streamTimeout', streamTimeout >= 0 ? streamTimeout * 1000 : -1);
// 应用 HTTP 和 MCP 超时到主进程
const bridge = window.metonaDesktop;
if (bridge?.tool?.setTimeouts) {
await bridge.tool.setTimeouts({
http: httpTimeout >= 0 ? httpTimeout * 1000 : 30_000,
http: httpTimeout >= 0 ? httpTimeout * 1000 : 900_000,
mcp: mcpTimeout >= 0 ? mcpTimeout * 1000 : 60_000,
});
}
@@ -474,7 +474,7 @@ async function init(): Promise<void> {
(document.querySelector('#inputHttpTimeout') as HTMLInputElement).value = httpTimeout >= 0 ? String(httpTimeout) : '';
(document.querySelector('#inputStreamTimeout') as HTMLInputElement).value = streamTimeout >= 0 ? String(streamTimeout) : '';
(document.querySelector('#inputMCPTimeout') as HTMLInputElement).value = mcpTimeout >= 0 ? String(mcpTimeout) : '';
logInit(`超时设置: HTTP=${httpTimeout>=0?httpTimeout:30}s 流式=${streamTimeout>=0?streamTimeout:300}s MCP=${mcpTimeout>=0?mcpTimeout:60}s`);
logInit(`超时设置: HTTP=${httpTimeout>=0?httpTimeout:900}s 流式=${streamTimeout>=0?streamTimeout:'动态'}s MCP=${mcpTimeout>=0?mcpTimeout:60}s`);
// ── 子代理参数 ──
let subAgentMaxLoops = await db.getSetting<number>('subAgentMaxLoops', 10);
+1 -1
View File
@@ -215,7 +215,7 @@ export async function executeSubAgent(
if (chunk.message?.content) content += chunk.message.content;
if (chunk.message?.tool_calls?.length) {
for (const tc of chunk.message.tool_calls) {
if (tc.function?.name && SUB_AGENT_TOOL_WHITELIST.has(tc.function.name)) {
if (tc.function?.name && toolWhitelist.has(tc.function.name)) {
toolCalls.push({ name: tc.function.name, arguments: tc.function.arguments || {} });
}
}