skillmux 0.1.2 → 0.1.4
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 +24 -1
- package/dist/chunk-6TMTFWDX.js +419 -0
- package/dist/chunk-6TMTFWDX.js.map +1 -0
- package/dist/chunk-EEIOA7GC.js +2239 -0
- package/dist/chunk-EEIOA7GC.js.map +1 -0
- package/dist/cli.js +4 -2540
- package/dist/cli.js.map +1 -1
- package/dist/index.js +4 -2539
- package/dist/index.js.map +1 -1
- package/dist/launch-tui-IC7COEGE.js +3188 -0
- package/dist/launch-tui-IC7COEGE.js.map +1 -0
- package/package.json +11 -2
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ SkillMux 是一个用来管理本地 agent skills 的命令行工具。
|
|
|
10
10
|
|
|
11
11
|
SkillMux 的作用就是把这件事接管下来:把 skill 收拢到统一位置,然后按 agent 启用、停用、扫描和检查状态。它既适合人直接用,也适合把仓库链接发给 AI,让 AI 按文档自动安装和操作。
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
你可以继续把它交给 AI 使用,也可以用 `skillmux tui` 在终端里直接查看和管理某个 agent 的 skills。后续如果需要,还可以继续扩展 web 等界面。
|
|
14
14
|
|
|
15
15
|
## 适合谁
|
|
16
16
|
|
|
@@ -421,3 +421,26 @@ skillmux doctor
|
|
|
421
421
|
- 控制某个 skill 对哪些 agent 可见,用 `skillmux enable` 和 `skillmux disable`
|
|
422
422
|
- 删除已经停用的托管 skill 用 `skillmux remove`
|
|
423
423
|
- 检查异常状态用 `skillmux doctor`
|
|
424
|
+
|
|
425
|
+
## 交互式看板
|
|
426
|
+
|
|
427
|
+
如果你想一次只看一个 agent,并直接管理它能看到的 skills,可以运行:
|
|
428
|
+
|
|
429
|
+
```bash
|
|
430
|
+
skillmux tui
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
这个界面适合在交互式终端里使用。它会直接占住当前终端,把 Agents、Skills 和详情信息放在同一个工作区里,方便你一边看状态一边操作。
|
|
434
|
+
|
|
435
|
+
- `Left` / `Right` 在 Agents 和 Skills 两栏之间切换焦点。
|
|
436
|
+
- `Space` 启用或停用当前选中的已托管 skill。
|
|
437
|
+
- `a` 在确认后接管一个未托管 skill。
|
|
438
|
+
- `r` 在确认后移除一个已停用的已托管 skill。
|
|
439
|
+
- `s` 扫描本地 agent 文件夹并刷新看板。
|
|
440
|
+
- `/` 在当前聚焦的列表里搜索。
|
|
441
|
+
- `?` 打开帮助。
|
|
442
|
+
- `q` 退出界面。
|
|
443
|
+
|
|
444
|
+
底部会直接标出列表里图标的含义。切到 Skills 时,当前选中的 agent 也会继续保持高亮,方便你一直看清自己正在管理谁。
|
|
445
|
+
|
|
446
|
+
如果输出是脚本重定向,或者当前终端不是交互式终端,请改用 `skillmux list`、`skillmux scan` 或 `skillmux doctor`。
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildConfigPath,
|
|
3
|
+
discoverAgents,
|
|
4
|
+
loadUserConfig,
|
|
5
|
+
printJson,
|
|
6
|
+
printTable,
|
|
7
|
+
resolveSkillmuxHome,
|
|
8
|
+
runAdopt,
|
|
9
|
+
runConfigAddAgent,
|
|
10
|
+
runConfigRemoveAgent,
|
|
11
|
+
runConfigUpdateAgent,
|
|
12
|
+
runDisable,
|
|
13
|
+
runDoctor,
|
|
14
|
+
runEnable,
|
|
15
|
+
runImport,
|
|
16
|
+
runRemove,
|
|
17
|
+
runScan,
|
|
18
|
+
supportedPlatforms
|
|
19
|
+
} from "./chunk-EEIOA7GC.js";
|
|
20
|
+
|
|
21
|
+
// src/index.ts
|
|
22
|
+
import { Command } from "commander";
|
|
23
|
+
|
|
24
|
+
// src/commands/agents.ts
|
|
25
|
+
import { homedir } from "os";
|
|
26
|
+
function buildTableOutput(agents) {
|
|
27
|
+
return printTable(
|
|
28
|
+
agents.map((agent) => ({
|
|
29
|
+
id: agent.id,
|
|
30
|
+
name: agent.stableName,
|
|
31
|
+
path: agent.absoluteSkillsDirectoryPath,
|
|
32
|
+
exists: String(agent.exists),
|
|
33
|
+
supported: String(agent.supportedOnPlatform),
|
|
34
|
+
discovery: agent.discovery
|
|
35
|
+
})),
|
|
36
|
+
[
|
|
37
|
+
{ key: "id", label: "Agent" },
|
|
38
|
+
{ key: "name", label: "Name" },
|
|
39
|
+
{ key: "path", label: "Path" },
|
|
40
|
+
{ key: "exists", label: "Exists" },
|
|
41
|
+
{ key: "supported", label: "Supported" },
|
|
42
|
+
{ key: "discovery", label: "Discovery" }
|
|
43
|
+
]
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
async function runAgents(options = {}) {
|
|
47
|
+
const homeDir = options.homeDir ?? homedir();
|
|
48
|
+
const resolvedPaths = resolveSkillmuxHome(homeDir);
|
|
49
|
+
const skillmuxHome = options.skillmuxHome ?? resolvedPaths.skillmuxHome;
|
|
50
|
+
const agents = await discoverAgents({
|
|
51
|
+
homeDir,
|
|
52
|
+
skillmuxHome,
|
|
53
|
+
platform: options.platform
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
agents,
|
|
57
|
+
output: options.json === true ? printJson(agents) : buildTableOutput(agents)
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// src/commands/config.ts
|
|
62
|
+
import { homedir as homedir2 } from "os";
|
|
63
|
+
function buildTableOutput2(result) {
|
|
64
|
+
const summary = printTable(
|
|
65
|
+
[
|
|
66
|
+
{
|
|
67
|
+
skillmuxHome: result.skillmuxHome,
|
|
68
|
+
configPath: result.configPath,
|
|
69
|
+
overrides: String(Object.keys(result.config.agents).length)
|
|
70
|
+
}
|
|
71
|
+
],
|
|
72
|
+
[
|
|
73
|
+
{ key: "skillmuxHome", label: "SkillMux Home" },
|
|
74
|
+
{ key: "configPath", label: "Config Path" },
|
|
75
|
+
{ key: "overrides", label: "Overrides" }
|
|
76
|
+
]
|
|
77
|
+
);
|
|
78
|
+
const agentRows = Object.entries(result.config.agents).sort(([left], [right]) => left.localeCompare(right)).map(([agentId, agent]) => ({
|
|
79
|
+
agentId,
|
|
80
|
+
stableName: agent.stableName ?? "",
|
|
81
|
+
root: agent.homeRelativeRootPath ?? "",
|
|
82
|
+
skills: agent.skillsDirectoryPath ?? ""
|
|
83
|
+
}));
|
|
84
|
+
if (agentRows.length === 0) {
|
|
85
|
+
return `${summary}
|
|
86
|
+
No user overrides configured.
|
|
87
|
+
`;
|
|
88
|
+
}
|
|
89
|
+
return `${summary}
|
|
90
|
+
${printTable(agentRows, [
|
|
91
|
+
{ key: "agentId", label: "Agent" },
|
|
92
|
+
{ key: "stableName", label: "Name" },
|
|
93
|
+
{ key: "root", label: "Root" },
|
|
94
|
+
{ key: "skills", label: "Skills Dir" }
|
|
95
|
+
])}`;
|
|
96
|
+
}
|
|
97
|
+
async function runConfig(options = {}) {
|
|
98
|
+
const homeDir = options.homeDir ?? homedir2();
|
|
99
|
+
const resolvedPaths = resolveSkillmuxHome(homeDir);
|
|
100
|
+
const skillmuxHome = options.skillmuxHome ?? resolvedPaths.skillmuxHome;
|
|
101
|
+
const config = await loadUserConfig(skillmuxHome);
|
|
102
|
+
const resultWithoutOutput = {
|
|
103
|
+
skillmuxHome,
|
|
104
|
+
configPath: buildConfigPath(skillmuxHome),
|
|
105
|
+
config
|
|
106
|
+
};
|
|
107
|
+
return {
|
|
108
|
+
...resultWithoutOutput,
|
|
109
|
+
output: options.json === true ? printJson(resultWithoutOutput) : buildTableOutput2(resultWithoutOutput)
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// src/commands/list.ts
|
|
114
|
+
function buildRecordsView(scanResult) {
|
|
115
|
+
return {
|
|
116
|
+
view: "records",
|
|
117
|
+
records: scanResult.entries,
|
|
118
|
+
issues: scanResult.issues
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function buildAgentsView(scanResult) {
|
|
122
|
+
const groups = /* @__PURE__ */ new Map();
|
|
123
|
+
for (const agent of scanResult.agents) {
|
|
124
|
+
groups.set(agent.id, {
|
|
125
|
+
agentId: agent.id,
|
|
126
|
+
agentName: agent.stableName,
|
|
127
|
+
entries: []
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
for (const entry of scanResult.entries) {
|
|
131
|
+
const current = groups.get(entry.agentId) ?? {
|
|
132
|
+
agentId: entry.agentId,
|
|
133
|
+
agentName: entry.agentName,
|
|
134
|
+
entries: []
|
|
135
|
+
};
|
|
136
|
+
current.entries.push(entry);
|
|
137
|
+
groups.set(entry.agentId, current);
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
view: "agents",
|
|
141
|
+
agents: [...groups.values()].sort(
|
|
142
|
+
(left, right) => left.agentId.localeCompare(right.agentId)
|
|
143
|
+
),
|
|
144
|
+
issues: scanResult.issues
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
function buildSkillsView(scanResult) {
|
|
148
|
+
const groups = /* @__PURE__ */ new Map();
|
|
149
|
+
for (const skill of Object.values(scanResult.manifest.skills)) {
|
|
150
|
+
groups.set(skill.id, {
|
|
151
|
+
skillName: skill.id,
|
|
152
|
+
entries: []
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
for (const entry of scanResult.entries) {
|
|
156
|
+
const current = groups.get(entry.skillName) ?? {
|
|
157
|
+
skillName: entry.skillName,
|
|
158
|
+
entries: []
|
|
159
|
+
};
|
|
160
|
+
current.entries.push(entry);
|
|
161
|
+
groups.set(entry.skillName, current);
|
|
162
|
+
}
|
|
163
|
+
return {
|
|
164
|
+
view: "skills",
|
|
165
|
+
skills: [...groups.values()].sort(
|
|
166
|
+
(left, right) => left.skillName.localeCompare(right.skillName)
|
|
167
|
+
),
|
|
168
|
+
issues: scanResult.issues
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function buildListData(scanResult, view) {
|
|
172
|
+
if (view === "agents") {
|
|
173
|
+
return buildAgentsView(scanResult);
|
|
174
|
+
}
|
|
175
|
+
if (view === "skills") {
|
|
176
|
+
return buildSkillsView(scanResult);
|
|
177
|
+
}
|
|
178
|
+
return buildRecordsView(scanResult);
|
|
179
|
+
}
|
|
180
|
+
function buildTableOutput3(data, view) {
|
|
181
|
+
if (view === "agents") {
|
|
182
|
+
const agentRows = data.agents;
|
|
183
|
+
return printTable(
|
|
184
|
+
agentRows.map((agent) => ({
|
|
185
|
+
agent: agent.agentId,
|
|
186
|
+
name: agent.agentName,
|
|
187
|
+
entries: String(agent.entries.length)
|
|
188
|
+
})),
|
|
189
|
+
[
|
|
190
|
+
{ key: "agent", label: "Agent" },
|
|
191
|
+
{ key: "name", label: "Name" },
|
|
192
|
+
{ key: "entries", label: "Entries" }
|
|
193
|
+
]
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
if (view === "skills") {
|
|
197
|
+
const skillRows = data.skills;
|
|
198
|
+
return printTable(
|
|
199
|
+
skillRows.map((skill) => ({
|
|
200
|
+
skill: skill.skillName,
|
|
201
|
+
entries: String(skill.entries.length)
|
|
202
|
+
})),
|
|
203
|
+
[
|
|
204
|
+
{ key: "skill", label: "Skill" },
|
|
205
|
+
{ key: "entries", label: "Entries" }
|
|
206
|
+
]
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
const records = data.records;
|
|
210
|
+
return printTable(
|
|
211
|
+
records.map((record) => ({
|
|
212
|
+
agent: record.agentId,
|
|
213
|
+
skill: record.skillName,
|
|
214
|
+
kind: record.kind
|
|
215
|
+
})),
|
|
216
|
+
[
|
|
217
|
+
{ key: "agent", label: "Agent" },
|
|
218
|
+
{ key: "skill", label: "Skill" },
|
|
219
|
+
{ key: "kind", label: "Kind" }
|
|
220
|
+
]
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
async function runList(options = {}) {
|
|
224
|
+
const view = options.view ?? "records";
|
|
225
|
+
const format = options.format ?? "table";
|
|
226
|
+
const scanResult = await runScan(options);
|
|
227
|
+
const data = buildListData(scanResult, view);
|
|
228
|
+
return {
|
|
229
|
+
data,
|
|
230
|
+
output: format === "json" ? printJson(data) : buildTableOutput3(data, view)
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// src/tui/tty.ts
|
|
235
|
+
function isInteractiveTerminal(stdin, stdout) {
|
|
236
|
+
return stdin.isTTY === true && stdout.isTTY === true;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// src/commands/tui.ts
|
|
240
|
+
var TuiNonInteractiveTerminalError = class extends Error {
|
|
241
|
+
constructor() {
|
|
242
|
+
super("skillmux tui requires an interactive terminal");
|
|
243
|
+
this.name = "TuiNonInteractiveTerminalError";
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
async function launchDefaultTui(options) {
|
|
247
|
+
const { launchTui } = await import("./launch-tui-IC7COEGE.js");
|
|
248
|
+
await launchTui(options);
|
|
249
|
+
}
|
|
250
|
+
async function runTui(options = {}) {
|
|
251
|
+
const stdin = options.stdin ?? process.stdin;
|
|
252
|
+
const stdout = options.stdout ?? process.stdout;
|
|
253
|
+
const stderr = options.stderr ?? process.stderr;
|
|
254
|
+
if (!isInteractiveTerminal(stdin, stdout)) {
|
|
255
|
+
stderr.write(
|
|
256
|
+
"skillmux tui requires an interactive terminal. Use skillmux list, skillmux scan, or skillmux doctor for non-interactive output.\n"
|
|
257
|
+
);
|
|
258
|
+
throw new TuiNonInteractiveTerminalError();
|
|
259
|
+
}
|
|
260
|
+
await (options.launch ?? launchDefaultTui)({
|
|
261
|
+
homeDir: options.homeDir,
|
|
262
|
+
skillmuxHome: options.skillmuxHome
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// src/index.ts
|
|
267
|
+
function collectValues(value, previous = []) {
|
|
268
|
+
return [...previous, value];
|
|
269
|
+
}
|
|
270
|
+
function requireSingleValue(values, label) {
|
|
271
|
+
if (values.length !== 1) {
|
|
272
|
+
throw new Error(`Expected exactly one ${label}`);
|
|
273
|
+
}
|
|
274
|
+
return values[0];
|
|
275
|
+
}
|
|
276
|
+
function requireAtLeastOneValue(values, label) {
|
|
277
|
+
if (values.length === 0) {
|
|
278
|
+
throw new Error(`Expected at least one ${label}`);
|
|
279
|
+
}
|
|
280
|
+
return values;
|
|
281
|
+
}
|
|
282
|
+
function buildCli() {
|
|
283
|
+
const program = new Command();
|
|
284
|
+
program.name("skillmux");
|
|
285
|
+
program.command("adopt").requiredOption("--agent <agent>", "Source agent id").option("--skill <skill>", "Repeatable installed skill to adopt", collectValues, []).option("--json", "Emit structured JSON output").action(async (options) => {
|
|
286
|
+
const result = options.skill.length === 0 ? await runAdopt({
|
|
287
|
+
agent: options.agent,
|
|
288
|
+
json: options.json === true
|
|
289
|
+
}) : options.skill.length === 1 ? await runAdopt({
|
|
290
|
+
agent: options.agent,
|
|
291
|
+
skill: options.skill[0],
|
|
292
|
+
json: options.json === true
|
|
293
|
+
}) : await runAdopt({
|
|
294
|
+
agent: options.agent,
|
|
295
|
+
skills: options.skill,
|
|
296
|
+
json: options.json === true
|
|
297
|
+
});
|
|
298
|
+
process.stdout.write(result.output);
|
|
299
|
+
});
|
|
300
|
+
program.command("scan").option("--json", "Emit structured JSON output").action(async (options) => {
|
|
301
|
+
const result = await runScan({ json: options.json === true });
|
|
302
|
+
process.stdout.write(result.output);
|
|
303
|
+
});
|
|
304
|
+
program.command("agents").option("--json", "Emit structured JSON output").action(async (options) => {
|
|
305
|
+
const result = await runAgents({ json: options.json === true });
|
|
306
|
+
process.stdout.write(result.output);
|
|
307
|
+
});
|
|
308
|
+
program.command("list").option("--view <view>", "Select records, agents, or skills view", "records").option("--format <format>", "Select table or json output", "table").action(async (options) => {
|
|
309
|
+
const result = await runList({
|
|
310
|
+
view: options.view,
|
|
311
|
+
format: options.format
|
|
312
|
+
});
|
|
313
|
+
process.stdout.write(result.output);
|
|
314
|
+
});
|
|
315
|
+
program.command("import").requiredOption("--source <path>", "Local skill source directory").requiredOption("--name <name>", "Managed skill name").action(async (options) => {
|
|
316
|
+
const result = await runImport({
|
|
317
|
+
sourcePath: options.source,
|
|
318
|
+
skillName: options.name
|
|
319
|
+
});
|
|
320
|
+
process.stdout.write(result.output);
|
|
321
|
+
});
|
|
322
|
+
program.command("doctor").option("--json", "Emit structured JSON output").action(async (options) => {
|
|
323
|
+
const result = await runDoctor({ json: options.json === true });
|
|
324
|
+
process.stdout.write(result.output);
|
|
325
|
+
});
|
|
326
|
+
program.command("tui").description("Open the interactive SkillMux dashboard").action(async () => {
|
|
327
|
+
try {
|
|
328
|
+
await runTui();
|
|
329
|
+
} catch (error) {
|
|
330
|
+
if (error instanceof TuiNonInteractiveTerminalError) {
|
|
331
|
+
process.exitCode = 1;
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
throw error;
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
const configCommand = program.command("config");
|
|
338
|
+
configCommand.option("--json", "Emit structured JSON output").action(async (options) => {
|
|
339
|
+
const result = await runConfig({ json: options.json === true });
|
|
340
|
+
process.stdout.write(result.output);
|
|
341
|
+
});
|
|
342
|
+
configCommand.command("add-agent").requiredOption("--id <id>", "Agent id").requiredOption("--root <path>", "Home-relative root path").option("--skills <path>", "Skills directory path relative to the agent root", "skills").option("--name <name>", "Stable display name").option(
|
|
343
|
+
"--platform <platform>",
|
|
344
|
+
`Supported platform (${supportedPlatforms.join(", ")})`,
|
|
345
|
+
(value, previous = []) => [...previous, value],
|
|
346
|
+
[]
|
|
347
|
+
).option("--disabled-by-default", "Mark this custom agent as disabled by default").option("--json", "Emit structured JSON output").action(
|
|
348
|
+
async (options) => {
|
|
349
|
+
const result = await runConfigAddAgent({
|
|
350
|
+
id: options.id,
|
|
351
|
+
root: options.root,
|
|
352
|
+
skills: options.skills,
|
|
353
|
+
name: options.name,
|
|
354
|
+
platforms: options.platform,
|
|
355
|
+
disabledByDefault: options.disabledByDefault === true,
|
|
356
|
+
json: options.json === true
|
|
357
|
+
});
|
|
358
|
+
process.stdout.write(result.output);
|
|
359
|
+
}
|
|
360
|
+
);
|
|
361
|
+
configCommand.command("remove-agent").requiredOption("--id <id>", "Agent id").option("--json", "Emit structured JSON output").action(async (options) => {
|
|
362
|
+
const result = await runConfigRemoveAgent({
|
|
363
|
+
id: options.id,
|
|
364
|
+
json: options.json === true
|
|
365
|
+
});
|
|
366
|
+
process.stdout.write(result.output);
|
|
367
|
+
});
|
|
368
|
+
configCommand.command("update-agent").requiredOption("--id <id>", "Agent id").option("--root <path>", "Home-relative root path").option("--skills <path>", "Skills directory path relative to the agent root").option("--name <name>", "Stable display name").option(
|
|
369
|
+
"--platform <platform>",
|
|
370
|
+
`Supported platform (${supportedPlatforms.join(", ")})`,
|
|
371
|
+
(value, previous = []) => [...previous, value],
|
|
372
|
+
[]
|
|
373
|
+
).option("--enabled-by-default", "Mark this custom agent as enabled by default").option("--disabled-by-default", "Mark this custom agent as disabled by default").option("--json", "Emit structured JSON output").action(
|
|
374
|
+
async (options) => {
|
|
375
|
+
const result = await runConfigUpdateAgent({
|
|
376
|
+
id: options.id,
|
|
377
|
+
root: options.root,
|
|
378
|
+
skills: options.skills,
|
|
379
|
+
name: options.name,
|
|
380
|
+
platforms: options.platform !== void 0 && options.platform.length > 0 ? options.platform : void 0,
|
|
381
|
+
enabledByDefault: options.enabledByDefault === true ? true : void 0,
|
|
382
|
+
disabledByDefault: options.disabledByDefault === true,
|
|
383
|
+
json: options.json === true
|
|
384
|
+
});
|
|
385
|
+
process.stdout.write(result.output);
|
|
386
|
+
}
|
|
387
|
+
);
|
|
388
|
+
program.command("enable").requiredOption("--skill <skill>", "Managed skill name or id", collectValues, []).requiredOption("--agent <agent>", "Repeatable target agent", collectValues, []).action(async (options) => {
|
|
389
|
+
const result = await runEnable({
|
|
390
|
+
skill: requireSingleValue(options.skill, "skill"),
|
|
391
|
+
agents: requireAtLeastOneValue(options.agent, "agent")
|
|
392
|
+
});
|
|
393
|
+
process.stdout.write(result.output);
|
|
394
|
+
});
|
|
395
|
+
program.command("disable").requiredOption("--skill <skill>", "Managed skill name or id", collectValues, []).requiredOption("--agent <agent>", "Repeatable target agent", collectValues, []).action(async (options) => {
|
|
396
|
+
const result = await runDisable({
|
|
397
|
+
skill: requireSingleValue(options.skill, "skill"),
|
|
398
|
+
agents: requireAtLeastOneValue(options.agent, "agent")
|
|
399
|
+
});
|
|
400
|
+
process.stdout.write(result.output);
|
|
401
|
+
});
|
|
402
|
+
program.command("remove").requiredOption("--skill <skill>", "Repeatable managed skill name or id", collectValues, []).option("--json", "Emit structured JSON output").action(async (options) => {
|
|
403
|
+
const skills = requireAtLeastOneValue(options.skill, "skill");
|
|
404
|
+
const result = skills.length === 1 ? await runRemove({
|
|
405
|
+
skill: skills[0],
|
|
406
|
+
json: options.json === true
|
|
407
|
+
}) : await runRemove({
|
|
408
|
+
skills,
|
|
409
|
+
json: options.json === true
|
|
410
|
+
});
|
|
411
|
+
process.stdout.write(result.output);
|
|
412
|
+
});
|
|
413
|
+
return program;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
export {
|
|
417
|
+
buildCli
|
|
418
|
+
};
|
|
419
|
+
//# sourceMappingURL=chunk-6TMTFWDX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/agents.ts","../src/commands/config.ts","../src/commands/list.ts","../src/tui/tty.ts","../src/commands/tui.ts"],"sourcesContent":["import { Command } from \"commander\";\r\nimport { supportedPlatforms } from \"./config/default-agent-rules\";\r\nimport { runAdopt } from \"./commands/adopt\";\r\nimport { runAgents } from \"./commands/agents\";\r\nimport { runConfigAddAgent } from \"./commands/config-add-agent\";\r\nimport { runConfigRemoveAgent } from \"./commands/config-remove-agent\";\r\nimport { runConfigUpdateAgent } from \"./commands/config-update-agent\";\r\nimport { runConfig } from \"./commands/config\";\r\nimport { runDoctor } from \"./commands/doctor\";\r\nimport { runDisable } from \"./commands/disable\";\r\nimport { runEnable } from \"./commands/enable\";\r\nimport { runImport } from \"./commands/import\";\r\nimport { runList } from \"./commands/list\";\r\nimport { runRemove } from \"./commands/remove\";\r\nimport { runScan } from \"./commands/scan\";\r\nimport { runTui, TuiNonInteractiveTerminalError } from \"./commands/tui\";\n\r\nfunction collectValues(value: string, previous: string[] = []): string[] {\r\n return [...previous, value];\r\n}\r\n\r\nfunction requireSingleValue(values: string[], label: string): string {\r\n if (values.length !== 1) {\r\n throw new Error(`Expected exactly one ${label}`);\r\n }\r\n\r\n return values[0] as string;\r\n}\r\n\r\nfunction requireAtLeastOneValue(values: string[], label: string): string[] {\r\n if (values.length === 0) {\r\n throw new Error(`Expected at least one ${label}`);\r\n }\r\n\r\n return values;\r\n}\r\n\r\nexport function buildCli(): Command {\r\n const program = new Command();\r\n program.name(\"skillmux\");\r\n\r\n program\r\n .command(\"adopt\")\r\n .requiredOption(\"--agent <agent>\", \"Source agent id\")\r\n .option(\"--skill <skill>\", \"Repeatable installed skill to adopt\", collectValues, [])\r\n .option(\"--json\", \"Emit structured JSON output\")\r\n .action(async (options: { agent: string; skill: string[]; json?: boolean }) => {\r\n const result = options.skill.length === 0\r\n ? await runAdopt({\r\n agent: options.agent,\r\n json: options.json === true\r\n })\r\n : options.skill.length === 1\r\n ? await runAdopt({\r\n agent: options.agent,\r\n skill: options.skill[0] as string,\r\n json: options.json === true\r\n })\r\n : await runAdopt({\r\n agent: options.agent,\r\n skills: options.skill,\r\n json: options.json === true\r\n });\r\n process.stdout.write(result.output);\r\n });\r\n\r\n program\r\n .command(\"scan\")\r\n .option(\"--json\", \"Emit structured JSON output\")\r\n .action(async (options: { json?: boolean }) => {\r\n const result = await runScan({ json: options.json === true });\r\n process.stdout.write(result.output);\r\n });\r\n\r\n program\r\n .command(\"agents\")\r\n .option(\"--json\", \"Emit structured JSON output\")\r\n .action(async (options: { json?: boolean }) => {\r\n const result = await runAgents({ json: options.json === true });\r\n process.stdout.write(result.output);\r\n });\r\n\r\n program\r\n .command(\"list\")\r\n .option(\"--view <view>\", \"Select records, agents, or skills view\", \"records\")\r\n .option(\"--format <format>\", \"Select table or json output\", \"table\")\r\n .action(async (options: { view?: \"records\" | \"agents\" | \"skills\"; format?: \"table\" | \"json\" }) => {\r\n const result = await runList({\r\n view: options.view,\r\n format: options.format\r\n });\r\n process.stdout.write(result.output);\r\n });\r\n\r\n program\r\n .command(\"import\")\r\n .requiredOption(\"--source <path>\", \"Local skill source directory\")\r\n .requiredOption(\"--name <name>\", \"Managed skill name\")\r\n .action(async (options: { source: string; name: string }) => {\r\n const result = await runImport({\r\n sourcePath: options.source,\r\n skillName: options.name\r\n });\r\n process.stdout.write(result.output);\r\n });\r\n\r\n program\r\n .command(\"doctor\")\r\n .option(\"--json\", \"Emit structured JSON output\")\r\n .action(async (options: { json?: boolean }) => {\r\n const result = await runDoctor({ json: options.json === true });\r\n process.stdout.write(result.output);\r\n });\r\n\r\n program\n .command(\"tui\")\n .description(\"Open the interactive SkillMux dashboard\")\n .action(async () => {\n try {\n await runTui();\n } catch (error) {\n if (error instanceof TuiNonInteractiveTerminalError) {\n process.exitCode = 1;\n return;\n }\n\n throw error;\n }\n });\n\r\n const configCommand = program.command(\"config\");\r\n\r\n configCommand\r\n .option(\"--json\", \"Emit structured JSON output\")\r\n .action(async (options: { json?: boolean }) => {\r\n const result = await runConfig({ json: options.json === true });\r\n process.stdout.write(result.output);\r\n });\r\n\r\n configCommand\r\n .command(\"add-agent\")\r\n .requiredOption(\"--id <id>\", \"Agent id\")\r\n .requiredOption(\"--root <path>\", \"Home-relative root path\")\r\n .option(\"--skills <path>\", \"Skills directory path relative to the agent root\", \"skills\")\r\n .option(\"--name <name>\", \"Stable display name\")\r\n .option(\r\n \"--platform <platform>\",\r\n `Supported platform (${supportedPlatforms.join(\", \")})`,\r\n (value: string, previous: string[] = []) => [...previous, value],\r\n []\r\n )\r\n .option(\"--disabled-by-default\", \"Mark this custom agent as disabled by default\")\r\n .option(\"--json\", \"Emit structured JSON output\")\r\n .action(\r\n async (options: {\r\n id: string;\r\n root: string;\r\n skills?: string;\r\n name?: string;\r\n platform?: string[];\r\n disabledByDefault?: boolean;\r\n json?: boolean;\r\n }) => {\r\n const result = await runConfigAddAgent({\r\n id: options.id,\r\n root: options.root,\r\n skills: options.skills,\r\n name: options.name,\r\n platforms: options.platform,\r\n disabledByDefault: options.disabledByDefault === true,\r\n json: options.json === true\r\n });\r\n process.stdout.write(result.output);\r\n }\r\n );\r\n\r\n configCommand\r\n .command(\"remove-agent\")\r\n .requiredOption(\"--id <id>\", \"Agent id\")\r\n .option(\"--json\", \"Emit structured JSON output\")\r\n .action(async (options: { id: string; json?: boolean }) => {\r\n const result = await runConfigRemoveAgent({\r\n id: options.id,\r\n json: options.json === true\r\n });\r\n process.stdout.write(result.output);\r\n });\r\n\r\n configCommand\r\n .command(\"update-agent\")\r\n .requiredOption(\"--id <id>\", \"Agent id\")\r\n .option(\"--root <path>\", \"Home-relative root path\")\r\n .option(\"--skills <path>\", \"Skills directory path relative to the agent root\")\r\n .option(\"--name <name>\", \"Stable display name\")\r\n .option(\r\n \"--platform <platform>\",\r\n `Supported platform (${supportedPlatforms.join(\", \")})`,\r\n (value: string, previous: string[] = []) => [...previous, value],\r\n []\r\n )\r\n .option(\"--enabled-by-default\", \"Mark this custom agent as enabled by default\")\r\n .option(\"--disabled-by-default\", \"Mark this custom agent as disabled by default\")\r\n .option(\"--json\", \"Emit structured JSON output\")\r\n .action(\r\n async (options: {\r\n id: string;\r\n root?: string;\r\n skills?: string;\r\n name?: string;\r\n platform?: string[];\r\n enabledByDefault?: boolean;\r\n disabledByDefault?: boolean;\r\n json?: boolean;\r\n }) => {\r\n const result = await runConfigUpdateAgent({\r\n id: options.id,\r\n root: options.root,\r\n skills: options.skills,\r\n name: options.name,\r\n platforms:\r\n options.platform !== undefined && options.platform.length > 0\r\n ? options.platform\r\n : undefined,\r\n enabledByDefault:\r\n options.enabledByDefault === true ? true : undefined,\r\n disabledByDefault: options.disabledByDefault === true,\r\n json: options.json === true\r\n });\r\n process.stdout.write(result.output);\r\n }\r\n );\r\n\r\n program\r\n .command(\"enable\")\r\n .requiredOption(\"--skill <skill>\", \"Managed skill name or id\", collectValues, [])\r\n .requiredOption(\"--agent <agent>\", \"Repeatable target agent\", collectValues, [])\r\n .action(async (options: { skill: string[]; agent: string[] }) => {\r\n const result = await runEnable({\r\n skill: requireSingleValue(options.skill, \"skill\"),\r\n agents: requireAtLeastOneValue(options.agent, \"agent\")\r\n });\r\n process.stdout.write(result.output);\r\n });\r\n\r\n program\r\n .command(\"disable\")\r\n .requiredOption(\"--skill <skill>\", \"Managed skill name or id\", collectValues, [])\r\n .requiredOption(\"--agent <agent>\", \"Repeatable target agent\", collectValues, [])\r\n .action(async (options: { skill: string[]; agent: string[] }) => {\r\n const result = await runDisable({\r\n skill: requireSingleValue(options.skill, \"skill\"),\r\n agents: requireAtLeastOneValue(options.agent, \"agent\")\r\n });\r\n process.stdout.write(result.output);\r\n });\r\n\r\n program\r\n .command(\"remove\")\r\n .requiredOption(\"--skill <skill>\", \"Repeatable managed skill name or id\", collectValues, [])\r\n .option(\"--json\", \"Emit structured JSON output\")\r\n .action(async (options: { skill: string[]; json?: boolean }) => {\r\n const skills = requireAtLeastOneValue(options.skill, \"skill\");\r\n const result = skills.length === 1\r\n ? await runRemove({\r\n skill: skills[0] as string,\r\n json: options.json === true\r\n })\r\n : await runRemove({\r\n skills,\r\n json: options.json === true\r\n });\r\n process.stdout.write(result.output);\r\n });\r\n\r\n return program;\r\n}\r\n","import { homedir } from \"node:os\";\r\nimport { resolveSkillmuxHome } from \"../config/resolve-skillmux-home\";\r\nimport {\r\n discoverAgents,\r\n type DiscoveredAgent\r\n} from \"../discovery/discover-agents\";\r\nimport { printJson } from \"../output/print-json\";\r\nimport { printTable } from \"../output/print-table\";\r\n\r\nexport type RunAgentsOptions = {\r\n homeDir?: string;\r\n skillmuxHome?: string;\r\n platform?: NodeJS.Platform;\r\n json?: boolean;\r\n};\r\n\r\nexport type RunAgentsResult = {\r\n agents: DiscoveredAgent[];\r\n output: string;\r\n};\r\n\r\nfunction buildTableOutput(agents: DiscoveredAgent[]): string {\r\n return printTable(\r\n agents.map((agent) => ({\r\n id: agent.id,\r\n name: agent.stableName,\r\n path: agent.absoluteSkillsDirectoryPath,\r\n exists: String(agent.exists),\r\n supported: String(agent.supportedOnPlatform),\r\n discovery: agent.discovery\r\n })),\r\n [\r\n { key: \"id\", label: \"Agent\" },\r\n { key: \"name\", label: \"Name\" },\r\n { key: \"path\", label: \"Path\" },\r\n { key: \"exists\", label: \"Exists\" },\r\n { key: \"supported\", label: \"Supported\" },\r\n { key: \"discovery\", label: \"Discovery\" }\r\n ]\r\n );\r\n}\r\n\r\nexport async function runAgents(\r\n options: RunAgentsOptions = {}\r\n): Promise<RunAgentsResult> {\r\n const homeDir = options.homeDir ?? homedir();\r\n const resolvedPaths = resolveSkillmuxHome(homeDir);\r\n const skillmuxHome = options.skillmuxHome ?? resolvedPaths.skillmuxHome;\r\n const agents = await discoverAgents({\r\n homeDir,\r\n skillmuxHome,\r\n platform: options.platform\r\n });\r\n\r\n return {\r\n agents,\r\n output:\r\n options.json === true\r\n ? printJson(agents)\r\n : buildTableOutput(agents)\r\n };\r\n}\r\n","import { homedir } from \"node:os\";\nimport { buildConfigPath } from \"../config/resolve-skillmux-home\";\nimport { loadUserConfig, type UserConfig } from \"../config/load-user-config\";\nimport { resolveSkillmuxHome } from \"../config/resolve-skillmux-home\";\nimport { printJson } from \"../output/print-json\";\r\nimport { printTable } from \"../output/print-table\";\r\n\r\nexport type RunConfigOptions = {\r\n homeDir?: string;\r\n skillmuxHome?: string;\r\n json?: boolean;\r\n};\r\n\r\nexport type RunConfigResult = {\r\n skillmuxHome: string;\r\n configPath: string;\r\n config: UserConfig;\r\n output: string;\r\n};\r\n\r\nfunction buildTableOutput(result: Omit<RunConfigResult, \"output\">): string {\r\n const summary = printTable(\r\n [\r\n {\r\n skillmuxHome: result.skillmuxHome,\r\n configPath: result.configPath,\r\n overrides: String(Object.keys(result.config.agents).length)\r\n }\r\n ],\r\n [\r\n { key: \"skillmuxHome\", label: \"SkillMux Home\" },\r\n { key: \"configPath\", label: \"Config Path\" },\r\n { key: \"overrides\", label: \"Overrides\" }\r\n ]\r\n );\r\n\r\n const agentRows = Object.entries(result.config.agents)\r\n .sort(([left], [right]) => left.localeCompare(right))\r\n .map(([agentId, agent]) => ({\r\n agentId,\r\n stableName: agent.stableName ?? \"\",\r\n root: agent.homeRelativeRootPath ?? \"\",\r\n skills: agent.skillsDirectoryPath ?? \"\"\r\n }));\r\n\r\n if (agentRows.length === 0) {\r\n return `${summary}\\nNo user overrides configured.\\n`;\r\n }\r\n\r\n return `${summary}\\n${printTable(agentRows, [\r\n { key: \"agentId\", label: \"Agent\" },\r\n { key: \"stableName\", label: \"Name\" },\r\n { key: \"root\", label: \"Root\" },\r\n { key: \"skills\", label: \"Skills Dir\" }\r\n ])}`;\r\n}\r\n\r\nexport async function runConfig(\r\n options: RunConfigOptions = {}\r\n): Promise<RunConfigResult> {\r\n const homeDir = options.homeDir ?? homedir();\n const resolvedPaths = resolveSkillmuxHome(homeDir);\n const skillmuxHome = options.skillmuxHome ?? resolvedPaths.skillmuxHome;\n const config = await loadUserConfig(skillmuxHome);\n\r\n const resultWithoutOutput = {\r\n skillmuxHome,\n configPath: buildConfigPath(skillmuxHome),\n config\n };\n\r\n return {\r\n ...resultWithoutOutput,\r\n output:\r\n options.json === true\r\n ? printJson(resultWithoutOutput)\r\n : buildTableOutput(resultWithoutOutput)\r\n };\r\n}\r\n","import { printJson } from \"../output/print-json\";\r\nimport { printTable } from \"../output/print-table\";\r\nimport { runScan, type RunScanOptions, type RunScanResult } from \"./scan\";\r\n\r\nexport type ListView = \"records\" | \"agents\" | \"skills\";\r\nexport type ListFormat = \"table\" | \"json\";\r\n\r\nexport type RunListOptions = Omit<RunScanOptions, \"json\"> & {\r\n view?: ListView;\r\n format?: ListFormat;\r\n};\r\n\r\nexport type RunListResult = {\r\n output: string;\r\n data: unknown;\r\n};\r\n\r\nfunction buildRecordsView(scanResult: RunScanResult) {\r\n return {\r\n view: \"records\" as const,\r\n records: scanResult.entries,\r\n issues: scanResult.issues\r\n };\r\n}\r\n\r\nfunction buildAgentsView(scanResult: RunScanResult) {\n const groups = new Map<\n string,\n {\r\n agentId: string;\r\n agentName: string;\r\n entries: RunScanResult[\"entries\"];\r\n }\n >();\n\n for (const agent of scanResult.agents) {\n groups.set(agent.id, {\n agentId: agent.id,\n agentName: agent.stableName,\n entries: []\n });\n }\n\n for (const entry of scanResult.entries) {\n const current = groups.get(entry.agentId) ?? {\n agentId: entry.agentId,\n agentName: entry.agentName,\r\n entries: []\r\n };\r\n current.entries.push(entry);\r\n groups.set(entry.agentId, current);\r\n }\r\n\r\n return {\r\n view: \"agents\" as const,\r\n agents: [...groups.values()].sort((left, right) =>\r\n left.agentId.localeCompare(right.agentId)\r\n ),\r\n issues: scanResult.issues\r\n };\r\n}\r\n\r\nfunction buildSkillsView(scanResult: RunScanResult) {\n const groups = new Map<\n string,\n {\r\n skillName: string;\r\n entries: RunScanResult[\"entries\"];\r\n }\n >();\n\n for (const skill of Object.values(scanResult.manifest.skills)) {\n groups.set(skill.id, {\n skillName: skill.id,\n entries: []\n });\n }\n\n for (const entry of scanResult.entries) {\n const current = groups.get(entry.skillName) ?? {\n skillName: entry.skillName,\n entries: []\r\n };\r\n current.entries.push(entry);\r\n groups.set(entry.skillName, current);\r\n }\r\n\r\n return {\r\n view: \"skills\" as const,\r\n skills: [...groups.values()].sort((left, right) =>\r\n left.skillName.localeCompare(right.skillName)\r\n ),\r\n issues: scanResult.issues\r\n };\r\n}\r\n\r\nfunction buildListData(scanResult: RunScanResult, view: ListView): unknown {\r\n if (view === \"agents\") {\r\n return buildAgentsView(scanResult);\r\n }\r\n\r\n if (view === \"skills\") {\r\n return buildSkillsView(scanResult);\r\n }\r\n\r\n return buildRecordsView(scanResult);\r\n}\r\n\r\nfunction buildTableOutput(data: unknown, view: ListView): string {\r\n if (view === \"agents\") {\r\n const agentRows = (data as { agents: Array<{ agentId: string; agentName: string; entries: unknown[] }> }).agents;\r\n return printTable(\r\n agentRows.map((agent) => ({\r\n agent: agent.agentId,\r\n name: agent.agentName,\r\n entries: String(agent.entries.length)\r\n })),\r\n [\r\n { key: \"agent\", label: \"Agent\" },\r\n { key: \"name\", label: \"Name\" },\r\n { key: \"entries\", label: \"Entries\" }\r\n ]\r\n );\r\n }\r\n\r\n if (view === \"skills\") {\r\n const skillRows = (data as { skills: Array<{ skillName: string; entries: unknown[] }> }).skills;\r\n return printTable(\r\n skillRows.map((skill) => ({\r\n skill: skill.skillName,\r\n entries: String(skill.entries.length)\r\n })),\r\n [\r\n { key: \"skill\", label: \"Skill\" },\r\n { key: \"entries\", label: \"Entries\" }\r\n ]\r\n );\r\n }\r\n\r\n const records = (data as { records: Array<{ agentId: string; skillName: string; kind: string }> }).records;\r\n return printTable(\r\n records.map((record) => ({\r\n agent: record.agentId,\r\n skill: record.skillName,\r\n kind: record.kind\r\n })),\r\n [\r\n { key: \"agent\", label: \"Agent\" },\r\n { key: \"skill\", label: \"Skill\" },\r\n { key: \"kind\", label: \"Kind\" }\r\n ]\r\n );\r\n}\r\n\r\nexport async function runList(options: RunListOptions = {}): Promise<RunListResult> {\r\n const view = options.view ?? \"records\";\r\n const format = options.format ?? \"table\";\r\n const scanResult = await runScan(options);\r\n const data = buildListData(scanResult, view);\r\n\r\n return {\r\n data,\r\n output: format === \"json\" ? printJson(data) : buildTableOutput(data, view)\r\n };\r\n}\r\n","export type TtyLike = {\r\n isTTY?: boolean;\r\n};\r\n\r\nexport function isInteractiveTerminal(stdin: TtyLike, stdout: TtyLike): boolean {\r\n return stdin.isTTY === true && stdout.isTTY === true;\r\n}\r\n","import type { LaunchTuiOptions } from \"../tui/launch-tui\";\r\nimport { isInteractiveTerminal, type TtyLike } from \"../tui/tty\";\r\n\r\nexport type RunTuiOptions = LaunchTuiOptions & {\n stdin?: TtyLike;\n stdout?: TtyLike;\n stderr?: { write(message: string): unknown };\n launch?: (options: LaunchTuiOptions) => Promise<void>;\n};\n\nexport class TuiNonInteractiveTerminalError extends Error {\n constructor() {\n super(\"skillmux tui requires an interactive terminal\");\n this.name = \"TuiNonInteractiveTerminalError\";\n }\n}\n\nasync function launchDefaultTui(options: LaunchTuiOptions): Promise<void> {\n const { launchTui } = await import(\"../tui/launch-tui\");\n\r\n await launchTui(options);\r\n}\r\n\r\nexport async function runTui(options: RunTuiOptions = {}): Promise<void> {\r\n const stdin = options.stdin ?? process.stdin;\r\n const stdout = options.stdout ?? process.stdout;\r\n const stderr = options.stderr ?? process.stderr;\r\n\r\n if (!isInteractiveTerminal(stdin, stdout)) {\r\n stderr.write(\n \"skillmux tui requires an interactive terminal. Use skillmux list, skillmux scan, or skillmux doctor for non-interactive output.\\n\"\n );\n throw new TuiNonInteractiveTerminalError();\n }\n\r\n await (options.launch ?? launchDefaultTui)({\r\n homeDir: options.homeDir,\r\n skillmuxHome: options.skillmuxHome\r\n });\r\n}\r\n"],"mappings":"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","names":["homedir","buildTableOutput","homedir","buildTableOutput"]}
|