local M = {} local uv = vim.loop local ok_yaml, lyaml = pcall(require, "lyaml") local prompt_blocks = { ["go-development"] = "You are a coding assistant specialized in Go development. You will receive a project’s context and user instructions related to Go code, and you must return the requested modifications or guidance. When returning modifications, follow the specified YAML structure. Keep your suggestions aligned with Go best practices and idiomatic Go.", ["typo3-development"] = "You are a coding assistant specialized in TYPO3 development. You have access to the project’s context and the user’s instructions. Your answers should focus on TYPO3 coding guidelines, extension development best practices, and TSconfig or TypoScript recommendations. When returning modifications, follow the YAML structure given.", ["basic-prompt"] = "You are a coding assistant who receives a project's context and user instructions. The user will provide a prompt, and you will guide them through a workflow:\n1. First, ask them which files from the project are needed to understand and perform the coding task.\n2. If more information or context is needed, ask the user (outside of the YAML) to provide that.\n3. When all necessary information is gathered, provide the final YAML with the project's name and a list of files to be created or modified.\n\nThe final YAML must have a top-level key named 'project_name' that matches the project's configured name, and a top-level key named 'files', which is a list of file changes. Each element in 'files' must be a mapping with:\n- 'path' for the file path relative to the project’s root directory.\n- either 'content' with a multiline string for new content, or 'delete: true' if the file should be deleted.\n\nIf more context is needed at any point before providing the final YAML, request it outside of the YAML.\n\nAdditionally, it is forbidden to change any files which have not been requested or whose source code has not been provided." } local function get_project_root() local current_file = vim.fn.expand("%:p") local root_dir if current_file == "" then root_dir = vim.fn.getcwd() else local file_dir = current_file:match("(.*)/") if not file_dir then root_dir = vim.fn.getcwd() else local cmd = string.format("cd %s && git rev-parse --show-toplevel 2>/dev/null", vim.fn.shellescape(file_dir)) local git_root = vim.fn.systemlist(cmd) if vim.v.shell_error == 0 and git_root and #git_root > 0 then root_dir = git_root[1] else root_dir = file_dir end end end return root_dir end local function get_config_path() local root = get_project_root() return root .. "/.chatgpt_config.yaml" end function M.load() local path = get_config_path() local fd = uv.fs_open(path, "r", 438) local config = { initial_prompt = "", directories = { "." }, default_prompt_blocks = {}, token_limit = 128000, project_name = "", debug = false, initial_files = {} } if fd then local stat = uv.fs_fstat(fd) local data = uv.fs_read(fd, stat.size, 0) uv.fs_close(fd) if data and ok_yaml then local ok, result = pcall(lyaml.load, data) if ok and type(result) == "table" then if type(result.initial_prompt) == "string" then config.initial_prompt = result.initial_prompt end if type(result.directories) == "table" then config.directories = result.directories end if type(result.default_prompt_blocks) == "table" then config.default_prompt_blocks = result.default_prompt_blocks end if type(result.token_limit) == "number" then config.token_limit = result.token_limit end if type(result.project_name) == "string" then config.project_name = result.project_name end if type(result.debug) == "boolean" then config.debug = result.debug end if type(result.initial_files) == "table" then config.initial_files = result.initial_files end end end else config.initial_prompt = "You are a coding assistant who receives a project's context and user instructions. You will guide the user through a workflow:\n1. First, ask the user which files are needed from the project to understand and perform the coding task.\n2. If more information or context is needed, ask for it outside of the YAML.\n3. Once all information is obtained, return the final YAML with the project_name and the files to be created/modified or deleted.\n\nThe final YAML must have:\nproject_name: \nfiles:\n - path: \"relative/path/to/file\"\n content: |\n \n - path: \"relative/path/to/other_file\"\n delete: true\n\nIf more context is needed at any step before providing the final YAML, request it outside of the YAML." end if type(config.default_prompt_blocks) == "table" and #config.default_prompt_blocks > 0 then local merged_prompt = {} for _, block_name in ipairs(config.default_prompt_blocks) do if prompt_blocks[block_name] then table.insert(merged_prompt, prompt_blocks[block_name]) end end if #merged_prompt > 0 then config.initial_prompt = table.concat(merged_prompt, "\n\n") end end if config.debug then vim.api.nvim_out_write("[chatgpt_nvim:config] Loaded config from: " .. path .. "\n") vim.api.nvim_out_write("[chatgpt_nvim:config] Debug logging is enabled.\n") end return config end return M