@danieldeusing/seedr 0.1.80
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/dist/chunk-5XFKC3T7.js +681 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +1232 -0
- package/dist/index.d.ts +128 -0
- package/dist/index.js +140 -0
- package/package.json +70 -0
|
@@ -0,0 +1,681 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/config/registry.ts
|
|
4
|
+
import { readFile, readdir, writeFile, mkdir } from "fs/promises";
|
|
5
|
+
import { join, dirname } from "path";
|
|
6
|
+
import { fileURLToPath } from "url";
|
|
7
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
var REGISTRY_PATH = join(__dirname, "../../../../registry");
|
|
9
|
+
var GITHUB_RAW_URL = "https://raw.githubusercontent.com/danieldeusing/seedr/main/registry";
|
|
10
|
+
var cache = {
|
|
11
|
+
index: null,
|
|
12
|
+
types: /* @__PURE__ */ new Map(),
|
|
13
|
+
assembled: null
|
|
14
|
+
};
|
|
15
|
+
async function loadFile(filename) {
|
|
16
|
+
try {
|
|
17
|
+
return await readFile(join(REGISTRY_PATH, filename), "utf-8");
|
|
18
|
+
} catch {
|
|
19
|
+
return fetchRemote(`${GITHUB_RAW_URL}/${filename}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async function fetchRemote(url) {
|
|
23
|
+
const response = await fetch(url);
|
|
24
|
+
if (!response.ok) {
|
|
25
|
+
throw new Error(`Failed to fetch ${url}: ${response.statusText}`);
|
|
26
|
+
}
|
|
27
|
+
return response.text();
|
|
28
|
+
}
|
|
29
|
+
async function loadIndex() {
|
|
30
|
+
if (cache.index) return cache.index;
|
|
31
|
+
const content = await loadFile("manifest.json");
|
|
32
|
+
const data = JSON.parse(content);
|
|
33
|
+
cache.index = data;
|
|
34
|
+
return data;
|
|
35
|
+
}
|
|
36
|
+
async function loadTypeItems(type) {
|
|
37
|
+
const cached = cache.types.get(type);
|
|
38
|
+
if (cached) return cached;
|
|
39
|
+
const index = await loadIndex();
|
|
40
|
+
const desc = index.types[type];
|
|
41
|
+
const content = await loadFile(desc.file);
|
|
42
|
+
const typeManifest = JSON.parse(content);
|
|
43
|
+
cache.types.set(type, typeManifest.items);
|
|
44
|
+
return typeManifest.items;
|
|
45
|
+
}
|
|
46
|
+
async function loadManifest() {
|
|
47
|
+
if (cache.assembled) return cache.assembled;
|
|
48
|
+
const index = await loadIndex();
|
|
49
|
+
const typeEntries = Object.entries(index.types);
|
|
50
|
+
const typeResults = await Promise.all(
|
|
51
|
+
typeEntries.map(async ([type]) => loadTypeItems(type))
|
|
52
|
+
);
|
|
53
|
+
const items = typeResults.flat();
|
|
54
|
+
const manifest = { version: index.version, items };
|
|
55
|
+
cache.assembled = manifest;
|
|
56
|
+
return manifest;
|
|
57
|
+
}
|
|
58
|
+
async function getItem(slug, type) {
|
|
59
|
+
const manifest = await loadManifest();
|
|
60
|
+
if (type) return manifest.items.find((item) => item.slug === slug && item.type === type);
|
|
61
|
+
return manifest.items.find((item) => item.slug === slug);
|
|
62
|
+
}
|
|
63
|
+
async function listItems(type) {
|
|
64
|
+
if (type) {
|
|
65
|
+
return loadTypeItems(type);
|
|
66
|
+
}
|
|
67
|
+
const manifest = await loadManifest();
|
|
68
|
+
return manifest.items;
|
|
69
|
+
}
|
|
70
|
+
async function searchItems(query) {
|
|
71
|
+
const manifest = await loadManifest();
|
|
72
|
+
const lowerQuery = query.toLowerCase();
|
|
73
|
+
return manifest.items.filter(
|
|
74
|
+
(item) => item.slug.toLowerCase().includes(lowerQuery) || item.name.toLowerCase().includes(lowerQuery) || item.description.toLowerCase().includes(lowerQuery)
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
async function getItemFull(item) {
|
|
78
|
+
const typeDir = item.type + "s";
|
|
79
|
+
const itemJsonPath = `${typeDir}/${item.slug}/item.json`;
|
|
80
|
+
const content = await loadFile(itemJsonPath);
|
|
81
|
+
return JSON.parse(content);
|
|
82
|
+
}
|
|
83
|
+
function getItemBaseUrl(item) {
|
|
84
|
+
if (item.externalUrl) {
|
|
85
|
+
const rawUrl = item.externalUrl.replace("github.com", "raw.githubusercontent.com").replace("/tree/", "/");
|
|
86
|
+
return { local: null, remote: rawUrl };
|
|
87
|
+
}
|
|
88
|
+
const typeDir = item.type + "s";
|
|
89
|
+
return {
|
|
90
|
+
local: join(REGISTRY_PATH, typeDir, item.slug),
|
|
91
|
+
remote: `${GITHUB_RAW_URL}/${typeDir}/${item.slug}`
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
async function getItemContent(item) {
|
|
95
|
+
const { local, remote } = getItemBaseUrl(item);
|
|
96
|
+
const mainFile = item.type === "skill" ? "SKILL.md" : `${item.type}.md`;
|
|
97
|
+
if (local) {
|
|
98
|
+
try {
|
|
99
|
+
return await readFile(join(local, mainFile), "utf-8");
|
|
100
|
+
} catch {
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return fetchRemote(`${remote}/${mainFile}`);
|
|
104
|
+
}
|
|
105
|
+
function getItemSourcePath(item) {
|
|
106
|
+
if (item.sourceType !== "toolr") {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
const typeDir = item.type + "s";
|
|
110
|
+
return join(REGISTRY_PATH, typeDir, item.slug);
|
|
111
|
+
}
|
|
112
|
+
async function fetchItemToDestination(item, destPath) {
|
|
113
|
+
const { remote } = getItemBaseUrl(item);
|
|
114
|
+
let files = item.contents?.files;
|
|
115
|
+
if (!files && item.type === "plugin") {
|
|
116
|
+
const full = await getItemFull(item);
|
|
117
|
+
files = full.contents?.files;
|
|
118
|
+
}
|
|
119
|
+
if (files) {
|
|
120
|
+
await mkdir(destPath, { recursive: true });
|
|
121
|
+
await fetchFileTree(files, remote, destPath);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const filesToFetch = item.type === "skill" ? ["SKILL.md"] : item.type === "plugin" ? [".claude-plugin/plugin.json"] : [`${item.type}.md`];
|
|
125
|
+
await mkdir(destPath, { recursive: true });
|
|
126
|
+
await Promise.all(filesToFetch.map(async (file) => {
|
|
127
|
+
const content = await fetchRemote(`${remote}/${file}`);
|
|
128
|
+
const filePath = join(destPath, file);
|
|
129
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
130
|
+
await writeFile(filePath, content, "utf-8");
|
|
131
|
+
}));
|
|
132
|
+
}
|
|
133
|
+
async function fetchFileTree(nodes, baseUrl, destPath) {
|
|
134
|
+
await Promise.all(nodes.map(async (node) => {
|
|
135
|
+
const nodePath = join(destPath, node.name);
|
|
136
|
+
if (node.type === "directory") {
|
|
137
|
+
await mkdir(nodePath, { recursive: true });
|
|
138
|
+
if (node.children) {
|
|
139
|
+
await fetchFileTree(node.children, `${baseUrl}/${node.name}`, nodePath);
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
const content = await fetchRemote(`${baseUrl}/${node.name}`);
|
|
143
|
+
await writeFile(nodePath, content, "utf-8");
|
|
144
|
+
}
|
|
145
|
+
}));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// src/config/agents.ts
|
|
149
|
+
import { homedir } from "os";
|
|
150
|
+
import { join as join2 } from "path";
|
|
151
|
+
var home = homedir();
|
|
152
|
+
var CODING_AGENTS = {
|
|
153
|
+
claude: {
|
|
154
|
+
name: "Claude Code",
|
|
155
|
+
shortName: "claude",
|
|
156
|
+
projectRoot: ".claude",
|
|
157
|
+
userRoot: join2(home, ".claude"),
|
|
158
|
+
contentTypes: {
|
|
159
|
+
skill: {
|
|
160
|
+
path: "skills",
|
|
161
|
+
extension: ".md",
|
|
162
|
+
structure: "directory",
|
|
163
|
+
mainFile: "SKILL.md"
|
|
164
|
+
},
|
|
165
|
+
command: {
|
|
166
|
+
path: "commands",
|
|
167
|
+
extension: ".md",
|
|
168
|
+
structure: "directory",
|
|
169
|
+
mainFile: "COMMAND.md"
|
|
170
|
+
},
|
|
171
|
+
agent: {
|
|
172
|
+
path: "agents",
|
|
173
|
+
extension: ".md",
|
|
174
|
+
structure: "file"
|
|
175
|
+
},
|
|
176
|
+
hook: {
|
|
177
|
+
path: "",
|
|
178
|
+
extension: ".json",
|
|
179
|
+
structure: "json-merge",
|
|
180
|
+
mergeTarget: "settings.json",
|
|
181
|
+
mergeField: "hooks"
|
|
182
|
+
},
|
|
183
|
+
plugin: {
|
|
184
|
+
path: "plugins/cache",
|
|
185
|
+
extension: "",
|
|
186
|
+
structure: "plugin"
|
|
187
|
+
},
|
|
188
|
+
settings: {
|
|
189
|
+
path: "",
|
|
190
|
+
extension: ".json",
|
|
191
|
+
structure: "json-merge",
|
|
192
|
+
mergeTarget: "settings.json"
|
|
193
|
+
},
|
|
194
|
+
mcp: {
|
|
195
|
+
path: "",
|
|
196
|
+
extension: ".json",
|
|
197
|
+
structure: "json-merge",
|
|
198
|
+
mergeTarget: ".mcp.json",
|
|
199
|
+
mergeField: "mcpServers"
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
copilot: {
|
|
204
|
+
name: "GitHub Copilot",
|
|
205
|
+
shortName: "copilot",
|
|
206
|
+
projectRoot: ".github",
|
|
207
|
+
userRoot: join2(home, ".github"),
|
|
208
|
+
contentTypes: {
|
|
209
|
+
skill: {
|
|
210
|
+
path: "skills",
|
|
211
|
+
extension: ".md",
|
|
212
|
+
structure: "directory",
|
|
213
|
+
mainFile: "SKILL.md"
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
gemini: {
|
|
218
|
+
name: "Gemini Code Assist",
|
|
219
|
+
shortName: "gemini",
|
|
220
|
+
projectRoot: ".gemini",
|
|
221
|
+
userRoot: join2(home, ".gemini"),
|
|
222
|
+
contentTypes: {
|
|
223
|
+
skill: {
|
|
224
|
+
path: "skills",
|
|
225
|
+
extension: ".md",
|
|
226
|
+
structure: "directory",
|
|
227
|
+
mainFile: "SKILL.md"
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
codex: {
|
|
232
|
+
name: "OpenAI Codex CLI",
|
|
233
|
+
shortName: "codex",
|
|
234
|
+
projectRoot: ".codex",
|
|
235
|
+
userRoot: join2(home, ".codex"),
|
|
236
|
+
contentTypes: {
|
|
237
|
+
skill: {
|
|
238
|
+
path: "skills",
|
|
239
|
+
extension: ".md",
|
|
240
|
+
structure: "directory",
|
|
241
|
+
mainFile: "SKILL.md"
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
opencode: {
|
|
246
|
+
name: "OpenCode",
|
|
247
|
+
shortName: "opencode",
|
|
248
|
+
projectRoot: ".opencode",
|
|
249
|
+
userRoot: join2(home, ".opencode"),
|
|
250
|
+
contentTypes: {
|
|
251
|
+
skill: {
|
|
252
|
+
path: "skills",
|
|
253
|
+
extension: ".md",
|
|
254
|
+
structure: "directory",
|
|
255
|
+
mainFile: "SKILL.md"
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
var ALL_AGENTS = Object.keys(CODING_AGENTS);
|
|
261
|
+
function getAgentConfig(agent) {
|
|
262
|
+
return CODING_AGENTS[agent];
|
|
263
|
+
}
|
|
264
|
+
function getContentTypeConfig(agent, type) {
|
|
265
|
+
return CODING_AGENTS[agent].contentTypes[type];
|
|
266
|
+
}
|
|
267
|
+
function getAgentRoot(agent, scope, cwd = process.cwd()) {
|
|
268
|
+
const config = CODING_AGENTS[agent];
|
|
269
|
+
switch (scope) {
|
|
270
|
+
case "project":
|
|
271
|
+
case "local":
|
|
272
|
+
return join2(cwd, config.projectRoot);
|
|
273
|
+
case "user":
|
|
274
|
+
return config.userRoot;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
function getContentPath(agent, type, scope, cwd = process.cwd()) {
|
|
278
|
+
const typeConfig = getContentTypeConfig(agent, type);
|
|
279
|
+
if (!typeConfig) return void 0;
|
|
280
|
+
const root = getAgentRoot(agent, scope, cwd);
|
|
281
|
+
return typeConfig.path ? join2(root, typeConfig.path) : root;
|
|
282
|
+
}
|
|
283
|
+
function getSettingsPath(scope, cwd = process.cwd()) {
|
|
284
|
+
switch (scope) {
|
|
285
|
+
case "project":
|
|
286
|
+
return join2(cwd, ".claude/settings.json");
|
|
287
|
+
case "user":
|
|
288
|
+
return join2(home, ".claude/settings.json");
|
|
289
|
+
case "local":
|
|
290
|
+
return join2(cwd, ".claude/settings.local.json");
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
function getMcpPath(scope, cwd = process.cwd()) {
|
|
294
|
+
switch (scope) {
|
|
295
|
+
case "project":
|
|
296
|
+
case "local":
|
|
297
|
+
return join2(cwd, ".mcp.json");
|
|
298
|
+
case "user":
|
|
299
|
+
return join2(home, ".claude.json");
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
function getAgentPath(agent, scope, cwd = process.cwd()) {
|
|
303
|
+
return getContentPath(agent, "skill", scope, cwd) || "";
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// src/utils/fs.ts
|
|
307
|
+
import {
|
|
308
|
+
access,
|
|
309
|
+
mkdir as mkdir2,
|
|
310
|
+
symlink,
|
|
311
|
+
copyFile,
|
|
312
|
+
readFile as readFile2,
|
|
313
|
+
writeFile as writeFile2,
|
|
314
|
+
unlink,
|
|
315
|
+
readlink,
|
|
316
|
+
lstat,
|
|
317
|
+
cp,
|
|
318
|
+
rm
|
|
319
|
+
} from "fs/promises";
|
|
320
|
+
import { dirname as dirname2, join as join3, relative, isAbsolute } from "path";
|
|
321
|
+
async function exists(path) {
|
|
322
|
+
try {
|
|
323
|
+
await access(path);
|
|
324
|
+
return true;
|
|
325
|
+
} catch {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
async function ensureDir(path) {
|
|
330
|
+
await mkdir2(path, { recursive: true });
|
|
331
|
+
}
|
|
332
|
+
async function installFile(source, destination, method) {
|
|
333
|
+
await ensureDir(dirname2(destination));
|
|
334
|
+
try {
|
|
335
|
+
await unlink(destination);
|
|
336
|
+
} catch (e) {
|
|
337
|
+
if (e.code !== "ENOENT") throw e;
|
|
338
|
+
}
|
|
339
|
+
if (method === "symlink") {
|
|
340
|
+
const relPath = relative(dirname2(destination), source);
|
|
341
|
+
await symlink(relPath, destination);
|
|
342
|
+
} else {
|
|
343
|
+
await copyFile(source, destination);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
async function removeFile(path) {
|
|
347
|
+
try {
|
|
348
|
+
await unlink(path);
|
|
349
|
+
return true;
|
|
350
|
+
} catch {
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
async function writeTextFile(path, content) {
|
|
355
|
+
await ensureDir(dirname2(path));
|
|
356
|
+
await writeFile2(path, content, "utf-8");
|
|
357
|
+
}
|
|
358
|
+
function getAgentsPath(contentType, slug, cwd) {
|
|
359
|
+
return join3(cwd, ".agents", contentType + "s", slug);
|
|
360
|
+
}
|
|
361
|
+
async function copyDirectory(source, destination) {
|
|
362
|
+
await cp(source, destination, { recursive: true });
|
|
363
|
+
}
|
|
364
|
+
async function installDirectory(source, destination, method) {
|
|
365
|
+
await ensureDir(dirname2(destination));
|
|
366
|
+
await rm(destination, { recursive: true, force: true });
|
|
367
|
+
if (method === "symlink") {
|
|
368
|
+
const relPath = relative(dirname2(destination), source);
|
|
369
|
+
await symlink(relPath, destination);
|
|
370
|
+
} else {
|
|
371
|
+
await copyDirectory(source, destination);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// src/utils/detection.ts
|
|
376
|
+
async function detectInstalledAgents(cwd = process.cwd()) {
|
|
377
|
+
const checks = ALL_AGENTS.flatMap((agent) => {
|
|
378
|
+
const projectPath = getAgentPath(agent, "project", cwd);
|
|
379
|
+
const userPath = getAgentPath(agent, "user", cwd);
|
|
380
|
+
return [
|
|
381
|
+
exists(projectPath).then((found) => found ? { agent, scope: "project", path: projectPath } : null),
|
|
382
|
+
exists(userPath).then((found) => found ? { agent, scope: "user", path: userPath } : null)
|
|
383
|
+
];
|
|
384
|
+
});
|
|
385
|
+
const results = await Promise.all(checks);
|
|
386
|
+
return results.filter((r) => r !== null);
|
|
387
|
+
}
|
|
388
|
+
async function detectProjectAgents(cwd = process.cwd()) {
|
|
389
|
+
const checks = ALL_AGENTS.map(async (agent) => {
|
|
390
|
+
const projectPath = getAgentPath(agent, "project", cwd);
|
|
391
|
+
return await exists(projectPath) ? agent : null;
|
|
392
|
+
});
|
|
393
|
+
const results = await Promise.all(checks);
|
|
394
|
+
return results.filter((a) => a !== null);
|
|
395
|
+
}
|
|
396
|
+
async function isAgentInstalled(agent, scope, cwd = process.cwd()) {
|
|
397
|
+
const effectiveScope = scope === "local" ? "project" : scope;
|
|
398
|
+
const path = getAgentPath(agent, effectiveScope, cwd);
|
|
399
|
+
return exists(path);
|
|
400
|
+
}
|
|
401
|
+
function parseAgentArg(arg) {
|
|
402
|
+
const normalized = arg.toLowerCase().trim();
|
|
403
|
+
if (ALL_AGENTS.includes(normalized)) {
|
|
404
|
+
return normalized;
|
|
405
|
+
}
|
|
406
|
+
const aliases = {
|
|
407
|
+
"claude-code": "claude",
|
|
408
|
+
claudecode: "claude",
|
|
409
|
+
cc: "claude",
|
|
410
|
+
"github-copilot": "copilot",
|
|
411
|
+
gh: "copilot",
|
|
412
|
+
"gemini-code": "gemini",
|
|
413
|
+
gca: "gemini",
|
|
414
|
+
"openai-codex": "codex",
|
|
415
|
+
oc: "opencode"
|
|
416
|
+
};
|
|
417
|
+
return aliases[normalized] ?? null;
|
|
418
|
+
}
|
|
419
|
+
function parseAgentsArg(agents, allAgents) {
|
|
420
|
+
if (agents === "all") {
|
|
421
|
+
return allAgents;
|
|
422
|
+
}
|
|
423
|
+
return agents.split(",").map((a) => parseAgentArg(a.trim())).filter((a) => a !== null);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// src/utils/ui.ts
|
|
427
|
+
import * as p from "@clack/prompts";
|
|
428
|
+
import chalk from "chalk";
|
|
429
|
+
var brand = chalk.hex("#22c55e");
|
|
430
|
+
var bgBrand = chalk.bgHex("#22c55e").black;
|
|
431
|
+
var LOGO = `
|
|
432
|
+
\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557
|
|
433
|
+
\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
|
|
434
|
+
\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D
|
|
435
|
+
\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
|
|
436
|
+
\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551
|
|
437
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D`;
|
|
438
|
+
var URLS = {
|
|
439
|
+
seedr: "https://seedr.danieldeusing.de"
|
|
440
|
+
};
|
|
441
|
+
function printLogo() {
|
|
442
|
+
console.log(brand(LOGO));
|
|
443
|
+
console.log(brand(" \u{1F331} Seed your Coding Agents with capabilities"));
|
|
444
|
+
console.log(chalk.gray(` ${URLS.seedr}`));
|
|
445
|
+
console.log();
|
|
446
|
+
}
|
|
447
|
+
async function selectSkill(items) {
|
|
448
|
+
const result = await p.select({
|
|
449
|
+
message: "Select a skill to install",
|
|
450
|
+
options: items.map((item) => ({
|
|
451
|
+
label: item.name,
|
|
452
|
+
value: item,
|
|
453
|
+
hint: item.description
|
|
454
|
+
}))
|
|
455
|
+
});
|
|
456
|
+
return result;
|
|
457
|
+
}
|
|
458
|
+
async function selectAgents(compatible) {
|
|
459
|
+
const allOption = await p.select({
|
|
460
|
+
message: "Which coding agents do you want to install for?",
|
|
461
|
+
options: [
|
|
462
|
+
{ label: `All (${compatible.length} agents)`, value: "all" },
|
|
463
|
+
{ label: "Select specific agents...", value: "select" }
|
|
464
|
+
]
|
|
465
|
+
});
|
|
466
|
+
if (p.isCancel(allOption)) return allOption;
|
|
467
|
+
if (allOption === "all") return compatible;
|
|
468
|
+
const result = await p.multiselect({
|
|
469
|
+
message: "Select agents",
|
|
470
|
+
options: compatible.map((agent) => ({
|
|
471
|
+
label: CODING_AGENTS[agent].name,
|
|
472
|
+
value: agent,
|
|
473
|
+
hint: CODING_AGENTS[agent].projectRoot
|
|
474
|
+
})),
|
|
475
|
+
initialValues: ["claude"],
|
|
476
|
+
required: true
|
|
477
|
+
});
|
|
478
|
+
return result;
|
|
479
|
+
}
|
|
480
|
+
async function selectScope(includeLocal = false) {
|
|
481
|
+
const options = [
|
|
482
|
+
{ label: "Project", value: "project", hint: includeLocal ? "current directory, settings.json" : "current directory" },
|
|
483
|
+
{ label: "User", value: "user", hint: "home directory" },
|
|
484
|
+
...includeLocal ? [{ label: "Local", value: "local", hint: "current directory, settings.local.json" }] : []
|
|
485
|
+
];
|
|
486
|
+
const result = await p.select({ message: "Installation scope", options });
|
|
487
|
+
return result;
|
|
488
|
+
}
|
|
489
|
+
async function selectMethod(symlinkPath) {
|
|
490
|
+
const result = await p.select({
|
|
491
|
+
message: "Installation method",
|
|
492
|
+
options: [
|
|
493
|
+
{ label: "Symlink", value: "symlink", hint: `shared at ${symlinkPath}` },
|
|
494
|
+
{ label: "Copy", value: "copy", hint: "standalone copy per agent" }
|
|
495
|
+
]
|
|
496
|
+
});
|
|
497
|
+
return result;
|
|
498
|
+
}
|
|
499
|
+
async function confirm2(message) {
|
|
500
|
+
return p.confirm({ message });
|
|
501
|
+
}
|
|
502
|
+
function cancelled() {
|
|
503
|
+
p.cancel("Operation cancelled");
|
|
504
|
+
process.exit(0);
|
|
505
|
+
}
|
|
506
|
+
function intro2(message) {
|
|
507
|
+
p.intro(bgBrand(` ${message} `));
|
|
508
|
+
}
|
|
509
|
+
function outro2(message) {
|
|
510
|
+
p.outro(brand(message));
|
|
511
|
+
}
|
|
512
|
+
function step(message) {
|
|
513
|
+
p.log.step(message);
|
|
514
|
+
}
|
|
515
|
+
function info(message) {
|
|
516
|
+
p.log.info(message);
|
|
517
|
+
}
|
|
518
|
+
function success(message) {
|
|
519
|
+
p.log.success(message);
|
|
520
|
+
}
|
|
521
|
+
function warn(message) {
|
|
522
|
+
p.log.warn(message);
|
|
523
|
+
}
|
|
524
|
+
function error(message) {
|
|
525
|
+
p.log.error(message);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// src/handlers/skill.ts
|
|
529
|
+
import { join as join4, relative as relative2, dirname as dirname3 } from "path";
|
|
530
|
+
import { readdir as readdir2, symlink as symlink2, rm as rm2 } from "fs/promises";
|
|
531
|
+
import chalk2 from "chalk";
|
|
532
|
+
import ora from "ora";
|
|
533
|
+
async function installToCentralLocation(item, sourcePath, cwd) {
|
|
534
|
+
const centralPath = getAgentsPath("skill", item.slug, cwd);
|
|
535
|
+
await rm2(centralPath, { recursive: true, force: true });
|
|
536
|
+
if (sourcePath && await exists(sourcePath)) {
|
|
537
|
+
await copyDirectory(sourcePath, centralPath);
|
|
538
|
+
} else {
|
|
539
|
+
await fetchItemToDestination(item, centralPath);
|
|
540
|
+
}
|
|
541
|
+
return centralPath;
|
|
542
|
+
}
|
|
543
|
+
async function createAgentSymlink(centralPath, destPath) {
|
|
544
|
+
await ensureDir(dirname3(destPath));
|
|
545
|
+
await rm2(destPath, { recursive: true, force: true });
|
|
546
|
+
const relPath = relative2(dirname3(destPath), centralPath);
|
|
547
|
+
await symlink2(relPath, destPath);
|
|
548
|
+
}
|
|
549
|
+
async function installSkillForAgent(item, agent, scope, method, cwd, centralPath) {
|
|
550
|
+
const spinner = ora(
|
|
551
|
+
`Installing ${item.name} for ${CODING_AGENTS[agent].name}...`
|
|
552
|
+
).start();
|
|
553
|
+
try {
|
|
554
|
+
const destDir = getContentPath(agent, "skill", scope, cwd);
|
|
555
|
+
if (!destDir) {
|
|
556
|
+
throw new Error(`${CODING_AGENTS[agent].name} does not support skills`);
|
|
557
|
+
}
|
|
558
|
+
const destPath = join4(destDir, item.slug);
|
|
559
|
+
const sourcePath = getItemSourcePath(item);
|
|
560
|
+
if (method === "symlink" && centralPath) {
|
|
561
|
+
await createAgentSymlink(centralPath, destPath);
|
|
562
|
+
} else if (sourcePath && await exists(sourcePath)) {
|
|
563
|
+
await installDirectory(sourcePath, destPath, "copy");
|
|
564
|
+
} else {
|
|
565
|
+
await fetchItemToDestination(item, destPath);
|
|
566
|
+
}
|
|
567
|
+
spinner.succeed(
|
|
568
|
+
brand(`Installed ${item.name} for ${CODING_AGENTS[agent].name}`)
|
|
569
|
+
);
|
|
570
|
+
return { agent, success: true, path: destPath };
|
|
571
|
+
} catch (error2) {
|
|
572
|
+
const errorMsg = error2 instanceof Error ? error2.message : "Unknown error";
|
|
573
|
+
spinner.fail(
|
|
574
|
+
chalk2.red(`Failed to install for ${CODING_AGENTS[agent].name}: ${errorMsg}`)
|
|
575
|
+
);
|
|
576
|
+
return { agent, success: false, path: "", error: errorMsg };
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
async function installSkill(item, agents, scope, method, cwd = process.cwd()) {
|
|
580
|
+
const results = [];
|
|
581
|
+
const sourcePath = getItemSourcePath(item);
|
|
582
|
+
let centralPath;
|
|
583
|
+
if (method === "symlink") {
|
|
584
|
+
centralPath = await installToCentralLocation(item, sourcePath, cwd);
|
|
585
|
+
}
|
|
586
|
+
for (const agent of agents) {
|
|
587
|
+
const readsAgentsDir = agent === "gemini" || agent === "codex" || agent === "opencode";
|
|
588
|
+
if (readsAgentsDir && method === "symlink" && centralPath) {
|
|
589
|
+
results.push({ agent, success: true, path: centralPath });
|
|
590
|
+
continue;
|
|
591
|
+
}
|
|
592
|
+
const result = await installSkillForAgent(
|
|
593
|
+
item,
|
|
594
|
+
agent,
|
|
595
|
+
scope,
|
|
596
|
+
method,
|
|
597
|
+
cwd,
|
|
598
|
+
centralPath
|
|
599
|
+
);
|
|
600
|
+
results.push(result);
|
|
601
|
+
}
|
|
602
|
+
return results;
|
|
603
|
+
}
|
|
604
|
+
async function uninstallSkill(slug, agent, scope, cwd = process.cwd()) {
|
|
605
|
+
const destDir = getContentPath(agent, "skill", scope, cwd);
|
|
606
|
+
if (!destDir) return false;
|
|
607
|
+
const destPath = join4(destDir, slug);
|
|
608
|
+
if (!await exists(destPath)) {
|
|
609
|
+
return false;
|
|
610
|
+
}
|
|
611
|
+
await rm2(destPath, { recursive: true });
|
|
612
|
+
return true;
|
|
613
|
+
}
|
|
614
|
+
async function getInstalledSkills(agent, scope, cwd = process.cwd()) {
|
|
615
|
+
const destDir = getContentPath(agent, "skill", scope, cwd);
|
|
616
|
+
if (!destDir || !await exists(destDir)) {
|
|
617
|
+
return [];
|
|
618
|
+
}
|
|
619
|
+
const entries = await readdir2(destDir, { withFileTypes: true });
|
|
620
|
+
return entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
621
|
+
}
|
|
622
|
+
var skillHandler = {
|
|
623
|
+
type: "skill",
|
|
624
|
+
async install(item, agents, scope, method, cwd) {
|
|
625
|
+
return installSkill(item, agents, scope, method, cwd);
|
|
626
|
+
},
|
|
627
|
+
async uninstall(slug, agent, scope, cwd) {
|
|
628
|
+
return uninstallSkill(slug, agent, scope, cwd);
|
|
629
|
+
},
|
|
630
|
+
async listInstalled(agent, scope, cwd) {
|
|
631
|
+
return getInstalledSkills(agent, scope, cwd);
|
|
632
|
+
}
|
|
633
|
+
};
|
|
634
|
+
|
|
635
|
+
export {
|
|
636
|
+
loadManifest,
|
|
637
|
+
getItem,
|
|
638
|
+
listItems,
|
|
639
|
+
searchItems,
|
|
640
|
+
getItemContent,
|
|
641
|
+
getItemSourcePath,
|
|
642
|
+
fetchItemToDestination,
|
|
643
|
+
exists,
|
|
644
|
+
ensureDir,
|
|
645
|
+
installFile,
|
|
646
|
+
removeFile,
|
|
647
|
+
writeTextFile,
|
|
648
|
+
getAgentsPath,
|
|
649
|
+
installDirectory,
|
|
650
|
+
CODING_AGENTS,
|
|
651
|
+
ALL_AGENTS,
|
|
652
|
+
getAgentConfig,
|
|
653
|
+
getContentPath,
|
|
654
|
+
getSettingsPath,
|
|
655
|
+
getMcpPath,
|
|
656
|
+
getAgentPath,
|
|
657
|
+
detectInstalledAgents,
|
|
658
|
+
detectProjectAgents,
|
|
659
|
+
isAgentInstalled,
|
|
660
|
+
parseAgentsArg,
|
|
661
|
+
p,
|
|
662
|
+
brand,
|
|
663
|
+
printLogo,
|
|
664
|
+
selectSkill,
|
|
665
|
+
selectAgents,
|
|
666
|
+
selectScope,
|
|
667
|
+
selectMethod,
|
|
668
|
+
confirm2 as confirm,
|
|
669
|
+
cancelled,
|
|
670
|
+
intro2 as intro,
|
|
671
|
+
outro2 as outro,
|
|
672
|
+
step,
|
|
673
|
+
info,
|
|
674
|
+
success,
|
|
675
|
+
warn,
|
|
676
|
+
error,
|
|
677
|
+
installSkill,
|
|
678
|
+
uninstallSkill,
|
|
679
|
+
getInstalledSkills,
|
|
680
|
+
skillHandler
|
|
681
|
+
};
|
package/dist/cli.d.ts
ADDED