mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-09 14:59:27 +08:00
feat: introduce MCP Prompt Plugin and refactor built-in plugin structure
- Added `mcpPromptPlugin.ts` to encapsulate MCP Prompt functionality, providing a structured approach for tool calls within prompts. - Updated `index.ts` to reference the new `mcpPromptPlugin`, enhancing modularity and clarity in the built-in plugins. - Removed the outdated `example-plugins.ts` file to streamline the plugin directory and focus on essential components.
This commit is contained in:
parent
cbbaa3127c
commit
30a288ce5d
@ -5,5 +5,5 @@
|
|||||||
export const BUILT_IN_PLUGIN_PREFIX = 'built-in:'
|
export const BUILT_IN_PLUGIN_PREFIX = 'built-in:'
|
||||||
|
|
||||||
export { createLoggingPlugin } from './logging'
|
export { createLoggingPlugin } from './logging'
|
||||||
export type { MCPPromptConfig, ToolUseResult } from './mcpPrompt'
|
export type { MCPPromptConfig, ToolUseResult } from './mcpPromptPlugin'
|
||||||
export { createMCPPromptPlugin } from './mcpPrompt'
|
export { createMCPPromptPlugin } from './mcpPromptPlugin'
|
||||||
|
|||||||
@ -286,10 +286,10 @@ function defaultParseToolUse(content: string, tools: ToolSet): ToolUseResult[] {
|
|||||||
/**
|
/**
|
||||||
* 创建 MCP Prompt 插件
|
* 创建 MCP Prompt 插件
|
||||||
*/
|
*/
|
||||||
export const createMCPPromptPlugin = definePlugin((config: MCPPromptConfig = {}) => {
|
export const createMCPPromptPlugin = (config: MCPPromptConfig = {}) => {
|
||||||
const { enabled = true, buildSystemPrompt = defaultBuildSystemPrompt, parseToolUse = defaultParseToolUse } = config
|
const { enabled = true, buildSystemPrompt = defaultBuildSystemPrompt, parseToolUse = defaultParseToolUse } = config
|
||||||
|
|
||||||
return {
|
return definePlugin({
|
||||||
name: 'built-in:mcp-prompt',
|
name: 'built-in:mcp-prompt',
|
||||||
|
|
||||||
transformParams: async (params: any, context: MCPRequestContext) => {
|
transformParams: async (params: any, context: MCPRequestContext) => {
|
||||||
@ -562,5 +562,5 @@ export const createMCPPromptPlugin = definePlugin((config: MCPPromptConfig = {})
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
}
|
||||||
@ -1,192 +0,0 @@
|
|||||||
import type { AiPlugin } from '../types'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 【First 钩子示例】模型别名解析插件
|
|
||||||
*/
|
|
||||||
export const ModelAliasPlugin: AiPlugin = {
|
|
||||||
name: 'model-alias',
|
|
||||||
enforce: 'pre',
|
|
||||||
|
|
||||||
async resolveModel(modelId) {
|
|
||||||
const aliases: Record<string, string> = {
|
|
||||||
gpt4: 'gpt-4-turbo-preview',
|
|
||||||
claude: 'claude-3-sonnet-20240229',
|
|
||||||
gemini: 'gemini-pro'
|
|
||||||
}
|
|
||||||
|
|
||||||
return aliases[modelId] || null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 【Sequential 钩子示例】参数验证和转换插件
|
|
||||||
*/
|
|
||||||
export const ParamsValidationPlugin: AiPlugin = {
|
|
||||||
name: 'params-validation',
|
|
||||||
|
|
||||||
async transformParams(params) {
|
|
||||||
// 参数验证
|
|
||||||
if (!params.messages || !Array.isArray(params.messages)) {
|
|
||||||
throw new Error('Invalid messages parameter')
|
|
||||||
}
|
|
||||||
|
|
||||||
// 参数转换:添加默认配置
|
|
||||||
return {
|
|
||||||
...params,
|
|
||||||
temperature: params.temperature ?? 0.7,
|
|
||||||
max_tokens: params.max_tokens ?? 4096,
|
|
||||||
stream: params.stream ?? true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async transformResult(result, context) {
|
|
||||||
// 结果后处理:添加元数据
|
|
||||||
return {
|
|
||||||
...result,
|
|
||||||
metadata: {
|
|
||||||
...result.metadata,
|
|
||||||
processedAt: new Date().toISOString(),
|
|
||||||
provider: context.providerId,
|
|
||||||
model: context.modelId
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 【Parallel 钩子示例】日志记录插件
|
|
||||||
*/
|
|
||||||
export const LoggingPlugin: AiPlugin = {
|
|
||||||
name: 'logging',
|
|
||||||
|
|
||||||
async onRequestStart(context) {
|
|
||||||
console.log(`🚀 AI请求开始: ${context.providerId}/${context.modelId}`, {
|
|
||||||
requestId: context.requestId,
|
|
||||||
timestamp: new Date().toISOString()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
async onRequestEnd(context, result) {
|
|
||||||
const duration = Date.now() - context.startTime
|
|
||||||
console.log(`✅ AI请求完成: ${context.requestId} (${duration}ms)`, {
|
|
||||||
provider: context.providerId,
|
|
||||||
model: context.modelId,
|
|
||||||
hasResult: !!result
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
async onError(error, context) {
|
|
||||||
const duration = Date.now() - context.startTime
|
|
||||||
console.error(`❌ AI请求失败: ${context.requestId} (${duration}ms)`, {
|
|
||||||
provider: context.providerId,
|
|
||||||
model: context.modelId,
|
|
||||||
error: error.message,
|
|
||||||
stack: error.stack
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 【Parallel 钩子示例】性能监控插件
|
|
||||||
*/
|
|
||||||
export const PerformancePlugin: AiPlugin = {
|
|
||||||
name: 'performance',
|
|
||||||
enforce: 'post',
|
|
||||||
|
|
||||||
async onRequestEnd(context) {
|
|
||||||
const duration = Date.now() - context.startTime
|
|
||||||
|
|
||||||
// 记录性能指标
|
|
||||||
const metrics = {
|
|
||||||
requestId: context.requestId,
|
|
||||||
provider: context.providerId,
|
|
||||||
model: context.modelId,
|
|
||||||
duration,
|
|
||||||
timestamp: context.startTime,
|
|
||||||
success: true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 发送到监控系统(这里只是示例)
|
|
||||||
// await sendMetrics(metrics)
|
|
||||||
console.log('📊 性能指标:', metrics)
|
|
||||||
},
|
|
||||||
|
|
||||||
async onError(error, context) {
|
|
||||||
const duration = Date.now() - context.startTime
|
|
||||||
|
|
||||||
const metrics = {
|
|
||||||
requestId: context.requestId,
|
|
||||||
provider: context.providerId,
|
|
||||||
model: context.modelId,
|
|
||||||
duration,
|
|
||||||
timestamp: context.startTime,
|
|
||||||
success: false,
|
|
||||||
errorType: error.constructor.name
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('📊 错误指标:', metrics)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 【Stream 钩子示例】内容过滤插件
|
|
||||||
*/
|
|
||||||
export const ContentFilterPlugin: AiPlugin = {
|
|
||||||
name: 'content-filter',
|
|
||||||
|
|
||||||
transformStream() {
|
|
||||||
return () =>
|
|
||||||
new TransformStream({
|
|
||||||
transform(chunk, controller) {
|
|
||||||
// 过滤敏感内容
|
|
||||||
if (chunk.type === 'text-delta') {
|
|
||||||
const filtered = chunk.textDelta.replace(/\b(敏感词|违禁词)\b/g, '***')
|
|
||||||
controller.enqueue({
|
|
||||||
...chunk,
|
|
||||||
textDelta: filtered
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
controller.enqueue(chunk)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 【First 钩子示例】模板加载插件
|
|
||||||
*/
|
|
||||||
export const TemplatePlugin: AiPlugin = {
|
|
||||||
name: 'template-loader',
|
|
||||||
|
|
||||||
async loadTemplate(templateName) {
|
|
||||||
const templates: Record<string, any> = {
|
|
||||||
chat: {
|
|
||||||
systemPrompt: '你是一个有用的AI助手',
|
|
||||||
temperature: 0.7
|
|
||||||
},
|
|
||||||
coding: {
|
|
||||||
systemPrompt: '你是一个专业的编程助手,请提供清晰、高质量的代码',
|
|
||||||
temperature: 0.3
|
|
||||||
},
|
|
||||||
creative: {
|
|
||||||
systemPrompt: '你是一个创意写作助手,请发挥想象力',
|
|
||||||
temperature: 0.9
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return templates[templateName] || null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 示例插件组合
|
|
||||||
*/
|
|
||||||
export const defaultPlugins: AiPlugin[] = [
|
|
||||||
ModelAliasPlugin,
|
|
||||||
TemplatePlugin,
|
|
||||||
ParamsValidationPlugin,
|
|
||||||
LoggingPlugin,
|
|
||||||
PerformancePlugin,
|
|
||||||
ContentFilterPlugin
|
|
||||||
]
|
|
||||||
Loading…
Reference in New Issue
Block a user