2025-07-02 08:09:22 +08:00

252 lines
7.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useMemo } from 'react'
import { ApplyStatus, ToolArgs } from '../../types/apply'
import {
ParsedMsgBlock,
parseMsgBlocks,
} from '../../utils/parse-infio-block'
import MarkdownApplyDiffBlock from './Markdown/MarkdownApplyDiffBlock'
import MarkdownDataviewQueryBlock from './Markdown/MarkdownDataviewQueryBlock'
import MarkdownEditFileBlock from './Markdown/MarkdownEditFileBlock'
import MarkdownFetchUrlsContentBlock from './Markdown/MarkdownFetchUrlsContentBlock'
import MarkdownListFilesBlock from './Markdown/MarkdownListFilesBlock'
import MarkdownManageFilesBlock from './Markdown/MarkdownManageFilesBlock'
import MarkdownMatchSearchFilesBlock from './Markdown/MarkdownMatchSearchFilesBlock'
import MarkdownReadFileBlock from './Markdown/MarkdownReadFileBlock'
import MarkdownReasoningBlock from './Markdown/MarkdownReasoningBlock'
import MarkdownRegexSearchFilesBlock from './Markdown/MarkdownRegexSearchFilesBlock'
import MarkdownSearchAndReplace from './Markdown/MarkdownSearchAndReplace'
import MarkdownSearchWebBlock from './Markdown/MarkdownSearchWebBlock'
import MarkdownSemanticSearchFilesBlock from './Markdown/MarkdownSemanticSearchFilesBlock'
import MarkdownSwitchModeBlock from './Markdown/MarkdownSwitchModeBlock'
import MarkdownToolResult from './Markdown/MarkdownToolResult'
import MarkdownTransformationToolBlock from './Markdown/MarkdownTransformationToolBlock'
import MarkdownWithIcons from './Markdown/MarkdownWithIcon'
import RawMarkdownBlock from './Markdown/RawMarkdownBlock'
import UseMcpToolBlock from './Markdown/UseMcpToolBlock'
function ReactMarkdown({
applyStatus,
onApply,
children,
}: {
applyStatus: ApplyStatus
onApply: (toolArgs: ToolArgs) => void
children: string
}) {
const blocks: ParsedMsgBlock[] = useMemo(
() => parseMsgBlocks(children),
[children],
)
return (
<>
{blocks.map((block, index) =>
block.type === 'think' ? (
<MarkdownReasoningBlock
key={"reasoning-" + index}
reasoningContent={block.content}
/>
) : block.type === 'thinking' ? (
<RawMarkdownBlock
key={"plan-" + index}
content={block.content}
/>
) : block.type === 'write_to_file' ? (
<MarkdownEditFileBlock
key={"write-to-file-" + index}
applyStatus={applyStatus}
mode={block.type}
onApply={onApply}
path={block.path}
startLine={1}
>
{block.content}
</MarkdownEditFileBlock>
) : block.type === 'insert_content' ? (
<MarkdownEditFileBlock
key={"insert-content-" + index}
applyStatus={applyStatus}
mode={block.type}
onApply={onApply}
path={block.path}
startLine={block.startLine}
endLine={block.startLine} // 插入内容时endLine 和 startLine 相同
>
{block.content}
</MarkdownEditFileBlock>
) : block.type === 'search_and_replace' ? (
<MarkdownSearchAndReplace
key={"search-and-replace-" + index}
applyStatus={applyStatus}
onApply={onApply}
path={block.path}
content={block.content}
operations={block.operations.map(op => ({
search: op.search,
replace: op.replace,
startLine: op.start_line,
endLine: op.end_line,
useRegex: op.use_regex,
ignoreCase: op.ignore_case,
regexFlags: op.regex_flags,
}))}
finish={block.finish}
/>
) : block.type === 'apply_diff' ? (
<MarkdownApplyDiffBlock
key={"apply-diff-" + index}
applyStatus={applyStatus}
mode={block.type}
onApply={onApply}
path={block.path}
diff={block.diff}
finish={block.finish}
/>
) : block.type === 'read_file' ? (
<MarkdownReadFileBlock
key={"read-file-" + index}
applyStatus={applyStatus}
onApply={onApply}
path={block.path}
finish={block.finish}
/>
) : block.type === 'list_files' ? (
<MarkdownListFilesBlock
key={"list-files-" + index}
applyStatus={applyStatus}
onApply={onApply}
path={block.path}
recursive={block.recursive}
finish={block.finish}
/>
) : block.type === 'match_search_files' ? (
<MarkdownMatchSearchFilesBlock
key={"match-search-files-" + index}
applyStatus={applyStatus}
onApply={onApply}
path={block.path}
query={block.query}
finish={block.finish}
/>
) : block.type === 'regex_search_files' ? (
<MarkdownRegexSearchFilesBlock
key={"regex-search-files-" + index}
applyStatus={applyStatus}
onApply={onApply}
path={block.path}
regex={block.regex}
finish={block.finish}
/>
) : block.type === 'semantic_search_files' ? (
<MarkdownSemanticSearchFilesBlock
key={"semantic-search-files-" + index}
applyStatus={applyStatus}
onApply={onApply}
path={block.path}
query={block.query}
finish={block.finish}
/>
) : block.type === 'attempt_completion' ? (
<MarkdownWithIcons
key={"attempt-completion-" + index}
className="infio-markdown infio-attempt-completion"
markdownContent={block.result}
finish={block.finish}
iconName="attempt_completion"
iconSize={14}
iconClassName="infio-markdown-icon"
/>
) : block.type === 'ask_followup_question' ? (
<MarkdownWithIcons
key={"ask-followup-question-" + index}
className="infio-markdown infio-followup-question"
markdownContent={block.question}
finish={block.finish}
iconName="ask_followup_question"
iconSize={14}
iconClassName="infio-markdown-icon"
/>
) : block.type === 'switch_mode' ? (
<MarkdownSwitchModeBlock
key={"switch-mode-" + index}
applyStatus={applyStatus}
onApply={onApply}
mode={block.mode}
reason={block.reason}
finish={block.finish}
/>
) : 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}
/>
) : block.type === 'use_mcp_tool' ? (
<UseMcpToolBlock
key={"use-mcp-tool-" + index}
applyStatus={applyStatus}
onApply={onApply}
serverName={block.server_name}
toolName={block.tool_name}
parameters={block.parameters}
finish={block.finish}
/>
) : block.type === 'dataview_query' ? (
<MarkdownDataviewQueryBlock
key={"dataview-query-" + index}
applyStatus={applyStatus}
onApply={onApply}
query={block.query}
outputFormat={block.outputFormat}
finish={block.finish}
/>
) : block.type === 'call_transformations' ? (
<MarkdownTransformationToolBlock
key={"call-transformations-" + index}
applyStatus={applyStatus}
onApply={onApply}
toolType="call_transformations"
path={block.path}
transformation={block.transformation}
finish={block.finish}
/>
) : block.type === 'manage_files' ? (
<MarkdownManageFilesBlock
key={"manage-files-" + index}
applyStatus={applyStatus}
onApply={onApply}
operations={block.operations}
finish={block.finish}
/>
) : block.type === 'tool_result' ? (
<MarkdownToolResult
key={"tool-result-" + index}
content={block.content}
/>
) : (
<RawMarkdownBlock
key={"markdown-" + index}
content={block.content}
className="infio-markdown"
/>
),
)}
</>
)
}
export default React.memo(ReactMarkdown)