Skip to content

Commit b5432a8

Browse files
committed
More fixes
1 parent be38e7d commit b5432a8

File tree

7 files changed

+233
-140
lines changed

7 files changed

+233
-140
lines changed

src/services/deep-research/DeepResearchService.ts

Lines changed: 64 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
ResearchQuery,
2121
} from "./types"
2222
import { truncatePrompt, trimPrompt } from "./utils/prompt"
23+
import { getTreeSize } from "./utils/progress"
2324

2425
export 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({
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// npx jest src/services/deep-research/__tests__/utils/progress.test.ts
2+
3+
import { getTreeSize } from "../../utils/progress"
4+
5+
describe("getTreeSize", () => {
6+
it("should calculate the correct number of expected queries", () => {
7+
// Typical cases.
8+
expect(getTreeSize({ breadth: 2, depth: 0 })).toBe(2)
9+
expect(getTreeSize({ breadth: 3, depth: 1 })).toBe(7)
10+
expect(getTreeSize({ breadth: 4, depth: 2 })).toBe(12)
11+
expect(getTreeSize({ breadth: 5, depth: 3 })).toBe(27)
12+
13+
// Try each minimum and maximum for breadth and depth.
14+
expect(getTreeSize({ breadth: 1, depth: 0 })).toBe(1)
15+
expect(getTreeSize({ breadth: 10, depth: 0 })).toBe(10)
16+
expect(getTreeSize({ breadth: 1, depth: 9 })).toBe(1023)
17+
expect(getTreeSize({ breadth: 10, depth: 9 })).toBe(1056)
18+
})
19+
})
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Calculate total expected queries across all depth levels.
2+
// At each level, the breadth is halved, so level 1 has full breadth,
3+
// level 2 has breadth/2, level 3 has breadth/4, etc.
4+
// For breadth = 4, depth = 2, the expected queries are:
5+
// D2: 2^2 * 1 = 4
6+
// D1: 2^1 * 2 = 4
7+
// D0: 2^0 * 4 = 4
8+
// Total: 12
9+
export const getTreeSize = ({ breadth, depth }: { breadth: number; depth: number }) => {
10+
let value = 0
11+
12+
for (let i = depth; i >= 0; i--) {
13+
value = value + Math.pow(2, i) * Math.ceil(breadth / Math.pow(2, i))
14+
}
15+
16+
return value
17+
}

webview-ui/src/features/deep-research/DeepResearch.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const DeepResearch = ({ isHidden }: DeepResearchProps) => {
2323

2424
return (
2525
<div
26-
className={cn("lex flex-col items-center justify-center h-full gap-4 overflow-y-auto py-4", {
26+
className={cn("flex flex-col items-center justify-center h-full min-w-64 gap-4 overflow-auto py-4", {
2727
hidden: isHidden,
2828
})}>
2929
<GetStarted />

0 commit comments

Comments
 (0)