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());
    });
};
var __asyncValues = (this && this.__asyncValues) || function (o) {
    if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
    var m = o[Symbol.asyncIterator], i;
    return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
    function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
    function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
};
import { AdminForthPlugin, logger, Filters, Sorts } from "adminforth";
import { randomUUID } from 'crypto';
import { HumanMessage, SystemMessage } from "langchain";
import { MemorySaver } from "@langchain/langgraph";
import { z } from "zod";
import { createAgentChatModel, callAgent } from "./agent/simpleAgent.js";
import { AdminForthCheckpointSaver } from "./agent/checkpointer.js";
import { createSequenceDebugCollector } from "./agent/middleware/sequenceDebug.js";
import { detectUserLanguage } from "./agent/languageDetect.js";
import { prepareApiBasedTools as buildApiBasedTools } from './apiBasedTools.js';
import { createAgentEventStream } from "./agentResponseEvents.js";
import { appendCustomSystemPrompt, buildAgentSystemPrompt, buildAgentTurnSystemPrompt, DEFAULT_AGENT_SYSTEM_PROMPT } from "./agent/systemPrompt.js";
import { sanitizeSpeechText } from "./sanitizeSpeechText.js";
const agentResponseBodySchema = z.object({
    message: z.string(),
    sessionId: z.string(),
    mode: z.string().nullish(),
    timeZone: z.string().optional(),
    currentPage: z.custom().optional(),
}).strict();
const agentSpeechResponseBodySchema = agentResponseBodySchema.omit({ message: true });
const addSystemMessageBodySchema = z.object({
    sessionId: z.string(),
    systemMessage: z.string(),
}).strict();
const getSessionsBodySchema = z.object({
    limit: z.number().optional(),
}).strict();
const sessionIdBodySchema = z.object({
    sessionId: z.string(),
}).strict();
const createSessionBodySchema = z.object({
    triggerMessage: z.string().optional(),
}).strict();
function isAbortError(error) {
    return (error instanceof DOMException && error.name === "AbortError") || (typeof error === "object" &&
        error !== null &&
        "name" in error &&
        (error.name === "AbortError" || error.name === "APIUserAbortError"));
}
function getErrorMessage(error) {
    return error instanceof Error ? error.message : String(error);
}
export default class AdminForthAgentPlugin extends AdminForthPlugin {
    parseBody(schema, body, response) {
        const parsed = schema.safeParse(body !== null && body !== void 0 ? body : {});
        if (!parsed.success) {
            response.setStatus(422, parsed.error.message);
            return null;
        }
        return parsed.data;
    }
    createNewTurn(sessionId, prompt, response) {
        return __awaiter(this, void 0, void 0, function* () {
            const turnId = randomUUID();
            const turnRecord = {
                [this.options.turnResource.idField]: turnId,
                [this.options.turnResource.sessionIdField]: sessionId,
                [this.options.turnResource.promptField]: prompt,
                [this.options.turnResource.responseField]: response || "not_finished",
            };
            const newTurn = yield this.adminforth.resource(this.options.turnResource.resourceId).create(turnRecord);
            return newTurn.createdRecord[this.options.turnResource.idField];
        });
    }
    getSessionTurns(sessionId) {
        return __awaiter(this, void 0, void 0, function* () {
            const turns = yield this.adminforth.resource(this.options.turnResource.resourceId).list([Filters.EQ(this.options.turnResource.sessionIdField, sessionId)], undefined, undefined, [Sorts.ASC(this.options.turnResource.createdAtField)]);
            return turns.map(turn => ({
                prompt: turn[this.options.turnResource.promptField],
                response: turn[this.options.turnResource.responseField],
            }));
        });
    }
    getPreviousUserMessages(sessionId) {
        return __awaiter(this, void 0, void 0, function* () {
            const turns = yield this.adminforth.resource(this.options.turnResource.resourceId).list([Filters.EQ(this.options.turnResource.sessionIdField, sessionId)], 2, undefined, [Sorts.DESC(this.options.turnResource.createdAtField)]);
            return turns
                .reverse()
                .map((turn) => ({
                text: turn[this.options.turnResource.promptField],
            }));
        });
    }
    getCheckpointer() {
        if (this.checkpointer)
            return this.checkpointer;
        this.checkpointer = this.options.checkpointResource
            ? new AdminForthCheckpointSaver(this.adminforth, this.options)
            : new MemorySaver();
        return this.checkpointer;
    }
    getInternalAgentResourceIds() {
        var _a;
        return [
            this.options.sessionResource.resourceId,
            this.options.turnResource.resourceId,
            (_a = this.options.checkpointResource) === null || _a === void 0 ? void 0 : _a.resourceId,
        ].filter((resourceId) => Boolean(resourceId));
    }
    constructor(options) {
        super(options, import.meta.url);
        this.checkpointer = null;
        this.options = options;
        this.agentSystemPromptPromise = Promise.resolve(appendCustomSystemPrompt(DEFAULT_AGENT_SYSTEM_PROMPT, this.options.systemPrompt));
        this.shouldHaveSingleInstancePerWholeApp = () => false;
    }
    modifyResourceConfig(adminforth, resourceConfig) {
        const _super = Object.create(null, {
            modifyResourceConfig: { get: () => super.modifyResourceConfig }
        });
        return __awaiter(this, void 0, void 0, function* () {
            var _a, _b;
            _super.modifyResourceConfig.call(this, adminforth, resourceConfig);
            if (!((_a = this.options.modes) === null || _a === void 0 ? void 0 : _a.length)) {
                throw new Error("modes is required for AdminForthAgentPlugin");
            }
            if (!this.adminforth.config.customization.globalInjections.header) {
                this.adminforth.config.customization.globalInjections.header = [];
            }
            this.adminforth.config.customization.globalInjections.header.push({
                file: this.componentPath("ChatSurface.vue"),
                meta: {
                    pluginInstanceId: this.pluginInstanceId,
                    modes: this.options.modes.map((mode) => ({ name: mode.name })),
                    defaultModeName: this.options.modes[0].name,
                    stickByDefault: (_b = this.options.stickByDefault) !== null && _b !== void 0 ? _b : false,
                    hasAudioAdapter: Boolean(this.options.audioAdapter),
                }
            });
            if (!this.adminforth.config.customization.customHeadItems) {
                this.adminforth.config.customization.customHeadItems = [];
            }
            this.adminforth.config.customization.customHeadItems.push({
                tagName: 'script',
                attributes: {
                    src: 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.22.0/dist/ort.wasm.min.js'
                }
            }, {
                tagName: 'script',
                attributes: {
                    src: 'https://cdn.jsdelivr.net/npm/@ricky0123/vad-web@0.0.29/dist/bundle.min.js'
                },
            });
            if (!this.options.sessionResource) {
                throw new Error("sessionResource is required for AdminForthAgentPlugin");
            }
        });
    }
    validateConfigAfterDiscover(adminforth, resourceConfig) {
        var _a;
        (_a = this.options.audioAdapter) === null || _a === void 0 ? void 0 : _a.validate();
        this.agentSystemPromptPromise = buildAgentSystemPrompt(adminforth, this.getInternalAgentResourceIds())
            .then((systemPrompt) => appendCustomSystemPrompt(systemPrompt, this.options.systemPrompt));
    }
    instanceUniqueRepresentation(pluginOptions) {
        return `single`;
    }
    runAgentTurn(input) {
        return __awaiter(this, void 0, void 0, function* () {
            var _a, e_1, _b, _c;
            var _d, _e, _f, _g, _h;
            let fullResponse = "";
            const maxTokens = (_d = this.options.maxTokens) !== null && _d !== void 0 ? _d : 1000;
            const selectedMode = (_e = this.options.modes.find((mode) => mode.name === input.modeName)) !== null && _e !== void 0 ? _e : this.options.modes[0];
            const [primaryModelSpec, summaryModelSpec] = yield Promise.all([
                createAgentChatModel({
                    adapter: selectedMode.completionAdapter,
                    maxTokens,
                    purpose: "primary",
                }),
                createAgentChatModel({
                    adapter: selectedMode.completionAdapter,
                    maxTokens,
                    purpose: "summary",
                }),
            ]);
            const model = primaryModelSpec.model;
            const summaryModel = summaryModelSpec.model;
            const modelMiddleware = primaryModelSpec.middleware;
            const userLanguage = yield detectUserLanguage(selectedMode.completionAdapter, input.prompt, input.previousUserMessages)
                .catch((error) => {
                var _a;
                if (((_a = input.abortSignal) === null || _a === void 0 ? void 0 : _a.aborted) || isAbortError(error)) {
                    throw error;
                }
                logger.warn(`Failed to detect user language: ${getErrorMessage(error)}`);
                return null;
            });
            const systemPrompt = buildAgentTurnSystemPrompt({
                agentSystemPrompt: yield this.agentSystemPromptPromise,
                adminUser: input.adminUser,
                usernameField: this.adminforth.config.auth.usernameField,
                userLanguage,
            });
            const apiBasedTools = buildApiBasedTools(this.adminforth, this.getInternalAgentResourceIds());
            const stream = yield callAgent({
                name: `adminforth-agent-${this.pluginInstanceId}`,
                model,
                summaryModel,
                modelMiddleware,
                checkpointer: this.getCheckpointer(),
                messages: [
                    new SystemMessage(systemPrompt),
                    new HumanMessage(input.prompt),
                ],
                adminUser: input.adminUser,
                adminforth: this.adminforth,
                apiBasedTools,
                customComponentsDir: this.adminforth.config.customization.customComponentsDir,
                sessionId: input.sessionId,
                turnId: input.turnId,
                currentPage: input.currentPage,
                userTimeZone: input.userTimeZone,
                abortSignal: input.abortSignal,
                emitToolCallEvent: (event) => {
                    var _a;
                    input.sequenceDebugCollector.handleToolCallEvent(event);
                    (_a = input.emitToolCallEvent) === null || _a === void 0 ? void 0 : _a.call(input, event);
                },
                sequenceDebugSink: input.sequenceDebugCollector,
            });
            try {
                for (var _j = true, _k = __asyncValues(stream), _l; _l = yield _k.next(), _a = _l.done, !_a; _j = true) {
                    _c = _l.value;
                    _j = false;
                    const rawChunk = _c;
                    if ((_f = input.abortSignal) === null || _f === void 0 ? void 0 : _f.aborted) {
                        throw new DOMException("This operation was aborted", "AbortError");
                    }
                    const [token, metadata] = rawChunk;
                    const nodeName = typeof (metadata === null || metadata === void 0 ? void 0 : metadata.langgraph_node) === "string"
                        ? metadata.langgraph_node
                        : "";
                    if (nodeName && !["model", "model_request"].includes(nodeName)) {
                        continue;
                    }
                    const blocks = Array.isArray(token === null || token === void 0 ? void 0 : token.contentBlocks)
                        ? token.contentBlocks
                        : Array.isArray(token === null || token === void 0 ? void 0 : token.content)
                            ? token.content
                            : [];
                    const reasoningDelta = blocks
                        .filter((b) => (b === null || b === void 0 ? void 0 : b.type) === "reasoning")
                        .map((b) => { var _a; return String((_a = b.reasoning) !== null && _a !== void 0 ? _a : ""); })
                        .join("");
                    const textDelta = blocks
                        .filter((b) => (b === null || b === void 0 ? void 0 : b.type) === "text")
                        .map((b) => { var _a; return String((_a = b.text) !== null && _a !== void 0 ? _a : ""); })
                        .join("");
                    if (reasoningDelta) {
                        (_g = input.emitReasoningDelta) === null || _g === void 0 ? void 0 : _g.call(input, reasoningDelta);
                    }
                    if (textDelta) {
                        fullResponse += textDelta;
                        (_h = input.emitTextDelta) === null || _h === void 0 ? void 0 : _h.call(input, textDelta);
                    }
                }
            }
            catch (e_1_1) { e_1 = { error: e_1_1 }; }
            finally {
                try {
                    if (!_j && !_a && (_b = _k.return)) yield _b.call(_k);
                }
                finally { if (e_1) throw e_1.error; }
            }
            return {
                text: fullResponse,
            };
        });
    }
    runAndPersistAgentResponse(input) {
        return __awaiter(this, void 0, void 0, function* () {
            var _a, _b;
            const previousUserMessages = yield this.getPreviousUserMessages(input.sessionId);
            const turnId = yield this.createNewTurn(input.sessionId, input.prompt);
            yield this.adminforth.resource(this.options.sessionResource.resourceId).update(input.sessionId, {
                [this.options.sessionResource.createdAtField]: new Date().toISOString(),
            });
            const sequenceDebugCollector = createSequenceDebugCollector();
            let fullResponse = "";
            let aborted = false;
            let failed = false;
            try {
                const agentResponse = yield this.runAgentTurn({
                    prompt: input.prompt,
                    sessionId: input.sessionId,
                    turnId,
                    previousUserMessages,
                    modeName: input.modeName,
                    userTimeZone: input.userTimeZone,
                    currentPage: input.currentPage,
                    abortSignal: input.abortSignal,
                    adminUser: input.adminUser,
                    sequenceDebugCollector,
                    emitToolCallEvent: input.emitToolCallEvent,
                    emitReasoningDelta: input.emitReasoningDelta,
                    emitTextDelta: input.emitTextDelta,
                });
                fullResponse = agentResponse.text;
            }
            catch (error) {
                if (((_a = input.abortSignal) === null || _a === void 0 ? void 0 : _a.aborted) || isAbortError(error)) {
                    aborted = true;
                    logger.info(input.abortLogMessage);
                }
                else {
                    failed = true;
                    fullResponse = getErrorMessage(error);
                    logger.error(`${input.failureLogMessage}:\n${fullResponse}`);
                    (_b = input.emitErrorResponse) === null || _b === void 0 ? void 0 : _b.call(input, fullResponse);
                }
            }
            sequenceDebugCollector.flush();
            const turnUpdates = {
                [this.options.turnResource.responseField]: fullResponse,
            };
            if (this.options.turnResource.debugField) {
                turnUpdates[this.options.turnResource.debugField] = sequenceDebugCollector.getHistory();
            }
            yield this.adminforth.resource(this.options.turnResource.resourceId).update(turnId, turnUpdates);
            return {
                text: fullResponse,
                turnId,
                aborted,
                failed,
            };
        });
    }
    setupEndpoints(server) {
        server.endpoint({
            method: 'POST',
            path: `/agent/get-placeholder-messages`,
            handler: (_a) => __awaiter(this, [_a], void 0, function* ({ headers, adminUser }) {
                if (!this.options.placeholderMessages) {
                    return {
                        messages: [],
                    };
                }
                const messages = yield this.options.placeholderMessages({
                    adminUser,
                    headers,
                });
                return {
                    messages,
                };
            })
        });
        server.endpoint({
            method: 'POST',
            path: `/agent/response`,
            handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response, _raw_express_res, abortSignal }) {
                var _b;
                const data = this.parseBody(agentResponseBodySchema, body, response);
                if (!data)
                    return;
                const stream = createAgentEventStream(_raw_express_res, { vercelAiUiMessageStream: true, closeActiveBlockOnToolStart: true });
                const messageId = randomUUID();
                stream.start(messageId);
                yield this.runAndPersistAgentResponse({
                    prompt: data.message,
                    sessionId: data.sessionId,
                    modeName: data.mode,
                    userTimeZone: (_b = data.timeZone) !== null && _b !== void 0 ? _b : 'UTC',
                    currentPage: data.currentPage,
                    abortSignal,
                    adminUser,
                    emitToolCallEvent: stream.toolCall,
                    emitReasoningDelta: stream.reasoningDelta,
                    emitTextDelta: stream.textDelta,
                    emitErrorResponse: stream.textDelta,
                    failureLogMessage: "Agent response streaming failed",
                    abortLogMessage: "Agent response streaming aborted by the client",
                });
                stream.end();
                return null;
            })
        });
        server.endpoint({
            method: 'POST',
            path: `/agent/speech-response`,
            target: 'upload',
            handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response, _raw_express_req, _raw_express_res, abortSignal }) {
                var _b;
                const req = _raw_express_req;
                const audioAdapter = this.options.audioAdapter;
                if (!audioAdapter) {
                    response.setStatus(400, undefined);
                    return { error: "Audio adapter is not configured for AdminForth Agent" };
                }
                const data = this.parseBody(agentSpeechResponseBodySchema, body, response);
                if (!data)
                    return;
                if (!req.file) {
                    response.setStatus(400, undefined);
                    return { error: "Audio file is required" };
                }
                const stream = createAgentEventStream(_raw_express_res);
                let transcription;
                try {
                    transcription = yield audioAdapter.transcribe({
                        buffer: req.file.buffer,
                        filename: req.file.originalname,
                        mimeType: req.file.mimetype,
                        language: "auto",
                        abortSignal,
                    });
                }
                catch (error) {
                    if (abortSignal.aborted || isAbortError(error)) {
                        logger.info("Agent speech transcription aborted by the client");
                        stream.end();
                        return null;
                    }
                    logger.error(`Agent speech transcription failed:\n${getErrorMessage(error)}`);
                    stream.error("Speech transcription failed. Check server logs for details.");
                    stream.end();
                    return null;
                }
                if (abortSignal.aborted) {
                    stream.end();
                    return null;
                }
                const prompt = transcription.text;
                if (!prompt) {
                    stream.error("Speech transcription is empty");
                    stream.end();
                    return null;
                }
                stream.transcript(transcription.text, transcription.language);
                const sessionId = data.sessionId;
                const currentPage = data.currentPage;
                const agentResponse = yield this.runAndPersistAgentResponse({
                    prompt,
                    sessionId,
                    modeName: data.mode,
                    userTimeZone: (_b = data.timeZone) !== null && _b !== void 0 ? _b : 'UTC',
                    currentPage,
                    abortSignal,
                    adminUser,
                    emitToolCallEvent: stream.toolCall,
                    failureLogMessage: "Agent speech response failed",
                    abortLogMessage: "Agent speech response aborted by the client",
                });
                if (agentResponse.aborted) {
                    stream.end();
                    return null;
                }
                if (agentResponse.failed) {
                    stream.error(agentResponse.text);
                    stream.end();
                    return null;
                }
                try {
                    stream.speechResponse({
                        text: transcription.text,
                        language: transcription.language,
                    }, {
                        text: agentResponse.text,
                    }, sessionId, agentResponse.turnId);
                    const speech = yield audioAdapter.synthesize({
                        text: sanitizeSpeechText(agentResponse.text),
                        stream: true,
                        streamFormat: "audio",
                        format: "pcm",
                        abortSignal,
                    });
                    stream.audioStart(speech.mimeType, speech.format, 24000, 1, 16);
                    const reader = speech.audioStream.getReader();
                    const cancelAudioStream = () => {
                        void reader.cancel().catch(() => undefined);
                    };
                    try {
                        abortSignal.addEventListener("abort", cancelAudioStream, { once: true });
                        while (true) {
                            if (abortSignal.aborted) {
                                yield reader.cancel().catch(() => undefined);
                                break;
                            }
                            const { value, done } = yield reader.read();
                            if (done) {
                                break;
                            }
                            if (abortSignal.aborted) {
                                break;
                            }
                            stream.audioDelta(value);
                        }
                    }
                    finally {
                        abortSignal.removeEventListener("abort", cancelAudioStream);
                        reader.releaseLock();
                    }
                    stream.audioDone();
                    stream.end();
                    return null;
                }
                catch (error) {
                    if (abortSignal.aborted || isAbortError(error)) {
                        logger.info("Agent speech audio streaming aborted by the client");
                    }
                    else {
                        logger.error(`Agent speech audio streaming failed:\n${error}`);
                        stream.error(error);
                    }
                    stream.end();
                    return null;
                }
            })
        });
        server.endpoint({
            method: 'POST',
            path: `/agent/get-sessions`,
            handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
                var _b;
                const data = this.parseBody(getSessionsBodySchema, body, response);
                if (!data)
                    return;
                const userId = adminUser.pk;
                const limit = (_b = data.limit) !== null && _b !== void 0 ? _b : 20;
                const sessions = yield this.adminforth.resource(this.options.sessionResource.resourceId).list([Filters.EQ(this.options.sessionResource.askerIdField, userId)], limit, undefined, [Sorts.DESC(this.options.sessionResource.createdAtField)]);
                return {
                    sessions: sessions.map((session) => ({
                        sessionId: session[this.options.sessionResource.idField],
                        title: session[this.options.sessionResource.titleField],
                        timestamp: session[this.options.sessionResource.createdAtField],
                    })),
                };
            })
        });
        server.endpoint({
            method: 'POST',
            path: `/agent/get-session-info`,
            handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
                const parsedBody = sessionIdBodySchema.safeParse(body);
                if (!parsedBody.success) {
                    response.setStatus(422, parsedBody.error.message);
                    return;
                }
                const userId = adminUser.pk;
                const sessionId = parsedBody.data.sessionId;
                const session = yield this.adminforth.resource(this.options.sessionResource.resourceId).get([Filters.EQ(this.options.sessionResource.idField, sessionId)]);
                if (!session) {
                    return {
                        error: 'Session not found'
                    };
                }
                if (session[this.options.sessionResource.askerIdField] !== userId) {
                    return {
                        error: 'Unauthorized'
                    };
                }
                const turns = yield this.getSessionTurns(sessionId);
                return {
                    session: {
                        sessionId,
                        title: session[this.options.sessionResource.titleField],
                        timestamp: session[this.options.sessionResource.createdAtField],
                        messages: turns.flatMap(turn => {
                            const messages = [];
                            if (turn.prompt) {
                                messages.push({
                                    text: turn.prompt,
                                    role: 'user',
                                });
                            }
                            if (turn.response && turn.response !== "not_finished") {
                                messages.push({
                                    text: turn.response,
                                    role: 'assistant',
                                });
                            }
                            return messages;
                        }),
                    },
                };
            })
        });
        server.endpoint({
            method: 'POST',
            path: `/agent/create-session`,
            handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
                const data = this.parseBody(createSessionBodySchema, body, response);
                if (!data)
                    return;
                const triggerMessage = data.triggerMessage;
                const userId = adminUser.pk;
                const title = (triggerMessage === null || triggerMessage === void 0 ? void 0 : triggerMessage.slice(0, 40)) || "New Session";
                const newSession = {
                    [this.options.sessionResource.idField]: randomUUID(),
                    [this.options.sessionResource.titleField]: title,
                    [this.options.sessionResource.askerIdField]: userId,
                };
                yield this.adminforth.resource(this.options.sessionResource.resourceId).create(newSession);
                return {
                    sessionId: newSession[this.options.sessionResource.idField],
                    title: newSession[this.options.sessionResource.titleField],
                    timestamp: newSession[this.options.sessionResource.createdAtField],
                    messages: []
                };
            })
        });
        server.endpoint({
            method: 'POST',
            path: `/agent/delete-session`,
            handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
                const data = this.parseBody(sessionIdBodySchema, body, response);
                if (!data)
                    return;
                const sessionId = data.sessionId;
                const userId = adminUser.pk;
                const session = yield this.adminforth.resource(this.options.sessionResource.resourceId).get([Filters.EQ(this.options.sessionResource.idField, sessionId)]);
                if (!session) {
                    return {
                        error: 'Session not found'
                    };
                }
                if (session[this.options.sessionResource.askerIdField] !== userId) {
                    return {
                        error: 'Unauthorized'
                    };
                }
                yield this.adminforth.resource(this.options.sessionResource.resourceId).delete(sessionId);
                const turns = yield this.adminforth.resource(this.options.turnResource.resourceId).list([Filters.EQ(this.options.turnResource.sessionIdField, sessionId)]);
                for (const turn of turns) {
                    yield this.adminforth.resource(this.options.turnResource.resourceId).delete(turn[this.options.turnResource.idField]);
                }
                return {
                    ok: true
                };
            })
        }),
            server.endpoint({
                method: 'POST',
                path: `/agent/add-system-message-to-turns`,
                handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, response }) {
                    const data = this.parseBody(addSystemMessageBodySchema, body, response);
                    if (!data)
                        return;
                    yield this.createNewTurn(data.sessionId, data.systemMessage);
                    return {
                        ok: true
                    };
                })
            });
    }
}
