harness-bujang 0.7.2 → 0.8.1
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.
|
@@ -170,6 +170,62 @@ If installed via npm, try reinstalling. If running from source, run "npm run bui
|
|
|
170
170
|
);
|
|
171
171
|
}
|
|
172
172
|
var ALL_ADAPTERS = ["cursor", "cline", "aider", "codex", "gemini"];
|
|
173
|
+
var CODEX_BALANCED = {
|
|
174
|
+
director: "gpt-5",
|
|
175
|
+
cofounder: "gpt-5",
|
|
176
|
+
"architect-team": "gpt-5",
|
|
177
|
+
consultant: "gpt-5",
|
|
178
|
+
"security-team": "o1",
|
|
179
|
+
"db-guard-team": "o1",
|
|
180
|
+
"dev-team": "gpt-5-codex",
|
|
181
|
+
"code-review-team": "gpt-5-codex",
|
|
182
|
+
"qa-team": "gpt-4-turbo",
|
|
183
|
+
"verifier-team": "gpt-4-turbo",
|
|
184
|
+
"doc-sync-team": "gpt-4-turbo",
|
|
185
|
+
"research-team": "gpt-5",
|
|
186
|
+
"analysis-team": "gpt-5",
|
|
187
|
+
"script-team": "gpt-4-turbo",
|
|
188
|
+
"image-team": "o1-mini",
|
|
189
|
+
"voice-team": "o1-mini",
|
|
190
|
+
"edit-team": "o1-mini",
|
|
191
|
+
"content-qa-team": "o1-mini"
|
|
192
|
+
};
|
|
193
|
+
var GEMINI_BALANCED = {
|
|
194
|
+
director: "gemini-2.5-pro",
|
|
195
|
+
cofounder: "gemini-2.5-pro",
|
|
196
|
+
"architect-team": "gemini-2.5-pro",
|
|
197
|
+
consultant: "gemini-2.5-pro",
|
|
198
|
+
"security-team": "gemini-2.5-pro",
|
|
199
|
+
"db-guard-team": "gemini-2.5-pro",
|
|
200
|
+
"dev-team": "gemini-2.5-pro",
|
|
201
|
+
"code-review-team": "gemini-2.5-pro",
|
|
202
|
+
"qa-team": "gemini-2.5-flash",
|
|
203
|
+
"verifier-team": "gemini-2.5-flash",
|
|
204
|
+
"doc-sync-team": "gemini-2.5-flash",
|
|
205
|
+
"research-team": "gemini-2.5-pro",
|
|
206
|
+
"analysis-team": "gemini-2.5-pro",
|
|
207
|
+
"script-team": "gemini-2.5-flash",
|
|
208
|
+
"image-team": "gemini-2.5-flash",
|
|
209
|
+
"voice-team": "gemini-2.5-flash",
|
|
210
|
+
"edit-team": "gemini-2.5-flash",
|
|
211
|
+
"content-qa-team": "gemini-2.5-flash"
|
|
212
|
+
};
|
|
213
|
+
function resolveCodexPreset(preset) {
|
|
214
|
+
if (preset === "keep") return {};
|
|
215
|
+
if (preset === "balanced") return { ...CODEX_BALANCED };
|
|
216
|
+
const tier = preset === "cost" ? "gpt-4-turbo" : "gpt-5";
|
|
217
|
+
const out = {};
|
|
218
|
+
for (const k of Object.keys(CODEX_BALANCED)) out[k] = tier;
|
|
219
|
+
return out;
|
|
220
|
+
}
|
|
221
|
+
function resolveGeminiPreset(preset) {
|
|
222
|
+
if (preset === "keep") return {};
|
|
223
|
+
if (preset === "balanced") return { ...GEMINI_BALANCED };
|
|
224
|
+
const tier = preset === "cost" ? "gemini-2.5-flash" : "gemini-2.5-pro";
|
|
225
|
+
const out = {};
|
|
226
|
+
for (const k of Object.keys(GEMINI_BALANCED)) out[k] = tier;
|
|
227
|
+
return out;
|
|
228
|
+
}
|
|
173
229
|
var BALANCED_MAPPING = {
|
|
174
230
|
director: "opus",
|
|
175
231
|
cofounder: "opus",
|
|
@@ -233,7 +289,10 @@ async function runInit(args) {
|
|
|
233
289
|
console.log(c.dim(` Language: ${opts.lang}`));
|
|
234
290
|
console.log(c.dim(` Chat backend: ${opts.chatBackend}${opts.chatBackend === "sqlite" ? " (local file)" : " (cloud Postgres)"}`));
|
|
235
291
|
console.log(c.dim(` Tools: claude${opts.adapters.length > 0 ? ` + ${opts.adapters.join(", ")}` : " (only)"}`));
|
|
236
|
-
console.log(c.dim(`
|
|
292
|
+
console.log(c.dim(` Claude models: ${describeModelMap(opts.modelMap)}`));
|
|
293
|
+
if (opts.codexModelMap) console.log(c.dim(` Codex models: ${describeAnyMap(opts.codexModelMap)}`));
|
|
294
|
+
if (opts.geminiModelMap) console.log(c.dim(` Gemini models: ${describeAnyMap(opts.geminiModelMap)}`));
|
|
295
|
+
if (opts.aiderModel && opts.aiderModel !== "(skip)") console.log(c.dim(` Aider model: ${opts.aiderModel} (.aider.conf.yml)`));
|
|
237
296
|
if (scan.framework.startsWith("Next.js")) {
|
|
238
297
|
console.log(c.dim(` Chat-room UI: ${opts.installTemplate ? "install" : "skip"}`));
|
|
239
298
|
}
|
|
@@ -416,6 +475,9 @@ async function runInit(args) {
|
|
|
416
475
|
`--target=${opts.target}`,
|
|
417
476
|
"--yes"
|
|
418
477
|
]);
|
|
478
|
+
if (opts.codexModelMap && Object.keys(opts.codexModelMap).length > 0) await injectCodexModelMemos(opts.target, opts.codexModelMap);
|
|
479
|
+
if (opts.geminiModelMap && Object.keys(opts.geminiModelMap).length > 0) await injectGeminiModelMemos(opts.target, opts.geminiModelMap);
|
|
480
|
+
if (opts.aiderModel && opts.aiderModel !== "(skip)") await setAiderModel(opts.target, opts.aiderModel);
|
|
419
481
|
}
|
|
420
482
|
console.log(c.bold(c.green("\u2705 Done.")));
|
|
421
483
|
console.log();
|
|
@@ -470,9 +532,9 @@ async function promptInteractive(opts, scan) {
|
|
|
470
532
|
});
|
|
471
533
|
const isPreset = (t) => opts.adapters.includes(t);
|
|
472
534
|
const adaptersRaw = await checkbox({
|
|
473
|
-
message: "\uB3C4\uAD6C \uC120\uD0DD \u2014
|
|
535
|
+
message: "\uB3C4\uAD6C \uC120\uD0DD \u2014 \uCCB4\uD06C\uB41C \uB3C4\uAD6C\uB9CC \uC14B\uC5C5\uB429\uB2C8\uB2E4. (.claude/agents/ \uB294 \uC5B4\uB311\uD130 SoT \uB77C \uD56D\uC0C1 \uAE54\uB9BD\uB2C8\uB2E4)",
|
|
474
536
|
choices: [
|
|
475
|
-
{ name: "Claude Code (.claude/agents/)
|
|
537
|
+
{ name: "Claude Code (.claude/agents/)", value: "claude", checked: true },
|
|
476
538
|
{ name: "Cursor (.cursor/rules/bujang-*.mdc)", value: "cursor", checked: isPreset("cursor") },
|
|
477
539
|
{ name: "Codex / Copilot (AGENTS.md)", value: "codex", checked: isPreset("codex") },
|
|
478
540
|
{ name: "Cline (.clinerules/bujang-*.md)", value: "cline", checked: isPreset("cline") },
|
|
@@ -481,23 +543,66 @@ async function promptInteractive(opts, scan) {
|
|
|
481
543
|
],
|
|
482
544
|
required: false
|
|
483
545
|
});
|
|
546
|
+
const claudeChecked = adaptersRaw.includes("claude");
|
|
484
547
|
const adapters = adaptersRaw.filter((t) => t !== "claude");
|
|
485
|
-
const preset = await select({
|
|
486
|
-
message: "\uC5D0\uC774\uC804\uD2B8\uBCC4 Claude \uBAA8\uB378? (.claude/agents/ \uC5D0\uB9CC \uC801\uC6A9 \u2014 \uB2E4\uB978 \uB3C4\uAD6C\uB294 \uC790\uCCB4 \uBAA8\uB378 \uAD00\uB9AC)",
|
|
487
|
-
choices: [
|
|
488
|
-
{ name: "balanced \u2014 opus / sonnet / haiku \uADE0\uD615 \uB9E4\uD551 (\uCD94\uCC9C, \uBE44\uC6A9 ~60% \uC808\uAC10)", value: "balanced" },
|
|
489
|
-
{ name: "keep \u2014 \uAC01 \uC5D0\uC774\uC804\uD2B8 \uAE30\uBCF8 \uBAA8\uB378 \uADF8\uB300\uB85C", value: "keep" },
|
|
490
|
-
{ name: "cost \u2014 \uC804\uBD80 haiku (\uAC00\uC7A5 \uC800\uB834, \uBE60\uB984)", value: "cost" },
|
|
491
|
-
{ name: "quality \u2014 \uC804\uBD80 opus (\uAC00\uC7A5 \uBE44\uC2F8\uACE0, \uD488\uC9C8 \uCD5C\uC0C1)", value: "quality" },
|
|
492
|
-
{ name: "custom \u2014 \uC5D0\uC774\uC804\uD2B8\uBCC4 \uC9C1\uC811 \uC120\uD0DD (18\uAC1C prompt)", value: "custom" }
|
|
493
|
-
],
|
|
494
|
-
default: "balanced"
|
|
495
|
-
});
|
|
496
548
|
let modelMap = {};
|
|
497
|
-
if (
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
549
|
+
if (claudeChecked) {
|
|
550
|
+
const preset = await select({
|
|
551
|
+
message: "\u{1F7E3} Claude \uC5D0\uC774\uC804\uD2B8 \uBAA8\uB378 \uB9E4\uD551? [.claude/agents/ frontmatter \uC5D0 \uBC15\uD798 \u2014 Claude Code \uAC00 \uC9C4\uC9DC \uC801\uC6A9]",
|
|
552
|
+
choices: [
|
|
553
|
+
{ name: "balanced \u2014 opus / sonnet / haiku \uADE0\uD615 \uB9E4\uD551 (\uCD94\uCC9C, \uBE44\uC6A9 ~60% \uC808\uAC10)", value: "balanced" },
|
|
554
|
+
{ name: "keep \u2014 \uAC01 \uC5D0\uC774\uC804\uD2B8 \uAE30\uBCF8 \uBAA8\uB378 \uADF8\uB300\uB85C", value: "keep" },
|
|
555
|
+
{ name: "cost \u2014 \uC804\uBD80 haiku (\uAC00\uC7A5 \uC800\uB834, \uBE60\uB984)", value: "cost" },
|
|
556
|
+
{ name: "quality \u2014 \uC804\uBD80 opus (\uAC00\uC7A5 \uBE44\uC2F8\uACE0, \uD488\uC9C8 \uCD5C\uC0C1)", value: "quality" },
|
|
557
|
+
{ name: "custom \u2014 \uC5D0\uC774\uC804\uD2B8\uBCC4 \uC9C1\uC811 \uC120\uD0DD (18\uAC1C prompt)", value: "custom" }
|
|
558
|
+
],
|
|
559
|
+
default: "balanced"
|
|
560
|
+
});
|
|
561
|
+
modelMap = preset === "custom" ? await promptCustomModelMap() : resolvePreset(preset);
|
|
562
|
+
}
|
|
563
|
+
let codexModelMap;
|
|
564
|
+
if (adapters.includes("codex")) {
|
|
565
|
+
const preset = await select({
|
|
566
|
+
message: "\u{1F7E2} Codex \uC5D0\uC774\uC804\uD2B8 \uBAA8\uB378 \uB9E4\uD551? [AGENTS.md \uC758 \uAC01 \uC5D0\uC774\uC804\uD2B8 \uC139\uC158\uC5D0 \uBA54\uBAA8\uB85C \uBC15\uD798 \u2014 \uAC00\uC774\uB4DC\uC6A9]",
|
|
567
|
+
choices: [
|
|
568
|
+
{ name: "balanced \u2014 gpt-5 / gpt-5-codex / o1 / gpt-4-turbo \uC5ED\uD560\uBCC4 \uB9E4\uD551 (\uCD94\uCC9C)", value: "balanced" },
|
|
569
|
+
{ name: "keep \u2014 \uBA54\uBAA8 \uC548 \uBC15\uC74C (\uC0AC\uC6A9\uC790\uAC00 \uCF54\uB371\uC2A4 \uC548\uC5D0\uC11C \uD53D)", value: "keep" },
|
|
570
|
+
{ name: "cost \u2014 \uC804\uBD80 gpt-4-turbo (\uAC00\uC7A5 \uC800\uB834)", value: "cost" },
|
|
571
|
+
{ name: "quality \u2014 \uC804\uBD80 gpt-5 (\uAC00\uC7A5 \uB611\uB611)", value: "quality" },
|
|
572
|
+
{ name: "custom \u2014 \uC5D0\uC774\uC804\uD2B8\uBCC4 \uC9C1\uC811 \uC120\uD0DD (18\uAC1C prompt)", value: "custom" }
|
|
573
|
+
],
|
|
574
|
+
default: "balanced"
|
|
575
|
+
});
|
|
576
|
+
codexModelMap = preset === "custom" ? await promptCustomCodexMap() : resolveCodexPreset(preset);
|
|
577
|
+
}
|
|
578
|
+
let geminiModelMap;
|
|
579
|
+
if (adapters.includes("gemini")) {
|
|
580
|
+
const preset = await select({
|
|
581
|
+
message: "\u{1F535} Gemini \uC5D0\uC774\uC804\uD2B8 \uBAA8\uB378 \uB9E4\uD551? [GEMINI.md \uC758 \uAC01 \uC5D0\uC774\uC804\uD2B8 \uC139\uC158\uC5D0 \uBA54\uBAA8\uB85C \uBC15\uD798 \u2014 \uAC00\uC774\uB4DC\uC6A9]",
|
|
582
|
+
choices: [
|
|
583
|
+
{ name: "balanced \u2014 pro / flash \uC5ED\uD560\uBCC4 \uB9E4\uD551 (\uCD94\uCC9C)", value: "balanced" },
|
|
584
|
+
{ name: "keep \u2014 \uBA54\uBAA8 \uC548 \uBC15\uC74C (Gemini \uB3C4\uAD6C \uC548\uC5D0\uC11C \uD53D)", value: "keep" },
|
|
585
|
+
{ name: "cost \u2014 \uC804\uBD80 gemini-2.5-flash (\uAC00\uC7A5 \uBE60\uB974\uACE0 \uC800\uB834)", value: "cost" },
|
|
586
|
+
{ name: "quality \u2014 \uC804\uBD80 gemini-2.5-pro (\uAC00\uC7A5 \uB611\uB611)", value: "quality" },
|
|
587
|
+
{ name: "custom \u2014 \uC5D0\uC774\uC804\uD2B8\uBCC4 \uC9C1\uC811 \uC120\uD0DD (18\uAC1C prompt)", value: "custom" }
|
|
588
|
+
],
|
|
589
|
+
default: "balanced"
|
|
590
|
+
});
|
|
591
|
+
geminiModelMap = preset === "custom" ? await promptCustomGeminiMap() : resolveGeminiPreset(preset);
|
|
592
|
+
}
|
|
593
|
+
let aiderModel;
|
|
594
|
+
if (adapters.includes("aider")) {
|
|
595
|
+
aiderModel = await select({
|
|
596
|
+
message: "\u{1F7E1} Aider \uBAA8\uB378? [.aider.conf.yml \uC758 model \uD544\uB4DC\uC5D0 \uBC15\uD798 \u2014 Aider \uAC00 \uC2DC\uC791 \uC2DC \uC9C4\uC9DC \uC801\uC6A9]",
|
|
597
|
+
choices: [
|
|
598
|
+
{ name: "claude-opus-4-7 (\uCD5C\uACE0 \uD488\uC9C8)", value: "claude-opus-4-7" },
|
|
599
|
+
{ name: "claude-sonnet-4-6 (\uADE0\uD615)", value: "claude-sonnet-4-6" },
|
|
600
|
+
{ name: "gpt-5 (OpenAI \uCD5C\uC2E0)", value: "gpt-5" },
|
|
601
|
+
{ name: "gemini-2.5-pro (Google \uCD5C\uC2E0)", value: "gemini-2.5-pro" },
|
|
602
|
+
{ name: "(skip) (model \uD544\uB4DC \uC548 \uBC15\uC74C)", value: "(skip)" }
|
|
603
|
+
],
|
|
604
|
+
default: "claude-sonnet-4-6"
|
|
605
|
+
});
|
|
501
606
|
}
|
|
502
607
|
let installTemplate = opts.installTemplate;
|
|
503
608
|
if (scan.framework.startsWith("Next.js") && opts.installTemplate) {
|
|
@@ -506,7 +611,58 @@ async function promptInteractive(opts, scan) {
|
|
|
506
611
|
default: true
|
|
507
612
|
});
|
|
508
613
|
}
|
|
509
|
-
return {
|
|
614
|
+
return {
|
|
615
|
+
...opts,
|
|
616
|
+
lang,
|
|
617
|
+
chatBackend,
|
|
618
|
+
installTemplate,
|
|
619
|
+
adapters,
|
|
620
|
+
modelMap,
|
|
621
|
+
codexModelMap,
|
|
622
|
+
geminiModelMap,
|
|
623
|
+
aiderModel
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
async function promptCustomCodexMap() {
|
|
627
|
+
const out = {};
|
|
628
|
+
const slugs = Object.keys(CODEX_BALANCED);
|
|
629
|
+
console.log();
|
|
630
|
+
console.log(c.dim(` Codex custom \uB9E4\uD551 \u2014 ${slugs.length}\uAC1C \uC5D0\uC774\uC804\uD2B8\uB9C8\uB2E4 \uBAA8\uB378\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694.`));
|
|
631
|
+
for (const slug of slugs) {
|
|
632
|
+
const tier = await select({
|
|
633
|
+
message: `${slug.padEnd(20)}`,
|
|
634
|
+
choices: [
|
|
635
|
+
{ name: "gpt-5 (\uCD5C\uC2E0, \uD070 \uACB0\uC815)", value: "gpt-5" },
|
|
636
|
+
{ name: "gpt-5-codex (\uCF54\uB529 \uD2B9\uD654)", value: "gpt-5-codex" },
|
|
637
|
+
{ name: "gpt-4-turbo (\uADE0\uD615)", value: "gpt-4-turbo" },
|
|
638
|
+
{ name: "o1 (\uCD94\uB860 \uD2B9\uD654)", value: "o1" },
|
|
639
|
+
{ name: "o1-mini (\uAC00\uBCBC\uC6B4, \uBE60\uB984)", value: "o1-mini" }
|
|
640
|
+
],
|
|
641
|
+
default: CODEX_BALANCED[slug] ?? "gpt-4-turbo"
|
|
642
|
+
});
|
|
643
|
+
out[slug] = tier;
|
|
644
|
+
}
|
|
645
|
+
return out;
|
|
646
|
+
}
|
|
647
|
+
async function promptCustomGeminiMap() {
|
|
648
|
+
const out = {};
|
|
649
|
+
const slugs = Object.keys(GEMINI_BALANCED);
|
|
650
|
+
console.log();
|
|
651
|
+
console.log(c.dim(` Gemini custom \uB9E4\uD551 \u2014 ${slugs.length}\uAC1C \uC5D0\uC774\uC804\uD2B8\uB9C8\uB2E4 \uBAA8\uB378\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694.`));
|
|
652
|
+
for (const slug of slugs) {
|
|
653
|
+
const tier = await select({
|
|
654
|
+
message: `${slug.padEnd(20)}`,
|
|
655
|
+
choices: [
|
|
656
|
+
{ name: "gemini-2.5-pro (\uCD5C\uC2E0, \uAC00\uC7A5 \uB611\uB611)", value: "gemini-2.5-pro" },
|
|
657
|
+
{ name: "gemini-2.5-flash (\uBE60\uB974\uACE0 \uC800\uB834)", value: "gemini-2.5-flash" },
|
|
658
|
+
{ name: "gemini-2.0-pro", value: "gemini-2.0-pro" },
|
|
659
|
+
{ name: "gemini-2.0-flash", value: "gemini-2.0-flash" }
|
|
660
|
+
],
|
|
661
|
+
default: GEMINI_BALANCED[slug] ?? "gemini-2.5-flash"
|
|
662
|
+
});
|
|
663
|
+
out[slug] = tier;
|
|
664
|
+
}
|
|
665
|
+
return out;
|
|
510
666
|
}
|
|
511
667
|
async function promptCustomModelMap() {
|
|
512
668
|
const out = {};
|
|
@@ -561,6 +717,23 @@ function parseArgs(args) {
|
|
|
561
717
|
}
|
|
562
718
|
modelMap = resolvePreset(modelsRaw);
|
|
563
719
|
}
|
|
720
|
+
const codexPresetRaw = getFlag(args, "--codex-models");
|
|
721
|
+
const geminiPresetRaw = getFlag(args, "--gemini-models");
|
|
722
|
+
let codexModelMap;
|
|
723
|
+
let geminiModelMap;
|
|
724
|
+
if (codexPresetRaw) {
|
|
725
|
+
if (!["balanced", "cost", "quality", "keep"].includes(codexPresetRaw)) {
|
|
726
|
+
throw new Error(`--codex-models must be one of: balanced, cost, quality, keep (got "${codexPresetRaw}")`);
|
|
727
|
+
}
|
|
728
|
+
codexModelMap = resolveCodexPreset(codexPresetRaw);
|
|
729
|
+
}
|
|
730
|
+
if (geminiPresetRaw) {
|
|
731
|
+
if (!["balanced", "cost", "quality", "keep"].includes(geminiPresetRaw)) {
|
|
732
|
+
throw new Error(`--gemini-models must be one of: balanced, cost, quality, keep (got "${geminiPresetRaw}")`);
|
|
733
|
+
}
|
|
734
|
+
geminiModelMap = resolveGeminiPreset(geminiPresetRaw);
|
|
735
|
+
}
|
|
736
|
+
const aiderModel = getFlag(args, "--aider-model");
|
|
564
737
|
return {
|
|
565
738
|
lang,
|
|
566
739
|
target: path2.resolve(targetRaw),
|
|
@@ -573,7 +746,10 @@ function parseArgs(args) {
|
|
|
573
746
|
seedLearningLog: !args.includes("--no-learning-log"),
|
|
574
747
|
yes: args.includes("--yes") || args.includes("-y"),
|
|
575
748
|
adapters,
|
|
576
|
-
modelMap
|
|
749
|
+
modelMap,
|
|
750
|
+
codexModelMap,
|
|
751
|
+
geminiModelMap,
|
|
752
|
+
aiderModel
|
|
577
753
|
};
|
|
578
754
|
}
|
|
579
755
|
function resolvePreset(preset) {
|
|
@@ -692,6 +868,58 @@ function printBackendInstructions(backend, commitChat) {
|
|
|
692
868
|
}
|
|
693
869
|
console.log();
|
|
694
870
|
}
|
|
871
|
+
async function injectCodexModelMemos(target, modelMap) {
|
|
872
|
+
const fp = path2.join(target, "AGENTS.md");
|
|
873
|
+
if (!await exists2(fp)) return;
|
|
874
|
+
const raw = await fs2.readFile(fp, "utf8");
|
|
875
|
+
const updated = injectPerAgentMemos(raw, modelMap, "\uCF54\uB371\uC2A4 / Copilot \uC548\uC5D0\uC11C \uC774 \uBAA8\uB378\uB85C \uC791\uC5C5");
|
|
876
|
+
await fs2.writeFile(fp, updated);
|
|
877
|
+
const count = Object.keys(modelMap).length;
|
|
878
|
+
console.log(c.dim(` \u2713 AGENTS.md \u2190 Codex \uAD8C\uC7A5 \uBAA8\uB378 \uBA54\uBAA8 ${count}\uAC74 (\uAC01 \uC5D0\uC774\uC804\uD2B8 \uC139\uC158 \uC704)`));
|
|
879
|
+
}
|
|
880
|
+
async function injectGeminiModelMemos(target, modelMap) {
|
|
881
|
+
const fp = path2.join(target, "GEMINI.md");
|
|
882
|
+
if (!await exists2(fp)) return;
|
|
883
|
+
const raw = await fs2.readFile(fp, "utf8");
|
|
884
|
+
const updated = injectPerAgentMemos(raw, modelMap, "Gemini CLI / Antigravity \uC548\uC5D0\uC11C \uC774 \uBAA8\uB378\uB85C \uC791\uC5C5");
|
|
885
|
+
await fs2.writeFile(fp, updated);
|
|
886
|
+
const count = Object.keys(modelMap).length;
|
|
887
|
+
console.log(c.dim(` \u2713 GEMINI.md \u2190 Gemini \uAD8C\uC7A5 \uBAA8\uB378 \uBA54\uBAA8 ${count}\uAC74 (\uAC01 \uC5D0\uC774\uC804\uD2B8 \uC139\uC158 \uC704)`));
|
|
888
|
+
}
|
|
889
|
+
function injectPerAgentMemos(raw, modelMap, hint) {
|
|
890
|
+
const lines = raw.split("\n");
|
|
891
|
+
const out = [];
|
|
892
|
+
for (let i = 0; i < lines.length; i++) {
|
|
893
|
+
const line = lines[i];
|
|
894
|
+
const m = /^##\s+([a-z][a-z0-9-]*)\s*$/.exec(line);
|
|
895
|
+
if (m) {
|
|
896
|
+
const slug = m[1];
|
|
897
|
+
const model = modelMap[slug];
|
|
898
|
+
const prev = out[out.length - 1] ?? "";
|
|
899
|
+
if (model && !prev.includes("\u{1F4A1} Recommended")) {
|
|
900
|
+
out.push(`> \u{1F4A1} Recommended model: \`${model}\` \u2014 ${hint}`);
|
|
901
|
+
out.push("");
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
out.push(line);
|
|
905
|
+
}
|
|
906
|
+
return out.join("\n");
|
|
907
|
+
}
|
|
908
|
+
async function setAiderModel(target, model) {
|
|
909
|
+
const fp = path2.join(target, ".aider.conf.yml");
|
|
910
|
+
if (!await exists2(fp)) return;
|
|
911
|
+
let raw = await fs2.readFile(fp, "utf8");
|
|
912
|
+
if (/^model:\s*\S+/m.test(raw)) {
|
|
913
|
+
raw = raw.replace(/^model:\s*\S+/m, `model: ${model}`);
|
|
914
|
+
} else {
|
|
915
|
+
raw = raw.trimEnd() + `
|
|
916
|
+
# Added by harness-bujang init
|
|
917
|
+
model: ${model}
|
|
918
|
+
`;
|
|
919
|
+
}
|
|
920
|
+
await fs2.writeFile(fp, raw);
|
|
921
|
+
console.log(c.dim(` \u2713 .aider.conf.yml \u2190 model: ${model}`));
|
|
922
|
+
}
|
|
695
923
|
function overrideModelFrontmatter(content, model) {
|
|
696
924
|
if (!content.startsWith("---\n")) return content;
|
|
697
925
|
const end = content.indexOf("\n---\n", 4);
|
|
@@ -712,6 +940,13 @@ function describeModelMap(map) {
|
|
|
712
940
|
}
|
|
713
941
|
return parts.join(" \xB7 ");
|
|
714
942
|
}
|
|
943
|
+
function describeAnyMap(map) {
|
|
944
|
+
if (Object.keys(map).length === 0) return "keep (\uBA54\uBAA8 \uC548 \uBC15\uC74C)";
|
|
945
|
+
const counts = {};
|
|
946
|
+
for (const v of Object.values(map)) counts[v] = (counts[v] ?? 0) + 1;
|
|
947
|
+
const parts = Object.entries(counts).sort((a, b) => b[1] - a[1]).map(([model, n]) => `${n} ${model}`);
|
|
948
|
+
return parts.join(" \xB7 ");
|
|
949
|
+
}
|
|
715
950
|
function stackReviewRules(framework) {
|
|
716
951
|
if (framework.startsWith("Next.js")) {
|
|
717
952
|
return `Next.js App Router rules:
|
package/dist/index.js
CHANGED
|
@@ -189,7 +189,7 @@ async function main() {
|
|
|
189
189
|
const command = args[0];
|
|
190
190
|
switch (command) {
|
|
191
191
|
case "init":
|
|
192
|
-
await (await import("./init-
|
|
192
|
+
await (await import("./init-WAVPUHNL.js")).runInit(args.slice(1));
|
|
193
193
|
break;
|
|
194
194
|
case "status":
|
|
195
195
|
await (await import("./status-UE2TQQPU.js")).runStatus(args.slice(1));
|
|
@@ -201,7 +201,7 @@ async function main() {
|
|
|
201
201
|
await (await import("./adapt-VPWOYF6W.js")).runAdapt(args.slice(1));
|
|
202
202
|
break;
|
|
203
203
|
case "update":
|
|
204
|
-
await (await import("./update-
|
|
204
|
+
await (await import("./update-HAGOKTNL.js")).runUpdate(args.slice(1));
|
|
205
205
|
break;
|
|
206
206
|
case "migrate":
|
|
207
207
|
await (await import("./migrate-PISZFX6C.js")).runMigrate(args.slice(1));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "harness-bujang",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "Install the Harness-Bujang multi-agent harness into any project — Director, 7 specialist teams, real-time chat-room UI. Korean and English personas. Works with Claude Code, Cursor, Cline, Aider, or any tool that reads .claude/agents/.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|