/**
 * ============================================================
 *  src/session/runTurn.ts —— Headless 单 turn 执行器
 * ------------------------------------------------------------
 *  把"读 session 文件 → 跑 runQuery → 写 session 文件"封装成单一入口。
 *  PR 4 HTTP server 的每个请求 handler 用它即可，无需自己拼装。
 *
 *  调用方契约：
 *    - sessionFile: per-chat 隔离的上下文文件路径（参见 sessionPath.sessionFileFor）
 *    - systemPrompt: 当 loadContext 返回 null（首次会话）时用它建初始 history；
 *      未提供则用空数组开局（少数 case 才合理，例如不需要 system prompt）
 *    - sessionState: 多并发场景必须 per-request 创建一份，避免不同 chat 串扰
 *    - signal:      调用方持有 AbortController，断开/超时时主动 abort
 *
 *  落盘策略：
 *    用 try/finally 包住 runQuery；不管成功、抛错、还是被中断都保存当前
 *    history。中断时 loop.ts 内部会先把"用户按下了 ESC/Ctrl+C"标记
 *    消息追加到 history，所以落盘的也是合法且完整的会话状态。
 * ============================================================
 */
import { loadContext, saveContext } from '../context/persistContext.js';
import { runWithPlugins } from '../plugins/pluginRunner.js';
export async function* runTurn(opts) {
    const loaded = await loadContext(opts.sessionFile);
    const history = loaded ??
        (opts.systemPrompt
            ? [{ role: 'system', content: opts.systemPrompt }]
            : []);
    try {
        yield* runWithPlugins(opts.userInput, {
            provider: opts.provider,
            history,
            signal: opts.signal,
            maxTurns: opts.maxTurns,
            sessionState: opts.sessionState,
        });
    }
    finally {
        await saveContext(history, opts.sessionFile);
    }
}
