@hiver/skills 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +407 -127
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5,8 +5,8 @@ import React10 from "react";
|
|
|
5
5
|
import { render, Box as Box9, Text as Text10 } from "ink";
|
|
6
6
|
|
|
7
7
|
// src/commands/Add.jsx
|
|
8
|
-
import
|
|
9
|
-
import { Box as
|
|
8
|
+
import React5, { useState as useState3, useEffect } from "react";
|
|
9
|
+
import { Box as Box4, Text as Text5, useApp } from "ink";
|
|
10
10
|
|
|
11
11
|
// src/components/Select.jsx
|
|
12
12
|
import React, { useState } from "react";
|
|
@@ -149,28 +149,36 @@ function Info({ children }) {
|
|
|
149
149
|
] });
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
// src/
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
152
|
+
// src/components/Confirm.jsx
|
|
153
|
+
import React4 from "react";
|
|
154
|
+
import { Box as Box3, Text as Text4, useInput as useInput3 } from "ink";
|
|
155
|
+
import { jsx as jsx3, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
156
|
+
function Confirm({ message, onConfirm, onBack }) {
|
|
157
|
+
useInput3((input, key) => {
|
|
158
|
+
if (input === "y" || input === "Y") {
|
|
159
|
+
onConfirm(true);
|
|
160
|
+
}
|
|
161
|
+
if (input === "n" || input === "N") {
|
|
162
|
+
onConfirm(false);
|
|
163
|
+
}
|
|
164
|
+
if (key.escape && onBack) {
|
|
165
|
+
onBack();
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
return /* @__PURE__ */ jsx3(Box3, { children: /* @__PURE__ */ jsxs4(Text4, { bold: true, color: "cyan", children: [
|
|
169
|
+
"? ",
|
|
170
|
+
message,
|
|
171
|
+
/* @__PURE__ */ jsxs4(Text4, { color: "gray", children: [
|
|
172
|
+
" (y/n",
|
|
173
|
+
onBack ? ", esc back" : "",
|
|
174
|
+
")"
|
|
175
|
+
] })
|
|
176
|
+
] }) });
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// src/utils/installer.js
|
|
180
|
+
import path2 from "path";
|
|
181
|
+
import fs2 from "fs-extra";
|
|
174
182
|
|
|
175
183
|
// src/utils/collections.js
|
|
176
184
|
import path from "path";
|
|
@@ -282,8 +290,6 @@ function resolveDependencies(selected, selectedCollections) {
|
|
|
282
290
|
}
|
|
283
291
|
|
|
284
292
|
// src/utils/installer.js
|
|
285
|
-
import path2 from "path";
|
|
286
|
-
import fs2 from "fs-extra";
|
|
287
293
|
async function installSkill(collectionName, skillName, targetConfig, destRoot) {
|
|
288
294
|
const src = path2.join(getCollectionsDir(), collectionName, "skills", skillName);
|
|
289
295
|
const dest = path2.join(destRoot, targetConfig.skillsDir, skillName);
|
|
@@ -332,17 +338,41 @@ async function removeAgent(agentName, targetConfig, destRoot) {
|
|
|
332
338
|
return false;
|
|
333
339
|
}
|
|
334
340
|
|
|
341
|
+
// src/utils/targets.js
|
|
342
|
+
var targets = {
|
|
343
|
+
claude: {
|
|
344
|
+
name: "Claude Code",
|
|
345
|
+
skillsDir: ".claude/skills",
|
|
346
|
+
agentsDir: ".claude/agents"
|
|
347
|
+
},
|
|
348
|
+
cursor: {
|
|
349
|
+
name: "Cursor",
|
|
350
|
+
skillsDir: ".cursor/rules",
|
|
351
|
+
agentsDir: ".cursor/rules"
|
|
352
|
+
},
|
|
353
|
+
windsurf: {
|
|
354
|
+
name: "Windsurf",
|
|
355
|
+
skillsDir: ".windsurfrules",
|
|
356
|
+
agentsDir: ".windsurfrules"
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
var targetList = Object.entries(targets).map(([key, t]) => ({
|
|
360
|
+
label: t.name,
|
|
361
|
+
value: key
|
|
362
|
+
}));
|
|
363
|
+
|
|
335
364
|
// src/commands/Add.jsx
|
|
336
|
-
import { jsx as
|
|
365
|
+
import { jsx as jsx4, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
337
366
|
var STEPS = {
|
|
338
367
|
TARGET: "target",
|
|
339
368
|
COLLECTIONS: "collections",
|
|
340
369
|
TYPE: "type",
|
|
341
370
|
ITEMS: "items",
|
|
371
|
+
CONFIRM_ALL: "confirm_all",
|
|
342
372
|
INSTALLING: "installing",
|
|
343
373
|
DONE: "done"
|
|
344
374
|
};
|
|
345
|
-
function Add({ directSkills }) {
|
|
375
|
+
function Add({ directSkills, addAll }) {
|
|
346
376
|
const { exit } = useApp();
|
|
347
377
|
const [step, setStep] = useState3(STEPS.TARGET);
|
|
348
378
|
const [targetKey, setTargetKey] = useState3(null);
|
|
@@ -351,6 +381,7 @@ function Add({ directSkills }) {
|
|
|
351
381
|
const [toInstall, setToInstall] = useState3({ skills: [], agents: [] });
|
|
352
382
|
const [results, setResults] = useState3({ skills: 0, agents: 0, deps: [] });
|
|
353
383
|
const [directMissing, setDirectMissing] = useState3([]);
|
|
384
|
+
const [allPlan, setAllPlan] = useState3(null);
|
|
354
385
|
const destRoot = process.cwd();
|
|
355
386
|
function getAvailableTypes(col) {
|
|
356
387
|
const { skills, agents } = scanCollection(col);
|
|
@@ -365,6 +396,32 @@ function Add({ directSkills }) {
|
|
|
365
396
|
}
|
|
366
397
|
function handleCollectionSelect(col) {
|
|
367
398
|
setSelectedCollection(col);
|
|
399
|
+
if (addAll) {
|
|
400
|
+
const targetConfig = targets[targetKey];
|
|
401
|
+
const { skills, agents } = scanCollection(col);
|
|
402
|
+
const installed = listInstalled(targetConfig, destRoot);
|
|
403
|
+
const installedSkillSet = new Set(installed.skills);
|
|
404
|
+
const installedAgentSet = new Set(installed.agents);
|
|
405
|
+
const newSkills = skills.filter((n) => !installedSkillSet.has(n));
|
|
406
|
+
const newAgents = agents.filter((n) => !installedAgentSet.has(n));
|
|
407
|
+
const alreadySkills = skills.filter((n) => installedSkillSet.has(n));
|
|
408
|
+
const alreadyAgents = agents.filter((n) => installedAgentSet.has(n));
|
|
409
|
+
if (newSkills.length === 0 && newAgents.length === 0) {
|
|
410
|
+
setDirectMissing(
|
|
411
|
+
[...alreadySkills, ...alreadyAgents].map((n) => `${n} (already installed)`)
|
|
412
|
+
);
|
|
413
|
+
setStep(STEPS.DONE);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
setAllPlan({
|
|
417
|
+
skills: newSkills,
|
|
418
|
+
agents: newAgents,
|
|
419
|
+
alreadyInstalled: [...alreadySkills, ...alreadyAgents],
|
|
420
|
+
collection: col
|
|
421
|
+
});
|
|
422
|
+
setStep(STEPS.CONFIRM_ALL);
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
368
425
|
if (directSkills && directSkills.length > 0) {
|
|
369
426
|
const { skills, agents } = scanCollection(col);
|
|
370
427
|
const skillItems = [];
|
|
@@ -410,6 +467,21 @@ function Add({ directSkills }) {
|
|
|
410
467
|
}
|
|
411
468
|
setStep(STEPS.INSTALLING);
|
|
412
469
|
}
|
|
470
|
+
function handleConfirmAllAdd(yes) {
|
|
471
|
+
if (!yes) {
|
|
472
|
+
setStep(STEPS.DONE);
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
const col = allPlan.collection;
|
|
476
|
+
setToInstall({
|
|
477
|
+
skills: allPlan.skills.map((name) => ({ collection: col, name })),
|
|
478
|
+
agents: allPlan.agents.map((name) => ({ collection: col, name }))
|
|
479
|
+
});
|
|
480
|
+
if (allPlan.alreadyInstalled.length > 0) {
|
|
481
|
+
setDirectMissing(allPlan.alreadyInstalled.map((n) => `${n} (already installed)`));
|
|
482
|
+
}
|
|
483
|
+
setStep(STEPS.INSTALLING);
|
|
484
|
+
}
|
|
413
485
|
function handleTargetBack() {
|
|
414
486
|
exit();
|
|
415
487
|
}
|
|
@@ -456,7 +528,7 @@ function Add({ directSkills }) {
|
|
|
456
528
|
doInstall();
|
|
457
529
|
}, [step]);
|
|
458
530
|
if (step === STEPS.TARGET) {
|
|
459
|
-
return /* @__PURE__ */
|
|
531
|
+
return /* @__PURE__ */ jsx4(
|
|
460
532
|
Select,
|
|
461
533
|
{
|
|
462
534
|
items: targetList,
|
|
@@ -479,13 +551,13 @@ function Add({ directSkills }) {
|
|
|
479
551
|
const items = collections.map((c) => ({ label: c, value: c }));
|
|
480
552
|
if (items.length === 0) {
|
|
481
553
|
setTimeout(() => exit(), 100);
|
|
482
|
-
return /* @__PURE__ */
|
|
554
|
+
return /* @__PURE__ */ jsxs5(ErrorMsg, { children: [
|
|
483
555
|
"None of: ",
|
|
484
556
|
directSkills.join(", "),
|
|
485
557
|
" found in any collection."
|
|
486
558
|
] });
|
|
487
559
|
}
|
|
488
|
-
return /* @__PURE__ */
|
|
560
|
+
return /* @__PURE__ */ jsx4(
|
|
489
561
|
Select,
|
|
490
562
|
{
|
|
491
563
|
items,
|
|
@@ -497,7 +569,7 @@ function Add({ directSkills }) {
|
|
|
497
569
|
}
|
|
498
570
|
if (step === STEPS.TYPE) {
|
|
499
571
|
const types = getAvailableTypes(selectedCollection);
|
|
500
|
-
return /* @__PURE__ */
|
|
572
|
+
return /* @__PURE__ */ jsx4(
|
|
501
573
|
Select,
|
|
502
574
|
{
|
|
503
575
|
items: types,
|
|
@@ -515,7 +587,7 @@ function Add({ directSkills }) {
|
|
|
515
587
|
const meta = getSkillMeta(col, s);
|
|
516
588
|
return { label: s, value: s, description: meta.description, checked: false };
|
|
517
589
|
});
|
|
518
|
-
return /* @__PURE__ */
|
|
590
|
+
return /* @__PURE__ */ jsx4(
|
|
519
591
|
MultiSelect,
|
|
520
592
|
{
|
|
521
593
|
items,
|
|
@@ -530,7 +602,7 @@ function Add({ directSkills }) {
|
|
|
530
602
|
const meta = getAgentMeta(col, a);
|
|
531
603
|
return { label: a, value: a, description: meta.description, checked: false };
|
|
532
604
|
});
|
|
533
|
-
return /* @__PURE__ */
|
|
605
|
+
return /* @__PURE__ */ jsx4(
|
|
534
606
|
MultiSelect,
|
|
535
607
|
{
|
|
536
608
|
items,
|
|
@@ -541,19 +613,53 @@ function Add({ directSkills }) {
|
|
|
541
613
|
);
|
|
542
614
|
}
|
|
543
615
|
}
|
|
616
|
+
if (step === STEPS.CONFIRM_ALL) {
|
|
617
|
+
const total = allPlan.skills.length + allPlan.agents.length;
|
|
618
|
+
return /* @__PURE__ */ jsxs5(Box4, { flexDirection: "column", children: [
|
|
619
|
+
/* @__PURE__ */ jsxs5(Warning, { children: [
|
|
620
|
+
"Will install ",
|
|
621
|
+
allPlan.skills.length,
|
|
622
|
+
" skill(s), ",
|
|
623
|
+
allPlan.agents.length,
|
|
624
|
+
' agent(s) from "',
|
|
625
|
+
allPlan.collection,
|
|
626
|
+
'":'
|
|
627
|
+
] }),
|
|
628
|
+
/* @__PURE__ */ jsxs5(Box4, { flexDirection: "column", marginTop: 1, children: [
|
|
629
|
+
allPlan.skills.map((n) => /* @__PURE__ */ jsxs5(Text5, { color: "green", children: [
|
|
630
|
+
" + ",
|
|
631
|
+
n,
|
|
632
|
+
" (skill)"
|
|
633
|
+
] }, `s-${n}`)),
|
|
634
|
+
allPlan.agents.map((n) => /* @__PURE__ */ jsxs5(Text5, { color: "green", children: [
|
|
635
|
+
" + ",
|
|
636
|
+
n,
|
|
637
|
+
" (agent)"
|
|
638
|
+
] }, `a-${n}`))
|
|
639
|
+
] }),
|
|
640
|
+
allPlan.alreadyInstalled.length > 0 && /* @__PURE__ */ jsxs5(Box4, { flexDirection: "column", marginTop: 1, children: [
|
|
641
|
+
/* @__PURE__ */ jsx4(Info, { children: "Already installed (will skip):" }),
|
|
642
|
+
allPlan.alreadyInstalled.map((n) => /* @__PURE__ */ jsxs5(Text5, { color: "gray", children: [
|
|
643
|
+
" \u2022 ",
|
|
644
|
+
n
|
|
645
|
+
] }, `x-${n}`))
|
|
646
|
+
] }),
|
|
647
|
+
/* @__PURE__ */ jsx4(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx4(Confirm, { message: `Install all ${total} item(s)?`, onConfirm: handleConfirmAllAdd }) })
|
|
648
|
+
] });
|
|
649
|
+
}
|
|
544
650
|
if (step === STEPS.INSTALLING) {
|
|
545
|
-
return /* @__PURE__ */
|
|
651
|
+
return /* @__PURE__ */ jsx4(Text5, { color: "yellow", children: "Installing..." });
|
|
546
652
|
}
|
|
547
653
|
if (step === STEPS.DONE) {
|
|
548
654
|
setTimeout(() => exit(), 100);
|
|
549
|
-
return /* @__PURE__ */
|
|
550
|
-
directMissing.length > 0 && /* @__PURE__ */
|
|
655
|
+
return /* @__PURE__ */ jsxs5(Box4, { flexDirection: "column", marginTop: 1, children: [
|
|
656
|
+
directMissing.length > 0 && /* @__PURE__ */ jsx4(Box4, { marginBottom: 1, children: /* @__PURE__ */ jsxs5(ErrorMsg, { children: [
|
|
551
657
|
"Not found in any collection: ",
|
|
552
658
|
directMissing.join(", ")
|
|
553
659
|
] }) }),
|
|
554
|
-
results.deps.length > 0 && /* @__PURE__ */
|
|
555
|
-
/* @__PURE__ */
|
|
556
|
-
results.deps.map((d) => /* @__PURE__ */
|
|
660
|
+
results.deps.length > 0 && /* @__PURE__ */ jsxs5(Box4, { flexDirection: "column", marginBottom: 1, children: [
|
|
661
|
+
/* @__PURE__ */ jsx4(Info, { children: "Auto-installed dependencies:" }),
|
|
662
|
+
results.deps.map((d) => /* @__PURE__ */ jsxs5(Text5, { color: "cyan", children: [
|
|
557
663
|
" + ",
|
|
558
664
|
d.name,
|
|
559
665
|
" (from ",
|
|
@@ -561,7 +667,7 @@ function Add({ directSkills }) {
|
|
|
561
667
|
")"
|
|
562
668
|
] }, d.name))
|
|
563
669
|
] }),
|
|
564
|
-
/* @__PURE__ */
|
|
670
|
+
/* @__PURE__ */ jsxs5(Success, { children: [
|
|
565
671
|
"Installed ",
|
|
566
672
|
results.skills,
|
|
567
673
|
" skill(s), ",
|
|
@@ -575,18 +681,18 @@ function Add({ directSkills }) {
|
|
|
575
681
|
}
|
|
576
682
|
|
|
577
683
|
// src/commands/List.jsx
|
|
578
|
-
import
|
|
579
|
-
import { Box as
|
|
580
|
-
import { jsx as
|
|
684
|
+
import React6 from "react";
|
|
685
|
+
import { Box as Box5, Text as Text6, useApp as useApp2 } from "ink";
|
|
686
|
+
import { jsx as jsx5, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
581
687
|
function List() {
|
|
582
688
|
const { exit } = useApp2();
|
|
583
689
|
const collections = listCollections();
|
|
584
690
|
setTimeout(() => exit(), 100);
|
|
585
691
|
if (collections.length === 0) {
|
|
586
|
-
return /* @__PURE__ */
|
|
692
|
+
return /* @__PURE__ */ jsx5(Text6, { color: "yellow", children: "No collections found." });
|
|
587
693
|
}
|
|
588
|
-
return /* @__PURE__ */
|
|
589
|
-
/* @__PURE__ */
|
|
694
|
+
return /* @__PURE__ */ jsxs6(Box5, { flexDirection: "column", children: [
|
|
695
|
+
/* @__PURE__ */ jsxs6(Text6, { bold: true, color: "cyan", children: [
|
|
590
696
|
"\n",
|
|
591
697
|
"Available skills & agents",
|
|
592
698
|
"\n"
|
|
@@ -594,44 +700,44 @@ function List() {
|
|
|
594
700
|
collections.map((col) => {
|
|
595
701
|
const { skills, agents } = scanCollection(col);
|
|
596
702
|
if (skills.length === 0 && agents.length === 0) return null;
|
|
597
|
-
return /* @__PURE__ */
|
|
598
|
-
/* @__PURE__ */
|
|
703
|
+
return /* @__PURE__ */ jsxs6(Box5, { flexDirection: "column", marginBottom: 1, children: [
|
|
704
|
+
/* @__PURE__ */ jsxs6(Text6, { bold: true, color: "yellow", children: [
|
|
599
705
|
" ",
|
|
600
706
|
"\u{1F4E6} ",
|
|
601
707
|
col
|
|
602
708
|
] }),
|
|
603
|
-
skills.length > 0 && /* @__PURE__ */
|
|
604
|
-
/* @__PURE__ */
|
|
709
|
+
skills.length > 0 && /* @__PURE__ */ jsxs6(Box5, { flexDirection: "column", marginLeft: 2, marginTop: 1, children: [
|
|
710
|
+
/* @__PURE__ */ jsxs6(Text6, { bold: true, color: "magenta", children: [
|
|
605
711
|
" ",
|
|
606
712
|
"Skills"
|
|
607
713
|
] }),
|
|
608
714
|
skills.map((s) => {
|
|
609
715
|
const meta = getSkillMeta(col, s);
|
|
610
|
-
return /* @__PURE__ */
|
|
611
|
-
/* @__PURE__ */
|
|
716
|
+
return /* @__PURE__ */ jsxs6(Box5, { flexDirection: "column", marginBottom: 1, marginLeft: 2, children: [
|
|
717
|
+
/* @__PURE__ */ jsxs6(Text6, { bold: true, color: "green", children: [
|
|
612
718
|
" ",
|
|
613
719
|
s
|
|
614
720
|
] }),
|
|
615
|
-
meta.description && /* @__PURE__ */
|
|
721
|
+
meta.description && /* @__PURE__ */ jsxs6(Text6, { color: "gray", children: [
|
|
616
722
|
" ",
|
|
617
723
|
meta.description
|
|
618
724
|
] })
|
|
619
725
|
] }, s);
|
|
620
726
|
})
|
|
621
727
|
] }),
|
|
622
|
-
agents.length > 0 && /* @__PURE__ */
|
|
623
|
-
/* @__PURE__ */
|
|
728
|
+
agents.length > 0 && /* @__PURE__ */ jsxs6(Box5, { flexDirection: "column", marginLeft: 2, marginTop: 1, children: [
|
|
729
|
+
/* @__PURE__ */ jsxs6(Text6, { bold: true, color: "magenta", children: [
|
|
624
730
|
" ",
|
|
625
731
|
"Agents"
|
|
626
732
|
] }),
|
|
627
733
|
agents.map((a) => {
|
|
628
734
|
const meta = getAgentMeta(col, a);
|
|
629
|
-
return /* @__PURE__ */
|
|
630
|
-
/* @__PURE__ */
|
|
735
|
+
return /* @__PURE__ */ jsxs6(Box5, { flexDirection: "column", marginBottom: 1, marginLeft: 2, children: [
|
|
736
|
+
/* @__PURE__ */ jsxs6(Text6, { bold: true, color: "blue", children: [
|
|
631
737
|
" ",
|
|
632
738
|
a
|
|
633
739
|
] }),
|
|
634
|
-
meta.description && /* @__PURE__ */
|
|
740
|
+
meta.description && /* @__PURE__ */ jsxs6(Text6, { color: "gray", children: [
|
|
635
741
|
" ",
|
|
636
742
|
meta.description
|
|
637
743
|
] })
|
|
@@ -646,35 +752,8 @@ function List() {
|
|
|
646
752
|
// src/commands/Update.jsx
|
|
647
753
|
import React8, { useState as useState4, useEffect as useEffect2 } from "react";
|
|
648
754
|
import { Box as Box7, Text as Text8, useApp as useApp3 } from "ink";
|
|
649
|
-
import
|
|
650
|
-
import
|
|
651
|
-
|
|
652
|
-
// src/components/Confirm.jsx
|
|
653
|
-
import React6 from "react";
|
|
654
|
-
import { Box as Box5, Text as Text6, useInput as useInput3 } from "ink";
|
|
655
|
-
import { jsx as jsx5, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
656
|
-
function Confirm({ message, onConfirm, onBack }) {
|
|
657
|
-
useInput3((input, key) => {
|
|
658
|
-
if (input === "y" || input === "Y") {
|
|
659
|
-
onConfirm(true);
|
|
660
|
-
}
|
|
661
|
-
if (input === "n" || input === "N") {
|
|
662
|
-
onConfirm(false);
|
|
663
|
-
}
|
|
664
|
-
if (key.escape && onBack) {
|
|
665
|
-
onBack();
|
|
666
|
-
}
|
|
667
|
-
});
|
|
668
|
-
return /* @__PURE__ */ jsx5(Box5, { children: /* @__PURE__ */ jsxs6(Text6, { bold: true, color: "cyan", children: [
|
|
669
|
-
"? ",
|
|
670
|
-
message,
|
|
671
|
-
/* @__PURE__ */ jsxs6(Text6, { color: "gray", children: [
|
|
672
|
-
" (y/n",
|
|
673
|
-
onBack ? ", esc back" : "",
|
|
674
|
-
")"
|
|
675
|
-
] })
|
|
676
|
-
] }) });
|
|
677
|
-
}
|
|
755
|
+
import path4 from "path";
|
|
756
|
+
import fs4 from "fs-extra";
|
|
678
757
|
|
|
679
758
|
// src/components/DiffView.jsx
|
|
680
759
|
import React7 from "react";
|
|
@@ -692,6 +771,8 @@ function DiffView({ patch }) {
|
|
|
692
771
|
}
|
|
693
772
|
|
|
694
773
|
// src/utils/diffUtil.js
|
|
774
|
+
import path3 from "path";
|
|
775
|
+
import fs3 from "fs-extra";
|
|
695
776
|
import { createTwoFilesPatch } from "diff";
|
|
696
777
|
function computeDiff(filePath, localContent, latestContent) {
|
|
697
778
|
return createTwoFilesPatch(
|
|
@@ -706,6 +787,63 @@ function computeDiff(filePath, localContent, latestContent) {
|
|
|
706
787
|
function hasChanges(localContent, latestContent) {
|
|
707
788
|
return localContent.trim() !== latestContent.trim();
|
|
708
789
|
}
|
|
790
|
+
function walkFiles(dir) {
|
|
791
|
+
const out = [];
|
|
792
|
+
if (!fs3.existsSync(dir)) return out;
|
|
793
|
+
const entries = fs3.readdirSync(dir, { withFileTypes: true });
|
|
794
|
+
for (const entry of entries) {
|
|
795
|
+
const full = path3.join(dir, entry.name);
|
|
796
|
+
if (entry.isDirectory()) {
|
|
797
|
+
for (const sub of walkFiles(full)) out.push(path3.join(entry.name, sub));
|
|
798
|
+
} else if (entry.isFile()) {
|
|
799
|
+
out.push(entry.name);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
return out;
|
|
803
|
+
}
|
|
804
|
+
function isBinary(buf) {
|
|
805
|
+
const sample = buf.subarray(0, Math.min(buf.length, 8e3));
|
|
806
|
+
for (let i = 0; i < sample.length; i++) {
|
|
807
|
+
if (sample[i] === 0) return true;
|
|
808
|
+
}
|
|
809
|
+
return false;
|
|
810
|
+
}
|
|
811
|
+
function hasDirChanges(localDir, latestDir) {
|
|
812
|
+
const localFiles = new Set(walkFiles(localDir));
|
|
813
|
+
const latestFiles = new Set(walkFiles(latestDir));
|
|
814
|
+
if (localFiles.size !== latestFiles.size) return true;
|
|
815
|
+
for (const rel of latestFiles) {
|
|
816
|
+
if (!localFiles.has(rel)) return true;
|
|
817
|
+
const a = fs3.readFileSync(path3.join(localDir, rel));
|
|
818
|
+
const b = fs3.readFileSync(path3.join(latestDir, rel));
|
|
819
|
+
if (!a.equals(b)) return true;
|
|
820
|
+
}
|
|
821
|
+
for (const rel of localFiles) {
|
|
822
|
+
if (!latestFiles.has(rel)) return true;
|
|
823
|
+
}
|
|
824
|
+
return false;
|
|
825
|
+
}
|
|
826
|
+
function computeDirDiff(localDir, latestDir) {
|
|
827
|
+
const localFiles = new Set(walkFiles(localDir));
|
|
828
|
+
const latestFiles = new Set(walkFiles(latestDir));
|
|
829
|
+
const allFiles = /* @__PURE__ */ new Set([...localFiles, ...latestFiles]);
|
|
830
|
+
const parts = [];
|
|
831
|
+
for (const rel of [...allFiles].sort()) {
|
|
832
|
+
const localBuf = localFiles.has(rel) ? fs3.readFileSync(path3.join(localDir, rel)) : Buffer.alloc(0);
|
|
833
|
+
const latestBuf = latestFiles.has(rel) ? fs3.readFileSync(path3.join(latestDir, rel)) : Buffer.alloc(0);
|
|
834
|
+
if (localBuf.equals(latestBuf)) continue;
|
|
835
|
+
if (isBinary(localBuf) || isBinary(latestBuf)) {
|
|
836
|
+
const verb = !localFiles.has(rel) ? "added" : !latestFiles.has(rel) ? "removed" : "changed";
|
|
837
|
+
parts.push(`Binary file ${rel} ${verb} (${localBuf.length} \u2192 ${latestBuf.length} bytes)`);
|
|
838
|
+
continue;
|
|
839
|
+
}
|
|
840
|
+
const localContent = localBuf.toString("utf-8");
|
|
841
|
+
const latestContent = latestBuf.toString("utf-8");
|
|
842
|
+
if (localContent.trim() === latestContent.trim()) continue;
|
|
843
|
+
parts.push(computeDiff(rel, localContent, latestContent));
|
|
844
|
+
}
|
|
845
|
+
return parts.join("\n");
|
|
846
|
+
}
|
|
709
847
|
|
|
710
848
|
// src/commands/Update.jsx
|
|
711
849
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
@@ -715,16 +853,17 @@ var STEPS2 = {
|
|
|
715
853
|
ITEMS: "items",
|
|
716
854
|
RESOLVE: "resolve",
|
|
717
855
|
CONFIRM: "confirm",
|
|
856
|
+
CONFIRM_ALL: "confirm_all",
|
|
718
857
|
DONE: "done"
|
|
719
858
|
};
|
|
720
859
|
function detectType(name, targetConfig, destRoot) {
|
|
721
|
-
const skillPath =
|
|
722
|
-
if (
|
|
723
|
-
const agentPath =
|
|
724
|
-
if (
|
|
860
|
+
const skillPath = path4.join(destRoot, targetConfig.skillsDir, name, "SKILL.md");
|
|
861
|
+
if (fs4.existsSync(skillPath)) return "skill";
|
|
862
|
+
const agentPath = path4.join(destRoot, targetConfig.agentsDir, `${name}.md`);
|
|
863
|
+
if (fs4.existsSync(agentPath)) return "agent";
|
|
725
864
|
return null;
|
|
726
865
|
}
|
|
727
|
-
function Update({ directSkills }) {
|
|
866
|
+
function Update({ directSkills, updateAll }) {
|
|
728
867
|
const { exit } = useApp3();
|
|
729
868
|
const [step, setStep] = useState4(STEPS2.TARGET);
|
|
730
869
|
const [targetKey, setTargetKey] = useState4(null);
|
|
@@ -737,6 +876,8 @@ function Update({ directSkills }) {
|
|
|
737
876
|
const [installedCount, setInstalledCount] = useState4(0);
|
|
738
877
|
const [missingNames, setMissingNames] = useState4([]);
|
|
739
878
|
const [directInfo, setDirectInfo] = useState4([]);
|
|
879
|
+
const [skipReasons, setSkipReasons] = useState4([]);
|
|
880
|
+
const [allBundle, setAllBundle] = useState4(null);
|
|
740
881
|
const destRoot = process.cwd();
|
|
741
882
|
function handleTargetSelect(key) {
|
|
742
883
|
setTargetKey(key);
|
|
@@ -773,6 +914,57 @@ function Update({ directSkills }) {
|
|
|
773
914
|
}
|
|
774
915
|
function handleCollectionSelect(collection) {
|
|
775
916
|
setSelectedCollection(collection);
|
|
917
|
+
if (updateAll) {
|
|
918
|
+
const targetConfig = targets[targetKey];
|
|
919
|
+
const installed = listInstalled(targetConfig, destRoot);
|
|
920
|
+
const { skills, agents } = scanCollection(collection);
|
|
921
|
+
const items = [];
|
|
922
|
+
const localSkipped = [];
|
|
923
|
+
const parts = [];
|
|
924
|
+
for (const name of installed.skills) {
|
|
925
|
+
if (!skills.includes(name)) {
|
|
926
|
+
localSkipped.push({ name, reason: `not in ${collection}` });
|
|
927
|
+
continue;
|
|
928
|
+
}
|
|
929
|
+
const localDir = path4.join(destRoot, targetConfig.skillsDir, name);
|
|
930
|
+
const latestDir = path4.join(getCollectionsDir(), collection, "skills", name);
|
|
931
|
+
if (!hasDirChanges(localDir, latestDir)) {
|
|
932
|
+
localSkipped.push({ name, reason: `already up-to-date with ${collection}` });
|
|
933
|
+
continue;
|
|
934
|
+
}
|
|
935
|
+
items.push({ name, type: "skill" });
|
|
936
|
+
parts.push(`### ${name} (skill)
|
|
937
|
+
${computeDirDiff(localDir, latestDir)}`);
|
|
938
|
+
}
|
|
939
|
+
for (const name of installed.agents) {
|
|
940
|
+
if (!agents.includes(name)) {
|
|
941
|
+
localSkipped.push({ name, reason: `not in ${collection}` });
|
|
942
|
+
continue;
|
|
943
|
+
}
|
|
944
|
+
const localFile = path4.join(destRoot, targetConfig.agentsDir, `${name}.md`);
|
|
945
|
+
const latestFile = path4.join(getCollectionsDir(), collection, "agents", `${name}.md`);
|
|
946
|
+
const localContent = fs4.readFileSync(localFile, "utf-8");
|
|
947
|
+
const latestContent = fs4.readFileSync(latestFile, "utf-8");
|
|
948
|
+
if (!hasChanges(localContent, latestContent)) {
|
|
949
|
+
localSkipped.push({ name, reason: `already up-to-date with ${collection}` });
|
|
950
|
+
continue;
|
|
951
|
+
}
|
|
952
|
+
items.push({ name, type: "agent" });
|
|
953
|
+
parts.push(`### ${name} (agent)
|
|
954
|
+
${computeDiff(`${name}.md`, localContent, latestContent)}`);
|
|
955
|
+
}
|
|
956
|
+
if (localSkipped.length > 0) {
|
|
957
|
+
setSkipReasons((prev) => [...prev, ...localSkipped]);
|
|
958
|
+
setSkippedCount((c) => c + localSkipped.length);
|
|
959
|
+
}
|
|
960
|
+
if (items.length === 0) {
|
|
961
|
+
setStep(STEPS2.DONE);
|
|
962
|
+
return;
|
|
963
|
+
}
|
|
964
|
+
setAllBundle({ items, patch: parts.join("\n\n") });
|
|
965
|
+
setStep(STEPS2.CONFIRM_ALL);
|
|
966
|
+
return;
|
|
967
|
+
}
|
|
776
968
|
if (directSkills && directSkills.length > 0) {
|
|
777
969
|
const items = [];
|
|
778
970
|
const skipped = [];
|
|
@@ -832,46 +1024,88 @@ function Update({ directSkills }) {
|
|
|
832
1024
|
advance();
|
|
833
1025
|
return;
|
|
834
1026
|
}
|
|
835
|
-
let localFile;
|
|
836
|
-
let latestFile;
|
|
837
1027
|
if (item.type === "skill") {
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
1028
|
+
const localDir = path4.join(destRoot, targetConfig.skillsDir, item.name);
|
|
1029
|
+
const latestDir = path4.join(getCollectionsDir(), collection, "skills", item.name);
|
|
1030
|
+
if (!fs4.existsSync(localDir) || !fs4.existsSync(latestDir)) {
|
|
1031
|
+
recordSkip(item.name, "source or local directory missing");
|
|
1032
|
+
advance();
|
|
1033
|
+
return;
|
|
1034
|
+
}
|
|
1035
|
+
if (!hasDirChanges(localDir, latestDir)) {
|
|
1036
|
+
recordSkip(item.name, `already up-to-date with ${collection}`);
|
|
1037
|
+
advance();
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1040
|
+
setCurrentPatch(computeDirDiff(localDir, latestDir));
|
|
1041
|
+
setStep(STEPS2.CONFIRM);
|
|
1042
|
+
return;
|
|
843
1043
|
}
|
|
844
|
-
|
|
1044
|
+
const localFile = path4.join(destRoot, targetConfig.agentsDir, `${item.name}.md`);
|
|
1045
|
+
const latestFile = path4.join(getCollectionsDir(), collection, "agents", `${item.name}.md`);
|
|
1046
|
+
if (!fs4.existsSync(localFile) || !fs4.existsSync(latestFile)) {
|
|
1047
|
+
recordSkip(item.name, "source or local file missing");
|
|
845
1048
|
advance();
|
|
846
1049
|
return;
|
|
847
1050
|
}
|
|
848
|
-
const localContent =
|
|
849
|
-
const latestContent =
|
|
1051
|
+
const localContent = fs4.readFileSync(localFile, "utf-8");
|
|
1052
|
+
const latestContent = fs4.readFileSync(latestFile, "utf-8");
|
|
850
1053
|
if (!hasChanges(localContent, latestContent)) {
|
|
851
|
-
|
|
1054
|
+
recordSkip(item.name, `already up-to-date with ${collection}`);
|
|
852
1055
|
advance();
|
|
853
1056
|
return;
|
|
854
1057
|
}
|
|
855
|
-
|
|
856
|
-
setCurrentPatch(computeDiff(filename, localContent, latestContent));
|
|
1058
|
+
setCurrentPatch(computeDiff(`${item.name}.md`, localContent, latestContent));
|
|
857
1059
|
setStep(STEPS2.CONFIRM);
|
|
858
1060
|
}
|
|
1061
|
+
function recordSkip(name, reason) {
|
|
1062
|
+
setSkippedCount((c) => c + 1);
|
|
1063
|
+
setSkipReasons((prev) => [...prev, { name, reason }]);
|
|
1064
|
+
}
|
|
1065
|
+
function handleConfirmAll(yes) {
|
|
1066
|
+
const targetConfig = targets[targetKey];
|
|
1067
|
+
if (!yes) {
|
|
1068
|
+
const declined = allBundle.items.map((it) => ({
|
|
1069
|
+
name: it.name,
|
|
1070
|
+
reason: "declined (bulk)"
|
|
1071
|
+
}));
|
|
1072
|
+
setSkipReasons((prev) => [...prev, ...declined]);
|
|
1073
|
+
setSkippedCount((c) => c + declined.length);
|
|
1074
|
+
setStep(STEPS2.DONE);
|
|
1075
|
+
return;
|
|
1076
|
+
}
|
|
1077
|
+
let updated = 0;
|
|
1078
|
+
for (const item of allBundle.items) {
|
|
1079
|
+
if (item.type === "skill") {
|
|
1080
|
+
const src = path4.join(getCollectionsDir(), selectedCollection, "skills", item.name);
|
|
1081
|
+
const dest = path4.join(destRoot, targetConfig.skillsDir, item.name);
|
|
1082
|
+
fs4.copySync(src, dest, { overwrite: true });
|
|
1083
|
+
} else {
|
|
1084
|
+
const src = path4.join(getCollectionsDir(), selectedCollection, "agents", `${item.name}.md`);
|
|
1085
|
+
const dest = path4.join(destRoot, targetConfig.agentsDir, `${item.name}.md`);
|
|
1086
|
+
fs4.copySync(src, dest, { overwrite: true });
|
|
1087
|
+
}
|
|
1088
|
+
updated++;
|
|
1089
|
+
}
|
|
1090
|
+
setUpdatedCount((c) => c + updated);
|
|
1091
|
+
setStep(STEPS2.DONE);
|
|
1092
|
+
}
|
|
859
1093
|
function handleConfirm(yes) {
|
|
860
1094
|
const item = queue[currentIdx];
|
|
861
1095
|
const targetConfig = targets[targetKey];
|
|
862
1096
|
if (yes) {
|
|
863
1097
|
if (item.type === "skill") {
|
|
864
|
-
const src =
|
|
865
|
-
const dest =
|
|
866
|
-
|
|
1098
|
+
const src = path4.join(getCollectionsDir(), selectedCollection, "skills", item.name);
|
|
1099
|
+
const dest = path4.join(destRoot, targetConfig.skillsDir, item.name);
|
|
1100
|
+
fs4.copySync(src, dest, { overwrite: true });
|
|
867
1101
|
} else {
|
|
868
|
-
const src =
|
|
869
|
-
const dest =
|
|
870
|
-
|
|
1102
|
+
const src = path4.join(getCollectionsDir(), selectedCollection, "agents", `${item.name}.md`);
|
|
1103
|
+
const dest = path4.join(destRoot, targetConfig.agentsDir, `${item.name}.md`);
|
|
1104
|
+
fs4.copySync(src, dest, { overwrite: true });
|
|
871
1105
|
}
|
|
872
1106
|
setUpdatedCount((c) => c + 1);
|
|
873
1107
|
} else {
|
|
874
|
-
|
|
1108
|
+
recordSkip(item.name, "declined");
|
|
875
1109
|
}
|
|
876
1110
|
advance();
|
|
877
1111
|
}
|
|
@@ -956,6 +1190,23 @@ function Update({ directSkills }) {
|
|
|
956
1190
|
if (step === STEPS2.RESOLVE) {
|
|
957
1191
|
return /* @__PURE__ */ jsx7(Text8, { color: "yellow", children: "Checking..." });
|
|
958
1192
|
}
|
|
1193
|
+
if (step === STEPS2.CONFIRM_ALL) {
|
|
1194
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
1195
|
+
/* @__PURE__ */ jsxs7(Warning, { children: [
|
|
1196
|
+
allBundle.items.length,
|
|
1197
|
+
" item(s) differ from ",
|
|
1198
|
+
selectedCollection
|
|
1199
|
+
] }),
|
|
1200
|
+
/* @__PURE__ */ jsx7(DiffView, { patch: allBundle.patch }),
|
|
1201
|
+
/* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsx7(
|
|
1202
|
+
Confirm,
|
|
1203
|
+
{
|
|
1204
|
+
message: `Apply all ${allBundle.items.length} updates?`,
|
|
1205
|
+
onConfirm: handleConfirmAll
|
|
1206
|
+
}
|
|
1207
|
+
) })
|
|
1208
|
+
] });
|
|
1209
|
+
}
|
|
959
1210
|
if (step === STEPS2.CONFIRM) {
|
|
960
1211
|
const item = queue[currentIdx];
|
|
961
1212
|
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
@@ -975,17 +1226,26 @@ function Update({ directSkills }) {
|
|
|
975
1226
|
}
|
|
976
1227
|
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
977
1228
|
missingNames.length > 0 && /* @__PURE__ */ jsxs7(ErrorMsg, { children: [
|
|
978
|
-
"
|
|
1229
|
+
"Not found: ",
|
|
979
1230
|
missingNames.join(", ")
|
|
980
1231
|
] }),
|
|
981
|
-
/* @__PURE__ */ jsxs7(
|
|
1232
|
+
skipReasons.length > 0 && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", marginTop: 1, children: [
|
|
1233
|
+
/* @__PURE__ */ jsx7(Info, { children: "Skipped:" }),
|
|
1234
|
+
skipReasons.map((s, i) => /* @__PURE__ */ jsxs7(Text8, { color: "gray", children: [
|
|
1235
|
+
" \u2022 ",
|
|
1236
|
+
s.name,
|
|
1237
|
+
" \u2014 ",
|
|
1238
|
+
s.reason
|
|
1239
|
+
] }, `${s.name}-${i}`))
|
|
1240
|
+
] }),
|
|
1241
|
+
/* @__PURE__ */ jsx7(Box7, { marginTop: 1, children: /* @__PURE__ */ jsxs7(Success, { children: [
|
|
982
1242
|
updatedCount,
|
|
983
1243
|
" updated, ",
|
|
984
1244
|
installedCount,
|
|
985
1245
|
" installed, ",
|
|
986
1246
|
skippedCount,
|
|
987
1247
|
" skipped"
|
|
988
|
-
] })
|
|
1248
|
+
] }) })
|
|
989
1249
|
] });
|
|
990
1250
|
}
|
|
991
1251
|
return null;
|
|
@@ -994,8 +1254,8 @@ function Update({ directSkills }) {
|
|
|
994
1254
|
// src/commands/Remove.jsx
|
|
995
1255
|
import React9, { useState as useState5 } from "react";
|
|
996
1256
|
import { Box as Box8, Text as Text9, useApp as useApp4 } from "ink";
|
|
997
|
-
import
|
|
998
|
-
import
|
|
1257
|
+
import path5 from "path";
|
|
1258
|
+
import fs5 from "fs-extra";
|
|
999
1259
|
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1000
1260
|
var STEPS3 = {
|
|
1001
1261
|
TARGET: "target",
|
|
@@ -1015,9 +1275,9 @@ function Remove({ skillNames }) {
|
|
|
1015
1275
|
const targetConfig = targets[key];
|
|
1016
1276
|
const missing = [];
|
|
1017
1277
|
for (const name of skillNames) {
|
|
1018
|
-
const skillPath =
|
|
1019
|
-
const agentPath =
|
|
1020
|
-
if (!
|
|
1278
|
+
const skillPath = path5.join(destRoot, targetConfig.skillsDir, name);
|
|
1279
|
+
const agentPath = path5.join(destRoot, targetConfig.agentsDir, `${name}.md`);
|
|
1280
|
+
if (!fs5.existsSync(skillPath) && !fs5.existsSync(agentPath)) {
|
|
1021
1281
|
missing.push(name);
|
|
1022
1282
|
}
|
|
1023
1283
|
}
|
|
@@ -1086,18 +1346,20 @@ var command = args[0];
|
|
|
1086
1346
|
var restArgs = args.slice(1);
|
|
1087
1347
|
function Help() {
|
|
1088
1348
|
const commands = [
|
|
1089
|
-
{ name: "add [skills...]", desc: "Install skills/agents (interactive if no args)" },
|
|
1349
|
+
{ name: "add [skills...] [--all]", desc: "Install skills/agents (interactive if no args; --all installs everything in chosen collection)" },
|
|
1090
1350
|
{ name: "list", desc: "List all available skills and agents" },
|
|
1091
|
-
{ name: "update [skills...]", desc: "Update installed skills (interactive if no args)" },
|
|
1351
|
+
{ name: "update [skills...] [--all]", desc: "Update installed skills (interactive if no args; --all updates everything in chosen collection)" },
|
|
1092
1352
|
{ name: "remove <skills>", desc: "Remove installed skills/agents" },
|
|
1093
1353
|
{ name: "help", desc: "Show this help message" }
|
|
1094
1354
|
];
|
|
1095
1355
|
const examples = [
|
|
1096
1356
|
"npx @hiver/skills add",
|
|
1097
1357
|
"npx @hiver/skills add discuss-problem create-prd",
|
|
1358
|
+
"npx @hiver/skills add --all",
|
|
1098
1359
|
"npx @hiver/skills list",
|
|
1099
1360
|
"npx @hiver/skills update",
|
|
1100
1361
|
"npx @hiver/skills update build-component",
|
|
1362
|
+
"npx @hiver/skills update --all",
|
|
1101
1363
|
"npx @hiver/skills remove discuss-problem"
|
|
1102
1364
|
];
|
|
1103
1365
|
return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", marginTop: 1, marginBottom: 1, children: [
|
|
@@ -1129,12 +1391,30 @@ function Help() {
|
|
|
1129
1391
|
}
|
|
1130
1392
|
function App() {
|
|
1131
1393
|
switch (command) {
|
|
1132
|
-
case "add":
|
|
1133
|
-
|
|
1394
|
+
case "add": {
|
|
1395
|
+
const all = restArgs.includes("--all");
|
|
1396
|
+
const names = restArgs.filter((a) => !a.startsWith("--"));
|
|
1397
|
+
return /* @__PURE__ */ jsx9(
|
|
1398
|
+
Add,
|
|
1399
|
+
{
|
|
1400
|
+
directSkills: names.length > 0 ? names : null,
|
|
1401
|
+
addAll: all
|
|
1402
|
+
}
|
|
1403
|
+
);
|
|
1404
|
+
}
|
|
1134
1405
|
case "list":
|
|
1135
1406
|
return /* @__PURE__ */ jsx9(List, {});
|
|
1136
|
-
case "update":
|
|
1137
|
-
|
|
1407
|
+
case "update": {
|
|
1408
|
+
const all = restArgs.includes("--all");
|
|
1409
|
+
const names = restArgs.filter((a) => !a.startsWith("--"));
|
|
1410
|
+
return /* @__PURE__ */ jsx9(
|
|
1411
|
+
Update,
|
|
1412
|
+
{
|
|
1413
|
+
directSkills: names.length > 0 ? names : null,
|
|
1414
|
+
updateAll: all
|
|
1415
|
+
}
|
|
1416
|
+
);
|
|
1417
|
+
}
|
|
1138
1418
|
case "remove":
|
|
1139
1419
|
if (restArgs.length === 0) {
|
|
1140
1420
|
return /* @__PURE__ */ jsxs9(Text10, { color: "red", children: [
|