"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
var SessionInputsService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SessionInputsService = void 0;
const common_1 = require("@nestjs/common");
const typeorm_1 = require("@nestjs/typeorm");
const typeorm_2 = require("typeorm");
const core_entities_1 = require("../core-entities");
const ai_actions_service_1 = require("../ai-actions/ai-actions.service");
const system_prompts_service_1 = require("../system-prompts/system-prompts.service");
const session_input_context_service_1 = require("./session-input-context.service");
const application_state_service_1 = require("../application-state/application-state.service");
const chat_service_1 = require("../interactive-chat/chat.service");
const llm_responses_service_1 = require("../llm-responses/llm-responses.service");
function formatActionStatusForLLM(status) {
    switch (status) {
        case ai_actions_service_1.AIActionStatus.CONFIRMED_KEPT:
            return 'The user confirmed and kept the changes.';
        case ai_actions_service_1.AIActionStatus.CONFIRMED_REVERTED:
            return 'The user chose to revert the changes.';
        case ai_actions_service_1.AIActionStatus.REJECTED_BEFORE_APPLY:
            return 'The action was rejected by the user before being applied.';
        case ai_actions_service_1.AIActionStatus.EXECUTION_FAILED:
            return 'The action failed to execute.';
        case ai_actions_service_1.AIActionStatus.REVERT_FAILED:
            return 'Reverting the action failed.';
        default:
            return `The action's final status was '${status}'.`;
    }
}
let SessionInputsService = SessionInputsService_1 = class SessionInputsService {
    constructor(sessionsRepository, sessionInputsRepository, contextTemplatesRepository, aiActionsRepository, executionLogsRepository, aiActionsService, systemPromptsService, sessionInputContextService, applicationStateService, chatService, llmResponsesService) {
        this.sessionsRepository = sessionsRepository;
        this.sessionInputsRepository = sessionInputsRepository;
        this.contextTemplatesRepository = contextTemplatesRepository;
        this.aiActionsRepository = aiActionsRepository;
        this.executionLogsRepository = executionLogsRepository;
        this.aiActionsService = aiActionsService;
        this.systemPromptsService = systemPromptsService;
        this.sessionInputContextService = sessionInputContextService;
        this.applicationStateService = applicationStateService;
        this.chatService = chatService;
        this.llmResponsesService = llmResponsesService;
        this.logger = new common_1.Logger(SessionInputsService_1.name);
    }
    generatePreviousActionsSummary(session) {
        if (!session.sessionInputs || session.sessionInputs.length === 0) {
            return '';
        }
        const lastInput = session.sessionInputs[session.sessionInputs.length - 1];
        if (!lastInput ||
            !lastInput.aiActions ||
            lastInput.aiActions.length === 0) {
            return '';
        }
        const finalStatuses = [
            ai_actions_service_1.AIActionStatus.REJECTED_BEFORE_APPLY,
            ai_actions_service_1.AIActionStatus.CONFIRMED_KEPT,
            ai_actions_service_1.AIActionStatus.CONFIRMED_REVERTED,
            ai_actions_service_1.AIActionStatus.EXECUTION_FAILED,
            ai_actions_service_1.AIActionStatus.REVERT_FAILED,
        ];
        const finalActions = lastInput.aiActions.filter((action) => finalStatuses.includes(action.status));
        if (finalActions.length === 0) {
            return '';
        }
        return ('Summary of the results from your previous plan:\n' +
            finalActions
                .map((action) => `- For the action \`${action.action_type}\` on \`${action.file_path || action.command_string || 'N/A'}\`: ${formatActionStatusForLLM(action.status)}`)
                .join('\n'));
    }
    async generateContextString(sessionId, createSessionInputDto) {
        const session = await this.sessionsRepository.findOne({
            where: { id: sessionId },
            relations: ['systemPrompt', 'sessionInputs', 'sessionInputs.aiActions'],
            order: {
                sessionInputs: {
                    created_at: 'ASC',
                },
            },
        });
        if (!session) {
            throw new common_1.NotFoundException(`Session with ID "${sessionId}" not found`);
        }
        let contextTemplate = null;
        if (createSessionInputDto.context_template_id) {
            contextTemplate = await this.contextTemplatesRepository.findOneBy({
                id: createSessionInputDto.context_template_id,
            });
        }
        const previous_actions_summary = this.generatePreviousActionsSummary(session);
        const generated_context_string = await this.sessionInputContextService.generateContext(createSessionInputDto, contextTemplate, previous_actions_summary);
        return generated_context_string;
    }
    async create(sessionId, createSessionInputDto) {
        if (createSessionInputDto.skip_persistence) {
            this.logger.log(`Triggering follow-up for session ${sessionId} without persistence.`);
            const generated_context_string = createSessionInputDto.user_prompt || '';
            this.chatService
                .sendMessage(sessionId, generated_context_string)
                .catch((err) => {
                this.logger.error(`LLM follow-up call failed for session ${sessionId}: ${err.message}`, err.stack);
            });
            return null;
        }
        this.logger.log(`Creating new session input for session ${sessionId}.`);
        const session = await this.sessionsRepository.findOne({
            where: { id: sessionId },
            relations: ['systemPrompt', 'sessionInputs', 'sessionInputs.aiActions'],
            order: {
                sessionInputs: {
                    created_at: 'ASC',
                },
            },
        });
        if (!session) {
            throw new common_1.NotFoundException(`Session with ID "${sessionId}" not found`);
        }
        let contextTemplate = null;
        if (createSessionInputDto.context_template_id) {
            contextTemplate = await this.contextTemplatesRepository.findOneBy({
                id: createSessionInputDto.context_template_id,
            });
        }
        const previous_actions_summary = this.generatePreviousActionsSummary(session);
        const generated_context_string = await this.sessionInputContextService.generateContext(createSessionInputDto, contextTemplate, previous_actions_summary);
        const newSessionInputEntity = this.sessionInputsRepository.create({
            ...createSessionInputDto,
            session: { id: sessionId },
            contextTemplate: contextTemplate,
            generated_context_string: generated_context_string,
            raw_llm_response: null,
            role: 'user',
        });
        const savedSessionInput = await this.sessionInputsRepository.save(newSessionInputEntity);
        await this.applicationStateService.setActiveSessionId(sessionId);
        this.chatService
            .sendMessage(sessionId, generated_context_string)
            .catch((err) => {
            this.logger.error(`LLM call failed for input ID ${savedSessionInput.id}: ${err.message}`, err.stack);
        });
        return savedSessionInput;
    }
    async createFromRawLlmResponse() {
        throw new Error('This method is deprecated and its logic has moved to LlmResponsesService.');
    }
    async findAllBySessionId(sessionId) {
        const session = await this.sessionsRepository.findOneBy({ id: sessionId });
        if (!session) {
            throw new common_1.NotFoundException(`Session with ID "${sessionId}" not found`);
        }
        return this.sessionInputsRepository.find({
            where: { session: { id: sessionId } },
            relations: ['contextTemplate', 'aiActions', 'aiActions.executionLogs'],
            order: {
                created_at: 'ASC',
                aiActions: {
                    order_of_execution: 'ASC',
                },
            },
        });
    }
    async findOne(sessionId, inputId) {
        const sessionInput = await this.sessionInputsRepository.findOne({
            where: { id: inputId, session: { id: sessionId } },
            relations: ['contextTemplate', 'aiActions', 'aiActions.executionLogs'],
            order: {
                aiActions: {
                    order_of_execution: 'ASC',
                },
            },
        });
        if (!sessionInput) {
            throw new common_1.NotFoundException(`SessionInput with ID "${inputId}" not found in Session "${sessionId}"`);
        }
        return sessionInput;
    }
    async removeUntilHere(sessionId, inputId) {
        const session = await this.sessionsRepository.findOne({
            where: { id: sessionId },
            relations: ['sessionInputs', 'sessionInputs.aiActions'],
            order: {
                sessionInputs: {
                    created_at: 'ASC',
                },
            },
        });
        if (!session) {
            throw new common_1.NotFoundException(`Session with ID "${sessionId}" not found`);
        }
        const targetIndex = session.sessionInputs.findIndex((input) => input.id === inputId);
        if (targetIndex === -1) {
            throw new common_1.NotFoundException(`SessionInput with ID "${inputId}" not found in Session "${sessionId}"`);
        }
        const inputsToDelete = session.sessionInputs.slice(targetIndex + 1);
        if (inputsToDelete.length === 0) {
            this.logger.log(`No inputs after ${inputId} to delete in Session ${sessionId}.`);
            return;
        }
        const idsToDelete = inputsToDelete.map((input) => input.id);
        const deleteResult = await this.sessionInputsRepository.delete(idsToDelete);
        this.logger.log(`Deleted ${deleteResult.affected} SessionInputs (from ${idsToDelete[0]} onwards) from Session ${sessionId}.`);
    }
    async remove(sessionId, inputId) {
        const sessionInput = await this.findOne(sessionId, inputId);
        await this.sessionInputsRepository.remove(sessionInput);
        this.logger.log(`Deleted SessionInput ${inputId} from Session ${sessionId}.`);
    }
    async retry(sessionId, inputId, updateSessionInputDto) {
        this.logger.log(`Retrying SessionInput ${inputId} for Session ${sessionId}.`);
        const sessionInput = await this.sessionInputsRepository.findOne({
            where: { id: inputId, session: { id: sessionId } },
            relations: ['session', 'session.systemPrompt'],
        });
        if (!sessionInput) {
            throw new common_1.NotFoundException(`SessionInput with ID "${inputId}" not found in Session "${sessionId}"`);
        }
        if (updateSessionInputDto.user_prompt) {
            sessionInput.user_prompt = updateSessionInputDto.user_prompt;
        }
        let contextTemplate = null;
        if (updateSessionInputDto.context_template_id) {
            contextTemplate = await this.contextTemplatesRepository.findOneBy({
                id: updateSessionInputDto.context_template_id,
            });
            sessionInput.contextTemplate = contextTemplate;
        }
        const generated_context_string = await this.sessionInputContextService.generateContext({
            user_prompt: sessionInput.user_prompt,
            context_template_id: contextTemplate?.id || sessionInput.context_template_id,
            ad_hoc_context_definition: updateSessionInputDto.ad_hoc_context_definition ||
                sessionInput.ad_hoc_context_definition,
            execution_strategy: updateSessionInputDto.execution_strategy ||
                sessionInput.execution_strategy,
        }, contextTemplate, '');
        sessionInput.generated_context_string = generated_context_string;
        sessionInput.raw_llm_response = null;
        sessionInput.llm_response_explanation = null;
        sessionInput.tool_calls = null;
        sessionInput.thoughts = null;
        sessionInput.error_message = null;
        sessionInput.updated_at = new Date();
        const updatedSessionInput = await this.sessionInputsRepository.save(sessionInput);
        await this.aiActionsService.deleteAllByInputId(inputId);
        this.chatService
            .sendMessage(sessionId, generated_context_string)
            .catch((err) => {
            this.logger.error(`LLM retry failed for input ID ${updatedSessionInput.id}: ${err.message}`, err.stack);
        });
        return this.findOne(sessionId, updatedSessionInput.id);
    }
    async regenerateAiResponse(sessionId, inputId) {
        this.logger.log(`Regenerating AI response for SessionInput ${inputId} in Session ${sessionId}.`);
        const sessionInput = await this.sessionInputsRepository.findOne({
            where: { id: inputId, session: { id: sessionId } },
            relations: ['session'],
        });
        if (!sessionInput) {
            throw new common_1.NotFoundException(`SessionInput with ID "${inputId}" not found in Session "${sessionId}"`);
        }
        const allInputs = await this.sessionInputsRepository.find({
            where: { session: { id: sessionId } },
            order: { sequence_number: 'ASC' },
        });
        const currentIndex = allInputs.findIndex((input) => input.id === sessionInput.id);
        if (currentIndex === -1) {
            throw new common_1.NotFoundException(`SessionInput ${inputId} not found in session inputs list.`);
        }
        let contextString = null;
        for (let i = currentIndex - 1; i >= 0; i--) {
            if (allInputs[i].role === 'user' &&
                allInputs[i].generated_context_string) {
                contextString = allInputs[i].generated_context_string;
                break;
            }
        }
        if (!contextString) {
            throw new Error(`No preceding user input with generated_context_string found for SessionInput ${inputId}. Cannot regenerate.`);
        }
        const subsequentInputs = allInputs.slice(currentIndex + 1);
        if (subsequentInputs.length > 0) {
            const idsToDelete = subsequentInputs.map((input) => input.id);
            this.logger.log(`Deleting ${idsToDelete.length} subsequent inputs for regeneration.`);
            await this.sessionInputsRepository.delete(idsToDelete);
        }
        await this.aiActionsService.deleteAllByInputId(inputId);
        sessionInput.raw_llm_response = null;
        sessionInput.thoughts = null;
        sessionInput.tool_calls = null;
        sessionInput.llm_response_explanation = null;
        sessionInput.error_message = null;
        sessionInput.input_token_count = null;
        sessionInput.output_token_count = null;
        sessionInput.cached_token_count = null;
        await this.sessionInputsRepository.save(sessionInput);
        this.chatService
            .sendMessage(sessionId, contextString, inputId)
            .catch((err) => {
            this.logger.error(`LLM regeneration failed for input ID ${inputId}: ${err.message}`, err.stack);
        });
        return this.findOne(sessionId, inputId);
    }
    async updateContent(sessionId, inputId, updateDto) {
        this.logger.log(`Silent update of SessionInput ${inputId} in Session ${sessionId}.`);
        const input = await this.findOne(sessionId, inputId);
        if (updateDto.user_prompt !== undefined) {
            input.user_prompt = updateDto.user_prompt;
        }
        if (updateDto.raw_llm_response !== undefined) {
            input.raw_llm_response = updateDto.raw_llm_response;
        }
        if (updateDto.llm_response_explanation !== undefined) {
            input.llm_response_explanation = updateDto.llm_response_explanation;
        }
        if (updateDto.generated_context_string !== undefined) {
            input.generated_context_string = updateDto.generated_context_string;
        }
        if (updateDto.thoughts !== undefined) {
            input.thoughts = updateDto.thoughts;
        }
        await this.sessionInputsRepository.save(input);
        if (updateDto.tool_results && updateDto.tool_results.length > 0) {
            await this.updateToolResults(inputId, updateDto.tool_results);
        }
        this.logger.log(`Silent update complete for SessionInput ${inputId}.`);
        return this.findOne(sessionId, inputId);
    }
    async updateToolResults(inputId, toolResults) {
        for (const tr of toolResults) {
            const action = await this.aiActionsRepository.findOne({
                where: { input_id: inputId, tool_call_id: tr.tool_call_id },
                relations: ['executionLogs'],
            });
            if (action && action.executionLogs && action.executionLogs.length > 0) {
                action.executionLogs[0].output = tr.output;
                await this.executionLogsRepository.save(action.executionLogs[0]);
                this.logger.log(`Updated execution log for tool_call_id ${tr.tool_call_id}`);
            }
            else {
                this.logger.warn(`No execution log found for tool_call_id ${tr.tool_call_id} in input ${inputId}`);
            }
        }
    }
    async toggleDiscardedBatch(sessionId, dto) {
        const inputs = await this.sessionInputsRepository.find({
            where: { id: (0, typeorm_2.In)(dto.input_ids), session: { id: sessionId } },
        });
        if (inputs.length === 0) {
            throw new common_1.NotFoundException(`No inputs found with provided IDs in session ${sessionId}`);
        }
        const updateResult = await this.sessionInputsRepository.update({ id: (0, typeorm_2.In)(inputs.map((i) => i.id)) }, { is_discarded: dto.is_discarded });
        this.logger.log(`Toggled is_discarded=${dto.is_discarded} for ${updateResult.affected} inputs in session ${sessionId}`);
        return { affected: updateResult.affected || 0 };
    }
};
exports.SessionInputsService = SessionInputsService;
exports.SessionInputsService = SessionInputsService = SessionInputsService_1 = __decorate([
    (0, common_1.Injectable)(),
    __param(0, (0, typeorm_1.InjectRepository)(core_entities_1.Session)),
    __param(1, (0, typeorm_1.InjectRepository)(core_entities_1.SessionInput)),
    __param(2, (0, typeorm_1.InjectRepository)(core_entities_1.ContextTemplate)),
    __param(3, (0, typeorm_1.InjectRepository)(core_entities_1.AIAction)),
    __param(4, (0, typeorm_1.InjectRepository)(core_entities_1.ExecutionLog)),
    __param(5, (0, common_1.Inject)((0, common_1.forwardRef)(() => ai_actions_service_1.AIActionsService))),
    __param(9, (0, common_1.Inject)((0, common_1.forwardRef)(() => chat_service_1.ChatService))),
    __param(10, (0, common_1.Inject)((0, common_1.forwardRef)(() => llm_responses_service_1.LlmResponsesService))),
    __metadata("design:paramtypes", [typeorm_2.Repository,
        typeorm_2.Repository,
        typeorm_2.Repository,
        typeorm_2.Repository,
        typeorm_2.Repository,
        ai_actions_service_1.AIActionsService,
        system_prompts_service_1.SystemPromptsService,
        session_input_context_service_1.SessionInputContextService,
        application_state_service_1.ApplicationStateService,
        chat_service_1.ChatService,
        llm_responses_service_1.LlmResponsesService])
], SessionInputsService);
//# sourceMappingURL=session-inputs.service.js.map