update research mode, add search web and fetch url content
This commit is contained in:
@@ -44,6 +44,7 @@ import {
|
||||
import { readTFileContent } from '../../utils/obsidian'
|
||||
import { openSettingsModalWithError } from '../../utils/open-settings-modal'
|
||||
import { PromptGenerator, addLineNumbers } from '../../utils/prompt-generator'
|
||||
import { fetchUrlsContent, webSearch } from '../../utils/web-search'
|
||||
|
||||
// Simple file reading function that returns a placeholder content for testing
|
||||
const readFileContent = (filePath: string): string => {
|
||||
@@ -283,7 +284,7 @@ const Chat = forwardRef<ChatRef, ChatProps>((props, ref) => {
|
||||
chatModel,
|
||||
{
|
||||
model: chatModel.modelId,
|
||||
temperature: 0.5,
|
||||
temperature: 0,
|
||||
messages: requestMessages,
|
||||
stream: true,
|
||||
},
|
||||
@@ -532,6 +533,38 @@ const Chat = forwardRef<ChatRef, ChatProps>((props, ref) => {
|
||||
mentionables: [],
|
||||
}
|
||||
}
|
||||
} else if (toolArgs.type === 'search_web') {
|
||||
const results = await webSearch(toolArgs.query)
|
||||
const formattedContent = `[search_web for '${toolArgs.query}'] Result:\n${results}\n`;
|
||||
return {
|
||||
type: 'search_web',
|
||||
applyMsgId,
|
||||
applyStatus: ApplyStatus.Applied,
|
||||
returnMsg: {
|
||||
role: 'user',
|
||||
applyStatus: ApplyStatus.Idle,
|
||||
content: null,
|
||||
promptContent: formattedContent,
|
||||
id: uuidv4(),
|
||||
mentionables: [],
|
||||
}
|
||||
}
|
||||
} else if (toolArgs.type === 'fetch_urls_content') {
|
||||
const results = await fetchUrlsContent(toolArgs.urls)
|
||||
const formattedContent = `[ fetch_urls_content ] Result:\n${results}\n`;
|
||||
return {
|
||||
type: 'fetch_urls_content',
|
||||
applyMsgId,
|
||||
applyStatus: ApplyStatus.Applied,
|
||||
returnMsg: {
|
||||
role: 'user',
|
||||
applyStatus: ApplyStatus.Idle,
|
||||
content: null,
|
||||
promptContent: formattedContent,
|
||||
id: uuidv4(),
|
||||
mentionables: [],
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to apply changes', error)
|
||||
|
||||
81
src/components/chat-view/MarkdownFetchUrlsContentBlock.tsx
Normal file
81
src/components/chat-view/MarkdownFetchUrlsContentBlock.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
import { ChevronDown, ChevronRight, Globe } from 'lucide-react'
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react'
|
||||
|
||||
import { useDarkModeContext } from '../../contexts/DarkModeContext'
|
||||
import { ApplyStatus, FetchUrlsContentToolArgs } from '../../types/apply'
|
||||
|
||||
import { MemoizedSyntaxHighlighterWrapper } from './SyntaxHighlighterWrapper'
|
||||
|
||||
export default function MarkdownFetchUrlsContentBlock({
|
||||
applyStatus,
|
||||
onApply,
|
||||
urls,
|
||||
finish
|
||||
}: {
|
||||
applyStatus: ApplyStatus
|
||||
onApply: (args: FetchUrlsContentToolArgs) => void
|
||||
urls: string[],
|
||||
finish: boolean
|
||||
}) {
|
||||
const { isDarkMode } = useDarkModeContext()
|
||||
const containerRef = useRef<HTMLDivElement>(null)
|
||||
const [isOpen, setIsOpen] = useState(true)
|
||||
|
||||
React.useEffect(() => {
|
||||
console.log('finish', finish, applyStatus)
|
||||
if (finish && applyStatus === ApplyStatus.Idle) {
|
||||
console.log('finish auto fetch urls content', urls)
|
||||
onApply({
|
||||
type: 'fetch_urls_content',
|
||||
urls: urls
|
||||
})
|
||||
}
|
||||
}, [finish])
|
||||
|
||||
const urlsMarkdownContent = useMemo(() => {
|
||||
return urls.map(url => {
|
||||
return `${url}`
|
||||
}).join('\n\n')
|
||||
}, [urls])
|
||||
|
||||
useEffect(() => {
|
||||
if (containerRef.current) {
|
||||
containerRef.current.scrollTop = containerRef.current.scrollHeight
|
||||
}
|
||||
}, [urlsMarkdownContent])
|
||||
|
||||
return (
|
||||
urlsMarkdownContent && (
|
||||
<div
|
||||
className={`infio-chat-code-block has-filename infio-reasoning-block`}
|
||||
>
|
||||
<div className={'infio-chat-code-block-header'}>
|
||||
<div className={'infio-chat-code-block-header-filename'}>
|
||||
<Globe size={10} className="infio-chat-code-block-header-icon" />
|
||||
Fetch URLs Content
|
||||
</div>
|
||||
<button
|
||||
className="clickable-icon infio-chat-list-dropdown"
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
>
|
||||
{isOpen ? <ChevronDown size={16} /> : <ChevronRight size={16} />}
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="infio-reasoning-content-wrapper"
|
||||
>
|
||||
<MemoizedSyntaxHighlighterWrapper
|
||||
isDarkMode={isDarkMode}
|
||||
language="markdown"
|
||||
hasFilename={true}
|
||||
wrapLines={true}
|
||||
isOpen={isOpen}
|
||||
>
|
||||
{urlsMarkdownContent}
|
||||
</MemoizedSyntaxHighlighterWrapper>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
41
src/components/chat-view/MarkdownSearchWebBlock.tsx
Normal file
41
src/components/chat-view/MarkdownSearchWebBlock.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import { Search } from 'lucide-react'
|
||||
import React from 'react'
|
||||
|
||||
import { ApplyStatus, SearchWebToolArgs } from '../../types/apply'
|
||||
|
||||
export default function MarkdownWebSearchBlock({
|
||||
applyStatus,
|
||||
onApply,
|
||||
query,
|
||||
finish
|
||||
}: {
|
||||
applyStatus: ApplyStatus
|
||||
onApply: (args: SearchWebToolArgs) => void
|
||||
query: string,
|
||||
finish: boolean
|
||||
}) {
|
||||
|
||||
React.useEffect(() => {
|
||||
console.log('finish', finish, applyStatus)
|
||||
if (finish && applyStatus === ApplyStatus.Idle) {
|
||||
console.log('finish auto web search', query)
|
||||
onApply({
|
||||
type: 'search_web',
|
||||
query: query,
|
||||
})
|
||||
}
|
||||
}, [finish])
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`infio-chat-code-block has-filename`}
|
||||
>
|
||||
<div className={'infio-chat-code-block-header'}>
|
||||
<div className={'infio-chat-code-block-header-filename'}>
|
||||
<Search size={14} className="infio-chat-code-block-header-icon" />
|
||||
Web search: {query}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -8,14 +8,15 @@ import {
|
||||
} from '../../utils/parse-infio-block'
|
||||
|
||||
import MarkdownEditFileBlock from './MarkdownEditFileBlock'
|
||||
import MarkdownFetchUrlsContentBlock from './MarkdownFetchUrlsContentBlock'
|
||||
import MarkdownListFilesBlock from './MarkdownListFilesBlock'
|
||||
import MarkdownReadFileBlock from './MarkdownReadFileBlock'
|
||||
import MarkdownReasoningBlock from './MarkdownReasoningBlock'
|
||||
import MarkdownRegexSearchFilesBlock from './MarkdownRegexSearchFilesBlock'
|
||||
import MarkdownSearchAndReplace from './MarkdownSearchAndReplace'
|
||||
import MarkdownSearchWebBlock from './MarkdownSearchWebBlock'
|
||||
import MarkdownSemanticSearchFilesBlock from './MarkdownSemanticSearchFilesBlock'
|
||||
import MarkdownWithIcons from './MarkdownWithIcon'
|
||||
|
||||
function ReactMarkdown({
|
||||
applyStatus,
|
||||
onApply,
|
||||
@@ -131,6 +132,22 @@ function ReactMarkdown({
|
||||
markdownContent={
|
||||
`<icon name='ask_followup_question' size={14} className="infio-markdown-icon" />
|
||||
${block.question && block.question.trimStart()}`} />
|
||||
) : block.type === 'search_web' ? (
|
||||
<MarkdownSearchWebBlock
|
||||
key={"search-web-" + index}
|
||||
applyStatus={applyStatus}
|
||||
onApply={onApply}
|
||||
query={block.query}
|
||||
finish={block.finish}
|
||||
/>
|
||||
) : block.type === 'fetch_urls_content' ? (
|
||||
<MarkdownFetchUrlsContentBlock
|
||||
key={"fetch-urls-content-" + index}
|
||||
applyStatus={applyStatus}
|
||||
onApply={onApply}
|
||||
urls={block.urls}
|
||||
finish={block.finish}
|
||||
/>
|
||||
) : (
|
||||
<Markdown key={"markdown-" + index} className="infio-markdown">
|
||||
{block.content}
|
||||
|
||||
Reference in New Issue
Block a user