From 032111994b27dbf35841f5dce5a96f9072b634ef Mon Sep 17 00:00:00 2001 From: duanfuxiang Date: Thu, 10 Apr 2025 10:59:23 +0800 Subject: [PATCH] add chat behavior setting --- README.md | 2 ++ src/components/chat-view/Chat.tsx | 41 ++++++++++++++++--------------- src/settings/SettingTab.tsx | 37 ++++++++++++++++++++++++++++ src/types/settings.ts | 3 ++- 4 files changed, 62 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index b740a83..aaa3f36 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ [中文文档](README_zh-CN.md) +## New Version + ## Features ### Chat & Edit Flow diff --git a/src/components/chat-view/Chat.tsx b/src/components/chat-view/Chat.tsx index a7cc64e..d5514c0 100644 --- a/src/components/chat-view/Chat.tsx +++ b/src/components/chat-view/Chat.tsx @@ -32,6 +32,7 @@ import { useChatHistory } from '../../hooks/use-chat-history' import { ApplyStatus, ToolArgs } from '../../types/apply' import { ChatMessage, ChatUserMessage } from '../../types/chat' import { + Mentionable, MentionableBlock, MentionableBlockData, MentionableCurrentFile, @@ -47,15 +48,6 @@ 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 readFileContentByPath = async (app: App, filePath: string): Promise => { - const file = app.vault.getFileByPath(filePath) - if (!file) { - throw new Error(`File not found: ${filePath}`) - } - return await readTFileContent(file, app.vault) -} - import { ModeSelect } from './chat-input/ModeSelect' import PromptInputWithActions, { ChatUserInputRef } from './chat-input/PromptInputWithActions' import { editorStateToPlainText } from './chat-input/utils/editor-state-to-plain-text' @@ -67,19 +59,28 @@ import ShortcutInfo from './ShortcutInfo' import SimilaritySearchResults from './SimilaritySearchResults' // Add an empty line here -const getNewInputMessage = (app: App): ChatUserMessage => { +const getNewInputMessage = (app: App, defaultMention: string): ChatUserMessage => { + const mentionables: Mentionable[] = []; + if (defaultMention === 'current-file') { + const activeFile = app.workspace.getActiveFile(); + if (activeFile) { + mentionables.push({ + type: 'current-file', + file: activeFile, + }); + } + } else if (defaultMention === 'vault') { + mentionables.push({ + type: 'vault', + }); + } return { role: 'user', applyStatus: ApplyStatus.Idle, content: null, promptContent: null, id: uuidv4(), - mentionables: [ - { - type: 'current-file', - file: app.workspace.getActiveFile(), - }, - ], + mentionables: mentionables, } } @@ -113,7 +114,7 @@ const Chat = forwardRef((props, ref) => { }, [getRAGEngine, app, settings, diffStrategy]) const [inputMessage, setInputMessage] = useState(() => { - const newMessage = getNewInputMessage(app) + const newMessage = getNewInputMessage(app, settings.defaultMention) if (props.selectedBlock) { newMessage.mentionables = [ ...newMessage.mentionables, @@ -206,7 +207,7 @@ const Chat = forwardRef((props, ref) => { } setCurrentConversationId(conversationId) setChatMessages(conversation) - const newInputMessage = getNewInputMessage(app) + const newInputMessage = getNewInputMessage(app, settings.defaultMention) setInputMessage(newInputMessage) setFocusedMessageId(newInputMessage.id) setQueryProgress({ @@ -221,7 +222,7 @@ const Chat = forwardRef((props, ref) => { const handleNewChat = (selectedBlock?: MentionableBlockData) => { setCurrentConversationId(uuidv4()) setChatMessages([]) - const newInputMessage = getNewInputMessage(app) + const newInputMessage = getNewInputMessage(app, settings.defaultMention) if (selectedBlock) { const mentionableBlock: MentionableBlock = { type: 'block', @@ -990,7 +991,7 @@ const Chat = forwardRef((props, ref) => { [...chatMessages, { ...inputMessage, content }], useVaultSearch, ) - setInputMessage(getNewInputMessage(app)) + setInputMessage(getNewInputMessage(app, settings.defaultMention)) preventAutoScrollRef.current = false handleScrollToBottom() }} diff --git a/src/settings/SettingTab.tsx b/src/settings/SettingTab.tsx index dbb8b2f..2e51f92 100644 --- a/src/settings/SettingTab.tsx +++ b/src/settings/SettingTab.tsx @@ -38,6 +38,7 @@ export class InfioSettingTab extends PluginSettingTab { containerEl.empty() this.renderModelsSection(containerEl) this.renderFilesSearchSection(containerEl) + this.renderChatBehaviorSection(containerEl) this.renderDeepResearchSection(containerEl) this.renderRAGSection(containerEl) this.renderAutoCompleteSection(containerEl) @@ -93,6 +94,42 @@ export class InfioSettingTab extends PluginSettingTab { ) } + private renderChatBehaviorSection(containerEl: HTMLElement): void { + new Setting(containerEl).setHeading().setName('Chat Behavior'); + new Setting(containerEl) + .setName('Default mention for new chat') + .setDesc('Choose the default file mention behavior when starting a new chat.') + .addDropdown((dropdown) => + dropdown + .addOption('none', 'None') + .addOption('current-file', 'Current File') + .addOption('vault', 'Vault') + .setValue(this.plugin.settings.defaultMention || 'none') + .onChange(async (value) => { + await this.plugin.setSettings({ + ...this.plugin.settings, + defaultMention: value as 'none' | 'current-file' | 'vault', + }); + }), + ); + new Setting(containerEl) + .setName('Mode for new chat') + .setDesc('Choose the mode to use when starting a new chat.') + .addDropdown((dropdown) => + dropdown + .addOption('ask', 'Ask') + .addOption('write', 'Write') + .addOption('research', 'Research') + .setValue(this.plugin.settings.mode || 'ask') + .onChange(async (value) => { + await this.plugin.setSettings({ + ...this.plugin.settings, + mode: value as 'ask' | 'write' | 'research', + }); + }), + ); + } + renderModelsSection(containerEl: HTMLElement): void { const modelsDiv = containerEl.createDiv("models-section"); this.modelsContainer = modelsDiv; diff --git a/src/types/settings.ts b/src/types/settings.ts index 6b01462..ca88e17 100644 --- a/src/types/settings.ts +++ b/src/types/settings.ts @@ -229,7 +229,8 @@ export const InfioSettingsSchema = z.object({ multiSearchReplaceDiffStrategy: z.boolean().catch(true), // Mode - mode: z.string().catch('ask'), + mode: z.enum(['ask', 'write', 'research']).catch('ask'), + defaultMention: z.enum(['none', 'current-file', 'vault']).catch('none'), // web search serperApiKey: z.string().catch(''),