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 { AdminForthPlugin } from "adminforth";
import { MemorySaver } from "@langchain/langgraph";
import { AdminForthCheckpointSaver } from "./agent/checkpointer.js";
import { appendCustomSystemPrompt, buildAgentSystemPrompt, DEFAULT_AGENT_SYSTEM_PROMPT } from "./agent/systemPrompt.js";
import { setupCoreEndpoints } from "./endpoints/core.js";
import { setupSessionEndpoints } from "./endpoints/sessions.js";
import { setupChatSurfaceEndpoints } from "./endpoints/chatSurfaces.js";
import { AgentSessionStore } from "./sessionStore.js";
import { ChatSurfaceService } from "./chatSurfaceService.js";
import { AgentTurnService } from "./agentTurnService.js";
import { AgentModelFactory } from "./agent/models/AgentModelFactory.js";
import { AgentModeResolver } from "./agent/models/AgentModeResolver.js";
import { AgentRuntime } from "./agent/runtime/AgentRuntime.js";
import { SpeechTurnService } from "./agent/speech/SpeechTurnService.js";
import { AgentToolProvider } from "./agent/tools/AgentToolProvider.js";
import { TurnContextBuilder } from "./agent/turn/TurnContextBuilder.js";
import { TurnLifecycleService } from "./agent/turn/TurnLifecycleService.js";
import { TurnPersistenceService } from "./agent/turn/TurnPersistenceService.js";
import { TurnPromptBuilder } from "./agent/turn/TurnPromptBuilder.js";
import { TurnStreamConsumer } from "./agent/turn/TurnStreamConsumer.js";
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;
    }
    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) {
        var _a;
        super(options, import.meta.url);
        this.checkpointer = null;
        this.options = options;
        this.sessionStore = new AgentSessionStore(() => this.adminforth, this.options);
        const toolProvider = new AgentToolProvider(() => this.adminforth, this.getInternalAgentResourceIds.bind(this));
        const runtime = new AgentRuntime({
            name: `adminforth-agent-${this.pluginInstanceId}`,
            getAdminforth: () => this.adminforth,
            getCheckpointer: this.getCheckpointer.bind(this),
            toolProvider,
        });
        const persistence = new TurnPersistenceService(() => this.adminforth, this.options);
        this.agentTurnService = new AgentTurnService(new TurnLifecycleService(this.sessionStore, persistence, this.options), new TurnContextBuilder(() => this.adminforth), new AgentModeResolver(this.options), new AgentModelFactory((_a = this.options.maxTokens) !== null && _a !== void 0 ? _a : 1000), new TurnPromptBuilder({
            getAdminforth: () => this.adminforth,
            getAgentSystemPrompt: () => this.agentSystemPromptPromise,
        }), runtime, new TurnStreamConsumer());
        this.speechTurnService = new SpeechTurnService(this.agentTurnService.runAndPersistAgentResponse.bind(this.agentTurnService));
        this.chatSurfaceService = new ChatSurfaceService(() => this.adminforth, this.options, this.sessionStore, this.agentTurnService.handleTurn.bind(this.agentTurnService), this.agentTurnService.runAndPersistAgentResponse.bind(this.agentTurnService));
        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, _b;
        (_a = this.options.audioAdapter) === null || _a === void 0 ? void 0 : _a.validate();
        for (const chatSurfaceAdapter of (_b = this.options.chatSurfaceAdapters) !== null && _b !== void 0 ? _b : []) {
            chatSurfaceAdapter.validate();
        }
        this.agentSystemPromptPromise = buildAgentSystemPrompt(adminforth, this.getInternalAgentResourceIds())
            .then((systemPrompt) => appendCustomSystemPrompt(systemPrompt, this.options.systemPrompt));
    }
    instanceUniqueRepresentation(pluginOptions) {
        return `single`;
    }
    setupEndpoints(server) {
        const endpointContext = {
            adminforth: this.adminforth,
            options: this.options,
            parseBody: this.parseBody.bind(this),
            handleTurn: this.agentTurnService.handleTurn.bind(this.agentTurnService),
            handleSpeechTurn: this.speechTurnService.handle.bind(this.speechTurnService),
            runAndPersistAgentResponse: this.agentTurnService.runAndPersistAgentResponse.bind(this.agentTurnService),
            getSessionTurns: this.sessionStore.getSessionTurns.bind(this.sessionStore),
            createNewTurn: this.sessionStore.createNewTurn.bind(this.sessionStore),
            createSystemTurn: this.sessionStore.createSystemTurn.bind(this.sessionStore),
            handleChatSurfaceMessage: this.chatSurfaceService.handleMessage.bind(this.chatSurfaceService),
        };
        setupCoreEndpoints(endpointContext, server);
        setupSessionEndpoints(endpointContext, server);
        setupChatSurfaceEndpoints(endpointContext, server);
    }
}
