Skip to content

Commit 7e9d252

Browse files
committed
fix: adding sources at the end of the stream to preserve
1 parent 22eb360 commit 7e9d252

File tree

1 file changed

+25
-46
lines changed

1 file changed

+25
-46
lines changed

src/api/providers/gemini.ts

Lines changed: 25 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,7 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
9393
const result = await this.client.models.generateContentStream(params)
9494

9595
let lastUsageMetadata: GenerateContentResponseUsageMetadata | undefined
96-
let accumulatedText = ""
9796
let pendingGroundingMetadata: GroundingMetadata | undefined
98-
let hasGroundingEnabled = this.options.enableGrounding
9997

10098
for await (const chunk of result) {
10199
// Process candidates and their parts to separate thoughts from content
@@ -116,11 +114,7 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
116114
} else {
117115
// This is regular content
118116
if (part.text) {
119-
accumulatedText += part.text
120-
121-
if (!hasGroundingEnabled) {
122-
yield { type: "text", text: part.text }
123-
}
117+
yield { type: "text", text: part.text }
124118
}
125119
}
126120
}
@@ -129,26 +123,19 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
129123

130124
// Fallback to the original text property if no candidates structure
131125
else if (chunk.text) {
132-
accumulatedText += chunk.text
133-
134-
if (!hasGroundingEnabled) {
135-
yield { type: "text", text: chunk.text }
136-
}
126+
yield { type: "text", text: chunk.text }
137127
}
138128

139129
if (chunk.usageMetadata) {
140130
lastUsageMetadata = chunk.usageMetadata
141131
}
142132
}
143133

144-
if (hasGroundingEnabled && accumulatedText) {
145-
let finalText = accumulatedText
146-
147-
if (pendingGroundingMetadata) {
148-
finalText = this.processGroundingCitations(accumulatedText, pendingGroundingMetadata)
134+
if (pendingGroundingMetadata) {
135+
const citations = this.extractCitationsOnly(pendingGroundingMetadata)
136+
if (citations) {
137+
yield { type: "text", text: `\n\nSources: ${citations}` }
149138
}
150-
151-
yield { type: "text", text: finalText }
152139
}
153140

154141
if (lastUsageMetadata) {
@@ -188,39 +175,28 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
188175
return { id: id.endsWith(":thinking") ? id.replace(":thinking", "") : id, info, ...params }
189176
}
190177

191-
private processGroundingCitations(text: string, groundingMetadata?: GroundingMetadata): string {
192-
const supports = groundingMetadata?.groundingSupports
178+
private extractCitationsOnly(groundingMetadata?: GroundingMetadata): string | null {
193179
const chunks = groundingMetadata?.groundingChunks
194180

195-
if (!supports || !chunks) {
196-
return text
181+
if (!chunks) {
182+
return null
197183
}
198184

199-
const sortedSupports = [...supports].sort((a, b) => (b.segment?.endIndex ?? 0) - (a.segment?.endIndex ?? 0))
200-
201-
for (const support of sortedSupports) {
202-
const endIndex = support.segment?.endIndex
203-
if (endIndex === undefined || !support.groundingChunkIndices?.length) {
204-
continue
205-
}
206-
207-
const citationLinks = support.groundingChunkIndices
208-
.map((i) => {
209-
const uri = chunks[i]?.web?.uri
210-
if (uri) {
211-
return `[${i + 1}](${uri})`
212-
}
213-
return null
214-
})
215-
.filter(Boolean)
185+
const citationLinks = chunks
186+
.map((chunk, i) => {
187+
const uri = chunk.web?.uri
188+
if (uri) {
189+
return `[${i + 1}](${uri})`
190+
}
191+
return null
192+
})
193+
.filter((link): link is string => link !== null)
216194

217-
if (citationLinks.length > 0) {
218-
const citationString = citationLinks.join(", ")
219-
text = text.slice(0, endIndex) + citationString + text.slice(endIndex)
220-
}
195+
if (citationLinks.length > 0) {
196+
return citationLinks.join(", ")
221197
}
222198

223-
return text
199+
return null
224200
}
225201

226202
async completePrompt(prompt: string): Promise<string> {
@@ -256,7 +232,10 @@ export class GeminiHandler extends BaseProvider implements SingleCompletionHandl
256232

257233
const candidate = result.candidates?.[0]
258234
if (candidate?.groundingMetadata) {
259-
text = this.processGroundingCitations(text, candidate.groundingMetadata)
235+
const citations = this.extractCitationsOnly(candidate.groundingMetadata)
236+
if (citations) {
237+
text += `\n\nSources: ${citations}`
238+
}
260239
}
261240

262241
return text

0 commit comments

Comments
 (0)