Skip to content

Commit fa47951

Browse files
fix: keep slash commands working while a turn is running
`handleSubmit` treated every submission as guidance while a turn was running, including the `/exit` command that `PromptInput` deliberately lets through. The CLI then queued "/exit" as a user message and steered the turn instead of quitting. Commands are not prompts, so they take the normal path again: non-exit commands stay blocked while the turn runs, and `/exit` still quits. Found by driving the real TUI in a pseudo-terminal against a stub OpenAI-compatible server. The guidance path itself behaved as designed: the streaming answer was aborted after 21 of 130 chunks, the partial text was kept and marked `meta.interrupted`, and the follow-up request carried it together with the guidance as a user message. Refs lessweb#113, lessweb#117
1 parent 96f71c2 commit fa47951

2 files changed

Lines changed: 22 additions & 1 deletion

File tree

‎packages/cli/src/tests/prompt-input-queue.test.ts‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,25 @@ test("PromptInput keeps blocking slash commands while busy", async () => {
139139
}
140140
});
141141

142+
test("PromptInput still allows /exit while busy so the CLI can quit", async () => {
143+
const harness = createHarness();
144+
const submissions: PromptSubmission[] = [];
145+
const app = renderPromptInput(harness, { busy: true, onSubmit: (submission) => submissions.push(submission) });
146+
try {
147+
await press(harness, app, "/exit");
148+
await press(harness, app, "\r");
149+
// App receives the command (not a prompt), so `/exit` keeps quitting the CLI
150+
// instead of being queued as guidance for the running turn.
151+
assert.deepEqual(
152+
submissions.map((submission) => submission.command),
153+
["exit"]
154+
);
155+
assert.equal(submissions[0]?.steer, undefined);
156+
} finally {
157+
app.unmount();
158+
}
159+
});
160+
142161
test("PromptInput renders pending guidance and removes the last one on backspace", async () => {
143162
const harness = createHarness();
144163
let removed = 0;

‎packages/cli/src/ui/views/App.tsx‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,9 @@ function App({ projectRoot, initialPrompt, resumeSessionId, forkSessionId, onRes
560560
// Prompts submitted while a turn is running become supplemental guidance:
561561
// SessionManager appends them as a user message right before the next LLM
562562
// call of that turn, so the model can revise what it is doing.
563-
if (busyRef.current) {
563+
// Slash commands are not prompts: `/exit` must still quit the CLI while a turn
564+
// is running, exactly as it did before, so they take the normal path.
565+
if (busyRef.current && !submission.command) {
564566
sessionManager.addSupplementaryPrompt(sessionManager.getActiveSessionId(), {
565567
text: submission.text,
566568
imageUrls: submission.imageUrls,

0 commit comments

Comments
 (0)