gadget/docs/archive/tools/skills/search-skills.ts

109 lines
2.9 KiB
TypeScript

// src/tools/skills/search-skills.ts
// Copyright (C) 2025 DTP Technologies, LLC
// All Rights Reserved
import type { ToolDefinition } from "../../lib/ai-client.js";
import {
DtpTool,
type ToolArguments,
type ToolContext,
} from "../../lib/tool.js";
import { AiSkill } from "../../models/ai-skill.js";
import { ChatSessionMode } from "../../models/chat-session.js";
export class SearchSkillsTool extends DtpTool {
get name(): string {
return "SearchSkillsTool";
}
get slug(): string {
return "search-skills";
}
get metadata() {
return {
name: this.definition.function.name || "search_skills",
category: "skills",
tags: ["skill", "search", "find", "query"],
modes: [
ChatSessionMode.Plan,
ChatSessionMode.Build,
ChatSessionMode.Test,
ChatSessionMode.Ship,
ChatSessionMode.Develop,
],
};
}
public definition: ToolDefinition = {
type: "function",
function: {
name: "search_skills",
description:
"Search for skills using text search. Matches against skill names, descriptions, and tags. Returns a list of matching skills with their basic info. Use this to find relevant skills when you need guidance on a specific task, then fetch the skill(s) you need by ID to read their full content.",
parameters: {
type: "object",
properties: {
query: {
type: "string",
description:
"The search query. Use keywords that match skill names, descriptions, or tags.",
},
},
required: ["query"],
},
},
};
public async execute(
_context: ToolContext,
args: ToolArguments,
): Promise<string> {
const query = args.query as string | undefined;
if (!query || query.trim().length === 0) {
return this.error("INVALID_PARAMETER", "query is required.", {
parameter: "query",
});
}
try {
const skills = await AiSkill.find(
{ $text: { $search: query } },
{ score: { $meta: "textScore" } },
)
.sort({ score: { $meta: "textScore" } })
.limit(10)
.lean();
if (skills.length === 0) {
return this.success(
{ skills: [], total: 0 },
`No skills found matching "${query}".`,
);
}
const results = skills.map((s) => ({
skillId: s._id.toString(),
name: s.name,
description: s.description,
tags: s.tags,
modes: s.modes,
isGlobal: s.user === null,
}));
return this.success(
{ results, total: results.length },
`Found ${results.length} skill(s).`,
);
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : String(error);
return this.error(
"OPERATION_FAILED",
`Failed to search skills: ${errorMessage}`,
);
}
}
}
export default new SearchSkillsTool();