/**
 * ============================================================
 *  src/askBridge.ts —— 「向人提问」的宿主交互桥（host interaction channel）
 * ------------------------------------------------------------
 *  动态工作流的地基：让一个**工具**（AskUserQuestion）能在执行中途停下来问用户，
 *  拿到选择再继续。对齐上游 Claude Code 的 AskUserQuestion —— 交互不是给工作流引擎
 *  特制的「双向生成器通道」，而是**骑在既有 tool_call → tool_result 回路上**：
 *  「等用户」只不过是这个工具返回得慢而已。所以同一座桥同时服务于：
 *    - 主循环 TAOR（模型自己决定何时 AskUserQuestion）
 *    - workflow 的 `tool: AskUserQuestion` 步骤
 *    - agent: 节点 miniReAct 把 AskUserQuestion 纳入工具白名单
 *  → 这就是「交互 + TAOR = 动态工作流」。
 *
 *  为什么放在 src 根（而非 ui/ 或 tools/）：它是工具（产出问题）与宿主/UI（回答）
 *  之间的中介，两边都要 import。放在中立位置，避免 tools → ui 的反向层级耦合。
 *
 *  两种宿主：
 *    - TUI：useChat mount 时 setAskHandler() 注册一个会弹出选择界面的处理器。
 *    - 非交互（`-p` / gateway / webchat 子进程）：没有 handler →
 *      requestUserChoice() 自动选**推荐项（每题首项）**并在 stderr 注记，
 *      绝不挂起（保 `-p` 单行 JSON 契约 + 子进程不卡死）。
 * ============================================================
 */
let handler = null;
/**
 * 注册 / 注销 UI 处理器。
 * TUI 的 useChat 在 mount 时注册、unmount 时传 null 注销。
 * 单进程单 UI，模块级单例即可；HTTP 多租户场景以后再按 session 隔离（留 TODO）。
 */
export function setAskHandler(h) {
    handler = h;
}
/** 是否有交互 UI 在场（测试 / 诊断用）。 */
export function hasAskHandler() {
    return handler !== null;
}
/**
 * 向用户提问，返回答案。
 *
 * - 有 handler（TUI）→ 交给它弹界面、等用户。
 * - 无 handler（非交互宿主）→ 自动选每题首项（约定=推荐），stderr 注记，不挂起。
 */
export async function requestUserChoice(questions, signal) {
    if (handler)
        return handler(questions, signal);
    // 非交互兜底
    return questions.map((q) => {
        const pick = q.options[0]?.label ?? '';
        try {
            process.stderr.write(`[AskUserQuestion·非交互] "${q.header}" 无 UI，自动选推荐项："${pick}"\n`);
        }
        catch {
            /* stderr 不可用也不阻断 */
        }
        return {
            header: q.header,
            question: q.question,
            selected: pick ? [pick] : [],
        };
    });
}
