skillmux 0.1.3 → 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/dist/{chunk-UMN3UJFN.js → chunk-6TMTFWDX.js} +14 -431
- package/dist/chunk-6TMTFWDX.js.map +1 -0
- package/dist/{chunk-DBEVDI27.js → chunk-EEIOA7GC.js} +575 -162
- package/dist/chunk-EEIOA7GC.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/index.js +2 -2
- package/dist/launch-tui-IC7COEGE.js +3188 -0
- package/dist/launch-tui-IC7COEGE.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-DBEVDI27.js.map +0 -1
- package/dist/chunk-UMN3UJFN.js.map +0 -1
- package/dist/launch-tui-PHWJPIQZ.js +0 -1790
- package/dist/launch-tui-PHWJPIQZ.js.map +0 -1
|
@@ -1084,20 +1084,509 @@ async function runAdopt(options) {
|
|
|
1084
1084
|
return runAdoptSingle(options);
|
|
1085
1085
|
}
|
|
1086
1086
|
|
|
1087
|
-
// src/commands/
|
|
1088
|
-
import * as fs11 from "fs/promises";
|
|
1087
|
+
// src/commands/config-add-agent.ts
|
|
1089
1088
|
import { homedir as homedir2 } from "os";
|
|
1090
|
-
import { join as join8, resolve as resolve9 } from "path";
|
|
1091
1089
|
|
|
1092
|
-
// src/
|
|
1090
|
+
// src/config/agent-override-validation.ts
|
|
1091
|
+
import { isAbsolute } from "path";
|
|
1092
|
+
function normalizeRelativePath(value, field) {
|
|
1093
|
+
const trimmed = value.trim();
|
|
1094
|
+
if (trimmed.length === 0) {
|
|
1095
|
+
throw new UserConfigValidationError(`${field} must not be empty`);
|
|
1096
|
+
}
|
|
1097
|
+
if (isAbsolute(trimmed)) {
|
|
1098
|
+
throw new UserConfigValidationError(`${field} must be a relative path`);
|
|
1099
|
+
}
|
|
1100
|
+
const normalized = trimmed.replaceAll("\\", "/");
|
|
1101
|
+
if (normalized === "." || normalized === ".." || normalized.startsWith("../") || normalized.includes("/../")) {
|
|
1102
|
+
throw new UserConfigValidationError(`${field} must stay within the configured home-relative tree`);
|
|
1103
|
+
}
|
|
1104
|
+
return normalized.replace(/^\.\/+/, "");
|
|
1105
|
+
}
|
|
1106
|
+
function normalizeAgentId(value) {
|
|
1107
|
+
const trimmed = value.trim();
|
|
1108
|
+
if (trimmed.length === 0 || /[a-z0-9]/i.test(trimmed) === false) {
|
|
1109
|
+
throw new InvalidIdentifierError("agent id", value);
|
|
1110
|
+
}
|
|
1111
|
+
return normalizeId(trimmed);
|
|
1112
|
+
}
|
|
1113
|
+
function normalizePlatforms(value) {
|
|
1114
|
+
if (value === void 0 || value.length === 0) {
|
|
1115
|
+
return [process.platform];
|
|
1116
|
+
}
|
|
1117
|
+
const normalized = [...new Set(value.map((entry) => entry.trim().toLowerCase()))];
|
|
1118
|
+
const invalid = normalized.filter(
|
|
1119
|
+
(entry) => supportedPlatforms.includes(entry) === false
|
|
1120
|
+
);
|
|
1121
|
+
if (invalid.length > 0) {
|
|
1122
|
+
throw new UserConfigValidationError(
|
|
1123
|
+
`platform must be one of: ${supportedPlatforms.join(", ")}`
|
|
1124
|
+
);
|
|
1125
|
+
}
|
|
1126
|
+
return normalized;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
// src/config/write-user-config.ts
|
|
1093
1130
|
import * as fs10 from "fs/promises";
|
|
1131
|
+
async function writeUserConfig(skillmuxHome, config) {
|
|
1132
|
+
const configPath = buildConfigPath(skillmuxHome);
|
|
1133
|
+
await fs10.mkdir(skillmuxHome, { recursive: true });
|
|
1134
|
+
await fs10.writeFile(configPath, `${JSON.stringify(config, null, 2)}
|
|
1135
|
+
`, "utf8");
|
|
1136
|
+
return {
|
|
1137
|
+
skillmuxHome,
|
|
1138
|
+
configPath
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
// src/output/print-table.ts
|
|
1143
|
+
function printTable(rows, columns) {
|
|
1144
|
+
const renderedRows = rows.map(
|
|
1145
|
+
(row) => columns.map((column) => String(row[column.key] ?? ""))
|
|
1146
|
+
);
|
|
1147
|
+
const widths = columns.map(
|
|
1148
|
+
(column, index) => Math.max(
|
|
1149
|
+
column.label.length,
|
|
1150
|
+
...renderedRows.map((row) => row[index]?.length ?? 0)
|
|
1151
|
+
)
|
|
1152
|
+
);
|
|
1153
|
+
const header = columns.map((column, index) => column.label.padEnd(widths[index])).join(" ");
|
|
1154
|
+
const separator = widths.map((width) => "-".repeat(width)).join(" ");
|
|
1155
|
+
const body = renderedRows.map(
|
|
1156
|
+
(row) => row.map((cell, index) => cell.padEnd(widths[index])).join(" ")
|
|
1157
|
+
);
|
|
1158
|
+
return `${[header, separator, ...body].join("\n")}
|
|
1159
|
+
`;
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
// src/commands/config-add-agent.ts
|
|
1163
|
+
function buildAgentOverride(options) {
|
|
1164
|
+
const agentId = normalizeAgentId(options.id);
|
|
1165
|
+
const agent = {
|
|
1166
|
+
supportedPlatforms: normalizePlatforms(options.platforms),
|
|
1167
|
+
homeRelativeRootPath: normalizeRelativePath(options.root, "root"),
|
|
1168
|
+
skillsDirectoryPath: normalizeRelativePath(options.skills ?? "skills", "skills")
|
|
1169
|
+
};
|
|
1170
|
+
if (options.name !== void 0 && options.name.trim().length > 0) {
|
|
1171
|
+
agent.stableName = options.name.trim();
|
|
1172
|
+
}
|
|
1173
|
+
if (options.disabledByDefault === true) {
|
|
1174
|
+
agent.enabledByDefault = false;
|
|
1175
|
+
}
|
|
1176
|
+
return { agentId, agent };
|
|
1177
|
+
}
|
|
1178
|
+
function buildTableOutput(result) {
|
|
1179
|
+
const summary = printTable(
|
|
1180
|
+
[
|
|
1181
|
+
{
|
|
1182
|
+
agentId: result.agentId,
|
|
1183
|
+
configPath: result.configPath,
|
|
1184
|
+
changed: String(result.changed)
|
|
1185
|
+
}
|
|
1186
|
+
],
|
|
1187
|
+
[
|
|
1188
|
+
{ key: "agentId", label: "Agent" },
|
|
1189
|
+
{ key: "configPath", label: "Config Path" },
|
|
1190
|
+
{ key: "changed", label: "Changed" }
|
|
1191
|
+
]
|
|
1192
|
+
);
|
|
1193
|
+
const detail = printTable(
|
|
1194
|
+
[
|
|
1195
|
+
{
|
|
1196
|
+
stableName: result.agent.stableName ?? "",
|
|
1197
|
+
platforms: (result.agent.supportedPlatforms ?? []).join(","),
|
|
1198
|
+
root: result.agent.homeRelativeRootPath ?? "",
|
|
1199
|
+
skills: result.agent.skillsDirectoryPath ?? "",
|
|
1200
|
+
enabledByDefault: result.agent.enabledByDefault === void 0 ? "" : String(result.agent.enabledByDefault)
|
|
1201
|
+
}
|
|
1202
|
+
],
|
|
1203
|
+
[
|
|
1204
|
+
{ key: "stableName", label: "Name" },
|
|
1205
|
+
{ key: "platforms", label: "Platforms" },
|
|
1206
|
+
{ key: "root", label: "Root" },
|
|
1207
|
+
{ key: "skills", label: "Skills Dir" },
|
|
1208
|
+
{ key: "enabledByDefault", label: "Enabled By Default" }
|
|
1209
|
+
]
|
|
1210
|
+
);
|
|
1211
|
+
return `${summary}${detail}`;
|
|
1212
|
+
}
|
|
1213
|
+
async function runConfigAddAgent(options) {
|
|
1214
|
+
const homeDir = options.homeDir ?? homedir2();
|
|
1215
|
+
const resolvedPaths = resolveSkillmuxHome(homeDir);
|
|
1216
|
+
const skillmuxHome = options.skillmuxHome ?? resolvedPaths.skillmuxHome;
|
|
1217
|
+
const configPath = buildConfigPath(skillmuxHome);
|
|
1218
|
+
const config = await loadUserConfig(skillmuxHome);
|
|
1219
|
+
const { agentId, agent } = buildAgentOverride(options);
|
|
1220
|
+
const previous = config.agents[agentId];
|
|
1221
|
+
const changed = JSON.stringify(previous ?? null) !== JSON.stringify(agent);
|
|
1222
|
+
const nextConfig = {
|
|
1223
|
+
...config,
|
|
1224
|
+
agents: {
|
|
1225
|
+
...config.agents,
|
|
1226
|
+
[agentId]: agent
|
|
1227
|
+
}
|
|
1228
|
+
};
|
|
1229
|
+
await writeUserConfig(skillmuxHome, nextConfig);
|
|
1230
|
+
const resultWithoutOutput = {
|
|
1231
|
+
skillmuxHome,
|
|
1232
|
+
configPath,
|
|
1233
|
+
agentId,
|
|
1234
|
+
changed,
|
|
1235
|
+
agent,
|
|
1236
|
+
config: nextConfig
|
|
1237
|
+
};
|
|
1238
|
+
return {
|
|
1239
|
+
...resultWithoutOutput,
|
|
1240
|
+
output: options.json === true ? printJson(resultWithoutOutput) : buildTableOutput(resultWithoutOutput)
|
|
1241
|
+
};
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
// src/commands/config-remove-agent.ts
|
|
1245
|
+
import { homedir as homedir3 } from "os";
|
|
1246
|
+
function normalizeAgentId2(value) {
|
|
1247
|
+
const trimmed = value.trim();
|
|
1248
|
+
if (trimmed.length === 0 || /[a-z0-9]/i.test(trimmed) === false) {
|
|
1249
|
+
throw new InvalidIdentifierError("agent id", value);
|
|
1250
|
+
}
|
|
1251
|
+
return normalizeId(trimmed);
|
|
1252
|
+
}
|
|
1253
|
+
function buildTableOutput2(result) {
|
|
1254
|
+
return printTable(
|
|
1255
|
+
[
|
|
1256
|
+
{
|
|
1257
|
+
agentId: result.agentId,
|
|
1258
|
+
configPath: result.configPath,
|
|
1259
|
+
changed: String(result.changed),
|
|
1260
|
+
removed: String(result.removed)
|
|
1261
|
+
}
|
|
1262
|
+
],
|
|
1263
|
+
[
|
|
1264
|
+
{ key: "agentId", label: "Agent" },
|
|
1265
|
+
{ key: "configPath", label: "Config Path" },
|
|
1266
|
+
{ key: "changed", label: "Changed" },
|
|
1267
|
+
{ key: "removed", label: "Removed" }
|
|
1268
|
+
]
|
|
1269
|
+
);
|
|
1270
|
+
}
|
|
1271
|
+
async function runConfigRemoveAgent(options) {
|
|
1272
|
+
const homeDir = options.homeDir ?? homedir3();
|
|
1273
|
+
const resolvedPaths = resolveSkillmuxHome(homeDir);
|
|
1274
|
+
const skillmuxHome = options.skillmuxHome ?? resolvedPaths.skillmuxHome;
|
|
1275
|
+
const configPath = buildConfigPath(skillmuxHome);
|
|
1276
|
+
const config = await loadUserConfig(skillmuxHome);
|
|
1277
|
+
const agentId = normalizeAgentId2(options.id);
|
|
1278
|
+
const removed = agentId in config.agents;
|
|
1279
|
+
const nextConfig = {
|
|
1280
|
+
...config,
|
|
1281
|
+
agents: Object.fromEntries(
|
|
1282
|
+
Object.entries(config.agents).filter(([currentAgentId]) => currentAgentId !== agentId)
|
|
1283
|
+
)
|
|
1284
|
+
};
|
|
1285
|
+
if (removed) {
|
|
1286
|
+
await writeUserConfig(skillmuxHome, nextConfig);
|
|
1287
|
+
}
|
|
1288
|
+
const resultWithoutOutput = {
|
|
1289
|
+
skillmuxHome,
|
|
1290
|
+
configPath,
|
|
1291
|
+
agentId,
|
|
1292
|
+
changed: removed,
|
|
1293
|
+
removed,
|
|
1294
|
+
config: nextConfig
|
|
1295
|
+
};
|
|
1296
|
+
return {
|
|
1297
|
+
...resultWithoutOutput,
|
|
1298
|
+
output: options.json === true ? printJson(resultWithoutOutput) : buildTableOutput2(resultWithoutOutput)
|
|
1299
|
+
};
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
// src/commands/config-update-agent.ts
|
|
1303
|
+
import { homedir as homedir4 } from "os";
|
|
1304
|
+
function buildAgentPatch(options) {
|
|
1305
|
+
const patch = {};
|
|
1306
|
+
if (options.root !== void 0) {
|
|
1307
|
+
patch.homeRelativeRootPath = normalizeRelativePath(options.root, "root");
|
|
1308
|
+
}
|
|
1309
|
+
if (options.skills !== void 0) {
|
|
1310
|
+
patch.skillsDirectoryPath = normalizeRelativePath(options.skills, "skills");
|
|
1311
|
+
}
|
|
1312
|
+
if (options.name !== void 0 && options.name.trim().length > 0) {
|
|
1313
|
+
patch.stableName = options.name.trim();
|
|
1314
|
+
}
|
|
1315
|
+
if (options.platforms !== void 0) {
|
|
1316
|
+
patch.supportedPlatforms = normalizePlatforms(options.platforms);
|
|
1317
|
+
}
|
|
1318
|
+
if (options.enabledByDefault !== void 0 && options.disabledByDefault === true) {
|
|
1319
|
+
throw new UserConfigValidationError(
|
|
1320
|
+
"enabled-by-default and disabled-by-default cannot both be set"
|
|
1321
|
+
);
|
|
1322
|
+
}
|
|
1323
|
+
if (options.enabledByDefault !== void 0) {
|
|
1324
|
+
patch.enabledByDefault = options.enabledByDefault;
|
|
1325
|
+
}
|
|
1326
|
+
if (options.disabledByDefault === true) {
|
|
1327
|
+
patch.enabledByDefault = false;
|
|
1328
|
+
}
|
|
1329
|
+
return patch;
|
|
1330
|
+
}
|
|
1331
|
+
function buildTableOutput3(result) {
|
|
1332
|
+
const summary = printTable(
|
|
1333
|
+
[
|
|
1334
|
+
{
|
|
1335
|
+
agentId: result.agentId,
|
|
1336
|
+
configPath: result.configPath,
|
|
1337
|
+
changed: String(result.changed)
|
|
1338
|
+
}
|
|
1339
|
+
],
|
|
1340
|
+
[
|
|
1341
|
+
{ key: "agentId", label: "Agent" },
|
|
1342
|
+
{ key: "configPath", label: "Config Path" },
|
|
1343
|
+
{ key: "changed", label: "Changed" }
|
|
1344
|
+
]
|
|
1345
|
+
);
|
|
1346
|
+
const detail = printTable(
|
|
1347
|
+
[
|
|
1348
|
+
{
|
|
1349
|
+
stableName: result.agent.stableName ?? "",
|
|
1350
|
+
platforms: (result.agent.supportedPlatforms ?? []).join(","),
|
|
1351
|
+
root: result.agent.homeRelativeRootPath ?? "",
|
|
1352
|
+
skills: result.agent.skillsDirectoryPath ?? "",
|
|
1353
|
+
enabledByDefault: result.agent.enabledByDefault === void 0 ? "" : String(result.agent.enabledByDefault)
|
|
1354
|
+
}
|
|
1355
|
+
],
|
|
1356
|
+
[
|
|
1357
|
+
{ key: "stableName", label: "Name" },
|
|
1358
|
+
{ key: "platforms", label: "Platforms" },
|
|
1359
|
+
{ key: "root", label: "Root" },
|
|
1360
|
+
{ key: "skills", label: "Skills Dir" },
|
|
1361
|
+
{ key: "enabledByDefault", label: "Enabled By Default" }
|
|
1362
|
+
]
|
|
1363
|
+
);
|
|
1364
|
+
return `${summary}${detail}`;
|
|
1365
|
+
}
|
|
1366
|
+
async function runConfigUpdateAgent(options) {
|
|
1367
|
+
const homeDir = options.homeDir ?? homedir4();
|
|
1368
|
+
const resolvedPaths = resolveSkillmuxHome(homeDir);
|
|
1369
|
+
const skillmuxHome = options.skillmuxHome ?? resolvedPaths.skillmuxHome;
|
|
1370
|
+
const configPath = buildConfigPath(skillmuxHome);
|
|
1371
|
+
const config = await loadUserConfig(skillmuxHome);
|
|
1372
|
+
const agentId = normalizeAgentId(options.id);
|
|
1373
|
+
const previous = config.agents[agentId];
|
|
1374
|
+
if (previous === void 0) {
|
|
1375
|
+
throw new UserConfigValidationError(`Agent override does not exist: ${agentId}`);
|
|
1376
|
+
}
|
|
1377
|
+
const agent = {
|
|
1378
|
+
...previous,
|
|
1379
|
+
...buildAgentPatch(options)
|
|
1380
|
+
};
|
|
1381
|
+
const changed = JSON.stringify(previous) !== JSON.stringify(agent);
|
|
1382
|
+
const nextConfig = {
|
|
1383
|
+
...config,
|
|
1384
|
+
agents: {
|
|
1385
|
+
...config.agents,
|
|
1386
|
+
[agentId]: agent
|
|
1387
|
+
}
|
|
1388
|
+
};
|
|
1389
|
+
if (changed) {
|
|
1390
|
+
await writeUserConfig(skillmuxHome, nextConfig);
|
|
1391
|
+
}
|
|
1392
|
+
const resultWithoutOutput = {
|
|
1393
|
+
skillmuxHome,
|
|
1394
|
+
configPath,
|
|
1395
|
+
agentId,
|
|
1396
|
+
changed,
|
|
1397
|
+
agent,
|
|
1398
|
+
config: nextConfig
|
|
1399
|
+
};
|
|
1400
|
+
return {
|
|
1401
|
+
...resultWithoutOutput,
|
|
1402
|
+
output: options.json === true ? printJson(resultWithoutOutput) : buildTableOutput3(resultWithoutOutput)
|
|
1403
|
+
};
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
// src/commands/doctor.ts
|
|
1407
|
+
import { homedir as homedir5 } from "os";
|
|
1408
|
+
|
|
1409
|
+
// src/diagnostics/collect-doctor-issues.ts
|
|
1410
|
+
import * as fs11 from "fs/promises";
|
|
1411
|
+
import { join as join8 } from "path";
|
|
1412
|
+
function buildIssue2(code, severity, message, path) {
|
|
1413
|
+
return path === void 0 ? { code, severity, message } : { code, severity, message, path };
|
|
1414
|
+
}
|
|
1415
|
+
async function pathExists2(path) {
|
|
1416
|
+
try {
|
|
1417
|
+
await fs11.access(path);
|
|
1418
|
+
return true;
|
|
1419
|
+
} catch (error) {
|
|
1420
|
+
if (error.code === "ENOENT") {
|
|
1421
|
+
return false;
|
|
1422
|
+
}
|
|
1423
|
+
throw error;
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
async function addUnmanagedDirectoryIssues(entries, issues) {
|
|
1427
|
+
for (const entry of entries) {
|
|
1428
|
+
if (entry.kind !== "unmanaged-directory") {
|
|
1429
|
+
continue;
|
|
1430
|
+
}
|
|
1431
|
+
if (await pathExists2(join8(entry.path, "SKILL.md"))) {
|
|
1432
|
+
issues.push(
|
|
1433
|
+
buildIssue2(
|
|
1434
|
+
"unmanaged-skill-directory",
|
|
1435
|
+
"warning",
|
|
1436
|
+
`Unmanaged skill directory is present for ${entry.agentId}/${entry.skillName}`,
|
|
1437
|
+
entry.path
|
|
1438
|
+
)
|
|
1439
|
+
);
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
async function addMissingManagedSkillIssues(manifest, issues) {
|
|
1444
|
+
for (const skill of Object.values(manifest.skills)) {
|
|
1445
|
+
if (await pathExists2(skill.path)) {
|
|
1446
|
+
continue;
|
|
1447
|
+
}
|
|
1448
|
+
issues.push(
|
|
1449
|
+
buildIssue2(
|
|
1450
|
+
"missing-managed-skill-path",
|
|
1451
|
+
"error",
|
|
1452
|
+
`Managed skill path is missing for ${skill.id}`,
|
|
1453
|
+
skill.path
|
|
1454
|
+
)
|
|
1455
|
+
);
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
function addConflictingAgentPathIssues(agents, issues) {
|
|
1459
|
+
const pathToAgents = /* @__PURE__ */ new Map();
|
|
1460
|
+
for (const agent of agents) {
|
|
1461
|
+
const key = normalizeAbsolutePath(agent.absoluteSkillsDirectoryPath);
|
|
1462
|
+
const current = pathToAgents.get(key) ?? [];
|
|
1463
|
+
current.push(agent);
|
|
1464
|
+
pathToAgents.set(key, current);
|
|
1465
|
+
}
|
|
1466
|
+
for (const conflictedAgents of pathToAgents.values()) {
|
|
1467
|
+
if (conflictedAgents.length < 2) {
|
|
1468
|
+
continue;
|
|
1469
|
+
}
|
|
1470
|
+
const agentIds = conflictedAgents.map((agent) => agent.id).sort((left, right) => left.localeCompare(right));
|
|
1471
|
+
issues.push(
|
|
1472
|
+
buildIssue2(
|
|
1473
|
+
"conflicting-agent-path",
|
|
1474
|
+
"warning",
|
|
1475
|
+
`Multiple agents resolve to the same skills directory: ${agentIds.join(", ")}`,
|
|
1476
|
+
conflictedAgents[0].absoluteSkillsDirectoryPath
|
|
1477
|
+
)
|
|
1478
|
+
);
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
function issueSortKey(issue) {
|
|
1482
|
+
return `${issue.severity}:${issue.code}:${issue.path ?? ""}:${issue.message}`;
|
|
1483
|
+
}
|
|
1484
|
+
function sortIssues(issues) {
|
|
1485
|
+
return [...issues].sort(
|
|
1486
|
+
(left, right) => issueSortKey(left).localeCompare(issueSortKey(right))
|
|
1487
|
+
);
|
|
1488
|
+
}
|
|
1489
|
+
function dedupeAndSortIssues(issues) {
|
|
1490
|
+
const issueByKey = /* @__PURE__ */ new Map();
|
|
1491
|
+
for (const issue of issues) {
|
|
1492
|
+
issueByKey.set(issueSortKey(issue), issue);
|
|
1493
|
+
}
|
|
1494
|
+
return sortIssues([...issueByKey.values()]);
|
|
1495
|
+
}
|
|
1496
|
+
async function collectDoctorIssues(input) {
|
|
1497
|
+
const issues = [];
|
|
1498
|
+
await addUnmanagedDirectoryIssues(input.entries, issues);
|
|
1499
|
+
await addMissingManagedSkillIssues(input.manifest, issues);
|
|
1500
|
+
addConflictingAgentPathIssues(input.agents, issues);
|
|
1501
|
+
return dedupeAndSortIssues(issues);
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
// src/commands/doctor.ts
|
|
1505
|
+
function buildTableOutput4(issues) {
|
|
1506
|
+
if (issues.length === 0) {
|
|
1507
|
+
return "No doctor issues found.\n";
|
|
1508
|
+
}
|
|
1509
|
+
return printTable(
|
|
1510
|
+
issues.map((issue) => ({
|
|
1511
|
+
severity: issue.severity,
|
|
1512
|
+
code: issue.code,
|
|
1513
|
+
path: issue.path ?? "",
|
|
1514
|
+
message: issue.message
|
|
1515
|
+
})),
|
|
1516
|
+
[
|
|
1517
|
+
{ key: "severity", label: "Severity" },
|
|
1518
|
+
{ key: "code", label: "Code" },
|
|
1519
|
+
{ key: "path", label: "Path" },
|
|
1520
|
+
{ key: "message", label: "Message" }
|
|
1521
|
+
]
|
|
1522
|
+
);
|
|
1523
|
+
}
|
|
1524
|
+
function buildJsonOutput(result) {
|
|
1525
|
+
return printJson({
|
|
1526
|
+
skillmuxHome: result.skillmuxHome,
|
|
1527
|
+
issues: result.issues,
|
|
1528
|
+
agents: result.agents.map((agent) => ({
|
|
1529
|
+
id: agent.id,
|
|
1530
|
+
path: agent.absoluteSkillsDirectoryPath,
|
|
1531
|
+
supportedOnPlatform: agent.supportedOnPlatform
|
|
1532
|
+
})),
|
|
1533
|
+
entries: result.entries
|
|
1534
|
+
});
|
|
1535
|
+
}
|
|
1536
|
+
async function runDoctor(options = {}) {
|
|
1537
|
+
const homeDir = options.homeDir ?? homedir5();
|
|
1538
|
+
const resolvedPaths = resolveSkillmuxHome(homeDir);
|
|
1539
|
+
const skillmuxHome = options.skillmuxHome ?? resolvedPaths.skillmuxHome;
|
|
1540
|
+
const [manifest, config, agents] = await Promise.all([
|
|
1541
|
+
readManifest(skillmuxHome),
|
|
1542
|
+
loadUserConfig(skillmuxHome),
|
|
1543
|
+
discoverAgents({
|
|
1544
|
+
homeDir,
|
|
1545
|
+
skillmuxHome,
|
|
1546
|
+
platform: options.platform
|
|
1547
|
+
})
|
|
1548
|
+
]);
|
|
1549
|
+
const entries = [];
|
|
1550
|
+
const issues = [];
|
|
1551
|
+
for (const agent of agents) {
|
|
1552
|
+
const scannedAgent = await scanAgentSkills(agent, skillmuxHome);
|
|
1553
|
+
entries.push(...scannedAgent.entries);
|
|
1554
|
+
issues.push(...scannedAgent.issues);
|
|
1555
|
+
}
|
|
1556
|
+
const doctorIssues = await collectDoctorIssues({
|
|
1557
|
+
manifest,
|
|
1558
|
+
agents,
|
|
1559
|
+
entries
|
|
1560
|
+
});
|
|
1561
|
+
const dedupedIssues = dedupeAndSortIssues([...issues, ...doctorIssues]);
|
|
1562
|
+
const resultWithoutOutput = {
|
|
1563
|
+
skillmuxHome,
|
|
1564
|
+
manifest,
|
|
1565
|
+
config,
|
|
1566
|
+
agents,
|
|
1567
|
+
entries,
|
|
1568
|
+
issues: dedupedIssues
|
|
1569
|
+
};
|
|
1570
|
+
return {
|
|
1571
|
+
...resultWithoutOutput,
|
|
1572
|
+
output: options.json === true ? buildJsonOutput(resultWithoutOutput) : buildTableOutput4(dedupedIssues)
|
|
1573
|
+
};
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
// src/commands/disable.ts
|
|
1577
|
+
import * as fs13 from "fs/promises";
|
|
1578
|
+
import { homedir as homedir6 } from "os";
|
|
1579
|
+
import { join as join9, resolve as resolve9 } from "path";
|
|
1580
|
+
|
|
1581
|
+
// src/fs/safe-remove-link.ts
|
|
1582
|
+
import * as fs12 from "fs/promises";
|
|
1094
1583
|
async function safeRemoveLink(path) {
|
|
1095
1584
|
try {
|
|
1096
|
-
const entry = await
|
|
1585
|
+
const entry = await fs12.lstat(path);
|
|
1097
1586
|
if (!entry.isSymbolicLink()) {
|
|
1098
1587
|
return false;
|
|
1099
1588
|
}
|
|
1100
|
-
await
|
|
1589
|
+
await fs12.rm(path, { recursive: true, force: false });
|
|
1101
1590
|
return true;
|
|
1102
1591
|
} catch (error) {
|
|
1103
1592
|
if (error.code === "ENOENT") {
|
|
@@ -1142,7 +1631,7 @@ function buildManagedSkillPath2(skillmuxHome, skillId) {
|
|
|
1142
1631
|
}
|
|
1143
1632
|
async function tryAdoptManagedSkill(manifest, skillmuxHome, skillId, skillName, linkPath, timestamp) {
|
|
1144
1633
|
try {
|
|
1145
|
-
const entry = await
|
|
1634
|
+
const entry = await fs13.lstat(linkPath);
|
|
1146
1635
|
if (!entry.isSymbolicLink()) {
|
|
1147
1636
|
return void 0;
|
|
1148
1637
|
}
|
|
@@ -1152,7 +1641,7 @@ async function tryAdoptManagedSkill(manifest, skillmuxHome, skillId, skillName,
|
|
|
1152
1641
|
}
|
|
1153
1642
|
throw error;
|
|
1154
1643
|
}
|
|
1155
|
-
const sourcePath = await
|
|
1644
|
+
const sourcePath = await fs13.realpath(linkPath);
|
|
1156
1645
|
await assertSkillSourceLayout(sourcePath);
|
|
1157
1646
|
const managedSkillPath = buildManagedSkillPath2(skillmuxHome, skillId);
|
|
1158
1647
|
await copySkillContentsToManagedStore(sourcePath, managedSkillPath);
|
|
@@ -1181,9 +1670,9 @@ async function resolveTargetAgent2(homeDir, skillmuxHome, agentName) {
|
|
|
1181
1670
|
}
|
|
1182
1671
|
return agent;
|
|
1183
1672
|
}
|
|
1184
|
-
async function
|
|
1673
|
+
async function pathExists3(path) {
|
|
1185
1674
|
try {
|
|
1186
|
-
await
|
|
1675
|
+
await fs13.lstat(path);
|
|
1187
1676
|
return true;
|
|
1188
1677
|
} catch (error) {
|
|
1189
1678
|
if (error.code === "ENOENT") {
|
|
@@ -1196,14 +1685,14 @@ async function runDisableSingle(options) {
|
|
|
1196
1685
|
if (options.agent === void 0) {
|
|
1197
1686
|
throw new Error("Disable requires one target agent");
|
|
1198
1687
|
}
|
|
1199
|
-
const homeDir = options.homeDir ??
|
|
1688
|
+
const homeDir = options.homeDir ?? homedir6();
|
|
1200
1689
|
const { skillmuxHome: defaultSkillmuxHome } = resolveSkillmuxHome(homeDir);
|
|
1201
1690
|
const skillmuxHome = options.skillmuxHome ?? defaultSkillmuxHome;
|
|
1202
1691
|
const timestamp = (options.now ?? /* @__PURE__ */ new Date()).toISOString();
|
|
1203
1692
|
const manifest = await readManifest(skillmuxHome);
|
|
1204
1693
|
const skillId = normalizeId(options.skill);
|
|
1205
1694
|
const agent = await resolveTargetAgent2(homeDir, skillmuxHome, options.agent);
|
|
1206
|
-
const linkPath =
|
|
1695
|
+
const linkPath = join9(agent.absoluteSkillsDirectoryPath, skillId);
|
|
1207
1696
|
const adoption = manifest.skills[skillId] ? void 0 : await tryAdoptManagedSkill(
|
|
1208
1697
|
manifest,
|
|
1209
1698
|
skillmuxHome,
|
|
@@ -1224,7 +1713,7 @@ async function runDisableSingle(options) {
|
|
|
1224
1713
|
manifest.agents[agent.id] = agentRecord;
|
|
1225
1714
|
const adoptedLinkRemoved = adoption !== void 0 ? await safeRemoveLink(linkPath) : false;
|
|
1226
1715
|
const linkMatchesSkill = adoption === void 0 ? await isLinkPointingToTarget(activationLinkPath, skill.path) : false;
|
|
1227
|
-
if (adoption === void 0 && !linkMatchesSkill && await
|
|
1716
|
+
if (adoption === void 0 && !linkMatchesSkill && await pathExists3(activationLinkPath)) {
|
|
1228
1717
|
throw new Error(`Refusing to disable non-managed entry at ${linkPath}`);
|
|
1229
1718
|
}
|
|
1230
1719
|
const removedLink = adoptedLinkRemoved ? true : linkMatchesSkill ? await safeRemoveLink(activationLinkPath) : false;
|
|
@@ -1286,9 +1775,9 @@ async function runDisable(options) {
|
|
|
1286
1775
|
}
|
|
1287
1776
|
|
|
1288
1777
|
// src/commands/enable.ts
|
|
1289
|
-
import * as
|
|
1290
|
-
import { homedir as
|
|
1291
|
-
import { join as
|
|
1778
|
+
import * as fs14 from "fs/promises";
|
|
1779
|
+
import { homedir as homedir7 } from "os";
|
|
1780
|
+
import { join as join10 } from "path";
|
|
1292
1781
|
function buildAgentRecord3(agent, timestamp) {
|
|
1293
1782
|
return {
|
|
1294
1783
|
id: agent.id,
|
|
@@ -1334,7 +1823,7 @@ async function runEnableSingle(options) {
|
|
|
1334
1823
|
if (options.agent === void 0) {
|
|
1335
1824
|
throw new Error("Enable requires one target agent");
|
|
1336
1825
|
}
|
|
1337
|
-
const homeDir = options.homeDir ??
|
|
1826
|
+
const homeDir = options.homeDir ?? homedir7();
|
|
1338
1827
|
const { skillmuxHome: defaultSkillmuxHome } = resolveSkillmuxHome(homeDir);
|
|
1339
1828
|
const skillmuxHome = options.skillmuxHome ?? defaultSkillmuxHome;
|
|
1340
1829
|
const timestamp = (options.now ?? /* @__PURE__ */ new Date()).toISOString();
|
|
@@ -1345,13 +1834,13 @@ async function runEnableSingle(options) {
|
|
|
1345
1834
|
throw new Error(`Managed skill not found: ${skillId}`);
|
|
1346
1835
|
}
|
|
1347
1836
|
const agent = await resolveTargetAgent3(homeDir, skillmuxHome, options.agent);
|
|
1348
|
-
const linkPath =
|
|
1837
|
+
const linkPath = join10(agent.absoluteSkillsDirectoryPath, skill.id);
|
|
1349
1838
|
const currentActivation = manifest.activations.find(
|
|
1350
1839
|
(entry) => entry.skillId === skill.id && entry.agentId === agent.id
|
|
1351
1840
|
);
|
|
1352
1841
|
const agentRecord = buildAgentRecord3(agent, timestamp);
|
|
1353
1842
|
manifest.agents[agent.id] = agentRecord;
|
|
1354
|
-
await
|
|
1843
|
+
await fs14.mkdir(agent.absoluteSkillsDirectoryPath, { recursive: true });
|
|
1355
1844
|
const linkAlreadyEnabled = await isLinkPointingToTarget(linkPath, skill.path);
|
|
1356
1845
|
const activationAlreadyEnabled = currentActivation?.state === "enabled" && currentActivation.linkPath === linkPath;
|
|
1357
1846
|
if (linkAlreadyEnabled && activationAlreadyEnabled) {
|
|
@@ -1418,8 +1907,48 @@ async function runEnable(options) {
|
|
|
1418
1907
|
return runEnableSingle(options);
|
|
1419
1908
|
}
|
|
1420
1909
|
|
|
1910
|
+
// src/commands/import.ts
|
|
1911
|
+
import { resolve as resolve10 } from "path";
|
|
1912
|
+
import { homedir as homedir8 } from "os";
|
|
1913
|
+
function buildManagedSkillPath3(skillmuxHome, skillId) {
|
|
1914
|
+
return resolve10(skillmuxHome, "skills", skillId);
|
|
1915
|
+
}
|
|
1916
|
+
async function runImport(options) {
|
|
1917
|
+
const homeDir = options.homeDir ?? homedir8();
|
|
1918
|
+
const resolvedPaths = resolveSkillmuxHome(homeDir);
|
|
1919
|
+
const skillmuxHome = options.skillmuxHome ?? resolvedPaths.skillmuxHome;
|
|
1920
|
+
const sourcePath = resolve10(options.sourcePath);
|
|
1921
|
+
const skillId = normalizeId(options.skillName);
|
|
1922
|
+
const importedAt = (options.now ?? /* @__PURE__ */ new Date()).toISOString();
|
|
1923
|
+
const manifest = await readManifest(skillmuxHome);
|
|
1924
|
+
const managedSkillPath = buildManagedSkillPath3(skillmuxHome, skillId);
|
|
1925
|
+
await assertSkillSourceLayout(sourcePath);
|
|
1926
|
+
if (manifest.skills[skillId] !== void 0) {
|
|
1927
|
+
throw new Error(`Managed skill already exists for ${skillId}`);
|
|
1928
|
+
}
|
|
1929
|
+
await copySkillContentsToManagedStore(sourcePath, managedSkillPath);
|
|
1930
|
+
const skill = {
|
|
1931
|
+
id: skillId,
|
|
1932
|
+
name: options.skillName,
|
|
1933
|
+
path: managedSkillPath,
|
|
1934
|
+
source: {
|
|
1935
|
+
kind: "local",
|
|
1936
|
+
path: sourcePath
|
|
1937
|
+
},
|
|
1938
|
+
importedAt
|
|
1939
|
+
};
|
|
1940
|
+
manifest.skills[skillId] = skill;
|
|
1941
|
+
await writeManifest(skillmuxHome, manifest);
|
|
1942
|
+
return {
|
|
1943
|
+
skill,
|
|
1944
|
+
manifest,
|
|
1945
|
+
output: `Imported ${skillId} to ${managedSkillPath}
|
|
1946
|
+
`
|
|
1947
|
+
};
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1421
1950
|
// src/commands/scan.ts
|
|
1422
|
-
import { homedir as
|
|
1951
|
+
import { homedir as homedir9 } from "os";
|
|
1423
1952
|
|
|
1424
1953
|
// src/output/format-issue.ts
|
|
1425
1954
|
function formatIssue(issue) {
|
|
@@ -1429,26 +1958,6 @@ function formatIssue(issue) {
|
|
|
1429
1958
|
return `[${issue.severity}] ${issue.code} @ ${issue.path}: ${issue.message}`;
|
|
1430
1959
|
}
|
|
1431
1960
|
|
|
1432
|
-
// src/output/print-table.ts
|
|
1433
|
-
function printTable(rows, columns) {
|
|
1434
|
-
const renderedRows = rows.map(
|
|
1435
|
-
(row) => columns.map((column) => String(row[column.key] ?? ""))
|
|
1436
|
-
);
|
|
1437
|
-
const widths = columns.map(
|
|
1438
|
-
(column, index) => Math.max(
|
|
1439
|
-
column.label.length,
|
|
1440
|
-
...renderedRows.map((row) => row[index]?.length ?? 0)
|
|
1441
|
-
)
|
|
1442
|
-
);
|
|
1443
|
-
const header = columns.map((column, index) => column.label.padEnd(widths[index])).join(" ");
|
|
1444
|
-
const separator = widths.map((width) => "-".repeat(width)).join(" ");
|
|
1445
|
-
const body = renderedRows.map(
|
|
1446
|
-
(row) => row.map((cell, index) => cell.padEnd(widths[index])).join(" ")
|
|
1447
|
-
);
|
|
1448
|
-
return `${[header, separator, ...body].join("\n")}
|
|
1449
|
-
`;
|
|
1450
|
-
}
|
|
1451
|
-
|
|
1452
1961
|
// src/commands/scan.ts
|
|
1453
1962
|
function buildAgentRecord4(agent, timestamp, previousRecord) {
|
|
1454
1963
|
const lastSeenAt = agent.exists ? timestamp : previousRecord?.lastSeenAt ?? null;
|
|
@@ -1500,7 +2009,7 @@ ${result.issues.map(formatIssue).join("\n")}
|
|
|
1500
2009
|
`;
|
|
1501
2010
|
}
|
|
1502
2011
|
async function runScan(options = {}) {
|
|
1503
|
-
const homeDir = options.homeDir ??
|
|
2012
|
+
const homeDir = options.homeDir ?? homedir9();
|
|
1504
2013
|
const resolvedPaths = resolveSkillmuxHome(homeDir);
|
|
1505
2014
|
const skillmuxHome = options.skillmuxHome ?? resolvedPaths.skillmuxHome;
|
|
1506
2015
|
const manifest = await readManifest(skillmuxHome);
|
|
@@ -1540,17 +2049,17 @@ async function runScan(options = {}) {
|
|
|
1540
2049
|
}
|
|
1541
2050
|
|
|
1542
2051
|
// src/commands/remove.ts
|
|
1543
|
-
import * as
|
|
1544
|
-
import { homedir as
|
|
1545
|
-
import { resolve as
|
|
1546
|
-
function
|
|
1547
|
-
return
|
|
2052
|
+
import * as fs15 from "fs/promises";
|
|
2053
|
+
import { homedir as homedir10 } from "os";
|
|
2054
|
+
import { resolve as resolve11 } from "path";
|
|
2055
|
+
function buildManagedSkillPath4(skillmuxHome, skillId) {
|
|
2056
|
+
return resolve11(skillmuxHome, "skills", skillId);
|
|
1548
2057
|
}
|
|
1549
2058
|
function buildManifestPath(skillmuxHome) {
|
|
1550
|
-
return
|
|
2059
|
+
return resolve11(skillmuxHome, "manifest.json");
|
|
1551
2060
|
}
|
|
1552
2061
|
function buildConfigPath2(skillmuxHome) {
|
|
1553
|
-
return
|
|
2062
|
+
return resolve11(skillmuxHome, "config.json");
|
|
1554
2063
|
}
|
|
1555
2064
|
function resolveManagedSkill(manifest, skillNameOrId) {
|
|
1556
2065
|
const skillId = normalizeId(skillNameOrId);
|
|
@@ -1576,7 +2085,7 @@ function buildHumanOutput(skill, managedSkillPath) {
|
|
|
1576
2085
|
return `Removed ${skill.id} from ${managedSkillPath}
|
|
1577
2086
|
`;
|
|
1578
2087
|
}
|
|
1579
|
-
function
|
|
2088
|
+
function buildJsonOutput2(result) {
|
|
1580
2089
|
return printJson({
|
|
1581
2090
|
changed: result.changed,
|
|
1582
2091
|
removedSkillId: result.removedSkillId,
|
|
@@ -1585,9 +2094,9 @@ function buildJsonOutput(result) {
|
|
|
1585
2094
|
manifest: result.manifest
|
|
1586
2095
|
});
|
|
1587
2096
|
}
|
|
1588
|
-
async function
|
|
2097
|
+
async function pathExists4(path) {
|
|
1589
2098
|
try {
|
|
1590
|
-
await
|
|
2099
|
+
await fs15.lstat(path);
|
|
1591
2100
|
return true;
|
|
1592
2101
|
} catch (error) {
|
|
1593
2102
|
if (error.code === "ENOENT") {
|
|
@@ -1597,15 +2106,15 @@ async function pathExists3(path) {
|
|
|
1597
2106
|
}
|
|
1598
2107
|
}
|
|
1599
2108
|
async function assertManagedSkillRemovalSafety(skillmuxHome, skillPath, skillId) {
|
|
1600
|
-
const expectedSkillPath =
|
|
2109
|
+
const expectedSkillPath = buildManagedSkillPath4(skillmuxHome, skillId);
|
|
1601
2110
|
if (!pathsAreEqual(skillPath, expectedSkillPath)) {
|
|
1602
2111
|
throw new Error(`Refusing to remove unmanaged skill path at ${skillPath}`);
|
|
1603
2112
|
}
|
|
1604
2113
|
await assertNoSymlinkAncestors(skillPath, { includeLeaf: true });
|
|
1605
|
-
if (!await
|
|
2114
|
+
if (!await pathExists4(skillPath)) {
|
|
1606
2115
|
return;
|
|
1607
2116
|
}
|
|
1608
|
-
const entry = await
|
|
2117
|
+
const entry = await fs15.lstat(skillPath);
|
|
1609
2118
|
if (entry.isSymbolicLink()) {
|
|
1610
2119
|
throw new Error(`Refusing to remove symlinked managed skill path at ${skillPath}`);
|
|
1611
2120
|
}
|
|
@@ -1617,14 +2126,14 @@ async function runRemoveSingle(options) {
|
|
|
1617
2126
|
if (options.skill === void 0) {
|
|
1618
2127
|
throw new Error("Remove requires one target skill");
|
|
1619
2128
|
}
|
|
1620
|
-
const homeDir = options.homeDir ??
|
|
2129
|
+
const homeDir = options.homeDir ?? homedir10();
|
|
1621
2130
|
const { skillmuxHome: defaultSkillmuxHome } = resolveSkillmuxHome(homeDir);
|
|
1622
2131
|
const skillmuxHome = options.skillmuxHome ?? defaultSkillmuxHome;
|
|
1623
2132
|
const manifestPath = buildManifestPath(skillmuxHome);
|
|
1624
2133
|
const configPath = buildConfigPath2(skillmuxHome);
|
|
1625
2134
|
const manifest = await readManifest(skillmuxHome);
|
|
1626
2135
|
const skill = resolveManagedSkill(manifest, options.skill);
|
|
1627
|
-
const managedSkillsDirectory =
|
|
2136
|
+
const managedSkillsDirectory = resolve11(skillmuxHome, "skills");
|
|
1628
2137
|
const managedSkillPath = skill.path;
|
|
1629
2138
|
const enabledActivations = manifest.activations.filter(
|
|
1630
2139
|
(activation) => activation.skillId === skill.id && activation.state === "enabled"
|
|
@@ -1638,8 +2147,8 @@ async function runRemoveSingle(options) {
|
|
|
1638
2147
|
);
|
|
1639
2148
|
}
|
|
1640
2149
|
await assertManagedSkillRemovalSafety(skillmuxHome, managedSkillPath, skill.id);
|
|
1641
|
-
if (await
|
|
1642
|
-
await
|
|
2150
|
+
if (await pathExists4(managedSkillPath)) {
|
|
2151
|
+
await fs15.rm(managedSkillPath, { recursive: true, force: false });
|
|
1643
2152
|
}
|
|
1644
2153
|
delete manifest.skills[skill.id];
|
|
1645
2154
|
manifest.activations = manifest.activations.filter(
|
|
@@ -1661,7 +2170,7 @@ async function runRemoveSingle(options) {
|
|
|
1661
2170
|
};
|
|
1662
2171
|
return {
|
|
1663
2172
|
...resultWithoutOutput,
|
|
1664
|
-
output: options.json === true ?
|
|
2173
|
+
output: options.json === true ? buildJsonOutput2(resultWithoutOutput) : buildHumanOutput(skill, managedSkillPath)
|
|
1665
2174
|
};
|
|
1666
2175
|
}
|
|
1667
2176
|
async function runRemove(options) {
|
|
@@ -1699,128 +2208,32 @@ async function runRemove(options) {
|
|
|
1699
2208
|
return runRemoveSingle(options);
|
|
1700
2209
|
}
|
|
1701
2210
|
|
|
1702
|
-
// src/diagnostics/collect-doctor-issues.ts
|
|
1703
|
-
import * as fs14 from "fs/promises";
|
|
1704
|
-
import { join as join10 } from "path";
|
|
1705
|
-
function buildIssue2(code, severity, message, path) {
|
|
1706
|
-
return path === void 0 ? { code, severity, message } : { code, severity, message, path };
|
|
1707
|
-
}
|
|
1708
|
-
async function pathExists4(path) {
|
|
1709
|
-
try {
|
|
1710
|
-
await fs14.access(path);
|
|
1711
|
-
return true;
|
|
1712
|
-
} catch (error) {
|
|
1713
|
-
if (error.code === "ENOENT") {
|
|
1714
|
-
return false;
|
|
1715
|
-
}
|
|
1716
|
-
throw error;
|
|
1717
|
-
}
|
|
1718
|
-
}
|
|
1719
|
-
async function addUnmanagedDirectoryIssues(entries, issues) {
|
|
1720
|
-
for (const entry of entries) {
|
|
1721
|
-
if (entry.kind !== "unmanaged-directory") {
|
|
1722
|
-
continue;
|
|
1723
|
-
}
|
|
1724
|
-
if (await pathExists4(join10(entry.path, "SKILL.md"))) {
|
|
1725
|
-
issues.push(
|
|
1726
|
-
buildIssue2(
|
|
1727
|
-
"unmanaged-skill-directory",
|
|
1728
|
-
"warning",
|
|
1729
|
-
`Unmanaged skill directory is present for ${entry.agentId}/${entry.skillName}`,
|
|
1730
|
-
entry.path
|
|
1731
|
-
)
|
|
1732
|
-
);
|
|
1733
|
-
}
|
|
1734
|
-
}
|
|
1735
|
-
}
|
|
1736
|
-
async function addMissingManagedSkillIssues(manifest, issues) {
|
|
1737
|
-
for (const skill of Object.values(manifest.skills)) {
|
|
1738
|
-
if (await pathExists4(skill.path)) {
|
|
1739
|
-
continue;
|
|
1740
|
-
}
|
|
1741
|
-
issues.push(
|
|
1742
|
-
buildIssue2(
|
|
1743
|
-
"missing-managed-skill-path",
|
|
1744
|
-
"error",
|
|
1745
|
-
`Managed skill path is missing for ${skill.id}`,
|
|
1746
|
-
skill.path
|
|
1747
|
-
)
|
|
1748
|
-
);
|
|
1749
|
-
}
|
|
1750
|
-
}
|
|
1751
|
-
function addConflictingAgentPathIssues(agents, issues) {
|
|
1752
|
-
const pathToAgents = /* @__PURE__ */ new Map();
|
|
1753
|
-
for (const agent of agents) {
|
|
1754
|
-
const key = normalizeAbsolutePath(agent.absoluteSkillsDirectoryPath);
|
|
1755
|
-
const current = pathToAgents.get(key) ?? [];
|
|
1756
|
-
current.push(agent);
|
|
1757
|
-
pathToAgents.set(key, current);
|
|
1758
|
-
}
|
|
1759
|
-
for (const conflictedAgents of pathToAgents.values()) {
|
|
1760
|
-
if (conflictedAgents.length < 2) {
|
|
1761
|
-
continue;
|
|
1762
|
-
}
|
|
1763
|
-
const agentIds = conflictedAgents.map((agent) => agent.id).sort((left, right) => left.localeCompare(right));
|
|
1764
|
-
issues.push(
|
|
1765
|
-
buildIssue2(
|
|
1766
|
-
"conflicting-agent-path",
|
|
1767
|
-
"warning",
|
|
1768
|
-
`Multiple agents resolve to the same skills directory: ${agentIds.join(", ")}`,
|
|
1769
|
-
conflictedAgents[0].absoluteSkillsDirectoryPath
|
|
1770
|
-
)
|
|
1771
|
-
);
|
|
1772
|
-
}
|
|
1773
|
-
}
|
|
1774
|
-
function issueSortKey(issue) {
|
|
1775
|
-
return `${issue.severity}:${issue.code}:${issue.path ?? ""}:${issue.message}`;
|
|
1776
|
-
}
|
|
1777
|
-
function sortIssues(issues) {
|
|
1778
|
-
return [...issues].sort(
|
|
1779
|
-
(left, right) => issueSortKey(left).localeCompare(issueSortKey(right))
|
|
1780
|
-
);
|
|
1781
|
-
}
|
|
1782
|
-
function dedupeAndSortIssues(issues) {
|
|
1783
|
-
const issueByKey = /* @__PURE__ */ new Map();
|
|
1784
|
-
for (const issue of issues) {
|
|
1785
|
-
issueByKey.set(issueSortKey(issue), issue);
|
|
1786
|
-
}
|
|
1787
|
-
return sortIssues([...issueByKey.values()]);
|
|
1788
|
-
}
|
|
1789
|
-
async function collectDoctorIssues(input) {
|
|
1790
|
-
const issues = [];
|
|
1791
|
-
await addUnmanagedDirectoryIssues(input.entries, issues);
|
|
1792
|
-
await addMissingManagedSkillIssues(input.manifest, issues);
|
|
1793
|
-
addConflictingAgentPathIssues(input.agents, issues);
|
|
1794
|
-
return dedupeAndSortIssues(issues);
|
|
1795
|
-
}
|
|
1796
|
-
|
|
1797
2211
|
export {
|
|
1798
2212
|
supportedPlatforms,
|
|
1799
|
-
InvalidIdentifierError,
|
|
1800
2213
|
ManifestValidationError,
|
|
1801
|
-
UserConfigValidationError,
|
|
1802
|
-
normalizeId,
|
|
1803
2214
|
buildConfigPath,
|
|
1804
2215
|
resolveSkillmuxHome,
|
|
1805
2216
|
loadUserConfig,
|
|
1806
2217
|
discoverAgents,
|
|
1807
2218
|
isPathInside,
|
|
1808
2219
|
scanAgentSkills,
|
|
1809
|
-
assertSkillSourceLayout,
|
|
1810
|
-
copySkillContentsToManagedStore,
|
|
1811
2220
|
buildEmptyManifest,
|
|
1812
2221
|
manifestSchema,
|
|
1813
|
-
writeManifest,
|
|
1814
2222
|
formatValidationIssues2 as formatValidationIssues,
|
|
1815
|
-
readManifest,
|
|
1816
2223
|
printJson,
|
|
1817
2224
|
runAdopt,
|
|
1818
2225
|
printTable,
|
|
2226
|
+
normalizeAgentId,
|
|
2227
|
+
runConfigAddAgent,
|
|
2228
|
+
runConfigRemoveAgent,
|
|
2229
|
+
runConfigUpdateAgent,
|
|
1819
2230
|
dedupeAndSortIssues,
|
|
1820
2231
|
collectDoctorIssues,
|
|
2232
|
+
runDoctor,
|
|
1821
2233
|
runDisable,
|
|
1822
2234
|
runEnable,
|
|
2235
|
+
runImport,
|
|
1823
2236
|
runScan,
|
|
1824
2237
|
runRemove
|
|
1825
2238
|
};
|
|
1826
|
-
//# sourceMappingURL=chunk-
|
|
2239
|
+
//# sourceMappingURL=chunk-EEIOA7GC.js.map
|