"use strict";
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());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.appRouter = void 0;
const server_1 = require("@trpc/server");
const zod_1 = require("zod");
const src_1 = require("../../../shared/src");
const Run_1 = require("../dao/Run");
const InputRequest_1 = require("../dao/InputRequest");
const Message_1 = require("../dao/Message");
const socket_1 = require("./socket");
const friday_1 = require("../../../shared/src/config/friday");
const FridayAppMessage_1 = require("../dao/FridayAppMessage");
const textBlock = zod_1.z.object({
    text: zod_1.z.string(),
    type: zod_1.z.literal(src_1.BlockType.TEXT),
});
const thinkingBlock = zod_1.z.object({
    thinking: zod_1.z.string(),
    type: zod_1.z.literal(src_1.BlockType.THINKING),
});
const base64Source = zod_1.z.object({
    type: zod_1.z.literal('base64'),
    media_type: zod_1.z.string(),
    data: zod_1.z.string(),
});
const urlSource = zod_1.z.object({
    type: zod_1.z.literal('url'),
    url: zod_1.z.string(),
});
const imageBlock = zod_1.z.object({
    type: zod_1.z.literal(src_1.BlockType.IMAGE),
    source: zod_1.z.union([base64Source, urlSource]),
});
const audioBlock = zod_1.z.object({
    type: zod_1.z.literal(src_1.BlockType.AUDIO),
    source: zod_1.z.union([base64Source, urlSource]),
});
const videoBlock = zod_1.z.object({
    type: zod_1.z.literal(src_1.BlockType.VIDEO),
    source: zod_1.z.union([base64Source, urlSource]),
});
const toolUseBlock = zod_1.z.object({
    type: zod_1.z.literal(src_1.BlockType.TOOL_USE),
    id: zod_1.z.string(),
    name: zod_1.z.string(),
    input: zod_1.z.record(zod_1.z.unknown()),
});
const toolResultBlock = zod_1.z.object({
    type: zod_1.z.literal(src_1.BlockType.TOOL_RESULT),
    id: zod_1.z.string(),
    name: zod_1.z.string(),
    output: zod_1.z.union([
        zod_1.z.string(),
        zod_1.z.array(zod_1.z.union([textBlock, imageBlock, audioBlock])),
    ]),
});
// Define ContentBlock as a union of all possible block types
const contentBlock = zod_1.z.union([
    textBlock,
    thinkingBlock,
    imageBlock,
    audioBlock,
    videoBlock,
    toolUseBlock,
    toolResultBlock,
]);
// Define ContentBlocks as an array of ContentBlock
const contentBlocks = zod_1.z.array(contentBlock);
// Define ContentType as a string or ContentBlocks
const contentType = zod_1.z.union([zod_1.z.string(), contentBlocks]);
const t = server_1.initTRPC.create();
exports.appRouter = t.router({
    registerRun: t.procedure
        .input(zod_1.z.object({
        id: zod_1.z.string(),
        project: zod_1.z.string(),
        name: zod_1.z.string(),
        timestamp: zod_1.z.string(),
        run_dir: zod_1.z.string(),
        pid: zod_1.z.number(),
        status: zod_1.z.enum(Object.values(src_1.Status)),
    }))
        .mutation((_a) => __awaiter(void 0, [_a], void 0, function* ({ input }) {
        const runData = {
            id: input.id,
            project: input.project,
            name: input.name,
            timestamp: input.timestamp,
            run_dir: input.run_dir,
            pid: input.pid,
            status: input.status,
        };
        yield Run_1.RunDao.addRun(runData);
        // Notify the subscribers of the specific project
        socket_1.SocketManager.broadcastRunToProjectRoom(input.project);
        // Notify the clients of the project list
        socket_1.SocketManager.broadcastRunToProjectListRoom();
        // Notify the clients of the overview room
        socket_1.SocketManager.broadcastOverviewDataToDashboardRoom();
    })),
    requestUserInput: t.procedure
        .input(zod_1.z.object({
        requestId: zod_1.z.string(),
        runId: zod_1.z.string(),
        agentId: zod_1.z.string(),
        agentName: zod_1.z.string(),
        structuredInput: zod_1.z.record(zod_1.z.unknown()).nullable(),
    }))
        .mutation((_a) => __awaiter(void 0, [_a], void 0, function* ({ input }) {
        const runExist = yield Run_1.RunDao.doesRunExist(input.runId);
        if (!runExist) {
            throw new server_1.TRPCError({
                code: 'BAD_REQUEST',
                message: `Run with id ${input.runId} does not exist`,
            });
        }
        try {
            // Save the input request to the database
            yield InputRequest_1.InputRequestDao.saveInputRequest({
                requestId: input.requestId,
                runId: input.runId,
                agentId: input.agentId,
                agentName: input.agentName,
                structuredInput: input.structuredInput,
            });
            console.debug(`${input.runId}: input request saved with id ${input.requestId}`);
            // Broadcast the input request to the run room
            socket_1.SocketManager.broadcastInputRequestToRunRoom(input.runId, {
                requestId: input.requestId,
                agentId: input.agentId,
                agentName: input.agentName,
                structuredInput: input.structuredInput,
            });
        }
        catch (error) {
            console.error(error);
            throw new server_1.TRPCError({
                code: 'BAD_REQUEST',
                message: 'Failed to save input request, look at the server logs for more information',
            });
        }
    })),
    pushMessage: t.procedure
        .input(zod_1.z.object({
        runId: zod_1.z.string(),
        replyId: zod_1.z.string().nullable(),
        msg: zod_1.z.object({
            id: zod_1.z.string(),
            name: zod_1.z.string(),
            role: zod_1.z.string(),
            content: contentType,
            metadata: zod_1.z.unknown(),
            timestamp: zod_1.z.string(),
        }),
    }))
        .mutation((_a) => __awaiter(void 0, [_a], void 0, function* ({ input }) {
        const runExist = yield Run_1.RunDao.doesRunExist(input.runId);
        console.log('Received pushMessage:', input);
        if (!runExist) {
            throw new server_1.TRPCError({
                code: 'BAD_REQUEST',
                message: `Run with id ${input.runId} does not exist`,
            });
        }
        // Save the message to the database
        const msgFormData = {
            id: input.msg.id,
            runId: input.runId,
            replyId: input.replyId,
            msg: {
                name: input.msg.name,
                role: input.msg.role,
                content: input.msg.content,
                metadata: input.msg.metadata,
                timestamp: input.msg.timestamp,
            },
        };
        Message_1.MessageDao.saveMessage(msgFormData)
            .then(() => {
            console.debug(`RUN-${input.runId}: message saved`);
            // Broadcast the message to the run room
            console.debug(`Broadcasting message to room run-${input.runId}`);
            socket_1.SocketManager.broadcastMessageToRunRoom(input.runId, msgFormData);
        })
            .catch((error) => {
            console.error(error);
            throw error;
        });
    })),
    pushMessageToFridayApp: t.procedure
        .input(zod_1.z.object({
        replyId: zod_1.z.string(),
        msg: zod_1.z.object({
            id: zod_1.z.string(),
            name: zod_1.z.string(),
            role: zod_1.z.string(),
            content: contentBlocks,
            metadata: zod_1.z.unknown(),
            timestamp: zod_1.z.string(),
        }),
    }))
        .mutation((_a) => __awaiter(void 0, [_a], void 0, function* ({ input }) {
        FridayAppMessage_1.FridayAppMessageDao.saveReplyMessage(input.replyId, input.msg, false)
            .then((reply) => {
            // Broadcast to all the clients in the FridayAppRoom
            socket_1.SocketManager.broadcastReplyToFridayAppRoom(reply);
        })
            .catch((error) => {
            console.error(error);
            throw error;
        });
    })),
    pushFinishedSignalToFridayApp: t.procedure
        .input(zod_1.z.object({
        replyId: zod_1.z.string(),
    }))
        .mutation((_a) => __awaiter(void 0, [_a], void 0, function* ({ input }) {
        FridayAppMessage_1.FridayAppMessageDao.finishReply(input.replyId)
            .then((reply) => {
            // Broadcast to all the clients in the FridayAppRoom
            socket_1.SocketManager.broadcastReplyToFridayAppRoom(reply);
        })
            .catch((error) => {
            console.error(error);
            throw error;
        });
    })),
    clientGetFridayConfig: t.procedure.query(() => __awaiter(void 0, void 0, void 0, function* () {
        return friday_1.FridayConfigManager.getInstance().getConfig();
    })),
});
