playbooks 0.1.16 → 0.1.17
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 +833 -466
- 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.17",
|
|
12
12
|
description: "Install agent skills, MCPs and docs into your coding agents from any git repository.",
|
|
13
13
|
type: "module",
|
|
14
14
|
bin: {
|
|
@@ -4571,12 +4571,16 @@ async function recordParsedTracking(skills, results, installGlobally, parsed, te
|
|
|
4571
4571
|
const hash = await fetchSkillFolderHash(normalizedSource, skillPathValue);
|
|
4572
4572
|
if (hash) skillFolderHash = hash;
|
|
4573
4573
|
}
|
|
4574
|
+
if (parsed.type === "well-known" && parsed.contentHash) {
|
|
4575
|
+
skillFolderHash = parsed.contentHash;
|
|
4576
|
+
}
|
|
4574
4577
|
await addSkillToLock(
|
|
4575
4578
|
displayName,
|
|
4576
4579
|
{
|
|
4577
4580
|
source: normalizedSource ?? parsed.url,
|
|
4578
4581
|
sourceType: parsed.type,
|
|
4579
4582
|
sourceUrl: parsed.url,
|
|
4583
|
+
...parsed.type === "well-known" && parsed.licenseKey ? { licenseKey: parsed.licenseKey } : {},
|
|
4580
4584
|
skillPath: skillPathValue,
|
|
4581
4585
|
skillFolderHash,
|
|
4582
4586
|
ref: parsed.ref
|
|
@@ -4646,7 +4650,10 @@ function formatResultSummary(results) {
|
|
|
4646
4650
|
if (!firstResult) continue;
|
|
4647
4651
|
if (firstResult.mode === "copy") {
|
|
4648
4652
|
lines.push(`${chalk2.green("\u2713")} ${skillName} ${chalk2.dim("(copied)")}`);
|
|
4653
|
+
const seenPaths = /* @__PURE__ */ new Set();
|
|
4649
4654
|
for (const r of skillResults) {
|
|
4655
|
+
if (seenPaths.has(r.path)) continue;
|
|
4656
|
+
seenPaths.add(r.path);
|
|
4650
4657
|
const shortPath = shortenPath(r.path, cwd);
|
|
4651
4658
|
lines.push(` ${chalk2.dim("\u2192")} ${shortPath}`);
|
|
4652
4659
|
}
|
|
@@ -4754,15 +4761,51 @@ function AddInstallScreen() {
|
|
|
4754
4761
|
] });
|
|
4755
4762
|
}
|
|
4756
4763
|
|
|
4757
|
-
// src/tui/screens/
|
|
4758
|
-
import {
|
|
4759
|
-
import
|
|
4764
|
+
// src/tui/screens/AddLicenseKey.tsx
|
|
4765
|
+
import { Box as Box14, Text as Text14 } from "ink";
|
|
4766
|
+
import TextInput2 from "ink-text-input";
|
|
4760
4767
|
import React11 from "react";
|
|
4761
4768
|
import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
4769
|
+
function AddLicenseKeyScreen() {
|
|
4770
|
+
const { invocation, addSkill, updateAddSkill, navigateTo, setFlash } = useNavigation();
|
|
4771
|
+
const [value, setValue] = React11.useState(
|
|
4772
|
+
addSkill.licenseKey ?? invocation.options.licenseKey ?? ""
|
|
4773
|
+
);
|
|
4774
|
+
const { wrapOnChange } = useTextInput({
|
|
4775
|
+
onClear: () => {
|
|
4776
|
+
setValue("");
|
|
4777
|
+
}
|
|
4778
|
+
});
|
|
4779
|
+
const onSubmit = (input) => {
|
|
4780
|
+
const trimmed = input.trim();
|
|
4781
|
+
if (!trimmed) {
|
|
4782
|
+
setFlash("Enter a license key.");
|
|
4783
|
+
return;
|
|
4784
|
+
}
|
|
4785
|
+
updateAddSkill({ licenseKey: trimmed });
|
|
4786
|
+
navigateTo("add-skill-select");
|
|
4787
|
+
};
|
|
4788
|
+
return /* @__PURE__ */ jsxs12(Box14, { flexDirection: "column", padding: 1, children: [
|
|
4789
|
+
/* @__PURE__ */ jsx16(Header, { title: "License key" }),
|
|
4790
|
+
/* @__PURE__ */ jsx16(Box14, { marginBottom: 1, children: /* @__PURE__ */ jsx16(Text14, { children: "Enter the license key for this paid/private skill." }) }),
|
|
4791
|
+
/* @__PURE__ */ jsx16(Box14, { marginBottom: 1, children: /* @__PURE__ */ jsx16(Text14, { dimColor: true, children: "Tip: you can also pass it via --license-key." }) }),
|
|
4792
|
+
/* @__PURE__ */ jsxs12(Box14, { children: [
|
|
4793
|
+
/* @__PURE__ */ jsx16(Text14, { color: "green", children: "> " }),
|
|
4794
|
+
/* @__PURE__ */ jsx16(TextInput2, { value, onChange: wrapOnChange(setValue), onSubmit })
|
|
4795
|
+
] }),
|
|
4796
|
+
/* @__PURE__ */ jsx16(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx16(Text14, { dimColor: true, children: TEXT_INPUT_HINT }) })
|
|
4797
|
+
] });
|
|
4798
|
+
}
|
|
4799
|
+
|
|
4800
|
+
// src/tui/screens/AddMode.tsx
|
|
4801
|
+
import { join as join12 } from "path";
|
|
4802
|
+
import { Box as Box15 } from "ink";
|
|
4803
|
+
import React12 from "react";
|
|
4804
|
+
import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
4762
4805
|
function AddModeScreen() {
|
|
4763
4806
|
const { invocation, addSkill, updateAddSkill, navigateTo, navAction } = useNavigation();
|
|
4764
4807
|
const options = invocation.options;
|
|
4765
|
-
|
|
4808
|
+
React12.useEffect(() => {
|
|
4766
4809
|
if (navAction === "pop") return;
|
|
4767
4810
|
if (addSkill.installMode) {
|
|
4768
4811
|
navigateTo("add-confirm");
|
|
@@ -4792,9 +4835,9 @@ function AddModeScreen() {
|
|
|
4792
4835
|
{ label: "Symlink (recommended)", value: "symlink", hint: symlinkHint },
|
|
4793
4836
|
{ label: "Copy to each agent", value: "copy", hint: copyHint }
|
|
4794
4837
|
];
|
|
4795
|
-
return /* @__PURE__ */
|
|
4796
|
-
/* @__PURE__ */
|
|
4797
|
-
/* @__PURE__ */
|
|
4838
|
+
return /* @__PURE__ */ jsxs13(Box15, { flexDirection: "column", padding: 1, children: [
|
|
4839
|
+
/* @__PURE__ */ jsx17(AddFlowHeader, { title: "Install mode" }),
|
|
4840
|
+
/* @__PURE__ */ jsx17(
|
|
4798
4841
|
SingleSelect,
|
|
4799
4842
|
{
|
|
4800
4843
|
items,
|
|
@@ -4810,9 +4853,9 @@ function AddModeScreen() {
|
|
|
4810
4853
|
|
|
4811
4854
|
// src/tui/screens/AddResult.tsx
|
|
4812
4855
|
import chalk3 from "chalk";
|
|
4813
|
-
import { Box as
|
|
4814
|
-
import
|
|
4815
|
-
import { jsx as
|
|
4856
|
+
import { Box as Box16, Text as Text15 } from "ink";
|
|
4857
|
+
import React13 from "react";
|
|
4858
|
+
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
4816
4859
|
function AddResultScreen() {
|
|
4817
4860
|
const { addSkill, resetAddSkill, navigateTo } = useNavigation();
|
|
4818
4861
|
const results = addSkill.installResults ?? [];
|
|
@@ -4820,7 +4863,7 @@ function AddResultScreen() {
|
|
|
4820
4863
|
const failed = results.filter((r) => !r.success);
|
|
4821
4864
|
const symlinkFailures = successful.filter((r) => r.mode === "symlink" && r.symlinkFailed);
|
|
4822
4865
|
const summary = successful.length > 0 ? formatResultSummary(successful) : null;
|
|
4823
|
-
const summaryLines =
|
|
4866
|
+
const summaryLines = React13.useMemo(() => {
|
|
4824
4867
|
if (!summary) return [];
|
|
4825
4868
|
const counts = /* @__PURE__ */ new Map();
|
|
4826
4869
|
return summary.lines.map((line) => {
|
|
@@ -4829,15 +4872,15 @@ function AddResultScreen() {
|
|
|
4829
4872
|
return { line, key: `${line}-${count}` };
|
|
4830
4873
|
});
|
|
4831
4874
|
}, [summary]);
|
|
4832
|
-
return /* @__PURE__ */
|
|
4833
|
-
/* @__PURE__ */
|
|
4834
|
-
summary ? /* @__PURE__ */
|
|
4835
|
-
/* @__PURE__ */
|
|
4836
|
-
summaryLines.map(({ line, key }) => /* @__PURE__ */
|
|
4875
|
+
return /* @__PURE__ */ jsxs14(Box16, { flexDirection: "column", padding: 1, children: [
|
|
4876
|
+
/* @__PURE__ */ jsx18(AddFlowHeader, { title: "Install results" }),
|
|
4877
|
+
summary ? /* @__PURE__ */ jsxs14(Box16, { flexDirection: "column", marginBottom: 1, children: [
|
|
4878
|
+
/* @__PURE__ */ jsx18(Text15, { children: summary.title }),
|
|
4879
|
+
summaryLines.map(({ line, key }) => /* @__PURE__ */ jsx18(Text15, { children: line }, key))
|
|
4837
4880
|
] }) : null,
|
|
4838
|
-
failed.length > 0 ? /* @__PURE__ */
|
|
4839
|
-
/* @__PURE__ */
|
|
4840
|
-
failed.map((r) => /* @__PURE__ */
|
|
4881
|
+
failed.length > 0 ? /* @__PURE__ */ jsxs14(Box16, { flexDirection: "column", marginBottom: 1, children: [
|
|
4882
|
+
/* @__PURE__ */ jsx18(Text15, { color: "red", children: `Failed to install ${failed.length}` }),
|
|
4883
|
+
failed.map((r) => /* @__PURE__ */ jsxs14(Text15, { children: [
|
|
4841
4884
|
chalk3.red("\u2717"),
|
|
4842
4885
|
" ",
|
|
4843
4886
|
r.skill,
|
|
@@ -4847,15 +4890,15 @@ function AddResultScreen() {
|
|
|
4847
4890
|
chalk3.dim(r.error)
|
|
4848
4891
|
] }, `${r.skill}-${r.agentId}`))
|
|
4849
4892
|
] }) : null,
|
|
4850
|
-
successful.length > 0 ? /* @__PURE__ */
|
|
4893
|
+
successful.length > 0 ? /* @__PURE__ */ jsx18(Box16, { marginBottom: 1, children: /* @__PURE__ */ jsxs14(Text15, { dimColor: true, children: [
|
|
4851
4894
|
"Installed to: ",
|
|
4852
4895
|
formatList(successful.map((r) => r.agent))
|
|
4853
4896
|
] }) }) : null,
|
|
4854
|
-
symlinkFailures.length > 0 ? /* @__PURE__ */
|
|
4855
|
-
/* @__PURE__ */
|
|
4856
|
-
/* @__PURE__ */
|
|
4897
|
+
symlinkFailures.length > 0 ? /* @__PURE__ */ jsxs14(Box16, { marginBottom: 1, children: [
|
|
4898
|
+
/* @__PURE__ */ jsx18(Text15, { color: "yellow", children: `Symlinks failed for: ${formatList(symlinkFailures.map((r) => r.agent))}` }),
|
|
4899
|
+
/* @__PURE__ */ jsx18(Text15, { dimColor: true, children: "Files were copied instead." })
|
|
4857
4900
|
] }) : null,
|
|
4858
|
-
/* @__PURE__ */
|
|
4901
|
+
/* @__PURE__ */ jsx18(
|
|
4859
4902
|
SelectMenu,
|
|
4860
4903
|
{
|
|
4861
4904
|
items: [
|
|
@@ -4878,13 +4921,13 @@ function AddResultScreen() {
|
|
|
4878
4921
|
}
|
|
4879
4922
|
|
|
4880
4923
|
// src/tui/screens/AddScope.tsx
|
|
4881
|
-
import { Box as
|
|
4882
|
-
import
|
|
4883
|
-
import { jsx as
|
|
4924
|
+
import { Box as Box17 } from "ink";
|
|
4925
|
+
import React14 from "react";
|
|
4926
|
+
import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
4884
4927
|
function AddScopeScreen() {
|
|
4885
4928
|
const { invocation, addSkill, updateAddSkill, navigateTo, navAction } = useNavigation();
|
|
4886
4929
|
const options = invocation.options;
|
|
4887
|
-
|
|
4930
|
+
React14.useEffect(() => {
|
|
4888
4931
|
if (navAction === "pop") return;
|
|
4889
4932
|
if (addSkill.installGlobally !== void 0) {
|
|
4890
4933
|
navigateTo("add-mode");
|
|
@@ -4907,9 +4950,9 @@ function AddScopeScreen() {
|
|
|
4907
4950
|
const globalBase = getCanonicalSkillsBase({ global: true, cwd });
|
|
4908
4951
|
const projectHint = `Project base (symlink): ${shortenPath(projectBase, cwd)}`;
|
|
4909
4952
|
const globalHint = `Global base (symlink): ${shortenPath(globalBase, cwd)}`;
|
|
4910
|
-
return /* @__PURE__ */
|
|
4911
|
-
/* @__PURE__ */
|
|
4912
|
-
/* @__PURE__ */
|
|
4953
|
+
return /* @__PURE__ */ jsxs15(Box17, { flexDirection: "column", padding: 1, children: [
|
|
4954
|
+
/* @__PURE__ */ jsx19(AddFlowHeader, { title: "Install scope" }),
|
|
4955
|
+
/* @__PURE__ */ jsx19(
|
|
4913
4956
|
SingleSelect,
|
|
4914
4957
|
{
|
|
4915
4958
|
items: [
|
|
@@ -4931,23 +4974,23 @@ function AddScopeScreen() {
|
|
|
4931
4974
|
}
|
|
4932
4975
|
|
|
4933
4976
|
// src/tui/screens/AddSecurityScan.tsx
|
|
4934
|
-
import { Box as
|
|
4935
|
-
import
|
|
4936
|
-
import { jsx as
|
|
4977
|
+
import { Box as Box18, Text as Text16 } from "ink";
|
|
4978
|
+
import React15 from "react";
|
|
4979
|
+
import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
4937
4980
|
function AddSecurityScanScreen() {
|
|
4938
4981
|
const { invocation, addSkill, updateAddSkill, navigateTo, resetTo, setFlash, setBackHandler } = useNavigation();
|
|
4939
4982
|
const options = invocation.options;
|
|
4940
|
-
const [status, setStatus] =
|
|
4941
|
-
const [error, setError] =
|
|
4942
|
-
const [manualView, setManualView] =
|
|
4943
|
-
const [confirmText, setConfirmText] =
|
|
4944
|
-
const [selectedRow, setSelectedRow] =
|
|
4983
|
+
const [status, setStatus] = React15.useState("scanning");
|
|
4984
|
+
const [error, setError] = React15.useState(null);
|
|
4985
|
+
const [manualView, setManualView] = React15.useState("menu");
|
|
4986
|
+
const [confirmText, setConfirmText] = React15.useState("");
|
|
4987
|
+
const [selectedRow, setSelectedRow] = React15.useState(null);
|
|
4945
4988
|
const spinner = useSpinnerFrame(status === "scanning");
|
|
4946
4989
|
const { wrapOnChange } = useTextInput({
|
|
4947
4990
|
onClear: () => setConfirmText(""),
|
|
4948
4991
|
disabled: status !== "risky" || manualView !== "type-confirm"
|
|
4949
4992
|
});
|
|
4950
|
-
|
|
4993
|
+
React15.useEffect(() => {
|
|
4951
4994
|
const selectedSkills = addSkill.selectedSkills;
|
|
4952
4995
|
if (!selectedSkills || selectedSkills.length === 0) {
|
|
4953
4996
|
navigateTo("add-skill-select");
|
|
@@ -4987,7 +5030,7 @@ function AddSecurityScanScreen() {
|
|
|
4987
5030
|
cancelled = true;
|
|
4988
5031
|
};
|
|
4989
5032
|
}, [addSkill.selectedSkills, navigateTo, updateAddSkill]);
|
|
4990
|
-
|
|
5033
|
+
React15.useEffect(() => {
|
|
4991
5034
|
if (status !== "risky") {
|
|
4992
5035
|
setBackHandler(null);
|
|
4993
5036
|
return () => setBackHandler(null);
|
|
@@ -5011,17 +5054,17 @@ function AddSecurityScanScreen() {
|
|
|
5011
5054
|
return () => setBackHandler(null);
|
|
5012
5055
|
}, [status, manualView, setBackHandler]);
|
|
5013
5056
|
if (status === "error") {
|
|
5014
|
-
return /* @__PURE__ */
|
|
5015
|
-
/* @__PURE__ */
|
|
5016
|
-
/* @__PURE__ */
|
|
5017
|
-
/* @__PURE__ */
|
|
5057
|
+
return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", padding: 1, children: [
|
|
5058
|
+
/* @__PURE__ */ jsx20(AddFlowHeader, { title: "Security scan" }),
|
|
5059
|
+
/* @__PURE__ */ jsx20(Text16, { color: "red", children: error ?? "Scan failed" }),
|
|
5060
|
+
/* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(Text16, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
5018
5061
|
] });
|
|
5019
5062
|
}
|
|
5020
5063
|
if (status === "scanning") {
|
|
5021
5064
|
const count = addSkill.selectedSkills?.length ?? 0;
|
|
5022
|
-
return /* @__PURE__ */
|
|
5023
|
-
/* @__PURE__ */
|
|
5024
|
-
/* @__PURE__ */
|
|
5065
|
+
return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", padding: 1, children: [
|
|
5066
|
+
/* @__PURE__ */ jsx20(AddFlowHeader, { title: "Security scan" }),
|
|
5067
|
+
/* @__PURE__ */ jsxs16(Text16, { children: [
|
|
5025
5068
|
spinner,
|
|
5026
5069
|
" Scanning ",
|
|
5027
5070
|
count,
|
|
@@ -5032,9 +5075,9 @@ function AddSecurityScanScreen() {
|
|
|
5032
5075
|
] });
|
|
5033
5076
|
}
|
|
5034
5077
|
if (status === "risky") {
|
|
5035
|
-
return /* @__PURE__ */
|
|
5036
|
-
/* @__PURE__ */
|
|
5037
|
-
/* @__PURE__ */
|
|
5078
|
+
return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", padding: 1, children: [
|
|
5079
|
+
/* @__PURE__ */ jsx20(AddFlowHeader, { title: "Security scan" }),
|
|
5080
|
+
/* @__PURE__ */ jsx20(
|
|
5038
5081
|
ManualSecurityGate,
|
|
5039
5082
|
{
|
|
5040
5083
|
scanRows: addSkill.securityScanRows ?? [],
|
|
@@ -5058,12 +5101,12 @@ function AddSecurityScanScreen() {
|
|
|
5058
5101
|
] });
|
|
5059
5102
|
}
|
|
5060
5103
|
if (options.yes) {
|
|
5061
|
-
return /* @__PURE__ */
|
|
5104
|
+
return /* @__PURE__ */ jsx20(Box18, { padding: 1 });
|
|
5062
5105
|
}
|
|
5063
|
-
return /* @__PURE__ */
|
|
5064
|
-
/* @__PURE__ */
|
|
5065
|
-
/* @__PURE__ */
|
|
5066
|
-
/* @__PURE__ */
|
|
5106
|
+
return /* @__PURE__ */ jsxs16(Box18, { flexDirection: "column", padding: 1, children: [
|
|
5107
|
+
/* @__PURE__ */ jsx20(AddFlowHeader, { title: "Security scan" }),
|
|
5108
|
+
/* @__PURE__ */ jsx20(Text16, { dimColor: true, children: "Scan complete." }),
|
|
5109
|
+
/* @__PURE__ */ jsx20(Box18, { marginTop: 1, children: /* @__PURE__ */ jsx20(Text16, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
5067
5110
|
] });
|
|
5068
5111
|
}
|
|
5069
5112
|
|
|
@@ -5072,8 +5115,8 @@ import { existsSync as existsSync6 } from "fs";
|
|
|
5072
5115
|
import { mkdir as mkdir6, mkdtemp as mkdtemp4, writeFile as writeFile4 } from "fs/promises";
|
|
5073
5116
|
import { tmpdir as tmpdir5 } from "os";
|
|
5074
5117
|
import { join as join15 } from "path";
|
|
5075
|
-
import { Box as
|
|
5076
|
-
import
|
|
5118
|
+
import { Box as Box19, Text as Text17 } from "ink";
|
|
5119
|
+
import React16 from "react";
|
|
5077
5120
|
|
|
5078
5121
|
// src/mintlify.ts
|
|
5079
5122
|
import matter3 from "gray-matter";
|
|
@@ -5346,7 +5389,18 @@ var WellKnownProvider = class {
|
|
|
5346
5389
|
try {
|
|
5347
5390
|
const parsed = new URL(baseUrl);
|
|
5348
5391
|
const basePath = parsed.pathname.replace(/\/$/, "");
|
|
5392
|
+
const indexSuffix = `/${this.WELL_KNOWN_PATH}/${this.INDEX_FILE}`;
|
|
5349
5393
|
const urlsToTry = [
|
|
5394
|
+
// If the caller already passed the index.json URL, try it directly.
|
|
5395
|
+
...basePath.endsWith(indexSuffix) ? [
|
|
5396
|
+
{
|
|
5397
|
+
indexUrl: `${parsed.protocol}//${parsed.host}${basePath}`,
|
|
5398
|
+
baseUrl: `${parsed.protocol}//${parsed.host}${basePath.slice(
|
|
5399
|
+
0,
|
|
5400
|
+
Math.max(0, basePath.length - indexSuffix.length)
|
|
5401
|
+
)}`
|
|
5402
|
+
}
|
|
5403
|
+
] : [],
|
|
5350
5404
|
{
|
|
5351
5405
|
indexUrl: `${parsed.protocol}//${parsed.host}${basePath}/${this.WELL_KNOWN_PATH}/${this.INDEX_FILE}`,
|
|
5352
5406
|
baseUrl: `${parsed.protocol}//${parsed.host}${basePath}`
|
|
@@ -5391,19 +5445,46 @@ var WellKnownProvider = class {
|
|
|
5391
5445
|
const e = entry;
|
|
5392
5446
|
if (typeof e.name !== "string" || !e.name) return false;
|
|
5393
5447
|
if (typeof e.description !== "string" || !e.description) return false;
|
|
5394
|
-
if (!Array.isArray(e.files) || e.files.length === 0) return false;
|
|
5395
5448
|
const nameRegex = /^[a-z0-9]([a-z0-9-]{0,62}[a-z0-9])?$/;
|
|
5396
5449
|
if (!nameRegex.test(e.name) && e.name.length > 1) {
|
|
5397
5450
|
if (e.name.length === 1 && !/^[a-z0-9]$/.test(e.name)) {
|
|
5398
5451
|
return false;
|
|
5399
5452
|
}
|
|
5400
5453
|
}
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5454
|
+
if (Array.isArray(e.files) && e.files.length > 0) {
|
|
5455
|
+
for (const file of e.files) {
|
|
5456
|
+
if (typeof file !== "string") return false;
|
|
5457
|
+
if (file.startsWith("/") || file.startsWith("\\") || file.includes("..")) return false;
|
|
5458
|
+
}
|
|
5459
|
+
const hasSkillMd2 = e.files.some(
|
|
5460
|
+
(f) => typeof f === "string" && f.toLowerCase() === "skill.md"
|
|
5461
|
+
);
|
|
5462
|
+
if (!hasSkillMd2) return false;
|
|
5463
|
+
return true;
|
|
5464
|
+
}
|
|
5465
|
+
if (!e.content || typeof e.content !== "object") return false;
|
|
5466
|
+
const c = e.content;
|
|
5467
|
+
if (typeof c.endpoint !== "string" || !c.endpoint) return false;
|
|
5468
|
+
if (typeof c.method !== "string" || !c.method) return false;
|
|
5469
|
+
if (e.auth != null) {
|
|
5470
|
+
if (typeof e.auth !== "object") return false;
|
|
5471
|
+
const a = e.auth;
|
|
5472
|
+
if (typeof a.tokenHeader !== "string" || !a.tokenHeader) return false;
|
|
5473
|
+
if (a.tokenPrefix != null && typeof a.tokenPrefix !== "string") return false;
|
|
5474
|
+
} else {
|
|
5475
|
+
if (typeof c.tokenHeader !== "string" || !c.tokenHeader) return false;
|
|
5476
|
+
if (c.tokenPrefix != null && typeof c.tokenPrefix !== "string") return false;
|
|
5477
|
+
}
|
|
5478
|
+
if (e.verify != null) {
|
|
5479
|
+
if (typeof e.verify !== "object") return false;
|
|
5480
|
+
const v = e.verify;
|
|
5481
|
+
if (typeof v.endpoint !== "string" || !v.endpoint) return false;
|
|
5482
|
+
if (typeof v.method !== "string" || !v.method) return false;
|
|
5483
|
+
if (e.auth == null) {
|
|
5484
|
+
if (typeof v.tokenHeader !== "string" || !v.tokenHeader) return false;
|
|
5485
|
+
if (v.tokenPrefix != null && typeof v.tokenPrefix !== "string") return false;
|
|
5486
|
+
}
|
|
5404
5487
|
}
|
|
5405
|
-
const hasSkillMd2 = e.files.some((f) => typeof f === "string" && f.toLowerCase() === "skill.md");
|
|
5406
|
-
if (!hasSkillMd2) return false;
|
|
5407
5488
|
return true;
|
|
5408
5489
|
}
|
|
5409
5490
|
async fetchSkill(url) {
|
|
@@ -5450,6 +5531,9 @@ var WellKnownProvider = class {
|
|
|
5450
5531
|
}
|
|
5451
5532
|
async fetchSkillByEntry(baseUrl, entry) {
|
|
5452
5533
|
try {
|
|
5534
|
+
if (!("files" in entry)) {
|
|
5535
|
+
return null;
|
|
5536
|
+
}
|
|
5453
5537
|
const skillBaseUrl = `${baseUrl.replace(/\/$/, "")}/${this.WELL_KNOWN_PATH}/${entry.name}`;
|
|
5454
5538
|
const skillMdUrl = `${skillBaseUrl}/SKILL.md`;
|
|
5455
5539
|
const response = await fetch(skillMdUrl);
|
|
@@ -5610,9 +5694,82 @@ async function resolveRemoteSkill(url) {
|
|
|
5610
5694
|
import { mkdir as mkdir5, mkdtemp as mkdtemp3, writeFile as writeFile3 } from "fs/promises";
|
|
5611
5695
|
import { tmpdir as tmpdir4 } from "os";
|
|
5612
5696
|
import { dirname as dirname4, join as join13 } from "path";
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5697
|
+
var WellKnownLicenseKeyRequiredError = class extends Error {
|
|
5698
|
+
code = "LICENSE_KEY_REQUIRED";
|
|
5699
|
+
constructor() {
|
|
5700
|
+
super("A license key is required to install this skill.");
|
|
5701
|
+
}
|
|
5702
|
+
};
|
|
5703
|
+
function isStaticEntry(entry) {
|
|
5704
|
+
return "files" in entry;
|
|
5705
|
+
}
|
|
5706
|
+
function isAuthedEntry(entry) {
|
|
5707
|
+
return "content" in entry && !("files" in entry);
|
|
5708
|
+
}
|
|
5709
|
+
function resolveAuthForEndpoint(entry, endpoint) {
|
|
5710
|
+
if (entry.auth?.tokenHeader) {
|
|
5711
|
+
return { tokenHeader: entry.auth.tokenHeader, tokenPrefix: entry.auth.tokenPrefix ?? "" };
|
|
5712
|
+
}
|
|
5713
|
+
const spec = endpoint === "content" ? entry.content : entry.verify;
|
|
5714
|
+
const tokenHeader = spec?.tokenHeader;
|
|
5715
|
+
const tokenPrefix = spec?.tokenPrefix;
|
|
5716
|
+
if (typeof tokenHeader !== "string" || !tokenHeader) {
|
|
5717
|
+
throw new Error(
|
|
5718
|
+
"Invalid well-known index entry: missing auth.tokenHeader (or legacy tokenHeader)."
|
|
5719
|
+
);
|
|
5720
|
+
}
|
|
5721
|
+
return { tokenHeader, tokenPrefix: typeof tokenPrefix === "string" ? tokenPrefix : "" };
|
|
5722
|
+
}
|
|
5723
|
+
async function fetchAuthedManifest(entry, licenseKey) {
|
|
5724
|
+
const contentAuth = resolveAuthForEndpoint(entry, "content");
|
|
5725
|
+
const tokenValue = `${contentAuth.tokenPrefix}${licenseKey}`;
|
|
5726
|
+
if (entry.verify) {
|
|
5727
|
+
const verifyAuth = resolveAuthForEndpoint(entry, "verify");
|
|
5728
|
+
const verifyRes = await fetch(entry.verify.endpoint, {
|
|
5729
|
+
method: entry.verify.method,
|
|
5730
|
+
headers: { [verifyAuth.tokenHeader]: tokenValue }
|
|
5731
|
+
});
|
|
5732
|
+
if (!verifyRes.ok) {
|
|
5733
|
+
const text = await verifyRes.text().catch(() => "");
|
|
5734
|
+
let msg = text;
|
|
5735
|
+
try {
|
|
5736
|
+
const parsed = JSON.parse(text);
|
|
5737
|
+
if (typeof parsed?.error === "string" && parsed.error) {
|
|
5738
|
+
msg = parsed.error;
|
|
5739
|
+
}
|
|
5740
|
+
} catch {
|
|
5741
|
+
}
|
|
5742
|
+
throw new Error(msg || `License verification failed (${verifyRes.status}).`);
|
|
5743
|
+
}
|
|
5744
|
+
}
|
|
5745
|
+
const res = await fetch(entry.content.endpoint, {
|
|
5746
|
+
method: entry.content.method,
|
|
5747
|
+
headers: { [contentAuth.tokenHeader]: tokenValue }
|
|
5748
|
+
});
|
|
5749
|
+
if (!res.ok) {
|
|
5750
|
+
const text = await res.text().catch(() => "");
|
|
5751
|
+
throw new Error(text || `Unable to fetch skill content (${res.status}).`);
|
|
5752
|
+
}
|
|
5753
|
+
const json = await res.json();
|
|
5754
|
+
if (json && typeof json === "object" && "success" in json) {
|
|
5755
|
+
const wrapped = json;
|
|
5756
|
+
if (!wrapped.success) {
|
|
5757
|
+
throw new Error(wrapped.error || "Unable to fetch skill content.");
|
|
5758
|
+
}
|
|
5759
|
+
return wrapped.data;
|
|
5760
|
+
}
|
|
5761
|
+
return json;
|
|
5762
|
+
}
|
|
5763
|
+
async function prepareWellKnownSkills(sourceUrl, options) {
|
|
5764
|
+
const result = await wellKnownProvider.fetchIndex(sourceUrl);
|
|
5765
|
+
if (!result) {
|
|
5766
|
+
throw new Error(
|
|
5767
|
+
"No skills found at this URL. Make sure it exposes /.well-known/skills/index.json."
|
|
5768
|
+
);
|
|
5769
|
+
}
|
|
5770
|
+
const { index, resolvedBaseUrl } = result;
|
|
5771
|
+
const entries = index.skills ?? [];
|
|
5772
|
+
if (!Array.isArray(entries) || entries.length === 0) {
|
|
5616
5773
|
throw new Error(
|
|
5617
5774
|
"No skills found at this URL. Make sure it exposes /.well-known/skills/index.json."
|
|
5618
5775
|
);
|
|
@@ -5623,33 +5780,86 @@ async function prepareWellKnownSkills(sourceUrl) {
|
|
|
5623
5780
|
const originMap = /* @__PURE__ */ new Map();
|
|
5624
5781
|
const skills = [];
|
|
5625
5782
|
const sourceIdentifier = wellKnownProvider.getSourceIdentifier(sourceUrl);
|
|
5626
|
-
|
|
5627
|
-
|
|
5783
|
+
let contentHash;
|
|
5784
|
+
const authedEntries = entries.filter(isAuthedEntry);
|
|
5785
|
+
const staticEntries = entries.filter(isStaticEntry);
|
|
5786
|
+
if (authedEntries.length > 0) {
|
|
5787
|
+
const licenseKey = options?.licenseKey?.trim();
|
|
5788
|
+
if (!licenseKey) {
|
|
5789
|
+
throw new WellKnownLicenseKeyRequiredError();
|
|
5790
|
+
}
|
|
5791
|
+
const prefixPerEntry = authedEntries.length > 1;
|
|
5792
|
+
for (const entry of authedEntries) {
|
|
5793
|
+
const manifest = await fetchAuthedManifest(entry, licenseKey);
|
|
5794
|
+
const m = manifest;
|
|
5795
|
+
if (!m || typeof m !== "object" || !m.files || typeof m.files !== "object") {
|
|
5796
|
+
throw new Error("Invalid manifest returned from content endpoint.");
|
|
5797
|
+
}
|
|
5798
|
+
if (typeof m.contentHash === "string" && m.contentHash) {
|
|
5799
|
+
contentHash = m.contentHash;
|
|
5800
|
+
}
|
|
5801
|
+
const base = prefixPerEntry ? join13(tempDir, entry.name) : tempDir;
|
|
5802
|
+
if (prefixPerEntry) {
|
|
5803
|
+
await mkdir5(base, { recursive: true });
|
|
5804
|
+
}
|
|
5805
|
+
for (const [filePath, fileContent] of Object.entries(m.files)) {
|
|
5806
|
+
if (typeof fileContent !== "string") continue;
|
|
5807
|
+
const targetPath = join13(base, filePath);
|
|
5808
|
+
if (!isPathSafe(base, targetPath)) {
|
|
5809
|
+
continue;
|
|
5810
|
+
}
|
|
5811
|
+
await mkdir5(dirname4(targetPath), { recursive: true });
|
|
5812
|
+
await writeFile3(targetPath, fileContent, "utf-8");
|
|
5813
|
+
}
|
|
5814
|
+
const discovered = await discoverSkills(base);
|
|
5815
|
+
for (const skill of discovered) {
|
|
5816
|
+
skills.push(skill);
|
|
5817
|
+
const displayName = getSkillDisplayName(skill);
|
|
5818
|
+
const relativeSkillDir = skill.path.startsWith(`${tempDir}/`) ? skill.path.slice(tempDir.length + 1) : null;
|
|
5819
|
+
const relativeSkillMd = relativeSkillDir ? `${relativeSkillDir}/SKILL.md` : null;
|
|
5820
|
+
originMap.set(displayName, {
|
|
5821
|
+
sourceType: "well-known",
|
|
5822
|
+
sourceUrl,
|
|
5823
|
+
source: sourceIdentifier,
|
|
5824
|
+
skillPath: relativeSkillMd ?? void 0
|
|
5825
|
+
});
|
|
5826
|
+
}
|
|
5827
|
+
}
|
|
5828
|
+
}
|
|
5829
|
+
for (const entry of staticEntries) {
|
|
5830
|
+
const fetched = await wellKnownProvider.fetchSkillByEntry(resolvedBaseUrl, entry);
|
|
5831
|
+
if (!fetched) continue;
|
|
5832
|
+
const skillDir = join13(tempDir, fetched.installName);
|
|
5628
5833
|
await mkdir5(skillDir, { recursive: true });
|
|
5629
|
-
for (const [filePath,
|
|
5834
|
+
for (const [filePath, fileContent] of fetched.files.entries()) {
|
|
5630
5835
|
const targetPath = join13(skillDir, filePath);
|
|
5631
5836
|
if (!isPathSafe(skillDir, targetPath)) {
|
|
5632
5837
|
throw new Error("Invalid file path in well-known skill index.");
|
|
5633
5838
|
}
|
|
5634
5839
|
await mkdir5(dirname4(targetPath), { recursive: true });
|
|
5635
|
-
await writeFile3(targetPath,
|
|
5840
|
+
await writeFile3(targetPath, fileContent, "utf-8");
|
|
5636
5841
|
}
|
|
5637
5842
|
const localSkill = {
|
|
5638
|
-
name:
|
|
5639
|
-
description:
|
|
5843
|
+
name: fetched.installName,
|
|
5844
|
+
description: fetched.description,
|
|
5640
5845
|
path: skillDir,
|
|
5641
|
-
rawContent:
|
|
5642
|
-
metadata:
|
|
5846
|
+
rawContent: fetched.content,
|
|
5847
|
+
metadata: fetched.metadata
|
|
5643
5848
|
};
|
|
5644
5849
|
skills.push(localSkill);
|
|
5645
5850
|
originMap.set(getSkillDisplayName(localSkill), {
|
|
5646
5851
|
sourceType: "well-known",
|
|
5647
|
-
sourceUrl:
|
|
5852
|
+
sourceUrl: fetched.sourceUrl,
|
|
5648
5853
|
source: sourceIdentifier,
|
|
5649
|
-
skillPath:
|
|
5854
|
+
skillPath: fetched.sourceUrl
|
|
5650
5855
|
});
|
|
5651
5856
|
}
|
|
5652
|
-
|
|
5857
|
+
if (skills.length === 0) {
|
|
5858
|
+
throw new Error(
|
|
5859
|
+
"No skills found at this URL. Make sure it exposes /.well-known/skills/index.json."
|
|
5860
|
+
);
|
|
5861
|
+
}
|
|
5862
|
+
return { tempDir, skills, originBySkillName: originMap, contentHash };
|
|
5653
5863
|
}
|
|
5654
5864
|
|
|
5655
5865
|
// src/marketplace.ts
|
|
@@ -5959,7 +6169,7 @@ function autoSelect(skills, options) {
|
|
|
5959
6169
|
}
|
|
5960
6170
|
|
|
5961
6171
|
// src/tui/screens/AddSkillSelect.tsx
|
|
5962
|
-
import { jsx as
|
|
6172
|
+
import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
5963
6173
|
function AddSkillSelectScreen() {
|
|
5964
6174
|
const {
|
|
5965
6175
|
invocation,
|
|
@@ -5973,16 +6183,16 @@ function AddSkillSelectScreen() {
|
|
|
5973
6183
|
resetAddSkill,
|
|
5974
6184
|
setLastSource
|
|
5975
6185
|
} = useNavigation();
|
|
5976
|
-
const [status, setStatus] =
|
|
6186
|
+
const [status, setStatus] = React16.useState(
|
|
5977
6187
|
addSkill.skills && addSkill.skills.length > 0 ? "ready" : "loading"
|
|
5978
6188
|
);
|
|
5979
|
-
const [error, setError] =
|
|
5980
|
-
const [listMode, setListMode] =
|
|
5981
|
-
const [showLoading, setShowLoading] =
|
|
6189
|
+
const [error, setError] = React16.useState(null);
|
|
6190
|
+
const [listMode, setListMode] = React16.useState(false);
|
|
6191
|
+
const [showLoading, setShowLoading] = React16.useState(false);
|
|
5982
6192
|
const spinner = useSpinnerFrame(status === "loading");
|
|
5983
6193
|
const source = addSkill.source ?? invocation.source;
|
|
5984
6194
|
const options = invocation.options;
|
|
5985
|
-
|
|
6195
|
+
React16.useEffect(() => {
|
|
5986
6196
|
let cancelled = false;
|
|
5987
6197
|
const load = async () => {
|
|
5988
6198
|
if (!source) {
|
|
@@ -6046,10 +6256,27 @@ function AddSkillSelectScreen() {
|
|
|
6046
6256
|
return;
|
|
6047
6257
|
}
|
|
6048
6258
|
if (parsed.type === "well-known") {
|
|
6049
|
-
const
|
|
6259
|
+
const licenseKey = addSkill.licenseKey ?? options.licenseKey ?? parsed.licenseKey;
|
|
6260
|
+
let prepared;
|
|
6261
|
+
try {
|
|
6262
|
+
prepared = await prepareWellKnownSkills(parsed.url, { licenseKey });
|
|
6263
|
+
} catch (err) {
|
|
6264
|
+
if (err instanceof WellKnownLicenseKeyRequiredError) {
|
|
6265
|
+
updateAddSkill({ parsed });
|
|
6266
|
+
navigateTo("add-license-key");
|
|
6267
|
+
return;
|
|
6268
|
+
}
|
|
6269
|
+
throw err;
|
|
6270
|
+
}
|
|
6050
6271
|
tempDirForCleanup = prepared.tempDir;
|
|
6272
|
+
const nextParsed = {
|
|
6273
|
+
...parsed,
|
|
6274
|
+
...licenseKey ? { licenseKey } : {},
|
|
6275
|
+
...prepared.contentHash ? { contentHash: prepared.contentHash } : {}
|
|
6276
|
+
};
|
|
6051
6277
|
updateAddSkill({
|
|
6052
|
-
parsed,
|
|
6278
|
+
parsed: nextParsed,
|
|
6279
|
+
...licenseKey ? { licenseKey } : {},
|
|
6053
6280
|
tempDir: prepared.tempDir,
|
|
6054
6281
|
skills: prepared.skills,
|
|
6055
6282
|
originBySkillName: prepared.originBySkillName
|
|
@@ -6162,8 +6389,8 @@ function AddSkillSelectScreen() {
|
|
|
6162
6389
|
return () => {
|
|
6163
6390
|
cancelled = true;
|
|
6164
6391
|
};
|
|
6165
|
-
}, [source, addSkill.skills, updateAddSkill, navigateTo, options, setFlash]);
|
|
6166
|
-
|
|
6392
|
+
}, [source, addSkill.skills, addSkill.licenseKey, updateAddSkill, navigateTo, options, setFlash]);
|
|
6393
|
+
React16.useEffect(() => {
|
|
6167
6394
|
if (invocation.source) {
|
|
6168
6395
|
setBackHandler(() => {
|
|
6169
6396
|
setLastSource(invocation.source ?? null);
|
|
@@ -6179,7 +6406,7 @@ function AddSkillSelectScreen() {
|
|
|
6179
6406
|
setBackHandler(null);
|
|
6180
6407
|
};
|
|
6181
6408
|
}, [invocation.source, resetTo, setBackHandler, resetAddSkill, setInvocation, setLastSource]);
|
|
6182
|
-
|
|
6409
|
+
React16.useEffect(() => {
|
|
6183
6410
|
if (status !== "loading") {
|
|
6184
6411
|
setShowLoading(false);
|
|
6185
6412
|
return;
|
|
@@ -6190,18 +6417,18 @@ function AddSkillSelectScreen() {
|
|
|
6190
6417
|
return () => clearTimeout(timer);
|
|
6191
6418
|
}, [status]);
|
|
6192
6419
|
if (!source) {
|
|
6193
|
-
return /* @__PURE__ */
|
|
6194
|
-
/* @__PURE__ */
|
|
6195
|
-
/* @__PURE__ */
|
|
6420
|
+
return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
|
|
6421
|
+
/* @__PURE__ */ jsx21(AddFlowHeader, { title: "Add skills" }),
|
|
6422
|
+
/* @__PURE__ */ jsx21(Text17, { children: `Missing source. ${BACK_QUIT_HINT}` })
|
|
6196
6423
|
] });
|
|
6197
6424
|
}
|
|
6198
6425
|
if (status === "loading" && !showLoading) {
|
|
6199
|
-
return /* @__PURE__ */
|
|
6426
|
+
return /* @__PURE__ */ jsx21(Box19, { padding: 1 });
|
|
6200
6427
|
}
|
|
6201
6428
|
if (status === "loading") {
|
|
6202
|
-
return /* @__PURE__ */
|
|
6203
|
-
/* @__PURE__ */
|
|
6204
|
-
/* @__PURE__ */
|
|
6429
|
+
return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
|
|
6430
|
+
/* @__PURE__ */ jsx21(AddFlowHeader, { title: "Scanning skills" }),
|
|
6431
|
+
/* @__PURE__ */ jsxs17(Text17, { children: [
|
|
6205
6432
|
spinner,
|
|
6206
6433
|
" Fetching skills from ",
|
|
6207
6434
|
source
|
|
@@ -6209,32 +6436,32 @@ function AddSkillSelectScreen() {
|
|
|
6209
6436
|
] });
|
|
6210
6437
|
}
|
|
6211
6438
|
if (status === "error") {
|
|
6212
|
-
return /* @__PURE__ */
|
|
6213
|
-
/* @__PURE__ */
|
|
6214
|
-
/* @__PURE__ */
|
|
6215
|
-
/* @__PURE__ */
|
|
6439
|
+
return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
|
|
6440
|
+
/* @__PURE__ */ jsx21(AddFlowHeader, { title: "Unable to load skills" }),
|
|
6441
|
+
/* @__PURE__ */ jsx21(Text17, { color: "red", children: error }),
|
|
6442
|
+
/* @__PURE__ */ jsx21(Box19, { marginTop: 1, children: /* @__PURE__ */ jsx21(Text17, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
6216
6443
|
] });
|
|
6217
6444
|
}
|
|
6218
6445
|
const skills = addSkill.skills ?? [];
|
|
6219
6446
|
if (listMode || status === "list") {
|
|
6220
|
-
return /* @__PURE__ */
|
|
6221
|
-
/* @__PURE__ */
|
|
6222
|
-
skills.map((skill) => /* @__PURE__ */
|
|
6223
|
-
/* @__PURE__ */
|
|
6224
|
-
skill.description ? /* @__PURE__ */
|
|
6447
|
+
return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
|
|
6448
|
+
/* @__PURE__ */ jsx21(AddFlowHeader, { title: `Available skills (${skills.length})` }),
|
|
6449
|
+
skills.map((skill) => /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", marginBottom: 1, children: [
|
|
6450
|
+
/* @__PURE__ */ jsx21(Text17, { children: getSkillDisplayName(skill) }),
|
|
6451
|
+
skill.description ? /* @__PURE__ */ jsx21(Text17, { dimColor: true, children: skill.description }) : null
|
|
6225
6452
|
] }, skill.name)),
|
|
6226
|
-
/* @__PURE__ */
|
|
6453
|
+
/* @__PURE__ */ jsx21(Text17, { dimColor: true, children: BACK_QUIT_HINT })
|
|
6227
6454
|
] });
|
|
6228
6455
|
}
|
|
6229
6456
|
if (skills.length === 0) {
|
|
6230
|
-
return /* @__PURE__ */
|
|
6231
|
-
/* @__PURE__ */
|
|
6232
|
-
/* @__PURE__ */
|
|
6457
|
+
return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
|
|
6458
|
+
/* @__PURE__ */ jsx21(AddFlowHeader, { title: "No skills found" }),
|
|
6459
|
+
/* @__PURE__ */ jsx21(Text17, { dimColor: true, children: BACK_QUIT_HINT })
|
|
6233
6460
|
] });
|
|
6234
6461
|
}
|
|
6235
|
-
return /* @__PURE__ */
|
|
6236
|
-
/* @__PURE__ */
|
|
6237
|
-
/* @__PURE__ */
|
|
6462
|
+
return /* @__PURE__ */ jsxs17(Box19, { flexDirection: "column", padding: 1, children: [
|
|
6463
|
+
/* @__PURE__ */ jsx21(AddFlowHeader, { title: "Select skills" }),
|
|
6464
|
+
/* @__PURE__ */ jsx21(
|
|
6238
6465
|
MultiSelect,
|
|
6239
6466
|
{
|
|
6240
6467
|
items: skills.map((skill) => ({
|
|
@@ -6266,22 +6493,22 @@ function AddSkillSelectScreen() {
|
|
|
6266
6493
|
}
|
|
6267
6494
|
|
|
6268
6495
|
// src/tui/screens/AddSource.tsx
|
|
6269
|
-
import { Box as
|
|
6270
|
-
import
|
|
6271
|
-
import
|
|
6272
|
-
import { jsx as
|
|
6496
|
+
import { Box as Box20, Text as Text18 } from "ink";
|
|
6497
|
+
import TextInput3 from "ink-text-input";
|
|
6498
|
+
import React17 from "react";
|
|
6499
|
+
import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
6273
6500
|
function AddSourceScreen() {
|
|
6274
6501
|
const { invocation, addSkill, updateAddSkill, navigateTo, setFlash, lastSource, setLastSource } = useNavigation();
|
|
6275
|
-
const [value, setValue] =
|
|
6502
|
+
const [value, setValue] = React17.useState(
|
|
6276
6503
|
addSkill.source ?? invocation.source ?? lastSource ?? ""
|
|
6277
6504
|
);
|
|
6278
|
-
const didAutofillRef =
|
|
6505
|
+
const didAutofillRef = React17.useRef(false);
|
|
6279
6506
|
const { wrapOnChange } = useTextInput({
|
|
6280
6507
|
onClear: () => {
|
|
6281
6508
|
setValue("");
|
|
6282
6509
|
}
|
|
6283
6510
|
});
|
|
6284
|
-
|
|
6511
|
+
React17.useEffect(() => {
|
|
6285
6512
|
const preset = invocation.source;
|
|
6286
6513
|
if (!preset || didAutofillRef.current) return;
|
|
6287
6514
|
didAutofillRef.current = true;
|
|
@@ -6298,31 +6525,31 @@ function AddSourceScreen() {
|
|
|
6298
6525
|
updateAddSkill({ source: trimmed });
|
|
6299
6526
|
navigateTo("add-skill-select");
|
|
6300
6527
|
};
|
|
6301
|
-
return /* @__PURE__ */
|
|
6302
|
-
/* @__PURE__ */
|
|
6303
|
-
/* @__PURE__ */
|
|
6304
|
-
/* @__PURE__ */
|
|
6305
|
-
/* @__PURE__ */
|
|
6306
|
-
/* @__PURE__ */
|
|
6307
|
-
/* @__PURE__ */
|
|
6528
|
+
return /* @__PURE__ */ jsxs18(Box20, { flexDirection: "column", padding: 1, children: [
|
|
6529
|
+
/* @__PURE__ */ jsx22(Header, { title: "Add skills" }),
|
|
6530
|
+
/* @__PURE__ */ jsx22(Box20, { marginBottom: 1, children: /* @__PURE__ */ jsx22(Text18, { children: "Where should we fetch skills from?" }) }),
|
|
6531
|
+
/* @__PURE__ */ jsx22(Box20, { marginBottom: 1, children: /* @__PURE__ */ jsx22(Text18, { dimColor: true, children: "Examples: owner/repo, https://.../SKILL.md, ./local/path" }) }),
|
|
6532
|
+
/* @__PURE__ */ jsxs18(Box20, { children: [
|
|
6533
|
+
/* @__PURE__ */ jsx22(Text18, { color: "green", children: "> " }),
|
|
6534
|
+
/* @__PURE__ */ jsx22(TextInput3, { value, onChange: wrapOnChange(setValue), onSubmit })
|
|
6308
6535
|
] }),
|
|
6309
|
-
/* @__PURE__ */
|
|
6536
|
+
/* @__PURE__ */ jsx22(Box20, { marginTop: 1, children: /* @__PURE__ */ jsx22(Text18, { dimColor: true, children: TEXT_INPUT_HINT }) })
|
|
6310
6537
|
] });
|
|
6311
6538
|
}
|
|
6312
6539
|
|
|
6313
6540
|
// src/tui/screens/AddTargets.tsx
|
|
6314
|
-
import { Box as
|
|
6315
|
-
import
|
|
6316
|
-
import { Fragment as Fragment2, jsx as
|
|
6541
|
+
import { Box as Box21, Text as Text19 } from "ink";
|
|
6542
|
+
import React18 from "react";
|
|
6543
|
+
import { Fragment as Fragment2, jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
6317
6544
|
function AddTargetsScreen() {
|
|
6318
6545
|
const { invocation, addSkill, updateAddSkill, navigateTo, setFlash, navAction } = useNavigation();
|
|
6319
|
-
const [status, setStatus] =
|
|
6320
|
-
const [mode, setMode] =
|
|
6321
|
-
const [availableAgents, setAvailableAgents] =
|
|
6322
|
-
const [lastSelected, setLastSelected] =
|
|
6323
|
-
const [showLoading, setShowLoading] =
|
|
6546
|
+
const [status, setStatus] = React18.useState("loading");
|
|
6547
|
+
const [mode, setMode] = React18.useState("choice");
|
|
6548
|
+
const [availableAgents, setAvailableAgents] = React18.useState([]);
|
|
6549
|
+
const [lastSelected, setLastSelected] = React18.useState([]);
|
|
6550
|
+
const [showLoading, setShowLoading] = React18.useState(false);
|
|
6324
6551
|
const spinner = useSpinnerFrame(status === "loading");
|
|
6325
|
-
|
|
6552
|
+
React18.useEffect(() => {
|
|
6326
6553
|
let cancelled = false;
|
|
6327
6554
|
const run = async () => {
|
|
6328
6555
|
setStatus("loading");
|
|
@@ -6371,7 +6598,7 @@ function AddTargetsScreen() {
|
|
|
6371
6598
|
cancelled = true;
|
|
6372
6599
|
};
|
|
6373
6600
|
}, [invocation.options, updateAddSkill, navigateTo, addSkill.targetAgents, setFlash, navAction]);
|
|
6374
|
-
|
|
6601
|
+
React18.useEffect(() => {
|
|
6375
6602
|
if (status !== "loading") {
|
|
6376
6603
|
setShowLoading(false);
|
|
6377
6604
|
return;
|
|
@@ -6382,12 +6609,12 @@ function AddTargetsScreen() {
|
|
|
6382
6609
|
return () => clearTimeout(timer);
|
|
6383
6610
|
}, [status]);
|
|
6384
6611
|
if (status === "loading" && !showLoading) {
|
|
6385
|
-
return /* @__PURE__ */
|
|
6612
|
+
return /* @__PURE__ */ jsx23(Box21, { padding: 1 });
|
|
6386
6613
|
}
|
|
6387
6614
|
if (status === "loading") {
|
|
6388
|
-
return /* @__PURE__ */
|
|
6389
|
-
/* @__PURE__ */
|
|
6390
|
-
/* @__PURE__ */
|
|
6615
|
+
return /* @__PURE__ */ jsxs19(Box21, { flexDirection: "column", padding: 1, children: [
|
|
6616
|
+
/* @__PURE__ */ jsx23(AddFlowHeader, { title: "Detecting agents" }),
|
|
6617
|
+
/* @__PURE__ */ jsxs19(Text19, { children: [
|
|
6391
6618
|
spinner,
|
|
6392
6619
|
" Checking installed agents..."
|
|
6393
6620
|
] })
|
|
@@ -6409,9 +6636,9 @@ function AddTargetsScreen() {
|
|
|
6409
6636
|
label: agents[agent].displayName,
|
|
6410
6637
|
hint: agents[agent].skillsDir
|
|
6411
6638
|
}));
|
|
6412
|
-
return /* @__PURE__ */
|
|
6413
|
-
/* @__PURE__ */
|
|
6414
|
-
/* @__PURE__ */
|
|
6639
|
+
return /* @__PURE__ */ jsx23(Box21, { flexDirection: "column", padding: 1, children: mode === "choice" ? /* @__PURE__ */ jsxs19(Fragment2, { children: [
|
|
6640
|
+
/* @__PURE__ */ jsx23(AddFlowHeader, { title: "Install to" }),
|
|
6641
|
+
/* @__PURE__ */ jsx23(
|
|
6415
6642
|
SingleSelect,
|
|
6416
6643
|
{
|
|
6417
6644
|
items: [
|
|
@@ -6444,9 +6671,9 @@ function AddTargetsScreen() {
|
|
|
6444
6671
|
}
|
|
6445
6672
|
}
|
|
6446
6673
|
)
|
|
6447
|
-
] }) : /* @__PURE__ */
|
|
6448
|
-
/* @__PURE__ */
|
|
6449
|
-
/* @__PURE__ */
|
|
6674
|
+
] }) : /* @__PURE__ */ jsxs19(Fragment2, { children: [
|
|
6675
|
+
/* @__PURE__ */ jsx23(AddFlowHeader, { title: "Select agents" }),
|
|
6676
|
+
/* @__PURE__ */ jsx23(
|
|
6450
6677
|
MultiSelect,
|
|
6451
6678
|
{
|
|
6452
6679
|
items: selectableItems,
|
|
@@ -6478,9 +6705,9 @@ function AddTargetsScreen() {
|
|
|
6478
6705
|
}
|
|
6479
6706
|
|
|
6480
6707
|
// src/tui/screens/FindSkillResults.tsx
|
|
6481
|
-
import { Box as
|
|
6482
|
-
import
|
|
6483
|
-
import { jsx as
|
|
6708
|
+
import { Box as Box22, Text as Text20 } from "ink";
|
|
6709
|
+
import React19 from "react";
|
|
6710
|
+
import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
6484
6711
|
var formatStars = (value) => {
|
|
6485
6712
|
if (!value || value <= 0) return "";
|
|
6486
6713
|
if (value >= 1e3) {
|
|
@@ -6509,8 +6736,8 @@ var truncateLabel = (value, max = 100) => {
|
|
|
6509
6736
|
};
|
|
6510
6737
|
function FindSkillResultsScreen() {
|
|
6511
6738
|
const { findSkill, updateFindSkill, resetAddSkill, updateAddSkill, navigateTo, setFlash } = useNavigation();
|
|
6512
|
-
const [status, setStatus] =
|
|
6513
|
-
const [error, setError] =
|
|
6739
|
+
const [status, setStatus] = React19.useState("ready");
|
|
6740
|
+
const [error, setError] = React19.useState(null);
|
|
6514
6741
|
const spinner = useSpinnerFrame(status === "loading");
|
|
6515
6742
|
const results = findSkill.results ?? [];
|
|
6516
6743
|
const query = findSkill.query ?? "";
|
|
@@ -6548,36 +6775,36 @@ function FindSkillResultsScreen() {
|
|
|
6548
6775
|
setStatus("error");
|
|
6549
6776
|
}
|
|
6550
6777
|
};
|
|
6551
|
-
|
|
6778
|
+
React19.useEffect(() => {
|
|
6552
6779
|
if (results.length === 0) {
|
|
6553
6780
|
setStatus("ready");
|
|
6554
6781
|
}
|
|
6555
6782
|
}, [results.length]);
|
|
6556
6783
|
if (status === "loading") {
|
|
6557
|
-
return /* @__PURE__ */
|
|
6558
|
-
/* @__PURE__ */
|
|
6559
|
-
/* @__PURE__ */
|
|
6784
|
+
return /* @__PURE__ */ jsxs20(Box22, { flexDirection: "column", padding: 1, children: [
|
|
6785
|
+
/* @__PURE__ */ jsx24(Header, { title: "Preparing skills" }),
|
|
6786
|
+
/* @__PURE__ */ jsxs20(Text20, { children: [
|
|
6560
6787
|
spinner,
|
|
6561
6788
|
" Cloning repositories..."
|
|
6562
6789
|
] })
|
|
6563
6790
|
] });
|
|
6564
6791
|
}
|
|
6565
6792
|
if (results.length === 0) {
|
|
6566
|
-
return /* @__PURE__ */
|
|
6567
|
-
/* @__PURE__ */
|
|
6568
|
-
/* @__PURE__ */
|
|
6569
|
-
/* @__PURE__ */
|
|
6793
|
+
return /* @__PURE__ */ jsxs20(Box22, { flexDirection: "column", padding: 1, children: [
|
|
6794
|
+
/* @__PURE__ */ jsx24(Header, { title: "No results" }),
|
|
6795
|
+
/* @__PURE__ */ jsx24(Text20, { dimColor: true, children: "No skills found." }),
|
|
6796
|
+
/* @__PURE__ */ jsx24(Box22, { marginTop: 1, children: /* @__PURE__ */ jsx24(Text20, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
6570
6797
|
] });
|
|
6571
6798
|
}
|
|
6572
|
-
return /* @__PURE__ */
|
|
6573
|
-
/* @__PURE__ */
|
|
6574
|
-
/* @__PURE__ */
|
|
6575
|
-
/* @__PURE__ */
|
|
6576
|
-
/* @__PURE__ */
|
|
6577
|
-
/* @__PURE__ */
|
|
6799
|
+
return /* @__PURE__ */ jsxs20(Box22, { flexDirection: "column", padding: 1, children: [
|
|
6800
|
+
/* @__PURE__ */ jsx24(Header, { title: "Select skills" }),
|
|
6801
|
+
/* @__PURE__ */ jsxs20(Box22, { marginBottom: 1, flexDirection: "column", children: [
|
|
6802
|
+
/* @__PURE__ */ jsx24(Text20, { children: `Query: ${query}` }),
|
|
6803
|
+
/* @__PURE__ */ jsx24(Text20, { dimColor: true, children: `Mode: ${modeLabel} search` }),
|
|
6804
|
+
/* @__PURE__ */ jsx24(Text20, { dimColor: true, children: FIND_SKILLS_HINT })
|
|
6578
6805
|
] }),
|
|
6579
|
-
status === "error" ? /* @__PURE__ */
|
|
6580
|
-
/* @__PURE__ */
|
|
6806
|
+
status === "error" ? /* @__PURE__ */ jsx24(Box22, { marginBottom: 1, children: /* @__PURE__ */ jsx24(Text20, { color: "red", children: error }) }) : null,
|
|
6807
|
+
/* @__PURE__ */ jsx24(
|
|
6581
6808
|
MultiSelect,
|
|
6582
6809
|
{
|
|
6583
6810
|
items: results.map((result) => ({
|
|
@@ -6595,21 +6822,21 @@ function FindSkillResultsScreen() {
|
|
|
6595
6822
|
}
|
|
6596
6823
|
|
|
6597
6824
|
// src/tui/screens/FindSkillSearch.tsx
|
|
6598
|
-
import { Box as
|
|
6599
|
-
import
|
|
6600
|
-
import
|
|
6601
|
-
import { jsx as
|
|
6825
|
+
import { Box as Box23, Text as Text21, useInput as useInput5 } from "ink";
|
|
6826
|
+
import TextInput4 from "ink-text-input";
|
|
6827
|
+
import React20 from "react";
|
|
6828
|
+
import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
6602
6829
|
var MIN_QUERY_LENGTH = 2;
|
|
6603
6830
|
function getDebounceMs(queryLength) {
|
|
6604
6831
|
return Math.max(150, 350 - queryLength * 50);
|
|
6605
6832
|
}
|
|
6606
6833
|
function FindSkillSearchScreen() {
|
|
6607
6834
|
const { findSkill, updateFindSkill, navigateTo, setFlash } = useNavigation();
|
|
6608
|
-
const [value, setValue] =
|
|
6609
|
-
const [status, setStatus] =
|
|
6610
|
-
const [error, setError] =
|
|
6611
|
-
const [preview, setPreview] =
|
|
6612
|
-
const debounceRef =
|
|
6835
|
+
const [value, setValue] = React20.useState(findSkill.query ?? "");
|
|
6836
|
+
const [status, setStatus] = React20.useState("idle");
|
|
6837
|
+
const [error, setError] = React20.useState(null);
|
|
6838
|
+
const [preview, setPreview] = React20.useState([]);
|
|
6839
|
+
const debounceRef = React20.useRef(null);
|
|
6613
6840
|
const spinner = useSpinnerFrame(status === "searching" || status === "loading");
|
|
6614
6841
|
const { wrapOnChange } = useTextInput({
|
|
6615
6842
|
disabled: status === "loading",
|
|
@@ -6620,7 +6847,7 @@ function FindSkillSearchScreen() {
|
|
|
6620
6847
|
updateFindSkill({ query: "" });
|
|
6621
6848
|
}
|
|
6622
6849
|
});
|
|
6623
|
-
const triggerLiveSearch =
|
|
6850
|
+
const triggerLiveSearch = React20.useCallback((query) => {
|
|
6624
6851
|
if (debounceRef.current) {
|
|
6625
6852
|
clearTimeout(debounceRef.current);
|
|
6626
6853
|
debounceRef.current = null;
|
|
@@ -6644,14 +6871,14 @@ function FindSkillSearchScreen() {
|
|
|
6644
6871
|
}
|
|
6645
6872
|
}, debounceMs);
|
|
6646
6873
|
}, []);
|
|
6647
|
-
|
|
6874
|
+
React20.useEffect(() => {
|
|
6648
6875
|
return () => {
|
|
6649
6876
|
if (debounceRef.current) {
|
|
6650
6877
|
clearTimeout(debounceRef.current);
|
|
6651
6878
|
}
|
|
6652
6879
|
};
|
|
6653
6880
|
}, []);
|
|
6654
|
-
const goToLexicalResults =
|
|
6881
|
+
const goToLexicalResults = React20.useCallback(async () => {
|
|
6655
6882
|
const query = value.trim();
|
|
6656
6883
|
if (!query || query.length < MIN_QUERY_LENGTH) {
|
|
6657
6884
|
setFlash(`Enter at least ${MIN_QUERY_LENGTH} characters.`);
|
|
@@ -6678,7 +6905,7 @@ function FindSkillSearchScreen() {
|
|
|
6678
6905
|
setStatus("error");
|
|
6679
6906
|
}
|
|
6680
6907
|
}, [value, setFlash, updateFindSkill, navigateTo]);
|
|
6681
|
-
const runSemanticSearch =
|
|
6908
|
+
const runSemanticSearch = React20.useCallback(async () => {
|
|
6682
6909
|
const query = value.trim();
|
|
6683
6910
|
if (!query) {
|
|
6684
6911
|
setFlash("Enter a search term.");
|
|
@@ -6723,13 +6950,13 @@ function FindSkillSearchScreen() {
|
|
|
6723
6950
|
});
|
|
6724
6951
|
const showPreview = preview.length > 0 && status !== "loading";
|
|
6725
6952
|
const showSearching = status === "searching" && value.trim().length >= MIN_QUERY_LENGTH;
|
|
6726
|
-
return /* @__PURE__ */
|
|
6727
|
-
/* @__PURE__ */
|
|
6728
|
-
/* @__PURE__ */
|
|
6729
|
-
/* @__PURE__ */
|
|
6730
|
-
/* @__PURE__ */
|
|
6731
|
-
/* @__PURE__ */
|
|
6732
|
-
|
|
6953
|
+
return /* @__PURE__ */ jsxs21(Box23, { flexDirection: "column", padding: 1, children: [
|
|
6954
|
+
/* @__PURE__ */ jsx25(Header, { title: "Find skills" }),
|
|
6955
|
+
/* @__PURE__ */ jsx25(Box23, { marginBottom: 1, children: /* @__PURE__ */ jsx25(Text21, { children: "Find a skill to give your agent new capabilities." }) }),
|
|
6956
|
+
/* @__PURE__ */ jsxs21(Box23, { children: [
|
|
6957
|
+
/* @__PURE__ */ jsx25(Text21, { color: "green", children: "> " }),
|
|
6958
|
+
/* @__PURE__ */ jsx25(
|
|
6959
|
+
TextInput4,
|
|
6733
6960
|
{
|
|
6734
6961
|
value,
|
|
6735
6962
|
onChange: wrapOnChange((next) => {
|
|
@@ -6746,52 +6973,52 @@ function FindSkillSearchScreen() {
|
|
|
6746
6973
|
}
|
|
6747
6974
|
)
|
|
6748
6975
|
] }),
|
|
6749
|
-
showSearching && !showPreview ? /* @__PURE__ */
|
|
6976
|
+
showSearching && !showPreview ? /* @__PURE__ */ jsx25(Box23, { marginTop: 1, children: /* @__PURE__ */ jsxs21(Text21, { dimColor: true, children: [
|
|
6750
6977
|
spinner,
|
|
6751
6978
|
" Searching..."
|
|
6752
6979
|
] }) }) : null,
|
|
6753
|
-
showPreview ? /* @__PURE__ */
|
|
6754
|
-
/* @__PURE__ */
|
|
6980
|
+
showPreview ? /* @__PURE__ */ jsxs21(Box23, { flexDirection: "column", marginTop: 1, children: [
|
|
6981
|
+
/* @__PURE__ */ jsxs21(Text21, { dimColor: true, children: [
|
|
6755
6982
|
preview.length,
|
|
6756
6983
|
" result",
|
|
6757
6984
|
preview.length !== 1 ? "s" : "",
|
|
6758
6985
|
" found:"
|
|
6759
6986
|
] }),
|
|
6760
|
-
preview.slice(0, 3).map((result) => /* @__PURE__ */
|
|
6987
|
+
preview.slice(0, 3).map((result) => /* @__PURE__ */ jsxs21(Text21, { dimColor: true, children: [
|
|
6761
6988
|
" ",
|
|
6762
6989
|
"\u2022 ",
|
|
6763
6990
|
result.name,
|
|
6764
6991
|
result.repoOwner ? ` (${result.repoOwner}/${result.repoName})` : ""
|
|
6765
6992
|
] }, result.id)),
|
|
6766
|
-
preview.length > 3 ? /* @__PURE__ */
|
|
6993
|
+
preview.length > 3 ? /* @__PURE__ */ jsxs21(Text21, { dimColor: true, children: [
|
|
6767
6994
|
" ",
|
|
6768
6995
|
"... and ",
|
|
6769
6996
|
preview.length - 3,
|
|
6770
6997
|
" more"
|
|
6771
6998
|
] }) : null
|
|
6772
6999
|
] }) : null,
|
|
6773
|
-
status === "loading" ? /* @__PURE__ */
|
|
7000
|
+
status === "loading" ? /* @__PURE__ */ jsx25(Box23, { marginTop: 1, children: /* @__PURE__ */ jsxs21(Text21, { children: [
|
|
6774
7001
|
spinner,
|
|
6775
7002
|
" Running AI search..."
|
|
6776
7003
|
] }) }) : null,
|
|
6777
|
-
status === "error" ? /* @__PURE__ */
|
|
6778
|
-
/* @__PURE__ */
|
|
6779
|
-
/* @__PURE__ */
|
|
7004
|
+
status === "error" ? /* @__PURE__ */ jsx25(Box23, { marginTop: 1, children: /* @__PURE__ */ jsx25(Text21, { color: "red", children: error }) }) : null,
|
|
7005
|
+
/* @__PURE__ */ jsx25(Box23, { marginTop: 1, children: /* @__PURE__ */ jsx25(Text21, { dimColor: true, children: "Enter for fast results, Tab for AI search" }) }),
|
|
7006
|
+
/* @__PURE__ */ jsx25(Box23, { children: /* @__PURE__ */ jsx25(Text21, { dimColor: true, children: TEXT_INPUT_HINT }) })
|
|
6780
7007
|
] });
|
|
6781
7008
|
}
|
|
6782
7009
|
|
|
6783
7010
|
// src/tui/screens/GetUrl.tsx
|
|
6784
|
-
import { Box as
|
|
6785
|
-
import
|
|
6786
|
-
import { jsx as
|
|
7011
|
+
import { Box as Box24, Text as Text22, useApp } from "ink";
|
|
7012
|
+
import React21 from "react";
|
|
7013
|
+
import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
6787
7014
|
function GetUrlScreen() {
|
|
6788
7015
|
const { exit } = useApp();
|
|
6789
7016
|
const { invocation } = useNavigation();
|
|
6790
7017
|
const spinner = useSpinnerFrame(true);
|
|
6791
|
-
const didRun =
|
|
7018
|
+
const didRun = React21.useRef(false);
|
|
6792
7019
|
const outputPath = invocation.options?.output ?? null;
|
|
6793
7020
|
const outputFormat = invocation.options?.json ? "json" : "markdown";
|
|
6794
|
-
|
|
7021
|
+
React21.useEffect(() => {
|
|
6795
7022
|
let cancelled = false;
|
|
6796
7023
|
const run = async () => {
|
|
6797
7024
|
if (didRun.current) return;
|
|
@@ -6820,12 +7047,12 @@ function GetUrlScreen() {
|
|
|
6820
7047
|
cancelled = true;
|
|
6821
7048
|
};
|
|
6822
7049
|
}, [exit, invocation]);
|
|
6823
|
-
return /* @__PURE__ */
|
|
6824
|
-
/* @__PURE__ */
|
|
6825
|
-
invocation.source ? /* @__PURE__ */
|
|
6826
|
-
outputPath ? /* @__PURE__ */
|
|
6827
|
-
outputFormat === "json" ? /* @__PURE__ */
|
|
6828
|
-
/* @__PURE__ */
|
|
7050
|
+
return /* @__PURE__ */ jsxs22(Box24, { flexDirection: "column", padding: 1, children: [
|
|
7051
|
+
/* @__PURE__ */ jsx26(Header, { title: "Fetching URL" }),
|
|
7052
|
+
invocation.source ? /* @__PURE__ */ jsx26(Text22, { dimColor: true, children: `URL: ${invocation.source}` }) : null,
|
|
7053
|
+
outputPath ? /* @__PURE__ */ jsx26(Text22, { dimColor: true, children: `Output: ${outputPath}` }) : null,
|
|
7054
|
+
outputFormat === "json" ? /* @__PURE__ */ jsx26(Text22, { dimColor: true, children: "Format: json" }) : null,
|
|
7055
|
+
/* @__PURE__ */ jsxs22(Text22, { children: [
|
|
6829
7056
|
spinner,
|
|
6830
7057
|
" Fetching markdown..."
|
|
6831
7058
|
] })
|
|
@@ -6833,8 +7060,8 @@ function GetUrlScreen() {
|
|
|
6833
7060
|
}
|
|
6834
7061
|
|
|
6835
7062
|
// src/tui/screens/ListSkills.tsx
|
|
6836
|
-
import { Box as
|
|
6837
|
-
import
|
|
7063
|
+
import { Box as Box25, Text as Text23 } from "ink";
|
|
7064
|
+
import React22 from "react";
|
|
6838
7065
|
|
|
6839
7066
|
// src/installed-skills.ts
|
|
6840
7067
|
import { lstat as lstat2, readFile as readFile5, readdir as readdir4, stat as stat4 } from "fs/promises";
|
|
@@ -6949,12 +7176,12 @@ async function findSkillInstallations(skillName, scope, cwd = process.cwd()) {
|
|
|
6949
7176
|
}
|
|
6950
7177
|
|
|
6951
7178
|
// src/tui/screens/ListSkills.tsx
|
|
6952
|
-
import { jsx as
|
|
7179
|
+
import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
6953
7180
|
function ListScreen() {
|
|
6954
7181
|
const { navigateTo, setBackHandler } = useNavigation();
|
|
6955
|
-
const [summaries, setSummaries] =
|
|
6956
|
-
const [selectedAgent, setSelectedAgent] =
|
|
6957
|
-
|
|
7182
|
+
const [summaries, setSummaries] = React22.useState([]);
|
|
7183
|
+
const [selectedAgent, setSelectedAgent] = React22.useState(null);
|
|
7184
|
+
React22.useEffect(() => {
|
|
6958
7185
|
let cancelled = false;
|
|
6959
7186
|
const load = async () => {
|
|
6960
7187
|
const installed = await detectInstalledAgents();
|
|
@@ -6977,7 +7204,7 @@ function ListScreen() {
|
|
|
6977
7204
|
cancelled = true;
|
|
6978
7205
|
};
|
|
6979
7206
|
}, []);
|
|
6980
|
-
|
|
7207
|
+
React22.useEffect(() => {
|
|
6981
7208
|
if (!selectedAgent) {
|
|
6982
7209
|
setBackHandler(null);
|
|
6983
7210
|
return;
|
|
@@ -6992,17 +7219,17 @@ function ListScreen() {
|
|
|
6992
7219
|
}, [selectedAgent, setBackHandler]);
|
|
6993
7220
|
if (selectedAgent) {
|
|
6994
7221
|
const total = selectedAgent.projectSkills.length + selectedAgent.globalSkills.length;
|
|
6995
|
-
return /* @__PURE__ */
|
|
6996
|
-
/* @__PURE__ */
|
|
6997
|
-
selectedAgent.projectSkills.length > 0 ? /* @__PURE__ */
|
|
6998
|
-
/* @__PURE__ */
|
|
6999
|
-
selectedAgent.projectSkills.map((name) => /* @__PURE__ */
|
|
7222
|
+
return /* @__PURE__ */ jsxs23(Box25, { flexDirection: "column", padding: 1, children: [
|
|
7223
|
+
/* @__PURE__ */ jsx27(Header, { title: `${agents[selectedAgent.agent].displayName} (${total})` }),
|
|
7224
|
+
selectedAgent.projectSkills.length > 0 ? /* @__PURE__ */ jsxs23(Box25, { flexDirection: "column", marginBottom: 1, children: [
|
|
7225
|
+
/* @__PURE__ */ jsx27(Text23, { children: "Project" }),
|
|
7226
|
+
selectedAgent.projectSkills.map((name) => /* @__PURE__ */ jsx27(Text23, { dimColor: true, children: name }, `p-${name}`))
|
|
7000
7227
|
] }) : null,
|
|
7001
|
-
selectedAgent.globalSkills.length > 0 ? /* @__PURE__ */
|
|
7002
|
-
/* @__PURE__ */
|
|
7003
|
-
selectedAgent.globalSkills.map((name) => /* @__PURE__ */
|
|
7228
|
+
selectedAgent.globalSkills.length > 0 ? /* @__PURE__ */ jsxs23(Box25, { flexDirection: "column", marginBottom: 1, children: [
|
|
7229
|
+
/* @__PURE__ */ jsx27(Text23, { children: "Global" }),
|
|
7230
|
+
selectedAgent.globalSkills.map((name) => /* @__PURE__ */ jsx27(Text23, { dimColor: true, children: name }, `g-${name}`))
|
|
7004
7231
|
] }) : null,
|
|
7005
|
-
/* @__PURE__ */
|
|
7232
|
+
/* @__PURE__ */ jsx27(
|
|
7006
7233
|
SelectMenu,
|
|
7007
7234
|
{
|
|
7008
7235
|
items: [
|
|
@@ -7029,9 +7256,9 @@ function ListScreen() {
|
|
|
7029
7256
|
hint: `${count} skill${count !== 1 ? "s" : ""}`
|
|
7030
7257
|
};
|
|
7031
7258
|
});
|
|
7032
|
-
return /* @__PURE__ */
|
|
7033
|
-
/* @__PURE__ */
|
|
7034
|
-
/* @__PURE__ */
|
|
7259
|
+
return /* @__PURE__ */ jsxs23(Box25, { flexDirection: "column", padding: 1, children: [
|
|
7260
|
+
/* @__PURE__ */ jsx27(Header, { title: "Installed skills" }),
|
|
7261
|
+
/* @__PURE__ */ jsx27(
|
|
7035
7262
|
SelectMenu,
|
|
7036
7263
|
{
|
|
7037
7264
|
items,
|
|
@@ -7048,8 +7275,8 @@ function ListScreen() {
|
|
|
7048
7275
|
}
|
|
7049
7276
|
|
|
7050
7277
|
// src/tui/screens/MainMenu.tsx
|
|
7051
|
-
import { Box as
|
|
7052
|
-
import { jsx as
|
|
7278
|
+
import { Box as Box26 } from "ink";
|
|
7279
|
+
import { jsx as jsx28 } from "react/jsx-runtime";
|
|
7053
7280
|
function MainMenu() {
|
|
7054
7281
|
const { navigateTo, resetAddSkill, resetFindSkill, setInvocation } = useNavigation();
|
|
7055
7282
|
const items = [
|
|
@@ -7063,7 +7290,7 @@ function MainMenu() {
|
|
|
7063
7290
|
{ label: "Update docs", value: "update-docs" },
|
|
7064
7291
|
{ label: "Exit", value: "exit" }
|
|
7065
7292
|
];
|
|
7066
|
-
return /* @__PURE__ */
|
|
7293
|
+
return /* @__PURE__ */ jsx28(Box26, { flexDirection: "column", padding: 1, children: /* @__PURE__ */ jsx28(
|
|
7067
7294
|
SelectMenu,
|
|
7068
7295
|
{
|
|
7069
7296
|
items,
|
|
@@ -7118,16 +7345,16 @@ function MainMenu() {
|
|
|
7118
7345
|
// src/tui/screens/ManageSkills.tsx
|
|
7119
7346
|
import { rm as rm5 } from "fs/promises";
|
|
7120
7347
|
import chalk4 from "chalk";
|
|
7121
|
-
import { Box as
|
|
7122
|
-
import
|
|
7123
|
-
import { jsx as
|
|
7348
|
+
import { Box as Box27, Text as Text24 } from "ink";
|
|
7349
|
+
import React23 from "react";
|
|
7350
|
+
import { jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
7124
7351
|
function ManageScreen() {
|
|
7125
7352
|
const { navigateTo, setFlash, setBackHandler } = useNavigation();
|
|
7126
|
-
const [summaries, setSummaries] =
|
|
7127
|
-
const [selectedAgent, setSelectedAgent] =
|
|
7128
|
-
const [selectedSkills, setSelectedSkills] =
|
|
7129
|
-
const [isRemoving, setIsRemoving] =
|
|
7130
|
-
|
|
7353
|
+
const [summaries, setSummaries] = React23.useState([]);
|
|
7354
|
+
const [selectedAgent, setSelectedAgent] = React23.useState(null);
|
|
7355
|
+
const [selectedSkills, setSelectedSkills] = React23.useState(null);
|
|
7356
|
+
const [isRemoving, setIsRemoving] = React23.useState(false);
|
|
7357
|
+
React23.useEffect(() => {
|
|
7131
7358
|
let cancelled = false;
|
|
7132
7359
|
const load = async () => {
|
|
7133
7360
|
const installedAgents = await detectInstalledAgents();
|
|
@@ -7149,7 +7376,7 @@ function ManageScreen() {
|
|
|
7149
7376
|
cancelled = true;
|
|
7150
7377
|
};
|
|
7151
7378
|
}, [setFlash]);
|
|
7152
|
-
|
|
7379
|
+
React23.useEffect(() => {
|
|
7153
7380
|
if (isRemoving) {
|
|
7154
7381
|
setBackHandler(() => true);
|
|
7155
7382
|
return () => setBackHandler(null);
|
|
@@ -7172,16 +7399,16 @@ function ManageScreen() {
|
|
|
7172
7399
|
return () => setBackHandler(null);
|
|
7173
7400
|
}, [isRemoving, selectedSkills, selectedAgent, setBackHandler]);
|
|
7174
7401
|
if (summaries.length === 0) {
|
|
7175
|
-
return /* @__PURE__ */
|
|
7176
|
-
/* @__PURE__ */
|
|
7177
|
-
/* @__PURE__ */
|
|
7178
|
-
/* @__PURE__ */
|
|
7402
|
+
return /* @__PURE__ */ jsxs24(Box27, { flexDirection: "column", padding: 1, children: [
|
|
7403
|
+
/* @__PURE__ */ jsx29(Header, { title: "Remove skills" }),
|
|
7404
|
+
/* @__PURE__ */ jsx29(Text24, { dimColor: true, children: "No skills found yet." }),
|
|
7405
|
+
/* @__PURE__ */ jsx29(Text24, { dimColor: true, children: BACK_QUIT_HINT })
|
|
7179
7406
|
] });
|
|
7180
7407
|
}
|
|
7181
7408
|
if (!selectedAgent) {
|
|
7182
|
-
return /* @__PURE__ */
|
|
7183
|
-
/* @__PURE__ */
|
|
7184
|
-
/* @__PURE__ */
|
|
7409
|
+
return /* @__PURE__ */ jsxs24(Box27, { flexDirection: "column", padding: 1, children: [
|
|
7410
|
+
/* @__PURE__ */ jsx29(Header, { title: "Select agent" }),
|
|
7411
|
+
/* @__PURE__ */ jsx29(
|
|
7185
7412
|
SelectMenu,
|
|
7186
7413
|
{
|
|
7187
7414
|
items: summaries.map((summary) => ({
|
|
@@ -7198,9 +7425,9 @@ function ManageScreen() {
|
|
|
7198
7425
|
] });
|
|
7199
7426
|
}
|
|
7200
7427
|
if (!selectedSkills) {
|
|
7201
|
-
return /* @__PURE__ */
|
|
7202
|
-
/* @__PURE__ */
|
|
7203
|
-
/* @__PURE__ */
|
|
7428
|
+
return /* @__PURE__ */ jsxs24(Box27, { flexDirection: "column", padding: 1, children: [
|
|
7429
|
+
/* @__PURE__ */ jsx29(Header, { title: `Remove skills (${agents[selectedAgent.agent].displayName})` }),
|
|
7430
|
+
/* @__PURE__ */ jsx29(
|
|
7204
7431
|
MultiSelect,
|
|
7205
7432
|
{
|
|
7206
7433
|
items: selectedAgent.skills.map((skill) => ({
|
|
@@ -7220,19 +7447,19 @@ function ManageScreen() {
|
|
|
7220
7447
|
] });
|
|
7221
7448
|
}
|
|
7222
7449
|
if (isRemoving) {
|
|
7223
|
-
return /* @__PURE__ */
|
|
7224
|
-
/* @__PURE__ */
|
|
7225
|
-
/* @__PURE__ */
|
|
7450
|
+
return /* @__PURE__ */ jsxs24(Box27, { flexDirection: "column", padding: 1, children: [
|
|
7451
|
+
/* @__PURE__ */ jsx29(Header, { title: "Removing skills" }),
|
|
7452
|
+
/* @__PURE__ */ jsx29(Text24, { children: "Removing selected skills..." })
|
|
7226
7453
|
] });
|
|
7227
7454
|
}
|
|
7228
|
-
return /* @__PURE__ */
|
|
7229
|
-
/* @__PURE__ */
|
|
7230
|
-
selectedSkills.map((skill) => /* @__PURE__ */
|
|
7455
|
+
return /* @__PURE__ */ jsxs24(Box27, { flexDirection: "column", padding: 1, children: [
|
|
7456
|
+
/* @__PURE__ */ jsx29(Header, { title: "Confirm removal" }),
|
|
7457
|
+
selectedSkills.map((skill) => /* @__PURE__ */ jsxs24(Text24, { children: [
|
|
7231
7458
|
formatSkillLabel(skill),
|
|
7232
7459
|
" ",
|
|
7233
7460
|
chalk4.dim(`(${skill.scope})`)
|
|
7234
7461
|
] }, `${skill.slug}-${skill.scope}`)),
|
|
7235
|
-
/* @__PURE__ */
|
|
7462
|
+
/* @__PURE__ */ jsx29(
|
|
7236
7463
|
SelectMenu,
|
|
7237
7464
|
{
|
|
7238
7465
|
items: [
|
|
@@ -7295,14 +7522,14 @@ function formatSkillLabel(skill) {
|
|
|
7295
7522
|
}
|
|
7296
7523
|
|
|
7297
7524
|
// src/tui/screens/MarketplacePlugins.tsx
|
|
7298
|
-
import { Box as
|
|
7299
|
-
import
|
|
7300
|
-
import { jsx as
|
|
7525
|
+
import { Box as Box28, Text as Text25 } from "ink";
|
|
7526
|
+
import React24 from "react";
|
|
7527
|
+
import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
7301
7528
|
function MarketplacePluginScreen() {
|
|
7302
7529
|
const { invocation, addSkill, updateAddSkill, navigateTo, setFlash } = useNavigation();
|
|
7303
7530
|
const plugins = addSkill.marketplace?.plugins ?? [];
|
|
7304
7531
|
const options = invocation.options;
|
|
7305
|
-
|
|
7532
|
+
React24.useEffect(() => {
|
|
7306
7533
|
if (plugins.length === 0) {
|
|
7307
7534
|
return;
|
|
7308
7535
|
}
|
|
@@ -7317,25 +7544,25 @@ function MarketplacePluginScreen() {
|
|
|
7317
7544
|
}
|
|
7318
7545
|
}, [plugins, options.yes, updateAddSkill, navigateTo, addSkill.marketplace]);
|
|
7319
7546
|
if (plugins.length === 0) {
|
|
7320
|
-
return /* @__PURE__ */
|
|
7321
|
-
/* @__PURE__ */
|
|
7322
|
-
/* @__PURE__ */
|
|
7323
|
-
/* @__PURE__ */
|
|
7547
|
+
return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
|
|
7548
|
+
/* @__PURE__ */ jsx30(AddFlowHeader, { title: "Marketplace plugins" }),
|
|
7549
|
+
/* @__PURE__ */ jsx30(Text25, { dimColor: true, children: "No plugins found." }),
|
|
7550
|
+
/* @__PURE__ */ jsx30(Text25, { dimColor: true, children: BACK_QUIT_HINT })
|
|
7324
7551
|
] });
|
|
7325
7552
|
}
|
|
7326
7553
|
if (options.list) {
|
|
7327
|
-
return /* @__PURE__ */
|
|
7328
|
-
/* @__PURE__ */
|
|
7329
|
-
plugins.map((plugin) => /* @__PURE__ */
|
|
7330
|
-
/* @__PURE__ */
|
|
7331
|
-
plugin.description ? /* @__PURE__ */
|
|
7554
|
+
return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
|
|
7555
|
+
/* @__PURE__ */ jsx30(AddFlowHeader, { title: `Marketplace plugins (${plugins.length})` }),
|
|
7556
|
+
plugins.map((plugin) => /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", marginBottom: 1, children: [
|
|
7557
|
+
/* @__PURE__ */ jsx30(Text25, { children: plugin.name }),
|
|
7558
|
+
plugin.description ? /* @__PURE__ */ jsx30(Text25, { dimColor: true, children: plugin.description }) : null
|
|
7332
7559
|
] }, plugin.name)),
|
|
7333
|
-
/* @__PURE__ */
|
|
7560
|
+
/* @__PURE__ */ jsx30(Text25, { dimColor: true, children: BACK_QUIT_HINT })
|
|
7334
7561
|
] });
|
|
7335
7562
|
}
|
|
7336
|
-
return /* @__PURE__ */
|
|
7337
|
-
/* @__PURE__ */
|
|
7338
|
-
/* @__PURE__ */
|
|
7563
|
+
return /* @__PURE__ */ jsxs25(Box28, { flexDirection: "column", padding: 1, children: [
|
|
7564
|
+
/* @__PURE__ */ jsx30(AddFlowHeader, { title: "Select plugins" }),
|
|
7565
|
+
/* @__PURE__ */ jsx30(
|
|
7339
7566
|
MultiSelect,
|
|
7340
7567
|
{
|
|
7341
7568
|
items: plugins.map((plugin) => ({
|
|
@@ -7362,16 +7589,16 @@ function MarketplacePluginScreen() {
|
|
|
7362
7589
|
}
|
|
7363
7590
|
|
|
7364
7591
|
// src/tui/screens/MarketplaceSkills.tsx
|
|
7365
|
-
import { Box as
|
|
7366
|
-
import
|
|
7592
|
+
import { Box as Box29, Text as Text26 } from "ink";
|
|
7593
|
+
import React25 from "react";
|
|
7367
7594
|
|
|
7368
7595
|
// src/flows/marketplace.ts
|
|
7369
|
-
import { dirname as
|
|
7596
|
+
import { dirname as dirname7, join as join17, relative as relative4 } from "path";
|
|
7370
7597
|
function normalizeCandidatePath(basePath, candidate) {
|
|
7371
7598
|
if (!candidate) return basePath;
|
|
7372
7599
|
const cleaned = candidate.replace(/\\/g, "/");
|
|
7373
7600
|
if (cleaned.endsWith(".md")) {
|
|
7374
|
-
return join17(basePath,
|
|
7601
|
+
return join17(basePath, dirname7(cleaned));
|
|
7375
7602
|
}
|
|
7376
7603
|
return join17(basePath, cleaned);
|
|
7377
7604
|
}
|
|
@@ -7523,16 +7750,16 @@ function buildOriginMap(skills) {
|
|
|
7523
7750
|
}
|
|
7524
7751
|
|
|
7525
7752
|
// src/tui/screens/MarketplaceSkills.tsx
|
|
7526
|
-
import { jsx as
|
|
7753
|
+
import { jsx as jsx31, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
7527
7754
|
function MarketplaceSkillScreen() {
|
|
7528
7755
|
const { invocation, addSkill, updateAddSkill, navigateTo, setFlash } = useNavigation();
|
|
7529
7756
|
const options = invocation.options;
|
|
7530
|
-
const [status, setStatus] =
|
|
7531
|
-
const [error, setError] =
|
|
7757
|
+
const [status, setStatus] = React25.useState("loading");
|
|
7758
|
+
const [error, setError] = React25.useState(null);
|
|
7532
7759
|
const spinner = useSpinnerFrame(status === "loading");
|
|
7533
7760
|
const selectedPlugins = addSkill.marketplace?.selectedPlugins ?? [];
|
|
7534
7761
|
const context = addSkill.marketplace?.context;
|
|
7535
|
-
|
|
7762
|
+
React25.useEffect(() => {
|
|
7536
7763
|
let cancelled = false;
|
|
7537
7764
|
const load = async () => {
|
|
7538
7765
|
if (!context || selectedPlugins.length === 0) {
|
|
@@ -7596,27 +7823,27 @@ function MarketplaceSkillScreen() {
|
|
|
7596
7823
|
options.yes
|
|
7597
7824
|
]);
|
|
7598
7825
|
if (status === "loading") {
|
|
7599
|
-
return /* @__PURE__ */
|
|
7600
|
-
/* @__PURE__ */
|
|
7601
|
-
/* @__PURE__ */
|
|
7826
|
+
return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
|
|
7827
|
+
/* @__PURE__ */ jsx31(AddFlowHeader, { title: "Scanning marketplace" }),
|
|
7828
|
+
/* @__PURE__ */ jsxs26(Text26, { children: [
|
|
7602
7829
|
spinner,
|
|
7603
7830
|
" Discovering skills from plugins..."
|
|
7604
7831
|
] })
|
|
7605
7832
|
] });
|
|
7606
7833
|
}
|
|
7607
7834
|
if (status === "error") {
|
|
7608
|
-
return /* @__PURE__ */
|
|
7609
|
-
/* @__PURE__ */
|
|
7610
|
-
/* @__PURE__ */
|
|
7611
|
-
/* @__PURE__ */
|
|
7835
|
+
return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
|
|
7836
|
+
/* @__PURE__ */ jsx31(AddFlowHeader, { title: "Marketplace scan failed" }),
|
|
7837
|
+
/* @__PURE__ */ jsx31(Text26, { color: "red", children: error }),
|
|
7838
|
+
/* @__PURE__ */ jsx31(Text26, { dimColor: true, children: BACK_QUIT_HINT })
|
|
7612
7839
|
] });
|
|
7613
7840
|
}
|
|
7614
7841
|
const skills = addSkill.marketplace?.skills ?? [];
|
|
7615
7842
|
const warnings = addSkill.marketplace?.warnings ?? [];
|
|
7616
|
-
return /* @__PURE__ */
|
|
7617
|
-
/* @__PURE__ */
|
|
7618
|
-
warnings.length > 0 ? /* @__PURE__ */
|
|
7619
|
-
/* @__PURE__ */
|
|
7843
|
+
return /* @__PURE__ */ jsxs26(Box29, { flexDirection: "column", padding: 1, children: [
|
|
7844
|
+
/* @__PURE__ */ jsx31(AddFlowHeader, { title: "Select skills" }),
|
|
7845
|
+
warnings.length > 0 ? /* @__PURE__ */ jsx31(Box29, { flexDirection: "column", marginBottom: 1, children: warnings.map((warning) => /* @__PURE__ */ jsx31(Text26, { dimColor: true, children: warning }, warning)) }) : null,
|
|
7846
|
+
/* @__PURE__ */ jsx31(
|
|
7620
7847
|
MultiSelect,
|
|
7621
7848
|
{
|
|
7622
7849
|
items: skills.map((entry) => ({
|
|
@@ -7666,8 +7893,8 @@ function autoSelect2(skills, names, yes) {
|
|
|
7666
7893
|
// src/tui/screens/ScanSkills.tsx
|
|
7667
7894
|
import { rm as rm6 } from "fs/promises";
|
|
7668
7895
|
import chalk5 from "chalk";
|
|
7669
|
-
import { Box as
|
|
7670
|
-
import
|
|
7896
|
+
import { Box as Box30, Text as Text27 } from "ink";
|
|
7897
|
+
import React26 from "react";
|
|
7671
7898
|
|
|
7672
7899
|
// src/flows/scan-installed-skills.ts
|
|
7673
7900
|
import { existsSync as existsSync7 } from "fs";
|
|
@@ -7890,17 +8117,17 @@ function removalTargetsForRow(row, cwd) {
|
|
|
7890
8117
|
}
|
|
7891
8118
|
|
|
7892
8119
|
// src/tui/screens/ScanSkills.tsx
|
|
7893
|
-
import { Fragment as Fragment3, jsx as
|
|
8120
|
+
import { Fragment as Fragment3, jsx as jsx32, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
7894
8121
|
function ScanSkillsScreen() {
|
|
7895
8122
|
const { setFlash, setBackHandler } = useNavigation();
|
|
7896
|
-
const [view, setView] =
|
|
7897
|
-
const [error, setError] =
|
|
7898
|
-
const [rows, setRows] =
|
|
7899
|
-
const [progress, setProgress] =
|
|
7900
|
-
const [selected, setSelected] =
|
|
7901
|
-
const [removeTargets, setRemoveTargets] =
|
|
8123
|
+
const [view, setView] = React26.useState("loading");
|
|
8124
|
+
const [error, setError] = React26.useState(null);
|
|
8125
|
+
const [rows, setRows] = React26.useState([]);
|
|
8126
|
+
const [progress, setProgress] = React26.useState(null);
|
|
8127
|
+
const [selected, setSelected] = React26.useState(null);
|
|
8128
|
+
const [removeTargets, setRemoveTargets] = React26.useState(null);
|
|
7902
8129
|
const spinner = useSpinnerFrame(view === "running" || view === "removing");
|
|
7903
|
-
|
|
8130
|
+
React26.useEffect(() => {
|
|
7904
8131
|
let cancelled = false;
|
|
7905
8132
|
const run = async () => {
|
|
7906
8133
|
try {
|
|
@@ -7970,7 +8197,7 @@ function ScanSkillsScreen() {
|
|
|
7970
8197
|
cancelled = true;
|
|
7971
8198
|
};
|
|
7972
8199
|
}, []);
|
|
7973
|
-
|
|
8200
|
+
React26.useEffect(() => {
|
|
7974
8201
|
if (view === "actions" || view === "confirm-remove" || view === "removing") {
|
|
7975
8202
|
setBackHandler(() => {
|
|
7976
8203
|
if (view === "confirm-remove") {
|
|
@@ -7990,26 +8217,26 @@ function ScanSkillsScreen() {
|
|
|
7990
8217
|
setBackHandler(null);
|
|
7991
8218
|
return () => setBackHandler(null);
|
|
7992
8219
|
}, [view, setBackHandler]);
|
|
7993
|
-
const riskyRows =
|
|
7994
|
-
const summary =
|
|
8220
|
+
const riskyRows = React26.useMemo(() => rows.filter(isRisky), [rows]);
|
|
8221
|
+
const summary = React26.useMemo(() => scanSummary(rows), [rows]);
|
|
7995
8222
|
if (view === "empty") {
|
|
7996
|
-
return /* @__PURE__ */
|
|
7997
|
-
/* @__PURE__ */
|
|
7998
|
-
/* @__PURE__ */
|
|
8223
|
+
return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
|
|
8224
|
+
/* @__PURE__ */ jsx32(Header, { title: "Scan skills" }),
|
|
8225
|
+
/* @__PURE__ */ jsx32(Text27, { dimColor: true, children: rows.length === 0 ? "No skills found to scan (project + global)." : `Scanned ${rows.length} skill${rows.length === 1 ? "" : "s"}. No risks found.` })
|
|
7999
8226
|
] });
|
|
8000
8227
|
}
|
|
8001
8228
|
if (view === "loading") {
|
|
8002
|
-
return /* @__PURE__ */
|
|
8003
|
-
/* @__PURE__ */
|
|
8004
|
-
/* @__PURE__ */
|
|
8229
|
+
return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
|
|
8230
|
+
/* @__PURE__ */ jsx32(Header, { title: "Scan skills" }),
|
|
8231
|
+
/* @__PURE__ */ jsx32(Text27, { dimColor: true, children: "Discovering skills..." })
|
|
8005
8232
|
] });
|
|
8006
8233
|
}
|
|
8007
8234
|
if (view === "running") {
|
|
8008
8235
|
const completed = progress?.completed ?? 0;
|
|
8009
8236
|
const total = progress?.total ?? 0;
|
|
8010
|
-
return /* @__PURE__ */
|
|
8011
|
-
/* @__PURE__ */
|
|
8012
|
-
/* @__PURE__ */
|
|
8237
|
+
return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
|
|
8238
|
+
/* @__PURE__ */ jsx32(Header, { title: "Scan skills" }),
|
|
8239
|
+
/* @__PURE__ */ jsxs27(Text27, { children: [
|
|
8013
8240
|
spinner,
|
|
8014
8241
|
" Scanning ",
|
|
8015
8242
|
completed,
|
|
@@ -8019,14 +8246,14 @@ function ScanSkillsScreen() {
|
|
|
8019
8246
|
total === 1 ? "" : "s",
|
|
8020
8247
|
"..."
|
|
8021
8248
|
] }),
|
|
8022
|
-
/* @__PURE__ */
|
|
8249
|
+
/* @__PURE__ */ jsx32(Box30, { marginTop: 1, children: /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
8023
8250
|
] });
|
|
8024
8251
|
}
|
|
8025
8252
|
if (view === "error") {
|
|
8026
|
-
return /* @__PURE__ */
|
|
8027
|
-
/* @__PURE__ */
|
|
8028
|
-
/* @__PURE__ */
|
|
8029
|
-
/* @__PURE__ */
|
|
8253
|
+
return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
|
|
8254
|
+
/* @__PURE__ */ jsx32(Header, { title: "Scan skills" }),
|
|
8255
|
+
/* @__PURE__ */ jsx32(Text27, { color: "red", children: error ?? "Scan failed" }),
|
|
8256
|
+
/* @__PURE__ */ jsx32(Box30, { marginTop: 1, children: /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
8030
8257
|
] });
|
|
8031
8258
|
}
|
|
8032
8259
|
if (view === "actions" && selected) {
|
|
@@ -8037,27 +8264,27 @@ function ScanSkillsScreen() {
|
|
|
8037
8264
|
const top = selected.topSignals?.slice(0, 10) ?? [];
|
|
8038
8265
|
const locationLabels = selected.skill.locations.map((l) => l.label);
|
|
8039
8266
|
const riskColor = level === "critical" || level === "high" ? "red" : level === "medium" ? "yellow" : level === "low" ? "green" : "gray";
|
|
8040
|
-
return /* @__PURE__ */
|
|
8041
|
-
/* @__PURE__ */
|
|
8042
|
-
/* @__PURE__ */
|
|
8043
|
-
/* @__PURE__ */
|
|
8267
|
+
return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
|
|
8268
|
+
/* @__PURE__ */ jsx32(Header, { title: "Skill risk details" }),
|
|
8269
|
+
/* @__PURE__ */ jsxs27(Text27, { children: [
|
|
8270
|
+
/* @__PURE__ */ jsx32(Text27, { bold: true, children: selected.skill.name }),
|
|
8044
8271
|
" ",
|
|
8045
|
-
/* @__PURE__ */
|
|
8272
|
+
/* @__PURE__ */ jsx32(Text27, { dimColor: true, children: `(${selected.skill.slug})` })
|
|
8046
8273
|
] }),
|
|
8047
|
-
selected.error ? /* @__PURE__ */
|
|
8048
|
-
/* @__PURE__ */
|
|
8049
|
-
/* @__PURE__ */
|
|
8274
|
+
selected.error ? /* @__PURE__ */ jsx32(Text27, { color: "red", children: selected.error }) : /* @__PURE__ */ jsxs27(Fragment3, { children: [
|
|
8275
|
+
/* @__PURE__ */ jsxs27(Text27, { children: [
|
|
8276
|
+
/* @__PURE__ */ jsx32(Text27, { dimColor: true, children: "Verdict:" }),
|
|
8050
8277
|
" ",
|
|
8051
|
-
/* @__PURE__ */
|
|
8052
|
-
/* @__PURE__ */
|
|
8278
|
+
/* @__PURE__ */ jsx32(Text27, { color: riskColor, children: verdict }),
|
|
8279
|
+
/* @__PURE__ */ jsx32(Text27, { dimColor: true, children: ` \u2022 level=${level} score=${score} issues=${issues}` })
|
|
8053
8280
|
] }),
|
|
8054
|
-
top.length > 0 ? /* @__PURE__ */
|
|
8055
|
-
selected.ruleset ? /* @__PURE__ */
|
|
8281
|
+
top.length > 0 ? /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: `Top signals: ${top.join(", ")}` }) : null,
|
|
8282
|
+
selected.ruleset ? /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: `Ruleset: ${selected.ruleset}` }) : null
|
|
8056
8283
|
] }),
|
|
8057
|
-
selected.skill.description ? /* @__PURE__ */
|
|
8058
|
-
/* @__PURE__ */
|
|
8059
|
-
locationLabels.length > 0 ? /* @__PURE__ */
|
|
8060
|
-
/* @__PURE__ */
|
|
8284
|
+
selected.skill.description ? /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: selected.skill.description }) : null,
|
|
8285
|
+
/* @__PURE__ */ jsx32(Text27, { dimColor: true, children: `Path: ${selected.skill.path}` }),
|
|
8286
|
+
locationLabels.length > 0 ? /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: `Locations: ${locationLabels.join(", ")}` }) : null,
|
|
8287
|
+
/* @__PURE__ */ jsx32(Box30, { marginTop: 1, children: /* @__PURE__ */ jsx32(
|
|
8061
8288
|
SelectMenu,
|
|
8062
8289
|
{
|
|
8063
8290
|
items: [
|
|
@@ -8083,17 +8310,17 @@ function ScanSkillsScreen() {
|
|
|
8083
8310
|
}
|
|
8084
8311
|
if (view === "confirm-remove" && selected && removeTargets) {
|
|
8085
8312
|
const title = `Remove ${selected.skill.name}`;
|
|
8086
|
-
return /* @__PURE__ */
|
|
8087
|
-
/* @__PURE__ */
|
|
8088
|
-
/* @__PURE__ */
|
|
8089
|
-
/* @__PURE__ */
|
|
8090
|
-
/* @__PURE__ */
|
|
8313
|
+
return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
|
|
8314
|
+
/* @__PURE__ */ jsx32(Header, { title }),
|
|
8315
|
+
/* @__PURE__ */ jsx32(Text27, { dimColor: true, children: "These locations will be removed:" }),
|
|
8316
|
+
/* @__PURE__ */ jsx32(Box30, { flexDirection: "column", marginTop: 1, children: removeTargets.length === 0 ? /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: "None found." }) : removeTargets.map((t) => /* @__PURE__ */ jsxs27(Text27, { children: [
|
|
8317
|
+
/* @__PURE__ */ jsx32(Text27, { children: chalk5.red("\u2022") }),
|
|
8091
8318
|
" ",
|
|
8092
|
-
/* @__PURE__ */
|
|
8319
|
+
/* @__PURE__ */ jsx32(Text27, { dimColor: true, children: t.label }),
|
|
8093
8320
|
" ",
|
|
8094
8321
|
t.path
|
|
8095
8322
|
] }, t.path)) }),
|
|
8096
|
-
/* @__PURE__ */
|
|
8323
|
+
/* @__PURE__ */ jsx32(Box30, { marginTop: 1, children: /* @__PURE__ */ jsx32(
|
|
8097
8324
|
SelectMenu,
|
|
8098
8325
|
{
|
|
8099
8326
|
items: [
|
|
@@ -8141,33 +8368,33 @@ function ScanSkillsScreen() {
|
|
|
8141
8368
|
] });
|
|
8142
8369
|
}
|
|
8143
8370
|
if (view === "removing") {
|
|
8144
|
-
return /* @__PURE__ */
|
|
8145
|
-
/* @__PURE__ */
|
|
8146
|
-
/* @__PURE__ */
|
|
8371
|
+
return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
|
|
8372
|
+
/* @__PURE__ */ jsx32(Header, { title: "Removing skill" }),
|
|
8373
|
+
/* @__PURE__ */ jsxs27(Text27, { children: [
|
|
8147
8374
|
spinner,
|
|
8148
8375
|
" Removing..."
|
|
8149
8376
|
] }),
|
|
8150
|
-
/* @__PURE__ */
|
|
8377
|
+
/* @__PURE__ */ jsx32(Box30, { marginTop: 1, children: /* @__PURE__ */ jsx32(Text27, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
8151
8378
|
] });
|
|
8152
8379
|
}
|
|
8153
8380
|
if (riskyRows.length === 0) {
|
|
8154
|
-
return /* @__PURE__ */
|
|
8155
|
-
/* @__PURE__ */
|
|
8156
|
-
/* @__PURE__ */
|
|
8381
|
+
return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
|
|
8382
|
+
/* @__PURE__ */ jsx32(Header, { title: "Scan skills" }),
|
|
8383
|
+
/* @__PURE__ */ jsx32(Text27, { dimColor: true, children: rows.length === 0 ? "No skills found to scan (project + global)." : `Scanned ${rows.length} skill${rows.length === 1 ? "" : "s"}. No risks found.` })
|
|
8157
8384
|
] });
|
|
8158
8385
|
}
|
|
8159
|
-
return /* @__PURE__ */
|
|
8160
|
-
/* @__PURE__ */
|
|
8161
|
-
/* @__PURE__ */
|
|
8162
|
-
/* @__PURE__ */
|
|
8163
|
-
/* @__PURE__ */
|
|
8164
|
-
/* @__PURE__ */
|
|
8165
|
-
/* @__PURE__ */
|
|
8166
|
-
/* @__PURE__ */
|
|
8167
|
-
/* @__PURE__ */
|
|
8386
|
+
return /* @__PURE__ */ jsxs27(Box30, { flexDirection: "column", padding: 1, children: [
|
|
8387
|
+
/* @__PURE__ */ jsx32(Header, { title: "Scan skills" }),
|
|
8388
|
+
/* @__PURE__ */ jsxs27(Box30, { marginBottom: 1, flexDirection: "column", children: [
|
|
8389
|
+
/* @__PURE__ */ jsx32(Text27, { dimColor: true, children: `Scanned ${plural(summary.total, "skill")}.` }),
|
|
8390
|
+
/* @__PURE__ */ jsxs27(Text27, { children: [
|
|
8391
|
+
/* @__PURE__ */ jsx32(Text27, { color: "red", children: plural(summary.high, "high risk") }),
|
|
8392
|
+
/* @__PURE__ */ jsx32(Text27, { children: ", " }),
|
|
8393
|
+
/* @__PURE__ */ jsx32(Text27, { color: "yellow", children: plural(summary.medium, "medium risk") }),
|
|
8394
|
+
/* @__PURE__ */ jsx32(Text27, { children: " detected." })
|
|
8168
8395
|
] })
|
|
8169
8396
|
] }),
|
|
8170
|
-
/* @__PURE__ */
|
|
8397
|
+
/* @__PURE__ */ jsx32(
|
|
8171
8398
|
SingleSelect,
|
|
8172
8399
|
{
|
|
8173
8400
|
items: riskyRows.map((row) => ({
|
|
@@ -8188,8 +8415,8 @@ function ScanSkillsScreen() {
|
|
|
8188
8415
|
}
|
|
8189
8416
|
|
|
8190
8417
|
// src/tui/screens/UpdateDocs.tsx
|
|
8191
|
-
import { Box as
|
|
8192
|
-
import
|
|
8418
|
+
import { Box as Box31, Text as Text28 } from "ink";
|
|
8419
|
+
import React27 from "react";
|
|
8193
8420
|
|
|
8194
8421
|
// src/docs/update.ts
|
|
8195
8422
|
import { readdir as readdir6, stat as stat6 } from "fs/promises";
|
|
@@ -8255,12 +8482,12 @@ async function updateDocs(cwd = process.cwd()) {
|
|
|
8255
8482
|
}
|
|
8256
8483
|
|
|
8257
8484
|
// src/tui/screens/UpdateDocs.tsx
|
|
8258
|
-
import { jsx as
|
|
8485
|
+
import { jsx as jsx33, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
8259
8486
|
function UpdateDocsScreen() {
|
|
8260
|
-
const [status, setStatus] =
|
|
8261
|
-
const [summary, setSummary] =
|
|
8487
|
+
const [status, setStatus] = React27.useState("running");
|
|
8488
|
+
const [summary, setSummary] = React27.useState(null);
|
|
8262
8489
|
const spinner = useSpinnerFrame(status === "running");
|
|
8263
|
-
|
|
8490
|
+
React27.useEffect(() => {
|
|
8264
8491
|
let cancelled = false;
|
|
8265
8492
|
const run = async () => {
|
|
8266
8493
|
const output2 = await updateDocs();
|
|
@@ -8278,65 +8505,180 @@ function UpdateDocsScreen() {
|
|
|
8278
8505
|
};
|
|
8279
8506
|
}, []);
|
|
8280
8507
|
if (status === "running") {
|
|
8281
|
-
return /* @__PURE__ */
|
|
8282
|
-
/* @__PURE__ */
|
|
8283
|
-
/* @__PURE__ */
|
|
8508
|
+
return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
|
|
8509
|
+
/* @__PURE__ */ jsx33(Header, { title: "Updating docs" }),
|
|
8510
|
+
/* @__PURE__ */ jsxs28(Text28, { children: [
|
|
8284
8511
|
spinner,
|
|
8285
8512
|
" Pulling latest docs..."
|
|
8286
8513
|
] })
|
|
8287
8514
|
] });
|
|
8288
8515
|
}
|
|
8289
8516
|
if (status === "empty") {
|
|
8290
|
-
return /* @__PURE__ */
|
|
8291
|
-
/* @__PURE__ */
|
|
8292
|
-
/* @__PURE__ */
|
|
8293
|
-
/* @__PURE__ */
|
|
8517
|
+
return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
|
|
8518
|
+
/* @__PURE__ */ jsx33(Header, { title: "Update docs" }),
|
|
8519
|
+
/* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "No docs installed yet." }),
|
|
8520
|
+
/* @__PURE__ */ jsx33(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
8294
8521
|
] });
|
|
8295
8522
|
}
|
|
8296
8523
|
if (!summary) {
|
|
8297
|
-
return /* @__PURE__ */
|
|
8298
|
-
/* @__PURE__ */
|
|
8299
|
-
/* @__PURE__ */
|
|
8524
|
+
return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
|
|
8525
|
+
/* @__PURE__ */ jsx33(Header, { title: "Update docs" }),
|
|
8526
|
+
/* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "Nothing to update." })
|
|
8300
8527
|
] });
|
|
8301
8528
|
}
|
|
8302
8529
|
const cwd = process.cwd();
|
|
8303
|
-
return /* @__PURE__ */
|
|
8304
|
-
/* @__PURE__ */
|
|
8305
|
-
summary.updated.length > 0 ? /* @__PURE__ */
|
|
8306
|
-
/* @__PURE__ */
|
|
8307
|
-
summary.updated.map((item) => /* @__PURE__ */
|
|
8530
|
+
return /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", padding: 1, children: [
|
|
8531
|
+
/* @__PURE__ */ jsx33(Header, { title: "Docs update results" }),
|
|
8532
|
+
summary.updated.length > 0 ? /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", marginBottom: 1, children: [
|
|
8533
|
+
/* @__PURE__ */ jsx33(Text28, { children: `Updated ${summary.updated.length} repo${summary.updated.length !== 1 ? "s" : ""}` }),
|
|
8534
|
+
summary.updated.map((item) => /* @__PURE__ */ jsxs28(Text28, { dimColor: true, children: [
|
|
8308
8535
|
item.name,
|
|
8309
8536
|
" \u2192 ",
|
|
8310
8537
|
shortenPath(item.path, cwd)
|
|
8311
8538
|
] }, `updated-${item.name}`))
|
|
8312
8539
|
] }) : null,
|
|
8313
|
-
summary.skipped.length > 0 ? /* @__PURE__ */
|
|
8314
|
-
/* @__PURE__ */
|
|
8315
|
-
summary.skipped.map((item) => /* @__PURE__ */
|
|
8540
|
+
summary.skipped.length > 0 ? /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", marginBottom: 1, children: [
|
|
8541
|
+
/* @__PURE__ */ jsx33(Text28, { dimColor: true, children: "Skipped" }),
|
|
8542
|
+
summary.skipped.map((item) => /* @__PURE__ */ jsxs28(Text28, { dimColor: true, children: [
|
|
8316
8543
|
item.name,
|
|
8317
8544
|
item.message ? ` (${item.message})` : ""
|
|
8318
8545
|
] }, `skipped-${item.name}`))
|
|
8319
8546
|
] }) : null,
|
|
8320
|
-
summary.failed.length > 0 ? /* @__PURE__ */
|
|
8321
|
-
/* @__PURE__ */
|
|
8322
|
-
summary.failed.map((item) => /* @__PURE__ */
|
|
8547
|
+
summary.failed.length > 0 ? /* @__PURE__ */ jsxs28(Box31, { flexDirection: "column", marginBottom: 1, children: [
|
|
8548
|
+
/* @__PURE__ */ jsx33(Text28, { color: "red", children: "Failed" }),
|
|
8549
|
+
summary.failed.map((item) => /* @__PURE__ */ jsxs28(Text28, { color: "red", children: [
|
|
8323
8550
|
item.name,
|
|
8324
8551
|
item.message ? ` (${item.message})` : ""
|
|
8325
8552
|
] }, `failed-${item.name}`))
|
|
8326
8553
|
] }) : null,
|
|
8327
|
-
/* @__PURE__ */
|
|
8554
|
+
/* @__PURE__ */ jsx33(Box31, { marginTop: 1, children: /* @__PURE__ */ jsx33(Text28, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
8328
8555
|
] });
|
|
8329
8556
|
}
|
|
8330
8557
|
|
|
8331
8558
|
// src/tui/screens/UpdateSkills.tsx
|
|
8332
8559
|
import chalk6 from "chalk";
|
|
8333
|
-
import { Box as
|
|
8334
|
-
import
|
|
8560
|
+
import { Box as Box32, Text as Text29, useInput as useInput6 } from "ink";
|
|
8561
|
+
import React28 from "react";
|
|
8335
8562
|
|
|
8336
8563
|
// src/flows/update-skills.ts
|
|
8337
|
-
import {
|
|
8564
|
+
import { randomUUID } from "crypto";
|
|
8565
|
+
import { cp as cp2, mkdir as mkdir8, mkdtemp as mkdtemp6, rm as rm7, stat as stat7, writeFile as writeFile6 } from "fs/promises";
|
|
8566
|
+
import { homedir as homedir5, tmpdir as tmpdir7 } from "os";
|
|
8567
|
+
import { dirname as dirname9, join as join22 } from "path";
|
|
8568
|
+
|
|
8569
|
+
// src/flows/update-well-known-authed.ts
|
|
8570
|
+
import { mkdir as mkdir7, mkdtemp as mkdtemp5, writeFile as writeFile5 } from "fs/promises";
|
|
8338
8571
|
import { tmpdir as tmpdir6 } from "os";
|
|
8339
|
-
import { dirname as
|
|
8572
|
+
import { dirname as dirname8, join as join21 } from "path";
|
|
8573
|
+
function resolveAuthedIndexAuth(entry, endpoint) {
|
|
8574
|
+
if (entry.auth?.tokenHeader) {
|
|
8575
|
+
return { tokenHeader: entry.auth.tokenHeader, tokenPrefix: entry.auth.tokenPrefix ?? "" };
|
|
8576
|
+
}
|
|
8577
|
+
const spec = endpoint === "content" ? entry.content : entry.verify;
|
|
8578
|
+
const tokenHeader = spec?.tokenHeader;
|
|
8579
|
+
const tokenPrefix = spec?.tokenPrefix;
|
|
8580
|
+
if (!tokenHeader) {
|
|
8581
|
+
throw new Error(
|
|
8582
|
+
"Invalid well-known index entry: missing auth.tokenHeader (or legacy tokenHeader)."
|
|
8583
|
+
);
|
|
8584
|
+
}
|
|
8585
|
+
return { tokenHeader, tokenPrefix: tokenPrefix ?? "" };
|
|
8586
|
+
}
|
|
8587
|
+
async function fetchWellKnownAuthedManifest(sourceUrl, licenseKey) {
|
|
8588
|
+
const result = await wellKnownProvider.fetchIndex(sourceUrl);
|
|
8589
|
+
if (!result) return null;
|
|
8590
|
+
const entry = result.index.skills.find(
|
|
8591
|
+
(e) => e && typeof e === "object" && "content" in e && !("files" in e)
|
|
8592
|
+
);
|
|
8593
|
+
if (!entry?.content?.endpoint) return null;
|
|
8594
|
+
const contentAuth = resolveAuthedIndexAuth(entry, "content");
|
|
8595
|
+
const tokenValue = `${contentAuth.tokenPrefix}${licenseKey}`;
|
|
8596
|
+
if (entry.verify?.endpoint) {
|
|
8597
|
+
const verifyAuth = resolveAuthedIndexAuth(entry, "verify");
|
|
8598
|
+
const verifyRes = await fetch(entry.verify.endpoint, {
|
|
8599
|
+
method: entry.verify.method,
|
|
8600
|
+
headers: { [verifyAuth.tokenHeader]: tokenValue }
|
|
8601
|
+
});
|
|
8602
|
+
if (!verifyRes.ok) {
|
|
8603
|
+
const text = await verifyRes.text().catch(() => "");
|
|
8604
|
+
let msg = text;
|
|
8605
|
+
try {
|
|
8606
|
+
const parsed = JSON.parse(text);
|
|
8607
|
+
if (typeof parsed?.error === "string" && parsed.error) {
|
|
8608
|
+
msg = parsed.error;
|
|
8609
|
+
}
|
|
8610
|
+
} catch {
|
|
8611
|
+
}
|
|
8612
|
+
throw new Error(msg || `License verification failed (${verifyRes.status}).`);
|
|
8613
|
+
}
|
|
8614
|
+
}
|
|
8615
|
+
const res = await fetch(entry.content.endpoint, {
|
|
8616
|
+
method: entry.content.method,
|
|
8617
|
+
headers: { [contentAuth.tokenHeader]: tokenValue }
|
|
8618
|
+
});
|
|
8619
|
+
if (!res.ok) {
|
|
8620
|
+
const text = await res.text().catch(() => "");
|
|
8621
|
+
throw new Error(text || `Unable to fetch skill content (${res.status}).`);
|
|
8622
|
+
}
|
|
8623
|
+
const json = await res.json();
|
|
8624
|
+
if (json && typeof json === "object" && "success" in json) {
|
|
8625
|
+
const wrapped = json;
|
|
8626
|
+
if (!wrapped.success) {
|
|
8627
|
+
throw new Error(wrapped.error || "Unable to fetch skill content.");
|
|
8628
|
+
}
|
|
8629
|
+
return wrapped.data;
|
|
8630
|
+
}
|
|
8631
|
+
return json;
|
|
8632
|
+
}
|
|
8633
|
+
async function updateFromWellKnownAuthed(target, helpers) {
|
|
8634
|
+
if (target.entry.sourceType !== "well-known") return false;
|
|
8635
|
+
if (!target.entry.licenseKey) return false;
|
|
8636
|
+
const sourceUrl = target.entry.sourceUrl || target.entry.source;
|
|
8637
|
+
const manifest = await fetchWellKnownAuthedManifest(sourceUrl, target.entry.licenseKey);
|
|
8638
|
+
if (!manifest?.files || typeof manifest.files !== "object") {
|
|
8639
|
+
return false;
|
|
8640
|
+
}
|
|
8641
|
+
if (manifest.contentHash) {
|
|
8642
|
+
target.latestHash = manifest.contentHash;
|
|
8643
|
+
if (target.entry.skillFolderHash && target.entry.skillFolderHash === manifest.contentHash) {
|
|
8644
|
+
target.status = "up-to-date";
|
|
8645
|
+
return false;
|
|
8646
|
+
}
|
|
8647
|
+
}
|
|
8648
|
+
const tempDir = await mkdtemp5(join21(tmpdir6(), "playbooks-well-known-"));
|
|
8649
|
+
registerTempDir(tempDir);
|
|
8650
|
+
try {
|
|
8651
|
+
await mkdir7(tempDir, { recursive: true });
|
|
8652
|
+
for (const [filePath, fileContent] of Object.entries(manifest.files)) {
|
|
8653
|
+
const targetPath = join21(tempDir, filePath);
|
|
8654
|
+
if (!isPathSafe(tempDir, targetPath)) continue;
|
|
8655
|
+
await mkdir7(dirname8(targetPath), { recursive: true });
|
|
8656
|
+
await writeFile5(targetPath, fileContent, "utf-8");
|
|
8657
|
+
}
|
|
8658
|
+
let sourceDir = null;
|
|
8659
|
+
if (target.entry.skillPath) {
|
|
8660
|
+
const normalized = target.entry.skillPath.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
8661
|
+
const folder = normalized.toLowerCase().endsWith("skill.md") ? dirname8(normalized) : normalized;
|
|
8662
|
+
const candidate = join21(tempDir, folder);
|
|
8663
|
+
if (await helpers.pathExists(join21(candidate, "SKILL.md"))) {
|
|
8664
|
+
sourceDir = candidate;
|
|
8665
|
+
}
|
|
8666
|
+
}
|
|
8667
|
+
if (!sourceDir) {
|
|
8668
|
+
const discovered = await discoverSkills(tempDir);
|
|
8669
|
+
const match = discovered.find((s) => s.name === target.name) ?? null;
|
|
8670
|
+
sourceDir = match ? match.path : null;
|
|
8671
|
+
}
|
|
8672
|
+
if (!sourceDir) {
|
|
8673
|
+
return false;
|
|
8674
|
+
}
|
|
8675
|
+
return await helpers.applyUpdateFromDir(target.name, target.scope, sourceDir);
|
|
8676
|
+
} finally {
|
|
8677
|
+
await cleanupTempDir(tempDir);
|
|
8678
|
+
}
|
|
8679
|
+
}
|
|
8680
|
+
|
|
8681
|
+
// src/flows/update-skills.ts
|
|
8340
8682
|
var repoTreeCache = /* @__PURE__ */ new Map();
|
|
8341
8683
|
function normalizeSkillFolderPath(skillPath) {
|
|
8342
8684
|
let folderPath = skillPath;
|
|
@@ -8404,6 +8746,23 @@ async function pathExists3(path) {
|
|
|
8404
8746
|
return false;
|
|
8405
8747
|
}
|
|
8406
8748
|
}
|
|
8749
|
+
function getBackupRoot(scope) {
|
|
8750
|
+
const baseDir = scope === "global" ? homedir5() : process.cwd();
|
|
8751
|
+
return join22(baseDir, ".playbooks", "backups");
|
|
8752
|
+
}
|
|
8753
|
+
async function backupDirIfExists(input) {
|
|
8754
|
+
if (process.env.PLAYBOOKS_DISABLE_BACKUPS === "1") return;
|
|
8755
|
+
try {
|
|
8756
|
+
if (!await pathExists3(input.sourcePath)) return;
|
|
8757
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
8758
|
+
const safeSkillName = sanitizeSkillName(input.skillName);
|
|
8759
|
+
const backupBase = join22(getBackupRoot(input.scope), stamp, input.scope, safeSkillName);
|
|
8760
|
+
const dest = join22(backupBase, `${input.label}-${randomUUID()}`);
|
|
8761
|
+
await mkdir8(dirname9(dest), { recursive: true });
|
|
8762
|
+
await cp2(input.sourcePath, dest, { recursive: true, dereference: false });
|
|
8763
|
+
} catch {
|
|
8764
|
+
}
|
|
8765
|
+
}
|
|
8407
8766
|
async function applyUpdateFromDir(skillName, scope, sourceDir) {
|
|
8408
8767
|
const canonicalPath = getCanonicalPath(skillName, { global: scope === "global" });
|
|
8409
8768
|
const installs = await findSkillInstallations(skillName, scope);
|
|
@@ -8413,12 +8772,14 @@ async function applyUpdateFromDir(skillName, scope, sourceDir) {
|
|
|
8413
8772
|
return false;
|
|
8414
8773
|
}
|
|
8415
8774
|
if (canonicalExists || hasSymlink) {
|
|
8775
|
+
await backupDirIfExists({ scope, skillName, sourcePath: canonicalPath, label: "canonical" });
|
|
8416
8776
|
await rm7(canonicalPath, { recursive: true, force: true });
|
|
8417
8777
|
await copySkillDirectory(sourceDir, canonicalPath);
|
|
8418
8778
|
}
|
|
8419
8779
|
const updateTargets = installs.filter((i) => !i.isSymlink && i.path !== canonicalPath);
|
|
8420
8780
|
if (updateTargets.length > 0) {
|
|
8421
8781
|
for (const install of updateTargets) {
|
|
8782
|
+
await backupDirIfExists({ scope, skillName, sourcePath: install.path, label: "install" });
|
|
8422
8783
|
await rm7(install.path, { recursive: true, force: true });
|
|
8423
8784
|
await copySkillDirectory(sourceDir, install.path);
|
|
8424
8785
|
}
|
|
@@ -8431,8 +8792,8 @@ async function updateFromRepo(target) {
|
|
|
8431
8792
|
let sourceDir = null;
|
|
8432
8793
|
if (target.entry.skillPath) {
|
|
8433
8794
|
const normalizedPath = target.entry.skillPath.replace(/\\/g, "/");
|
|
8434
|
-
const skillDir =
|
|
8435
|
-
if (await pathExists3(
|
|
8795
|
+
const skillDir = join22(tempDir, dirname9(normalizedPath));
|
|
8796
|
+
if (await pathExists3(join22(skillDir, "SKILL.md"))) {
|
|
8436
8797
|
sourceDir = skillDir;
|
|
8437
8798
|
}
|
|
8438
8799
|
}
|
|
@@ -8473,21 +8834,21 @@ async function updateFromRemote(target) {
|
|
|
8473
8834
|
if (!content && !files) {
|
|
8474
8835
|
return false;
|
|
8475
8836
|
}
|
|
8476
|
-
const tempDir = await
|
|
8837
|
+
const tempDir = await mkdtemp6(join22(tmpdir7(), "playbooks-skill-"));
|
|
8477
8838
|
registerTempDir(tempDir);
|
|
8478
8839
|
try {
|
|
8479
|
-
await
|
|
8840
|
+
await mkdir8(tempDir, { recursive: true });
|
|
8480
8841
|
if (files) {
|
|
8481
8842
|
for (const [filePath, fileContent] of files.entries()) {
|
|
8482
|
-
const targetPath =
|
|
8843
|
+
const targetPath = join22(tempDir, filePath);
|
|
8483
8844
|
if (!isPathSafe(tempDir, targetPath)) {
|
|
8484
8845
|
continue;
|
|
8485
8846
|
}
|
|
8486
|
-
await
|
|
8487
|
-
await
|
|
8847
|
+
await mkdir8(dirname9(targetPath), { recursive: true });
|
|
8848
|
+
await writeFile6(targetPath, fileContent, "utf-8");
|
|
8488
8849
|
}
|
|
8489
8850
|
} else if (content) {
|
|
8490
|
-
await
|
|
8851
|
+
await writeFile6(join22(tempDir, "SKILL.md"), content, "utf-8");
|
|
8491
8852
|
}
|
|
8492
8853
|
return await applyUpdateFromDir(target.name, target.scope, tempDir);
|
|
8493
8854
|
} finally {
|
|
@@ -8495,6 +8856,10 @@ async function updateFromRemote(target) {
|
|
|
8495
8856
|
}
|
|
8496
8857
|
}
|
|
8497
8858
|
async function updateTargetSkill(target) {
|
|
8859
|
+
if (target.entry.sourceType === "well-known" && target.entry.licenseKey) {
|
|
8860
|
+
const updated = await updateFromWellKnownAuthed(target, { applyUpdateFromDir, pathExists: pathExists3 });
|
|
8861
|
+
if (updated) return true;
|
|
8862
|
+
}
|
|
8498
8863
|
if (target.entry.sourceType === "github" || target.entry.sourceType === "gitlab" || target.entry.sourceType === "git") {
|
|
8499
8864
|
return await updateFromRepo(target);
|
|
8500
8865
|
}
|
|
@@ -8584,15 +8949,15 @@ async function updateSkills(targets) {
|
|
|
8584
8949
|
}
|
|
8585
8950
|
|
|
8586
8951
|
// src/tui/screens/UpdateSkills.tsx
|
|
8587
|
-
import { jsx as
|
|
8952
|
+
import { jsx as jsx34, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
8588
8953
|
function UpdateScreen() {
|
|
8589
8954
|
const { invocation, navigateTo, setFlash } = useNavigation();
|
|
8590
|
-
const [status, setStatus] =
|
|
8591
|
-
const [targets, setTargets] =
|
|
8592
|
-
const [selected, setSelected] =
|
|
8593
|
-
const [summary, setSummary] =
|
|
8594
|
-
const [showOnlyNeeds, setShowOnlyNeeds] =
|
|
8595
|
-
const [rateLimited, setRateLimited] =
|
|
8955
|
+
const [status, setStatus] = React28.useState("loading");
|
|
8956
|
+
const [targets, setTargets] = React28.useState([]);
|
|
8957
|
+
const [selected, setSelected] = React28.useState([]);
|
|
8958
|
+
const [summary, setSummary] = React28.useState(null);
|
|
8959
|
+
const [showOnlyNeeds, setShowOnlyNeeds] = React28.useState(false);
|
|
8960
|
+
const [rateLimited, setRateLimited] = React28.useState(false);
|
|
8596
8961
|
const spinner = useSpinnerFrame(status === "running");
|
|
8597
8962
|
useInput6((input) => {
|
|
8598
8963
|
if (status !== "select") return;
|
|
@@ -8600,7 +8965,7 @@ function UpdateScreen() {
|
|
|
8600
8965
|
setShowOnlyNeeds((prev) => !prev);
|
|
8601
8966
|
}
|
|
8602
8967
|
});
|
|
8603
|
-
|
|
8968
|
+
React28.useEffect(() => {
|
|
8604
8969
|
let cancelled = false;
|
|
8605
8970
|
const load = async () => {
|
|
8606
8971
|
const scopes = resolveScopes(invocation.options);
|
|
@@ -8642,7 +9007,7 @@ function UpdateScreen() {
|
|
|
8642
9007
|
cancelled = true;
|
|
8643
9008
|
};
|
|
8644
9009
|
}, [invocation, setFlash]);
|
|
8645
|
-
|
|
9010
|
+
React28.useEffect(() => {
|
|
8646
9011
|
let cancelled = false;
|
|
8647
9012
|
const run = async () => {
|
|
8648
9013
|
if (status !== "running" || selected.length === 0) return;
|
|
@@ -8657,16 +9022,16 @@ function UpdateScreen() {
|
|
|
8657
9022
|
};
|
|
8658
9023
|
}, [status, selected]);
|
|
8659
9024
|
if (status === "empty") {
|
|
8660
|
-
return /* @__PURE__ */
|
|
8661
|
-
/* @__PURE__ */
|
|
8662
|
-
/* @__PURE__ */
|
|
8663
|
-
/* @__PURE__ */
|
|
9025
|
+
return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
|
|
9026
|
+
/* @__PURE__ */ jsx34(Header, { title: "Update skills" }),
|
|
9027
|
+
/* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "No tracked skills to update yet." }),
|
|
9028
|
+
/* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "Re-install a skill once to enable updates." })
|
|
8664
9029
|
] });
|
|
8665
9030
|
}
|
|
8666
9031
|
if (status === "loading") {
|
|
8667
|
-
return /* @__PURE__ */
|
|
8668
|
-
/* @__PURE__ */
|
|
8669
|
-
/* @__PURE__ */
|
|
9032
|
+
return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
|
|
9033
|
+
/* @__PURE__ */ jsx34(Header, { title: "Update skills" }),
|
|
9034
|
+
/* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "Loading tracked skills..." })
|
|
8670
9035
|
] });
|
|
8671
9036
|
}
|
|
8672
9037
|
if (status === "select") {
|
|
@@ -8674,17 +9039,17 @@ function UpdateScreen() {
|
|
|
8674
9039
|
const defaults = selected;
|
|
8675
9040
|
const hint = showOnlyNeeds ? UPDATE_HINT_NEEDS_ONLY : UPDATE_HINT_ALL;
|
|
8676
9041
|
if (showOnlyNeeds && visibleTargets.length === 0) {
|
|
8677
|
-
return /* @__PURE__ */
|
|
8678
|
-
/* @__PURE__ */
|
|
8679
|
-
/* @__PURE__ */
|
|
8680
|
-
rateLimited ? /* @__PURE__ */
|
|
8681
|
-
/* @__PURE__ */
|
|
9042
|
+
return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
|
|
9043
|
+
/* @__PURE__ */ jsx34(Header, { title: "Select skills to update" }),
|
|
9044
|
+
/* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "No updates found." }),
|
|
9045
|
+
rateLimited ? /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "GitHub rate limit hit. Some skills may be marked unknown." }) : null,
|
|
9046
|
+
/* @__PURE__ */ jsx34(Box32, { marginTop: 1, children: /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: UPDATE_EMPTY_HINT }) })
|
|
8682
9047
|
] });
|
|
8683
9048
|
}
|
|
8684
|
-
return /* @__PURE__ */
|
|
8685
|
-
/* @__PURE__ */
|
|
8686
|
-
rateLimited ? /* @__PURE__ */
|
|
8687
|
-
/* @__PURE__ */
|
|
9049
|
+
return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
|
|
9050
|
+
/* @__PURE__ */ jsx34(Header, { title: "Select skills to update" }),
|
|
9051
|
+
rateLimited ? /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "GitHub rate limit hit. Some skills marked unknown." }) : null,
|
|
9052
|
+
/* @__PURE__ */ jsx34(
|
|
8688
9053
|
MultiSelect,
|
|
8689
9054
|
{
|
|
8690
9055
|
items: visibleTargets.map((target) => ({
|
|
@@ -8707,9 +9072,9 @@ function UpdateScreen() {
|
|
|
8707
9072
|
] });
|
|
8708
9073
|
}
|
|
8709
9074
|
if (status === "running") {
|
|
8710
|
-
return /* @__PURE__ */
|
|
8711
|
-
/* @__PURE__ */
|
|
8712
|
-
/* @__PURE__ */
|
|
9075
|
+
return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
|
|
9076
|
+
/* @__PURE__ */ jsx34(Header, { title: "Updating skills" }),
|
|
9077
|
+
/* @__PURE__ */ jsxs29(Text29, { children: [
|
|
8713
9078
|
spinner,
|
|
8714
9079
|
" Updating ",
|
|
8715
9080
|
selected.length,
|
|
@@ -8720,17 +9085,17 @@ function UpdateScreen() {
|
|
|
8720
9085
|
] });
|
|
8721
9086
|
}
|
|
8722
9087
|
if (!summary) {
|
|
8723
|
-
return /* @__PURE__ */
|
|
8724
|
-
/* @__PURE__ */
|
|
8725
|
-
/* @__PURE__ */
|
|
9088
|
+
return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
|
|
9089
|
+
/* @__PURE__ */ jsx34(Header, { title: "Update skills" }),
|
|
9090
|
+
/* @__PURE__ */ jsx34(Text29, { dimColor: true, children: "Nothing to update." })
|
|
8726
9091
|
] });
|
|
8727
9092
|
}
|
|
8728
|
-
return /* @__PURE__ */
|
|
8729
|
-
/* @__PURE__ */
|
|
8730
|
-
summary.updated.length > 0 ? /* @__PURE__ */
|
|
8731
|
-
summary.skipped.length > 0 ? /* @__PURE__ */
|
|
8732
|
-
summary.failed.length > 0 ? /* @__PURE__ */
|
|
8733
|
-
/* @__PURE__ */
|
|
9093
|
+
return /* @__PURE__ */ jsxs29(Box32, { flexDirection: "column", padding: 1, children: [
|
|
9094
|
+
/* @__PURE__ */ jsx34(Header, { title: "Update results" }),
|
|
9095
|
+
summary.updated.length > 0 ? /* @__PURE__ */ jsx34(Text29, { children: `Updated ${summary.updated.length} skill${summary.updated.length !== 1 ? "s" : ""}` }) : null,
|
|
9096
|
+
summary.skipped.length > 0 ? /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: `Skipped: ${summary.skipped.map(formatTargetLabel).join(", ")}` }) : null,
|
|
9097
|
+
summary.failed.length > 0 ? /* @__PURE__ */ jsx34(Text29, { color: "red", children: `Failed: ${summary.failed.map(formatTargetLabel).join(", ")}` }) : null,
|
|
9098
|
+
/* @__PURE__ */ jsx34(Box32, { marginTop: 1, children: /* @__PURE__ */ jsx34(Text29, { dimColor: true, children: BACK_QUIT_HINT }) })
|
|
8734
9099
|
] });
|
|
8735
9100
|
}
|
|
8736
9101
|
function resolveScopes(options) {
|
|
@@ -8759,61 +9124,63 @@ function sortTargets(a, b) {
|
|
|
8759
9124
|
}
|
|
8760
9125
|
|
|
8761
9126
|
// src/tui/ScreenRouter.tsx
|
|
8762
|
-
import { Fragment as Fragment4, jsx as
|
|
9127
|
+
import { Fragment as Fragment4, jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
8763
9128
|
function ScreenRouter() {
|
|
8764
9129
|
const { screen } = useNavigation();
|
|
8765
9130
|
const render2 = (s) => {
|
|
8766
9131
|
switch (s) {
|
|
8767
9132
|
case "main":
|
|
8768
|
-
return /* @__PURE__ */
|
|
9133
|
+
return /* @__PURE__ */ jsx35(MainMenu, {});
|
|
8769
9134
|
case "add-source":
|
|
8770
|
-
return /* @__PURE__ */
|
|
9135
|
+
return /* @__PURE__ */ jsx35(AddSourceScreen, {});
|
|
8771
9136
|
case "add-docs":
|
|
8772
|
-
return /* @__PURE__ */
|
|
9137
|
+
return /* @__PURE__ */ jsx35(AddDocsScreen, {});
|
|
8773
9138
|
case "add-marketplace-plugins":
|
|
8774
|
-
return /* @__PURE__ */
|
|
9139
|
+
return /* @__PURE__ */ jsx35(MarketplacePluginScreen, {});
|
|
8775
9140
|
case "add-marketplace-skills":
|
|
8776
|
-
return /* @__PURE__ */
|
|
9141
|
+
return /* @__PURE__ */ jsx35(MarketplaceSkillScreen, {});
|
|
8777
9142
|
case "find-skill-search":
|
|
8778
|
-
return /* @__PURE__ */
|
|
9143
|
+
return /* @__PURE__ */ jsx35(FindSkillSearchScreen, {});
|
|
8779
9144
|
case "find-skill-results":
|
|
8780
|
-
return /* @__PURE__ */
|
|
9145
|
+
return /* @__PURE__ */ jsx35(FindSkillResultsScreen, {});
|
|
8781
9146
|
case "scan-skills":
|
|
8782
|
-
return /* @__PURE__ */
|
|
9147
|
+
return /* @__PURE__ */ jsx35(ScanSkillsScreen, {});
|
|
8783
9148
|
case "get-url":
|
|
8784
|
-
return /* @__PURE__ */
|
|
9149
|
+
return /* @__PURE__ */ jsx35(GetUrlScreen, {});
|
|
8785
9150
|
case "add-skill-select":
|
|
8786
|
-
return /* @__PURE__ */
|
|
9151
|
+
return /* @__PURE__ */ jsx35(AddSkillSelectScreen, {});
|
|
9152
|
+
case "add-license-key":
|
|
9153
|
+
return /* @__PURE__ */ jsx35(AddLicenseKeyScreen, {});
|
|
8787
9154
|
case "add-security-scan":
|
|
8788
|
-
return /* @__PURE__ */
|
|
9155
|
+
return /* @__PURE__ */ jsx35(AddSecurityScanScreen, {});
|
|
8789
9156
|
case "add-targets":
|
|
8790
|
-
return /* @__PURE__ */
|
|
9157
|
+
return /* @__PURE__ */ jsx35(AddTargetsScreen, {});
|
|
8791
9158
|
case "add-scope":
|
|
8792
|
-
return /* @__PURE__ */
|
|
9159
|
+
return /* @__PURE__ */ jsx35(AddScopeScreen, {});
|
|
8793
9160
|
case "add-mode":
|
|
8794
|
-
return /* @__PURE__ */
|
|
9161
|
+
return /* @__PURE__ */ jsx35(AddModeScreen, {});
|
|
8795
9162
|
case "add-confirm":
|
|
8796
|
-
return /* @__PURE__ */
|
|
9163
|
+
return /* @__PURE__ */ jsx35(AddConfirmScreen, {});
|
|
8797
9164
|
case "add-install":
|
|
8798
|
-
return /* @__PURE__ */
|
|
9165
|
+
return /* @__PURE__ */ jsx35(AddInstallScreen, {});
|
|
8799
9166
|
case "add-result":
|
|
8800
|
-
return /* @__PURE__ */
|
|
9167
|
+
return /* @__PURE__ */ jsx35(AddResultScreen, {});
|
|
8801
9168
|
case "list":
|
|
8802
|
-
return /* @__PURE__ */
|
|
9169
|
+
return /* @__PURE__ */ jsx35(ListScreen, {});
|
|
8803
9170
|
case "manage":
|
|
8804
|
-
return /* @__PURE__ */
|
|
9171
|
+
return /* @__PURE__ */ jsx35(ManageScreen, {});
|
|
8805
9172
|
case "update":
|
|
8806
|
-
return /* @__PURE__ */
|
|
9173
|
+
return /* @__PURE__ */ jsx35(UpdateScreen, {});
|
|
8807
9174
|
case "update-docs":
|
|
8808
|
-
return /* @__PURE__ */
|
|
9175
|
+
return /* @__PURE__ */ jsx35(UpdateDocsScreen, {});
|
|
8809
9176
|
default:
|
|
8810
9177
|
return null;
|
|
8811
9178
|
}
|
|
8812
9179
|
};
|
|
8813
|
-
return /* @__PURE__ */
|
|
8814
|
-
/* @__PURE__ */
|
|
9180
|
+
return /* @__PURE__ */ jsxs30(Fragment4, { children: [
|
|
9181
|
+
/* @__PURE__ */ jsx35(BrandHeader, {}),
|
|
8815
9182
|
render2(screen),
|
|
8816
|
-
/* @__PURE__ */
|
|
9183
|
+
/* @__PURE__ */ jsx35(FlashBar, { align: "center" })
|
|
8817
9184
|
] });
|
|
8818
9185
|
}
|
|
8819
9186
|
|
|
@@ -8893,14 +9260,14 @@ function useKeyboardShortcuts() {
|
|
|
8893
9260
|
}
|
|
8894
9261
|
|
|
8895
9262
|
// src/tui/App.tsx
|
|
8896
|
-
import { jsx as
|
|
9263
|
+
import { jsx as jsx36 } from "react/jsx-runtime";
|
|
8897
9264
|
function AppRoot() {
|
|
8898
9265
|
useKeyboardShortcuts();
|
|
8899
|
-
return /* @__PURE__ */
|
|
9266
|
+
return /* @__PURE__ */ jsx36(ScreenRouter, {});
|
|
8900
9267
|
}
|
|
8901
9268
|
function runApp(initialInvocation, initialScreen) {
|
|
8902
9269
|
const { waitUntilExit } = render(
|
|
8903
|
-
/* @__PURE__ */
|
|
9270
|
+
/* @__PURE__ */ jsx36(NavigationProvider, { initialInvocation, initialScreen, children: /* @__PURE__ */ jsx36(AppRoot, {}) })
|
|
8904
9271
|
);
|
|
8905
9272
|
return waitUntilExit();
|
|
8906
9273
|
}
|
|
@@ -8914,7 +9281,7 @@ program.addHelpCommand();
|
|
|
8914
9281
|
var applyAddSkillOptions = (cmd) => cmd.option("-g, --global", "Install globally (user-level) instead of project-level").option(
|
|
8915
9282
|
"-a, --agent <agents...>",
|
|
8916
9283
|
"Target agents to install to (claude-code, codex, cursor, opencode, and more)"
|
|
8917
|
-
).option("-s, --skill <skills...>", "Install specific skills by name").option("-l, --list", "List available skills in the repository without installing").option("-y, --yes", "Skip confirmation prompts").option("--all", "Install all skills to all agents without prompts (implies -y -g)");
|
|
9284
|
+
).option("-s, --skill <skills...>", "Install specific skills by name").option("-l, --list", "List available skills in the repository without installing").option("-y, --yes", "Skip confirmation prompts").option("--license-key <key>", "License key for paid/private skills").option("--all", "Install all skills to all agents without prompts (implies -y -g)");
|
|
8918
9285
|
function normalizeOptions(options) {
|
|
8919
9286
|
const normalized = { ...options };
|
|
8920
9287
|
if (normalized.all) {
|