@@ -14,6 +14,8 @@ const STOP_WORDS = new Set([
1414 'i' , 'you' , 'he' , 'she' , 'it' , 'we' , 'they' , 'what' , 'which' , 'who' , 'how' , 'when' , 'where' ,
1515 'why' , 'and' , 'or' , 'but' , 'not' , 'in' , 'on' , 'at' , 'to' , 'for' , 'of' , 'with' , 'by' , 'from' ,
1616 'this' , 'that' , 'these' , 'those' , 'my' , 'your' , 'his' , 'her' , 'its' , 'our' , 'their' ,
17+ 'about' , 'other' , 'another' , 'also' , 'too' , 'more' , 'any' , 'some' , 'just' , 'even' ,
18+ 'still' , 'like' , 'else' , 'same' , 'different' , 'similar' , 'related' , 'using' , 'use' ,
1719] ) ;
1820
1921function buildSearchQuery ( text : string ) : string {
@@ -32,25 +34,32 @@ async function runSearch(query: string, maxPages = 8) {
3234 {
3335 indexName : process . env . NEXT_PUBLIC_ALGOLIA_INDEX ! ,
3436 query : searchQuery ,
35- hitsPerPage : 40 ,
37+ hitsPerPage : 60 ,
3638 } ,
3739 ] ,
3840 } ) ;
3941
40- const seen = new Set < string > ( ) ;
41- const hits : { url : string ; title : string ; section : string ; content : string } [ ] = [ ] ;
42+ // Group all chunks by url+section, preserving rank order of first appearance
43+ const groups = new Map < string , { url : string ; title : string ; section : string ; parts : string [ ] } > ( ) ;
44+ const order : string [ ] = [ ] ;
4245
4346 for ( const hit of ( results [ 0 ] as any ) . hits ?? [ ] ) {
4447 const url = hit . url ?? hit . objectID ;
48+ const section = ( hit . section ?? '' ) as string ;
4549 const content = ( hit . content ?? '' ) as string ;
46- if ( content . length < 40 ) continue ; // skip table cell fragments
47- if ( seen . has ( url ) ) continue ; // one chunk per page
48- seen . add ( url ) ;
49- hits . push ( { url, title : hit . title ?? '' , section : hit . section ?? '' , content } ) ;
50- if ( hits . length >= maxPages ) break ;
50+ if ( ! content . trim ( ) ) continue ;
51+ const key = `${ url } |${ section } ` ;
52+ if ( ! groups . has ( key ) ) {
53+ groups . set ( key , { url, title : hit . title ?? '' , section, parts : [ ] } ) ;
54+ order . push ( key ) ;
55+ }
56+ groups . get ( key ) ! . parts . push ( content ) ;
5157 }
5258
53- return hits ;
59+ return order . slice ( 0 , maxPages ) . map ( ( key ) => {
60+ const g = groups . get ( key ) ! ;
61+ return { url : g . url , title : g . title , section : g . section , content : g . parts . join ( ' | ' ) } ;
62+ } ) ;
5463}
5564
5665const openrouter = createOpenRouter ( {
@@ -71,13 +80,16 @@ export async function POST(req: Request) {
7180 const reqJson : { messages ?: UIMessage [ ] } = await req . json ( ) ;
7281 const messages = reqJson . messages ?? [ ] ;
7382
74- const userMessages = messages . filter ( ( m ) => m . role === 'user' ) ;
75- const recentUserText = userMessages
76- . slice ( - 3 )
77- . flatMap ( ( m ) => m . parts ?. filter ( ( p : any ) => p . type === 'text' ) . map ( ( p : any ) => p . text as string ) ?? [ ] )
78- . join ( ' ' ) ;
83+ const lastUserMessage = messages . filter ( ( m ) => m . role === 'user' ) . at ( - 1 ) ;
84+ const lastUserText =
85+ lastUserMessage ?. parts
86+ ?. filter ( ( p : any ) => p . type === 'text' )
87+ . map ( ( p : any ) => p . text as string )
88+ . join ( ' ' ) ?? '' ;
7989
80- const docs = recentUserText ? await runSearch ( recentUserText ) : [ ] ;
90+ console . log ( '[chat] searching for:' , lastUserText ) ;
91+ const docs = lastUserText ? await runSearch ( lastUserText ) : [ ] ;
92+ console . log ( '[chat] got' , docs . length , 'results:' , docs . map ( d => `${ d . url } [${ d . section } ] "${ d . content . slice ( 0 , 80 ) } ""` ) ) ;
8193
8294 const contextBlock =
8395 docs . length > 0
@@ -91,7 +103,7 @@ export async function POST(req: Request) {
91103 model : openrouter . chat ( process . env . OPENROUTER_MODEL ?? 'anthropic/claude-3.5-sonnet' ) ,
92104 maxOutputTokens : 1024 ,
93105 messages : [
94- { role : 'system' , content : `${ systemPrompt } \n\n${ contextBlock } ` } ,
106+ { role : 'system' , content : `${ systemPrompt } \n\n${ contextBlock } \n\nCurrent question: ${ lastUserText } ` } ,
95107 ...messages
96108 . filter ( ( m ) => m . role === 'user' || m . role === 'assistant' )
97109 . map ( ( m ) => ( {
0 commit comments