mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-12 00:49:14 +08:00
✨ feat(hub): add dedicated AUTO_MODE_SYSTEM_PROMPT for auto mode
- Create self-contained prompt teaching XML tool_use format - Only shows search/exec tools (no generic examples) - Add complete workflow example with common mistakes - Update parameterBuilder to use getAutoModeSystemPrompt() - User prompt comes first, then auto mode instructions - Skip hub prompt when no tools available
This commit is contained in:
parent
9af45a6689
commit
b58569fcec
@ -26,7 +26,7 @@ import {
|
||||
isSupportedThinkingTokenModel,
|
||||
isWebSearchModel
|
||||
} from '@renderer/config/models'
|
||||
import { getHubModeSystemPrompt } from '@renderer/config/prompts'
|
||||
import { getAutoModeSystemPrompt } from '@renderer/config/prompts'
|
||||
import { fetchAllActiveServerTools } from '@renderer/services/ApiService'
|
||||
import { getDefaultModel } from '@renderer/services/AssistantService'
|
||||
import store from '@renderer/store'
|
||||
@ -245,16 +245,18 @@ export async function buildStreamTextParams(
|
||||
params.tools = tools
|
||||
}
|
||||
|
||||
if (assistant.prompt) {
|
||||
let systemPrompt = await replacePromptVariables(assistant.prompt, model.name)
|
||||
if (getEffectiveMcpMode(assistant) === 'auto') {
|
||||
const allActiveTools = await fetchAllActiveServerTools()
|
||||
systemPrompt = systemPrompt + '\n\n' + getHubModeSystemPrompt(allActiveTools)
|
||||
}
|
||||
params.system = systemPrompt
|
||||
} else if (getEffectiveMcpMode(assistant) === 'auto') {
|
||||
let systemPrompt = assistant.prompt ? await replacePromptVariables(assistant.prompt, model.name) : ''
|
||||
|
||||
if (getEffectiveMcpMode(assistant) === 'auto') {
|
||||
const allActiveTools = await fetchAllActiveServerTools()
|
||||
params.system = getHubModeSystemPrompt(allActiveTools)
|
||||
const autoModePrompt = getAutoModeSystemPrompt(allActiveTools)
|
||||
if (autoModePrompt) {
|
||||
systemPrompt = systemPrompt ? `${systemPrompt}\n\n${autoModePrompt}` : autoModePrompt
|
||||
}
|
||||
}
|
||||
|
||||
if (systemPrompt) {
|
||||
params.system = systemPrompt
|
||||
}
|
||||
|
||||
logger.debug('params', params)
|
||||
|
||||
@ -619,3 +619,108 @@ export function getHubModeSystemPrompt(tools: ToolInfo[] = []): string {
|
||||
${toolsSection}
|
||||
`
|
||||
}
|
||||
|
||||
const AUTO_MODE_SYSTEM_PROMPT_BASE = `
|
||||
You can discover and invoke MCP tools through a hub using TWO meta-tools: \`search\` and \`exec\`.
|
||||
|
||||
## Tool Invocation Format
|
||||
|
||||
When you want to call a tool, output exactly one XML block:
|
||||
|
||||
<tool_use>
|
||||
<name>{tool_name}</name>
|
||||
<arguments>{json_arguments}</arguments>
|
||||
</tool_use>
|
||||
|
||||
Rules:
|
||||
- \`{tool_name}\` MUST be either \`search\` or \`exec\`
|
||||
- \`<arguments>\` MUST contain valid JSON (no comments, no trailing commas)
|
||||
- Do NOT include extra text before or after the \`<tool_use>\` block
|
||||
|
||||
## Available Tools
|
||||
|
||||
1. **search** - Discover MCP tools by keyword
|
||||
\`\`\`json
|
||||
{ "query": "keyword1,keyword2", "limit": 10 }
|
||||
\`\`\`
|
||||
Returns JavaScript function declarations with JSDoc showing names, parameters, and return types.
|
||||
|
||||
2. **exec** - Execute JavaScript that calls discovered tools
|
||||
\`\`\`json
|
||||
{ "code": "const r = await ToolName({...}); return r;" }
|
||||
\`\`\`
|
||||
**CRITICAL:** You MUST \`return\` the final value, or result will be \`undefined\`.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Call \`search\` with keywords to discover tools
|
||||
2. Read the returned function signatures carefully
|
||||
3. Call \`exec\` with JavaScript code that:
|
||||
- Uses ONLY functions returned by \`search\`
|
||||
- Calls them with \`await\`
|
||||
- Ends with explicit \`return\`
|
||||
4. Answer the user based on the result
|
||||
|
||||
## Example
|
||||
|
||||
User: "Calculate 15 * 7"
|
||||
|
||||
Assistant calls search:
|
||||
<tool_use>
|
||||
<name>search</name>
|
||||
<arguments>{"query": "python,calculator"}</arguments>
|
||||
</tool_use>
|
||||
|
||||
Hub returns function signature:
|
||||
\`\`\`js
|
||||
async function CherryPython_pythonExecute(params: { code: string }): Promise<unknown>
|
||||
\`\`\`
|
||||
|
||||
Assistant calls exec:
|
||||
<tool_use>
|
||||
<name>exec</name>
|
||||
<arguments>{"code": "const result = await CherryPython_pythonExecute({ code: '15 * 7' }); return result;"}</arguments>
|
||||
</tool_use>
|
||||
|
||||
Hub returns: { "result": 105 }
|
||||
|
||||
Assistant answers: "15 × 7 = 105"
|
||||
|
||||
## Common Mistakes
|
||||
|
||||
❌ Forgetting to return (result will be undefined):
|
||||
\`\`\`js
|
||||
await SomeTool({ id: "123" })
|
||||
\`\`\`
|
||||
|
||||
✅ Always return:
|
||||
\`\`\`js
|
||||
const data = await SomeTool({ id: "123" }); return data;
|
||||
\`\`\`
|
||||
|
||||
❌ Calling exec before search - you must discover tools first
|
||||
|
||||
❌ Using functions not returned by search
|
||||
`
|
||||
|
||||
export function getAutoModeSystemPrompt(tools: ToolInfo[] = []): string {
|
||||
if (tools.length === 0) {
|
||||
return ''
|
||||
}
|
||||
|
||||
const existingNames = new Set<string>()
|
||||
const toolsSection = tools
|
||||
.map((t) => {
|
||||
const functionName = generateMcpToolFunctionName(t.serverName, t.name, existingNames)
|
||||
const desc = t.description || ''
|
||||
const normalizedDesc = desc.replace(/\s+/g, ' ').trim()
|
||||
const truncatedDesc = normalizedDesc.length > 50 ? `${normalizedDesc.slice(0, 50)}...` : normalizedDesc
|
||||
return `- ${functionName}: ${truncatedDesc}`
|
||||
})
|
||||
.join('\n')
|
||||
|
||||
return `${AUTO_MODE_SYSTEM_PROMPT_BASE}
|
||||
## Discoverable Tools (use search to get full signatures)
|
||||
${toolsSection}
|
||||
`
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user