skillops-cli 1.3.2 → 1.3.3
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/README.md +1 -1
- package/dist/cli.js +198 -47
- package/dist/index.d.ts +17 -6
- package/dist/index.js +198 -46
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SkillOps (`npx skillops-cli@latest`)
|
|
2
2
|
|
|
3
|
-
> **The Zero-API Framework & Benchmark-Verified Library for High-End AI Coding Skills & Context-Isolated Subagents (`v1.3.
|
|
3
|
+
> **The Zero-API Framework & Benchmark-Verified Library for High-End AI Coding Skills & Context-Isolated Subagents (`v1.3.3`)**
|
|
4
4
|
> *Explore, search, inspect, and install benchmark-verified AI Coding Skills and Context-Isolated Subagents in 10 seconds (`npx skillops-cli@latest quickstart`), scaffold and certify your own custom Skills & Subagents (`npx skillops-cli@latest create skill <name>`), enforce Startup Token Tax budgets (`npx skillops-cli@latest budget`), and transpile natively across the Top 20 AI coding agents & IDEs — 100% offline with zero API keys.*
|
|
5
5
|
|
|
6
6
|
[](./AGENTS.md)
|
package/dist/cli.js
CHANGED
|
@@ -10,7 +10,7 @@ import YAML6 from "yaml";
|
|
|
10
10
|
import fs from "fs";
|
|
11
11
|
import YAML from "yaml";
|
|
12
12
|
import { z } from "zod";
|
|
13
|
-
var SKILLOPS_VERSION = "1.3.
|
|
13
|
+
var SKILLOPS_VERSION = "1.3.3";
|
|
14
14
|
var SKILL_NAME_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
15
15
|
var SEMVER_REGEX = /^\d+\.\d+\.\d+$/;
|
|
16
16
|
var FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
|
|
@@ -5124,6 +5124,10 @@ function renderGlobalHelp(version, colorEnabled) {
|
|
|
5124
5124
|
cmd: "add [name...]",
|
|
5125
5125
|
desc: "Import Skills or Agents (interactive if no name given)"
|
|
5126
5126
|
},
|
|
5127
|
+
{
|
|
5128
|
+
cmd: "search <query>",
|
|
5129
|
+
desc: "Search Skills & Agents by keyword, stack, or domain"
|
|
5130
|
+
},
|
|
5127
5131
|
{
|
|
5128
5132
|
cmd: "list [query]",
|
|
5129
5133
|
desc: "List or filter available Skills & Agents in catalog"
|
|
@@ -5184,6 +5188,24 @@ function renderCommandHelp(spec, version, colorEnabled) {
|
|
|
5184
5188
|
}
|
|
5185
5189
|
|
|
5186
5190
|
// src/ui/prompt.ts
|
|
5191
|
+
function optionMatchesTab(opt, tab) {
|
|
5192
|
+
if (opt.kind === "agent") {
|
|
5193
|
+
return tab === "agent";
|
|
5194
|
+
}
|
|
5195
|
+
return tab === "skill";
|
|
5196
|
+
}
|
|
5197
|
+
function optionMatchesQuery(opt, rawQuery) {
|
|
5198
|
+
const q = rawQuery.trim().toLowerCase();
|
|
5199
|
+
if (!q) {
|
|
5200
|
+
return true;
|
|
5201
|
+
}
|
|
5202
|
+
return opt.label.toLowerCase().includes(q) || opt.value.toLowerCase().includes(q) || (opt.hint ?? "").toLowerCase().includes(q);
|
|
5203
|
+
}
|
|
5204
|
+
function getFilteredTabOptions(state, tab = state.activeTab) {
|
|
5205
|
+
return state.options.filter(
|
|
5206
|
+
(opt) => optionMatchesTab(opt, tab) && optionMatchesQuery(opt, state.searchQuery)
|
|
5207
|
+
);
|
|
5208
|
+
}
|
|
5187
5209
|
function createMultiSelectState(options) {
|
|
5188
5210
|
const initial = /* @__PURE__ */ new Set();
|
|
5189
5211
|
for (const opt of options) {
|
|
@@ -5191,10 +5213,14 @@ function createMultiSelectState(options) {
|
|
|
5191
5213
|
initial.add(opt.value);
|
|
5192
5214
|
}
|
|
5193
5215
|
}
|
|
5216
|
+
const hasSkills = options.some((opt) => optionMatchesTab(opt, "skill"));
|
|
5194
5217
|
return {
|
|
5195
5218
|
options,
|
|
5219
|
+
activeTab: hasSkills ? "skill" : "agent",
|
|
5196
5220
|
cursor: 0,
|
|
5197
5221
|
selected: initial,
|
|
5222
|
+
searchMode: false,
|
|
5223
|
+
searchQuery: "",
|
|
5198
5224
|
status: "active"
|
|
5199
5225
|
};
|
|
5200
5226
|
}
|
|
@@ -5202,8 +5228,21 @@ function applyMultiSelectKey(state, key) {
|
|
|
5202
5228
|
if (state.status !== "active" || state.options.length === 0) {
|
|
5203
5229
|
return state;
|
|
5204
5230
|
}
|
|
5205
|
-
|
|
5206
|
-
|
|
5231
|
+
if (key === "") {
|
|
5232
|
+
return {
|
|
5233
|
+
...state,
|
|
5234
|
+
status: "cancelled"
|
|
5235
|
+
};
|
|
5236
|
+
}
|
|
5237
|
+
if (key === "\x1B") {
|
|
5238
|
+
if (state.searchMode || state.searchQuery.length > 0) {
|
|
5239
|
+
return {
|
|
5240
|
+
...state,
|
|
5241
|
+
searchMode: false,
|
|
5242
|
+
searchQuery: "",
|
|
5243
|
+
cursor: 0
|
|
5244
|
+
};
|
|
5245
|
+
}
|
|
5207
5246
|
return {
|
|
5208
5247
|
...state,
|
|
5209
5248
|
status: "cancelled"
|
|
@@ -5212,17 +5251,34 @@ function applyMultiSelectKey(state, key) {
|
|
|
5212
5251
|
if (key === "\r" || key === "\n") {
|
|
5213
5252
|
return {
|
|
5214
5253
|
...state,
|
|
5254
|
+
searchMode: false,
|
|
5215
5255
|
status: "submitted"
|
|
5216
5256
|
};
|
|
5217
5257
|
}
|
|
5218
|
-
if (key === "\x1B[
|
|
5258
|
+
if (key === "\x1B[D" || key === "\x1BOD" || key === "\x1B[C" || key === "\x1BOC" || key === " " || !state.searchMode && (key === "h" || key === "H" || key === "l" || key === "L")) {
|
|
5259
|
+
const nextTab = state.activeTab === "skill" ? "agent" : "skill";
|
|
5260
|
+
return {
|
|
5261
|
+
...state,
|
|
5262
|
+
activeTab: nextTab,
|
|
5263
|
+
cursor: 0
|
|
5264
|
+
};
|
|
5265
|
+
}
|
|
5266
|
+
const visible = getFilteredTabOptions(state, state.activeTab);
|
|
5267
|
+
const count = visible.length;
|
|
5268
|
+
if (key === "\x1B[A" || key === "\x1BOA" || !state.searchMode && (key === "k" || key === "K")) {
|
|
5269
|
+
if (count === 0) {
|
|
5270
|
+
return state;
|
|
5271
|
+
}
|
|
5219
5272
|
const nextCursor = (state.cursor - 1 + count) % count;
|
|
5220
5273
|
return {
|
|
5221
5274
|
...state,
|
|
5222
5275
|
cursor: nextCursor
|
|
5223
5276
|
};
|
|
5224
5277
|
}
|
|
5225
|
-
if (key === "\x1B[B" || key === "\x1BOB" || key === "j" || key === "J") {
|
|
5278
|
+
if (key === "\x1B[B" || key === "\x1BOB" || !state.searchMode && (key === "j" || key === "J")) {
|
|
5279
|
+
if (count === 0) {
|
|
5280
|
+
return state;
|
|
5281
|
+
}
|
|
5226
5282
|
const nextCursor = (state.cursor + 1) % count;
|
|
5227
5283
|
return {
|
|
5228
5284
|
...state,
|
|
@@ -5230,7 +5286,7 @@ function applyMultiSelectKey(state, key) {
|
|
|
5230
5286
|
};
|
|
5231
5287
|
}
|
|
5232
5288
|
if (key === " ") {
|
|
5233
|
-
const currentOpt =
|
|
5289
|
+
const currentOpt = visible[state.cursor];
|
|
5234
5290
|
if (!currentOpt) {
|
|
5235
5291
|
return state;
|
|
5236
5292
|
}
|
|
@@ -5245,11 +5301,71 @@ function applyMultiSelectKey(state, key) {
|
|
|
5245
5301
|
selected: nextSelected
|
|
5246
5302
|
};
|
|
5247
5303
|
}
|
|
5304
|
+
if (state.searchMode) {
|
|
5305
|
+
if (key === "\x7F" || key === "\b") {
|
|
5306
|
+
if (state.searchQuery.length === 0) {
|
|
5307
|
+
return {
|
|
5308
|
+
...state,
|
|
5309
|
+
searchMode: false,
|
|
5310
|
+
cursor: 0
|
|
5311
|
+
};
|
|
5312
|
+
}
|
|
5313
|
+
const nextQuery = state.searchQuery.slice(0, -1);
|
|
5314
|
+
return {
|
|
5315
|
+
...state,
|
|
5316
|
+
searchQuery: nextQuery,
|
|
5317
|
+
cursor: 0
|
|
5318
|
+
};
|
|
5319
|
+
}
|
|
5320
|
+
if (/^[a-zA-Z0-9_.-]$/.test(key)) {
|
|
5321
|
+
const nextQuery = `${state.searchQuery}${key}`;
|
|
5322
|
+
const nextState = {
|
|
5323
|
+
...state,
|
|
5324
|
+
searchQuery: nextQuery,
|
|
5325
|
+
cursor: 0
|
|
5326
|
+
};
|
|
5327
|
+
const currentMatches = getFilteredTabOptions(nextState, state.activeTab);
|
|
5328
|
+
if (currentMatches.length === 0) {
|
|
5329
|
+
const otherTab = state.activeTab === "skill" ? "agent" : "skill";
|
|
5330
|
+
const otherMatches = getFilteredTabOptions(nextState, otherTab);
|
|
5331
|
+
if (otherMatches.length > 0) {
|
|
5332
|
+
return {
|
|
5333
|
+
...nextState,
|
|
5334
|
+
activeTab: otherTab
|
|
5335
|
+
};
|
|
5336
|
+
}
|
|
5337
|
+
}
|
|
5338
|
+
return nextState;
|
|
5339
|
+
}
|
|
5340
|
+
return state;
|
|
5341
|
+
}
|
|
5342
|
+
if (key === "/") {
|
|
5343
|
+
return {
|
|
5344
|
+
...state,
|
|
5345
|
+
searchMode: true,
|
|
5346
|
+
cursor: 0
|
|
5347
|
+
};
|
|
5348
|
+
}
|
|
5349
|
+
if (key === "q" || key === "Q") {
|
|
5350
|
+
return {
|
|
5351
|
+
...state,
|
|
5352
|
+
status: "cancelled"
|
|
5353
|
+
};
|
|
5354
|
+
}
|
|
5248
5355
|
if (key === "a" || key === "A") {
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5356
|
+
if (visible.length === 0) {
|
|
5357
|
+
return state;
|
|
5358
|
+
}
|
|
5359
|
+
const allTabSelected = visible.every(
|
|
5360
|
+
(opt) => state.selected.has(opt.value)
|
|
5361
|
+
);
|
|
5362
|
+
const nextSelected = new Set(state.selected);
|
|
5363
|
+
if (allTabSelected) {
|
|
5364
|
+
for (const opt of visible) {
|
|
5365
|
+
nextSelected.delete(opt.value);
|
|
5366
|
+
}
|
|
5367
|
+
} else {
|
|
5368
|
+
for (const opt of visible) {
|
|
5253
5369
|
nextSelected.add(opt.value);
|
|
5254
5370
|
}
|
|
5255
5371
|
}
|
|
@@ -5264,54 +5380,89 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5264
5380
|
const c = options.colorEnabled;
|
|
5265
5381
|
const bar = style.dim("\u2502", c);
|
|
5266
5382
|
const maxVisible = options.maxVisible ?? 10;
|
|
5267
|
-
const
|
|
5383
|
+
const totalSkills = state.options.filter(
|
|
5384
|
+
(o) => optionMatchesTab(o, "skill")
|
|
5385
|
+
).length;
|
|
5386
|
+
const totalAgents = state.options.filter(
|
|
5387
|
+
(o) => optionMatchesTab(o, "agent")
|
|
5388
|
+
).length;
|
|
5389
|
+
const filteredSkills = getFilteredTabOptions(state, "skill");
|
|
5390
|
+
const filteredAgents = getFilteredTabOptions(state, "agent");
|
|
5391
|
+
const visible = state.activeTab === "skill" ? filteredSkills : filteredAgents;
|
|
5392
|
+
const total = visible.length;
|
|
5268
5393
|
const header = `${style.bold(style.cyan(`\u25C6 ${title}`, c), c)}`;
|
|
5269
|
-
const instructions = `${bar} ${style.dim("(\u2191/\u2193 move \xB7 Space select \xB7
|
|
5394
|
+
const instructions = state.searchMode ? `${bar} ${style.dim("\u2191/\u2193 move \xB7 \u2190/\u2192 switch tab \xB7 Space select \xB7 Esc clear search \xB7 Enter import", c)}` : `${bar} ${style.dim("\u2191/\u2193 move \xB7 \u2190/\u2192 switch tab \xB7 Space select \xB7 / search \xB7 a all \xB7 Enter import", c)}`;
|
|
5270
5395
|
const lines = [header];
|
|
5271
5396
|
if (options.subtitle) {
|
|
5272
5397
|
lines.push(`${bar} ${options.subtitle}`);
|
|
5273
5398
|
}
|
|
5274
5399
|
lines.push(instructions, bar);
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
}
|
|
5280
|
-
const
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
26,
|
|
5286
|
-
state.options.reduce((m, o) => Math.max(m, visibleLength(o.label)), 14)
|
|
5400
|
+
const hasQuery = state.searchQuery.length > 0;
|
|
5401
|
+
const skillCountStr = hasQuery ? `${filteredSkills.length}/${totalSkills}` : `${totalSkills}`;
|
|
5402
|
+
const agentCountStr = hasQuery ? `${filteredAgents.length}/${totalAgents}` : `${totalAgents}`;
|
|
5403
|
+
const skillTabLabel = state.activeTab === "skill" ? style.bold(style.cyan(`[ \u25C6 Skills (${skillCountStr}) ]`, c), c) : style.dim(`\u25CB Skills (${skillCountStr})`, c);
|
|
5404
|
+
const agentTabLabel = state.activeTab === "agent" ? style.bold(style.magenta(`[ \u25C6 Agents (${agentCountStr}) ]`, c), c) : style.dim(`\u25CB Agents (${agentCountStr})`, c);
|
|
5405
|
+
const rawQuerySlice = state.searchQuery.length > 14 ? `\u2026${state.searchQuery.slice(-13)}` : state.searchQuery;
|
|
5406
|
+
const searchSuffix = state.searchMode || hasQuery ? ` ${style.yellow(`/ Filter: ${rawQuerySlice}${state.searchMode ? "\u2588" : ""}`, c)}` : ` ${style.dim("(/ search)", c)}`;
|
|
5407
|
+
lines.push(
|
|
5408
|
+
`${style.dim("\u251C\u2500", c)} ${skillTabLabel} ${agentTabLabel}${searchSuffix}`,
|
|
5409
|
+
bar
|
|
5287
5410
|
);
|
|
5288
|
-
|
|
5289
|
-
const
|
|
5290
|
-
if (!opt) continue;
|
|
5291
|
-
const isCurrent = i === state.cursor;
|
|
5292
|
-
const isChecked = state.selected.has(opt.value);
|
|
5293
|
-
const pointer = isCurrent ? style.cyan("\u276F", c) : " ";
|
|
5294
|
-
const checkbox = isChecked ? style.green("\u25FC", c) : style.dim("\u25FB", c);
|
|
5295
|
-
const kindTag = opt.kind === "skill" ? style.cyan("skill ", c) : opt.kind === "agent" ? style.magenta("agent ", c) : "";
|
|
5296
|
-
const labelRaw = opt.label.length > maxLabelCols ? `${opt.label.slice(0, maxLabelCols - 1)}\u2026` : opt.label;
|
|
5297
|
-
const labelPadded = padVisible(labelRaw, maxLabelCols + 1, "left");
|
|
5298
|
-
const styledLabel = isCurrent ? style.bold(labelPadded, c) : isChecked ? style.green(labelPadded, c) : labelPadded;
|
|
5299
|
-
const prefixWidth = 6 + (opt.kind === "skill" || opt.kind === "agent" ? 6 : 0) + maxLabelCols + 1;
|
|
5300
|
-
const maxHintCols = Math.max(10, 75 - prefixWidth);
|
|
5301
|
-
const rawHint = opt.hint ?? "";
|
|
5302
|
-
const shortHint = rawHint.length > maxHintCols ? `${rawHint.slice(0, maxHintCols - 1)}\u2026` : rawHint;
|
|
5303
|
-
const hintPart = shortHint ? ` ${style.dim(shortHint, c)}` : "";
|
|
5411
|
+
if (total === 0) {
|
|
5412
|
+
const tabName = state.activeTab === "skill" ? "Skills" : "Agents";
|
|
5304
5413
|
lines.push(
|
|
5305
|
-
`${bar} ${
|
|
5414
|
+
`${bar} ${style.dim(`No ${tabName} match "${state.searchQuery}". Press Esc to clear filter.`, c)}`
|
|
5306
5415
|
);
|
|
5307
|
-
}
|
|
5308
|
-
|
|
5309
|
-
|
|
5416
|
+
} else {
|
|
5417
|
+
let startIdx = 0;
|
|
5418
|
+
if (total > maxVisible) {
|
|
5419
|
+
const half = Math.floor(maxVisible / 2);
|
|
5420
|
+
startIdx = Math.max(0, Math.min(state.cursor - half, total - maxVisible));
|
|
5421
|
+
}
|
|
5422
|
+
const endIdx = Math.min(total, startIdx + maxVisible);
|
|
5423
|
+
if (startIdx > 0) {
|
|
5424
|
+
lines.push(`${bar} ${style.dim(`\u2191 ${startIdx} more above...`, c)}`);
|
|
5425
|
+
}
|
|
5426
|
+
const maxLabelCols = Math.min(
|
|
5427
|
+
26,
|
|
5428
|
+
visible.reduce((m, o) => Math.max(m, visibleLength(o.label)), 14)
|
|
5429
|
+
);
|
|
5430
|
+
for (let i = startIdx; i < endIdx; i++) {
|
|
5431
|
+
const opt = visible[i];
|
|
5432
|
+
if (!opt) continue;
|
|
5433
|
+
const isCurrent = i === state.cursor;
|
|
5434
|
+
const isChecked = state.selected.has(opt.value);
|
|
5435
|
+
const pointer = isCurrent ? style.cyan("\u276F", c) : " ";
|
|
5436
|
+
const checkbox = isChecked ? style.green("\u25C9", c) : style.dim("\u25EF", c);
|
|
5437
|
+
const labelRaw = opt.label.length > maxLabelCols ? `${opt.label.slice(0, maxLabelCols - 1)}\u2026` : opt.label;
|
|
5438
|
+
const labelPadded = padVisible(labelRaw, maxLabelCols + 1, "left");
|
|
5439
|
+
const styledLabel = isCurrent ? style.bold(labelPadded, c) : isChecked ? style.green(labelPadded, c) : labelPadded;
|
|
5440
|
+
const prefixWidth = 7 + maxLabelCols + 1;
|
|
5441
|
+
const maxHintCols = Math.max(10, 76 - prefixWidth);
|
|
5442
|
+
const rawHint = opt.hint ?? "";
|
|
5443
|
+
const shortHint = rawHint.length > maxHintCols ? `${rawHint.slice(0, maxHintCols - 1)}\u2026` : rawHint;
|
|
5444
|
+
const hintPart = shortHint ? ` ${style.dim(shortHint, c)}` : "";
|
|
5445
|
+
lines.push(`${bar} ${pointer} ${checkbox} ${styledLabel}${hintPart}`);
|
|
5446
|
+
}
|
|
5447
|
+
if (endIdx < total) {
|
|
5448
|
+
lines.push(
|
|
5449
|
+
`${bar} ${style.dim(`\u2193 ${total - endIdx} more below...`, c)}`
|
|
5450
|
+
);
|
|
5451
|
+
}
|
|
5310
5452
|
}
|
|
5311
5453
|
lines.push(bar);
|
|
5312
|
-
const
|
|
5454
|
+
const selectedSkillsCount = state.options.filter(
|
|
5455
|
+
(o) => optionMatchesTab(o, "skill") && state.selected.has(o.value)
|
|
5456
|
+
).length;
|
|
5457
|
+
const selectedAgentsCount = state.options.filter(
|
|
5458
|
+
(o) => optionMatchesTab(o, "agent") && state.selected.has(o.value)
|
|
5459
|
+
).length;
|
|
5460
|
+
const summaryText = `${state.selected.size} selected (${selectedSkillsCount} Skills, ${selectedAgentsCount} Agents)`;
|
|
5461
|
+
const rawTarget = options.targetHint ?? "";
|
|
5462
|
+
const shortTarget = rawTarget.length > 18 ? `${rawTarget.slice(0, 17)}\u2026` : rawTarget;
|
|
5463
|
+
const targetSuffix = shortTarget ? ` \xB7 IDE: ${shortTarget}` : "";
|
|
5313
5464
|
lines.push(
|
|
5314
|
-
`${style.dim("\u2570\u2500", c)} ${style.bold(
|
|
5465
|
+
`${style.dim("\u2570\u2500", c)} ${style.bold(summaryText, c)}${style.dim(`${targetSuffix} \u2014 Enter to import`, c)}`
|
|
5315
5466
|
);
|
|
5316
5467
|
return lines.join("\n");
|
|
5317
5468
|
}
|
|
@@ -6930,7 +7081,7 @@ async function runCliInteractive(argv) {
|
|
|
6930
7081
|
"SkillOps \u2014 Select Skills & Agents to Import",
|
|
6931
7082
|
options,
|
|
6932
7083
|
{
|
|
6933
|
-
targetHint:
|
|
7084
|
+
targetHint: targets.join(", ")
|
|
6934
7085
|
}
|
|
6935
7086
|
);
|
|
6936
7087
|
if (!selected || selected.length === 0) {
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { z } from 'zod';
|
|
|
8
8
|
* telemetry and Multi-Runtime Transpilation lockfiles.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
declare const SKILLOPS_VERSION = "1.3.
|
|
11
|
+
declare const SKILLOPS_VERSION = "1.3.3";
|
|
12
12
|
/**
|
|
13
13
|
* Count whitespace-delimited words in text.
|
|
14
14
|
*/
|
|
@@ -2176,9 +2176,13 @@ declare function renderCommandHelp(spec: CommandHelpSpec, version: string, color
|
|
|
2176
2176
|
/**
|
|
2177
2177
|
* Zero-dependency interactive terminal multi-select prompt (`src/ui/prompt.ts`).
|
|
2178
2178
|
*
|
|
2179
|
-
* Supports
|
|
2180
|
-
*
|
|
2179
|
+
* Supports:
|
|
2180
|
+
* - Horizontal tabs (`←`/`→` or `Tab`) separating `Skills` and `Agents`
|
|
2181
|
+
* - Vertical navigation (`↑`/`↓` or `j`/`k`)
|
|
2182
|
+
* - Real-time keyword filtering (`/` to search, `Backspace` to edit, `Esc` to clear)
|
|
2183
|
+
* - `Space` to toggle selection across tabs, `a` to toggle all in current tab, `Enter` to confirm
|
|
2181
2184
|
*/
|
|
2185
|
+
type MultiSelectTab = "skill" | "agent";
|
|
2182
2186
|
interface MultiSelectOption {
|
|
2183
2187
|
readonly value: string;
|
|
2184
2188
|
readonly label: string;
|
|
@@ -2188,8 +2192,11 @@ interface MultiSelectOption {
|
|
|
2188
2192
|
}
|
|
2189
2193
|
interface MultiSelectState {
|
|
2190
2194
|
readonly options: readonly MultiSelectOption[];
|
|
2195
|
+
readonly activeTab: MultiSelectTab;
|
|
2191
2196
|
readonly cursor: number;
|
|
2192
2197
|
readonly selected: ReadonlySet<string>;
|
|
2198
|
+
readonly searchMode: boolean;
|
|
2199
|
+
readonly searchQuery: string;
|
|
2193
2200
|
readonly status: "active" | "submitted" | "cancelled";
|
|
2194
2201
|
}
|
|
2195
2202
|
interface RenderMultiSelectOptions {
|
|
@@ -2198,16 +2205,20 @@ interface RenderMultiSelectOptions {
|
|
|
2198
2205
|
readonly maxVisible?: number;
|
|
2199
2206
|
readonly colorEnabled?: boolean;
|
|
2200
2207
|
}
|
|
2208
|
+
/**
|
|
2209
|
+
* Return the filtered options for a given tab (`skill` or `agent`) and active `searchQuery`.
|
|
2210
|
+
*/
|
|
2211
|
+
declare function getFilteredTabOptions(state: MultiSelectState, tab?: MultiSelectTab): MultiSelectOption[];
|
|
2201
2212
|
/**
|
|
2202
2213
|
* Initialize a deterministic multi-select state from a list of options.
|
|
2203
2214
|
*/
|
|
2204
2215
|
declare function createMultiSelectState(options: readonly MultiSelectOption[]): MultiSelectState;
|
|
2205
2216
|
/**
|
|
2206
|
-
* Pure state reducer for keyboard input in the multi-select TUI.
|
|
2217
|
+
* Pure state reducer for keyboard input in the tabbed + searchable multi-select TUI.
|
|
2207
2218
|
*/
|
|
2208
2219
|
declare function applyMultiSelectKey(state: MultiSelectState, key: string): MultiSelectState;
|
|
2209
2220
|
/**
|
|
2210
|
-
* Render a single frame of the multi-select tree prompt (guaranteed <= 78 columns).
|
|
2221
|
+
* Render a single frame of the tabbed + searchable multi-select tree prompt (guaranteed <= 78 columns).
|
|
2211
2222
|
*/
|
|
2212
2223
|
declare function renderMultiSelectFrame(title: string, state: MultiSelectState, options?: RenderMultiSelectOptions): string;
|
|
2213
2224
|
/**
|
|
@@ -2335,4 +2346,4 @@ declare const DEFAULT_VALID_COMMANDS: readonly string[];
|
|
|
2335
2346
|
*/
|
|
2336
2347
|
declare function suggestCommand(unknownCommand: string, validCommands?: readonly string[]): string | null;
|
|
2337
2348
|
|
|
2338
|
-
export { ALL_RUNTIME_TARGETS, type AddOptions, type AnalyzeTokenEconomyOptions, type AuditCatalogOptions, type BadgeType, type BenchmarkArm, BenchmarkArmSchema, type BenchmarkDelta, BenchmarkDeltaSchema, type BoxOptions, COMMAND_HELP_SPECS, CORE_RUNTIME_TARGETS, type CatalogEvalSummary, CatalogEvalSummarySchema, type CatalogItemInfo, type CatalogSearchMatch, type CatalogSearchReport, type CatalogTokenBudgetSummary, type CatalogTrack, CatalogTrackSchema, type CleanOptions, type CollisionPair, CollisionPairSchema, type CollisionReport, CollisionReportSchema, type CollisionSeverity, CollisionSeveritySchema, type ColorOverrideOptions, type CommandHelpSpec, type CommandOptionSpec, DEFAULT_VALID_COMMANDS, type DiagnoseRepositoryOptions, type DoctorCheckItem, type DoctorReport, type EvalAssertion, EvalAssertionSchema, type EvalCase, EvalCaseSchema, ExitCode, type ExitCodeValue, type HarnessCategory, type HarnessInspectionEntry, type HarnessInspectionReport, type HarnessSkillFormat, type JsonRpcRequest, type JsonRpcResponse, type LoadedSkillOpsConfigResult, type LockfileArtifactDiagnostic, type McpConfigAction, type McpServerContext, type McpSetupOptions, type McpSetupReport, type MultiSelectOption, type MultiSelectState, type NextStepHint, type ParseSkillOptions, type ParsedSkillDirectory, type ParsedSubagentFile, type QuickstartOptions, type QuickstartReport, RUNTIME_HARNESS_SPECS, type RemoveOptions, type RenderMultiSelectOptions, RepoFingerprinter, type RepoProfile, RepoProfileSchema, type RouteOptions, type RoutedBundle, RoutedBundleSchema, type RoutingSignals, RoutingSignalsSchema, type RuntimeHarnessSpec, type RuntimeTarget, RuntimeTargetSchema, SKILLOPS_VERSION, type ScaffoldOptions, type ScaffoldResult, type ScoredSkill, ScoredSkillSchema, type ScriptEntrypoint, ScriptEntrypointSchema, type SkillBenchmark, SkillBenchmarkSchema, type SkillEntrypoints, SkillEntrypointsSchema, type SkillEvalSuite, SkillEvalSuiteSchema, type SkillManifest, type SkillManifestInput, SkillManifestSchema, type SkillOpsConfig, SkillOpsConfigSchema, type SkillOpsDetectedStackConfig, SkillOpsDetectedStackConfigSchema, type SkillOpsTokenEconomyConfig, SkillOpsTokenEconomyConfigSchema, type SkillTokenBudgetAudit, type SkippedSkill, SkippedSkillSchema, type SubagentManifest, SubagentManifestSchema, type SubagentTokenBudgetAudit, type SyncLockEntry, SyncLockEntrySchema, type SyncLockfile, SyncLockfileSchema, type SyncOptions, type SyncReport, SyncReportSchema, type SyncedArtifact, SyncedArtifactSchema, type TableOptions, type TokenBarOptions, type TokenEconomyReport, TokenEconomyReportSchema, type TokenFileCategory, TokenFileCategorySchema, type TokenFileEntry, TokenFileEntrySchema, type TokenWasteHotspot, TokenWasteHotspotSchema, addSkillOrSubagent, analyzeRepoTokenEconomy, applyMultiSelectKey, auditCatalog, auditCatalogTokenBudgets, auditSkillTokenBudget, auditSubagentTokenBudget, classifyCollisionSeverity, cleanSyncedArtifacts, compileSkillBundle, computeCollisionMatrix, computeFeatureCosine, computeIdfWeights, computeSha256, countWords, createCollisionPair, createCollisionReport, createMultiSelectState, createSkillManifest, createSubagentManifest, detectInstalledHarnesses, diagnoseRepository, discoverSkillDirectories, discoverSubagentFiles, estimateTokenCount, evaluateCatalog, evaluateSkillDirectory, extractSkillFeatures, findCommandHelpSpec, fingerprintRepository, formatBadge, formatCatalogItemInfo, formatCatalogSearchReport, formatDoctorReport, formatEvalSummary, formatHarnessInspectionReport, formatMcpSetupReport, formatQuickstartReport, formatRoutedBundle, formatScaffoldReport, formatSyncReport, formatTokenEconomyReport, handleMcpJsonRpcRequest, inspectCatalogItem, inspectHarnesses, isColorEnabled, levenshteinDistance, loadSkillOpsConfig, normalizePackageName, padVisible, parseSkillDirectory, parseSkillMdFile, parseSubagentFile, parseSubagentMdFile, removeSkillOrSubagent, renderAiUsageGuide, renderBox, renderCodexAgentsIndex, renderCommandHelp, renderGlobalHelp, renderHeaderBanner, renderMultiSelectFrame, renderNextSteps, renderProgressBar, renderSectionHeader, renderStep, renderTable, renderTokenBar, resolveRuntimeTargets, routeRepository, runMultiSelectPrompt, runQuickstart, scaffoldFrameworkItem, scoreSkillAgainstProfile, searchCatalog, setupMcpForHarnesses, splitFrontmatter, startMcpStdioServer, stripAnsi, stripCodexAgentsBlock, stripNegativeTriggerClauses, style, suggestCommand, syncRepository, tokenizeRoutingText, visibleLength };
|
|
2349
|
+
export { ALL_RUNTIME_TARGETS, type AddOptions, type AnalyzeTokenEconomyOptions, type AuditCatalogOptions, type BadgeType, type BenchmarkArm, BenchmarkArmSchema, type BenchmarkDelta, BenchmarkDeltaSchema, type BoxOptions, COMMAND_HELP_SPECS, CORE_RUNTIME_TARGETS, type CatalogEvalSummary, CatalogEvalSummarySchema, type CatalogItemInfo, type CatalogSearchMatch, type CatalogSearchReport, type CatalogTokenBudgetSummary, type CatalogTrack, CatalogTrackSchema, type CleanOptions, type CollisionPair, CollisionPairSchema, type CollisionReport, CollisionReportSchema, type CollisionSeverity, CollisionSeveritySchema, type ColorOverrideOptions, type CommandHelpSpec, type CommandOptionSpec, DEFAULT_VALID_COMMANDS, type DiagnoseRepositoryOptions, type DoctorCheckItem, type DoctorReport, type EvalAssertion, EvalAssertionSchema, type EvalCase, EvalCaseSchema, ExitCode, type ExitCodeValue, type HarnessCategory, type HarnessInspectionEntry, type HarnessInspectionReport, type HarnessSkillFormat, type JsonRpcRequest, type JsonRpcResponse, type LoadedSkillOpsConfigResult, type LockfileArtifactDiagnostic, type McpConfigAction, type McpServerContext, type McpSetupOptions, type McpSetupReport, type MultiSelectOption, type MultiSelectState, type MultiSelectTab, type NextStepHint, type ParseSkillOptions, type ParsedSkillDirectory, type ParsedSubagentFile, type QuickstartOptions, type QuickstartReport, RUNTIME_HARNESS_SPECS, type RemoveOptions, type RenderMultiSelectOptions, RepoFingerprinter, type RepoProfile, RepoProfileSchema, type RouteOptions, type RoutedBundle, RoutedBundleSchema, type RoutingSignals, RoutingSignalsSchema, type RuntimeHarnessSpec, type RuntimeTarget, RuntimeTargetSchema, SKILLOPS_VERSION, type ScaffoldOptions, type ScaffoldResult, type ScoredSkill, ScoredSkillSchema, type ScriptEntrypoint, ScriptEntrypointSchema, type SkillBenchmark, SkillBenchmarkSchema, type SkillEntrypoints, SkillEntrypointsSchema, type SkillEvalSuite, SkillEvalSuiteSchema, type SkillManifest, type SkillManifestInput, SkillManifestSchema, type SkillOpsConfig, SkillOpsConfigSchema, type SkillOpsDetectedStackConfig, SkillOpsDetectedStackConfigSchema, type SkillOpsTokenEconomyConfig, SkillOpsTokenEconomyConfigSchema, type SkillTokenBudgetAudit, type SkippedSkill, SkippedSkillSchema, type SubagentManifest, SubagentManifestSchema, type SubagentTokenBudgetAudit, type SyncLockEntry, SyncLockEntrySchema, type SyncLockfile, SyncLockfileSchema, type SyncOptions, type SyncReport, SyncReportSchema, type SyncedArtifact, SyncedArtifactSchema, type TableOptions, type TokenBarOptions, type TokenEconomyReport, TokenEconomyReportSchema, type TokenFileCategory, TokenFileCategorySchema, type TokenFileEntry, TokenFileEntrySchema, type TokenWasteHotspot, TokenWasteHotspotSchema, addSkillOrSubagent, analyzeRepoTokenEconomy, applyMultiSelectKey, auditCatalog, auditCatalogTokenBudgets, auditSkillTokenBudget, auditSubagentTokenBudget, classifyCollisionSeverity, cleanSyncedArtifacts, compileSkillBundle, computeCollisionMatrix, computeFeatureCosine, computeIdfWeights, computeSha256, countWords, createCollisionPair, createCollisionReport, createMultiSelectState, createSkillManifest, createSubagentManifest, detectInstalledHarnesses, diagnoseRepository, discoverSkillDirectories, discoverSubagentFiles, estimateTokenCount, evaluateCatalog, evaluateSkillDirectory, extractSkillFeatures, findCommandHelpSpec, fingerprintRepository, formatBadge, formatCatalogItemInfo, formatCatalogSearchReport, formatDoctorReport, formatEvalSummary, formatHarnessInspectionReport, formatMcpSetupReport, formatQuickstartReport, formatRoutedBundle, formatScaffoldReport, formatSyncReport, formatTokenEconomyReport, getFilteredTabOptions, handleMcpJsonRpcRequest, inspectCatalogItem, inspectHarnesses, isColorEnabled, levenshteinDistance, loadSkillOpsConfig, normalizePackageName, padVisible, parseSkillDirectory, parseSkillMdFile, parseSubagentFile, parseSubagentMdFile, removeSkillOrSubagent, renderAiUsageGuide, renderBox, renderCodexAgentsIndex, renderCommandHelp, renderGlobalHelp, renderHeaderBanner, renderMultiSelectFrame, renderNextSteps, renderProgressBar, renderSectionHeader, renderStep, renderTable, renderTokenBar, resolveRuntimeTargets, routeRepository, runMultiSelectPrompt, runQuickstart, scaffoldFrameworkItem, scoreSkillAgainstProfile, searchCatalog, setupMcpForHarnesses, splitFrontmatter, startMcpStdioServer, stripAnsi, stripCodexAgentsBlock, stripNegativeTriggerClauses, style, suggestCommand, syncRepository, tokenizeRoutingText, visibleLength };
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import YAML from "yaml";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
-
var SKILLOPS_VERSION = "1.3.
|
|
5
|
+
var SKILLOPS_VERSION = "1.3.3";
|
|
6
6
|
var SKILL_NAME_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
7
7
|
var SEMVER_REGEX = /^\d+\.\d+\.\d+$/;
|
|
8
8
|
var FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
|
|
@@ -5142,6 +5142,10 @@ function renderGlobalHelp(version, colorEnabled) {
|
|
|
5142
5142
|
cmd: "add [name...]",
|
|
5143
5143
|
desc: "Import Skills or Agents (interactive if no name given)"
|
|
5144
5144
|
},
|
|
5145
|
+
{
|
|
5146
|
+
cmd: "search <query>",
|
|
5147
|
+
desc: "Search Skills & Agents by keyword, stack, or domain"
|
|
5148
|
+
},
|
|
5145
5149
|
{
|
|
5146
5150
|
cmd: "list [query]",
|
|
5147
5151
|
desc: "List or filter available Skills & Agents in catalog"
|
|
@@ -5202,6 +5206,24 @@ function renderCommandHelp(spec, version, colorEnabled) {
|
|
|
5202
5206
|
}
|
|
5203
5207
|
|
|
5204
5208
|
// src/ui/prompt.ts
|
|
5209
|
+
function optionMatchesTab(opt, tab) {
|
|
5210
|
+
if (opt.kind === "agent") {
|
|
5211
|
+
return tab === "agent";
|
|
5212
|
+
}
|
|
5213
|
+
return tab === "skill";
|
|
5214
|
+
}
|
|
5215
|
+
function optionMatchesQuery(opt, rawQuery) {
|
|
5216
|
+
const q = rawQuery.trim().toLowerCase();
|
|
5217
|
+
if (!q) {
|
|
5218
|
+
return true;
|
|
5219
|
+
}
|
|
5220
|
+
return opt.label.toLowerCase().includes(q) || opt.value.toLowerCase().includes(q) || (opt.hint ?? "").toLowerCase().includes(q);
|
|
5221
|
+
}
|
|
5222
|
+
function getFilteredTabOptions(state, tab = state.activeTab) {
|
|
5223
|
+
return state.options.filter(
|
|
5224
|
+
(opt) => optionMatchesTab(opt, tab) && optionMatchesQuery(opt, state.searchQuery)
|
|
5225
|
+
);
|
|
5226
|
+
}
|
|
5205
5227
|
function createMultiSelectState(options) {
|
|
5206
5228
|
const initial = /* @__PURE__ */ new Set();
|
|
5207
5229
|
for (const opt of options) {
|
|
@@ -5209,10 +5231,14 @@ function createMultiSelectState(options) {
|
|
|
5209
5231
|
initial.add(opt.value);
|
|
5210
5232
|
}
|
|
5211
5233
|
}
|
|
5234
|
+
const hasSkills = options.some((opt) => optionMatchesTab(opt, "skill"));
|
|
5212
5235
|
return {
|
|
5213
5236
|
options,
|
|
5237
|
+
activeTab: hasSkills ? "skill" : "agent",
|
|
5214
5238
|
cursor: 0,
|
|
5215
5239
|
selected: initial,
|
|
5240
|
+
searchMode: false,
|
|
5241
|
+
searchQuery: "",
|
|
5216
5242
|
status: "active"
|
|
5217
5243
|
};
|
|
5218
5244
|
}
|
|
@@ -5220,8 +5246,21 @@ function applyMultiSelectKey(state, key) {
|
|
|
5220
5246
|
if (state.status !== "active" || state.options.length === 0) {
|
|
5221
5247
|
return state;
|
|
5222
5248
|
}
|
|
5223
|
-
|
|
5224
|
-
|
|
5249
|
+
if (key === "") {
|
|
5250
|
+
return {
|
|
5251
|
+
...state,
|
|
5252
|
+
status: "cancelled"
|
|
5253
|
+
};
|
|
5254
|
+
}
|
|
5255
|
+
if (key === "\x1B") {
|
|
5256
|
+
if (state.searchMode || state.searchQuery.length > 0) {
|
|
5257
|
+
return {
|
|
5258
|
+
...state,
|
|
5259
|
+
searchMode: false,
|
|
5260
|
+
searchQuery: "",
|
|
5261
|
+
cursor: 0
|
|
5262
|
+
};
|
|
5263
|
+
}
|
|
5225
5264
|
return {
|
|
5226
5265
|
...state,
|
|
5227
5266
|
status: "cancelled"
|
|
@@ -5230,17 +5269,34 @@ function applyMultiSelectKey(state, key) {
|
|
|
5230
5269
|
if (key === "\r" || key === "\n") {
|
|
5231
5270
|
return {
|
|
5232
5271
|
...state,
|
|
5272
|
+
searchMode: false,
|
|
5233
5273
|
status: "submitted"
|
|
5234
5274
|
};
|
|
5235
5275
|
}
|
|
5236
|
-
if (key === "\x1B[
|
|
5276
|
+
if (key === "\x1B[D" || key === "\x1BOD" || key === "\x1B[C" || key === "\x1BOC" || key === " " || !state.searchMode && (key === "h" || key === "H" || key === "l" || key === "L")) {
|
|
5277
|
+
const nextTab = state.activeTab === "skill" ? "agent" : "skill";
|
|
5278
|
+
return {
|
|
5279
|
+
...state,
|
|
5280
|
+
activeTab: nextTab,
|
|
5281
|
+
cursor: 0
|
|
5282
|
+
};
|
|
5283
|
+
}
|
|
5284
|
+
const visible = getFilteredTabOptions(state, state.activeTab);
|
|
5285
|
+
const count = visible.length;
|
|
5286
|
+
if (key === "\x1B[A" || key === "\x1BOA" || !state.searchMode && (key === "k" || key === "K")) {
|
|
5287
|
+
if (count === 0) {
|
|
5288
|
+
return state;
|
|
5289
|
+
}
|
|
5237
5290
|
const nextCursor = (state.cursor - 1 + count) % count;
|
|
5238
5291
|
return {
|
|
5239
5292
|
...state,
|
|
5240
5293
|
cursor: nextCursor
|
|
5241
5294
|
};
|
|
5242
5295
|
}
|
|
5243
|
-
if (key === "\x1B[B" || key === "\x1BOB" || key === "j" || key === "J") {
|
|
5296
|
+
if (key === "\x1B[B" || key === "\x1BOB" || !state.searchMode && (key === "j" || key === "J")) {
|
|
5297
|
+
if (count === 0) {
|
|
5298
|
+
return state;
|
|
5299
|
+
}
|
|
5244
5300
|
const nextCursor = (state.cursor + 1) % count;
|
|
5245
5301
|
return {
|
|
5246
5302
|
...state,
|
|
@@ -5248,7 +5304,7 @@ function applyMultiSelectKey(state, key) {
|
|
|
5248
5304
|
};
|
|
5249
5305
|
}
|
|
5250
5306
|
if (key === " ") {
|
|
5251
|
-
const currentOpt =
|
|
5307
|
+
const currentOpt = visible[state.cursor];
|
|
5252
5308
|
if (!currentOpt) {
|
|
5253
5309
|
return state;
|
|
5254
5310
|
}
|
|
@@ -5263,11 +5319,71 @@ function applyMultiSelectKey(state, key) {
|
|
|
5263
5319
|
selected: nextSelected
|
|
5264
5320
|
};
|
|
5265
5321
|
}
|
|
5322
|
+
if (state.searchMode) {
|
|
5323
|
+
if (key === "\x7F" || key === "\b") {
|
|
5324
|
+
if (state.searchQuery.length === 0) {
|
|
5325
|
+
return {
|
|
5326
|
+
...state,
|
|
5327
|
+
searchMode: false,
|
|
5328
|
+
cursor: 0
|
|
5329
|
+
};
|
|
5330
|
+
}
|
|
5331
|
+
const nextQuery = state.searchQuery.slice(0, -1);
|
|
5332
|
+
return {
|
|
5333
|
+
...state,
|
|
5334
|
+
searchQuery: nextQuery,
|
|
5335
|
+
cursor: 0
|
|
5336
|
+
};
|
|
5337
|
+
}
|
|
5338
|
+
if (/^[a-zA-Z0-9_.-]$/.test(key)) {
|
|
5339
|
+
const nextQuery = `${state.searchQuery}${key}`;
|
|
5340
|
+
const nextState = {
|
|
5341
|
+
...state,
|
|
5342
|
+
searchQuery: nextQuery,
|
|
5343
|
+
cursor: 0
|
|
5344
|
+
};
|
|
5345
|
+
const currentMatches = getFilteredTabOptions(nextState, state.activeTab);
|
|
5346
|
+
if (currentMatches.length === 0) {
|
|
5347
|
+
const otherTab = state.activeTab === "skill" ? "agent" : "skill";
|
|
5348
|
+
const otherMatches = getFilteredTabOptions(nextState, otherTab);
|
|
5349
|
+
if (otherMatches.length > 0) {
|
|
5350
|
+
return {
|
|
5351
|
+
...nextState,
|
|
5352
|
+
activeTab: otherTab
|
|
5353
|
+
};
|
|
5354
|
+
}
|
|
5355
|
+
}
|
|
5356
|
+
return nextState;
|
|
5357
|
+
}
|
|
5358
|
+
return state;
|
|
5359
|
+
}
|
|
5360
|
+
if (key === "/") {
|
|
5361
|
+
return {
|
|
5362
|
+
...state,
|
|
5363
|
+
searchMode: true,
|
|
5364
|
+
cursor: 0
|
|
5365
|
+
};
|
|
5366
|
+
}
|
|
5367
|
+
if (key === "q" || key === "Q") {
|
|
5368
|
+
return {
|
|
5369
|
+
...state,
|
|
5370
|
+
status: "cancelled"
|
|
5371
|
+
};
|
|
5372
|
+
}
|
|
5266
5373
|
if (key === "a" || key === "A") {
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5374
|
+
if (visible.length === 0) {
|
|
5375
|
+
return state;
|
|
5376
|
+
}
|
|
5377
|
+
const allTabSelected = visible.every(
|
|
5378
|
+
(opt) => state.selected.has(opt.value)
|
|
5379
|
+
);
|
|
5380
|
+
const nextSelected = new Set(state.selected);
|
|
5381
|
+
if (allTabSelected) {
|
|
5382
|
+
for (const opt of visible) {
|
|
5383
|
+
nextSelected.delete(opt.value);
|
|
5384
|
+
}
|
|
5385
|
+
} else {
|
|
5386
|
+
for (const opt of visible) {
|
|
5271
5387
|
nextSelected.add(opt.value);
|
|
5272
5388
|
}
|
|
5273
5389
|
}
|
|
@@ -5282,54 +5398,89 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5282
5398
|
const c = options.colorEnabled;
|
|
5283
5399
|
const bar = style.dim("\u2502", c);
|
|
5284
5400
|
const maxVisible = options.maxVisible ?? 10;
|
|
5285
|
-
const
|
|
5401
|
+
const totalSkills = state.options.filter(
|
|
5402
|
+
(o) => optionMatchesTab(o, "skill")
|
|
5403
|
+
).length;
|
|
5404
|
+
const totalAgents = state.options.filter(
|
|
5405
|
+
(o) => optionMatchesTab(o, "agent")
|
|
5406
|
+
).length;
|
|
5407
|
+
const filteredSkills = getFilteredTabOptions(state, "skill");
|
|
5408
|
+
const filteredAgents = getFilteredTabOptions(state, "agent");
|
|
5409
|
+
const visible = state.activeTab === "skill" ? filteredSkills : filteredAgents;
|
|
5410
|
+
const total = visible.length;
|
|
5286
5411
|
const header = `${style.bold(style.cyan(`\u25C6 ${title}`, c), c)}`;
|
|
5287
|
-
const instructions = `${bar} ${style.dim("(\u2191/\u2193 move \xB7 Space select \xB7
|
|
5412
|
+
const instructions = state.searchMode ? `${bar} ${style.dim("\u2191/\u2193 move \xB7 \u2190/\u2192 switch tab \xB7 Space select \xB7 Esc clear search \xB7 Enter import", c)}` : `${bar} ${style.dim("\u2191/\u2193 move \xB7 \u2190/\u2192 switch tab \xB7 Space select \xB7 / search \xB7 a all \xB7 Enter import", c)}`;
|
|
5288
5413
|
const lines = [header];
|
|
5289
5414
|
if (options.subtitle) {
|
|
5290
5415
|
lines.push(`${bar} ${options.subtitle}`);
|
|
5291
5416
|
}
|
|
5292
5417
|
lines.push(instructions, bar);
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
|
|
5297
|
-
}
|
|
5298
|
-
const
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
26,
|
|
5304
|
-
state.options.reduce((m, o) => Math.max(m, visibleLength(o.label)), 14)
|
|
5418
|
+
const hasQuery = state.searchQuery.length > 0;
|
|
5419
|
+
const skillCountStr = hasQuery ? `${filteredSkills.length}/${totalSkills}` : `${totalSkills}`;
|
|
5420
|
+
const agentCountStr = hasQuery ? `${filteredAgents.length}/${totalAgents}` : `${totalAgents}`;
|
|
5421
|
+
const skillTabLabel = state.activeTab === "skill" ? style.bold(style.cyan(`[ \u25C6 Skills (${skillCountStr}) ]`, c), c) : style.dim(`\u25CB Skills (${skillCountStr})`, c);
|
|
5422
|
+
const agentTabLabel = state.activeTab === "agent" ? style.bold(style.magenta(`[ \u25C6 Agents (${agentCountStr}) ]`, c), c) : style.dim(`\u25CB Agents (${agentCountStr})`, c);
|
|
5423
|
+
const rawQuerySlice = state.searchQuery.length > 14 ? `\u2026${state.searchQuery.slice(-13)}` : state.searchQuery;
|
|
5424
|
+
const searchSuffix = state.searchMode || hasQuery ? ` ${style.yellow(`/ Filter: ${rawQuerySlice}${state.searchMode ? "\u2588" : ""}`, c)}` : ` ${style.dim("(/ search)", c)}`;
|
|
5425
|
+
lines.push(
|
|
5426
|
+
`${style.dim("\u251C\u2500", c)} ${skillTabLabel} ${agentTabLabel}${searchSuffix}`,
|
|
5427
|
+
bar
|
|
5305
5428
|
);
|
|
5306
|
-
|
|
5307
|
-
const
|
|
5308
|
-
if (!opt) continue;
|
|
5309
|
-
const isCurrent = i === state.cursor;
|
|
5310
|
-
const isChecked = state.selected.has(opt.value);
|
|
5311
|
-
const pointer = isCurrent ? style.cyan("\u276F", c) : " ";
|
|
5312
|
-
const checkbox = isChecked ? style.green("\u25FC", c) : style.dim("\u25FB", c);
|
|
5313
|
-
const kindTag = opt.kind === "skill" ? style.cyan("skill ", c) : opt.kind === "agent" ? style.magenta("agent ", c) : "";
|
|
5314
|
-
const labelRaw = opt.label.length > maxLabelCols ? `${opt.label.slice(0, maxLabelCols - 1)}\u2026` : opt.label;
|
|
5315
|
-
const labelPadded = padVisible(labelRaw, maxLabelCols + 1, "left");
|
|
5316
|
-
const styledLabel = isCurrent ? style.bold(labelPadded, c) : isChecked ? style.green(labelPadded, c) : labelPadded;
|
|
5317
|
-
const prefixWidth = 6 + (opt.kind === "skill" || opt.kind === "agent" ? 6 : 0) + maxLabelCols + 1;
|
|
5318
|
-
const maxHintCols = Math.max(10, 75 - prefixWidth);
|
|
5319
|
-
const rawHint = opt.hint ?? "";
|
|
5320
|
-
const shortHint = rawHint.length > maxHintCols ? `${rawHint.slice(0, maxHintCols - 1)}\u2026` : rawHint;
|
|
5321
|
-
const hintPart = shortHint ? ` ${style.dim(shortHint, c)}` : "";
|
|
5429
|
+
if (total === 0) {
|
|
5430
|
+
const tabName = state.activeTab === "skill" ? "Skills" : "Agents";
|
|
5322
5431
|
lines.push(
|
|
5323
|
-
`${bar} ${
|
|
5432
|
+
`${bar} ${style.dim(`No ${tabName} match "${state.searchQuery}". Press Esc to clear filter.`, c)}`
|
|
5324
5433
|
);
|
|
5325
|
-
}
|
|
5326
|
-
|
|
5327
|
-
|
|
5434
|
+
} else {
|
|
5435
|
+
let startIdx = 0;
|
|
5436
|
+
if (total > maxVisible) {
|
|
5437
|
+
const half = Math.floor(maxVisible / 2);
|
|
5438
|
+
startIdx = Math.max(0, Math.min(state.cursor - half, total - maxVisible));
|
|
5439
|
+
}
|
|
5440
|
+
const endIdx = Math.min(total, startIdx + maxVisible);
|
|
5441
|
+
if (startIdx > 0) {
|
|
5442
|
+
lines.push(`${bar} ${style.dim(`\u2191 ${startIdx} more above...`, c)}`);
|
|
5443
|
+
}
|
|
5444
|
+
const maxLabelCols = Math.min(
|
|
5445
|
+
26,
|
|
5446
|
+
visible.reduce((m, o) => Math.max(m, visibleLength(o.label)), 14)
|
|
5447
|
+
);
|
|
5448
|
+
for (let i = startIdx; i < endIdx; i++) {
|
|
5449
|
+
const opt = visible[i];
|
|
5450
|
+
if (!opt) continue;
|
|
5451
|
+
const isCurrent = i === state.cursor;
|
|
5452
|
+
const isChecked = state.selected.has(opt.value);
|
|
5453
|
+
const pointer = isCurrent ? style.cyan("\u276F", c) : " ";
|
|
5454
|
+
const checkbox = isChecked ? style.green("\u25C9", c) : style.dim("\u25EF", c);
|
|
5455
|
+
const labelRaw = opt.label.length > maxLabelCols ? `${opt.label.slice(0, maxLabelCols - 1)}\u2026` : opt.label;
|
|
5456
|
+
const labelPadded = padVisible(labelRaw, maxLabelCols + 1, "left");
|
|
5457
|
+
const styledLabel = isCurrent ? style.bold(labelPadded, c) : isChecked ? style.green(labelPadded, c) : labelPadded;
|
|
5458
|
+
const prefixWidth = 7 + maxLabelCols + 1;
|
|
5459
|
+
const maxHintCols = Math.max(10, 76 - prefixWidth);
|
|
5460
|
+
const rawHint = opt.hint ?? "";
|
|
5461
|
+
const shortHint = rawHint.length > maxHintCols ? `${rawHint.slice(0, maxHintCols - 1)}\u2026` : rawHint;
|
|
5462
|
+
const hintPart = shortHint ? ` ${style.dim(shortHint, c)}` : "";
|
|
5463
|
+
lines.push(`${bar} ${pointer} ${checkbox} ${styledLabel}${hintPart}`);
|
|
5464
|
+
}
|
|
5465
|
+
if (endIdx < total) {
|
|
5466
|
+
lines.push(
|
|
5467
|
+
`${bar} ${style.dim(`\u2193 ${total - endIdx} more below...`, c)}`
|
|
5468
|
+
);
|
|
5469
|
+
}
|
|
5328
5470
|
}
|
|
5329
5471
|
lines.push(bar);
|
|
5330
|
-
const
|
|
5472
|
+
const selectedSkillsCount = state.options.filter(
|
|
5473
|
+
(o) => optionMatchesTab(o, "skill") && state.selected.has(o.value)
|
|
5474
|
+
).length;
|
|
5475
|
+
const selectedAgentsCount = state.options.filter(
|
|
5476
|
+
(o) => optionMatchesTab(o, "agent") && state.selected.has(o.value)
|
|
5477
|
+
).length;
|
|
5478
|
+
const summaryText = `${state.selected.size} selected (${selectedSkillsCount} Skills, ${selectedAgentsCount} Agents)`;
|
|
5479
|
+
const rawTarget = options.targetHint ?? "";
|
|
5480
|
+
const shortTarget = rawTarget.length > 18 ? `${rawTarget.slice(0, 17)}\u2026` : rawTarget;
|
|
5481
|
+
const targetSuffix = shortTarget ? ` \xB7 IDE: ${shortTarget}` : "";
|
|
5331
5482
|
lines.push(
|
|
5332
|
-
`${style.dim("\u2570\u2500", c)} ${style.bold(
|
|
5483
|
+
`${style.dim("\u2570\u2500", c)} ${style.bold(summaryText, c)}${style.dim(`${targetSuffix} \u2014 Enter to import`, c)}`
|
|
5333
5484
|
);
|
|
5334
5485
|
return lines.join("\n");
|
|
5335
5486
|
}
|
|
@@ -6185,6 +6336,7 @@ export {
|
|
|
6185
6336
|
formatScaffoldReport,
|
|
6186
6337
|
formatSyncReport,
|
|
6187
6338
|
formatTokenEconomyReport,
|
|
6339
|
+
getFilteredTabOptions,
|
|
6188
6340
|
handleMcpJsonRpcRequest,
|
|
6189
6341
|
inspectCatalogItem,
|
|
6190
6342
|
inspectHarnesses,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skillops-cli",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.3",
|
|
4
4
|
"description": "SkillOps — The Zero-API Framework & Benchmark-Verified Library for High-End AI Coding Skills & Context-Isolated Subagents with Universal Top-20 AI Agent Transpilation & Token Economy Auditing.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|