159 lines
4.5 KiB
TypeScript
159 lines
4.5 KiB
TypeScript
// src/tools/skills/create-skill.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";
|
|
import type { IUser } from "../../models/user.js";
|
|
|
|
export class CreateSkillTool extends DtpTool {
|
|
get name(): string {
|
|
return "CreateSkillTool";
|
|
}
|
|
get slug(): string {
|
|
return "create-skill";
|
|
}
|
|
get metadata() {
|
|
return {
|
|
name: this.definition.function.name || "create_skill",
|
|
category: "skills",
|
|
tags: ["skill", "create", "new", "add"],
|
|
modes: [
|
|
ChatSessionMode.Plan,
|
|
ChatSessionMode.Build,
|
|
ChatSessionMode.Test,
|
|
ChatSessionMode.Ship,
|
|
ChatSessionMode.Develop,
|
|
],
|
|
};
|
|
}
|
|
|
|
public definition: ToolDefinition = {
|
|
type: "function",
|
|
function: {
|
|
name: "create_skill",
|
|
description:
|
|
"Create a new skill. Skills are recipes or instruction manuals the agent can follow. Provide a clear name, description, tags for searchability, and the content with detailed instructions.",
|
|
parameters: {
|
|
type: "object",
|
|
properties: {
|
|
name: {
|
|
type: "string",
|
|
description:
|
|
"The name of the skill (e.g., 'Write React Component').",
|
|
},
|
|
description: {
|
|
type: "string",
|
|
description:
|
|
"A brief description of what this skill does and when to use it.",
|
|
},
|
|
tags: {
|
|
type: "string",
|
|
description:
|
|
"Comma-separated list of tags for searchability (e.g., 'react, frontend, component').",
|
|
},
|
|
modes: {
|
|
type: "array",
|
|
items: {
|
|
type: "string",
|
|
enum: ["build", "plan", "test", "ship", "dev"],
|
|
},
|
|
description:
|
|
"Array of modes where this skill can be used. Defaults to ['build'] if not specified.",
|
|
},
|
|
content: {
|
|
type: "string",
|
|
description:
|
|
"The full content/instructions of the skill. This is what the agent will read when using this skill.",
|
|
},
|
|
},
|
|
required: ["name", "description", "content"],
|
|
},
|
|
},
|
|
};
|
|
|
|
public async execute(
|
|
context: ToolContext,
|
|
args: ToolArguments,
|
|
): Promise<string> {
|
|
const name = args.name as string | undefined;
|
|
const description = args.description as string | undefined;
|
|
const tagsStr = args.tags as string | undefined;
|
|
const modesArg = args.modes as string[] | undefined;
|
|
const content = args.content as string | undefined;
|
|
|
|
if (!name || !description || !content) {
|
|
return this.error(
|
|
"INVALID_PARAMETER",
|
|
"name, description, and content are required.",
|
|
{ parameter: "name, description, content" },
|
|
);
|
|
}
|
|
|
|
const tags = tagsStr
|
|
? tagsStr
|
|
.split(",")
|
|
.map((t) => t.trim())
|
|
.filter((t) => t.length > 0)
|
|
: [];
|
|
|
|
let modes: ChatSessionMode[] = [ChatSessionMode.Build];
|
|
if (modesArg && Array.isArray(modesArg)) {
|
|
modes = modesArg
|
|
.map((m) => m.toLowerCase())
|
|
.filter((m) => ["build", "plan", "test", "ship", "dev"].includes(m))
|
|
.map((m) => {
|
|
switch (m) {
|
|
case "build":
|
|
return ChatSessionMode.Build;
|
|
case "plan":
|
|
return ChatSessionMode.Plan;
|
|
case "test":
|
|
return ChatSessionMode.Test;
|
|
case "ship":
|
|
return ChatSessionMode.Ship;
|
|
case "dev":
|
|
return ChatSessionMode.Develop;
|
|
default:
|
|
return ChatSessionMode.Build;
|
|
}
|
|
});
|
|
if (modes.length === 0) modes = [ChatSessionMode.Build];
|
|
}
|
|
|
|
try {
|
|
const user = context.session.user as IUser;
|
|
const skill = new AiSkill({
|
|
user: user._id,
|
|
name,
|
|
description,
|
|
tags,
|
|
modes,
|
|
content,
|
|
});
|
|
|
|
await skill.save();
|
|
return this.success(
|
|
{ skillId: skill._id?.toString(), name },
|
|
`Skill created: ${name}`,
|
|
);
|
|
} catch (error) {
|
|
const errorMessage =
|
|
error instanceof Error ? error.message : String(error);
|
|
return this.error(
|
|
"OPERATION_FAILED",
|
|
`Failed to create skill: ${errorMessage}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
export default new CreateSkillTool();
|