@kurokeita/add-skill 1.6.0 → 1.8.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.
- package/README.md +3 -3
- package/dist/bin/cli.js +691 -26
- package/dist/skills/skill-creator/scripts/init_skill.cjs +31 -31
- package/dist/skills/skill-creator/scripts/package_skill.cjs +29 -29
- package/dist/skills/skill-creator/scripts/validate_skill.cjs +41 -41
- package/package.json +11 -6
- package/dist/src/commands/add.js +0 -235
- package/dist/src/commands/import.js +0 -116
- package/dist/src/commands/list.js +0 -92
- package/dist/src/commands/remove.js +0 -118
- package/dist/src/utils/github.js +0 -65
- package/dist/src/utils/paths.js +0 -45
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { cancel, confirm, intro, isCancel, outro, spinner, } from "@clack/prompts";
|
|
3
|
-
import fs from "fs-extra";
|
|
4
|
-
import pc from "picocolors";
|
|
5
|
-
import { fetchSkillFromGitHub } from "../utils/github.js";
|
|
6
|
-
import { TYPE_DIRS } from "../utils/paths.js";
|
|
7
|
-
export async function importItem(type, url) {
|
|
8
|
-
intro(pc.bgCyan(pc.black(` AI Manager : Import ${type} `)));
|
|
9
|
-
// Normalize type
|
|
10
|
-
const normalizedType = type.toLowerCase().endsWith("s")
|
|
11
|
-
? type.slice(0, -1)
|
|
12
|
-
: type;
|
|
13
|
-
const targetBaseDir = TYPE_DIRS[normalizedType];
|
|
14
|
-
if (!targetBaseDir) {
|
|
15
|
-
cancel(`Unknown type: ${type}. Supported: skill, agent, workflow`);
|
|
16
|
-
process.exit(1);
|
|
17
|
-
}
|
|
18
|
-
if (!url) {
|
|
19
|
-
cancel("GitHub URL is required.");
|
|
20
|
-
process.exit(1);
|
|
21
|
-
}
|
|
22
|
-
let tempDir = null;
|
|
23
|
-
try {
|
|
24
|
-
// 1. Fetch Item (using fetchSkillFromGitHub as generic fetcher)
|
|
25
|
-
const s = spinner();
|
|
26
|
-
s.start(`Fetching ${normalizedType} from GitHub...`);
|
|
27
|
-
let itemName = "";
|
|
28
|
-
let isFile = false;
|
|
29
|
-
try {
|
|
30
|
-
const result = await fetchSkillFromGitHub(url);
|
|
31
|
-
tempDir = result.tempDir;
|
|
32
|
-
if (!tempDir)
|
|
33
|
-
throw new Error("Failed to create temp directory");
|
|
34
|
-
itemName = result.skillName; // reuse property or rename if possible. assuming generic repo structure
|
|
35
|
-
isFile = result.isFile;
|
|
36
|
-
s.stop(pc.green(`Fetched: ${itemName}`));
|
|
37
|
-
}
|
|
38
|
-
catch (e) {
|
|
39
|
-
s.stop(pc.red("Failed to fetch"));
|
|
40
|
-
throw e;
|
|
41
|
-
}
|
|
42
|
-
// 2. Determine Target
|
|
43
|
-
const shouldFlatten = (normalizedType === "agent" || normalizedType === "workflow") && !isFile;
|
|
44
|
-
const targetPath = shouldFlatten
|
|
45
|
-
? targetBaseDir
|
|
46
|
-
: path.join(targetBaseDir, itemName);
|
|
47
|
-
// 3. Check Existence & Confirm Overwrite
|
|
48
|
-
if (shouldFlatten) {
|
|
49
|
-
const srcFiles = await fs.readdir(tempDir);
|
|
50
|
-
const conflicts = [];
|
|
51
|
-
for (const file of srcFiles) {
|
|
52
|
-
if (await fs.pathExists(path.join(targetBaseDir, file))) {
|
|
53
|
-
conflicts.push(file);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
if (conflicts.length > 0) {
|
|
57
|
-
const limit = 5;
|
|
58
|
-
const displayList = conflicts.slice(0, limit).join(", ");
|
|
59
|
-
const remainder = conflicts.length - limit;
|
|
60
|
-
const message = remainder > 0
|
|
61
|
-
? `Files ${displayList} (and ${remainder} others) already exist in ${targetBaseDir}. Overwrite?`
|
|
62
|
-
: `Files ${displayList} already exist in ${targetBaseDir}. Overwrite?`;
|
|
63
|
-
const shouldOverwrite = await confirm({
|
|
64
|
-
message,
|
|
65
|
-
initialValue: false,
|
|
66
|
-
});
|
|
67
|
-
if (isCancel(shouldOverwrite) || !shouldOverwrite) {
|
|
68
|
-
if (tempDir)
|
|
69
|
-
await fs.remove(tempDir);
|
|
70
|
-
cancel("Operation cancelled.");
|
|
71
|
-
process.exit(0);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
else if (await fs.pathExists(targetPath)) {
|
|
76
|
-
const shouldOverwrite = await confirm({
|
|
77
|
-
message: `${normalizedType} '${itemName}' already exists in the repo. Overwrite?`,
|
|
78
|
-
initialValue: false,
|
|
79
|
-
});
|
|
80
|
-
if (isCancel(shouldOverwrite) || !shouldOverwrite) {
|
|
81
|
-
if (tempDir)
|
|
82
|
-
await fs.remove(tempDir);
|
|
83
|
-
cancel("Operation cancelled.");
|
|
84
|
-
process.exit(0);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
// 4. Move/Copy to Target Directory
|
|
88
|
-
s.start(`Importing ${itemName} to ${targetBaseDir}...`);
|
|
89
|
-
await fs.ensureDir(targetBaseDir);
|
|
90
|
-
if (isFile) {
|
|
91
|
-
await fs.copy(path.join(tempDir, itemName), targetPath, {
|
|
92
|
-
overwrite: true,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
if (shouldFlatten) {
|
|
97
|
-
await fs.copy(tempDir, targetBaseDir, { overwrite: true });
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
await fs.copy(tempDir, targetPath, { overwrite: true });
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
s.stop(pc.green(`Successfully imported ${itemName}!`));
|
|
104
|
-
// Cleanup
|
|
105
|
-
if (tempDir) {
|
|
106
|
-
await fs.remove(tempDir);
|
|
107
|
-
}
|
|
108
|
-
outro(`${normalizedType} available at: ${targetPath}`);
|
|
109
|
-
}
|
|
110
|
-
catch (error) {
|
|
111
|
-
if (tempDir)
|
|
112
|
-
await fs.remove(tempDir);
|
|
113
|
-
cancel(`An error occurred: ${error}`);
|
|
114
|
-
process.exit(1);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import fs from "fs-extra";
|
|
2
|
-
import pc from "picocolors";
|
|
3
|
-
import { getTargetPaths, TYPE_DIRS } from "../utils/paths.js";
|
|
4
|
-
export async function list(type, options) {
|
|
5
|
-
try {
|
|
6
|
-
const typesToList = type
|
|
7
|
-
? [type.toLowerCase()]
|
|
8
|
-
: ["skill", "agent", "workflow"];
|
|
9
|
-
for (const t of typesToList) {
|
|
10
|
-
// Handle plural/singular input for convenience
|
|
11
|
-
const normalizedType = t.endsWith("s") ? t.slice(0, -1) : t;
|
|
12
|
-
if (options?.local) {
|
|
13
|
-
// List installed items locally
|
|
14
|
-
console.log(pc.bold(pc.blue(`Installed ${normalizedType}s (Local):`)));
|
|
15
|
-
const targetPaths = getTargetPaths(normalizedType);
|
|
16
|
-
let foundAny = false;
|
|
17
|
-
for (const [platform, pathStr] of Object.entries(targetPaths)) {
|
|
18
|
-
const fullPath = pathStr;
|
|
19
|
-
if (await fs.pathExists(fullPath)) {
|
|
20
|
-
const entries = await fs.readdir(fullPath, {
|
|
21
|
-
withFileTypes: true,
|
|
22
|
-
});
|
|
23
|
-
const items = entries
|
|
24
|
-
.filter((entry) => entry.isDirectory() ||
|
|
25
|
-
// For local items, agents/workflows might be directories OR .md files depending on how they were installed/flattened.
|
|
26
|
-
// Usually flattened -> directory (if unpacked) or file (if generic).
|
|
27
|
-
// Existing add logic:
|
|
28
|
-
// Agents/Workflows can be flattened (unpacked to base) or not.
|
|
29
|
-
// If flattened, they are files in the base dir? No, unpacked to base means they are files/dirs IN the base dir.
|
|
30
|
-
// Wait, if I import "agent-a" (dir) and flatten, it copies contents of agent-a to agents/.
|
|
31
|
-
// So "agents/skill.md" might exist.
|
|
32
|
-
// The user requirement says "list all installed agents/skills/workflows".
|
|
33
|
-
// In local global_skills (antigravity), they are directories.
|
|
34
|
-
// In local global_agents, they might be directories or .md files.
|
|
35
|
-
// Let's list directories and .md files.
|
|
36
|
-
(entry.isFile() && entry.name.endsWith(".md")))
|
|
37
|
-
.map((entry) => entry.name)
|
|
38
|
-
.sort();
|
|
39
|
-
if (items.length > 0) {
|
|
40
|
-
foundAny = true;
|
|
41
|
-
console.log(pc.cyan(` ${platform}:`));
|
|
42
|
-
for (const item of items) {
|
|
43
|
-
console.log(` - ${item}`);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
if (!foundAny) {
|
|
49
|
-
console.log(pc.dim(` No installed ${normalizedType}s found.`));
|
|
50
|
-
}
|
|
51
|
-
console.log(""); // Newline for separation
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
// List available items in repo (existing logic)
|
|
55
|
-
if (!TYPE_DIRS[normalizedType]) {
|
|
56
|
-
if (type) {
|
|
57
|
-
console.error(pc.red(`Unknown type: ${type}. Supported types: skill, agent, workflow`));
|
|
58
|
-
}
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
const dirPath = TYPE_DIRS[normalizedType];
|
|
62
|
-
if (!(await fs.pathExists(dirPath))) {
|
|
63
|
-
if (type) {
|
|
64
|
-
console.log(pc.yellow(`No ${t} directory found at: ${dirPath}`));
|
|
65
|
-
}
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
69
|
-
const items = entries
|
|
70
|
-
.filter((entry) => entry.isDirectory() ||
|
|
71
|
-
(normalizedType !== "skill" &&
|
|
72
|
-
entry.isFile() &&
|
|
73
|
-
entry.name.endsWith(".md")))
|
|
74
|
-
.map((entry) => entry.name)
|
|
75
|
-
.sort();
|
|
76
|
-
if (items.length > 0) {
|
|
77
|
-
console.log(pc.bold(pc.blue(`Available ${normalizedType}s:`)));
|
|
78
|
-
for (const item of items) {
|
|
79
|
-
console.log(`- ${item}`);
|
|
80
|
-
}
|
|
81
|
-
console.log(pc.dim(`Total: ${items.length} ${normalizedType}s\n`));
|
|
82
|
-
}
|
|
83
|
-
else if (type) {
|
|
84
|
-
console.log(pc.dim(`No ${normalizedType}s found.`));
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
catch (error) {
|
|
90
|
-
console.error(pc.red("Error listing items:"), error);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import { cancel, confirm, intro, isCancel, multiselect, outro, spinner, } from "@clack/prompts";
|
|
3
|
-
import fs from "fs-extra";
|
|
4
|
-
import pc from "picocolors";
|
|
5
|
-
import { getTargetPaths, PLATFORM_LABELS, } from "../utils/paths.js";
|
|
6
|
-
export async function remove(type) {
|
|
7
|
-
intro(pc.bgCyan(pc.black(` AI Manager : Remove ${type} `)));
|
|
8
|
-
// Normalize type
|
|
9
|
-
const normalizedType = type.toLowerCase().endsWith("s")
|
|
10
|
-
? type.slice(0, -1)
|
|
11
|
-
: type;
|
|
12
|
-
const targetPaths = getTargetPaths(normalizedType);
|
|
13
|
-
// 1. Collect unique installed items across all platforms
|
|
14
|
-
const uniqueItems = new Set();
|
|
15
|
-
const s = spinner();
|
|
16
|
-
s.start("Scanning for installed items...");
|
|
17
|
-
for (const pathStr of Object.values(targetPaths)) {
|
|
18
|
-
if (await fs.pathExists(pathStr)) {
|
|
19
|
-
const entries = await fs.readdir(pathStr, {
|
|
20
|
-
withFileTypes: true,
|
|
21
|
-
});
|
|
22
|
-
for (const entry of entries) {
|
|
23
|
-
if (entry.isDirectory() ||
|
|
24
|
-
(normalizedType === "workflow" &&
|
|
25
|
-
entry.isFile() &&
|
|
26
|
-
entry.name.endsWith(".md")) ||
|
|
27
|
-
(normalizedType === "agent" &&
|
|
28
|
-
entry.isFile() &&
|
|
29
|
-
entry.name.endsWith(".md"))) {
|
|
30
|
-
uniqueItems.add(entry.name);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
s.stop(`Found ${uniqueItems.size} unique installed ${normalizedType}s.`);
|
|
36
|
-
if (uniqueItems.size === 0) {
|
|
37
|
-
cancel(`No installed ${normalizedType}s found.`);
|
|
38
|
-
process.exit(0);
|
|
39
|
-
}
|
|
40
|
-
// Sort explicitly
|
|
41
|
-
const sortedItems = Array.from(uniqueItems).sort();
|
|
42
|
-
// 2. Select Items
|
|
43
|
-
const itemSelections = await multiselect({
|
|
44
|
-
message: `Select ${normalizedType}s to remove:`,
|
|
45
|
-
options: sortedItems.map((item) => ({ value: item, label: item })),
|
|
46
|
-
required: true,
|
|
47
|
-
});
|
|
48
|
-
if (isCancel(itemSelections)) {
|
|
49
|
-
cancel("Operation cancelled.");
|
|
50
|
-
process.exit(0);
|
|
51
|
-
}
|
|
52
|
-
const selectedItems = itemSelections;
|
|
53
|
-
// 3. Select Platforms
|
|
54
|
-
// Only show platforms relevant to the type
|
|
55
|
-
const platformOptions = Object.entries(targetPaths).map(([platform]) => ({
|
|
56
|
-
label: PLATFORM_LABELS[platform],
|
|
57
|
-
value: platform,
|
|
58
|
-
}));
|
|
59
|
-
const platformSelections = await multiselect({
|
|
60
|
-
message: "Select platforms to remove from:",
|
|
61
|
-
options: platformOptions,
|
|
62
|
-
required: true,
|
|
63
|
-
});
|
|
64
|
-
if (isCancel(platformSelections)) {
|
|
65
|
-
cancel("Operation cancelled.");
|
|
66
|
-
process.exit(0);
|
|
67
|
-
}
|
|
68
|
-
const selectedPlatforms = platformSelections;
|
|
69
|
-
// 4. Confirmation
|
|
70
|
-
const confirmDelete = await confirm({
|
|
71
|
-
message: `Are you sure you want to remove ${selectedItems.length} item(s) from ${selectedPlatforms.length} platform(s)?`,
|
|
72
|
-
initialValue: false,
|
|
73
|
-
});
|
|
74
|
-
if (isCancel(confirmDelete) || !confirmDelete) {
|
|
75
|
-
cancel("Operation cancelled.");
|
|
76
|
-
process.exit(0);
|
|
77
|
-
}
|
|
78
|
-
// 5. Deletion Loop
|
|
79
|
-
const sDel = spinner();
|
|
80
|
-
sDel.start("Removing items...");
|
|
81
|
-
let removedCount = 0;
|
|
82
|
-
let notFoundCount = 0;
|
|
83
|
-
const errors = [];
|
|
84
|
-
for (const platform of selectedPlatforms) {
|
|
85
|
-
const targetBase = targetPaths[platform];
|
|
86
|
-
if (!targetBase)
|
|
87
|
-
continue;
|
|
88
|
-
for (const item of selectedItems) {
|
|
89
|
-
const targetPath = path.join(targetBase, item);
|
|
90
|
-
// Check if exists before trying to remove, to correctly count "removed" vs "not found"
|
|
91
|
-
if (await fs.pathExists(targetPath)) {
|
|
92
|
-
sDel.message(`Removing ${pc.bold(item)} from ${pc.cyan(platform)}...`);
|
|
93
|
-
try {
|
|
94
|
-
await fs.remove(targetPath);
|
|
95
|
-
removedCount++;
|
|
96
|
-
}
|
|
97
|
-
catch (err) {
|
|
98
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
99
|
-
errors.push(`${item} (${platform}): ${msg}`);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
notFoundCount++;
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
if (errors.length > 0) {
|
|
108
|
-
sDel.stop(pc.yellow(`Completed with errors. Removed: ${removedCount}, Not Found: ${notFoundCount}, Errors: ${errors.length}`));
|
|
109
|
-
console.error(pc.red("\nErrors encountered:"));
|
|
110
|
-
for (const e of errors) {
|
|
111
|
-
console.error(pc.red(`- ${e}`));
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
sDel.stop(pc.green(`Successfully removed ${removedCount} items. (${notFoundCount} not found)`));
|
|
116
|
-
}
|
|
117
|
-
outro("Done!");
|
|
118
|
-
}
|
package/dist/src/utils/github.js
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import os from "node:os";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import fs from "fs-extra";
|
|
4
|
-
export async function fetchSkillFromGitHub(url) {
|
|
5
|
-
const regex = /github\.com\/([^/]+)\/([^/]+)\/(?:tree|blob)\/([^/]+)\/(.+)/;
|
|
6
|
-
const match = url.match(regex);
|
|
7
|
-
if (!match) {
|
|
8
|
-
throw new Error("Invalid GitHub URL. Format: https://github.com/owner/repo/tree/branch/path/to/skill or blob/branch/path/to/file");
|
|
9
|
-
}
|
|
10
|
-
const [, owner, repo, ref, skillPath] = match;
|
|
11
|
-
const skillName = path.basename(skillPath);
|
|
12
|
-
const initialApiUrl = `https://api.github.com/repos/${owner}/${repo}/contents/${skillPath}?ref=${ref}`;
|
|
13
|
-
const tempDir = path.join(os.tmpdir(), "ai-agents-install", skillName);
|
|
14
|
-
await fs.ensureDir(tempDir);
|
|
15
|
-
await fs.emptyDir(tempDir);
|
|
16
|
-
let isFile = false;
|
|
17
|
-
async function downloadDirectory(apiUrl, localDir) {
|
|
18
|
-
const response = await fetch(apiUrl, {
|
|
19
|
-
headers: {
|
|
20
|
-
"User-Agent": "ai-agents-cli",
|
|
21
|
-
Accept: "application/vnd.github.v3+json",
|
|
22
|
-
},
|
|
23
|
-
});
|
|
24
|
-
if (!response.ok) {
|
|
25
|
-
throw new Error(`Failed to fetch from GitHub (${response.status}): ${response.statusText}`);
|
|
26
|
-
}
|
|
27
|
-
const data = await response.json();
|
|
28
|
-
// Handle single file response
|
|
29
|
-
if (!Array.isArray(data) && data.type === "file") {
|
|
30
|
-
isFile = true;
|
|
31
|
-
const item = data;
|
|
32
|
-
if (item.download_url) {
|
|
33
|
-
const fileContentResponse = await fetch(item.download_url);
|
|
34
|
-
if (!fileContentResponse.ok) {
|
|
35
|
-
throw new Error(`Failed to download ${item.name}: ${fileContentResponse.statusText}`);
|
|
36
|
-
}
|
|
37
|
-
const content = await fileContentResponse.text();
|
|
38
|
-
await fs.writeFile(path.join(localDir, item.name), content);
|
|
39
|
-
}
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
if (!Array.isArray(data)) {
|
|
43
|
-
throw new Error("Invalid response from GitHub API. Expected directory listing or file object.");
|
|
44
|
-
}
|
|
45
|
-
const files = data;
|
|
46
|
-
for (const item of files) {
|
|
47
|
-
if (item.type === "file" && item.download_url) {
|
|
48
|
-
const fileContentResponse = await fetch(item.download_url);
|
|
49
|
-
if (!fileContentResponse.ok) {
|
|
50
|
-
console.warn(`Failed to download ${item.name}: ${fileContentResponse.statusText}`);
|
|
51
|
-
continue;
|
|
52
|
-
}
|
|
53
|
-
const content = await fileContentResponse.text();
|
|
54
|
-
await fs.writeFile(path.join(localDir, item.name), content);
|
|
55
|
-
}
|
|
56
|
-
else if (item.type === "dir") {
|
|
57
|
-
const newLocalDir = path.join(localDir, item.name);
|
|
58
|
-
await fs.ensureDir(newLocalDir);
|
|
59
|
-
await downloadDirectory(item.url, newLocalDir);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
await downloadDirectory(initialApiUrl, tempDir);
|
|
64
|
-
return { tempDir, skillName, isFile };
|
|
65
|
-
}
|
package/dist/src/utils/paths.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import os from "node:os";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
5
|
-
const __dirname = path.dirname(__filename);
|
|
6
|
-
export const PROJECT_ROOT = path.resolve(__dirname, "../..");
|
|
7
|
-
export const PLATFORM_LABELS = {
|
|
8
|
-
antigravity: "Antigravity",
|
|
9
|
-
gemini: "Gemini CLI",
|
|
10
|
-
copilot: "GitHub Copilot",
|
|
11
|
-
windsurf: "Windsurf",
|
|
12
|
-
};
|
|
13
|
-
export const PLATFORM_PATHS_SKILLS = {
|
|
14
|
-
antigravity: path.join(os.homedir(), ".gemini/antigravity/global_skills"),
|
|
15
|
-
copilot: path.join(os.homedir(), ".copilot/skills"),
|
|
16
|
-
gemini: path.join(os.homedir(), ".gemini/skills"),
|
|
17
|
-
windsurf: path.join(os.homedir(), ".codeium/windsurf/skills"),
|
|
18
|
-
};
|
|
19
|
-
export const PLATFORM_PATHS_AGENTS = {
|
|
20
|
-
antigravity: path.join(os.homedir(), ".gemini/antigravity/global_agents"),
|
|
21
|
-
copilot: path.join(os.homedir(), ".copilot/agents"),
|
|
22
|
-
gemini: path.join(os.homedir(), ".gemini/agents"),
|
|
23
|
-
windsurf: path.join(os.homedir(), ".codeium/windsurf/agents"),
|
|
24
|
-
};
|
|
25
|
-
export const PLATFORM_PATHS_WORKFLOWS = {
|
|
26
|
-
antigravity: path.join(os.homedir(), ".gemini/antigravity/global_workflows"),
|
|
27
|
-
copilot: path.join(os.homedir(), ".copilot/prompts"),
|
|
28
|
-
gemini: path.join(os.homedir(), ".gemini/workflows"),
|
|
29
|
-
windsurf: path.join(os.homedir(), ".codeium/windsurf/global_workflows"),
|
|
30
|
-
};
|
|
31
|
-
export const TYPE_DIRS = {
|
|
32
|
-
skill: path.join(PROJECT_ROOT, "skills"),
|
|
33
|
-
agent: path.join(PROJECT_ROOT, "agents"),
|
|
34
|
-
workflow: path.join(PROJECT_ROOT, "workflows"),
|
|
35
|
-
};
|
|
36
|
-
export function getTargetPaths(type) {
|
|
37
|
-
switch (type) {
|
|
38
|
-
case "agent":
|
|
39
|
-
return PLATFORM_PATHS_AGENTS;
|
|
40
|
-
case "workflow":
|
|
41
|
-
return PLATFORM_PATHS_WORKFLOWS;
|
|
42
|
-
default:
|
|
43
|
-
return PLATFORM_PATHS_SKILLS;
|
|
44
|
-
}
|
|
45
|
-
}
|