@codemcp/workflows 6.20.1 → 6.21.0
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/package.json +2 -2
- package/packages/cli/dist/{chunk-4N42FFJE.js → chunk-KWAFQZUI.js} +91 -2670
- package/packages/cli/dist/{cli-MFHC7UWY.js → cli-O52P3RVC.js} +468 -33
- package/packages/cli/dist/{dist-ISN3FRV4.js → dist-FIUD5G5U.js} +65 -4
- package/packages/cli/dist/{dist-TDV3DJ2J.js → dist-ZTAPC4IK.js} +3 -1
- package/packages/cli/dist/index.js +2 -2
- package/packages/cli/package.json +5 -2
- package/packages/cli/resources/templates/opencode-agents/coding.md.tmpl +13 -0
- package/packages/cli/resources/templates/opencode-agents/research.md.tmpl +13 -0
- package/packages/cli/resources/templates/opencode-agents/thinking.md.tmpl +13 -0
- package/packages/cli/resources/workflows/bugfix.yaml +6 -0
- package/packages/cli/resources/workflows/epcc.yaml +3 -0
- package/packages/cli/resources/workflows/greenfield.yaml +3 -0
- package/packages/cli/resources/workflows/pr-review.yaml +2 -0
- package/packages/cli/resources/workflows/qrspi.yaml +5 -0
- package/packages/cli/resources/workflows/tdd.yaml +3 -0
- package/packages/cli/resources/workflows/waterfall.yaml +3 -0
- package/packages/core/dist/capability-hint.d.ts +28 -0
- package/packages/core/dist/capability-hint.js +52 -0
- package/packages/core/dist/capability-hint.js.map +1 -0
- package/packages/core/dist/config-manager.d.ts +19 -0
- package/packages/core/dist/config-manager.js +26 -0
- package/packages/core/dist/config-manager.js.map +1 -1
- package/packages/core/dist/index.d.ts +1 -0
- package/packages/core/dist/index.js +1 -0
- package/packages/core/dist/index.js.map +1 -1
- package/packages/core/dist/instruction-generator.js +7 -1
- package/packages/core/dist/instruction-generator.js.map +1 -1
- package/packages/core/dist/interfaces/instruction-generator.interface.d.ts +14 -0
- package/packages/core/dist/state-machine-types.d.ts +7 -0
- package/packages/core/package.json +1 -1
- package/packages/core/resources/templates/opencode-agents/coding.md.tmpl +13 -0
- package/packages/core/resources/templates/opencode-agents/research.md.tmpl +13 -0
- package/packages/core/resources/templates/opencode-agents/thinking.md.tmpl +13 -0
- package/packages/core/resources/workflows/bugfix.yaml +6 -0
- package/packages/core/resources/workflows/epcc.yaml +3 -0
- package/packages/core/resources/workflows/greenfield.yaml +3 -0
- package/packages/core/resources/workflows/pr-review.yaml +2 -0
- package/packages/core/resources/workflows/qrspi.yaml +5 -0
- package/packages/core/resources/workflows/tdd.yaml +3 -0
- package/packages/core/resources/workflows/waterfall.yaml +3 -0
- package/packages/docs/.vitepress/dist/404.html +1 -1
- package/packages/docs/.vitepress/dist/assets/user_capability-routing.md.DbNKvMiS.js +15 -0
- package/packages/docs/.vitepress/dist/assets/user_capability-routing.md.DbNKvMiS.lean.js +1 -0
- package/packages/docs/.vitepress/dist/dev/ARCHITECTURE.html +2 -2
- package/packages/docs/.vitepress/dist/dev/DEVELOPMENT.html +2 -2
- package/packages/docs/.vitepress/dist/dev/LOGGING.html +2 -2
- package/packages/docs/.vitepress/dist/dev/PUBLISHING.html +2 -2
- package/packages/docs/.vitepress/dist/hashmap.json +1 -1
- package/packages/docs/.vitepress/dist/index.html +2 -2
- package/packages/docs/.vitepress/dist/user/advanced-engineering.html +3 -3
- package/packages/docs/.vitepress/dist/user/agent-setup.html +3 -3
- package/packages/docs/.vitepress/dist/user/beads-integration.html +2 -2
- package/packages/docs/.vitepress/dist/user/capability-routing.html +40 -0
- package/packages/docs/.vitepress/dist/user/crowd-mcp-integration.html +2 -2
- package/packages/docs/.vitepress/dist/user/custom-workflows.html +2 -2
- package/packages/docs/.vitepress/dist/user/git-commit-feature.html +2 -2
- package/packages/docs/.vitepress/dist/user/how-it-works.html +2 -2
- package/packages/docs/.vitepress/dist/user/long-term-memory.html +2 -2
- package/packages/docs/.vitepress/dist/user/packaged-workflows.html +2 -2
- package/packages/docs/.vitepress/dist/user/tutorial.html +2 -2
- package/packages/docs/.vitepress/dist/user/workflow-selection.html +2 -2
- package/packages/docs/.vitepress/dist/workflows/adr.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/big-bang-conversion.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/boundary-testing.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/bugfix.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/bugfix.yaml +6 -0
- package/packages/docs/.vitepress/dist/workflows/business-analysis.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/c4-analysis.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/epcc.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/epcc.yaml +3 -0
- package/packages/docs/.vitepress/dist/workflows/game-beginner.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/greenfield.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/greenfield.yaml +3 -0
- package/packages/docs/.vitepress/dist/workflows/minor.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/posts.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/pr-review.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/pr-review.yaml +2 -0
- package/packages/docs/.vitepress/dist/workflows/qrspi.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/qrspi.yaml +5 -0
- package/packages/docs/.vitepress/dist/workflows/sdd-bugfix-crowd.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/sdd-bugfix.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/sdd-feature-crowd.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/sdd-feature.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/sdd-greenfield-crowd.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/sdd-greenfield.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/skilled-bugfix.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/skilled-epcc.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/skilled-greenfield.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/slides.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/tdd.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/tdd.yaml +3 -0
- package/packages/docs/.vitepress/dist/workflows/waterfall.html +1 -1
- package/packages/docs/.vitepress/dist/workflows/waterfall.yaml +3 -0
- package/packages/docs/.vitepress/dist/workflows.html +1 -1
- package/packages/docs/package.json +1 -1
- package/packages/mcp-server/dist/index.js +67 -4
- package/packages/mcp-server/package.json +1 -1
- package/packages/mcp-server/resources/templates/opencode-agents/coding.md.tmpl +13 -0
- package/packages/mcp-server/resources/templates/opencode-agents/research.md.tmpl +13 -0
- package/packages/mcp-server/resources/templates/opencode-agents/thinking.md.tmpl +13 -0
- package/packages/mcp-server/resources/workflows/bugfix.yaml +6 -0
- package/packages/mcp-server/resources/workflows/epcc.yaml +3 -0
- package/packages/mcp-server/resources/workflows/greenfield.yaml +3 -0
- package/packages/mcp-server/resources/workflows/pr-review.yaml +2 -0
- package/packages/mcp-server/resources/workflows/qrspi.yaml +5 -0
- package/packages/mcp-server/resources/workflows/tdd.yaml +3 -0
- package/packages/mcp-server/resources/workflows/waterfall.yaml +3 -0
- package/packages/opencode-plugin/dist/index.d.ts +8 -192
- package/packages/opencode-plugin/dist/index.js +76 -5
- package/packages/opencode-plugin/package.json +6 -1
- package/packages/opencode-plugin/resources/templates/opencode-agents/coding.md.tmpl +13 -0
- package/packages/opencode-plugin/resources/templates/opencode-agents/research.md.tmpl +13 -0
- package/packages/opencode-plugin/resources/templates/opencode-agents/thinking.md.tmpl +13 -0
- package/packages/opencode-plugin/resources/workflows/bugfix.yaml +6 -0
- package/packages/opencode-plugin/resources/workflows/epcc.yaml +3 -0
- package/packages/opencode-plugin/resources/workflows/greenfield.yaml +3 -0
- package/packages/opencode-plugin/resources/workflows/pr-review.yaml +2 -0
- package/packages/opencode-plugin/resources/workflows/qrspi.yaml +5 -0
- package/packages/opencode-plugin/resources/workflows/tdd.yaml +3 -0
- package/packages/opencode-plugin/resources/workflows/waterfall.yaml +3 -0
- package/packages/opencode-tui-plugin/package.json +1 -1
- package/packages/visualizer/package.json +1 -1
- package/resources/state-machine-schema.json +4 -0
- package/resources/templates/opencode-agents/coding.md.tmpl +13 -0
- package/resources/templates/opencode-agents/research.md.tmpl +13 -0
- package/resources/templates/opencode-agents/thinking.md.tmpl +13 -0
- package/resources/workflows/bugfix.yaml +6 -0
- package/resources/workflows/epcc.yaml +3 -0
- package/resources/workflows/greenfield.yaml +3 -0
- package/resources/workflows/pr-review.yaml +2 -0
- package/resources/workflows/qrspi.yaml +5 -0
- package/resources/workflows/tdd.yaml +3 -0
- package/resources/workflows/waterfall.yaml +3 -0
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ConfigManager,
|
|
2
3
|
StateMachineLoader,
|
|
3
4
|
WorkflowManager,
|
|
4
5
|
generateSystemPrompt
|
|
5
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-KWAFQZUI.js";
|
|
6
7
|
import "./chunk-R5U7XKVJ.js";
|
|
7
8
|
|
|
8
9
|
// src/cli.ts
|
|
9
|
-
import { fileURLToPath as
|
|
10
|
-
import { dirname as
|
|
10
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
11
|
+
import { dirname as dirname4, join as join6 } from "path";
|
|
11
12
|
import {
|
|
12
|
-
existsSync as
|
|
13
|
+
existsSync as existsSync4,
|
|
13
14
|
mkdirSync,
|
|
14
15
|
writeFileSync,
|
|
15
16
|
readFileSync,
|
|
@@ -991,18 +992,354 @@ async function generateSkill(platform, outputDir = ".") {
|
|
|
991
992
|
console.log(`\u2705 Skill generated successfully for ${platform}`);
|
|
992
993
|
}
|
|
993
994
|
|
|
994
|
-
// src/
|
|
995
|
+
// src/capability-generator.ts
|
|
996
|
+
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
|
|
997
|
+
import { existsSync as existsSync3 } from "fs";
|
|
998
|
+
import { join as join5, dirname as dirname3 } from "path";
|
|
999
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
1000
|
+
import yaml from "js-yaml";
|
|
995
1001
|
var __filename3 = fileURLToPath3(import.meta.url);
|
|
996
1002
|
var __dirname3 = dirname3(__filename3);
|
|
997
|
-
var
|
|
1003
|
+
var SUPPORTED_CAPABILITIES = [
|
|
1004
|
+
"thinking",
|
|
1005
|
+
"coding",
|
|
1006
|
+
"research"
|
|
1007
|
+
];
|
|
1008
|
+
var CapabilityGenerator = class {
|
|
1009
|
+
/**
|
|
1010
|
+
* Concrete orchestration: for each provided capability, resolve the output
|
|
1011
|
+
* path, render the file, then write (or skip if it exists and `!force`).
|
|
1012
|
+
* Finally, merge the matching `capability_models` entries into
|
|
1013
|
+
* `.vibe/config.yaml` (target-agnostic; lives in the base).
|
|
1014
|
+
*/
|
|
1015
|
+
async generate(opts) {
|
|
1016
|
+
const { projectPath, models, force = false } = opts;
|
|
1017
|
+
const generatedFiles = [];
|
|
1018
|
+
const skippedFiles = [];
|
|
1019
|
+
for (const capability of SUPPORTED_CAPABILITIES) {
|
|
1020
|
+
const model = models[capability];
|
|
1021
|
+
if (!model) {
|
|
1022
|
+
continue;
|
|
1023
|
+
}
|
|
1024
|
+
const targetPath = this.getOutputPath(capability, projectPath);
|
|
1025
|
+
const content = await this.renderCapabilityFile(capability, model);
|
|
1026
|
+
if (existsSync3(targetPath) && !force) {
|
|
1027
|
+
skippedFiles.push(targetPath);
|
|
1028
|
+
continue;
|
|
1029
|
+
}
|
|
1030
|
+
await mkdir3(dirname3(targetPath), { recursive: true });
|
|
1031
|
+
await writeFile3(targetPath, content, "utf-8");
|
|
1032
|
+
generatedFiles.push(targetPath);
|
|
1033
|
+
}
|
|
1034
|
+
const configPath = join5(projectPath, ".vibe", "config.yaml");
|
|
1035
|
+
const configUpdated = await mergeCapabilityModels(configPath, models);
|
|
1036
|
+
return { generatedFiles, skippedFiles, configUpdated, configPath };
|
|
1037
|
+
}
|
|
1038
|
+
};
|
|
1039
|
+
async function mergeCapabilityModels(configPath, models) {
|
|
1040
|
+
const newEntries = {};
|
|
1041
|
+
for (const capability of SUPPORTED_CAPABILITIES) {
|
|
1042
|
+
const model = models[capability];
|
|
1043
|
+
if (model) {
|
|
1044
|
+
newEntries[capability] = { model, agent: capability };
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
if (Object.keys(newEntries).length === 0) {
|
|
1048
|
+
return false;
|
|
1049
|
+
}
|
|
1050
|
+
let existingConfig = {};
|
|
1051
|
+
let configExisted = false;
|
|
1052
|
+
if (existsSync3(configPath)) {
|
|
1053
|
+
configExisted = true;
|
|
1054
|
+
const projectRoot = dirname3(dirname3(configPath));
|
|
1055
|
+
const loaded = ConfigManager.loadProjectConfig(projectRoot);
|
|
1056
|
+
if (loaded !== null) {
|
|
1057
|
+
existingConfig = loaded;
|
|
1058
|
+
} else {
|
|
1059
|
+
const existingRaw = await readFile3(configPath, "utf-8");
|
|
1060
|
+
const parsed = yaml.load(existingRaw);
|
|
1061
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
1062
|
+
existingConfig = parsed;
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
const mergedConfig = {
|
|
1067
|
+
...existingConfig,
|
|
1068
|
+
capability_models: {
|
|
1069
|
+
...existingConfig.capability_models,
|
|
1070
|
+
...newEntries
|
|
1071
|
+
}
|
|
1072
|
+
};
|
|
1073
|
+
const serialized = yaml.dump(mergedConfig, { noRefs: true, sortKeys: false });
|
|
1074
|
+
if (configExisted) {
|
|
1075
|
+
const existingSerialized = yaml.dump(existingConfig, {
|
|
1076
|
+
noRefs: true,
|
|
1077
|
+
sortKeys: false
|
|
1078
|
+
});
|
|
1079
|
+
if (existingSerialized === serialized) {
|
|
1080
|
+
return false;
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
await mkdir3(dirname3(configPath), { recursive: true });
|
|
1084
|
+
await writeFile3(configPath, serialized, "utf-8");
|
|
1085
|
+
return true;
|
|
1086
|
+
}
|
|
1087
|
+
function resolveOpencodeTemplatePath(capability) {
|
|
1088
|
+
const filename = `${capability}.md.tmpl`;
|
|
1089
|
+
const possiblePaths = [
|
|
1090
|
+
// From src/ in dev (vitest): <cli>/resources/templates/opencode-agents/<file>
|
|
1091
|
+
join5(
|
|
1092
|
+
__dirname3,
|
|
1093
|
+
"..",
|
|
1094
|
+
"resources",
|
|
1095
|
+
"templates",
|
|
1096
|
+
"opencode-agents",
|
|
1097
|
+
filename
|
|
1098
|
+
),
|
|
1099
|
+
// From dist/ at runtime: <cli>/resources/templates/opencode-agents/<file>
|
|
1100
|
+
join5(
|
|
1101
|
+
__dirname3,
|
|
1102
|
+
"..",
|
|
1103
|
+
"..",
|
|
1104
|
+
"resources",
|
|
1105
|
+
"templates",
|
|
1106
|
+
"opencode-agents",
|
|
1107
|
+
filename
|
|
1108
|
+
),
|
|
1109
|
+
// From dist/cli/ at runtime (alt bundled layout)
|
|
1110
|
+
join5(
|
|
1111
|
+
__dirname3,
|
|
1112
|
+
"..",
|
|
1113
|
+
"..",
|
|
1114
|
+
"..",
|
|
1115
|
+
"resources",
|
|
1116
|
+
"templates",
|
|
1117
|
+
"opencode-agents",
|
|
1118
|
+
filename
|
|
1119
|
+
),
|
|
1120
|
+
// Root canonical source of truth
|
|
1121
|
+
join5(
|
|
1122
|
+
__dirname3,
|
|
1123
|
+
"..",
|
|
1124
|
+
"..",
|
|
1125
|
+
"..",
|
|
1126
|
+
"..",
|
|
1127
|
+
"resources",
|
|
1128
|
+
"templates",
|
|
1129
|
+
"opencode-agents",
|
|
1130
|
+
filename
|
|
1131
|
+
),
|
|
1132
|
+
// From core package resources
|
|
1133
|
+
join5(
|
|
1134
|
+
__dirname3,
|
|
1135
|
+
"..",
|
|
1136
|
+
"..",
|
|
1137
|
+
"core",
|
|
1138
|
+
"resources",
|
|
1139
|
+
"templates",
|
|
1140
|
+
"opencode-agents",
|
|
1141
|
+
filename
|
|
1142
|
+
)
|
|
1143
|
+
];
|
|
1144
|
+
for (const candidate of possiblePaths) {
|
|
1145
|
+
if (existsSync3(candidate)) {
|
|
1146
|
+
return candidate;
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
throw new Error(
|
|
1150
|
+
`Capability template not found: ${filename}. Searched: ${possiblePaths.join(", ")}`
|
|
1151
|
+
);
|
|
1152
|
+
}
|
|
1153
|
+
function renderOpencodeTemplate(content, capability, model) {
|
|
1154
|
+
return content.replace(/\$\{capability\}/g, capability).replace(/\$\{model\}/g, model);
|
|
1155
|
+
}
|
|
1156
|
+
var OpencodeCapabilityGenerator = class extends CapabilityGenerator {
|
|
1157
|
+
name = "opencode";
|
|
1158
|
+
description = "Generate .opencode/agents/<capability>.md (mode: subagent, model pinned)";
|
|
1159
|
+
getOutputPath(capability, projectPath) {
|
|
1160
|
+
return join5(projectPath, ".opencode", "agents", `${capability}.md`);
|
|
1161
|
+
}
|
|
1162
|
+
async renderCapabilityFile(capability, model) {
|
|
1163
|
+
const templatePath = resolveOpencodeTemplatePath(capability);
|
|
1164
|
+
const templateContent = await readFile3(templatePath, "utf-8");
|
|
1165
|
+
return renderOpencodeTemplate(templateContent, capability, model);
|
|
1166
|
+
}
|
|
1167
|
+
};
|
|
1168
|
+
function buildNotYetSupportedError(target) {
|
|
1169
|
+
return new Error(
|
|
1170
|
+
`Capability generation for ${target} is not yet supported \u2014 see \`setup capabilities --help\``
|
|
1171
|
+
);
|
|
1172
|
+
}
|
|
1173
|
+
var KiroCapabilityGenerator = class extends CapabilityGenerator {
|
|
1174
|
+
name = "kiro";
|
|
1175
|
+
description = "Not yet supported for kiro \u2014 see `setup capabilities --help`";
|
|
1176
|
+
getOutputPath() {
|
|
1177
|
+
throw buildNotYetSupportedError(this.name);
|
|
1178
|
+
}
|
|
1179
|
+
renderCapabilityFile() {
|
|
1180
|
+
return Promise.reject(buildNotYetSupportedError(this.name));
|
|
1181
|
+
}
|
|
1182
|
+
};
|
|
1183
|
+
var ClaudeCapabilityGenerator = class extends CapabilityGenerator {
|
|
1184
|
+
name = "claude";
|
|
1185
|
+
description = "Not yet supported for claude \u2014 see `setup capabilities --help`";
|
|
1186
|
+
getOutputPath() {
|
|
1187
|
+
throw buildNotYetSupportedError(this.name);
|
|
1188
|
+
}
|
|
1189
|
+
renderCapabilityFile() {
|
|
1190
|
+
return Promise.reject(buildNotYetSupportedError(this.name));
|
|
1191
|
+
}
|
|
1192
|
+
};
|
|
1193
|
+
var GeminiCapabilityGenerator = class extends CapabilityGenerator {
|
|
1194
|
+
name = "gemini";
|
|
1195
|
+
description = "Not yet supported for gemini \u2014 see `setup capabilities --help`";
|
|
1196
|
+
getOutputPath() {
|
|
1197
|
+
throw buildNotYetSupportedError(this.name);
|
|
1198
|
+
}
|
|
1199
|
+
renderCapabilityFile() {
|
|
1200
|
+
return Promise.reject(buildNotYetSupportedError(this.name));
|
|
1201
|
+
}
|
|
1202
|
+
};
|
|
1203
|
+
var VSCodeCapabilityGenerator = class extends CapabilityGenerator {
|
|
1204
|
+
name = "vscode";
|
|
1205
|
+
description = "Not yet supported for vscode \u2014 see `setup capabilities --help`";
|
|
1206
|
+
getOutputPath() {
|
|
1207
|
+
throw buildNotYetSupportedError(this.name);
|
|
1208
|
+
}
|
|
1209
|
+
renderCapabilityFile() {
|
|
1210
|
+
return Promise.reject(buildNotYetSupportedError(this.name));
|
|
1211
|
+
}
|
|
1212
|
+
};
|
|
1213
|
+
var GithubCopilotCapabilityGenerator = class extends CapabilityGenerator {
|
|
1214
|
+
name = "github-copilot";
|
|
1215
|
+
description = "Not yet supported for github-copilot \u2014 see `setup capabilities --help`";
|
|
1216
|
+
getOutputPath() {
|
|
1217
|
+
throw buildNotYetSupportedError(this.name);
|
|
1218
|
+
}
|
|
1219
|
+
renderCapabilityFile() {
|
|
1220
|
+
return Promise.reject(buildNotYetSupportedError(this.name));
|
|
1221
|
+
}
|
|
1222
|
+
};
|
|
1223
|
+
var CapabilityGeneratorRegistry = class {
|
|
1224
|
+
static generators = /* @__PURE__ */ new Map();
|
|
1225
|
+
/**
|
|
1226
|
+
* Register a generator with its metadata.
|
|
1227
|
+
*/
|
|
1228
|
+
static register(metadata) {
|
|
1229
|
+
this.generators.set(metadata.name.toLowerCase(), metadata);
|
|
1230
|
+
}
|
|
1231
|
+
/**
|
|
1232
|
+
* Create a generator instance by name.
|
|
1233
|
+
*
|
|
1234
|
+
* - Throws `Unknown capability target: ...` when the name is not
|
|
1235
|
+
* registered at all.
|
|
1236
|
+
* - Throws `Capability generation for <target> is not yet supported` when
|
|
1237
|
+
* the name is registered but `supported: false`.
|
|
1238
|
+
* - Otherwise returns a fresh `CapabilityGenerator` instance.
|
|
1239
|
+
*/
|
|
1240
|
+
static createGenerator(name) {
|
|
1241
|
+
const metadata = this.generators.get(name.toLowerCase());
|
|
1242
|
+
if (!metadata) {
|
|
1243
|
+
const supported = this.getSupportedNames();
|
|
1244
|
+
throw new Error(
|
|
1245
|
+
`Unknown capability target: ${name}. Supported: ${supported.join(", ")}`
|
|
1246
|
+
);
|
|
1247
|
+
}
|
|
1248
|
+
if (!metadata.supported) {
|
|
1249
|
+
throw new Error(
|
|
1250
|
+
`Capability generation for ${metadata.name} is not yet supported \u2014 see \`setup capabilities --help\``
|
|
1251
|
+
);
|
|
1252
|
+
}
|
|
1253
|
+
return new metadata.generatorClass();
|
|
1254
|
+
}
|
|
1255
|
+
/**
|
|
1256
|
+
* Get all registered generators (including unsupported stubs).
|
|
1257
|
+
*/
|
|
1258
|
+
static getAllGenerators() {
|
|
1259
|
+
return Array.from(this.generators.values());
|
|
1260
|
+
}
|
|
1261
|
+
/**
|
|
1262
|
+
* Get the names of fully-supported generators (excludes stubs).
|
|
1263
|
+
*/
|
|
1264
|
+
static getSupportedNames() {
|
|
1265
|
+
return this.getAllGenerators().filter((g) => g.supported).map((g) => g.name);
|
|
1266
|
+
}
|
|
1267
|
+
/**
|
|
1268
|
+
* Get formatted help text for all registered generators, with a status
|
|
1269
|
+
* indicator (✅ supported / ⏳ not yet supported) and a padded name column
|
|
1270
|
+
* so the descriptions line up as the list grows.
|
|
1271
|
+
*/
|
|
1272
|
+
static getHelpText() {
|
|
1273
|
+
const generators = this.getAllGenerators();
|
|
1274
|
+
if (generators.length === 0) {
|
|
1275
|
+
return "";
|
|
1276
|
+
}
|
|
1277
|
+
const maxNameLength = Math.max(...generators.map((g) => g.name.length));
|
|
1278
|
+
return generators.map((g) => {
|
|
1279
|
+
const icon = g.supported ? "\u2705" : "\u23F3";
|
|
1280
|
+
const paddedName = g.name.padEnd(maxNameLength + 2, " ");
|
|
1281
|
+
return `${icon} ${paddedName}${g.description}`;
|
|
1282
|
+
}).join("\n");
|
|
1283
|
+
}
|
|
1284
|
+
/**
|
|
1285
|
+
* Check if a generator is registered by name.
|
|
1286
|
+
*/
|
|
1287
|
+
static exists(name) {
|
|
1288
|
+
return this.generators.has(name.toLowerCase());
|
|
1289
|
+
}
|
|
1290
|
+
};
|
|
1291
|
+
CapabilityGeneratorRegistry.register({
|
|
1292
|
+
name: "opencode",
|
|
1293
|
+
description: "Generate .opencode/agents/<capability>.md (mode: subagent, model pinned)",
|
|
1294
|
+
generatorClass: OpencodeCapabilityGenerator,
|
|
1295
|
+
supported: true
|
|
1296
|
+
});
|
|
1297
|
+
CapabilityGeneratorRegistry.register({
|
|
1298
|
+
name: "kiro",
|
|
1299
|
+
description: "Not yet supported for kiro \u2014 see `setup capabilities --help`",
|
|
1300
|
+
generatorClass: KiroCapabilityGenerator,
|
|
1301
|
+
supported: false
|
|
1302
|
+
});
|
|
1303
|
+
CapabilityGeneratorRegistry.register({
|
|
1304
|
+
name: "claude",
|
|
1305
|
+
description: "Not yet supported for claude \u2014 see `setup capabilities --help`",
|
|
1306
|
+
generatorClass: ClaudeCapabilityGenerator,
|
|
1307
|
+
supported: false
|
|
1308
|
+
});
|
|
1309
|
+
CapabilityGeneratorRegistry.register({
|
|
1310
|
+
name: "gemini",
|
|
1311
|
+
description: "Not yet supported for gemini \u2014 see `setup capabilities --help`",
|
|
1312
|
+
generatorClass: GeminiCapabilityGenerator,
|
|
1313
|
+
supported: false
|
|
1314
|
+
});
|
|
1315
|
+
CapabilityGeneratorRegistry.register({
|
|
1316
|
+
name: "vscode",
|
|
1317
|
+
description: "Not yet supported for vscode \u2014 see `setup capabilities --help`",
|
|
1318
|
+
generatorClass: VSCodeCapabilityGenerator,
|
|
1319
|
+
supported: false
|
|
1320
|
+
});
|
|
1321
|
+
CapabilityGeneratorRegistry.register({
|
|
1322
|
+
name: "github-copilot",
|
|
1323
|
+
description: "Not yet supported for github-copilot \u2014 see `setup capabilities --help`",
|
|
1324
|
+
generatorClass: GithubCopilotCapabilityGenerator,
|
|
1325
|
+
supported: false
|
|
1326
|
+
});
|
|
1327
|
+
function generateCapabilities(target, opts) {
|
|
1328
|
+
return CapabilityGeneratorRegistry.createGenerator(target).generate(opts);
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
// src/cli.ts
|
|
1332
|
+
var __filename4 = fileURLToPath4(import.meta.url);
|
|
1333
|
+
var __dirname4 = dirname4(__filename4);
|
|
1334
|
+
var isLocal = existsSync4(join6(__dirname4, "../../core/dist/index.js"));
|
|
998
1335
|
var generateSystemPrompt2;
|
|
999
1336
|
var StateMachineLoader2;
|
|
1000
1337
|
if (isLocal) {
|
|
1001
|
-
const coreModule = await import("./dist-
|
|
1338
|
+
const coreModule = await import("./dist-ZTAPC4IK.js");
|
|
1002
1339
|
generateSystemPrompt2 = coreModule.generateSystemPrompt;
|
|
1003
1340
|
StateMachineLoader2 = coreModule.StateMachineLoader;
|
|
1004
1341
|
} else {
|
|
1005
|
-
const coreModule = await import("./dist-
|
|
1342
|
+
const coreModule = await import("./dist-ZTAPC4IK.js");
|
|
1006
1343
|
generateSystemPrompt2 = coreModule.generateSystemPrompt;
|
|
1007
1344
|
StateMachineLoader2 = coreModule.StateMachineLoader;
|
|
1008
1345
|
}
|
|
@@ -1020,7 +1357,7 @@ function parseFlag(args, flag) {
|
|
|
1020
1357
|
}
|
|
1021
1358
|
async function parseCliArgs() {
|
|
1022
1359
|
const args = process.argv.slice(2);
|
|
1023
|
-
if (args
|
|
1360
|
+
if (args[0] === "--help" || args[0] === "-h") {
|
|
1024
1361
|
showHelp();
|
|
1025
1362
|
return { shouldExit: true };
|
|
1026
1363
|
}
|
|
@@ -1030,6 +1367,9 @@ async function parseCliArgs() {
|
|
|
1030
1367
|
if (subcommand === "list") {
|
|
1031
1368
|
handleSetupList();
|
|
1032
1369
|
return { shouldExit: true };
|
|
1370
|
+
} else if (subcommand === "capabilities") {
|
|
1371
|
+
await handleSetupCapabilities(args.slice(2));
|
|
1372
|
+
return { shouldExit: true };
|
|
1033
1373
|
} else if (subcommand) {
|
|
1034
1374
|
const mode = parseFlag(args, "--mode") ?? "config";
|
|
1035
1375
|
if (mode !== "skill" && mode !== "config") {
|
|
@@ -1042,6 +1382,9 @@ async function parseCliArgs() {
|
|
|
1042
1382
|
console.error("\u274C Error: setup requires a target");
|
|
1043
1383
|
console.error("Usage: setup <target> [--mode config|skill]");
|
|
1044
1384
|
console.error(" setup list");
|
|
1385
|
+
console.error(
|
|
1386
|
+
" setup capabilities <target> [--model-thinking M] [--model-coding M] [--model-research M] [--force]"
|
|
1387
|
+
);
|
|
1045
1388
|
process.exit(1);
|
|
1046
1389
|
}
|
|
1047
1390
|
}
|
|
@@ -1201,8 +1544,8 @@ function handleWorkflowCopy(sourceWorkflow, customName) {
|
|
|
1201
1544
|
process.exit(1);
|
|
1202
1545
|
}
|
|
1203
1546
|
const possibleSourcePaths = [
|
|
1204
|
-
|
|
1205
|
-
|
|
1547
|
+
join6(
|
|
1548
|
+
__dirname4,
|
|
1206
1549
|
"..",
|
|
1207
1550
|
"..",
|
|
1208
1551
|
"..",
|
|
@@ -1210,8 +1553,8 @@ function handleWorkflowCopy(sourceWorkflow, customName) {
|
|
|
1210
1553
|
"workflows",
|
|
1211
1554
|
`${sourceWorkflow}.yaml`
|
|
1212
1555
|
),
|
|
1213
|
-
|
|
1214
|
-
|
|
1556
|
+
join6(
|
|
1557
|
+
__dirname4,
|
|
1215
1558
|
"..",
|
|
1216
1559
|
"..",
|
|
1217
1560
|
"core",
|
|
@@ -1219,28 +1562,28 @@ function handleWorkflowCopy(sourceWorkflow, customName) {
|
|
|
1219
1562
|
"workflows",
|
|
1220
1563
|
`${sourceWorkflow}.yaml`
|
|
1221
1564
|
),
|
|
1222
|
-
|
|
1565
|
+
join6(process.cwd(), "resources", "workflows", `${sourceWorkflow}.yaml`)
|
|
1223
1566
|
];
|
|
1224
|
-
const foundPath = possibleSourcePaths.find((p) =>
|
|
1567
|
+
const foundPath = possibleSourcePaths.find((p) => existsSync4(p));
|
|
1225
1568
|
if (!foundPath) {
|
|
1226
1569
|
console.error(`\u274C Could not find source workflow: ${sourceWorkflow}`);
|
|
1227
1570
|
process.exit(1);
|
|
1228
1571
|
}
|
|
1229
1572
|
const sourceContent = readFileSync(foundPath, "utf8");
|
|
1230
|
-
const vibeDir =
|
|
1231
|
-
const workflowsDir =
|
|
1232
|
-
if (!
|
|
1573
|
+
const vibeDir = join6(process.cwd(), ".vibe");
|
|
1574
|
+
const workflowsDir = join6(vibeDir, "workflows");
|
|
1575
|
+
if (!existsSync4(vibeDir)) {
|
|
1233
1576
|
mkdirSync(vibeDir, { recursive: true });
|
|
1234
1577
|
}
|
|
1235
|
-
if (!
|
|
1578
|
+
if (!existsSync4(workflowsDir)) {
|
|
1236
1579
|
mkdirSync(workflowsDir, { recursive: true });
|
|
1237
1580
|
}
|
|
1238
1581
|
const customContent = sourceContent.replace(
|
|
1239
1582
|
new RegExp(`name: '${sourceWorkflow}'`, "g"),
|
|
1240
1583
|
`name: '${customName}'`
|
|
1241
1584
|
);
|
|
1242
|
-
const workflowPath =
|
|
1243
|
-
if (
|
|
1585
|
+
const workflowPath = join6(workflowsDir, `${customName}.yaml`);
|
|
1586
|
+
if (existsSync4(workflowPath)) {
|
|
1244
1587
|
console.error(
|
|
1245
1588
|
`\u274C Workflow '${customName}' already exists at ${workflowPath}`
|
|
1246
1589
|
);
|
|
@@ -1291,6 +1634,97 @@ async function handleSetup(target, mode) {
|
|
|
1291
1634
|
process.exit(1);
|
|
1292
1635
|
}
|
|
1293
1636
|
}
|
|
1637
|
+
function printSetupCapabilitiesHelp() {
|
|
1638
|
+
console.log(`
|
|
1639
|
+
setup capabilities <target> [flags]
|
|
1640
|
+
|
|
1641
|
+
Wire up capability-routed subagents for a target IDE/CLI and merge the
|
|
1642
|
+
matching \`capability_models\` entries into \`.vibe/config.yaml\`.
|
|
1643
|
+
|
|
1644
|
+
FLAGS:
|
|
1645
|
+
--model-thinking <model> Set the model for the thinking agent
|
|
1646
|
+
--model-coding <model> Set the model for the coding agent
|
|
1647
|
+
--model-research <model> Set the model for the research agent
|
|
1648
|
+
--force Overwrite existing per-target agent files
|
|
1649
|
+
--help, -h Show this help message
|
|
1650
|
+
|
|
1651
|
+
TARGETS:
|
|
1652
|
+
${CapabilityGeneratorRegistry.getHelpText().split("\n").map((line) => ` ${line}`).join("\n")}
|
|
1653
|
+
|
|
1654
|
+
USAGE:
|
|
1655
|
+
setup capabilities opencode --model-thinking anthropic/claude-opus-4-7 --model-coding anthropic/claude-sonnet-4-5 --model-research anthropic/claude-haiku-4-5
|
|
1656
|
+
|
|
1657
|
+
Only 'opencode' is currently implemented. Other targets listed above will
|
|
1658
|
+
throw a "not yet supported" error and exit non-zero.
|
|
1659
|
+
`);
|
|
1660
|
+
}
|
|
1661
|
+
async function handleSetupCapabilities(args) {
|
|
1662
|
+
if (args[0] === "--help" || args[0] === "-h") {
|
|
1663
|
+
printSetupCapabilitiesHelp();
|
|
1664
|
+
return;
|
|
1665
|
+
}
|
|
1666
|
+
if (args.length === 0 || args[0].startsWith("--")) {
|
|
1667
|
+
console.error("\u274C Error: setup capabilities requires a <target>");
|
|
1668
|
+
console.error(
|
|
1669
|
+
"Usage: setup capabilities <target> [--model-thinking M] [--model-coding M] [--model-research M] [--force]"
|
|
1670
|
+
);
|
|
1671
|
+
console.error(
|
|
1672
|
+
`Supported targets: ${CapabilityGeneratorRegistry.getSupportedNames().join(", ")}`
|
|
1673
|
+
);
|
|
1674
|
+
console.error("Run `setup capabilities --help` for the full target list.");
|
|
1675
|
+
process.exit(1);
|
|
1676
|
+
}
|
|
1677
|
+
const target = args[0];
|
|
1678
|
+
const flagArgs = args.slice(1);
|
|
1679
|
+
const thinking = parseFlag(flagArgs, "--model-thinking");
|
|
1680
|
+
const coding = parseFlag(flagArgs, "--model-coding");
|
|
1681
|
+
const research = parseFlag(flagArgs, "--model-research");
|
|
1682
|
+
const force = flagArgs.includes("--force");
|
|
1683
|
+
const models = {};
|
|
1684
|
+
if (thinking !== void 0) models.thinking = thinking;
|
|
1685
|
+
if (coding !== void 0) models.coding = coding;
|
|
1686
|
+
if (research !== void 0) models.research = research;
|
|
1687
|
+
if (Object.keys(models).length === 0) {
|
|
1688
|
+
console.error(
|
|
1689
|
+
"\u274C Error: setup capabilities requires at least one --model-* flag"
|
|
1690
|
+
);
|
|
1691
|
+
console.error(
|
|
1692
|
+
"Usage: setup capabilities <target> [--model-thinking M] [--model-coding M] [--model-research M] [--force]"
|
|
1693
|
+
);
|
|
1694
|
+
process.exit(1);
|
|
1695
|
+
}
|
|
1696
|
+
for (const [capability, value] of Object.entries(models)) {
|
|
1697
|
+
if (value.trim() === "") {
|
|
1698
|
+
console.error(
|
|
1699
|
+
`\u274C Error: --model-${capability} must be a non-empty string`
|
|
1700
|
+
);
|
|
1701
|
+
process.exit(1);
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
try {
|
|
1705
|
+
const result = await generateCapabilities(target, {
|
|
1706
|
+
projectPath: process.cwd(),
|
|
1707
|
+
models,
|
|
1708
|
+
force
|
|
1709
|
+
});
|
|
1710
|
+
for (const file of result.generatedFiles) {
|
|
1711
|
+
console.log(`\u2705 Generated: ${file}`);
|
|
1712
|
+
}
|
|
1713
|
+
for (const file of result.skippedFiles) {
|
|
1714
|
+
console.log(
|
|
1715
|
+
`\u23ED\uFE0F Skipped: ${file} (already exists; re-run with --force to overwrite)`
|
|
1716
|
+
);
|
|
1717
|
+
}
|
|
1718
|
+
if (result.configUpdated) {
|
|
1719
|
+
console.log(`\u2705 Config updated: ${result.configPath}`);
|
|
1720
|
+
} else {
|
|
1721
|
+
console.log(`\u2139\uFE0F Config unchanged: ${result.configPath}`);
|
|
1722
|
+
}
|
|
1723
|
+
} catch (error) {
|
|
1724
|
+
console.error(`\u274C Failed: ${error.message}`);
|
|
1725
|
+
process.exit(1);
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1294
1728
|
function handleSetupList() {
|
|
1295
1729
|
const skillTargets = SkillGeneratorRegistry.getGeneratorNames();
|
|
1296
1730
|
const configTargets = GeneratorRegistry.getGeneratorNames();
|
|
@@ -1316,12 +1750,12 @@ function handleSetupList() {
|
|
|
1316
1750
|
function handleCrowdList() {
|
|
1317
1751
|
try {
|
|
1318
1752
|
const possibleAgentsPaths = [
|
|
1319
|
-
|
|
1320
|
-
|
|
1753
|
+
join6(__dirname4, "..", "..", "..", "resources", "agents"),
|
|
1754
|
+
join6(__dirname4, "..", "..", "core", "resources", "agents")
|
|
1321
1755
|
];
|
|
1322
1756
|
let agentsDir = null;
|
|
1323
1757
|
for (const path of possibleAgentsPaths) {
|
|
1324
|
-
if (
|
|
1758
|
+
if (existsSync4(path)) {
|
|
1325
1759
|
agentsDir = path;
|
|
1326
1760
|
break;
|
|
1327
1761
|
}
|
|
@@ -1339,7 +1773,7 @@ function handleCrowdList() {
|
|
|
1339
1773
|
}
|
|
1340
1774
|
console.log("\u{1F4CB} Available crowd agent configurations:\n");
|
|
1341
1775
|
for (const file of files) {
|
|
1342
|
-
const agentPath =
|
|
1776
|
+
const agentPath = join6(agentsDir, file);
|
|
1343
1777
|
const content = readFileSync(agentPath, "utf8");
|
|
1344
1778
|
const nameMatch = content.match(/^name:\s*(.+)$/m);
|
|
1345
1779
|
const displayNameMatch = content.match(/^displayName:\s*(.+)$/m);
|
|
@@ -1358,12 +1792,12 @@ function handleCrowdList() {
|
|
|
1358
1792
|
function handleCrowdCopy(outputDir) {
|
|
1359
1793
|
try {
|
|
1360
1794
|
const possibleAgentsPaths = [
|
|
1361
|
-
|
|
1362
|
-
|
|
1795
|
+
join6(__dirname4, "..", "..", "..", "resources", "agents"),
|
|
1796
|
+
join6(__dirname4, "..", "..", "core", "resources", "agents")
|
|
1363
1797
|
];
|
|
1364
1798
|
let sourceAgentsDir = null;
|
|
1365
1799
|
for (const path of possibleAgentsPaths) {
|
|
1366
|
-
if (
|
|
1800
|
+
if (existsSync4(path)) {
|
|
1367
1801
|
sourceAgentsDir = path;
|
|
1368
1802
|
break;
|
|
1369
1803
|
}
|
|
@@ -1372,8 +1806,8 @@ function handleCrowdCopy(outputDir) {
|
|
|
1372
1806
|
console.error("\u274C Could not find source agents directory");
|
|
1373
1807
|
process.exit(1);
|
|
1374
1808
|
}
|
|
1375
|
-
const targetDir = outputDir ||
|
|
1376
|
-
if (!
|
|
1809
|
+
const targetDir = outputDir || join6(process.cwd(), ".crowd", "agents");
|
|
1810
|
+
if (!existsSync4(targetDir)) {
|
|
1377
1811
|
mkdirSync(targetDir, { recursive: true });
|
|
1378
1812
|
}
|
|
1379
1813
|
const files = readdirSync(sourceAgentsDir).filter(
|
|
@@ -1390,9 +1824,9 @@ function handleCrowdCopy(outputDir) {
|
|
|
1390
1824
|
let copiedCount = 0;
|
|
1391
1825
|
let skippedCount = 0;
|
|
1392
1826
|
for (const file of files) {
|
|
1393
|
-
const sourcePath =
|
|
1394
|
-
const targetPath =
|
|
1395
|
-
if (
|
|
1827
|
+
const sourcePath = join6(sourceAgentsDir, file);
|
|
1828
|
+
const targetPath = join6(targetDir, file);
|
|
1829
|
+
if (existsSync4(targetPath)) {
|
|
1396
1830
|
console.log(`\u23ED\uFE0F ${file} (already exists, skipping)`);
|
|
1397
1831
|
skippedCount++;
|
|
1398
1832
|
} else {
|
|
@@ -1430,6 +1864,7 @@ SETUP COMMANDS:
|
|
|
1430
1864
|
setup <target> --mode config Generate full agent configuration
|
|
1431
1865
|
setup <target> --mode skill Generate skill files only
|
|
1432
1866
|
setup list List available targets
|
|
1867
|
+
setup capabilities <target> Wire up capability-routed agents (see --help)
|
|
1433
1868
|
|
|
1434
1869
|
WORKFLOW COMMANDS:
|
|
1435
1870
|
workflow list List available workflows
|