feat(ext): add ui-prompts with timed auto-defaults
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* UI prompts for goal-driven-loop.
|
||||
*
|
||||
* Wraps Pi's UI methods with timed auto-defaults to avoid
|
||||
* blocking the user forever.
|
||||
*/
|
||||
|
||||
export interface UIContext {
|
||||
hasUI: boolean;
|
||||
select: (
|
||||
title: string,
|
||||
options: string[],
|
||||
opts?: { timeout?: number }
|
||||
) => Promise<string | undefined>;
|
||||
notify: (message: string, level?: "info" | "warn" | "error") => void;
|
||||
confirm: (
|
||||
title: string,
|
||||
message: string,
|
||||
opts?: { timeout?: number }
|
||||
) => Promise<boolean>;
|
||||
}
|
||||
|
||||
const DEFAULT_TIMEOUT_MS = 10_000;
|
||||
const STAGNATION_NOTIFY_THRESHOLD = 2;
|
||||
|
||||
/**
|
||||
* Prompt the user to resolve a stale goal state.
|
||||
* Returns the choice or undefined on timeout.
|
||||
* Auto-default: "continue"
|
||||
*/
|
||||
export async function promptStaleState(
|
||||
ctx: UIContext
|
||||
): Promise<"continue" | "replace" | "abandon" | undefined> {
|
||||
if (!ctx.hasUI) {
|
||||
return "continue";
|
||||
}
|
||||
|
||||
const choice = await ctx.select(
|
||||
"已有目标在进行中",
|
||||
["继续当前目标", "替换为新目标", "放弃当前目标"],
|
||||
{ timeout: DEFAULT_TIMEOUT_MS }
|
||||
);
|
||||
|
||||
switch (choice) {
|
||||
case "继续当前目标":
|
||||
return "continue";
|
||||
case "替换为新目标":
|
||||
return "replace";
|
||||
case "放弃当前目标":
|
||||
return "abandon";
|
||||
default:
|
||||
return "continue";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the user that the goal is being delegated to comet.
|
||||
*/
|
||||
export function notifyCoarseGrainedDelegation(
|
||||
ctx: UIContext,
|
||||
goal: string
|
||||
): void {
|
||||
if (!ctx.hasUI) return;
|
||||
ctx.notify(
|
||||
`目标粒度较大,已委托给 comet 全流程处理:${goal}`,
|
||||
"info"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the user about mid-loop granularity upgrade.
|
||||
*/
|
||||
export function notifyMidLoopUpgrade(ctx: UIContext, goal: string): void {
|
||||
if (!ctx.hasUI) return;
|
||||
ctx.notify(
|
||||
`执行中发现目标比预期复杂,已升级到 comet:${goal}`,
|
||||
"info"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the user about stagnation that auto-recovery couldn't fix.
|
||||
* Called after STAGNATION_NOTIFY_THRESHOLD auto-recovery attempts.
|
||||
*/
|
||||
export function notifyStagnation(
|
||||
ctx: UIContext,
|
||||
goal: string,
|
||||
passedCount: number,
|
||||
totalCount: number,
|
||||
iteration: number
|
||||
): void {
|
||||
if (!ctx.hasUI) return;
|
||||
ctx.notify(
|
||||
`目标停滞:${goal} (${passedCount}/${totalCount} 通过, 第 ${iteration} 轮)。自动策略调整未奏效,请人工介入。`,
|
||||
"warn"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we should notify the user about stagnation yet.
|
||||
*/
|
||||
export function shouldNotifyStagnation(
|
||||
consecutiveStagnations: number
|
||||
): boolean {
|
||||
return consecutiveStagnations > STAGNATION_NOTIFY_THRESHOLD;
|
||||
}
|
||||
Reference in New Issue
Block a user