mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-06 21:35:52 +08:00
Merge branch 'main' into develop
# Conflicts: # src/renderer/src/providers/AiProvider/OpenAIProvider.ts # src/renderer/src/providers/AiProvider/OpenAIResponseProvider.ts
This commit is contained in:
commit
8bd38ccd86
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "CherryStudio",
|
"name": "CherryStudio",
|
||||||
"version": "1.3.0",
|
"version": "1.3.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "A powerful AI assistant for producer.",
|
"description": "A powerful AI assistant for producer.",
|
||||||
"main": "./out/main/index.js",
|
"main": "./out/main/index.js",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import 'emoji-picker-element'
|
import 'emoji-picker-element'
|
||||||
|
|
||||||
import { CheckOutlined, LoadingOutlined, ThunderboltOutlined } from '@ant-design/icons'
|
import { CheckOutlined, LoadingOutlined, ThunderboltOutlined, RollbackOutlined } from '@ant-design/icons'
|
||||||
import EmojiPicker from '@renderer/components/EmojiPicker'
|
import EmojiPicker from '@renderer/components/EmojiPicker'
|
||||||
import { TopView } from '@renderer/components/TopView'
|
import { TopView } from '@renderer/components/TopView'
|
||||||
import { AGENT_PROMPT } from '@renderer/config/prompts'
|
import { AGENT_PROMPT } from '@renderer/config/prompts'
|
||||||
@ -38,6 +38,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
|||||||
const formRef = useRef<FormInstance>(null)
|
const formRef = useRef<FormInstance>(null)
|
||||||
const [emoji, setEmoji] = useState('')
|
const [emoji, setEmoji] = useState('')
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
|
const [showUndoButton, setShowUndoButton] = useState(false)
|
||||||
|
const [originalPrompt, setOriginalPrompt] = useState('')
|
||||||
const [tokenCount, setTokenCount] = useState(0)
|
const [tokenCount, setTokenCount] = useState(0)
|
||||||
const knowledgeState = useAppSelector((state) => state.knowledge)
|
const knowledgeState = useAppSelector((state) => state.knowledge)
|
||||||
const showKnowledgeIcon = useSidebarIconShow('knowledge')
|
const showKnowledgeIcon = useSidebarIconShow('knowledge')
|
||||||
@ -98,7 +100,7 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
|||||||
resolve(null)
|
resolve(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleButtonClick = async () => {
|
const handleGenerateButtonClick = async () => {
|
||||||
const name = formRef.current?.getFieldValue('name')
|
const name = formRef.current?.getFieldValue('name')
|
||||||
const content = formRef.current?.getFieldValue('prompt')
|
const content = formRef.current?.getFieldValue('prompt')
|
||||||
const promptText = content || name
|
const promptText = content || name
|
||||||
@ -112,6 +114,7 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
|
setShowUndoButton(false)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const generatedText = await fetchGenerate({
|
const generatedText = await fetchGenerate({
|
||||||
@ -119,6 +122,8 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
|||||||
content: promptText
|
content: promptText
|
||||||
})
|
})
|
||||||
form.setFieldsValue({ prompt: generatedText })
|
form.setFieldsValue({ prompt: generatedText })
|
||||||
|
setShowUndoButton(true)
|
||||||
|
setOriginalPrompt(content)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching data:', error)
|
console.error('Error fetching data:', error)
|
||||||
}
|
}
|
||||||
@ -126,6 +131,11 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
|||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleUndoButtonClick = async () => {
|
||||||
|
form.setFieldsValue({ prompt: originalPrompt })
|
||||||
|
setShowUndoButton(false)
|
||||||
|
}
|
||||||
|
|
||||||
// Compute label width based on the longest label
|
// Compute label width based on the longest label
|
||||||
const labelWidth = [t('agents.add.name'), t('agents.add.prompt'), t('agents.add.knowledge_base')]
|
const labelWidth = [t('agents.add.name'), t('agents.add.prompt'), t('agents.add.knowledge_base')]
|
||||||
.map((labelText) => stringWidth(labelText) * 8)
|
.map((labelText) => stringWidth(labelText) * 8)
|
||||||
@ -155,6 +165,7 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
|||||||
if (changedValues.prompt) {
|
if (changedValues.prompt) {
|
||||||
const count = await estimateTextTokens(changedValues.prompt)
|
const count = await estimateTextTokens(changedValues.prompt)
|
||||||
setTokenCount(count)
|
setTokenCount(count)
|
||||||
|
setShowUndoButton(false)
|
||||||
}
|
}
|
||||||
}}>
|
}}>
|
||||||
<Form.Item name="name" label="Emoji">
|
<Form.Item name="name" label="Emoji">
|
||||||
@ -176,10 +187,15 @@ const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
|||||||
<TokenCount>Tokens: {tokenCount}</TokenCount>
|
<TokenCount>Tokens: {tokenCount}</TokenCount>
|
||||||
<Button
|
<Button
|
||||||
icon={loading ? <LoadingOutlined /> : <ThunderboltOutlined />}
|
icon={loading ? <LoadingOutlined /> : <ThunderboltOutlined />}
|
||||||
onClick={handleButtonClick}
|
onClick={handleGenerateButtonClick}
|
||||||
style={{ position: 'absolute', top: 8, right: 8 }}
|
style={{ position: 'absolute', top: 8, right: 8 }}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
/>
|
/>
|
||||||
|
{showUndoButton && <Button
|
||||||
|
icon={<RollbackOutlined />}
|
||||||
|
onClick={handleUndoButtonClick}
|
||||||
|
style={{ position: 'absolute', top: 8, right: 48 }}
|
||||||
|
/>}
|
||||||
</div>
|
</div>
|
||||||
{showKnowledgeIcon && (
|
{showKnowledgeIcon && (
|
||||||
<Form.Item name="knowledge_base_ids" label={t('agents.add.knowledge_base')} rules={[{ required: false }]}>
|
<Form.Item name="knowledge_base_ids" label={t('agents.add.knowledge_base')} rules={[{ required: false }]}>
|
||||||
|
|||||||
@ -50,29 +50,34 @@ const WebSearchButton: FC<Props> = ({ ref, assistant, ToolbarButton }) => {
|
|||||||
const providerItems = useMemo<QuickPanelListItem[]>(() => {
|
const providerItems = useMemo<QuickPanelListItem[]>(() => {
|
||||||
const isWebSearchModelEnabled = assistant.model && isWebSearchModel(assistant.model)
|
const isWebSearchModelEnabled = assistant.model && isWebSearchModel(assistant.model)
|
||||||
|
|
||||||
const items: QuickPanelListItem[] = providers.map((p) => ({
|
const items: QuickPanelListItem[] = providers
|
||||||
label: p.name,
|
.map((p) => ({
|
||||||
description: WebSearchService.isWebSearchEnabled(p.id)
|
label: p.name,
|
||||||
? hasObjectKey(p, 'apiKey')
|
description: WebSearchService.isWebSearchEnabled(p.id)
|
||||||
? t('settings.websearch.apikey')
|
? hasObjectKey(p, 'apiKey')
|
||||||
: t('settings.websearch.free')
|
? t('settings.websearch.apikey')
|
||||||
: t('chat.input.web_search.enable_content'),
|
: t('settings.websearch.free')
|
||||||
icon: <Globe />,
|
: t('chat.input.web_search.enable_content'),
|
||||||
isSelected: p.id === assistant?.webSearchProviderId,
|
icon: <Globe />,
|
||||||
disabled: !WebSearchService.isWebSearchEnabled(p.id),
|
isSelected: p.id === assistant?.webSearchProviderId,
|
||||||
action: () => updateSelectedWebSearchProvider(p.id)
|
disabled: !WebSearchService.isWebSearchEnabled(p.id),
|
||||||
}))
|
action: () => updateSelectedWebSearchProvider(p.id)
|
||||||
|
}))
|
||||||
|
.filter((o) => !o.disabled)
|
||||||
|
|
||||||
|
if (isWebSearchModelEnabled) {
|
||||||
|
items.unshift({
|
||||||
|
label: t('chat.input.web_search.builtin'),
|
||||||
|
description: isWebSearchModelEnabled
|
||||||
|
? t('chat.input.web_search.builtin.enabled_content')
|
||||||
|
: t('chat.input.web_search.builtin.disabled_content'),
|
||||||
|
icon: <Globe />,
|
||||||
|
isSelected: assistant.enableWebSearch,
|
||||||
|
disabled: !isWebSearchModelEnabled,
|
||||||
|
action: () => updateSelectedWebSearchBuiltin()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
items.unshift({
|
|
||||||
label: t('chat.input.web_search.builtin'),
|
|
||||||
description: isWebSearchModelEnabled
|
|
||||||
? t('chat.input.web_search.builtin.enabled_content')
|
|
||||||
: t('chat.input.web_search.builtin.disabled_content'),
|
|
||||||
icon: <Globe />,
|
|
||||||
isSelected: assistant.enableWebSearch,
|
|
||||||
disabled: !isWebSearchModelEnabled,
|
|
||||||
action: () => updateSelectedWebSearchBuiltin()
|
|
||||||
})
|
|
||||||
items.push({
|
items.push({
|
||||||
label: '前往设置' + '...',
|
label: '前往设置' + '...',
|
||||||
icon: <Settings />,
|
icon: <Settings />,
|
||||||
@ -105,7 +110,8 @@ const WebSearchButton: FC<Props> = ({ ref, assistant, ToolbarButton }) => {
|
|||||||
quickPanel.open({
|
quickPanel.open({
|
||||||
title: t('chat.input.web_search'),
|
title: t('chat.input.web_search'),
|
||||||
list: providerItems,
|
list: providerItems,
|
||||||
symbol: '?'
|
symbol: '?',
|
||||||
|
pageSize: 9
|
||||||
})
|
})
|
||||||
}, [quickPanel, providerItems, t])
|
}, [quickPanel, providerItems, t])
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user