@clubmatto/ai-kit 0.0.1 → 0.0.4

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.
Files changed (44) hide show
  1. package/.nvmrc +1 -0
  2. package/CHANGELOG.md +10 -2
  3. package/LICENSE +17 -0
  4. package/README.md +7 -7
  5. package/dist/src/index.js +0 -0
  6. package/dist/src/template.js +1 -1
  7. package/package.json +5 -23
  8. package/src/agents/monorepo.md +2 -8
  9. package/src/agents/opencode.json +0 -9
  10. package/src/commands/commit.md +6 -5
  11. package/src/gradient-string.d.ts +1 -0
  12. package/src/template.ts +1 -1
  13. package/dist/scripts/fetch-playwright-skills.js +0 -63
  14. package/dist/src/commands/sync.js +0 -111
  15. package/dist/src/content.js +0 -99
  16. package/dist/tests/content.test.js +0 -141
  17. package/dist/tests/integration/cli.test.js +0 -43
  18. package/dist/tests/output.js +0 -36
  19. package/dist/tests/reader.test.js +0 -141
  20. package/dist/tests/sync.test.js +0 -90
  21. package/dist/tests/utils.js +0 -20
  22. package/dist/vitest.config.js +0 -9
  23. package/docs/roadmap.md +0 -16
  24. package/scripts/fetch-playwright-skills.ts +0 -79
  25. package/src/skills/image-gen/scripts/generate.js +0 -166
  26. package/tests/fixtures/agents/another.json +0 -4
  27. package/tests/fixtures/agents/monorepo.md +0 -5
  28. package/tests/fixtures/agents/opencode.json +0 -4
  29. package/tests/fixtures/commands/another.md +0 -5
  30. package/tests/fixtures/commands/commit.md +0 -7
  31. package/tests/fixtures/commands/test.md +0 -13
  32. package/tests/fixtures/rules/nested/nested-rule.md +0 -3
  33. package/tests/fixtures/rules/test-rule.md +0 -5
  34. package/tests/fixtures/rules/typescript.md +0 -5
  35. package/tests/fixtures/skills/test-skill/SKILL.md +0 -7
  36. package/tests/fixtures/skills/test-skill/nested-refs/doc.md +0 -3
  37. package/tests/fixtures/skills/test-skill/skill-details.md +0 -7
  38. package/tests/integration/cli.test.ts +0 -55
  39. package/tests/output.ts +0 -37
  40. package/tests/reader.test.ts +0 -193
  41. package/tests/sync.test.ts +0 -136
  42. package/tests/utils.ts +0 -17
  43. package/tsconfig.json +0 -23
  44. package/vitest.config.ts +0 -8
@@ -1,43 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const vitest_1 = require("vitest");
4
- const child_process_1 = require("child_process");
5
- const path_1 = require("path");
6
- const utils_1 = require("../utils");
7
- const projectRoot = (0, path_1.join)(__dirname, "..", "..");
8
- (0, vitest_1.describe)("CLI integration", () => {
9
- let tempDir;
10
- (0, vitest_1.beforeEach)(() => {
11
- tempDir = (0, utils_1.createTempDir)();
12
- });
13
- (0, vitest_1.it)("runs as CLI and syncs files", () => {
14
- (0, child_process_1.execSync)(`node ${(0, path_1.join)(projectRoot, "dist", "src", "index.js")} sync`, {
15
- cwd: tempDir,
16
- });
17
- (0, vitest_1.expect)((0, utils_1.fileExists)(tempDir, ".agents/.ai-kit")).toBe(true);
18
- (0, vitest_1.expect)((0, utils_1.fileExists)(tempDir, ".agents/rules")).toBe(true);
19
- (0, vitest_1.expect)((0, utils_1.fileExists)(tempDir, "opencode.json")).toBe(true);
20
- (0, vitest_1.expect)((0, utils_1.fileExists)(tempDir, "AGENTS.md")).toBe(true);
21
- });
22
- (0, vitest_1.it)("creates rules with templated content", () => {
23
- (0, child_process_1.execSync)(`node ${(0, path_1.join)(projectRoot, "dist", "src", "index.js")} sync`, {
24
- cwd: tempDir,
25
- });
26
- const ruleContent = (0, utils_1.readFile)(tempDir, ".agents/rules/typescript.md");
27
- (0, vitest_1.expect)(ruleContent).toContain("Last updated:");
28
- (0, vitest_1.expect)(ruleContent).not.toContain("{{FOOTER}}");
29
- (0, vitest_1.expect)(ruleContent).toMatch(/\d{4}-\d{2}-\d{2}/);
30
- });
31
- (0, vitest_1.it)("injects commands into opencode.json", () => {
32
- (0, child_process_1.execSync)(`node ${(0, path_1.join)(projectRoot, "dist", "src", "index.js")} sync`, {
33
- cwd: tempDir,
34
- });
35
- const opencodeJson = JSON.parse((0, utils_1.readFile)(tempDir, "opencode.json"));
36
- (0, vitest_1.expect)(opencodeJson).toHaveProperty("command");
37
- });
38
- (0, vitest_1.it)("skips opencode.json when --skip-opencode is passed", () => {
39
- (0, child_process_1.execSync)(`node ${(0, path_1.join)(projectRoot, "dist", "src", "index.js")} sync --skip-opencode`, { cwd: tempDir });
40
- (0, vitest_1.expect)((0, utils_1.fileExists)(tempDir, "opencode.json")).toBe(false);
41
- (0, vitest_1.expect)((0, utils_1.fileExists)(tempDir, "AGENTS.md")).toBe(true);
42
- });
43
- });
@@ -1,36 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.testLog = void 0;
4
- exports.getLastLog = getLastLog;
5
- exports.findLogs = findLogs;
6
- const logs = [];
7
- exports.testLog = {
8
- clear: () => {
9
- logs.length = 0;
10
- },
11
- get: () => [...logs],
12
- logo: (version) => {
13
- logs.push(["logo", version]);
14
- },
15
- welcome: () => {
16
- logs.push(["welcome", ""]);
17
- },
18
- section: (msg) => {
19
- logs.push(["section", msg]);
20
- },
21
- success: (msg) => {
22
- logs.push(["success", msg]);
23
- },
24
- final: (msg) => {
25
- logs.push(["final", msg]);
26
- },
27
- summary: (counts) => {
28
- logs.push(["summary", JSON.stringify(counts)]);
29
- },
30
- };
31
- function getLastLog() {
32
- return logs[logs.length - 1];
33
- }
34
- function findLogs(type) {
35
- return logs.filter(([t]) => t === type);
36
- }
@@ -1,141 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const vitest_1 = require("vitest");
4
- const path_1 = require("path");
5
- const reader_1 = require("../src/reader");
6
- const template_1 = require("../src/template");
7
- const fixturesDir = (0, path_1.join)(__dirname, "fixtures");
8
- const commandsDir = (0, path_1.join)(fixturesDir, "commands");
9
- const rulesDir = (0, path_1.join)(fixturesDir, "rules");
10
- const skillsDir = (0, path_1.join)(fixturesDir, "skills");
11
- const agentsDir = (0, path_1.join)(fixturesDir, "agents");
12
- (0, vitest_1.describe)("getCommandConfig", () => {
13
- (0, vitest_1.it)("parses command files and returns config object", () => {
14
- const config = (0, reader_1.getCommandConfig)(commandsDir);
15
- (0, vitest_1.expect)(config).toHaveProperty("test");
16
- (0, vitest_1.expect)(config.test.description).toBe("A test command for testing purposes.");
17
- (0, vitest_1.expect)(config.test.template).toContain("This is a test command template.");
18
- });
19
- (0, vitest_1.it)("includes all command files", () => {
20
- const config = (0, reader_1.getCommandConfig)(commandsDir);
21
- (0, vitest_1.expect)(config).toHaveProperty("test");
22
- (0, vitest_1.expect)(config).toHaveProperty("another");
23
- });
24
- (0, vitest_1.it)("has correct structure for opencode.json command format", () => {
25
- const config = (0, reader_1.getCommandConfig)(commandsDir);
26
- for (const [_, cmd] of Object.entries(config)) {
27
- (0, vitest_1.expect)(cmd).toHaveProperty("description");
28
- (0, vitest_1.expect)(cmd).toHaveProperty("template");
29
- (0, vitest_1.expect)(typeof cmd.description).toBe("string");
30
- (0, vitest_1.expect)(typeof cmd.template).toBe("string");
31
- }
32
- });
33
- (0, vitest_1.it)("returns empty object for non-existent directory", () => {
34
- const config = (0, reader_1.getCommandConfig)("/non/existent/dir");
35
- (0, vitest_1.expect)(config).toEqual({});
36
- });
37
- });
38
- (0, vitest_1.describe)("readContent", () => {
39
- (0, vitest_1.it)("returns files from rules and skills directories", () => {
40
- const files = (0, reader_1.readContent)(rulesDir, skillsDir);
41
- const ruleFiles = files.filter((f) => f.type === "rules");
42
- const skillFiles = files.filter((f) => f.type === "skills");
43
- (0, vitest_1.expect)(ruleFiles.length).toBeGreaterThan(0);
44
- (0, vitest_1.expect)(skillFiles.length).toBeGreaterThan(0);
45
- });
46
- (0, vitest_1.it)("includes nested files recursively", () => {
47
- const files = (0, reader_1.readContent)(rulesDir, skillsDir);
48
- const nestedRule = files.find((f) => f.name === "nested/nested-rule.md" && f.type === "rules");
49
- (0, vitest_1.expect)(nestedRule).toBeDefined();
50
- (0, vitest_1.expect)(nestedRule?.content).toContain("Nested Rule");
51
- });
52
- (0, vitest_1.it)("returns correct file structure", () => {
53
- const files = (0, reader_1.readContent)(rulesDir, skillsDir);
54
- for (const file of files) {
55
- (0, vitest_1.expect)(file).toHaveProperty("type");
56
- (0, vitest_1.expect)(file).toHaveProperty("name");
57
- (0, vitest_1.expect)(file).toHaveProperty("content");
58
- (0, vitest_1.expect)(["rules", "skills"]).toContain(file.type);
59
- (0, vitest_1.expect)(file.name.endsWith(".md")).toBe(true);
60
- }
61
- });
62
- (0, vitest_1.it)("includes skill directory name in file path", () => {
63
- const files = (0, reader_1.readContent)(rulesDir, skillsDir);
64
- const skillFile = files.find((f) => f.type === "skills" && f.name === "test-skill/SKILL.md");
65
- (0, vitest_1.expect)(skillFile).toBeDefined();
66
- (0, vitest_1.expect)(skillFile?.content).toContain("Test Skill");
67
- });
68
- (0, vitest_1.it)("includes additional files in skill directories", () => {
69
- const files = (0, reader_1.readContent)(rulesDir, skillsDir);
70
- const detailsFile = files.find((f) => f.type === "skills" && f.name === "test-skill/skill-details.md");
71
- (0, vitest_1.expect)(detailsFile).toBeDefined();
72
- (0, vitest_1.expect)(detailsFile?.content).toContain("Skill Details");
73
- });
74
- (0, vitest_1.it)("includes nested references in skill directories", () => {
75
- const files = (0, reader_1.readContent)(rulesDir, skillsDir);
76
- const refFile = files.find((f) => f.type === "skills" && f.name === "test-skill/nested-refs/doc.md");
77
- (0, vitest_1.expect)(refFile).toBeDefined();
78
- });
79
- });
80
- (0, vitest_1.describe)("readConfigs", () => {
81
- (0, vitest_1.it)("returns JSON files from agents directory", () => {
82
- const files = (0, reader_1.readConfigs)(agentsDir);
83
- (0, vitest_1.expect)(files.length).toBe(2);
84
- (0, vitest_1.expect)(files.map((f) => f.name).sort()).toEqual([
85
- "another.json",
86
- "opencode.json",
87
- ]);
88
- });
89
- (0, vitest_1.it)("returns file content as string", () => {
90
- const files = (0, reader_1.readConfigs)(agentsDir);
91
- const opencodeFile = files.find((f) => f.name === "opencode.json");
92
- (0, vitest_1.expect)(opencodeFile?.content).toContain("test-agent");
93
- });
94
- (0, vitest_1.it)("returns empty array for non-existent directory", () => {
95
- const files = (0, reader_1.readConfigs)("/non/existent/dir");
96
- (0, vitest_1.expect)(files).toEqual([]);
97
- });
98
- });
99
- (0, vitest_1.describe)("readAgents", () => {
100
- (0, vitest_1.it)("returns AGENTS.md file content", () => {
101
- const file = (0, reader_1.readAgents)(agentsDir);
102
- (0, vitest_1.expect)(file).not.toBeNull();
103
- (0, vitest_1.expect)(file?.name).toBe("AGENTS.md");
104
- (0, vitest_1.expect)(file?.content).toContain("AGENTS.md");
105
- });
106
- (0, vitest_1.it)("returns null when monorepo.md does not exist", () => {
107
- const file = (0, reader_1.readAgents)(rulesDir);
108
- (0, vitest_1.expect)(file).toBeNull();
109
- });
110
- });
111
- (0, vitest_1.describe)("processTemplate", () => {
112
- (0, vitest_1.it)("replaces {{FOOTER}} with full footer text and ISO date", () => {
113
- const result = (0, template_1.processTemplate)("{{FOOTER}}");
114
- const today = new Date().toISOString().split("T")[0];
115
- (0, vitest_1.expect)(result).toBe(`Last updated: ${today}. This file extends the global rules in @AGENTS.md. Always check both files.`);
116
- });
117
- (0, vitest_1.it)("replaces {{AGENTS_FOOTER}} with agents footer text and ISO date", () => {
118
- const result = (0, template_1.processTemplate)("{{AGENTS_FOOTER}}");
119
- const today = new Date().toISOString().split("T")[0];
120
- (0, vitest_1.expect)(result).toBe(`This file was last updated: ${today}. Always check the \`.ai/rules/\` directory for the most current language-specific guidelines.`);
121
- });
122
- (0, vitest_1.it)("replaces multiple placeholders in same content", () => {
123
- const result = (0, template_1.processTemplate)("{{FOOTER}} and {{AGENTS_FOOTER}}");
124
- const today = new Date().toISOString().split("T")[0];
125
- (0, vitest_1.expect)(result).toContain(`Last updated: ${today}`);
126
- (0, vitest_1.expect)(result).toContain(`This file was last updated: ${today}`);
127
- });
128
- (0, vitest_1.it)("leaves non-matching content unchanged", () => {
129
- const input = "Some {{OTHER}} content {{NOTREAL}}";
130
- const result = (0, template_1.processTemplate)(input);
131
- (0, vitest_1.expect)(result).toBe(input);
132
- });
133
- (0, vitest_1.it)("handles empty string", () => {
134
- const result = (0, template_1.processTemplate)("");
135
- (0, vitest_1.expect)(result).toBe("");
136
- });
137
- (0, vitest_1.it)("handles content without placeholders", () => {
138
- const result = (0, template_1.processTemplate)("No placeholders here");
139
- (0, vitest_1.expect)(result).toBe("No placeholders here");
140
- });
141
- });
@@ -1,90 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const vitest_1 = require("vitest");
4
- const sync_1 = require("../src/cmd/sync");
5
- const utils_1 = require("./utils");
6
- const output_1 = require("./output");
7
- const path_1 = require("path");
8
- const fixturesDir = (0, path_1.join)(__dirname, "fixtures");
9
- const testSourceDirs = {
10
- rules: (0, path_1.join)(fixturesDir, "rules"),
11
- skills: (0, path_1.join)(fixturesDir, "skills"),
12
- agents: (0, path_1.join)(fixturesDir, "agents"),
13
- commands: (0, path_1.join)(fixturesDir, "commands"),
14
- };
15
- (0, vitest_1.describe)("sync command", () => {
16
- let tempDir;
17
- (0, vitest_1.beforeEach)(() => {
18
- tempDir = (0, utils_1.createTempDir)();
19
- output_1.testLog.clear();
20
- });
21
- (0, vitest_1.it)("initializes when not already initialized", async () => {
22
- await (0, sync_1.sync)(tempDir, "0.0.1", {}, output_1.testLog, testSourceDirs);
23
- (0, vitest_1.expect)((0, utils_1.fileExists)(tempDir, ".agents/.ai-kit")).toBe(true);
24
- (0, vitest_1.expect)((0, utils_1.fileExists)(tempDir, ".agents/rules")).toBe(true);
25
- (0, vitest_1.expect)((0, utils_1.fileExists)(tempDir, "opencode.json")).toBe(true);
26
- (0, vitest_1.expect)((0, utils_1.fileExists)(tempDir, "AGENTS.md")).toBe(true);
27
- });
28
- (0, vitest_1.it)("skips opencode.json when skipOpencode is true", async () => {
29
- await (0, sync_1.sync)(tempDir, "0.0.1", { skipOpencode: true }, output_1.testLog, testSourceDirs);
30
- (0, vitest_1.expect)((0, utils_1.fileExists)(tempDir, "opencode.json")).toBe(false);
31
- (0, vitest_1.expect)((0, utils_1.fileExists)(tempDir, "AGENTS.md")).toBe(true);
32
- });
33
- (0, vitest_1.it)("writes correct manifest on init", async () => {
34
- await (0, sync_1.sync)(tempDir, "0.0.1", {}, output_1.testLog, testSourceDirs);
35
- const manifest = JSON.parse((0, utils_1.readFile)(tempDir, ".agents/.ai-kit"));
36
- (0, vitest_1.expect)(manifest.version).toBe("0.0.1");
37
- (0, vitest_1.expect)(manifest.rootFiles).toContain("opencode.json");
38
- });
39
- (0, vitest_1.it)("does not re-initialize if already at latest version", async () => {
40
- await (0, sync_1.sync)(tempDir, "0.0.1", {}, output_1.testLog, testSourceDirs);
41
- await (0, sync_1.sync)(tempDir, "0.0.1", {}, output_1.testLog, testSourceDirs);
42
- const lastLog = (0, output_1.getLastLog)();
43
- (0, vitest_1.expect)(lastLog).toEqual(["success", "Already at latest version (0.0.1)"]);
44
- });
45
- (0, vitest_1.it)("updates when version differs", async () => {
46
- await (0, sync_1.sync)(tempDir, "0.0.1", {}, output_1.testLog, testSourceDirs);
47
- await (0, sync_1.sync)(tempDir, "0.0.2", {}, output_1.testLog, testSourceDirs);
48
- const manifest = JSON.parse((0, utils_1.readFile)(tempDir, ".agents/.ai-kit"));
49
- (0, vitest_1.expect)(manifest.version).toBe("0.0.2");
50
- });
51
- (0, vitest_1.it)("respects skipOpencode option on update", async () => {
52
- await (0, sync_1.sync)(tempDir, "0.0.1", { skipOpencode: true }, output_1.testLog, testSourceDirs);
53
- await (0, sync_1.sync)(tempDir, "0.0.2", { skipOpencode: true }, output_1.testLog, testSourceDirs);
54
- const manifest = JSON.parse((0, utils_1.readFile)(tempDir, ".agents/.ai-kit"));
55
- (0, vitest_1.expect)(manifest.rootFiles).toEqual([]);
56
- });
57
- (0, vitest_1.it)("includes commands in opencode.json", async () => {
58
- await (0, sync_1.sync)(tempDir, "0.0.1", {}, output_1.testLog, testSourceDirs);
59
- const opencodeJson = JSON.parse((0, utils_1.readFile)(tempDir, "opencode.json"));
60
- (0, vitest_1.expect)(opencodeJson).toHaveProperty("command");
61
- (0, vitest_1.expect)(opencodeJson.command).toHaveProperty("commit");
62
- (0, vitest_1.expect)(opencodeJson.command.commit.description).toBe("Commit the work done in this session with a structured commit message.");
63
- });
64
- (0, vitest_1.it)("processes template variables in content files", async () => {
65
- await (0, sync_1.sync)(tempDir, "0.0.1", {}, output_1.testLog, testSourceDirs);
66
- const ruleFiles = (0, utils_1.readFile)(tempDir, ".agents/rules/typescript.md");
67
- (0, vitest_1.expect)(ruleFiles).toContain("Last updated:");
68
- (0, vitest_1.expect)(ruleFiles).not.toContain("{{FOOTER}}");
69
- (0, vitest_1.expect)(ruleFiles).toMatch(/\d{4}-\d{2}-\d{2}/);
70
- });
71
- (0, vitest_1.it)("processes template variables in AGENTS.md", async () => {
72
- await (0, sync_1.sync)(tempDir, "0.0.1", {}, output_1.testLog, testSourceDirs);
73
- const agentsMd = (0, utils_1.readFile)(tempDir, "AGENTS.md");
74
- (0, vitest_1.expect)(agentsMd).not.toContain("{{AGENTS_FOOTER}}");
75
- (0, vitest_1.expect)(agentsMd).toMatch(/\d{4}-\d{2}-\d{2}/);
76
- });
77
- (0, vitest_1.it)("logs output correctly", async () => {
78
- await (0, sync_1.sync)(tempDir, "0.0.1", {}, output_1.testLog, testSourceDirs);
79
- const logs = output_1.testLog.get();
80
- (0, vitest_1.expect)(logs[logs.length - 1][0]).toBe("summary");
81
- });
82
- (0, vitest_1.it)("logs all synced files", async () => {
83
- await (0, sync_1.sync)(tempDir, "0.0.1", {}, output_1.testLog, testSourceDirs);
84
- const successLogs = (0, output_1.findLogs)("success");
85
- (0, vitest_1.expect)(successLogs.length).toBeGreaterThan(0);
86
- (0, vitest_1.expect)(successLogs.some(([, msg]) => msg.includes(".md"))).toBe(true);
87
- (0, vitest_1.expect)(successLogs.some(([, msg]) => msg === "opencode.json")).toBe(true);
88
- (0, vitest_1.expect)(successLogs.some(([, msg]) => msg === "AGENTS.md")).toBe(true);
89
- });
90
- });
@@ -1,20 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createTempDir = createTempDir;
4
- exports.readFile = readFile;
5
- exports.fileExists = fileExists;
6
- const fs_1 = require("fs");
7
- const path_1 = require("path");
8
- const os_1 = require("os");
9
- function createTempDir() {
10
- return (0, fs_1.mkdtempSync)((0, path_1.join)((0, os_1.tmpdir)(), "ai-kit-test-"));
11
- }
12
- function readFile(dir, filename) {
13
- const path = (0, path_1.join)(dir, filename);
14
- if (!(0, fs_1.existsSync)(path))
15
- return null;
16
- return (0, fs_1.readFileSync)(path, "utf-8");
17
- }
18
- function fileExists(dir, filename) {
19
- return (0, fs_1.existsSync)((0, path_1.join)(dir, filename));
20
- }
@@ -1,9 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const config_1 = require("vitest/config");
4
- exports.default = (0, config_1.defineConfig)({
5
- test: {
6
- include: ["tests/**/*.test.ts"],
7
- testTimeout: 10000,
8
- },
9
- });
package/docs/roadmap.md DELETED
@@ -1,16 +0,0 @@
1
- # Roadmap
2
-
3
- ## Near
4
-
5
- - Publish to npm
6
-
7
- ## Soon
8
-
9
- - Add --force flag to sync (reimports everything)
10
- - Safe copy files (check if file exists before writing)
11
- - AGENTS.md for single repo (non monorepo)
12
- - Selective sync (choose which commands/rules to install)
13
-
14
- ## Long-term
15
-
16
- - Language detection for lang rules
@@ -1,79 +0,0 @@
1
- import { mkdirSync, writeFileSync } from "fs";
2
- import { join } from "path";
3
-
4
- const rootDir = join(__dirname, "..");
5
- const skillsDir = join(rootDir, "src", "skills", "playwright-cli");
6
-
7
- const GITHUB_API = "https://api.github.com";
8
- const REPO = "microsoft/playwright-cli";
9
-
10
- const args = process.argv.slice(2);
11
- const VERSION = args[0] || "v0.1.1";
12
-
13
- interface GitHubFile {
14
- name: string;
15
- path: string;
16
- type: "file" | "dir";
17
- download_url?: string;
18
- url?: string;
19
- }
20
-
21
- async function fetchJson(url: string): Promise<GitHubFile[]> {
22
- const res = await fetch(url, {
23
- headers: {
24
- Accept: "application/vnd.github.v3+json",
25
- "User-Agent": "ai-kit",
26
- },
27
- });
28
- if (!res.ok) {
29
- throw new Error(`Failed to fetch ${url}: ${res.status} ${res.statusText}`);
30
- }
31
- return (await res.json()) as GitHubFile[];
32
- }
33
-
34
- async function fetchFile(url: string): Promise<string> {
35
- const res = await fetch(url, {
36
- headers: {
37
- Accept: "application/vnd.github.v3.raw",
38
- "User-Agent": "ai-kit",
39
- },
40
- });
41
- if (!res.ok) {
42
- throw new Error(`Failed to fetch ${url}: ${res.status} ${res.statusText}`);
43
- }
44
- return res.text();
45
- }
46
-
47
- async function main() {
48
- console.log(`Fetching playwright-cli skills from ${REPO}@${VERSION}...`);
49
-
50
- const baseUrl = `${GITHUB_API}/repos/${REPO}/contents/skills/playwright-cli?ref=${VERSION}`;
51
- const files = await fetchJson(baseUrl);
52
-
53
- mkdirSync(skillsDir, { recursive: true });
54
- mkdirSync(join(skillsDir, "references"), { recursive: true });
55
-
56
- for (const file of files) {
57
- if (file.type === "dir" && file.name === "references") {
58
- const refs = await fetchJson(file.url!);
59
- for (const ref of refs) {
60
- const content = await fetchFile(ref.download_url!);
61
- const targetPath = join(skillsDir, "references", ref.name);
62
- writeFileSync(targetPath, content);
63
- console.log(` - references/${ref.name}`);
64
- }
65
- } else if (file.type === "file") {
66
- const content = await fetchFile(file.download_url!);
67
- const targetPath = join(skillsDir, file.name);
68
- writeFileSync(targetPath, content);
69
- console.log(` - ${file.name}`);
70
- }
71
- }
72
-
73
- console.log(`\nDone! Skills written to src/skills/playwright-cli/`);
74
- }
75
-
76
- main().catch((err) => {
77
- console.error(err);
78
- process.exit(1);
79
- });
@@ -1,166 +0,0 @@
1
- const https = require("https");
2
- const fs = require("fs");
3
- const path = require("path");
4
-
5
- function generateFilename(prompt, index = 0) {
6
- const base = prompt
7
- .toLowerCase()
8
- .split(/\s+/)
9
- .join("-")
10
- .replace(/[^a-z0-9-]/g, "");
11
- const truncated = base.length > 50 ? base.slice(0, 50) : base;
12
- const ext = ".jpeg";
13
- const suffix = index > 0 ? `-${index}` : "";
14
-
15
- if (!fs.existsSync(truncated + suffix + ext)) {
16
- return truncated + suffix + ext;
17
- }
18
-
19
- for (let i = 1; ; i++) {
20
- const name = `${truncated}-${i}`;
21
- if (!fs.existsSync(name + ext)) {
22
- return name + ext;
23
- }
24
- }
25
- }
26
-
27
- function parseArgs() {
28
- const args = process.argv.slice(2);
29
- let prompt = "";
30
- let outputDir = "";
31
- let options = {
32
- aspectRatio: "16:9",
33
- width: null,
34
- height: null,
35
- seed: null,
36
- n: 1,
37
- promptOptimizer: false,
38
- };
39
-
40
- for (const arg of args) {
41
- if (arg.startsWith("--aspect-ratio=")) {
42
- options.aspectRatio = arg.split("=")[1];
43
- } else if (arg.startsWith("--width=")) {
44
- options.width = parseInt(arg.split("=")[1], 10);
45
- } else if (arg.startsWith("--height=")) {
46
- options.height = parseInt(arg.split("=")[1], 10);
47
- } else if (arg.startsWith("--seed=")) {
48
- options.seed = parseInt(arg.split("=")[1], 10);
49
- } else if (arg.startsWith("--n=")) {
50
- options.n = parseInt(arg.split("=")[1], 10);
51
- } else if (arg === "--prompt-optimizer") {
52
- options.promptOptimizer = true;
53
- } else if (arg.startsWith("--output-dir=")) {
54
- outputDir = arg.split("=")[1];
55
- } else if (!arg.startsWith("--")) {
56
- prompt = arg;
57
- }
58
- }
59
-
60
- if (!prompt) {
61
- console.error(
62
- "usage: generate.js <prompt> --output-dir=<path> [--aspect-ratio=16:9] [--width=1024] [--height=1024] [--seed=<number>] [--n=1] [--prompt-optimizer]",
63
- );
64
- process.exit(1);
65
- }
66
-
67
- if (!outputDir) {
68
- console.error(
69
- "usage: generate.js <prompt> --output-dir=<path> [--aspect-ratio=16:9] [--width=1024] [--height=1024] [--seed=<number>] [--n=1] [--prompt-optimizer]",
70
- );
71
- console.error("error: --output-dir is required");
72
- process.exit(1);
73
- }
74
-
75
- return { prompt, outputDir, options };
76
- }
77
-
78
- function buildPayload(prompt, options) {
79
- const payload = {
80
- model: "image-01",
81
- prompt,
82
- response_format: "base64",
83
- n: options.n,
84
- prompt_optimizer: options.promptOptimizer,
85
- };
86
-
87
- if (options.width && options.height) {
88
- payload.width = options.width;
89
- payload.height = options.height;
90
- } else {
91
- payload.aspect_ratio = options.aspectRatio;
92
- }
93
-
94
- if (options.seed !== null) {
95
- payload.seed = options.seed;
96
- }
97
-
98
- return payload;
99
- }
100
-
101
- function main() {
102
- const { prompt, outputDir, options } = parseArgs();
103
-
104
- const apiKey = process.env.MINIMAX_API_KEY;
105
- if (!apiKey) {
106
- console.error("MINIMAX_API_KEY not set");
107
- process.exit(1);
108
- }
109
-
110
- if (!fs.existsSync(outputDir)) {
111
- fs.mkdirSync(outputDir, { recursive: true });
112
- }
113
-
114
- const payload = JSON.stringify(buildPayload(prompt, options));
115
-
116
- const req = https.request(
117
- {
118
- hostname: "api.minimax.io",
119
- port: 443,
120
- path: "/v1/image_generation",
121
- method: "POST",
122
- headers: {
123
- Authorization: `Bearer ${apiKey}`,
124
- "Content-Type": "application/json",
125
- "Content-Length": Buffer.byteLength(payload),
126
- },
127
- },
128
- (res) => {
129
- if (res.statusCode && res.statusCode >= 400) {
130
- let body = "";
131
- res.on("data", (chunk) => (body += chunk));
132
- res.on("end", () => {
133
- console.error(
134
- `request failed with status ${res.statusCode}: ${body}`,
135
- );
136
- process.exit(1);
137
- });
138
- return;
139
- }
140
-
141
- let body = "";
142
- res.on("data", (chunk) => (body += chunk));
143
- res.on("end", () => {
144
- const result = JSON.parse(body);
145
- const images = result.data?.image_base64 || [];
146
-
147
- for (let i = 0; i < images.length; i++) {
148
- const decoded = Buffer.from(images[i], "base64");
149
- const filename = generateFilename(prompt, i);
150
- const outputPath = path.join(outputDir, filename);
151
- fs.writeFileSync(outputPath, decoded);
152
- }
153
- });
154
- },
155
- );
156
-
157
- req.on("error", (err) => {
158
- console.error(`request failed: ${err}`);
159
- process.exit(1);
160
- });
161
-
162
- req.write(payload);
163
- req.end();
164
- }
165
-
166
- main();
@@ -1,4 +0,0 @@
1
- {
2
- "name": "another-agent",
3
- "version": "2.0.0"
4
- }
@@ -1,5 +0,0 @@
1
- # AGENTS.md
2
-
3
- This is a test AGENTS.md file.
4
-
5
- {{AGENTS_FOOTER}}
@@ -1,4 +0,0 @@
1
- {
2
- "name": "test-agent",
3
- "version": "1.0.0"
4
- }
@@ -1,5 +0,0 @@
1
- ---
2
- description: Another test command.
3
- ---
4
-
5
- Another command template.
@@ -1,7 +0,0 @@
1
- ---
2
- description: Commit the work done in this session with a structured commit message.
3
- ---
4
-
5
- # commit
6
-
7
- Commits the work done in this session.
@@ -1,13 +0,0 @@
1
- ---
2
- description: A test command for testing purposes.
3
- ---
4
-
5
- This is a test command template.
6
-
7
- ## Section 1
8
-
9
- Test content here.
10
-
11
- ## Section 2
12
-
13
- More test content.
@@ -1,3 +0,0 @@
1
- # Nested Rule
2
-
3
- This is a nested rule file.
@@ -1,5 +0,0 @@
1
- # Test Rule
2
-
3
- {{FOOTER}}
4
-
5
- This is a test rule file.
@@ -1,5 +0,0 @@
1
- # Typescript
2
-
3
- Follow TypeScript best practices.
4
-
5
- {{FOOTER}}