@testchimp/cli 0.1.65 → 0.1.66
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/chimphands/run.js +57 -27
- package/package.json +1 -1
package/dist/chimphands/run.js
CHANGED
|
@@ -1773,6 +1773,8 @@ export async function runChimphands(opts) {
|
|
|
1773
1773
|
let lastUserActivity = Date.now();
|
|
1774
1774
|
let exitCode;
|
|
1775
1775
|
let cancelTurnRequested = false;
|
|
1776
|
+
/** True when cancel was triggered by a mid-turn user message (steer), not Stop. */
|
|
1777
|
+
let steerAbortRequested = false;
|
|
1776
1778
|
let activeOpencodeChild = null;
|
|
1777
1779
|
let agentTurnInProgress = false;
|
|
1778
1780
|
/** Wakes waitForNextPrompt when idle is signaled (SSE) or a user message arrives. */
|
|
@@ -1788,6 +1790,35 @@ export async function runChimphands(opts) {
|
|
|
1788
1790
|
activeOpencodeChild = child;
|
|
1789
1791
|
},
|
|
1790
1792
|
};
|
|
1793
|
+
/** Abort in-flight OpenCode turn (session HTTP abort + kill `opencode run` child). */
|
|
1794
|
+
const abortActiveTurn = (reason) => {
|
|
1795
|
+
cancelTurnRequested = true;
|
|
1796
|
+
if (reason === "steer") {
|
|
1797
|
+
steerAbortRequested = true;
|
|
1798
|
+
}
|
|
1799
|
+
const sessionToAbort = opencodeSessionId?.trim();
|
|
1800
|
+
if (attachUrl && sessionToAbort) {
|
|
1801
|
+
void abortOpencodeSession(attachUrl, sessionToAbort);
|
|
1802
|
+
}
|
|
1803
|
+
const ch = activeOpencodeChild;
|
|
1804
|
+
if (ch && !ch.killed) {
|
|
1805
|
+
try {
|
|
1806
|
+
ch.kill("SIGTERM");
|
|
1807
|
+
setTimeout(() => {
|
|
1808
|
+
try {
|
|
1809
|
+
if (!ch.killed)
|
|
1810
|
+
ch.kill("SIGKILL");
|
|
1811
|
+
}
|
|
1812
|
+
catch {
|
|
1813
|
+
/* ignore */
|
|
1814
|
+
}
|
|
1815
|
+
}, 2000);
|
|
1816
|
+
}
|
|
1817
|
+
catch {
|
|
1818
|
+
/* ignore */
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
};
|
|
1791
1822
|
const enqueueUserMessage = (msg) => {
|
|
1792
1823
|
const id = msg.id?.trim();
|
|
1793
1824
|
if (id) {
|
|
@@ -1801,9 +1832,15 @@ export async function runChimphands(opts) {
|
|
|
1801
1832
|
queue.push(content);
|
|
1802
1833
|
lastUserActivity = Date.now();
|
|
1803
1834
|
idle = false;
|
|
1804
|
-
wakePromptWaiter();
|
|
1805
1835
|
const preview = content.length > 120 ? `${content.slice(0, 117)}...` : content;
|
|
1806
1836
|
console.error(`ChimpHands queued user message (turnActive=${agentTurnInProgress}, depth=${queue.length}): ${JSON.stringify(preview)}`);
|
|
1837
|
+
// OpenCode has no mid-turn inject: abort the active turn so the queued
|
|
1838
|
+
// message is consumed immediately as the next prompt (course-correct).
|
|
1839
|
+
if (agentTurnInProgress && !cancelTurnRequested) {
|
|
1840
|
+
console.error(`ChimpHands steering: aborting active turn so queued user message reaches OpenCode`);
|
|
1841
|
+
abortActiveTurn("steer");
|
|
1842
|
+
}
|
|
1843
|
+
wakePromptWaiter();
|
|
1807
1844
|
};
|
|
1808
1845
|
const pollPendingUserMessages = async () => {
|
|
1809
1846
|
try {
|
|
@@ -1869,29 +1906,8 @@ export async function runChimphands(opts) {
|
|
|
1869
1906
|
childEnv.TESTCHIMP_USER_ID = userId;
|
|
1870
1907
|
const handleCancelTurn = () => {
|
|
1871
1908
|
console.error(`ChimpHands cancel_turn received for session ${sessionId}`);
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
if (attachUrl && sessionToAbort) {
|
|
1875
|
-
void abortOpencodeSession(attachUrl, sessionToAbort);
|
|
1876
|
-
}
|
|
1877
|
-
const ch = activeOpencodeChild;
|
|
1878
|
-
if (ch && !ch.killed) {
|
|
1879
|
-
try {
|
|
1880
|
-
ch.kill("SIGTERM");
|
|
1881
|
-
setTimeout(() => {
|
|
1882
|
-
try {
|
|
1883
|
-
if (!ch.killed)
|
|
1884
|
-
ch.kill("SIGKILL");
|
|
1885
|
-
}
|
|
1886
|
-
catch {
|
|
1887
|
-
/* ignore */
|
|
1888
|
-
}
|
|
1889
|
-
}, 2000);
|
|
1890
|
-
}
|
|
1891
|
-
catch {
|
|
1892
|
-
/* ignore */
|
|
1893
|
-
}
|
|
1894
|
-
}
|
|
1909
|
+
steerAbortRequested = false;
|
|
1910
|
+
abortActiveTurn("cancel");
|
|
1895
1911
|
};
|
|
1896
1912
|
const stopInbound = connectInboundStream(backend, apiKey, sessionId, {
|
|
1897
1913
|
onUserMessage: enqueueUserMessage,
|
|
@@ -2006,11 +2022,21 @@ export async function runChimphands(opts) {
|
|
|
2006
2022
|
});
|
|
2007
2023
|
while (prompt) {
|
|
2008
2024
|
cancelTurnRequested = false;
|
|
2025
|
+
const wasSteered = steerAbortRequested;
|
|
2026
|
+
steerAbortRequested = false;
|
|
2009
2027
|
agentTurnInProgress = true;
|
|
2010
2028
|
let useOpencodeSessionId = opencodeSessionId;
|
|
2011
2029
|
let isNewOpencodeSession = !useOpencodeSessionId;
|
|
2012
|
-
|
|
2013
|
-
|
|
2030
|
+
const promptForOpencode = wasSteered
|
|
2031
|
+
? [
|
|
2032
|
+
"The previous agent turn was interrupted because the user sent a new message.",
|
|
2033
|
+
"Stop any long-running watch/poll that no longer applies. Course-correct using this guidance:",
|
|
2034
|
+
"",
|
|
2035
|
+
prompt,
|
|
2036
|
+
].join("\n")
|
|
2037
|
+
: prompt;
|
|
2038
|
+
let effectivePrompt = wrapPromptWithContext(conversationSummary, promptForOpencode, isNewOpencodeSession, workingBranch, pullRequestUrl);
|
|
2039
|
+
const turnPostEvent = (role, content, opts) => postEventForTurn(promptForOpencode, effectivePrompt, role, content, opts);
|
|
2014
2040
|
// Visible in chat (not filtered as routine). OpenCode may not emit text until a
|
|
2015
2041
|
// part completes — without this the UI looks empty while the turn is running.
|
|
2016
2042
|
postEvent(ROLE_STATUS, "Agent is working…", { status: STATUS_RUNNING });
|
|
@@ -2098,7 +2124,11 @@ export async function runChimphands(opts) {
|
|
|
2098
2124
|
exitCode = result.code || 1;
|
|
2099
2125
|
break;
|
|
2100
2126
|
}
|
|
2101
|
-
if (result.cancelled) {
|
|
2127
|
+
if (result.cancelled && (steerAbortRequested || queue.length > 0)) {
|
|
2128
|
+
// Mid-turn user message aborted this turn — run the queued prompt next.
|
|
2129
|
+
postEvent(ROLE_STATUS, "Incorporating your message…", { status: STATUS_RUNNING });
|
|
2130
|
+
}
|
|
2131
|
+
else if (result.cancelled) {
|
|
2102
2132
|
postEvent(ROLE_STATUS, "Turn stopped", { status: STATUS_WAITING_USER });
|
|
2103
2133
|
}
|
|
2104
2134
|
else {
|
package/package.json
CHANGED