@jphutchins/code-review 0.1.0-alpha.13 → 0.1.0-alpha.15
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 +43 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -762,10 +762,14 @@ var money = (n) => `$${n.toFixed(2)}`;
|
|
|
762
762
|
var mins = (ms) => `${(ms / 6e4).toFixed(1)}m`;
|
|
763
763
|
var spendClause = (i) => i.spentUsd === null ? null : i.budgetUsd !== null && i.budgetUsd > 0 ? `spent ${money(i.spentUsd)}/${money(i.budgetUsd)} (${pct(i.spentUsd / i.budgetUsd)})` : `spent ${money(i.spentUsd)}`;
|
|
764
764
|
var timeClause = (i) => i.elapsedMs === null ? null : i.wallMs !== null && i.wallMs > 0 ? `${mins(i.elapsedMs)}/${mins(i.wallMs)} elapsed (${pct(i.elapsedMs / i.wallMs)})` : `${mins(i.elapsedMs)} elapsed`;
|
|
765
|
-
var directive = (phase, draftPath) =>
|
|
766
|
-
|
|
765
|
+
var directive = (phase, draftPath, isSubagent) => {
|
|
766
|
+
if (isSubagent)
|
|
767
|
+
return phase.kind === "hard" ? `Budget nearly exhausted \u2014 STOP all new investigation now and report the findings you have back to the main agent in your reply. Do not write ${draftPath} yourself; only the main agent writes it.` : `Wind down investigation and report the findings you have back to the main agent in your reply \u2014 do not write ${draftPath} yourself; the main agent writes it, and you may run out of budget otherwise.`;
|
|
768
|
+
return phase.kind === "hard" ? `Budget nearly exhausted \u2014 STOP all new investigation now. Write your COMPLETE findings to ${draftPath} and run \`code-review validate ${draftPath} --explain\` until it passes (--explain prints the exact schema when the shape is wrong). Other tools are blocked until that draft is written.` : `Wind down investigation and write your COMPLETE findings to ${draftPath} now, then run \`code-review validate ${draftPath} --explain\` (it prints the exact schema if the shape is wrong) \u2014 you may run out of budget before you finish otherwise.`;
|
|
769
|
+
};
|
|
770
|
+
var budgetMessage = (i, phase, draftPath, isSubagent) => {
|
|
767
771
|
const status = [spendClause(i), timeClause(i)].filter((c) => c !== null).join(" \xB7 ");
|
|
768
|
-
return `Budget check \u2014 ${status}. ${directive(phase, draftPath)}`;
|
|
772
|
+
return `Budget check \u2014 ${status}. ${directive(phase, draftPath, isSubagent)}`;
|
|
769
773
|
};
|
|
770
774
|
var invokesCodeReviewValidate = (toolInput) => {
|
|
771
775
|
const cmd = asRecord(toolInput)?.["command"];
|
|
@@ -778,6 +782,35 @@ var blockedDuringConvergence = (toolName, toolInput) => {
|
|
|
778
782
|
if (toolName === "Bash") return !invokesCodeReviewValidate(toolInput);
|
|
779
783
|
return false;
|
|
780
784
|
};
|
|
785
|
+
var escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
786
|
+
var WRITE_TOOLS = /* @__PURE__ */ new Set(["Write", "Edit", "MultiEdit", "NotebookEdit"]);
|
|
787
|
+
var writesToDraft = (toolName, toolInput, draftPath) => {
|
|
788
|
+
const rec = asRecord(toolInput);
|
|
789
|
+
const targets = [draftPath, basename(draftPath), "$DRAFT", "${DRAFT}"];
|
|
790
|
+
if (WRITE_TOOLS.has(toolName)) {
|
|
791
|
+
const fp = rec?.["file_path"] ?? rec?.["notebook_path"];
|
|
792
|
+
if (typeof fp === "string" && targets.some((t4) => fp === t4 || basename(fp) === basename(t4)))
|
|
793
|
+
return true;
|
|
794
|
+
}
|
|
795
|
+
if (toolName === "Bash") {
|
|
796
|
+
const cmd = rec?.["command"];
|
|
797
|
+
if (typeof cmd !== "string") return false;
|
|
798
|
+
const alt = targets.map(escapeRegExp).join("|");
|
|
799
|
+
const end = "(?=$|[\\s|&;)])";
|
|
800
|
+
const redirect = new RegExp(`>>?\\|?\\s*(['"]?)(?:${alt})\\1${end}`);
|
|
801
|
+
const teeArg = new RegExp(`\\btee\\b(?:\\s+-{1,2}\\S+)*\\s+(['"]?)(?:${alt})\\1${end}`);
|
|
802
|
+
return redirect.test(cmd) || teeArg.test(cmd);
|
|
803
|
+
}
|
|
804
|
+
return false;
|
|
805
|
+
};
|
|
806
|
+
var singleWriterMessage = (draftPath) => `Only the main agent may write ${draftPath}. When a subagent writes it too, the concurrent writers clobber each other and the review comes out empty. Do NOT write, edit, or redirect into ${draftPath} \u2014 instead, return the findings you discovered in your reply (the field names are in the schema); the main agent collects every subagent's reported findings and writes the draft itself.`;
|
|
807
|
+
var denyPreTool = (reason) => ({
|
|
808
|
+
hookSpecificOutput: {
|
|
809
|
+
hookEventName: "PreToolUse",
|
|
810
|
+
permissionDecision: "deny",
|
|
811
|
+
permissionDecisionReason: reason
|
|
812
|
+
}
|
|
813
|
+
});
|
|
781
814
|
var evaluateBudgetHook = (input, params) => {
|
|
782
815
|
const rec = asRecord(input);
|
|
783
816
|
const inputs = {
|
|
@@ -788,25 +821,23 @@ var evaluateBudgetHook = (input, params) => {
|
|
|
788
821
|
reserve: params.reserve
|
|
789
822
|
};
|
|
790
823
|
const phase = decideBudget(inputs);
|
|
824
|
+
const agentId = rec?.["agent_id"];
|
|
825
|
+
const isSubagent = typeof agentId === "string" && agentId.length > 0;
|
|
791
826
|
switch (rec?.["hook_event_name"]) {
|
|
792
827
|
case "PostToolBatch":
|
|
793
828
|
return phase.kind === "ok" ? {} : {
|
|
794
829
|
hookSpecificOutput: {
|
|
795
830
|
hookEventName: "PostToolBatch",
|
|
796
|
-
additionalContext: budgetMessage(inputs, phase, params.draftPath)
|
|
831
|
+
additionalContext: budgetMessage(inputs, phase, params.draftPath, isSubagent)
|
|
797
832
|
}
|
|
798
833
|
};
|
|
799
834
|
case "PreToolUse": {
|
|
800
|
-
if (phase.kind !== "hard") return {};
|
|
801
835
|
const toolName = rec["tool_name"];
|
|
836
|
+
if (isSubagent && typeof toolName === "string" && writesToDraft(toolName, rec["tool_input"], params.draftPath))
|
|
837
|
+
return denyPreTool(singleWriterMessage(params.draftPath));
|
|
838
|
+
if (phase.kind !== "hard") return {};
|
|
802
839
|
if (typeof toolName === "string" && blockedDuringConvergence(toolName, rec["tool_input"]))
|
|
803
|
-
return
|
|
804
|
-
hookSpecificOutput: {
|
|
805
|
-
hookEventName: "PreToolUse",
|
|
806
|
-
permissionDecision: "deny",
|
|
807
|
-
permissionDecisionReason: budgetMessage(inputs, phase, params.draftPath)
|
|
808
|
-
}
|
|
809
|
-
};
|
|
840
|
+
return denyPreTool(budgetMessage(inputs, phase, params.draftPath, isSubagent));
|
|
810
841
|
return {};
|
|
811
842
|
}
|
|
812
843
|
default:
|