@codemoot/cli 0.2.9 → 0.2.11
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/LICENSE +21 -0
- package/dist/index.js +84 -25
- package/dist/index.js.map +1 -1
- package/dist/prompts-GB7HH4EL.js +0 -0
- package/package.json +28 -12
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 CodeMoot Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.js
CHANGED
|
@@ -538,6 +538,7 @@ import {
|
|
|
538
538
|
preflightTokenCheck
|
|
539
539
|
} from "@codemoot/core";
|
|
540
540
|
import chalk4 from "chalk";
|
|
541
|
+
import { writeFileSync } from "fs";
|
|
541
542
|
async function debateStartCommand(topic, options) {
|
|
542
543
|
let db;
|
|
543
544
|
try {
|
|
@@ -560,7 +561,8 @@ async function debateStartCommand(topic, options) {
|
|
|
560
561
|
status: "running",
|
|
561
562
|
sessionIds: {},
|
|
562
563
|
resumeStats: { attempted: 0, succeeded: 0, fallbacks: 0 },
|
|
563
|
-
maxRounds: options.maxRounds ?? 5
|
|
564
|
+
maxRounds: options.maxRounds ?? 5,
|
|
565
|
+
defaultTimeout: options.timeout
|
|
564
566
|
});
|
|
565
567
|
const output = {
|
|
566
568
|
debateId,
|
|
@@ -605,9 +607,10 @@ async function debateTurnCommand(debateId, prompt, options) {
|
|
|
605
607
|
}
|
|
606
608
|
const rawRound = options.round ?? criticRow.round + 1;
|
|
607
609
|
const newRound = Number.isFinite(rawRound) && rawRound > 0 ? rawRound : criticRow.round + 1;
|
|
608
|
-
const rawTimeout = options.timeout ?? 600;
|
|
609
|
-
const timeout = (Number.isFinite(rawTimeout) && rawTimeout > 0 ? rawTimeout : 600) * 1e3;
|
|
610
610
|
const proposerStateForLimit = store.loadState(debateId, "proposer");
|
|
611
|
+
const storedTimeout = proposerStateForLimit?.defaultTimeout;
|
|
612
|
+
const rawTimeout = options.timeout ?? storedTimeout ?? 600;
|
|
613
|
+
const timeout = (Number.isFinite(rawTimeout) && rawTimeout > 0 ? rawTimeout : 600) * 1e3;
|
|
611
614
|
const rawMax = proposerStateForLimit?.maxRounds ?? 5;
|
|
612
615
|
const maxRounds = Number.isFinite(rawMax) && rawMax > 0 ? rawMax : 5;
|
|
613
616
|
if (newRound > maxRounds) {
|
|
@@ -626,10 +629,16 @@ async function debateTurnCommand(debateId, prompt, options) {
|
|
|
626
629
|
status: "active"
|
|
627
630
|
});
|
|
628
631
|
}
|
|
632
|
+
if (options.output && existing.responseText) {
|
|
633
|
+
writeFileSync(options.output, existing.responseText, "utf-8");
|
|
634
|
+
console.error(chalk4.dim(`Full response written to ${options.output}`));
|
|
635
|
+
}
|
|
629
636
|
const output = {
|
|
630
637
|
debateId,
|
|
631
638
|
round: newRound,
|
|
632
639
|
response: existing.responseText?.slice(0, 2e3) ?? "",
|
|
640
|
+
responseTruncated: (existing.responseText?.length ?? 0) > 2e3,
|
|
641
|
+
responseFile: options.output ?? void 0,
|
|
633
642
|
sessionId: existing.sessionId,
|
|
634
643
|
resumed: false,
|
|
635
644
|
cached: true,
|
|
@@ -671,10 +680,16 @@ async function debateTurnCommand(debateId, prompt, options) {
|
|
|
671
680
|
if (!msgStore.markRunning(msgId)) {
|
|
672
681
|
const recheckRow = msgStore.getByRound(debateId, newRound, "critic");
|
|
673
682
|
if (recheckRow?.status === "completed") {
|
|
683
|
+
if (options.output && recheckRow.responseText) {
|
|
684
|
+
writeFileSync(options.output, recheckRow.responseText, "utf-8");
|
|
685
|
+
console.error(chalk4.dim(`Full response written to ${options.output}`));
|
|
686
|
+
}
|
|
674
687
|
const output = {
|
|
675
688
|
debateId,
|
|
676
689
|
round: newRound,
|
|
677
690
|
response: recheckRow.responseText?.slice(0, 2e3) ?? "",
|
|
691
|
+
responseTruncated: (recheckRow.responseText?.length ?? 0) > 2e3,
|
|
692
|
+
responseFile: options.output ?? void 0,
|
|
678
693
|
sessionId: recheckRow.sessionId,
|
|
679
694
|
resumed: false,
|
|
680
695
|
cached: true,
|
|
@@ -702,14 +717,20 @@ async function debateTurnCommand(debateId, prompt, options) {
|
|
|
702
717
|
const completedHistory = msgStore.getHistory(debateId).filter((m) => m.status === "completed");
|
|
703
718
|
const maxContext = adapter.capabilities.maxContextTokens;
|
|
704
719
|
const preflight = preflightTokenCheck(completedHistory, prompt, maxContext);
|
|
705
|
-
if (preflight.shouldStop) {
|
|
706
|
-
console.error(chalk4.
|
|
720
|
+
if (preflight.shouldStop && !options.force) {
|
|
721
|
+
console.error(chalk4.red(`Token budget at ${Math.round(preflight.utilizationRatio * 100)}% (${preflight.totalTokensUsed}/${maxContext}). Debate blocked \u2014 use --force to override.`));
|
|
722
|
+
db.close();
|
|
723
|
+
process.exit(1);
|
|
724
|
+
} else if (preflight.shouldStop && options.force) {
|
|
725
|
+
console.error(chalk4.yellow(` Token budget at ${Math.round(preflight.utilizationRatio * 100)}% (${preflight.totalTokensUsed}/${maxContext}) \u2014 forced past budget limit.`));
|
|
707
726
|
} else if (preflight.shouldSummarize) {
|
|
708
727
|
console.error(chalk4.yellow(` Token budget at ${Math.round(preflight.utilizationRatio * 100)}%. Older rounds will be summarized on resume failure.`));
|
|
709
728
|
}
|
|
710
729
|
const overflowCheck = sessionMgr.preCallOverflowCheck(unifiedSession.id);
|
|
711
730
|
if (overflowCheck.rolled) {
|
|
712
731
|
console.error(chalk4.yellow(` ${overflowCheck.message}`));
|
|
732
|
+
console.error(chalk4.yellow(" Warning: Session rolled over \u2014 previous conversation context has been lost."));
|
|
733
|
+
sessionMgr.updateThreadId(unifiedSession.id, null);
|
|
713
734
|
existingSessionId = void 0;
|
|
714
735
|
}
|
|
715
736
|
try {
|
|
@@ -781,11 +802,16 @@ async function debateTurnCommand(debateId, prompt, options) {
|
|
|
781
802
|
proposerState.resumeStats = stats;
|
|
782
803
|
store.saveState(debateId, "proposer", proposerState);
|
|
783
804
|
}
|
|
805
|
+
if (options.output) {
|
|
806
|
+
writeFileSync(options.output, result.text, "utf-8");
|
|
807
|
+
console.error(chalk4.dim(`Full response written to ${options.output}`));
|
|
808
|
+
}
|
|
784
809
|
const output = {
|
|
785
810
|
debateId,
|
|
786
811
|
round: newRound,
|
|
787
812
|
response: result.text.slice(0, 2e3),
|
|
788
813
|
responseTruncated: result.text.length > 2e3,
|
|
814
|
+
responseFile: options.output ?? void 0,
|
|
789
815
|
sessionId: result.sessionId,
|
|
790
816
|
resumed,
|
|
791
817
|
cached: false,
|
|
@@ -800,7 +826,7 @@ Round ${newRound} \u2014 Stance: ${verdict.stance}`));
|
|
|
800
826
|
for (const line of previewLines) {
|
|
801
827
|
console.error(chalk4.dim(` ${line.trim().slice(0, 120)}`));
|
|
802
828
|
}
|
|
803
|
-
console.error(chalk4.dim(`Duration: ${(result.durationMs / 1e3).toFixed(1)}s |
|
|
829
|
+
console.error(chalk4.dim(`Duration: ${(result.durationMs / 1e3).toFixed(1)}s | Output: ${result.usage?.outputTokens ?? "?"} tokens | Input: ${result.usage?.inputTokens ?? "?"} (includes sandbox) | Resumed: ${resumed}`));
|
|
804
830
|
console.log(JSON.stringify(output, null, 2));
|
|
805
831
|
} catch (error) {
|
|
806
832
|
msgStore.markFailed(msgId, error instanceof Error ? error.message : String(error));
|
|
@@ -813,6 +839,10 @@ Round ${newRound} \u2014 Stance: ${verdict.stance}`));
|
|
|
813
839
|
process.exit(1);
|
|
814
840
|
}
|
|
815
841
|
}
|
|
842
|
+
async function debateNextCommand(debateId, options) {
|
|
843
|
+
const prompt = "Continue your analysis. Respond to the previous round's arguments and refine your position.";
|
|
844
|
+
return debateTurnCommand(debateId, prompt, options);
|
|
845
|
+
}
|
|
816
846
|
async function debateStatusCommand(debateId) {
|
|
817
847
|
let db;
|
|
818
848
|
try {
|
|
@@ -893,7 +923,7 @@ async function debateListCommand(options) {
|
|
|
893
923
|
process.exit(1);
|
|
894
924
|
}
|
|
895
925
|
}
|
|
896
|
-
async function debateHistoryCommand(debateId) {
|
|
926
|
+
async function debateHistoryCommand(debateId, options = {}) {
|
|
897
927
|
let db;
|
|
898
928
|
try {
|
|
899
929
|
const dbPath = getDbPath();
|
|
@@ -937,6 +967,29 @@ async function debateHistoryCommand(debateId) {
|
|
|
937
967
|
completedAt: m.completedAt ? new Date(m.completedAt).toISOString() : null
|
|
938
968
|
}))
|
|
939
969
|
};
|
|
970
|
+
if (options.output) {
|
|
971
|
+
const fullOutput = {
|
|
972
|
+
...output,
|
|
973
|
+
messages: history.map((m) => ({
|
|
974
|
+
round: m.round,
|
|
975
|
+
role: m.role,
|
|
976
|
+
bridge: m.bridge,
|
|
977
|
+
model: m.model,
|
|
978
|
+
status: m.status,
|
|
979
|
+
stance: m.stance,
|
|
980
|
+
confidence: m.confidence,
|
|
981
|
+
durationMs: m.durationMs,
|
|
982
|
+
sessionId: m.sessionId,
|
|
983
|
+
promptText: m.promptText,
|
|
984
|
+
responseText: m.responseText ?? null,
|
|
985
|
+
error: m.error,
|
|
986
|
+
createdAt: new Date(m.createdAt).toISOString(),
|
|
987
|
+
completedAt: m.completedAt ? new Date(m.completedAt).toISOString() : null
|
|
988
|
+
}))
|
|
989
|
+
};
|
|
990
|
+
writeFileSync(options.output, JSON.stringify(fullOutput, null, 2), "utf-8");
|
|
991
|
+
console.error(chalk4.dim(`Full history written to ${options.output}`));
|
|
992
|
+
}
|
|
940
993
|
console.log(JSON.stringify(output, null, 2));
|
|
941
994
|
db.close();
|
|
942
995
|
} catch (error) {
|
|
@@ -1199,8 +1252,8 @@ Scan complete in ${(durationMs / 1e3).toFixed(1)}s`));
|
|
|
1199
1252
|
durationMs
|
|
1200
1253
|
});
|
|
1201
1254
|
if (options.output) {
|
|
1202
|
-
const { writeFileSync:
|
|
1203
|
-
|
|
1255
|
+
const { writeFileSync: writeFileSync5 } = await import("fs");
|
|
1256
|
+
writeFileSync5(options.output, JSON.stringify(report, null, 2), "utf-8");
|
|
1204
1257
|
console.error(chalk5.green(` Findings written to ${options.output}`));
|
|
1205
1258
|
}
|
|
1206
1259
|
const reportJson = JSON.stringify(report, null, 2);
|
|
@@ -1618,7 +1671,7 @@ async function eventsCommand(options) {
|
|
|
1618
1671
|
|
|
1619
1672
|
// src/commands/fix.ts
|
|
1620
1673
|
import { execFileSync as execFileSync2, execSync as execSync3 } from "child_process";
|
|
1621
|
-
import { readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
1674
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
1622
1675
|
import { resolve } from "path";
|
|
1623
1676
|
import {
|
|
1624
1677
|
DEFAULT_RULES,
|
|
@@ -1666,7 +1719,7 @@ function applyFix(fix, projectDir) {
|
|
|
1666
1719
|
const trimmedOld = fix.oldCode.trim();
|
|
1667
1720
|
if (content.includes(trimmedOld)) {
|
|
1668
1721
|
const updated = content.replace(trimmedOld, fix.newCode.trim());
|
|
1669
|
-
|
|
1722
|
+
writeFileSync2(filePath, updated, "utf-8");
|
|
1670
1723
|
return true;
|
|
1671
1724
|
}
|
|
1672
1725
|
return false;
|
|
@@ -1676,7 +1729,7 @@ function applyFix(fix, projectDir) {
|
|
|
1676
1729
|
const newLines = fix.newCode.trim().split("\n");
|
|
1677
1730
|
const oldLineCount = Math.max(1, newLines.length);
|
|
1678
1731
|
lines.splice(lineIdx, oldLineCount, ...newLines);
|
|
1679
|
-
|
|
1732
|
+
writeFileSync2(filePath, lines.join("\n"), "utf-8");
|
|
1680
1733
|
return true;
|
|
1681
1734
|
}
|
|
1682
1735
|
async function fixCommand(fileOrGlob, options) {
|
|
@@ -1999,7 +2052,7 @@ Initialized with '${presetName}' preset`));
|
|
|
1999
2052
|
}
|
|
2000
2053
|
|
|
2001
2054
|
// src/commands/install-skills.ts
|
|
2002
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as
|
|
2055
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
2003
2056
|
import { dirname, join as join5 } from "path";
|
|
2004
2057
|
import chalk11 from "chalk";
|
|
2005
2058
|
var SKILLS = [
|
|
@@ -2449,7 +2502,7 @@ async function installSkillsCommand(options) {
|
|
|
2449
2502
|
continue;
|
|
2450
2503
|
}
|
|
2451
2504
|
mkdirSync2(dir, { recursive: true });
|
|
2452
|
-
|
|
2505
|
+
writeFileSync3(fullPath, skill.content, "utf-8");
|
|
2453
2506
|
console.error(chalk11.green(` OK ${skill.path}`));
|
|
2454
2507
|
installed++;
|
|
2455
2508
|
}
|
|
@@ -2467,7 +2520,7 @@ async function installSkillsCommand(options) {
|
|
|
2467
2520
|
const afterMarker = sectionEnd >= 0 ? existing.slice(sectionEnd + CLAUDE_MD_SECTION.trimEnd().length) : existing.slice(markerIdx + marker.length);
|
|
2468
2521
|
const nextHeadingMatch = sectionEnd >= 0 ? null : afterMarker.match(/\n#{1,6} (?!CodeMoot)/);
|
|
2469
2522
|
const after = nextHeadingMatch ? afterMarker.slice(nextHeadingMatch.index) : "";
|
|
2470
|
-
|
|
2523
|
+
writeFileSync3(claudeMdPath, before.trimEnd() + "\n" + CLAUDE_MD_SECTION + after, "utf-8");
|
|
2471
2524
|
console.error(chalk11.green(" OK CLAUDE.md (updated CodeMoot section)"));
|
|
2472
2525
|
installed++;
|
|
2473
2526
|
} else {
|
|
@@ -2475,12 +2528,12 @@ async function installSkillsCommand(options) {
|
|
|
2475
2528
|
skipped++;
|
|
2476
2529
|
}
|
|
2477
2530
|
} else {
|
|
2478
|
-
|
|
2531
|
+
writeFileSync3(claudeMdPath, existing.trimEnd() + "\n" + CLAUDE_MD_SECTION, "utf-8");
|
|
2479
2532
|
console.error(chalk11.green(" OK CLAUDE.md (appended CodeMoot section)"));
|
|
2480
2533
|
installed++;
|
|
2481
2534
|
}
|
|
2482
2535
|
} else {
|
|
2483
|
-
|
|
2536
|
+
writeFileSync3(claudeMdPath, `# Project Instructions
|
|
2484
2537
|
${CLAUDE_MD_SECTION}`, "utf-8");
|
|
2485
2538
|
console.error(chalk11.green(" OK CLAUDE.md (created with CodeMoot section)"));
|
|
2486
2539
|
installed++;
|
|
@@ -2502,7 +2555,7 @@ ${CLAUDE_MD_SECTION}`, "utf-8");
|
|
|
2502
2555
|
...existing.hooks,
|
|
2503
2556
|
PostToolUse: [...otherHooks, ...HOOKS_CONFIG.hooks.PostToolUse]
|
|
2504
2557
|
};
|
|
2505
|
-
|
|
2558
|
+
writeFileSync3(settingsPath, JSON.stringify(existing, null, 2), "utf-8");
|
|
2506
2559
|
console.error(chalk11.green(" OK .claude/settings.json (added post-commit hint hook)"));
|
|
2507
2560
|
installed++;
|
|
2508
2561
|
}
|
|
@@ -2513,7 +2566,7 @@ ${CLAUDE_MD_SECTION}`, "utf-8");
|
|
|
2513
2566
|
}
|
|
2514
2567
|
} else {
|
|
2515
2568
|
mkdirSync2(settingsDir, { recursive: true });
|
|
2516
|
-
|
|
2569
|
+
writeFileSync3(settingsPath, JSON.stringify(HOOKS_CONFIG, null, 2), "utf-8");
|
|
2517
2570
|
console.error(chalk11.green(" OK .claude/settings.json (created with post-commit hook)"));
|
|
2518
2571
|
installed++;
|
|
2519
2572
|
}
|
|
@@ -2811,7 +2864,7 @@ async function jobsStatusCommand(jobId) {
|
|
|
2811
2864
|
}
|
|
2812
2865
|
|
|
2813
2866
|
// src/commands/plan.ts
|
|
2814
|
-
import { readFileSync as readFileSync4, writeFileSync as
|
|
2867
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
2815
2868
|
import {
|
|
2816
2869
|
ModelRegistry as ModelRegistry4,
|
|
2817
2870
|
Orchestrator,
|
|
@@ -2928,7 +2981,7 @@ async function planGenerateCommand(task, options) {
|
|
|
2928
2981
|
maxRounds: options.rounds
|
|
2929
2982
|
});
|
|
2930
2983
|
if (options.output) {
|
|
2931
|
-
|
|
2984
|
+
writeFileSync4(options.output, result.finalOutput, "utf-8");
|
|
2932
2985
|
console.error(chalk15.green(`Plan saved to ${options.output}`));
|
|
2933
2986
|
}
|
|
2934
2987
|
printSessionSummary(result);
|
|
@@ -3079,7 +3132,7 @@ Verdict: ${verdict.toUpperCase()} (${score ?? "?"}/10)`));
|
|
|
3079
3132
|
};
|
|
3080
3133
|
console.log(JSON.stringify(output, null, 2));
|
|
3081
3134
|
if (options.output) {
|
|
3082
|
-
|
|
3135
|
+
writeFileSync4(options.output, JSON.stringify(output, null, 2), "utf-8");
|
|
3083
3136
|
console.error(chalk15.green(`Review saved to ${options.output}`));
|
|
3084
3137
|
}
|
|
3085
3138
|
db.close();
|
|
@@ -3985,11 +4038,17 @@ var plan = program.command("plan").description("Plan generation and review \u201
|
|
|
3985
4038
|
plan.command("generate").description("Generate a plan using architect + reviewer loop").argument("<task>", "Task to plan").option("--rounds <n>", "Max plan-review rounds", (v) => Number.parseInt(v, 10), 3).option("--output <file>", "Save plan to file").action(planGenerateCommand);
|
|
3986
4039
|
plan.command("review").description("Send a host-authored plan to codex for review").argument("<plan-file>", "Plan file to review (use - for stdin)").option("--build <id>", "Link review to a build ID").option("--phase <id>", 'Phase identifier (e.g. "1", "setup")').option("--timeout <seconds>", "Review timeout", (v) => Number.parseInt(v, 10), 300).option("--output <file>", "Save review result to file").action(planReviewCommand);
|
|
3987
4040
|
var debate = program.command("debate").description("Multi-model debate with session persistence");
|
|
3988
|
-
debate.command("start").description("Start a new debate").argument("<topic>", "Debate topic or question").option("--max-rounds <n>", "Max debate rounds", (v) => Number.parseInt(v, 10), 5).
|
|
3989
|
-
|
|
4041
|
+
debate.command("start").description("Start a new debate").argument("<topic>", "Debate topic or question").option("--max-rounds <n>", "Max debate rounds", (v) => Number.parseInt(v, 10), 5).option("--timeout <seconds>", "Default timeout for debate turns in seconds", (v) => {
|
|
4042
|
+
if (!/^\d+$/.test(v)) throw new InvalidArgumentError("Timeout must be a positive integer");
|
|
4043
|
+
const n = Number.parseInt(v, 10);
|
|
4044
|
+
if (n <= 0) throw new InvalidArgumentError("Timeout must be a positive integer");
|
|
4045
|
+
return n;
|
|
4046
|
+
}).action(debateStartCommand);
|
|
4047
|
+
debate.command("turn").description("Send a prompt to GPT and get critique (with session resume)").argument("<debate-id>", "Debate ID from start command").argument("<prompt>", "Prompt to send to GPT").option("--round <n>", "Round number", (v) => Number.parseInt(v, 10)).option("--timeout <seconds>", "Timeout in seconds", (v) => Number.parseInt(v, 10)).option("--output <file>", "Write full untruncated response to file").option("--force", "Continue past token budget limit", false).action(debateTurnCommand);
|
|
4048
|
+
debate.command("next").description("Continue debate with auto-generated prompt").argument("<debate-id>", "Debate ID").option("--timeout <seconds>", "Timeout in seconds", (v) => Number.parseInt(v, 10)).option("--output <file>", "Write full untruncated response to file").option("--force", "Continue past token budget limit", false).action(debateNextCommand);
|
|
3990
4049
|
debate.command("status").description("Show debate status and session info").argument("<debate-id>", "Debate ID").action(debateStatusCommand);
|
|
3991
4050
|
debate.command("list").description("List all debates").option("--status <status>", "Filter by status (active|completed|stale)").option("--limit <n>", "Max results", (v) => Number.parseInt(v, 10), 20).action(debateListCommand);
|
|
3992
|
-
debate.command("history").description("Show full message history with token budget").argument("<debate-id>", "Debate ID").action(debateHistoryCommand);
|
|
4051
|
+
debate.command("history").description("Show full message history with token budget").argument("<debate-id>", "Debate ID").option("--output <file>", "Write full untruncated history to file").action(debateHistoryCommand);
|
|
3993
4052
|
debate.command("complete").description("Mark a debate as completed").argument("<debate-id>", "Debate ID").action(debateCompleteCommand);
|
|
3994
4053
|
var build = program.command("build").description("Automated build loop: debate \u2192 plan \u2192 implement \u2192 review \u2192 fix");
|
|
3995
4054
|
build.command("start").description("Start a new build session").argument("<task>", "Task description").option("--max-rounds <n>", "Max debate rounds", (v) => Number.parseInt(v, 10), 5).option("--allow-dirty", "Allow starting with dirty working tree (auto-stashes)").action(buildStartCommand);
|