@@ -20,6 +20,7 @@ import {
2020 ResearchQuery ,
2121} from "./types"
2222import { truncatePrompt , trimPrompt } from "./utils/prompt"
23+ import { getTreeSize } from "./utils/progress"
2324
2425export class DeepResearchService {
2526 public readonly providerId : string
@@ -183,63 +184,78 @@ export class DeepResearchService {
183184 const results = await Promise . all (
184185 queries . map ( ( { query, researchGoal } ) =>
185186 limit ( async ( ) => {
186- try {
187- if ( this . isAborted ( ) ) {
188- return { learnings, visitedUrls }
189- }
187+ if ( this . isAborted ( ) ) {
188+ return { learnings, visitedUrls }
189+ }
190+
191+ let result : SearchResponse
190192
191- const result = await this . firecrawl . search ( query , {
193+ try {
194+ result = await this . firecrawl . search ( query , {
192195 timeout : 15000 ,
193196 limit : 5 ,
194197 scrapeOptions : { formats : [ "markdown" ] } ,
195198 } )
199+ } catch ( e ) {
200+ const text = e instanceof Error ? e . message : "Unknown error"
201+ console . log ( `[deepResearch] error = ${ text } ` )
196202
197- const newUrls = result . data
198- . map ( ( { url } ) => url )
199- . filter ( ( url ) : url is string => url !== undefined )
200-
201- const newBreadth = Math . ceil ( breadth / 2 )
202- const newDepth = depth - 1
203- const newLearnings = await this . extractLearnings ( { query, result, breadth : newBreadth } )
204- const allLearnings = [ ...learnings , ...newLearnings . learnings ]
205- const allUrls = [ ...visitedUrls , ...newUrls ]
206- onExtractedLearnings ( { ...newLearnings , urls : newUrls } )
207-
208- this . progress . completedQueries = this . progress . completedQueries + 1
209- onProgressUpdated ( )
210-
211- if ( newDepth === 0 ) {
212- return { learnings : allLearnings , visitedUrls : allUrls }
213- }
214-
215- console . log ( `[deepResearch] researching deeper, breadth: ${ newBreadth } , depth: ${ newDepth } ` )
216-
217- const nextQuery = trimPrompt ( `
218- Previous research goal: ${ researchGoal }
219- Follow-up research directions: ${ newLearnings . followUpQuestions . map ( ( q ) => `\n${ q } ` ) . join ( "" ) }
220- ` )
221-
222- return this . deepResearch ( {
223- query : nextQuery ,
224- breadth : newBreadth ,
225- depth : newDepth ,
226- learnings : allLearnings ,
227- visitedUrls : allUrls ,
228- onProgressUpdated,
229- onGeneratedQueries,
230- onExtractedLearnings,
203+ await this . postMessage ( {
204+ type : "research.error" ,
205+ text : `Encountered an error while crawling "${ query } ": ${ text } ` ,
231206 } )
207+
208+ return { learnings, visitedUrls }
209+ }
210+
211+ const newUrls = result . data . map ( ( { url } ) => url ) . filter ( ( url ) : url is string => url !== undefined )
212+
213+ const newBreadth = Math . ceil ( breadth / 2 )
214+ const newDepth = depth - 1
215+ let newLearnings : ResearchLearnings
216+
217+ try {
218+ newLearnings = await this . extractLearnings ( { query, result, breadth : newBreadth } )
232219 } catch ( e ) {
233220 const text = e instanceof Error ? e . message : "Unknown error"
234221 console . log ( `[deepResearch] error = ${ text } ` )
235222
236223 await this . postMessage ( {
237224 type : "research.error" ,
238- text : `Encountered an error while researching "${ query } ": ${ text } ` ,
225+ text : `Encountered an error while extracting learnings from "${ query } ": ${ text } ` ,
239226 } )
240227
241- return { learnings : [ ] , visitedUrls : [ ] }
228+ return { learnings, visitedUrls }
242229 }
230+
231+ const allLearnings = [ ...learnings , ...newLearnings . learnings ]
232+ const allUrls = [ ...visitedUrls , ...newUrls ]
233+ onExtractedLearnings ( { ...newLearnings , urls : newUrls } )
234+
235+ this . progress . completedQueries = this . progress . completedQueries + 1
236+ onProgressUpdated ( )
237+
238+ if ( newDepth === 0 ) {
239+ return { learnings : allLearnings , visitedUrls : allUrls }
240+ }
241+
242+ console . log ( `[deepResearch] researching deeper, breadth: ${ newBreadth } , depth: ${ newDepth } ` )
243+
244+ const nextQuery = trimPrompt ( `
245+ Previous research goal: ${ researchGoal }
246+ Follow-up research directions: ${ newLearnings . followUpQuestions . map ( ( q ) => `\n${ q } ` ) . join ( "" ) }
247+ ` )
248+
249+ return this . deepResearch ( {
250+ query : nextQuery ,
251+ breadth : newBreadth ,
252+ depth : newDepth ,
253+ learnings : allLearnings ,
254+ visitedUrls : allUrls ,
255+ onProgressUpdated,
256+ onGeneratedQueries,
257+ onExtractedLearnings,
258+ } )
243259 } ) ,
244260 ) ,
245261 )
@@ -326,7 +342,7 @@ export class DeepResearchService {
326342 schema,
327343 } )
328344
329- console . log ( `[generateQueries] generated ${ queries . length } queries` , queries )
345+ console . log ( `[generateQueries] generated ${ queries . length } (out of ${ breadth } ) queries` , queries )
330346
331347 return queries . slice ( 0 , breadth )
332348 } catch ( error ) {
@@ -530,15 +546,14 @@ export class DeepResearchService {
530546 } ) ,
531547 } )
532548
533- // Calculate total expected queries across all depth levels.
534- // At each level, the breadth is halved, so level 1 has full breadth,
535- // level 2 has breadth/2, level 3 has breadth/4, etc.
536- for ( let i = this . depth ; i > 0 ; i -- ) {
537- this . progress . expectedQueries += Math . ceil ( this . breadth / Math . pow ( 2 , this . depth - i ) )
538- }
539-
549+ this . progress . expectedQueries = getTreeSize ( { breadth : this . breadth , depth : this . depth } )
540550 onProgressUpdated ( )
541551
552+ console . log ( `[transitionToResearch] query = ${ query } ` )
553+ console . log ( `[transitionToResearch] breadth = ${ this . breadth } ` )
554+ console . log ( `[transitionToResearch] depth = ${ this . depth } ` )
555+ console . log ( `[transitionToResearch] expectedQueries = ${ this . progress . expectedQueries } ` )
556+
542557 const { learnings, visitedUrls } = await this . withLoading (
543558 ( ) =>
544559 this . deepResearch ( {
0 commit comments