skild 0.10.6 → 0.10.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +49 -116
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -86,31 +86,10 @@ var logger = {
|
|
|
86
86
|
};
|
|
87
87
|
|
|
88
88
|
// src/utils/interactive-select.ts
|
|
89
|
+
import { checkbox } from "@inquirer/prompts";
|
|
89
90
|
import readline from "readline";
|
|
90
91
|
import chalk2 from "chalk";
|
|
91
92
|
import { PLATFORMS } from "@skild/core";
|
|
92
|
-
function buildSkillTree(skills) {
|
|
93
|
-
const allNode = createTreeNode("all", "All Skills", 1, false);
|
|
94
|
-
for (let i = 0; i < skills.length; i++) {
|
|
95
|
-
const relPath = skills[i].relPath;
|
|
96
|
-
const parts = relPath === "." ? ["."] : relPath.split("/").filter(Boolean);
|
|
97
|
-
allNode.leafIndices.push(i);
|
|
98
|
-
let current = allNode;
|
|
99
|
-
for (let d = 0; d < parts.length; d++) {
|
|
100
|
-
const part = parts[d];
|
|
101
|
-
const nodeId = parts.slice(0, d + 1).join("/");
|
|
102
|
-
let child = current.children.find((c2) => c2.name === part);
|
|
103
|
-
if (!child) {
|
|
104
|
-
child = createTreeNode(nodeId, part, d + 2, d === parts.length - 1);
|
|
105
|
-
current.children.push(child);
|
|
106
|
-
}
|
|
107
|
-
child.leafIndices.push(i);
|
|
108
|
-
current = child;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
collapseIntermediateNodes(allNode);
|
|
112
|
-
return wrapWithRoot(allNode);
|
|
113
|
-
}
|
|
114
93
|
function buildSyncTree(choices) {
|
|
115
94
|
const root = createTreeNode("root", "All targets", 1, false);
|
|
116
95
|
const platforms = /* @__PURE__ */ new Map();
|
|
@@ -144,56 +123,12 @@ function buildPlatformTree(items) {
|
|
|
144
123
|
}
|
|
145
124
|
return wrapWithRoot(allNode);
|
|
146
125
|
}
|
|
147
|
-
function buildTreeFromSkillNodes(nodes, totalSkills) {
|
|
148
|
-
const allNode = createTreeNode("all", "All Skills", 1, false);
|
|
149
|
-
const attach = (node, depth) => {
|
|
150
|
-
const treeNode = createTreeNode(
|
|
151
|
-
node.id,
|
|
152
|
-
node.label,
|
|
153
|
-
depth,
|
|
154
|
-
Boolean(node.skillIndex != null && (!node.children || node.children.length === 0)),
|
|
155
|
-
node.skillIndex != null ? [node.skillIndex] : []
|
|
156
|
-
);
|
|
157
|
-
if (node.children?.length) {
|
|
158
|
-
for (const child of node.children) {
|
|
159
|
-
const childNode = attach(child, depth + 1);
|
|
160
|
-
treeNode.children.push(childNode);
|
|
161
|
-
treeNode.leafIndices.push(...childNode.leafIndices);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
return treeNode;
|
|
165
|
-
};
|
|
166
|
-
for (const node of nodes) {
|
|
167
|
-
const childNode = attach(node, 2);
|
|
168
|
-
allNode.children.push(childNode);
|
|
169
|
-
allNode.leafIndices.push(...childNode.leafIndices);
|
|
170
|
-
}
|
|
171
|
-
if (allNode.leafIndices.length === 0 && totalSkills > 0) {
|
|
172
|
-
for (let i = 0; i < totalSkills; i++) allNode.leafIndices.push(i);
|
|
173
|
-
}
|
|
174
|
-
return wrapWithRoot(allNode);
|
|
175
|
-
}
|
|
176
126
|
function createTreeNode(id, name, depth, isLeaf, leafIndices = []) {
|
|
177
127
|
return { id, name, depth, children: [], leafIndices, isLeaf };
|
|
178
128
|
}
|
|
179
129
|
function wrapWithRoot(allNode) {
|
|
180
130
|
return { id: "", name: ".", depth: 0, children: [allNode], leafIndices: [...allNode.leafIndices], isLeaf: false };
|
|
181
131
|
}
|
|
182
|
-
function collapseIntermediateNodes(allNode) {
|
|
183
|
-
while (allNode.children.length === 1 && !allNode.children[0].isLeaf && allNode.children[0].children.length > 0) {
|
|
184
|
-
const singleChild = allNode.children[0];
|
|
185
|
-
for (const grandchild of singleChild.children) {
|
|
186
|
-
adjustDepth(grandchild, -1);
|
|
187
|
-
}
|
|
188
|
-
allNode.children = singleChild.children;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
function adjustDepth(node, delta) {
|
|
192
|
-
node.depth += delta;
|
|
193
|
-
for (const child of node.children) {
|
|
194
|
-
adjustDepth(child, delta);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
132
|
function flattenTree(root) {
|
|
198
133
|
const result = [];
|
|
199
134
|
function walk(node) {
|
|
@@ -263,15 +198,19 @@ async function interactiveTreeSelect(items, options) {
|
|
|
263
198
|
if (!stdin.isTTY || !stdout.isTTY) {
|
|
264
199
|
return defaultAll ? Array.from(selected) : null;
|
|
265
200
|
}
|
|
201
|
+
const useAltScreen = true;
|
|
266
202
|
const wasRaw = Boolean(stdin.isRaw);
|
|
267
203
|
stdin.setRawMode(true);
|
|
268
204
|
stdin.resume();
|
|
269
205
|
readline.emitKeypressEvents(stdin);
|
|
206
|
+
if (useAltScreen) {
|
|
207
|
+
stdout.write("\x1B[?1049h");
|
|
208
|
+
}
|
|
270
209
|
const renderer = createRenderer(title, subtitle, flatNodes, selected, () => cursor, formatNode);
|
|
271
210
|
writeToTerminal(stdout, renderer.renderContent());
|
|
272
211
|
return new Promise((resolve) => {
|
|
273
212
|
function cleanup(clear = false) {
|
|
274
|
-
if (clear) {
|
|
213
|
+
if (clear && !useAltScreen) {
|
|
275
214
|
const lineCount = renderer.getLineCount();
|
|
276
215
|
stdout.write(`\x1B[${lineCount}A`);
|
|
277
216
|
stdout.write("\x1B[0J");
|
|
@@ -280,6 +219,9 @@ async function interactiveTreeSelect(items, options) {
|
|
|
280
219
|
stdin.pause();
|
|
281
220
|
stdin.removeListener("keypress", onKeypress);
|
|
282
221
|
stdout.write("\x1B[?25h");
|
|
222
|
+
if (useAltScreen) {
|
|
223
|
+
stdout.write("\x1B[?1049l");
|
|
224
|
+
}
|
|
283
225
|
}
|
|
284
226
|
function rerender() {
|
|
285
227
|
clearAndRerender(stdout, renderer.getLineCount(), renderer.renderContent());
|
|
@@ -347,7 +289,7 @@ function formatTreeNode(node, selection, isCursor, options = {}) {
|
|
|
347
289
|
const { state, selectedCount } = selection;
|
|
348
290
|
const totalCount = node.leafIndices.length;
|
|
349
291
|
const indent = " ".repeat(node.depth - 1);
|
|
350
|
-
const
|
|
292
|
+
const checkbox2 = state === "all" ? chalk2.green("\u25CF") : state === "partial" ? chalk2.yellow("\u25D0") : chalk2.dim("\u25CB");
|
|
351
293
|
const name = isCursor ? chalk2.cyan.underline(node.name) : node.name;
|
|
352
294
|
const cursorMark = isCursor ? chalk2.cyan("\u203A ") : " ";
|
|
353
295
|
let count = "";
|
|
@@ -359,21 +301,13 @@ function formatTreeNode(node, selection, isCursor, options = {}) {
|
|
|
359
301
|
if (isCursor && totalCount > 0) {
|
|
360
302
|
hint = state === "all" ? chalk2.dim(" \u2190 Space to deselect") : chalk2.dim(" \u2190 Space to select");
|
|
361
303
|
}
|
|
362
|
-
return `${cursorMark}${indent}${
|
|
304
|
+
return `${cursorMark}${indent}${checkbox2} ${name}${count}${suffix}${hint}`;
|
|
363
305
|
}
|
|
364
306
|
function truncateDescription(value, maxLen) {
|
|
365
307
|
const trimmed = value.trim();
|
|
366
308
|
if (trimmed.length <= maxLen) return trimmed;
|
|
367
309
|
return `${trimmed.slice(0, maxLen - 3).trimEnd()}...`;
|
|
368
310
|
}
|
|
369
|
-
function getSkillDescriptionSuffix(skills, node, isCursor) {
|
|
370
|
-
if (!isCursor || !node.isLeaf || node.leafIndices.length !== 1) return "";
|
|
371
|
-
const skill = skills[node.leafIndices[0]];
|
|
372
|
-
if (!skill?.description) return "";
|
|
373
|
-
const description = truncateDescription(skill.description, 72);
|
|
374
|
-
if (!description) return "";
|
|
375
|
-
return chalk2.dim(` - ${description}`);
|
|
376
|
-
}
|
|
377
311
|
function getPlatformDisplay(platform) {
|
|
378
312
|
return PLATFORM_DISPLAY[platform] || platform;
|
|
379
313
|
}
|
|
@@ -386,37 +320,27 @@ async function promptSkillsInteractive(skills, options = {}) {
|
|
|
386
320
|
const skill = skills[i];
|
|
387
321
|
const installedOnTargets = skill.installedPlatforms?.filter((p) => targetPlatforms.includes(p)) || [];
|
|
388
322
|
const isFullyInstalled = hasInstalledCheck && installedOnTargets.length === targetPlatforms.length;
|
|
389
|
-
if (options.defaultAll !== false && !isFullyInstalled)
|
|
390
|
-
defaultSelected.add(i);
|
|
391
|
-
}
|
|
323
|
+
if (options.defaultAll !== false && !isFullyInstalled) defaultSelected.add(i);
|
|
392
324
|
}
|
|
393
|
-
const
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
if (isCursor && installedSuffix && selection.state !== "all") {
|
|
412
|
-
return formatted.replace("\u2190 Space to select", "\u2190 Space to reinstall");
|
|
413
|
-
}
|
|
414
|
-
return formatted;
|
|
415
|
-
},
|
|
416
|
-
defaultAll: false,
|
|
417
|
-
defaultSelected
|
|
325
|
+
const choices = skills.map((skill, i) => {
|
|
326
|
+
const base = skill.relPath === "." ? skill.suggestedSource : skill.relPath;
|
|
327
|
+
const desc = skill.description ? ` - ${truncateDescription(skill.description, 72)}` : "";
|
|
328
|
+
let installedSuffix = "";
|
|
329
|
+
if (skill.installedPlatforms?.length) {
|
|
330
|
+
installedSuffix = targetPlatforms.length > 0 && skill.installedPlatforms.length === targetPlatforms.length ? " [installed]" : ` [installed on ${skill.installedPlatforms.length}]`;
|
|
331
|
+
}
|
|
332
|
+
return {
|
|
333
|
+
name: `${base}${installedSuffix ? chalk2.dim(installedSuffix) : ""}${desc ? chalk2.dim(desc) : ""}`,
|
|
334
|
+
value: i,
|
|
335
|
+
checked: defaultSelected.has(i)
|
|
336
|
+
};
|
|
337
|
+
});
|
|
338
|
+
const selectedIndices = await checkbox({
|
|
339
|
+
message: "Select skills to install",
|
|
340
|
+
choices,
|
|
341
|
+
loop: false,
|
|
342
|
+
pageSize: Math.min(20, choices.length)
|
|
418
343
|
});
|
|
419
|
-
if (!selectedIndices) return null;
|
|
420
344
|
const selectedSkills = selectedIndices.map((i) => skills[i]);
|
|
421
345
|
const names = selectedSkills.map((s) => s.relPath === "." ? s.suggestedSource : s.relPath);
|
|
422
346
|
console.log(chalk2.green(`
|
|
@@ -454,17 +378,26 @@ async function promptSyncTargetsInteractive(choices) {
|
|
|
454
378
|
return selected;
|
|
455
379
|
}
|
|
456
380
|
async function promptSkillsTreeInteractive(skills, tree, options = {}) {
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
}
|
|
465
|
-
|
|
381
|
+
if (skills.length === 0) return null;
|
|
382
|
+
const defaultSelected = /* @__PURE__ */ new Set();
|
|
383
|
+
if (options.defaultAll !== false) {
|
|
384
|
+
for (let i = 0; i < skills.length; i++) defaultSelected.add(i);
|
|
385
|
+
}
|
|
386
|
+
const choices = skills.map((skill, i) => {
|
|
387
|
+
const label = skill.displayName || skill.relPath || skill.suggestedSource;
|
|
388
|
+
const desc = skill.description ? ` - ${truncateDescription(skill.description, 72)}` : "";
|
|
389
|
+
return {
|
|
390
|
+
name: `${label}${desc ? chalk2.dim(desc) : ""}`,
|
|
391
|
+
value: i,
|
|
392
|
+
checked: defaultSelected.has(i)
|
|
393
|
+
};
|
|
394
|
+
});
|
|
395
|
+
const selectedIndices = await checkbox({
|
|
396
|
+
message: "Select skills",
|
|
397
|
+
choices,
|
|
398
|
+
loop: false,
|
|
399
|
+
pageSize: Math.min(20, choices.length)
|
|
466
400
|
});
|
|
467
|
-
if (!selectedIndices) return null;
|
|
468
401
|
const selectedSkills = selectedIndices.map((i) => skills[i]);
|
|
469
402
|
const names = selectedSkills.map((s) => s.displayName || s.relPath || s.suggestedSource);
|
|
470
403
|
console.log(chalk2.green(`
|