Skip to content

Commit 7053c2b

Browse files
authored
🤖 fix: treat default Continue as resume sentinel (#1137)
### What changed - Use a short resume sentinel ("Continue") for forced compaction. - Don't inject that sentinel into the compaction *prompt* (summary request), while still keeping it in compaction metadata so the backend can auto-send it after compaction. - Add unit coverage for the default vs. explicit follow-up behavior. ### Why Appending a verbose auto-injected instruction can compete with the user's actual message; treating "Continue" as a control sentinel and keeping it out of the summarization prompt reduces instruction confusion. --- _Generated with `mux` • Model: `unknown` • Thinking: `unknown`_
1 parent 8c52449 commit 7053c2b

File tree

3 files changed

+52
-7
lines changed

3 files changed

+52
-7
lines changed

src/browser/components/AIView.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,17 @@ const AIViewInner: React.FC<AIViewProps> = ({
190190
// Show warning when: shouldShowWarning flag is true AND not currently compacting
191191
const shouldShowCompactionWarning = !isCompacting && autoCompactionResult.shouldShowWarning;
192192

193-
// Handle force compaction callback - memoized to avoid effect re-runs
193+
// Handle force compaction callback - memoized to avoid effect re-runs.
194+
// We pass a default continueMessage of "Continue" as a resume sentinel so the backend can
195+
// auto-send it after compaction. The compaction prompt builder special-cases this sentinel
196+
// to avoid injecting it into the summarization request.
194197
const handleForceCompaction = useCallback(() => {
195198
if (!api) return;
196199
void executeCompaction({
197200
api,
198201
workspaceId,
199202
sendMessageOptions: pendingSendOptions,
200-
continueMessage: { text: "Continue with the current task" },
203+
continueMessage: { text: "Continue" },
201204
});
202205
}, [api, workspaceId, pendingSendOptions]);
203206

src/browser/utils/chatCommands.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,35 @@ describe("prepareCompactionMessage", () => {
166166
expect(metadata.parsed.continueMessage?.text).toBe("Continue with this");
167167
});
168168

169+
test("omits default resume text from compaction prompt", () => {
170+
const sendMessageOptions = createBaseOptions();
171+
const { messageText, metadata } = prepareCompactionMessage({
172+
workspaceId: "ws-1",
173+
continueMessage: { text: "Continue" },
174+
sendMessageOptions,
175+
});
176+
177+
expect(messageText).not.toContain("The user wants to continue with: Continue");
178+
179+
if (metadata.type !== "compaction-request") {
180+
throw new Error("Expected compaction metadata");
181+
}
182+
183+
// Still queued for auto-send after compaction
184+
expect(metadata.parsed.continueMessage?.text).toBe("Continue");
185+
});
186+
187+
test("includes non-default continue text in compaction prompt", () => {
188+
const sendMessageOptions = createBaseOptions();
189+
const { messageText } = prepareCompactionMessage({
190+
workspaceId: "ws-1",
191+
continueMessage: { text: "fix tests" },
192+
sendMessageOptions,
193+
});
194+
195+
expect(messageText).toContain("The user wants to continue with: fix tests");
196+
});
197+
169198
test("creates continueMessage when images are provided without text", () => {
170199
const sendMessageOptions = createBaseOptions();
171200
const { metadata } = prepareCompactionMessage({

src/browser/utils/chatCommands.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,23 @@ export function prepareCompactionMessage(options: CompactionOptions): {
627627
// Build compaction message with optional continue context
628628
let messageText = buildCompactionPrompt(targetWords);
629629

630-
if (options.continueMessage) {
630+
const continueText = options.continueMessage?.text;
631+
const hasImages =
632+
options.continueMessage?.imageParts && options.continueMessage.imageParts.length > 0;
633+
const hasReviews = options.continueMessage?.reviews && options.continueMessage.reviews.length > 0;
634+
635+
// continueMessage is a follow-up user message that will be auto-sent after compaction.
636+
// For forced compaction (no explicit follow-up), we inject a short resume sentinel ("Continue").
637+
// Keep that sentinel out of the *compaction prompt* (summarization request), otherwise the model can
638+
// misread it as a competing instruction. We still keep it in metadata so the backend resumes.
639+
// Only treat it as the default resume when there's no other queued content (images/reviews).
640+
const isDefaultResume =
641+
typeof continueText === "string" &&
642+
continueText.trim() === "Continue" &&
643+
!hasImages &&
644+
!hasReviews;
645+
646+
if (options.continueMessage && !isDefaultResume) {
631647
messageText += `\n\nThe user wants to continue with: ${options.continueMessage.text}`;
632648
}
633649

@@ -636,10 +652,7 @@ export function prepareCompactionMessage(options: CompactionOptions): {
636652

637653
// Create compaction metadata (will be stored in user message)
638654
// Only include continueMessage if there's text, images, or reviews to queue after compaction
639-
const hasText = options.continueMessage?.text;
640-
const hasImages =
641-
options.continueMessage?.imageParts && options.continueMessage.imageParts.length > 0;
642-
const hasReviews = options.continueMessage?.reviews && options.continueMessage.reviews.length > 0;
655+
const hasText = continueText;
643656
const compactData: CompactionRequestData = {
644657
model: effectiveModel,
645658
maxOutputTokens: options.maxOutputTokens,

0 commit comments

Comments
 (0)