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