5e32375f0e
架构变更: - 采用 pnpm workspaces 实现 Monorepo 结构 - 将现有代码迁移到 packages/core - 新增 packages/server HTTP 服务层 Server 功能: - REST API: 会话管理、工具管理、配置管理 - WebSocket: 实时双向通信支持 - SSE: 服务端事件推送 - Hono + Bun 作为运行时 API 端点: - GET/POST /api/sessions - 会话 CRUD - GET/POST /api/sessions/:id/messages - 消息管理 - GET /api/sessions/:id/events - SSE 事件流 - WS /api/ws/:sessionId - WebSocket 连接 - GET/POST /api/tools - 工具管理 - GET/PUT /api/config - 配置管理
84 lines
1.9 KiB
TypeScript
84 lines
1.9 KiB
TypeScript
import type { ToolMetadata, ToolSearchResult } from './types.js';
|
|
|
|
/**
|
|
* 分词函数,支持中英文
|
|
*/
|
|
function tokenize(text: string): string[] {
|
|
return text
|
|
.toLowerCase()
|
|
.split(/[\s,,、_\-]+/)
|
|
.filter((t) => t.length > 0);
|
|
}
|
|
|
|
/**
|
|
* 计算工具与查询的匹配分数
|
|
*/
|
|
function calculateScore(queryTerms: string[], tool: ToolMetadata): number {
|
|
let score = 0;
|
|
|
|
const nameLower = tool.name.toLowerCase();
|
|
const descLower = tool.description.toLowerCase();
|
|
const keywordsLower = tool.keywords.map((k) => k.toLowerCase());
|
|
|
|
for (const term of queryTerms) {
|
|
// 名称精确匹配 (最高分)
|
|
if (nameLower === term) {
|
|
score += 10;
|
|
}
|
|
// 名称包含匹配
|
|
else if (nameLower.includes(term)) {
|
|
score += 5;
|
|
}
|
|
|
|
// 关键词精确匹配
|
|
if (keywordsLower.includes(term)) {
|
|
score += 8;
|
|
}
|
|
// 关键词包含匹配
|
|
else if (keywordsLower.some((k) => k.includes(term) || term.includes(k))) {
|
|
score += 3;
|
|
}
|
|
|
|
// 描述包含匹配
|
|
if (descLower.includes(term)) {
|
|
score += 2;
|
|
}
|
|
}
|
|
|
|
return score;
|
|
}
|
|
|
|
/**
|
|
* 搜索工具
|
|
* @param query 搜索查询
|
|
* @param allTools 所有工具的元数据
|
|
* @param limit 返回结果数量限制
|
|
* @returns 匹配的工具列表(按分数排序)
|
|
*/
|
|
export function searchTools(
|
|
query: string,
|
|
allTools: ToolMetadata[],
|
|
limit: number = 5
|
|
): ToolSearchResult[] {
|
|
const queryTerms = tokenize(query);
|
|
|
|
if (queryTerms.length === 0) {
|
|
return [];
|
|
}
|
|
|
|
const results = allTools
|
|
// 只搜索延迟加载的工具
|
|
.filter((tool) => tool.deferLoading)
|
|
.map((tool) => ({
|
|
name: tool.name,
|
|
description: tool.description,
|
|
category: tool.category,
|
|
score: calculateScore(queryTerms, tool),
|
|
}))
|
|
.filter((r) => r.score > 0)
|
|
.sort((a, b) => b.score - a.score)
|
|
.slice(0, limit);
|
|
|
|
return results;
|
|
}
|