"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 RequestContextHandler_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RequestContextHandler = void 0;
const common_1 = require("@nestjs/common");
const request_context_args_dto_1 = require("./dto/request-context.args.dto");
const class_transformer_1 = require("class-transformer");
const class_validator_1 = require("class-validator");
const utils_1 = require("../../utils");
const context_generation_service_1 = require("../../context-generation/context-generation.service");
const application_state_service_1 = require("../../application-state/application-state.service");
const gpt_tokenizer_1 = require("gpt-tokenizer");
let RequestContextHandler = RequestContextHandler_1 = class RequestContextHandler {
    constructor(contextGenerationService, applicationStateService) {
        this.contextGenerationService = contextGenerationService;
        this.applicationStateService = applicationStateService;
        this.toolName = 'request_context';
        this.logger = new common_1.Logger(RequestContextHandler_1.name);
    }
    getMetadata() {
        return {
            name: this.toolName,
            description: this.getDefinition(),
            arguments: [
                {
                    name: 'files',
                    type: 'string',
                    description: 'A comma-separated list of relative file paths to read.',
                    required: false,
                },
                {
                    name: 'folders',
                    type: 'string',
                    description: 'A comma-separated list of relative folder paths to read.',
                    required: false,
                },
            ],
        };
    }
    generateExample(toolCall) {
        return (0, utils_1.generateToolCallJson)(toolCall);
    }
    getDefinition() {
        const filesExample = this.generateExample({
            tool_name: this.toolName,
            files: 'src/App.tsx,src/theme/ThemeProvider.tsx,src/store/session.slice.ts,src/lib/api/client.ts',
        });
        const foldersExample = this.generateExample({
            tool_name: this.toolName,
            folders: 'src/components/common,src/hooks',
        });
        const definition = `
-------------
### ${this.toolName}
  Requests content of files or entire folders to build context before making changes.
  This is a crucial exploration tool. It is efficient to request many files at once.

  #### Parameters
  - "files": (string, optional) A comma-separated list of relative file paths to read.
  - "folders": (string, optional) A comma-separated list of relative folder paths to read.

  #### Example: Files
:${filesExample}

  #### Example: Folders
:${foldersExample}
-------------
`;
        return `\n${definition.trim()}\n`;
    }
    async execute(args, context) {
        const validatedArgs = (0, class_transformer_1.plainToClass)(request_context_args_dto_1.RequestContextArgsDto, args);
        const errors = await (0, class_validator_1.validate)(validatedArgs);
        if (errors.length > 0) {
            const errorMessages = errors
                .map((err) => Object.values(err.constraints || {}).join(', '))
                .join('; ');
            return {
                status: 'FAILURE',
                summary: `Invalid arguments for ${this.toolName}.`,
                error_message: errorMessages,
                persisted_args: args,
                execution_log: { output: '', error_message: errorMessages },
            };
        }
        const { files, folders } = validatedArgs;
        const fileList = files ? files.split(',').map((f) => f.trim()) : [];
        const folderList = folders ? folders.split(',').map((f) => f.trim()) : [];
        const outputParts = [];
        let errorMessage = '';
        for (const filePath of fileList) {
            try {
                const content = await this.contextGenerationService.secureReadFile(filePath);
                outputParts.push(content);
            }
            catch (error) {
                this.logger.warn(`Failed to fetch file ${filePath}: ${error.message}`);
                outputParts.push(`Error: File not found at '${filePath}'`);
            }
        }
        for (const folderPath of folderList) {
            try {
                const folderFiles = await this.contextGenerationService.secureGlob(`${folderPath}/**/*`);
                for (const file of folderFiles) {
                    try {
                        const content = await this.contextGenerationService.secureReadFile(file);
                        outputParts.push(content);
                    }
                    catch (error) {
                        this.logger.warn(`Failed to fetch file ${file}: ${error.message}`);
                        outputParts.push(`Error: Could not read file '${file}'`);
                    }
                }
            }
            catch (error) {
                this.logger.warn(`Failed to glob folder ${folderPath}: ${error.message}`);
                outputParts.push(`Error: Could not read folder '${folderPath}'`);
                errorMessage += `Failed to read folder '${folderPath}'. `;
            }
        }
        const output = outputParts.join('\n\n');
        const tokenCount = (0, gpt_tokenizer_1.countTokens)(output);
        const tokenLimit = await this.applicationStateService.getEffectiveFollowupTokenLimit(context.system_prompt_id);
        if (tokenCount > tokenLimit) {
            const limitErrorMessage = `Context too large: ${tokenCount} tokens (limit: ${tokenLimit}). ` +
                `Request fewer files or smaller folders. Consider using specific file paths instead of entire folders.`;
            this.logger.warn(`Context request exceeded token limit: ${tokenCount} > ${tokenLimit}`);
            return {
                status: 'FAILURE',
                summary: `Context request exceeded token limit.`,
                error_message: limitErrorMessage,
                persisted_args: validatedArgs,
                execution_log: { output: '', error_message: limitErrorMessage },
            };
        }
        return {
            status: 'SUCCESS',
            summary: `Fetched ${fileList.length} files and ${folderList.length} folders (${tokenCount} tokens).`,
            persisted_args: validatedArgs,
            execution_log: { output, error_message: errorMessage },
        };
    }
};
exports.RequestContextHandler = RequestContextHandler;
exports.RequestContextHandler = RequestContextHandler = RequestContextHandler_1 = __decorate([
    (0, common_1.Injectable)(),
    __metadata("design:paramtypes", [context_generation_service_1.ContextGenerationService,
        application_state_service_1.ApplicationStateService])
], RequestContextHandler);
//# sourceMappingURL=request-context.handler.js.map