@lousy-agents/cli 1.0.6 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,16 @@
1
+ /**
2
+ * The `skill` subcommand for creating Agent Skills
3
+ */
4
+ export declare const skillCommand: import("citty").CommandDef<{
5
+ name: {
6
+ type: "positional";
7
+ description: string;
8
+ required: boolean;
9
+ };
10
+ }>;
1
11
  /**
2
12
  * The `new` command for scaffolding new resources.
3
- * Currently supports creating Copilot custom agents.
13
+ * Supports creating Copilot custom agents and Agent Skills.
4
14
  */
5
15
  export declare const newCommand: import("citty").CommandDef<{
6
16
  "copilot-agent": {
@@ -1 +1 @@
1
- {"version":3,"file":"new.d.ts","sourceRoot":"","sources":["../../src/commands/new.ts"],"names":[],"mappings":"AAgBA;;;GAGG;AACH,eAAO,MAAM,UAAU;;;;;EAkCrB,CAAC"}
1
+ {"version":3,"file":"new.d.ts","sourceRoot":"","sources":["../../src/commands/new.ts"],"names":[],"mappings":"AA6BA;;GAEG;AACH,eAAO,MAAM,YAAY;;;;;;EAmCvB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,UAAU;;;;;EAmDrB,CAAC"}
@@ -1,31 +1,84 @@
1
1
  import { defineCommand } from "citty";
2
2
  import { consola } from "consola";
3
3
  import { createAgentFileGateway } from "../gateways/agent-file-gateway.js";
4
+ import { createSkillFileGateway } from "../gateways/skill-file-gateway.js";
4
5
  import { CreateCopilotAgentUseCase } from "../use-cases/create-copilot-agent.js";
5
- const newArgs = {
6
+ import { CreateSkillUseCase } from "../use-cases/create-skill.js";
7
+ const copilotAgentArgs = {
6
8
  "copilot-agent": {
7
9
  type: "string",
8
10
  description: "Create a new GitHub Copilot custom agent with the specified name. Example: lousy-agents new --copilot-agent security",
9
11
  },
10
12
  };
13
+ const skillArgs = {
14
+ name: {
15
+ type: "positional",
16
+ description: "The name of the skill to create. Example: lousy-agents new skill github-actions-debug",
17
+ required: true,
18
+ },
19
+ };
20
+ /**
21
+ * The `skill` subcommand for creating Agent Skills
22
+ */
23
+ export const skillCommand = defineCommand({
24
+ meta: {
25
+ name: "skill",
26
+ description: "Create a new GitHub Copilot Agent Skill. Example: lousy-agents new skill github-actions-debug",
27
+ },
28
+ args: skillArgs,
29
+ run: async (context) => {
30
+ // Support dependency injection for testing via context.data
31
+ const targetDir = typeof context.data?.targetDir === "string"
32
+ ? context.data.targetDir
33
+ : process.cwd();
34
+ const skillName = context.args.name;
35
+ if (!skillName) {
36
+ throw new Error("Missing required argument: <name>. Example: lousy-agents new skill github-actions-debug");
37
+ }
38
+ // Create the use case with the file system gateway
39
+ const gateway = createSkillFileGateway();
40
+ const useCase = new CreateSkillUseCase(gateway);
41
+ // Execute the use case
42
+ const result = await useCase.execute(targetDir, skillName);
43
+ if (!result.success) {
44
+ throw new Error(result.error);
45
+ }
46
+ consola.success(`Created Agent Skill: ${result.skillFilePath}`);
47
+ },
48
+ });
11
49
  /**
12
50
  * The `new` command for scaffolding new resources.
13
- * Currently supports creating Copilot custom agents.
51
+ * Supports creating Copilot custom agents and Agent Skills.
14
52
  */
15
53
  export const newCommand = defineCommand({
16
54
  meta: {
17
55
  name: "new",
18
- description: "Create new resources (e.g., Copilot agents)",
56
+ description: "Create new resources (e.g., Copilot agents, skills). Use 'new skill <name>' to create an Agent Skill.",
57
+ },
58
+ args: copilotAgentArgs,
59
+ subCommands: {
60
+ skill: skillCommand,
19
61
  },
20
- args: newArgs,
21
62
  run: async (context) => {
63
+ // citty runs both the subcommand's run function and the parent's run function.
64
+ // We need to detect when a subcommand was invoked and exit early to avoid
65
+ // throwing an error for missing --copilot-agent option.
66
+ const subCommand = context.rawArgs[0];
67
+ if (subCommand === "skill") {
68
+ return; // Subcommand was handled by skillCommand.run
69
+ }
22
70
  // Support dependency injection for testing via context.data
23
71
  const targetDir = typeof context.data?.targetDir === "string"
24
72
  ? context.data.targetDir
25
73
  : process.cwd();
26
74
  const copilotAgentName = context.args["copilot-agent"];
27
75
  if (!copilotAgentName) {
28
- throw new Error("Missing required option: --copilot-agent <name>. Example: lousy-agents new --copilot-agent security");
76
+ throw new Error("Missing required option. Use one of:\n" +
77
+ " --copilot-agent <name> Create a Copilot custom agent\n" +
78
+ " skill <name> Create an Agent Skill\n\n" +
79
+ "Examples:\n" +
80
+ " lousy-agents new --copilot-agent security\n" +
81
+ " lousy-agents new skill github-actions-debug");
29
82
  }
30
83
  // Create the use case with the file system gateway
31
84
  const gateway = createAgentFileGateway();
@@ -1 +1 @@
1
- {"version":3,"file":"new.js","sourceRoot":"","sources":["../../src/commands/new.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAEjF,MAAM,OAAO,GAAG;IACZ,eAAe,EAAE;QACb,IAAI,EAAE,QAAiB;QACvB,WAAW,EACP,sHAAsH;KAC7H;CACJ,CAAC;AAIF;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAC;IACpC,IAAI,EAAE;QACF,IAAI,EAAE,KAAK;QACX,WAAW,EAAE,6CAA6C;KAC7D;IACD,IAAI,EAAE,OAAO;IACb,GAAG,EAAE,KAAK,EAAE,OAAgC,EAAE,EAAE;QAC5C,4DAA4D;QAC5D,MAAM,SAAS,GACX,OAAO,OAAO,CAAC,IAAI,EAAE,SAAS,KAAK,QAAQ;YACvC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS;YACxB,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QAExB,MAAM,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAEvD,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CACX,qGAAqG,CACxG,CAAC;QACN,CAAC;QAED,mDAAmD;QACnD,MAAM,OAAO,GAAG,sBAAsB,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,IAAI,yBAAyB,CAAC,OAAO,CAAC,CAAC;QAEvD,uBAAuB;QACvB,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;QAElE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAClC,CAAC;QAED,OAAO,CAAC,OAAO,CAAC,0BAA0B,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IACjE,CAAC;CACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"new.js","sourceRoot":"","sources":["../../src/commands/new.ts"],"names":[],"mappings":"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"}
@@ -3,4 +3,5 @@
3
3
  */
4
4
  export * from "./copilot-agent.js";
5
5
  export * from "./copilot-setup.js";
6
+ export * from "./skill.js";
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/entities/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/entities/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC"}
@@ -3,4 +3,5 @@
3
3
  */
4
4
  export * from "./copilot-agent.js";
5
5
  export * from "./copilot-setup.js";
6
+ export * from "./skill.js";
6
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/entities/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/entities/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Core domain entity for GitHub Copilot Agent Skills.
3
+ * Handles name normalization and SKILL.md content generation.
4
+ */
5
+ /**
6
+ * Normalizes a skill name to lowercase with hyphens.
7
+ * Handles spaces, mixed case, multiple spaces, and leading/trailing spaces.
8
+ */
9
+ export declare function normalizeSkillName(name: string): string;
10
+ /**
11
+ * Generates the SKILL.md content for a Copilot Agent Skill.
12
+ * Includes YAML frontmatter, documentation link, and example structure.
13
+ */
14
+ export declare function generateSkillContent(skillName: string): string;
15
+ //# sourceMappingURL=skill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/entities/skill.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CA+C9D"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Core domain entity for GitHub Copilot Agent Skills.
3
+ * Handles name normalization and SKILL.md content generation.
4
+ */
5
+ /**
6
+ * Normalizes a skill name to lowercase with hyphens.
7
+ * Handles spaces, mixed case, multiple spaces, and leading/trailing spaces.
8
+ */
9
+ export function normalizeSkillName(name) {
10
+ return name.trim().toLowerCase().replace(/\s+/g, "-");
11
+ }
12
+ /**
13
+ * Generates the SKILL.md content for a Copilot Agent Skill.
14
+ * Includes YAML frontmatter, documentation link, and example structure.
15
+ */
16
+ export function generateSkillContent(skillName) {
17
+ const normalizedName = normalizeSkillName(skillName);
18
+ return `---
19
+ name: ${normalizedName}
20
+ description: Brief description of what this skill does and when Copilot should use it
21
+ ---
22
+
23
+ <!--
24
+ This is a GitHub Copilot Agent Skill for repository-level use.
25
+ Learn more: https://docs.github.com/en/copilot/concepts/agents/about-agent-skills
26
+ -->
27
+
28
+ # ${normalizedName}
29
+
30
+ {Brief description of what this skill teaches Copilot to do}
31
+
32
+ ## When to Use This Skill
33
+
34
+ Copilot should use this skill when:
35
+
36
+ - {Trigger condition 1}
37
+ - {Trigger condition 2}
38
+ - {Trigger condition 3}
39
+
40
+ ## Instructions
41
+
42
+ {Detailed step-by-step instructions for Copilot to follow}
43
+
44
+ 1. {Step 1}
45
+ 2. {Step 2}
46
+ 3. {Step 3}
47
+
48
+ ## Guidelines
49
+
50
+ - {Guideline or best practice}
51
+ - {Guideline or best practice}
52
+ - {Guideline or best practice}
53
+
54
+ ## Examples
55
+
56
+ {Examples of inputs and expected outputs or behaviors}
57
+
58
+ ### Example 1: {Title}
59
+
60
+ {Description of the example scenario and expected behavior}
61
+ `;
62
+ }
63
+ //# sourceMappingURL=skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/entities/skill.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC3C,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAAiB;IAClD,MAAM,cAAc,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAErD,OAAO;QACH,cAAc;;;;;;;;;IASlB,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCjB,CAAC;AACF,CAAC"}
@@ -5,5 +5,6 @@ export * from "./action-version-gateway.js";
5
5
  export * from "./agent-file-gateway.js";
6
6
  export * from "./environment-gateway.js";
7
7
  export * from "./file-system-utils.js";
8
+ export * from "./skill-file-gateway.js";
8
9
  export * from "./workflow-gateway.js";
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/gateways/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/gateways/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC"}
@@ -5,5 +5,6 @@ export * from "./action-version-gateway.js";
5
5
  export * from "./agent-file-gateway.js";
6
6
  export * from "./environment-gateway.js";
7
7
  export * from "./file-system-utils.js";
8
+ export * from "./skill-file-gateway.js";
8
9
  export * from "./workflow-gateway.js";
9
10
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/gateways/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/gateways/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Gateway for skill file system operations.
3
+ * This module abstracts file system access for Copilot Agent Skill files.
4
+ */
5
+ /**
6
+ * Interface for skill file gateway
7
+ * Allows for different implementations (file system, mock, etc.)
8
+ */
9
+ export interface SkillFileGateway {
10
+ /**
11
+ * Checks if a skill directory already exists
12
+ * @param targetDir The root directory of the repository
13
+ * @param skillName The normalized name of the skill
14
+ * @returns true if the skill directory exists
15
+ */
16
+ skillDirectoryExists(targetDir: string, skillName: string): Promise<boolean>;
17
+ /**
18
+ * Ensures the .github/skills/<name> directory exists
19
+ * @param targetDir The root directory of the repository
20
+ * @param skillName The normalized name of the skill
21
+ */
22
+ ensureSkillDirectory(targetDir: string, skillName: string): Promise<void>;
23
+ /**
24
+ * Writes content to a SKILL.md file
25
+ * @param targetDir The root directory of the repository
26
+ * @param skillName The normalized name of the skill
27
+ * @param content The content to write to the file
28
+ */
29
+ writeSkillFile(targetDir: string, skillName: string, content: string): Promise<void>;
30
+ /**
31
+ * Returns the full path to a skill directory
32
+ * @param targetDir The root directory of the repository
33
+ * @param skillName The normalized name of the skill
34
+ * @returns The full path to the skill directory
35
+ */
36
+ getSkillDirectoryPath(targetDir: string, skillName: string): string;
37
+ /**
38
+ * Returns the full path to a SKILL.md file
39
+ * @param targetDir The root directory of the repository
40
+ * @param skillName The normalized name of the skill
41
+ * @returns The full path to the SKILL.md file
42
+ */
43
+ getSkillFilePath(targetDir: string, skillName: string): string;
44
+ }
45
+ /**
46
+ * File system implementation of the skill file gateway
47
+ */
48
+ export declare class FileSystemSkillFileGateway implements SkillFileGateway {
49
+ getSkillDirectoryPath(targetDir: string, skillName: string): string;
50
+ getSkillFilePath(targetDir: string, skillName: string): string;
51
+ skillDirectoryExists(targetDir: string, skillName: string): Promise<boolean>;
52
+ ensureSkillDirectory(targetDir: string, skillName: string): Promise<void>;
53
+ writeSkillFile(targetDir: string, skillName: string, content: string): Promise<void>;
54
+ }
55
+ /**
56
+ * Creates and returns the default skill file gateway
57
+ */
58
+ export declare function createSkillFileGateway(): SkillFileGateway;
59
+ //# sourceMappingURL=skill-file-gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-file-gateway.d.ts","sourceRoot":"","sources":["../../src/gateways/skill-file-gateway.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC7B;;;;;OAKG;IACH,oBAAoB,CAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB;;;;OAIG;IACH,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1E;;;;;OAKG;IACH,cAAc,CACV,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;;;;OAKG;IACH,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAEpE;;;;;OAKG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;CAClE;AAED;;GAEG;AACH,qBAAa,0BAA2B,YAAW,gBAAgB;IAC/D,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;IAInE,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;IAOxD,oBAAoB,CACtB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,OAAO,CAAC;IAKb,oBAAoB,CACtB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC;IAKV,cAAc,CAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC;CAInB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,gBAAgB,CAEzD"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Gateway for skill file system operations.
3
+ * This module abstracts file system access for Copilot Agent Skill files.
4
+ */
5
+ import { mkdir, writeFile } from "node:fs/promises";
6
+ import { join } from "node:path";
7
+ import { fileExists } from "./file-system-utils.js";
8
+ /**
9
+ * File system implementation of the skill file gateway
10
+ */
11
+ export class FileSystemSkillFileGateway {
12
+ getSkillDirectoryPath(targetDir, skillName) {
13
+ return join(targetDir, ".github", "skills", skillName);
14
+ }
15
+ getSkillFilePath(targetDir, skillName) {
16
+ return join(this.getSkillDirectoryPath(targetDir, skillName), "SKILL.md");
17
+ }
18
+ async skillDirectoryExists(targetDir, skillName) {
19
+ const dirPath = this.getSkillDirectoryPath(targetDir, skillName);
20
+ return fileExists(dirPath);
21
+ }
22
+ async ensureSkillDirectory(targetDir, skillName) {
23
+ const skillDir = this.getSkillDirectoryPath(targetDir, skillName);
24
+ await mkdir(skillDir, { recursive: true });
25
+ }
26
+ async writeSkillFile(targetDir, skillName, content) {
27
+ const filePath = this.getSkillFilePath(targetDir, skillName);
28
+ await writeFile(filePath, content, { encoding: "utf-8" });
29
+ }
30
+ }
31
+ /**
32
+ * Creates and returns the default skill file gateway
33
+ */
34
+ export function createSkillFileGateway() {
35
+ return new FileSystemSkillFileGateway();
36
+ }
37
+ //# sourceMappingURL=skill-file-gateway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-file-gateway.js","sourceRoot":"","sources":["../../src/gateways/skill-file-gateway.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAsDpD;;GAEG;AACH,MAAM,OAAO,0BAA0B;IACnC,qBAAqB,CAAC,SAAiB,EAAE,SAAiB;QACtD,OAAO,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC3D,CAAC;IAED,gBAAgB,CAAC,SAAiB,EAAE,SAAiB;QACjD,OAAO,IAAI,CACP,IAAI,CAAC,qBAAqB,CAAC,SAAS,EAAE,SAAS,CAAC,EAChD,UAAU,CACb,CAAC;IACN,CAAC;IAED,KAAK,CAAC,oBAAoB,CACtB,SAAiB,EACjB,SAAiB;QAEjB,MAAM,OAAO,GAAG,IAAI,CAAC,qBAAqB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACjE,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,oBAAoB,CACtB,SAAiB,EACjB,SAAiB;QAEjB,MAAM,QAAQ,GAAG,IAAI,CAAC,qBAAqB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAClE,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,cAAc,CAChB,SAAiB,EACjB,SAAiB,EACjB,OAAe;QAEf,MAAM,QAAQ,GAAG,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAC7D,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9D,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,UAAU,sBAAsB;IAClC,OAAO,IAAI,0BAA0B,EAAE,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Use case for creating GitHub Copilot Agent Skills.
3
+ * Orchestrates entity logic with gateway operations.
4
+ */
5
+ import type { SkillFileGateway } from "../gateways/skill-file-gateway.js";
6
+ /**
7
+ * Result of the create skill operation
8
+ */
9
+ export interface CreateSkillResult {
10
+ success: boolean;
11
+ normalizedName?: string;
12
+ skillDirectoryPath?: string;
13
+ skillFilePath?: string;
14
+ error?: string;
15
+ }
16
+ /**
17
+ * Use case for creating a new Agent Skill
18
+ */
19
+ export declare class CreateSkillUseCase {
20
+ private readonly gateway;
21
+ constructor(gateway: SkillFileGateway);
22
+ /**
23
+ * Executes the create skill operation
24
+ * @param targetDir The root directory of the repository
25
+ * @param skillName The name of the skill to create
26
+ * @returns Result of the operation
27
+ */
28
+ execute(targetDir: string, skillName: string): Promise<CreateSkillResult>;
29
+ }
30
+ //# sourceMappingURL=create-skill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-skill.d.ts","sourceRoot":"","sources":["../../src/use-cases/create-skill.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAe1E;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,kBAAkB;IACf,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,gBAAgB;IAEtD;;;;;OAKG;IACG,OAAO,CACT,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAClB,OAAO,CAAC,iBAAiB,CAAC;CA6DhC"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Use case for creating GitHub Copilot Agent Skills.
3
+ * Orchestrates entity logic with gateway operations.
4
+ */
5
+ import { z } from "zod";
6
+ import { generateSkillContent, normalizeSkillName } from "../entities/skill.js";
7
+ /**
8
+ * Schema for validating skill name input
9
+ * Validates that the input is a non-empty string with reasonable constraints
10
+ */
11
+ const SkillNameSchema = z
12
+ .string()
13
+ .min(1, "Skill name is required")
14
+ .max(100, "Skill name must be 100 characters or less")
15
+ .regex(/^[a-zA-Z0-9\s_-]+$/, "Skill name can only contain letters, numbers, spaces, hyphens, and underscores");
16
+ /**
17
+ * Use case for creating a new Agent Skill
18
+ */
19
+ export class CreateSkillUseCase {
20
+ gateway;
21
+ constructor(gateway) {
22
+ this.gateway = gateway;
23
+ }
24
+ /**
25
+ * Executes the create skill operation
26
+ * @param targetDir The root directory of the repository
27
+ * @param skillName The name of the skill to create
28
+ * @returns Result of the operation
29
+ */
30
+ async execute(targetDir, skillName) {
31
+ // Validate the skill name using Zod schema
32
+ const validationResult = SkillNameSchema.safeParse(skillName);
33
+ if (!validationResult.success) {
34
+ const errorMessage = validationResult.error.issues[0]?.message ??
35
+ "Invalid skill name";
36
+ return {
37
+ success: false,
38
+ error: errorMessage,
39
+ };
40
+ }
41
+ // Normalize the skill name
42
+ const normalizedName = normalizeSkillName(validationResult.data);
43
+ // Validate that the normalized name is not empty (handles whitespace-only input)
44
+ if (!normalizedName) {
45
+ return {
46
+ success: false,
47
+ error: "Skill name is required",
48
+ };
49
+ }
50
+ // Get the paths
51
+ const skillDirectoryPath = this.gateway.getSkillDirectoryPath(targetDir, normalizedName);
52
+ const skillFilePath = this.gateway.getSkillFilePath(targetDir, normalizedName);
53
+ // Check if the skill directory already exists
54
+ if (await this.gateway.skillDirectoryExists(targetDir, normalizedName)) {
55
+ return {
56
+ success: false,
57
+ error: `Skill already exists: ${skillDirectoryPath}`,
58
+ skillDirectoryPath,
59
+ };
60
+ }
61
+ // Ensure the skill directory exists
62
+ await this.gateway.ensureSkillDirectory(targetDir, normalizedName);
63
+ // Generate the content
64
+ const content = generateSkillContent(normalizedName);
65
+ // Write the SKILL.md file
66
+ await this.gateway.writeSkillFile(targetDir, normalizedName, content);
67
+ return {
68
+ success: true,
69
+ normalizedName,
70
+ skillDirectoryPath,
71
+ skillFilePath,
72
+ };
73
+ }
74
+ }
75
+ //# sourceMappingURL=create-skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-skill.js","sourceRoot":"","sources":["../../src/use-cases/create-skill.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAGhF;;;GAGG;AACH,MAAM,eAAe,GAAG,CAAC;KACpB,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,EAAE,wBAAwB,CAAC;KAChC,GAAG,CAAC,GAAG,EAAE,2CAA2C,CAAC;KACrD,KAAK,CACF,oBAAoB,EACpB,gFAAgF,CACnF,CAAC;AAaN;;GAEG;AACH,MAAM,OAAO,kBAAkB;IACE;IAA7B,YAA6B,OAAyB;QAAzB,YAAO,GAAP,OAAO,CAAkB;IAAG,CAAC;IAE1D;;;;;OAKG;IACH,KAAK,CAAC,OAAO,CACT,SAAiB,EACjB,SAAiB;QAEjB,2CAA2C;QAC3C,MAAM,gBAAgB,GAAG,eAAe,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAC9D,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC;YAC5B,MAAM,YAAY,GACd,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO;gBACzC,oBAAoB,CAAC;YACzB,OAAO;gBACH,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,YAAY;aACtB,CAAC;QACN,CAAC;QAED,2BAA2B;QAC3B,MAAM,cAAc,GAAG,kBAAkB,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAEjE,iFAAiF;QACjF,IAAI,CAAC,cAAc,EAAE,CAAC;YAClB,OAAO;gBACH,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,wBAAwB;aAClC,CAAC;QACN,CAAC;QAED,gBAAgB;QAChB,MAAM,kBAAkB,GAAG,IAAI,CAAC,OAAO,CAAC,qBAAqB,CACzD,SAAS,EACT,cAAc,CACjB,CAAC;QACF,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAC/C,SAAS,EACT,cAAc,CACjB,CAAC;QAEF,8CAA8C;QAC9C,IACI,MAAM,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,SAAS,EAAE,cAAc,CAAC,EACpE,CAAC;YACC,OAAO;gBACH,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,yBAAyB,kBAAkB,EAAE;gBACpD,kBAAkB;aACrB,CAAC;QACN,CAAC;QAED,oCAAoC;QACpC,MAAM,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;QAEnE,uBAAuB;QACvB,MAAM,OAAO,GAAG,oBAAoB,CAAC,cAAc,CAAC,CAAC;QAErD,0BAA0B;QAC1B,MAAM,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QAEtE,OAAO;YACH,OAAO,EAAE,IAAI;YACb,cAAc;YACd,kBAAkB;YAClB,aAAa;SAChB,CAAC;IACN,CAAC;CACJ"}
@@ -5,5 +5,6 @@ export * from "./action-resolution.js";
5
5
  export * from "./candidate-builder.js";
6
6
  export * from "./copilot-setup.js";
7
7
  export * from "./create-copilot-agent.js";
8
+ export * from "./create-skill.js";
8
9
  export * from "./workflow-generator.js";
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/use-cases/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/use-cases/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC"}
@@ -5,5 +5,6 @@ export * from "./action-resolution.js";
5
5
  export * from "./candidate-builder.js";
6
6
  export * from "./copilot-setup.js";
7
7
  export * from "./create-copilot-agent.js";
8
+ export * from "./create-skill.js";
8
9
  export * from "./workflow-generator.js";
9
10
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/use-cases/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/use-cases/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lousy-agents/cli",
3
- "version": "1.0.6",
3
+ "version": "1.1.0",
4
4
  "description": "CLI scaffolding tool that sets up projects with structure, instructions, and feedback loops for AI coding assistants",
5
5
  "type": "module",
6
6
  "repository": {