playbooks 0.1.17 → 0.1.18
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/index.js +1295 -995
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import { program } from "commander";
|
|
|
8
8
|
// package.json
|
|
9
9
|
var package_default = {
|
|
10
10
|
name: "playbooks",
|
|
11
|
-
version: "0.1.
|
|
11
|
+
version: "0.1.18",
|
|
12
12
|
description: "Install agent skills, MCPs and docs into your coding agents from any git repository.",
|
|
13
13
|
type: "module",
|
|
14
14
|
bin: {
|
|
@@ -656,6 +656,31 @@ async function pollUrlMarkdown(jobId, timeoutMs = 6e4, pollIntervalMs = 1e3) {
|
|
|
656
656
|
}
|
|
657
657
|
throw new Error("Timed out waiting for markdown");
|
|
658
658
|
}
|
|
659
|
+
async function fetchBundle(slug) {
|
|
660
|
+
const url = new URL(`${API_BASE}/bundles/${encodeURIComponent(slug)}`);
|
|
661
|
+
const response = await fetch(url.toString(), {
|
|
662
|
+
headers: {
|
|
663
|
+
"User-Agent": USER_AGENT
|
|
664
|
+
}
|
|
665
|
+
});
|
|
666
|
+
let payload = null;
|
|
667
|
+
try {
|
|
668
|
+
payload = await response.json();
|
|
669
|
+
} catch {
|
|
670
|
+
payload = null;
|
|
671
|
+
}
|
|
672
|
+
if (response.status === 404) {
|
|
673
|
+
throw new Error(`Bundle "${slug}" not found.`);
|
|
674
|
+
}
|
|
675
|
+
if (!response.ok || !payload?.success) {
|
|
676
|
+
const message = payload?.error || `Failed to fetch bundle (${response.status})`;
|
|
677
|
+
throw new Error(message);
|
|
678
|
+
}
|
|
679
|
+
if (!payload.bundle || !payload.skills) {
|
|
680
|
+
throw new Error("Invalid bundle response.");
|
|
681
|
+
}
|
|
682
|
+
return { bundle: payload.bundle, skills: payload.skills };
|
|
683
|
+
}
|
|
659
684
|
async function fetchUrlMarkdown(url) {
|
|
660
685
|
const response = await requestUrlMarkdown(url);
|
|
661
686
|
if (response.success && response.data) {
|
|
@@ -1310,93 +1335,656 @@ function BrandHeader() {
|
|
|
1310
1335
|
setTitle(TARGET_TEXT);
|
|
1311
1336
|
return false;
|
|
1312
1337
|
}
|
|
1313
|
-
return true;
|
|
1338
|
+
return true;
|
|
1339
|
+
};
|
|
1340
|
+
tick();
|
|
1341
|
+
const timer = setInterval(() => {
|
|
1342
|
+
if (!tick()) {
|
|
1343
|
+
clearInterval(timer);
|
|
1344
|
+
}
|
|
1345
|
+
}, interval);
|
|
1346
|
+
return () => {
|
|
1347
|
+
clearInterval(timer);
|
|
1348
|
+
};
|
|
1349
|
+
}, []);
|
|
1350
|
+
return /* @__PURE__ */ jsxs(Box, { marginBottom: 1, flexDirection: "column", children: [
|
|
1351
|
+
/* @__PURE__ */ jsx2(Text, { bold: true, children: title }),
|
|
1352
|
+
/* @__PURE__ */ jsx2(Text, { dimColor: true, children: TAGLINE })
|
|
1353
|
+
] });
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
// src/tui/ui/FlashBar.tsx
|
|
1357
|
+
import { Box as Box2, Text as Text2 } from "ink";
|
|
1358
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1359
|
+
function classify(msg) {
|
|
1360
|
+
const m = msg.toLowerCase();
|
|
1361
|
+
if (/(error|failed|unable|denied|invalid|cannot|not found)/i.test(msg)) return "error";
|
|
1362
|
+
if (/(deleted|linked|unlinked|updated|created|saved|enabled|disabled|added|removed|✓)/i.test(msg))
|
|
1363
|
+
return "success";
|
|
1364
|
+
if (/(warn|deprecated|missing|retry|timeout)/i.test(msg)) return "warning";
|
|
1365
|
+
return "info";
|
|
1366
|
+
}
|
|
1367
|
+
function FlashBar({ align = "left" }) {
|
|
1368
|
+
const { flashes } = useNavigation();
|
|
1369
|
+
if (flashes.length === 0) return /* @__PURE__ */ jsx3(Box2, { height: 1 });
|
|
1370
|
+
return /* @__PURE__ */ jsx3(
|
|
1371
|
+
Box2,
|
|
1372
|
+
{
|
|
1373
|
+
flexDirection: "column",
|
|
1374
|
+
paddingX: 1,
|
|
1375
|
+
paddingY: 0,
|
|
1376
|
+
gap: 0,
|
|
1377
|
+
justifyContent: align === "center" ? "center" : "flex-start",
|
|
1378
|
+
children: flashes.map((flash) => {
|
|
1379
|
+
const kind = classify(flash.text);
|
|
1380
|
+
const color = kind === "success" ? "green" : kind === "error" ? "red" : kind === "warning" ? "yellow" : "cyan";
|
|
1381
|
+
const label = kind === "success" ? "\u2713" : kind === "error" ? "x" : kind === "warning" ? "!" : "i";
|
|
1382
|
+
return /* @__PURE__ */ jsxs2(Text2, { color, children: [
|
|
1383
|
+
"[",
|
|
1384
|
+
label,
|
|
1385
|
+
"] ",
|
|
1386
|
+
flash.text
|
|
1387
|
+
] }, flash.id);
|
|
1388
|
+
})
|
|
1389
|
+
}
|
|
1390
|
+
);
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
// src/tui/screens/AddBundleSelect.tsx
|
|
1394
|
+
import { basename as basename4 } from "path";
|
|
1395
|
+
import { Box as Box6, Text as Text6 } from "ink";
|
|
1396
|
+
import React5 from "react";
|
|
1397
|
+
|
|
1398
|
+
// src/tui/controls/MultiSelect.tsx
|
|
1399
|
+
import { Box as Box3, Text as Text3, useInput } from "ink";
|
|
1400
|
+
import React3 from "react";
|
|
1401
|
+
|
|
1402
|
+
// src/tui/ui/hints.ts
|
|
1403
|
+
var TEXT_INPUT_HINT = "Ctrl+D to clear, Esc to go back";
|
|
1404
|
+
var MENU_HINT = "Use \u2191\u2193 to navigate, Enter to select, m for main, q/esc to quit";
|
|
1405
|
+
var SINGLE_SELECT_HINT = "Use \u2191\u2193 to navigate, Enter to continue, m for main, q/esc to quit";
|
|
1406
|
+
var MULTI_SELECT_HINT = "Space to toggle, s to select all, Enter to continue, m for main, q/esc to quit";
|
|
1407
|
+
var BACK_QUIT_HINT = "Press \u2190 to go back, q/esc to quit";
|
|
1408
|
+
var FIND_SKILLS_HINT = "Space to select one or more skills, then Enter to install.";
|
|
1409
|
+
var FIND_RESULTS_HINT = "Space to toggle, s to select all, i for info, Enter to install, q/esc to quit";
|
|
1410
|
+
var UPDATE_HINT_NEEDS_ONLY = "Showing needs update only. u to show all, s to select all, m for main, q/esc to quit";
|
|
1411
|
+
var UPDATE_HINT_ALL = "u to show needs update only, s to select all, m for main, q/esc to quit";
|
|
1412
|
+
var UPDATE_EMPTY_HINT = "Press u to show all, m for main, q/esc to quit";
|
|
1413
|
+
var SCAN_SKILLS_HINT = "Use \u2191\u2193 to navigate, i for info, Enter for actions, m for main, q/esc to quit";
|
|
1414
|
+
|
|
1415
|
+
// src/tui/controls/MultiSelect.tsx
|
|
1416
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1417
|
+
var FILTER_THRESHOLD = 10;
|
|
1418
|
+
function MultiSelect({
|
|
1419
|
+
items,
|
|
1420
|
+
initialSelected = [],
|
|
1421
|
+
onSubmit,
|
|
1422
|
+
limit = 10,
|
|
1423
|
+
hint = MULTI_SELECT_HINT,
|
|
1424
|
+
enableFilter,
|
|
1425
|
+
lockedSection,
|
|
1426
|
+
hintMode = "all",
|
|
1427
|
+
onSelectionChange
|
|
1428
|
+
}) {
|
|
1429
|
+
const [cursor, setCursor] = React3.useState(0);
|
|
1430
|
+
const [infoIndex, setInfoIndex] = React3.useState(null);
|
|
1431
|
+
const [filter, setFilter] = React3.useState("");
|
|
1432
|
+
const [selected, setSelected] = React3.useState(
|
|
1433
|
+
new Set(
|
|
1434
|
+
initialSelected.length > 0 ? items.map((item, index) => ({ item, index })).filter(({ item }) => initialSelected.includes(item.value)).map(({ index }) => index) : []
|
|
1435
|
+
)
|
|
1436
|
+
);
|
|
1437
|
+
const showFilter = enableFilter ?? items.length >= FILTER_THRESHOLD;
|
|
1438
|
+
const { setTextInputActive, setTextInputEscMode } = useNavigation();
|
|
1439
|
+
const resetFocus = React3.useCallback(() => {
|
|
1440
|
+
setCursor(0);
|
|
1441
|
+
setInfoIndex(null);
|
|
1442
|
+
}, []);
|
|
1443
|
+
React3.useEffect(() => {
|
|
1444
|
+
if (!showFilter) return;
|
|
1445
|
+
setTextInputActive(true);
|
|
1446
|
+
setTextInputEscMode("back");
|
|
1447
|
+
return () => {
|
|
1448
|
+
setTextInputActive(false);
|
|
1449
|
+
setTextInputEscMode("back");
|
|
1450
|
+
};
|
|
1451
|
+
}, [showFilter, setTextInputActive, setTextInputEscMode]);
|
|
1452
|
+
const filteredItems = React3.useMemo(() => {
|
|
1453
|
+
if (!filter) return items.map((item, index) => ({ item, originalIndex: index }));
|
|
1454
|
+
const lowerFilter = filter.toLowerCase();
|
|
1455
|
+
return items.map((item, index) => ({ item, originalIndex: index })).filter(
|
|
1456
|
+
({ item }) => item.label.toLowerCase().includes(lowerFilter) || String(item.value).toLowerCase().includes(lowerFilter)
|
|
1457
|
+
);
|
|
1458
|
+
}, [items, filter]);
|
|
1459
|
+
const total = filteredItems.length;
|
|
1460
|
+
const maxItems = Math.max(5, Math.min(limit, total));
|
|
1461
|
+
const windowStart = Math.min(
|
|
1462
|
+
Math.max(0, cursor - Math.floor(maxItems / 2)),
|
|
1463
|
+
Math.max(0, total - maxItems)
|
|
1464
|
+
);
|
|
1465
|
+
const visible = filteredItems.slice(windowStart, windowStart + maxItems);
|
|
1466
|
+
const truncate = (value, max = 100) => {
|
|
1467
|
+
if (value.length <= max) return value;
|
|
1468
|
+
return `${value.slice(0, max - 3)}...`;
|
|
1469
|
+
};
|
|
1470
|
+
const getSelectedValues = React3.useCallback(
|
|
1471
|
+
(nextSelected) => {
|
|
1472
|
+
const lockedValues = lockedSection ? lockedSection.items.map((i) => i.value) : [];
|
|
1473
|
+
const selectedValues = Array.from(nextSelected).map((index) => items[index]?.value).filter((value) => value !== void 0);
|
|
1474
|
+
return [...lockedValues, ...selectedValues];
|
|
1475
|
+
},
|
|
1476
|
+
[items, lockedSection]
|
|
1477
|
+
);
|
|
1478
|
+
useInput((input, key) => {
|
|
1479
|
+
if (showFilter) {
|
|
1480
|
+
if (key.backspace || key.delete) {
|
|
1481
|
+
setFilter((prev) => prev.slice(0, -1));
|
|
1482
|
+
resetFocus();
|
|
1483
|
+
return;
|
|
1484
|
+
}
|
|
1485
|
+
if (input && input.length === 1 && !key.ctrl && !key.meta && !key.return && !key.tab && input !== " " && input !== "s" && input !== "S" && input !== "i" && input !== "I") {
|
|
1486
|
+
setFilter((prev) => prev + input);
|
|
1487
|
+
resetFocus();
|
|
1488
|
+
return;
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
if (key.downArrow) {
|
|
1492
|
+
setCursor((prev) => {
|
|
1493
|
+
if (total === 0) return 0;
|
|
1494
|
+
const next = (prev + 1) % total;
|
|
1495
|
+
if (infoIndex !== null) {
|
|
1496
|
+
setInfoIndex(null);
|
|
1497
|
+
}
|
|
1498
|
+
return next;
|
|
1499
|
+
});
|
|
1500
|
+
} else if (key.upArrow) {
|
|
1501
|
+
setCursor((prev) => {
|
|
1502
|
+
if (total === 0) return 0;
|
|
1503
|
+
const next = (prev - 1 + total) % total;
|
|
1504
|
+
if (infoIndex !== null) {
|
|
1505
|
+
setInfoIndex(null);
|
|
1506
|
+
}
|
|
1507
|
+
return next;
|
|
1508
|
+
});
|
|
1509
|
+
} else if (input === " ") {
|
|
1510
|
+
if (total === 0) return;
|
|
1511
|
+
const currentFiltered = filteredItems[cursor];
|
|
1512
|
+
if (!currentFiltered) return;
|
|
1513
|
+
if (currentFiltered.item.disabled) return;
|
|
1514
|
+
const originalIndex = currentFiltered.originalIndex;
|
|
1515
|
+
setSelected((prev) => {
|
|
1516
|
+
const next = new Set(prev);
|
|
1517
|
+
if (next.has(originalIndex)) next.delete(originalIndex);
|
|
1518
|
+
else next.add(originalIndex);
|
|
1519
|
+
if (onSelectionChange) {
|
|
1520
|
+
onSelectionChange(getSelectedValues(next));
|
|
1521
|
+
}
|
|
1522
|
+
return next;
|
|
1523
|
+
});
|
|
1524
|
+
} else if (input === "s" || input === "S") {
|
|
1525
|
+
const selectableIndices = filteredItems.filter(({ item }) => !item.disabled).map(({ originalIndex }) => originalIndex);
|
|
1526
|
+
setSelected((prev) => {
|
|
1527
|
+
const allSelected = selectableIndices.length > 0 && selectableIndices.every((index) => prev.has(index));
|
|
1528
|
+
if (allSelected) {
|
|
1529
|
+
const next2 = new Set(prev);
|
|
1530
|
+
for (const index of selectableIndices) {
|
|
1531
|
+
next2.delete(index);
|
|
1532
|
+
}
|
|
1533
|
+
if (onSelectionChange) {
|
|
1534
|
+
onSelectionChange(getSelectedValues(next2));
|
|
1535
|
+
}
|
|
1536
|
+
return next2;
|
|
1537
|
+
}
|
|
1538
|
+
const next = new Set(prev);
|
|
1539
|
+
for (const index of selectableIndices) {
|
|
1540
|
+
next.add(index);
|
|
1541
|
+
}
|
|
1542
|
+
if (onSelectionChange) {
|
|
1543
|
+
onSelectionChange(getSelectedValues(next));
|
|
1544
|
+
}
|
|
1545
|
+
return next;
|
|
1546
|
+
});
|
|
1547
|
+
} else if (input === "i" || input === "I") {
|
|
1548
|
+
setInfoIndex((prev) => prev === cursor ? null : cursor);
|
|
1549
|
+
} else if (key.return) {
|
|
1550
|
+
const lockedValues = lockedSection ? lockedSection.items.map((i) => i.value) : [];
|
|
1551
|
+
const selectedValues = Array.from(selected).map((index) => items[index]?.value).filter((value) => value !== void 0);
|
|
1552
|
+
onSubmit([...lockedValues, ...selectedValues]);
|
|
1553
|
+
}
|
|
1554
|
+
});
|
|
1555
|
+
const filterHint = showFilter ? "Type to filter, " : "";
|
|
1556
|
+
const displayHint = filterHint + hint;
|
|
1557
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
1558
|
+
lockedSection && lockedSection.items.length > 0 && /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", marginBottom: 1, children: [
|
|
1559
|
+
/* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
1560
|
+
"\u2500\u2500 ",
|
|
1561
|
+
lockedSection.title,
|
|
1562
|
+
" \u2500\u2500"
|
|
1563
|
+
] }),
|
|
1564
|
+
lockedSection.items.map((item) => /* @__PURE__ */ jsxs3(Text3, { color: "green", children: [
|
|
1565
|
+
" ",
|
|
1566
|
+
"\u2713 ",
|
|
1567
|
+
item.label
|
|
1568
|
+
] }, String(item.value)))
|
|
1569
|
+
] }),
|
|
1570
|
+
lockedSection && items.length > 0 && /* @__PURE__ */ jsx4(Box3, { marginBottom: 0, children: /* @__PURE__ */ jsx4(Text3, { dimColor: true, children: "\u2500\u2500 Other agents \u2500\u2500" }) }),
|
|
1571
|
+
showFilter && /* @__PURE__ */ jsxs3(Box3, { marginBottom: 1, marginTop: lockedSection ? 1 : 0, children: [
|
|
1572
|
+
/* @__PURE__ */ jsx4(Text3, { dimColor: true, children: "Filter: " }),
|
|
1573
|
+
/* @__PURE__ */ jsx4(Text3, { children: filter || " " }),
|
|
1574
|
+
/* @__PURE__ */ jsx4(Text3, { dimColor: true, inverse: true, children: " " }),
|
|
1575
|
+
filter && /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
1576
|
+
" ",
|
|
1577
|
+
"(",
|
|
1578
|
+
filteredItems.length,
|
|
1579
|
+
"/",
|
|
1580
|
+
items.length,
|
|
1581
|
+
")"
|
|
1582
|
+
] })
|
|
1583
|
+
] }),
|
|
1584
|
+
total === 0 ? /* @__PURE__ */ jsx4(Text3, { dimColor: true, children: "No matches found" }) : visible.map(({ item, originalIndex }, index) => {
|
|
1585
|
+
const visibleIndex = windowStart + index;
|
|
1586
|
+
const isActive = visibleIndex === cursor;
|
|
1587
|
+
const isSelected = selected.has(originalIndex);
|
|
1588
|
+
const marker = isSelected ? "\u25FC" : "\u25FB";
|
|
1589
|
+
const pointer = isActive ? "\u276F" : " ";
|
|
1590
|
+
const color = item.disabled ? "gray" : isActive ? "cyan" : void 0;
|
|
1591
|
+
const showHint = hintMode === "all" || hintMode === "active" && isActive;
|
|
1592
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
1593
|
+
/* @__PURE__ */ jsxs3(Text3, { color, children: [
|
|
1594
|
+
pointer,
|
|
1595
|
+
" ",
|
|
1596
|
+
marker,
|
|
1597
|
+
" ",
|
|
1598
|
+
item.label
|
|
1599
|
+
] }),
|
|
1600
|
+
infoIndex === visibleIndex && item.info ? /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
1601
|
+
" ",
|
|
1602
|
+
" ",
|
|
1603
|
+
truncate(item.info)
|
|
1604
|
+
] }) : item.hint && showHint ? /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
1605
|
+
" ",
|
|
1606
|
+
" ",
|
|
1607
|
+
item.hint
|
|
1608
|
+
] }) : null
|
|
1609
|
+
] }, `${item.label}-${originalIndex}`);
|
|
1610
|
+
}),
|
|
1611
|
+
/* @__PURE__ */ jsx4(Box3, { marginTop: 1, children: /* @__PURE__ */ jsx4(Text3, { dimColor: true, children: displayHint }) })
|
|
1612
|
+
] });
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
// src/tui/ui/AddFlowHeader.tsx
|
|
1616
|
+
import { Box as Box5, Text as Text5 } from "ink";
|
|
1617
|
+
|
|
1618
|
+
// src/cli-utils.ts
|
|
1619
|
+
import { homedir as homedir2 } from "os";
|
|
1620
|
+
function shortenPath(fullPath, cwd) {
|
|
1621
|
+
const home2 = homedir2();
|
|
1622
|
+
if (fullPath.startsWith(home2)) {
|
|
1623
|
+
return fullPath.replace(home2, "~");
|
|
1624
|
+
}
|
|
1625
|
+
if (fullPath.startsWith(cwd)) {
|
|
1626
|
+
return `.${fullPath.slice(cwd.length)}`;
|
|
1627
|
+
}
|
|
1628
|
+
return fullPath;
|
|
1629
|
+
}
|
|
1630
|
+
function formatList(items, maxShow = 5) {
|
|
1631
|
+
if (items.length <= maxShow) {
|
|
1632
|
+
return items.join(", ");
|
|
1633
|
+
}
|
|
1634
|
+
const shown = items.slice(0, maxShow);
|
|
1635
|
+
const remaining = items.length - maxShow;
|
|
1636
|
+
return `${shown.join(", ")} +${remaining} more`;
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
// src/tui/ui/Header.tsx
|
|
1640
|
+
import { Box as Box4, Text as Text4 } from "ink";
|
|
1641
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1642
|
+
function Header({ title }) {
|
|
1643
|
+
return /* @__PURE__ */ jsx5(Box4, { marginBottom: 1, children: /* @__PURE__ */ jsx5(Text4, { bold: true, color: "cyan", children: title }) });
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
// src/tui/ui/AddFlowHeader.tsx
|
|
1647
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1648
|
+
function AddFlowHeader({ title }) {
|
|
1649
|
+
const { invocation, addSkill } = useNavigation();
|
|
1650
|
+
const source = addSkill.source ?? invocation.source;
|
|
1651
|
+
const cwd = process.cwd();
|
|
1652
|
+
let sourceLabel = source ?? "";
|
|
1653
|
+
if (addSkill.parsed?.type === "local" && addSkill.parsed.localPath) {
|
|
1654
|
+
sourceLabel = shortenPath(addSkill.parsed.localPath, cwd);
|
|
1655
|
+
}
|
|
1656
|
+
const selected = addSkill.selectedSkills;
|
|
1657
|
+
const available = addSkill.skills;
|
|
1658
|
+
let skillsLabel = null;
|
|
1659
|
+
if (selected && selected.length > 0) {
|
|
1660
|
+
skillsLabel = formatList(selected.map(getSkillDisplayName), 3);
|
|
1661
|
+
} else if (available && available.length > 0) {
|
|
1662
|
+
skillsLabel = `${available.length} available`;
|
|
1663
|
+
}
|
|
1664
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginBottom: 1, children: [
|
|
1665
|
+
/* @__PURE__ */ jsx6(Header, { title }),
|
|
1666
|
+
source ? /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: `Source: ${sourceLabel}` }) : null,
|
|
1667
|
+
skillsLabel ? /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: `Skills: ${skillsLabel}` }) : null
|
|
1668
|
+
] });
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
// src/tui/ui/spinner.ts
|
|
1672
|
+
import React4 from "react";
|
|
1673
|
+
var spinnerFrames = ["|", "/", "-", "\\"];
|
|
1674
|
+
function useSpinnerFrame(active = true, interval = 100) {
|
|
1675
|
+
const [index, setIndex] = React4.useState(0);
|
|
1676
|
+
React4.useEffect(() => {
|
|
1677
|
+
if (!active) return void 0;
|
|
1678
|
+
const timer = setInterval(() => {
|
|
1679
|
+
setIndex((prev) => (prev + 1) % spinnerFrames.length);
|
|
1680
|
+
}, interval);
|
|
1681
|
+
return () => clearInterval(timer);
|
|
1682
|
+
}, [active, interval]);
|
|
1683
|
+
return spinnerFrames[index] ?? "|";
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
// src/tui/utils/skill-selection.ts
|
|
1687
|
+
import { basename as basename3 } from "path";
|
|
1688
|
+
function matchesSkillName(skill, input) {
|
|
1689
|
+
const normalized = input.toLowerCase();
|
|
1690
|
+
const byName = skill.name.toLowerCase() === normalized;
|
|
1691
|
+
const byPath = basename3(skill.path).toLowerCase() === normalized;
|
|
1692
|
+
return byName || byPath;
|
|
1693
|
+
}
|
|
1694
|
+
function autoSelect(skills, options) {
|
|
1695
|
+
if (options.skill && options.skill.length > 0) {
|
|
1696
|
+
const selected = skills.filter((s) => options.skill?.some((name) => matchesSkillName(s, name)));
|
|
1697
|
+
if (selected.length === 0) {
|
|
1698
|
+
return {
|
|
1699
|
+
status: "prompt",
|
|
1700
|
+
message: `No matching skills found for: ${options.skill.join(", ")}`
|
|
1701
|
+
};
|
|
1702
|
+
}
|
|
1703
|
+
return { status: "selected", skills: selected };
|
|
1704
|
+
}
|
|
1705
|
+
if (skills.length === 1) {
|
|
1706
|
+
return { status: "selected", skills };
|
|
1707
|
+
}
|
|
1708
|
+
if (options.yes) {
|
|
1709
|
+
return { status: "selected", skills };
|
|
1710
|
+
}
|
|
1711
|
+
return { status: "prompt" };
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
// src/tui/screens/AddBundleSelect.tsx
|
|
1715
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1716
|
+
function groupByRepo(skills) {
|
|
1717
|
+
const map = /* @__PURE__ */ new Map();
|
|
1718
|
+
for (const skill of skills) {
|
|
1719
|
+
if (!skill.repoOwner || !skill.repoName) continue;
|
|
1720
|
+
const key = `${skill.repoOwner}/${skill.repoName}`;
|
|
1721
|
+
const list = map.get(key) ?? [];
|
|
1722
|
+
list.push(skill);
|
|
1723
|
+
map.set(key, list);
|
|
1724
|
+
}
|
|
1725
|
+
return map;
|
|
1726
|
+
}
|
|
1727
|
+
function findMatchingSkill(discovered, entry) {
|
|
1728
|
+
const targets = [entry.name, entry.skillSlug].filter((t) => Boolean(t)).map((t) => t.toLowerCase());
|
|
1729
|
+
for (const skill of discovered) {
|
|
1730
|
+
const candidates = [skill.name.toLowerCase(), basename4(skill.path).toLowerCase()];
|
|
1731
|
+
if (candidates.some((c) => targets.includes(c))) {
|
|
1732
|
+
return skill;
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
return void 0;
|
|
1736
|
+
}
|
|
1737
|
+
function AddBundleSelectScreen() {
|
|
1738
|
+
const {
|
|
1739
|
+
invocation,
|
|
1740
|
+
addSkill,
|
|
1741
|
+
updateAddSkill,
|
|
1742
|
+
navigateTo,
|
|
1743
|
+
setFlash,
|
|
1744
|
+
setBackHandler,
|
|
1745
|
+
resetTo,
|
|
1746
|
+
setInvocation,
|
|
1747
|
+
resetAddSkill,
|
|
1748
|
+
setLastSource
|
|
1749
|
+
} = useNavigation();
|
|
1750
|
+
const [status, setStatus] = React5.useState(
|
|
1751
|
+
addSkill.skills && addSkill.skills.length > 0 ? "ready" : "loading"
|
|
1752
|
+
);
|
|
1753
|
+
const [error, setError] = React5.useState(null);
|
|
1754
|
+
const [bundleName, setBundleName] = React5.useState(null);
|
|
1755
|
+
const [listMode, setListMode] = React5.useState(false);
|
|
1756
|
+
const [showLoading, setShowLoading] = React5.useState(false);
|
|
1757
|
+
const spinner = useSpinnerFrame(status === "loading");
|
|
1758
|
+
const slug = invocation.source;
|
|
1759
|
+
const options = invocation.options;
|
|
1760
|
+
React5.useEffect(() => {
|
|
1761
|
+
let cancelled = false;
|
|
1762
|
+
const load = async () => {
|
|
1763
|
+
if (!slug) {
|
|
1764
|
+
setError("Missing bundle slug.");
|
|
1765
|
+
setStatus("error");
|
|
1766
|
+
return;
|
|
1767
|
+
}
|
|
1768
|
+
if (addSkill.skills && addSkill.skills.length > 0) {
|
|
1769
|
+
setStatus("ready");
|
|
1770
|
+
return;
|
|
1771
|
+
}
|
|
1772
|
+
setStatus("loading");
|
|
1773
|
+
const tempDirs2 = [];
|
|
1774
|
+
try {
|
|
1775
|
+
const bundle = await fetchBundle(slug);
|
|
1776
|
+
if (cancelled) return;
|
|
1777
|
+
setBundleName(bundle.bundle.name);
|
|
1778
|
+
const cloneable = bundle.skills.filter((s) => s.repoOwner && s.repoName);
|
|
1779
|
+
const skippedCount = bundle.skills.length - cloneable.length;
|
|
1780
|
+
if (cloneable.length === 0) {
|
|
1781
|
+
throw new Error("No installable skills found in this bundle.");
|
|
1782
|
+
}
|
|
1783
|
+
const grouped = groupByRepo(cloneable);
|
|
1784
|
+
const allSkills = [];
|
|
1785
|
+
const warnings = [];
|
|
1786
|
+
for (const [repo, entries] of grouped) {
|
|
1787
|
+
if (cancelled) break;
|
|
1788
|
+
const repoUrl = `https://github.com/${repo}.git`;
|
|
1789
|
+
let tempDir;
|
|
1790
|
+
try {
|
|
1791
|
+
tempDir = await cloneRepo(repoUrl);
|
|
1792
|
+
} catch {
|
|
1793
|
+
warnings.push(`Failed to clone ${repo}`);
|
|
1794
|
+
continue;
|
|
1795
|
+
}
|
|
1796
|
+
tempDirs2.push(tempDir);
|
|
1797
|
+
let discovered;
|
|
1798
|
+
try {
|
|
1799
|
+
discovered = await discoverSkills(tempDir);
|
|
1800
|
+
} catch {
|
|
1801
|
+
warnings.push(`Failed to discover skills in ${repo}`);
|
|
1802
|
+
continue;
|
|
1803
|
+
}
|
|
1804
|
+
for (const entry of entries) {
|
|
1805
|
+
if (cancelled) break;
|
|
1806
|
+
const match = findMatchingSkill(discovered, entry);
|
|
1807
|
+
if (match) {
|
|
1808
|
+
allSkills.push(match);
|
|
1809
|
+
} else {
|
|
1810
|
+
warnings.push(`Could not find skill "${entry.name}" in ${repo}`);
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
if (cancelled) {
|
|
1815
|
+
for (const dir of tempDirs2) {
|
|
1816
|
+
try {
|
|
1817
|
+
await cleanupTempDir(dir);
|
|
1818
|
+
} catch {
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
return;
|
|
1822
|
+
}
|
|
1823
|
+
if (allSkills.length === 0) {
|
|
1824
|
+
for (const dir of tempDirs2) {
|
|
1825
|
+
try {
|
|
1826
|
+
await cleanupTempDir(dir);
|
|
1827
|
+
} catch {
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
const detail = warnings.length > 0 ? `
|
|
1831
|
+
${warnings.join("\n")}` : "";
|
|
1832
|
+
throw new Error(`No skills could be resolved from this bundle.${detail}`);
|
|
1833
|
+
}
|
|
1834
|
+
if (skippedCount > 0) {
|
|
1835
|
+
warnings.push(`${skippedCount} skill(s) skipped (missing repo info)`);
|
|
1836
|
+
}
|
|
1837
|
+
if (warnings.length > 0) {
|
|
1838
|
+
setFlash(warnings.join(". "));
|
|
1839
|
+
}
|
|
1840
|
+
updateAddSkill({
|
|
1841
|
+
tempDir: tempDirs2[0] ?? null,
|
|
1842
|
+
skills: allSkills
|
|
1843
|
+
});
|
|
1844
|
+
if (options.list) {
|
|
1845
|
+
setListMode(true);
|
|
1846
|
+
setStatus("list");
|
|
1847
|
+
return;
|
|
1848
|
+
}
|
|
1849
|
+
const autoSelection = autoSelect(allSkills, options);
|
|
1850
|
+
if (autoSelection.status === "selected") {
|
|
1851
|
+
updateAddSkill({
|
|
1852
|
+
selectedSkills: autoSelection.skills,
|
|
1853
|
+
securityBySkillName: void 0,
|
|
1854
|
+
securityScanRows: void 0,
|
|
1855
|
+
securityAccepted: void 0
|
|
1856
|
+
});
|
|
1857
|
+
navigateTo("add-security-scan");
|
|
1858
|
+
return;
|
|
1859
|
+
}
|
|
1860
|
+
if (autoSelection.status === "error") {
|
|
1861
|
+
throw new Error(autoSelection.message);
|
|
1862
|
+
}
|
|
1863
|
+
if (autoSelection.status === "prompt" && autoSelection.message) {
|
|
1864
|
+
setFlash(autoSelection.message);
|
|
1865
|
+
}
|
|
1866
|
+
setStatus("ready");
|
|
1867
|
+
} catch (err) {
|
|
1868
|
+
if (cancelled) return;
|
|
1869
|
+
for (const dir of tempDirs2) {
|
|
1870
|
+
try {
|
|
1871
|
+
await cleanupTempDir(dir);
|
|
1872
|
+
} catch {
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
updateAddSkill({ tempDir: null, skills: void 0, selectedSkills: void 0 });
|
|
1876
|
+
setError(err instanceof Error ? err.message : "Failed to load bundle");
|
|
1877
|
+
setStatus("error");
|
|
1878
|
+
}
|
|
1314
1879
|
};
|
|
1315
|
-
|
|
1316
|
-
const timer = setInterval(() => {
|
|
1317
|
-
if (!tick()) {
|
|
1318
|
-
clearInterval(timer);
|
|
1319
|
-
}
|
|
1320
|
-
}, interval);
|
|
1880
|
+
load();
|
|
1321
1881
|
return () => {
|
|
1322
|
-
|
|
1882
|
+
cancelled = true;
|
|
1323
1883
|
};
|
|
1324
|
-
}, []);
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
}
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
}
|
|
1342
|
-
function FlashBar({ align = "left" }) {
|
|
1343
|
-
const { flashes } = useNavigation();
|
|
1344
|
-
if (flashes.length === 0) return /* @__PURE__ */ jsx3(Box2, { height: 1 });
|
|
1345
|
-
return /* @__PURE__ */ jsx3(
|
|
1346
|
-
Box2,
|
|
1347
|
-
{
|
|
1348
|
-
flexDirection: "column",
|
|
1349
|
-
paddingX: 1,
|
|
1350
|
-
paddingY: 0,
|
|
1351
|
-
gap: 0,
|
|
1352
|
-
justifyContent: align === "center" ? "center" : "flex-start",
|
|
1353
|
-
children: flashes.map((flash) => {
|
|
1354
|
-
const kind = classify(flash.text);
|
|
1355
|
-
const color = kind === "success" ? "green" : kind === "error" ? "red" : kind === "warning" ? "yellow" : "cyan";
|
|
1356
|
-
const label = kind === "success" ? "\u2713" : kind === "error" ? "x" : kind === "warning" ? "!" : "i";
|
|
1357
|
-
return /* @__PURE__ */ jsxs2(Text2, { color, children: [
|
|
1358
|
-
"[",
|
|
1359
|
-
label,
|
|
1360
|
-
"] ",
|
|
1361
|
-
flash.text
|
|
1362
|
-
] }, flash.id);
|
|
1363
|
-
})
|
|
1884
|
+
}, [slug, addSkill.skills, updateAddSkill, navigateTo, options, setFlash]);
|
|
1885
|
+
React5.useEffect(() => {
|
|
1886
|
+
setBackHandler(() => {
|
|
1887
|
+
setLastSource(null);
|
|
1888
|
+
resetAddSkill();
|
|
1889
|
+
setInvocation({ intent: "none", options: {} });
|
|
1890
|
+
resetTo("main");
|
|
1891
|
+
return true;
|
|
1892
|
+
});
|
|
1893
|
+
return () => {
|
|
1894
|
+
setBackHandler(null);
|
|
1895
|
+
};
|
|
1896
|
+
}, [resetTo, setBackHandler, resetAddSkill, setInvocation, setLastSource]);
|
|
1897
|
+
React5.useEffect(() => {
|
|
1898
|
+
if (status !== "loading") {
|
|
1899
|
+
setShowLoading(false);
|
|
1900
|
+
return;
|
|
1364
1901
|
}
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
// src/cli-utils.ts
|
|
1374
|
-
import { homedir as homedir2 } from "os";
|
|
1375
|
-
function shortenPath(fullPath, cwd) {
|
|
1376
|
-
const home2 = homedir2();
|
|
1377
|
-
if (fullPath.startsWith(home2)) {
|
|
1378
|
-
return fullPath.replace(home2, "~");
|
|
1902
|
+
const timer = setTimeout(() => {
|
|
1903
|
+
setShowLoading(true);
|
|
1904
|
+
}, 150);
|
|
1905
|
+
return () => clearTimeout(timer);
|
|
1906
|
+
}, [status]);
|
|
1907
|
+
if (status === "loading" && !showLoading) {
|
|
1908
|
+
return /* @__PURE__ */ jsx7(Box6, { padding: 1 });
|
|
1379
1909
|
}
|
|
1380
|
-
if (
|
|
1381
|
-
return
|
|
1910
|
+
if (status === "loading") {
|
|
1911
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", padding: 1, children: [
|
|
1912
|
+
/* @__PURE__ */ jsx7(AddFlowHeader, { title: bundleName ? `Bundle: ${bundleName}` : "Loading bundle" }),
|
|
1913
|
+
/* @__PURE__ */ jsxs6(Text6, { children: [
|
|
1914
|
+
spinner,
|
|
1915
|
+
" ",
|
|
1916
|
+
bundleName ? "Cloning skills..." : `Fetching bundle "${slug}"...`
|
|
1917
|
+
] })
|
|
1918
|
+
] });
|
|
1382
1919
|
}
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1920
|
+
if (status === "error") {
|
|
1921
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", padding: 1, children: [
|
|
1922
|
+
/* @__PURE__ */ jsx7(AddFlowHeader, { title: "Unable to load bundle" }),
|
|
1923
|
+
/* @__PURE__ */ jsx7(Text6, { color: "red", children: error }),
|
|
1924
|
+
/* @__PURE__ */ jsx7(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
1925
|
+
] });
|
|
1388
1926
|
}
|
|
1389
|
-
const
|
|
1390
|
-
|
|
1391
|
-
|
|
1927
|
+
const skills = addSkill.skills ?? [];
|
|
1928
|
+
if (listMode || status === "list") {
|
|
1929
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", padding: 1, children: [
|
|
1930
|
+
/* @__PURE__ */ jsx7(AddFlowHeader, { title: `${bundleName ?? "Bundle"} (${skills.length} skills)` }),
|
|
1931
|
+
skills.map((skill) => /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginBottom: 1, children: [
|
|
1932
|
+
/* @__PURE__ */ jsx7(Text6, { children: getSkillDisplayName(skill) }),
|
|
1933
|
+
skill.description ? /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: skill.description }) : null
|
|
1934
|
+
] }, skill.name)),
|
|
1935
|
+
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: BACK_QUIT_HINT })
|
|
1936
|
+
] });
|
|
1937
|
+
}
|
|
1938
|
+
if (skills.length === 0) {
|
|
1939
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", padding: 1, children: [
|
|
1940
|
+
/* @__PURE__ */ jsx7(AddFlowHeader, { title: "No skills found" }),
|
|
1941
|
+
/* @__PURE__ */ jsx7(Text6, { dimColor: true, children: BACK_QUIT_HINT })
|
|
1942
|
+
] });
|
|
1943
|
+
}
|
|
1944
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", padding: 1, children: [
|
|
1945
|
+
/* @__PURE__ */ jsx7(AddFlowHeader, { title: `${bundleName ?? "Bundle"} - Select skills` }),
|
|
1946
|
+
/* @__PURE__ */ jsx7(
|
|
1947
|
+
MultiSelect,
|
|
1948
|
+
{
|
|
1949
|
+
items: skills.map((skill) => ({
|
|
1950
|
+
value: skill,
|
|
1951
|
+
label: getSkillDisplayName(skill),
|
|
1952
|
+
hint: skill.description && skill.description.length > 60 ? `${skill.description.slice(0, 57)}...` : skill.description
|
|
1953
|
+
})),
|
|
1954
|
+
initialSelected: addSkill.selectedSkills ?? skills,
|
|
1955
|
+
onSubmit: (values) => {
|
|
1956
|
+
if (values.length === 0) {
|
|
1957
|
+
setFlash("Select at least one skill.");
|
|
1958
|
+
return;
|
|
1959
|
+
}
|
|
1960
|
+
updateAddSkill({
|
|
1961
|
+
selectedSkills: values,
|
|
1962
|
+
targetAgents: void 0,
|
|
1963
|
+
installGlobally: void 0,
|
|
1964
|
+
installMode: void 0,
|
|
1965
|
+
planLines: void 0,
|
|
1966
|
+
securityBySkillName: void 0,
|
|
1967
|
+
securityScanRows: void 0,
|
|
1968
|
+
securityAccepted: void 0
|
|
1969
|
+
});
|
|
1970
|
+
navigateTo("add-security-scan");
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
)
|
|
1974
|
+
] });
|
|
1392
1975
|
}
|
|
1393
1976
|
|
|
1977
|
+
// src/tui/screens/AddConfirm.tsx
|
|
1978
|
+
import { join as join9 } from "path";
|
|
1979
|
+
import { Box as Box12, Text as Text12 } from "ink";
|
|
1980
|
+
import React9 from "react";
|
|
1981
|
+
|
|
1394
1982
|
// src/flows/plan-summary.ts
|
|
1395
1983
|
import chalk from "chalk";
|
|
1396
1984
|
|
|
1397
1985
|
// src/installer/install.ts
|
|
1398
1986
|
import { access, mkdir as mkdir2, rm as rm4, writeFile } from "fs/promises";
|
|
1399
|
-
import { basename as
|
|
1987
|
+
import { basename as basename5, join as join7 } from "path";
|
|
1400
1988
|
|
|
1401
1989
|
// src/installer/files.ts
|
|
1402
1990
|
import { cp, lstat, mkdir, readdir as readdir2, readlink, rm as rm3, symlink } from "fs/promises";
|
|
@@ -1542,7 +2130,7 @@ async function installSkillForAgent(skill, agentType, options = {}) {
|
|
|
1542
2130
|
error: `Agent ${agent.displayName} does not support global installation`
|
|
1543
2131
|
};
|
|
1544
2132
|
}
|
|
1545
|
-
const rawSkillName = skill.name ||
|
|
2133
|
+
const rawSkillName = skill.name || basename5(skill.path);
|
|
1546
2134
|
const { canonicalBase, canonicalDir, agentBase, agentDir } = getInstallTargets(
|
|
1547
2135
|
rawSkillName,
|
|
1548
2136
|
agentType,
|
|
@@ -2721,41 +3309,26 @@ async function scanSkillsForSecurity(skills, options = {}) {
|
|
|
2721
3309
|
}
|
|
2722
3310
|
|
|
2723
3311
|
// src/tui/controls/SelectMenu.tsx
|
|
2724
|
-
import { Box as
|
|
3312
|
+
import { Box as Box9 } from "ink";
|
|
2725
3313
|
import SelectInput from "ink-select-input";
|
|
2726
3314
|
|
|
2727
3315
|
// src/tui/ui/Divider.tsx
|
|
2728
|
-
import { Box as
|
|
2729
|
-
import { jsx as
|
|
3316
|
+
import { Box as Box7, Text as Text7 } from "ink";
|
|
3317
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
2730
3318
|
function Divider() {
|
|
2731
|
-
return /* @__PURE__ */
|
|
3319
|
+
return /* @__PURE__ */ jsx8(Box7, { children: /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }) });
|
|
2732
3320
|
}
|
|
2733
3321
|
|
|
2734
3322
|
// src/tui/ui/HelpBar.tsx
|
|
2735
|
-
import { Box as
|
|
2736
|
-
|
|
2737
|
-
// src/tui/ui/hints.ts
|
|
2738
|
-
var TEXT_INPUT_HINT = "Ctrl+D to clear, Esc to go back";
|
|
2739
|
-
var MENU_HINT = "Use \u2191\u2193 to navigate, Enter to select, m for main, q/esc to quit";
|
|
2740
|
-
var SINGLE_SELECT_HINT = "Use \u2191\u2193 to navigate, Enter to continue, m for main, q/esc to quit";
|
|
2741
|
-
var MULTI_SELECT_HINT = "Space to toggle, s to select all, Enter to continue, m for main, q/esc to quit";
|
|
2742
|
-
var BACK_QUIT_HINT = "Press \u2190 to go back, q/esc to quit";
|
|
2743
|
-
var FIND_SKILLS_HINT = "Space to select one or more skills, then Enter to install.";
|
|
2744
|
-
var FIND_RESULTS_HINT = "Space to toggle, s to select all, i for info, Enter to install, q/esc to quit";
|
|
2745
|
-
var UPDATE_HINT_NEEDS_ONLY = "Showing needs update only. u to show all, s to select all, m for main, q/esc to quit";
|
|
2746
|
-
var UPDATE_HINT_ALL = "u to show needs update only, s to select all, m for main, q/esc to quit";
|
|
2747
|
-
var UPDATE_EMPTY_HINT = "Press u to show all, m for main, q/esc to quit";
|
|
2748
|
-
var SCAN_SKILLS_HINT = "Use \u2191\u2193 to navigate, i for info, Enter for actions, m for main, q/esc to quit";
|
|
2749
|
-
|
|
2750
|
-
// src/tui/ui/HelpBar.tsx
|
|
2751
|
-
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
3323
|
+
import { Box as Box8, Text as Text8 } from "ink";
|
|
3324
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
2752
3325
|
function HelpBar({ text = MENU_HINT }) {
|
|
2753
|
-
return /* @__PURE__ */
|
|
3326
|
+
return /* @__PURE__ */ jsx9(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: text }) });
|
|
2754
3327
|
}
|
|
2755
3328
|
|
|
2756
3329
|
// src/tui/ui/SelectItem.tsx
|
|
2757
|
-
import { Text as
|
|
2758
|
-
import { jsx as
|
|
3330
|
+
import { Text as Text9 } from "ink";
|
|
3331
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
2759
3332
|
function SelectItem({ label }) {
|
|
2760
3333
|
const l = label.toLowerCase();
|
|
2761
3334
|
let color;
|
|
@@ -2764,11 +3337,11 @@ function SelectItem({ label }) {
|
|
|
2764
3337
|
else if (l.includes("failed \u2717") || l.includes("inactive \u2717")) color = "red";
|
|
2765
3338
|
else if (l.includes("sent \u2713") || l.includes("success \u2713") || l.includes("active \u2713"))
|
|
2766
3339
|
color = "green";
|
|
2767
|
-
return /* @__PURE__ */
|
|
3340
|
+
return /* @__PURE__ */ jsx10(Text9, { color, children: label });
|
|
2768
3341
|
}
|
|
2769
3342
|
|
|
2770
3343
|
// src/tui/controls/SelectMenu.tsx
|
|
2771
|
-
import { jsx as
|
|
3344
|
+
import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2772
3345
|
var SelectInputTyped = SelectInput;
|
|
2773
3346
|
function SelectMenu({
|
|
2774
3347
|
items,
|
|
@@ -2778,9 +3351,9 @@ function SelectMenu({
|
|
|
2778
3351
|
itemComponent = SelectItem,
|
|
2779
3352
|
limit
|
|
2780
3353
|
}) {
|
|
2781
|
-
return /* @__PURE__ */
|
|
2782
|
-
showDivider && /* @__PURE__ */
|
|
2783
|
-
/* @__PURE__ */
|
|
3354
|
+
return /* @__PURE__ */ jsxs7(Box9, { flexDirection: "column", children: [
|
|
3355
|
+
showDivider && /* @__PURE__ */ jsx11(Divider, {}),
|
|
3356
|
+
/* @__PURE__ */ jsx11(
|
|
2784
3357
|
SelectInputTyped,
|
|
2785
3358
|
{
|
|
2786
3359
|
items,
|
|
@@ -2789,17 +3362,17 @@ function SelectMenu({
|
|
|
2789
3362
|
limit
|
|
2790
3363
|
}
|
|
2791
3364
|
),
|
|
2792
|
-
/* @__PURE__ */
|
|
3365
|
+
/* @__PURE__ */ jsx11(HelpBar, { text: hint })
|
|
2793
3366
|
] });
|
|
2794
3367
|
}
|
|
2795
3368
|
|
|
2796
3369
|
// src/tui/hooks/useTextInput.tsx
|
|
2797
|
-
import { useInput } from "ink";
|
|
2798
|
-
import
|
|
3370
|
+
import { useInput as useInput2 } from "ink";
|
|
3371
|
+
import React6 from "react";
|
|
2799
3372
|
function useTextInput({ onClear, disabled = false }) {
|
|
2800
3373
|
const { setTextInputActive, setTextInputEscMode } = useNavigation();
|
|
2801
|
-
const skipNextChangeRef =
|
|
2802
|
-
|
|
3374
|
+
const skipNextChangeRef = React6.useRef(false);
|
|
3375
|
+
React6.useEffect(() => {
|
|
2803
3376
|
if (disabled) {
|
|
2804
3377
|
setTextInputActive(false);
|
|
2805
3378
|
setTextInputEscMode("back");
|
|
@@ -2812,17 +3385,17 @@ function useTextInput({ onClear, disabled = false }) {
|
|
|
2812
3385
|
setTextInputEscMode("back");
|
|
2813
3386
|
};
|
|
2814
3387
|
}, [disabled, setTextInputActive, setTextInputEscMode]);
|
|
2815
|
-
const clearValue =
|
|
3388
|
+
const clearValue = React6.useCallback(() => {
|
|
2816
3389
|
skipNextChangeRef.current = true;
|
|
2817
3390
|
onClear();
|
|
2818
3391
|
}, [onClear]);
|
|
2819
|
-
|
|
3392
|
+
useInput2((input, key) => {
|
|
2820
3393
|
if (disabled) return;
|
|
2821
3394
|
if (key.ctrl && input === "d" || input === "") {
|
|
2822
3395
|
clearValue();
|
|
2823
3396
|
}
|
|
2824
3397
|
});
|
|
2825
|
-
const wrapOnChange =
|
|
3398
|
+
const wrapOnChange = React6.useCallback(
|
|
2826
3399
|
(handler) => (next) => {
|
|
2827
3400
|
if (skipNextChangeRef.current) {
|
|
2828
3401
|
skipNextChangeRef.current = false;
|
|
@@ -2836,66 +3409,16 @@ function useTextInput({ onClear, disabled = false }) {
|
|
|
2836
3409
|
return { wrapOnChange };
|
|
2837
3410
|
}
|
|
2838
3411
|
|
|
2839
|
-
// src/tui/ui/AddFlowHeader.tsx
|
|
2840
|
-
import { Box as Box7, Text as Text7 } from "ink";
|
|
2841
|
-
|
|
2842
|
-
// src/tui/ui/Header.tsx
|
|
2843
|
-
import { Box as Box6, Text as Text6 } from "ink";
|
|
2844
|
-
import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2845
|
-
function Header({ title }) {
|
|
2846
|
-
return /* @__PURE__ */ jsx8(Box6, { marginBottom: 1, children: /* @__PURE__ */ jsx8(Text6, { bold: true, color: "cyan", children: title }) });
|
|
2847
|
-
}
|
|
2848
|
-
|
|
2849
|
-
// src/tui/ui/AddFlowHeader.tsx
|
|
2850
|
-
import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2851
|
-
function AddFlowHeader({ title }) {
|
|
2852
|
-
const { invocation, addSkill } = useNavigation();
|
|
2853
|
-
const source = addSkill.source ?? invocation.source;
|
|
2854
|
-
const cwd = process.cwd();
|
|
2855
|
-
let sourceLabel = source ?? "";
|
|
2856
|
-
if (addSkill.parsed?.type === "local" && addSkill.parsed.localPath) {
|
|
2857
|
-
sourceLabel = shortenPath(addSkill.parsed.localPath, cwd);
|
|
2858
|
-
}
|
|
2859
|
-
const selected = addSkill.selectedSkills;
|
|
2860
|
-
const available = addSkill.skills;
|
|
2861
|
-
let skillsLabel = null;
|
|
2862
|
-
if (selected && selected.length > 0) {
|
|
2863
|
-
skillsLabel = formatList(selected.map(getSkillDisplayName), 3);
|
|
2864
|
-
} else if (available && available.length > 0) {
|
|
2865
|
-
skillsLabel = `${available.length} available`;
|
|
2866
|
-
}
|
|
2867
|
-
return /* @__PURE__ */ jsxs5(Box7, { flexDirection: "column", marginBottom: 1, children: [
|
|
2868
|
-
/* @__PURE__ */ jsx9(Header, { title }),
|
|
2869
|
-
source ? /* @__PURE__ */ jsx9(Text7, { dimColor: true, children: `Source: ${sourceLabel}` }) : null,
|
|
2870
|
-
skillsLabel ? /* @__PURE__ */ jsx9(Text7, { dimColor: true, children: `Skills: ${skillsLabel}` }) : null
|
|
2871
|
-
] });
|
|
2872
|
-
}
|
|
2873
|
-
|
|
2874
|
-
// src/tui/ui/spinner.ts
|
|
2875
|
-
import React4 from "react";
|
|
2876
|
-
var spinnerFrames = ["|", "/", "-", "\\"];
|
|
2877
|
-
function useSpinnerFrame(active = true, interval = 100) {
|
|
2878
|
-
const [index, setIndex] = React4.useState(0);
|
|
2879
|
-
React4.useEffect(() => {
|
|
2880
|
-
if (!active) return void 0;
|
|
2881
|
-
const timer = setInterval(() => {
|
|
2882
|
-
setIndex((prev) => (prev + 1) % spinnerFrames.length);
|
|
2883
|
-
}, interval);
|
|
2884
|
-
return () => clearInterval(timer);
|
|
2885
|
-
}, [active, interval]);
|
|
2886
|
-
return spinnerFrames[index] ?? "|";
|
|
2887
|
-
}
|
|
2888
|
-
|
|
2889
3412
|
// src/tui/screens/add-confirm-security.tsx
|
|
2890
|
-
import { Box as
|
|
3413
|
+
import { Box as Box11, Text as Text11 } from "ink";
|
|
2891
3414
|
import TextInput from "ink-text-input";
|
|
2892
|
-
import
|
|
3415
|
+
import React8 from "react";
|
|
2893
3416
|
|
|
2894
3417
|
// src/tui/controls/SingleSelect.tsx
|
|
2895
|
-
import { Box as
|
|
2896
|
-
import
|
|
2897
|
-
import { jsx as
|
|
2898
|
-
var
|
|
3418
|
+
import { Box as Box10, Text as Text10, useInput as useInput3 } from "ink";
|
|
3419
|
+
import React7 from "react";
|
|
3420
|
+
import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3421
|
+
var FILTER_THRESHOLD2 = 10;
|
|
2899
3422
|
function SingleSelect({
|
|
2900
3423
|
items,
|
|
2901
3424
|
onSubmit,
|
|
@@ -2905,20 +3428,20 @@ function SingleSelect({
|
|
|
2905
3428
|
hintMode = "active",
|
|
2906
3429
|
initialValue
|
|
2907
3430
|
}) {
|
|
2908
|
-
const [cursor, setCursor] =
|
|
3431
|
+
const [cursor, setCursor] = React7.useState(() => {
|
|
2909
3432
|
if (initialValue === void 0) return 0;
|
|
2910
3433
|
const index = items.findIndex((item) => item.value === initialValue);
|
|
2911
3434
|
return index >= 0 ? index : 0;
|
|
2912
3435
|
});
|
|
2913
|
-
const [infoIndex, setInfoIndex] =
|
|
2914
|
-
const [filter, setFilter] =
|
|
2915
|
-
const showFilter = enableFilter ?? items.length >=
|
|
3436
|
+
const [infoIndex, setInfoIndex] = React7.useState(null);
|
|
3437
|
+
const [filter, setFilter] = React7.useState("");
|
|
3438
|
+
const showFilter = enableFilter ?? items.length >= FILTER_THRESHOLD2;
|
|
2916
3439
|
const { setTextInputActive, setTextInputEscMode } = useNavigation();
|
|
2917
|
-
const resetFocus =
|
|
3440
|
+
const resetFocus = React7.useCallback(() => {
|
|
2918
3441
|
setCursor(0);
|
|
2919
3442
|
setInfoIndex(null);
|
|
2920
3443
|
}, []);
|
|
2921
|
-
|
|
3444
|
+
React7.useEffect(() => {
|
|
2922
3445
|
if (!showFilter) return;
|
|
2923
3446
|
setTextInputActive(true);
|
|
2924
3447
|
setTextInputEscMode("back");
|
|
@@ -2927,7 +3450,7 @@ function SingleSelect({
|
|
|
2927
3450
|
setTextInputEscMode("back");
|
|
2928
3451
|
};
|
|
2929
3452
|
}, [showFilter, setTextInputActive, setTextInputEscMode]);
|
|
2930
|
-
const filteredItems =
|
|
3453
|
+
const filteredItems = React7.useMemo(() => {
|
|
2931
3454
|
if (!filter) return items.map((item, index) => ({ item, originalIndex: index }));
|
|
2932
3455
|
const lowerFilter = filter.toLowerCase();
|
|
2933
3456
|
return items.map((item, index) => ({ item, originalIndex: index })).filter(
|
|
@@ -2945,7 +3468,7 @@ function SingleSelect({
|
|
|
2945
3468
|
if (value.length <= max) return value;
|
|
2946
3469
|
return `${value.slice(0, max - 3)}...`;
|
|
2947
3470
|
};
|
|
2948
|
-
|
|
3471
|
+
React7.useEffect(() => {
|
|
2949
3472
|
if (total === 0) {
|
|
2950
3473
|
setCursor(0);
|
|
2951
3474
|
return;
|
|
@@ -2954,7 +3477,7 @@ function SingleSelect({
|
|
|
2954
3477
|
setCursor(total - 1);
|
|
2955
3478
|
}
|
|
2956
3479
|
}, [total, cursor]);
|
|
2957
|
-
|
|
3480
|
+
useInput3((input, key) => {
|
|
2958
3481
|
if (showFilter) {
|
|
2959
3482
|
if (key.backspace || key.delete) {
|
|
2960
3483
|
setFilter((prev) => prev.slice(0, -1));
|
|
@@ -2996,12 +3519,12 @@ function SingleSelect({
|
|
|
2996
3519
|
});
|
|
2997
3520
|
const filterHint = showFilter ? "Type to filter, " : "";
|
|
2998
3521
|
const displayHint = filterHint + hint;
|
|
2999
|
-
return /* @__PURE__ */
|
|
3000
|
-
showFilter && /* @__PURE__ */
|
|
3001
|
-
/* @__PURE__ */
|
|
3002
|
-
/* @__PURE__ */
|
|
3003
|
-
/* @__PURE__ */
|
|
3004
|
-
filter && /* @__PURE__ */
|
|
3522
|
+
return /* @__PURE__ */ jsxs8(Box10, { flexDirection: "column", children: [
|
|
3523
|
+
showFilter && /* @__PURE__ */ jsxs8(Box10, { marginBottom: 1, children: [
|
|
3524
|
+
/* @__PURE__ */ jsx12(Text10, { dimColor: true, children: "Filter: " }),
|
|
3525
|
+
/* @__PURE__ */ jsx12(Text10, { children: filter || " " }),
|
|
3526
|
+
/* @__PURE__ */ jsx12(Text10, { dimColor: true, inverse: true, children: " " }),
|
|
3527
|
+
filter && /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
|
|
3005
3528
|
" ",
|
|
3006
3529
|
"(",
|
|
3007
3530
|
filteredItems.length,
|
|
@@ -3010,35 +3533,35 @@ function SingleSelect({
|
|
|
3010
3533
|
")"
|
|
3011
3534
|
] })
|
|
3012
3535
|
] }),
|
|
3013
|
-
total === 0 ? /* @__PURE__ */
|
|
3536
|
+
total === 0 ? /* @__PURE__ */ jsx12(Text10, { dimColor: true, children: "No matches found" }) : visible.map(({ item, originalIndex }, index) => {
|
|
3014
3537
|
const visibleIndex = windowStart + index;
|
|
3015
3538
|
const isActive = visibleIndex === cursor;
|
|
3016
3539
|
const pointer = isActive ? "\u276F" : " ";
|
|
3017
3540
|
const color = item.disabled ? "gray" : isActive ? "cyan" : void 0;
|
|
3018
3541
|
const showHint = hintMode === "all" || hintMode === "active" && isActive;
|
|
3019
|
-
return /* @__PURE__ */
|
|
3020
|
-
/* @__PURE__ */
|
|
3542
|
+
return /* @__PURE__ */ jsxs8(Box10, { flexDirection: "column", children: [
|
|
3543
|
+
/* @__PURE__ */ jsxs8(Text10, { color, children: [
|
|
3021
3544
|
pointer,
|
|
3022
3545
|
" ",
|
|
3023
3546
|
item.label
|
|
3024
3547
|
] }),
|
|
3025
|
-
infoIndex === visibleIndex && item.info ? /* @__PURE__ */
|
|
3548
|
+
infoIndex === visibleIndex && item.info ? /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
|
|
3026
3549
|
" ",
|
|
3027
3550
|
" ",
|
|
3028
3551
|
truncate(item.info)
|
|
3029
|
-
] }) : item.hint && showHint ? /* @__PURE__ */
|
|
3552
|
+
] }) : item.hint && showHint ? /* @__PURE__ */ jsxs8(Text10, { dimColor: true, children: [
|
|
3030
3553
|
" ",
|
|
3031
3554
|
" ",
|
|
3032
3555
|
item.hint
|
|
3033
3556
|
] }) : null
|
|
3034
3557
|
] }, `${item.label}-${originalIndex}`);
|
|
3035
3558
|
}),
|
|
3036
|
-
/* @__PURE__ */
|
|
3559
|
+
/* @__PURE__ */ jsx12(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx12(Text10, { dimColor: true, children: displayHint }) })
|
|
3037
3560
|
] });
|
|
3038
3561
|
}
|
|
3039
3562
|
|
|
3040
3563
|
// src/tui/screens/add-confirm-security.tsx
|
|
3041
|
-
import { Fragment, jsx as
|
|
3564
|
+
import { Fragment, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3042
3565
|
function formatSignalsBrief(signals) {
|
|
3043
3566
|
if (signals.length === 0) return "None";
|
|
3044
3567
|
const uniq = Array.from(new Set(signals.map((s) => s.id)));
|
|
@@ -3068,11 +3591,11 @@ function ManualSecurityGate({
|
|
|
3068
3591
|
onInstall,
|
|
3069
3592
|
onCancel
|
|
3070
3593
|
}) {
|
|
3071
|
-
const riskyScanRows =
|
|
3594
|
+
const riskyScanRows = React8.useMemo(() => getRiskyScanRows(scanRows), [scanRows]);
|
|
3072
3595
|
if (manualView === "details") {
|
|
3073
|
-
return /* @__PURE__ */
|
|
3074
|
-
/* @__PURE__ */
|
|
3075
|
-
/* @__PURE__ */
|
|
3596
|
+
return /* @__PURE__ */ jsxs9(Box11, { flexDirection: "column", children: [
|
|
3597
|
+
/* @__PURE__ */ jsx13(Text11, { dimColor: true, children: "Skills with scan findings:" }),
|
|
3598
|
+
/* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: riskyScanRows.length === 0 ? /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: "None." }) : /* @__PURE__ */ jsx13(
|
|
3076
3599
|
SingleSelect,
|
|
3077
3600
|
{
|
|
3078
3601
|
items: riskyScanRows.map((row) => ({
|
|
@@ -3093,49 +3616,49 @@ function ManualSecurityGate({
|
|
|
3093
3616
|
}
|
|
3094
3617
|
if (manualView === "detail-skill" && selectedRow) {
|
|
3095
3618
|
const riskColor = selectedRow.level === "critical" || selectedRow.level === "high" ? "red" : selectedRow.level === "medium" ? "yellow" : selectedRow.level === "low" ? "green" : "gray";
|
|
3096
|
-
return /* @__PURE__ */
|
|
3097
|
-
/* @__PURE__ */
|
|
3098
|
-
selectedRow.error ? /* @__PURE__ */
|
|
3099
|
-
/* @__PURE__ */
|
|
3100
|
-
/* @__PURE__ */
|
|
3619
|
+
return /* @__PURE__ */ jsxs9(Box11, { flexDirection: "column", children: [
|
|
3620
|
+
/* @__PURE__ */ jsx13(Text11, { children: /* @__PURE__ */ jsx13(Text11, { bold: true, children: selectedRow.name }) }),
|
|
3621
|
+
selectedRow.error ? /* @__PURE__ */ jsx13(Text11, { color: "red", children: selectedRow.error }) : /* @__PURE__ */ jsxs9(Fragment, { children: [
|
|
3622
|
+
/* @__PURE__ */ jsxs9(Text11, { children: [
|
|
3623
|
+
/* @__PURE__ */ jsx13(Text11, { dimColor: true, children: "Verdict:" }),
|
|
3101
3624
|
" ",
|
|
3102
|
-
/* @__PURE__ */
|
|
3103
|
-
/* @__PURE__ */
|
|
3104
|
-
|
|
3625
|
+
/* @__PURE__ */ jsx13(Text11, { color: riskColor, children: selectedRow.verdict }),
|
|
3626
|
+
/* @__PURE__ */ jsx13(
|
|
3627
|
+
Text11,
|
|
3105
3628
|
{
|
|
3106
3629
|
dimColor: true,
|
|
3107
3630
|
children: ` \u2022 level=${selectedRow.level} score=${selectedRow.score} issues=${selectedRow.signals.length}`
|
|
3108
3631
|
}
|
|
3109
3632
|
)
|
|
3110
3633
|
] }),
|
|
3111
|
-
/* @__PURE__ */
|
|
3112
|
-
/* @__PURE__ */
|
|
3113
|
-
selectedRow.truncated ? /* @__PURE__ */
|
|
3634
|
+
/* @__PURE__ */ jsx13(Text11, { dimColor: true, children: `Top signals: ${formatSignalsBrief(selectedRow.signals)}` }),
|
|
3635
|
+
/* @__PURE__ */ jsx13(Text11, { dimColor: true, children: `Ruleset: ${selectedRow.ruleset}` }),
|
|
3636
|
+
selectedRow.truncated ? /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: "Note: scan was truncated due to file/byte/signal limits." }) : null
|
|
3114
3637
|
] }),
|
|
3115
|
-
/* @__PURE__ */
|
|
3116
|
-
!selectedRow.error && selectedRow.signals.length > 0 ? /* @__PURE__ */
|
|
3117
|
-
/* @__PURE__ */
|
|
3118
|
-
selectedRow.signals.slice(0, 12).map((sig, idx) => /* @__PURE__ */
|
|
3638
|
+
/* @__PURE__ */ jsx13(Text11, { dimColor: true, children: `Path: ${selectedRow.path}` }),
|
|
3639
|
+
!selectedRow.error && selectedRow.signals.length > 0 ? /* @__PURE__ */ jsxs9(Box11, { flexDirection: "column", marginTop: 1, children: [
|
|
3640
|
+
/* @__PURE__ */ jsx13(Text11, { dimColor: true, children: `Findings (${selectedRow.signals.length}):` }),
|
|
3641
|
+
selectedRow.signals.slice(0, 12).map((sig, idx) => /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
|
|
3119
3642
|
"\u2022 ",
|
|
3120
3643
|
" ",
|
|
3121
3644
|
formatFindingLine(sig)
|
|
3122
3645
|
] }, `${sig.id}-${idx}`)),
|
|
3123
|
-
selectedRow.signals.length > 12 ? /* @__PURE__ */
|
|
3646
|
+
selectedRow.signals.length > 12 ? /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: `\u2026 ${selectedRow.signals.length - 12} more` }) : null
|
|
3124
3647
|
] }) : null,
|
|
3125
|
-
/* @__PURE__ */
|
|
3648
|
+
/* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
3126
3649
|
] });
|
|
3127
3650
|
}
|
|
3128
3651
|
if (manualView === "type-confirm") {
|
|
3129
|
-
return /* @__PURE__ */
|
|
3130
|
-
/* @__PURE__ */
|
|
3131
|
-
/* @__PURE__ */
|
|
3652
|
+
return /* @__PURE__ */ jsxs9(Box11, { flexDirection: "column", children: [
|
|
3653
|
+
/* @__PURE__ */ jsx13(Text11, { color: "red", children: "High risk patterns detected." }),
|
|
3654
|
+
/* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
|
|
3132
3655
|
"If you still want to proceed, type ",
|
|
3133
|
-
/* @__PURE__ */
|
|
3656
|
+
/* @__PURE__ */ jsx13(Text11, { bold: true, children: "install" }),
|
|
3134
3657
|
" and press Enter."
|
|
3135
3658
|
] }),
|
|
3136
|
-
/* @__PURE__ */
|
|
3137
|
-
/* @__PURE__ */
|
|
3138
|
-
/* @__PURE__ */
|
|
3659
|
+
/* @__PURE__ */ jsxs9(Box11, { marginTop: 1, children: [
|
|
3660
|
+
/* @__PURE__ */ jsx13(Text11, { color: "green", children: "> " }),
|
|
3661
|
+
/* @__PURE__ */ jsx13(
|
|
3139
3662
|
TextInput,
|
|
3140
3663
|
{
|
|
3141
3664
|
value: confirmText,
|
|
@@ -3152,22 +3675,22 @@ function ManualSecurityGate({
|
|
|
3152
3675
|
}
|
|
3153
3676
|
)
|
|
3154
3677
|
] }),
|
|
3155
|
-
/* @__PURE__ */
|
|
3678
|
+
/* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: TEXT_INPUT_HINT }) })
|
|
3156
3679
|
] });
|
|
3157
3680
|
}
|
|
3158
|
-
return /* @__PURE__ */
|
|
3159
|
-
/* @__PURE__ */
|
|
3160
|
-
/* @__PURE__ */
|
|
3681
|
+
return /* @__PURE__ */ jsxs9(Box11, { flexDirection: "column", children: [
|
|
3682
|
+
/* @__PURE__ */ jsx13(Text11, { color: "red", children: "High risk patterns detected." }),
|
|
3683
|
+
/* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
|
|
3161
3684
|
"Review the scan summary below (or open scan details). If you proceed, you will need to type",
|
|
3162
3685
|
" ",
|
|
3163
|
-
/* @__PURE__ */
|
|
3686
|
+
/* @__PURE__ */ jsx13(Text11, { bold: true, children: "install" }),
|
|
3164
3687
|
"."
|
|
3165
3688
|
] }),
|
|
3166
|
-
/* @__PURE__ */
|
|
3689
|
+
/* @__PURE__ */ jsx13(Box11, { flexDirection: "column", marginTop: 1, children: riskyScanRows.slice(0, 6).map((row) => {
|
|
3167
3690
|
const level = row.level ?? "none";
|
|
3168
3691
|
const top = row.error ? "" : ` top=${formatSignalsBrief(row.signals)}`;
|
|
3169
3692
|
const suffix = row.error ? ` scan failed: ${row.error}` : ` score=${row.score} issues=${row.signals.length}${top}`;
|
|
3170
|
-
return /* @__PURE__ */
|
|
3693
|
+
return /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
|
|
3171
3694
|
"\u2022",
|
|
3172
3695
|
" ",
|
|
3173
3696
|
row.name,
|
|
@@ -3176,7 +3699,7 @@ function ManualSecurityGate({
|
|
|
3176
3699
|
suffix
|
|
3177
3700
|
] }, row.path);
|
|
3178
3701
|
}) }),
|
|
3179
|
-
/* @__PURE__ */
|
|
3702
|
+
/* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(
|
|
3180
3703
|
SelectMenu,
|
|
3181
3704
|
{
|
|
3182
3705
|
items: [
|
|
@@ -3203,7 +3726,7 @@ function ManualSecurityGate({
|
|
|
3203
3726
|
}
|
|
3204
3727
|
|
|
3205
3728
|
// src/tui/screens/AddConfirm.tsx
|
|
3206
|
-
import { jsx as
|
|
3729
|
+
import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
3207
3730
|
function AddConfirmScreen() {
|
|
3208
3731
|
const {
|
|
3209
3732
|
invocation,
|
|
@@ -3216,13 +3739,13 @@ function AddConfirmScreen() {
|
|
|
3216
3739
|
setBackHandler
|
|
3217
3740
|
} = useNavigation();
|
|
3218
3741
|
const options = invocation.options;
|
|
3219
|
-
const [lines, setLines] =
|
|
3220
|
-
const [scanStatus, setScanStatus] =
|
|
3221
|
-
const [requiresManual, setRequiresManual] =
|
|
3222
|
-
const [confirmText, setConfirmText] =
|
|
3223
|
-
const [scanRows, setScanRows] =
|
|
3224
|
-
const [manualView, setManualView] =
|
|
3225
|
-
const [selectedRow, setSelectedRow] =
|
|
3742
|
+
const [lines, setLines] = React9.useState([]);
|
|
3743
|
+
const [scanStatus, setScanStatus] = React9.useState("idle");
|
|
3744
|
+
const [requiresManual, setRequiresManual] = React9.useState(false);
|
|
3745
|
+
const [confirmText, setConfirmText] = React9.useState("");
|
|
3746
|
+
const [scanRows, setScanRows] = React9.useState([]);
|
|
3747
|
+
const [manualView, setManualView] = React9.useState("menu");
|
|
3748
|
+
const [selectedRow, setSelectedRow] = React9.useState(null);
|
|
3226
3749
|
const spinner = useSpinnerFrame(scanStatus === "scanning");
|
|
3227
3750
|
const { wrapOnChange } = useTextInput({
|
|
3228
3751
|
onClear: () => {
|
|
@@ -3230,7 +3753,7 @@ function AddConfirmScreen() {
|
|
|
3230
3753
|
},
|
|
3231
3754
|
disabled: !requiresManual || manualView !== "type-confirm"
|
|
3232
3755
|
});
|
|
3233
|
-
|
|
3756
|
+
React9.useEffect(() => {
|
|
3234
3757
|
const selectedSkills = addSkill.selectedSkills;
|
|
3235
3758
|
const targetAgents2 = addSkill.targetAgents;
|
|
3236
3759
|
const installGlobally = addSkill.installGlobally;
|
|
@@ -3301,7 +3824,7 @@ function AddConfirmScreen() {
|
|
|
3301
3824
|
navigateTo,
|
|
3302
3825
|
setFlash
|
|
3303
3826
|
]);
|
|
3304
|
-
|
|
3827
|
+
React9.useEffect(() => {
|
|
3305
3828
|
if (!requiresManual) {
|
|
3306
3829
|
setBackHandler(null);
|
|
3307
3830
|
return () => setBackHandler(null);
|
|
@@ -3332,7 +3855,7 @@ function AddConfirmScreen() {
|
|
|
3332
3855
|
const canonicalBase = getCanonicalSkillsBase({ global: addSkill.installGlobally, cwd });
|
|
3333
3856
|
const canonicalLabel = shortenPath(canonicalBase, cwd);
|
|
3334
3857
|
const targetAgents = addSkill.targetAgents ?? [];
|
|
3335
|
-
const keyedLines =
|
|
3858
|
+
const keyedLines = React9.useMemo(() => {
|
|
3336
3859
|
const counts = /* @__PURE__ */ new Map();
|
|
3337
3860
|
return lines.map((line) => {
|
|
3338
3861
|
const count = (counts.get(line) ?? 0) + 1;
|
|
@@ -3349,21 +3872,21 @@ function AddConfirmScreen() {
|
|
|
3349
3872
|
}).filter((p) => p !== null)
|
|
3350
3873
|
)
|
|
3351
3874
|
) : [];
|
|
3352
|
-
return /* @__PURE__ */
|
|
3353
|
-
/* @__PURE__ */
|
|
3354
|
-
/* @__PURE__ */
|
|
3355
|
-
/* @__PURE__ */
|
|
3356
|
-
addSkill.targetAgents ? /* @__PURE__ */
|
|
3357
|
-
addSkill.installGlobally !== void 0 ? /* @__PURE__ */
|
|
3358
|
-
addSkill.installMode ? /* @__PURE__ */
|
|
3359
|
-
addSkill.installMode === "symlink" ? /* @__PURE__ */
|
|
3360
|
-
addSkill.installMode === "copy" && agentPaths.length > 0 ? /* @__PURE__ */
|
|
3875
|
+
return /* @__PURE__ */ jsxs10(Box12, { flexDirection: "column", padding: 1, children: [
|
|
3876
|
+
/* @__PURE__ */ jsx14(AddFlowHeader, { title: "Review plan" }),
|
|
3877
|
+
/* @__PURE__ */ jsxs10(Box12, { flexDirection: "column", marginBottom: 1, children: [
|
|
3878
|
+
/* @__PURE__ */ jsx14(Text12, { children: `Skills: ${skillsCount} \u2022 Agents: ${agentsCount}` }),
|
|
3879
|
+
addSkill.targetAgents ? /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: `Targets: ${formatList(addSkill.targetAgents.map((agent) => agents[agent].displayName))}` }) : null,
|
|
3880
|
+
addSkill.installGlobally !== void 0 ? /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: `Scope: ${scopeLabel}` }) : null,
|
|
3881
|
+
addSkill.installMode ? /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: `Mode: ${installModeLabel}` }) : null,
|
|
3882
|
+
addSkill.installMode === "symlink" ? /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: `Canonical base: ${canonicalLabel}` }) : null,
|
|
3883
|
+
addSkill.installMode === "copy" && agentPaths.length > 0 ? /* @__PURE__ */ jsx14(Text12, { dimColor: true, children: `Agent dirs: ${formatList(agentPaths, 3)}` }) : null
|
|
3361
3884
|
] }),
|
|
3362
|
-
keyedLines.map(({ line, key }) => /* @__PURE__ */
|
|
3363
|
-
/* @__PURE__ */
|
|
3885
|
+
keyedLines.map(({ line, key }) => /* @__PURE__ */ jsx14(Text12, { children: line }, key)),
|
|
3886
|
+
/* @__PURE__ */ jsx14(Box12, { marginTop: 1, children: scanStatus === "scanning" ? /* @__PURE__ */ jsxs10(Text12, { dimColor: true, children: [
|
|
3364
3887
|
spinner,
|
|
3365
3888
|
" Scanning skills for suspicious patterns..."
|
|
3366
|
-
] }) : requiresManual ? /* @__PURE__ */
|
|
3889
|
+
] }) : requiresManual ? /* @__PURE__ */ jsx14(
|
|
3367
3890
|
ManualSecurityGate,
|
|
3368
3891
|
{
|
|
3369
3892
|
scanRows,
|
|
@@ -3378,7 +3901,7 @@ function AddConfirmScreen() {
|
|
|
3378
3901
|
onInstall: () => navigateTo("add-install"),
|
|
3379
3902
|
onCancel: () => resetTo("main")
|
|
3380
3903
|
}
|
|
3381
|
-
) : /* @__PURE__ */
|
|
3904
|
+
) : /* @__PURE__ */ jsx14(
|
|
3382
3905
|
SelectMenu,
|
|
3383
3906
|
{
|
|
3384
3907
|
items: [
|
|
@@ -3399,12 +3922,12 @@ function AddConfirmScreen() {
|
|
|
3399
3922
|
}
|
|
3400
3923
|
|
|
3401
3924
|
// src/tui/screens/AddDocs.tsx
|
|
3402
|
-
import { Box as
|
|
3403
|
-
import
|
|
3925
|
+
import { Box as Box13, Text as Text13, useInput as useInput4 } from "ink";
|
|
3926
|
+
import React10 from "react";
|
|
3404
3927
|
|
|
3405
3928
|
// src/docs/install.ts
|
|
3406
3929
|
import { mkdir as mkdir3, stat as stat3 } from "fs/promises";
|
|
3407
|
-
import { basename as
|
|
3930
|
+
import { basename as basename6 } from "path";
|
|
3408
3931
|
|
|
3409
3932
|
// src/docs/paths.ts
|
|
3410
3933
|
import { join as join10 } from "path";
|
|
@@ -3449,7 +3972,7 @@ async function installDocs(sources, cwd = process.cwd()) {
|
|
|
3449
3972
|
const docsBase = getDocsBase(cwd);
|
|
3450
3973
|
await mkdir3(docsBase, { recursive: true });
|
|
3451
3974
|
for (const source of sources) {
|
|
3452
|
-
const slug = sanitizeDocName(source.name ||
|
|
3975
|
+
const slug = sanitizeDocName(source.name || basename6(source.url));
|
|
3453
3976
|
const targetPath = getDocPath(slug, cwd);
|
|
3454
3977
|
if (!isPathSafe(docsBase, targetPath)) {
|
|
3455
3978
|
results.push({
|
|
@@ -3704,226 +4227,24 @@ function normalizeStringArray(value) {
|
|
|
3704
4227
|
return filtered.length > 0 ? filtered : void 0;
|
|
3705
4228
|
}
|
|
3706
4229
|
|
|
3707
|
-
// src/tui/controls/MultiSelect.tsx
|
|
3708
|
-
import { Box as Box11, Text as Text11, useInput as useInput3 } from "ink";
|
|
3709
|
-
import React8 from "react";
|
|
3710
|
-
import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3711
|
-
var FILTER_THRESHOLD2 = 10;
|
|
3712
|
-
function MultiSelect({
|
|
3713
|
-
items,
|
|
3714
|
-
initialSelected = [],
|
|
3715
|
-
onSubmit,
|
|
3716
|
-
limit = 10,
|
|
3717
|
-
hint = MULTI_SELECT_HINT,
|
|
3718
|
-
enableFilter,
|
|
3719
|
-
lockedSection,
|
|
3720
|
-
hintMode = "all",
|
|
3721
|
-
onSelectionChange
|
|
3722
|
-
}) {
|
|
3723
|
-
const [cursor, setCursor] = React8.useState(0);
|
|
3724
|
-
const [infoIndex, setInfoIndex] = React8.useState(null);
|
|
3725
|
-
const [filter, setFilter] = React8.useState("");
|
|
3726
|
-
const [selected, setSelected] = React8.useState(
|
|
3727
|
-
new Set(
|
|
3728
|
-
initialSelected.length > 0 ? items.map((item, index) => ({ item, index })).filter(({ item }) => initialSelected.includes(item.value)).map(({ index }) => index) : []
|
|
3729
|
-
)
|
|
3730
|
-
);
|
|
3731
|
-
const showFilter = enableFilter ?? items.length >= FILTER_THRESHOLD2;
|
|
3732
|
-
const { setTextInputActive, setTextInputEscMode } = useNavigation();
|
|
3733
|
-
const resetFocus = React8.useCallback(() => {
|
|
3734
|
-
setCursor(0);
|
|
3735
|
-
setInfoIndex(null);
|
|
3736
|
-
}, []);
|
|
3737
|
-
React8.useEffect(() => {
|
|
3738
|
-
if (!showFilter) return;
|
|
3739
|
-
setTextInputActive(true);
|
|
3740
|
-
setTextInputEscMode("back");
|
|
3741
|
-
return () => {
|
|
3742
|
-
setTextInputActive(false);
|
|
3743
|
-
setTextInputEscMode("back");
|
|
3744
|
-
};
|
|
3745
|
-
}, [showFilter, setTextInputActive, setTextInputEscMode]);
|
|
3746
|
-
const filteredItems = React8.useMemo(() => {
|
|
3747
|
-
if (!filter) return items.map((item, index) => ({ item, originalIndex: index }));
|
|
3748
|
-
const lowerFilter = filter.toLowerCase();
|
|
3749
|
-
return items.map((item, index) => ({ item, originalIndex: index })).filter(
|
|
3750
|
-
({ item }) => item.label.toLowerCase().includes(lowerFilter) || String(item.value).toLowerCase().includes(lowerFilter)
|
|
3751
|
-
);
|
|
3752
|
-
}, [items, filter]);
|
|
3753
|
-
const total = filteredItems.length;
|
|
3754
|
-
const maxItems = Math.max(5, Math.min(limit, total));
|
|
3755
|
-
const windowStart = Math.min(
|
|
3756
|
-
Math.max(0, cursor - Math.floor(maxItems / 2)),
|
|
3757
|
-
Math.max(0, total - maxItems)
|
|
3758
|
-
);
|
|
3759
|
-
const visible = filteredItems.slice(windowStart, windowStart + maxItems);
|
|
3760
|
-
const truncate = (value, max = 100) => {
|
|
3761
|
-
if (value.length <= max) return value;
|
|
3762
|
-
return `${value.slice(0, max - 3)}...`;
|
|
3763
|
-
};
|
|
3764
|
-
const getSelectedValues = React8.useCallback(
|
|
3765
|
-
(nextSelected) => {
|
|
3766
|
-
const lockedValues = lockedSection ? lockedSection.items.map((i) => i.value) : [];
|
|
3767
|
-
const selectedValues = Array.from(nextSelected).map((index) => items[index]?.value).filter((value) => value !== void 0);
|
|
3768
|
-
return [...lockedValues, ...selectedValues];
|
|
3769
|
-
},
|
|
3770
|
-
[items, lockedSection]
|
|
3771
|
-
);
|
|
3772
|
-
useInput3((input, key) => {
|
|
3773
|
-
if (showFilter) {
|
|
3774
|
-
if (key.backspace || key.delete) {
|
|
3775
|
-
setFilter((prev) => prev.slice(0, -1));
|
|
3776
|
-
resetFocus();
|
|
3777
|
-
return;
|
|
3778
|
-
}
|
|
3779
|
-
if (input && input.length === 1 && !key.ctrl && !key.meta && !key.return && !key.tab && input !== " " && input !== "s" && input !== "S" && input !== "i" && input !== "I") {
|
|
3780
|
-
setFilter((prev) => prev + input);
|
|
3781
|
-
resetFocus();
|
|
3782
|
-
return;
|
|
3783
|
-
}
|
|
3784
|
-
}
|
|
3785
|
-
if (key.downArrow) {
|
|
3786
|
-
setCursor((prev) => {
|
|
3787
|
-
if (total === 0) return 0;
|
|
3788
|
-
const next = (prev + 1) % total;
|
|
3789
|
-
if (infoIndex !== null) {
|
|
3790
|
-
setInfoIndex(null);
|
|
3791
|
-
}
|
|
3792
|
-
return next;
|
|
3793
|
-
});
|
|
3794
|
-
} else if (key.upArrow) {
|
|
3795
|
-
setCursor((prev) => {
|
|
3796
|
-
if (total === 0) return 0;
|
|
3797
|
-
const next = (prev - 1 + total) % total;
|
|
3798
|
-
if (infoIndex !== null) {
|
|
3799
|
-
setInfoIndex(null);
|
|
3800
|
-
}
|
|
3801
|
-
return next;
|
|
3802
|
-
});
|
|
3803
|
-
} else if (input === " ") {
|
|
3804
|
-
if (total === 0) return;
|
|
3805
|
-
const currentFiltered = filteredItems[cursor];
|
|
3806
|
-
if (!currentFiltered) return;
|
|
3807
|
-
if (currentFiltered.item.disabled) return;
|
|
3808
|
-
const originalIndex = currentFiltered.originalIndex;
|
|
3809
|
-
setSelected((prev) => {
|
|
3810
|
-
const next = new Set(prev);
|
|
3811
|
-
if (next.has(originalIndex)) next.delete(originalIndex);
|
|
3812
|
-
else next.add(originalIndex);
|
|
3813
|
-
if (onSelectionChange) {
|
|
3814
|
-
onSelectionChange(getSelectedValues(next));
|
|
3815
|
-
}
|
|
3816
|
-
return next;
|
|
3817
|
-
});
|
|
3818
|
-
} else if (input === "s" || input === "S") {
|
|
3819
|
-
const selectableIndices = filteredItems.filter(({ item }) => !item.disabled).map(({ originalIndex }) => originalIndex);
|
|
3820
|
-
setSelected((prev) => {
|
|
3821
|
-
const allSelected = selectableIndices.length > 0 && selectableIndices.every((index) => prev.has(index));
|
|
3822
|
-
if (allSelected) {
|
|
3823
|
-
const next2 = new Set(prev);
|
|
3824
|
-
for (const index of selectableIndices) {
|
|
3825
|
-
next2.delete(index);
|
|
3826
|
-
}
|
|
3827
|
-
if (onSelectionChange) {
|
|
3828
|
-
onSelectionChange(getSelectedValues(next2));
|
|
3829
|
-
}
|
|
3830
|
-
return next2;
|
|
3831
|
-
}
|
|
3832
|
-
const next = new Set(prev);
|
|
3833
|
-
for (const index of selectableIndices) {
|
|
3834
|
-
next.add(index);
|
|
3835
|
-
}
|
|
3836
|
-
if (onSelectionChange) {
|
|
3837
|
-
onSelectionChange(getSelectedValues(next));
|
|
3838
|
-
}
|
|
3839
|
-
return next;
|
|
3840
|
-
});
|
|
3841
|
-
} else if (input === "i" || input === "I") {
|
|
3842
|
-
setInfoIndex((prev) => prev === cursor ? null : cursor);
|
|
3843
|
-
} else if (key.return) {
|
|
3844
|
-
const lockedValues = lockedSection ? lockedSection.items.map((i) => i.value) : [];
|
|
3845
|
-
const selectedValues = Array.from(selected).map((index) => items[index]?.value).filter((value) => value !== void 0);
|
|
3846
|
-
onSubmit([...lockedValues, ...selectedValues]);
|
|
3847
|
-
}
|
|
3848
|
-
});
|
|
3849
|
-
const filterHint = showFilter ? "Type to filter, " : "";
|
|
3850
|
-
const displayHint = filterHint + hint;
|
|
3851
|
-
return /* @__PURE__ */ jsxs9(Box11, { flexDirection: "column", children: [
|
|
3852
|
-
lockedSection && lockedSection.items.length > 0 && /* @__PURE__ */ jsxs9(Box11, { flexDirection: "column", marginBottom: 1, children: [
|
|
3853
|
-
/* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
|
|
3854
|
-
"\u2500\u2500 ",
|
|
3855
|
-
lockedSection.title,
|
|
3856
|
-
" \u2500\u2500"
|
|
3857
|
-
] }),
|
|
3858
|
-
lockedSection.items.map((item) => /* @__PURE__ */ jsxs9(Text11, { color: "green", children: [
|
|
3859
|
-
" ",
|
|
3860
|
-
"\u2713 ",
|
|
3861
|
-
item.label
|
|
3862
|
-
] }, String(item.value)))
|
|
3863
|
-
] }),
|
|
3864
|
-
lockedSection && items.length > 0 && /* @__PURE__ */ jsx13(Box11, { marginBottom: 0, children: /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: "\u2500\u2500 Other agents \u2500\u2500" }) }),
|
|
3865
|
-
showFilter && /* @__PURE__ */ jsxs9(Box11, { marginBottom: 1, marginTop: lockedSection ? 1 : 0, children: [
|
|
3866
|
-
/* @__PURE__ */ jsx13(Text11, { dimColor: true, children: "Filter: " }),
|
|
3867
|
-
/* @__PURE__ */ jsx13(Text11, { children: filter || " " }),
|
|
3868
|
-
/* @__PURE__ */ jsx13(Text11, { dimColor: true, inverse: true, children: " " }),
|
|
3869
|
-
filter && /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
|
|
3870
|
-
" ",
|
|
3871
|
-
"(",
|
|
3872
|
-
filteredItems.length,
|
|
3873
|
-
"/",
|
|
3874
|
-
items.length,
|
|
3875
|
-
")"
|
|
3876
|
-
] })
|
|
3877
|
-
] }),
|
|
3878
|
-
total === 0 ? /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: "No matches found" }) : visible.map(({ item, originalIndex }, index) => {
|
|
3879
|
-
const visibleIndex = windowStart + index;
|
|
3880
|
-
const isActive = visibleIndex === cursor;
|
|
3881
|
-
const isSelected = selected.has(originalIndex);
|
|
3882
|
-
const marker = isSelected ? "\u25FC" : "\u25FB";
|
|
3883
|
-
const pointer = isActive ? "\u276F" : " ";
|
|
3884
|
-
const color = item.disabled ? "gray" : isActive ? "cyan" : void 0;
|
|
3885
|
-
const showHint = hintMode === "all" || hintMode === "active" && isActive;
|
|
3886
|
-
return /* @__PURE__ */ jsxs9(Box11, { flexDirection: "column", children: [
|
|
3887
|
-
/* @__PURE__ */ jsxs9(Text11, { color, children: [
|
|
3888
|
-
pointer,
|
|
3889
|
-
" ",
|
|
3890
|
-
marker,
|
|
3891
|
-
" ",
|
|
3892
|
-
item.label
|
|
3893
|
-
] }),
|
|
3894
|
-
infoIndex === visibleIndex && item.info ? /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
|
|
3895
|
-
" ",
|
|
3896
|
-
" ",
|
|
3897
|
-
truncate(item.info)
|
|
3898
|
-
] }) : item.hint && showHint ? /* @__PURE__ */ jsxs9(Text11, { dimColor: true, children: [
|
|
3899
|
-
" ",
|
|
3900
|
-
" ",
|
|
3901
|
-
item.hint
|
|
3902
|
-
] }) : null
|
|
3903
|
-
] }, `${item.label}-${originalIndex}`);
|
|
3904
|
-
}),
|
|
3905
|
-
/* @__PURE__ */ jsx13(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text11, { dimColor: true, children: displayHint }) })
|
|
3906
|
-
] });
|
|
3907
|
-
}
|
|
3908
|
-
|
|
3909
4230
|
// src/tui/screens/AddDocs.tsx
|
|
3910
|
-
import { jsx as
|
|
4231
|
+
import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
3911
4232
|
var DOCS_HINT = "Space to toggle, Enter to install, m for main, q/esc to quit";
|
|
3912
4233
|
var REF_HINT = "Enter to select, Ctrl+P to toggle prerelease, m for main, q/esc to quit";
|
|
3913
4234
|
function AddDocsScreen() {
|
|
3914
4235
|
const { navigateTo, setFlash, setBackHandler } = useNavigation();
|
|
3915
|
-
const sources =
|
|
3916
|
-
const [status, setStatus] =
|
|
3917
|
-
const [selected, setSelected] =
|
|
3918
|
-
const [results, setResults] =
|
|
3919
|
-
const [notice, setNotice] =
|
|
3920
|
-
const [pendingSources, setPendingSources] =
|
|
3921
|
-
const [currentIndex, setCurrentIndex] =
|
|
3922
|
-
const [repoRefs, setRepoRefs] =
|
|
3923
|
-
const [refStatus, setRefStatus] =
|
|
3924
|
-
const [refError, setRefError] =
|
|
3925
|
-
const [refSelections, setRefSelections] =
|
|
3926
|
-
const [includePrerelease, setIncludePrerelease] =
|
|
4236
|
+
const sources = React10.useMemo(() => getDocSources(), []);
|
|
4237
|
+
const [status, setStatus] = React10.useState(sources.length === 0 ? "empty" : "select");
|
|
4238
|
+
const [selected, setSelected] = React10.useState([]);
|
|
4239
|
+
const [results, setResults] = React10.useState(null);
|
|
4240
|
+
const [notice, setNotice] = React10.useState(null);
|
|
4241
|
+
const [pendingSources, setPendingSources] = React10.useState([]);
|
|
4242
|
+
const [currentIndex, setCurrentIndex] = React10.useState(0);
|
|
4243
|
+
const [repoRefs, setRepoRefs] = React10.useState(null);
|
|
4244
|
+
const [refStatus, setRefStatus] = React10.useState("idle");
|
|
4245
|
+
const [refError, setRefError] = React10.useState(null);
|
|
4246
|
+
const [refSelections, setRefSelections] = React10.useState(/* @__PURE__ */ new Map());
|
|
4247
|
+
const [includePrerelease, setIncludePrerelease] = React10.useState(false);
|
|
3927
4248
|
const spinner = useSpinnerFrame(status === "installing" || refStatus === "loading");
|
|
3928
4249
|
useInput4((input, key) => {
|
|
3929
4250
|
if (status !== "choose-ref") return;
|
|
@@ -3931,7 +4252,7 @@ function AddDocsScreen() {
|
|
|
3931
4252
|
setIncludePrerelease((prev) => !prev);
|
|
3932
4253
|
}
|
|
3933
4254
|
});
|
|
3934
|
-
|
|
4255
|
+
React10.useEffect(() => {
|
|
3935
4256
|
let cancelled = false;
|
|
3936
4257
|
const run = async () => {
|
|
3937
4258
|
if (status !== "installing" || selected.length === 0) return;
|
|
@@ -3952,7 +4273,7 @@ function AddDocsScreen() {
|
|
|
3952
4273
|
cancelled = true;
|
|
3953
4274
|
};
|
|
3954
4275
|
}, [status, selected, setFlash]);
|
|
3955
|
-
|
|
4276
|
+
React10.useEffect(() => {
|
|
3956
4277
|
if (status !== "choose-ref") {
|
|
3957
4278
|
setBackHandler(null);
|
|
3958
4279
|
return;
|
|
@@ -3969,7 +4290,7 @@ function AddDocsScreen() {
|
|
|
3969
4290
|
setBackHandler(null);
|
|
3970
4291
|
};
|
|
3971
4292
|
}, [status, setBackHandler]);
|
|
3972
|
-
|
|
4293
|
+
React10.useEffect(() => {
|
|
3973
4294
|
let cancelled = false;
|
|
3974
4295
|
const loadRefs = async () => {
|
|
3975
4296
|
if (status !== "choose-ref") return;
|
|
@@ -4003,35 +4324,35 @@ function AddDocsScreen() {
|
|
|
4003
4324
|
};
|
|
4004
4325
|
}, [status, pendingSources, currentIndex]);
|
|
4005
4326
|
if (status === "empty") {
|
|
4006
|
-
return /* @__PURE__ */
|
|
4007
|
-
/* @__PURE__ */
|
|
4008
|
-
/* @__PURE__ */
|
|
4009
|
-
/* @__PURE__ */
|
|
4327
|
+
return /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", padding: 1, children: [
|
|
4328
|
+
/* @__PURE__ */ jsx15(Header, { title: "Add docs" }),
|
|
4329
|
+
/* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "No curated docs configured yet." }),
|
|
4330
|
+
/* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
4010
4331
|
] });
|
|
4011
4332
|
}
|
|
4012
4333
|
if (status === "choose-ref") {
|
|
4013
4334
|
const source = pendingSources[currentIndex];
|
|
4014
4335
|
if (!source) {
|
|
4015
|
-
return /* @__PURE__ */
|
|
4016
|
-
/* @__PURE__ */
|
|
4017
|
-
/* @__PURE__ */
|
|
4336
|
+
return /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", padding: 1, children: [
|
|
4337
|
+
/* @__PURE__ */ jsx15(Header, { title: "Select branch or tag" }),
|
|
4338
|
+
/* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "No docs selected." })
|
|
4018
4339
|
] });
|
|
4019
4340
|
}
|
|
4020
4341
|
const built = repoRefs ? buildRefOptions(repoRefs, includePrerelease) : { options: [], note: "" };
|
|
4021
4342
|
const prereleaseNote = includePrerelease ? "Showing prerelease refs." : "Stable only (Ctrl+P for prerelease).";
|
|
4022
|
-
return /* @__PURE__ */
|
|
4023
|
-
/* @__PURE__ */
|
|
4024
|
-
/* @__PURE__ */
|
|
4025
|
-
/* @__PURE__ */
|
|
4026
|
-
/* @__PURE__ */
|
|
4027
|
-
/* @__PURE__ */
|
|
4028
|
-
/* @__PURE__ */
|
|
4343
|
+
return /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", padding: 1, children: [
|
|
4344
|
+
/* @__PURE__ */ jsx15(Header, { title: "Select branch or tag" }),
|
|
4345
|
+
/* @__PURE__ */ jsxs11(Box13, { marginBottom: 1, flexDirection: "column", children: [
|
|
4346
|
+
/* @__PURE__ */ jsx15(Text13, { children: source.name }),
|
|
4347
|
+
/* @__PURE__ */ jsx15(Text13, { dimColor: true, children: source.docs ? `docs: ${source.docs}` : "full repo" }),
|
|
4348
|
+
/* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "Tags are pinned; update docs will skip them." }),
|
|
4349
|
+
/* @__PURE__ */ jsx15(Text13, { dimColor: true, children: `Repo ${currentIndex + 1}/${pendingSources.length}` })
|
|
4029
4350
|
] }),
|
|
4030
|
-
refError ? /* @__PURE__ */
|
|
4031
|
-
refStatus === "loading" ? /* @__PURE__ */
|
|
4351
|
+
refError ? /* @__PURE__ */ jsx15(Box13, { marginBottom: 1, children: /* @__PURE__ */ jsx15(Text13, { color: "red", children: refError }) }) : null,
|
|
4352
|
+
refStatus === "loading" ? /* @__PURE__ */ jsxs11(Text13, { children: [
|
|
4032
4353
|
spinner,
|
|
4033
4354
|
" Loading refs..."
|
|
4034
|
-
] }) : /* @__PURE__ */
|
|
4355
|
+
] }) : /* @__PURE__ */ jsx15(
|
|
4035
4356
|
SingleSelect,
|
|
4036
4357
|
{
|
|
4037
4358
|
items: built.options.map((option) => ({
|
|
@@ -4061,17 +4382,17 @@ function AddDocsScreen() {
|
|
|
4061
4382
|
hintMode: "active"
|
|
4062
4383
|
}
|
|
4063
4384
|
),
|
|
4064
|
-
/* @__PURE__ */
|
|
4065
|
-
/* @__PURE__ */
|
|
4066
|
-
built.note ? /* @__PURE__ */
|
|
4385
|
+
/* @__PURE__ */ jsxs11(Box13, { marginTop: 1, children: [
|
|
4386
|
+
/* @__PURE__ */ jsx15(Text13, { dimColor: true, children: prereleaseNote }),
|
|
4387
|
+
built.note ? /* @__PURE__ */ jsx15(Text13, { dimColor: true, children: built.note }) : null
|
|
4067
4388
|
] })
|
|
4068
4389
|
] });
|
|
4069
4390
|
}
|
|
4070
4391
|
if (status === "installing") {
|
|
4071
4392
|
const docsBase = shortenPath(getDocsBase(), process.cwd());
|
|
4072
|
-
return /* @__PURE__ */
|
|
4073
|
-
/* @__PURE__ */
|
|
4074
|
-
/* @__PURE__ */
|
|
4393
|
+
return /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", padding: 1, children: [
|
|
4394
|
+
/* @__PURE__ */ jsx15(Header, { title: "Installing docs" }),
|
|
4395
|
+
/* @__PURE__ */ jsxs11(Text13, { children: [
|
|
4075
4396
|
spinner,
|
|
4076
4397
|
" Cloning ",
|
|
4077
4398
|
selected.length,
|
|
@@ -4087,31 +4408,31 @@ function AddDocsScreen() {
|
|
|
4087
4408
|
const skipped = results.filter((r) => r.status === "skipped");
|
|
4088
4409
|
const failed = results.filter((r) => r.status === "failed");
|
|
4089
4410
|
const cwd = process.cwd();
|
|
4090
|
-
return /* @__PURE__ */
|
|
4091
|
-
/* @__PURE__ */
|
|
4092
|
-
installed.length > 0 ? /* @__PURE__ */
|
|
4093
|
-
/* @__PURE__ */
|
|
4094
|
-
installed.map((item) => /* @__PURE__ */
|
|
4411
|
+
return /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", padding: 1, children: [
|
|
4412
|
+
/* @__PURE__ */ jsx15(Header, { title: "Docs installed" }),
|
|
4413
|
+
installed.length > 0 ? /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", marginBottom: 1, children: [
|
|
4414
|
+
/* @__PURE__ */ jsx15(Text13, { children: `Installed ${installed.length} repo${installed.length !== 1 ? "s" : ""}` }),
|
|
4415
|
+
installed.map((item) => /* @__PURE__ */ jsxs11(Text13, { dimColor: true, children: [
|
|
4095
4416
|
item.source.name,
|
|
4096
4417
|
" -> ",
|
|
4097
4418
|
shortenPath(item.path, cwd)
|
|
4098
4419
|
] }, `installed-${item.slug}`))
|
|
4099
4420
|
] }) : null,
|
|
4100
|
-
skipped.length > 0 ? /* @__PURE__ */
|
|
4101
|
-
/* @__PURE__ */
|
|
4102
|
-
skipped.map((item) => /* @__PURE__ */
|
|
4421
|
+
skipped.length > 0 ? /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", marginBottom: 1, children: [
|
|
4422
|
+
/* @__PURE__ */ jsx15(Text13, { dimColor: true, children: "Skipped" }),
|
|
4423
|
+
skipped.map((item) => /* @__PURE__ */ jsxs11(Text13, { dimColor: true, children: [
|
|
4103
4424
|
item.source.name,
|
|
4104
4425
|
item.message ? ` (${item.message})` : ""
|
|
4105
4426
|
] }, `skipped-${item.slug}`))
|
|
4106
4427
|
] }) : null,
|
|
4107
|
-
failed.length > 0 ? /* @__PURE__ */
|
|
4108
|
-
/* @__PURE__ */
|
|
4109
|
-
failed.map((item) => /* @__PURE__ */
|
|
4428
|
+
failed.length > 0 ? /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", marginBottom: 1, children: [
|
|
4429
|
+
/* @__PURE__ */ jsx15(Text13, { color: "red", children: "Failed" }),
|
|
4430
|
+
failed.map((item) => /* @__PURE__ */ jsxs11(Text13, { color: "red", children: [
|
|
4110
4431
|
item.source.name,
|
|
4111
4432
|
item.message ? ` (${item.message})` : ""
|
|
4112
4433
|
] }, `failed-${item.slug}`))
|
|
4113
4434
|
] }) : null,
|
|
4114
|
-
/* @__PURE__ */
|
|
4435
|
+
/* @__PURE__ */ jsx15(
|
|
4115
4436
|
SelectMenu,
|
|
4116
4437
|
{
|
|
4117
4438
|
items: [
|
|
@@ -4146,9 +4467,9 @@ function AddDocsScreen() {
|
|
|
4146
4467
|
disabled: false
|
|
4147
4468
|
};
|
|
4148
4469
|
});
|
|
4149
|
-
return /* @__PURE__ */
|
|
4150
|
-
/* @__PURE__ */
|
|
4151
|
-
/* @__PURE__ */
|
|
4470
|
+
return /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", padding: 1, children: [
|
|
4471
|
+
/* @__PURE__ */ jsx15(Header, { title: "Select docs" }),
|
|
4472
|
+
/* @__PURE__ */ jsx15(
|
|
4152
4473
|
MultiSelect,
|
|
4153
4474
|
{
|
|
4154
4475
|
items,
|
|
@@ -4177,7 +4498,7 @@ function AddDocsScreen() {
|
|
|
4177
4498
|
}
|
|
4178
4499
|
}
|
|
4179
4500
|
),
|
|
4180
|
-
notice ? /* @__PURE__ */
|
|
4501
|
+
notice ? /* @__PURE__ */ jsx15(Box13, { marginTop: 1, children: /* @__PURE__ */ jsxs11(Text13, { color: "cyan", children: [
|
|
4181
4502
|
"[i] ",
|
|
4182
4503
|
notice
|
|
4183
4504
|
] }) }) : null
|
|
@@ -4185,8 +4506,8 @@ function AddDocsScreen() {
|
|
|
4185
4506
|
}
|
|
4186
4507
|
|
|
4187
4508
|
// src/tui/screens/AddInstall.tsx
|
|
4188
|
-
import { Box as
|
|
4189
|
-
import
|
|
4509
|
+
import { Box as Box14, Text as Text14 } from "ink";
|
|
4510
|
+
import React11 from "react";
|
|
4190
4511
|
|
|
4191
4512
|
// src/skill-lock.ts
|
|
4192
4513
|
import { createHash } from "crypto";
|
|
@@ -4685,14 +5006,14 @@ function formatResultSummary(results) {
|
|
|
4685
5006
|
}
|
|
4686
5007
|
|
|
4687
5008
|
// src/tui/screens/AddInstall.tsx
|
|
4688
|
-
import { jsx as
|
|
5009
|
+
import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
4689
5010
|
function AddInstallScreen() {
|
|
4690
5011
|
const { addSkill, updateAddSkill, navigateTo } = useNavigation();
|
|
4691
5012
|
const spinner = useSpinnerFrame(true);
|
|
4692
|
-
const [status, setStatus] =
|
|
4693
|
-
const [error, setError] =
|
|
4694
|
-
const didRun =
|
|
4695
|
-
|
|
5013
|
+
const [status, setStatus] = React11.useState("running");
|
|
5014
|
+
const [error, setError] = React11.useState(null);
|
|
5015
|
+
const didRun = React11.useRef(false);
|
|
5016
|
+
React11.useEffect(() => {
|
|
4696
5017
|
let cancelled = false;
|
|
4697
5018
|
const run = async () => {
|
|
4698
5019
|
if (didRun.current) return;
|
|
@@ -4746,15 +5067,15 @@ function AddInstallScreen() {
|
|
|
4746
5067
|
};
|
|
4747
5068
|
}, [addSkill, updateAddSkill, navigateTo]);
|
|
4748
5069
|
if (status === "error") {
|
|
4749
|
-
return /* @__PURE__ */
|
|
4750
|
-
/* @__PURE__ */
|
|
4751
|
-
/* @__PURE__ */
|
|
4752
|
-
/* @__PURE__ */
|
|
5070
|
+
return /* @__PURE__ */ jsxs12(Box14, { flexDirection: "column", padding: 1, children: [
|
|
5071
|
+
/* @__PURE__ */ jsx16(AddFlowHeader, { title: "Install failed" }),
|
|
5072
|
+
/* @__PURE__ */ jsx16(Text14, { color: "red", children: error }),
|
|
5073
|
+
/* @__PURE__ */ jsx16(Text14, { dimColor: true, children: BACK_QUIT_HINT })
|
|
4753
5074
|
] });
|
|
4754
5075
|
}
|
|
4755
|
-
return /* @__PURE__ */
|
|
4756
|
-
/* @__PURE__ */
|
|
4757
|
-
/* @__PURE__ */
|
|
5076
|
+
return /* @__PURE__ */ jsxs12(Box14, { flexDirection: "column", padding: 1, children: [
|
|
5077
|
+
/* @__PURE__ */ jsx16(AddFlowHeader, { title: "Installing skills" }),
|
|
5078
|
+
/* @__PURE__ */ jsxs12(Text14, { children: [
|
|
4758
5079
|
spinner,
|
|
4759
5080
|
" Installing..."
|
|
4760
5081
|
] })
|
|
@@ -4762,13 +5083,13 @@ function AddInstallScreen() {
|
|
|
4762
5083
|
}
|
|
4763
5084
|
|
|
4764
5085
|
// src/tui/screens/AddLicenseKey.tsx
|
|
4765
|
-
import { Box as
|
|
5086
|
+
import { Box as Box15, Text as Text15 } from "ink";
|
|
4766
5087
|
import TextInput2 from "ink-text-input";
|
|
4767
|
-
import
|
|
4768
|
-
import { jsx as
|
|
5088
|
+
import React12 from "react";
|
|
5089
|
+
import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
4769
5090
|
function AddLicenseKeyScreen() {
|
|
4770
5091
|
const { invocation, addSkill, updateAddSkill, navigateTo, setFlash } = useNavigation();
|
|
4771
|
-
const [value, setValue] =
|
|
5092
|
+
const [value, setValue] = React12.useState(
|
|
4772
5093
|
addSkill.licenseKey ?? invocation.options.licenseKey ?? ""
|
|
4773
5094
|
);
|
|
4774
5095
|
const { wrapOnChange } = useTextInput({
|
|
@@ -4785,27 +5106,27 @@ function AddLicenseKeyScreen() {
|
|
|
4785
5106
|
updateAddSkill({ licenseKey: trimmed });
|
|
4786
5107
|
navigateTo("add-skill-select");
|
|
4787
5108
|
};
|
|
4788
|
-
return /* @__PURE__ */
|
|
4789
|
-
/* @__PURE__ */
|
|
4790
|
-
/* @__PURE__ */
|
|
4791
|
-
/* @__PURE__ */
|
|
4792
|
-
/* @__PURE__ */
|
|
4793
|
-
/* @__PURE__ */
|
|
4794
|
-
/* @__PURE__ */
|
|
5109
|
+
return /* @__PURE__ */ jsxs13(Box15, { flexDirection: "column", padding: 1, children: [
|
|
5110
|
+
/* @__PURE__ */ jsx17(Header, { title: "License key" }),
|
|
5111
|
+
/* @__PURE__ */ jsx17(Box15, { marginBottom: 1, children: /* @__PURE__ */ jsx17(Text15, { children: "Enter the license key for this paid/private skill." }) }),
|
|
5112
|
+
/* @__PURE__ */ jsx17(Box15, { marginBottom: 1, children: /* @__PURE__ */ jsx17(Text15, { dimColor: true, children: "Tip: you can also pass it via --license-key." }) }),
|
|
5113
|
+
/* @__PURE__ */ jsxs13(Box15, { children: [
|
|
5114
|
+
/* @__PURE__ */ jsx17(Text15, { color: "green", children: "> " }),
|
|
5115
|
+
/* @__PURE__ */ jsx17(TextInput2, { value, onChange: wrapOnChange(setValue), onSubmit })
|
|
4795
5116
|
] }),
|
|
4796
|
-
/* @__PURE__ */
|
|
5117
|
+
/* @__PURE__ */ jsx17(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx17(Text15, { dimColor: true, children: TEXT_INPUT_HINT }) })
|
|
4797
5118
|
] });
|
|
4798
5119
|
}
|
|
4799
5120
|
|
|
4800
5121
|
// src/tui/screens/AddMode.tsx
|
|
4801
5122
|
import { join as join12 } from "path";
|
|
4802
|
-
import { Box as
|
|
4803
|
-
import
|
|
4804
|
-
import { jsx as
|
|
5123
|
+
import { Box as Box16 } from "ink";
|
|
5124
|
+
import React13 from "react";
|
|
5125
|
+
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
4805
5126
|
function AddModeScreen() {
|
|
4806
5127
|
const { invocation, addSkill, updateAddSkill, navigateTo, navAction } = useNavigation();
|
|
4807
5128
|
const options = invocation.options;
|
|
4808
|
-
|
|
5129
|
+
React13.useEffect(() => {
|
|
4809
5130
|
if (navAction === "pop") return;
|
|
4810
5131
|
if (addSkill.installMode) {
|
|
4811
5132
|
navigateTo("add-confirm");
|
|
@@ -4835,9 +5156,9 @@ function AddModeScreen() {
|
|
|
4835
5156
|
{ label: "Symlink (recommended)", value: "symlink", hint: symlinkHint },
|
|
4836
5157
|
{ label: "Copy to each agent", value: "copy", hint: copyHint }
|
|
4837
5158
|
];
|
|
4838
|
-
return /* @__PURE__ */
|
|
4839
|
-
/* @__PURE__ */
|
|
4840
|
-
/* @__PURE__ */
|
|
5159
|
+
return /* @__PURE__ */ jsxs14(Box16, { flexDirection: "column", padding: 1, children: [
|
|
5160
|
+
/* @__PURE__ */ jsx18(AddFlowHeader, { title: "Install mode" }),
|
|
5161
|
+
/* @__PURE__ */ jsx18(
|
|
4841
5162
|
SingleSelect,
|
|
4842
5163
|
{
|
|
4843
5164
|
items,
|
|
@@ -4853,9 +5174,9 @@ function AddModeScreen() {
|
|
|
4853
5174
|
|
|
4854
5175
|
// src/tui/screens/AddResult.tsx
|
|
4855
5176
|
import chalk3 from "chalk";
|
|
4856
|
-
import { Box as
|
|
4857
|
-
import
|
|
4858
|
-
import { jsx as
|
|
5177
|
+
import { Box as Box17, Text as Text16 } from "ink";
|
|
5178
|
+
import React14 from "react";
|
|
5179
|
+
import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
4859
5180
|
function AddResultScreen() {
|
|
4860
5181
|
const { addSkill, resetAddSkill, navigateTo } = useNavigation();
|
|
4861
5182
|
const results = addSkill.installResults ?? [];
|
|
@@ -4863,7 +5184,7 @@ function AddResultScreen() {
|
|
|
4863
5184
|
const failed = results.filter((r) => !r.success);
|
|
4864
5185
|
const symlinkFailures = successful.filter((r) => r.mode === "symlink" && r.symlinkFailed);
|
|
4865
5186
|
const summary = successful.length > 0 ? formatResultSummary(successful) : null;
|
|
4866
|
-
const summaryLines =
|
|
5187
|
+
const summaryLines = React14.useMemo(() => {
|
|
4867
5188
|
if (!summary) return [];
|
|
4868
5189
|
const counts = /* @__PURE__ */ new Map();
|
|
4869
5190
|
return summary.lines.map((line) => {
|
|
@@ -4872,15 +5193,15 @@ function AddResultScreen() {
|
|
|
4872
5193
|
return { line, key: `${line}-${count}` };
|
|
4873
5194
|
});
|
|
4874
5195
|
}, [summary]);
|
|
4875
|
-
return /* @__PURE__ */
|
|
4876
|
-
/* @__PURE__ */
|
|
4877
|
-
summary ? /* @__PURE__ */
|
|
4878
|
-
/* @__PURE__ */
|
|
4879
|
-
summaryLines.map(({ line, key }) => /* @__PURE__ */
|
|
5196
|
+
return /* @__PURE__ */ jsxs15(Box17, { flexDirection: "column", padding: 1, children: [
|
|
5197
|
+
/* @__PURE__ */ jsx19(AddFlowHeader, { title: "Install results" }),
|
|
5198
|
+
summary ? /* @__PURE__ */ jsxs15(Box17, { flexDirection: "column", marginBottom: 1, children: [
|
|
5199
|
+
/* @__PURE__ */ jsx19(Text16, { children: summary.title }),
|
|
5200
|
+
summaryLines.map(({ line, key }) => /* @__PURE__ */ jsx19(Text16, { children: line }, key))
|
|
4880
5201
|
] }) : null,
|
|
4881
|
-
failed.length > 0 ? /* @__PURE__ */
|
|
4882
|
-
/* @__PURE__ */
|
|
4883
|
-
failed.map((r) => /* @__PURE__ */
|
|
5202
|
+
failed.length > 0 ? /* @__PURE__ */ jsxs15(Box17, { flexDirection: "column", marginBottom: 1, children: [
|
|
5203
|
+
/* @__PURE__ */ jsx19(Text16, { color: "red", children: `Failed to install ${failed.length}` }),
|
|
5204
|
+
failed.map((r) => /* @__PURE__ */ jsxs15(Text16, { children: [
|
|
4884
5205
|
chalk3.red("\u2717"),
|
|
4885
5206
|
" ",
|
|
4886
5207
|
r.skill,
|
|
@@ -4890,15 +5211,15 @@ function AddResultScreen() {
|
|
|
4890
5211
|
chalk3.dim(r.error)
|
|
4891
5212
|
] }, `${r.skill}-${r.agentId}`))
|
|
4892
5213
|
] }) : null,
|
|
4893
|
-
successful.length > 0 ? /* @__PURE__ */
|
|
5214
|
+
successful.length > 0 ? /* @__PURE__ */ jsx19(Box17, { marginBottom: 1, children: /* @__PURE__ */ jsxs15(Text16, { dimColor: true, children: [
|
|
4894
5215
|
"Installed to: ",
|
|
4895
5216
|
formatList(successful.map((r) => r.agent))
|
|
4896
5217
|
] }) }) : null,
|
|
4897
|
-
symlinkFailures.length > 0 ? /* @__PURE__ */
|
|
4898
|
-
/* @__PURE__ */
|
|
4899
|
-
/* @__PURE__ */
|
|
5218
|
+
symlinkFailures.length > 0 ? /* @__PURE__ */ jsxs15(Box17, { marginBottom: 1, children: [
|
|
5219
|
+
/* @__PURE__ */ jsx19(Text16, { color: "yellow", children: `Symlinks failed for: ${formatList(symlinkFailures.map((r) => r.agent))}` }),
|
|
5220
|
+
/* @__PURE__ */ jsx19(Text16, { dimColor: true, children: "Files were copied instead." })
|
|
4900
5221
|
] }) : null,
|
|
4901
|
-
/* @__PURE__ */
|
|
5222
|
+
/* @__PURE__ */ jsx19(
|
|
4902
5223
|
SelectMenu,
|
|
4903
5224
|
{
|
|
4904
5225
|
items: [
|
|
@@ -4921,13 +5242,13 @@ function AddResultScreen() {
|
|
|
4921
5242
|
}
|
|
4922
5243
|
|
|
4923
5244
|
// src/tui/screens/AddScope.tsx
|
|
4924
|
-
import { Box as
|
|
4925
|
-
import
|
|
4926
|
-
import { jsx as
|
|
5245
|
+
import { Box as Box18 } from "ink";
|
|
5246
|
+
import React15 from "react";
|
|
5247
|
+
import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
4927
5248
|
function AddScopeScreen() {
|
|
4928
5249
|
const { invocation, addSkill, updateAddSkill, navigateTo, navAction } = useNavigation();
|
|
4929
5250
|
const options = invocation.options;
|
|
4930
|
-
|
|
5251
|
+
React15.useEffect(() => {
|
|
4931
5252
|
if (navAction === "pop") return;
|
|
4932
5253
|
if (addSkill.installGlobally !== void 0) {
|
|
4933
5254
|
navigateTo("add-mode");
|
|
@@ -4950,9 +5271,9 @@ function AddScopeScreen() {
|
|
|
4950
5271
|
const globalBase = getCanonicalSkillsBase({ global: true, cwd });
|
|
4951
5272
|
const projectHint = `Project base (symlink): ${shortenPath(projectBase, cwd)}`;
|
|
4952
5273
|
const globalHint = `Global base (symlink): ${shortenPath(globalBase, cwd)}`;
|
|
4953
|
-
return /* @__PURE__ */
|
|
4954
|
-
/* @__PURE__ */
|
|
4955
|
-
/* @__PURE__ */
|
|
5274
|
+
return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", padding: 1, children: [
|
|
5275
|
+
/* @__PURE__ */ jsx20(AddFlowHeader, { title: "Install scope" }),
|
|
5276
|
+
/* @__PURE__ */ jsx20(
|
|
4956
5277
|
SingleSelect,
|
|
4957
5278
|
{
|
|
4958
5279
|
items: [
|
|
@@ -4973,24 +5294,24 @@ function AddScopeScreen() {
|
|
|
4973
5294
|
] });
|
|
4974
5295
|
}
|
|
4975
5296
|
|
|
4976
|
-
// src/tui/screens/AddSecurityScan.tsx
|
|
4977
|
-
import { Box as
|
|
4978
|
-
import
|
|
4979
|
-
import { jsx as
|
|
5297
|
+
// src/tui/screens/AddSecurityScan.tsx
|
|
5298
|
+
import { Box as Box19, Text as Text17 } from "ink";
|
|
5299
|
+
import React16 from "react";
|
|
5300
|
+
import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
4980
5301
|
function AddSecurityScanScreen() {
|
|
4981
5302
|
const { invocation, addSkill, updateAddSkill, navigateTo, resetTo, setFlash, setBackHandler } = useNavigation();
|
|
4982
5303
|
const options = invocation.options;
|
|
4983
|
-
const [status, setStatus] =
|
|
4984
|
-
const [error, setError] =
|
|
4985
|
-
const [manualView, setManualView] =
|
|
4986
|
-
const [confirmText, setConfirmText] =
|
|
4987
|
-
const [selectedRow, setSelectedRow] =
|
|
5304
|
+
const [status, setStatus] = React16.useState("scanning");
|
|
5305
|
+
const [error, setError] = React16.useState(null);
|
|
5306
|
+
const [manualView, setManualView] = React16.useState("menu");
|
|
5307
|
+
const [confirmText, setConfirmText] = React16.useState("");
|
|
5308
|
+
const [selectedRow, setSelectedRow] = React16.useState(null);
|
|
4988
5309
|
const spinner = useSpinnerFrame(status === "scanning");
|
|
4989
5310
|
const { wrapOnChange } = useTextInput({
|
|
4990
5311
|
onClear: () => setConfirmText(""),
|
|
4991
5312
|
disabled: status !== "risky" || manualView !== "type-confirm"
|
|
4992
5313
|
});
|
|
4993
|
-
|
|
5314
|
+
React16.useEffect(() => {
|
|
4994
5315
|
const selectedSkills = addSkill.selectedSkills;
|
|
4995
5316
|
if (!selectedSkills || selectedSkills.length === 0) {
|
|
4996
5317
|
navigateTo("add-skill-select");
|
|
@@ -5030,7 +5351,7 @@ function AddSecurityScanScreen() {
|
|
|
5030
5351
|
cancelled = true;
|
|
5031
5352
|
};
|
|
5032
5353
|
}, [addSkill.selectedSkills, navigateTo, updateAddSkill]);
|
|
5033
|
-
|
|
5354
|
+
React16.useEffect(() => {
|
|
5034
5355
|
if (status !== "risky") {
|
|
5035
5356
|
setBackHandler(null);
|
|
5036
5357
|
return () => setBackHandler(null);
|
|
@@ -5054,17 +5375,17 @@ function AddSecurityScanScreen() {
|
|
|
5054
5375
|
return () => setBackHandler(null);
|
|
5055
5376
|
}, [status, manualView, setBackHandler]);
|
|
5056
5377
|
if (status === "error") {
|
|
5057
|
-
return /* @__PURE__ */
|
|
5058
|
-
/* @__PURE__ */
|
|
5059
|
-
/* @__PURE__ */
|
|
5060
|
-
/* @__PURE__ */
|
|
5378
|
+
return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
|
|
5379
|
+
/* @__PURE__ */ jsx21(AddFlowHeader, { title: "Security scan" }),
|
|
5380
|
+
/* @__PURE__ */ jsx21(Text17, { color: "red", children: error ?? "Scan failed" }),
|
|
5381
|
+
/* @__PURE__ */ jsx21(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx21(Text17, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
5061
5382
|
] });
|
|
5062
5383
|
}
|
|
5063
5384
|
if (status === "scanning") {
|
|
5064
5385
|
const count = addSkill.selectedSkills?.length ?? 0;
|
|
5065
|
-
return /* @__PURE__ */
|
|
5066
|
-
/* @__PURE__ */
|
|
5067
|
-
/* @__PURE__ */
|
|
5386
|
+
return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
|
|
5387
|
+
/* @__PURE__ */ jsx21(AddFlowHeader, { title: "Security scan" }),
|
|
5388
|
+
/* @__PURE__ */ jsxs17(Text17, { children: [
|
|
5068
5389
|
spinner,
|
|
5069
5390
|
" Scanning ",
|
|
5070
5391
|
count,
|
|
@@ -5075,9 +5396,9 @@ function AddSecurityScanScreen() {
|
|
|
5075
5396
|
] });
|
|
5076
5397
|
}
|
|
5077
5398
|
if (status === "risky") {
|
|
5078
|
-
return /* @__PURE__ */
|
|
5079
|
-
/* @__PURE__ */
|
|
5080
|
-
/* @__PURE__ */
|
|
5399
|
+
return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
|
|
5400
|
+
/* @__PURE__ */ jsx21(AddFlowHeader, { title: "Security scan" }),
|
|
5401
|
+
/* @__PURE__ */ jsx21(
|
|
5081
5402
|
ManualSecurityGate,
|
|
5082
5403
|
{
|
|
5083
5404
|
scanRows: addSkill.securityScanRows ?? [],
|
|
@@ -5101,12 +5422,12 @@ function AddSecurityScanScreen() {
|
|
|
5101
5422
|
] });
|
|
5102
5423
|
}
|
|
5103
5424
|
if (options.yes) {
|
|
5104
|
-
return /* @__PURE__ */
|
|
5425
|
+
return /* @__PURE__ */ jsx21(Box19, { padding: 1 });
|
|
5105
5426
|
}
|
|
5106
|
-
return /* @__PURE__ */
|
|
5107
|
-
/* @__PURE__ */
|
|
5108
|
-
/* @__PURE__ */
|
|
5109
|
-
/* @__PURE__ */
|
|
5427
|
+
return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
|
|
5428
|
+
/* @__PURE__ */ jsx21(AddFlowHeader, { title: "Security scan" }),
|
|
5429
|
+
/* @__PURE__ */ jsx21(Text17, { dimColor: true, children: "Scan complete." }),
|
|
5430
|
+
/* @__PURE__ */ jsx21(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx21(Text17, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
5110
5431
|
] });
|
|
5111
5432
|
}
|
|
5112
5433
|
|
|
@@ -5115,8 +5436,8 @@ import { existsSync as existsSync6 } from "fs";
|
|
|
5115
5436
|
import { mkdir as mkdir6, mkdtemp as mkdtemp4, writeFile as writeFile4 } from "fs/promises";
|
|
5116
5437
|
import { tmpdir as tmpdir5 } from "os";
|
|
5117
5438
|
import { join as join15 } from "path";
|
|
5118
|
-
import { Box as
|
|
5119
|
-
import
|
|
5439
|
+
import { Box as Box20, Text as Text18 } from "ink";
|
|
5440
|
+
import React17 from "react";
|
|
5120
5441
|
|
|
5121
5442
|
// src/mintlify.ts
|
|
5122
5443
|
import matter3 from "gray-matter";
|
|
@@ -6140,36 +6461,8 @@ function resolvePluginSource(plugin, context) {
|
|
|
6140
6461
|
return { kind: "unsupported", reason: "Unknown source type", overrides };
|
|
6141
6462
|
}
|
|
6142
6463
|
|
|
6143
|
-
// src/tui/utils/skill-selection.ts
|
|
6144
|
-
import { basename as basename5 } from "path";
|
|
6145
|
-
function matchesSkillName(skill, input) {
|
|
6146
|
-
const normalized = input.toLowerCase();
|
|
6147
|
-
const byName = skill.name.toLowerCase() === normalized;
|
|
6148
|
-
const byPath = basename5(skill.path).toLowerCase() === normalized;
|
|
6149
|
-
return byName || byPath;
|
|
6150
|
-
}
|
|
6151
|
-
function autoSelect(skills, options) {
|
|
6152
|
-
if (options.skill && options.skill.length > 0) {
|
|
6153
|
-
const selected = skills.filter((s) => options.skill?.some((name) => matchesSkillName(s, name)));
|
|
6154
|
-
if (selected.length === 0) {
|
|
6155
|
-
return {
|
|
6156
|
-
status: "prompt",
|
|
6157
|
-
message: `No matching skills found for: ${options.skill.join(", ")}`
|
|
6158
|
-
};
|
|
6159
|
-
}
|
|
6160
|
-
return { status: "selected", skills: selected };
|
|
6161
|
-
}
|
|
6162
|
-
if (skills.length === 1) {
|
|
6163
|
-
return { status: "selected", skills };
|
|
6164
|
-
}
|
|
6165
|
-
if (options.yes) {
|
|
6166
|
-
return { status: "selected", skills };
|
|
6167
|
-
}
|
|
6168
|
-
return { status: "prompt" };
|
|
6169
|
-
}
|
|
6170
|
-
|
|
6171
6464
|
// src/tui/screens/AddSkillSelect.tsx
|
|
6172
|
-
import { jsx as
|
|
6465
|
+
import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
6173
6466
|
function AddSkillSelectScreen() {
|
|
6174
6467
|
const {
|
|
6175
6468
|
invocation,
|
|
@@ -6183,16 +6476,16 @@ function AddSkillSelectScreen() {
|
|
|
6183
6476
|
resetAddSkill,
|
|
6184
6477
|
setLastSource
|
|
6185
6478
|
} = useNavigation();
|
|
6186
|
-
const [status, setStatus] =
|
|
6479
|
+
const [status, setStatus] = React17.useState(
|
|
6187
6480
|
addSkill.skills && addSkill.skills.length > 0 ? "ready" : "loading"
|
|
6188
6481
|
);
|
|
6189
|
-
const [error, setError] =
|
|
6190
|
-
const [listMode, setListMode] =
|
|
6191
|
-
const [showLoading, setShowLoading] =
|
|
6482
|
+
const [error, setError] = React17.useState(null);
|
|
6483
|
+
const [listMode, setListMode] = React17.useState(false);
|
|
6484
|
+
const [showLoading, setShowLoading] = React17.useState(false);
|
|
6192
6485
|
const spinner = useSpinnerFrame(status === "loading");
|
|
6193
6486
|
const source = addSkill.source ?? invocation.source;
|
|
6194
6487
|
const options = invocation.options;
|
|
6195
|
-
|
|
6488
|
+
React17.useEffect(() => {
|
|
6196
6489
|
let cancelled = false;
|
|
6197
6490
|
const load = async () => {
|
|
6198
6491
|
if (!source) {
|
|
@@ -6390,7 +6683,7 @@ function AddSkillSelectScreen() {
|
|
|
6390
6683
|
cancelled = true;
|
|
6391
6684
|
};
|
|
6392
6685
|
}, [source, addSkill.skills, addSkill.licenseKey, updateAddSkill, navigateTo, options, setFlash]);
|
|
6393
|
-
|
|
6686
|
+
React17.useEffect(() => {
|
|
6394
6687
|
if (invocation.source) {
|
|
6395
6688
|
setBackHandler(() => {
|
|
6396
6689
|
setLastSource(invocation.source ?? null);
|
|
@@ -6406,7 +6699,7 @@ function AddSkillSelectScreen() {
|
|
|
6406
6699
|
setBackHandler(null);
|
|
6407
6700
|
};
|
|
6408
6701
|
}, [invocation.source, resetTo, setBackHandler, resetAddSkill, setInvocation, setLastSource]);
|
|
6409
|
-
|
|
6702
|
+
React17.useEffect(() => {
|
|
6410
6703
|
if (status !== "loading") {
|
|
6411
6704
|
setShowLoading(false);
|
|
6412
6705
|
return;
|
|
@@ -6417,18 +6710,18 @@ function AddSkillSelectScreen() {
|
|
|
6417
6710
|
return () => clearTimeout(timer);
|
|
6418
6711
|
}, [status]);
|
|
6419
6712
|
if (!source) {
|
|
6420
|
-
return /* @__PURE__ */
|
|
6421
|
-
/* @__PURE__ */
|
|
6422
|
-
/* @__PURE__ */
|
|
6713
|
+
return /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", padding: 1, children: [
|
|
6714
|
+
/* @__PURE__ */ jsx22(AddFlowHeader, { title: "Add skills" }),
|
|
6715
|
+
/* @__PURE__ */ jsx22(Text18, { children: `Missing source. ${BACK_QUIT_HINT}` })
|
|
6423
6716
|
] });
|
|
6424
6717
|
}
|
|
6425
6718
|
if (status === "loading" && !showLoading) {
|
|
6426
|
-
return /* @__PURE__ */
|
|
6719
|
+
return /* @__PURE__ */ jsx22(Box20, { padding: 1 });
|
|
6427
6720
|
}
|
|
6428
6721
|
if (status === "loading") {
|
|
6429
|
-
return /* @__PURE__ */
|
|
6430
|
-
/* @__PURE__ */
|
|
6431
|
-
/* @__PURE__ */
|
|
6722
|
+
return /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", padding: 1, children: [
|
|
6723
|
+
/* @__PURE__ */ jsx22(AddFlowHeader, { title: "Scanning skills" }),
|
|
6724
|
+
/* @__PURE__ */ jsxs18(Text18, { children: [
|
|
6432
6725
|
spinner,
|
|
6433
6726
|
" Fetching skills from ",
|
|
6434
6727
|
source
|
|
@@ -6436,32 +6729,32 @@ function AddSkillSelectScreen() {
|
|
|
6436
6729
|
] });
|
|
6437
6730
|
}
|
|
6438
6731
|
if (status === "error") {
|
|
6439
|
-
return /* @__PURE__ */
|
|
6440
|
-
/* @__PURE__ */
|
|
6441
|
-
/* @__PURE__ */
|
|
6442
|
-
/* @__PURE__ */
|
|
6732
|
+
return /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", padding: 1, children: [
|
|
6733
|
+
/* @__PURE__ */ jsx22(AddFlowHeader, { title: "Unable to load skills" }),
|
|
6734
|
+
/* @__PURE__ */ jsx22(Text18, { color: "red", children: error }),
|
|
6735
|
+
/* @__PURE__ */ jsx22(Box20, { marginTop: 1, children: /* @__PURE__ */ jsx22(Text18, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
6443
6736
|
] });
|
|
6444
6737
|
}
|
|
6445
6738
|
const skills = addSkill.skills ?? [];
|
|
6446
6739
|
if (listMode || status === "list") {
|
|
6447
|
-
return /* @__PURE__ */
|
|
6448
|
-
/* @__PURE__ */
|
|
6449
|
-
skills.map((skill) => /* @__PURE__ */
|
|
6450
|
-
/* @__PURE__ */
|
|
6451
|
-
skill.description ? /* @__PURE__ */
|
|
6740
|
+
return /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", padding: 1, children: [
|
|
6741
|
+
/* @__PURE__ */ jsx22(AddFlowHeader, { title: `Available skills (${skills.length})` }),
|
|
6742
|
+
skills.map((skill) => /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", marginBottom: 1, children: [
|
|
6743
|
+
/* @__PURE__ */ jsx22(Text18, { children: getSkillDisplayName(skill) }),
|
|
6744
|
+
skill.description ? /* @__PURE__ */ jsx22(Text18, { dimColor: true, children: skill.description }) : null
|
|
6452
6745
|
] }, skill.name)),
|
|
6453
|
-
/* @__PURE__ */
|
|
6746
|
+
/* @__PURE__ */ jsx22(Text18, { dimColor: true, children: BACK_QUIT_HINT })
|
|
6454
6747
|
] });
|
|
6455
6748
|
}
|
|
6456
6749
|
if (skills.length === 0) {
|
|
6457
|
-
return /* @__PURE__ */
|
|
6458
|
-
/* @__PURE__ */
|
|
6459
|
-
/* @__PURE__ */
|
|
6750
|
+
return /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", padding: 1, children: [
|
|
6751
|
+
/* @__PURE__ */ jsx22(AddFlowHeader, { title: "No skills found" }),
|
|
6752
|
+
/* @__PURE__ */ jsx22(Text18, { dimColor: true, children: BACK_QUIT_HINT })
|
|
6460
6753
|
] });
|
|
6461
6754
|
}
|
|
6462
|
-
return /* @__PURE__ */
|
|
6463
|
-
/* @__PURE__ */
|
|
6464
|
-
/* @__PURE__ */
|
|
6755
|
+
return /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", padding: 1, children: [
|
|
6756
|
+
/* @__PURE__ */ jsx22(AddFlowHeader, { title: "Select skills" }),
|
|
6757
|
+
/* @__PURE__ */ jsx22(
|
|
6465
6758
|
MultiSelect,
|
|
6466
6759
|
{
|
|
6467
6760
|
items: skills.map((skill) => ({
|
|
@@ -6493,22 +6786,22 @@ function AddSkillSelectScreen() {
|
|
|
6493
6786
|
}
|
|
6494
6787
|
|
|
6495
6788
|
// src/tui/screens/AddSource.tsx
|
|
6496
|
-
import { Box as
|
|
6789
|
+
import { Box as Box21, Text as Text19 } from "ink";
|
|
6497
6790
|
import TextInput3 from "ink-text-input";
|
|
6498
|
-
import
|
|
6499
|
-
import { jsx as
|
|
6791
|
+
import React18 from "react";
|
|
6792
|
+
import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
6500
6793
|
function AddSourceScreen() {
|
|
6501
6794
|
const { invocation, addSkill, updateAddSkill, navigateTo, setFlash, lastSource, setLastSource } = useNavigation();
|
|
6502
|
-
const [value, setValue] =
|
|
6795
|
+
const [value, setValue] = React18.useState(
|
|
6503
6796
|
addSkill.source ?? invocation.source ?? lastSource ?? ""
|
|
6504
6797
|
);
|
|
6505
|
-
const didAutofillRef =
|
|
6798
|
+
const didAutofillRef = React18.useRef(false);
|
|
6506
6799
|
const { wrapOnChange } = useTextInput({
|
|
6507
6800
|
onClear: () => {
|
|
6508
6801
|
setValue("");
|
|
6509
6802
|
}
|
|
6510
6803
|
});
|
|
6511
|
-
|
|
6804
|
+
React18.useEffect(() => {
|
|
6512
6805
|
const preset = invocation.source;
|
|
6513
6806
|
if (!preset || didAutofillRef.current) return;
|
|
6514
6807
|
didAutofillRef.current = true;
|
|
@@ -6525,31 +6818,31 @@ function AddSourceScreen() {
|
|
|
6525
6818
|
updateAddSkill({ source: trimmed });
|
|
6526
6819
|
navigateTo("add-skill-select");
|
|
6527
6820
|
};
|
|
6528
|
-
return /* @__PURE__ */
|
|
6529
|
-
/* @__PURE__ */
|
|
6530
|
-
/* @__PURE__ */
|
|
6531
|
-
/* @__PURE__ */
|
|
6532
|
-
/* @__PURE__ */
|
|
6533
|
-
/* @__PURE__ */
|
|
6534
|
-
/* @__PURE__ */
|
|
6821
|
+
return /* @__PURE__ */ jsxs19(Box21, { flexDirection: "column", padding: 1, children: [
|
|
6822
|
+
/* @__PURE__ */ jsx23(Header, { title: "Add skills" }),
|
|
6823
|
+
/* @__PURE__ */ jsx23(Box21, { marginBottom: 1, children: /* @__PURE__ */ jsx23(Text19, { children: "Where should we fetch skills from?" }) }),
|
|
6824
|
+
/* @__PURE__ */ jsx23(Box21, { marginBottom: 1, children: /* @__PURE__ */ jsx23(Text19, { dimColor: true, children: "Examples: owner/repo, https://.../SKILL.md, ./local/path" }) }),
|
|
6825
|
+
/* @__PURE__ */ jsxs19(Box21, { children: [
|
|
6826
|
+
/* @__PURE__ */ jsx23(Text19, { color: "green", children: "> " }),
|
|
6827
|
+
/* @__PURE__ */ jsx23(TextInput3, { value, onChange: wrapOnChange(setValue), onSubmit })
|
|
6535
6828
|
] }),
|
|
6536
|
-
/* @__PURE__ */
|
|
6829
|
+
/* @__PURE__ */ jsx23(Box21, { marginTop: 1, children: /* @__PURE__ */ jsx23(Text19, { dimColor: true, children: TEXT_INPUT_HINT }) })
|
|
6537
6830
|
] });
|
|
6538
6831
|
}
|
|
6539
6832
|
|
|
6540
6833
|
// src/tui/screens/AddTargets.tsx
|
|
6541
|
-
import { Box as
|
|
6542
|
-
import
|
|
6543
|
-
import { Fragment as Fragment2, jsx as
|
|
6834
|
+
import { Box as Box22, Text as Text20 } from "ink";
|
|
6835
|
+
import React19 from "react";
|
|
6836
|
+
import { Fragment as Fragment2, jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
6544
6837
|
function AddTargetsScreen() {
|
|
6545
6838
|
const { invocation, addSkill, updateAddSkill, navigateTo, setFlash, navAction } = useNavigation();
|
|
6546
|
-
const [status, setStatus] =
|
|
6547
|
-
const [mode, setMode] =
|
|
6548
|
-
const [availableAgents, setAvailableAgents] =
|
|
6549
|
-
const [lastSelected, setLastSelected] =
|
|
6550
|
-
const [showLoading, setShowLoading] =
|
|
6839
|
+
const [status, setStatus] = React19.useState("loading");
|
|
6840
|
+
const [mode, setMode] = React19.useState("choice");
|
|
6841
|
+
const [availableAgents, setAvailableAgents] = React19.useState([]);
|
|
6842
|
+
const [lastSelected, setLastSelected] = React19.useState([]);
|
|
6843
|
+
const [showLoading, setShowLoading] = React19.useState(false);
|
|
6551
6844
|
const spinner = useSpinnerFrame(status === "loading");
|
|
6552
|
-
|
|
6845
|
+
React19.useEffect(() => {
|
|
6553
6846
|
let cancelled = false;
|
|
6554
6847
|
const run = async () => {
|
|
6555
6848
|
setStatus("loading");
|
|
@@ -6598,7 +6891,7 @@ function AddTargetsScreen() {
|
|
|
6598
6891
|
cancelled = true;
|
|
6599
6892
|
};
|
|
6600
6893
|
}, [invocation.options, updateAddSkill, navigateTo, addSkill.targetAgents, setFlash, navAction]);
|
|
6601
|
-
|
|
6894
|
+
React19.useEffect(() => {
|
|
6602
6895
|
if (status !== "loading") {
|
|
6603
6896
|
setShowLoading(false);
|
|
6604
6897
|
return;
|
|
@@ -6609,12 +6902,12 @@ function AddTargetsScreen() {
|
|
|
6609
6902
|
return () => clearTimeout(timer);
|
|
6610
6903
|
}, [status]);
|
|
6611
6904
|
if (status === "loading" && !showLoading) {
|
|
6612
|
-
return /* @__PURE__ */
|
|
6905
|
+
return /* @__PURE__ */ jsx24(Box22, { padding: 1 });
|
|
6613
6906
|
}
|
|
6614
6907
|
if (status === "loading") {
|
|
6615
|
-
return /* @__PURE__ */
|
|
6616
|
-
/* @__PURE__ */
|
|
6617
|
-
/* @__PURE__ */
|
|
6908
|
+
return /* @__PURE__ */ jsxs20(Box22, { flexDirection: "column", padding: 1, children: [
|
|
6909
|
+
/* @__PURE__ */ jsx24(AddFlowHeader, { title: "Detecting agents" }),
|
|
6910
|
+
/* @__PURE__ */ jsxs20(Text20, { children: [
|
|
6618
6911
|
spinner,
|
|
6619
6912
|
" Checking installed agents..."
|
|
6620
6913
|
] })
|
|
@@ -6636,9 +6929,9 @@ function AddTargetsScreen() {
|
|
|
6636
6929
|
label: agents[agent].displayName,
|
|
6637
6930
|
hint: agents[agent].skillsDir
|
|
6638
6931
|
}));
|
|
6639
|
-
return /* @__PURE__ */
|
|
6640
|
-
/* @__PURE__ */
|
|
6641
|
-
/* @__PURE__ */
|
|
6932
|
+
return /* @__PURE__ */ jsx24(Box22, { flexDirection: "column", padding: 1, children: mode === "choice" ? /* @__PURE__ */ jsxs20(Fragment2, { children: [
|
|
6933
|
+
/* @__PURE__ */ jsx24(AddFlowHeader, { title: "Install to" }),
|
|
6934
|
+
/* @__PURE__ */ jsx24(
|
|
6642
6935
|
SingleSelect,
|
|
6643
6936
|
{
|
|
6644
6937
|
items: [
|
|
@@ -6671,9 +6964,9 @@ function AddTargetsScreen() {
|
|
|
6671
6964
|
}
|
|
6672
6965
|
}
|
|
6673
6966
|
)
|
|
6674
|
-
] }) : /* @__PURE__ */
|
|
6675
|
-
/* @__PURE__ */
|
|
6676
|
-
/* @__PURE__ */
|
|
6967
|
+
] }) : /* @__PURE__ */ jsxs20(Fragment2, { children: [
|
|
6968
|
+
/* @__PURE__ */ jsx24(AddFlowHeader, { title: "Select agents" }),
|
|
6969
|
+
/* @__PURE__ */ jsx24(
|
|
6677
6970
|
MultiSelect,
|
|
6678
6971
|
{
|
|
6679
6972
|
items: selectableItems,
|
|
@@ -6705,9 +6998,9 @@ function AddTargetsScreen() {
|
|
|
6705
6998
|
}
|
|
6706
6999
|
|
|
6707
7000
|
// src/tui/screens/FindSkillResults.tsx
|
|
6708
|
-
import { Box as
|
|
6709
|
-
import
|
|
6710
|
-
import { jsx as
|
|
7001
|
+
import { Box as Box23, Text as Text21 } from "ink";
|
|
7002
|
+
import React20 from "react";
|
|
7003
|
+
import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
6711
7004
|
var formatStars = (value) => {
|
|
6712
7005
|
if (!value || value <= 0) return "";
|
|
6713
7006
|
if (value >= 1e3) {
|
|
@@ -6736,8 +7029,8 @@ var truncateLabel = (value, max = 100) => {
|
|
|
6736
7029
|
};
|
|
6737
7030
|
function FindSkillResultsScreen() {
|
|
6738
7031
|
const { findSkill, updateFindSkill, resetAddSkill, updateAddSkill, navigateTo, setFlash } = useNavigation();
|
|
6739
|
-
const [status, setStatus] =
|
|
6740
|
-
const [error, setError] =
|
|
7032
|
+
const [status, setStatus] = React20.useState("ready");
|
|
7033
|
+
const [error, setError] = React20.useState(null);
|
|
6741
7034
|
const spinner = useSpinnerFrame(status === "loading");
|
|
6742
7035
|
const results = findSkill.results ?? [];
|
|
6743
7036
|
const query = findSkill.query ?? "";
|
|
@@ -6775,36 +7068,36 @@ function FindSkillResultsScreen() {
|
|
|
6775
7068
|
setStatus("error");
|
|
6776
7069
|
}
|
|
6777
7070
|
};
|
|
6778
|
-
|
|
7071
|
+
React20.useEffect(() => {
|
|
6779
7072
|
if (results.length === 0) {
|
|
6780
7073
|
setStatus("ready");
|
|
6781
7074
|
}
|
|
6782
7075
|
}, [results.length]);
|
|
6783
7076
|
if (status === "loading") {
|
|
6784
|
-
return /* @__PURE__ */
|
|
6785
|
-
/* @__PURE__ */
|
|
6786
|
-
/* @__PURE__ */
|
|
7077
|
+
return /* @__PURE__ */ jsxs21(Box23, { flexDirection: "column", padding: 1, children: [
|
|
7078
|
+
/* @__PURE__ */ jsx25(Header, { title: "Preparing skills" }),
|
|
7079
|
+
/* @__PURE__ */ jsxs21(Text21, { children: [
|
|
6787
7080
|
spinner,
|
|
6788
7081
|
" Cloning repositories..."
|
|
6789
7082
|
] })
|
|
6790
7083
|
] });
|
|
6791
7084
|
}
|
|
6792
7085
|
if (results.length === 0) {
|
|
6793
|
-
return /* @__PURE__ */
|
|
6794
|
-
/* @__PURE__ */
|
|
6795
|
-
/* @__PURE__ */
|
|
6796
|
-
/* @__PURE__ */
|
|
7086
|
+
return /* @__PURE__ */ jsxs21(Box23, { flexDirection: "column", padding: 1, children: [
|
|
7087
|
+
/* @__PURE__ */ jsx25(Header, { title: "No results" }),
|
|
7088
|
+
/* @__PURE__ */ jsx25(Text21, { dimColor: true, children: "No skills found." }),
|
|
7089
|
+
/* @__PURE__ */ jsx25(Box23, { marginTop: 1, children: /* @__PURE__ */ jsx25(Text21, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
6797
7090
|
] });
|
|
6798
7091
|
}
|
|
6799
|
-
return /* @__PURE__ */
|
|
6800
|
-
/* @__PURE__ */
|
|
6801
|
-
/* @__PURE__ */
|
|
6802
|
-
/* @__PURE__ */
|
|
6803
|
-
/* @__PURE__ */
|
|
6804
|
-
/* @__PURE__ */
|
|
7092
|
+
return /* @__PURE__ */ jsxs21(Box23, { flexDirection: "column", padding: 1, children: [
|
|
7093
|
+
/* @__PURE__ */ jsx25(Header, { title: "Select skills" }),
|
|
7094
|
+
/* @__PURE__ */ jsxs21(Box23, { marginBottom: 1, flexDirection: "column", children: [
|
|
7095
|
+
/* @__PURE__ */ jsx25(Text21, { children: `Query: ${query}` }),
|
|
7096
|
+
/* @__PURE__ */ jsx25(Text21, { dimColor: true, children: `Mode: ${modeLabel} search` }),
|
|
7097
|
+
/* @__PURE__ */ jsx25(Text21, { dimColor: true, children: FIND_SKILLS_HINT })
|
|
6805
7098
|
] }),
|
|
6806
|
-
status === "error" ? /* @__PURE__ */
|
|
6807
|
-
/* @__PURE__ */
|
|
7099
|
+
status === "error" ? /* @__PURE__ */ jsx25(Box23, { marginBottom: 1, children: /* @__PURE__ */ jsx25(Text21, { color: "red", children: error }) }) : null,
|
|
7100
|
+
/* @__PURE__ */ jsx25(
|
|
6808
7101
|
MultiSelect,
|
|
6809
7102
|
{
|
|
6810
7103
|
items: results.map((result) => ({
|
|
@@ -6822,21 +7115,21 @@ function FindSkillResultsScreen() {
|
|
|
6822
7115
|
}
|
|
6823
7116
|
|
|
6824
7117
|
// src/tui/screens/FindSkillSearch.tsx
|
|
6825
|
-
import { Box as
|
|
7118
|
+
import { Box as Box24, Text as Text22, useInput as useInput5 } from "ink";
|
|
6826
7119
|
import TextInput4 from "ink-text-input";
|
|
6827
|
-
import
|
|
6828
|
-
import { jsx as
|
|
7120
|
+
import React21 from "react";
|
|
7121
|
+
import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
6829
7122
|
var MIN_QUERY_LENGTH = 2;
|
|
6830
7123
|
function getDebounceMs(queryLength) {
|
|
6831
7124
|
return Math.max(150, 350 - queryLength * 50);
|
|
6832
7125
|
}
|
|
6833
7126
|
function FindSkillSearchScreen() {
|
|
6834
7127
|
const { findSkill, updateFindSkill, navigateTo, setFlash } = useNavigation();
|
|
6835
|
-
const [value, setValue] =
|
|
6836
|
-
const [status, setStatus] =
|
|
6837
|
-
const [error, setError] =
|
|
6838
|
-
const [preview, setPreview] =
|
|
6839
|
-
const debounceRef =
|
|
7128
|
+
const [value, setValue] = React21.useState(findSkill.query ?? "");
|
|
7129
|
+
const [status, setStatus] = React21.useState("idle");
|
|
7130
|
+
const [error, setError] = React21.useState(null);
|
|
7131
|
+
const [preview, setPreview] = React21.useState([]);
|
|
7132
|
+
const debounceRef = React21.useRef(null);
|
|
6840
7133
|
const spinner = useSpinnerFrame(status === "searching" || status === "loading");
|
|
6841
7134
|
const { wrapOnChange } = useTextInput({
|
|
6842
7135
|
disabled: status === "loading",
|
|
@@ -6847,7 +7140,7 @@ function FindSkillSearchScreen() {
|
|
|
6847
7140
|
updateFindSkill({ query: "" });
|
|
6848
7141
|
}
|
|
6849
7142
|
});
|
|
6850
|
-
const triggerLiveSearch =
|
|
7143
|
+
const triggerLiveSearch = React21.useCallback((query) => {
|
|
6851
7144
|
if (debounceRef.current) {
|
|
6852
7145
|
clearTimeout(debounceRef.current);
|
|
6853
7146
|
debounceRef.current = null;
|
|
@@ -6871,14 +7164,14 @@ function FindSkillSearchScreen() {
|
|
|
6871
7164
|
}
|
|
6872
7165
|
}, debounceMs);
|
|
6873
7166
|
}, []);
|
|
6874
|
-
|
|
7167
|
+
React21.useEffect(() => {
|
|
6875
7168
|
return () => {
|
|
6876
7169
|
if (debounceRef.current) {
|
|
6877
7170
|
clearTimeout(debounceRef.current);
|
|
6878
7171
|
}
|
|
6879
7172
|
};
|
|
6880
7173
|
}, []);
|
|
6881
|
-
const goToLexicalResults =
|
|
7174
|
+
const goToLexicalResults = React21.useCallback(async () => {
|
|
6882
7175
|
const query = value.trim();
|
|
6883
7176
|
if (!query || query.length < MIN_QUERY_LENGTH) {
|
|
6884
7177
|
setFlash(`Enter at least ${MIN_QUERY_LENGTH} characters.`);
|
|
@@ -6905,7 +7198,7 @@ function FindSkillSearchScreen() {
|
|
|
6905
7198
|
setStatus("error");
|
|
6906
7199
|
}
|
|
6907
7200
|
}, [value, setFlash, updateFindSkill, navigateTo]);
|
|
6908
|
-
const runSemanticSearch =
|
|
7201
|
+
const runSemanticSearch = React21.useCallback(async () => {
|
|
6909
7202
|
const query = value.trim();
|
|
6910
7203
|
if (!query) {
|
|
6911
7204
|
setFlash("Enter a search term.");
|
|
@@ -6950,12 +7243,12 @@ function FindSkillSearchScreen() {
|
|
|
6950
7243
|
});
|
|
6951
7244
|
const showPreview = preview.length > 0 && status !== "loading";
|
|
6952
7245
|
const showSearching = status === "searching" && value.trim().length >= MIN_QUERY_LENGTH;
|
|
6953
|
-
return /* @__PURE__ */
|
|
6954
|
-
/* @__PURE__ */
|
|
6955
|
-
/* @__PURE__ */
|
|
6956
|
-
/* @__PURE__ */
|
|
6957
|
-
/* @__PURE__ */
|
|
6958
|
-
/* @__PURE__ */
|
|
7246
|
+
return /* @__PURE__ */ jsxs22(Box24, { flexDirection: "column", padding: 1, children: [
|
|
7247
|
+
/* @__PURE__ */ jsx26(Header, { title: "Find skills" }),
|
|
7248
|
+
/* @__PURE__ */ jsx26(Box24, { marginBottom: 1, children: /* @__PURE__ */ jsx26(Text22, { children: "Find a skill to give your agent new capabilities." }) }),
|
|
7249
|
+
/* @__PURE__ */ jsxs22(Box24, { children: [
|
|
7250
|
+
/* @__PURE__ */ jsx26(Text22, { color: "green", children: "> " }),
|
|
7251
|
+
/* @__PURE__ */ jsx26(
|
|
6959
7252
|
TextInput4,
|
|
6960
7253
|
{
|
|
6961
7254
|
value,
|
|
@@ -6973,52 +7266,52 @@ function FindSkillSearchScreen() {
|
|
|
6973
7266
|
}
|
|
6974
7267
|
)
|
|
6975
7268
|
] }),
|
|
6976
|
-
showSearching && !showPreview ? /* @__PURE__ */
|
|
7269
|
+
showSearching && !showPreview ? /* @__PURE__ */ jsx26(Box24, { marginTop: 1, children: /* @__PURE__ */ jsxs22(Text22, { dimColor: true, children: [
|
|
6977
7270
|
spinner,
|
|
6978
7271
|
" Searching..."
|
|
6979
7272
|
] }) }) : null,
|
|
6980
|
-
showPreview ? /* @__PURE__ */
|
|
6981
|
-
/* @__PURE__ */
|
|
7273
|
+
showPreview ? /* @__PURE__ */ jsxs22(Box24, { flexDirection: "column", marginTop: 1, children: [
|
|
7274
|
+
/* @__PURE__ */ jsxs22(Text22, { dimColor: true, children: [
|
|
6982
7275
|
preview.length,
|
|
6983
7276
|
" result",
|
|
6984
7277
|
preview.length !== 1 ? "s" : "",
|
|
6985
7278
|
" found:"
|
|
6986
7279
|
] }),
|
|
6987
|
-
preview.slice(0, 3).map((result) => /* @__PURE__ */
|
|
7280
|
+
preview.slice(0, 3).map((result) => /* @__PURE__ */ jsxs22(Text22, { dimColor: true, children: [
|
|
6988
7281
|
" ",
|
|
6989
7282
|
"\u2022 ",
|
|
6990
7283
|
result.name,
|
|
6991
7284
|
result.repoOwner ? ` (${result.repoOwner}/${result.repoName})` : ""
|
|
6992
7285
|
] }, result.id)),
|
|
6993
|
-
preview.length > 3 ? /* @__PURE__ */
|
|
7286
|
+
preview.length > 3 ? /* @__PURE__ */ jsxs22(Text22, { dimColor: true, children: [
|
|
6994
7287
|
" ",
|
|
6995
7288
|
"... and ",
|
|
6996
7289
|
preview.length - 3,
|
|
6997
7290
|
" more"
|
|
6998
7291
|
] }) : null
|
|
6999
7292
|
] }) : null,
|
|
7000
|
-
status === "loading" ? /* @__PURE__ */
|
|
7293
|
+
status === "loading" ? /* @__PURE__ */ jsx26(Box24, { marginTop: 1, children: /* @__PURE__ */ jsxs22(Text22, { children: [
|
|
7001
7294
|
spinner,
|
|
7002
7295
|
" Running AI search..."
|
|
7003
7296
|
] }) }) : null,
|
|
7004
|
-
status === "error" ? /* @__PURE__ */
|
|
7005
|
-
/* @__PURE__ */
|
|
7006
|
-
/* @__PURE__ */
|
|
7297
|
+
status === "error" ? /* @__PURE__ */ jsx26(Box24, { marginTop: 1, children: /* @__PURE__ */ jsx26(Text22, { color: "red", children: error }) }) : null,
|
|
7298
|
+
/* @__PURE__ */ jsx26(Box24, { marginTop: 1, children: /* @__PURE__ */ jsx26(Text22, { dimColor: true, children: "Enter for fast results, Tab for AI search" }) }),
|
|
7299
|
+
/* @__PURE__ */ jsx26(Box24, { children: /* @__PURE__ */ jsx26(Text22, { dimColor: true, children: TEXT_INPUT_HINT }) })
|
|
7007
7300
|
] });
|
|
7008
7301
|
}
|
|
7009
7302
|
|
|
7010
7303
|
// src/tui/screens/GetUrl.tsx
|
|
7011
|
-
import { Box as
|
|
7012
|
-
import
|
|
7013
|
-
import { jsx as
|
|
7304
|
+
import { Box as Box25, Text as Text23, useApp } from "ink";
|
|
7305
|
+
import React22 from "react";
|
|
7306
|
+
import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
7014
7307
|
function GetUrlScreen() {
|
|
7015
7308
|
const { exit } = useApp();
|
|
7016
7309
|
const { invocation } = useNavigation();
|
|
7017
7310
|
const spinner = useSpinnerFrame(true);
|
|
7018
|
-
const didRun =
|
|
7311
|
+
const didRun = React22.useRef(false);
|
|
7019
7312
|
const outputPath = invocation.options?.output ?? null;
|
|
7020
7313
|
const outputFormat = invocation.options?.json ? "json" : "markdown";
|
|
7021
|
-
|
|
7314
|
+
React22.useEffect(() => {
|
|
7022
7315
|
let cancelled = false;
|
|
7023
7316
|
const run = async () => {
|
|
7024
7317
|
if (didRun.current) return;
|
|
@@ -7047,12 +7340,12 @@ function GetUrlScreen() {
|
|
|
7047
7340
|
cancelled = true;
|
|
7048
7341
|
};
|
|
7049
7342
|
}, [exit, invocation]);
|
|
7050
|
-
return /* @__PURE__ */
|
|
7051
|
-
/* @__PURE__ */
|
|
7052
|
-
invocation.source ? /* @__PURE__ */
|
|
7053
|
-
outputPath ? /* @__PURE__ */
|
|
7054
|
-
outputFormat === "json" ? /* @__PURE__ */
|
|
7055
|
-
/* @__PURE__ */
|
|
7343
|
+
return /* @__PURE__ */ jsxs23(Box25, { flexDirection: "column", padding: 1, children: [
|
|
7344
|
+
/* @__PURE__ */ jsx27(Header, { title: "Fetching URL" }),
|
|
7345
|
+
invocation.source ? /* @__PURE__ */ jsx27(Text23, { dimColor: true, children: `URL: ${invocation.source}` }) : null,
|
|
7346
|
+
outputPath ? /* @__PURE__ */ jsx27(Text23, { dimColor: true, children: `Output: ${outputPath}` }) : null,
|
|
7347
|
+
outputFormat === "json" ? /* @__PURE__ */ jsx27(Text23, { dimColor: true, children: "Format: json" }) : null,
|
|
7348
|
+
/* @__PURE__ */ jsxs23(Text23, { children: [
|
|
7056
7349
|
spinner,
|
|
7057
7350
|
" Fetching markdown..."
|
|
7058
7351
|
] })
|
|
@@ -7060,12 +7353,12 @@ function GetUrlScreen() {
|
|
|
7060
7353
|
}
|
|
7061
7354
|
|
|
7062
7355
|
// src/tui/screens/ListSkills.tsx
|
|
7063
|
-
import { Box as
|
|
7064
|
-
import
|
|
7356
|
+
import { Box as Box26, Text as Text24 } from "ink";
|
|
7357
|
+
import React23 from "react";
|
|
7065
7358
|
|
|
7066
7359
|
// src/installed-skills.ts
|
|
7067
7360
|
import { lstat as lstat2, readFile as readFile5, readdir as readdir4, stat as stat4 } from "fs/promises";
|
|
7068
|
-
import { basename as
|
|
7361
|
+
import { basename as basename7, join as join16 } from "path";
|
|
7069
7362
|
import matter8 from "gray-matter";
|
|
7070
7363
|
function getAgentSkillsDir(agent, scope, cwd) {
|
|
7071
7364
|
const config = agents[agent];
|
|
@@ -7153,7 +7446,7 @@ async function listSkillsForAgents(agentsList, scopes, cwd = process.cwd()) {
|
|
|
7153
7446
|
}
|
|
7154
7447
|
async function findSkillInstallations(skillName, scope, cwd = process.cwd()) {
|
|
7155
7448
|
const installs = [];
|
|
7156
|
-
const sanitized =
|
|
7449
|
+
const sanitized = basename7(getCanonicalPath(skillName, { global: scope === "global", cwd }));
|
|
7157
7450
|
if (!sanitized) {
|
|
7158
7451
|
return installs;
|
|
7159
7452
|
}
|
|
@@ -7176,12 +7469,12 @@ async function findSkillInstallations(skillName, scope, cwd = process.cwd()) {
|
|
|
7176
7469
|
}
|
|
7177
7470
|
|
|
7178
7471
|
// src/tui/screens/ListSkills.tsx
|
|
7179
|
-
import { jsx as
|
|
7472
|
+
import { jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
7180
7473
|
function ListScreen() {
|
|
7181
7474
|
const { navigateTo, setBackHandler } = useNavigation();
|
|
7182
|
-
const [summaries, setSummaries] =
|
|
7183
|
-
const [selectedAgent, setSelectedAgent] =
|
|
7184
|
-
|
|
7475
|
+
const [summaries, setSummaries] = React23.useState([]);
|
|
7476
|
+
const [selectedAgent, setSelectedAgent] = React23.useState(null);
|
|
7477
|
+
React23.useEffect(() => {
|
|
7185
7478
|
let cancelled = false;
|
|
7186
7479
|
const load = async () => {
|
|
7187
7480
|
const installed = await detectInstalledAgents();
|
|
@@ -7204,7 +7497,7 @@ function ListScreen() {
|
|
|
7204
7497
|
cancelled = true;
|
|
7205
7498
|
};
|
|
7206
7499
|
}, []);
|
|
7207
|
-
|
|
7500
|
+
React23.useEffect(() => {
|
|
7208
7501
|
if (!selectedAgent) {
|
|
7209
7502
|
setBackHandler(null);
|
|
7210
7503
|
return;
|
|
@@ -7219,17 +7512,17 @@ function ListScreen() {
|
|
|
7219
7512
|
}, [selectedAgent, setBackHandler]);
|
|
7220
7513
|
if (selectedAgent) {
|
|
7221
7514
|
const total = selectedAgent.projectSkills.length + selectedAgent.globalSkills.length;
|
|
7222
|
-
return /* @__PURE__ */
|
|
7223
|
-
/* @__PURE__ */
|
|
7224
|
-
selectedAgent.projectSkills.length > 0 ? /* @__PURE__ */
|
|
7225
|
-
/* @__PURE__ */
|
|
7226
|
-
selectedAgent.projectSkills.map((name) => /* @__PURE__ */
|
|
7515
|
+
return /* @__PURE__ */ jsxs24(Box26, { flexDirection: "column", padding: 1, children: [
|
|
7516
|
+
/* @__PURE__ */ jsx28(Header, { title: `${agents[selectedAgent.agent].displayName} (${total})` }),
|
|
7517
|
+
selectedAgent.projectSkills.length > 0 ? /* @__PURE__ */ jsxs24(Box26, { flexDirection: "column", marginBottom: 1, children: [
|
|
7518
|
+
/* @__PURE__ */ jsx28(Text24, { children: "Project" }),
|
|
7519
|
+
selectedAgent.projectSkills.map((name) => /* @__PURE__ */ jsx28(Text24, { dimColor: true, children: name }, `p-${name}`))
|
|
7227
7520
|
] }) : null,
|
|
7228
|
-
selectedAgent.globalSkills.length > 0 ? /* @__PURE__ */
|
|
7229
|
-
/* @__PURE__ */
|
|
7230
|
-
selectedAgent.globalSkills.map((name) => /* @__PURE__ */
|
|
7521
|
+
selectedAgent.globalSkills.length > 0 ? /* @__PURE__ */ jsxs24(Box26, { flexDirection: "column", marginBottom: 1, children: [
|
|
7522
|
+
/* @__PURE__ */ jsx28(Text24, { children: "Global" }),
|
|
7523
|
+
selectedAgent.globalSkills.map((name) => /* @__PURE__ */ jsx28(Text24, { dimColor: true, children: name }, `g-${name}`))
|
|
7231
7524
|
] }) : null,
|
|
7232
|
-
/* @__PURE__ */
|
|
7525
|
+
/* @__PURE__ */ jsx28(
|
|
7233
7526
|
SelectMenu,
|
|
7234
7527
|
{
|
|
7235
7528
|
items: [
|
|
@@ -7256,9 +7549,9 @@ function ListScreen() {
|
|
|
7256
7549
|
hint: `${count} skill${count !== 1 ? "s" : ""}`
|
|
7257
7550
|
};
|
|
7258
7551
|
});
|
|
7259
|
-
return /* @__PURE__ */
|
|
7260
|
-
/* @__PURE__ */
|
|
7261
|
-
/* @__PURE__ */
|
|
7552
|
+
return /* @__PURE__ */ jsxs24(Box26, { flexDirection: "column", padding: 1, children: [
|
|
7553
|
+
/* @__PURE__ */ jsx28(Header, { title: "Installed skills" }),
|
|
7554
|
+
/* @__PURE__ */ jsx28(
|
|
7262
7555
|
SelectMenu,
|
|
7263
7556
|
{
|
|
7264
7557
|
items,
|
|
@@ -7275,8 +7568,8 @@ function ListScreen() {
|
|
|
7275
7568
|
}
|
|
7276
7569
|
|
|
7277
7570
|
// src/tui/screens/MainMenu.tsx
|
|
7278
|
-
import { Box as
|
|
7279
|
-
import { jsx as
|
|
7571
|
+
import { Box as Box27 } from "ink";
|
|
7572
|
+
import { jsx as jsx29 } from "react/jsx-runtime";
|
|
7280
7573
|
function MainMenu() {
|
|
7281
7574
|
const { navigateTo, resetAddSkill, resetFindSkill, setInvocation } = useNavigation();
|
|
7282
7575
|
const items = [
|
|
@@ -7290,7 +7583,7 @@ function MainMenu() {
|
|
|
7290
7583
|
{ label: "Update docs", value: "update-docs" },
|
|
7291
7584
|
{ label: "Exit", value: "exit" }
|
|
7292
7585
|
];
|
|
7293
|
-
return /* @__PURE__ */
|
|
7586
|
+
return /* @__PURE__ */ jsx29(Box27, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx29(
|
|
7294
7587
|
SelectMenu,
|
|
7295
7588
|
{
|
|
7296
7589
|
items,
|
|
@@ -7345,16 +7638,16 @@ function MainMenu() {
|
|
|
7345
7638
|
// src/tui/screens/ManageSkills.tsx
|
|
7346
7639
|
import { rm as rm5 } from "fs/promises";
|
|
7347
7640
|
import chalk4 from "chalk";
|
|
7348
|
-
import { Box as
|
|
7349
|
-
import
|
|
7350
|
-
import { jsx as
|
|
7641
|
+
import { Box as Box28, Text as Text25 } from "ink";
|
|
7642
|
+
import React24 from "react";
|
|
7643
|
+
import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
7351
7644
|
function ManageScreen() {
|
|
7352
7645
|
const { navigateTo, setFlash, setBackHandler } = useNavigation();
|
|
7353
|
-
const [summaries, setSummaries] =
|
|
7354
|
-
const [selectedAgent, setSelectedAgent] =
|
|
7355
|
-
const [selectedSkills, setSelectedSkills] =
|
|
7356
|
-
const [isRemoving, setIsRemoving] =
|
|
7357
|
-
|
|
7646
|
+
const [summaries, setSummaries] = React24.useState([]);
|
|
7647
|
+
const [selectedAgent, setSelectedAgent] = React24.useState(null);
|
|
7648
|
+
const [selectedSkills, setSelectedSkills] = React24.useState(null);
|
|
7649
|
+
const [isRemoving, setIsRemoving] = React24.useState(false);
|
|
7650
|
+
React24.useEffect(() => {
|
|
7358
7651
|
let cancelled = false;
|
|
7359
7652
|
const load = async () => {
|
|
7360
7653
|
const installedAgents = await detectInstalledAgents();
|
|
@@ -7376,7 +7669,7 @@ function ManageScreen() {
|
|
|
7376
7669
|
cancelled = true;
|
|
7377
7670
|
};
|
|
7378
7671
|
}, [setFlash]);
|
|
7379
|
-
|
|
7672
|
+
React24.useEffect(() => {
|
|
7380
7673
|
if (isRemoving) {
|
|
7381
7674
|
setBackHandler(() => true);
|
|
7382
7675
|
return () => setBackHandler(null);
|
|
@@ -7399,16 +7692,16 @@ function ManageScreen() {
|
|
|
7399
7692
|
return () => setBackHandler(null);
|
|
7400
7693
|
}, [isRemoving, selectedSkills, selectedAgent, setBackHandler]);
|
|
7401
7694
|
if (summaries.length === 0) {
|
|
7402
|
-
return /* @__PURE__ */
|
|
7403
|
-
/* @__PURE__ */
|
|
7404
|
-
/* @__PURE__ */
|
|
7405
|
-
/* @__PURE__ */
|
|
7695
|
+
return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
|
|
7696
|
+
/* @__PURE__ */ jsx30(Header, { title: "Remove skills" }),
|
|
7697
|
+
/* @__PURE__ */ jsx30(Text25, { dimColor: true, children: "No skills found yet." }),
|
|
7698
|
+
/* @__PURE__ */ jsx30(Text25, { dimColor: true, children: BACK_QUIT_HINT })
|
|
7406
7699
|
] });
|
|
7407
7700
|
}
|
|
7408
7701
|
if (!selectedAgent) {
|
|
7409
|
-
return /* @__PURE__ */
|
|
7410
|
-
/* @__PURE__ */
|
|
7411
|
-
/* @__PURE__ */
|
|
7702
|
+
return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
|
|
7703
|
+
/* @__PURE__ */ jsx30(Header, { title: "Select agent" }),
|
|
7704
|
+
/* @__PURE__ */ jsx30(
|
|
7412
7705
|
SelectMenu,
|
|
7413
7706
|
{
|
|
7414
7707
|
items: summaries.map((summary) => ({
|
|
@@ -7425,9 +7718,9 @@ function ManageScreen() {
|
|
|
7425
7718
|
] });
|
|
7426
7719
|
}
|
|
7427
7720
|
if (!selectedSkills) {
|
|
7428
|
-
return /* @__PURE__ */
|
|
7429
|
-
/* @__PURE__ */
|
|
7430
|
-
/* @__PURE__ */
|
|
7721
|
+
return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
|
|
7722
|
+
/* @__PURE__ */ jsx30(Header, { title: `Remove skills (${agents[selectedAgent.agent].displayName})` }),
|
|
7723
|
+
/* @__PURE__ */ jsx30(
|
|
7431
7724
|
MultiSelect,
|
|
7432
7725
|
{
|
|
7433
7726
|
items: selectedAgent.skills.map((skill) => ({
|
|
@@ -7447,19 +7740,19 @@ function ManageScreen() {
|
|
|
7447
7740
|
] });
|
|
7448
7741
|
}
|
|
7449
7742
|
if (isRemoving) {
|
|
7450
|
-
return /* @__PURE__ */
|
|
7451
|
-
/* @__PURE__ */
|
|
7452
|
-
/* @__PURE__ */
|
|
7743
|
+
return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
|
|
7744
|
+
/* @__PURE__ */ jsx30(Header, { title: "Removing skills" }),
|
|
7745
|
+
/* @__PURE__ */ jsx30(Text25, { children: "Removing selected skills..." })
|
|
7453
7746
|
] });
|
|
7454
7747
|
}
|
|
7455
|
-
return /* @__PURE__ */
|
|
7456
|
-
/* @__PURE__ */
|
|
7457
|
-
selectedSkills.map((skill) => /* @__PURE__ */
|
|
7748
|
+
return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
|
|
7749
|
+
/* @__PURE__ */ jsx30(Header, { title: "Confirm removal" }),
|
|
7750
|
+
selectedSkills.map((skill) => /* @__PURE__ */ jsxs25(Text25, { children: [
|
|
7458
7751
|
formatSkillLabel(skill),
|
|
7459
7752
|
" ",
|
|
7460
7753
|
chalk4.dim(`(${skill.scope})`)
|
|
7461
7754
|
] }, `${skill.slug}-${skill.scope}`)),
|
|
7462
|
-
/* @__PURE__ */
|
|
7755
|
+
/* @__PURE__ */ jsx30(
|
|
7463
7756
|
SelectMenu,
|
|
7464
7757
|
{
|
|
7465
7758
|
items: [
|
|
@@ -7522,14 +7815,14 @@ function formatSkillLabel(skill) {
|
|
|
7522
7815
|
}
|
|
7523
7816
|
|
|
7524
7817
|
// src/tui/screens/MarketplacePlugins.tsx
|
|
7525
|
-
import { Box as
|
|
7526
|
-
import
|
|
7527
|
-
import { jsx as
|
|
7818
|
+
import { Box as Box29, Text as Text26 } from "ink";
|
|
7819
|
+
import React25 from "react";
|
|
7820
|
+
import { jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
7528
7821
|
function MarketplacePluginScreen() {
|
|
7529
7822
|
const { invocation, addSkill, updateAddSkill, navigateTo, setFlash } = useNavigation();
|
|
7530
7823
|
const plugins = addSkill.marketplace?.plugins ?? [];
|
|
7531
7824
|
const options = invocation.options;
|
|
7532
|
-
|
|
7825
|
+
React25.useEffect(() => {
|
|
7533
7826
|
if (plugins.length === 0) {
|
|
7534
7827
|
return;
|
|
7535
7828
|
}
|
|
@@ -7544,25 +7837,25 @@ function MarketplacePluginScreen() {
|
|
|
7544
7837
|
}
|
|
7545
7838
|
}, [plugins, options.yes, updateAddSkill, navigateTo, addSkill.marketplace]);
|
|
7546
7839
|
if (plugins.length === 0) {
|
|
7547
|
-
return /* @__PURE__ */
|
|
7548
|
-
/* @__PURE__ */
|
|
7549
|
-
/* @__PURE__ */
|
|
7550
|
-
/* @__PURE__ */
|
|
7840
|
+
return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
|
|
7841
|
+
/* @__PURE__ */ jsx31(AddFlowHeader, { title: "Marketplace plugins" }),
|
|
7842
|
+
/* @__PURE__ */ jsx31(Text26, { dimColor: true, children: "No plugins found." }),
|
|
7843
|
+
/* @__PURE__ */ jsx31(Text26, { dimColor: true, children: BACK_QUIT_HINT })
|
|
7551
7844
|
] });
|
|
7552
7845
|
}
|
|
7553
7846
|
if (options.list) {
|
|
7554
|
-
return /* @__PURE__ */
|
|
7555
|
-
/* @__PURE__ */
|
|
7556
|
-
plugins.map((plugin) => /* @__PURE__ */
|
|
7557
|
-
/* @__PURE__ */
|
|
7558
|
-
plugin.description ? /* @__PURE__ */
|
|
7847
|
+
return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
|
|
7848
|
+
/* @__PURE__ */ jsx31(AddFlowHeader, { title: `Marketplace plugins (${plugins.length})` }),
|
|
7849
|
+
plugins.map((plugin) => /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", marginBottom: 1, children: [
|
|
7850
|
+
/* @__PURE__ */ jsx31(Text26, { children: plugin.name }),
|
|
7851
|
+
plugin.description ? /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: plugin.description }) : null
|
|
7559
7852
|
] }, plugin.name)),
|
|
7560
|
-
/* @__PURE__ */
|
|
7853
|
+
/* @__PURE__ */ jsx31(Text26, { dimColor: true, children: BACK_QUIT_HINT })
|
|
7561
7854
|
] });
|
|
7562
7855
|
}
|
|
7563
|
-
return /* @__PURE__ */
|
|
7564
|
-
/* @__PURE__ */
|
|
7565
|
-
/* @__PURE__ */
|
|
7856
|
+
return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
|
|
7857
|
+
/* @__PURE__ */ jsx31(AddFlowHeader, { title: "Select plugins" }),
|
|
7858
|
+
/* @__PURE__ */ jsx31(
|
|
7566
7859
|
MultiSelect,
|
|
7567
7860
|
{
|
|
7568
7861
|
items: plugins.map((plugin) => ({
|
|
@@ -7589,8 +7882,8 @@ function MarketplacePluginScreen() {
|
|
|
7589
7882
|
}
|
|
7590
7883
|
|
|
7591
7884
|
// src/tui/screens/MarketplaceSkills.tsx
|
|
7592
|
-
import { Box as
|
|
7593
|
-
import
|
|
7885
|
+
import { Box as Box30, Text as Text27 } from "ink";
|
|
7886
|
+
import React26 from "react";
|
|
7594
7887
|
|
|
7595
7888
|
// src/flows/marketplace.ts
|
|
7596
7889
|
import { dirname as dirname7, join as join17, relative as relative4 } from "path";
|
|
@@ -7750,16 +8043,16 @@ function buildOriginMap(skills) {
|
|
|
7750
8043
|
}
|
|
7751
8044
|
|
|
7752
8045
|
// src/tui/screens/MarketplaceSkills.tsx
|
|
7753
|
-
import { jsx as
|
|
8046
|
+
import { jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
7754
8047
|
function MarketplaceSkillScreen() {
|
|
7755
8048
|
const { invocation, addSkill, updateAddSkill, navigateTo, setFlash } = useNavigation();
|
|
7756
8049
|
const options = invocation.options;
|
|
7757
|
-
const [status, setStatus] =
|
|
7758
|
-
const [error, setError] =
|
|
8050
|
+
const [status, setStatus] = React26.useState("loading");
|
|
8051
|
+
const [error, setError] = React26.useState(null);
|
|
7759
8052
|
const spinner = useSpinnerFrame(status === "loading");
|
|
7760
8053
|
const selectedPlugins = addSkill.marketplace?.selectedPlugins ?? [];
|
|
7761
8054
|
const context = addSkill.marketplace?.context;
|
|
7762
|
-
|
|
8055
|
+
React26.useEffect(() => {
|
|
7763
8056
|
let cancelled = false;
|
|
7764
8057
|
const load = async () => {
|
|
7765
8058
|
if (!context || selectedPlugins.length === 0) {
|
|
@@ -7823,27 +8116,27 @@ function MarketplaceSkillScreen() {
|
|
|
7823
8116
|
options.yes
|
|
7824
8117
|
]);
|
|
7825
8118
|
if (status === "loading") {
|
|
7826
|
-
return /* @__PURE__ */
|
|
7827
|
-
/* @__PURE__ */
|
|
7828
|
-
/* @__PURE__ */
|
|
8119
|
+
return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
|
|
8120
|
+
/* @__PURE__ */ jsx32(AddFlowHeader, { title: "Scanning marketplace" }),
|
|
8121
|
+
/* @__PURE__ */ jsxs27(Text27, { children: [
|
|
7829
8122
|
spinner,
|
|
7830
8123
|
" Discovering skills from plugins..."
|
|
7831
8124
|
] })
|
|
7832
8125
|
] });
|
|
7833
8126
|
}
|
|
7834
8127
|
if (status === "error") {
|
|
7835
|
-
return /* @__PURE__ */
|
|
7836
|
-
/* @__PURE__ */
|
|
7837
|
-
/* @__PURE__ */
|
|
7838
|
-
/* @__PURE__ */
|
|
8128
|
+
return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
|
|
8129
|
+
/* @__PURE__ */ jsx32(AddFlowHeader, { title: "Marketplace scan failed" }),
|
|
8130
|
+
/* @__PURE__ */ jsx32(Text27, { color: "red", children: error }),
|
|
8131
|
+
/* @__PURE__ */ jsx32(Text27, { dimColor: true, children: BACK_QUIT_HINT })
|
|
7839
8132
|
] });
|
|
7840
8133
|
}
|
|
7841
8134
|
const skills = addSkill.marketplace?.skills ?? [];
|
|
7842
8135
|
const warnings = addSkill.marketplace?.warnings ?? [];
|
|
7843
|
-
return /* @__PURE__ */
|
|
7844
|
-
/* @__PURE__ */
|
|
7845
|
-
warnings.length > 0 ? /* @__PURE__ */
|
|
7846
|
-
/* @__PURE__ */
|
|
8136
|
+
return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
|
|
8137
|
+
/* @__PURE__ */ jsx32(AddFlowHeader, { title: "Select skills" }),
|
|
8138
|
+
warnings.length > 0 ? /* @__PURE__ */ jsx32(Box30, { flexDirection: "column", marginBottom: 1, children: warnings.map((warning) => /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: warning }, warning)) }) : null,
|
|
8139
|
+
/* @__PURE__ */ jsx32(
|
|
7847
8140
|
MultiSelect,
|
|
7848
8141
|
{
|
|
7849
8142
|
items: skills.map((entry) => ({
|
|
@@ -7893,8 +8186,8 @@ function autoSelect2(skills, names, yes) {
|
|
|
7893
8186
|
// src/tui/screens/ScanSkills.tsx
|
|
7894
8187
|
import { rm as rm6 } from "fs/promises";
|
|
7895
8188
|
import chalk5 from "chalk";
|
|
7896
|
-
import { Box as
|
|
7897
|
-
import
|
|
8189
|
+
import { Box as Box31, Text as Text28 } from "ink";
|
|
8190
|
+
import React27 from "react";
|
|
7898
8191
|
|
|
7899
8192
|
// src/flows/scan-installed-skills.ts
|
|
7900
8193
|
import { existsSync as existsSync7 } from "fs";
|
|
@@ -8117,17 +8410,17 @@ function removalTargetsForRow(row, cwd) {
|
|
|
8117
8410
|
}
|
|
8118
8411
|
|
|
8119
8412
|
// src/tui/screens/ScanSkills.tsx
|
|
8120
|
-
import { Fragment as Fragment3, jsx as
|
|
8413
|
+
import { Fragment as Fragment3, jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
8121
8414
|
function ScanSkillsScreen() {
|
|
8122
8415
|
const { setFlash, setBackHandler } = useNavigation();
|
|
8123
|
-
const [view, setView] =
|
|
8124
|
-
const [error, setError] =
|
|
8125
|
-
const [rows, setRows] =
|
|
8126
|
-
const [progress, setProgress] =
|
|
8127
|
-
const [selected, setSelected] =
|
|
8128
|
-
const [removeTargets, setRemoveTargets] =
|
|
8416
|
+
const [view, setView] = React27.useState("loading");
|
|
8417
|
+
const [error, setError] = React27.useState(null);
|
|
8418
|
+
const [rows, setRows] = React27.useState([]);
|
|
8419
|
+
const [progress, setProgress] = React27.useState(null);
|
|
8420
|
+
const [selected, setSelected] = React27.useState(null);
|
|
8421
|
+
const [removeTargets, setRemoveTargets] = React27.useState(null);
|
|
8129
8422
|
const spinner = useSpinnerFrame(view === "running" || view === "removing");
|
|
8130
|
-
|
|
8423
|
+
React27.useEffect(() => {
|
|
8131
8424
|
let cancelled = false;
|
|
8132
8425
|
const run = async () => {
|
|
8133
8426
|
try {
|
|
@@ -8197,7 +8490,7 @@ function ScanSkillsScreen() {
|
|
|
8197
8490
|
cancelled = true;
|
|
8198
8491
|
};
|
|
8199
8492
|
}, []);
|
|
8200
|
-
|
|
8493
|
+
React27.useEffect(() => {
|
|
8201
8494
|
if (view === "actions" || view === "confirm-remove" || view === "removing") {
|
|
8202
8495
|
setBackHandler(() => {
|
|
8203
8496
|
if (view === "confirm-remove") {
|
|
@@ -8217,26 +8510,26 @@ function ScanSkillsScreen() {
|
|
|
8217
8510
|
setBackHandler(null);
|
|
8218
8511
|
return () => setBackHandler(null);
|
|
8219
8512
|
}, [view, setBackHandler]);
|
|
8220
|
-
const riskyRows =
|
|
8221
|
-
const summary =
|
|
8513
|
+
const riskyRows = React27.useMemo(() => rows.filter(isRisky), [rows]);
|
|
8514
|
+
const summary = React27.useMemo(() => scanSummary(rows), [rows]);
|
|
8222
8515
|
if (view === "empty") {
|
|
8223
|
-
return /* @__PURE__ */
|
|
8224
|
-
/* @__PURE__ */
|
|
8225
|
-
/* @__PURE__ */
|
|
8516
|
+
return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
|
|
8517
|
+
/* @__PURE__ */ jsx33(Header, { title: "Scan skills" }),
|
|
8518
|
+
/* @__PURE__ */ jsx33(Text28, { dimColor: true, children: rows.length === 0 ? "No skills found to scan (project + global)." : `Scanned ${rows.length} skill${rows.length === 1 ? "" : "s"}. No risks found.` })
|
|
8226
8519
|
] });
|
|
8227
8520
|
}
|
|
8228
8521
|
if (view === "loading") {
|
|
8229
|
-
return /* @__PURE__ */
|
|
8230
|
-
/* @__PURE__ */
|
|
8231
|
-
/* @__PURE__ */
|
|
8522
|
+
return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
|
|
8523
|
+
/* @__PURE__ */ jsx33(Header, { title: "Scan skills" }),
|
|
8524
|
+
/* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "Discovering skills..." })
|
|
8232
8525
|
] });
|
|
8233
8526
|
}
|
|
8234
8527
|
if (view === "running") {
|
|
8235
8528
|
const completed = progress?.completed ?? 0;
|
|
8236
8529
|
const total = progress?.total ?? 0;
|
|
8237
|
-
return /* @__PURE__ */
|
|
8238
|
-
/* @__PURE__ */
|
|
8239
|
-
/* @__PURE__ */
|
|
8530
|
+
return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
|
|
8531
|
+
/* @__PURE__ */ jsx33(Header, { title: "Scan skills" }),
|
|
8532
|
+
/* @__PURE__ */ jsxs28(Text28, { children: [
|
|
8240
8533
|
spinner,
|
|
8241
8534
|
" Scanning ",
|
|
8242
8535
|
completed,
|
|
@@ -8246,14 +8539,14 @@ function ScanSkillsScreen() {
|
|
|
8246
8539
|
total === 1 ? "" : "s",
|
|
8247
8540
|
"..."
|
|
8248
8541
|
] }),
|
|
8249
|
-
/* @__PURE__ */
|
|
8542
|
+
/* @__PURE__ */ jsx33(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
8250
8543
|
] });
|
|
8251
8544
|
}
|
|
8252
8545
|
if (view === "error") {
|
|
8253
|
-
return /* @__PURE__ */
|
|
8254
|
-
/* @__PURE__ */
|
|
8255
|
-
/* @__PURE__ */
|
|
8256
|
-
/* @__PURE__ */
|
|
8546
|
+
return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
|
|
8547
|
+
/* @__PURE__ */ jsx33(Header, { title: "Scan skills" }),
|
|
8548
|
+
/* @__PURE__ */ jsx33(Text28, { color: "red", children: error ?? "Scan failed" }),
|
|
8549
|
+
/* @__PURE__ */ jsx33(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
8257
8550
|
] });
|
|
8258
8551
|
}
|
|
8259
8552
|
if (view === "actions" && selected) {
|
|
@@ -8264,27 +8557,27 @@ function ScanSkillsScreen() {
|
|
|
8264
8557
|
const top = selected.topSignals?.slice(0, 10) ?? [];
|
|
8265
8558
|
const locationLabels = selected.skill.locations.map((l) => l.label);
|
|
8266
8559
|
const riskColor = level === "critical" || level === "high" ? "red" : level === "medium" ? "yellow" : level === "low" ? "green" : "gray";
|
|
8267
|
-
return /* @__PURE__ */
|
|
8268
|
-
/* @__PURE__ */
|
|
8269
|
-
/* @__PURE__ */
|
|
8270
|
-
/* @__PURE__ */
|
|
8560
|
+
return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
|
|
8561
|
+
/* @__PURE__ */ jsx33(Header, { title: "Skill risk details" }),
|
|
8562
|
+
/* @__PURE__ */ jsxs28(Text28, { children: [
|
|
8563
|
+
/* @__PURE__ */ jsx33(Text28, { bold: true, children: selected.skill.name }),
|
|
8271
8564
|
" ",
|
|
8272
|
-
/* @__PURE__ */
|
|
8565
|
+
/* @__PURE__ */ jsx33(Text28, { dimColor: true, children: `(${selected.skill.slug})` })
|
|
8273
8566
|
] }),
|
|
8274
|
-
selected.error ? /* @__PURE__ */
|
|
8275
|
-
/* @__PURE__ */
|
|
8276
|
-
/* @__PURE__ */
|
|
8567
|
+
selected.error ? /* @__PURE__ */ jsx33(Text28, { color: "red", children: selected.error }) : /* @__PURE__ */ jsxs28(Fragment3, { children: [
|
|
8568
|
+
/* @__PURE__ */ jsxs28(Text28, { children: [
|
|
8569
|
+
/* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "Verdict:" }),
|
|
8277
8570
|
" ",
|
|
8278
|
-
/* @__PURE__ */
|
|
8279
|
-
/* @__PURE__ */
|
|
8571
|
+
/* @__PURE__ */ jsx33(Text28, { color: riskColor, children: verdict }),
|
|
8572
|
+
/* @__PURE__ */ jsx33(Text28, { dimColor: true, children: ` \u2022 level=${level} score=${score} issues=${issues}` })
|
|
8280
8573
|
] }),
|
|
8281
|
-
top.length > 0 ? /* @__PURE__ */
|
|
8282
|
-
selected.ruleset ? /* @__PURE__ */
|
|
8574
|
+
top.length > 0 ? /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: `Top signals: ${top.join(", ")}` }) : null,
|
|
8575
|
+
selected.ruleset ? /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: `Ruleset: ${selected.ruleset}` }) : null
|
|
8283
8576
|
] }),
|
|
8284
|
-
selected.skill.description ? /* @__PURE__ */
|
|
8285
|
-
/* @__PURE__ */
|
|
8286
|
-
locationLabels.length > 0 ? /* @__PURE__ */
|
|
8287
|
-
/* @__PURE__ */
|
|
8577
|
+
selected.skill.description ? /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: selected.skill.description }) : null,
|
|
8578
|
+
/* @__PURE__ */ jsx33(Text28, { dimColor: true, children: `Path: ${selected.skill.path}` }),
|
|
8579
|
+
locationLabels.length > 0 ? /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: `Locations: ${locationLabels.join(", ")}` }) : null,
|
|
8580
|
+
/* @__PURE__ */ jsx33(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx33(
|
|
8288
8581
|
SelectMenu,
|
|
8289
8582
|
{
|
|
8290
8583
|
items: [
|
|
@@ -8310,17 +8603,17 @@ function ScanSkillsScreen() {
|
|
|
8310
8603
|
}
|
|
8311
8604
|
if (view === "confirm-remove" && selected && removeTargets) {
|
|
8312
8605
|
const title = `Remove ${selected.skill.name}`;
|
|
8313
|
-
return /* @__PURE__ */
|
|
8314
|
-
/* @__PURE__ */
|
|
8315
|
-
/* @__PURE__ */
|
|
8316
|
-
/* @__PURE__ */
|
|
8317
|
-
/* @__PURE__ */
|
|
8606
|
+
return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
|
|
8607
|
+
/* @__PURE__ */ jsx33(Header, { title }),
|
|
8608
|
+
/* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "These locations will be removed:" }),
|
|
8609
|
+
/* @__PURE__ */ jsx33(Box31, { flexDirection: "column", marginTop: 1, children: removeTargets.length === 0 ? /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "None found." }) : removeTargets.map((t) => /* @__PURE__ */ jsxs28(Text28, { children: [
|
|
8610
|
+
/* @__PURE__ */ jsx33(Text28, { children: chalk5.red("\u2022") }),
|
|
8318
8611
|
" ",
|
|
8319
|
-
/* @__PURE__ */
|
|
8612
|
+
/* @__PURE__ */ jsx33(Text28, { dimColor: true, children: t.label }),
|
|
8320
8613
|
" ",
|
|
8321
8614
|
t.path
|
|
8322
8615
|
] }, t.path)) }),
|
|
8323
|
-
/* @__PURE__ */
|
|
8616
|
+
/* @__PURE__ */ jsx33(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx33(
|
|
8324
8617
|
SelectMenu,
|
|
8325
8618
|
{
|
|
8326
8619
|
items: [
|
|
@@ -8368,33 +8661,33 @@ function ScanSkillsScreen() {
|
|
|
8368
8661
|
] });
|
|
8369
8662
|
}
|
|
8370
8663
|
if (view === "removing") {
|
|
8371
|
-
return /* @__PURE__ */
|
|
8372
|
-
/* @__PURE__ */
|
|
8373
|
-
/* @__PURE__ */
|
|
8664
|
+
return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
|
|
8665
|
+
/* @__PURE__ */ jsx33(Header, { title: "Removing skill" }),
|
|
8666
|
+
/* @__PURE__ */ jsxs28(Text28, { children: [
|
|
8374
8667
|
spinner,
|
|
8375
8668
|
" Removing..."
|
|
8376
8669
|
] }),
|
|
8377
|
-
/* @__PURE__ */
|
|
8670
|
+
/* @__PURE__ */ jsx33(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
8378
8671
|
] });
|
|
8379
8672
|
}
|
|
8380
8673
|
if (riskyRows.length === 0) {
|
|
8381
|
-
return /* @__PURE__ */
|
|
8382
|
-
/* @__PURE__ */
|
|
8383
|
-
/* @__PURE__ */
|
|
8674
|
+
return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
|
|
8675
|
+
/* @__PURE__ */ jsx33(Header, { title: "Scan skills" }),
|
|
8676
|
+
/* @__PURE__ */ jsx33(Text28, { dimColor: true, children: rows.length === 0 ? "No skills found to scan (project + global)." : `Scanned ${rows.length} skill${rows.length === 1 ? "" : "s"}. No risks found.` })
|
|
8384
8677
|
] });
|
|
8385
8678
|
}
|
|
8386
|
-
return /* @__PURE__ */
|
|
8387
|
-
/* @__PURE__ */
|
|
8388
|
-
/* @__PURE__ */
|
|
8389
|
-
/* @__PURE__ */
|
|
8390
|
-
/* @__PURE__ */
|
|
8391
|
-
/* @__PURE__ */
|
|
8392
|
-
/* @__PURE__ */
|
|
8393
|
-
/* @__PURE__ */
|
|
8394
|
-
/* @__PURE__ */
|
|
8679
|
+
return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
|
|
8680
|
+
/* @__PURE__ */ jsx33(Header, { title: "Scan skills" }),
|
|
8681
|
+
/* @__PURE__ */ jsxs28(Box31, { marginBottom: 1, flexDirection: "column", children: [
|
|
8682
|
+
/* @__PURE__ */ jsx33(Text28, { dimColor: true, children: `Scanned ${plural(summary.total, "skill")}.` }),
|
|
8683
|
+
/* @__PURE__ */ jsxs28(Text28, { children: [
|
|
8684
|
+
/* @__PURE__ */ jsx33(Text28, { color: "red", children: plural(summary.high, "high risk") }),
|
|
8685
|
+
/* @__PURE__ */ jsx33(Text28, { children: ", " }),
|
|
8686
|
+
/* @__PURE__ */ jsx33(Text28, { color: "yellow", children: plural(summary.medium, "medium risk") }),
|
|
8687
|
+
/* @__PURE__ */ jsx33(Text28, { children: " detected." })
|
|
8395
8688
|
] })
|
|
8396
8689
|
] }),
|
|
8397
|
-
/* @__PURE__ */
|
|
8690
|
+
/* @__PURE__ */ jsx33(
|
|
8398
8691
|
SingleSelect,
|
|
8399
8692
|
{
|
|
8400
8693
|
items: riskyRows.map((row) => ({
|
|
@@ -8415,8 +8708,8 @@ function ScanSkillsScreen() {
|
|
|
8415
8708
|
}
|
|
8416
8709
|
|
|
8417
8710
|
// src/tui/screens/UpdateDocs.tsx
|
|
8418
|
-
import { Box as
|
|
8419
|
-
import
|
|
8711
|
+
import { Box as Box32, Text as Text29 } from "ink";
|
|
8712
|
+
import React28 from "react";
|
|
8420
8713
|
|
|
8421
8714
|
// src/docs/update.ts
|
|
8422
8715
|
import { readdir as readdir6, stat as stat6 } from "fs/promises";
|
|
@@ -8482,12 +8775,12 @@ async function updateDocs(cwd = process.cwd()) {
|
|
|
8482
8775
|
}
|
|
8483
8776
|
|
|
8484
8777
|
// src/tui/screens/UpdateDocs.tsx
|
|
8485
|
-
import { jsx as
|
|
8778
|
+
import { jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
8486
8779
|
function UpdateDocsScreen() {
|
|
8487
|
-
const [status, setStatus] =
|
|
8488
|
-
const [summary, setSummary] =
|
|
8780
|
+
const [status, setStatus] = React28.useState("running");
|
|
8781
|
+
const [summary, setSummary] = React28.useState(null);
|
|
8489
8782
|
const spinner = useSpinnerFrame(status === "running");
|
|
8490
|
-
|
|
8783
|
+
React28.useEffect(() => {
|
|
8491
8784
|
let cancelled = false;
|
|
8492
8785
|
const run = async () => {
|
|
8493
8786
|
const output2 = await updateDocs();
|
|
@@ -8505,60 +8798,60 @@ function UpdateDocsScreen() {
|
|
|
8505
8798
|
};
|
|
8506
8799
|
}, []);
|
|
8507
8800
|
if (status === "running") {
|
|
8508
|
-
return /* @__PURE__ */
|
|
8509
|
-
/* @__PURE__ */
|
|
8510
|
-
/* @__PURE__ */
|
|
8801
|
+
return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
|
|
8802
|
+
/* @__PURE__ */ jsx34(Header, { title: "Updating docs" }),
|
|
8803
|
+
/* @__PURE__ */ jsxs29(Text29, { children: [
|
|
8511
8804
|
spinner,
|
|
8512
8805
|
" Pulling latest docs..."
|
|
8513
8806
|
] })
|
|
8514
8807
|
] });
|
|
8515
8808
|
}
|
|
8516
8809
|
if (status === "empty") {
|
|
8517
|
-
return /* @__PURE__ */
|
|
8518
|
-
/* @__PURE__ */
|
|
8519
|
-
/* @__PURE__ */
|
|
8520
|
-
/* @__PURE__ */
|
|
8810
|
+
return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
|
|
8811
|
+
/* @__PURE__ */ jsx34(Header, { title: "Update docs" }),
|
|
8812
|
+
/* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "No docs installed yet." }),
|
|
8813
|
+
/* @__PURE__ */ jsx34(Box32, { marginTop: 1, children: /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
8521
8814
|
] });
|
|
8522
8815
|
}
|
|
8523
8816
|
if (!summary) {
|
|
8524
|
-
return /* @__PURE__ */
|
|
8525
|
-
/* @__PURE__ */
|
|
8526
|
-
/* @__PURE__ */
|
|
8817
|
+
return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
|
|
8818
|
+
/* @__PURE__ */ jsx34(Header, { title: "Update docs" }),
|
|
8819
|
+
/* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "Nothing to update." })
|
|
8527
8820
|
] });
|
|
8528
8821
|
}
|
|
8529
8822
|
const cwd = process.cwd();
|
|
8530
|
-
return /* @__PURE__ */
|
|
8531
|
-
/* @__PURE__ */
|
|
8532
|
-
summary.updated.length > 0 ? /* @__PURE__ */
|
|
8533
|
-
/* @__PURE__ */
|
|
8534
|
-
summary.updated.map((item) => /* @__PURE__ */
|
|
8823
|
+
return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
|
|
8824
|
+
/* @__PURE__ */ jsx34(Header, { title: "Docs update results" }),
|
|
8825
|
+
summary.updated.length > 0 ? /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", marginBottom: 1, children: [
|
|
8826
|
+
/* @__PURE__ */ jsx34(Text29, { children: `Updated ${summary.updated.length} repo${summary.updated.length !== 1 ? "s" : ""}` }),
|
|
8827
|
+
summary.updated.map((item) => /* @__PURE__ */ jsxs29(Text29, { dimColor: true, children: [
|
|
8535
8828
|
item.name,
|
|
8536
8829
|
" \u2192 ",
|
|
8537
8830
|
shortenPath(item.path, cwd)
|
|
8538
8831
|
] }, `updated-${item.name}`))
|
|
8539
8832
|
] }) : null,
|
|
8540
|
-
summary.skipped.length > 0 ? /* @__PURE__ */
|
|
8541
|
-
/* @__PURE__ */
|
|
8542
|
-
summary.skipped.map((item) => /* @__PURE__ */
|
|
8833
|
+
summary.skipped.length > 0 ? /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", marginBottom: 1, children: [
|
|
8834
|
+
/* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "Skipped" }),
|
|
8835
|
+
summary.skipped.map((item) => /* @__PURE__ */ jsxs29(Text29, { dimColor: true, children: [
|
|
8543
8836
|
item.name,
|
|
8544
8837
|
item.message ? ` (${item.message})` : ""
|
|
8545
8838
|
] }, `skipped-${item.name}`))
|
|
8546
8839
|
] }) : null,
|
|
8547
|
-
summary.failed.length > 0 ? /* @__PURE__ */
|
|
8548
|
-
/* @__PURE__ */
|
|
8549
|
-
summary.failed.map((item) => /* @__PURE__ */
|
|
8840
|
+
summary.failed.length > 0 ? /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", marginBottom: 1, children: [
|
|
8841
|
+
/* @__PURE__ */ jsx34(Text29, { color: "red", children: "Failed" }),
|
|
8842
|
+
summary.failed.map((item) => /* @__PURE__ */ jsxs29(Text29, { color: "red", children: [
|
|
8550
8843
|
item.name,
|
|
8551
8844
|
item.message ? ` (${item.message})` : ""
|
|
8552
8845
|
] }, `failed-${item.name}`))
|
|
8553
8846
|
] }) : null,
|
|
8554
|
-
/* @__PURE__ */
|
|
8847
|
+
/* @__PURE__ */ jsx34(Box32, { marginTop: 1, children: /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
8555
8848
|
] });
|
|
8556
8849
|
}
|
|
8557
8850
|
|
|
8558
8851
|
// src/tui/screens/UpdateSkills.tsx
|
|
8559
8852
|
import chalk6 from "chalk";
|
|
8560
|
-
import { Box as
|
|
8561
|
-
import
|
|
8853
|
+
import { Box as Box33, Text as Text30, useInput as useInput6 } from "ink";
|
|
8854
|
+
import React29 from "react";
|
|
8562
8855
|
|
|
8563
8856
|
// src/flows/update-skills.ts
|
|
8564
8857
|
import { randomUUID } from "crypto";
|
|
@@ -8949,15 +9242,15 @@ async function updateSkills(targets) {
|
|
|
8949
9242
|
}
|
|
8950
9243
|
|
|
8951
9244
|
// src/tui/screens/UpdateSkills.tsx
|
|
8952
|
-
import { jsx as
|
|
9245
|
+
import { jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
8953
9246
|
function UpdateScreen() {
|
|
8954
9247
|
const { invocation, navigateTo, setFlash } = useNavigation();
|
|
8955
|
-
const [status, setStatus] =
|
|
8956
|
-
const [targets, setTargets] =
|
|
8957
|
-
const [selected, setSelected] =
|
|
8958
|
-
const [summary, setSummary] =
|
|
8959
|
-
const [showOnlyNeeds, setShowOnlyNeeds] =
|
|
8960
|
-
const [rateLimited, setRateLimited] =
|
|
9248
|
+
const [status, setStatus] = React29.useState("loading");
|
|
9249
|
+
const [targets, setTargets] = React29.useState([]);
|
|
9250
|
+
const [selected, setSelected] = React29.useState([]);
|
|
9251
|
+
const [summary, setSummary] = React29.useState(null);
|
|
9252
|
+
const [showOnlyNeeds, setShowOnlyNeeds] = React29.useState(false);
|
|
9253
|
+
const [rateLimited, setRateLimited] = React29.useState(false);
|
|
8961
9254
|
const spinner = useSpinnerFrame(status === "running");
|
|
8962
9255
|
useInput6((input) => {
|
|
8963
9256
|
if (status !== "select") return;
|
|
@@ -8965,7 +9258,7 @@ function UpdateScreen() {
|
|
|
8965
9258
|
setShowOnlyNeeds((prev) => !prev);
|
|
8966
9259
|
}
|
|
8967
9260
|
});
|
|
8968
|
-
|
|
9261
|
+
React29.useEffect(() => {
|
|
8969
9262
|
let cancelled = false;
|
|
8970
9263
|
const load = async () => {
|
|
8971
9264
|
const scopes = resolveScopes(invocation.options);
|
|
@@ -9007,7 +9300,7 @@ function UpdateScreen() {
|
|
|
9007
9300
|
cancelled = true;
|
|
9008
9301
|
};
|
|
9009
9302
|
}, [invocation, setFlash]);
|
|
9010
|
-
|
|
9303
|
+
React29.useEffect(() => {
|
|
9011
9304
|
let cancelled = false;
|
|
9012
9305
|
const run = async () => {
|
|
9013
9306
|
if (status !== "running" || selected.length === 0) return;
|
|
@@ -9022,16 +9315,16 @@ function UpdateScreen() {
|
|
|
9022
9315
|
};
|
|
9023
9316
|
}, [status, selected]);
|
|
9024
9317
|
if (status === "empty") {
|
|
9025
|
-
return /* @__PURE__ */
|
|
9026
|
-
/* @__PURE__ */
|
|
9027
|
-
/* @__PURE__ */
|
|
9028
|
-
/* @__PURE__ */
|
|
9318
|
+
return /* @__PURE__ */ jsxs30(Box33, { flexDirection: "column", padding: 1, children: [
|
|
9319
|
+
/* @__PURE__ */ jsx35(Header, { title: "Update skills" }),
|
|
9320
|
+
/* @__PURE__ */ jsx35(Text30, { dimColor: true, children: "No tracked skills to update yet." }),
|
|
9321
|
+
/* @__PURE__ */ jsx35(Text30, { dimColor: true, children: "Re-install a skill once to enable updates." })
|
|
9029
9322
|
] });
|
|
9030
9323
|
}
|
|
9031
9324
|
if (status === "loading") {
|
|
9032
|
-
return /* @__PURE__ */
|
|
9033
|
-
/* @__PURE__ */
|
|
9034
|
-
/* @__PURE__ */
|
|
9325
|
+
return /* @__PURE__ */ jsxs30(Box33, { flexDirection: "column", padding: 1, children: [
|
|
9326
|
+
/* @__PURE__ */ jsx35(Header, { title: "Update skills" }),
|
|
9327
|
+
/* @__PURE__ */ jsx35(Text30, { dimColor: true, children: "Loading tracked skills..." })
|
|
9035
9328
|
] });
|
|
9036
9329
|
}
|
|
9037
9330
|
if (status === "select") {
|
|
@@ -9039,17 +9332,17 @@ function UpdateScreen() {
|
|
|
9039
9332
|
const defaults = selected;
|
|
9040
9333
|
const hint = showOnlyNeeds ? UPDATE_HINT_NEEDS_ONLY : UPDATE_HINT_ALL;
|
|
9041
9334
|
if (showOnlyNeeds && visibleTargets.length === 0) {
|
|
9042
|
-
return /* @__PURE__ */
|
|
9043
|
-
/* @__PURE__ */
|
|
9044
|
-
/* @__PURE__ */
|
|
9045
|
-
rateLimited ? /* @__PURE__ */
|
|
9046
|
-
/* @__PURE__ */
|
|
9335
|
+
return /* @__PURE__ */ jsxs30(Box33, { flexDirection: "column", padding: 1, children: [
|
|
9336
|
+
/* @__PURE__ */ jsx35(Header, { title: "Select skills to update" }),
|
|
9337
|
+
/* @__PURE__ */ jsx35(Text30, { dimColor: true, children: "No updates found." }),
|
|
9338
|
+
rateLimited ? /* @__PURE__ */ jsx35(Text30, { dimColor: true, children: "GitHub rate limit hit. Some skills may be marked unknown." }) : null,
|
|
9339
|
+
/* @__PURE__ */ jsx35(Box33, { marginTop: 1, children: /* @__PURE__ */ jsx35(Text30, { dimColor: true, children: UPDATE_EMPTY_HINT }) })
|
|
9047
9340
|
] });
|
|
9048
9341
|
}
|
|
9049
|
-
return /* @__PURE__ */
|
|
9050
|
-
/* @__PURE__ */
|
|
9051
|
-
rateLimited ? /* @__PURE__ */
|
|
9052
|
-
/* @__PURE__ */
|
|
9342
|
+
return /* @__PURE__ */ jsxs30(Box33, { flexDirection: "column", padding: 1, children: [
|
|
9343
|
+
/* @__PURE__ */ jsx35(Header, { title: "Select skills to update" }),
|
|
9344
|
+
rateLimited ? /* @__PURE__ */ jsx35(Text30, { dimColor: true, children: "GitHub rate limit hit. Some skills marked unknown." }) : null,
|
|
9345
|
+
/* @__PURE__ */ jsx35(
|
|
9053
9346
|
MultiSelect,
|
|
9054
9347
|
{
|
|
9055
9348
|
items: visibleTargets.map((target) => ({
|
|
@@ -9072,9 +9365,9 @@ function UpdateScreen() {
|
|
|
9072
9365
|
] });
|
|
9073
9366
|
}
|
|
9074
9367
|
if (status === "running") {
|
|
9075
|
-
return /* @__PURE__ */
|
|
9076
|
-
/* @__PURE__ */
|
|
9077
|
-
/* @__PURE__ */
|
|
9368
|
+
return /* @__PURE__ */ jsxs30(Box33, { flexDirection: "column", padding: 1, children: [
|
|
9369
|
+
/* @__PURE__ */ jsx35(Header, { title: "Updating skills" }),
|
|
9370
|
+
/* @__PURE__ */ jsxs30(Text30, { children: [
|
|
9078
9371
|
spinner,
|
|
9079
9372
|
" Updating ",
|
|
9080
9373
|
selected.length,
|
|
@@ -9085,17 +9378,17 @@ function UpdateScreen() {
|
|
|
9085
9378
|
] });
|
|
9086
9379
|
}
|
|
9087
9380
|
if (!summary) {
|
|
9088
|
-
return /* @__PURE__ */
|
|
9089
|
-
/* @__PURE__ */
|
|
9090
|
-
/* @__PURE__ */
|
|
9381
|
+
return /* @__PURE__ */ jsxs30(Box33, { flexDirection: "column", padding: 1, children: [
|
|
9382
|
+
/* @__PURE__ */ jsx35(Header, { title: "Update skills" }),
|
|
9383
|
+
/* @__PURE__ */ jsx35(Text30, { dimColor: true, children: "Nothing to update." })
|
|
9091
9384
|
] });
|
|
9092
9385
|
}
|
|
9093
|
-
return /* @__PURE__ */
|
|
9094
|
-
/* @__PURE__ */
|
|
9095
|
-
summary.updated.length > 0 ? /* @__PURE__ */
|
|
9096
|
-
summary.skipped.length > 0 ? /* @__PURE__ */
|
|
9097
|
-
summary.failed.length > 0 ? /* @__PURE__ */
|
|
9098
|
-
/* @__PURE__ */
|
|
9386
|
+
return /* @__PURE__ */ jsxs30(Box33, { flexDirection: "column", padding: 1, children: [
|
|
9387
|
+
/* @__PURE__ */ jsx35(Header, { title: "Update results" }),
|
|
9388
|
+
summary.updated.length > 0 ? /* @__PURE__ */ jsx35(Text30, { children: `Updated ${summary.updated.length} skill${summary.updated.length !== 1 ? "s" : ""}` }) : null,
|
|
9389
|
+
summary.skipped.length > 0 ? /* @__PURE__ */ jsx35(Text30, { dimColor: true, children: `Skipped: ${summary.skipped.map(formatTargetLabel).join(", ")}` }) : null,
|
|
9390
|
+
summary.failed.length > 0 ? /* @__PURE__ */ jsx35(Text30, { color: "red", children: `Failed: ${summary.failed.map(formatTargetLabel).join(", ")}` }) : null,
|
|
9391
|
+
/* @__PURE__ */ jsx35(Box33, { marginTop: 1, children: /* @__PURE__ */ jsx35(Text30, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
9099
9392
|
] });
|
|
9100
9393
|
}
|
|
9101
9394
|
function resolveScopes(options) {
|
|
@@ -9124,63 +9417,65 @@ function sortTargets(a, b) {
|
|
|
9124
9417
|
}
|
|
9125
9418
|
|
|
9126
9419
|
// src/tui/ScreenRouter.tsx
|
|
9127
|
-
import { Fragment as Fragment4, jsx as
|
|
9420
|
+
import { Fragment as Fragment4, jsx as jsx36, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
9128
9421
|
function ScreenRouter() {
|
|
9129
9422
|
const { screen } = useNavigation();
|
|
9130
9423
|
const render2 = (s) => {
|
|
9131
9424
|
switch (s) {
|
|
9132
9425
|
case "main":
|
|
9133
|
-
return /* @__PURE__ */
|
|
9426
|
+
return /* @__PURE__ */ jsx36(MainMenu, {});
|
|
9134
9427
|
case "add-source":
|
|
9135
|
-
return /* @__PURE__ */
|
|
9428
|
+
return /* @__PURE__ */ jsx36(AddSourceScreen, {});
|
|
9136
9429
|
case "add-docs":
|
|
9137
|
-
return /* @__PURE__ */
|
|
9430
|
+
return /* @__PURE__ */ jsx36(AddDocsScreen, {});
|
|
9138
9431
|
case "add-marketplace-plugins":
|
|
9139
|
-
return /* @__PURE__ */
|
|
9432
|
+
return /* @__PURE__ */ jsx36(MarketplacePluginScreen, {});
|
|
9140
9433
|
case "add-marketplace-skills":
|
|
9141
|
-
return /* @__PURE__ */
|
|
9434
|
+
return /* @__PURE__ */ jsx36(MarketplaceSkillScreen, {});
|
|
9142
9435
|
case "find-skill-search":
|
|
9143
|
-
return /* @__PURE__ */
|
|
9436
|
+
return /* @__PURE__ */ jsx36(FindSkillSearchScreen, {});
|
|
9144
9437
|
case "find-skill-results":
|
|
9145
|
-
return /* @__PURE__ */
|
|
9438
|
+
return /* @__PURE__ */ jsx36(FindSkillResultsScreen, {});
|
|
9146
9439
|
case "scan-skills":
|
|
9147
|
-
return /* @__PURE__ */
|
|
9440
|
+
return /* @__PURE__ */ jsx36(ScanSkillsScreen, {});
|
|
9148
9441
|
case "get-url":
|
|
9149
|
-
return /* @__PURE__ */
|
|
9442
|
+
return /* @__PURE__ */ jsx36(GetUrlScreen, {});
|
|
9150
9443
|
case "add-skill-select":
|
|
9151
|
-
return /* @__PURE__ */
|
|
9444
|
+
return /* @__PURE__ */ jsx36(AddSkillSelectScreen, {});
|
|
9445
|
+
case "add-bundle-select":
|
|
9446
|
+
return /* @__PURE__ */ jsx36(AddBundleSelectScreen, {});
|
|
9152
9447
|
case "add-license-key":
|
|
9153
|
-
return /* @__PURE__ */
|
|
9448
|
+
return /* @__PURE__ */ jsx36(AddLicenseKeyScreen, {});
|
|
9154
9449
|
case "add-security-scan":
|
|
9155
|
-
return /* @__PURE__ */
|
|
9450
|
+
return /* @__PURE__ */ jsx36(AddSecurityScanScreen, {});
|
|
9156
9451
|
case "add-targets":
|
|
9157
|
-
return /* @__PURE__ */
|
|
9452
|
+
return /* @__PURE__ */ jsx36(AddTargetsScreen, {});
|
|
9158
9453
|
case "add-scope":
|
|
9159
|
-
return /* @__PURE__ */
|
|
9454
|
+
return /* @__PURE__ */ jsx36(AddScopeScreen, {});
|
|
9160
9455
|
case "add-mode":
|
|
9161
|
-
return /* @__PURE__ */
|
|
9456
|
+
return /* @__PURE__ */ jsx36(AddModeScreen, {});
|
|
9162
9457
|
case "add-confirm":
|
|
9163
|
-
return /* @__PURE__ */
|
|
9458
|
+
return /* @__PURE__ */ jsx36(AddConfirmScreen, {});
|
|
9164
9459
|
case "add-install":
|
|
9165
|
-
return /* @__PURE__ */
|
|
9460
|
+
return /* @__PURE__ */ jsx36(AddInstallScreen, {});
|
|
9166
9461
|
case "add-result":
|
|
9167
|
-
return /* @__PURE__ */
|
|
9462
|
+
return /* @__PURE__ */ jsx36(AddResultScreen, {});
|
|
9168
9463
|
case "list":
|
|
9169
|
-
return /* @__PURE__ */
|
|
9464
|
+
return /* @__PURE__ */ jsx36(ListScreen, {});
|
|
9170
9465
|
case "manage":
|
|
9171
|
-
return /* @__PURE__ */
|
|
9466
|
+
return /* @__PURE__ */ jsx36(ManageScreen, {});
|
|
9172
9467
|
case "update":
|
|
9173
|
-
return /* @__PURE__ */
|
|
9468
|
+
return /* @__PURE__ */ jsx36(UpdateScreen, {});
|
|
9174
9469
|
case "update-docs":
|
|
9175
|
-
return /* @__PURE__ */
|
|
9470
|
+
return /* @__PURE__ */ jsx36(UpdateDocsScreen, {});
|
|
9176
9471
|
default:
|
|
9177
9472
|
return null;
|
|
9178
9473
|
}
|
|
9179
9474
|
};
|
|
9180
|
-
return /* @__PURE__ */
|
|
9181
|
-
/* @__PURE__ */
|
|
9475
|
+
return /* @__PURE__ */ jsxs31(Fragment4, { children: [
|
|
9476
|
+
/* @__PURE__ */ jsx36(BrandHeader, {}),
|
|
9182
9477
|
render2(screen),
|
|
9183
|
-
/* @__PURE__ */
|
|
9478
|
+
/* @__PURE__ */ jsx36(FlashBar, { align: "center" })
|
|
9184
9479
|
] });
|
|
9185
9480
|
}
|
|
9186
9481
|
|
|
@@ -9260,14 +9555,14 @@ function useKeyboardShortcuts() {
|
|
|
9260
9555
|
}
|
|
9261
9556
|
|
|
9262
9557
|
// src/tui/App.tsx
|
|
9263
|
-
import { jsx as
|
|
9558
|
+
import { jsx as jsx37 } from "react/jsx-runtime";
|
|
9264
9559
|
function AppRoot() {
|
|
9265
9560
|
useKeyboardShortcuts();
|
|
9266
|
-
return /* @__PURE__ */
|
|
9561
|
+
return /* @__PURE__ */ jsx37(ScreenRouter, {});
|
|
9267
9562
|
}
|
|
9268
9563
|
function runApp(initialInvocation, initialScreen) {
|
|
9269
9564
|
const { waitUntilExit } = render(
|
|
9270
|
-
/* @__PURE__ */
|
|
9565
|
+
/* @__PURE__ */ jsx37(NavigationProvider, { initialInvocation, initialScreen, children: /* @__PURE__ */ jsx37(AppRoot, {}) })
|
|
9271
9566
|
);
|
|
9272
9567
|
return waitUntilExit();
|
|
9273
9568
|
}
|
|
@@ -9350,6 +9645,11 @@ applyAddSkillOptions(
|
|
|
9350
9645
|
await launch({ intent: "add-skill", source, options }, initialAddSkillScreen(source));
|
|
9351
9646
|
})
|
|
9352
9647
|
);
|
|
9648
|
+
applyAddSkillOptions(
|
|
9649
|
+
addCmd.command("bundle <slug>").description("Add all skills from a bundle").action(async (slug, options) => {
|
|
9650
|
+
await launch({ intent: "add-bundle", source: slug, options }, "add-bundle-select");
|
|
9651
|
+
})
|
|
9652
|
+
);
|
|
9353
9653
|
addCmd.command("docs").description("Add docs").action(async (options) => {
|
|
9354
9654
|
await launch({ intent: "add-docs", options }, "add-docs");
|
|
9355
9655
|
});
|