feat: 实现@tool协议完整功能 - JavaScript工具执行框架
✨ 核心功能 - 新增ToolProtocol处理器,支持@tool://协议解析 - 实现PromptXToolCommand,统一MCP/CLI工具调用 - 完善ToolExecutor,支持工具实例化和参数验证 - 新增calculator和send-email示例工具 🔧 技术改进 - 优化PackageDiscovery统一资源扫描逻辑 - 增强CrossPlatformFileScanner支持.tool.js文件 - 完善ResourceManager集成ToolProtocol - 更新MCP工具定义支持promptx_tool 📋 详细变更 Core: - src/lib/core/resource/protocols/ToolProtocol.js: 新增工具协议处理器 - src/lib/commands/PromptXToolCommand.js: 新增工具命令处理器 - src/lib/tool/ToolExecutor.js: 增强工具执行器兼容性 Discovery: - src/lib/core/resource/discovery/PackageDiscovery.js: 统一资源扫描 - src/lib/core/resource/discovery/CrossPlatformFileScanner.js: 支持tool文件 - src/lib/core/resource/discovery/ProjectDiscovery.js: 增加tool验证 Integration: - src/lib/core/resource/resourceManager.js: 集成ToolProtocol - src/lib/mcp/toolDefinitions.js: 新增promptx_tool定义 - src/lib/commands/MCPServerCommand.js: 支持tool参数转换 - src/bin/promptx.js: 新增tool命令行支持 Tools: - prompt/tool/calculator.tool.js: 数学计算工具示例 - prompt/tool/send-email.tool.js: 邮件发送工具示例 Registry: - src/package.registry.json: 自动生成包含2个tool资源 🧪 测试验证 - ✅ @tool://calculator 数学计算: 25 + 37 = 62 - ✅ @tool://send-email 邮件发送演示版本 - ✅ CLI和MCP双模式支持 - ✅ 完整的错误处理和执行元数据 - ✅ 资源自动发现和注册 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
139
prompt/tool/calculator.tool.js
Normal file
139
prompt/tool/calculator.tool.js
Normal file
@ -0,0 +1,139 @@
|
||||
/**
|
||||
* @tool calculator
|
||||
* @description 数学计算工具
|
||||
* @version 1.0.0
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* 获取工具元信息
|
||||
* @returns {Object} 工具元信息
|
||||
*/
|
||||
getMetadata() {
|
||||
return {
|
||||
name: 'calculator',
|
||||
description: '提供基础数学计算功能,支持加减乘除运算',
|
||||
version: '1.0.0',
|
||||
author: 'PromptX Framework',
|
||||
category: 'math',
|
||||
tags: ['calculator', 'math', 'arithmetic']
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取参数Schema
|
||||
* @returns {Object} JSON Schema定义
|
||||
*/
|
||||
getSchema() {
|
||||
return {
|
||||
type: 'object',
|
||||
properties: {
|
||||
operation: {
|
||||
type: 'string',
|
||||
enum: ['add', 'subtract', 'multiply', 'divide'],
|
||||
description: '数学运算类型'
|
||||
},
|
||||
a: {
|
||||
type: 'number',
|
||||
description: '第一个操作数'
|
||||
},
|
||||
b: {
|
||||
type: 'number',
|
||||
description: '第二个操作数'
|
||||
}
|
||||
},
|
||||
required: ['operation', 'a', 'b'],
|
||||
additionalProperties: false
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 验证参数
|
||||
* @param {Object} params - 输入参数
|
||||
* @returns {boolean} 验证结果
|
||||
*/
|
||||
validate(params) {
|
||||
const { operation, a, b } = params
|
||||
|
||||
// 检查必需参数
|
||||
if (!operation || typeof a !== 'number' || typeof b !== 'number') {
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查操作类型
|
||||
const validOperations = ['add', 'subtract', 'multiply', 'divide']
|
||||
if (!validOperations.includes(operation)) {
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查除零
|
||||
if (operation === 'divide' && b === 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
},
|
||||
|
||||
/**
|
||||
* 执行计算
|
||||
* @param {Object} params - 计算参数
|
||||
* @param {string} params.operation - 运算类型 ('add', 'subtract', 'multiply', 'divide')
|
||||
* @param {number} params.a - 第一个操作数
|
||||
* @param {number} params.b - 第二个操作数
|
||||
* @returns {Object} 计算结果
|
||||
*/
|
||||
async execute(params) {
|
||||
const { operation, a, b } = params
|
||||
|
||||
let result
|
||||
let expression
|
||||
|
||||
switch (operation) {
|
||||
case 'add':
|
||||
result = a + b
|
||||
expression = `${a} + ${b}`
|
||||
break
|
||||
case 'subtract':
|
||||
result = a - b
|
||||
expression = `${a} - ${b}`
|
||||
break
|
||||
case 'multiply':
|
||||
result = a * b
|
||||
expression = `${a} × ${b}`
|
||||
break
|
||||
case 'divide':
|
||||
if (b === 0) {
|
||||
throw new Error('Division by zero is not allowed')
|
||||
}
|
||||
result = a / b
|
||||
expression = `${a} ÷ ${b}`
|
||||
break
|
||||
default:
|
||||
throw new Error(`Unknown operation: ${operation}`)
|
||||
}
|
||||
|
||||
return {
|
||||
expression,
|
||||
result,
|
||||
operation,
|
||||
operands: { a, b },
|
||||
formatted: `${expression} = ${result}`
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 工具初始化(可选)
|
||||
*/
|
||||
async init() {
|
||||
// 可以在这里进行工具初始化工作
|
||||
return true
|
||||
},
|
||||
|
||||
/**
|
||||
* 工具清理(可选)
|
||||
*/
|
||||
async cleanup() {
|
||||
// 可以在这里进行清理工作
|
||||
return true
|
||||
}
|
||||
}
|
||||
202
prompt/tool/send-email.tool.js
Normal file
202
prompt/tool/send-email.tool.js
Normal file
@ -0,0 +1,202 @@
|
||||
/**
|
||||
* @tool send-email
|
||||
* @description 邮件发送工具(演示版)
|
||||
* @version 1.0.0
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* 获取工具元信息
|
||||
* @returns {Object} 工具元信息
|
||||
*/
|
||||
getMetadata() {
|
||||
return {
|
||||
name: 'send-email',
|
||||
description: '邮件发送工具,支持发送格式化邮件(演示版本)',
|
||||
version: '1.0.0',
|
||||
author: 'PromptX Framework',
|
||||
category: 'communication',
|
||||
tags: ['email', 'communication', 'notification'],
|
||||
demo: true
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取参数Schema
|
||||
* @returns {Object} JSON Schema定义
|
||||
*/
|
||||
getSchema() {
|
||||
return {
|
||||
type: 'object',
|
||||
properties: {
|
||||
to: {
|
||||
type: 'string',
|
||||
format: 'email',
|
||||
description: '收件人邮箱地址'
|
||||
},
|
||||
subject: {
|
||||
type: 'string',
|
||||
minLength: 1,
|
||||
description: '邮件主题'
|
||||
},
|
||||
content: {
|
||||
type: 'string',
|
||||
minLength: 1,
|
||||
description: '邮件内容'
|
||||
},
|
||||
cc: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string',
|
||||
format: 'email'
|
||||
},
|
||||
description: '抄送邮箱列表(可选)'
|
||||
},
|
||||
priority: {
|
||||
type: 'string',
|
||||
enum: ['low', 'normal', 'high'],
|
||||
default: 'normal',
|
||||
description: '邮件优先级'
|
||||
}
|
||||
},
|
||||
required: ['to', 'subject', 'content'],
|
||||
additionalProperties: false
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 验证参数
|
||||
* @param {Object} params - 输入参数
|
||||
* @returns {boolean} 验证结果
|
||||
*/
|
||||
validate(params) {
|
||||
const { to, subject, content } = params
|
||||
|
||||
// 检查必需参数
|
||||
if (!to || !subject || !content) {
|
||||
return false
|
||||
}
|
||||
|
||||
// 简单的邮箱格式验证
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
|
||||
if (!emailRegex.test(to)) {
|
||||
return false
|
||||
}
|
||||
|
||||
// 检查抄送邮箱格式(如果存在)
|
||||
if (params.cc && Array.isArray(params.cc)) {
|
||||
for (const ccEmail of params.cc) {
|
||||
if (!emailRegex.test(ccEmail)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
},
|
||||
|
||||
/**
|
||||
* 发送邮件(演示版本)
|
||||
* @param {Object} params - 邮件参数
|
||||
* @param {string} params.to - 收件人邮箱
|
||||
* @param {string} params.subject - 邮件主题
|
||||
* @param {string} params.content - 邮件内容
|
||||
* @param {string[]} params.cc - 抄送邮箱列表(可选)
|
||||
* @param {string} params.priority - 邮件优先级(可选)
|
||||
* @returns {Object} 发送结果
|
||||
*/
|
||||
async execute(params) {
|
||||
const { to, subject, content, cc = [], priority = 'normal' } = params
|
||||
|
||||
// 生成邮件ID(演示用)
|
||||
const emailId = `email_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
||||
|
||||
// 格式化邮件内容
|
||||
const formattedEmail = this.formatEmail({
|
||||
to,
|
||||
subject,
|
||||
content,
|
||||
cc,
|
||||
priority,
|
||||
timestamp: new Date().toISOString()
|
||||
})
|
||||
|
||||
// 模拟发送延迟
|
||||
await this.simulateDelay(500)
|
||||
|
||||
// 演示版本:不实际发送邮件,只返回格式化结果
|
||||
return {
|
||||
success: true,
|
||||
email_id: emailId,
|
||||
to,
|
||||
subject,
|
||||
content_preview: content.slice(0, 100) + (content.length > 100 ? '...' : ''),
|
||||
cc_count: cc.length,
|
||||
priority,
|
||||
timestamp: new Date().toISOString(),
|
||||
formatted_email: formattedEmail,
|
||||
demo_note: '这是演示版本,邮件未实际发送',
|
||||
status: 'demo_sent'
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 格式化邮件内容
|
||||
* @param {Object} emailData - 邮件数据
|
||||
* @returns {string} 格式化的邮件
|
||||
*/
|
||||
formatEmail(emailData) {
|
||||
const { to, subject, content, cc, priority, timestamp } = emailData
|
||||
|
||||
let formatted = `收件人: ${to}\n`
|
||||
|
||||
if (cc.length > 0) {
|
||||
formatted += `抄送: ${cc.join(', ')}\n`
|
||||
}
|
||||
|
||||
formatted += `主题: ${subject}\n`
|
||||
formatted += `优先级: ${this.getPriorityText(priority)}\n`
|
||||
formatted += `时间: ${new Date(timestamp).toLocaleString('zh-CN')}\n`
|
||||
formatted += `\n内容:\n${content}\n`
|
||||
|
||||
return formatted
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取优先级文本
|
||||
* @param {string} priority - 优先级
|
||||
* @returns {string} 优先级文本
|
||||
*/
|
||||
getPriorityText(priority) {
|
||||
const priorityMap = {
|
||||
low: '低',
|
||||
normal: '普通',
|
||||
high: '高'
|
||||
}
|
||||
return priorityMap[priority] || '普通'
|
||||
},
|
||||
|
||||
/**
|
||||
* 模拟网络延迟
|
||||
* @param {number} ms - 延迟毫秒数
|
||||
*/
|
||||
async simulateDelay(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms))
|
||||
},
|
||||
|
||||
/**
|
||||
* 工具初始化
|
||||
*/
|
||||
async init() {
|
||||
// 在实际版本中,这里可以初始化邮件服务连接
|
||||
return true
|
||||
},
|
||||
|
||||
/**
|
||||
* 工具清理
|
||||
*/
|
||||
async cleanup() {
|
||||
// 在实际版本中,这里可以关闭邮件服务连接
|
||||
return true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user