@codemoot/cli 0.2.13 → 0.2.14
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/index.js +108 -100
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -424,12 +424,8 @@ async function buildReviewCommand(buildId) {
|
|
|
424
424
|
}
|
|
425
425
|
const sessionMgr = new SessionManager(db);
|
|
426
426
|
const session2 = sessionMgr.resolveActive("build-review");
|
|
427
|
-
const overflowCheck = sessionMgr.preCallOverflowCheck(session2.id);
|
|
428
|
-
if (overflowCheck.rolled) {
|
|
429
|
-
console.error(chalk3.yellow(` ${overflowCheck.message}`));
|
|
430
|
-
}
|
|
431
427
|
const currentSession = sessionMgr.get(session2.id);
|
|
432
|
-
const existingSession =
|
|
428
|
+
const existingSession = currentSession?.codexThreadId ?? run.reviewCodexSession ?? void 0;
|
|
433
429
|
const prompt = buildHandoffEnvelope({
|
|
434
430
|
command: "build-review",
|
|
435
431
|
task: `Review code changes for the task: "${run.task}"
|
|
@@ -486,7 +482,7 @@ Review for:
|
|
|
486
482
|
buildStore.updateWithEvent(
|
|
487
483
|
buildId,
|
|
488
484
|
{
|
|
489
|
-
reviewCodexSession: result.sessionId ??
|
|
485
|
+
reviewCodexSession: result.sessionId ?? void 0,
|
|
490
486
|
reviewCycles: run.reviewCycles + 1
|
|
491
487
|
},
|
|
492
488
|
{
|
|
@@ -550,7 +546,8 @@ import {
|
|
|
550
546
|
preflightTokenCheck
|
|
551
547
|
} from "@codemoot/core";
|
|
552
548
|
import chalk4 from "chalk";
|
|
553
|
-
import { writeFileSync } from "fs";
|
|
549
|
+
import { mkdirSync as mkdirSync2, writeFileSync } from "fs";
|
|
550
|
+
import { join as join3 } from "path";
|
|
554
551
|
async function debateStartCommand(topic, options) {
|
|
555
552
|
let db;
|
|
556
553
|
try {
|
|
@@ -590,6 +587,40 @@ async function debateStartCommand(topic, options) {
|
|
|
590
587
|
process.exit(1);
|
|
591
588
|
}
|
|
592
589
|
}
|
|
590
|
+
var DEFAULT_RESPONSE_CAP = 16384;
|
|
591
|
+
var MAX_RESPONSE_CAP = 24576;
|
|
592
|
+
function buildResponseOutput(debateId, round, responseText, cap, explicitOutput) {
|
|
593
|
+
const text = responseText ?? "";
|
|
594
|
+
const byteLen = Buffer.byteLength(text, "utf-8");
|
|
595
|
+
const truncated = byteLen > cap;
|
|
596
|
+
let responseFile;
|
|
597
|
+
if (truncated && !explicitOutput) {
|
|
598
|
+
const dir = join3(process.cwd(), ".codemoot", "debates");
|
|
599
|
+
mkdirSync2(dir, { recursive: true, mode: 448 });
|
|
600
|
+
responseFile = join3(dir, `${debateId}-r${round}.txt`);
|
|
601
|
+
writeFileSync(responseFile, text, { encoding: "utf-8", mode: 384 });
|
|
602
|
+
} else if (explicitOutput && text.length > 0) {
|
|
603
|
+
responseFile = explicitOutput;
|
|
604
|
+
}
|
|
605
|
+
let sliced = text;
|
|
606
|
+
if (truncated) {
|
|
607
|
+
let lo = 0;
|
|
608
|
+
let hi = text.length;
|
|
609
|
+
while (lo < hi) {
|
|
610
|
+
const mid = lo + hi + 1 >>> 1;
|
|
611
|
+
if (Buffer.byteLength(text.slice(0, mid), "utf-8") <= cap) lo = mid;
|
|
612
|
+
else hi = mid - 1;
|
|
613
|
+
}
|
|
614
|
+
sliced = text.slice(0, lo);
|
|
615
|
+
}
|
|
616
|
+
return {
|
|
617
|
+
response: sliced,
|
|
618
|
+
responseTruncated: truncated,
|
|
619
|
+
responseBytes: byteLen,
|
|
620
|
+
responseCap: cap,
|
|
621
|
+
responseFile
|
|
622
|
+
};
|
|
623
|
+
}
|
|
593
624
|
async function debateTurnCommand(debateId, prompt, options) {
|
|
594
625
|
let db;
|
|
595
626
|
try {
|
|
@@ -619,6 +650,11 @@ async function debateTurnCommand(debateId, prompt, options) {
|
|
|
619
650
|
}
|
|
620
651
|
const rawRound = options.round ?? criticRow.round + 1;
|
|
621
652
|
const newRound = Number.isFinite(rawRound) && rawRound > 0 ? rawRound : criticRow.round + 1;
|
|
653
|
+
const responseCap = Math.min(
|
|
654
|
+
options.responseCap && options.responseCap > 0 ? options.responseCap : DEFAULT_RESPONSE_CAP,
|
|
655
|
+
MAX_RESPONSE_CAP
|
|
656
|
+
);
|
|
657
|
+
const quiet = options.quiet ?? false;
|
|
622
658
|
const proposerStateForLimit = store.loadState(debateId, "proposer");
|
|
623
659
|
const storedTimeout = proposerStateForLimit?.defaultTimeout;
|
|
624
660
|
const rawTimeout = options.timeout ?? storedTimeout ?? 600;
|
|
@@ -643,14 +679,13 @@ async function debateTurnCommand(debateId, prompt, options) {
|
|
|
643
679
|
}
|
|
644
680
|
if (options.output && existing.responseText) {
|
|
645
681
|
writeFileSync(options.output, existing.responseText, "utf-8");
|
|
646
|
-
console.error(chalk4.dim(`Full response written to ${options.output}`));
|
|
682
|
+
if (!quiet) console.error(chalk4.dim(`Full response written to ${options.output}`));
|
|
647
683
|
}
|
|
684
|
+
const responseFields = buildResponseOutput(debateId, newRound, existing.responseText, responseCap, options.output);
|
|
648
685
|
const output = {
|
|
649
686
|
debateId,
|
|
650
687
|
round: newRound,
|
|
651
|
-
|
|
652
|
-
responseTruncated: (existing.responseText?.length ?? 0) > 2e3,
|
|
653
|
-
responseFile: options.output ?? void 0,
|
|
688
|
+
...responseFields,
|
|
654
689
|
sessionId: existing.sessionId,
|
|
655
690
|
resumed: false,
|
|
656
691
|
cached: true,
|
|
@@ -669,7 +704,7 @@ async function debateTurnCommand(debateId, prompt, options) {
|
|
|
669
704
|
}
|
|
670
705
|
const staleThreshold = timeout + 6e4;
|
|
671
706
|
const recovered = msgStore.recoverStaleForDebate(debateId, staleThreshold);
|
|
672
|
-
if (recovered > 0) {
|
|
707
|
+
if (recovered > 0 && !quiet) {
|
|
673
708
|
console.error(chalk4.yellow(` Recovered ${recovered} stale message(s) from prior crash.`));
|
|
674
709
|
}
|
|
675
710
|
const current = msgStore.getByRound(debateId, newRound, "critic");
|
|
@@ -694,14 +729,13 @@ async function debateTurnCommand(debateId, prompt, options) {
|
|
|
694
729
|
if (recheckRow?.status === "completed") {
|
|
695
730
|
if (options.output && recheckRow.responseText) {
|
|
696
731
|
writeFileSync(options.output, recheckRow.responseText, "utf-8");
|
|
697
|
-
console.error(chalk4.dim(`Full response written to ${options.output}`));
|
|
732
|
+
if (!quiet) console.error(chalk4.dim(`Full response written to ${options.output}`));
|
|
698
733
|
}
|
|
734
|
+
const recheckResponseFields = buildResponseOutput(debateId, newRound, recheckRow.responseText, responseCap, options.output);
|
|
699
735
|
const output = {
|
|
700
736
|
debateId,
|
|
701
737
|
round: newRound,
|
|
702
|
-
|
|
703
|
-
responseTruncated: (recheckRow.responseText?.length ?? 0) > 2e3,
|
|
704
|
-
responseFile: options.output ?? void 0,
|
|
738
|
+
...recheckResponseFields,
|
|
705
739
|
sessionId: recheckRow.sessionId,
|
|
706
740
|
resumed: false,
|
|
707
741
|
cached: true,
|
|
@@ -734,28 +768,32 @@ async function debateTurnCommand(debateId, prompt, options) {
|
|
|
734
768
|
db.close();
|
|
735
769
|
process.exit(1);
|
|
736
770
|
} else if (preflight.shouldStop && options.force) {
|
|
737
|
-
console.error(chalk4.yellow(` Token budget at ${Math.round(preflight.utilizationRatio * 100)}% (${preflight.totalTokensUsed}/${maxContext}) \u2014 forced past budget limit.`));
|
|
771
|
+
if (!quiet) console.error(chalk4.yellow(` Token budget at ${Math.round(preflight.utilizationRatio * 100)}% (${preflight.totalTokensUsed}/${maxContext}) \u2014 forced past budget limit.`));
|
|
738
772
|
} else if (preflight.shouldSummarize) {
|
|
739
|
-
console.error(chalk4.yellow(` Token budget at ${Math.round(preflight.utilizationRatio * 100)}%. Older rounds will be summarized on resume failure.`));
|
|
740
|
-
}
|
|
741
|
-
const overflowCheck = sessionMgr.preCallOverflowCheck(unifiedSession.id);
|
|
742
|
-
if (overflowCheck.rolled) {
|
|
743
|
-
console.error(chalk4.yellow(` ${overflowCheck.message}`));
|
|
744
|
-
console.error(chalk4.yellow(" Warning: Session rolled over \u2014 previous conversation context has been lost."));
|
|
745
|
-
sessionMgr.updateThreadId(unifiedSession.id, null);
|
|
746
|
-
existingSessionId = void 0;
|
|
773
|
+
if (!quiet) console.error(chalk4.yellow(` Token budget at ${Math.round(preflight.utilizationRatio * 100)}%. Older rounds will be summarized on resume failure.`));
|
|
747
774
|
}
|
|
748
775
|
try {
|
|
749
776
|
const progress = createProgressCallbacks("debate");
|
|
750
|
-
let result
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
777
|
+
let result;
|
|
778
|
+
try {
|
|
779
|
+
result = await adapter.callWithResume(prompt, {
|
|
780
|
+
sessionId: existingSessionId,
|
|
781
|
+
timeout,
|
|
782
|
+
...progress
|
|
783
|
+
});
|
|
784
|
+
} catch (err) {
|
|
785
|
+
if (existingSessionId) {
|
|
786
|
+
sessionMgr.updateThreadId(unifiedSession.id, null);
|
|
787
|
+
}
|
|
788
|
+
throw err;
|
|
789
|
+
}
|
|
790
|
+
if (existingSessionId && result.sessionId !== existingSessionId) {
|
|
791
|
+
sessionMgr.updateThreadId(unifiedSession.id, null);
|
|
792
|
+
}
|
|
755
793
|
const resumed = attemptedResume && result.sessionId === existingSessionId;
|
|
756
794
|
const resumeFailed = attemptedResume && !resumed;
|
|
757
795
|
if (resumeFailed && result.text.length < 50) {
|
|
758
|
-
console.error(chalk4.yellow(" Resume failed with minimal response. Reconstructing from ledger..."));
|
|
796
|
+
if (!quiet) console.error(chalk4.yellow(" Resume failed with minimal response. Reconstructing from ledger..."));
|
|
759
797
|
const history = msgStore.getHistory(debateId);
|
|
760
798
|
const reconstructed = buildReconstructionPrompt(history, prompt);
|
|
761
799
|
result = await adapter.callWithResume(reconstructed, {
|
|
@@ -764,7 +802,7 @@ async function debateTurnCommand(debateId, prompt, options) {
|
|
|
764
802
|
});
|
|
765
803
|
}
|
|
766
804
|
if (result.text.length < 200 && (result.durationMs ?? 0) > 6e4) {
|
|
767
|
-
console.error(chalk4.yellow(` Warning: GPT response is only ${result.text.length} chars after ${Math.round((result.durationMs ?? 0) / 1e3)}s \u2014 possible output truncation (codex may have spent its turn on tool calls).`));
|
|
805
|
+
if (!quiet) console.error(chalk4.yellow(` Warning: GPT response is only ${result.text.length} chars after ${Math.round((result.durationMs ?? 0) / 1e3)}s \u2014 possible output truncation (codex may have spent its turn on tool calls).`));
|
|
768
806
|
}
|
|
769
807
|
const verdict = parseDebateVerdict(result.text);
|
|
770
808
|
const completed = msgStore.markCompleted(msgId, {
|
|
@@ -801,7 +839,7 @@ async function debateTurnCommand(debateId, prompt, options) {
|
|
|
801
839
|
store.upsert({
|
|
802
840
|
debateId,
|
|
803
841
|
role: "critic",
|
|
804
|
-
codexSessionId: result.sessionId ??
|
|
842
|
+
codexSessionId: result.sessionId ?? void 0,
|
|
805
843
|
round: newRound,
|
|
806
844
|
status: "active"
|
|
807
845
|
});
|
|
@@ -816,14 +854,13 @@ async function debateTurnCommand(debateId, prompt, options) {
|
|
|
816
854
|
}
|
|
817
855
|
if (options.output) {
|
|
818
856
|
writeFileSync(options.output, result.text, "utf-8");
|
|
819
|
-
console.error(chalk4.dim(`Full response written to ${options.output}`));
|
|
857
|
+
if (!quiet) console.error(chalk4.dim(`Full response written to ${options.output}`));
|
|
820
858
|
}
|
|
859
|
+
const freshResponseFields = buildResponseOutput(debateId, newRound, result.text, responseCap, options.output);
|
|
821
860
|
const output = {
|
|
822
861
|
debateId,
|
|
823
862
|
round: newRound,
|
|
824
|
-
|
|
825
|
-
responseTruncated: result.text.length > 2e3,
|
|
826
|
-
responseFile: options.output ?? void 0,
|
|
863
|
+
...freshResponseFields,
|
|
827
864
|
sessionId: result.sessionId,
|
|
828
865
|
resumed,
|
|
829
866
|
cached: false,
|
|
@@ -831,14 +868,16 @@ async function debateTurnCommand(debateId, prompt, options) {
|
|
|
831
868
|
usage: result.usage,
|
|
832
869
|
durationMs: result.durationMs
|
|
833
870
|
};
|
|
834
|
-
|
|
835
|
-
|
|
871
|
+
if (!quiet) {
|
|
872
|
+
const stanceColor = verdict.stance === "SUPPORT" ? chalk4.green : verdict.stance === "OPPOSE" ? chalk4.red : chalk4.yellow;
|
|
873
|
+
console.error(stanceColor(`
|
|
836
874
|
Round ${newRound} \u2014 Stance: ${verdict.stance}`));
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
875
|
+
const previewLines = result.text.split("\n").filter((l) => l.trim().length > 10).slice(0, 3);
|
|
876
|
+
for (const line of previewLines) {
|
|
877
|
+
console.error(chalk4.dim(` ${line.trim().slice(0, 120)}`));
|
|
878
|
+
}
|
|
879
|
+
console.error(chalk4.dim(`Duration: ${(result.durationMs / 1e3).toFixed(1)}s | Output: ${result.usage?.outputTokens ?? "?"} tokens | Input: ${result.usage?.inputTokens ?? "?"} (includes sandbox) | Resumed: ${resumed}`));
|
|
840
880
|
}
|
|
841
|
-
console.error(chalk4.dim(`Duration: ${(result.durationMs / 1e3).toFixed(1)}s | Output: ${result.usage?.outputTokens ?? "?"} tokens | Input: ${result.usage?.inputTokens ?? "?"} (includes sandbox) | Resumed: ${resumed}`));
|
|
842
881
|
console.log(JSON.stringify(output, null, 2));
|
|
843
882
|
} catch (error) {
|
|
844
883
|
msgStore.markFailed(msgId, error instanceof Error ? error.message : String(error));
|
|
@@ -1127,10 +1166,6 @@ async function cleanupCommand(path, options) {
|
|
|
1127
1166
|
}
|
|
1128
1167
|
const sessionMgr = new SessionManager3(db);
|
|
1129
1168
|
const session2 = sessionMgr.resolveActive("cleanup");
|
|
1130
|
-
const overflowCheck = sessionMgr.preCallOverflowCheck(session2.id);
|
|
1131
|
-
if (overflowCheck.rolled) {
|
|
1132
|
-
console.error(chalk5.yellow(` ${overflowCheck.message}`));
|
|
1133
|
-
}
|
|
1134
1169
|
const currentSession = sessionMgr.get(session2.id);
|
|
1135
1170
|
const sessionThreadId = currentSession?.codexThreadId ?? void 0;
|
|
1136
1171
|
const [deterministicFindings, semanticFindings] = await Promise.all([
|
|
@@ -1511,7 +1546,7 @@ async function costCommand(options) {
|
|
|
1511
1546
|
// src/commands/doctor.ts
|
|
1512
1547
|
import { existsSync, accessSync, constants } from "fs";
|
|
1513
1548
|
import { execSync as execSync2 } from "child_process";
|
|
1514
|
-
import { join as
|
|
1549
|
+
import { join as join4 } from "path";
|
|
1515
1550
|
import chalk7 from "chalk";
|
|
1516
1551
|
import { VERSION } from "@codemoot/core";
|
|
1517
1552
|
async function doctorCommand() {
|
|
@@ -1531,7 +1566,7 @@ async function doctorCommand() {
|
|
|
1531
1566
|
fix: "npm install -g @openai/codex"
|
|
1532
1567
|
});
|
|
1533
1568
|
}
|
|
1534
|
-
const configPath =
|
|
1569
|
+
const configPath = join4(cwd, ".cowork.yml");
|
|
1535
1570
|
if (existsSync(configPath)) {
|
|
1536
1571
|
checks.push({ name: "config", status: "pass", message: ".cowork.yml found" });
|
|
1537
1572
|
} else {
|
|
@@ -1542,8 +1577,8 @@ async function doctorCommand() {
|
|
|
1542
1577
|
fix: "codemoot init"
|
|
1543
1578
|
});
|
|
1544
1579
|
}
|
|
1545
|
-
const dbDir =
|
|
1546
|
-
const dbPath =
|
|
1580
|
+
const dbDir = join4(cwd, ".cowork", "db");
|
|
1581
|
+
const dbPath = join4(dbDir, "cowork.db");
|
|
1547
1582
|
if (existsSync(dbDir)) {
|
|
1548
1583
|
try {
|
|
1549
1584
|
accessSync(dbDir, constants.W_OK);
|
|
@@ -1571,11 +1606,11 @@ async function doctorCommand() {
|
|
|
1571
1606
|
let gitFound = false;
|
|
1572
1607
|
let searchDir = cwd;
|
|
1573
1608
|
while (searchDir) {
|
|
1574
|
-
if (existsSync(
|
|
1609
|
+
if (existsSync(join4(searchDir, ".git"))) {
|
|
1575
1610
|
gitFound = true;
|
|
1576
1611
|
break;
|
|
1577
1612
|
}
|
|
1578
|
-
const parent =
|
|
1613
|
+
const parent = join4(searchDir, "..");
|
|
1579
1614
|
if (parent === searchDir) break;
|
|
1580
1615
|
searchDir = parent;
|
|
1581
1616
|
}
|
|
@@ -1793,11 +1828,6 @@ async function fixCommand(fileOrGlob, options) {
|
|
|
1793
1828
|
)
|
|
1794
1829
|
);
|
|
1795
1830
|
for (let round = 1; round <= options.maxRounds; round++) {
|
|
1796
|
-
const overflowCheck = sessionMgr.preCallOverflowCheck(session2.id);
|
|
1797
|
-
if (overflowCheck.rolled) {
|
|
1798
|
-
console.error(chalk9.yellow(` ${overflowCheck.message}`));
|
|
1799
|
-
threadId = void 0;
|
|
1800
|
-
}
|
|
1801
1831
|
const roundStart = Date.now();
|
|
1802
1832
|
console.error(chalk9.dim(`
|
|
1803
1833
|
\u2500\u2500 Round ${round}/${options.maxRounds} \u2500\u2500`));
|
|
@@ -2053,12 +2083,12 @@ Result: ${converged ? "CONVERGED" : "NOT CONVERGED"} (${exitReason})`));
|
|
|
2053
2083
|
|
|
2054
2084
|
// src/commands/init.ts
|
|
2055
2085
|
import { existsSync as existsSync2 } from "fs";
|
|
2056
|
-
import { basename, join as
|
|
2086
|
+
import { basename, join as join5 } from "path";
|
|
2057
2087
|
import { loadConfig as loadConfig5, writeConfig } from "@codemoot/core";
|
|
2058
2088
|
import chalk10 from "chalk";
|
|
2059
2089
|
async function initCommand(options) {
|
|
2060
2090
|
const cwd = process.cwd();
|
|
2061
|
-
const configPath =
|
|
2091
|
+
const configPath = join5(cwd, ".cowork.yml");
|
|
2062
2092
|
if (existsSync2(configPath) && !options.force) {
|
|
2063
2093
|
console.error(chalk10.red("Already initialized. Use --force to overwrite."));
|
|
2064
2094
|
process.exit(1);
|
|
@@ -2090,8 +2120,8 @@ Initialized with '${presetName}' preset`));
|
|
|
2090
2120
|
}
|
|
2091
2121
|
|
|
2092
2122
|
// src/commands/install-skills.ts
|
|
2093
|
-
import { existsSync as existsSync3, mkdirSync as
|
|
2094
|
-
import { dirname, join as
|
|
2123
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
2124
|
+
import { dirname, join as join6 } from "path";
|
|
2095
2125
|
import chalk11 from "chalk";
|
|
2096
2126
|
var SKILLS = [
|
|
2097
2127
|
{
|
|
@@ -2532,21 +2562,21 @@ async function installSkillsCommand(options) {
|
|
|
2532
2562
|
console.error(chalk11.cyan("\n Installing CodeMoot integration for Claude Code\n"));
|
|
2533
2563
|
console.error(chalk11.dim(" Skills & Agents:"));
|
|
2534
2564
|
for (const skill of SKILLS) {
|
|
2535
|
-
const fullPath =
|
|
2565
|
+
const fullPath = join6(cwd, skill.path);
|
|
2536
2566
|
const dir = dirname(fullPath);
|
|
2537
2567
|
if (existsSync3(fullPath) && !options.force) {
|
|
2538
2568
|
console.error(chalk11.dim(` SKIP ${skill.path} (exists)`));
|
|
2539
2569
|
skipped++;
|
|
2540
2570
|
continue;
|
|
2541
2571
|
}
|
|
2542
|
-
|
|
2572
|
+
mkdirSync3(dir, { recursive: true });
|
|
2543
2573
|
writeFileSync3(fullPath, skill.content, "utf-8");
|
|
2544
2574
|
console.error(chalk11.green(` OK ${skill.path}`));
|
|
2545
2575
|
installed++;
|
|
2546
2576
|
}
|
|
2547
2577
|
console.error("");
|
|
2548
2578
|
console.error(chalk11.dim(" CLAUDE.md:"));
|
|
2549
|
-
const claudeMdPath =
|
|
2579
|
+
const claudeMdPath = join6(cwd, "CLAUDE.md");
|
|
2550
2580
|
const marker = "## CodeMoot \u2014 Multi-Model Collaboration";
|
|
2551
2581
|
if (existsSync3(claudeMdPath)) {
|
|
2552
2582
|
const existing = readFileSync3(claudeMdPath, "utf-8");
|
|
@@ -2578,8 +2608,8 @@ ${CLAUDE_MD_SECTION}`, "utf-8");
|
|
|
2578
2608
|
}
|
|
2579
2609
|
console.error("");
|
|
2580
2610
|
console.error(chalk11.dim(" Hooks:"));
|
|
2581
|
-
const settingsDir =
|
|
2582
|
-
const settingsPath =
|
|
2611
|
+
const settingsDir = join6(cwd, ".claude");
|
|
2612
|
+
const settingsPath = join6(settingsDir, "settings.json");
|
|
2583
2613
|
if (existsSync3(settingsPath)) {
|
|
2584
2614
|
try {
|
|
2585
2615
|
const existing = JSON.parse(readFileSync3(settingsPath, "utf-8"));
|
|
@@ -2603,7 +2633,7 @@ ${CLAUDE_MD_SECTION}`, "utf-8");
|
|
|
2603
2633
|
skipped++;
|
|
2604
2634
|
}
|
|
2605
2635
|
} else {
|
|
2606
|
-
|
|
2636
|
+
mkdirSync3(settingsDir, { recursive: true });
|
|
2607
2637
|
writeFileSync3(settingsPath, JSON.stringify(HOOKS_CONFIG, null, 2), "utf-8");
|
|
2608
2638
|
console.error(chalk11.green(" OK .claude/settings.json (created with post-commit hook)"));
|
|
2609
2639
|
installed++;
|
|
@@ -2656,18 +2686,12 @@ async function sessionCurrentCommand() {
|
|
|
2656
2686
|
return;
|
|
2657
2687
|
}
|
|
2658
2688
|
const events = mgr.getEvents(session2.id, 5);
|
|
2659
|
-
const overflow = mgr.getOverflowStatus(session2.id);
|
|
2660
2689
|
console.log(JSON.stringify({
|
|
2661
2690
|
sessionId: session2.id,
|
|
2662
2691
|
name: session2.name,
|
|
2663
2692
|
codexThreadId: session2.codexThreadId,
|
|
2664
2693
|
status: session2.status,
|
|
2665
|
-
|
|
2666
|
-
used: overflow.cumulativeTokens,
|
|
2667
|
-
lastTurnInput: overflow.lastTurnInputTokens,
|
|
2668
|
-
max: overflow.maxContext,
|
|
2669
|
-
utilization: `${Math.round(overflow.utilizationRatio * 100)}%`
|
|
2670
|
-
},
|
|
2694
|
+
tokenUsage: session2.tokenUsage,
|
|
2671
2695
|
recentEvents: events.map((e) => ({
|
|
2672
2696
|
command: e.command,
|
|
2673
2697
|
subcommand: e.subcommand,
|
|
@@ -2707,20 +2731,12 @@ async function sessionStatusCommand(sessionId) {
|
|
|
2707
2731
|
process.exit(1);
|
|
2708
2732
|
}
|
|
2709
2733
|
const events = mgr.getEvents(sessionId, 20);
|
|
2710
|
-
const overflow = mgr.getOverflowStatus(sessionId);
|
|
2711
2734
|
console.log(JSON.stringify({
|
|
2712
2735
|
sessionId: session2.id,
|
|
2713
2736
|
name: session2.name,
|
|
2714
2737
|
codexThreadId: session2.codexThreadId,
|
|
2715
2738
|
status: session2.status,
|
|
2716
|
-
|
|
2717
|
-
used: overflow.cumulativeTokens,
|
|
2718
|
-
lastTurnInput: overflow.lastTurnInputTokens,
|
|
2719
|
-
max: overflow.maxContext,
|
|
2720
|
-
utilization: `${Math.round(overflow.utilizationRatio * 100)}%`,
|
|
2721
|
-
shouldWarn: overflow.shouldWarn,
|
|
2722
|
-
shouldReconstruct: overflow.shouldReconstruct
|
|
2723
|
-
},
|
|
2739
|
+
tokenUsage: session2.tokenUsage,
|
|
2724
2740
|
eventCount: events.length,
|
|
2725
2741
|
events: events.map((e) => ({
|
|
2726
2742
|
command: e.command,
|
|
@@ -3060,12 +3076,8 @@ async function planReviewCommand(planFile, options) {
|
|
|
3060
3076
|
db = openDatabase9(dbPath);
|
|
3061
3077
|
const sessionMgr = new SessionManager7(db);
|
|
3062
3078
|
const session2 = sessionMgr.resolveActive("plan-review");
|
|
3063
|
-
const overflowCheck = sessionMgr.preCallOverflowCheck(session2.id);
|
|
3064
|
-
if (overflowCheck.rolled) {
|
|
3065
|
-
console.error(chalk15.yellow(` ${overflowCheck.message}`));
|
|
3066
|
-
}
|
|
3067
3079
|
const currentSession = sessionMgr.get(session2.id);
|
|
3068
|
-
const threadId =
|
|
3080
|
+
const threadId = currentSession?.codexThreadId ?? void 0;
|
|
3069
3081
|
const phaseContext = options.phase ? `
|
|
3070
3082
|
This is Phase ${options.phase} of a multi-phase plan.` : "";
|
|
3071
3083
|
const buildContext = options.build ? `
|
|
@@ -3266,10 +3278,6 @@ async function reviewCommand(fileOrGlob, options) {
|
|
|
3266
3278
|
db.close();
|
|
3267
3279
|
process.exit(1);
|
|
3268
3280
|
}
|
|
3269
|
-
const overflowCheck = sessionMgr.preCallOverflowCheck(session2.id);
|
|
3270
|
-
if (overflowCheck.rolled) {
|
|
3271
|
-
console.error(chalk16.yellow(` ${overflowCheck.message}`));
|
|
3272
|
-
}
|
|
3273
3281
|
const preset = options.preset ? getReviewPreset(options.preset) : void 0;
|
|
3274
3282
|
if (options.preset && !preset) {
|
|
3275
3283
|
console.error(chalk16.red(`Unknown preset: ${options.preset}. Use: security-audit, performance, quick-scan, pre-commit, api-review`));
|
|
@@ -3635,7 +3643,7 @@ async function shipitCommand(options) {
|
|
|
3635
3643
|
// src/commands/start.ts
|
|
3636
3644
|
import { existsSync as existsSync5 } from "fs";
|
|
3637
3645
|
import { execFileSync as execFileSync4, execSync as execSync6 } from "child_process";
|
|
3638
|
-
import { join as
|
|
3646
|
+
import { join as join7, basename as basename2 } from "path";
|
|
3639
3647
|
import chalk19 from "chalk";
|
|
3640
3648
|
import { loadConfig as loadConfig9, writeConfig as writeConfig2 } from "@codemoot/core";
|
|
3641
3649
|
async function startCommand() {
|
|
@@ -3655,7 +3663,7 @@ async function startCommand() {
|
|
|
3655
3663
|
}
|
|
3656
3664
|
console.error(chalk19.green(` Codex CLI ${codexVersion} found.`));
|
|
3657
3665
|
console.error(chalk19.dim(" [2/4] Checking project config..."));
|
|
3658
|
-
const configPath =
|
|
3666
|
+
const configPath = join7(cwd, ".cowork.yml");
|
|
3659
3667
|
if (existsSync5(configPath)) {
|
|
3660
3668
|
console.error(chalk19.green(" .cowork.yml exists \u2014 using it."));
|
|
3661
3669
|
} else {
|
|
@@ -3665,9 +3673,9 @@ async function startCommand() {
|
|
|
3665
3673
|
console.error(chalk19.green(" Created .cowork.yml with cli-first preset."));
|
|
3666
3674
|
}
|
|
3667
3675
|
console.error(chalk19.dim(" [3/4] Detecting project..."));
|
|
3668
|
-
const hasGit = existsSync5(
|
|
3669
|
-
const hasSrc = existsSync5(
|
|
3670
|
-
const hasPackageJson = existsSync5(
|
|
3676
|
+
const hasGit = existsSync5(join7(cwd, ".git"));
|
|
3677
|
+
const hasSrc = existsSync5(join7(cwd, "src"));
|
|
3678
|
+
const hasPackageJson = existsSync5(join7(cwd, "package.json"));
|
|
3671
3679
|
let reviewTarget = "";
|
|
3672
3680
|
if (hasGit) {
|
|
3673
3681
|
try {
|
|
@@ -4105,8 +4113,8 @@ debate.command("start").description("Start a new debate").argument("<topic>", "D
|
|
|
4105
4113
|
if (n <= 0) throw new InvalidArgumentError("Timeout must be a positive integer");
|
|
4106
4114
|
return n;
|
|
4107
4115
|
}).action(debateStartCommand);
|
|
4108
|
-
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);
|
|
4109
|
-
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);
|
|
4116
|
+
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).option("--quiet", "Suppress non-error stderr output", false).option("--response-cap <bytes>", "Max response bytes in JSON output (default: 16384)", (v) => Number.parseInt(v, 10)).action(debateTurnCommand);
|
|
4117
|
+
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).option("--quiet", "Suppress non-error stderr output", false).option("--response-cap <bytes>", "Max response bytes in JSON output (default: 16384)", (v) => Number.parseInt(v, 10)).action(debateNextCommand);
|
|
4110
4118
|
debate.command("status").description("Show debate status and session info").argument("<debate-id>", "Debate ID").action(debateStatusCommand);
|
|
4111
4119
|
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);
|
|
4112
4120
|
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);
|