@tritard/waterbrother 0.6.2 → 0.6.4
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 +1 -1
- package/src/cli.js +87 -15
- package/src/router.js +2 -2
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -5780,31 +5780,103 @@ async function promptLoop(agent, session, context) {
|
|
|
5780
5780
|
continue;
|
|
5781
5781
|
}
|
|
5782
5782
|
if (naturalResult && typeof naturalResult === "object" && naturalResult.rewrittenLine) {
|
|
5783
|
-
// Rewritten to a slash command —
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
// We need to re-trigger, so just run build inline
|
|
5783
|
+
// Rewritten to a slash command — re-process through the command dispatch
|
|
5784
|
+
line = naturalResult.rewrittenLine;
|
|
5785
|
+
// Don't continue — fall through so the rewritten line hits the slash handlers above
|
|
5786
|
+
// But we're past them, so we need to handle inline
|
|
5787
|
+
// Extract the actual /build handler's logic by calling runBuildWorkflow directly
|
|
5788
|
+
if (line === "/build" || line.startsWith("/build ")) {
|
|
5790
5789
|
const task = context.runtime.activeTask;
|
|
5791
5790
|
if (task) {
|
|
5792
|
-
const buildArg =
|
|
5791
|
+
const buildArg = line.replace("/build", "").trim();
|
|
5793
5792
|
const buildPrompt = buildArg || (task.chosenOption ? `Execute the chosen approach: ${task.chosenOption}` : `Build: ${task.name}`);
|
|
5793
|
+
|
|
5794
|
+
await maybeAutoCompactConversation({ agent, currentSession, context, pendingInput: buildPrompt });
|
|
5795
|
+
|
|
5796
|
+
const spinner = createProgressSpinner("building...");
|
|
5797
|
+
const railStates = new Set();
|
|
5798
|
+
let currentState = "planning";
|
|
5799
|
+
|
|
5800
|
+
function toolToPhaseRewritten(toolName) {
|
|
5801
|
+
if (toolName === "run_shell") return "running";
|
|
5802
|
+
if (toolName === "write_file" || toolName === "replace_in_file" || toolName === "apply_patch") return "editing";
|
|
5803
|
+
if (toolName === "read_file" || toolName === "search_text" || toolName === "list_files" || toolName === "glob_files" || toolName === "read_many_files") return "reading";
|
|
5804
|
+
if (toolName === "declare_contract") return "planning";
|
|
5805
|
+
return "reading";
|
|
5806
|
+
}
|
|
5807
|
+
|
|
5808
|
+
function printRailRewritten(phase) {
|
|
5809
|
+
if (railStates.has(phase)) return;
|
|
5810
|
+
railStates.add(phase);
|
|
5811
|
+
console.log(`${dim(" ▸")} ${phase}`);
|
|
5812
|
+
}
|
|
5813
|
+
|
|
5814
|
+
printRailRewritten("planning");
|
|
5815
|
+
|
|
5816
|
+
const abortController = typeof AbortController === "function" ? new AbortController() : null;
|
|
5817
|
+
let interrupted = false;
|
|
5818
|
+
const detachInterruptListener = createInterruptListener(() => {
|
|
5819
|
+
if (interrupted) return;
|
|
5820
|
+
interrupted = true;
|
|
5821
|
+
spinner.setLabel("interrupting...");
|
|
5822
|
+
if (abortController) abortController.abort();
|
|
5823
|
+
}, { enableEsc: process.stdin.isTTY, shouldIgnoreEsc: () => approvalPromptActive });
|
|
5824
|
+
|
|
5794
5825
|
try {
|
|
5795
|
-
await
|
|
5796
|
-
agent,
|
|
5797
|
-
currentSession,
|
|
5798
|
-
context,
|
|
5826
|
+
const buildResult = await runBuildWorkflow({
|
|
5827
|
+
agent, context, task,
|
|
5799
5828
|
promptText: buildPrompt,
|
|
5800
|
-
|
|
5801
|
-
|
|
5829
|
+
handlers: {
|
|
5830
|
+
signal: abortController?.signal,
|
|
5831
|
+
onStateChange(state) { currentState = state; },
|
|
5832
|
+
onAssistantDelta() {},
|
|
5833
|
+
onToolStart(toolCall) {
|
|
5834
|
+
const toolName = toolCall?.function?.name || "tool";
|
|
5835
|
+
printRailRewritten(toolToPhaseRewritten(toolName));
|
|
5836
|
+
spinner.setLabel(`${toolName}...`);
|
|
5837
|
+
},
|
|
5838
|
+
onToolEnd(toolCall, result) {
|
|
5839
|
+
const toolName = toolCall?.function?.name || "tool";
|
|
5840
|
+
const status = parseToolResultShape(result);
|
|
5841
|
+
if (status !== "ok") {
|
|
5842
|
+
console.log(`${dim(" ▸")} ${toolName}: ${status === "blocked" ? yellow("blocked") : red(status)}`);
|
|
5843
|
+
}
|
|
5844
|
+
spinner.setLabel("thinking...");
|
|
5845
|
+
},
|
|
5846
|
+
onAssistant() {}
|
|
5847
|
+
}
|
|
5802
5848
|
});
|
|
5849
|
+
|
|
5850
|
+
detachInterruptListener();
|
|
5851
|
+
spinner.stop();
|
|
5852
|
+
printRailRewritten("done");
|
|
5853
|
+
|
|
5854
|
+
if (buildResult) {
|
|
5855
|
+
const { receipt, review, impactSummary } = buildResult;
|
|
5856
|
+
if (receipt) {
|
|
5857
|
+
task.latestReceiptId = receipt.id;
|
|
5858
|
+
task.lastVerdict = review?.verdict || null;
|
|
5859
|
+
task.state = "review-ready";
|
|
5860
|
+
await saveTask({ cwd: context.cwd, task });
|
|
5861
|
+
context.runtime.activeTask = task;
|
|
5862
|
+
context.runtime.lastReceipt = receipt;
|
|
5863
|
+
}
|
|
5864
|
+
console.log(`────────────────────────────────────────────────────────────────────────`);
|
|
5865
|
+
console.log(`task: ${task.name} → ${task.state}`);
|
|
5866
|
+
console.log(`────────────────────────────────────────────────────────────────────────`);
|
|
5867
|
+
if (review) {
|
|
5868
|
+
renderReviewCockpit(task, receipt);
|
|
5869
|
+
} else {
|
|
5870
|
+
updatePanel();
|
|
5871
|
+
}
|
|
5872
|
+
}
|
|
5803
5873
|
} catch (error) {
|
|
5874
|
+
detachInterruptListener();
|
|
5875
|
+
spinner.stop();
|
|
5804
5876
|
console.log(`build failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
5805
5877
|
}
|
|
5806
5878
|
}
|
|
5807
|
-
} else if (
|
|
5879
|
+
} else if (line === "/challenge") {
|
|
5808
5880
|
const task = context.runtime.activeTask;
|
|
5809
5881
|
const receipt = context.runtime.lastReceipt || (task && await agent.toolRuntime.readReceipt(task?.latestReceiptId || "last"));
|
|
5810
5882
|
if (receipt) {
|
package/src/router.js
CHANGED
|
@@ -14,9 +14,9 @@ function looksLikeWorkRequest(text) {
|
|
|
14
14
|
if (/^(hi|hello|thanks|thank you|help|what can you do)\b/.test(l)) return false;
|
|
15
15
|
if (/^(build it|go|check it|ship it|fix these|ignore|challenge harder|think deeper)\b/.test(l)) return false;
|
|
16
16
|
if (/^[1-9]\d*$/.test(l)) return false;
|
|
17
|
-
const verbStart = /^(add|build|implement|create|fix|refactor|remove|update|wire|support|migrate|improve|audit|review|debug|investigate|clean up|set up|setup|rewrite|port|optimize)\b/;
|
|
17
|
+
const verbStart = /^(add|build|implement|create|fix|refactor|remove|update|wire|support|migrate|improve|audit|review|debug|investigate|clean up|set up|setup|rewrite|port|optimize|write|make|deploy|install|configure|connect|test|run|generate|scaffold|move|rename|delete|extract|split|merge)\b/;
|
|
18
18
|
const suffixHint = /( to the | for the | in the | across | using | with | without )/;
|
|
19
|
-
return verbStart.test(l) || suffixHint.test(l)
|
|
19
|
+
return verbStart.test(l) || (suffixHint.test(l) && verbStart.test(l));
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
function inferPassFromText(text) {
|