@@ -4,6 +4,7 @@ import type { SupabaseVectorStore } from "../supabase/client";
44import type { RetrievedChunk } from "../supabase/types" ;
55import type { Logger } from "pino" ;
66import { getLogger } from "../utils/logger" ;
7+ import { resolveSourceLinks } from "../utils/sourceLinks" ;
78
89export interface AskAiOptions {
910 question : string ;
@@ -138,21 +139,25 @@ export async function askAi(
138139 }
139140 if ( chunk . sources && chunk . sources . length > 0 ) {
140141 collectedSources . length = 0 ;
141- // Map sources from matches (which have entityType, startLine, endLine)
142- const sourceMap = new Map ( matches . map ( m => [ `${ m . filepath } :${ m . chunkTitle } ` , m ] ) ) ;
143- collectedSources . push ( ...chunk . sources . map ( ( src ) => {
144- const match = sourceMap . get ( `${ src . filepath } :${ src . chunkTitle } ` ) ;
145- return {
146- filepath : src . filepath ,
147- chunkTitle : src . chunkTitle ,
148- githubUrl : match ?. githubUrl ,
149- docsUrl : match ?. docsUrl ,
150- finalUrl : src . url || match ?. githubUrl || match ?. finalUrl || src . filepath ,
151- entityType : match ?. entityType ,
152- startLine : match ?. startLine ,
153- endLine : match ?. endLine ,
154- } ;
155- } ) ) ;
142+ collectedSources . push ( ...chunk . sources
143+ . filter ( ( src ) => src . filepath ) // Filter out sources without filepath; during the first stream sources are empty
144+ . map ( ( src ) => {
145+ // Recompute URLs using resolveSourceLinks for consistency
146+ const links = resolveSourceLinks (
147+ src . filepath ! ,
148+ src . chunkTitle ,
149+ context ?. config ,
150+ src . url
151+ ) ;
152+
153+ return {
154+ filepath : src . filepath ! ,
155+ chunkTitle : src . chunkTitle ,
156+ githubUrl : links . githubUrl ,
157+ docsUrl : links . docsUrl ,
158+ finalUrl : links . finalUrl || src . url || src . filepath ! ,
159+ } ;
160+ } ) ) ;
156161 }
157162 }
158163 }
@@ -169,21 +174,25 @@ export async function askAi(
169174 signal : options . signal ,
170175 } ) ;
171176
172- // Map sources from matches (which have entityType, startLine, endLine)
173- const sourceMap = new Map ( matches . map ( m => [ `${ m . filepath } :${ m . chunkTitle } ` , m ] ) ) ;
174- const sources : AskAiSource [ ] = result . sources . map ( ( src ) => {
175- const match = sourceMap . get ( `${ src . filepath } :${ src . chunkTitle } ` ) ;
176- return {
177- filepath : src . filepath ,
178- chunkTitle : src . chunkTitle ,
179- githubUrl : match ?. githubUrl ,
180- docsUrl : match ?. docsUrl ,
181- finalUrl : src . url || match ?. githubUrl || match ?. finalUrl || src . filepath ,
182- entityType : match ?. entityType ,
183- startLine : match ?. startLine ,
184- endLine : match ?. endLine ,
185- } ;
186- } ) ;
177+ // Recompute URLs using resolveSourceLinks for consistency
178+ const sources : AskAiSource [ ] = result . sources
179+ . filter ( ( src ) => src . filepath ) // Filter out sources without filepath
180+ . map ( ( src ) => {
181+ const links = resolveSourceLinks (
182+ src . filepath ! ,
183+ src . chunkTitle ,
184+ context ?. config ,
185+ src . url
186+ ) ;
187+
188+ return {
189+ filepath : src . filepath ! ,
190+ chunkTitle : src . chunkTitle ,
191+ githubUrl : links . githubUrl ,
192+ docsUrl : links . docsUrl ,
193+ finalUrl : links . finalUrl || src . url || src . filepath ! ,
194+ } ;
195+ } ) ;
187196
188197 activeLogger . info ( { answer : result . answer , sourcesCount : sources . length } , "answer from the AI" ) ;
189198
0 commit comments