Skip to content

Commit 45156eb

Browse files
committed
fix(desktop): distinguish interrupted compaction outcomes
1 parent b6e98a6 commit 45156eb

3 files changed

Lines changed: 51 additions & 17 deletions

File tree

packages/app/e2e/regression/session-timeline-notices.spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,40 @@ test("updates running compactions to failed and cancelled boundaries", async ({
191191
await expect(cancelled).not.toContainText("Summary before cancellation.")
192192
})
193193

194+
test("shows an interrupted outcome when stopping automatic compaction", async ({ page }) => {
195+
const timeline = await setupTimeline(page, {
196+
sessionMessages: [user, assistant(true)],
197+
sessionStatus: { [sessionID]: { type: "busy" } },
198+
})
199+
await timeline.send(compactionStarted({ sessionID, reason: "auto", recent: "" }))
200+
await timeline.send(compactionDelta({ sessionID, text: "Partial automatic summary." }))
201+
const compaction = page.locator('[data-component="session-compaction-message"]')
202+
await expect(compaction.getByRole("status").getByLabel("Compacting session", { exact: true })).toBeVisible()
203+
await expect(compaction).toContainText("Partial automatic summary.")
204+
205+
const request = page.waitForRequest(
206+
(request) =>
207+
request.method() === "POST" && new URL(request.url()).pathname === `/api/session/${sessionID}/interrupt`,
208+
)
209+
await page.getByRole("button", { name: "Stop", exact: true }).click()
210+
await request
211+
await timeline.send(
212+
compactionFailed({
213+
sessionID,
214+
reason: "auto",
215+
error: { type: "compaction.interrupted", message: "Compaction was interrupted" },
216+
}),
217+
)
218+
219+
await expect(compaction.getByText("Session compacting started", { exact: true })).toBeVisible()
220+
await expect(compaction.getByText("Session compaction interrupted", { exact: true })).toBeVisible()
221+
await expect(compaction.getByText("Session compaction failed", { exact: true })).toHaveCount(0)
222+
await expect(compaction.getByText("Session compacted", { exact: true })).toHaveCount(0)
223+
await expect(compaction.getByRole("status")).toHaveCount(0)
224+
await expect(compaction).not.toContainText("Partial automatic summary.")
225+
await expect(compaction).not.toContainText("Compaction was interrupted")
226+
})
227+
194228
test("moves blocking work to the background with Ctrl+B", async ({ page }) => {
195229
await setupTimeline(page, {
196230
settings: {

packages/session-ui/src/message/message-content.tsx

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,12 @@ export function SessionCompactionMessage(props: { message: SessionMessageCompact
392392
const i18n = useI18n()
393393
const summary = () => (props.message.status === "failed" ? "" : props.message.summary)
394394
const error = () => {
395-
if (props.message.status !== "failed" || props.message.error.type === "aborted") return ""
395+
if (
396+
props.message.status !== "failed" ||
397+
props.message.error.type === "aborted" ||
398+
props.message.error.type === "compaction.interrupted"
399+
)
400+
return ""
396401
return props.error
397402
}
398403
const compact = createMemo(
@@ -410,22 +415,16 @@ export function SessionCompactionMessage(props: { message: SessionMessageCompact
410415
output: compact().format(output),
411416
})
412417
}
413-
const label = createMemo(() =>
414-
[
415-
i18n.t(
416-
props.message.status === "failed"
417-
? props.message.error.type === "aborted"
418-
? "ui.messagePart.compaction.cancelled"
419-
: "ui.messagePart.compaction.failed"
420-
: props.message.status === "completed" && props.message.providerContext
421-
? "ui.messagePart.providerCompaction"
422-
: "ui.messagePart.compaction",
423-
),
424-
usage(),
425-
]
426-
.filter(Boolean)
427-
.join(" · "),
428-
)
418+
const outcome = createMemo(() => {
419+
if (props.message.status !== "failed")
420+
return props.message.status === "completed" && props.message.providerContext
421+
? "ui.messagePart.providerCompaction"
422+
: "ui.messagePart.compaction"
423+
if (props.message.error.type === "aborted") return "ui.messagePart.compaction.cancelled"
424+
if (props.message.error.type === "compaction.interrupted") return "ui.messagePart.compaction.interrupted"
425+
return "ui.messagePart.compaction.failed"
426+
})
427+
const label = createMemo(() => [i18n.t(outcome()), usage()].filter(Boolean).join(" · "))
429428

430429
return (
431430
<div data-component="session-compaction-message">

packages/ui/src/i18n/en.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ const source = {
108108
"ui.messagePart.compaction.running": "Compacting session",
109109
"ui.messagePart.compaction.failed": "Session compaction failed",
110110
"ui.messagePart.compaction.cancelled": "Session compaction cancelled",
111+
"ui.messagePart.compaction.interrupted": "Session compaction interrupted",
111112
"ui.messagePart.providerCompaction": "Session compacted by provider",
112113
"ui.messagePart.compaction.usage": "{{input}} in · {{output}} out",
113114
"ui.messagePart.context.details": "Details",

0 commit comments

Comments
 (0)