Files
PromptX/src/lib/core/resource/ResourceData.js

217 lines
5.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 资源数据类
* 描述单个资源的完整元信息
*/
class ResourceData {
/**
* @param {Object} options - 资源配置选项
* @param {string} options.id - 资源唯一标识
* @param {string} options.source - 资源来源 ('package' | 'project' | 'user')
* @param {string} options.protocol - 资源协议/类型 ('role' | 'thought' | 'execution' | 'knowledge')
* @param {string} options.name - 资源名称
* @param {string} options.description - 资源描述
* @param {string} options.reference - 资源引用路径
* @param {Object} options.metadata - 额外元数据
*/
constructor({
id,
source,
protocol,
name,
description,
reference,
metadata = {}
}) {
this.id = id
this.source = source
this.protocol = protocol
this.name = name
this.description = description
this.reference = reference
this.metadata = {
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
...metadata
}
}
/**
* 从原始数据创建ResourceData实例
* @param {Object} rawData - 原始数据
* @returns {ResourceData} ResourceData实例
*/
static fromRawData(rawData) {
return new ResourceData(rawData)
}
/**
* 从文件路径和协议推断创建ResourceData
* @param {string} filePath - 文件路径仅用于提取ID不保存
* @param {string} source - 资源来源
* @param {string} protocol - 资源协议
* @param {string} reference - 资源引用
* @returns {ResourceData} ResourceData实例
*/
static fromFilePath(filePath, source, protocol, reference) {
const path = require('path')
const fileName = path.basename(filePath, `.${protocol}.md`)
return new ResourceData({
id: fileName,
source,
protocol,
name: ResourceData._generateDefaultName(fileName, protocol),
description: ResourceData._generateDefaultDescription(fileName, protocol),
reference,
metadata: {
inferredFromFile: true
}
})
}
/**
* 生成默认名称
* @param {string} id - 资源ID
* @param {string} protocol - 资源协议
* @returns {string} 默认名称
* @private
*/
static _generateDefaultName(id, protocol) {
const nameMap = {
'role': '角色',
'thought': '思维模式',
'execution': '执行模式',
'knowledge': '知识库'
}
// 将kebab-case转换为可读名称
const readableName = id
.split('-')
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ')
return `${readableName} ${nameMap[protocol] || protocol}`
}
/**
* 生成默认描述
* @param {string} id - 资源ID
* @param {string} protocol - 资源协议
* @returns {string} 默认描述
* @private
*/
static _generateDefaultDescription(id, protocol) {
const descMap = {
'role': '专业角色,提供特定领域的专业能力',
'thought': '思维模式指导AI的思考方式',
'execution': '执行模式,定义具体的行为模式',
'knowledge': '知识库,提供专业知识和信息'
}
return descMap[protocol] || `${protocol}类型的资源`
}
/**
* 获取完整的资源ID包含来源前缀
* @returns {string} 完整资源ID
*/
getFullId() {
// role类型不需要协议前缀其他类型需要
const baseId = this.protocol === 'role' ? this.id : `${this.protocol}:${this.id}`
return `${this.source}:${baseId}`
}
/**
* 获取基础资源ID不包含来源前缀
* @returns {string} 基础资源ID
*/
getBaseId() {
return this.protocol === 'role' ? this.id : `${this.protocol}:${this.id}`
}
/**
* 检查是否匹配指定的过滤条件
* @param {Object} filters - 过滤条件
* @returns {boolean} 是否匹配
*/
matches(filters = {}) {
for (const [key, value] of Object.entries(filters)) {
if (value !== undefined && value !== null) {
if (Array.isArray(value)) {
if (!value.includes(this[key])) return false
} else {
if (this[key] !== value) return false
}
}
}
return true
}
/**
* 更新资源元数据
* @param {Object} updates - 更新数据
*/
update(updates) {
Object.assign(this, updates)
this.metadata.updatedAt = new Date().toISOString()
}
/**
* 转换为JSON对象
* @returns {Object} JSON对象
*/
toJSON() {
return {
id: this.id,
source: this.source,
protocol: this.protocol,
name: this.name,
description: this.description,
reference: this.reference,
metadata: this.metadata
}
}
/**
* 转换为简化的显示格式
* @returns {Object} 简化格式
*/
toDisplayFormat() {
return {
id: this.id,
fullId: this.getFullId(),
baseId: this.getBaseId(),
name: this.name,
description: this.description,
source: this.source,
protocol: this.protocol
}
}
/**
* 动态获取文件路径
* 通过解析 reference 动态计算实际的文件路径
* @returns {Promise<string>} 文件路径
*/
async getFilePath() {
const ProtocolResolver = require('./ProtocolResolver')
const resolver = new ProtocolResolver()
try {
const resolvedPath = await resolver.resolve(this.reference)
return resolvedPath
} catch (error) {
throw new Error(`无法解析资源路径 ${this.reference}: ${error.message}`)
}
}
/**
* 克隆资源数据
* @returns {ResourceData} 克隆的实例
*/
clone() {
return new ResourceData(this.toJSON())
}
}
module.exports = ResourceData