/**
 * This file is part of the NocoBase (R) project.
 * Copyright (c) 2020-2024 NocoBase Co., Ltd.
 * Authors: NocoBase Team.
 *
 * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
 * For more information, please refer to: https://www.nocobase.com/agreement.
 */

var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var conversation_exports = {};
__export(conversation_exports, {
  conversationMiddleware: () => conversationMiddleware
});
module.exports = __toCommonJS(conversation_exports);
var import_langchain = require("langchain");
var import_zod = __toESM(require("zod"));
var import_utils = require("../utils");
const conversationMiddleware = (aiEmployee, options) => {
  const { providerName, model, messageId, agentThread } = options;
  const convertAIMessage = (aiMessage) => (0, import_utils.convertAIMessage)({
    aiEmployee,
    providerName,
    model,
    aiMessage
  });
  const convertHumanMessage = (humanMessage) => (0, import_utils.convertHumanMessage)({ providerName, model, humanMessage });
  const convertToolMessage = (toolMessage) => (0, import_utils.convertToolMessage)({
    providerName,
    model,
    toolMessage
  });
  const fillToolCall = (message, toolsMap, initializedToolCalls, toolCalls) => {
    const initializedToolCallMap = new Map(initializedToolCalls.map((x) => x.toJSON()).map((x) => [x.toolCallId, x]));
    for (const toolCall of toolCalls) {
      const tools = toolsMap.get(toolCall.name);
      const { status, content, invokeStatus, invokeStartTime, invokeEndTime, auto, execution } = initializedToolCallMap.get(toolCall.id) ?? {};
      toolCall.sessionId = message.sessionId;
      toolCall.messageId = message.messageId;
      toolCall.status = status;
      toolCall.content = content;
      toolCall.invokeStatus = invokeStatus;
      toolCall.invokeStartTime = invokeStartTime;
      toolCall.invokeEndTime = invokeEndTime;
      toolCall.auto = auto;
      toolCall.execution = execution;
      toolCall.willInterrupt = aiEmployee.shouldInterruptToolCall(tools);
      toolCall.defaultPermission = tools == null ? void 0 : tools.defaultPermission;
    }
  };
  return (0, import_langchain.createMiddleware)({
    name: "ConversationMiddleware",
    contextSchema: import_zod.default.object({
      ctx: import_zod.default.any()
    }),
    stateSchema: import_zod.default.object({
      messageId: import_zod.default.coerce.string().optional(),
      lastMessageIndex: import_zod.default.object({
        lastHumanMessageIndex: import_zod.default.number().default(0),
        lastAIMessageIndex: import_zod.default.number().default(0),
        lastToolMessageIndex: import_zod.default.number().default(0),
        lastMessageIndex: import_zod.default.number().default(0)
      }).default({
        lastHumanMessageIndex: 0,
        lastAIMessageIndex: 0,
        lastToolMessageIndex: 0,
        lastMessageIndex: 0
      })
    }),
    beforeAgent: async (state) => {
      const lastHumanMessageIndex = state.lastMessageIndex.lastHumanMessageIndex;
      const userMessages = state.messages.filter((x) => x.type === "human").slice(lastHumanMessageIndex).map((x) => x).map(convertHumanMessage);
      await aiEmployee.aiChatConversation.withTransaction(async (conversation, transaction) => {
        if (agentThread) {
          await aiEmployee.updateThread(transaction, agentThread);
        }
        if (messageId && await conversation.getMessage(messageId)) {
          await conversation.removeMessages({ messageId });
        }
        if (userMessages.length) {
          await conversation.addMessages(userMessages);
        }
      });
    },
    beforeModel: async (state, runtime) => {
      var _a;
      const { messageId: messageId2 } = state;
      const lastToolMessageIndex = state.lastMessageIndex.lastToolMessageIndex;
      const toolMessages = state.messages.filter((x) => x.type === "tool").slice(lastToolMessageIndex).map((x) => x).map(convertToolMessage);
      if (toolMessages.length) {
        for (const tm of toolMessages) {
          tm.metadata.messageId = messageId2;
        }
        await aiEmployee.aiChatConversation.withTransaction(async (conversation, transaction) => {
          await conversation.addMessages(toolMessages);
          await aiEmployee.confirmToolCall(
            transaction,
            messageId2,
            toolMessages.map((x) => x.metadata.toolCallId)
          );
        });
        (_a = runtime.writer) == null ? void 0 : _a.call(runtime, { action: "beforeSendToolMessage", body: { messageId: messageId2, messages: toolMessages } });
      }
    },
    afterModel: async (state, runtime) => {
      var _a, _b, _c, _d, _e, _f;
      try {
        const newState = {
          lastMessageIndex: {
            lastHumanMessageIndex: state.messages.filter((x) => x.type === "human").length,
            lastAIMessageIndex: state.messages.filter((x) => x.type === "ai").length,
            lastToolMessageIndex: state.messages.filter((x) => x.type === "tool").length,
            lastMessageIndex: state.messages.length
          }
        };
        const lastMessage = state.messages.at(-1);
        if ((lastMessage == null ? void 0 : lastMessage.type) !== "ai") {
          return newState;
        }
        aiEmployee.removeAbortController();
        if ((_a = runtime.signal) == null ? void 0 : _a.aborted) {
          return newState;
        }
        const aiMessage = lastMessage;
        const toolCalls = aiMessage.tool_calls;
        const values = convertAIMessage(aiMessage);
        if (values) {
          await aiEmployee.aiChatConversation.withTransaction(async (conversation, transaction) => {
            const result = await conversation.addMessages(values);
            state.messageId = result.messageId;
            if (toolCalls == null ? void 0 : toolCalls.length) {
              const toolsMap = await aiEmployee.getToolsMap();
              const initializedToolCalls = await aiEmployee.initToolCall(
                transaction,
                result.messageId,
                toolCalls
              );
              fillToolCall(result, toolsMap, initializedToolCalls, toolCalls);
            }
          });
          (_b = runtime.writer) == null ? void 0 : _b.call(runtime, {
            action: "AfterAIMessageSaved",
            body: { id: aiMessage.id, messageId: state.messageId }
          });
        }
        if (toolCalls == null ? void 0 : toolCalls.length) {
          (_c = runtime.writer) == null ? void 0 : _c.call(runtime, {
            action: "initToolCalls",
            body: { toolCalls }
          });
        }
        return newState;
      } catch (e) {
        (_f = (_e = (_d = runtime.context) == null ? void 0 : _d.ctx) == null ? void 0 : _e.logger) == null ? void 0 : _f.error(e);
      }
    }
  });
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  conversationMiddleware
});
