mirror of
https://github.com/EthanMarti/infio-copilot.git
synced 2026-05-08 08:00:10 +00:00
add mode custom
This commit is contained in:
@@ -30,6 +30,7 @@ import {
|
||||
} from '../../core/llm/exception'
|
||||
import { regexSearchFiles } from '../../core/ripgrep'
|
||||
import { useChatHistory } from '../../hooks/use-chat-history'
|
||||
import { useCustomModes } from '../../hooks/use-custom-mode'
|
||||
import { ApplyStatus, ToolArgs } from '../../types/apply'
|
||||
import { ChatMessage, ChatUserMessage } from '../../types/chat'
|
||||
import {
|
||||
@@ -101,6 +102,7 @@ const Chat = forwardRef<ChatRef, ChatProps>((props, ref) => {
|
||||
const { settings, setSettings } = useSettings()
|
||||
const { getRAGEngine } = useRAG()
|
||||
const diffStrategy = useDiffStrategy()
|
||||
const { customModeList, customModePrompts } = useCustomModes()
|
||||
|
||||
const {
|
||||
createOrUpdateConversation,
|
||||
@@ -112,8 +114,8 @@ const Chat = forwardRef<ChatRef, ChatProps>((props, ref) => {
|
||||
const { streamResponse, chatModel } = useLLM()
|
||||
|
||||
const promptGenerator = useMemo(() => {
|
||||
return new PromptGenerator(getRAGEngine, app, settings, diffStrategy)
|
||||
}, [getRAGEngine, app, settings, diffStrategy])
|
||||
return new PromptGenerator(getRAGEngine, app, settings, diffStrategy, customModePrompts, customModeList)
|
||||
}, [getRAGEngine, app, settings, diffStrategy, customModePrompts, customModeList])
|
||||
|
||||
const [inputMessage, setInputMessage] = useState<ChatUserMessage>(() => {
|
||||
const newMessage = getNewInputMessage(app, settings.defaultMention)
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import { Plus, Undo2, Settings, Circle, Trash2 } from 'lucide-react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { ChevronDown, ChevronRight, Plus, Trash2, Undo2 } from 'lucide-react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { useApp } from '../../contexts/AppContext';
|
||||
import { CustomMode, GroupEntry, ToolGroup } from '../../database/json/custom-mode/types';
|
||||
import { useCustomModes } from '../../hooks/use-custom-mode';
|
||||
import { CustomMode, ToolGroup, toolGroups, GroupEntry } from '../../database/json/custom-mode/types';
|
||||
import { modes as buildinModes } from '../../utils/modes';
|
||||
import { openOrCreateMarkdownFile } from '../../utils/obsidian';
|
||||
const CustomModeView = () => {
|
||||
const app = useApp()
|
||||
|
||||
const {
|
||||
createCustomMode,
|
||||
deleteCustomMode,
|
||||
@@ -15,7 +19,7 @@ const CustomModeView = () => {
|
||||
// 当前选择的模式
|
||||
const [selectedMode, setSelectedMode] = useState<string>('ask')
|
||||
const [isBuiltinMode, setIsBuiltinMode] = useState<boolean>(true)
|
||||
|
||||
const [isAdvancedCollapsed, setIsAdvancedCollapsed] = useState(true);
|
||||
|
||||
const isNewMode = React.useMemo(() => selectedMode === "add_new_mode", [selectedMode])
|
||||
|
||||
@@ -46,7 +50,6 @@ const CustomModeView = () => {
|
||||
// 自定义指令
|
||||
const [customInstructions, setCustomInstructions] = useState<string>('')
|
||||
|
||||
|
||||
// 当模式变更时更新表单数据
|
||||
useEffect(() => {
|
||||
// new mode
|
||||
@@ -63,7 +66,7 @@ const CustomModeView = () => {
|
||||
const builtinMode = buildinModes.find(m => m.slug === selectedMode);
|
||||
if (builtinMode) {
|
||||
setIsBuiltinMode(true);
|
||||
setModeName(builtinMode.name);
|
||||
setModeName(builtinMode.slug);
|
||||
setRoleDefinition(builtinMode.roleDefinition);
|
||||
setCustomInstructions(builtinMode.customInstructions || '');
|
||||
setSelectedTools(builtinMode.groups as GroupEntry[]);
|
||||
@@ -219,9 +222,11 @@ const CustomModeView = () => {
|
||||
<div className="infio-custom-modes-section">
|
||||
<div className="infio-section-header">
|
||||
<h3>角色定义</h3>
|
||||
<button className="infio-section-btn">
|
||||
<Undo2 size={16} />
|
||||
</button>
|
||||
{isBuiltinMode && (
|
||||
<button className="infio-section-btn">
|
||||
<Undo2 size={16} />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<p className="infio-section-subtitle">设定专业领域和应答风格</p>
|
||||
<textarea
|
||||
@@ -274,7 +279,7 @@ const CustomModeView = () => {
|
||||
checked={selectedTools.includes('research')}
|
||||
onChange={() => handleToolChange('research')}
|
||||
/>
|
||||
浏览器
|
||||
网络搜索
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -298,10 +303,29 @@ const CustomModeView = () => {
|
||||
placeholder="输入模式自定义指令..."
|
||||
/>
|
||||
<p className="infio-section-footer">
|
||||
支持从<a href="#" className="infio-link">_infio_prompts/code-rules/</a>目录读取配置
|
||||
支持从<a href="#" className="infio-link" onClick={() => openOrCreateMarkdownFile(app, `_infio_prompts/${modeName}/rules.md`, 0)}>_infio_prompts/{modeName}/rules</a> 文件中读取配置
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* 高级, 覆盖系统提示词 */}
|
||||
<div className="infio-custom-modes-section">
|
||||
<div
|
||||
className="infio-section-header infio-section-header-collapsible"
|
||||
onClick={() => setIsAdvancedCollapsed(!isAdvancedCollapsed)}
|
||||
>
|
||||
<div className="infio-section-header-title-container">
|
||||
{isAdvancedCollapsed ? <ChevronRight size={16} /> : <ChevronDown size={16} />}
|
||||
<h6>覆盖系统提示词</h6>
|
||||
</div>
|
||||
</div>
|
||||
{!isAdvancedCollapsed && (
|
||||
<p className="infio-section-subtitle">
|
||||
您可以通过在工作区创建文件
|
||||
<a href="#" className="infio-link" onClick={() => openOrCreateMarkdownFile(app, `_infio_prompts/${modeName}/system-prompt.md`, 0)}>_infio_prompts/{modeName}/system-prompt</a>
|
||||
,完全替换此模式的系统提示(角色定义和自定义指令除外)。这是一个非常高级的功能,会覆盖工具使用等全部内置提示, 请谨慎操作
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="infio-custom-modes-actions">
|
||||
<button className="infio-preview-btn">
|
||||
预览
|
||||
@@ -546,6 +570,17 @@ const CustomModeView = () => {
|
||||
justify-content: center;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.infio-section-header-collapsible {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.infio-section-header-title-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
||||
import { ChevronDown, ChevronUp } from 'lucide-react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import React, { useEffect, useState, useMemo } from 'react'
|
||||
|
||||
import { useSettings } from '../../../contexts/SettingsContext'
|
||||
import { useCustomModes } from '../../../hooks/use-custom-mode'
|
||||
import { modes } from '../../../utils/modes'
|
||||
|
||||
export function ModeSelect() {
|
||||
@@ -10,11 +11,14 @@ export function ModeSelect() {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [mode, setMode] = useState(settings.mode)
|
||||
|
||||
const { customModeList } = useCustomModes()
|
||||
|
||||
const allModes = useMemo(() => [...modes, ...customModeList], [customModeList])
|
||||
|
||||
useEffect(() => {
|
||||
setMode(settings.mode)
|
||||
}, [settings.mode])
|
||||
|
||||
|
||||
return (
|
||||
<DropdownMenu.Root open={isOpen} onOpenChange={setIsOpen}>
|
||||
<DropdownMenu.Trigger className="infio-chat-input-model-select">
|
||||
@@ -22,7 +26,7 @@ export function ModeSelect() {
|
||||
{isOpen ? <ChevronUp size={12} /> : <ChevronDown size={12} />}
|
||||
</div>
|
||||
<div className="infio-chat-input-model-select__model-name">
|
||||
{modes.find((m) => m.slug === mode)?.name}
|
||||
{allModes.find((m) => m.slug === mode)?.name}
|
||||
</div>
|
||||
</DropdownMenu.Trigger>
|
||||
|
||||
@@ -30,7 +34,7 @@ export function ModeSelect() {
|
||||
<DropdownMenu.Content
|
||||
className="infio-popover">
|
||||
<ul>
|
||||
{modes.map((mode) => (
|
||||
{allModes.map((mode) => (
|
||||
<DropdownMenu.Item
|
||||
key={mode.slug}
|
||||
onSelect={() => {
|
||||
|
||||
Reference in New Issue
Block a user