opencode-swarm-plugin 0.12.22 → 0.12.24
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/bin/swarm.ts +153 -2
- package/package.json +1 -1
package/bin/swarm.ts
CHANGED
|
@@ -623,6 +623,66 @@ async function doctor() {
|
|
|
623
623
|
const requiredMissing = required.filter((r) => !r.available);
|
|
624
624
|
const optionalMissing = optional.filter((r) => !r.available);
|
|
625
625
|
|
|
626
|
+
// Check skills
|
|
627
|
+
p.log.step("Skills:");
|
|
628
|
+
const configDir = join(homedir(), ".config", "opencode");
|
|
629
|
+
const globalSkillsPath = join(configDir, "skills");
|
|
630
|
+
const bundledSkillsPath = join(__dirname, "..", "global-skills");
|
|
631
|
+
|
|
632
|
+
// Global skills directory
|
|
633
|
+
if (existsSync(globalSkillsPath)) {
|
|
634
|
+
try {
|
|
635
|
+
const { readdirSync } = require("fs");
|
|
636
|
+
const skills = readdirSync(globalSkillsPath, { withFileTypes: true })
|
|
637
|
+
.filter((d: { isDirectory: () => boolean }) => d.isDirectory())
|
|
638
|
+
.map((d: { name: string }) => d.name);
|
|
639
|
+
if (skills.length > 0) {
|
|
640
|
+
p.log.success(`Global skills (${skills.length}): ${skills.join(", ")}`);
|
|
641
|
+
} else {
|
|
642
|
+
p.log.warn("Global skills directory exists but is empty");
|
|
643
|
+
}
|
|
644
|
+
} catch {
|
|
645
|
+
p.log.warn("Global skills directory: " + globalSkillsPath);
|
|
646
|
+
}
|
|
647
|
+
} else {
|
|
648
|
+
p.log.warn("No global skills directory (run 'swarm setup' to create)");
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// Bundled skills
|
|
652
|
+
if (existsSync(bundledSkillsPath)) {
|
|
653
|
+
try {
|
|
654
|
+
const { readdirSync } = require("fs");
|
|
655
|
+
const bundled = readdirSync(bundledSkillsPath, { withFileTypes: true })
|
|
656
|
+
.filter((d: { isDirectory: () => boolean }) => d.isDirectory())
|
|
657
|
+
.map((d: { name: string }) => d.name);
|
|
658
|
+
p.log.success(
|
|
659
|
+
`Bundled skills (${bundled.length}): ${bundled.join(", ")}`,
|
|
660
|
+
);
|
|
661
|
+
} catch {
|
|
662
|
+
p.log.warn("Could not read bundled skills");
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// Project skills (check current directory)
|
|
667
|
+
const projectSkillsDirs = [".opencode/skills", ".claude/skills", "skills"];
|
|
668
|
+
for (const dir of projectSkillsDirs) {
|
|
669
|
+
if (existsSync(dir)) {
|
|
670
|
+
try {
|
|
671
|
+
const { readdirSync } = require("fs");
|
|
672
|
+
const skills = readdirSync(dir, { withFileTypes: true })
|
|
673
|
+
.filter((d: { isDirectory: () => boolean }) => d.isDirectory())
|
|
674
|
+
.map((d: { name: string }) => d.name);
|
|
675
|
+
if (skills.length > 0) {
|
|
676
|
+
p.log.success(
|
|
677
|
+
`Project skills in ${dir}/ (${skills.length}): ${skills.join(", ")}`,
|
|
678
|
+
);
|
|
679
|
+
}
|
|
680
|
+
} catch {
|
|
681
|
+
// Ignore
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
626
686
|
if (requiredMissing.length > 0) {
|
|
627
687
|
p.outro(
|
|
628
688
|
"Missing " +
|
|
@@ -977,7 +1037,8 @@ async function setup() {
|
|
|
977
1037
|
p.log.step("Setting up OpenCode integration...");
|
|
978
1038
|
|
|
979
1039
|
// Create directories if needed
|
|
980
|
-
|
|
1040
|
+
const skillsDir = join(configDir, "skills");
|
|
1041
|
+
for (const dir of [pluginDir, commandDir, agentDir, skillsDir]) {
|
|
981
1042
|
if (!existsSync(dir)) {
|
|
982
1043
|
mkdirSync(dir, { recursive: true });
|
|
983
1044
|
}
|
|
@@ -995,8 +1056,24 @@ async function setup() {
|
|
|
995
1056
|
writeFileSync(workerAgentPath, getWorkerAgent(workerModel as string));
|
|
996
1057
|
p.log.success("Worker agent: " + workerAgentPath);
|
|
997
1058
|
|
|
1059
|
+
p.log.success("Skills directory: " + skillsDir);
|
|
1060
|
+
|
|
1061
|
+
// Show bundled skills info
|
|
1062
|
+
const bundledSkillsPath = join(__dirname, "..", "global-skills");
|
|
1063
|
+
if (existsSync(bundledSkillsPath)) {
|
|
1064
|
+
try {
|
|
1065
|
+
const { readdirSync } = require("fs");
|
|
1066
|
+
const bundled = readdirSync(bundledSkillsPath, { withFileTypes: true })
|
|
1067
|
+
.filter((d: { isDirectory: () => boolean }) => d.isDirectory())
|
|
1068
|
+
.map((d: { name: string }) => d.name);
|
|
1069
|
+
p.log.message(dim(" Bundled skills: " + bundled.join(", ")));
|
|
1070
|
+
} catch {
|
|
1071
|
+
// Ignore
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
|
|
998
1075
|
p.note(
|
|
999
|
-
'cd your-project\nbd init\nopencode\n/swarm "your task"',
|
|
1076
|
+
'cd your-project\nbd init\nopencode\n/swarm "your task"\n\nSkills: Use skills_list to see available skills',
|
|
1000
1077
|
"Next steps",
|
|
1001
1078
|
);
|
|
1002
1079
|
|
|
@@ -1078,6 +1155,25 @@ async function init() {
|
|
|
1078
1155
|
}
|
|
1079
1156
|
}
|
|
1080
1157
|
|
|
1158
|
+
// Offer to create project skills directory
|
|
1159
|
+
const createSkillsDir = await p.confirm({
|
|
1160
|
+
message: "Create project skills directory (.opencode/skills/)?",
|
|
1161
|
+
initialValue: false,
|
|
1162
|
+
});
|
|
1163
|
+
|
|
1164
|
+
if (!p.isCancel(createSkillsDir) && createSkillsDir) {
|
|
1165
|
+
const skillsPath = ".opencode/skills";
|
|
1166
|
+
if (!existsSync(skillsPath)) {
|
|
1167
|
+
mkdirSync(skillsPath, { recursive: true });
|
|
1168
|
+
p.log.success("Created " + skillsPath + "/");
|
|
1169
|
+
p.log.message(
|
|
1170
|
+
dim(" Add SKILL.md files here for project-specific skills"),
|
|
1171
|
+
);
|
|
1172
|
+
} else {
|
|
1173
|
+
p.log.warn(skillsPath + "/ already exists");
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1081
1177
|
p.outro("Project initialized! Use '/swarm' in OpenCode to get started.");
|
|
1082
1178
|
} else {
|
|
1083
1179
|
s.stop("Failed to initialize beads");
|
|
@@ -1106,6 +1202,7 @@ function config() {
|
|
|
1106
1202
|
const commandPath = join(configDir, "command", "swarm.md");
|
|
1107
1203
|
const plannerAgentPath = join(configDir, "agent", "swarm-planner.md");
|
|
1108
1204
|
const workerAgentPath = join(configDir, "agent", "swarm-worker.md");
|
|
1205
|
+
const globalSkillsPath = join(configDir, "skills");
|
|
1109
1206
|
|
|
1110
1207
|
console.log(yellow(BANNER));
|
|
1111
1208
|
console.log(dim(" " + TAGLINE + " v" + VERSION));
|
|
@@ -1129,6 +1226,60 @@ function config() {
|
|
|
1129
1226
|
console.log();
|
|
1130
1227
|
}
|
|
1131
1228
|
|
|
1229
|
+
// Skills section
|
|
1230
|
+
console.log(cyan("Skills:"));
|
|
1231
|
+
console.log();
|
|
1232
|
+
|
|
1233
|
+
// Global skills directory
|
|
1234
|
+
const globalSkillsExists = existsSync(globalSkillsPath);
|
|
1235
|
+
const globalStatus = globalSkillsExists ? "✓" : "✗";
|
|
1236
|
+
const globalColor = globalSkillsExists ? "\x1b[32m" : "\x1b[31m";
|
|
1237
|
+
console.log(` 📚 Global skills directory`);
|
|
1238
|
+
console.log(
|
|
1239
|
+
` ${globalColor}${globalStatus}\x1b[0m ${dim(globalSkillsPath)}`,
|
|
1240
|
+
);
|
|
1241
|
+
|
|
1242
|
+
// Count skills if directory exists
|
|
1243
|
+
if (globalSkillsExists) {
|
|
1244
|
+
try {
|
|
1245
|
+
const { readdirSync } = require("fs");
|
|
1246
|
+
const skills = readdirSync(globalSkillsPath, { withFileTypes: true })
|
|
1247
|
+
.filter((d: { isDirectory: () => boolean }) => d.isDirectory())
|
|
1248
|
+
.map((d: { name: string }) => d.name);
|
|
1249
|
+
if (skills.length > 0) {
|
|
1250
|
+
console.log(
|
|
1251
|
+
` ${dim(`Found ${skills.length} skill(s): ${skills.join(", ")}`)}`,
|
|
1252
|
+
);
|
|
1253
|
+
}
|
|
1254
|
+
} catch {
|
|
1255
|
+
// Ignore errors
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
console.log();
|
|
1259
|
+
|
|
1260
|
+
// Project skills locations
|
|
1261
|
+
console.log(` 📁 Project skills locations ${dim("(checked in order)")}`);
|
|
1262
|
+
console.log(` ${dim(".opencode/skills/")}`);
|
|
1263
|
+
console.log(` ${dim(".claude/skills/")}`);
|
|
1264
|
+
console.log(` ${dim("skills/")}`);
|
|
1265
|
+
console.log();
|
|
1266
|
+
|
|
1267
|
+
// Bundled skills info
|
|
1268
|
+
const bundledSkillsPath = join(__dirname, "..", "global-skills");
|
|
1269
|
+
if (existsSync(bundledSkillsPath)) {
|
|
1270
|
+
try {
|
|
1271
|
+
const { readdirSync } = require("fs");
|
|
1272
|
+
const bundled = readdirSync(bundledSkillsPath, { withFileTypes: true })
|
|
1273
|
+
.filter((d: { isDirectory: () => boolean }) => d.isDirectory())
|
|
1274
|
+
.map((d: { name: string }) => d.name);
|
|
1275
|
+
console.log(` 🎁 Bundled skills ${dim("(always available)")}`);
|
|
1276
|
+
console.log(` ${dim(bundled.join(", "))}`);
|
|
1277
|
+
console.log();
|
|
1278
|
+
} catch {
|
|
1279
|
+
// Ignore errors
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1132
1283
|
console.log(dim("Edit these files to customize swarm behavior."));
|
|
1133
1284
|
console.log(dim("Run 'swarm setup' to regenerate defaults."));
|
|
1134
1285
|
console.log();
|
package/package.json
CHANGED