gadget/docs/archive/tools/skills/create-skill.ts

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();