From 32f8c661e4e441183ba254b5760764b058855f44 Mon Sep 17 00:00:00 2001 From: multipleof4 Date: Thu, 20 Aug 2026 10:26:16 -0700 Subject: [PATCH] Feat: Enforce 64k tokens & full URL source citations Co-authored-by: gemini-3.7-flash --- providers.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/providers.js b/providers.js index efa7f33..7dbc497 100644 --- a/providers.js +++ b/providers.js @@ -97,7 +97,6 @@ function mapToGoogleContents(messages) { if (last?.role === role) last.parts.push(...parts) else contents.push({ role, parts }) } - // Drop empty/placeholder trailing model turns (no prefill support needed here) while (contents.length && contents.at(-1).role === 'model' && isBlankTurn(contents.at(-1))) contents.pop() return contents } @@ -112,13 +111,11 @@ function toGoogleSchema(s) { function collectSources(candidate, sources) { for (const c of candidate?.groundingMetadata?.groundingChunks || []) { const uri = c?.web?.uri - if (uri && !sources.has(uri)) sources.set(uri, c.web.title || new URL(uri).hostname) + if (uri) sources.add(uri) } for (const u of candidate?.urlContextMetadata?.urlMetadata || []) { const uri = u?.retrievedUrl - if (!uri || sources.has(uri)) continue - if (u.urlRetrievalStatus && u.urlRetrievalStatus !== 'URL_RETRIEVAL_STATUS_SUCCESS') continue - try { sources.set(uri, new URL(uri).hostname) } catch { sources.set(uri, uri) } + if (uri && (!u.urlRetrievalStatus || u.urlRetrievalStatus === 'URL_RETRIEVAL_STATUS_SUCCESS')) sources.add(uri) } } @@ -288,10 +285,12 @@ export async function streamGoogle({ apiKey, body, signal, onDelta, isRunning }) const online = raw.endsWith(':online') const model = (online ? raw.slice(0, -7) : raw).replace(/^models\//, '') - const config = { abortSignal: signal } + const config = { + abortSignal: signal, + maxOutputTokens: Number.isFinite(+body.max_tokens) && +body.max_tokens > 0 ? +body.max_tokens : 65536, + } if (Number.isFinite(+body.temperature)) config.temperature = +body.temperature if (Number.isFinite(+body.top_p)) config.topP = +body.top_p - if (Number.isFinite(+body.max_tokens) && +body.max_tokens > 0) config.maxOutputTokens = +body.max_tokens const systemInstruction = body.messages.filter(m => m.role === 'system').map(extractText).filter(Boolean).join('\n\n') if (systemInstruction) config.systemInstruction = systemInstruction @@ -321,7 +320,7 @@ export async function streamGoogle({ apiKey, body, signal, onDelta, isRunning }) const contents = mapToGoogleContents(body.messages) if (!contents.length) throw new Error('Google API error: no usable content') - const sources = new Map() + const sources = new Set() let hasReasoning = false, hasContent = false const stream = await ai.models.generateContentStream({ model, contents, config }) @@ -350,7 +349,7 @@ export async function streamGoogle({ apiKey, body, signal, onDelta, isRunning }) } if (sources.size && isRunning()) { - const list = [...sources].map(([uri, title], i) => `${i + 1}. [${title}](${uri})`).join('\n') + const list = [...sources].map((uri, i) => `${i + 1}. [${uri}](${uri})`).join('\n') onDelta(`\n\n---\n\n**Sources**\n\n${list}\n`) } }