skillops-cli 1.3.6 → 1.3.8
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.js +273 -64
- package/dist/index.d.ts +69 -3
- package/dist/index.js +307 -57
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -10,7 +10,7 @@ import YAML6 from "yaml";
|
|
|
10
10
|
import fs from "fs";
|
|
11
11
|
import YAML from "yaml";
|
|
12
12
|
import { z } from "zod";
|
|
13
|
-
var SKILLOPS_VERSION = "1.3.
|
|
13
|
+
var SKILLOPS_VERSION = "1.3.8";
|
|
14
14
|
var SKILL_NAME_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
15
15
|
var SEMVER_REGEX = /^\d+\.\d+\.\d+$/;
|
|
16
16
|
var FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
|
|
@@ -1426,9 +1426,104 @@ import fs3 from "fs";
|
|
|
1426
1426
|
import path2 from "path";
|
|
1427
1427
|
import YAML2 from "yaml";
|
|
1428
1428
|
|
|
1429
|
-
// src/ui/
|
|
1429
|
+
// src/ui/lipgloss.ts
|
|
1430
1430
|
var ESC = String.fromCharCode(27);
|
|
1431
|
-
var
|
|
1431
|
+
var CHARM_PALETTE = {
|
|
1432
|
+
indigo: "#7D56F4",
|
|
1433
|
+
fuchsia: "#EE6FF8",
|
|
1434
|
+
hotPink: "#F25D94",
|
|
1435
|
+
mint: "#04B575",
|
|
1436
|
+
amber: "#FFBD2E",
|
|
1437
|
+
coral: "#FF5F56",
|
|
1438
|
+
cyan: "#00D7FF",
|
|
1439
|
+
lavender: "#B4A7D6",
|
|
1440
|
+
white: "#FAFAFA",
|
|
1441
|
+
muted: "#6C6C6C",
|
|
1442
|
+
subtle: "#4A4A4A",
|
|
1443
|
+
surface: "#2A2438",
|
|
1444
|
+
keycapBg: "#302B3F"
|
|
1445
|
+
};
|
|
1446
|
+
function hexToRgb(hex) {
|
|
1447
|
+
const cleaned = hex.trim().replace(/^#/, "");
|
|
1448
|
+
if (cleaned.length === 3) {
|
|
1449
|
+
const r2 = Number.parseInt(`${cleaned[0]}${cleaned[0]}`, 16);
|
|
1450
|
+
const g2 = Number.parseInt(`${cleaned[1]}${cleaned[1]}`, 16);
|
|
1451
|
+
const b2 = Number.parseInt(`${cleaned[2]}${cleaned[2]}`, 16);
|
|
1452
|
+
return [
|
|
1453
|
+
Number.isNaN(r2) ? 255 : r2,
|
|
1454
|
+
Number.isNaN(g2) ? 255 : g2,
|
|
1455
|
+
Number.isNaN(b2) ? 255 : b2
|
|
1456
|
+
];
|
|
1457
|
+
}
|
|
1458
|
+
const r = Number.parseInt(cleaned.slice(0, 2), 16);
|
|
1459
|
+
const g = Number.parseInt(cleaned.slice(2, 4), 16);
|
|
1460
|
+
const b = Number.parseInt(cleaned.slice(4, 6), 16);
|
|
1461
|
+
return [
|
|
1462
|
+
Number.isNaN(r) ? 255 : r,
|
|
1463
|
+
Number.isNaN(g) ? 255 : g,
|
|
1464
|
+
Number.isNaN(b) ? 255 : b
|
|
1465
|
+
];
|
|
1466
|
+
}
|
|
1467
|
+
function fgHex(hex, text, enabled) {
|
|
1468
|
+
const useColor = enabled ?? isColorEnabled();
|
|
1469
|
+
if (!useColor || text.length === 0) {
|
|
1470
|
+
return text;
|
|
1471
|
+
}
|
|
1472
|
+
const [r, g, b] = hexToRgb(hex);
|
|
1473
|
+
return `${ESC}[38;2;${r};${g};${b}m${text}${ESC}[39m`;
|
|
1474
|
+
}
|
|
1475
|
+
function bgHex(hex, text, enabled) {
|
|
1476
|
+
const useColor = enabled ?? isColorEnabled();
|
|
1477
|
+
if (!useColor || text.length === 0) {
|
|
1478
|
+
return text;
|
|
1479
|
+
}
|
|
1480
|
+
const [r, g, b] = hexToRgb(hex);
|
|
1481
|
+
return `${ESC}[48;2;${r};${g};${b}m${text}${ESC}[49m`;
|
|
1482
|
+
}
|
|
1483
|
+
function renderPill(text, options) {
|
|
1484
|
+
const useColor = options?.colorEnabled ?? isColorEnabled();
|
|
1485
|
+
if (!useColor || text.length === 0) {
|
|
1486
|
+
return text;
|
|
1487
|
+
}
|
|
1488
|
+
const fg = options?.fg ?? CHARM_PALETTE.white;
|
|
1489
|
+
const bg = options?.bg ?? CHARM_PALETTE.indigo;
|
|
1490
|
+
const bold = options?.bold ?? true;
|
|
1491
|
+
let styled = fgHex(fg, text, true);
|
|
1492
|
+
styled = bgHex(bg, styled, true);
|
|
1493
|
+
if (bold) {
|
|
1494
|
+
styled = `${ESC}[1m${styled}${ESC}[22m`;
|
|
1495
|
+
}
|
|
1496
|
+
return styled;
|
|
1497
|
+
}
|
|
1498
|
+
function renderKeycap(keyLabel, actionLabel, colorEnabled) {
|
|
1499
|
+
const useColor = colorEnabled ?? isColorEnabled();
|
|
1500
|
+
if (!useColor) {
|
|
1501
|
+
return `${keyLabel} ${actionLabel}`;
|
|
1502
|
+
}
|
|
1503
|
+
const keyStyled = `${ESC}[1m${fgHex(CHARM_PALETTE.lavender, keyLabel, true)}${ESC}[22m`;
|
|
1504
|
+
const actionStyled = fgHex(CHARM_PALETTE.muted, actionLabel, true);
|
|
1505
|
+
return `${keyStyled} ${actionStyled}`;
|
|
1506
|
+
}
|
|
1507
|
+
function renderPaginationDots(currentPage, totalPages, colorEnabled) {
|
|
1508
|
+
const safeTotal = Math.max(1, Math.min(12, totalPages));
|
|
1509
|
+
const safeCurrent = Math.max(0, Math.min(safeTotal - 1, currentPage));
|
|
1510
|
+
const useColor = colorEnabled ?? isColorEnabled();
|
|
1511
|
+
const dots = [];
|
|
1512
|
+
for (let i = 0; i < safeTotal; i++) {
|
|
1513
|
+
if (i === safeCurrent) {
|
|
1514
|
+
dots.push(
|
|
1515
|
+
useColor ? `${ESC}[1m${fgHex(CHARM_PALETTE.hotPink, "\u2022", true)}${ESC}[22m` : "\u2022"
|
|
1516
|
+
);
|
|
1517
|
+
} else {
|
|
1518
|
+
dots.push(useColor ? fgHex(CHARM_PALETTE.muted, "\u25E6", true) : "\u25E6");
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
return dots.join(" ");
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
// src/ui/terminal.ts
|
|
1525
|
+
var ESC2 = String.fromCharCode(27);
|
|
1526
|
+
var ANSI_ESCAPE_REGEX = new RegExp(`${ESC2}\\[[0-9;]*m`, "g");
|
|
1432
1527
|
function isColorEnabled(options) {
|
|
1433
1528
|
const env = options?.env ?? process.env;
|
|
1434
1529
|
const isTTY = options?.isTTY ?? Boolean(process.stdout?.isTTY);
|
|
@@ -1454,21 +1549,21 @@ function wrapAnsi(openCode, closeCode, text, enabled) {
|
|
|
1454
1549
|
if (!useColor || text.length === 0) {
|
|
1455
1550
|
return text;
|
|
1456
1551
|
}
|
|
1457
|
-
return `${
|
|
1552
|
+
return `${ESC2}[${openCode}m${text}${ESC2}[${closeCode}m`;
|
|
1458
1553
|
}
|
|
1459
1554
|
var style = {
|
|
1460
1555
|
bold: (text, enabled) => wrapAnsi("1", "22", text, enabled),
|
|
1461
1556
|
dim: (text, enabled) => wrapAnsi("2", "22", text, enabled),
|
|
1462
1557
|
italic: (text, enabled) => wrapAnsi("3", "23", text, enabled),
|
|
1463
1558
|
underline: (text, enabled) => wrapAnsi("4", "24", text, enabled),
|
|
1464
|
-
cyan: (text, enabled) =>
|
|
1465
|
-
green: (text, enabled) =>
|
|
1466
|
-
yellow: (text, enabled) =>
|
|
1467
|
-
red: (text, enabled) =>
|
|
1468
|
-
magenta: (text, enabled) =>
|
|
1469
|
-
blue: (text, enabled) =>
|
|
1470
|
-
gray: (text, enabled) =>
|
|
1471
|
-
white: (text, enabled) =>
|
|
1559
|
+
cyan: (text, enabled) => fgHex(CHARM_PALETTE.cyan, text, enabled),
|
|
1560
|
+
green: (text, enabled) => fgHex(CHARM_PALETTE.mint, text, enabled),
|
|
1561
|
+
yellow: (text, enabled) => fgHex(CHARM_PALETTE.amber, text, enabled),
|
|
1562
|
+
red: (text, enabled) => fgHex(CHARM_PALETTE.coral, text, enabled),
|
|
1563
|
+
magenta: (text, enabled) => fgHex(CHARM_PALETTE.fuchsia, text, enabled),
|
|
1564
|
+
blue: (text, enabled) => fgHex(CHARM_PALETTE.indigo, text, enabled),
|
|
1565
|
+
gray: (text, enabled) => fgHex(CHARM_PALETTE.muted, text, enabled),
|
|
1566
|
+
white: (text, enabled) => fgHex(CHARM_PALETTE.white, text, enabled)
|
|
1472
1567
|
};
|
|
1473
1568
|
function stripAnsi(text) {
|
|
1474
1569
|
return text.replace(ANSI_ESCAPE_REGEX, "");
|
|
@@ -1495,7 +1590,13 @@ function padVisible(text, width, align = "left") {
|
|
|
1495
1590
|
function renderHeaderBanner(subtitle = "Framework & Library for AI Skills & Subagents", options) {
|
|
1496
1591
|
const ver = options?.version ?? SKILLOPS_VERSION;
|
|
1497
1592
|
const c = options?.colorEnabled;
|
|
1498
|
-
|
|
1593
|
+
const brandPill = renderPill(`\u25C6 SkillOps v${ver}`, {
|
|
1594
|
+
fg: CHARM_PALETTE.white,
|
|
1595
|
+
bg: CHARM_PALETTE.indigo,
|
|
1596
|
+
bold: true,
|
|
1597
|
+
colorEnabled: c
|
|
1598
|
+
});
|
|
1599
|
+
return `${brandPill} ${style.dim("\u2014", c)} ${fgHex(CHARM_PALETTE.lavender, subtitle, c)}`;
|
|
1499
1600
|
}
|
|
1500
1601
|
function renderTable(headers, rows, options) {
|
|
1501
1602
|
const indent = " ".repeat(options?.indent ?? 2);
|
|
@@ -1572,15 +1673,19 @@ function formatBadge(type, customLabel, colorEnabled) {
|
|
|
1572
1673
|
colorEnabled
|
|
1573
1674
|
);
|
|
1574
1675
|
case "skill":
|
|
1575
|
-
return
|
|
1576
|
-
|
|
1676
|
+
return renderPill(`[${customLabel ?? "SKILL"}]`, {
|
|
1677
|
+
fg: CHARM_PALETTE.white,
|
|
1678
|
+
bg: CHARM_PALETTE.indigo,
|
|
1679
|
+
bold: true,
|
|
1577
1680
|
colorEnabled
|
|
1578
|
-
);
|
|
1681
|
+
});
|
|
1579
1682
|
case "subagent":
|
|
1580
|
-
return
|
|
1581
|
-
|
|
1683
|
+
return renderPill(`[${customLabel ?? "SUBAGENT"}]`, {
|
|
1684
|
+
fg: CHARM_PALETTE.white,
|
|
1685
|
+
bg: CHARM_PALETTE.hotPink,
|
|
1686
|
+
bold: true,
|
|
1582
1687
|
colorEnabled
|
|
1583
|
-
);
|
|
1688
|
+
});
|
|
1584
1689
|
}
|
|
1585
1690
|
}
|
|
1586
1691
|
function renderStep(step, total, title, detail, status = "done", colorEnabled) {
|
|
@@ -5412,6 +5517,9 @@ function optionMatchesQuery(opt, rawQuery) {
|
|
|
5412
5517
|
if (!q) {
|
|
5413
5518
|
return true;
|
|
5414
5519
|
}
|
|
5520
|
+
if (opt.isSelectAll) {
|
|
5521
|
+
return false;
|
|
5522
|
+
}
|
|
5415
5523
|
return opt.label.toLowerCase().includes(q) || opt.value.toLowerCase().includes(q) || (opt.hint ?? "").toLowerCase().includes(q);
|
|
5416
5524
|
}
|
|
5417
5525
|
function getFilteredTabOptions(state, tab = state.activeTab) {
|
|
@@ -5419,16 +5527,47 @@ function getFilteredTabOptions(state, tab = state.activeTab) {
|
|
|
5419
5527
|
(opt) => optionMatchesTab(opt, tab) && optionMatchesQuery(opt, state.searchQuery)
|
|
5420
5528
|
);
|
|
5421
5529
|
}
|
|
5422
|
-
function createMultiSelectState(options) {
|
|
5530
|
+
function createMultiSelectState(options, stateOptions = {}) {
|
|
5531
|
+
let finalOptions = options;
|
|
5532
|
+
if (stateOptions.showSelectAll && !options.some((opt) => opt.isSelectAll === true)) {
|
|
5533
|
+
const skillItems = options.filter((opt) => optionMatchesTab(opt, "skill"));
|
|
5534
|
+
const agentItems = options.filter((opt) => optionMatchesTab(opt, "agent"));
|
|
5535
|
+
const withAll = [];
|
|
5536
|
+
if (skillItems.length > 0) {
|
|
5537
|
+
withAll.push({
|
|
5538
|
+
value: "__all_skills__",
|
|
5539
|
+
label: "[ALL] Select all Skills",
|
|
5540
|
+
kind: "skill",
|
|
5541
|
+
tab: "skill",
|
|
5542
|
+
isSelectAll: true,
|
|
5543
|
+
hint: `Select or deselect all ${skillItems.length} Skills in this tab`
|
|
5544
|
+
});
|
|
5545
|
+
withAll.push(...skillItems);
|
|
5546
|
+
}
|
|
5547
|
+
if (agentItems.length > 0) {
|
|
5548
|
+
withAll.push({
|
|
5549
|
+
value: "__all_agents__",
|
|
5550
|
+
label: "[ALL] Select all Agents",
|
|
5551
|
+
kind: "agent",
|
|
5552
|
+
tab: "agent",
|
|
5553
|
+
isSelectAll: true,
|
|
5554
|
+
hint: `Select or deselect all ${agentItems.length} Agents in this tab`
|
|
5555
|
+
});
|
|
5556
|
+
withAll.push(...agentItems);
|
|
5557
|
+
}
|
|
5558
|
+
if (withAll.length > 0) {
|
|
5559
|
+
finalOptions = withAll;
|
|
5560
|
+
}
|
|
5561
|
+
}
|
|
5423
5562
|
const initial = /* @__PURE__ */ new Set();
|
|
5424
|
-
for (const opt of
|
|
5425
|
-
if (opt.initialSelected) {
|
|
5563
|
+
for (const opt of finalOptions) {
|
|
5564
|
+
if (opt.initialSelected && !opt.isSelectAll) {
|
|
5426
5565
|
initial.add(opt.value);
|
|
5427
5566
|
}
|
|
5428
5567
|
}
|
|
5429
|
-
const hasSkills =
|
|
5568
|
+
const hasSkills = finalOptions.some((opt) => optionMatchesTab(opt, "skill"));
|
|
5430
5569
|
return {
|
|
5431
|
-
options,
|
|
5570
|
+
options: finalOptions,
|
|
5432
5571
|
activeTab: hasSkills ? "skill" : "agent",
|
|
5433
5572
|
cursor: 0,
|
|
5434
5573
|
selected: initial,
|
|
@@ -5518,6 +5657,29 @@ function applyMultiSelectKey(state, key, options = {}) {
|
|
|
5518
5657
|
if (!currentOpt) {
|
|
5519
5658
|
return state;
|
|
5520
5659
|
}
|
|
5660
|
+
if (currentOpt.isSelectAll) {
|
|
5661
|
+
const realVisible = visible.filter((opt) => !opt.isSelectAll);
|
|
5662
|
+
if (realVisible.length === 0) {
|
|
5663
|
+
return state;
|
|
5664
|
+
}
|
|
5665
|
+
const allTabSelected = realVisible.every(
|
|
5666
|
+
(opt) => state.selected.has(opt.value)
|
|
5667
|
+
);
|
|
5668
|
+
const nextSelected2 = new Set(state.selected);
|
|
5669
|
+
if (allTabSelected) {
|
|
5670
|
+
for (const opt of realVisible) {
|
|
5671
|
+
nextSelected2.delete(opt.value);
|
|
5672
|
+
}
|
|
5673
|
+
} else {
|
|
5674
|
+
for (const opt of realVisible) {
|
|
5675
|
+
nextSelected2.add(opt.value);
|
|
5676
|
+
}
|
|
5677
|
+
}
|
|
5678
|
+
return {
|
|
5679
|
+
...state,
|
|
5680
|
+
selected: nextSelected2
|
|
5681
|
+
};
|
|
5682
|
+
}
|
|
5521
5683
|
const nextSelected = new Set(state.selected);
|
|
5522
5684
|
if (nextSelected.has(currentOpt.value)) {
|
|
5523
5685
|
nextSelected.delete(currentOpt.value);
|
|
@@ -5581,19 +5743,20 @@ function applyMultiSelectKey(state, key, options = {}) {
|
|
|
5581
5743
|
};
|
|
5582
5744
|
}
|
|
5583
5745
|
if (key === "a" || key === "A") {
|
|
5584
|
-
|
|
5746
|
+
const realVisible = visible.filter((opt) => !opt.isSelectAll);
|
|
5747
|
+
if (realVisible.length === 0) {
|
|
5585
5748
|
return state;
|
|
5586
5749
|
}
|
|
5587
|
-
const allTabSelected =
|
|
5750
|
+
const allTabSelected = realVisible.every(
|
|
5588
5751
|
(opt) => state.selected.has(opt.value)
|
|
5589
5752
|
);
|
|
5590
5753
|
const nextSelected = new Set(state.selected);
|
|
5591
5754
|
if (allTabSelected) {
|
|
5592
|
-
for (const opt of
|
|
5755
|
+
for (const opt of realVisible) {
|
|
5593
5756
|
nextSelected.delete(opt.value);
|
|
5594
5757
|
}
|
|
5595
5758
|
} else {
|
|
5596
|
-
for (const opt of
|
|
5759
|
+
for (const opt of realVisible) {
|
|
5597
5760
|
nextSelected.add(opt.value);
|
|
5598
5761
|
}
|
|
5599
5762
|
}
|
|
@@ -5608,41 +5771,69 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5608
5771
|
const c = options.colorEnabled;
|
|
5609
5772
|
const bar = style.dim("\u2502", c);
|
|
5610
5773
|
const maxVisible = options.maxVisible ?? 10;
|
|
5611
|
-
const
|
|
5774
|
+
const realOptions = state.options.filter((o) => !o.isSelectAll);
|
|
5775
|
+
const totalSkills = realOptions.filter(
|
|
5612
5776
|
(o) => optionMatchesTab(o, "skill")
|
|
5613
5777
|
).length;
|
|
5614
|
-
const totalAgents =
|
|
5778
|
+
const totalAgents = realOptions.filter(
|
|
5615
5779
|
(o) => optionMatchesTab(o, "agent")
|
|
5616
5780
|
).length;
|
|
5617
5781
|
const filteredSkills = getFilteredTabOptions(state, "skill");
|
|
5618
5782
|
const filteredAgents = getFilteredTabOptions(state, "agent");
|
|
5783
|
+
const realFilteredSkills = filteredSkills.filter((o) => !o.isSelectAll);
|
|
5784
|
+
const realFilteredAgents = filteredAgents.filter((o) => !o.isSelectAll);
|
|
5619
5785
|
const visible = state.activeTab === "skill" ? filteredSkills : filteredAgents;
|
|
5786
|
+
const realVisible = state.activeTab === "skill" ? realFilteredSkills : realFilteredAgents;
|
|
5620
5787
|
const total = visible.length;
|
|
5621
5788
|
const skillTabTitle = options.tabLabels?.skill ?? "Skills";
|
|
5622
5789
|
const agentTabTitle = options.tabLabels?.agent ?? "Agents";
|
|
5623
5790
|
const submitVerb = options.submitActionLabel ?? "import";
|
|
5624
5791
|
const isSinglePage = totalAgents === 0 || totalSkills === 0;
|
|
5625
|
-
const header =
|
|
5626
|
-
|
|
5627
|
-
|
|
5792
|
+
const header = renderPill(`\u25C6 ${title}`, {
|
|
5793
|
+
fg: CHARM_PALETTE.white,
|
|
5794
|
+
bg: CHARM_PALETTE.indigo,
|
|
5795
|
+
bold: true,
|
|
5796
|
+
colorEnabled: c
|
|
5797
|
+
});
|
|
5798
|
+
const sep = style.dim(" \xB7 ", c);
|
|
5799
|
+
const keyItems = [
|
|
5800
|
+
renderKeycap("\u2191/\u2193", "move", c),
|
|
5801
|
+
...isSinglePage ? [] : [renderKeycap("\u2190/\u2192", "tab", c)],
|
|
5802
|
+
renderKeycap("Space", "select", c),
|
|
5803
|
+
...state.searchMode ? [renderKeycap("Esc", "clear", c)] : [renderKeycap("/", "search", c), renderKeycap("a", "all", c)],
|
|
5804
|
+
renderKeycap("Enter", submitVerb, c)
|
|
5805
|
+
];
|
|
5806
|
+
const instructions = `${bar} ${keyItems.join(sep)}`;
|
|
5628
5807
|
const lines = [header];
|
|
5629
5808
|
if (options.subtitle) {
|
|
5630
|
-
lines.push(`${bar} ${options.subtitle}`);
|
|
5809
|
+
lines.push(`${bar} ${fgHex(CHARM_PALETTE.lavender, options.subtitle, c)}`);
|
|
5631
5810
|
}
|
|
5632
5811
|
lines.push(instructions, bar);
|
|
5633
5812
|
const hasQuery = state.searchQuery.length > 0;
|
|
5634
|
-
const skillCountStr = hasQuery ? `${
|
|
5635
|
-
const agentCountStr = hasQuery ? `${
|
|
5636
|
-
const skillTabLabel = state.activeTab === "skill" ?
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5813
|
+
const skillCountStr = hasQuery ? `${realFilteredSkills.length}/${totalSkills}` : `${totalSkills}`;
|
|
5814
|
+
const agentCountStr = hasQuery ? `${realFilteredAgents.length}/${totalAgents}` : `${totalAgents}`;
|
|
5815
|
+
const skillTabLabel = state.activeTab === "skill" ? renderPill(`[ \u25C6 ${skillTabTitle} (${skillCountStr}) ]`, {
|
|
5816
|
+
fg: CHARM_PALETTE.white,
|
|
5817
|
+
bg: CHARM_PALETTE.indigo,
|
|
5818
|
+
bold: true,
|
|
5819
|
+
colorEnabled: c
|
|
5820
|
+
}) : style.dim(`\u25CB ${skillTabTitle} (${skillCountStr})`, c);
|
|
5821
|
+
const agentTabLabel = state.activeTab === "agent" ? renderPill(`[ \u25C6 ${agentTabTitle} (${agentCountStr}) ]`, {
|
|
5822
|
+
fg: CHARM_PALETTE.white,
|
|
5823
|
+
bg: CHARM_PALETTE.hotPink,
|
|
5824
|
+
bold: true,
|
|
5825
|
+
colorEnabled: c
|
|
5826
|
+
}) : style.dim(`\u25CB ${agentTabTitle} (${agentCountStr})`, c);
|
|
5644
5827
|
const rawQuerySlice = state.searchQuery.length > 14 ? `\u2026${state.searchQuery.slice(-13)}` : state.searchQuery;
|
|
5645
|
-
const searchSuffix = state.searchMode || hasQuery ? ` ${
|
|
5828
|
+
const searchSuffix = state.searchMode || hasQuery ? ` ${renderPill(
|
|
5829
|
+
`/ Filter: ${rawQuerySlice}${state.searchMode ? "\u2588" : ""}`,
|
|
5830
|
+
{
|
|
5831
|
+
fg: CHARM_PALETTE.amber,
|
|
5832
|
+
bg: CHARM_PALETTE.surface,
|
|
5833
|
+
bold: true,
|
|
5834
|
+
colorEnabled: c
|
|
5835
|
+
}
|
|
5836
|
+
)}` : ` ${style.dim("(/ search)", c)}`;
|
|
5646
5837
|
const singleTabLabel = totalSkills > 0 ? skillTabLabel : agentTabLabel;
|
|
5647
5838
|
lines.push(
|
|
5648
5839
|
isSinglePage ? `${style.dim("\u251C\u2500", c)} ${singleTabLabel}${searchSuffix}` : `${style.dim("\u251C\u2500", c)} ${skillTabLabel} ${agentTabLabel}${searchSuffix}`,
|
|
@@ -5660,8 +5851,16 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5660
5851
|
startIdx = Math.max(0, Math.min(state.cursor - half, total - maxVisible));
|
|
5661
5852
|
}
|
|
5662
5853
|
const endIdx = Math.min(total, startIdx + maxVisible);
|
|
5854
|
+
const totalPages = Math.max(1, Math.ceil(total / maxVisible));
|
|
5855
|
+
const currentPage = Math.min(
|
|
5856
|
+
totalPages - 1,
|
|
5857
|
+
Math.floor(state.cursor / maxVisible)
|
|
5858
|
+
);
|
|
5859
|
+
const pageDots = totalPages > 1 ? ` ${renderPaginationDots(currentPage, totalPages, c)}` : "";
|
|
5663
5860
|
if (startIdx > 0) {
|
|
5664
|
-
lines.push(
|
|
5861
|
+
lines.push(
|
|
5862
|
+
`${bar} ${style.dim(`\u2191 ${startIdx} more above...`, c)}${endIdx >= total ? pageDots : ""}`
|
|
5863
|
+
);
|
|
5665
5864
|
}
|
|
5666
5865
|
const maxLabelCols = Math.min(
|
|
5667
5866
|
26,
|
|
@@ -5671,30 +5870,32 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5671
5870
|
const opt = visible[i];
|
|
5672
5871
|
if (!opt) continue;
|
|
5673
5872
|
const isCurrent = i === state.cursor;
|
|
5674
|
-
const
|
|
5675
|
-
const
|
|
5676
|
-
const
|
|
5873
|
+
const allRealSelected = realVisible.length > 0 && realVisible.every((o) => state.selected.has(o.value));
|
|
5874
|
+
const someRealSelected = realVisible.some((o) => state.selected.has(o.value)) && !allRealSelected;
|
|
5875
|
+
const isChecked = opt.isSelectAll ? allRealSelected : state.selected.has(opt.value);
|
|
5876
|
+
const pointer = isCurrent ? fgHex(CHARM_PALETTE.hotPink, style.bold("\u276F", c), c) : " ";
|
|
5877
|
+
const checkbox = isChecked ? style.green("\u25C9", c) : opt.isSelectAll && someRealSelected ? fgHex(CHARM_PALETTE.fuchsia, "\u25D0", c) : style.dim("\u25EF", c);
|
|
5677
5878
|
const labelRaw = opt.label.length > maxLabelCols ? `${opt.label.slice(0, maxLabelCols - 1)}\u2026` : opt.label;
|
|
5678
5879
|
const labelPadded = padVisible(labelRaw, maxLabelCols + 1, "left");
|
|
5679
|
-
const styledLabel = isCurrent ? style.bold(labelPadded, c) : isChecked ? style.green(labelPadded, c) : labelPadded;
|
|
5880
|
+
const styledLabel = isCurrent ? fgHex(CHARM_PALETTE.fuchsia, style.bold(labelPadded, c), c) : isChecked ? style.green(labelPadded, c) : labelPadded;
|
|
5680
5881
|
const prefixWidth = 7 + maxLabelCols + 1;
|
|
5681
5882
|
const maxHintCols = Math.max(10, 76 - prefixWidth);
|
|
5682
5883
|
const rawHint = opt.hint ?? "";
|
|
5683
5884
|
const shortHint = rawHint.length > maxHintCols ? `${rawHint.slice(0, maxHintCols - 1)}\u2026` : rawHint;
|
|
5684
|
-
const hintPart = shortHint ? ` ${style.dim(shortHint, c)}` : "";
|
|
5885
|
+
const hintPart = shortHint ? ` ${isCurrent ? fgHex(CHARM_PALETTE.lavender, shortHint, c) : style.dim(shortHint, c)}` : "";
|
|
5685
5886
|
lines.push(`${bar} ${pointer} ${checkbox} ${styledLabel}${hintPart}`);
|
|
5686
5887
|
}
|
|
5687
5888
|
if (endIdx < total) {
|
|
5688
5889
|
lines.push(
|
|
5689
|
-
`${bar} ${style.dim(`\u2193 ${total - endIdx} more below...`, c)}`
|
|
5890
|
+
`${bar} ${style.dim(`\u2193 ${total - endIdx} more below...`, c)}${pageDots}`
|
|
5690
5891
|
);
|
|
5691
5892
|
}
|
|
5692
5893
|
}
|
|
5693
5894
|
lines.push(bar);
|
|
5694
|
-
const selectedSkillsCount =
|
|
5895
|
+
const selectedSkillsCount = realOptions.filter(
|
|
5695
5896
|
(o) => optionMatchesTab(o, "skill") && state.selected.has(o.value)
|
|
5696
5897
|
).length;
|
|
5697
|
-
const selectedAgentsCount =
|
|
5898
|
+
const selectedAgentsCount = realOptions.filter(
|
|
5698
5899
|
(o) => optionMatchesTab(o, "agent") && state.selected.has(o.value)
|
|
5699
5900
|
).length;
|
|
5700
5901
|
const currentOptLabel = visible[state.cursor]?.label ?? "";
|
|
@@ -5702,8 +5903,9 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5702
5903
|
const rawTarget = options.targetHint ?? "";
|
|
5703
5904
|
const shortTarget = rawTarget.length > 18 ? `${rawTarget.slice(0, 17)}\u2026` : rawTarget;
|
|
5704
5905
|
const targetSuffix = shortTarget ? ` \xB7 IDE: ${shortTarget}` : "";
|
|
5906
|
+
const styledSummary = state.selected.size > 0 ? fgHex(CHARM_PALETTE.mint, style.bold(summaryText, c), c) : fgHex(CHARM_PALETTE.lavender, style.bold(summaryText, c), c);
|
|
5705
5907
|
lines.push(
|
|
5706
|
-
`${style.dim("\u2570\u2500", c)} ${
|
|
5908
|
+
`${style.dim("\u2570\u2500", c)} ${styledSummary}${style.dim(`${targetSuffix} \u2014 Enter to ${submitVerb}`, c)}`
|
|
5707
5909
|
);
|
|
5708
5910
|
return lines.join("\n");
|
|
5709
5911
|
}
|
|
@@ -5711,7 +5913,9 @@ async function runMultiSelectPrompt(title, options, renderOpts = {}) {
|
|
|
5711
5913
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
5712
5914
|
return null;
|
|
5713
5915
|
}
|
|
5714
|
-
let state = createMultiSelectState(options
|
|
5916
|
+
let state = createMultiSelectState(options, {
|
|
5917
|
+
showSelectAll: renderOpts.showSelectAll
|
|
5918
|
+
});
|
|
5715
5919
|
let renderedLineCount = 0;
|
|
5716
5920
|
const render = () => {
|
|
5717
5921
|
const frame = renderMultiSelectFrame(title, state, renderOpts);
|
|
@@ -6972,16 +7176,19 @@ function runCli(argv) {
|
|
|
6972
7176
|
unit: "tokens"
|
|
6973
7177
|
});
|
|
6974
7178
|
const firstSkill = summary.skills[0]?.skillName ?? "security-sast-gate";
|
|
7179
|
+
const skillBadge = formatBadge("skill", "SKILL");
|
|
7180
|
+
const subagentBadge = formatBadge("subagent", "SUBAGENT");
|
|
6975
7181
|
const lines = [
|
|
6976
|
-
|
|
6977
|
-
`Skills (${summary.skills.length}) \u2014 Total L1 Routing Tax: ${summary.totalL1Tokens} tokens`,
|
|
6978
|
-
|
|
7182
|
+
renderHeaderBanner("Catalog \u2014 Hybrid Skills & Context-Isolated Agents"),
|
|
7183
|
+
`${style.dim("\u251C\u2500")} ${style.bold(`Skills (${summary.skills.length})`)} \u2014 Total L1 Routing Tax: ${style.green(`${summary.totalL1Tokens} tokens`)}`,
|
|
7184
|
+
`${style.dim("\u2502")} L1 Budget Meter: ${l1Bar}`,
|
|
6979
7185
|
...summary.skills.map(
|
|
6980
|
-
(s) =>
|
|
7186
|
+
(s) => `${style.dim("\u2502")} ${skillBadge} ${style.bold(s.skillName)} \u2014 L1: ${s.l1Tokens}t | L2: ${s.l2Lines} lines (${s.l2Tokens}t) | L3 Scripts: ${s.scriptsCount}`
|
|
6981
7187
|
),
|
|
6982
|
-
|
|
7188
|
+
style.dim("\u2502"),
|
|
7189
|
+
`${style.dim("\u251C\u2500")} ${style.bold(`Subagents (${summary.subagents.length})`)} \u2014 Context-Isolated Specialist Agents:`,
|
|
6983
7190
|
...summary.subagents.map(
|
|
6984
|
-
(a) =>
|
|
7191
|
+
(a) => `${style.dim("\u2502")} ${subagentBadge} ${style.bold(a.subagentName)} (prompt=${a.systemPromptTokens}t, max_out<=${a.maxOutputTokens}t, tools=${a.tools.length})`
|
|
6985
7192
|
),
|
|
6986
7193
|
renderNextSteps([
|
|
6987
7194
|
{
|
|
@@ -7478,7 +7685,8 @@ async function runCliInteractive(argv) {
|
|
|
7478
7685
|
const options = buildInteractiveCatalogOptions(catalogDir);
|
|
7479
7686
|
const step2Title = !explicitTargetsArg ? "SkillOps \u2014 Step 2/2: Select Skills & Agents to Import" : "SkillOps \u2014 Select Skills & Agents to Import";
|
|
7480
7687
|
const selected = await runMultiSelectPrompt(step2Title, options, {
|
|
7481
|
-
targetHint: targets.join(", ")
|
|
7688
|
+
targetHint: targets.join(", "),
|
|
7689
|
+
showSelectAll: true
|
|
7482
7690
|
});
|
|
7483
7691
|
if (!selected || selected.length === 0) {
|
|
7484
7692
|
process.stdout.write("No Skills or Agents selected.\n");
|
|
@@ -7529,7 +7737,8 @@ async function runCliInteractive(argv) {
|
|
|
7529
7737
|
installedOptions,
|
|
7530
7738
|
{
|
|
7531
7739
|
submitActionLabel: "remove",
|
|
7532
|
-
targetHint: targets ? targets.join(", ") : void 0
|
|
7740
|
+
targetHint: targets ? targets.join(", ") : void 0,
|
|
7741
|
+
showSelectAll: true
|
|
7533
7742
|
}
|
|
7534
7743
|
);
|
|
7535
7744
|
if (!selected || selected.length === 0) {
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { z } from 'zod';
|
|
|
8
8
|
* telemetry and Multi-Runtime Transpilation lockfiles.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
declare const SKILLOPS_VERSION = "1.3.
|
|
11
|
+
declare const SKILLOPS_VERSION = "1.3.8";
|
|
12
12
|
/**
|
|
13
13
|
* Count whitespace-delimited words in text.
|
|
14
14
|
*/
|
|
@@ -2173,6 +2173,67 @@ declare function renderGlobalHelp(version: string, colorEnabled?: boolean): stri
|
|
|
2173
2173
|
*/
|
|
2174
2174
|
declare function renderCommandHelp(spec: CommandHelpSpec, version: string, colorEnabled?: boolean): string;
|
|
2175
2175
|
|
|
2176
|
+
/**
|
|
2177
|
+
* Charmbracelet Lip Gloss & Bubbles Inspired Terminal Styling Engine (`src/ui/lipgloss.ts`).
|
|
2178
|
+
*
|
|
2179
|
+
* Zero-dependency TypeScript implementation of Lip Gloss TrueColor (24-bit RGB)
|
|
2180
|
+
* palettes, background pills, Bubbles paginator dots, keycap status bars, and
|
|
2181
|
+
* ANSI-aware horizontal block composition (`joinHorizontal`).
|
|
2182
|
+
*/
|
|
2183
|
+
/**
|
|
2184
|
+
* Official Charmbracelet Lip Gloss / Huh / Bubbles inspired TrueColor palette.
|
|
2185
|
+
*/
|
|
2186
|
+
declare const CHARM_PALETTE: {
|
|
2187
|
+
readonly indigo: "#7D56F4";
|
|
2188
|
+
readonly fuchsia: "#EE6FF8";
|
|
2189
|
+
readonly hotPink: "#F25D94";
|
|
2190
|
+
readonly mint: "#04B575";
|
|
2191
|
+
readonly amber: "#FFBD2E";
|
|
2192
|
+
readonly coral: "#FF5F56";
|
|
2193
|
+
readonly cyan: "#00D7FF";
|
|
2194
|
+
readonly lavender: "#B4A7D6";
|
|
2195
|
+
readonly white: "#FAFAFA";
|
|
2196
|
+
readonly muted: "#6C6C6C";
|
|
2197
|
+
readonly subtle: "#4A4A4A";
|
|
2198
|
+
readonly surface: "#2A2438";
|
|
2199
|
+
readonly keycapBg: "#302B3F";
|
|
2200
|
+
};
|
|
2201
|
+
type CharmColorKey = keyof typeof CHARM_PALETTE;
|
|
2202
|
+
/**
|
|
2203
|
+
* Parse a `#RRGGBB` or `#RGB` hex color string into an `[r, g, b]` tuple.
|
|
2204
|
+
*/
|
|
2205
|
+
declare function hexToRgb(hex: string): readonly [number, number, number];
|
|
2206
|
+
/**
|
|
2207
|
+
* Apply 24-bit TrueColor foreground (`\x1b[38;2;R;G;Bm`) when color is enabled.
|
|
2208
|
+
*/
|
|
2209
|
+
declare function fgHex(hex: string, text: string, enabled?: boolean): string;
|
|
2210
|
+
/**
|
|
2211
|
+
* Apply 24-bit TrueColor background (`\x1b[48;2;R;G;Bm`) when color is enabled.
|
|
2212
|
+
*/
|
|
2213
|
+
declare function bgHex(hex: string, text: string, enabled?: boolean): string;
|
|
2214
|
+
interface PillOptions {
|
|
2215
|
+
readonly fg?: string;
|
|
2216
|
+
readonly bg?: string;
|
|
2217
|
+
readonly bold?: boolean;
|
|
2218
|
+
readonly colorEnabled?: boolean;
|
|
2219
|
+
}
|
|
2220
|
+
/**
|
|
2221
|
+
* Render a Lip Gloss background pill badge without altering visible character length.
|
|
2222
|
+
*/
|
|
2223
|
+
declare function renderPill(text: string, options?: PillOptions): string;
|
|
2224
|
+
/**
|
|
2225
|
+
* Render a Charm `bubbles/help` style keybinding hint (`key action`).
|
|
2226
|
+
*/
|
|
2227
|
+
declare function renderKeycap(keyLabel: string, actionLabel: string, colorEnabled?: boolean): string;
|
|
2228
|
+
/**
|
|
2229
|
+
* Render Charm `bubbles/paginator` style pagination dots (`• ◦ ◦`).
|
|
2230
|
+
*/
|
|
2231
|
+
declare function renderPaginationDots(currentPage: number, totalPages: number, colorEnabled?: boolean): string;
|
|
2232
|
+
/**
|
|
2233
|
+
* Compose two multi-line blocks horizontally (`lipgloss.JoinHorizontal`).
|
|
2234
|
+
*/
|
|
2235
|
+
declare function joinHorizontal(align: "top" | "center" | "bottom", leftBlock: string, rightBlock: string, gap?: number): string;
|
|
2236
|
+
|
|
2176
2237
|
/**
|
|
2177
2238
|
* Zero-dependency interactive terminal multi-select prompt (`src/ui/prompt.ts`).
|
|
2178
2239
|
*
|
|
@@ -2190,6 +2251,10 @@ interface MultiSelectOption {
|
|
|
2190
2251
|
readonly tab?: MultiSelectTab;
|
|
2191
2252
|
readonly hint?: string;
|
|
2192
2253
|
readonly initialSelected?: boolean;
|
|
2254
|
+
readonly isSelectAll?: boolean;
|
|
2255
|
+
}
|
|
2256
|
+
interface CreateMultiSelectStateOptions {
|
|
2257
|
+
readonly showSelectAll?: boolean;
|
|
2193
2258
|
}
|
|
2194
2259
|
interface MultiSelectState {
|
|
2195
2260
|
readonly options: readonly MultiSelectOption[];
|
|
@@ -2212,6 +2277,7 @@ interface RenderMultiSelectOptions {
|
|
|
2212
2277
|
};
|
|
2213
2278
|
readonly submitActionLabel?: string;
|
|
2214
2279
|
readonly selectCursorOnEmptySubmit?: boolean;
|
|
2280
|
+
readonly showSelectAll?: boolean;
|
|
2215
2281
|
readonly maxVisible?: number;
|
|
2216
2282
|
readonly colorEnabled?: boolean;
|
|
2217
2283
|
}
|
|
@@ -2222,7 +2288,7 @@ declare function getFilteredTabOptions(state: MultiSelectState, tab?: MultiSelec
|
|
|
2222
2288
|
/**
|
|
2223
2289
|
* Initialize a deterministic multi-select state from a list of options.
|
|
2224
2290
|
*/
|
|
2225
|
-
declare function createMultiSelectState(options: readonly MultiSelectOption[]): MultiSelectState;
|
|
2291
|
+
declare function createMultiSelectState(options: readonly MultiSelectOption[], stateOptions?: CreateMultiSelectStateOptions): MultiSelectState;
|
|
2226
2292
|
/**
|
|
2227
2293
|
* Pure state reducer for keyboard input in the tabbed + searchable multi-select TUI.
|
|
2228
2294
|
*/
|
|
@@ -2356,4 +2422,4 @@ declare const DEFAULT_VALID_COMMANDS: readonly string[];
|
|
|
2356
2422
|
*/
|
|
2357
2423
|
declare function suggestCommand(unknownCommand: string, validCommands?: readonly string[]): string | null;
|
|
2358
2424
|
|
|
2359
|
-
export { ALL_RUNTIME_TARGETS, type AddOptions, type AnalyzeTokenEconomyOptions, type ApplyMultiSelectKeyOptions, type AuditCatalogOptions, type BadgeType, type BenchmarkArm, BenchmarkArmSchema, type BenchmarkDelta, BenchmarkDeltaSchema, type BoxOptions, COMMAND_HELP_SPECS, CORE_RUNTIME_TARGETS, type CatalogEvalSummary, CatalogEvalSummarySchema, type CatalogItemInfo, type CatalogSearchMatch, type CatalogSearchReport, type CatalogTokenBudgetSummary, type CatalogTrack, CatalogTrackSchema, type CleanOptions, type CollisionPair, CollisionPairSchema, type CollisionReport, CollisionReportSchema, type CollisionSeverity, CollisionSeveritySchema, type ColorOverrideOptions, type CommandHelpSpec, type CommandOptionSpec, DEFAULT_VALID_COMMANDS, type DiagnoseRepositoryOptions, type DoctorCheckItem, type DoctorReport, type EvalAssertion, EvalAssertionSchema, type EvalCase, EvalCaseSchema, ExitCode, type ExitCodeValue, type HarnessCategory, type HarnessInspectionEntry, type HarnessInspectionReport, type HarnessSkillFormat, type JsonRpcRequest, type JsonRpcResponse, type LoadedSkillOpsConfigResult, type LockfileArtifactDiagnostic, type McpConfigAction, type McpServerContext, type McpSetupOptions, type McpSetupReport, type MultiSelectOption, type MultiSelectState, type MultiSelectTab, type NextStepHint, type ParseSkillOptions, type ParsedSkillDirectory, type ParsedSubagentFile, type QuickstartOptions, type QuickstartReport, RUNTIME_HARNESS_SPECS, type RemoveOptions, type RenderMultiSelectOptions, RepoFingerprinter, type RepoProfile, RepoProfileSchema, type RouteOptions, type RoutedBundle, RoutedBundleSchema, type RoutingSignals, RoutingSignalsSchema, type RuntimeHarnessSpec, type RuntimeTarget, RuntimeTargetSchema, SKILLOPS_VERSION, type ScaffoldOptions, type ScaffoldResult, type ScoredSkill, ScoredSkillSchema, type ScriptEntrypoint, ScriptEntrypointSchema, type SkillBenchmark, SkillBenchmarkSchema, type SkillEntrypoints, SkillEntrypointsSchema, type SkillEvalSuite, SkillEvalSuiteSchema, type SkillManifest, type SkillManifestInput, SkillManifestSchema, type SkillOpsConfig, SkillOpsConfigSchema, type SkillOpsDetectedStackConfig, SkillOpsDetectedStackConfigSchema, type SkillOpsTokenEconomyConfig, SkillOpsTokenEconomyConfigSchema, type SkillTokenBudgetAudit, type SkippedSkill, SkippedSkillSchema, type SubagentManifest, SubagentManifestSchema, type SubagentTokenBudgetAudit, type SyncLockEntry, SyncLockEntrySchema, type SyncLockfile, SyncLockfileSchema, type SyncOptions, type SyncReport, SyncReportSchema, type SyncedArtifact, SyncedArtifactSchema, type TableOptions, type TokenBarOptions, type TokenEconomyReport, TokenEconomyReportSchema, type TokenFileCategory, TokenFileCategorySchema, type TokenFileEntry, TokenFileEntrySchema, type TokenWasteHotspot, TokenWasteHotspotSchema, addSkillOrSubagent, analyzeRepoTokenEconomy, applyMultiSelectKey, auditCatalog, auditCatalogTokenBudgets, auditSkillTokenBudget, auditSubagentTokenBudget, classifyCollisionSeverity, cleanSyncedArtifacts, compileSkillBundle, computeCollisionMatrix, computeFeatureCosine, computeIdfWeights, computeSha256, countWords, createCollisionPair, createCollisionReport, createMultiSelectState, createSkillManifest, createSubagentManifest, detectInstalledHarnesses, diagnoseRepository, discoverSkillDirectories, discoverSubagentFiles, estimateTokenCount, evaluateCatalog, evaluateSkillDirectory, extractSkillFeatures, findCommandHelpSpec, fingerprintRepository, formatBadge, formatCatalogItemInfo, formatCatalogSearchReport, formatDoctorReport, formatEvalSummary, formatHarnessInspectionReport, formatMcpSetupReport, formatQuickstartReport, formatRoutedBundle, formatScaffoldReport, formatSyncReport, formatTokenEconomyReport, getFilteredTabOptions, handleMcpJsonRpcRequest, inspectCatalogItem, inspectHarnesses, isColorEnabled, levenshteinDistance, loadSkillOpsConfig, normalizePackageName, padVisible, parseSkillDirectory, parseSkillMdFile, parseSubagentFile, parseSubagentMdFile, removeSkillOrSubagent, renderAiUsageGuide, renderBox, renderCodexAgentsIndex, renderCommandHelp, renderGlobalHelp, renderHeaderBanner, renderMultiSelectFrame, renderNextSteps, renderProgressBar, renderSectionHeader, renderStep, renderTable, renderTokenBar, resolveRuntimeTargets, routeRepository, runMultiSelectPrompt, runQuickstart, scaffoldFrameworkItem, scoreSkillAgainstProfile, searchCatalog, setupMcpForHarnesses, splitFrontmatter, startMcpStdioServer, stripAnsi, stripCodexAgentsBlock, stripNegativeTriggerClauses, style, suggestCommand, syncRepository, tokenizeRoutingText, visibleLength };
|
|
2425
|
+
export { ALL_RUNTIME_TARGETS, type AddOptions, type AnalyzeTokenEconomyOptions, type ApplyMultiSelectKeyOptions, type AuditCatalogOptions, type BadgeType, type BenchmarkArm, BenchmarkArmSchema, type BenchmarkDelta, BenchmarkDeltaSchema, type BoxOptions, CHARM_PALETTE, COMMAND_HELP_SPECS, CORE_RUNTIME_TARGETS, type CatalogEvalSummary, CatalogEvalSummarySchema, type CatalogItemInfo, type CatalogSearchMatch, type CatalogSearchReport, type CatalogTokenBudgetSummary, type CatalogTrack, CatalogTrackSchema, type CharmColorKey, type CleanOptions, type CollisionPair, CollisionPairSchema, type CollisionReport, CollisionReportSchema, type CollisionSeverity, CollisionSeveritySchema, type ColorOverrideOptions, type CommandHelpSpec, type CommandOptionSpec, type CreateMultiSelectStateOptions, DEFAULT_VALID_COMMANDS, type DiagnoseRepositoryOptions, type DoctorCheckItem, type DoctorReport, type EvalAssertion, EvalAssertionSchema, type EvalCase, EvalCaseSchema, ExitCode, type ExitCodeValue, type HarnessCategory, type HarnessInspectionEntry, type HarnessInspectionReport, type HarnessSkillFormat, type JsonRpcRequest, type JsonRpcResponse, type LoadedSkillOpsConfigResult, type LockfileArtifactDiagnostic, type McpConfigAction, type McpServerContext, type McpSetupOptions, type McpSetupReport, type MultiSelectOption, type MultiSelectState, type MultiSelectTab, type NextStepHint, type ParseSkillOptions, type ParsedSkillDirectory, type ParsedSubagentFile, type PillOptions, type QuickstartOptions, type QuickstartReport, RUNTIME_HARNESS_SPECS, type RemoveOptions, type RenderMultiSelectOptions, RepoFingerprinter, type RepoProfile, RepoProfileSchema, type RouteOptions, type RoutedBundle, RoutedBundleSchema, type RoutingSignals, RoutingSignalsSchema, type RuntimeHarnessSpec, type RuntimeTarget, RuntimeTargetSchema, SKILLOPS_VERSION, type ScaffoldOptions, type ScaffoldResult, type ScoredSkill, ScoredSkillSchema, type ScriptEntrypoint, ScriptEntrypointSchema, type SkillBenchmark, SkillBenchmarkSchema, type SkillEntrypoints, SkillEntrypointsSchema, type SkillEvalSuite, SkillEvalSuiteSchema, type SkillManifest, type SkillManifestInput, SkillManifestSchema, type SkillOpsConfig, SkillOpsConfigSchema, type SkillOpsDetectedStackConfig, SkillOpsDetectedStackConfigSchema, type SkillOpsTokenEconomyConfig, SkillOpsTokenEconomyConfigSchema, type SkillTokenBudgetAudit, type SkippedSkill, SkippedSkillSchema, type SubagentManifest, SubagentManifestSchema, type SubagentTokenBudgetAudit, type SyncLockEntry, SyncLockEntrySchema, type SyncLockfile, SyncLockfileSchema, type SyncOptions, type SyncReport, SyncReportSchema, type SyncedArtifact, SyncedArtifactSchema, type TableOptions, type TokenBarOptions, type TokenEconomyReport, TokenEconomyReportSchema, type TokenFileCategory, TokenFileCategorySchema, type TokenFileEntry, TokenFileEntrySchema, type TokenWasteHotspot, TokenWasteHotspotSchema, addSkillOrSubagent, analyzeRepoTokenEconomy, applyMultiSelectKey, auditCatalog, auditCatalogTokenBudgets, auditSkillTokenBudget, auditSubagentTokenBudget, bgHex, classifyCollisionSeverity, cleanSyncedArtifacts, compileSkillBundle, computeCollisionMatrix, computeFeatureCosine, computeIdfWeights, computeSha256, countWords, createCollisionPair, createCollisionReport, createMultiSelectState, createSkillManifest, createSubagentManifest, detectInstalledHarnesses, diagnoseRepository, discoverSkillDirectories, discoverSubagentFiles, estimateTokenCount, evaluateCatalog, evaluateSkillDirectory, extractSkillFeatures, fgHex, findCommandHelpSpec, fingerprintRepository, formatBadge, formatCatalogItemInfo, formatCatalogSearchReport, formatDoctorReport, formatEvalSummary, formatHarnessInspectionReport, formatMcpSetupReport, formatQuickstartReport, formatRoutedBundle, formatScaffoldReport, formatSyncReport, formatTokenEconomyReport, getFilteredTabOptions, handleMcpJsonRpcRequest, hexToRgb, inspectCatalogItem, inspectHarnesses, isColorEnabled, joinHorizontal, levenshteinDistance, loadSkillOpsConfig, normalizePackageName, padVisible, parseSkillDirectory, parseSkillMdFile, parseSubagentFile, parseSubagentMdFile, removeSkillOrSubagent, renderAiUsageGuide, renderBox, renderCodexAgentsIndex, renderCommandHelp, renderGlobalHelp, renderHeaderBanner, renderKeycap, renderMultiSelectFrame, renderNextSteps, renderPaginationDots, renderPill, renderProgressBar, renderSectionHeader, renderStep, renderTable, renderTokenBar, resolveRuntimeTargets, routeRepository, runMultiSelectPrompt, runQuickstart, scaffoldFrameworkItem, scoreSkillAgainstProfile, searchCatalog, setupMcpForHarnesses, splitFrontmatter, startMcpStdioServer, stripAnsi, stripCodexAgentsBlock, stripNegativeTriggerClauses, style, suggestCommand, syncRepository, tokenizeRoutingText, visibleLength };
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import YAML from "yaml";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
-
var SKILLOPS_VERSION = "1.3.
|
|
5
|
+
var SKILLOPS_VERSION = "1.3.8";
|
|
6
6
|
var SKILL_NAME_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
7
7
|
var SEMVER_REGEX = /^\d+\.\d+\.\d+$/;
|
|
8
8
|
var FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
|
|
@@ -1418,9 +1418,142 @@ import fs3 from "fs";
|
|
|
1418
1418
|
import path2 from "path";
|
|
1419
1419
|
import YAML2 from "yaml";
|
|
1420
1420
|
|
|
1421
|
-
// src/ui/
|
|
1421
|
+
// src/ui/lipgloss.ts
|
|
1422
1422
|
var ESC = String.fromCharCode(27);
|
|
1423
|
-
var
|
|
1423
|
+
var CHARM_PALETTE = {
|
|
1424
|
+
indigo: "#7D56F4",
|
|
1425
|
+
fuchsia: "#EE6FF8",
|
|
1426
|
+
hotPink: "#F25D94",
|
|
1427
|
+
mint: "#04B575",
|
|
1428
|
+
amber: "#FFBD2E",
|
|
1429
|
+
coral: "#FF5F56",
|
|
1430
|
+
cyan: "#00D7FF",
|
|
1431
|
+
lavender: "#B4A7D6",
|
|
1432
|
+
white: "#FAFAFA",
|
|
1433
|
+
muted: "#6C6C6C",
|
|
1434
|
+
subtle: "#4A4A4A",
|
|
1435
|
+
surface: "#2A2438",
|
|
1436
|
+
keycapBg: "#302B3F"
|
|
1437
|
+
};
|
|
1438
|
+
function hexToRgb(hex) {
|
|
1439
|
+
const cleaned = hex.trim().replace(/^#/, "");
|
|
1440
|
+
if (cleaned.length === 3) {
|
|
1441
|
+
const r2 = Number.parseInt(`${cleaned[0]}${cleaned[0]}`, 16);
|
|
1442
|
+
const g2 = Number.parseInt(`${cleaned[1]}${cleaned[1]}`, 16);
|
|
1443
|
+
const b2 = Number.parseInt(`${cleaned[2]}${cleaned[2]}`, 16);
|
|
1444
|
+
return [
|
|
1445
|
+
Number.isNaN(r2) ? 255 : r2,
|
|
1446
|
+
Number.isNaN(g2) ? 255 : g2,
|
|
1447
|
+
Number.isNaN(b2) ? 255 : b2
|
|
1448
|
+
];
|
|
1449
|
+
}
|
|
1450
|
+
const r = Number.parseInt(cleaned.slice(0, 2), 16);
|
|
1451
|
+
const g = Number.parseInt(cleaned.slice(2, 4), 16);
|
|
1452
|
+
const b = Number.parseInt(cleaned.slice(4, 6), 16);
|
|
1453
|
+
return [
|
|
1454
|
+
Number.isNaN(r) ? 255 : r,
|
|
1455
|
+
Number.isNaN(g) ? 255 : g,
|
|
1456
|
+
Number.isNaN(b) ? 255 : b
|
|
1457
|
+
];
|
|
1458
|
+
}
|
|
1459
|
+
function fgHex(hex, text, enabled) {
|
|
1460
|
+
const useColor = enabled ?? isColorEnabled();
|
|
1461
|
+
if (!useColor || text.length === 0) {
|
|
1462
|
+
return text;
|
|
1463
|
+
}
|
|
1464
|
+
const [r, g, b] = hexToRgb(hex);
|
|
1465
|
+
return `${ESC}[38;2;${r};${g};${b}m${text}${ESC}[39m`;
|
|
1466
|
+
}
|
|
1467
|
+
function bgHex(hex, text, enabled) {
|
|
1468
|
+
const useColor = enabled ?? isColorEnabled();
|
|
1469
|
+
if (!useColor || text.length === 0) {
|
|
1470
|
+
return text;
|
|
1471
|
+
}
|
|
1472
|
+
const [r, g, b] = hexToRgb(hex);
|
|
1473
|
+
return `${ESC}[48;2;${r};${g};${b}m${text}${ESC}[49m`;
|
|
1474
|
+
}
|
|
1475
|
+
function renderPill(text, options) {
|
|
1476
|
+
const useColor = options?.colorEnabled ?? isColorEnabled();
|
|
1477
|
+
if (!useColor || text.length === 0) {
|
|
1478
|
+
return text;
|
|
1479
|
+
}
|
|
1480
|
+
const fg = options?.fg ?? CHARM_PALETTE.white;
|
|
1481
|
+
const bg = options?.bg ?? CHARM_PALETTE.indigo;
|
|
1482
|
+
const bold = options?.bold ?? true;
|
|
1483
|
+
let styled = fgHex(fg, text, true);
|
|
1484
|
+
styled = bgHex(bg, styled, true);
|
|
1485
|
+
if (bold) {
|
|
1486
|
+
styled = `${ESC}[1m${styled}${ESC}[22m`;
|
|
1487
|
+
}
|
|
1488
|
+
return styled;
|
|
1489
|
+
}
|
|
1490
|
+
function renderKeycap(keyLabel, actionLabel, colorEnabled) {
|
|
1491
|
+
const useColor = colorEnabled ?? isColorEnabled();
|
|
1492
|
+
if (!useColor) {
|
|
1493
|
+
return `${keyLabel} ${actionLabel}`;
|
|
1494
|
+
}
|
|
1495
|
+
const keyStyled = `${ESC}[1m${fgHex(CHARM_PALETTE.lavender, keyLabel, true)}${ESC}[22m`;
|
|
1496
|
+
const actionStyled = fgHex(CHARM_PALETTE.muted, actionLabel, true);
|
|
1497
|
+
return `${keyStyled} ${actionStyled}`;
|
|
1498
|
+
}
|
|
1499
|
+
function renderPaginationDots(currentPage, totalPages, colorEnabled) {
|
|
1500
|
+
const safeTotal = Math.max(1, Math.min(12, totalPages));
|
|
1501
|
+
const safeCurrent = Math.max(0, Math.min(safeTotal - 1, currentPage));
|
|
1502
|
+
const useColor = colorEnabled ?? isColorEnabled();
|
|
1503
|
+
const dots = [];
|
|
1504
|
+
for (let i = 0; i < safeTotal; i++) {
|
|
1505
|
+
if (i === safeCurrent) {
|
|
1506
|
+
dots.push(
|
|
1507
|
+
useColor ? `${ESC}[1m${fgHex(CHARM_PALETTE.hotPink, "\u2022", true)}${ESC}[22m` : "\u2022"
|
|
1508
|
+
);
|
|
1509
|
+
} else {
|
|
1510
|
+
dots.push(useColor ? fgHex(CHARM_PALETTE.muted, "\u25E6", true) : "\u25E6");
|
|
1511
|
+
}
|
|
1512
|
+
}
|
|
1513
|
+
return dots.join(" ");
|
|
1514
|
+
}
|
|
1515
|
+
function joinHorizontal(align, leftBlock, rightBlock, gap = 2) {
|
|
1516
|
+
const leftLines = leftBlock.split("\n");
|
|
1517
|
+
const rightLines = rightBlock.split("\n");
|
|
1518
|
+
const totalRows = Math.max(leftLines.length, rightLines.length);
|
|
1519
|
+
const leftWidth = leftLines.reduce(
|
|
1520
|
+
(max, line) => Math.max(max, visibleLength(line)),
|
|
1521
|
+
0
|
|
1522
|
+
);
|
|
1523
|
+
const gapStr = " ".repeat(Math.max(0, gap));
|
|
1524
|
+
const padBlockLines = (lines) => {
|
|
1525
|
+
const diff = totalRows - lines.length;
|
|
1526
|
+
if (diff <= 0) {
|
|
1527
|
+
return lines;
|
|
1528
|
+
}
|
|
1529
|
+
if (align === "bottom") {
|
|
1530
|
+
return [...Array.from({ length: diff }, () => ""), ...lines];
|
|
1531
|
+
}
|
|
1532
|
+
if (align === "center") {
|
|
1533
|
+
const top = Math.floor(diff / 2);
|
|
1534
|
+
const bottom = diff - top;
|
|
1535
|
+
return [
|
|
1536
|
+
...Array.from({ length: top }, () => ""),
|
|
1537
|
+
...lines,
|
|
1538
|
+
...Array.from({ length: bottom }, () => "")
|
|
1539
|
+
];
|
|
1540
|
+
}
|
|
1541
|
+
return [...lines, ...Array.from({ length: diff }, () => "")];
|
|
1542
|
+
};
|
|
1543
|
+
const paddedLeft = padBlockLines(leftLines);
|
|
1544
|
+
const paddedRight = padBlockLines(rightLines);
|
|
1545
|
+
const out = [];
|
|
1546
|
+
for (let i = 0; i < totalRows; i++) {
|
|
1547
|
+
const l = padVisible(paddedLeft[i] ?? "", leftWidth, "left");
|
|
1548
|
+
const r = paddedRight[i] ?? "";
|
|
1549
|
+
out.push(r.length > 0 ? `${l}${gapStr}${r}` : l.trimEnd());
|
|
1550
|
+
}
|
|
1551
|
+
return out.join("\n");
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
// src/ui/terminal.ts
|
|
1555
|
+
var ESC2 = String.fromCharCode(27);
|
|
1556
|
+
var ANSI_ESCAPE_REGEX = new RegExp(`${ESC2}\\[[0-9;]*m`, "g");
|
|
1424
1557
|
function isColorEnabled(options) {
|
|
1425
1558
|
const env = options?.env ?? process.env;
|
|
1426
1559
|
const isTTY = options?.isTTY ?? Boolean(process.stdout?.isTTY);
|
|
@@ -1446,21 +1579,21 @@ function wrapAnsi(openCode, closeCode, text, enabled) {
|
|
|
1446
1579
|
if (!useColor || text.length === 0) {
|
|
1447
1580
|
return text;
|
|
1448
1581
|
}
|
|
1449
|
-
return `${
|
|
1582
|
+
return `${ESC2}[${openCode}m${text}${ESC2}[${closeCode}m`;
|
|
1450
1583
|
}
|
|
1451
1584
|
var style = {
|
|
1452
1585
|
bold: (text, enabled) => wrapAnsi("1", "22", text, enabled),
|
|
1453
1586
|
dim: (text, enabled) => wrapAnsi("2", "22", text, enabled),
|
|
1454
1587
|
italic: (text, enabled) => wrapAnsi("3", "23", text, enabled),
|
|
1455
1588
|
underline: (text, enabled) => wrapAnsi("4", "24", text, enabled),
|
|
1456
|
-
cyan: (text, enabled) =>
|
|
1457
|
-
green: (text, enabled) =>
|
|
1458
|
-
yellow: (text, enabled) =>
|
|
1459
|
-
red: (text, enabled) =>
|
|
1460
|
-
magenta: (text, enabled) =>
|
|
1461
|
-
blue: (text, enabled) =>
|
|
1462
|
-
gray: (text, enabled) =>
|
|
1463
|
-
white: (text, enabled) =>
|
|
1589
|
+
cyan: (text, enabled) => fgHex(CHARM_PALETTE.cyan, text, enabled),
|
|
1590
|
+
green: (text, enabled) => fgHex(CHARM_PALETTE.mint, text, enabled),
|
|
1591
|
+
yellow: (text, enabled) => fgHex(CHARM_PALETTE.amber, text, enabled),
|
|
1592
|
+
red: (text, enabled) => fgHex(CHARM_PALETTE.coral, text, enabled),
|
|
1593
|
+
magenta: (text, enabled) => fgHex(CHARM_PALETTE.fuchsia, text, enabled),
|
|
1594
|
+
blue: (text, enabled) => fgHex(CHARM_PALETTE.indigo, text, enabled),
|
|
1595
|
+
gray: (text, enabled) => fgHex(CHARM_PALETTE.muted, text, enabled),
|
|
1596
|
+
white: (text, enabled) => fgHex(CHARM_PALETTE.white, text, enabled)
|
|
1464
1597
|
};
|
|
1465
1598
|
function stripAnsi(text) {
|
|
1466
1599
|
return text.replace(ANSI_ESCAPE_REGEX, "");
|
|
@@ -1488,7 +1621,7 @@ function renderBox(lines, options) {
|
|
|
1488
1621
|
const paddingX = options?.paddingX ?? 2;
|
|
1489
1622
|
const minWidth = options?.minWidth ?? 36;
|
|
1490
1623
|
const colorEnabled = options?.colorEnabled;
|
|
1491
|
-
const borderFn = options?.borderColor ?? style.
|
|
1624
|
+
const borderFn = options?.borderColor ?? style.blue;
|
|
1492
1625
|
const titleText = options?.title ? ` ${options.title.trim()} ` : "";
|
|
1493
1626
|
const titleVisibleLen = visibleLength(titleText);
|
|
1494
1627
|
const maxLineLen = lines.reduce(
|
|
@@ -1513,7 +1646,13 @@ function renderBox(lines, options) {
|
|
|
1513
1646
|
function renderHeaderBanner(subtitle = "Framework & Library for AI Skills & Subagents", options) {
|
|
1514
1647
|
const ver = options?.version ?? SKILLOPS_VERSION;
|
|
1515
1648
|
const c = options?.colorEnabled;
|
|
1516
|
-
|
|
1649
|
+
const brandPill = renderPill(`\u25C6 SkillOps v${ver}`, {
|
|
1650
|
+
fg: CHARM_PALETTE.white,
|
|
1651
|
+
bg: CHARM_PALETTE.indigo,
|
|
1652
|
+
bold: true,
|
|
1653
|
+
colorEnabled: c
|
|
1654
|
+
});
|
|
1655
|
+
return `${brandPill} ${style.dim("\u2014", c)} ${fgHex(CHARM_PALETTE.lavender, subtitle, c)}`;
|
|
1517
1656
|
}
|
|
1518
1657
|
function renderTable(headers, rows, options) {
|
|
1519
1658
|
const indent = " ".repeat(options?.indent ?? 2);
|
|
@@ -1590,15 +1729,19 @@ function formatBadge(type, customLabel, colorEnabled) {
|
|
|
1590
1729
|
colorEnabled
|
|
1591
1730
|
);
|
|
1592
1731
|
case "skill":
|
|
1593
|
-
return
|
|
1594
|
-
|
|
1732
|
+
return renderPill(`[${customLabel ?? "SKILL"}]`, {
|
|
1733
|
+
fg: CHARM_PALETTE.white,
|
|
1734
|
+
bg: CHARM_PALETTE.indigo,
|
|
1735
|
+
bold: true,
|
|
1595
1736
|
colorEnabled
|
|
1596
|
-
);
|
|
1737
|
+
});
|
|
1597
1738
|
case "subagent":
|
|
1598
|
-
return
|
|
1599
|
-
|
|
1739
|
+
return renderPill(`[${customLabel ?? "SUBAGENT"}]`, {
|
|
1740
|
+
fg: CHARM_PALETTE.white,
|
|
1741
|
+
bg: CHARM_PALETTE.hotPink,
|
|
1742
|
+
bold: true,
|
|
1600
1743
|
colorEnabled
|
|
1601
|
-
);
|
|
1744
|
+
});
|
|
1602
1745
|
}
|
|
1603
1746
|
}
|
|
1604
1747
|
function renderStep(step, total, title, detail, status = "done", colorEnabled) {
|
|
@@ -5430,6 +5573,9 @@ function optionMatchesQuery(opt, rawQuery) {
|
|
|
5430
5573
|
if (!q) {
|
|
5431
5574
|
return true;
|
|
5432
5575
|
}
|
|
5576
|
+
if (opt.isSelectAll) {
|
|
5577
|
+
return false;
|
|
5578
|
+
}
|
|
5433
5579
|
return opt.label.toLowerCase().includes(q) || opt.value.toLowerCase().includes(q) || (opt.hint ?? "").toLowerCase().includes(q);
|
|
5434
5580
|
}
|
|
5435
5581
|
function getFilteredTabOptions(state, tab = state.activeTab) {
|
|
@@ -5437,16 +5583,47 @@ function getFilteredTabOptions(state, tab = state.activeTab) {
|
|
|
5437
5583
|
(opt) => optionMatchesTab(opt, tab) && optionMatchesQuery(opt, state.searchQuery)
|
|
5438
5584
|
);
|
|
5439
5585
|
}
|
|
5440
|
-
function createMultiSelectState(options) {
|
|
5586
|
+
function createMultiSelectState(options, stateOptions = {}) {
|
|
5587
|
+
let finalOptions = options;
|
|
5588
|
+
if (stateOptions.showSelectAll && !options.some((opt) => opt.isSelectAll === true)) {
|
|
5589
|
+
const skillItems = options.filter((opt) => optionMatchesTab(opt, "skill"));
|
|
5590
|
+
const agentItems = options.filter((opt) => optionMatchesTab(opt, "agent"));
|
|
5591
|
+
const withAll = [];
|
|
5592
|
+
if (skillItems.length > 0) {
|
|
5593
|
+
withAll.push({
|
|
5594
|
+
value: "__all_skills__",
|
|
5595
|
+
label: "[ALL] Select all Skills",
|
|
5596
|
+
kind: "skill",
|
|
5597
|
+
tab: "skill",
|
|
5598
|
+
isSelectAll: true,
|
|
5599
|
+
hint: `Select or deselect all ${skillItems.length} Skills in this tab`
|
|
5600
|
+
});
|
|
5601
|
+
withAll.push(...skillItems);
|
|
5602
|
+
}
|
|
5603
|
+
if (agentItems.length > 0) {
|
|
5604
|
+
withAll.push({
|
|
5605
|
+
value: "__all_agents__",
|
|
5606
|
+
label: "[ALL] Select all Agents",
|
|
5607
|
+
kind: "agent",
|
|
5608
|
+
tab: "agent",
|
|
5609
|
+
isSelectAll: true,
|
|
5610
|
+
hint: `Select or deselect all ${agentItems.length} Agents in this tab`
|
|
5611
|
+
});
|
|
5612
|
+
withAll.push(...agentItems);
|
|
5613
|
+
}
|
|
5614
|
+
if (withAll.length > 0) {
|
|
5615
|
+
finalOptions = withAll;
|
|
5616
|
+
}
|
|
5617
|
+
}
|
|
5441
5618
|
const initial = /* @__PURE__ */ new Set();
|
|
5442
|
-
for (const opt of
|
|
5443
|
-
if (opt.initialSelected) {
|
|
5619
|
+
for (const opt of finalOptions) {
|
|
5620
|
+
if (opt.initialSelected && !opt.isSelectAll) {
|
|
5444
5621
|
initial.add(opt.value);
|
|
5445
5622
|
}
|
|
5446
5623
|
}
|
|
5447
|
-
const hasSkills =
|
|
5624
|
+
const hasSkills = finalOptions.some((opt) => optionMatchesTab(opt, "skill"));
|
|
5448
5625
|
return {
|
|
5449
|
-
options,
|
|
5626
|
+
options: finalOptions,
|
|
5450
5627
|
activeTab: hasSkills ? "skill" : "agent",
|
|
5451
5628
|
cursor: 0,
|
|
5452
5629
|
selected: initial,
|
|
@@ -5536,6 +5713,29 @@ function applyMultiSelectKey(state, key, options = {}) {
|
|
|
5536
5713
|
if (!currentOpt) {
|
|
5537
5714
|
return state;
|
|
5538
5715
|
}
|
|
5716
|
+
if (currentOpt.isSelectAll) {
|
|
5717
|
+
const realVisible = visible.filter((opt) => !opt.isSelectAll);
|
|
5718
|
+
if (realVisible.length === 0) {
|
|
5719
|
+
return state;
|
|
5720
|
+
}
|
|
5721
|
+
const allTabSelected = realVisible.every(
|
|
5722
|
+
(opt) => state.selected.has(opt.value)
|
|
5723
|
+
);
|
|
5724
|
+
const nextSelected2 = new Set(state.selected);
|
|
5725
|
+
if (allTabSelected) {
|
|
5726
|
+
for (const opt of realVisible) {
|
|
5727
|
+
nextSelected2.delete(opt.value);
|
|
5728
|
+
}
|
|
5729
|
+
} else {
|
|
5730
|
+
for (const opt of realVisible) {
|
|
5731
|
+
nextSelected2.add(opt.value);
|
|
5732
|
+
}
|
|
5733
|
+
}
|
|
5734
|
+
return {
|
|
5735
|
+
...state,
|
|
5736
|
+
selected: nextSelected2
|
|
5737
|
+
};
|
|
5738
|
+
}
|
|
5539
5739
|
const nextSelected = new Set(state.selected);
|
|
5540
5740
|
if (nextSelected.has(currentOpt.value)) {
|
|
5541
5741
|
nextSelected.delete(currentOpt.value);
|
|
@@ -5599,19 +5799,20 @@ function applyMultiSelectKey(state, key, options = {}) {
|
|
|
5599
5799
|
};
|
|
5600
5800
|
}
|
|
5601
5801
|
if (key === "a" || key === "A") {
|
|
5602
|
-
|
|
5802
|
+
const realVisible = visible.filter((opt) => !opt.isSelectAll);
|
|
5803
|
+
if (realVisible.length === 0) {
|
|
5603
5804
|
return state;
|
|
5604
5805
|
}
|
|
5605
|
-
const allTabSelected =
|
|
5806
|
+
const allTabSelected = realVisible.every(
|
|
5606
5807
|
(opt) => state.selected.has(opt.value)
|
|
5607
5808
|
);
|
|
5608
5809
|
const nextSelected = new Set(state.selected);
|
|
5609
5810
|
if (allTabSelected) {
|
|
5610
|
-
for (const opt of
|
|
5811
|
+
for (const opt of realVisible) {
|
|
5611
5812
|
nextSelected.delete(opt.value);
|
|
5612
5813
|
}
|
|
5613
5814
|
} else {
|
|
5614
|
-
for (const opt of
|
|
5815
|
+
for (const opt of realVisible) {
|
|
5615
5816
|
nextSelected.add(opt.value);
|
|
5616
5817
|
}
|
|
5617
5818
|
}
|
|
@@ -5626,41 +5827,69 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5626
5827
|
const c = options.colorEnabled;
|
|
5627
5828
|
const bar = style.dim("\u2502", c);
|
|
5628
5829
|
const maxVisible = options.maxVisible ?? 10;
|
|
5629
|
-
const
|
|
5830
|
+
const realOptions = state.options.filter((o) => !o.isSelectAll);
|
|
5831
|
+
const totalSkills = realOptions.filter(
|
|
5630
5832
|
(o) => optionMatchesTab(o, "skill")
|
|
5631
5833
|
).length;
|
|
5632
|
-
const totalAgents =
|
|
5834
|
+
const totalAgents = realOptions.filter(
|
|
5633
5835
|
(o) => optionMatchesTab(o, "agent")
|
|
5634
5836
|
).length;
|
|
5635
5837
|
const filteredSkills = getFilteredTabOptions(state, "skill");
|
|
5636
5838
|
const filteredAgents = getFilteredTabOptions(state, "agent");
|
|
5839
|
+
const realFilteredSkills = filteredSkills.filter((o) => !o.isSelectAll);
|
|
5840
|
+
const realFilteredAgents = filteredAgents.filter((o) => !o.isSelectAll);
|
|
5637
5841
|
const visible = state.activeTab === "skill" ? filteredSkills : filteredAgents;
|
|
5842
|
+
const realVisible = state.activeTab === "skill" ? realFilteredSkills : realFilteredAgents;
|
|
5638
5843
|
const total = visible.length;
|
|
5639
5844
|
const skillTabTitle = options.tabLabels?.skill ?? "Skills";
|
|
5640
5845
|
const agentTabTitle = options.tabLabels?.agent ?? "Agents";
|
|
5641
5846
|
const submitVerb = options.submitActionLabel ?? "import";
|
|
5642
5847
|
const isSinglePage = totalAgents === 0 || totalSkills === 0;
|
|
5643
|
-
const header =
|
|
5644
|
-
|
|
5645
|
-
|
|
5848
|
+
const header = renderPill(`\u25C6 ${title}`, {
|
|
5849
|
+
fg: CHARM_PALETTE.white,
|
|
5850
|
+
bg: CHARM_PALETTE.indigo,
|
|
5851
|
+
bold: true,
|
|
5852
|
+
colorEnabled: c
|
|
5853
|
+
});
|
|
5854
|
+
const sep = style.dim(" \xB7 ", c);
|
|
5855
|
+
const keyItems = [
|
|
5856
|
+
renderKeycap("\u2191/\u2193", "move", c),
|
|
5857
|
+
...isSinglePage ? [] : [renderKeycap("\u2190/\u2192", "tab", c)],
|
|
5858
|
+
renderKeycap("Space", "select", c),
|
|
5859
|
+
...state.searchMode ? [renderKeycap("Esc", "clear", c)] : [renderKeycap("/", "search", c), renderKeycap("a", "all", c)],
|
|
5860
|
+
renderKeycap("Enter", submitVerb, c)
|
|
5861
|
+
];
|
|
5862
|
+
const instructions = `${bar} ${keyItems.join(sep)}`;
|
|
5646
5863
|
const lines = [header];
|
|
5647
5864
|
if (options.subtitle) {
|
|
5648
|
-
lines.push(`${bar} ${options.subtitle}`);
|
|
5865
|
+
lines.push(`${bar} ${fgHex(CHARM_PALETTE.lavender, options.subtitle, c)}`);
|
|
5649
5866
|
}
|
|
5650
5867
|
lines.push(instructions, bar);
|
|
5651
5868
|
const hasQuery = state.searchQuery.length > 0;
|
|
5652
|
-
const skillCountStr = hasQuery ? `${
|
|
5653
|
-
const agentCountStr = hasQuery ? `${
|
|
5654
|
-
const skillTabLabel = state.activeTab === "skill" ?
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
|
|
5869
|
+
const skillCountStr = hasQuery ? `${realFilteredSkills.length}/${totalSkills}` : `${totalSkills}`;
|
|
5870
|
+
const agentCountStr = hasQuery ? `${realFilteredAgents.length}/${totalAgents}` : `${totalAgents}`;
|
|
5871
|
+
const skillTabLabel = state.activeTab === "skill" ? renderPill(`[ \u25C6 ${skillTabTitle} (${skillCountStr}) ]`, {
|
|
5872
|
+
fg: CHARM_PALETTE.white,
|
|
5873
|
+
bg: CHARM_PALETTE.indigo,
|
|
5874
|
+
bold: true,
|
|
5875
|
+
colorEnabled: c
|
|
5876
|
+
}) : style.dim(`\u25CB ${skillTabTitle} (${skillCountStr})`, c);
|
|
5877
|
+
const agentTabLabel = state.activeTab === "agent" ? renderPill(`[ \u25C6 ${agentTabTitle} (${agentCountStr}) ]`, {
|
|
5878
|
+
fg: CHARM_PALETTE.white,
|
|
5879
|
+
bg: CHARM_PALETTE.hotPink,
|
|
5880
|
+
bold: true,
|
|
5881
|
+
colorEnabled: c
|
|
5882
|
+
}) : style.dim(`\u25CB ${agentTabTitle} (${agentCountStr})`, c);
|
|
5662
5883
|
const rawQuerySlice = state.searchQuery.length > 14 ? `\u2026${state.searchQuery.slice(-13)}` : state.searchQuery;
|
|
5663
|
-
const searchSuffix = state.searchMode || hasQuery ? ` ${
|
|
5884
|
+
const searchSuffix = state.searchMode || hasQuery ? ` ${renderPill(
|
|
5885
|
+
`/ Filter: ${rawQuerySlice}${state.searchMode ? "\u2588" : ""}`,
|
|
5886
|
+
{
|
|
5887
|
+
fg: CHARM_PALETTE.amber,
|
|
5888
|
+
bg: CHARM_PALETTE.surface,
|
|
5889
|
+
bold: true,
|
|
5890
|
+
colorEnabled: c
|
|
5891
|
+
}
|
|
5892
|
+
)}` : ` ${style.dim("(/ search)", c)}`;
|
|
5664
5893
|
const singleTabLabel = totalSkills > 0 ? skillTabLabel : agentTabLabel;
|
|
5665
5894
|
lines.push(
|
|
5666
5895
|
isSinglePage ? `${style.dim("\u251C\u2500", c)} ${singleTabLabel}${searchSuffix}` : `${style.dim("\u251C\u2500", c)} ${skillTabLabel} ${agentTabLabel}${searchSuffix}`,
|
|
@@ -5678,8 +5907,16 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5678
5907
|
startIdx = Math.max(0, Math.min(state.cursor - half, total - maxVisible));
|
|
5679
5908
|
}
|
|
5680
5909
|
const endIdx = Math.min(total, startIdx + maxVisible);
|
|
5910
|
+
const totalPages = Math.max(1, Math.ceil(total / maxVisible));
|
|
5911
|
+
const currentPage = Math.min(
|
|
5912
|
+
totalPages - 1,
|
|
5913
|
+
Math.floor(state.cursor / maxVisible)
|
|
5914
|
+
);
|
|
5915
|
+
const pageDots = totalPages > 1 ? ` ${renderPaginationDots(currentPage, totalPages, c)}` : "";
|
|
5681
5916
|
if (startIdx > 0) {
|
|
5682
|
-
lines.push(
|
|
5917
|
+
lines.push(
|
|
5918
|
+
`${bar} ${style.dim(`\u2191 ${startIdx} more above...`, c)}${endIdx >= total ? pageDots : ""}`
|
|
5919
|
+
);
|
|
5683
5920
|
}
|
|
5684
5921
|
const maxLabelCols = Math.min(
|
|
5685
5922
|
26,
|
|
@@ -5689,30 +5926,32 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5689
5926
|
const opt = visible[i];
|
|
5690
5927
|
if (!opt) continue;
|
|
5691
5928
|
const isCurrent = i === state.cursor;
|
|
5692
|
-
const
|
|
5693
|
-
const
|
|
5694
|
-
const
|
|
5929
|
+
const allRealSelected = realVisible.length > 0 && realVisible.every((o) => state.selected.has(o.value));
|
|
5930
|
+
const someRealSelected = realVisible.some((o) => state.selected.has(o.value)) && !allRealSelected;
|
|
5931
|
+
const isChecked = opt.isSelectAll ? allRealSelected : state.selected.has(opt.value);
|
|
5932
|
+
const pointer = isCurrent ? fgHex(CHARM_PALETTE.hotPink, style.bold("\u276F", c), c) : " ";
|
|
5933
|
+
const checkbox = isChecked ? style.green("\u25C9", c) : opt.isSelectAll && someRealSelected ? fgHex(CHARM_PALETTE.fuchsia, "\u25D0", c) : style.dim("\u25EF", c);
|
|
5695
5934
|
const labelRaw = opt.label.length > maxLabelCols ? `${opt.label.slice(0, maxLabelCols - 1)}\u2026` : opt.label;
|
|
5696
5935
|
const labelPadded = padVisible(labelRaw, maxLabelCols + 1, "left");
|
|
5697
|
-
const styledLabel = isCurrent ? style.bold(labelPadded, c) : isChecked ? style.green(labelPadded, c) : labelPadded;
|
|
5936
|
+
const styledLabel = isCurrent ? fgHex(CHARM_PALETTE.fuchsia, style.bold(labelPadded, c), c) : isChecked ? style.green(labelPadded, c) : labelPadded;
|
|
5698
5937
|
const prefixWidth = 7 + maxLabelCols + 1;
|
|
5699
5938
|
const maxHintCols = Math.max(10, 76 - prefixWidth);
|
|
5700
5939
|
const rawHint = opt.hint ?? "";
|
|
5701
5940
|
const shortHint = rawHint.length > maxHintCols ? `${rawHint.slice(0, maxHintCols - 1)}\u2026` : rawHint;
|
|
5702
|
-
const hintPart = shortHint ? ` ${style.dim(shortHint, c)}` : "";
|
|
5941
|
+
const hintPart = shortHint ? ` ${isCurrent ? fgHex(CHARM_PALETTE.lavender, shortHint, c) : style.dim(shortHint, c)}` : "";
|
|
5703
5942
|
lines.push(`${bar} ${pointer} ${checkbox} ${styledLabel}${hintPart}`);
|
|
5704
5943
|
}
|
|
5705
5944
|
if (endIdx < total) {
|
|
5706
5945
|
lines.push(
|
|
5707
|
-
`${bar} ${style.dim(`\u2193 ${total - endIdx} more below...`, c)}`
|
|
5946
|
+
`${bar} ${style.dim(`\u2193 ${total - endIdx} more below...`, c)}${pageDots}`
|
|
5708
5947
|
);
|
|
5709
5948
|
}
|
|
5710
5949
|
}
|
|
5711
5950
|
lines.push(bar);
|
|
5712
|
-
const selectedSkillsCount =
|
|
5951
|
+
const selectedSkillsCount = realOptions.filter(
|
|
5713
5952
|
(o) => optionMatchesTab(o, "skill") && state.selected.has(o.value)
|
|
5714
5953
|
).length;
|
|
5715
|
-
const selectedAgentsCount =
|
|
5954
|
+
const selectedAgentsCount = realOptions.filter(
|
|
5716
5955
|
(o) => optionMatchesTab(o, "agent") && state.selected.has(o.value)
|
|
5717
5956
|
).length;
|
|
5718
5957
|
const currentOptLabel = visible[state.cursor]?.label ?? "";
|
|
@@ -5720,8 +5959,9 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5720
5959
|
const rawTarget = options.targetHint ?? "";
|
|
5721
5960
|
const shortTarget = rawTarget.length > 18 ? `${rawTarget.slice(0, 17)}\u2026` : rawTarget;
|
|
5722
5961
|
const targetSuffix = shortTarget ? ` \xB7 IDE: ${shortTarget}` : "";
|
|
5962
|
+
const styledSummary = state.selected.size > 0 ? fgHex(CHARM_PALETTE.mint, style.bold(summaryText, c), c) : fgHex(CHARM_PALETTE.lavender, style.bold(summaryText, c), c);
|
|
5723
5963
|
lines.push(
|
|
5724
|
-
`${style.dim("\u2570\u2500", c)} ${
|
|
5964
|
+
`${style.dim("\u2570\u2500", c)} ${styledSummary}${style.dim(`${targetSuffix} \u2014 Enter to ${submitVerb}`, c)}`
|
|
5725
5965
|
);
|
|
5726
5966
|
return lines.join("\n");
|
|
5727
5967
|
}
|
|
@@ -5729,7 +5969,9 @@ async function runMultiSelectPrompt(title, options, renderOpts = {}) {
|
|
|
5729
5969
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
5730
5970
|
return null;
|
|
5731
5971
|
}
|
|
5732
|
-
let state = createMultiSelectState(options
|
|
5972
|
+
let state = createMultiSelectState(options, {
|
|
5973
|
+
showSelectAll: renderOpts.showSelectAll
|
|
5974
|
+
});
|
|
5733
5975
|
let renderedLineCount = 0;
|
|
5734
5976
|
const render = () => {
|
|
5735
5977
|
const frame = renderMultiSelectFrame(title, state, renderOpts);
|
|
@@ -6500,6 +6742,7 @@ export {
|
|
|
6500
6742
|
ALL_RUNTIME_TARGETS,
|
|
6501
6743
|
BenchmarkArmSchema,
|
|
6502
6744
|
BenchmarkDeltaSchema,
|
|
6745
|
+
CHARM_PALETTE,
|
|
6503
6746
|
COMMAND_HELP_SPECS,
|
|
6504
6747
|
CORE_RUNTIME_TARGETS,
|
|
6505
6748
|
CatalogEvalSummarySchema,
|
|
@@ -6544,6 +6787,7 @@ export {
|
|
|
6544
6787
|
auditCatalogTokenBudgets,
|
|
6545
6788
|
auditSkillTokenBudget,
|
|
6546
6789
|
auditSubagentTokenBudget,
|
|
6790
|
+
bgHex,
|
|
6547
6791
|
classifyCollisionSeverity,
|
|
6548
6792
|
cleanSyncedArtifacts,
|
|
6549
6793
|
compileSkillBundle,
|
|
@@ -6565,6 +6809,7 @@ export {
|
|
|
6565
6809
|
evaluateCatalog,
|
|
6566
6810
|
evaluateSkillDirectory,
|
|
6567
6811
|
extractSkillFeatures,
|
|
6812
|
+
fgHex,
|
|
6568
6813
|
findCommandHelpSpec,
|
|
6569
6814
|
fingerprintRepository,
|
|
6570
6815
|
formatBadge,
|
|
@@ -6581,9 +6826,11 @@ export {
|
|
|
6581
6826
|
formatTokenEconomyReport,
|
|
6582
6827
|
getFilteredTabOptions,
|
|
6583
6828
|
handleMcpJsonRpcRequest,
|
|
6829
|
+
hexToRgb,
|
|
6584
6830
|
inspectCatalogItem,
|
|
6585
6831
|
inspectHarnesses,
|
|
6586
6832
|
isColorEnabled,
|
|
6833
|
+
joinHorizontal,
|
|
6587
6834
|
levenshteinDistance,
|
|
6588
6835
|
loadSkillOpsConfig,
|
|
6589
6836
|
normalizePackageName,
|
|
@@ -6599,8 +6846,11 @@ export {
|
|
|
6599
6846
|
renderCommandHelp,
|
|
6600
6847
|
renderGlobalHelp,
|
|
6601
6848
|
renderHeaderBanner,
|
|
6849
|
+
renderKeycap,
|
|
6602
6850
|
renderMultiSelectFrame,
|
|
6603
6851
|
renderNextSteps,
|
|
6852
|
+
renderPaginationDots,
|
|
6853
|
+
renderPill,
|
|
6604
6854
|
renderProgressBar,
|
|
6605
6855
|
renderSectionHeader,
|
|
6606
6856
|
renderStep,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skillops-cli",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.8",
|
|
4
4
|
"description": "SkillOps — The Zero-API Framework & Benchmark-Verified Library for High-End AI Coding Skills & Context-Isolated Subagents with Universal Top-28 AI Agent Transpilation & Token Economy Auditing.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|