var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { HumanMessage } from "langchain";
import { createMiddleware } from "langchain";
import { z } from "zod";
const steerContextSchema = z.object({
    sessionId: z.string(),
    emit: z.custom().optional(),
});
/**
 * `beforeModel` middleware that folds user "steering" instructions into a running
 * turn. Before every model call in the agent loop it drains the per-session
 * {@link SteerBuffer}; any buffered steers are appended to the conversation as
 * user messages (so the model sees them on the very next call) and a
 * `steer-applied` event is emitted on the turn's already-open SSE stream so the
 * frontend knows the steer was actually consumed (not just received/queued).
 *
 * Placed first in the middleware array so the injected messages are present for
 * every downstream `beforeModel` hook (e.g. summarization) and the model itself.
 */
export function createSteerMiddleware(steerBuffer) {
    return createMiddleware({
        name: "SteerMiddleware",
        contextSchema: steerContextSchema,
        beforeModel(_state, runtime) {
            return __awaiter(this, void 0, void 0, function* () {
                const { sessionId, emit } = runtime.context;
                const steers = steerBuffer.drain(sessionId);
                if (steers.length === 0) {
                    return;
                }
                void (emit === null || emit === void 0 ? void 0 : emit({
                    type: "steer-applied",
                    count: steers.length,
                    ids: steers.map((steer) => steer.id),
                }));
                return {
                    messages: steers.map((steer) => new HumanMessage(`[User steering — new instruction sent mid-turn, take it into account from now on]\n${steer.text}`)),
                };
            });
        },
    });
}
