import type { CommitConfig, GeneratedCommitMessage } from "../types.ts"; import { BorderedLoader, type ExtensionCommandContext } from "@earendil-works/pi-coding-agent"; import { GenerationCancelledError, generateCommitMessage } from "../llm/generate-message.ts"; interface GenerationOutcome { ok: boolean; generated?: GeneratedCommitMessage; error?: string; cancelled?: boolean; } /** 把未知错误转换为可跨 UI 边界传递的文本。 */ function getGenerationError(error: unknown): string { return error instanceof Error ? error.message : String(error); } /** * 使用 Pi 原生 BorderedLoader 展示 working 状态,并阻塞等待完整 LLM 结果。 */ export async function generateWithWorkingState( config: CommitConfig, systemPrompt: string, prompt: string, ctx: ExtensionCommandContext, isRegeneration: boolean, ): Promise { const message = isRegeneration ? "Regenerating commit message…" : "Generating commit message…"; if (ctx.mode !== "tui") { ctx.ui.notify(message, "info"); return generateCommitMessage(config, systemPrompt, prompt, ctx); } const outcome = await ctx.ui.custom((tui, theme, _keybindings, done) => { const loader = new BorderedLoader(tui, theme, message, { cancellable: true, }); generateCommitMessage(config, systemPrompt, prompt, ctx, loader.signal).then( (generated) => done({ ok: true, generated }), (error: unknown) => done({ ok: false, error: getGenerationError(error), cancelled: error instanceof GenerationCancelledError, }), ); return loader; }); if (!outcome) { throw new Error("The commit message loading view closed unexpectedly."); } if (!outcome.ok || !outcome.generated) { // 跨 UI 边界只能传递纯数据,这里按标记还原取消错误类型。 if (outcome.cancelled) { throw new GenerationCancelledError(); } throw new Error(outcome.error || "Failed to generate commit message."); } return outcome.generated; }