fix(session): surface empty handoff generation as failure not cancel

The #7904 fix stopped masking provider errors as "Handoff cancelled", but
an empty or whitespace-only generation still fell through: whitespace-only
text passed the `!handoffText` guard and produced a bogus handoff, while
empty text returned undefined which the interactive /handoff caller mapped
to "Handoff cancelled" with no detail and no log entry.

Treat empty/whitespace-only output as a real failure: a user-initiated
handoff throws "Handoff generation produced no content" (surfaced as
"Handoff failed: ...") and logs it; auto-handoff keeps returning undefined
so maintenance falls back to context-full compaction. Also log genuine
handoff failures in the command controller so they persist for debugging.

Fixes #7993
This commit is contained in:
roboomp
2026-08-08 08:21:16 +00:00
parent 08819b279c
commit 92e574cb02
4 changed files with 45 additions and 3 deletions
@@ -11,7 +11,7 @@ import {
type UsageReport,
} from "@oh-my-pi/pi-ai";
import { Loader, Markdown, padding, Spacer, Text, visibleWidth } from "@oh-my-pi/pi-tui";
import { formatDuration, Snowflake, sanitizeText } from "@oh-my-pi/pi-utils";
import { formatDuration, logger, Snowflake, sanitizeText } from "@oh-my-pi/pi-utils";
import { shouldEnableAppendOnlyContext } from "../../config/append-only-context-mode";
import { type BashResult, isPersistentShellCdCommand } from "../../exec/bash-executor";
import { type LoadedCustomShare, loadCustomShare } from "../../export/custom-share";
@@ -1442,6 +1442,9 @@ export class CommandController {
if (message === "Handoff cancelled") {
this.ctx.showError("Handoff cancelled");
} else {
// Persist the real failure so it is debuggable after the transient
// TUI error clears (#7993).
logger.error("Handoff failed", { error: message });
this.ctx.showError(`Handoff failed: ${message}`);
}
} finally {