>({})
const isLoading = ref(false)
+ // Inject global data from index.vue
+ const form = inject(formInjectionKey)!
+ const feedback = inject(feedbackInjectionKey)!
+ const completeResult = inject(researchResultInjectionKey)!
+
function handleResearchProgress(step: ResearchStep) {
let node: TreeNode | null = null
let nodeId = ''
@@ -80,14 +89,17 @@
}
case 'generated_query': {
+ console.log(`[DeepResearch] node ${nodeId} generated query:`, step)
break
}
case 'searching': {
+ console.log(`[DeepResearch] node ${nodeId} searching:`, step)
break
}
case 'search_complete': {
+ console.log(`[DeepResearch] node ${nodeId} search complete:`, step)
if (node) {
node.visitedUrls = step.urls
}
@@ -110,6 +122,10 @@
}
case 'processed_search_result': {
+ console.log(
+ `[DeepResearch] node ${nodeId} processed_search_result:`,
+ step,
+ )
if (node) {
node.learnings = step.result.learnings
searchResults.value[nodeId] = step.result
@@ -118,7 +134,7 @@
}
case 'error':
- console.error(`Research error on node ${nodeId}:`, step.message)
+ console.error(`[DeepResearch] node ${nodeId} error:`, step.message)
node!.error = step.message
toast.add({
title: t('webBrowsing.nodeFailedToast', {
@@ -131,7 +147,12 @@
break
case 'complete':
- emit('complete', step)
+ console.log(`[DeepResearch] complete:`, step)
+ completeResult.value = {
+ learnings: step.learnings,
+ visitedUrls: step.visitedUrls,
+ }
+ emit('complete')
isLoading.value = false
break
}
@@ -167,7 +188,9 @@
return parts.join('-')
}
- async function startResearch(query: string, depth: number, breadth: number) {
+ async function startResearch() {
+ if (!form.value.query || !form.value.breadth || !form.value.depth) return
+
tree.value.children = []
selectedNode.value = undefined
searchResults.value = {}
@@ -179,9 +202,9 @@
? t('language', {}, { locale: config.value.webSearch.searchLanguage })
: undefined
await deepResearch({
- query,
- maxDepth: depth,
- breadth,
+ query: getCombinedQuery(form.value, feedback.value),
+ maxDepth: form.value.depth,
+ breadth: form.value.breadth,
language: t('language', {}, { locale: locale.value }),
searchLanguage,
onProgress: handleResearchProgress,
@@ -276,7 +299,9 @@
+ import {
+ feedbackInjectionKey,
+ formInjectionKey,
+ } from '~/constants/injection-keys'
import { generateFeedback } from '~/lib/feedback'
export interface ResearchFeedbackResult {
@@ -11,16 +15,21 @@
}>()
defineEmits<{
- (e: 'submit', feedback: ResearchFeedbackResult[]): void
+ (e: 'submit'): void
}>()
const { t, locale } = useI18n()
- const reasoningContent = ref('')
- const feedback = ref([])
+ const { config, showConfigManager } = storeToRefs(useConfigStore())
+ const toast = useToast()
+ const reasoningContent = ref('')
const isLoading = ref(false)
const error = ref('')
+ // Inject global data from index.vue
+ const form = inject(formInjectionKey)!
+ const feedback = inject(feedbackInjectionKey)!
+
const isSubmitButtonDisabled = computed(
() =>
!feedback.value.length ||
@@ -31,13 +40,25 @@
props.isLoadingSearch,
)
- async function getFeedback(query: string, numQuestions = 3) {
+ async function getFeedback() {
+ const aiConfig = config.value.ai
+ const webSearchConfig = config.value.webSearch
+
+ if (!aiConfig.model || !aiConfig.apiKey || !webSearchConfig.apiKey) {
+ toast.add({
+ title: t('index.missingConfigTitle'),
+ description: t('index.missingConfigDescription'),
+ color: 'error',
+ })
+ showConfigManager.value = true
+ return
+ }
clear()
isLoading.value = true
try {
for await (const f of generateFeedback({
- query,
- numQuestions,
+ query: form.value.query,
+ numQuestions: form.value.numQuestions,
language: t('language', {}, { locale: locale.value }),
})) {
if (f.type === 'reasoning') {
@@ -63,6 +84,10 @@
error.value = t('invalidStructuredOutput')
}
}
+ console.log(
+ `[ResearchFeedback] query: ${form.value.query}, feedback:`,
+ feedback.value,
+ )
// Check if model returned questions
if (!feedback.value.length) {
error.value = t('modelFeedback.noQuestions')
@@ -125,7 +150,7 @@
:loading="isLoadingSearch || isLoading"
:disabled="isSubmitButtonDisabled"
block
- @click="$emit('submit', feedback)"
+ @click="$emit('submit')"
>
{{ $t('modelFeedback.submit') }}
diff --git a/components/ResearchForm.vue b/components/ResearchForm.vue
index 99c4611..607e844 100644
--- a/components/ResearchForm.vue
+++ b/components/ResearchForm.vue
@@ -1,4 +1,6 @@
@@ -102,7 +97,11 @@
block
@click="handleSubmit"
>
- {{ isLoadingFeedback ? $t('researchTopic.researching') : $t('researchTopic.start') }}
+ {{
+ isLoadingFeedback
+ ? $t('researchTopic.researching')
+ : $t('researchTopic.start')
+ }}
diff --git a/components/ResearchReport.vue b/components/ResearchReport.vue
index 3d09ee9..ea1b936 100644
--- a/components/ResearchReport.vue
+++ b/components/ResearchReport.vue
@@ -1,14 +1,12 @@
diff --git a/public/version.json b/public/version.json
index 688e939..578757c 100644
--- a/public/version.json
+++ b/public/version.json
@@ -1,3 +1,3 @@
{
- "version": "1.0.0"
+ "version": "1.0.4"
}
\ No newline at end of file
diff --git a/stores/config.ts b/stores/config.ts
index 339915c..d4ef11d 100644
--- a/stores/config.ts
+++ b/stores/config.ts
@@ -37,5 +37,7 @@ export const useConfigStore = defineStore('config', () => {
return config.value.ai.apiBase || 'https://api.openai.com/v1'
})
- return { config: skipHydrate(config), aiApiBase }
+ const showConfigManager = ref(false)
+
+ return { config: skipHydrate(config), aiApiBase, showConfigManager }
})
diff --git a/utils/prompt.ts b/utils/prompt.ts
new file mode 100644
index 0000000..9448bde
--- /dev/null
+++ b/utils/prompt.ts
@@ -0,0 +1,14 @@
+import type { ResearchFeedbackResult } from '~/components/ResearchFeedback.vue'
+import type { ResearchInputData } from '~/components/ResearchForm.vue'
+
+export function getCombinedQuery(
+ form: ResearchInputData,
+ feedback: ResearchFeedbackResult[],
+) {
+ return `Initial Query: ${form.query}
+Follow-up Questions and Answers:
+${feedback
+ .map((qa) => `Q: ${qa.assistantQuestion}\nA: ${qa.userAnswer}`)
+ .join('\n')}
+ `
+}