@@ -10,6 +10,7 @@ import { ArtifactTypeCode, ArtifactStatus } from '@/lib/services/notebooklm/type
1010import { generateWithGemini , stripCodeFences } from '@/lib/gemini' ;
1111import { getConfigValue } from '@/lib/config' ;
1212import type { ResearchPayload } from '@/lib/services/research' ;
13+ import { writeClient } from '@/lib/sanity-write-client' ;
1314
1415// ---------------------------------------------------------------------------
1516// Types
@@ -351,20 +352,77 @@ async function stepInfographicsGenerating(
351352 return { id : doc . _id , title : doc . title , step : 'infographics_generating' , outcome : 'still_generating' } ;
352353 }
353354
354- // Collect infographic URLs from completed artifacts
355+ // Download and upload infographics to Sanity
356+ interface SanityImageRef {
357+ _type : 'image' ;
358+ _key : string ;
359+ alt ?: string ;
360+ asset : { _type : 'reference' ; _ref : string } ;
361+ }
362+
363+ const infographicRefs : SanityImageRef [ ] = [ ] ;
355364 const infographicUrls : string [ ] = [ ] ;
356- for ( const artifactId of artifactIds ) {
365+
366+ for ( let i = 0 ; i < artifactIds . length ; i ++ ) {
367+ const artifactId = artifactIds [ i ] ;
357368 try {
358- const url = await nbClient . getInfographicUrl ( notebookId , artifactId ) ;
359- if ( url ) {
360- infographicUrls . push ( url ) ;
369+ // Step 1: Get the auth-gated URL
370+ const authUrl = await nbClient . getInfographicUrl ( notebookId , artifactId ) ;
371+ if ( ! authUrl ) {
372+ console . warn ( `[check-research] No URL for artifact ${ artifactId } ` ) ;
373+ continue ;
374+ }
375+
376+ // Step 2: Download PNG with NotebookLM auth cookies
377+ const cookies = nbClient . getCookieHeader ( ) ;
378+ const imageResponse = await fetch ( authUrl , {
379+ headers : { Cookie : cookies } ,
380+ redirect : 'follow' ,
381+ } ) ;
382+
383+ if ( ! imageResponse . ok ) {
384+ console . warn ( `[check-research] Failed to download infographic ${ artifactId } : ${ imageResponse . status } ` ) ;
385+ continue ;
361386 }
387+
388+ const contentType = imageResponse . headers . get ( 'content-type' ) || '' ;
389+ if ( ! contentType . includes ( 'image' ) ) {
390+ console . warn ( `[check-research] Infographic ${ artifactId } returned non-image: ${ contentType } ` ) ;
391+ continue ;
392+ }
393+
394+ const arrayBuffer = await imageResponse . arrayBuffer ( ) ;
395+ const buffer = Buffer . from ( arrayBuffer ) ;
396+ console . log ( `[check-research] Downloaded infographic ${ i + 1 } : ${ buffer . length } bytes` ) ;
397+
398+ // Step 3: Upload to Sanity assets
399+ const filename = `infographic-${ doc . _id } -${ i } .png` ;
400+ const asset = await writeClient . assets . upload ( 'image' , buffer , {
401+ filename,
402+ contentType : 'image/png' ,
403+ } ) ;
404+
405+ console . log ( `[check-research] Uploaded to Sanity: ${ asset . _id } ` ) ;
406+
407+ // Step 4: Build image reference for the array field
408+ const artifact = ourArtifacts . find ( a => a . id === artifactId ) ;
409+ infographicRefs . push ( {
410+ _type : 'image' ,
411+ _key : artifactId . slice ( 0 , 8 ) ,
412+ alt : artifact ?. title || `Research infographic ${ i + 1 } ` ,
413+ asset : { _type : 'reference' , _ref : asset . _id } ,
414+ } ) ;
415+
416+ // Also store the Sanity CDN URL for researchData backward compat
417+ const cdnUrl = `https://cdn.sanity.io/images/${ process . env . NEXT_PUBLIC_SANITY_PROJECT_ID } /${ process . env . NEXT_PUBLIC_SANITY_DATASET } /${ asset . _id . replace ( 'image-' , '' ) . replace ( '-png' , '.png' ) . replace ( '-jpg' , '.jpg' ) } ` ;
418+ infographicUrls . push ( cdnUrl ) ;
419+
362420 } catch ( err ) {
363- console . warn ( `[check-research] Failed to get infographic URL for ${ artifactId } :` , err instanceof Error ? err . message : err ) ;
421+ console . warn ( `[check-research] Failed to process infographic ${ artifactId } :` , err instanceof Error ? err . message : err ) ;
364422 }
365423 }
366424
367- console . log ( `[check-research] Collected ${ infographicUrls . length } infographic URLs` ) ;
425+ console . log ( `[check-research] Processed ${ infographicRefs . length } infographics ( ${ infographicUrls . length } URLs) ` ) ;
368426
369427 // Parse existing research data and add infographic URLs
370428 let researchData : Record < string , unknown > = { } ;
@@ -377,15 +435,19 @@ async function stepInfographicsGenerating(
377435 }
378436 researchData . infographicUrls = infographicUrls ;
379437
380- await sanity
381- . patch ( doc . _id )
382- . set ( {
383- status : 'enriching' ,
384- researchData : JSON . stringify ( researchData ) ,
385- } )
386- . commit ( ) ;
438+ const patchData : Record < string , unknown > = {
439+ status : 'enriching' ,
440+ researchData : JSON . stringify ( researchData ) ,
441+ } ;
442+
443+ // Add infographic image refs if we have any
444+ if ( infographicRefs . length > 0 ) {
445+ patchData . infographics = infographicRefs ;
446+ }
447+
448+ await sanity . patch ( doc . _id ) . set ( patchData ) . commit ( ) ;
387449
388- console . log ( `[check-research] "${ doc . title } " → enriching (${ infographicUrls . length } infographic URLs)` ) ;
450+ console . log ( `[check-research] "${ doc . title } " → enriching (${ infographicRefs . length } infographics, ${ infographicUrls . length } URLs)` ) ;
389451 return { id : doc . _id , title : doc . title , step : 'infographics_generating' , outcome : 'enriching' } ;
390452}
391453
0 commit comments