@synapsync/synk 1.0.0 → 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.
- package/dist/cli.mjs +1237 -1031
- package/package.json +10 -7
- /package/bin/{cli.mjs → cli.js} +0 -0
package/dist/cli.mjs
CHANGED
|
@@ -15,7 +15,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
|
15
15
|
import { basename, dirname, isAbsolute, join, normalize, relative, resolve, sep } from "path";
|
|
16
16
|
import { fileURLToPath } from "url";
|
|
17
17
|
import { homedir, platform, tmpdir } from "os";
|
|
18
|
-
import { access, cp, lstat, mkdir, mkdtemp, readFile, readdir, readlink, rm, stat, symlink, writeFile } from "fs/promises";
|
|
18
|
+
import { access, cp, lstat, mkdir, mkdtemp, readFile, readdir, readlink, rename, rm, stat, symlink, writeFile } from "fs/promises";
|
|
19
19
|
import "crypto";
|
|
20
20
|
import { execSync, spawnSync } from "child_process";
|
|
21
21
|
import * as readline from "readline";
|
|
@@ -110,6 +110,17 @@ const logger = {
|
|
|
110
110
|
console.log(` ${message}`);
|
|
111
111
|
}
|
|
112
112
|
};
|
|
113
|
+
const COGNITIVE_SUBDIRS = {
|
|
114
|
+
skill: "skills",
|
|
115
|
+
agent: "agents",
|
|
116
|
+
prompt: "prompts"
|
|
117
|
+
};
|
|
118
|
+
const COGNITIVE_FILE_NAMES = {
|
|
119
|
+
skill: "SKILL.md",
|
|
120
|
+
agent: "AGENT.md",
|
|
121
|
+
prompt: "PROMPT.md"
|
|
122
|
+
};
|
|
123
|
+
const AGENTS_DIR$1 = ".agents";
|
|
113
124
|
function getOwnerRepo(parsed) {
|
|
114
125
|
if (parsed.type === "local") return null;
|
|
115
126
|
if (!parsed.url.startsWith("http://") && !parsed.url.startsWith("https://")) return null;
|
|
@@ -140,9 +151,14 @@ async function isRepoPrivate(owner, repo) {
|
|
|
140
151
|
function isLocalPath(input) {
|
|
141
152
|
return isAbsolute(input) || input.startsWith("./") || input.startsWith("../") || input === "." || input === ".." || /^[a-zA-Z]:[/\\]/.test(input);
|
|
142
153
|
}
|
|
143
|
-
|
|
154
|
+
const cognitiveFileNamesLower = new Set(Object.values(COGNITIVE_FILE_NAMES).map((n) => n.toLowerCase()));
|
|
155
|
+
function endsWithCognitiveFile(input) {
|
|
156
|
+
const lower = input.toLowerCase();
|
|
157
|
+
return [...cognitiveFileNamesLower].some((f) => lower.endsWith("/" + f));
|
|
158
|
+
}
|
|
159
|
+
function isDirectCognitiveUrl(input) {
|
|
144
160
|
if (!input.startsWith("http://") && !input.startsWith("https://")) return false;
|
|
145
|
-
if (!input
|
|
161
|
+
if (!endsWithCognitiveFile(input)) return false;
|
|
146
162
|
if (input.includes("github.com/") && !input.includes("raw.githubusercontent.com")) {
|
|
147
163
|
if (!input.includes("/blob/") && !input.includes("/raw/")) return false;
|
|
148
164
|
}
|
|
@@ -158,7 +174,7 @@ function parseSource(input) {
|
|
|
158
174
|
localPath: resolvedPath
|
|
159
175
|
};
|
|
160
176
|
}
|
|
161
|
-
if (
|
|
177
|
+
if (isDirectCognitiveUrl(input)) return {
|
|
162
178
|
type: "direct-url",
|
|
163
179
|
url: input
|
|
164
180
|
};
|
|
@@ -253,7 +269,7 @@ function isWellKnownUrl(input) {
|
|
|
253
269
|
"huggingface.co",
|
|
254
270
|
"raw.githubusercontent.com"
|
|
255
271
|
].includes(parsed.hostname)) return false;
|
|
256
|
-
if (input
|
|
272
|
+
if (endsWithCognitiveFile(input)) return false;
|
|
257
273
|
if (input.endsWith(".git")) return false;
|
|
258
274
|
return true;
|
|
259
275
|
} catch {
|
|
@@ -265,41 +281,86 @@ const configHome = xdgConfig ?? join(home, ".config");
|
|
|
265
281
|
const codexHome = process.env.CODEX_HOME?.trim() || join(home, ".codex");
|
|
266
282
|
const claudeHome = process.env.CLAUDE_CONFIG_DIR?.trim() || join(home, ".claude");
|
|
267
283
|
const agents = {
|
|
268
|
-
|
|
284
|
+
"adal": {
|
|
285
|
+
name: "adal",
|
|
286
|
+
displayName: "AdaL",
|
|
287
|
+
dirs: {
|
|
288
|
+
skill: {
|
|
289
|
+
local: ".adal/skills",
|
|
290
|
+
global: join(join(home, ".adal"), "skills")
|
|
291
|
+
},
|
|
292
|
+
agent: {
|
|
293
|
+
local: ".adal/agents",
|
|
294
|
+
global: join(join(home, ".adal"), "agents")
|
|
295
|
+
},
|
|
296
|
+
prompt: {
|
|
297
|
+
local: ".adal/prompts",
|
|
298
|
+
global: join(join(home, ".adal"), "prompts")
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
detectInstalled: async () => {
|
|
302
|
+
return existsSync(join(home, ".adal"));
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
"amp": {
|
|
269
306
|
name: "amp",
|
|
270
307
|
displayName: "Amp",
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
308
|
+
dirs: {
|
|
309
|
+
skill: {
|
|
310
|
+
local: ".agents/skills",
|
|
311
|
+
global: join(join(configHome, "agents"), "skills")
|
|
312
|
+
},
|
|
313
|
+
agent: {
|
|
314
|
+
local: ".agents/agents",
|
|
315
|
+
global: join(join(configHome, "agents"), "agents")
|
|
316
|
+
},
|
|
317
|
+
prompt: {
|
|
318
|
+
local: ".agents/prompts",
|
|
319
|
+
global: join(join(configHome, "agents"), "prompts")
|
|
320
|
+
}
|
|
321
|
+
},
|
|
277
322
|
detectInstalled: async () => {
|
|
278
323
|
return existsSync(join(configHome, "amp"));
|
|
279
324
|
}
|
|
280
325
|
},
|
|
281
|
-
antigravity: {
|
|
326
|
+
"antigravity": {
|
|
282
327
|
name: "antigravity",
|
|
283
328
|
displayName: "Antigravity",
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
329
|
+
dirs: {
|
|
330
|
+
skill: {
|
|
331
|
+
local: ".agent/skills",
|
|
332
|
+
global: join(join(home, ".gemini/antigravity"), "skills")
|
|
333
|
+
},
|
|
334
|
+
agent: {
|
|
335
|
+
local: ".agent/agents",
|
|
336
|
+
global: join(join(home, ".gemini/antigravity"), "agents")
|
|
337
|
+
},
|
|
338
|
+
prompt: {
|
|
339
|
+
local: ".agent/prompts",
|
|
340
|
+
global: join(join(home, ".gemini/antigravity"), "prompts")
|
|
341
|
+
}
|
|
342
|
+
},
|
|
290
343
|
detectInstalled: async () => {
|
|
291
344
|
return existsSync(join(process.cwd(), ".agent")) || existsSync(join(home, ".gemini/antigravity"));
|
|
292
345
|
}
|
|
293
346
|
},
|
|
294
|
-
augment: {
|
|
347
|
+
"augment": {
|
|
295
348
|
name: "augment",
|
|
296
349
|
displayName: "Augment",
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
350
|
+
dirs: {
|
|
351
|
+
skill: {
|
|
352
|
+
local: ".augment/skills",
|
|
353
|
+
global: join(join(home, ".augment"), "skills")
|
|
354
|
+
},
|
|
355
|
+
agent: {
|
|
356
|
+
local: ".augment/agents",
|
|
357
|
+
global: join(join(home, ".augment"), "agents")
|
|
358
|
+
},
|
|
359
|
+
prompt: {
|
|
360
|
+
local: ".augment/prompts",
|
|
361
|
+
global: join(join(home, ".augment"), "prompts")
|
|
362
|
+
}
|
|
363
|
+
},
|
|
303
364
|
detectInstalled: async () => {
|
|
304
365
|
return existsSync(join(home, ".augment"));
|
|
305
366
|
}
|
|
@@ -307,64 +368,83 @@ const agents = {
|
|
|
307
368
|
"claude-code": {
|
|
308
369
|
name: "claude-code",
|
|
309
370
|
displayName: "Claude Code",
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
371
|
+
dirs: {
|
|
372
|
+
skill: {
|
|
373
|
+
local: ".claude/skills",
|
|
374
|
+
global: join(claudeHome, "skills")
|
|
375
|
+
},
|
|
376
|
+
agent: {
|
|
377
|
+
local: ".claude/agents",
|
|
378
|
+
global: join(claudeHome, "agents")
|
|
379
|
+
},
|
|
380
|
+
prompt: {
|
|
381
|
+
local: ".claude/prompts",
|
|
382
|
+
global: join(claudeHome, "prompts")
|
|
383
|
+
}
|
|
384
|
+
},
|
|
316
385
|
detectInstalled: async () => {
|
|
317
386
|
return existsSync(claudeHome);
|
|
318
387
|
}
|
|
319
388
|
},
|
|
320
|
-
|
|
321
|
-
name: "openclaw",
|
|
322
|
-
displayName: "OpenClaw",
|
|
323
|
-
skillsDir: "skills",
|
|
324
|
-
globalSkillsDir: existsSync(join(home, ".openclaw")) ? join(home, ".openclaw/skills") : existsSync(join(home, ".clawdbot")) ? join(home, ".clawdbot/skills") : join(home, ".moltbot/skills"),
|
|
325
|
-
agentsDir: "agents",
|
|
326
|
-
globalAgentsDir: existsSync(join(home, ".openclaw")) ? join(home, ".openclaw/agents") : existsSync(join(home, ".clawdbot")) ? join(home, ".clawdbot/agents") : join(home, ".moltbot/agents"),
|
|
327
|
-
promptsDir: "prompts",
|
|
328
|
-
globalPromptsDir: existsSync(join(home, ".openclaw")) ? join(home, ".openclaw/prompts") : existsSync(join(home, ".clawdbot")) ? join(home, ".clawdbot/prompts") : join(home, ".moltbot/prompts"),
|
|
329
|
-
detectInstalled: async () => {
|
|
330
|
-
return existsSync(join(home, ".openclaw")) || existsSync(join(home, ".clawdbot")) || existsSync(join(home, ".moltbot"));
|
|
331
|
-
}
|
|
332
|
-
},
|
|
333
|
-
cline: {
|
|
389
|
+
"cline": {
|
|
334
390
|
name: "cline",
|
|
335
391
|
displayName: "Cline",
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
392
|
+
dirs: {
|
|
393
|
+
skill: {
|
|
394
|
+
local: ".cline/skills",
|
|
395
|
+
global: join(join(home, ".cline"), "skills")
|
|
396
|
+
},
|
|
397
|
+
agent: {
|
|
398
|
+
local: ".cline/agents",
|
|
399
|
+
global: join(join(home, ".cline"), "agents")
|
|
400
|
+
},
|
|
401
|
+
prompt: {
|
|
402
|
+
local: ".cline/prompts",
|
|
403
|
+
global: join(join(home, ".cline"), "prompts")
|
|
404
|
+
}
|
|
405
|
+
},
|
|
342
406
|
detectInstalled: async () => {
|
|
343
407
|
return existsSync(join(home, ".cline"));
|
|
344
408
|
}
|
|
345
409
|
},
|
|
346
|
-
codebuddy: {
|
|
410
|
+
"codebuddy": {
|
|
347
411
|
name: "codebuddy",
|
|
348
412
|
displayName: "CodeBuddy",
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
413
|
+
dirs: {
|
|
414
|
+
skill: {
|
|
415
|
+
local: ".codebuddy/skills",
|
|
416
|
+
global: join(join(home, ".codebuddy"), "skills")
|
|
417
|
+
},
|
|
418
|
+
agent: {
|
|
419
|
+
local: ".codebuddy/agents",
|
|
420
|
+
global: join(join(home, ".codebuddy"), "agents")
|
|
421
|
+
},
|
|
422
|
+
prompt: {
|
|
423
|
+
local: ".codebuddy/prompts",
|
|
424
|
+
global: join(join(home, ".codebuddy"), "prompts")
|
|
425
|
+
}
|
|
426
|
+
},
|
|
355
427
|
detectInstalled: async () => {
|
|
356
428
|
return existsSync(join(process.cwd(), ".codebuddy")) || existsSync(join(home, ".codebuddy"));
|
|
357
429
|
}
|
|
358
430
|
},
|
|
359
|
-
codex: {
|
|
431
|
+
"codex": {
|
|
360
432
|
name: "codex",
|
|
361
433
|
displayName: "Codex",
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
434
|
+
dirs: {
|
|
435
|
+
skill: {
|
|
436
|
+
local: ".agents/skills",
|
|
437
|
+
global: join(codexHome, "skills")
|
|
438
|
+
},
|
|
439
|
+
agent: {
|
|
440
|
+
local: ".agents/agents",
|
|
441
|
+
global: join(codexHome, "agents")
|
|
442
|
+
},
|
|
443
|
+
prompt: {
|
|
444
|
+
local: ".agents/prompts",
|
|
445
|
+
global: join(codexHome, "prompts")
|
|
446
|
+
}
|
|
447
|
+
},
|
|
368
448
|
detectInstalled: async () => {
|
|
369
449
|
return existsSync(codexHome) || existsSync("/etc/codex");
|
|
370
450
|
}
|
|
@@ -372,64 +452,104 @@ const agents = {
|
|
|
372
452
|
"command-code": {
|
|
373
453
|
name: "command-code",
|
|
374
454
|
displayName: "Command Code",
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
455
|
+
dirs: {
|
|
456
|
+
skill: {
|
|
457
|
+
local: ".commandcode/skills",
|
|
458
|
+
global: join(join(home, ".commandcode"), "skills")
|
|
459
|
+
},
|
|
460
|
+
agent: {
|
|
461
|
+
local: ".commandcode/agents",
|
|
462
|
+
global: join(join(home, ".commandcode"), "agents")
|
|
463
|
+
},
|
|
464
|
+
prompt: {
|
|
465
|
+
local: ".commandcode/prompts",
|
|
466
|
+
global: join(join(home, ".commandcode"), "prompts")
|
|
467
|
+
}
|
|
468
|
+
},
|
|
381
469
|
detectInstalled: async () => {
|
|
382
470
|
return existsSync(join(home, ".commandcode"));
|
|
383
471
|
}
|
|
384
472
|
},
|
|
385
|
-
continue: {
|
|
473
|
+
"continue": {
|
|
386
474
|
name: "continue",
|
|
387
475
|
displayName: "Continue",
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
476
|
+
dirs: {
|
|
477
|
+
skill: {
|
|
478
|
+
local: ".continue/skills",
|
|
479
|
+
global: join(join(home, ".continue"), "skills")
|
|
480
|
+
},
|
|
481
|
+
agent: {
|
|
482
|
+
local: ".continue/agents",
|
|
483
|
+
global: join(join(home, ".continue"), "agents")
|
|
484
|
+
},
|
|
485
|
+
prompt: {
|
|
486
|
+
local: ".continue/prompts",
|
|
487
|
+
global: join(join(home, ".continue"), "prompts")
|
|
488
|
+
}
|
|
489
|
+
},
|
|
394
490
|
detectInstalled: async () => {
|
|
395
491
|
return existsSync(join(process.cwd(), ".continue")) || existsSync(join(home, ".continue"));
|
|
396
492
|
}
|
|
397
493
|
},
|
|
398
|
-
crush: {
|
|
494
|
+
"crush": {
|
|
399
495
|
name: "crush",
|
|
400
496
|
displayName: "Crush",
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
497
|
+
dirs: {
|
|
498
|
+
skill: {
|
|
499
|
+
local: ".crush/skills",
|
|
500
|
+
global: join(join(home, ".config/crush"), "skills")
|
|
501
|
+
},
|
|
502
|
+
agent: {
|
|
503
|
+
local: ".crush/agents",
|
|
504
|
+
global: join(join(home, ".config/crush"), "agents")
|
|
505
|
+
},
|
|
506
|
+
prompt: {
|
|
507
|
+
local: ".crush/prompts",
|
|
508
|
+
global: join(join(home, ".config/crush"), "prompts")
|
|
509
|
+
}
|
|
510
|
+
},
|
|
407
511
|
detectInstalled: async () => {
|
|
408
512
|
return existsSync(join(home, ".config/crush"));
|
|
409
513
|
}
|
|
410
514
|
},
|
|
411
|
-
cursor: {
|
|
515
|
+
"cursor": {
|
|
412
516
|
name: "cursor",
|
|
413
517
|
displayName: "Cursor",
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
518
|
+
dirs: {
|
|
519
|
+
skill: {
|
|
520
|
+
local: ".cursor/skills",
|
|
521
|
+
global: join(join(home, ".cursor"), "skills")
|
|
522
|
+
},
|
|
523
|
+
agent: {
|
|
524
|
+
local: ".cursor/agents",
|
|
525
|
+
global: join(join(home, ".cursor"), "agents")
|
|
526
|
+
},
|
|
527
|
+
prompt: {
|
|
528
|
+
local: ".cursor/prompts",
|
|
529
|
+
global: join(join(home, ".cursor"), "prompts")
|
|
530
|
+
}
|
|
531
|
+
},
|
|
420
532
|
detectInstalled: async () => {
|
|
421
533
|
return existsSync(join(home, ".cursor"));
|
|
422
534
|
}
|
|
423
535
|
},
|
|
424
|
-
droid: {
|
|
536
|
+
"droid": {
|
|
425
537
|
name: "droid",
|
|
426
538
|
displayName: "Droid",
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
539
|
+
dirs: {
|
|
540
|
+
skill: {
|
|
541
|
+
local: ".factory/skills",
|
|
542
|
+
global: join(join(home, ".factory"), "skills")
|
|
543
|
+
},
|
|
544
|
+
agent: {
|
|
545
|
+
local: ".factory/agents",
|
|
546
|
+
global: join(join(home, ".factory"), "agents")
|
|
547
|
+
},
|
|
548
|
+
prompt: {
|
|
549
|
+
local: ".factory/prompts",
|
|
550
|
+
global: join(join(home, ".factory"), "prompts")
|
|
551
|
+
}
|
|
552
|
+
},
|
|
433
553
|
detectInstalled: async () => {
|
|
434
554
|
return existsSync(join(home, ".factory"));
|
|
435
555
|
}
|
|
@@ -437,12 +557,20 @@ const agents = {
|
|
|
437
557
|
"gemini-cli": {
|
|
438
558
|
name: "gemini-cli",
|
|
439
559
|
displayName: "Gemini CLI",
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
560
|
+
dirs: {
|
|
561
|
+
skill: {
|
|
562
|
+
local: ".agents/skills",
|
|
563
|
+
global: join(join(home, ".gemini"), "skills")
|
|
564
|
+
},
|
|
565
|
+
agent: {
|
|
566
|
+
local: ".agents/agents",
|
|
567
|
+
global: join(join(home, ".gemini"), "agents")
|
|
568
|
+
},
|
|
569
|
+
prompt: {
|
|
570
|
+
local: ".agents/prompts",
|
|
571
|
+
global: join(join(home, ".gemini"), "prompts")
|
|
572
|
+
}
|
|
573
|
+
},
|
|
446
574
|
detectInstalled: async () => {
|
|
447
575
|
return existsSync(join(home, ".gemini"));
|
|
448
576
|
}
|
|
@@ -450,64 +578,104 @@ const agents = {
|
|
|
450
578
|
"github-copilot": {
|
|
451
579
|
name: "github-copilot",
|
|
452
580
|
displayName: "GitHub Copilot",
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
581
|
+
dirs: {
|
|
582
|
+
skill: {
|
|
583
|
+
local: ".agents/skills",
|
|
584
|
+
global: join(join(home, ".copilot"), "skills")
|
|
585
|
+
},
|
|
586
|
+
agent: {
|
|
587
|
+
local: ".agents/agents",
|
|
588
|
+
global: join(join(home, ".copilot"), "agents")
|
|
589
|
+
},
|
|
590
|
+
prompt: {
|
|
591
|
+
local: ".agents/prompts",
|
|
592
|
+
global: join(join(home, ".copilot"), "prompts")
|
|
593
|
+
}
|
|
594
|
+
},
|
|
459
595
|
detectInstalled: async () => {
|
|
460
596
|
return existsSync(join(process.cwd(), ".github")) || existsSync(join(home, ".copilot"));
|
|
461
597
|
}
|
|
462
598
|
},
|
|
463
|
-
goose: {
|
|
599
|
+
"goose": {
|
|
464
600
|
name: "goose",
|
|
465
601
|
displayName: "Goose",
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
602
|
+
dirs: {
|
|
603
|
+
skill: {
|
|
604
|
+
local: ".goose/skills",
|
|
605
|
+
global: join(join(configHome, "goose"), "skills")
|
|
606
|
+
},
|
|
607
|
+
agent: {
|
|
608
|
+
local: ".goose/agents",
|
|
609
|
+
global: join(join(configHome, "goose"), "agents")
|
|
610
|
+
},
|
|
611
|
+
prompt: {
|
|
612
|
+
local: ".goose/prompts",
|
|
613
|
+
global: join(join(configHome, "goose"), "prompts")
|
|
614
|
+
}
|
|
615
|
+
},
|
|
472
616
|
detectInstalled: async () => {
|
|
473
617
|
return existsSync(join(configHome, "goose"));
|
|
474
618
|
}
|
|
475
619
|
},
|
|
476
|
-
junie: {
|
|
477
|
-
name: "junie",
|
|
478
|
-
displayName: "Junie",
|
|
479
|
-
skillsDir: ".junie/skills",
|
|
480
|
-
globalSkillsDir: join(home, ".junie/skills"),
|
|
481
|
-
agentsDir: ".junie/agents",
|
|
482
|
-
globalAgentsDir: join(home, ".junie/agents"),
|
|
483
|
-
promptsDir: ".junie/prompts",
|
|
484
|
-
globalPromptsDir: join(home, ".junie/prompts"),
|
|
485
|
-
detectInstalled: async () => {
|
|
486
|
-
return existsSync(join(home, ".junie"));
|
|
487
|
-
}
|
|
488
|
-
},
|
|
489
620
|
"iflow-cli": {
|
|
490
621
|
name: "iflow-cli",
|
|
491
622
|
displayName: "iFlow CLI",
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
623
|
+
dirs: {
|
|
624
|
+
skill: {
|
|
625
|
+
local: ".iflow/skills",
|
|
626
|
+
global: join(join(home, ".iflow"), "skills")
|
|
627
|
+
},
|
|
628
|
+
agent: {
|
|
629
|
+
local: ".iflow/agents",
|
|
630
|
+
global: join(join(home, ".iflow"), "agents")
|
|
631
|
+
},
|
|
632
|
+
prompt: {
|
|
633
|
+
local: ".iflow/prompts",
|
|
634
|
+
global: join(join(home, ".iflow"), "prompts")
|
|
635
|
+
}
|
|
636
|
+
},
|
|
498
637
|
detectInstalled: async () => {
|
|
499
638
|
return existsSync(join(home, ".iflow"));
|
|
500
639
|
}
|
|
501
640
|
},
|
|
502
|
-
|
|
641
|
+
"junie": {
|
|
642
|
+
name: "junie",
|
|
643
|
+
displayName: "Junie",
|
|
644
|
+
dirs: {
|
|
645
|
+
skill: {
|
|
646
|
+
local: ".junie/skills",
|
|
647
|
+
global: join(join(home, ".junie"), "skills")
|
|
648
|
+
},
|
|
649
|
+
agent: {
|
|
650
|
+
local: ".junie/agents",
|
|
651
|
+
global: join(join(home, ".junie"), "agents")
|
|
652
|
+
},
|
|
653
|
+
prompt: {
|
|
654
|
+
local: ".junie/prompts",
|
|
655
|
+
global: join(join(home, ".junie"), "prompts")
|
|
656
|
+
}
|
|
657
|
+
},
|
|
658
|
+
detectInstalled: async () => {
|
|
659
|
+
return existsSync(join(home, ".junie"));
|
|
660
|
+
}
|
|
661
|
+
},
|
|
662
|
+
"kilo": {
|
|
503
663
|
name: "kilo",
|
|
504
664
|
displayName: "Kilo Code",
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
665
|
+
dirs: {
|
|
666
|
+
skill: {
|
|
667
|
+
local: ".kilocode/skills",
|
|
668
|
+
global: join(join(home, ".kilocode"), "skills")
|
|
669
|
+
},
|
|
670
|
+
agent: {
|
|
671
|
+
local: ".kilocode/agents",
|
|
672
|
+
global: join(join(home, ".kilocode"), "agents")
|
|
673
|
+
},
|
|
674
|
+
prompt: {
|
|
675
|
+
local: ".kilocode/prompts",
|
|
676
|
+
global: join(join(home, ".kilocode"), "prompts")
|
|
677
|
+
}
|
|
678
|
+
},
|
|
511
679
|
detectInstalled: async () => {
|
|
512
680
|
return existsSync(join(home, ".kilocode"));
|
|
513
681
|
}
|
|
@@ -515,12 +683,20 @@ const agents = {
|
|
|
515
683
|
"kimi-cli": {
|
|
516
684
|
name: "kimi-cli",
|
|
517
685
|
displayName: "Kimi Code CLI",
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
686
|
+
dirs: {
|
|
687
|
+
skill: {
|
|
688
|
+
local: ".agents/skills",
|
|
689
|
+
global: join(join(home, ".config/agents"), "skills")
|
|
690
|
+
},
|
|
691
|
+
agent: {
|
|
692
|
+
local: ".agents/agents",
|
|
693
|
+
global: join(join(home, ".config/agents"), "agents")
|
|
694
|
+
},
|
|
695
|
+
prompt: {
|
|
696
|
+
local: ".agents/prompts",
|
|
697
|
+
global: join(join(home, ".config/agents"), "prompts")
|
|
698
|
+
}
|
|
699
|
+
},
|
|
524
700
|
detectInstalled: async () => {
|
|
525
701
|
return existsSync(join(home, ".kimi"));
|
|
526
702
|
}
|
|
@@ -528,38 +704,62 @@ const agents = {
|
|
|
528
704
|
"kiro-cli": {
|
|
529
705
|
name: "kiro-cli",
|
|
530
706
|
displayName: "Kiro CLI",
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
707
|
+
dirs: {
|
|
708
|
+
skill: {
|
|
709
|
+
local: ".kiro/skills",
|
|
710
|
+
global: join(join(home, ".kiro"), "skills")
|
|
711
|
+
},
|
|
712
|
+
agent: {
|
|
713
|
+
local: ".kiro/agents",
|
|
714
|
+
global: join(join(home, ".kiro"), "agents")
|
|
715
|
+
},
|
|
716
|
+
prompt: {
|
|
717
|
+
local: ".kiro/prompts",
|
|
718
|
+
global: join(join(home, ".kiro"), "prompts")
|
|
719
|
+
}
|
|
720
|
+
},
|
|
537
721
|
detectInstalled: async () => {
|
|
538
722
|
return existsSync(join(home, ".kiro"));
|
|
539
723
|
}
|
|
540
724
|
},
|
|
541
|
-
kode: {
|
|
725
|
+
"kode": {
|
|
542
726
|
name: "kode",
|
|
543
727
|
displayName: "Kode",
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
728
|
+
dirs: {
|
|
729
|
+
skill: {
|
|
730
|
+
local: ".kode/skills",
|
|
731
|
+
global: join(join(home, ".kode"), "skills")
|
|
732
|
+
},
|
|
733
|
+
agent: {
|
|
734
|
+
local: ".kode/agents",
|
|
735
|
+
global: join(join(home, ".kode"), "agents")
|
|
736
|
+
},
|
|
737
|
+
prompt: {
|
|
738
|
+
local: ".kode/prompts",
|
|
739
|
+
global: join(join(home, ".kode"), "prompts")
|
|
740
|
+
}
|
|
741
|
+
},
|
|
550
742
|
detectInstalled: async () => {
|
|
551
743
|
return existsSync(join(home, ".kode"));
|
|
552
744
|
}
|
|
553
745
|
},
|
|
554
|
-
mcpjam: {
|
|
746
|
+
"mcpjam": {
|
|
555
747
|
name: "mcpjam",
|
|
556
748
|
displayName: "MCPJam",
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
749
|
+
dirs: {
|
|
750
|
+
skill: {
|
|
751
|
+
local: ".mcpjam/skills",
|
|
752
|
+
global: join(join(home, ".mcpjam"), "skills")
|
|
753
|
+
},
|
|
754
|
+
agent: {
|
|
755
|
+
local: ".mcpjam/agents",
|
|
756
|
+
global: join(join(home, ".mcpjam"), "agents")
|
|
757
|
+
},
|
|
758
|
+
prompt: {
|
|
759
|
+
local: ".mcpjam/prompts",
|
|
760
|
+
global: join(join(home, ".mcpjam"), "prompts")
|
|
761
|
+
}
|
|
762
|
+
},
|
|
563
763
|
detectInstalled: async () => {
|
|
564
764
|
return existsSync(join(home, ".mcpjam"));
|
|
565
765
|
}
|
|
@@ -567,77 +767,188 @@ const agents = {
|
|
|
567
767
|
"mistral-vibe": {
|
|
568
768
|
name: "mistral-vibe",
|
|
569
769
|
displayName: "Mistral Vibe",
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
770
|
+
dirs: {
|
|
771
|
+
skill: {
|
|
772
|
+
local: ".vibe/skills",
|
|
773
|
+
global: join(join(home, ".vibe"), "skills")
|
|
774
|
+
},
|
|
775
|
+
agent: {
|
|
776
|
+
local: ".vibe/agents",
|
|
777
|
+
global: join(join(home, ".vibe"), "agents")
|
|
778
|
+
},
|
|
779
|
+
prompt: {
|
|
780
|
+
local: ".vibe/prompts",
|
|
781
|
+
global: join(join(home, ".vibe"), "prompts")
|
|
782
|
+
}
|
|
783
|
+
},
|
|
576
784
|
detectInstalled: async () => {
|
|
577
785
|
return existsSync(join(home, ".vibe"));
|
|
578
786
|
}
|
|
579
787
|
},
|
|
580
|
-
mux: {
|
|
788
|
+
"mux": {
|
|
581
789
|
name: "mux",
|
|
582
790
|
displayName: "Mux",
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
791
|
+
dirs: {
|
|
792
|
+
skill: {
|
|
793
|
+
local: ".mux/skills",
|
|
794
|
+
global: join(join(home, ".mux"), "skills")
|
|
795
|
+
},
|
|
796
|
+
agent: {
|
|
797
|
+
local: ".mux/agents",
|
|
798
|
+
global: join(join(home, ".mux"), "agents")
|
|
799
|
+
},
|
|
800
|
+
prompt: {
|
|
801
|
+
local: ".mux/prompts",
|
|
802
|
+
global: join(join(home, ".mux"), "prompts")
|
|
803
|
+
}
|
|
804
|
+
},
|
|
589
805
|
detectInstalled: async () => {
|
|
590
806
|
return existsSync(join(home, ".mux"));
|
|
591
807
|
}
|
|
592
808
|
},
|
|
593
|
-
|
|
809
|
+
"neovate": {
|
|
810
|
+
name: "neovate",
|
|
811
|
+
displayName: "Neovate",
|
|
812
|
+
dirs: {
|
|
813
|
+
skill: {
|
|
814
|
+
local: ".neovate/skills",
|
|
815
|
+
global: join(join(home, ".neovate"), "skills")
|
|
816
|
+
},
|
|
817
|
+
agent: {
|
|
818
|
+
local: ".neovate/agents",
|
|
819
|
+
global: join(join(home, ".neovate"), "agents")
|
|
820
|
+
},
|
|
821
|
+
prompt: {
|
|
822
|
+
local: ".neovate/prompts",
|
|
823
|
+
global: join(join(home, ".neovate"), "prompts")
|
|
824
|
+
}
|
|
825
|
+
},
|
|
826
|
+
detectInstalled: async () => {
|
|
827
|
+
return existsSync(join(home, ".neovate"));
|
|
828
|
+
}
|
|
829
|
+
},
|
|
830
|
+
"openclaw": {
|
|
831
|
+
name: "openclaw",
|
|
832
|
+
displayName: "OpenClaw",
|
|
833
|
+
dirs: {
|
|
834
|
+
skill: {
|
|
835
|
+
local: "skills",
|
|
836
|
+
global: existsSync(join(home, ".openclaw")) ? join(join(home, ".openclaw"), "skills") : existsSync(join(home, ".clawdbot")) ? join(join(home, ".clawdbot"), "skills") : join(join(home, ".moltbot"), "skills")
|
|
837
|
+
},
|
|
838
|
+
agent: {
|
|
839
|
+
local: "agents",
|
|
840
|
+
global: existsSync(join(home, ".openclaw")) ? join(join(home, ".openclaw"), "agents") : existsSync(join(home, ".clawdbot")) ? join(join(home, ".clawdbot"), "agents") : join(join(home, ".moltbot"), "agents")
|
|
841
|
+
},
|
|
842
|
+
prompt: {
|
|
843
|
+
local: "prompts",
|
|
844
|
+
global: existsSync(join(home, ".openclaw")) ? join(join(home, ".openclaw"), "prompts") : existsSync(join(home, ".clawdbot")) ? join(join(home, ".clawdbot"), "prompts") : join(join(home, ".moltbot"), "prompts")
|
|
845
|
+
}
|
|
846
|
+
},
|
|
847
|
+
detectInstalled: async () => {
|
|
848
|
+
return existsSync(join(home, ".openclaw")) || existsSync(join(home, ".clawdbot")) || existsSync(join(home, ".moltbot"));
|
|
849
|
+
}
|
|
850
|
+
},
|
|
851
|
+
"opencode": {
|
|
594
852
|
name: "opencode",
|
|
595
853
|
displayName: "OpenCode",
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
854
|
+
dirs: {
|
|
855
|
+
skill: {
|
|
856
|
+
local: ".agents/skills",
|
|
857
|
+
global: join(join(configHome, "opencode"), "skills")
|
|
858
|
+
},
|
|
859
|
+
agent: {
|
|
860
|
+
local: ".agents/agents",
|
|
861
|
+
global: join(join(configHome, "opencode"), "agents")
|
|
862
|
+
},
|
|
863
|
+
prompt: {
|
|
864
|
+
local: ".agents/prompts",
|
|
865
|
+
global: join(join(configHome, "opencode"), "prompts")
|
|
866
|
+
}
|
|
867
|
+
},
|
|
602
868
|
detectInstalled: async () => {
|
|
603
869
|
return existsSync(join(configHome, "opencode")) || existsSync(join(claudeHome, "skills"));
|
|
604
870
|
}
|
|
605
871
|
},
|
|
606
|
-
openhands: {
|
|
872
|
+
"openhands": {
|
|
607
873
|
name: "openhands",
|
|
608
874
|
displayName: "OpenHands",
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
875
|
+
dirs: {
|
|
876
|
+
skill: {
|
|
877
|
+
local: ".openhands/skills",
|
|
878
|
+
global: join(join(home, ".openhands"), "skills")
|
|
879
|
+
},
|
|
880
|
+
agent: {
|
|
881
|
+
local: ".openhands/agents",
|
|
882
|
+
global: join(join(home, ".openhands"), "agents")
|
|
883
|
+
},
|
|
884
|
+
prompt: {
|
|
885
|
+
local: ".openhands/prompts",
|
|
886
|
+
global: join(join(home, ".openhands"), "prompts")
|
|
887
|
+
}
|
|
888
|
+
},
|
|
615
889
|
detectInstalled: async () => {
|
|
616
890
|
return existsSync(join(home, ".openhands"));
|
|
617
891
|
}
|
|
618
892
|
},
|
|
619
|
-
pi: {
|
|
893
|
+
"pi": {
|
|
620
894
|
name: "pi",
|
|
621
895
|
displayName: "Pi",
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
896
|
+
dirs: {
|
|
897
|
+
skill: {
|
|
898
|
+
local: ".pi/skills",
|
|
899
|
+
global: join(join(home, ".pi/agent"), "skills")
|
|
900
|
+
},
|
|
901
|
+
agent: {
|
|
902
|
+
local: ".pi/agents",
|
|
903
|
+
global: join(join(home, ".pi/agent"), "agents")
|
|
904
|
+
},
|
|
905
|
+
prompt: {
|
|
906
|
+
local: ".pi/prompts",
|
|
907
|
+
global: join(join(home, ".pi/agent"), "prompts")
|
|
908
|
+
}
|
|
909
|
+
},
|
|
628
910
|
detectInstalled: async () => {
|
|
629
911
|
return existsSync(join(home, ".pi/agent"));
|
|
630
912
|
}
|
|
631
913
|
},
|
|
632
|
-
|
|
914
|
+
"pochi": {
|
|
915
|
+
name: "pochi",
|
|
916
|
+
displayName: "Pochi",
|
|
917
|
+
dirs: {
|
|
918
|
+
skill: {
|
|
919
|
+
local: ".pochi/skills",
|
|
920
|
+
global: join(join(home, ".pochi"), "skills")
|
|
921
|
+
},
|
|
922
|
+
agent: {
|
|
923
|
+
local: ".pochi/agents",
|
|
924
|
+
global: join(join(home, ".pochi"), "agents")
|
|
925
|
+
},
|
|
926
|
+
prompt: {
|
|
927
|
+
local: ".pochi/prompts",
|
|
928
|
+
global: join(join(home, ".pochi"), "prompts")
|
|
929
|
+
}
|
|
930
|
+
},
|
|
931
|
+
detectInstalled: async () => {
|
|
932
|
+
return existsSync(join(home, ".pochi"));
|
|
933
|
+
}
|
|
934
|
+
},
|
|
935
|
+
"qoder": {
|
|
633
936
|
name: "qoder",
|
|
634
937
|
displayName: "Qoder",
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
938
|
+
dirs: {
|
|
939
|
+
skill: {
|
|
940
|
+
local: ".qoder/skills",
|
|
941
|
+
global: join(join(home, ".qoder"), "skills")
|
|
942
|
+
},
|
|
943
|
+
agent: {
|
|
944
|
+
local: ".qoder/agents",
|
|
945
|
+
global: join(join(home, ".qoder"), "agents")
|
|
946
|
+
},
|
|
947
|
+
prompt: {
|
|
948
|
+
local: ".qoder/prompts",
|
|
949
|
+
global: join(join(home, ".qoder"), "prompts")
|
|
950
|
+
}
|
|
951
|
+
},
|
|
641
952
|
detectInstalled: async () => {
|
|
642
953
|
return existsSync(join(home, ".qoder"));
|
|
643
954
|
}
|
|
@@ -645,133 +956,150 @@ const agents = {
|
|
|
645
956
|
"qwen-code": {
|
|
646
957
|
name: "qwen-code",
|
|
647
958
|
displayName: "Qwen Code",
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
959
|
+
dirs: {
|
|
960
|
+
skill: {
|
|
961
|
+
local: ".qwen/skills",
|
|
962
|
+
global: join(join(home, ".qwen"), "skills")
|
|
963
|
+
},
|
|
964
|
+
agent: {
|
|
965
|
+
local: ".qwen/agents",
|
|
966
|
+
global: join(join(home, ".qwen"), "agents")
|
|
967
|
+
},
|
|
968
|
+
prompt: {
|
|
969
|
+
local: ".qwen/prompts",
|
|
970
|
+
global: join(join(home, ".qwen"), "prompts")
|
|
971
|
+
}
|
|
972
|
+
},
|
|
654
973
|
detectInstalled: async () => {
|
|
655
974
|
return existsSync(join(home, ".qwen"));
|
|
656
975
|
}
|
|
657
976
|
},
|
|
658
|
-
replit: {
|
|
977
|
+
"replit": {
|
|
659
978
|
name: "replit",
|
|
660
979
|
displayName: "Replit",
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
980
|
+
dirs: {
|
|
981
|
+
skill: {
|
|
982
|
+
local: ".agents/skills",
|
|
983
|
+
global: join(join(configHome, "agents"), "skills")
|
|
984
|
+
},
|
|
985
|
+
agent: {
|
|
986
|
+
local: ".agents/agents",
|
|
987
|
+
global: join(join(configHome, "agents"), "agents")
|
|
988
|
+
},
|
|
989
|
+
prompt: {
|
|
990
|
+
local: ".agents/prompts",
|
|
991
|
+
global: join(join(configHome, "agents"), "prompts")
|
|
992
|
+
}
|
|
993
|
+
},
|
|
667
994
|
showInUniversalList: false,
|
|
668
995
|
detectInstalled: async () => {
|
|
669
996
|
return existsSync(join(process.cwd(), ".agents"));
|
|
670
997
|
}
|
|
671
998
|
},
|
|
672
|
-
roo: {
|
|
999
|
+
"roo": {
|
|
673
1000
|
name: "roo",
|
|
674
1001
|
displayName: "Roo Code",
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
1002
|
+
dirs: {
|
|
1003
|
+
skill: {
|
|
1004
|
+
local: ".roo/skills",
|
|
1005
|
+
global: join(join(home, ".roo"), "skills")
|
|
1006
|
+
},
|
|
1007
|
+
agent: {
|
|
1008
|
+
local: ".roo/agents",
|
|
1009
|
+
global: join(join(home, ".roo"), "agents")
|
|
1010
|
+
},
|
|
1011
|
+
prompt: {
|
|
1012
|
+
local: ".roo/prompts",
|
|
1013
|
+
global: join(join(home, ".roo"), "prompts")
|
|
1014
|
+
}
|
|
1015
|
+
},
|
|
681
1016
|
detectInstalled: async () => {
|
|
682
1017
|
return existsSync(join(home, ".roo"));
|
|
683
1018
|
}
|
|
684
1019
|
},
|
|
685
|
-
trae: {
|
|
686
|
-
name: "trae",
|
|
687
|
-
displayName: "Trae",
|
|
688
|
-
skillsDir: ".trae/skills",
|
|
689
|
-
globalSkillsDir: join(home, ".trae/skills"),
|
|
690
|
-
agentsDir: ".trae/agents",
|
|
691
|
-
globalAgentsDir: join(home, ".trae/agents"),
|
|
692
|
-
promptsDir: ".trae/prompts",
|
|
693
|
-
globalPromptsDir: join(home, ".trae/prompts"),
|
|
694
|
-
detectInstalled: async () => {
|
|
695
|
-
return existsSync(join(home, ".trae"));
|
|
696
|
-
}
|
|
697
|
-
},
|
|
698
1020
|
"trae-cn": {
|
|
699
1021
|
name: "trae-cn",
|
|
700
1022
|
displayName: "Trae CN",
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
1023
|
+
dirs: {
|
|
1024
|
+
skill: {
|
|
1025
|
+
local: ".trae/skills",
|
|
1026
|
+
global: join(join(home, ".trae-cn"), "skills")
|
|
1027
|
+
},
|
|
1028
|
+
agent: {
|
|
1029
|
+
local: ".trae/agents",
|
|
1030
|
+
global: join(join(home, ".trae-cn"), "agents")
|
|
1031
|
+
},
|
|
1032
|
+
prompt: {
|
|
1033
|
+
local: ".trae/prompts",
|
|
1034
|
+
global: join(join(home, ".trae-cn"), "prompts")
|
|
1035
|
+
}
|
|
1036
|
+
},
|
|
707
1037
|
detectInstalled: async () => {
|
|
708
1038
|
return existsSync(join(home, ".trae-cn"));
|
|
709
1039
|
}
|
|
710
1040
|
},
|
|
711
|
-
|
|
1041
|
+
"trae": {
|
|
1042
|
+
name: "trae",
|
|
1043
|
+
displayName: "Trae",
|
|
1044
|
+
dirs: {
|
|
1045
|
+
skill: {
|
|
1046
|
+
local: ".trae/skills",
|
|
1047
|
+
global: join(join(home, ".trae"), "skills")
|
|
1048
|
+
},
|
|
1049
|
+
agent: {
|
|
1050
|
+
local: ".trae/agents",
|
|
1051
|
+
global: join(join(home, ".trae"), "agents")
|
|
1052
|
+
},
|
|
1053
|
+
prompt: {
|
|
1054
|
+
local: ".trae/prompts",
|
|
1055
|
+
global: join(join(home, ".trae"), "prompts")
|
|
1056
|
+
}
|
|
1057
|
+
},
|
|
1058
|
+
detectInstalled: async () => {
|
|
1059
|
+
return existsSync(join(home, ".trae"));
|
|
1060
|
+
}
|
|
1061
|
+
},
|
|
1062
|
+
"windsurf": {
|
|
712
1063
|
name: "windsurf",
|
|
713
1064
|
displayName: "Windsurf",
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
1065
|
+
dirs: {
|
|
1066
|
+
skill: {
|
|
1067
|
+
local: ".windsurf/skills",
|
|
1068
|
+
global: join(join(home, ".codeium/windsurf"), "skills")
|
|
1069
|
+
},
|
|
1070
|
+
agent: {
|
|
1071
|
+
local: ".windsurf/agents",
|
|
1072
|
+
global: join(join(home, ".codeium/windsurf"), "agents")
|
|
1073
|
+
},
|
|
1074
|
+
prompt: {
|
|
1075
|
+
local: ".windsurf/prompts",
|
|
1076
|
+
global: join(join(home, ".codeium/windsurf"), "prompts")
|
|
1077
|
+
}
|
|
1078
|
+
},
|
|
720
1079
|
detectInstalled: async () => {
|
|
721
1080
|
return existsSync(join(home, ".codeium/windsurf"));
|
|
722
1081
|
}
|
|
723
1082
|
},
|
|
724
|
-
zencoder: {
|
|
1083
|
+
"zencoder": {
|
|
725
1084
|
name: "zencoder",
|
|
726
1085
|
displayName: "Zencoder",
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
1086
|
+
dirs: {
|
|
1087
|
+
skill: {
|
|
1088
|
+
local: ".zencoder/skills",
|
|
1089
|
+
global: join(join(home, ".zencoder"), "skills")
|
|
1090
|
+
},
|
|
1091
|
+
agent: {
|
|
1092
|
+
local: ".zencoder/agents",
|
|
1093
|
+
global: join(join(home, ".zencoder"), "agents")
|
|
1094
|
+
},
|
|
1095
|
+
prompt: {
|
|
1096
|
+
local: ".zencoder/prompts",
|
|
1097
|
+
global: join(join(home, ".zencoder"), "prompts")
|
|
1098
|
+
}
|
|
1099
|
+
},
|
|
733
1100
|
detectInstalled: async () => {
|
|
734
1101
|
return existsSync(join(home, ".zencoder"));
|
|
735
1102
|
}
|
|
736
|
-
},
|
|
737
|
-
neovate: {
|
|
738
|
-
name: "neovate",
|
|
739
|
-
displayName: "Neovate",
|
|
740
|
-
skillsDir: ".neovate/skills",
|
|
741
|
-
globalSkillsDir: join(home, ".neovate/skills"),
|
|
742
|
-
agentsDir: ".neovate/agents",
|
|
743
|
-
globalAgentsDir: join(home, ".neovate/agents"),
|
|
744
|
-
promptsDir: ".neovate/prompts",
|
|
745
|
-
globalPromptsDir: join(home, ".neovate/prompts"),
|
|
746
|
-
detectInstalled: async () => {
|
|
747
|
-
return existsSync(join(home, ".neovate"));
|
|
748
|
-
}
|
|
749
|
-
},
|
|
750
|
-
pochi: {
|
|
751
|
-
name: "pochi",
|
|
752
|
-
displayName: "Pochi",
|
|
753
|
-
skillsDir: ".pochi/skills",
|
|
754
|
-
globalSkillsDir: join(home, ".pochi/skills"),
|
|
755
|
-
agentsDir: ".pochi/agents",
|
|
756
|
-
globalAgentsDir: join(home, ".pochi/agents"),
|
|
757
|
-
promptsDir: ".pochi/prompts",
|
|
758
|
-
globalPromptsDir: join(home, ".pochi/prompts"),
|
|
759
|
-
detectInstalled: async () => {
|
|
760
|
-
return existsSync(join(home, ".pochi"));
|
|
761
|
-
}
|
|
762
|
-
},
|
|
763
|
-
adal: {
|
|
764
|
-
name: "adal",
|
|
765
|
-
displayName: "AdaL",
|
|
766
|
-
skillsDir: ".adal/skills",
|
|
767
|
-
globalSkillsDir: join(home, ".adal/skills"),
|
|
768
|
-
agentsDir: ".adal/agents",
|
|
769
|
-
globalAgentsDir: join(home, ".adal/agents"),
|
|
770
|
-
promptsDir: ".adal/prompts",
|
|
771
|
-
globalPromptsDir: join(home, ".adal/prompts"),
|
|
772
|
-
detectInstalled: async () => {
|
|
773
|
-
return existsSync(join(home, ".adal"));
|
|
774
|
-
}
|
|
775
1103
|
}
|
|
776
1104
|
};
|
|
777
1105
|
async function detectInstalledAgents() {
|
|
@@ -780,55 +1108,29 @@ async function detectInstalledAgents() {
|
|
|
780
1108
|
installed: await config.detectInstalled()
|
|
781
1109
|
})))).filter((r) => r.installed).map((r) => r.type);
|
|
782
1110
|
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
skill: "skills",
|
|
786
|
-
agent: "agents",
|
|
787
|
-
prompt: "prompts"
|
|
788
|
-
};
|
|
789
|
-
const COGNITIVE_FILE_NAMES = {
|
|
790
|
-
skill: "SKILL.md",
|
|
791
|
-
agent: "AGENT.md",
|
|
792
|
-
prompt: "PROMPT.md"
|
|
793
|
-
};
|
|
794
|
-
function getUniversalAgents() {
|
|
795
|
-
return Object.entries(agents).filter(([_, config]) => config.skillsDir === ".agents/skills" && config.showInUniversalList !== false).map(([type]) => type);
|
|
1111
|
+
function getUniversalAgents(cognitiveType = "skill") {
|
|
1112
|
+
return Object.entries(agents).filter(([_, config]) => config.dirs[cognitiveType].local === `.agents/${COGNITIVE_SUBDIRS[cognitiveType]}` && config.showInUniversalList !== false).map(([type]) => type);
|
|
796
1113
|
}
|
|
797
|
-
function getNonUniversalAgents() {
|
|
798
|
-
return Object.entries(agents).filter(([_, config]) => config.
|
|
1114
|
+
function getNonUniversalAgents(cognitiveType = "skill") {
|
|
1115
|
+
return Object.entries(agents).filter(([_, config]) => config.dirs[cognitiveType].local !== `.agents/${COGNITIVE_SUBDIRS[cognitiveType]}`).map(([type]) => type);
|
|
799
1116
|
}
|
|
800
|
-
function isUniversalAgent(type) {
|
|
801
|
-
return agents[type].
|
|
1117
|
+
function isUniversalAgent(type, cognitiveType = "skill") {
|
|
1118
|
+
return agents[type].dirs[cognitiveType].local === `.agents/${COGNITIVE_SUBDIRS[cognitiveType]}`;
|
|
802
1119
|
}
|
|
803
1120
|
function getCognitiveDir(agentType, cognitiveType, scope) {
|
|
804
|
-
const
|
|
805
|
-
|
|
806
|
-
case "skill": return agent.globalSkillsDir;
|
|
807
|
-
case "agent": return agent.globalAgentsDir;
|
|
808
|
-
case "prompt": return agent.globalPromptsDir;
|
|
809
|
-
}
|
|
810
|
-
else switch (cognitiveType) {
|
|
811
|
-
case "skill": return agent.skillsDir;
|
|
812
|
-
case "agent": return agent.agentsDir;
|
|
813
|
-
case "prompt": return agent.promptsDir;
|
|
814
|
-
}
|
|
1121
|
+
const dirEntry = agents[agentType].dirs[cognitiveType];
|
|
1122
|
+
return scope === "global" ? dirEntry.global : dirEntry.local;
|
|
815
1123
|
}
|
|
816
1124
|
function isUniversalForType(agentType, cognitiveType) {
|
|
817
|
-
|
|
818
|
-
const universalDir = `.agents/${COGNITIVE_SUBDIRS[cognitiveType]}`;
|
|
819
|
-
switch (cognitiveType) {
|
|
820
|
-
case "skill": return agent.skillsDir === universalDir;
|
|
821
|
-
case "agent": return agent.agentsDir === universalDir;
|
|
822
|
-
case "prompt": return agent.promptsDir === universalDir;
|
|
823
|
-
}
|
|
1125
|
+
return agents[agentType].dirs[cognitiveType].local === `.agents/${COGNITIVE_SUBDIRS[cognitiveType]}`;
|
|
824
1126
|
}
|
|
825
|
-
function shortenPath
|
|
1127
|
+
function shortenPath(fullPath, cwd) {
|
|
826
1128
|
const home = homedir();
|
|
827
1129
|
if (fullPath === home || fullPath.startsWith(home + sep)) return "~" + fullPath.slice(home.length);
|
|
828
1130
|
if (fullPath === cwd || fullPath.startsWith(cwd + sep)) return "." + fullPath.slice(cwd.length);
|
|
829
1131
|
return fullPath;
|
|
830
1132
|
}
|
|
831
|
-
function formatList
|
|
1133
|
+
function formatList(items, maxShow = 5) {
|
|
832
1134
|
if (items.length <= maxShow) return items.join(", ");
|
|
833
1135
|
const shown = items.slice(0, maxShow);
|
|
834
1136
|
const remaining = items.length - maxShow;
|
|
@@ -848,11 +1150,11 @@ function buildAgentSummaryLines(targetAgents, installMode) {
|
|
|
848
1150
|
const lines = [];
|
|
849
1151
|
const { universal, symlinked } = splitAgentsByType(targetAgents);
|
|
850
1152
|
if (installMode === "symlink") {
|
|
851
|
-
if (universal.length > 0) lines.push(` ${import_picocolors.default.green("universal:")} ${formatList
|
|
852
|
-
if (symlinked.length > 0) lines.push(` ${import_picocolors.default.dim("symlink →")} ${formatList
|
|
1153
|
+
if (universal.length > 0) lines.push(` ${import_picocolors.default.green("universal:")} ${formatList(universal)}`);
|
|
1154
|
+
if (symlinked.length > 0) lines.push(` ${import_picocolors.default.dim("symlink →")} ${formatList(symlinked)}`);
|
|
853
1155
|
} else {
|
|
854
1156
|
const allNames = targetAgents.map((a) => agents[a].displayName);
|
|
855
|
-
lines.push(` ${import_picocolors.default.dim("copy →")} ${formatList
|
|
1157
|
+
lines.push(` ${import_picocolors.default.dim("copy →")} ${formatList(allNames)}`);
|
|
856
1158
|
}
|
|
857
1159
|
return lines;
|
|
858
1160
|
}
|
|
@@ -867,31 +1169,62 @@ function buildResultLines(results, targetAgents) {
|
|
|
867
1169
|
const { universal, symlinked: symlinkAgents } = splitAgentsByType(targetAgents);
|
|
868
1170
|
const successfulSymlinks = results.filter((r) => !r.symlinkFailed && !universal.includes(r.agent)).map((r) => r.agent);
|
|
869
1171
|
const failedSymlinks = results.filter((r) => r.symlinkFailed).map((r) => r.agent);
|
|
870
|
-
if (universal.length > 0) lines.push(` ${import_picocolors.default.green("universal:")} ${formatList
|
|
871
|
-
if (successfulSymlinks.length > 0) lines.push(` ${import_picocolors.default.dim("symlinked:")} ${formatList
|
|
872
|
-
if (failedSymlinks.length > 0) lines.push(` ${import_picocolors.default.yellow("copied:")} ${formatList
|
|
1172
|
+
if (universal.length > 0) lines.push(` ${import_picocolors.default.green("universal:")} ${formatList(universal)}`);
|
|
1173
|
+
if (successfulSymlinks.length > 0) lines.push(` ${import_picocolors.default.dim("symlinked:")} ${formatList(successfulSymlinks)}`);
|
|
1174
|
+
if (failedSymlinks.length > 0) lines.push(` ${import_picocolors.default.yellow("copied:")} ${formatList(failedSymlinks)}`);
|
|
873
1175
|
return lines;
|
|
874
1176
|
}
|
|
875
|
-
const AGENTS_DIR
|
|
876
|
-
const LOCK_FILE
|
|
1177
|
+
const AGENTS_DIR = ".agents";
|
|
1178
|
+
const LOCK_FILE = ".synk-lock.json";
|
|
1179
|
+
const OLD_LOCK_FILE = ".skill-lock.json";
|
|
877
1180
|
const CURRENT_VERSION = 4;
|
|
878
|
-
function
|
|
879
|
-
return join(homedir(), AGENTS_DIR
|
|
1181
|
+
function getLockFilePath() {
|
|
1182
|
+
return join(homedir(), AGENTS_DIR, LOCK_FILE);
|
|
1183
|
+
}
|
|
1184
|
+
async function migrateLockFileIfNeeded() {
|
|
1185
|
+
const newPath = join(homedir(), AGENTS_DIR, LOCK_FILE);
|
|
1186
|
+
const oldPath = join(homedir(), AGENTS_DIR, OLD_LOCK_FILE);
|
|
1187
|
+
try {
|
|
1188
|
+
await stat(newPath);
|
|
1189
|
+
return;
|
|
1190
|
+
} catch {}
|
|
1191
|
+
try {
|
|
1192
|
+
await stat(oldPath);
|
|
1193
|
+
await rename(oldPath, newPath);
|
|
1194
|
+
} catch {}
|
|
880
1195
|
}
|
|
881
|
-
async function
|
|
882
|
-
|
|
1196
|
+
async function readLockFile() {
|
|
1197
|
+
await migrateLockFileIfNeeded();
|
|
1198
|
+
const lockPath = getLockFilePath();
|
|
883
1199
|
try {
|
|
884
1200
|
const content = await readFile(lockPath, "utf-8");
|
|
885
1201
|
const parsed = JSON.parse(content);
|
|
886
|
-
if (typeof parsed.version !== "number"
|
|
1202
|
+
if (typeof parsed.version !== "number") return createEmptyLockFile();
|
|
887
1203
|
if (parsed.version < CURRENT_VERSION) return createEmptyLockFile();
|
|
888
|
-
|
|
1204
|
+
const cognitives = parsed.cognitives ?? parsed.skills ?? {};
|
|
1205
|
+
const migratedCognitives = {};
|
|
1206
|
+
for (const [name, entry] of Object.entries(cognitives)) migratedCognitives[name] = {
|
|
1207
|
+
source: entry.source,
|
|
1208
|
+
sourceType: entry.sourceType,
|
|
1209
|
+
sourceUrl: entry.sourceUrl,
|
|
1210
|
+
cognitivePath: entry.cognitivePath ?? entry.skillPath,
|
|
1211
|
+
cognitiveFolderHash: entry.cognitiveFolderHash ?? entry.skillFolderHash,
|
|
1212
|
+
installedAt: entry.installedAt,
|
|
1213
|
+
updatedAt: entry.updatedAt,
|
|
1214
|
+
cognitiveType: entry.cognitiveType
|
|
1215
|
+
};
|
|
1216
|
+
return {
|
|
1217
|
+
version: parsed.version,
|
|
1218
|
+
cognitives: migratedCognitives,
|
|
1219
|
+
dismissed: parsed.dismissed,
|
|
1220
|
+
lastSelectedAgents: parsed.lastSelectedAgents
|
|
1221
|
+
};
|
|
889
1222
|
} catch (error) {
|
|
890
1223
|
return createEmptyLockFile();
|
|
891
1224
|
}
|
|
892
1225
|
}
|
|
893
|
-
async function
|
|
894
|
-
const lockPath =
|
|
1226
|
+
async function writeLockFile(lock) {
|
|
1227
|
+
const lockPath = getLockFilePath();
|
|
895
1228
|
await mkdir(dirname(lockPath), { recursive: true });
|
|
896
1229
|
await writeFile(lockPath, JSON.stringify(lock, null, 2), "utf-8");
|
|
897
1230
|
}
|
|
@@ -911,16 +1244,21 @@ function getGitHubToken() {
|
|
|
911
1244
|
} catch {}
|
|
912
1245
|
return null;
|
|
913
1246
|
}
|
|
914
|
-
async function
|
|
915
|
-
let folderPath =
|
|
916
|
-
if (folderPath.endsWith("/
|
|
917
|
-
|
|
1247
|
+
async function fetchCognitiveFolderHash(ownerRepo, cognitivePath, token) {
|
|
1248
|
+
let folderPath = cognitivePath.replace(/\\/g, "/");
|
|
1249
|
+
for (const fileName of Object.values(COGNITIVE_FILE_NAMES)) if (folderPath.endsWith("/" + fileName)) {
|
|
1250
|
+
folderPath = folderPath.slice(0, -(fileName.length + 1));
|
|
1251
|
+
break;
|
|
1252
|
+
} else if (folderPath.endsWith(fileName)) {
|
|
1253
|
+
folderPath = folderPath.slice(0, -fileName.length);
|
|
1254
|
+
break;
|
|
1255
|
+
}
|
|
918
1256
|
if (folderPath.endsWith("/")) folderPath = folderPath.slice(0, -1);
|
|
919
1257
|
for (const branch of ["main", "master"]) try {
|
|
920
1258
|
const url = `https://api.github.com/repos/${ownerRepo}/git/trees/${branch}?recursive=1`;
|
|
921
1259
|
const headers = {
|
|
922
1260
|
Accept: "application/vnd.github.v3+json",
|
|
923
|
-
"User-Agent": "
|
|
1261
|
+
"User-Agent": "synk-cli"
|
|
924
1262
|
};
|
|
925
1263
|
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
926
1264
|
const response = await fetch(url, { headers });
|
|
@@ -935,53 +1273,50 @@ async function fetchSkillFolderHash(ownerRepo, skillPath, token) {
|
|
|
935
1273
|
return null;
|
|
936
1274
|
}
|
|
937
1275
|
async function addCognitiveToLock(name, cognitiveType, entry) {
|
|
938
|
-
const lock = await
|
|
1276
|
+
const lock = await readLockFile();
|
|
939
1277
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
940
|
-
const existingEntry = lock.
|
|
941
|
-
lock.
|
|
1278
|
+
const existingEntry = lock.cognitives[name];
|
|
1279
|
+
lock.cognitives[name] = {
|
|
942
1280
|
...entry,
|
|
943
1281
|
cognitiveType,
|
|
944
1282
|
installedAt: existingEntry?.installedAt ?? now,
|
|
945
1283
|
updatedAt: now
|
|
946
1284
|
};
|
|
947
|
-
await
|
|
948
|
-
}
|
|
949
|
-
async function addSkillToLock(skillName, entry) {
|
|
950
|
-
return addCognitiveToLock(skillName, "skill", entry);
|
|
1285
|
+
await writeLockFile(lock);
|
|
951
1286
|
}
|
|
952
|
-
async function
|
|
953
|
-
const lock = await
|
|
954
|
-
if (!(
|
|
955
|
-
delete lock.
|
|
956
|
-
await
|
|
1287
|
+
async function removeCognitiveFromLock(name) {
|
|
1288
|
+
const lock = await readLockFile();
|
|
1289
|
+
if (!(name in lock.cognitives)) return false;
|
|
1290
|
+
delete lock.cognitives[name];
|
|
1291
|
+
await writeLockFile(lock);
|
|
957
1292
|
return true;
|
|
958
1293
|
}
|
|
959
|
-
async function
|
|
960
|
-
return (await
|
|
1294
|
+
async function getCognitiveFromLock(name) {
|
|
1295
|
+
return (await readLockFile()).cognitives[name] ?? null;
|
|
961
1296
|
}
|
|
962
1297
|
function createEmptyLockFile() {
|
|
963
1298
|
return {
|
|
964
1299
|
version: CURRENT_VERSION,
|
|
965
|
-
|
|
1300
|
+
cognitives: {},
|
|
966
1301
|
dismissed: {}
|
|
967
1302
|
};
|
|
968
1303
|
}
|
|
969
1304
|
async function isPromptDismissed(promptKey) {
|
|
970
|
-
return (await
|
|
1305
|
+
return (await readLockFile()).dismissed?.[promptKey] === true;
|
|
971
1306
|
}
|
|
972
1307
|
async function dismissPrompt(promptKey) {
|
|
973
|
-
const lock = await
|
|
1308
|
+
const lock = await readLockFile();
|
|
974
1309
|
if (!lock.dismissed) lock.dismissed = {};
|
|
975
1310
|
lock.dismissed[promptKey] = true;
|
|
976
|
-
await
|
|
1311
|
+
await writeLockFile(lock);
|
|
977
1312
|
}
|
|
978
1313
|
async function getLastSelectedAgents() {
|
|
979
|
-
return (await
|
|
1314
|
+
return (await readLockFile()).lastSelectedAgents;
|
|
980
1315
|
}
|
|
981
1316
|
async function saveSelectedAgents(agents) {
|
|
982
|
-
const lock = await
|
|
1317
|
+
const lock = await readLockFile();
|
|
983
1318
|
lock.lastSelectedAgents = agents;
|
|
984
|
-
await
|
|
1319
|
+
await writeLockFile(lock);
|
|
985
1320
|
}
|
|
986
1321
|
const silentOutput = new Writable({ write(_chunk, _encoding, callback) {
|
|
987
1322
|
callback();
|
|
@@ -1178,11 +1513,12 @@ async function promptForAgents(message, choices) {
|
|
|
1178
1513
|
return selected;
|
|
1179
1514
|
}
|
|
1180
1515
|
async function selectAgentsInteractive(options) {
|
|
1181
|
-
const
|
|
1516
|
+
const cognitiveType = options.cognitiveType ?? "skill";
|
|
1517
|
+
const supportsGlobalFilter = (a) => !options.global || agents[a].dirs[cognitiveType]?.global;
|
|
1182
1518
|
const universalAgents = getUniversalAgents().filter(supportsGlobalFilter);
|
|
1183
1519
|
const otherAgents = getNonUniversalAgents().filter(supportsGlobalFilter);
|
|
1184
1520
|
const universalSection = {
|
|
1185
|
-
title:
|
|
1521
|
+
title: `Universal (.agents/${COGNITIVE_SUBDIRS[cognitiveType]})`,
|
|
1186
1522
|
items: universalAgents.map((a) => ({
|
|
1187
1523
|
value: a,
|
|
1188
1524
|
label: agents[a].displayName
|
|
@@ -1191,7 +1527,7 @@ async function selectAgentsInteractive(options) {
|
|
|
1191
1527
|
const otherChoices = otherAgents.map((a) => ({
|
|
1192
1528
|
value: a,
|
|
1193
1529
|
label: agents[a].displayName,
|
|
1194
|
-
hint: options.global ? agents[a].
|
|
1530
|
+
hint: options.global ? agents[a].dirs[cognitiveType].global : agents[a].dirs[cognitiveType].local
|
|
1195
1531
|
}));
|
|
1196
1532
|
let lastSelected;
|
|
1197
1533
|
try {
|
|
@@ -1286,9 +1622,6 @@ async function parseCognitiveMd(mdPath, cognitiveType, options) {
|
|
|
1286
1622
|
return null;
|
|
1287
1623
|
}
|
|
1288
1624
|
}
|
|
1289
|
-
async function parseSkillMd(skillMdPath, options) {
|
|
1290
|
-
return parseCognitiveMd(skillMdPath, "skill", options);
|
|
1291
|
-
}
|
|
1292
1625
|
function isContainedIn(targetPath, basePath) {
|
|
1293
1626
|
const normalizedBase = normalize(resolve(basePath));
|
|
1294
1627
|
const normalizedTarget = normalize(resolve(targetPath));
|
|
@@ -1331,11 +1664,7 @@ const SKIP_DIRS = [
|
|
|
1331
1664
|
"build",
|
|
1332
1665
|
"__pycache__"
|
|
1333
1666
|
];
|
|
1334
|
-
const ALL_COGNITIVE_TYPES =
|
|
1335
|
-
"skill",
|
|
1336
|
-
"agent",
|
|
1337
|
-
"prompt"
|
|
1338
|
-
];
|
|
1667
|
+
const ALL_COGNITIVE_TYPES = Object.keys(COGNITIVE_FILE_NAMES);
|
|
1339
1668
|
const AGENT_DIR_PREFIXES = [
|
|
1340
1669
|
".agent",
|
|
1341
1670
|
".agents",
|
|
@@ -1447,20 +1776,14 @@ async function discoverCognitives(basePath, subpath, options) {
|
|
|
1447
1776
|
}
|
|
1448
1777
|
return results;
|
|
1449
1778
|
}
|
|
1450
|
-
|
|
1451
|
-
return
|
|
1452
|
-
...options,
|
|
1453
|
-
types: options?.types ?? ["skill"]
|
|
1454
|
-
});
|
|
1455
|
-
}
|
|
1456
|
-
function getSkillDisplayName(skill) {
|
|
1457
|
-
return skill.name || basename(skill.path);
|
|
1779
|
+
function getCognitiveDisplayName(cognitive) {
|
|
1780
|
+
return cognitive.name || basename(cognitive.path);
|
|
1458
1781
|
}
|
|
1459
|
-
function
|
|
1782
|
+
function filterCognitives(cognitives, inputNames) {
|
|
1460
1783
|
const normalizedInputs = inputNames.map((n) => n.toLowerCase());
|
|
1461
|
-
return
|
|
1462
|
-
const name =
|
|
1463
|
-
const displayName =
|
|
1784
|
+
return cognitives.filter((cognitive) => {
|
|
1785
|
+
const name = cognitive.name.toLowerCase();
|
|
1786
|
+
const displayName = getCognitiveDisplayName(cognitive).toLowerCase();
|
|
1464
1787
|
return normalizedInputs.some((input) => input === name || input === displayName);
|
|
1465
1788
|
});
|
|
1466
1789
|
}
|
|
@@ -1473,7 +1796,7 @@ function isPathSafe(basePath, targetPath) {
|
|
|
1473
1796
|
return normalizedTarget.startsWith(normalizedBase + sep) || normalizedTarget === normalizedBase;
|
|
1474
1797
|
}
|
|
1475
1798
|
function getCanonicalDir(cognitiveType, global, cwd) {
|
|
1476
|
-
return join(global ? homedir() : cwd || process.cwd(), AGENTS_DIR$
|
|
1799
|
+
return join(global ? homedir() : cwd || process.cwd(), AGENTS_DIR$1, COGNITIVE_SUBDIRS[cognitiveType]);
|
|
1477
1800
|
}
|
|
1478
1801
|
function getInstallPath(skillName, agentType, options = {}) {
|
|
1479
1802
|
const cognitiveType = options.cognitiveType ?? "skill";
|
|
@@ -1636,7 +1959,7 @@ async function installCognitiveForAgent(cognitive, agentType, options = {}) {
|
|
|
1636
1959
|
};
|
|
1637
1960
|
}
|
|
1638
1961
|
}
|
|
1639
|
-
async function
|
|
1962
|
+
async function installRemoteCognitiveForAgent(skill, agentType, options = {}) {
|
|
1640
1963
|
const cognitiveType = options.cognitiveType ?? skill.cognitiveType ?? "skill";
|
|
1641
1964
|
const agent = agents[agentType];
|
|
1642
1965
|
const isGlobal = options.global ?? false;
|
|
@@ -1650,12 +1973,12 @@ async function installRemoteSkillForAgent(skill, agentType, options = {}) {
|
|
|
1650
1973
|
mode: installMode,
|
|
1651
1974
|
error: `${agent.displayName} does not support global ${cognitiveType} installation`
|
|
1652
1975
|
};
|
|
1653
|
-
const
|
|
1976
|
+
const cognitiveName = sanitizeName(skill.installName);
|
|
1654
1977
|
const canonicalBase = getCanonicalDir(cognitiveType, isGlobal, cwd);
|
|
1655
|
-
const canonicalDir = join(canonicalBase,
|
|
1978
|
+
const canonicalDir = join(canonicalBase, cognitiveName);
|
|
1656
1979
|
const localDir = getCognitiveDir(agentType, cognitiveType, "local");
|
|
1657
1980
|
const agentBase = isGlobal ? globalDir : join(cwd, localDir);
|
|
1658
|
-
const agentDir = join(agentBase,
|
|
1981
|
+
const agentDir = join(agentBase, cognitiveName);
|
|
1659
1982
|
if (!isPathSafe(canonicalBase, canonicalDir)) return {
|
|
1660
1983
|
success: false,
|
|
1661
1984
|
path: agentDir,
|
|
@@ -1712,7 +2035,7 @@ async function installRemoteSkillForAgent(skill, agentType, options = {}) {
|
|
|
1712
2035
|
};
|
|
1713
2036
|
}
|
|
1714
2037
|
}
|
|
1715
|
-
async function
|
|
2038
|
+
async function installWellKnownCognitiveForAgent(skill, agentType, options = {}) {
|
|
1716
2039
|
const cognitiveType = options.cognitiveType ?? "skill";
|
|
1717
2040
|
const agent = agents[agentType];
|
|
1718
2041
|
const isGlobal = options.global ?? false;
|
|
@@ -1725,12 +2048,12 @@ async function installWellKnownSkillForAgent(skill, agentType, options = {}) {
|
|
|
1725
2048
|
mode: installMode,
|
|
1726
2049
|
error: `${agent.displayName} does not support global ${cognitiveType} installation`
|
|
1727
2050
|
};
|
|
1728
|
-
const
|
|
2051
|
+
const cognitiveName = sanitizeName(skill.installName);
|
|
1729
2052
|
const canonicalBase = getCanonicalDir(cognitiveType, isGlobal, cwd);
|
|
1730
|
-
const canonicalDir = join(canonicalBase,
|
|
2053
|
+
const canonicalDir = join(canonicalBase, cognitiveName);
|
|
1731
2054
|
const localDir = getCognitiveDir(agentType, cognitiveType, "local");
|
|
1732
2055
|
const agentBase = isGlobal ? globalDir : join(cwd, localDir);
|
|
1733
|
-
const agentDir = join(agentBase,
|
|
2056
|
+
const agentDir = join(agentBase, cognitiveName);
|
|
1734
2057
|
if (!isPathSafe(canonicalBase, canonicalDir)) return {
|
|
1735
2058
|
success: false,
|
|
1736
2059
|
path: agentDir,
|
|
@@ -1798,11 +2121,7 @@ async function installWellKnownSkillForAgent(skill, agentType, options = {}) {
|
|
|
1798
2121
|
}
|
|
1799
2122
|
async function listInstalledCognitives(options = {}) {
|
|
1800
2123
|
const cwd = options.cwd || process.cwd();
|
|
1801
|
-
const typesToScan = options.typeFilter ??
|
|
1802
|
-
"skill",
|
|
1803
|
-
"agent",
|
|
1804
|
-
"prompt"
|
|
1805
|
-
];
|
|
2124
|
+
const typesToScan = options.typeFilter ?? Object.keys(COGNITIVE_FILE_NAMES);
|
|
1806
2125
|
const cognitivesMap = /* @__PURE__ */ new Map();
|
|
1807
2126
|
const detectedAgents = await detectInstalledAgents();
|
|
1808
2127
|
const agentFilter = options.agentFilter;
|
|
@@ -1841,7 +2160,7 @@ async function listInstalledCognitives(options = {}) {
|
|
|
1841
2160
|
} catch {
|
|
1842
2161
|
continue;
|
|
1843
2162
|
}
|
|
1844
|
-
const parsed =
|
|
2163
|
+
const parsed = await parseCognitiveMd(mdPath, cognitiveType);
|
|
1845
2164
|
if (!parsed) continue;
|
|
1846
2165
|
const scopeKey = scope.global ? "global" : "project";
|
|
1847
2166
|
const cognitiveKey = `${scopeKey}:${cognitiveType}:${parsed.name}`;
|
|
@@ -1891,7 +2210,7 @@ async function listInstalledCognitives(options = {}) {
|
|
|
1891
2210
|
try {
|
|
1892
2211
|
const candidateMdPath = join(candidateDir, fileName);
|
|
1893
2212
|
await stat(candidateMdPath);
|
|
1894
|
-
const candidateParsed =
|
|
2213
|
+
const candidateParsed = await parseCognitiveMd(candidateMdPath, cognitiveType);
|
|
1895
2214
|
if (candidateParsed && candidateParsed.name === parsed.name) {
|
|
1896
2215
|
found = true;
|
|
1897
2216
|
break;
|
|
@@ -1918,12 +2237,6 @@ async function listInstalledCognitives(options = {}) {
|
|
|
1918
2237
|
}
|
|
1919
2238
|
return Array.from(cognitivesMap.values());
|
|
1920
2239
|
}
|
|
1921
|
-
async function listInstalledSkills(options = {}) {
|
|
1922
|
-
return listInstalledCognitives({
|
|
1923
|
-
...options,
|
|
1924
|
-
typeFilter: ["skill"]
|
|
1925
|
-
});
|
|
1926
|
-
}
|
|
1927
2240
|
async function isCognitiveInstalled(name, agentType, cognitiveType, options = {}) {
|
|
1928
2241
|
const sanitized = sanitizeName(name);
|
|
1929
2242
|
const globalDir = getCognitiveDir(agentType, cognitiveType, "global");
|
|
@@ -1939,9 +2252,6 @@ async function isCognitiveInstalled(name, agentType, cognitiveType, options = {}
|
|
|
1939
2252
|
return false;
|
|
1940
2253
|
}
|
|
1941
2254
|
}
|
|
1942
|
-
async function isSkillInstalled(skillName, agentType, options = {}) {
|
|
1943
|
-
return isCognitiveInstalled(skillName, agentType, options.cognitiveType ?? "skill", options);
|
|
1944
|
-
}
|
|
1945
2255
|
const TELEMETRY_URL = "https://add-skill.vercel.sh/t";
|
|
1946
2256
|
let cliVersion = null;
|
|
1947
2257
|
function isCI() {
|
|
@@ -1984,17 +2294,28 @@ function registerProvider(provider) {
|
|
|
1984
2294
|
function findProvider(url) {
|
|
1985
2295
|
return registry.findProvider(url);
|
|
1986
2296
|
}
|
|
2297
|
+
const FILE_NAME_TO_TYPE$1 = new Map(Object.entries(COGNITIVE_FILE_NAMES).map(([type, name]) => [name.toLowerCase(), type]));
|
|
2298
|
+
function detectCognitiveType$1(url) {
|
|
2299
|
+
const lower = url.toLowerCase();
|
|
2300
|
+
for (const [fileName, type] of FILE_NAME_TO_TYPE$1) if (lower.endsWith("/" + fileName)) return type;
|
|
2301
|
+
return "skill";
|
|
2302
|
+
}
|
|
2303
|
+
function matchesCognitiveFile$1(url) {
|
|
2304
|
+
const lower = url.toLowerCase();
|
|
2305
|
+
for (const fileName of FILE_NAME_TO_TYPE$1.keys()) if (lower.endsWith("/" + fileName)) return true;
|
|
2306
|
+
return false;
|
|
2307
|
+
}
|
|
1987
2308
|
var MintlifyProvider = class {
|
|
1988
2309
|
id = "mintlify";
|
|
1989
2310
|
displayName = "Mintlify";
|
|
1990
2311
|
match(url) {
|
|
1991
2312
|
if (!url.startsWith("http://") && !url.startsWith("https://")) return { matches: false };
|
|
1992
|
-
if (!url
|
|
2313
|
+
if (!matchesCognitiveFile$1(url)) return { matches: false };
|
|
1993
2314
|
if (url.includes("github.com") || url.includes("gitlab.com")) return { matches: false };
|
|
1994
2315
|
if (url.includes("huggingface.co")) return { matches: false };
|
|
1995
2316
|
return { matches: true };
|
|
1996
2317
|
}
|
|
1997
|
-
async
|
|
2318
|
+
async fetchCognitive(url) {
|
|
1998
2319
|
try {
|
|
1999
2320
|
const response = await fetch(url, { signal: AbortSignal.timeout(3e4) });
|
|
2000
2321
|
if (!response.ok) return null;
|
|
@@ -2009,12 +2330,16 @@ var MintlifyProvider = class {
|
|
|
2009
2330
|
content,
|
|
2010
2331
|
installName: mintlifySite,
|
|
2011
2332
|
sourceUrl: url,
|
|
2012
|
-
metadata: data.metadata
|
|
2333
|
+
metadata: data.metadata,
|
|
2334
|
+
cognitiveType: detectCognitiveType$1(url)
|
|
2013
2335
|
};
|
|
2014
2336
|
} catch {
|
|
2015
2337
|
return null;
|
|
2016
2338
|
}
|
|
2017
2339
|
}
|
|
2340
|
+
async fetchSkill(url) {
|
|
2341
|
+
return this.fetchCognitive(url);
|
|
2342
|
+
}
|
|
2018
2343
|
toRawUrl(url) {
|
|
2019
2344
|
return url;
|
|
2020
2345
|
}
|
|
@@ -2023,6 +2348,17 @@ var MintlifyProvider = class {
|
|
|
2023
2348
|
}
|
|
2024
2349
|
};
|
|
2025
2350
|
const mintlifyProvider = new MintlifyProvider();
|
|
2351
|
+
const FILE_NAME_TO_TYPE = new Map(Object.entries(COGNITIVE_FILE_NAMES).map(([type, name]) => [name.toLowerCase(), type]));
|
|
2352
|
+
function matchesCognitiveFile(url) {
|
|
2353
|
+
const lower = url.toLowerCase();
|
|
2354
|
+
for (const fileName of FILE_NAME_TO_TYPE.keys()) if (lower.endsWith("/" + fileName)) return true;
|
|
2355
|
+
return false;
|
|
2356
|
+
}
|
|
2357
|
+
function detectCognitiveType(url) {
|
|
2358
|
+
const lower = url.toLowerCase();
|
|
2359
|
+
for (const [fileName, type] of FILE_NAME_TO_TYPE) if (lower.endsWith("/" + fileName)) return type;
|
|
2360
|
+
return "skill";
|
|
2361
|
+
}
|
|
2026
2362
|
var HuggingFaceProvider = class {
|
|
2027
2363
|
id = "huggingface";
|
|
2028
2364
|
displayName = "HuggingFace";
|
|
@@ -2034,11 +2370,11 @@ var HuggingFaceProvider = class {
|
|
|
2034
2370
|
} catch {
|
|
2035
2371
|
return { matches: false };
|
|
2036
2372
|
}
|
|
2037
|
-
if (!url
|
|
2373
|
+
if (!matchesCognitiveFile(url)) return { matches: false };
|
|
2038
2374
|
if (!url.includes("/spaces/")) return { matches: false };
|
|
2039
2375
|
return { matches: true };
|
|
2040
2376
|
}
|
|
2041
|
-
async
|
|
2377
|
+
async fetchCognitive(url) {
|
|
2042
2378
|
try {
|
|
2043
2379
|
const rawUrl = this.toRawUrl(url);
|
|
2044
2380
|
const response = await fetch(rawUrl, { signal: AbortSignal.timeout(3e4) });
|
|
@@ -2055,7 +2391,8 @@ var HuggingFaceProvider = class {
|
|
|
2055
2391
|
content,
|
|
2056
2392
|
installName,
|
|
2057
2393
|
sourceUrl: url,
|
|
2058
|
-
metadata: data.metadata
|
|
2394
|
+
metadata: data.metadata,
|
|
2395
|
+
cognitiveType: detectCognitiveType(url)
|
|
2059
2396
|
};
|
|
2060
2397
|
} catch {
|
|
2061
2398
|
return null;
|
|
@@ -2069,6 +2406,9 @@ var HuggingFaceProvider = class {
|
|
|
2069
2406
|
if (!parsed) return "huggingface/unknown";
|
|
2070
2407
|
return `huggingface/${parsed.owner}/${parsed.repo}`;
|
|
2071
2408
|
}
|
|
2409
|
+
async fetchSkill(url) {
|
|
2410
|
+
return this.fetchCognitive(url);
|
|
2411
|
+
}
|
|
2072
2412
|
parseUrl(url) {
|
|
2073
2413
|
const match = url.match(/\/spaces\/([^/]+)\/([^/]+)/);
|
|
2074
2414
|
if (!match || !match[1] || !match[2]) return null;
|
|
@@ -2081,8 +2421,9 @@ var HuggingFaceProvider = class {
|
|
|
2081
2421
|
const huggingFaceProvider = new HuggingFaceProvider();
|
|
2082
2422
|
var WellKnownProvider = class {
|
|
2083
2423
|
id = "well-known";
|
|
2084
|
-
displayName = "Well-Known
|
|
2085
|
-
WELL_KNOWN_PATH = ".well-known/
|
|
2424
|
+
displayName = "Well-Known Cognitives";
|
|
2425
|
+
WELL_KNOWN_PATH = ".well-known/cognitives";
|
|
2426
|
+
WELL_KNOWN_PATH_LEGACY = ".well-known/skills";
|
|
2086
2427
|
INDEX_FILE = "index.json";
|
|
2087
2428
|
match(url) {
|
|
2088
2429
|
if (!url.startsWith("http://") && !url.startsWith("https://")) return { matches: false };
|
|
@@ -2105,37 +2446,41 @@ var WellKnownProvider = class {
|
|
|
2105
2446
|
try {
|
|
2106
2447
|
const parsed = new URL(baseUrl);
|
|
2107
2448
|
const basePath = parsed.pathname.replace(/\/$/, "");
|
|
2108
|
-
const
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2449
|
+
const wellKnownPaths = [this.WELL_KNOWN_PATH, this.WELL_KNOWN_PATH_LEGACY];
|
|
2450
|
+
for (const wkPath of wellKnownPaths) {
|
|
2451
|
+
const urlsToTry = [{
|
|
2452
|
+
indexUrl: `${parsed.protocol}//${parsed.host}${basePath}/${wkPath}/${this.INDEX_FILE}`,
|
|
2453
|
+
baseUrl: `${parsed.protocol}//${parsed.host}${basePath}`
|
|
2454
|
+
}];
|
|
2455
|
+
if (basePath && basePath !== "") urlsToTry.push({
|
|
2456
|
+
indexUrl: `${parsed.protocol}//${parsed.host}/${wkPath}/${this.INDEX_FILE}`,
|
|
2457
|
+
baseUrl: `${parsed.protocol}//${parsed.host}`
|
|
2458
|
+
});
|
|
2459
|
+
for (const { indexUrl, baseUrl: resolvedBase } of urlsToTry) try {
|
|
2460
|
+
const response = await fetch(indexUrl);
|
|
2461
|
+
if (!response.ok) continue;
|
|
2462
|
+
const raw = await response.json();
|
|
2463
|
+
const entries = raw.cognitives ?? raw.skills;
|
|
2464
|
+
if (!entries || !Array.isArray(entries)) continue;
|
|
2465
|
+
let allValid = true;
|
|
2466
|
+
for (const entry of entries) if (!this.isValidCognitiveEntry(entry)) {
|
|
2467
|
+
allValid = false;
|
|
2468
|
+
break;
|
|
2469
|
+
}
|
|
2470
|
+
if (allValid) return {
|
|
2471
|
+
index: { cognitives: entries },
|
|
2472
|
+
resolvedBaseUrl: resolvedBase
|
|
2473
|
+
};
|
|
2474
|
+
} catch {
|
|
2475
|
+
continue;
|
|
2125
2476
|
}
|
|
2126
|
-
if (allValid) return {
|
|
2127
|
-
index,
|
|
2128
|
-
resolvedBaseUrl: resolvedBase
|
|
2129
|
-
};
|
|
2130
|
-
} catch {
|
|
2131
|
-
continue;
|
|
2132
2477
|
}
|
|
2133
2478
|
return null;
|
|
2134
2479
|
} catch {
|
|
2135
2480
|
return null;
|
|
2136
2481
|
}
|
|
2137
2482
|
}
|
|
2138
|
-
|
|
2483
|
+
isValidCognitiveEntry(entry) {
|
|
2139
2484
|
if (!entry || typeof entry !== "object") return false;
|
|
2140
2485
|
const e = entry;
|
|
2141
2486
|
if (typeof e.name !== "string" || !e.name) return false;
|
|
@@ -2148,41 +2493,50 @@ var WellKnownProvider = class {
|
|
|
2148
2493
|
if (typeof file !== "string") return false;
|
|
2149
2494
|
if (file.startsWith("/") || file.startsWith("\\") || file.includes("..")) return false;
|
|
2150
2495
|
}
|
|
2151
|
-
|
|
2496
|
+
const cognitiveFileNames = new Set(Object.values(COGNITIVE_FILE_NAMES).map((n) => n.toLowerCase()));
|
|
2497
|
+
if (!e.files.some((f) => typeof f === "string" && cognitiveFileNames.has(f.toLowerCase()))) return false;
|
|
2152
2498
|
return true;
|
|
2153
2499
|
}
|
|
2154
|
-
async
|
|
2500
|
+
async fetchCognitive(url) {
|
|
2155
2501
|
try {
|
|
2156
2502
|
const parsed = new URL(url);
|
|
2157
2503
|
const result = await this.fetchIndex(url);
|
|
2158
2504
|
if (!result) return null;
|
|
2159
2505
|
const { index, resolvedBaseUrl } = result;
|
|
2160
|
-
let
|
|
2161
|
-
const pathMatch = parsed.pathname.match(/\/.well-known\/skills\/([^/]+)\/?$/);
|
|
2162
|
-
if (pathMatch && pathMatch[1] && pathMatch[1] !== "index.json")
|
|
2163
|
-
else if (index.
|
|
2164
|
-
if (!
|
|
2165
|
-
const
|
|
2166
|
-
if (!
|
|
2167
|
-
return this.
|
|
2506
|
+
let cognitiveName = null;
|
|
2507
|
+
const pathMatch = parsed.pathname.match(/\/.well-known\/cognitives\/([^/]+)\/?$/) ?? parsed.pathname.match(/\/.well-known\/skills\/([^/]+)\/?$/);
|
|
2508
|
+
if (pathMatch && pathMatch[1] && pathMatch[1] !== "index.json") cognitiveName = pathMatch[1];
|
|
2509
|
+
else if (index.cognitives.length === 1) cognitiveName = index.cognitives[0].name;
|
|
2510
|
+
if (!cognitiveName) return null;
|
|
2511
|
+
const cognitiveEntry = index.cognitives.find((s) => s.name === cognitiveName);
|
|
2512
|
+
if (!cognitiveEntry) return null;
|
|
2513
|
+
return this.fetchCognitiveByEntry(resolvedBaseUrl, cognitiveEntry);
|
|
2168
2514
|
} catch {
|
|
2169
2515
|
return null;
|
|
2170
2516
|
}
|
|
2171
2517
|
}
|
|
2172
|
-
async
|
|
2518
|
+
async fetchCognitiveByEntry(baseUrl, entry) {
|
|
2173
2519
|
try {
|
|
2174
|
-
const
|
|
2175
|
-
const
|
|
2176
|
-
const
|
|
2520
|
+
const cognitiveBaseUrl = `${baseUrl.replace(/\/$/, "")}/${this.WELL_KNOWN_PATH}/${entry.name}`;
|
|
2521
|
+
const cognitiveFileNames = Object.values(COGNITIVE_FILE_NAMES).map((n) => n.toLowerCase());
|
|
2522
|
+
const primaryFile = entry.files.find((f) => cognitiveFileNames.includes(f.toLowerCase()));
|
|
2523
|
+
if (!primaryFile) return null;
|
|
2524
|
+
const cognitiveType = Object.entries(COGNITIVE_FILE_NAMES).find(([_, name]) => name.toLowerCase() === primaryFile.toLowerCase())?.[0] ?? "skill";
|
|
2525
|
+
const primaryUrl = `${cognitiveBaseUrl}/${primaryFile}`;
|
|
2526
|
+
let response = await fetch(primaryUrl);
|
|
2527
|
+
if (!response.ok) {
|
|
2528
|
+
const legacyPrimaryUrl = `${`${baseUrl.replace(/\/$/, "")}/${this.WELL_KNOWN_PATH_LEGACY}/${entry.name}`}/${primaryFile}`;
|
|
2529
|
+
response = await fetch(legacyPrimaryUrl);
|
|
2530
|
+
}
|
|
2177
2531
|
if (!response.ok) return null;
|
|
2178
2532
|
const content = await response.text();
|
|
2179
2533
|
const { data } = (0, import_gray_matter.default)(content);
|
|
2180
2534
|
if (!data.name || !data.description) return null;
|
|
2181
2535
|
const files = /* @__PURE__ */ new Map();
|
|
2182
|
-
files.set(
|
|
2183
|
-
const filePromises = entry.files.filter((f) => f.toLowerCase() !==
|
|
2536
|
+
files.set(primaryFile, content);
|
|
2537
|
+
const filePromises = entry.files.filter((f) => f.toLowerCase() !== primaryFile.toLowerCase()).map(async (filePath) => {
|
|
2184
2538
|
try {
|
|
2185
|
-
const fileUrl = `${
|
|
2539
|
+
const fileUrl = `${cognitiveBaseUrl}/${filePath}`;
|
|
2186
2540
|
const fileResponse = await fetch(fileUrl);
|
|
2187
2541
|
if (fileResponse.ok) return {
|
|
2188
2542
|
path: filePath,
|
|
@@ -2198,8 +2552,9 @@ var WellKnownProvider = class {
|
|
|
2198
2552
|
description: data.description,
|
|
2199
2553
|
content,
|
|
2200
2554
|
installName: entry.name,
|
|
2201
|
-
sourceUrl:
|
|
2555
|
+
sourceUrl: primaryUrl,
|
|
2202
2556
|
metadata: data.metadata,
|
|
2557
|
+
cognitiveType,
|
|
2203
2558
|
files,
|
|
2204
2559
|
indexEntry: entry
|
|
2205
2560
|
};
|
|
@@ -2207,13 +2562,13 @@ var WellKnownProvider = class {
|
|
|
2207
2562
|
return null;
|
|
2208
2563
|
}
|
|
2209
2564
|
}
|
|
2210
|
-
async
|
|
2565
|
+
async fetchAllCognitives(url) {
|
|
2211
2566
|
try {
|
|
2212
2567
|
const result = await this.fetchIndex(url);
|
|
2213
2568
|
if (!result) return [];
|
|
2214
2569
|
const { index, resolvedBaseUrl } = result;
|
|
2215
|
-
const
|
|
2216
|
-
return (await Promise.all(
|
|
2570
|
+
const cognitivePromises = index.cognitives.map((entry) => this.fetchCognitiveByEntry(resolvedBaseUrl, entry));
|
|
2571
|
+
return (await Promise.all(cognitivePromises)).filter((s) => s !== null);
|
|
2217
2572
|
} catch {
|
|
2218
2573
|
return [];
|
|
2219
2574
|
}
|
|
@@ -2221,11 +2576,16 @@ var WellKnownProvider = class {
|
|
|
2221
2576
|
toRawUrl(url) {
|
|
2222
2577
|
try {
|
|
2223
2578
|
const parsed = new URL(url);
|
|
2224
|
-
|
|
2225
|
-
const
|
|
2579
|
+
const cognitiveFileNames = Object.values(COGNITIVE_FILE_NAMES).map((n) => n.toLowerCase());
|
|
2580
|
+
const lower = url.toLowerCase();
|
|
2581
|
+
if (cognitiveFileNames.some((f) => lower.endsWith("/" + f))) return url;
|
|
2582
|
+
const pathMatch = parsed.pathname.match(/\/.well-known\/cognitives\/([^/]+?)(?:\/([^/]+))?\/?$/) ?? parsed.pathname.match(/\/.well-known\/skills\/([^/]+?)(?:\/([^/]+))?\/?$/);
|
|
2226
2583
|
if (pathMatch && pathMatch[1]) {
|
|
2227
|
-
const
|
|
2228
|
-
|
|
2584
|
+
const matchedWkPath = parsed.pathname.includes(".well-known/cognitives") ? this.WELL_KNOWN_PATH : this.WELL_KNOWN_PATH_LEGACY;
|
|
2585
|
+
const basePath = parsed.pathname.replace(/\/.well-known\/(?:cognitives|skills)\/.*$/, "");
|
|
2586
|
+
const trailingFile = pathMatch[2]?.toLowerCase();
|
|
2587
|
+
const cognitiveFile = cognitiveFileNames.find((f) => f === trailingFile) ? pathMatch[2] : COGNITIVE_FILE_NAMES.skill;
|
|
2588
|
+
return `${parsed.protocol}//${parsed.host}${basePath}/${matchedWkPath}/${pathMatch[1]}/${cognitiveFile}`;
|
|
2229
2589
|
}
|
|
2230
2590
|
const basePath = parsed.pathname.replace(/\/$/, "");
|
|
2231
2591
|
return `${parsed.protocol}//${parsed.host}${basePath}/${this.WELL_KNOWN_PATH}/${this.INDEX_FILE}`;
|
|
@@ -2246,34 +2606,50 @@ var WellKnownProvider = class {
|
|
|
2246
2606
|
return "unknown/unknown";
|
|
2247
2607
|
}
|
|
2248
2608
|
}
|
|
2249
|
-
async
|
|
2609
|
+
async hasCognitivesIndex(url) {
|
|
2250
2610
|
return await this.fetchIndex(url) !== null;
|
|
2251
2611
|
}
|
|
2612
|
+
async hasSkillsIndex(url) {
|
|
2613
|
+
return this.hasCognitivesIndex(url);
|
|
2614
|
+
}
|
|
2615
|
+
async fetchSkill(url) {
|
|
2616
|
+
return this.fetchCognitive(url);
|
|
2617
|
+
}
|
|
2618
|
+
async fetchSkillByEntry(baseUrl, entry) {
|
|
2619
|
+
return this.fetchCognitiveByEntry(baseUrl, entry);
|
|
2620
|
+
}
|
|
2621
|
+
async fetchAllSkills(url) {
|
|
2622
|
+
return this.fetchAllCognitives(url);
|
|
2623
|
+
}
|
|
2252
2624
|
};
|
|
2253
2625
|
const wellKnownProvider = new WellKnownProvider();
|
|
2254
2626
|
registerProvider(mintlifyProvider);
|
|
2255
2627
|
registerProvider(huggingFaceProvider);
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
} catch {
|
|
2273
|
-
return null;
|
|
2628
|
+
var version$1 = "1.1.0";
|
|
2629
|
+
function assertNotCancelled(value, cleanup) {
|
|
2630
|
+
if (pD(value)) {
|
|
2631
|
+
logger.cancel("Operation cancelled");
|
|
2632
|
+
if (cleanup) cleanup().then(() => process.exit(0)).catch(() => process.exit(0));
|
|
2633
|
+
else process.exit(0);
|
|
2634
|
+
throw new Error("cancelled");
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
2637
|
+
function validateAgentNames(agentNames) {
|
|
2638
|
+
const validAgents = Object.keys(agents);
|
|
2639
|
+
const invalid = agentNames.filter((a) => !validAgents.includes(a));
|
|
2640
|
+
if (invalid.length > 0) {
|
|
2641
|
+
logger.error(`Invalid agents: ${invalid.join(", ")}`);
|
|
2642
|
+
logger.info(`Valid agents: ${validAgents.join(", ")}`);
|
|
2643
|
+
process.exit(1);
|
|
2274
2644
|
}
|
|
2645
|
+
return agentNames;
|
|
2646
|
+
}
|
|
2647
|
+
function buildLockEntry(params) {
|
|
2648
|
+
return {
|
|
2649
|
+
...params,
|
|
2650
|
+
cognitiveFolderHash: ""
|
|
2651
|
+
};
|
|
2275
2652
|
}
|
|
2276
|
-
var version$1 = "1.0.0";
|
|
2277
2653
|
function initTelemetry(version) {
|
|
2278
2654
|
setVersion(version);
|
|
2279
2655
|
}
|
|
@@ -2313,29 +2689,21 @@ async function selectTargetAgents(options, spinner, cleanup, useUniversalAgents
|
|
|
2313
2689
|
}
|
|
2314
2690
|
if (useUniversalAgents) {
|
|
2315
2691
|
const selected = await selectAgentsInteractive({ global: options.global });
|
|
2316
|
-
|
|
2317
|
-
logger.cancel("Installation cancelled");
|
|
2318
|
-
await cleanup?.();
|
|
2319
|
-
process.exit(0);
|
|
2320
|
-
}
|
|
2692
|
+
assertNotCancelled(selected, cleanup);
|
|
2321
2693
|
return selected;
|
|
2322
2694
|
}
|
|
2323
|
-
logger.info("Select agents to install
|
|
2695
|
+
logger.info("Select agents to install to");
|
|
2324
2696
|
const selected = await promptForAgents("Which agents do you want to install to?", Object.entries(agents).map(([key, config]) => ({
|
|
2325
2697
|
value: key,
|
|
2326
2698
|
label: config.displayName
|
|
2327
2699
|
})));
|
|
2328
|
-
|
|
2329
|
-
logger.cancel("Installation cancelled");
|
|
2330
|
-
await cleanup?.();
|
|
2331
|
-
process.exit(0);
|
|
2332
|
-
}
|
|
2700
|
+
assertNotCancelled(selected, cleanup);
|
|
2333
2701
|
return selected;
|
|
2334
2702
|
}
|
|
2335
2703
|
if (installedAgents.length === 1 || options.yes) {
|
|
2336
2704
|
if (useUniversalAgents) {
|
|
2337
2705
|
const target = ensureUniversalAgents(installedAgents);
|
|
2338
|
-
const {
|
|
2706
|
+
const { symlinked } = splitAgentsByType(target);
|
|
2339
2707
|
if (symlinked.length > 0) logger.info(`Installing to: ${import_picocolors.default.green("universal")} + ${symlinked.map((a) => import_picocolors.default.cyan(a)).join(", ")}`);
|
|
2340
2708
|
else logger.info(`Installing to: ${import_picocolors.default.green("universal agents")}`);
|
|
2341
2709
|
return target;
|
|
@@ -2347,16 +2715,13 @@ async function selectTargetAgents(options, spinner, cleanup, useUniversalAgents
|
|
|
2347
2715
|
return installedAgents;
|
|
2348
2716
|
}
|
|
2349
2717
|
const selected = await selectAgentsInteractive({ global: options.global });
|
|
2350
|
-
|
|
2351
|
-
logger.cancel("Installation cancelled");
|
|
2352
|
-
await cleanup?.();
|
|
2353
|
-
process.exit(0);
|
|
2354
|
-
}
|
|
2718
|
+
assertNotCancelled(selected, cleanup);
|
|
2355
2719
|
return selected;
|
|
2356
2720
|
}
|
|
2357
2721
|
async function selectInstallScope(options, targetAgents, cleanup) {
|
|
2358
2722
|
let installGlobally = options.global ?? false;
|
|
2359
|
-
const
|
|
2723
|
+
const cogType = options.type ?? "skill";
|
|
2724
|
+
const supportsGlobal = targetAgents.some((a) => agents[a].dirs[cogType]?.global !== void 0);
|
|
2360
2725
|
if (options.global === void 0 && !options.yes && supportsGlobal) {
|
|
2361
2726
|
const scope = await ve({
|
|
2362
2727
|
message: "Installation scope",
|
|
@@ -2370,11 +2735,7 @@ async function selectInstallScope(options, targetAgents, cleanup) {
|
|
|
2370
2735
|
hint: "Install in home directory (available across all projects)"
|
|
2371
2736
|
}]
|
|
2372
2737
|
});
|
|
2373
|
-
|
|
2374
|
-
logger.cancel("Installation cancelled");
|
|
2375
|
-
await cleanup?.();
|
|
2376
|
-
process.exit(0);
|
|
2377
|
-
}
|
|
2738
|
+
assertNotCancelled(scope, cleanup);
|
|
2378
2739
|
installGlobally = scope;
|
|
2379
2740
|
}
|
|
2380
2741
|
return installGlobally;
|
|
@@ -2393,56 +2754,53 @@ async function selectInstallMode(options, cleanup) {
|
|
|
2393
2754
|
hint: "Independent copies for each agent"
|
|
2394
2755
|
}]
|
|
2395
2756
|
});
|
|
2396
|
-
|
|
2397
|
-
logger.cancel("Installation cancelled");
|
|
2398
|
-
await cleanup?.();
|
|
2399
|
-
process.exit(0);
|
|
2400
|
-
}
|
|
2757
|
+
assertNotCancelled(modeChoice, cleanup);
|
|
2401
2758
|
return modeChoice;
|
|
2402
2759
|
}
|
|
2760
|
+
async function selectInstallContext(options, spinner, cleanup, config) {
|
|
2761
|
+
const targetAgents = await selectTargetAgents(options, spinner, cleanup, config?.useUniversalAgents);
|
|
2762
|
+
return {
|
|
2763
|
+
targetAgents,
|
|
2764
|
+
installGlobally: await selectInstallScope(options, targetAgents, cleanup),
|
|
2765
|
+
installMode: config?.forceMode ?? await selectInstallMode(options, cleanup)
|
|
2766
|
+
};
|
|
2767
|
+
}
|
|
2403
2768
|
async function isSourcePrivate(source) {
|
|
2404
2769
|
const ownerRepo = parseOwnerRepo(source);
|
|
2405
2770
|
if (!ownerRepo) return false;
|
|
2406
2771
|
return isRepoPrivate(ownerRepo.owner, ownerRepo.repo);
|
|
2407
2772
|
}
|
|
2408
|
-
async function
|
|
2409
|
-
const { items, targetAgents, installGlobally, installMode, cognitiveType } = prepared;
|
|
2410
|
-
const cwd = process.cwd();
|
|
2773
|
+
async function checkOverwrites(items, targetAgents, installGlobally, cognitiveType) {
|
|
2411
2774
|
const overwriteChecks = await Promise.all(items.flatMap((item) => targetAgents.map(async (agent) => ({
|
|
2412
|
-
|
|
2775
|
+
itemName: item.installName,
|
|
2413
2776
|
agent,
|
|
2414
|
-
installed:
|
|
2777
|
+
installed: await isCognitiveInstalled(item.installName, agent, cognitiveType, { global: installGlobally })
|
|
2415
2778
|
}))));
|
|
2416
2779
|
const overwriteStatus = /* @__PURE__ */ new Map();
|
|
2417
|
-
for (const {
|
|
2418
|
-
if (!overwriteStatus.has(
|
|
2419
|
-
overwriteStatus.get(
|
|
2780
|
+
for (const { itemName, agent, installed } of overwriteChecks) {
|
|
2781
|
+
if (!overwriteStatus.has(itemName)) overwriteStatus.set(itemName, /* @__PURE__ */ new Map());
|
|
2782
|
+
overwriteStatus.get(itemName).set(agent, installed);
|
|
2420
2783
|
}
|
|
2784
|
+
return overwriteStatus;
|
|
2785
|
+
}
|
|
2786
|
+
function buildInstallSummary(items, targetAgents, installGlobally, installMode, cognitiveType, overwriteStatus, cwd) {
|
|
2421
2787
|
const summaryLines = [];
|
|
2422
2788
|
for (const item of items) {
|
|
2423
2789
|
if (summaryLines.length > 0) summaryLines.push("");
|
|
2424
|
-
const shortCanonical = shortenPath
|
|
2790
|
+
const shortCanonical = shortenPath(getCanonicalPath(item.installName, {
|
|
2425
2791
|
global: installGlobally,
|
|
2426
2792
|
cognitiveType
|
|
2427
2793
|
}), cwd);
|
|
2428
2794
|
summaryLines.push(`${import_picocolors.default.cyan(shortCanonical)}`);
|
|
2429
2795
|
summaryLines.push(...buildAgentSummaryLines(targetAgents, installMode));
|
|
2430
2796
|
if (item.fileCount && item.fileCount > 1) summaryLines.push(` ${import_picocolors.default.dim("files:")} ${item.fileCount}`);
|
|
2431
|
-
const
|
|
2432
|
-
const overwriteAgents = targetAgents.filter((a) =>
|
|
2433
|
-
if (overwriteAgents.length > 0) summaryLines.push(` ${import_picocolors.default.yellow("overwrites:")} ${formatList
|
|
2797
|
+
const itemOverwrites = overwriteStatus.get(item.installName);
|
|
2798
|
+
const overwriteAgents = targetAgents.filter((a) => itemOverwrites?.get(a)).map((a) => agents[a].displayName);
|
|
2799
|
+
if (overwriteAgents.length > 0) summaryLines.push(` ${import_picocolors.default.yellow("overwrites:")} ${formatList(overwriteAgents)}`);
|
|
2434
2800
|
}
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
if (pD(confirmed) || !confirmed) {
|
|
2439
|
-
logger.cancel("Installation cancelled");
|
|
2440
|
-
await cleanup?.();
|
|
2441
|
-
process.exit(0);
|
|
2442
|
-
}
|
|
2443
|
-
}
|
|
2444
|
-
const label = items.length === 1 ? "Installing skill..." : "Installing skills...";
|
|
2445
|
-
spinner.start(label);
|
|
2801
|
+
return summaryLines;
|
|
2802
|
+
}
|
|
2803
|
+
async function performInstalls(items, targetAgents, installGlobally, installMode) {
|
|
2446
2804
|
const results = [];
|
|
2447
2805
|
for (const item of items) for (const agent of targetAgents) {
|
|
2448
2806
|
const result = await item.installFn(agent, {
|
|
@@ -2450,450 +2808,383 @@ async function executeInstallFlow(prepared, options, spinner, cleanup) {
|
|
|
2450
2808
|
mode: installMode
|
|
2451
2809
|
});
|
|
2452
2810
|
results.push({
|
|
2453
|
-
|
|
2811
|
+
name: item.installName,
|
|
2454
2812
|
agent: agents[agent].displayName,
|
|
2455
2813
|
...result
|
|
2456
2814
|
});
|
|
2457
2815
|
}
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
const
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
if (await isSourcePrivate(telemetry.source) === true) shouldTrack = false;
|
|
2816
|
+
return results;
|
|
2817
|
+
}
|
|
2818
|
+
async function writeLockEntries(prepared, successfulNames) {
|
|
2819
|
+
for (const entry of prepared.lockEntries) if (successfulNames.has(entry.name)) try {
|
|
2820
|
+
let cognitiveFolderHash = entry.cognitiveFolderHash;
|
|
2821
|
+
if (!cognitiveFolderHash && entry.sourceType === "github" && entry.cognitivePath) {
|
|
2822
|
+
const hash = await fetchCognitiveFolderHash(entry.source, entry.cognitivePath);
|
|
2823
|
+
if (hash) cognitiveFolderHash = hash;
|
|
2467
2824
|
}
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
skillFiles: JSON.stringify(telemetry.skillFiles),
|
|
2475
|
-
...telemetry.sourceType && { sourceType: telemetry.sourceType }
|
|
2825
|
+
await addCognitiveToLock(entry.name, entry.cognitiveType, {
|
|
2826
|
+
source: entry.source,
|
|
2827
|
+
sourceType: entry.sourceType,
|
|
2828
|
+
sourceUrl: entry.sourceUrl,
|
|
2829
|
+
cognitivePath: entry.cognitivePath,
|
|
2830
|
+
cognitiveFolderHash
|
|
2476
2831
|
});
|
|
2477
|
-
}
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
if (!skillFolderHash && entry.sourceType === "github" && entry.skillPath) {
|
|
2483
|
-
const hash = await fetchSkillFolderHash(entry.source, entry.skillPath);
|
|
2484
|
-
if (hash) skillFolderHash = hash;
|
|
2485
|
-
}
|
|
2486
|
-
if (entry.isCognitive) await addCognitiveToLock(entry.name, entry.cognitiveType, {
|
|
2487
|
-
source: entry.source,
|
|
2488
|
-
sourceType: entry.sourceType,
|
|
2489
|
-
sourceUrl: entry.sourceUrl,
|
|
2490
|
-
skillPath: entry.skillPath,
|
|
2491
|
-
skillFolderHash
|
|
2492
|
-
});
|
|
2493
|
-
else await addSkillToLock(entry.name, {
|
|
2494
|
-
source: entry.source,
|
|
2495
|
-
sourceType: entry.sourceType,
|
|
2496
|
-
sourceUrl: entry.sourceUrl,
|
|
2497
|
-
skillFolderHash
|
|
2498
|
-
});
|
|
2499
|
-
} catch {}
|
|
2500
|
-
}
|
|
2832
|
+
} catch {}
|
|
2833
|
+
}
|
|
2834
|
+
function displayResults(results, targetAgents, cognitiveType, cwd) {
|
|
2835
|
+
const successful = results.filter((r) => r.success);
|
|
2836
|
+
const failed = results.filter((r) => !r.success);
|
|
2501
2837
|
if (successful.length > 0) {
|
|
2502
|
-
const
|
|
2838
|
+
const byName = /* @__PURE__ */ new Map();
|
|
2503
2839
|
for (const r of successful) {
|
|
2504
|
-
const
|
|
2505
|
-
|
|
2506
|
-
|
|
2840
|
+
const group = byName.get(r.name) || [];
|
|
2841
|
+
group.push(r);
|
|
2842
|
+
byName.set(r.name, group);
|
|
2507
2843
|
}
|
|
2508
|
-
const
|
|
2844
|
+
const itemCount = byName.size;
|
|
2509
2845
|
const resultLines = [];
|
|
2510
|
-
for (const [
|
|
2511
|
-
const firstResult =
|
|
2846
|
+
for (const [itemName, itemResults] of byName) {
|
|
2847
|
+
const firstResult = itemResults[0];
|
|
2512
2848
|
if (firstResult.mode === "copy") {
|
|
2513
|
-
resultLines.push(`${import_picocolors.default.green("✓")} ${
|
|
2514
|
-
for (const r of
|
|
2515
|
-
const shortPath = shortenPath
|
|
2849
|
+
resultLines.push(`${import_picocolors.default.green("✓")} ${itemName} ${import_picocolors.default.dim("(copied)")}`);
|
|
2850
|
+
for (const r of itemResults) {
|
|
2851
|
+
const shortPath = shortenPath(r.path, cwd);
|
|
2516
2852
|
resultLines.push(` ${import_picocolors.default.dim("→")} ${shortPath}`);
|
|
2517
2853
|
}
|
|
2518
2854
|
} else {
|
|
2519
2855
|
if (firstResult.canonicalPath) {
|
|
2520
|
-
const shortPath = shortenPath
|
|
2856
|
+
const shortPath = shortenPath(firstResult.canonicalPath, cwd);
|
|
2521
2857
|
resultLines.push(`${import_picocolors.default.green("✓")} ${shortPath}`);
|
|
2522
|
-
} else resultLines.push(`${import_picocolors.default.green("✓")} ${
|
|
2523
|
-
resultLines.push(...buildResultLines(
|
|
2858
|
+
} else resultLines.push(`${import_picocolors.default.green("✓")} ${itemName}`);
|
|
2859
|
+
resultLines.push(...buildResultLines(itemResults, targetAgents));
|
|
2524
2860
|
}
|
|
2525
2861
|
}
|
|
2526
|
-
const title = import_picocolors.default.green(`Installed ${
|
|
2862
|
+
const title = import_picocolors.default.green(`Installed ${itemCount} ${cognitiveType}${itemCount !== 1 ? "s" : ""}`);
|
|
2527
2863
|
logger.note(resultLines.join("\n"), title);
|
|
2528
2864
|
const symlinkFailures = successful.filter((r) => r.mode === "symlink" && r.symlinkFailed);
|
|
2529
2865
|
if (symlinkFailures.length > 0) {
|
|
2530
2866
|
const copiedAgentNames = symlinkFailures.map((r) => r.agent);
|
|
2531
|
-
logger.warning(import_picocolors.default.yellow(`Symlinks failed for: ${formatList
|
|
2867
|
+
logger.warning(import_picocolors.default.yellow(`Symlinks failed for: ${formatList(copiedAgentNames)}`));
|
|
2532
2868
|
logger.message(import_picocolors.default.dim("Files were copied instead. On Windows, enable Developer Mode for symlink support."));
|
|
2533
2869
|
}
|
|
2534
2870
|
}
|
|
2535
2871
|
if (failed.length > 0) {
|
|
2536
2872
|
logger.line();
|
|
2537
2873
|
logger.error(import_picocolors.default.red(`Failed to install ${failed.length}`));
|
|
2538
|
-
for (const r of failed) logger.message(`${import_picocolors.default.red("✗")} ${r.
|
|
2874
|
+
for (const r of failed) logger.message(`${import_picocolors.default.red("✗")} ${r.name} → ${r.agent}: ${import_picocolors.default.dim(r.error)}`);
|
|
2875
|
+
}
|
|
2876
|
+
}
|
|
2877
|
+
async function executeInstallFlow(prepared, options, spinner, cleanup) {
|
|
2878
|
+
const { items, targetAgents, installGlobally, installMode, cognitiveType } = prepared;
|
|
2879
|
+
const cwd = process.cwd();
|
|
2880
|
+
const summaryLines = buildInstallSummary(items, targetAgents, installGlobally, installMode, cognitiveType, await checkOverwrites(items, targetAgents, installGlobally, cognitiveType), cwd);
|
|
2881
|
+
logger.note(summaryLines.join("\n"), "Installation Summary");
|
|
2882
|
+
if (!options.yes) {
|
|
2883
|
+
const confirmed = await ye({ message: "Proceed with installation?" });
|
|
2884
|
+
if (pD(confirmed) || !confirmed) {
|
|
2885
|
+
logger.cancel("Installation cancelled");
|
|
2886
|
+
await cleanup?.();
|
|
2887
|
+
process.exit(0);
|
|
2888
|
+
}
|
|
2539
2889
|
}
|
|
2540
|
-
|
|
2890
|
+
const label = items.length === 1 ? `Installing ${cognitiveType}...` : `Installing ${cognitiveType}s...`;
|
|
2891
|
+
spinner.start(label);
|
|
2892
|
+
const results = await performInstalls(items, targetAgents, installGlobally, installMode);
|
|
2893
|
+
spinner.succeed("Installation complete");
|
|
2894
|
+
logger.line();
|
|
2895
|
+
const successful = results.filter((r) => r.success);
|
|
2896
|
+
const { telemetry } = prepared;
|
|
2897
|
+
if (telemetry.source) {
|
|
2898
|
+
let shouldTrack = true;
|
|
2899
|
+
if (telemetry.checkPrivacy) {
|
|
2900
|
+
if (await isSourcePrivate(telemetry.source) === true) shouldTrack = false;
|
|
2901
|
+
}
|
|
2902
|
+
if (shouldTrack) track({
|
|
2903
|
+
event: "install",
|
|
2904
|
+
source: telemetry.source,
|
|
2905
|
+
skills: items.map((i) => i.installName).join(","),
|
|
2906
|
+
agents: targetAgents.join(","),
|
|
2907
|
+
...installGlobally && { global: "1" },
|
|
2908
|
+
skillFiles: JSON.stringify(telemetry.skillFiles),
|
|
2909
|
+
...telemetry.sourceType && { sourceType: telemetry.sourceType }
|
|
2910
|
+
});
|
|
2911
|
+
}
|
|
2912
|
+
if (successful.length > 0 && installGlobally) await writeLockEntries(prepared, new Set(successful.map((r) => r.name)));
|
|
2913
|
+
displayResults(results, targetAgents, cognitiveType, cwd);
|
|
2914
|
+
logger.outro(import_picocolors.default.green("Done!") + import_picocolors.default.dim(" Review cognitives before use; they run with full agent permissions."));
|
|
2541
2915
|
await promptForFindSkills(options, targetAgents);
|
|
2542
2916
|
}
|
|
2543
|
-
async function
|
|
2917
|
+
async function selectCognitiveItems(items, options, cleanup) {
|
|
2918
|
+
const cognitiveType = options.type ?? "skill";
|
|
2919
|
+
const label = cognitiveType === "skill" ? "skills" : `${cognitiveType}s`;
|
|
2544
2920
|
if (options.skill?.includes("*")) {
|
|
2545
|
-
logger.info(`Installing all ${items.length}
|
|
2921
|
+
logger.info(`Installing all ${items.length} ${label}`);
|
|
2546
2922
|
return items;
|
|
2547
2923
|
}
|
|
2548
2924
|
if (options.skill && options.skill.length > 0) {
|
|
2549
2925
|
const selected = items.filter((s) => options.skill.some((name) => "installName" in s && s.installName?.toLowerCase() === name.toLowerCase() || s.name.toLowerCase() === name.toLowerCase()));
|
|
2550
2926
|
if (selected.length === 0) {
|
|
2551
|
-
logger.error(`No matching
|
|
2552
|
-
logger.info(
|
|
2927
|
+
logger.error(`No matching ${label} found for: ${options.skill.join(", ")}`);
|
|
2928
|
+
logger.info(`Available ${label}:`);
|
|
2553
2929
|
for (const s of items) logger.message(`- ${"installName" in s ? s.installName : s.name}`);
|
|
2554
2930
|
await cleanup?.();
|
|
2555
2931
|
process.exit(1);
|
|
2556
2932
|
}
|
|
2557
|
-
logger.info(`Selected ${selected.length}
|
|
2933
|
+
logger.info(`Selected ${selected.length} ${cognitiveType}${selected.length !== 1 ? "s" : ""}: ${selected.map((s) => import_picocolors.default.cyan("installName" in s ? s.installName : s.name)).join(", ")}`);
|
|
2558
2934
|
return selected;
|
|
2559
2935
|
}
|
|
2560
2936
|
if (items.length === 1) {
|
|
2561
2937
|
const first = items[0];
|
|
2562
|
-
logger.info(
|
|
2938
|
+
logger.info(`${cognitiveType}: ${import_picocolors.default.cyan("installName" in first ? first.installName : first.name)}`);
|
|
2563
2939
|
return items;
|
|
2564
2940
|
}
|
|
2565
2941
|
if (options.yes) {
|
|
2566
|
-
logger.info(`Installing all ${items.length}
|
|
2942
|
+
logger.info(`Installing all ${items.length} ${label}`);
|
|
2567
2943
|
return items;
|
|
2568
2944
|
}
|
|
2945
|
+
const cognitiveChoices = items.map((s) => ({
|
|
2946
|
+
value: s,
|
|
2947
|
+
label: "installName" in s ? s.installName : s.name,
|
|
2948
|
+
hint: s.description.length > 60 ? s.description.slice(0, 57) + "..." : s.description
|
|
2949
|
+
}));
|
|
2569
2950
|
const selected = await multiselect({
|
|
2570
|
-
message:
|
|
2571
|
-
options:
|
|
2572
|
-
value: s,
|
|
2573
|
-
label: "installName" in s ? s.installName : s.name,
|
|
2574
|
-
hint: s.description.length > 60 ? s.description.slice(0, 57) + "..." : s.description
|
|
2575
|
-
})),
|
|
2951
|
+
message: `Select ${label} to install`,
|
|
2952
|
+
options: cognitiveChoices,
|
|
2576
2953
|
required: true
|
|
2577
2954
|
});
|
|
2578
|
-
|
|
2579
|
-
logger.cancel("Installation cancelled");
|
|
2580
|
-
await cleanup?.();
|
|
2581
|
-
process.exit(0);
|
|
2582
|
-
}
|
|
2955
|
+
assertNotCancelled(selected, cleanup);
|
|
2583
2956
|
return selected;
|
|
2584
2957
|
}
|
|
2585
|
-
async function
|
|
2958
|
+
async function resolveRemoteCognitive(url, options, spinner) {
|
|
2586
2959
|
const provider = findProvider(url);
|
|
2587
|
-
if (!provider)
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
if (!providerSkill) {
|
|
2591
|
-
spinner.fail("Invalid skill");
|
|
2592
|
-
logger.outro(import_picocolors.default.red("Could not fetch skill.md or missing required frontmatter (name, description)."));
|
|
2960
|
+
if (!provider) {
|
|
2961
|
+
spinner.fail("Unsupported source host");
|
|
2962
|
+
logger.outro(import_picocolors.default.red("Could not find a provider for this URL. Supported hosts include Mintlify, HuggingFace, and well-known endpoints."));
|
|
2593
2963
|
process.exit(1);
|
|
2594
2964
|
}
|
|
2595
|
-
const
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2965
|
+
const cognitiveType = options.type ?? "skill";
|
|
2966
|
+
const cognitiveFile = COGNITIVE_FILE_NAMES[cognitiveType];
|
|
2967
|
+
spinner.start(`Fetching ${cognitiveFile} from ${provider.displayName}...`);
|
|
2968
|
+
const providerCognitive = await provider.fetchCognitive(url);
|
|
2969
|
+
if (!providerCognitive) {
|
|
2970
|
+
spinner.fail(`Invalid ${cognitiveType}`);
|
|
2971
|
+
logger.outro(import_picocolors.default.red(`Could not fetch ${cognitiveFile} or missing required frontmatter (name, description).`));
|
|
2972
|
+
process.exit(1);
|
|
2973
|
+
}
|
|
2974
|
+
const resolvedType = providerCognitive.cognitiveType ?? cognitiveType;
|
|
2975
|
+
const remoteCognitive = {
|
|
2976
|
+
name: providerCognitive.name,
|
|
2977
|
+
description: providerCognitive.description,
|
|
2978
|
+
content: providerCognitive.content,
|
|
2979
|
+
installName: providerCognitive.installName,
|
|
2980
|
+
sourceUrl: providerCognitive.sourceUrl,
|
|
2601
2981
|
providerId: provider.id,
|
|
2602
2982
|
sourceIdentifier: provider.getSourceIdentifier(url),
|
|
2603
|
-
metadata:
|
|
2983
|
+
metadata: providerCognitive.metadata,
|
|
2984
|
+
cognitiveType: resolvedType
|
|
2604
2985
|
};
|
|
2605
|
-
spinner.succeed(`Found
|
|
2606
|
-
logger.info(
|
|
2607
|
-
logger.message(import_picocolors.default.dim(
|
|
2608
|
-
logger.message(import_picocolors.default.dim(`Source: ${
|
|
2986
|
+
spinner.succeed(`Found ${resolvedType}: ${import_picocolors.default.cyan(remoteCognitive.installName)}`);
|
|
2987
|
+
logger.info(`${resolvedType}: ${import_picocolors.default.cyan(remoteCognitive.name)}`);
|
|
2988
|
+
logger.message(import_picocolors.default.dim(remoteCognitive.description));
|
|
2989
|
+
logger.message(import_picocolors.default.dim(`Source: ${remoteCognitive.sourceIdentifier}`));
|
|
2609
2990
|
if (options.list) {
|
|
2610
2991
|
logger.line();
|
|
2611
|
-
logger.step(import_picocolors.default.bold("
|
|
2612
|
-
logger.message(`${import_picocolors.default.cyan("Name:")} ${
|
|
2613
|
-
logger.message(`${import_picocolors.default.cyan("Install as:")} ${
|
|
2992
|
+
logger.step(import_picocolors.default.bold("Details"));
|
|
2993
|
+
logger.message(`${import_picocolors.default.cyan("Name:")} ${remoteCognitive.name}`);
|
|
2994
|
+
logger.message(`${import_picocolors.default.cyan("Install as:")} ${remoteCognitive.installName}`);
|
|
2614
2995
|
logger.message(`${import_picocolors.default.cyan("Provider:")} ${provider.displayName}`);
|
|
2615
|
-
logger.message(`${import_picocolors.default.cyan("Description:")} ${
|
|
2996
|
+
logger.message(`${import_picocolors.default.cyan("Description:")} ${remoteCognitive.description}`);
|
|
2616
2997
|
logger.outro("Run without --list to install");
|
|
2617
2998
|
process.exit(0);
|
|
2618
2999
|
}
|
|
2619
|
-
const targetAgents = await
|
|
2620
|
-
|
|
2621
|
-
|
|
3000
|
+
const { targetAgents, installGlobally, installMode } = await selectInstallContext(options, spinner, void 0, {
|
|
3001
|
+
useUniversalAgents: true,
|
|
3002
|
+
forceMode: provider.id === "mintlify" ? "symlink" : void 0
|
|
3003
|
+
});
|
|
2622
3004
|
return {
|
|
2623
3005
|
items: [{
|
|
2624
|
-
installName:
|
|
2625
|
-
displayName:
|
|
2626
|
-
description:
|
|
2627
|
-
sourceIdentifier:
|
|
2628
|
-
providerId:
|
|
3006
|
+
installName: remoteCognitive.installName,
|
|
3007
|
+
displayName: remoteCognitive.name,
|
|
3008
|
+
description: remoteCognitive.description,
|
|
3009
|
+
sourceIdentifier: remoteCognitive.sourceIdentifier,
|
|
3010
|
+
providerId: remoteCognitive.providerId,
|
|
2629
3011
|
sourceUrl: url,
|
|
2630
|
-
installFn: (agent, opts) =>
|
|
3012
|
+
installFn: (agent, opts) => installRemoteCognitiveForAgent(remoteCognitive, agent, {
|
|
3013
|
+
...opts,
|
|
3014
|
+
cognitiveType: resolvedType
|
|
3015
|
+
})
|
|
2631
3016
|
}],
|
|
2632
3017
|
targetAgents,
|
|
2633
3018
|
installGlobally,
|
|
2634
3019
|
installMode,
|
|
2635
|
-
cognitiveType:
|
|
2636
|
-
lockEntries: [{
|
|
2637
|
-
name:
|
|
2638
|
-
source:
|
|
2639
|
-
sourceType:
|
|
3020
|
+
cognitiveType: resolvedType,
|
|
3021
|
+
lockEntries: [buildLockEntry({
|
|
3022
|
+
name: remoteCognitive.installName,
|
|
3023
|
+
source: remoteCognitive.sourceIdentifier,
|
|
3024
|
+
sourceType: remoteCognitive.providerId,
|
|
2640
3025
|
sourceUrl: url,
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
isCognitive: false
|
|
2644
|
-
}],
|
|
3026
|
+
cognitiveType: resolvedType
|
|
3027
|
+
})],
|
|
2645
3028
|
telemetry: {
|
|
2646
|
-
source:
|
|
2647
|
-
sourceType:
|
|
2648
|
-
skillFiles: { [
|
|
3029
|
+
source: remoteCognitive.sourceIdentifier,
|
|
3030
|
+
sourceType: remoteCognitive.providerId,
|
|
3031
|
+
skillFiles: { [remoteCognitive.installName]: url },
|
|
2649
3032
|
checkPrivacy: true
|
|
2650
3033
|
}
|
|
2651
3034
|
};
|
|
2652
3035
|
}
|
|
2653
|
-
async function
|
|
2654
|
-
|
|
2655
|
-
const
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
const remoteSkill = {
|
|
2662
|
-
name: mintlifySkill.name,
|
|
2663
|
-
description: mintlifySkill.description,
|
|
2664
|
-
content: mintlifySkill.content,
|
|
2665
|
-
installName: mintlifySkill.mintlifySite,
|
|
2666
|
-
sourceUrl: mintlifySkill.sourceUrl,
|
|
2667
|
-
providerId: "mintlify",
|
|
2668
|
-
sourceIdentifier: "mintlify/com"
|
|
2669
|
-
};
|
|
2670
|
-
spinner.succeed(`Found skill: ${import_picocolors.default.cyan(remoteSkill.installName)}`);
|
|
2671
|
-
logger.info(`Skill: ${import_picocolors.default.cyan(remoteSkill.name)}`);
|
|
2672
|
-
logger.message(import_picocolors.default.dim(remoteSkill.description));
|
|
2673
|
-
if (options.list) {
|
|
2674
|
-
logger.line();
|
|
2675
|
-
logger.step(import_picocolors.default.bold("Skill Details"));
|
|
2676
|
-
logger.message(`${import_picocolors.default.cyan("Name:")} ${remoteSkill.name}`);
|
|
2677
|
-
logger.message(`${import_picocolors.default.cyan("Site:")} ${remoteSkill.installName}`);
|
|
2678
|
-
logger.message(`${import_picocolors.default.cyan("Description:")} ${remoteSkill.description}`);
|
|
2679
|
-
logger.outro("Run without --list to install");
|
|
2680
|
-
process.exit(0);
|
|
2681
|
-
}
|
|
2682
|
-
const targetAgents = await selectTargetAgents(options, spinner);
|
|
2683
|
-
const installGlobally = await selectInstallScope(options, targetAgents);
|
|
2684
|
-
return {
|
|
2685
|
-
items: [{
|
|
2686
|
-
installName: remoteSkill.installName,
|
|
2687
|
-
displayName: remoteSkill.name,
|
|
2688
|
-
description: remoteSkill.description,
|
|
2689
|
-
sourceIdentifier: "mintlify/com",
|
|
2690
|
-
providerId: "mintlify",
|
|
2691
|
-
sourceUrl: url,
|
|
2692
|
-
installFn: (agent, opts) => installRemoteSkillForAgent(remoteSkill, agent, opts)
|
|
2693
|
-
}],
|
|
2694
|
-
targetAgents,
|
|
2695
|
-
installGlobally,
|
|
2696
|
-
installMode: "symlink",
|
|
2697
|
-
cognitiveType: "skill",
|
|
2698
|
-
lockEntries: [{
|
|
2699
|
-
name: remoteSkill.installName,
|
|
2700
|
-
source: `mintlify/${remoteSkill.installName}`,
|
|
2701
|
-
sourceType: "mintlify",
|
|
2702
|
-
sourceUrl: url,
|
|
2703
|
-
skillFolderHash: "",
|
|
2704
|
-
cognitiveType: "skill",
|
|
2705
|
-
isCognitive: false
|
|
2706
|
-
}],
|
|
2707
|
-
telemetry: {
|
|
2708
|
-
source: "mintlify/com",
|
|
2709
|
-
sourceType: "mintlify",
|
|
2710
|
-
skillFiles: { [remoteSkill.installName]: url },
|
|
2711
|
-
checkPrivacy: false
|
|
2712
|
-
}
|
|
2713
|
-
};
|
|
2714
|
-
}
|
|
2715
|
-
async function resolveWellKnownSkills(source, url, options, spinner) {
|
|
2716
|
-
spinner.start("Discovering skills from well-known endpoint...");
|
|
2717
|
-
const skills = await wellKnownProvider.fetchAllSkills(url);
|
|
2718
|
-
if (skills.length === 0) {
|
|
2719
|
-
spinner.fail("No skills found");
|
|
2720
|
-
logger.outro(import_picocolors.default.red("No skills found at this URL. Make sure the server has a /.well-known/skills/index.json file."));
|
|
3036
|
+
async function resolveWellKnownCognitives(url, options, spinner) {
|
|
3037
|
+
const cognitiveType = options.type ?? "skill";
|
|
3038
|
+
const label = cognitiveType === "skill" ? "skills" : `${cognitiveType}s`;
|
|
3039
|
+
spinner.start(`Discovering ${label} from well-known endpoint...`);
|
|
3040
|
+
const cognitives = await wellKnownProvider.fetchAllCognitives(url);
|
|
3041
|
+
if (cognitives.length === 0) {
|
|
3042
|
+
spinner.fail(`No ${label} found`);
|
|
3043
|
+
logger.outro(import_picocolors.default.red(`No ${label} found at this URL. Make sure the server has a /.well-known/skills/index.json file.`));
|
|
2721
3044
|
process.exit(1);
|
|
2722
3045
|
}
|
|
2723
|
-
spinner.succeed(`Found ${import_picocolors.default.green(
|
|
2724
|
-
for (const
|
|
2725
|
-
logger.info(
|
|
2726
|
-
logger.message(import_picocolors.default.dim(
|
|
2727
|
-
if (
|
|
3046
|
+
spinner.succeed(`Found ${import_picocolors.default.green(cognitives.length)} ${cognitiveType}${cognitives.length > 1 ? "s" : ""}`);
|
|
3047
|
+
for (const item of cognitives) {
|
|
3048
|
+
logger.info(`${cognitiveType}: ${import_picocolors.default.cyan(item.installName)}`);
|
|
3049
|
+
logger.message(import_picocolors.default.dim(item.description));
|
|
3050
|
+
if (item.files.size > 1) logger.message(import_picocolors.default.dim(` Files: ${Array.from(item.files.keys()).join(", ")}`));
|
|
2728
3051
|
}
|
|
2729
3052
|
if (options.list) {
|
|
2730
3053
|
logger.line();
|
|
2731
|
-
logger.step(import_picocolors.default.bold(
|
|
2732
|
-
for (const
|
|
2733
|
-
logger.message(`${import_picocolors.default.cyan(
|
|
2734
|
-
logger.message(` ${import_picocolors.default.dim(
|
|
2735
|
-
if (
|
|
3054
|
+
logger.step(import_picocolors.default.bold(`Available ${label}`));
|
|
3055
|
+
for (const item of cognitives) {
|
|
3056
|
+
logger.message(`${import_picocolors.default.cyan(item.installName)}`);
|
|
3057
|
+
logger.message(` ${import_picocolors.default.dim(item.description)}`);
|
|
3058
|
+
if (item.files.size > 1) logger.message(` ${import_picocolors.default.dim(`Files: ${item.files.size}`)}`);
|
|
2736
3059
|
}
|
|
2737
3060
|
logger.outro("Run without --list to install");
|
|
2738
3061
|
process.exit(0);
|
|
2739
3062
|
}
|
|
2740
|
-
const
|
|
2741
|
-
const targetAgents = await
|
|
2742
|
-
const installGlobally = await selectInstallScope(options, targetAgents);
|
|
2743
|
-
const installMode = await selectInstallMode(options);
|
|
3063
|
+
const selectedCognitives = await selectCognitiveItems(cognitives, options);
|
|
3064
|
+
const { targetAgents, installGlobally, installMode } = await selectInstallContext(options, spinner);
|
|
2744
3065
|
const sourceIdentifier = wellKnownProvider.getSourceIdentifier(url);
|
|
2745
|
-
const items =
|
|
2746
|
-
installName:
|
|
2747
|
-
displayName:
|
|
2748
|
-
description:
|
|
3066
|
+
const items = selectedCognitives.map((cog) => ({
|
|
3067
|
+
installName: cog.installName,
|
|
3068
|
+
displayName: cog.name,
|
|
3069
|
+
description: cog.description,
|
|
2749
3070
|
sourceIdentifier,
|
|
2750
3071
|
providerId: "well-known",
|
|
2751
|
-
sourceUrl:
|
|
2752
|
-
fileCount:
|
|
2753
|
-
installFn: (agent, opts) =>
|
|
3072
|
+
sourceUrl: cog.sourceUrl,
|
|
3073
|
+
fileCount: cog.files.size,
|
|
3074
|
+
installFn: (agent, opts) => installWellKnownCognitiveForAgent(cog, agent, opts)
|
|
2754
3075
|
}));
|
|
2755
|
-
const
|
|
3076
|
+
const telemetryFiles = {};
|
|
2756
3077
|
const lockEntries = [];
|
|
2757
|
-
for (const
|
|
2758
|
-
|
|
2759
|
-
lockEntries.push({
|
|
2760
|
-
name:
|
|
3078
|
+
for (const cog of selectedCognitives) {
|
|
3079
|
+
telemetryFiles[cog.installName] = cog.sourceUrl;
|
|
3080
|
+
lockEntries.push(buildLockEntry({
|
|
3081
|
+
name: cog.installName,
|
|
2761
3082
|
source: sourceIdentifier,
|
|
2762
3083
|
sourceType: "well-known",
|
|
2763
|
-
sourceUrl:
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
isCognitive: false
|
|
2767
|
-
});
|
|
3084
|
+
sourceUrl: cog.sourceUrl,
|
|
3085
|
+
cognitiveType: cog.cognitiveType ?? cognitiveType
|
|
3086
|
+
}));
|
|
2768
3087
|
}
|
|
2769
3088
|
return {
|
|
2770
3089
|
items,
|
|
2771
3090
|
targetAgents,
|
|
2772
3091
|
installGlobally,
|
|
2773
3092
|
installMode,
|
|
2774
|
-
cognitiveType:
|
|
3093
|
+
cognitiveType: selectedCognitives[0]?.cognitiveType ?? cognitiveType,
|
|
2775
3094
|
lockEntries,
|
|
2776
3095
|
telemetry: {
|
|
2777
3096
|
source: sourceIdentifier,
|
|
2778
3097
|
sourceType: "well-known",
|
|
2779
|
-
skillFiles,
|
|
3098
|
+
skillFiles: telemetryFiles,
|
|
2780
3099
|
checkPrivacy: true
|
|
2781
3100
|
}
|
|
2782
3101
|
};
|
|
2783
3102
|
}
|
|
2784
|
-
async function
|
|
3103
|
+
async function resolveGitRepoCognitives(source, parsed, options, spinner, sourceDir, tempDir) {
|
|
2785
3104
|
const cleanupFn = async () => {
|
|
2786
3105
|
await cleanupDir(tempDir);
|
|
2787
3106
|
};
|
|
2788
3107
|
const cognitiveType = options.type ?? "skill";
|
|
2789
|
-
const
|
|
2790
|
-
const cognitiveFile = cognitiveType
|
|
3108
|
+
const label = cognitiveType === "skill" ? "skills" : `${cognitiveType}s`;
|
|
3109
|
+
const cognitiveFile = COGNITIVE_FILE_NAMES[cognitiveType];
|
|
2791
3110
|
const includeInternal = !!(options.skill && options.skill.length > 0);
|
|
2792
|
-
spinner.start(`Discovering ${
|
|
2793
|
-
const
|
|
3111
|
+
spinner.start(`Discovering ${label}...`);
|
|
3112
|
+
const cognitives = await discoverCognitives(sourceDir, parsed.subpath, {
|
|
2794
3113
|
includeInternal,
|
|
2795
3114
|
fullDepth: options.fullDepth,
|
|
2796
|
-
types: [options.type]
|
|
2797
|
-
}) : await discoverSkills(skillsDir, parsed.subpath, {
|
|
2798
|
-
includeInternal,
|
|
2799
|
-
fullDepth: options.fullDepth
|
|
3115
|
+
types: options.type ? [options.type] : ["skill"]
|
|
2800
3116
|
});
|
|
2801
|
-
if (
|
|
2802
|
-
spinner.fail(`No ${
|
|
2803
|
-
logger.outro(import_picocolors.default.red(`No valid ${
|
|
3117
|
+
if (cognitives.length === 0) {
|
|
3118
|
+
spinner.fail(`No ${label} found`);
|
|
3119
|
+
logger.outro(import_picocolors.default.red(`No valid ${label} found. They require a ${cognitiveFile} with name and description.`));
|
|
2804
3120
|
await cleanupFn();
|
|
2805
3121
|
process.exit(1);
|
|
2806
3122
|
}
|
|
2807
|
-
spinner.succeed(`Found ${import_picocolors.default.green(
|
|
3123
|
+
spinner.succeed(`Found ${import_picocolors.default.green(cognitives.length)} ${cognitiveType}${cognitives.length > 1 ? "s" : ""}`);
|
|
2808
3124
|
if (options.list) {
|
|
2809
3125
|
logger.line();
|
|
2810
|
-
logger.step(import_picocolors.default.bold(
|
|
2811
|
-
for (const
|
|
2812
|
-
logger.message(`${import_picocolors.default.cyan(
|
|
2813
|
-
logger.message(` ${import_picocolors.default.dim(
|
|
3126
|
+
logger.step(import_picocolors.default.bold(`Available ${label}`));
|
|
3127
|
+
for (const cog of cognitives) {
|
|
3128
|
+
logger.message(`${import_picocolors.default.cyan(getCognitiveDisplayName(cog))}`);
|
|
3129
|
+
logger.message(` ${import_picocolors.default.dim(cog.description)}`);
|
|
2814
3130
|
}
|
|
2815
|
-
logger.outro(
|
|
3131
|
+
logger.outro(`Use --skill <name> to install specific ${label}`);
|
|
2816
3132
|
await cleanupFn();
|
|
2817
3133
|
process.exit(0);
|
|
2818
3134
|
}
|
|
2819
|
-
let
|
|
2820
|
-
if (options.skill
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
logger.error(`No matching skills found for: ${options.skill.join(", ")}`);
|
|
2827
|
-
logger.info("Available skills:");
|
|
2828
|
-
for (const s of skills) logger.message(`- ${getSkillDisplayName(s)}`);
|
|
3135
|
+
let selectedCognitives;
|
|
3136
|
+
if (options.skill && options.skill.length > 0 && !options.skill.includes("*")) {
|
|
3137
|
+
selectedCognitives = filterCognitives(cognitives, options.skill);
|
|
3138
|
+
if (selectedCognitives.length === 0) {
|
|
3139
|
+
logger.error(`No matching ${label} found for: ${options.skill.join(", ")}`);
|
|
3140
|
+
logger.info(`Available ${label}:`);
|
|
3141
|
+
for (const s of cognitives) logger.message(`- ${getCognitiveDisplayName(s)}`);
|
|
2829
3142
|
await cleanupFn();
|
|
2830
3143
|
process.exit(1);
|
|
2831
3144
|
}
|
|
2832
|
-
logger.info(`Selected ${
|
|
2833
|
-
} else
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
}
|
|
2839
|
-
selectedSkills = skills;
|
|
2840
|
-
logger.info(`Installing all ${skills.length} skills`);
|
|
2841
|
-
} else {
|
|
2842
|
-
const selected = await multiselect({
|
|
2843
|
-
message: "Select skills to install",
|
|
2844
|
-
options: skills.map((s) => ({
|
|
2845
|
-
value: s,
|
|
2846
|
-
label: getSkillDisplayName(s),
|
|
2847
|
-
hint: s.description.length > 60 ? s.description.slice(0, 57) + "..." : s.description
|
|
2848
|
-
})),
|
|
2849
|
-
required: true
|
|
2850
|
-
});
|
|
2851
|
-
if (pD(selected)) {
|
|
2852
|
-
logger.cancel("Installation cancelled");
|
|
2853
|
-
await cleanupFn();
|
|
2854
|
-
process.exit(0);
|
|
2855
|
-
}
|
|
2856
|
-
selectedSkills = selected;
|
|
2857
|
-
}
|
|
2858
|
-
const targetAgents = await selectTargetAgents(options, spinner, cleanupFn);
|
|
2859
|
-
const installGlobally = await selectInstallScope(options, targetAgents, cleanupFn);
|
|
2860
|
-
const installMode = await selectInstallMode(options, cleanupFn);
|
|
3145
|
+
logger.info(`Selected ${selectedCognitives.length} ${cognitiveType}${selectedCognitives.length !== 1 ? "s" : ""}: ${selectedCognitives.map((s) => import_picocolors.default.cyan(getCognitiveDisplayName(s))).join(", ")}`);
|
|
3146
|
+
} else selectedCognitives = (await selectCognitiveItems(cognitives.map((s) => ({
|
|
3147
|
+
installName: s.name,
|
|
3148
|
+
name: getCognitiveDisplayName(s),
|
|
3149
|
+
description: s.description
|
|
3150
|
+
})), options, cleanupFn)).map((s) => cognitives.find((c) => c.name === s.installName));
|
|
3151
|
+
const { targetAgents, installGlobally, installMode } = await selectInstallContext(options, spinner, cleanupFn);
|
|
2861
3152
|
const normalizedSource = getOwnerRepo(parsed);
|
|
2862
|
-
const
|
|
2863
|
-
for (const
|
|
3153
|
+
const telemetryFiles = {};
|
|
3154
|
+
for (const cog of selectedCognitives) {
|
|
2864
3155
|
let relativePath;
|
|
2865
|
-
if (tempDir &&
|
|
2866
|
-
else if (tempDir &&
|
|
3156
|
+
if (tempDir && cog.path === tempDir) relativePath = cognitiveFile;
|
|
3157
|
+
else if (tempDir && cog.path.startsWith(tempDir + sep)) relativePath = cog.path.slice(tempDir.length + 1).split(sep).join("/") + `/${cognitiveFile}`;
|
|
2867
3158
|
else continue;
|
|
2868
|
-
|
|
3159
|
+
telemetryFiles[cog.name] = relativePath;
|
|
2869
3160
|
}
|
|
2870
|
-
const items =
|
|
2871
|
-
installName:
|
|
2872
|
-
displayName:
|
|
2873
|
-
description:
|
|
3161
|
+
const items = selectedCognitives.map((cog) => ({
|
|
3162
|
+
installName: cog.name,
|
|
3163
|
+
displayName: getCognitiveDisplayName(cog),
|
|
3164
|
+
description: cog.description,
|
|
2874
3165
|
sourceIdentifier: normalizedSource ?? source,
|
|
2875
3166
|
providerId: parsed.type,
|
|
2876
3167
|
sourceUrl: parsed.url,
|
|
2877
|
-
installFn: (agent, opts) => installCognitiveForAgent(
|
|
3168
|
+
installFn: (agent, opts) => installCognitiveForAgent(cog, agent, {
|
|
2878
3169
|
...opts,
|
|
2879
3170
|
cognitiveType
|
|
2880
3171
|
})
|
|
2881
3172
|
}));
|
|
2882
3173
|
const lockEntries = [];
|
|
2883
|
-
if (normalizedSource) for (const
|
|
2884
|
-
name:
|
|
3174
|
+
if (normalizedSource) for (const cog of selectedCognitives) lockEntries.push(buildLockEntry({
|
|
3175
|
+
name: getCognitiveDisplayName(cog),
|
|
2885
3176
|
source: normalizedSource,
|
|
2886
3177
|
sourceType: parsed.type,
|
|
2887
3178
|
sourceUrl: parsed.url,
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
isCognitive: true
|
|
2892
|
-
});
|
|
3179
|
+
cognitivePath: telemetryFiles[cog.name],
|
|
3180
|
+
cognitiveType
|
|
3181
|
+
}));
|
|
2893
3182
|
let telemetrySource = normalizedSource ?? "";
|
|
2894
3183
|
if (normalizedSource) {
|
|
2895
3184
|
const ownerRepo = parseOwnerRepo(normalizedSource);
|
|
2896
|
-
if (ownerRepo)
|
|
3185
|
+
if (ownerRepo) {
|
|
3186
|
+
if (await isRepoPrivate(ownerRepo.owner, ownerRepo.repo) !== false) telemetrySource = "";
|
|
3187
|
+
}
|
|
2897
3188
|
}
|
|
2898
3189
|
return {
|
|
2899
3190
|
items,
|
|
@@ -2904,7 +3195,7 @@ async function resolveGitRepoSkills(source, parsed, options, spinner, skillsDir,
|
|
|
2904
3195
|
lockEntries,
|
|
2905
3196
|
telemetry: {
|
|
2906
3197
|
source: telemetrySource,
|
|
2907
|
-
skillFiles,
|
|
3198
|
+
skillFiles: telemetryFiles,
|
|
2908
3199
|
checkPrivacy: false
|
|
2909
3200
|
}
|
|
2910
3201
|
};
|
|
@@ -2941,16 +3232,16 @@ async function runAdd(args, options = {}) {
|
|
|
2941
3232
|
const spinner = logger.spinner();
|
|
2942
3233
|
spinner.start("Parsing source...");
|
|
2943
3234
|
const parsed = parseSource(source);
|
|
2944
|
-
spinner.succeed(`Source: ${parsed.type === "local" ? parsed.localPath : parsed.url}${parsed.ref ? ` @ ${import_picocolors.default.yellow(parsed.ref)}` : ""}${parsed.subpath ? ` (${parsed.subpath})` : ""}${parsed.
|
|
3235
|
+
spinner.succeed(`Source: ${parsed.type === "local" ? parsed.localPath : parsed.url}${parsed.ref ? ` @ ${import_picocolors.default.yellow(parsed.ref)}` : ""}${parsed.subpath ? ` (${parsed.subpath})` : ""}${parsed.nameFilter ? ` ${import_picocolors.default.dim("@")}${import_picocolors.default.cyan(parsed.nameFilter)}` : ""}`);
|
|
2945
3236
|
if (parsed.type === "direct-url") {
|
|
2946
|
-
await executeInstallFlow(await
|
|
3237
|
+
await executeInstallFlow(await resolveRemoteCognitive(parsed.url, options, spinner), options, spinner);
|
|
2947
3238
|
return;
|
|
2948
3239
|
}
|
|
2949
3240
|
if (parsed.type === "well-known") {
|
|
2950
|
-
await executeInstallFlow(await
|
|
3241
|
+
await executeInstallFlow(await resolveWellKnownCognitives(parsed.url, options, spinner), options, spinner);
|
|
2951
3242
|
return;
|
|
2952
3243
|
}
|
|
2953
|
-
let
|
|
3244
|
+
let sourceDir;
|
|
2954
3245
|
if (parsed.type === "local") {
|
|
2955
3246
|
spinner.start("Validating local path...");
|
|
2956
3247
|
if (!existsSync(parsed.localPath)) {
|
|
@@ -2958,19 +3249,19 @@ async function runAdd(args, options = {}) {
|
|
|
2958
3249
|
logger.outro(import_picocolors.default.red(`Local path does not exist: ${parsed.localPath}`));
|
|
2959
3250
|
process.exit(1);
|
|
2960
3251
|
}
|
|
2961
|
-
|
|
3252
|
+
sourceDir = parsed.localPath;
|
|
2962
3253
|
spinner.succeed("Local path validated");
|
|
2963
3254
|
} else {
|
|
2964
3255
|
spinner.start("Cloning repository...");
|
|
2965
3256
|
tempDir = await cloneRepo(parsed.url, parsed.ref);
|
|
2966
|
-
|
|
3257
|
+
sourceDir = tempDir;
|
|
2967
3258
|
spinner.succeed("Repository cloned");
|
|
2968
3259
|
}
|
|
2969
|
-
if (parsed.
|
|
3260
|
+
if (parsed.nameFilter) {
|
|
2970
3261
|
options.skill = options.skill || [];
|
|
2971
|
-
if (!options.skill.includes(parsed.
|
|
3262
|
+
if (!options.skill.includes(parsed.nameFilter)) options.skill.push(parsed.nameFilter);
|
|
2972
3263
|
}
|
|
2973
|
-
const prepared = await
|
|
3264
|
+
const prepared = await resolveGitRepoCognitives(source, parsed, options, spinner, sourceDir, tempDir);
|
|
2974
3265
|
const cleanupFn = async () => {
|
|
2975
3266
|
await cleanupDir(tempDir);
|
|
2976
3267
|
};
|
|
@@ -2997,7 +3288,7 @@ async function promptForFindSkills(options, targetAgents) {
|
|
|
2997
3288
|
if (options?.yes) return;
|
|
2998
3289
|
try {
|
|
2999
3290
|
if (await isPromptDismissed("findSkillsPrompt")) return;
|
|
3000
|
-
if (await
|
|
3291
|
+
if (await isCognitiveInstalled("find-skills", "claude-code", "skill", { global: true })) {
|
|
3001
3292
|
await dismissPrompt("findSkillsPrompt");
|
|
3002
3293
|
return;
|
|
3003
3294
|
}
|
|
@@ -3063,7 +3354,7 @@ function parseAddOptions(args) {
|
|
|
3063
3354
|
} else if (arg === "-t" || arg === "--type") {
|
|
3064
3355
|
i++;
|
|
3065
3356
|
const typeVal = args[i];
|
|
3066
|
-
if (typeVal
|
|
3357
|
+
if (typeVal && Object.keys(COGNITIVE_FILE_NAMES).includes(typeVal)) options.type = typeVal;
|
|
3067
3358
|
} else if (arg === "--full-depth") options.fullDepth = true;
|
|
3068
3359
|
else if (arg && !arg.startsWith("-")) source.push(arg);
|
|
3069
3360
|
}
|
|
@@ -3280,18 +3571,6 @@ ${import_picocolors.default.dim(" 2) npx synk add <owner/repo@skill>")}`;
|
|
|
3280
3571
|
else logger.log(`${import_picocolors.default.dim("Discover more skills at")} https://skills.sh`);
|
|
3281
3572
|
logger.line();
|
|
3282
3573
|
}
|
|
3283
|
-
function shortenPath(fullPath, cwd) {
|
|
3284
|
-
const home = homedir();
|
|
3285
|
-
if (fullPath.startsWith(home)) return fullPath.replace(home, "~");
|
|
3286
|
-
if (fullPath.startsWith(cwd)) return "." + fullPath.slice(cwd.length);
|
|
3287
|
-
return fullPath;
|
|
3288
|
-
}
|
|
3289
|
-
function formatList(items, maxShow = 5) {
|
|
3290
|
-
if (items.length <= maxShow) return items.join(", ");
|
|
3291
|
-
const shown = items.slice(0, maxShow);
|
|
3292
|
-
const remaining = items.length - maxShow;
|
|
3293
|
-
return `${shown.join(", ")} +${remaining} more`;
|
|
3294
|
-
}
|
|
3295
3574
|
function parseListOptions(args) {
|
|
3296
3575
|
const options = {};
|
|
3297
3576
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -3303,7 +3582,7 @@ function parseListOptions(args) {
|
|
|
3303
3582
|
} else if (arg === "-t" || arg === "--type") {
|
|
3304
3583
|
i++;
|
|
3305
3584
|
const typeVal = args[i];
|
|
3306
|
-
if (typeVal
|
|
3585
|
+
if (typeVal && Object.keys(COGNITIVE_FILE_NAMES).includes(typeVal)) options.type = typeVal;
|
|
3307
3586
|
}
|
|
3308
3587
|
}
|
|
3309
3588
|
return options;
|
|
@@ -3312,25 +3591,16 @@ async function runList(args) {
|
|
|
3312
3591
|
const options = parseListOptions(args);
|
|
3313
3592
|
const scope = options.global === true ? true : false;
|
|
3314
3593
|
let agentFilter;
|
|
3315
|
-
if (options.agent && options.agent.length > 0)
|
|
3316
|
-
|
|
3317
|
-
const invalidAgents = options.agent.filter((a) => !validAgents.includes(a));
|
|
3318
|
-
if (invalidAgents.length > 0) {
|
|
3319
|
-
logger.warning(`Invalid agents: ${invalidAgents.join(", ")}`);
|
|
3320
|
-
logger.dim(`Valid agents: ${validAgents.join(", ")}`);
|
|
3321
|
-
process.exit(1);
|
|
3322
|
-
}
|
|
3323
|
-
agentFilter = options.agent;
|
|
3324
|
-
}
|
|
3325
|
-
const installedSkills = await listInstalledSkills({
|
|
3594
|
+
if (options.agent && options.agent.length > 0) agentFilter = validateAgentNames(options.agent);
|
|
3595
|
+
const installedCognitives = await listInstalledCognitives({
|
|
3326
3596
|
global: scope,
|
|
3327
3597
|
agentFilter
|
|
3328
3598
|
});
|
|
3329
|
-
const
|
|
3599
|
+
const filteredCognitives = options.type ? installedCognitives.filter((s) => (s.cognitiveType || "skill") === options.type) : installedCognitives;
|
|
3330
3600
|
const cwd = process.cwd();
|
|
3331
3601
|
const scopeLabel = scope ? "Global" : "Project";
|
|
3332
3602
|
const typeLabel = options.type ? ` ${options.type}s` : "";
|
|
3333
|
-
if (
|
|
3603
|
+
if (filteredCognitives.length === 0) {
|
|
3334
3604
|
logger.dim(`No ${scopeLabel.toLowerCase()}${typeLabel} found.`);
|
|
3335
3605
|
if (scope) logger.dim("Try listing project cognitives without -g");
|
|
3336
3606
|
else logger.dim("Try listing global cognitives with -g");
|
|
@@ -3351,13 +3621,13 @@ async function runList(args) {
|
|
|
3351
3621
|
}
|
|
3352
3622
|
logger.bold(`${scopeLabel}${typeLabel ? typeLabel.charAt(0).toUpperCase() + typeLabel.slice(1) : " Cognitives"}`);
|
|
3353
3623
|
logger.line();
|
|
3354
|
-
for (const skill of
|
|
3624
|
+
for (const skill of filteredCognitives) printSkill(skill);
|
|
3355
3625
|
logger.line();
|
|
3356
3626
|
}
|
|
3357
3627
|
async function removeCommand(skillNames, options) {
|
|
3358
3628
|
const isGlobal = options.global ?? false;
|
|
3359
3629
|
const cwd = process.cwd();
|
|
3360
|
-
const spinner = logger.spinner("Scanning for installed
|
|
3630
|
+
const spinner = logger.spinner("Scanning for installed cognitives...");
|
|
3361
3631
|
const skillNamesSet = /* @__PURE__ */ new Set();
|
|
3362
3632
|
const scanDir = async (dir) => {
|
|
3363
3633
|
try {
|
|
@@ -3367,36 +3637,27 @@ async function removeCommand(skillNames, options) {
|
|
|
3367
3637
|
if (err instanceof Error && err.code !== "ENOENT") logger.warning(`Could not scan directory ${dir}: ${err.message}`);
|
|
3368
3638
|
}
|
|
3369
3639
|
};
|
|
3370
|
-
const typesToScan = options.type ? [options.type] :
|
|
3371
|
-
"skill",
|
|
3372
|
-
"agent",
|
|
3373
|
-
"prompt"
|
|
3374
|
-
];
|
|
3640
|
+
const typesToScan = options.type ? [options.type] : Object.keys(COGNITIVE_FILE_NAMES);
|
|
3375
3641
|
for (const cogType of typesToScan) if (isGlobal) {
|
|
3376
3642
|
await scanDir(getCanonicalDir(cogType, true, cwd));
|
|
3377
3643
|
for (const agent of Object.values(agents)) {
|
|
3378
|
-
const dir =
|
|
3644
|
+
const dir = agent.dirs[cogType].global;
|
|
3379
3645
|
if (dir !== void 0) await scanDir(dir);
|
|
3380
3646
|
}
|
|
3381
3647
|
} else {
|
|
3382
3648
|
await scanDir(getCanonicalDir(cogType, false, cwd));
|
|
3383
|
-
for (const agent of Object.values(agents))
|
|
3649
|
+
for (const agent of Object.values(agents)) {
|
|
3650
|
+
const dir = agent.dirs[cogType].local;
|
|
3651
|
+
await scanDir(join(cwd, dir));
|
|
3652
|
+
}
|
|
3384
3653
|
}
|
|
3385
3654
|
const installedSkills = Array.from(skillNamesSet).sort();
|
|
3386
|
-
spinner.succeed(`Found ${installedSkills.length} unique installed
|
|
3655
|
+
spinner.succeed(`Found ${installedSkills.length} unique installed cognitive(s)`);
|
|
3387
3656
|
if (installedSkills.length === 0) {
|
|
3388
|
-
logger.outro(import_picocolors.default.yellow("No
|
|
3657
|
+
logger.outro(import_picocolors.default.yellow("No cognitives found to remove."));
|
|
3389
3658
|
return;
|
|
3390
3659
|
}
|
|
3391
|
-
if (options.agent && options.agent.length > 0)
|
|
3392
|
-
const validAgents = Object.keys(agents);
|
|
3393
|
-
const invalidAgents = options.agent.filter((a) => !validAgents.includes(a));
|
|
3394
|
-
if (invalidAgents.length > 0) {
|
|
3395
|
-
logger.error(`Invalid agents: ${invalidAgents.join(", ")}`);
|
|
3396
|
-
logger.info(`Valid agents: ${validAgents.join(", ")}`);
|
|
3397
|
-
process.exit(1);
|
|
3398
|
-
}
|
|
3399
|
-
}
|
|
3660
|
+
if (options.agent && options.agent.length > 0) validateAgentNames(options.agent);
|
|
3400
3661
|
let selectedSkills = [];
|
|
3401
3662
|
if (options.all) selectedSkills = installedSkills;
|
|
3402
3663
|
else if (skillNames.length > 0) {
|
|
@@ -3411,14 +3672,11 @@ async function removeCommand(skillNames, options) {
|
|
|
3411
3672
|
label: s
|
|
3412
3673
|
}));
|
|
3413
3674
|
const selected = await fe({
|
|
3414
|
-
message: `Select
|
|
3675
|
+
message: `Select cognitives to remove ${import_picocolors.default.dim("(space to toggle)")}`,
|
|
3415
3676
|
options: choices,
|
|
3416
3677
|
required: true
|
|
3417
3678
|
});
|
|
3418
|
-
|
|
3419
|
-
logger.cancel("Removal cancelled");
|
|
3420
|
-
process.exit(0);
|
|
3421
|
-
}
|
|
3679
|
+
assertNotCancelled(selected);
|
|
3422
3680
|
selectedSkills = selected;
|
|
3423
3681
|
}
|
|
3424
3682
|
let targetAgents;
|
|
@@ -3431,16 +3689,17 @@ async function removeCommand(skillNames, options) {
|
|
|
3431
3689
|
}
|
|
3432
3690
|
if (!options.yes) {
|
|
3433
3691
|
logger.line();
|
|
3434
|
-
logger.info("
|
|
3692
|
+
logger.info("Cognitives to remove:");
|
|
3435
3693
|
for (const skill of selectedSkills) logger.message(`${import_picocolors.default.red("•")} ${skill}`);
|
|
3436
3694
|
logger.line();
|
|
3437
|
-
const confirmed = await ye({ message: `Are you sure you want to uninstall ${selectedSkills.length}
|
|
3438
|
-
|
|
3695
|
+
const confirmed = await ye({ message: `Are you sure you want to uninstall ${selectedSkills.length} cognitive(s)?` });
|
|
3696
|
+
assertNotCancelled(confirmed);
|
|
3697
|
+
if (!confirmed) {
|
|
3439
3698
|
logger.cancel("Removal cancelled");
|
|
3440
3699
|
process.exit(0);
|
|
3441
3700
|
}
|
|
3442
3701
|
}
|
|
3443
|
-
spinner.start("Removing
|
|
3702
|
+
spinner.start("Removing cognitives...");
|
|
3444
3703
|
const results = [];
|
|
3445
3704
|
for (const skillName of selectedSkills) try {
|
|
3446
3705
|
for (const agentKey of targetAgents) {
|
|
@@ -3466,10 +3725,10 @@ async function removeCommand(skillNames, options) {
|
|
|
3466
3725
|
recursive: true,
|
|
3467
3726
|
force: true
|
|
3468
3727
|
});
|
|
3469
|
-
const lockEntry = isGlobal ? await
|
|
3728
|
+
const lockEntry = isGlobal ? await getCognitiveFromLock(skillName) : null;
|
|
3470
3729
|
const effectiveSource = lockEntry?.source || "local";
|
|
3471
3730
|
const effectiveSourceType = lockEntry?.sourceType || "local";
|
|
3472
|
-
if (isGlobal) await
|
|
3731
|
+
if (isGlobal) await removeCognitiveFromLock(skillName);
|
|
3473
3732
|
results.push({
|
|
3474
3733
|
skill: skillName,
|
|
3475
3734
|
success: true,
|
|
@@ -3504,9 +3763,9 @@ async function removeCommand(skillNames, options) {
|
|
|
3504
3763
|
sourceType: data.sourceType
|
|
3505
3764
|
});
|
|
3506
3765
|
}
|
|
3507
|
-
if (successful.length > 0) logger.success(import_picocolors.default.green(`Successfully removed ${successful.length}
|
|
3766
|
+
if (successful.length > 0) logger.success(import_picocolors.default.green(`Successfully removed ${successful.length} cognitive(s)`));
|
|
3508
3767
|
if (failed.length > 0) {
|
|
3509
|
-
logger.error(import_picocolors.default.red(`Failed to remove ${failed.length}
|
|
3768
|
+
logger.error(import_picocolors.default.red(`Failed to remove ${failed.length} cognitive(s)`));
|
|
3510
3769
|
for (const r of failed) logger.message(`${import_picocolors.default.red("✗")} ${r.skill}: ${r.error}`);
|
|
3511
3770
|
}
|
|
3512
3771
|
logger.line();
|
|
@@ -3533,7 +3792,7 @@ function parseRemoveOptions(args) {
|
|
|
3533
3792
|
} else if (arg === "-t" || arg === "--type") {
|
|
3534
3793
|
i++;
|
|
3535
3794
|
const typeVal = args[i];
|
|
3536
|
-
if (typeVal
|
|
3795
|
+
if (typeVal && Object.keys(COGNITIVE_FILE_NAMES).includes(typeVal)) options.type = typeVal;
|
|
3537
3796
|
} else if (arg && !arg.startsWith("-")) skills.push(arg);
|
|
3538
3797
|
}
|
|
3539
3798
|
return {
|
|
@@ -3549,17 +3808,13 @@ function runInit(args) {
|
|
|
3549
3808
|
const arg = args[i];
|
|
3550
3809
|
if ((arg === "-t" || arg === "--type") && i + 1 < args.length) {
|
|
3551
3810
|
const typeVal = args[i + 1];
|
|
3552
|
-
if (typeVal
|
|
3811
|
+
if (typeVal && Object.keys(COGNITIVE_FILE_NAMES).includes(typeVal)) cognitiveType = typeVal;
|
|
3553
3812
|
i++;
|
|
3554
3813
|
} else if (arg && !arg.startsWith("-")) filteredArgs.push(arg);
|
|
3555
3814
|
}
|
|
3556
3815
|
const itemName = filteredArgs[0] || basename(cwd);
|
|
3557
3816
|
const hasName = filteredArgs[0] !== void 0;
|
|
3558
|
-
const fileName =
|
|
3559
|
-
skill: "SKILL.md",
|
|
3560
|
-
agent: "AGENT.md",
|
|
3561
|
-
prompt: "PROMPT.md"
|
|
3562
|
-
}[cognitiveType];
|
|
3817
|
+
const fileName = COGNITIVE_FILE_NAMES[cognitiveType];
|
|
3563
3818
|
const itemDir = hasName ? join(cwd, itemName) : cwd;
|
|
3564
3819
|
const itemFile = join(itemDir, fileName);
|
|
3565
3820
|
const displayPath = hasName ? `${itemName}/${fileName}` : fileName;
|
|
@@ -3639,70 +3894,43 @@ Describe when this skill should be used.
|
|
|
3639
3894
|
logger.log(` ${import_picocolors.default.dim("URL:")} Host the file, then ${import_picocolors.default.cyan(`npx synk add https://example.com/${displayPath}`)}`);
|
|
3640
3895
|
logger.line();
|
|
3641
3896
|
}
|
|
3642
|
-
const AGENTS_DIR$1 = ".agents";
|
|
3643
|
-
const LOCK_FILE$1 = ".skill-lock.json";
|
|
3644
|
-
const CURRENT_LOCK_VERSION$1 = 4;
|
|
3645
|
-
function getSkillLockPath$1() {
|
|
3646
|
-
return join(homedir(), AGENTS_DIR$1, LOCK_FILE$1);
|
|
3647
|
-
}
|
|
3648
|
-
function readSkillLock$1() {
|
|
3649
|
-
const lockPath = getSkillLockPath$1();
|
|
3650
|
-
try {
|
|
3651
|
-
const content = readFileSync(lockPath, "utf-8");
|
|
3652
|
-
const parsed = JSON.parse(content);
|
|
3653
|
-
if (typeof parsed.version !== "number" || !parsed.skills) return {
|
|
3654
|
-
version: CURRENT_LOCK_VERSION$1,
|
|
3655
|
-
skills: {}
|
|
3656
|
-
};
|
|
3657
|
-
if (parsed.version < CURRENT_LOCK_VERSION$1) return {
|
|
3658
|
-
version: CURRENT_LOCK_VERSION$1,
|
|
3659
|
-
skills: {}
|
|
3660
|
-
};
|
|
3661
|
-
return parsed;
|
|
3662
|
-
} catch {
|
|
3663
|
-
return {
|
|
3664
|
-
version: CURRENT_LOCK_VERSION$1,
|
|
3665
|
-
skills: {}
|
|
3666
|
-
};
|
|
3667
|
-
}
|
|
3668
|
-
}
|
|
3669
3897
|
async function runCheck(args = []) {
|
|
3670
|
-
logger.log(
|
|
3898
|
+
logger.log("Checking for updates...");
|
|
3671
3899
|
logger.line();
|
|
3672
|
-
const lock =
|
|
3673
|
-
const
|
|
3674
|
-
if (
|
|
3675
|
-
logger.dim("No
|
|
3676
|
-
logger.log(`${import_picocolors.default.dim("Install
|
|
3900
|
+
const lock = await readLockFile();
|
|
3901
|
+
const cognitiveNames = Object.keys(lock.cognitives);
|
|
3902
|
+
if (cognitiveNames.length === 0) {
|
|
3903
|
+
logger.dim("No cognitives tracked in lock file.");
|
|
3904
|
+
logger.log(`${import_picocolors.default.dim("Install cognitives with")} npx synk add <package>`);
|
|
3677
3905
|
return;
|
|
3678
3906
|
}
|
|
3679
3907
|
const token = getGitHubToken();
|
|
3680
|
-
const
|
|
3908
|
+
const cognitivesBySource = /* @__PURE__ */ new Map();
|
|
3681
3909
|
let skippedCount = 0;
|
|
3682
|
-
for (const
|
|
3683
|
-
const entry = lock.
|
|
3910
|
+
for (const name of cognitiveNames) {
|
|
3911
|
+
const entry = lock.cognitives[name];
|
|
3684
3912
|
if (!entry) continue;
|
|
3685
|
-
if (entry.sourceType !== "github" || !entry.
|
|
3913
|
+
if (entry.sourceType !== "github" || !entry.cognitiveFolderHash || !entry.cognitivePath) {
|
|
3686
3914
|
skippedCount++;
|
|
3687
3915
|
continue;
|
|
3688
3916
|
}
|
|
3689
|
-
const existing =
|
|
3917
|
+
const existing = cognitivesBySource.get(entry.source) || [];
|
|
3690
3918
|
existing.push({
|
|
3691
|
-
name
|
|
3919
|
+
name,
|
|
3692
3920
|
entry
|
|
3693
3921
|
});
|
|
3694
|
-
|
|
3922
|
+
cognitivesBySource.set(entry.source, existing);
|
|
3695
3923
|
}
|
|
3696
|
-
const
|
|
3697
|
-
if (
|
|
3698
|
-
logger.dim("No GitHub
|
|
3924
|
+
const totalCognitives = cognitiveNames.length - skippedCount;
|
|
3925
|
+
if (totalCognitives === 0) {
|
|
3926
|
+
logger.dim("No GitHub cognitives to check.");
|
|
3699
3927
|
return;
|
|
3700
3928
|
}
|
|
3701
|
-
logger.dim(`Checking ${
|
|
3929
|
+
logger.dim(`Checking ${totalCognitives} cognitive(s) for updates...`);
|
|
3702
3930
|
const updates = [];
|
|
3703
3931
|
const errors = [];
|
|
3704
|
-
for (const [source,
|
|
3705
|
-
const latestHash = await
|
|
3932
|
+
for (const [source, cognitives] of cognitivesBySource) for (const { name, entry } of cognitives) try {
|
|
3933
|
+
const latestHash = await fetchCognitiveFolderHash(source, entry.cognitivePath, token);
|
|
3706
3934
|
if (!latestHash) {
|
|
3707
3935
|
errors.push({
|
|
3708
3936
|
name,
|
|
@@ -3711,7 +3939,7 @@ async function runCheck(args = []) {
|
|
|
3711
3939
|
});
|
|
3712
3940
|
continue;
|
|
3713
3941
|
}
|
|
3714
|
-
if (latestHash !== entry.
|
|
3942
|
+
if (latestHash !== entry.cognitiveFolderHash) updates.push({
|
|
3715
3943
|
name,
|
|
3716
3944
|
source
|
|
3717
3945
|
});
|
|
@@ -3723,7 +3951,7 @@ async function runCheck(args = []) {
|
|
|
3723
3951
|
});
|
|
3724
3952
|
}
|
|
3725
3953
|
logger.line();
|
|
3726
|
-
if (updates.length === 0) logger.success("All
|
|
3954
|
+
if (updates.length === 0) logger.success("All cognitives are up to date");
|
|
3727
3955
|
else {
|
|
3728
3956
|
logger.log(`${updates.length} update(s) available:`);
|
|
3729
3957
|
logger.line();
|
|
@@ -3732,75 +3960,48 @@ async function runCheck(args = []) {
|
|
|
3732
3960
|
logger.dim(` source: ${update.source}`);
|
|
3733
3961
|
}
|
|
3734
3962
|
logger.line();
|
|
3735
|
-
logger.log(`${import_picocolors.default.dim("Run")} npx synk update ${import_picocolors.default.dim("to update all
|
|
3963
|
+
logger.log(`${import_picocolors.default.dim("Run")} npx synk update ${import_picocolors.default.dim("to update all cognitives")}`);
|
|
3736
3964
|
}
|
|
3737
3965
|
if (errors.length > 0) {
|
|
3738
3966
|
logger.line();
|
|
3739
|
-
logger.dim(`Could not check ${errors.length}
|
|
3967
|
+
logger.dim(`Could not check ${errors.length} cognitive(s) (may need reinstall)`);
|
|
3740
3968
|
}
|
|
3741
3969
|
track({
|
|
3742
3970
|
event: "check",
|
|
3743
|
-
skillCount: String(
|
|
3971
|
+
skillCount: String(totalCognitives),
|
|
3744
3972
|
updatesAvailable: String(updates.length)
|
|
3745
3973
|
});
|
|
3746
3974
|
logger.line();
|
|
3747
3975
|
}
|
|
3748
|
-
const AGENTS_DIR = ".agents";
|
|
3749
|
-
const LOCK_FILE = ".skill-lock.json";
|
|
3750
|
-
const CURRENT_LOCK_VERSION = 4;
|
|
3751
|
-
function getSkillLockPath() {
|
|
3752
|
-
return join(homedir(), AGENTS_DIR, LOCK_FILE);
|
|
3753
|
-
}
|
|
3754
|
-
function readSkillLock() {
|
|
3755
|
-
const lockPath = getSkillLockPath();
|
|
3756
|
-
try {
|
|
3757
|
-
const content = readFileSync(lockPath, "utf-8");
|
|
3758
|
-
const parsed = JSON.parse(content);
|
|
3759
|
-
if (typeof parsed.version !== "number" || !parsed.skills) return {
|
|
3760
|
-
version: CURRENT_LOCK_VERSION,
|
|
3761
|
-
skills: {}
|
|
3762
|
-
};
|
|
3763
|
-
if (parsed.version < CURRENT_LOCK_VERSION) return {
|
|
3764
|
-
version: CURRENT_LOCK_VERSION,
|
|
3765
|
-
skills: {}
|
|
3766
|
-
};
|
|
3767
|
-
return parsed;
|
|
3768
|
-
} catch {
|
|
3769
|
-
return {
|
|
3770
|
-
version: CURRENT_LOCK_VERSION,
|
|
3771
|
-
skills: {}
|
|
3772
|
-
};
|
|
3773
|
-
}
|
|
3774
|
-
}
|
|
3775
3976
|
async function runUpdate() {
|
|
3776
|
-
logger.log("Checking for
|
|
3977
|
+
logger.log("Checking for updates...");
|
|
3777
3978
|
logger.line();
|
|
3778
|
-
const lock =
|
|
3779
|
-
const
|
|
3780
|
-
if (
|
|
3781
|
-
logger.dim("No
|
|
3782
|
-
logger.log(`${import_picocolors.default.dim("Install
|
|
3979
|
+
const lock = await readLockFile();
|
|
3980
|
+
const cognitiveNames = Object.keys(lock.cognitives);
|
|
3981
|
+
if (cognitiveNames.length === 0) {
|
|
3982
|
+
logger.dim("No cognitives tracked in lock file.");
|
|
3983
|
+
logger.log(`${import_picocolors.default.dim("Install cognitives with")} npx synk add <package>`);
|
|
3783
3984
|
return;
|
|
3784
3985
|
}
|
|
3785
3986
|
const token = getGitHubToken();
|
|
3786
3987
|
const updates = [];
|
|
3787
3988
|
let checkedCount = 0;
|
|
3788
|
-
for (const
|
|
3789
|
-
const entry = lock.
|
|
3989
|
+
for (const name of cognitiveNames) {
|
|
3990
|
+
const entry = lock.cognitives[name];
|
|
3790
3991
|
if (!entry) continue;
|
|
3791
|
-
if (entry.sourceType !== "github" || !entry.
|
|
3992
|
+
if (entry.sourceType !== "github" || !entry.cognitiveFolderHash || !entry.cognitivePath) continue;
|
|
3792
3993
|
checkedCount++;
|
|
3793
3994
|
try {
|
|
3794
|
-
const latestHash = await
|
|
3795
|
-
if (latestHash && latestHash !== entry.
|
|
3796
|
-
name
|
|
3995
|
+
const latestHash = await fetchCognitiveFolderHash(entry.source, entry.cognitivePath, token);
|
|
3996
|
+
if (latestHash && latestHash !== entry.cognitiveFolderHash) updates.push({
|
|
3997
|
+
name,
|
|
3797
3998
|
source: entry.source,
|
|
3798
3999
|
entry
|
|
3799
4000
|
});
|
|
3800
4001
|
} catch {}
|
|
3801
4002
|
}
|
|
3802
4003
|
if (checkedCount === 0) {
|
|
3803
|
-
logger.dim("No
|
|
4004
|
+
logger.dim("No cognitives to check.");
|
|
3804
4005
|
return;
|
|
3805
4006
|
}
|
|
3806
4007
|
if (updates.length === 0) {
|
|
@@ -3815,17 +4016,22 @@ async function runUpdate() {
|
|
|
3815
4016
|
for (const update of updates) {
|
|
3816
4017
|
logger.log(`Updating ${update.name}...`);
|
|
3817
4018
|
let installUrl = update.entry.sourceUrl;
|
|
3818
|
-
if (update.entry.
|
|
3819
|
-
let skillFolder = update.entry.
|
|
3820
|
-
if (skillFolder.endsWith("/
|
|
3821
|
-
|
|
4019
|
+
if (update.entry.cognitivePath) {
|
|
4020
|
+
let skillFolder = update.entry.cognitivePath;
|
|
4021
|
+
for (const fileName of Object.values(COGNITIVE_FILE_NAMES)) if (skillFolder.endsWith("/" + fileName)) {
|
|
4022
|
+
skillFolder = skillFolder.slice(0, -(fileName.length + 1));
|
|
4023
|
+
break;
|
|
4024
|
+
} else if (skillFolder.endsWith(fileName)) {
|
|
4025
|
+
skillFolder = skillFolder.slice(0, -fileName.length);
|
|
4026
|
+
break;
|
|
4027
|
+
}
|
|
3822
4028
|
if (skillFolder.endsWith("/")) skillFolder = skillFolder.slice(0, -1);
|
|
3823
4029
|
installUrl = update.entry.sourceUrl.replace(/\.git$/, "").replace(/\/$/, "");
|
|
3824
4030
|
installUrl = `${installUrl}/tree/main/${skillFolder}`;
|
|
3825
4031
|
}
|
|
3826
4032
|
if (spawnSync("npx", [
|
|
3827
4033
|
"-y",
|
|
3828
|
-
"
|
|
4034
|
+
"synk",
|
|
3829
4035
|
"add",
|
|
3830
4036
|
installUrl,
|
|
3831
4037
|
"-g",
|
|
@@ -3843,8 +4049,8 @@ async function runUpdate() {
|
|
|
3843
4049
|
}
|
|
3844
4050
|
}
|
|
3845
4051
|
logger.line();
|
|
3846
|
-
if (successCount > 0) logger.success(`Updated ${successCount}
|
|
3847
|
-
if (failCount > 0) logger.dim(`Failed to update ${failCount}
|
|
4052
|
+
if (successCount > 0) logger.success(`Updated ${successCount} cognitive(s)`);
|
|
4053
|
+
if (failCount > 0) logger.dim(`Failed to update ${failCount} cognitive(s)`);
|
|
3848
4054
|
track({
|
|
3849
4055
|
event: "update",
|
|
3850
4056
|
skillCount: String(updates.length),
|