diff --git a/src/renderer/src/i18n/locales/en-us.json b/src/renderer/src/i18n/locales/en-us.json index 250e2be90c..8e42dda829 100644 --- a/src/renderer/src/i18n/locales/en-us.json +++ b/src/renderer/src/i18n/locales/en-us.json @@ -8,6 +8,7 @@ "add.name.placeholder": "Enter name", "add.prompt": "Prompt", "add.prompt.placeholder": "Enter prompt", + "add.prompt.variables.tip": "Available variables: {{date}}, {{time}}, {{datetime}}, {{system}}, {{arch}}, {{language}}, {{model_name}}", "add.title": "Create Agent", "import": { "title": "Import from External", diff --git a/src/renderer/src/i18n/locales/ja-jp.json b/src/renderer/src/i18n/locales/ja-jp.json index f7d35fd904..679849fbaa 100644 --- a/src/renderer/src/i18n/locales/ja-jp.json +++ b/src/renderer/src/i18n/locales/ja-jp.json @@ -8,6 +8,7 @@ "add.name.placeholder": "名前を入力", "add.prompt": "プロンプト", "add.prompt.placeholder": "プロンプトを入力", + "add.prompt.variables.tip": "利用可能な変数:{{date}}, {{time}}, {{datetime}}, {{system}}, {{arch}}, {{language}}, {{model_name}}", "add.title": "エージェントを作成", "import": { "title": "外部からインポート", diff --git a/src/renderer/src/i18n/locales/ru-ru.json b/src/renderer/src/i18n/locales/ru-ru.json index 960b242728..3e1049f524 100644 --- a/src/renderer/src/i18n/locales/ru-ru.json +++ b/src/renderer/src/i18n/locales/ru-ru.json @@ -8,6 +8,7 @@ "add.name.placeholder": "Введите имя", "add.prompt": "Промпт", "add.prompt.placeholder": "Введите промпт", + "add.prompt.variables.tip": "Доступные переменные: {{date}}, {{time}}, {{datetime}}, {{system}}, {{arch}}, {{language}}, {{model_name}}", "add.title": "Создать агента", "delete.popup.content": "Вы уверены, что хотите удалить этого агента?", "edit.message.add.title": "Добавить", diff --git a/src/renderer/src/i18n/locales/zh-cn.json b/src/renderer/src/i18n/locales/zh-cn.json index b88c9f7996..55af6f7fd7 100644 --- a/src/renderer/src/i18n/locales/zh-cn.json +++ b/src/renderer/src/i18n/locales/zh-cn.json @@ -8,6 +8,7 @@ "add.name.placeholder": "输入名称", "add.prompt": "提示词", "add.prompt.placeholder": "输入提示词", + "add.prompt.variables.tip": "可用的变量:{{date}}, {{time}}, {{datetime}}, {{system}}, {{arch}}, {{language}}, {{model_name}}", "add.title": "创建智能体", "import": { "title": "从外部导入", diff --git a/src/renderer/src/i18n/locales/zh-tw.json b/src/renderer/src/i18n/locales/zh-tw.json index d8eabe45f1..ce4294ec01 100644 --- a/src/renderer/src/i18n/locales/zh-tw.json +++ b/src/renderer/src/i18n/locales/zh-tw.json @@ -8,6 +8,7 @@ "add.name.placeholder": "輸入名稱", "add.prompt": "提示詞", "add.prompt.placeholder": "輸入提示詞", + "add.prompt.variables.tip": "可用的變數:{{date}}, {{time}}, {{datetime}}, {{system}}, {{arch}}, {{language}}, {{model_name}}", "add.title": "建立智慧代理人", "import": { "title": "從外部導入", diff --git a/src/renderer/src/pages/settings/AssistantSettings/AssistantPromptSettings.tsx b/src/renderer/src/pages/settings/AssistantSettings/AssistantPromptSettings.tsx index 7cd83a17f4..7cfdd72eb7 100644 --- a/src/renderer/src/pages/settings/AssistantSettings/AssistantPromptSettings.tsx +++ b/src/renderer/src/pages/settings/AssistantSettings/AssistantPromptSettings.tsx @@ -1,12 +1,12 @@ import 'emoji-picker-element' -import { CloseCircleFilled } from '@ant-design/icons' +import { CloseCircleFilled, QuestionCircleOutlined } from '@ant-design/icons' import EmojiPicker from '@renderer/components/EmojiPicker' import { Box, HSpaceBetweenStack, HStack } from '@renderer/components/Layout' import { estimateTextTokens } from '@renderer/services/TokenService' import { Assistant, AssistantSettings } from '@renderer/types' import { getLeadingEmoji } from '@renderer/utils' -import { Button, Input, Popover } from 'antd' +import { Button, Input, Popover, Tooltip } from 'antd' import TextArea from 'antd/es/input/TextArea' import { useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' @@ -90,9 +90,12 @@ const AssistantPromptSettings: React.FC = ({ assistant, updateAssistant } style={{ flex: 1 }} /> - - {t('common.prompt')} - + + {t('common.prompt')} + + + + {showMarkdown ? ( setShowMarkdown(false)}> diff --git a/src/renderer/src/providers/AiProvider/AnthropicProvider.ts b/src/renderer/src/providers/AiProvider/AnthropicProvider.ts index 703fa4b921..1f53f5d05e 100644 --- a/src/renderer/src/providers/AiProvider/AnthropicProvider.ts +++ b/src/renderer/src/providers/AiProvider/AnthropicProvider.ts @@ -243,7 +243,7 @@ export default class AnthropicProvider extends BaseProvider { }) if (this.useSystemPromptForTools && mcpTools && mcpTools.length) { - systemPrompt = buildSystemPrompt(systemPrompt, mcpTools) + systemPrompt = await buildSystemPrompt(systemPrompt, mcpTools) } let systemMessage: TextBlockParam | undefined = undefined diff --git a/src/renderer/src/providers/AiProvider/GeminiProvider.ts b/src/renderer/src/providers/AiProvider/GeminiProvider.ts index e19c47ea3c..28ead9e5e5 100644 --- a/src/renderer/src/providers/AiProvider/GeminiProvider.ts +++ b/src/renderer/src/providers/AiProvider/GeminiProvider.ts @@ -370,7 +370,7 @@ export default class GeminiProvider extends BaseProvider { }) if (this.useSystemPromptForTools) { - systemInstruction = buildSystemPrompt(assistant.prompt || '', mcpTools) + systemInstruction = await buildSystemPrompt(assistant.prompt || '', mcpTools) } const toolResponses: MCPToolResponse[] = [] diff --git a/src/renderer/src/providers/AiProvider/OpenAIProvider.ts b/src/renderer/src/providers/AiProvider/OpenAIProvider.ts index c9d2383c8f..78c6d306f2 100644 --- a/src/renderer/src/providers/AiProvider/OpenAIProvider.ts +++ b/src/renderer/src/providers/AiProvider/OpenAIProvider.ts @@ -399,7 +399,7 @@ export default class OpenAIProvider extends BaseOpenAIProvider { }) if (this.useSystemPromptForTools) { - systemMessage.content = buildSystemPrompt(systemMessage.content || '', mcpTools) + systemMessage.content = await buildSystemPrompt(systemMessage.content || '', mcpTools) } const userMessages: ChatCompletionMessageParam[] = [] diff --git a/src/renderer/src/providers/AiProvider/OpenAIResponseProvider.ts b/src/renderer/src/providers/AiProvider/OpenAIResponseProvider.ts index e6fa668f30..06fddd05ac 100644 --- a/src/renderer/src/providers/AiProvider/OpenAIResponseProvider.ts +++ b/src/renderer/src/providers/AiProvider/OpenAIResponseProvider.ts @@ -352,7 +352,7 @@ export abstract class BaseOpenAIProvider extends BaseProvider { tools = tools.concat(extraTools) if (this.useSystemPromptForTools) { - systemMessageInput.text = buildSystemPrompt(systemMessageInput.text || '', mcpTools) + systemMessageInput.text = await buildSystemPrompt(systemMessageInput.text || '', mcpTools) } systemMessageContent.push(systemMessageInput) systemMessage.content = systemMessageContent diff --git a/src/renderer/src/utils/__tests__/prompt.test.ts b/src/renderer/src/utils/__tests__/prompt.test.ts index 45886e8c7d..dd20ee5b0b 100644 --- a/src/renderer/src/utils/__tests__/prompt.test.ts +++ b/src/renderer/src/utils/__tests__/prompt.test.ts @@ -29,26 +29,26 @@ describe('prompt', () => { }) describe('buildSystemPrompt', () => { - it('should build prompt with tools', () => { + it('should build prompt with tools', async () => { const userPrompt = 'Custom user system prompt' const tools = [ { id: 'test-tool', description: 'Test tool description', inputSchema: { type: 'object' } } as MCPTool ] - const result = buildSystemPrompt(userPrompt, tools) + const result = await buildSystemPrompt(userPrompt, tools) expect(result).toContain(userPrompt) expect(result).toContain('test-tool') expect(result).toContain('Test tool description') }) - it('should return user prompt without tools', () => { + it('should return user prompt without tools', async () => { const userPrompt = 'Custom user system prompt' - const result = buildSystemPrompt(userPrompt, []) + const result = await buildSystemPrompt(userPrompt, []) expect(result).toBe(userPrompt) }) - it('should handle null or undefined user prompt', () => { + it('should handle null or undefined user prompt', async () => { const tools = [ { id: 'test-tool', description: 'Test tool description', inputSchema: { type: 'object' } } as MCPTool ] diff --git a/src/renderer/src/utils/prompt.ts b/src/renderer/src/utils/prompt.ts index d014bd4ce0..072635e430 100644 --- a/src/renderer/src/utils/prompt.ts +++ b/src/renderer/src/utils/prompt.ts @@ -1,5 +1,5 @@ +import store from '@renderer/store' import { MCPTool } from '@renderer/types' - export const SYSTEM_PROMPT = `In this environment you have access to a set of tools you can use to answer the user's question. \ You can use one tool per message, and will receive the result of that tool use in the user's response. You use tools step-by-step to accomplish a given task, with each tool use informed by the result of the previous tool use. @@ -147,7 +147,65 @@ ${availableTools} ` } -export const buildSystemPrompt = (userSystemPrompt: string, tools?: MCPTool[]): string => { +export const buildSystemPrompt = async (userSystemPrompt: string, tools?: MCPTool[]): Promise => { + if (typeof userSystemPrompt === 'string') { + const now = new Date() + if (userSystemPrompt.includes('{{date}}')) { + const date = now.toLocaleDateString() + userSystemPrompt = userSystemPrompt.replace(/{{date}}/g, date) + } + + if (userSystemPrompt.includes('{{time}}')) { + const time = now.toLocaleTimeString() + userSystemPrompt = userSystemPrompt.replace(/{{time}}/g, time) + } + + if (userSystemPrompt.includes('{{datetime}}')) { + const datetime = now.toLocaleString() + userSystemPrompt = userSystemPrompt.replace(/{{datetime}}/g, datetime) + } + + if (userSystemPrompt.includes('{{system}}')) { + try { + const systemType = await window.api.system.getDeviceType() + userSystemPrompt = userSystemPrompt.replace(/{{system}}/g, systemType) + } catch (error) { + console.error('Failed to get system type:', error) + userSystemPrompt = userSystemPrompt.replace(/{{system}}/g, 'Unknown System') + } + } + + if (userSystemPrompt.includes('{{language}}')) { + try { + const language = store.getState().settings.language + userSystemPrompt = userSystemPrompt.replace(/{{language}}/g, language) + } catch (error) { + console.error('Failed to get language:', error) + userSystemPrompt = userSystemPrompt.replace(/{{language}}/g, 'Unknown System Language') + } + } + + if (userSystemPrompt.includes('{{arch}}')) { + try { + const appInfo = await window.api.getAppInfo() + userSystemPrompt = userSystemPrompt.replace(/{{arch}}/g, appInfo.arch) + } catch (error) { + console.error('Failed to get architecture:', error) + userSystemPrompt = userSystemPrompt.replace(/{{arch}}/g, 'Unknown Architecture') + } + } + + if (userSystemPrompt.includes('{{model_name}}')) { + try { + const modelName = store.getState().llm.defaultModel.name + userSystemPrompt = userSystemPrompt.replace(/{{model_name}}/g, modelName) + } catch (error) { + console.error('Failed to get model name:', error) + userSystemPrompt = userSystemPrompt.replace(/{{model_name}}/g, 'Unknown Model') + } + } + } + if (tools && tools.length > 0) { return SYSTEM_PROMPT.replace('{{ USER_SYSTEM_PROMPT }}', userSystemPrompt) .replace('{{ TOOL_USE_EXAMPLES }}', ToolUseExamples)