skillio 0.1.12 → 0.1.13

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.
@@ -1,252 +0,0 @@
1
- import {
2
- cyan,
3
- discoverSkills,
4
- getLockPath,
5
- red
6
- } from "./chunk-0qvp6v8g.js";
7
-
8
- // src/commands/picker.ts
9
- import { spawnSync } from "node:child_process";
10
-
11
- // src/utils/list-removable.ts
12
- function listRemovableTargets(input) {
13
- const records = [...discoverSkills(input).values()];
14
- const inLock = [];
15
- const orphan = [];
16
- for (const r of records) {
17
- if (r.sources.includes("lock"))
18
- inLock.push(r.name);
19
- else
20
- orphan.push(r.name);
21
- }
22
- inLock.sort();
23
- orphan.sort();
24
- return { inLock, orphan };
25
- }
26
-
27
- // src/utils/prompt.ts
28
- import { emitKeypressEvents } from "node:readline";
29
- async function select(params) {
30
- const input = params.input ?? process.stdin;
31
- const output = params.output ?? process.stdout;
32
- if (!input.isTTY || !output.isTTY)
33
- return null;
34
- let cursor = 0;
35
- const total = params.options.length;
36
- function render() {
37
- output.write(`${params.title}
38
- `);
39
- for (let i = 0;i < total; i++) {
40
- const opt = params.options[i];
41
- if (!opt)
42
- continue;
43
- const marker = i === cursor ? cyan(">") : " ";
44
- output.write(`${marker} ${opt.label}
45
- `);
46
- }
47
- }
48
- function clear() {
49
- output.write(`\x1B[${total + 1}A\x1B[J`);
50
- }
51
- emitKeypressEvents(input);
52
- if (input.setRawMode)
53
- input.setRawMode(true);
54
- input.resume();
55
- render();
56
- return await new Promise((resolve) => {
57
- const onKey = (_str, key) => {
58
- if (key.ctrl && key.name === "c") {
59
- cleanup();
60
- resolve(null);
61
- return;
62
- }
63
- if (key.name === "escape" || key.name === "q") {
64
- cleanup();
65
- resolve(null);
66
- return;
67
- }
68
- if (key.name === "up" && cursor > 0) {
69
- cursor--;
70
- clear();
71
- render();
72
- return;
73
- }
74
- if (key.name === "down" && cursor < total - 1) {
75
- cursor++;
76
- clear();
77
- render();
78
- return;
79
- }
80
- if (key.name === "return") {
81
- cleanup();
82
- const chosen = params.options[cursor]?.value ?? null;
83
- resolve(chosen);
84
- return;
85
- }
86
- };
87
- function onSigterm() {
88
- cleanup();
89
- resolve(null);
90
- }
91
- function cleanup() {
92
- input.removeListener("keypress", onKey);
93
- process.removeListener("SIGTERM", onSigterm);
94
- if (input.setRawMode)
95
- input.setRawMode(false);
96
- input.pause();
97
- }
98
- process.once("SIGTERM", onSigterm);
99
- input.on("keypress", onKey);
100
- });
101
- }
102
- async function multiSelect(params) {
103
- const input = params.input ?? process.stdin;
104
- const output = params.output ?? process.stdout;
105
- if (!input.isTTY || !output.isTTY)
106
- return null;
107
- let cursor = 0;
108
- const total = params.options.length;
109
- const selected = new Set;
110
- function render() {
111
- output.write(`${params.title}
112
- `);
113
- for (let i = 0;i < total; i++) {
114
- const opt = params.options[i];
115
- if (!opt)
116
- continue;
117
- const cursorMark = i === cursor ? cyan(">") : " ";
118
- const checkbox = selected.has(i) ? "[x]" : "[ ]";
119
- output.write(`${cursorMark} ${checkbox} ${opt.label}
120
- `);
121
- }
122
- }
123
- function clear() {
124
- output.write(`\x1B[${total + 1}A\x1B[J`);
125
- }
126
- emitKeypressEvents(input);
127
- if (input.setRawMode)
128
- input.setRawMode(true);
129
- input.resume();
130
- render();
131
- return await new Promise((resolve) => {
132
- const onKey = (_str, key) => {
133
- if (key.ctrl && key.name === "c") {
134
- cleanup();
135
- resolve(null);
136
- return;
137
- }
138
- if (key.name === "escape" || key.name === "q") {
139
- cleanup();
140
- resolve(null);
141
- return;
142
- }
143
- if (key.name === "up" && cursor > 0) {
144
- cursor--;
145
- clear();
146
- render();
147
- return;
148
- }
149
- if (key.name === "down" && cursor < total - 1) {
150
- cursor++;
151
- clear();
152
- render();
153
- return;
154
- }
155
- if (key.name === "space") {
156
- if (selected.has(cursor))
157
- selected.delete(cursor);
158
- else
159
- selected.add(cursor);
160
- clear();
161
- render();
162
- return;
163
- }
164
- if (key.name === "return") {
165
- cleanup();
166
- const values = [];
167
- for (let i = 0;i < total; i++) {
168
- if (selected.has(i)) {
169
- const v = params.options[i]?.value;
170
- if (v !== undefined)
171
- values.push(v);
172
- }
173
- }
174
- resolve(values);
175
- return;
176
- }
177
- };
178
- function onSigterm() {
179
- cleanup();
180
- resolve(null);
181
- }
182
- function cleanup() {
183
- input.removeListener("keypress", onKey);
184
- process.removeListener("SIGTERM", onSigterm);
185
- if (input.setRawMode)
186
- input.setRawMode(false);
187
- input.pause();
188
- }
189
- process.once("SIGTERM", onSigterm);
190
- input.on("keypress", onKey);
191
- });
192
- }
193
-
194
- // src/commands/picker.ts
195
- async function pickRemoveTargets(args) {
196
- const lockPath = getLockPath(args.global);
197
- const { inLock, orphan } = listRemovableTargets({
198
- isGlobal: args.global,
199
- cwd: process.cwd(),
200
- lockPath
201
- });
202
- if (inLock.length === 0 && orphan.length === 0) {
203
- console.log("No skills found in scope.");
204
- return [];
205
- }
206
- const options = [
207
- ...inLock.map((name) => ({ value: name, label: name })),
208
- ...orphan.map((name) => ({ value: name, label: `${name} ${red("(orphan)")}` }))
209
- ];
210
- return await multiSelect({
211
- title: "skillio — pick skills to remove (Space toggle, Enter confirm)",
212
- options
213
- });
214
- }
215
- async function runPicker(args) {
216
- const choice = await select({
217
- title: "skillio — pick a command",
218
- options: [
219
- { value: "usage", label: "usage — count of skill invocations" },
220
- { value: "cost", label: "cost — per-skill ambient tokens" },
221
- { value: "list", label: "list — installed skills per source" },
222
- { value: "remove", label: "remove — delete a skill (disk-only; lock with --force-lock)" },
223
- { value: "quit", label: "quit" }
224
- ]
225
- });
226
- if (choice === null || choice === "quit")
227
- return 0;
228
- const cliPath = process.argv[1];
229
- if (!cliPath) {
230
- console.error("skillio: cannot resolve CLI path (process.argv[1] missing)");
231
- return 1;
232
- }
233
- let argv;
234
- if (choice === "remove") {
235
- const targets = await pickRemoveTargets(args);
236
- if (targets === null || targets.length === 0)
237
- return 0;
238
- argv = ["rm", ...targets];
239
- } else {
240
- argv = [choice];
241
- }
242
- if (args.global)
243
- argv.push("-g");
244
- const r = spawnSync(process.execPath, [cliPath, ...argv], {
245
- stdio: "inherit",
246
- env: process.env
247
- });
248
- return r.status ?? 0;
249
- }
250
- export {
251
- runPicker
252
- };