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:
Vaayne 2025-12-31 11:49:07 +08:00
parent 9af45a6689
commit b58569fcec
2 changed files with 117 additions and 10 deletions

View File

@ -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)

View File

@ -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}
`
}