diff --git a/server/src/routes/configs.ts b/server/src/routes/configs.ts index f3838a59..3ffeca48 100644 --- a/server/src/routes/configs.ts +++ b/server/src/routes/configs.ts @@ -456,7 +456,15 @@ router.put('/api/settings', (req, res) => { value = encrypt(value, config.encryptionKey); } - stmt.run(key, value ?? null); + // better-sqlite3 interprets objects/arrays as named parameter maps, + // causing RangeError. Serialize non-primitive values to JSON strings. + const serialized = + value === null || value === undefined + ? null + : typeof value === 'object' + ? JSON.stringify(value) + : value; + stmt.run(key, serialized); } }); diff --git a/server/src/routes/releases.ts b/server/src/routes/releases.ts index 840c1bd4..1aedd091 100644 --- a/server/src/routes/releases.ts +++ b/server/src/routes/releases.ts @@ -100,7 +100,7 @@ router.put('/api/releases', (req, res) => { prerelease, draft, is_read, assets, repo_id, repo_full_name, repo_name, zipball_url, tarball_url - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) `); const upsert = db.transaction(() => { diff --git a/src/services/aiService.ts b/src/services/aiService.ts index 876fcf22..253f9a14 100644 --- a/src/services/aiService.ts +++ b/src/services/aiService.ts @@ -250,9 +250,12 @@ ${options.user}` : options.user; const candidates = (data as { candidates?: unknown }).candidates; if (Array.isArray(candidates) && candidates.length > 0) { - const parts = (candidates[0] as { content?: { parts?: unknown } }).content?.parts; + const candidate = candidates[0] as { content?: { parts?: unknown }; finishReason?: string }; + const parts = candidate.content?.parts; if (Array.isArray(parts)) { + // Skip thought parts emitted by Gemini thinking models (e.g. gemini-2.5-pro) const text = parts + .filter((p) => p && typeof p === 'object' && !(p as { thought?: boolean }).thought) .map((p) => { if (!p || typeof p !== 'object') return ''; const part = p as { text?: unknown }; @@ -476,7 +479,7 @@ Focus on practicality and accurate categorization to help users quickly understa async testConnection(): Promise { const apiType = this.getApiType(); - const timeoutMs = apiType === 'openai-responses' || this.config.reasoningEffort ? 30000 : 10000; + const timeoutMs = apiType === 'openai-responses' || apiType === 'gemini' || this.config.reasoningEffort ? 30000 : 10000; try { const base = new URL(this.config.baseUrl); @@ -497,7 +500,7 @@ Focus on practicality and accurate categorization to help users quickly understa system: 'You are a connection test assistant.', user: 'Reply with exactly one word: OK', temperature: 0, - maxTokens: 50, + maxTokens: 2048, signal: controller.signal, }); if (content) {